
; Test Program to interact with the CPM3 type BIOS for the S100Computers IDE/CF card and FPGA_DC + FDC board
; John Monahan San Ramon CA 94583.  
;==============================================================================
;
;	V1.7	3/1/2010	;Removed Z80 Code (so it can be translated to 8086 code later)
;	V2.0	1/23/2011	;Updated to accomidate two CF cards (Master/Slave) & better menu options
;				;Note I still have more work to do with this but what is here seems OK.
;	V2.1	2/5/2011	;Menu driven, and added code to copy & restore disk data from another
;				;"backup" partition on disk
;	V2.2	2/13/2011	;Added Sec++ & Sec--
;	V2.3	2/15/2011	;Re-did drive initilization (Pulse CF cards twice on reset line)
;	V2.4	2/16/2011	;Correct small error for end of drive track check
;	V2.5	3/14/2011	;Added BOOT CPM option, cleaned up some areas.
;	V2.6	3/15/2011	;Re-dis reset line pulse. Correct CPM boot to Track 0 sector 1
;	V2.7	4/26/2011	;Add code for two drive system	
;	V2.8	4/27/2011	;Format sectors with E5's and warn "formatting CURRENT drive".
;	V2.9	3/28/2011	;Fixed initilization hanging if no drive present in drive #0 or #1 positions
;	V2.91	12/23/2017	;Fixed (double shifting) error in ZBITS
;	V3.00	5/31/2019	;Moved stack before buffers, so that V and X commands work properly
;				;Fix issue in verify:  ANA => ORA in VERIFY$AB: at NEXTV:
;				;Fix issue in RAM Clear:  ANA => ORA, and clear A each time
;				;Changed drive selection code into subroutines
;				;Moved call to CLEAR$ID$BUFFER into routine driveid
;				;Display drive letters as they are initialized
;				;Display parameter info for both drives, if present (abort if no drive 0)
;				;Made max sector a stored variable, and treated as max "CPM" sector
;				;Fixed issue in read next sector ("I")  where condition code not set 
;				;Fixed issue where operations stopped one track short (after FE, rather than FF)
;				;Fixed issue where an invalid command char. took an unpredictable flying leap
;				;Added Hole/No Hole mode, and display mode
;				;Added ability to set the maximum track, and display current value
;				;Added report of LBA support in DriveID info printout
;				;Added check for busy in IDEInit - CF cards were not going into LBA mode
;				;Changed BOOTCPM to work properly in no hole mode.
;				;Added / moved checks for IDEWaitnotbusy into wrlba
;	V3.1	2/19/2021	;Whole Disk copy 0FFH sectors/track (0FFH Tracks).  Can set Sec/Track dynamically, Sect# start at 0 not 1
;	V3.11	3/5/2021	;Corrected 1st sector message (O CMD)			
;	V4.0	4/8/2021	;Converted menu etc. to be similar to MYSD.ASM
;
;	V4.3	5/16/2012	;Completely rearranged to work the FPGA_DC Boards (and the old Dual IDE board)
;	V5.0	5/31/2021	;Completely upgraded for FPGA_DC Board
;	V5.1    8/1/2021	;Split program into an IDE & FDC specific program
;	V6.1	8/15/2021	;Added 2.5" Drive table
;	V6.2	9/27/2021	;Fixed Startup device configuration
;	V6.3    10/2/2021	:Fixec CPM Console Interface
;	V6.4	10/11/2021	;Improved Disk Format menues
;
;
;	Ports for 8255 chip. Change these to specify where your 8255 is addressed,
;	The first three control which 8255 ports have the control signals,
;	upper and lower data bytes.  The last one (IDEportCtrl), is for mode setting for the
;	8255 to configure its actual I/O ports (A,B & C).  
;
;	Note most drives these days dont use the old Head,Track, Sector terminology. Instead
;	we use "Logical Block Addressing" or LBA. This is what we use below. LBA treats the drive
;	as one continous set of sectors, 0,1,2,3,... 3124,....etc.  However as seen below we need to 
;	convert this LBA to heads,tracks and sectors to be compatible with CPM & MSDOS.

;	NOTE: If you have only one drive/CF card, be sure it is in drive A: The IDE hardware gets 
;	confused if there is only a drive in slot B:

					;Equates for display on Propeller Console IO Board (Used In CPM Debugging mode only)
