I'm trying to get CHR bank switching to work with cc65, but nothing happens when I write "1" to 0x8000. Can anyone spot the issue?
Linker config:
The end of my crt0.s:
Switching code:
The CHR files exist and are correct. At runtime it only displays from the first bank though. Shutting down the PPU for switching didn't make a difference.
Linker config:
Code:
SYMBOLS {
__STACKSIZE__: type = weak, value = $0500; # 5 pages stack
NES_MAPPER: type = weak, value = 3; # mapper number
NES_PRG_BANKS: type = weak, value= 2; # number of 16K PRG banks, change to 2 for NROM256
NES_CHR_BANKS: type = weak, value = 2; # number of 8K CHR banks
NES_MIRRORING: type = weak, value = 1; # 0 horizontal, 1 vertical, 8 four screen
}
MEMORY {
ZP: start = $0000, size = $0100, type = rw, define = yes;
HEADER: start = $0000, size = $0010, file = %O ,fill = yes;
PRG: start = $8000, size = $7fc0, file = %O ,fill = yes, define = yes;
DMC: start = $ffc0, size = $003a, file = %O, fill = yes;
VECTORS: start = $fffa, size = $0006, file = %O, fill = yes;
CHR: start = $0000, size = $2000, file = %O, fill = yes;
CHR2: start = $0000, size = $2000, file = %O, fill = yes;
RAM: start = $0300, size = $0500, define = yes;
# Use this definition instead if you going to use extra 8K RAM
# RAM: start = $6000, size = $2000, define = yes;
}
SEGMENTS {
HEADER: load = HEADER, type = ro;
STARTUP: load = PRG, type = ro, define = yes;
LOWCODE: load = PRG, type = ro, optional = yes;
INIT: load = PRG, type = ro, define = yes, optional = yes;
CODE: load = PRG, type = ro, define = yes;
RODATA: load = PRG, type = ro, define = yes;
DATA: load = PRG, run = RAM, type = rw, define = yes;
VECTORS: load = VECTORS, type = rw;
SAMPLES: load = DMC, type = rw;
CHARS: load = CHR, type = rw;
CHARS2: load = CHR2, type = rw;
BSS: load = RAM, type = bss, define = yes;
HEAP: load = RAM, type = bss, optional = yes;
ZEROPAGE: load = ZP, type = zp;
}
FEATURES {
CONDES: segment = INIT,
type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__;
CONDES: segment = RODATA,
type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__;
CONDES: type = interruptor,
segment = RODATA,
label = __INTERRUPTOR_TABLE__,
count = __INTERRUPTOR_COUNT__;
}
__STACKSIZE__: type = weak, value = $0500; # 5 pages stack
NES_MAPPER: type = weak, value = 3; # mapper number
NES_PRG_BANKS: type = weak, value= 2; # number of 16K PRG banks, change to 2 for NROM256
NES_CHR_BANKS: type = weak, value = 2; # number of 8K CHR banks
NES_MIRRORING: type = weak, value = 1; # 0 horizontal, 1 vertical, 8 four screen
}
MEMORY {
ZP: start = $0000, size = $0100, type = rw, define = yes;
HEADER: start = $0000, size = $0010, file = %O ,fill = yes;
PRG: start = $8000, size = $7fc0, file = %O ,fill = yes, define = yes;
DMC: start = $ffc0, size = $003a, file = %O, fill = yes;
VECTORS: start = $fffa, size = $0006, file = %O, fill = yes;
CHR: start = $0000, size = $2000, file = %O, fill = yes;
CHR2: start = $0000, size = $2000, file = %O, fill = yes;
RAM: start = $0300, size = $0500, define = yes;
# Use this definition instead if you going to use extra 8K RAM
# RAM: start = $6000, size = $2000, define = yes;
}
SEGMENTS {
HEADER: load = HEADER, type = ro;
STARTUP: load = PRG, type = ro, define = yes;
LOWCODE: load = PRG, type = ro, optional = yes;
INIT: load = PRG, type = ro, define = yes, optional = yes;
CODE: load = PRG, type = ro, define = yes;
RODATA: load = PRG, type = ro, define = yes;
DATA: load = PRG, run = RAM, type = rw, define = yes;
VECTORS: load = VECTORS, type = rw;
SAMPLES: load = DMC, type = rw;
CHARS: load = CHR, type = rw;
CHARS2: load = CHR2, type = rw;
BSS: load = RAM, type = bss, define = yes;
HEAP: load = RAM, type = bss, optional = yes;
ZEROPAGE: load = ZP, type = zp;
}
FEATURES {
CONDES: segment = INIT,
type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__;
CONDES: segment = RODATA,
type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__;
CONDES: type = interruptor,
segment = RODATA,
label = __INTERRUPTOR_TABLE__,
count = __INTERRUPTOR_COUNT__;
}
The end of my crt0.s:
Code:
.segment "CHARS"
.incbin "tiles.chr"
.segment "CHARS2"
.incbin "tiles2.chr"
.incbin "tiles.chr"
.segment "CHARS2"
.incbin "tiles2.chr"
Switching code:
Code:
#define BANK ((char *) 0x8000)
static void screena() {
// ppu_off();
*BANK = 0;
// ppu_on_all();
}
static void screenb() {
// ppu_off();
*BANK = 1;
// ppu_on_all();
}
static void screena() {
// ppu_off();
*BANK = 0;
// ppu_on_all();
}
static void screenb() {
// ppu_off();
*BANK = 1;
// ppu_on_all();
}
The CHR files exist and are correct. At runtime it only displays from the first bank though. Shutting down the PPU for switching didn't make a difference.