diff --git a/Core/gb.c b/Core/gb.c index 7a607f2e..6e82c349 100755 --- a/Core/gb.c +++ b/Core/gb.c @@ -350,6 +350,11 @@ int GB_load_state(GB_gameboy_t *gb, const char *path) memcpy(gb, &save, sizeof(save)); errno = 0; + + if (gb->cartridge_type->has_rumble && gb->rumble_callback) { + gb->rumble_callback(gb, gb->rumble_state); + } + error: fclose(f); return errno; @@ -489,6 +494,11 @@ void GB_queue_infrared_input(GB_gameboy_t *gb, bool state, long cycles_after_pre gb->ir_queue[gb->ir_queue_length++] = (GB_ir_queue_item_t){state, cycles_after_previous_change}; } +void GB_set_rumble_callback(GB_gameboy_t *gb, GB_rumble_callback_t callback) +{ + gb->rumble_callback = callback; +} + 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 6cf4c630..9b1a64a9 100644 --- a/Core/gb.h +++ b/Core/gb.h @@ -161,6 +161,7 @@ typedef uint32_t (*GB_rgb_encode_callback_t)(GB_gameboy_t *gb, uint8_t r, uint8_ typedef void (*GB_infrared_callback_t)(GB_gameboy_t *gb, bool on, long cycles_since_last_update); 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 struct { enum { @@ -317,6 +318,7 @@ typedef struct GB_gameboy_s { uint16_t mbc_rom0_bank; /* For some MBC1 wirings. */ bool camera_registers_mapped; uint8_t camera_registers[0x36]; + bool rumble_state; ); @@ -415,6 +417,7 @@ typedef struct GB_gameboy_s { GB_infrared_callback_t infrared_callback; 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; /* IR */ long cycles_since_ir_change; @@ -493,4 +496,5 @@ void GB_set_rgb_encode_callback(GB_gameboy_t *gb, GB_rgb_encode_callback_t callb 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); #endif /* GB_h */ diff --git a/Core/memory.c b/Core/memory.c index 3c04264f..0ea1330b 100644 --- a/Core/memory.c +++ b/Core/memory.c @@ -317,6 +317,15 @@ static void write_mbc(GB_gameboy_t *gb, uint16_t addr, uint8_t value) case 0x2000: gb->mbc5.rom_bank_low = value; break; case 0x3000: gb->mbc5.rom_bank_high = value; break; case 0x4000: case 0x5000: + if (gb->cartridge_type->has_rumble) { + if (!!(value & 8) != gb->rumble_state) { + gb->rumble_state = !gb->rumble_state; + if (gb->rumble_callback) { + gb->rumble_callback(gb, gb->rumble_state); + } + } + value &= 7; + } gb->mbc5.ram_bank = value; gb->camera_registers_mapped = (value & 0x10) && gb->cartridge_type->mbc_subtype == GB_CAMERA; break;