NEW
PREFIX
AUTO 4,1
				.LIST OFF
				.OP	65C02
				.OR	$2000
				.TF SYS/KM.RAMWORKS
*--------------------------------------
				.INB INC/MACROS.I
				.INB INC/IO.I
				.INB INC/MONITOR.I
				.INB INC/MLI.I
				.INB INC/MLI.E.I
*--------------------------------------
TmpPtr1			.EQ	$0
TmpPtr2			.EQ	$2
*--------------------------------------
RW.SAVEZP0		.EQ $800
RW.SAVEZP1		.EQ $900
*--------------------------------------
RW.BLOCK		.EQ $A00
*--------------------------------------
* A2OSX.SYSTEM relocated at $1000 !!!
*--------------------------------------
RWBankSelect	.EQ $C073
*--------------------------------------
RW.Init			>LDYAI RW.MSG
				jsr PrintFYA
				
				jsr RW.Detect1
				bcs .10

				>LDYAI RW.MSG.OK
				jsr PrintFYA
				
				rts

.10				jsr RW.Detect2
				bcc .1
				
				>LDYAI RW.MSG.KO1
				jsr PrintFYA
				rts
				
.1				pha						Push Page count

				lsr						divide by 4 to compute KB size
				ror .11+1
				lsr
				ror .11+1

.11				ldx #$00
				phx						Push Kbyte LO
				pha						Push Kbyte HI

				>LDYAI RW.MSG.OK1
				jsr PrintFYA

				jsr RW.Install
				bcc .2

				>LDYAI RW.MSG.KO2
				jsr PrintFYA
				rts

.2				>LDYAI RW.MSG.OK2
				jsr PrintFYA

				jsr RW.Format
				bcc .3

				>LDYAI RW.MSG.KO3
				jsr PrintFYA
				rts
				
.3				>LDYAI RW.MSG.OK3
				jsr PrintFYA
				rts
*--------------------------------------
RW.Detect1		jsr MLI
				.DA #MLIONLINE
				.DA RW.ONLINE
				rts
*--------------------------------------
RW.ONLINE		.DA #2
				.DA #$B0				Slot 3,Drive 2
				.DA RW.ONLINEBUFFER
RW.ONLINEBUFFER	.BS 16
*--------------------------------------
RW.Detect2		php
				sei
				sta SETALTZP
				
				ldx #0					start detection at page $00
				
.1				stx RWBankSelect
				lda 0
				sta RW.SAVEZP0,x	save Bank 0 $0000 to prevent ALTZP trash
				lda 1
				sta RW.SAVEZP1,x
				inx
				bpl .1
				
				lda #0
				
.2				sta RWBankSelect

*--------------------------------------
* Added after David Finnigan from macgui.com testing sessions
*	
				pha
				pla
* 
* to address possibly a timing issue with Accelerators
*--------------------------------------
				
				sta 0
				eor #$FF
				sta 1
				eor #$FF
				inc
				bpl .2
				
				ldx #0
				
.3				txa
				sta RWBankSelect
				
*--------------------------------------
* Added after David Finnigan from macgui.com testing sessions
*	
				pha
				pla
* 
* to address possibly a timing issue with Accelerators
*--------------------------------------

				cmp 0
				bne .4
				eor #$FF
				cmp 1
				bne .4
				
				inx
				bpl .3
				
.4				dex						we reached 128,last detected page was 127
				
				ldy #127				X = detected page count 

.6				sty RWBankSelect

				lda RW.SAVEZP0,y
				sta 0
				lda RW.SAVEZP1,y
				sta 1
				dey
				bpl .6

				txa
										
				stx	RW.PGCNT			PGCNT = last detected page, as we do -1 for AuxMem
				
				sta CLRALTZP
				plp
				lda RW.PGCNT
				beq .9
				
				clc
				rts
				
.9				sec				
				rts
*--------------------------------------
RW.Install		lda RRAMWRAMBNK1
				lda RRAMWRAMBNK1
				
				ldx #RWDRV.SIZE
.1				lda RWDRV.B.START-1,x
				sta RWDRV.START-1,x
				dex
				bne .1
				
				lda RW.PGCNT
				lsr
				sta RWDRV.MAXHI+1
				lda #0
				ror
				sta RWDRV.MAXLO+1
				
				lda RROMBNK1
				
				sta SETWRITEAUX
				
				ldx #RWDRVX.SIZE
