; **********************
; *  Black Rabbit 2.0  *
; **********************
;
; Highspeed sector copier
; for single-drive systems
;
; by Brian Moriarty
; ANALOG Compendium Volume 1
;
; OS disk handler equates
;
DEVNUM	= $0301
DCOMND	= $0302
DSTATS	= $0303
DBUFLO	= $0304
DBUFHI	= $0305
SECTLO	= $030A
SECTHI	= $030B
DVSTAT	= $02EB
DISKIO	= $E453
;
; Disk handler commands
;
READ	= $52
WRITE	= $57
FORMAT	= $21
;
; Misc. system equates
;
COLDST	= $0244
BOOT?	= $09
SAVMSC	= $58
COLOR2	= $02C6
OLDADR	= $5E
CONSOL	= $D01F
RAMTOP	= $6A
AUDF1	= $D200
AUDC1	= $D201
RTCLOK	= $14
ATRACT	= $4D
COLDSV	= $E477
;
; Internal program equates
;
RTOTAL	= $80
WTOTAL	= $82
BPOINT	= $84
PPOINT	= $86
SCREEN	= $88
VTOC	= $8A
LINE	= $8C
SAVEY	= $8E
SBYTE	= $8F
FFLAG	= $90
;
; Characters for "Visible VTOC"
;
DOT	= $0E
DATA	= $80
BAD	= $1F
WRITTEN	= $8E
NOTHING	= $10
;
; Memory usage
;
DUMMY	= $0400 	; Dummy buffer
ORIGIN	= $0480 	; Program start
BUFFER	= $0780 	; Data buffer
;
	*= ORIGIN
;
; 6 bytes to control boot-up
;
	.BYTE $00,$06 	; # boot sects
	.BYTE ORIGIN&255,ORIGIN/256
	.BYTE ENTRY&255,ENTRY/256
;
ENTRY
;
; Init screen line pointer
;
	LDA #0
	TAY 
	STA (OLDADR),Y 	; Kill cursor
	JSR TOPLINE
;
; Check for 48K RAM
;
	LDA RAMTOP
	CMP #$C0 	; $C0 = 48K
	BCS RABBIT 	; > OR = 48K
;
; Print RAM warning
;
	LDA #WARNING&255
	STA PPOINT
	LDA #WARNING/256
	JSR MESSAGE
;
FREEZE
	JMP FREEZE 	; Infinite loop
;
; ********************
; *  Initialize R/W  *
; ********************
;
RABBIT
;
; Initialize important things
;
	LDX #0 	; Black
	STX COLOR2 	; Background
	STX RTOTAL+1 	; Clear MSB
	STX WTOTAL+1 	; Ditto
	STX COLDST 	; Coldstart flag
	INX  	; X = 1
	STX RTOTAL 	; LSB
	STX WTOTAL 	; Ditto
	STX BOOT? 	; Boot flag
	STX DEVNUM 	; Drive #1
	STX FFLAG 	; Format enable
;
; Setup VTOC screen pointer
;
	CLC 
	LDA SAVMSC 	; Addr of screen
	ADC #239 	; 6 lines down
	STA SCREEN
	STA VTOC
	LDA SAVMSC+1
	ADC #0
	STA SCREEN+1
	STA VTOC+1
;
; Print title
;
	JSR TOPLINE
	LDA #TITLE&255
	STA PPOINT
	LDA #TITLE/256
	JSR MESSAGE
;
; Reset screen pointer
;
	CLC 
	LDA SAVMSC
	ADC #122 	; X=2, Y=3
	STA LINE
	BCC DODOTS
	INC LINE+1
;
; Init VTOC display matrix
;
DODOTS
	INC VTOC
	BNE MATRIX
	INC VTOC+1
MATRIX
	LDX #2
LOOP1
	LDY #0
	LDA #DOT
LOOP2
	STA (VTOC),Y
	INY 
	CPY #240
	BNE LOOP2
	CLC 
	LDA VTOC
	ADC #240
	STA VTOC
	BCC MORE
	INC VTOC+1
MORE
	DEX 
	BPL LOOP1
