SNES Doom Source Released! Now What?

Discussion of hardware and software development for Super NES and Super Famicom. See the SNESdev wiki for more information.

Moderator: Moderators

Forum rules
  • For making cartridges of your Super NES games, see Reproduction.
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: SNES Doom Source Released! Now What?

Post by tepples »

Another option: a 112x112 tilemap canvas, stretched vertically by 50%. A trick described in the video The Making of Dread, episode 8 "Total Graphics Replacement", at 7:30 through 11:00, lets you draw 112 columns that look like 224 pixels.

Put the canvas in the tilemap. Each byte drawn to the tilemap represents two texels side by side. To make this work, the textures are stored pixel-doubled: if the texture is 0, 2, 4, 6, 1, 5, 3, 7, it's stored so as to display as 0x02, 0x24, 0x46, 0x61, 0x15, 0x53, 0x37, 0x70. Drawing one column of doubled texels per tilemap entry displays as 0224466115533770. Drawing it half the size (twice as far away) gives 02461537. Drawing even farther away (say one-third) gives 026137: a visually acceptable approximation.

Then you stretch 112 pixels height to 168 using mode 7. Turn on the interlace bit ($2133 bit 0), and during alternate fields, set the center of rotation such that each line of texels becomes 1 and 2 lines of output in one field and 2 and 1 lines the next. I've made a demo of this part of the chain, which I consider the successor to a 2009 NES demo titled Tall Pixel.
Attachments
Screenshot
Screenshot
TallPixel-wip.zip
ROM and source
(36.99 KiB) Downloaded 27 times
93143
Posts: 1717
Joined: Fri Jul 04, 2014 9:31 pm

Re: SNES Doom Source Released! Now What?

Post by 93143 »

tepples wrote: Wed Jan 25, 2023 8:26 pmPut the canvas in the tilemap. Each byte drawn to the tilemap represents two texels side by side.
This unfortunately only works if the graphics are 4bpp. If any pixel can be any of 256 different colours (which is necessary in a Doom port, though not perhaps in a Doom-like indie knockoff), you need 65,536 different tiles to represent all the possible combinations. If there are only 16 colours, you can do it in 256 tiles, which Mode 7 has.
Then you stretch 112 pixels height to 168 using mode 7.
That interlace trick looks a bit restless on my TV, but it's a really neat idea and it might look acceptable in this application.
User avatar
Individualised
Posts: 310
Joined: Mon Sep 05, 2022 6:46 am

Re: SNES Doom Source Released! Now What?

Post by Individualised »

Off-topic to the current conversation but of curiosity what ever happened to that one trick that Randy Linden mentioned, something involving HDMA, that would have allowed the game to reach double its current speed? Was that not feasible?
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: SNES Doom Source Released! Now What?

Post by tepples »

One way to work around the color depth limit of the Dread technique is to reserve about 12 colors for the half-and-half trick and the rest of the colors for lower-contrast areas of a texture that don't need to be as high resolution. Then have your texture converter use half-and-half tiles for detailed areas and single-color tiles of the other colors for areas with less horizontal detail.

Or to get fancy, treat it as a vector quantization problem, looking for the 256 texel pairs that best represent the texel pairs found in the game's textures.
93143
Posts: 1717
Joined: Fri Jul 04, 2014 9:31 pm

Re: SNES Doom Source Released! Now What?

Post by 93143 »

Individualised wrote: Thu Jan 26, 2023 2:25 am Off-topic to the current conversation but of curiosity what ever happened to that one trick that Randy Linden mentioned, something involving HDMA, that would have allowed the game to reach double its current speed? Was that not feasible?
Oh, I'm sure it's feasible. It's just not trivial, and it's not his day job this time.

...

Honestly, if I were attempting to speed up the game, and nothing else, I think I'd try Mode 7.

