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.
738 lines
18 KiB
738 lines
18 KiB
title 'Boot loader module for CP/M 3.0'
|
|
|
|
maclib options.lib
|
|
|
|
public ?init,?ldccp,?rlccp,?time
|
|
public @bootdu
|
|
extrn ?pmsg,?conin
|
|
extrn ?mvinit,?bnkxlt,?xmove,?move
|
|
extrn @civec,@covec,@aivec,@aovec,@lovec
|
|
extrn @cbnk,?bnksl,?bank
|
|
extrn @sysdr,@ccpdr
|
|
extrn dph0
|
|
extrn @dtbl,@ctbl
|
|
extrn @date,@hour,@min,@sec
|
|
extrn @srch1
|
|
extrn addhla, bcd2bin, bin2bcd
|
|
;extrn cout, phex8
|
|
|
|
include ver.inc
|
|
|
|
bdos equ 5
|
|
|
|
if banked
|
|
tpa$bank equ 1
|
|
else
|
|
tpa$bank equ 0
|
|
endif
|
|
|
|
dseg ; init done from banked memory
|
|
|
|
?init:
|
|
call ?mvinit
|
|
|
|
; Install RomWBW CBIOS stamp in page zero
|
|
ld hl,stpimg
|
|
ld de,stploc
|
|
ld bc,stpsiz
|
|
ldir
|
|
|
|
if banked
|
|
|
|
; Clone page zero from bank 0 to additional banks
|
|
ld b,3 ; last bank
|
|
ld c,0 ; src bank
|
|
init$2:
|
|
push bc ; save bank id's
|
|
call ?xmove ; set src/dest banks
|
|
ld bc,0100h ; size is one page
|
|
ld hl,0 ; dest adr is 0
|
|
ld de,0 ; src adr is 0
|
|
call ?move ; do it
|
|
pop bc ; restore bank id's
|
|
djnz init$2 ; loop till done
|
|
|
|
endif
|
|
|
|
call cinit ; char device init
|
|
ld hl,signon$msg ; signon message
|
|
call ?pmsg ; print it
|
|
|
|
; Get boot disk unit and save it
|
|
ld bc,0F8E0h ; HBIOS func: get boot info
|
|
rst 08 ; do it, D := boot unit
|
|
ld a,d ; move to A
|
|
ld (@bootdu),a ; save it
|
|
|
|
call dinit
|
|
ret
|
|
|
|
cinit:
|
|
; Setup CON: I/O vector based on HBIOS console device
|
|
ld b,0FAh ; HBIOS Peek Function
|
|
ld d,0 ; Bank 0 has HCB
|
|
ld hl,112h ; Offset 112h is current console device
|
|
rst 08 ; Call HBIOS, value in E
|
|
push de ; save console unit value
|
|
ld b,e ; Use as loop counter
|
|
inc b ; ... but loop 1 extra time
|
|
ld hl,0 ; Clear vector bitmap
|
|
scf ; Set carry
|
|
cinit$1:
|
|
rr h ; Rotate carry flag
|
|
rr l ; ... into correct vector position
|
|
djnz cinit$1 ; loop as needed
|
|
|
|
;ld hl,8000H ; device 0
|
|
ld (@civec),hl ; assign to console input
|
|
ld (@covec),hl ; assign to console output
|
|
|
|
; Setup AUX: I/O vector if there are 2+ char devices in system
|
|
ld bc,0F800h ; HBIOS GET Character Device Count
|
|
rst 08 ; do it, count in E
|
|
ld a,e ; device count to accum
|
|
pop de ; recover console unit num to E
|
|
cp 2 ; check for 2+ char devices
|
|
jr c,cinit$3 ; if not, skip aux assignment
|
|
or a ; check for zero
|
|
ld hl,4000h ; assume aux on second char device
|
|
jr nz,cinit$2 ; if console on unit 0, assumption good
|
|
ld hl,8000h ; otherwise, aux goes to first char device
|
|
cinit$2:
|
|
;ld hl,4000H ; device 1
|
|
ld (@aivec),hl ; assign to aux input
|
|
ld (@aovec),hl ; assign to aux output
|
|
cinit$3:
|
|
; Truncate char table based on actual num of char devices
|
|
rlca ; A still has char device count
|
|
rlca ; * 8 for ctbl entry size
|
|
rlca ; "
|
|
ld hl,@ctbl ; Start of char table
|
|
call addhla ; Skip used entries
|
|
xor a ; Zero to accum
|
|
ld (hl),0 ; Set table terminator
|
|
|
|
dinit:
|
|
; loop through all disk devices to count hard disk units
|
|
ld b,0F8h ; SYS GET
|
|
ld c,010h ; Disk Drive Unit Count
|
|
rst 08 ; e := disk unit count
|
|
ld b,e ; count to b
|
|
ld a,b ; count to a
|
|
or a ; set flags
|
|
ret z ; !!! handle zero devices (albeit poorly) !!!
|
|
|
|
; ; loop thru devices to count total hard disk volumes
|
|
; push bc ; save the device count
|
|
; ld c,0 ; use c as device list index
|
|
; ld e,0 ; init e for hard disk volume count
|
|
;
|
|
;dinit2:
|
|
; push bc ; save loop control
|
|
; call dinit3 ; check drive
|
|
; pop bc ; restore loop control
|
|
; inc c ; next unit
|
|
; djnz dinit2 ; loop
|
|
; pop bc ; restore unit count in b
|
|
; jr dinit4 ; continue
|
|
|
|
; loop thru devices to count total hard disk volumes
|
|
ld c,0 ; init c as device list index
|
|
ld d,0 ; init d as total device count
|
|
ld e,0 ; init e for hard disk device count
|
|
ld hl,drvlst ; init hl ptr to drive list
|
|
;
|
|
dinit2:
|
|
call dinit3 ; check drive
|
|
inc c ; next unit
|
|
djnz dinit2 ; loop
|
|
ld a,d ; total device count to d
|
|
ld (drvlstc),a ; save the count
|
|
jr dinit4 ; continue
|
|
|
|
;dinit3:
|
|
; push de ; save de (hard disk volume counter)
|
|
; ld b,017h ; hbios func: report device info
|
|
; rst 08 ; call hbios, unit to c
|
|
; ld a,d ; device type to a
|
|
; pop de ; restore de
|
|
; cp 050h ; hard disk device?
|
|
; ret c ; nope, return
|
|
; inc e ; increment hard disk count
|
|
; ret ; and return
|
|
|
|
dinit3:
|
|
push de ; save de (hard disk volume counter)
|
|
push hl ; save drive list ptr
|
|
push bc ; save loop control
|
|
ld b,17h ; hbios func: report device info
|
|
rst 08 ; call hbios, unit to c
|
|
ld a,d ; device type to a
|
|
pop bc ; restore loop control
|
|
pop hl ; restore drive list ptr
|
|
pop de ; restore de
|
|
cp 30h ; hard disk device?
|
|
jr nc,dinit3a ; if so, handle special
|
|
ld (hl),c ; save unit num in list
|
|
inc hl ; bump ptr
|
|
inc d ; inc total device count
|
|
ret
|
|
;
|
|
dinit3a:
|
|
; check for active and return if not
|
|
push de ; save de (hard disk volume counter)
|
|
push hl ; save drive list ptr
|
|
push bc ; save loop control
|
|
|
|
ld b,18h ; hbios func: sense media
|
|
ld e,1 ; perform media discovery
|
|
rst 08
|
|
|
|
pop bc ; restore loop control
|
|
pop hl ; restore drive list ptr
|
|
pop de ; restore de
|
|
|
|
ret nz ; if no media, just return
|
|
|
|
; if active...
|
|
ld (hl),c ; save unit num in list
|
|
inc hl ; bump ptr
|
|
inc d ; inc total device count
|
|
inc e ; increment hard disk count
|
|
ret ; and return
|
|
|
|
|
|
;dinit4: ; set slices per volume (hdspv) based on hard disk volume count
|
|
; ld a,e ; hard disk volume count to a
|
|
; ld e,8 ; assume 8 slices per volume
|
|
; dec a ; dec accum to check for count = 1
|
|
; jr z,dinit5 ; yes, skip ahead to implement 8 hdspv
|
|
; ld e,4 ; now assume 4 slices per volume
|
|
; dec a ; dec accum to check for count = 2
|
|
; jr z,dinit5 ; yes, skip ahead to implement 4 hdspv
|
|
; ld e,2 ; in all other cases, we use 2 hdspv
|
|
|
|
dinit4: ; set slices per volume (hdspv) based on hard disk volume count
|
|
|
|
; ; *** debug ***
|
|
; ;call newline2
|
|
; ld a,(drvlstc)
|
|
; ld b,a
|
|
; call phex8
|
|
; ld a,' '
|
|
; call cout
|
|
; ld hl,drvlst
|
|
;temp1:
|
|
; ld a,(hl)
|
|
; inc hl
|
|
; call phex8
|
|
; djnz temp1
|
|
; ; *** debug ***
|
|
|
|
ld a,e ; hard disk volume count to a
|
|
ld e,8 ; assume 8 slices per volume
|
|
dec a ; dec accum to check for count = 1
|
|
jr z,dinit5 ; yes, skip ahead to implement 8 hdspv
|
|
ld e,4 ; now assume 4 slices per volume
|
|
dec a ; dec accum to check for count = 2
|
|
jr z,dinit5 ; yes, skip ahead to implement 4 hdspv
|
|
ld e,2 ; in all other cases, we use 2 hdspv
|
|
|
|
;dinit5:
|
|
; ld a,e ; slices per volume value to accum
|
|
; ld (hdspv),a ; save it
|
|
;
|
|
; ; setup to enumerate devices to build drvmap
|
|
; ld b,0F8h ; SYS GET
|
|
; ld c,010h ; Disk Drive Unit Count
|
|
; rst 08 ; e := disk unit count
|
|
; ld b,e ; count to b
|
|
; ld c,0 ; use c as device list index
|
|
; ld hl,0 ; dph index
|
|
|
|
dinit5:
|
|
ld a,e ; slices per volume value to accum
|
|
ld (hdspv),a ; save it
|
|
ld a,(drvlstc) ; active drive list count to accum
|
|
ld b,a ; ... and move to b for loop counter
|
|
ld de,drvlst ; de is ptr to active drive list
|
|
ld hl,0 ; dph index
|
|
|
|
;dinit6: ; loop thru all units available
|
|
; push bc ; preserve loop control
|
|
; push hl ; preserve dph pointer
|
|
; ld b,017h ; hbios func: report device info
|
|
; rst 08 ; call hbios, d := device type
|
|
; pop hl ; restore dph pointer
|
|
; pop bc ; get unit index back in c
|
|
; push bc ; resave loop control
|
|
; call dinit7 ; update dph entries
|
|
; pop bc ; restore loop control
|
|
; inc c ; increment list index
|
|
; djnz dinit6 ; loop as needed
|
|
|
|
dinit6: ; loop thru all units available
|
|
push de ; preserve drive list ptr
|
|
ex de,hl ; list ptr to hl
|
|
ld c,(hl) ; get unit num from list
|
|
ex de,hl ; list ptr back to de
|
|
push bc ; preserve loop control
|
|
push hl ; preserve dph pointer
|
|
ld b,17h ; hbios func: report device info
|
|
rst 08 ; call hbios, d := device type
|
|
pop hl ; restore dph pointer
|
|
pop bc ; get unit index back in c
|
|
push bc ; resave loop control
|
|
call dinit7 ; make drive map entry(s)
|
|
pop bc ; restore loop control
|
|
inc c ; increment list index
|
|
pop de ; restore drive list ptr
|
|
inc de ; increment active drive list ptr
|
|
djnz dinit6 ; loop as needed
|
|
|
|
; zero out remaining dph table entries
|
|
ld a,16 ; dph table entries
|
|
sub l ; subtract entries used
|
|
ret z ; return if all entries used
|
|
ld b,a ; save as loop counter
|
|
ld a,l ; current dph to accum
|
|
rlca ; *2 for word entry
|
|
ld hl,@dtbl ; start of dtbl
|
|
call addhla ; hl now points to entry
|
|
dinit6a:
|
|
xor a ; zero accum
|
|
ld (hl),a ; zero lsb
|
|
inc hl ; next byte
|
|
ld (hl),a ; zero msb
|
|
inc hl ; next byte
|
|
djnz dinit6a
|
|
ret ; finished
|
|
|
|
dinit7: ; process unit
|
|
ld e,0 ; initialize slice index
|
|
ld b,1 ; default loop counter
|
|
ld a,d ; device type to accum
|
|
ld d,c ; unit number to d
|
|
cp 050h ; hard disk device?
|
|
jr c,dinit8 ; nope, leave loop count at 1
|
|
ld a,(hdspv) ; get slices per volume to accum
|
|
ld b,a ; move to b for loop counter
|
|
|
|
dinit8:
|
|
; d=unit, e=slice, l=dph#
|
|
ld a,l ; dph # to accum
|
|
cp 16 ; dph table size
|
|
ret z ; bail out if overflow
|
|
push hl ; save dph #
|
|
rlca ; *2 for adr entry
|
|
ld hl,@dtbl ; dph table start
|
|
call addhla ; offset hl to desired entry
|
|
ld a,(hl) ; dereference
|
|
inc hl
|
|
ld h,(hl)
|
|
ld l,a
|
|
dec hl ; backup to slice field
|
|
ld (hl),e ; update slice number
|
|
dec hl ; backup to unit number
|
|
ld (hl),d ; update unit number
|
|
inc e ; next slice
|
|
pop hl ; restore dph #
|
|
inc hl ; next dph #
|
|
djnz dinit8 ; loop till done with unit
|
|
ret
|
|
|
|
; RomWBW CBIOS page zero stamp starts at $40
|
|
; $40-$41: Marker ('W', ~'W')
|
|
; $42-$43: Version bytes: major/minor, update/patch
|
|
; $44-$45: CBIOS Extension Info address
|
|
|
|
stploc equ 40h
|
|
stpimg db 'W',~'W' ; marker
|
|
db rmj << 4 | rmn ; first byte of version info
|
|
db rup << 4 | rtp ; second byte of version info
|
|
dw cbx ; address of cbios ext data
|
|
stpsiz equ $ - stpimg
|
|
|
|
cseg ; boot loading most be done from resident memory
|
|
|
|
; This version of the boot loader loads the CCP from a file
|
|
; called CCP.COM on the system drive.
|
|
|
|
?ldccp:
|
|
|
|
if zpm
|
|
|
|
; Swap A: and system drive (make A: the system drive)
|
|
ld bc,(@dtbl) ; get drive A DPH
|
|
ld hl,@dtbl ; point to boot drive DPH
|
|
ld a,(@sysdr)
|
|
rlca
|
|
call addhla
|
|
ld e,(hl) ; set boot drive to drive A DPH
|
|
ld (hl),c ; ... and save boot drive DPH
|
|
inc hl
|
|
ld d,(hl)
|
|
ld (hl),b
|
|
ld (@dtbl),de ; set drive a DPH to boot drive
|
|
|
|
xor a ; update @sysdr
|
|
ld (@sysdr),a
|
|
|
|
endif
|
|
|
|
; Force CCP to use system boot drive as initial default
|
|
ld a,(@sysdr) ; get system boot drive
|
|
ld (@ccpdr),a ; set CCP current drive
|
|
|
|
; First time, load the CCP.COM file into TPA
|
|
ld a,(@sysdr) ; get system boot drive
|
|
;ld (4),a ; save in page zero???
|
|
inc a ; drive + 1 for FCB
|
|
ld (ccp$fcb),a ; stuff into FCB
|
|
add 'A' - 1 ; drive letter
|
|
ld (ccp$msg$drv),a ; save for load msg
|
|
xor a
|
|
ld (ccp$fcb+15),a
|
|
ld hl,0
|
|
ld (fcb$nr),hl
|
|
ld de,ccp$fcb
|
|
call open
|
|
inc a
|
|
jr z,no$CCP
|
|
ld de,0100H
|
|
call setdma
|
|
ld de,128
|
|
call setmulti
|
|
ld de,ccp$fcb
|
|
call read
|
|
|
|
if banked
|
|
|
|
; ; now,
|
|
; ; copy CCP to bank 0 for reloading
|
|
; lxi h,0100h ! lxi b,0C80h ; clone 3K, just in case
|
|
; lda @cbnk ! push psw ; save current bank
|
|
;ld$1:
|
|
; mvi a,tpa$bank ! call ?bnksl ; select TPA
|
|
; mov a,m ! push psw ; get a byte
|
|
; mvi a,2 ! call ?bnksl ; select extra bank
|
|
; pop psw ! mov m,a ; save the byte
|
|
; inx h ! dcx b ; bump pointer, drop count
|
|
; mov a,b ! ora c ; test for done
|
|
; jnz ld$1
|
|
; pop psw ! call ?bnksl ; restore original bank
|
|
|
|
; ; now,
|
|
; ; copy CCP to bank 0 for reloading
|
|
ld hl,0100h ; clone 3K, just in case
|
|
ld bc,0C80h
|
|
ld a,(@cbnk) ; save current bank
|
|
push af
|
|
ld$1:
|
|
ld a,tpa$bank ; select TPA
|
|
call ?bnksl
|
|
ld a,(hl) ; get a byte
|
|
push af
|
|
ld a,2 ; select extra bank
|
|
call ?bnksl
|
|
pop af ; save the byte
|
|
ld (hl),a
|
|
inc hl ; bump pointer, drop count
|
|
dec bc
|
|
ld a,b ; test for done
|
|
or c
|
|
jr nz,ld$1
|
|
pop af ; restore original bank
|
|
call ?bnksl
|
|
|
|
endif
|
|
|
|
;; Set first search path to system boot drive
|
|
;inc a
|
|
;ld (@srch1),a
|
|
|
|
;ld e,a
|
|
;ld c,14
|
|
;call bdos
|
|
|
|
ret
|
|
|
|
no$CCP: ; here if we couldn't find the file
|
|
ld hl,ccp$msg
|
|
call ?pmsg
|
|
call ?conin
|
|
jp ?ldccp
|
|
|
|
|
|
?rlccp:
|
|
|
|
if banked
|
|
|
|
; lxi h,0100h ! lxi b,0C00h ; clone 3K
|
|
;rl$1:
|
|
; mvi a,2 ! call ?bnksl ; select extra bank
|
|
; mov a,m ! push psw ; get a byte
|
|
; mvi a,tpa$bank ! call ?bnksl ; select TPA
|
|
; pop psw ! mov m,a ; save the byte
|
|
; inx h ! dcx b ; bump pointer, drop count
|
|
; mov a,b ! ora c ; test for done
|
|
; jnz rl$1
|
|
; ret
|
|
|
|
ld hl,0100h ; clone 3K
|
|
ld bc,0C80h
|
|
rl$1:
|
|
ld a,2 ; select extra bank
|
|
call ?bnksl
|
|
ld a,(hl) ; get a byte
|
|
push af
|
|
ld a,tpa$bank ; select TPA
|
|
call ?bnksl
|
|
pop af ; save the byte
|
|
ld (hl),a
|
|
inc hl ; bump pointer, drop count
|
|
dec bc
|
|
ld a,b ; test for done
|
|
or c
|
|
jr nz,rl$1
|
|
ret
|
|
|
|
else
|
|
|
|
jr ?ldccp
|
|
|
|
endif
|
|
|
|
?time:
|
|
; per CP/M 3 docs, *must* preserve HL, DE
|
|
push hl
|
|
push de
|
|
|
|
; force return through time$ret
|
|
ld hl,time$ret
|
|
push hl
|
|
|
|
; branch to get or set routine
|
|
ld a,c ; get switch value
|
|
or a ; test for zero
|
|
jr z,time$get ; 0 means get time
|
|
jr time$set ; else set time
|
|
|
|
time$ret:
|
|
; restore HL, DE
|
|
pop de
|
|
pop hl
|
|
ret
|
|
|
|
time$get:
|
|
; RTC -> cpm date/time in SCB
|
|
|
|
; read time from RTC
|
|
ld b,020h ; HBIOS func: get time
|
|
ld hl,tim$buf ; time buffer
|
|
rst 08 ; do it
|
|
|
|
; convert yymmss in time buffer -> cpm3 epoch date offset
|
|
call date2cpm ; time buf (yr, mon, day) -> SCB (@date)
|
|
|
|
; set time fields in SCB
|
|
ld a,(tim$hr) ; get hour from time buf
|
|
ld (@hour),a ; ... and put in SCB
|
|
ld a,(tim$min) ; get minute from time buf
|
|
ld (@min),a ; ... and put in SCB
|
|
ld a,(tim$sec) ; get second from time buf
|
|
ld (@sec),a ; ... and put in SCB
|
|
|
|
ret
|
|
|
|
time$set:
|
|
; CPM date/time in SCB -> RTC
|
|
|
|
; convert CPM3 epoch date offset in SCB -> yymmss in time buffer
|
|
call cpm2date ; SCB (@date) -> time buf (yr, mon, day)
|
|
|
|
; copy CPM3 time values from SCB -> time buffer
|
|
ld a,(@hour) ; get hour from SCB
|
|
ld (tim$hr),a ; ... and put in tim$hr
|
|
ld a,(@min) ; get minute from SCB
|
|
ld (tim$min),a ; ... and put in tim$min
|
|
ld a,(@sec) ; get second from SCB
|
|
ld (tim$sec),a ; ... and put in tim$sec
|
|
|
|
; send time to RTC
|
|
ld b,021h ; HBIOS func: set time
|
|
ld hl,tim$buf ; ... from time buffer
|
|
rst 08 ; do it
|
|
|
|
ret
|
|
|
|
date2cpm:
|
|
; Convert YYMMSS from time buffer at HL
|
|
; into offset from CPM epoch and store
|
|
; result in SCB.
|
|
|
|
ld hl,0 ; initialize day counter
|
|
; Add in days for elapsed years
|
|
ld a,(tim$yr) ; get current year
|
|
call bcd2bin ; convert to binary
|
|
sub 78 ; epoch year
|
|
jr nc,d2c1 ; if not negative, good to go
|
|
add a,100 ; else, adjust for Y2K wrap
|
|
d2c1:
|
|
ld b,a ; loop counter
|
|
ld c,3 ; leap counter, 78->79->80, so 3
|
|
ld de,365 ; days in non-leap year
|
|
or a ; check for zero
|
|
jr z,d2c10 ; skip if zero
|
|
d2c2:
|
|
add hl,de ; add non-leap days
|
|
dec c ; dec leap counter
|
|
jr nz,d2c3 ; if not leap, bypss leap inc
|
|
inc hl ; add leap day
|
|
ld c,4 ; reset leap year counter
|
|
d2c3:
|
|
djnz d2c2 ; loop for all years
|
|
d2c10:
|
|
; Add in days for elapsed months
|
|
ex de,hl ; save HL in DE
|
|
ld hl,daystbl ; point to table of cum days by month
|
|
ld a,(tim$mon) ; get current month
|
|
call bcd2bin ; convert to binary
|
|
dec a ; index from zero
|
|
rlca ; table entries are 2 bytes
|
|
call addhla ; offset to desired month entry
|
|
ld a,(hl) ; get the entry into HL
|
|
inc hl ; ...
|
|
ld h,(hl) ; ...
|
|
ld l,a ; ...
|
|
ex de,hl ; HL = day count, DE = months count
|
|
add hl,de ; add months count into day count
|
|
; Add leap day for current year if appropriate
|
|
dec c ; C still has leap counter
|
|
jr nz,d2c20 ; skip if not leap year
|
|
ld a,(tim$mon) ; get cur mon
|
|
cp 3 ; March?
|
|
jr c,d2c20 ; skip if mon less than March
|
|
inc hl ; add leap day for cur year
|
|
d2c20:
|
|
; Add in days elapsed within month
|
|
; Note that we don't adjust the date to be a zero
|
|
; offset which seems wrong. From what I can tell
|
|
; the CP/M epoch is really 1/0/1978 rather than the
|
|
; 1/1/1978 that the documentation claims. Below seems
|
|
; to work correctly.
|
|
ld a,(tim$day) ; get day
|
|
call bcd2bin ; make binary
|
|
call addhla ; add in days
|
|
ld (@date),hl ; store in SCB
|
|
ret
|
|
|
|
cpm2date:
|
|
; Convert CPM epoch date offset in SCB
|
|
; into YYMMSS values and store result in
|
|
; time buffer at HL.
|
|
ld a,019h
|
|
ld (tim$yr),a
|
|
ld a,001h
|
|
ld (tim$mon),a
|
|
ld a,001h
|
|
ld (tim$day),a
|
|
|
|
ret
|
|
|
|
daystbl:
|
|
; cumulative days elapsed by month (non-leap year)
|
|
dw 0 ; January
|
|
dw 31 ; February (non-leap)
|
|
dw 59 ; March
|
|
dw 90 ; April
|
|
dw 120 ; May
|
|
dw 151 ; June
|
|
dw 181 ; July
|
|
dw 212 ; August
|
|
dw 243 ; September
|
|
dw 273 ; October
|
|
dw 304 ; November
|
|
dw 334 ; December
|
|
|
|
; RTC time buffer (all values packed bcd)
|
|
tim$buf:
|
|
tim$yr db 80h
|
|
tim$mon db 05h
|
|
tim$day db 10h
|
|
tim$hr db 01h
|
|
tim$min db 02h
|
|
tim$sec db 03h
|
|
|
|
open:
|
|
ld c,15
|
|
jp bdos
|
|
|
|
setdma:
|
|
ld c,26
|
|
jp bdos
|
|
|
|
setmulti:
|
|
ld c,44
|
|
jp bdos
|
|
|
|
read:
|
|
ld c,20
|
|
jp bdos
|
|
|
|
if zpm
|
|
|
|
signon$msg db 13,10,'ZPM3'
|
|
if banked
|
|
db ' [BANKED]'
|
|
endif
|
|
db ' on HBIOS v'
|
|
biosver
|
|
db 13,10,13,10,0
|
|
|
|
ccp$msg db 13,10,'BIOS Err on '
|
|
ccp$msg$drv db '?'
|
|
db ': No ZCCP.COM file',0
|
|
|
|
|
|
ccp$fcb db 0,'ZCCP ','COM',0,0,0,0
|
|
ds 16
|
|
fcb$nr db 0,0,0
|
|
|
|
else
|
|
|
|
signon$msg db 13,10,'CP/M v3.0'
|
|
if banked
|
|
db ' [BANKED]'
|
|
endif
|
|
db ' on HBIOS v'
|
|
biosver
|
|
db 13,10,13,10,0
|
|
|
|
ccp$msg db 13,10,'BIOS Err on '
|
|
ccp$msg$drv db '?'
|
|
db ': No CCP.COM file',0
|
|
|
|
|
|
ccp$fcb db 0,'CCP ','COM',0,0,0,0
|
|
ds 16
|
|
fcb$nr db 0,0,0
|
|
|
|
endif
|
|
|
|
@bootdu db 0
|
|
hdspv db 2 ; slices per volume for hard disks (must be >= 1)
|
|
drvlst ds 32 ; active drive list used durint drv_init
|
|
drvlstc db 0 ; entry count for active drive list
|
|
|
|
; The following section contains key information and addresses for the
|
|
; RomWBW CBIOS. A pointer to the start of this section is stored with
|
|
; with the CBX data in page zero at $44 (see above).
|
|
|
|
cbx:
|
|
devmapadr dw 0 ; device map address
|
|
drvtbladr dw @dtbl ; drive map address (filled in later)
|
|
dphtbladr dw dph0 ; dpb map address
|
|
cbxsiz equ $ - cbx
|
|
|
|
end
|
|
|