; ; Extended memory driver for the VDC RAM available on all C128 machines ; (based on code by Ullrich von Bassewitz) ; Maciej 'YTM/Elysium' Witkowiak ; 06,20.12.2002 .include "zeropage.inc" .include "em-kernel.inc" .include "em-error.inc" .macpack generic ; ------------------------------------------------------------------------ ; Header. Includes jump table .segment "HEADER" ; Driver signature .byte $65, $6d, $64 ; "emd" .byte EMD_API_VERSION ; EM API version number ; Library reference .addr $0000 ; Jump table .addr INSTALL .addr UNINSTALL .addr PAGECOUNT .addr MAP .addr USE .addr COMMIT .addr COPYFROM .addr COPYTO ; ------------------------------------------------------------------------ ; Constants VDC_ADDR_REG = $D600 ; VDC address VDC_DATA_REG = $D601 ; VDC data VDC_DATA_HI = 18 ; used registers VDC_DATA_LO = 19 VDC_CSET = 28 VDC_DATA = 31 ; ------------------------------------------------------------------------ ; Data. .data pagecount: .word 64 ; $0000-$3fff as 16k default curpage: .word $ffff ; currently mapped-in page (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: ; do test for VDC presence here??? ldx #VDC_CSET ; determine size of RAM... jsr vdcgetreg sta tmp1 ora #%00010000 jsr vdcputreg ; turn on 64k jsr settestadr1 ; save original value of test byte jsr vdcgetbyte sta tmp2 lda #$55 ; write $55 here ldy #ptr1 jsr test64k ; read it here and there lda #$aa ; write $aa here ldy #ptr2 jsr test64k ; read it here and there jsr settestadr1 lda tmp2 jsr vdcputbyte ; restore original value of test byte lda ptr1 ; do bytes match? cmp ptr1+1 bne @have64k lda ptr2 cmp ptr2+1 bne @have64k ldx #VDC_CSET lda tmp1 jsr vdcputreg ; restore 16/64k flag jmp @endok ; and leave default values for 16k @have64k: lda #<256 ldx #>256 sta pagecount stx pagecount+1 @endok: lda #EM_ERR_OK rts test64k: sta tmp1 sty ptr3 lda #0 sta ptr3+1 jsr settestadr1 lda tmp1 jsr vdcputbyte ; write $55 jsr settestadr1 jsr vdcgetbyte ; read here pha jsr settestadr2 jsr vdcgetbyte ; and there ldy #1 sta (ptr3),y pla dey sta (ptr3),y rts settestadr1: ldy #$02 ; test page 2 (here) .byte $2c settestadr2: ldy #$42 ; or page 64+2 (there) lda #0 jmp vdcsetsrcaddr ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. ; Can do cleanup or whatever. Must not return anything. ; UNINSTALL: ;on C128 restore font and clear the screen? rts ; ------------------------------------------------------------------------ ; PAGECOUNT: Return the total number of available pages in a/x. ; PAGECOUNT: lda pagecount ldx pagecount+1 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 stx curpage+1 sta ptr1+1 ldy #0 sty ptr1 lda #window sta ptr2+1 jsr transferin lda #window rts ; copy a single page from (ptr1):VDCRAM to (ptr2):RAM transferin: lda ptr1 ldy ptr1+1 jsr vdcsetsrcaddr ; set source address in VDC ldy #0 ldx #VDC_DATA stx VDC_ADDR_REG @L0: bit VDC_ADDR_REG bpl @L0 lda VDC_DATA_REG ; get 2 bytes at a time to speed-up sta (ptr2),y ; (in fact up to 8 bytes could be fetched with special VDC config) iny lda VDC_DATA_REG sta (ptr2),y iny bne @L0 rts ; ------------------------------------------------------------------------ ; USE: Tell the driver that the window is now associated with a given page. USE: sta curpage stx curpage+1 ; Remember the page lda #window ; Return the window done: rts ; ------------------------------------------------------------------------ ; COMMIT: Commit changes in the memory window to extended storage. COMMIT: lda curpage ; jump if no page mapped ldx curpage+1 bmi done sta ptr1+1 ldy #0 sty ptr1 lda #window sta ptr2+1 ; fall through to transferout ; copy a single page from (ptr2):RAM to (ptr1):VDCRAM transferout: lda ptr1 ldy ptr1+1 jsr vdcsetsrcaddr ; set source address in VDC ldy #0 ldx #VDC_DATA stx VDC_ADDR_REG @L0: bit VDC_ADDR_REG bpl @L0 lda (ptr2),y ; speedup does not work for writing sta VDC_DATA_REG iny bne @L0 rts ; ------------------------------------------------------------------------ ; 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: jsr setup beq @L2 ; Skip if no full pages ; Copy full pages @L1: jsr transferin inc ptr1+1 inc ptr2+1 dec tmp1 bne @L1 ; Copy the remainder of the page @L2: ldy #EM_COPY::COUNT lda (ptr3),y ; Get bytes in last page beq @L4 sta tmp1 ; Transfer the bytes in the last page ldy #0 @L3: jsr vdcgetbyte sta (ptr2),y iny dec tmp1 lda tmp1 bne @L3 @L4: rts ; ------------------------------------------------------------------------ ; 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: jsr setup beq @L2 ; Skip if no full pages ; Copy full pages @L1: jsr transferout inc ptr1+1 inc ptr2+1 dec tmp1 bne @L1 ; Copy the remainder of the page @L2: ldy #EM_COPY::COUNT lda (ptr3),y ; Get bytes in last page beq @L4 sta tmp1 ; Transfer the bytes in the last page ldy #0 @L3: lda (ptr2),y jsr vdcputbyte iny dec tmp1 lda tmp1 bne @L3 @L4: rts ;------------------------------------------------------------------------- ; Helper functions to handle VDC ram ; vdcsetsrcaddr: ldx #VDC_DATA_LO stx VDC_ADDR_REG @L0: bit VDC_ADDR_REG bpl @L0 sta VDC_DATA_REG dex tya stx VDC_ADDR_REG sta VDC_DATA_REG rts vdcgetbyte: ldx #VDC_DATA vdcgetreg: stx VDC_ADDR_REG @L0: bit VDC_ADDR_REG bpl @L0 lda VDC_DATA_REG rts vdcputbyte: ldx #VDC_DATA vdcputreg: stx VDC_ADDR_REG @L0: bit VDC_ADDR_REG bpl @L0 sta VDC_DATA_REG rts ; ------------------------------------------------------------------------ ; Helper function for COPYFROM and COPYTO: Store the pointer to the request ; structure and prepare data for the copy ; setup: 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 sta ptr1+1 ; From ldy #EM_COPY::BUF lda (ptr3),y sta ptr2 iny lda (ptr3),y sta ptr2+1 ; To ldy #EM_COPY::COUNT+1 lda (ptr3),y ; Get number of pages sta tmp1 rts