*----------------------------------------------------------------------
*  LOADER FOR SOFTWARE DYNAMICS SDOS 1.1 OPERATING SYSTEM
*  I/O ROUTINES FOR MF68 FLOPPY DISK
*
*  (C) ROBERTO SANCHO, JUN/2022
*
*  UPDATED MAY/2023 BY MIKE DOUGLAS TO WORK ON REAL HARDWARE.
*  THE MF68 DOES NOT SUPPORT DOUBLE SIDED OPERATION AS REQUIRED
*  BY THIS SDOS CONFIGURATION, SO THIS HAS BEEN MADE TO WORK
*  ON THE PERIPHERAL TECHNOLOGY FD-2 FLOPPY CONTROLLER WHICH
*  SUPPORTS DOUBLE SIDED OPERATION AND IS BACKWARD COMPATIBLE
*  WITH THE MF68.
*----------------------------------------------------------------------

SRCPTR	EQU	0		SOURCE POINTER FOR MOVE OPERATION
ENTRY	EQU	2		POINTER TO LOADER ENTRY ADDRESS

*  THE SWTBUG D COMMAND READS CONSECUTIVE SECTORS STARTING AT SECTOR 0
*  INTO RAM AT $2400 UNTIL AN ERROR OCCURS. THIS LOADER IS 5 SECTORS
*  LONG AND IS ON SECTORS 0-4 ON THE DISK. SECTOR 5 DOES NOT EXIST
*  AND SECTORS RESUME WITH SECTOR 6. THE SWTBUG D COMMAND STOPS
*  READING WHEN IT IS NOT ABLE TO READ SECTOR 5. ONLY TRACK 0
*  SIDE 0 IS FORMATTED THIS WAY (0,1,2,3,4,6,7...). ALL OTHER TRACKS
*  HAVE SECTORS 1-18.

	ORG	$2400		SWTBUG D COMMAND READS INTO $2400

BOOT	LDX	#BASE		MOVE SDOS LOADER TO EXECUTION ADDRESS
	STX	SRCPTR
	LDX	DESTPTR		SAVE LOADER ENTRY ADDRESS FOR LATER
	STX	ENTRY

MOVE	LDX	SRCPTR		X->SOURCE
	CPX	#MOVEND		DONE?
	BEQ	JMPLDR		YES, JUMP TO LOADER

	LDAA	0,X		MOVE BYTE TO NEW LOCATION	
	INX
	STX	SRCPTR
	LDX	DESTPTR
	STAA	0,X
	INX
	STX	DESTPTR
	BRA	MOVE
	
JMPLDR	LDX	ENTRY		X->LOADER EXECUTION ADDRESS
	JMP	0,X		JUMP TO SDOS LOADER

*----------------------------------------------------------------------
*  SECTOR 1 ONE CONTAINS DISK INFORMATION MAINTAINED BY SDOS. THIS
*  INFORMATION IS IN THE 1ST 64 BYTES. THIS SECTION WILL BE OVER-
*  WRITTEN BY THE CONTENT OF SECTOR 1.
*----------------------------------------------------------------------
	ORG	BOOT+128	SECTOR 1 ENDS UP HERE IN MEMORY
SECTOR1	FCB	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
	FCB	$10
LDRSECS	FCB	5		NUMBER OF SECTORS IN BOOT LOADER
	FCB	0,1,0,1,0,1,$10,8,$82,0,2,$76,0,$D5
	FCC	"SWTPC 6800 SDOS 1.1G BOOT       "

	FCB	$02		RECORD TYPE
DESTPTR	FDB	LOADER		RECORD LOAD ADDRESS
	FDB	LDREND-LOADER	LENGTH

BASE	EQU	*		LOADER IS HERE AFTER "D" COMMAND

*----------------------------------------------------------------------
* SDOS COLD BOOT LOADER
*----------------------------------------------------------------------
	ORG	$5000		EXECUTION ADDRESS OF SDOS LOADER
BUF	EQU	*+$800		BUFFER FOR SDOS LOADER TO USE

LOADER	LDAA	LDRSECS		GET NUM OF SECTORS USED BY THE LOADER
	INCA			NEXT SECTOR IS 1ST SECTOR OF SDOS.SYS
	STAA	SECT     
	LDX	#BUF+128	POINT TO END (NEW SECTOR NEEDED)
	STX	DDATA
	CLR	GOFLAG		NOT READY TO RUN YET
	
