forked from MirrorRepos/RomWBW
37 changed files with 1177 additions and 791 deletions
@ -0,0 +1,411 @@ |
|||
;=============================================================================== |
|||
; SIMER - Display system timer value |
|||
; |
|||
;=============================================================================== |
|||
; |
|||
; Author: Wayne Warthen (wwarthen@gmail.com) |
|||
;_______________________________________________________________________________ |
|||
; |
|||
; Usage: |
|||
; TIMER [/C] [/?] |
|||
; ex: TIMER (display current timer value) |
|||
; TIMER /? (display version and usage) |
|||
; TIMER /C (display timer value continuously) |
|||
; |
|||
; Operation: |
|||
; Reads and displays system timer value. |
|||
;_______________________________________________________________________________ |
|||
; |
|||
; Change Log: |
|||
; 2018-01-14 [WBW] Initial release |
|||
;_______________________________________________________________________________ |
|||
; |
|||
; ToDo: |
|||
;_______________________________________________________________________________ |
|||
; |
|||
;=============================================================================== |
|||
; Definitions |
|||
;=============================================================================== |
|||
; |
|||
stksiz .equ $40 ; Working stack size |
|||
; |
|||
restart .equ $0000 ; CP/M restart vector |
|||
bdos .equ $0005 ; BDOS invocation vector |
|||
; |
|||
ident .equ $FFFE ; loc of RomWBW HBIOS ident ptr |
|||
; |
|||
rmj .equ 2 ; intended CBIOS version - major |
|||
rmn .equ 9 ; intended CBIOS version - minor |
|||
; |
|||
bf_sysget .equ $F8 ; HBIOS: SYSGET function |
|||
bf_sysgettimer .equ $D0 ; TIMER subfunction |
|||
; |
|||
;=============================================================================== |
|||
; Code Section |
|||
;=============================================================================== |
|||
; |
|||
.org $100 |
|||
; |
|||
; setup stack (save old value) |
|||
ld (stksav),sp ; save stack |
|||
ld sp,stack ; set new stack |
|||
; |
|||
; initialization |
|||
call init ; initialize |
|||
jr nz,exit ; abort if init fails |
|||
; |
|||
; process |
|||
call process ; do main processing |
|||
jr nz,exit ; abort on error |
|||
; |
|||
exit: ; clean up and return to command processor |
|||
call crlf ; formatting |
|||
ld sp,(stksav) ; restore stack |
|||
;jp restart ; return to CP/M via restart |
|||
ret ; return to CP/M w/o restart |
|||
; |
|||
; Initialization |
|||
; |
|||
init: |
|||
call crlf ; formatting |
|||
ld de,msgban ; point to version message part 1 |
|||
call prtstr ; print it |
|||
; |
|||
initx |
|||
; initialization complete |
|||
xor a ; signal success |
|||
ret ; return |
|||
; |
|||
; Process |
|||
; |
|||
process: |
|||
; look for start of parms |
|||
ld hl,$81 ; point to start of parm area (past len byte) |
|||
call nonblank ; skip to next non-blank char |
|||
jp z,process0 ; no parms, go to display |
|||
; |
|||
; check for special option, introduced by a "/" |
|||
cp '/' ; start of options? |
|||
jp nz,usage ; yes, handle option |
|||
call option ; do option processing |
|||
ret nz ; done if non-zero reture |
|||
; |
|||
process0: |
|||
call crlf2 ; formatting |
|||
; |
|||
process1: |
|||
ld b,bf_sysget ; HBIOS SYSGET function |
|||
ld c,bf_sysgettimer ; TIMER subfunction |
|||
rst 08 ; call HBIOS, DE:HL := timer value |
|||
|
|||
ld a,(first) |
|||
or a |
|||
ld a,0 |
|||
ld (first),a |
|||
jr nz,process1a |
|||
|
|||
; test for new value |
|||
ld a,(last) ; last LSB value to A |
|||
cp l ; compare to current LSB |
|||
jr z,process2 ; if equal, bypass display |
|||
|
|||
process1a: |
|||
; save and print new value |
|||
ld a,l ; new LSB value to A |
|||
ld (last),a ; save as last value |
|||
call prtcr ; back to start of line |
|||
call nz,prthex32 ; display it |
|||
; |
|||
process2: |
|||
ld a,(cont) ; continuous display? |
|||
or a ; test for true/false |
|||
jr z,process3 ; if false, get out |
|||
; |
|||
ld c,6 ; BDOS: direct console I/O |
|||
ld e,$FF ; input char |
|||
call bdos ; call BDOS, A := char |
|||
or a ; test for zero |
|||
jr z,process1 ; loop until char pressed |
|||
; |
|||
process3: |
|||
xor a ; signal success |
|||
ret |
|||
; |
|||
; Handle special options |
|||
; |
|||
option: |
|||
; |
|||
inc hl ; next char |
|||
ld a,(hl) ; get it |
|||
cp '?' ; is it a '?'? |
|||
jp z,usage ; yes, display usage |
|||
cp 'C' ; is it a 'C', continuous? |
|||
jp z,setcont ; yes, set continuous display |
|||
jp errprm ; anything else is an error |
|||
; |
|||
usage: |
|||
; |
|||
call crlf2 ; blank line |
|||
ld de,msguse ; point to usage message |
|||
call prtstr ; print it |
|||
or $FF ; signal no action performed |
|||
ret ; and return |
|||
; |
|||
setcont: |
|||
; |
|||
or $FF ; set A to true |
|||
ld (cont),a ; and save it |
|||
xor a ; signal success |
|||
ret ; and done |
|||
; |
|||
; Print character in A without destroying any registers |
|||
; |
|||
prtchr: |
|||
push bc ; save registers |
|||
push de |
|||
push hl |
|||
ld e,a ; character to print in E |
|||
ld c,$02 ; BDOS function to output a character |
|||
call bdos ; do it |
|||
pop hl ; restore registers |
|||
pop de |
|||
pop bc |
|||
ret |
|||
; |
|||
prtdot: |
|||
; |
|||
; shortcut to print a dot preserving all regs |
|||
push af ; save af |
|||
ld a,'.' ; load dot char |
|||
call prtchr ; print it |
|||
pop af ; restore af |
|||
ret ; done |
|||
; |
|||
prtcr: |
|||
; |
|||
; shortcut to print a dot preserving all regs |
|||
push af ; save af |
|||
ld a,13 ; load CR value |
|||
call prtchr ; print it |
|||
pop af ; restore af |
|||
ret ; done |
|||
; |
|||
; Print a zero terminated string at (DE) without destroying any registers |
|||
; |
|||
prtstr: |
|||
push de |
|||
; |
|||
prtstr1: |
|||
ld a,(de) ; get next char |
|||
or a |
|||
jr z,prtstr2 |
|||
call prtchr |
|||
inc de |
|||
jr prtstr1 |
|||
; |
|||
prtstr2: |
|||
pop de ; restore registers |
|||
ret |
|||
; |
|||
; Print the value in A in hex without destroying any registers |
|||
; |
|||
prthex: |
|||
push af ; save AF |
|||
push de ; save DE |
|||
call hexascii ; convert value in A to hex chars in DE |
|||
ld a,d ; get the high order hex char |
|||
call prtchr ; print it |
|||
ld a,e ; get the low order hex char |
|||
call prtchr ; print it |
|||
pop de ; restore DE |
|||
pop af ; restore AF |
|||
ret ; done |
|||
; |
|||
; print the hex word value in bc |
|||
; |
|||
prthexword: |
|||
push af |
|||
ld a,b |
|||
call prthex |
|||
ld a,c |
|||
call prthex |
|||
pop af |
|||
ret |
|||
; |
|||
; print the hex dword value in de:hl |
|||
; |
|||
prthex32: |
|||
push bc |
|||
push de |
|||
pop bc |
|||
call prthexword |
|||
push hl |
|||
pop bc |
|||
call prthexword |
|||
pop bc |
|||
ret |
|||
; |
|||
; Convert binary value in A to ascii hex characters in DE |
|||
; |
|||
hexascii: |
|||
ld d,a ; save A in D |
|||
call hexconv ; convert low nibble of A to hex |
|||
ld e,a ; save it in E |
|||
ld a,d ; get original value back |
|||
rlca ; rotate high order nibble to low bits |
|||
rlca |
|||
rlca |
|||
rlca |
|||
call hexconv ; convert nibble |
|||
ld d,a ; save it in D |
|||
ret ; done |
|||
; |
|||
; Convert low nibble of A to ascii hex |
|||
; |
|||
hexconv: |
|||
and $0F ; low nibble only |
|||
add a,$90 |
|||
daa |
|||
adc a,$40 |
|||
daa |
|||
ret |
|||
; |
|||
; Print value of A or HL in decimal with leading zero suppression |
|||
; Use prtdecb for A or prtdecw for HL |
|||
; |
|||
prtdecb: |
|||
push hl |
|||
ld h,0 |
|||
ld l,a |
|||
call prtdecw ; print it |
|||
pop hl |
|||
ret |
|||
; |
|||
prtdecw: |
|||
push af |
|||
push bc |
|||
push de |
|||
push hl |
|||
call prtdec0 |
|||
pop hl |
|||
pop de |
|||
pop bc |
|||
pop af |
|||
ret |
|||
; |
|||
prtdec0: |
|||
ld e,'0' |
|||
ld bc,-10000 |
|||
call prtdec1 |
|||
ld bc,-1000 |
|||
call prtdec1 |
|||
ld bc,-100 |
|||
call prtdec1 |
|||
ld c,-10 |
|||
call prtdec1 |
|||
ld e,0 |
|||
ld c,-1 |
|||
prtdec1: |
|||
ld a,'0' - 1 |
|||
prtdec2: |
|||
inc a |
|||
add hl,bc |
|||
jr c,prtdec2 |
|||
sbc hl,bc |
|||
cp e |
|||
ret z |
|||
ld e,0 |
|||
call prtchr |
|||
ret |
|||
; |
|||
; Start a new line |
|||
; |
|||
crlf2: |
|||
call crlf ; two of them |
|||
crlf: |
|||
push af ; preserve AF |
|||
ld a,13 ; <CR> |
|||
call prtchr ; print it |
|||
ld a,10 ; <LF> |
|||
call prtchr ; print it |
|||
pop af ; restore AF |
|||
ret |
|||
; |
|||
; Get the next non-blank character from (HL). |
|||
; |
|||
nonblank: |
|||
ld a,(hl) ; load next character |
|||
or a ; string ends with a null |
|||
ret z ; if null, return pointing to null |
|||
cp ' ' ; check for blank |
|||
ret nz ; return if not blank |
|||
inc hl ; if blank, increment character pointer |
|||
jr nonblank ; and loop |
|||
; |
|||
; Convert character in A to uppercase |
|||
; |
|||
ucase: |
|||
cp 'a' ; if below 'a' |
|||
ret c ; ... do nothing and return |
|||
cp 'z' + 1 ; if above 'z' |
|||
ret nc ; ... do nothing and return |
|||
res 5,a ; clear bit 5 to make lower case -> upper case |
|||
ret ; and return |
|||
; |
|||
; Add the value in A to HL (HL := HL + A) |
|||
; |
|||
addhl: |
|||
add a,l ; A := A + L |
|||
ld l,a ; Put result back in L |
|||
ret nc ; if no carry, we are done |
|||
inc h ; if carry, increment H |
|||
ret ; and return |
|||
; |
|||
; Jump indirect to address in HL |
|||
; |
|||
jphl: |
|||
jp (hl) |
|||
; |
|||
; Errors |
|||
; |
|||
erruse: ; command usage error (syntax) |
|||
ld de,msguse |
|||
jr err |
|||
; |
|||
errprm: ; command parameter error (syntax) |
|||
ld de,msgprm |
|||
jr err |
|||
err: ; print error string and return error signal |
|||
call crlf ; print newline |
|||
; |
|||
err1: ; without the leading crlf |
|||
call prtstr ; print error string |
|||
; |
|||
err2: ; without the string |
|||
; call crlf ; print newline |
|||
or $FF ; signal error |
|||
ret ; done |
|||
; |
|||
;=============================================================================== |
|||
; Storage Section |
|||
;=============================================================================== |
|||
; |
|||
last .db 0 ; last LSB of timer value |
|||
cont .db 0 ; non-zero indicates continuous display |
|||
first .db $FF ; first pass flag (true at start) |
|||
; |
|||
stksav .dw 0 ; stack pointer saved at start |
|||
.fill stksiz,0 ; stack |
|||
stack .equ $ ; stack top |
|||
; |
|||
; Messages |
|||
; |
|||
msgban .db "TIMER v1.0, 14-Jan-2018",13,10 |
|||
.db "Copyright (C) 2018, Wayne Warthen, GNU GPL v3",0 |
|||
msguse .db "Usage: TIMER [/C] [/?]",13,10 |
|||
.db " ex. TIMER (display current timer value)",13,10 |
|||
.db " TIMER /? (display version and usage)",13,10 |
|||
.db " TIMER /C (display timer value continuously)",0 |
|||
msgprm .db "Parameter error (TIMER /? for usage)",0 |
|||
; |
|||
.end |
|||
File diff suppressed because it is too large
Binary file not shown.
Binary file not shown.
Loading…
Reference in new issue