A7800Hawk: Rewrite Maria Rendering
- now has pixel accurate rendering - much simpler code
This commit is contained in:
parent
e983fc8419
commit
ca42aac5ff
|
@ -25,7 +25,10 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
|
||||
// technically there is no limit on the number of graphics objects, but since dma is automatically killed
|
||||
// at the end of a scanline, we have an effective limit
|
||||
GFX_Object[,] GFX_Objects = new GFX_Object[2,128];
|
||||
GFX_Object[] GFX_Objects = new GFX_Object[128];
|
||||
|
||||
public byte[,] line_ram = new byte[2, 320];
|
||||
byte temp_check = 0;
|
||||
|
||||
int GFX_index = 0;
|
||||
|
||||
|
@ -37,7 +40,6 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
public int[] _vidbuffer;
|
||||
public int[] _palette;
|
||||
public int[] scanline_buffer = new int[320];
|
||||
public int[] bg_temp = new int[320]; // since BG color can be changed midscanline, we need to account for this here.
|
||||
|
||||
public int[] GetVideoBuffer()
|
||||
{
|
||||
|
@ -88,7 +90,6 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
public bool global_write_mode;
|
||||
|
||||
public int header_counter;
|
||||
public int[] header_counter_max = new int [2];
|
||||
public int header_pointer; // since headers could be 4 or 5 bytes, we need a seperate pointer
|
||||
|
||||
// each frame contains 263 scanlines
|
||||
|
@ -210,12 +211,6 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
}
|
||||
}
|
||||
|
||||
if (cycle > 133)
|
||||
{
|
||||
bg_temp[cycle - 134] = Core.Maria_regs[0];
|
||||
}
|
||||
|
||||
|
||||
if (cycle == 453 && !sl_DMA_complete && do_dma && (DMA_phase == DMA_GRAPHICS || DMA_phase == DMA_HEADER))
|
||||
{
|
||||
overrun_dma = true;
|
||||
|
@ -234,15 +229,15 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
|
||||
Core.RunCPUCycle();
|
||||
|
||||
if (cycle >=130 && cycle < 450 && scanline > 20)
|
||||
{
|
||||
draw_pixel(scanline - 21, cycle - 130);
|
||||
}
|
||||
|
||||
cycle++;
|
||||
|
||||
if (cycle == 454)
|
||||
{
|
||||
if (scanline > 20)
|
||||
{
|
||||
// add the current graphics to the buffer
|
||||
draw_scanline(scanline - 21);
|
||||
}
|
||||
scanline++;
|
||||
cycle = 0;
|
||||
Core.tia._hsyncCnt = 0;
|
||||
|
@ -299,7 +294,7 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
if (DMA_phase_counter==1)
|
||||
{
|
||||
header_counter++;
|
||||
GFX_Objects[GFX_index, header_counter].addr = ReadMemory((ushort)(current_DLL_addr + header_pointer));
|
||||
GFX_Objects[header_counter].addr = ReadMemory((ushort)(current_DLL_addr + header_pointer));
|
||||
header_pointer++;
|
||||
byte temp = ReadMemory((ushort)(current_DLL_addr + header_pointer));
|
||||
// if there is no width, then we must have an extended header
|
||||
|
@ -324,12 +319,12 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
else
|
||||
{
|
||||
// we are in 5 Byte header mode (i.e. using the character map)
|
||||
GFX_Objects[GFX_index, header_counter].write_mode = temp.Bit(7);
|
||||
GFX_Objects[header_counter].write_mode = temp.Bit(7);
|
||||
global_write_mode = temp.Bit(7);
|
||||
GFX_Objects[GFX_index, header_counter].ind_mode = temp.Bit(5);
|
||||
GFX_Objects[header_counter].ind_mode = temp.Bit(5);
|
||||
header_pointer++;
|
||||
temp = (byte)(ReadMemory((ushort)(current_DLL_addr + header_pointer)));
|
||||
GFX_Objects[GFX_index, header_counter].addr |= (ushort)(temp << 8);
|
||||
GFX_Objects[header_counter].addr |= (ushort)(temp << 8);
|
||||
header_pointer++;
|
||||
temp = ReadMemory((ushort)(current_DLL_addr + header_pointer));
|
||||
int temp_w = (temp & 0x1F); // this is the 2's complement of width (for reasons that escape me)
|
||||
|
@ -337,18 +332,18 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
if (temp_w == 0)
|
||||
{
|
||||
// important note here. In 5 byte mode, width 0 actually counts as 32
|
||||
GFX_Objects[GFX_index, header_counter].width = 32;
|
||||
GFX_Objects[header_counter].width = 32;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp_w = (temp_w - 1);
|
||||
temp_w = (0x1F - temp_w);
|
||||
GFX_Objects[GFX_index, header_counter].width = (byte)(temp_w & 0x1F);
|
||||
GFX_Objects[header_counter].width = (byte)(temp_w & 0x1F);
|
||||
}
|
||||
|
||||
GFX_Objects[GFX_index, header_counter].palette = (byte)((temp & 0xE0) >> 5);
|
||||
GFX_Objects[header_counter].palette = (byte)((temp & 0xE0) >> 5);
|
||||
header_pointer++;
|
||||
GFX_Objects[GFX_index, header_counter].h_pos = ReadMemory((ushort)(current_DLL_addr + header_pointer));
|
||||
GFX_Objects[header_counter].h_pos = ReadMemory((ushort)(current_DLL_addr + header_pointer));
|
||||
header_pointer++;
|
||||
|
||||
DMA_phase_next = DMA_GRAPHICS;
|
||||
|
@ -361,21 +356,21 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
int temp_w = (temp & 0x1F); // this is the 2's complement of width (for reasons that escape me)
|
||||
temp_w = (temp_w - 1);
|
||||
temp_w = (0x1F - temp_w);
|
||||
GFX_Objects[GFX_index, header_counter].width = (byte)(temp_w & 0x1F);
|
||||
GFX_Objects[header_counter].width = (byte)(temp_w & 0x1F);
|
||||
|
||||
GFX_Objects[GFX_index, header_counter].palette = (byte)((temp & 0xE0) >> 5);
|
||||
GFX_Objects[header_counter].palette = (byte)((temp & 0xE0) >> 5);
|
||||
header_pointer++;
|
||||
temp = (byte)(ReadMemory((ushort)(current_DLL_addr + header_pointer)));
|
||||
GFX_Objects[GFX_index, header_counter].addr |= (ushort)(temp << 8);
|
||||
GFX_Objects[header_counter].addr |= (ushort)(temp << 8);
|
||||
header_pointer++;
|
||||
GFX_Objects[GFX_index, header_counter].h_pos = ReadMemory((ushort)(current_DLL_addr + header_pointer));
|
||||
GFX_Objects[header_counter].h_pos = ReadMemory((ushort)(current_DLL_addr + header_pointer));
|
||||
header_pointer++;
|
||||
|
||||
DMA_phase_next = DMA_GRAPHICS;
|
||||
|
||||
GFX_Objects[GFX_index, header_counter].write_mode = global_write_mode;
|
||||
GFX_Objects[header_counter].write_mode = global_write_mode;
|
||||
|
||||
GFX_Objects[GFX_index, header_counter].ind_mode = false;
|
||||
GFX_Objects[header_counter].ind_mode = false;
|
||||
|
||||
header_read_time = 8;
|
||||
}
|
||||
|
@ -396,38 +391,37 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
ushort addr_t = 0;
|
||||
|
||||
// in 5 byte mode, we first have to check if we are in direct or indirect mode
|
||||
if (GFX_Objects[GFX_index, header_counter].ind_mode)
|
||||
if (GFX_Objects[header_counter].ind_mode)
|
||||
{
|
||||
int ch_size = 0;
|
||||
|
||||
if (Core.Maria_regs[0x1C].Bit(4))
|
||||
{
|
||||
graphics_read_time = 9 * GFX_Objects[GFX_index, header_counter].width;
|
||||
graphics_read_time = 9 * GFX_Objects[header_counter].width + 3;
|
||||
ch_size = 2;
|
||||
GFX_Objects[GFX_index, header_counter].width *= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
graphics_read_time = 6 * GFX_Objects[GFX_index, header_counter].width;
|
||||
graphics_read_time = 6 * GFX_Objects[header_counter].width + 3;
|
||||
ch_size = 1;
|
||||
}
|
||||
|
||||
// the address here is specified by CHAR_BASE maria registers
|
||||
// ushort addr = (ushort)(GFX_Objects[header_counter].addr & 0xFF);
|
||||
for (int i = 0; i < GFX_Objects[GFX_index, header_counter].width; i++)
|
||||
for (int i = 0; i < GFX_Objects[header_counter].width; i++)
|
||||
{
|
||||
addr_t = ReadMemory((ushort)(GFX_Objects[GFX_index, header_counter].addr + i));
|
||||
addr_t = ReadMemory((ushort)(GFX_Objects[header_counter].addr + i));
|
||||
addr_t |= (ushort)((Core.Maria_regs[0x14] + current_DLL_offset) << 8);
|
||||
|
||||
if (((current_DLL_H16 && addr_t.Bit(12)) || (current_DLL_H8 && addr_t.Bit(11))) && (addr_t >= 0x8000))
|
||||
{
|
||||
if (i * ch_size < 128)
|
||||
{
|
||||
GFX_Objects[GFX_index, header_counter].obj[i * ch_size] = 0;
|
||||
GFX_Objects[header_counter].obj[i * ch_size] = 0;
|
||||
}
|
||||
if ((i * ch_size + 1 < 128) && (ch_size == 2))
|
||||
{
|
||||
GFX_Objects[GFX_index, header_counter].obj[i * ch_size + 1] = 0;
|
||||
GFX_Objects[header_counter].obj[i * ch_size + 1] = 0;
|
||||
}
|
||||
if (ch_size == 1)
|
||||
{
|
||||
|
@ -443,31 +437,34 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
{
|
||||
if (i * ch_size < 128)
|
||||
{
|
||||
GFX_Objects[GFX_index, header_counter].obj[i * ch_size] = ReadMemory(addr_t);
|
||||
GFX_Objects[header_counter].obj[i * ch_size] = ReadMemory(addr_t);
|
||||
fill_line_ram(GFX_Objects[header_counter].h_pos * 2, i, 0, ch_size, GFX_Objects[header_counter].obj[i * ch_size], GFX_Objects[header_counter].write_mode);
|
||||
}
|
||||
if (((i * ch_size + 1) < 128) && (ch_size == 2))
|
||||
{
|
||||
GFX_Objects[GFX_index, header_counter].obj[i * ch_size + 1] = ReadMemory((ushort)(addr_t + 1));
|
||||
GFX_Objects[header_counter].obj[i * ch_size + 1] = ReadMemory((ushort)(addr_t + 1));
|
||||
fill_line_ram(GFX_Objects[header_counter].h_pos * 2, i, 1, ch_size, GFX_Objects[header_counter].obj[i * ch_size + 1], GFX_Objects[header_counter].write_mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
graphics_read_time = 3 * GFX_Objects[GFX_index, header_counter].width;
|
||||
graphics_read_time = 3 * GFX_Objects[header_counter].width;
|
||||
|
||||
for (int i = 0; i < GFX_Objects[GFX_index, header_counter].width; i++)
|
||||
for (int i = 0; i < GFX_Objects[header_counter].width; i++)
|
||||
{
|
||||
addr_t = (ushort)(GFX_Objects[GFX_index, header_counter].addr + (current_DLL_offset << 8) + i);
|
||||
addr_t = (ushort)(GFX_Objects[header_counter].addr + (current_DLL_offset << 8) + i);
|
||||
|
||||
if (((current_DLL_H16 && addr_t.Bit(12)) || (current_DLL_H8 && addr_t.Bit(11))) && (addr_t >= 0x8000))
|
||||
{
|
||||
GFX_Objects[GFX_index, header_counter].obj[i] = 0;
|
||||
GFX_Objects[header_counter].obj[i] = 0;
|
||||
graphics_read_time -= 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
GFX_Objects[GFX_index, header_counter].obj[i] = ReadMemory(addr_t);
|
||||
GFX_Objects[header_counter].obj[i] = ReadMemory(addr_t);
|
||||
fill_line_ram(GFX_Objects[header_counter].h_pos * 2, i, 0, 1, GFX_Objects[header_counter].obj[i], GFX_Objects[header_counter].write_mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -488,7 +485,6 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
Core.cpu_resume_pending = true;
|
||||
sl_DMA_complete = true;
|
||||
current_DLL_offset -= 1; // this is reduced by one for each scanline, which changes where graphics are fetched
|
||||
header_counter_max[GFX_index] = header_counter;
|
||||
header_counter = -1;
|
||||
header_pointer = 0;
|
||||
return;
|
||||
|
@ -515,7 +511,6 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
current_DLL_H16 = temp.Bit(6);
|
||||
current_DLL_H8 = temp.Bit(5);
|
||||
|
||||
header_counter_max[GFX_index] = header_counter;
|
||||
header_counter = -1;
|
||||
header_pointer = 0;
|
||||
}
|
||||
|
@ -524,298 +519,153 @@ namespace BizHawk.Emulation.Cores.Atari.A7800Hawk
|
|||
}
|
||||
}
|
||||
|
||||
public void draw_scanline(int scanline)
|
||||
public void fill_line_ram(int temp_start, int index, int doub_size, int ch_s, byte temp_byte, bool w_m)
|
||||
{
|
||||
if (w_m)
|
||||
{
|
||||
temp_start = temp_start + index * ch_s * 4 + doub_size * 4;
|
||||
|
||||
for (int z = 0; z < 4; z++)
|
||||
{
|
||||
if ((temp_start + z) % 512 < 320)
|
||||
{
|
||||
if (z < 2)
|
||||
{
|
||||
temp_check = (byte)((temp_byte & 0xC) + ((temp_byte >> 6) & 0x3));
|
||||
}
|
||||
else
|
||||
{
|
||||
temp_check = (byte)(((temp_byte & 0x3) << 2) + ((temp_byte >> 4) & 0x3));
|
||||
}
|
||||
|
||||
if ((temp_check & 3) != 0)
|
||||
{
|
||||
line_ram[GFX_index, (temp_start + z) % 512] = temp_check;
|
||||
line_ram[GFX_index, (temp_start + z) % 512] += (byte)((GFX_Objects[header_counter].palette & 4) << 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
temp_start = temp_start + index * ch_s * 8 + doub_size * 8;
|
||||
|
||||
for (int z = 0; z < 8; z++)
|
||||
{
|
||||
if (((temp_start + z) % 512) < 320)
|
||||
{
|
||||
if (z < 2)
|
||||
{
|
||||
temp_check = (byte)((temp_byte >> 6) & 0x3);
|
||||
}
|
||||
else if (z < 4)
|
||||
{
|
||||
temp_check = (byte)((temp_byte >> 4) & 0x3);
|
||||
}
|
||||
else if (z < 6)
|
||||
{
|
||||
temp_check = (byte)((temp_byte >> 2) & 0x3);
|
||||
}
|
||||
else
|
||||
{
|
||||
temp_check = (byte)(temp_byte & 0x3);
|
||||
}
|
||||
|
||||
if (temp_check != 0)
|
||||
{
|
||||
line_ram[GFX_index, (temp_start + z) % 512] = temp_check;
|
||||
line_ram[GFX_index, (temp_start + z) % 512] += (byte)(GFX_Objects[header_counter].palette << 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void draw_pixel(int scanline, int pixel)
|
||||
{
|
||||
int local_start;
|
||||
int local_width;
|
||||
int local_palette;
|
||||
int index;
|
||||
int color;
|
||||
int local_GFX_index;
|
||||
int temp_palette = 0;
|
||||
int temp_bit_0 = 0;
|
||||
int temp_bit_1 = 0;
|
||||
|
||||
local_GFX_index = (GFX_index == 1) ? 0 : 1; // whatever the current index is, we use the opposite
|
||||
|
||||
int disp_mode = Core.Maria_regs[0x1C] & 0x3;
|
||||
|
||||
for (int i = 0; i < 320; i++)
|
||||
{
|
||||
scanline_buffer[i] = _palette[bg_temp[i]];
|
||||
}
|
||||
scanline_buffer[pixel] = _palette[Core.Maria_regs[0x00]];
|
||||
|
||||
for (int i = 0; i < header_counter_max[local_GFX_index]; i++)
|
||||
{
|
||||
local_start = GFX_Objects[local_GFX_index, i].h_pos;
|
||||
local_palette = GFX_Objects[local_GFX_index, i].palette;
|
||||
color = line_ram[local_GFX_index, pixel];
|
||||
|
||||
// the two different rendering paths are basically controlled by write mode
|
||||
if (GFX_Objects[local_GFX_index, i].write_mode)
|
||||
if (disp_mode == 0)
|
||||
{
|
||||
if ((color & 3) != 0)
|
||||
{
|
||||
if (disp_mode == 0)
|
||||
{
|
||||
local_width = GFX_Objects[local_GFX_index, i].width;
|
||||
scanline_buffer[pixel] = _palette[Core.Maria_regs[color]];
|
||||
}
|
||||
}
|
||||
else if (disp_mode == 2) // note: 1 is not used
|
||||
{
|
||||
// there is a trick here to be aware of.
|
||||
// the renderer has no concept of objects, as it only has information on each pixel
|
||||
// but objects are specified in groups of 8 pixels.
|
||||
// however, since objects can only be placed in 160 resolution
|
||||
// we can pick bits based on whether the current pixel is even or odd
|
||||
temp_palette = color & 0x10;
|
||||
temp_bit_0 = 0;
|
||||
temp_bit_1 = 0;
|
||||
|
||||
for (int j = 0; j < local_width; j++)
|
||||
{
|
||||
for (int k = 3; k >= 0; k--)
|
||||
{
|
||||
index = local_start * 2 + j * 4 + (3 - k);
|
||||
|
||||
if (index > 511)
|
||||
{
|
||||
index -= 512;
|
||||
}
|
||||
|
||||
if (index < 320)
|
||||
{
|
||||
color = GFX_Objects[local_GFX_index, i].obj[j];
|
||||
|
||||
// this is now the color index (0-3) we choose from the palette
|
||||
if (k >= 2)
|
||||
{
|
||||
color = (((color >> 2) & 0x3) << 2) + ((color >> 6) & 0x3);
|
||||
}
|
||||
else
|
||||
{
|
||||
color = ((color & 0x3) << 2) + ((color >> 4) & 0x3);
|
||||
}
|
||||
|
||||
if ((color != 0) && (color != 4) && (color != 8) && (color != 12)) // transparent
|
||||
{
|
||||
color = ((local_palette & 4) << 2) + color;
|
||||
|
||||
color = Core.Maria_regs[color];
|
||||
|
||||
scanline_buffer[index] = _palette[color];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (disp_mode == 2) // note: 1 is not used
|
||||
{
|
||||
local_width = GFX_Objects[local_GFX_index, i].width;
|
||||
|
||||
for (int j = 0; j < local_width; j++)
|
||||
{
|
||||
for (int k = 7; k >= 0; k--)
|
||||
{
|
||||
index = local_start * 4 + j * 8 + (7 - k);
|
||||
|
||||
if (index > 511)
|
||||
{
|
||||
index -= 512;
|
||||
}
|
||||
|
||||
if (index < 320)
|
||||
{
|
||||
color = GFX_Objects[local_GFX_index, i].obj[j];
|
||||
|
||||
// this is now the color index (0-3) we choose from the palette
|
||||
if (k >= 6)
|
||||
{
|
||||
color = ((color >> 6) & 0x2) + ((color >> 3) & 0x1);
|
||||
}
|
||||
else if (k >= 4)
|
||||
{
|
||||
color = ((color >> 5) & 0x2) + ((color >> 2) & 0x1);
|
||||
|
||||
}
|
||||
else if (k >= 2)
|
||||
{
|
||||
color = ((color >> 4) & 0x2) + ((color >> 1) & 0x1);
|
||||
}
|
||||
else
|
||||
{
|
||||
color = ((color >> 3) & 0x2) + (color & 0x1);
|
||||
}
|
||||
|
||||
if (color != 0) // transparent
|
||||
{
|
||||
color = ((local_palette & 4) << 2) + color;
|
||||
|
||||
color = Core.Maria_regs[color];
|
||||
|
||||
scanline_buffer[index] = _palette[color];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
local_width = GFX_Objects[local_GFX_index, i].width;
|
||||
|
||||
for (int j = 0; j < local_width; j++)
|
||||
{
|
||||
for (int k = 3; k >= 0; k--)
|
||||
{
|
||||
index = local_start * 2 + j * 4 + (3 - k);
|
||||
|
||||
if (index > 511)
|
||||
{
|
||||
index -= 512;
|
||||
}
|
||||
|
||||
if (index < 320)
|
||||
{
|
||||
color = GFX_Objects[local_GFX_index, i].obj[j];
|
||||
int temp_color = color;
|
||||
|
||||
// this is now the color index (0-3) we choose from the palette
|
||||
if (k >= 3)
|
||||
{
|
||||
color = ((color >> 7) & 0x1);
|
||||
temp_color = (local_palette & 4) + ((temp_color >> 2) & 3);
|
||||
}
|
||||
else if (k >= 2)
|
||||
{
|
||||
color = ((color >> 6) & 0x1);
|
||||
temp_color = (local_palette & 4) + ((temp_color >> 2) & 3);
|
||||
|
||||
}
|
||||
else if (k >= 1)
|
||||
{
|
||||
color = ((color >> 5) & 0x1);
|
||||
temp_color = (local_palette & 4) + (temp_color & 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
color = ((color >> 4) & 0x1);
|
||||
temp_color = (local_palette & 4) + (temp_color & 3);
|
||||
}
|
||||
|
||||
if (color != 0) // transparent
|
||||
{
|
||||
color = (temp_color << 2) + 2;
|
||||
|
||||
color = Core.Maria_regs[color];
|
||||
|
||||
scanline_buffer[index] = _palette[color];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pixel % 2 == 0)
|
||||
{
|
||||
temp_bit_1 = color & 2;
|
||||
temp_bit_0 = (color & 8) >> 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (disp_mode == 0)
|
||||
{
|
||||
local_width = GFX_Objects[local_GFX_index, i].width;
|
||||
temp_bit_1 = (color & 1) << 1;
|
||||
temp_bit_0 = (color & 4) >> 2;
|
||||
}
|
||||
|
||||
for (int j = 0; j < local_width; j++)
|
||||
{
|
||||
for (int k = 7; k >= 0; k--)
|
||||
{
|
||||
index = local_start * 2 + j * 8 + (7 - k);
|
||||
color = temp_palette + temp_bit_1 + temp_bit_0;
|
||||
|
||||
if (index > 511)
|
||||
{
|
||||
index -= 512;
|
||||
}
|
||||
|
||||
if (index < 320)
|
||||
{
|
||||
color = GFX_Objects[local_GFX_index, i].obj[j];
|
||||
|
||||
// this is now the color index (0-3) we choose from the palette
|
||||
if (k >= 6)
|
||||
{
|
||||
color = (color >> 6) & 0x3;
|
||||
}
|
||||
else if (k >= 4)
|
||||
{
|
||||
color = (color >> 4) & 0x3;
|
||||
|
||||
}
|
||||
else if (k >= 2)
|
||||
{
|
||||
color = (color >> 2) & 0x3;
|
||||
}
|
||||
else
|
||||
{
|
||||
color = color & 0x3;
|
||||
}
|
||||
|
||||
if (color != 0) // transparent
|
||||
{
|
||||
color = Core.Maria_regs[local_palette * 4 + color];
|
||||
|
||||
scanline_buffer[index] = _palette[color];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (disp_mode == 2) // note: 1 is not used
|
||||
{
|
||||
local_width = GFX_Objects[local_GFX_index, i].width;
|
||||
// here the palette is determined by palette bit 2 only
|
||||
// hence only palette 0 or 4 is available
|
||||
local_palette = GFX_Objects[local_GFX_index, i].palette & 0x4;
|
||||
|
||||
int temp_c0 = GFX_Objects[local_GFX_index, i].palette & 0x1;
|
||||
int temp_c1 = GFX_Objects[local_GFX_index, i].palette & 0x2;
|
||||
|
||||
for (int j = 0; j < local_width; j++)
|
||||
{
|
||||
for (int k = 7; k >= 0; k--)
|
||||
{
|
||||
color = (GFX_Objects[local_GFX_index, i].obj[j] >> k) & 1;
|
||||
color = (color << 1) | ((k % 2 == 0) ? temp_c0 : temp_c1);
|
||||
index = local_start * 2 + j * 8 + (7 - k);
|
||||
if (index > 511) index -= 512;
|
||||
|
||||
if (index < 320)
|
||||
{
|
||||
color = Core.Maria_regs[local_palette + color];
|
||||
|
||||
scanline_buffer[index] = _palette[color];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
local_width = GFX_Objects[local_GFX_index, i].width;
|
||||
|
||||
for (int j = 0; j < local_width; j++)
|
||||
{
|
||||
for (int k = 7; k >= 0; k--)
|
||||
{
|
||||
color = (GFX_Objects[local_GFX_index, i].obj[j] >> k) & 1;
|
||||
index = local_start * 2 + j * 8 + (7 - k);
|
||||
if (index > 511) index -= 512;
|
||||
if (index < 320 && color == 1)
|
||||
{
|
||||
color = Core.Maria_regs[local_palette * 4 + 2]; // automatically use index 2 here
|
||||
|
||||
scanline_buffer[index] = _palette[color];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((color & 3) != 0)
|
||||
{
|
||||
scanline_buffer[pixel] = _palette[Core.Maria_regs[color]];
|
||||
}
|
||||
}
|
||||
|
||||
// send buffer to the video buffer
|
||||
for (int i = 0; i < 320; i ++)
|
||||
else
|
||||
{
|
||||
_vidbuffer[scanline * 320 + i] = scanline_buffer[i];
|
||||
// same as above, we can use the pixel index to pick the bits out
|
||||
if (pixel % 2 == 0)
|
||||
{
|
||||
color &= 0x1E;
|
||||
}
|
||||
else
|
||||
{
|
||||
color = (color & 0x1C) + ((color & 1) << 1);
|
||||
}
|
||||
|
||||
if ((color & 3) != 0)
|
||||
{
|
||||
scanline_buffer[pixel] = _palette[Core.Maria_regs[color]];
|
||||
}
|
||||
}
|
||||
|
||||
// send buffer to the video buffer
|
||||
_vidbuffer[scanline * 320 + pixel] = scanline_buffer[pixel];
|
||||
|
||||
// clear the line ram
|
||||
line_ram[local_GFX_index, pixel] = 0;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
_vidbuffer = new int[VirtualWidth * VirtualHeight];
|
||||
|
||||
for (int j = 0; j < 2; j++)
|
||||
for (int i = 0; i < 128; i++)
|
||||
{
|
||||
for (int i = 0; i < 128; i++)
|
||||
{
|
||||
GFX_Objects[j, i].obj = new byte[128];
|
||||
}
|
||||
}
|
||||
GFX_Objects[i].obj = new byte[128];
|
||||
}
|
||||
}
|
||||
|
||||
// Most of the Maria state is captured in Maria Regs in the core
|
||||
|
|
Loading…
Reference in New Issue