It is currently Tue Nov 12, 2019 7:41 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 17 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Thu Nov 07, 2019 7:04 am 
Offline
User avatar

Joined: Sat Feb 16, 2013 11:52 am
Posts: 333
Well I'm dead set at making a platformer game similar to Super Pitfall (in map size/exploration, calm down :lol:) but there are some basic stuff about a 4/8/whatever way scrolling engine that I'm still confused about.

1. Mapper/Mirroring

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!

_________________
This is a block of text that can be added to posts you make. There is a 255 character limit.


Top
 Profile  
 
PostPosted: Thu Nov 07, 2019 8:18 am 
Offline
User avatar

Joined: Sat Jan 09, 2016 9:21 pm
Posts: 632
Location: Central Illinois, USA
Well, there are lots of ways to implement this, so it always comes down to trade-offs.

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.

Quote:
I'm going to try this but I'm always afraid it's gonna be too slow/impractical. Any techniques or hints are welcomed!


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?

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.

_________________
My games: http://www.bitethechili.com


Top
 Profile  
 
PostPosted: Thu Nov 07, 2019 8:19 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 21678
Location: NE Indiana, USA (NTSC)
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.

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:
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)


This gives a few useful settings for register $8000 that include 1-screen mirroring:

$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:
  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


After this init code runs, the following register is mapped to $8000-$FFFF:
Code:
7654 3210  PRG bank ($01) (mode $1C)
   |   ++- Select 16K PRG bank at $8000
   +------ Select nametable at $2000

_________________
Pin Eight | Twitter | GitHub | Patreon


Top
 Profile  
 
PostPosted: Thu Nov 07, 2019 10:44 am 
Offline
User avatar

Joined: Fri May 08, 2015 7:17 pm
Posts: 2592
Location: DIGDUG
The way Cobra Triangle does it seems bad. Only using 1 palette for the entire main screen. And a HUD at the bottom.

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?

_________________
nesdoug.com -- blog/tutorial on programming for the NES


Top
 Profile  
 
PostPosted: Thu Nov 07, 2019 10:55 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 21678
Location: NE Indiana, USA (NTSC)
"Is this Battletoads?"

_________________
Pin Eight | Twitter | GitHub | Patreon


Top
 Profile  
 
PostPosted: Thu Nov 07, 2019 11:08 am 
Offline
User avatar

Joined: Fri May 08, 2015 7:17 pm
Posts: 2592
Location: DIGDUG
Thank you. Battletoads. AxROM is always single screen mirroring. HUD at the top. Sprite zero hit.

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.

_________________
nesdoug.com -- blog/tutorial on programming for the NES


Top
 Profile  
 
PostPosted: Thu Nov 07, 2019 11:11 am 
Offline
User avatar

Joined: Fri Nov 19, 2004 7:35 pm
Posts: 4230
Ice Cavern, Snake Pit, and Gargantua Ducts scroll freely.

_________________
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!


Top
 Profile  
 
PostPosted: Thu Nov 07, 2019 11:14 am 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 7628
Location: Canada
Solar Jetman also does it with single screen, but a sprite 0 bottom status bar. (I think it kinda runs at 30fps to distribute the load and keep from missing the sprite 0, though.)


Top
 Profile  
 
PostPosted: Thu Nov 07, 2019 11:41 am 
Offline
User avatar

Joined: Fri May 08, 2015 7:17 pm
Posts: 2592
Location: DIGDUG
I've been looking at Solar Jetman. It has a HUD at the bottom, and I was trying to figure out how it does a Sprite zero hit when there is so much blank sky that might overlap...

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.

_________________
nesdoug.com -- blog/tutorial on programming for the NES


Last edited by dougeff on Thu Nov 07, 2019 4:30 pm, edited 1 time in total.

Top
 Profile  
 
PostPosted: Thu Nov 07, 2019 2:39 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 11432
Location: Rio de Janeiro - Brazil
No status bar, but Big Nose Freaks Out scrolls freely and uses a Sprite zero hit at the bottom right of the screen to disable rendering early. You can clearly see an opaque background tile following that corner of the screen.

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.


Top
 Profile  
 
PostPosted: Thu Nov 07, 2019 3:58 pm 
Offline
User avatar

Joined: Fri Nov 19, 2004 7:35 pm
Posts: 4230
Wizards and Warriors 3 forces a sprite 0 hit by editing the tile that will be displayed in the lower-left corner of the screen.

_________________
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!


Top
 Profile  
 
PostPosted: Thu Nov 07, 2019 6:08 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 7628
Location: Canada
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.

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.


Top
 Profile  
 
PostPosted: Thu Nov 07, 2019 6:13 pm 
Offline
User avatar

Joined: Sat Feb 16, 2013 11:52 am
Posts: 333
gauauu wrote:
But yeah, single-screen does simplify some of the math of figuring out where writes should go.


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.

Quote:
before you spend a lot of time on


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.

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.


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.

_________________
This is a block of text that can be added to posts you make. There is a 255 character limit.


Top
 Profile  
 
PostPosted: Fri Nov 08, 2019 7:54 am 
Offline
User avatar

Joined: Sat Jan 09, 2016 9:21 pm
Posts: 632
Location: Central Illinois, USA
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.


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.

_________________
My games: http://www.bitethechili.com


Top
 Profile  
 
PostPosted: Fri Nov 08, 2019 10:49 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 21678
Location: NE Indiana, USA (NTSC)
With 32K bank switching, the overall strategy is to put each subroutine in the same bank as the data it needs to access. This minimizes the amount of code that must be either duplicated across banks or copied to RAM. For example, put the metasprite drawing routine with the metasprite definitions, the background map drawing routine with the background map definitions, etc. This paradigm is easier in a 64K game than in, say, a 512K game like Lizard or Haunted: Halloween '85 because there's probably no single data type that's bigger than 32K.

_________________
Pin Eight | Twitter | GitHub | Patreon


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 17 posts ]  Go to page 1, 2  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 6 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group