;
;	Serial BOOTLOADER aka BOOT.SYS
;	V1.0 2025 TB
;


;START_ADR = $0B00		; Version for 4k systems
;START_ADR = $1B00		; Version for 8k systems
START_ADR = $3B00		; Version for 16k systems
;START_ADR = $5B00		; Version for 24k systems
;START_ADR = $7B00		; Version for 32k systems
;START_ADR = $9B00		; Version for 40k systems
BASICPLUS = START_ADR + $01C0
LOADER    = $02D8-14		; Loader start address
				; 14 bytes header
	; JMP 	LOADER		; $02D8-14
	;.DB	$0		; TYPE 0=BAS(TXT) 1=LOD, 2=PRG(BIN)
	;.DB	$0		; ACTION 0=LOAD >0=SAVE
	;.DB	$0, $0		; START for save
	;.DB	$0, $0		; END for save
	;.DB	<Path, >Path
	;.DB	<File, >File
	;.DB	$0		; AUTOSTART 0=not >0=yes for BASIC only


BASIC_LPT = $00BC		; Basic Line Processing Vector in Zero-Page
RESET     = $FFFC
BOOT	  = $FF00
KEY	  = $FD00
Monitor   = $FE00
TextOut	  = $BF2D
Screen    = $D000
LOD	  = $FE2A
LODFLAG   = $FB
POS	  = $FC
DATA	  = $FD
BASFLAG	  = $0203
Selector  = $D105

ACIA_S = $F000
ACIA_D = $F001
TMP    = $FE			; Return Address on RESTORE

	.ORG	START_ADR-2	; In free Memory
	.DB	<START_ADR
	.DB	>START_ADR
	
	.ORG	START_ADR	; In free Memory

	JMP	MENU

; ********************+*************************************
; ***************** internal LOADER ************************
;
	
EXLOAD:	LDA	ACIA_D		; Clean up any pending byte
	LDA	#$71
	STA	ACIA_S
	LDA	#$30
	JSR 	ACIA_WRITE	; Check SD card
	JSR	ACIA_READ
	BNE	LD		; SD card found ?

STOP:	JMP 	BOOT


LD:	LDA	#$71
	STA	ACIA_S
	LDA	#$35
	JSR 	ACIA_WRITE	; Define Path
		
	LDA	LOADER+9
	STA	TMP
	LDA	LOADER+10
	STA	TMP+1
	LDY	#0
LD0:	LDA 	(TMP),y
	INY
	JSR 	ACIA_WRITE
	BEQ	LD_SECOND
	BNE	LD0
	
LD_SECOND:
	LDA	#$71
	STA	ACIA_S
	LDA	#$33
	JSR 	ACIA_WRITE	; Define Filename

	LDA	LOADER+11
	STA	TMP
	LDA	LOADER+12
	STA	TMP+1
			
	LDY	#0
L1:	LDA 	(TMP),y
	INY
	JSR 	ACIA_WRITE
	BNE	L1

L2:	LDA	LOADER+5	; START for SAVE
	STA	TMP
	LDA	LOADER+6
	STA	TMP+1
	
	LDA	LOADER+4
	BEQ	SDLOAD

SDSAVE:	BNE	STOP		; not yet implemented

SDLOAD:
	LDA	#$71
	STA	ACIA_S
	LDA	#$39
	JSR 	ACIA_WRITE	; Get File
	
	JSR	ACIA_READ	; Lengh ignored BASIC text files
	TAX			; Low in X
	JSR	ACIA_READ
	TAY			; High in Y
	BNE	NX0
	TXA
	BEQ	STOP		; File not found or empty

NX0:	LDA	LOADER+3	; CHECK TYPE 0=BAS 1=LOD, 2=PRG
	BNE	NX1		; BASIC TEXT file ?
	LDA	#$FF
	STA	BASFLAG
	JMP	0		; Go to BASIC
NX1:	CMP	#1		; LOD file ?
	BNE	NX2
	STA	LODFLAG
	JMP	LOD		; Go to ROM LOD loader	

NX2:	TXA			; substract 2 of file length
	BNE	LD21
	DEY
LD21:	DEX
	BNE	LD22
	DEY
LD22:	DEX
	
	
LD4:	JSR	ACIA_READ	; PRG file Start adress
	STA	LDAD+1
	STA	TMP
	JSR	ACIA_READ
	STA	LDAD+2
	STA	TMP+1

LD5:	JSR	ACIA_READ
LDAD:	STA	$8888		; Store
	INC	LDAD+1
	BNE	LD6
	INC	LDAD+2
LD6:	TXA
	BNE	LD7
	DEY
LD7:	DEX
	BNE	LD5
	TYA
	BNE	LD5
	JMP	(TMP)

; ********** Routines for ACIA ***********

	
ACIA_READ:
	LDA	ACIA_S		;(4)
	LSR			;(2)
	BCC	ACIA_READ	;(2), (3)
	LDA	ACIA_D		;(4)
	RTS			;(6) sum min (18)
	
