SD Card updates for CPM

This commit is contained in:
Philip Smart
2020-03-23 19:34:15 +00:00
parent 76258e54d6
commit b928974b6c
48 changed files with 4958 additions and 2434 deletions

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -45,18 +45,30 @@
NOP
; After switching in Bank 0, it will automatically continue processing in Bank 0 at the XOR A instructionof ROMFS:
; Jump table for entry into this pages public functions.
;-------------------------------------------------------------------------------
; Jump table for entry into this pages functions.
;-------------------------------------------------------------------------------
JP ?REBOOT ; 9 REBOOT
JP ?MLDY ; 12 QMELDY
JP ?TEMP ; 15 QTEMP
JP MLDST ; 18 QMSTA
JP MLDSP ; 21 QMSTP
JP ?BEL ; 24 QBEL
JP ?MODE ; 27 QMODE
JP ?TIMESET ; 30 QTIMESET
JP ?TIMEREAD ; 33 QTIMEREAD
JP ?CHKKY ; 36 QCHKKY
JP ?GETKY ; 39 QGETKY
; Method to reboot the machine into startup mode, ie. Monitor at MROM Bank 0, UROM at Bank 0.
?REBOOT: LD A,(MEMSWR) ; Switch memory to power up state, ie. Monitor ROM at 00000H
JP UROMADDR ; Now run the code at the bank start which switches to bank 0, intitialises and then calls 00000H
;-------------------------------------------------------------------------------
; START OF AUDIO CONTROLLER FUNCTIONALITY
;-------------------------------------------------------------------------------
; Melody function.
?MLDY: PUSH BC
@@ -215,14 +227,18 @@ MLDDLY: ADD A,C
POP AF
RET
;
; Method to sound the bell, basically play a constant tone.
;
?BEL: PUSH DE
LD DE,00DB1H
CALL ?MLDY
POP DE
RET
;
; Melody (note) lookup table.
;
MTBL: DB 043H
DB 077H
DB 007H
@@ -282,6 +298,137 @@ OPTBL: DB 001H
DB 010H
DB 018H
DB 020H
;-------------------------------------------------------------------------------
; END OF AUDIO CONTROLLER FUNCTIONALITY
;-------------------------------------------------------------------------------
;-------------------------------------------------------------------------------
; START OF RTC FUNCTIONALITY (INTR HANDLER IN MAIN CBIOS)
;-------------------------------------------------------------------------------
;
; BC:DE:HL contains the time in milliseconds (100msec resolution) since 01/01/1980. In IX is held the interrupt service handler routine address for the RTC.
; HL contains lower 16 bits, DE contains middle 16 bits, BC contains upper 16bits, allows for a time from 00:00:00 to 23:59:59, for > 500000 days!
?TIMESET: DI
;
LD (TIMESEC),HL ; Load lower 16 bits.
EX DE,HL
LD (TIMESEC+2),HL ; Load middle 16 bits.
PUSH BC
POP HL
LD (TIMESEC+4),HL ; Load upper 16 bits.
;
LD HL,CONTF
LD (HL),074H ; Set Counter 1, read/load lsb first then msb, mode 2 rate generator, binary
LD (HL),0B0H ; Set Counter 2, read/load lsb first then msb, mode 0 interrupt on terminal count, binary
DEC HL
LD DE,TMRTICKINTV ; 100Hz coming into Timer 2 from Timer 1, set divisor to set interrupts per second.
LD (HL),E ; Place current time in Counter 2
LD (HL),D
DEC HL
LD (HL),03BH ; Place divisor in Counter 1, = 315, thus 31500/315 = 100
LD (HL),001H
NOP
NOP
NOP
;
LD A, 0C3H ; Install the interrupt vector for when interrupts are enabled.
LD (00038H),A
LD (00039H),IX
;EI
RET
; Time Read;
; Returns BC:DE:HL where HL is lower 16bits, DE is middle 16bits and BC is upper 16bits of milliseconds since 01/01/1980.
?TIMEREAD: LD HL,(TIMESEC+4)
PUSH HL
POP BC
LD HL,(TIMESEC+2)
EX DE,HL
LD HL,(TIMESEC)
RET
;-------------------------------------------------------------------------------
; END OF RTC FUNCTIONALITY
;-------------------------------------------------------------------------------
;-------------------------------------------------------------------------------
; START OF KEYBOARD FUNCTIONALITY (INTR HANDLER SEPERATE IN CBIOS)
;-------------------------------------------------------------------------------
?MODE: LD HL,KEYPF
LD (HL),08AH
LD (HL),007H
LD (HL),005H
LD (HL),001H
RET
; Method to check if a key has been pressed and stored in buffer..
?CHKKY: LD A, (KEYCOUNT)
OR A
JR Z,CHKKY2
LD A,0FFH
RET
CHKKY2: XOR A
RET
?GETKY: PUSH HL
LD A,(KEYCOUNT)
OR A
JR Z,GETKY2
GETKY1: DI ; Disable interrupts, we dont want a race state occurring.
LD A,(KEYCOUNT)
DEC A ; Take 1 off the total count as we are reading a character out of the buffer.
LD (KEYCOUNT),A
LD HL,(KEYREAD) ; Get the position in the buffer where the next available character resides.
LD A,(HL) ; Read the character and save.
PUSH AF
INC L ; Update the read pointer and save.
LD A,L
AND KEYBUFSIZE-1
LD L,A
LD (KEYREAD),HL
POP AF
EI ; Interrupts back on so keys and RTC are actioned.
JR ?PRCKEY ; Process the key, action any non ASCII keys.
;
GETKY2: LD A,(KEYCOUNT) ; No key available so loop until one is.
OR A
JR Z,GETKY2
JR GETKY1
;
?PRCKEY: CP CR ; CR
JR NZ,?PRCKY3
JR ?PRCKYE
?PRCKY3: CP HOMEKEY ; HOME
JR NZ,?PRCKY4
JR GETKY2
?PRCKY4: CP CLRKEY ; CLR
JR NZ,?PRCKY5
JR GETKY2
?PRCKY5: CP INSERT ; INSERT
JR NZ,?PRCKY6
JR GETKY2
?PRCKY6: CP DBLZERO ; 00
JR NZ,?PRCKY7
LD A,'0'
LD (KEYBUF),A ; Place a character into the keybuffer so we double up on 0
JR ?PRCKYX
?PRCKY7: CP BREAKKEY ; Break key processing.
JR NZ,?PRCKY8
?PRCKY8:
?PRCKYX:
?PRCKYE:
POP HL
RET
;-------------------------------------------------------------------------------
; END OF KEYBOARD FUNCTIONALITY
;-------------------------------------------------------------------------------
ALIGN_NOPS UROMADDR + 0800h

View File

