diff --git a/Core/gb.c b/Core/gb.c index 69453b9..e512f21 100644 --- a/Core/gb.c +++ b/Core/gb.c @@ -466,6 +466,16 @@ void GB_set_rgb_encode_callback(GB_gameboy_t *gb, GB_rgb_encode_callback_t callb gb->rgb_encode_callback = callback; } +void GB_set_infrared_callback(GB_gameboy_t *gb, GB_infrared_callback_t callback) +{ + gb->infrared_callback = callback; +} + +void GB_set_infrared_input(GB_gameboy_t *gb, bool state) +{ + gb->infrared_input = state; +} + void GB_set_sample_rate(GB_gameboy_t *gb, unsigned int sample_rate) { if (gb->audio_buffer) { diff --git a/Core/gb.h b/Core/gb.h index 24fc291..563fef1 100644 --- a/Core/gb.h +++ b/Core/gb.h @@ -155,6 +155,7 @@ typedef void (*GB_vblank_callback_t)(GB_gameboy_t *gb); typedef void (*GB_log_callback_t)(GB_gameboy_t *gb, const char *string, GB_log_attributes attributes); typedef char *(*GB_input_callback_t)(GB_gameboy_t *gb); typedef uint32_t (*GB_rgb_encode_callback_t)(GB_gameboy_t *gb, uint8_t r, uint8_t g, uint8_t b); +typedef void (*GB_infrared_callback_t)(GB_gameboy_t *gb, bool on); typedef struct { enum { @@ -210,6 +211,10 @@ typedef struct GB_gameboy_s { bool halted; bool stopped; bool boot_rom_finished; + + /* Misc state*/ + /* IR */ + bool infrared_input; ); /* HDMA */ @@ -342,6 +347,7 @@ typedef struct GB_gameboy_s { GB_input_callback_t async_input_callback; GB_rgb_encode_callback_t rgb_encode_callback; GB_vblank_callback_t vblank_callback; + GB_infrared_callback_t infrared_callback; /*** Debugger ***/ bool debug_stopped; @@ -398,5 +404,6 @@ void GB_set_input_callback(GB_gameboy_t *gb, GB_input_callback_t callback); void GB_set_async_input_callback(GB_gameboy_t *gb, GB_input_callback_t callback); void GB_set_sample_rate(GB_gameboy_t *gb, unsigned int sample_rate); void GB_set_rgb_encode_callback(GB_gameboy_t *gb, GB_rgb_encode_callback_t callback); - +void GB_set_infrared_callback(GB_gameboy_t *gb, GB_infrared_callback_t callback); +void GB_set_infrared_input(GB_gameboy_t *gb, bool state); #endif /* GB_h */ diff --git a/Core/memory.c b/Core/memory.c index 647cd6f..490cd87 100644 --- a/Core/memory.c +++ b/Core/memory.c @@ -160,7 +160,16 @@ static uint8_t read_high_memory(GB_gameboy_t *gb, uint16_t addr) } return (gb->io_registers[GB_IO_KEY1] & 0x7F) | (gb->cgb_double_speed? 0xFE : 0x7E); - + case GB_IO_RP: { + if (!gb->is_cgb) return 0xFF; + /* You will read your own IR LED if it's on. */ + bool read_value = gb->infrared_input || (gb->io_registers[GB_IO_RP] & 1); + uint8_t ret = (gb->io_registers[GB_IO_RP] & 0xC1) | 0x3C; + if ((gb->io_registers[GB_IO_RP] & 0xC0) == 0xC0 && read_value) { + ret |= read_value; + } + return ret; + } default: if ((addr & 0xFF) >= GB_IO_NR10 && (addr & 0xFF) <= GB_IO_WAV_END) { return GB_apu_read(gb, addr & 0xFF); @@ -440,6 +449,19 @@ static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value) } return; + case GB_IO_RP: { + if (!gb->is_cgb) { + return; + } + if ((value & 1) != (gb->io_registers[GB_IO_RP] & 1)) { + if (gb->infrared_callback) { + gb->infrared_callback(gb, value & 1); + } + } + gb->io_registers[GB_IO_RP] = value; + return; + } + default: if ((addr & 0xFF) >= GB_IO_NR10 && (addr & 0xFF) <= GB_IO_WAV_END) { GB_apu_write(gb, addr & 0xFF, value);