Files
RomWBW/Source/CPM3/boot.z80
b1ackmai1er 78f65522b7 Dev (#108)
* added hack to handle tunes

* quiet clean

* added chmod for execution

* suppress warnings

* Multi-boot fixes

* the windows build somehow thinks that these filesystems are cpm3.

* credit and primitive instructions

* Update sd.asm

Cosmetic fix.

* make compile shut up about conditionals

* Add bin2asm for linus and update build to process font files under linix

* fixed quoted double quote bug, added tests

* added tests

* added bin2asm for font file source creation

* Revert linux bin2asm font stuff

* added rule for font source generation

* build fonts

* added directory mapping cache.  if the same directory is being hit
as last run, we don't need to rebuild the map.  will likely break if
you are running more than one at a time, in that the cache will be
ineffective.  also, if the directory contents change, this will also break.

* removed strip.  breaks osx

* added directory tag so . isn't matched all over the place

* added real cache validation

* fixed build

* this file is copied from optdsk.lib or optcmd.lib

* install to ../HBIOS

* prerequisite verbosity

* diff soft failure and casefn speedup

* added lzsa

* added lzsa

* removed strip. breaks on osx

* added clobber

* added code to handle multiple platform rom builds with rom size override

* added align and 0x55 hex syntax

* default to hd64180

* added N8 capability

* added SBC_std.rom to default build

* added support for binary diff

* diff fixes

* clean, identical build.  font source generator emitted .align.  this does not match the windows build

* Upgrade NZCOM to latest

* Misc. Cleanup

* fixed expression parser bug : ~(1|2) returned 0xfe

* added diff build option

* Update Makefile

Makefile enhancement to better handle ncurses library from Bob Dunlop.

* Update sd.asm

Back out hack for uz80as now that Curt fixed it.

* Misc. Cleanup

* UNA Catchup

UNA support was lacking some of the more recent behavior changes.  This corrects most of it.

* Add github action for building RomWBW

* Bump Pre-release Version

* Update build.yml

Added "make clean" which will remove temporary files without removing final binary outputs.

* Update Makefile

Build all ROM variants by default in Linux/Mac build.

* Update Makefile

* Update Makefile

* Update Makefile

* Update Makefile

* Update Makefile

* Update Makefile

* Update Makefile

* Update Makefile

* Update Makefile

* Update for GitHub Build

Case issue in TASM includes showing up in GitHub build.  This should correct that.

* Added an gitignore files to exclude generated files

* Removed Tunes/clean.cmd and Tunes/ReadMe.txt - as make clean removes them

* Build.sh: marked as executable

chmod +x Build.sh

* Fix to HBIOS/build.sh

When adding files to rom disk, if files were missing, it would error out.

It appears the intent is to skip non-existing files.

Updated to log out correctly for missing files - and continue operation.

* Update Microsoft NASCOM BASIC.docx

Nascom manual, text version by Jan S (full name unknown)

* Fix issue with Apps/Tune not making

If dest directory does not exist, fails to make Apps

* Create ReadMe.txt

* Update Makefile

* Update Build.sh

* Make .gitignores for Tools/unix more specific

* cpmtools Update

Updated cpmtools applications (Windows only).  Removed hack in diskdefs that is no longer required.

* HBIOS Proxy Temp Stack Enhancement

Reuse the bounce buffer area as the temporary stack space required briefly in HBX_INVOKE when transitioning banks.  Increases size of temporary stack space to 64 bytes.

* Update ReadMe.txt

* HBIOS - clean up TMPSTK

* Update hbios.asm

Minor cosmetic changes.

* Build Process Updates

Minor udpates to build process to improve consistency between Windows and Mac/Linux builds.

* Update hbios.asm

Add improved interrupt protection to HBIOS PEEK, POKE, and BNKCPY functions.

* hbios - wrap hbx_bnkcpy

* hbios - adjust hbx_peek hbx_poke guards

* Update hbios.asm

Adjusted used of DI/EI for PEEK and POKE to regain a bit of INTSTK space.  Added code so that HB_INVBNK can be used as a flag indicating if HBIOS is active, $FF is inactive, anything else means active.

* Add HBIOS MuTex

* Initial Nascom basic ecb-vdu graphics

set and reset for 80x25b screen with 256 character mod

* Finalize Pre-release 34

Final support for FreeRTOS

* Update nascom.asm

Optimization, cleanup, tabs and white spaces

* IDE & PPIDE Cleanup

* Clean up

Make version include files common.

* Update Makefile

* Update Makefile

* Build Test

* Build Test

* Build Fixes

* Update nascom.asm

Cleanup

* Update nascom.asm

Optimization

* hbios - temp stack tweak

* Update hbios.asm

Comments on HBX_BUF usage.

* Update nascom.asm

Optimization

* Update nascom.asm

Setup ECB-VDU build option, remove debug code

* Update nascom.asm

Set default build. update initialization

* Update nascom.asm

Make CLS clear vdu screen

* Update nascom.asm

Fixup top screen line not showing

* Add SC131 Support

Also cleaned up some ReadMe files.

* HBIOS SCZ180 - remove mutex special files

* HBIOS SCZ180 - adjust mutex comment

* Misc. Cleanup

Includes some minor improvements to contents in some disk images.

* Delete FAT.COM

Changing case of FAT.COM extension to lowercase.

* Create FAT.com

Completing change of case in extension of FAT.com.

* Update Makefile

Remove ROM variants that just have the HBIOS MUTEX enabled.  Users can easily enable this in a custom build.

* Cleanup

Removed hack from Images Makefile.  Fixed use of DEFSERCFG in various places.

* GitHub CI Updates

Adds automation of build and release assets upon release.

* Prerelease 36

General cleanup

* Build Script Cleanups

* Config File Cleanups

* Update RomWBW Architecture

General refresh for v2.9.2

* Update vdu.asm

Removed a hack in VDU driver that has existed for 8 years.  :-)

