Implemenmted rendering priorities
This commit is contained in:
@@ -9,6 +9,7 @@ namespace Core.Video
|
||||
public byte[] CRAM { get; private set; } = new byte[0x20]; // 32 Bytes Color Palette
|
||||
public byte[] Registers { get; private set; } = new byte[16]; // 11 Hardware Control Registers
|
||||
public int[] FrameBuffer { get; private set; } = new int[256 * 192];
|
||||
private bool[] _priorityBuffer = new bool[256 * 192]; // Tracks priority pixels!
|
||||
|
||||
// The Control Port State Machine (Port 0xBF)
|
||||
private bool _isSecondControlByte = false;
|
||||
@@ -131,18 +132,19 @@ namespace Core.Video
|
||||
private void RenderBackground()
|
||||
{
|
||||
ushort nameTableBase = (ushort)((Registers[2] & 0x0E) << 10);
|
||||
|
||||
byte scrollX = Registers[8];
|
||||
byte scrollY = Registers[9];
|
||||
|
||||
bool lockRowScroll = (Registers[0] & 0x80) != 0; // Top 2 rows (Y < 16)
|
||||
bool lockColScroll = (Registers[0] & 0x40) != 0; // Right 8 columns (X >= 192)
|
||||
bool lockRowScroll = (Registers[0] & 0x80) != 0;
|
||||
bool lockColScroll = (Registers[0] & 0x40) != 0;
|
||||
|
||||
// Clear the priority mask for the new frame!
|
||||
Array.Clear(_priorityBuffer, 0, _priorityBuffer.Length);
|
||||
|
||||
for (int screenY = 0; screenY < 192; screenY++)
|
||||
{
|
||||
for (int screenX = 0; screenX < 256; screenX++)
|
||||
{
|
||||
// Apply Vertical Scrolling (Depends on X for column locking!)
|
||||
int effectiveScrollY = scrollY;
|
||||
if (lockColScroll && screenX >= 192) effectiveScrollY = 0;
|
||||
|
||||
@@ -150,7 +152,6 @@ namespace Core.Video
|
||||
int row = vdpY / 8;
|
||||
int tileY = vdpY % 8;
|
||||
|
||||
// Apply Horizontal Scrolling (Depends on Y for row locking!)
|
||||
int effectiveScrollX = scrollX;
|
||||
if (lockRowScroll && screenY < 16) effectiveScrollX = 0;
|
||||
|
||||
@@ -158,31 +159,34 @@ namespace Core.Video
|
||||
int col = vdpX / 8;
|
||||
int tileX = vdpX % 8;
|
||||
|
||||
// 1. Read the 16-bit Tile instruction from the Name Table
|
||||
// 1. Read the 16-bit Tile instruction
|
||||
ushort nameTableAddr = (ushort)(nameTableBase + (row * 64) + (col * 2));
|
||||
byte lowByte = VRAM[nameTableAddr];
|
||||
byte highByte = VRAM[nameTableAddr + 1];
|
||||
ushort tileData = (ushort)((highByte << 8) | lowByte);
|
||||
|
||||
// 2. Extract Tile Index and Palette Info
|
||||
// 2. EXTRACT ALL THE HARDWARE BITS!
|
||||
int tileIndex = tileData & 0x01FF;
|
||||
bool useSpritePalette = (tileData & 0x0800) != 0;
|
||||
bool flipH = (tileData & 0x0200) != 0; // Bit 9
|
||||
bool flipV = (tileData & 0x0400) != 0; // Bit 10
|
||||
bool useSpritePalette = (tileData & 0x0800) != 0; // Bit 11
|
||||
bool priority = (tileData & 0x1000) != 0; // Bit 12
|
||||
|
||||
// 3. Find the tile data in VRAM
|
||||
// 3. Apply Vertical Flip (Read from the bottom of the tile instead of the top)
|
||||
int readY = flipV ? (7 - tileY) : tileY;
|
||||
ushort tileAddress = (ushort)(tileIndex * 32);
|
||||
|
||||
// 4. Fetch the 4 bitplanes
|
||||
byte bp0 = VRAM[tileAddress + (tileY * 4) + 0];
|
||||
byte bp1 = VRAM[tileAddress + (tileY * 4) + 1];
|
||||
byte bp2 = VRAM[tileAddress + (tileY * 4) + 2];
|
||||
byte bp3 = VRAM[tileAddress + (tileY * 4) + 3];
|
||||
byte bp0 = VRAM[tileAddress + (readY * 4) + 0];
|
||||
byte bp1 = VRAM[tileAddress + (readY * 4) + 1];
|
||||
byte bp2 = VRAM[tileAddress + (readY * 4) + 2];
|
||||
byte bp3 = VRAM[tileAddress + (readY * 4) + 3];
|
||||
|
||||
// 5. Extract color index
|
||||
int shift = 7 - tileX;
|
||||
int colorIndex = ((bp0 >> shift) & 1) |
|
||||
(((bp1 >> shift) & 1) << 1) |
|
||||
(((bp2 >> shift) & 1) << 2) |
|
||||
(((bp3 >> shift) & 1) << 3);
|
||||
// 4. Apply Horizontal Flip (Shift from right-to-left instead of left-to-right)
|
||||
int readX = flipH ? tileX : (7 - tileX);
|
||||
int colorIndex = ((bp0 >> readX) & 1) |
|
||||
(((bp1 >> readX) & 1) << 1) |
|
||||
(((bp2 >> readX) & 1) << 2) |
|
||||
(((bp3 >> readX) & 1) << 3);
|
||||
|
||||
int paletteOffset = useSpritePalette ? 16 : 0;
|
||||
byte smsColor = CRAM[paletteOffset + colorIndex];
|
||||
@@ -191,7 +195,16 @@ namespace Core.Video
|
||||
int g = ((smsColor >> 2) & 0x03) * 85;
|
||||
int b = ((smsColor >> 4) & 0x03) * 85;
|
||||
|
||||
FrameBuffer[(screenY * 256) + screenX] = (255 << 24) | (r << 16) | (g << 8) | b;
|
||||
int screenAddress = (screenY * 256) + screenX;
|
||||
FrameBuffer[screenAddress] = (255 << 24) | (r << 16) | (g << 8) | b;
|
||||
|
||||
// 5. FLAG THE PRIORITY PIXEL!
|
||||
// If this tile has priority AND the pixel isn't transparent (color 0),
|
||||
// tell the sprite renderer not to draw over it!
|
||||
if (priority && colorIndex != 0)
|
||||
{
|
||||
_priorityBuffer[screenAddress] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -262,6 +275,9 @@ namespace Core.Video
|
||||
// If the color index is 0, DO NOT draw it! Let the background show through.
|
||||
if (colorIndex == 0) continue;
|
||||
|
||||
// If the background tile at this exact pixel claimed priority, hide the sprite!
|
||||
if (_priorityBuffer[(screenY * 256) + screenX]) continue;
|
||||
|
||||
// Sprites ALWAYS use the second half of CRAM (Palette 1: Indices 16-31)
|
||||
byte smsColor = CRAM[16 + colorIndex];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user