.2				lda RWDRVX.B.START-1,x
				sta RWDRVX.START-1,x
				dex
				bne .2
				
				sta CLRWRITEAUX
				
				inc DEVCNT
				ldx DEVCNT
				lda #$B0				Slot 3,Drive 2,0=Not Removable, 0=no int, 00=1 Volume
				sta DEVLST,x
				
				lda #RWDRV.START
				sta DEVPTRS3D2
				lda /RWDRV.START
				sta DEVPTRS3D2+1
				clc
				rts
*--------------------------------------
RW.Format		jsr RW.BLOCK.SET00
				
				lda RW.PGCNT
				lsr
				sta RW.BLOCK2.TB+1
				lda #0
				ror
				sta RW.BLOCK2.TB
				
				jsr MLI
				.DA #MLIGETTIME
				.DA 0
				
				ldx #3
.1				lda DATELO,x				
				sta RW.BLOCK2.CT,x
				dex
				bpl .1
				
				ldx #RW.BLOCK2.END-RW.BLOCK2
.2				lda RW.BLOCK2-1,x
				sta RW.BLOCK-1,x
				dex
				bne .2

				jsr MLI					Write Block 2,First VOL directory block
				.DA #MLIWRITEBLOCK
				.DA RW.MLIWRITEBLOCK
				bcc .22
				rts
*--------------------------------------
.22				jsr RW.BLOCK.SET00

				lda #2
				sta RW.BLOCK			LO byte of previous block pointer

				inc RW.MLIWRITEBLOCK.BLK
				jsr MLI					Write Block 3,Last VOL directory block
				.DA #MLIWRITEBLOCK
				.DA RW.MLIWRITEBLOCK
				bcc .33
				rts
*--------------------------------------
.33				lda RW.PGCNT			divide RW.PGCNT by 32 to get how many bitmap
				lsr						blocks we need :
				lsr						1 page = 128 blocks = 16 bytes
				lsr						32 pages = 512 bytes = 1 Block
				lsr
				lsr
				sta RW.FBITMAPCNT		store FULL bitmap block count needed

				tax
				lda RW.PGCNT
				and #$1F				need an extra incomplete bitmap block?
				beq .3
				inx
.3				stx RW.BITMAPCNT		store TOTAL bitmap block needed
			
.4				lda RW.FBITMAPCNT
				beq .49
				
				dec RW.FBITMAPCNT
				jsr RW.BLOCK.SETFF

				bra .5
			
.49				jsr RW.BLOCK.SET00
				
				lda RW.PGCNT
				and #$1F				compute incomplete bitmap block
				asl
				asl
				asl
				asl						times 16 for byte count
				tay
				lda #$FF
				bcc	.42					first half of block only	
				
				ldx #0
.40				sta RW.BLOCK,x
				inx
				bne .40
				
				cpy #0
				beq .5
.41				sta RW.BLOCK+$ff,y
				dey
				bne .41
				
				bra .5
				
.42				sta RW.BLOCK-1,y
				dey
				bne .42
				
.5				inc RW.MLIWRITEBLOCK.BLK
				lda RW.MLIWRITEBLOCK.BLK
				cmp #4					Are we writing first volume bitmap ?
				bne .63					no, regular one

*				lda #$CF				Mark Block 0 & 1 free, 2,3 used (vol hdr)
				lda #$0F
				sta RW.BLOCK			
				
				ldy #0
				lda #$8					Start a BLOCK 4 (%00001000)
				ldx RW.BITMAPCNT
				
.62				pha
				eor RW.BLOCK,y			Mark bitmap blocks as "used"
				sta RW.BLOCK,y
				pla
				dex
				beq .63
				lsr
				bne .62
				lda #$80				
				iny
				bra .62
				
.63				jsr MLI					Write Block 4,5...
				.DA #MLIWRITEBLOCK
				.DA RW.MLIWRITEBLOCK
				bcs .9
				
				dec RW.BITMAPCNT		another bitmap block needed ?
				bne .4
				
				clc
.9				rts				
*--------------------------------------
RW.BLOCK.SETFF	lda #$FF
				bra RW.BLOCK.SET