* Fix CONSOLE Constant

Rename CIODEV_CONSOLE constant to CIO_CONSOLE because it is a unit code, not a device type code.

Retabify TastyBasic.

* Minor Bug Fixes

- Disk assignment edge case
- CP/M 3 accidental fall thru
- Cosmetic updates

* Update util.z80

* Documentation Cleanup

* Documentation Update

* Documentation Update

* Documentation Updates

* Documentation Updates

* Create Common.inc

* Documentation Updates

* Documentation Updates

* doc - a few random fixes

* Documentation Cleanup

* Fix IM 0 Build Error in ACIA

* Documentation Updates

* Documentation Cleanup

* Remove OSLDR

The OSLDR application was badly broken and almost impossible to fix with new expanded OS support.

* Bug Fixes

- Init RAM disk at boot under CP/M 3
- Fix ACR activation in TUNE

* FD Motor Timeout

- Made FDC motor timeout smaller and more consistent across different speed CPUs
- Added "boot" messaging to RTC

* Cleanup

* Cleanup

- Fix SuperZAP to work under NZCOM and ZPM3
- Finalize standard config files

* Minor Changes

- Slight change to ZAP configuration
- Added ZSDOS.ZRL to NZCOM image

* ZDE Upgrade

- Upgraded ZDE 1.6 -> 1.6a

* Config File Tuning

* Pre-release for Testing

* cfg - mutex consistent config language

* Bump to Version 3.0

* Update SD Card How-To

Thanks David!

* update ReadMe.md

