CNROM and CHR bank switching

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems. See the NESdev wiki for more information.

Moderator: Moderators

User avatar
gauauu
Posts: 779
Joined: Sat Jan 09, 2016 9:21 pm
Location: Central Illinois, USA
Contact:

CNROM and CHR bank switching

Post by gauauu »

I'm trying to get CHR bank switching working in my CNROM game. Currently it works correctly in mesen, but not in fceux. I won't get a chance to try it on hardware until later this weekend, but regardless if it works on hardware, I'd like to know that it will work as expected on fceux. Is there anything obvious here that I'm doing that would make it not work right?

I've got 2 8k CHR banks, and my header is declared as:

Code: Select all

.segment "INESHDR"
  .byt "NES",$1A  ; magic signature
  .byt 2          ; PRG ROM size in 16384 byte units
  .byt 2          ; CHR ROM size in 8192 byte units
  .byt $31        ; mirroring type and mapper number lower nibble
  .byt $00        ; mapper number upper nibble
To switch banks, I'm doing:

Code: Select all

  lda #01
  sta $8000
Both mesen and fceux report that it's mapper #3 with 2 8K CHR-ROM. But fceux doesn't seem to want to switch to the 2nd bank.

I'll test on my powerpak later tonight, but regardless, I'd like be able to figure out what I might be doing that makes them differ.

Any guesses?
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: CNROM and CHR bank switching

Post by tokumaru »

Are you taking bus conflicts into account? Address $8000 must contain $01 if you want this code to succeed. Most games on boards with bus conflicts just have a table with all possible values that can be written to the mapper somewhere in ROM, and that table gets used for all mapper operations. Some emulators ignore bus conflicts.

EDIT: according to that wiki page, bus conflicts involving NES-era CPU and ROMs would result in 0s winning against 1s, so if your program starts at $8000, and you have a SEI there, SEI is opcode $78, a value whose bit 0 is 0, so this wins against the 1 you're trying to write, and the second CHR page never gets selected. Any even value at $8000 would cause this result in an emulator that simulates bus conflicts as suggested in the wiki. Also, as the wiki says, don't count on 0s winning against 1s, because different hardware (such as the PowerPak or FPGA consoles) could give different results.
User avatar
gauauu
Posts: 779
Joined: Sat Jan 09, 2016 9:21 pm
Location: Central Illinois, USA
Contact:

Re: CNROM and CHR bank switching

Post by gauauu »

Awesome, thank you. I can't test right now, but I had completely forgotten about the possibility of bus conflicts; I imagine that's the issue.

Thanks.
User avatar
rainwarrior
Posts: 8731
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: CNROM and CHR bank switching

Post by rainwarrior »

Yeah, iNES mapper 3 is one of those examples where annoyingly there isn't really consensus among emulators as to whether it should have bus conflicts or not. I think there's basically one game that relies on it, and one game that doesn't. (Otherwise the official boards do have bus conflicts but I don't think there's any known bugs where it matters.)

Also, "test on hardware" won't help with bus conflicts if your hardware is a PowerPak or something else that's not a discrete logic board, unfortunately.

You can use a submapper to specify explicitly that you want bus conflicts or not, but I'm not sure you'll find many emulators that support that at this point.
User avatar
Memblers
Site Admin
Posts: 4044
Joined: Mon Sep 20, 2004 6:04 am
Location: Indianapolis
Contact:

Re: CNROM and CHR bank switching

Post by Memblers »

This is utterly unimportant, but with simple mappers I like this trick that I stole from the SMB/DH multicart:

Code: Select all

label:
 lda #1
 sta label+1
Reuses that immediate operand as the write target. :)
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: CNROM and CHR bank switching

Post by tokumaru »

Yeah, if you're swapping to a known bank, that's one way to do it. It's a little less readable though, so if you have a complete bankswitch table somewhere already, better use that for consistency.

It's even better for consistency if you use macros to handle mapper operations, since this will make mapper changes significantly easier, in case you want to reuse an engine for other projects or whatever. You could do something like this:

Code: Select all

;selects a constant CHR bank or one specified in the accumulator
.macro SWITCH_CHR _Bank
  .ifnblank _Bank
    lda #_Bank
    sta BankswitchTable+_Bank
  .else
    tax
    sta BankswitchTable, x
  .endif
