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)
|
void GB_set_infrared_input(GB_gameboy_t *gb, bool state)
|
||||||
{
|
{
|
||||||
gb->infrared_input = 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)
|
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,
|
GB_ZERO_FLAG = 128,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define GB_MAX_IR_QUEUE 256
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
/* Joypad and Serial */
|
/* Joypad and Serial */
|
||||||
GB_IO_JOYP = 0x00, // Joypad (R/W)
|
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 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 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 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 {
|
typedef struct {
|
||||||
enum {
|
enum {
|
||||||
@ -172,6 +174,11 @@ typedef struct {
|
|||||||
bool has_rumble;
|
bool has_rumble;
|
||||||
} GB_cartridge_t;
|
} GB_cartridge_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool state;
|
||||||
|
long delay;
|
||||||
|
} GB_ir_queue_item_t;
|
||||||
|
|
||||||
struct GB_breakpoint_s;
|
struct GB_breakpoint_s;
|
||||||
struct GB_watchpoint_s;
|
struct GB_watchpoint_s;
|
||||||
|
|
||||||
@ -349,6 +356,12 @@ typedef struct GB_gameboy_s {
|
|||||||
GB_vblank_callback_t vblank_callback;
|
GB_vblank_callback_t vblank_callback;
|
||||||
GB_infrared_callback_t infrared_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 ***/
|
/*** Debugger ***/
|
||||||
bool debug_stopped;
|
bool debug_stopped;
|
||||||
bool debug_fin_command, debug_next_command;
|
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_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_callback(GB_gameboy_t *gb, GB_infrared_callback_t callback);
|
||||||
void GB_set_infrared_input(GB_gameboy_t *gb, bool state);
|
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 */
|
#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);
|
bool read_value = gb->infrared_input || (gb->io_registers[GB_IO_RP] & 1);
|
||||||
uint8_t ret = (gb->io_registers[GB_IO_RP] & 0xC1) | 0x3C;
|
uint8_t ret = (gb->io_registers[GB_IO_RP] & 0xC1) | 0x3C;
|
||||||
if ((gb->io_registers[GB_IO_RP] & 0xC0) == 0xC0 && read_value) {
|
if ((gb->io_registers[GB_IO_RP] & 0xC0) == 0xC0 && read_value) {
|
||||||
ret |= read_value;
|
ret |= 2;
|
||||||
}
|
}
|
||||||
return ret;
|
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 ((value & 1) != (gb->io_registers[GB_IO_RP] & 1)) {
|
||||||
if (gb->infrared_callback) {
|
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;
|
gb->io_registers[GB_IO_RP] = value;
|
||||||
|
@ -3,6 +3,17 @@
|
|||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "display.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)
|
void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles)
|
||||||
{
|
{
|
||||||
// Affected by speed boost
|
// Affected by speed boost
|
||||||
@ -24,10 +35,13 @@ void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles)
|
|||||||
gb->hdma_cycles += cycles;
|
gb->hdma_cycles += cycles;
|
||||||
gb->display_cycles += cycles;
|
gb->display_cycles += cycles;
|
||||||
gb->apu_cycles += cycles;
|
gb->apu_cycles += cycles;
|
||||||
|
gb->cycles_since_ir_change += cycles;
|
||||||
|
gb->cycles_since_input_ir_change += cycles;
|
||||||
GB_hdma_run(gb);
|
GB_hdma_run(gb);
|
||||||
GB_timers_run(gb);
|
GB_timers_run(gb);
|
||||||
GB_apu_run(gb);
|
GB_apu_run(gb);
|
||||||
GB_display_run(gb);
|
GB_display_run(gb);
|
||||||
|
GB_ir_run(gb);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GB_timers_run(GB_gameboy_t *gb)
|
void GB_timers_run(GB_gameboy_t *gb)
|
||||||
|
Loading…
Reference in New Issue
Block a user