Serial API

This commit is contained in:
Lior Halphon 2016-11-12 01:58:53 +02:00
parent 15f6412581
commit 22c34e1095
4 changed files with 54 additions and 2 deletions

View File

@ -503,6 +503,35 @@ void GB_set_rumble_callback(GB_gameboy_t *gb, GB_rumble_callback_t callback)
gb->rumble_callback = callback;
}
void GB_set_serial_transfer_start_callback(GB_gameboy_t *gb, GB_serial_transfer_start_callback_t callback)
{
gb->serial_transfer_start_callback = callback;
}
void GB_set_serial_transfer_end_callback(GB_gameboy_t *gb, GB_serial_transfer_end_callback_t callback)
{
gb->serial_transfer_end_callback = callback;
}
uint8_t GB_serial_get_data(GB_gameboy_t *gb)
{
if (gb->io_registers[GB_IO_SC] & 1) {
/* Internal Clock */
GB_log(gb, "Serial read request while using internal clock. \n");
return 0xFF;
}
return gb->io_registers[GB_IO_SB];
}
void GB_serial_set_data(GB_gameboy_t *gb, uint8_t data)
{
if (gb->io_registers[GB_IO_SC] & 1) {
/* Internal Clock */
GB_log(gb, "Serial write request while using internal clock. \n");
return;
}
gb->io_registers[GB_IO_SB] = data;
}
void GB_set_sample_rate(GB_gameboy_t *gb, unsigned int sample_rate)
{
if (gb->audio_buffer) {

View File

@ -162,6 +162,9 @@ typedef void (*GB_infrared_callback_t)(GB_gameboy_t *gb, bool on, long cycles_si
typedef uint8_t (*GB_camera_get_pixel_callback_t)(GB_gameboy_t *gb, uint8_t x, uint8_t y);
typedef void (*GB_camera_update_request_callback_t)(GB_gameboy_t *gb);
typedef void (*GB_rumble_callback_t)(GB_gameboy_t *gb, bool rumble_on);
typedef void (*GB_serial_transfer_start_callback_t)(GB_gameboy_t *gb, uint8_t byte_to_send);
typedef uint8_t (*GB_serial_transfer_end_callback_t)(GB_gameboy_t *gb);
typedef struct {
enum {
@ -418,7 +421,8 @@ typedef struct GB_gameboy_s {
GB_camera_get_pixel_callback_t camera_get_pixel_callback;
GB_camera_update_request_callback_t camera_update_request_callback;
GB_rumble_callback_t rumble_callback;
GB_serial_transfer_start_callback_t serial_transfer_start_callback;
GB_serial_transfer_end_callback_t serial_transfer_end_callback;
/* IR */
long cycles_since_ir_change;
long cycles_since_input_ir_change;
@ -497,4 +501,13 @@ 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);
void GB_set_rumble_callback(GB_gameboy_t *gb, GB_rumble_callback_t callback);
/* These APIs are used when using internal clock */
void GB_set_serial_transfer_start_callback(GB_gameboy_t *gb, GB_serial_transfer_start_callback_t callback);
void GB_set_serial_transfer_end_callback(GB_gameboy_t *gb, GB_serial_transfer_end_callback_t callback);
/* These APIs are used when using external clock */
uint8_t GB_serial_get_data(GB_gameboy_t *gb);
void GB_serial_set_data(GB_gameboy_t *gb, uint8_t data);
#endif /* GB_h */

View File

@ -576,6 +576,9 @@ static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
gb->io_registers[GB_IO_SC] = value | (~0x83);
if ((value & 0x80) && (value & 0x1) ) {
gb->serial_cycles = gb->cgb_mode && (value & 2)? 128 : 4096;
if (gb->serial_transfer_start_callback) {
gb->serial_transfer_start_callback(gb, gb->io_registers[GB_IO_SB]);
}
}
else {
gb->serial_cycles = 0;

View File

@ -45,7 +45,14 @@ void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles)
if (gb->serial_cycles <= cycles) {
gb->serial_cycles = 0;
gb->io_registers[GB_IO_SC] &= ~0x80;
gb->io_registers[GB_IO_SB] = 0xFF;
/* TODO: Does SB "update" bit by bit? */
if (gb->serial_transfer_end_callback) {
gb->io_registers[GB_IO_SB] = gb->serial_transfer_end_callback(gb);
}
else {
gb->io_registers[GB_IO_SB] = 0xFF;
}
gb->io_registers[GB_IO_IF] |= 8;
}
else {