VDP1 VRAM and Command Tables

Hi,

I'm reading the docs (cripes, there's a lot of them!) and looking at code examples and I want to make sure I understood some of the basics of the VDP1. This is what I got so far, please correct me if I'm wrong.

Command Tables.
- Whenever calling a function like slPutPolygon or slDispSprite, it sets up a command table for the polygons or sprite for that call.
- There's a command table for each polygon? Not for the entire mesh? (Maybe this is SGL specific?)
- since a command table contains a gouraud shading table, they don't seem to be shared across command tables. But they're only 8 bytes, so not so bad?
- the character pattern table in a command table isn't an array of indices to the tiles, they're the actual tiles. That means for each sprite setup with slDispSprite, it actually copies the pattern data to that area of VRAM? Being used to the Genesis where setting up a sprite only requires an index to the tile patterns and a sprite size, isn't this wasteful and/or slow?
- if I work with the SGL, are command tables abstracted away? I don't have to worry about command tables unless I bust the memory reserved for them?

VRAM
- tile patterns for sprites are stored in the VDP1 VRAM? If they share VRAM along with command tables, then I probably have to reserve areas for each. How do I tell if I have too many command tables and stomp the other reserved areas? (Not a problem with SGL?)

Sprites
- What's the difference between slDispSpriteSZ and slDispSpriteHV? What I found in a RockinB tutorial says they work similarly but didn't explain any differences. I haven't found it in the docs yet.

Mixing Color Depths
- There seems to be a ridiculous amount of flexibility to choosing color depths of the screen, textures, palettes and backgrounds. Can I really setup a scene using (for example) a 16bit color screen using 16 color sprites, 32k color polygons and 256 color backgrounds? The options are overwhelming!


Thanks!
 
If you're using Yabause, use the VDP1 viewer to see the command list, even during the boot sequence.

Each sprite and polygon is added to the command list which is processed by the VDP1 until the end command is found (or you fill up VRAM).

Gouraud shading is performed on a per-sprite/polygon (as long as it's RGB15) basis, therefore each part (polygon/sprite) gets its own set of values for Gouraud shading. As the commands are always 30 bytes (plus two for alignment), it doesn't take up any more room than a non-Gouraud shaded part.

The character pattern is held at an offset in VRAM, and you have to ensure that you don't stomp on that with another character pattern or something else. I'm not familiar with the Mega Drive/Genesis, so I'm assuming that the data is accessed from the cartridge rather than held in RAM (please correct me if I'm wrong). For the Saturn, the character pattern has to be put into VRAM for the VDP1 to access, as it is restricted to its own VRAM.

I cannot speak for the SGLs functions, as I haven't used it extensively.

I'd recommend you check out my sprite sample and the common code base for the samples for a very simple look at how to send sprites to the VDP1 (polygons are almost the same). If you haven't already; read the VDP1 User's Manual, as it contains information about how this works on a much lower level.
 
If you're using Yabause, use the VDP1 viewer to see the command list, even during the boot sequence.

Nice, I didn't know that! I am indeed using Yabause.

As the commands are always 30 bytes (plus two for alignment), it doesn't take up any more room than a non-Gouraud shaded part.
Hmmm, since they're always 30 bytes, then that means that they probably don't contain the actual sprite patterns. I'll have to read again about how that works.

If each polygon takes up 30(32) bytes, then say ten thousand polygons takes a huge chunk out of VRAM. What were the per-frame polygon counts for a typical game?

