GBHawk: Sprite Evaluation work
This commit is contained in:
parent
5d3ca7bc47
commit
5bf7b060af
|
@ -59,6 +59,13 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
||||||
public int tile_byte;
|
public int tile_byte;
|
||||||
public int sprite_fetch_cycles;
|
public int sprite_fetch_cycles;
|
||||||
public bool fetch_sprite;
|
public bool fetch_sprite;
|
||||||
|
public bool fetch_sprite_01;
|
||||||
|
public bool going_to_fetch;
|
||||||
|
public int sprite_fetch_counter;
|
||||||
|
public bool glitchy_eval;
|
||||||
|
public byte[] sprite_attr_list = new byte[160];
|
||||||
|
public byte[] sprite_pixel_list = new byte[160];
|
||||||
|
public byte[] sprite_present_list = new byte[160];
|
||||||
public int temp_fetch;
|
public int temp_fetch;
|
||||||
public int tile_inc;
|
public int tile_inc;
|
||||||
public bool pre_render;
|
public bool pre_render;
|
||||||
|
@ -74,11 +81,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
||||||
public byte[] sprite_sel = new byte[2];
|
public byte[] sprite_sel = new byte[2];
|
||||||
public int sl_use_index;
|
public int sl_use_index;
|
||||||
public bool no_sprites;
|
public bool no_sprites;
|
||||||
public int sprite_fetch_index;
|
|
||||||
public int[] SL_sprites_ordered = new int[40]; // (x_end, data_low, data_high, attr)
|
public int[] SL_sprites_ordered = new int[40]; // (x_end, data_low, data_high, attr)
|
||||||
public int index_used;
|
public int evaled_sprites;
|
||||||
public int sprite_ordered_index;
|
public int sprite_ordered_index;
|
||||||
public int bottom_index;
|
|
||||||
public bool blank_frame;
|
public bool blank_frame;
|
||||||
|
|
||||||
// windowing state
|
// windowing state
|
||||||
|
@ -582,11 +587,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
||||||
tile_inc = 0;
|
tile_inc = 0;
|
||||||
pixel_counter = 0;
|
pixel_counter = 0;
|
||||||
sl_use_index = 0;
|
sl_use_index = 0;
|
||||||
index_used = 0;
|
|
||||||
bottom_index = 0;
|
|
||||||
sprite_ordered_index = 0;
|
|
||||||
fetch_sprite = false;
|
fetch_sprite = false;
|
||||||
|
fetch_sprite_01 = false;
|
||||||
|
going_to_fetch = false;
|
||||||
no_sprites = false;
|
no_sprites = false;
|
||||||
|
glitchy_eval = false;
|
||||||
|
evaled_sprites = 0;
|
||||||
|
|
||||||
window_pre_render = false;
|
window_pre_render = false;
|
||||||
if (window_started && LCDC.Bit(5))
|
if (window_started && LCDC.Bit(5))
|
||||||
|
@ -601,12 +607,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
||||||
}
|
}
|
||||||
window_started = false;
|
window_started = false;
|
||||||
|
|
||||||
if (SL_sprites_index == 0)
|
if (SL_sprites_index == 0) { no_sprites = true; }
|
||||||
{
|
// it is much easier to process sprites if we order them according to the rules of sprite priority first
|
||||||
no_sprites = true;
|
if (!no_sprites) { reorder_and_assemble_sprites(); }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// before anything else, we have to check if windowing is in effect
|
// before anything else, we have to check if windowing is in effect
|
||||||
if (LCDC.Bit(5) && !window_started && (LY >= window_y) && (pixel_counter >= (window_x_latch - 7)) && (window_x_latch < 167))
|
if (LCDC.Bit(5) && !window_started && (LY >= window_y) && (pixel_counter >= (window_x_latch - 7)) && (window_x_latch < 167))
|
||||||
{
|
{
|
||||||
|
@ -643,132 +649,109 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
||||||
|
|
||||||
if (!pre_render && !fetch_sprite && !window_pre_render)
|
if (!pre_render && !fetch_sprite && !window_pre_render)
|
||||||
{
|
{
|
||||||
// start by fetching all the sprites that need to be fetched
|
// start shifting data into the LCD
|
||||||
if (!no_sprites)
|
if (render_counter >= (render_offset + 8))
|
||||||
{
|
{
|
||||||
for (int i = 0; i < SL_sprites_index; i++)
|
pixel = tile_data_latch[0].Bit(7 - (render_counter % 8)) ? 1 : 0;
|
||||||
|
pixel |= tile_data_latch[1].Bit(7 - (render_counter % 8)) ? 2 : 0;
|
||||||
|
|
||||||
|
int ref_pixel = pixel;
|
||||||
|
if (LCDC.Bit(0))
|
||||||
{
|
{
|
||||||
if ((pixel_counter >= (SL_sprites[i * 4 + 1] - 8)) &&
|
pixel = (BGP >> (pixel * 2)) & 3;
|
||||||
(pixel_counter < SL_sprites[i * 4 + 1]) &&
|
|
||||||
!index_used.Bit(i))
|
|
||||||
{
|
|
||||||
fetch_sprite = true;
|
|
||||||
sprite_fetch_index = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
|
|
||||||
if (!fetch_sprite)
|
|
||||||
{
|
|
||||||
// start shifting data into the LCD
|
|
||||||
if (render_counter >= (render_offset + 8))
|
|
||||||
{
|
{
|
||||||
pixel = tile_data_latch[0].Bit(7 - (render_counter % 8)) ? 1 : 0;
|
pixel = 0;
|
||||||
pixel |= tile_data_latch[1].Bit(7 - (render_counter % 8)) ? 2 : 0;
|
}
|
||||||
|
|
||||||
int ref_pixel = pixel;
|
|
||||||
if (LCDC.Bit(0))
|
|
||||||
{
|
|
||||||
pixel = (BGP >> (pixel * 2)) & 3;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pixel = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// now we have the BG pixel, we next need the sprite pixel
|
||||||
|
if (!no_sprites)
|
||||||
|
{
|
||||||
|
bool have_sprite = false;
|
||||||
|
int s_pixel = 0;
|
||||||
|
int sprite_attr = 0;
|
||||||
|
|
||||||
// now we have the BG pixel, we next need the sprite pixel
|
if (sprite_present_list[pixel_counter] == 1)
|
||||||
if (!no_sprites)
|
|
||||||
{
|
{
|
||||||
bool have_sprite = false;
|
have_sprite = true;
|
||||||
int i = bottom_index;
|
s_pixel = sprite_pixel_list[pixel_counter];
|
||||||
int s_pixel = 0;
|
sprite_attr = sprite_attr_list[pixel_counter];
|
||||||
int sprite_attr = 0;
|
|
||||||
|
|
||||||
while (i < sprite_ordered_index)
|
|
||||||
{
|
|
||||||
if (SL_sprites_ordered[i * 4] == pixel_counter)
|
|
||||||
{
|
|
||||||
bottom_index++;
|
|
||||||
if (bottom_index == SL_sprites_index) { no_sprites = true; }
|
|
||||||
}
|
|
||||||
else if (!have_sprite)
|
|
||||||
{
|
|
||||||
// we can use the current sprite, so pick out a pixel for it
|
|
||||||
int t_index = pixel_counter - (SL_sprites_ordered[i * 4] - 8);
|
|
||||||
|
|
||||||
t_index = 7 - t_index;
|
|
||||||
|
|
||||||
sprite_data[0] = (byte)((SL_sprites_ordered[i * 4 + 1] >> t_index) & 1);
|
|
||||||
sprite_data[1] = (byte)(((SL_sprites_ordered[i * 4 + 2] >> t_index) & 1) << 1);
|
|
||||||
|
|
||||||
s_pixel = sprite_data[0] + sprite_data[1];
|
|
||||||
sprite_attr = SL_sprites_ordered[i * 4 + 3];
|
|
||||||
|
|
||||||
// pixel color of 0 is transparent, so if this is the case we dont have a pixel
|
|
||||||
if (s_pixel != 0)
|
|
||||||
{
|
|
||||||
have_sprite = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (have_sprite)
|
|
||||||
{
|
|
||||||
bool use_sprite = false;
|
|
||||||
if (LCDC.Bit(1))
|
|
||||||
{
|
|
||||||
if (!sprite_attr.Bit(7))
|
|
||||||
{
|
|
||||||
use_sprite = true;
|
|
||||||
}
|
|
||||||
else if (ref_pixel == 0)
|
|
||||||
{
|
|
||||||
use_sprite = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!LCDC.Bit(0))
|
|
||||||
{
|
|
||||||
use_sprite = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (use_sprite)
|
|
||||||
{
|
|
||||||
if (sprite_attr.Bit(4))
|
|
||||||
{
|
|
||||||
pixel = (obj_pal_1 >> (s_pixel * 2)) & 3;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pixel = (obj_pal_0 >> (s_pixel * 2)) & 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// based on sprite priority and pixel values, pick a final pixel color
|
if (have_sprite)
|
||||||
Core._vidbuffer[LY * 160 + pixel_counter] = (int)Core.color_palette[pixel];
|
|
||||||
pixel_counter++;
|
|
||||||
|
|
||||||
if (pixel_counter == 160)
|
|
||||||
{
|
{
|
||||||
read_case = 8;
|
bool use_sprite = false;
|
||||||
hbl_countdown = 6;
|
if (LCDC.Bit(1))
|
||||||
|
{
|
||||||
|
if (!sprite_attr.Bit(7))
|
||||||
|
{
|
||||||
|
use_sprite = true;
|
||||||
|
}
|
||||||
|
else if (ref_pixel == 0)
|
||||||
|
{
|
||||||
|
use_sprite = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!LCDC.Bit(0))
|
||||||
|
{
|
||||||
|
use_sprite = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (use_sprite)
|
||||||
|
{
|
||||||
|
if (sprite_attr.Bit(4))
|
||||||
|
{
|
||||||
|
pixel = (obj_pal_1 >> (s_pixel * 2)) & 3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pixel = (obj_pal_0 >> (s_pixel * 2)) & 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
render_counter++;
|
|
||||||
|
// based on sprite priority and pixel values, pick a final pixel color
|
||||||
|
Core._vidbuffer[LY * 160 + pixel_counter] = (int)Core.color_palette[pixel];
|
||||||
|
pixel_counter++;
|
||||||
|
|
||||||
|
if (pixel_counter == 160)
|
||||||
|
{
|
||||||
|
read_case = 8;
|
||||||
|
hbl_countdown = 7;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
render_counter++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fetch_sprite)
|
if (!fetch_sprite)
|
||||||
{
|
{
|
||||||
if (latch_new_data)
|
if (!pre_render)
|
||||||
{
|
{
|
||||||
latch_new_data = false;
|
// before we go on to read case 3, we need to know if we stall there or not
|
||||||
tile_data_latch[0] = tile_data[0];
|
// Gekkio's tests show that if sprites are at position 0 or 1 (mod 8)
|
||||||
tile_data_latch[1] = tile_data[1];
|
// 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;
|
||||||
|
|
||||||
|
if ((SL_sprites[i * 4 + 1] % 8) < 2)
|
||||||
|
{
|
||||||
|
fetch_sprite_01 = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (read_case)
|
switch (read_case)
|
||||||
|
@ -856,15 +839,33 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
||||||
// here we set up rendering
|
// here we set up rendering
|
||||||
pre_render = false;
|
pre_render = false;
|
||||||
render_offset = scroll_x % 8;
|
render_offset = scroll_x % 8;
|
||||||
render_counter = -1;
|
render_counter = 0; // -1;
|
||||||
latch_counter = 0;
|
latch_counter = 0;
|
||||||
read_case = 0;
|
read_case = 0;
|
||||||
|
|
||||||
|
// here we also do a glitchy sprite evaluation for sprites with x=0
|
||||||
|
if (!no_sprites)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < SL_sprites_index; i++)
|
||||||
|
{
|
||||||
|
if (SL_sprites[i * 4 + 1] == 0)
|
||||||
|
{
|
||||||
|
going_to_fetch = true;
|
||||||
|
fetch_sprite = true;
|
||||||
|
glitchy_eval = true;
|
||||||
|
|
||||||
|
if ((SL_sprites[i * 4 + 1] % 8) < 2)
|
||||||
|
{
|
||||||
|
fetch_sprite_01 = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
read_case = 3;
|
read_case = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -959,13 +960,14 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
||||||
// here we set up rendering
|
// here we set up rendering
|
||||||
window_pre_render = false;
|
window_pre_render = false;
|
||||||
render_offset = 0;
|
render_offset = 0;
|
||||||
render_counter = -1;
|
render_counter = 0; // -1;
|
||||||
latch_counter = 0;
|
latch_counter = 0;
|
||||||
read_case = 4;
|
read_case = 4;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
read_case = 7;
|
read_case = 7;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
window_counter++;
|
window_counter++;
|
||||||
|
@ -1009,54 +1011,69 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
internal_cycle++;
|
internal_cycle++;
|
||||||
|
|
||||||
|
if (latch_new_data)
|
||||||
|
{
|
||||||
|
latch_new_data = false;
|
||||||
|
tile_data_latch[0] = tile_data[0];
|
||||||
|
tile_data_latch[1] = tile_data[1];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// every in range sprite takes 6 cycles to process
|
||||||
|
// sprites located at x=0 still take 6 cycles to process even though they don't appear on screen
|
||||||
|
// sprites above x=168 do not take any cycles to process however
|
||||||
if (fetch_sprite)
|
if (fetch_sprite)
|
||||||
{
|
{
|
||||||
if (sprite_fetch_index < SL_sprites_index)
|
if (going_to_fetch)
|
||||||
{
|
{
|
||||||
if (pixel_counter != 0) {
|
going_to_fetch = false;
|
||||||
if ((pixel_counter == (SL_sprites[sprite_fetch_index * 4 + 1] - 8)) &&
|
sprite_fetch_counter = 0;
|
||||||
//(pixel_counter < SL_sprites[sprite_fetch_index * 4 + 1]) &&
|
|
||||||
!index_used.Bit(sprite_fetch_index))
|
if (fetch_sprite_01)
|
||||||
{
|
|
||||||
sl_use_index = sprite_fetch_index;
|
|
||||||
process_sprite();
|
|
||||||
SL_sprites_ordered[sprite_ordered_index * 4] = SL_sprites[sprite_fetch_index * 4 + 1];
|
|
||||||
SL_sprites_ordered[sprite_ordered_index * 4 + 1] = sprite_sel[0];
|
|
||||||
SL_sprites_ordered[sprite_ordered_index * 4 + 2] = sprite_sel[1];
|
|
||||||
SL_sprites_ordered[sprite_ordered_index * 4 + 3] = SL_sprites[sprite_fetch_index * 4 + 3];
|
|
||||||
sprite_ordered_index++;
|
|
||||||
index_used |= (1 << sl_use_index);
|
|
||||||
}
|
|
||||||
sprite_fetch_index++;
|
|
||||||
if (sprite_fetch_index == SL_sprites_index) { fetch_sprite = false; }
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
// whan pixel counter is 0, we want to scan all the points before 0 as well
|
sprite_fetch_counter += 2;
|
||||||
// certainly non-physical but good enough for now
|
fetch_sprite_01 = false;
|
||||||
for (int j = -7; j < 1; j++)
|
}
|
||||||
|
|
||||||
|
// at this time it is unknown what each cycle does, but we only need to accurately keep track of cycles
|
||||||
|
for (int i = 0; i < SL_sprites_index; i++)
|
||||||
|
{
|
||||||
|
if (glitchy_eval && (SL_sprites[i * 4 + 1] == 0))
|
||||||
{
|
{
|
||||||
for (int i = 0; i < SL_sprites_index; i++)
|
sprite_fetch_counter += 6;
|
||||||
{
|
evaled_sprites |= (1 << i);
|
||||||
if ((j == (SL_sprites[i * 4 + 1] - 8)) &&
|
|
||||||
!index_used.Bit(i))
|
|
||||||
{
|
|
||||||
sl_use_index = i;
|
|
||||||
process_sprite();
|
|
||||||
SL_sprites_ordered[sprite_ordered_index * 4] = SL_sprites[i * 4 + 1];
|
|
||||||
SL_sprites_ordered[sprite_ordered_index * 4 + 1] = sprite_sel[0];
|
|
||||||
SL_sprites_ordered[sprite_ordered_index * 4 + 2] = sprite_sel[1];
|
|
||||||
SL_sprites_ordered[sprite_ordered_index * 4 + 3] = SL_sprites[i * 4 + 3];
|
|
||||||
sprite_ordered_index++;
|
|
||||||
index_used |= (1 << sl_use_index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if ((pixel_counter >= (SL_sprites[i * 4 + 1] - 8)) &&
|
||||||
|
(pixel_counter < (SL_sprites[i * 4 + 1])) &&
|
||||||
|
!evaled_sprites.Bit(i))
|
||||||
|
{
|
||||||
|
sprite_fetch_counter += 6;
|
||||||
|
evaled_sprites |= (1 << i);
|
||||||
|
|
||||||
|
//Console.Write(SL_sprites[i * 4 + 1]);
|
||||||
|
//Console.Write(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we didn't evaluate all the sprites immediately, 2 more cycles are added to restart it
|
||||||
|
if (evaled_sprites != (Math.Pow(2,SL_sprites_index) - 1))
|
||||||
|
{
|
||||||
|
sprite_fetch_counter += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
glitchy_eval = false;
|
||||||
|
//Console.WriteLine(sprite_fetch_counter);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sprite_fetch_counter--;
|
||||||
|
if (sprite_fetch_counter == 0)
|
||||||
|
{
|
||||||
fetch_sprite = false;
|
fetch_sprite = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1081,6 +1098,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
||||||
VRAM_access_read = true;
|
VRAM_access_read = true;
|
||||||
OAM_access_write = true;
|
OAM_access_write = true;
|
||||||
VRAM_access_write = true;
|
VRAM_access_write = true;
|
||||||
|
DMA_OAM_access = true;
|
||||||
|
|
||||||
cycle = 0;
|
cycle = 0;
|
||||||
LYC_INT = false;
|
LYC_INT = false;
|
||||||
|
@ -1156,6 +1174,81 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// order sprites according to x coordinate
|
||||||
|
// note that for sprites of equal x coordinate, priority goes to first on the list
|
||||||
|
public void reorder_and_assemble_sprites()
|
||||||
|
{
|
||||||
|
sprite_ordered_index = 0;
|
||||||
|
/*
|
||||||
|
for (int i = 0; i < SL_sprites_index; i++)
|
||||||
|
{
|
||||||
|
Console.Write(SL_sprites[i * 4 + 1]);
|
||||||
|
Console.Write(" ");
|
||||||
|
}
|
||||||
|
Console.WriteLine(" ");
|
||||||
|
*/
|
||||||
|
for (int i = 0; i < 256; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < SL_sprites_index; j++)
|
||||||
|
{
|
||||||
|
if (SL_sprites[j * 4 + 1] == i)
|
||||||
|
{
|
||||||
|
sl_use_index = j;
|
||||||
|
process_sprite();
|
||||||
|
SL_sprites_ordered[sprite_ordered_index * 4] = SL_sprites[j * 4 + 1];
|
||||||
|
SL_sprites_ordered[sprite_ordered_index * 4 + 1] = sprite_sel[0];
|
||||||
|
SL_sprites_ordered[sprite_ordered_index * 4 + 2] = sprite_sel[1];
|
||||||
|
SL_sprites_ordered[sprite_ordered_index * 4 + 3] = SL_sprites[j * 4 + 3];
|
||||||
|
sprite_ordered_index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool have_pixel = false;
|
||||||
|
byte s_pixel = 0;
|
||||||
|
byte sprite_attr = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < 160; i++)
|
||||||
|
{
|
||||||
|
have_pixel = false;
|
||||||
|
for (int j = 0; j < SL_sprites_index; j++)
|
||||||
|
{
|
||||||
|
if ((i >= (SL_sprites_ordered[j * 4] - 8)) &&
|
||||||
|
(i < SL_sprites_ordered[j * 4]) &&
|
||||||
|
!have_pixel)
|
||||||
|
{
|
||||||
|
// we can use the current sprite, so pick out a pixel for it
|
||||||
|
int t_index = i - (SL_sprites_ordered[j * 4] - 8);
|
||||||
|
|
||||||
|
t_index = 7 - t_index;
|
||||||
|
|
||||||
|
sprite_data[0] = (byte)((SL_sprites_ordered[j * 4 + 1] >> t_index) & 1);
|
||||||
|
sprite_data[1] = (byte)(((SL_sprites_ordered[j * 4 + 2] >> t_index) & 1) << 1);
|
||||||
|
|
||||||
|
s_pixel = (byte)(sprite_data[0] + sprite_data[1]);
|
||||||
|
sprite_attr = (byte)SL_sprites_ordered[j * 4 + 3];
|
||||||
|
|
||||||
|
// pixel color of 0 is transparent, so if this is the case we dont have a pixel
|
||||||
|
if (s_pixel != 0)
|
||||||
|
{
|
||||||
|
have_pixel = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (have_pixel)
|
||||||
|
{
|
||||||
|
sprite_present_list[i] = 1;
|
||||||
|
sprite_pixel_list[i] = s_pixel;
|
||||||
|
sprite_attr_list[i] = sprite_attr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sprite_present_list[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void SyncState(Serializer ser)
|
public void SyncState(Serializer ser)
|
||||||
{
|
{
|
||||||
ser.Sync("LCDC", ref LCDC);
|
ser.Sync("LCDC", ref LCDC);
|
||||||
|
@ -1206,6 +1299,12 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
||||||
ser.Sync("tile_byte", ref tile_byte);
|
ser.Sync("tile_byte", ref tile_byte);
|
||||||
ser.Sync("sprite_fetch_cycles", ref sprite_fetch_cycles);
|
ser.Sync("sprite_fetch_cycles", ref sprite_fetch_cycles);
|
||||||
ser.Sync("fetch_sprite", ref fetch_sprite);
|
ser.Sync("fetch_sprite", ref fetch_sprite);
|
||||||
|
ser.Sync("fetch_sprite_01", ref fetch_sprite_01);
|
||||||
|
ser.Sync("going_to_fetch", ref going_to_fetch);
|
||||||
|
ser.Sync("sprite_fetch_counter", ref sprite_fetch_counter);
|
||||||
|
ser.Sync("sprite_attr_list", ref sprite_attr_list, false);
|
||||||
|
ser.Sync("sprite_pixel_list", ref sprite_pixel_list, false);
|
||||||
|
ser.Sync("sprite_present_list", ref sprite_present_list, false);
|
||||||
ser.Sync("temp_fetch", ref temp_fetch);
|
ser.Sync("temp_fetch", ref temp_fetch);
|
||||||
ser.Sync("tile_inc", ref tile_inc);
|
ser.Sync("tile_inc", ref tile_inc);
|
||||||
ser.Sync("pre_render", ref pre_render);
|
ser.Sync("pre_render", ref pre_render);
|
||||||
|
@ -1221,11 +1320,9 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
|
||||||
ser.Sync("sl_use_index", ref sl_use_index);
|
ser.Sync("sl_use_index", ref sl_use_index);
|
||||||
ser.Sync("sprite_sel", ref sprite_sel, false);
|
ser.Sync("sprite_sel", ref sprite_sel, false);
|
||||||
ser.Sync("no_sprites", ref no_sprites);
|
ser.Sync("no_sprites", ref no_sprites);
|
||||||
ser.Sync("sprite_fetch_index", ref sprite_fetch_index);
|
ser.Sync("evaled_sprites", ref evaled_sprites);
|
||||||
ser.Sync("SL_sprites_ordered", ref SL_sprites_ordered, false);
|
ser.Sync("SL_sprites_ordered", ref SL_sprites_ordered, false);
|
||||||
ser.Sync("index_used", ref index_used);
|
|
||||||
ser.Sync("sprite_ordered_index", ref sprite_ordered_index);
|
ser.Sync("sprite_ordered_index", ref sprite_ordered_index);
|
||||||
ser.Sync("bottom_index", ref bottom_index);
|
|
||||||
ser.Sync("blank_frame", ref blank_frame);
|
ser.Sync("blank_frame", ref blank_frame);
|
||||||
|
|
||||||
ser.Sync("window_counter", ref window_counter);
|
ser.Sync("window_counter", ref window_counter);
|
||||||
|
|
Loading…
Reference in New Issue