RW.BLOCK.SET00	lda #$00
RW.BLOCK.SET	ldx #0
.1				sta	RW.BLOCK,x
				sta RW.BLOCK+$100,x
				inx
				bne .1
				rts
*--------------------------------------
RW.MLIWRITEBLOCK
				.DA #3
				.DA #$B0				Slot 3,Drive 2
				.DA RW.BLOCK
RW.MLIWRITEBLOCK.BLK
				.DA 2					Start writing block at #2
*--------------------------------------
RW.PGCNT		.BS 1
RW.FBITMAPCNT	.BS 1
RW.BITMAPCNT	.BS 1
*--------------------------------------
RW.BLOCK2		.DA 0					pointer to previous block
				.DA 3					pointer to next block
				.DA #$F4				$F=Vol Dir Header, 4=name len
				.AS 'RAM3'
				.BS 11					(RAM3 len=4, fill to 15)
				.HS 0000000000000000
RW.BLOCK2.CT	.BS 4					Creation time
				.HS 0100C3270D			version/min version/access/EL/EPB
				.DA 0					File Count
				.DA 4					bitmap pointer (Block 2&3 are Volume directory)
RW.BLOCK2.TB	.BS 2					Total Blocks
RW.BLOCK2.END	.EQ *
*--------------------------------------
				.INB USR/SRC/X.PRINTF.S
*--------------------------------------
RW.MSG			.AZ "RAMWorks (I,II,III,z-Ram) Driver For A2osX\n"
RW.MSG.OK		.AZ "/RAM3 Device Already Installed.\n"
RW.MSG.OK1		.AZ "%D KB (%d Pages) Available for RamDrive.\n"
RW.MSG.KO1		.AZ "Not Detected.\n"
RW.MSG.OK2		.AZ "RamWorks Driver Installed.\n"
RW.MSG.KO2		.AZ "RamWorks Driver Install Error.\n"
RW.MSG.OK3		.AZ "RamWorks Drive Formatted as /RAM3.\n"
RW.MSG.KO3		.AZ "RamWorks Drive Format Error.\n"
*--------------------------------------
* Driver for Ramworks in main LC
* $FF00 -> $FF9A (Inclusive)
* $FF58	MUST BE $60 (RTS)
* DO NOT trash DRV.COMMAND...DRV.BLKNUM as ProDOS 
* reuses it after Block operation
* A1,A2 are used by Disk II Driver, 
* so we use it safely as Tmp Ptr
*--------------------------------------
DRV.A2L			.EQ $3E
DRV.A2H			.EQ $3F
DRV.COMMAND 	.EQ $42
DRV.BUFF		.EQ $44        
DRV.BLKNUM		.EQ $46        
*--------------------------------------
RWDRV.B.START
				.PH	$FF00
RWDRV.START		cld						ProDOS will check that byte!!!
				ldy DRV.COMMAND			0 = Status ?
				beq RMDRV.CMDSTATUS
				
				cpy #3
				beq RWDRV.EXITOK		3 = Format : nothing to do, exit with no error
				bcs RWDRV.IOERR			> 3 = Invalid OP, IO error

				lda DRV.BLKNUM
				sbc RWDRV.MAXLO+1		Carry is Clear 
				lda DRV.BLKNUM+1
				sbc RWDRV.MAXHI+1
				bcs	RWDRV.IOERR			DRV.BLKNUM >= RW.DRV.SIZE, IO error
				
				lda DRV.BLKNUM			Get Back DRV.BLKNUM
				asl						compute PAGE = blocknumLO *2
				pha
				lda DRV.BLKNUM+1		compute BANK = blocknumHI *2
				rol
				inc 					+1 for skipping Aux BANK 0
				plx						move page into X
				beq RWDRV.GOAUX			move from/to aux page0/1
				cpx #$C0
				bcs RWDRV.GOAUX			move from/to aux LC