RDTY	TST	GOFLAG		TIME TO RUN SDOS?
	BNE	GO		YES

	JSR	RDBYTE		GET RECORD TYPE
	TSTA			TYPE 0 (FILL RECORD)
	BEQ	RDTY0

	CMPA	#1		TYPE 1 (SKIP 4 BYTES)
	BEQ	RDTY1

	CMPA	#2		TYPE 2 (LOAD RECORD)
	BEQ	RDTY2

	CMPA	#3		TYPE 3 (LAST LOAD RECORD
	BEQ	RDTY3		BR IF TYPE 3 (LAST LOAD RECORD)

GO	JSR	PATCH		PATCH SDOS AS NEEDED
	JMP	$2000		JUMP TO SDOS

RDTY0	JSR	RDWORD		TYPE 0 RECORD (FILL RECORD), GET LENGTH
	STX	PLEN
RD0A	LDX	PLEN
	BEQ	RDTY		BR IF RECORD DONE, TO READ NEXT ONE
	DEX
	STX	PLEN
	JSR	RDBYTE		READ BYTE AND DISCARD IT
	BRA	RD0A
		
RDTY1	JSR	RDWORD		TYPE 1 RECORD: SKIP 4 BYTES
	JSR	RDWORD
	BRA	RDTY

RDTY3	INC	GOFLAG		INDICATE READY TO RUN	
RDTY2	JSR	RDWORD		GET LOAD ADDR
	STX	PDATA
	JSR	RDWORD		GET LOAD LENGTH
	STX	PLEN	

RD2	LDX	PLEN		LOAD TYPE 2 RECORD DATA
	BEQ	RDTY		BR IF RECORD DONE, TO READ NEXT ONE
	DEX
	STX	PLEN
	JSR	RDBYTE
	LDX	PDATA
	STAA	0,X
	INX
	STX	PDATA
	BRA	RD2

RDWORD	JSR	RDBYTE	
	STAA	WORD
	JSR	RDBYTE
	STAA	WORD+1
	LDX	WORD
	RTS

RDBYTE	LDX	DDATA		X->DATA POINTER
	CPX	#BUF+128	ANY BYTES LEFT?
	BNE	RDBYTE1		YES
	BSR	RDSK		ELSE, READ NEW SECTOR
	LDX	#BUF		POINT AGAIN TO START OF BUF
	STX	DDATA

RDBYTE1	LDAA	0,X		RETURN NEXT BYTE
	INX
	STX	DDATA
	RTS			

RDSK	LDX	#BUF		X->WHERE TO READ SECTOR
	STX	DDATA
	JSR	RDSEC		READ THE SECTOR
	LDAB	SECT		END OF A TRACK?
	CMPB	#18
	BNE	RDSK1		NO

	TST	SIDE		DO TOP AFTER BOTTOM
	BNE	RDSK0A		BRANCH IF TOP ALREADY DONEE
	INC	SIDE		ELSE, MOVE TO TOP
	BRA	RDSK0B

RDSK0A	CLR	SIDE		BACK TO BOTTOM
	INC	TRK		MOVE TO NEXT TRACK
RDSK0B	CLR	SECT
RDSK1	INC	SECT
	RTS

WORD	FDB	0		USED BY RDWORD
PDATA	FDB	0		
PLEN	FDB	0		
GOFLAG	FCB	0

*----------------------------------------------------------------------
* DISK DRIVERS FOR SWTPC MF-68 (FD-2 CONTROLLER)
*----------------------------------------------------------------------

* INPUT PARAMS

DRV	FCB	0		DRIVE TO OPERATE ON
TRK	FCB	0		TRACK TO READ/WRITE
SECT	FCB	0		SECTOR TO READ/WRITE
SIDE	FCB	0		SIDE TO READ/WRITE
DDATA	FDB	0		POINTER TO DATA BUFFER

* COMMANDS FOR 1771 (WD2797) CONTROLLER CHIP ON THE FD-2

SKFAST	EQU	0
SKSLOW	EQU	3
SKRATE	EQU	SKFAST		SPECIFY SEEK RATE HERE

FDRSC	EQU	$08+SKRATE	RESTORE
FDSKI	EQU	$18+SKRATE	SEEK
FDRDC	EQU	$88		READ A SECTOR (E-BIT OFF)
FDWRC	EQU	$A8		WRITE A SECTOR (E-BIT OFF)

* ADDR OF 1771 (WD2797) CONTROLLER CHIP REGISTERS 

DRVREG	EQU	$8014		DRIVE SELECT REGISTER
CMDREG	EQU	$8018
TRKREG	EQU	$8019
SECREG	EQU	$801A
DATREG	EQU	$801B

* DRIVER VARIABLES

RCNT	FCB	0		RETRY COUNT		

* READ A SECTOR

RDSEC	JSR	SELDRV

