;
;	SILICON DISC FOR TATUNG EINSTEIN
;	SOURCE CODE FOR ROM VERSION 1.1
;
;	Copyright (c) Tony Brewer 1986,2010
;	Disassembled from ROM code 2010
;
;
;	EQUATES
;
SDISC	EQU	3		;Silicon disc is disc 3
;
;Fixed addresses
;
SCRP	EQU	0FB00H		;Start of scratch-pad area
DIRBUF	EQU	0FD00H		;128-byte directory buffer
CSV	EQU	DIRBUF+128	;Start of check vector area
CSVSD	EQU	CSV+16*SDISC	;Check vector for silicon disc - not needed so use for
ALVSD	EQU	CSVSD		;allocation vector instead as both are same size luckily
HSTBUF	EQU	0FE00H		;512-byte file de-blocking buffer
;
FREE	EQU	0FDE4H		;Free space, not used by MOS or DOS
OLDVCT	EQU	FREE+02H	;Original MCAL vector table address
SDIO	EQU	FREE+04H	;Silicon disc I/O routine
DPBSD	EQU	FREE+0CH	;Disc parameter block for silicon disc
DSCXLT	EQU	FREE+1BH	;Disc translation byte
;
;Scratch-pad
;
FMVCT	EQU	SCRP+3AH	;MCAL vector table address
HSTDSC	EQU	SCRP+50H	;Disc drive (0-3)
HSTTRK	EQU	SCRP+51H	;Track
;HSTSEC	EQU	SCRP+52H	;Sector
HSTDMA	EQU	SCRP+53H	;Disc buffer area
STATUS	EQU	SCRP+56H	;Error status value
SAVHL	EQU	SCRP+79H	;Saves HL during MCAL routine
DISC	EQU	SCRP+7DH	;DOS disc
TRAK	EQU	SCRP+7EH	;DOS track
;SECT	EQU	SCRP+7FH	;DOS sector
DBUF	EQU	SCRP+80H	;DOS buffer address
DPBPTR	EQU	SCRP+0B3H	;Disc parameter base address
;
;Ports
;
BANKSW	EQU	24H		;Memory bank switch
;
SDSECL	EQU	0F8H		;Silicon disc sector low
SDSECH	EQU	0F9H		;Silicon disc sector high
SDDATA	EQU	0FAH		;Silicon disc data
;
;Other
;
FORMAT	EQU	0E5H		;CP/M format byte
;
;
;
;	CODE
;
	ORG	4000H
;
;4000H
ROM2:	DB 0			;ROM 2 detection byte, 0 for auto execution
;
;Entry point from MOS ROM, if byte at 4000H is zero
;
;4001H
R2INIT:	JP	SD1		;Jump to initialisation code
;
;4004H
R2XEC:	RET			;Entry point for MCAL D2 (does nothing)
	NOP			;Leave space for JP xxxx in future
	NOP			;Leave space for JP xxxx in future
	NOP			;Why have this? Two NOPs are enough
;
;
;Silicon Disc initialisation code 
;
;Copy data and I/O routine to free space in high memory
;
SD1:	LD	BC,COPY2-COPY1
	LD	DE,FREE
	LD	HL,COPY1
	LDIR
;
;Check whether silicon disc formatted previously (before a reset)
;
	LD	BC,39*256+1	;B = logical sector 39, C = track 1 (last logical system sector)
;
;Assume last logical system sector is never written to after formatting
;If it contains all format characters then silicon disc has survived a reset

	LD	HL,HSTBUF
	CALL	RDSD		;Preserves HL
	CALL	CHKFMT		;Preserves HL
	JR	Z,SD6		;Jump if silicon disc already formatted
;
;Here if silicon disc unformatted
;
	LD	B,128
SD2:	LD	(HL),FORMAT	;Fill first 128 bytes of HSTBUF with format byte
	INC	HL
	DJNZ	SD2
;
;Now format silicon disc
;
	LD	BC,0		;B = logical sector 0, C = track 0 
	LD	HL,HSTBUF
	LD	DE,0		;DE = logical sector count
;
;Write next sector
;
SD3:	CALL	WRSD		;Write logical sector
	JR	NZ,SD4		;Jump if past end of silicon disc
;
;Now read sector and verify it
;
	CALL	RDSD		;Read logical sector
	CALL	CHKFMT		;All format characters?
	JR	NZ,SD4		;Jump if not
;
	CALL	INCSEC		;Increment logical sector
	INC	DE		;Increment logical sector count
	JR	SD3
