fvdhoef / vera-module

Versatile Embedded Retro Adapter
MIT License
106 stars 44 forks source link

Sprite rendering priority doesn't match documentation #10

Closed jburks closed 2 years ago

jburks commented 2 years ago

Sprites at the same Z depth are rendered from lowest VRAM location to highest location which places sprites at the lowest location behind all others at the same Z depth. This is opposite to what is stated in the VERA documentation:

Rendering Priority The sprite memory location dictates the order in which it is rendered. The sprite whose attributes are at the lowest location will be rendered in front of all other sprites; the sprite at the highest location will be rendered behind all other sprites, and so forth.

The Commander X16 emulator implements rendering priority as described in the documentation which does not match hardware. Comparing the appearance of the end screen of the FlappyX16 game between hardware and emulator resulted in several sprites being invisible when played on hardware because those sprites were rendered behind a larger sprite at a higher VRAM location. Those same sprites were visible on the emulator. Changing the sprite order such that background sprites were placed into lower locations fixed the rendering on hardware.

Some possible fixes for this:

  1. Update the documentation and X16 emulator to reflect the functionality of the hardware. This may require existing software to be rewritten.
  2. Update VERA to render sprites at higher locations first. This will make VERA match the documentation and emulator, but may cause undesirable effects when higher priority / low VRAM location sprites do not get rendered due to running out of available rendering cycles / "work units".
  3. Update VERA such that it does not render sprite pixels to non-transparent pixels in the line buffer. This is probably the best solution and might work by inverting the is_pixel_transparent check in this line:
    // Determine if current pixel should be rendered
    wire render_pixel =  !pixel_is_transparent && sprite_z_r >= linebuf_rddata[9:8] && tmp_pixel_color != 0;
jburks commented 2 years ago

Fix suggestion 3 isn't quite right since !pixel_is_transparent refers to the current sprite, not the pixel from the line buffer.