This page is a mirror of Tepples' nesdev forum mirror (URL TBD).
Last updated on Oct-18-2019 Download

Setting inesprg to 2 makes game stop running

Setting inesprg to 2 makes game stop running
by on (#236449)
The mapper is set to MMC1.
I ran out of space in the two default banks, but when I set inesprg to anything other than 1 it makes the game freeze before starting.
Now, I've heard that the bank MMC1 starts is random, but I've tried putting the init code in every single bank and it didn't help, besides the init code is in the fixed bank, which leads me to believe I must have forgotten to put something somewhere, but where?

Is there something I'm missing?
Does anyone know where I can find a simple sample code for the MMC1?
Re: Setting inesprg to 2 makes game stop running
by on (#236450)
Tepples has some sample code here:
https://github.com/pinobatch/snrom-template

I'd suggest trying with some debugging emulator, such as Mesen or the windows build of FCEUX.
Re: Setting inesprg to 2 makes game stop running
by on (#236452)
To expand a bit on lidnariq's statement: This part of the MMC1 page (see paragraph after register description) explains the behaviour. If you read the content and the referenced threads, you'll see that there is some variance in which PRG bank different MMC1 chips tend to start in.

Thus, from a programmer's perspective (today), the universal solution is to put your startup code (what the RESET vector points to) at the top of every bank -- and that includes the vectors themselves. That startup code should reset the MMC1 to put it into a known state where you don't have to worry.

Tepples' snrom-template code does this through use of the STUBxx segments you see in the ld65 cfg file, combined with the startup code that consists of 16 bytes (which includes the vectors) which references said STUBxx entries. The code in resetstub_entry is what the RESET vector points to; the code is commented fairly clearly so it should make sense.

You can customise that template to work with something smaller than 2mbit; he went with the largest PRG scenario but it works universally.
Re: Setting inesprg to 2 makes game stop running
by on (#236459)
Jay John wrote:
I ran out of space in the two default banks, but when I set inesprg to anything other than 1 it makes the game freeze before starting.

You forgot to mention which assembler you're using, but from the above I guess it's NESASM?

Quote:
I must have forgotten to put something somewhere, but where?

Can't say without seeing any code.
Re: Setting inesprg to 2 makes game stop running
by on (#236463)
tokumaru wrote:
You forgot to mention which assembler you're using, but from the above I guess it's NESASM?.

Yes, that's correct.

So, I added this in every bank and it now seems to be working.

Code:
resetstub_entry:
  sei
  ldx #$FF
  txs
  stx $FFF2
  jmp reset_handler
  .addr nmi_handler, resetstub_entry, irq_handler


But I can't switch the prg banks (the chr switches work fine).
This is the code I'm using to do so:

Code:
   lda bankswitch
   sta $E000
   lsr a
   sta $E000
   lsr a
   sta $E000
   lsr a
   sta $E000
   lsr a   
   sta $E000
   rts   


First bank is fixed at bank 0 and I want to switch the last bank from bank 1 to 3, but this code is doing nothing.
Do I have to put a specific number on the "bankswitch" variable? It's currently loaded with 2, but I also tried 1 and 3.
Re: Setting inesprg to 2 makes game stop running
by on (#236464)
Have you already written to the register at $8000? If not, you should do that first. If yes, what did you write there?
Re: Setting inesprg to 2 makes game stop running
by on (#236465)
lidnariq wrote:
Have you already written to the register at $8000? If not, you should do that first. If yes, what did you write there?


Last time I've written there is when I changed mirroring

Code:
ldvermir:
   lda #$80
   sta $8000
   lda #%00011010
   sta $8000   
   lsr a
   sta $8000   
   lsr a
   sta $8000   
   lsr a
   sta $8000   
   lsr a
   sta $8000
   rts
Re: Setting inesprg to 2 makes game stop running
by on (#236466)
Let's get something out of the way: NESASM requires everything to be formatted with these stupid 8KB banks, but the NES itself has no concept of banks whatsoever, and MMC1 banks are 16KB, so the numbering you use for NESASM is not the same you'll use with the MMC1. NESASM banks 0 and 1 will be MMC1 bank 0, NESASM banks 2 and 3 will be MMC1 bank 1, and so on. The iNES header assumes 16KB banks regardless of the mapper.

Jay John wrote:
Code:
resetstub_entry:
  sei
  ldx #$FF
  txs
  stx $FFF2
  jmp reset_handler
  .addr nmi_handler, resetstub_entry, irq_handler

This is to reset the MMC1, right? Why use address $FFF2, though? I mean, I guess it works, but why not use $8000 and keep things less cryptic?

Quote:
Code:
   lda bankswitch
   sta $E000
   lsr a
   sta $E000
   lsr a
   sta $E000
   lsr a
   sta $E000
   lsr a   
   sta $E000
   rts   

This is in the fixed bank, right?

Quote:
First bank is fixed at bank 0

While the MMC1 has a PRG switching mode that fixes the first bank to $8000-$BFFF, but most people would prefer to hardwire the last bank to $C000-$FFFF, as that's way more common, and it's the default configuration.

Quote:
Do I have to put a specific number on the "bankswitch" variable? It's currently loaded with 2, but I also tried 1 and 3.

Just keep in mind what I said above: NESASM banks are 8KB, MMC1 banks are 16KB.
Re: Setting inesprg to 2 makes game stop running
by on (#236468)
tokumaru wrote:
Let's get something out of the way: NESASM requires everything to be formatted with these stupid 8KB banks, but the NES itself has no concept of banks whatsoever, and MMC1 banks are 16KB, so the numbering you use for NESASM is not the same you'll use with the MMC1. NESASM banks 0 and 1 will be MMC1 bank 0, NESASM banks 2 and 3 will be MMC1 bank 1, and so on. The iNES header assumes 16KB banks regardless of the mapper.


Oh, I've been meaning to change the assembler, but never got around to it.

So, let me see if I got this.
If I were to order them by memory, then on NESASM it'd be:

Code:
    .bank 0
    .org $8000
;code

    .bank 1
    .org $A000
;code

    .bank 2
    .org $C000
;code

    .bank 3
    .org $E000
;code


While on other assemblers it'd be:

Code:
    .bank 0
    .org $8000
;code

    .bank 1
    .org $C000
;code


Quote:
"This is to reset the MMC1, right? Why use address $FFF2, though? I mean, I guess it works, but why not use $8000 and keep things less cryptic?


Because it's how it was written in that github file, but thanks for the heads up, it makes it a lot easier to understand it.

Quote:
This is in the fixed bank, right?


Yes

Quote:
While the MMC1 has a PRG switching mode that fixes the first bank to $8000-$BFFF, but most people would prefer to hardwire the last bank to $C000-$FFFF, as that's way more common, and it's the default configuration.


It's just to get the hang of it, at the moment most of the code is organized without bank shifting in mind, I'll definitely be shuffling things around to better accommodate it later.
Re: Setting inesprg to 2 makes game stop running
by on (#236472)
Jay John wrote:
While on other assemblers it'd be:

Code:
    .bank 0
    .org $8000
;code

    .bank 1
    .org $C000
;code

Kinda, but not exactly... directives and general code organization change from assembler to assembler (e.g. most assemblers don't have a ".bank" directive). My main point is that, unlike NESASM, assemblers don't usually force the programmer to use a specific bank size, which is a good thing because bank sizes vary from mapper to mapper.
Re: Setting inesprg to 2 makes game stop running
by on (#236476)
For instance, asm6 (the assembler I prefer) has no built-in concept of banks at all, instead giving you very direct control over the layout of the file it outputs, so you might have something like this:
Code:
; iNES header
    .db "NES",$1a
    ; etc.

; bank 0
    .base $8000
    ; code...
    .org $c000      ; pad to $c000

; bank 1
    .base $c000
    ; code...
    .org $fffa      ; pad to $fffa
    .dw nmi, reset, irq

; CHR banks
    .incbin "tiles0.chr"
    .incbin "tiles1.chr"
    ; etc.
Re: Setting inesprg to 2 makes game stop running
by on (#236477)
tokumaru wrote:
Kinda, but not exactly... directives and general code organization change from assembler to assembler (e.g. most assemblers don't have a ".bank" directive). My main point is that, unlike NESASM, assemblers don't usually force the programmer to use a specific bank size, which is a good thing because bank sizes vary from mapper to mapper.


Alright, so I've set up the banks that way. But do I have to change anything else? It doesn't want to load the $C000 and $E000 banks.
Re: Setting inesprg to 2 makes game stop running
by on (#236503)
Anyone?
Re: Setting inesprg to 2 makes game stop running
by on (#236504)
Can you show the complete structure of your source code? You can omit unrelated logic/data, but I'd like to see everything from the iNES directives, going through all the .banks and .orgs, mapper writes, reset stubs and interrupt vectors. It's hard to tell what's happening when looking at just bits and pieces that don't look wrong by themselves, but may not be in the correct places or something.
Re: Setting inesprg to 2 makes game stop running
by on (#236505)
tokumaru wrote:
Can you show the complete structure of your source code? You can omit unrelated logic/data, but I'd like to see everything from the iNES directives, going through all the .banks and .orgs, mapper writes, reset stubs and interrupt vectors. It's hard to tell what's happening when looking at just bits and pieces that don't look wrong by themselves, but may not be in the correct places or something.


Code:
   .inesprg 2
   .ineschr 3
   .inesmap 1
   .inesmir %10

   .bank 0
   .org $0000
;variables

   .org $8000
   
start:
   sei
   cld
   ldx #$40
   stx $4017

   jsr ldhormir
   lda bankcheckb
   cmp #$FF
   beq .start2   
   jsr bankswitch0000bck      
   jsr bankswitchC000for      
.start2:
   jsr off
   jsr vblank
   jsr vblank
   jsr ldscrolldefault
;code
;jmp to bank1

off:   
   lda #%10001000
   sta $2000
   lda #%00000000
   sta $2001
   rts
on:
   lda #%10001000
   sta $2000
   lda #%00011110
   sta $2001
   rts

ldscrolldefault
   lda #$00
   sta scrollh
   lda #$00
   sta scrollv
   rts

vblank:
   bit $2002
   bpl vblank
   rts   
   
bankswitch0000bck:
   lda bankswitch
   sta $A000
   asl a
   sta $A000
   asl a
   sta $A000
   asl a
   sta $A000
   asl a   
   sta $A000   
   lda bankcheckb
   sec
   sbc #$01
   sta bankcheckb
   rts

bankswitch0000for:
   lda bankswitch
   sta $A000
   lsr a
   sta $A000
   lsr a
   sta $A000
   lsr a
   sta $A000
   lsr a   
   sta $A000   
   lsr a   
   sta $A000
   lda bankcheckb
   clc
   adc #$01      
   sta bankcheckb
   rts   
   
bankswitchC000for:   
   lda bankswitch
   sta $C000
   lsr a
   sta $C000
   lsr a
   sta $C000
   lsr a
   sta $C000
   lsr a   
   sta $C000
   lda bankchecks
   clc
   adc #$01
   sta bankchecks
   rts   
   
ldhormir:
   lda #$80
   sta $8000
   lda #%00011011
   sta $8000   
   lsr a
   sta $8000   
   lsr a
   sta $8000   
   lsr a
   sta $8000   
   lsr a
   sta $8000
   rts
   
ldvermir:
   lda #$80
   sta $8000
   lda #%00011010
   sta $8000   
   lsr a
   sta $8000   
   lsr a
   sta $8000   
   lsr a
   sta $8000   
   lsr a
   sta $8000
   rts

   .org $9FF0
bfind0   
   sei
   ldx #$FF
   txs
   stx $8000 
   jmp start
   .dw NMI
   .dw bfind0
   .dw bfind0   

NMI:
   lda $2002
   lda #$7E
   sta $2002
   lda #$00
   sta $2003
   lda #$00
   sta $2006
   sta $2006   
   sta $2005
   sta $2005
;code
   rts
   
   .bank 1
   .org $A000

   jsr ldvermir
   jsr bankswitch0000for
   jsr bankswitch0000for
;code
   jsr bankswitch0000bck
;jmp to bank2


   .org $BFF0
bfind   
   sei
   ldx #$FF
   txs
   stx $8000
   jmp start
   .dw NMI
   .dw bfind
   .dw bfind   
   
   .bank 2
   .org $C000
;the code that's not running

   .org $DFF0
bfind2   
   sei
   ldx #$FF
   txs
   stx $8000
   jmp start
   .dw NMI
   .dw bfind2
   .dw bfind2      
   
   .bank 3
   .org $E000
;empty      
   
   .org $FFF0
bfind3
   sei
   ldx #$FF
   txs
   stx $8000
   jmp start
   .dw NMI
   .dw bfind3
   .dw bfind3      
   
   .bank 4
   .org $0000
;tile data

   .bank 5
   .org $0000
;sprite data

   .bank 6
   .org $0000
;tile data


There may be stuff in the code I missed, but most of it is here.
Re: Setting inesprg to 2 makes game stop running
by on (#236507)
I'm not an expert in NESASM, but I think you're supposed to use .rsset and .rs for declaring variables... I suspect that having .org $0000 and then .org $8000 in bank 0 is generating a lot of blank ROM data, which gets output to the final ROM, throwing bank sizes and addresses off.

Your NMI is placed after the end of bank 0 and before the start of bank 1. I have no idea how NESASM handles that. The NMI handler should be somewhere within the fixed bank.

As for the reset stubs, they need to be present in every MMC1 bank, not every NESASM bank. The unnecessary stubs and vectors probably aren't causing any problems, but I though I'd point out that you only really need the ones in odd NESASM banks (1 and 3).

You can't have 3 CHR banks. ROM sizes must be powers of 2, so the number of banks needs to be a power of 2 too (1, 2, 4, 8, 16, and so on). Emulators may refuse to load ROMs with weird chip sizes, or map then in inconsistent ways.
Re: Setting inesprg to 2 makes game stop running
by on (#236509)
tokumaru wrote:
I'm not an expert in NESASM, but I think you're supposed to use .rsset and .rs for declaring variables... I suspect that having .org $0000 and then .org $8000 in bank 0 is generating a lot of blank ROM data, which gets output to the final ROM, throwing bank sizes and addresses off.


So, instead of doing it like this:

Code:
   .bank 0
   .org $0000
characterselected      = $0001
changescreen           = $0002
loadtext               = $0003
position               = $0004


I should do it like this?

Code:
   .bank 0
   .org $8000
   .rsset $0000
characterselected      .rs 0

   .rsset $0001
changescreen           .rs 0

   .rsset $0002
loadtext               .rs 0

   .rsset $0003
position               .rs 0


tokumaru wrote:
Your NMI is placed after the end of bank 0 and before the start of bank 1. I have no idea how NESASM handles that. The NMI handler should be somewhere within the fixed bank.


Sorry, that was a mistake I made when I copy and pasted it, the NMI is actually before the .org $9FF0

tokumaru wrote:
As for the reset stubs, they need to be present in every MMC1 bank, not every NESASM bank. The unnecessary stubs and vectors probably aren't causing any problems, but I though I'd point out that you only really need the ones in odd NESASM banks (1 and 3).

You can't have 3 CHR banks. ROM sizes must be powers of 2, so the number of banks needs to be a power of 2 too (1, 2, 4, 8, 16, and so on). Emulators may refuse to load ROMs with weird chip sizes, or map then in inconsistent ways.


Alright, so I fixed these, but I'm still not able to load what's on bank 2 and 3.
Re: Setting inesprg to 2 makes game stop running
by on (#236512)
How big is the final .NES file, in bytes?
Re: Setting inesprg to 2 makes game stop running
by on (#236516)
tokumaru wrote:
How big is the final .NES file, in bytes?


65552 bytes
Re: Setting inesprg to 2 makes game stop running
by on (#236523)
That's correct for 16 bytes + 2x 16KB + 4x 8KB, so it doesn't look like there's any big discrepancy between what you're trying to make and what the assembler is actually outputting.

The best thing to do IMO would be to trace through your program in FCEUX or Mesen... Open the debugger, pause execution and reset, then step through the instructions to see where things go wrong. This will quickly tell you if the MMC1 initialization is working, whether the fixed bank is mapped correctly, whether the bankswitch code is being correctly called...
Re: Setting inesprg to 2 makes game stop running
by on (#236525)
Jay John wrote:
Code:
ldhormir:
   lda #$80
   sta $8000
   lda #%00011011
   sta $8000   
   lsr a
This may be what's going wrong...

The effect of writing to the MMC1 with the $80s bit set is to set both "P" bits, which sets a fixed bank at $C000-$FFFF equal to the last bank. You then immediately switch that to the fixed $8000-$BFFF configuration... so your code is probably going haywire here.

You should never need to write to the MMC1's "reset" bit after you actually reset.
Re: Setting inesprg to 2 makes game stop running
by on (#236528)
tokumaru wrote:
That's correct for 16 bytes + 2x 16KB + 4x 8KB, so it doesn't look like there's any big discrepancy between what you're trying to make and what the assembler is actually outputting.

The best thing to do IMO would be to trace through your program in FCEUX or Mesen... Open the debugger, pause execution and reset, then step through the instructions to see where things go wrong. This will quickly tell you if the MMC1 initialization is working, whether the fixed bank is mapped correctly, whether the bankswitch code is being correctly called...


Would a problem like this also affect CHR banks? Because I'm having no problem with these.

Though I feel I haven't described the problem properly.
What happens is: The code seems to run properly through bank 0 and 1, but then I put a JMP in bank 1 to go to a routine that's at the beginning of bank 2, but instead of loading what's in bank 2, it loads what's in bank 0, basically restarting the game, but with the wrong data, making everything look glitched.

I think that the game is loading the part in the memory where the jump leads to, but in bank 0, I've no idea why though.
I've even move the location of the routine in bank 2 and it seems to confirm my theory that that's what's happening, since it loads a different screen that's in bank 0.
Re: Setting inesprg to 2 makes game stop running
by on (#236532)
To solve your problem, you're going to have to step through your code in a debugger. FCEUX can do this, or Mesen. The one advantage (in this case) that Mesen has is that its debugger GUI shows you what PRG bank is actively mapped to what memory range (look at the bottom of the debugger window). Situations like "I ask for PRG bank 2 but I get PRG bank 0!" can 100% be watched/monitored by stepping through your bankswitch routine in the debugger.

The situation would affect CHR banks too, naturally, depending on what you're doing right or wrong. It just happens to be "easier" to figure out CHR bank swap issues because your code still works / nothing crashes, you just get the wrong tiles/pattern table data (for CHR-ROM, that is).

See lidnariq's post first, though. It looks like your mapper bank switch code is faulty.
Re: Setting inesprg to 2 makes game stop running
by on (#236535)
Jay John wrote:
Though I feel I haven't described the problem properly.
What happens is: The code seems to run properly through bank 0 and 1, but then I put a JMP in bank 1 to go to a routine that's at the beginning of bank 2, but instead of loading what's in bank 2, it loads what's in bank 0, basically restarting the game, but with the wrong data, making everything look glitched.

I think that the game is loading the part in the memory where the jump leads to, but in bank 0, I've no idea why though.
I've even move the location of the routine in bank 2 and it seems to confirm my theory that that's what's happening, since it loads a different screen that's in bank 0.

It sounds like your bank 0 and bank 2 have the same program counter, but the example code you posted does not reflect that.
Could it be that you just accidentally mapped bank 0 to be in the address space where you expect your bank 2 to be after init? That you actually have bank 0 mapped both in $8000 and $C000?
Re: Setting inesprg to 2 makes game stop running
by on (#236542)
lidnariq wrote:
This may be what's going wrong...

The effect of writing to the MMC1 with the $80s bit set is to set both "P" bits, which sets a fixed bank at $C000-$FFFF equal to the last bank. You then immediately switch that to the fixed $8000-$BFFF configuration... so your code is probably going haywire here.

You should never need to write to the MMC1's "reset" bit after you actually reset.


Done it, still nothing though...

koitsu wrote:
To solve your problem, you're going to have to step through your code in a debugger. FCEUX can do this, or Mesen. The one advantage (in this case) that Mesen has is that its debugger GUI shows you what PRG bank is actively mapped to what memory range (look at the bottom of the debugger window). Situations like "I ask for PRG bank 2 but I get PRG bank 0!" can 100% be watched/monitored by stepping through your bankswitch routine in the debugger.

The situation would affect CHR banks too, naturally, depending on what you're doing right or wrong. It just happens to be "easier" to figure out CHR bank swap issues because your code still works / nothing crashes, you just get the wrong tiles/pattern table data (for CHR-ROM, that is).


I've been checking debbugers and messing around with the code, and here's a thing I've noticed:

In the reset routine, I load #$80 into x:

Code:
bfind   
   sei
   ldx #$80
   txs
   stx $8000
   jmp start
   .dw NMI
   .dw bfind
   .dw bfind   


However if I load #$00 or any binary without the most significant bit the problem now is with the CHR banks not the PRG one.
Re: Setting inesprg to 2 makes game stop running
by on (#236543)
Mesen's debugger literally tells you what banks are mapped to CPU and PPU memory. You should really pay attention to that and find where it ceases to be what you believe it should be.
Re: Setting inesprg to 2 makes game stop running
by on (#236546)
lidnariq wrote:
Mesen's debugger literally tells you what banks are mapped to CPU and PPU memory. You should really pay attention to that and find where it ceases to be what you believe it should be.


Already checked it, it's like this at the beginning:
Image

But after a frame it's like this:
Image

That's why I was checking the start and reset code.
Re: Setting inesprg to 2 makes game stop running
by on (#236547)
Jay John wrote:
But after a frame it's like this

Step trough the code to see when exactly it changes to this.
Re: Setting inesprg to 2 makes game stop running
by on (#236549)
tokumaru wrote:
Jay John wrote:
But after a frame it's like this

Step trough the code to see when exactly it changes to this.


Done it it's when it reaches the last "sta $8000".

Code:
ldhormir:
   lda #%00011011
   sta $8000   
   lsr a
   sta $8000   
   lsr a
   sta $8000   
   lsr a
   sta $8000   
   lsr a
   sta $8000
   rts
Re: Setting inesprg to 2 makes game stop running
by on (#236550)
What are you trying to get the MMC1 to do? The behavior you're seeing is correct for the value you're writing...
Re: Setting inesprg to 2 makes game stop running
by on (#236551)
lidnariq wrote:
What are you trying to get the MMC1 to do? The behavior you're seeing is correct for the value you're writing...


Change the mirroring.
Re: Setting inesprg to 2 makes game stop running
by on (#236552)
And what value do you want for the other bits that are set at the same time?
Re: Setting inesprg to 2 makes game stop running
by on (#236553)
lidnariq wrote:
And what value do you want for the other bits that are set at the same time?


Fix bank at $8000 (for now) in prg and switch 4 kb at a time in chr
Re: Setting inesprg to 2 makes game stop running
by on (#236554)
When you boot up, you write $80 to $8000, resetting the MMC1. That sets the bank at $C000 to bank 15, and leaves the bank at $8000 undefined.
Shortly afterwards, you write %110MM (M=mirroring) to the MMC1 at $8000, which sets the bank at $8000 to bank 0, and leaves the bank at $C000 undefined.
So you have to set things up to handle this.

One possibility would be to have multiple reset stages:
One in every 16K bank that writes $80 to $8000, resetting the MMC1's shift register and setting the bank at $C000 to be known
edit: now you have a temporary fixed bank 15, which contains code that writes %00000 or %10000 to $A000 so that the bank at $8000 is the same bank #0 that will happen when you switch layouts
jumps to the "real" code in your desired fixed bank
which then writes $110MM to $8000 so that the bank at $C000 is the one that can be changed.

After all this dance, both 16K banks will be at bank 0, and subsequent writes to $A000 will set the bank at $C000, as you apparently desire.
Re: Setting inesprg to 2 makes game stop running
by on (#236555)
lidnariq wrote:
When you boot up, you write $80 to $8000, resetting the MMC1. That sets the bank at $C000 to bank 15, and leaves the bank at $8000 undefined.
Shortly afterwards, you write %110MM (M=mirroring) to the MMC1 at $8000, which sets the bank at $8000 to bank 0, and leaves the bank at $C000 undefined.

At this point, I think you should reconsider your decision to make $8000-$BFFF fixed, since it's the switch from the more common setup (fixed bank at $C000-$FFFF) to the alternate one that might be causing you problems. The only real justification for making $C000-$FFFF switchable is if you need to bankswitch DPCM samples, which is not very common in actual games, considering you wouldn't be able to use bankswitching for other purposes.
Re: Setting inesprg to 2 makes game stop running
by on (#236563)
tokumaru wrote:
lidnariq wrote:
When you boot up, you write $80 to $8000, resetting the MMC1. That sets the bank at $C000 to bank 15, and leaves the bank at $8000 undefined.
Shortly afterwards, you write %110MM (M=mirroring) to the MMC1 at $8000, which sets the bank at $8000 to bank 0, and leaves the bank at $C000 undefined.

At this point, I think you should reconsider your decision to make $8000-$BFFF fixed, since it's the switch from the more common setup (fixed bank at $C000-$FFFF) to the alternate one that might be causing you problems. The only real justification for making $C000-$FFFF switchable is if you need to bankswitch DPCM samples, which is not very common in actual games, considering you wouldn't be able to use bankswitching for other purposes.


Done it, and it's finally working!
Thanks!!!