; ; Extended memory driver for the Double Quick Brown Box cartridge ; Marco van den Heuvel, 2010-01-27 ; .include "zeropage.inc" .include "em-kernel.inc" .include "em-error.inc" .macpack generic .macpack module ; ------------------------------------------------------------------------ ; Header. Includes jump table module_header _c64_dqbb_emd ; 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 BASE = $8000 PAGES = ($C000 - BASE) / 256 TARGETLOC = $200 ; Target location for copy/check code CONTROL = $DE00 ; ------------------------------------------------------------------------ ; Data. .proc check template: .org ::TARGETLOC ; Assemble for target location entry: lda $01 pha lda #$37 sta $01 ldx #$14 ldy #$90 sty CONTROL lda $8000 stx CONTROL cmp $8000 bne present sty CONTROL inc $8000 stx CONTROL cmp $8000 beq present dec $8000 ldy #$00 done: pla sta $01 rts present: sty CONTROL ldy #$01 bne done .reloc .endproc .proc copy template: .org ::TARGETLOC ; Assemble for target location entry: .proc fetch stx CONTROL ldx $01 lda #$37 sta $01 address := *+1 ; Patched at runtime lda ($00),y stx $01 ldx #$90 stx CONTROL rts .endproc .proc stash stx CONTROL ldx $01 ldy #$37 sty $01 ldy #$00 address := *+1 ; Patched at runtime sta ($00),y stx $01 ldx #$90 stx CONTROL rts .endproc .reloc .endproc .bss curpage: .res 1 ; Current page number window: .res 256 ; Memory "window" ; Since the functions above are copied to $200, the current contents of this ; memory area must be saved into backup storage. Allocate enough space. backup: .res .max (.sizeof (copy), .sizeof (check)) .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: sei jsr backup_and_setup_check_routine jsr check::entry cli ldx #.sizeof (check) - 1 jsr restore_data cpy #$01 beq @present lda #EM_ERR_NO_DEVICE rts @present: lda #EM_ERR_OK ; rts ; Run into UNINSTALL instead ; ------------------------------------------------------------------------ ; UNINSTALL routine. Is called before the driver is removed from memory. ; Can do cleanup or whatever. Must not return anything. ; UNINSTALL: rts ; ------------------------------------------------------------------------ ; PAGECOUNT: Return the total number of available pages in a/x. ; PAGECOUNT: lda #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: sei sta curpage ; Remember the new page clc adc #>BASE sta ptr1+1 ldy #0 sty ptr1 jsr backup_and_setup_copy_routine ldx #window ; Return the window address cli rts ; ------------------------------------------------------------------------ ; USE: Tell the driver that the window is now associated with a given page. USE: sta curpage ; Remember the page lda #window ; Return the window rts ; ------------------------------------------------------------------------ ; COMMIT: Commit changes in the memory window to extended storage. COMMIT: sei lda curpage ; Get the current page clc adc #>BASE sta ptr1+1 ldy #0 sty ptr1 jsr backup_and_setup_copy_routine ldx #BASE sta ptr4+1 ; Get the buffer pointer into ptr2 ldy #EM_COPY::BUF lda (ptr1),y sta ptr2 iny lda (ptr1),y sta ptr2+1 ; Get the count, calculate -(count-1) and store it into ptr3 ldy #EM_COPY::COUNT lda (ptr1),y eor #$FF sta ptr3 iny lda (ptr1),y eor #$FF sta ptr3+1 ; Get the page offset into ptr4 and clear tmp1 ldy #EM_COPY::OFFS lda (ptr1),y sta ptr4 lda #0 sta tmp1 ; Done rts ; Helper routines for copying to and from the +256k ram backup_and_setup_copy_routine: ldx #.sizeof (copy) - 1 @L1: lda copy::entry,x sta backup,x lda copy::template,x sta copy::entry,x dex bpl @L1 rts backup_and_setup_check_routine: ldx #.sizeof (check) - 1 @L1: lda check::entry,x sta backup,x lda check::template,x sta check::entry,x dex bpl @L1 rts restore_copy_routine: ldx #.sizeof (copy) - 1 restore_data: lda backup,x sta TARGETLOC,x dex bpl restore_data rts