diff --git a/apu/apu.cpp b/apu/apu.cpp index e5143ff3..5dbd9319 100644 --- a/apu/apu.cpp +++ b/apu/apu.cpp @@ -180,15 +180,17 @@ #include "apu.h" #include "snapshot.h" #include "display.h" -#include "resampler.h" +#include "linear_resampler.h" +#include "hermite_resampler.h" #define APU_DEFAULT_INPUT_RATE 32000 #define APU_MINIMUM_SAMPLE_COUNT 512 #define APU_MINIMUM_SAMPLE_BLOCK 128 -#define APU_NUMERATOR_NTSC 5632 -#define APU_DENOMINATOR_NTSC 118125 -#define APU_NUMERATOR_PAL 102400 -#define APU_DENOMINATOR_PAL 2128137 +#define APU_NUMERATOR_NTSC 15664 +#define APU_DENOMINATOR_NTSC 328125 +#define APU_NUMERATOR_PAL 34176 +#define APU_DENOMINATOR_PAL 709379 +#define APU_DEFAULT_RESAMPLER HermiteResampler SNES_SPC *spc_core = NULL; @@ -224,8 +226,12 @@ namespace spc static int32 reference_time; static uint32 remainder; - static const int32 timing_hack_numerator = SNES_SPC::tempo_unit; - static int32 timing_hack_denominator = SNES_SPC::tempo_unit; + static const int timing_hack_numerator = SNES_SPC::tempo_unit; + static int timing_hack_denominator = SNES_SPC::tempo_unit; + /* Set these to NTSC for now. Will change to PAL in S9xAPUTimingSetSpeedup + if necessary on game load. */ + static uint32 ratio_numerator = APU_NUMERATOR_NTSC; + static uint32 ratio_denominator = APU_DENOMINATOR_NTSC; } static void EightBitize (uint8 *, int); @@ -445,7 +451,7 @@ bool8 S9xInitSound (int buffer_ms, int lag_ms) arguments. Use 2x in the resampler for buffer leveling with SoundSync */ if (!spc::resampler) { - spc::resampler = new Resampler(spc::buffer_size >> (Settings.SoundSync ? 0 : 1)); + spc::resampler = new APU_DEFAULT_RESAMPLER(spc::buffer_size >> (Settings.SoundSync ? 0 : 1)); if (!spc::resampler) { delete[] spc::landing_buffer; @@ -534,22 +540,14 @@ void S9xDeinitAPU (void) static inline int S9xAPUGetClock (int32 cpucycles) { - if (Settings.PAL) - return ((int) floor(((double) APU_NUMERATOR_PAL * spc::timing_hack_numerator * (cpucycles - spc::reference_time) + spc::remainder) / - ((double) APU_DENOMINATOR_PAL * spc::timing_hack_denominator))); - else - return (APU_NUMERATOR_NTSC * spc::timing_hack_numerator * (cpucycles - spc::reference_time) + spc::remainder) / - (APU_DENOMINATOR_NTSC * spc::timing_hack_denominator); + return (spc::ratio_numerator * (cpucycles - spc::reference_time) + spc::remainder) / + spc::ratio_denominator; } static inline int S9xAPUGetClockRemainder (int32 cpucycles) { - if (Settings.PAL) - return ((int) fmod (((double) APU_NUMERATOR_PAL * spc::timing_hack_numerator * (cpucycles - spc::reference_time) + spc::remainder), - ((double) APU_DENOMINATOR_PAL * spc::timing_hack_denominator))); - else - return (APU_NUMERATOR_NTSC * spc::timing_hack_numerator * (cpucycles - spc::reference_time) + spc::remainder) % - (APU_DENOMINATOR_NTSC * spc::timing_hack_denominator); + return (spc::ratio_numerator * (cpucycles - spc::reference_time) + spc::remainder) % + spc::ratio_denominator; } uint8 S9xAPUReadPort (int port) @@ -590,9 +588,12 @@ void S9xAPUTimingSetSpeedup (int ticks) if (ticks != 0) printf("APU speedup hack: %d\n", ticks); - spc_core->set_tempo(SNES_SPC::tempo_unit - ticks); - spc::timing_hack_denominator = SNES_SPC::tempo_unit - ticks; + spc_core->set_tempo(spc::timing_hack_denominator); + + spc::ratio_numerator = Settings.PAL ? APU_NUMERATOR_PAL : APU_NUMERATOR_NTSC; + spc::ratio_denominator = Settings.PAL ? APU_DENOMINATOR_PAL : APU_DENOMINATOR_NTSC; + spc::ratio_denominator = spc::ratio_denominator * spc::timing_hack_denominator / spc::timing_hack_numerator; UpdatePlaybackRate(); } diff --git a/apu/hermite_resampler.h b/apu/hermite_resampler.h new file mode 100644 index 00000000..30ee1032 --- /dev/null +++ b/apu/hermite_resampler.h @@ -0,0 +1,144 @@ +/* Simple resampler based on bsnes's ruby audio library */ + +#ifndef __HERMITE_RESAMPLER_H +#define __HERMITE_RESAMPLER_H + +#include "resampler.h" + +#undef CLAMP +#undef SHORT_CLAMP +#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) +#define SHORT_CLAMP(n) ((short) CLAMP((n), -32768, 32767)) + +class HermiteResampler : public Resampler +{ + protected: + + double r_step; + double r_frac; + int r_left[4], r_right[4]; + + double + hermite (double mu1, double a, double b, double c, double d) + { + const double tension = 0.0; //-1 = low, 0 = normal, 1 = high + const double bias = 0.0; //-1 = left, 0 = even, 1 = right + + double mu2, mu3, m0, m1, a0, a1, a2, a3; + + mu2 = mu1 * mu1; + mu3 = mu2 * mu1; + + m0 = (b - a) * (1 + bias) * (1 - tension) / 2; + m0 += (c - b) * (1 - bias) * (1 - tension) / 2; + m1 = (c - b) * (1 + bias) * (1 - tension) / 2; + m1 += (d - c) * (1 - bias) * (1 - tension) / 2; + + a0 = +2 * mu3 - 3 * mu2 + 1; + a1 = mu3 - 2 * mu2 + mu1; + a2 = mu3 - mu2; + a3 = -2 * mu3 + 3 * mu2; + + return (a0 * b) + (a1 * m0) + (a2 * m1) + (a3 * c); + } + + public: + HermiteResampler (int num_samples) : Resampler (num_samples) + { + clear (); + } + + ~HermiteResampler () + { + } + + void + time_ratio (double ratio) + { + r_step = ratio; + clear (); + } + + void + clear (void) + { + ring_buffer::clear (); + r_frac = 1.0; + r_left [0] = r_left [1] = r_left [2] = r_left [3] = 0; + r_right[0] = r_right[1] = r_right[2] = r_right[3] = 0; + } + + void + read (short *data, int num_samples) + { + int i_position = start >> 1; + short *internal_buffer = (short *) buffer; + int o_position = 0; + int consumed = 0; + + while (o_position < num_samples && consumed < buffer_size) + { + int s_left = internal_buffer[i_position]; + int s_right = internal_buffer[i_position + 1]; + int max_samples = buffer_size >> 1; + const double margin_of_error = 1.0e-10; + + if (fabs(r_step - 1.0) < margin_of_error) + { + data[o_position] = (short) s_left; + data[o_position + 1] = (short) s_right; + + o_position += 2; + i_position += 2; + if (i_position >= max_samples) + i_position -= max_samples; + consumed += 2; + + continue; + } + + while (r_frac <= 1.0 && o_position < num_samples) + { + data[o_position] = SHORT_CLAMP (hermite (r_frac, r_left [0], r_left [1], r_left [2], r_left [3])); + data[o_position + 1] = SHORT_CLAMP (hermite (r_frac, r_right[0], r_right[1], r_right[2], r_right[3])); + + o_position += 2; + + r_frac += r_step; + } + + if (r_frac > 1.0) + { + r_left [0] = r_left [1]; + r_left [1] = r_left [2]; + r_left [2] = r_left [3]; + r_left [3] = s_left; + + r_right[0] = r_right[1]; + r_right[1] = r_right[2]; + r_right[2] = r_right[3]; + r_right[3] = s_right; + + r_frac -= 1.0; + + i_position += 2; + if (i_position >= max_samples) + i_position -= max_samples; + consumed += 2; + } + } + + size -= consumed << 1; + start += consumed << 1; + if (start >= buffer_size) + start -= buffer_size; + } + + inline int + avail (void) + { + return (int) floor (((size >> 2) - r_frac) / r_step) * 2; + } +}; + +#endif /* __HERMITE_RESAMPLER_H */ diff --git a/apu/linear_resampler.h b/apu/linear_resampler.h new file mode 100644 index 00000000..35789db1 --- /dev/null +++ b/apu/linear_resampler.h @@ -0,0 +1,115 @@ +/* Simple fixed-point linear resampler by BearOso*/ + +#ifndef __LINEAR_RESAMPLER_H +#define __LINEAR_RESAMPLER_H + +#include "resampler.h" +#include "snes9x.h" + +static const int f_prec = 15; +static const uint32 f__one = (1 << f_prec); + +#define lerp(t, a, b) (((((b) - (a)) * (t)) >> f_prec) + (a)) + +class LinearResampler : public Resampler +{ + protected: + uint32 f__r_step; + uint32 f__inv_r_step; + uint32 f__r_frac; + int r_left, r_right; + + public: + LinearResampler (int num_samples) : Resampler (num_samples) + { + f__r_frac = 0; + } + + ~LinearResampler () + { + } + + void + time_ratio (double ratio) + { + if (ratio == 0.0) + ratio = 1.0; + f__r_step = (uint32) (ratio * f__one); + f__inv_r_step = (uint32) (f__one / ratio); + clear (); + } + + void + clear (void) + { + ring_buffer::clear (); + f__r_frac = 0; + r_left = 0; + r_right = 0; + } + + void + read (short *data, int num_samples) + { + int i_position = start >> 1; + short *internal_buffer = (short *) buffer; + int o_position = 0; + int consumed = 0; + int max_samples = (buffer_size >> 1); + + while (o_position < num_samples && consumed < buffer_size) + { + if (f__r_step == f__one) + { + data[o_position] = internal_buffer[i_position]; + data[o_position + 1] = internal_buffer[i_position + 1]; + + o_position += 2; + i_position += 2; + if (i_position >= max_samples) + i_position -= max_samples; + consumed += 2; + + continue; + } + + while (f__r_frac <= f__one && o_position < num_samples) + { + data[o_position] = lerp (f__r_frac, + r_left, + internal_buffer[i_position]); + data[o_position + 1] = lerp (f__r_frac, + r_right, + internal_buffer[i_position + 1]); + + o_position += 2; + + f__r_frac += f__r_step; + } + + if (f__r_frac > f__one) + { + f__r_frac -= f__one; + r_left = internal_buffer[i_position]; + r_right = internal_buffer[i_position + 1]; + i_position += 2; + if (i_position >= max_samples) + i_position -= max_samples; + consumed += 2; + } + } + + size -= consumed << 1; + start += consumed << 1; + if (start >= buffer_size) + start -= buffer_size; + } + + inline int + avail (void) + { + return (((size >> 2) * f__inv_r_step) - ((f__r_frac * f__inv_r_step) >> f_prec)) >> (f_prec - 1); + } +}; + +#endif /* __LINEAR_RESAMPLER_H */ diff --git a/apu/resampler.h b/apu/resampler.h index 51a32266..2e62addb 100644 --- a/apu/resampler.h +++ b/apu/resampler.h @@ -5,158 +5,56 @@ #include "ring_buffer.h" -#undef MIN -#define MIN(a, b) ((a) < (b) ? (a) : (b)) - -#undef CLAMP -#undef short_clamp -#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) -#define short_clamp(n) ((short) CLAMP((n), -32768, 32767)) - class Resampler : public ring_buffer { - protected: - - double r_step; - double r_frac; - int r_left[4], r_right[4]; - - double - hermite (double mu1, double a, double b, double c, double d) - { - const double tension = 0.0; //-1 = low, 0 = normal, 1 = high - const double bias = 0.0; //-1 = left, 0 = even, 1 = right - - double mu2, mu3, m0, m1, a0, a1, a2, a3; - - mu2 = mu1 * mu1; - mu3 = mu2 * mu1; - - m0 = (b - a) * (1 + bias) * (1 - tension) / 2; - m0 += (c - b) * (1 - bias) * (1 - tension) / 2; - m1 = (c - b) * (1 + bias) * (1 - tension) / 2; - m1 += (d - c) * (1 - bias) * (1 - tension) / 2; - - a0 = +2 * mu3 - 3 * mu2 + 1; - a1 = mu3 - 2 * mu2 + mu1; - a2 = mu3 - mu2; - a3 = -2 * mu3 + 3 * mu2; - - return (a0 * b) + (a1 * m0) + (a2 * m1) + (a3 * c); - } - public: + virtual void clear (void) = 0; + virtual void time_ratio (double) = 0; + virtual void read (short *, int) = 0; + virtual int avail (void) = 0; + Resampler (int num_samples) : ring_buffer (num_samples << 1) { - r_frac = 0.0; } ~Resampler () { } - void - time_ratio (double ratio) - { - r_step = ratio; - clear (); - } - - void - clear (void) - { - ring_buffer::clear (); - r_frac = 0; - r_left [0] = r_left [1] = r_left [2] = r_left [3] = 0; - r_right[0] = r_right[1] = r_right[2] = r_right[3] = 0; - } - - void - read (short *data, int num_samples) - { - int i_position = start >> 1; - short *internal_buffer = (short *) buffer; - int o_position = 0; - int consumed = 0; - - while (o_position < num_samples && consumed < buffer_size) - { - int s_left = internal_buffer[i_position]; - int s_right = internal_buffer[i_position + 1]; - const double margin_of_error = 1.0e-10; - - if (fabs(r_step - 1.0) < margin_of_error) - { - data[o_position] = (short) s_left; - data[o_position + 1] = (short) s_right; - - o_position += 2; - i_position = (i_position + 2) % (buffer_size >> 1); - consumed += 2; - - continue; - } - - r_left [0] = r_left [1]; - r_left [1] = r_left [2]; - r_left [2] = r_left [3]; - r_left [3] = s_left; - - r_right[0] = r_right[1]; - r_right[1] = r_right[2]; - r_right[2] = r_right[3]; - r_right[3] = s_right; - - while (r_frac <= 1.0 && o_position < num_samples) - { - data[o_position] = short_clamp (hermite (r_frac, r_left [0], r_left [1], r_left [2], r_left [3])); - data[o_position + 1] = short_clamp (hermite (r_frac, r_right[0], r_right[1], r_right[2], r_right[3])); - - o_position += 2; - - r_frac += r_step; - } - - if (r_frac > 1.0) - { - r_frac -= 1.0; - i_position = (i_position + 2) % (buffer_size >> 1); - consumed += 2; - } - } - - size -= consumed << 1; - start = (start + (consumed << 1)) % buffer_size; - } - - bool + inline bool push (short *src, int num_samples) { if (max_write () < num_samples) return false; - ring_buffer::push ((unsigned char *) src, num_samples << 1); + !num_samples || ring_buffer::push ((unsigned char *) src, num_samples << 1); return true; } - int + inline int + space_empty (void) + { + return buffer_size - size; + } + + inline int + space_filled (void) + { + return size; + } + + inline int max_write (void) { return space_empty () >> 1; } - void + inline void resize (int num_samples) { ring_buffer::resize (num_samples << 1); } - - int - avail (void) - { - return (int) floor (((size >> 2) - r_frac) / r_step) * 2; - } }; #endif /* __RESAMPLER_H */ diff --git a/cpu.cpp b/cpu.cpp index 91c986cf..3e249cc5 100644 --- a/cpu.cpp +++ b/cpu.cpp @@ -207,22 +207,6 @@ static void S9xResetCPU (void) static void S9xSoftResetCPU (void) { - Registers.PBPC = 0; - Registers.PB = 0; - Registers.PCw = S9xGetWord(0xfffc); - OpenBus = Registers.PCh; - Registers.D.W = 0; - Registers.DB = 0; - Registers.SH = 1; - Registers.SL -= 3; - Registers.XH = 0; - Registers.YH = 0; - - ICPU.ShiftedPB = 0; - ICPU.ShiftedDB = 0; - SetFlags(MemoryFlag | IndexFlag | IRQ | Emulation); - ClearFlags(Decimal); - CPU.Cycles = 182; // Or 188. This is the cycle count just after the jump to the Reset Vector. CPU.PrevCycles = -1; CPU.V_Counter = 0; @@ -248,6 +232,22 @@ static void S9xSoftResetCPU (void) CPU.AutoSaveTimer = 0; CPU.SRAMModified = FALSE; + Registers.PBPC = 0; + Registers.PB = 0; + Registers.PCw = S9xGetWord(0xfffc); + OpenBus = Registers.PCh; + Registers.D.W = 0; + Registers.DB = 0; + Registers.SH = 1; + Registers.SL -= 3; + Registers.XH = 0; + Registers.YH = 0; + + ICPU.ShiftedPB = 0; + ICPU.ShiftedDB = 0; + SetFlags(MemoryFlag | IndexFlag | IRQ | Emulation); + ClearFlags(Decimal); + Timings.InterlaceField = FALSE; Timings.H_Max = Timings.H_Max_Master; Timings.V_Max = Timings.V_Max_Master; diff --git a/cpuexec.cpp b/cpuexec.cpp index d7f22db9..1b9d892b 100644 --- a/cpuexec.cpp +++ b/cpuexec.cpp @@ -307,8 +307,10 @@ void S9xMainLoop (void) if (SA1.Executing) S9xSA1MainLoop(); + #if (S9X_ACCURACY_LEVEL <= 2) while (CPU.Cycles >= CPU.NextEvent) S9xDoHEventProcessing(); + #endif } S9xPackStatus(); @@ -355,10 +357,29 @@ void S9xClearIRQ (uint32 source) void S9xDoHEventProcessing (void) { +#ifdef DEBUGGER + static char eventname[13][32] = + { + "", + "HC_HBLANK_START_EVENT", + "HC_IRQ_1_3_EVENT ", + "HC_HDMA_START_EVENT ", + "HC_IRQ_3_5_EVENT ", + "HC_HCOUNTER_MAX_EVENT", + "HC_IRQ_5_7_EVENT ", + "HC_HDMA_INIT_EVENT ", + "HC_IRQ_7_9_EVENT ", + "HC_RENDER_EVENT ", + "HC_IRQ_9_A_EVENT ", + "HC_WRAM_REFRESH_EVENT", + "HC_IRQ_A_1_EVENT " + }; +#endif + #ifdef DEBUGGER if (Settings.TraceHCEvent) - S9xTraceFormattedMessage("--- HC event processing (%02d) expected HC:%04d executed HC:%04d", - CPU.WhichEvent, CPU.NextEvent, CPU.Cycles); + S9xTraceFormattedMessage("--- HC event processing (%s) expected HC:%04d executed HC:%04d", + eventname[CPU.WhichEvent], CPU.NextEvent, CPU.Cycles); #endif #ifdef CPU_SHUTDOWN @@ -366,13 +387,16 @@ void S9xDoHEventProcessing (void) #endif switch (CPU.WhichEvent) - { + { case HC_HBLANK_START_EVENT: S9xCheckMissingHTimerPosition(Timings.HBlankStart); - + S9xReschedule(); break; case HC_HDMA_START_EVENT: + S9xCheckMissingHTimerPosition(Timings.HDMAStart); + S9xReschedule(); + if (PPU.HDMA && CPU.V_Counter <= PPU.ScreenHeight) { #ifdef DEBUGGER @@ -381,8 +405,6 @@ void S9xDoHEventProcessing (void) PPU.HDMA = S9xDoHDMA(PPU.HDMA); } - S9xCheckMissingHTimerPosition(Timings.HDMAStart); - break; case HC_HCOUNTER_MAX_EVENT: @@ -470,7 +492,7 @@ void S9xDoHEventProcessing (void) missing.dma_this_frame = 0; #endif IPPU.MaxBrightness = PPU.Brightness; - PPU.ForcedBlanking = (Memory.FillRAM [0x2100] >> 7) & 1; + PPU.ForcedBlanking = (Memory.FillRAM[0x2100] >> 7) & 1; if (!PPU.ForcedBlanking) { @@ -511,14 +533,21 @@ void S9xDoHEventProcessing (void) S9xStartScreenRefresh(); CPU.NextEvent = -1; + S9xReschedule(); break; case HC_HDMA_INIT_EVENT: - if (CPU.V_Counter == 0) - S9xStartHDMA(); - S9xCheckMissingHTimerPosition(Timings.HDMAInit); + S9xReschedule(); + + if (CPU.V_Counter == 0) + { + #ifdef DEBUGGER + S9xTraceFormattedMessage("*** HDMA Init HC:%04d, Channel:%02x", CPU.Cycles, PPU.HDMA); + #endif + S9xStartHDMA(); + } break; @@ -527,6 +556,7 @@ void S9xDoHEventProcessing (void) RenderLine((uint8) (CPU.V_Counter - FIRST_VISIBLE_LINE)); S9xCheckMissingHTimerPosition(Timings.RenderPos); + S9xReschedule(); break; @@ -534,10 +564,12 @@ void S9xDoHEventProcessing (void) #ifdef DEBUGGER S9xTraceFormattedMessage("*** WRAM Refresh HC:%04d", CPU.Cycles); #endif + S9xCheckMissingHTimerHalt(Timings.WRAMRefreshPos, SNES_WRAM_REFRESH_CYCLES); CPU.Cycles += SNES_WRAM_REFRESH_CYCLES; S9xCheckMissingHTimerPosition(Timings.WRAMRefreshPos); + S9xReschedule(); break; @@ -553,13 +585,13 @@ void S9xDoHEventProcessing (void) if (PPU.VTimerEnabled && (CPU.V_Counter == PPU.VTimerPosition)) S9xSetIRQ(PPU_IRQ_SOURCE); + S9xReschedule(); break; - } - - S9xReschedule(); + } #ifdef DEBUGGER if (Settings.TraceHCEvent) - S9xTraceFormattedMessage("--- HC event rescheduled (%02d) expected HC:%04d", CPU.WhichEvent, CPU.NextEvent); + S9xTraceFormattedMessage("--- HC event rescheduled (%s) expected HC:%04d current HC:%04d", + eventname[CPU.WhichEvent], CPU.NextEvent, CPU.Cycles); #endif } diff --git a/cpuops.cpp b/cpuops.cpp index c10a0c09..ea8d8653 100644 --- a/cpuops.cpp +++ b/cpuops.cpp @@ -190,7 +190,11 @@ #ifdef SA1_OPCODES #define AddCycles(n) { } #else -#define AddCycles(n) CPU.Cycles += n +#if (S9X_ACCURACY_LEVEL >= 3) +#define AddCycles(n) { CPU.Cycles += (n); while (CPU.Cycles >= CPU.NextEvent) S9xDoHEventProcessing(); } +#else +#define AddCycles(n) { CPU.Cycles += (n); } +#endif #endif #include "cpuaddr.h" diff --git a/debug.cpp b/debug.cpp index 94918e68..555ca086 100644 --- a/debug.cpp +++ b/debug.cpp @@ -317,6 +317,10 @@ static int AddrModes[256] = 4, 11, 9, 20, 26, 7, 7, 13, 0, 16, 0, 0, 23, 15, 15, 18 // F }; +static uint8 S9xDebugGetByte (uint32); +static uint16 S9xDebugGetWord (uint32); +static uint8 S9xDebugSA1GetByte (uint32); +static uint16 S9xDebugSA1GetWord (uint32); static uint8 debug_cpu_op_print (char *, uint8, uint16); static uint8 debug_sa1_op_print (char *, uint8, uint16); static void debug_line_print (const char *); @@ -329,6 +333,107 @@ static void debug_whats_used (void); static void debug_whats_missing (void); +static uint8 S9xDebugGetByte (uint32 Address) +{ + int block = (Address & 0xffffff) >> MEMMAP_SHIFT; + uint8 *GetAddress = Memory.Map[block]; + uint8 byte = 0; + + if (GetAddress >= (uint8 *) CMemory::MAP_LAST) + { + byte = *(GetAddress + (Address & 0xffff)); + return (byte); + } + + switch ((pint) GetAddress) + { + case CMemory::MAP_LOROM_SRAM: + case CMemory::MAP_SA1RAM: + byte = *(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask)); + return (byte); + + case CMemory::MAP_LOROM_SRAM_B: + byte = *(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB)); + return (byte); + + case CMemory::MAP_HIROM_SRAM: + case CMemory::MAP_RONLY_SRAM: + byte = *(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask)); + return (byte); + + case CMemory::MAP_BWRAM: + byte = *(Memory.BWRAM + ((Address & 0x7fff) - 0x6000)); + return (byte); + + default: + return (byte); + } +} + +static uint16 S9xDebugGetWord (uint32 Address) +{ + uint16 word; + + word = S9xDebugGetByte(Address); + word |= S9xDebugGetByte(Address + 1) << 8; + + return (word); +} + +static uint8 S9xDebugSA1GetByte (uint32 Address) +{ + int block = (Address & 0xffffff) >> MEMMAP_SHIFT; + uint8 *GetAddress = SA1.Map[block]; + uint8 byte = 0; + + if (GetAddress >= (uint8 *) CMemory::MAP_LAST) + { + byte = *(GetAddress + (Address & 0xffff)); + return (byte); + } + + switch ((pint) GetAddress) + { + case CMemory::MAP_LOROM_SRAM: + case CMemory::MAP_SA1RAM: + byte = *(Memory.SRAM + (Address & 0xffff)); + return (byte); + + case CMemory::MAP_BWRAM: + byte = *(SA1.BWRAM + ((Address & 0x7fff) - 0x6000)); + return (byte); + + case CMemory::MAP_BWRAM_BITMAP: + Address -= 0x600000; + if (SA1.VirtualBitmapFormat == 2) + byte = (Memory.SRAM[(Address >> 2) & 0xffff] >> ((Address & 3) << 1)) & 3; + else + byte = (Memory.SRAM[(Address >> 1) & 0xffff] >> ((Address & 1) << 2)) & 15; + return (byte); + + case CMemory::MAP_BWRAM_BITMAP2: + Address = (Address & 0xffff) - 0x6000; + if (SA1.VirtualBitmapFormat == 2) + byte = (SA1.BWRAM[(Address >> 2) & 0xffff] >> ((Address & 3) << 1)) & 3; + else + byte = (SA1.BWRAM[(Address >> 1) & 0xffff] >> ((Address & 1) << 2)) & 15; + return (byte); + + default: + return (byte); + } +} + +static uint16 S9xDebugSA1GetWord (uint32 Address) +{ + uint16 word; + + word = S9xDebugSA1GetByte(Address); + word |= S9xDebugSA1GetByte(Address + 1) << 8; + + return (word); +} + static uint8 debug_cpu_op_print (char *Line, uint8 Bank, uint16 Address) { uint8 S9xOpcode; @@ -339,15 +444,12 @@ static uint8 debug_cpu_op_print (char *Line, uint8 Bank, uint16 Address) int8 SByte; uint8 Size = 0; - int32 Cycles = CPU.Cycles; - uint32 WaitAddress = CPU.WaitAddress; - - S9xOpcode = S9xGetByte((Bank << 16) + Address); + S9xOpcode = S9xDebugGetByte((Bank << 16) + Address); sprintf(Line, "$%02X:%04X %02X ", Bank, Address, S9xOpcode); - Operant[0] = S9xGetByte((Bank << 16) + Address + 1); - Operant[1] = S9xGetByte((Bank << 16) + Address + 2); - Operant[2] = S9xGetByte((Bank << 16) + Address + 3); + Operant[0] = S9xDebugGetByte((Bank << 16) + Address + 1); + Operant[1] = S9xDebugGetByte((Bank << 16) + Address + 2); + Operant[2] = S9xDebugGetByte((Bank << 16) + Address + 3); switch (AddrModes[S9xOpcode]) { @@ -505,7 +607,7 @@ static uint8 debug_cpu_op_print (char *Line, uint8 Bank, uint16 Address) Operant[0]); Word = Operant[0]; Word += Registers.D.W; - Word = S9xGetWord(Word); + Word = S9xDebugGetWord(Word); sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word); Size = 2; break; @@ -520,7 +622,7 @@ static uint8 debug_cpu_op_print (char *Line, uint8 Bank, uint16 Address) Word = Operant[0]; Word += Registers.D.W; Word += Registers.X.W; - Word = S9xGetWord(Word); + Word = S9xDebugGetWord(Word); sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word); Size = 2; break; @@ -534,7 +636,7 @@ static uint8 debug_cpu_op_print (char *Line, uint8 Bank, uint16 Address) Operant[0]); Word = Operant[0]; Word += Registers.D.W; - Word = S9xGetWord(Word); + Word = S9xDebugGetWord(Word); Word += Registers.Y.W; sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word); Size = 2; @@ -549,8 +651,8 @@ static uint8 debug_cpu_op_print (char *Line, uint8 Bank, uint16 Address) Operant[0]); Word = Operant[0]; Word += Registers.D.W; - Byte = S9xGetByte(Word + 2); - Word = S9xGetWord(Word); + Byte = S9xDebugGetByte(Word + 2); + Word = S9xDebugGetWord(Word); sprintf(Line, "%-32s[$%02X:%04X]", Line, Byte, Word); Size = 2; break; @@ -564,8 +666,8 @@ static uint8 debug_cpu_op_print (char *Line, uint8 Bank, uint16 Address) Operant[0]); Word = Operant[0]; Word += Registers.D.W; - Byte = S9xGetByte(Word + 2); - Word = S9xGetWord(Word); + Byte = S9xDebugGetByte(Word + 2); + Word = S9xDebugGetWord(Word); Word += Registers.Y.W; sprintf(Line, "%-32s[$%02X:%04X]", Line, Byte, Word); Size = 2; @@ -670,7 +772,7 @@ static uint8 debug_cpu_op_print (char *Line, uint8 Bank, uint16 Address) Operant[0]); Word = Registers.S.W; Word += Operant[0]; - Word = S9xGetWord(Word); + Word = S9xDebugGetWord(Word); Word += Registers.Y.W; sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word); Size = 2; @@ -686,7 +788,7 @@ static uint8 debug_cpu_op_print (char *Line, uint8 Bank, uint16 Address) Operant[1], Operant[0]); Word = (Operant[1] << 8) | Operant[0]; - Word = S9xGetWord(Word); + Word = S9xDebugGetWord(Word); sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.PB, Word); Size = 3; break; @@ -701,8 +803,8 @@ static uint8 debug_cpu_op_print (char *Line, uint8 Bank, uint16 Address) Operant[1], Operant[0]); Word = (Operant[1] << 8) | Operant[0]; - Byte = S9xGetByte(Word + 2); - Word = S9xGetWord(Word); + Byte = S9xDebugGetByte(Word + 2); + Word = S9xDebugGetWord(Word); sprintf(Line, "%-32s[$%02X:%04X]", Line, Byte, Word); Size = 3; break; @@ -718,7 +820,7 @@ static uint8 debug_cpu_op_print (char *Line, uint8 Bank, uint16 Address) Operant[0]); Word = (Operant[1] << 8) | Operant[0]; Word += Registers.X.W; - Word = S9xGetWord(ICPU.ShiftedPB + Word); + Word = S9xDebugGetWord(ICPU.ShiftedPB + Word); sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.PB, Word); Size = 3; break; @@ -764,7 +866,7 @@ static uint8 debug_cpu_op_print (char *Line, uint8 Bank, uint16 Address) Operant[0]); Word = Operant[0]; Word += Registers.D.W; - Word = S9xGetWord(Word); + Word = S9xDebugGetWord(Word); sprintf(Line, "%-32s[$%04X]", Line, Word); Size = 2; break; @@ -782,14 +884,11 @@ static uint8 debug_cpu_op_print (char *Line, uint8 Bank, uint16 Address) CheckIRQ() ? 'I' : 'i', CheckZero() ? 'Z' : 'z', CheckCarry() ? 'C' : 'c', - (long) Cycles, + (long) CPU.Cycles, (long) CPU.V_Counter, IPPU.FrameCount, CPU.IRQActive); - CPU.Cycles = Cycles; - CPU.WaitAddress = WaitAddress; - return (Size); } @@ -803,12 +902,12 @@ static uint8 debug_sa1_op_print (char *Line, uint8 Bank, uint16 Address) int8 SByte; uint8 Size = 0; - S9xOpcode = S9xSA1GetByte((Bank << 16) + Address); + S9xOpcode = S9xDebugSA1GetByte((Bank << 16) + Address); sprintf(Line, "$%02X:%04X %02X ", Bank, Address, S9xOpcode); - Operant[0] = S9xSA1GetByte((Bank << 16) + Address + 1); - Operant[1] = S9xSA1GetByte((Bank << 16) + Address + 2); - Operant[2] = S9xSA1GetByte((Bank << 16) + Address + 3); + Operant[0] = S9xDebugSA1GetByte((Bank << 16) + Address + 1); + Operant[1] = S9xDebugSA1GetByte((Bank << 16) + Address + 2); + Operant[2] = S9xDebugSA1GetByte((Bank << 16) + Address + 3); switch (AddrModes[S9xOpcode]) { @@ -966,7 +1065,7 @@ static uint8 debug_sa1_op_print (char *Line, uint8 Bank, uint16 Address) Operant[0]); Word = Operant[0]; Word += SA1Registers.D.W; - Word = S9xSA1GetWord(Word); + Word = S9xDebugSA1GetWord(Word); sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.DB, Word); Size = 2; break; @@ -981,7 +1080,7 @@ static uint8 debug_sa1_op_print (char *Line, uint8 Bank, uint16 Address) Word = Operant[0]; Word += SA1Registers.D.W; Word += SA1Registers.X.W; - Word = S9xSA1GetWord(Word); + Word = S9xDebugSA1GetWord(Word); sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.DB, Word); Size = 2; break; @@ -995,7 +1094,7 @@ static uint8 debug_sa1_op_print (char *Line, uint8 Bank, uint16 Address) Operant[0]); Word = Operant[0]; Word += SA1Registers.D.W; - Word = S9xSA1GetWord(Word); + Word = S9xDebugSA1GetWord(Word); Word += SA1Registers.Y.W; sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.DB, Word); Size = 2; @@ -1010,8 +1109,8 @@ static uint8 debug_sa1_op_print (char *Line, uint8 Bank, uint16 Address) Operant[0]); Word = Operant[0]; Word += SA1Registers.D.W; - Byte = S9xSA1GetByte(Word + 2); - Word = S9xSA1GetWord(Word); + Byte = S9xDebugSA1GetByte(Word + 2); + Word = S9xDebugSA1GetWord(Word); sprintf(Line, "%-32s[$%02X:%04X]", Line, Byte, Word); Size = 2; break; @@ -1025,8 +1124,8 @@ static uint8 debug_sa1_op_print (char *Line, uint8 Bank, uint16 Address) Operant[0]); Word = Operant[0]; Word += SA1Registers.D.W; - Byte = S9xSA1GetByte(Word + 2); - Word = S9xSA1GetWord(Word); + Byte = S9xDebugSA1GetByte(Word + 2); + Word = S9xDebugSA1GetWord(Word); Word += SA1Registers.Y.W; sprintf(Line, "%-32s[$%02X:%04X]", Line, Byte, Word); Size = 2; @@ -1131,7 +1230,7 @@ static uint8 debug_sa1_op_print (char *Line, uint8 Bank, uint16 Address) Operant[0]); Word = SA1Registers.S.W; Word += Operant[0]; - Word = S9xSA1GetWord(Word); + Word = S9xDebugSA1GetWord(Word); Word += SA1Registers.Y.W; sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.DB, Word); Size = 2; @@ -1147,7 +1246,7 @@ static uint8 debug_sa1_op_print (char *Line, uint8 Bank, uint16 Address) Operant[1], Operant[0]); Word = (Operant[1] << 8) | Operant[0]; - Word = S9xSA1GetWord(Word); + Word = S9xDebugSA1GetWord(Word); sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.PB, Word); Size = 3; break; @@ -1162,8 +1261,8 @@ static uint8 debug_sa1_op_print (char *Line, uint8 Bank, uint16 Address) Operant[1], Operant[0]); Word = (Operant[1] << 8) | Operant[0]; - Byte = S9xSA1GetByte(Word + 2); - Word = S9xSA1GetWord(Word); + Byte = S9xDebugSA1GetByte(Word + 2); + Word = S9xDebugSA1GetWord(Word); sprintf(Line, "%-32s[$%02X:%04X]", Line, Byte, Word); Size = 3; break; @@ -1179,7 +1278,7 @@ static uint8 debug_sa1_op_print (char *Line, uint8 Bank, uint16 Address) Operant[0]); Word = (Operant[1] << 8) | Operant[0]; Word += SA1Registers.X.W; - Word = S9xSA1GetWord(SA1.ShiftedPB + Word); + Word = S9xDebugSA1GetWord(SA1.ShiftedPB + Word); sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.PB, Word); Size = 3; break; @@ -1275,7 +1374,7 @@ static void debug_process_command (char *Line) if (fs) { for (int i = 0; i < Count; i++) - putc(S9xGetByte(Address + i), fs); + putc(S9xDebugGetByte(Address + i), fs); fclose(fs); } else @@ -1292,17 +1391,17 @@ static void debug_process_command (char *Line) printf("Vectors:\n"); sprintf(string, " 8 Bit 16 Bit "); debug_line_print(string); - sprintf(string, "ABT $00:%04X|$00:%04X", S9xGetWord(0xFFF8), S9xGetWord(0xFFE8)); + sprintf(string, "ABT $00:%04X|$00:%04X", S9xDebugGetWord(0xFFF8), S9xDebugGetWord(0xFFE8)); debug_line_print(string); - sprintf(string, "BRK $00:%04X|$00:%04X", S9xGetWord(0xFFFE), S9xGetWord(0xFFE6)); + sprintf(string, "BRK $00:%04X|$00:%04X", S9xDebugGetWord(0xFFFE), S9xDebugGetWord(0xFFE6)); debug_line_print(string); - sprintf(string, "COP $00:%04X|$00:%04X", S9xGetWord(0xFFF4), S9xGetWord(0xFFE4)); + sprintf(string, "COP $00:%04X|$00:%04X", S9xDebugGetWord(0xFFF4), S9xDebugGetWord(0xFFE4)); debug_line_print(string); - sprintf(string, "IRQ $00:%04X|$00:%04X", S9xGetWord(0xFFFE), S9xGetWord(0xFFEE)); + sprintf(string, "IRQ $00:%04X|$00:%04X", S9xDebugGetWord(0xFFFE), S9xDebugGetWord(0xFFEE)); debug_line_print(string); - sprintf(string, "NMI $00:%04X|$00:%04X", S9xGetWord(0xFFFA), S9xGetWord(0xFFEA)); + sprintf(string, "NMI $00:%04X|$00:%04X", S9xDebugGetWord(0xFFFA), S9xDebugGetWord(0xFFEA)); debug_line_print(string); - sprintf(string, "RES $00:%04X", S9xGetWord(0xFFFC)); + sprintf(string, "RES $00:%04X", S9xDebugGetWord(0xFFFC)); debug_line_print(string); } @@ -1733,7 +1832,6 @@ static void debug_process_command (char *Line) int CLine; int CByte; uint8 MemoryByte; - int32 Cycles = CPU.Cycles; if (Debug.Dump.Bank != 0 || Debug.Dump.Address != 0) { @@ -1756,7 +1854,7 @@ static void debug_process_command (char *Line) Address + CByte == 0x4210) MemoryByte = 0; else - MemoryByte = S9xGetByte((Bank << 16) + Address + CByte); + MemoryByte = S9xDebugGetByte((Bank << 16) + Address + CByte); sprintf(string, "%s %02X", string, MemoryByte); } @@ -1772,7 +1870,7 @@ static void debug_process_command (char *Line) Address + CByte == 0x4210) MemoryByte = 0; else - MemoryByte = S9xGetByte((Bank << 16) + Address + CByte); + MemoryByte = S9xDebugGetByte((Bank << 16) + Address + CByte); if (MemoryByte < 32 || MemoryByte >= 127) MemoryByte = '?'; @@ -1787,8 +1885,6 @@ static void debug_process_command (char *Line) Debug.Dump.Bank = Bank; Debug.Dump.Address = Address; - - CPU.Cycles = Cycles; } if (*Line == 'q') diff --git a/dma.cpp b/dma.cpp index ef8d7377..bd2c6f22 100644 --- a/dma.cpp +++ b/dma.cpp @@ -185,6 +185,8 @@ #include "missing.h" #endif +#define ADD_CYCLES(n) CPU.Cycles += (n) + extern uint8 *HDMAMemPointers[8]; extern int HDMA_ModeByteCounts[8]; extern SPC7110 s7emu; @@ -199,7 +201,7 @@ static inline bool8 addCyclesInDMA (uint8 dma_channel) { // Add 8 cycles per byte, sync APU, and do HC related events. // If HDMA was done in S9xDoHEventProcessing(), check if it used the same channel as DMA. - CPU.Cycles += SLOW_ONE_CYCLE; + ADD_CYCLES(SLOW_ONE_CYCLE); while (CPU.Cycles >= CPU.NextEvent) S9xDoHEventProcessing(); @@ -245,7 +247,7 @@ bool8 S9xDoDMA (uint8 Channel) c = 0x10000; // 8 cycles per channel - CPU.Cycles += SLOW_ONE_CYCLE; + ADD_CYCLES(SLOW_ONE_CYCLE); // 8 cycles per byte while (c) { @@ -510,7 +512,7 @@ bool8 S9xDoDMA (uint8 Channel) uint8 Work; // 8 cycles per channel - CPU.Cycles += SLOW_ONE_CYCLE; + ADD_CYCLES(SLOW_ONE_CYCLE); if (!d->ReverseTransfer) { @@ -1315,7 +1317,7 @@ static inline bool8 HDMAReadLineCount (int d) uint8 line; line = S9xGetByte((DMA[d].ABank << 16) + DMA[d].Address); - CPU.Cycles += SLOW_ONE_CYCLE; + ADD_CYCLES(SLOW_ONE_CYCLE); if (!line) { @@ -1327,10 +1329,10 @@ static inline bool8 HDMAReadLineCount (int d) if (PPU.HDMA & (0xfe << d)) { DMA[d].Address++; - CPU.Cycles += SLOW_ONE_CYCLE * 2; + ADD_CYCLES(SLOW_ONE_CYCLE << 1); } else - CPU.Cycles += SLOW_ONE_CYCLE; + ADD_CYCLES(SLOW_ONE_CYCLE); DMA[d].IndirectAddress = S9xGetWord((DMA[d].ABank << 16) + DMA[d].Address); DMA[d].Address++; @@ -1358,7 +1360,7 @@ static inline bool8 HDMAReadLineCount (int d) if (DMA[d].HDMAIndirectAddressing) { - CPU.Cycles += SLOW_ONE_CYCLE << 1; + ADD_CYCLES(SLOW_ONE_CYCLE << 1); DMA[d].IndirectAddress = S9xGetWord((DMA[d].ABank << 16) + DMA[d].Address); DMA[d].Address += 2; HDMAMemPointers[d] = S9xGetMemPointer((DMA[d].IndirectBank << 16) + DMA[d].IndirectAddress); @@ -1390,7 +1392,7 @@ void S9xStartHDMA (void) // XXX: Not quite right... if (PPU.HDMA != 0) - CPU.Cycles += Timings.DMACPUSync; + ADD_CYCLES(Timings.DMACPUSync); for (uint8 i = 0; i < 8; i++) { @@ -1433,7 +1435,7 @@ uint8 S9xDoHDMA (uint8 byte) tmpch = CPU.CurrentDMAorHDMAChannel; // XXX: Not quite right... - CPU.Cycles += Timings.DMACPUSync; + ADD_CYCLES(Timings.DMACPUSync); for (uint8 mask = 1; mask; mask <<= 1, p++, d++) { @@ -1498,46 +1500,57 @@ uint8 S9xDoHDMA (uint8 byte) switch (p->TransferMode) { case 0: - CPU.Cycles += SLOW_ONE_CYCLE; DOBYTE(IAddr, 0); + ADD_CYCLES(SLOW_ONE_CYCLE); break; case 5: - CPU.Cycles += 4 * SLOW_ONE_CYCLE; DOBYTE(IAddr + 0, 0); + ADD_CYCLES(SLOW_ONE_CYCLE); DOBYTE(IAddr + 1, 1); + ADD_CYCLES(SLOW_ONE_CYCLE); DOBYTE(IAddr + 2, 0); + ADD_CYCLES(SLOW_ONE_CYCLE); DOBYTE(IAddr + 3, 1); + ADD_CYCLES(SLOW_ONE_CYCLE); break; case 1: - CPU.Cycles += 2 * SLOW_ONE_CYCLE; DOBYTE(IAddr + 0, 0); + ADD_CYCLES(SLOW_ONE_CYCLE); DOBYTE(IAddr + 1, 1); + ADD_CYCLES(SLOW_ONE_CYCLE); break; case 2: case 6: - CPU.Cycles += 2 * SLOW_ONE_CYCLE; DOBYTE(IAddr + 0, 0); + ADD_CYCLES(SLOW_ONE_CYCLE); DOBYTE(IAddr + 1, 0); + ADD_CYCLES(SLOW_ONE_CYCLE); break; case 3: case 7: - CPU.Cycles += 4 * SLOW_ONE_CYCLE; DOBYTE(IAddr + 0, 0); + ADD_CYCLES(SLOW_ONE_CYCLE); DOBYTE(IAddr + 1, 0); + ADD_CYCLES(SLOW_ONE_CYCLE); DOBYTE(IAddr + 2, 1); + ADD_CYCLES(SLOW_ONE_CYCLE); DOBYTE(IAddr + 3, 1); + ADD_CYCLES(SLOW_ONE_CYCLE); break; case 4: - CPU.Cycles += 4 * SLOW_ONE_CYCLE; DOBYTE(IAddr + 0, 0); + ADD_CYCLES(SLOW_ONE_CYCLE); DOBYTE(IAddr + 1, 1); + ADD_CYCLES(SLOW_ONE_CYCLE); DOBYTE(IAddr + 2, 2); + ADD_CYCLES(SLOW_ONE_CYCLE); DOBYTE(IAddr + 3, 3); + ADD_CYCLES(SLOW_ONE_CYCLE); break; } @@ -1556,44 +1569,53 @@ uint8 S9xDoHDMA (uint8 byte) switch (p->TransferMode) { case 0: - CPU.Cycles += SLOW_ONE_CYCLE; S9xSetPPU(S9xGetByte(Addr), 0x2100 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); break; case 5: - CPU.Cycles += 2 * SLOW_ONE_CYCLE; S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); S9xSetPPU(S9xGetByte(Addr + 1), 0x2101 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); Addr += 2; /* fall through */ case 1: - CPU.Cycles += 2 * SLOW_ONE_CYCLE; S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); S9xSetPPU(S9xGetByte(Addr + 1), 0x2101 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); break; case 2: case 6: - CPU.Cycles += 2 * SLOW_ONE_CYCLE; S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); S9xSetPPU(S9xGetByte(Addr + 1), 0x2100 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); break; case 3: case 7: - CPU.Cycles += 4 * SLOW_ONE_CYCLE; S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); S9xSetPPU(S9xGetByte(Addr + 1), 0x2100 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); S9xSetPPU(S9xGetByte(Addr + 2), 0x2101 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); S9xSetPPU(S9xGetByte(Addr + 3), 0x2101 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); break; case 4: - CPU.Cycles += 4 * SLOW_ONE_CYCLE; S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); S9xSetPPU(S9xGetByte(Addr + 1), 0x2101 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); S9xSetPPU(S9xGetByte(Addr + 2), 0x2102 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); S9xSetPPU(S9xGetByte(Addr + 3), 0x2103 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); break; } } @@ -1603,47 +1625,56 @@ uint8 S9xDoHDMA (uint8 byte) switch (p->TransferMode) { case 0: - CPU.Cycles += SLOW_ONE_CYCLE; S9xSetPPU(*HDMAMemPointers[d]++, 0x2100 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); break; case 5: - CPU.Cycles += 2 * SLOW_ONE_CYCLE; S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); HDMAMemPointers[d] += 2; /* fall through */ case 1: - CPU.Cycles += 2 * SLOW_ONE_CYCLE; S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); HDMAMemPointers[d] += 2; break; case 2: case 6: - CPU.Cycles += 2 * SLOW_ONE_CYCLE; S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2100 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); HDMAMemPointers[d] += 2; break; case 3: case 7: - CPU.Cycles += 4 * SLOW_ONE_CYCLE; S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2100 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); S9xSetPPU(*(HDMAMemPointers[d] + 2), 0x2101 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); S9xSetPPU(*(HDMAMemPointers[d] + 3), 0x2101 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); HDMAMemPointers[d] += 4; break; case 4: - CPU.Cycles += 4 * SLOW_ONE_CYCLE; S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); S9xSetPPU(*(HDMAMemPointers[d] + 2), 0x2102 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); S9xSetPPU(*(HDMAMemPointers[d] + 3), 0x2103 + p->BAddress); + ADD_CYCLES(SLOW_ONE_CYCLE); HDMAMemPointers[d] += 4; break; } @@ -1665,46 +1696,57 @@ uint8 S9xDoHDMA (uint8 byte) switch (p->TransferMode) { case 0: - CPU.Cycles += SLOW_ONE_CYCLE; DOBYTE(IAddr, 0); + ADD_CYCLES(SLOW_ONE_CYCLE); break; case 5: - CPU.Cycles += 4 * SLOW_ONE_CYCLE; DOBYTE(IAddr + 0, 0); + ADD_CYCLES(SLOW_ONE_CYCLE); DOBYTE(IAddr + 1, 1); + ADD_CYCLES(SLOW_ONE_CYCLE); DOBYTE(IAddr + 2, 0); + ADD_CYCLES(SLOW_ONE_CYCLE); DOBYTE(IAddr + 3, 1); + ADD_CYCLES(SLOW_ONE_CYCLE); break; case 1: - CPU.Cycles += 2 * SLOW_ONE_CYCLE; DOBYTE(IAddr + 0, 0); + ADD_CYCLES(SLOW_ONE_CYCLE); DOBYTE(IAddr + 1, 1); + ADD_CYCLES(SLOW_ONE_CYCLE); break; case 2: case 6: - CPU.Cycles += 2 * SLOW_ONE_CYCLE; DOBYTE(IAddr + 0, 0); + ADD_CYCLES(SLOW_ONE_CYCLE); DOBYTE(IAddr + 1, 0); + ADD_CYCLES(SLOW_ONE_CYCLE); break; case 3: case 7: - CPU.Cycles += 4 * SLOW_ONE_CYCLE; DOBYTE(IAddr + 0, 0); + ADD_CYCLES(SLOW_ONE_CYCLE); DOBYTE(IAddr + 1, 0); + ADD_CYCLES(SLOW_ONE_CYCLE); DOBYTE(IAddr + 2, 1); + ADD_CYCLES(SLOW_ONE_CYCLE); DOBYTE(IAddr + 3, 1); + ADD_CYCLES(SLOW_ONE_CYCLE); break; case 4: - CPU.Cycles += 4 * SLOW_ONE_CYCLE; DOBYTE(IAddr + 0, 0); + ADD_CYCLES(SLOW_ONE_CYCLE); DOBYTE(IAddr + 1, 1); + ADD_CYCLES(SLOW_ONE_CYCLE); DOBYTE(IAddr + 2, 2); + ADD_CYCLES(SLOW_ONE_CYCLE); DOBYTE(IAddr + 3, 3); + ADD_CYCLES(SLOW_ONE_CYCLE); break; } @@ -1730,7 +1772,7 @@ uint8 S9xDoHDMA (uint8 byte) } } else - CPU.Cycles += SLOW_ONE_CYCLE; + ADD_CYCLES(SLOW_ONE_CYCLE); } } diff --git a/docs/porting.html b/docs/porting.html index 63d80376..9c62e23c 100644 --- a/docs/porting.html +++ b/docs/porting.html @@ -291,11 +291,6 @@

