====== 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