Tetris CNROM patch
by Javantea
Feb 9, 2024 - Nov 9, 2024
Github branch cnrom-0.1.patch cnrom-0.1.ips
Over a few days I was able to write most of a CNROM patch for NES Tetris. The last pieces fell into place tonight resulting in a complete port. While this won't be useful for most people, those who have a CNROM cartridge may save the time I spent on this project.
What is CNROM? It's a simple mapper for NES cartridges that can be used to create homebrew. Here's a circuit board you can have printed. Here are a list of games that use CNROM. If that does not interest you at all, then I can save you some time reading the rest of this.
Having started preparation in April 2023, I found myself putting this project off again and again because 6502 assembly is not an easy task -- even if someone has done the hard part already. Thanks to Kirjava and the TetrisGYM project I was able to copy code from their CNROM code. Hopefully my patch will make it easier for others to port their romhacks to CNROM. Why would they do that? CNROM is substantially easier to make a physical copy than MMC1, which enables homebrew authors. MMC1 clones are available at $3.50 each while the SN74HC161N is an off-the-shelf electronics component that sells for $0.64. While the MMC1 has a lot more features than the 161
, Tetris doesn't actually use any of them. Fractal161's Speedhack uses the MMC3 to do something very interesting, but that's a topic for another blog post.
So why do I want a CNROM patch for NES Tetris? I wanted an easy, source-code assisted look into the source code of NES Tetris to determine what was going on. To port valuable romhacks like jazzthief's DAS Trainer to CNROM, we will need to start with a known-good port. So now that I have that port, it should be pretty easy to port DAS Trainer. Are there any other ports that interest me? Not immediately.
For those who want to support both MMC1 and CNROM, I will be creating a version with ifdefs that will allow that.
What did I find? A lot of interesting bugs. The first was the black background for the play screen. This makes the game work like invisible mode in TetrisGYM. By changing the CHR rom to display F instead of black tiles, I found that the whole background was filled with the value 0xff
. This indicates that the data isn't being copied to the PPU.
That hindered progress for a while and I finally asked for help in #romhacking
. Kirjava was quick to help, but the final success was to check each mention of CNROM in the code. There was one missing from my code that happened to match the play screen at the bottom of render_mode_play_and_demo
. Why that happens I still don't know. It writes 0x80
to PPUCTRL. This sets the sprite and background pattern table address to 0
instead of 0x1000
, flipping which bank is being used. If you think about the CHR banks, the 161
mapper switches between the top two and the bottom two while the PPUCTRL
controls whether sprites use the first or second and whether background tiles use the first or the second. Understanding every line I copy is something that takes time and the second round of debugging uncovered that logic. The next thing was the level select screen showing garbage. A cleanup of the code -- block by block fixed this bug. Then there was a glitch at the top of the play screen.
The giveaway was that the top of the screen was using a different tileset than the rest of the screen. That indicates that there is a call to PPUCTRL which is flipping the tileset. And that is what I found when I looked. gameModeState_updateCountersAndNonPlayerState
had code to set the PPUCTRL value to use a different tileset. Removing that code fixed this glitch.
The next to last thing was the high score. It took a leap to find that moving the CNROM code to later worked. We can see that tileset is an important part of the CNROM port since that is mostly what the 161
does.
The final two things were to get low score games to have the right tiles (fixing the PPUCTRL in gameMode_levelMenu) and 18-2 B-type ending (CNROM_CHR_B_END and CNROM_CHR_B_END2).
Thanks for reading. I hope to to use this project on every romhack going forward. News as it becomes available.
Javantea out.
Permalink-
Leave a Reply
Comments: 0
Leave a reply »