mirror of
https://github.com/wwarthen/RomWBW.git
synced 2026-02-06 22:43:15 -06:00
Jörg Linder has disassembled and thoroughly commented a great deal of the BPBIOS binaries. This was an incredible amount of work. I have added all of these to the RomWBW build scripts and will ultimately integrate them more completely.
753 lines
21 KiB
Z80 Assembly
753 lines
21 KiB
Z80 Assembly
TITLE "HASHINI Drive Utility"
|
|
;************************************************************************
|
|
;* H A S H I N I *
|
|
;* Set Drive Volume Name and Init for File Stamps *
|
|
;* by Harold F. Bower and Cameron W. Cotrill *
|
|
;*----------------------------------------------------------------------*
|
|
;* Disassembly: jxl Mar 2025 *
|
|
;* public release 1.0 Apr 2025 *
|
|
;* see remarks at the end *
|
|
;*----------------------------------------------------------------------*
|
|
;* LINK with Version 4 libraries: Z3LIB, SYSLIB *
|
|
;* *
|
|
;* A>Z80ASM HASHINI/RS *
|
|
;* A>SLRNK HASHINI/N,/A:100,/D:09E5,HASHINI,Z3LIBS/S,SYSLIBS/S,/E *
|
|
;************************************************************************
|
|
|
|
VER EQU 02
|
|
REV EQU ' '
|
|
|
|
DATE MACRO
|
|
DEFB '12 Sep 93'
|
|
ENDM
|
|
|
|
|
|
CTRLC EQU 03H ; Control-C character
|
|
BEL EQU 07H ; Bell character
|
|
BS EQU 08H ; Backspace character
|
|
TAB EQU 09H ; Tab character
|
|
LF EQU 0AH ; Line Feed character
|
|
CR EQU 0DH ; Carriage Return character
|
|
ESC EQU 1BH ; Escape character
|
|
|
|
CPMBIOS EQU 0 ; CP/M BIOS warm boot (JP)
|
|
CPMBDOS EQU 5 ; CP/M BDOS entry point (JP)
|
|
CPMFCB EQU 5CH ; CP/M standard FCB #1 (+1 filename, +9 filetype)
|
|
CPMFCB2 EQU 6CH ; CP/M standard FCB #2
|
|
CPMDMA EQU 80H ; CP/M standard DMA buffer
|
|
|
|
|
|
; From Z3LIB Get..
|
|
EXTRN GETNAME, PRTNAME, GETQUIET, Z3INIT
|
|
|
|
; From SYSLIB Get..
|
|
EXTRN BLINE, EPRINT, CRLF, CAPIN, COUT, CODEND
|
|
|
|
|
|
;::::: PROGRAM START
|
|
|
|
ORG 100H
|
|
CSEG
|
|
|
|
|
|
HASHINI: JP START ; bypass header
|
|
DEFB 'Z3ENV' ; this is a ZCPR3 utility
|
|
DEFB 1 ; show external environment
|
|
DEFB 1
|
|
|
|
ENVADR: DEFW 0 ; addr of Z3 environment
|
|
|
|
DEFB 1
|
|
DEFB 'HASHINI '
|
|
DEFB 0
|
|
|
|
; config area (for ZNCFG.COM)
|
|
CFGAREA: DEFB 0 ; default value for program quiet flag
|
|
DEFB 0FFH
|
|
|
|
START: LD (STACK),SP ; save stack
|
|
LD SP,STACK
|
|
CALL Z3INIT ; init ENVPTR for Z3LIB routines
|
|
CALL GETNAME ; get ptr to program name
|
|
CALL GETQUIET ; check ENV quiet flag
|
|
LD HL,CFGAREA ; ptr to config area
|
|
OR (HL) ; merge flags (ENV + program)
|
|
LD (PRGQFLG),A ; store program quiet flag
|
|
CALL EPRINT
|
|
DEFB CR,LF,'Initialize Volume Label and File Stamps Ver '
|
|
DEFB VER/10+'0','.',VER MOD 10 + '0',REV,' '
|
|
DATE
|
|
DEFB CR,LF
|
|
DEFB 0
|
|
LD C,25 ; get current disk (BDOS fn #25)
|
|
CALL CPMBDOS
|
|
LD (OLDDRV),A ; remember drive #
|
|
CALL EVALCMD ; evaluate command line
|
|
JR INITWSPC
|
|
|
|
|
|
;::::: MAIN LOOP
|
|
|
|
START0: LD SP,STACK ; reset stack pointer
|
|
CALL EPRINT
|
|
DEFB CR,LF,LF,'Initialize another Disk? (Y/[N]) : '
|
|
DEFB 0
|
|
CALL CINPUT ; get user input
|
|
CP 'Y' ; is it 'Y' ?
|
|
JP NZ,EXIT ; ..if not, jump to exit
|
|
CALL SELODRV ; restore previously logged drive
|
|
CALL CRLF
|
|
OR 0FFH ; from now on run interactively
|
|
|
|
; init workspace (ram storage)
|
|
INITWSPC: LD (RUNMODE),A ; store mode
|
|
LD HL,WSPC ; clear workspace data area
|
|
LD B,(STACK-WSPC)-3
|
|
CALL FILLZ
|
|
|
|
|
|
;::::: DISK DRIVE
|
|
|
|
GETDISK: LD A,(RUNMODE) ; get mode
|
|
OR A ; running in cmdline mode ?
|
|
JR Z,GETVOLN ; ..if so, drive is known, jump to continue
|
|
|
|
; interactive mode - ask for disk to initialize
|
|
IMDISK: CALL EPRINT
|
|
DEFB CR,LF,LF,'Initialize which Disk for '
|
|
DEFB 0
|
|
LD A,(STMPTYP) ; stamp format indicator
|
|
OR A ; is it P2Dos ?
|
|
JR NZ,IMDISK1 ; ..if not, jump to continue
|
|
CALL EPRINT ; display chosen format
|
|
DEFB 'P2DOS'
|
|
DEFB 0
|
|
JR IMDISK2 ; skip over
|
|
IMDISK1: CALL EPRINT
|
|
DEFB 'NZTIME'
|
|
DEFB 0
|
|
|
|
IMDISK2: CALL EPRINT
|
|
DEFB ' Date/Time Stamps? : '
|
|
DEFB 0
|
|
CALL CINPUT ; get user input
|
|
CP 'A' ; disk drive letter must be
|
|
JR C,IMDISK3 ; between 'A' and 'P'
|
|
CP 'P'+1
|
|
JR C,IMDISK4
|
|
IMDISK3: CALL EPRINT ; else, notify user and loop
|
|
DEFB BEL,BS,' ',BS
|
|
DEFB 0
|
|
JR IMDISK
|
|
|
|
IMDISK4: LD (CURRDSK),A ; store disk drive letter
|
|
|
|
|
|
;::::: VOLUME NAME
|
|
|
|
GETVOLN: LD A,(VOLNAME)
|
|
OR A
|
|
JR NZ,IMVOLN3
|
|
|
|
; interactive mode - ask for volume name
|
|
IMVOLN: CALL EPRINT
|
|
DEFB CR,LF,'Enter Volume Name [1-11 chars] : '
|
|
DEFB 0
|
|
LD HL,CPMDMA ; set ptr to standard buffer
|
|
LD (HL),11 ; prepare char count (max. 11 chars)
|
|
XOR A ; clear A
|
|
LD (CPMDMA+1),A ; prepare end-of-string
|
|
DEC A ; let capitalize (A= non-zero)
|
|
CALL BLINE ; get user input
|
|
LD A,(HL) ; check char count
|
|
OR A ; is it empty string (nothing entered) ?
|
|
JR Z,IMVOLN ; ..if so, loop
|
|
LD DE,VOLNAME ; point to volname buffer
|
|
IMVOLN1: LD A,(HL) ; get char
|
|
LDI ; ..and copy over
|
|
OR A ; end of string ?
|
|
JR NZ,IMVOLN1 ; ..if not, loop
|
|
|
|
IMVOLN3: LD A,(PRGQFLG) ; get program quiet flag
|
|
OR A ; running in quiet mode ?
|
|
JR Z,DSKPROC ; ..if so, skip over
|
|
CALL EPRINT
|
|
DEFB CR,LF,' Confirm Initialize Drive '
|
|
DEFB 0
|
|
LD A,(CURRDSK)
|
|
CALL COUT
|
|
CALL EPRINT
|
|
DEFB ': (Y/[N]) '
|
|
DEFB 0
|
|
CALL CINPUT ; get user input
|
|
CP 'Y'
|
|
JP NZ,FINISH
|
|
|
|
|
|
;::::: PROCESS DISK
|
|
|
|
DSKPROC: LD A,(CURRDSK) ; get current disk drive letter
|
|
SUB 'A' ; make numeric
|
|
PUSH AF ; save regs
|
|
LD E,A ; drive # in E
|
|
CALL BDSELD ; select disk drive (BDOS call)
|
|
CALL EPRINT ; display warning
|
|
DEFB BEL,CR,LF,'+++ Existing Files will be ERASED! +++'
|
|
DEFB CR,LF,' --- Proceed anyway (Y/[N]) : '
|
|
DEFB 0
|
|
|
|
CALL CINPUT ; get user input
|
|
CP 'Y' ; is it 'Y' ?
|
|
JP NZ,FINISH ; ..if not, jump to finish processing
|
|
POP AF ; restore regs
|
|
LD C,A ; drive # in C
|
|
CALL BIOSELD ; select disk drive (BIOS call)
|
|
LD A,H ; check if DPH addr is valid
|
|
OR L
|
|
JP Z,E$DRVILL ; ..if not, jump display error msg and exit
|
|
|
|
; get parameters of current disk drive
|
|
LD E,(HL) ; get addr of skew table in DE
|
|
INC HL
|
|
LD D,(HL)
|
|
LD (SKEWTBL),DE ; and store value
|
|
LD DE,9
|
|
ADD HL,DE ; move ptr fwd (to DPH+10)
|
|
LD E,(HL) ; addr of DPB in DE
|
|
INC HL
|
|
LD D,(HL)
|
|
PUSH DE ; move addr to IX
|
|
POP IX
|
|
|
|
; ??? ##### CODEND not used
|
|
CALL CODEND ; get first free memory page addr in HL
|
|
|
|
LD D,(IX+8) ; get DirMax in DE
|
|
LD E,(IX+7) ; (max. dir entries -1)
|
|
INC DE ; +1
|
|
LD (DIRMAX),DE ; store value
|
|
SRL D ; /2
|
|
RR E
|
|
SRL D ; /4
|
|
RR E
|
|
LD (STMPMAX),DE ; store value
|
|
; (1 stamp dir entry for 4 file dir entries)
|
|
LD BC,0
|
|
LD HL,CPMDMA ; set to standard buffer
|
|
PUSH DE ; save regs
|
|
PUSH BC
|
|
LD DE,VOLNAME ; ptr to volume name
|
|
LD A,(DE) ; get char
|
|
OR A ; is it zero ? (<NUL> means empty string)
|
|
LD B,3*32 ; prepare counter for 3 stamp entries
|
|
JR Z,MKSTMP ; ..if no volume name, jump to continue
|
|
|
|
; make a volume name entry
|
|
; HL= ptr to standard buffer, DE= ptr to VOLNAME
|
|
; B= char count, C= char
|
|
LD (HL),020H ; set first byte of dir entry (user area)
|
|
; to 0x20 - indicates time stamp
|
|
INC HL ; move ptr fwd
|
|
LD B,11 ; number of chars
|
|
MKVOLN: LD A,(DE) ; get VOLNAME char in A
|
|
LD C,' ' ; prepare for <NUL> byte
|
|
OR A ; end of string ?
|
|
JR Z,MKVOLN1 ; ..if so, skip over
|
|
LD C,A ; else, get char in C
|
|
INC DE ; move VOLNAME ptr forward
|
|
MKVOLN1: LD (HL),C ; copy char to buffer
|
|
INC HL ; move ptr fwd
|
|
DJNZ MKVOLN ; loop till done
|
|
LD B,32-12 ; clear remaining bytes of stamp entry
|
|
CALL FILLZ
|
|
LD B,2*32 ; fill next 2 stamp entries
|
|
|
|
; make a stamp entry and write to dir
|
|
MKSTMP: LD A,0E5H ; CP/M default byte for free dir entries
|
|
CALL FILLA ; fill stamp entries
|
|
LD A,(STMPTYP) ; get chosen stamp format (0x00 = P2Dos, 0xFF = NZTime)
|
|
OR A ; ..and check
|
|
LD A,021H ; prepare for P2Dos
|
|
JR Z,MKSTMP1 ; ..if so, skip over
|
|
LD A,0A1H ; else, prepare for NZTime
|
|
MKSTMP1: LD (HL),A ; store byte
|
|
INC HL ; move ptr fwd
|
|
LD B,32-1 ; ..and clear remaining bytes of stamp entry
|
|
CALL FILLZ
|
|
POP BC ; restore regs
|
|
POP DE
|
|
CALL PVBOSE ; if verbose mode, display msg
|
|
DEFB CR,LF,'...Writing Initialized Directory...'
|
|
DEFB 0
|
|
|
|
LD DE,0 ; initial start #
|
|
LD (STMPCUR),DE ; set # of current stamp entry
|
|
CALL WRSTMP ; ..and write stamp to directory
|
|
LD HL,CPMDMA ; reset ptr to begin of standard buffer
|
|
LD A,0E5H ; clear first part of stamp entry
|
|
LD B,32
|
|
CALL FILLA
|
|
MKSTMP2: CALL WRSTMP ; ..and write next stamp entry
|
|
LD HL,(STMPCUR) ; get current #
|
|
LD DE,(STMPMAX) ; get max. #
|
|
OR A ; clear flags
|
|
SBC HL,DE ; check if all entries were written
|
|
ADD HL,DE
|
|
JR NZ,MKSTMP2 ; ..if not, loop
|
|
LD BC,1 ; set C= 1 to indicate Directory Write (forced)
|
|
CALL BIOWRIT ; ..and perform through BIOS
|
|
JP DSKDONE
|
|
|
|
|
|
; display help and exit
|
|
HLPEXIT: XOR A ; clear A
|
|
LD (RUNMODE),A ; ..and store mode (cmdline)
|
|
JR HELP
|
|
|
|
E$DRVILL: CALL EPRINT ; display error msg and fall through
|
|
DEFB CR,LF,LF,BEL,'Illegal drive name'
|
|
DEFB 0
|
|
|
|
|
|
;::::: HELP
|
|
|
|
HELP: CALL EPRINT
|
|
DEFB CR,LF,'Usage: Set Drive Volume Name & '
|
|
DEFB 'Initialize for P2Dos/NzTime file stamps',CR,LF,LF
|
|
DEFB 'Syntax:',CR,LF,TAB
|
|
DEFB 0
|
|
CALL PPRGNAM
|
|
CALL EPRINT
|
|
DEFB ' [d:][volname] [/][P | Z | Q]',CR,LF
|
|
DEFB 'Examples:',CR,LF,TAB
|
|
DEFB 0
|
|
CALL PPRGNAM
|
|
CALL EPRINT
|
|
DEFB TAB,'- Enter Interactive Mode',CR,LF,TAB
|
|
DEFB 0
|
|
CALL PPRGNAM
|
|
CALL EPRINT
|
|
DEFB ' /P',TAB,'- Init Drive interactively w/P2D stamps',CR,LF,TAB
|
|
DEFB 0
|
|
CALL PPRGNAM
|
|
CALL EPRINT
|
|
DEFB ' d:',TAB,'- Initialize drive "d" w/default Stamp',CR,LF,TAB
|
|
DEFB 0
|
|
CALL PPRGNAM
|
|
CALL EPRINT
|
|
DEFB ' d:name',TAB,'- Init drive "d" adding Vol ID "name"',CR,LF,TAB
|
|
DEFB TAB,TAB,' file with default Stamps',CR,LF,TAB
|
|
DEFB 0
|
|
CALL PPRGNAM
|
|
CALL EPRINT
|
|
DEFB ' d: ZQ',TAB,'- Init drive "d" for NZTime Stamps',CR,LF,TAB
|
|
DEFB TAB,TAB,' suppressing unneeded messages',CR,LF,TAB
|
|
DEFB 0
|
|
CALL PPRGNAM
|
|
CALL EPRINT
|
|
DEFB ' //',TAB,'- Display this message',CR,LF,LF
|
|
DEFB 'Note: ZCNFG may be used to configure a flag to suppress',CR,LF
|
|
DEFB ' drive confirmation prompt and status messages',CR,LF
|
|
DEFB 0
|
|
|
|
JP FINISH
|
|
|
|
|
|
; print program name on CON: device
|
|
; (either the actual name, or fallback to default)
|
|
; only used by HELP
|
|
PPRGNAM: LD A,(ENVADR) ; get high byte of ENV ptr
|
|
OR A ; check if valid (<> zero)
|
|
JP NZ,PRTNAME ; ..if so, display actual name
|
|
; and let return from there
|
|
CALL EPRINT ; else, display default name
|
|
DEFB 'HASHINI'
|
|
DEFB 0
|
|
RET
|
|
|
|
|
|
; write a stamp entry to directory
|
|
; in: IX= ptr DPB
|
|
; STMPCUR= # of current stamp entry
|
|
WRSTMP: PUSH BC ; save regs
|
|
PUSH DE
|
|
PUSH HL
|
|
LD HL,0
|
|
LD BC,(STMPCUR) ; get # of current stamp entry
|
|
LD D,(IX+1) ; get sectors per track (DPB+0)
|
|
LD E,(IX+0)
|
|
LD A,17 ; set counter
|
|
|
|
; determine track # (in BC) and sector # (in HL)
|
|
WRSTMP1: OR A ; clear flags
|
|
SBC HL,DE ; divide by subtraction
|
|
CCF ; inverse C-flag
|
|
JR C,WRSTMP2
|
|
ADD HL,DE ; compensate overflow
|
|
OR A ; clear flags
|
|
WRSTMP2: RL C ; divide BC by 2 (track #)
|
|
RL B
|
|
DEC A ; decrease counter
|
|
JR Z,WRSTMP3 ; ..if zero, exit loop
|
|
RL L ; else, also divide HL by 2 (sector #)
|
|
RL H
|
|
JR WRSTMP1 ; and continue
|
|
|
|
WRSTMP3: PUSH HL ; save (log.) sector #
|
|
LD H,(IX+14) ; get track offset (# sys tracks)
|
|
LD L,(IX+13)
|
|
ADD HL,BC ; add to calculated track #
|
|
LD B,H
|
|
LD C,L
|
|
CALL BIOSTTR ; set track
|
|
POP BC ; restore (log.) sector #
|
|
LD DE,(SKEWTBL) ; get addr of skew table
|
|
CALL BIOSTRN ; translate logical to physical sector
|
|
LD B,H
|
|
LD C,L
|
|
CALL BIOSTSE ; set (phys.) sector
|
|
LD BC,CPMDMA ; set buffer addr
|
|
CALL BIOSTDM
|
|
LD BC,0 ; set C= 0 to indicate Unallocated Write
|
|
CALL BIOWRIT ; ..and perform through BIOS
|
|
OR A ; check for error
|
|
JR Z,WRSTMPX ; ..if not, jump to exit subroutine
|
|
CALL EPRINT ; else, display msg
|
|
DEFB CR,LF,BEL,'Directory write error'
|
|
DEFB 0
|
|
JR FINISH
|
|
|
|
WRSTMPX: LD BC,(STMPCUR) ; get current stamp #
|
|
INC BC ; increase
|
|
LD (STMPCUR),BC ; ..and save again
|
|
POP HL ; restore regs
|
|
POP DE
|
|
POP BC
|
|
RET
|
|
|
|
|
|
; select disk drive that was logged at start of program
|
|
; using BIOS fn first, then BDOS fn
|
|
SELODRV: LD A,(OLDDRV) ; get # of old logged disk drive
|
|
LD C,A ; in C
|
|
LD B,0
|
|
PUSH BC ; save it
|
|
LD DE,1 ; ??? ##### not necessary
|
|
CALL BIOSELD ; select disk drive (through BIOS)
|
|
POP DE ; restore drive # in E
|
|
; ..and fall through
|
|
|
|
|
|
; call BDOS fn #14 SELDSK
|
|
; in: E= drive #
|
|
BDSELD: LD C,14
|
|
JP CPMBDOS ; jump BDOS and let return from there
|
|
|
|
|
|
;::::: FINISH PROCESSING DISK
|
|
|
|
FINISH: CALL SELODRV ; restore previously logged drive
|
|
; ..and fall through
|
|
|
|
DSKDONE: LD A,(CURRDSK)
|
|
SUB 40H ; make numeric
|
|
LD B,A ; use value as counter
|
|
SCF ; set C-flag
|
|
LD HL,0 ; start with all bits cleared
|
|
DSKDN0: ADC HL,HL ; shift Carry bit into position
|
|
DJNZ DSKDN0 ; loop till done
|
|
EX DE,HL ; bit mask in DE (selected disk drive)
|
|
LD C,37 ; BDOS fn #37 RESDSK reset disk system
|
|
CALL CPMBDOS
|
|
LD A,(RUNMODE) ; get mode
|
|
OR A ; running in cmdline mode ?
|
|
JP NZ,START0 ; ..if not, loop for next drive
|
|
; else, fall through and exit
|
|
|
|
|
|
;::::: EXIT PROGRAM
|
|
|
|
EXIT: LD SP,(STACK) ; restore stack
|
|
RET ; ..and return to system
|
|
|
|
|
|
;::::: SUPPORT FUNCTIONS
|
|
|
|
; EVALCMD Evaluate command line
|
|
; based on tokens provided by CP/M parser in FCB #1/#2
|
|
; in: A= # of current drive
|
|
; out: A= 0x00 cmdline mode, 0xFF interactive mode
|
|
; Syntax: [d:][volname] [/][P | Z | Q]
|
|
EVALCMD: XOR A ; clear A
|
|
LD (CURRDSK),A ; ..and variables
|
|
LD (RUNMODE),A
|
|
LD HL,CPMFCB ; set ptr to standard FCB #1
|
|
LD A,(HL) ; get drive #
|
|
OR A ; check if zero
|
|
JR Z,ECMD1 ; ..if so, skip over
|
|
ADD A,40H ; else, make ascii
|
|
CP 'P'+1 ; check if valid
|
|
JR NC,ECMD1 ; ..if not, skip over
|
|
LD (CURRDSK),A ; else, save disk drive letter
|
|
ECMD1
|
|
INC HL ; move ptr fwd
|
|
LD A,(HL) ; get char
|
|
LD DE,VOLNAME ; ptr to buffer for volume name
|
|
LD B,11 ; max. 11 chars
|
|
CP ' ' ; is it <SP> ?
|
|
JR Z,ECMD2 ; ..if so, jump to continue
|
|
CP '/' ; is it option or help request ?
|
|
JR NZ,ECMD1V ; ..if not, jump to copy volume name
|
|
INC HL ; else, move ptr fwd
|
|
CP (HL) ; and check next char
|
|
JP Z,HLPEXIT ; ..if also '/', jump to display help
|
|
JR ECMD3OPT ; else, this char indicates an option
|
|
|
|
; volume name found, copy it
|
|
ECMD1V0: LD A,(HL) ; get char
|
|
ECMD1V: CP ' ' ; is it <SP> ?
|
|
JR Z,ECMD2 ; ..if so, jump to continue
|
|
LD (DE),A ; save char in VOLNAME buffer
|
|
INC DE ; move both ptr's forward
|
|
INC HL
|
|
DJNZ ECMD1V0 ; loop till done
|
|
|
|
; eval 2nd cmdline token (FCB #2)
|
|
ECMD2: XOR A ; clear A
|
|
LD (DE),A ; store in VOLNAME to indicate no name
|
|
LD HL,CPMFCB2+1 ; set ptr to standard FCB #2, after drive letter
|
|
LD A,(HL) ; get char
|
|
CP '/' ; is it option or help request ?
|
|
JR NZ,ECMD3OPT ; ..if not, letter must be an option, so skip over
|
|
INC HL ; else, move ptr fwd
|
|
CP (HL) ; and check next char
|
|
JP Z,HLPEXIT ; ..if also '/', jump to display help
|
|
|
|
; eval option and done
|
|
ECMD3OPT: CALL EVLOPT ; eval option
|
|
RET NZ ; if error, switch to interactive mode and return
|
|
; else, continue final check
|
|
LD HL,CPMFCB ; set ptr to standard FCB #1
|
|
LD A,(HL) ; get byte
|
|
OR A ; is it zero ?
|
|
JR Z,ECMDIM ; ..if so, jump done (interactive mode)
|
|
INC HL ; move ptr fwd
|
|
LD A,(HL) ; get char
|
|
CP ' ' ; is it <SP> ?
|
|
JR NZ,ECMDCM ; ..if not, jump done (cmdline mode)
|
|
LD A,(CPMFCB2+1) ; get char of 2nd token
|
|
CP ' ' ; is it <SP> ?
|
|
JR NZ,ECMDCM ; ..if not, jump done (cmdline mode)
|
|
; else, fall through (interactive mode)
|
|
|
|
ECMDIM: OR 0FFH ; set status (interactive mode)
|
|
RET
|
|
ECMDCM: XOR A ; set status (cmdline mode)
|
|
RET
|
|
|
|
|
|
; evaluate _one_ option on cmdline
|
|
; in: HL= ptr to char (already behind a leading '/')
|
|
; out: A= 0x00 cmdline mode, 0xFF interactive mode
|
|
; Z-flag reset (NZ) in case of error, i.e. interactive mode
|
|
; possible flags are /Q (quiet), /P (P2Dos stamps), /Z (NZTime stamps)
|
|
EVLOPT: LD B,7 ; max. 7 chars
|
|
|
|
EVLOPTQ: LD A,(HL) ; get char
|
|
CP 'Q' ; option /Q - quiet ?
|
|
JR NZ,EVLOPTP ; ..if not, jump to check next option
|
|
LD A,(PRGQFLG) ; get program quiet flag
|
|
XOR 0FFH ; toggle
|
|
LD (PRGQFLG),A ; ..and save back
|
|
JR EVLONXT ; jump to continue
|
|
|
|
EVLOPTP: CP 'P' ; option /P - P2Dos stamps ?
|
|
JR NZ,EVLOPTZ ; ..if not, jump to check next option
|
|
XOR A ; clear A
|
|
LD (STMPTYP),A ; ..and store stamp type
|
|
JR EVLONXT ; jump to continue
|
|
|
|
EVLOPTZ: CP 'Z' ; option /Z - NZTime stamps ?
|
|
JR NZ,EVLONX1 ; ..if not, jump to check for whitespace
|
|
OR 0FFH ; set A= 0xFF
|
|
LD (STMPTYP),A ; store stamp type
|
|
; ..and fall through to read next char
|
|
|
|
EVLONXT: INC HL ; move ptr fwd
|
|
LD A,(HL) ; get char
|
|
; options are separated by whitespace
|
|
EVLONX1: CP ' ' ; is it <SP> ?
|
|
JR Z,EVLOXIT ; ..if so, jump to exit loop
|
|
CP TAB ; is it <TAB> ?
|
|
JR Z,EVLOXIT ; ..if so, jump to exit loop
|
|
JR NZ,EVLOERR ; else, invalid option char found
|
|
DJNZ EVLOPTQ ; loop till done
|
|
|
|
EVLOXIT: XOR A ; set return code 0x00 (clear A and flags)
|
|
RET
|
|
|
|
EVLOERR: LD A,(PRGQFLG) ; get program quiet flag
|
|
OR A ; running in verbose mode ?
|
|
LD A,BEL
|
|
CALL Z,COUT ; ..if so, notify user
|
|
CALL EPRINT
|
|
DEFB CR,LF,'+++ Unrecognized Option "'
|
|
DEFB 0
|
|
LD A,(HL)
|
|
CALL COUT
|
|
CALL EPRINT
|
|
DEFB '" ... Setting Interactive'
|
|
DEFB 0
|
|
OR 0FFH ; set return code 0xFF
|
|
RET
|
|
|
|
|
|
; get console input
|
|
; and check for abort request
|
|
CINPUT: CALL CAPIN ; get char and capitalize
|
|
CP CTRLC ; is it <Ctrl-C> ?
|
|
JP Z,EXIT
|
|
CP ESC ; is it <ESC> ?
|
|
JP Z,EXIT
|
|
CP 'a' ; below 'a' ? (not possible, CAPIN capitalizes)
|
|
RET C
|
|
CP 'z'+1 ; between lowercase 'a' and lowercase 'z' ?
|
|
RET NC
|
|
AND 01011111b ; remove bit 5 to capitalize
|
|
RET
|
|
|
|
|
|
; ##### unreferenced code (not used)
|
|
; copy 32 (0x20) bytes from (HL) to (DE)
|
|
LD B,32
|
|
UNUSED1: LD A,(HL)
|
|
LD (DE),A
|
|
INC HL
|
|
INC DE
|
|
DJNZ UNUSED1
|
|
RET
|
|
; #####
|
|
|
|
|
|
; fill memory with zero, or byte
|
|
; in: A= byte
|
|
; B= # of bytes
|
|
; HL= target addr
|
|
FILLZ: XOR A ; clear A
|
|
FILLA: LD (HL),A ; store byte
|
|
INC HL ; move ptr fwd
|
|
DJNZ FILLA ; loop
|
|
RET
|
|
|
|
|
|
; verbose print - print string to CON: if quiet flag is off
|
|
; in: (Stack) contains start addr of nul-terminated string
|
|
PVBOSE: LD A,(PRGQFLG) ; get program quiet flag
|
|
OR A ; running in verbose mode ?
|
|
JP Z,EPRINT ; ..if so, jump to print and let return from there
|
|
EX (SP),HL ; else, swap HL and top-of-stack
|
|
PVBOSE0: LD A,(HL) ; get char
|
|
INC HL ; move ptr fwd
|
|
OR A ; is byte = zero ?
|
|
JR NZ,PVBOSE0 ; ..if not, loop
|
|
EX (SP),HL ; else, swap back
|
|
RET
|
|
|
|
|
|
; entry points for indirect BIOS calls
|
|
; BC is loaded with absolute offset from WBOOT (fn #1)
|
|
; to respective jump instruction, i.e. 3 bytes per fn
|
|
BIOSELD: PUSH BC
|
|
LD BC,3*8 ; fn #9 SELDSK select disk
|
|
JR BIOSFN
|
|
|
|
BIOSTTR: PUSH BC
|
|
LD BC,3*9 ; fn #10 SETTRK set track
|
|
JR BIOSFN
|
|
|
|
BIOSTSE: PUSH BC
|
|
LD BC,3*10 ; fn #11 SETSEC set sector
|
|
JR BIOSFN
|
|
|
|
BIOSTDM: PUSH BC
|
|
LD BC,3*11 ; fn #12 SETDMA set buffer addr
|
|
JR BIOSFN
|
|
|
|
BIOREAD: PUSH BC
|
|
LD BC,3*12 ; fn #13 READ read one sector (not used)
|
|
JR BIOSFN
|
|
|
|
BIOWRIT: PUSH BC
|
|
LD BC,3*13 ; fn #14 WRITE write one sector
|
|
JR BIOSFN
|
|
|
|
BIOSTRN: PUSH BC
|
|
LD BC,3*15 ; fn #16 SECTRN sector translation
|
|
JR BIOSFN
|
|
|
|
|
|
; call BIOS fn indirectly
|
|
; in: BC= offset to fn in Bios jump table
|
|
BIOSFN: EX (SP),HL ; swap HL and top-of-stack (= prev. BC)
|
|
PUSH HL ; save HL (prev. BC)
|
|
LD HL,(CPMBIOS+1) ; Bios base addr
|
|
ADD HL,BC ; add offset to fn #
|
|
POP BC ; restore BC
|
|
EX (SP),HL ; swap HL and top-of-stack again
|
|
RET ; "call" by returning to Bios fn
|
|
|
|
|
|
UNUSED2:
|
|
DEFB 0,0,0,0,0,0 ; ##### unreferenced chunk of data
|
|
DEFB '!!!TIME&DAT' ; obviously not used
|
|
DEFB 0,0,0,0,0,0,0,0
|
|
DEFB 0,0,0,0,0,0,0,0
|
|
DEFB 0,0,0,0,0,0,0,0
|
|
|
|
|
|
;:::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
; Z3LIB - 0x08a7
|
|
; SYSLIB - 0x091a
|
|
; end addr 0x09e5 (begin DSEG)
|
|
;:::::::::::::::::::::::::::::::::::::::::::::::::::::
|
|
|
|
|
|
DSEG
|
|
|
|
STMPTYP: DEFB 0 ; stamp type flag, 0x00 = P2Dos, 0xFF = NZTime
|
|
PRGQFLG: DEFB 0 ; program quiet flag, 0x00 = verbose
|
|
VOLNAME: DEFS 12 ; buffer for volume name, 11 bytes + <NUL> terminator
|
|
|
|
RUNMODE: DEFB 0 ; indicator, 0x00 = cmdline mode / 0xFF = interactive mode
|
|
OLDDRV: DEFB 0 ; logged drive at program start
|
|
CURRDSK: DEFB 0 ; current disk drive letter
|
|
|
|
WSPC: ; workspace starts here
|
|
DIRMAX: DEFW 0 ; max. # of dir entries (from DPH +1)
|
|
STMPMAX: DEFW 0 ; max. # of stamp entries (= DIRMAX / 4)
|
|
STMPCUR: DEFW 0 ; current # of stamp entry (used as counter)
|
|
SKEWTBL: DEFW 0 ; addr of skew table (from DPH)
|
|
|
|
DEFS 070H ; room for stack
|
|
STACK: DEFW 0 ; stack storage location
|
|
|
|
END
|
|
|
|
|
|
;************************************************************************
|
|
; Remarks jxl:
|
|
; HASHINI.COM, included in available B/P Bios package(s), was dis-
|
|
; assembled and extensively commented. Labels are up to seven chars long
|
|
; to comply with M-REL standards. However, it is recommended to use SLR
|
|
; tools that support labels up to sixteen chars.
|
|
; In its current state, the compiled/linked file matches exactly the
|
|
; original SHOWHD.COM, i.e. no changes to the source were made. Possible
|
|
; optimisations detected during disassembly are marked with "#####" in the
|
|
; comment. It is fair to say that the program seems to be in an early
|
|
; stage; as the version number indicates. Apparently, provisions were made
|
|
; to test exitence, or even generate a DateStamper !!!TIME&.DAT file
|
|
; (which is not the case right now.)
|
|
; The program supports an interactive and a command line mode. Labels
|
|
; start with "IM" to indicate code specifically for interactive mode.
|
|
;************************************************************************
|