I'm not familiar with the Mega Drive/Genesis, so I'm assuming that the data is accessed from the cartridge rather than held in RAM (please correct me if I'm wrong). For the Saturn, the character pattern has to be put into VRAM for the VDP1 to access, as it is restricted to its own VRAM.

It's the same thing on Genesis. Patterns to be displayed need to be copied from ROM to VRAM first. Then there's a sprite table in VRAM that contains indices to the patterns.

I'd recommend you check out my sprite sample and the common code base for the samples for a very simple look at how to send sprites to the VDP1 (polygons are almost the same). If you haven't already; read the VDP1 User's Manual, as it contains information about how this works on a much lower level.

I'm reading the VDP1 doc over and over again until things start to stick. :)
I'll check out those samples, thanks!
 
Hmmm, since they're always 30 bytes, then that means that they probably don't contain the actual sprite patterns.
The drawing command contains the VRAM address and dimensions of the image.

If each polygon takes up 30(32) bytes, then say ten thousand polygons takes a huge chunk out of VRAM. What were the per-frame polygon counts for a typical game?
VDP1 is a frame-buffer based device, you don't have to draw all polygons at once. In fact you probably don't want to, since you can get better system utilization by preparing the next batch of drawing commands while VDP1 is working.
 
Hmmm, since they're always 30 bytes, then that means that they probably don't contain the actual sprite patterns. I'll have to read again about how that works.
Indeed, they do not contain the character pattern. The command table comes first in VRAM and is read until the end command is encountered. After the last command, the character pattern table is stored. The address for the character pattern table is used when specifying the sprite, though I'm not sure what SGL does. Specifically, the character pattern address is specified 8 bytes into the command table entry, the address is divided by 8 to get the correct address for the VDP1 to process. As you can see in the sample.

If each polygon takes up 30(32) bytes, then say ten thousand polygons takes a huge chunk out of VRAM. What were the per-frame polygon counts for a typical game?
I'm not entirely sure on the typical sprite count for specific games. As there is 1MiB VRAM available drawing 2,000 sprites consumes 64,000 bytes, which isn't so bad. Though, if you factor in these are Gouraud shaded (requiring 15-bit colour), then if you have even 16x16 textures this will take 1,024,000 bytes of your VRAM for a total of 1,088,000. Just over the amount of VRAM available. Of course, there are more commands than just the part drawing commands, though they are for ending drawing, and specifying screen and clip coordinates so are not used as frequently.

It's the same thing on Genesis. Patterns to be displayed need to be copied from ROM to VRAM first. Then there's a sprite table in VRAM that contains indices to the patterns.
I see. Thank you for the correction.

I'm reading the VDP1 doc over and over again until things start to stick. :)
I'll check out those samples, thanks!
Yeah, there are a lot of documents to sift through. I'm looking at the CD block at the moment, which has several documents to read. Plus, there's the SBL6 source which contains a lot of hints for how to interface with it. I'd recommend reading over it once, from start to finish, then read it again. Most likely there are specifics referenced earlier that you needed the information later for it to make complete sense =P.
 
VDP1 is a frame-buffer based device, you don't have to draw all polygons at once. In fact you probably don't want to, since you can get better system utilization by preparing the next batch of drawing commands while VDP1 is working.
This is something I wasn't sure of. Though I assumed it was possible, I didn't want to suggest it as a proven method without testing first. Thank you, antime, for the information.
 
VDP1 is a frame-buffer based device, you don't have to draw all polygons at once. In fact you probably don't want to, since you can get better system utilization by preparing the next batch of drawing commands while VDP1 is working.

Do you mean during the building of one frame or over multiple frames?

If it's during one frame, what kind of work is VDP1 doing that gives us time to prepare more commands during the frame? I had the (noobie) impression you just gave it all the commands for one frame and then go.
 
This is something I wasn't sure of. Though I assumed it was possible, I didn't want to suggest it as a proven method without testing first.
I'm not certain of how access to VRAM is arbitrated, but there's no prohibition on accessing it while VDP1 is active (at least as I recall). There's probably a performance hit, but you can always construct the command tables in work RAM and DMA them over. Again something you probably want to do anyway, as accessing the narrower A bus will be slower in any case.

Do you mean during the building of one frame or over multiple frames?
Either works.

If it's during one frame, what kind of work is VDP1 doing that gives us time to prepare more commands during the frame?
Drawing the previous batch. For polygonal games, the goal will be to keep VDP1 busy at all times. How to best achieve that is really up to you.

Regarding polycounts, from reading old articles and post-mortems, PS1 games typically used somewhere around 1000-2000 polygons per frame.
 
I just realized that the vdp1 color bank mode and the lookup table modes are different things. But I don't really understand the difference. Why would I prefer a lookup table of 16 colors over a color bank of 16 colors?
 
If you want to use VDP1 color calculation effects like Gouraud shading or transparency, the framebuffer pixels must be in RGB format.
 
I don't quite understand the VRAM bank restrictions for VPD2.

If, say, I use bank VRAM-A0 as the first bank, I can only use VRAM-A1 or VRAM-B1? But not VRAM-B0 because it has the same ending number?

Even with the bank restrictions, I can store all the normal scroll screen pattern data for all the normal scrolling backgrounds in them? (ignoring rotating screens)

If I had a rotating scroll screen, since I can 1) only use 2 banks and 2) can't mix normal and rotating scroll screen data, then that means 1 bank would go for normal scroll screens and the other goes to the rotating scroll screen?