ACIA_WRITE:
	PHA
WR1:	LDA	ACIA_S
	AND	#$02
	BEQ	WR1
	PLA
	STA	ACIA_D	
	RTS
	

; ********** Routines for MENU ***********	

CLS:	LDY	#0
	LDA	#$20
CL1:	STA	Screen,y
	STA	Screen+$100,y
	STA	Screen+$200,y
	STA	Screen+$300,y
	INY
	BNE	CL1
CLR:	RTS

TEXTP:	STY	TMP		; Print text info from position X,Y
	STX	TMP+1
	LDY	#0
	LDA	(TMP),Y		; Start address on screen
	STA	TX+1
	INY
	LDA	(TMP),Y
	STA	TX+2
TXL:	INY
	LDA	(TMP),Y		; text to display
	BEQ	CLR		; ends with zero
TX	STA	$8888
	INC	TX+1
	BNE	TXL
	INC	TX+2
	BNE	TXL		; always
	
CLRLN:	CLC
	LDA	TMP
	ADC	#$40		; Next line in double line mode
	STA	TMP
	BCC	CLR0
	INC	TMP+1
CLR0:	LDA	TMP+1
	CMP	#$D3
	BEQ	CLRE
	LDA	#$20		; Clean line
	LDY	#38
CLR1:	STA	(TMP),Y
	DEY
	BPL	CLR1
	LDA	#1
CLRE:	RTS			; zero flag is set at end of screen

Display_FN:
	LDY	#0
DI0:	LDA	FN,Y
	STA	$D345,Y
	BEQ	DI1
	INY
	BNE	DI0
DI1:	LDA	#$20
	STA	$D345,Y
	INY
	CPY	#25
	BNE	DI1
	RTS

Display_PA:
	LDY	#0
DI2:	LDA	PA,Y
	STA	$D385,Y
	BEQ	DI3
	INY
	BNE	DI2
DI3:	LDA	#$20
	STA	$D385,Y
	INY
	CPY	#33
	BNE	DI3
	RTS
			
; ********************+*************************************
; ***************** MENU @ BASICPLUS position **************
;

	.ORG	BASICPLUS

MENU: 	LDA	#$4C		; Prepare Jump address
	STA	LOADER
	LDA	#<EXLOAD
	STA	LOADER+1
	LDA	#>EXLOAD
	STA	LOADER+2
	LDY	#11
	LDA	#0
IN:	STA	LOADER+2,Y	; Clear header
	DEY
	BNE	IN
	
	LDA	#$E6		; Restore old BASIC vector
	STA	BASIC_LPT
	LDA	#$C3
	STA	BASIC_LPT+1
	LDA	#$D0
	STA	BASIC_LPT+2

		
	LDA	#$FF		; Set Top of Ram to startaddress-1
	STA	$81
	STA	$85
	LDA	#>START_ADR-1
	STA	$82
	STA	$86
	JSR	CLS
	LDX	#>INF1
	LDY	#<INF1
	JSR	TEXTP
	LDX	#>WA4
	LDY	#<WA4
	JSR	TEXTP

	LDA	0		; Needs to take place here !!!
	CMP	#$4C		; Check for active BASIC
	BEQ	CHECKCARD	; No BASIC COLD START
	LDX	#>WA1
	LDY	#<WA1
	JMP	MERR

CHECKCARD:
	LDA	ACIA_D		; Clean up any pending byte
	LDA	#$71
	STA	ACIA_S
	LDA	#$30
	JSR 	ACIA_WRITE	; Check SD card
	JSR	ACIA_READ
	BNE	CARDOK		; SD card found ?
	LDX	#>WA2
	LDY	#<WA2
MERR:	JSR	TEXTP
MLEAVE:	LDX	#>WA3
	LDY	#<WA3
	JSR	TEXTP
	JSR	KEY
	JMP	STOP

CARDOK: LDA	#1
	STA	POS		; Pos from on direcrory is shown

DIRL:	LDA	ACIA_D		; Clean up any pending byte
	LDX	#0		; first line in D0E7 + 40 = D127
	LDA	#$C7		; to be able to clear next line
	STA	TMP		; Good for 8 lines until D300
	LDA	#$D0
	STA	TMP+1
	LDA	#'>'		; Selection cursor
	STA	Selector
	JSR	CLRLN		; set and clear next line
	
	LDA	#$71
	STA	ACIA_S
	LDA	#$35
	JSR 	ACIA_WRITE	; Start Path
		
	LDY	#0
PA1:	LDA 	PA,y
	INY
	JSR 	ACIA_WRITE
	BNE	PA1		; until end of Path

	LDA	#$71
	STA	ACIA_S
	LDA	#$36
	JSR 	ACIA_WRITE	; Get Directory
	BNE	DLR		; always jump
	
DLC:	CPX	POS
	BCC	DLR
	JSR	CLRLN		; set and clear next line
	BEQ	DLREST		; end of screen reached ?
	
