Hello!
For some reason I cannot get any bank other then bank 02 to load (in a 4 bank UNROM).
I've tried reducing it down to the bare essentials, and have had a look at the very helpful sample project nathan posted (thanks!) but I still can't figure out what is wrong.
I'm using CHRAM, and testing it by storing the tiles in different banks before loading them in to the ram. If I load from bank 2, it works fine. If I try any other bank, it does nothing. Switching banks appears to do nothing.
My config file looks like this (I've only recently added the ONCE segment, as I added initlib to my reset.s file):
The only clue I've been able to uncover is that if I swap the order of the PRG bank declarations (so I declare them PRG2, PRG1, PRG0 for instance) the program does not seem to automatically load PRG2.
My startup code looks like this (I've removed a bunch of functions to make it clearer - things like vblanks, etc, and the mytiles code which is just the code from the wiki):
Even though I call lda #$01, the program still seems to have bank 2 attached, as it loads the tiles in to the chr-ram from there. Is there anything obviously wrong with this?
For some reason I cannot get any bank other then bank 02 to load (in a 4 bank UNROM).
I've tried reducing it down to the bare essentials, and have had a look at the very helpful sample project nathan posted (thanks!) but I still can't figure out what is wrong.
I'm using CHRAM, and testing it by storing the tiles in different banks before loading them in to the ram. If I load from bank 2, it works fine. If I try any other bank, it does nothing. Switching banks appears to do nothing.
My config file looks like this (I've only recently added the ONCE segment, as I added initlib to my reset.s file):
Code:
MEMORY {
ZP: start = $00, size = $100, type = rw, define = yes;
OAM1: start = $0200, size = $0100, define = yes;
RAM: start = $0400, size = $0500, define = yes;
HEADER: start = $0, size = $10, file = %O ,fill = yes;
PRG0: start = $8000, size = $4000, file = %O, fill = yes, define = yes;
PRG1: start = $8000, size = $4000, file = %O, fill = yes, define = yes;
PRG2: start = $8000, size = $4000, file = %O, fill = yes, define = yes;
PRG3: start = $c000, size = $3ffa, file = %O ,fill = yes, define = yes;
VECTORS: start = $fffa, size = $6, file = %O, fill = yes;
#had to add this to get initlib to work
ONCE: start = $0000, size = $0000;
}
SEGMENTS {
HEADER: load = HEADER, type = ro;
ROM0: load = PRG0, type = ro, define = yes;
ROM1: load = PRG1, type = ro, define = yes;
ROM2: load = PRG2, type = ro, define = yes;
STARTUP: load = PRG3, type = ro, define = yes;
LOWCODE: load = PRG3, type = ro, optional = yes;
INIT: load = PRG3, type = ro, define = yes, optional = yes;
CODE: load = PRG3, type = ro, define = yes;
RODATA: load = PRG3, type = ro, define = yes;
DATA: load = PRG3, run = RAM, type = rw, define = yes;
VECTORS: load = VECTORS, type = rw;
BSS: load = RAM, type = bss, define = yes;
HEAP: load = RAM, type = bss, optional = yes;
ZEROPAGE: load = ZP, type = zp;
OAM: load = OAM1, type = bss, define = yes;
ONCE: load=PRG3, type=ro, optional=yes;
}
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__;
}
SYMBOLS {
__STACK_SIZE__: type = weak, value = $0400;
__STACK_START__: type = weak, value = $500;
}
ZP: start = $00, size = $100, type = rw, define = yes;
OAM1: start = $0200, size = $0100, define = yes;
RAM: start = $0400, size = $0500, define = yes;
HEADER: start = $0, size = $10, file = %O ,fill = yes;
PRG0: start = $8000, size = $4000, file = %O, fill = yes, define = yes;
PRG1: start = $8000, size = $4000, file = %O, fill = yes, define = yes;
PRG2: start = $8000, size = $4000, file = %O, fill = yes, define = yes;
PRG3: start = $c000, size = $3ffa, file = %O ,fill = yes, define = yes;
VECTORS: start = $fffa, size = $6, file = %O, fill = yes;
#had to add this to get initlib to work
ONCE: start = $0000, size = $0000;
}
SEGMENTS {
HEADER: load = HEADER, type = ro;
ROM0: load = PRG0, type = ro, define = yes;
ROM1: load = PRG1, type = ro, define = yes;
ROM2: load = PRG2, type = ro, define = yes;
STARTUP: load = PRG3, type = ro, define = yes;
LOWCODE: load = PRG3, type = ro, optional = yes;
INIT: load = PRG3, type = ro, define = yes, optional = yes;
CODE: load = PRG3, type = ro, define = yes;
RODATA: load = PRG3, type = ro, define = yes;
DATA: load = PRG3, run = RAM, type = rw, define = yes;
VECTORS: load = VECTORS, type = rw;
BSS: load = RAM, type = bss, define = yes;
HEAP: load = RAM, type = bss, optional = yes;
ZEROPAGE: load = ZP, type = zp;
OAM: load = OAM1, type = bss, define = yes;
ONCE: load=PRG3, type=ro, optional=yes;
}
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__;
}
SYMBOLS {
__STACK_SIZE__: type = weak, value = $0400;
__STACK_START__: type = weak, value = $500;
}
The only clue I've been able to uncover is that if I swap the order of the PRG bank declarations (so I declare them PRG2, PRG1, PRG0 for instance) the program does not seem to automatically load PRG2.
My startup code looks like this (I've removed a bunch of functions to make it clearer - things like vblanks, etc, and the mytiles code which is just the code from the wiki):
Code:
.import _main
.export __STARTUP__:absolute=1, _vblankwait, _get_input, _blanksprite, _bankswitch_a, _bankswitch_nosave
.importzp _NMI_flag, _Frame_Count, _joypad1, _joypad1old, _joypad1test, _joypad2, _joypad2old, _joypad2test, _current_bank
.import initlib,push0,popa,popax,_main,zerobss,copydata
.import __STACK_START__, __STACK_SIZE__
.include "zeropage.inc"
PPUMASK = $2001
PPUADDR = $2006
PPUDATA = $2007
DMC_FREQ =$4010 ;copied from dougs tutorial
.segment "ZEROPAGE"
current_bank: .res 1
.segment "HEADER"
.byte $4e,$45,$53,$1a
.byte 04
.byte 00
.byte 02
.byte 02
.res 8,0
.segment "STARTUP"
reset:
sei
cld
ldx #$40
stx $4017
ldx #$ff
txs
inx
stx $2000 ; disable NMI
stx $2001 ; disable rendering
stx $4010 ; disable DMC IRQs
jsr _vblankwait
;ppu wont stablise for around 30,000 cycles, so may as well clear ram
clear_memory:
lda #$00
sta $0000, x
sta $0100, x
sta $0200, x
sta $0300, x
sta $0400, x
sta $0500, x
sta $0600, x
sta $0700, x
lda #$fe
sta $0200, x ;this moves the sprites off screen
inx
bne clear_memory
jsr _vblankwait
;ppu should be stable now. copy tiles in.
lda #$01
jsr _bankswitch_a
jsr _copy_mytiles_chr
jsr zerobss
jsr copydata
lda #<(__STACK_START__+__STACK_SIZE__)
sta sp
lda #>(__STACK_START__+__STACK_SIZE__)
sta sp+1 ; Set the c stack pointer
jsr initlib
lda $2002
jmp _main
.segment "CODE"
_bankswitch_a:
tay
sty _current_bank ; save the current bank in RAM so the NMI handler can restore it
_bankswitch_nosave:
lda banktable, y ; read a byte from the banktable
sta banktable, y ; and write it back, switching banks
rts
.segment "ROM0"
.segment "ROM1"
.segment "ROM2"
mytiles_chr: .incbin "tiles.chr"
.segment "RODATA"
banktable: ; Write to this table to switch banks.
.byte $00, $01, $02, $03, $04, $05, $06
.segment "VECTORS"
.word nmi
.word reset
.word irq
.export __STARTUP__:absolute=1, _vblankwait, _get_input, _blanksprite, _bankswitch_a, _bankswitch_nosave
.importzp _NMI_flag, _Frame_Count, _joypad1, _joypad1old, _joypad1test, _joypad2, _joypad2old, _joypad2test, _current_bank
.import initlib,push0,popa,popax,_main,zerobss,copydata
.import __STACK_START__, __STACK_SIZE__
.include "zeropage.inc"
PPUMASK = $2001
PPUADDR = $2006
PPUDATA = $2007
DMC_FREQ =$4010 ;copied from dougs tutorial
.segment "ZEROPAGE"
current_bank: .res 1
.segment "HEADER"
.byte $4e,$45,$53,$1a
.byte 04
.byte 00
.byte 02
.byte 02
.res 8,0
.segment "STARTUP"
reset:
sei
cld
ldx #$40
stx $4017
ldx #$ff
txs
inx
stx $2000 ; disable NMI
stx $2001 ; disable rendering
stx $4010 ; disable DMC IRQs
jsr _vblankwait
;ppu wont stablise for around 30,000 cycles, so may as well clear ram
clear_memory:
lda #$00
sta $0000, x
sta $0100, x
sta $0200, x
sta $0300, x
sta $0400, x
sta $0500, x
sta $0600, x
sta $0700, x
lda #$fe
sta $0200, x ;this moves the sprites off screen
inx
bne clear_memory
jsr _vblankwait
;ppu should be stable now. copy tiles in.
lda #$01
jsr _bankswitch_a
jsr _copy_mytiles_chr
jsr zerobss
jsr copydata
lda #<(__STACK_START__+__STACK_SIZE__)
sta sp
lda #>(__STACK_START__+__STACK_SIZE__)
sta sp+1 ; Set the c stack pointer
jsr initlib
lda $2002
jmp _main
.segment "CODE"
_bankswitch_a:
tay
sty _current_bank ; save the current bank in RAM so the NMI handler can restore it
_bankswitch_nosave:
lda banktable, y ; read a byte from the banktable
sta banktable, y ; and write it back, switching banks
rts
.segment "ROM0"
.segment "ROM1"
.segment "ROM2"
mytiles_chr: .incbin "tiles.chr"
.segment "RODATA"
banktable: ; Write to this table to switch banks.
.byte $00, $01, $02, $03, $04, $05, $06
.segment "VECTORS"
.word nmi
.word reset
.word irq
Even though I call lda #$01, the program still seems to have bank 2 attached, as it loads the tiles in to the chr-ram from there. Is there anything obviously wrong with this?