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

Issue with replacing tiles during gameplay... :(

Issue with replacing tiles during gameplay... :(
by on (#174766)
Hey Guys:

I'm currently working on a Berzerk / Frenzy port (I did one for the Atari 7800 a while back, and now I'm trying to port it here).

But, I'm running into trouble. In Frenzy, if you shoot part of a wall it gets removed. This means I need to replace the tile with another one depending on what section gets shot. This part is working. However, being that you cannot replace a tile outside of vblank (or shut the screen off which I cannot do), I need to wait for vblank to check if all of the shots (2 player shots and up to 5 robot shots) have hit a section a wall. This means running a routine up to 7 times to read tiles and replace if necessary. I am also doing the DMA transfer of sprite data during this time.

As you can probably guess, I am running out fo vblank time. At least I think that is what is happening; the more shots that are out, the more screen 'jumping' I get. If I just have the player shoot one shot (or most of the time two), the screen is solid as can be.
This discourages me, because I still haven't added the routines for the player / playfield collision detection yet, nor the robot / playfield collision detection. And from what I understand, this can also only be done during vblank because reading from $2007 outside of vblank seems to cause screen jumping as well.

NOTE: I am not using any mapper (i.e. mapper 0)... I'd like to be able to make a cart of this when I have completed it.

EDIT: Video of it in action: ...

Can anyone think of any suggestions? I'm new to NES development, but I've done many games for the Atari 7800 so I am not new to game programming...
Thanks! :)

Re: Issue with replacing tiles during gameplay... :(
by on (#174769)
The limited bandwidth to the PPU basically requires that NES games maintain a separation of view from game model. (So you should try restructuring your game to keep state where the CPU can to directly address it rather than via $2007)

If find you need more RAM CPU-side, you could add extra to the virtual emulated cartridge using a NES 2.0 header. (Not all emulators honor it, though, but most that don't assume the game already has 8 KiB available from $6000-$7FFF)
Re: Issue with replacing tiles during gameplay... :(
by on (#174774)
For example, RHDE keeps a copy of the playfield in main RAM at $0300-$05FF.
Re: Issue with replacing tiles during gameplay... :(
by on (#174778)

It's funny you both should mention that, when I first started having this issue I started thinking I would have to keep another 'copy' of the screen in memory and work with that. However I didn't think I had enough memory for that, but I guess that's the only way to get past this. I'll have to make room somehow. I'd like to keep this without any extra 'additions' (i.e. RAM, mappers, etc.).

What I guess I can do, is use the 'copy' of the screen that is in memory, and make a list of tiles that need to be replaced each frame (Row, Column, New Tile). I can work on that list during vblank, and that would use much less CPU time. :)

Thanks guys! I'll let you know how I make out. :)
Re: Issue with replacing tiles during gameplay... :(
by on (#174780)
If you made a collision map of each room, and made it a grid of 16x16 sections, it would fit nicely in 240 bytes. You wouldn't have to make the walls 16 pixels wide, just the collision map.

Do all your calculations for what tiles need to be changed based on the map, and 'buffer' all the writes to the PPU, so you can do them quickly in V-blank.
Re: Issue with replacing tiles during gameplay... :(
by on (#174781)
Thank you :)

The only issue with that, is that each tile is broken up into 4x4 sections. (The arcade 'Frenzy' has it's wall sections as 4 pixels by 4 pixels), so I had to convert each tile to have a variation of a 4x4 tile with different sections removed. So I have to know not only if there's a tile there or not, but *which* tile to map the collision against. This is so I know if there's a wall piece in the quadrant of the tile that the player / robot / missile collided with.

Re: Issue with replacing tiles during gameplay... :(
by on (#174782)
So in other words, the resolution of the "Bad Apple" demo. If the playfield is 64 cells wide by 48 cells tall, with 1 bit per cell, it can fit in a 16x24 = 384 byte grid, with each byte representing 4x2 cells. That's the worst case.

But from what I see in screenshots, the game is played on a grid of 6x4 large cells with each large cell 10 small cells (40 pixels) on a side. And the wall blocks can be placed only on the edges of this grid. So you have five rows of 61 cells and seven columns of 40 cells, for a lot less memory.
Re: Issue with replacing tiles during gameplay... :(
by on (#174785)
I agree that if you pack the data correctly, you can represent those levels in RAM just fine. But if you feel like you really need to read the name tables in order to make decisions, you could spread the logic across 2 frames: during the first vblank you read all the necessary tiles and buffer them, then, during the game logic, you make all the decisions based on those tiles and buffer the appropriate updates for the next vblank. This way you'll not be wasting precious vblank time with logic, you'll only be using it for transferring data.
Re: Issue with replacing tiles during gameplay... :(
by on (#174787)
Looks great so far. If you include the speech samples (I hope so!) using the DPCM channel, keep in mind that the $2007 register can not be read reliably while a sample is playing. It'll be fine in emulators probably, but on the NES, it will be a problem..

Even when DPCM isn't involved, reading $2007 AFAIK is pretty rare in NES games, all the situations I can think of was for reading data from CHR-ROM because they ran out of room in PRG-ROM. Reading nametables can be pretty awkward, as you've found.
Re: Issue with replacing tiles during gameplay... :(
by on (#174790)
Read-modify-write operations in attribute tables are quite common, I believe. Less common, but still used, RMW operations of CHR-RAM tiles, for instance in Squaresoft games.
Re: Issue with replacing tiles during gameplay... :(
by on (#176100)
Thanks, everyone, for your help.

I have reserved a section of memory to 'mirror' the screen. I do all checks for the maze against that, and if I have to replace a tile, I build a list and do it during VBLANK.
Here is where I am so far:

Still have a way to go, though. Sound and possibly voice (if I can figure out how to do play samples on the NES) are last.