;
; ******************
; *  READ Routine  *
; ******************
;
READER
;
; Reset buffer addr pointers
;
	JSR REPOINT
;
; Update VTOC pointer
;
	CLC 
	LDA SCREEN
	ADC RTOTAL
	STA VTOC
	LDA SCREEN+1
	ADC RTOTAL+1
	STA VTOC+1
;
; Print READ prompt
;
	LDA #RPROMPT&255
	STA PPOINT
	LDA #RPROMPT/256
	JSR MESSAGE
;
	JSR WAIT 	; START key
;
	LDA #READ
	STA DCOMND 	; Set READ mode
;
; ************************
; *  Start of READ loop  *
; ************************
;
RLOOP
;
; Update sector #
;
	LDA RTOTAL
	STA SECTLO
	LDA RTOTAL+1
	STA SECTHI
;
	JSR DISKIO 	; Fetch sector
	LDA DSTATS 	; Check status
	BPL SECSTAT 	; Branch if okay
	LDA #BAD
	BNE SHOWSTAT
;
; Check sector data for status
;
SECSTAT
	LDY #$7F
NEXTBYTE
	LDA (BPOINT),Y
	BNE DATAID
	DEY 
	BPL NEXTBYTE
	LDA #NOTHING
	BNE SHOWSTAT
DATAID
	LDA #DATA
SHOWSTAT
	STA SBYTE
	LDY #0
	STY ATRACT 	; Attract off
	STA (VTOC),Y
;
; Update VTOC addr pointer
;
	INC VTOC
	BNE UPCOUNT
	INC VTOC+1
UPCOUNT
	INC RTOTAL
	BNE SECTMAX
	INC RTOTAL+1
;
; End of disk?
;
SECTMAX
	LDA RTOTAL+1
	CMP #$02
	BNE DATACHECK
	LDA RTOTAL
	CMP #$D1
	BEQ WRITER
;
; Check for data sector
;
DATACHECK
	LDA SBYTE
	CMP #DATA
	BNE RLOOP
;
; Add 128 to buffer pointers
;
	CLC 
	LDA DBUFLO
	ADC #$80
	STA DBUFLO
	STA BPOINT
	LDA DBUFHI
	ADC #0
	STA DBUFHI
	STA BPOINT+1
;
; Check if buffer full
;
	CMP #$BC 	; Top of buffer?
	BNE RLOOP 	; No; keep going
;
; *******************
; *  WRITE Routine  *
; *******************
;
WRITER
;
; Init VTOC pointer
;
	CLC 
	LDA SCREEN
	ADC WTOTAL
	STA VTOC
	LDA SCREEN+1
	ADC WTOTAL+1
	STA VTOC+1
;
; Print WRITE prompt
;
	LDA #WPROMPT&255
	STA PPOINT
	LDA #WPROMPT/256
	JSR MESSAGE
;
	JSR WAIT 	; START key
;
	DEC FFLAG
	BNE NOFORM 	; Skip if Pass 2
;
; Format disk
;
ERASE
	JSR DUMPOINT 	; buffer addr
	LDA #FORMAT
	STA DCOMND 	; format cmnd
	JSR DISKIO 	; Do it!
;
; Check for okay format
;
	LDA DSTATS
	CMP #1
	BEQ NOFORM
;
; Print bad format warning
;
	LDA #BADFORM&255
	STA PPOINT
	LDA #BADFORM/256
	JSR MESSAGE
	JSR WAIT
	BEQ ERASE
;
NOFORM
;
	JSR REPOINT 	; Reset pntrs
;
	LDA #WRITE
	STA DCOMND 	; WRITE command
;
; *************************
; *  Start of WRITE loop  *
; *************************
;
WLOOP
;
; Update setor #
;
	LDA WTOTAL
	STA SECTLO
	LDA WTOTAL+1
	STA SECTHI
;
; Get status of next read
;
	LDY #0
	STY ATRACT
	LDA (VTOC),Y
	STA SBYTE
;
; Branch depending on status
;
	CMP #DATA
	BNE SKIPSECT 	; If no data
;
DWRITE
	JSR DISKIO 	; Write sector
	BMI DWRITE
