Modifying WX and WY outside of VBlank is now more accurate, but still requires more research. Closes #6.

This commit is contained in:
Lior Halphon 2017-05-12 19:33:42 +03:00
parent 00623d4eea
commit 86332d0311
2 changed files with 25 additions and 26 deletions

View File

@ -31,6 +31,16 @@ typedef struct __attribute__((packed)) {
uint8_t flags; uint8_t flags;
} GB_sprite_t; } GB_sprite_t;
static bool window_enabled(GB_gameboy_t *gb)
{
if ((gb->io_registers[GB_IO_LCDC] & 0x1) == 0) {
if (!gb->cgb_mode && gb->is_cgb) {
return false;
}
}
return (gb->io_registers[GB_IO_LCDC] & 0x20) && gb->io_registers[GB_IO_WX] < 167;
}
static uint32_t get_pixel(GB_gameboy_t *gb, uint8_t x, uint8_t y) static uint32_t get_pixel(GB_gameboy_t *gb, uint8_t x, uint8_t y)
{ {
/* /*
@ -56,25 +66,18 @@ static uint32_t get_pixel(GB_gameboy_t *gb, uint8_t x, uint8_t y)
uint8_t lowest_sprite_x = 0xFF; uint8_t lowest_sprite_x = 0xFF;
bool use_obp1 = false, priority = false; bool use_obp1 = false, priority = false;
bool in_window = false; bool in_window = false;
bool window_enabled = (gb->io_registers[GB_IO_LCDC] & 0x20);
bool bg_enabled = true; bool bg_enabled = true;
bool bg_behind = false; bool bg_behind = false;
if ((gb->io_registers[GB_IO_LCDC] & 0x1) == 0) { if ((gb->io_registers[GB_IO_LCDC] & 0x1) == 0) {
if (gb->cgb_mode) { if (gb->cgb_mode) {
bg_behind = true; bg_behind = true;
} }
else if (gb->is_cgb) { /* CGB in DMG mode*/
bg_enabled = window_enabled = false;
}
else { else {
/* DMG */
bg_enabled = false; bg_enabled = false;
} }
} }
if (gb->effective_window_enabled && window_enabled) { /* Window Enabled */ if (window_enabled(gb) && y >= gb->io_registers[GB_IO_WY] && x + 7 >= gb->io_registers[GB_IO_WX] && gb->current_window_line != 0xFF) {
if (y >= gb->effective_window_y && x + 7 >= gb->io_registers[GB_IO_WX]) { in_window = true;
in_window = true;
}
} }
if (sprites_enabled) { if (sprites_enabled) {
@ -125,8 +128,8 @@ static uint32_t get_pixel(GB_gameboy_t *gb, uint8_t x, uint8_t y)
} }
if (in_window) { if (in_window) {
x -= gb->io_registers[GB_IO_WX] - 7; x -= gb->io_registers[GB_IO_WX] - 7; // Todo: This value is probably latched
y -= gb->effective_window_y; y = gb->current_window_line;
} }
else { else {
x += gb->effective_scx; x += gb->effective_scx;
@ -271,8 +274,7 @@ static void update_display_state(GB_gameboy_t *gb, uint8_t cycles)
} }
/* Reset window rendering state */ /* Reset window rendering state */
gb->effective_window_enabled = false; gb->current_window_line = 0xFF;
gb->effective_window_y = 0xFF;
return; return;
} }
@ -302,8 +304,7 @@ static void update_display_state(GB_gameboy_t *gb, uint8_t cycles)
ly_for_comparison = gb->io_registers[GB_IO_LY] = 0; ly_for_comparison = gb->io_registers[GB_IO_LY] = 0;
/* Reset window rendering state */ /* Reset window rendering state */
gb->effective_window_enabled = false; gb->current_window_line = 0xFF;
gb->effective_window_y = 0xFF;
} }
/* Entered VBlank state, update STAT and IF */ /* Entered VBlank state, update STAT and IF */
@ -325,6 +326,9 @@ static void update_display_state(GB_gameboy_t *gb, uint8_t cycles)
if (position_in_line == stat_delay) { if (position_in_line == stat_delay) {
gb->io_registers[GB_IO_STAT] &= ~3; gb->io_registers[GB_IO_STAT] &= ~3;
gb->io_registers[GB_IO_STAT] |= 2; gb->io_registers[GB_IO_STAT] |= 2;
if (window_enabled(gb) && gb->display_cycles / LINE_LENGTH >= gb->io_registers[GB_IO_WY]) {
gb->current_window_line++;
}
} }
else if (position_in_line == 0 && gb->display_cycles != 0) { else if (position_in_line == 0 && gb->display_cycles != 0) {
should_compare_ly = gb->is_cgb; should_compare_ly = gb->is_cgb;
@ -335,6 +339,11 @@ static void update_display_state(GB_gameboy_t *gb, uint8_t cycles)
gb->io_registers[GB_IO_STAT] |= 3; gb->io_registers[GB_IO_STAT] |= 3;
gb->effective_scx = gb->io_registers[GB_IO_SCX]; gb->effective_scx = gb->io_registers[GB_IO_SCX];
gb->previous_lcdc_x = - (gb->effective_scx & 0x7); gb->previous_lcdc_x = - (gb->effective_scx & 0x7);
/* Todo: This works on both 007 - The World Is Not Enough and Donkey Kong 94, but should be verified better */
if (window_enabled(gb) && gb->display_cycles / LINE_LENGTH == gb->io_registers[GB_IO_WY] && gb->current_window_line == 0xFF) {
gb->current_window_line = 0;
}
} }
else if (position_in_line == MODE2_LENGTH + MODE3_LENGTH + stat_delay + scx_delay) { else if (position_in_line == MODE2_LENGTH + MODE3_LENGTH + stat_delay + scx_delay) {
gb->io_registers[GB_IO_STAT] &= ~3; gb->io_registers[GB_IO_STAT] &= ~3;
@ -491,17 +500,8 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles)
uint8_t effective_ly = gb->display_cycles / LINE_LENGTH; uint8_t effective_ly = gb->display_cycles / LINE_LENGTH;
// Todo: verify this window behavior. It is assumed from the expected behavior of 007 - The World Is Not Enough.
if ((gb->io_registers[GB_IO_LCDC] & 0x20) && effective_ly == gb->io_registers[GB_IO_WY]) {
gb->effective_window_enabled = true;
}
if (gb->display_cycles % LINE_LENGTH < MODE2_LENGTH) { /* Mode 2 */ if (gb->display_cycles % LINE_LENGTH < MODE2_LENGTH) { /* Mode 2 */
/* See above comment about window behavior. */
if (gb->effective_window_enabled && gb->effective_window_y == 0xFF) {
gb->effective_window_y = effective_ly;
}
return; return;
} }

View File

@ -362,10 +362,9 @@ struct GB_gameboy_internal_s {
uint32_t background_palettes_rgb[0x20]; uint32_t background_palettes_rgb[0x20];
uint32_t sprite_palettes_rgb[0x20]; uint32_t sprite_palettes_rgb[0x20];
int16_t previous_lcdc_x; int16_t previous_lcdc_x;
bool effective_window_enabled;
uint8_t effective_window_y;
bool stat_interrupt_line; bool stat_interrupt_line;
uint8_t effective_scx; uint8_t effective_scx;
uint8_t current_window_line;
); );
/* Unsaved data. This includes all pointers, as well as everything that shouldn't be on a save state */ /* Unsaved data. This includes all pointers, as well as everything that shouldn't be on a save state */