;
;Here if past end of silicon disc if DE = 2048 or verify error if DE < 2048
;
SD4:	LD	HL,2048
	AND	A		;Clear carry flag for SBC
	SBC	HL,DE
	JR	Z,SD6		;Jump if all silicon disc formatted and verified
;
;Here if silicon disc did not format properly
;It is either not connected or faulty
;Wipe silicon disc stuff in high memory and quit
;
	LD	B,COPY2-COPY1
	LD	HL,FREE
SD5:	LD	(HL),0
	INC	HL
	DJNZ	SD5
	RET
;
;Here if silicon disc formatted
;Re-direct MCALs, then return to MOS
;
SD6:	LD	HL,(FMVCT)	;HL = original MCAL vector address
	LD	(OLDVCT),HL	;Save it
	LD	HL,NEWVCT	;HL = new MCAL vector address
	LD	(FMVCT),HL	;MCALs re-directed from now on
	RET 
;
;
;	New MCAL routines for Silicon Disc
;
;
;SELDSC	Select Disc MCAL B6
;
;Entry	C = logical disc to select
;Exit	HL -> disc parameter header if disc <= 4, else HL = 0
;
SELDSC:	LD	A,C
	CP	4
	JP	NC,MCALC	;Jump if beyond disc 3
;
;Now find physical disc using new translation byte
;
	LD	A,(DSCXLT)	;A = disc translation byte
	INC	C
SELDS1:	DEC	C
	JR	Z,SELDS2
	RRCA
	RRCA
	JR	SELDS1
;
;Here bits 1-0 of A are physical disc number
;
SELDS2:	AND	00000011B	;Zero unwanted bits
	LD	C,A		;C = physical disc to select
	PUSH	AF
	CALL	MCALC		;Call MOS MCAL B6 Select Disc
	POP	AF
	CP	SDISC
	RET	NZ		;Return if not silicon disc
;
;HL = 0 after MOS MCAL B6 only if disc > 4
;but test already done for valid disc so HL <> 0
;HL -> DPH disc parameter header for silicon disc
;
	LD	A,H		;Unnecessary
	AND	A		;     "
	RET	Z		;     "
;
	EX	DE,HL		;DE -> disc parameter header
	LD	HL,10
	ADD	HL,DE		;HL -> disc parameter block address
	LD	C,(HL)
	INC	HL
	LD	B,(HL)		;BC -> existing disc parameter block
	LD	HL,DPBSD	;HL -> new disc paramater block for silicon disc
	AND	A		;Clear carry flag for SBC
	SBC	HL,BC
	EX	DE,HL		;HL -> disc parameter header
	RET	Z		;Return if DPH data already correct
;
;Overwrite existing disc parameter header with correct silicon disc data
;This is done once only
;
	PUSH	HL
	EX	DE,HL		;DE -> existing disc parameter header
	LD	HL,DPHSD	;HL -> new disc parameter header for silicon disc
	LD	BC,16
	LDIR
	POP	HL
	RET
;
;
;RDREC	Read Record MCAL BA
;Read logical sector
;
;Entry	-
;Exit	A = error code (0 if success)
;
RDREC:	LD	A,(DISC)
	CP	SDISC
	JP	NZ,MCALC	;Jump to MOS MCAL routine if not silicon disc
;
	LD	BC,(TRAK)
	LD	HL,(DBUF)
	JP	RDSD		;Read logical sector and return
;
;
;WRREC	Write Record MCAL BB
;Write logical sector
;
;Entry	-
;Exit	A = error code (0 if success)
;
WRREC:	LD	A,(DISC)
	CP	SDISC
	JP	NZ,MCALC	;Jump to MOS MCAL routine if not silicon disc
;
	LD	BC,(TRAK)
	LD	HL,(DBUF)
	JP	WRSD		;Write logical sector and return
;
;
;RDSECT	Read Sector MCAL A2
;Reads 512-byte sector
;
;Entry	-
;Exit	A = error code (0 if success)
;
RDSECT:	LD	A,(HSTDSC)
	CP	SDISC
	JP	NZ,MCALC	;Jump to MOS MCAL routine if not silicon disc
;
	LD	BC,(HSTTRK)	;C = track, B = 512-byte sector
	LD	HL,(HSTDMA)
	LD	DE,4		;DE =logical sector count {LD E,4 is better}
RDSEC1:	SLA	B
	SLA	B		;B = logical sector (4 * 512-byte sector)
