;
; Extended memory driver for the Apple II auxiliary memory
;
; Stefan Haubenthal, 2003-12-12
; Ullrich von Bassewitz, 2002-12-02
;

	.include	"zeropage.inc"

	.include	"em-kernel.inc"
	.include	"em-error.inc"


	.macpack	generic


; ------------------------------------------------------------------------
; Header. Includes jump table

.segment	"JUMPTABLE"

; Driver signature

	.byte	$65, $6d, $64		; "emd"
	.byte	EMD_API_VERSION		; EM API version number

; Jump table.

	.word	INSTALL
	.word	DEINSTALL
	.word	PAGECOUNT
	.word	MAP
	.word	USE
	.word	COMMIT
	.word	COPYFROM
	.word	COPYTO

; ------------------------------------------------------------------------
; Constants

BASE	= $0200
AUXCARD	= $C30C				; Card signature
AUXMOVE	= $C311				; Auxiliary move routine
PAGES	= ($C000 - BASE) / 256

; ------------------------------------------------------------------------
; Data.

.data
curpage:	.byte	$FF		; Current page number (invalid)

.bss
window:		.res	256		; Memory "window"

.code

; ------------------------------------------------------------------------
; INSTALL routine. Is called after the driver is loaded into memory. If
; possible, check if the hardware is present and determine the amount of
; memory available.
; Must return an EM_ERR_xx code in a/x.
;

INSTALL:
	ldx	#0
	lda	AUXCARD
	and	#$f0
	cmp	#$80
	bne	@L1
	lda	#EM_ERR_OK
	rts
@L1:	lda	#EM_ERR_NO_DEVICE
;	rts

; ------------------------------------------------------------------------
; DEINSTALL routine. Is called before the driver is removed from memory.
; Can do cleanup or whatever. Must not return anything.
;

DEINSTALL:
	rts


; ------------------------------------------------------------------------
; PAGECOUNT: Return the total number of available pages in a/x.
;

PAGECOUNT:
	lda	#<PAGES
	ldx	#>PAGES
	rts

; ------------------------------------------------------------------------
; MAP: Map the page in a/x into memory and return a pointer to the page in
; a/x. The contents of the currently mapped page (if any) may be discarded
; by the driver.
;

MAP:	sta	curpage			; Remember the new page

	add	#>BASE
	sta	ptr1+1
	ldy	#$00
	sty	ptr1

	lda	#<window
	sta	ptr2
	lda	#>window
	sta	ptr2+1

; Transfer one page

	clc				; Direction flag
	jsr	transfer		; Transfer one page

; Return the memory window

	lda	#<window
	ldx	#>window		; Return the window address

; Done

done:	rts

; ------------------------------------------------------------------------
; USE: Tell the driver that the window is now associated with a given page.

USE:	sta	curpage			; Remember the page
	lda	#<window
	ldx	#>window		; Return the window
	rts

; ------------------------------------------------------------------------
; COMMIT: Commit changes in the memory window to extended storage.

COMMIT: lda	curpage			; Get the current page
	cmp	#$FF
	beq	done			; Jump if no page mapped

	add	#>BASE
	sta	ptr2+1
	ldy	#$00
	sty	ptr2

	lda	#<window
	sta	ptr1
	lda	#>window
	sta	ptr1+1
	lda	#<$FF
	sta	ptr4
	lda	#>$FF
	sta	ptr4+1
	sec				; Direction flag

; Transfer one page/all bytes

transfer:
	php
	lda	ptr1
	sta	$3C
	add	ptr4
	sta	$3E
	lda	ptr1+1
	sta	$3D
	adc	ptr4+1
	sta	$3F
	lda	ptr2
	sta	$42
	lda	ptr2+1
	sta	$43
	plp
	jmp	AUXMOVE

; ------------------------------------------------------------------------
; COPYFROM: Copy from extended into linear memory. A pointer to a structure
; describing the request is passed in a/x.
; The function must not return anything.
;

COPYFROM:
	sta	ptr3
	stx	ptr3+1			; Save the passed em_copy pointer

	ldy	#EM_COPY::OFFS
	lda	(ptr3),y
	sta	ptr1
	ldy	#EM_COPY::PAGE
	lda	(ptr3),y
	add	#>BASE
	sta	ptr1+1			; From

	ldy	#EM_COPY::BUF
	lda	(ptr3),y
	sta	ptr2
	iny
	lda	(ptr3),y
	sta	ptr2+1			; To
	clc				; Direction flag

common: ldy	#EM_COPY::COUNT
	lda	(ptr3),y		; Get bytes in last page
	sta	ptr4
	iny
	lda	(ptr3),y		; Get number of pages
	sta	ptr4+1

	jmp	transfer

; ------------------------------------------------------------------------
; COPYTO: Copy from linear into extended memory. A pointer to a structure
; describing the request is passed in a/x.
; The function must not return anything.
;

COPYTO: sta	ptr3
	stx	ptr3+1			; Save the passed em_copy pointer

	ldy	#EM_COPY::OFFS
	lda	(ptr3),y
	sta	ptr2
	ldy	#EM_COPY::PAGE
	lda	(ptr3),y
	add	#>BASE
	sta	ptr2+1			; To

	ldy	#EM_COPY::BUF
	lda	(ptr3),y
	sta	ptr1
	iny
	lda	(ptr3),y
	sta	ptr1+1			; From

	sec				; Direction flag
	jmp	common