If only two banks can be used for pattern data, what are the two other banks are used for?
 
I just realized that the vdp1 color bank mode and the lookup table modes are different things. But I don't really understand the difference. Why would I prefer a lookup table of 16 colors over a color bank of 16 colors?

The CLUT is a "shortcut" for a given colour, I think it can be both RGB and palette, and if you use CLUTs with RGB colours maybe you can end up with smaller textures, since the textures would have short CLUT colour entries instead of 2-byte RGB ones? And/or maybe ramp their colours manually (like, doing palette animation), without actually using VDP2 palettes? You can also have more CLUTs than palette entries. That's just my idea on some potential uses though, not sure if it happens that way on the hardware, but from what I recall on the manuals it does.

In 8-bit mode you can only use palettes though, so I don't know how you would benefit from CLUTs then.
Also they might be a bit slower to read since the VDP1 has to check for both the texture data and the CLUT, but I don't know how significant the performance difference is. The entries could be cached for all I know. Gouraud Shading definitely slow things down, but primarily because the VDP1 needs the shading tables from VRAM.

If you want to use VDP1 color calculation effects like Gouraud shading or transparency, the framebuffer pixels must be in RGB format.
You can use Gouraud shading on palette sprites, but it's tricky. You have to set up every colour as a gradient in CRAM, and then use red gouraud shading to ramp up on that gradient. Red gouraud shading will only affect the part of your pixel data where the palette is, raising its value, to a later palette entry. Not sure if it works on every pixel mode though.
 
In 8-bit mode you can only use palettes though, so I don't know how you would benefit from CLUTs then.
It can be useful when you used all colors for nbgs and you need to use other palettes/colors for sprites.
 
Yes, but CLUTs are basically colour pointers, so if you use them for 8-bit textures they will point to palette entries, which are all in the VDP2? So if you use up all palettes for backgrounds, then you don't have any you can point to with CLUTs? That's how I understand them.
 
Yes, but CLUTs are basically colour pointers, so if you use them for 8-bit textures they will point to palette entries, which are all in the VDP2? So if you use up all palettes for backgrounds, then you don't have any you can point to with CLUTs? That's how I understand them.
yes i think it's store in vdp2 mem but not in colorram, i don't remember exactly how it works, my clut was stored there :

#define COLADDR (FBUF_ADDR-0x400)
#define COLADDR_SPR (COLADDR>>3)

i used that hint on system1 emulation, all color ram was used for layers then i needed 512 colors for sprites. clut helped me to increase the max usable number of colors.
 
Didn't you use RGB sprites for those?

I just checked the VDP1 manual, it says that in CLUTs you can either use RGB sprites (so, 16bit pixel data), or you can use "color bank code" aka palette entry, and it even warns you to format the data as the VDP2 wants them in, so they have to be VDP2 palette entries... so if you already used up the entire vdp2 cram, then you can't use the CLUT to add more palette entries (you can only specify existing colours).
 
Color bank code is special in that you can either store it in VDP1 VRAM (CLUT) or VDP2 CRAM. How the data is represented is key. You need to set bit 15 to the 2-byte color entry if you're using pure RGB values. Otherwise, if bit 15 isn't set, you need to follow the sprite type format. I believe by default, it's sprite type 0. This has a format that has bits for an offset to another section in CRAM that has the actual palette entries. To make matters worse, there are 16 sprite types. The lower 8 (0-7) are for when the VDP1 framebuffer is 16-bits, the rest are for when the framebuffer is 8-bits. You'll see that there are multiple levels of indirection. It can go from VDP1 VRAM to CRAM to CRAM to reach the final color values. All of this is useful for making use of sprite priority and color calculations. Of course, this is dependent on the sprite type.
 
Back
Top