VERA and number 48 ...

Chat about anything CX16 related that doesn't fit elsewhere
User avatar
svenvandevelde
Posts: 488
Joined: Wed Dec 23, 2020 6:30 am
Location: Belgium, Antwerpen

VERA and number 48 ...

Post by svenvandevelde »


Hi,

Before you read further, please keep in mind that this post is not meant to pose any critic to Frank VdH or to the overall design of the CX16 regarding its graphics capabilities ...

However, allow me to reflect the followiing ...

Using vera in 640x400 graphics mode, there is a function in vera which I believe which could be further fine tuned ... It is the setting of the height and width of sprites ...

Sprites can be configured as 8, 16, 32 and 64 width and height by setting the respective bits in register 7 of the sprite attributes...

image.png.332f590b511e87d179310409d06860b3.png

I find the width and height of 64 however a bit too big of a gap.

Hopping from 8 to 16 is ok, from 16 to 32 is ok, but from 32 to 64 means that in terms of memory consumption there is a big increase ...

Let me illustrate:


  • 8 x 8 in 4bpp requires 32 bytes.


  • 16 x 16 in 4bpp requires 128 bytes.


  • 32 x 32 in 4bpp requires 512 bytes.


  • 64 x 64 in 4bpp requires 2048. In 8 bpp that would be a whopping 4096 bytes!


My question is, what if the vera would model the sprite painting with the following width registers: 16, 32, 48, 64, and discard the 8 pixel width and height setting.

That would mean, that the following mode would become available:


  • 48 x 48 in 4bpp requires 1152 bytes, in 8bpp that would be 2304 bytes.


 

Additionally:


  • A sprite width/height of 32 x 32 is too limiting, it does not draw sprites with sufficient size. It is a bit too small.


  • A sprite width/height of 64 x 64 is big, which is great, but it consumes too much memory. These kind of sprites would have a more limited animation count to save memory.


  • A sprite width/height of 48 x 48 would be a great size, as this would not consume too much memory, but would show sprites with sufficient pixel size.


Please see examples below:

1879682699_2022-10-03(1).thumb.png.f5e7f4eb6687c1c37fe2744568670d6c.png

Above is an example of a 48 x 48 sprite animation...

 

1535898409_2022-10-03(27).thumb.png.34c6cd4ee1b74b9665c2dd84bb49e629.png

Above is an animation of a 32 x 32 animation, great but a bit small. However, this size is perfect to flood the screen with enemies :-).

But the density to show sprite animations is limited and the width/height quickly becomes obvious to the player that 32x32 is the limit as all sprites will be in this size ...

 

269720725_2022-10-03(28).thumb.png.d4c818673b91b486d95184b02c0ad24b.png

Above shows 64 x 64 sprites animation, great for larger type of enemies, but consumes a lot of space.

 

The 48 x 48 sprite size seems to be the right fit, a 64 x 64 is needed, but consumes a lot of memory.



Drawing a 48 x 48 sprite animation results in a lot of vram memory being lost, due to having to draw this 48 x 48 sprite animation on 64 x 64 planes.

One could argue, that yes, we can do magic and start combining sprites to make larger pictures to draw a 48x48 bitmap, like drawing 9 16x16 sprites, or 1 sprite of 32x32 + 1 sprite of 16x32 + 1 sprite of 32x16 + 1 sprite of 16x16 ... But that would make things very, very complicated, and also notice by having to draw 9 or 4 sprites instead of one, there is a performance impact. Also notice, that if I would draw a 48x48 sprite out of 9 sprites of 16x16, that would mean 72 sprites to be drawn if i want to show 8 images of 48x48 pixels!

Any thoughts on this? @Wavicle?

KICKC home page by Jesper Gravgaard.
My KICKC alpha with Commander X16 extensions.
User avatar
AndyMt
Posts: 326
Joined: Sun Jun 21, 2020 3:02 pm
Location: Switzerland

VERA and number 48 ...

Post by AndyMt »


I can see where you are coming from, however:


On 10/3/2022 at 8:30 AM, svenvandevelde said:




and discard the 8 pixel width and height setting.



I use that size and it solved a VRAM shortage in Invaderz. I could squeeze just about everything in by using 8x8 for the phasers etc. Having to use 16x16 instead would be too much... Ok, maybe I could make it by analysing carefully again, but 8x8 has it's advantages. Especially if using 320x240 resolution. You would never use 64x64 there I think...

I would argue to drop 64x64 in favor of 48x48... but then maybe someone else already has a reasonable use case for that? Or drop 8x8 if in 640x400 resolution? Or use one of the unused bits in byte 1 to switch to a different size scheme?

User avatar
svenvandevelde
Posts: 488
Joined: Wed Dec 23, 2020 6:30 am
Location: Belgium, Antwerpen

VERA and number 48 ...

Post by svenvandevelde »



On 10/3/2022 at 9:36 AM, AndyMt said:




Or use one of the unused bits in byte 1 to switch to a different size scheme?



This idea would be a fantastic solution. 

Other could be that the scheme adapts based on screen width/height setting?

KICKC home page by Jesper Gravgaard.
My KICKC alpha with Commander X16 extensions.
User avatar
Yazwho
Posts: 167
Joined: Fri Feb 19, 2021 2:59 pm
Contact:

VERA and number 48 ...

Post by Yazwho »


Someone with more knowledge can correct me:

The sizes are so vera can pull data quickly, as it can mask or shift the address to look up the sprite data.

At 48bits the maths become more complicated as it would have to calculate the offset first which would reduce the number of sprites per line.

 

