Import latest peanut_gb.h from deltabeard (commit ef26527)

This commit is contained in:
Vincent Mistler
2023-04-23 18:11:53 +02:00
parent da9680c9c7
commit 4fcf31bf53
+60 -44
View File
@@ -176,8 +176,8 @@
/** LCD characteristics **/
/* PPU cycles through modes every 456 cycles. */
#define LCD_LINE_CYCLES 456
/* Mode 0 starts on cycle 0. */
#define LCD_MODE_0_CYCLES 0
/* Mode 0 starts on cycle 372. */
#define LCD_MODE_0_CYCLES 372
/* Mode 2 starts on cycle 204. */
#define LCD_MODE_2_CYCLES 204
/* Mode 3 starts on cycle 284. */
@@ -745,10 +745,8 @@ uint8_t __gb_read(struct gb_s *gb, const uint16_t addr)
return 0xFF;
case 0xC:
return gb->wram[addr - WRAM_0_ADDR];
case 0xD:
return gb->wram[addr - WRAM_1_ADDR + WRAM_BANK_SIZE];
return gb->wram[addr - WRAM_0_ADDR];
case 0xE:
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. */
(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 */
case 0x40:
if(((gb->hram_io[IO_LCDC] & LCDC_ENABLE) == 0) &&
(val & LCDC_ENABLE))
{
gb->counter.lcd_count = 0;
gb->lcd_blank = 1;
}
{
uint8_t lcd_enabled;
/* Check if LCD is already enabled. */
lcd_enabled = (gb->hram_io[IO_LCDC] & LCDC_ENABLE);
gb->hram_io[IO_LCDC] = val;
/* LY fixed to 0 when LCD turned off. */
if((gb->hram_io[IO_LCDC] & LCDC_ENABLE) == 0)
/* Check if LCD is going to be switched on. */
if (!lcd_enabled && (val & LCDC_ENABLE))
{
/* Do not turn off LCD outside of VBLANK. This may
* 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;
}
gb->lcd_blank = 1;
}
/* 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. */
gb->hram_io[IO_STAT] = (gb->hram_io[IO_STAT] & ~0x03);
/* Set to line 0. */
gb->hram_io[IO_STAT] =
(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;
/* Reset LCD timer. */
gb->counter.lcd_count = 0;
}
return;
}
case 0x41:
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
* loop. */
(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)
@@ -2376,22 +2376,31 @@ void __gb_step_cpu(struct gb_s *gb)
halt_cycles = tac_cycles;
}
if((gb->hram_io[IO_LCDC] & LCDC_ENABLE) != 0)
if((gb->hram_io[IO_LCDC] & LCDC_ENABLE))
{
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
* mode 1. */
if((gb->hram_io[IO_STAT] & STAT_MODE) == IO_STAT_MODE_HBLANK)
{
lcd_cycles = LCD_MODE_2_CYCLES -
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_HBLANK)
else if((gb->hram_io[IO_STAT] & STAT_MODE) == IO_STAT_MODE_SEARCH_TRANSFER)
{
lcd_cycles = LCD_MODE_2_CYCLES -
lcd_cycles = LCD_MODE_0_CYCLES -
gb->counter.lcd_count;
}
else
{
/* VBlank */
lcd_cycles =
LCD_LINE_CYCLES - gb->counter.lcd_count;
}
@@ -3153,9 +3162,9 @@ void __gb_step_cpu(struct gb_s *gb)
break;
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);
// PGB_UNREACHABLE();
PGB_UNREACHABLE();
}
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. */
if((gb->hram_io[IO_LCDC] & LCDC_ENABLE) == 0)
/* If LCD is off, don't update LCD state or increase the LCD
* ticks. */
if(!(gb->hram_io[IO_LCDC] & LCDC_ENABLE))
continue;
/* LCD Timing */
@@ -3279,7 +3288,6 @@ void __gb_step_cpu(struct gb_s *gb)
gb->hram_io[IO_IF] |= LCDC_INTR;
#if ENABLE_LCD
/* If frame skip is activated, check if we need to draw
* the frame or skip it. */
if(gb->direct.frame_skip)
@@ -3292,15 +3300,15 @@ void __gb_step_cpu(struct gb_s *gb)
* updated. Also, only update lines on frames that are
* actually drawn when frame skip is enabled. */
if(gb->direct.interlace &&
(!gb->direct.frame_skip ||
gb->display.frame_skip_count))
(!gb->direct.frame_skip ||
gb->display.frame_skip_count))
{
gb->display.interlace_count =
!gb->display.interlace_count;
}
#endif
}
/* Normal Line */
/* Normal Line */
else if(gb->hram_io[IO_LY] < LCD_HEIGHT)
{
if(gb->hram_io[IO_LY] == 0)
@@ -3321,9 +3329,9 @@ void __gb_step_cpu(struct gb_s *gb)
inst_cycles = LCD_MODE_2_CYCLES - gb->counter.lcd_count;
}
}
/* OAM access */
/* OAM access */
else if((gb->hram_io[IO_STAT] & STAT_MODE) == IO_STAT_MODE_HBLANK &&
gb->counter.lcd_count >= LCD_MODE_2_CYCLES)
gb->counter.lcd_count >= LCD_MODE_2_CYCLES)
{
gb->hram_io[IO_STAT] =
(gb->hram_io[IO_STAT] & ~STAT_MODE) | IO_STAT_MODE_SEARCH_OAM;
@@ -3335,9 +3343,9 @@ void __gb_step_cpu(struct gb_s *gb)
if (gb->counter.lcd_count < LCD_MODE_3_CYCLES)
inst_cycles = LCD_MODE_3_CYCLES - gb->counter.lcd_count;
}
/* Update LCD */
/* Update LCD */
else if((gb->hram_io[IO_STAT] & STAT_MODE) == IO_STAT_MODE_SEARCH_OAM &&
gb->counter.lcd_count >= LCD_MODE_3_CYCLES)
gb->counter.lcd_count >= LCD_MODE_3_CYCLES)
{
gb->hram_io[IO_STAT] =
(gb->hram_io[IO_STAT] & ~STAT_MODE) | IO_STAT_MODE_SEARCH_TRANSFER;
@@ -3346,8 +3354,8 @@ void __gb_step_cpu(struct gb_s *gb)
__gb_draw_line(gb);
#endif
/* If halted immediately jump to next LCD mode. */
if (gb->counter.lcd_count < LCD_LINE_CYCLES)
inst_cycles = LCD_LINE_CYCLES - gb->counter.lcd_count;
if (gb->counter.lcd_count < LCD_MODE_0_CYCLES)
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);
/* 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);
/**
* 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 **/
/**
* Reset the emulator, like turning the Game Boy off and on again.