RDSEC2:	CALL	RDSD		;Read logical sector
	JR	NZ,RDSEC4	;Jump if error
;
	CALL	INCSEC
	LD	A,128
	ADD	A,L
	LD	L,A
	JR	NC,RDSEC3
;
	INC	H
RDSEC3:	DEC	DE		;{DEC E / JR NZ,RDSEC2 / LD A,E is better}
	LD	A,D
	OR	E
	JR	NZ,RDSEC2	;A = 0 if finished
;
RDSEC4:	LD	(STATUS),A	;Error code = 0 for success
	RET
;
;
;WRSECT	Write Sector MCAL A3
;Writes 512-byte sector
;
;Entry	-
;Exit	A = error code (0 if success)
;
WRSECT:	LD	A,(HSTDSC)
	CP	SDISC
	JP	NZ,MCALC	;Jump to MOS MCAL routine if not silicon disc
;
	LD	BC,(HSTTRK)	;C = track, B = 512-byte sector
	LD	HL,(HSTDMA)
	LD	DE,4		;DE = logical sector count {LD E,4 is better}
WRSEC1:	SLA	B
	SLA	B		;B = logical sector (4 * 512-byte sector)
WRSEC2:	CALL	WRSD		;Write sector to silicon disc
	JR	NZ,WRSEC4	;Jump if error
;
	CALL	INCSEC
	LD	A,128
	ADD	A,L
	LD	L,A
	JR	NC,WRSEC3
;
	INC	H
;
;HL -> next logical sector in buffer
;
WRSEC3:	DEC	DE		;{DEC E / JR NZ,WRSEC2 / LD A,E is better}
	LD	A,D
	OR	E
	JR	NZ,WRSEC2	;Jump if more logical sectors to write
;
;A = 0 if finished successfully
;
WRSEC4:	LD	(STATUS),A	;Store error code
	RET
;
;
;RDBLK	Read Block MCAL A4
;
;Entry	A = disc, B = 512-byte sector, C = track, DE = finish address, (SAVHL) = start address
;Exit	A = error code (0 if success)
;
;Entry	
;Exit	
;
RDBLK:	CP	SDISC
	JP	NZ,MCALC	;Jump to MOS MCAL routine if not silicon disc
;
	LD	HL,(SAVHL)	;HL = start address
;
;*** Is the rest of this routine right? ***
;
	EX	DE,HL
	SCF
	SBC	HL,DE
	JR	NC,RDBLK1
;
	LD	HL,0
RDBLK1:	SRL	H
	INC	H
	LD	L,H
	LD	H,0
	ADD	HL,HL
	ADD	HL,HL
	EX	DE,HL
	JR	RDSEC1
;
;
;WRBLK	Write Block MCAL A5
;
;Entry	A = disc, B = 512-byte sector, C = track, DE = finish address, (SAVHL) = start address
;Exit	A = error code (0 if success)
;
WRBLK:	CP	SDISC
	JP	NZ,MCALC	;Jump to MOS MCAL routine if not silicon disc
;
	LD	HL,(SAVHL)	;HL = start address
;
;*** Is the rest of this routine right? ***
;
	EX	DE,HL
	SCF
	SBC	HL,DE
	JR	NC,WRBLK1
;
	LD	HL,0
WRBLK1:	SRL	H
	INC	H
	LD	L,H
	LD	H,0
	ADD	HL,HL
	ADD	HL,HL
	EX	DE,HL
	JR	WRSEC1
;
;
;MCALFF	MCAL FF
;Does MCAL A4 Read Block for silicon disc
;Created just for testing?
;
;Entry	-
;Exit	-
;
MCALFF:	LD	A,SDISC		;Select silicon disc
	JP	RDBLKJ
;
;
;MCALC calculates address of MCAL routine and returns to it
;
;Entry	L = MCAL number - 80H (00H to 7FH)
;Exit	varies
;
MCALC:	PUSH	AF
	LD	A,L
	LD	HL,(OLDVCT)	;HL -> original MCAL vector table in MOS ROM
	ADD	A,A
	ADD	A,L
	LD	L,A
	JR	NC,MCALC1
;
	INC	H
;
;HL -> address of MCAL routine in MOS ROM
;
MCALC1:	LD	A,(HL)
	INC	HL
	LD	H,(HL)
	LD	L,A		;HL = address of MCAL routine
	POP	AF
;
	PUSH	HL		;Push MCAL routine address
	LD	HL,(SAVHL)	;Get saved value of HL
	RET			;Return to MCAL routine in MOS ROM
