home *** CD-ROM | disk | FTP | other *** search
- ;
- ; LOADKEY.MAC -- Version 3 -- January 16, 1988
- ;
- ; Loads key definitions from a disk file. For Commodore 128 CP/M only.
- ;
- ; USAGE:
- ;
- ; LOADKEY {{d:}<fn>}
- ;
- ; The file must have a .KEY filetype. If a filename is not given
- ; in the command line, it will be requested. If a drive is not
- ; given, the drive search chain in the System Control Block will be
- ; followed to locate it. If a drive is supplied, only that drive
- ; will be searched. This program will abort on any error.
- ;
- ; HISTORY:
- ;
- ; Version 1 -- February 25, 1987 -- Original release.
- ;
- ; Version 2 -- May 23, 1987 -- Converted some opcodes to Intel Z80 extensions.
- ; Removed my name from sign-on message. Now sends "failure" code to
- ; BDOS (for conditional SUBMIT's) if the KEY file is not found.
- ;
- ; Version 3 -- January 16, 1988 -- Added trapping for illegal filenames.
- ; Now makes primitive checks for an invalid KEY file. BIOS calls
- ; changed from direct addresses to offsets for compatibility
- ; with revised BIOS's. Sends "failure" code to BDOS on any error,
- ; including illegal filename, invalid KEY file, etc. Now checks
- ; drive search chain in SCB and follows it to locate KEY file, if
- ; no drive specification is given with the filename.
- ;
- ; Eugene L. Pizzetta CompuServe: 72060,505
- ; 481 Revere Street GEnie: E.Pizzetta
- ; Revere, MA 02151 Q-Link: GeneP
- ; Voice: (617) 284-0891
- ;
- ; Developed with SLRMAC. May be assembled with MAC by changing the
- ; filetype to ASM. Z80.LIB required.
- ;
- ;
- WBoot equ 00h ; warm boot
- Bdos equ 05h ; BDOS entry
- CpmBuf equ 80h ; default DMA buffer
- TPA equ 100h ; program load address
- DskBuf equ 1000h ; disk DMA address (Bank 1)
- KeyBuf equ 1000h ; key table address (Bank 0)
- DrvChSt equ 04Ch ; drive chain in SCB
- DrvChEn equ 04Fh ; end of drive chain
- Fail equ 0FF00h ; program failure return code
- ;
- ; File control block
- ;
- Fcb equ 05Ch ; default file control block
- FcbDr equ Fcb ; drive
- FcbEx equ Fcb+0Ch ; extent
- FcbName equ Fcb+1 ; filename
- FcbType equ Fcb+9 ; filetype
- ;
- ; BDOS service functions
- ;
- PrtStr equ 9 ; print string on console
- GetStr equ 10 ; get string from console
- FOpen equ 15 ; open file
- FClose equ 16 ; close file
- FRead equ 20 ; read sequential file
- SetDma equ 26 ; set DMA address
- FMulti equ 44 ; set multi-sector count
- GetSCB equ 49 ; get value from System Control Block
- BdosRet equ 108 ; set BDOS return code
- FParse equ 152 ; parse a filename
- ;
- ; BIOS service functions
- ;
- BiosMv equ 25 ; block move
- BiosXmv equ 29 ; set source and destination banks
- ;
- BEL equ 07h ; bell
- LF equ 0Ah ; linefeed
- CR equ 0Dh ; carriage return
- ;
- ;
- ; Macros . . .
- ;
- MACLIB Z80
- ;
- org TPA
- ;
- jmp MAIN
- ;
- ; Tables and messages . . .
- ;
- MsgSOn: db 'LOADKEY Commodore 128 Version 3$'
- MsgNFN: db CR,LF,LF,'Load key definitions from file: $'
- MsgFNF: db BEL,CR,LF,LF,'File Not Found.$'
- MsgIll: db BEL,CR,LF,LF,'Illegal filename.$'
- MsgAmb: db BEL,CR,LF,LF,'Ambiguous filename not allowed.$'
- MsgBad: db BEL,CR,LF,LF,'Bad KEY file.$'
- MsgDne: db CR,LF,LF,'DONE$'
- KType: db 'KEY' ; key table filetype
- PFcb: dw CpmBuf+2 ; parameter block for FParse
- dw Fcb
- ScbPb db 0,0,0,0 ; parameter block for GetSCB
- ;
- ; Start of program . . .
- ;
- MAIN: lxi d,MsgSOn ; print sign-on
- call PRINT
- ;
- ; First we check for a filename or request one.
- ;
- lda FcbName ; check for command tail
- cpi '#'
- jrnc IsFile ; tail found
- lxi d,MsgNFN ; if not, print message
- call PRINT
- lxi d,CpmBuf ; clear buffer
- mvi b,20
- mvi a,0
- call FILL
- mvi a,14
- sta CpmBuf
- lxi d,CpmBuf
- call GETS ; get filename
- call PARSE ; parse it, and
- lda FcbName ; ..check for error
- cpi '#'
- jrc BadNam ; (there is)
- mvi a,0FFh ; ..check for error
- cmp l
- jrnz IsFile ; (none)
- cmp h
- jrnz IsFile ; (none)
- Badnam: lxi d,MsgIll ; say it's illegal
- call PRINT
- jmp Error ; ..and abort
- ;
- IsFile: lda KType ; move .KEY filetype
- lhld KType+1
- sta FcbType ; ..to FCB
- shld FcbType+1
- mvi a,'?' ; check for ambiguous filename
- lxi h,FcbName
- lxi b,8
- ccir
- jrnz FindIt ; (filename okay)
- lxi d,MsgAmb ; say "be more definite"
- call PRINT
- jmp Error ; ..and abort
- ;
- ; Now we find the file.
- ;
- FindIt: lxi h,Fcb ; put FCB in HL
- call SEARCH ; find the file
- jrnz RdFile ; file exists, so read it
- lxi d,MsgFNF ; say file doesn't exist
- call PRINT
- jmp Error ; ..and abort
- ;
- ; Then we load it from disk.
- ;
- RdFile: mvi c,SetDma ; set DMA for disk read
- lxi d,DskBuf
- call Bdos
- mvi c,FMulti ; set multi-sector read
- lxi d,9 ; ..9 sectors
- call Bdos
- call READ
- ;
- ; After the read, we try to check for a bad file before we move the key
- ; table to the BIOS and possibly crash the system. In the code above
- ; we tried to load 9 sectors, but the key table file should be only 8
- ; sectors long. Register A should contain an error 1 (reading unwritten
- ; data), if the file is shorter than 9 sectors. Register H should contain
- ; the number of sectors read before the error occurred. That number
- ; should be 8. Any other values in A or H would indicate a file that is
- ; too long or too short, so we don't move it.
- ;
- cpi 01h ; check for read error
- jrnz BadFil ; (no error? something's wrong!)
- mov a,h
- cpi 08h
- jrnz BadFil ; (no error? another problem!)
- call CLOSE
- ;
- ; Finally we move the key table to the BIOS in bank 0.
- ;
- lxi d,DskBuf ; source address, bank 1
- lxi h,KeyBuf ; target address, bank 0
- mvi a,0 ; set count to 0
- Again: push psw ; store count
- mvi c,1 ; set source bank
- mvi b,0 ; set destination bank
- call BNKSET ; set for interbank move
- lxi b,128 ; number of bytes to move
- call BNKMOV ; then move it
- pop psw ; get count
- inr a ; increment it
- cpi 8 ; eight times yet?
- jrnz Again ; if not, go again
- lxi d,MsgDne ; say goodbye
- call PRINT
- jmp EXIT
- ;
- ; We come here if the file loaded is shorter or longer than eight sectors.
- ; This is the only check made on KEY file validity.
- ;
- BadFil: lxi d,MsgBad ; report bad file
- call PRINT ; ..and fall through to Error
- ;
- ; We come here if an error has occurred, such as file not found, illegal
- ; filename, etc.
- ;
- Error: lxi d,Fail ; send failure code to BDOS
- mvi c,BdosRet
- call Bdos
- ;
- EXIT: jmp WBoot ; return to CCP
- ;
- ; Subroutines . . .
- ;
- ; BNKSET calls BIOS XMOVE function to set up for interbank move.
- ; Source bank is expected in C; destination bank in B. This routine
- ; must be called before each call to BNKMOVE, but it doesn't change
- ; the pointer registers DE and HL.
- ;
- BNKSET: push h ; save HL on stack
- lhld WBoot+1 ; get BIOS address
- mvi l,BiosXmv*3 ; set XMOVE address
- xthl ; exchange HL with stack
- ret ; jump to BIOS & return to caller
- ;
- ; BNKMOV calls BIOS MOVE function to move a block of memory between
- ; two banks. The number of bytes to move should be in B (128 bytes
- ; maximum), the source starting address in DE, and the destination
- ; starting address in HL. On return DE and HL are incremented past
- ; the block moved, allowing multiple calls to move large blocks.
- ;
- BNKMOV: push h ; save HL on stack
- lhld WBoot+1 ; get BIOS address
- mvi l,BiosMv*3 ; set MOVE address
- xthl ; exchange HL with stack
- ret ; jump to BIOS & return to caller
- ;
- ; FILL fills an area of memory with the byte in A. The starting address
- ; is expected in DE and the number of bytes in B.
- ;
- FILL: stax d ; store the byte
- inx d ; increment the pointer
- djnz FILL
- ret
- ;
- ; SEARCH looks for a file on the given drive or, if no drive is given, it
- ; looks on each drive of drive chain in the System Control Block. If the
- ; file is found, SEARCH opens it. The address of the File Control Block
- ; is expected in HL. If the file is not found, SEARCH returns with the
- ; zero flag set.
- ;
- ; To use this routine in another program, you must initialize a parameter
- ; block (ScbPb) of 4 null bytes, and you must include the equates for Bdos,
- ; FOpen, GetSCB, DrvChSt, and DrvChEn.
- ;
- SEARCH: mvi a,0 ; see if a drive was given
- cmp m
- jrz NoDrv ; (none given)
- xchg ; put FCB address in DE
- mvi c,FOpen ; and try to open it
- call Bdos
- inr a ; does it exist?
- ret ; zero flag set if not
- ;
- NoDrv: mvi a,DrvChSt ; get SCB offset
- SLoop: push h ; save FCB address
- sta ScbPb ; store offset for BDOS
- lxi d,ScbPb ; point to parameter block
- mvi c,GetSCB ; get next drive
- call Bdos
- cpi 0FFh ; end of drive chain?
- pop h ; recover FCB pointer
- rz ; (yes, return with zero set)
- ;
- mov m,a ; put drive in FCB
- push h ; save FCB pointer
- xchg ; move pointer to DE
- mvi c,FOpen ; and try to open file
- call Bdos
- inr a ; did it exist?
- pop h ; recover pointer
- rnz ; (yes, return without zero set)
- lda ScbPb ; get back drive chain offset
- cpi DrvChEn ; end of drive chain?
- rz ; (yes, return with zero set)
- inr a ; increment chain offset
- jr SLoop ; ..and continue searching
- ;
- ; CLOSE closes a disk file.
- ;
- CLOSE: mvi c,FClose
- lxi d,Fcb
- call Bdos
- ret
- ;
- ; GETS gets a string from the console. The string is placed in the buffer
- ; pointed to by DE.
- ;
- GETS: mvi c,GetStr
- call Bdos
- ret
- ;
- ; PARSE parses a filename in CpmBuf and puts it into Fcb.
- ;
- PARSE: lxi d,PFcb
- mvi c,FParse
- call Bdos
- ret
- ;
- ; PRINT prints string on console. String address is in DE.
- ;
- PRINT: mvi c,PrtStr
- call Bdos
- ret
- ;
- ; READ reads a block of data from a disk file.
- ;
- READ: mvi c,FRead
- lxi d,Fcb
- call Bdos
- ret
- ;
- end