From 3f5216dd2b9b431dbb572e86b1beed8608c3442b Mon Sep 17 00:00:00 2001 From: Philip Smart Date: Wed, 1 Apr 2026 23:29:33 +0100 Subject: [PATCH] SFD700 bug fixes --- asm/include/macros.asm | 4 +- asm/include/rfs_definitions.asm | 20 +-- asm/rfs.asm | 226 ++++++++++++++++---------------- asm/rfs_bank1.asm | 2 +- asm/rfs_bank10.asm | 8 ++ asm/rfs_bank11.asm | 9 +- asm/rfs_bank7.asm | 105 ++++++++++++--- asm/rfs_bank8.asm | 7 + asm/rfs_bank9.asm | 7 + roms/rfs.rom | Bin 24576 -> 73728 bytes tools/make_roms.sh | 10 +- 11 files changed, 249 insertions(+), 149 deletions(-) diff --git a/asm/include/macros.asm b/asm/include/macros.asm index c016fea..631e021 100644 --- a/asm/include/macros.asm +++ b/asm/include/macros.asm @@ -136,9 +136,9 @@ BNKSWSEL: MACRO ENDIF IF BUILD_SFD700 = 1 OUT (REG_EXXX),A ; Execute active bank switch for E000:EFFF. - CP ROMBANK6 ; ROMBANK6/7 page in ROM from E300:FFFF + CP ROMBANK6 ; ROMBANK6:11 page in ROM from E300:FFFF JR C,BNKSWJMP - INC A ; FXXX are 4K banks, EXXX are 2K banks. + INC A ; FXXX are 4K banks, EXXX are 4K banks. JR BNKSWJMP2 BNKSWJMP: LD A,(ROMBK1) ; All other banks place the current active ROM into F000:FXXX space. BNKSWJMP2: OUT (REG_FXXX),A diff --git a/asm/include/rfs_definitions.asm b/asm/include/rfs_definitions.asm index 54b2fff..94c0ef7 100644 --- a/asm/include/rfs_definitions.asm +++ b/asm/include/rfs_definitions.asm @@ -51,8 +51,8 @@ VIDEOMODULE_ENA EQU 0 ; Targe ; Only enable one BUILD_<> operative. Customisations applied according ; to the target. BUILD_ROMDISK EQU 0 ; RFS is built for the MZ-80A RomDisk card. -BUILD_SFD700 EQU 0 ; RFS is built for the SFD700 Floppy Disk Controller. -BUILD_PICOZ80 EQU 1 ; RFS is built for the picoZ80 board. +BUILD_SFD700 EQU 1 ; RFS is built for the SFD700 Floppy Disk Controller. +BUILD_PICOZ80 EQU 0 ; RFS is built for the picoZ80 board. BUILD_MZ80A EQU 0 ; RFS is customised to operate on an MZ-80A. BUILD_MZ700 EQU 1 ; RFS is customised to operate on an MZ-700. @@ -421,14 +421,14 @@ ROMBANK4 EQU 4 + BNKDEFUROM ; ROMBANK5 EQU 5 + BNKDEFUROM ; : RFS Bank 5 ROMBANK6 EQU 6 + BNKDEFUROM ; : RFS Bank 6 ROMBANK7 EQU 8 + BNKDEFUROM ; : RFS Bank 7 - Memory and timer test utilities. -ROMBANK8 EQU 8 + BNKDEFUROM ; Free : RFS Bank 8 - -ROMBANK9 EQU 9 + BNKDEFUROM ; Free : RFS Bank 9 - -ROMBANK10 EQU 10 + BNKDEFUROM ; Free : RFS Bank 10 - -ROMBANK11 EQU 11 + BNKDEFUROM ; Free : RFS Bank 11 - -ROMBANK12 EQU 12 + BNKDEFUROM ; Free : CBIOS Bank 1 - Utilities -ROMBANK13 EQU 13 + BNKDEFUROM ; Free : CBIOS Bank 2 - Screen / ANSI Terminal -ROMBANK14 EQU 14 + BNKDEFUROM ; Free : CBIOS Bank 3 - SD Card -ROMBANK15 EQU 15 + BNKDEFUROM ; Free : CBIOS Bank 4 - Floppy disk controller. +ROMBANK8 EQU 10 + BNKDEFUROM ; Free : RFS Bank 8 - +ROMBANK9 EQU 12 + BNKDEFUROM ; Free : RFS Bank 9 - +ROMBANK10 EQU 14 + BNKDEFUROM ; Free : RFS Bank 10 - +ROMBANK11 EQU 16 + BNKDEFUROM ; Free : RFS Bank 11 - +ROMBANK12 EQU 17 + BNKDEFUROM ; Free : CBIOS Bank 1 - Utilities +ROMBANK13 EQU 18 + BNKDEFUROM ; Free : CBIOS Bank 2 - Screen / ANSI Terminal +ROMBANK14 EQU 19 + BNKDEFUROM ; Free : CBIOS Bank 3 - SD Card +ROMBANK15 EQU 20 + BNKDEFUROM ; Free : CBIOS Bank 4 - Floppy disk controller. ENDIF ; MMC/SD command (SPI mode) diff --git a/asm/rfs.asm b/asm/rfs.asm index 5694777..c10647b 100644 --- a/asm/rfs.asm +++ b/asm/rfs.asm @@ -48,6 +48,116 @@ ; Bring in additional resources. INCLUDE "rfs_definitions.asm" + ;============================================================ + ; + ; SFD700 COMMAND TABLE + ; + ; Placed after all bank includes so DW forward references to + ; functions in various IF blocks are resolved as backward refs. + ;============================================================ + IF BUILD_SFD700 = 1 + ORG 0E000H + ALIGN 0E300H + ENDIF + + ; Monitor command table (SFD700). This table contains the list of recognised commands along with the + ; handler function and bank in which it is located. + ; + ; 7 6:3 2:0 + ; MATCH BANK SIZE +CMDTABLE2: IF BUILD_SFD700 = 1 + DB 000H | 038H | 003H + DB "ASM" ; Assembler. + DW ASM_MAIN + DB 000H | 000H | 005H + DB "BASIC" ; Load and run BASIC SA-5510. + DW LOADBASIC + DB 000H | 020H | 001H + DB 'B' ; Bell. + DW SGX + DB 000H | 000H | 003H + DB "CPM" ; Load and run CPM. + DW LOADCPM + DB 000H | 018H | 002H + DB "CP" ; Copy Memory. + DW MCOPY + DB 000H | 018H | 003H + DB "DUC" ; Dump SD Card file contents (hex or text). + DW DUMPSDCARD + DB 000H | 018H | 001H + DB 'C' ; Clear Memory. + DW INITMEMX + DB 000H | 038H | 004H + DB "DASM" ; Disassembler. + DW DASM_MAIN + DB 000H | 018H | 001H + DB 'D' ; Dump Memory. + DW DUMPX + DB 000H | 008H | 002H + DB "FL" ; 'FL' Floppy disk boot (built-in WD1773 FDC). + DW FLOPPY + DB 000H | 008H | 002H + DB "FD" ; 'FD' Floppy disk directory listing. + DW FDDIR + DB 000H | 058H | 001H + DB 'H' ; Help screen (bank 11). + DW HELP + DB 000H | 018H | 002H ; Bank 3, 2-char command. + DB "IN" ; I/O port input. + DW INX + DB 000H | 000H | 002H + DB "IR" ; List ROM directory. + DW DIRROM + DB 000H | 000H | 001H + DB 'J' ; Jump to address. + DW GOTOX + DB 000H | 020H | 004H + DB "LTNX" ; Load from CMT without auto execution. + DW LOADTAPENX + DB 000H | 020H | 002H + DB "LT" ; Load from CMT + DW LOADTAPE + DB 000H | 000H | 004H + DB "LRNX" ; Load from ROM without auto execution. + DW LOADROMNX + DB 000H | 000H | 002H + DB "LR" ; Load from ROM + DW LOADROM + DB 000H | 020H | 001H + DB "L" ; Original Load from CMT + DW LOADTAPE + DB 000H | 018H | 001H + DB 'M' ; Edit Memory. + DW MCORX + DB 000H | 018H | 003H ; Bank 3, 3-char command. + DB "OUT" ; I/O port output. + DW OUTX + DB 000H | 018H | 001H + DB 'P' ; Printer test. + DW PTESTX + DB 000H | 020H | 001H + DB 'R' ; Memory test. + DW MEMTEST + DB 000H | 020H | 002H + DB "ST" ; Save to CMT + DW SAVEX + DB 000H | 020H | 001H + DB 'S' ; Save to CMT + DW SAVEX + DB 000H | 000H | 004H + DB "TEST" ; A test function used in debugging. + DW LOCALTEST + DB 000H | 020H | 001H + DB 'T' ; Timer test. + DW TIMERTST + DB 000H | 000H | 001H + DB 'V' ; Verify CMT Save. + DW VRFYX + DB 0FFH ; END OF TABLE + + ALIGN UROMADDR + ENDIF + ;============================================================ ; ; USER ROM BANK 0 - Main RFS Entry point and functions. @@ -633,10 +743,10 @@ SETMODE80: IF BUILD_ROMDISK+BUILD_PICOZ80 = 1 JP MONIT ENDIF -NOTZPU: LDDE MSGNOTZINST ; No tranZPUter installed. - LD HL,PRINTMSG - CALL BKSW0to6 - RET +;NOTZPU: LDDE 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 @@ -1490,111 +1600,3 @@ MEND: INCLUDE "rfs_bank9.asm" INCLUDE "rfs_bank10.asm" INCLUDE "rfs_bank11.asm" - - ;============================================================ - ; - ; SFD700 COMMAND TABLE - ; - ; Placed after all bank includes so DW forward references to - ; functions in various IF blocks are resolved as backward refs. - ;============================================================ - IF BUILD_SFD700 = 1 - ORG 0E000H - ALIGN 0E300H - ENDIF - - ; Monitor command table (SFD700). This table contains the list of recognised commands along with the - ; handler function and bank in which it is located. - ; - ; 7 6:3 2:0 - ; MATCH BANK SIZE -CMDTABLE2: IF BUILD_SFD700 = 1 - DB 000H | 038H | 003H - DB "ASM" ; Assembler. - DW ASM_MAIN - DB 000H | 000H | 005H - DB "BASIC" ; Load and run BASIC SA-5510. - DW LOADBASIC - DB 000H | 020H | 001H - DB 'B' ; Bell. - DW SGX - DB 000H | 000H | 003H - DB "CPM" ; Load and run CPM. - DW LOADCPM - DB 000H | 018H | 002H - DB "CP" ; Copy Memory. - DW MCOPY - DB 000H | 018H | 003H - DB "DUC" ; Dump SD Card file contents (hex or text). - DW DUMPSDCARD - DB 000H | 018H | 001H - DB 'C' ; Clear Memory. - DW INITMEMX - DB 000H | 038H | 004H - DB "DASM" ; Disassembler. - DW DASM_MAIN - DB 000H | 018H | 001H - DB 'D' ; Dump Memory. - DW DUMPX - DB 000H | 008H | 002H - DB "FL" ; 'FL' RFS Floppy load. - DW FDCK - ; NB: FD/FDDIR command not available on SFD700 — FDDIR only exists - ; for ROMDISK/picoZ80 builds (MZ-700 WD1773 FDC). SFD700 uses - ; AFI ROM at F000 via FDCK for floppy operations. - DB 000H | 058H | 001H - DB 'H' ; Help screen (bank 11). - DW HELP - DB 000H | 018H | 002H ; Bank 3, 2-char command. - DB "IN" ; I/O port input. - DW INX - DB 000H | 000H | 002H - DB "IR" ; List ROM directory. - DW DIRROM - DB 000H | 000H | 001H - DB 'J' ; Jump to address. - DW GOTOX - DB 000H | 020H | 004H - DB "LTNX" ; Load from CMT without auto execution. - DW LOADTAPENX - DB 000H | 020H | 002H - DB "LT" ; Load from CMT - DW LOADTAPE - DB 000H | 000H | 004H - DB "LRNX" ; Load from ROM without auto execution. - DW LOADROMNX - DB 000H | 000H | 002H - DB "LR" ; Load from ROM - DW LOADROM - DB 000H | 020H | 001H - DB "L" ; Original Load from CMT - DW LOADTAPE - DB 000H | 018H | 001H - DB 'M' ; Edit Memory. - DW MCORX - DB 000H | 018H | 003H ; Bank 3, 3-char command. - DB "OUT" ; I/O port output. - DW OUTX - DB 000H | 018H | 001H - DB 'P' ; Printer test. - DW PTESTX - DB 000H | 020H | 001H - DB 'R' ; Memory test. - DW MEMTEST - DB 000H | 020H | 002H - DB "ST" ; Save to CMT - DW SAVEX - DB 000H | 020H | 001H - DB 'S' ; Save to CMT - DW SAVEX - DB 000H | 000H | 004H - DB "TEST" ; A test function used in debugging. - DW LOCALTEST - DB 000H | 020H | 001H - DB 'T' ; Timer test. - DW TIMERTST - DB 000H | 000H | 001H - DB 'V' ; Verify CMT Save. - DW VRFYX - DB 0FFH ; END OF TABLE - ENDIF diff --git a/asm/rfs_bank1.asm b/asm/rfs_bank1.asm index c452040..bad7faa 100644 --- a/asm/rfs_bank1.asm +++ b/asm/rfs_bank1.asm @@ -159,7 +159,7 @@ FDCKROM: LD A,(0F000h) OR A RET -FLOPPY: IF BUILD_ROMDISK+BUILD_PICOZ80 = 1 +FLOPPY: IF BUILD_ROMDISK+BUILD_PICOZ80+BUILD_SFD700 = 1 IF BUILD_MZ80A = 1 PUSH DE ; Preserve pointer to input buffer. LD DE,BPARA ; Copy disk parameter block into RAM work area. (From) diff --git a/asm/rfs_bank10.asm b/asm/rfs_bank10.asm index d49d4a1..0ee72bd 100644 --- a/asm/rfs_bank10.asm +++ b/asm/rfs_bank10.asm @@ -36,6 +36,13 @@ ;- along with this program. If not, see . ;-------------------------------------------------------------------------------------------------------- + IF BUILD_SFD700 = 1 + ORG 0E000H + ALIGN 0E300H + DB "BANK10" + ALIGN UROMADDR + ENDIF + ;=========================================================== ; ; USER ROM BANK 10 - @@ -144,6 +151,7 @@ BKSWRET10: POP AF ; G ORG 0EFF8h DB 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh ENDIF + ; SFD700 - Pad to 10000H IF BUILD_SFD700 = 1 ALIGN 10000H diff --git a/asm/rfs_bank11.asm b/asm/rfs_bank11.asm index 9eba723..2d5c0c9 100644 --- a/asm/rfs_bank11.asm +++ b/asm/rfs_bank11.asm @@ -37,6 +37,13 @@ ;- along with this program. If not, see . ;-------------------------------------------------------------------------------------------------------- + IF BUILD_SFD700 = 1 + ORG 0E000H + ALIGN 0E300H + DB "BANK11" + ALIGN UROMADDR + ENDIF + ;=========================================================== ; ; USER ROM BANK 11 - @@ -391,7 +398,7 @@ HELPSCR: IF BUILD_ROMDISK+BUILD_PICOZ80 = 1 DB " - add NX for no exec, ie.LRNX.", 00DH DB "MXXXX - edit memory starting at X.", 00DH DB "P - test printer.", 00DH - DB "QD/QL - QD dir/boot", 00DH + ;DB "QD/QL - QD dir/boot", 00DH DB "R - test dram memory.", 00DH DB "SD2T - copy sd card to tape.", 00DH DB "ST[XXXXYYYYZZZZ] - save mem to tape.", 00DH diff --git a/asm/rfs_bank7.asm b/asm/rfs_bank7.asm index 78a8027..aec96be 100644 --- a/asm/rfs_bank7.asm +++ b/asm/rfs_bank7.asm @@ -149,12 +149,12 @@ DASM_FILL: LD (HL),A CALL DASMBITINST ; Is This a BIT,SET or RES Inst.? JP NZ,DASM_FIND ; NO=Do regular search CALL DSMFINDOPCD ; Search For Matching BIT,SET,RES OP Code - JP Z,DASM_ERR ; NOT FOUND - Error Message + JP Z,DASM_UNK ; NOT FOUND - output raw byte and continue CALL DASMGETINST ; Copy 4 byte Assembler Inst. to ASM_BUF - JP DASM_JUSTV ; VAL_BUF has already been populated - + JP DASM_JUSTV ; VAL_BUF has already been populated + DASM_FIND: CALL DSMFINDOPCD ; Search For Matching OP Code - JP Z,DASM_ERR ; NOT FOUND - Error Message + JP Z,DASM_UNK ; NOT FOUND - output raw byte and continue CALL DASMGETINST ; Copy 4 byte Assembler Inst. to ASM_BUF @@ -172,8 +172,8 @@ DASM_JUSTV: CALL DSMLFJVAL ; Left justify VAL_BUF(Trim leading zeros) CALL DASMGETPARM ; Build parameter string with value data CALL DSMRTRIMASM ; Trim trailing spaces from ASM_BUF - - LD A,0Fh ; Output Memory Bytes and Advance Address Pointer + +DASM_PROUT: LD A,0Fh ; Output Memory Bytes and Advance Address Pointer LD C,A LD HL,(ADDR_LO) ; Address ->HL LD A,(ML_BTCOUNT) ;Get Total Byte count from lookup table @@ -193,11 +193,13 @@ DASM_SPCOUT: CALL PRNTS ; Pad with spaces to 15 bytes DEC C JP NZ,DASM_SPCOUT ; DONE? NO=Continue - LD HL,ASM_BUF ; Send Assembly string + LD HL,ASM_BUF ; Send Assembly string EX DE,HL LD HL,PRINTMSG CALL BKSW7to6 - + LD A,ROMBANK7+1 ; Restore F-page (BNKSWSELRET sets it to ROMBK1). + OUT (REG_FXXX),A + LD A,(COUNT_C) ; Get Row Count CP 0FFh ; Using End Address? JP Z,DASM_CKEADR @@ -212,11 +214,42 @@ DASM_CKEADR: LD HL,(ASM_ADDR) ; Get End Address RET M ; If resulte negative - Exit JP DASM_LOOP1 ; Otherwise Continue... + ; Unknown/undefined opcode — output as "DB" and advance 1 byte. +DASM_UNK: LD A,1 + LD (ML_BTCOUNT),A ; 1 byte only + LD HL,DASM_UNKDB ; "DB" string → ASM_BUF + LD DE,ASM_BUF + LD A,(HL) + LD (DE),A + INC HL + INC DE + LD A,(HL) + LD (DE),A + INC DE + XOR A + LD (DE),A ; Null-terminate "DB" + ; Put hex value of opcode into VAL_BUF + LD A,(ML_BUF) + CALL BYTE2ASCII ; H=LSB nib, L=MSB nib + LD A,L + LD (VAL_BUF),A + LD A,H + LD (VAL_BUF+1),A + LD A,'H' + LD (VAL_BUF+2),A + XOR A + LD (VAL_BUF+3),A ; Null-terminate + JP DASM_PROUT ; Go to print output + +DASM_UNKDB: DB "DB", 0 + DASM_ERR: LD DE,MSGNOTFND LD HL,PRINTMSG CALL BKSW7to6 + LD A,ROMBANK7+1 ; Restore F-page. + OUT (REG_FXXX),A RET - + ;****************************************************************** ; Dis-Assembler Routines ;****************************************************************** @@ -560,7 +593,8 @@ DASM_MOVINS: INC HL ; Inc Block Header data pointer ; Return with BLK_ADDR=block header address, ROW_ADDR=found row address ; ML_BYCOUNT=a non-zero count if match was found ;****************************************************************** -DSMFINDOPCD: PUSH BC +DSMFINDOPCD: DI ;Disable interrupts during F-page table search. + PUSH BC LD IX,OPCD_TABLE ;Set IX=Table Start Address DSMFN_LOOP1: LD A,(IX+0) CP '#' ;Is Row Byte0='#'? @@ -605,8 +639,9 @@ DSMFN_MATCH: LD (ROW_ADDR),IX ; Save IX->ROW_ADDR LD (ML_BUF+1),A ; Save row byte8 ->ML_BUF1 LD A,(IX+9) LD (ML_BTCOUNT),A ; Save byte count->ML_BYCOUNT - CP 0 ; Set Z flag if NOT FOUND + CP 0 ; Set Z flag if NOT FOUND POP BC + EI ;Re-enable interrupts after table search. RET ;****************************************************************** @@ -728,15 +763,19 @@ ASMLOOPEXIT: LD BC,VAL_BUF ASM_ERR_INS: LD DE,MSGNOINSTR LD HL,PRINTMSG CALL BKSW7to6 - JP ASM_LOOP1 ; Get another line of ASM input... - + LD A,ROMBANK7+1 ; Restore F-page. + OUT (REG_FXXX),A + JP ASM_LOOP1 ; Get another line of ASM input... + ASM_FINDPRM: CALL ASMFINDPARM ; Look for matching parameter pattern - LD A,(ML_BUF+2) ; Found one? NO=ERROR - CP 0 + LD A,(ML_BUF+2) ; Found one? NO=ERROR + CP 0 JP NZ,ASMOUTML LD DE,MSGNOPARAM LD HL,PRINTMSG CALL BKSW7to6 + LD A,ROMBANK7+1 ; Restore F-page. + OUT (REG_FXXX),A JP ASM_LOOP1 ; Get another line of ASM input... @@ -988,12 +1027,12 @@ DASM_FILL: LD (HL),A ; BIT/SET/RES path: value already in VAL_BUF CALL DSMFIND_BOTH ; Search both MROM banks - JP Z,DASM_ERR2 ; NOT FOUND + JP Z,DASM_UNK2 ; NOT FOUND - output raw byte and continue CALL DASMGETINST ; Copy instruction name (MROM still active) JP DASM_JUSTV ; Skip to value justification DASM_FIND: CALL DSMFIND_BOTH ; Search both MROM banks - JP Z,DASM_ERR2 ; NOT FOUND + JP Z,DASM_UNK2 ; NOT FOUND - output raw byte and continue CALL DASMGETINST ; Copy instruction name ; Set up VAL_BUF defaults @@ -1014,7 +1053,7 @@ DASM_JUSTV: CALL DSMLFJVAL ; Left justify VAL_BUF CALL DSMRTRIMASM ; Trim trailing spaces - ; Output memory bytes and advance address pointer +DASM_PROUT2: ; Output memory bytes and advance address pointer LD A,0Fh LD C,A LD HL,(ADDR_LO) @@ -1054,6 +1093,36 @@ DASM_CKEADR: LD HL,(ASM_ADDR) RET M JP DASM_LOOP1 + ; Unknown/undefined opcode (picoZ80) — output as "DB" and advance 1 byte. +DASM_UNK2: POP AF ; Restore MROM bank + LD (BNKSELMROM),A + LD A,1 + LD (ML_BTCOUNT),A ; 1 byte only + LD HL,DASM_UNKDB2 ; "DB" string → ASM_BUF + LD DE,ASM_BUF + LD A,(HL) + LD (DE),A + INC HL + INC DE + LD A,(HL) + LD (DE),A + INC DE + XOR A + LD (DE),A ; Null-terminate "DB" + LD A,(ML_BUF) + CALL BYTE2ASCII ; H=LSB nib, L=MSB nib + LD A,L + LD (VAL_BUF),A + LD A,H + LD (VAL_BUF+1),A + LD A,'H' + LD (VAL_BUF+2),A + XOR A + LD (VAL_BUF+3),A + JP DASM_PROUT2 ; Go to print output + +DASM_UNKDB2: DB "DB", 0 + DASM_ERR2: POP AF ; Restore MROM bank LD (BNKSELMROM),A DASM_ERR: LD DE,MSGNOTFND diff --git a/asm/rfs_bank8.asm b/asm/rfs_bank8.asm index 074bc0b..73adc61 100644 --- a/asm/rfs_bank8.asm +++ b/asm/rfs_bank8.asm @@ -36,6 +36,13 @@ ;- along with this program. If not, see . ;-------------------------------------------------------------------------------------------------------- + IF BUILD_SFD700 = 1 + ORG 0E000H + ALIGN 0E300H + DB "BANK8" + ALIGN UROMADDR + ENDIF + ;=========================================================== ; ; USER ROM BANK 8 - diff --git a/asm/rfs_bank9.asm b/asm/rfs_bank9.asm index 7823091..4d63ade 100644 --- a/asm/rfs_bank9.asm +++ b/asm/rfs_bank9.asm @@ -38,6 +38,13 @@ ;- along with this program. If not, see . ;-------------------------------------------------------------------------------------------------------- + IF BUILD_SFD700 = 1 + ORG 0E000H + ALIGN 0E300H + DB "BANK9" + ALIGN UROMADDR + ENDIF + ;=========================================================== ; ; USER ROM BANK 9 - diff --git a/roms/rfs.rom b/roms/rfs.rom index ff4fd1f74ace815e7896467eede449e8a8cf423a..15e07382e4a3d02d3b48b6406cdd5330ddaab41e 100644 GIT binary patch literal 73728 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 R&=}Ad&=}Ad_}gUQe*ig<3GM&@ literal 24576 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