====== How to code for the EasyFlash cart ======
(a Quick-Start, see [[http://codebase64.org/lib/exe/fetch.php?media=base:easysdk.pdf|EasySDK Guide]] for detailed information)
EasyFlash consists of 2 Flash memory chips of 512 KB each.\\
It has a total of 1MB.\\
One Flash chip for low bank (at $8000),\\
one for high bank (at $a000 or $e000 in UMAX mode).
8 kb per chip can be banked into c64 memory at a time.\\
There is a total of 64 Banks.\\
The active bank is selected via $de00.\\
//$de00 always selects low and high bank simultaneously.//
$de02 selects the configuration:
* bit 7: toggle board LED
* bit 6: reserved
* bit 5: reserved
* bit 4: reserved
* bit 3: reserved
* bit 2: GAME MODE /1: controlled via bit0 /0: from jumper
* bit 1: EXROM state /0: high
* bit 0: GAME state (if bit 2 set) /0: high
In practice this means:
lda #%00000100 ;Cartridge ROM off (256 Bytes of RAM still available at $dfxx)
lda #%00000101 ;Ultimax Mode (low bank at $8000, high bank at $e000)
lda #%00000110 ; 8 Kb cart (low bank at $8000)
lda #%00000111 ;16 Kb cart (low bank at $8000, high bank at $a000)
sta $de02
Example:\\
To access 8Kb low and 8Kb high of Bank 0:
lda #$37 ;enable CART ROM
sta $01
lda #$00 ;select bank
sta $de00
lda #%00000111 ;select 16 Kb configuration, low at $8000, high at $a000
sta $de02
ldx #00
lda $8000,x ;access data from EasyFlash ($8000-$bfff in this case)
//$de00 and $de02 are WRITE ONLY, so you can not use INC or DEC to change banks or settings.//
Naturally the memory configuration via $01 remains valid,\\
i.e. #$37 or #$33 to enable CART ROM.
Note, that the additional RAM is always visible in I/O space at $dfxx.
//EasyFlash always starts up in Ultimax mode after Reset,//\\
hence you have to provide some startup code if you write your own crt.\\
The following snippet provides a commented working framework (ACME Assembler format) by skoe.
; EasyFlashSDK sample code
; see README for a description details
* = $0000
EASYFLASH_BANK = $DE00
EASYFLASH_CONTROL = $DE02
EASYFLASH_LED = $80
EASYFLASH_16K = $07
EASYFLASH_KILL = $04
; =============================================================================
; 00:0:0000 (LOROM, bank 0)
bankStart_00_0:
; This code resides on LOROM, it becomes visible at $8000
!pseudopc $8000 {
; === the main application entry point ===
; copy the main code to $C000 (or whereever) - we don't run it here
; since the banking would make it invisible
; it may be a good idea to let exomizer do this in real life
ldx #0
lp1:
lda main,x
sta $c000,x
dex
bne lp1
jmp $c000
main:
!pseudopc $C000 {
; Switch to bank 1, get a byte from LOROM and HIROM
lda #1
sta EASYFLASH_BANK
lda $8000
ldx $a000
; and put them to the screen, we should see "A" and "B" there
sta $0400
stx $0401
; Switch to bank 2, get a byte from LOROM and HIROM
lda #2
sta EASYFLASH_BANK
lda $8000
ldx $a000
; and put them to the screen, we should see "C" and "D" there
sta $0400 + 40
stx $0401 + 40
; effect!
lp2:
dec $d020
jmp lp2
}
; fill the whole bank with value $ff
!align $ffff, $a000, $ff
}
; =============================================================================
; 00:1:0000 (HIROM, bank 0)
bankStart_00_1:
; This code runs in Ultimax mode after reset, so this memory becomes
; visible at $E000..$FFFF first and must contain a reset vector
!pseudopc $e000 {
coldStart:
; === the reset vector points here ===
sei
ldx #$ff
txs
cld
; enable VIC (e.g. RAM refresh)
lda #8
sta $d016
; write to RAM to make sure it starts up correctly (=> RAM datasheets)
startWait:
sta $0100, x
dex
bne startWait
; copy the final start-up code to RAM (bottom of CPU stack)
ldx #(startUpEnd - startUpCode)
l1:
lda startUpCode, x
sta $0100, x
dex
bpl l1
jmp $0100
startUpCode:
!pseudopc $0100 {
; === this code is copied to the stack area, does some inits ===
; === scans the keyboard and kills the cartridge or ===
; === starts the main application ===
lda #EASYFLASH_16K + EASYFLASH_LED
sta EASYFLASH_CONTROL
; Check if one of the magic kill keys is pressed
; This should be done in the same way on any EasyFlash cartridge!
; Prepare the CIA to scan the keyboard
lda #$7f
sta $dc00 ; pull down row 7 (DPA)
ldx #$ff
stx $dc02 ; DDRA $ff = output (X is still $ff from copy loop)
inx
stx $dc03 ; DDRB $00 = input
; Read the keys pressed on this row
lda $dc01 ; read coloumns (DPB)
; Restore CIA registers to the state after (hard) reset
stx $dc02 ; DDRA input again
stx $dc00 ; Now row pulled down
; Check if one of the magic kill keys was pressed
and #$e0 ; only leave "Run/Stop", "Q" and "C="
cmp #$e0
bne kill ; branch if one of these keys is pressed
; same init stuff the kernel calls after reset
ldx #0
stx $d016
jsr $ff84 ; Initialise I/O
; These may not be needed - depending on what you'll do
jsr $ff87 ; Initialise System Constants
jsr $ff8a ; Restore Kernal Vectors
jsr $ff81 ; Initialize screen editor
; start the application code
jmp $8000
kill:
lda #EASYFLASH_KILL
sta EASYFLASH_CONTROL
jmp ($fffc) ; reset
}
startUpEnd:
; fill it up to $FFFA to put the vectors there
!align $ffff, $fffa, $ff
!word reti ; NMI
!word coldStart ; RESET
; we don't need the IRQ vector and can put RTI here to save space :)
reti:
rti
!byte 0xff
}
; =============================================================================
; 01:0:0000 (LOROM, bank 1)
bankStart_01_0:
; fill the whole bank with value 1 = 'A'
!fill $2000, 1
; =============================================================================
; 01:1:0000 (HIROM, bank 1)
bankStart_01_1:
; fill the whole bank with value 2 = 'B'
!fill $2000, 2
; =============================================================================
; 02:0:0000 (LOROM, bank 2)
bankStart_02_0:
; fill the whole bank with value 3 = 'C'
!fill $2000, 3
; =============================================================================
; 02:1:0000 (HIROM, bank 2)
bankStart_02_1:
; fill the whole bank with value 4 = 'D'
!fill $2000, 4