Last active
January 20, 2017 22:29
-
-
Save SaxxonPike/e6d3e65a212a9b2ac5c7b97558456bc9 to your computer and use it in GitHub Desktop.
Commodore 64 EasyFlash RAM driver [CA65 assembler]
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;------------------------------------------------------------------------------ | |
; [ efram chunk ] | |
; I wrote this because I needed something that could bank in/out the | |
; EasyFlash code, perform copies and memory swaps, and not occupy RAM | |
; where the game exists, all while fitting in the lower half of the | |
; page (because EasyAPI uses the upper half.) | |
; This starts at $DF03 to give us XBANK address at $DF00 and two | |
; variables to do whatever with at $DF01 and $DF02. Plus it fits nicely | |
; if you think of this as a jumptable entry address or something. | |
; (Don't mind my rants, these are notes to help ME think.) | |
;------------------------------------------------------------------------------ | |
.scope EFRAM | |
BASE = $DF03-START | |
;------------------------------------------------------------------------------ | |
; [ rom call jump ] | |
; A = low address to jump. If high address is needed too, write it | |
; externally or something. I use $A000 because it fits my driver. | |
;------------------------------------------------------------------------------ | |
START: | |
sta ROMADDR+1+BASE | |
jsr ENABLE+BASE | |
ROMADDR: jsr $A000 | |
;------------------------------------------------------------------------------ | |
; [ disable ef-rom ] | |
; Turn off the EasyFlash LED and banking. | |
; The "bne" instruction is used at the end to save space. | |
;------------------------------------------------------------------------------ | |
DISABLE: | |
ROMCONF: lda #$F5 | |
pha | |
lda #%00000100 | |
bne SWCOMMON | |
;------------------------------------------------------------------------------ | |
; [ swap ] | |
; note: source and destination must be written externally. | |
; Use SWAPSRC1, SWAPSRC2, SWAPDST1, and SWAPDST2. | |
; $FFFF is used as a temp address because it's all one bits and this | |
; somehow benefits the life of the EasyFlash. | |
; This only does up to one page at a time (the length is determined by | |
; the X register) and banks out EasyFlash during the operation. It will | |
; bank EasyFlash back in after it is finished. | |
; Also note that due to the way the indexing is done, the swapping will | |
; start at ADDRESS+1. Not a problem if X is zero, it will do a whole | |
; page. But keep this in mind for all other values. | |
;------------------------------------------------------------------------------ | |
SWAP: | |
.scope SWAPSEC | |
jsr DISABLE+BASE | |
LOOP: | |
SRC1: lda $FFFF,x | |
DST1: ldy $FFFF,x | |
DST2: sta $FFFF,x | |
tya | |
SRC2: sta $FFFF,x | |
dex | |
bne LOOP | |
.endscope | |
;------------------------------------------------------------------------------ | |
; [ enable ef-rom ] | |
; All other roms are enabled as a side-effect & EasyFlash LED is on. | |
;------------------------------------------------------------------------------ | |
ENABLE: | |
lda $01 | |
sta ROMCONF+1+BASE | |
ora #$07 | |
pha | |
lda #%10000111 | |
;------------------------------------------------------------------------------ | |
; [ set ef-rom state ] | |
; A = EasyFlash $DE02 state | |
;------------------------------------------------------------------------------ | |
SWCOMMON: | |
sta $DE02 | |
pla | |
sta $01 | |
;------------------------------------------------------------------------------ | |
; [ retore bank ] | |
; This is the ONLY return point from the loader. | |
; All functions lead here. Functions may also JSR here just to set | |
; the EasyFlash bank. | |
;------------------------------------------------------------------------------ | |
SETBANK: | |
BNK: lda #$01 | |
RESTBNK: | |
sta $DE00 | |
rts | |
;------------------------------------------------------------------------------ | |
; [ copy ] | |
; note: source and destination must be written externally to | |
; SRC+1/SRC+2 and DST+1/DST+2. | |
; X = highbyte length (two's complement) | |
; Y = lowbyte length (two's complement) | |
; The "bne RESTBNK" line is the *actual* exit point in this function. | |
; I have tried a number of methods and this hybrid self-modifying and | |
; absolute-indexing method is the fastest I could get. It does require | |
; a bit of setup due to the file length needing to be two's complement. | |
; Even using zeropage was slower because of the indirect addressing. | |
; BIT+BVC is used to determine if we are crossing EasyFlash banks. | |
; Due to this, you CANNOT tell it not to use the high bank. However, | |
; by writing different values to COPYWRP you can at least tell it you | |
; don't want the low bank (the value $A0 will work OK for this.) The | |
; default wrap value is $80. | |
;------------------------------------------------------------------------------ | |
COPY: | |
.scope COPYSEC | |
jsr SETBANK+BASE | |
LOOP: | |
SRC: lda $FFFF,y | |
DST: sta $FFFF,y | |
iny | |
beq BANKCHK | |
CTROK: | |
inx | |
bne LOOP | |
inc LEN+BASE | |
bne LOOP | |
lda #$01 | |
sta BNK+1+BASE | |
bne RESTBNK | |
BANKCHK: | |
inc SRC+2+BASE | |
inc DST+2+BASE | |
bit SRC+2+BASE | |
bvc CTROK | |
WRP: lda #$80 | |
sta SRC+2+BASE | |
inc BNK+1+BASE | |
jsr SETBANK+BASE | |
jmp CTROK+BASE | |
LEN: .byte $00 | |
.endscope | |
;------------------------------------------------------------------------------ | |
; [ footer ] | |
; I used to put padding here, but now that this routine is pretty much | |
; finished I removed it. | |
;------------------------------------------------------------------------------ | |
END: | |
.endscope | |
EFRAMSIZE = EFRAM::END-EFRAM::START | |
;------------------------------------------------------------------------------ | |
; [ exports ] | |
; To be used when writing internal variables externally. | |
;------------------------------------------------------------------------------ | |
EFMEMCONF := EFRAM::ROMCONF+1+EFRAM::BASE | |
EFDISABLE := EFRAM::DISABLE+EFRAM::BASE | |
EFENABLE := EFRAM::ENABLE+EFRAM::BASE | |
EFCOPY := EFRAM::COPY+EFRAM::BASE | |
COPYSRC := EFRAM::COPYSEC::SRC+1+EFRAM::BASE | |
COPYDST := EFRAM::COPYSEC::DST+1+EFRAM::BASE | |
COPYBNK := EFRAM::BNK+1+EFRAM::BASE | |
COPYWRP := EFRAM::COPYSEC::WRP+1+EFRAM::BASE | |
COPYLEN := EFRAM::COPYSEC::LEN+EFRAM::BASE | |
EFSWAP := EFRAM::SWAP+EFRAM::BASE | |
SWAPSRC1 := EFRAM::SWAPSEC::SRC1+1+EFRAM::BASE | |
SWAPSRC2 := EFRAM::SWAPSEC::SRC2+1+EFRAM::BASE | |
SWAPDST1 := EFRAM::SWAPSEC::DST1+1+EFRAM::BASE | |
SWAPDST2 := EFRAM::SWAPSEC::DST2+1+EFRAM::BASE |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
See this driver in action on the Legacy of the Ancients / Legend of Blacksilver +4 release on CSDB:
http://csdb.dk/release/?id=128480