Improvements to IR API, since timing is VERY important

This commit is contained in:
Lior Halphon 2016-07-21 01:03:13 +03:00
parent b740b7f3ba
commit 185e71fe12
4 changed files with 43 additions and 3 deletions

View File

@ -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)

View File

@ -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 */

View File

@ -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;

View File

@ -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)