User avatar
AndyMt
Posts: 326
Joined: Sun Jun 21, 2020 3:02 pm
Location: Switzerland

VERA and number 48 ...

Post by AndyMt »



On 10/3/2022 at 11:00 AM, Yazwho said:




The sizes are so vera can pull data quickly, as it can mask or shift the address to look up the sprite data.



That's true. With 48 pixels you cannot use simple bit operations (or the hardware equivalent) to get to the next line of data. This could reduce the number of available sprites per scan line.

Also any logic switching between different sizes based on an additional bit in some register would have the same effect.

User avatar
svenvandevelde
Posts: 488
Joined: Wed Dec 23, 2020 6:30 am
Location: Belgium, Antwerpen

VERA and number 48 ...

Post by svenvandevelde »


32 +16 = 48

KICKC home page by Jesper Gravgaard.
My KICKC alpha with Commander X16 extensions.
Wavicle
Posts: 282
Joined: Sun Feb 21, 2021 2:40 am

VERA and number 48 ...

Post by Wavicle »


I will think on this. I think calculating row address with 48 pixels isn't too bad. E.g.:

row = y_counter - sprite_y_start;

if (mode) begin

    // 8bpp

    line_addr = sprite_offset + (row << 6) - (row << 4); // row * 64 - row * 16

end

else begin

    // 4bpp

    line_addr = sprite_offset + (row << 5) - (row << 3); // row * 32 - row * 8

end

Something along those lines should work. I probably need to wake up a bit more and reality check this against the Verilog. Another concern is breaking any existing software that uses 64x64 sprites.

ZeroByte
Posts: 714
Joined: Wed Feb 10, 2021 2:40 pm

VERA and number 48 ...

Post by ZeroByte »


honestly, the correct solution is to use multiple sprites for one object. This is how it was done on classic systems.

Take this sprite of Samus from Super Metroid:

samus.gif.ef9743d5583fec7ff2a80fe626b4e63b.gif

It requires 36px to cover the full width of the character on screen. However, most of that extra 4px of width is blank, with only 10px height for back foot. This can be contained in an 8x16 sprite placed correctly in relation to the main 32x32 sprite. If I were to make a demo/game using artwork of this sort, I would simply make the actor/object control these sprites and define animation frames for each one.  In cases where the "extra bits" (like Samus's foot) move around relative to the main sprite, the engine would also need an x/y offsets table. In the Samus animation, the back foot is near the bottom of the sprite for one frame, and closer to the top on the next frame. This "foot sprite" would just be drawn at different relative locations to the main sprite during each frame of the animation cycle.



1268944635_SamusPieces.png.1570e1d91227178392831dbbcdd0efcd.png1091194834_SamusPieces2.png.e8aa00d7b87f4402afe8057b1ff9f02d.png



My Sonic demo faced a similar issue on the Sonic sprite, which is 40px tall. I used one 32x32 sprite for the main part of Sonic:

sonicmain.png.49dda40f9f35b23ba2d684f18f6bd2b3.png

and I use a separate sprite for the ears:

sonicears.png.3b0017f32e522d7cdfa0a0980425ae95.png

Interestingly, the ears only require 2 frames of animation (frames 3 and 4 are duplicates of 1 and 2). I didn't bother deleting frames 3 and 4 from the resource, as I've got plenty of VRAM for this simple demo, but the engine never uses those frames. I set up an animation frames table with the VRAM locations of the frames, and the engine cycles through these tables. So the main body's data is the VRAM address equivalents of: 0, 1, 2, 3 and the ear's data is 0, 1, 0, 1. This is also useful for "pingpong" animations where you only need pixel data for 3 frames of a walk/run cycle and you just display them as 0,1,2,1,0,1,2,1... no need to have frame 1 in VRAM twice.



This is part of the challenge of programming retro. It's nice when HW just does the work for you, but when it doesn't, that doesn't mean you're stuck. You just have to code a solution. This stuff I've explained here actually saves more memory too, as you only need exactly the pixel data for exactly the parts that go out-of-bounds. The lazy alternative would've been to use a 64x64 sprite, but yes, that would gobble up VRAM needlessly.



Hope this makes sense.

User avatar
svenvandevelde
Posts: 488
Joined: Wed Dec 23, 2020 6:30 am
Location: Belgium, Antwerpen

VERA and number 48 ...

Post by svenvandevelde »



On 10/3/2022 at 2:37 PM, Wavicle said:




I will think on this. I think calculating row address with 48 pixels isn't too bad. E.g.:



row = y_counter - sprite_y_start;

if (mode) begin

    // 8bpp

    line_addr = sprite_offset + (row << 6) - (row << 4); // row * 64 - row * 16

end

else begin

    // 4bpp

    line_addr = sprite_offset + (row << 5) - (row << 3); // row * 32 - row * 8

end



Something along those lines should work. I probably need to wake up a bit more and reality check this against the Verilog. Another concern is breaking any existing software that uses 64x64 sprites.



I suggest to model it that the high resolution 640 width supports 16, 32, 48, 64 resolutions.

And the lower resolution 320 supporting 8, 16, 32, 48?

 

lol

KICKC home page by Jesper Gravgaard.
My KICKC alpha with Commander X16 extensions.
User avatar
AndyMt
Posts: 326
Joined: Sun Jun 21, 2020 3:02 pm
Location: Switzerland

VERA and number 48 ...

Post by AndyMt »



On 10/3/2022 at 2:29 PM, svenvandevelde said:




32 +16 = 48



Yes sure, but it's still an additional operation. Don't know how many resources on the FPGA are left - if there are any. But if it's possible to do, I'm all in for it ?!

Post Reply