A method was proposed by tepples that sets up Mode 7 to scan diagonally through a tilemapped image with repeated tiles, allowing a column-major bitmap (the best way to render Doom) to be DMAed into VRAM and displayed with no format conversion step. There are two other ways to do that (tilemap-as-bitmap, as seen in Jurassic Park, and VRAM port address translation, as seen in Wolfenstein 3D), but this one allows (a) one axis to be larger than 128 pixels, and (b) the whole framebuffer to be dumped into VRAM in one chunk without requiring frequent stops to update the VRAM address between columns. This requires the major axis to be a multiple of 8 pixels, but the minor axis can be any size.

This lets you use a 108x144 framebuffer, which when stretched to 216x144 is the same size as in the existing port, but you don't have to worry about pixel buffer stall on the Super FX, and you don't have to do any software format translation (my original idea for circumventing pixel buffer stall was to render a linear bitmap and then use PLOT to convert it to SNES CHR in bulk afterwards). The problem is that Mode 7 only has 16 KB of pixel data storage and you can't move the address window, so with a 176-line display there isn't quite enough VBlank time to fractional-buffer without tearing. However...

...I did some experiments a while ago that successfully wrote to VRAM during HBlank between active scanlines, by using HDMA to turn off rendering, push some bytes to the VRAM port, and turn rendering back on. This borks sprites on the subsequent line, but if there aren't any you're golden. If, for instance, you can ensure that there are no sprites used to compose the status bar (i.e. it's all BG layers), you can use this method to transfer an extra 640 or so bytes per frame while leaving a spare channel for audio I/O. This is enough to get past the threshold and permit (just barely) perfect fractional double buffering of a 108x144 Mode 7 framebuffer, allowing a peak frame rate of 30 fps with no tearing.

...

The method I think he was talking about (the mosaic trick) would be great for increasing the size of the framebuffer, since compared to the existing port it cuts the DMA and VRAM requirements in half as well as speeding up rendering, and unlike the Mode 7 method it can use most of VRAM. You could potentially go as large as 128x192, which with a 32-line status bar is actually fullscreen on NTSC. But it requires either a somewhat more fiddly rendering procedure (with less pixel buffer stall, but not none) or a format conversion step on the Super FX. If you're not going to increase the size of the framebuffer, I think the Mode 7 approach is probably superior, assuming I haven't missed anything.

tepples wrote: Thu Jan 26, 2023 8:23 am One way to work around the color depth limit of the Dread technique is to reserve about 12 colors for the half-and-half trick and the rest of the colors for lower-contrast areas of a texture that don't need to be as high resolution. Then have your texture converter use half-and-half tiles for detailed areas and single-color tiles of the other colors for areas with less horizontal detail.
It is notable that the Doom palette is actually less than 256 unique colours on SNES, because the 18-bit VGA master palette allows slightly finer gradations than the 15-bit SNES master palette, and as a result the SNES Doom palette has some duplicates. And since it's addressed using a lighting table, it should be easy to rearrange said table to not need the duplicates.

I had considered a couple of possible ways to take advantage of this. For instance, one could smooth out some of the defects in the original palette. At a given light level, Demons and Barons of Hell (and other pink things such as red skull doorframes) have a maximum distance beyond which they abruptly become beige, because the lighting is limited by the available colours. (Obviously you'd keep the original colours in the raw textures, because even though they don't exist in the SNES palette, the extra information would reappear during light level transitions.) Or one could use a method such as you've proposed to add back dithering to untextured floors...

The tile-as-pixel approach seems, on its face, to limit both axes to 128 pixels. But it occurs to me that since this is Mode 7, there's no reason why extra rows couldn't be loaded sideways next to the main 128-high area. Unfortunately the actual DMA transfer would probably be quite fiddly, and you'd need two versions of each colour pair, one split along each axis...
Or to get fancy, treat it as a vector quantization problem, looking for the 256 texel pairs that best represent the texel pairs found in the game's textures.
I just remembered that I've done something similar before. Some of the graphics in my shmup port are Mode 7 textures that are too large for the amount of memory I can allocate for them. In one case, I managed to squeeze a 128x128 image with over 100 colours into 192 split tiles and a 64x128 tilemap, and it looks almost indistinguishable from the uncompressed version. Fun stuff...
SNES AYE
Posts: 201
Joined: Mon Nov 07, 2022 11:28 am

Re: SNES Doom Source Released! Now What?

Post by SNES AYE »

93143 wrote: Thu Jan 26, 2023 6:49 pm I just remembered that I've done something similar before. Some of the graphics in my shmup port are Mode 7 textures that are too large for the amount of memory I can allocate for them. In one case, I managed to squeeze a 128x128 image with over 100 colours into 192 split tiles and a 64x128 tilemap, and it looks almost indistinguishable from the uncompressed version. Fun stuff...
How is your shmup coming along? Anything ready to show?
93143
Posts: 1717
Joined: Fri Jul 04, 2014 9:31 pm

Re: SNES Doom Source Released! Now What?

Post by 93143 »

It's proceeding slowly. I've had to devote the bulk of my mental energy to real life, so I haven't been able to make much progress on actually finishing up this project. Part of the problem is that my actual job seems to use most of the same parts of my brain as this hobby, so the harder I try at it, the less I want to work on SNES programming the moment I knock off. Fortunately, what I'm doing in real life does have a definite endpoint, which will hopefully arrive within the year (although to be fair I've said that before) and I'm hoping that what follows will be less all-consuming.

I could show what I have, but most of it would give away the identity of the game I'm porting, which for various reasons I would like to avoid until it's nearly done. There's an old Super FX test that doesn't give away the secret, but I posted it a while back and you may have already seen it.
User avatar
Señor Ventura
Posts: 233
Joined: Sat Aug 20, 2016 3:58 am

Re: SNES Doom Source Released! Now What?

Post by Señor Ventura »

93143 wrote: Sat Jan 28, 2023 5:51 pm It's proceeding slowly. I've had to devote the bulk of my mental energy to real life, so I haven't been able to make much progress on actually finishing up this project. Part of the problem is that my actual job seems to use most of the same parts of my brain as this hobby, so the harder I try at it, the less I want to work on SNES programming the moment I knock off. Fortunately, what I'm doing in real life does have a definite endpoint, which will hopefully arrive within the year (although to be fair I've said that before) and I'm hoping that what follows will be less all-consuming.

I could show what I have, but most of it would give away the identity of the game I'm porting, which for various reasons I would like to avoid until it's nearly done. There's an old Super FX test that doesn't give away the secret, but I posted it a while back and you may have already seen it.
Do is your game a port?, or a new one... Bullet hell, may be?.

I understand you, i'm waiting to the day i finish one project that i'm in before i could dedicate to the snes, but it seems like if itself want NOT to be completed EVER.

I have some ideas about i want to dive in to learn, but never comes the moment in wich i finally can begin. This is my year, for sure, but all this waiting is painful as hell. Years of handicap.
93143
Posts: 1717
Joined: Fri Jul 04, 2014 9:31 pm

Re: SNES Doom Source Released! Now What?

Post by 93143 »

Señor Ventura wrote: Sat Jan 28, 2023 6:37 pm
93143 wrote: Sat Jan 28, 2023 5:51 pmthe game I'm porting
Do is your game a port?
I'll leave you to guess.
Bullet hell, may be?
Yes. More bullets than the SNES could handle as hardware sprites, even if there were nothing else onscreen. Hence the Super FX, to draw them in software.

...

I really need to get to work on the audio engine...
User avatar
Señor Ventura
Posts: 233
Joined: Sat Aug 20, 2016 3:58 am

Re: SNES Doom Source Released! Now What?

Post by Señor Ventura »

93143 wrote: Sun Jan 29, 2023 1:00 am
Señor Ventura wrote: Sat Jan 28, 2023 6:37 pm
93143 wrote: Sat Jan 28, 2023 5:51 pmthe game I'm porting
Do is your game a port?
I'll leave you to guess.
It seemed to me you mentioned something like that, but i think yor work is new...
93143 wrote: Sun Jan 29, 2023 1:00 am Yes. More bullets than the SNES could handle as hardware sprites, even if there were nothing else onscreen. Hence the Super FX, to draw them in software.
Do you mean a layer with bullets, and DMAing to the VRAM?.
93143 wrote: Sun Jan 29, 2023 1:00 am I really need to get to work on the audio engine...
How do you shall to distribute the channels? (how many for music, voices, and sound effects).
93143
Posts: 1717
Joined: Fri Jul 04, 2014 9:31 pm

Re: SNES Doom Source Released! Now What?

Post by 93143 »

Señor Ventura wrote: Sun Jan 29, 2023 6:53 am Do you mean a layer with bullets, and DMAing to the VRAM?, or is there a way to draw transferring only by coordinates with the tile of the bullet already in the VRAM.
Yes, and yes.

The "way to draw transferring only the coordinates with the tile of the bullet already in the VRAM" is how hardware sprites work. You put the parameters and coordinates in OAM (Object Attribute Memory), and the PPU will draw the specified graphic from VRAM at the specified coordinates, using the specified subpalette in CGRAM.

The problem with that is that there's only space in OAM for 128 hardware sprites. So if you want more, you need to do something else. In my case, I need sprites for enough things that I'm starting to run out in certain scenes even without the bullets.

The Super FX just draws the bullets to a framebuffer in SNES CHR format, and then I DMA that into VRAM. Sometimes I can get away with 2bpp, and that can run at 60 fps, but in most cases it's 4bpp, which caps the bullet frame rate at 30 fps because there's not enough DMA time to do it any faster. So far it looks like I can manage collisions at 60 fps, but the visible bullets (and some enemies that need software rendering) will be mostly at 30. The player ship always runs at 60 fps (it's made out of hardware sprites), and player bullets are a mix depending on what's going on.
How do you shall to distribute the channels? (how many for music, voices, and sound effects).
I haven't really gotten that far yet, but I figure I can get away with two dedicated sound effect channels: one for the noises the player makes, and one for noises other things make. That leaves six channels for the music, and if I really need another sound effect channel I can steal one from the music. I feel like this should be much less unpleasant than stealing a channel any time anything happens, especially considering that the original game (like any shmup, really) has nearly constant sound effects as long as you're shooting.

Crunching the music down into 6 channels will be a challenge, for sure. Hopefully I can use clever tricks with chord samples and echo to get it sounding good enough. Also, I plan to use HDMA sample streaming for a couple of sound effects, but I don't need the full possible bandwidth, so I might as well look at streaming samples as part of the music.
creaothceann
Posts: 611
Joined: Mon Jan 23, 2006 7:47 am
Location: Germany
Contact:

Re: SNES Doom Source Released! Now What?

Post by creaothceann »

Will there be more than 256 sprites? Theoretically you could display every bullet every other frame.
My current setup:
Super Famicom ("2/1/3" SNS-CPU-GPM-02) → SCART → OSSC → StarTech USB3HDCAP → AmaRecTV 3.10
User avatar
Señor Ventura
Posts: 233
Joined: Sat Aug 20, 2016 3:58 am

Re: SNES Doom Source Released! Now What?

Post by Señor Ventura »

93143 wrote: Sun Jan 29, 2023 7:46 am Yes, and yes.

The "way to draw transferring only the coordinates with the tile of the bullet already in the VRAM" is how hardware sprites work. You put the parameters and coordinates in OAM (Object Attribute Memory), and the PPU will draw the specified graphic from VRAM at the specified coordinates, using the specified subpalette in CGRAM.

The problem with that is that there's only space in OAM for 128 hardware sprites. So if you want more, you need to do something else. In my case, I need sprites for enough things that I'm starting to run out in certain scenes even without the bullets.

The Super FX just draws the bullets to a framebuffer in SNES CHR format, and then I DMA that into VRAM. Sometimes I can get away with 2bpp, and that can run at 60 fps, but in most cases it's 4bpp, which caps the bullet frame rate at 30 fps because there's not enough DMA time to do it any faster. So far it looks like I can manage collisions at 60 fps, but the visible bullets (and some enemies that need software rendering) will be mostly at 30. The player ship always runs at 60 fps (it's made out of hardware sprites), and player bullets are a mix depending on what's going on.
I meant, tranfering bullet from cartridge to vram through dma to a layer, forces you to transfer until 896 tiles (1BPP 8 Bytes each, 2BPP 16 Bytes each, 4BPP 32 Bytes each).

I supposed if it could not be better, in order to save bandwidth, to keep one tile of a bullet in vram, then receive the calculations of every bullet coordenates from the super fx, and then build the bullets layer "manually".

What spends more bandwidth?, one tile graphic?, or one coordenate.

93143 wrote: Sun Jan 29, 2023 7:46 am I haven't really gotten that far yet, but I figure I can get away with two dedicated sound effect channels: one for the noises the player makes, and one for noises other things make. That leaves six channels for the music, and if I really need another sound effect channel I can steal one from the music. I feel like this should be much less unpleasant than stealing a channel any time anything happens, especially considering that the original game (like any shmup, really) has nearly constant sound effects as long as you're shooting.

Crunching the music down into 6 channels will be a challenge, for sure. Hopefully I can use clever tricks with chord samples and echo to get it sounding good enough. Also, I plan to use HDMA sample streaming for a couple of sound effects, but I don't need the full possible bandwidth, so I might as well look at streaming samples as part of the music.
600 bullets hitting in a lot of things, and probably a dozen of explosions, plus some voices of items and things like that, for only two channels... i don't know if it could lack some inmersion.

How about music using 6 channels, in terms of sample quality?, How much bandwidth can you spend to keep 32khz/16 bits and the minimun compresion for 6 channels?.

P.D: I stop with the off topic, i promise xD
93143
Posts: 1717
Joined: Fri Jul 04, 2014 9:31 pm

Re: SNES Doom Source Released! Now What?

Post by 93143 »

creaothceann wrote: Sun Jan 29, 2023 8:57 am Will there be more than 256 sprites? Theoretically you could display every bullet every other frame.
Yes. There are way more than 256 enemy bullets, let alone all the other stuff that needs to be sprites (either because it moves independently, or because it needs to show up on top of a Mode 7 layer, or because it needs to not glitch out when BGMODE is written mid-scanline).

Also, that would flicker horribly, and technically wouldn't be any better than 30 fps anyway.

I am thinking of flickering the player bullets on purpose. They're typically low-priority, because on a Mode 7 backdrop the rendered layer has to be made up of tiled large sprites and the player bullets have to be underneath the enemy bullets for playability reasons, so they won't drop out naturally when the line limit is reached. Dropping them deliberately could minimize the gameplay impact of sprite overload (as well as saving OAM in some high-load cases - yes, I can run out even without the enemy bullets).

Señor Ventura wrote: Sun Jan 29, 2023 10:00 amI meant, tranfering bullet from cartridge to vram through dma to a layer, forces you to transfer until 896 tiles (1BPP 8 Bytes each, 2BPP 16 Bytes each, 4BPP 32 Bytes each).
It doesn't. This is a vertically-oriented shmup with a sidebar, and I've scaled the playfield to 144x192. This means it's only 13,824 bytes at 4bpp, or 6,912 bytes at 2bpp. Since my active display area is 204 pixels high including borders, I have over 9 KB of bandwidth every frame. This is enough for 30 fps at 4bpp, or 60 fps at 2bpp, with some margin for other updates and certain special effects.

Keep in mind it's only the enemy bullets (and some enemies, and occasionally some special effects) that have to be rendered on the Super FX. Everything else is handled on the PPU, using techniques similar to what most non-Super FX SNES games do.
I supposed if it could not be better, in order to save bandwidth, to keep one tile of a bullet in vram, then receive the calculations of every bullet coordenates from the super fx, and then build the bullets layer "manually".
The PPU is not programmable. It does what it does. You can poke registers to change settings, but ultimately it's fixed-function hardware.

What you are describing is hardware sprites, and there are only 128 of them. I need more.
600 bullets hitting in a lot of things, and probably a dozen of explosions, plus some voices of items and things like that, for only two channels... i don't know if it could lack some inmersion.
During normal gameplay, the important sounds are basically: player shooting bullet, bullet hitting enemy, enemy dying, enemy shooting bullet, bullet hitting player. If you've just been hit, you don't care about your own shots. If the enemy just exploded, the sound of your bullets hitting other enemies matters less (as does the tail end of a previous enemy explosion). There are scenarios where you want three channels, but in those scenarios you can steal a music channel.

I may end up trying to mostly jam the music into five channels, at least during some stages/bosses, because having player shots, enemy hits, and enemy shots all at the same time would be good. As I said before, the audio stuff is TBD...

I had thought of using the MSU1 for music, to allow 8 channels for sound effects. But since this would be cheating, I have decided that even if I do this, it will not be the default mode. So I have to come up with a way to make it sound decent in legacy mode.
How about music using 6 channels, in terms of sample quality?
This is what I have. It's a SNES. It has 8 channels, 64 KB of ARAM, and four I/O ports that in the context of the rest of my engine can only take significant data throughput via HDMA during 192 of the active scanlines. The challenge is making everything work well enough in that context.

Donkey Kong Country 2 uses all 8 channels for music, and in Lockjaw's Locker you can hear parts drop out every time you press the button to swim. It's incredibly aggravating (though part of the problem is that the music uses one channel for a particular instrument and another for its echo, and it's the main channel and not the echo that drops). Limiting the music to 6 channels mitigates this somewhat.
How much bandwidth can you spend to keep 32khz/16 bits and the minimun compresion for 6 channels?
I can probably fit in about four or five 36-line data bursts per frame via HDMA, depending on how granular the music timing needs to be. This is enough for 576 to 720 bytes per frame. I need about 150 bytes per frame for a 16 kHz streaming sound effect, so that leaves about 426 to 570 bytes for music support. This is enough for one full 32 kHz stream, or perhaps two 22 kHz streams, or possibly three 16 kHz streams on the high end. Considering I have the bulk of the 64 KB ARAM in which to cache samples, and I can completely replace the samples and sequence data between tracks, I think it should sound fine. Plenty of SNES music sounds fine with five channels and no HDMA streaming...
Señor Ventura wrote: Sun Jan 29, 2023 10:00 amP.D: I stop with the off topic, i promise xD
DOOM-FX is particularly bad at channel sharing. The chainsaw is an especially glaring example, as it cuts out regularly even when the music isn't using all 8 channels. And a sound effect will often outright kill the music channel it steals, nerfing the music for the rest of the loop. The sound effect engine itself has abysmal timing, the chaingun being the most obvious example. I don't know how this was achieved, but it strikes me that for my shmup port, I should probably make sure that sound effect commands get sent to the SPC700 on the frame they're triggered, and played immediately. This means that a double-buffered HDMA table may be the wrong way to handle sound effects, unless I can guarantee that the command is ready early enough to write to the end of the table before the DMA unit actually gets that far...

...it occurs to me that there may be scenarios in which I need two streaming sound effects at the same time. This would further restrict what I can do with the music, but since I haven't come to grips with the ARAM situation yet I don't know if this is true.
User avatar
Individualised
Posts: 310
Joined: Mon Sep 05, 2022 6:46 am

Re: SNES Doom Source Released! Now What?

Post by Individualised »

93143 wrote: Sun Jan 29, 2023 10:41 pm DOOM-FX is particularly bad at channel sharing. The chainsaw is an especially glaring example, as it cuts out regularly even when the music isn't using all 8 channels. And a sound effect will often outright kill the music channel it steals, nerfing the music for the rest of the loop. The sound effect engine itself has abysmal timing, the chaingun being the most obvious example. I don't know how this was achieved, but it strikes me that for my shmup port, I should probably make sure that sound effect commands get sent to the SPC700 on the frame they're triggered, and played immediately. This means that a double-buffered HDMA table may be the wrong way to handle sound effects, unless I can guarantee that the command is ready early enough to write to the end of the table before the DMA unit actually gets that far...

...it occurs to me that there may be scenarios in which I need two streaming sound effects at the same time. This would further restrict what I can do with the music, but since I haven't come to grips with the ARAM situation yet I don't know if this is true.
The music in SNES Doom was likely automatically converted from .MUS files, hence the strange sounding timing of the music, as the sound driver likely can't handle the precise timing of the MUS format.
Post Reply