Called once a complete SNES screen has been rendered into the GFX.Screen memory buffer, now is your chance to copy the SNES rendered screen to the host computer's screen memory. The problem is that you have to cope with different sized SNES rendered screens: 256*224, 256*239, 512*224, 512*239, 512*448 and 512*478.

- -

bool8 S9xContinueUpdate (int width, int height)

-

- Similar to S9xDeinitUpdate, but in interlace mode (512*448 or 512*478) only. Called once an even frame has been rendered into the GFX.Screen memory buffer. -

void S9xMessage (int type, int number, const char *message)

When Snes9x wants to display an error, information or warning message, it calls this function. Check in messages.h for the types and individual message numbers that Snes9x currently passes as parameters.
@@ -384,7 +379,7 @@ The sound generation rate on a SNES is directly proportional to the video output rate. Displays that synchronize with the vertical refresh but have a slightly lower refresh-rate than the emulated system can experience sound drop-outs. It may be beneficial to provide an option for users to configure Settings.SoundInputRate to suit their own systems. Setting Settings.SoundInputRate to a value that matches the actual output rate (i.e. 31977hz for 59.96hz) or lower will allow the users to eliminate crackling. A range of 31000hz to 33000hz should be inclusive enough for all displays. Use of this setting paired with the S9xSyncSound function can eliminate sound discontinuity.

