Glass Z80 assembler (v0.5.1) makes labels inside IF blocks invisible from outside those blocks. This caused multiple build failures for the SFD700 target: - JP _PRTMZF/_PRTDBG in jump table: replaced with DB 0C3H + DW encoding which resolves same-condition scope forward references via DW - LD DE,MSG* across IF scopes: created LDDE macro (DB 011H + DW) that produces identical machine code to LD DE,nn for all build targets - SFD700 command table (CMDTABLE2): moved after all INCLUDE statements so DW function references resolve as backward same-scope references - Removed FD/FDDIR entry from SFD700 command table — FDDIR only exists for ROMDISK/picoZ80 builds (MZ-700 WD1773 FDC direct access) - Fixed PRTSTR→PRINTMSG undefined symbol in rfs_bank7.asm - Fixed BUILD_PICOZ80 comment (was incorrectly labelled as SFD700) All three build targets (ROMDISK, SFD700, picoZ80) verified clean. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
870 lines
40 KiB
NASM
870 lines
40 KiB
NASM
;--------------------------------------------------------------------------------------------------------
|
|
;-
|
|
;- Name: rfs_bank3.asm
|
|
;- Created: July 2019
|
|
;- Author(s): Philip Smart
|
|
;- Description: Sharp MZ series Rom Filing System.
|
|
;- This assembly language program is written to utilise the banked flashroms added with
|
|
;- the MZ-80A RFS hardware upgrade.
|
|
;-
|
|
;- Credits:
|
|
;- Copyright: (c) 2018-2026 Philip Smart <philip.smart@net2net.org>
|
|
;-
|
|
;- History: July 2019 - Merged 2 utilities to create this compilation.
|
|
;- May 2020 - Bank switch changes with release of v2 pcb with coded latch. The coded
|
|
;- latch adds additional instruction overhead as the control latches share
|
|
;- the same address space as the Flash RAMS thus the extra hardware to
|
|
;- only enable the control registers if a fixed number of reads is made
|
|
;- into the upper 8 bytes which normally wouldnt occur. Caveat - ensure
|
|
;- that no loop instruction is ever placed into EFF8H - EFFFH.
|
|
;- Aug 2023 - Updates to make RFS run under the SFD700 Floppy Disk Interface board.
|
|
;- UROM remains the same, a 2K paged ROM, MROM is located at F000 when
|
|
;- RFS is built for the SFD700.
|
|
;-
|
|
;--------------------------------------------------------------------------------------------------------
|
|
;- This source file is free software: you can redistribute it and-or modify
|
|
;- it under the terms of the GNU General Public License as published
|
|
;- by the Free Software Foundation, either version 3 of the License, or
|
|
;- (at your option) any later version.
|
|
;-
|
|
;- This source file is distributed in the hope that it will be useful,
|
|
;- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
;- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
;- GNU General Public License for more details.
|
|
;-
|
|
;- You should have received a copy of the GNU General Public License
|
|
;- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
;--------------------------------------------------------------------------------------------------------
|
|
|
|
ROW EQU 25
|
|
COLW EQU 40
|
|
SCRNSZ EQU COLW * ROW
|
|
MODE80C EQU 0
|
|
|
|
IF BUILD_SFD700 = 1
|
|
ORG 0E000H
|
|
ALIGN 0E300H
|
|
DB "BANK3"
|
|
ALIGN UROMADDR
|
|
ENDIF
|
|
|
|
;===========================================================
|
|
;
|
|
; USER ROM BANK 3 - Monitor memory utilities.
|
|
;
|
|
;===========================================================
|
|
ORG UROMADDR
|
|
|
|
;--------------------------------
|
|
; Common code spanning all banks.
|
|
;--------------------------------
|
|
NOP
|
|
HWSELROM2 ; Select the first ROM page.
|
|
;
|
|
; No mans land... this should have switched to Bank 0 and at this point there is a jump to 00000H.
|
|
JP 00000H ; This is for safety!!
|
|
|
|
|
|
;------------------------------------------------------------------------------------------
|
|
; Bank switching code, allows a call to code in another bank.
|
|
; This code is duplicated in each bank such that a bank switch doesnt affect logic flow.
|
|
;------------------------------------------------------------------------------------------
|
|
ALIGN_NOPS UROMBSTBL
|
|
;
|
|
BKSW3to0: PUSH AF
|
|
LD A, ROMBANK3 ; Calling bank (ie. us).
|
|
PUSH AF
|
|
LD A, ROMBANK0 ; Required bank to call.
|
|
JR BKSW3_0
|
|
BKSW3to1: PUSH AF
|
|
LD A, ROMBANK3 ; Calling bank (ie. us).
|
|
PUSH AF
|
|
LD A, ROMBANK1 ; Required bank to call.
|
|
JR BKSW3_0
|
|
BKSW3to2: PUSH AF
|
|
LD A, ROMBANK3 ; Calling bank (ie. us).
|
|
PUSH AF
|
|
LD A, ROMBANK2 ; Required bank to call.
|
|
JR BKSW3_0
|
|
BKSW3to3: PUSH AF
|
|
LD A, ROMBANK3 ; Calling bank (ie. us).
|
|
PUSH AF
|
|
LD A, ROMBANK3 ; Required bank to call.
|
|
JR BKSW3_0
|
|
BKSW3to4: PUSH AF
|
|
LD A, ROMBANK3 ; Calling bank (ie. us).
|
|
PUSH AF
|
|
LD A, ROMBANK4 ; Required bank to call.
|
|
JR BKSW3_0
|
|
BKSW3to5: PUSH AF
|
|
LD A, ROMBANK3 ; Calling bank (ie. us).
|
|
PUSH AF
|
|
LD A, ROMBANK5 ; Required bank to call.
|
|
JR BKSW3_0
|
|
BKSW3to6: PUSH AF
|
|
LD A, ROMBANK3 ; Calling bank (ie. us).
|
|
PUSH AF
|
|
LD A, ROMBANK6 ; Required bank to call.
|
|
JR BKSW3_0
|
|
BKSW3to7: PUSH AF
|
|
LD A, ROMBANK3 ; Calling bank (ie. us).
|
|
PUSH AF
|
|
LD A, ROMBANK7 ; Required bank to call.
|
|
JR BKSW3_0
|
|
BKSW3to8: PUSH AF
|
|
LD A, ROMBANK3 ; Calling bank (ie. us).
|
|
PUSH AF
|
|
LD A, ROMBANK8 ; Required bank to call.
|
|
JR BKSW3_0
|
|
BKSW3to9: PUSH AF
|
|
LD A, ROMBANK3 ; Calling bank (ie. us).
|
|
PUSH AF
|
|
LD A, ROMBANK9 ; Required bank to call.
|
|
JR BKSW3_0
|
|
BKSW3to10: PUSH AF
|
|
LD A, ROMBANK3 ; Calling bank (ie. us).
|
|
PUSH AF
|
|
LD A, ROMBANK10 ; Required bank to call.
|
|
JR BKSW3_0
|
|
BKSW3to11: PUSH AF
|
|
LD A, ROMBANK3 ; Calling bank (ie. us).
|
|
PUSH AF
|
|
LD A, ROMBANK11 ; Required bank to call.
|
|
;
|
|
BKSW3_0: PUSH HL ; Place function to call on stack
|
|
LD HL, BKSWRET3 ; Place bank switchers return address on stack.
|
|
EX (SP),HL
|
|
LD (TMPSTACKP),SP ; Save the stack pointer as some old code corrupts it.
|
|
BNKSWSEL
|
|
JP (HL) ; Jump to required function.
|
|
BKSWRET3: POP AF ; Get bank which called us.
|
|
BNKSWSELRET
|
|
POP AF
|
|
RET
|
|
|
|
;-------------------------------------------------------------------------------
|
|
; START OF TAPE/SD CMDLINE TOOLS FUNCTIONALITY
|
|
;-------------------------------------------------------------------------------
|
|
|
|
; Method to copy an application on a tape to an SD stored application. The tape drive is read and the first
|
|
; encountered program is loaded into memory at 0x1200. The CMT header is populated with the correct details (even if
|
|
; the load address isnt 0x1200, the CMT Header contains the correct value).
|
|
; A call is then made to write the application to the SD card.
|
|
;
|
|
TAPE2SD: ; Load from tape into memory, filling the tape CMT header and loading data into location 0x1200.
|
|
LD HL,LOADTAPECP ; Call the Loadtape command, non execute version to get the tape contents into memory.
|
|
CALL BKSW3to4
|
|
LD A,(RESULT)
|
|
OR A
|
|
JR NZ,TAPE2SDERR
|
|
; Save to SD Card.
|
|
LD HL,SAVESDCARDX
|
|
CALL BKSW3to2
|
|
LD A,(RESULT)
|
|
OR A
|
|
JR NZ,TAPE2SDERR
|
|
LDDE MSGT2SDOK
|
|
JR TAPE2SDERR2
|
|
TAPE2SDERR: LDDE MSGT2SDERR
|
|
TAPE2SDERR2:LD HL,PRINTMSG
|
|
CALL BKSW3to6
|
|
RET
|
|
|
|
; Method to copy an SD stored application to a Cassette tape in the CMT.
|
|
; The directory entry number or filename is passed to the command and the entry is located within the SD
|
|
; directory structure. The file is then loaded into memory and the CMT header populated. A call is then made
|
|
; to write out the data to tap.
|
|
;
|
|
SD2TAPE: ; Load from SD, fill the CMT header then call CMT save.
|
|
LD HL,LOADSDCP
|
|
CALL BKSW3to2
|
|
LD A,(RESULT)
|
|
OR A
|
|
JR NZ,SD2TAPEERR
|
|
LD HL,SAVECMT
|
|
CALL BKSW3to4
|
|
LD A,(RESULT)
|
|
OR A
|
|
JR NZ,SD2TAPEERR
|
|
RET
|
|
SD2TAPEERR: LDDE MSGSD2TERR
|
|
JR TAPE2SDERR2
|
|
RET
|
|
;-------------------------------------------------------------------------------
|
|
; END OF TAPE/SD CMDLINE TOOLS FUNCTIONALITY
|
|
;-------------------------------------------------------------------------------
|
|
|
|
|
|
;-------------------------------------------------------------------------------
|
|
; START OF MEMORY CMDLINE TOOLS FUNCTIONALITY
|
|
;-------------------------------------------------------------------------------
|
|
|
|
;
|
|
; Memory correction
|
|
; command 'M'
|
|
;
|
|
MCORX: CALL READ4HEX ; correction address
|
|
RET C
|
|
MCORX1: CALL NLPHL ; corr. adr. print
|
|
CALL SPHEX ; ACC ASCII display
|
|
CALL PRNTS ; space print
|
|
LD DE,BUFER ; Input the data.
|
|
CALL GETL
|
|
LD A,(DE)
|
|
CP 01Bh ; If . pressed, exit.
|
|
RET Z
|
|
PUSH HL
|
|
POP BC
|
|
CALL HLHEX ; If the existing address is no longer hex, reset. HLASCII(DE). If it is hex, take as the address to store data into.
|
|
JR C,MCRX3 ; Line is corrupted as the address is no longer in Hex, reset.
|
|
INC DE
|
|
INC DE
|
|
INC DE
|
|
INC DE
|
|
INC DE ;
|
|
CALL _2HEX ; Get value entered.
|
|
JR C,MCORX1 ; Not hex, reset.
|
|
CP (HL) ; Not same as memory, reset.
|
|
JR NZ,MCORX1
|
|
INC DE ;
|
|
LD A,(DE) ; Check if no data just CR, if so, move onto next address.
|
|
CP 00Dh ; not correction
|
|
JR Z,MCRX2
|
|
CALL _2HEX ; Get the new entered data. ACCHL(ASCII)
|
|
JR C,MCORX1 ; New data not hex, reset.
|
|
LD (HL),A ; data correct so store.
|
|
MCRX2: INC HL
|
|
JR MCORX1
|
|
MCRX3: LD H,B ; memory address
|
|
LD L,C
|
|
JR MCORX1
|
|
|
|
; Memory copy command 'CPY'
|
|
; Parameters: XXXYYYZZZ - XXXX = Source, YYYY = Destination, ZZZZ = Size
|
|
MCOPY: CALL READ4HEX ; Source
|
|
JR C,MCOPYER1
|
|
PUSH HL
|
|
CALL READ4HEX ; Destination
|
|
JR C,MCOPYER2
|
|
PUSH HL
|
|
CALL READ4HEX ; Size
|
|
JR C,MCOPYER3
|
|
PUSH HL
|
|
POP BC ; Size
|
|
POP DE ; Destination
|
|
POP HL ; Source
|
|
LDIR
|
|
RET
|
|
;
|
|
MCOPYER3: POP HL
|
|
MCOPYER2: POP HL
|
|
MCOPYER1: RET
|
|
|
|
|
|
; Dump method when called interbank as HL cannot be passed.
|
|
;
|
|
; BC = Start
|
|
; DE = End
|
|
DUMPBC: PUSH BC
|
|
POP HL
|
|
JR DUMP
|
|
|
|
; Command line utility to dump memory.
|
|
; Get start and optional end addresses from the command line, ie. XXXX[XXXX]
|
|
; Paging is implemented, 23 lines at a time, pressing U goes back 100H, pressing D scrolls down 100H
|
|
;
|
|
DUMPX: CALL HLHEX ; Get start address if present into HL
|
|
JR NC,DUMPX1
|
|
LD DE,(DUMPADDR) ; Setup default start and end.
|
|
JR DUMPX2
|
|
DUMPX1: INC DE
|
|
INC DE
|
|
INC DE
|
|
INC DE
|
|
PUSH HL
|
|
CALL HLHEX ; Get end address if present into HL
|
|
POP DE ; DE = Start address
|
|
JR NC,DUMPX4 ; Both present? Then display.
|
|
DUMPX2: LD A,(SCRNMODE)
|
|
OR A
|
|
LD HL,000A0h ; Make up an end address based on 160 bytes from start for 40 column mode.
|
|
JR Z,DUMPX3
|
|
LD HL,00140h ; Make up an end address based on 320 bytes from start for 80 column mode.
|
|
DUMPX3: ADD HL,DE
|
|
DUMPX4: EX DE,HL
|
|
;
|
|
; HL = Start
|
|
; DE = End
|
|
DUMP: LD A,23
|
|
DUMP0: LD (TMPCNT),A
|
|
LD A,(SCRNMODE) ; Configure output according to screen mode, 40/80 chars.
|
|
OR A
|
|
JR NZ,DUMP1
|
|
LD B,008H ; 40 Char, output 23 lines of 40 char.
|
|
LD C,017H
|
|
JR DUMP2
|
|
DUMP1: LD B,010h ; 80 Char, output 23 lines of 80 char.
|
|
LD C,02Fh
|
|
DUMP2: CALL NLPHL
|
|
DUMP3: CALL SPHEX
|
|
INC HL
|
|
PUSH AF
|
|
LD A,(DSPXY)
|
|
ADD A,C
|
|
LD (DSPXY),A
|
|
POP AF
|
|
CP 020h
|
|
JR NC,DUMP4
|
|
LD A,02Eh
|
|
DUMP4: CALL ?ADCN
|
|
CALL PRNT3
|
|
LD A,(DSPXY)
|
|
INC C
|
|
SUB C
|
|
LD (DSPXY),A
|
|
DEC C
|
|
DEC C
|
|
DEC C
|
|
PUSH HL
|
|
SBC HL,DE
|
|
POP HL
|
|
JR NC,DUMP9
|
|
DUMP5: DJNZ DUMP3
|
|
LD A,(TMPCNT)
|
|
DEC A
|
|
JR NZ,DUMP0
|
|
DUMP6: CALL GETKY ; Pause, X to quit, D to go down a block, U to go up a block.
|
|
OR A
|
|
JR Z,DUMP6
|
|
CP 'D'
|
|
JR NZ,DUMP7
|
|
LD A,8
|
|
JR DUMP0
|
|
DUMP7: CP 'U'
|
|
JR NZ,DUMP8
|
|
PUSH DE
|
|
LD DE,00100H
|
|
OR A
|
|
SBC HL,DE
|
|
POP DE
|
|
LD A,8
|
|
JR DUMP0
|
|
DUMP8: CP 'X'
|
|
JR Z,DUMP9
|
|
JR DUMP
|
|
DUMP9: LD (DUMPADDR),HL ; Store last address so we can just press D for next page,
|
|
CALL NL
|
|
RET
|
|
|
|
|
|
; Cmd tool to clear memory.
|
|
; Read cmd line for an init byte, if one not present, use 00H
|
|
;
|
|
INITMEMX: CALL _2HEX
|
|
JR NC,INITMEMX1
|
|
LD A,000H
|
|
INITMEMX1: PUSH AF
|
|
LDDE MSGINITM
|
|
LD HL,PRINTMSG
|
|
CALL BKSW1to6
|
|
LD HL,1200h
|
|
LD BC,0D000h - 1200h
|
|
POP DE
|
|
CLEAR1: LD A,D
|
|
LD (HL),A
|
|
INC HL
|
|
DEC BC
|
|
LD A,B
|
|
OR C
|
|
JP NZ,CLEAR1
|
|
RET
|
|
|
|
|
|
; Method to get the CMT parameters from the command line.
|
|
; The parameters which should be given are:
|
|
; XXXXYYYYZZZZ - where XXXX = Start Address, YYYY = End Address, ZZZZ = Execution Address.
|
|
; If the start, end and execution address parameters are correct, prompt for a filename which will be written into the CMT header.
|
|
; Output: Reg C = 0 - Success
|
|
; = 1 - Error.
|
|
GETCMTPARM: CALL READ4HEX ; Start address
|
|
JR C,GETCMT1
|
|
LD (DTADR),HL ; data adress buffer
|
|
LD B,H
|
|
LD C,L
|
|
CALL READ4HEX ; End address
|
|
JR C,GETCMT1
|
|
SBC HL,BC
|
|
INC HL
|
|
LD (SIZE),HL ; byte size buffer
|
|
CALL READ4HEX ; Execution address
|
|
JR C,GETCMT1
|
|
LD (EXADR),HL ; buffer
|
|
CALL NL
|
|
LDDE MSGSAVE ; 'FILENAME? '
|
|
LD HL,PRINTMSG
|
|
CALL BKSW2to6 ; Print out the filename.
|
|
LD DE,BUFER
|
|
CALL GETL
|
|
LD HL,BUFER+10
|
|
LD DE,NAME ; name buffer
|
|
LD BC,FNSIZE
|
|
LDIR ; C = 0 means success.
|
|
RET
|
|
GETCMT1: LD C,1 ; C = 1 means an error occured.
|
|
RET
|
|
|
|
|
|
; Method to read 4 bytes from a buffer pointed to by DE and attempt to convert to a 16bit number. If it fails, print out an error
|
|
; message and return with C set.
|
|
;
|
|
; Input: DE = Address of digits to conver.
|
|
; Output: HL = 16 bit number.
|
|
|
|
READ4HEX: CALL HLHEX
|
|
JR C,READ4HEXERR
|
|
INC DE
|
|
INC DE
|
|
INC DE
|
|
INC DE
|
|
OR A ; Clear carry flag.
|
|
RET
|
|
READ4HEXERR:LDDE MSGREAD4HEX ; Load up error message, print and exit.
|
|
READ4HEXPRE:LD HL,PRINTMSG
|
|
CALL BKSW1to6
|
|
SCF
|
|
RET
|
|
|
|
; SPACE PRINT AND DISP ACC
|
|
; INPUT:HL=DISP. ADR.
|
|
SPHEX: CALL PRNTS ; SPACE PRINT
|
|
LD A,(HL)
|
|
CALL PRTHX ; DSP OF ACC (ASCII)
|
|
LD A,(HL)
|
|
RET
|
|
|
|
; NEW LINE AND PRINT HL REG (ASCII)
|
|
NLPHL: CALL NL
|
|
CALL PRTHL
|
|
RET
|
|
; Text dump of a memory region as ASCII with page pausing.
|
|
; Called inter-bank from DUMPSDCARD (bank 2).
|
|
; Input: BC = Start address, DE = End address.
|
|
;
|
|
DCTEXTX: PUSH BC
|
|
POP HL ; HL = start.
|
|
OR A
|
|
SBC HL,DE
|
|
ADD HL,DE ; Check HL >= DE (end).
|
|
JR NC,DCTXT9
|
|
PUSH DE ; Save end address.
|
|
EX DE,HL ; DE = start, HL = end (but we need count).
|
|
OR A
|
|
SBC HL,DE ; HL = size.
|
|
LD B,H
|
|
LD C,L ; BC = byte count.
|
|
EX DE,HL ; HL = start address.
|
|
POP DE ; DE = end (not needed, but clean stack).
|
|
LD A,1
|
|
LD (TMPCNT),A ; Line counter.
|
|
;
|
|
DCTXT1: LD A,B
|
|
OR C
|
|
JR Z,DCTXT9 ; Done.
|
|
LD A,(HL)
|
|
INC HL
|
|
DEC BC
|
|
CP 00DH ; CR?
|
|
JR NZ,DCTXT3
|
|
CALL NL
|
|
LD A,(TMPCNT)
|
|
INC A
|
|
LD (TMPCNT),A
|
|
CP 23
|
|
JR C,DCTXT1
|
|
XOR A
|
|
LD (TMPCNT),A
|
|
PUSH HL
|
|
PUSH BC
|
|
DCTXT2: CALL GETKY
|
|
OR A
|
|
JR Z,DCTXT2
|
|
CP 'X'
|
|
POP BC
|
|
POP HL
|
|
JR Z,DCTXT9
|
|
JR DCTXT1
|
|
;
|
|
DCTXT3: CP 00AH ; LF? Skip.
|
|
JR Z,DCTXT1
|
|
CP 020H ; Non-printable? Skip.
|
|
JR C,DCTXT1
|
|
CP 07FH
|
|
JR NC,DCTXT1
|
|
CALL ?ADCN
|
|
CALL PRNT3
|
|
JR DCTXT1
|
|
;
|
|
DCTXT9: CALL NL
|
|
RET
|
|
|
|
; DUC helper: find file, read header, force load at 1200H, load data.
|
|
; Three separate bank switches to bank 2, with HL preserved via BC.
|
|
;
|
|
; Input: DE = filename/number string.
|
|
; Output: SIZE set (0 = not found/error), data loaded at 1200H.
|
|
;
|
|
LOADSDDUMP: ; Step 1: Find file. FINDSDX returns HL = dirent ptr.
|
|
; Flags are LOST through bank switch, so we detect failure via SIZE=0.
|
|
LD HL,FINDSDX
|
|
CALL BKSW3to2 ; HL = dirent ptr on success.
|
|
LD B,H ; Save dirent ptr in BC.
|
|
LD C,L ; BC is preserved through bank switches.
|
|
;
|
|
; Step 2: Read header. LOADSD9 needs HL = dirent ptr.
|
|
; LOADSD9BC in bank 2 does: LD H,B / LD L,C / JP LOADSD9.
|
|
LD HL,LOADSD9BC
|
|
CALL BKSW3to2 ; Header -> SIZE, SDSTARTSEC etc.
|
|
;
|
|
; Check if FINDSDX actually found the file (SIZE != 0).
|
|
LD A,(SIZE+1)
|
|
OR A
|
|
JR NZ,LDSDMP1 ; SIZE > 255, file was found.
|
|
LD A,(SIZE)
|
|
OR A
|
|
JR NZ,LDSDMP1 ; SIZE > 0, file was found.
|
|
; Not found. Print message.
|
|
LD HL,LOADSD3
|
|
CALL BKSW3to2
|
|
RET ; SIZE=0, caller detects this.
|
|
;
|
|
; Step 3: Override load address and load data.
|
|
LDSDMP1: LD HL,01200H
|
|
LD (SDLOADADDR),HL ; Force load to 1200H (RAM, writeable from any bank).
|
|
LD HL,LOADSD11
|
|
CALL BKSW3to2 ; Load file data.
|
|
RET
|
|
|
|
; Method to dump the contents of an SD Card file as hex+ASCII or plain text.
|
|
;
|
|
; Usage: DUC[H|T] <filenumber|filename>
|
|
; DUC0A - Hex dump file #0A (no header)
|
|
; DUCH0A - Hex dump with MZF header info
|
|
; DUCT0A - Text dump (printable ASCII)
|
|
; DUCTMYFILE - Text dump file named MYFILE
|
|
;
|
|
; Loads the file into memory at 1200H via LOADSDDUMP, then displays
|
|
; using hex DUMP or text DUCTEXTX routines (both in this bank).
|
|
; TMPSIZE (RAM) is used for the mode flag since bank ROM is read-only.
|
|
;
|
|
; Input: DE = Pointer to command-line arguments after "DC".
|
|
;
|
|
DUMPSDCARD: XOR A
|
|
LD (TMPSIZE),A ; Default = 0 (hex, no header). Uses RAM variable.
|
|
LD A,(DE)
|
|
CP 'T'
|
|
JR Z,DUMPSDM1 ; T = text mode.
|
|
CP 'H'
|
|
JR NZ,DUMPSD0 ; No flag letter, straight to load.
|
|
LD A,2 ; H = hex with header.
|
|
JR DUMPSDM2
|
|
DUMPSDM1: LD A,1 ; T = text mode.
|
|
DUMPSDM2: LD (TMPSIZE),A ; Store mode in RAM.
|
|
INC DE ; Skip flag letter.
|
|
;
|
|
; Validate that a file number or filename follows.
|
|
DUMPSD0: LD A,(DE)
|
|
CP 00DH ; CR = no argument given.
|
|
RET Z ; Exit silently if no file specified.
|
|
OR A
|
|
RET Z ; Also exit on NULL.
|
|
;
|
|
; Load file into memory at 1200H via LOADSDDUMP.
|
|
; HL = function addr, DE = parameter string (filename/number).
|
|
DUMPSD1: XOR A ; Clear SIZE so we can detect load failure.
|
|
LD (SIZE),A
|
|
LD (SIZE+1),A
|
|
CALL LOADSDDUMP ; Load file (prints "Not Found" on fail).
|
|
LD A,(SIZE+1) ; Check if anything was loaded.
|
|
OR A
|
|
JR NZ,DUMPSD1A ; SIZE > 255, definitely loaded.
|
|
LD A,(SIZE)
|
|
OR A
|
|
RET Z ; SIZE = 0, nothing loaded (not found or error).
|
|
;
|
|
; File loaded at 1200H. Clamp size to BD00H (CF00-1200) for display.
|
|
DUMPSD1A: LD HL,(SIZE)
|
|
LD DE,0BD00H
|
|
OR A
|
|
SBC HL,DE
|
|
JR C,DUMPSD1B ; Fits.
|
|
LD HL,0BD00H
|
|
LD (SIZE),HL
|
|
;
|
|
; Print MZF header info if H flag was given.
|
|
DUMPSD1B: LD A,(TMPSIZE) ; Read mode from RAM.
|
|
CP 2
|
|
JR NZ,DUMPSD2 ; No header requested.
|
|
;
|
|
; Print: "filename" CR Load:XXXX, Exec:YYYY, Size:ZZZZ CR
|
|
; 0xFF=stack[0]=Load, 0xFE=stack[1]=Exec, 0xFD=stack[2]=Size
|
|
; 0xFA=filename from BC
|
|
LDDE MSGDCHEAD
|
|
LD HL,(DTADRSTORE) ; Original MZF load address.
|
|
PUSH HL ; Stack param 1 (0xFF).
|
|
LD HL,(EXADR)
|
|
PUSH HL ; Stack param 2 (0xFE).
|
|
LD HL,(SIZE)
|
|
PUSH HL ; Stack param 3 (0xFD).
|
|
LD BC,NAME ; Filename pointer for 0xFA marker.
|
|
LD HL,PRINTMSG
|
|
CALL BKSW3to6
|
|
POP HL ; Clean 3 stack parameters.
|
|
POP HL
|
|
POP HL
|
|
;
|
|
; Display file contents. BC = start addr, DE = end addr.
|
|
DUMPSD2: LD BC,01200H ; Data always at 1200H.
|
|
LD HL,01200H
|
|
LD DE,(SIZE)
|
|
ADD HL,DE
|
|
EX DE,HL ; DE = end address.
|
|
LD A,(TMPSIZE) ; Read mode from RAM.
|
|
CP 1
|
|
JP Z,DCTEXTX ; Text mode.
|
|
JP DUMPBC ; Hex dump mode (with or without header).
|
|
|
|
;-------------------------------------------------------------------------------
|
|
; END OF MEMORY CMDLINE TOOLS FUNCTIONALITY
|
|
;-------------------------------------------------------------------------------
|
|
|
|
;-------------------------------------------------------------------------------
|
|
; START OF PRINTER CMDLINE TOOLS FUNCTIONALITY
|
|
;-------------------------------------------------------------------------------
|
|
PTESTX: LD A,(DE)
|
|
CP '&' ; plotter test
|
|
JR NZ,PTST1X
|
|
PTST0X: INC DE
|
|
LD A,(DE)
|
|
CP 'L' ; 40 in 1 line
|
|
JR Z,.LPTX
|
|
CP 'S' ; 80 in 1 line
|
|
JR Z,..LPTX
|
|
CP 'C' ; Pen change
|
|
JR Z,PENX
|
|
CP 'G' ; Graph mode
|
|
JR Z,PLOTX
|
|
CP 'T' ; Test
|
|
JR Z,PTRNX
|
|
;
|
|
PTST1X: CALL PMSGX
|
|
ST1X2: RET
|
|
.LPTX: LD DE,LLPT ; 01-09-09-0B-0D
|
|
JR PTST1X
|
|
..LPTX: LD DE,SLPT ; 01-09-09-09-0D
|
|
JR PTST1X
|
|
PTRNX: LD A,004h ; Test pattern
|
|
JR LE999
|
|
PLOTX: LD A,002h ; Graph mode
|
|
LE999: CALL LPRNTX
|
|
JR PTST0X
|
|
PENX: LD A,01Dh ; 1 change code (text mode)
|
|
JR LE999
|
|
;
|
|
;
|
|
; 1 char print to $LPT
|
|
;
|
|
; in: ACC print data
|
|
;
|
|
;
|
|
LPRNTX: LD C,000h ; RDAX test
|
|
LD B,A ; print data store
|
|
CALL RDAX
|
|
LD A,B
|
|
OUT (0FFh),A ; data out
|
|
LD A,080h ; RDP high
|
|
OUT (0FEh),A
|
|
LD C,001h ; RDA test
|
|
CALL RDAX
|
|
XOR A ; RDP low
|
|
OUT (0FEh),A
|
|
RET
|
|
;
|
|
; $LPT msg.
|
|
; in: DE data low address
|
|
; 0D msg. end
|
|
;
|
|
PMSGX: PUSH DE
|
|
PUSH BC
|
|
PUSH AF
|
|
PMSGX1: LD A,(DE) ; ACC = data
|
|
CALL LPRNTX
|
|
LD A,(DE)
|
|
INC DE
|
|
CP 00Dh ; end ?
|
|
JR NZ,PMSGX1
|
|
POP AF
|
|
POP BC
|
|
POP DE
|
|
RET
|
|
|
|
;
|
|
; RDA check
|
|
;
|
|
; BRKEY in to monitor return
|
|
; in: C RDA code
|
|
;
|
|
RDAX: IN A,(0FEh)
|
|
AND 00Dh
|
|
CP C
|
|
RET Z
|
|
CALL BRKEY
|
|
JR NZ,RDAX
|
|
LD SP,ATRB
|
|
JR ST1X2
|
|
|
|
; 40 CHA. IN 1 LINE CODE (DATA)
|
|
LLPT: DB 01H ; TEXT MODE
|
|
DB 09H
|
|
DB 09H
|
|
DB 0BH
|
|
DB 0DH
|
|
|
|
; 80 CHA. 1 LINE CODE (DATA)
|
|
SLPT: DB 01H ; TEXT MODE
|
|
DB 09H
|
|
DB 09H
|
|
DB 09H
|
|
DB 0DH
|
|
|
|
;-------------------------------------------------------------------------------
|
|
; END OF PRINTER CMDLINE TOOLS FUNCTIONALITY
|
|
;-------------------------------------------------------------------------------
|
|
|
|
;-------------------------------------------------------------------------------
|
|
; START OF I/O PORT CMDLINE TOOLS
|
|
;-------------------------------------------------------------------------------
|
|
|
|
;******************************************************************
|
|
; TRYHEX
|
|
; Convert ASCII hex char in A to nibble value 0-15.
|
|
; Returns: carry set = valid hex, A = value (0-15).
|
|
; carry clear = not a hex digit, A unchanged.
|
|
;******************************************************************
|
|
TRYHEX: CP '0'
|
|
JR C,TRYHEX_NO
|
|
CP '9'+1
|
|
JR C,TRYHEX_DIG
|
|
CP 'A'
|
|
JR C,TRYHEX_NO
|
|
CP 'F'+1
|
|
JR C,TRYHEX_AF
|
|
TRYHEX_NO: OR A ; Clear carry = not hex.
|
|
RET
|
|
TRYHEX_DIG: SUB '0'
|
|
SCF ; Set carry = valid hex.
|
|
RET
|
|
TRYHEX_AF: SUB 'A'-10
|
|
SCF
|
|
RET
|
|
|
|
;******************************************************************
|
|
; PARSEHEX
|
|
; Parse 2 or 4 hex digits from (DE) into HL.
|
|
; Returns: carry clear = success, HL = value, DE past digits.
|
|
; carry set = error (not 2 or 4 hex digits).
|
|
;******************************************************************
|
|
PARSEHEX: LD HL,0
|
|
LD B,0 ; Digit count.
|
|
PARSEHX_LP: LD A,(DE)
|
|
CALL TRYHEX
|
|
JR NC,PARSEHX_DN ; Not hex = done reading digits.
|
|
ADD HL,HL ; HL <<= 4
|
|
ADD HL,HL
|
|
ADD HL,HL
|
|
ADD HL,HL
|
|
OR L ; Add new nibble.
|
|
LD L,A
|
|
INC DE
|
|
INC B
|
|
JR PARSEHX_LP
|
|
PARSEHX_DN: LD A,B
|
|
CP 2
|
|
JR Z,PARSEHX_OK
|
|
CP 4
|
|
JR Z,PARSEHX_OK
|
|
SCF ; Error: not 2 or 4 digits.
|
|
RET
|
|
PARSEHX_OK: OR A ; Clear carry = success.
|
|
RET
|
|
|
|
;******************************************************************
|
|
; INX I/O Port Input Command
|
|
; Syntax: IN<port>[,<port>...]
|
|
; Port = 2 or 4 hex digit I/O port address.
|
|
; Reads each port via IN A,(C) and prints the value.
|
|
;******************************************************************
|
|
INX: CALL NL
|
|
INX_LP: CALL PARSEHEX ; HL = port number.
|
|
RET C ; Bad input, exit.
|
|
LD B,H ; BC = 16-bit port.
|
|
LD C,L
|
|
IN A,(C) ; Read from port.
|
|
CALL PRTHX ; Print value as 2-digit hex.
|
|
LD A,(DE) ; Check for comma separator.
|
|
CP ','
|
|
JR NZ,INX_END
|
|
CALL PRNTS ; Space between values.
|
|
INC DE ; Skip comma.
|
|
JR INX_LP
|
|
INX_END: CALL NL
|
|
RET
|
|
|
|
;******************************************************************
|
|
; OUTX I/O Port Output Command
|
|
; Syntax: OUT<port>:<value>[,<port>:<value>...]
|
|
; Port = 2 or 4 hex digit I/O port address.
|
|
; Value = 2 hex digit byte value.
|
|
; Writes each value to the corresponding port via OUT (C),A.
|
|
;******************************************************************
|
|
OUTX: CALL NL
|
|
OUTX_LP: CALL PARSEHEX ; HL = port number.
|
|
RET C ; Bad input, exit.
|
|
LD B,H ; BC = 16-bit port.
|
|
LD C,L
|
|
LD A,(DE) ; Expect colon separator.
|
|
CP ':'
|
|
RET NZ ; No colon, exit.
|
|
INC DE ; Skip colon.
|
|
CALL _2HEX ; A = 2-digit hex value (DE auto-advanced).
|
|
RET C ; Bad value, exit.
|
|
OUT (C),A ; Write to port.
|
|
LD A,(DE) ; Check for comma separator.
|
|
CP ','
|
|
JR NZ,OUTX_END
|
|
INC DE ; Skip comma.
|
|
JR OUTX_LP
|
|
OUTX_END: CALL NL
|
|
RET
|
|
|
|
;-------------------------------------------------------------------------------
|
|
; END OF I/O PORT CMDLINE TOOLS
|
|
;-------------------------------------------------------------------------------
|
|
|
|
;--------------------------------------
|
|
;
|
|
; Message table - Refer to bank 6 for
|
|
; all messages.
|
|
;
|
|
;--------------------------------------
|
|
|
|
; RomDisk, top 8 bytes are used by the control registers when enabled so dont use the space.
|
|
IF BUILD_ROMDISK+BUILD_PICOZ80 = 1
|
|
ALIGN 0EFF8h
|
|
ORG 0EFF8h
|
|
DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
|
|
ENDIF
|
|
|
|
IF BUILD_SFD700 = 1
|
|
ALIGN 0F000H
|
|
ENDIF
|