;
; Display write status
;
SKIPSECT
	LDA #WRITTEN
	LDY #0
	STA (VTOC),Y
;
; Update VTOC, WTOTAL
;
	INC VTOC
	BNE WRUP
	INC VTOC+1
WRUP
	INC WTOTAL
	BNE WSECTMAX
	INC WTOTAL+1
WSECTMAX
	LDA WTOTAL+1
	CMP #$02
	BNE BUFLOOK
	LDA WTOTAL
	CMP #$D1
	BEQ FINISHED
;
; Should buffer addr be updated?
;
BUFLOOK
	LDA SBYTE
	CMP #DATA 	; Update bufadr?
	BNE WLOOP 	; No; next sect
;
; Update buffer address
;
	CLC 
	LDA DBUFLO
	ADC #$80
	STA DBUFLO
	LDA DBUFHI
	ADC #0
	STA DBUFHI
;
; Buffer full?
;
FULBUF
	CMP #$BC
	BNE WLOOP
	JMP READER 	; Next pass
;
; *****************
; *  End routine  *
; *****************
;
FINISHED
	LDA #COMPLETE&255
	STA PPOINT
	LDA #COMPLETE/256
	JSR MESSAGE
DECIDE
	LDA CONSOL
	CMP #6 	; START press?
	BEQ RERUN
	CMP #3 	; OPTION?
	BNE DECIDE
	JSR LETGO
	JMP COLDSV 	; Cold boot
RERUN
	JSR LETGO
	JMP RABBIT 	; Re-run Rabbit
;
; *****************
; *  Subroutines  *
; *****************
;
; Point to dummy buffer
;
DUMPOINT
	LDA #DUMMY&255
	STA DBUFLO
	LDA #DUMMY/256
	STA DBUFHI
	RTS 
;
; Point to top screen line
;
TOPLINE
	CLC 
	LDA SAVMSC
	ADC #42 	; X=2, Y=1
	STA LINE
	LDA SAVMSC+1
	ADC #0
	STA LINE+1
	RTS 
;
; Beep and wait for START key
;
WAIT
	LDA #100 	; Freq = 100
	STA AUDF1
	LDA #$AA 	; D & V = 10
	STA AUDC1
	LDA #0
	STA RTCLOK 	; Clear count
BEEP
	LDA RTCLOK
	CMP #15 	; 1/4 sec
	BNE BEEP
	LDA #0
	STA AUDC1 	; Silence!
;
; Check key
;
HOLDIT
	LDA CONSOL
	CMP #6
	BNE HOLDIT 	; Pressed?
LETGO
	LDA CONSOL
	CMP #7
	BNE LETGO 	; Till released
	RTS 
;
; Print text messages
;
MESSAGE
	STA PPOINT+1
	LDY #33
NEXTPRINT
	LDA (PPOINT),Y
	STA (LINE),Y
	DEY 
	BPL NEXTPRINT
	RTS 
;
; Set buffer pointers
;
REPOINT
	LDA #BUFFER&255
	STA BPOINT
	STA DBUFLO
	LDA #BUFFER/256
	STA BPOINT+1
	STA DBUFHI
	RTS 
;
; *******************
; *  Message texts  *
; *******************
;
WARNING
	.SBYTE "Remove cartridge; requires 48K RAM"
;
TITLE
	.SBYTE "Black Rabbit 2.0 by Brian Moriarty"	;!!!!!!!! INVERSE CHARS !!!!!!!!
;
RPROMPT
	.SBYTE "Insert SOURCE disk, press START   "	;!!!!!!!! INVERSE CHARS !!!!!!!!
;
WPROMPT
	.SBYTE "Insert COPY disk, press START     "	;!!!!!!!! INVERSE CHARS !!!!!!!!
;
COMPLETE
	.SBYTE "START to re-run, OPTION to boot   "	;!!!!!!!! INVERSE CHARS !!!!!!!!
;
BADFORM
	.SBYTE "Replace bad COPY disk, press START"	;!!!!!!!! INVERSE CHARS !!!!!!!!
;
	.END 