;
;
;
;NEWVCT is new MCAL vector table
;Has entries for MCALs above D4 not supported by MOS 1.2
;
NEWVCT:
	DW	MCALJP + (80H - 80H) * 5
	DW	MCALJP + (81H - 80H) * 5
	DW	MCALJP + (82H - 80H) * 5
	DW	MCALJP + (83H - 80H) * 5
	DW	MCALJP + (84H - 80H) * 5
	DW	MCALJP + (85H - 80H) * 5
	DW	MCALJP + (86H - 80H) * 5
	DW	MCALJP + (87H - 80H) * 5
	DW	MCALJP + (88H - 80H) * 5
	DW	MCALJP + (89H - 80H) * 5
	DW	MCALJP + (8AH - 80H) * 5
	DW	MCALJP + (8BH - 80H) * 5
	DW	MCALJP + (8CH - 80H) * 5
	DW	MCALJP + (8DH - 80H) * 5
	DW	MCALJP + (8EH - 80H) * 5
	DW	MCALJP + (8FH - 80H) * 5
;
	DW	MCALJP + (90H - 80H) * 5
	DW	MCALJP + (91H - 80H) * 5
	DW	MCALJP + (92H - 80H) * 5
	DW	MCALJP + (93H - 80H) * 5
	DW	MCALJP + (94H - 80H) * 5
	DW	MCALJP + (95H - 80H) * 5
	DW	MCALJP + (96H - 80H) * 5
	DW	MCALJP + (97H - 80H) * 5
	DW	MCALJP + (98H - 80H) * 5
	DW	MCALJP + (99H - 80H) * 5
	DW	MCALJP + (9AH - 80H) * 5
	DW	MCALJP + (9BH - 80H) * 5
	DW	MCALJP + (9CH - 80H) * 5
	DW	MCALJP + (9DH - 80H) * 5
	DW	MCALJP + (9EH - 80H) * 5
	DW	MCALJP + (9FH - 80H) * 5
;
	DW	MCALJP + (0A0H - 80H) * 5
	DW	MCALJP + (0A1H - 80H) * 5
	DW	MCALJP + (0A2H - 80H) * 5
	DW	MCALJP + (0A3H - 80H) * 5
	DW	MCALJP + (0A4H - 80H) * 5
	DW	MCALJP + (0A5H - 80H) * 5
	DW	MCALJP + (0A6H - 80H) * 5
	DW	MCALJP + (0A7H - 80H) * 5
	DW	MCALJP + (0A8H - 80H) * 5
	DW	MCALJP + (0A9H - 80H) * 5
	DW	MCALJP + (0AAH - 80H) * 5
	DW	MCALJP + (0ABH - 80H) * 5
	DW	MCALJP + (0ACH - 80H) * 5
	DW	MCALJP + (0ADH - 80H) * 5
	DW	MCALJP + (0AEH - 80H) * 5
	DW	MCALJP + (0AFH - 80H) * 5
;
	DW	MCALJP + (0B0H - 80H) * 5
	DW	MCALJP + (0B1H - 80H) * 5
	DW	MCALJP + (0B2H - 80H) * 5
	DW	MCALJP + (0B3H - 80H) * 5
	DW	MCALJP + (0B4H - 80H) * 5
	DW	MCALJP + (0B5H - 80H) * 5
	DW	MCALJP + (0B6H - 80H) * 5
	DW	MCALJP + (0B7H - 80H) * 5
	DW	MCALJP + (0B8H - 80H) * 5
	DW	MCALJP + (0B9H - 80H) * 5
	DW	MCALJP + (0BAH - 80H) * 5
	DW	MCALJP + (0BBH - 80H) * 5
	DW	MCALJP + (0BCH - 80H) * 5
	DW	MCALJP + (0BDH - 80H) * 5
	DW	MCALJP + (0BEH - 80H) * 5
	DW	MCALJP + (0BFH - 80H) * 5
;
	DW	MCALJP + (0C0H - 80H) * 5
	DW	MCALJP + (0C1H - 80H) * 5
	DW	MCALJP + (0C2H - 80H) * 5
	DW	MCALJP + (0C3H - 80H) * 5
	DW	MCALJP + (0C4H - 80H) * 5
	DW	MCALJP + (0C5H - 80H) * 5
	DW	MCALJP + (0C6H - 80H) * 5
	DW	MCALJP + (0C7H - 80H) * 5
	DW	MCALJP + (0C8H - 80H) * 5
	DW	MCALJP + (0C9H - 80H) * 5
	DW	MCALJP + (0CAH - 80H) * 5
	DW	MCALJP + (0CBH - 80H) * 5
	DW	MCALJP + (0CCH - 80H) * 5
	DW	MCALJP + (0CDH - 80H) * 5
	DW	MCALJP + (0CEH - 80H) * 5
	DW	MCALJP + (0CFH - 80H) * 5