*--------------------------------------
* X=Page($02 -> $BF),A=Bank,Y=CMD
*--------------------------------------
*				php
				sei						Disable IRQ as no vector set in RW Banks
				sta RWBankSelect		Select RAMWorks Bank
				sta CLR80STORE			make sure SETREADAUX/SETWRITEAUX effective everywhere

				inx						second 256 bytes first
				stx DRV.A2H				Use DRV.A1L/H for RAM PTR
				stz DRV.A2L
				
				inc DRV.BUFF+1
				
				dey						Y=CMD, zero if read
				bne RWDRV.W				non zero, go write
				
				sta SETREADAUX
				ldx #DRV.A2L			READ:copy from RAM to BUFF
				lda #DRV.BUFF
				bra RWDRV.RW
				
RWDRV.W			sta SETWRITEAUX				
				ldx #DRV.BUFF
				lda #DRV.A2L			WRITE:copy from BUFF to RAM
				dey						Make sure Y=0 for main loop below

RWDRV.RW		stx RWDRV.RW.SRC+1
				sta RWDRV.RW.DST+1

				ldx #2					2 pages to copy

RWDRV.RW.SRC	lda ($FF),y
RWDRV.RW.DST	sta ($FF),y
				iny
				bne RWDRV.RW.SRC

				
				.HS	24				BIT Zero Page to skip RTS
RWDRV.RTS		rts					$FF58 Must Be RTS

				dec DRV.BUFF+1
				dec DRV.A2H
				dex
				bne RWDRV.RW.SRC

				stz RWBankSelect
				sta CLRREADAUX
				sta CLRWRITEAUX
*				plp
				cli

RMDRV.CMDSTATUS				
RWDRV.MAXLO		ldx #$FF				return device block count in X,Y...
RWDRV.MAXHI		ldy #$FF
				
RWDRV.EXITOK	lda #0					make A=0
				clc
				rts
				
RWDRV.IOERR		lda #MLI.E.IO			Carry already set
				rts
*--------------------------------------
* X=Page(0/1 or LC),A=Bank
*--------------------------------------
RWDRV.GOAUX		pha						save BANK
				
				sta SETWRITEAUX			

				ldy #RWDRVX.XM.SIZE		Backup begining of $300 to generate move code
.1				lda RWDRV.XM.RUN-1,y
				sta RWDRVX.XM.SAVE-1,y
				dey
				bne .1
				
				pla						restore BANK
				
				sta SETREADAUX
				jsr RWDRVX.START		Setup Code in main mem at $300 for data move
*										returns : CC=WRITE, CS=READ
				sta CLRREADAUX			CLRWRITEAUX already triggered by code copy
				jsr RWDRV.XM.RUN		Now execute generated code in main memory
				
				sta SETREADAUX
				jsr RWDRVX.RESTORE
				sta CLRREADAUX
				rts						A & carry setup properly by RWDRVX.RESTORE
				
RWDRV.END		.EP
RWDRV.B.END
RWDRV.SIZE		.EQ RWDRV.B.END-RWDRV.B.START
*--------------------------------------
* Driver for Ramworks in aux memory
* $0200 -> $02FF TMP buffer for PAGE copy
* $0300 -> $03FD (Inclusive)
* do not trash $03FE-$03FF (IRQ Vector)
* X=Page(0/1 or LC),A=Bank 
*--------------------------------------
RMDRVX.TMP		.EQ $200
RWDRV.XM.RUN	.EQ $300
*--------------------------------------
RWDRVX.B.START
				.PH	$0300
RWDRVX.START	sta RWDRVX.XM.BANK+1	setup BANK
				txa
				beq .1					page 0/1, no need to check BANK
				cmp #$D0				$C0 <= PAGE < $D0 ?
				bcs .1					no, store in BNK1
				ora #$10				Remap $C0 page to $D0 BNK2
				
.1				ror RWDRVX.XM.RWLC+1	Save Carry to select proper RW bank later
				
				ldy DRV.BUFF
				ldx DRV.BUFF+1
				
				lsr	DRV.COMMAND			DRV.COMMAND: 1=READ,2=WRITE
				bcc .2					CC=WRITE, CS=READ
				stz RWDRVX.XM.SRC+1		READ from src LO = 0
				sta RWDRVX.XM.SRC+2		READ from src HI = PAGE
				sty RWDRVX.XM.DST+1		WRITE to DRV.BUFF
				stx RWDRVX.XM.DST+2
				bra .3
				
.2				sty RWDRVX.XM.SRC+1		READ from DRV.BUFF
				stx RWDRVX.XM.SRC+2
				stz RWDRVX.XM.DST+1		WRITE to dst LO = 0
				sta RWDRVX.XM.DST+2		WRITE to dst HI = PAGE
				
