O2Hawk: better fix for blockout
This commit is contained in:
parent
786fd9d5a1
commit
cb2d365284
|
@ -4,15 +4,9 @@ using BizHawk.Common.NumberExtensions;
|
|||
using BizHawk.Emulation.Common;
|
||||
|
||||
/*
|
||||
Notes: The line position returned by A4 is offset from display by 6 lines.
|
||||
The game blockout requires VBLank interrupt to be able to execute relative to a particular line value,
|
||||
but this line value would fall outside vblank by a wide margin if the Y return matched screen position relative to end of VBL
|
||||
This offset also makes the borders in Cosmic Conflict match to console, so presumably it is correct.
|
||||
But this effect isn't enough by itself to get correct display. Also from the data sheet for the 8245, the 'program coordinates' of the
|
||||
grid are 5 scanlines behind ahead of the actual display, so changes take effect 5 scanline later then for other objects like the BG.
|
||||
|
||||
Notes: Blockout expects STAT to return VBl 1 even outside VBl range. So this is an interrupt request bit, not a status bit (similar to sound)
|
||||
Also, according to the 8245 data sheet, the hbl status flag starts at roughly halfway through the scanline. This is also
|
||||
crucial for Blockout to display correctly.
|
||||
crucial for Blockout to display correctly. However this bit is reset once HBL ends
|
||||
|
||||
Blockout also turns on HBL interrupts and expects them either not to fire (or only one to fire per write to A0)
|
||||
*/
|
||||
|
@ -31,14 +25,13 @@ namespace BizHawk.Emulation.Cores.Consoles.O2Hawk
|
|||
public const int HBL_CNT = 45;
|
||||
public const int GRID_OFST = 24;
|
||||
public const int OBJ_OFST = 0;
|
||||
public const int SHT_SZ = 8;
|
||||
|
||||
public byte[] Sprites = new byte[16];
|
||||
public byte[] Sprite_Shapes = new byte[32];
|
||||
public byte[] Foreground = new byte[48];
|
||||
public byte[] Quad_Chars = new byte[64];
|
||||
public byte[] Grid_H = new byte[18 * SHT_SZ];
|
||||
public byte[] Grid_V = new byte[10 * SHT_SZ];
|
||||
public byte[] Grid_H = new byte[18];
|
||||
public byte[] Grid_V = new byte[10];
|
||||
public byte[] VDC_col_ret = new byte[8];
|
||||
|
||||
public byte VDC_ctrl, VDC_status, VDC_collision, VDC_color;
|
||||
|
@ -58,10 +51,6 @@ namespace BizHawk.Emulation.Cores.Consoles.O2Hawk
|
|||
public bool HBL_req;
|
||||
public int LY_ret;
|
||||
|
||||
public byte[] VDC_ctrl_latch = new byte[SHT_SZ];
|
||||
public byte[] VDC_color_latch = new byte[SHT_SZ];
|
||||
public int[] grid_brightness_latch = new int[SHT_SZ];
|
||||
|
||||
// local variables not stated
|
||||
int current_pixel_offset;
|
||||
int double_size;
|
||||
|
@ -97,6 +86,7 @@ namespace BizHawk.Emulation.Cores.Consoles.O2Hawk
|
|||
{
|
||||
ret = VDC_status;
|
||||
// reading status clears IRQ request
|
||||
VDC_status &= 0xF7;
|
||||
Core.cpu.IRQPending = false;
|
||||
}
|
||||
else if (addr == 0xA2)
|
||||
|
@ -118,7 +108,7 @@ namespace BizHawk.Emulation.Cores.Consoles.O2Hawk
|
|||
else if(addr == 0xA4)
|
||||
{
|
||||
if (latch_x_y) { ret = A4_latch; }
|
||||
else { ret = (byte)LY_ret; }
|
||||
else { ret = (byte)((LY_ret >= 0) ? LY_ret : 0); }
|
||||
}
|
||||
else if (addr == 0xA5)
|
||||
{
|
||||
|
@ -132,15 +122,15 @@ namespace BizHawk.Emulation.Cores.Consoles.O2Hawk
|
|||
}
|
||||
else if ((addr >= 0xC0) && (addr <= 0xC8))
|
||||
{
|
||||
ret = Grid_H[(addr - 0xC0) * SHT_SZ];
|
||||
ret = Grid_H[addr - 0xC0];
|
||||
}
|
||||
else if ((addr >= 0xD0) && (addr <= 0xD8))
|
||||
{
|
||||
ret = Grid_H[(addr - 0xD0 + 9) * SHT_SZ];
|
||||
ret = Grid_H[addr - 0xD0 + 9];
|
||||
}
|
||||
else if ((addr >= 0xE0) && (addr <= 0xE9))
|
||||
{
|
||||
ret = Grid_V[(addr - 0xE0) * SHT_SZ];
|
||||
ret = Grid_V[addr - 0xE0];
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -191,7 +181,7 @@ namespace BizHawk.Emulation.Cores.Consoles.O2Hawk
|
|||
{
|
||||
VDC_status &= 0xFD;
|
||||
latch_x_y = true;
|
||||
A4_latch = (byte)LY_ret;
|
||||
A4_latch = (byte)((LY_ret >= 0) ? LY_ret : 0);
|
||||
A5_latch = (byte)(cycle);
|
||||
}
|
||||
|
||||
|
@ -201,7 +191,6 @@ namespace BizHawk.Emulation.Cores.Consoles.O2Hawk
|
|||
}
|
||||
|
||||
VDC_ctrl = value;
|
||||
VDC_ctrl_latch[SHT_SZ - 1] = value;
|
||||
|
||||
if (VDC_ctrl.Bit(2)) { Console.WriteLine("sound INT"); }
|
||||
if (VDC_ctrl.Bit(0)) { Console.WriteLine("HBL INT"); }
|
||||
|
@ -221,8 +210,6 @@ namespace BizHawk.Emulation.Cores.Consoles.O2Hawk
|
|||
//Console.WriteLine("VDC_color: " + value + " " + LY + " " + Core.cpu.TotalExecutedCycles);
|
||||
grid_brightness = (!lum_en | VDC_color.Bit(6)) ? 8 : 0;
|
||||
bg_brightness = !lum_en ? 8 : 0;
|
||||
VDC_color_latch[SHT_SZ - 1] = value;
|
||||
grid_brightness_latch[SHT_SZ - 1] = grid_brightness;
|
||||
}
|
||||
else if (addr == 0xA4)
|
||||
{
|
||||
|
@ -238,15 +225,15 @@ namespace BizHawk.Emulation.Cores.Consoles.O2Hawk
|
|||
}
|
||||
else if ((addr >= 0xC0) && (addr <= 0xC8))
|
||||
{
|
||||
if (!VDC_ctrl.Bit(3)) { Grid_H[(addr - 0xC0) * SHT_SZ + SHT_SZ - 1] = value; } else { Console.WriteLine("blocked"); }
|
||||
if (!VDC_ctrl.Bit(3)) { Grid_H[addr - 0xC0] = value; } else { Console.WriteLine("blocked"); }
|
||||
}
|
||||
else if ((addr >= 0xD0) && (addr <= 0xD8))
|
||||
{
|
||||
if (!VDC_ctrl.Bit(3)) { Grid_H[(addr - 0xD0 + 9) * SHT_SZ + SHT_SZ - 1] = value; } else { Console.WriteLine("blocked"); }
|
||||
if (!VDC_ctrl.Bit(3)) { Grid_H[addr - 0xD0 + 9] = value; } else { Console.WriteLine("blocked"); }
|
||||
}
|
||||
else if ((addr >= 0xE0) && (addr <= 0xE9))
|
||||
{
|
||||
if (!VDC_ctrl.Bit(3)) { Grid_V[(addr - 0xE0) * SHT_SZ + SHT_SZ - 1] = value; } else { Console.WriteLine("blocked"); }
|
||||
if (!VDC_ctrl.Bit(3)) { Grid_V[addr - 0xE0] = value; } else { Console.WriteLine("blocked"); }
|
||||
}
|
||||
//Console.WriteLine(addr + " " + value + " " + LY + " " + Core.cpu.TotalExecutedCycles);
|
||||
}
|
||||
|
@ -268,8 +255,8 @@ namespace BizHawk.Emulation.Cores.Consoles.O2Hawk
|
|||
|
||||
if (grid_fill > 0)
|
||||
{
|
||||
Core._vidbuffer[LY * 372 + current_pixel_offset] = (int)Color_Palette_BG[(VDC_color_latch[0] & 0x7) + grid_brightness_latch[0]];
|
||||
Core._vidbuffer[LY * 372 + current_pixel_offset + 1] = (int)Color_Palette_BG[(VDC_color_latch[0] & 0x7) + grid_brightness_latch[0]];
|
||||
Core._vidbuffer[LY * 372 + current_pixel_offset] = (int)Color_Palette_BG[(VDC_color & 0x7) + grid_brightness];
|
||||
Core._vidbuffer[LY * 372 + current_pixel_offset + 1] = (int)Color_Palette_BG[(VDC_color & 0x7) + grid_brightness];
|
||||
Pixel_Stat |= grid_fill_col;
|
||||
grid_fill--;
|
||||
}
|
||||
|
@ -280,12 +267,12 @@ namespace BizHawk.Emulation.Cores.Consoles.O2Hawk
|
|||
int j = (int)Math.Floor((LY - GRID_OFST) / 24.0);
|
||||
if ((k < 10) && (j < 8))
|
||||
{
|
||||
if (Grid_V[k * SHT_SZ].Bit(j))
|
||||
if (Grid_V[k].Bit(j))
|
||||
{
|
||||
Core._vidbuffer[LY * 372 + current_pixel_offset] = (int)Color_Palette_BG[(VDC_color_latch[0] & 0x7) + grid_brightness_latch[0]];
|
||||
Core._vidbuffer[LY * 372 + current_pixel_offset + 1] = (int)Color_Palette_BG[(VDC_color_latch[0] & 0x7) + grid_brightness_latch[0]];
|
||||
Core._vidbuffer[LY * 372 + current_pixel_offset] = (int)Color_Palette_BG[(VDC_color & 0x7) + grid_brightness];
|
||||
Core._vidbuffer[LY * 372 + current_pixel_offset + 1] = (int)Color_Palette_BG[(VDC_color & 0x7) + grid_brightness];
|
||||
Pixel_Stat |= 0x10;
|
||||
if (VDC_ctrl_latch[0].Bit(7)) { grid_fill = 15; }
|
||||
if (VDC_ctrl.Bit(7)) { grid_fill = 15; }
|
||||
else { grid_fill = 1; }
|
||||
grid_fill_col = 0x10;
|
||||
}
|
||||
|
@ -301,10 +288,10 @@ namespace BizHawk.Emulation.Cores.Consoles.O2Hawk
|
|||
{
|
||||
if (j == 8)
|
||||
{
|
||||
if (Grid_H[(k + 9) * SHT_SZ].Bit(0))
|
||||
if (Grid_H[k + 9].Bit(0))
|
||||
{
|
||||
Core._vidbuffer[LY * 372 + current_pixel_offset] = (int)Color_Palette_BG[(VDC_color_latch[0] & 0x7) + grid_brightness_latch[0]];
|
||||
Core._vidbuffer[LY * 372 + current_pixel_offset + 1] = (int)Color_Palette_BG[(VDC_color_latch[0] & 0x7) + grid_brightness_latch[0]];
|
||||
Core._vidbuffer[LY * 372 + current_pixel_offset] = (int)Color_Palette_BG[(VDC_color & 0x7) + grid_brightness];
|
||||
Core._vidbuffer[LY * 372 + current_pixel_offset + 1] = (int)Color_Palette_BG[(VDC_color & 0x7) + grid_brightness];
|
||||
Pixel_Stat |= 0x20;
|
||||
|
||||
if (((cycle - 8) % 16) == 15) { grid_fill = 2; grid_fill_col = 0x20; }
|
||||
|
@ -312,10 +299,10 @@ namespace BizHawk.Emulation.Cores.Consoles.O2Hawk
|
|||
}
|
||||
else
|
||||
{
|
||||
if (Grid_H[k * SHT_SZ].Bit(j))
|
||||
if (Grid_H[k].Bit(j))
|
||||
{
|
||||
Core._vidbuffer[LY * 372 + current_pixel_offset] = (int)Color_Palette_BG[(VDC_color_latch[0] & 0x7) + grid_brightness_latch[0]];
|
||||
Core._vidbuffer[LY * 372 + current_pixel_offset+ 1] = (int)Color_Palette_BG[(VDC_color_latch[0] & 0x7) + grid_brightness_latch[0]];
|
||||
Core._vidbuffer[LY * 372 + current_pixel_offset] = (int)Color_Palette_BG[(VDC_color & 0x7) + grid_brightness];
|
||||
Core._vidbuffer[LY * 372 + current_pixel_offset+ 1] = (int)Color_Palette_BG[(VDC_color & 0x7) + grid_brightness];
|
||||
Pixel_Stat |= 0x20;
|
||||
if (((cycle - 8) % 16) == 15) { grid_fill = 2; grid_fill_col = 0x20; }
|
||||
}
|
||||
|
@ -324,7 +311,7 @@ namespace BizHawk.Emulation.Cores.Consoles.O2Hawk
|
|||
}
|
||||
|
||||
// grid
|
||||
if (VDC_ctrl_latch[0].Bit(6) && ((LY - GRID_OFST) >= 0) && (((LY - GRID_OFST) % GRID_OFST) < 3) && VDC_ctrl.Bit(3))
|
||||
if (VDC_ctrl.Bit(6) && ((LY - GRID_OFST) >= 0) && (((LY - GRID_OFST) % GRID_OFST) < 3) && VDC_ctrl.Bit(3))
|
||||
{
|
||||
|
||||
if (((cycle % 16) == 8) || ((cycle % 16) == 9))
|
||||
|
@ -333,8 +320,8 @@ namespace BizHawk.Emulation.Cores.Consoles.O2Hawk
|
|||
int j = (int)Math.Floor((LY - GRID_OFST) / 24.0);
|
||||
if ((k < 10) && (j < 9))
|
||||
{
|
||||
Core._vidbuffer[LY * 372 + current_pixel_offset] = (int)Color_Palette_BG[(VDC_color_latch[0] & 0x7) + grid_brightness_latch[0]];
|
||||
Core._vidbuffer[LY * 372 + current_pixel_offset + 1] = (int)Color_Palette_BG[(VDC_color_latch[0] & 0x7) + grid_brightness_latch[0]];
|
||||
Core._vidbuffer[LY * 372 + current_pixel_offset] = (int)Color_Palette_BG[(VDC_color & 0x7) + grid_brightness];
|
||||
Core._vidbuffer[LY * 372 + current_pixel_offset + 1] = (int)Color_Palette_BG[(VDC_color & 0x7) + grid_brightness];
|
||||
Pixel_Stat |= 0x20;
|
||||
}
|
||||
}
|
||||
|
@ -740,7 +727,7 @@ namespace BizHawk.Emulation.Cores.Consoles.O2Hawk
|
|||
}
|
||||
else
|
||||
{
|
||||
if (cycle == 182 && (LY < LINE_VBL) && (LY >= 0))
|
||||
if (cycle == 182 && (LY < LINE_VBL))
|
||||
{
|
||||
HBL = true;
|
||||
// Send T1 pulses
|
||||
|
@ -755,33 +742,6 @@ namespace BizHawk.Emulation.Cores.Consoles.O2Hawk
|
|||
}
|
||||
}
|
||||
|
||||
if (cycle == 12)
|
||||
{
|
||||
// the grid uses values from 5 lines in the past, so cycle them here
|
||||
for (int j = 0; j < (SHT_SZ - 1); j++)
|
||||
{
|
||||
VDC_ctrl_latch[j] = VDC_ctrl_latch[j + 1];
|
||||
VDC_color_latch[j] = VDC_color_latch[j + 1];
|
||||
grid_brightness_latch[j] = grid_brightness_latch[j + 1];
|
||||
}
|
||||
|
||||
for (int i = 0; i < 18; i++)
|
||||
{
|
||||
for (int j = 0; j < (SHT_SZ - 1); j++)
|
||||
{
|
||||
Grid_H[i * SHT_SZ + j] = Grid_H[i * SHT_SZ + j + 1];
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
for (int j = 0; j < (SHT_SZ - 1); j++)
|
||||
{
|
||||
Grid_V[i * SHT_SZ + j] = Grid_V[i * SHT_SZ + j + 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cycle == 113 && (LY < LINE_VBL))
|
||||
{
|
||||
VDC_status |= 0x01;
|
||||
|
@ -811,23 +771,18 @@ namespace BizHawk.Emulation.Cores.Consoles.O2Hawk
|
|||
LY_ret = 0;
|
||||
}
|
||||
|
||||
if (LY == (LINE_MAX - 6))
|
||||
{
|
||||
LY = -6;
|
||||
LY_ret = 0;
|
||||
}
|
||||
|
||||
if (LY == 0)
|
||||
if (LY == LINE_MAX)
|
||||
{
|
||||
LY = 0;
|
||||
VBL = false;
|
||||
Core.in_vblank = false;
|
||||
Core.cpu.T1 = false;
|
||||
if (Core.is_pal) { Core.cpu.IRQPending = false; }
|
||||
VDC_status &= 0xF7;
|
||||
for (int i = 0; i < 8; i++) { VDC_col_ret[i] = 0; }
|
||||
LY_ret = 0;
|
||||
}
|
||||
|
||||
if (LY < LINE_VBL && (LY >= 0))
|
||||
if (LY < LINE_VBL)
|
||||
{
|
||||
HBL = false;
|
||||
Core.cpu.T1 = false;
|
||||
|
@ -843,14 +798,14 @@ namespace BizHawk.Emulation.Cores.Consoles.O2Hawk
|
|||
Sprite_Shapes = new byte[32];
|
||||
Foreground = new byte[48];
|
||||
Quad_Chars = new byte[64];
|
||||
Grid_H = new byte[18 * SHT_SZ];
|
||||
Grid_V = new byte[10 * SHT_SZ];
|
||||
Grid_H = new byte[18];
|
||||
Grid_V = new byte[10];
|
||||
|
||||
VDC_ctrl = VDC_status = VDC_collision = VDC_color = grid_fill_col = 0;
|
||||
Pixel_Stat = A4_latch = A5_latch = 0;
|
||||
bg_brightness = grid_brightness = grid_fill = LY_ret = cycle = 0;
|
||||
VBL = HBL = lum_en = false;
|
||||
LY = -6;
|
||||
LY = 0;
|
||||
|
||||
AudioReset();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue