;; This example shows how to access the firmware from within CP/M 2.2 and CP/M+.
;; 
;; CP/M 2.2 and CP/M+ use a different address to execute firmware functions
;; but the parameters and method of calling are the same.
;;
;; Detect the version of CP/M which is in use and setup the correct firmware
;; jump. If a incorrect version of CP/M has been detected then just quit.
;;
;;---------------------------------------------------------

org &100							;; origin for C/PM .COM programs
nolist
write"test3.com"

.enter_firmware equ &be9b
.scr_set_mode equ &bc0e
.txt_output equ &bb5a
.bdos equ 5

;;---------------------------------------------------------
;; get version of CP/M

ld c,&0c							;; BDOS function get CP/M version
call bdos
ld a,l								;; CP/M Version
cp &22								;; CP/M 2.2?
jr nz,cpmtst1

;;-----------------------------
;; C/PM 2.2 detected
;;
;; initialise firm_jump with 
;; the appropiate value

ld hl,enter_firmware
ld (firm_jump+1),hl
jp start

.cpmtst1
cp &31								;; C/PM + (C/PM 3.1)?
jr nz,cpmtst2

;;------------------------------
;; C/PM+ detected
;;
;; initialise firm_jump with
;; the appropiate value

ld hl,(&0001)
ld de,&0057
add hl,de
ld (firm_jump+1),hl

jp start

.cpmtst2
ret

;;---------------------------------------------------------
;; the main program

.start
;;----------------------------------
;; change the display mode to mode 1
ld a,1
call firm_jump
defw scr_set_mode

;;----------------------------------
;; display a message on the screen
ld hl,test_message
call display_message

;;----------------------------------
;; quit back to command-line
ret

;;---------------------------------------------------------
;; HL = pointer to null terminated message
.display_message
ld a,(hl)				;; get ASCII character
inc hl					;; increment pointer for next character
or a					;; end of message marker (0)?
ret z					;; quit if end of message marker found.

call display_char		;; send character to console output
jp display_message		;; loop for next char

;;---------------------------------------------------------
.display_char
call firm_jump
defw txt_output			;; firmware function: TXT OUTPUT
ret

;;---------------------------------------------------------
;; execute a firmware function
.firm_jump
jp 0

;;---------------------------------------------------------
.test_message
defb "Hello World!",0