mirror of https://github.com/wwarthen/RomWBW.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
399 lines
8.5 KiB
399 lines
8.5 KiB
;===============================================================================
|
|
; STARTUP - Application run automatically at OS startup
|
|
;
|
|
;===============================================================================
|
|
;
|
|
; Author: Wayne Warthen (wwarthen@gmail.com)
|
|
;_______________________________________________________________________________
|
|
;
|
|
; Usage:
|
|
; MODE [/?]
|
|
;
|
|
; Operation:
|
|
; Determines if STARTUP.CMD exists on startup drive, user 0. If it is
|
|
; found, it is run via SUBMIT.
|
|
;_______________________________________________________________________________
|
|
;
|
|
; Change Log:
|
|
; 2017-12-01 [WBW] Initial release
|
|
;_______________________________________________________________________________
|
|
;
|
|
; ToDo:
|
|
; 1) Detect OS type (CP/M or ZSYS) and run different batch files as a result.
|
|
;_______________________________________________________________________________
|
|
;
|
|
;===============================================================================
|
|
; 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_cioinit .equ $04 ; HBIOS: CIOINIT function
|
|
bf_cioquery .equ $05 ; HBIOS: CIOQUERY function
|
|
bf_ciodevice .equ $06 ; HBIOS: CIODEVICE function
|
|
bf_sysget .equ $F8 ; HBIOS: SYSGET function
|
|
;
|
|
;===============================================================================
|
|
; 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:
|
|
;
|
|
initx
|
|
; initialization complete
|
|
xor a ; signal success
|
|
ret ; return
|
|
;
|
|
; Process
|
|
;
|
|
process:
|
|
; skip to start of first parm
|
|
ld ix,$81 ; point to start of parm area (past len byte)
|
|
call nonblank ; skip to next non-blank char
|
|
jp z,runcmd ; no parms, do command processing
|
|
;
|
|
process1:
|
|
; process options (if any)
|
|
cp '/' ; option prefix?
|
|
jp nz,erruse ; invalid option introducer
|
|
call option ; process option
|
|
ret nz ; some options mean we are done (e.g., "/?")
|
|
inc ix ; skip option character
|
|
call nonblank ; skip whitespace
|
|
jr nz,process1 ; continue option checking
|
|
jp runcmd ; end of parms, do cmd processing
|
|
;
|
|
;
|
|
;
|
|
runcmd:
|
|
call ldfil ; load executable
|
|
ret nz ; abort on error
|
|
;
|
|
xor a
|
|
ret
|
|
;
|
|
; Load file for execution
|
|
;
|
|
ldfil:
|
|
ld c,15 ; BDOS function: Open File
|
|
ld de,fcb ; pointer to FCB
|
|
call bdos ; do it
|
|
inc a ; check for err, 0xFF --> 0x00
|
|
jp z,errfil ; handle file not found err
|
|
;
|
|
ld c,16 ; BDOS function: Close File
|
|
ld de,fcb ; pointer to FCB
|
|
call bdos ; do it
|
|
inc a ; check for err, 0xFF --> 0x00
|
|
jp z,errfil ; handle file close err
|
|
;
|
|
xor a ; signal success
|
|
ret ; done
|
|
|
|
|
|
;
|
|
; Handle options
|
|
;
|
|
option:
|
|
;
|
|
inc ix ; next char
|
|
ld a,(ix) ; get it
|
|
cp '?' ; is it a '?' as expected?
|
|
jp z,usage ; yes, display usage
|
|
jp errprm ; anything else is an error
|
|
;
|
|
; Display usage
|
|
;
|
|
usage:
|
|
;
|
|
call crlf ; formatting
|
|
ld de,msgban ; point to version message part 1
|
|
call prtstr ; print it
|
|
call crlf2 ; blank line
|
|
ld de,msguse ; point to usage message
|
|
call prtstr ; print it
|
|
or $FF ; signal no action performed
|
|
ret ; and return
|
|
;
|
|
; 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
|
|
;
|
|
; 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,(ix) ; 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 ix ; 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
|
|
;
|
|
errfil: ; STARTUP.CMD file not present
|
|
ld de,msgfil
|
|
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
|
|
;===============================================================================
|
|
;
|
|
fcb .db 0 ; Drive code, 0 = current drive
|
|
.db "START " ; File name, 8 chars
|
|
.db "COM" ; File type, 3 chars
|
|
.fill 36-($-fcb),0 ; zero fill remainder of fcb
|
|
;
|
|
cmdblk .db cmdlen ; length
|
|
cmdtxt .db " B:SUBMIT START"
|
|
.db 0 ; null terminator
|
|
cmdlen .equ $ - cmdtxt
|
|
cmdend .equ $
|
|
;
|
|
stksav .dw 0 ; stack pointer saved at start
|
|
.fill stksiz,0 ; stack
|
|
stack .equ $ ; stack top
|
|
;
|
|
; Messages
|
|
;
|
|
msgban .db "STARTUP v1.0, 01-Dec-2017",13,10
|
|
.db "Copyright (C) 2017, Wayne Warthen, GNU GPL v3",0
|
|
msguse .db "Usage: STARTUP [/?]",0
|
|
msgprm .db "Parameter error (STARTUP /? for usage)",0
|
|
msgfil .db "STARTUP.CMD file missing",0
|
|
;
|
|
.end
|
|
|