From 8a3a0e95ade569e6811f39941f5b442deb69522b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrycjusz=20R=2E=20=C5=81ogiewa?= Date: Fri, 26 Feb 2016 23:51:37 +0100 Subject: [PATCH] blackystardust pull request with post-review changes --- libsrc/c64/emd/c64-65816.s | 376 +++++++++++++++++++++++++++++++++++++ testcode/lib/em-test.c | 1 + 2 files changed, 377 insertions(+) create mode 100644 libsrc/c64/emd/c64-65816.s diff --git a/libsrc/c64/emd/c64-65816.s b/libsrc/c64/emd/c64-65816.s new file mode 100644 index 000000000..bf44a0ecc --- /dev/null +++ b/libsrc/c64/emd/c64-65816.s @@ -0,0 +1,376 @@ +; +; Extended memory driver for 65816 based extra RAM. Driver works without +; problems when statically linked. +; +; Marco van den Heuvel, 2015-12-01 +; + + .include "zeropage.inc" + + .include "em-kernel.inc" + .include "em-error.inc" + + + .macpack generic + .macpack module + + +; ------------------------------------------------------------------------ +; Header. Includes jump table + + module_header _c64_65816_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 + +; ------------------------------------------------------------------------ +; Data. + +.bss +isnotscpu: .res 1 ; SuperCPU not present +curpage: .res 1 ; Current page number +curbank: .res 1 ; Current bank number (+1) +bankcount: .res 1 ; Number of available banks (pages = banks * 256) +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: + sei + clc + sed + lda #$99 + adc #$01 ; on 65C02, 65SC02, 65CE02, 65802 and 65816 sets the zero flag correctly + cld + bne @not_present + clc +.P816 + sep #$01 ; nop #$01 on 65C02/65SC02 and lda ($01,s),y on 65CE02 +.P02 + bcc @not_present + lda $d0bc + and #$80 + sta isnotscpu + lda $07e8 + pha ; save value incase it was used somewhere else + ldx #$ff +@fillloop: ; fill from top (bank 255) to bottom + txa + pha +.P816 + plb ; pull dbr +.P02 + stx $07e8 + dex + cpx #$ff + bne @fillloop + inx +@compareloop: ; check from bottom to top + txa + pha +.P816 + plb +.P02 + cmp $07e8 + bne @found_pages +.P816 + inc +.P02 + sta $07e8 + cmp $07e8 + bne @found_pages + inx + bne @compareloop +@found_pages: + dex + lda #$00 + pha +.P816 + plb +.P02 + pla + sta $07e8 + cli + lda isnotscpu + bne @noextradex + dex +@noextradex: + stx bankcount + lda #EM_ERR_OK + rts +@not_present: + cli + lda #EM_ERR_NO_DEVICE +; 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 #$00 ; a whole bank is either usable or not + ldx bankcount + 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 + stx curbank ; Remember the new bank + + sta ptr2+1 ; src address low + lda #$00 + sta ptr2 ; src address high + inx + ldy isnotscpu ; check if not scpu + bne @notscpu + inx +@notscpu: + stx tmp2 ; src bank + + sta tmp1 ; dst bank + + sta ptr3+1 ; length high + lda #$ff + sta ptr3 ; length low + + lda #window + stx ptr1+1 ; dst address high + + jsr transfer + + rts + +; ------------------------------------------------------------------------ +; USE: Tell the driver that the window is now associated with a given page. + +USE: sta curpage ; Remember the page + stx curbank ; Remember the bank + lda #window ; Return the window + rts + +; ------------------------------------------------------------------------ +; COMMIT: Commit changes in the memory window to extended storage. + +COMMIT: lda curpage ; Get the current page + sta ptr1+1 ; dst high + ldx #$00 + stx ptr1 ; dst low + + lda #window + sta ptr2+1 ; src high + + stx ptr3+1 ; length high + lda #$ff + sta ptr3 ; length low + + stx tmp2 ; src bank + ldy curbank ; Get the current bank + iny + ldx isnotscpu + bne @notascpu + iny +@notascpu: + sty tmp1 ; dst bank + + jsr transfer + + 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 ptr4 + stx ptr4+1 ; Save the passed em_copy pointer + + ldy #EM_COPY::COUNT+1 ; start at the end of the struct + lda (ptr4),y ; get high byte of count + tax + dey + lda (ptr4),y ; get low byte of count + bne @nodex + dex +@nodex: +.P816 + dec +.P02 + sta ptr3 ; length low + stx ptr3+1 ; length high + dey + lda (ptr4),y ; get bank +.P816 + inc +.P02 + ldx isnotscpu + bne @notscpu64 +.P816 + inc +.P02 +@notscpu64: + sta tmp2 ; src bank + dey + lda (ptr4),y ; get page + sta ptr2+1 ; src high + dey + lda (ptr4),y ; get offset in page + sta ptr2 ; src low + dey + lda (ptr4),y ; get memory buffer high + sta ptr1+1 ; dst high + dey + lda (ptr4),y ; get memory buffer low + sta ptr1 ; dst low + lda #$00 + sta tmp1 ; dst bank + + jsr transfer + + 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 ptr4 + stx ptr4+1 ; Save the passed em_copy pointer + + ldy #EM_COPY::COUNT+1 ; start at the end of the struct + lda (ptr4),y ; get high byte of count + tax + dey + lda (ptr4),y ; get low byte of count + bne @nodex2 + dex +@nodex2: +.P816 + dec +.P02 + sta ptr3 ; length low + txa + sta ptr3+1 ; length high + dey + lda (ptr4),y ; get bank +.P816 + inc +.P02 + ldx isnotscpu + bne @notascpu64 +.P816 + inc +.P02 +@notascpu64: + sta tmp1 ; dst bank + dey + lda (ptr4),y ; get page + sta ptr1+1 ; dst high + dey + lda (ptr4),y ; get page offset + sta ptr1 ; dst low + dey + lda (ptr4),y ; get memory buffer high + sta ptr2+1 ; src low + dey + lda (ptr4),y ; get memory buffer low + sta ptr2 ; src high + lda #$00 + sta tmp2 ; src bank + + jsr transfer + + rts + +; ------------------------------------------------------------------------ +; Helper function for moving a block, the following is used: +; ptr1: dst +; ptr2: src +; ptr3: length +; tmp1: dst bank +; tmp2: src bank + +transfer: +.P816 +.A8 +.I8 + sei + pha + phx + phy + ldx tmp1 ; load srcbank + stx @move+1 ; store srcbank in move + 1 + ldy tmp2 ; load dstbank + sty @move+2 ; store dstbank in move + 2 + clc ; switch to native mode + xce + php ; save status bits + rep #%00110000 ; set A and index to 16bit +.A16 +.I16 + ldy ptr1 + ldx ptr2 + lda ptr3 +@move: + mvn 0,0 + plp ; restore status bits +.A8 +.I8 + lda #$00 + pha + plb ; restore dbr + sec + xce ; switch to emul mode + ply + plx + pla + cli + rts +.P02 diff --git a/testcode/lib/em-test.c b/testcode/lib/em-test.c index f4a56029a..76f6400c1 100644 --- a/testcode/lib/em-test.c +++ b/testcode/lib/em-test.c @@ -87,6 +87,7 @@ static emd_test_t drivers[] = { { '6', "REU", "c64-reu.emd" }, { '7', "C128 VDC (in C64 mode)", "c64-vdc.emd" }, { '8', "C64DTV himem", "dtv-himem.emd" }, + { '9', "65816 extra banks", "c64-65816.emd" }, #endif #if defined(__C128__)