RDSEC1	JSR	READ		READ A SECTOR
	BEQ	RSEXIT		EXIT IF IT WORKED
	DEC	RCNT		ELSE, RETRY?
	BNE	RDSEC1		YES

	TSTA			A HAS THE STATUS BITS WITH ERROR 
RSEXIT	RTS

* READ A SECTOR (A=TRK, B=SECTOR, X=CTRKX)

READ	JSR	SEEK
	LDAA	#FDRDC		READ COMMAND
	STAA	CMDREG		
	JSR	DEL56U		DELAY
	LDX	DDATA		GET BUFFER ADDRESS
 
READ1	LDAA	CMDREG		
	BITA	#$02		DATA REG FULL?
	BNE	READ2		YES
	BITA	#$01		STILL BUSY?
	BNE	READ1		YES

	ANDA	#$1C		MASK OFF STATUS BITS
	RTS

READ2	LDAA	DATREG		GET A BYTE
	STAA	0,X		STORE IN BUFFER
	INX					
	BRA	READ1		DO AGAIN		

* SEEK A=TRACK, B=SECTOR, X=CTRKX

SEEK	STAB	SECREG		SET THE SECTOR
	CMPA	TRKREG		ALREADY ON TRACK?
	BEQ	SKEXIT		YES, EXIT

	STAA	DATREG		NO, SET SEEK TRACK#
	LDAA	#FDSKI		ISSUE SEEK COMMAND
DOSEEK	STAA	CMDREG		
	JSR	DEL56U

WBUSY	LDAA	CMDREG		WAIT FOR SEEK TO FINISH	
	BITA	#1		BUSY?
	BNE	WBUSY		YES
SKEXIT	RTS

* DEL56U- DELAY 56US INCLUDING THE CALL TO DELAY56U

DEL56U	JSR	DELAY2
DELAY2	JSR	DELAY3
DELAY3	RTS

* RESTORE TO TRACK 0

RESTOR	BSR	SELDRV		SELECT THE DRIVE
	LDAA	#FDRSC		ISSUE RESTORE COMMAND
	BRA	DOSEEK		DO THE SEEK TO TRACK 0

* SELECT THE DRIVE
* RETURN A=TRACK, B=SECTOR, X=CTRKX

SELDRV	LDAA	DRV		A=DRIVE TO SELECT
	TST	SIDE		TOP OR BOTTOM?
	BEQ	DOSEL		BOTTOM
	ORAA	#$40		ELSE, SELECT SIDE 1
DOSEL	STAA	DRVREG		SELECT THE DRIVE
	
	LDAA	#5		SET RETRY COUNT
	STAA	RCNT		
	LDAA	TRK		GET TRACK#        
	LDAB	SECT		GET SECTOR#
	RTS			

* PATCH SDOS

PATCH	CLR	$7918		FORCE SIDEBT TO ZERO (NOT USED)
	LDAA	#FDRDC		NO E-BIT ON READ COMMAND
	STAA	$794D
	LDAA	#FDWRC		NO E-BIT ON WRITE COMMAND
	STAA	$7983

	LDAA	#FDSKI		SEEK SLOW OR FAST
	STAA	$79BC
	LDAA	#FDRSC		RESTORE SLOW OR FAST
	STAA	$79EC
	
	LDAA	#$BD		JSR TO SIDE SELECT PATCH
	STAA	$7A04
	LDX	#$79CC
	STX	$7A05

	LDAA	#$39		RTS IN SEEK
	STAA	$79C9

	LDAA	#$7D		THIS IS THE SIDE SELECT PATCH
	STAA	$79CC		TST SIDE VS LDAA SIDE
	LDX	#$8A40		ORAA #$40 VS LDAA $08
	STX	$79D1
	LDX	#$8014		STORE TO DRIVE SELECT REGISTER
	STX	$79D4
	RTS

LDREND	EQU	*
MOVEND	EQU	BASE+LDREND-LOADER
	
	ORG	$6000

* THIS IS THE ENTRY POINT WHEN THIS LOADER IS BROUGHT INTO RAM
* USING SWTBUG "L" COMMAND. IN THIS CASE, THE PROGRAM IS LOADED AT
* ITS ASSEMBLED ADDRESS.
	
BOOT2	CLR	DRV		DRIVE 0
	JSR	RESTOR		RESTORE TO TRACK 0
	LDAA	#1		READ SECTOR 1
	STAA	SECT
	CLR	SIDE
	CLR	TRK
	LDX	#SECTOR1	ADDRESS OF WHERE TO PUT THE SECTOR
	STX	DDATA
	JSR	RDSEC
	JMP	LOADER

* TO START THE LOADER WITH SWTBUG "G" COMMAND

	ORG	$A048
	FDB	BOOT2		

	END
