Import latest peanut_gb.h from deltabeard (commit ef26527)
This commit is contained in:
+54
-38
@@ -176,8 +176,8 @@
|
|||||||
/** LCD characteristics **/
|
/** LCD characteristics **/
|
||||||
/* PPU cycles through modes every 456 cycles. */
|
/* PPU cycles through modes every 456 cycles. */
|
||||||
#define LCD_LINE_CYCLES 456
|
#define LCD_LINE_CYCLES 456
|
||||||
/* Mode 0 starts on cycle 0. */
|
/* Mode 0 starts on cycle 372. */
|
||||||
#define LCD_MODE_0_CYCLES 0
|
#define LCD_MODE_0_CYCLES 372
|
||||||
/* Mode 2 starts on cycle 204. */
|
/* Mode 2 starts on cycle 204. */
|
||||||
#define LCD_MODE_2_CYCLES 204
|
#define LCD_MODE_2_CYCLES 204
|
||||||
/* Mode 3 starts on cycle 284. */
|
/* Mode 3 starts on cycle 284. */
|
||||||
@@ -745,10 +745,8 @@ uint8_t __gb_read(struct gb_s *gb, const uint16_t addr)
|
|||||||
return 0xFF;
|
return 0xFF;
|
||||||
|
|
||||||
case 0xC:
|
case 0xC:
|
||||||
return gb->wram[addr - WRAM_0_ADDR];
|
|
||||||
|
|
||||||
case 0xD:
|
case 0xD:
|
||||||
return gb->wram[addr - WRAM_1_ADDR + WRAM_BANK_SIZE];
|
return gb->wram[addr - WRAM_0_ADDR];
|
||||||
|
|
||||||
case 0xE:
|
case 0xE:
|
||||||
return gb->wram[addr - ECHO_ADDR];
|
return gb->wram[addr - ECHO_ADDR];
|
||||||
@@ -792,7 +790,7 @@ uint8_t __gb_read(struct gb_s *gb, const uint16_t addr)
|
|||||||
|
|
||||||
/* Return address that caused read error. */
|
/* Return address that caused read error. */
|
||||||
(gb->gb_error)(gb, GB_INVALID_READ, addr);
|
(gb->gb_error)(gb, GB_INVALID_READ, addr);
|
||||||
// PGB_UNREACHABLE();
|
PGB_UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -991,35 +989,37 @@ void __gb_write(struct gb_s *gb, const uint_fast16_t addr, const uint8_t val)
|
|||||||
|
|
||||||
/* LCD Registers */
|
/* LCD Registers */
|
||||||
case 0x40:
|
case 0x40:
|
||||||
if(((gb->hram_io[IO_LCDC] & LCDC_ENABLE) == 0) &&
|
|
||||||
(val & LCDC_ENABLE))
|
|
||||||
{
|
{
|
||||||
gb->counter.lcd_count = 0;
|
uint8_t lcd_enabled;
|
||||||
gb->lcd_blank = 1;
|
|
||||||
}
|
/* Check if LCD is already enabled. */
|
||||||
|
lcd_enabled = (gb->hram_io[IO_LCDC] & LCDC_ENABLE);
|
||||||
|
|
||||||
gb->hram_io[IO_LCDC] = val;
|
gb->hram_io[IO_LCDC] = val;
|
||||||
|
|
||||||
/* LY fixed to 0 when LCD turned off. */
|
/* Check if LCD is going to be switched on. */
|
||||||
if((gb->hram_io[IO_LCDC] & LCDC_ENABLE) == 0)
|
if (!lcd_enabled && (val & LCDC_ENABLE))
|
||||||
{
|
{
|
||||||
/* Do not turn off LCD outside of VBLANK. This may
|
gb->lcd_blank = 1;
|
||||||
* happen due to poor timing in this emulator. */
|
|
||||||
if((gb->hram_io[IO_STAT] & STAT_MODE) != IO_STAT_MODE_VBLANK)
|
|
||||||
{
|
|
||||||
gb->hram_io[IO_LCDC] |= LCDC_ENABLE;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
/* Check if LCD is being switched off. */
|
||||||
|
else if (lcd_enabled && !(val & LCDC_ENABLE))
|
||||||
|
{
|
||||||
|
/* Peanut-GB will happily turn off LCD outside
|
||||||
|
* of VBLANK even though this damages real
|
||||||
|
* hardware. */
|
||||||
|
|
||||||
/* Set LCD to Mode 0. */
|
/* Set LCD to Mode 0. */
|
||||||
gb->hram_io[IO_STAT] = (gb->hram_io[IO_STAT] & ~0x03);
|
gb->hram_io[IO_STAT] =
|
||||||
/* Set to line 0. */
|
(gb->hram_io[IO_STAT] & ~STAT_MODE) |
|
||||||
|
IO_STAT_MODE_HBLANK;
|
||||||
|
/* LY fixed to 0 when LCD turned off. */
|
||||||
gb->hram_io[IO_LY] = 0;
|
gb->hram_io[IO_LY] = 0;
|
||||||
/* Reset LCD timer. */
|
/* Reset LCD timer. */
|
||||||
gb->counter.lcd_count = 0;
|
gb->counter.lcd_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
case 0x41:
|
case 0x41:
|
||||||
gb->hram_io[IO_STAT] = (val & STAT_USER_BITS) | (gb->hram_io[IO_STAT] & STAT_MODE);
|
gb->hram_io[IO_STAT] = (val & STAT_USER_BITS) | (gb->hram_io[IO_STAT] & STAT_MODE);
|
||||||
@@ -2355,7 +2355,7 @@ void __gb_step_cpu(struct gb_s *gb)
|
|||||||
/* This may be intentional, but this is required to stop an infinite
|
/* This may be intentional, but this is required to stop an infinite
|
||||||
* loop. */
|
* loop. */
|
||||||
(gb->gb_error)(gb, GB_HALT_FOREVER, gb->cpu_reg.pc.reg - 1);
|
(gb->gb_error)(gb, GB_HALT_FOREVER, gb->cpu_reg.pc.reg - 1);
|
||||||
// PGB_UNREACHABLE();
|
PGB_UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(gb->hram_io[IO_SC] & SERIAL_SC_TX_START)
|
if(gb->hram_io[IO_SC] & SERIAL_SC_TX_START)
|
||||||
@@ -2376,22 +2376,31 @@ void __gb_step_cpu(struct gb_s *gb)
|
|||||||
halt_cycles = tac_cycles;
|
halt_cycles = tac_cycles;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((gb->hram_io[IO_LCDC] & LCDC_ENABLE) != 0)
|
if((gb->hram_io[IO_LCDC] & LCDC_ENABLE))
|
||||||
{
|
{
|
||||||
int lcd_cycles;
|
int lcd_cycles;
|
||||||
|
|
||||||
if((gb->hram_io[IO_STAT] & STAT_MODE) == IO_STAT_MODE_SEARCH_OAM)
|
/* If LCD is in HBlank, calculate the number of cycles
|
||||||
{
|
* until the end of HBlank and the start of mode 2 or
|
||||||
lcd_cycles = LCD_MODE_3_CYCLES -
|
* mode 1. */
|
||||||
gb->counter.lcd_count;
|
if((gb->hram_io[IO_STAT] & STAT_MODE) == IO_STAT_MODE_HBLANK)
|
||||||
}
|
|
||||||
else if((gb->hram_io[IO_STAT] & STAT_MODE) == IO_STAT_MODE_HBLANK)
|
|
||||||
{
|
{
|
||||||
lcd_cycles = LCD_MODE_2_CYCLES -
|
lcd_cycles = LCD_MODE_2_CYCLES -
|
||||||
gb->counter.lcd_count;
|
gb->counter.lcd_count;
|
||||||
}
|
}
|
||||||
|
else if((gb->hram_io[IO_STAT] & STAT_MODE) == IO_STAT_MODE_SEARCH_OAM)
|
||||||
|
{
|
||||||
|
lcd_cycles = LCD_MODE_3_CYCLES -
|
||||||
|
gb->counter.lcd_count;
|
||||||
|
}
|
||||||
|
else if((gb->hram_io[IO_STAT] & STAT_MODE) == IO_STAT_MODE_SEARCH_TRANSFER)
|
||||||
|
{
|
||||||
|
lcd_cycles = LCD_MODE_0_CYCLES -
|
||||||
|
gb->counter.lcd_count;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/* VBlank */
|
||||||
lcd_cycles =
|
lcd_cycles =
|
||||||
LCD_LINE_CYCLES - gb->counter.lcd_count;
|
LCD_LINE_CYCLES - gb->counter.lcd_count;
|
||||||
}
|
}
|
||||||
@@ -3153,9 +3162,9 @@ void __gb_step_cpu(struct gb_s *gb)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* Return address where invalid opcode that was read. */
|
/* Return address where invlid opcode that was read. */
|
||||||
(gb->gb_error)(gb, GB_INVALID_OPCODE, gb->cpu_reg.pc.reg - 1);
|
(gb->gb_error)(gb, GB_INVALID_OPCODE, gb->cpu_reg.pc.reg - 1);
|
||||||
// PGB_UNREACHABLE();
|
PGB_UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
do
|
do
|
||||||
@@ -3239,9 +3248,9 @@ void __gb_step_cpu(struct gb_s *gb)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO Check behaviour of LCD during LCD power off state. */
|
/* If LCD is off, don't update LCD state or increase the LCD
|
||||||
/* If LCD is off, don't update LCD state. */
|
* ticks. */
|
||||||
if((gb->hram_io[IO_LCDC] & LCDC_ENABLE) == 0)
|
if(!(gb->hram_io[IO_LCDC] & LCDC_ENABLE))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* LCD Timing */
|
/* LCD Timing */
|
||||||
@@ -3279,7 +3288,6 @@ void __gb_step_cpu(struct gb_s *gb)
|
|||||||
gb->hram_io[IO_IF] |= LCDC_INTR;
|
gb->hram_io[IO_IF] |= LCDC_INTR;
|
||||||
|
|
||||||
#if ENABLE_LCD
|
#if ENABLE_LCD
|
||||||
|
|
||||||
/* If frame skip is activated, check if we need to draw
|
/* If frame skip is activated, check if we need to draw
|
||||||
* the frame or skip it. */
|
* the frame or skip it. */
|
||||||
if(gb->direct.frame_skip)
|
if(gb->direct.frame_skip)
|
||||||
@@ -3346,8 +3354,8 @@ void __gb_step_cpu(struct gb_s *gb)
|
|||||||
__gb_draw_line(gb);
|
__gb_draw_line(gb);
|
||||||
#endif
|
#endif
|
||||||
/* If halted immediately jump to next LCD mode. */
|
/* If halted immediately jump to next LCD mode. */
|
||||||
if (gb->counter.lcd_count < LCD_LINE_CYCLES)
|
if (gb->counter.lcd_count < LCD_MODE_0_CYCLES)
|
||||||
inst_cycles = LCD_LINE_CYCLES - gb->counter.lcd_count;
|
inst_cycles = LCD_MODE_0_CYCLES - gb->counter.lcd_count;
|
||||||
}
|
}
|
||||||
} while(gb->gb_halt && (gb->hram_io[IO_IF] & gb->hram_io[IO_IE]) == 0);
|
} while(gb->gb_halt && (gb->hram_io[IO_IF] & gb->hram_io[IO_IE]) == 0);
|
||||||
/* If halted, loop until an interrupt occurs. */
|
/* If halted, loop until an interrupt occurs. */
|
||||||
@@ -3687,6 +3695,14 @@ enum gb_init_error_e gb_init(struct gb_s *gb,
|
|||||||
*/
|
*/
|
||||||
void gb_run_frame(struct gb_s *gb);
|
void gb_run_frame(struct gb_s *gb);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal function used to step the CPU. Used mainly for testing.
|
||||||
|
* Use gb_run_frame() instead.
|
||||||
|
*
|
||||||
|
* \param An initialised emulator context. Must not be NULL.
|
||||||
|
*/
|
||||||
|
void __gb_step_cpu(struct gb_s *gb);
|
||||||
|
|
||||||
/** Function prototypes: Optional Functions **/
|
/** Function prototypes: Optional Functions **/
|
||||||
/**
|
/**
|
||||||
* Reset the emulator, like turning the Game Boy off and on again.
|
* Reset the emulator, like turning the Game Boy off and on again.
|
||||||
|
|||||||
Reference in New Issue
Block a user