GBHawk: Window and sprite timing work

This commit is contained in:
alyosha-tas 2020-10-12 18:14:36 -04:00
parent 2991b69363
commit 5a96022f28
3 changed files with 83 additions and 88 deletions

View File

@ -831,8 +831,26 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
window_tile_inc = 0;
window_started = true;
window_is_reset = false;
// don't evaluate sprites until pre-render for window is over
pre_render_2 = true;
}
// hardware tests show that window takes effect before sprites when actiavted on the same pixel
if (!no_sprites && !pre_render_2 && (pixel_counter < 160))
{
for (int i = 0; i < SL_sprites_index; i++)
{
if ((pixel_counter >= (SL_sprites[i * 4 + 1] - 8)) &&
(pixel_counter < (SL_sprites[i * 4 + 1])) &&
!evaled_sprites.Bit(i))
{
going_to_fetch = true;
fetch_sprite = true;
}
}
}
if (!pre_render && !fetch_sprite)
{
// start shifting data into the LCD
@ -969,27 +987,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
if (!fetch_sprite)
{
if (!pre_render_2)
{
// before we go on to read case 3, we need to know if we stall there or not
// Gekkio's tests show that if sprites are at position 0 or 1 (mod 8)
// then it takes an extra cycle (1 or 2 more t-states) to process them
if (!no_sprites && (pixel_counter < 160))
{
for (int i = 0; i < SL_sprites_index; i++)
{
if ((pixel_counter >= (SL_sprites[i * 4 + 1] - 8)) &&
(pixel_counter < (SL_sprites[i * 4 + 1])) &&
!evaled_sprites.Bit(i))
{
going_to_fetch = true;
fetch_sprite = true;
}
}
}
}
switch (read_case)
{
case 0: // read a background tile
@ -1048,11 +1045,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
break;
case 2: // read from tile graphics (1)
if ((internal_cycle % 2) == 0)
{
pre_render_2 = false;
}
else
if ((internal_cycle % 2) == 1)
{
y_scroll_offset = (scroll_y + LY) % 8;
@ -1088,6 +1081,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
{
// here we set up rendering
pre_render = false;
pre_render_2 = false;
// window X is latched for the scanline, mid-line changes have no effect
window_x_latch = window_x;
@ -1205,6 +1199,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
// here we set up rendering
// unlike for the normal background case, there is no pre-render period for the window
// so start shifting in data to the screen right away
pre_render_2 = false;
if (window_x_latch <= 7)
{
if (scroll_offset == 0)
@ -1219,7 +1215,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
render_offset = 7 - window_x_latch;
sprite_scroll_offset = 8 - (window_x_latch + 8 - 7) % 8;
sprite_scroll_offset = (8 - (window_x_latch + 8 - 7) % 8) % 8;
}
else
{
@ -1227,7 +1223,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
read_case = 4;
render_counter = 8;
sprite_scroll_offset = 8 - (window_x_latch - 7) % 8;
sprite_scroll_offset = (8 - (window_x_latch - 7) % 8) % 8;
}
latch_counter = 0;
@ -1380,6 +1376,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
}
}
sprite_fetch_counter -= 1;
total_counter += sprite_fetch_counter;
first_fetch = false;

View File

@ -827,8 +827,26 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
window_tile_inc = 0;
window_started = true;
window_is_reset = false;
// don't evaluate sprites until pre-render for window is over
pre_render_2 = true;
}
// hardware tests show that window takes effect before sprites when actiavted on the same pixel
if (!no_sprites && !pre_render_2 && (pixel_counter < 160))
{
for (int i = 0; i < SL_sprites_index; i++)
{
if ((pixel_counter >= (SL_sprites[i * 4 + 1] - 8)) &&
(pixel_counter < (SL_sprites[i * 4 + 1])) &&
!evaled_sprites.Bit(i))
{
going_to_fetch = true;
fetch_sprite = true;
}
}
}
if (!pre_render && !fetch_sprite)
{
// start shifting data into the LCD
@ -924,28 +942,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
}
if (!fetch_sprite)
{
if (!pre_render_2)
{
// before we go on to read case 3, we need to know if we stall there or not
// Gekkio's tests show that if sprites are at position 0 or 1 (mod 8)
// then it takes an extra cycle (1 or 2 more t-states) to process them
if (!no_sprites && (pixel_counter < 160))
{
for (int i = 0; i < SL_sprites_index; i++)
{
if ((pixel_counter >= (SL_sprites[i * 4 + 1] - 8)) &&
(pixel_counter < (SL_sprites[i * 4 + 1])) &&
!evaled_sprites.Bit(i))
{
going_to_fetch = true;
fetch_sprite = true;
}
}
}
}
{
switch (read_case)
{
case 0: // read a background tile
@ -1005,11 +1002,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
break;
case 2: // read from tile graphics (1)
if ((internal_cycle % 2) == 0)
{
pre_render_2 = false;
}
else
if ((internal_cycle % 2) == 1)
{
y_scroll_offset = (scroll_y + LY) % 8;
@ -1045,6 +1038,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
{
// here we set up rendering
pre_render = false;
pre_render_2 = false;
// window X is latched for the scanline, mid-line changes have no effect
window_x_latch = window_x;
@ -1162,6 +1156,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
// here we set up rendering
// unlike for the normal background case, there is no pre-render period for the window
// so start shifting in data to the screen right away
pre_render_2 = false;
if (window_x_latch <= 7)
{
if (scroll_offset == 0)
@ -1176,7 +1172,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
render_offset = 7 - window_x_latch;
sprite_scroll_offset = 8 - (window_x_latch + 8 - 7) % 8;
sprite_scroll_offset = (8 - (window_x_latch + 8 - 7) % 8) % 8;
}
else
{
@ -1184,7 +1180,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
read_case = 4;
render_counter = 8;
sprite_scroll_offset = 8 - (window_x_latch - 7) % 8;
sprite_scroll_offset = (8 - (window_x_latch - 7) % 8) % 8;
}
latch_counter = 0;
@ -1348,6 +1344,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
}
}
sprite_fetch_counter -= 1;
total_counter += sprite_fetch_counter;
first_fetch = false;

View File

@ -514,8 +514,27 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
window_tile_inc = 0;
window_started = true;
window_is_reset = false;
// don't evaluate sprites until pre-render for window is over
pre_render_2 = true;
}
if (!no_sprites && !pre_render_2 && (pixel_counter < 160) && LCDC.Bit(1))
{
// hardware tests show that window takes effect before sprites when actiavted on the same pixel
// Also, on DMG only, this process only runs if sprites are on in the LCDC (on GBC it always runs)
for (int i = 0; i < SL_sprites_index; i++)
{
if ((pixel_counter >= (SL_sprites[i * 4 + 1] - 8)) &&
(pixel_counter < (SL_sprites[i * 4 + 1])) &&
!evaled_sprites.Bit(i))
{
going_to_fetch = true;
fetch_sprite = true;
}
}
}
if (!pre_render && !fetch_sprite)
{
// start shifting data into the LCD
@ -601,27 +620,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
if (!fetch_sprite)
{
if (!pre_render_2)
{
// before we go on to read case 3, we need to know if we stall there or not
// Gekkio's tests show that if sprites are at position 0 or 1 (mod 8)
// then it takes an extra cycle (1 or 2 more t-states) to process them
// Also, on DMG only, this process only runs if sprites are on in the LCDC (on GBC it always runs)
if (!no_sprites && (pixel_counter < 160) && LCDC.Bit(1))
{
for (int i = 0; i < SL_sprites_index; i++)
{
if ((pixel_counter >= (SL_sprites[i * 4 + 1] - 8)) &&
(pixel_counter < (SL_sprites[i * 4 + 1])) &&
!evaled_sprites.Bit(i))
{
going_to_fetch = true;
fetch_sprite = true;
}
}
}
}
switch (read_case)
{
case 0: // read a background tile
@ -672,11 +670,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
break;
case 2: // read from tile graphics (1)
if ((internal_cycle % 2) == 0)
{
pre_render_2 = false;
}
else
if ((internal_cycle % 2) == 1)
{
y_scroll_offset = (scroll_y + LY) % 8;
@ -707,6 +701,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
{
// here we set up rendering
pre_render = false;
pre_render_2 = false;
// window X is latched for the scanline, mid-line changes have no effect
window_x_latch = window_x;
@ -809,6 +804,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
// here we set up rendering
// unlike for the normal background case, there is no pre-render period for the window
// so start shifting in data to the screen right away
pre_render_2 = false;
if (window_x_latch <= 7)
{
if (scroll_offset == 0)
@ -823,7 +820,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
render_offset = 7 - window_x_latch;
sprite_scroll_offset = 8 - (window_x_latch + 8 - 7) % 8;
sprite_scroll_offset = (8 - (window_x_latch + 8 - 7) % 8) % 8;
}
else
{
@ -831,7 +828,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
read_case = 4;
render_counter = 8;
sprite_scroll_offset = 8 - (window_x_latch - 7) % 8;
sprite_scroll_offset = (8 - (window_x_latch - 7) % 8) % 8;
}
latch_counter = 0;
@ -976,6 +973,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
}
}
sprite_fetch_counter -= 1;
total_counter += sprite_fetch_counter;
first_fetch = false;