.endmacro
I have a bunch of these macros using different register combinations (in case I need to preserve certain registers) in a single file, so if ever need to mapper-hack my own programs to use a similarly-featured mapper, I can just change these macros.
Sour
Posts: 890
Joined: Sun Feb 07, 2016 6:16 pm

Re: CNROM and CHR bank switching

Post by Sour »

rainwarrior wrote:You can use a submapper to specify explicitly that you want bus conflicts or not, but I'm not sure you'll find many emulators that support that at this point.
It's not the most complete/up-to-date thing, but based on this spreadsheet, it looks like only Mesen & puNES support the mapper 3 submappers at the moment (among the ones listed here anyway): https://docs.google.com/spreadsheets/d/ ... s=58f5771c (see 3_test_1 & 3_test_2 in the list).

Mesen defaults to no bus conflicts unless submapper 2, so I'm guessing FCEUX might default to having bus conflicts.
User avatar
gauauu
Posts: 779
Joined: Sat Jan 09, 2016 9:21 pm
Location: Central Illinois, USA
Contact:

Re: CNROM and CHR bank switching

Post by gauauu »

tokumaru wrote:Are you taking bus conflicts into account? Address $8000 must contain $01 if you want this code to succeed.

Just tested, yup, that was the issue.
Memblers wrote:This is utterly unimportant, but with simple mappers I like this trick that I stole from the SMB/DH multicart:

Code: Select all

label:
 lda #1
 sta label+1
Reuses that immediate operand as the write target. :)
And for the simple situation I'm doing for this game, this was the perfect solution.

Thanks all!
lidnariq
Posts: 11429
Joined: Sun Apr 13, 2008 11:12 am

Re: CNROM and CHR bank switching

Post by lidnariq »

Sour wrote:Mesen defaults to no bus conflicts unless submapper 2, so I'm guessing FCEUX might default to having bus conflicts.
It would probably be better to not default to "not having bus conflicts"...

My personal feeling is that:
An iNES image should enforce bus conflicts, because the majority of boards do have them, and failing to enforce them produces ROM hacks that don't work on hardware.
A NES2.0 image with submapper 0 ideally would warn on a bus conflict, but enforcing is ok too.

some prior discussion.
Sour
Posts: 890
Joined: Sun Feb 07, 2016 6:16 pm

Re: CNROM and CHR bank switching

Post by Sour »

I'm not opposed to switching it - it does make sense when it comes to helping prevent new game hacks from failing to work on real hardware.
I just checked, and FCEUX does default to having bus conflicts for mapper 3 - so it would help make things more uniform on the emulator side of things, too.
User avatar
Bregalad
Posts: 8055
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Re: CNROM and CHR bank switching

Post by Bregalad »

Until now I always assumed you had to write to a ROM value that already contains the desired value, but if it is known and proved that the value written to the mapper is a logical AND between the accumulator and the ROM value written to, why bother avoiding bus conflicts ? Writing to a ROM location containing $FF will always work as intended.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: CNROM and CHR bank switching

Post by tokumaru »

Bregalad wrote:Writing to a ROM location containing $FF will always work as intended.
I don't think this is something you should rely on, if different hardware combinations could give different results. Also, isn't simply putting different values in the same bus a bad thing by itself, regardless of which value "wins" and gets registered as the bank to select?
lidnariq
Posts: 11429
Joined: Sun Apr 13, 2008 11:12 am

Re: CNROM and CHR bank switching

Post by lidnariq »

Under the best of circumstances, bus conflicts cause extra heat dissipation in the drivers; if it happens too much in too little time (where "too much" and "too little time" are relative and depend on specifics) that can cause permanent damage to the drivers.

NMOS pullups are in general pretty weak; they almost always lose a fight. But "CPU wins (appearance of no bus conflicts but still potentially damaging)", "ROM wins", and "OR bus conlicts" are also possibilities.

If any of the ancient pure PMOS ROMs are large enough and fast enough to work in the NES, I would not assume AND bus conflicts would happen there.
User avatar
Bregalad
Posts: 8055
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Re: CNROM and CHR bank switching

Post by Bregalad »

So why does the emulators that simulate bus conflicts do so with AND ? A correct emulation would simulate the system blowing up !
lidnariq
Posts: 11429
Joined: Sun Apr 13, 2008 11:12 am

Re: CNROM and CHR bank switching

Post by lidnariq »

"Don't do it repeatedly" is different from "Don't do it ever".
Post Reply