Files
MZ80A_RFS/software/asm/rfs.asm

1348 lines
65 KiB
NASM

;--------------------------------------------------------------------------------------------------------
;-
;- Name: rfs.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-2023 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.
; July 2020 - Updated for the v2.1 hardware. RFS can run with a tranZPUter board with
; or without the K64 I/O processor. RFS wont use the K64 processor all
; operations are done by the Z80 under RFS.
;- April 2021- Updates for the v2.1 RFS board.
;-
;--------------------------------------------------------------------------------------------------------
;- 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/>.
;--------------------------------------------------------------------------------------------------------
; Bring in additional resources.
INCLUDE "rfs_definitions.asm"
;============================================================
;
; USER ROM BANK 0 - Main RFS Entry point and functions.
;
;============================================================
ORG UROMADDR
;--------------------------------
; Common code spanning all banks.
;--------------------------------
ROMFS: NOP
LD B,16 ; If we read the bank control reset register 15 times then this will enable bank control and then the 16th read will reset all bank control registers to default.
ROMFS_0: LD A,(BNKCTRLRST)
DJNZ ROMFS_0 ; Apply the default number of coded latch reads to enable the bank control registers.
LD A,BNKCTRLDEF ; Set coded latch, SDCS high, BBMOSI to high and BBCLK to high which enables SDCLK.
LD (BNKCTRL),A
LD (ROMCTL),A ; Save to memory the value in the bank control register - this register is used for SPI etc so need to remember its setting.
XOR A ; We shouldnt arrive here after a reset, if we do, select UROM bank 0
LD (BNKSELMROM),A
LD (BNKSELUSER),A ; and start up - ie. SA1510 Monitor - this occurs as User Bank 0 is enabled and the jmp to 0 is coded in it.
JP ROMFS_1 ; Skip the reset vector.
JP 00000H ; Other banks will switch at this point thus forcing a full reset.
ALIGN_NOPS UROMBSTBL
;------------------------------------------------------------------------------------------
; 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.
;------------------------------------------------------------------------------------------
;
BKSW0to0: PUSH AF
LD A, ROMBANK0 ; Calling bank (ie. us).
PUSH AF
LD A, ROMBANK0 ; Required bank to call.
JR BKSW0_0
BKSW0to1: PUSH AF
LD A, ROMBANK0 ; Calling bank (ie. us).
PUSH AF
LD A, ROMBANK1 ; Required bank to call.
JR BKSW0_0
BKSW0to2: PUSH AF
LD A, ROMBANK0 ; Calling bank (ie. us).
PUSH AF
LD A, ROMBANK2 ; Required bank to call.
JR BKSW0_0
BKSW0to3: PUSH AF
LD A, ROMBANK0 ; Calling bank (ie. us).
PUSH AF
LD A, ROMBANK3 ; Required bank to call.
JR BKSW0_0
BKSW0to4: PUSH AF
LD A, ROMBANK0 ; Calling bank (ie. us).
PUSH AF
LD A, ROMBANK4 ; Required bank to call.
JR BKSW0_0
BKSW0to5: PUSH AF
LD A, ROMBANK0 ; Calling bank (ie. us).
PUSH AF
LD A, ROMBANK5 ; Required bank to call.
JR BKSW0_0
BKSW0to6: PUSH AF
LD A, ROMBANK0 ; Calling bank (ie. us).
PUSH AF
LD A, ROMBANK6 ; Required bank to call.
JR BKSW0_0
BKSW0to7: PUSH AF
LD A, ROMBANK0 ; Calling bank (ie. us).
PUSH AF
LD A, ROMBANK7 ; Required bank to call.
;
BKSW0_0: PUSH HL ; Place function to call on stack
LD HL, BKSWRET0 ; Place bank switchers return address on stack.
EX (SP),HL
LD (TMPSTACKP),SP ; Save the stack pointer as some old code corrupts it.
LD (BNKSELUSER), A ; Repeat the bank switch B times to enable the bank control register and set its value.
JP (HL) ; Jump to required function.
BKSWRET0: POP AF ; Get bank which called us.
LD (BNKSELUSER), A ; Return to that bank.
POP AF
RET ; Return to caller.
ALIGN RFSJMPTABLE
ORG RFSJMPTABLE
;------------------------------------------------------------------------------------------
; Enhanced function Jump table.
; This table is generally used by the monitor ROM to call functions within the User ROM.
;------------------------------------------------------------------------------------------
PRTMZF: JP _PRTMZF ; UROMADDR+80H - Print out an MZF header stored in the IBUFE location.
PRTDBG: JP _PRTDBG ; UROMADDR+83H - Print out debug information, if enabled.
CMT_RDINF: JP _CMT_RDINF ; UROMADDR+86H - Tape/SD intercept handler - Read Header
CMT_RDDATA: JP _CMT_RDDATA ; UROMADDR+89H - Tape/SD intercept handler - Read Data
CMT_WRINF: JP _CMT_WRINF ; UROMADDR+80H - Tape/SD intercept handler - Write Header
CMT_WRDATA: JP _CMT_WRDATA ; UROMADDR+8FH - Tape/SD intercept handler - Write Data
CMT_VERIFY: JP _CMT_VERIFY ; UROMADDR+92H - Tape/SD intercept handler - Verify Data
CMT_DIR: JP _CMT_DIR ; UROMADDR+95H - SD card directory listing command.
CNV_ATOS: JP _CNV_ATOS ; UROMADDR+98H - Convert string from Ascii to Sharp Ascii
;-----------------------------------------
;-----------------------------------------
; Initialisation and startup.
;-----------------------------------------
;
; NB. Bank control registers are left selected. Any software needing access to the top 8 bytes of a
; ROM/RAM page need to disable them, perform their actions then re-emable.
;
JP ROMFS_1 ; Skip the reset vector.
;
ROMFS_1:
LD A, (ROMBK1) ; Ensure all banks are at default
CP 8 ; If the ROMBK1 value is 255, an illegal value, then the machine has just started so initialise memory.
JR C, ROMFS_3
XOR A ; Clear the lower stack space as we use it for variables.
LD B, 7*8
LD HL, 01000H
ROMFS_2: LD (HL),A
INC HL
DJNZ ROMFS_2
LD A,BNKCTRLDEF ; Set coded latch, SDCS high, BBMOSI to high and BBCLK to high which enables SDCLK.
LD (ROMCTL),A ; Save to memory the value in the bank control register - this register is used for SPI etc so need to remember its setting.
LD A,(ROMBK1)
ROMFS_3: LD (BNKSELMROM),A ; start up.
LD A, (ROMBK2)
LD (BNKSELUSER),A
;-------------------------------------------------------------------------------
; START OF RFS INITIALISATION AND COMMAND ENTRY PROCESSOR FUNCTIONALITY.
;-------------------------------------------------------------------------------
;
; Replacement command processor in place of the SA1510 command processor.
;
MONITOR: IF FUSIONX_ENA = 0
IN A,(CPLDINFO) ; See if a tranZPUter board is present.
AND 0E7H ; Mask out the CPLD Version and host HW.
LD C,A
CP 020H ; Upper bits specify the version, should be at least 1.
JR C,CHKTZ1
AND 007H ; Get Hardware, should be an MZ-80A for RFS.
CP MODE_MZ80A
LD A,C
JR Z,CHKTZ1
XOR A
CHKTZ1: AND 0E0H
ELSE
XOR A
ENDIF
LD (TZPU), A ; Flag = 0 if no tranZPUter present otherwise contains version (1 - 15).
LD HL,DSPCTL ; Setup address of display control register latch.
;
XOR A ; Set the initial SDCFS active drive number.
LD (SDDRIVENO),A
;
LD A, (ROMBK1)
CP 1
JR Z, SET80CHAR
CP 0
JR NZ, SIGNON
;
SET40CHAR: LD A, 0 ; Using MROM in Bank 0 = 40 char mode.
LD E,(HL) ; Dummy operation to enable latch write via multivibrator.
LD (HL), A
LD (SCRNMODE), A
LD (SPAGE), A ; Allow MZ80A scrolling
JR SIGNON
SET80CHAR: LD A, 128 ; Using MROM in Bank 1 = 80 char mode.
LD E,(HL) ; Dummy operation to enable latch write via multivibrator.
LD (HL), A
LD A, 1
LD (SCRNMODE), A
LD A, 0FFH
LD (SPAGE), A ; MZ80K Scrolling in 80 column mode for time being.
;
SIGNON: LD A,0C4h ; Move cursor left to overwrite part of SA-1510 monitor banner.
LD E,004h ; 2 times.
SIGNON1: CALL DPCT
DEC E
JR NZ,SIGNON1
;
LD A,(TZPU)
OR A
JR Z,SIGNON2
LD DE,MSGSONTZ
JR SIGNON3
;
SIGNON2: LD DE,MSGSON ; Sign on message,
SIGNON3: LD HL,PRINTMSG
CALL BKSW0to6
; JR ST1X
; Initialise SD card, report any errors.
LD HL, SDINIT ; SD Card Initialisation
CALL BKSW0to2 ; Call the initialisation routine.
LD A,L
OR A ; 0 = No error.
JR Z,ST1X
; Place error code in C to print as a number and report with the error message.
ADD A,'0'
LD C,A
LD DE,MSGSDINITER
LD HL,PRINTMSG
CALL BKSW0to6
; Command processor, table based.
; A line is inpt then a comparison made with entries in the table. If a match is found then the bank and function
; address are extracted and a call to the function @ given bank made. The commands can be of variable length
; but important to not that longer commands using the same letters as shorter commands must appear first in the table.
;
ST1X: CALL NL ; Command line monitor extension.
LD A,'*'
CALL PRNT
LD DE,BUFER
CALL GETL
;
LD A,(BUFER+1) ; Drive change number 0..9. Each number represents an RFS SDCFS Drive number.
CP '0'
JR C,CMDCMP
CP ':'
JR NC,CMDCMP
SUB '0'
LD D,A
LD A,(BUFER+2)
CP CR ; If a CR is present then we match, a drive selection number was entered.
LD A,D
JR NZ,CMDCMP
; Simple command, just update the active drive number.
LD (SDDRIVENO),A
JR ST1X
;
CMDCMP: XOR A ; Clear the result variable used by interbank calls. Some functions set this variable and we act on it.
LD (RESULT),A
LD HL,CMDTABLE
CMDCMP0: LD DE,BUFER+1 ; First command byte after the * prompt.
LD A,(HL)
CP 000H
JR Z,ST1X ; Skip processing on lines where just CR pressed.
BIT 7,A ; Bit 7 set on command properties indicates table end, exit if needed.
JR NZ,CMDNOCMP
LD C,A ; Command properties into C
SET 6,C ; Assume command match.
AND 007H ; Mask out bytes in command mask.
LD B,A ; Number of bytes in command.
INC HL
CMDCMP1: LD A,(DE) ; Compare all bytes and reset match bit if we find a difference.
CP (HL)
JR Z, CMDCMP2
RES 6,C ; No command match.
CMDCMP2: INC DE
INC HL
DJNZ CMDCMP1
BIT 6,C ; Bit 7 is still set then we have a command match.
JR NZ,CMDCMP3
INC HL
INC HL ; Skip over function address
JR CMDCMP0 ; Try match next command.
CMDCMP3: LD A,(HL) ; Command function address into HL
INC HL
LD H,(HL)
LD L,A
PUSH HL
LD (TMPADR),DE ; Store the key buffer location where arguments start.
LD A,C
SRL A
SRL A
SRL A
AND 007H ; Mask out just the bank number of the command.
CP 000H
JR Z,CMDCMP6 ; No point using the bank switching logic for the current bank 0.
LD B,A
LD HL,BKSW0to0 ; Base address of bank switching functions.
LD DE,BKSW0to1 - BKSW0to0 ; DE is the number of bytes between bank switch calls.
OR A
JR Z,CMDCMP5
CMDCMP4: ADD HL,DE
DJNZ CMDCMP4
CMDCMP5: EX DE,HL ; Address of bank switch function into DE.
POP HL ; Get address of command into HL.
LD BC,CMDCMPEND
PUSH BC ; Address to return to after command is executed.
PUSH DE ; Now jump to DE which will switch to the correct bank and execute function at HL.
LD DE,(TMPADR)
RET
CMDCMP6: LD DE,CMDCMPEND ; Put return address onto stack.
PUSH DE
LD DE,(TMPADR) ; For the current bank, just jump to the function.
JP (HL)
CMDNOCMP: LD DE,MSGBADCMD
LD HL,PRINTMSG
CALL BKSW0to6
CMDCMPEND: LD A,(RESULT)
CP 0FEH ; A Result code of 0FEH means execute loaded code, address is in the CMT Header EXADR location.
JP NZ,ST1X
LD HL,(EXADR)
JP (HL)
; Monitor command table. This table contains the list of recognised commands along with the
; handler function and bank in which it is located.
;
; 7 6 5:3 2:0
; END MATCH BANK SIZE
CMDTABLE: DB 000H | 000H | 000H | 002H ; Bit 2:0 = Command Size, 5:3 = Bank, 6 = Command match, 7 = Command table end.
DB "40" ; 40 Char screen mode.
DW SETMODE40
DB 000H | 000H | 000H | 002H
DB "80" ; 80 Char screen mode.
DW SETMODE80
;DB 000H | 000H | 000H | 004H
;DB "7008" ; Switch to 80 column MZ700 mode.
;DW SETMODE7008
;DB 000H | 000H | 000H | 003H
;DB "700" ; Switch to 40 column MZ700 mode.
;DW SETMODE700
DB 000H | 000H | 000H | 005H
DB "BASIC" ; Load and run BASIC SA-5510.
DW LOADBASIC
DB 000H | 000H | 020H | 001H
DB 'B' ; Bell.
DW SGX
DB 000H | 000H | 000H | 003H
DB "CPM" ; Load and run CPM.
DW LOADCPM
DB 000H | 000H | 018H | 002H
DB "CP" ; Copy Memory.
DW MCOPY
DB 000H | 000H | 018H | 001H
DB 'C' ; Clear Memory.
DW INITMEMX
DB 000H | 000H | 018H | 001H
DB 'D' ; Dump Memory.
DW DUMPX
DB 000H | 000H | 010H | 002H
DB "EC" ; Erase file.
DW ERASESD
DB 000H | 000H | 008H | 001H
DB 'F' ; RFS Floppy boot code.
DW FLOPPY
DB 000H | 000H | 008H | 001H
DB 0AAH ; Original Floppy boot code.
DW FDCK
DB 000H | 000H | 030H | 001H
DB 'H' ; Help screen.
DW HELP
DB 000H | 000H | 000H | 002H
DB "IR" ; List ROM directory.
DW DIRROM
DB 000H | 000H | 010H | 002H
DB "IC" ; List SD Card directory.
DW DIRSDCARD
DB 000H | 000H | 000H | 001H
DB 'J' ; Jump to address.
DW GOTOX
DB 000H | 000H | 020H | 004H
DB "LTNX" ; Load from CMT without auto execution.
DW LOADTAPENX
DB 000H | 000H | 020H | 002H
DB "LT" ; Load from CMT
DW LOADTAPE
DB 000H | 000H | 000H | 004H
DB "LRNX" ; Load from ROM without auto execution.
DW LOADROMNX
DB 000H | 000H | 000H | 002H
DB "LR" ; Load from ROM
DW LOADROM
DB 000H | 000H | 010H | 004H
DB "LCNX" ; Load from SDCARD without auto execution.
DW LOADSDCARDX
DB 000H | 000H | 010H | 002H
DB "LC" ; Load from SD CARD
DW LOADSDCARD
DB 000H | 000H | 020H | 001H
DB "L" ; Original Load from CMT
DW LOADTAPE
DB 000H | 000H | 018H | 001H
DB 'M' ; Edit Memory.
DW MCORX
DB 000H | 000H | 018H | 001H
DB 'P' ; Printer test.
DW PTESTX
DB 000H | 000H | 038H | 001H
DB 'R' ; Memory test.
DW MEMTEST
DB 000H | 000H | 018H | 004H
DB "SD2T" ; Copy SD Card to Tape.
DW SD2TAPE
DB 000H | 000H | 010H | 002H
DB "SC" ; Save to SD CARD
DW SAVESDCARD
DB 000H | 000H | 020H | 002H
DB "ST" ; Save to CMT
DW SAVEX
DB 000H | 000H | 020H | 001H
DB 'S' ; Save to CMT
DW SAVEX
DB 000H | 000H | 000H | 004H
DB "TEST" ; A test function used in debugging.
DW LOCALTEST
DB 000H | 000H | 018H | 004H
DB "T2SD" ; Copy Tape to SD Card.
DW TAPE2SD
DB 000H | 000H | 038H | 001H
DB 'T' ; Timer test.
DW TIMERTST
DB 000H | 000H | 000H | 001H
DB 'V' ; Verify CMT Save.
DW VRFYX
DB 000H | 000H | 000H | 001H
DB 'X' ; Exchange to hi load rom so DRAM = 0000:0CFFF
DW HIROM
DB 080H | 000H | 000H | 001H
;-------------------------------------------------------------------------------
; END OF RFS INITIALISATION AND COMMAND ENTRY PROCESSOR FUNCTIONALITY.
;-------------------------------------------------------------------------------
; A method used when testing hardware, scope and code will change but one of its purposes is to generate a scope signal pattern.
;
LOCALTEST: LD A,64
LD (0EFFBH),A
JP LOCALTEST
;-------------------------------------------------------------------------------
; START OF RFS COMMAND FUNCTIONS.
;-------------------------------------------------------------------------------
; Method to branch execution to a user given address.
;
GOTOX: CALL HEXIYX
JP (HL)
HEXIYX: EX (SP),IY
POP AF
CALL HLHEX
JR C,HEXIYX2
JP (IY)
HEXIYX2: POP AF ; Waste the intermediate caller address
RET
;====================================
;
; Screen Width Commands
;
;====================================
HIROM: LD A, (MEMSW) ; Swap ROM into high range slot.
LD A, ROMBANK2
LD (ROMBK1),A ; Save bank being enabled.
LD (BNKSELMROM),A ; Switch to the hiload rom in bank 2.
JP 0C000H
SETMODE40: LD A, ROMBANK0 ; Switch to 40Char monitor.
LD (ROMBK1),A
LD (BNKSELMROM),A
LD HL,DSPCTL ; Setup address of display control register latch.
LD A, 0
LD E,(HL) ; Dummy operation to enable latch write via multivibrator.
LD (HL), A
JP MONIT
SETMODE80: LD A, ROMBANK1 ; Switch to 80char monitor.
LD (ROMBK1),A
LD (BNKSELMROM),A
LD HL,DSPCTL ; Setup address of display control register latch.
LD A, 128
LD E,(HL) ; Dummy operation to enable latch write via multivibrator.
LD (HL), A
JP MONIT
NOTZPU: LD DE,MSGNOTZINST ; No tranZPUter installed.
LD HL,PRINTMSG
CALL BKSW0to6
RET
; The RFS depends on variables stored in unused parts of the Monitor scratch area.
; When switching into a compatibility mode the memory is switched and these variables go
; out of scope. This routine clears the memory and sets any crucial variables after
; memory switch so that a restart functions as expected.
;
SETMODECLR: POP HL ; Get return address, will go OOS after memory mode change.
LD A,TZMM_COMPAT
OUT (MMCFG),A ; Set memory mode to compatibility.
XOR A ; Clear out the RFS variable area in the tranZPUter memory.
LD DE, 01000H
LD B, 030H
SETCLR_1: LD (DE),A
INC DE
DJNZ SETCLR_1
JP (HL) ; Return to caller.
; Command to switch to the MZ700 compatibility mode with 80 column display.
;
;SETMODE7008:LD A,(TZPU) ; Check there is a tranZPUter card installed.
; OR A
; JR Z,NOTZPU
; LD HL,DSPCTL ; Setup address of display control register latch.
; LD A, 128 ; Setup for 80char display.
; LD E,(HL) ; Dummy operation to enable latch write via multivibrator.
; LD (HL), A
; CALL SETMODECLR ; Set memory mode and clear variable area.
; LD A,ROMBANK5 ; Select the 80 column version of the 1Z-013A ROM.
;SETMODE_2: LD (ROMBK1),A
; LD (BNKSELMROM),A
; LD A,MODE_MZ700 ; Set the CPLD compatibility mode.
;SETMODE_3: OUT (CPLDCFG),A
; JP MONIT ; Cold start the monitor.
; Command to switch to the MZ700 compatibility mode with original 40 column display.
;
;SETMODE700: LD A,(TZPU) ; Check there is a tranZPUter card installed.
; OR A
; JR Z,NOTZPU
; LD HL,DSPCTL ; Setup address of display control register latch.
; LD A, 0 ; Setup for 40char display.
; LD E,(HL) ; Dummy operation to enable latch write via multivibrator.
; LD (HL), A
; CALL SETMODECLR ; Set memory mode and clear variable area.
; LD A,ROMBANK4 ; Select the 40 column version of the 1Z-013A ROM.
; JR SETMODE_2
;====================================
;
; ROM File System Commands
;
;====================================
; HL contains address of block to check.
ISMZF: PUSH BC
PUSH DE
PUSH HL
;
LD A,(HL)
CP OBJCD ; Only interested in machine code images.
JR NZ, ISMZFNOT
;
INC HL
LD DE,NAME ; Checks to confirm this is an MZF header.
LD B,FNSIZE ; Maximum of 17 characters, including terminator in filename.
ISMZFNXT: LD A,(HL)
LD (DE),A
CP 00DH ; If we find a terminator then this indicates potentially a valid name.
JR Z, ISMZFNXT3
CP 000H ; Same applies for NULL terminator.
JR Z, ISMZFNXT3
CP 020H ; >= Space
JR C, ISMZFNOT
CP 05DH ; =< ]
JR C, ISMZFNXT3
ISMZFNXT2: CP 091H
JR C, ISMZFNOT ; DEL or > 0x7F, cant be a valid filename so this is not an MZF header.
ISMZFNXT3: INC DE
INC HL
DJNZ ISMZFNXT
ISMZFYES: CP A ; Set zero flag to indicate match.
ISMZFNOT: POP HL
POP DE
POP BC
RET
_PRTDBG: IF ENADEBUG = 1
PUSH HL
PUSH DE
PUSH BC
PUSH AF
LD A,(ROMBK1)
LD (BNKSELMROM),A ; Set the MROM bank back to original.
CALL PRTHL ; HL
LD A, ' '
CALL PRNT
LD H,B
LD L,C
CALL PRTHL ; BC
LD A, ' '
CALL PRNT
LD H,D
LD L,E
CALL PRTHL ; DE
LD A, ' '
CALL PRNT
POP HL ; Get AF into HL.
PUSH HL
CALL PRTHL ; AF
LD A, ' '
CALL PRNT
LD A, ':'
CALL PRNT
LD A, ' '
CALL PRNT
; CALL NL
; CALL GETKY
LD A,(WRKROMBK1)
LD (BNKSELMROM),A ; Set the MROM bank back to scanned bank.
POP AF
POP BC
POP DE
POP HL
RET
ENDIF
_PRTMZF: PUSH BC
PUSH DE
PUSH HL
;
LD A,(ROMBK1) ; Ensure main MROM is switched in.
LD (BNKSELMROM),A
;
LD A,(SCRNMODE)
CP 0
LD H,47
JR Z,PRTMZF0
LD H,93
PRTMZF0: LD A,(TMPLINECNT) ; Pause if we fill the screen.
LD E,A
INC E
CP H
JR NZ,PRTNOPAUSE
LD E, 0
PRTPAUSE: CALL GETKY
CP ' '
JR Z,PRTNOPAUSE
CP 'X' ; Exit from listing.
LD A,001H
JR Z,PRTMZF4
JR PRTPAUSE
PRTNOPAUSE: LD A,E
LD (TMPLINECNT),A
;
LD A, D ; Print out file number and increment.
CALL PRTHX
LD A, '.' ; File type is MACHINE CODE program.
CALL PRNT
LD DE,NAME ; Print out filename.
LD B,FNSIZE ; Maximum size of filename.
_PRTMSG: LD A,(DE)
INC DE
CP 000H
JR Z,_PRTMSGE
CP 00DH
JR Z,_PRTMSGE
CALL PRNT
DJNZ _PRTMSG
;
_PRTMSGE: LD HL, (DSPXY)
;
LD A,L
CP 20
LD A,20
JR C, PRTMZF2
;
LD A,(SCRNMODE) ; 40 Char mode? 2 columns of filenames displayed so NL.
CP 0
JR Z,PRTMZF1
;
LD A,L ; 80 Char mode we print 4 columns of filenames.
CP 40
LD A,40
JR C, PRTMZF2
;
LD A,L
CP 60
LD A,60
JR C, PRTMZF2
;
PRTMZF1: CALL NL
JR PRTMZF3
PRTMZF2: LD L,A
LD (DSPXY),HL
PRTMZF3: XOR A
PRTMZF4: OR A
PUSH AF
LD A, (WRKROMBK1)
LD (BNKSELMROM),A
POP AF
POP HL
POP DE
POP BC
RET
; Method to list the directory of the ROM devices.
;
DIRROM: ;DI ; Disable interrupts as we are switching out the main rom.
;
LD A,1 ; Account for the title.
LD (TMPLINECNT),A
;
LD DE,MSGRDIRLST ; Print out header.
LD HL,PRINTMSG
CALL BKSW0to6
; D = File sequence number.
LD D,0 ; File numbering start.
;
; Get directory of User ROM.
;
LD A,ROMBANK3
LD (WRKROMBK1),A
LD (BNKSELMROM),A
CALL DIRMROM
;
; Scan MROM Bank
; B = Bank Page
; C = Block in page
;
LD B,MROMPAGES ; First 8 pages are reserved in MROM bank.
LD C,0 ; Block in page.
;
DIRNXTPG: LD A,B
LD (WRKROMBK1), A
LD (BNKSELMROM),A ; Select bank.
PUSH BC ; Preserve bank count/block number.
PUSH DE ; Preserve file numbering.
LD A,C
IF RFSSECTSZ >= 512
RLCA
ENDIF
IF RFSSECTSZ >= 1024
RLCA
ENDIF
LD B,A
LD C,0
LD HL,RFS_ATRB ; Add block offset to get the valid block address.
ADD HL,BC
CALL ISMZF
POP DE
POP BC
JR NZ, DIRNOTMZF
;
CALL PRTMZF
JR NZ,DIRNXTPGX
INC D ; Next file sequence number.
;
DIRNOTMZF: INC C ; Next block.
LD A,C
CP MROMSIZE/RFSSECTSZ ; Max blocks per page reached?
JR C, DIRNXTPG2
LD C,0
INC B
DIRNXTPG2: LD A,B
CP 080h ; MROM has 128 banks of 4K, so stop when we reach 128.
JR NZ, DIRNXTPG
DIRNXTPGX: LD A,(ROMBK1)
LD (BNKSELMROM),A ; Set the MROM bank back to original.
;EI ; No need to block interrupts now as MROM bank restored.
RET ; End of scan, return to monitor
; In:
; HL = filename
; D = File sequence number.
; Out:
; B = Bank Page file found
; C = Block where found.
; D = File sequence number.
; Z set if found.
FINDMZF: PUSH DE
LD (TMPADR), HL ; Save name of program to load.
EX DE, HL ; String needed in DE for conversion.
LD HL,0FFFFh ; Tag the filenumber as invalid.
LD (TMPCNT), HL
CALL ConvertStringToNumber ; See if a file number was given instead of a filename.
JR NZ, FINDMZF0 ;
LD (TMPCNT), HL ; Store filenumber making load by filenumber valid.
;
; Scan MROM Bank
; B = Bank Page
; C = Block in page
;
FINDMZF0: POP DE ; Get file sequence number in D.
LD B,MROMPAGES ; First 4 pages are reserved in User ROM bank.
LD C,0 ; Block in page.
FINDMZF1: LD A,B
LD (WRKROMBK1), A
LD (BNKSELMROM),A ; Select bank.
FINDMZF2: PUSH BC ; Preserve bank count/block number.
PUSH DE ; Preserve file numbering.
LD HL,RFS_ATRB ; Add block offset to get the valid block.
LD A,C
IF RFSSECTSZ >= 512
RLCA
ENDIF
IF RFSSECTSZ >= 1024
RLCA
ENDIF
LD B,A
LD C,0
ADD HL,BC
CALL ISMZF
POP DE
POP BC
LD A,(ROMBK1)
LD (BNKSELMROM),A ; Set the MROM bank back to original.
JR NZ, FINDMZF4 ; Z set if we found an MZF record.
INC HL ; Save address of filename.
PUSH HL
; CALL PRTMZF ; Print out for confirmation.
LD HL,(TMPCNT)
LD A,H
CP 0FFh ; If TMPCNT tagged as 0xFF then we dont have a filenumber so must match filename.
JR Z, FINDMZF3
LD A,L ; Check file number, load if match
CP D
JR NZ, FINDMZF3 ; Check name just in case.
POP HL
JR FINDMZFYES ; Else the filenumber matches so load the file.
FINDMZF3: POP HL
PUSH DE
PUSH BC
LD DE,(TMPADR) ; Original DE put onto stack, original filename into HL
LD BC,FNSIZE
LD A,(WRKROMBK1)
LD (BNKSELMROM),A ; Select correct bank for comparison.
CALL CMPSTRING
POP BC
POP DE
JR Z, FINDMZFYES
INC D ; Next file sequence number.
FINDMZF4: INC C
LD A,C
CP MROMSIZE/RFSSECTSZ ; Max blocks per page reached?
JR C, FINDMZF5
LD C,0
INC B
FINDMZF5: LD A,B
CP 080h ; MROM has 128 banks of 4K, so stop when we get to 128.
JR NZ, FINDMZF1
INC B
JR FINDMZFNO
FINDMZFYES: ; Flag set by previous test.
FINDMZFNO: PUSH AF
LD A,(ROMBK1)
LD (BNKSELMROM),A ; Set the MROM bank back to original.
POP AF
RET
; Load Program from ROM
; IN DE Name of program to load.
; OUT zero Set if string1 = string2, reset if string1 != string2.
; carry Set if string1 > string2, reset if string1 <= string2.
LOADROMNX: LD L,0FFH
JR LOADROM1
LOADROM: LD L,000H
LOADROM1: ;DI
PUSH HL ; Preserve execute flag.
EX DE,HL ; User ROM expects HL to have the filename pointer.
PUSH HL ; Save pointer to filename for FINDMZF in Monitor ROM.
; D = File sequence number.
LD D,0 ; File numbering start.
;
LD A,ROMBANK3 ; Activate the RFS Utilities MROM bank.
LD (WRKROMBK1), A
LD (BNKSELMROM),A
CALL MFINDMZF ; Try and find the file in User ROM via MROM utility.
POP HL
JR Z,MROMLOAD0
;
CALL FINDMZF ; Find the bank and block where the file resides. HL = filename.
JR Z, LROMLOAD
;
JR LROMNTFND ; Requested file not found.
;
MROMLOAD0: PUSH BC ; Preserve bank and block where MZF file found.
PUSH AF
LD A,(ROMBK1) ; Page in monitor so we can print a message.
LD (BNKSELMROM),A
LD DE,MSGLOAD+1 ; Skip initial CR.
LD BC,NAME
LD HL,PRINTMSG
CALL BKSW0to6
LD A,(WRKROMBK1) ; Revert to MROM bank to load the application.
LD (BNKSELMROM),A
POP AF
POP BC
;
CALL MROMLOAD ; Load the file from User ROM via MROM utility.
JP Z, LROMLOAD5
LROMNTFND: POP HL ; Dont need execute flag anymore so waste it.
LD A,(ROMBK1)
LD (BNKSELMROM),A
LD HL,PRINTMSG
LD DE,MSGNOTFND ; Not found
CALL BKSW0to6
LOADROMEND:;EI
RET
;
; Load program from RFS Bank 1 (MROM Bank)
;
LROMLOAD: PUSH BC
;
PUSH BC
LD DE,MSGLOAD+1
LD BC,NAME
LD HL,PRINTMSG
CALL BKSW0to6
POP BC
;
LD A,B
LD (WRKROMBK1),A
LD (BNKSELMROM),A
;
LD DE, IBUFE ; Copy the header into the work area.
LD HL, 00000h ; Add block offset to get the valid block.
LD A,C
IF RFSSECTSZ >= 512
RLCA
ENDIF
IF RFSSECTSZ >= 1024
RLCA
ENDIF
LD B,A
LD C,0
ADD HL,BC
LD BC, MZFHDRSZ
LDIR
PUSH HL
LD DE, (DTADR)
LD HL, (SIZE)
LD BC, RFSSECTSZ - MZFHDRSZ
SBC HL, BC
JR NC, LROMLOAD4
LD HL, (SIZE)
JR LROMLOAD4
; HL = address in active block to read.
; B = Bank
; C = Block
LROMLOAD2: LD A, B
LD (WRKROMBK1), A
LD (BNKSELMROM),A
LROMLOAD3: PUSH BC
LD HL, 00000h
LD A, C
IF RFSSECTSZ >= 512
RLCA
ENDIF
IF RFSSECTSZ >= 1024
RLCA
ENDIF
LD B, A
LD C, 0
ADD HL,BC
PUSH HL
LD DE, (TMPADR)
LD HL, (TMPSIZE)
LD BC, RFSSECTSZ
SBC HL, BC
JR NC, LROMLOAD4
LD BC, (TMPSIZE)
LD HL, 0
LROMLOAD4: LD (TMPSIZE), HL ; HL contains remaining amount of bytes to load.
POP HL
;
LD A, B ; Pre check to ensure BC is not zero.
OR C
JR Z, LROMLOAD8
LDIR
LD BC, (TMPSIZE)
LD A, B ; Post check to ensure we still have bytes
OR C
JR Z, LROMLOAD8
;
LD (TMPADR),DE ; Address we are loading into.
POP BC
LROMLOAD6: INC C
LD A, C
CP MROMSIZE/RFSSECTSZ ; Max blocks per page reached?
JR C, LROMLOAD7
LD C, 0
INC B
;
LROMLOAD7: LD A, B
CP 080h
JR Z, LROMLOAD5
JR LROMLOAD2
;
LROMLOAD8: POP BC
LROMLOAD5: POP HL ; Retrieve execute flag.
LD A,(ROMBK1)
LD (BNKSELMROM),A ; Set the MROM bank back to original.
LD A,L ; Autoexecute turned off?
CP 0FFh
JP Z,LROMLOAD9 ; Go back to monitor if it has been, else execute.
LD HL,(EXADR)
;EI ; No need to block interrupts now as MROM bank restored.
JP (HL) ; Execution address.
LROMLOAD9: RET
; Quick method to load CPM. So long as the filename doesnt change this method will load and boot CPM.
LOADCPM: LD DE,CPMFN48 ; Load up the 48K version of CPM
LOADPRGNM: PUSH HL
LD HL,BUFER
LOADPRGNM1: LD A,(DE)
LD (HL),A
CP CR
JR Z,LOADPRGNM2
INC DE
INC HL
JR LOADPRGNM1
LOADPRGNM2: POP HL
LD DE,BUFER
JP LOADROM
; Quick method to load the basic interpreter. So long as the filename doesnt change this method will load and boot Basic.
LOADBASIC: LD DE,BASICFILENM
JR LOADPRGNM
LOADPROG: LD HL,LOADSDCARD
CALL BKSW0to2
RET
;-------------------------------------------------------------------------------
; END OF RFS COMMAND FUNCTIONS.
;-------------------------------------------------------------------------------
;-------------------------------------------------------------------------------
; DEVICE DRIVERS - Intercept handlers to provide enhanced services to
; existing MA-80A BIOS API functions.
;-------------------------------------------------------------------------------
; Method to set the RFS Drive number from the Load/Save string provided.
SETDRIVE: LD A,(DE) ; If a drive is given it will be in format <driveno>:<filename>
OR A ; Exit if null or CR found, no drive specifier present.
JR Z,SETDRV3
CP 00DH
JR Z,SETDRV3
CP '"' ; String quotes, skip over.
JR NZ,SETDRV1
INC DE
JR SETDRIVE
;
SETDRV1: LD A,(DE) ; Check for <digit>:, if no colon exit.
LD C,A
INC DE
LD A,(DE)
DEC DE
CP ':'
JR NZ, SETDRV3
;
LD A,C
CP 'C' ; CMT unit specified by C:
JR Z,SETDRV2
SUB '0' ; Check the drive number, should be in range 0..9
JP C,SD_INVDRV
CP 10
JP NC,SD_INVDRV
SETDRV2: INC DE
LD (SDDRIVENO),A ; Store drive number for later use.
XOR A
LD (CMTFILENO),A ; Setup the starting file number for sequential file reads (ie. when no filename given).
;
PUSH DE ; Need to remove the drive qualifier once processed.
PUSH DE
INC DE
INC DE ; Move onto filename.
EX DE,HL
POP DE
LD BC,SDDIR_FNSZ
LDIR
POP DE
;
SETDRV3: XOR A
RET
; Method to check if the active drive is the CMT.
CHECKCMT: LD A,(SDDRIVENO)
CP 'C'
RET
; Convert the lower 4 bits of A into a Hex character.
TOHEXDIGIT: AND 00FH ; Simple logic, add 30H to get 0..9, add additional 7 if value >= 10 to get digits A..F.
CP 00AH
JR C,NOADD
ADD A,007H
NOADD: ADD A,030H
RET
; Convert a number into Hex string and store in buffer pointed to by DE.
;
TOHEX: PUSH DE
PUSH AF ; Save AF to retrieve lower 4 bits.
RRCA ; Shift upper 4 bits to lower to convert to hex.
RRCA
RRCA
RRCA
CALL TOHEXDIGIT
LD (DE),A ; Store and convert lower 4 bits.
INC DE
POP AF
CALL TOHEXDIGIT
LD (DE),A
INC DE
LD A,CR ; Terminate with a CR.
LD (DE),A
POP DE ; DE back to start of string.
RET
; Handler to intercept the CMT Read Header Information call and insert selectable
; SD Card RFS Drive functionality.
; DE contains a pointer to memory containing the file to load. If (DE) = NULL then
; load the next sequential file from the SD card directory.
; DE = Filename. Can contain a drive specifier in format <driveno>:<filename>
;
; No registers or flags should be affected as we dont know the caller state.
_CMT_RDINF: CALL SETDRIVE ; Set drive if specified.
RET NZ
CALL CHECKCMT ; If drive is set to the CMT Unit exit with Z set so that the original CMT handlers are called.
JP Z,?RDI
LD A,(DE) ; Check to see if empty string given, if so expand the default Next file number into the buffer.
CP CR
JR NZ,_CMT_RDINF1
LD A,(CMTFILENO) ; Get next sequential number and convert to hex.
PUSH AF
CALL TOHEX
POP AF
INC A ; Increment number so next call retrieves the next sequential file.
LD (CMTFILENO),A
;
_CMT_RDINF1:PUSH DE
LD HL,LOADSDINF ; DE already points to the filename, call LOADSDINF to locate it on the SD card and setup the header.
CALL BKSW0to2
; Copy the filename into the Buffer provided allowing for file number to name expansion.
POP DE
LD HL,NAME
LD BC,SDDIR_FNSZ
LDIR
;
LD A,(RESULT)
OR A
RET Z ; 0 = success, return with carry clear.
SCF ; > 0 = fail, return with carry set.
RET
; Handler to intercept the CMT Read Data call and insert selectable SD Card RFS
; Drive functionality.
;
; No registers or flags should be affected as we dont know the caller state.
_CMT_RDDATA:LD HL,LOADSDDATA
CALL BKSW0to2
LD A,(RESULT)
OR A
JR NZ,_CMT_RDERR
RET
_CMT_RDERR: SCF
RET
; Handler to intercept the CMT Write Header Information call and insert selectable
; SD Card RFS Drive functionality.
;
; No registers or flags should be affected as we dont know the caller state.
;
; At the moment, the WRINF call only creates a filename if non specified. The actual write to file occurs in WRDATA. Once I have more understanding of
; how the sequential data mode works I can adapt it to be compatible.
_CMT_WRINF: LD DE,NAME ; Caller has already setup the CMT header so we use this for processing.
;
CALL SETDRIVE ; Set drive if specified.
RET NZ
CALL CHECKCMT
JP Z,?WRI
;
LD A,(DE) ; Check to see if empty string given, if so create a default name.
CP CR
JR NZ,_CMT_WRINF1
;
LD HL,DEFAULTFN
LD BC,DEFAULTFNE - DEFAULTFN
LDIR
LD A,(CMTFILENO) ; Get next sequential number and convert to hex.
PUSH AF
CALL TOHEX
POP AF
INC A ; Increment number so next call retrieves the next sequential file.
LD (CMTFILENO),A
;
_CMT_WRINF1:LD A,0 ; Always success as nothing is written.
OR A
RET
; Handler to intercept the CMT Write Data call and insert selectable SD Card RFS
; Drive functionality.
;
; No registers or flags should be affected as we dont know the caller state.
_CMT_WRDATA: LD HL,SAVESDDATA
CALL BKSW0to2
LD A,(RESULT)
OR A
JR NZ,_CMT_RDERR
RET
; Handler to intercept the CMT Verify Data call and insert selectable SD Card
; RFS Drive functionality.
;
; No registers or flags should be affected as we dont know the caller state.
_CMT_VERIFY:CALL SETDRIVE ; Set drive if specified.
RET NZ
CALL CHECKCMT
JR Z,_VERIFY
LD DE,MSGNOVERIFY
JR SD_ERRMSG
_VERIFY: JP ?VRFY
SD_INVDRV: LD DE,MSGINVDRV ; Invalid drive specified.
JR SD_ERRMSG
SD_NOTFND: LD DE,MSGNOTFND
SD_ERRMSG: LD HL,PRINTMSG
CALL BKSW0to6 ; Print message that file wasnt found.
LD A,1
OR A
RET
; Method to list the contents of the active RFS drive number.
_CMT_DIR: CALL SETDRIVE ; Change to the given drive.
RET NZ
CALL CHECKCMT ; Cannot DIR tape drive so give error.
JP Z,_CMT_NODIR
LD HL,DIRSDCARD
CALL BKSW0to2 ; Call the standard RFS directory command.
RET
_CMT_NODIR: LD DE,MSGNOCMTDIR
JR SD_ERRMSG
; Stub to call the ASCII to Sharp ASCII conversion routine stored in Bank 5.
; Inputs: DE = String to convert, NULL or CR terminated.
; B = Maximum number of characters to convert.
; All registers except AF preserved.
;
_CNV_ATOS: PUSH HL
LD HL,CNVSTR_AS
CALL BKSW0to5
POP HL
RET
;-------------------------------------------------------------------------------
; END OF DEVICE DRIVERS
;-------------------------------------------------------------------------------
;--------------------------------------
;
; Message table - Refer to bank 6 for
; all messages.
;
;--------------------------------------
; Quick load program names.
CPMFN48: DB "CPM223RFS", 00DH
BASICFILENM:DB "BASIC SA-5510RFS", 00DH
DEFAULTFN: DB "DEFAULT"
DEFAULTFNE: EQU $
; Bring in additional resources.
USE_CMPSTRING: EQU 1
USE_SUBSTRING: EQU 0
USE_INDEX: EQU 0
USE_STRINSERT: EQU 0
USE_STRDELETE: EQU 0
USE_CONCAT: EQU 0
USE_CNVUPPER: EQU 1
USE_CNVCHRTONUM: EQU 1
USE_ISNUMERIC: EQU 1
USE_CNVSTRTONUM: EQU 1
;
INCLUDE "macros.asm"
INCLUDE "rfs_utilities.asm"
;
; Ensure we fill the entire 2K by padding with FF's.
;
ALIGN 0EFF8h
ORG 0EFF8h
DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh
MEND:
;
; Include all other banks which make up the RFS User cited ROM.
;
INCLUDE "rfs_bank1.asm"
INCLUDE "rfs_bank2.asm"
INCLUDE "rfs_bank3.asm"
INCLUDE "rfs_bank4.asm"
INCLUDE "rfs_bank5.asm"
INCLUDE "rfs_bank6.asm"
INCLUDE "rfs_bank7.asm"