;
	DW	MCALJP + (0D0H - 80H) * 5
	DW	MCALJP + (0D1H - 80H) * 5
	DW	MCALJP + (0D2H - 80H) * 5
	DW	MCALJP + (0D3H - 80H) * 5
	DW	MCALJP + (0D4H - 80H) * 5
	DW	MCALJP + (0D5H - 80H) * 5
	DW	MCALJP + (0D6H - 80H) * 5
	DW	MCALJP + (0D7H - 80H) * 5
	DW	MCALJP + (0D8H - 80H) * 5
	DW	MCALJP + (0D9H - 80H) * 5
	DW	MCALJP + (0DAH - 80H) * 5
	DW	MCALJP + (0DBH - 80H) * 5
	DW	MCALJP + (0DCH - 80H) * 5
	DW	MCALJP + (0DDH - 80H) * 5
	DW	MCALJP + (0DEH - 80H) * 5
	DW	MCALJP + (0DFH - 80H) * 5
;
	DW	MCALJP + (0E0H - 80H) * 5
	DW	MCALJP + (0E1H - 80H) * 5
	DW	MCALJP + (0E2H - 80H) * 5
	DW	MCALJP + (0E3H - 80H) * 5
	DW	MCALJP + (0E4H - 80H) * 5
	DW	MCALJP + (0E5H - 80H) * 5
	DW	MCALJP + (0E6H - 80H) * 5
	DW	MCALJP + (0E7H - 80H) * 5
	DW	MCALJP + (0E8H - 80H) * 5
	DW	MCALJP + (0E9H - 80H) * 5
	DW	MCALJP + (0EAH - 80H) * 5
	DW	MCALJP + (0EBH - 80H) * 5
	DW	MCALJP + (0ECH - 80H) * 5
	DW	MCALJP + (0EDH - 80H) * 5
	DW	MCALJP + (0EEH - 80H) * 5
	DW	MCALJP + (0EFH - 80H) * 5
;
	DW	MCALJP + (0F0H - 80H) * 5
	DW	MCALJP + (0F1H - 80H) * 5
	DW	MCALJP + (0F2H - 80H) * 5
	DW	MCALJP + (0F3H - 80H) * 5
	DW	MCALJP + (0F4H - 80H) * 5
	DW	MCALJP + (0F5H - 80H) * 5
	DW	MCALJP + (0F6H - 80H) * 5
	DW	MCALJP + (0F7H - 80H) * 5
	DW	MCALJP + (0F8H - 80H) * 5
	DW	MCALJP + (0F9H - 80H) * 5
	DW	MCALJP + (0FAH - 80H) * 5
	DW	MCALJP + (0FBH - 80H) * 5
	DW	MCALJP + (0FCH - 80H) * 5
	DW	MCALJP + (0FDH - 80H) * 5
	DW	MCALJP + (0FEH - 80H) * 5
	DW	MCALJP + (0FFH - 80H) * 5
;
;
;MCALJP is MCAL jump table
;
MCALJP:
	LD	L,80H
	JP	MCALC
;
	LD	L,81H
	JP	MCALC
;
	LD	L,82H
	JP	MCALC
;
	LD	L,83H
	JP	MCALC
;
	LD	L,84H
	JP	MCALC
;
	LD	L,85H
	JP	MCALC
;
	LD	L,86H
	JP	MCALC
;
	LD	L,87H
	JP	MCALC
;
	LD	L,88H
	JP	MCALC
;
	LD	L,89H
	JP	MCALC
;
	LD	L,8AH
	JP	MCALC
;
	LD	L,8BH
	JP	MCALC
;
	LD	L,8CH
	JP	MCALC
;
	LD	L,8DH
	JP	MCALC
;
	LD	L,8EH
	JP	MCALC
;
	LD	L,8FH
	JP	MCALC
;
	LD	L,90H
	JP	MCALC
;
	LD	L,91H
	JP	MCALC
;
	LD	L,92H
	JP	MCALC
;
	LD	L,93H
	JP	MCALC