@@ -45,12 +45,17 @@
NOP
; After switching in Bank 0, it will automatically continue processing in Bank 0 at the XOR A instructionof ROMFS:
;-------------------------------------------------------------------------------
; Jump table for entry into this pages functions.
;-------------------------------------------------------------------------------
JP ?PRNT ; 9 QPRNT
JP ?PRTHX ; 12 QPRTHX
JP ?PRTHL ; 15 QPRTHL
JP ?ANSITERM ; 18 QANSITERM
;-------------------------------------------------------------------------------
; START OF SCREEN FUNCTIONALITY
;-------------------------------------------------------------------------------
; CR PAGE MODE1
.CR: CALL .MANG
@@ -105,51 +110,6 @@ DPCT1: ADD HL,BC
EX DE,HL
JP (HL)
;?SAVE: LD HL,FLSDT
; LD A,(SFTLK)
; OR A
; LD (HL),043H ; Thick block cursor when lower case.
; JR Z,SAVE1
; CP 1
; LD (HL),03EH ; Thick underscore when CAPS lock.
; JR Z,SAVE1
; LD (HL),0EFH ; Block cursor when SHIFT lock.
;SAVE1: LD A,(HL)
; PUSH AF
; CALL ?PONT
; LD A,(HL)
; LD (FLASH),A
; POP AF
; LD (HL),A
; XOR A
; LD HL,KEYPA
; LD (HL),A
; CPL
; LD (HL),A
; RET
;
;?LOAD: PUSH AF
; LD A,(FLASH)
; CALL ?PONT
; LD (HL),A
; POP AF
; RET
;
;?FLAS: PUSH AF
; PUSH HL
; LD A,(KEYPC)
; RLCA
; RLCA
; JR C,FLAS1
; LD A,(FLSDT)
;FLAS2: CALL ?PONT
; LD (HL),A
;FLAS3: POP HL
; POP AF
; RET
;FLAS1: LD A,(FLASH)
; JR FLAS2
?PRT: LD A,C
CALL ?ADCN
@@ -860,6 +820,9 @@ ATBL: DB 0CCH ; NUL '\0' (null character)
DB 0CBH
DB 000H
DB 01EH
;-------------------------------------------------------------------------------
; END OF SCREEN FUNCTIONALITY
;-------------------------------------------------------------------------------
;----------------------------------------
;
@@ -1470,6 +1433,10 @@ RCP: LD HL,(CURSORPSAV) ; (curr
LD (DSPXY),HL
JP ANSIEXIT
;-------------------------------------------------------------------------------
; END OF ANSI TERMINAL FUNCTIONALITY
;-------------------------------------------------------------------------------
ALIGN_NOPS UROMADDR + 0800h
; Bring in additional macros.

View File

@@ -27,11 +27,11 @@
;- along with this program. If not, see <http://www.gnu.org/licenses/>.
;--------------------------------------------------------------------------------------------------------
;======================================
;============================================================
;
; USER ROM CPM CBIOS BANK 3
; USER ROM CPM CBIOS BANK 3 - SD Card Controller functions.
;
;======================================
;============================================================
ORG UROMADDR
;-----------------------------------------------------------------------------------------
@@ -44,7 +44,702 @@
NOP
; After switching in Bank 0, it will automatically continue processing in Bank 0 at the XOR A instructionof ROMFS:
;-------------------------------------------------------------------------------
; Jump table for entry into this pages functions.
;-------------------------------------------------------------------------------
JP ?SD_INIT ; 9 SD_INIT
JP ?SD_READ ; 12 SD_READ
JP ?SD_WRITE ; 15 SD_WRITE
JP ?SD_GETLBA ; 18 SD_GETLBA
JP ?SDC_READ ; 21 SDC_READ
JP ?SDC_WRITE ; 24 SDC_WRITE
;-------------------------------------------------------------------------------
; START OF SD CARD CONTROLLER FUNCTIONALITY
;-------------------------------------------------------------------------------
; Method to initialise the SD card.
;
?SD_INIT: LD A,000H ; CS to high
CALL SPICS
;
CALL SPIINIT ; Train SD with our clock.
;
LD A,0FFH ; CS to low
CALL SPICS
LD BC,0FFFFH
SD_INIT1: LD A,CMD0 ; Command 0
LD HL,00000H ; NB. Important, HL should be coded as LH due to little endian and the way it is used in SDCMD.
LD DE,00000H ; NB. Important, DE should be coded as ED due to little endian and the way it is used in SDCMD.
CALL SDCMD
PUSH BC
LD A,(SDBUF+6) ; Get response code.
DEC A ; Set Z flag to test if response is 0x01
JP Z,SD_INIT2 ; Command response 0x01? Exit if match.
POP BC
DEC BC
LD A,B
OR C
JR NZ,SD_INIT1 ; Retry for BC times.
LD A,1
JP SD_EXIT ; Error, card is not responding to CMD0
SD_INIT2: POP BC
; Now send CMD8 to get card details. This command can only be sent
; when the card is idle.
LD A,CMD8 ; CMD8 has 0x00001AA as parameter, load up registers and call command routine.
LD HL,00000H ; NB. Important, HL should be coded as LH due to little endian and the way it is used in SDCMD.
LD DE,0AA01H ; NB. Important, DE should be coded as ED due to little endian and the way it is used in SDCMD.
CALL SDCMD
; Version 2 card, check its voltage range. IF not in the 2.7-3.6V dont try the ACMD41 to get capabilities.
SD_INIT3: LD A,1 ; Check that we receive 0x0001AA in response.
LD (SDVER),A ; Indicate this is not a version 2 card.
LD A,(SDBUF+9)
CP 1
JP NZ,SD_INIT8
LD A,(SDBUF+10)
CP 0AAH
JP NZ,SD_INIT8
SD_INIT4: LD A,2 ; This is a version 2 card.
SD_INIT5: LD (SDVER),A ; Indicate this is not a version 2 card.
CALL SDACMD41
JR Z,SD_INIT6
LD A,2 ; Error, card is not responding to ACMD41
JP SD_EXIT
SD_INIT6: LD A,CMD58 ; CMD58 has 0x00000000 as parameter, load up registers and call command routine.
LD HL,00000H ; NB. Important, HL should be coded as LH due to little endian and the way it is used in SDCMD.
LD DE,00000H ; NB. Important, DE should be coded as ED due to little endian and the way it is used in SDCMD.
CALL SDCMD
LD A,(SDBUF+6)
CP 040H
LD A,CT_SD2
JR Z,SD_INIT7
LD A,CT_SD2 | CT_BLOCK
SD_INIT7: LD (SDCAP),A ; Set the capabilities according to the returned flag.
JR SD_INIT14
; Version 1 card or MMC v3.
SD_INIT8: CALL SDACMD41
LD A, CT_SD1
LD E,ACMD41 ; SD1 cards we use the ACMD41 command.
JR Z,SD_INIT9
LD A,CT_MMC
LD E,CMD1 ; MMC cards we use the CMD1 command.
SD_INIT9: LD (SDCAP),A
LD A,E
CP ACMD41
JR NZ,SD_INIT10
CALL SDACMD41
JR Z,SD_INIT14
LD A,3 ; Exit code, failed to initialise v1 card.
JR SD_EXIT
SD_INIT10: LD BC,10 ; ACMD41/CMD55 may take some cards time to process or respond, so give a large number of retries.
SD_INIT11: PUSH BC
LD A,CMD1 ; CMD1 has 0x00000000 as parameter, load up registers and call command routine.
LD HL,00000H ; NB. Important, HL should be coded as LH due to little endian and the way it is used in SDCMD.
LD DE,00000H ; NB. Important, DE should be coded as ED due to little endian and the way it is used in SDCMD.
CALL SDCMD
LD A,(SDBUF+6) ; Should be a response of 0 whereby the card has left idle.
OR A
JR Z,SD_INIT13
LD BC,0FFFFH ; Delay for at least 200mS for the card to recover and be ready.
SD_INIT12: DEC BC ; 6T
LD A,B ; 9T
OR C ; 4T
JR NZ,SD_INIT12 ; 12T = 31T x 500ns = 15.5uS x 12903 = 200mS
;
POP BC
DEC BC
LD A,B
OR C
JR NZ,SD_INIT11
LD A,4 ; Exit code, failed to initialise v1 MMC card.
JR SD_EXIT
SD_INIT13: LD A,CMD16 ; No response from the card for an ACMD41/CMD1 so try CMD16 with parameter 0x00000200
LD HL,00000H ; NB. Important, HL should be coded as LH due to little endian and the way it is used in SDCMD.
LD DE,00002H ; NB. Important, DE should be coded as ED due to little endian and the way it is used in SDCMD.
CALL SDCMD
LD A,(SDBUF+6)
OR A
JR Z,SD_INIT14
LD A,0
LD (SDCAP),A ; No capabilities on this unknown card.
SD_INIT14: XOR A
SD_EXIT: OR A ; Return value is in A.
RET
; Method to initialise communications with the SD card. We basically train it to our clock characteristics.
; This is important, as is maintaining the same clock for read or write otherwise the card may not respond.
SPIINIT: LD B,80
SPIINIT1: LD A,DOUT_HIGH | CLOCK_HIGH | CS_HIGH ; Output a 1
OUT (SPI_OUT),A
LD A,DOUT_HIGH | CLOCK_LOW | CS_HIGH ; Output a 1
OUT (SPI_OUT),A
DJNZ SPIINIT1
RET
; Method to set the Chip Select level on the SD card. The Chip Select is active LOW.
;
; A = 0 - Set CS HIGH
; A = 0xFF - Set CS LOW
SPICS: OR A
LD A,DOUT_HIGH | CLOCK_LOW | CS_HIGH ; Set CS High if parameter = 0 (ie. disable)
JR Z, SPICS0
LD A,DOUT_HIGH | CLOCK_LOW | CS_LOW ; Set CS Low if parameter != 0 (ie. disable)
SPICS0: OUT (SPI_OUT),A
RET
; Method to send a command to the card and receive back a response.
;
; A = CMD to send
; LHED = Argument, ie. CMD = A, L, H, E, D, CRC
;
SDCMD: LD (SDBUF),A
LD (SDBUF+1),HL
EX DE,HL
LD (SDBUF+3),HL
;
; Send command but with parameters preloaded by caller.
SDCMDNP: LD B,5 ; R1 + 32bit argument for CMD8, CMD58
CP CMD8
LD C,135
JP Z,SDCMD0
LD C,1 ; CMD58 is not CRC checked so just set to 0x01.
CP CMD58
LD B,5 ; R1 + 32bit argument
JP Z,SDCMD0
;
LD B,1 ; Default, expect R1 which is 1 byte.
CP CMD0 ; Work out the CRC based on the command. CRC checking is
LD C,149 ; not implemented but certain commands require a fixed argument and CRC.
JP Z,SDCMD0
LD C,1 ; Remaining commands are not CRC checked so just set to 0x01.
SDCMD0: PUSH BC ; Save the CRC and the number of bytes to be returned,
LD A,C ; Store the CRC
LD (SDBUF+5),A
LD A,255 ; Preamble byte
CALL SPIOUT
LD HL,SDBUF
LD B,6
SDCMD1: PUSH BC
LD A,(HL)
INC HL
CALL SPIOUT ; Send the command and parameters.
POP BC
DJNZ SDCMD1
PUSH HL
SDCMD2: CALL SPIIN
CP 0FFH
JR Z,SDCMD2
JR SDCMD4
SDCMD3: PUSH BC
PUSH HL
CALL SPIIN ;
SDCMD4: POP HL
LD (HL),A
INC HL
POP BC ; Get back number of expected bytes. HL = place in buffer to store response.
DJNZ SDCMD3
LD A,DOUT_HIGH | CLOCK_LOW | CS_HIGH
OUT (SPI_OUT),A
RET
; Method to send an Application Command to the SD Card. This involves sending CMD55 followed by the required command.
;
; A = ACMD to send
; LHED = Argument, ie. ACMD = A, L, H, E, D, CRC
;
SDACMD: PUSH AF
PUSH DE
PUSH HL
LD A,CMD55 ; CMD55 has 0x00000000 as parameter, load up registers and call command routine.
LD HL,00000H ; NB. Important, HL should be coded as LH due to little endian and the way it is used in SDCMD.
LD DE,00000H ; NB. Important, DE should be coded as ED due to little endian and the way it is used in SDCMD.
CALL SDCMD
POP HL
POP DE
LD A,(SDBUF+6) ; Should be a response of 0 or 1.
CP 2
JR NC,SDACMD0
POP AF
CALL SDCMD
LD A,(SDBUF+6) ; Should be a response of 0 whereby the card has left idle.
OR A
RET
SDACMD0: POP AF
CP 1
RET
; Method to send Application Command 41 to the SD card. This command involves retries and delays
; hence coded seperately.
;
; Returns Z set if successful, else NZ.
;
SDACMD41: LD BC,10 ; ACMD41/CMD55 may take some cards time to process or respond, so give a large number of retries.
SDACMD1: PUSH BC
LD A,ACMD41 ; ACMD41 has 0x40000000 as parameter, load up registers and call command routine.
LD HL,00040H ; NB. Important, HL should be coded as LH due to little endian and the way it is used in SDCMD.
LD DE,00000H ; NB. Important, DE should be coded as ED due to little endian and the way it is used in SDCMD.
CALL SDACMD
JR Z,SDACMD3 ; Should be a response of 0 whereby the card has left idle.
LD BC,12903 ; Delay for at least 200mS for the card to recover and be ready.
SDACMD2: DEC BC ; 6T
LD A,B ; 9T
OR C ; 4T
JR NZ,SDACMD2 ; 12T = 31T x 500ns = 15.5uS x 12903 = 200mS
;
POP BC
DEC BC
LD A,B
OR C
JR NZ,SDACMD1
LD A,1 ; Retries exceeded, return error.
OR A
RET
SDACMD3: POP BC ; Success, tidy up stack and exit with Z set.
XOR A
RET
; Method to send a byte to the SD card via the SPI protocol.
; This method uses the bitbang technique, change if hardware spi is available.
;
; Input A = Byte to send.
;
SPIOUT: RLCA ; 65432107
RLCA ; 54321076
RLCA ; 43210765 - Adjust so that starting bit is same position as Data line.
LD E,A ; E = Character to send.
LD B,8 ; B = Bit count
SPIOUT0: LD A,E
AND DOUT_MASK ; Data bit to data line, clock and cs low.
RLC E
SPIOUT1: OUT (SPI_OUT),A
OR CLOCK_HIGH ; Clock high
OUT (SPI_OUT),A
AND CLOCK_MASK ; Clock low
OUT (SPI_OUT),A
DJNZ SPIOUT0 ; Perform actions for the full 8 bits.
RET
; Method to receive a byte from the SD card via the SPI protocol.
; This method uses the bitbang technique, change if hardware spi is available.
; NB. Timing must be very similar in SPIOUT and SPIIN.
;
; Output: A = received byte.
;
SPIIN: LD BC,00800H | SPI_OUT ; B = Bit count, C = clock port
LD L,0 ; L = Character being read.
LD D,DOUT_HIGH | CLOCK_LOW | CS_LOW ; Output a 0
OUT (C),D ; To start ensure clock is low and CS is low.
LD E,DOUT_HIGH | CLOCK_HIGH | CS_LOW ; Output a 0
SPIIN1: OUT (C),E ; Clock to high.
IN A,(SPI_IN) ; Input the received bit
OUT (C),D ; Clock to low.
SRL A
RL L
DJNZ SPIIN1 ; Perform actions for the full 8 bits.
LD A,L ; return value
RET
; A function from the z88dk stdlib, a delay loop with T state accuracy.
;
; enter : hl = tstates >= 141
; uses : af, bc, hl
T_DELAY: LD BC,-141
ADD HL,BC
LD BC,-23
TDELAYLOOP: ADD HL,BC
JR C, TDELAYLOOP
LD A,L
ADD A,15
JR NC, TDELAYG0
CP 8
JR C, TDELAYG1
OR 0
TDELAYG0: INC HL
TDELAYG1: RRA
JR C, TDELAYB0
NOP
TDELAYB0: RRA
JR NC, TDELAYB1
OR 0
TDELAYB1: RRA
RET NC
RET
; Method to skip over an SD card input stream to arrive at the required bytes,
;
; Input: BC = Number of bytes to skip.
;
SPISKIP: PUSH BC
CALL SPIIN
POP BC
DEC BC
LD A,B
OR C
JR NZ,SPISKIP
RET
; Method to convert an LBA value into a physical byte address. This is achieved by multiplying the block x 512.
; We take the big endian sector value, shift left 9 times then store the result back onto the stack.
; This is done as follows: <MSB> <2> <1> <0> => <2> <1> <0> 0 (ie. 8 bit shift): Shift left <0> with carry, shift left <1> shift left <2>, 0 to <LSB>
;
; Input: HL = Stack offset.
;
LBATOADDR: LD HL,(SDSTARTSEC+1)
LD A,(HL) ; Start ny retrieving bytes as HED0
INC HL
LD E,(HL)
INC HL
LD D,(HL)
LD L,A
SLA D ; Shift the long left by 9 to effect a x512
RL E
RL H
LD BC,(SDSTARTSEC)
LD A,H ; Now save the results as LHED, big endian format as used by the SD Card argument
LD (BC),A
INC BC
LD A,E
LD (BC),A
INC BC
LD A,D
LD (BC),A
INC BC
LD A,0
LD (BC),A
RET
; Method to read a sector or partial sector contents to an SD Card.
;
; This method was originally a C routine I was using for FatFS but optimised it (still more can be done). The C->ASM is not so optimal.
;
; Input: Memory variables: SDSTARTSEC= unsigned long sector. - The sector number or direct byte address for older cards. This is big endian as per card.
; HL: Address where to store data read from sector.
; Output: A = 0 - All ok. A > 0 - error occurred.
;
?SD_READ: PUSH HL ; Store the load address.
LD A,0
CALL SPICS ; Set CS low (active).
LD HL,(SDCAP) ; Test to see if CT_BLOCK is available.
LD H,0
LD A,CT_BLOCK
AND L
JP NZ,SD_READ1 ; If it has CT_BLOCK then use sector numbers otherwise multiply up to bytes.
CALL LBATOADDR ; Multiply the sector by 512 for byte addressing on older cards.
SD_READ1: ; A = ACMD to send
; LHED = Argument, ie. ACMD = A, L, H, E, D, CRC
LD A,CMD17 ; Send CMD17 to read a sector.
LD (SDBUF),A
LD HL,(SDSTARTSEC)
LD (SDBUF+1),HL
LD HL,(SDSTARTSEC+2)
LD (SDBUF+3),HL
CALL SDCMDNP ; Execute SD Command, parameters already loaded into command buffer.
LD A,(SDBUF+6) ; Fetch result and store.
AND A
JP NZ,SD_READ6
LD HL,1000 ; Sit in a tight loop waiting for the data packet arrival (ie. not 0xFF).
SD_READ2: PUSH HL
LD HL,200
CALL T_DELAY
CALL SPIIN
POP HL
CP 255
JP NZ,SD_READ3
DEC HL
LD A,H
OR L
JR NZ,SD_READ2
SD_READ3: CP 254 ; Data? If not exit with error code.
JP NZ,SD_READ6
LD BC,SD_SECSIZE ; Size of full sector + 2 bytes CRC.
POP HL ; Get the store address into HL.
SD_READ4: PUSH HL ; Start reading bytes into the buffer.
PUSH BC
CALL SPIIN
POP BC
POP HL
LD (HL),A
INC HL ; Update buffer pointer.
DEC BC
LD A,B
OR C
JP NZ,SD_READ4 ; Not zero, keep reading.
INC BC ; Were not interested in the CRC so skip it.
INC BC
CALL SPISKIP
LD A,0 ; And exit with success.
SD_READ5: PUSH AF
LD A,0
CALL SPICS
POP AF
RET
SD_READ6: POP HL
LD A,1
JR SD_READ5
; Method to write a 512byte sector to an SD Card.
;
; Input: Memory variables: SDSTARTSEC= unsigned long sector. - The sector number or direct byte address for older cards. This is big endian as per card.
; HL: Address of buffer to read data from.
; Output: A = 0 - All ok. A > 0 - error occurred.
?SD_WRITE: PUSH HL
LD A,0FFH ; Activate CS (set low).
CALL SPICS
; Open transaction.
LD HL,(SDCAP) ; Check to see if the card has block addressing.
LD H,0
LD A,CT_BLOCK
AND L
JP NZ,SD_WRITE1 ; If it hasnt then we need to multiply up to the correct byte.
CALL LBATOADDR ; Multiply the sector by 512 for byte addressing.
; A = ACMD to send
; LHED = Argument, ie. ACMD = A, L, H, E, D, CRC
SD_WRITE1: LD A,CMD24 ; Send CMD24 to write a sector.
LD (SDBUF),A
LD HL,(SDSTARTSEC) ; Place long endian sector into command buffer.
LD (SDBUF+1),HL
LD HL,(SDSTARTSEC+2)
LD (SDBUF+3),HL
CALL SDCMDNP ; Send command using No Parameters version as we loaded them into the command buffer already.
LD A,(SDBUF+6) ; Fetch result and store.
AND A
JP NZ,SD_WRITE10
LD A,255 ; Ok, so command sent successfully, mark the write by sending an 0xFF followed by 0xFE
CALL SPIOUT
LD A,254
CALL SPIOUT
; Write buffer.
LD DE,SD_SECSIZE
POP HL ; Address to read data from.
SD_WRITE2: LD A,D ; So long as we have bytes in the buffer, send to the card for writing.
OR E
JP Z,SD_WRITE3
PUSH DE
LD A,(HL) ; Get the byte to transmit.
INC HL ; And update the pointer.
CALL SPIOUT ; Transmit value in A.
POP DE
DEC DE
JR SD_WRITE2
; Close transaction.
SD_WRITE3: INC DE ; Add 2 bytes for CRC
INC DE
SD_WRITE4: LD A,D ; Test to see if we are already at zero, ie. all bytes sent. Exit if so.
OR E
JP Z,SD_WRITE5
DEC DE
PUSH DE
LD A,0 ; Send 0's as padding bytes and CRC.
CALL SPIOUT
POP DE
JP SD_WRITE4
SD_WRITE5: CALL SPIIN ; Check received response, if 0x05 which indicates write under way inside SD Card.
AND 01FH
LD L,A
LD H,0
CP 5
JP NZ,SD_WRITE11
LD HL,10000 ; Now wait for the write to complete allowing 1000mS before timing out.
PUSH HL
JR SD_WRITE7
SD_WRITE6: DEC HL
PUSH HL
LD HL,200 ; 200T state delay = 200 x 1/2000000 = 100uS
CALL T_DELAY
SD_WRITE7: CALL SPIIN ; Get a byte, if it is not 0xFF then we have our response so exit.
POP HL
CP 255
JP Z,SD_WRITE8
LD A,H
OR L
JR NZ,SD_WRITE6
SD_WRITE8: LD A,H ; End of timeout? If so we exit with the preset fail code.
OR L
JP Z,SD_WRITE11
XOR A ; Success code.
SD_WRITE9: PUSH AF
LD A,000H ; Disable SD Card Chip Select to finish.
CALL SPICS
POP AF
RET
SD_WRITE10: POP HL ; Waste the load address.
SD_WRITE11: LD A,1 ; Error exit.
JR SD_WRITE9
; Method to multiply a 16bit number by another 16 bit number to arrive at a 32bit result.
; Input: DE = Factor 1
; BC = Factor 2
; Output:DEHL = 32bit Product
;
MULT16X16: LD HL,0
LD A,16
MULT16X1: ADD HL,HL
RL E
RL D
JR NC,$+6
ADD HL,BC
JR NC,$+3
INC DE
DEC A
JR NZ,MULT16X1
RET
; Method to add a 16bit number to a 32bit number to obtain a 32bit product.
; Input: DEHL = 32bit Addend
; BC = 16bit Addend
; Output:DEHL = 32bit sum.
;
ADD3216: ADD HL,BC
EX DE,HL
LD BC,0
ADC HL,BC
EX DE,HL
RET
; Method to add two 32bit numbers whilst calculating the SD Start Sector.
; Input: DEHL = 32bit Addend
; (SDSTARTSEC) = 32bit Addend
; Output: (SDSTARTSEC) = 32bit Sum.
; Output; DEHL = 32bit Sum.
;
ADD32: LD BC,(SDSTARTSEC+2)
ADD HL,BC
LD (SDSTARTSEC+2),HL
LD BC,(SDSTARTSEC)
EX DE,HL
ADC HL,BC
LD (SDSTARTSEC),HL
EX DE,HL
RET
; Method to get the LBA sector from the current CP/M Track and Sector.
; This method needs to account for the Rom Filing System image and the other CPM disk images on the SD card.
;
; Input: (CDISK) = Disk number
; (HSTTRK) = Track
; (HSTSEC) = Sector
; Output: (SDSTARTSEC) = LBA on SD Card for the desired sector.
; DEHL = LBA on SD Card for the desired sector.
;
?SD_GETLBA: PUSH AF ; If needed, pass A and flags via the stack. NB This push is removed by BANKTOBANK so no need to pop after the call.
LD A,ROMBANK11 << 4 | ROMBANK10 ; Calling a function in Bank 11 (CBIOS Bank 4) and returning to current bank 10 (CBIOS Bank 3).
LD HL,QGETMAPDSK ; Calling the map disk function.
CALL BANKTOBANK ; Now make a bank to bank function call.
CP 0FFH
JR Z,SDGETLBAX ; This isnt a physical, ROM disk or SD disk, no need to perform any actions, exit.
CP 040H
JR C,SDGETLBAX ; This isnt a ROM disk or an SD disk, no need to perform any actions, exit.
AND 03FH ; Get the SD disk number.
LD B,0
LD C,A
LD DE,CPM_SD_IMGSZ / SD_SECSIZE
CALL MULT16X16
LD (SDSTARTSEC),DE
LD (SDSTARTSEC+2),HL
; DEHL contains the offset for the Disk number, ie. 0 for drive 1, CPM IMAGE SIZE for drive 2, 2x CPM IMAGE SIZE for drive 3 etc.
LD B,0
LD C, SD_SECPTRK ; Number of sectors per track.
LD DE,(HSTTRK) ; For the SD Card we use the full 16bit track number.
CALL MULT16X16
; Add the two.
CALL ADD32
; Add the number of sectors directly to the current sum.
LD A,(HSTSEC)
LD C,A
LD B,0
CALL ADD3216
; Now add the offset to account for the RFS image.
LD BC, RFS_IMGSZ/SD_SECSIZE ; Sector offset for the RFS Image.
CALL ADD3216
; Store the final sum as the start sector.
PUSH HL
LD HL,SDSTARTSEC
LD (HL),D
INC HL
LD (HL),E
INC HL
POP DE
LD (HL),D
INC HL
LD (HL),E
LD HL,(SDSTARTSEC)
OR 1 ; Indicate we successfully mapped the track/sector to an LBA.
SDGETLBAX: RET
; Method to read a sector for CPM using its track/sector addressing. All reads occur in a 512byte sector.
;
; Inputs: (HSTTRK) - 16bit track number.
; (HSTSEK) - 8bit sector number.
; (CDISK) - Disk drive number.
?SDC_READ: CALL ?SD_GETLBA ; Get the SD card sector in LBA,
LD A,1
JP Z,SDC_READ1 ; Error in read, exit with stack tidy.
LD HL,HSTBUF ; Address of the host buffer to hold the sector.
CALL ?SD_READ ; Read in the sector.
OR A
JR NZ,SDC_READ1 ; Check for errors and report.
XOR A ; Indicate success.
SDC_READ1: RET
; Method to write a sector for CPM using its track/sector addressing. All writes occur in a 512byte sector.
;
; Inputs: (HSTTRK) - 16bit track number.
; (HSTSEK) - 8bit sector number.
; (CDISK) - Disk drive number.
; Outputs: A = 1 - Error.
; A = 0 - Success.
?SDC_WRITE: CALL ?SD_GETLBA ; Get the SD card sector in LBA,
LD A,1
JP Z,SDC_WRITE1 ; Error in read, exit with stack tidy.
LD HL,HSTBUF ; Setup the location of the buffer to write.
CALL ?SD_WRITE ; Call write to write the buffer into the given sector.
JR NZ,SDC_WRITE1
XOR A
SDC_WRITE1: RET
;-------------------------------------------------------------------------------
; END OF SD CARD CONTROLLER FUNCTIONALITY
;-------------------------------------------------------------------------------
ALIGN_NOPS UROMADDR + 0800h

View File

@@ -27,11 +27,11 @@
;- along with this program. If not, see <http://www.gnu.org/licenses/>.
;--------------------------------------------------------------------------------------------------------
;======================================
;============================================================
;
; USER ROM CPM CBIOS BANK 4
; USER ROM CPM CBIOS BANK 4 - Floppy Disk Controller functions.
;
;======================================
;============================================================
ORG UROMADDR
;-----------------------------------------------------------------------------------------
@@ -44,9 +44,562 @@
NOP
; After switching in Bank 0, it will automatically continue processing in Bank 0 at the XOR A instructionof ROMFS:
;-------------------------------------------------------------------------------
; Jump table for entry into this pages functions.
;-------------------------------------------------------------------------------
JP ?DSKINIT ; 9 DSKINIT
JP ?SETDRVCFG ; 12 SETDRVCFG
JP ?SETDRVMAP ; 15 SETDRVMAP
JP ?SELDRIVE ; 18 SELDRIVE
JP ?GETMAPDSK ; 21 GETMAPDSK
JP ?DSKREAD ; 24 DSKREAD
JP ?DSKWRITE ; 24 DSKWRITE
;-------------------------------------------------------------------------------
; START OF FDC CONTROLLER FUNCTIONALITY
;-------------------------------------------------------------------------------
;------------------------------------------------------------------------------------------------
; Initialise drive and reset flags, Set motor off
;
;------------------------------------------------------------------------------------------------
?DSKINIT: XOR A
OUT (FDC_MOTOR),A ; Motor off
LD (TRK0FD1),A ; Track 0 flag drive 1
LD (TRK0FD2),A ; Track 0 flag drive 2
LD (TRK0FD3),A ; Track 0 flag drive 3
LD (TRK0FD4),A ; Track 0 flag drive 4
LD (MOTON),A ; Motor on flag
LD (MTROFFTIMER),A ; Clear the down counter for motor off.
LD A,(FDCROMADDR) ; Check to see if the FDC AFI ROM is installed, use this as
OR A ; an indicator that the FDC is present.
RET
; Function to create a mapping table between a CPM disk and a physical disk.
?SETDRVMAP: PUSH HL
PUSH DE
PUSH BC
; Zero out the map.
LD B,MAXDISKS
LD HL,DISKMAP
LD A,0FFH
SETDRVMAP1: LD (HL),A
INC HL
DJNZ SETDRVMAP1
LD HL,DISKMAP ; Place in the Map for next drive.
; Now go through each disk from the Disk Parameter Base list.
LD B,0 ; Disk number count = CDISK.
LD DE,0 ; Physical disk number, D = FDC, E = SDC.
SETDRVMAP2: LD A,B
CP MAXDISKS
JR Z,SETDRVMAP6
INC B
PUSH HL
PUSH DE
PUSH BC
; For the Disk in A, find the parameter table.
RLC A ; *2
RLC A ; *4
RLC A ; *8
RLC A ; *16
LD HL,DPBASE ; Base of disk description block.
LD B,0
LD C,A
ADD HL,BC ; HL contains address of actual selected disk block.
LD C,10
ADD HL,BC ; HL contains address of pointer to disk parameter block.
LD E,(HL)
INC HL
LD D,(HL) ; DE contains address of disk parameter block.
EX DE,HL
LD A,(HL)
LD E,A
LD BC,15
ADD HL,BC ; Move to configuuration byte which identifies the disk type.
;
POP BC
POP DE
LD A,(HL)
POP HL
BIT 4,A ; Disk type = FDC
JR Z,SETDRVMAP4 ; Is this an FDC controlled disk, if so store the mapping number in the map unchanged.
;
BIT 3,A ; Is this an SD Card disk, if so, add 080H to the mapping number and store.
JR Z,SETDRVMAP3
LD A,E
OR 080H
INC E
JR SETDRVMAP5
SETDRVMAP3: LD A,E ; This is a ROM drive, add 040H to the mapping number and store.
OR 040H
INC E
JR SETDRVMAP5
;
SETDRVMAP4: LD A,D
INC D
SETDRVMAP5: LD (HL),A
INC HL
JR SETDRVMAP2
;
SETDRVMAP6: POP BC
POP DE
POP HL
RET
; Function to setup the drive parameters according to the CFG byte in the disk parameter block.
?SETDRVCFG: PUSH HL
PUSH DE
PUSH BC
LD A,(CDISK)
RLC A ; *2
RLC A ; *4
RLC A ; *8
RLC A ; *16
LD HL,DPBASE ; Base of disk description block.
LD B,0
LD C,A
ADD HL,BC ; HL contains address of actual selected disk block.
LD C,10
ADD HL,BC ; HL contains address of pointer to disk parameter block.
LD E,(HL)
INC HL
LD D,(HL) ; DE contains address of disk parameter block.
EX DE,HL
LD A,(HL)
LD E,A
LD BC,15
ADD HL,BC ; Move to configuuration byte.
XOR A
BIT 2,(HL)
JR Z,SETDRV0
INC A
SETDRV0: LD (INVFDCDATA),A ; Data inversion is set according to drive parameter.
LD A,4
BIT 1,(HL)
JR Z,SETDRV1
LD A,2
BIT 0,(HL)
JR Z,SETDRV1
LD A,1
SETDRV1: LD (SECTORCNT),A ; Set the disk sector size.
LD D,A
CP 4
LD A,E
JR Z,SETDRV1A
OR A
RR A
LD E,A
LD A,D
CP 2
LD A,E
JR Z,SETDRV1A
OR A
RR A ; Convert sectors per track from 128 bytes to 256 byte sectors.
SETDRV1A: INC A ; Add 1 to ease comparisons.
LD (SECPERTRK),A ; Only cater for 8bit, ie. 256 sectors.
DEC A
OR A
RR A
INC A ; Add 1 to ease comparisons.
LD (SECPERHEAD),A ; Convert sectors per track to sectors per head.
;
XOR A ; Disk type = FDC
BIT 4,(HL)
JR Z,SETDRV2
LD A,DSKTYP_ROM ; Disk type = ROMFS
BIT 3,(HL)
JR Z,SETDRV2
LD A,DSKTYP_SDC ; Disk type = SD Card
SETDRV2: LD (DISKTYPE),A
POP BC
POP DE
POP HL
RET
; Method to get the current disk drive mapped to the correct controller.
; The CPM CDISK is mapped via MAPDISK[CDISK] and the result:
; Bit 7 = 1 - SD Card drive.
; Bit 6 = 1 - ROM Drive.
; BIT 7:6 = 00 - Floppy drive.
?GETMAPDSK: PUSH HL
PUSH BC
LD A,(CDISK)
LD HL,DISKMAP
LD C,A
LD B,0
ADD HL,BC
LD A,(HL) ; Get the physical number after mapping from the CDISK.
POP BC
POP HL
RET NC ; This isnt a physical floppy disk, no need to perform any actions, exit.
; Select FDC drive (make active) based on value in DISKMAP[CDISK].
?SELDRIVE: CALL ?GETMAPDSK
CP 040H ; Anything with bit 6 or 7 set is not an FDC drive.
RET NC ; This isnt a physical floppy disk, no need to perform any actions, exit.
LD (FDCDISK),A
CALL DSKMTRON ; yes, set motor on and wait
LD A,(FDCDISK) ; select drive no
OR 084H
OUT (FDC_MOTOR),A ; Motor on for drive 0-3
XOR A
LD (FDCCMD),A ; clr latest FDC command byte
LD HL,00000H
SELDRV2: DEC HL
LD A,H
OR L
JP Z,SELDRVERR ; Reset and print message that this is not a valid disk.
IN A,(FDC_STR) ; Status register.
CPL
RLCA
JR C,SELDRV2 ; Wait on Drive Ready Bit (bit 7)
LD A,(FDCDISK) ; Drive number
LD C,A
LD HL,TRK0FD1 ; 1 track 0 flag for each drive
LD B,000H
ADD HL,BC ; Compute related flag 1002/1003/1004/1005
BIT 0,(HL)
JR NZ,SELDRV3 ; If the drive hasnt been intialised to track 0, intialise and set flag.
CALL DSKSEEKTK0 ; Seek track 0.
SET 0,(HL) ; Set bit 0 of trk 0 flag
SELDRV3: CALL ?SETDRVCFG
RET
; Turn disk motor on if not already running.
DSKMTRON: LD A,255 ; Ensure motor is kept running whilst we read/write.
LD (MTROFFTIMER),A
LD A,(MOTON) ; Test to see if motor is on, if it isnt, switch it on.
RRCA
JR NC, DSKMOTORON
RET
DSKMOTORON: PUSH BC
LD A,080H
OUT (FDC_MOTOR),A ; Motor on
LD B,010H ;
DSKMTR2: CALL MTRDELAY ;
DJNZ DSKMTR2 ; Wait until becomes ready.
LD A,001H ; Set motor on flag.
LD (MOTON),A ;
POP BC
RET
FDCDLY1: PUSH DE
LD DE,00007H
JP MTRDEL2
MTRDELAY: PUSH DE
LD DE,01013H
MTRDEL2: DEC DE
LD A,E
OR D
JR NZ,MTRDEL2
POP DE
RET
?DSKWRITE: LD A,MAXWRRETRY
LD (RETRIES),A
LD A,(SECTORCNT)
LD B,A
LD A,(HSTSEC)
DSKWRITE0A: DJNZ DSKWRITE0B
JR DSKWRITE1
DSKWRITE0B: OR A
RL A
JR DSKWRITE0A
DSKWRITE1: INC A
LD (SECTORNO), A ; Convert from Host 512 byte sector into local sector according to paraameter block.
LD HL,(HSTTRK)
LD (TRACKNO),HL
DSKWRITE2: CALL SETTRKSEC ; Set current track & sector, get load address to HL
DSKWRITE3: CALL SETHEAD ; Set side reg
CALL SEEK ; Command 1b output (seek)
JP NZ,SEEKRETRY ;
CALL OUTTKSEC ; Set track & sector reg
LD IX, 0F3FEH ; As below. L03FE
LD IY,WRITEDATA ; Write sector from memory.
DI
;
LD A,0B4H ; Write Sector multipe with Side Compare for side 1.
CALL DISKCMDWAIT
LD D,2 ; Regardless of 4x128, 2x256 or 1x512, we always read 512bytes by the 2x INI instruction with B=256.
STRTDATWR: LD B,0 ; 256 bytes to load.
JP (IX)
WRITEDATA: OUTI
JP NZ, 0F3FEH ; This is crucial, as the Z80 is running at 2MHz it is not fast enough so needs
; hardware acceleration in the form of a banked ROM, if disk not ready jumps to IX, if
; data ready, jumps to IY.
DEC D
JP NZ,0F3FEH ; If we havent read all sectors to form a 512 byte block, go for next sector.
JR DATASTOP
; Read disk starting at the first logical sector in param block 1009/100A
; Continue reading for the given size 100B/100C and store in the location
; Pointed to by the address stored in the parameter block. 100D/100E
?DSKREAD: LD A,MAXRDRETRY
LD (RETRIES),A
LD A,(SECTORCNT)
LD B,A
LD A,(HSTSEC)
DSKREAD0A: DJNZ DSKREAD0B
JR DSKREAD1
DSKREAD0B: OR A
RL A
JR DSKREAD0A
DSKREAD1: INC A
LD (SECTORNO), A ; Convert from Host 512 byte sector into local sector according to paraameter block.
LD HL,(HSTTRK)
LD (TRACKNO),HL
DSKREAD2: CALL SETTRKSEC ; Set current track & sector, get load address to HL
DSKREAD3: CALL SETHEAD ; Set side reg
CALL SEEK ; Command 1b output (seek)
JP NZ,SEEKRETRY ;
CALL OUTTKSEC ; Set track & sector reg
LD IX, 0F3FEH ; As below. L03FE
LD IY,READDATA ; Read sector into memory.
DI
;
LD A,094H ; Read Sector multiple with Side Compare for side 1.
CALL DISKCMDWAIT
LD D,2 ; Regardless of 4x128, 2x256 or 1x512, we always read 512bytes by the 2x INI instruction with B=256.
STRTDATRD: LD B,0 ; 256 bytes to load.
JP (IX)
; Get data from disk sector to staging area.
READDATA: INI
JP NZ,0F3FEH ; This is crucial, as the Z80 is running at 2MHz it is not fast enough so needs
; hardware acceleration in the form of a banked ROM, if disk not ready jumps to IX, if
; data ready, jumps to IY.
DEC D
JP NZ,0F3FEH ; If we havent read all sectors to form a 512 byte block, go for next sector.
;
;
DATASTOP: LD A,0D8H ; Force interrupt command, Immediate interrupt (I3 bit 3=1) of multiple sector read.
CPL
OUT (FDC_CR),A
CALL WAITRDY ; Wait for controller to become ready, acknowledging interrupt.
IN A,(FDC_STR) ; Check for errors.
CPL
AND 0FFH
JR NZ,SEEKRETRY
UPDSECTOR: PUSH HL
LD A,(SECTORCNT)
LD HL,SECTORNO
ADD A,(HL) ; Update sector to account for sectors read. NB. All reads will start at such a position
LD (HL), A ; that a read will not span a track or head. Ensure that disk formats meet an even 512byte format.
POP HL
MOTOROFF: LD A,MTROFFMSECS ; Schedule motor to be turned off.
LD (MTROFFTIMER),A
XOR A ; Successful read, return 0
EI
RET
SEEKRETRY: LD B,A ; Preserve the FDC Error byte.
LD A,(RETRIES)
DEC A
LD (RETRIES),A
LD A,B
JP Z,RETRIESERR
CALL DSKSEEKTK0
LD A, (READOP)
OR A
LD A,(TRACKNO) ; NB. Track number is 16bit, FDC only uses lower 8bit and assumes little endian read.
JP Z, DSKWRITE2 ; Try write again.
JP DSKREAD2 ; Try the read again.
DISKCMDWAIT:LD (FDCCMD),A
CPL
OUT (FDC_CR),A
CALL WAITBUSY
RET
; Send a command to the disk controller.
DSKCMD: LD (FDCCMD),A ; Store latest FDC command.
CPL ; Compliment it (FDC bit value is reversed).
OUT (FDC_CR),A ; Send command to FDC.
CALL WAITRDY ; Wait to become ready.
IN A,(FDC_STR) ; Get status register.
CPL ; Inverse (FDC is reverse bit logic).
RET
; Seek to programmed track.
SEEK: LD A,01BH ; Seek command, load head, verify stepping 6ms.
CALL DSKCMD
AND 099H
RET
; Set current track & sector, get load address to HL
SETTRKSEC: CALL ?SELDRIVE
LD A,(TRACKNO) ; NB. Track number is 16bit, FDC only uses lower 8bit and assumes little endian read.
LD HL, HSTBUF
RET
; Compute side/head.
SETHEAD: CPL ;
OUT (FDC_DR),A ; Output track no for SEEK command.
PUSH HL
LD HL,SECPERHEAD
LD A,(SECTORNO) ; Check sector, if greater than sector per track, change head.
CP (HL)
POP HL
JR NC,SETHD2 ; Yes, even, set side/head 1
LD A,001H ; No, odd, set side/head 0
JR SETHD3
; Set side/head register.
SETHD2: XOR A ; Side 0
SETHD3: CPL ; Side 1
OUT (FDC_SIDE),A ; Side/head register.
RET
; Set track and sector register.
OUTTKSEC: PUSH HL
LD HL,SECPERHEAD
;
LD C,FDC_DR ; Port for data retrieval in the INI instruction in main block.
LD A,(TRACKNO) ; Current track number, NB. Track number is 16bit, FDC only uses lower 8bit and assumes little endian read.
CPL
OUT (FDC_TR),A ; Track reg
;
LD A,(SECTORNO) ; Current sector number
CP (HL)
JR C,OUTTKSEC2
SUB (HL)
INC A ; Account for the +1 added to ease comparisons.
OUTTKSEC2: CPL
OUT (FDC_SCR),A ; Sector reg
POP HL
RET
; Seek to track 0.
DSKSEEKTK0: CALL DSKMTRON ; Make sure disk is spinning.
LD A,00BH ; Restore command, seek track 0.
CALL DSKCMD ; Send command to FDC.
AND 085H ; Process result.
XOR 004H
RET Z
JP DSKSEEKERR
; Wait for the drive to become ready.
WAITRDY: PUSH DE
PUSH HL
CALL FDCDLY1
LD E,007H
WAITRDY2: LD HL,00000H
WAITRDY3: DEC HL
LD A,H
OR L
JR Z,WAITRDY4
IN A,(FDC_STR)
CPL
RRCA
JR C,WAITRDY3
POP HL
POP DE
RET
WAITRDY4: DEC E
JR NZ,WAITRDY2
POP HL
POP DE
JP WAITRDYERR
WAITBUSY: PUSH DE
PUSH HL
CALL FDCDLY1
LD E,007H ; 7 Chances of a 16bit down count delay waiting for DRQ.
WAITBUSY2: LD HL,00000H
WAITBUSY3: DEC HL
LD A,H
OR L
JR Z,WAITBUSY4 ; Down counter expired, decrement retries, error on 0.
IN A,(FDC_STR) ; Get the FDC Status
CPL ; Switch to positive logic.
RRCA ; Shift Busy flag into Carry.
JR NC,WAITBUSY3 ; Busy not set, decrement counter and retry.
POP HL
POP DE
RET
WAITBUSY4: DEC E
JR NZ,WAITBUSY2
POP HL
POP DE
JP DSKERR
; Error processing. Consists of printing a message followed by debug data (if enabled) and returning with carry set
; to indicate error.
DSKERR: LD DE,LOADERR ; Loading error message
JR HDLERROR
SELDRVERR: LD DE,SELDRVMSG ; Select drive error message.
JR HDLERROR
WAITRDYERR: LD DE,WAITRDYMSG ; Waiting for ready timeout error message.
JR HDLERROR
DSKSEEKERR: LD DE,DSKSEEKMSG ; Disk seek to track error message.
JR HDLERROR
RETRIESERR: BIT 2,A ; Data overrun error if 1.
LD DE,DATAOVRMSG
JR NZ, RETRIESERR2
BIT 3,A ; CRC error if 1.
LD DE,CRCERRMSG
JR NZ,RETRIESERR2
LD DE,RETRIESMSG ; Data sector read error message.
RETRIESERR2:
; Process error, dump debug data and return fail code.
HDLERROR: LD HL,MSGSTRBUF ; Copy the error messae
HOLERR1: LD A,(DE)
LD (HL),A
CP NUL
JR Z,HOLERR2
INC DE
INC HL
JR HOLERR1
HOLERR2: LD DE,MSGSTRBUF
HOLPRTSTR: LD A,(DE)
OR A
JR Z,HOLERR3
INC DE
HOLPRTSTR2: LD HL,QPRNT
PUSH AF
LD A,ROMBANK9 << 4 | ROMBANK11 ; Call CBIOS Bank 2 from CBIOS Bank 4
CALL BANKTOBANK
JR HOLPRTSTR
HOLERR3: XOR A
CALL ?DSKINIT
CALL DSKMTRON
LD A,001H ; Indicate error by setting 1 in A register.
EI
RET
;-------------------------------------------------------------------------------
; END OF FDC CONTROLLER FUNCTIONALITY
;-------------------------------------------------------------------------------
;--------------------------------------
;
; Message table
;
;--------------------------------------
LOADERR: DB "DISK ERROR - LOADING", CR, NUL
SELDRVMSG: DB "DISK ERROR - SELECT", CR, NUL
WAITRDYMSG: DB "DISK ERROR - WAIT", CR, NUL
DSKSEEKMSG: DB "DISK ERROR - SEEK", CR, NUL
RETRIESMSG: DB "DISK ERROR - RETRIES", CR, NUL
DATAOVRMSG: DB "DISK ERROR - DATA OVERRUN", CR, NUL
CRCERRMSG: DB "DISK ERROR - CRC ERROR", CR, NUL
ALIGN_NOPS UROMADDR + 0800h
; Bring in additional macros.

View File

@@ -55,24 +55,15 @@
; -ALV Address of a scratch pad area used by the BDOS to keep disk storage allocation information.
; This address is different for each DPH.
;------------------------------------------------------------------------------------------------------------
DPBASE: DW 0000H, 0000H, 0000H, 0000H, CDIRBUF, DPBLOCK1, CSV0, ALV0
DW 0000H, 0000H, 0000H, 0000H, CDIRBUF, DPBLOCK2, CSV1, ALV1
DW 0000H, 0000H, 0000H, 0000H, CDIRBUF, DPBLOCK3, CSV2, ALV2
DW 0000H, 0000H, 0000H, 0000H, CDIRBUF, DPBLOCK3, CSV3, ALV3
ALIGN_NOPS DPBASE ; Space for 2xROM, 2xFD, 3xSD or upto 7 drives
; These entries are created dynamically based on hardware available.
; NB. The Disk Parameter Blocks are stored in CBIOS ROM to save RAM space.
;------------------------------------------------------------------------------------------------------------
; CPN Disk work areas.
;------------------------------------------------------------------------------------------------------------
CDIRBUF: DS 128 ; scratch directory area
CSV0: DS 32 ; (DRM + 1)/4 = scratch area for drive 0.
ALV0: DS (720/8)+1 ; (DSM/8) + 1 = allocation vector 0 NB.Set to largest DSM declared in DPB tables as drives can be switched.
CSV1: DS 32 ; scratch area for drive 1.
ALV1: DS (720/8)+1 ; allocation vector 1
CSV2: DS 32 ; scratch area for drive 2.
ALV2: DS (720/8)+1 ; allocation vector 2
CSV3: DS 32 ; scratch area for drive 3.
ALV3: DS (720/8)+1 ; allocation vector 3
ALIGN CBIOSDATA
ALIGN_NOPS CDIRBUF ; Memory work areas, just allocate the space.
ALIGN_NOPS CSVALVMEM
ALIGN_NOPS CSVALVEND
ALIGN CBIOSDATA

View File

@@ -56,9 +56,13 @@ WRITE EQU CBIOSSTART + 42
FRSTAT EQU CBIOSSTART + 45
SECTRN EQU CBIOSSTART + 48
UNUSED EQU CBIOSSTART + 51
BANKTOBANK EQU CBIOSSTART + 54
CCP EQU CBASE
CCPCLRBUF EQU CBASE + 3
CPMDPBASE EQU CPMBIOS
DPBASE EQU CPMBIOS
CDIRBUF EQU CPMBIOS + (MAXDISKS * 16)
CSVALVMEM EQU CDIRBUF + 128
CSVALVEND EQU CSVALVMEM + 1253
IOBYT EQU 00003H ; IOBYTE address
CDISK EQU 00004H ; Address of Current drive name and user number
CPMUSERDMA EQU 00080h ; Default CPM User DMA address.
@@ -72,12 +76,6 @@ DPBLOCK5 EQU DPBLOCK4 + DPSIZE
DPBLOCK6 EQU DPBLOCK5 + DPSIZE
DPBLOCK7 EQU DPBLOCK6 + DPSIZE
; BIOS equates
NDISKS EQU 4 ; Number of Disk Drives
KEYBUFSIZE EQU 16 ; Ensure this is a power of 2, max size 256.
; Debugging
ENADEBUG EQU 1 ; Enable debugging logic, 1 = enable, 0 = disable
;-----------------------------------------------
; Configurable settings.
@@ -101,24 +99,53 @@ SCRNSZ: EQU COLW * ROW ; Total
SCRLW: EQU COLW / 8 ; Number of 8 byte regions in a line for hardware scroll.
MODE80C: EQU 1
; BIOS equates
MAXDISKS EQU 7 ; Max number of Drives supported
KEYBUFSIZE EQU 16 ; Ensure this is a power of 2, max size 256.
; Debugging
ENADEBUG EQU 1 ; Enable debugging logic, 1 = enable, 0 = disable
;-------------------------------------------------------
; Function entry points in the CBIOS ROMS
;-------------------------------------------------------
; Public functions in CBIOS User ROM Bank 1.
; Public functions in CBIOS User ROM Bank 1 - utility functions, ie. Audio.
QREBOOT EQU 9 + UROMADDR
QMELDY EQU 12 + UROMADDR
QTEMP EQU 15 + UROMADDR
QMSTA EQU 18 + UROMADDR
QMSTP EQU 21 + UROMADDR
QBEL EQU 24 + UROMADDR
QMODE EQU 27 + UROMADDR
QTIMESET EQU 30 + UROMADDR
QTIMEREAD EQU 33 + UROMADDR
QCHKKY EQU 36 + UROMADDR
QGETKY EQU 39 + UROMADDR
; Public functions in CBIOS User ROM Bank 1.
; Public functions in CBIOS User ROM Bank 2 - Screen / ANSI terminal functions.
QPRNT EQU 9 + UROMADDR
QPRTHX EQU 12 + UROMADDR
QPRTHL EQU 15 + UROMADDR
QANSITERM EQU 18 + UROMADDR
; Public functions in CBIOS User ROM Bank 3 - SD Card functions.
SD_INIT EQU 9 + UROMADDR
SD_READ EQU 12 + UROMADDR
SD_WRITE EQU 15 + UROMADDR
SD_GETLBA EQU 18 + UROMADDR
SDC_READ EQU 21 + UROMADDR
SDC_WRITE EQU 24 + UROMADDR
; Public functions in CBIOS User ROM Bank 4 - Floppy Disk Controller functions.
QDSKINIT EQU 9 + UROMADDR
QSETDRVCFG EQU 12 + UROMADDR
QSETDRVMAP EQU 15 + UROMADDR
QSELDRIVE EQU 18 + UROMADDR
QGETMAPDSK EQU 21 + UROMADDR
QDSKREAD EQU 24 + UROMADDR
QDSKWRITE EQU 27 + UROMADDR
;-----------------------------------------------
; Memory mapped ports in hardware.
@@ -157,10 +184,12 @@ SPI_IN EQU 0FEH
;
DOUT_LOW EQU 000H
DOUT_HIGH EQU 004H
DOUT_MASK EQU 004H
DIN_LOW EQU 000H
DIN_HIGH EQU 001H
CLOCK_LOW EQU 000H
CLOCK_HIGH EQU 002H
CLOCK_MASK EQU 0FDH
CS_LOW EQU 000H
CS_HIGH EQU 001H
@@ -198,19 +227,21 @@ WRKROMBK2: EQU 01019H ; WORKI
; the User ROM bank.
;-----------------------------------------------
MROMPAGES EQU 8
USRROMPAGES EQU 12
ROMBANK0 EQU 0
ROMBANK1 EQU 1
ROMBANK2 EQU 2
ROMBANK3 EQU 3
ROMBANK4 EQU 4
ROMBANK5 EQU 5
ROMBANK6 EQU 6
ROMBANK7 EQU 7
ROMBANK8 EQU 8
ROMBANK9 EQU 9
ROMBANK10 EQU 10
ROMBANK11 EQU 11
USRROMPAGES EQU 12 ; Monitor ROM : User ROM
ROMBANK0 EQU 0 ; MROM SA1510 40 Char : RFS Bank 0 - Main RFS Entry point and functions.
ROMBANK1 EQU 1 ; MROM SA1510 80 Char : RFS Bank 1 - Floppy disk controller and utilities.
ROMBANK2 EQU 2 ; CPM 2.2 CBIOS : RFS Bank 2 - SD Card controller and utilities.
ROMBANK3 EQU 3 ; RFS Utilities : RFS Bank 3 - Cmdline tools (Memory, Printer, Help)
ROMBANK4 EQU 4 ; Free : RFS Bank 4 - CMT Utilities.
ROMBANK5 EQU 5 ; Free : RFS Bank 5
ROMBANK6 EQU 6 ; Free : RFS Bank 6
ROMBANK7 EQU 7 ; Free : RFS Bank 7 - Memory and timer test utilities.
ROMBANK8 EQU 8 ; : CBIOS Bank 1 - Utilities
ROMBANK9 EQU 9 ; : CBIOS Bank 2 - Screen / ANSI Terminal
ROMBANK10 EQU 10 ; : CBIOS Bank 3 - SD Card
ROMBANK11 EQU 11 ; : CBIOS Bank 4 - Floppy disk controller.
OBJCD EQU 001h
@@ -288,6 +319,67 @@ CLRKEY EQU 0F7H
HOMEKEY EQU 0F8H
BREAKKEY EQU 0FBH
; MMC/SD command (SPI mode)
CMD0 EQU 64 + 0 ; GO_IDLE_STATE
CMD1 EQU 64 + 1 ; SEND_OP_COND
ACMD41 EQU 0x40+41 ; SEND_OP_COND (SDC)
CMD8 EQU 64 + 8 ; SEND_IF_COND
CMD9 EQU 64 + 9 ; SEND_CSD
CMD10 EQU 64 + 10 ; SEND_CID
CMD12 EQU 64 + 12 ; STOP_TRANSMISSION
CMD13 EQU 64 + 13 ; SEND_STATUS
ACMD13 EQU 0x40+13 ; SD_STATUS (SDC)
CMD16 EQU 64 + 16 ; SET_BLOCKLEN
CMD17 EQU 64 + 17 ; READ_SINGLE_BLOCK
CMD18 EQU 64 + 18 ; READ_MULTIPLE_BLOCK
CMD23 EQU 64 + 23 ; SET_BLOCK_COUNT
ACMD23 EQU 0x40+23 ; SET_WR_BLK_ERASE_COUNT (SDC)
CMD24 EQU 64 + 24 ; WRITE_BLOCK
CMD25 EQU 64 + 25 ; WRITE_MULTIPLE_BLOCK
CMD32 EQU 64 + 32 ; ERASE_ER_BLK_START
CMD33 EQU 64 + 33 ; ERASE_ER_BLK_END
CMD38 EQU 64 + 38 ; ERASE
CMD55 EQU 64 + 55 ; APP_CMD
CMD58 EQU 64 + 58 ; READ_OCR
; Card type flags (CardType)
CT_MMC EQU 001H ; MMC ver 3
CT_SD1 EQU 002H ; SD ver 1
CT_SD2 EQU 004H ; SD ver 2
CT_SDC EQU CT_SD1|CT_SD2 ; SD
CT_BLOCK EQU 008H ; Block addressing
; Disk types.
DSKTYP_FDC EQU 0 ; Type of disk is a Floppy disk and handled by the FDC controller.
DSKTYP_ROM EQU 1 ; Type of disk is a ROM and handled by the ROM methods.
DSKTYP_SDC EQU 2 ; Type of disk is an SD Card and handled by the SD Card methods.
;
; Rom Filing System constants.
;
RFS_DIRENT EQU 256 ; Directory entries in the RFS directory.
RFS_DIRENTSZ EQU 32 ; Size of a directory entry.
RFS_DIRSIZE EQU RFS_DIRENT * RFS_DIRENTSZ ; Total size of the directory.
RFS_BLOCKSZ EQU 65536 ; Size of a file block per directory entry.
RFS_IMGSZ EQU RFS_DIRSIZE + (RFS_DIRENT * RFS_BLOCKSZ) ; Total size of the RFS image.
;
; CPM constants
;
CPM_SD_SEC EQU 32
CPM_SD_TRK EQU 1024
CPM_SD_IMGSZ EQU CPM_SD_TRK * CPM_SD_SEC * SD_SECSIZE
;
; SD Card constants.
;
SD_SECSIZE EQU 512 ; Default size of an SD Sector
SD_SECPTRK EQU CPM_SD_SEC ; Sectors of SD_SECSIZE per virtual track.
SD_TRACKS EQU CPM_SD_TRK ; Number of virtual tracks per disk image.
;-----------------------------------------------
; BIOS WORK AREA (MZ80A)
;-----------------------------------------------
@@ -301,6 +393,8 @@ KEYWRITE: DS virtual 2 ; Point
KEYREAD: DS virtual 2 ; Pointer into the buffer where the next character can be read.
KEYLAST: DS virtual 1 ; KEY LAST VALUE
KEYRPT: DS virtual 1 ; KEY REPEAT COUNTER
USRBANKSAV: DS virtual 1 ; Save user bank number when calling another user bank.
HLSAVE: DS virtual 2 ; Space to save HL register when manipulating stack.
;
SPV:
IBUFE: ; TAPE BUFFER (128 BYTES)
@@ -339,6 +433,7 @@ OCTV: DS virtual 1 ; OCTAV
RATIO: DS virtual 2 ; ONPU RATIO
;BUFER: DS virtual 81 ; GET LINE BUFFER
;KEYBUF: DS virtual 1 ; KEY BUFFER
DRVAVAIL DS virtual 1 ; Flag to indicate which drive controllers are available. Bit 2 = SD, Bit 1 = ROM, Bit 0 = FDC
TIMESEC DS virtual 6 ; RTC 48bit TIME IN MILLISECONDS
FDCCMD DS virtual 1 ; LAST FDC COMMAND SENT TO CONTROLLER.
MOTON DS virtual 1 ; MOTOR ON = 1, OFF = 0
@@ -355,13 +450,13 @@ TMPCNT DS virtual 2 ; TEMPO
CPMROMLOC: DS virtual 2 ; Upper Byte = ROM Bank, Lower Byte = Page of CPM Image.
CPMROMDRV0: DS virtual 2 ; Upper Byte = ROM Bank, Lower Byte = Page of CPM Rom Drive Image Disk 0.
CPMROMDRV1: DS virtual 2 ; Upper Byte = ROM Bank, Lower Byte = Page of CPM Rom Drive Image Disk 1.
DISKMAP: DS virtual NDISKS ; Disk map of CPM logical to physical controller disk.
NDISKS: DS virtual 1 ; Dynamically calculated number of disks on boot.
DISKMAP: DS virtual MAXDISKS ; Disk map of CPM logical to physical controller disk.
FDCDISK: DS virtual 1 ; Physical disk number.
SECPERTRK: DS virtual 1 ; Sectors per track for 1 head.
SECPERHEAD: DS virtual 1 ; Sectors per head.
SECTORCNT: DS virtual 1 ; Sector size as a count of how many sectors make 512 bytes.
DISKTYPE: DS virtual 1 ; Disk type of current selection.
ROMDRV: DS virtual 1 ; ROM Drive Image to use.
MTROFFTIMER:DS virtual 1 ; Second down counter for FDC motor off.
;
SEKDSK: DS virtual 1 ; Seek disk number
@@ -390,6 +485,11 @@ DMAADDR: DS virtual 2 ; Last
HSTBUF: DS virtual 512 ; Host buffer for disk sector storage
HSTBUFE:
SDVER: DS virtual 1 ; SD Card version.
SDCAP: DS virtual 1 ; SD Card capabilities..
SDSTARTSEC DS virtual 4 ; Starting sector of data to read/write from/to SD card.
SDBUF: DS virtual 11 ; SD Card command fram buffer for the command and response storage.
CURSORPSAV DS virtual 2 ; Cursor save position;default 0,0
HAVELOADED DS virtual 1 ; To show that a value has been put in for Ansi emualtor.
ANSIFIRST DS virtual 1 ; Holds first character of Ansi sequence
@@ -414,9 +514,8 @@ COLOUR EQU 0
SPSAVE: DS virtual 2 ; CPM Stack save.
SPISRSAVE: DS virtual 2
VAREND EQU $ ; End of variables
; Stack space for the CBIOS.
DS virtual 64
MSGSTRBUF: DS virtual 128 ; Lower end of the stack space is for interbank message printing, ie.space for a string to print.
BIOSSTACK EQU $
; Stack space for the Interrupt Service Routine.
DS virtual 16 ; Max 8 stack pushes.

View File

@@ -26,6 +26,13 @@
;- along with this program. If not, see <http://www.gnu.org/licenses/>.
;--------------------------------------------------------------------------------------------------------
;-----------------------------------------------
; Entry/compilation start points.
;-----------------------------------------------
UROMADDR EQU 0E800H ; Start of User ROM Address space.
RFSJMPTABLE EQU UROMADDR + 00080H ; Start of jump table.
FDCROMADDR EQU 0F000H
;-------------------------------------------------------
; Function entry points in the standard SA-1510 Monitor.
;-------------------------------------------------------
@@ -99,6 +106,23 @@ RFSBK2: EQU 0EFFDh ; Selec
RFSRST1: EQU 0EFFEh ; Reset RFS Bank1 to original.
RFSRST2: EQU 0EFFFh ; Reset RFS Bank2 to original.
;-----------------------------------------------
; IO ports in hardware and values.
;-----------------------------------------------
SPI_OUT EQU 0FFH
SPI_IN EQU 0FEH
;
DOUT_LOW EQU 000H
DOUT_HIGH EQU 004H
DOUT_MASK EQU 004H
DIN_LOW EQU 000H
DIN_HIGH EQU 001H
CLOCK_LOW EQU 000H
CLOCK_HIGH EQU 002H
CLOCK_MASK EQU 0FDH
CS_LOW EQU 000H
CS_HIGH EQU 001H
;-----------------------------------------------
; Rom File System Header (MZF)
;-----------------------------------------------
@@ -122,6 +146,7 @@ MZFHDRSZ EQU 128
RFSSECTSZ EQU 256
MROMSIZE EQU 4096
UROMSIZE EQU 2048
FNSIZE EQU 17
;-----------------------------------------------
; ROM Banks, 0-7 are reserved for alternative
@@ -133,55 +158,84 @@ UROMSIZE EQU 2048
; the User ROM bank.
;-----------------------------------------------
MROMPAGES EQU 8
USRROMPAGES EQU 12
ROMBANK0 EQU 0
ROMBANK1 EQU 1
ROMBANK2 EQU 2
ROMBANK3 EQU 3
ROMBANK4 EQU 4
ROMBANK5 EQU 5
ROMBANK6 EQU 6
ROMBANK7 EQU 7
ROMBANK8 EQU 8
ROMBANK9 EQU 9
ROMBANK10 EQU 10
ROMBANK11 EQU 11
USRROMPAGES EQU 12 ; Monitor ROM : User ROM
ROMBANK0 EQU 0 ; MROM SA1510 40 Char : RFS Bank 0 - Main RFS Entry point and functions.
ROMBANK1 EQU 1 ; MROM SA1510 80 Char : RFS Bank 1 - Floppy disk controller and utilities.
ROMBANK2 EQU 2 ; CPM 2.2 CBIOS : RFS Bank 2 - SD Card controller and utilities.
ROMBANK3 EQU 3 ; RFS Utilities : RFS Bank 3 - Cmdline tools (Memory, Printer, Help)
ROMBANK4 EQU 4 ; Free : RFS Bank 4 - CMT Utilities.
ROMBANK5 EQU 5 ; Free : RFS Bank 5
ROMBANK6 EQU 6 ; Free : RFS Bank 6
ROMBANK7 EQU 7 ; Free : RFS Bank 7 - Memory and timer test utilities.
ROMBANK8 EQU 8 ; : CBIOS Bank 1 - Utilities
ROMBANK9 EQU 9 ; : CBIOS Bank 2 - Screen / ANSI Terminal
ROMBANK10 EQU 10 ; : CBIOS Bank 3 - SD Card
ROMBANK11 EQU 11 ; : CBIOS Bank 4 - Floppy disk controller.
OBJCD EQU 001h
;-----------------------------------------------
; Common character definitions.
;-----------------------------------------------
SCROLL EQU 01H ; Set scrool direction UP.
BELL EQU 07H
SPACE EQU 20H
TAB EQU 09H ; TAB ACROSS (8 SPACES FOR SD-BOARD)
CR EQU 0DH
LF EQU 0AH
FF EQU 0CH
ESC EQU 1BH
DELETE EQU 7FH
BACKS EQU 08H
SCROLL EQU 001H ; Set scrool direction UP.
BELL EQU 007H
SPACE EQU 020H
TAB EQU 009H ; TAB ACROSS (8 SPACES FOR SD-BOARD)
CR EQU 00DH
LF EQU 00AH
FF EQU 00CH
ESC EQU 01BH
DELETE EQU 07FH
BACKS EQU 008H
SOH EQU 1 ; For XModem etc.
EOT EQU 4
ACK EQU 6
NAK EQU 15H
NUL EQU 00H
NULL EQU 000H
CTRL_A EQU 001H
CTRL_B EQU 002H
CTRL_C EQU 003H
CTRL_D EQU 004H
CTRL_E EQU 005H
CTRL_F EQU 006H
CTRL_G EQU 007H
CTRL_H EQU 008H
CTRL_I EQU 009H
CTRL_J EQU 00AH
CTRL_K EQU 00BH
CTRL_L EQU 00CH
CTRL_M EQU 00DH
CTRL_N EQU 00EH
CTRL_O EQU 00FH
CTRL_P EQU 010H
CTRL_Q EQU 011H
CTRL_R EQU 012H
CTRL_S EQU 013H
CTRL_T EQU 014H
CTRL_U EQU 015H
CTRL_V EQU 016H
CTRL_W EQU 017H
CTRL_X EQU 018H
CTRL_Y EQU 019H
CTRL_Z EQU 01AH
CTRL_SLASH EQU 01CH
CTRL_RB EQU 01DH
CTRL_CAPPA EQU 01EH
CTRL_UNDSCR EQU 01FH
CTRL_AT EQU 000H
NOKEY EQU 0F0H
CURSRIGHT EQU 0F1H
CURSLEFT EQU 0F2H
CURSUP EQU 0F3H
CURSDOWN EQU 0F4H
DBLZERO EQU 0F5H
INSERT EQU 0F6H
CLRKEY EQU 0F7H
HOMEKEY EQU 0F8H
BREAKKEY EQU 0FBH
SPI_OUT EQU 0FFH
SPI_IN EQU 0FEH
DOUT_LOW EQU 000H
DOUT_HIGH EQU 004H
DOUT_MASK EQU 004H
DIN_LOW EQU 000H
DIN_HIGH EQU 001H
CLOCK_LOW EQU 000H
CLOCK_HIGH EQU 002H
CLOCK_MASK EQU 0FDH
CS_LOW EQU 000H
CS_HIGH EQU 001H
; MMC/SD command (SPI mode)
CMD0 EQU 64 + 0 ; GO_IDLE_STATE
CMD1 EQU 64 + 1 ; SEND_OP_COND
@@ -234,7 +288,7 @@ SDDIR_SSEC EQU 013H
SDDIR_SIZE EQU 015H
SDDIR_LOAD EQU 017H
SDDIR_EXEC EQU 019H
SDDIR_FNSZ EQU 17
SDDIR_FNSZ EQU FNSIZE
SDDIR_ENTSZ EQU 32
;-----------------------------------------------
@@ -247,7 +301,7 @@ STACK: EQU 010F0H
SPV:
IBUFE: ; TAPE BUFFER (128 BYTES)
ATRB: DS virtual 1 ; ATTRIBUTE
NAME: DS virtual 17 ; FILE NAME
NAME: DS virtual FNSIZE ; FILE NAME
SIZE: DS virtual 2 ; BYTESIZE
DTADR: DS virtual 2 ; DATA ADDRESS
EXADR: DS virtual 2 ; EXECUTION ADDRESS

File diff suppressed because it is too large Load Diff

View File

@@ -27,12 +27,12 @@
;- along with this program. If not, see <http://www.gnu.org/licenses/>.
;--------------------------------------------------------------------------------------------------------
;======================================
;============================================================
;
; USER ROM BANK 1
; USER ROM BANK 1 - Floppy Disk Controller functions.
;
;======================================
ORG 0E800h
;============================================================
ORG UROMADDR
;--------------------------------
; Common code spanning all banks.
@@ -109,11 +109,19 @@ TRK0FD3 EQU 01004H
TRK0FD4 EQU 01005H
RETRIES EQU 01006H
BPARA EQU 01008H
;======================================
;-------------------------------------------------------------------------------
; START OF FLOPPY DISK CONTROLLER FUNCTIONALITY
;-------------------------------------------------------------------------------
; Method to check if the floppy interface ROM is present and if it is, jump to its entry point.
;
; Floppy Disk Interface
;
;======================================
FDCK: CALL FDCKROM ; Check to see if the Floppy ROM is present, exit if it isnt.
CALL Z,0F000h
RET ; JP CMDCMPEND
FDCKROM: LD A,(0F000h)
OR A
RET
FLOPPY: PUSH DE ; Preserve pointer to input buffer.
LD DE,BPARA ; Copy disk parameter block into RAM work area. (From)
@@ -479,7 +487,15 @@ L0300: IN A,(0D8H) ; Sta
JR C,L0300 ; Wait on data reg ready
JP (IY) ; to f1df
; Messages
;-------------------------------------------------------------------------------
; END OF FLOPPY DISK CONTROLLER FUNCTIONALITY
;-------------------------------------------------------------------------------
;--------------------------------------
;
; Message table
;
;--------------------------------------
BOOTDRV: DB "FLOPPY BOOT DRIVE ?", 00DH
LOADERR: DB "DISK LOADING ERROR", 00DH
IPLLOAD: DB "DISK LOADING ", 00DH
@@ -492,13 +508,11 @@ DSKID: DB 002H, "IPLPRO"
; Parameter block to indicate configuration and load area.
PRMBLK: DB 000H, 000H, 000H, 000H, 001H, 000H, 0CEH, 000H, 000H, 000H, 000H
; Ensure we fill the entire 1K by padding with FF's.
; Ensure we fill the entire 2K by padding with FF's.
ALIGN 0EBFDh
DB 0FFh
L03FE: JP (IY)
;DB 0DDH
;DB 0E9H
ALIGN 0EFFFh
DB 0FFh

View File

@@ -27,12 +27,12 @@
;- along with this program. If not, see <http://www.gnu.org/licenses/>.
;--------------------------------------------------------------------------------------------------------
;======================================
;===========================================================
;
; USER ROM BANK 2
; USER ROM BANK 2 - SD Card Controller functions.
;
;======================================
ORG 0E800h
;===========================================================
ORG UROMADDR
;--------------------------------
; Common code spanning all banks.
@@ -98,7 +98,9 @@ BKSWRET2: POP BC
POP AF
RET ; Return to caller.
;-------------------------------------------------------------------------------
; START OF SD CONTROLLER FUNCTIONALITY
;-------------------------------------------------------------------------------
; Method to initialise the SD card.
;
@@ -308,17 +310,19 @@ SDACMD: PUSH AF
LD HL,00000H ; NB. Important, HL should be coded as LH due to little endian and the way it is used in SDCMD.
LD DE,00000H ; NB. Important, DE should be coded as ED due to little endian and the way it is used in SDCMD.
CALL SDCMD
LD A,(SDBUF+6) ; Should be a response of 0 whereby the card has left idle.
DEC A
JR NZ,SDACMD
POP HL
POP DE
LD A,(SDBUF+6) ; Should be a response of 0 or 1.
CP 2
JR NC,SDACMD0
POP AF
CALL SDCMD
LD A,(SDBUF+6) ; Should be a response of 0 whereby the card has left idle.
OR A
RET
SDACMD0: POP AF
CP 1
RET
; Method to send Application Command 41 to the SD card. This command involves retries and delays
; hence coded seperately.
@@ -331,8 +335,6 @@ SDACMD1: PUSH BC
LD HL,00040H ; NB. Important, HL should be coded as LH due to little endian and the way it is used in SDCMD.
LD DE,00000H ; NB. Important, DE should be coded as ED due to little endian and the way it is used in SDCMD.
CALL SDACMD
LD A,(SDBUF+6) ; Should be a response of 0 whereby the card has left idle.
OR A
JR Z,SDACMD3
LD BC,12903 ; Delay for at least 200mS for the card to recover and be ready.
SDACMD2: DEC BC ; 6T
@@ -346,7 +348,10 @@ SDACMD2: DEC BC ; 6T
OR C
JR NZ,SDACMD1
LD A,1
SDACMD3: OR A
OR A ; Retries exceeded, return error.
RET
SDACMD3: POP BC ; Success, tidy up stack and exit with Z set.
XOR A
RET
; Method to send a byte to the SD card via the SPI protocol.
@@ -434,6 +439,7 @@ SPISKIP: PUSH BC
; This is done as follows: <MSB> <2> <1> <0> => <2> <1> <0> 0 (ie. 8 bit shift): Shift left <0> with carry, shift left <1> shift left <2>, 0 to <LSB>
;
; Input: HL = Stack offset.
;
LBATOADDR: LD HL,(SDSTARTSEC+1)
LD A,(HL) ; Start ny retrieving bytes as HED0
INC HL
@@ -459,314 +465,6 @@ LBATOADDR: LD HL,(SDSTARTSEC+1)
LD (BC),A
RET
;
; ; Method to read a sector or partial sector contents to an SD Card.
; ;
; ; This method was originally a C routine I was using for FatFS but optimised it (still more can be done). The C->ASM is not so optimal.
; ;
; ; Input: on Stack : Position 2 = unsigned int count of 2 bytes. - The count of bytes to read.
; ; Position 4 = unsigned int offset of 2 bytes. - The offset in the 512 byte sector to commence read.
; ; Position 6 = unsigned long sector of 4 bytes. - The sector number or direct byte address for older cards.
; ; Position 10 = unsigned char BYTE *buf of 2 bytes- Pointer to a buffer where the bytes should be stored
; ; Output: A = 0 - All ok. A > 0 - error occurred.
; ;
;SD_READP: LD A,0
; CALL SPICS ; Set CS low (active).
;
; LD HL,(SDCAP) ; Test to see if CT_BLOCK is available.
; LD H,0
; LD A,CT_BLOCK
; AND L
; JP NZ,READP_3 ; If it has CT_BLOCK then use sector numbers otherwise multiply up to bytes.
;
; LD HL,6 + 2 ; It isnt so we need to convert the block to bytes by x512.
; CALL LBATOADDR
;
;READP_3: LD A,1
; LD (RESULT),A
;
; ; A = ACMD to send
; ; LHED = Argument, ie. ACMD = A, L, H, E, D, CRC
; LD HL,6 ; Sector is stored as 3rd paramneter at offset 6, retrieve and arrange in little endian order in LHED
; ADD HL,SP
; LD D,(HL)
; INC HL
; LD E,(HL)
; INC HL
; PUSH DE
; LD D,(HL)
; INC HL
; LD E,(HL)
; LD A,CMD17 ; Send CMD17 to read a sector.
; POP HL
; EX DE,HL
; CALL SDCMD
; LD A,(SDBUF+6) ; Fetch result and store.
; AND A
; JP NZ,READP_4
;
; LD HL,1000 ; Sit in a tight loop waiting for the data packet arrival (ie. not 0xFF).
;READP_7: PUSH HL
; LD HL,200
; CALL T_DELAY
; CALL SPIIN
; POP HL
; CP 255
; JP NZ,READP_6
; DEC HL
; LD A,H
; OR L
; JR NZ,READP_7
;
;READP_6: CP 254
; JP NZ,READP_4
; LD HL,4
; ADD HL,SP
; LD E,(HL)
; INC HL
; LD D,(HL)
; LD HL,514
; AND A
; SBC HL,DE
; EX DE,HL
; POP BC
; POP HL
; PUSH HL
; PUSH BC
; EX DE,HL
; AND A
; SBC HL,DE
; LD (BYTECNT),HL
;
; LD HL,4
; ADD HL,SP
; LD A,(HL)
; INC HL
; LD H,(HL)
; LD L,A
; LD A,H
; OR L
; JP Z,READP_11
;
; PUSH HL
; POP BC
; CALL SPISKIP
;
;READP_11: LD HL,10 ; Get the buffer pointer from where to read data.
; ADD HL,SP
; LD A,(HL)
; INC HL
; LD H,(HL)
; LD L,A
; LD A,H
; OR L
; JP Z,READP_12
;
;READP_15: PUSH HL
; CALL SPIIN
; POP HL
; LD (HL),A
; INC HL
; PUSH HL
; POP BC
;
; LD HL,10 ; Update the pointer on the stack with register copy.
; ADD HL,SP
; LD (HL),C
; INC HL
; LD (HL),B
;READP_13: POP DE ; Return address.
; POP HL ; Count
; DEC HL ; Decrement count
; PUSH HL ; And return stack to previous state.
; PUSH DE
; LD A,H
; OR L
; PUSH BC
; POP HL
; JP NZ,READP_15
;
;READP_12: LD HL,(BYTECNT)
; PUSH HL
; POP BC
; CALL SPISKIP
; LD A,0
; LD (RESULT),A
;READP_4:
; LD A,0
; CALL SPICS
; LD A,(RESULT)
; RET
; ; Method to write a sector or partial sector contents to an SD Card.
; ; This method was originally a C routine I was using for FatFS but optimised it (still more can be done). The C->ASM is not so optimal.
; ;
; ; Input: on Stack : Position 2 = unsigned long sector of 4 bytes. - This is the sector number if *buf = NULL, the byte count to write if *buf != NULL,
; ; or NULL to initialise/finalise a sector write.
; ; Position 6 = unsigned char BYTE *buf of 2 bytes.- This is the pointer to the data for writing. If NULL it indicates an initialise/
; ; finalise action with above sector being use to indicate mode (!= 0 initialise, 0 = finalise).
; ; If not NULL points to actual data for writing with the number of bytes stored in sector above.
; ; Output: A = 0 - All ok. A > 0 - error occurred.
;SD_WRITEP: LD A,1
; LD (RESULT),A
;
; LD A,0FFH ; Activate CS (set low).
; CALL SPICS
;
; LD HL,6 ; If buffer is not null, we are writing data, otherwise we are instigating a write transaction.
; ADD HL,SP
; LD A,(HL)
; INC HL
; LD H,(HL)
; LD L,A
; LD A,H
; OR L
; JP Z,WRITEP_3 ; NULL so we are performing a transaction open/close.
;
; LD HL,2 ; Get the sector into DEHL.
; ADD HL,SP
; LD A,(HL)
; INC HL
; LD H,(HL)
; LD L,A
; LD (BYTECNT),HL ; Only interested in the lower 16bit value of the long.
;
;WRITEP_4: LD A,H ; So long as we have bytes in the buffer, send to the card for writing.
; OR L
; JP Z,WRITEP_5
; LD HL,(WRITECNT) ; Count of bytes to write.
; LD A,H
; OR L
; JR Z,WRITEP_5 ; If either the max count (512) or the requested count (BYTECNT) have expired, exit.
;
; LD HL,6 ; Load the buffer pointer.
; ADD HL,SP
; INC (HL)
; LD A,(HL)
; INC HL
; JR NZ,WRITEP_2 ; Increment by 1 carrying overflow into MSB.
; INC (HL)
;WRITEP_2: LD H,(HL)
; LD L,A
; DEC HL ; Back to current byte.
; LD A,(HL)
; CALL SPIOUT
; LD HL,(WRITECNT) ; Decrement the max count.
; DEC HL
; LD (WRITECNT),HL
; LD HL,(BYTECNT) ; Decrement the requested count.
; DEC HL
; LD (BYTECNT),HL
; JP WRITEP_4
;
;WRITEP_5: LD A,0
; LD (RESULT),A
; JP WRITEP_8
;
;WRITEP_3: LD HL,2 ; Get the sector number into DEHL to test.
; ADD HL,SP
; LD E,(HL)
; INC HL
; LD D,(HL)
; INC HL
; LD A,(HL)
; INC HL
; LD H,(HL)
; LD L,A
; EX DE,HL
; LD A,H
; OR L
; OR D
; OR E
; JP Z,WRITEP_9 ; Sector is 0 so finalise the write transaction.
;
; LD HL,(SDCAP) ; Check to see if the card has block addressing.
; LD H,0
; LD A,CT_BLOCK
; AND L
; JP NZ,WRITEP_10 ; If it hasnt then we need to multiply up to the correct byte.
;
; LD HL,2 + 2 ; Fetch the sector number, multiply (by left shift x 9) x512 and store.
; CALL LBATOADDR
;
; ; A = ACMD to send
; ; LHED = Argument, ie. ACMD = A, L, H, E, D, CRC
;WRITEP_10: LD HL,2 ; Sector is stored as 3rd paramneter at offset 6, retrieve and arrange in little endian order in LHED
; ADD HL,SP
; LD D,(HL)
; INC HL
; LD E,(HL)
; INC HL
; PUSH DE
; LD D,(HL)
; INC HL
; LD E,(HL)
; LD A,CMD24 ; Send CMD24 to write a sector.
; POP HL
; EX DE,HL
; CALL SDCMD
; LD A,(SDBUF+6) ; Fetch result and store.
; AND A
; JP NZ,WRITEP_8
; LD A,255
; CALL SPIOUT
; LD A,254
; CALL SPIOUT
; LD HL,SD_SECSIZE
; LD (WRITECNT),HL
; LD A,0
; LD (RESULT),A
; JP WRITEP_8
;
;WRITEP_9: LD HL,(WRITECNT)
; INC HL
; INC HL
; LD (BYTECNT),HL
;WRITEP_13:
; LD HL,(BYTECNT)
; DEC HL
; LD (BYTECNT),HL
; INC HL
; LD A,H
; OR L
; JP Z,WRITEP_14
; LD A,0
; CALL SPIOUT
; JP WRITEP_13
;WRITEP_14:
; CALL SPIIN
; AND 01FH
; LD L,A
; LD H,0
; CP 5
; JP NZ,WRITEP_15
;
; LD HL,10000
; PUSH HL
; JR WRITEP_18
;WRITEP_20: DEC HL
; PUSH HL
; LD HL,200
; CALL T_DELAY
;WRITEP_18: CALL SPIIN
; POP HL
; CP 255
; JP Z,WRITEP_17
; LD A,H
; OR L
; JR NZ,WRITEP_20
;
;WRITEP_17: LD A,H
; OR L
; JP Z,WRITEP_15
; LD A,0
; LD (RESULT),HL
;WRITEP_15: LD A,000H
; CALL SPICS
;WRITEP_8: LD A,(RESULT)
; RET
; Method to read a sector or partial sector contents to an SD Card.
;
@@ -1003,6 +701,23 @@ SD_WRITE15: LD A,000H ; Disab
SD_WRITE8: LD A,(RESULT) ; Return result.
RET
; Method to print out the filename within an MZF header or SD Card header.
; The name may not be terminated as the full 17 chars are used, so this needs
; to be checked.
; Input: DE = Address of filename.
;
PRTFN: PUSH BC
LD B,FNSIZE ; Maximum size of filename.
PRTMSG: LD A,(DE)
INC DE
CP 000H ; If there is a valid terminator, exit.
JR Z,PRTMSGE
CP 00DH
JR Z,PRTMSGE
CALL PRNT
DJNZ PRTMSG ; Else print until 17 chars have been processed.
PRTMSGE: POP BC
RET
; Method to print out an SDC directory entry name along with an incremental file number. The file number can be
; used as a quick reference to a file rather than the filename.
@@ -1016,27 +731,32 @@ PRTDIR: PUSH BC
;
LD A,(SCRNMODE)
CP 0
LD H,46
LD H,47
JR Z,PRTDIR0
LD H,92
PRTDIR0: LD A,(TMPLINECNT) ; Pause if we fill the screen.
LD H,93
PRTDIR0: LD A,(TMPLINECNT) ; Pause if we fill the screen.
LD E,A
INC E
CP H
JR NZ,PRTNOWAIT
LD E, 0
PRTDIRWAIT: CALL ?KEY
JR Z,PRTDIRWAIT
PRTDIRWAIT: CALL GETKY
CP ' '
JR Z,PRTNOWAIT
CP 'X' ; Exit from listing.
LD A,001H
JR Z,PRTDIR4
JR PRTDIRWAIT
PRTNOWAIT: LD A,E
LD (TMPLINECNT),A
;
LD A, D ; Print out file number and increment.
LD A, D ; Print out file number and increment.
CALL PRTHX
LD A, '.'
CALL PRNT
POP DE
PUSH DE ; Get pointer to the file name and print.
RST 018h
PUSH DE ; Get pointer to the file name and print.
CALL PRTFN ; Print out the filename.
;
LD HL, (DSPXY)
;
@@ -1045,11 +765,11 @@ PRTNOWAIT: LD A,E
LD A,20
JR C, PRTDIR2
;
LD A,(SCRNMODE) ; 40 Char mode? 2 columns of filenames displayed so NL.
LD A,(SCRNMODE) ; 40 Char mode? 2 columns of filenames displayed so NL.
CP 0
JR Z,PRTDIR1
;
LD A,L ; 80 Char mode we print 4 columns of filenames.
LD A,L ; 80 Char mode we print 4 columns of filenames.
CP 40
LD A,40
JR C, PRTDIR2
@@ -1063,7 +783,9 @@ PRTDIR1: CALL NL
JR PRTDIR3
PRTDIR2: LD L,A
LD (DSPXY),HL
PRTDIR3: POP HL
PRTDIR3: XOR A
PRTDIR4: OR A
POP HL
POP DE
POP BC
RET
@@ -1096,7 +818,8 @@ GETSDDIRENT:PUSH BC
LD HL,0
LD (SDSTARTSEC),HL
LD (SDOFFSET),HL
LD B,0
LD B,C
LD C,0
LD (SDSTARTSEC+2),BC
LD HL,SD_SECSIZE
LD (SDLOADSIZE),HL
@@ -1164,10 +887,11 @@ DIRSD2: LD A,(HL)
BIT 7,A ; Is this entry active, ie. Bit 7 of lower flag = 1?
JR Z,DIRSD3
CALL PRTDIR ; Valid entry so print directory number and name pointed to by HL.
JR NZ,DIRSD4
INC D
DIRSD3: INC E ; Onto next directory entry number.
DJNZ DIRSD1
RET
DIRSD4: RET
;
; Load a program from the SD Card into RAM and/or execute it - Part 2.
@@ -1241,13 +965,18 @@ LOADSD9: POP DE ; No lo
LD L,A
LD A,(HL)
LD (ATRB),A ; Type of file, store in the tape header memory.
INC L
INC HL
LD DE,NAME
LD BC,SDDIR_FNSZ
LDIR ; Copy the filename into the CMT area.
LD D,(HL)
LD E,(HL)
INC HL
LD E,(HL) ; Start sector.
LD D,(HL) ; Start sector upper 16 bits, big endian.
INC HL
LD (SDSTARTSEC),DE
LD E,(HL)
INC HL
LD D,(HL) ; Start sector lower 16 bits, big endian.
INC HL
LD (COMNT),DE
LD (SDSTARTSEC+2),DE
@@ -1272,20 +1001,19 @@ LOADSD10: LD (DTADR),DE
LD D,(HL) ; Execution address, store in tape header memory.
LD (EXADR),DE
LD DE,0
LD (SDSTARTSEC),DE
LD (SDOFFSET),DE
;
LD DE,MSGSDLOAD
RST 018H
LD DE,NAME
RST 018H
CALL PRTFN
CALL NL
;
LOADSD11: LD A,(SDLOADSIZE+1)
CP 002H
LD HL,SD_SECSIZE ; A full sector read if remaining bytes >=512
JR NC,LOADSD12
LD HL,(SDLOADSIZE) ; Get remaining bytes size.
LD HL,(SDLOADSIZE) ; Get remaining bytes size.
LOADSD12: LD (SDBYTECNT),HL
DI
CALL SD_READ ; Read the sector.
@@ -1339,13 +1067,81 @@ LOADSDERR: LD DE,MSGSDRERR
LD A,2
JR LOADSDX1
; Method to save a block of memory to the SD card as a program.
; The parameters which should be given are:
; XXXXYYYYZZZZ - where XXXX = Start Address, YYYY = End Address, ZZZZ = Execution Address.
; Prompt for a filename which will be written into the SD Card directory.
;
SAVESDCARD: CALL READHEX ; Start address
LD (DTADR),HL ; data adress buffer
LD B,H
LD C,L
CALL INCDE4
CALL READHEX ; End address
SBC HL,BC ; byte size
INC HL
LD (SIZE),HL ; byte size buffer
CALL INCDE4
CALL READHEX ; execute address
LD (EXADR),HL ; buffer
CALL NL
LD DE,MSGSAVESD ; 'FILENAME? '
RST 018h
CALL GETLHEX ; filename input
CALL INCDE4
CALL INCDE4
LD HL,NAME ; name buffer
SAVESD1: INC DE
LD A,(DE)
LD (HL),A ; filename trans.
INC HL
CP 00Dh ; end code
JR NZ,SAVESD1
RET
; Method to read 4 hex digits and convert to a 16bit number.
;
READHEX: EX (SP),IY
POP AF
CALL HLHEX
JR C,READHEX2 ; Exit if the input is invalid
JP (IY)
READHEX2: POP AF ; Waste the intermediate caller address
RET
; Add 4 to DE.
INCDE4: INC DE
INC DE
INC DE
INC DE
RET
; Read a line from the user and store in BUFER.
READLHEX: EX (SP),HL ; Get return address into HL and pop of old HL value into BC.
POP BC
LD DE,BUFER
CALL GETL ; Input a line from the user.
LD A,(DE) ; Escape? Return to command processor.
CP 01Bh
JR Z,READHEX2
JP (HL) ; Else go to original return address.
;-------------------------------------------------------------------------------
; END OF SD CONTROLLER FUNCTIONALITY
;-------------------------------------------------------------------------------
;--------------------------------------
;
; Message table
;
;--------------------------------------
MSGCDIRLST: DB "SDCARD DIRECTORY:", 00DH
MSGSDRERR: DB "SDCARD READ ERROR, SECTOR:", 00DH
MSGLOADADDR:DB ", LOAD ADDR:", 00DH
MSGEXECADDR:DB "EXEC ADDR:", 00DH
MSGNOTBIN: DB "NOT BINARY", 00DH
MSGSDLOAD: DB "LOADING ", 00DH
MSGSAVESD: DB "FILENAME: ", 00DH
ALIGN 0EFFFh
DB 0FFh

View File

@@ -32,12 +32,12 @@ COLW EQU 40
SCRNSZ EQU COLW * ROW
MODE80C EQU 0
;======================================
;===========================================================
;
; USER ROM BANK 3
; USER ROM BANK 3 - Monitor memory and help utilities.
;
;======================================
ORG 0E800h
;===========================================================
ORG UROMADDR
;--------------------------------
; Common code spanning all banks.
@@ -106,339 +106,254 @@ BKSWRET3: POP BC
MEMTEST: LD B,240 ; Number of loops
LOOP: LD HL,MEMSTART ; Start of checked memory,
LD D,0CFh ; End memory check CF00
LOOP1: LD A,000h
CP L
JR NZ,LOOP1b
CALL PRTHL ; Print HL as 4digit hex.
LD A,0C4h ; Move cursor left.
LD E,004h ; 4 times.
LOOP1a: CALL DPCT
DEC E
JR NZ,LOOP1a
LOOP1b: INC HL
LD A,H
CP D ; Have we reached end of memory.
JR Z,LOOP3 ; Yes, exit.
LD A,(HL) ; Read memory location under test, ie. 0.
CPL ; Subtract, ie. FF - A, ie FF - 0 = FF.
LD (HL),A ; Write it back, ie. FF.
SUB (HL) ; Subtract written memory value from A, ie. should be 0.
JR NZ,LOOP2 ; Not zero, we have an error.
LD A,(HL) ; Reread memory location, ie. FF
CPL ; Subtract FF - FF
LD (HL),A ; Write 0
SUB (HL) ; Subtract 0
JR Z,LOOP1 ; Loop if the same, ie. 0
LOOP2: LD A,16h
CALL PRNT ; Print A
CALL PRTHX ; Print HL as 4 digit hex.
CALL PRNTS ; Print space.
XOR A
LD (HL),A
LD A,(HL) ; Get into A the failing bits.
CALL PRTHX ; Print A as 2 digit hex.
CALL PRNTS ; Print space.
LD A,0FFh ; Repeat but first load FF into memory
LD (HL),A
LD A,(HL)
CALL PRTHX ; Print A as 2 digit hex.
NOP
JR LOOP4
;-------------------------------------------------------------------------------
; START OF MEMORY CMDLINE TOOLS FUNCTIONALITY
;-------------------------------------------------------------------------------
LOOP3: CALL PRTHL
LD DE,OKCHECK
CALL MSG ; Print check message in DE
LD A,B ; Print loop count.
CALL PRTHX
LD DE,OKMSG
CALL MSG ; Print ok message in DE
CALL NL
DEC B
JR NZ,LOOP
LD DE,DONEMSG
CALL MSG ; Print check message in DE
JP ST1X
;
; Memory correction
; command 'M'
;
MCORX: CALL GETHEX ; correction address
MCORX1: CALL NLPHL ; corr. adr. print
CALL SPHEX ; ACC ASCII display
CALL PRNTS ; space print
CALL BGETLX ; get data & check data
CALL HLHEX ; HLASCII(DE)
JR C,MCRX3
CALL DOT4DE ; INC DE * 4
INC DE
CALL _2HEX ; data check
JR C,MCORX1
CP (HL)
JR NZ,MCORX1
INC DE
LD A,(DE)
CP 00Dh ; not correction
JR Z,MCRX2
CALL _2HEX ; ACCHL(ASCII)
JR C,MCORX1
LD (HL),A ; data correct
MCRX2: INC HL
JR MCORX1
MCRX3: LD H,B ; memory address
LD L,C
JR MCORX1
LOOP4: LD B,09h
CALL PRNTS ; Print space.
XOR A ; Zero A
SCF ; Set Carry
LOOP5: PUSH AF ; Store A and Flags
LD (HL),A ; Store 0 to bad location.
LD A,(HL) ; Read back
CALL PRTHX ; Print A as 2 digit hex.
CALL PRNTS ; Print space
POP AF ; Get back A (ie. 0 + C)
RLA ; Rotate left A. Bit LSB becomes Carry (ie. 1 first instance), Carry becomes MSB
DJNZ LOOP5 ; Loop if not zero, ie. print out all bit locations written and read to memory to locate bad bit.
XOR A ; Zero A, clears flags.
LD A,80h
LD B,08h
LOOP6: PUSH AF ; Repeat above but AND memory location with original A (ie. 80)
LD C,A ; Basically walk through all the bits to find which one is stuck.
LD (HL),A
LD A,(HL)
AND C
NOP
JR Z,LOOP8 ; If zero then print out the bit number
NOP
NOP
LD A,C
CPL
LD (HL),A
LD A,(HL)
AND C
JR NZ,LOOP8 ; As above, if the compliment doesnt yield zero, print out the bit number.
LOOP7: POP AF
RRCA
NOP
DJNZ LOOP6
JP ST1X
LOOP8: CALL LETNL ; New line.
LD DE,BITMSG ; BIT message
CALL MSG ; Print message in DE
LD A,B
DEC A
CALL PRTHX ; Print A as 2 digit hex, ie. BIT number.
CALL LETNL ; New line
LD DE,BANKMSG ; BANK message
CALL MSG ; Print message in DE
LD A,H
CP 50h ; 'P'
JR NC,LOOP9 ; Work out bank number, 1, 2 or 3.
LD A,01h
JR LOOP11
LOOP9: CP 90h
JR NC,LOOP10
LD A,02h
JR LOOP11
LOOP10: LD A,03h
LOOP11: CALL PRTHX ; Print A as 2 digit hex, ie. BANK number.
JR LOOP7
DLY1S: PUSH AF
PUSH BC
LD C,10
L0324: CALL DLY12
DEC C
JR NZ,L0324
POP BC
DUMPX: CALL GETHEX
CALL DOT4DE
PUSH HL
CALL HLHEX
POP DE
JR C,DUM4
DUM1: EX DE,HL
DUM3: LD B,008h
LD C,017h
CALL NLPHL
DUM2: CALL SPHEX
INC HL
PUSH AF
LD A,(DSPXY)
ADD A,C
LD (DSPXY),A
POP AF
CP 020h
JR NC,L0D51
LD A,02Eh
L0D51: 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 Z,L0D85
LD A,0F8h
LD (0E000h),A
NOP
LD A,(0E001h)
CP 0FEh
JR NZ,L0D78
CALL ?BLNK
L0D78: DJNZ DUM2
L0D7A: CALL ?KEY
OR A
JR Z,L0D7A
CALL BRKEY
JP NZ,DUM3
L0D85: RET ; JR LEA76
DUM4: LD HL,000A0h
ADD HL,DE
JR DUM1
; Clear memory.
INITMEMX: LD DE,MSG_INITM
CALL MSG
CALL LETNL
LD HL,1200h
LD BC,0D000h - 1200h
CLEAR1: LD A,00h
LD (HL),A
INC HL
DEC BC
LD A,B
OR C
JP NZ,CLEAR1
RET
; Test the 8253 Timer, configure it as per the monitor and display the read back values.
TIMERTST: CALL NL
LD DE,MSG_TIMERTST
CALL MSG
CALL NL
LD DE,MSG_TIMERVAL
CALL MSG
LD A,01h
LD DE,8000h
CALL TIMERTST1
NDE: JP NDE
JP ST1X
TIMERTST1: DI
PUSH BC
PUSH DE
PUSH HL
LD (AMPM),A
LD A,0F0H
LD (TIMFG),A
ABCD: LD HL,0A8C0H
XOR A
SBC HL,DE
PUSH HL
INC HL
EX DE,HL
LD HL,CONTF ; Control Register
LD (HL),0B0H ; 10110000 Control Counter 2 10, Write 2 bytes 11, 000 Interrupt on Terminal Count, 0 16 bit binary
LD (HL),074H ; 01110100 Control Counter 1 01, Write 2 bytes 11, 010 Rate Generator, 0 16 bit binary
LD (HL),030H ; 00110100 Control Counter 1 01, Write 2 bytes 11, 010 interrupt on Terminal Count, 0 16 bit binary
LD HL,CONT2 ; Counter 2
LD (HL),E
LD (HL),D
LD HL,CONT1 ; Counter 1
LD (HL),00AH
LD (HL),000H
LD HL,CONT0 ; Counter 0
LD (HL),00CH
LD (HL),0C0H
; LD HL,CONT2 ; Counter 2
; LD C,(HL)
; LD A,(HL)
; CP D
; JP NZ,L0323H
; LD A,C
; CP E
; JP Z,CDEF
;
L0323H: PUSH AF
PUSH BC
PUSH DE
PUSH HL
;
LD HL,CONTF ; Control Register
LD (HL),080H
LD HL,CONT2 ; Counter 2
LD C,(HL)
LD A,(HL)
CALL PRTHX
LD A,C
CALL PRTHX
;
CALL PRNTS
;CALL DLY1S
;
LD HL,CONTF ; Control Register
LD (HL),040H
LD HL,CONT1 ; Counter 1
LD C,(HL)
LD A,(HL)
CALL PRTHX
LD A,C
CALL PRTHX
;
CALL PRNTS
;CALL DLY1S
;
LD HL,CONTF ; Control Register
LD (HL),000H
LD HL,CONT0 ; Counter 0
LD C,(HL)
LD A,(HL)
CALL PRTHX
LD A,C
CALL PRTHX
;
;CALL DLY1S
;
LD A,0C4h ; Move cursor left.
LD E,0Eh ; 4 times.
L0330: CALL DPCT
DEC E
JR NZ,L0330
;
; LD C,20
;L0324: CALL DLY12
; DEC C
; JR NZ,L0324
;
POP HL
POP DE
POP BC
POP AF
;
LD HL,CONT2 ; Counter 2
LD C,(HL)
LD A,(HL)
CP D
JP NZ,L0323H
LD A,C
CP E
JP NZ,L0323H
;
;
PUSH AF
PUSH BC
PUSH DE
PUSH HL
CALL NL
CALL NL
CALL NL
LD DE,MSG_TIMERVAL2
CALL MSG
POP HL
POP DE
BGETLX: EX (SP),HL
POP BC
LD DE,BUFER
CALL GETL
LD A,(DE)
CP 01Bh
JP Z,GETHEX2
JP (HL)
GETHEX: EX (SP),IY
POP AF
CALL HLHEX
JR C,GETHEX2
JP (IY)
GETHEX2: POP AF ; Waste the intermediate caller address
RET
;
CDEF: POP DE
LD HL,CONT1
LD (HL),00CH
LD (HL),07BH
INC HL
; INCREMENT DE REG.
DOT4DE: INC DE
INC DE
INC DE
INC DE
RET
L0336H: PUSH AF
PUSH BC
PUSH DE
PUSH HL
;
LD HL,CONTF ; Control Register
LD (HL),080H
LD HL,CONT2 ; Counter 2
LD C,(HL)
LD A,(HL)
CALL PRTHX
LD A,C
CALL PRTHX
;
CALL PRNTS
CALL DLY1S
;
LD HL,CONTF ; Control Register
LD (HL),040H
LD HL,CONT1 ; Counter 1
LD C,(HL)
LD A,(HL)
CALL PRTHX
LD A,C
CALL PRTHX
;
CALL PRNTS
CALL DLY1S
;
LD HL,CONTF ; Control Register
LD (HL),000H
LD HL,CONT0 ; Counter 0
LD C,(HL)
LD A,(HL)
CALL PRTHX
LD A,C
CALL PRTHX
;
CALL DLY1S
;
LD A,0C4h ; Move cursor left.
LD E,0Eh ; 4 times.
L0340: CALL DPCT
DEC E
JR NZ,L0340
;
POP HL
POP DE
POP BC
POP AF
; 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
LD HL,CONT2 ; Counter 2
LD C,(HL)
LD A,(HL)
CP D
JR NZ,L0336H
LD A,C
CP E
JR NZ,L0336H
CALL NL
LD DE,MSG_TIMERVAL3
CALL MSG
POP HL
POP DE
POP BC
EI
RET
; NEW LINE AND PRINT HL REG (ASCII)
NLPHL: CALL NL
CALL PRTHL
RET
;-------------------------------------------------------------------------------
; 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 HELP SCREEN FUNCTIONALITY
;-------------------------------------------------------------------------------
; Simple help screen to display commands.
HELP: CALL NL
@@ -446,16 +361,33 @@ HELP: CALL NL
CALL PRTSTR
RET
; Modification of original MSG function, use NULL terminated strings not CR terminated.
; Modification of original MSG function, use NULL terminated strings not CR terminated and include page pause.
PRTSTR: PUSH AF
PUSH BC
PUSH DE
LD A,0
LD (TMPLINECNT),A
PRTSTR1: LD A,(DE)
CP 000H
JR Z,PRTSTRE
CALL PRNT
JR Z,PRTSTRE
CP 00DH
JR Z,PRTSTR3
PRTSTR2: CALL PRNT
INC DE
JR PRTSTR1
PRTSTR3: PUSH AF
LD A,(TMPLINECNT)
CP 24
JR Z,PRTSTR5
INC A
PRTSTR4: LD (TMPLINECNT),A
POP AF
JR PRTSTR2
PRTSTR5: CALL GETKY
CP ' '
JR NZ,PRTSTR5
XOR A
JR PRTSTR4
PRTSTRE: POP DE
POP BC
POP AF
@@ -471,36 +403,34 @@ HELPSCR: DB "4 - 40 COL MODE.", 00DH
DB "F[X] - BOOT FD DRIVE X.", 00DH
DB 0AAH," - BOOT FD ORIGINAL ROM.", 00DH
DB "H - THIS HELP SCREEN.", 00DH
DB "IR/IC - RFS DIR LISTING ROM/CARD.", 00DH
DB "IR/IC - RFS DIR LISTING ROM/SD CARD.", 00DH
DB "JXXXX - JUMP TO LOCATION XXXX.", 00DH
DB "LT[FN]- LOAD TAPE, FN=FILENAME", 00DH
DB "LR[FN]- LOAD ROM, FN=NO OR NAME", 00DH
DB "LC[FN]- LOAD SDCARD, FN=NO OR NAME", 00DH
DB " - ADD NX TO LOAD CMD FOR NO EXEC.", 00DH
DB " - ADD NX FOR NO EXEC, IE.LRNX.", 00DH
DB "MXXXX - EDIT MEMORY STARTING AT XXXX.", 00DH
DB "P - TEST PRINTER.", 00DH
DB "R - TEST DRAM MEMORY.", 00DH
DB "S - SAVE CURRENT PROG TO TAPE.", 00DH
DB "ST[XXXXYYYYZZZZ] - SAVE MEM TO TAPE.", 00DH
DB "SC[XXXXYYYYZZZZ] - SAVE MEM TO CARD.", 00DH
DB " XXXX=START,YYYY=END,ZZZZ=EXEC", 00DH
DB "T - TEST TIMER.", 00DH
DB "V - VERIFY TAPE SAVE.", 00DH
DB 000H
;-------------------------------------------------------------------------------
; END OF HELP SCREEN FUNCTIONALITY
;-------------------------------------------------------------------------------
OKCHECK: DB ", CHECK: ", 0Dh
OKMSG: DB " OK.", 0Dh
DONEMSG: DB 11h
DB "RAM TEST COMPLETE.", 0Dh
BITMSG: DB " BIT: ", 0Dh
BANKMSG: DB " BANK: ", 0Dh
MSG_TIMERTST:
DB "8253 TIMER TEST", 0Dh, 00h
MSG_TIMERVAL:
DB "READ VALUE 1: ", 0Dh, 00h
MSG_TIMERVAL2:
DB "READ VALUE 2: ", 0Dh, 00h
MSG_TIMERVAL3:
DB "READ DONE.", 0Dh, 00h
;--------------------------------------
;
; Message table
;
;--------------------------------------
MSG_INITM: DB "INIT MEMORY", 00DH
ALIGN 0EFFFh
DB 0FFh

View File

@@ -28,12 +28,12 @@
;--------------------------------------------------------------------------------------------------------
;======================================
;===========================================================
;
; USER ROM BANK 4
; USER ROM BANK 4 - CMT Controller utilities.
;
;======================================
ORG 0E800h
;===========================================================
ORG UROMADDR
;--------------------------------
; Common code spanning all banks.
@@ -101,6 +101,198 @@ BKSWRET4: POP BC
RET ; Return to caller.
;-------------------------------------------------------------------------------
; START OF CMT CONTROLLER FUNCTIONALITY
;-------------------------------------------------------------------------------
; Programm load
;
; cmd. 'L'
;
LOADTAPENX: LD L,0FFH
JR LOADTAPE1
LOADTAPE: LD L,000H
LOADTAPE1: PUSH HL ; Preserve auto execute flag.
CALL ?RDI
JP C,?ERX2
CALL NL
LD DE,MSG?2 ; 'LOADING '
RST 018h
LD DE,NAME
RST 018h
XOR A
LD (BUFER),A
LD HL,(DTADR)
LD A,H
OR L
JR NZ,LE941
LD HL,(EXADR)
LD A,H
OR L
JR NZ,LE941
LD A,0FFh
LD (BUFER),A
LD HL,01200h
LD (DTADR),HL
LE941: CALL ?RDD
JP C,?ERX2
POP HL ; Get back the auto execute flag.
LD A,L
OR A
JR Z,LOADTAPE4 ; Dont execute.
LD A,(BUFER)
CP 0FFh
JR Z,LOADTAPELM ; Execute at low memory?
LD BC,00100h
LD HL,(EXADR)
JP (HL)
LOADTAPELM: LD A,(MEMSW) ; Perform memory switch, mapping out ROM from $0000 to $C000
LD HL,01200h ; Shift the program down to RAM at $0000
LD DE,00000h
LD BC,(SIZE)
LDIR
LD BC,00100h
JP 00000h
LOADTAPE4: RET
;
; Programm save
;
; cmd. 'S'
;
SAVEX: CALL HEXIY ; Start address
LD (DTADR),HL ; data adress buffer
LD B,H
LD C,L
CALL INC4DE
CALL HEXIY ; End address
SBC HL,BC ; byte size
INC HL
LD (SIZE),HL ; byte size buffer
CALL INC4DE
CALL HEXIY ; execute address
LD (EXADR),HL ; buffer
CALL NL
LD DE,MSGSAVE ; 'FILENAME? '
RST 018h
CALL GETLHEX ; filename input
CALL INC4DE
CALL INC4DE
LD HL,NAME ; name buffer
SAVX1: INC DE
LD A,(DE)
LD (HL),A ; filename trans.
INC HL
CP 00Dh ; end code
JR NZ,SAVX1
LD A,OBJCD ; attribute: OBJ
LD (ATRB),A
CALL ?WRI
?ERX1: JP C,?ERX2
CALL ?WRD ; data
JR C,?ERX1
CALL NL
LD DE,MSGOK ; 'OK!'
RST 018h
RET
VRFYX: CALL ?VRFY
JP C,?ERX2
LD DE,MSGOK ; 'OK!'
RST 018h
RET
SGX: LD A,(SWRK)
RRA
CCF
RLA
LD (SWRK),A
RET
?ERX2: CP 002h
RET Z
CALL NL
LD DE,MSGE1 ; 'CHECK SUM ER.'
RST 018h
RET
HEXIY: EX (SP),IY
POP AF
CALL HLHEX
JR C,HEXIY ; Exit if the input is invalid
JP (IY)
HEXIY2: POP AF ; Waste the intermediate caller address
RET ; Return to command processor.
; INCREMENT DE REG.
INC4DE: INC DE
INC DE
INC DE
INC DE
RET
GETLHEX: EX (SP),HL
POP BC
LD DE,BUFER
CALL GETL
LD A,(DE)
CP 01Bh
JR Z,HEXIY2
JP (HL)
;FNINP: CALL NL
; LD DE,MSGSV ; 'FILENAME? '
; RST 018h
; LD DE,BUFER
; CALL GETL
; LD A,(DE)
; CP #1B
; JR NZ,LEAF3
; ;LD HL,ST1X
; ;EX (SP),HL
; RET
;
;LEAF3: LD B,000h
; LD DE,011ADh
; LD HL,BUFER
; LD A,(DE)
; CP 00Dh
; JR Z,LEB20
;LEB00: CP 020h
; JR NZ,LEB08
; INC DE
; LD A,(DE)
; JR LEB00
;LEB08: CP 022h
; JR Z,LEB14
;LEB0C: LD (HL),A
; INC HL
; INC B
; LD A,011h
; CP B
; JR Z,FNINP
;LEB14: INC DE
; LD A,(DE)
; CP 022h
; JR Z,LEB1E
; CP 00Dh
; JR NZ,LEB0C
;LEB1E: LD A,00dh
;LEB20: LD (HL),A
; RET
;
;-------------------------------------------------------------------------------
; END OF CMT CONTROLLER FUNCTIONALITY
;-------------------------------------------------------------------------------
;--------------------------------------
;
; Message table
;
;--------------------------------------
MSGSAVE: DB "FILENAME? ", 00DH
ALIGN 0EFFFh
DB 0FFh

View File

@@ -28,12 +28,12 @@
;--------------------------------------------------------------------------------------------------------
;======================================
;===========================================================
;
; USER ROM BANK 7
; USER ROM BANK 7 - Memory and timer test utilities.
;
;======================================
ORG 0E800h
;===========================================================
ORG UROMADDR
;--------------------------------
; Common code spanning all banks.
@@ -100,7 +100,375 @@ BKSWRET7: POP BC
POP AF
RET ; Return to caller.
;-------------------------------------------------------------------------------
; START OF MEMORY TEST FUNCTIONALITY
;-------------------------------------------------------------------------------
MEMTEST: LD B,240 ; Number of loops
LOOP: LD HL,MEMSTART ; Start of checked memory,
LD D,0CFh ; End memory check CF00
LOOP1: LD A,000h
CP L
JR NZ,LOOP1b
CALL PRTHL ; Print HL as 4digit hex.
LD A,0C4h ; Move cursor left.
LD E,004h ; 4 times.
LOOP1a: CALL DPCT
DEC E
JR NZ,LOOP1a
LOOP1b: INC HL
LD A,H
CP D ; Have we reached end of memory.
JR Z,LOOP3 ; Yes, exit.
LD A,(HL) ; Read memory location under test, ie. 0.
CPL ; Subtract, ie. FF - A, ie FF - 0 = FF.
LD (HL),A ; Write it back, ie. FF.
SUB (HL) ; Subtract written memory value from A, ie. should be 0.
JR NZ,LOOP2 ; Not zero, we have an error.
LD A,(HL) ; Reread memory location, ie. FF
CPL ; Subtract FF - FF
LD (HL),A ; Write 0
SUB (HL) ; Subtract 0
JR Z,LOOP1 ; Loop if the same, ie. 0
LOOP2: LD A,16h
CALL PRNT ; Print A
CALL PRTHX ; Print HL as 4 digit hex.
CALL PRNTS ; Print space.
XOR A
LD (HL),A
LD A,(HL) ; Get into A the failing bits.
CALL PRTHX ; Print A as 2 digit hex.
CALL PRNTS ; Print space.
LD A,0FFh ; Repeat but first load FF into memory
LD (HL),A
LD A,(HL)
CALL PRTHX ; Print A as 2 digit hex.
NOP
JR LOOP4
LOOP3: CALL PRTHL
LD DE,OKCHECK
CALL MSG ; Print check message in DE
LD A,B ; Print loop count.
CALL PRTHX
LD DE,OKMSG
CALL MSG ; Print ok message in DE
CALL NL
DEC B
JR NZ,LOOP
LD DE,DONEMSG
CALL MSG ; Print check message in DE
JP ST1X
LOOP4: LD B,09h
CALL PRNTS ; Print space.
XOR A ; Zero A
SCF ; Set Carry
LOOP5: PUSH AF ; Store A and Flags
LD (HL),A ; Store 0 to bad location.
LD A,(HL) ; Read back
CALL PRTHX ; Print A as 2 digit hex.
CALL PRNTS ; Print space
POP AF ; Get back A (ie. 0 + C)
RLA ; Rotate left A. Bit LSB becomes Carry (ie. 1 first instance), Carry becomes MSB
DJNZ LOOP5 ; Loop if not zero, ie. print out all bit locations written and read to memory to locate bad bit.
XOR A ; Zero A, clears flags.
LD A,80h
LD B,08h
LOOP6: PUSH AF ; Repeat above but AND memory location with original A (ie. 80)
LD C,A ; Basically walk through all the bits to find which one is stuck.
LD (HL),A
LD A,(HL)
AND C
NOP
JR Z,LOOP8 ; If zero then print out the bit number
NOP
NOP
LD A,C
CPL
LD (HL),A
LD A,(HL)
AND C
JR NZ,LOOP8 ; As above, if the compliment doesnt yield zero, print out the bit number.
LOOP7: POP AF
RRCA
NOP
DJNZ LOOP6
JP ST1X
LOOP8: CALL LETNL ; New line.
LD DE,BITMSG ; BIT message
CALL MSG ; Print message in DE
LD A,B
DEC A
CALL PRTHX ; Print A as 2 digit hex, ie. BIT number.
CALL LETNL ; New line
LD DE,BANKMSG ; BANK message
CALL MSG ; Print message in DE
LD A,H
CP 50h ; 'P'
JR NC,LOOP9 ; Work out bank number, 1, 2 or 3.
LD A,01h
JR LOOP11
LOOP9: CP 90h
JR NC,LOOP10
LD A,02h
JR LOOP11
LOOP10: LD A,03h
LOOP11: CALL PRTHX ; Print A as 2 digit hex, ie. BANK number.
JR LOOP7
DLY1S: PUSH AF
PUSH BC
LD C,10
L0324: CALL DLY12
DEC C
JR NZ,L0324
POP BC
POP AF
RET
;-------------------------------------------------------------------------------
; END OF MEMORY TEST FUNCTIONALITY
;-------------------------------------------------------------------------------
;-------------------------------------------------------------------------------
; START OF TIMER TEST FUNCTIONALITY
;-------------------------------------------------------------------------------
; Test the 8253 Timer, configure it as per the monitor and display the read back values.
TIMERTST: CALL NL
LD DE,MSG_TIMERTST
CALL MSG
CALL NL
LD DE,MSG_TIMERVAL
CALL MSG
LD A,01h
LD DE,8000h
CALL TIMERTST1
NDE: JP NDE
JP ST1X
TIMERTST1: DI
PUSH BC
PUSH DE
PUSH HL
LD (AMPM),A
LD A,0F0H
LD (TIMFG),A
ABCD: LD HL,0A8C0H
XOR A
SBC HL,DE
PUSH HL
INC HL
EX DE,HL
LD HL,CONTF ; Control Register
LD (HL),0B0H ; 10110000 Control Counter 2 10, Write 2 bytes 11, 000 Interrupt on Terminal Count, 0 16 bit binary
LD (HL),074H ; 01110100 Control Counter 1 01, Write 2 bytes 11, 010 Rate Generator, 0 16 bit binary
LD (HL),030H ; 00110100 Control Counter 1 01, Write 2 bytes 11, 010 interrupt on Terminal Count, 0 16 bit binary
LD HL,CONT2 ; Counter 2
LD (HL),E
LD (HL),D
LD HL,CONT1 ; Counter 1
LD (HL),00AH
LD (HL),000H
LD HL,CONT0 ; Counter 0
LD (HL),00CH
LD (HL),0C0H
; LD HL,CONT2 ; Counter 2
; LD C,(HL)
; LD A,(HL)
; CP D
; JP NZ,L0323H
; LD A,C
; CP E
; JP Z,CDEF
;
L0323H: PUSH AF
PUSH BC
PUSH DE
PUSH HL
;
LD HL,CONTF ; Control Register
LD (HL),080H
LD HL,CONT2 ; Counter 2
LD C,(HL)
LD A,(HL)
CALL PRTHX
LD A,C
CALL PRTHX
;
CALL PRNTS
;CALL DLY1S
;
LD HL,CONTF ; Control Register
LD (HL),040H
LD HL,CONT1 ; Counter 1
LD C,(HL)
LD A,(HL)
CALL PRTHX
LD A,C
CALL PRTHX
;
CALL PRNTS
;CALL DLY1S
;
LD HL,CONTF ; Control Register
LD (HL),000H
LD HL,CONT0 ; Counter 0
LD C,(HL)
LD A,(HL)
CALL PRTHX
LD A,C
CALL PRTHX
;
;CALL DLY1S
;
LD A,0C4h ; Move cursor left.
LD E,0Eh ; 4 times.
L0330: CALL DPCT
DEC E
JR NZ,L0330
;
; LD C,20
;L0324: CALL DLY12
; DEC C
; JR NZ,L0324
;
POP HL
POP DE
POP BC
POP AF
;
LD HL,CONT2 ; Counter 2
LD C,(HL)
LD A,(HL)
CP D
JP NZ,L0323H
LD A,C
CP E
JP NZ,L0323H
;
;
PUSH AF
PUSH BC
PUSH DE
PUSH HL
CALL NL
CALL NL
CALL NL
LD DE,MSG_TIMERVAL2
CALL MSG
POP HL
POP DE
POP BC
POP AF
;
CDEF: POP DE
LD HL,CONT1
LD (HL),00CH
LD (HL),07BH
INC HL
L0336H: PUSH AF
PUSH BC
PUSH DE
PUSH HL
;
LD HL,CONTF ; Control Register
LD (HL),080H
LD HL,CONT2 ; Counter 2
LD C,(HL)
LD A,(HL)
CALL PRTHX
LD A,C
CALL PRTHX
;
CALL PRNTS
CALL DLY1S
;
LD HL,CONTF ; Control Register
LD (HL),040H
LD HL,CONT1 ; Counter 1
LD C,(HL)
LD A,(HL)
CALL PRTHX
LD A,C
CALL PRTHX
;
CALL PRNTS
CALL DLY1S
;
LD HL,CONTF ; Control Register
LD (HL),000H
LD HL,CONT0 ; Counter 0
LD C,(HL)
LD A,(HL)
CALL PRTHX
LD A,C
CALL PRTHX
;
CALL DLY1S
;
LD A,0C4h ; Move cursor left.
LD E,0Eh ; 4 times.
L0340: CALL DPCT
DEC E
JR NZ,L0340
;
POP HL
POP DE
POP BC
POP AF
LD HL,CONT2 ; Counter 2
LD C,(HL)
LD A,(HL)
CP D
JR NZ,L0336H
LD A,C
CP E
JR NZ,L0336H
CALL NL
LD DE,MSG_TIMERVAL3
CALL MSG
POP HL
POP DE
POP BC
EI
RET
;-------------------------------------------------------------------------------
; END OF TIMER TEST FUNCTIONALITY
;-------------------------------------------------------------------------------
;--------------------------------------
;
; Message table
;
;--------------------------------------
OKCHECK: DB ", CHECK: ", 0Dh
OKMSG: DB " OK.", 0Dh
DONEMSG: DB 11h
DB "RAM TEST COMPLETE.", 0Dh
BITMSG: DB " BIT: ", 0Dh
BANKMSG: DB " BANK: ", 0Dh
MSG_TIMERTST:
DB "8253 TIMER TEST", 0Dh, 00h
MSG_TIMERVAL:
DB "READ VALUE 1: ", 0Dh, 00h
MSG_TIMERVAL2:
DB "READ VALUE 2: ", 0Dh, 00h
MSG_TIMERVAL3:
DB "READ DONE.", 0Dh, 00h
ALIGN 0EFFFh
DB 0FFh

View File

@@ -38,7 +38,7 @@ STACK: EQU 010F0H
SPV:
IBUFE: ; TAPE BUFFER (128 BYTES)
ATRB: DS virtual 1 ; ATTRIBUTE
NAME: DS virtual 17 ; FILE NAME
NAME: DS virtual FNSIZE ; FILE NAME
SIZE: DS virtual 2 ; BYTESIZE
DTADR: DS virtual 2 ; DATA ADDRESS
EXADR: DS virtual 2 ; EXECUTION ADDRESS
@@ -135,25 +135,28 @@ RFS_COMNT: EQU 00018h ; COMME
; the User ROM bank.
;-----------------------------------------------
MROMPAGES EQU 8
USRROMPAGES EQU 12
ROMBANK0 EQU 0
ROMBANK1 EQU 1
ROMBANK2 EQU 2
ROMBANK3 EQU 3
ROMBANK4 EQU 4
ROMBANK5 EQU 5
ROMBANK6 EQU 6
ROMBANK7 EQU 7
ROMBANK8 EQU 8
ROMBANK9 EQU 9
ROMBANK10 EQU 10
ROMBANK11 EQU 11
USRROMPAGES EQU 12 ; Monitor ROM : User ROM
ROMBANK0 EQU 0 ; MROM SA1510 40 Char : RFS Bank 0 - Main RFS Entry point and functions.
ROMBANK1 EQU 1 ; MROM SA1510 80 Char : RFS Bank 1 - Floppy disk controller and utilities.
ROMBANK2 EQU 2 ; CPM 2.2 CBIOS : RFS Bank 2 - SD Card controller and utilities.
ROMBANK3 EQU 3 ; RFS Utilities : RFS Bank 3 - Cmdline tools (Memory, Printer, Help)
ROMBANK4 EQU 4 ; Free : RFS Bank 4 - CMT Utilities.
ROMBANK5 EQU 5 ; Free : RFS Bank 5
ROMBANK6 EQU 6 ; Free : RFS Bank 6
ROMBANK7 EQU 7 ; Free : RFS Bank 7 - Memory and timer test utilities.
ROMBANK8 EQU 8 ; : CBIOS Bank 1 - Utilities
ROMBANK9 EQU 9 ; : CBIOS Bank 2 - Screen / ANSI Terminal
ROMBANK10 EQU 10 ; : CBIOS Bank 3 - SD Card
ROMBANK11 EQU 11 ; : CBIOS Bank 4 - Floppy disk controller.
PRTMZF EQU 0E880H
MZFHDRSZ EQU 128
RFSSECTSZ EQU 256
MROMSIZE EQU 4096
UROMSIZE EQU 2048
FNSIZE EQU 17 ; Size of tape filename.
;ROW EQU 25
;COLW40 EQU 80
@@ -212,12 +215,11 @@ MFINDMZF: JP _MFINDMZF
MROMLOAD: JP _MROMLOAD
;-----------------------------------------
;
;====================================
;
; ROM File System Commands
;
;====================================
;====================================
;
; ROM File System Commands
;
;====================================
; HL contains address of block to check.
ISMZF: PUSH BC
@@ -230,7 +232,7 @@ ISMZF: PUSH BC
;
INC HL
LD DE,NAME ; Checks to confirm this is an MZF header.
LD B,17 ; Maximum of 17 characters, including terminator in filename.
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.
@@ -246,7 +248,7 @@ ISMZFNXT3: INC DE
DJNZ ISMZFNXT
JR ISMZFNOT ; No end of string terminator, this cant be a valid filename.
ISMZFVFY: LD A,B
CP 17
CP FNSIZE
JR Z,ISMZFNOT ; If the filename has no length it cant be valid, so loop.
ISMZFYES: CP A ; Set zero flag to indicate match.
ISMZFNOT: POP HL
@@ -377,7 +379,7 @@ FINDMZF3: POP HL
PUSH DE
PUSH BC
LD DE,(TMPADR) ; Original DE put onto stack, original filename into DE
LD BC,17
LD BC,FNSIZE
CALL CMPSTRING
POP BC
POP DE
@@ -502,11 +504,11 @@ LROMLOAD5: PUSH AF
;======================================
;
; SA1510 mirrored functions.
;
;======================================
;======================================
;
; SA1510 mirrored functions.
;
;======================================
?MODE: LD HL,KEYPF
LD (HL),08AH
@@ -524,6 +526,14 @@ LROMLOAD5: PUSH AF
RET
;======================================
;
; Message table
;
;======================================
; Bring in additional resources.
USE_CMPSTRING: EQU 1
@@ -544,9 +554,3 @@ LROMLOAD5: PUSH AF
; Ensure we fill the entire 4K by padding with FF's.
ALIGN 1000H
;
;======================================
;
; Message table
;
;======================================

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

134
software/src/tools/Makefile Normal file
View File

@@ -0,0 +1,134 @@
#########################################################################################################
##
## Name: Makefile
## Created: March 2020
## Author(s): Philip Smart
## Description: Helper tools for the MZ80A RFS upgrade
## This makefile builds tools written in C which help with building/setting up the
## RFS images for use in the RFS adapter.
##
## Credits:
## Copyright: (c) 2020 Philip Smart <philip.smart@net2net.org>
##
## History: March 2020 - Initial Makefile creation
##
## Notes:
##
#########################################################################################################
## 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/>.
#########################################################################################################
BASE =
CC = $(BASE)gcc
LD = $(BASE)gcc
AS = $(BASE)as
CP = $(BASE)objcopy
DUMP = $(BASE)objdump
BASEDIR = ../../..
SWDIR = $(BASEDIR)/software/src
INSTALLDIR = $(BASEDIR)/software/tools
# we use printf from here
COMMON_DIR = $(SWDIR)/common
INCLUDE_DIR = $(SWDIR)/include
# Working directory to build object files.
BUILD_DIR = tools_obj
COMMON_SRC = #$(COMMON_DIR)/sdtool.c
COMMON_OBJ = $(patsubst $(COMMON_DIR)/%.c,$(BUILD_DIR)/%.o,$(COMMON_SRC))
SDTOOL_PRJ = sdtool
SDTOOL_SRC = sdtool.c
SDTOOL_OBJ = $(COMMON_OBJ) $(patsubst %.c,$(BUILD_DIR)/%.o,$(SDTOOL_SRC))
MZFDC2_PRJ = mzfdc2
MZFDC2_SRC = mz-fdc2.c
MZFDC2_OBJ = $(COMMON_OBJ) $(patsubst %.c,$(BUILD_DIR)/%.o,$(MZFDC2_SRC))
# Commandline options for each tool.
OPTS =
CFLAGS = -I. -I$(COMMON_DIR) -I$(INCLUDE_DIR) -O3
# Enable debug output.
OFLAGS += -DDEBUG
LFLAGS = -Wl,--gc-sections -Wl,--relax -Os
#
# Assembler flags.
ASFLAGS = -I. -I$(COMMON_DIR) -I$(INCLUDE_DIR) -I$(STARTUP_DIR)
#
# Our target.
all: clean $(BUILD_DIR) $(SDTOOL_PRJ) $(MZFDC2_PRJ)
install: all
cp $(SDTOOL_PRJ) $(MZFDC2_PRJ) $(INSTALLDIR)
clean:
rm -f $(BUILD_DIR)/*.o *.hex *.lss *.elf *.map *.lst *.srec *~ */*.o *.bin *.srec *.dmp *.vhd *.rpt $(SDTOOL_PRJ)
$(SDTOOL_PRJ): $(SDTOOL_PRJ).elf $(SDTOOL_PRJ).dmp $(SDTOOL_PRJ).lss
$(MZFDC2_PRJ): $(MZFDC2_PRJ).elf $(MZFDC2_PRJ).dmp $(MZFDC2_PRJ).lss
# Convert ELF binary to bin file.
%.bin: %.elf
@$(CP) -O binary $< $@
# Convert ELF to srec format for serial upload.
%.srec: %.elf
@$(CP) -O srec $< $@
%.dmp: %.elf
@$(DUMP) -x $< >>$@
# Create extended listing file from ELF output file.
# testing: option -C
%.lss: %.elf
@echo
@$(DUMP) -h -S -C $< > $@
$(SDTOOL_PRJ): $(SDTOOL_OBJ)
$(CC) $(LFLAGS) $(SDTOOL_OBJ) -o $@ $(LIBS)
chmod +x $@
$(MZFDC2_PRJ): $(MZFDC2L_OBJ)
$(CC) $(LFLAGS) $(MZFDC2_OBJ) -o $@ $(LIBS)
chmod +x $@
# Link - this produces an ELF binary.
$(SDTOOL_PRJ).elf: $(SDTOOL_OBJ)
$(LD) $(LFLAGS) -o $@ $+ $(LIBS)
$(MZFDC2_PRJ).elf: $(MZFDC2_OBJ)
$(LD) $(LFLAGS) -o $@ $+ $(LIBS)
$(BUILD_DIR)/%.o: %.c Makefile
$(CC) $(CFLAGS) $(OFLAGS) -o $@ -c $<
$(BUILD_DIR)/%.o: %.cpp Makefile
$(CC) $(CFLAGS) $(OFLAGS) -o $@ -c $<
$(BUILD_DIR)/%.o: $(COMMON_DIR)/%.c Makefile
$(CC) $(CFLAGS) $(OFLAGS) -o $@ -c $<
$(BUILD_DIR)/%.o: %.s
$(AS) $(ASFLAGS) -o $@ $<
$(BUILD_DIR)/%.o: $(STARTUP_DIR)/%.s
$(AS) $(ASFLAGS) -o $@ $<
$(BUILD_DIR):
mkdir $(BUILD_DIR)

BIN
software/src/tools/mzfdc2 Executable file

Binary file not shown.

View File

@@ -0,0 +1,84 @@
/*----------------------------------------------------------------------*/
/* Petit FatFs sample project for generic uC (C)ChaN, 2010 */
/*----------------------------------------------------------------------*/
#include <stdio.h>
#include "pff.h"
void die ( /* Stop with dying message */
FRESULT rc /* FatFs return value */
)
{
printf("Failed with rc=%u.\n", rc);
for (;;) ;
}
/*-----------------------------------------------------------------------*/
/* Program Main */
/*-----------------------------------------------------------------------*/
int main (void)
{
FATFS fatfs; /* File system object */
DIR dir; /* Directory object */
FILINFO fno; /* File information object */
UINT bw, br, i;
BYTE buff[64];
printf("\nMount a volume.\n");
rc = pf_mount(&fatfs);
if (rc) die(rc);
printf("\nOpen a test file (message.txt).\n");
rc = pf_open("MESSAGE.TXT");
if (rc) die(rc);
printf("\nType the file content.\n");
for (;;) {
rc = pf_read(buff, sizeof(buff), &br); /* Read a chunk of file */
if (rc || !br) break; /* Error or end of file */
for (i = 0; i < br; i++) /* Type the data */
putchar(buff[i]);
}
if (rc) die(rc);
#if PF_USE_WRITE
printf("\nOpen a file to write (write.txt).\n");
rc = pf_open("WRITE.TXT");
if (rc) die(rc);
printf("\nWrite a text data. (Hello world!)\n");
for (;;) {
rc = pf_write("Hello world!\r\n", 14, &bw);
if (rc || !bw) break;
}
if (rc) die(rc);
printf("\nTerminate the file write process.\n");
rc = pf_write(0, 0, &bw);
if (rc) die(rc);
#endif
#if PF_USE_DIR
printf("\nOpen root directory.\n");
rc = pf_opendir(&dir, "");
if (rc) die(rc);
printf("\nDirectory listing...\n");
for (;;) {
rc = pf_readdir(&dir, &fno); /* Read a directory item */
if (rc || !fno.fname[0]) break; /* Error or end of dir */
if (fno.fattrib & AM_DIR)
printf(" <dir> %s\n", fno.fname);
else
printf("%8lu %s\n", fno.fsize, fno.fname);
}
if (rc) die(rc);
#endif
printf("\nTest completed.\n");
for (;;) ;
}

BIN
software/src/tools/sdtool Executable file

Binary file not shown.

730
software/src/tools/sdtool.c Normal file
View File

@@ -0,0 +1,730 @@
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Name: sdtool.c
// Created: January 2019
// Author(s): Philip Smart
// Description: MZ-80A SD Card Drive file image manipulator.
// This program creates and manipulates an SD Card image for the Sharp MZ80A with the
// Rom Filing System addition. The image contains the Rom Filing System disk at
// the beginning of the image (contains original Sharp MZ80A programs) along
// with 1 or more CPM disk drive images. The resultant image is copied directly
// onto an sd card using DD or equivalent.
//
// The format of the image is as follows:
// SECTOR FUNCTION
// 00000000 ---------------------------------------------------------------------------
// | ROM FILING SYSTEM IMAGE |
// | |
// 00000000 | RFS DIRECTORY ENTRY 000 (32BYTE) |
// | .. |
// | .. |
// 00001FE0 | RFS DIRECTORY ENTRY 255 (32BYTE) |
// 00002000 ---------------------------------------------------------------------------
// | |
// | CP/M DISK IMAGE 1 |
// | |
// | |
// | |
// | |
// ---------------------------------------------------------------------------
// | |
// | CP/M DISK IMAGE 2 |
// | |
// | |
// | |
// | |
// ---------------------------------------------------------------------------
// | |
// | CP/M DISK IMAGE 3 |
// | |
// | |
// | |
// | |
// ---------------------------------------------------------------------------
// | |
// | CP/M DISK IMAGE ... |
// | |
// | |
// | |
// | |
// ---------------------------------------------------------------------------
//
// The Rom Filing System directory entry is based on the MZF Header format and is as follows:
// | FLAG1 | FLAG2 | FILE NAME | START SECTOR | SIZE | LOAD ADDR | EXEC ADDR | RESERVED
// | 1 Byte | 1 Byte | 17 Bytes | 4 Bytes | 2 Bytes | 2 Bytes | 2 Bytes | 3 Bytes
//
// FLAG1 : BIT 7 = 1, Valid directory entry, 0 = inactive.
// FLAG2 : MZF Execution Code, 0x01 = Binary
// FILENAME : Standard MZF format filename.
// START SECTOR : Sector in the SD card where the program starts. It always starts at position 0 of the sector.
// SIZE : Size in bytes of the program. Each file block occupies 64Kbyte space (as per a tape) and this
// parameter provides the actual space occupied by the program at the current time.
// LOAD ADDR : Start address in memory where data should be loaded.
// EXEC ADDR : If a binary then this parameter specifies the location to auto execute once loaded.
// RESERVED : Not used at the moemnt.
//
// Caveat: This program was just intended to be a simple helper hence not properly split into methods,
// it may need updating as it becomes more complex!!
//
// Credits:
// Copyright: (c) 2020 Philip Smart <philip.smart@net2net.org>
//
// History: March 2020 - Initial program written.
//
// Notes:
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// 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/>.
/////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <string.h>
#include <getopt.h>
#define VERSION "1.0"
#define RFS_MAX_DIR_ENTRIES 256
#define RFS_DIR_ENTRY_SIZE 32
#define RFS_DIRENT_INUSE 0x80
#define RFS_FILESIZE 65536
#define RFS_IMAGESIZE (RFS_FILESIZE * RFS_MAX_DIR_ENTRIES) + (RFS_DIR_ENTRY_SIZE * RFS_MAX_DIR_ENTRIES)
#define RFS_FILEBLOCK_START (RFS_DIR_ENTRY_SIZE * RFS_MAX_DIR_ENTRIES)
#define CPM_DRIVE_IMAGES 4
#define CPM_SECTOR_LEN 512
#define CPM_TRACKS 512
#define CPM_SECTORS 32
#define CPM_BLOCKSIZE 4096
#define CPM_MAXDIR_ENTRIES 512
// Structure to represent an RFS directory entry within the RFS SD Card druve image.
//
typedef struct __attribute__((__packed__)) {
uint8_t flag1;
uint8_t flag2;
uint8_t fileName[17];
uint32_t startSector;
uint16_t size;
uint16_t loadAddr;
uint16_t execAddr;
uint8_t reserved[3];
} rfs_dirent;
// Structure to represent an MZF header.
//
typedef struct __attribute__((__packed__)) {
uint8_t ATRB;
uint8_t NAME[17];
uint16_t SIZE;
uint16_t DTADR;
uint16_t EXADR;
uint8_t COMNT[104];
} mzf_dirent;
// Mapping table from Sharp MZ80A Ascii to real Ascii.
//
typedef struct {
uint8_t asciiCode;
char asciiPrintable[6];
} t_asciiMap;
static t_asciiMap asciiMap[] = {
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"}, // 0x0F
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"}, // 0x1F
{ 0x20, "SPACE"},
{ 0x21, "!" },
{ 0x22, "\"" },
{ 0x23, "#" },
{ 0x24, "$" },
{ 0x25, "%" },
{ 0x26, "&" },
{ 0x27, "'" },
{ 0x28, "(" },
{ 0x29, ")" },
{ 0x2A, "*" },
{ 0x2B, "+" },
{ 0x2C, "," },
{ 0x2D, "-" },
{ 0x2E, "." },
{ 0x2F, "/" }, // 0x2F
{ 0x30, "0" },
{ 0x31, "1" },
{ 0x32, "2" },
{ 0x33, "3" },
{ 0x34, "4" },
{ 0x35, "5" },
{ 0x36, "6" },
{ 0x37, "7" },
{ 0x38, "8" },
{ 0x39, "9" },
{ 0x3A, ":" },
{ 0x3B, ";" },
{ 0x3C, "<" },
{ 0x3D, "=" },
{ 0x3E, ">" },
{ 0x3F, "?" }, // 0x3F
{ 0x40, "@" },
{ 0x41, "A" },
{ 0x42, "B" },
{ 0x43, "C" },
{ 0x44, "D" },
{ 0x45, "E" },
{ 0x46, "F" },
{ 0x47, "G" },
{ 0x48, "H" },
{ 0x49, "I" },
{ 0x4A, "J" },
{ 0x4B, "K" },
{ 0x4C, "L" },
{ 0x4D, "M" },
{ 0x4E, "N" },
{ 0x4F, "O" }, // 0x4F
{ 0x50, "P" },
{ 0x51, "Q" },
{ 0x52, "R" },
{ 0x53, "S" },
{ 0x54, "T" },
{ 0x55, "U" },
{ 0x56, "V" },
{ 0x57, "W" },
{ 0x58, "X" },
{ 0x59, "Y" },
{ 0x5A, "Z" },
{ 0x5B, "[" },
{ 0x5C, "\\" },
{ 0x5D, "]" },
{ 0x5E, "^" },
{ 0x5F, "_" }, // 0x5F
{ 0x20, "SPACE"}, // 0x60
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"}, // 0x6F
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"}, // 0x7F
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"}, // 0x8F
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x65, "e" },
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x74, "t" },
{ 0x67, "g" },
{ 0x68, "h" },
{ 0x20, "SPACE"},
{ 0x62, "b" },
{ 0x78, "x" },
{ 0x64, "d" },
{ 0x72, "r" },
{ 0x70, "p" },
{ 0x63, "c" }, // 0x9F
{ 0x71, "q" },
{ 0x61, "a" },
{ 0x7A, "z" },
{ 0x77, "w" },
{ 0x73, "s" },
{ 0x75, "u" },
{ 0x69, "i" },
{ 0x20, "SPACE"},
{ 0x4F, "O" }, // O with umlaut
{ 0x6B, "k" },
{ 0x66, "f" },
{ 0x76, "v" },
{ 0x20, "SPACE"},
{ 0x75, "u" }, // u with umlaut
{ 0x42, "B" }, // Strasse S
{ 0x6A, "j" }, // 0XAF
{ 0x6E, "n" },
{ 0x20, "SPACE"},
{ 0x55, "U" }, // U with umlaut
{ 0x6D, "m" },
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x6F, "o" },
{ 0x6C, "l" },
{ 0x41, "A" }, // A with umlaut
{ 0x6F, "o" }, // o with umlaut
{ 0x61, "a" }, // a with umlaut
{ 0x20, "SPACE"},
{ 0x79, "y" },
{ 0x20, "SPACE"},
{ 0x20, "SPACE"}, // 0xBF
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"}, // 0XCF
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"}, // 0XDF
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"}, // 0XEF
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"},
{ 0x20, "SPACE"} // 0XFF
};
// Simple help screen to remmber how this utility works!!
//
void usage(void)
{
printf("SDTOOL v%s\n", VERSION);
printf("\nOptions:-\n");
printf(" -a | --add <file> Add given file into the Image.\n");
printf(" -b | --binary Indicate file being added is a binary file, not an MZF format file.\n");
printf(" -c | --create-image Create or re-initialise the given image file.\n");
printf(" -e | --exec-addr <addr> For a binary file, set the execution address to be written into the directory entry.\n");
printf(" -h | --help This help test.\n");
printf(" -d | --list-dir List the image directory contents.\n");
printf(" -l | --load-addr For a binary file, set the load address to be written into the directory entry.\n");
printf(" -i | --image <file> Image file to be created or manipulated.\n");
printf(" -v | --verbose Output more messages.\n");
printf("\nExamples:\n");
printf(" sdtool --image MZ80A_1.img --list-dir List the directory entries in the image.\n");
printf(" sdtool --image MZ80A_1.img --create-image Initialise MZ80A_1.img to a new empty state.\n");
printf(" sdtool --image MZ80A_1.img --add CLOCK.MZF Add the CLOCK.MZF file into the image and update the directory with the MZF header details.\n");
printf(" sdtool --image MZ80A_1.img --add CLOCK.BIN \\\n");
printf(" --binary \\\n");
printf(" --exec-addr 4608 --load-addr 4608 Add the CLOCK.BIN binary file into the image with the given load and exec addresses. Update directory.\n");
}
// Method to convert a little endian <-> big endian 32bit unsigned.
//
uint32_t swap_endian(uint32_t value)
{
uint32_t b[4];
b[0] = ((value & 0x000000ff) << 24u);
b[1] = ((value & 0x0000ff00) << 8u);
b[2] = ((value & 0x00ff0000) >> 8u);
b[3] = ((value & 0xff000000) >> 24u);
return(b[0] | b[1] | b[2] | b[3]);
}
// Main program, to be split up into methods at a later date!! Just quick write as Im concentrating on the SD Card with RFS and CPM.
//
int main(int argc, char *argv[])
{
int opt;
int option_index = 0;
int binary_flag = 0;
int help_flag = 0;
int listDir_flag = 0;
int createImage_flag = 0;
int verbose_flag = 0;
uint16_t loadAddr = 0x1200;
uint16_t execAddr = 0x1200;
char imageFile[1024];
char addFile[1024];
long fileSize;
FILE *fpImage;
FILE *fpAdd;
rfs_dirent rfs_directory[RFS_MAX_DIR_ENTRIES];
mzf_dirent mzf_header;
// Initialise other variables.
//
addFile[0] = 0x00;
imageFile[0] = 0x00;
// Modes of operation.
// sdtool --add file [--binary] --image file --create-image
// sdtool --add file [--binary] --image file
// sdtool
static struct option long_options[] =
{
{"add", required_argument, 0, 'a'},
{"binary", no_argument, 0, 'b'},
{"create-image",no_argument, 0, 'c'},
{"exec-addr", required_argument, 0, 'e'},
{"help", no_argument, 0, 'h'},
{"list-dir", no_argument, 0, 'd'},
{"load-addr", required_argument, 0, 'l'},
{"image", required_argument, 0, 'i'},
{"verbose", no_argument, 0, 'v'},
{0, 0, 0, 0}
};
// Parse the command line options.
//
while((opt = getopt_long(argc, argv, ":bcdha;i:l:e:", long_options, &option_index)) != -1)
{
switch(opt)
{
case 'a':
strcpy(addFile, optarg);
break;
case 'b':
binary_flag = 1;
break;
case 'c':
createImage_flag = 1;
break;
case 'd':
listDir_flag = 1;
break;
case 'e':
execAddr = atoi(optarg);
break;
case 'h':
help_flag = 1;
break;
case 'i':
strcpy(imageFile, optarg);
break;
case 'l':
loadAddr = atoi(optarg);
break;
case 'v':
verbose_flag = 1;
break;
case ':':
printf("Option %s needs a value\n", argv[optind-1]);
break;
case '?':
printf("Unknown option: %s, ignoring!\n", argv[optind-1]);
break;
}
}
// Validate the input.
if(help_flag == 1)
{
usage();
exit(0);
}
if(strlen(imageFile) == 0 )
{
printf("Image file not specified.\n");
exit(10);
}
if(strlen(addFile) == 0 && listDir_flag == 0 && createImage_flag == 0)
{
printf("File to add not specified.\n");
exit(11);
}
if(createImage_flag == 1 && listDir_flag == 1)
{
printf("Meaningless option, create image will result in an empty directory so no point listing the directory!!\n");
exit(12);
}
// If the create flag is set, initialise the base RFS image.
if(createImage_flag)
{
fpImage = fopen(imageFile, "w");
if(fpImage == NULL)
{
printf("Couldnt create the image file:%s.\n", imageFile);
exit(30);
} else
{
for(uint32_t idx=0; idx < RFS_IMAGESIZE; idx++)
fputc(0x00, fpImage);
}
fclose(fpImage);
// All done if we are not adding a file.
if(addFile[0] == 0x00)
{
if(verbose_flag)
printf("Image file created.\n");
exit(0);
}
}
// Open the image file for read/write operations
fpImage = fopen(imageFile, "r+");
if(fpImage == NULL)
{
printf("Couldnt open the image file:%s.\n", imageFile);
exit(20);
}
// Get the directory into memory.
size_t result=fread(&rfs_directory, 1, sizeof(rfs_dirent) * RFS_MAX_DIR_ENTRIES, fpImage);
if(result < (RFS_MAX_DIR_ENTRIES * RFS_DIR_ENTRY_SIZE))
{
printf("Failed to read RFS directory from image, is image corrupt? (%d)\n", result);
exit(40);
}
// List directory?
if(listDir_flag == 1)
{
printf("FileName Start Sector Size Load Addr Exec Addr\n");
printf("-------- ------------ ---- --------- ---------\n");
for(uint16_t idx=0; idx < RFS_MAX_DIR_ENTRIES; idx++)
{
if((rfs_directory[idx].flag1 & RFS_DIRENT_INUSE) != 0)
{
uint8_t canPrint = 1;
for(uint16_t idx2=0; idx2 < 17; idx2++)
{
if(rfs_directory[idx].fileName[idx2] == 0x0d || rfs_directory[idx].fileName[idx2] == 0x00)
canPrint = 0;
if(canPrint == 1)
putchar(asciiMap[rfs_directory[idx].fileName[idx2]].asciiCode);
else
putchar(' ');
}
printf(" %08lx %04x %04x %04x\n", swap_endian(rfs_directory[idx].startSector), rfs_directory[idx].size, rfs_directory[idx].loadAddr, rfs_directory[idx].execAddr);
}
}
exit(0);
}
// Open the MZF file to add in read only mode.
fpAdd = fopen(addFile, "r");
if(fpAdd == NULL)
{
printf("Couldnt open the file to add:%s.\n", addFile);
exit(21);
}
// Get size of image file.
fseek(fpImage, 0, SEEK_END);
fileSize = ftell(fpImage);
fseek(fpImage, 0, SEEK_SET);
if(fileSize < RFS_IMAGESIZE)
{
printf("Image size is too small, please recreate with --create-image flag.\n");
}
// Get size of file where adding.
fseek(fpAdd, 0, SEEK_END);
fileSize = ftell(fpAdd);
fseek(fpAdd, 0, SEEK_SET);
// If this is an MZF file, get header.
if(binary_flag == 0)
{
result=fread(&mzf_header, 1, sizeof(mzf_dirent), fpAdd);
if(result < sizeof(mzf_dirent))
{
printf("Failed to read MZF header from MZF file, is image an MZF file?\n");
exit(50);
}
}
// Locate the first empty slot to add the file.
uint16_t dirEntry = 0;
while((rfs_directory[dirEntry].flag1 & RFS_DIRENT_INUSE) != 0)
{
dirEntry++;
if(dirEntry > 255)
{
printf("Image directory is full, cannot add file.\n");
exit(60);
}
}
// Ok, we now have a valid image file, slot in the directory which is free and the MZF file details, populate the directory entry, write it and then
// write the file into the image.
rfs_directory[dirEntry].flag1 = RFS_DIRENT_INUSE;
if(binary_flag == 0)
{
rfs_directory[dirEntry].flag2 = mzf_header.ATRB;
memcpy(rfs_directory[dirEntry].fileName, mzf_header.NAME, 17);
rfs_directory[dirEntry].fileName[16] = 0x00;
rfs_directory[dirEntry].startSector = swap_endian((RFS_FILEBLOCK_START + (dirEntry * RFS_FILESIZE))/512);;
rfs_directory[dirEntry].size = mzf_header.SIZE;
rfs_directory[dirEntry].loadAddr = mzf_header.DTADR;
rfs_directory[dirEntry].execAddr = mzf_header.EXADR;
} else
{
rfs_directory[dirEntry].flag2 = 0x01;
strncpy(rfs_directory[dirEntry].fileName, addFile, 17);
rfs_directory[dirEntry].fileName[(strlen(addFile) < 17 ? strlen(addFile) : 16)] = 0x0d;
rfs_directory[dirEntry].startSector = swap_endian((RFS_FILEBLOCK_START + (dirEntry * RFS_FILESIZE))/512);
rfs_directory[dirEntry].size = fileSize;
rfs_directory[dirEntry].loadAddr = loadAddr;
rfs_directory[dirEntry].execAddr = execAddr;
}
fseek(fpImage, 0, SEEK_SET);
result=fwrite(&rfs_directory, 1, sizeof(rfs_dirent) * RFS_MAX_DIR_ENTRIES, fpImage);
if(result < (RFS_MAX_DIR_ENTRIES * RFS_DIR_ENTRY_SIZE))
{
printf("Failed to write RFS directory into image file, disk full or wrong permissions?\n");
exit(50);
}
// Seek to the correct 64K block then write out 64K.
fseek(fpImage, (RFS_FILEBLOCK_START + (dirEntry * RFS_FILESIZE)), SEEK_SET);
for(uint32_t idx=0; idx < RFS_FILESIZE; idx++)
{
int c = fgetc(fpAdd);
if(feof(fpAdd))
c = 0xFF;
fputc(c, fpImage);
}
if(verbose_flag)
printf("Added %s to image.\n", addFile);
// Tidy up, close and finish.
fclose(fpAdd);
fclose(fpImage);
if(verbose_flag)
printf("Image file updated.\n");
}