.3				sta CLRWRITEAUX

				ldy #RWDRVX.XM.SIZE
.4				lda RWDRVX.XM.START-1,y
				sta RWDRV.XM.RUN-1,y
				dey
				bne .4
				rts
*--------------------------------------
* Called form Main LC after RWDRVX.XM execution
*--------------------------------------
RWDRVX.RESTORE	ldy #RWDRVX.XM.SIZE		Now, restore begining of $300 
.1				lda RWDRVX.XM.SAVE-1,y
				sta RWDRV.XM.RUN-1,y
				dey
				bne .1
				tya						setup A=0 and CC for exit with non error
				clc
				rts
*--------------------------------------
* "auXMove" Code, moved from Aux to main $300
* $0200 -> $02FF TMP buffer for 2 steps moving between LCs
* CC=WRITE :
* CS=READ :
*--------------------------------------
RWDRVX.XM.START	php
				sei
		
				ldx #0
				ldy #2					2 pages to copy
			
RWDRVX.XM.COPY	jsr RWDRV.XM.RUN+RWDRVX.XM.MNLC-RWDRVX.XM.START		WRITE:copy from MAIN to TMP
				
				bcc RWDRVX.XM.SRC		CC=WRITE,CS=READ?
				
				jsr RWDRV.XM.RUN+RWDRVX.XM.RWLC-RWDRVX.XM.START		READ:copy from BANK to TMP
				sta SETALTZP

RWDRVX.XM.SRC	lda $FFFF,x
				sta RMDRVX.TMP,x
				inx
				bne RWDRVX.XM.SRC
				
				sta CLRALTZP
				jsr RWDRV.XM.RUN+RWDRVX.XM.MNLC-RWDRVX.XM.START		READ:copy from TMP to MAIN

				bcs RWDRVX.XM.1			CC=WRITE,CS=READ?
				
				jsr RWDRV.XM.RUN+RWDRVX.XM.RWLC-RWDRVX.XM.START		WRITE:copy from TMP to BANK
				sta SETALTZP
				
RWDRVX.XM.1		lda RMDRVX.TMP,x
RWDRVX.XM.DST	sta $FFFF,x
				inx
				bne RWDRVX.XM.1
				
				sta CLRALTZP

				inc RWDRV.XM.RUN+RWDRVX.XM.SRC+2-RWDRVX.XM.START
				inc RWDRV.XM.RUN+RWDRVX.XM.DST+2-RWDRVX.XM.START
				dey
				bne RWDRVX.XM.COPY
				
				plp

RWDRVX.XM.MNLC	stz RWBankSelect		ProDOS always uses LCBANK1
				bit RRAMWRAMBNK1
				bit RRAMWRAMBNK1
				rts
				
RWDRVX.XM.RWLC	lda #$FF
				bpl RWDRVX.XM.BANK
				bit RRAMWRAMBNK2
				bit RRAMWRAMBNK2
RWDRVX.XM.BANK	lda #$FF
				sta RWBankSelect
				rts
				
RWDRVX.XM.END
*--------------------------------------
RWDRVX.XM.SIZE	.EQ	RWDRVX.XM.END-RWDRVX.XM.START
*--------------------------------------
RWDRVX.XM.SAVE	.BS RWDRVX.XM.SIZE
*--------------------------------------
				.EP
*--------------------------------------
RWDRVX.B.END
RWDRVX.SIZE	.EQ	RWDRVX.B.END-RWDRVX.B.START
*--------------------------------------
* CONTROL SECTION :
*--------------------------------------
				.DO RWDRV.RTS=$FF58
				.ELSE
				ERROR:RWDRV.RTS <> $FF58
				.FIN
				.DO RWDRV.SIZE>$9B
				ERROR:RWDRV.SIZE too big
				.FIN
				.DO RWDRVX.SIZE>$FE
				ERROR:RWDRVX.SIZE too big
				.FIN
				.DO RWDRVX.XM.SIZE>$F0
				ERROR:RWDRVX.XM.SIZE too big
				.FIN
*--------------------------------------
MAN
SAVE USR/SRC/SYS/KM.RAMWORKS.S
ASM