;
	LD	L,94H
	JP	MCALC
;
	LD	L,95H
	JP	MCALC
;
	LD	L,96H
	JP	MCALC
;
	LD	L,97H
	JP	MCALC
;
	LD	L,98H
	JP	MCALC
;
	LD	L,99H
	JP	MCALC
;
	LD	L,9AH
	JP	MCALC
;
	LD	L,9BH
	JP	MCALC
;
	LD	L,9CH
	JP	MCALC
;
	LD	L,9DH
	JP	MCALC
;
	LD	L,9EH
	JP	MCALC
;
	LD	L,9FH
	JP	MCALC
;
	LD	L,0A0H
	JP	MCALC
;
	LD	L,0A1H
	JP	MCALC
;
	LD	L,0A2H		;Read Sector
	JP	RDSECT
;
	LD	L,0A3H		;Write Sector
	JP	WRSECT
;
RDBLKJ:	LD	L,0A4H		;Read Block
	JP	RDBLK
;
	LD	L,0A5H		;Write Block
	JP	WRBLK
;
	LD	L,0A6H
	JP	MCALC
;
	LD	L,0A7H
	JP	MCALC
;
	LD	L,0A8H
	JP	MCALC
;
	LD	L,0A9H
	JP	MCALC
;
	LD	L,0AAH
	JP	MCALC
;
	LD	L,0ABH
	JP	MCALC
;
	LD	L,0ACH
	JP	MCALC
;
	LD	L,0ADH
	JP	MCALC
;
	LD	L,0AEH
	JP	MCALC
;
	LD	L,0AFH
	JP	MCALC
;
	LD	L,0B0H
	JP	MCALC
;
	LD	L,0B1H
	JP	MCALC
;
	LD	L,0B2H
	JP	MCALC
;
	LD	L,0B3H
	JP	MCALC
;
	LD	L,0B4H
	JP	MCALC
;
	LD	L,0B5H
	JP	MCALC
;
	LD	L,0B6H		;Select Disc
	JP	SELDSC
;
	LD	L,0B7H
	JP	MCALC
;
	LD	L,0B8H
	JP	MCALC
;
	LD	L,0B9H
	JP	MCALC
;
	LD	L,0BAH		;Read Record
	JP	RDREC
;
	LD	L,0BBH		;Write Record
	JP	WRREC
;
	LD	L,0BCH
	JP	MCALC
;
	LD	L,0BDH
	JP	MCALC
;
	LD	L,0BEH
	JP	MCALC
;
	LD	L,0BFH
	JP	MCALC
;
	LD	L,0C0H
	JP	MCALC
;
	LD	L,0C1H
	JP	MCALC
;
	LD	L,0C2H
	JP	MCALC
;
	LD	L,0C3H
	JP	MCALC
;
	LD	L,0C4H
	JP	MCALC
;
	LD	L,0C5H
	JP	MCALC
;
	LD	L,0C6H
	JP	MCALC
;
	LD	L,0C7H
	JP	MCALC
;
	LD	L,0C8H
	JP	MCALC
;
	LD	L,0C9H
	JP	MCALC
;
	LD	L,0CAH
	JP	MCALC
;
	LD	L,0CBH
	JP	MCALC
;
	LD	L,0CCH
	JP	MCALC
;
	LD	L,0CDH
	JP	MCALC
;
	LD	L,0CEH
	JP	MCALC
;
	LD	L,0CFH
	JP	MCALC
;
	LD	L,0D0H
	JP	MCALC
;
	LD	L,0D1H
	JP	MCALC
;
	LD	L,0D2H
	JP	MCALC
;
	LD	L,0D3H
	JP	MCALC
;
	LD	L,0D4H
	JP	MCALC
;
	LD	L,0D5H
	JP	MCALC
;
	LD	L,0D6H
	JP	MCALC
;
	LD	L,0D7H
	JP	MCALC
;
	LD	L,0D8H
	JP	MCALC
;
	LD	L,0D9H
	JP	MCALC
;
	LD	L,0DAH
	JP	MCALC
;
	LD	L,0DBH
	JP	MCALC
;
	LD	L,0DCH
	JP	MCALC
;
	LD	L,0DDH
	JP	MCALC
;
	LD	L,0DEH
	JP	MCALC
;
	LD	L,0DFH
	JP	MCALC
;
	LD	L,0E0H
	JP	MCALC
;
	LD	L,0E1H
	JP	MCALC
;
	LD	L,0E2H
	JP	MCALC
