; ; Extended memory driver for the C16 hidden RAM. Driver works without ; problems when statically linked. ; ; Ullrich von Bassewitz, 2003-12-15 ; .include "zeropage.inc" .include "em-kernel.inc" .include "em-error.inc" .include "../plus4/plus4.inc" .macpack generic ; ------------------------------------------------------------------------ ; Header. Includes jump table .segment "JUMPTABLE" ; Driver signature .byte $65, $6d, $64 ; "emd" .byte $00 ; EM API version number ; Jump table. .word INSTALL .word UNINSTALL .word PAGECOUNT .word MAP .word USE .word COMMIT .word COPYFROM .word COPYTO ; ------------------------------------------------------------------------ ; Constants BASE = $8000 ; ------------------------------------------------------------------------ ; Data. .bss pages: .res 1 ; Number of pages curpage: .res 1 ; Current page number 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: ; Determine how much memory is available. We will use all memory above ; $8000 up to MEMTOP sec jsr $FF99 ; MEMTOP: Get top memory into Y/X tya sub #>BASE ; Low 32 K are used bcc nomem beq nomem ; Offering zero pages is a bad idea sta pages ldx #$FF stx curpage ; Invalidate the current page inx ; X = 0 txa ; A = X = EM_ERR_OK rts nomem: ldx #>EM_ERR_NO_DEVICE lda #BASE sta ptr1+1 ldy #$00 sty ptr1 lda #window sta ptr2+1 ; Transfer one page jsr transfer ; Transfer one page ; Return the memory window lda #window ; Return the window address 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: lda curpage ; Get the current page bmi done ; Jump if no page mapped add #>BASE sta ptr2+1 ldy #$00 sty ptr2 lda #window sta ptr1+1 ; Transfer one page. Y must be zero on entry. Because we bank out the ; kernal, we will run the routine with interrupts disabled but leave ; short breath times. Unroll the following loop to make it somewhat faster. transfer: sei sta ENABLE_RAM lda (ptr1),y sta (ptr2),y iny lda (ptr1),y sta (ptr2),y iny lda (ptr1),y sta (ptr2),y iny lda (ptr1),y sta (ptr2),y iny lda (ptr1),y sta (ptr2),y iny lda (ptr1),y sta (ptr2),y iny lda (ptr1),y sta (ptr2),y iny lda (ptr1),y sta (ptr2),y iny sta ENABLE_ROM cli bne transfer ; Done done: 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: 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 common: ldy #EM_COPY_COUNT+1 lda (ptr3),y ; Get number of pages beq @L2 ; Skip if no full pages sta tmp1 ; Copy full pages allowing interrupts after each page copied ldy #$00 @L1: jsr transfer 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 tax sei ; Disable ints sta ENABLE_RAM ; Bank out the ROM ; Transfer the bytes in the last page ldy #$00 @L3: lda (ptr1),y sta (ptr2),y iny dex bne @L3 ; Restore the old memory configuration, allow interrupts sta ENABLE_ROM cli ; Done @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: 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 jmp common