- Updated most recently by: 2010/01/09 zones + Updated most recently by: 2009/12/20 zones
diff --git a/fxinst.h b/fxinst.h index e1c649a3..8f44ae99 100644 --- a/fxinst.h +++ b/fxinst.h @@ -371,7 +371,7 @@ struct FxRegs_s uint32 vCounter; uint32 vInstCount; uint32 vSCBRDirty; // If SCBR is written, our cached screen pointers need updating - + uint8 *avRegAddr; // To reference avReg in snapshot.cpp }; diff --git a/getset.h b/getset.h index 6d2b6459..bf5557b4 100644 --- a/getset.h +++ b/getset.h @@ -187,15 +187,63 @@ #include "seta.h" #include "bsx.h" +#if (S9X_ACCURACY_LEVEL >= 2) + +#define addCyclesInMemoryAccess \ + if (!CPU.InDMAorHDMA) \ + { \ + CPU.Cycles += speed; \ + while (CPU.Cycles >= CPU.NextEvent) \ + S9xDoHEventProcessing(); \ + } + +#define addCyclesInMemoryAccess_x2 \ + if (!CPU.InDMAorHDMA) \ + { \ + CPU.Cycles += speed << 1; \ + while (CPU.Cycles >= CPU.NextEvent) \ + S9xDoHEventProcessing(); \ + } + +#else + +#define addCyclesInMemoryAccess \ + if (!CPU.InDMAorHDMA) \ + CPU.Cycles += speed; + +#define addCyclesInMemoryAccess_x2 \ + if (!CPU.InDMAorHDMA) \ + CPU.Cycles += speed << 1; + +#endif + extern uint8 OpenBus; +static inline int32 memory_speed (uint32 address) +{ + if (address & 0x408000) + { + if (address & 0x800000) + return (CPU.FastROMSpeed); + + return (SLOW_ONE_CYCLE); + } + + if ((address + 0x6000) & 0x4000) + return (SLOW_ONE_CYCLE); + + if ((address - 0x4000) & 0x7e00) + return (ONE_CYCLE); + + return (TWO_CYCLES); +} + inline uint8 S9xGetByte (uint32 Address) { - int block; - uint8 *GetAddress = Memory.Map[block = ((Address & 0xffffff) >> MEMMAP_SHIFT)]; - - if (!CPU.InDMAorHDMA) - CPU.Cycles += Memory.MemorySpeed[block]; + int block = (Address & 0xffffff) >> MEMMAP_SHIFT; + uint8 *GetAddress = Memory.Map[block]; + int32 speed = memory_speed(Address); + uint8 byte; if (GetAddress >= (uint8 *) CMemory::MAP_LAST) { @@ -203,18 +251,25 @@ inline uint8 S9xGetByte (uint32 Address) if (Memory.BlockIsRAM[block]) CPU.WaitAddress = CPU.PBPCAtOpcodeStart; #endif - return (*(GetAddress + (Address & 0xffff))); + byte = *(GetAddress + (Address & 0xffff)); + addCyclesInMemoryAccess; + return (byte); } switch ((pint) GetAddress) { case CMemory::MAP_CPU: - return (S9xGetCPU(Address & 0xffff)); + byte = S9xGetCPU(Address & 0xffff); + addCyclesInMemoryAccess; + return (byte); case CMemory::MAP_PPU: if (CPU.InDMAorHDMA && (Address & 0xff00) == 0x2100) return (OpenBus); - return (S9xGetPPU(Address & 0xffff)); + + byte = S9xGetPPU(Address & 0xffff); + addCyclesInMemoryAccess; + return (byte); case CMemory::MAP_LOROM_SRAM: case CMemory::MAP_SA1RAM: @@ -222,45 +277,71 @@ inline uint8 S9xGetByte (uint32 Address) // Address & 0xff0000 : bank // bank >> 1 | offset : SRAM address, unbound // unbound & SRAMMask : SRAM offset - return (*(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask))); + byte = *(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask)); + addCyclesInMemoryAccess; + return (byte); case CMemory::MAP_LOROM_SRAM_B: - return (*(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB))); + byte = *(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB)); + addCyclesInMemoryAccess; + return (byte); case CMemory::MAP_HIROM_SRAM: case CMemory::MAP_RONLY_SRAM: - return (*(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask))); + byte = *(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask)); + addCyclesInMemoryAccess; + return (byte); case CMemory::MAP_BWRAM: - return (*(Memory.BWRAM + ((Address & 0x7fff) - 0x6000))); + byte = *(Memory.BWRAM + ((Address & 0x7fff) - 0x6000)); + addCyclesInMemoryAccess; + return (byte); case CMemory::MAP_DSP: - return (S9xGetDSP(Address & 0xffff)); + byte = S9xGetDSP(Address & 0xffff); + addCyclesInMemoryAccess; + return (byte); case CMemory::MAP_SPC7110_ROM: - return (S9xGetSPC7110Byte(Address)); + byte = S9xGetSPC7110Byte(Address); + addCyclesInMemoryAccess; + return (byte); case CMemory::MAP_SPC7110_DRAM: - return (S9xGetSPC7110(0x4800)); + byte = S9xGetSPC7110(0x4800); + addCyclesInMemoryAccess; + return (byte); case CMemory::MAP_C4: - return (S9xGetC4(Address & 0xffff)); + byte = S9xGetC4(Address & 0xffff); + addCyclesInMemoryAccess; + return (byte); case CMemory::MAP_OBC_RAM: - return (S9xGetOBC1(Address & 0xffff)); + byte = S9xGetOBC1(Address & 0xffff); + addCyclesInMemoryAccess; + return (byte); case CMemory::MAP_SETA_DSP: - return (S9xGetSetaDSP(Address)); + byte = S9xGetSetaDSP(Address); + addCyclesInMemoryAccess; + return (byte); case CMemory::MAP_SETA_RISC: - return (S9xGetST018(Address)); + byte = S9xGetST018(Address); + addCyclesInMemoryAccess; + return (byte); case CMemory::MAP_BSX: - return (S9xGetBSX(Address)); + byte = S9xGetBSX(Address); + addCyclesInMemoryAccess; + return (byte); case CMemory::MAP_NONE: default: - return (OpenBus); + byte = OpenBus; + addCyclesInMemoryAccess; + return (byte); } } @@ -291,11 +372,10 @@ inline uint16 S9xGetWord (uint32 Address, enum s9xwrap_t w = WRAP_NONE) } } - int block; - uint8 *GetAddress = Memory.Map[block = ((Address & 0xffffff) >> MEMMAP_SHIFT)]; - - if (!CPU.InDMAorHDMA) - CPU.Cycles += (Memory.MemorySpeed[block] << 1); + int block = (Address & 0xffffff) >> MEMMAP_SHIFT; + uint8 *GetAddress = Memory.Map[block]; + int32 speed = memory_speed(Address); + uint16 word; if (GetAddress >= (uint8 *) CMemory::MAP_LAST) { @@ -303,13 +383,19 @@ inline uint16 S9xGetWord (uint32 Address, enum s9xwrap_t w = WRAP_NONE) if (Memory.BlockIsRAM[block]) CPU.WaitAddress = CPU.PBPCAtOpcodeStart; #endif - return (READ_WORD(GetAddress + (Address & 0xffff))); + word = READ_WORD(GetAddress + (Address & 0xffff)); + addCyclesInMemoryAccess_x2; + return (word); } switch ((pint) GetAddress) { case CMemory::MAP_CPU: - return (S9xGetCPU(Address & 0xffff) | (S9xGetCPU((Address + 1) & 0xffff) << 8)); + word = S9xGetCPU(Address & 0xffff); + addCyclesInMemoryAccess; + word |= S9xGetCPU((Address + 1) & 0xffff) << 8; + addCyclesInMemoryAccess; + return (word); case CMemory::MAP_PPU: if (CPU.InDMAorHDMA) @@ -318,61 +404,107 @@ inline uint16 S9xGetWord (uint32 Address, enum s9xwrap_t w = WRAP_NONE) return (OpenBus | (S9xGetByte(Address + 1) << 8)); } - return (S9xGetPPU(Address & 0xffff) | (S9xGetPPU((Address + 1) & 0xffff) << 8)); + word = S9xGetPPU(Address & 0xffff); + addCyclesInMemoryAccess; + word |= S9xGetPPU((Address + 1) & 0xffff) << 8; + addCyclesInMemoryAccess; + return (word); case CMemory::MAP_LOROM_SRAM: case CMemory::MAP_SA1RAM: if (Memory.SRAMMask >= MEMMAP_MASK) - return (READ_WORD(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask))); + word = READ_WORD(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask)); else - return ((*(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask))) | - ((*(Memory.SRAM + (((((Address + 1) & 0xff0000) >> 1) | ((Address + 1) & 0x7fff)) & Memory.SRAMMask))) << 8)); + word = (*(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask))) | + ((*(Memory.SRAM + (((((Address + 1) & 0xff0000) >> 1) | ((Address + 1) & 0x7fff)) & Memory.SRAMMask))) << 8); + addCyclesInMemoryAccess_x2; + return (word); case CMemory::MAP_LOROM_SRAM_B: if (Multi.sramMaskB >= MEMMAP_MASK) - return (READ_WORD(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB))); + word = READ_WORD(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB)); else - return ((*(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB))) | - ((*(Multi.sramB + (((((Address + 1) & 0xff0000) >> 1) | ((Address + 1) & 0x7fff)) & Multi.sramMaskB))) << 8)); + word = (*(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB))) | + ((*(Multi.sramB + (((((Address + 1) & 0xff0000) >> 1) | ((Address + 1) & 0x7fff)) & Multi.sramMaskB))) << 8); + addCyclesInMemoryAccess_x2; + return (word); case CMemory::MAP_HIROM_SRAM: case CMemory::MAP_RONLY_SRAM: if (Memory.SRAMMask >= MEMMAP_MASK) - return (READ_WORD(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask))); + word = READ_WORD(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask)); else - return ((*(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask)) | - (*(Memory.SRAM + ((((Address + 1) & 0x7fff) - 0x6000 + (((Address + 1) & 0xf0000) >> 3)) & Memory.SRAMMask)) << 8))); + word = (*(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask)) | + (*(Memory.SRAM + ((((Address + 1) & 0x7fff) - 0x6000 + (((Address + 1) & 0xf0000) >> 3)) & Memory.SRAMMask)) << 8)); + addCyclesInMemoryAccess_x2; + return (word); case CMemory::MAP_BWRAM: - return (READ_WORD(Memory.BWRAM + ((Address & 0x7fff) - 0x6000))); + word = READ_WORD(Memory.BWRAM + ((Address & 0x7fff) - 0x6000)); + addCyclesInMemoryAccess_x2; + return (word); case CMemory::MAP_DSP: - return (S9xGetDSP(Address & 0xffff) | (S9xGetDSP((Address + 1) & 0xffff) << 8)); + word = S9xGetDSP(Address & 0xffff); + addCyclesInMemoryAccess; + word |= S9xGetDSP((Address + 1) & 0xffff) << 8; + addCyclesInMemoryAccess; + return (word); case CMemory::MAP_SPC7110_ROM: - return (S9xGetSPC7110Byte(Address) | (S9xGetSPC7110Byte(Address + 1) << 8)); + word = S9xGetSPC7110Byte(Address); + addCyclesInMemoryAccess; + word |= S9xGetSPC7110Byte(Address + 1) << 8; + addCyclesInMemoryAccess; + return (word); case CMemory::MAP_SPC7110_DRAM: - return (S9xGetSPC7110(0x4800) | (S9xGetSPC7110(0x4800) << 8)); + word = S9xGetSPC7110(0x4800); + addCyclesInMemoryAccess; + word |= S9xGetSPC7110(0x4800) << 8; + addCyclesInMemoryAccess; + return (word); case CMemory::MAP_C4: - return (S9xGetC4(Address & 0xffff) | (S9xGetC4((Address + 1) & 0xffff) << 8)); + word = S9xGetC4(Address & 0xffff); + addCyclesInMemoryAccess; + word |= S9xGetC4((Address + 1) & 0xffff) << 8; + addCyclesInMemoryAccess; + return (word); case CMemory::MAP_OBC_RAM: - return (S9xGetOBC1(Address & 0xffff) | (S9xGetOBC1((Address + 1) & 0xffff) << 8)); + word = S9xGetOBC1(Address & 0xffff); + addCyclesInMemoryAccess; + word |= S9xGetOBC1((Address + 1) & 0xffff) << 8; + addCyclesInMemoryAccess; + return (word); case CMemory::MAP_SETA_DSP: - return (S9xGetSetaDSP(Address) | (S9xGetSetaDSP(Address + 1) << 8)); + word = S9xGetSetaDSP(Address); + addCyclesInMemoryAccess; + word |= S9xGetSetaDSP(Address + 1) << 8; + addCyclesInMemoryAccess; + return (word); case CMemory::MAP_SETA_RISC: - return (S9xGetST018(Address) | (S9xGetST018(Address + 1) << 8)); + word = S9xGetST018(Address); + addCyclesInMemoryAccess; + word |= S9xGetST018(Address + 1) << 8; + addCyclesInMemoryAccess; + return (word); case CMemory::MAP_BSX: - return (S9xGetBSX(Address) | (S9xGetBSX(Address + 1) << 8)); + word = S9xGetBSX(Address); + addCyclesInMemoryAccess; + word |= S9xGetBSX(Address + 1) << 8; + addCyclesInMemoryAccess; + return (word); case CMemory::MAP_NONE: default: - return (OpenBus | (OpenBus << 8)); + word = OpenBus | (OpenBus << 8); + addCyclesInMemoryAccess_x2; + return (word); } } @@ -382,17 +514,16 @@ inline void S9xSetByte (uint8 Byte, uint32 Address) CPU.WaitAddress = 0xffffffff; #endif - int block; - uint8 *SetAddress = Memory.WriteMap[block = ((Address & 0xffffff) >> MEMMAP_SHIFT)]; - - if (!CPU.InDMAorHDMA) - CPU.Cycles += Memory.MemorySpeed[block]; + int block = (Address & 0xffffff) >> MEMMAP_SHIFT; + uint8 *SetAddress = Memory.WriteMap[block]; + int32 speed = memory_speed(Address); if (SetAddress >= (uint8 *) CMemory::MAP_LAST) { #ifdef CPU_SHUTDOWN SetAddress += (Address & 0xffff); *SetAddress = Byte; + addCyclesInMemoryAccess; if (Settings.SA1) { @@ -404,6 +535,7 @@ inline void S9xSetByte (uint8 Byte, uint32 Address) } #else *(SetAddress + (Address & 0xffff)) = Byte; + addCyclesInMemoryAccess; #endif return; } @@ -412,12 +544,15 @@ inline void S9xSetByte (uint8 Byte, uint32 Address) { case CMemory::MAP_CPU: S9xSetCPU(Byte, Address & 0xffff); + addCyclesInMemoryAccess; return; case CMemory::MAP_PPU: if (CPU.InDMAorHDMA && (Address & 0xff00) == 0x2100) return; + S9xSetPPU(Byte, Address & 0xffff); + addCyclesInMemoryAccess; return; case CMemory::MAP_LOROM_SRAM: @@ -427,6 +562,7 @@ inline void S9xSetByte (uint8 Byte, uint32 Address) CPU.SRAMModified = TRUE; } + addCyclesInMemoryAccess; return; case CMemory::MAP_LOROM_SRAM_B: @@ -436,6 +572,7 @@ inline void S9xSetByte (uint8 Byte, uint32 Address) CPU.SRAMModified = TRUE; } + addCyclesInMemoryAccess; return; case CMemory::MAP_HIROM_SRAM: @@ -445,44 +582,54 @@ inline void S9xSetByte (uint8 Byte, uint32 Address) CPU.SRAMModified = TRUE; } + addCyclesInMemoryAccess; return; case CMemory::MAP_BWRAM: *(Memory.BWRAM + ((Address & 0x7fff) - 0x6000)) = Byte; CPU.SRAMModified = TRUE; + addCyclesInMemoryAccess; return; case CMemory::MAP_SA1RAM: *(Memory.SRAM + (Address & 0xffff)) = Byte; SA1.Executing = !SA1.Waiting; + addCyclesInMemoryAccess; return; case CMemory::MAP_DSP: S9xSetDSP(Byte, Address & 0xffff); + addCyclesInMemoryAccess; return; case CMemory::MAP_C4: S9xSetC4(Byte, Address & 0xffff); + addCyclesInMemoryAccess; return; case CMemory::MAP_OBC_RAM: S9xSetOBC1(Byte, Address & 0xffff); + addCyclesInMemoryAccess; return; case CMemory::MAP_SETA_DSP: S9xSetSetaDSP(Byte, Address); + addCyclesInMemoryAccess; return; case CMemory::MAP_SETA_RISC: S9xSetST018(Byte, Address); + addCyclesInMemoryAccess; return; case CMemory::MAP_BSX: S9xSetBSX(Byte, Address); + addCyclesInMemoryAccess; return; case CMemory::MAP_NONE: default: + addCyclesInMemoryAccess; return; } } @@ -527,17 +674,16 @@ inline void S9xSetWord (uint16 Word, uint32 Address, enum s9xwrap_t w = WRAP_NON CPU.WaitAddress = 0xffffffff; #endif - int block; - uint8 *SetAddress = Memory.WriteMap[block = ((Address & 0xffffff) >> MEMMAP_SHIFT)]; - - if (!CPU.InDMAorHDMA) - CPU.Cycles += (Memory.MemorySpeed[block] << 1); + int block = (Address & 0xffffff) >> MEMMAP_SHIFT; + uint8 *SetAddress = Memory.WriteMap[block]; + int32 speed = memory_speed(Address); if (SetAddress >= (uint8 *) CMemory::MAP_LAST) { #ifdef CPU_SHUTDOWN SetAddress += (Address & 0xffff); WRITE_WORD(SetAddress, Word); + addCyclesInMemoryAccess_x2; if (Settings.SA1) { @@ -549,6 +695,7 @@ inline void S9xSetWord (uint16 Word, uint32 Address, enum s9xwrap_t w = WRAP_NON } #else WRITE_WORD(SetAddress + (Address & 0xffff), Word); + addCyclesInMemoryAccess_x2; #endif return; } @@ -559,16 +706,20 @@ inline void S9xSetWord (uint16 Word, uint32 Address, enum s9xwrap_t w = WRAP_NON if (o) { S9xSetCPU(Word >> 8, (Address + 1) & 0xffff); + addCyclesInMemoryAccess; S9xSetCPU((uint8) Word, Address & 0xffff); + addCyclesInMemoryAccess; + return; } else { S9xSetCPU((uint8) Word, Address & 0xffff); + addCyclesInMemoryAccess; S9xSetCPU(Word >> 8, (Address + 1) & 0xffff); + addCyclesInMemoryAccess; + return; } - return; - case CMemory::MAP_PPU: if (CPU.InDMAorHDMA) { @@ -582,16 +733,20 @@ inline void S9xSetWord (uint16 Word, uint32 Address, enum s9xwrap_t w = WRAP_NON if (o) { S9xSetPPU(Word >> 8, (Address + 1) & 0xffff); + addCyclesInMemoryAccess; S9xSetPPU((uint8) Word, Address & 0xffff); + addCyclesInMemoryAccess; + return; } else { S9xSetPPU((uint8) Word, Address & 0xffff); + addCyclesInMemoryAccess; S9xSetPPU(Word >> 8, (Address + 1) & 0xffff); + addCyclesInMemoryAccess; + return; } - return; - case CMemory::MAP_LOROM_SRAM: if (Memory.SRAMMask) { @@ -606,6 +761,7 @@ inline void S9xSetWord (uint16 Word, uint32 Address, enum s9xwrap_t w = WRAP_NON CPU.SRAMModified = TRUE; } + addCyclesInMemoryAccess_x2; return; case CMemory::MAP_LOROM_SRAM_B: @@ -622,6 +778,7 @@ inline void S9xSetWord (uint16 Word, uint32 Address, enum s9xwrap_t w = WRAP_NON CPU.SRAMModified = TRUE; } + addCyclesInMemoryAccess_x2; return; case CMemory::MAP_HIROM_SRAM: @@ -638,104 +795,132 @@ inline void S9xSetWord (uint16 Word, uint32 Address, enum s9xwrap_t w = WRAP_NON CPU.SRAMModified = TRUE; } + addCyclesInMemoryAccess_x2; return; case CMemory::MAP_BWRAM: WRITE_WORD(Memory.BWRAM + ((Address & 0x7fff) - 0x6000), Word); CPU.SRAMModified = TRUE; + addCyclesInMemoryAccess_x2; return; case CMemory::MAP_SA1RAM: WRITE_WORD(Memory.SRAM + (Address & 0xffff), Word); SA1.Executing = !SA1.Waiting; + addCyclesInMemoryAccess_x2; return; case CMemory::MAP_DSP: if (o) { S9xSetDSP(Word >> 8, (Address + 1) & 0xffff); + addCyclesInMemoryAccess; S9xSetDSP((uint8) Word, Address & 0xffff); + addCyclesInMemoryAccess; + return; } else { S9xSetDSP((uint8) Word, Address & 0xffff); + addCyclesInMemoryAccess; S9xSetDSP(Word >> 8, (Address + 1) & 0xffff); + addCyclesInMemoryAccess; + return; } - return; - case CMemory::MAP_C4: if (o) { S9xSetC4(Word >> 8, (Address + 1) & 0xffff); + addCyclesInMemoryAccess; S9xSetC4((uint8) Word, Address & 0xffff); + addCyclesInMemoryAccess; + return; } else { S9xSetC4((uint8) Word, Address & 0xffff); + addCyclesInMemoryAccess; S9xSetC4(Word >> 8, (Address + 1) & 0xffff); + addCyclesInMemoryAccess; + return; } - return; - case CMemory::MAP_OBC_RAM: if (o) { S9xSetOBC1(Word >> 8, (Address + 1) & 0xffff); + addCyclesInMemoryAccess; S9xSetOBC1((uint8) Word, Address & 0xffff); + addCyclesInMemoryAccess; + return; } else { S9xSetOBC1((uint8) Word, Address & 0xffff); + addCyclesInMemoryAccess; S9xSetOBC1(Word >> 8, (Address + 1) & 0xffff); + addCyclesInMemoryAccess; + return; } - return; - case CMemory::MAP_SETA_DSP: if (o) { S9xSetSetaDSP(Word >> 8, Address + 1); + addCyclesInMemoryAccess; S9xSetSetaDSP((uint8) Word, Address); + addCyclesInMemoryAccess; + return; } else { S9xSetSetaDSP((uint8) Word, Address); + addCyclesInMemoryAccess; S9xSetSetaDSP(Word >> 8, Address + 1); + addCyclesInMemoryAccess; + return; } - return; - case CMemory::MAP_SETA_RISC: if (o) { S9xSetST018(Word >> 8, Address + 1); + addCyclesInMemoryAccess; S9xSetST018((uint8) Word, Address); + addCyclesInMemoryAccess; + return; } else { S9xSetST018((uint8) Word, Address); + addCyclesInMemoryAccess; S9xSetST018(Word >> 8, Address + 1); + addCyclesInMemoryAccess; + return; } - return; - case CMemory::MAP_BSX: if (o) { S9xSetBSX(Word >> 8, Address + 1); + addCyclesInMemoryAccess; S9xSetBSX((uint8) Word, Address); + addCyclesInMemoryAccess; + return; } else { S9xSetBSX((uint8) Word, Address); + addCyclesInMemoryAccess; S9xSetBSX(Word >> 8, Address + 1); + addCyclesInMemoryAccess; + return; } - return; - case CMemory::MAP_NONE: default: + addCyclesInMemoryAccess_x2; return; } } @@ -748,7 +933,7 @@ inline void S9xSetPCBase (uint32 Address) int block; uint8 *GetAddress = Memory.Map[block = ((Address & 0xffffff) >> MEMMAP_SHIFT)]; - CPU.MemSpeed = Memory.MemorySpeed[block]; + CPU.MemSpeed = memory_speed(Address); CPU.MemSpeedx2 = CPU.MemSpeed << 1; if (GetAddress >= (uint8 *) CMemory::MAP_LAST) diff --git a/gfx.cpp b/gfx.cpp index dff2ef20..f7bb546c 100644 --- a/gfx.cpp +++ b/gfx.cpp @@ -2013,6 +2013,20 @@ static void DisplayStringFromBottom (const char *string, int linesFromBottom, in static void DisplayFrameRate (void) { char string[10]; + static uint32 lastFrameCount = 0, calcFps = 0; + static time_t lastTime = time(NULL); + + time_t currTime = time(NULL); + if (lastTime != currTime) { + if (lastFrameCount < IPPU.TotalEmulatedFrames) { + calcFps = (IPPU.TotalEmulatedFrames - lastFrameCount) / (uint32)(currTime - lastTime); + } + lastTime = currTime; + lastFrameCount = IPPU.TotalEmulatedFrames; + } + sprintf(string, "%u fps", calcFps); + S9xDisplayString(string, 2, IPPU.RenderedScreenWidth - (font_width - 1) * strlen(string) - 1, false); + #ifdef DEBUGGER const int len = 8; sprintf(string, "%02d/%02d %02d", (int) IPPU.DisplayedRenderedFrameCount, (int) Memory.ROMFramesPerSecond, (int) IPPU.FrameCount); diff --git a/jma/portable.h b/jma/portable.h index d6ca1da6..0f708549 100644 --- a/jma/portable.h +++ b/jma/portable.h @@ -20,37 +20,53 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #define __PORTABLE_H #include +#ifdef __GNUC__ +#include -typedef signed char INT8; -typedef unsigned char UINT8; -typedef short INT16; -typedef unsigned short UINT16; -typedef long INT32; -typedef unsigned long UINT32; +typedef int8_t INT8; +typedef uint8_t UINT8; +typedef int16_t INT16; +typedef uint16_t UINT16; +typedef int32_t INT32; +typedef uint32_t UINT32; +typedef int64_t INT64; +typedef uint64_t UINT64; +typedef uintptr_t UINT_PTR; -//Not correct, but should work for Snes9x -typedef int INT64; -typedef unsigned int UINT64; -//typedef long long INT64; -//typedef unsigned long long UINT64; +#else -typedef UINT8 BYTE; +typedef signed char INT8; +typedef unsigned char UINT8; +typedef short INT16; +typedef unsigned short UINT16; +typedef int INT32; +typedef unsigned int UINT32; +#ifdef _MSC_VER +typedef __int64 INT64; +typedef unsigned __int64 UINT64; +#else +typedef long long INT64; +typedef unsigned long long UINT64; +#endif +typedef unsigned UINT_PTR; + +#endif + +typedef UINT8 BYTE; typedef UINT16 WORD; typedef UINT32 DWORD; -typedef unsigned UINT_PTR; - typedef int BOOL; #define FALSE 0 -#define TRUE 1 +#define TRUE 1 -#define HRESULT int -#define S_OK 0 -#define E_INVALIDARG -1 -#define E_OUTOFMEMORY -2 -#define E_FAIL -3 +#define HRESULT int +#define S_OK 0 +#define E_INVALIDARG -1 +#define E_OUTOFMEMORY -2 +#define E_FAIL -3 #define E_INTERNAL_ERROR -4 -#define E_INVALIDDATA -5 +#define E_INVALIDDATA -5 template inline T MyMin(T a, T b) { return a < b ? a : b; @@ -63,24 +79,24 @@ template inline T MyMax(T a, T b) { #define RETURN_IF_NOT_S_OK(x) { HRESULT __aResult_ = (x); if(__aResult_ != S_OK) return __aResult_; } -#define UINT_SIZE (4) -#define USHORT_SIZE (2) +#define UINT_SIZE ((int)sizeof(unsigned int)) +#define USHORT_SIZE ((int)sizeof(unsigned short)) //Convert an array of 4 bytes back into an integer -inline unsigned int charp_to_uint(const unsigned char buffer[UINT_SIZE]) +inline UINT32 charp_to_uint(const UINT8 buffer[UINT_SIZE]) { - unsigned int num = (unsigned int)buffer[3]; - num |= ((unsigned int)buffer[2]) << 8; - num |= ((unsigned int)buffer[1]) << 16; - num |= ((unsigned int)buffer[0]) << 24; + UINT32 num = (UINT32)buffer[3]; + num |= ((UINT32)buffer[2]) << 8; + num |= ((UINT32)buffer[1]) << 16; + num |= ((UINT32)buffer[0]) << 24; return(num); } //Convert an array of 2 bytes back into a short integer -inline unsigned short charp_to_ushort(const unsigned char buffer[USHORT_SIZE]) +inline UINT16 charp_to_ushort(const UINT8 buffer[USHORT_SIZE]) { - unsigned short num = (unsigned short)buffer[1]; - num |= ((unsigned short)buffer[0]) << 8; + UINT16 num = (UINT16)buffer[1]; + num |= ((UINT16)buffer[0]) << 8; return(num); } diff --git a/jma/winout.h b/jma/winout.h index 38e06bdf..0969b30a 100644 --- a/jma/winout.h +++ b/jma/winout.h @@ -64,8 +64,9 @@ public: MoveBlockBackward(); BYTE *p = m_Buffer + m_Pos; aDistance++; + BYTE *p2 = p - aDistance; for(UINT32 i = 0; i < aLen; i++) - p[i] = p[i - aDistance]; + p[i] = p2[i]; m_Pos += aLen; } diff --git a/memmap.cpp b/memmap.cpp index 3ecb9813..7790ee0b 100644 --- a/memmap.cpp +++ b/memmap.cpp @@ -2611,9 +2611,6 @@ void CMemory::InitROM (void) Timings.NMIDMADelay = 24; Timings.IRQPendCount = 0; - CPU.FastROMSpeed = 0; - ResetSpeedMap(); - IPPU.TotalEmulatedFrames = 0; //// Hack games @@ -2655,36 +2652,6 @@ void CMemory::InitROM (void) S9xVerifyControllers(); } -void CMemory::FixROMSpeed (void) -{ - if (CPU.FastROMSpeed == 0) - CPU.FastROMSpeed = SLOW_ONE_CYCLE; - - // [80-bf]:[8000-ffff], [c0-ff]:[0000-ffff] - for (int c = 0x800; c < 0x1000; c++) - { - if (c & 0x8 || c & 0x400) - MemorySpeed[c] = (uint8) CPU.FastROMSpeed; - } -} - -void CMemory::ResetSpeedMap (void) -{ - memset(MemorySpeed, SLOW_ONE_CYCLE, 0x1000); - - // Fast - [00-3f|80-bf]:[2000-3fff|4200-5fff] - // XSlow - [00-3f|80-bf]:[4000-41ff] see also S9xGet/SetCPU() - for (int i = 0; i < 0x400; i += 0x10) - { - MemorySpeed[i + 2] = MemorySpeed[0x800 + i + 2] = ONE_CYCLE; - MemorySpeed[i + 3] = MemorySpeed[0x800 + i + 3] = ONE_CYCLE; - MemorySpeed[i + 4] = MemorySpeed[0x800 + i + 4] = ONE_CYCLE; - MemorySpeed[i + 5] = MemorySpeed[0x800 + i + 5] = ONE_CYCLE; - } - - FixROMSpeed(); -} - // memory map uint32 CMemory::map_mirror (uint32 size, uint32 pos) @@ -3596,37 +3563,6 @@ void CMemory::ApplyROMFixes (void) Timings.HDMAStart = SNES_HDMA_START_HC + Settings.HDMATimingHack - 100; Timings.HBlankStart = SNES_HBLANK_START_HC + Timings.HDMAStart - SNES_HDMA_START_HC; - if (!Settings.DisableGameSpecificHacks) - { - // The HC counter (CPU.Cycles for snes9x) passes over the WRAM refresh point (HC~536) - // while preparing to jump to the IRQ vector address. - // That is to say, the WRAM refresh point is passed over in S9xOpcode_IRQ(). - // Then, HDMA starts just after $210e is half updated, and it causes the flicker of the ground. - // IRQ timing is bad? HDMA timing is bad? else? - if (match_na("GUNDAMW ENDLESSDUEL")) // Shin Kidou Senki Gundam W - Endless Duel - { - Timings.HDMAStart -= 10; - Timings.HBlankStart -= 10; - printf("HDMA timing hack: %d\n", Timings.HDMAStart); - } - - // Due to Snes9x's very inaccurate timings, - // HDMA transfer to $210D-$2114 between the first and second writings to the same addresses. - if (match_na("POWER RANGERS FIGHT")) // Mighty Morphin Power Rangers - The Fighting Edition - { - Timings.HDMAStart -= 10; - Timings.HBlankStart -= 10; - printf("HDMA timing hack: %d\n", Timings.HDMAStart); - } - - if (match_na("SFX SUPERBUTOUDEN2")) // Dragon Ball Z - Super Butouden 2 - { - Timings.HDMAStart += 20; - Timings.HBlankStart += 20; - printf("HDMA timing hack: %d\n", Timings.HDMAStart); - } - } - if (!Settings.DisableGameSpecificHacks) { // The delay to sync CPU and DMA which Snes9x cannot emulate. @@ -3657,6 +3593,12 @@ void CMemory::ApplyROMFixes (void) Timings.IRQPendCount = 2; printf("IRQ count hack: %d\n", Timings.IRQPendCount); } + + if (match_na("BATTLE BLAZE")) + { + Timings.IRQPendCount = 1; + printf("IRQ count hack: %d\n", Timings.IRQPendCount); + } } if (!Settings.DisableGameSpecificHacks) diff --git a/memmap.h b/memmap.h index 561cdccd..30aa4dbd 100644 --- a/memmap.h +++ b/memmap.h @@ -239,7 +239,6 @@ struct CMemory uint8 *WriteMap[MEMMAP_NUM_BLOCKS]; uint8 BlockIsRAM[MEMMAP_NUM_BLOCKS]; uint8 BlockIsROM[MEMMAP_NUM_BLOCKS]; - uint8 MemorySpeed[MEMMAP_NUM_BLOCKS]; uint8 ExtendedFormat; char ROMFilename[PATH_MAX + 1]; @@ -287,8 +286,6 @@ struct CMemory char * SafeANK (const char *); void ParseSNESHeader (uint8 *); void InitROM (void); - void FixROMSpeed (void); - void ResetSpeedMap (void); uint32 map_mirror (uint32, uint32); void map_lorom (uint32, uint32, uint32, uint32, uint32); diff --git a/netplay.cpp b/netplay.cpp index 2b244235..facacc19 100644 --- a/netplay.cpp +++ b/netplay.cpp @@ -194,7 +194,7 @@ #include "win32/wsnes9x.h" #define ioctl ioctlsocket - #define close closesocket + #define close(h) if(h){closesocket(h);} #define read(a,b,c) recv(a, b, c, 0) #define write(a,b,c) send(a, b, c, 0) #else diff --git a/port.h b/port.h index f6911329..9e1117c6 100644 --- a/port.h +++ b/port.h @@ -224,11 +224,15 @@ typedef uint32_t uint32; typedef int64_t int64; typedef uint64_t uint64; #else // HAVE_STDINT_H +#ifdef __WIN32__ +typedef intptr_t pint; +#else // __WIN32__ #ifdef PTR_NOT_INT typedef long pint; #else typedef int pint; #endif +#endif // __WIN32__ #ifdef __WIN32__ #ifdef __BORLANDC__ #include @@ -300,6 +304,8 @@ void _makepath (char *, const char *, const char *, const char *, const char *); #define strncasecmp strnicmp void WinDisplayStringFromBottom(const char *string, int linesFromBottom, int pixelsFromLeft, bool allowWrap); #define S9xDisplayString WinDisplayStringFromBottom +void SetInfoDlgColor(unsigned char, unsigned char, unsigned char); +#define SET_UI_COLOR(r,g,b) SetInfoDlgColor(r,g,b) #endif #ifdef __DJGPP @@ -323,7 +329,7 @@ void WinDisplayStringFromBottom(const char *string, int linesFromBottom, int pix #define TITLE "Snes9x" #endif -#if defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(__x86_64__) || defined(__alpha__) || defined(__MIPSEL__) || defined(_M_IX86) +#if defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(__x86_64__) || defined(__alpha__) || defined(__MIPSEL__) || defined(_M_IX86) || defined(_M_X64) #define LSB_FIRST #define FAST_LSB_WORD_ACCESS #else diff --git a/ppu.cpp b/ppu.cpp index 6872f6b3..e1d5c395 100644 --- a/ppu.cpp +++ b/ppu.cpp @@ -1565,8 +1565,6 @@ void S9xSetCPU (uint8 Byte, uint16 Address) { if (Address < 0x4200) { - CPU.Cycles += ONE_CYCLE; // XSlow - switch (Address) { case 0x4016: // JOYSER0 @@ -1851,8 +1849,6 @@ void S9xSetCPU (uint8 Byte, uint16 Address) } else CPU.FastROMSpeed = SLOW_ONE_CYCLE; - - Memory.FixROMSpeed(); } break; @@ -1911,8 +1907,6 @@ uint8 S9xGetCPU (uint16 Address) } #endif - CPU.Cycles += ONE_CYCLE; // XSlow - switch (Address) { case 0x4016: // JOYSER0 diff --git a/sa1.cpp b/sa1.cpp index 8ec6904a..f8d8892c 100644 --- a/sa1.cpp +++ b/sa1.cpp @@ -788,13 +788,41 @@ static void S9xSA1CharConv2 (void) uint32 offset = (SA1.in_char_dma & 7) ? 0 : 1; int depth = (Memory.FillRAM[0x2231] & 3) == 0 ? 8 : (Memory.FillRAM[0x2231] & 3) == 1 ? 4 : 2; int bytes_per_char = 8 * depth; - uint8 *p = &Memory.FillRAM[0x3000] + dest + offset * bytes_per_char; + uint8 *p = &Memory.FillRAM[0x3000] + (dest & 0x7ff) + offset * bytes_per_char; uint8 *q = &Memory.ROM[CMemory::MAX_ROM_SIZE - 0x10000] + offset * 64; switch (depth) { case 2: + for (int l = 0; l < 8; l++, q += 8) + { + for (int b = 0; b < 8; b++) + { + uint8 r = *(q + b); + *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); + *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); + } + + p += 2; + } + + break; + case 4: + for (int l = 0; l < 8; l++, q += 8) + { + for (int b = 0; b < 8; b++) + { + uint8 r = *(q + b); + *(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1); + *(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1); + *(p + 16) = (*(p + 16) << 1) | ((r >> 2) & 1); + *(p + 17) = (*(p + 17) << 1) | ((r >> 3) & 1); + } + + p += 2; + } + break; case 8: diff --git a/screenshot.cpp b/screenshot.cpp index 6c0aec72..ec8f7503 100644 --- a/screenshot.cpp +++ b/screenshot.cpp @@ -209,7 +209,7 @@ bool8 S9xDoScreenshot (int width, int height) if (!png_ptr) { fclose(fp); - unlink(fname); + remove(fname); S9xMessage(S9X_ERROR, 0, "Failed to take screenshot."); return (FALSE); } @@ -219,7 +219,7 @@ bool8 S9xDoScreenshot (int width, int height) { png_destroy_write_struct(&png_ptr, (png_infopp) NULL); fclose(fp); - unlink(fname); + remove(fname); S9xMessage(S9X_ERROR, 0, "Failed to take screenshot."); return (FALSE); } @@ -228,7 +228,7 @@ bool8 S9xDoScreenshot (int width, int height) { png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); - unlink(fname); + remove(fname); S9xMessage(S9X_ERROR, 0, "Failed to take screenshot."); return (FALSE); } diff --git a/snapshot.cpp b/snapshot.cpp index 3d2c0f51..bca4f8c2 100644 --- a/snapshot.cpp +++ b/snapshot.cpp @@ -1692,7 +1692,6 @@ int S9xUnfreezeFromStream (STREAM stream) S9xSetPCBase(Registers.PBPC); S9xUnpackStatus(); S9xFixCycles(); - Memory.FixROMSpeed(); for (int d = 0; d < 8; d++) DMA[d] = dma_snap.dma[d]; diff --git a/snes9x.h b/snes9x.h index 2b75bd7b..692d01ab 100644 --- a/snes9x.h +++ b/snes9x.h @@ -179,13 +179,15 @@ #define _SNES9X_H_ #ifndef VERSION -#define VERSION "1.52" +#define VERSION "1.53" #endif #include "port.h" #include "65c816.h" #include "messages.h" +#define S9X_ACCURACY_LEVEL 3 + #ifdef ZLIB #include #define STREAM gzFile