;
	LD	L,0E3H
	JP	MCALC
;
	LD	L,0E4H
	JP	MCALC
;
	LD	L,0E5H
	JP	MCALC
;
	LD	L,0E6H
	JP	MCALC
;
	LD	L,0E7H
	JP	MCALC
;
	LD	L,0E8H
	JP	MCALC
;
	LD	L,0E9H
	JP	MCALC
;
	LD	L,0EAH
	JP	MCALC
;
	LD	L,0EBH
	JP	MCALC
;
	LD	L,0ECH
	JP	MCALC
;
	LD	L,0EDH
	JP	MCALC
;
	LD	L,0EEH
	JP	MCALC
;
	LD	L,0EFH
	JP	MCALC
;
	LD	L,0F0H
	JP	MCALC
;
	LD	L,0F1H
	JP	MCALC
;
	LD	L,0F2H
	JP	MCALC
;
	LD	L,0F3H
	JP	MCALC
;
	LD	L,0F4H
	JP	MCALC
;
	LD	L,0F5H
	JP	MCALC
;
	LD	L,0F6H
	JP	MCALC
;
	LD	L,0F7H
	JP	MCALC
;
	LD	L,0F8H
	JP	MCALC
;
	LD	L,0F9H
	JP	MCALC
;
	LD	L,0FAH
	JP	MCALC
;
	LD	L,0FBH
	JP	MCALC
;
	LD	L,0FCH
	JP	MCALC
;
	LD	L,0FDH
	JP	MCALC
;
	LD	L,0FEH
	JP	MCALC
;
	LD	L,0FFH		;New MCAL (just for testing?)
	JP	MCALFF
;
;
;RDSD reads logical sector from silicon disc
;
;Entry	B = logical sector, C = track, HL -> buffer
;Exit	A = error code
;
RDSD:	PUSH	BC
	PUSH	DE
	PUSH	HL
	CALL	SETSEC		;Set sector address
	AND	A
	JR	NZ,WRSD1	;Jump if past end of disc
;
;B = 128, C = silicon disc data port
;
	DEC	B		;Needed due to INIR and OTIR difference 
	LD	A,0B2H		;Opcode for INIR (after 0EDH)
	LD	(SDIO+3),A	;Patch RAM routine
	CALL	SDIO		;Input 127 bytes
;
	LD	A,0A2H		;Opcode for INI (after 0EDH)
	LD	(SDIO+3),A	;Patch RAM routine
	CALL	SDIO		;Input last byte
	XOR A			;Success
	JR	WRSD1		;Restore registers and return
;
;
;WRSD writes logical sector to silicon disc
;
;Entry	B = logical sector, C = track, HL -> buffer
;Exit	A = error code, B = logical sector, C = track, HL -> buffer
;
WRSD:	PUSH	BC
	PUSH	DE
	PUSH	HL
	CALL	SETSEC		;Set sector address
	AND	A
	JR	NZ,WRSD1	;Jump if past end of disc
;
;B = 128, C = silicon disc data port
;
	LD	A,0B3H		;Opcode for OTIR (after 0EDH)
	LD	(SDIO+3),A	;Patch RAM routine
	CALL	SDIO		;Output 128 bytes
	XOR	A		;Success
WRSD1:	POP	HL
	POP	DE
	POP	BC
	AND	A
	RET
;
;
;SETSEC sets logical sector registers on silicon disc
;
;Entry:	B = logical sector, C = track, HL -> buffer
;Exit:	A = error code, B = 128 (if A = 0), C = silicon disc data port (if A = 0)
;
SETSEC:	EX	DE,HL		;DE -> buffer
	LD	A,B		;Save 128-byte sector
	LD	L,C
	LD	H,0		;HL = track
	ADD	HL,HL
	ADD	HL,HL
	ADD	HL,HL		;HL = track * 8
	LD	B,H
	LD	C,L		;BC = track * 8
	ADD	HL,HL
	ADD	HL,HL		;HL = track * 32
	ADD	HL,BC		;HL = track * 40 (there are 40 logical sectors per track)
	LD	C,A
	LD	B,0		;BC = sector
	ADD	HL,BC		;HL = track * 40 + sector = sectors from start of disc
	EX	DE,HL		;DE = logical sector count (0-2047 for 256KB silicon disc), HL -> buffer
;
;Check logical sector count is in range
;
	LD	A,7
	CP	D
	LD	A,3		;Error code: track/sector not found
	RET	C		;Return if logical sector count past end of disc
