General cleanup. Minor fixes to LCD Controller accuracy.
This commit is contained in:
parent
d7d8da3fa9
commit
8153b765a2
@ -683,8 +683,6 @@ void debugger_ret_hook(GB_gameboy_t *gb)
|
||||
}
|
||||
}
|
||||
|
||||
/* The debugger interface is quite primitive. One letter commands with a single parameter maximum.
|
||||
Only one breakpoint is allowed at a time. More features will be added later. */
|
||||
void debugger_run(GB_gameboy_t *gb)
|
||||
{
|
||||
char *input = NULL;
|
||||
|
@ -240,6 +240,23 @@ void palette_changed(GB_gameboy_t *gb, bool background_palette, unsigned char in
|
||||
(background_palette? gb->background_palletes_rgb : gb->sprite_palletes_rgb)[index / 2] = gb->rgb_encode_callback(gb, r, g, b);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Each line is 456 cycles, approximately:
|
||||
Mode 2 - 80 cycles / OAM Transfer
|
||||
Mode 3 - 172 cycles / Rendering
|
||||
Mode 0 - 204 cycles / HBlank
|
||||
|
||||
Mode 1 is VBlank
|
||||
|
||||
Todo: Mode lengths are not constants, see http://blog.kevtris.org/blogfiles/Nitty%20Gritty%20Gameboy%20VRAM%20Timing.txt
|
||||
*/
|
||||
|
||||
#define MODE2_LENGTH 80
|
||||
#define MODE3_LENGTH 172
|
||||
#define MODE1_LENGTH 204
|
||||
#define LINE_LENGTH (MODE2_LENGTH + MODE3_LENGTH + MODE1_LENGTH) // = 456
|
||||
|
||||
void display_run(GB_gameboy_t *gb)
|
||||
{
|
||||
/*
|
||||
@ -248,42 +265,43 @@ void display_run(GB_gameboy_t *gb)
|
||||
|
||||
See http://forums.nesdev.com/viewtopic.php?f=20&t=13727
|
||||
*/
|
||||
unsigned char last_mode = gb->io_registers[GB_IO_STAT] & 3;
|
||||
|
||||
/*
|
||||
STAT interrupt is implemented based on this finding:
|
||||
http://board.byuu.org/phpbb3/viewtopic.php?p=25527#p25531
|
||||
*/
|
||||
|
||||
unsigned char previous_stat_interrupt_line = gb->stat_interrupt_line;
|
||||
gb->stat_interrupt_line = false;
|
||||
|
||||
unsigned char last_mode = gb->io_registers[GB_IO_STAT] & 3;
|
||||
gb->io_registers[GB_IO_STAT] &= ~3;
|
||||
|
||||
if (gb->display_cycles >= LCDC_PERIOD) {
|
||||
/* VBlank! */
|
||||
gb->display_cycles -= LCDC_PERIOD;
|
||||
gb->ly144_bug_oam = false;
|
||||
gb->ly144_bug_hblank = false;
|
||||
display_vblank(gb);
|
||||
}
|
||||
|
||||
if (!(gb->io_registers[GB_IO_LCDC] & 0x80)) {
|
||||
/* LCD is disabled, do nothing */
|
||||
gb->io_registers[GB_IO_STAT] &= ~3;
|
||||
|
||||
/* Some games expect LY to be zero when the LCD is off.
|
||||
Todo: Verify this behavior.
|
||||
Keep in mind that this only affects the value being read from the Gameboy, not the actualy display state.
|
||||
This also explains why the coincidence interrupt triggers when LYC = 0 and LY = 153. */
|
||||
gb->io_registers[GB_IO_LY] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
gb->io_registers[GB_IO_STAT] &= ~3;
|
||||
|
||||
/*
|
||||
Each line is 456 cycles, approximately:
|
||||
Mode 2 - 80 cycles
|
||||
Mode 3 - 172 cycles
|
||||
Mode 0 - 204 cycles
|
||||
gb->io_registers[GB_IO_LY] = gb->display_cycles / LINE_LENGTH;
|
||||
|
||||
Todo: Mode lengths are not constants???
|
||||
*/
|
||||
|
||||
gb->io_registers[GB_IO_LY] = gb->display_cycles / 456;
|
||||
/* Todo: This behavior is seen in BGB and it fixes some ROMs with delicate timing, such as Hitman's 8bit.
|
||||
This should be verified to be correct on a real gameboy. */
|
||||
if (gb->io_registers[GB_IO_LY] == 153 && gb->display_cycles % LINE_LENGTH > 8) {
|
||||
gb->io_registers[GB_IO_LY] = 0;
|
||||
}
|
||||
|
||||
gb->io_registers[GB_IO_STAT] &= ~4;
|
||||
if (gb->io_registers[GB_IO_LY] == gb->io_registers[GB_IO_LYC]) {
|
||||
@ -294,13 +312,7 @@ void display_run(GB_gameboy_t *gb)
|
||||
}
|
||||
}
|
||||
|
||||
/* Todo: This behavior is seen in BGB and it fixes some ROMs with delicate timing, such as Hitman's 8bit.
|
||||
This should be verified to be correct on a real gameboy. */
|
||||
if (gb->io_registers[GB_IO_LY] == 153 && gb->display_cycles % 456 > 8) {
|
||||
gb->io_registers[GB_IO_LY] = 0;
|
||||
}
|
||||
|
||||
if (gb->display_cycles >= 456 * 144) { /* VBlank */
|
||||
if (gb->display_cycles >= LINE_LENGTH * 144) { /* VBlank */
|
||||
gb->io_registers[GB_IO_STAT] |= 1; /* Set mode to 1 */
|
||||
gb->effective_window_enabled = false;
|
||||
gb->effective_window_y = 0xFF;
|
||||
@ -314,23 +326,9 @@ void display_run(GB_gameboy_t *gb)
|
||||
|
||||
// LY = 144 interrupt bug
|
||||
if (gb->io_registers[GB_IO_LY] == 144) {
|
||||
if (gb->display_cycles % 456 < 80) { // Mode 2
|
||||
if (gb->io_registers[GB_IO_STAT] & 0x20 && !gb->ly144_bug_oam) { /* User requests an interrupt on Mode 2 */
|
||||
gb->io_registers[GB_IO_IF] |= 2;
|
||||
}
|
||||
gb->ly144_bug_oam = true;
|
||||
}
|
||||
if (gb->display_cycles % 456 < 80 + 172) { /* Mode 3 */
|
||||
// Nothing to do
|
||||
}
|
||||
else { /* Mode 0 */
|
||||
if (gb->io_registers[GB_IO_STAT] & 8 && !gb->ly144_bug_hblank) { /* User requests an interrupt on Mode 0 */
|
||||
/*
|
||||
Todo: Verify if this actually happens.
|
||||
gb->io_registers[GB_IO_IF] |= 2;
|
||||
*/
|
||||
}
|
||||
gb->ly144_bug_hblank = true;
|
||||
/* User requests an interrupt on Mode 2 */
|
||||
if (gb->display_cycles % LINE_LENGTH < 92 && gb->io_registers[GB_IO_STAT] & 0x20) { // Mode 2
|
||||
gb->stat_interrupt_line = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -342,7 +340,7 @@ void display_run(GB_gameboy_t *gb)
|
||||
gb->effective_window_enabled = true;
|
||||
}
|
||||
|
||||
if (gb->display_cycles % 456 < 80) { /* Mode 2 */
|
||||
if (gb->display_cycles % LINE_LENGTH < MODE2_LENGTH) { /* Mode 2 */
|
||||
gb->io_registers[GB_IO_STAT] |= 2; /* Set mode to 2 */
|
||||
|
||||
if (gb->io_registers[GB_IO_STAT] & 0x20) { /* User requests an interrupt on Mode 2 */
|
||||
@ -359,7 +357,11 @@ void display_run(GB_gameboy_t *gb)
|
||||
goto updateSTAT;
|
||||
}
|
||||
|
||||
signed short current_lcdc_x = ((gb->display_cycles % 456 - 80) & ~7) - (gb->effective_scx & 0x7);
|
||||
if (gb->display_cycles % LINE_LENGTH < MODE2_LENGTH + MODE3_LENGTH) { /* Mode 3 */
|
||||
if (last_mode != 3) {
|
||||
|
||||
}
|
||||
signed short current_lcdc_x = ((gb->display_cycles % LINE_LENGTH - MODE2_LENGTH) & ~7) - (gb->effective_scx & 0x7);
|
||||
for (;gb->previous_lcdc_x < current_lcdc_x; gb->previous_lcdc_x++) {
|
||||
if (gb->previous_lcdc_x >= 160) {
|
||||
continue;
|
||||
@ -370,23 +372,21 @@ void display_run(GB_gameboy_t *gb)
|
||||
gb->screen[gb->io_registers[GB_IO_LY] * 160 + gb->previous_lcdc_x] =
|
||||
get_pixel(gb, gb->previous_lcdc_x, gb->io_registers[GB_IO_LY]);
|
||||
}
|
||||
|
||||
if (gb->display_cycles % 456 < 80 + 172) { /* Mode 3 */
|
||||
gb->io_registers[GB_IO_STAT] |= 3; /* Set mode to 3 */
|
||||
goto updateSTAT;
|
||||
}
|
||||
|
||||
/* if (gb->display_cycles % 456 < 80 + 172 + 204) */ { /* Mode 0*/
|
||||
/* Mode 0*/
|
||||
if (gb->io_registers[GB_IO_STAT] & 8) { /* User requests an interrupt on Mode 0 */
|
||||
gb->stat_interrupt_line = true;
|
||||
}
|
||||
|
||||
if (last_mode != 0) {
|
||||
if (gb->hdma_on_hblank) {
|
||||
gb->hdma_on = true;
|
||||
gb->hdma_cycles = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateSTAT:
|
||||
if (gb->stat_interrupt_line && !previous_stat_interrupt_line) {
|
||||
|
@ -261,8 +261,8 @@ typedef struct GB_gameboy_s {
|
||||
unsigned char sprite_palletes_data[0x40];
|
||||
uint32_t background_palletes_rgb[0x20];
|
||||
uint32_t sprite_palletes_rgb[0x20];
|
||||
bool ly144_bug_oam;
|
||||
bool ly144_bug_hblank;
|
||||
GB_PADDING(bool, ly144_bug_oam);
|
||||
GB_PADDING(bool, ly144_bug_hblank);
|
||||
signed short previous_lcdc_x;
|
||||
unsigned char padding;
|
||||
bool effective_window_enabled;
|
||||
|
Loading…
Reference in New Issue
Block a user