Import latest Peanut-GB (commit 72f6922) from deltabeard: gb: fix incorrect LCD timing: fixes #75 where Kirby's Dream Land 2 used an incorrect opcode.
This commit is contained in:
+86
-46
@@ -104,6 +104,10 @@
|
|||||||
# define PEANUT_GB_USE_INTRINSICS 1
|
# define PEANUT_GB_USE_INTRINSICS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Only include function prototypes. At least one file must *not* have this
|
||||||
|
* defined. */
|
||||||
|
// #define PEANUT_GB_HEADER_ONLY
|
||||||
|
|
||||||
/** Internal source code. **/
|
/** Internal source code. **/
|
||||||
/* Interrupt masks */
|
/* Interrupt masks */
|
||||||
#define VBLANK_INTR 0x01
|
#define VBLANK_INTR 0x01
|
||||||
@@ -176,7 +180,7 @@
|
|||||||
#define LCDC_BG_ENABLE 0x01
|
#define LCDC_BG_ENABLE 0x01
|
||||||
|
|
||||||
/* LCD characteristics */
|
/* LCD characteristics */
|
||||||
#define LCD_LINE_CYCLES 456
|
#define LCD_LINE_CYCLES (456 + 4)
|
||||||
#define LCD_MODE_0_CYCLES 0
|
#define LCD_MODE_0_CYCLES 0
|
||||||
#define LCD_MODE_2_CYCLES 204
|
#define LCD_MODE_2_CYCLES 204
|
||||||
#define LCD_MODE_3_CYCLES 284
|
#define LCD_MODE_3_CYCLES 284
|
||||||
@@ -237,13 +241,13 @@
|
|||||||
/* If using MSVC, only enable intrinsics for x86 platforms*/
|
/* If using MSVC, only enable intrinsics for x86 platforms*/
|
||||||
# if defined(_MSC_VER) && __has_include("intrin.h") && \
|
# if defined(_MSC_VER) && __has_include("intrin.h") && \
|
||||||
(defined(_M_IX86_FP) || defined(_M_AMD64) || defined(_M_X64))
|
(defined(_M_IX86_FP) || defined(_M_AMD64) || defined(_M_X64))
|
||||||
/* Define instrinsic functions for MSVC. */
|
/* Define intrinsic functions for MSVC. */
|
||||||
# include <intrin.h>
|
# include <intrin.h>
|
||||||
# define PGB_INTRIN_SBC(x,y,cin,res) _subborrow_u8(cin,x,y,&res)
|
# define PGB_INTRIN_SBC(x,y,cin,res) _subborrow_u8(cin,x,y,&res)
|
||||||
# define PGB_INTRIN_ADC(x,y,cin,res) _addcarry_u8(cin,x,y,&res)
|
# define PGB_INTRIN_ADC(x,y,cin,res) _addcarry_u8(cin,x,y,&res)
|
||||||
# endif /* MSVC */
|
# endif /* MSVC */
|
||||||
|
|
||||||
/* Check for instrinsic functions in GCC and Clang. */
|
/* Check for intrinsic functions in GCC and Clang. */
|
||||||
# if __has_builtin(__builtin_sub_overflow)
|
# if __has_builtin(__builtin_sub_overflow)
|
||||||
# define PGB_INTRIN_SBC(x,y,cin,res) __builtin_sub_overflow(x,y+cin,&res)
|
# define PGB_INTRIN_SBC(x,y,cin,res) __builtin_sub_overflow(x,y+cin,&res)
|
||||||
# define PGB_INTRIN_ADC(x,y,cin,res) __builtin_add_overflow(x,y+cin,&res)
|
# define PGB_INTRIN_ADC(x,y,cin,res) __builtin_add_overflow(x,y+cin,&res)
|
||||||
@@ -428,6 +432,7 @@ struct count_s
|
|||||||
#define IO_OBP1 0x49
|
#define IO_OBP1 0x49
|
||||||
#define IO_WY 0x4A
|
#define IO_WY 0x4A
|
||||||
#define IO_WX 0x4B
|
#define IO_WX 0x4B
|
||||||
|
#define IO_BR 0x50
|
||||||
#define IO_IE 0xFF
|
#define IO_IE 0xFF
|
||||||
|
|
||||||
#define IO_TAC_RATE_MASK 0x3
|
#define IO_TAC_RATE_MASK 0x3
|
||||||
@@ -533,7 +538,7 @@ struct gb_s
|
|||||||
*
|
*
|
||||||
* \param gb_s emulator context
|
* \param gb_s emulator context
|
||||||
* \param gb_error_e error code
|
* \param gb_error_e error code
|
||||||
* \param addr address of where error occured
|
* \param addr address of where error occurred
|
||||||
*/
|
*/
|
||||||
void (*gb_error)(struct gb_s*, const enum gb_error_e, const uint16_t addr);
|
void (*gb_error)(struct gb_s*, const enum gb_error_e, const uint16_t addr);
|
||||||
|
|
||||||
@@ -541,13 +546,12 @@ struct gb_s
|
|||||||
void (*gb_serial_tx)(struct gb_s*, const uint8_t tx);
|
void (*gb_serial_tx)(struct gb_s*, const uint8_t tx);
|
||||||
enum gb_serial_rx_ret_e (*gb_serial_rx)(struct gb_s*, uint8_t* rx);
|
enum gb_serial_rx_ret_e (*gb_serial_rx)(struct gb_s*, uint8_t* rx);
|
||||||
|
|
||||||
|
uint8_t (*gb_bios_read)(struct gb_s*, const uint_fast16_t);
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
unsigned gb_halt : 1;
|
unsigned gb_halt : 1;
|
||||||
unsigned gb_ime : 1;
|
unsigned gb_ime : 1;
|
||||||
#if PEANUT_GB_USE_BIOS
|
|
||||||
unsigned gb_bios_enable : 1;
|
|
||||||
#endif
|
|
||||||
unsigned gb_frame : 1; /* New frame drawn. */
|
unsigned gb_frame : 1; /* New frame drawn. */
|
||||||
|
|
||||||
unsigned lcd_blank : 1;
|
unsigned lcd_blank : 1;
|
||||||
@@ -665,6 +669,7 @@ struct gb_s
|
|||||||
} direct;
|
} direct;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifndef PEANUT_GB_HEADER_ONLY
|
||||||
/**
|
/**
|
||||||
* Internal function used to read bytes.
|
* Internal function used to read bytes.
|
||||||
* addr is host platform endian.
|
* addr is host platform endian.
|
||||||
@@ -674,8 +679,14 @@ uint8_t __gb_read(struct gb_s *gb, const uint16_t addr)
|
|||||||
switch(PEANUT_GB_GET_MSN16(addr))
|
switch(PEANUT_GB_GET_MSN16(addr))
|
||||||
{
|
{
|
||||||
case 0x0:
|
case 0x0:
|
||||||
|
/* IO_BR is only set to 1 if gb->gb_bios_read was not NULL on
|
||||||
|
* reset. */
|
||||||
|
if(gb->hram_io[IO_BR] == 0 && addr < 0x0100)
|
||||||
|
{
|
||||||
|
return gb->gb_bios_read(gb, addr);
|
||||||
|
}
|
||||||
|
|
||||||
/* TODO: BIOS support. */
|
/* Fallthrough */
|
||||||
case 0x1:
|
case 0x1:
|
||||||
case 0x2:
|
case 0x2:
|
||||||
case 0x3:
|
case 0x3:
|
||||||
@@ -1057,9 +1068,7 @@ void __gb_write(struct gb_s *gb, const uint_fast16_t addr, const uint8_t val)
|
|||||||
|
|
||||||
/* Turn off boot ROM */
|
/* Turn off boot ROM */
|
||||||
case 0x50:
|
case 0x50:
|
||||||
#if PEANUT_GB_USE_BIOS
|
gb->hram_io[IO_BR] = val;
|
||||||
gb->gb_bios_enable = 0;
|
|
||||||
#endif
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Interrupt Enable Register */
|
/* Interrupt Enable Register */
|
||||||
@@ -3485,15 +3494,12 @@ uint8_t gb_colour_hash(struct gb_s *gb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets the context, and initialises startup values.
|
* Resets the context, and initialises startup values for a DMG console.
|
||||||
*/
|
*/
|
||||||
void gb_reset(struct gb_s *gb)
|
void gb_reset(struct gb_s *gb)
|
||||||
{
|
{
|
||||||
gb->gb_halt = 0;
|
gb->gb_halt = 0;
|
||||||
gb->gb_ime = 1;
|
gb->gb_ime = 1;
|
||||||
#if PEANUT_GB_USE_BIOS
|
|
||||||
gb->gb_bios_enable = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Initialise MBC values. */
|
/* Initialise MBC values. */
|
||||||
gb->selected_rom_bank = 1;
|
gb->selected_rom_bank = 1;
|
||||||
@@ -3501,52 +3507,69 @@ void gb_reset(struct gb_s *gb)
|
|||||||
gb->enable_cart_ram = 0;
|
gb->enable_cart_ram = 0;
|
||||||
gb->cart_mode_select = 0;
|
gb->cart_mode_select = 0;
|
||||||
|
|
||||||
/* Initialise CPU registers as though a DMG. */
|
/* Use values as though the bootrom was already executed. */
|
||||||
gb->cpu_reg.a = 0x01;
|
if(gb->gb_bios_read == NULL)
|
||||||
gb->cpu_reg.f_bits.z = 1;
|
{
|
||||||
gb->cpu_reg.f_bits.n = 0;
|
uint8_t hdr_chk;
|
||||||
gb->cpu_reg.f_bits.h = 1;
|
hdr_chk = gb->gb_rom_read(gb, ROM_HEADER_CHECKSUM_LOC) != 0;
|
||||||
gb->cpu_reg.f_bits.c = 1;
|
|
||||||
gb->cpu_reg.bc.reg = 0x0013;
|
gb->cpu_reg.a = 0x01;
|
||||||
gb->cpu_reg.de.reg = 0x00D8;
|
gb->cpu_reg.f_bits.z = 1;
|
||||||
gb->cpu_reg.hl.reg = 0x014D;
|
gb->cpu_reg.f_bits.n = 0;
|
||||||
gb->cpu_reg.sp.reg = 0xFFFE;
|
gb->cpu_reg.f_bits.h = hdr_chk;
|
||||||
/* TODO: Add BIOS support. */
|
gb->cpu_reg.f_bits.c = hdr_chk;
|
||||||
gb->cpu_reg.pc.reg = 0x0100;
|
gb->cpu_reg.bc.reg = 0x0013;
|
||||||
|
gb->cpu_reg.de.reg = 0x00D8;
|
||||||
|
gb->cpu_reg.hl.reg = 0x014D;
|
||||||
|
gb->cpu_reg.sp.reg = 0xFFFE;
|
||||||
|
gb->cpu_reg.pc.reg = 0x0100;
|
||||||
|
|
||||||
|
gb->hram_io[IO_DIV ] = 0xAB;
|
||||||
|
gb->hram_io[IO_LCDC] = 0x91;
|
||||||
|
gb->hram_io[IO_STAT] = 0x85;
|
||||||
|
gb->hram_io[IO_BR ] = 0x01;
|
||||||
|
|
||||||
|
memset(gb->vram, 0x00, VRAM_SIZE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Set value as though the console was just switched on.
|
||||||
|
* CPU registers are uninitialised. */
|
||||||
|
gb->cpu_reg.pc.reg = 0x0000;
|
||||||
|
gb->hram_io[IO_DIV ] = 0x00;
|
||||||
|
gb->hram_io[IO_LCDC] = 0x00;
|
||||||
|
gb->hram_io[IO_STAT] = 0x84;
|
||||||
|
gb->hram_io[IO_BR ] = 0x00;
|
||||||
|
}
|
||||||
|
|
||||||
gb->counter.lcd_count = 0;
|
gb->counter.lcd_count = 0;
|
||||||
gb->counter.div_count = 0;
|
gb->counter.div_count = 0;
|
||||||
gb->counter.tima_count = 0;
|
gb->counter.tima_count = 0;
|
||||||
gb->counter.serial_count = 0;
|
gb->counter.serial_count = 0;
|
||||||
|
|
||||||
memset(gb->hram_io, 0xFF, HRAM_IO_SIZE);
|
gb->direct.joypad = 0xFF;
|
||||||
|
gb->hram_io[IO_JOYP] = 0xCF;
|
||||||
|
gb->hram_io[IO_SB ] = 0x00;
|
||||||
|
gb->hram_io[IO_SC ] = 0x7E;
|
||||||
|
/* DIV */
|
||||||
gb->hram_io[IO_TIMA] = 0x00;
|
gb->hram_io[IO_TIMA] = 0x00;
|
||||||
gb->hram_io[IO_TMA ] = 0x00;
|
gb->hram_io[IO_TMA ] = 0x00;
|
||||||
gb->hram_io[IO_TAC ] = 0xF8;
|
gb->hram_io[IO_TAC ] = 0xF8;
|
||||||
gb->hram_io[IO_DIV ] = 0xAC;
|
|
||||||
gb->hram_io[IO_IF ] = 0xE1;
|
gb->hram_io[IO_IF ] = 0xE1;
|
||||||
gb->hram_io[IO_LCDC] = 0x91;
|
|
||||||
gb->hram_io[IO_STAT] = STAT_MODE & IO_STAT_MODE_HBLANK;
|
/* LCDC */
|
||||||
|
/* STAT */
|
||||||
gb->hram_io[IO_SCY ] = 0x00;
|
gb->hram_io[IO_SCY ] = 0x00;
|
||||||
gb->hram_io[IO_SCX ] = 0x00;
|
gb->hram_io[IO_SCX ] = 0x00;
|
||||||
|
gb->hram_io[IO_LY ] = 0x00;
|
||||||
gb->hram_io[IO_LYC ] = 0x00;
|
gb->hram_io[IO_LYC ] = 0x00;
|
||||||
|
__gb_write(gb, 0xFF47, 0xFC); // BGP
|
||||||
/* Appease valgrind for invalid reads and unconditional jumps. */
|
__gb_write(gb, 0xFF48, 0xFF); // OBJP0
|
||||||
gb->hram_io[IO_SC] = 0x7E;
|
__gb_write(gb, 0xFF49, 0xFF); // OBJP1
|
||||||
gb->hram_io[IO_LY] = 0;
|
|
||||||
|
|
||||||
__gb_write(gb, 0xFF47, 0xFC); // BGP
|
|
||||||
__gb_write(gb, 0xFF48, 0xFF); // OBJP0
|
|
||||||
__gb_write(gb, 0xFF49, 0x0F); // OBJP1
|
|
||||||
gb->hram_io[IO_WY] = 0x00;
|
gb->hram_io[IO_WY] = 0x00;
|
||||||
gb->hram_io[IO_WX] = 0x00;
|
gb->hram_io[IO_WX] = 0x00;
|
||||||
gb->hram_io[IO_IE] = 0x00;
|
gb->hram_io[IO_IE] = 0x00;
|
||||||
|
gb->hram_io[IO_IF] = 0xE1;
|
||||||
gb->direct.joypad = 0xFF;
|
|
||||||
gb->hram_io[IO_JOYP] = 0xCF;
|
|
||||||
|
|
||||||
memset(gb->vram, 0x00, VRAM_SIZE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum gb_init_error_e gb_init(struct gb_s *gb,
|
enum gb_init_error_e gb_init(struct gb_s *gb,
|
||||||
@@ -3597,6 +3620,8 @@ enum gb_init_error_e gb_init(struct gb_s *gb,
|
|||||||
gb->gb_serial_tx = NULL;
|
gb->gb_serial_tx = NULL;
|
||||||
gb->gb_serial_rx = NULL;
|
gb->gb_serial_rx = NULL;
|
||||||
|
|
||||||
|
gb->gb_bios_read = NULL;
|
||||||
|
|
||||||
/* Check valid ROM using checksum value. */
|
/* Check valid ROM using checksum value. */
|
||||||
{
|
{
|
||||||
uint8_t x = 0;
|
uint8_t x = 0;
|
||||||
@@ -3673,6 +3698,12 @@ void gb_init_lcd(struct gb_s *gb,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void gb_set_bios(struct gb_s *gb,
|
||||||
|
uint8_t (*gb_bios_read)(struct gb_s*, const uint_fast16_t))
|
||||||
|
{
|
||||||
|
gb->gb_bios_read = gb_bios_read;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This was taken from SameBoy, which is released under MIT Licence.
|
* This was taken from SameBoy, which is released under MIT Licence.
|
||||||
*/
|
*/
|
||||||
@@ -3716,6 +3747,7 @@ void gb_set_rtc(struct gb_s *gb, const struct tm * const time)
|
|||||||
gb->cart_rtc[3] = time->tm_yday & 0xFF; /* Low 8 bits of day counter. */
|
gb->cart_rtc[3] = time->tm_yday & 0xFF; /* Low 8 bits of day counter. */
|
||||||
gb->cart_rtc[4] = time->tm_yday >> 8; /* High 1 bit of day counter. */
|
gb->cart_rtc[4] = time->tm_yday >> 8; /* High 1 bit of day counter. */
|
||||||
}
|
}
|
||||||
|
#endif // PEANUT_GB_HEADER_ONLY
|
||||||
|
|
||||||
/** Function prototypes: Required functions **/
|
/** Function prototypes: Required functions **/
|
||||||
/**
|
/**
|
||||||
@@ -3790,7 +3822,7 @@ void gb_init_lcd(struct gb_s *gb,
|
|||||||
* \param gb_serial_tx Pointer to function that transmits a byte of data over
|
* \param gb_serial_tx Pointer to function that transmits a byte of data over
|
||||||
* the serial connection. Must not be NULL.
|
* the serial connection. Must not be NULL.
|
||||||
* \param gb_serial_rx Pointer to function that receives a byte of data over the
|
* \param gb_serial_rx Pointer to function that receives a byte of data over the
|
||||||
* serial connection. If no byte is recieved,
|
* serial connection. If no byte is received,
|
||||||
* return GB_SERIAL_RX_NO_CONNECTION. Must not be NULL.
|
* return GB_SERIAL_RX_NO_CONNECTION. Must not be NULL.
|
||||||
*/
|
*/
|
||||||
void gb_init_serial(struct gb_s *gb,
|
void gb_init_serial(struct gb_s *gb,
|
||||||
@@ -3844,6 +3876,14 @@ void gb_tick_rtc(struct gb_s *gb);
|
|||||||
*/
|
*/
|
||||||
void gb_set_rtc(struct gb_s *gb, const struct tm * const time);
|
void gb_set_rtc(struct gb_s *gb, const struct tm * const time);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use BIOS on reset. gb_reset() must be called for this to take affect.
|
||||||
|
* \param gb An initialised emulator context. Must not be NULL.
|
||||||
|
* \param gb_bios_read Function pointer to read BIOS binary.
|
||||||
|
*/
|
||||||
|
void gb_set_bios(struct gb_s *gb,
|
||||||
|
uint8_t (*gb_bios_read)(struct gb_s*, const uint_fast16_t));
|
||||||
|
|
||||||
/* Undefine CPU Flag helper functions. */
|
/* Undefine CPU Flag helper functions. */
|
||||||
#undef PEANUT_GB_CPUFLAG_MASK_CARRY
|
#undef PEANUT_GB_CPUFLAG_MASK_CARRY
|
||||||
#undef PEANUT_GB_CPUFLAG_MASK_HALFC
|
#undef PEANUT_GB_CPUFLAG_MASK_HALFC
|
||||||
|
|||||||
Reference in New Issue
Block a user