From fbf1bb7f981978e58afc2ac94a81c9a76d4a8cba Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Sun, 7 Nov 2021 01:10:58 +0200 Subject: [PATCH] Save state compatibility breaking cleanup --- Cocoa/Document.m | 2 + Core/apu.c | 104 ++++++++++++++-------------- Core/apu.h | 43 +++++------- Core/debugger.c | 10 +-- Core/display.c | 14 ++-- Core/display.h | 1 - Core/gb.c | 145 +++++++++++++++++++-------------------- Core/gb.h | 35 +++++----- Core/mbc.c | 8 +-- Core/memory.c | 109 ++++++++++++++--------------- Core/save_state.c | 117 +++++-------------------------- Core/sgb.h | 10 +-- Core/sm83_cpu.c | 16 ++--- Core/sm83_disassembler.c | 4 +- Core/symbol_hash.c | 6 +- Core/timing.c | 41 ++++------- Core/timing.h | 1 + 17 files changed, 280 insertions(+), 386 deletions(-) diff --git a/Cocoa/Document.m b/Cocoa/Document.m index c757ce1..39f0852 100644 --- a/Cocoa/Document.m +++ b/Cocoa/Document.m @@ -12,6 +12,8 @@ #include "BigSurToolbar.h" #import "GBPaletteEditorController.h" +#define GB_MODEL_PAL_BIT_OLD 0x1000 + /* Todo: The general Objective-C coding style conflicts with SameBoy's. This file needs a cleanup. */ /* Todo: Split into category files! This is so messy!!! */ diff --git a/Core/apu.c b/Core/apu.c index aac87b5..8386b91 100644 --- a/Core/apu.c +++ b/Core/apu.c @@ -280,7 +280,7 @@ static void render(GB_gameboy_t *gb) static void update_square_sample(GB_gameboy_t *gb, unsigned index) { - if (gb->apu.square_channels[index].current_sample_index & 0x80) return; + if (gb->apu.square_channels[index].sample_surpressed) return; uint8_t duty = gb->io_registers[index == GB_SQUARE_1? GB_IO_NR11 :GB_IO_NR21] >> 6; update_sample(gb, index, @@ -377,7 +377,7 @@ static void tick_square_envelope(GB_gameboy_t *gb, enum GB_CHANNELS index) { uint8_t nrx2 = gb->io_registers[index == GB_SQUARE_1? GB_IO_NR12 : GB_IO_NR22]; - if (gb->apu.square_envelope_clock[index].locked) return; + if (gb->apu.square_channels[index].envelope_clock.locked) return; if (!(nrx2 & 7)) return; if (gb->cgb_double_speed) { if (index == GB_SQUARE_1) { @@ -393,7 +393,7 @@ static void tick_square_envelope(GB_gameboy_t *gb, enum GB_CHANNELS index) gb->apu.square_channels[index].current_volume++; } else { - gb->apu.square_envelope_clock[index].locked = true; + gb->apu.square_channels[index].envelope_clock.locked = true; } } else { @@ -401,7 +401,7 @@ static void tick_square_envelope(GB_gameboy_t *gb, enum GB_CHANNELS index) gb->apu.square_channels[index].current_volume--; } else { - gb->apu.square_envelope_clock[index].locked = true; + gb->apu.square_channels[index].envelope_clock.locked = true; } } @@ -414,7 +414,7 @@ static void tick_noise_envelope(GB_gameboy_t *gb) { uint8_t nr42 = gb->io_registers[GB_IO_NR42]; - if (gb->apu.noise_envelope_clock.locked) return; + if (gb->apu.noise_channel.envelope_clock.locked) return; if (!(nr42 & 7)) return; if (gb->cgb_double_speed) { @@ -426,7 +426,7 @@ static void tick_noise_envelope(GB_gameboy_t *gb) gb->apu.noise_channel.current_volume++; } else { - gb->apu.noise_envelope_clock.locked = true; + gb->apu.noise_channel.envelope_clock.locked = true; } } else { @@ -434,7 +434,7 @@ static void tick_noise_envelope(GB_gameboy_t *gb) gb->apu.noise_channel.current_volume--; } else { - gb->apu.noise_envelope_clock.locked = true; + gb->apu.noise_channel.envelope_clock.locked = true; } } @@ -486,27 +486,27 @@ void GB_apu_div_event(GB_gameboy_t *gb) if ((gb->apu.div_divider & 7) == 7) { unrolled for (unsigned i = GB_SQUARE_2 + 1; i--;) { - if (!gb->apu.square_envelope_clock[i].clock) { + if (!gb->apu.square_channels[i].envelope_clock.clock) { gb->apu.square_channels[i].volume_countdown--; gb->apu.square_channels[i].volume_countdown &= 7; } } - if (!gb->apu.noise_envelope_clock.clock) { + if (!gb->apu.noise_channel.envelope_clock.clock) { gb->apu.noise_channel.volume_countdown--; gb->apu.noise_channel.volume_countdown &= 7; } } unrolled for (unsigned i = GB_SQUARE_2 + 1; i--;) { - if (gb->apu.square_envelope_clock[i].clock) { + if (gb->apu.square_channels[i].envelope_clock.clock) { tick_square_envelope(gb, i); - gb->apu.square_envelope_clock[i].clock = false; + gb->apu.square_channels[i].envelope_clock.clock = false; } } - if (gb->apu.noise_envelope_clock.clock) { + if (gb->apu.noise_channel.envelope_clock.clock) { tick_noise_envelope(gb); - gb->apu.noise_envelope_clock.clock = false; + gb->apu.noise_channel.envelope_clock.clock = false; } if ((gb->apu.div_divider & 1) == 1) { @@ -562,12 +562,12 @@ void GB_apu_div_secondary_event(GB_gameboy_t *gb) unrolled for (unsigned i = GB_SQUARE_2 + 1; i--;) { uint8_t nrx2 = gb->io_registers[i == GB_SQUARE_1? GB_IO_NR12 : GB_IO_NR22]; if (gb->apu.is_active[i] && gb->apu.square_channels[i].volume_countdown == 0) { - gb->apu.square_envelope_clock[i].clock = (gb->apu.square_channels[i].volume_countdown = nrx2 & 7); + gb->apu.square_channels[i].envelope_clock.clock = (gb->apu.square_channels[i].volume_countdown = nrx2 & 7); } } if (gb->apu.is_active[GB_NOISE] && gb->apu.noise_channel.volume_countdown == 0) { - gb->apu.noise_envelope_clock.clock = (gb->apu.noise_channel.volume_countdown = gb->io_registers[GB_IO_NR42] & 7); + gb->apu.noise_channel.envelope_clock.clock = (gb->apu.noise_channel.volume_countdown = gb->io_registers[GB_IO_NR42] & 7); } } @@ -585,10 +585,10 @@ static void step_lfsr(GB_gameboy_t *gb, unsigned cycles_offset) gb->apu.noise_channel.lfsr &= ~high_bit_mask; } - gb->apu.current_lfsr_sample = gb->apu.noise_channel.lfsr & 1; + gb->apu.noise_channel.current_lfsr_sample = gb->apu.noise_channel.lfsr & 1; if (gb->apu.is_active[GB_NOISE]) { update_sample(gb, GB_NOISE, - gb->apu.current_lfsr_sample ? + gb->apu.noise_channel.current_lfsr_sample ? gb->apu.noise_channel.current_volume : 0, cycles_offset); } @@ -601,26 +601,26 @@ void GB_apu_run(GB_gameboy_t *gb) gb->apu.apu_cycles = 0; if (!cycles) return; - if (unlikely(gb->apu.channel_3_delayed_bugged_read)) { - gb->apu.channel_3_delayed_bugged_read = false; + if (unlikely(gb->apu.wave_channel.delayed_bugged_read)) { + gb->apu.wave_channel.delayed_bugged_read = false; gb->apu.wave_channel.current_sample_byte = gb->io_registers[GB_IO_WAV_START + (gb->address_bus & 0xF)]; } bool start_ch4 = false; if (likely(!gb->stopped || GB_is_cgb(gb))) { - if (gb->apu.channel_4_dmg_delayed_start) { - if (gb->apu.channel_4_dmg_delayed_start == cycles) { - gb->apu.channel_4_dmg_delayed_start = 0; + if (gb->apu.noise_channel.dmg_delayed_start) { + if (gb->apu.noise_channel.dmg_delayed_start == cycles) { + gb->apu.noise_channel.dmg_delayed_start = 0; start_ch4 = true; } - else if (gb->apu.channel_4_dmg_delayed_start > cycles) { - gb->apu.channel_4_dmg_delayed_start -= cycles; + else if (gb->apu.noise_channel.dmg_delayed_start > cycles) { + gb->apu.noise_channel.dmg_delayed_start -= cycles; } else { /* Split it into two */ - cycles -= gb->apu.channel_4_dmg_delayed_start; - gb->apu.apu_cycles = gb->apu.channel_4_dmg_delayed_start * 4; + cycles -= gb->apu.noise_channel.dmg_delayed_start; + gb->apu.apu_cycles = gb->apu.noise_channel.dmg_delayed_start * 4; GB_apu_run(gb); } } @@ -669,6 +669,7 @@ void GB_apu_run(GB_gameboy_t *gb) gb->apu.square_channels[i].sample_countdown = (gb->apu.square_channels[i].sample_length ^ 0x7FF) * 2 + 1; gb->apu.square_channels[i].current_sample_index++; gb->apu.square_channels[i].current_sample_index &= 0x7; + gb->apu.square_channels[i].sample_surpressed = false; if (cycles_left == 0 && gb->apu.samples[i] == 0) { gb->apu.pcm_mask[0] &= i == GB_SQUARE_1? 0xF0 : 0x0F; } @@ -699,7 +700,7 @@ void GB_apu_run(GB_gameboy_t *gb) gb->apu.wave_channel.wave_form_just_read = false; } } - else if (gb->apu.wave_channel.enable && gb->apu.channel_3_pulsed && gb->model < GB_MODEL_AGB) { + else if (gb->apu.wave_channel.enable && gb->apu.wave_channel.pulsed && gb->model < GB_MODEL_AGB) { uint8_t cycles_left = cycles; while (unlikely(cycles_left > gb->apu.wave_channel.sample_countdown)) { cycles_left -= gb->apu.wave_channel.sample_countdown + 1; @@ -709,7 +710,7 @@ void GB_apu_run(GB_gameboy_t *gb) gb->io_registers[GB_IO_WAV_START + (gb->address_bus & 0xF)]; } else { - gb->apu.channel_3_delayed_bugged_read = true; + gb->apu.wave_channel.delayed_bugged_read = true; } } if (cycles_left) { @@ -727,8 +728,8 @@ void GB_apu_run(GB_gameboy_t *gb) } while (unlikely(cycles_left >= gb->apu.noise_channel.counter_countdown)) { cycles_left -= gb->apu.noise_channel.counter_countdown; - gb->apu.noise_channel.counter_countdown = divisor + gb->apu.channel_4_delta; - gb->apu.channel_4_delta = 0; + gb->apu.noise_channel.counter_countdown = divisor + gb->apu.noise_channel.delta; + gb->apu.noise_channel.delta = 0; bool old_bit = (gb->apu.noise_channel.counter >> (gb->io_registers[GB_IO_NR43] >> 4)) & 1; gb->apu.noise_channel.counter++; gb->apu.noise_channel.counter &= 0x3FFF; @@ -744,10 +745,10 @@ void GB_apu_run(GB_gameboy_t *gb) } if (cycles_left) { gb->apu.noise_channel.counter_countdown -= cycles_left; - gb->apu.channel_4_countdown_reloaded = false; + gb->apu.noise_channel.countdown_reloaded = false; } else { - gb->apu.channel_4_countdown_reloaded = true; + gb->apu.noise_channel.countdown_reloaded = true; } } } @@ -1037,7 +1038,7 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value) else if (gb->apu.is_active[index]) { nrx2_glitch(gb, &gb->apu.square_channels[index].current_volume, value, gb->io_registers[reg], &gb->apu.square_channels[index].volume_countdown, - &gb->apu.square_envelope_clock[index]); + &gb->apu.square_channels[index].envelope_clock); update_square_sample(gb, index); } @@ -1066,6 +1067,7 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value) if (gb->apu.square_channels[index].sample_countdown >> 1 == (gb->apu.square_channels[index].sample_length ^ 0x7FF)) { gb->apu.square_channels[index].current_sample_index--; gb->apu.square_channels[index].current_sample_index &= 7; + gb->apu.square_channels[index].sample_surpressed = false; } } } @@ -1076,8 +1078,8 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value) if (value & 0x80) { /* Current sample index remains unchanged when restarting channels 1 or 2. It is only reset by turning the APU off. */ - gb->apu.square_envelope_clock[index].locked = false; - gb->apu.square_envelope_clock[index].clock = false; + gb->apu.square_channels[index].envelope_clock.locked = false; + gb->apu.square_channels[index].envelope_clock.clock = false; if (!gb->apu.is_active[index]) { gb->apu.square_channels[index].sample_countdown = (gb->apu.square_channels[index].sample_length ^ 0x7FF) * 2 + 6 - gb->apu.lf_div; if (gb->model <= GB_MODEL_CGB_C && gb->apu.lf_div) { @@ -1090,11 +1092,12 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value) if (!(value & 4) && !(((gb->apu.square_channels[index].sample_countdown - 1) / 2) & 0x400)) { gb->apu.square_channels[index].current_sample_index++; gb->apu.square_channels[index].current_sample_index &= 0x7; + gb->apu.square_channels[index].sample_surpressed = false; } /* Todo: verify with the schematics what's going on in here */ else if (gb->apu.square_channels[index].sample_length == 0x7FF && old_sample_length != 0x7FF && - (gb->apu.square_channels[index].current_sample_index & 0x80)) { + (gb->apu.square_channels[index].sample_surpressed)) { extra_delay += 2; } } @@ -1117,8 +1120,7 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value) if ((gb->io_registers[index == GB_SQUARE_1 ? GB_IO_NR12 : GB_IO_NR22] & 0xF8) != 0 && !gb->apu.is_active[index]) { gb->apu.is_active[index] = true; update_sample(gb, index, 0, 0); - /* We use the highest bit in current_sample_index to mark this sample is not actually playing yet, */ - gb->apu.square_channels[index].current_sample_index |= 0x80; + gb->apu.square_channels[index].sample_surpressed = true; } if (gb->apu.square_channels[index].pulse_length == 0) { gb->apu.square_channels[index].pulse_length = 0x40; @@ -1182,7 +1184,7 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value) case GB_IO_NR30: gb->apu.wave_channel.enable = value & 0x80; if (!gb->apu.wave_channel.enable) { - gb->apu.channel_3_pulsed = false; + gb->apu.wave_channel.pulsed = false; if (gb->apu.is_active[GB_WAVE]) { // Todo: I assume this happens on pre-CGB models; test this with an audible test if (gb->apu.wave_channel.sample_countdown == 0 && gb->model < GB_MODEL_AGB) { @@ -1213,7 +1215,7 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value) gb->apu.wave_channel.sample_length &= 0xFF; gb->apu.wave_channel.sample_length |= (value & 7) << 8; if (value & 0x80) { - gb->apu.channel_3_pulsed = true; + gb->apu.wave_channel.pulsed = true; /* DMG bug: wave RAM gets corrupted if the channel is retriggerred 1 cycle before the APU reads from it. */ if (!GB_is_cgb(gb) && @@ -1295,9 +1297,9 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value) else if (gb->apu.is_active[GB_NOISE]) { nrx2_glitch(gb, &gb->apu.noise_channel.current_volume, value, gb->io_registers[reg], &gb->apu.noise_channel.volume_countdown, - &gb->apu.noise_envelope_clock); + &gb->apu.noise_channel.envelope_clock); update_sample(gb, GB_NOISE, - gb->apu.current_lfsr_sample ? + gb->apu.noise_channel.current_lfsr_sample ? gb->apu.noise_channel.current_volume : 0, 0); } @@ -1310,7 +1312,7 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value) bool old_bit = (effective_counter >> (gb->io_registers[GB_IO_NR43] >> 4)) & 1; gb->io_registers[GB_IO_NR43] = value; bool new_bit = (effective_counter >> (gb->io_registers[GB_IO_NR43] >> 4)) & 1; - if (gb->apu.channel_4_countdown_reloaded) { + if (gb->apu.noise_channel.countdown_reloaded) { unsigned divisor = (gb->io_registers[GB_IO_NR43] & 0x07) << 2; if (!divisor) divisor = 2; if (gb->model > GB_MODEL_CGB_C) { @@ -1321,7 +1323,7 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value) gb->apu.noise_channel.counter_countdown = divisor + (divisor == 2? 0 : (uint8_t[]){2, 1, 4, 3}[(gb->apu.noise_channel.alignment) & 3]); } - gb->apu.channel_4_delta = 0; + gb->apu.noise_channel.delta = 0; } /* Step LFSR */ if (new_bit && (!old_bit || gb->model <= GB_MODEL_CGB_C)) { @@ -1340,15 +1342,15 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value) case GB_IO_NR44: { if (value & 0x80) { - gb->apu.noise_envelope_clock.locked = false; - gb->apu.noise_envelope_clock.clock = false; + gb->apu.noise_channel.envelope_clock.locked = false; + gb->apu.noise_channel.envelope_clock.clock = false; if (!GB_is_cgb(gb) && (gb->apu.noise_channel.alignment & 3) != 0) { - gb->apu.channel_4_dmg_delayed_start = 6; + gb->apu.noise_channel.dmg_delayed_start = 6; } else { unsigned divisor = (gb->io_registers[GB_IO_NR43] & 0x07) << 2; if (!divisor) divisor = 2; - gb->apu.channel_4_delta = 0; + gb->apu.noise_channel.delta = 0; gb->apu.noise_channel.counter_countdown = divisor + 4; if (divisor == 2) { if (gb->model <= GB_MODEL_CGB_C) { @@ -1371,7 +1373,7 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value) if (((gb->apu.noise_channel.alignment + 1) & 3) < 2) { if ((gb->io_registers[GB_IO_NR43] & 0x07) == 1) { gb->apu.noise_channel.counter_countdown -= 2; - gb->apu.channel_4_delta = 2; + gb->apu.noise_channel.delta = 2; } else { gb->apu.noise_channel.counter_countdown -= 4; @@ -1401,12 +1403,12 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value) cases. */ if (gb->apu.is_active[GB_NOISE]) { update_sample(gb, GB_NOISE, - gb->apu.current_lfsr_sample ? + gb->apu.noise_channel.current_lfsr_sample ? gb->apu.noise_channel.current_volume : 0, 0); } gb->apu.noise_channel.lfsr = 0; - gb->apu.current_lfsr_sample = false; + gb->apu.noise_channel.current_lfsr_sample = false; gb->apu.noise_channel.volume_countdown = gb->io_registers[GB_IO_NR42] & 7; if (!gb->apu.is_active[GB_NOISE] && (gb->io_registers[GB_IO_NR42] & 0xF8) != 0) { diff --git a/Core/apu.h b/Core/apu.h index ead4088..ad1e197 100644 --- a/Core/apu.h +++ b/Core/apu.h @@ -75,19 +75,20 @@ typedef struct uint16_t shadow_sweep_sample_length; bool unshifted_sweep; bool enable_zombie_calculate_stepping; - + + uint8_t channel_1_restart_hold; + uint16_t channel1_completed_addend; struct { uint16_t pulse_length; // Reloaded from NRX1 (xorred), in 256Hz DIV ticks uint8_t current_volume; // Reloaded from NRX2 uint8_t volume_countdown; // Reloaded from NRX2 - uint8_t current_sample_index; /* For save state compatibility, - highest bit is reused (See NR14/NR24's - write code)*/ + uint8_t current_sample_index; + bool sample_surpressed; uint16_t sample_countdown; // in APU ticks (Reloaded from sample_length, xorred $7FF) uint16_t sample_length; // From NRX3, NRX4, in APU ticks bool length_enabled; // NRX4 - + GB_envelope_clock_t envelope_clock; } square_channels[2]; struct { @@ -100,9 +101,9 @@ typedef struct uint16_t sample_countdown; // in APU ticks (Reloaded from sample_length, xorred $7FF) uint8_t current_sample_index; uint8_t current_sample_byte; // Current sample byte. - - GB_PADDING(int8_t, wave_form)[32]; bool wave_form_just_read; + bool pulsed; + bool delayed_bugged_read; } wave_channel; struct { @@ -113,32 +114,24 @@ typedef struct bool narrow; uint8_t counter_countdown; // Counts from 0-7 to 0 to tick counter (Scaled from 512KHz to 2MHz) - uint8_t __padding; uint16_t counter; // A bit from this 14-bit register ticks LFSR bool length_enabled; // NR44 uint8_t alignment; // If (NR43 & 7) != 0, samples are aligned to 512KHz clock instead of // 1MHz. This variable keeps track of the alignment. - + bool current_lfsr_sample; + int8_t delta; + bool countdown_reloaded; + uint8_t dmg_delayed_start; + GB_envelope_clock_t envelope_clock; } noise_channel; - /* Todo: merge these into their structs when breaking save state compatibility */ -#define GB_SKIP_DIV_EVENT_INACTIVE 0 -#define GB_SKIP_DIV_EVENT_SKIPPED 1 -#define GB_SKIP_DIV_EVENT_SKIP 2 - uint8_t skip_div_event; - bool current_lfsr_sample; + enum { + GB_SKIP_DIV_EVENT_INACTIVE, + GB_SKIP_DIV_EVENT_SKIPPED, + GB_SKIP_DIV_EVENT_SKIP, + } skip_div_event:8; uint8_t pcm_mask[2]; // For CGB-0 to CGB-C PCM read glitch - uint8_t channel_1_restart_hold; - int8_t channel_4_delta; - bool channel_4_countdown_reloaded; - uint8_t channel_4_dmg_delayed_start; - uint16_t channel1_completed_addend; - - GB_envelope_clock_t square_envelope_clock[2]; - GB_envelope_clock_t noise_envelope_clock; - bool channel_3_pulsed; - bool channel_3_delayed_bugged_read; } GB_apu_t; typedef enum { diff --git a/Core/debugger.c b/Core/debugger.c index db4b02f..80f4d46 100644 --- a/Core/debugger.c +++ b/Core/debugger.c @@ -1771,8 +1771,8 @@ static bool apu(GB_gameboy_t *gb, char *arguments, char *modifiers, const debugg GB_log(gb, " Duty cycle %s%% (%s), current index %u/8%s\n", duty > 3? "" : (const char *[]){"12.5", " 25", " 50", " 75"}[duty], duty > 3? "" : (const char *[]){"_______-", "-______-", "-____---", "_------_"}[duty], - gb->apu.square_channels[channel].current_sample_index & 0x7f, - gb->apu.square_channels[channel].current_sample_index >> 7 ? " (suppressed)" : ""); + gb->apu.square_channels[channel].current_sample_index, + gb->apu.square_channels[channel].sample_surpressed ? " (suppressed)" : ""); if (channel == GB_SQUARE_1) { GB_log(gb, " Frequency sweep %s and %s\n", @@ -2541,7 +2541,7 @@ static bool is_in_trivial_memory(uint16_t addr) return false; } -typedef uint16_t GB_opcode_address_getter_t(GB_gameboy_t *gb, uint8_t opcode); +typedef uint16_t opcode_address_getter_t(GB_gameboy_t *gb, uint8_t opcode); uint16_t trivial_1(GB_gameboy_t *gb, uint8_t opcode) { @@ -2631,7 +2631,7 @@ static uint16_t jp_hl(GB_gameboy_t *gb, uint8_t opcode) return gb->hl; } -static GB_opcode_address_getter_t *opcodes[256] = { +static opcode_address_getter_t *opcodes[256] = { /* X0 X1 X2 X3 X4 X5 X6 X7 */ /* X8 X9 Xa Xb Xc Xd Xe Xf */ trivial_1, trivial_3, trivial_1, trivial_1, trivial_1, trivial_1, trivial_2, trivial_1, /* 0X */ @@ -2709,7 +2709,7 @@ static jump_to_return_t test_jump_to_breakpoints(GB_gameboy_t *gb, uint16_t *add return JUMP_TO_NONE; } - GB_opcode_address_getter_t *getter = opcodes[opcode]; + opcode_address_getter_t *getter = opcodes[opcode]; if (!getter) { gb->n_watchpoints = n_watchpoints; return JUMP_TO_NONE; diff --git a/Core/display.c b/Core/display.c index 83a499f..46fd672 100644 --- a/Core/display.c +++ b/Core/display.c @@ -107,7 +107,7 @@ typedef struct __attribute__((packed)) { uint8_t x; uint8_t tile; uint8_t flags; -} GB_object_t; +} object_t; static void display_vblank(GB_gameboy_t *gb) { @@ -470,7 +470,7 @@ static void add_object_from_index(GB_gameboy_t *gb, unsigned index) } /* This reverse sorts the visible objects by location and priority */ - GB_object_t *objects = (GB_object_t *) &gb->oam; + object_t *objects = (object_t *) &gb->oam; bool height_16 = (gb->io_registers[GB_IO_LCDC] & 4) != 0; signed y = objects[index].y - 16; if (y <= gb->current_line && y + (height_16? 16 : 8) > gb->current_line) { @@ -825,11 +825,11 @@ static void advance_fetcher_state_machine(GB_gameboy_t *gb) } } -static uint16_t get_object_line_address(GB_gameboy_t *gb, const GB_object_t *object) +static uint16_t get_object_line_address(GB_gameboy_t *gb, const object_t *object) { /* TODO: what does the PPU read if DMA is active? */ if (gb->oam_ppu_blocked) { - static const GB_object_t blocked = {0xFF, 0xFF, 0xFF, 0xFF}; + static const object_t blocked = {0xFF, 0xFF, 0xFF, 0xFF}; object = &blocked; } @@ -864,7 +864,7 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles) } return; } - GB_object_t *objects = (GB_object_t *) &gb->oam; + object_t *objects = (object_t *) &gb->oam; GB_STATE_MACHINE(gb, display, cycles, 2) { GB_STATE(gb, display, 1); @@ -1208,7 +1208,7 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles) gb->cycles_for_line++; GB_SLEEP(gb, display, 40, 1); - const GB_object_t *object = &objects[gb->visible_objs[gb->n_visible_objs - 1]]; + const object_t *object = &objects[gb->visible_objs[gb->n_visible_objs - 1]]; uint16_t line_address = get_object_line_address(gb, object); @@ -1553,7 +1553,7 @@ uint8_t GB_get_oam_info(GB_gameboy_t *gb, GB_oam_info_t *dest, uint8_t *sprite_h *sprite_height = (gb->io_registers[GB_IO_LCDC] & 4) ? 16:8; uint8_t oam_to_dest_index[40] = {0,}; for (signed y = 0; y < LINES; y++) { - GB_object_t *sprite = (GB_object_t *) &gb->oam; + object_t *sprite = (object_t *) &gb->oam; uint8_t sprites_in_line = 0; for (uint8_t i = 0; i < 40; i++, sprite++) { signed sprite_y = sprite->y - 16; diff --git a/Core/display.h b/Core/display.h index c9411dc..085985d 100644 --- a/Core/display.h +++ b/Core/display.h @@ -12,7 +12,6 @@ void GB_STAT_update(GB_gameboy_t *gb); void GB_lcd_off(GB_gameboy_t *gb); enum { - GB_OBJECT_PRIORITY_UNDEFINED, // For save state compatibility GB_OBJECT_PRIORITY_X, GB_OBJECT_PRIORITY_INDEX, }; diff --git a/Core/gb.c b/Core/gb.c index 0c47ce9..9662663 100644 --- a/Core/gb.c +++ b/Core/gb.c @@ -753,7 +753,7 @@ typedef struct { uint8_t padding4[3]; uint8_t high; uint8_t padding5[3]; -} GB_vba_rtc_time_t; +} vba_rtc_time_t; typedef struct __attribute__((packed)) { uint32_t magic; @@ -762,7 +762,7 @@ typedef struct __attribute__((packed)) { uint8_t reserved; uint64_t last_rtc_second; uint8_t rtc_data[4]; -} GB_tpp1_rtc_save_t; +} tpp1_rtc_save_t; typedef union { struct __attribute__((packed)) { @@ -771,17 +771,17 @@ typedef union { } sameboy_legacy; struct { /* Used by VBA versions with 32-bit timestamp*/ - GB_vba_rtc_time_t rtc_real, rtc_latched; + vba_rtc_time_t rtc_real, rtc_latched; uint32_t last_rtc_second; /* Always little endian */ } vba32; struct { /* Used by BGB and VBA versions with 64-bit timestamp*/ - GB_vba_rtc_time_t rtc_real, rtc_latched; + vba_rtc_time_t rtc_real, rtc_latched; uint64_t last_rtc_second; /* Always little endian */ } vba64; -} GB_rtc_save_t; +} rtc_save_t; -static void GB_fill_tpp1_save_data(GB_gameboy_t *gb, GB_tpp1_rtc_save_t *data) +static void fill_tpp1_save_data(GB_gameboy_t *gb, tpp1_rtc_save_t *data) { data->magic = BE32('TPP1'); data->version = BE16(0x100); @@ -805,10 +805,10 @@ int GB_save_battery_size(GB_gameboy_t *gb) } if (gb->cartridge_type->mbc_type == GB_TPP1) { - return gb->mbc_ram_size + sizeof(GB_tpp1_rtc_save_t); + return gb->mbc_ram_size + sizeof(tpp1_rtc_save_t); } - GB_rtc_save_t rtc_save_size; + rtc_save_t rtc_save_size; return gb->mbc_ram_size + (gb->cartridge_type->has_rtc ? sizeof(rtc_save_size.vba64) : 0); } @@ -824,8 +824,8 @@ int GB_save_battery_to_buffer(GB_gameboy_t *gb, uint8_t *buffer, size_t size) if (gb->cartridge_type->mbc_type == GB_TPP1) { buffer += gb->mbc_ram_size; - GB_tpp1_rtc_save_t rtc_save; - GB_fill_tpp1_save_data(gb, &rtc_save); + tpp1_rtc_save_t rtc_save; + fill_tpp1_save_data(gb, &rtc_save); memcpy(buffer, &rtc_save, sizeof(rtc_save)); } else if (gb->cartridge_type->mbc_type == GB_HUC3) { @@ -834,26 +834,26 @@ int GB_save_battery_to_buffer(GB_gameboy_t *gb, uint8_t *buffer, size_t size) #ifdef GB_BIG_ENDIAN GB_huc3_rtc_time_t rtc_save = { __builtin_bswap64(gb->last_rtc_second), - __builtin_bswap16(gb->huc3_minutes), - __builtin_bswap16(gb->huc3_days), - __builtin_bswap16(gb->huc3_alarm_minutes), - __builtin_bswap16(gb->huc3_alarm_days), - gb->huc3_alarm_enabled, + __builtin_bswap16(gb->huc3.minutes), + __builtin_bswap16(gb->huc3.days), + __builtin_bswap16(gb->huc3.alarm_minutes), + __builtin_bswap16(gb->huc3.alarm_days), + gb->huc3.alarm_enabled, }; #else GB_huc3_rtc_time_t rtc_save = { gb->last_rtc_second, - gb->huc3_minutes, - gb->huc3_days, - gb->huc3_alarm_minutes, - gb->huc3_alarm_days, - gb->huc3_alarm_enabled, + gb->huc3.minutes, + gb->huc3.days, + gb->huc3.alarm_minutes, + gb->huc3.alarm_days, + gb->huc3.alarm_enabled, }; #endif memcpy(buffer, &rtc_save, sizeof(rtc_save)); } else if (gb->cartridge_type->has_rtc) { - GB_rtc_save_t rtc_save = {{{{0,}},},}; + rtc_save_t rtc_save = {{{{0,}},},}; rtc_save.vba64.rtc_real.seconds = gb->rtc_real.seconds; rtc_save.vba64.rtc_real.minutes = gb->rtc_real.minutes; rtc_save.vba64.rtc_real.hours = gb->rtc_real.hours; @@ -892,8 +892,8 @@ int GB_save_battery(GB_gameboy_t *gb, const char *path) return EIO; } if (gb->cartridge_type->mbc_type == GB_TPP1) { - GB_tpp1_rtc_save_t rtc_save; - GB_fill_tpp1_save_data(gb, &rtc_save); + tpp1_rtc_save_t rtc_save; + fill_tpp1_save_data(gb, &rtc_save); if (fwrite(&rtc_save, sizeof(rtc_save), 1, f) != 1) { fclose(f); @@ -904,20 +904,20 @@ int GB_save_battery(GB_gameboy_t *gb, const char *path) #ifdef GB_BIG_ENDIAN GB_huc3_rtc_time_t rtc_save = { __builtin_bswap64(gb->last_rtc_second), - __builtin_bswap16(gb->huc3_minutes), - __builtin_bswap16(gb->huc3_days), - __builtin_bswap16(gb->huc3_alarm_minutes), - __builtin_bswap16(gb->huc3_alarm_days), - gb->huc3_alarm_enabled, + __builtin_bswap16(gb->huc3.minutes), + __builtin_bswap16(gb->huc3.days), + __builtin_bswap16(gb->huc3.alarm_minutes), + __builtin_bswap16(gb->huc3.alarm_days), + gb->huc3.alarm_enabled, }; #else GB_huc3_rtc_time_t rtc_save = { gb->last_rtc_second, - gb->huc3_minutes, - gb->huc3_days, - gb->huc3_alarm_minutes, - gb->huc3_alarm_days, - gb->huc3_alarm_enabled, + gb->huc3.minutes, + gb->huc3.days, + gb->huc3.alarm_minutes, + gb->huc3.alarm_days, + gb->huc3.alarm_enabled, }; #endif @@ -927,7 +927,7 @@ int GB_save_battery(GB_gameboy_t *gb, const char *path) } } else if (gb->cartridge_type->has_rtc) { - GB_rtc_save_t rtc_save = {{{{0,}},},}; + rtc_save_t rtc_save = {{{{0,}},},}; rtc_save.vba64.rtc_real.seconds = gb->rtc_real.seconds; rtc_save.vba64.rtc_real.minutes = gb->rtc_real.minutes; rtc_save.vba64.rtc_real.hours = gb->rtc_real.hours; @@ -955,7 +955,7 @@ int GB_save_battery(GB_gameboy_t *gb, const char *path) return errno; } -static void GB_load_tpp1_save_data(GB_gameboy_t *gb, const GB_tpp1_rtc_save_t *data) +static void load_tpp1_save_data(GB_gameboy_t *gb, const tpp1_rtc_save_t *data) { gb->last_rtc_second = LE64(data->last_rtc_second); unrolled for (unsigned i = 4; i--;) { @@ -971,13 +971,13 @@ void GB_load_battery_from_buffer(GB_gameboy_t *gb, const uint8_t *buffer, size_t } if (gb->cartridge_type->mbc_type == GB_TPP1) { - GB_tpp1_rtc_save_t rtc_save; + tpp1_rtc_save_t rtc_save; if (size - gb->mbc_ram_size < sizeof(rtc_save)) { goto reset_rtc; } memcpy(&rtc_save, buffer + gb->mbc_ram_size, sizeof(rtc_save)); - GB_load_tpp1_save_data(gb, &rtc_save); + load_tpp1_save_data(gb, &rtc_save); if (gb->last_rtc_second > time(NULL)) { /* We must reset RTC here, or it will not advance. */ @@ -994,18 +994,18 @@ void GB_load_battery_from_buffer(GB_gameboy_t *gb, const uint8_t *buffer, size_t memcpy(&rtc_save, buffer + gb->mbc_ram_size, sizeof(rtc_save)); #ifdef GB_BIG_ENDIAN gb->last_rtc_second = __builtin_bswap64(rtc_save.last_rtc_second); - gb->huc3_minutes = __builtin_bswap16(rtc_save.minutes); - gb->huc3_days = __builtin_bswap16(rtc_save.days); - gb->huc3_alarm_minutes = __builtin_bswap16(rtc_save.alarm_minutes); - gb->huc3_alarm_days = __builtin_bswap16(rtc_save.alarm_days); - gb->huc3_alarm_enabled = rtc_save.alarm_enabled; + gb->huc3.minutes = __builtin_bswap16(rtc_save.minutes); + gb->huc3.days = __builtin_bswap16(rtc_save.days); + gb->huc3.alarm_minutes = __builtin_bswap16(rtc_save.alarm_minutes); + gb->huc3.alarm_days = __builtin_bswap16(rtc_save.alarm_days); + gb->huc3.alarm_enabled = rtc_save.alarm_enabled; #else gb->last_rtc_second = rtc_save.last_rtc_second; - gb->huc3_minutes = rtc_save.minutes; - gb->huc3_days = rtc_save.days; - gb->huc3_alarm_minutes = rtc_save.alarm_minutes; - gb->huc3_alarm_days = rtc_save.alarm_days; - gb->huc3_alarm_enabled = rtc_save.alarm_enabled; + gb->huc3.minutes = rtc_save.minutes; + gb->huc3.days = rtc_save.days; + gb->huc3.alarm_minutes = rtc_save.alarm_minutes; + gb->huc3.alarm_days = rtc_save.alarm_days; + gb->huc3.alarm_enabled = rtc_save.alarm_enabled; #endif if (gb->last_rtc_second > time(NULL)) { /* We must reset RTC here, or it will not advance. */ @@ -1014,7 +1014,7 @@ void GB_load_battery_from_buffer(GB_gameboy_t *gb, const uint8_t *buffer, size_t return; } - GB_rtc_save_t rtc_save; + rtc_save_t rtc_save; memcpy(&rtc_save, buffer + gb->mbc_ram_size, MIN(sizeof(rtc_save), size)); switch (size - gb->mbc_ram_size) { case sizeof(rtc_save.sameboy_legacy): @@ -1076,9 +1076,9 @@ void GB_load_battery_from_buffer(GB_gameboy_t *gb, const uint8_t *buffer, size_t reset_rtc: gb->last_rtc_second = time(NULL); gb->rtc_real.high |= 0x80; /* This gives the game a hint that the clock should be reset. */ - gb->huc3_days = 0xFFFF; - gb->huc3_minutes = 0xFFF; - gb->huc3_alarm_enabled = false; + gb->huc3.days = 0xFFFF; + gb->huc3.minutes = 0xFFF; + gb->huc3.alarm_enabled = false; exit: return; } @@ -1096,12 +1096,12 @@ void GB_load_battery(GB_gameboy_t *gb, const char *path) } if (gb->cartridge_type->mbc_type == GB_TPP1) { - GB_tpp1_rtc_save_t rtc_save; + tpp1_rtc_save_t rtc_save; if (fread(&rtc_save, sizeof(rtc_save), 1, f) != 1) { goto reset_rtc; } - GB_load_tpp1_save_data(gb, &rtc_save); + load_tpp1_save_data(gb, &rtc_save); if (gb->last_rtc_second > time(NULL)) { /* We must reset RTC here, or it will not advance. */ @@ -1117,18 +1117,18 @@ void GB_load_battery(GB_gameboy_t *gb, const char *path) } #ifdef GB_BIG_ENDIAN gb->last_rtc_second = __builtin_bswap64(rtc_save.last_rtc_second); - gb->huc3_minutes = __builtin_bswap16(rtc_save.minutes); - gb->huc3_days = __builtin_bswap16(rtc_save.days); - gb->huc3_alarm_minutes = __builtin_bswap16(rtc_save.alarm_minutes); - gb->huc3_alarm_days = __builtin_bswap16(rtc_save.alarm_days); - gb->huc3_alarm_enabled = rtc_save.alarm_enabled; + gb->huc3.minutes = __builtin_bswap16(rtc_save.minutes); + gb->huc3.days = __builtin_bswap16(rtc_save.days); + gb->huc3.alarm_minutes = __builtin_bswap16(rtc_save.alarm_minutes); + gb->huc3.alarm_days = __builtin_bswap16(rtc_save.alarm_days); + gb->huc3.alarm_enabled = rtc_save.alarm_enabled; #else gb->last_rtc_second = rtc_save.last_rtc_second; - gb->huc3_minutes = rtc_save.minutes; - gb->huc3_days = rtc_save.days; - gb->huc3_alarm_minutes = rtc_save.alarm_minutes; - gb->huc3_alarm_days = rtc_save.alarm_days; - gb->huc3_alarm_enabled = rtc_save.alarm_enabled; + gb->huc3.minutes = rtc_save.minutes; + gb->huc3.days = rtc_save.days; + gb->huc3.alarm_minutes = rtc_save.alarm_minutes; + gb->huc3.alarm_days = rtc_save.alarm_days; + gb->huc3.alarm_enabled = rtc_save.alarm_enabled; #endif if (gb->last_rtc_second > time(NULL)) { /* We must reset RTC here, or it will not advance. */ @@ -1137,7 +1137,7 @@ void GB_load_battery(GB_gameboy_t *gb, const char *path) return; } - GB_rtc_save_t rtc_save; + rtc_save_t rtc_save; switch (fread(&rtc_save, 1, sizeof(rtc_save), f)) { case sizeof(rtc_save.sameboy_legacy): memcpy(&gb->rtc_real, &rtc_save.sameboy_legacy.rtc_real, sizeof(gb->rtc_real)); @@ -1198,9 +1198,9 @@ void GB_load_battery(GB_gameboy_t *gb, const char *path) reset_rtc: gb->last_rtc_second = time(NULL); gb->rtc_real.high |= 0x80; /* This gives the game a hint that the clock should be reset. */ - gb->huc3_days = 0xFFFF; - gb->huc3_minutes = 0xFFF; - gb->huc3_alarm_enabled = false; + gb->huc3.days = 0xFFFF; + gb->huc3.minutes = 0xFFF; + gb->huc3.alarm_enabled = false; exit: fclose(f); return; @@ -1711,8 +1711,7 @@ void GB_reset(GB_gameboy_t *gb) } } - /* Todo: Ugly, fixme, see comment in the timer state machine */ - gb->div_state = 3; + GB_set_internal_div_counter(gb, 8); GB_apu_update_cycles_per_sample(gb); @@ -1910,10 +1909,10 @@ void GB_set_boot_rom_load_callback(GB_gameboy_t *gb, GB_boot_rom_load_callback_t unsigned GB_time_to_alarm(GB_gameboy_t *gb) { if (gb->cartridge_type->mbc_type != GB_HUC3) return 0; - if (!gb->huc3_alarm_enabled) return 0; - if (!(gb->huc3_alarm_days & 0x2000)) return 0; - unsigned current_time = (gb->huc3_days & 0x1FFF) * 24 * 60 * 60 + gb->huc3_minutes * 60 + (time(NULL) % 60); - unsigned alarm_time = (gb->huc3_alarm_days & 0x1FFF) * 24 * 60 * 60 + gb->huc3_alarm_minutes * 60; + if (!gb->huc3.alarm_enabled) return 0; + if (!(gb->huc3.alarm_days & 0x2000)) return 0; + unsigned current_time = (gb->huc3.days & 0x1FFF) * 24 * 60 * 60 + gb->huc3.minutes * 60 + (time(NULL) % 60); + unsigned alarm_time = (gb->huc3.alarm_days & 0x1FFF) * 24 * 60 * 60 + gb->huc3.alarm_minutes * 60; if (current_time > alarm_time) return 0; return alarm_time - current_time; } diff --git a/Core/gb.h b/Core/gb.h index a23922a..3dbd7b3 100644 --- a/Core/gb.h +++ b/Core/gb.h @@ -26,7 +26,7 @@ #include "workboy.h" #include "random.h" -#define GB_STRUCT_VERSION 13 +#define GB_STRUCT_VERSION 14 #define GB_MODEL_FAMILY_MASK 0xF00 #define GB_MODEL_DMG_FAMILY 0x000 @@ -35,9 +35,6 @@ #define GB_MODEL_PAL_BIT 0x40 #define GB_MODEL_NO_SFC_BIT 0x80 -#define GB_MODEL_PAL_BIT_OLD 0x1000 -#define GB_MODEL_NO_SFC_BIT_OLD 0x2000 - #ifdef GB_INTERNAL #if __clang__ #define unrolled _Pragma("unroll") @@ -471,6 +468,7 @@ struct GB_gameboy_internal_s { struct { uint8_t rom_bank:8; uint8_t ram_bank:3; + bool rtc_mapped:1; } mbc3; struct { @@ -490,26 +488,27 @@ struct GB_gameboy_internal_s { uint8_t rom_bank:7; uint8_t padding:1; uint8_t ram_bank:4; + uint8_t mode; + uint8_t access_index; + uint16_t minutes, days; + uint16_t alarm_minutes, alarm_days; + bool alarm_enabled; + uint8_t read; + uint8_t access_flags; } huc3; + + struct { + uint16_t rom_bank; + uint8_t ram_bank; + uint8_t mode; + } tpp1; }; uint16_t mbc_rom0_bank; /* For some MBC1 wirings. */ bool camera_registers_mapped; uint8_t camera_registers[0x36]; uint8_t rumble_strength; bool cart_ir; - - // TODO: move to huc3/mbc3/tpp1 struct when breaking save compat - uint8_t huc3_mode; - uint8_t huc3_access_index; - uint16_t huc3_minutes, huc3_days; - uint16_t huc3_alarm_minutes, huc3_alarm_days; - bool huc3_alarm_enabled; - uint8_t huc3_read; - uint8_t huc3_access_flags; - bool mbc3_rtc_mapped; - uint16_t tpp1_rom_bank; - uint8_t tpp1_ram_bank; - uint8_t tpp1_mode; + ); @@ -543,7 +542,6 @@ struct GB_gameboy_internal_s { GB_SECTION(rtc, GB_rtc_time_t rtc_real, rtc_latched; uint64_t last_rtc_second; - GB_PADDING(bool, rtc_latch); uint32_t rtc_cycles; uint8_t tpp1_mr4; ); @@ -579,7 +577,6 @@ struct GB_gameboy_internal_s { uint8_t current_line; uint16_t ly_for_comparison; GB_fifo_t bg_fifo, oam_fifo; - GB_PADDING(uint8_t, fetcher_x); uint8_t fetcher_y; uint16_t cycles_for_line; uint8_t current_tile; diff --git a/Core/mbc.c b/Core/mbc.c index a9e758e..b76778c 100644 --- a/Core/mbc.c +++ b/Core/mbc.c @@ -112,9 +112,9 @@ void GB_update_mbc_mappings(GB_gameboy_t *gb) gb->mbc_ram_bank = gb->huc3.ram_bank; break; case GB_TPP1: - gb->mbc_rom_bank = gb->tpp1_rom_bank; - gb->mbc_ram_bank = gb->tpp1_ram_bank; - gb->mbc_ram_enable = (gb->tpp1_mode == 2) || (gb->tpp1_mode == 3); + gb->mbc_rom_bank = gb->tpp1.rom_bank; + gb->mbc_ram_bank = gb->tpp1.ram_bank; + gb->mbc_ram_enable = (gb->tpp1.mode == 2) || (gb->tpp1.mode == 3); break; } } @@ -127,7 +127,7 @@ void GB_configure_cart(GB_gameboy_t *gb) gb->rom[0x14a] == 0x65) { static const GB_cartridge_t tpp1 = {GB_TPP1, GB_STANDARD_MBC, true, true, true, true}; gb->cartridge_type = &tpp1; - gb->tpp1_rom_bank = 1; + gb->tpp1.rom_bank = 1; } if (gb->rom[0x147] == 0 && gb->rom_size > 0x8000) { diff --git a/Core/memory.c b/Core/memory.c index bcfff64..0174eb1 100644 --- a/Core/memory.c +++ b/Core/memory.c @@ -2,17 +2,17 @@ #include #include "gb.h" -typedef uint8_t GB_read_function_t(GB_gameboy_t *gb, uint16_t addr); -typedef void GB_write_function_t(GB_gameboy_t *gb, uint16_t addr, uint8_t value); +typedef uint8_t read_function_t(GB_gameboy_t *gb, uint16_t addr); +typedef void write_function_t(GB_gameboy_t *gb, uint16_t addr, uint8_t value); typedef enum { GB_BUS_MAIN, /* In DMG: Cart and RAM. In CGB: Cart only */ GB_BUS_RAM, /* In CGB only. */ GB_BUS_VRAM, GB_BUS_INTERNAL, /* Anything in highram. Might not be the most correct name. */ -} GB_bus_t; +} bus_t; -static GB_bus_t bus_for_addr(GB_gameboy_t *gb, uint16_t addr) +static bus_t bus_for_addr(GB_gameboy_t *gb, uint16_t addr) { if (addr < 0x8000) { return GB_BUS_MAIN; @@ -304,18 +304,18 @@ static uint8_t read_vram(GB_gameboy_t *gb, uint16_t addr) static uint8_t read_mbc_ram(GB_gameboy_t *gb, uint16_t addr) { if (gb->cartridge_type->mbc_type == GB_HUC3) { - switch (gb->huc3_mode) { + switch (gb->huc3.mode) { case 0xC: // RTC read - if (gb->huc3_access_flags == 0x2) { + if (gb->huc3.access_flags == 0x2) { return 1; } - return gb->huc3_read; + return gb->huc3.read; case 0xD: // RTC status return 1; case 0xE: // IR mode return gb->effective_ir_input; // TODO: What are the other bits? default: - GB_log(gb, "Unsupported HuC-3 mode %x read: %04x\n", gb->huc3_mode, addr); + GB_log(gb, "Unsupported HuC-3 mode %x read: %04x\n", gb->huc3.mode, addr); return 1; // TODO: What happens in this case? case 0: // TODO: R/O RAM? (or is it disabled?) case 0xA: // RAM @@ -324,12 +324,12 @@ static uint8_t read_mbc_ram(GB_gameboy_t *gb, uint16_t addr) } if (gb->cartridge_type->mbc_type == GB_TPP1) { - switch (gb->tpp1_mode) { + switch (gb->tpp1.mode) { case 0: switch (addr & 3) { - case 0: return gb->tpp1_rom_bank; - case 1: return gb->tpp1_rom_bank >> 8; - case 2: return gb->tpp1_ram_bank; + case 0: return gb->tpp1.rom_bank; + case 1: return gb->tpp1.rom_bank >> 8; + case 2: return gb->tpp1.ram_bank; case 3: return gb->rumble_strength | gb->tpp1_mr4; } case 2: @@ -353,7 +353,7 @@ static uint8_t read_mbc_ram(GB_gameboy_t *gb, uint16_t addr) } if (gb->cartridge_type->has_rtc && gb->cartridge_type->mbc_type != GB_HUC3 && - gb->mbc3_rtc_mapped) { + gb->mbc3.rtc_mapped) { /* RTC read */ if (gb->mbc_ram_bank <= 4) { gb->rtc_latched.seconds &= 0x3F; @@ -651,7 +651,7 @@ static uint8_t read_high_memory(GB_gameboy_t *gb, uint16_t addr) return gb->hram[addr - 0xFF80]; } -static GB_read_function_t * const read_map[] = +static read_function_t *const read_map[] = { read_rom, read_rom, read_rom, read_rom, /* 0XXX, 1XXX, 2XXX, 3XXX */ read_mbc_rom, read_mbc_rom, read_mbc_rom, read_mbc_rom, /* 4XXX, 5XXX, 6XXX, 7XXX */ @@ -706,7 +706,7 @@ static void write_mbc(GB_gameboy_t *gb, uint16_t addr, uint8_t value) case 0x2000: case 0x3000: gb->mbc3.rom_bank = value; break; case 0x4000: case 0x5000: gb->mbc3.ram_bank = value; - gb->mbc3_rtc_mapped = value & 8; + gb->mbc3.rtc_mapped = value & 8; break; case 0x6000: case 0x7000: memcpy(&gb->rtc_latched, &gb->rtc_real, sizeof(gb->rtc_real)); @@ -741,8 +741,8 @@ static void write_mbc(GB_gameboy_t *gb, uint16_t addr, uint8_t value) case GB_HUC3: switch (addr & 0xF000) { case 0x0000: case 0x1000: - gb->huc3_mode = value & 0xF; - gb->mbc_ram_enable = gb->huc3_mode == 0xA; + gb->huc3.mode = value & 0xF; + gb->mbc_ram_enable = gb->huc3.mode == 0xA; break; case 0x2000: case 0x3000: gb->huc3.rom_bank = value; break; case 0x4000: case 0x5000: gb->huc3.ram_bank = value; break; @@ -751,15 +751,15 @@ static void write_mbc(GB_gameboy_t *gb, uint16_t addr, uint8_t value) case GB_TPP1: switch (addr & 3) { case 0: - gb->tpp1_rom_bank &= 0xFF00; - gb->tpp1_rom_bank |= value; + gb->tpp1.rom_bank &= 0xFF00; + gb->tpp1.rom_bank |= value; break; case 1: - gb->tpp1_rom_bank &= 0xFF; - gb->tpp1_rom_bank |= value << 8; + gb->tpp1.rom_bank &= 0xFF; + gb->tpp1.rom_bank |= value << 8; break; case 2: - gb->tpp1_ram_bank = value; + gb->tpp1.ram_bank = value; break; case 3: switch (value) { @@ -767,7 +767,7 @@ static void write_mbc(GB_gameboy_t *gb, uint16_t addr, uint8_t value) case 2: case 3: case 5: - gb->tpp1_mode = value; + gb->tpp1.mode = value; break; case 0x10: memcpy(&gb->rtc_latched, &gb->rtc_real, sizeof(gb->rtc_real)); @@ -823,59 +823,59 @@ static void write_vram(GB_gameboy_t *gb, uint16_t addr, uint8_t value) static bool huc3_write(GB_gameboy_t *gb, uint8_t value) { - switch (gb->huc3_mode) { + switch (gb->huc3.mode) { case 0xB: // RTC Write switch (value >> 4) { case 1: - if (gb->huc3_access_index < 3) { - gb->huc3_read = (gb->huc3_minutes >> (gb->huc3_access_index * 4)) & 0xF; + if (gb->huc3.access_index < 3) { + gb->huc3.read = (gb->huc3.minutes >> (gb->huc3.access_index * 4)) & 0xF; } - else if (gb->huc3_access_index < 7) { - gb->huc3_read = (gb->huc3_days >> ((gb->huc3_access_index - 3) * 4)) & 0xF; + else if (gb->huc3.access_index < 7) { + gb->huc3.read = (gb->huc3.days >> ((gb->huc3.access_index - 3) * 4)) & 0xF; } else { - // GB_log(gb, "Attempting to read from unsupported HuC-3 register: %03x\n", gb->huc3_access_index); + // GB_log(gb, "Attempting to read from unsupported HuC-3 register: %03x\n", gb->huc3.access_index); } - gb->huc3_access_index++; + gb->huc3.access_index++; break; case 2: case 3: - if (gb->huc3_access_index < 3) { - gb->huc3_minutes &= ~(0xF << (gb->huc3_access_index * 4)); - gb->huc3_minutes |= ((value & 0xF) << (gb->huc3_access_index * 4)); + if (gb->huc3.access_index < 3) { + gb->huc3.minutes &= ~(0xF << (gb->huc3.access_index * 4)); + gb->huc3.minutes |= ((value & 0xF) << (gb->huc3.access_index * 4)); } - else if (gb->huc3_access_index < 7) { - gb->huc3_days &= ~(0xF << ((gb->huc3_access_index - 3) * 4)); - gb->huc3_days |= ((value & 0xF) << ((gb->huc3_access_index - 3) * 4)); + else if (gb->huc3.access_index < 7) { + gb->huc3.days &= ~(0xF << ((gb->huc3.access_index - 3) * 4)); + gb->huc3.days |= ((value & 0xF) << ((gb->huc3.access_index - 3) * 4)); } - else if (gb->huc3_access_index >= 0x58 && gb->huc3_access_index <= 0x5a) { - gb->huc3_alarm_minutes &= ~(0xF << ((gb->huc3_access_index - 0x58) * 4)); - gb->huc3_alarm_minutes |= ((value & 0xF) << ((gb->huc3_access_index - 0x58) * 4)); + else if (gb->huc3.access_index >= 0x58 && gb->huc3.access_index <= 0x5a) { + gb->huc3.alarm_minutes &= ~(0xF << ((gb->huc3.access_index - 0x58) * 4)); + gb->huc3.alarm_minutes |= ((value & 0xF) << ((gb->huc3.access_index - 0x58) * 4)); } - else if (gb->huc3_access_index >= 0x5b && gb->huc3_access_index <= 0x5e) { - gb->huc3_alarm_days &= ~(0xF << ((gb->huc3_access_index - 0x5b) * 4)); - gb->huc3_alarm_days |= ((value & 0xF) << ((gb->huc3_access_index - 0x5b) * 4)); + else if (gb->huc3.access_index >= 0x5b && gb->huc3.access_index <= 0x5e) { + gb->huc3.alarm_days &= ~(0xF << ((gb->huc3.access_index - 0x5b) * 4)); + gb->huc3.alarm_days |= ((value & 0xF) << ((gb->huc3.access_index - 0x5b) * 4)); } - else if (gb->huc3_access_index == 0x5f) { - gb->huc3_alarm_enabled = value & 1; + else if (gb->huc3.access_index == 0x5f) { + gb->huc3.alarm_enabled = value & 1; } else { - // GB_log(gb, "Attempting to write %x to unsupported HuC-3 register: %03x\n", value & 0xF, gb->huc3_access_index); + // GB_log(gb, "Attempting to write %x to unsupported HuC-3 register: %03x\n", value & 0xF, gb->huc3.access_index); } if ((value >> 4) == 3) { - gb->huc3_access_index++; + gb->huc3.access_index++; } break; case 4: - gb->huc3_access_index &= 0xF0; - gb->huc3_access_index |= value & 0xF; + gb->huc3.access_index &= 0xF0; + gb->huc3.access_index |= value & 0xF; break; case 5: - gb->huc3_access_index &= 0x0F; - gb->huc3_access_index |= (value & 0xF) << 4; + gb->huc3.access_index &= 0x0F; + gb->huc3.access_index |= (value & 0xF) << 4; break; case 6: - gb->huc3_access_flags = (value & 0xF); + gb->huc3.access_flags = (value & 0xF); break; default: @@ -917,7 +917,7 @@ static void write_mbc_ram(GB_gameboy_t *gb, uint16_t addr, uint8_t value) } if (gb->cartridge_type->mbc_type == GB_TPP1) { - switch (gb->tpp1_mode) { + switch (gb->tpp1.mode) { case 3: break; case 5: @@ -941,7 +941,7 @@ static void write_mbc_ram(GB_gameboy_t *gb, uint16_t addr, uint8_t value) return; } - if (gb->cartridge_type->has_rtc && gb->mbc3_rtc_mapped) { + if (gb->cartridge_type->has_rtc && gb->mbc3.rtc_mapped) { if (gb->mbc_ram_bank <= 4) { if (gb->mbc_ram_bank == 0) { gb->rtc_cycles = 0; @@ -1191,6 +1191,7 @@ static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value) return; case GB_IO_DIV: + GB_set_internal_div_counter(gb, 0); /* Reset the div state machine */ gb->div_state = 0; gb->div_cycles = 0; @@ -1388,7 +1389,7 @@ static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value) -static GB_write_function_t * const write_map[] = +static write_function_t *const write_map[] = { write_mbc, write_mbc, write_mbc, write_mbc, /* 0XXX, 1XXX, 2XXX, 3XXX */ write_mbc, write_mbc, write_mbc, write_mbc, /* 4XXX, 5XXX, 6XXX, 7XXX */ diff --git a/Core/save_state.c b/Core/save_state.c index e472995..7e1767c 100644 --- a/Core/save_state.c +++ b/Core/save_state.c @@ -276,30 +276,6 @@ size_t GB_get_save_state_size(GB_gameboy_t *gb) static bool verify_and_update_state_compatibility(GB_gameboy_t *gb, GB_gameboy_t *save, bool *attempt_bess) { *attempt_bess = false; - if (save->ram_size == 0 && (&save->ram_size)[-1] == gb->ram_size) { - /* This is a save state with a bad printer struct from a 32-bit OS */ - memmove(save->extra_oam + 4, save->extra_oam, (uintptr_t)&save->ram_size - (uintptr_t)&save->extra_oam); - } - if (save->ram_size == 0) { - /* Save doesn't have ram size specified, it's a pre 0.12 save state with potentially - incorrect RAM amount if it's a CGB instance */ - if (GB_is_cgb(save)) { - save->ram_size = 0x2000 * 8; // Incorrect RAM size - } - else { - save->ram_size = gb->ram_size; - } - } - - if (save->model & GB_MODEL_PAL_BIT_OLD) { - save->model &= ~GB_MODEL_PAL_BIT_OLD; - save->model |= GB_MODEL_PAL_BIT; - } - - if (save->model & GB_MODEL_NO_SFC_BIT_OLD) { - save->model &= ~GB_MODEL_NO_SFC_BIT_OLD; - save->model |= GB_MODEL_NO_SFC_BIT; - } if (gb->version != save->version) { GB_log(gb, "The save state is for a different version of SameBoy.\n"); @@ -328,14 +304,8 @@ static bool verify_and_update_state_compatibility(GB_gameboy_t *gb, GB_gameboy_t } if (gb->ram_size != save->ram_size) { - if (gb->ram_size == 0x1000 * 8 && save->ram_size == 0x2000 * 8) { - /* A bug in versions prior to 0.12 made CGB instances allocate twice the ammount of RAM. - Ignore this issue to retain compatibility with older, 0.11, save states. */ - } - else { - GB_log(gb, "The save state has non-matching RAM size. Try changing the emulated model.\n"); - return false; - } + GB_log(gb, "The save state has non-matching RAM size. Try changing the emulated model.\n"); + return false; } switch (save->model) { @@ -407,62 +377,12 @@ static void sanitize_state(GB_gameboy_t *gb) gb->lcd_x = gb->position_in_line; } - if (gb->object_priority == GB_OBJECT_PRIORITY_UNDEFINED) { - gb->object_priority = gb->cgb_mode? GB_OBJECT_PRIORITY_INDEX : GB_OBJECT_PRIORITY_X; - } if (gb->sgb) { if (gb->sgb->player_count != 1 && gb->sgb->player_count != 2 && gb->sgb->player_count != 4) { gb->sgb->player_count = 1; } gb->sgb->current_player &= gb->sgb->player_count - 1; } - if (gb->sgb && !gb->sgb->v14_3) { -#ifdef GB_BIG_ENDIAN - for (unsigned i = 0; i < sizeof(gb->sgb->border.raw_data) / 2; i++) { - gb->sgb->border.raw_data[i] = LE16(gb->sgb->border.raw_data[i]); - } - - for (unsigned i = 0; i < sizeof(gb->sgb->pending_border.raw_data) / 2; i++) { - gb->sgb->pending_border.raw_data[i] = LE16(gb->sgb->pending_border.raw_data[i]); - } - - for (unsigned i = 0; i < sizeof(gb->sgb->effective_palettes) / 2; i++) { - gb->sgb->effective_palettes[i] = LE16(gb->sgb->effective_palettes[i]); - } - - for (unsigned i = 0; i < sizeof(gb->sgb->ram_palettes) / 2; i++) { - gb->sgb->ram_palettes[i] = LE16(gb->sgb->ram_palettes[i]); - } -#endif - uint8_t converted_tiles[sizeof(gb->sgb->border.tiles)] = {0,}; - for (unsigned tile = 0; tile < sizeof(gb->sgb->border.tiles_legacy) / 64; tile++) { - for (unsigned y = 0; y < 8; y++) { - unsigned base = tile * 32 + y * 2; - for (unsigned x = 0; x < 8; x++) { - uint8_t pixel = gb->sgb->border.tiles_legacy[tile * 8 * 8 + y * 8 + x]; - if (pixel & 1) converted_tiles[base] |= (1 << (7 ^ x)); - if (pixel & 2) converted_tiles[base + 1] |= (1 << (7 ^ x)); - if (pixel & 4) converted_tiles[base + 16] |= (1 << (7 ^ x)); - if (pixel & 8) converted_tiles[base + 17] |= (1 << (7 ^ x)); - } - } - } - memcpy(gb->sgb->border.tiles, converted_tiles, sizeof(converted_tiles)); - memset(converted_tiles, 0, sizeof(converted_tiles)); - for (unsigned tile = 0; tile < sizeof(gb->sgb->pending_border.tiles_legacy) / 64; tile++) { - for (unsigned y = 0; y < 8; y++) { - unsigned base = tile * 32 + y * 2; - for (unsigned x = 0; x < 8; x++) { - uint8_t pixel = gb->sgb->pending_border.tiles_legacy[tile * 8 * 8 + y * 8 + x]; - if (pixel & 1) converted_tiles[base] |= (1 << (7 ^ x)); - if (pixel & 2) converted_tiles[base + 1] |= (1 << (7 ^ x)); - if (pixel & 4) converted_tiles[base + 16] |= (1 << (7 ^ x)); - if (pixel & 8) converted_tiles[base + 17] |= (1 << (7 ^ x)); - } - } - } - memcpy(gb->sgb->pending_border.tiles, converted_tiles, sizeof(converted_tiles)); - } } static bool dump_section(virtual_file_t *file, const void *src, uint32_t size) @@ -503,7 +423,7 @@ static int save_bess_mbc_block(GB_gameboy_t *gb, virtual_file_t *file) case GB_MBC3: pairs[0] = (BESS_MBC_pair_t){LE16(0x0000), gb->mbc_ram_enable? 0xA : 0x0}; pairs[1] = (BESS_MBC_pair_t){LE16(0x2000), gb->mbc3.rom_bank}; - pairs[2] = (BESS_MBC_pair_t){LE16(0x4000), gb->mbc3.ram_bank | (gb->mbc3_rtc_mapped? 8 : 0)}; + pairs[2] = (BESS_MBC_pair_t){LE16(0x4000), gb->mbc3.ram_bank | (gb->mbc3.rtc_mapped? 8 : 0)}; mbc_block.size = 3 * sizeof(pairs[0]); break; case GB_MBC5: @@ -521,17 +441,17 @@ static int save_bess_mbc_block(GB_gameboy_t *gb, virtual_file_t *file) mbc_block.size = 4 * sizeof(pairs[0]); case GB_HUC3: - pairs[0] = (BESS_MBC_pair_t){LE16(0x0000), gb->huc3_mode}; + pairs[0] = (BESS_MBC_pair_t){LE16(0x0000), gb->huc3.mode}; pairs[1] = (BESS_MBC_pair_t){LE16(0x2000), gb->huc3.rom_bank}; pairs[2] = (BESS_MBC_pair_t){LE16(0x4000), gb->huc3.ram_bank}; mbc_block.size = 3 * sizeof(pairs[0]); break; case GB_TPP1: - pairs[0] = (BESS_MBC_pair_t){LE16(0x0000), gb->tpp1_rom_bank}; - pairs[1] = (BESS_MBC_pair_t){LE16(0x0001), gb->tpp1_rom_bank >> 8}; - pairs[2] = (BESS_MBC_pair_t){LE16(0x0002), gb->tpp1_rom_bank}; - pairs[3] = (BESS_MBC_pair_t){LE16(0x0003), gb->tpp1_mode}; + pairs[0] = (BESS_MBC_pair_t){LE16(0x0000), gb->tpp1.rom_bank}; + pairs[1] = (BESS_MBC_pair_t){LE16(0x0001), gb->tpp1.rom_bank >> 8}; + pairs[2] = (BESS_MBC_pair_t){LE16(0x0002), gb->tpp1.rom_bank}; + pairs[3] = (BESS_MBC_pair_t){LE16(0x0003), gb->tpp1.mode}; mbc_block.size = 4 * sizeof(pairs[0]); break; } @@ -566,7 +486,6 @@ static int save_state_internal(GB_gameboy_t *gb, virtual_file_t *file, bool appe uint32_t sgb_offset = 0; if (GB_is_hle_sgb(gb)) { - gb->sgb->v14_3 = true; sgb_offset = file->tell(file) + 4; if (!dump_section(file, gb->sgb, sizeof(*gb->sgb))) goto error; } @@ -746,11 +665,11 @@ static int save_state_internal(GB_gameboy_t *gb, virtual_file_t *file, bool appe bess_huc3.data = (GB_huc3_rtc_time_t) { LE64(gb->last_rtc_second), - LE16(gb->huc3_minutes), - LE16(gb->huc3_days), - LE16(gb->huc3_alarm_minutes), - LE16(gb->huc3_alarm_days), - gb->huc3_alarm_enabled, + LE16(gb->huc3.minutes), + LE16(gb->huc3.days), + LE16(gb->huc3.alarm_minutes), + LE16(gb->huc3.alarm_days), + gb->huc3.alarm_enabled, }; if (file->write(file, &bess_huc3, sizeof(bess_huc3)) != sizeof(bess_huc3)) { goto error; @@ -1116,11 +1035,11 @@ static int load_bess_save(GB_gameboy_t *gb, virtual_file_t *file, bool is_samebo if (gb->rtc_mode == GB_RTC_MODE_SYNC_TO_HOST) { save.last_rtc_second = MIN(LE64(bess_huc3.data.last_rtc_second), time(NULL)); } - save.huc3_minutes = LE16(bess_huc3.data.minutes); - save.huc3_days = LE16(bess_huc3.data.days); - save.huc3_alarm_minutes = LE16(bess_huc3.data.alarm_minutes); - save.huc3_alarm_days = LE16(bess_huc3.data.alarm_days); - save.huc3_alarm_enabled = bess_huc3.data.alarm_enabled; + save.huc3.minutes = LE16(bess_huc3.data.minutes); + save.huc3.days = LE16(bess_huc3.data.days); + save.huc3.alarm_minutes = LE16(bess_huc3.data.alarm_minutes); + save.huc3.alarm_days = LE16(bess_huc3.data.alarm_days); + save.huc3.alarm_enabled = bess_huc3.data.alarm_enabled; break; case BE32('TPP1'): if (!found_core) goto parse_error; diff --git a/Core/sgb.h b/Core/sgb.h index 1e1a5c2..f4d60fe 100644 --- a/Core/sgb.h +++ b/Core/sgb.h @@ -6,10 +6,7 @@ typedef struct GB_sgb_s GB_sgb_t; typedef struct { - union { - uint8_t tiles[0x100 * 8 * 4]; - uint8_t tiles_legacy[0x100 * 8 * 8]; /* High nibble not used; TODO: Remove when breaking save-state compatibility! */ - }; + uint8_t tiles[0x100 * 8 * 4]; union { struct { uint16_t map[32 * 32]; @@ -59,11 +56,6 @@ struct GB_sgb_s { /* GB Header */ uint8_t received_header[0x54]; - - /* Multiplayer (cont) */ - GB_PADDING(bool, mlt_lock); - - bool v14_3; // True on save states created on 0.14.3 or newer; Remove when breaking save state compatibility! }; void GB_sgb_write(GB_gameboy_t *gb, uint8_t value); diff --git a/Core/sm83_cpu.c b/Core/sm83_cpu.c index f2a22a1..6920c79 100644 --- a/Core/sm83_cpu.c +++ b/Core/sm83_cpu.c @@ -4,7 +4,7 @@ #include "gb.h" -typedef void GB_opcode_t(GB_gameboy_t *gb, uint8_t opcode); +typedef void opcode_t(GB_gameboy_t *gb, uint8_t opcode); typedef enum { /* Default behavior. If the CPU writes while another component reads, it reads the old value */ @@ -23,10 +23,10 @@ typedef enum { GB_CONFLICT_WX, GB_CONFLICT_CGB_LCDC, GB_CONFLICT_NR10, -} GB_conflict_t; +} conflict_t; /* Todo: How does double speed mode affect these? */ -static const GB_conflict_t cgb_conflict_map[0x80] = { +static const conflict_t cgb_conflict_map[0x80] = { [GB_IO_LCDC] = GB_CONFLICT_CGB_LCDC, [GB_IO_IF] = GB_CONFLICT_WRITE_CPU, [GB_IO_LYC] = GB_CONFLICT_WRITE_CPU, @@ -41,7 +41,7 @@ static const GB_conflict_t cgb_conflict_map[0x80] = { }; /* Todo: verify on an MGB */ -static const GB_conflict_t dmg_conflict_map[0x80] = { +static const conflict_t dmg_conflict_map[0x80] = { [GB_IO_IF] = GB_CONFLICT_WRITE_CPU, [GB_IO_LYC] = GB_CONFLICT_READ_OLD, [GB_IO_LCDC] = GB_CONFLICT_DMG_LCDC, @@ -60,7 +60,7 @@ static const GB_conflict_t dmg_conflict_map[0x80] = { }; /* Todo: Verify on an SGB1 */ -static const GB_conflict_t sgb_conflict_map[0x80] = { +static const conflict_t sgb_conflict_map[0x80] = { [GB_IO_IF] = GB_CONFLICT_WRITE_CPU, [GB_IO_LYC] = GB_CONFLICT_READ_OLD, [GB_IO_LCDC] = GB_CONFLICT_SGB_LCDC, @@ -109,9 +109,9 @@ static uint8_t cycle_write_if(GB_gameboy_t *gb, uint8_t value) static void cycle_write(GB_gameboy_t *gb, uint16_t addr, uint8_t value) { assert(gb->pending_cycles); - GB_conflict_t conflict = GB_CONFLICT_READ_OLD; + conflict_t conflict = GB_CONFLICT_READ_OLD; if ((addr & 0xFF80) == 0xFF00) { - const GB_conflict_t *map = NULL; + const conflict_t *map = NULL; if (GB_is_cgb(gb)) { map = cgb_conflict_map; } @@ -1530,7 +1530,7 @@ static void cb_prefix(GB_gameboy_t *gb, uint8_t opcode) } } -static GB_opcode_t *opcodes[256] = { +static opcode_t *opcodes[256] = { /* X0 X1 X2 X3 X4 X5 X6 X7 */ /* X8 X9 Xa Xb Xc Xd Xe Xf */ nop, ld_rr_d16, ld_drr_a, inc_rr, inc_hr, dec_hr, ld_hr_d8, rlca, /* 0X */ diff --git a/Core/sm83_disassembler.c b/Core/sm83_disassembler.c index 7dacd9e..894c766 100644 --- a/Core/sm83_disassembler.c +++ b/Core/sm83_disassembler.c @@ -3,7 +3,7 @@ #include "gb.h" -typedef void GB_opcode_t(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc); +typedef void opcode_t(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc); static void ill(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc) { @@ -716,7 +716,7 @@ static void cb_prefix(GB_gameboy_t *gb, uint8_t opcode, uint16_t *pc) } } -static GB_opcode_t *opcodes[256] = { +static opcode_t *opcodes[256] = { /* X0 X1 X2 X3 X4 X5 X6 X7 */ /* X8 X9 Xa Xb Xc Xd Xe Xf */ nop, ld_rr_d16, ld_drr_a, inc_rr, inc_hr, dec_hr, ld_hr_d8, rlca, /* 0X */ diff --git a/Core/symbol_hash.c b/Core/symbol_hash.c index a3718b8..66894f1 100644 --- a/Core/symbol_hash.c +++ b/Core/symbol_hash.c @@ -4,7 +4,7 @@ #include #include -static size_t GB_map_find_symbol_index(GB_symbol_map_t *map, uint16_t addr) +static size_t map_find_symbol_index(GB_symbol_map_t *map, uint16_t addr) { if (!map->symbols) { return 0; @@ -26,7 +26,7 @@ static size_t GB_map_find_symbol_index(GB_symbol_map_t *map, uint16_t addr) GB_bank_symbol_t *GB_map_add_symbol(GB_symbol_map_t *map, uint16_t addr, const char *name) { - size_t index = GB_map_find_symbol_index(map, addr); + size_t index = map_find_symbol_index(map, addr); map->symbols = realloc(map->symbols, (map->n_symbols + 1) * sizeof(map->symbols[0])); memmove(&map->symbols[index + 1], &map->symbols[index], (map->n_symbols - index) * sizeof(map->symbols[0])); @@ -39,7 +39,7 @@ GB_bank_symbol_t *GB_map_add_symbol(GB_symbol_map_t *map, uint16_t addr, const c const GB_bank_symbol_t *GB_map_find_symbol(GB_symbol_map_t *map, uint16_t addr) { if (!map) return NULL; - size_t index = GB_map_find_symbol_index(map, addr); + size_t index = map_find_symbol_index(map, addr); if (index >= map->n_symbols || map->symbols[index].addr != addr) { index--; } diff --git a/Core/timing.c b/Core/timing.c index 786dbc9..67c206e 100644 --- a/Core/timing.c +++ b/Core/timing.c @@ -8,7 +8,7 @@ #include #endif -static const unsigned GB_TAC_TRIGGER_BITS[] = {512, 8, 32, 128}; +static const unsigned TAC_TRIGGER_BITS[] = {512, 8, 32, 128}; #ifndef GB_DISABLE_TIMEKEEPING static int64_t get_nanoseconds(void) @@ -99,7 +99,7 @@ void GB_timing_sync(GB_gameboy_t *gb) #define IR_THRESHOLD 19900 #define IR_MAX IR_THRESHOLD * 2 + IR_DECAY -static void GB_ir_run(GB_gameboy_t *gb, uint32_t cycles) +static void ir_run(GB_gameboy_t *gb, uint32_t cycles) { if (gb->model == GB_MODEL_AGB) return; if (gb->infrared_input || gb->cart_ir || (gb->io_registers[GB_IO_RP] & 1)) { @@ -142,11 +142,11 @@ static void increase_tima(GB_gameboy_t *gb) } } -static void GB_set_internal_div_counter(GB_gameboy_t *gb, uint16_t value) +void GB_set_internal_div_counter(GB_gameboy_t *gb, uint16_t value) { /* TIMA increases when a specific high-bit becomes a low-bit. */ uint16_t triggers = gb->div_counter & ~value; - if ((gb->io_registers[GB_IO_TAC] & 4) && (triggers & GB_TAC_TRIGGER_BITS[gb->io_registers[GB_IO_TAC] & 3])) { + if ((gb->io_registers[GB_IO_TAC] & 4) && (triggers & TAC_TRIGGER_BITS[gb->io_registers[GB_IO_TAC] & 3])) { increase_tima(gb); } @@ -166,7 +166,7 @@ static void GB_set_internal_div_counter(GB_gameboy_t *gb, uint16_t value) gb->div_counter = value; } -static void GB_timers_run(GB_gameboy_t *gb, uint8_t cycles) +static void timers_run(GB_gameboy_t *gb, uint8_t cycles) { if (gb->stopped) { if (GB_is_cgb(gb)) { @@ -178,11 +178,8 @@ static void GB_timers_run(GB_gameboy_t *gb, uint8_t cycles) GB_STATE_MACHINE(gb, div, cycles, 1) { GB_STATE(gb, div, 1); GB_STATE(gb, div, 2); - GB_STATE(gb, div, 3); } - GB_set_internal_div_counter(gb, 0); -main: GB_SLEEP(gb, div, 1, 3); while (true) { advance_tima_state_machine(gb); @@ -190,14 +187,6 @@ main: gb->apu.apu_cycles += 4 << !gb->cgb_double_speed; GB_SLEEP(gb, div, 2, 4); } - - /* Todo: This is ugly to allow compatibility with 0.11 save states. Fix me when breaking save compatibility */ - { - div3: - /* Compensate for lack of prefetch emulation, as well as DIV's internal initial value */ - GB_set_internal_div_counter(gb, 8); - goto main; - } } static void advance_serial(GB_gameboy_t *gb, uint8_t cycles) @@ -247,7 +236,7 @@ static void advance_serial(GB_gameboy_t *gb, uint8_t cycles) } -static void GB_rtc_run(GB_gameboy_t *gb, uint8_t cycles) +static void rtc_run(GB_gameboy_t *gb, uint8_t cycles) { if (gb->cartridge_type->mbc_type != GB_HUC3 && !gb->cartridge_type->has_rtc) return; gb->rtc_cycles += cycles; @@ -274,10 +263,10 @@ static void GB_rtc_run(GB_gameboy_t *gb, uint8_t cycles) if (gb->cartridge_type->mbc_type == GB_HUC3) { while (gb->last_rtc_second / 60 < current_time / 60) { gb->last_rtc_second += 60; - gb->huc3_minutes++; - if (gb->huc3_minutes == 60 * 24) { - gb->huc3_days++; - gb->huc3_minutes = 0; + gb->huc3.minutes++; + if (gb->huc3.minutes == 60 * 24) { + gb->huc3.days++; + gb->huc3.minutes = 0; } } return; @@ -366,7 +355,7 @@ void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles) // Affected by speed boost gb->dma_cycles += cycles; - GB_timers_run(gb, cycles); + timers_run(gb, cycles); if (!gb->stopped) { advance_serial(gb, cycles); // TODO: Verify what happens in STOP mode } @@ -414,8 +403,8 @@ void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles) } GB_apu_run(gb); GB_display_run(gb, cycles); - GB_ir_run(gb, cycles); - GB_rtc_run(gb, cycles); + ir_run(gb, cycles); + rtc_run(gb, cycles); } /* @@ -428,8 +417,8 @@ void GB_emulate_timer_glitch(GB_gameboy_t *gb, uint8_t old_tac, uint8_t new_tac) /* Glitch only happens when old_tac is enabled. */ if (!(old_tac & 4)) return; - unsigned old_clocks = GB_TAC_TRIGGER_BITS[old_tac & 3]; - unsigned new_clocks = GB_TAC_TRIGGER_BITS[new_tac & 3]; + unsigned old_clocks = TAC_TRIGGER_BITS[old_tac & 3]; + unsigned new_clocks = TAC_TRIGGER_BITS[new_tac & 3]; /* The bit used for overflow testing must have been 1 */ if (gb->div_counter & old_clocks) { diff --git a/Core/timing.h b/Core/timing.h index 07e0473..b53eeec 100644 --- a/Core/timing.h +++ b/Core/timing.h @@ -7,6 +7,7 @@ void GB_advance_cycles(GB_gameboy_t *gb, uint8_t cycles); void GB_emulate_timer_glitch(GB_gameboy_t *gb, uint8_t old_tac, uint8_t new_tac); bool GB_timing_sync_turbo(GB_gameboy_t *gb); /* Returns true if should skip frame */ void GB_timing_sync(GB_gameboy_t *gb); +void GB_set_internal_div_counter(GB_gameboy_t *gb, uint16_t value); enum { GB_TIMA_RUNNING = 0,