mirror of https://github.com/bsnes-emu/bsnes.git
Improvements to IR API, since timing is VERY important
This commit is contained in:
parent
b740b7f3ba
commit
185e71fe12
11
Core/gb.c
11
Core/gb.c
|
@ -474,6 +474,17 @@ 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)
|
||||
{
|
||||
gb->infrared_input = state;
|
||||
gb->cycles_since_input_ir_change = 0;
|
||||
gb->ir_queue_length = 0;
|
||||
}
|
||||
|
||||
void GB_queue_infrared_input(GB_gameboy_t *gb, bool state, long cycles_after_previous_change)
|
||||
{
|
||||
if (gb->ir_queue_length == GB_MAX_IR_QUEUE) {
|
||||
GB_log(gb, "IR Queue is full\n");
|
||||
return;
|
||||
}
|
||||
gb->ir_queue[gb->ir_queue_length++] = (GB_ir_queue_item_t){state, cycles_after_previous_change};
|
||||
}
|
||||
|
||||
void GB_set_sample_rate(GB_gameboy_t *gb, unsigned int sample_rate)
|
||||
|
|
16
Core/gb.h
16
Core/gb.h
|
@ -28,6 +28,8 @@ enum {
|
|||
GB_ZERO_FLAG = 128,
|
||||
};
|
||||
|
||||
#define GB_MAX_IR_QUEUE 256
|
||||
|
||||
enum {
|
||||
/* Joypad and Serial */
|
||||
GB_IO_JOYP = 0x00, // Joypad (R/W)
|
||||
|
@ -155,7 +157,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 void (*GB_infrared_callback_t)(GB_gameboy_t *gb, bool on, long cycles_since_last_update);
|
||||
|
||||
typedef struct {
|
||||
enum {
|
||||
|
@ -172,6 +174,11 @@ typedef struct {
|
|||
bool has_rumble;
|
||||
} GB_cartridge_t;
|
||||
|
||||
typedef struct {
|
||||
bool state;
|
||||
long delay;
|
||||
} GB_ir_queue_item_t;
|
||||
|
||||
struct GB_breakpoint_s;
|
||||
struct GB_watchpoint_s;
|
||||
|
||||
|
@ -349,6 +356,12 @@ typedef struct GB_gameboy_s {
|
|||
GB_vblank_callback_t vblank_callback;
|
||||
GB_infrared_callback_t infrared_callback;
|
||||
|
||||
/* IR */
|
||||
long cycles_since_ir_change;
|
||||
long cycles_since_input_ir_change;
|
||||
GB_ir_queue_item_t ir_queue[GB_MAX_IR_QUEUE];
|
||||
size_t ir_queue_length;
|
||||
|
||||
/*** Debugger ***/
|
||||
bool debug_stopped;
|
||||
bool debug_fin_command, debug_next_command;
|
||||
|
@ -406,4 +419,5 @@ 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);
|
||||
void GB_queue_infrared_input(GB_gameboy_t *gb, bool state, long cycles_after_previous_change);
|
||||
#endif /* GB_h */
|
||||
|
|
|
@ -166,7 +166,7 @@ static uint8_t read_high_memory(GB_gameboy_t *gb, uint16_t addr)
|
|||
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;
|
||||
ret |= 2;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -455,7 +455,8 @@ static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
|
|||
}
|
||||
if ((value & 1) != (gb->io_registers[GB_IO_RP] & 1)) {
|
||||
if (gb->infrared_callback) {
|
||||
gb->infrared_callback(gb, value & 1);
|
||||
gb->infrared_callback(gb, value & 1, gb->cycles_since_ir_change);
|
||||
gb->cycles_since_ir_change = 0;
|
||||
}
|
||||
}
|
||||
gb->io_registers[GB_IO_RP] = value;
|
||||
|
|
|
@ -3,6 +3,17 @@
|
|||
#include "memory.h"
|
||||
#include "display.h"
|
||||
|
||||
static void GB_ir_run(GB_gameboy_t *gb)
|
||||
{
|
||||
if (gb->ir_queue_length == 0) return;
|
||||
if (gb->cycles_since_input_ir_change >= gb->ir_queue[0].delay) {
|
||||
gb->cycles_since_input_ir_change -= gb->ir_queue[0].delay;
|
||||
gb->infrared_input = gb->ir_queue[0].state;
|
||||
gb->ir_queue_length--;
|
||||
memmove(&gb->ir_queue[0], &gb->ir_queue[1], sizeof(gb->ir_queue[0]) * (gb->ir_queue_length));
|
||||
}
|
||||
}
|
||||
|
||||
void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles)
|
||||
{
|
||||
// Affected by speed boost
|
||||
|
@ -24,10 +35,13 @@ void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles)
|
|||
gb->hdma_cycles += cycles;
|
||||
gb->display_cycles += cycles;
|
||||
gb->apu_cycles += cycles;
|
||||
gb->cycles_since_ir_change += cycles;
|
||||
gb->cycles_since_input_ir_change += cycles;
|
||||
GB_hdma_run(gb);
|
||||
GB_timers_run(gb);
|
||||
GB_apu_run(gb);
|
||||
GB_display_run(gb);
|
||||
GB_ir_run(gb);
|
||||
}
|
||||
|
||||
void GB_timers_run(GB_gameboy_t *gb)
|
||||
|
|
Loading…
Reference in New Issue