;
;Set sector registers
;
	LD	A,E
	OUT	(SDSECL),A	;Output logical sector count low
	LD	A,D
	OUT	(SDSECH),A	;Output logical sector count high
;
	LD	B,128		;B = logical sector length
	LD	C,SDDATA	;C = silicon disc data port
	XOR	A
	RET
; 
;
;CHKFMT checks whether 128-byte buffer contains all format characters
;
;Entry	HL -> buffer
;Exit	Z for success, else NZ
;
CHKFMT:	PUSH	BC
	PUSH	HL
	LD	A,FORMAT
	LD	B,128
CHKFM1:	CP	(HL)
	JR	NZ,CHKFM2
;
;Here Z flag set if (HL) is format character
;
	INC	HL		;Preserves Z flag
	DJNZ	CHKFM1		;Preserves Z flag
CHKFM2:	POP	HL
	POP	BC
	RET
; 
;
;INCSEC increments logical sector
;
;Entry	B = logical sector, C = track
;Exit	B = logical sector + 1 or 0, C = track or track + 1
;
INCSEC:	LD	A,B
	INC	A
	CP	40
	JR	C,INCSC1	;Jump if still in same track
;
;Here if must go to next track
;
	XOR	A		;Logical sector 0
	INC	C		;Increment track
INCSC1:	LD	B,A
	RET
;
;Alternative that saves a byte
;
;INCSEC: LD	A,B
;	 INC	A
;	 SUB	40		;A = 0 if sector 40 (sector 0 on next track)
;	 JR	NZ,INCSC1	;Jump if still in same track
;	 INC	C		;Increment track
;INCSC1: LD	B,A
;	 RET
;
;
;Data and code from COPY1-COPY2 copied to high memory
;
COPY1:
;
;Copied to FREE in high memory
;What is the word for?
;
;FREE:
	DW	4453H		;Appears to be unused
;
;
;OLDVCT holds original MCAL vector table address
;Copied to OLDVCT (FREE+02H) in high memory
;
;OLDVCT:
	DW	0		;Holds (FMVCT)
;
;
;SDIO is low-level silicon disc input or output routine
;(SDIO+3) is patched with INIR/INI/OTIR opcode as needed
;Copied to SDIO (FREE+04H) in high memory
;
;Entry	B = byte count, C = silicon disc data port
;Exit	-
;
;SDIO:
	OUT	(BANKSW),A	;Switch out ROM
	OTIR 			;I/O instruction
	NOP			;Unnecessary
	OUT	(BANKSW),A	;Switch in ROM
	RET
;
;
;DPBSD disc parameter block for silicon disc (15 bytes)
;Copied to DPBSD (FREE+0CH) in high memory
;
;DPBSD:
	DW	40		;SPT	logical sectors per track	
	DB	4		;BSH	for block size BLS = 2048
	DB	15		;BHM	for block size BLS = 2048
	DB	0		;EXM	should be 1!
	DW	122		;DSM	BLS * (DSM + 1) + 10K for reserved tracks = 256K
	DW	63		;DRM	directory entries - 1
	DB	10000000B	;AL0	one block for directory (bit 7 of AL0 set)
	DB	00000000B	;AL1	one block for directory (bit 7 of AL0 set)
	DW	0		;CKS	no check vector for non-removable disc
	DW	2		;OFF	two reserved tracks at start of disc
;
;
;DSCXLT is logical-physical disc translation byte
;Copied to DSCXLT (FREE+1BH) in high memory
;
;	Bits 1-0: physical disc for logical disc 0 (default 00)
;	Bits 3-2: physical disc for logical disc 1 (default 01)
;	Bits 5-4: physical disc for logical disc 2 (default 10)
;	Bits 7-6: physical disc for logical disc 3 (default 11)
;
;Modifying this byte changes the disc numbering
;
;DSCXLT:
	DB	11100100B	;Physical disc = logical disc by default
;
COPY2:
;
;
;DPHSD disc parameter header for silicon disc (16 bytes)
;Copied to existing DPH area in high memory
;
DPHSD:	DW	0		;XLT	no sector translation
	DW	0		;	scratchpad
	DW	0		;	scratchpad
	DW	0		;	scratchpad
	DW	DIRBUF		;DIRBUF	same for all discs
	DW	DPBSD		;DPB	address of disc parameter block
	DW	0		;CSV	no check vector for non-removable disc
	DW	ALVSD		;ALV	address of allocation vector
;
;
END
