Triangle rasterization substitute.
Moderator: Moderators
Triangle rasterization substitute.
I'm considering making a rewrite of a sailing game I made a few years ago in Pico8:
https://www.lexaloffle.com/bbs/?tid=2802
The boat was drawn using triangle rasterization so it could rotate and animate smoothly. I'm wondering if people know of any good ideas to do this on the NES?
My thoughts:
1) Lots of frames. 64 16x16 frames would fill up a whole sprite page... and that's not a lot of rotation + sail combinations.
2) Use scanline interrputs to smear some sprites across the screen. (Sounds hard)
3) Use CHR RAM and render into that. (Maybe hard? Sounds like only Battletoads does this?)
4) Break the sprite into some pieces and move those around independently? (Not sure how to make this look good)
5) Try making a more suitable game for the NES... I have some puzzle games I could make, but they aren't as exciting. :p
https://www.lexaloffle.com/bbs/?tid=2802
The boat was drawn using triangle rasterization so it could rotate and animate smoothly. I'm wondering if people know of any good ideas to do this on the NES?
My thoughts:
1) Lots of frames. 64 16x16 frames would fill up a whole sprite page... and that's not a lot of rotation + sail combinations.
2) Use scanline interrputs to smear some sprites across the screen. (Sounds hard)
3) Use CHR RAM and render into that. (Maybe hard? Sounds like only Battletoads does this?)
4) Break the sprite into some pieces and move those around independently? (Not sure how to make this look good)
5) Try making a more suitable game for the NES... I have some puzzle games I could make, but they aren't as exciting. :p
Re: Triangle rasterization substitute.
Not possible at all. On the NES, sprites can only be changed once per redraw¹.slembcke wrote:2) Use scanline interrputs to smear some sprites across the screen. (Sounds hard)
¹ There's one game that disables rendering for five lines in the middle of the screen to upload a new set of sprites.
At the very least, Solstice uses dynamic CHR RAM compositing to move the player character behind the background. I wouldn't be surprised if it's actually quite frequent among games with CHR RAM.3) Use CHR RAM and render into that. (Maybe hard? Sounds like only Battletoads does this?)
- FrankenGraphics
- Formerly WheelInventor
- Posts: 2064
- Joined: Thu Apr 14, 2016 2:55 am
- Location: Gothenburg, Sweden
- Contact:
Re: Triangle rasterization substitute.
-I think you could shear a sprite somewhat within its boxy constraints, and without breaking the cpu budget. Actually, i seem to remember tepples had a demo like that. Shearing could be used interim between coarser rotation frames.
-8x16 mode can be somewhat unhelpful in a way when it comes to rotation, but in a way which shouldn't matter here. More importantly with this mode, you get access to both pattern tables for sprites. As a side, you need less sprites which can save you some cpu time.
-Pair that with MMC5 and you have 8kB for sprites and an additional 4kB for background (mmc5 has 12kB:s unlike most mappers, but you can only access it all in 8x16 mode)
-Or you can use a mapper like cheapocabra which can flick chr-ram pages like it was chr-rom, since it has 16kB. Keep a duplicate of the background and you'll essentially get something like MMC5, except you can only use one page of sprite chr at a time. Or use as much of the total 16kB for sprites as you want and let the background have less tiles to work with.
-lastly, you might be able to update chr-ram continously, but there's a limit to how many tiles you can update in one frame. I see Solstice already got mentioned.
-8x16 mode can be somewhat unhelpful in a way when it comes to rotation, but in a way which shouldn't matter here. More importantly with this mode, you get access to both pattern tables for sprites. As a side, you need less sprites which can save you some cpu time.
-Pair that with MMC5 and you have 8kB for sprites and an additional 4kB for background (mmc5 has 12kB:s unlike most mappers, but you can only access it all in 8x16 mode)
-Or you can use a mapper like cheapocabra which can flick chr-ram pages like it was chr-rom, since it has 16kB. Keep a duplicate of the background and you'll essentially get something like MMC5, except you can only use one page of sprite chr at a time. Or use as much of the total 16kB for sprites as you want and let the background have less tiles to work with.
-lastly, you might be able to update chr-ram continously, but there's a limit to how many tiles you can update in one frame. I see Solstice already got mentioned.
Re: Triangle rasterization substitute.
If you swapped sprites every frame...and half of the frames had transparent bits where the other had solid bits...it would look blurry (on a CRT). On a flatscreen TV, it will probably not work correctly at all. (IDK)smear
Shifting sprites in VRAM byte by byte is not trivial. This effect should be pre-rendered.
(Edited)
nesdoug.com -- blog/tutorial on programming for the NES
Re: Triangle rasterization substitute.
CHR RAM is how I would do it. I would not consider it "hard", in fact, I think it would be a lot easier than other techniques.
Is this even possible? I think you're mistaken. Sprites aren't effected by scroll.2) Use scanline interrputs to smear some sprites across the screen. (Sounds hard
Re: Triangle rasterization substitute.
Haunted: Halloween '85 double-buffers all character animations into CHR RAM. So does my sprite shrinking demo.slembcke wrote:3) Use CHR RAM and render into that. (Maybe hard? Sounds like only Battletoads does this?)
As FrankenGraphics alluded, if you precompute a few rotation frames for the hull and sail, you should be able to generate inbetween frames by shearing a sprite. This slides 8-pixel-wide columns of sprites or 8-pixel-tall rows of sprites to the left by 1 or 2 pixels. Battletoads uses a similar technique to draw the walker legs in level 1 and the rope in level 2.4) Break the sprite into some pieces and move those around independently? (Not sure how to make this look good)
MMC3 is among these mappers. The Curse of Possum Hollow uses what amounts to TGROM with the 6264 (8Kx8 SRAM) CHR RAM replaced with a 62256 (32Kx8 SRAM).FrankenGraphics wrote:Or you can use a mapper like cheapocabra which can flick chr-ram pages like it was chr-rom
Re: Triangle rasterization substitute.
I don't know where this misconception that animating characters through CHR-RAM updates is hard or rare... It's a little rarer on the NES because unlike most other consoles, CHR-ROM is a possibility, but it's still pretty common. Here's a list of CHR-RAM games I just checked that animate one or more characters via pattern table updates:slembcke wrote:3) Use CHR RAM and render into that. (Maybe hard? Sounds like only Battletoads does this?)
Alfred Chicken
Asterix
Bad Street Brawler
Battle Chess
Battletoads
Best of the Best - Championship Karate
California Games
Castelian
Cobra Triangle <-------- THIS ONE IS EVEN ROTATING A BOAT!
Danny Sullivan's Indy Heat
Defender of the Crown
Dragon's Lair
Flight of the Intruder
Ikari Warriors II - Victory Road
Indiana Jones and the Last Crusade (Taito)
Indiana Jones and the Last Crusade (UBI Soft)
Ironsword - Wizards & Warriors II
Ivan Ironman Stewart's Super Off-Road
Jimmy Connor's Tennis
Jordan Vs Bird - One On One
Lion King, The
Prince of Persia
Solstice - The Quest for the Staff of Demnos
The Smurfs
Time Lord
Who Framed Roger Rabbit
Wizards & Warriors III - Kuros - Visions of Power
WWF WrestleMania
WWF WrestleMania Challenge
Anyway, I'd go with CHR-RAM updates, copying pre-rendered frames from ROM. I'm pretty sure you have more space to work with on the NES than on the Pico8.
Re: Triangle rasterization substitute.
Sprite smearing:
Hmm. Ok. I've seen it on the Atari and C64. I just assumed it was possible on the NES too.
CHR RAM:
So then with CHR RAM, a 16*16 pixel sprite is 64 bytes? I think I read somewhere that you have time for like 150 bytes during vblank? That seems like plenty even if I split it into layers to make more colors available. Looking over the original code again, I'm uncertain about having enough CPU time to run the vertex transforms and rasterization at 60hz. If the vertexes are precomputed, then might as well just store the scanline data in RLE chunks instead.
Shearing:
Hmm. Yeah! I could use that in combination with palette swapping to store extra subframes since the boat outline really only needs 1 bpp.
If I quantize the rotation in the original, it's still pretty playable with 32 rotation frames. If I do 16x3 frames using palette swapping + shearing that's even smoother. That leaves plenty of frames for animating the sail as well. If I can get away with putting them all in a single pattern table it would certainly make it easier.
@tokumaru The CHR RAM part sounds as easy as memcpy()? (unless there are a lot of gotchas?). Transforming and rasterizing a bunch of triangles at 60hz on a CPU I haven't worked with in a looooong time sounds like I'm asking for trouble though.
Hmm. Ok. I've seen it on the Atari and C64. I just assumed it was possible on the NES too.
CHR RAM:
So then with CHR RAM, a 16*16 pixel sprite is 64 bytes? I think I read somewhere that you have time for like 150 bytes during vblank? That seems like plenty even if I split it into layers to make more colors available. Looking over the original code again, I'm uncertain about having enough CPU time to run the vertex transforms and rasterization at 60hz. If the vertexes are precomputed, then might as well just store the scanline data in RLE chunks instead.
Shearing:
Hmm. Yeah! I could use that in combination with palette swapping to store extra subframes since the boat outline really only needs 1 bpp.
If I quantize the rotation in the original, it's still pretty playable with 32 rotation frames. If I do 16x3 frames using palette swapping + shearing that's even smoother. That leaves plenty of frames for animating the sail as well. If I can get away with putting them all in a single pattern table it would certainly make it easier.
@tokumaru The CHR RAM part sounds as easy as memcpy()? (unless there are a lot of gotchas?). Transforming and rasterizing a bunch of triangles at 60hz on a CPU I haven't worked with in a looooong time sounds like I'm asking for trouble though.
Re: Triangle rasterization substitute.
True, but pixels on the NES are also half the size in each direction of pixels on the PICO-8, and there's no hardware scaling. You might end up needing to rasterize to 32x32 at 30 fps and transfer it over the course of two frames. But fortunately, there's enough CHR RAM to double buffer every sprite.slembcke wrote:So then with CHR RAM, a 16*16 pixel sprite is 64 bytes?
You can safely assume that a moderately unrolled copy from a buffer in RAM to VRAM can push five sequences of 32 bytes, totaling 160 bytes.slembcke wrote:I think I read somewhere that you have time for like 150 bytes during vblank?
The video memory isn't directly mapped into the CPU's memory space. Instead it's in a separate memory space like on the MSX or Master System, where the CPU has to ask the PPU nicely to write data to video memory. First write the destination address to a PPU port, then write the data to another port. For this reason, it's common to pack data into a buffer, wait for vertical blanking, and then copy that buffer.slembcke wrote:The CHR RAM part sounds as easy as memcpy()?
- FrankenGraphics
- Formerly WheelInventor
- Posts: 2064
- Joined: Thu Apr 14, 2016 2:55 am
- Location: Gothenburg, Sweden
- Contact:
Re: Triangle rasterization substitute.
Another problem with porting the game not related to the rotation of the boat and sail is the seamless, smooth all-directional scrolling. If you want to be able to do that without border glitches, i'd recommend cheapocapra/GTROM (or some other mapper with 4 nametables: TVROM, TR1ROM) for that reason alone, just to make it easier to achieve. With four nametables, you have more than ample room to update the threadmill edges without the player ever noticing, and you won't need to get tricky while doing so. It's not the only way, but it's the easiest.
This is going to be very off topic, but how does Curse of Possum Hollow use its 4 pages of 8kB? Large loads between levels? Midscreen flicking?
Huh.. clever. Since MMC3 has controls for flicking chr-rom pages, it can do that with a chr-ram configuration, too. The size of prg-rom makes it viable. Never thought of that.tepples wrote:MMC3 is among these mappers. The Curse of Possum Hollow uses what amounts to TGROM with the 6264 (8Kx8 SRAM) CHR RAM replaced with a 62256 (32Kx8 SRAM).
This is going to be very off topic, but how does Curse of Possum Hollow use its 4 pages of 8kB? Large loads between levels? Midscreen flicking?
Re: Triangle rasterization substitute.
I think MMC3 + swapping the boats in an 1kb CHR-ROM chunk + keeping all possible sails in the remainder would be easiest.
- FrankenGraphics
- Formerly WheelInventor
- Posts: 2064
- Joined: Thu Apr 14, 2016 2:55 am
- Location: Gothenburg, Sweden
- Contact:
Re: Triangle rasterization substitute.
With that approach, you might even get away with CNROM: 32kB of prg rom (more than enough), 64kb chr rom (meaning 8 page flips. I think you can do it in 4, 3 or even 2 page flips). CNROM is ~7-9 usd cheaper than MMC3 if you want to make cartridges.
Though, you'd still need a solution for the HUD and the scrolling that is satisfactory for the OP. MMC3 could help with its irq if a bg-based status bar is acceptable. With sprites, 8x16 mode would prove cumbersome and expensive, so in that case i think 8x8 mode is preferable. Again for a bg-based status bar, GTROM virtually has 8 nametables (4 at a time), but no irq, so you need to use sprite 0, just like with CNROM. It's somewhat cheaper than CNROM, but both are what i'd consider low cost.
Though, you'd still need a solution for the HUD and the scrolling that is satisfactory for the OP. MMC3 could help with its irq if a bg-based status bar is acceptable. With sprites, 8x16 mode would prove cumbersome and expensive, so in that case i think 8x8 mode is preferable. Again for a bg-based status bar, GTROM virtually has 8 nametables (4 at a time), but no irq, so you need to use sprite 0, just like with CNROM. It's somewhat cheaper than CNROM, but both are what i'd consider low cost.
Re: Triangle rasterization substitute.
I would definitely pre-render the ship at different angles. That's how Solar Jetman does it (it's a spaceship but the concept is the exact same), and it's a great NES game. Also with flipping you can reuse many angles, so you only have to pre-render angles between 0° and 90° and the rest is obtained by flipping existing frames. So with something like 5 or 6 angles you're done, there's really no need to do anything more complex.
Re: Triangle rasterization substitute.
If anyone cares, I've explained.FrankenGraphics wrote:how does Curse of Possum Hollow use its 4 pages of 8kB? Large loads between levels? Midscreen flicking?tepples wrote:The Curse of Possum Hollow uses what amounts to TGROM with [...] 32Kx8 SRAM
Re: Triangle rasterization substitute.
After sleeping on it. I can only get 2 sub-frames using palette swaps.
Also considering turning it into single direction scrolling with a very long map instead. I don't want to make *exactly* the same game.
Is the sprite 0 trick hard? You get an interrupt where you change the scroll position, and do some buffering trickery to keep the HUD away from the onscreen tiles?
This is *way* more help than I was expecting to get. I kinda feel bad that I can't take everybody's advice all at once. Haha.
Nah, wasn't going for a 1:1 remake. I was looking for an interesting, but doable project. No need to add extra constraints.tepples wrote:True, but pixels on the NES are also half the size in each direction of pixels on the PICO-8
Right. I just meant that copying data into VRAM isn't rocket science. Just pushing bytes one at a time across a bus.slembcke wrote:The video memory isn't directly mapped into the CPU's memory space.
Yeah. I was kinda thinking about that. I don't really mind border glitches myself. After reading up on how the attribute table worked, I immediately thought of the color glitches on the left edge in Kirby's Adventure. Maybe it's dumb nostalgia, but I kind of like them more now. :pFrankenGraphics wrote:Another problem with porting the game not related to the rotation of the boat and sail is the seamless, smooth all-directional scrolling.
Also considering turning it into single direction scrolling with a very long map instead. I don't want to make *exactly* the same game.
Interesting to know. Not sure I'd ever want to make cartridges, but there is a store a few blocks from my house that sells homebrew games.FrankenGraphics wrote:CNROM is ~7-9 usd cheaper than MMC3 if you want to make cartridges.
Yeah... Dunno. Might just skip it. Alternatively, put it in a fixed world location like a physical scoreboard near the finish line.FrankenGraphics wrote:Though, you'd still need a solution for the HUD
Is the sprite 0 trick hard? You get an interrupt where you change the scroll position, and do some buffering trickery to keep the HUD away from the onscreen tiles?
Bwa! I totally missed that there is a sprite flip flag on my first skim through the wiki. This might be a game changer really. Along with palette swapped sub-frames, I should be able to pack a lot of sprites into a single sprite page. I kind of like the idea of sticking with the basic ROM type without bank switching as a limitation.Bregalad wrote:and the rest is obtained by flipping existing frames
This is *way* more help than I was expecting to get. I kinda feel bad that I can't take everybody's advice all at once. Haha.