Triangle rasterization substitute.

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

User avatar
slembcke
Posts: 172
Joined: Fri Nov 24, 2017 2:40 pm
Location: Minnesota

Triangle rasterization substitute.

Post by slembcke »

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?

Image

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
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: Triangle rasterization substitute.

Post by lidnariq »

slembcke wrote:2) Use scanline interrputs to smear some sprites across the screen. (Sounds hard)
Not possible at all. On the NES, sprites can only be changed once per redraw¹.

¹ There's one game that disables rendering for five lines in the middle of the screen to upload a new set of sprites.
3) Use CHR RAM and render into that. (Maybe hard? Sounds like only Battletoads does this?)
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.
User avatar
FrankenGraphics
Formerly WheelInventor
Posts: 2064
Joined: Thu Apr 14, 2016 2:55 am
Location: Gothenburg, Sweden
Contact:

Re: Triangle rasterization substitute.

Post by FrankenGraphics »

-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.
User avatar
dougeff
Posts: 3079
Joined: Fri May 08, 2015 7:17 pm

Re: Triangle rasterization substitute.

Post by dougeff »

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

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
User avatar
pubby
Posts: 583
Joined: Thu Mar 31, 2016 11:15 am

Re: Triangle rasterization substitute.

Post by pubby »

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.
2) Use scanline interrputs to smear some sprites across the screen. (Sounds hard
Is this even possible? I think you're mistaken. Sprites aren't effected by scroll.
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Triangle rasterization substitute.

Post by tepples »

slembcke wrote:3) Use CHR RAM and render into that. (Maybe hard? Sounds like only Battletoads does this?)
Haunted: Halloween '85 double-buffers all character animations into CHR RAM. So does my sprite shrinking demo.
4) Break the sprite into some pieces and move those around independently? (Not sure how to make this look good)
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.
FrankenGraphics wrote:Or you can use a mapper like cheapocabra which can flick chr-ram pages like it was chr-rom
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).
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Triangle rasterization substitute.

Post by tokumaru »

slembcke wrote:3) Use CHR RAM and render into that. (Maybe hard? Sounds like only Battletoads does this?)
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:

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.
User avatar
slembcke
Posts: 172
Joined: Fri Nov 24, 2017 2:40 pm
Location: Minnesota

Re: Triangle rasterization substitute.

Post by slembcke »

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

Re: Triangle rasterization substitute.

Post by tepples »

slembcke wrote:So then with CHR RAM, a 16*16 pixel sprite is 64 bytes?
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:I think I read somewhere that you have time for like 150 bytes during vblank?
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:The CHR RAM part sounds as easy as memcpy()?
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.
User avatar
FrankenGraphics
Formerly WheelInventor
Posts: 2064
Joined: Thu Apr 14, 2016 2:55 am
Location: Gothenburg, Sweden
Contact:

Re: Triangle rasterization substitute.

Post by FrankenGraphics »

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.
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).
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.
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?
calima
Posts: 1745
Joined: Tue Oct 06, 2015 10:16 am

Re: Triangle rasterization substitute.

Post by calima »

I think MMC3 + swapping the boats in an 1kb CHR-ROM chunk + keeping all possible sails in the remainder would be easiest.
User avatar
FrankenGraphics
Formerly WheelInventor
Posts: 2064
Joined: Thu Apr 14, 2016 2:55 am
Location: Gothenburg, Sweden
Contact:

Re: Triangle rasterization substitute.

Post by FrankenGraphics »

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.
User avatar
Bregalad
Posts: 8056
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Re: Triangle rasterization substitute.

Post by Bregalad »

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

Re: Triangle rasterization substitute.

Post by tepples »

FrankenGraphics wrote:
tepples wrote:The Curse of Possum Hollow uses what amounts to TGROM with [...] 32Kx8 SRAM
how does Curse of Possum Hollow use its 4 pages of 8kB? Large loads between levels? Midscreen flicking?
If anyone cares, I've explained.
User avatar
slembcke
Posts: 172
Joined: Fri Nov 24, 2017 2:40 pm
Location: Minnesota

Re: Triangle rasterization substitute.

Post by slembcke »

After sleeping on it. I can only get 2 sub-frames using palette swaps.
tepples wrote:True, but pixels on the NES are also half the size in each direction of pixels on the PICO-8
Nah, wasn't going for a 1:1 remake. I was looking for an interesting, but doable project. No need to add extra constraints. ;)
slembcke wrote:The video memory isn't directly mapped into the CPU's memory space.
Right. I just meant that copying data into VRAM isn't rocket science. Just pushing bytes one at a time across a bus.
FrankenGraphics wrote:Another problem with porting the game not related to the rotation of the boat and sail is the seamless, smooth all-directional scrolling.
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. :p
Image

Also considering turning it into single direction scrolling with a very long map instead. I don't want to make *exactly* the same game.
FrankenGraphics wrote:CNROM is ~7-9 usd cheaper than MMC3 if you want to make cartridges.
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. :D
FrankenGraphics wrote:Though, you'd still need a solution for the HUD
Yeah... Dunno. Might just skip it. Alternatively, put it in a fixed world location like a physical scoreboard near the finish line.

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?
Bregalad wrote:and the rest is obtained by flipping existing frames
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.

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.
Post Reply