SCROLL		EQU	01H		;Set scrool direction UP.
LF		EQU	0AH
CR		EQU	0DH
BS		EQU	08H		;Back space (required for sector display)
BELL		EQU	07H
SPACE		EQU	20H
FAST		EQU	10H		;High speed scrool
TAB		EQU	09H		;TAB ACROSS (8 SPACES FOR SD Systems Video Board)
ESC		EQU	1BH
CLEAR		EQU	1CH		;<<< Propeller Video Board, Clear to EOL. (Use 80 spaces if EOL not available

FALSE	EQU	0
TRUE	EQU	NOT FALSE

CPM		EQU	FALSE		;TRUE if output via CPM, FALSE if direct to hardware
DEBUG		EQU	TRUE		;TRUE Show detailed Sector R/W error codes
RANGE$CHECK	EQU	FALSE		;True if you need to check you have a valid sector #. (Skip for CPM DS Disks)



MAX$TRACK$SIZE	EQU	 3000H		;Maximum number of bytes there will be on a track. Used for formatting a disk 
MAX$SEC$SIZE	EQU	 1000H		;Maximum number of bytes there will be in a sector


STATUS$BUS$PORT		EQU	80H	;CMD Communications port with Z80 on FPGA_DC Board
DATA$BUS$PORT		EQU	81H	;CMD data is sent via this port
RELEASE$ERROR$PORT	EQU	82H	;A pulse out to this port will reset the Sertor R/W Error flag on the FPGA Z80
REBOOT$PORT		EQU	83H	;Outputting anything to this port reboots the Z80 on the FPGA_DC Board
ABORT$CMD$PORT		EQU	84H	;Outputting 80H to port 84H will flag the FPGA to abort a currently running CMD

;-------------------------------------- IX OFFSET EQUATES for Disk Tables  -------------------------------------
;
;			
; EQUATES FOR [IX] REGISTER OFFSETS INTO DISK FORMAT PARAMATER TABLES
; Each of the many disk formats have their own table with things like sector size, tracks/disk, sectors/track etc. 
; You can add more.  (Noter this table is similar but slightly different from the one used with the the ZFDC Board).
;
DISK$TYPE		EQU	0		;0  0FFH for all IDE Drives, Different for 0FEH, 0FDH...Floppy disks
NO$DRIVE$PRESENT	EQU	1H		;1  BYTE  1 if No Card Present 
DRIVE$ADDR		EQU	2H		;2  BYTE  Byte output for Drive CS* Line
						;   Bits 0,1 are used for drive hardware selection (00=A, 01=B,10=C,11=D)
						;   Bit 2, 1 if side A is selected, 0 if Side B
						;   Bit 3, 1 if 8" disk, 0 = 5" disk 
						;   Bit 4, 1 if Single Density, 0 = Double Density
						;   Bit 5 WD2793 INTRQ  1=ON, 0=OFF
						;   Bit 6 Write protect flag 0 = ON, 1 = OFF
						;   Bit 7 Drive Head load (currently unused)
						
DRIVE$NUMBER		EQU	3H		;3  BYTE  Drive Number (0,1,2,3,4,5 for display)
INITILIZED		EQU	4H		;4  BYTE  Drive itilized flag, 0 = un-initilized
SEC$SIZE$FLAG		EQU	5H		;5  BYTE  0=128 Byte sectors, 1 = 256, 2 = 512, 4=1024 Byte sectors
SYS$TRKS		EQU	6H		;6  BYTE  How many tracks for system 
DRIVE$LETTER		EQU	7H		;7  BYTE  HEX of Drive Letter
DRIVE$ASCII		EQU	8H		;8  BYTE  ASCII character of Drive #
FIRST$SEC		EQU	9H		;9  BYTE  Number of first sector, 0 for IDE, 1 for floppies

SEC$SIZE$BYTES		EQU	0AH		;10  WORD (128,256,512 or 1024)
NSCTRS			EQU	0CH		;12  WORD  Sectors/Track +1 for this disk format
NTRKS			EQU	0EH		;14  WORD  MAX+1 Tracks/disk
TRK			EQU	10H		;16  WORD  Current Track
SEC			EQU	12H		;18  WORD  Current Sector
SIDE			EQU	14H		;20  BYTE  Floppy Side

HEADR			EQU	15H		;21  BYTE  For Formatting
GAP1			EQU	16H		;22  BYTE  	"
GAP2			EQU	17H		;23  BYTE  	"
GAP3			EQU	18H		;24  BYTE  	"
GAP4			EQU	19H		;25  BYTE  	"
GAP4R			EQU	1AH		;26  BYTE  	"
GAP$FILL$CHAR		EQU	1BH		;27  BYTE   Byte used in disk formating
DATA$FILL$CHAR		EQU	1CH		;28  BYTE      "       "       "
SPECIAL$FLAG		EQU	1DH		;29  BYTE   Flag byte for cases where after formatting Normally 0, CPM86$FLAG = 1
SEC$SKEW$TABLE		EQU	1EH		;30  WORD   Two Bytes.    Address of sector skew table  
FORMAT$NUM		EQU	20H		;32  BYTE  Each format will have a unique number in the table list below. 
TRACK$SIZE		EQU	21H		;33  WORD  Two Bytes.   (Used in formatting disk)
SIDES$NUMBER		EQU	23H		;35  BYTE  Number of sides for a floppy disk
DISK$TITLE		EQU	24H		;36  Text string of the disk format (must end with 0, total table size < 80H)


IDE$CS$1		EQU	00000000B		; CS* select bit for IDE Card drive 1 
IDE$CS$2		EQU	00000001B		; CS* select bit for IDE Card drive 2 

FL$CS$1			EQU	01100100B		; Floppy select bit for 8" SSSD Floppy drive 1, Side A, No WP  (IBM System 3740)
FL$CS$2			EQU	01100101B		; Floppy select bit for 8" SSSD Floppy drive 2, Side A, No WP (IBM System 3740)
FL$CS$3			EQU	01110100B		; Floppy select bit for 8" DSDD Floppy drive 3, Side A, No WP (IMB System 34)
FL$CS$4			EQU	01110111B		; Floppy select bit for 2.5" DSDD Floppy drive 4, Side A, No WP  (IBM_PC 1.44MB Disk)

CFCARD			EQU	0FFH			; All CF & CF Card type in IX table
IBM3740			EQU	080H			; Disk hardware type 8" SS DD 128 Byte sectors
IBM34			EQU	060H			; Disk hardware type 8" DS DD 256 byte Sectors
IBM144			EQU	040H			; Disk hardware type 2.5" DS DD 512 byte Sectors


;----------------------------------------------------------------------------------------------------------------------

;	Commands to the FPGA_DC Board:-
;	Note these commands are a sub-set of the ZFDC and ZFDC_II Board commands
;	Commands to the FPGA_DC Board:-
;	Note these commands are a sub-set of the old ZFDC and ZFDC_II Board commands

CMD$SEL$DRIVE		EQU	5H		;**** (Re)select an already initilized drive
CMD$SET$SIDE		EQU	8H		;**** This will set the active side for a floppy disk
CMD$SET$TRK$SEC		EQU	35H		;Set new current TRACK+SECTOR on current drive (new)
CMD$READ$SECTOR		EQU	10H		;**** Read data from the CURRENT sector (on current track,drive).
CMD$WRITE$SECTOR	EQU	11H		;**** Write data to the CURRENT sector (on current track,drive).
CMD$SET$IDE$MODE	EQU	38H		;Set IDE drive hardware mode on FPG_DC Board (Internal or External)
						;Second Byte 0 = External IDE mode + Interrupt driven info (Default Mode). 
						;Second Byte 1 = External IDE mode + CMD driven info
						;Second Byte 2 = Local FPGA Board IDE mode + CMD driven info
CMD$FAST$COPY$AB	EQU	39H		;Special CMD to fast copy CF Card A:->B: (All within FPGA_DC Board software)


CMD$SET$HOME		EQU	0AH		;This will set floppy disk head request to Track 0 of CURRENT drive
CMD$GET$TRACK$ID	EQU	0FH		;Read the CURRENT TRACK ID
CMD$STEP$IN		EQU	0BH		;Step head in one track of CURRENT drive
CMD$STEP$OUT		EQU	0CH		;Step head out one track of CURRENT drive
CMD$SEEK$NV		EQU	0DH		;Seek to track with NO verify of CURRENT drive
CMD$SEEK$TRACK		EQU	0EH		;Seek to track to (IY+DRIVE_TRACK) with verify bit set on CURRENT drive/format
CMD$TRACK$DUMP		EQU	15H		;Dump complete CURRENT track to S-100 system
						
INFO$SEL$DRIVE		EQU	40H		;Inform a drive select (not currently used)
INFO$POST$MSG		EQU	41H		;Post a message on the USB Port Terminal

INFO$READ$SECTOR	EQU	42H		;Send info, read sector (Actual Sec Read done externally)
INFO$WRITE$SECTOR	EQU	43H		;Send info, write sector

CMD$FORMAT$DISK		EQU	44H		;Format the disk in the of the CURRENT drive
CMD$FDC$COPY		EQU	45H		;Fast Copy Disk C:->D:

CMD$BOARD$CONFIG	EQU	52H		;Get FPGA_DC Board hardware configuration
						;Bits 7&6 contain IDE & FDC circuit flags 
						;Bits 1&0 contain IDE Mode (0,1,2) 

CMD$GET$TIME		EQU	80H		;Get Time and Data from FPGA DC Board RTC
CMD$SET$TIME		EQU	81H		;Set Time and Data on FPGA DC Board RTC

						
CMD$FAILED		EQU	0FFH		;CMD failed to exacuite completely
CMD$COMPLETE		EQU	0F0H		;Flag returned by DC board to signal the previous CMD was completed OK
CMD$ABORT		EQU	0E0H		;CMD to abort the current process

;----------------------------------------------------------------------------------------------------------------------------

EXT$IDE$MODE		EQU	00H	;MODE 0, FPGA IDE mode set to external IDE ports etc, [Intererupt driven Hex display/info] 
LOCAL$IDE$MODE		EQU	01H	;MODE 1, FPGA Local IDE CMD mode   [CMD driven Hex display/info]
EXT$IDE$INFO$MODE	EQU	02H	;MODE 2, FPGA External IDE  + Info       [CMD driven Hex display/info]


IDE$BOARD		EQU	0H	;If the disk controller board is the Dual IDE/CF card board
FPGA$BOARD		EQU	1H	;If the controller is the FPGA_DC Board

IDEportA		EQU	030H		;Lower 8 bits of IDE interface (8255)
IDEportB		EQU	031H		;Upper 8 bits of IDE interface
IDEportC		EQU	032H		;Control lines for IDE interface
IDEportCtrl		EQU	033H		;8255 configuration port
IDEDrive		EQU	034H		;Bit 0 = 0 Drive A, =1 Drive B

IDE$CS$1		EQU	00000000B	; CS* select bit for IDE Card drive 1 
IDE$CS$2		EQU	00000001B	; CS* select bit for IDE Card drive 2 

READcfg8255		EQU	10010010b	;Set 8255 IDEportC to output, IDEportA/B input
WRITEcfg8255		EQU	10000000b	;Set all three 8255 ports to output mode

;IDE control lines for use with IDEportC.  

IDEa0line		EQU	01H		;direct from 8255 to IDE interface
IDEa1line		EQU	02H		;direct from 8255 to IDE interface
IDEa2line		EQU	04H		;direct from 8255 to IDE interface
IDEcs0line		EQU	08H		;inverter between 8255 and IDE interface
IDEcs1line		EQU	10H		;inverter between 8255 and IDE interface
IDEwrline		EQU	20H		;inverter between 8255 and IDE interface
IDErdline		EQU	40H		;inverter between 8255 and IDE interface
IDErstline		EQU	80H		;inverter between 8255 and IDE interface

;Symbolic constants for the IDE Drive registers, which makes the
;code more readable than always specifying the address bits

REGdata			EQU	IDEcs0line
REGerr			EQU	IDEcs0line + IDEa0line
REGseccnt		EQU	IDEcs0line + IDEa1line
REGsector		EQU	IDEcs0line + IDEa1line + IDEa0line
REGcylinderLSB		EQU	IDEcs0line + IDEa2line
REGcylinderMSB		EQU	IDEcs0line + IDEa2line + IDEa0line
REGshd			EQU	IDEcs0line + IDEa2line + IDEa1line		;(0EH)
REGcommand		EQU	IDEcs0line + IDEa2line + IDEa1line + IDEa0line	;(0FH)
REGstatus		EQU	IDEcs0line + IDEa2line + IDEa1line + IDEa0line
REGcontrol		EQU	IDEcs1line + IDEa2line + IDEa1line
REGastatus		EQU	IDEcs1line + IDEa2line + IDEa1line + IDEa0line

;IDE Command Constants.  These should never change.

COMMANDrecal		EQU	10H
COMMANDread		EQU	20H
COMMANDwrite		EQU	30H
COMMANDinit		EQU	91H
COMMANDid		EQU	0ECH
COMMANDspindown		EQU	0E0H
COMMANDspinup		EQU	0E1H


; IDE Status Register:
;  bit 7: Busy	1=busy, 0=not busy
;  bit 6: Ready 1=ready for command, 0=not ready yet
;  bit 5: DF	1=fault occured insIDE drive
;  bit 4: DSC	1=seek complete
;  bit 3: DRQ	1=data request ready, 0=not ready to xfer yet
;  bit 2: CORR	1=correctable error occured
;  bit 1: IDX	vendor specific
;  bit 0: ERR	1=error occured

				

BUFFER$ORG		EQU	4000H		;<----- Will place all sector data here

CPM$BOOT$COUNT		EQU	12		;Allow up to 12 CPM sectors for CPMLDR
CPMLDR$ADDRESS		EQU	BUFFER$ORG	;We cannot load the CPMLDR at 100H in RAM since this is where this program resides

RDCON			EQU	1		;For CP/M I/O
WRCON			EQU	2
RESET$DISK		EQU	0DH		;Reset all CPM disks
PRINT			EQU	9
CONST			EQU	11		;CONSOLE STAT
BDOS			EQU	5


	; INCLUDE Z-80 MACRO LIBRARY:
	
	MACLIB	Z80			;For the Z80 DJNZ opcode




;--------------------------------------------------------------------------------------------
	ORG	100H			;<--- For CPM

START:	LXI	SP,STACK

IF CPM
	LXI     D,SIGN$ON$CPM		;print a welcome message CPM IO
ELSE
 	LXI     D,SIGN$ON$Z80		;print a welcome message Z80 monitor IO
ENDIF	

	CALL	PSTRING
	
	IN	STATUS$BUS$PORT		;(80H) If FPGA_DC is active this will be X000000X
	CPI	0FFH
	JNZ	GOT$RESPONSE

	LXI	D,OLD$IDE$BOARD$MSG	;Dual IDE Board only
	CALL	PSTRING
	MVI	A,EXT$IDE$MODE		;MODE 0, for old dual IDE board
	STA	@CURRENT$IDE$MODE
	XRA	A
	STA	@BOARD$TYPE		;0 for dual IDE Board >>>
	JP	ABORT
	
GOT$RESPONSE:
	MVI	A,1
	STA	@BOARD$TYPE		;<<<< 1 for FPGA_DC Board >>>

;	OUT	REBOOT$PORT		;Just to be safer reboot the ZFDC_DC Z80 CPU
	LXI	D,FPGA$BOARD$MSG	;The FPGA_DC Board was detected.
	CALL	PSTRING
	
	MVI	A,CMD$BOARD$CONFIG	;Get the current FPGA_DC Board configuration
	CALL	DATA$TO$FPGA
	
	CALL	GET$FPGA$TO$S100	;Wait for returned signal 

	STA	@CURRENT$BOARD$HARDEWARE ;10XXXXXX = IDE, 01XXXXXX = FDC, 11XXXXXX +IDE+FDC
	
	ANI	11000000B
	CPI	11000000B
	JZ	BOTH$CIRCUITS
	CPI	10000000B
	JZ	IDE$CIRCUIT
FDC$CIRCUIT:
	LXI	D,FDC$CIRCUIT$MSG	;FDC Board only
	CALL	PSTRING
	JR	OVER$CIRCUITS
IDE$CIRCUIT:
	LXI	D,IDE$CIRCUIT$MSG	;IDE Board only
	CALL	PSTRING
	JR	OVER$CIRCUITS
BOTH$CIRCUITS:
	LXI	D,BOTH$CIRCUITS$MSG	;IDE + FDC Board only
	CALL	PSTRING

OVER$CIRCUITS:
	MVI	A,CMD$SET$IDE$MODE	;38H set IDE to External mode 
	CALL	DATA$TO$FPGA
	
;	MVI	A,EXT$IDE$MODE		;0H, Select External IDE FPGA circuit for drive A: or B: access, Interrupt driven
	MVI	A,EXT$IDE$INFO$MODE	;02H, FPGA External IDE + Info [CMD driven Hex display/info only]
;	MVI	A,LOCAL$IDE$MODE	;01H, FPGA Local IDE CMD mode   [CMD driven IDE Sec R/W (+ Hex display/info on IDE only Board))
	STA	@CURRENT$IDE$MODE	;Store in RAM

	CALL	DATA$TO$FPGA
;	MVI	A,EXT$IDE$MODE		;0H, Select External IDE FPGA circuit for drive A: or B: access, Interrupt driven
	MVI	A,EXT$IDE$INFO$MODE	;02H, FPGA External IDE + Info [CMD driven Hex display/info only]
;	MVI	A,LOCAL$IDE$MODE	;01H, FPGA Local IDE CMD mode   [CMD driven IDE Sec R/W (+ Hex display/info on IDE only Board))



					;--------------- Actual start of menu commands ------------------------------
BEGIN:	CALL	ZCRLF
	LXI	H,0
	SHLD	@TRK			;Start with Track 0,sec 0
	XRA	A
	INR	A
	STA	@SEC			;Sectors are 1,2,3...
	STA	@SIDE			;Side A
	
	MVI	B,'C'			;Start with C drive
	CALL	SELECT$FDC$DRIVE	
	JZ	MAINLOOP		;And continue

NO$C$DRIVE:
	LXI	D,INIT$1$ERROR	
	CALL	PSTRING
	JMP	ABORT

ABORT:	MVI	B,'C'			;Start with C drive
	CALL	SELECT$FDC$DRIVE	
IF CPM
	MVI	C,RESET$DISK		;Reset All disks in CPM
	CALL	BDOS		
	JMP	0H			;Jump to CP/M cold start address
ELSE
	JMP	0F000H			;Else jump to monitor (note will not work if CPM3 is Banked)	
ENDIF
 

ERROR:	LXI     D, msgErr		;CMD error msg
	CALL	PSTRING
	JMP	MAINLOOP
	
					;COMMAND BRANCH TABLE
TBL$IDE:DW  ERROR			; "A"  
	DW  SHOW$BUFFER			; "B"  Show buffer
	DW  COPY$SECTOR			; "C"  Copy a sector
	DW  SELECT$DISK			; "D"  Select a new disk
	DW  ERROR			; "E"  
	DW  FILL$SECTOR			; "F"  Fill a sector with a value
	DW  DISPLAY$TRACK		; "G"  Display a complete track
	DW  STEP$IN			; "H"  Step Head in one Track
	DW  DISPLAY$TRACK		; "I"  Read a complete Track
	DW  FORMAT$DISK			; "J"  Format current Disk
	DW  CPMBOOT			; "K"  LOAD CPM (If present) from A:
	DW  GET$TIME$DATE		; "L"  Get Time and Date from FPGA RTC  
	DW  COPY$DISK			; "M"  Copy C:->D:
	DW  GET$NEXT$SEC		; "N"  Next Sector
	DW  STEP$OUT			; "O"  Step Head out one Track
	DW  GET$PREV$SEC		; "P"  Previous sector
	DW  ERROR			; "Q"  
	DW  SEQ$RD			; "R"  Read sector(s) to data buffer
	DW  SET$DISK$SIDE 		; "S"  Set Current disk side
	DW  DO$SET$LBA			; "T"  Set LBA value (Set "CPM" Track,sector)
	DW  SET$TIME$DATE		; "U"  Reset RTC and update to a new Time & Date
	DW  VERIFY$SECTOR		; "V"  Verify current sector with another
	DW  SEQ$WR			; "W"  Write data buffer to current sector
	DW  RESTORE$DISK		; "X"  Head to Track 0
	DW  GET$TRACK$ID		; "Y"  Get Track ID
	DW  REBOOT$PORT			; "Z"  Reboot FPGA_DC Board


;-------------------------- MAIN LOOP ------------------------------------------------------------

MAINLOOP:				;print main menu
	LXI	D,MENU$STRING$1		;FDC menu
	CALL	PSTRING
	LXI	H,TBL$IDE		;Get IDE Menu selection

	CALL	FDC$PRINT$LBA		;Display current Track,sector,head#

OVER$IDE$MENU:
	LXI	D,Prompt		;Please Enter a CMD >
	CALL	PSTRING

	OUT	RELEASE$ERROR$PORT	;Clear any previous any abort CMD flag
	
					;----------------------------------------------------
	CALL	GETCMD			;Simple UC character Input (Note, no fancy checking)
	CPI	ESC			;Abort if ESC
	JZ	ABORT

	CALL	upper
	CPI	'+'			;Allow + or - instead of N or P
	JNZ	NOT$PLUS
	MVI	A,'N'
	JP	OVER$PLUS
NOT$PLUS:
	CPI	'-'
	JNZ	OVER$PLUS
	MVI	A,'P'
OVER$PLUS:		
	CPI	'A'			;Must be >= 'A" (Otherwise it jumps off table)
	JC	ERROR
	CPI	'Z'+1			;Must be <= 'Z'
	JNC	ERROR
	CALL	ZCRLF
	
	SBI	'@'			;Adjust to 0,1AH
	
	LXI	H,TBL$IDE		;Get IDE Menu selection
	ADD	A			;X2
	ADD	L
	MOV	L,A
	MOV	A,M
	INX	H
	MOV	H,M
	MOV	L,A			;Jump to table pointer
	PCHL				;JMP (HL)

	

;----------------------------- SELECT CARD/DISK SECTOR ------------------------------------------------------	

SELECT$DISK:	
	LXI	D,CURRENT$DR$MSG	;Select Drive(C,D,E or F)
	CALL	PSTRING
	CALL	GETCMD			;Simple UC character Input (Note, no fancy checking)
	CPI	ESC			;Abort if ESC
	JZ	ABORT
	CALL	UPPER

RESELECT$DRIVE:				;Reselect drive in [A]
	MOV	B,A			;Store in B
	CPI	'C'
	JZ	SELECT$FDC$DISK
	CPI	'D'
	JZ	SELECT$FDC$DISK
	CPI	'E'
	JZ	SELECT$FDC$DISK
	CPI	'F'
	JZ	SELECT$FDC$DISK
	JMP	BAD$SEL$DRIVE

SELECT$FDC$DISK:			; Select a Card/Disk in [B]	
	CALL	SELECT$FDC$DRIVE
	JZ	MAINLOOP
BAD$SEL$DRIVE:
	LXI	D,BAD$SEL$DR$MSG
	CALL	PSTRING
	JMP	MAINLOOP



;----------------------------- SELECT CARD/DISK SECTOR ------------------------------------------------------	

RESTORE$DISK:
	LXI	D,HOME$DR$MSG		;Move Disk head to track 0
	CALL	PSTRING

	MVI	A,CMD$SET$HOME		;0AH, this will set floppy disk head request to Track 0 of CURRENT drive
	CALL	DATA$TO$FPGA

	XRA	A
	STA	@TRK			;Update Track
	CALL	GET$FPGA$TO$S100	;Get CMD$CPMPLETE/ERROR FLAG
	CPI	CMD$COMPLETE		;0F0H, Flag returned by DC board to signal the previous CMD was completed OK
	JZ	MAINLOOP
	
	LXI	D,BAD$RESTORE$MSG
	CALL	PSTRING
	JMP	MAINLOOP



;----------------------------- GET CURRENT TRACK ID ------------------------------------------------------	

GET$TRACK$ID:
	LXI	D,TRK$ID$MSG		;'Track ID =     $'
	CALL	PSTRING

	MVI	A,CMD$GET$TRACK$ID	;0FH, Get floppy disk current tarck ID
	CALL	DATA$TO$FPGA

	CALL	GET$FPGA$TO$S100	;Get Byte data
	CALL	HEXOUT
	STA	@TRK			;Update Track
	CALL	GET$FPGA$TO$S100	;Get Byte data
	CALL	HEXOUT
	CALL	GET$FPGA$TO$S100	;Get Byte data
	CALL	HEXOUT
	CALL	GET$FPGA$TO$S100	;Get Byte data
	CALL	HEXOUT
	CALL	GET$FPGA$TO$S100	;Get Byte data
	CALL	HEXOUT
	CALL	GET$FPGA$TO$S100	;Get Byte data
	CALL	HEXOUT

	CALL	GET$FPGA$TO$S100	;Get CMD$CPMPLETE/ERROR FLAG
	CPI	CMD$COMPLETE		;0F0H, Flag returned by DC board to signal the previous CMD was completed OK
	JZ	MAINLOOP
	
	LXI	D,BAD$TRK$ID$MSG
	CALL	PSTRING
	JMP	MAINLOOP

;----------------------------- STEP IN  ------------------------------------------------------

STEP$IN:
	LXI	D,STEP$IN$MSG		;'Step head in one Track $'
	CALL	PSTRING
	
	MVI	A,CMD$STEP$IN		;0BH	
	CALL	DATA$TO$FPGA 
	
	CALL	GET$FPGA$TO$S100	;Get data in [A] back to S100 
	STA	(@TRK)			;Store updated track
	CALL	GET$FPGA$TO$S100	;Get CMD$CPMPLETE (No error flag returned)
	CPI	CMD$COMPLETE		;0F0H, Flag returned by DC board to signal the previous CMD was completed OK
	JZ	MAINLOOP
	LXI	D,STEP$IN$ERR		;'Step head in Error $'
	CALL	PSTRING
	JMP	MAINLOOP

;----------------------------- STEP OUT ------------------------------------------------------

STEP$OUT:
	LXI	D,STEP$OUT$MSG		;'Step head out one Track $'
	CALL	PSTRING
	
	MVI	A,CMD$STEP$OUT		;0CH	
	CALL	DATA$TO$FPGA 

	CALL	GET$FPGA$TO$S100	;Get data in [A] back to S100 
	STA	(@TRK)			;Store updated track
	CALL	GET$FPGA$TO$S100	;Get CMD$CPMPLETE (No error flag returned)
	CPI	CMD$COMPLETE		;0F0H, Flag returned by DC board to signal the previous CMD was completed OK
	JZ	MAINLOOP
	LXI	D,STEP$OUT$ERR		;'Step head out Error $'
	CALL	PSTRING
	JMP	MAINLOOP
	
	
;----------------------------- SEQ READ CF CARD SECTORS ------------------------------------------------------
	
SEQ$RD:					;Do sequential reads
	LXI	H,buffer		;Point to buffer
	SHLD	@DMA

	CALL	READ$FDC$SECTOR
	JNZ	SHOW$SECTOR$READ$ERROR
	
SEQ$READ$OK:	
	LXI     D,msgrd			;Sector read OK
	CALL	PSTRING
	
	LXI	H,buffer		;Point to buffer. Show sector data flag is on
	SHLD	@DMA
	CALL	HEXDUMP			;Show sector data
	CALL	FDC$PRINT$LBA
	CALL	ZCRLF
	
	LXI	D,CONTINUE$MSG		;"Hit keyboard for next sector. ESC to return to menu$ '
	CALL	PSTRING

	CALL	GETCMD			;Simple UC character Input (Note, no fancy checking)
	CPI	ESC			;Abort if ESC
	JZ	MAINLOOP
	CALL	SEC$BUMP		;Call GET SEC$BUMPOR
	JMP	SEQ$RD

SHOW$SECTOR$READ$ERROR:
	LXI	D,SR$ERR$MSG		;'Sector READ error. TRK,SEC = $'
	CALL	PSTRING
	LDA	@TRK			;TRK = (8 bits)
	CALL	HEXOUT
	MVI	C,','
	CALL	ZCO
	LDA	@SEC
	CALL	HEXOUT			;XX,XX
	CALL	ZCRLF
	JMP	MAINLOOP

;----------------------------- WRITE TO A SECTOR FROM RAM ------------------------------------------------------	

SEQ$WR:					;Write data in RAM buffer to sector @ LBA
	LXI	D,RAM$DATA$MSG		;Write dara from a RAM location to the current Track/Sector(s)$'
	CALL	PSTRING
	
	LXI	D,WR$RAM$MENU$MSG	;From RAM at:- (XXXXH):$'
	CALL	PSTRING

	CALL	GET$HL$HEX		;Get RAM in HL
	JC	MAINLOOP

	SHLD	@DMA			;Point to buffer
	SHLD	@DMA$STORE		;Start Buffer DMA
	
	LXI	D,msgsure		;Are you sure?
	call	P$STRING
	call	ZCI
	call	upper
IF CPM 
ELSE
	PUSH	PSW
	PUSH	B
	MOV	C,A			;Print response
	CALL	ZCO
	POP	B
	POP	PSW
ENDIF
	CPI	'Y'
	JNZ	MAINLOOP
	
NEXT$SEQ$WR:
	CALL	ZCRLF

	LHLD	@DMA
	SHLD	@DMA$STORE		;Store for next display below

	CALL	WRITE$FDC$SECTOR	;Write to the current disk Sector
	JZ	WRITE$OK		;Z means the sector read was OK

	CALL	SHOW$SECTOR$WRITE$ERROR
	CALL	ZCRLF
	JMP	MAINLOOP

WRITE$OK:
	SHLD	@DMA			;Store for next time
	LXI     D,msgwr			;Sector written OK
	CALL	PSTRING
	
	LHLD	@DMA$STORE
	CALL	HEXDUMP			;Show sector data
	CALL	FDC$PRINT$LBA
	CALL	ZCRLF
	
	LXI	D,CONTINUE$MSG		;"Hit keyboard for next sector. ESC to return to menu$ '
	CALL	PSTRING

	CALL	GETCMD			;Simple UC character Input (Note, no fancy checking)
	CPI	ESC			;Abort if ESC
	JZ	MAINLOOP
	CALL	SEC$BUMP		;Call GET SECTOR
	JMP	NEXT$SEQ$WR



;----------------------------- FILL A SECTOR WITH A BYTE VALUE ------------------------------------------------------	

FILL$SECTOR:
	LXI	D,FILL$DATA$MSG		;Fill  the current Track/Sector(s) with a byte value$'
	call	PSTRING
	
	call	GETHEX
	JC	MAINLOOP

	MOV	B,A			;Save the value
	PUSH	B
	LXI	D,msgsure		;Are you sure?
	call	P$STRING
	
	call	ZCI
	call	upper
IF CPM 
ELSE
	PUSH	PSW
	PUSH	B
	MOV	C,A			;Print response
	CALL	ZCO
	POP	B
	POP	PSW
ENDIF
	POP	B
	CPI	'Y'
	JNZ	MAINLOOP

	MOV	A,B
	LXI	H,buffer		;Point to buffer.
	LXI	B,MAX$SEC$SIZE	
	
SEC$FILL:
	MOV	M,A			;Fill the whole Buffer area with the byte value
	INX	H
	DCR	C
	JNZ	SEC$FILL
	DCR	B
	JNZ	SEC$FILL		;Do 4K, (should be overkill)!

	LXI	H,buffer		;Point to buffer. Show sector data flag is on
	SHLD	@DMA			
	
	CALL	WRITE$FDC$SECTOR	;Write to the current disk Sector
	JZ	FILL$OK			;Z means the sector write was OK

	CALL	SHOW$SECTOR$WRITE$ERROR
	CALL	ZCRLF
	JMP	MAINLOOP

FILL$OK:
	LXI	D,FILL$DATA$OK		;Sector Write complete$'
	CALL	PSTRING
	JMP	MAINLOOP


;----------------------------- COPY A SECTOR ------------------------------------------------------	

COPY$SECTOR:
	LXI	D,COPY$SEC$MSG		;Will copy current Sector to another sector
	CALL	PSTRING
	
	LDA	@TRK
	STA	@TRK1
	LDA	@SEC
	STA	@SEC1
	
	LXI	D,LBA$FORMAT		;'Enter new Track,Sector as XX,XX (+CR):$'
	CALL	PSTRING
	CALL	SET$LBA			;Call the generalized routine
	JNZ	MAINLOOP
	
	LDA	@TRK
	STA	@TRK2
	LDA	@SEC
	STA	@SEC2

	LDA	@TRK1
	STA	@TRK
	LDA	@SEC1
	STA	@SEC

	LXI	H,buffer		;Point to buffer
	SHLD	@DMA

	CALL	READ$FDC$SECTOR
	JNZ	SHOW$SECTOR$READ$ERROR
	
	LDA	@TRK2
	STA	@TRK
	LDA	@SEC2
	STA	@SEC
	LXI	H,buffer		;Point to buffer. Show sector data flag is on
	SHLD	@DMA

	CALL	WRITE$FDC$SECTOR	;Write to the new disk Sector
	JZ	COPY$OK			;Z means the sector read was OK

	CALL	SHOW$SECTOR$WRITE$ERROR
	CALL	ZCRLF
	JMP	MAINLOOP
	
COPY$OK:
	LXI	D,COPY$OK$MSG		;Sector copied OK
	CALL	PSTRING
	JMP	MAINLOOP
	

;----------------------------- VERIFT CURRENT SECTOR WITH ANOTHER --------------------------------------------------	

VERIFY$SECTOR:
	LXI	D,VERIFY$SEC$MSG	;Will copy current Sector to another sector
	CALL	PSTRING
	
	LDA	@TRK
	STA	@TRK1
	LDA	@SEC
	STA	@SEC1
	
	LXI	D,SECOND$SEC		;'Enter Track,Sector info. for the second Sector as (XX,XX): $'
	CALL	PSTRING
	CALL	SET$LBA			;Call the generalized routine
	JNZ	MAINLOOP
	
	LDA	@TRK
	STA	@TRK2
	LDA	@SEC
	STA	@SEC2

	LDA	@TRK1
	STA	@TRK
	LDA	@SEC1
	STA	@SEC

	LXI	H,buffer		;Point to buffer
	SHLD	@DMA

	CALL	READ$FDC$SECTOR
	JNZ	SHOW$SECTOR$READ$ERROR

	LXI	H,buffer		;Point to buffer
	SHLD	@DMA
	CALL	HEXDUMP			;Show sector data
	
	LDA	@TRK2
	STA	@TRK
	LDA	@SEC2
	STA	@SEC
	LXI	H,buffer2		;Point to buffer. Show sector data flag is on
	SHLD	@DMA

	CALL	READ$FDC$SECTOR
	JNZ	SHOW$SECTOR$READ$ERROR

	LXI	H,buffer2		;Point to buffer
	SHLD	@DMA
	CALL	HEXDUMP			;Show sector data

	CALL	COMPARE$BUFFERS		;<<<CHECK THEY ARE THE SAME
	JNZ	MATCH$ERR
	
	LXI	D,SAME$SEC$MSG		;The two sectors are the same
	CALL	PSTRING
MATCH$ERR:
	LXI	H,buffer		;Point to buffer. Show sector data flag is on
	SHLD	@DMA
	JMP	MAINLOOP
	
	
COMPARE$BUFFERS:
	LXI	H,0
	SHLD	@SEC$POSITION
	LXI	H,buffer		;First Sector buffer
	LXI	D,buffer2		;Second sector buffer
	LDX	B,SEC$SIZE$BYTES+1	;Get sector size in bytes
	LDX	C,SEC$SIZE$BYTES
	PUSH	BC			;Save it
COMPARE1:
	MOV	B,M
	LDAX	D
	CMP	B
	JNZ	SEC$MISMATCH
	INX	H
	INX	D

	PUSH	H
	LHLD	@SEC$POSITION
	INX	HL			;Update sector pointer
	SHLD	@SEC$POSITION
	POP	H
	
	POP	B
	DCX	B			;Do all (usually 512 bytes or 128)
	MOV	A,C
	ORA	B
	PUSH	B
	JZ	COMPARE2
	JMP	COMPARE1
COMPARE2:
	POP	B			;Balance up stack
	XRA	A
	RET

SEC$MISMATCH:
	LXI	D,SEC$MISMATCH$MSG	;Sectors do NOT match starting at position:-
	CALL	PSTRING
	POP	B			;Balance up stack
	LHLD	@SEC$POSITION		;Get current pointer
	CALL	PRINT$HL		;Show position in HL
	MVI	C,'H'
	CALL	ZCO
	XRA	A
	DCR	A
	RET	
	
;----------------------------- SET DISK SIDE ------------------------------------------------------	

SET$DISK$SIDE:				; "G"  Set Current disk side	
	LXI	D,SIDE$MSG		;Enter Side of current Disk (A,B):
	CALL	PSTRING

	CALL	ZCI			;Get character and echo
	CPI	ESC			;ESC back to main menu
	JZ	MAINLOOP	
	CALL	UPPER 
IF CPM 
ELSE
	PUSH	PSW
	PUSH	B
	MOV	C,A			;Print response
	CALL	ZCO
	POP	B
	POP	PSW
ENDIF
	CALL	ZCRLF
	CPI	'B'
	JZ	DO$B$SIDE
	MVI	A,1
	STX	A,SIDE
	STA	@SIDE			;1 = a side
	
	MVI	A,CMD$SET$SIDE		;This will set the active side for a floppy disk
	CALL	DATA$TO$FPGA
	MVI	A,1
	CALL	DATA$TO$FPGA

	CALL	GET$FPGA$TO$S100	;Wait for the CMD$CPMPLETE/ERROR FLAG
	CPI	CMD$COMPLETE		;0F0H, Flag returned by DC board to signal the previous CMD was completed OK
	JNZ	SIDE$ERROR
	LXI	D,ACTIVE0$SIDE$MSG	;The Active Floppy disk side is now side A
	CALL	PSTRING
	JP	MAINLOOP
	
DO$B$SIDE:	
	MVI	A,0
	STX	A,SIDE
	STA	@SIDE

	MVI	A,CMD$SET$SIDE		;This will set the active side for a floppy disk
	CALL	DATA$TO$FPGA
	MVI	A,0
	CALL	DATA$TO$FPGA

	CALL	GET$FPGA$TO$S100	;Wait for the CMD$CPMPLETE/ERROR FLAG
	CPI	CMD$COMPLETE		;0F0H, Flag returned by DC board to signal the previous CMD was completed OK
	JNZ	SIDE$ERROR
	LXI	D,ACTIVE1$SIDE$MSG	;The Active Floppy disk side is now side B
	CALL	PSTRING
	JP	MAINLOOP

SIDE$ERROR:
	LXI	D,SIDE$ERR$MSG		;FPGA_DC Board failed to set the floppy disk active side
	CALL	PSTRING
	JP	MAINLOOP



;----------------------------- SHOW CONTENTS OF CURRENT SECTOR BUFFER ------------------------------------------------------	

SHOW$BUFFER:
	CALL	HEXDUMP			;Show sector data
	CALL	FDC$PRINT$LBA
	CALL	ZCRLF
	JMP	MAINLOOP



;----------------------------- SET LBA ------------------------------------------------------	

DO$SET$LBA:				;Set the logical block address
	LXI	D,LBA$FORMAT		;'Enter new Track,Sector as XX,XX (+CR):$'
	CALL	PSTRING
	CALL	SET$LBA			;Call the generalized routine
	JMP	MAINLOOP


;----------------------------- FORMAT DISK ------------------------------------------------------	

FORMAT$DISK:	
	LXI     D,msgsure		;Are you sure
	CALL	PSTRING
	CALL	ZCI
	CALL	upper
IF CPM 
ELSE
	PUSH	PSW
	PUSH	B
	MOV	C,A			;Print response
	CALL	ZCO
	POP	B
	POP	PSW
ENDIF
	CALL	ZCRLF
	CPI	'Y'
	JNZ	MAINLOOP
	
	LDX	A,DRIVE$ASCII			;Bytes/sector  (128,256 for 8" IBM Disk or 512 for 1.44MB disk)
	CPI	'C'
	JZ	IS$8$IBM
	CPI	'D'
	JZ	IS$8$IBM
	CPI	'E'
	JZ	IS$34$IBM
	CPI	'F'
	JZ	IS$144$IBM
	
IS$8$IBM:
	LXI	D,FORMAT$3740$MSG		;Format a 8" IBM SSSD Disk or DSSD Disk
	CALL	PSTRING
	CALL	ZCI
	CALL	upper
IF CPM 
ELSE
	PUSH	PSW
	PUSH	B
	MOV	C,A			;Print response
	CALL	ZCO
	POP	B
	POP	PSW
ENDIF
	CALL	ZCRLF
	CPI	'1'
	JZ	FORMAT$1
	CPI	'2'
	JZ	FORMAT$2
	JMP	ERROR

IS$34$IBM	
	LXI	D,FORMAT$34$MSG			;Will Format as 8" DD, DS, 26 X 256
	CALL	PSTRING
	JP	FORMAT$SYS34

IS$144$IBM:
	LXI	D,FORMAT$144$MSG		;Will Format as 3.5" DD, DS, 18 X 512
	CALL	PSTRING
	JZ	FORMAT$144

FORMAT$1:
	MVI	A,1
	STA	@DISK$FORMAT
	JMP	GOT$FORMAT
	
FORMAT$2:
	MVI	A,2
	STA	@DISK$FORMAT
	JMP	GOT$FORMAT

FORMAT$SYS34:
	MVI	A,3
	STA	@DISK$FORMAT
	JMP	GOT$FORMAT
	
FORMAT$144:
	MVI	A,4			;Format a 2.25" IBM DSDD Disk
	STA	@DISK$FORMAT
	JMP	GOT$FORMAT

GOT$FORMAT:
	MVI	A,CMD$FORMAT$DISK	;44H, Format the current Track of the CURRENT drive
	CALL	DATA$TO$FPGA
	 
	CALL	DRIVE$DELAY		;Absolutly critical the disk is up to speed. 
					;If not Track 0, Sec 1 and/or Sec 2 is not written correctly.
					;Took two days to figure this out!
	LDA	@DISK$FORMAT		;After a delay send disk type (Currently only 1, 2 3 or 4)
	CALL	DATA$TO$FPGA


BEGIN$FORMAT:
	IN	STATUS$BUS$PORT		;Get S100 Status Port - Bit 0, 1 = FPGA data present, 0, no data present
	ANI	01H			;01H, Bit 0
	JZ	BEGIN$FORMAT		;wait for DC Board to present data 

	CALL	GET$FPGA$TO$S100	;Wait for the CMD$CPMPLETE/ERROR FLAG
	CPI	CMD$COMPLETE		;0F0H, Flag returned by DC board to signal the previous CMD was completed OK
	JNZ	FORMAT$ERROR

	LXI	D,FormatDone		;Disk format complete
	CALL	PSTRING
	JMP	MAINLOOP

FORMAT$ERROR:
	LXI	D,FORMAT$ERR$MSG	;Error writing Track data for a disk format
	CALL	PSTRING
	OUT	REBOOT$PORT		;Anything out to this port (83H), will reboot the FPGA_DC Board 
	JMP	MAINLOOP
	
DRIVE$DELAY:				;About a 1/2 Sec  delay to allow the disk to get up to full speed
	LXI	H,0			;on drives tha have motor on/off controls
	MVI	B,6
DELAY1:	DCX	H
	MOV	A,L
	ORA	H
	JNZ	DELAY1
	DJNZ	DELAY1
	RET

;----------------------------- READ A COMPLETE TRACK ------------------------------------------------------	

DISPLAY$TRACK:
	LXI	D,TRACK$MSG		;"Displaying the complete contents of Track: $"
	CALL	PSTRING
	LDA	(@TRK)
	CALL	HHEXOUT
	
	MVI	A,CMD$TRACK$DUMP	;Routine assumes required Drive is already selected on ZFDC board
	CALL	DATA$TO$FPGA

	LXI	H,buffer		;Point to buffer.
	LXI	B,MAX$TRACK$SIZE	
	XRA	A
	
TRK$FILL:
	MOV	M,A			;Fill the whole Buffer area with "blank" bytes
	INX	H
	DCR	C
	JNZ	TRK$FILL
	DCR	B
	JNZ	TRK$FILL		;Do 4K, (should be overkill)!

	LXI	H,buffer		;Point to buffer. Show sector data flag is on
	LXI	D,MAX$TRACK$SIZE	

RTD$DATA:
	CALL	GET$FPGA$TO$S100	;Get Byte data
	MOV	M,A
	INX	H
	DCX	D
	MOV	A,E
	ORA	D
	JNZ     RTD$DATA
	
	CALL	GET$FPGA$TO$S100	;Wait for the CMD$CPMPLETE/ERROR FLAG
	CPI	CMD$COMPLETE		;0F0H, Flag returned by DC board to signal the previous CMD was completed OK
	JNZ	TRACK$ERROR

	LXI	H,buffer		;Point to buffer. Show sector data flag is on
 READ$TRACK$DATA:
	LHLD	@DMA
	CALL	DUMP$TRACK		;Show Track data
	SHLD	@DMA
	CALL	ZCRLF
	
	LXI	D,CONTINUE$MSG		;"To Abort enter ESC. Any other key to continue$ '
	CALL	PSTRING

	CALL	GETCMD			;Simple UC character Input (Note, no fancy checking)
	CPI	ESC			;Abort if ESC
	JZ	MAINLOOP
	
	LXI	BC,512
	LHLD	@DMA
	DAD	B
	SHLD	@DMA
	JMP	READ$TRACK$DATA

TRACK$ERROR:
	LXI	D,TRACK$ERR$MSG		;Error writing Track data for a disk format
	CALL	PSTRING
	JMP	MAINLOOP



DUMP$TRACK:
	PUSH	PSW		;Note this code is currently hard wired to either 128 of 512 byte sectors
	PUSH	B
	PUSH	D			 
	PUSH	H

	MVI	D,32		;Print 32 lines total
	MVI	B,16		;16 characters across
	SHLD	@StartLineHex	;Save the buffer location for ASCII display below
	LXI	H,0
	SHLD	@BYTE$COUNT
	JMP	BUFF$DONE




;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

N$RD$SEC:				;Read N sectors >>>> NOTE no check is made to not overwrite 
	LXI	D,ReadN$MSG		;CPM etc. in high RAM
	CALL	PSTRING
	CALL	GETHEX
	JC	BAD$RD$ENTRY		;Abort if ESC (C flag set)
	
	CALL	ZCRLF
	STA	@SECTOR$COUNT		;Store sector count
	STA	@SECTOR$COUNT1		;Store sector count
	
	LXI	H,buffer		;Point to buffer
	SHLD	@DMA

	LXI	D,ONE$MOMENT$MSG	;'One moment while data is collected'
	CALL	PSTRING

NextRSec:
	CALL	READ$FDC$SECTOR		;Read the current CF Card Sector
	SHLD	(@DMA)			;Update for next time
	JZ	N$READ$OK		;Z means the sector read was OK

	CALL	SHOW$SECTOR$READ$ERROR
	CALL	ZCRLF
	JMP	MAINLOOP

N$READ$OK:
	LDA	@SECTOR$COUNT
	DCR	A
	STA	@SECTOR$COUNT
	JZ	N$SEC$READ$DONE
	
	CALL	SEC$BUMP		;Point to the next sector
	JR	NextRSec
	

N$SEC$READ$DONE
	LDA	@SECTOR$COUNT1		;Get from store sector count
	CALL	HEXOUT
	LXI	D,N$SEC$READ$MSG	;'H Sectors read to RAM buffer'
	CALL	PSTRING
	PUSH	H
	LHLD	@DMA$STORE
	MOV	A,H
	CALL	HEXOUT
	MOV	A,L
	CALL	HEXOUT
	MVI	C,'H'
	CALL	ZCO
	MVI	C,'-'
	CALL	ZCO
	POP	H
	MOV	A,H
	CALL	HEXOUT
	MOV	A,L
	CALL	HEXOUT
	MVI	C,'H'
	CALL	ZCO
	MVI	C,')'
	CALL	ZCO
	CALL	ZCRLF
	LXI	H,buffer		;Point back to buffer
	SHLD	@DMA
	JMP	MAINLOOP

BAD$RD$ENTRY
	LXI	D,BAD$ENTRY$MSG		;'Bad data entry format'
	CALL	PSTRING
	CALL	ZCRLF
	LXI	H,buffer		;Point back to buffer
	SHLD	@DMA
	JMP	MAINLOOP



;----------------------------- WRITE N SECTORS FROM RAM ------------------------------------------------------	

N$WR$SEC:				;Read N sectors >>>> NOTE no check is made to not overwrite 
	LXI	D,WriteN$MSG		;'Write multiple sectors from RAM to the current CF card.'
	CALL	PSTRING			;'How many 512 byte sectores (xx HEX):$'
	CALL	GETHEX
	JC	BAD$WR$ENTRY		;Abort if ESC (C flag set)

	STA	@SECTOR$COUNT		;Store sector count
	STA	@SECTOR$COUNT1		;Store sector count
	
	LXI	D,DMA$N$MSG		;'Enter Starting RAM location (xxxxH):'
	CALL	PSTRING
	CALL	GET$HL$HEX		;Get 4 characters for HL address
	JC	BAD$WR$ENTRY		;Abort if ESC (C flag set)
	SHLD	@DMA$STORE
	
	LXI     D,msgsure		;Are you sure?
	CALL	PSTRING
	CALL	ZCI
	CALL	upper
IF CPM 
ELSE
	PUSH	PSW
	PUSH	B
	MOV	C,A			;Print response
	CALL	ZCO
	POP	B
	POP	PSW
ENDIF
	CPI	'Y'
	JMP	MAINLOOP

N$WR$SEC1:	
	LXI	D,ONEW$MOMENT$MSG	;'One moment while data is collected'
	CALL	PSTRING

	SHLD	@DMA
NextWSec:
	CALL	WRITE$FDC$SECTOR		;Write the current CF Card Sector
	SHLD	(@DMA)			;Store for next time
	JZ	N$WRITE$OK		;Z means the sector read was OK
	
	CALL	SHOW$SECTOR$WRITE$ERROR
	CALL	ZCRLF
	JMP	MAINLOOP

N$WRITE$OK:
	LDA	@SECTOR$COUNT
	DCR	A
	STA	@SECTOR$COUNT
	JZ	N$SEC$WRITE$DONE

	CALL	SEC$BUMP		;Point to the next sector
	JR	NextWSec
	

N$SEC$WRITE$DONE
	LDA	@SECTOR$COUNT1		;Get from store sector count
	CALL	HEXOUT
	LXI	D,N$SEC$WRITE$MSG	;'H Sectors read to RAM buffer'
	CALL	PSTRING
	PUSH	H
	LHLD	@DMA$STORE
	MOV	A,H
	CALL	HEXOUT
	MOV	A,L
	CALL	HEXOUT
	MVI	C,'H'
	CALL	ZCO
	MVI	C,'-'
	CALL	ZCO
	POP	H
	MOV	A,H
	CALL	HEXOUT
	MOV	A,L
	CALL	HEXOUT
	MVI	C,'H'
	CALL	ZCO
	MVI	C,')'
	CALL	ZCO
	CALL	ZCRLF
	LXI	H,buffer		;Point back to buffer
	SHLD	@DMA
	JMP	MAINLOOP

BAD$WR$ENTRY
	LXI	D,BAD$ENTRY$MSG		;'Bad data entry format'
	CALL	PSTRING
	CALL	ZCRLF
	LXI	H,buffer		;Point back to buffer
	SHLD	@DMA
	JMP	MAINLOOP




;----------------------------- COPY A DISK  ------------------------------------------------------	

COPY$DISK:				;"M"  Copy Drives
	LXI	D,WILL$COPY$MSG		;Will copy the 8" IBM SSSD Drive C: to Drive D: (Track by Track)$
	CALL	PSTRING

	LXI	D,COPY$MSG		;Warning: this will change data on Drive D: 
	CALL	PSTRING
	CALL	ZCI			;Are you sure?
	CALL	UPPER
IF CPM 
ELSE
	PUSH	PSW
	PUSH	B
	MOV	C,A			;Print response
	CALL	ZCO
	POP	B
	POP	PSW
ENDIF
	CPI	'Y'
	JZ	COPY1
	CALL	ZCRLF
	JMP	MAINLOOP
	
COPY1:	LXI     D,TO$ABORT$C		;Remember you can hit ESC to abort the copy process.
	CALL	PSTRING
	CALL	ZCRLF
	
	LXI	D,Copy$Ongoing$MSG	;Disk copy in process. See USB/Serial Terminal for status
	CALL	PSTRING

	MVI	A,CMD$FDC$COPY		;Special CMD for C:->D: copy
	CALL	DATA$TO$FPGA

COPY3:
	CALL	ZCSTS			;Any keyboard character will stop display
	CPI	01H
	JNZ	COPY4
	CALL	ZCI			;Flush character
	CPI	ESC
	JZ	ABORT$COPY
	CALL	ZCRLF
	
COPY4:
	IN	STATUS$BUS$PORT		;Get S100 Status Port - Bit 0, 1 = FPGA data present, 0, no data present
	ANI	01H			;01H, Bit 0
	JZ	COPY3			;wait for DC Board to present data 

	CALL	GET$FPGA$TO$S100	;Wait for the CMD$CPMPLETE/ERROR FLAG
	CPI	CMD$COMPLETE		;0F0H, Flag returned by DC board to signal the previous CMD was completed OK
	JNZ	COPY$ERROR

	LXI	D,Copy$Done$MSG		;Disk copy complete
	CALL	PSTRING
	JMP	DONE$COPY
	
COPY$ERROR:
	LXI	D,COPY$ERR$MSG		;Error writing Track data for a disk format
	CALL	PSTRING
	JMP	DONE$COPY
	
ABORT$COPY:
	LXI	D,COPY$ABORTING		;Disk Copying aborted, Hit any character to continue
	CALL	PSTRING
	OUT	ABORT$CMD$PORT		;Anything out to this port (84H), will abort the running copying command 
	CALL	ZCI			;Need this delay so the FPGA code gets to check this ports status

	CALL	GET$FPGA$TO$S100	;Wait for the CMD$CPMPLETE/ERROR FLAG
	CPI	CMD$COMPLETE		;0F0H, Flag returned by DC board to signal the previous CMD was completed OK

	XRA	A			;Back to Trk/Sec 0 in for Drive C:
	STA	@TRK
	INR	A	
	STA	@SEC			;First sector is always 1
	STA	@SIDE			;Side A
	CALL	ZCRLF
	
	MVI	A,'C'
	STA	@CURRENT$DRIVE		;Select Drive C:
	CALL	RESELECT$DRIVE		;Reselect drive in [A]

	MVI	A,CMD$SET$HOME		;0AH, this will set floppy disk head request to Track 0 of CURRENT drive
	CALL	DATA$TO$FPGA

	CALL	ZCRLF	
	JMP	MAINLOOP

DONE$COPY:
	XRA	A			;Back to Trk/Sec 0 in for Drive C:
	STA	@TRK
	INR	A	
	STA	@SEC			;First sector is always 1
	STA	@SIDE			;Side A
	CALL	ZCRLF
	
	MVI	A,'C'
	STA	@CURRENT$DRIVE		;Select Drive C:
	CALL	RESELECT$DRIVE		;Reselect drive in [A]

	MVI	A,CMD$SET$HOME		;0AH, this will set floppy disk head request to Track 0 of CURRENT drive
	CALL	DATA$TO$FPGA

	LXI	D,COPY$COMPLET$MSG
	CALL	PSTRING
	CALL	ZCRLF
	CALL	ZCRLF	
	JMP	MAINLOOP



;------------------------------------- BOOT CPM ------------------------------------------
	
CPMBOOT:				;Boot CPM from IDE system tracks of A: (Always)
	XRA	A			;Load from track 0,sec 1, head 0 (Always)
	STA	@TRK+1
	STA	@TRK
	MVI	A,1			;Boot from Track 0, SEC 1 
	STA	@SEC

	MVI	A,CPM$BOOT$COUNT	;Count of CPMLDR sectors  (12)
	STA	@SECTOR$COUNT
	LXI	H,BUFFER		;DMA address where the CPMLDR will INITIALLY be placed in RAM
	SHLD	@DMA

	MVI	A,CMD$SET$IDE$MODE	;38H set IDE to External mode 
	CALL	DATA$TO$FPGA
	MVI	A,EXT$IDE$MODE		;MODE 0, FPGA External IDE         [INT display/info only]
	STA	@CURRENT$IDE$MODE	;Store new current mode
	CALL	DATA$TO$FPGA

NextRCPM:
	LHLD	@DMA
	SHLD	@DMA$STORE		;Store for HEXDUMP
;	CALL	EXT$READ$FDC$SECTOR		;Read a sector in external IDE mode (Note @DMA is updated)
;	LHLD	@DMA$STORE
;	CALL	HEXDUMP			;<------- For Debugging	show contents @{HL]
;	CALL	FDC$PRINT$LBA
;	CALL	ZCRLF
	
	LDA	@SECTOR$COUNT
	DCR	A
	STA	@SECTOR$COUNT
	JZ	LOAD$DONE

	LDA	@SEC
	INR	A
	STA	@SEC			;Note we assume we alway will stay on track 0 in this special case
	MVI	C,'.'
	CALL	ZCO
	JMP	NextRCPM


LOAD$DONE:
	MVI	E,REGstatus		;Check the R/W status when done
;	CALL	IDErd8D
	BIT	0,D
	JNZ	CPMLoadErr		;Z if no errors
;	JMP	0F000H			;<---- For debugging with Monitor M4000,6000,100. Then G100

	LXI	H,BUFFER
	MOV	A,M
	CPI	31H			;EXPECT TO HAVE 31H @80H IE. LD SP,80H
	JNZ	CPMLoadErr1		;Z if no errors
	
	LXI	D,MOVE$REQUEST		;Ask if we can move data to 100H overwriting this program
	CALL	PSTRING
	CALL	ZCI
	CALL	upper
IF CPM 
ELSE
	PUSH	PSW
	PUSH	B
	MOV	C,A			;Print response
	CALL	ZCO
	POP	B
	POP	PSW
ENDIF
	CPI	'Y'
	JNZ	START
	
	LXI	H,CPM$MOVE$CODE		;Need to put memory move code out of the way.
	LXI	D,0H
	LXI	B,(CPM$MOVE$CODE$END-CPM$MOVE$CODE)
	LDIR
	NOP
	NOP
	NOP
	JMP	0H			;Now jump here where the code will move the CPMLDR currently @4000H to 100H
					;Note this will overwrite this code, no calls are valid after this! 
					
CPMLoadErr1:
	LXI	D,CPM$ERROR1		;Drive data error
	CALL	PSTRING
	JMP	MAINLOOP
	
CPMLoadErr:
	LXI	D,CPM$ERROR		;Drive Read Error
	CALL	PSTRING
	JMP	MAINLOOP



;----------------------------- NEXT SEC ------------------------------------------------------	

GET$NEXT$SEC:				; "N"  Next Sector
	CALL	SEC$BUMP	
	MVI	A,CMD$SET$TRK$SEC	;35H  Set new current TRACK/SECTOR on current drive
	CALL	DATA$TO$FPGA
	LDA	@TRK		
	CALL	DATA$TO$FPGA
	LDA	@SEC		
	CALL	DATA$TO$FPGA
	JMP	MAINLOOP

	
SEC$BUMP:				;General callable routine
	PUSH	B
	LDX	C,NSCTRS		;Sec/track+1
	LDA	@SEC
	INR	A
	CMP	C			;At last sector on track
	JZ	EO$TRK
	STA	@SEC
	JMP	NEXT$SEC$DONE
EO$TRK:
	MVI	A,1	
	STA	@SEC			;First sector is always 1 fot floppies
	LDX	A,NTRKS			;Sec/track (77 for 8")
	DCR	A
	MOV	C,A
	LDA	@TRK
	CMP	C
	JZ	END$OF$DISK
	INR	A
	STA	@TRK
	JMP	NEXT$SEC$DONE
END$OF$DISK:
	MVI	C,BELL
	CALL	ZCO
	LDX	A,NSCTRS		;Sec/track+1
	DCR	A
	STA	@SEC			;Put back the old end of track sector
	POP	B
	XRA	A
	DCR	A
	STC				;Set carry flag in a new track
	RET				;RET NZ if just a sector increase
			
NEXT$SEC$DONE:
	POP	B
	XRA	A
	DCR	A
	RET					;RET NZ if just a sector increase		
	
	
;----------------------------- PREVIOUS SECTOR ------------------------------------------------------	

GET$PREV$SEC:				; "P"  Previous Sector
	CALL	PREV$SEC
	MVI	A,CMD$SET$TRK$SEC	;35H  Set new current TRACK/SECTOR on current drive
	CALL	DATA$TO$FPGA
	LDA	@TRK		
	CALL	DATA$TO$FPGA
	LDA	@SEC		
	CALL	DATA$TO$FPGA
	JMP	MAINLOOP
	
PREV$SEC:				;General callable routine
	LDA	@SEC
	CPI	1			
	JZ	BO$TRK			;At first sector on current tarck
	DCR	A
	STA	@SEC
	JMP	START$SEC$DONE
BO$TRK:
	LDX	C,NSCTRS		;Sec/track+1
	DCR	A
	STA	@SEC
	LDA	@TRK
	ORA	A
	JZ	START$OF$CARD
	DCR	A
	STA	@TRK
	XRA	A
	DCR	A
	STC				;Set carry flag in a new track

START$OF$CARD:
	MVI	C,BELL
	CALL	ZCO
	MVI	A,1
	STA	@SEC
	XRA	A
	STA	@TRK
START$SEC$DONE:
	XRA	A
	DCR	A
	RET				;RET NZ if just a sector decrease		
	
;----------------------------- SELECT FLOPPY DISK DRIVES in [B] --------------------------------------------------	


SELECT$FDC$DRIVE:			;Select Drive in [B], IX updated.
	MOV	A,B
	CPI	'C'
	JNZ	SEL$D
	LXIX	FL$DRIVE$3		;FDC C:
	JR	SELECT$FDC1
SEL$D:	CPI	'D'
	JNZ	SEL$E
	LXIX	FL$DRIVE$4		;FDC D:
	JR	SELECT$FDC1
SEL$E:	CPI	'E'
	JNZ	SEL$F
	LXIX	FL$DRIVE$5		;FDC E:
	JR	SELECT$FDC1
SEL$F:	LXIX	FL$DRIVE$6		;FDC F:

SELECT$FDC1:
	MVI	A,CMD$SEL$DRIVE		;05H,  Select Drive CMD, drive in [B]
	CALL	DATA$TO$FPGA
	MOV	A,B			;Get selected drive
	STA	@CURRENT$DRIVE		;ASCII for DRIVE STORE
	CALL	DATA$TO$FPGA		
	CALL	GET$FPGA$TO$S100	;Wait for returned ACK signal 
	CMP	B 
	RET				;Returns with drive in A and Z if OK

;----------------------------- RAM CLEAR --------------------------------------------------	
	

FILL$RAM:				;Fill RAM buffer with a Byte value
	LXI	D,FILL$MSG		;CPM etc. in high RAM
	CALL	PSTRING
	CALL	GETHEX
	JC	BAD$ENTRY		;Abort if ESC (C flag set)

	MOV	B,A			;Store Fill character
	LXI	H,buffer		;Point to buffer
	LXI	D,512

CLEAR1:	MOV	M,B
	INX	H
	DCX	D
	MOV	A,E
	ORA	D
	JNZ	CLEAR1
	CALL	ZCRLF
	jmp	MAINLOOP

BAD$ENTRY
	LXI	D,BAD$ENTRY$MSG		;'Bad data entry format'
	CALL	PSTRING
	CALL	ZCRLF
	JMP	MAINLOOP



;----------------------------- SHOW RAM  ------------------------------------------------------	

SHOW$RAM:				;Show RAM Buffer Contents
	LXI	H,buffer		;Point to buffer. Show sector data flag is on
	SHLD	@DMA
	CALL	HEXDUMP			;Show sector data
	LXI	D,DONE$MSG		;"Hit keyboard to return to menu$ '
	CALL	PSTRING
	CALL	ZCI
	JMP	MAINLOOP


;----------------------------- REBOOT FPGA_DC BOARD  ------------------------------------------------------	

DO$REBOOT:
	LXI     D,SURE$REBOOT		;'Are you sure you want to Reboot/Reset teh FPGA_DC Board (Y/N)$'
	CALL	PSTRING			
	CALL	ZCI			;Are you sure?
	CALL	UPPER
IF CPM 
ELSE
	PUSH	PSW
	PUSH	B
	MOV	C,A			;Print response
	CALL	ZCO
	POP	B
	POP	PSW
ENDIF
	CPI	'Y'
	JZ	REBOOT1
	CALL	ZCRLF
	JMP	MAINLOOP
	
REBOOT1:
	MVI	C,'Y'
	CALL	ZCO
	CALL	ZCRLF
	OUT	REBOOT$PORT
	JMP	BEGIN



;--------------------------------------------------------------------------------------
;---------------- Support Routines ----------------------------------------------------
;--------------------------------------------------------------------------------------

CHECK$BOARD$TYPE:			;Check we have a FPGA DC Board. If not abort
	LDA	@BOARD$TYPE		;1 for FPGA_DC Board >>>
	ORA	A
	RNZ
	LXI	D,BOARD$ERR$MSG		;Command only valid for FPGA DC Board
	CALL	PSTRING
	POP	PSW			;Balance up stack
	JMP	MAINLOOP

	

SET$LBA:				;Set a new logical block address
	LDA	@TRK			;Store current data
	STA	@TRK1
	LDA	@SEC
	STA	@SEC1
	
	CALL	GETHEX			;TRACK LOW, get 2 more HEX digits
	JNC	SKIP$CR			;Carry flag in no entry
	CPI	CR			;If CR here then no data update
	JZ	NO$UPDATE		;No track entry
	JMP	BAD$FORMAT$ENTRY	
SKIP$CR:
	MOV	C,A
	LDX	A,NTRKS			;Highest track #+1.  (0,1,2,3...76),  Total 77 for 8" disk
	CMP	C
	JC	TRK$RANGE$ERR
	JZ	TRK$RANGE$ERR
	MOV	A,C
	STA	@TRK
	CALL	ZCI			;Format is XX,XX
	CPI	','
	JNZ	BAD$FORMAT$ENTRY
	MVI	C,','
IF CPM 
ELSE
	CALL	ZCO
ENDIF
	call	GETHEX		         ;SECTOR, get 2 more HEX digits
	JC	NO$UPDATE

	MOV	C,A
	ORA	A
	JZ	ZERO$ENTRY		;Sectors numbered 1,2,3 

IS$0$FIRST:
	LDX	A,NSCTRS		;1---26 for 8"
IF RANGE$CHECK
	CMP	C
	JZ	SEC$RANGE$ERR		;Check valid sector number check. Skip is checking
	JC	SEC$RANGE$ERR		;double sided disks
ELSE
ENDIF
	MOV	A,C
	STA	@SEC
	JMP	UPDATE$OK

TRK$RANGE$ERR:
	LXI	D,TRK$RANGE$$MSG	;Tracks range must be 00H-
	CALL	PSTRING
	LDX	A,NTRKS
	DCR	A
	CALL	HHEXOUT
	CALL	ZCRLF
	JP	NO$UPDATE	

SEC$RANGE$ERR:
	LXI	D,SEC$RANGE$$MSG	;Sectors range must be 01H-
	CALL	PSTRING
	LDX	A,NSCTRS
	CALL	HHEXOUT
	CALL	ZCRLF
	JP	NO$UPDATE	

ZERO$ENTRY:				
	LXI	D,ZERO$MSG		;Sectors numbered 1,2,3 
	CALL	PSTRING
	JMP	NO$UPDATE
	
BAD$FORMAT$ENTRY:
	LXI	D,BAD$LBA$MSG
	CALL	PSTRING
NO$UPDATE:	
	LDA	@TRK1			;Store current data
	STA	@TRK
	LDA	@SEC1
	STA	@SEC
	xra	A			;Ret NZ if no new data is NOT OK
	DCR	A
	RET
	
UPDATE$OK:
	CALL	ZCRLF
	xra	A			;Ret Z if no new data is OK
	RET


;
GETHEX:
	call	ZCI			;GET A CHARACTER, convert to UC, ECHO it
	call	UPPER
	cpI	ESC
	jz	HEXABORT$NO$ECHO
	cpi	'/'			;check 0-9, A-F
	jc	HEXABORT$NO$ECHO
	cpi	'F'+1
	jnc	HEXABORT$NO$ECHO

IF CPM 
ELSE
	PUSH	B
	PUSH	PSW
	MOV	C,A
	CALL	ZCO
	POP	PSW
	POP	B
ENDIF
	call	ASBIN			;Convert to binary
	rlc				;Shift to high nibble
	rlc
	rlc
	rlc
	MOV	b,A			;Store it
	
	call	ZCI			;GET second CHARACTER, convert to UC, ECHO it
	call	UPPER	
	cpi	ESC
	jz	HEXABORT$NO$ECHO
	CPI	CR
	JZ	ONE$DIGIT
	
	cpi	'/'			;check 0-9, A-F
	jc	HEXABORT$NO$ECHO
	cpi	'F'+1
	jnc	HEXABORT$NO$ECHO
IF CPM 
ELSE
	PUSH	B
	PUSH	PSW
	MOV	C,A
	CALL	ZCO
	POP	PSW
	POP	B
ENDIF
	call	ASBIN			;Convert to binary
	ora	B			;add in the first digit
	ora	A			;To return NC
	ret
HEXABORT$NO$ECHO:
	scf				;Set Carry flag
	ret
;
ONE$DIGIT:				;A CR wase ntered after only 1 digit
	MOV	A,B
	RAR				;Shift to high nibble back down
	RAR
	RAR
	RAR
	ANI	0FH
	ORA	A
	RET

GET$HL$HEX:
	CALL	GETCMD			;Get a 2 characters from keyboard for H
	CPI	ESC
	JZ	HEXABORT
	CPI	'/'			;check 0-9, A-F
	JC	HEXABORT
	CPI	'F'+1
	JNC	HEXABORT
	CALL	ASBIN			;Convert to binary
	RLC				;Shift to high nibble
	RLC
	RLC
	RLC
	MOV	B,A			;Store it
	CALL	GETCMD			;Get 2nd character from keyboard & ECHO
	CPI	CR
	JZ	HEXABORT
	CPI	ESC
	JZ	HEXABORT
	CPI	'/'			;check 0-9, A-F
	JC	HEXABORT
	CPI	'F'+1
	JNC	HEXABORT
	CALL	ASBIN			;Convert to binary
	ORA	B			;Add in the first digit
	MOV	H,A

	CALL	GETCMD			;Get a 2 characters from keyboard for L
	CPI	ESC
	JZ	HEXABORT
	CPI	'/'			;check 0-9, A-F
	JC	HEXABORT
	CPI	'F'+1
	JNC	HEXABORT
	CALL	ASBIN			;Convert to binary
	RLC				;Shift to high nibble
	RLC
	RLC
	RLC
	MOV	B,A			;Store it
	CALL	GETCMD			;Get 2nd character from keyboard & ECHO
	CPI	CR
	JZ	HEXABORT
	CPI	ESC
	JZ	HEXABORT
	CPI	'/'			;check 0-9, A-F
	JC	HEXABORT
	CPI	'F'+1
	JNC	HEXABORT
	CALL	ASBIN			;Convert to binary
	ORA	B			;Add in the first digit
	MOV	L,A
	ORA	A			;To return NC
	RET
HEXABORT:
	STC				;Set Carry flag 
	RET



				

FDC$PRINT$LBA:
	LXI	D,DMA$STRING		;'Buffer='
	CALL	PSTRING
	LHLD	@DMA
	MOV	A,H
	CALL	HEXOUT
	MOV	A,L
	CALL	HHEXOUT
	
	CALL	SHOW$DISK$NAME		;Show current disk name pointed to in IX

	LXI	D,SEC$RANGE		;'(Sec Range 1 - '
	CALL	PSTRING
	PUSHIX				;Point to Disk table
	POP	H
	LXI	D,NSCTRS		;Sectors/track offset in table
	DAD	D
	MOV	A,M
	DCR	A			;NSCTRS-1
	CALL	HEXOUT
	LXI	D,TRACK$STRING		;)  Track '
	CALL	PSTRING
	LDA	@TRK
	CALL	HEXOUT
	LXI	D,SECTOR$STRING		;' Sector '
	CALL	PSTRING
	LDA	@SEC
	CALL	HEXOUT
	LDA	@SIDE
	ORA	A
	JZ	SIDE$B
	LXI	D,SIDE$STRING$A		;' Side A'
	CALL	PSTRING
	RET
SIDE$B:	LXI	D,SIDE$STRING$B		;' Side B'
	CALL	PSTRING
	RET



ZCRLF:
	PUSH	PSW
	PUSH	BC
	MVI	C,CR
	CALL	ZCO
	MVI	C,LF
	CALL	ZCO
	POP	BC
	POP	PSW
	RET

ZEOL:				;CR and clear current line
	MVI	C,CR
	CALL	ZCO
	MVI	C,CLEAR		;Note hardware dependent, (Use 80 spaces if necessary)
	CALL	ZCO
	RET

ZCSTS:
  IF  CPM
	PUSH	B
	PUSH	D
	PUSH	H
	MVI	C,CONST
	CALL	BDOS		;Returns with 1 in [A] if character at keyboard
	POP	H
	POP	D
	POP	B
	CPI	1
	RET
  ELSE	
	IN	0H		;Get Character in [A]
	ANI	02H
	RZ
	MVI	A,01H
	ORA	A
	RET
  ENDIF
	
 
ZCO:				;Write character that is in [C]
  IF  CPM
	PUSH	PSW
	PUSH	B
	PUSH	D
	PUSH	H
	MOV	E,C
	MVI	C,WRCON
	CALL	BDOS
	POP	H
	POP	D
	POP	B
	POP	PSW
	RET
  ELSE	
	PUSH	PSW	
ZCO1:	IN   	0H		;Show Character
	ANI	04H
	JZ	ZCO1
	MOV	A,C
	OUT	1H
	POP	PSW
	RET
  ENDIF

ZCI:				;Return keyboard character in [A]
  IF CPM
	PUSH	B
	PUSH	D
	PUSH	H
	MVI	C,RDCON
	CALL	BDOS
	POP	H
	POP	D
	POP	B
	RET
  ELSE
ZCI1:	IN	0H		;Get Character in [A]
	ANI	02H
	JZ	ZCI1
	IN	01H
	RET
  ENDIF


;	Print a string in [DE] up to '$'

PSTRING:
 IF CPM
	MVI	C,PRINT
	JMP	BDOS		;PRINT MESSAGE, 
 ELSE
	PUSH	B
	PUSH	D
	PUSH	H
	XCHG
PSTRX:	MOV	A,M
	CPI	'$'
	JZ	DONEP
	MOV	C,A
	CALL	ZCO
	INX	H
	JMP	PSTRX
DONEP:	POP	H
	POP	D
	POP	B
	RET
  ENDIF



HHEXOUT:				;No registers altered
	CALL	HEXOUT
	PUSH	PSW
	PUSH	B
	MVI	C,'H'
	CALL	ZCO
	POP	B
	POP	PSW
	RET
	
; Print an 8 bit number, located in [A]
HEXOUT:	PUSH	PSW			;No registers altered
	PUSH	B
	PUSH	PSW
	RRC
	RRC
	RRC
	RRC
	CALL	ZCONV
	POP	PSW
	CALL	ZCONV
	POP	B
	POP	PSW
	RET

ZCONV:	ANI	0FH		;HEX to ASCII and print it
	ADI	90H
	DAA
	ACI	40H
	DAA
	MOV	C,A
	CALL	ZCO
	RET

;DISPLAY BIT PATTERN IN [A]
ZBITS:	PUSH	PSW
	PUSH	B
	PUSH	D
	MOV	E,A		
	MVI	B,8
BQ2:	DB	0CBH,23H	;Z80 Op code for SLA A,E
	MVI	A,18H
	ADC	A
	MOV	C,A
	CALL	ZCO
	DJNZ	BQ2
	POP	D
	POP	B
	POP	PSW
	RET

GETCMD:	CALL	ZCI		;GET A CHARACTER, convert to UC, ECHO it
	CALL	UPPER
	CPI	ESC
	RZ			;Don't echo an ESC
  IF NOT CPM
	PUSH	PSW		;Save it
	PUSH	B
 	MOV	C,A
	CALL	ZCO		;Echo it
	POP	B
	POP	PSW		;get it back
 ENDIF
	RET

				;Convert LC to UC
UPPER:	CPI	'a'		;must be >= lowercase a
	RC			; else go back...
	CPI	'z'+1		;must be <= lowercase z
	RNC			; else go back...
	SUI	'a'-'A'		;subtract lowercase bias
	RET

				;ASCII TO BINARY CONVERSION ROUTINE
ASBIN:	SUI	30H 
	CPI	0AH 
	RM
	SUI	07H 
	RET


HEXDUMP:			;Print a hexdump of the data in the 128/512 byte buffer @[HL] (Note NOT @DMA)
	PUSH	PSW		;Note this code is currently hard wired to either 128 of 512 byte sectors
	PUSH	B
	PUSH	D			 
	PUSH	H
	
	LDX	A,SEC$SIZE$BYTES+1	;If 0 then 128 byte sectors
	ORA	A
	JZ      BUFF$128	;128 Byte sectors
	CPI	1
	JZ      BUFF$256	;256 Byte sectors

BUFF$512:			
	MVI	D,32		;Print 32 lines total
	MVI	B,16		;16 characters across
	SHLD	@StartLineHex	;Save the buffer location in HL for ASCII display below
	LXI	H,0
	SHLD	@BYTE$COUNT
	JP	BUFF$DONE

BUFF$128:	
	MVI	D,8		;Print 8 lines total
	MVI	B,16		;16 characters across
	SHLD	@StartLineHex	;Save the buffer location in HL for ASCII display below
	LXI	H,0
	SHLD	@BYTE$COUNT
	JP	BUFF$DONE

BUFF$256:	
	MVI	D,16		;Print 16 lines total
	MVI	B,16		;16 characters across
	SHLD	@StartLineHex	;Save the buffer location in HL for ASCII display below
	LXI	H,0
	SHLD	@BYTE$COUNT
	
BUFF$DONE:			;<----- ENTRY POINT FOR DUMP$TRACK
	CALL	ZCRLF		;CR/LF first
SF172:	CALL	ZCRLF
	LHLD	@BYTE$COUNT
	MOV	A,H
	CALL	HEXOUT		;Print byte count in sector
	MOV	A,L
	CALL	HEXOUT		
	PUSH	D
	LXI	D,16
	DAD	D
	POP	D
	SHLD	@BYTE$COUNT	;store for next time
	CALL	BLANK
	LHLD	@StartLineHex	;BUFFER LOCATION
	SHLD	@StartLineASCII	;Store for ASCII display below
SF175:	MOV	A,M
	CALL	LBYTE		;Display [A] on CRT/LCD
	INX	H
	DJNZ	SF175
	SHLD	@StartLineHex	;Save for next line later
	CALL	ShowAscii	;Now translate to ASCII and display
	MVI	B,16		;16 characters across for next line
	DCR	D
	JNZ	SF172		;Have we done all 32 lines
;
	CALL	ZCRLF
	POP   H			;Get back origional registers
	POP   D
	POP   B
	POP   PSW
	RET
	
ShowAscii:			;Now show as ascii info
	LHLD	@StartLineASCII
	MVI	B,16		;16 ASCII characters across
XF172:	CALL	BLANK		;send a space character
	CALL	BLANK
XF175:	MOV	A,M
	ANI	7FH
	CPI	' ' 		;FILTER OUT CONTROL CHARACTERS
	JNC	XT33
XT22:	MVI	A,'.'
XT33:	CPI	07CH
	JNC	XT22
	MOV	C,A		;SET UP TO SEND
	PUSH	B
	CALL	ZCO
	POP	B
	INX	H		;Next position in buffer
	DJNZ	XF175
	RET
;
BLANK:	PUSH	B
	PUSH	H
	MVI	C,' '
	CALL	ZCO
	POP	H
	POP	B
	RET
;

PRINT$HL:					;PRINT [HL] ON CONSOL
	PUSH	PSW
	MOV	A,H
	CALL	LBYTE
	MOV	A,L
	CALL	LBYTE
	POP	PSW
	RET


LBYTE:	PUSH	PSW
	RRC
	RRC
	RRC
	RRC
	CALL	SF598
	POP	PSW
SF598:	CALL	ZCONV
	RET


;-------------------------------------------------------------------------------------------------------------

READ$FDC$SECTOR:			;Read a CF Card or SD Card Sector
	MVI	A,CMD$READ$SECTOR	;10H,  Send CMD_READ_SECTOR command 
	CALL	DATA$TO$FPGA
	
	LHLD  	@DMA			;DMA address
	MOV	A,H
	CALL	DATA$TO$FPGA
	MOV	A,L
	CALL	DATA$TO$FPGA

	LDA	@TRK			;Send Track
	CALL	DATA$TO$FPGA
	
	LDA	@SEC			;Send Sector
	CALL	DATA$TO$FPGA
	
	LHLD  	@DMA			;DMA address, DE Has the byte count
	LDX	E,SEC$SIZE$BYTES	;Bytes/sector  (128,256 for 8" IBM Disk or 512 for 1.44MB disk)
	LDX	D,SEC$SIZE$BYTES+1
	
FDC$SEC$RD$LOOP:			;<<<< LOOP CF/SD Card Sector READ >>>>
	CALL	GET$FPGA$TO$S100	;Get data in [A] back to S100 
	JC	SECTOR$READ$ERROR	;If error break out of loop
	MOV	M,A
	INX	H
	DCX	D			;Decrease DE
	MOV	A,E
	ORA	D
	JNZ	FDC$SEC$RD$LOOP		;Get all 128 256, or 512 bytes

	CALL	GET$FPGA$TO$S100	;Get CMD$CPMPLETE/ERROR FLAG
	CPI	CMD$COMPLETE		;0F0H, Flag returned by DC board to signal the previous CMD was completed OK
	JNZ	SHOW$SECTOR$READ$ERROR	
	XRA	A
	RET				;Ret Z if all OK
	
SECTOR$READ$ERROR:
	XRA	A
	DCR	A
	RET				;RET NZ if error
	
	
;--------------------------------------------------------------------------------------------------------------------

WRITE$FDC$SECTOR:
	MVI	A,CMD$WRITE$SECTOR	;11H,  Send CMD_WRITE_SECTOR command 
	CALL	DATA$TO$FPGA

	LHLD  	@DMA			;DMA address
	MOV	A,H
	CALL	DATA$TO$FPGA
	MOV	A,L
	CALL	DATA$TO$FPGA

	LDA	@TRK			;Send Track
	CALL	DATA$TO$FPGA
	
	LDA	@SEC			;Send Sector
	CALL	DATA$TO$FPGA
	
	LHLD  	@DMA			;DMA address, DE Has the byte count
	LDX	E,SEC$SIZE$BYTES	;Bytes/sector  (128 for 8" IBM Disk)
	LDX	D,SEC$SIZE$BYTES+1

	
FDC$SEC$WR$LOOP:			;<<<< LOOP CF/SD Card Sector READ >>>>
	MOV	A,M
	CALL	DATA$TO$FPGA		;Send data in [A] to FPGA 
	INX	H
	DCX	D			;Decrease DE
	MOV	A,E
	ORA	D
	JNZ	FDC$SEC$WR$LOOP		;Get all 128 or 512 bytes

	CALL	GET$FPGA$TO$S100	;Get CMD$CPMPLETE/ERROR FLAG
	CPI	CMD$COMPLETE		;0F0H, Flag returned by DC board to signal the previous CMD was completed OK
	JNZ	SHOW$SECTOR$READ$ERROR	
	XRA	A
	RET				;Ret Z if all OK
	
SHOW$SECTOR$WRITE$ERROR:
	LXI	D,SR$ERR$MSG		;'Sector READ error. TRK,SEC = $'
	CALL	PSTRING
	LDA	@TRK			;TRK = (8 bits)
	CALL	HEXOUT
	MVI	C,','
	CALL	ZCO
	LDA	@SEC
	CALL	HEXOUT			;XX,XX
	RET


	
;--------------------------------------------------------------------------------------------------------------------

SHOW$DISK$NAME:				;Show Disk name from IX table string
	PUSHIX
	POP	H
	LXI	D,DISK$TITLE
	DAD	D
DISK$NAME1:
	MOV	A,M		
	ORA	A			;Repeat up to end of string
	RZ	
	MOV	C,A
	CALL	ZCO
	INX	H
	JP	DISK$NAME1





CPM$MOVE$CODE:				;This code is written to reside at 0H. Will be relocated by this
	LXI	H,BUFFER		;this program to move the boot CPMLDR to 100H in RAM (Overwriting this program)
	LXI	D,100H
	LXI	B,(12*512)
	LDIR
	NOP
	NOP
	NOP
	JMP	100H
CPM$MOVE$CODE$END:



;-----------------------------------------------------------------------------------------------------
;------------------------------------- RTC ROUTINES --------------------------------------------------
;-----------------------------------------------------------------------------------------------------

GET$TIME$DATE:
	CALL	CHECK$BOARD$TYPE	;Must be FPGA DC Board

	LXI	D,Read$RTC		;Reading the Time  & Date from the FPGA DC Board RTC.
	CALL	PSTRING

	MVI	A,CMD$GET$TIME		;80H  Get Time CMD 
	CALL	DATA$TO$FPGA		;CMD to FPGA Board

	LXI	D,MSG20			; 'Date = '
	CALL	PSTRING

	CALL	GET$FPGA$TO$S100	;Wait for century (20)
	CALL	HEXOUT

	CALL	GET$FPGA$TO$S100	;Wait for year
	CALL	HEXOUT
	MVI	C,'/'
	CALL	ZCO


	CALL	GET$FPGA$TO$S100	;Wait for month
	CALL	HEXOUT
	MVI	C,'/'
	CALL	ZCO

	CALL	GET$FPGA$TO$S100	;Wait for day
	CALL	HEXOUT

	LXI	D,MSG19			; '  Time= '
	CALL	PSTRING

	CALL	GET$FPGA$TO$S100	;Wait for hour
	CALL	HEXOUT
	MVI	C,':'
	CALL	ZCO
	
	CALL	GET$FPGA$TO$S100	;Wait for minutes
	CALL	HEXOUT
	MVI	C,':'
	CALL	ZCO

	CALL	GET$FPGA$TO$S100	;Wait for seconds
	CALL	HEXOUT
	CALL	ZCRLF
	JMP	MAINLOOP


SET$TIME$DATE:
	CALL	CHECK$BOARD$TYPE	;Must be FPGA DC Board

	LXI	D,Set$RTC		;Set the Time & Date on the FPGA DC Board RTC.
	CALL	PSTRING

	MVI	A,CMD$SET$TIME		;81H  Set Time CMD 
	CALL	DATA$TO$FPGA		

	LXI	D,MSG12			;CR,LF,'Enter Year (00-99) '
	CALL	PSTRING
	CALL	GETHEX
	CALL	DATA$TO$FPGA		

	LXI	D,MSG13			;CR,LF,'Enter Month (01-12) '
	CALL	PSTRING
	CALL	GETHEX
	CALL	DATA$TO$FPGA		

	LXI	D,MSG14			;CR,LF,'Enter Date (01-31) '
	CALL	PSTRING
	CALL	GETHEX
	CALL	DATA$TO$FPGA		
	
	LXI	D,MSG15			;CR,LF,'Enter Hours (00-23) '
	CALL	PSTRING
	CALL	GETHEX
	CALL	DATA$TO$FPGA		

	LXI	D,MSG16			;CR,LF,'Enter Minutes (00-59) '
	CALL	PSTRING
	CALL	GETHEX		
	CALL	DATA$TO$FPGA		
	
	LXI	D,MSG17			;CR,LF,'Enter Seconds (00-59) '
	CALL	PSTRING
	CALL	GETHEX
	CALL	DATA$TO$FPGA		;Data to FPGA Board
	
	CALL	ZCRLF
	JMP	MAINLOOP



;-----------------------------------------------------------------------------------------------------------------------

DATA$TO$FPGA:				;Send CMD/data to FPGA_DC Z80
	PUSH	PSW
DATA$TO$FPGA1:
	IN	STATUS$BUS$PORT	
	CPI	0FFH			;0FFH if we have the Dual IDE/CF Card 
	JZ	NO$FPGA$DC
	ANI	80H
	JRNZ	DATA$TO$FPGA1		;Wait until bit 7 is 0 (ie. any previous data has been read by FPGA_DC board Z80)
	POP	PSW
	OUT	DATA$BUS$PORT		;This will cause the FPGA_DC board to set the S100$RTS bit
DATA$TO$FPGA2:
	IN	STATUS$BUS$PORT	
	ANI	80H
	JRNZ	DATA$TO$FPGA2		;Wait until bit 7 is 0 
	RET				;Ret NZ if error
NO$FPGA$DC
	POP	PSW
	RET
	

GET$FPGA$TO$S100:			;Get data from FPGA
	IN	STATUS$BUS$PORT		;Get S100 Status Port - Bit 0, 1 = FPGA data present, 0, no data present
	BIT	2,A			;04H, Bit 2
	JNZ	CLR$ERROR$FLAG		;Return carry flag set if error
	IN	STATUS$BUS$PORT		;Get S100 Status Port - Bit 0, 1 = FPGA data present, 0, no data present
	ANI	01H			;01H, Bit 0
	JZ	GET$FPGA$TO$S100	;wait for DC Board to present data 
	XRA	A
	IN	DATA$BUS$PORT		;Return Data in [A], FPGA "hardware" will lower bit 7 of S100 Bus port 80H
	STC
	CMC
	RET
	
CLR$ERROR$FLAG:
	OUT	RELEASE$ERROR$PORT	;This will release the Error flag gate 43H on the FPGA side
	STC				;Set carry flag if error on s100 bus side
	RET

;---------------------------------------------------------------------------------------------------
;
;	LOOKUP TABLES OF DISK PARAMETERS
;	
FL$DRIVE$3:			;(0F0H), 8" SINGLE DENSITY DRIVE VARIABLES (IBM 3740 Format)
	DB	IBM3740		;DISK_TYPE (SDSS)
	DB	0		;Default 0, No Drive Present 
	DB	FL$CS$1		;DRIVE_ADDR, actual Drive CS* Line 
						;   Bits 0,1 are used for drive hardware selection (00=A, 01=B,10=C,11=D)
						;   Bit 2, 1 if side A is selected, 0 if Side B
						;   Bit 3, 0 if 8" disk, 1 = 5" disk 
						;   Bit 4, 0 if Single Density, 1 = Double Density
						;   Bit 5 WD2793 INTRQ  1=ON, 0=OFF
						;   Bit 6 Write protect flag 0 = ON, 1 = OFF
						;   Bit 7 Drive Head load (currently unused)
	DB	3		;Drive NUMBER
	DB	0		;INITILIZED, unitilized
	DB	0		;128 Bytes/sec
	DB	2		;Tracks set aside for operating system (eg CPM = 2)
	DB	0CH		;HEX of Drive letter
	DB	'C'		;ACCII Character for Drive
	DB	1		;9 First sector #

	DW	128		;10,  <------ 128 Bytes/sec
	DW	26+1		;12, (1AH) 26+1 SECTORS PER TRACK (Note  Floppy sectors are numbered 1,2,...1B (not 0,1,2,3)
	DW	76		;14, (4CH) TRACKS PER SIDE    (0,1,2,3...76)
	DW	0000H		;16, TRK, Current Track
	DW	0000H		;18, SEC, Current Sector
	DB	0H		;20  SIDE, Current Side

	DB	40		;21, HEADER GAP (SD-Systems has 100-27, IBM is 40)
	DB	6		;22, GAP 1 (0's)
	DB	11		;23, GAP 2 (FF's)
	DB	27		;24, GAP 3 (FF's)
	DB	247		;25, GAP 4 (FF's)
	DB	1		;26, GAPR (Flag for multiple repeats of GAP4)
	DB	0FFH		;27, GAP Format fill character
	
	DB	0E5H		;28, CPM Sector Data Fill Character
	DB     	0H     	       	;29, No special post format
	DW	SKEW$IBM	;30, Location of this disks sector skew table
	DB	01H		;32, Each format will have a unique number. For disk to disk copy
	DW	13F0H		;33, <--- Size in bytes of 1 formatted track (see top of tables)
	DB	1		;35, Number of Floppy Disk sides
	DB	' 8" IBM 3740 Drive C: ',0 ;36
	
SKEW$IBM:
	DB	1H,2H,3H,4H,5H,6H,7H,8H,9H,0AH,0BH,0CH,0DH,0EH,0FH
	DB	10H,11H,12H,13H,14H,15H,16H,17H,18H,19H,1AH
;
;
FL$DRIVE$4:			;(0F0H), 8" SINGLE DENSITY DRIVE VARIABLES (IBM 3740 Format)
	DB	IBM3740		;DISK_TYPE (SDSS)
	DB	0		;Default 0, No Drive Present 
	DB	FL$CS$1		;DRIVE_ADDR, actual Drive CS* Line (Use this value if you have only one 8" Floppy Disk)
;	DB	F$CS$2		;DRIVE_ADDR, actual Drive CS* Line 
						;   Bits 0,1 are used for drive hardware selection (00=A, 01=B,10=C,11=D)
						;   Bit 2, 1 if side A is selected, 0 if Side B
						;   Bit 3, 0 if 8" disk, 1 = 5" disk 
						;   Bit 4, 0 if Single Density, 1 = Double Density
						;   Bit 5 WD2793 INTRQ  1=ON, 0=OFF
						;   Bit 6 Write protect flag 0 = ON, 1 = OFF
						;   Bit 7 Drive Head load (currently unused)
	DB	4		;Drive NUMBER
	DB	0		;INITILIZED, unitilized
	DB	0		;128 Bytes/sec
	DB	2		;Tracks set aside for operating system (eg CPM = 2)
	DB	0DH		;HEX of Drive letter
	DB	'D'		;ACCII Character for Drive
	DB	1		;First sector #


	DW	128		;<------ 128 Bytes/sec
	DW	26+1		;12, (1AH) 26+1 SECTORS PER TRACK (Note  Floppy sectors are numbered 1,2,...1B (not 0,1,2,3)
	DW	76		;14, (4CH) TRACKS PER SIDE      (0,1,2,3...76)
	DW	0000H		;TRK, Current Track
	DW	0000H		;SEC, Current Sector
	DB	0H		;SIDE, Current Side

	DB	40		;HEADER GAP (SD-Systems has 100-27, IBM is 40)
	DB	6		;GAP 1 (0's)
	DB	11		;GAP 2 (FF's)
	DB	27		;GAP 3 (FF's)
	DB	247		;GAP 4 (FF's)
	DB	1		;GAPR (Flag for multiple repeats of GAP4)
	DB	0FFH		;GAP Format fill character
	
	DB	0E5H		;CPM Sector Data Fill Character
	DB     	0H     	       	;No special post format
	DW	SKEW$IBM	;Location of this disks sector skew table
	DB	01H		;Each format will have a unique number. For disk to disk copy
	DW	13F0H		;<--- Size in bytes of 1 formatted track (see top of tables)
	DB	1		;Number of Floppy Disk sides
	DB	' 8" IBM 3740 Drive D: ',0
;
;
FL$DRIVE$5:			
	DB	IBM34		;(080H), 8" DOUBLE DENSITY DRIVE VARIABLES (IBM 34 Format)
	DB	0		;Default 0, No Drive Present 
	DB	FL$CS$1		;DRIVE_ADDR, actual Drive CS* Line (Use this value if you have only one 8" Floppy Disk)
;	DB	FL$CS$3		;DRIVE_ADDR, actual Drive CS* Line 
						;   Bits 0,1 are used for drive hardware selection (00=A, 01=B,10=C,11=D)
						;   Bit 2, 1 if side A is selected, 0 if Side B
						;   Bit 3, 0 if 8" disk, 1 = 5" disk 
						;   Bit 4, 0 if Single Density, 1 = Double Density
						;   Bit 5 WD2793 INTRQ  1=ON, 0=OFF
						;   Bit 6 Write protect flag 0 = ON, 1 = OFF
						;   Bit 7 Drive Head load (currently unused)
	DB	5		;Drive NUMBER
	DB	0		;INITILIZED, unitilized
	DB	2		;512 Bytes/sec flag
	DB	0		;Tracks set aside for operating system (eg CPM 2 for floppies)
	DB	0EH		;HEX of Drive letter
	DB	'E'		;ACCII Character for Drive
	DB	1		;First sector #

	DW	256		;<------ 256 Bytes/sec
	DW	26+1		;12, (1AH) 26+1 SECTORS PER TRACK (Note  Floppy sectors are numbered 1,2,...1B (not 0,1,2,3)
	DW	76		;14, (4CH) TRACKS PER SIDE    (0,1,2,3...76)
	DW	0000H		;TRK, Current Track
	DW	0000H		;SEC, Current Sector
	DB	0H		;SIDE, Current Side

	DB	80		;HEADER GAP (SD-Systems has 100-54, IBM is 80)
	DB	12		;GAP 1 (00's)
	DB	22		;GAP 2 (4E's)
	DB	54		;GAP 3 (4E's)
	DB	199		;GAP 4 (4E's) (X3 = 597)
	DB	3		;GAPR (Flag for multiple repeats of GAP4)
	DB	4EH		;GAP Format fill character
	
	DB	0E5H		;CPM Sector Data Fill Character
	DB	0H		;Special formating modifications of disk req (+++ NOT DONE YET)
	DW	SKEW$256	;Location of this disks sector skew table
	DB	12H		;Each format will have a unique number. For disk to disk copy
	DW	2780H		;<--- Size in bytes of 1 formatted track (more than enough)
	DB	2		;Number of Floppy Disk sides
	DB	' 8" IBM 34 Drive E:   ',0 ;36

SKEW$256:
	DB	1H,2H,3H,4H,5H,6H,7H,8H,9H,0AH,0BH,0CH,0DH,0EH,0FH
	db	10H,11H,12H,13H,14H,15H,16H,17H,18H,19H,1AH
;
;
FL$DRIVE$6:
	DB	IBM144		;(040H), DISK_TYPE (2.5" 1.4MB DDDS Disk)
	DB	0		;Default 0, No Drive Present 
	DB	FL$CS$4		;DRIVE_ADDR, actual Drive CS* Line 
						;   Bits 0,1 are used for drive hardware selection (00=A, 01=B,10=C,11=D)
						;   Bit 2, 1 if side A is selected, 0 if Side B
						;   Bit 3, 0 if 8" disk, 1 = 5" disk 
						;   Bit 4, 0 if Single Density, 1 = Double Density
						;   Bit 5 WD2793 INTRQ  1=ON, 0=OFF
						;   Bit 6 Write protect flag 0 = ON, 1 = OFF
						;   Bit 7 Drive Head load (currently unused)
	DB	6		;Drive NUMBER
	DB	0		;INITILIZED, unitilized
	DB	2		;512 Bytes/sec flag
	DB	0		;Tracks set aside for operating system (eg CPM 2 for floppies)
	DB	0FH		;ASCII of Drive letter
	DB	'F'		;ACCII Character for Drive
	DB	1		;First sector #

	DW	512		;<------ 512 Bytes/sec
	DW	18+1		; (12H) SECTORS PER TRACK +1 (Note, always +1 for floppies)
	DW	80		; (50H) Max Tracks
	DW	0000H		;TRK, Current Track
	DW	0000H		;SEC, Current Sector
	DB	0H		;SIDE, Current Side

	DB	80		;HEADER GAP (SD-Systems has 100-54, IBM is 80)
	DB	12		;GAP 1
	DB	22		;GAP 2
	DB	84		;GAP 3
	DB	200		;GAP 4 (4E's) (X3 = 597)
	DB	1		;GAPR (Flag for multiple repeats of GAP4)
	DB	4EH		;GAP Format fill character
	
	DB	0E5H		;CPM Sector Data Fill Character  (Is 0 for MSDOS)
	DB	0H		;Special formating modifications of disk req (+++ NOT DONE YET)
	DW	SKEW$144	;Location of this disks sector skew table
	DB	15H		;Each format will have a unique number. For disk to disk copy
	DW	2E90H		;Size in bytes of 1 formatted track (more than enough)
	DB	2		;Number of Floppy Disk sides
	DB	' 2.5" 1.44MB Drive F: ',0

SKEW$144:
	DB	1H,2H,3H,4H,5H,6H,7H,8H,9H,0AH,0BH,0CH,0DH,0EH,0FH
	DB	10H,11H,12H
;
;
;--------------------------------------------------------------------------------------------------------
	
SIGN$ON$CPM:	DB	CR,LF,LF,'FDC_FPGA Disk Controller Test Program (V6.4a) '
		DB	'using CPM3 Console BIOS Routines',CR,LF
		DB	'(Make sure the Disk Controller IOBYTE bit 7 is open).',CR,LF,'$'
SIGN$ON$Z80:	DB	CR,LF,LF,'FDC_FPGA Disk Controller Test Program (V6.4a) '
		DB	'using the Z80 Monitor for IO',CR,LF
		DB	'(Make sure the Disk Controller IOBYTE bit 7 is open).',CR,LF,'$'
		DB	'Initilizing FDC Circuit, one moment please...',CR,LF,'$'
		
INIT$1$ERROR:	DB	'Initilizing of Drive C: failed. Aborting Program.',BELL,CR,LF,LF,'$'
ID$ERROR:	DB	'Error obtaining Drive ID.',CR,LF,'$'
INIT$DR$OK:	DB	'Drive Initilized OK.',CR,LF,LF,'$'
BAD$DRIVE:	DB	CR,LF,'Drive ID Information appears invalid. '
		DB	'(Drive possibly not present).',CR,LF,'$'
DRIVE0$IDMSG:	DB	'Drive #0 - Invalid ID - Aborting',CR,LF,'$'
DRIVE$INFO:	DB	'Drive ID Paramater Information:-',CR,LF,'$'
msgmdl:		DB	'Model: $'
msgsn:		DB	'S/N:   $'
msgrev:		DB	'Rev:   $'
msgcy:		DB	'Cylinders: $'
msghd:		DB	', Heads: $'
msgsc:		DB	', Sectors: $'
msgCPMTRK:	DB	'CPM TRK = $'
msgCPMSEC:	DB	' CPM SEC = $'
msgLBA:		DB	'  (LBA = 00$'
MSGBracket	DB	')$'
msgLBAsup1:	DB	'LBA is $'
msgLBAnot:	DB	'NOT $'
msgLBAsup2	DB	'Supported',CR,LF,'$'


MENU$STRING$1:	DB  CR,LF,LF
		DB '(R) Read Sectors         (W) Write to a Sector    '
		DB '(+) Next Sector',CR,LF
		
		DB '(-) Previous Sector      (C) Copy a Sector        '
		DB '(V) Verify Sectors',CR,LF 
		      
		DB '(F) Fill Sector          (T) Set Trk#,Sec#        '
		DB '(S) Set Disk Side',CR,LF
		
		DB '(B) Show Sec. Buffer     (D) Select Disk          '
		DB '(M) Copy C:->D:',CR,LF
		          
		DB '(J) Format current Disk  (G) Show Track           '
		DB '(X) Restore Head',CR,LF
		
		DB '(H) Step Head In         (O) Step Head Out        '
		DB '(Y) Get Track ID',CR,LF
		                               
		DB '(L) Get Date & Time      (U) Set Date & Time      '
		DB '(K) Boot CPM from C:',CR,LF
		
		DB '(Z) Reboot FPGA_DC Board (ESC) Quit',CR,LF,'$'
		

DMA$STRING	DB	CR,LF,'Buffer=$'
SEC$RANGE	DB	'(Sec. Range 1-$'
TRACK$STRING	DB	') Track $'
SECTOR$STRING	DB	' Sec. $'
SIDE$STRING$A	DB	' Side A$'
SIDE$STRING$B	DB	' Side B$'
	 
Prompt:		db	CR,LF,LF,'Please enter command > $'
msgsure:	DB	CR,LF,'Warning: this will change data on the drive, '
		DB	'are you sure? (Y/N)...$'
msgrd:		DB	CR,LF,'Sector Read OK',CR,LF,'$'
msgwr:		DB	CR,LF,'Sector Write OK',CR,LF,'$'
SEC$RW$ERROR	DB	'Drive Error, Status Register = $'
ERR$REG$DATA	DB	'Drive Error, Error Register = $'
ENTER$SECL	DB	'Starting sector number,(xxH) = $'
ENTER$TRKL	DB	'Track number (LOW byte, xxH) = $'
ENTER$TRKH	DB	'Track number (HIGH byte, xxH) = $'
ENTER$HEAD	DB	'Head number (01-0f) = $'
ENTER$COUNT	DB	'Number of sectors to R/W = $'
DRIVE$BUSY	DB	'Drive Busy (bit 7) stuck high.   Status = $'
DRIVE$NOT$READY	DB	'Drive Ready (bit 6) stuck low.  Status = $'
DRIVE$WR$FAULT	DB	'Drive write fault.    Status = $'
UNKNOWN$ERROR	DB	'Unknown error in status register.   Status = $'
BAD$BLOCK	DB	'Bad Sector ID.    Error Register = $'
UNRECOVER$ERR	DB	'Uncorrectable data error.  Error Register = $'
READ$ID$ERROR	DB	'Error setting up to read Drive ID',CR,LF,'$'
SEC$NOT$FOUND	DB	'Sector not found. Error Register = $'
INVALID$CMD	DB	'Invalid Command. Error Register = $'
TRK0$ERR	DB	'Track Zero not found. Error Register = $'
UNKNOWN$ERROR1	DB	'Unknown Error. Error Register = $'
CONTINUE$MSG	DB	CR,LF,'To Abort enter ESC. Any other key to continue. $'
ReadN$MSG	DB	CR,LF,'Read multiple sectors from current disk/CF card to RAM buffer.'
		DB	CR,LF,'How many 512 byte sectores (xx HEX):$'
WriteN$MSG	DB	CR,LF,'Write multiple sectors RAM buffer CURRENT disk/CF card.'
		DB	CR,LF,'How many 512 byte sectores (xx HEX):$'
ReadingN$MSG	DB	CR,LF,'Reading Sector at:- $'
WritingN$MSG	DB	CR,LF,'Writing Sector at:- $'
msgErr		DB	CR,LF,'Sorry, that was not a valid menu option!$'
FC$DONE$MSG	DB	CR,LF,'Fast Copy of A:->B: Complete$'

RRANGE$MSG	DB	CR,LF,'Sector value out of range.',CR,LF,'$'
CPM$ERROR	DB	CR,LF,'Hardware error reading CPMLDR.',CR,LF,'$'
CPM$ERROR1	DB	CR,LF,'Data error reading CPMLDR. (The first byte loaded was not 31H).',CR,LF,'$'
MOVE$REQUEST	DB	CR,LF,'The CPMLDR image is now at 4000H in RAM. '
		DB	'To boot CPM you will have to'
		DB	CR,LF,'overwrite this program at 100H. Do you wish to do so (Y/N)...$'
SETC$MSG	DB	CR,LF,'Current Drive is now C:$'
SETD$MSG	DB	CR,LF,'Current Drive is now D:$'
SETE$MSG	DB	CR,LF,'Current Drive is now E:$'
SETF$MSG	DB	CR,LF,'Current Drive is now F:$'

FILL$MSG	DB	CR,LF,'Enter Fill Byte Character $'
		
VerifyTrk$MSG	DB	'Verifying track: $'
VerifyDone	DB	CR,LF,'Verify CPM disk A: = B: complete.',CR,LF,'$'
Verify$ERR	DB	CR,LF,BELL,'Verify error on Track $'
SEC$Msg		DB	'H  Sector $'
;SET$NOHOLE$Msg	DB	'No Hole mode set.  Maximum sector set to default of 03FH',CR,LF,'$'
;SET$HOLE$Msg	DB	'Hole mode set.  Maximum sector left at current value',CR,LF,'$'
GET$MAX$SEC$Msg	DB	'Enter max sector/Track value (00 - FF): $'
GET$FIRST$SEC$Msg DB	'Sectors can be numbered 0,1,2,3... (On CF cards) or '
		DB	'1,2,3,4... (On Hard Disks).',CR,LF
		DB	'Enter the first sector number (00 or 01):$'  
FIRST$STRING	DB	', First Sec # = $'
LBA$FORMAT	DB	CR,LF,'Enter new Track,Sector as (XX,XX): $'
TRK$RANGE$MSG	DB	CR,LF,BELL,'Error. Track range must be 00H-$'
SEC$RANGE$MSG	DB	CR,LF,BELL,'Error. Sector range must be 01H-$'
BAD$LBA$MSG	DB	CR,LF,BELL,'Data must be in the form XX,XX (Hex).$'
WAIT$MSG	DB	CR,LF,'Hit any keyboard character to continue$'
SR$ERR$MSG	DB	CR,LF,'Sector READ error. TRK,SEC = $'
SW$ERR$MSG	DB	CR,LF,'Sector WRITE error. TRK,SEC = $'
N$SEC$READ$MSG	DB	'H Sectors read to RAM ($'
ONE$MOMENT$MSG	DB	CR,LF,'One moment please while the data is collected',CR,LF,'$'
BAD$ENTRY$MSG	DB	CR,LF,BELL,'Bad data entry format$'
DMA$N$MSG	DB	CR,LF,'Enter Starting RAM location (xxxxH): $'
ONEW$MOMENT$MSG DB	CR,LF,'One moment please while the data is written',CR,LF,'$'
N$SEC$WRITE$MSG	DB	'H Sectors written to the Card from RAM ($'
Quick$Format	DB	CR,LF,'Do you want a "Quick Format", (Tracks 0 & 1 only) Y/N: $'
TO$ABORT$F	DB	CR,LF,'Remember you can hit ESC any time to abort'
		DB	' the formatting process.$'
msgTRK$SEC	DB	'Disk TRK,SEC = $'
msgBS5		DB	BS,BS,BS,BS,BS,'$'
msgBS2		DB	BS,BS,'$'
WILL$COPY$MSG	DB	CR,LF,'Will copy the 8" IBM SSSD Drive C: to Drive D: (Track by Track)$'
COPY$MSG	DB	CR,LF,'Warning: this will change data on Drive D: '
		DB	'Is this OK (Y/N) $' 
COPY$COMPLET$MSG DB	CR,LF,BELL,'Copying of Disk complete$'
TO$ABORT$C	DB	CR,LF,'Remember you can hit ESC to abort the copy process$'
DONE$MSG	DB	CR,LF,'Hit keyboard to return to menu$'
SURE$REBOOT	DB	CR,LF,'Are you sure you want to Reboot/Reset the FPGA_DC Board (Y/N) $'
LAST$MSG	DB	CR,LF,'Enter the last sector number on a track - in hardware. $'
FIRST$MSG	DB	CR,LF,'Enter the starting sector number on a track - '
		DB	'in hardware. (0 or 1) $'

FPGA$BOARD$MSG DB	CR,LF,'The FPGA_DC Board was detected.$'

OLD$IDE$BOARD$MSG   DB	CR,LF,BELL,'The FPGA_DC + FDC Board was NOT detected.$'
CURRENT$DR$MSG	DB	CR,LF,'Select Floppy Drive: (C,D,E or F) $'
BAD$SEL$DR$MSG	DB	CR,LF,BELL,'Select Drive Error$'

DiskCopyMsg	DB	CR,LF,'Fast Copy IDE/CF Card A: to Drive B:'
		DB	CR,LF,BELL,'Warning: This will delete all data on CF Card B:, '
		DB	'are you sure? (Y/N)...$ '
Copy$Ongoing$MSG DB     CR,LF,'Disk copy in process. See the USB/Serial Terminal for status.$'
Copy$Done$MSG	DB	CR,LF,'Disk copy of Drive C:->D: complete.',CR,LF,'$'
CopyTrk$MSG	DB	'Copying track: $'
FAST$COPY$MSG	DB	CR,LF,'Fast Copy of Disk C:->D: Started. '
		DB	'(Use USB Port Terminal for status).$'
NO$DRIVE$MSG	DB	CR,LF,BELL,'A valid CF card is not present in B:',CR,LF,'$'
FAST$ERROR$MSG	DB	CR,LF,'Fast Copy of CF Card A:->B: returned an error',CR,LF,'$'
FAST$ABORT$MSG	DB	CR,LF,'Fast Copy of CF Card A:->B: Aborted.',CR,LF,'$'
POST$TEST$MSG	DB	'This is a test of the Post Message CMD',0
SET$IDE$MODE$MSG DB	CR,LF,'Set IDE Mode (0,1 or 2) $'
BOARD$ERR$MSG	DB	CR,LF,BELL,'Sorry that Command is valid only for the FPGA DC Board$'
IDE$MODE$0$MSG	DB	CR,LF,'IDE Mode to Mode 0$'
IDE$MODE$1$MSG	DB	CR,LF,'IDE Mode to Mode 1$'
IDE$MODE$2$MSG	DB	CR,LF,'IDE Mode to Mode 2$'
FDC$CIRCUIT$MSG	DB	CR,LF,'FDC circuit detected on FPGA_DC Board$'
IDE$CIRCUIT$MSG	DB	CR,LF,'IDE/CF card circuit detected on FPGA_DC Board$'
BOTH$CIRCUITS$MSG DB	CR,LF,'IDE/CF card and FDC circuits detected on FPGA_DC Board$'
HOME$DR$MSG	DB	CR,LF,'Move Disk head to track 0$'
BAD$RESTORE$MSG	DB	CR,LF,BELL,'Failed to restore current disk head to Track 0$'
TRK$ID$MSG	DB	CR,LF,'Track ID = $'
BAD$TRK$ID$MSG  DB	CR,LF,'Track ID Error detected.$'
STEP$IN$MSG	DB	CR,LF,'Step head in one Track $'
STEP$OUT$MSG	DB	CR,LF,'Step head out one Track $'
STEP$IN$ERR	DB	CR,LF,'Step head In Error $'
STEP$OUT$ERR	DB	CR,LF,'Step head Out Error $'
ZERO$MSG	DB	CR,LF,'Sectors must be numbered 1,2,3...$' 

FORMAT$3740$MSG	DB	CR,LF,'Disk Format Menu.'
		DB	CR,LF,'1. 8" Single Density, Single Sided, 26 X 128 '
		DB	'Byte Sec. (IBM 3740 Format).'
		DB	CR,LF,'2. 8" Single Density, Double Sided, 26 X 128 '
		DB	'Byte Sec.'
		DB	CR,LF,LF,'Enter Disk Format. (ESC to abort): $'
		
FORMAT$34$MSG	DB	CR,LF,'Will Format as 8" DD, DS, 26 X 256 '
		DB	'Byte Sec. (IBM Sys. 34 Format).$'
		
FORMAT$144$MSG	DB	CR,LF,'Will Format as 3.5" DD, DS, 18 X 512 '
		DB	'Byte Sec.$'
		
FORMAT$WARNING	DB	CR,LF,'Warning: this will change data on the Disk, '
		DB	'are you sure? (Y/N)...$'
FORMAT$ERR$MSG  DB	CR,LF,'Error writing Track data for a disk format.$'
COPY$ERR$MSG	DB	CR,LF,'Error copying Disk C:->D:$'
FormatDone	DB	CR,LF,'Disk format complete.$'
TRK$CONT$MSG    DB	CR,LF,'Hit ESC to abort Disk Track formatting.$'
FORMAT$ABORTING DB	CR,LF,'Formatting aborted. Hit any character to '
		DB	'return to the main menu.$'
COPY$ABORTING   DB	CR,LF,'Disk Copy aborted. Hit any character to '
		DB	'return to the main menu.$'
TRACK$MSG	DB	CR,LF,'Displaying the complete contents of Track: $'
TRACK$ERR$MSG	DB	CR,LF,'An error was detected for the Track data dump.$'
RAM$DATA$MSG	DB	CR,LF,'Write data from a RAM location to the current Track/Sector(s)$'
WR$RAM$MENU$MSG	DB	CR,LF,'From RAM at:- (XXXXH):$'
FILL$DATA$MSG	DB	CR,LF,'Fill  the current Track-Sector(s) with a byte value.'
		DB	CR,LF,'Please enter the fill byte value (XX): $'
FILL$DATA$OK	DB	CR,LF,'Sector Write complete$'
COPY$SEC$MSG	DB	CR,LF,'Will copy current Sector to another sector.$'
COPY$OK$MSG	DB	CR,LF,'Sector copied OK$'
VERIFY$SEC$MSG	DB	CR,LF,'Will compare the current Sector to another sector.$'
SAME$SEC$MSG	DB	CR,LF,'The two sectors are the same.$'
SECOND$SEC	DB	CR,LF,'Enter Track,Sector info. for the second Sector as (XX,XX): $'
SEC$MISMATCH$MSG DB	CR,LF,'Sectors do NOT match starting at position:- $'
SIDE$MSG	DB	CR,LF,'Enter Active Side of current Disk (A,B): $'
SIDE$ERR$MSG	DB	CR,LF,'The FPGA_DC Board failed to set the requested floppy '
		DB	'disk active side.$'
ACTIVE0$SIDE$MSG  DB	CR,LF,'The Active Floppy disk side is now side A.$'
ACTIVE1$SIDE$MSG  DB	CR,LF,'The Active Floppy disk side is now side B.$'




Read$RTC	DB	CR,LF,'Reading the Time & Date from the FPGA DC Board RTC.$'
MSG20:		DB	CR,LF,'Date = $'
MSG19:		DB	'  Time = $'
Set$RTC		DB	CR,LF,'Set the Time & Date on the FPGA DC Board RTC.$'
MSG12:		DB	CR,LF,'Enter Year (00-99) $'
MSG13:		DB	CR,LF,'Enter Month (01-12) $'
MSG14:		DB	CR,LF,'Enter Date (01-31) $'
MSG15:		DB	CR,LF,'Enter Hours (00-23) $'
MSG16:		DB	CR,LF,'Enter Minutes (00-59) $'
MSG17:		DB	CR,LF,'Enter Seconds (00-59) $'

; -------------------------- RAM usage -----------------------------------------

RAMAREA			DB	'           RAM STORE AREA -------->'	;useful for debugging
@DMA			DW	buffer
@DMA$STORE		DW	buffer
@DRIVE$SEC		DB	0H
@DRIVE$TRK		DW	0H
@SEC			DW	0H
@TRK			DW	0H
@SIDE			DW	0H

@DRIVE1			DW	0H
@SEC1			DW	0H		
@TRK1			DW	0H
@DRIVE2			DW	0H
@SEC2			DW	0H
@TRK2			DW	0H

@StartLineHex		DW	0H
@StartLineASCII		DW	0H
@BYTE$COUNT		DW	0H
@SECTOR$COUNT		DW	0H
@SECTOR$COUNT1		DW	0H
@CURRENT$DRIVE		DB	0H
@CURRENT$DRIVE$PORT	DB	0H		;0=IDE A: 1=IDE B:
@Second$DriveBPresent	DB	0H		;1 if second drive is present
@TRACK$COUNT		DB	0H
@DELAYSTORE		DB	0H
@CURRENT$IDE$MODE	DB	0H		;0 = old IDE Board - must do things here. 
						;1 = Extenal IDE Ports  + CMD Info
						;2 = Local FPGA IDE Ports + CMD Info
@CURRENT$BOARD$HARDEWARE DB     0H		;0XXXXXX = IDE, 01XXXXXX = FDC, 11XXXXXX +IDE+FDC
@BOARD$TYPE		DB	0H		;0= Dual IDE/CF Board, 1= FPGA_DC Board
@DISK$FORMAT		DB	0H
@SEC$POSITION		DB	0H


			DS	100H
STACK:			DW	0H
			DB	'<--End of MYIDE Code           '

		ORG	4000H	
BUFFER:			DS	512
IDBUFFER
BUFFER2:	DS	512