DLR:	INX			; first line is 1
	LDY	#0
	JSR	ACIA_READ
	BEQ	LEA0		; End of directory ?
	BNE	DL2	
DL1:	JSR	ACIA_READ
	BEQ	DLC		; End of string ?
DL2:	CPX	POS
	BCC	DL1		; read empty, if X<POS
	STA	(TMP),Y		; TextOut
	INY
	JMP	DL1

DLREST: JSR	ACIA_READ
	BEQ	LEA0		; End of directory ?
	
	LDA	#$03		; Ends DIR Process  (needs to be in active data transfer !!)
	STA	ACIA_S
	JSR	ACIA_READ	; Get confirmation for break

LEA0:	JSR	CLRLN		; End of directory list, Clear rest of screen
	BNE	LEA0		; until end of screen


	
LEAVE:	JSR 	KEY		; ****** KEY Input *********
	LDX	#$80		; some delay for the SD Card
LEAD:	DEX
	BNE 	LEAD
	
	CMP	#$1B		; ESCAPE to go back to Monitor
	BNE	LEA1
	JMP	STOP
	
LEA1:	CMP	#'.'		; > to step one down
	BNE	LEA2
	INC	POS
LEAR:	JMP	DIRL
	
LEA2:	CMP	#','		; < to step one up
	BNE	LEA3
	DEC	POS
	BNE	LEAR
	INC	POS		; Lowest POS is 1
	BNE	LEAR
	
LEA3:	CMP	#$0D		; RETURN File/path selected?
	BEQ	LEA40
	CMP	#'/'		; Back to ROOT
	BNE	LEAR		
	LDA	#0		; Back to root
	STA	PA
	JSR	Display_PA	; in this case clear
	JMP	CARDOK

; ****************************************************
	
LEA40:	LDY	#0		; Execute program or go into subdirectory
LEA4:	LDA	Selector+2,Y
	CMP	#$20		; End of name ?
	BEQ	LEA5	
	CMP	#'['		; Folder indicator
	BEQ	LEA6	
	STA	FN,Y		; Transfer File name
	INY
	CPY	#23
	BNE	LEA4
LEA5:	LDA	#0		; terminate with 00
	STA 	FN,Y
	JSR	Display_FN

	LDY	#0		; Check extension
EXT0:	LDA	FN,Y
	BEQ	LEAR		; nothing found
	CMP	#'.'
	BEQ	EXT1		; dot found ?
	INY
	BNE	EXT0		; always jump
EXT1:	INY
	LDA	FN,Y
	BEQ	LEAR		; nothing found
	
	LDY	#0		; filetype in Y
	AND	#$DF		; capital letter
	CMP	#'B'		; BAS	
	BEQ	EXT2		; Type 0
	INY
	CMP	#'L'		; LOD
	BEQ	EXT2
	CMP	#'6'		; 65V
	BEQ	EXT2
	CMP	#'H'		; HEX
	BEQ	EXT2		; Type 1
	INY
	CMP	#'P'		; PRG
	BEQ	EXT2		; Type 3
	BNE	LEAR		; unknown, do nothing
	
EXT2:	STY	LOADER+3	; Setup and execute pogram
	LDA	#0
	STA	LOADER+4
	LDA	#<PA
	STA	LOADER+9			
	LDA	#>PA
	STA	LOADER+10			
	LDA	#<FN
	STA	LOADER+11			
	LDA	#>FN
	STA	LOADER+12
	JSR	CLS
	JMP	LOADER		; Back to internal LOADER	
	
LEA6:	INY			; **** Folder selected ****
	INY
	TYA
	PHA
	
	LDA	#<PA		; Check end of existing path
	STA	TMP
	LDA	#>PA
	STA	TMP+1
		
	LDY	#$FF
LEA61:	INY
	LDA	(TMP),Y
	BNE	LEA61
	CPY	#0		; Are we already down the path ?
	BEQ	LEA62
	LDA	#'/'
	STA	(TMP),Y
	INY

LEA62:	PLA
	TAX	
	
LEA7:	LDA	Selector+2,X
	CMP	#$20
	BEQ	LEA8	
	STA	(TMP),Y		; Transfer PATH name
	INX
	INY
	CPY	#31		; Max path length ?
	BCC	LEA7
	
LEA8:	LDA	#0
	STA 	(TMP),Y
	JSR	Display_PA
	JMP	CARDOK		; Restart in new folder
	

WA1:	.db $A5,$D0
	.ASCII "BASIC COLDSTART NEEDED !",0
WA2:	.db $A5,$D0
	.ASCII "NO SD CARD INSERTED",0
WA3:	.db $C5,$D0
	.ASCII "<PRESS ANY KEY>",0
WA4:	.db $86,$D0
	.ASCII " *** OSI SD-MENU V1 ***",0
	
INF1:	.db $25,$D3	
	.ASCII "KEY: >FWD <BWD /HOME ESC",0
	
FN:	.DCB 24,$00
PA:	.DCB 32,$00