View File

@@ -58,6 +58,13 @@ ROMRFS_HEADS=1
ROMRFS_SECTORS=128
ROMRFS_GAP3=78
ROMRFS_INTERLEAVE=1
SDC16M_PATH=${CPM_PATH}/SDC16M
SDC16M_CYLS=1024
SDC16M_HEADS=1
SDC16M_SECTORS=32
SDC16M_GAP3=78
SDC16M_INTERLEAVE=1
#BLOCKSIZELIST="256 512 1024 4096" # List of required output files in target RFS sector size.
BLOCKSIZELIST="128 256" # List of required output files in target RFS sector size.
MAXIMAGESIZE=524288 # Largest expected image size (generally 1 ROM less 16K Rom Banks).
@@ -67,6 +74,8 @@ echo "Creating CPM Disks from all the directories in:$CPM_PATH} matching this fi
rm -f ${ROMRFS_PATH}/RAW/*.RAW
rm -f ${FD1M44_PATH}/RAW/*.RAW
rm -f ${FD1M44_PATH}/DSK/*.DSK
rm -f ${SDC16M_PATH}/RAW/*.RAW
rm -f ${SDC16M_PATH}/DSK/*.DSK
for src in ${SOURCEDIRS}
do
# Different processing for the ROM RFS drives.
@@ -98,6 +107,101 @@ echo "Creating CPM Disks from all the directories in:$CPM_PATH} matching this fi
samdisk copy ${FD1M44_PATH}/RAW/${NEWDSKNAME}.RAW ${FD1M44_PATH}/DSK/${NEWDSKNAME}.DSK --cyls=${FD1M44_CYLS} --head=${FD1M44_HEADS} --gap3=${FD1M44_GAP3} --sectors=${FD1M44_SECTORS} --interleave=${FD1M44_INTERLEAVE}
fi
done
# Build the SD Card images, these images differ as they are larger and combine more programs in one disk under different user numbers.
# Copy a blank image to create the new disk.
cp ${CPM_PATH}/BLANKFD/BLANK_16M.RAW ${SDC16M_PATH}/RAW/SDCDISK1.RAW;
# Copy the CPM files from the linux filesystem into the CPM Disk under the CPM filesystem.
cp ${CPM_PATH}/BLANKFD/BLANK_16M.RAW ${SDC16M_PATH}/RAW/SDCDISK0.RAW;
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK0.RAW ${CPM_PATH}/CPM00_SYSTEM/*.* 0:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK0.RAW ${CPM_PATH}/CPM01_TURBOP/*.* 1:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK0.RAW ${CPM_PATH}/CPM02_HI_C/*.* 2:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK0.RAW ${CPM_PATH}/CPM03_FORTRAN80/*.* 3:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK0.RAW ${CPM_PATH}/CPM04_MBASIC/*.* 4:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK0.RAW ${CPM_PATH}/CPM05_COBOL80_v13/*.* 5:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK0.RAW ${CPM_PATH}/CPM06_COBOL80_v20/*.* 6:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK0.RAW ${CPM_PATH}/CPM07_COBOL80/*.* 7:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK0.RAW ${CPM_PATH}/CPM08_Z80FORTH/*.* 8:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK0.RAW ${CPM_PATH}/CPM09_CPMTEX/*.* 9:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK0.RAW ${CPM_PATH}/CPM10_DISKUTILFUNC5/*.* 10:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK0.RAW ${CPM_PATH}/CPM11_MAC80/*.* 11:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK0.RAW ${CPM_PATH}/CPM29_ZSID_v14/*.* 12:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK0.RAW ${CPM_PATH}/CPM32_ZCPR3/*.* 13:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK0.RAW ${CPM_PATH}/CPM33_ZCPR3_COMMON/*.* 14:
cp ${CPM_PATH}/BLANKFD/BLANK_16M.RAW ${SDC16M_PATH}/RAW/SDCDISK1.RAW;
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK1.RAW ${CPM_PATH}/CPM12_PASCALMTP_v561/*.* 0:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK1.RAW ${CPM_PATH}/CPM26_TPASCAL_v300a/*.* 1:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK1.RAW ${CPM_PATH}/CPM13_MTPUG_01/*.* 2:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK1.RAW ${CPM_PATH}/CPM14_MTPUG_02/*.* 3:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK1.RAW ${CPM_PATH}/CPM15_MTPUG_03/*.* 4:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK1.RAW ${CPM_PATH}/CPM16_MTPUG_04/*.* 5:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK1.RAW ${CPM_PATH}/CPM17_MTPUG_05/*.* 6:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK1.RAW ${CPM_PATH}/CPM18_MTPUG_06/*.* 7:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK1.RAW ${CPM_PATH}/CPM19_MTPUG_07/*.* 8:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK1.RAW ${CPM_PATH}/CPM20_MTPUG_08/*.* 9:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK1.RAW ${CPM_PATH}/CPM21_MTPUG_09/*.* 10:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK1.RAW ${CPM_PATH}/CPM22_MTPUG_10/*.* 11:
cp ${CPM_PATH}/BLANKFD/BLANK_16M.RAW ${SDC16M_PATH}/RAW/SDCDISK2.RAW;
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK2.RAW ${CPM_PATH}/CPM23_PLI/*.* 0:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK2.RAW ${CPM_PATH}/CPM24_PLI80_v13/*.* 1:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK2.RAW ${CPM_PATH}/CPM25_PLI80_v14/*.* 2:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK2.RAW ${CPM_PATH}/CPM28_PLM80/*.* 3:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK2.RAW ${CPM_PATH}/CPM27_WORDSTAR_v30/*.* 4:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK2.RAW ${CPM_PATH}/CPM31_WORDSTAR_v330/*.* 5:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK2.RAW ${CPM_PATH}/CPM30_WORDSTAR_v400/*.* 6:
cp ${CPM_PATH}/BLANKFD/BLANK_16M.RAW ${SDC16M_PATH}/RAW/SDCDISK3.RAW;
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK3.RAW ${CPM_PATH}/CPM_MC_C0/*.* 0:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK3.RAW ${CPM_PATH}/CPM_MC_C1/*.* 1:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK3.RAW ${CPM_PATH}/CPM_MC_C2/*.* 2:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK3.RAW ${CPM_PATH}/CPM_MC_C3/*.* 3:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK3.RAW ${CPM_PATH}/CPM_MC_C4/*.* 4:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK3.RAW ${CPM_PATH}/CPM_MC_C5/*.* 5:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK3.RAW ${CPM_PATH}/CPM_MC_C6/*.* 6:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK3.RAW ${CPM_PATH}/CPM_MC_C7/*.* 7:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK3.RAW ${CPM_PATH}/CPM_MC_C8/*.* 8:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK3.RAW ${CPM_PATH}/CPM_MC_C9/*.* 9:
cp ${CPM_PATH}/BLANKFD/BLANK_16M.RAW ${SDC16M_PATH}/RAW/SDCDISK4.RAW;
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK4.RAW ${CPM_PATH}/CPM_MC_D0/*.* 0:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK4.RAW ${CPM_PATH}/CPM_MC_D1/*.* 1:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK4.RAW ${CPM_PATH}/CPM_MC_D2/*.* 2:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK4.RAW ${CPM_PATH}/CPM_MC_D3/*.* 3:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK4.RAW ${CPM_PATH}/CPM_MC_D4/*.* 4:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK4.RAW ${CPM_PATH}/CPM_MC_D5/*.* 5:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK4.RAW ${CPM_PATH}/CPM_MC_D6/*.* 6:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK4.RAW ${CPM_PATH}/CPM_MC_D7/*.* 7:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK4.RAW ${CPM_PATH}/CPM_MC_D8/*.* 8:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK4.RAW ${CPM_PATH}/CPM_MC_D9/*.* 9:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK4.RAW ${CPM_PATH}/CPM_MC_D9/*.* 9:
cp ${CPM_PATH}/BLANKFD/BLANK_16M.RAW ${SDC16M_PATH}/RAW/SDCDISK5.RAW;
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK5.RAW ${CPM_PATH}/CPM_MC_E0/*.* 0:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK5.RAW ${CPM_PATH}/CPM_MC_E1/*.* 1:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK5.RAW ${CPM_PATH}/CPM_MC_E2/*.* 2:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK5.RAW ${CPM_PATH}/CPM_MC_E3/*.* 3:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK5.RAW ${CPM_PATH}/CPM_MC_E4/*.* 4:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK5.RAW ${CPM_PATH}/CPM_MC_E5/*.* 5:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK5.RAW ${CPM_PATH}/CPM_MC_E6/*.* 6:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK5.RAW ${CPM_PATH}/CPM_MC_E7/*.* 7:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK5.RAW ${CPM_PATH}/CPM_MC_E8/*.* 8:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK5.RAW ${CPM_PATH}/CPM_MC_E9/*.* 9:
cp ${CPM_PATH}/BLANKFD/BLANK_16M.RAW ${SDC16M_PATH}/RAW/SDCDISK6.RAW;
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK6.RAW ${CPM_PATH}/CPM_MC_F0/*.* 0:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK6.RAW ${CPM_PATH}/CPM_MC_F1/*.* 1:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK6.RAW ${CPM_PATH}/CPM_MC_F2/*.* 2:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK6.RAW ${CPM_PATH}/CPM_MC_F3/*.* 3:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK6.RAW ${CPM_PATH}/CPM_MC_F4/*.* 4:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK6.RAW ${CPM_PATH}/CPM_MC_F5/*.* 5:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK6.RAW ${CPM_PATH}/CPM_MC_F6/*.* 6:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK6.RAW ${CPM_PATH}/CPM_MC_F7/*.* 7:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK6.RAW ${CPM_PATH}/CPM_MC_F8/*.* 8:
cpmcp -f MZ80A-SDC16M ${SDC16M_PATH}/RAW/SDCDISK6.RAW ${CPM_PATH}/CPM_MC_F9/*.* 9:
)
# Create the CPM boot image and Drive images.
@@ -148,7 +252,7 @@ do
done
done </tmp/filelist
ls ${ROMRFS_PATH}/RAW/ ${FD1M44_PATH}/DSK/
echo "Done, all EDSK images can be found in:${ROMRFS_PATH}/ & ${FD1M44_PATH}."
ls ${ROMRFS_PATH}/RAW/ ${FD1M44_PATH}/DSK/ ${SDC16M_PATH}/DSK/
echo "Done, all EDSK images can be found in:${ROMRFS_PATH}/ & ${FD1M44_PATH} & ${SDC16M_PATH}."
exit 0

310
software/tools/make_sdcard.sh Executable file
View File

@@ -0,0 +1,310 @@
#!/bin/bash
#########################################################################################################
##
## Name: make_sdcard.sh
## Created: August 2018
## Author(s): Philip Smart
## Description: Sharp MZ series SD Card Packaging tool
## This is a very basic script to package programs into images for writing onto an
## SD Card as used in the Rom Filing System. The image is comprised of several parts,
## ie. <RFS IMAGE> + <CPM DISK IMAGE 0> .. <CPM DIK IMAGE n>.
##
## Credits:
## Copyright: (c) 2020 Philip Smart <philip.smart@net2net.org>
##
## History: March 2020 - Initial script written.
##
#########################################################################################################
## 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/>.
#########################################################################################################
ROOTDIR=../../MZ80A_RFS
MZF_PATH=${ROOTDIR}/software/MZF
TOOL_DIR=${ROOTDIR}/software/tools
IMAGE_DIR=${ROOTDIR}/software/roms
CPM_DIR=${ROOTDIR}/software/CPM/SDC16M/RAW
SDTOOL=${TOOL_DIR}/sdtool
RFS_IMAGE_FILE=${IMAGE_DIR}/SHARP_MZ80A_RFS_IMAGE_1.img
CPM_IMAGE_FILES="SDCDISK0.RAW SDCDISK1.RAW SDCDISK2.RAW SDCDISK3.RAW SDCDISK4.RAW SDCDISK5.RAW SDCDISK6.RAW"
SD_IMAGE_FILE=${IMAGE_DIR}/SHARP_MZ80A_RFS_CPM_IMAGE_1.img
# Create the initial RFS image.
${SDTOOL} --image ${RFS_IMAGE_FILE} --create
if [ $? != 0 ]; then
echo "Failed to create initial RFS Image, aborting."
exit 1
fi
# Manually choose the programs you want installed into the RFS image. The files will be first placed into
# the directory in the order they appear here, which initially is alphabetic order.
RFS_INCLUDE=
RFS_INCLUDE+="${MZF_PATH}/1Z-013B.MZF:"
RFS_INCLUDE+="${MZF_PATH}/2Z009E.MZF:"
RFS_INCLUDE+="${MZF_PATH}/2z-046a.MZF:"
RFS_INCLUDE+="${MZF_PATH}/5Z-009A.MZF:"
RFS_INCLUDE+="${MZF_PATH}/5Z-009B.MZF:"
RFS_INCLUDE+="${MZF_PATH}/6502_Betriebssys.MZF:"
RFS_INCLUDE+="${MZF_PATH}/80A PENCIL.A2_C2.MZF:"
RFS_INCLUDE+="${MZF_PATH}/80A_PENCIL.A2_C2.MZF:"
RFS_INCLUDE+="${MZF_PATH}/80A PENCIL.A2_S.MZF:"
RFS_INCLUDE+="${MZF_PATH}/80A_PENCIL.A2_S.MZF:"
RFS_INCLUDE+="${MZF_PATH}/80zbasic.MZF:"
RFS_INCLUDE+="${MZF_PATH}/A-BASIC_SA-5510.MZF:"
RFS_INCLUDE+="${MZF_PATH}/AIP_-_LOGO_xrr.MZF:"
RFS_INCLUDE+="${MZF_PATH}/APOLLO CHESS v2a.MZF:"
RFS_INCLUDE+="${MZF_PATH}/APOLLO_CHESS_v2a.MZF:"
RFS_INCLUDE+="${MZF_PATH}/B880.A3_P6.MZF:"
RFS_INCLUDE+="${MZF_PATH}/B880 MASTER.MZF:"
RFS_INCLUDE+="${MZF_PATH}/B880_MASTER.MZF:"
RFS_INCLUDE+="${MZF_PATH}/BASIC_MZ-5Z008_2.MZF:"
RFS_INCLUDE+="${MZF_PATH}/BASIC_MZ-5Z008.MZF:"
RFS_INCLUDE+="${MZF_PATH}/BASIC_MZ-5Z009_modified.MZF:"
RFS_INCLUDE+="${MZF_PATH}/BASIC_MZ-5Z009.MZF:"
RFS_INCLUDE+="${MZF_PATH}/BASIC_OM-1000.MZF:"
RFS_INCLUDE+="${MZF_PATH}/BASIC_OM-1001.MZF:"
RFS_INCLUDE+="${MZF_PATH}/BASIC_OM-500.MZF:"
RFS_INCLUDE+="${MZF_PATH}/basic_sa-5510.MZF:"
RFS_INCLUDE+="${MZF_PATH}/BASIC.SA-5510.MZF:"
RFS_INCLUDE+="${MZF_PATH}/BASIC SA-5575_C.MZF:"
RFS_INCLUDE+="${MZF_PATH}/BASIC_SA-5575_C.MZF:"
RFS_INCLUDE+="${MZF_PATH}/BASIC SA-5575_S.MZF:"
RFS_INCLUDE+="${MZF_PATH}/BASIC_SA-5575_S.MZF:"
RFS_INCLUDE+="${MZF_PATH}/BASIC SA-5577_C.MZF:"
RFS_INCLUDE+="${MZF_PATH}/BASIC_SA-5577_C.MZF:"
RFS_INCLUDE+="${MZF_PATH}/BASIC SA-5577_S.MZF:"
RFS_INCLUDE+="${MZF_PATH}/BASIC_SA-5577_S.MZF:"
RFS_INCLUDE+="${MZF_PATH}/BASIC SA-5580.MZF:"
RFS_INCLUDE+="${MZF_PATH}/BASIC_SA-5580.MZF:"
RFS_INCLUDE+="${MZF_PATH}/BASIC_SP-5025.MZF:"
RFS_INCLUDE+="${MZF_PATH}/BAS MOD v3.74.MZF:"
RFS_INCLUDE+="${MZF_PATH}/BAS_MOD_v3.74.MZF:"
RFS_INCLUDE+="${MZF_PATH}/BATTLE_GAME.MZF:"
RFS_INCLUDE+="${MZF_PATH}/BINARY COUNT.MZF:"
RFS_INCLUDE+="${MZF_PATH}/BINARY_COUNT.MZF:"
RFS_INCLUDE+="${MZF_PATH}/bomberman_MZ700.m12:"
RFS_INCLUDE+="${MZF_PATH}/BYTESAVER SA5510.MZF:"
RFS_INCLUDE+="${MZF_PATH}/BYTESAVER_SA5510.MZF:"
RFS_INCLUDE+="${MZF_PATH}/cannon_ball.m12:"
RFS_INCLUDE+="${MZF_PATH}/clock1.MZF:"
RFS_INCLUDE+="${MZF_PATH}/CLUB COPY.U1.MZF:"
RFS_INCLUDE+="${MZF_PATH}/CLUB_COPY.U1.MZF:"
RFS_INCLUDE+="${MZF_PATH}/CLUB MON.A1_M.MZF:"
RFS_INCLUDE+="${MZF_PATH}/CLUB_MON.A1_M.MZF:"
RFS_INCLUDE+="${MZF_PATH}/CLUB MON.A1_S.MZF:"
RFS_INCLUDE+="${MZF_PATH}/CLUB_MON.A1_S.MZF:"
RFS_INCLUDE+="${MZF_PATH}/cmttofd.MZF:"
RFS_INCLUDE+="${MZF_PATH}/COLONY.MZF:"
RFS_INCLUDE+="${MZF_PATH}/COMPILER_A2.MZF:"
RFS_INCLUDE+="${MZF_PATH}/CONVERTER A_700.MZF:"
RFS_INCLUDE+="${MZF_PATH}/CONVERTER_A_700.MZF:"
RFS_INCLUDE+="${MZF_PATH}/CONVERTER.MZF:"
RFS_INCLUDE+="${MZF_PATH}/COPIER.MZF:"
RFS_INCLUDE+="${MZF_PATH}/COSMO_BLASTER_MZ700.MZF:"
RFS_INCLUDE+="${MZF_PATH}/cpm22.MZF:"
RFS_INCLUDE+="${MZF_PATH}/CPM_RFS_1.MZF:"
RFS_INCLUDE+="${MZF_PATH}/CPM_RFS_2.MZF:"
RFS_INCLUDE+="${MZF_PATH}/CRUISER3_MZ1500.M12:"
RFS_INCLUDE+="${MZF_PATH}/DCS MZ80A APPEND.MZF:"
RFS_INCLUDE+="${MZF_PATH}/DCS_MZ80A_APPEND.MZF:"
RFS_INCLUDE+="${MZF_PATH}/DCS MZ80A RENUM.MZF:"
RFS_INCLUDE+="${MZF_PATH}/DCS_MZ80A_RENUM.MZF:"
RFS_INCLUDE+="${MZF_PATH}/DELETE.MZF:"
RFS_INCLUDE+="${MZF_PATH}/diamond.MZF:"
RFS_INCLUDE+="${MZF_PATH}/DISASM 8800.A15.MZF:"
RFS_INCLUDE+="${MZF_PATH}/DISASM_8800.A15.MZF:"
RFS_INCLUDE+="${MZF_PATH}/DISASM B800.A15.MZF:"
RFS_INCLUDE+="${MZF_PATH}/DISASM_B800.A15.MZF:"
RFS_INCLUDE+="${MZF_PATH}/DISKEDIT.A4B.MZF:"
RFS_INCLUDE+="${MZF_PATH}/DISKEDIT.A7_40T.MZF:"
RFS_INCLUDE+="${MZF_PATH}/diskutility.MZF:"
RFS_INCLUDE+="${MZF_PATH}/doordoor:"
RFS_INCLUDE+="${MZF_PATH}/Doordoor.mzt:"
RFS_INCLUDE+="${MZF_PATH}/EXPRESS BAS_700.MZF:"
RFS_INCLUDE+="${MZF_PATH}/EXPRESS_BAS_700.MZF:"
RFS_INCLUDE+="${MZF_PATH}/EXPRESS COMPILER.MZF:"
RFS_INCLUDE+="${MZF_PATH}/EXPRESS_COMPILER.MZF:"
RFS_INCLUDE+="${MZF_PATH}/EXPRESS PLUS.MZF:"
RFS_INCLUDE+="${MZF_PATH}/EXPRESS_PLUS.MZF:"
RFS_INCLUDE+="${MZF_PATH}/EXT.BASIC_OM-500.MZF:"
RFS_INCLUDE+="${MZF_PATH}/FDCOPY.MZF:"
RFS_INCLUDE+="${MZF_PATH}/FDCOPY.MZT:"
RFS_INCLUDE+="${MZF_PATH}/FD_Editor_MZ700.MZF:"
RFS_INCLUDE+="${MZF_PATH}/Filing(CMT).MZF:"
RFS_INCLUDE+="${MZF_PATH}/Filing_CMT_.MZT:"
RFS_INCLUDE+="${MZF_PATH}/FLAP.MZF:"
RFS_INCLUDE+="${MZF_PATH}/flugsim_MZ700.m12:"
RFS_INCLUDE+="${MZF_PATH}/fortransosz80.MZF:"
RFS_INCLUDE+="${MZF_PATH}/FRONT_PANEL_v1.5.MZF:"
RFS_INCLUDE+="${MZF_PATH}/GALAXI_FORM.MZF:"
RFS_INCLUDE+="${MZF_PATH}/GALAXY_INVADERS.MZF:"
RFS_INCLUDE+="${MZF_PATH}/GDP9-BA.MZF:"
RFS_INCLUDE+="${MZF_PATH}/Greedy_Gremlins.MZF:"
RFS_INCLUDE+="${MZF_PATH}/Hardcopy.MZF:"
RFS_INCLUDE+="${MZF_PATH}/hi-ramcheck.MZF:"
RFS_INCLUDE+="${MZF_PATH}/HP4TMZ7L.MZF:"
RFS_INCLUDE+="${MZF_PATH}/HP4TMZ7.MZF:"
RFS_INCLUDE+="${MZF_PATH}/HU-BASIC.A1_M.MZF:"
RFS_INCLUDE+="${MZF_PATH}/HU-BASIC.A1_S.MZF:"
RFS_INCLUDE+="${MZF_PATH}/HU-BASIC.A2_80M.MZF:"
RFS_INCLUDE+="${MZF_PATH}/HU-BASIC.A2_80S.MZF:"
RFS_INCLUDE+="${MZF_PATH}/HU-BASIC_V1.3_K.MZF:"
RFS_INCLUDE+="${MZF_PATH}/HUCALC_80A+_C2.MZF:"
RFS_INCLUDE+="${MZF_PATH}/HUCALC_80A+_M.MZF:"
RFS_INCLUDE+="${MZF_PATH}/HUCALC_80A+_S.MZF:"
RFS_INCLUDE+="${MZF_PATH}/hudson_basic.MZF:"
RFS_INCLUDE+="${MZF_PATH}/HUNCHY.MZF:"
RFS_INCLUDE+="${MZF_PATH}/INSTRUCS_v1.1.MZF:"
RFS_INCLUDE+="${MZF_PATH}/JIGSAW.MZF:"
RFS_INCLUDE+="${MZF_PATH}/Joy.MZF:"
RFS_INCLUDE+="${MZF_PATH}/k-basic_v.5.MZF:"
RFS_INCLUDE+="${MZF_PATH}/KNIFORTH.MZF:"
RFS_INCLUDE+="${MZF_PATH}/KUMA_INTERPR..MZF:"
RFS_INCLUDE+="${MZF_PATH}/KuPTest.MZF:"
RFS_INCLUDE+="${MZF_PATH}/Lady_Bug_MZ80K.m12:"
RFS_INCLUDE+="${MZF_PATH}/LAND_ESCAPE.MZF:"
RFS_INCLUDE+="${MZF_PATH}/Le_Mans.MZF:"
RFS_INCLUDE+="${MZF_PATH}/loader.MZF:"
RFS_INCLUDE+="${MZF_PATH}/MAGIC_PAINTBOX.MZF:"
RFS_INCLUDE+="${MZF_PATH}/MAN-HUNT.MZF:"
RFS_INCLUDE+="${MZF_PATH}/m_c_Breakout_2.MZF:"
RFS_INCLUDE+="${MZF_PATH}/m_c_Hissing_Sid.MZF:"
RFS_INCLUDE+="${MZF_PATH}/m_c_Race_Chase.MZF:"
RFS_INCLUDE+="${MZF_PATH}/MEMORY_TEST.MZF:"
RFS_INCLUDE+="${MZF_PATH}/MINI_DATACARD..MZF:"
RFS_INCLUDE+="${MZF_PATH}/minotaur.MZF:"
RFS_INCLUDE+="${MZF_PATH}/ML-SP_8002_BBG.MZF:"
RFS_INCLUDE+="${MZF_PATH}/monitor2:"
RFS_INCLUDE+="${MZF_PATH}/monitor3.MZF:"
RFS_INCLUDE+="${MZF_PATH}/MONITOR6.MZF:"
RFS_INCLUDE+="${MZF_PATH}/MOVING_SEARCHER.MZF:"
RFS_INCLUDE+="${MZF_PATH}/Mz1571.MZF:"
RFS_INCLUDE+="${MZF_PATH}/MZ-2Z009.MZF:"
RFS_INCLUDE+="${MZF_PATH}/mz-5z009_modified2.MZF:"
RFS_INCLUDE+="${MZF_PATH}/MZ700BAS.M12:"
RFS_INCLUDE+="${MZF_PATH}/MZ700BAS.MZF:"
RFS_INCLUDE+="${MZF_PATH}/MZ-700_FORTH.MZF:"
RFS_INCLUDE+="${MZF_PATH}/MZ80A_basic.DSK:"
RFS_INCLUDE+="${MZF_PATH}/MZ-80A_GALACTIC.MZF:"
RFS_INCLUDE+="${MZF_PATH}/Mzprint.MZF:"
RFS_INCLUDE+="${MZF_PATH}/nakamoto_MZ700.m12:"
RFS_INCLUDE+="${MZF_PATH}/NEW_INVADERS.MZF:"
RFS_INCLUDE+="${MZF_PATH}/OPENING_DATA.MZF:"
RFS_INCLUDE+="${MZF_PATH}/OTHELLO.MZF:"
RFS_INCLUDE+="${MZF_PATH}/PAC-MAN3.MZF:"
RFS_INCLUDE+="${MZF_PATH}/PAC-MAN.MZF:"
RFS_INCLUDE+="${MZF_PATH}/PAINFUL_MAN.MZF:"
RFS_INCLUDE+="${MZF_PATH}/PAINTBOX.BAS.MZF:"
RFS_INCLUDE+="${MZF_PATH}/PCG_BASIC_MZ700.MZF:"
RFS_INCLUDE+="${MZF_PATH}/PCG_BASIC.MZF:"
RFS_INCLUDE+="${MZF_PATH}/Pcgrally_MZ800.MZF:"
RFS_INCLUDE+="${MZF_PATH}/PROBE_A_1200.MZF:"
RFS_INCLUDE+="${MZF_PATH}/PROBE_A_8000.MZF:"
RFS_INCLUDE+="${MZF_PATH}/PROBE_A_B600.MZF:"
RFS_INCLUDE+="${MZF_PATH}/QD_BAS_5Z008_MZ700.MZF:"
RFS_INCLUDE+="${MZF_PATH}/QDCOPY.MZF:"
RFS_INCLUDE+="${MZF_PATH}/RAM_CHECK_A.MZF:"
RFS_INCLUDE+="${MZF_PATH}/REALFORT.MZF:"
RFS_INCLUDE+="${MZF_PATH}/ROUND_SHOOT.MZF:"
RFS_INCLUDE+="${MZF_PATH}/sa-5510_Bas_MZ80K.MZF:"
RFS_INCLUDE+="${MZF_PATH}/SA-5510_Compiler.MZF:"
RFS_INCLUDE+="${MZF_PATH}/SA-5510+KN.COMM..MZF:"
RFS_INCLUDE+="${MZF_PATH}/SA-6510.DSK:"
RFS_INCLUDE+="${MZF_PATH}/sa-6510.MZF:"
RFS_INCLUDE+="${MZF_PATH}/SARGON_2.71.MZF:"
RFS_INCLUDE+="${MZF_PATH}/S-Basic-Cent-2.MZF:"
RFS_INCLUDE+="${MZF_PATH}/schach2_MZ700.m12:"
RFS_INCLUDE+="${MZF_PATH}/SCRAMBLE_A.MZF:"
RFS_INCLUDE+="${MZF_PATH}/sdtest.MZF:"
RFS_INCLUDE+="${MZF_PATH}/SECTOR_R_W.MZF:"
RFS_INCLUDE+="${MZF_PATH}/SECTOR_R_W(NEC).MZF:"
RFS_INCLUDE+="${MZF_PATH}/send-1_MZ700.m12:"
RFS_INCLUDE+="${MZF_PATH}/SEND-1.MZF:"
RFS_INCLUDE+="${MZF_PATH}/SHARPLAN01.MZF:"
RFS_INCLUDE+="${MZF_PATH}/sharpmz-test.mzf:"
RFS_INCLUDE+="${MZF_PATH}/sharpmz-test.MZF:"
RFS_INCLUDE+="${MZF_PATH}/SHARP_PENCIL.A1.MZF:"
RFS_INCLUDE+="${MZF_PATH}/SHARP_PENCIL.ALF.MZF:"
RFS_INCLUDE+="${MZF_PATH}/SLAVE_v1.1A.MZF:"
RFS_INCLUDE+="${MZF_PATH}/S-MASTER.MZF:"
RFS_INCLUDE+="${MZF_PATH}/SNAKE&SNAKE_EXP1.MZF:"
RFS_INCLUDE+="${MZF_PATH}/SNOWFLAKES.MZF:"
RFS_INCLUDE+="${MZF_PATH}/SOLO_BASIC.MZF:"
RFS_INCLUDE+="${MZF_PATH}/SP-4015.A1_C.MZF:"
RFS_INCLUDE+="${MZF_PATH}/SP-4015.A1_S.MZF:"
RFS_INCLUDE+="${MZF_PATH}/SP-5060.A1_M.MZF:"
RFS_INCLUDE+="${MZF_PATH}/SP-5060.A1_S.MZF:"
RFS_INCLUDE+="${MZF_PATH}/SPACE_INVADERS.MZF:"
RFS_INCLUDE+="${MZF_PATH}/SP-CONVERT.A1.MZF:"
RFS_INCLUDE+="${MZF_PATH}/STKEEPER2BAS700A.MZF:"
RFS_INCLUDE+="${MZF_PATH}/SUB-MONITOR-700.MZF:"
RFS_INCLUDE+="${MZF_PATH}/SUCOPY_A000.A16.MZF:"
RFS_INCLUDE+="${MZF_PATH}/SUPERFIRE.MZF:"
RFS_INCLUDE+="${MZF_PATH}/SUPER_PUCK-MAN.MZF:"
RFS_INCLUDE+="${MZF_PATH}/SUPERTAPE_2.MZF:"
RFS_INCLUDE+="${MZF_PATH}/SUTAM1F.MZF:"
RFS_INCLUDE+="${MZF_PATH}/SUTAMC9.MZF:"
RFS_INCLUDE+="${MZF_PATH}/SUTAPEBA.MZF:"
RFS_INCLUDE+="${MZF_PATH}/SUTAPEMO.MZF:"
RFS_INCLUDE+="${MZF_PATH}/tetris-2_MZ800.MZF:"
RFS_INCLUDE+="${MZF_PATH}/TETRIS.MZF:"
RFS_INCLUDE+="${MZF_PATH}/TEXT_BASIC_I.MZF:"
RFS_INCLUDE+="${MZF_PATH}/TEXT~ED_v1.2.MZF:"
RFS_INCLUDE+="${MZF_PATH}/textsobs5.MZF:"
RFS_INCLUDE+="${MZF_PATH}/TRANS.MZF:"
RFS_INCLUDE+="${MZF_PATH}/TRANS.MZT:"
RFS_INCLUDE+="${MZF_PATH}/ufo.MZF:"
RFS_INCLUDE+="${MZF_PATH}/UNI=BASIC800.MZF:"
RFS_INCLUDE+="${MZF_PATH}/UNIVERSAL_BASIC.MZF:"
RFS_INCLUDE+="${MZF_PATH}/URAS-700.MZF:"
RFS_INCLUDE+="${MZF_PATH}/Utility_2.MZF:"
RFS_INCLUDE+="${MZF_PATH}/Utility.MZT:"
RFS_INCLUDE+="${MZF_PATH}/Utility_V_1.1.MZF:"
RFS_INCLUDE+="${MZF_PATH}/Utility_V_2.0.MZF:"
RFS_INCLUDE+="${MZF_PATH}/WDPRO_2.37AT_C2.MZF:"
RFS_INCLUDE+="${MZF_PATH}/WDPRO_2.37AT.MZF:"
RFS_INCLUDE+="${MZF_PATH}/Wooky.MZF:"
RFS_INCLUDE+="${MZF_PATH}/XPATCH_5510_v2.2.MZF:"
RFS_INCLUDE+="${MZF_PATH}/Z80_MACHINE.A1_M.MZF:"
RFS_INCLUDE+="${MZF_PATH}/Z80_MACHINE.A1_S.MZF:"
RFS_INCLUDE+="${MZF_PATH}/Z80_MACHINE.A2_M.MZF:"
RFS_INCLUDE+="${MZF_PATH}/Z80MACHINE.A3_C2.MZF:"
RFS_INCLUDE+="${MZF_PATH}/Z80_MACHINE.A3_S.MZF:"
RFS_INCLUDE+="${MZF_PATH}/ZEN7E.A2.MZF:"
RFS_INCLUDE+="${MZF_PATH}/Zexas_MZ800.MZF:"
RFS_INCLUDE+="${MZF_PATH}/ZSP:"
RFS_INCLUDE+="${MZF_PATH}/ZSP.MZF"
IFS=":"; for f in ${RFS_INCLUDE}
do
${SDTOOL} --image ${RFS_IMAGE_FILE} --add ${f}
if [ $? != 0 ]; then
echo "Failed to add:${f} into the RFS Image, aborting."
exit 2
fi
done
${SDTOOL} --image ${RFS_IMAGE_FILE} --list-dir
# Concatenate the RFS and CPM images to make a final SD card image.
#
echo "Adding RFS Image:$RFS_IMAGE_FILE} to start of SD Card image."
cat ${RFS_IMAGE_FILE} > ${SD_IMAGE_FILE}
IFS=" "; for f in ${CPM_IMAGE_FILES}
do
echo "Adding CPM Drive Image:${f} to SD Card image."
cat ${CPM_DIR}/${f} >> ${SD_IMAGE_FILE}
done
echo "SD Card image generated, file:${SD_IMAGE_FILE}"
exit 0

BIN
software/tools/mzfdc2 Executable file

Binary file not shown.

BIN
software/tools/sdtool Executable file

Binary file not shown.