mirror of
https://github.com/wwarthen/RomWBW.git
synced 2026-02-06 22:43:15 -06:00
BPBIOS Sources From Jörg Linder
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.
This commit is contained in:
@@ -15,8 +15,7 @@ as needed. The RomWBW ASSIGN command is not supported. BPBIOS
|
||||
will boot from the first hard disk unit number you assign and
|
||||
always from the first slice.
|
||||
|
||||
BPBIOS does not yet understand the 1024 directory entry
|
||||
hard disk format. You must use the 512 directory entry
|
||||
format images.
|
||||
BPBIOS is hard-coded to use the 1024 directory entry hard disk
|
||||
format (hd1k). The hd512 format is not supported at all.
|
||||
|
||||
--WBW 1:25 PM 10/7/2021
|
||||
--WBW 5:04 PM 6/16/2025
|
||||
@@ -2,6 +2,7 @@
|
||||
setlocal
|
||||
|
||||
pushd ZCPR33 && call Build || exit /b & popd
|
||||
pushd UTIL && call Build || exit /b & popd
|
||||
|
||||
set TOOLS=..\..\Tools
|
||||
set PATH=%PATH%;%TOOLS%\zxcc;%TOOLS%\cpmtools;
|
||||
|
||||
@@ -11,3 +11,4 @@ if exist *.bak del *.bak
|
||||
if exist def-ww.lib del def-ww.lib
|
||||
|
||||
pushd ZCPR33 && call Clean.cmd & popd
|
||||
pushd UTIL && call Clean.cmd & popd
|
||||
|
||||
@@ -13,7 +13,7 @@ OTHERS = zcpr33.rel bp*.prn bp*.rel \
|
||||
|
||||
TOOLS = ../../Tools
|
||||
|
||||
SUBDIRS = ZCPR33
|
||||
SUBDIRS = ZCPR33 UTIL
|
||||
include $(TOOLS)/Makefile.inc
|
||||
|
||||
zcpr33.rel:
|
||||
|
||||
55
Source/BPBIOS/UTIL/Build.cmd
Normal file
55
Source/BPBIOS/UTIL/Build.cmd
Normal file
@@ -0,0 +1,55 @@
|
||||
@echo off
|
||||
setlocal
|
||||
|
||||
set TOOLS=..\..\..\Tools
|
||||
set PATH=%PATH%;%TOOLS%\zxcc;%TOOLS%\cpmtools;
|
||||
set CPMDIR80=%TOOLS%/cpm/
|
||||
|
||||
zxcc Z80ASM -BPBUILD/RFS || exit /b
|
||||
zxcc SLRNK -BPBUILD/N,/A:100,/D:23E0,BPBUILD,B:SLINK0,B:VLIBS/S,B:Z3LIBS/S,B:SYSLIBS/S,/E || exit /b
|
||||
|
||||
zxcc Z80ASM -BPCNFG/RFS || exit /b
|
||||
zxcc SLRNK -BPCNFG/N,/A:100,/D:3A55,BPCNFG,B:VLIBS/S,B:Z3LIBS/S,B:SYSLIBS/S,/E || exit /b
|
||||
|
||||
zxcc Z80ASM -BPSWAP/RFS || exit /b
|
||||
zxcc SLRNK -BPSWAP/N,/A:100,/D:0854,BPSWAP,B:VLIBS/S,B:Z3LIBS/S,B:SYSLIBS/S,/E || exit /b
|
||||
|
||||
zxcc Z80ASM -BPSYSGEN/RFS || exit /b
|
||||
zxcc SLRNK -BPSYSGEN/N,/A:100,/D:08CD,BPSYSGEN,B:Z3LIBS/S,B:SYSLIBS/S,/E || exit /b
|
||||
|
||||
zxcc Z80ASM -CONFZ4/RFS || exit /b
|
||||
zxcc SLRNK -CONFZ4/N,/A:100,/D:080A,CONFZ4,B:Z3LIBS/S,B:SYSLIBS/S,/E || exit /b
|
||||
|
||||
zxcc Z80ASM -HASHINI/RFS || exit /b
|
||||
zxcc SLRNK -HASHINI/N,/A:100,/D:09E5,HASHINI,B:Z3LIBS/S,B:SYSLIBS/S,/E || exit /b
|
||||
|
||||
zxcc Z80ASM -LDSYS/RFS || exit /b
|
||||
zxcc SLRNK -LDSYS/N,/A:100,/D:0CF8,LDSYS,B:VLIBS/S,B:Z3LIBS/S,B:SYSLIBS/S,/E || exit /b
|
||||
|
||||
zxcc Z80ASM -SHOWHD/RFS || exit /b
|
||||
zxcc SLRNK -SHOWHD/N,/A:100,/D:064D,SHOWHD,B:SYSLIBS/S,/E || exit /b
|
||||
|
||||
zxcc Z80ASM -SIZERAM/RFS || exit /b
|
||||
zxcc SLRNK -SIZERAM/N,/A:100,/D:0750,SIZERAM,B:VLIBS/S,B:Z3LIBS/S,B:SYSLIBS/S,/E || exit /b
|
||||
|
||||
zxcc Z80ASM -ZSCFG2/RFS || exit /b
|
||||
zxcc SLRNK -ZSCFG2/N,/A:100,/D:145E,ZSCFG2,B:VLIBS/S,B:Z3LIBS/S,B:SYSLIBS/S,/E || exit /b
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
:: zxcc Z80ASM
|
||||
:: zxcc ZMAC -zcpr33.z80 -/P || exit /b
|
||||
6
Source/BPBIOS/UTIL/Clean.cmd
Normal file
6
Source/BPBIOS/UTIL/Clean.cmd
Normal file
@@ -0,0 +1,6 @@
|
||||
@echo off
|
||||
setlocal
|
||||
|
||||
if exist *.com del *.com
|
||||
if exist *.lst del *.lst
|
||||
if exist *.rel del *.rel
|
||||
40
Source/BPBIOS/UTIL/Makefile
Normal file
40
Source/BPBIOS/UTIL/Makefile
Normal file
@@ -0,0 +1,40 @@
|
||||
OBJECTS = bpbuild.com bpcnfg.com bpswap.com bpsysgen.com confz4.com hashini.com \
|
||||
ldsys.com showhd.com sizeram.com zscfg2.com
|
||||
TOOLS = ../../../Tools
|
||||
# DEST = ..
|
||||
OTHERS = *.rel
|
||||
|
||||
include $(TOOLS)/Makefile.inc
|
||||
|
||||
%.rel: %.z80
|
||||
@$(ZXCC) $(CPM)/Z80ASM -$(basename $<)/RFS
|
||||
|
||||
bpbuild.com : bpbuild.rel
|
||||
$(ZXCC) slrnk -bpbuild/n,/a:100,/d:23e0,bpbuild,b:slink0,b:vlibs/s,b:z3libs/s,b:syslibs/s,/e
|
||||
|
||||
bpcnfg.com : bpcnfg.rel
|
||||
$(ZXCC) slrnk -bpcnfg/n,/a:100,/d:3a55,bpcnfg,b:vlibs/s,b:z3libs/s,b:syslibs/s,/e
|
||||
|
||||
bpswap.com : bpswap.rel
|
||||
$(ZXCC) slrnk -bpswap/n,/a:100,/d:0854,bpswap,b:vlibs/s,b:z3libs/s,b:syslibs/s,/e
|
||||
|
||||
bpsysgen.com : bpsysgen.rel
|
||||
$(ZXCC) slrnk -bpsysgen/n,/a:100,/d:08cd,bpsysgen,b:z3libs/s,b:syslibs/s,/e
|
||||
|
||||
confz4.com : confz4.rel
|
||||
$(ZXCC) slrnk -confz4/n,/a:100,/d:080a,confz4,b:z3libs/s,b:syslibs/s,/e
|
||||
|
||||
hashini.com : hashini.rel
|
||||
$(ZXCC) slrnk -hashini/n,/a:100,/d:09e5,hashini,b:z3libs/s,b:syslibs/s,/e
|
||||
|
||||
ldsys.com : ldsys.rel
|
||||
$(ZXCC) slrnk -ldsys/n,/a:100,/d:0cf8,ldsys,b:vlibs/s,b:z3libs/s,b:syslibs/s,/e
|
||||
|
||||
showhd.com : showhd.rel
|
||||
$(ZXCC) slrnk -showhd/n,/a:100,/d:064d,showhd,b:syslibs/s,/e
|
||||
|
||||
sizeram.com : sizeram.rel
|
||||
$(ZXCC) slrnk -sizeram/n,/a:100,/d:0750,sizeram,b:vlibs/s,b:z3libs/s,b:syslibs/s,/e
|
||||
|
||||
zscfg2.com : zscfg2.rel
|
||||
$(ZXCC) slrnk -zscfg2/n,/a:100,/d:145e,zscfg2,b:vlibs/s,b:z3libs/s,b:syslibs/s,/e
|
||||
2357
Source/BPBIOS/UTIL/bpbuild.z80
Normal file
2357
Source/BPBIOS/UTIL/bpbuild.z80
Normal file
File diff suppressed because it is too large
Load Diff
4539
Source/BPBIOS/UTIL/bpcnfg.z80
Normal file
4539
Source/BPBIOS/UTIL/bpcnfg.z80
Normal file
File diff suppressed because it is too large
Load Diff
483
Source/BPBIOS/UTIL/bpswap.z80
Normal file
483
Source/BPBIOS/UTIL/bpswap.z80
Normal file
@@ -0,0 +1,483 @@
|
||||
TITLE "Swap drives under B/P Bios"
|
||||
;************************************************************************
|
||||
;* B P S W A P *
|
||||
;* Swap two drive letters in a running B/P Bios system *
|
||||
;* by Harold F. Bower and Cameron W. Cotrill *
|
||||
;*----------------------------------------------------------------------*
|
||||
;* Disassembly: jxl Dec 2024 *
|
||||
;* public release 1.0 Apr 2025 *
|
||||
;* see remarks at the end *
|
||||
;*----------------------------------------------------------------------*
|
||||
;* LINK with Version 4 libraries: VLIB, Z3LIB, SYSLIB *
|
||||
;* *
|
||||
;* A>Z80ASM BPSWAP/RS *
|
||||
;* A>SLRNK BPSWAP/N,/A:100,/D:0854,BPSWAP,VLIBS/S,Z3LIBS/S,SYSLIBS/S,/E *
|
||||
;************************************************************************
|
||||
|
||||
VER EQU 10
|
||||
REV EQU ' '
|
||||
|
||||
DATE MACRO
|
||||
DEFB '31 Aug 92'
|
||||
ENDM
|
||||
|
||||
|
||||
CTRLC EQU 03H ; Control-C character
|
||||
BEL EQU 07H ; Bell character
|
||||
TAB EQU 09H ; Tab character
|
||||
LF EQU 0AH ; Line Feed character
|
||||
CR EQU 0DH ; Carriage Return 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)
|
||||
CPMDMA EQU 80H ; CP/M standard DMA buffer
|
||||
|
||||
|
||||
; From VLIB Get..
|
||||
EXTRN VPRINT, Z3VINIT
|
||||
|
||||
; From Z3LIB Get..
|
||||
EXTRN GETNAME, PRTNAME, WHRENV
|
||||
|
||||
; From SYSLIB Get..
|
||||
EXTRN CRLF, CAPINE, COUT
|
||||
|
||||
|
||||
;::::: PROGRAM START
|
||||
|
||||
ORG 100H
|
||||
CSEG
|
||||
|
||||
|
||||
BPSWAP: JP START ; bypass header
|
||||
DEFB 'Z3ENV' ; this is a ZCPR3 utility
|
||||
DEFB 1 ; show external environment
|
||||
|
||||
ENVADR: DEFW 0 ; addr of Z3 environment
|
||||
|
||||
START: LD HL,(CPMBDOS) ; ##### BUG: should be CPMBDOS+1 ?
|
||||
CALL WHRENV ; find Z3 Environment Descriptor
|
||||
LD (ENVADR),HL ; store addr
|
||||
CALL Z3VINIT ; ..and init for Z3LIB routines
|
||||
CALL GETNAME ; get actual program name
|
||||
CALL GQFLAG
|
||||
AND A ; running in quiet mode ?
|
||||
JR NZ,START0 ; ..if so, skip over
|
||||
CALL VPRINT
|
||||
DEFB 1,'B/P Drive Swap',2,' V',VER/10+'0','.',VER MOD 10 + '0',', '
|
||||
DATE
|
||||
DEFB CR,LF
|
||||
DEFB 0
|
||||
|
||||
START0: LD (STACK),SP
|
||||
LD SP,STACK
|
||||
|
||||
; get first token from command line (in FCB #1)
|
||||
LD A,(CPMFCB+1) ; get char
|
||||
CP '/' ; is this a help request ?
|
||||
JP Z,HELP ; ..if so, show help screen
|
||||
LD HL,(CPMBIOS+1) ; get warm boot addr (BIOS fn #1)
|
||||
LD L,30*3 ; adjust ptr to fn #30
|
||||
LD A,(HL) ; check byte at ptr location
|
||||
CP 0C3H ; is it opcode 0xC3 (JP) ?
|
||||
JR NZ,E$BPBIO ; ..if not, jump error and exit
|
||||
CALL JUMPHL ; else, "call" B/P Bios fn #30 (RETBIO)
|
||||
LD (BPBASE),BC ; store B/P Bios base addr
|
||||
LD HL,-6 ; move ptr 6 bytes backward
|
||||
ADD HL,DE ; (signature string)
|
||||
LD A,(HL) ; get byte
|
||||
CP 'B' ; is it 'B' ?
|
||||
JR NZ,E$BPBIO ; ..if not, error and exit
|
||||
INC HL ; ptr fwd
|
||||
LD A,(HL) ; get byte
|
||||
CP '/' ; is it '/' ?
|
||||
JR NZ,E$BPBIO ; ..if not, error and exit
|
||||
INC HL ; ptr fwd
|
||||
LD A,(HL) ; get byte
|
||||
CP 'P' ; is it 'P' ?
|
||||
JR Z,EVALCMD ; ..if so, jump to continue
|
||||
; else, fall through (error and exit)
|
||||
|
||||
E$BPBIO: CALL VPRINT
|
||||
DEFB CR,LF,BEL,'+++ Not B/P Bios ... aborting +++',CR,LF
|
||||
DEFB 0
|
||||
JP EXIT
|
||||
|
||||
|
||||
; evaluate command line
|
||||
EVALCMD: LD HL,CPMDMA ; ptr to standard DMA buffer (holds command line)
|
||||
LD A,(HL) ; get length of first token
|
||||
INC HL ; +1
|
||||
CALL ADDHLA ; move ptr fwd
|
||||
LD (HL),0 ; set <NUL> terminator
|
||||
LD HL,CPMDMA+1 ; set ptr to start of string
|
||||
CALL FINDDRV ; find letter of first drive
|
||||
JR C,RUNIMOD ; ..if invalid/not found, switch to interactive mode
|
||||
LD (DRV1ST),A ; else, store # of first drive
|
||||
LD A,(HL) ; get following byte
|
||||
CALL EVALSEP ; is it a separator char ?
|
||||
JP C,M$ABORT ; ..if not, abort program
|
||||
CALL FINDDRV ; find letter of second drive
|
||||
JR C,RUNIM0 ; ..if invalid/not found, switch to interactive mode
|
||||
LD (DRV2ND),A ; else, store # of second drive
|
||||
LD A,(HL) ; get following byte
|
||||
CALL EVALSEP ; is it a separator char ?
|
||||
JP C,M$ABORT ; ..if not, abort program
|
||||
JR SWAPDRV ; else, jump to continue
|
||||
|
||||
|
||||
; run in interactive mode
|
||||
RUNIMOD: CALL VPRINT
|
||||
DEFB ' First Drive to Swap [A..P] : '
|
||||
DEFB 0
|
||||
CALL CAPINE ; get input
|
||||
CALL CRLF
|
||||
CP CTRLC ; is it <Ctrl-C> ?
|
||||
JP Z,M$ABORT ; ..if so, abort program
|
||||
CALL EVALDRV ; check if drive letter is valid (A..P)
|
||||
JR C,RUNIMOD ; ..if not, loop ask for new input
|
||||
LD (DRV1ST),A ; else, store drive #
|
||||
RUNIM0: CALL VPRINT
|
||||
DEFB ' Second Drive to Swap [A..P] : '
|
||||
DEFB 0
|
||||
CALL CAPINE ; get input
|
||||
CALL CRLF
|
||||
CP CTRLC ; is it <Ctrl-C> ?
|
||||
JP Z,M$ABORT ; ..if so, abort program
|
||||
CALL EVALDRV ; check if drive letter is valid (A..P)
|
||||
JR C,RUNIM0 ; ..if not, loop ask for new input
|
||||
LD (DRV2ND),A ; else, store drive #
|
||||
|
||||
|
||||
;::::: PROCESS
|
||||
|
||||
SWAPDRV: LD HL,(BPBASE) ; get B/P Bios base addr
|
||||
LD L,22*3 ; adjust ptr to fn #22 (DRVTBL)
|
||||
CALL JUMPHL ; ..and "call" fn
|
||||
PUSH HL ; save ptr to DRVTBL
|
||||
LD A,(DRV1ST) ; get # of first drive
|
||||
ADD A,A ; *2 for 16-bit entries
|
||||
CALL ADDHLA ; ..and move ptr fwd
|
||||
EX DE,HL ; swap regs
|
||||
POP HL ; restore ptr to DRVTBL
|
||||
LD A,(DRV2ND) ; get # of second drive
|
||||
ADD A,A ; *2
|
||||
CALL ADDHLA ; ..and move ptr fwd
|
||||
|
||||
; DE= addr DPH first drive
|
||||
; HL= addr DPH second drive
|
||||
LD C,(HL) ; swap addr's in DRVTBL using
|
||||
LD A,(DE) ; regs DE, HL as pointers
|
||||
LD (HL),A ; and regs A, C holding bytes to copy
|
||||
LD A,C
|
||||
LD (DE),A
|
||||
INC HL
|
||||
INC DE
|
||||
LD C,(HL)
|
||||
LD A,(DE)
|
||||
LD (HL),A
|
||||
LD A,C
|
||||
LD (DE),A
|
||||
LD HL,0
|
||||
LD (PDRVVCT),HL ; init new Drive Vector (pos) with 0x0000
|
||||
DEC HL
|
||||
LD (NDRVVCT),HL ; init new Drive Vector (neg) with 0xFFFF
|
||||
LD HL,(ENVADR) ; get ENV addr
|
||||
LD DE,52 ; offset to Drive Vector
|
||||
ADD HL,DE ; move ptr
|
||||
PUSH HL ; ..and save it
|
||||
LD E,(HL) ; get Drive Vector in DE
|
||||
INC HL
|
||||
LD D,(HL)
|
||||
LD A,(DRV1ST) ; get # of first drive
|
||||
CALL MKDRMSK ; get bit mask for first drive
|
||||
LD C,L ; ..and move it to BC
|
||||
LD B,H
|
||||
LD A,(DRV2ND) ; get # of second drive
|
||||
CALL MKDRMSK ; get bit mask for second drive
|
||||
EX DE,HL ; ..and move it to DE
|
||||
CALL MKVCMSK ; update new Drive Vector for first drive
|
||||
PUSH BC ; swap BC and DE
|
||||
PUSH DE
|
||||
POP BC
|
||||
POP DE
|
||||
CALL MKVCMSK ; update new Drive Vector for second drive
|
||||
|
||||
; (Stack) = addr of Drive Vector in ENV - PUSH HL
|
||||
; HL= current Drive Vector, DE= bit mask first drive, BC= bit mask second drive
|
||||
EX DE,HL ; swap regs (save current Drive Vector in DE)
|
||||
ADD HL,BC ; add/merge bit masks
|
||||
EX (SP),HL ; put merged mask on stack - used by SWAPDRX
|
||||
; get addr of Drive Vector in ENV
|
||||
PUSH HL ; ..and save it
|
||||
EX DE,HL ; swap regs back (current Drive Vector in HL)
|
||||
LD BC,(PDRVVCT) ; get new Drive Vector (pos)
|
||||
LD DE,(NDRVVCT) ; and (neg)
|
||||
LD A,L ; low byte of current Drive Vector
|
||||
AND E ; reset bit (neg)
|
||||
OR C ; set bit (pos)
|
||||
LD E,A ; ..and store result in E
|
||||
LD A,H ; high byte of current Drive Vector
|
||||
AND D ; reset bit (neg)
|
||||
OR B ; set bit (pos)
|
||||
LD D,A ; ..and store result in D
|
||||
POP HL ; get addr of Drive Vector in ENV
|
||||
LD (HL),E ; store new Drive Vector (low byte)
|
||||
INC HL
|
||||
LD (HL),D ; ..and high byte
|
||||
CALL GQFLAG
|
||||
OR A ; check quiet flag
|
||||
JR NZ,SWAPDRX ; ..if quiet mode, skip over
|
||||
CALL VPRINT
|
||||
DEFB ' ...Drives '
|
||||
DEFB 0
|
||||
LD A,(DRV1ST) ; get # of first drive
|
||||
ADD A,'A' ; make ascii letter
|
||||
CALL COUT ; ..and display it
|
||||
CALL VPRINT
|
||||
DEFB ': and '
|
||||
DEFB 0
|
||||
LD A,(DRV2ND) ; get # of second drive
|
||||
ADD A,'A' ; make ascii letter
|
||||
CALL COUT ; ..and display it
|
||||
CALL VPRINT
|
||||
DEFB ': exchanged',CR,LF
|
||||
DEFB 0
|
||||
|
||||
; exit function
|
||||
SWAPDRX: POP DE ; restore merged bit masked 1st+2nd drive
|
||||
LD C,37 ; BDOS fn #37 Reset Drive(s)
|
||||
CALL CPMBDOS
|
||||
JP EXIT
|
||||
|
||||
|
||||
M$ABORT: CALL VPRINT
|
||||
DEFB ' ...aborting...',CR,LF
|
||||
DEFB 0
|
||||
JP EXIT
|
||||
|
||||
|
||||
;::::: HELP SCREEN
|
||||
|
||||
HELP: CALL VPRINT
|
||||
DEFB CR,LF,1
|
||||
DEFB 0
|
||||
CALL PPRGNAM
|
||||
CALL VPRINT
|
||||
DEFB 2,' exchanges the logical definition '
|
||||
DEFB 'of two physical disk drives',CR,LF
|
||||
DEFB ' or partitions. Drive letters must be '
|
||||
DEFB 'in the range of "A"-"P".',CR,LF
|
||||
DEFB ' The program is re-executable under '
|
||||
DEFB 'ZCPR with the "GO" command',CR,LF,LF
|
||||
DEFB ' Syntax: '
|
||||
DEFB 0
|
||||
CALL PPRGNAM
|
||||
CALL VPRINT
|
||||
DEFB ' <Drv1>[:] <tab| |,> <Drv2>[:]',CR,LF,LF
|
||||
DEFB ' Examples:',CR,LF,' '
|
||||
DEFB 0
|
||||
CALL PPRGNAM
|
||||
CALL VPRINT
|
||||
DEFB ' A: E: - Exchange E drive with A',CR,LF
|
||||
DEFB ' '
|
||||
DEFB 0
|
||||
CALL PPRGNAM
|
||||
CALL VPRINT
|
||||
DEFB ' D,H - Exchange D drive with H',CR,LF
|
||||
DEFB ' '
|
||||
DEFB 0
|
||||
CALL PPRGNAM
|
||||
CALL VPRINT
|
||||
DEFB ' // - display this message',CR,LF
|
||||
DEFB 0
|
||||
|
||||
|
||||
;::::: EXIT PROGRAM
|
||||
|
||||
EXIT: LD SP,(STACK) ; restore stack
|
||||
RET ; ..and return to system
|
||||
|
||||
|
||||
;::::: SUPPORT FUNCTIONS
|
||||
|
||||
; "called" as a pseudo-routine that returns to caller
|
||||
; in: HL= target addr
|
||||
JUMPHL: JP (HL) ; jump to addr in HL regs
|
||||
|
||||
|
||||
; parse nul-terminated string skipping separator chars
|
||||
; then fall through and check/convert drive letter
|
||||
; in: HL= ptr to string
|
||||
; out: A= drive number (or <NUL> if invalid letter)
|
||||
; HL= ptr to byte after end of string
|
||||
; C-Flag set if <NUL> (end of string) reached
|
||||
FINDDRV: LD A,(HL) ; get byte
|
||||
INC HL ; move ptr fwd
|
||||
OR A ; check if <NUL> (zero) = end of string
|
||||
SCF ; prepare status indicator (C-Flag set)
|
||||
RET Z ; ..if <NUL> byte, return
|
||||
CALL EVALSEP ; check if byte is a separator
|
||||
JR NC,FINDDRV ; ..if so, get next char
|
||||
; else, fall through and check if letter is valid
|
||||
|
||||
|
||||
; evaluate if letter is a valid drive (A..P) and return as number
|
||||
; in: A= letter to check
|
||||
; out: A= drive number
|
||||
; C-Flag set if error, NC= ok
|
||||
EVALDRV: CP 'A' ; is it lower than ascii 'A' ?
|
||||
RET C ; ..return with C-Flag already set
|
||||
CP 'P'+1 ; is it greater than ascii 'P' ?
|
||||
CCF ; ..reverse C-Flag to set correct status
|
||||
RET C ; and return
|
||||
SUB 'A' ; else, convert to number
|
||||
RET
|
||||
|
||||
|
||||
; evaluate char in register A whether it is a separator
|
||||
; (space, comma, colon, tab, zero)
|
||||
; in: A= char
|
||||
; out: C-Flag set if not separator, NC= char is separator
|
||||
EVALSEP: CP ' ' ; is it <SP> ?
|
||||
RET Z
|
||||
CP ',' ; Comma ?
|
||||
RET Z
|
||||
CP ':' ; Colon ?
|
||||
RET Z
|
||||
CP TAB ; <TAB> ?
|
||||
RET Z
|
||||
OR A ; <NUL> (zero) ?
|
||||
RET Z
|
||||
SCF ; set C-Flag
|
||||
RET
|
||||
|
||||
|
||||
; make bit mask for specified drive #
|
||||
; position of 1-bit represents drive in 16-bit word (similar to Drive Vector)
|
||||
; in: A= drive number
|
||||
; out: HL= bit mask
|
||||
MKDRMSK: LD HL,1 ; set bit 0
|
||||
INC A ; ahead of loop, increase A
|
||||
MKDRMS0: DEC A ; decrease A
|
||||
RET Z ; ..if zero, finished
|
||||
ADD HL,HL ; *2 (shift 1-bit to next position)
|
||||
JR MKDRMS0 ; loop
|
||||
|
||||
|
||||
; make bit masks for new Drive Vector
|
||||
; maintaining a positive (bits set) map, and a negate version (bits reset)
|
||||
; in: HL= current Drive Vector (from ENV)
|
||||
; BC= bit mask w/ old position
|
||||
; DE= bit mask w/ new position
|
||||
MKVCMSK: PUSH BC ; save regs
|
||||
LD A,B
|
||||
AND H ; mask high byte
|
||||
LD B,A ; ..and store result back in B
|
||||
LD A,C
|
||||
AND L ; mask low byte
|
||||
OR B ; check if invalid (= zero), ie. not mapped in Vector
|
||||
POP BC ; restore regs
|
||||
JR Z,MKVCMS0 ; if invalid drive, jump
|
||||
|
||||
; drive at new position exists in Drive Vector - set bit
|
||||
PUSH HL
|
||||
LD HL,(PDRVVCT)
|
||||
LD A,H ; high byte first
|
||||
OR D ; ..merge with new position
|
||||
LD H,A ; and store result back in H
|
||||
LD A,L ; low byte
|
||||
OR E ; ..merge with new position
|
||||
LD L,A ; and store result back in L
|
||||
LD (PDRVVCT),HL ; save final result
|
||||
POP HL
|
||||
RET
|
||||
|
||||
; drive at new position does _not_ exist in Drive Vector - reset bit
|
||||
MKVCMS0: PUSH HL
|
||||
LD HL,(NDRVVCT)
|
||||
LD A,D ; get high byte of new position
|
||||
CPL ; invert it
|
||||
AND H ; reset corresponding bit
|
||||
LD H,A ; ..and store result in H
|
||||
LD A,E ; get low byte of new position
|
||||
CPL ; invert it
|
||||
AND L ; reset corresponding bit
|
||||
LD L,A ; ..and store result in L
|
||||
LD (NDRVVCT),HL ; save final result
|
||||
POP HL
|
||||
RET
|
||||
|
||||
|
||||
; get Quiet Flag from Z3 Environment
|
||||
; in: -
|
||||
; out: A= Quiet Flag, defaults to A= 0 (not quiet)
|
||||
GQFLAG: LD HL,(ENVADR) ; get ENV addr
|
||||
LD A,H ; check if invalid (= zero)
|
||||
OR L
|
||||
RET Z ; ..if so, return
|
||||
LD A,40 ; else, move ptr forward
|
||||
CALL ADDHLA ; to Quiet Flag
|
||||
LD A,(HL) ; get value
|
||||
RET ; ..and return
|
||||
|
||||
|
||||
; add A to HL (result in HL)
|
||||
ADDHLA: ADD A,L ; add L
|
||||
LD L,A ; store result in L
|
||||
RET NC ; ..if no overflow, return
|
||||
INC H ; else, increment H
|
||||
RET
|
||||
|
||||
|
||||
; print program name on CON: device
|
||||
; (either the actual name, or fallback to default)
|
||||
; only used by HELP
|
||||
PPRGNAM: LD A,(ENVADR+1) ; get high byte of ENVPTR
|
||||
OR A ; check if valid (<> zero)
|
||||
JP NZ,PRTNAME ; ..if so, display actual name
|
||||
; and let return from there
|
||||
CALL VPRINT ; else, display default
|
||||
DEFB 'BPSWAP'
|
||||
DEFB 0
|
||||
RET
|
||||
|
||||
|
||||
;:::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
; VLIB - 0x0536
|
||||
; Z3LIB - 0x0757
|
||||
; SYSLIB - 0x0805
|
||||
; end addr 0x0854 (begin DSEG)
|
||||
;:::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
|
||||
|
||||
;::::: RAM STORAGE
|
||||
|
||||
DSEG
|
||||
|
||||
PDRVVCT: DEFW 0 ; new Drive Vector
|
||||
; (positive notation, bit _set_ for existing drives)
|
||||
NDRVVCT: DEFW 0 ; new Drive Vector
|
||||
; (negative notation, bits _reset_ for existing drives)
|
||||
BPBASE: DEFW 0 ; B/P Bios base addr
|
||||
DRV1ST: DEFB 0 ; # of first drive
|
||||
DRV2ND: DEFB 0 ; # of second drive
|
||||
|
||||
DEFS 40H ; room for stack
|
||||
STACK: DEFW 0 ; stack storage location
|
||||
|
||||
END
|
||||
|
||||
|
||||
;************************************************************************
|
||||
; Remarks jxl:
|
||||
; BPSWAP.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 BPSWAP.COM, i.e. no changes to the source were made. There
|
||||
; seems to be one bug (marked with "##### BUG") at the beginning of the
|
||||
; program.
|
||||
;************************************************************************
|
||||
636
Source/BPBIOS/UTIL/bpsysgen.z80
Normal file
636
Source/BPBIOS/UTIL/bpsysgen.z80
Normal file
@@ -0,0 +1,636 @@
|
||||
TITLE "Write B/P Bios System to system tracks of a disk"
|
||||
;************************************************************************
|
||||
;* B P S Y S G E N *
|
||||
;* Copy B/P Bios based Operating System to system tracks *
|
||||
;* by Harold F. Bower and Cameron W. Cotrill *
|
||||
;*----------------------------------------------------------------------*
|
||||
;* Disassembly: jxl Dec 2024 *
|
||||
;* public release 1.0 Apr 2025 *
|
||||
;* see remarks at the end *
|
||||
;*----------------------------------------------------------------------*
|
||||
;* LINK with Version 4 libraries: VLIB, Z3LIB, SYSLIB *
|
||||
;* *
|
||||
;* A>Z80ASM BPSYSGEN/RS *
|
||||
;* A>SLRNK BPSYSGEN/N,/A:100,/D:08CD,BPSYSGEN,Z3LIBS/S,SYSLIBS/S,/E *
|
||||
;************************************************************************
|
||||
|
||||
VER EQU 10
|
||||
REV EQU ' '
|
||||
|
||||
DATE MACRO
|
||||
DEFB '31 Aug 92'
|
||||
ENDM
|
||||
|
||||
|
||||
CTRLC EQU 03H ; Control-C character
|
||||
BEL EQU 07H ; Bell character
|
||||
LF EQU 0AH ; Line Feed character
|
||||
CR EQU 0DH ; Carriage Return 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
|
||||
|
||||
; From Z3LIB Get..
|
||||
EXTRN GETNAME, PRTNAME, Z3INIT, WHRENV
|
||||
|
||||
; From SYSLIB Get..
|
||||
EXTRN PUTUD, GETUD, SUA, EPRINT, CRLF, CAPINE, CIN, COUT
|
||||
|
||||
|
||||
;::::: PROGRAM START
|
||||
|
||||
ORG 100H
|
||||
CSEG
|
||||
|
||||
|
||||
BPSYSGEN: JP START ; bypass header
|
||||
DEFB 'Z3ENV' ; this is a ZCPR3 utility
|
||||
DEFB 1 ; show external environment
|
||||
|
||||
ENVADR: DEFW 0 ; addr of Z3 environment
|
||||
|
||||
START: LD HL,(CPMBDOS+1) ; BDOS entry as starting point for Z3ENV search
|
||||
CALL WHRENV ; get Z3 Environment
|
||||
LD (ENVADR),HL ; ..store it
|
||||
CALL Z3INIT ; init ENV ptr for Z3LIB modules
|
||||
CALL GETNAME ; get actual program name
|
||||
CALL GETQFLG ; check ENV quiet flag
|
||||
AND A ; zero means 'verbose' i.e. not quiet
|
||||
JR NZ,START1 ; ..if quiet mode, skip msg
|
||||
START0: CALL EPRINT
|
||||
DEFB 'B/P SYSGEN Utility V',VER/10+'0','.',VER MOD 10 + '0',REV
|
||||
DATE
|
||||
DEFB CR,LF,LF
|
||||
DEFB 0
|
||||
|
||||
START1: CALL PUTUD ; currently logged in drive/user
|
||||
LD HL,RESDISK ; prepare exit with resetting disk system
|
||||
PUSH HL ; by putting addr of 'RESDISK' on stack
|
||||
LD HL,(CPMBIOS+1) ; get BIOS entry addr
|
||||
LD A,8*3 ; move forward to fn #9 SELDSK
|
||||
CALL ADDHLA
|
||||
LD DE,BIOSELD ; ptr to target addr
|
||||
LD BC,8*3 ; bytes to copy (8 JP instructions, 3 bytes each)
|
||||
LDIR ; ..copy
|
||||
|
||||
|
||||
; Evaluate command line (if invalid parameters, switch to interactive mode)
|
||||
EVALCMD: LD HL,CPMFCB ; set ptr to standard FCB #1
|
||||
LD A,(HL) ; get drive
|
||||
LD (SRCDRV),A ; ..and store it (SRC)
|
||||
INC HL ; move ptr forard
|
||||
LD A,(HL) ; get byte/char
|
||||
CP '/' ; is this a help request ?
|
||||
JP Z,HELP ; ..if so, jump display help
|
||||
; ..and quit (addr of exit routine on stack)
|
||||
|
||||
; syntax: BPSYSGEN [d:]fn[.ft] [d:]
|
||||
; drive #1 = source, drive #2 = destination
|
||||
LD A,(CPMFCB2) ; get first byte of standard FCB #2
|
||||
LD (DSTDRV),A ; store drive # (DEST)
|
||||
LD (DSTDR2),A ; ..and a copy (as indicator for cmdline input)
|
||||
LD B,A ; remember value
|
||||
LD A,(HL) ; get first char of filename in FCB #1
|
||||
CP ' ' ; is it <SP> ?
|
||||
JP NZ,SRCRD0 ; ..if not, jump read sys file
|
||||
LD A,B ; else, restore char (from FCB #2)
|
||||
AND A ; is it <NUL> ?
|
||||
JP NZ,SRCREAD ; ..if not, jump read sys tracks
|
||||
; else, no source specified in command line
|
||||
; (switch to interactive mode)
|
||||
LD A,(SRCDRV) ; get source drive number
|
||||
LD (DSTDRV),A ; ..and overwrite destination drive number
|
||||
|
||||
|
||||
;::::: SOURCE DRIVE
|
||||
|
||||
; interactive mode
|
||||
SRCINP: CALL EPRINT
|
||||
DEFB 'Source Drive (CR to skip)? '
|
||||
DEFB 0
|
||||
CALL CAPINE ; get user input
|
||||
CALL CRLF
|
||||
CP CR ; is it <CR> ?
|
||||
JP Z,SRCRD1 ; ..if so, skip
|
||||
SUB 40H ; else, convert ascii to number
|
||||
LD (SRCDRV),A ; ..and store it
|
||||
CALL EPRINT
|
||||
DEFB 'Place source disk in drive '
|
||||
DEFB 0
|
||||
LD A,(SRCDRV) ; get source drive number
|
||||
ADD A,40H ; convert to ascii
|
||||
CALL COUT ; ..and display it
|
||||
CALL EPRINT
|
||||
DEFB ': and press return to continue...'
|
||||
DEFB 0
|
||||
SRCINP0: CALL CIN ; get input
|
||||
CP CTRLC ; is it <Ctrl-C> ?
|
||||
RET Z ; ..if so, return
|
||||
CP CR ; <CR> ?
|
||||
JR NZ,SRCINP0 ; ..if not, loop ask for new input
|
||||
CALL CRLF
|
||||
|
||||
|
||||
; start reading
|
||||
SRCREAD: CALL RDTRACK ; read system tracks of source disk
|
||||
JR SRCRD1 ; ..and skip over
|
||||
SRCRD0: CALL RDFILE ; read system file
|
||||
SRCRD1: CALL CHKSYS ; check if a valid system was loaded/read
|
||||
; (fn _not_ implemented, simply returns)
|
||||
JP NZ,E$NOSYS ; ..if not, jump error and exit
|
||||
LD A,(DSTDRV) ; get # of destination disk
|
||||
AND A
|
||||
JP NZ,DSTINP0 ; ..if not empty (= zero), jump to continue
|
||||
; else, fall through and ask user
|
||||
|
||||
|
||||
;::::: DESTINATION DRIVE
|
||||
|
||||
; interactive mode
|
||||
DSTINP: CALL EPRINT
|
||||
DEFB CR,LF,'Destination Drive (^C quits)? '
|
||||
DEFB 0
|
||||
CALL CAPINE ; get user input
|
||||
CP CTRLC ; is it <Ctrl-C> ?
|
||||
RET Z ; ..if so, return
|
||||
SUB 40H ; else, convert ascii to number
|
||||
LD (DSTDRV),A ; ..and store it
|
||||
CALL CRLF
|
||||
DSTINP0: LD A,(DSTDR2) ; get copy of # destination disk
|
||||
AND A ; check if valid
|
||||
JR NZ,DSTWRIT ; ..if so, running in command line mode
|
||||
; ..continue writing to destination immediately
|
||||
; else, fall through and ask user for input
|
||||
CALL EPRINT
|
||||
DEFB 'Place destination disk in drive '
|
||||
DEFB 0
|
||||
LD A,(DSTDRV) ; get destination drive number
|
||||
ADD A,40H ; convert to ascii
|
||||
CALL COUT ; ..and display it
|
||||
CALL EPRINT
|
||||
DEFB ': and press return to continue...'
|
||||
DEFB 0
|
||||
DSTINP1: CALL CIN ; get input
|
||||
CP CTRLC ; is it <Ctrl-C> ?
|
||||
RET Z ; ..if so, return
|
||||
CP CR ; <CR> ?
|
||||
JR NZ,DSTINP1 ; ..if not, loop ask for new input
|
||||
CALL CRLF
|
||||
|
||||
|
||||
; start writing
|
||||
; exit through "RET", addr of RESDISK routine is on stack
|
||||
DSTWRIT: CALL WRTRACK
|
||||
CALL GETQFLG
|
||||
AND A ; check if quiet flag is set
|
||||
RET NZ ; ..if not (= verbose), exit program
|
||||
LD A,(DSTDR2) ; else, get copy of # dest. disk (indicator cmdline mode)
|
||||
AND A ; check if valid
|
||||
RET NZ ; ..if not, exit program
|
||||
JP DSTINP ; else, loop ask for input
|
||||
|
||||
|
||||
; initiate a reset of disk system when returning to system
|
||||
RESDISK: LD C,13 ; BDOS fn #13 (reset disk system)
|
||||
CALL CPMBDOS
|
||||
JP GETUD ; set Drive/User and let return from there
|
||||
|
||||
|
||||
;::::: HELP SCREEN
|
||||
|
||||
HELP: CALL PRGNAME
|
||||
CALL EPRINT
|
||||
DEFB ' Places a copy of the operating '
|
||||
DEFB 'system onto the system',CR,LF
|
||||
DEFB ' tracks of a drive on the system.',CR,LF,LF
|
||||
DEFB ' Syntax: '
|
||||
DEFB 0
|
||||
CALL PRGNAME
|
||||
CALL EPRINT
|
||||
DEFB ' [DIR:[Ufn.Ft]] [D:]',CR,LF,LF
|
||||
DEFB ' Examples:',CR,LF,LF
|
||||
DEFB ' '
|
||||
DEFB 0
|
||||
CALL PRGNAME
|
||||
CALL EPRINT
|
||||
DEFB ' - Execute in Interactive Mode',CR,LF
|
||||
DEFB ' '
|
||||
DEFB 0
|
||||
CALL PRGNAME
|
||||
CALL EPRINT
|
||||
DEFB ' A: - Prompt for Source, '
|
||||
DEFB 'Place System onto A',CR,LF
|
||||
DEFB ' '
|
||||
DEFB 0
|
||||
CALL PRGNAME
|
||||
CALL EPRINT
|
||||
DEFB ' B:ZSDOS64.COM - Get System from File, '
|
||||
DEFB 'Prompt for Drive',CR,LF
|
||||
DEFB ' '
|
||||
DEFB 0
|
||||
CALL PRGNAME
|
||||
CALL EPRINT
|
||||
DEFB ' A: B: - Copy System from Drive A '
|
||||
DEFB 'to Drive B',CR,LF
|
||||
DEFB ' '
|
||||
DEFB 0
|
||||
CALL PRGNAME
|
||||
CALL EPRINT
|
||||
DEFB ' // - display this help',CR,LF
|
||||
DEFB 0
|
||||
RET
|
||||
|
||||
|
||||
;::::: SUPPORT FUNCTIONS
|
||||
|
||||
; get Quiet Flag from Z3 Environment
|
||||
; in: -
|
||||
; out: A= Quiet Flag, defaults to A= 0 (not quiet)
|
||||
GETQFLG: LD HL,(ENVADR) ; get local ENVPTR
|
||||
LD A,H ; check if invalid (= zero)
|
||||
OR L
|
||||
RET Z ; ..if so, return
|
||||
LD A,40 ; else, move ptr forward
|
||||
CALL ADDHLA ; to Quiet Flag
|
||||
LD A,(HL) ; get value
|
||||
RET ; ..and return
|
||||
|
||||
|
||||
; print program name on CON: device
|
||||
; (either the actual name, or fallback to default)
|
||||
; only used by HELP
|
||||
PRGNAME: LD A,(ENVADR+1) ; get high byte of ENVPTR
|
||||
OR A ; check if valid (<> zero)
|
||||
JP NZ,PRTNAME ; ..if so, display actual name
|
||||
; and let return from there
|
||||
CALL EPRINT ; else, display default
|
||||
DEFB 'BPSYSGEN'
|
||||
DEFB 0
|
||||
RET
|
||||
|
||||
|
||||
; Read system tracks - source
|
||||
RDTRACK: LD A,(SRCDRV) ; get source drive
|
||||
CALL SELDRV ; and select it
|
||||
JP Z,E$SRC ; ..if error, jump
|
||||
LD (SRCDPH),HL ; store addr of DPH
|
||||
LD A,10 ; move forward to DPB addr
|
||||
CALL ADDHLA ; at DPH+10
|
||||
LD E,(HL) ; get DPB addr in DE
|
||||
INC HL
|
||||
LD D,(HL)
|
||||
EX DE,HL ; swap regs
|
||||
LD (SRCDPB),HL ; ..and store DPB addr
|
||||
LD E,(HL) ; get sectors per track in DE
|
||||
INC HL ; at DPB+0
|
||||
LD D,(HL)
|
||||
LD (SECTTRK),DE ; store value
|
||||
LD A,12 ; move forward to track offset
|
||||
CALL ADDHLA ; (beginning of directory) at DPB+13
|
||||
LD E,(HL) ; get track offset in DE
|
||||
INC HL
|
||||
LD D,(HL)
|
||||
LD A,D ; check upper nybble
|
||||
AND A ; is it zero ?
|
||||
JP NZ,RDTRK0 ; ..if not, jump to adjust
|
||||
OR E ; check lower nybble
|
||||
JP Z,E$NOSYS ; ..if also zero, jump to error and exit
|
||||
CP 4 ; check upper limit for # of system tracks
|
||||
JR C,RDTRK1 ; ..if within boundaries, skip over
|
||||
RDTRK0: LD DE,2 ; set (default) # of system tracks
|
||||
|
||||
RDTRK1: LD B,E ; trk offset in B (counter)
|
||||
LD DE,(SECTTRK) ; get sect/trk
|
||||
LD HL,0 ; set initial value
|
||||
RDTRK2: ADD HL,DE ; multiply by addition
|
||||
DJNZ RDTRK2 ; loop till done
|
||||
XOR A ; nullify A
|
||||
OR H ; check if H is zero
|
||||
JP NZ,E$NOSYS ; ..if not, jump error and exit
|
||||
PUSH HL ; save regs
|
||||
LD BC,0
|
||||
CALL BIOSTTR ; set track # 0
|
||||
POP HL ; restore regs
|
||||
LD C,H ; move # of sectors containing system
|
||||
LD B,L ; to BC (as counter)
|
||||
LD DE,0 ; set intial value
|
||||
LD HL,FILEBUF ; set target addr to file buffer
|
||||
; (at 0x0900, page-aligned after end of program)
|
||||
|
||||
RDTRK3: PUSH DE ; save regs
|
||||
PUSH BC
|
||||
PUSH HL
|
||||
LD HL,(SRCDPH) ; get addr of DPH
|
||||
LD E,(HL) ; get skew table ptr in DE
|
||||
INC HL
|
||||
LD D,(HL)
|
||||
CALL BIOSTRN ; translate logical sector # in BC
|
||||
LD B,H ; move physical sector # to BC
|
||||
LD C,L
|
||||
CALL BIOSTSE ; ..and set (physical) sector
|
||||
POP BC ; restore target addr
|
||||
PUSH BC
|
||||
CALL BIOSTDM ; set as DMA buffer addr
|
||||
CALL BIOREAD ; read one sector
|
||||
OR A ; check for error (A <> 0)
|
||||
JP NZ,E$READ ; ..if error, jump
|
||||
POP HL ; restore target addr
|
||||
LD DE,128 ; increase by 128 bytes (1 sector)
|
||||
ADD HL,DE
|
||||
POP BC ; restore regs / clear stack
|
||||
POP DE
|
||||
DEC B ; decrease counter
|
||||
RET Z ; ..if finished, return
|
||||
INC C
|
||||
LD A,C
|
||||
AND 00000011b ; mask lower 2 bits
|
||||
LD A,'.'
|
||||
CALL Z,COUT ; display progress every 4 sectors (0.5 kB)
|
||||
LD A,(SECTTRK)
|
||||
CP C ; max. # sect/trk reached ?
|
||||
JR NZ,RDTRK3 ; ..if not, loop
|
||||
INC DE ; increase trk counter
|
||||
LD C,0 ; reset sect counter
|
||||
PUSH DE ; save regs
|
||||
PUSH BC
|
||||
PUSH HL
|
||||
LD B,D ; copy trk # in BC
|
||||
LD C,E
|
||||
CALL BIOSTTR ; ..and set track #
|
||||
POP HL ; restore regs
|
||||
POP BC
|
||||
POP DE
|
||||
JR RDTRK3 ; loop
|
||||
|
||||
|
||||
; Read system file (img) - source
|
||||
RDFILE: LD A,(ENVADR+1) ; get base addr of ENV
|
||||
AND A ; check if invalid (= zero)
|
||||
JR Z,RDFIL0 ; ..if no ENV, skip over
|
||||
LD A,(CPMFCB+0DH) ; else, get user no from standard FCB #1
|
||||
CALL SUA ; ..and log in
|
||||
RDFIL0: LD DE,CPMFCB ; set ptr to standard FCB #1
|
||||
LD C,15 ; BDOS fn #15 Open File
|
||||
CALL BDOSSV
|
||||
JP Z,E$SOPEN
|
||||
LD HL,32 ; ptr to current record
|
||||
ADD HL,DE
|
||||
LD (HL),16 ; set # of current record
|
||||
; (skip 16 records = 2kB, MOVSYS boot loader code)
|
||||
LD HL,FILEBUF-128 ; set addr of file buffer (-128 ahead of loop)
|
||||
|
||||
RDFIL1: LD A,128 ; move forward by 128 bytes (1 sector)
|
||||
CALL ADDHLA
|
||||
EX DE,HL ; swap regs
|
||||
LD C,26 ; BDOS fn #26 Set DMA Address
|
||||
CALL BDOSSV
|
||||
EX DE,HL ; swap regs back
|
||||
LD C,20 ; BDOS fn #20 Read Sequentially
|
||||
CALL BDOSSV
|
||||
DEC A ; A= 1 returned means EOF, so decrease A
|
||||
JR Z,RDFIL1 ; ..if zero, continue with next sector
|
||||
LD C,16 ; BDOS fn #16 Close File
|
||||
JP BDOSSV
|
||||
|
||||
|
||||
; Write system tracks - destination
|
||||
WRTRACK: LD A,(DSTDRV) ; get destination drive
|
||||
CALL SELDRV ; and select it
|
||||
JP Z,E$DEST ; ..if error, jump and exit
|
||||
LD (DSTDPH),HL ; store addr of DPH
|
||||
LD A,10 ; move forward to DPB addr
|
||||
CALL ADDHLA ; at DPH+10
|
||||
LD E,(HL) ; get DPB addr in DE
|
||||
INC HL
|
||||
LD D,(HL)
|
||||
EX DE,HL ; swap regs
|
||||
LD (DSTDPB),HL ; ..and store DPB addr
|
||||
LD E,(HL) ; get sectors per track in DE
|
||||
INC HL ; at DPB+0
|
||||
LD D,(HL)
|
||||
LD (SECTTRK),DE ; store value
|
||||
LD A,12 ; move forward to track offset
|
||||
CALL ADDHLA ; (beginning of directory) at DPB+13
|
||||
LD E,(HL) ; get track offset in DE
|
||||
INC HL
|
||||
LD D,(HL)
|
||||
LD A,D ; check upper nybble
|
||||
AND A ; is it zero ?
|
||||
JP NZ,WRTRK0 ; ..if not, jump to adjust
|
||||
OR E ; check lower nybble
|
||||
JP Z,E$NOSYS ; ..if also zero, jump to error and exit
|
||||
CP 4 ; check upper limit for # of system tracks
|
||||
JR C,WRTRK1 ; ..if within boundaries, skip over
|
||||
|
||||
WRTRK0: LD DE,2 ; set (default) # of system tracks
|
||||
|
||||
WRTRK1: LD B,E ; trk offset in B (counter)
|
||||
LD DE,(SECTTRK) ; get sect/trk
|
||||
LD HL,0 ; set initial value
|
||||
WRTRK2: ADD HL,DE ; multiply by addition
|
||||
DJNZ WRTRK2 ; loop till done
|
||||
XOR A ; nullify A
|
||||
OR H ; check if H is zero
|
||||
JP NZ,E$NOSYS ; ..if not, jump error and exit
|
||||
PUSH HL ; save regs
|
||||
LD BC,0
|
||||
CALL BIOSTTR ; set track # 0
|
||||
POP HL ; save regs
|
||||
LD C,H ; move # of sectors containing system
|
||||
LD B,L ; to BC (as counter)
|
||||
LD DE,0 ; set initial value
|
||||
LD HL,FILEBUF ; set origin addr (file buffer)
|
||||
|
||||
WRTRK3: PUSH DE ; save regs
|
||||
PUSH BC
|
||||
PUSH HL
|
||||
LD HL,(DSTDPH) ; get addr of DPH
|
||||
LD E,(HL) ; get skew table ptr in DE
|
||||
INC HL
|
||||
LD D,(HL)
|
||||
CALL BIOSTRN ; translate logical sector # in BC
|
||||
LD B,H ; move physical sector # to BC
|
||||
LD C,L
|
||||
CALL BIOSTSE ; ..and set (physical) sector
|
||||
POP BC ; restore origin addr
|
||||
PUSH BC
|
||||
CALL BIOSTDM ; set as DMA buffer addr
|
||||
LD C,0
|
||||
CALL BIOWRIT ; write one sector
|
||||
OR A ; check for error (A <> 0)
|
||||
JP NZ,E$WRITE ; ..if error, jump
|
||||
POP HL ; restore origin addr
|
||||
LD DE,128 ; ..and increase by 128 bytes (1 sector)
|
||||
ADD HL,DE
|
||||
POP BC ; restore regs / clear stack
|
||||
POP DE
|
||||
DEC B ; decrease counter
|
||||
JR NZ,WRTRK4 ; ..if not finished, continue
|
||||
LD C,1 ; else, force write (flush to disk)
|
||||
JP BIOWRIT ; ..and let return from there
|
||||
|
||||
WRTRK4: INC C
|
||||
LD A,C
|
||||
AND 00000011b ; mask lower 2 bits
|
||||
LD A,'.'
|
||||
CALL Z,COUT ; display progress every 4 sectors (0.5 kB)
|
||||
LD A,(SECTTRK)
|
||||
CP C ; max. # sect/trk reached ?
|
||||
JR NZ,WRTRK3 ; ..if not, loop
|
||||
INC DE ; increase trk counter
|
||||
LD C,0 ; reset sect counter
|
||||
PUSH DE ; save regs
|
||||
PUSH BC
|
||||
PUSH HL
|
||||
LD B,D ; copy trk # in BC
|
||||
LD C,E
|
||||
CALL BIOSTTR ; ..and set track
|
||||
POP HL ; restore regs
|
||||
POP BC
|
||||
POP DE
|
||||
JR WRTRK3 ; loop
|
||||
|
||||
|
||||
; check if a valid B/P Bios was loaded
|
||||
; *** function not implemented ***
|
||||
; in: -
|
||||
; out: Z-Flag set if ok, NZ= error
|
||||
CHKSYS: XOR A ; always return Z-Flag set
|
||||
RET
|
||||
|
||||
|
||||
; select disk drive
|
||||
; in: A= drive number (one-based)
|
||||
; out: Z-Flag set if error
|
||||
SELDRV: DEC A ; -1 to comply with CP/M BIOS standards
|
||||
LD C,A
|
||||
LD E,0
|
||||
CALL BIOSELD ; call BIOS fn #9 directly
|
||||
LD A,H
|
||||
OR L
|
||||
RET
|
||||
|
||||
|
||||
; call BDOS saving regs BC, DE, HL
|
||||
; out: A= 0 and Z-Flag set if not found
|
||||
BDOSSV: PUSH BC
|
||||
PUSH DE
|
||||
PUSH HL
|
||||
CALL CPMBDOS
|
||||
INC A ; 0xFF --> 0x00 if not found
|
||||
POP HL
|
||||
POP DE
|
||||
POP BC
|
||||
RET
|
||||
|
||||
|
||||
; add A to HL (result in HL)
|
||||
ADDHLA: ADD A,L ; add L
|
||||
LD L,A ; store result in L
|
||||
RET NC ; ..if no overflow, return
|
||||
INC H ; else, increment H
|
||||
RET
|
||||
|
||||
|
||||
;::::: ERROR MESSAGES
|
||||
|
||||
; display msg on CON: then exit with warm boot
|
||||
E$READ: CALL EPRINT
|
||||
DEFB BEL,'*** Read error'
|
||||
DEFB 0
|
||||
JP EXIT
|
||||
|
||||
E$SRC: CALL EPRINT
|
||||
DEFB BEL,'*** Bad source!'
|
||||
DEFB 0
|
||||
JP EXIT
|
||||
|
||||
E$WRITE: CALL EPRINT
|
||||
DEFB BEL,'*** Write error'
|
||||
DEFB 0
|
||||
JP EXIT
|
||||
|
||||
E$DEST: CALL EPRINT
|
||||
DEFB BEL,'*** Bad destination!'
|
||||
DEFB 0
|
||||
JP EXIT
|
||||
|
||||
E$NOSYS: CALL EPRINT
|
||||
DEFB BEL,'*** No system!'
|
||||
DEFB 0
|
||||
JP EXIT
|
||||
|
||||
E$SOPEN: CALL EPRINT
|
||||
DEFB BEL,"*** Can't open source file!"
|
||||
DEFB 0
|
||||
|
||||
|
||||
;::::: EXIT PROGRAM
|
||||
|
||||
EXIT: CALL CRLF
|
||||
LD HL,0 ; set addr
|
||||
JP (HL) ; and jump to CP/M WBOOT
|
||||
|
||||
|
||||
;::::: BIOS JUMPS (for direct calls)
|
||||
|
||||
; area is filled with actual jumps at runtime
|
||||
; to call BIOS fn's directly
|
||||
BIOSELD: JP 0 ; fn #9 SELDSK select disk
|
||||
BIOSTTR: JP 0 ; fn #10 SETTRK set track
|
||||
BIOSTSE: JP 0 ; fn #11 SETSEC set sector
|
||||
BIOSTDM: JP 0 ; fn #12 SETDMA set buffer addr
|
||||
BIOREAD: JP 0 ; fn #13 READ read one sector
|
||||
BIOWRIT: JP 0 ; fn #14 WRITE write one sector
|
||||
BIOLIST: JP 0 ; fn #15 LISTST list status (not used)
|
||||
BIOSTRN: JP 0 ; fn #16 SECTRN sector translation
|
||||
|
||||
|
||||
|
||||
;::::: RAM STORAGE (not in DSEG !)
|
||||
|
||||
SECTTRK: DEFW 0 ; sectors per track (sect/trk), used for src+dst
|
||||
SRCDPH: DEFW 0 ; source: addr of Disk Parameter Header (DPH)
|
||||
SRCDPB: DEFW 0 ; source: addr of Disk Parameter Block (DPB)
|
||||
DSTDPH: DEFW 0 ; destination: addr of DPH
|
||||
DSTDPB: DEFW 0 ; destination: addr of DPB
|
||||
SRCDRV: DEFB 0 ; source: drive # (from standard FCB #1)
|
||||
DSTDRV: DEFB 0 ; destination drive #
|
||||
DSTDR2: DEFB 0 ; destination drive # (copy)
|
||||
; extracted from cmdline, used as indicator for run mode
|
||||
|
||||
|
||||
|
||||
;:::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
; Z3LIB - 0x0735
|
||||
; SYSLIB - 0x07e3
|
||||
; end addr 0x08cc (DSEG Z3+SYS = 4 bytes)
|
||||
;:::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
|
||||
; buffer start addr = 0x0900
|
||||
FILEBUF: EQU $+512-($-BPSYSGEN AND 255)
|
||||
|
||||
DSEG
|
||||
|
||||
END
|
||||
|
||||
|
||||
;************************************************************************
|
||||
; Remarks jxl:
|
||||
; BPSYSGEN.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 BPSYSGEN.COM, i.e. no changes to the source were made.
|
||||
; The program is pretty straightforward. It supports a command line
|
||||
; mode and an interactive mode. (Code portions for the latter are pretty
|
||||
; short.) Functionality to check if the running system is valid, was
|
||||
; not implemented. Since other B/P Bios tools perform such checks, this
|
||||
; is rather surprising.
|
||||
; An interesting approach was used to end the program and literally
|
||||
; return to the system. The address of RESDISK routine is pushed on the
|
||||
; stack at the very beginning.
|
||||
;************************************************************************
|
||||
489
Source/BPBIOS/UTIL/confz4.z80
Normal file
489
Source/BPBIOS/UTIL/confz4.z80
Normal file
@@ -0,0 +1,489 @@
|
||||
TITLE "ZCPR 4 Configuration Utility"
|
||||
;************************************************************************
|
||||
;* C O N F Z 4 *
|
||||
;* Configure ZCPR 4 options *
|
||||
;* by Harold F. Bower and Cameron W. Cotrill *
|
||||
;*----------------------------------------------------------------------*
|
||||
;* Disassembly: jxl Jan 2025 *
|
||||
;* public release 1.0 Apr 2025 *
|
||||
;* see remarks at the end *
|
||||
;*----------------------------------------------------------------------*
|
||||
;* LINK with Version 4 libraries: Z3LIB, SYSLIB *
|
||||
;* *
|
||||
;* A>Z80ASM CONFZ4/RS *
|
||||
;* A>SLRNK CONFZ4/N,/A:100,/D:080A,CONFZ4,Z3LIBS/S,SYSLIBS/S,/E *
|
||||
;************************************************************************
|
||||
|
||||
VER EQU 10
|
||||
REV EQU ' '
|
||||
|
||||
DATE MACRO
|
||||
DEFB '18 Nov 95'
|
||||
ENDM
|
||||
|
||||
|
||||
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
|
||||
|
||||
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)
|
||||
CPMDMA EQU 80H ; CP/M standard DMA buffer
|
||||
|
||||
|
||||
; From Z3LIB Get..
|
||||
EXTRN GETNAME, PRTNAME, Z3INIT, WHRENV
|
||||
|
||||
; From SYSLIB Get..
|
||||
EXTRN EPRINT, CRLF, CAPIN, PA2HC, COUT
|
||||
|
||||
|
||||
;::::: PROGRAM START
|
||||
|
||||
ORG 100H
|
||||
CSEG
|
||||
|
||||
|
||||
CONFZ4: JP START ; bypass header
|
||||
DEFB 'Z3ENV' ; this is a ZCPR3 utility
|
||||
DEFB 1 ; show external environment
|
||||
|
||||
ENVADR: DEFW 0 ; addr of Z3 environment
|
||||
DEFW CONFZ4 ; type 4 filler
|
||||
|
||||
DEFB 'CONFZ41 ',0 ; configuration name
|
||||
|
||||
START: LD (STACK),SP
|
||||
LD SP,STACK
|
||||
CALL EPRINT
|
||||
DEFB 'B/P System Command Processor Configuration V'
|
||||
DEFB VER/10+'0','.',VER MOD 10 + '0',REV,' '
|
||||
DATE
|
||||
DEFB CR,LF
|
||||
DEFB 0
|
||||
|
||||
CALL INITZ3 ; find Z3ENV and check Wheel Byte
|
||||
CALL GETNAME ; get actual program name
|
||||
CALL CHKHLP ; check if help was requested
|
||||
SUB ' ' ; ##### convert to ... ??
|
||||
LD (UNUSED1),A ; ##### and store (not used at all)
|
||||
CALL CHKSYS ; check if running B/P Bios
|
||||
LD HL,(BPCNFG) ; addr CONFIG area
|
||||
INC HL ; move ptr fwd
|
||||
INC HL
|
||||
LD A,(HL) ; get option flags (OPTF1)
|
||||
AND 00000001B ; mask bit 0 (0= unbanked, 1= banked)
|
||||
LD (BPBNKD),A ; store indicator
|
||||
JR NZ,CHKXENV ; ..if banked, jump to continue
|
||||
CALL EPRINT ; else, display msg and exit
|
||||
DEFB CR,LF,'+++ Not Banked System..aborting...!',BEL
|
||||
DEFB 0
|
||||
JP EXIT
|
||||
|
||||
; check for extended environment
|
||||
CHKXENV: INC HL ; move ptr fwd
|
||||
INC HL
|
||||
INC HL
|
||||
LD A,(HL) ; get first system bank (SYSBNK)
|
||||
LD (SYSBNK),A ; store it
|
||||
LD HL,(ENVADR) ; addr ENV
|
||||
LD DE,8 ; offset to type
|
||||
ADD HL,DE ; move ptr
|
||||
BIT 7,(HL) ; check high bit (= 0x80+ for extended Z3ENV)
|
||||
JR NZ,CHKVERS ; ..if set, jump to continue
|
||||
CALL EPRINT
|
||||
DEFB CR,LF,'+++ Not Extended Environment..aborting..!',BEL
|
||||
DEFB 0
|
||||
JP EXIT
|
||||
|
||||
; check ZCPR version
|
||||
CHKVERS
|
||||
LD DE,55 ; offset addr CPR (8+55 = 63)
|
||||
ADD HL,DE ; move ptr
|
||||
LD E,(HL) ; get addr in DE
|
||||
INC HL
|
||||
LD D,(HL)
|
||||
LD HL,5 ; offset to version byte in ZCPR 4.x
|
||||
; (code starts with JP.., JR.., VERSION)
|
||||
ADD HL,DE ; move ptr
|
||||
LD A,(HL) ; get byte
|
||||
CP 41H ; is it 4.1 (or higher) ?
|
||||
JR NC,PVRSION ; ..if so, jump to continue
|
||||
PUSH AF ; else, display error msg and exit
|
||||
CALL EPRINT
|
||||
DEFB CR,LF,BEL,"+++ Can't Configure Vers : "
|
||||
DEFB 0
|
||||
POP AF
|
||||
CALL PA2HC
|
||||
CALL EPRINT
|
||||
DEFB ' of Command Processor!'
|
||||
DEFB 0
|
||||
JP EXIT
|
||||
|
||||
; display version
|
||||
PVRSION: PUSH AF
|
||||
CALL EPRINT
|
||||
DEFB CR,LF,' Configuring Options for CPR Version : '
|
||||
DEFB 0
|
||||
POP AF ; restore version #
|
||||
PUSH AF
|
||||
RRCA ; rotate upper nybble to lower
|
||||
RRCA ; (major version #)
|
||||
RRCA
|
||||
RRCA
|
||||
AND 00001111B ; mask lower nybble
|
||||
ADD A,'0' ; ..and convert to ascii
|
||||
CALL COUT ; display major version #
|
||||
LD A,'.'
|
||||
CALL COUT
|
||||
POP AF ; restore version #
|
||||
AND 00001111B ; mask lower nybble
|
||||
ADD A,'0' ; ..and convert to ascii
|
||||
CALL COUT ; display minor version #
|
||||
CALL CRLF
|
||||
LD DE,10 ; move forward by another 10 bytes
|
||||
ADD HL,DE ; (in Z40-1.Z80 three bytes are defined as 'Space
|
||||
; reserved for expansion' - this is the last byte)
|
||||
LD (PFLGADR),HL ; store addr
|
||||
|
||||
; branch interactive/cmdline mode
|
||||
LD A,(CPMFCB+1) ; get first char from cmdline
|
||||
CP ' ' ; is it <SP> ?
|
||||
JP NZ,EVALCMD ; ..if not, jump cmdline mode
|
||||
CALL EPRINT ; else, interactive mode
|
||||
DEFB CR,LF,'Turn Time ON in Prompt Line ([Y]/N)? : '
|
||||
DEFB 0
|
||||
CALL CAPIN ; get user input
|
||||
LD BC,0FE01H ; default to ON, European format
|
||||
; ( 11111110 00000001 B )
|
||||
CP 'N' ; is it 'N' ?
|
||||
JR NZ,RUNIMOD ; ..if not, skip over
|
||||
LD C,0 ; else, clear C (indicating OFF)
|
||||
|
||||
; run interactive mode
|
||||
RUNIMOD: CALL SETOPTB ; set byte
|
||||
CALL EPRINT
|
||||
DEFB CR,LF,'US (mm/dd/yy) or European (dd.mm.yy) Dates ([U]/E) : '
|
||||
DEFB 0
|
||||
CALL CAPIN ; get user input
|
||||
LD BC,0FD00H ; default to US format
|
||||
; ( 11111101 00000000 B )
|
||||
CP 'E' ; is it 'E' ?
|
||||
JR NZ,RUNIM0 ; ..if not, skip over
|
||||
LD C,00000010B ; else, set European format
|
||||
RUNIM0: CALL SETOPTB ; set byte
|
||||
JP EXIT
|
||||
|
||||
; evaluate command line
|
||||
EVALCMD: LD HL,CPMDMA
|
||||
LD A,(HL) ; get # of chars
|
||||
INC HL ; set ptr to start of cmdline
|
||||
PUSH HL ; save regs
|
||||
CALL ADDHLA ; move ptr to end of cmdline
|
||||
LD (HL),0 ; set <NUL> terminator
|
||||
POP HL ; restore start of cmdline
|
||||
CALL SKPWHSP ; skip any whitespace at the beginning
|
||||
LD A,(HL) ; get char
|
||||
CP '/' ; is it option char ?
|
||||
JR NZ,ECMD0 ; ..if not, skip over
|
||||
INC HL ; else, move ptr forward
|
||||
ECMD0: LD A,(HL) ; get byte
|
||||
OR A
|
||||
JR Z,ECMD1 ; ..if zero, jump and exit
|
||||
CALL CMPRMPT ; else, attempt processing option
|
||||
JR ECMD0 ; ..and loop
|
||||
|
||||
ECMD1: JP EXIT
|
||||
|
||||
|
||||
; cmdline: /T[+|-] Toggle Time in Prompt
|
||||
; option byte, bit 0 = 0 off / 1 on
|
||||
;
|
||||
; cmdline: /U /E US/Europe format
|
||||
; option byte, bit 1 = 0 US / 1 European
|
||||
|
||||
; process prompt on/off
|
||||
CMPRMPT: CP 'T' ; is char 'T' (Toggle) ?
|
||||
JR NZ,CMFORMT ; ..if not, try processing format option
|
||||
INC HL
|
||||
LD C,00000001B ; prepare for ON
|
||||
LD A,(HL) ; get next char
|
||||
CP '+' ; is it '+' ?
|
||||
JR Z,CMPRMP0 ; ..if so, skip over
|
||||
LD C,00000000B ; else, prepare for OFF
|
||||
CP '-' ; is it '-' ?
|
||||
JR NZ,CMFORMT ; ..if not, rather check format
|
||||
CMPRMP0: LD B,11111110B ; default to European format
|
||||
|
||||
CMSETOP: CALL SETOPTB ; set
|
||||
CMSETX: INC HL ; move ptr fwd
|
||||
RET ; ..and exit
|
||||
|
||||
; process format
|
||||
CMFORMT: LD B,11111101B ; default to ON (else, format wouldn't make sense)
|
||||
LD C,00000010B ; prepare for European
|
||||
CP 'E' ; is it 'E' ?
|
||||
JR Z,CMSETOP ; ..if so, set byte
|
||||
LD C,00000000B ; else, prepare for US
|
||||
CP 'U' ; is it 'U' ?
|
||||
JR Z,CMSETOP ; ..if so, set byte
|
||||
JR CMSETX ; jump exit
|
||||
|
||||
|
||||
; set option byte
|
||||
; in: B= format (US/European)
|
||||
; C= on/off
|
||||
SETOPTB: EX DE,HL ; swap regs (save HL)
|
||||
LD HL,(PFLGADR) ; addr of Prompt flag in ZCPR4 config area
|
||||
LD A,(HL) ; get byte
|
||||
AND B ; apply format setting
|
||||
OR C ; merge on/off setting
|
||||
LD (HL),A ; ..and save byte
|
||||
LD HL,010FH ; offset to option byte in SYSBNK
|
||||
CALL GETFRB ; get current setting
|
||||
AND B ; apply format setting
|
||||
OR C ; merge on/off setting
|
||||
CALL SETINB ; ..and write back
|
||||
EX DE,HL
|
||||
RET
|
||||
|
||||
|
||||
; check if help was requested
|
||||
; get first token from command line (in FCB #1)
|
||||
CHKHLP: LD HL,CPMFCB+1
|
||||
LD A,(HL) ; get char
|
||||
CP '/' ; is this a help request ?
|
||||
RET NZ ; ..if not, return
|
||||
INC HL ; move ptr fwd
|
||||
LD A,(HL) ; check following char
|
||||
CP '/' ; if it is also '/'
|
||||
RET NZ ; ..if not, return
|
||||
; else, fall through and show help screen
|
||||
|
||||
|
||||
;::::: HELP SCREEN
|
||||
|
||||
HELP: CALL EPRINT
|
||||
DEFB CR,LF,' '
|
||||
DEFB 0
|
||||
CALL PPRGNAM
|
||||
CALL EPRINT
|
||||
DEFB ' Configure Running B/P Command Processor Options.',CR,LF,LF
|
||||
DEFB ' Syntax:',CR,LF,' '
|
||||
DEFB 0
|
||||
CALL PPRGNAM
|
||||
CALL EPRINT
|
||||
DEFB ' - Configure in Interactive Mode',CR,LF,' '
|
||||
DEFB 0
|
||||
CALL PPRGNAM
|
||||
CALL EPRINT
|
||||
DEFB ' /T[+|-] - Toggle Time in Prompt [Set On/Off]',CR,LF,' '
|
||||
DEFB 0
|
||||
CALL PPRGNAM
|
||||
CALL EPRINT
|
||||
DEFB ' /E - Display Date in European (dd.mm.yy) form',CR,LF,' '
|
||||
DEFB 0
|
||||
CALL PPRGNAM
|
||||
CALL EPRINT
|
||||
DEFB ' /U - Display Date in US (mm/dd/yy) form',CR,LF,' '
|
||||
DEFB 0
|
||||
CALL PPRGNAM
|
||||
CALL EPRINT
|
||||
DEFB ' // - display this screen',CR,LF,LF
|
||||
DEFB ' Arguments may be combined as:',CR,LF,' '
|
||||
DEFB 0
|
||||
CALL PPRGNAM
|
||||
CALL EPRINT
|
||||
DEFB ' /T+U - Turn Time On, US-style Date Display',CR,LF,LF
|
||||
DEFB 'This program will only run in Banked B/P Systems.',CR,LF
|
||||
DEFB 0
|
||||
|
||||
|
||||
;::::: EXIT PROGRAM
|
||||
|
||||
EXIT: CALL CRLF
|
||||
LD SP,(STACK) ; restore stack
|
||||
RET ; ..and return to system
|
||||
|
||||
|
||||
;::::: SUPPORT FUNCTIONS
|
||||
|
||||
; init Z3ENV and check Wheel byte
|
||||
; if not successful, exit program
|
||||
INITZ3: LD HL,(CPMBDOS+1)
|
||||
CALL WHRENV ; find Z3 Environment Descriptor
|
||||
LD (ENVADR),HL ; store ENV addr
|
||||
LD A,H ; check if invalid (= zero)
|
||||
OR L
|
||||
JP Z,E$BPBIO ; ..if so, jump exit
|
||||
CALL Z3INIT ; init for Z3LIB routines
|
||||
LD A,41 ; offset to addr wheel byte (Z3WHL)
|
||||
CALL ADDHLA ; move ptr fwd
|
||||
LD E,(HL) ; get addr in DE
|
||||
INC HL
|
||||
LD D,(HL)
|
||||
EX DE,HL ; swap regs
|
||||
LD A,(HL) ; get value of wheel byte
|
||||
AND A ; check if zero
|
||||
RET NZ ; ..if not ON, return
|
||||
CALL EPRINT ; else, display message and exit
|
||||
DEFB BEL,CR,LF,'Must be wheel to Execute !',CR,LF
|
||||
DEFB 0
|
||||
JR EXIT
|
||||
|
||||
|
||||
; check if running under B/P Bios
|
||||
; if not, program is terminated
|
||||
CHKSYS: LD HL,(CPMBIOS+1) ; get warm boot addr (BIOS fn #1)
|
||||
LD L,30*3 ; adjust ptr to fn #30
|
||||
LD A,(HL) ; check byte at ptr location
|
||||
CP 0C3H ; is it opcode 0xC3 (JP) ?
|
||||
JR NZ,E$BPBIO ; ..if not, jump error and exit
|
||||
CALL JUMPHL ; else, "call" B/P Bios fn #30 (RETBIO)
|
||||
LD (BPADDR),BC ; store base addr of B/P Bios
|
||||
LD (BPCNFG),DE ; " config area addr
|
||||
LD HL,-6 ; move ptr 6 bytes backward
|
||||
ADD HL,DE ; (signature string)
|
||||
LD A,(HL) ; get byte
|
||||
CP 'B' ; is it 'B' ?
|
||||
JR NZ,E$BPBIO ; ..if not, jump error and exit
|
||||
INC HL
|
||||
LD A,(HL) ; get next byte
|
||||
CP '/' ; is it '/' ?
|
||||
JR NZ,E$BPBIO ; ..if not, jump error and exit
|
||||
INC HL
|
||||
LD A,(HL) ; and get next byte
|
||||
CP 'P' ; is it 'P' ?
|
||||
RET Z ; ..if so, return
|
||||
; else, fall through (error and exit)
|
||||
|
||||
|
||||
; error msg
|
||||
E$BPBIO: CALL EPRINT
|
||||
DEFB CR,LF,BEL,'Not B/P Bios, aborting...!',CR,LF
|
||||
DEFB 0
|
||||
RST 0
|
||||
|
||||
|
||||
; print program name on CON: device
|
||||
; (either the actual name, or fallback to default)
|
||||
; only used by HELP
|
||||
PPRGNAM: LD A,(ENVADR+1) ; get high byte of local ENVPTR
|
||||
OR A ; check if valid (<> zero)
|
||||
JP NZ,PRTNAME ; ..if so, display actual name
|
||||
; and let return from there
|
||||
CALL EPRINT ; else, display default
|
||||
DEFB 'SIZERAM' ; apparently wrong :-)
|
||||
DEFB 0
|
||||
RET
|
||||
|
||||
|
||||
; skip whitespace (<SP> or <TAB>)
|
||||
; in: HL= ptr to string
|
||||
; out: HL= ptr to first char <> whitespace
|
||||
SKPWHSP: DEC HL ; prior to loop, set ptr back
|
||||
SKPWH0: INC HL ; move ptr fwd
|
||||
LD A,(HL) ; get byte
|
||||
CP ' ' ; is it <SP> ?
|
||||
JR Z,SKPWH0 ; ..if so, loop
|
||||
CP TAB ; is it <TAB> ?
|
||||
JR Z,SKPWH0 ; ..if so, loop
|
||||
RET ; else, return
|
||||
|
||||
|
||||
; add A to HL (result in HL)
|
||||
ADDHLA: ADD A,L ; add L
|
||||
LD L,A ; store result in L
|
||||
RET NC ; ..if no overflow, return
|
||||
INC H ; else, increment H
|
||||
RET
|
||||
|
||||
|
||||
; the following routines rearrange Top of Stack by injecting an
|
||||
; intermediate return addr, and putting the Bios fn call on top
|
||||
; so that HL regs are preserved
|
||||
; order of steps:
|
||||
; [1] HL (= addr) is pushed onto stack
|
||||
; [2] intermediate return addr is swapped to Top of Stack
|
||||
; [3] HL (= addr) is pushed onto stack again
|
||||
; [4] Bios fn JP addr is swapped to Top of Stack
|
||||
; [5] Bios is "called" through RET, and returns to intermediate addr
|
||||
|
||||
; get byte from ram bank (in C) - in the form LD A,(HL)
|
||||
; in: HL= addr
|
||||
; out: A= byte
|
||||
GETFRB: PUSH BC
|
||||
PUSH HL ; save addr
|
||||
LD BC,(SYSBNK) ; C= System Bank, B= not used
|
||||
LD HL,GETFRB0 ; load return addr
|
||||
EX (SP),HL ; put it on stack
|
||||
PUSH HL ; save HL again (previous top of stack)
|
||||
LD HL,(BPADDR) ; get B/P Bios base addr
|
||||
LD L,35*3 ; adjust ptr to fn #35 (FRGETB)
|
||||
EX (SP),HL ; put addr on stack
|
||||
RET ; ..and "call" Bios fn through stack
|
||||
|
||||
GETFRB0: POP BC ; restore regs
|
||||
RET ; ..and finally return
|
||||
|
||||
; set byte in ram bank (in C) - in the form LD (HL),A
|
||||
; in: HL= addr, A= byte to set
|
||||
SETINB: PUSH BC
|
||||
PUSH HL ; save addr
|
||||
LD BC,(SYSBNK)
|
||||
LD HL,GETFRB0 ; load return addr
|
||||
EX (SP),HL ; put it on stack
|
||||
PUSH HL ; save HL again (previous top of stack)
|
||||
LD HL,(BPADDR) ; get B/P Bios base addr
|
||||
LD L,37*3 ; adjust ptr to fn #37 (FRPUTB)
|
||||
EX (SP),HL
|
||||
RET ; ..and "call" Bios fn through stack
|
||||
|
||||
|
||||
; "called" as a pseudo-routine that returns to caller
|
||||
; in: HL= target addr
|
||||
JUMPHL: JP (HL) ; jump to addr in HL regs
|
||||
|
||||
|
||||
;::::: RAM STORAGE (_no_ DSEG !)
|
||||
|
||||
PFLGADR: DEFW 0 ; addr of Prompt flag (last reserved option byte)
|
||||
SYSBNK: DEFB 0 ; beginning of System Bank(s)
|
||||
UNUSED1: DEFB 0 ; #####
|
||||
BPADDR: DEFW 0 ; base addr B/P Bios
|
||||
BPCNFG: DEFW 0 ; addr of B/P Bios CONFIG area
|
||||
BPBNKD: DEFB 0 ; indicator banked system
|
||||
; (bit 0 of OPTF1, 0= unbanked, 1= banked)
|
||||
|
||||
DEFS 30H ; room for stack
|
||||
STACK: DEFW 0 ; stack storage location
|
||||
|
||||
|
||||
END
|
||||
|
||||
|
||||
;:::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
; Z3LIB - 0x06b4
|
||||
; SYSLIB - 0x0762
|
||||
; end addr 0x080a (begin DSEG of LIB's)
|
||||
;:::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
|
||||
|
||||
;************************************************************************
|
||||
; Remarks jxl:
|
||||
; CONFZ4.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 CONFZ4.COM, i.e. no changes to the source were made. Possible
|
||||
; optimisations detected during disassembly are marked with "#####" in the
|
||||
; comment.
|
||||
; The program seems to be in an early stage as it does not comply with
|
||||
; general coding standards seen by HFB/CWC. For instance, no DSEG is used.
|
||||
; Only 2 options can be configured with this program. It is not known
|
||||
; whether provisions were made in ZCPR v4.1 for further options.
|
||||
;************************************************************************
|
||||
752
Source/BPBIOS/UTIL/hashini.z80
Normal file
752
Source/BPBIOS/UTIL/hashini.z80
Normal file
@@ -0,0 +1,752 @@
|
||||
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.
|
||||
;************************************************************************
|
||||
640
Source/BPBIOS/UTIL/ldsys.z80
Normal file
640
Source/BPBIOS/UTIL/ldsys.z80
Normal file
@@ -0,0 +1,640 @@
|
||||
TITLE "B/P Bios System Loader"
|
||||
;************************************************************************
|
||||
;* L D S Y S *
|
||||
;* Load a B/P Bios based system into RAM memory for direct execution *
|
||||
;* by Harold F. Bower and Cameron W. Cotrill *
|
||||
;*----------------------------------------------------------------------*
|
||||
;* Disassembly: jxl Dec 2024 *
|
||||
;* public release 1.0 Apr 2025 *
|
||||
;* see remarks at the end *
|
||||
;*----------------------------------------------------------------------*
|
||||
;* LINK with Version 4 libraries: VLIB, Z3LIB, SYSLIB *
|
||||
;* *
|
||||
;* A>Z80ASM LDSYS/RS *
|
||||
;* A>SLRNK LDSYS/N,/A:100,/D:0CF8,LDSYS,VLIBS/S,Z3LIBS/S,SYSLIBS/S,/E *
|
||||
;************************************************************************
|
||||
|
||||
VER EQU 12
|
||||
REV EQU ' '
|
||||
|
||||
DATE MACRO
|
||||
DEFB '17 Jul 96'
|
||||
ENDM
|
||||
|
||||
|
||||
BEL EQU 07H ; Bell character
|
||||
LF EQU 0AH ; Line Feed character
|
||||
CR EQU 0DH ; Carriage Return character
|
||||
|
||||
CPMBDOS EQU 5 ; CP/M BDOS entry point (JP)
|
||||
CPMFCB EQU 5CH ; CP/M standard FCB #1 (+1 filename, +9 filetype)
|
||||
CPMDMA EQU 80H ; CP/M standard DMA buffer
|
||||
|
||||
|
||||
; From VLIB Get..
|
||||
EXTRN VPRINT, Z3VINIT
|
||||
|
||||
; From Z3LIB Get..
|
||||
EXTRN GETNAME, PRTNAME, ZFNAME, Z3LOG, WHRENV
|
||||
EXTRN GZMTOP ; ##### not used, but linked
|
||||
|
||||
; From SYSLIB Get..
|
||||
EXTRN PUTUD, GETUD, F$OPEN, F$READ, SETDMA, PFN3, PHL4HC, COUT, CODEND
|
||||
EXTRN F$CLOSE, CRLF ; ##### not used, but linked
|
||||
|
||||
|
||||
;::::: PROGRAM START
|
||||
|
||||
ORG 100H
|
||||
CSEG
|
||||
|
||||
|
||||
LDSYS: JP START ; bypass header
|
||||
DEFB 'Z3ENV' ; this is a ZCPR3 utility
|
||||
DEFB 1 ; show external environment
|
||||
|
||||
ENVADR: DEFW 0 ; addr of Z3 environment
|
||||
DEFW LDSYS ; type 4 filler
|
||||
|
||||
DEFB 'LDSYS ',0 ; configuration name
|
||||
|
||||
FTYPE: DEFB 'IMG' ; standard file type
|
||||
|
||||
START: LD (STACK),SP
|
||||
LD SP,STACK
|
||||
CALL PUTUD ; currently logged drive/user
|
||||
LD HL,(CPMBDOS+1)
|
||||
CALL WHRENV ; find Z3 Environment Descriptor
|
||||
PUSH AF
|
||||
LD (ENVADR),HL ; store ENV addr
|
||||
CALL Z3VINIT ; ..and init for Z3LIB routines
|
||||
CALL GETNAME ; get actual program name
|
||||
CALL VPRINT
|
||||
DEFB CR,LF,1,'B/P Bios System Loader',2,' Vers ',VER/10+'0','.'
|
||||
DEFB VER MOD 10 + '0',REV,' '
|
||||
DATE
|
||||
DEFB CR,LF,' Copyright (C) 1991,3 by H.F.Bower & C.W.Cotrill',CR,LF
|
||||
DEFB 0
|
||||
|
||||
; get first token from command line (in FCB #1)
|
||||
LD A,(CPMFCB+1)
|
||||
CP '/' ; is this a help request ?
|
||||
JP Z,HELP ; ..if so, jump display help screen
|
||||
POP AF
|
||||
JR Z,E$NOFIL ; else, jump error no file specified
|
||||
|
||||
LD HL,(ENVADR) ; get addr Z3ENV
|
||||
LD DE,70 ; offset to high byte BIOS addr
|
||||
ADD HL,DE ; move ptr
|
||||
LD H,(HL) ; get high byte of B/P Bios page addr
|
||||
LD L,30*3 ; ..and set low byte to fn #30
|
||||
LD A,(HL) ; check byte at ptr location
|
||||
CP 0C3H ; is it opcode 0xC3 (JP) ?
|
||||
JR NZ,E$NOFIL ; ..if not, jump error and exit
|
||||
CALL JUMPHL ; else, "call" B/P Bios fn #30 (RETBIO)
|
||||
LD HL,-6 ; move ptr 6 bytes backward
|
||||
ADD HL,DE ; (signature string)
|
||||
LD A,(HL) ; get byte
|
||||
CP 'B' ; is it 'B' ?
|
||||
JR NZ,E$NOFIL ; ..if not, jump error and exit
|
||||
INC HL ; ptr fwd
|
||||
LD A,(HL) ; get byte
|
||||
CP '/' ; is it '/' ?
|
||||
JR NZ,E$NOFIL ; ..if not, jump error and exit
|
||||
INC HL ; ptr fwd
|
||||
LD A,(HL) ; get byte
|
||||
CP 'P' ; is it 'P' ?
|
||||
JR NZ,E$NOFIL ; ..if not, jump error and exit
|
||||
LD DE,6 ; else, set ptr to OPTF1 (Bios Option Flags)
|
||||
ADD HL,DE ; at CONFIG+2
|
||||
BIT 7,(HL) ; check bit 7 (0= not locked, 1= locked, can't reload)
|
||||
JR Z,E$NOFIL ; ..if not set, skip over
|
||||
|
||||
|
||||
E$RUNBP: CALL VPRINT
|
||||
DEFB CR,LF,BEL,'*** Running Bios Cannot be Replaced ! ***',CR,LF
|
||||
DEFB 0
|
||||
JP EXIT
|
||||
|
||||
E$NOFIL: LD A,(CPMFCB+1)
|
||||
CP ' '
|
||||
JR NZ,EVALCMD
|
||||
CALL VPRINT
|
||||
DEFB ' *** No file specified ! ***',CR,LF,BEL
|
||||
DEFB 0
|
||||
|
||||
|
||||
;::::: EXIT PROGRAM
|
||||
|
||||
EXIT: CALL GETUD ; set previous drive/user
|
||||
LD SP,(STACK) ; set stack to initial location
|
||||
RET ; ..and return to system
|
||||
|
||||
|
||||
;::::: EVALUATE COMMAND LINE
|
||||
|
||||
EVALCMD: LD DE,CPMFCB
|
||||
LD HL,CPMDMA+1 ; set ptr to start of string
|
||||
ECMD1: LD A,(HL) ; get char
|
||||
INC HL ; move ptr fwd
|
||||
CP ' ' ; is it <SP> ?
|
||||
JR Z,ECMD1 ; ..if so, loop get next char
|
||||
DEC HL ; non-blank char found, move ptr back
|
||||
XOR A ; and nullify A
|
||||
CALL ZFNAME ; parse token into FCB
|
||||
JP NZ,E$AMBIG ; filename must be unambiguous, jump if error
|
||||
LD HL,9 ; move ptr to file type
|
||||
ADD HL,DE
|
||||
LD A,(HL) ; get char
|
||||
CP ' ' ; is it <SP> ?
|
||||
JR NZ,RDIMG ; ..if not, skip over
|
||||
PUSH DE ; else, save regs
|
||||
EX DE,HL ; swap regs
|
||||
LD HL,FTYPE ; ptr to standard file type
|
||||
LD BC,3 ; 3 chars
|
||||
LDIR ; ... and copy
|
||||
POP DE ; restore ptr to ZCPR3 FCB
|
||||
|
||||
|
||||
;::::: READ IMAGE FILE
|
||||
|
||||
RDIMG: CALL Z3LOG ; log in drive/user
|
||||
CALL F$OPEN ; attempt to open file
|
||||
OR A
|
||||
JP NZ,E$OPEN ; ..if error, jump error and exit
|
||||
CALL CODEND ; get first available page after code end
|
||||
LD (WSPCBEG),HL ; ..and store it
|
||||
RDIMG0: PUSH HL
|
||||
CALL SETDMA ; set DMA buffer addr (HL)
|
||||
LD DE,CPMFCB ; set standard FCB #1
|
||||
CALL F$READ ; read one sector (128 bytes)
|
||||
POP HL ; restore start addr
|
||||
JR NZ,RDIMG1 ; ..if end of file, jump exit loop
|
||||
LD DE,128 ; else, move buffer addr forward
|
||||
ADD HL,DE
|
||||
JR RDIMG0 ; ..and loop
|
||||
RDIMG1: CALL GETUD ; set previously logged drive/user
|
||||
CALL VPRINT
|
||||
DEFB CR,LF,' CCP starts at : '
|
||||
DEFB 0
|
||||
|
||||
|
||||
;::::: READ IMAGE HEADER
|
||||
|
||||
; header contains information at following offsets:
|
||||
; ZCPR CCP 0x10 (16) filename
|
||||
; 0x1B (27) Unbanked base addr, 0x1D (29) Unbanked size
|
||||
; 0x1F (31) Banked base addr, 0x22 (33) Banked size
|
||||
; ZSDOS 0x30 (48) filename
|
||||
; 0x3B (59) Unbanked base addr, 0x3D (61) Unbanked size
|
||||
; 0x3F (63) Banked base addr, 0x41 (65) Banked size
|
||||
; B/P Bios 0x50 (80) filename
|
||||
; 0x5B (91) Unbanked base addr, 0x5D (93) Unbanked size
|
||||
; 0x5F (95) Banked base addr, 0x62 (98) Banked size
|
||||
; 0x70 (112) IMG filename
|
||||
|
||||
RDHDR: LD DE,27 ; offset CCP Unbanked base addr
|
||||
CALL PSEGAS ; display addr and size of segment
|
||||
LD DE,33 ; offset CCP Banked size
|
||||
CALL GBYTEWS ; check if empty (0x0000)
|
||||
JR Z,RDHDR0 ; ..if so, skip over
|
||||
CALL VPRINT
|
||||
DEFB ' Banked Ccp at : '
|
||||
DEFB 0
|
||||
LD DE,31 ; offset to CCP Banked base addr
|
||||
CALL PSEGAS ; display addr and size
|
||||
RDHDR0: CALL VPRINT
|
||||
DEFB ' DOS starts at : '
|
||||
DEFB 0
|
||||
LD DE,59 ; offset to DOS Unbanked base addr
|
||||
CALL PSEGAS ; display addr and size of segment
|
||||
LD DE,65 ; offset to DOS Banked size
|
||||
CALL GBYTEWS ; check if empty (0x0000)
|
||||
JR Z,RDHDR1 ; ..if so, skip over
|
||||
CALL VPRINT
|
||||
DEFB ' Banked Dos at : '
|
||||
DEFB 0
|
||||
LD DE,63 ; offset to DOS Banked base addr
|
||||
CALL PSEGAS ; display addr and size
|
||||
RDHDR1: CALL VPRINT
|
||||
DEFB ' BIOS starts at : '
|
||||
DEFB 0
|
||||
LD DE,91 ; offset to B/P Bios Unbanked base addr
|
||||
CALL PSEGAS ; display addr and size of segment
|
||||
LD DE,97 ; offset to B/P Bios Banked size
|
||||
CALL GBYTEWS ; check if empty (0x0000)
|
||||
JR Z,LDSEG ; ..if so, skip over
|
||||
CALL VPRINT
|
||||
DEFB ' Banked Bios at : '
|
||||
DEFB 0
|
||||
LD DE,95 ; offset to B/P Bios Banked base addr
|
||||
CALL PSEGAS ; display addr and size
|
||||
|
||||
|
||||
;::::: LOAD SYSTEM SEGMENTS
|
||||
|
||||
LDSEG: CALL VPRINT
|
||||
DEFB CR,LF,' ...installing '
|
||||
DEFB 0
|
||||
CALL CHKBNKD ; check options flag if banked system
|
||||
JR Z,LDSEG0 ; ..if not, skip over
|
||||
CALL VPRINT
|
||||
DEFB 'Banked '
|
||||
DEFB 0
|
||||
LDSEG0: CALL VPRINT
|
||||
DEFB 'System',CR,LF,LF
|
||||
DEFB 0
|
||||
|
||||
LDSEG1: DI ; disable interrupts
|
||||
LD HL,(WSPCBEG) ; get addr WSPC area
|
||||
LD DE,100H ; + 100H to account for file base
|
||||
ADD HL,DE
|
||||
|
||||
; ZCPR Unbanked portion
|
||||
LD (CCPUSTRT),HL ; store start in WSPC area
|
||||
LD DE,27 ; file offset to ZCPR Unbanked base addr
|
||||
CALL G2WRDWS
|
||||
LD (CCPUSIZ),BC ; store size
|
||||
LD (CCPUADR),DE ; store base addr
|
||||
LD HL,(CCPUSTRT) ; get start in WSPC
|
||||
PUSH HL
|
||||
ADD HL,BC ; calc end / start of ZSDOS Unbanked portion
|
||||
LD (DOSUSTRT),HL ; ..and store it
|
||||
POP HL ; restore start
|
||||
LDIR ; copy ZCPR Unbanked
|
||||
; from img file to target addr
|
||||
|
||||
; ZCPR Banked portion
|
||||
LD DE,31 ; offset to ZCPR Banked base addr
|
||||
CALL G2WRDWS
|
||||
LD (CCPBSIZ),BC ; store size
|
||||
LD (CCPBADR),DE ; store base addr
|
||||
LD HL,(DOSUSTRT) ; get previously calc'd end
|
||||
LD (CCPBSTRT),HL ; ..and store it as Banked start in WSPC
|
||||
LD A,B ; check if size is zero
|
||||
OR C
|
||||
JR Z,LDSEG2 ; ..if so, skip over
|
||||
ADD HL,BC ; else, calc new start of ZSDOS Unbanked
|
||||
LD (DOSUSTRT),HL ; ..and update it
|
||||
|
||||
; ZSDOS Unbanked portion
|
||||
LDSEG2: LD DE,59 ; offset to ZSDOS Unbanked base addr
|
||||
CALL G2WRDWS ; DE= base addr, BC= size
|
||||
LD (DOSUSIZ),BC ; store size
|
||||
LD HL,(DOSUSTRT) ; get ZSDOS Unbanked start in WSPC area
|
||||
PUSH HL
|
||||
ADD HL,BC ; calc end / start of B/P Bios Unbanked portion
|
||||
LD (BIOUSTRT),HL ; ..and store it
|
||||
POP HL ; restore start
|
||||
LDIR ; copy ZSDOS Unbanked
|
||||
; from img file to target addr
|
||||
|
||||
; ZSDOS Banked portion
|
||||
LD DE,63 ; offset to ZSDOS Banked base addr
|
||||
CALL G2WRDWS
|
||||
LD (DOSBSIZ),BC ; store size
|
||||
LD (DOSBADR),DE ; store base addr
|
||||
LD HL,(BIOUSTRT) ; get previously calc'd end
|
||||
LD (DOSBSTRT),HL ; ..and store it as Banked start in WSPC
|
||||
LD A,B ; check if size is zero
|
||||
OR C
|
||||
JR Z,LDSEG3 ; ..if so, skip over
|
||||
ADD HL,BC ; else, calc new start of B/P Bios Unbanked
|
||||
LD (BIOUSTRT),HL ; ..and update it
|
||||
|
||||
; B/P Bios Unbanked portion
|
||||
LDSEG3: LD DE,91 ; offset to B/P Bios Unbanked base addr
|
||||
CALL G2WRDWS
|
||||
LD (BIOUSIZ),BC ; store size
|
||||
LD (BIOUADR),DE ; store base addr
|
||||
LD HL,(BIOUSTRT) ; get start in WSPC area
|
||||
PUSH HL
|
||||
ADD HL,BC ; calc end / beginning of Banked portion
|
||||
LD (BIOBSTRT),HL ; ..and store it
|
||||
POP HL ; restore start
|
||||
LDIR ; copy B/P Bios Unbanked
|
||||
; from img file to target addr
|
||||
|
||||
; B/P Bios Banked portion
|
||||
LD DE,95 ; offset to B/P Bios Banked base addr
|
||||
CALL G2WRDWS
|
||||
LD (BIOBSIZ),BC ; store size
|
||||
LD (BIOBADR),DE ; store base addr
|
||||
|
||||
; use B/P Bios functions at new location (Unbanked portion was just loaded)
|
||||
LD HL,(BIOUADR) ; get (new) B/P Bios base addr
|
||||
LD L,82h ; offset to TPABNK in config area
|
||||
LD A,(HL) ; get value
|
||||
LD L,27*3 ; offset to B/P Bios fn #27 (SELMEM)
|
||||
CALL JUMPHL ; "call" fn
|
||||
LD HL,CCPBSIZ ; ptr to stored ZCPR Banked size
|
||||
CALL LDBNKD
|
||||
LD HL,DOSBSIZ ; ptr to stored ZSDOS Banked size
|
||||
CALL LDBNKD
|
||||
LD HL,BIOBSIZ ; ptr to stored B/P Bios Banked size
|
||||
CALL LDBNKD
|
||||
|
||||
; Z3ENV Descriptor
|
||||
LD BC,(WSPCBEG) ; get (new) B/P Bios base addr
|
||||
LD HL,155 ; offset to addr of Z3 Environment Descriptor
|
||||
ADD HL,BC ; in B/P Bios config area (CONFIG+26)
|
||||
LD E,(HL) ; get addr in DE
|
||||
INC HL
|
||||
LD D,(HL)
|
||||
LD HL,128 ; offset from start of WSPC area (img file)
|
||||
ADD HL,BC
|
||||
LD BC,128 ; bytes to copy
|
||||
LDIR
|
||||
|
||||
; boot new system
|
||||
LD SP,80H ; set stack pointer to default
|
||||
XOR A ; nullify A
|
||||
; ..and fall through, initiating a cold boot
|
||||
|
||||
|
||||
;::::: SUPPORT FUNCTIONS
|
||||
|
||||
; call B/P Bios function (at new base addr in RAM)
|
||||
; in: A= offset to JP (fn # *3)
|
||||
BIOSFN: LD HL,(BIOUADR) ; get (new) B/P Bios base addr
|
||||
LD L,A ; adjust to JP of fn #
|
||||
; ..and fall through
|
||||
|
||||
|
||||
; "called" as a pseudo-routine that returns to caller
|
||||
; in: HL= target addr
|
||||
JUMPHL: JP (HL) ; jump to addr in HL regs
|
||||
|
||||
|
||||
; load banked portions of (new) system from WSPC area to SYSBNK
|
||||
; segment information is stored as consecutive 16-bit words
|
||||
; in the order <size> <base addr> <start addr in WSPC>
|
||||
; in: HL= ptr to <size>
|
||||
; uses B/P Bios functions at new location (Unbanked portion)
|
||||
LDBNKD: LD C,(HL) ; get <size> low byte
|
||||
LD A,C
|
||||
INC HL ; move ptr fwd
|
||||
LD B,(HL) ; get <size> high byte
|
||||
INC HL ; ptr fwd
|
||||
OR B ; check if <size> is zero
|
||||
RET Z ; ..if so, return
|
||||
|
||||
PUSH BC ; save regs
|
||||
PUSH HL
|
||||
LD HL,(BIOUADR) ; get (new) B/P Bios base addr
|
||||
LD L,82H ; offset to TPABNK in config area
|
||||
LD C,(HL) ; get value
|
||||
INC HL ; move ptr to SYSBNK
|
||||
LD B,(HL) ; get value
|
||||
LD A,29*3 ; offset to B/P Bios fn #29 (XMOVE)
|
||||
CALL BIOSFN
|
||||
POP DE ; restore regs, DE now ptr to <base addr>
|
||||
POP BC
|
||||
LD HL,(BIOUADR) ; get (new) B/P Bios base addr
|
||||
LD L,25*3 ; offset to B/P Bios fn #25 (MOVE)
|
||||
PUSH HL ; put on stack, so it is called at return
|
||||
; and let Bios routine return to initial caller
|
||||
EX DE,HL ; swap regs
|
||||
LD E,(HL) ; get <base addr> in DE
|
||||
INC HL
|
||||
LD D,(HL)
|
||||
INC HL
|
||||
LD A,(HL)
|
||||
INC HL
|
||||
LD H,(HL) ; get <start addr in WSPC> in HL
|
||||
LD L,A
|
||||
RET ; ..and call B/P Bios fn #25 (MOVE)
|
||||
; to copy banked segment to SYSBNK
|
||||
|
||||
|
||||
; get _two_ consecutive 16-bit words from offset addr in WSPC area
|
||||
; in: DE= offset
|
||||
; out: DE= first value (at addr)
|
||||
; BC= second value (at addr+2)
|
||||
; HL= ptr to high byte of second value in WSPC area
|
||||
; uses BC, DE, HL
|
||||
G2WRDWS: CALL G1WRDWS ; get first word in HL
|
||||
EX DE,HL ; swap regs
|
||||
INC HL ; move ptr fwd
|
||||
LD C,(HL) ; get second word in BC
|
||||
INC HL
|
||||
LD B,(HL)
|
||||
RET
|
||||
|
||||
|
||||
; print base addr and size of system segment ton CON:
|
||||
; in: DE= offset in WSPC area
|
||||
PSEGAS: CALL G1WRDWS ; get 16-bit word (in HL) at offset (in DE)
|
||||
CALL PHL4HC ; ..and print to CON: as hex digits
|
||||
EX DE,HL ; swap regs
|
||||
INC HL ; move ptr fwd
|
||||
LD E,(HL) ; get next 16-bit word in DE
|
||||
INC HL
|
||||
LD D,(HL)
|
||||
CALL VPRINT
|
||||
DEFB ' ('
|
||||
DEFB 0
|
||||
EX DE,HL ; swap regs
|
||||
CALL PHL4HC ; print value (now in HL) to CON: as hex digits
|
||||
CALL VPRINT
|
||||
DEFB 'H Bytes)',CR,LF
|
||||
DEFB 0
|
||||
RET
|
||||
|
||||
|
||||
; get _one_ 16-bit word from offset addr in WSPC area
|
||||
; in: DE= offset
|
||||
; out: HL= value
|
||||
; DE= ptr to high byte in WSPC area
|
||||
G1WRDWS: LD HL,(WSPCBEG) ; addr WSPC area
|
||||
ADD HL,DE ; add offset
|
||||
LD E,(HL) ; get low byte at ptr addr in E
|
||||
INC HL
|
||||
LD D,(HL) ; get high byte at ptr addr in D
|
||||
EX DE,HL ; swap regs
|
||||
RET
|
||||
|
||||
|
||||
; get byte from offset addr in WSPC area
|
||||
; in: DE= offset
|
||||
; out: A= value, Z-Flag set if following byte is eqal
|
||||
; HL= ptr to next byte in WSPC area
|
||||
GBYTEWS: LD HL,(WSPCBEG) ; addr WSPC area
|
||||
ADD HL,DE ; add offset
|
||||
LD A,(HL) ; get byte
|
||||
INC HL ; move ptr fwd
|
||||
OR (HL) ; check if next byte has same value
|
||||
RET
|
||||
|
||||
|
||||
; check if img file contains a banked system
|
||||
; in: -
|
||||
; out: Z-Flag set for Unbanked Bios, NZ= Banked
|
||||
CHKBNKD: LD HL,(WSPCBEG) ; addr WSPC area
|
||||
INC H ; + 100H to account for file base
|
||||
EX DE,HL ; swap regs, DE holds result over next calc's
|
||||
LD BC,29 ; offset to ZCPR Unbanked size
|
||||
CALL SEGTSIZ ; ..add ZCPR size(s) to DE
|
||||
LD BC,61 ; offset to ZSDOS Unbanked size
|
||||
CALL SEGTSIZ ; ..add ZSDOS size(s) to DE
|
||||
LD HL,128 ; DE= offset to beginning of B/P Bios in
|
||||
ADD HL,DE ; img file, move fwd by 128 more bytes
|
||||
LD A,(HL) ; get B/P Bios options flag OPTF1 (at CONFIG+2)
|
||||
AND 00000001b ; check bit 0, and set Z-Flag accordingly
|
||||
RET
|
||||
|
||||
|
||||
; get total size of a system segment (add Unbanked and Banked sizes)
|
||||
; in: BC= offset in WSPC area to Unbanked size
|
||||
; out: DE= sum of segment sizes
|
||||
SEGTSIZ: LD HL,(WSPCBEG) ; addr WSPC area
|
||||
ADD HL,BC ; add offset
|
||||
LD C,(HL) ; get 16-bit word in BC
|
||||
INC HL ; (Unbanked size)
|
||||
LD B,(HL)
|
||||
EX DE,HL ; swap regs
|
||||
ADD HL,BC ; add retrieved value
|
||||
EX DE,HL ; ..and swap regs back
|
||||
INC HL ; move ptr 3 bytes fwd
|
||||
INC HL
|
||||
INC HL
|
||||
LD C,(HL) ; get 16-bit value in BC
|
||||
INC HL ; (Banked size)
|
||||
LD B,(HL)
|
||||
EX DE,HL ; swap regs
|
||||
ADD HL,BC ; add retrieved value
|
||||
EX DE,HL ; ..and swap regs back
|
||||
RET
|
||||
|
||||
|
||||
;::::: ERROR MESSAGES
|
||||
|
||||
E$AMBIG: CALL VPRINT
|
||||
DEFB CR,LF,BEL,' --- Ambiguous File: '
|
||||
DEFB 0
|
||||
JR E$FNAME
|
||||
|
||||
E$OPEN: CALL VPRINT
|
||||
DEFB CR,LF,BEL,' --- Error Opening: '
|
||||
DEFB 0
|
||||
|
||||
E$FNAME: LD DE,CPMFCB+1 ; ptr to file name in standard FCB #1
|
||||
CALL PFN3 ; print it
|
||||
JP EXIT
|
||||
|
||||
|
||||
;::::: HELP SCREEN
|
||||
|
||||
HELP: CALL VPRINT
|
||||
DEFB CR,LF,1
|
||||
DEFB 0
|
||||
CALL PPRGNAM
|
||||
CALL VPRINT
|
||||
DEFB 2,' Loads and executes a System image prepared by',CR,LF
|
||||
DEFB ' BPBUILD containing a B/P Bios.',CR,LF,LF
|
||||
DEFB ' Syntax:',CR,LF
|
||||
DEFB ' '
|
||||
DEFB 0
|
||||
CALL PPRGNAM
|
||||
CALL VPRINT
|
||||
DEFB ' // - print this message',CR,LF
|
||||
DEFB ' '
|
||||
DEFB 0
|
||||
CALL PPRGNAM
|
||||
CALL VPRINT
|
||||
DEFB ' [du|dir:]name[.typ] - load system image',CR,LF,LF
|
||||
DEFB ' File Type Defaults to "'
|
||||
DEFB 0
|
||||
LD HL,FTYPE ; ptr to default file type
|
||||
LD B,3 ; # of chars
|
||||
HELP0: LD A,(HL) ; get char
|
||||
INC HL ; move ptr fwd
|
||||
CALL COUT ; display char on CON:
|
||||
DJNZ HELP0 ; ..and loop
|
||||
CALL VPRINT
|
||||
DEFB '" if not explicitly entered',CR,LF,LF
|
||||
DEFB 'NOTE: This utility will NOT load a system '
|
||||
DEFB 'if the "Lock" bit in',CR,LF
|
||||
DEFB 'the Option Byte (Bit 7 of CONFIG+2) is Set to "1"',CR,LF
|
||||
DEFB 0
|
||||
JP EXIT
|
||||
|
||||
|
||||
; print program name on CON: device
|
||||
; (either the actual name, or fallback to default)
|
||||
; only used by HELP
|
||||
PPRGNAM: LD A,(ENVADR+1) ; get high byte of ENVPTR
|
||||
OR A ; check if valid (<> zero)
|
||||
JP NZ,PRTNAME ; ..if so, display actual name
|
||||
; and let return from there
|
||||
CALL VPRINT ; else, display default
|
||||
DEFB 'LDSYS'
|
||||
DEFB 0
|
||||
RET
|
||||
|
||||
|
||||
;:::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
; VLIB - 0x06db
|
||||
; Z3LIB - 0x08fc
|
||||
; SYSLIB - 0x0bcf
|
||||
; end addr 0x0bf8 (begin DSEG)
|
||||
;:::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
|
||||
|
||||
;::::: RAM STORAGE
|
||||
|
||||
DSEG
|
||||
|
||||
WSPCBEG: DEFW 0 ; begin of workspace
|
||||
; (first available page, returned by CODEND)
|
||||
|
||||
; addresses of new system as extracted from img file
|
||||
; first _Unbanked_, then _Banked_
|
||||
BIOUADR: DEFW 0 ; B/P Bios Unbanked base addr
|
||||
CCPUADR: DEFW 0 ; ZCPR Unbanked base addr
|
||||
CCPUSTRT: DEFW 0 ; start in WSPC area
|
||||
CCPUSIZ: DEFW 0 ; size
|
||||
DOSUSTRT: DEFW 0 ; ZSDOS Unbanked start
|
||||
DOSUSIZ: DEFW 0 ; size
|
||||
BIOUSTRT: DEFW 0 ; B/P Bios Unbanked start
|
||||
BIOUSIZ: DEFW 0 ; size
|
||||
|
||||
CCPBSIZ: DEFW 0 ; ZCPR Banked size
|
||||
CCPBADR: DEFW 0 ; base addr
|
||||
CCPBSTRT: DEFW 0 ; start
|
||||
DOSBSIZ: DEFW 0 ; ZSDOS Banked size
|
||||
DOSBADR: DEFW 0 ; base addr
|
||||
DOSBSTRT: DEFW 0 ; start
|
||||
BIOBSIZ: DEFW 0 ; B/P Bios Banked size
|
||||
BIOBADR: DEFW 0 ; base addr
|
||||
BIOBSTRT: DEFW 0 ; start
|
||||
|
||||
|
||||
DEFW GZMTOP ; reference Z3LIB/SYSLIB routines, so they are linked
|
||||
DEFW F$CLOSE
|
||||
DEFW CRLF
|
||||
|
||||
DEFS 30H-6 ; room for stack
|
||||
; -6 to account for above ref's
|
||||
STACK: DEFW 0 ; stack storage location
|
||||
|
||||
END
|
||||
|
||||
|
||||
;************************************************************************
|
||||
; Remarks jxl:
|
||||
; LDSYS.COM, included in available B/P Bios package(s), was dis-
|
||||
; assembled and extensively commented. Labels are unique up to the seventh
|
||||
; character 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 _almost_ matches the
|
||||
; original LDSYS.COM with the exception of Z3LIB routine GZMTOP, and
|
||||
; SYSLIB routines F$CLOSE and CRLF. Even though they are part of the
|
||||
; original program, they are neither needed nor referenced. This seems
|
||||
; to indicate that other versions of the LIB's were used. To reproduce
|
||||
; the original program, the above mentioned routines are referenced (in
|
||||
; stack area) to have them included when linking.
|
||||
;
|
||||
; As a byproduct of the disassembly, the structure of a B/P Bios image
|
||||
; file was documented. This file contains an excerpt.
|
||||
;************************************************************************
|
||||
409
Source/BPBIOS/UTIL/showhd.z80
Normal file
409
Source/BPBIOS/UTIL/showhd.z80
Normal file
@@ -0,0 +1,409 @@
|
||||
TITLE "B/P Bios HD drive partition display"
|
||||
;************************************************************************
|
||||
;* S H O W H D *
|
||||
;* Display DPH and DPB data for making B/P HD Partition data the same *
|
||||
;* by Harold F. Bower and Cameron W. Cotrill *
|
||||
;*----------------------------------------------------------------------*
|
||||
;* Disassembly: jxl Jan 2025 *
|
||||
;* public release 1.0 Apr 2025 *
|
||||
;* see remarks at the end *
|
||||
;*----------------------------------------------------------------------*
|
||||
;* LINK with Version 4 libraries: SYSLIB *
|
||||
;* *
|
||||
;* A>Z80ASM SHOWHD/RS *
|
||||
;* A>SLRNK SHOWHD/N,/A:100,/D:064D,SHOWHD,SYSLIBS/S,/E *
|
||||
;************************************************************************
|
||||
|
||||
VER EQU 10
|
||||
REV EQU ' '
|
||||
|
||||
DATE MACRO
|
||||
DEFB '2 Nov 91'
|
||||
ENDM
|
||||
|
||||
|
||||
CTRLC EQU 03H ; Control-C character
|
||||
BEL EQU 07H ; Bell 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)
|
||||
CPMFCB EQU 5CH ; CP/M standard FCB #1 (+1 filename, +9 filetype)
|
||||
|
||||
|
||||
; For SYSLIB make visible...
|
||||
PUBLIC COUT
|
||||
|
||||
; From SYSLIB Get..
|
||||
EXTRN EPRINT, BOUT, CAPINE, PAFDC, PHLFDC, PA2HC
|
||||
|
||||
|
||||
;::::: PROGRAM START
|
||||
|
||||
ORG 100H
|
||||
CSEG
|
||||
|
||||
|
||||
SHOWHD: JP START ; bypass header
|
||||
DEFB 'Z3ENV' ; this is (not really) a Z3CPR utility
|
||||
DEFB 1 ; show external environment
|
||||
|
||||
ENVADR: DEFW 0 ; addr of Z3 environment
|
||||
|
||||
START: LD (STACK),SP
|
||||
LD SP,STACK
|
||||
CALL EPRINT
|
||||
DEFB CR,LF,'Show Hard Drive Partition Data - '
|
||||
DATE
|
||||
DEFB CR,LF
|
||||
DEFB 0
|
||||
|
||||
LD A,(CPMFCB+1) ; check first char of cmdline
|
||||
CP '/' ; is this a help request ?
|
||||
JP Z,HELP ; ..if so, jump
|
||||
|
||||
START0: CALL EPRINT
|
||||
DEFB CR,LF,'Enter Drive Letter [A..P] : '
|
||||
DEFB 0
|
||||
CALL CAPINE ; get user input
|
||||
CP CTRLC ; is it <Ctrl-C> ?
|
||||
JP Z,0 ; ..abort
|
||||
CP ESC ; is it <ESC> ?
|
||||
JP Z,0 ; ..abort
|
||||
CP 'A' ; below ascii 'A' ?
|
||||
JR C,START0 ; ..if so, loop ask for new input
|
||||
CP 'P'+1 ; greater than ascii 'P' ?
|
||||
JR NC,START0 ; ..if so, loop ask for new input
|
||||
LD (DRLTR),A ; store drive letter
|
||||
|
||||
CALL EPRINT
|
||||
DEFB CR,LF,LF,'Drive: '
|
||||
DEFB 0
|
||||
CALL COUT ; display drive
|
||||
CALL EPRINT
|
||||
DEFB CR,LF,TAB,'DPH Info',TAB,TAB,'BPCNFG Info',CR,LF
|
||||
DEFB 0
|
||||
|
||||
CALL GDPHADR ; get DPH addr for selected Disk drive
|
||||
LD (DPHADR),HL ; ..and store it
|
||||
LD A,H ; check if invalid (= zero)
|
||||
OR L
|
||||
JR NZ,PDSKDAT ; ..if not, skip over
|
||||
CALL EPRINT
|
||||
DEFB CR,LF,BEL,'+++ Invalid Drive : '
|
||||
DEFB 0
|
||||
LD A,(DRLTR) ; get drive letter
|
||||
CALL COUT ; ..and display it
|
||||
JP START0 ; then loop to ask for new input
|
||||
|
||||
|
||||
;::::: DISPLAY DISK DRIVE DATA
|
||||
|
||||
PDSKDAT: LD DE,10 ; offset in DPH to DPB addr
|
||||
ADD HL,DE
|
||||
LD E,(HL) ; DPB addr in DE
|
||||
INC HL
|
||||
LD D,(HL)
|
||||
EX DE,HL ; swap regs
|
||||
LD (DPBADR),HL ; ..and store DPB addr
|
||||
CALL EPRINT
|
||||
DEFB CR,LF,LF,' Sectors/Track = '
|
||||
DEFB 0
|
||||
LD E,(HL) ; get Sect/Trk from DPB in DE
|
||||
INC HL
|
||||
LD D,(HL)
|
||||
INC HL
|
||||
EX DE,HL ; swap regs
|
||||
CALL PHLFDC ; ..and display (as decimal)
|
||||
SRL H ; divide by 2
|
||||
RR L
|
||||
SRL H ; .. /4
|
||||
RR L
|
||||
SRL H ; .. /8
|
||||
RR L
|
||||
LD (KBTRK),HL ; store kByte/Trk
|
||||
EX DE,HL ; swap regs
|
||||
CALL P2TAB
|
||||
CALL EPRINT
|
||||
DEFB '(same)',CR,LF,' Blk Shift Fctr = '
|
||||
DEFB 0
|
||||
LD A,(HL) ; get next byte from DPB (= BSH, Block Shift Factor)
|
||||
INC HL ; move ptr fwd
|
||||
CALL PAFDC ; display BSH
|
||||
CALL P2TAB
|
||||
SUB 3 ; BSH -3
|
||||
LD B,A ; use as counter for multiplication
|
||||
LD (BSH3),A ; ..and also store it
|
||||
LD A,1 ; set initial value
|
||||
JR Z,PBLKSIZ ; if BSH -3 = 0, skip over
|
||||
|
||||
BLKSZLP: ADD A,A ; *2
|
||||
DJNZ BLKSZLP ; loop
|
||||
|
||||
PBLKSIZ: CALL PAFDC ; display block size
|
||||
; (BSH= 3 -> 1k, 4 -> 2k, ... 8 -> 32k)
|
||||
CALL EPRINT
|
||||
DEFB 'k/Block',CR,LF,' Block Mask = '
|
||||
DEFB 0
|
||||
LD A,(HL) ; next byte from DPB (= BSM, Block Mask)
|
||||
INC HL
|
||||
CALL PAFDC ; ..display it
|
||||
CALL EPRINT
|
||||
DEFB CR,LF,' Extent Mask = '
|
||||
DEFB 0
|
||||
LD A,(HL) ; next byte from DPB (= EXM, Extent Mask)
|
||||
INC HL
|
||||
CALL PAFDC ; ..display it
|
||||
CALL EPRINT
|
||||
DEFB CR,LF,' Disk Blocks-1 = '
|
||||
DEFB 0
|
||||
LD E,(HL) ; next 16-bit value from DPB in DE
|
||||
INC HL ; (= Disk Size in BLS units -1)
|
||||
LD D,(HL)
|
||||
INC HL
|
||||
EX DE,HL ; swap regs
|
||||
CALL PHLFDC ; display value
|
||||
CALL P2TAB
|
||||
INC HL ; +1 (= Disk Size)
|
||||
LD A,(BSH3) ; get BSH-3
|
||||
LD B,A ; set as initial loop counter
|
||||
OR A ; check if zero (means single density 1k/block)
|
||||
LD A,0 ; nullify A
|
||||
JR Z,PDSKCAP ; ..if already zero, no more calc needed
|
||||
|
||||
DSKCLP: ADD HL,HL ; double HL (2, 4, 8 etc. k/block)
|
||||
ADC A,0 ; a power-of-two multiple
|
||||
DJNZ DSKCLP ; ..and loop
|
||||
LD (DCAPH),A ; store disk capacity in kByte
|
||||
LD (DCAPML),HL ; as 24-bit value
|
||||
|
||||
PDSKCAP: CALL PDSKSZ ; ..and display it
|
||||
CALL EPRINT
|
||||
DEFB 'k Total ('
|
||||
DEFB 0
|
||||
PUSH DE
|
||||
LD DE,(KBTRK) ; kByte/Trk
|
||||
LD HL,(DCAPML) ; disk capacity in kByte
|
||||
LD A,(DCAPH)
|
||||
LD BC,-1 ; set initial counter value
|
||||
OR A
|
||||
|
||||
DSKTRLP: INC BC ; increase counter (quotient)
|
||||
SBC HL,DE ; divide by subtraction
|
||||
SBC A,0 ; check for underflow
|
||||
JR NC,DSKTRLP ; ..and loop while more to go
|
||||
|
||||
LD H,B ; result in HL
|
||||
LD L,C
|
||||
CALL PHLFDC ; ..display it
|
||||
CALL EPRINT
|
||||
DEFB ' Tracks)'
|
||||
DEFB 0
|
||||
POP DE ; restore DPB ptr
|
||||
EX DE,HL ; swap to HL
|
||||
CALL EPRINT
|
||||
DEFB CR,LF,' Max Dirs - 1 = '
|
||||
DEFB 0
|
||||
LD E,(HL) ; get next 16-bit value from DPB in DE
|
||||
INC HL ; (= Dir Max -1)
|
||||
LD D,(HL)
|
||||
INC HL
|
||||
EX DE,HL ; swap regs
|
||||
CALL PHLFDC ; ..and display value
|
||||
CALL P2TAB
|
||||
INC HL ; +1 (= Dir Max)
|
||||
CALL PHLFDC ; ..and display, too
|
||||
EX DE,HL
|
||||
CALL EPRINT
|
||||
DEFB ' Dir Entries',CR,LF,' Alloc bytes = '
|
||||
DEFB 0
|
||||
LD A,(HL) ; next byte from DPB (= AL0, Allocation byte 0)
|
||||
INC HL
|
||||
LD D,(HL) ; (= AL1, Allocation byte 1)
|
||||
INC HL
|
||||
CALL PA2HC ; display AL0 as hex
|
||||
CALL EPRINT
|
||||
DEFB 'H, '
|
||||
DEFB 0
|
||||
LD A,D ; AL1 in A
|
||||
CALL PA2HC ; ..and display as hex
|
||||
CALL EPRINT
|
||||
DEFB 'H',CR,LF,' Check Size = '
|
||||
DEFB 0
|
||||
LD E,(HL) ; next 16-bit value from DPB in DE
|
||||
INC HL ; (= CKS, Check Size)
|
||||
LD D,(HL)
|
||||
INC HL
|
||||
EX DE,HL ; swap regs
|
||||
CALL PHLFDC ; display value
|
||||
EX DE,HL ; swap regs back
|
||||
CALL EPRINT
|
||||
DEFB CR,LF,' Track Offset = '
|
||||
DEFB 0
|
||||
LD E,(HL) ; next 16-bit value from DPB in DE
|
||||
INC HL ; (= Track Offset)
|
||||
LD D,(HL)
|
||||
INC HL
|
||||
EX DE,HL ; swap regs
|
||||
CALL PHLFDC ; display value
|
||||
EX DE,HL ; swap regs back
|
||||
CALL P2TAB
|
||||
CALL EPRINT
|
||||
DEFB '(same)',CR,LF
|
||||
DEFB 0
|
||||
JP 0 ; and exit with Warm Boot
|
||||
|
||||
|
||||
; print 2 tabs on CON:
|
||||
P2TAB: PUSH AF
|
||||
LD A,TAB ; <TAB> in A
|
||||
CALL COUT ; display on CON:
|
||||
CALL COUT ; 2x
|
||||
POP AF ; restore
|
||||
RET
|
||||
|
||||
|
||||
;::::: HELP
|
||||
|
||||
HELP
|
||||
CALL EPRINT
|
||||
DEFB CR,LF,'SHOWHD - Display DPH and DPB data for '
|
||||
DEFB 'specified drive for making B/P',CR,LF
|
||||
DEFB ' Hard Drive Partition data the same as '
|
||||
DEFB 'an operating system.',CR,LF,LF
|
||||
DEFB ' Syntax:',CR,LF,LF
|
||||
DEFB TAB,'SHOWHD <-- Execute program interactively',CR,LF
|
||||
DEFB TAB,'SHOWHD // <-- Display this message',CR,LF
|
||||
DEFB 0
|
||||
LD SP,(STACK)
|
||||
RET
|
||||
|
||||
|
||||
;::::: SUPPORT FUNCTIONS
|
||||
|
||||
; get addr of Disk Parameter Header (DPH)
|
||||
; in: Disk drive letter in mem variable
|
||||
; out: HL= addr DPH
|
||||
GDPHADR: LD HL,(CPMBIOS+1) ; addr Bios fn #1 (WBOOT)
|
||||
LD L,9*3 ; adjust ptr to fn #9 (SELDSK)
|
||||
LD A,(DRLTR) ; get drive letter
|
||||
SUB 'A' ; ..and convert to number
|
||||
LD C,A ; copy to reg. C (for Bios call)
|
||||
LD E,0
|
||||
JP (HL) ; "call" Bios fn #9 and let return from there
|
||||
; (SELDSK returns DPH addr in HL)
|
||||
|
||||
|
||||
; print disk size to CON: (capacity of a drive in kB)
|
||||
; output as decimal with provision for 3-byte values - see ZXD21.Z80 PRBIG
|
||||
; in: 24-bit value to print in A,H,L
|
||||
PDSKSZ: PUSH DE ; save regs
|
||||
PUSH BC
|
||||
EX AF,AF' ; swap AF
|
||||
PUSH AF ; save it
|
||||
EX AF,AF' ; ..and swap back
|
||||
LD B,0
|
||||
LD C,-1 ; set initial result
|
||||
LD DE,86A0H ; 100,000 = 0x0186A0, set lower 2 bytes
|
||||
OR A ; clear C-Flag
|
||||
PDSKSZ0: INC C ; accumulate count
|
||||
SBC HL,DE ; subtract lower 2 bytes
|
||||
SBC A,1 ; ..and upper byte
|
||||
JR NC,PDSKSZ0 ; loop till done
|
||||
ADD HL,DE ; adjust underflow
|
||||
ADC A,1
|
||||
CALL PHLD1
|
||||
LD DE,10000 ; print 10000's
|
||||
CALL PHLD
|
||||
LD DE,1000 ; print 1000's
|
||||
CALL PHLD
|
||||
LD DE,100 ; print 100's
|
||||
CALL PHLD
|
||||
LD DE,10 ; print 10's
|
||||
CALL PHLD
|
||||
LD A,L ; print 1's
|
||||
CALL PHLD2
|
||||
POP AF ; restore regs
|
||||
EX AF,AF' ; swap
|
||||
POP BC ; ..and also restore other regs
|
||||
POP DE
|
||||
RET
|
||||
|
||||
|
||||
; print content of HL to CON: as decimal
|
||||
; divide HL by DE, convert remainder to ascii digit and print it
|
||||
; (similar to SYSLIB's PHLFDC/PHDC1 - see ZXD21.Z80 DECDSP)
|
||||
; in: HL= value, DE= divisor
|
||||
PHLD: LD C,-1 ; set initial count
|
||||
OR A ; clear C-Flag
|
||||
PHLD0: INC C ; accumulate count
|
||||
SBC HL,DE ; divide by subtraction
|
||||
SBC A,0
|
||||
JR NC,PHLD0 ; ..and loop while more to go
|
||||
ADD HL,DE ; compensate underflow
|
||||
ADC A,0
|
||||
PHLD1: EX AF,AF' ; swap to retain flags
|
||||
LD A,C ; get result (quotient)
|
||||
OR A ; is it zero ?
|
||||
JR NZ,PHLD2 ; ..if not, skip over
|
||||
OR B ; get prior digit print flag
|
||||
JR Z,PHLD3 ; ..if anything printed yet, jump
|
||||
XOR A ; else, print a zero
|
||||
PHLD2: ADD A,'0' ; convert to ascii
|
||||
LD B,A ; remember for next loop
|
||||
CALL COUT ; ..and display it
|
||||
PHLD3: EX AF,AF' ; swap regs back
|
||||
RET
|
||||
|
||||
|
||||
; intercept COUT to re-route SYSLIB calls to to BOUT
|
||||
; --> declare COUT as PUBLIC, and do _not_ import from SYSLIB
|
||||
COUT: JP BOUT
|
||||
|
||||
|
||||
;:::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
; SYSLIB - 0x0530
|
||||
; end addr 0x064d (begin DSEG)
|
||||
;:::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
|
||||
|
||||
;::::: RAM STORAGE
|
||||
|
||||
DSEG
|
||||
|
||||
KBTRK: DEFW 0 ; kByte/Trk (Sect/Trk divided by 8)
|
||||
BSH3: DEFB 0 ; BSH -3 (Block Shift Factor -3)
|
||||
|
||||
; disk capacity as 24-bit value
|
||||
DCAPH: DEFB 0 ; high byte
|
||||
DCAPML: DEFW 0 ; middle and low byte
|
||||
|
||||
DRLTR: DEFB 0 ; drive letter (entered by user)
|
||||
DPHADR: DEFW 0 ; addr DPH (not used)
|
||||
DPBADR: DEFW 0 ; addr DPB (not used)
|
||||
|
||||
DEFS 30H ; room for stack
|
||||
STACK: DEFW 0 ; stack storage location
|
||||
|
||||
END
|
||||
|
||||
|
||||
;************************************************************************
|
||||
; Remarks jxl:
|
||||
; SHOWHD.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.
|
||||
;
|
||||
; The program is not very complex. However, one thing might be worth
|
||||
; to be pointed out: SYSLIB's routine COUT is replaced with an own
|
||||
; implementation. While it is just a re-routing to another SYSLIB routine,
|
||||
; it shows how simply this can be achieved. Bear in mind that _all_
|
||||
; SYSLIB routines calling COUT would now call the local implementation
|
||||
; instead. With this technique existing routines can be modified without
|
||||
; rewriting them entirely.
|
||||
;************************************************************************
|
||||
546
Source/BPBIOS/UTIL/sizeram.z80
Normal file
546
Source/BPBIOS/UTIL/sizeram.z80
Normal file
@@ -0,0 +1,546 @@
|
||||
TITLE "B/P Bios RAM size display"
|
||||
;************************************************************************
|
||||
;* S I Z E R A M *
|
||||
;* Determine size and location of (banked) Memory *
|
||||
;* by Harold F. Bower and Cameron W. Cotrill *
|
||||
;*----------------------------------------------------------------------*
|
||||
;* Disassembly: jxl Dec 2024 *
|
||||
;* public release 1.0 Apr 2025 *
|
||||
;* see remarks at the end *
|
||||
;*----------------------------------------------------------------------*
|
||||
;* LINK with Version 4 libraries: VLIB, Z3LIB, SYSLIB *
|
||||
;* *
|
||||
;* A>Z80ASM SIZERAM/RS *
|
||||
;* A>SLRNK SIZERAM/N,/A:100,/D:0750,SIZERAM,VLIBS/S,Z3LIBS/S,SYSLIBS/S,/E *
|
||||
;************************************************************************
|
||||
|
||||
VER EQU 12
|
||||
REV EQU ' '
|
||||
|
||||
DATE MACRO
|
||||
DEFB '30 Aug 01'
|
||||
ENDM
|
||||
|
||||
|
||||
BEL EQU 07H ; Bell character
|
||||
LF EQU 0AH ; Line Feed character
|
||||
CR EQU 0DH ; Carriage Return 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)
|
||||
|
||||
|
||||
; From Z3LIB Get..
|
||||
EXTRN GETNAME, PRTNAME, Z3INIT, WHRENV
|
||||
|
||||
; From SYSLIB Get..
|
||||
EXTRN EPRINT, CRLF, PAFDC, PHLFDC, COUT, CODEND
|
||||
|
||||
|
||||
;::::: PROGRAM START
|
||||
|
||||
ORG 100H
|
||||
CSEG
|
||||
|
||||
|
||||
SIZERAM: JP START ; bypass header
|
||||
DEFB 'Z3ENV' ; this is a ZCPR3 utility
|
||||
DEFB 1 ; show external environment
|
||||
|
||||
ENVADR: DEFW 0 ; addr of Z3 environment
|
||||
DEFW SIZERAM ; type 4 filler
|
||||
|
||||
DEFB 'SIZERAM ',0 ; configuration name
|
||||
|
||||
START: LD (STACK),SP
|
||||
LD SP,STACK
|
||||
CALL EPRINT
|
||||
DEFB 'B/P Banked RAM Sizing Utility V',VER/10+'0','.'
|
||||
DEFB VER MOD 10 + '0',REV,' '
|
||||
DATE
|
||||
DEFB CR,LF
|
||||
DEFB 0
|
||||
CALL CHKZ3E ; check if Z3 Environment is valid
|
||||
CALL GETNAME ; get actual program name
|
||||
CALL CHKHELP ; check cmdline for help request
|
||||
CALL CHKSYS ; check if running under B/P Bios
|
||||
CALL M$BVER ; display version # msg
|
||||
LD HL,(BPCNFG) ; get addr of config area
|
||||
INC HL ; move ptr fwd
|
||||
INC HL
|
||||
LD A,(HL) ; get OPTF1 (option flag at CONFIG+2)
|
||||
AND 00000001b ; mask bit 0
|
||||
LD (BPBNKD),A ; ..and store it
|
||||
JP NZ,BNKDSYS ; if banked, jump to continue
|
||||
|
||||
|
||||
;::::: NON-BANKED SYSTEM
|
||||
|
||||
NBNKSYS: INC HL ; move ptr to TPABNK in config area
|
||||
INC HL
|
||||
CALL EPRINT
|
||||
DEFB CR,LF,LF,'Non-Banked System using TPA Banks = '
|
||||
DEFB 0
|
||||
LD A,(HL) ; get value
|
||||
PUSH AF
|
||||
CALL PAFDC ; ..and display
|
||||
LD A,'/'
|
||||
CALL COUT
|
||||
POP AF ; restore value
|
||||
INC A ; increase it
|
||||
CALL PAFDC ; ..and display
|
||||
CALL CRLF
|
||||
JP EXIT
|
||||
|
||||
|
||||
;::::: BANKED SYSTEM
|
||||
|
||||
BNKDSYS: INC HL ; move ptr to UABNK in config area
|
||||
LD DE,UABNK ; ..and make local copies
|
||||
LD BC,5 ; (5 bytes, UABNK..MAXBNK)
|
||||
LDIR
|
||||
CALL CODEND ; get first available page after code end
|
||||
LD (WSPCBEG),HL ; and store it
|
||||
EX DE,HL ; swap regs
|
||||
|
||||
; memory read/write tests for all ram banks at addr 0x0000
|
||||
; building a map in WSPC area: b1= zero if no bank found, b2= initially read byte
|
||||
|
||||
; test #1: 0x00/0xFF byte - iterate over banks in forward order
|
||||
LD HL,0 ; set addr 0x0000
|
||||
LD C,0 ; start with bank #0 (TPA)
|
||||
MEMRW: CALL GETFRB ; get byte
|
||||
LD B,A ; store in B
|
||||
CPL ; invert (complement) byte
|
||||
CALL SETINB ; write it back
|
||||
CALL GETFRB ; read again
|
||||
CPL ; ..and invert
|
||||
XOR B ; xor'd with initially read byte
|
||||
JR NZ,MEMRW0 ; ..if no match, skip over
|
||||
LD A,B ; get initially read byte
|
||||
CALL SETINB ; write it
|
||||
CALL GETFRB ; and read again
|
||||
SUB B ; subtract initially read byte
|
||||
JR NZ,MEMRW0 ; ..if not zero, skip over
|
||||
|
||||
; injected opcode 0xF6 (OR n) to skip following XOR A
|
||||
DEFB 0F6h ; = OR 0AFH (write non-zero)
|
||||
MEMRW0: XOR A ; nullify A
|
||||
LD (DE),A ; store in WSPC area
|
||||
INC DE ; move ptr fwd
|
||||
LD A,B ; get initially read byte
|
||||
LD (DE),A ; store it, too
|
||||
INC DE ; move ptr fwd
|
||||
INC C ; bank # +1
|
||||
JR NZ,MEMRW ; ..loop till all possible (256 / 0x100) banks tested
|
||||
|
||||
; test #2: write no. in each bank (iterate backward), then read and compare (forward)
|
||||
DEC C ; correct bank # (loop was 1 ahead)
|
||||
MEMWRB: DEC DE ; move ptr back
|
||||
DEC DE
|
||||
LD A,(DE) ; get byte
|
||||
OR A ; check if bank exists
|
||||
JR Z,MEMWRB0 ; ..if not, skip over
|
||||
LD A,C ; else, get bank #
|
||||
CALL SETINB ; and write in bank
|
||||
MEMWRB0: LD A,C ; get bank #
|
||||
SUB 1 ; -1
|
||||
LD C,A ; set bank #
|
||||
JR NC,MEMWRB ; ..if not below zero, loop
|
||||
INC C ; correct bank #
|
||||
|
||||
MEMRDB: LD A,(DE) ; get byte from WSPC area
|
||||
OR A ; check if bank exists
|
||||
JR Z,MEMRDB0 ; ..if not, skip over
|
||||
CALL GETFRB ; read byte from bank
|
||||
CP C ; compare to bank #
|
||||
JR Z,MEMRDB0 ; ..if match, skip over
|
||||
XOR A ; else, set <NUL> as indicator
|
||||
LD (DE),A ; that bank doesn't exist
|
||||
MEMRDB0: INC DE ; move ptr fwd
|
||||
INC DE
|
||||
INC C ; bank # +1
|
||||
JR NZ,MEMRDB ; ..loop till all possible (256 / 0x100) banks tested
|
||||
|
||||
; restore bytes initially read in all banks
|
||||
LD DE,(WSPCBEG) ; set ptr to start of WSPC addr
|
||||
MEMRST: LD A,(DE) ; get byte
|
||||
OR A ; check bank exists
|
||||
JR Z,MEMRST0 ; ..if not, skip over
|
||||
INC DE ; move ptr fwd
|
||||
LD A,(DE) ; get initially read byte
|
||||
CALL SETINB ; ..and restore it
|
||||
INC DE ; ptr fwd
|
||||
JR MEMRST1 ; skip over
|
||||
MEMRST0: INC DE ; ptr fwd
|
||||
INC DE
|
||||
MEMRST1: INC C ; bank # +1
|
||||
JR NZ,MEMRST ; loop till done
|
||||
; ..then fall through to display collected data
|
||||
|
||||
|
||||
; display information for Banked System
|
||||
; detect ranges of continuous ram banks
|
||||
;
|
||||
; HL= ptr in WSPC area
|
||||
; C= counter (up) bank #, B= counter (down) for outer loop
|
||||
; D= bank # begin of range, E= bank # end of range
|
||||
LD BC,0
|
||||
LD HL,(WSPCBEG) ; set ptr to start of WSPC addr
|
||||
BRANGLP: LD A,(HL) ; get byte
|
||||
OR A ; check bank exists
|
||||
JR NZ,BRANGE ; ..if so, skip over
|
||||
INC HL ; else, use a shorter loop
|
||||
INC HL ; ..move ptr fwd
|
||||
INC C ; ..and bank #
|
||||
JR NZ,BRANGLP ; loop until max. reached (256 / 0x100)
|
||||
JR PCNFIG ; else, display Bios config report
|
||||
|
||||
BRANGE: LD D,C ; store start of range (bank # in D)
|
||||
BRANG0: INC HL ; ptr fwd
|
||||
INC HL
|
||||
INC C ; bank # +1
|
||||
JR NZ,BRANG1 ; ..if not max., skip over
|
||||
DEC B
|
||||
JR PBRANG ; else, display bank ranges
|
||||
|
||||
BRANG1: LD A,(HL) ; get byte
|
||||
OR A ; check bank exists
|
||||
JR NZ,BRANG0 ; ..if so, loop
|
||||
; else, fall through
|
||||
|
||||
; display collected information
|
||||
PBRANG: LD E,C ; get current bank # in E
|
||||
DEC E ; loop is ahead, so -1
|
||||
CALL EPRINT
|
||||
DEFB CR,LF,'RAM Banks '
|
||||
DEFB 0
|
||||
LD A,D ; get begin of range
|
||||
CALL PAFDC ; ..and display it
|
||||
CALL EPRINT
|
||||
DEFB ' - '
|
||||
DEFB 0
|
||||
LD A,E ; get end of range
|
||||
CALL PAFDC ; ..and display it
|
||||
CALL EPRINT
|
||||
DEFB ' ('
|
||||
DEFB 0
|
||||
LD A,E ; get end of range
|
||||
INC A ; adjust for correct calc
|
||||
SUB D ; calc difference of begin/end
|
||||
PUSH HL
|
||||
LD L,A ; get value in L
|
||||
LD H,0 ; ..and multiply for display
|
||||
ADD HL,HL ; *2
|
||||
ADD HL,HL ; *4
|
||||
ADD HL,HL ; *8
|
||||
ADD HL,HL ; *16
|
||||
ADD HL,HL ; *32 (fixed bank size of 32k assumed)
|
||||
CALL PHLFDC ; ..and display
|
||||
POP HL
|
||||
CALL EPRINT
|
||||
DEFB 'k Bytes)'
|
||||
DEFB 0
|
||||
LD A,B ; check if more to go
|
||||
OR A
|
||||
JR Z,BRANGLP ; loop till done
|
||||
|
||||
; display information as stored in B/P Bios config area
|
||||
PCNFIG: CALL EPRINT
|
||||
DEFB CR,LF,LF,'Bios Reports:',CR,LF
|
||||
DEFB ' TPA Banks = '
|
||||
DEFB 0
|
||||
LD A,(TPABNK) ; get TPA bank #
|
||||
PUSH AF ; save regs
|
||||
CALL PAFDC ; and display it
|
||||
LD A,'/'
|
||||
CALL COUT
|
||||
POP AF ; restore value
|
||||
INC A ; +1 (TPA bank is build by 2 consecutive banks)
|
||||
; fixed size of 32k per bank is assumed
|
||||
CALL PAFDC ; and display it
|
||||
CALL EPRINT
|
||||
DEFB CR,LF,' System Bank = '
|
||||
DEFB 0
|
||||
LD A,(SYSBNK) ; get SYSTEM bank #
|
||||
CALL PAFDC ; and display it
|
||||
CALL EPRINT
|
||||
DEFB CR,LF,' User Bank = '
|
||||
DEFB 0
|
||||
LD A,(UABNK) ; get # of USER banks
|
||||
OR A
|
||||
JR NZ,PCNFIG0 ; ..if not zero, skip over
|
||||
CALL EPRINT
|
||||
DEFB '(None)'
|
||||
DEFB 0
|
||||
JR PCNFIG1
|
||||
PCNFIG0: CALL PAFDC ; display # of USER banks
|
||||
PCNFIG1: CALL EPRINT
|
||||
DEFB CR,LF,' RAM Disk Start = '
|
||||
DEFB 0
|
||||
LD A,(RAMBNK) ; get # of begin RAM Disk
|
||||
CALL PAFDC
|
||||
CALL EPRINT
|
||||
DEFB CR,LF,' Last Used Bank = '
|
||||
DEFB 0
|
||||
LD A,(MAXBNK) ; get max. available bank #
|
||||
CALL PAFDC
|
||||
CALL EPRINT
|
||||
DEFB CR,LF,LF,' -- Scan Complete.',CR,LF
|
||||
DEFB 0
|
||||
JP EXIT
|
||||
|
||||
|
||||
;::::: SUPPORT FUNCTIONS
|
||||
|
||||
; get first token from command line (in FCB #1)
|
||||
; and check if help was requested
|
||||
CHKHELP: LD HL,CPMFCB+1
|
||||
LD A,(HL) ; get byte
|
||||
CP '/' ; is this a help request ?
|
||||
RET NZ ; ..if not, return
|
||||
INC HL ; else, move ptr fwd
|
||||
LD A,(HL) ; and get next byte
|
||||
CP '/' ; is it also '/' ?
|
||||
RET NZ ; ..if not, return
|
||||
; else, fall through and display help
|
||||
|
||||
|
||||
;::::: HELP SCREEN
|
||||
|
||||
HELP: CALL EPRINT
|
||||
DEFB CR,LF,' '
|
||||
DEFB 0
|
||||
CALL PPRGNAM
|
||||
CALL EPRINT
|
||||
DEFB ' Determines location and Size of Banked Memory.',CR,LF
|
||||
DEFB ' (Only TPA Banks printed if Non-Banked)',CR,LF,LF
|
||||
DEFB ' Syntax:',CR,LF
|
||||
DEFB ' '
|
||||
DEFB 0
|
||||
CALL PPRGNAM
|
||||
CALL EPRINT
|
||||
DEFB ' - Print 32k RAM banks present and B/P Allocations',CR,LF
|
||||
DEFB ' '
|
||||
DEFB 0
|
||||
CALL PPRGNAM
|
||||
CALL EPRINT
|
||||
DEFB ' // - display this screen',CR,LF
|
||||
DEFB 0 ; fall through and exit
|
||||
|
||||
|
||||
;::::: EXIT PROGRAM
|
||||
|
||||
EXIT: CALL CRLF
|
||||
LD SP,(STACK) ; restore stack pointer
|
||||
RET ; ..and return to system
|
||||
|
||||
|
||||
;::::: SUPPORT FUNCTIONS
|
||||
|
||||
; check if running under ZCPR3 and status of wheel byte
|
||||
; terminate program if not succesful
|
||||
CHKZ3E: LD HL,(CPMBDOS+1)
|
||||
CALL WHRENV ; find Z3 Environment Descriptor
|
||||
LD (ENVADR),HL ; store ENV ptr
|
||||
LD A,H ; check if invalid (= zero)
|
||||
OR L
|
||||
JP Z,E$BPBIO ; ..if so, jump error and terminate
|
||||
CALL Z3INIT ; else, init for Z3LIB routines
|
||||
LD A,41 ; offset to addr of wheel byte (Z3WHL)
|
||||
CALL ADDHLA ; adjust ptr
|
||||
LD E,(HL) ; get addr in DE
|
||||
INC HL
|
||||
LD D,(HL)
|
||||
EX DE,HL ; swap regs
|
||||
LD A,(HL) ; get value of wheel byte
|
||||
AND A ; check if zero
|
||||
RET NZ ; ..if not (wheel on), return
|
||||
CALL EPRINT ; else, display message and exit
|
||||
DEFB BEL,CR,LF,'Must be wheel to Execute !',CR,LF
|
||||
DEFB 0
|
||||
JR EXIT
|
||||
|
||||
|
||||
; check if running under B/P Bios
|
||||
; if not, program is terminated
|
||||
CHKSYS: LD HL,(CPMBIOS+1) ; get warm boot addr (BIOS fn #1)
|
||||
LD L,30*3 ; adjust ptr to fn #30
|
||||
LD A,(HL) ; check byte at ptr location
|
||||
CP 0C3H ; is it opcode 0xC3 (JP) ?
|
||||
JR NZ,E$BPBIO ; ..if not, jump error and terminate
|
||||
CALL JUMPHL ; else, "call" B/P Bios fn #30 (RETBIO)
|
||||
LD (BPVERS),A ; store version of B/P Bios
|
||||
LD (BPADDR),BC ; " base addr
|
||||
LD (BPCNFG),DE ; " config area addr
|
||||
LD HL,-6 ; move ptr 6 bytes backward
|
||||
ADD HL,DE ; (signature string)
|
||||
LD A,(HL) ; get byte
|
||||
CP 'B' ; is it 'B' ?
|
||||
JR NZ,E$BPBIO ; ..if not, jump error and exit
|
||||
INC HL ; ptr fwd
|
||||
LD A,(HL) ; get byte
|
||||
CP '/' ; is it '/' ?
|
||||
JR NZ,E$BPBIO ; ..if not, jump error and exit
|
||||
INC HL ; ptr fwd
|
||||
LD A,(HL) ; get byte
|
||||
CP 'P' ; is it 'P' ?
|
||||
RET Z ; ..if so, return
|
||||
; else, fall through (error and exit)
|
||||
|
||||
|
||||
; msg aborting
|
||||
E$BPBIO: CALL EPRINT
|
||||
DEFB CR,LF,BEL,'Not B/P Bios, aborting...!',CR,LF
|
||||
DEFB 0
|
||||
RST 0
|
||||
|
||||
|
||||
; print program name on CON: device
|
||||
; (either the actual name, or fallback to default)
|
||||
; only used by HELP
|
||||
PPRGNAM: LD A,(ENVADR+1) ; get high byte of ENVPTR
|
||||
OR A ; check if valid (<> zero)
|
||||
JP NZ,PRTNAME ; ..if so, display actual name
|
||||
; ..and let return from there
|
||||
CALL EPRINT ; else, display default
|
||||
DEFB 'SIZERAM'
|
||||
DEFB 0
|
||||
RET
|
||||
|
||||
|
||||
; msg B/P Bios Vers x.x
|
||||
M$BVER: CALL EPRINT
|
||||
DEFB ' (B/P Bios Vers '
|
||||
DEFB 0
|
||||
LD A,(BPVERS) ; get version #
|
||||
RRCA ; reverse nybbles in A
|
||||
RRCA
|
||||
RRCA
|
||||
RRCA
|
||||
AND 00001111b ; mask lower nybble
|
||||
ADD A,'0' ; make it ascii
|
||||
CALL COUT ; ..and display
|
||||
LD A,'.'
|
||||
CALL COUT
|
||||
LD A,(BPVERS) ; get version #
|
||||
AND 00001111b ; mask lower nybble
|
||||
ADD A,'0' ; make it ascii
|
||||
CALL COUT ; ..and display
|
||||
CALL EPRINT
|
||||
DEFB ')',CR,LF
|
||||
DEFB 0
|
||||
RET
|
||||
|
||||
|
||||
; add A to HL (result in HL)
|
||||
ADDHLA: ADD A,L ; add L
|
||||
LD L,A ; store result in L
|
||||
RET NC ; ..if no overflow, return
|
||||
INC H ; else, increment H
|
||||
RET
|
||||
|
||||
|
||||
; the following routines rearrange Top of Stack by injecting an
|
||||
; intermediate return addr, and putting the Bios fn call on top
|
||||
; so that HL regs are preserved
|
||||
; order of steps:
|
||||
; [1] HL (= addr) is pushed onto stack
|
||||
; [2] intermediate return addr is swapped to Top of Stack
|
||||
; [3] HL (= addr) is pushed onto stack again
|
||||
; [4] Bios fn JP addr is swapped to Top of Stack
|
||||
; [5] Bios is "called" through RET, and returns to intermediate addr
|
||||
|
||||
; get byte from ram bank - in the form LD A,(HL)
|
||||
; in: C= bank #, HL= addr
|
||||
; out: A= byte
|
||||
GETFRB: PUSH BC
|
||||
PUSH HL ; save addr
|
||||
LD HL,GETFRB0 ; load return addr
|
||||
EX (SP),HL ; put it on stack
|
||||
PUSH HL ; save HL again (previous top of stack)
|
||||
LD HL,(BPADDR) ; get B/P Bios base addr
|
||||
LD L,35*3 ; adjust ptr to fn #35 (FRGETB)
|
||||
EX (SP),HL ; put addr on stack
|
||||
RET ; ..and "call" Bios fn through stack
|
||||
|
||||
GETFRB0: POP BC ; restore regs
|
||||
RET ; ..and finally return
|
||||
|
||||
; set byte in ram bank - in the form LD (HL),A
|
||||
; in: C= bank #, HL= addr, A= byte to set
|
||||
SETINB: PUSH BC
|
||||
PUSH HL ; save addr
|
||||
LD HL,GETFRB0 ; load return addr
|
||||
EX (SP),HL ; put it on stack
|
||||
PUSH HL ; save HL again (previous top of stack)
|
||||
LD HL,(BPADDR) ; get B/P Bios base addr
|
||||
LD L,37*3 ; adjust ptr to fn #37 (FRPUTB)
|
||||
EX (SP),HL ; put addr on stack
|
||||
RET ; ..and "call" Bios fn through stack
|
||||
|
||||
|
||||
; "called" as a pseudo-routine that returns to caller
|
||||
; in: HL= target addr
|
||||
JUMPHL: JP (HL) ; jump to addr in HL regs
|
||||
|
||||
|
||||
;::::: LOCAL DATA (not in DSEG)
|
||||
|
||||
WSPCBEG: DEFW 0 ; addr begin of workspace area
|
||||
; (first available page, returned by CODEND)
|
||||
|
||||
; data retrieved from running system
|
||||
BPVERS: DEFB 0 ; B/P Bios version
|
||||
BPADDR: DEFW 0 ; B/P Bios base addr
|
||||
BPCNFG: DEFW 0 ; addr of Config Area
|
||||
BPBNKD: DEFB 0 ; indicator banked system (bit 0 of OPTF1) --> not used
|
||||
|
||||
; local copies of RAM bank configuration
|
||||
UABNK: DEFB 0 ; beginning of User Bank(s)
|
||||
TPABNK: DEFB 0 ; TPA Bank
|
||||
SYSBNK: DEFB 0 ; beginning of System Bank(s)
|
||||
RAMBNK: DEFB 0 ; base bank # for Ram Disk
|
||||
MAXBNK: DEFB 0 ; highest permissible Bank #
|
||||
|
||||
|
||||
DEFS 30H ; room for stack
|
||||
STACK: DEFW 0 ; stack storage location
|
||||
|
||||
|
||||
;:::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
; Z3LIB - 0x05ae
|
||||
; SYSLIB - 0x065c
|
||||
; end addr 0x0750 (begin DSEG)
|
||||
;:::::::::::::::::::::::::::::::::::::::::::::::::::::
|
||||
|
||||
|
||||
;::::: RAM STORAGE
|
||||
|
||||
DSEG
|
||||
|
||||
END
|
||||
|
||||
|
||||
;************************************************************************
|
||||
; Remarks jxl:
|
||||
; SIZERAM.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 INITRAM.COM, i.e. no changes to the source were made.
|
||||
;
|
||||
; The program uses an interesting technique to read and write data in
|
||||
; alternative ram banks utilizing B/P Bios functions no. 35 FRGETB and
|
||||
; no. 37 FRPUTB. Top of Stack is manipulated to keep registers intact
|
||||
; and "call" functions through a RET statement (instead of CALL.)
|
||||
; Another specialty which is worth mentioning: Routine MEMRW (memory
|
||||
; read/write) contains an "injected" opcode to alter the behaviour at
|
||||
; runtime. Otherwise a more complex logic and/or additional routine
|
||||
; would have been necessary.
|
||||
; Storage of local data is in CSEG (code segment), not DSEG. There
|
||||
; seems to be no particular reason for this. So, it can be assumed that
|
||||
; this just happened by mistake.
|
||||
;************************************************************************
|
||||
1323
Source/BPBIOS/UTIL/zscfg2.z80
Normal file
1323
Source/BPBIOS/UTIL/zscfg2.z80
Normal file
File diff suppressed because it is too large
Load Diff
1247
Source/BPBIOS/bpart.txt
Normal file
1247
Source/BPBIOS/bpart.txt
Normal file
File diff suppressed because it is too large
Load Diff
@@ -8,6 +8,7 @@ pushd QPM && call Build || exit /b & popd
|
||||
pushd ZCPR && call Build || exit /b & popd
|
||||
pushd ZCPR-DJ && call Build || exit /b & popd
|
||||
pushd ZSDOS && call Build || exit /b & popd
|
||||
pushd ZSDOS2 && call Build || exit /b & popd
|
||||
pushd CPM3 && call Build || exit /b & popd
|
||||
pushd ZPM3 && call Build || exit /b & popd
|
||||
pushd CPNET && call Build || exit /b & popd
|
||||
|
||||
@@ -8,6 +8,7 @@ pushd QPM && call Clean.cmd & popd
|
||||
pushd ZCPR && call Clean.cmd & popd
|
||||
pushd ZCPR-DJ && call Clean.cmd & popd
|
||||
pushd ZSDOS && call Clean.cmd & popd
|
||||
pushd ZSDOS2 && call Clean.cmd & popd
|
||||
pushd CBIOS && call Clean.cmd & popd
|
||||
pushd CPM3 && call Clean.cmd & popd
|
||||
pushd ZPM3 && call Clean.cmd & popd
|
||||
|
||||
@@ -328,6 +328,9 @@ please let me know if I missed you!
|
||||
contributed a driver for the Xosera FPGA-based video
|
||||
controller.
|
||||
|
||||
* Jörg Linder has contributed disassembled and nicely commented
|
||||
source for ZSDOS2 and the BPBIOS utilities.
|
||||
|
||||
`\clearpage`{=latex}
|
||||
|
||||
## Related Projects
|
||||
|
||||
@@ -8,19 +8,14 @@ set PATH=%TOOLS%\lzsa;%TOOLS%\fonttool;%PATH%
|
||||
echo.
|
||||
echo Preparing compressed font files...
|
||||
|
||||
lzsa -f2 -r font8x8u.bin font8x8c.bin || exit /b
|
||||
lzsa -f2 -r font8x11u.bin font8x11c.bin || exit /b
|
||||
lzsa -f2 -r font8x16u.bin font8x16c.bin || exit /b
|
||||
lzsa -f2 -r fontcgau.bin fontcgac.bin || exit /b
|
||||
lzsa -f2 -r fontvgarcu.bin fontvgarcc.bin || exit /b
|
||||
for %%f in (font6x8 font8x8 font8x11 font8x16 fontcga fontvgarc) do call :genfont %%f
|
||||
|
||||
fonttool font8x8u.bin > font8x8u.asm || exit /b
|
||||
fonttool font8x11u.bin > font8x11u.asm || exit /b
|
||||
fonttool font8x16u.bin > font8x16u.asm || exit /b
|
||||
fonttool font8x8c.bin > font8x8c.asm || exit /b
|
||||
fonttool font8x11c.bin > font8x11c.asm || exit /b
|
||||
fonttool font8x16c.bin > font8x16c.asm || exit /b
|
||||
fonttool fontcgau.bin > fontcgau.asm || exit /b
|
||||
fonttool fontcgac.bin > fontcgac.asm || exit /b
|
||||
fonttool fontvgarcu.bin > fontvgarcu.asm || exit /b
|
||||
fonttool fontvgarcc.bin > fontvgarcc.asm || exit /b
|
||||
goto :eof
|
||||
|
||||
:genfont
|
||||
echo Processing font %1...
|
||||
lzsa -f2 -r %1u.bin %1c.bin || exit /b
|
||||
fonttool %1u.bin >%1u.asm || exit /b
|
||||
fonttool %1c.bin >%1c.asm || exit /b
|
||||
|
||||
goto :eof
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
OBJECTS = \
|
||||
font8x8u.asm font8x11u.asm font8x16u.asm fontcgau.asm fontvgarcu.asm \
|
||||
font8x8c.asm font8x11c.asm font8x16c.asm fontcgac.asm fontvgarcc.asm
|
||||
font6x8u.asm font8x8u.asm font8x11u.asm font8x16u.asm fontcgau.asm fontvgarcu.asm \
|
||||
font6x8c.asm font8x8c.asm font8x11c.asm font8x16c.asm fontcgac.asm fontvgarcc.asm
|
||||
|
||||
OTHERS = font8x8c.bin font8x11c.bin font8x16c.bin fontcgac.bin fontvgarcc.bin
|
||||
OTHERS = font6x8c.bin font8x8c.bin font8x11c.bin font8x16c.bin fontcgac.bin fontvgarcc.bin
|
||||
|
||||
TOOLS = ../../Tools
|
||||
|
||||
@@ -14,6 +14,9 @@ include $(TOOLS)/Makefile.inc
|
||||
%.rel: %.asm
|
||||
%.bin: %.asm
|
||||
|
||||
font6x8c.bin: font6x8u.bin
|
||||
$(BINDIR)/lzsa -f2 -r $< $@
|
||||
|
||||
font8x8c.bin: font8x8u.bin
|
||||
$(BINDIR)/lzsa -f2 -r $< $@
|
||||
|
||||
|
||||
BIN
Source/Fonts/font6x8.png
Normal file
BIN
Source/Fonts/font6x8.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.7 KiB |
BIN
Source/Fonts/font6x8u.bin
Normal file
BIN
Source/Fonts/font6x8u.bin
Normal file
Binary file not shown.
@@ -17,16 +17,18 @@ There are multiple fonts associated with ROMWBW supported hardware:
|
||||
MBC-VDP tms.asm 9938/9958
|
||||
RCBUS-VRC vrc.asm PLD
|
||||
RCBUS-TMS tms.asm 99x8
|
||||
XOSERA xosera.asm ?
|
||||
|
||||
Name Glyph Cell Size Comp Board & Display Mode
|
||||
------------------------------------------------------------------------------------------------
|
||||
font8x8 6x8 8x8 2048 1034 ECB-SCG, ECB-VGA3 (80x60), MBC-VDP
|
||||
font6x8 6x8 8x8 2048 1094 ECB-SCG, MBC-VDP
|
||||
font8x8 6x8 8x8 2048 1034 ECB-VGA3 (80x60)
|
||||
font8x11 8x11 8x11 2816 1252 ECB-VGA3 (80x43)
|
||||
font8x16 8x14 8x16 4096 1466 ECB-CVDU (EGA), ECB-VGA3 (80x24, 80x25, 80x30), MBC-VDC (EGA)
|
||||
fontcga 8x8 8x16 4096 1280 ECB-CVDU (CGA), MBC-VDC (CGA)
|
||||
fontvrc 8x8 8x8 1024 650 VGARC
|
||||
----- -----
|
||||
14080 5682
|
||||
16128 6776
|
||||
|
||||
Notes:
|
||||
|
||||
@@ -36,7 +38,7 @@ Notes:
|
||||
but the font definition must still be 8x16. The CGA font is used for this.
|
||||
|
||||
For inclusion in HBIOS the .bin format files must be converted to assembler .asm format.
|
||||
This is acheived using the fonttool utility and is completed automatically as part of the build process.
|
||||
This is achieved using the fonttool utility and is completed automatically as part of the build process.
|
||||
i.e. fonts files are converted to .asm format and then copied to the HBIOS directory.
|
||||
|
||||
To replace a font, simply copy it to the Fonts directory using the same naming convention above,
|
||||
|
||||
@@ -98,6 +98,8 @@ call :asm game || exit /b
|
||||
call :asm usrrom || exit /b
|
||||
call :asm updater || exit /b
|
||||
|
||||
:: call :asm fonts || exit /b
|
||||
|
||||
:: Sysconf builds as both BIN and COM files
|
||||
tasm -t%CPUType% -g3 -fFF -dROMWBW sysconf.asm sysconf.bin sysconf_bin.lst || exit /b
|
||||
tasm -t%CPUType% -g3 -fFF -dCPM sysconf.asm sysconf.com sysconf_com.lst || exit /b
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
MOREDIFF = game.bin hbios_rom.bin nascom.bin usrrom.bin \
|
||||
dbgmon.bin hbios_app.bin imgpad2.bin rom2.bin rom3.bin romldr.bin \
|
||||
dbgmon.bin hbios_app.bin rom2.bin rom3.bin romldr.bin \
|
||||
eastaegg.bin hbios_img.bin rom1.bin game.bin updater.bin usrrom.bin
|
||||
|
||||
DEST = ../../Binary
|
||||
@@ -24,7 +24,7 @@ endif
|
||||
include $(TOOLS)/Makefile.inc
|
||||
|
||||
FONTS := font8x11c.asm font8x11u.asm font8x16c.asm font8x16u.asm font8x8c.asm font8x8u.asm \
|
||||
fontcgac.asm fontcgau.asm fontvgarcc.asm fontvgarcu.asm
|
||||
font6x8c.asm font6x8u.asm fontcgac.asm fontcgau.asm fontvgarcc.asm fontvgarcu.asm
|
||||
|
||||
ifeq ($(CPUFAM),2)
|
||||
TASM=$(BINDIR)/uz80as -t hd64180
|
||||
@@ -32,7 +32,7 @@ else ifeq ($(CPUFAM),3)
|
||||
TASM=$(BINDIR)/uz80as -t z280
|
||||
endif
|
||||
|
||||
DEPS=prereq dbgmon.bin romldr.bin nascom.bin tastybasic.bin game.bin eastaegg.bin updater.bin sysconf.bin sysconf.com usrrom.bin imgpad2.bin
|
||||
DEPS=prereq dbgmon.bin romldr.bin nascom.bin tastybasic.bin game.bin eastaegg.bin updater.bin sysconf.bin sysconf.com usrrom.bin
|
||||
|
||||
ifeq ($(ROM_PLATFORM),UNA)
|
||||
ROMDEPS=romldr.bin dbgmon.bin
|
||||
|
||||
@@ -1927,7 +1927,7 @@ ROMRESUME:
|
||||
;
|
||||
; LAUNCH S100 MONITOR FROM ROM BANK 3
|
||||
LD A,BID_IMG2 ; S100 MONITOR BANK
|
||||
LD IX,0 ; EXECUTION RESUMES HERE
|
||||
LD IX,HWMON_IMGLOC ; EXECUTION RESUMES HERE
|
||||
CALL HBX_BNKCALL ; CONTINUE IN RAM BANK, DO NOT RETURN
|
||||
HALT ; WE SHOULD NOT COME BACK HERE!
|
||||
;
|
||||
@@ -9506,12 +9506,23 @@ ORG_FONTS .EQU $
|
||||
;
|
||||
MEMECHO "FONTS"
|
||||
;
|
||||
#IFDEF USEFONT6X8
|
||||
FONT6X8:
|
||||
;
|
||||
; FOR NOW, WE NEVER COMPRESS THE 6X8 FONT. SEE TMS DRIVER.
|
||||
;
|
||||
#IF USELZSA2 & FALSE
|
||||
#INCLUDE "font6x8c.asm"
|
||||
#ELSE
|
||||
#INCLUDE "font6x8u.asm"
|
||||
#ENDIF
|
||||
MEMECHO " 6X8"
|
||||
#ENDIF
|
||||
;
|
||||
#IFDEF USEFONT8X8
|
||||
FONT8X8:
|
||||
;
|
||||
; FOR NOW, WE NEVER COMPRESS THE 8X8 FONT. SEE TMS DRIVER.
|
||||
;
|
||||
#IF USELZSA2 & FALSE
|
||||
#IF USELZSA2
|
||||
#INCLUDE "font8x8c.asm"
|
||||
#ELSE
|
||||
#INCLUDE "font8x8u.asm"
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
#INCLUDE "std.asm"
|
||||
;
|
||||
SLACK .EQU $8000
|
||||
.FILL SLACK,00H
|
||||
;
|
||||
.ECHO "Padspace space created: "
|
||||
.ECHO SLACK
|
||||
.ECHO " bytes.\n"
|
||||
|
||||
.END
|
||||
@@ -185,9 +185,9 @@ HWMON_IMGLOC .EQU BNK_NXTLOC ; LOCATION OF BINARY LOAD IMAGE IN BANK
|
||||
BNK_NXTLOC .SET HWMON_IMGLOC + HWMON_SIZ ; IMG LOC OF NEXT COMPONENT
|
||||
;
|
||||
FONTS_BNK .EQU BNK_CUR
|
||||
;;;FONTS_LOC .EQU $E000
|
||||
FONTS_SIZ .EQU $2000
|
||||
;;;FONTS_END .EQU FONTS_LOC + FONTS_SIZ
|
||||
FONTS_LOC .EQU $0000
|
||||
FONTS_SIZ .EQU $4000
|
||||
FONTS_END .EQU FONTS_LOC + FONTS_SIZ
|
||||
FONTS_IMGLOC .EQU BNK_NXTLOC ; LOCATION OF BINARY LOAD IMAGE IN BANK
|
||||
BNK_NXTLOC .SET FONTS_IMGLOC + FONTS_SIZ ; IMG LOC OF NEXT COMPONENT
|
||||
;
|
||||
@@ -206,19 +206,19 @@ BNK3_SLACK .EQU BNKTOP - BNK_NXTLOC ; REMAINING BANK SPACE
|
||||
.ECHO "BANK3 BID_IMG2 \t" \ .ECHO BNK3_LEN \ .ECHO "\t" \ .ECHO BNK3_SLACK \ .ECHO "\n"
|
||||
.ECHO "-------------------------------\n"
|
||||
;
|
||||
#IF (BNK1_LEN > BNKTOP)
|
||||
#ENDIF
|
||||
;
|
||||
#IF (BNK1_SLACK < 0)
|
||||
.ECHO "*** ROM BANK 1 IS TOO BIG!!!\n"
|
||||
!!! ; FORCE AN ASSEMBLY ERROR IF BANK SIZE EXCEEDS SPACE
|
||||
#ENDIF
|
||||
#ENDIF
|
||||
;
|
||||
#IF (BNK2_LEN > BNKTOP)
|
||||
#IF (BNK2_SLACK < 0)
|
||||
.ECHO "*** ROM BANK 2 IS TOO BIG!!!\n"
|
||||
!!! ; FORCE AN ASSEMBLY ERROR IF BANK SIZE EXCEEDS SPACE
|
||||
#ENDIF
|
||||
#ENDIF
|
||||
;
|
||||
#IF (BNK3_LEN > BNKTOP)
|
||||
#IF (BNK3_SLACK < 0)
|
||||
.ECHO "*** ROM BANK 3 IS TOO BIG!!!\n"
|
||||
!!! ; FORCE AN ASSEMBLY ERROR IF BANK SIZE EXCEEDS SPACE
|
||||
#ENDIF
|
||||
;
|
||||
#ENDIF
|
||||
|
||||
@@ -1554,7 +1554,7 @@ s100mon1:
|
||||
call ldelay ; wait for UART buf to empty
|
||||
di ; suspend interrupts
|
||||
ld a,HWMON_BNK ; S100 monitor bank
|
||||
ld ix,0 ; execution resumes here
|
||||
ld ix,HWMON_IMGLOC ; execution resumes here
|
||||
jp HB_BNKCALL ; do it
|
||||
;
|
||||
str_smon .db "S100 Z180 Monitor",0
|
||||
|
||||
@@ -432,16 +432,16 @@ CNTLB0_VALUE equ 00H ; For setting final baud rate from
|
||||
;
|
||||
jp mon_start
|
||||
|
||||
DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;To clean up PROM for easy reading
|
||||
DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
Db 0,0,0,0
|
||||
;;; DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;To clean up PROM for easy reading
|
||||
;;; DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
;;; DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
;;; DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
;;; DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
;;; DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
;;; DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
;;; DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
;;; DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
;;; Db 0,0,0,0
|
||||
|
||||
; Jump to monitor!!!
|
||||
;
|
||||
|
||||
@@ -549,6 +549,14 @@ V80X43 .EQU 5 ; ECB-VGA3
|
||||
V80X60 .EQU 6 ; ECB-VGA3
|
||||
V40X24 .EQU 7 ; EF9345
|
||||
;
|
||||
; FONT IDS
|
||||
;
|
||||
FONTID_8X8 .EQU 1
|
||||
FONTID_8X11 .EQU 2
|
||||
FONTID_8X16 .EQU 3
|
||||
FONTID_CGA .EQU 4
|
||||
FONTID_VGARC .EQU 5
|
||||
;
|
||||
; KEYBOARD LAYOUTS
|
||||
;
|
||||
KBD_US .EQU 0 ; US ENGLISH
|
||||
|
||||
@@ -150,8 +150,10 @@ TMS_COLS .EQU 40
|
||||
DEVECHO "X"
|
||||
DEVECHO TMS_ROWS
|
||||
;
|
||||
#DEFINE USEFONT8X8
|
||||
#DEFINE TMS_FONT FONT8X8
|
||||
;;;#DEFINE USEFONT8X8
|
||||
;;;#DEFINE TMS_FONT FONT8X8
|
||||
#DEFINE USEFONT6X8
|
||||
#DEFINE TMS_FONT FONT6X8
|
||||
;
|
||||
TERMENABLE .SET TRUE ; INCLUDE TERMINAL PSEUDODEVICE DRIVER
|
||||
;
|
||||
|
||||
@@ -23,6 +23,7 @@ shared:
|
||||
$(MAKE) --directory ZCPR $(ACTION)
|
||||
$(MAKE) --directory ZCPR-DJ $(ACTION)
|
||||
$(MAKE) --directory ZSDOS $(ACTION)
|
||||
$(MAKE) --directory ZSDOS2 $(ACTION)
|
||||
$(MAKE) --directory CPM3 $(ACTION)
|
||||
$(MAKE) --directory ZPM3 $(ACTION)
|
||||
$(MAKE) --directory CPNET $(ACTION)
|
||||
|
||||
12
Source/ZSDOS2/Build.cmd
Normal file
12
Source/ZSDOS2/Build.cmd
Normal file
@@ -0,0 +1,12 @@
|
||||
@echo off
|
||||
setlocal
|
||||
|
||||
set TOOLS=../../Tools
|
||||
|
||||
set PATH=%TOOLS%\tasm32;%TOOLS%\zxcc;%PATH%
|
||||
|
||||
set TASMTABS=%TOOLS%\tasm32
|
||||
|
||||
set CPMDIR80=%TOOLS%/cpm/
|
||||
|
||||
zxcc Z80ASM -ZSDOS2/6FS || exit /b
|
||||
6
Source/ZSDOS2/Clean.cmd
Normal file
6
Source/ZSDOS2/Clean.cmd
Normal file
@@ -0,0 +1,6 @@
|
||||
@echo off
|
||||
setlocal
|
||||
|
||||
if exist *.lst del *.lst
|
||||
if exist *.rel del *.rel
|
||||
if exist *.sym del *.sym
|
||||
5
Source/ZSDOS2/Makefile
Normal file
5
Source/ZSDOS2/Makefile
Normal file
@@ -0,0 +1,5 @@
|
||||
TOOLS = ../../Tools
|
||||
|
||||
OBJECTS = zsdos2.rel
|
||||
|
||||
include $(TOOLS)/Makefile.inc
|
||||
4116
Source/ZSDOS2/zsdos2.z80
Normal file
4116
Source/ZSDOS2/zsdos2.z80
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user