Ideally I want my game to be compatible with the Nesdev Competition carts so this puts a limit on usable mappers. I'd like to have RAM for the Chara chip, but a banked ROM option would be ok.
Now, in the Mirroring page I saw that when you're using single-screen mirroring you actually get to have the unused second nametable in VRAM, so you could show a HUD with a simple nametable swap. This would be great save for one issue: how on earth will I know when it's time to switch the nametables? I'm here wondering if the classic Sprite 0 hit interrupt trick will do (as in, HUD is in top of the screen, sprite 0 + solid color denotes last "line" of hud, switch to actual playfield on interrupt).
The thing that worries me the most, though, is Nesdev wiki saying that this simplifies calculations, it's ideal for infinitely expanding playfields, etc. while Doug's blog says the opposite: single-screen mirroring is not recommended.
I would love some input on this since I fail to see the problem in the single-screen approach (and I have no idea how to render a HUD with the other options -- vert/horiz mirroring -- while maintaining a freely scrolling background). And while I'd love to have 4 nametables I'm not sure if that would even solve my problems or be compatible with the Competition cartridge mapper. Apparently cart mapper 28 support both single nametable behaviour AND Chara RAM but I don't know if I *can* mess with that stuff for a competition entry (and I really have no idea how it works or it's set up, again, pointers welcome )
2. Screen storage and retrieval
This is another area I'd love to get input for, since I haven't thought of any practical method but this one (which I'm not even sure will actually work): have the "world map" be composed of compressed single-screen (32x30) metatile maps laid down in a grid. Game peeks/fully decompresses immediate screen and surrounding screens into RAM. Draw new row/column of 16x16 metatiles whenever an AND of the nametable "camera" x/y & 0x00011111 yields '0'. Update screen "windows" with similar logic. World areas with different tilesets can handle
tile loading/bankswitch by having a connecting screen "corridor" between them with only horizontal OR vertical exits.
I'm going to try this but I'm always afraid it's gonna be too slow/impractical. Any techniques or hints are welcomed!
For using single-screen mirroring, I'm not completely sure what all Doug considered when saying it isn't recommended, but the big issue that you'll run into is attribute glitches at both the sides and the top (instead of just having to deal with one or the other). If you're effectively shrinking the screen by using a status bar from another nametable, that might be less of an issue though? If you put the HUD at the top of the screen, it should be pretty straightforward to start with it showing, then do a sprite-0 hit to switch back to whatever your main screen should display. (Putting the HUD at the bottom should be fine also, although you have do more work to figure out when to start waiting for the sprite 0 hit that's not too early and wastes all your cpu time, or too late where you miss it and it locks up). But yeah, single-screen does simplify some of the math of figuring out where writes should go.
I'm using 4 nametables for Halcyon (mostly because that's what the low-cost GTROM board supports, but it also means I don't have to worry about attribute collisions), but it does complicate the math in doing screen updates.
I think what you suggest sounds reasonable. Any scheme with compression/metatiles for all-way scrolling of large maps is going to have a cost in cpu time. Code it up and see how much cpu time it takes in the worst case. Then trade that against the demands that you want to have in the rest of the game (ie how many enemies do you want to support on screen at a time?) One thing to make sure to consider is the diagonal case -- if you hit the row update and the column update at the same time, can you do both in the same frame?I'm going to try this but I'm always afraid it's gonna be too slow/impractical. Any techniques or hints are welcomed!
Regarding compression -- before you spend a lot of time on compressing the levels, first do some quick math to make sure you actually need to. Figure out the size of the game in physical space, and the target rom size, and verify what sort of compression you think you'll actually need.
Otherwise, read on.
The Action 53 mapper defines the mode register as follows, with bits 3-0 behaving like MMC1 $8000 bits 3-0.
Code: Select all
7654 3210 Mode ($80) || ||++- Mirroring (0, 1: 1-screen, 2: vertical, 3: horizontal) || ++--- PRG bank style (0, 1: 32K, 2: fixed $8000, 3: fixed $C000) ++------ PRG size (0: 32K, 1: 64K, 2, 3: Do not use in compo entries)
$00: 1-screen mirroring, one 32K PRG bank
$10: 1-screen mirroring, two 32K PRG banks
$1C: 1-screen mirroring, four 16K PRG banks, last fixed to $C000 (UNROM style)
A 32 KiB mapper 7 entry would get translated to $00.
A 64 KiB mapper 7 entry would get translated to $10.
But there's no common discrete mapper that behaves like $1C. If you want to use 1-screen mirroring with mode $1C, you'll need to use mapper 28 in your entry, and your init code in the last 16K of the ROM needs to have this:
Code: Select all
ldy #$81 sty $5000 ; Select outer bank register lda #$FF sta $8000 ; Outer bank: $FF (will get patched out) ldx #$01 stx $5000 ; Select inner bank register sta $8000 ; Inner bank: $FF dey sty $5000 ; Select mode register lda #$1C ; 1-screen mirroring, four PRG banks, fixed at $C000 sta $8000 stx $5000 ; The game will use the inner bank register
Code: Select all
7654 3210 PRG bank ($01) (mode $1C) | ++- Select 16K PRG bank at $8000 +------ Select nametable at $2000
The way you describe it... HUD at the top, sprite zero hit, use all 4 palettes for the main screen... shouldn't look any worse than any other Horizontal Mirroring game... and the programming on the HUD would be easier.
Does anyone know of any game that uses this exact approach and does all direction scrolling?
left 8 pixels turned off. You can see attribute glitches on the right. Battletoads doesn't freely scroll in both directions, but I don't see why you couldn't make a game that does with this setup.
Maybe I will update my blog.
If you watch the PPU Viewer, It is drawing a new dot BG tile (#ff) every frame and the dot is moving around to line up to the Sprite dot (bottom left of the screen). Fascinating.
Edit. Wizards & Warriors 3 does the same thing, but it colors the sprite dot black so you can't see it. Background tile $85 is a copy of another tile, but always with a non-zero dot that lines up to the Sprite zero dot.
Seems more complicated that just having a fixed position HUD at the top.
Another game that has an opaque tile following a corner of the screen (the lower left corner in this case) is The Guardian Legend. I vaguely remember someone mentioning that the game uses DPCM IRQs firing slightly before the Sprite zero hit so the hit is never missed, but I haven't verified that myself.
EDIT: I also suspect that Pugsley's Scavenger Hunt is doing something funny with sprite 0 on the corner of the screen, but is trying to disguise it by decorating all 4 corners of the screen with spider webs.
I think it plays the DPCM every frame, but it only activates the IRQ sometimes... I think it might turn it on deliberately when a heavy load is predicted? Seems to start using the IRQ when there's a lot of enemies on screen. It's curious though, I don't know why it wouldn't just do it every time.tokumaru wrote:Another game that has an opaque tile following a corner of the screen (the lower left corner in this case) is The Guardian Legend. I vaguely remember someone mentioning that the game uses DPCM IRQs firing slightly before the Sprite zero hit so the hit is never missed, but I haven't verified that myself.
That's the idea! I love the trickery involved with some similar games but I don't really want to put tech over the actual game this time. I wanna focus on the actual game.gauauu wrote: But yeah, single-screen does simplify some of the math of figuring out where writes should go.
I'm still at the planning stage so everything's open for changes. Nothing's set in stone yet and that's on purpose so I can make a game around the NES and not the opposite.before you spend a lot of time on
I somehow missed Mapper 7 having CHR-RAM instead of ROM and this pretty much makes it the mapper I want to use, however I'm not a fan of the 32kb bankswitch so I'm gonna study if I'm making it a direct Mapper 28 game or not. Having UNROM like bankswitching would be ideal.tepples wrote:If you're fine with 32K bank switching for your 64K entry that uses single-screen mirroring, you can just use mapper 7 for your entry.
32k switching can be a pain in the butt, but if your rom is big enough and the game small enough, you can make a pseudo-fixed-bank by just repeating the important code into each bank. It's a little more work to set up though.Punch wrote: I somehow missed Mapper 7 having CHR-RAM instead of ROM and this pretty much makes it the mapper I want to use, however I'm not a fan of the 32kb bankswitch so I'm gonna study if I'm making it a direct Mapper 28 game or not. Having UNROM like bankswitching would be ideal.