Remove some odd `\`.

* Update ReadMe.txt

* Update ReadMe.md

* Update Generated Doc Files

* Improve XModem Startup

- Extended startup timeout for XM.COM so that it doesn't timeout so quickly while host is selecing a file to send.
- Updated SD Card How-To from David Reese.

* XModem Timing Refinements

* TMS Driver Z180 Improvements

- TMS driver udpated to insert Z180 I/O waitstates internally so other code can run at full speed.
- Updated How-To documents from David.
- Fixed TUNE app to properly restore Z180 I/O waitstates after manipulating them.

* CLRDIR and ZDE updates

- CLRDIR has been updated by Max Scane for CP/M 3 compatibility.
- A minor issue in the preconfigured ZDE VT100 terminal escape sequences was corrected.

* Fix Auto CRT Console Switch on CP/M 3

* Handle lack of RTC better

DSRTC driver now correctly returns an error if there is no RTC present.

* Minor RTC Updates

* Finalize v3.0.1

Cleanup release for v3.0

* New ROMLDR and INTRTC driver

- Refactored romldr.asm
- Added new periodic timer based RTC driver

* CP/M 3 Date Hack

- Hack to allow INTRTC to increment time without destroying the date

* Update romldr.asm

Work around minor Linux build inconsistency

* Update Apps for New Version

* Revert "Update Apps for New Version"

This reverts commit ad80432252.

* Revert "Update romldr.asm"

This reverts commit 4a9825cd57.

* Revert "CP/M 3 Date Hack"

This reverts commit 153b494e61.

* Revert "New ROMLDR and INTRTC driver"

This reverts commit d9bed4563e.

* Start v3.1 Development

* Update FDISK80.COM

Updated FDISK80 to allow reserving up to 256 slices.

* Update sd.asm

For Z180 CSIO, ensure that xmit is finished, before asserting CS for next transaction.

* Add RC2014 UART, Improve SD protocol fix

- RC2014 and related platforms will autodetect a UART at 0xA0 and 0xA8
- Ensure that CS fully brackets all SD I/O

* ROMLDR Improvements

.com files can now be started from CP/M and size of .com files has been reduced so they always fit.

* Update commit.yml

Run commit build in all branches

* Update commit.yml

Run commit build for master and dev branches

* Improved clock driver auto-detect/fallback

* SIO driver now CTC aware

The SIO driver can now use a CTC (if available) to provide much more flexible baud rate programming.

* CTC driver fine tuning

* Update xmdm125.asm

Fixed a small issue in core XM125 code that caused a file write error message to not be displayed when it should be.

* CF Card compatibility improvement

Older CF Cards did not reset IDE registers to defaults values when reset.  Implemented a work around.

* Update ACIA detection

ACIA should no longer be detected if there is also a UART module in the system.

* Handle CTC anomaly

Small update to accommodate CTC behavior that occurs when the CTC trigger is more than half the CTC clock.

* Update acia.asm

Updated ACIA detection to use primary ACIA port instead of phantom port.

* Update acia.asm

Fix bug in ACIA detection.

Thanks Alan!

* MacOS Build Improvement

Build script updated to improve compatibility with MacOS.

Credit to Fredrik Axtelius for this.

* HBIOS Makefile - use env vars for target

Allow build ROM targets to be restricted to just one platform thru use of ENV vars:

ROM_PLATFORM - if defined to a known platform, only this platform is build - defaults to std config
ROM_CONFIG - sets the desired platform config - defaults to std

if the above ENVs are not defined, builds all ROMs

* Added some more gitignores

* Whitespace changes (crlf)

* HBIOS: Force the assembly to fail for vdu drivers if function table count is not correct

* Whitespace: trailing whitespaces

* makefile: updated some make scripts to use  when calling subdir makefiles

* linux build: update to Build.sh fix for some platforms

The initialization of the Rom dat file used the pipe (|) operator to build an initial empty file.

But the pipe operator | may sometimes return a non-zero exit code for some linux platforms, if the
the streams are closed before dd has fully processed the stream.

This issue occured on a travis linux ubuntu image.

Solution was to change to redirection.

* Bump version

* Enhance CTC periodic timer

Add ability to use TIMER mode in CTC driver to generate priodic interrupts.

* HBIOS: Added support for sound drivers

New sound driver support with initial support for the SN76489 chip

New build configuration entry:
* SN76489ENABLE

Ports are currently locked in with:
* SN76489_PORT_LEFT       .EQU    $FC     ; PORTS FOR ACCESSING THE SN76489 CHIP (LEFT)
* SN76489_PORT_RIGHT      .EQU    $F8     ; PORTS FOR ACCESSING THE SN76489 CHIP (LEFT)

* Miscellaneous Cleanup

No functional changes.

Co-authored-by: curt mayer <curt@zen-room.org>
Co-authored-by: Wayne Warthen <wwarthen@gmail.com>
Co-authored-by: ed <linux@maidavale.org>
Co-authored-by: Dean Netherton <dnetherton@dius.com.au>
Co-authored-by: ed <ed@maidavale.org>
Co-authored-by: Phillip Stevens <phillip.stevens@gmail.com>
Co-authored-by: Dean Netherton <dean.netherton@gmail.com>
2020-04-24 06:17:22 +08:00

731 lines
18 KiB
Z80 Assembly

title 'Boot loader module for CP/M 3.0'
maclib options.lib
public ?init,?ldccp,?rlccp,?time
public @bootdu,@bootsl
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 @hbbio
extrn addhla, bcd2bin, bin2bcd
extrn cout, phex8, phex16, crlf, crlf2
include c:ver.lib
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, E: := boot slice
ld a,d ; move boot unit to A
ld (@bootdu),a ; save it
ld a,e ; move boot slice to A
ld (@bootsl),a ; save it
call dinit
call clrram
ret
cinit:
; Setup CON: I/O vector based on HBIOS console device
ld b,0FAh ; HBIOS Peek Function
ld a,(@hbbio) ; HBIOS bank id
ld d,a ; ... goes in D
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 (@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
push af ; save device count
cp 2 ; check for 2+ char devices
jr c,cinit$3 ; if not, skip aux assignment
ld a,e ; console unit num to A
or a ; check for zero
ld hl,4000h ; assume aux on second char device
jr z,cinit$2 ; if console on unit 0, assumption good
ld hl,8000h ; otherwise, aux goes to first char device
cinit$2:
ld (@aivec),hl ; assign to aux input
ld (@aovec),hl ; assign to aux output
cinit$3:
pop af ; recover device count
; 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
ret ; done
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
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)
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
dinit5:
ld a,e ; slices per volume value to accum
ld (hdspv),a ; save it
ld hl,0 ; dph index
ld a,(@bootdu) ; boot disk unit
ld d,a ; ... to d
ld a,(@bootsl) ; boot slice
ld e,a ; ... to e
ld b,1 ; one slice please
call dinit8a ; make DPH for A:
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
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 a unit (all slices)
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 030h ; 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: ; test to avoid reallocating boot disk unit/slice
ld a,(@bootdu) ; boot disk unit to accum
cp d ; compare to cur unit
jr nz,dinit8a ; if ne, ok to continue
ld a,(@bootsl) ; boot slice to accum
cp e ; compare to cur slice
jr nz,dinit8a ; if ne, ok to continue
inc e ; is boot du/slice, skip it
djnz dinit8 ; loop till done with unit
ret
dinit8a:
; d=unit, e=slice, l=dph#, b=slice cnt
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
pop hl ; restore dph #
inc hl ; next dph #
inc e ; next slice
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 ; ram disk init must be done from resident memory
;
; Initialize ram disk by filling directory with 'e5' bytes
; Fill first 8k of ram disk track 1 with 'e5'
;
clrram:
di ; no interrupts
ld a,(0FFE0h) ; get current bank
push af ; save it
;ld a,(bnkramd) ; first bank of ram disk
ld a,080h ; first bank of ram disk
;call hb_bnksel ; select bank
call 0FFF3h ; select bank
; Check first 32 directory entries. If any start with an invalid
; value, init the ram disk. Valid entries are e5 (empty entry) or
; 0-15 (user number).
ld hl,0
ld de,32
ld b,32
clrram0:
ld a,(hl)
cp 0E5h
jr z,clrram1 ; e5 is valid
cp 16
jr c,clrram1 ; 0-15 is also valid
jr clrram2 ; invalid entry! jump to init
clrram1:
add hl,de ; loop for 32 entries
djnz clrram0
; jr clrram2 ; *debug*
jr clrram3 ; all entries valid, bypass init
clrram2:
ld hl,0 ; source adr for fill
ld bc,2000h ; length of fill is 8k
ld a,0E5h ; fill value
call fill ; do it
or 0ffh ; flag value for cleared
ld (clrflg),a ; save it
clrram3:
;ld a,(bnkuser) ; usr bank (tpa)
pop af ; recover original bank
;call hb_bnksel ; select bank
call 0FFF3h ; select bank
ei ; resume interrupts
ld a,(clrflg) ; get cleared flag
or a ; set flags
ld hl,clr$msg ; clear ram disk message
call nz,?pmsg ; print msg if true
ret
;
; Fill memory at hl with value a, length in bc. All regs used.
; Length *must* be greater than 1 for proper operation!!!
;
fill:
ld d,h ; set de to hl
ld e,l ; so destination equals source
ld (hl),a ; fill the first byte with desired value
inc de ; increment destination
dec bc ; decrement the count
ldir ; do the rest
ret ; return
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:
; 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
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
ret
no$CCP: ; here if we couldn't find the file
ld hl,ccp$msg
call ?pmsg
call ?conin
jp ?ldccp
?rlccp:
if banked
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
ret nz ; bail out on error
ld a,(datehack)
or a
jr nz,time$get1
; convert yymmss in time buffer -> cpm3 epoch date offset
call date2cpm ; time buf (yr, mon, day) -> SCB (@date)
time$get1:
; 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)
; this is a temporary hack!!!
; since we cannot actually set the date on the RTC, we
; just read the current RTC date and use that so that we
; don't clobber a potentially good date.
; read time from RTC
ld b,020h ; HBIOS func: get time
ld hl,tim$buf ; time buffer
rst 08 ; do it
ret nz ; bail out on error
;
; now we set a hack active flag so that future time$get
; calls do not update the date field in the SCB
;
ld a,0FFh ; true value
ld (datehack),a ; save it
; 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
datehack db 00h
open:
ld c,15
jp bdos
setdma:
ld c,26
jp bdos
setmulti:
ld c,44
jp bdos
read:
ld c,20
jp bdos
clrflg db 0 ; RAM disk cleared flag
clr$msg db 'RAM Disk Initialized',13,10,13,10,0
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 ; boot disk unit
@bootsl db 0 ; boot slice
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