upstream changes. change sound defaults

This commit is contained in:
dborth 2010-04-06 02:13:53 +00:00
parent 723010768b
commit 4e752fceb8
18 changed files with 1253 additions and 869 deletions

View File

@ -450,11 +450,12 @@ DefaultSettings ()
Settings.HDMATimingHack = 100; Settings.HDMATimingHack = 100;
// Sound defaults. On Wii this is 32Khz/16bit/Stereo // Sound defaults. On Wii this is 32Khz/16bit/Stereo
Settings.SoundSync = true;
Settings.SixteenBitSound = true; Settings.SixteenBitSound = true;
Settings.Stereo = true; Settings.Stereo = true;
Settings.ReverseStereo = true; Settings.ReverseStereo = true;
Settings.SoundPlaybackRate = 32000; Settings.SoundPlaybackRate = 32000;
Settings.SoundInputRate = 31950; Settings.SoundInputRate = 32000;
// Graphics // Graphics
Settings.Transparency = true; Settings.Transparency = true;

View File

@ -180,15 +180,17 @@
#include "apu.h" #include "apu.h"
#include "snapshot.h" #include "snapshot.h"
#include "display.h" #include "display.h"
#include "resampler.h" #include "linear_resampler.h"
#include "hermite_resampler.h"
#define APU_DEFAULT_INPUT_RATE 32000 #define APU_DEFAULT_INPUT_RATE 32000
#define APU_MINIMUM_SAMPLE_COUNT 512 #define APU_MINIMUM_SAMPLE_COUNT 512
#define APU_MINIMUM_SAMPLE_BLOCK 128 #define APU_MINIMUM_SAMPLE_BLOCK 128
#define APU_NUMERATOR_NTSC 5632 #define APU_NUMERATOR_NTSC 15664
#define APU_DENOMINATOR_NTSC 118125 #define APU_DENOMINATOR_NTSC 328125
#define APU_NUMERATOR_PAL 102400 #define APU_NUMERATOR_PAL 34176
#define APU_DENOMINATOR_PAL 2128137 #define APU_DENOMINATOR_PAL 709379
#define APU_DEFAULT_RESAMPLER HermiteResampler
SNES_SPC *spc_core = NULL; SNES_SPC *spc_core = NULL;
@ -224,8 +226,12 @@ namespace spc
static int32 reference_time; static int32 reference_time;
static uint32 remainder; static uint32 remainder;
static const int32 timing_hack_numerator = SNES_SPC::tempo_unit; static const int timing_hack_numerator = SNES_SPC::tempo_unit;
static int32 timing_hack_denominator = 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); 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 */ arguments. Use 2x in the resampler for buffer leveling with SoundSync */
if (!spc::resampler) 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) if (!spc::resampler)
{ {
delete[] spc::landing_buffer; delete[] spc::landing_buffer;
@ -534,22 +540,14 @@ void S9xDeinitAPU (void)
static inline int S9xAPUGetClock (int32 cpucycles) static inline int S9xAPUGetClock (int32 cpucycles)
{ {
if (Settings.PAL) return (spc::ratio_numerator * (cpucycles - spc::reference_time) + spc::remainder) /
return ((int) floor(((double) APU_NUMERATOR_PAL * spc::timing_hack_numerator * (cpucycles - spc::reference_time) + spc::remainder) / spc::ratio_denominator;
((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);
} }
static inline int S9xAPUGetClockRemainder (int32 cpucycles) static inline int S9xAPUGetClockRemainder (int32 cpucycles)
{ {
if (Settings.PAL) return (spc::ratio_numerator * (cpucycles - spc::reference_time) + spc::remainder) %
return ((int) fmod (((double) APU_NUMERATOR_PAL * spc::timing_hack_numerator * (cpucycles - spc::reference_time) + spc::remainder), spc::ratio_denominator;
((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);
} }
uint8 S9xAPUReadPort (int port) uint8 S9xAPUReadPort (int port)
@ -590,9 +588,12 @@ void S9xAPUTimingSetSpeedup (int ticks)
if (ticks != 0) if (ticks != 0)
printf("APU speedup hack: %d\n", ticks); 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::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(); UpdatePlaybackRate();
} }

View File

@ -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 */

File diff suppressed because it is too large Load Diff

View File

@ -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 */

View File

@ -5,158 +5,56 @@
#include "ring_buffer.h" #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 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: 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) Resampler (int num_samples) : ring_buffer (num_samples << 1)
{ {
r_frac = 0.0;
} }
~Resampler () ~Resampler ()
{ {
} }
void inline bool
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
push (short *src, int num_samples) push (short *src, int num_samples)
{ {
if (max_write () < num_samples) if (max_write () < num_samples)
return false; return false;
ring_buffer::push ((unsigned char *) src, num_samples << 1); !num_samples || ring_buffer::push ((unsigned char *) src, num_samples << 1);
return true; return true;
} }
int inline int
space_empty (void)
{
return buffer_size - size;
}
inline int
space_filled (void)
{
return size;
}
inline int
max_write (void) max_write (void)
{ {
return space_empty () >> 1; return space_empty () >> 1;
} }
void inline void
resize (int num_samples) resize (int num_samples)
{ {
ring_buffer::resize (num_samples << 1); ring_buffer::resize (num_samples << 1);
} }
int
avail (void)
{
return (int) floor (((size >> 2) - r_frac) / r_step) * 2;
}
}; };
#endif /* __RESAMPLER_H */ #endif /* __RESAMPLER_H */

View File

@ -207,22 +207,6 @@ static void S9xResetCPU (void)
static void S9xSoftResetCPU (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.Cycles = 182; // Or 188. This is the cycle count just after the jump to the Reset Vector.
CPU.PrevCycles = -1; CPU.PrevCycles = -1;
CPU.V_Counter = 0; CPU.V_Counter = 0;
@ -248,6 +232,22 @@ static void S9xSoftResetCPU (void)
CPU.AutoSaveTimer = 0; CPU.AutoSaveTimer = 0;
CPU.SRAMModified = FALSE; 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.InterlaceField = FALSE;
Timings.H_Max = Timings.H_Max_Master; Timings.H_Max = Timings.H_Max_Master;
Timings.V_Max = Timings.V_Max_Master; Timings.V_Max = Timings.V_Max_Master;

View File

@ -307,8 +307,10 @@ void S9xMainLoop (void)
if (SA1.Executing) if (SA1.Executing)
S9xSA1MainLoop(); S9xSA1MainLoop();
#if (S9X_ACCURACY_LEVEL <= 2)
while (CPU.Cycles >= CPU.NextEvent) while (CPU.Cycles >= CPU.NextEvent)
S9xDoHEventProcessing(); S9xDoHEventProcessing();
#endif
} }
S9xPackStatus(); S9xPackStatus();
@ -355,10 +357,29 @@ void S9xClearIRQ (uint32 source)
void S9xDoHEventProcessing (void) 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 #ifdef DEBUGGER
if (Settings.TraceHCEvent) if (Settings.TraceHCEvent)
S9xTraceFormattedMessage("--- HC event processing (%02d) expected HC:%04d executed HC:%04d", S9xTraceFormattedMessage("--- HC event processing (%s) expected HC:%04d executed HC:%04d",
CPU.WhichEvent, CPU.NextEvent, CPU.Cycles); eventname[CPU.WhichEvent], CPU.NextEvent, CPU.Cycles);
#endif #endif
#ifdef CPU_SHUTDOWN #ifdef CPU_SHUTDOWN
@ -366,13 +387,16 @@ void S9xDoHEventProcessing (void)
#endif #endif
switch (CPU.WhichEvent) switch (CPU.WhichEvent)
{ {
case HC_HBLANK_START_EVENT: case HC_HBLANK_START_EVENT:
S9xCheckMissingHTimerPosition(Timings.HBlankStart); S9xCheckMissingHTimerPosition(Timings.HBlankStart);
S9xReschedule();
break; break;
case HC_HDMA_START_EVENT: case HC_HDMA_START_EVENT:
S9xCheckMissingHTimerPosition(Timings.HDMAStart);
S9xReschedule();
if (PPU.HDMA && CPU.V_Counter <= PPU.ScreenHeight) if (PPU.HDMA && CPU.V_Counter <= PPU.ScreenHeight)
{ {
#ifdef DEBUGGER #ifdef DEBUGGER
@ -381,8 +405,6 @@ void S9xDoHEventProcessing (void)
PPU.HDMA = S9xDoHDMA(PPU.HDMA); PPU.HDMA = S9xDoHDMA(PPU.HDMA);
} }
S9xCheckMissingHTimerPosition(Timings.HDMAStart);
break; break;
case HC_HCOUNTER_MAX_EVENT: case HC_HCOUNTER_MAX_EVENT:
@ -470,7 +492,7 @@ void S9xDoHEventProcessing (void)
missing.dma_this_frame = 0; missing.dma_this_frame = 0;
#endif #endif
IPPU.MaxBrightness = PPU.Brightness; IPPU.MaxBrightness = PPU.Brightness;
PPU.ForcedBlanking = (Memory.FillRAM [0x2100] >> 7) & 1; PPU.ForcedBlanking = (Memory.FillRAM[0x2100] >> 7) & 1;
if (!PPU.ForcedBlanking) if (!PPU.ForcedBlanking)
{ {
@ -511,14 +533,21 @@ void S9xDoHEventProcessing (void)
S9xStartScreenRefresh(); S9xStartScreenRefresh();
CPU.NextEvent = -1; CPU.NextEvent = -1;
S9xReschedule();
break; break;
case HC_HDMA_INIT_EVENT: case HC_HDMA_INIT_EVENT:
if (CPU.V_Counter == 0)
S9xStartHDMA();
S9xCheckMissingHTimerPosition(Timings.HDMAInit); 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; break;
@ -527,6 +556,7 @@ void S9xDoHEventProcessing (void)
RenderLine((uint8) (CPU.V_Counter - FIRST_VISIBLE_LINE)); RenderLine((uint8) (CPU.V_Counter - FIRST_VISIBLE_LINE));
S9xCheckMissingHTimerPosition(Timings.RenderPos); S9xCheckMissingHTimerPosition(Timings.RenderPos);
S9xReschedule();
break; break;
@ -534,10 +564,12 @@ void S9xDoHEventProcessing (void)
#ifdef DEBUGGER #ifdef DEBUGGER
S9xTraceFormattedMessage("*** WRAM Refresh HC:%04d", CPU.Cycles); S9xTraceFormattedMessage("*** WRAM Refresh HC:%04d", CPU.Cycles);
#endif #endif
S9xCheckMissingHTimerHalt(Timings.WRAMRefreshPos, SNES_WRAM_REFRESH_CYCLES); S9xCheckMissingHTimerHalt(Timings.WRAMRefreshPos, SNES_WRAM_REFRESH_CYCLES);
CPU.Cycles += SNES_WRAM_REFRESH_CYCLES; CPU.Cycles += SNES_WRAM_REFRESH_CYCLES;
S9xCheckMissingHTimerPosition(Timings.WRAMRefreshPos); S9xCheckMissingHTimerPosition(Timings.WRAMRefreshPos);
S9xReschedule();
break; break;
@ -553,13 +585,13 @@ void S9xDoHEventProcessing (void)
if (PPU.VTimerEnabled && (CPU.V_Counter == PPU.VTimerPosition)) if (PPU.VTimerEnabled && (CPU.V_Counter == PPU.VTimerPosition))
S9xSetIRQ(PPU_IRQ_SOURCE); S9xSetIRQ(PPU_IRQ_SOURCE);
S9xReschedule();
break; break;
} }
S9xReschedule();
#ifdef DEBUGGER #ifdef DEBUGGER
if (Settings.TraceHCEvent) 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 #endif
} }

View File

@ -190,7 +190,11 @@
#ifdef SA1_OPCODES #ifdef SA1_OPCODES
#define AddCycles(n) { } #define AddCycles(n) { }
#else #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 #endif
#include "cpuaddr.h" #include "cpuaddr.h"

View File

@ -185,6 +185,8 @@
#include "missing.h" #include "missing.h"
#endif #endif
#define ADD_CYCLES(n) CPU.Cycles += (n)
extern uint8 *HDMAMemPointers[8]; extern uint8 *HDMAMemPointers[8];
extern int HDMA_ModeByteCounts[8]; extern int HDMA_ModeByteCounts[8];
extern SPC7110 s7emu; 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. // 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. // 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) while (CPU.Cycles >= CPU.NextEvent)
S9xDoHEventProcessing(); S9xDoHEventProcessing();
@ -245,7 +247,7 @@ bool8 S9xDoDMA (uint8 Channel)
c = 0x10000; c = 0x10000;
// 8 cycles per channel // 8 cycles per channel
CPU.Cycles += SLOW_ONE_CYCLE; ADD_CYCLES(SLOW_ONE_CYCLE);
// 8 cycles per byte // 8 cycles per byte
while (c) while (c)
{ {
@ -510,7 +512,7 @@ bool8 S9xDoDMA (uint8 Channel)
uint8 Work; uint8 Work;
// 8 cycles per channel // 8 cycles per channel
CPU.Cycles += SLOW_ONE_CYCLE; ADD_CYCLES(SLOW_ONE_CYCLE);
if (!d->ReverseTransfer) if (!d->ReverseTransfer)
{ {
@ -1315,7 +1317,7 @@ static inline bool8 HDMAReadLineCount (int d)
uint8 line; uint8 line;
line = S9xGetByte((DMA[d].ABank << 16) + DMA[d].Address); line = S9xGetByte((DMA[d].ABank << 16) + DMA[d].Address);
CPU.Cycles += SLOW_ONE_CYCLE; ADD_CYCLES(SLOW_ONE_CYCLE);
if (!line) if (!line)
{ {
@ -1327,10 +1329,10 @@ static inline bool8 HDMAReadLineCount (int d)
if (PPU.HDMA & (0xfe << d)) if (PPU.HDMA & (0xfe << d))
{ {
DMA[d].Address++; DMA[d].Address++;
CPU.Cycles += SLOW_ONE_CYCLE * 2; ADD_CYCLES(SLOW_ONE_CYCLE << 1);
} }
else else
CPU.Cycles += SLOW_ONE_CYCLE; ADD_CYCLES(SLOW_ONE_CYCLE);
DMA[d].IndirectAddress = S9xGetWord((DMA[d].ABank << 16) + DMA[d].Address); DMA[d].IndirectAddress = S9xGetWord((DMA[d].ABank << 16) + DMA[d].Address);
DMA[d].Address++; DMA[d].Address++;
@ -1358,7 +1360,7 @@ static inline bool8 HDMAReadLineCount (int d)
if (DMA[d].HDMAIndirectAddressing) 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].IndirectAddress = S9xGetWord((DMA[d].ABank << 16) + DMA[d].Address);
DMA[d].Address += 2; DMA[d].Address += 2;
HDMAMemPointers[d] = S9xGetMemPointer((DMA[d].IndirectBank << 16) + DMA[d].IndirectAddress); HDMAMemPointers[d] = S9xGetMemPointer((DMA[d].IndirectBank << 16) + DMA[d].IndirectAddress);
@ -1390,7 +1392,7 @@ void S9xStartHDMA (void)
// XXX: Not quite right... // XXX: Not quite right...
if (PPU.HDMA != 0) if (PPU.HDMA != 0)
CPU.Cycles += Timings.DMACPUSync; ADD_CYCLES(Timings.DMACPUSync);
for (uint8 i = 0; i < 8; i++) for (uint8 i = 0; i < 8; i++)
{ {
@ -1433,7 +1435,7 @@ uint8 S9xDoHDMA (uint8 byte)
tmpch = CPU.CurrentDMAorHDMAChannel; tmpch = CPU.CurrentDMAorHDMAChannel;
// XXX: Not quite right... // XXX: Not quite right...
CPU.Cycles += Timings.DMACPUSync; ADD_CYCLES(Timings.DMACPUSync);
for (uint8 mask = 1; mask; mask <<= 1, p++, d++) for (uint8 mask = 1; mask; mask <<= 1, p++, d++)
{ {
@ -1498,46 +1500,57 @@ uint8 S9xDoHDMA (uint8 byte)
switch (p->TransferMode) switch (p->TransferMode)
{ {
case 0: case 0:
CPU.Cycles += SLOW_ONE_CYCLE;
DOBYTE(IAddr, 0); DOBYTE(IAddr, 0);
ADD_CYCLES(SLOW_ONE_CYCLE);
break; break;
case 5: case 5:
CPU.Cycles += 4 * SLOW_ONE_CYCLE;
DOBYTE(IAddr + 0, 0); DOBYTE(IAddr + 0, 0);
ADD_CYCLES(SLOW_ONE_CYCLE);
DOBYTE(IAddr + 1, 1); DOBYTE(IAddr + 1, 1);
ADD_CYCLES(SLOW_ONE_CYCLE);
DOBYTE(IAddr + 2, 0); DOBYTE(IAddr + 2, 0);
ADD_CYCLES(SLOW_ONE_CYCLE);
DOBYTE(IAddr + 3, 1); DOBYTE(IAddr + 3, 1);
ADD_CYCLES(SLOW_ONE_CYCLE);
break; break;
case 1: case 1:
CPU.Cycles += 2 * SLOW_ONE_CYCLE;
DOBYTE(IAddr + 0, 0); DOBYTE(IAddr + 0, 0);
ADD_CYCLES(SLOW_ONE_CYCLE);
DOBYTE(IAddr + 1, 1); DOBYTE(IAddr + 1, 1);
ADD_CYCLES(SLOW_ONE_CYCLE);
break; break;
case 2: case 2:
case 6: case 6:
CPU.Cycles += 2 * SLOW_ONE_CYCLE;
DOBYTE(IAddr + 0, 0); DOBYTE(IAddr + 0, 0);
ADD_CYCLES(SLOW_ONE_CYCLE);
DOBYTE(IAddr + 1, 0); DOBYTE(IAddr + 1, 0);
ADD_CYCLES(SLOW_ONE_CYCLE);
break; break;
case 3: case 3:
case 7: case 7:
CPU.Cycles += 4 * SLOW_ONE_CYCLE;
DOBYTE(IAddr + 0, 0); DOBYTE(IAddr + 0, 0);
ADD_CYCLES(SLOW_ONE_CYCLE);
DOBYTE(IAddr + 1, 0); DOBYTE(IAddr + 1, 0);
ADD_CYCLES(SLOW_ONE_CYCLE);
DOBYTE(IAddr + 2, 1); DOBYTE(IAddr + 2, 1);
ADD_CYCLES(SLOW_ONE_CYCLE);
DOBYTE(IAddr + 3, 1); DOBYTE(IAddr + 3, 1);
ADD_CYCLES(SLOW_ONE_CYCLE);
break; break;
case 4: case 4:
CPU.Cycles += 4 * SLOW_ONE_CYCLE;
DOBYTE(IAddr + 0, 0); DOBYTE(IAddr + 0, 0);
ADD_CYCLES(SLOW_ONE_CYCLE);
DOBYTE(IAddr + 1, 1); DOBYTE(IAddr + 1, 1);
ADD_CYCLES(SLOW_ONE_CYCLE);
DOBYTE(IAddr + 2, 2); DOBYTE(IAddr + 2, 2);
ADD_CYCLES(SLOW_ONE_CYCLE);
DOBYTE(IAddr + 3, 3); DOBYTE(IAddr + 3, 3);
ADD_CYCLES(SLOW_ONE_CYCLE);
break; break;
} }
@ -1556,44 +1569,53 @@ uint8 S9xDoHDMA (uint8 byte)
switch (p->TransferMode) switch (p->TransferMode)
{ {
case 0: case 0:
CPU.Cycles += SLOW_ONE_CYCLE;
S9xSetPPU(S9xGetByte(Addr), 0x2100 + p->BAddress); S9xSetPPU(S9xGetByte(Addr), 0x2100 + p->BAddress);
ADD_CYCLES(SLOW_ONE_CYCLE);
break; break;
case 5: case 5:
CPU.Cycles += 2 * SLOW_ONE_CYCLE;
S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress);
ADD_CYCLES(SLOW_ONE_CYCLE);
S9xSetPPU(S9xGetByte(Addr + 1), 0x2101 + p->BAddress); S9xSetPPU(S9xGetByte(Addr + 1), 0x2101 + p->BAddress);
ADD_CYCLES(SLOW_ONE_CYCLE);
Addr += 2; Addr += 2;
/* fall through */ /* fall through */
case 1: case 1:
CPU.Cycles += 2 * SLOW_ONE_CYCLE;
S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress);
ADD_CYCLES(SLOW_ONE_CYCLE);
S9xSetPPU(S9xGetByte(Addr + 1), 0x2101 + p->BAddress); S9xSetPPU(S9xGetByte(Addr + 1), 0x2101 + p->BAddress);
ADD_CYCLES(SLOW_ONE_CYCLE);
break; break;
case 2: case 2:
case 6: case 6:
CPU.Cycles += 2 * SLOW_ONE_CYCLE;
S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress);
ADD_CYCLES(SLOW_ONE_CYCLE);
S9xSetPPU(S9xGetByte(Addr + 1), 0x2100 + p->BAddress); S9xSetPPU(S9xGetByte(Addr + 1), 0x2100 + p->BAddress);
ADD_CYCLES(SLOW_ONE_CYCLE);
break; break;
case 3: case 3:
case 7: case 7:
CPU.Cycles += 4 * SLOW_ONE_CYCLE;
S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress);
ADD_CYCLES(SLOW_ONE_CYCLE);
S9xSetPPU(S9xGetByte(Addr + 1), 0x2100 + p->BAddress); S9xSetPPU(S9xGetByte(Addr + 1), 0x2100 + p->BAddress);
ADD_CYCLES(SLOW_ONE_CYCLE);
S9xSetPPU(S9xGetByte(Addr + 2), 0x2101 + p->BAddress); S9xSetPPU(S9xGetByte(Addr + 2), 0x2101 + p->BAddress);
ADD_CYCLES(SLOW_ONE_CYCLE);
S9xSetPPU(S9xGetByte(Addr + 3), 0x2101 + p->BAddress); S9xSetPPU(S9xGetByte(Addr + 3), 0x2101 + p->BAddress);
ADD_CYCLES(SLOW_ONE_CYCLE);
break; break;
case 4: case 4:
CPU.Cycles += 4 * SLOW_ONE_CYCLE;
S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress); S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress);
ADD_CYCLES(SLOW_ONE_CYCLE);
S9xSetPPU(S9xGetByte(Addr + 1), 0x2101 + p->BAddress); S9xSetPPU(S9xGetByte(Addr + 1), 0x2101 + p->BAddress);
ADD_CYCLES(SLOW_ONE_CYCLE);
S9xSetPPU(S9xGetByte(Addr + 2), 0x2102 + p->BAddress); S9xSetPPU(S9xGetByte(Addr + 2), 0x2102 + p->BAddress);
ADD_CYCLES(SLOW_ONE_CYCLE);
S9xSetPPU(S9xGetByte(Addr + 3), 0x2103 + p->BAddress); S9xSetPPU(S9xGetByte(Addr + 3), 0x2103 + p->BAddress);
ADD_CYCLES(SLOW_ONE_CYCLE);
break; break;
} }
} }
@ -1603,47 +1625,56 @@ uint8 S9xDoHDMA (uint8 byte)
switch (p->TransferMode) switch (p->TransferMode)
{ {
case 0: case 0:
CPU.Cycles += SLOW_ONE_CYCLE;
S9xSetPPU(*HDMAMemPointers[d]++, 0x2100 + p->BAddress); S9xSetPPU(*HDMAMemPointers[d]++, 0x2100 + p->BAddress);
ADD_CYCLES(SLOW_ONE_CYCLE);
break; break;
case 5: case 5:
CPU.Cycles += 2 * SLOW_ONE_CYCLE;
S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress); S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress);
ADD_CYCLES(SLOW_ONE_CYCLE);
S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress); S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress);
ADD_CYCLES(SLOW_ONE_CYCLE);
HDMAMemPointers[d] += 2; HDMAMemPointers[d] += 2;
/* fall through */ /* fall through */
case 1: case 1:
CPU.Cycles += 2 * SLOW_ONE_CYCLE;
S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress); S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress);
ADD_CYCLES(SLOW_ONE_CYCLE);
S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress); S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress);
ADD_CYCLES(SLOW_ONE_CYCLE);
HDMAMemPointers[d] += 2; HDMAMemPointers[d] += 2;
break; break;
case 2: case 2:
case 6: case 6:
CPU.Cycles += 2 * SLOW_ONE_CYCLE;
S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress); S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress);
ADD_CYCLES(SLOW_ONE_CYCLE);
S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2100 + p->BAddress); S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2100 + p->BAddress);
ADD_CYCLES(SLOW_ONE_CYCLE);
HDMAMemPointers[d] += 2; HDMAMemPointers[d] += 2;
break; break;
case 3: case 3:
case 7: case 7:
CPU.Cycles += 4 * SLOW_ONE_CYCLE;
S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress); S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress);
ADD_CYCLES(SLOW_ONE_CYCLE);
S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2100 + p->BAddress); S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2100 + p->BAddress);
ADD_CYCLES(SLOW_ONE_CYCLE);
S9xSetPPU(*(HDMAMemPointers[d] + 2), 0x2101 + p->BAddress); S9xSetPPU(*(HDMAMemPointers[d] + 2), 0x2101 + p->BAddress);
ADD_CYCLES(SLOW_ONE_CYCLE);
S9xSetPPU(*(HDMAMemPointers[d] + 3), 0x2101 + p->BAddress); S9xSetPPU(*(HDMAMemPointers[d] + 3), 0x2101 + p->BAddress);
ADD_CYCLES(SLOW_ONE_CYCLE);
HDMAMemPointers[d] += 4; HDMAMemPointers[d] += 4;
break; break;
case 4: case 4:
CPU.Cycles += 4 * SLOW_ONE_CYCLE;
S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress); S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress);
ADD_CYCLES(SLOW_ONE_CYCLE);
S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress); S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress);
ADD_CYCLES(SLOW_ONE_CYCLE);
S9xSetPPU(*(HDMAMemPointers[d] + 2), 0x2102 + p->BAddress); S9xSetPPU(*(HDMAMemPointers[d] + 2), 0x2102 + p->BAddress);
ADD_CYCLES(SLOW_ONE_CYCLE);
S9xSetPPU(*(HDMAMemPointers[d] + 3), 0x2103 + p->BAddress); S9xSetPPU(*(HDMAMemPointers[d] + 3), 0x2103 + p->BAddress);
ADD_CYCLES(SLOW_ONE_CYCLE);
HDMAMemPointers[d] += 4; HDMAMemPointers[d] += 4;
break; break;
} }
@ -1665,46 +1696,57 @@ uint8 S9xDoHDMA (uint8 byte)
switch (p->TransferMode) switch (p->TransferMode)
{ {
case 0: case 0:
CPU.Cycles += SLOW_ONE_CYCLE;
DOBYTE(IAddr, 0); DOBYTE(IAddr, 0);
ADD_CYCLES(SLOW_ONE_CYCLE);
break; break;
case 5: case 5:
CPU.Cycles += 4 * SLOW_ONE_CYCLE;
DOBYTE(IAddr + 0, 0); DOBYTE(IAddr + 0, 0);
ADD_CYCLES(SLOW_ONE_CYCLE);
DOBYTE(IAddr + 1, 1); DOBYTE(IAddr + 1, 1);
ADD_CYCLES(SLOW_ONE_CYCLE);
DOBYTE(IAddr + 2, 0); DOBYTE(IAddr + 2, 0);
ADD_CYCLES(SLOW_ONE_CYCLE);
DOBYTE(IAddr + 3, 1); DOBYTE(IAddr + 3, 1);
ADD_CYCLES(SLOW_ONE_CYCLE);
break; break;
case 1: case 1:
CPU.Cycles += 2 * SLOW_ONE_CYCLE;
DOBYTE(IAddr + 0, 0); DOBYTE(IAddr + 0, 0);
ADD_CYCLES(SLOW_ONE_CYCLE);
DOBYTE(IAddr + 1, 1); DOBYTE(IAddr + 1, 1);
ADD_CYCLES(SLOW_ONE_CYCLE);
break; break;
case 2: case 2:
case 6: case 6:
CPU.Cycles += 2 * SLOW_ONE_CYCLE;
DOBYTE(IAddr + 0, 0); DOBYTE(IAddr + 0, 0);
ADD_CYCLES(SLOW_ONE_CYCLE);
DOBYTE(IAddr + 1, 0); DOBYTE(IAddr + 1, 0);
ADD_CYCLES(SLOW_ONE_CYCLE);
break; break;
case 3: case 3:
case 7: case 7:
CPU.Cycles += 4 * SLOW_ONE_CYCLE;
DOBYTE(IAddr + 0, 0); DOBYTE(IAddr + 0, 0);
ADD_CYCLES(SLOW_ONE_CYCLE);
DOBYTE(IAddr + 1, 0); DOBYTE(IAddr + 1, 0);
ADD_CYCLES(SLOW_ONE_CYCLE);
DOBYTE(IAddr + 2, 1); DOBYTE(IAddr + 2, 1);
ADD_CYCLES(SLOW_ONE_CYCLE);
DOBYTE(IAddr + 3, 1); DOBYTE(IAddr + 3, 1);
ADD_CYCLES(SLOW_ONE_CYCLE);
break; break;
case 4: case 4:
CPU.Cycles += 4 * SLOW_ONE_CYCLE;
DOBYTE(IAddr + 0, 0); DOBYTE(IAddr + 0, 0);
ADD_CYCLES(SLOW_ONE_CYCLE);
DOBYTE(IAddr + 1, 1); DOBYTE(IAddr + 1, 1);
ADD_CYCLES(SLOW_ONE_CYCLE);
DOBYTE(IAddr + 2, 2); DOBYTE(IAddr + 2, 2);
ADD_CYCLES(SLOW_ONE_CYCLE);
DOBYTE(IAddr + 3, 3); DOBYTE(IAddr + 3, 3);
ADD_CYCLES(SLOW_ONE_CYCLE);
break; break;
} }
@ -1730,7 +1772,7 @@ uint8 S9xDoHDMA (uint8 byte)
} }
} }
else else
CPU.Cycles += SLOW_ONE_CYCLE; ADD_CYCLES(SLOW_ONE_CYCLE);
} }
} }

View File

@ -187,15 +187,63 @@
#include "seta.h" #include "seta.h"
#include "bsx.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; 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) inline uint8 S9xGetByte (uint32 Address)
{ {
int block; int block = (Address & 0xffffff) >> MEMMAP_SHIFT;
uint8 *GetAddress = Memory.Map[block = ((Address & 0xffffff) >> MEMMAP_SHIFT)]; uint8 *GetAddress = Memory.Map[block];
int32 speed = memory_speed(Address);
if (!CPU.InDMAorHDMA) uint8 byte;
CPU.Cycles += Memory.MemorySpeed[block];
if (GetAddress >= (uint8 *) CMemory::MAP_LAST) if (GetAddress >= (uint8 *) CMemory::MAP_LAST)
{ {
@ -203,18 +251,25 @@ inline uint8 S9xGetByte (uint32 Address)
if (Memory.BlockIsRAM[block]) if (Memory.BlockIsRAM[block])
CPU.WaitAddress = CPU.PBPCAtOpcodeStart; CPU.WaitAddress = CPU.PBPCAtOpcodeStart;
#endif #endif
return (*(GetAddress + (Address & 0xffff))); byte = *(GetAddress + (Address & 0xffff));
addCyclesInMemoryAccess;
return (byte);
} }
switch ((pint) GetAddress) switch ((pint) GetAddress)
{ {
case CMemory::MAP_CPU: case CMemory::MAP_CPU:
return (S9xGetCPU(Address & 0xffff)); byte = S9xGetCPU(Address & 0xffff);
addCyclesInMemoryAccess;
return (byte);
case CMemory::MAP_PPU: case CMemory::MAP_PPU:
if (CPU.InDMAorHDMA && (Address & 0xff00) == 0x2100) if (CPU.InDMAorHDMA && (Address & 0xff00) == 0x2100)
return (OpenBus); return (OpenBus);
return (S9xGetPPU(Address & 0xffff));
byte = S9xGetPPU(Address & 0xffff);
addCyclesInMemoryAccess;
return (byte);
case CMemory::MAP_LOROM_SRAM: case CMemory::MAP_LOROM_SRAM:
case CMemory::MAP_SA1RAM: case CMemory::MAP_SA1RAM:
@ -222,45 +277,71 @@ inline uint8 S9xGetByte (uint32 Address)
// Address & 0xff0000 : bank // Address & 0xff0000 : bank
// bank >> 1 | offset : SRAM address, unbound // bank >> 1 | offset : SRAM address, unbound
// unbound & SRAMMask : SRAM offset // 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: 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_HIROM_SRAM:
case CMemory::MAP_RONLY_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: case CMemory::MAP_BWRAM:
return (*(Memory.BWRAM + ((Address & 0x7fff) - 0x6000))); byte = *(Memory.BWRAM + ((Address & 0x7fff) - 0x6000));
addCyclesInMemoryAccess;
return (byte);
case CMemory::MAP_DSP: case CMemory::MAP_DSP:
return (S9xGetDSP(Address & 0xffff)); byte = S9xGetDSP(Address & 0xffff);
addCyclesInMemoryAccess;
return (byte);
case CMemory::MAP_SPC7110_ROM: case CMemory::MAP_SPC7110_ROM:
return (S9xGetSPC7110Byte(Address)); byte = S9xGetSPC7110Byte(Address);
addCyclesInMemoryAccess;
return (byte);
case CMemory::MAP_SPC7110_DRAM: case CMemory::MAP_SPC7110_DRAM:
return (S9xGetSPC7110(0x4800)); byte = S9xGetSPC7110(0x4800);
addCyclesInMemoryAccess;
return (byte);
case CMemory::MAP_C4: case CMemory::MAP_C4:
return (S9xGetC4(Address & 0xffff)); byte = S9xGetC4(Address & 0xffff);
addCyclesInMemoryAccess;
return (byte);
case CMemory::MAP_OBC_RAM: case CMemory::MAP_OBC_RAM:
return (S9xGetOBC1(Address & 0xffff)); byte = S9xGetOBC1(Address & 0xffff);
addCyclesInMemoryAccess;
return (byte);
case CMemory::MAP_SETA_DSP: case CMemory::MAP_SETA_DSP:
return (S9xGetSetaDSP(Address)); byte = S9xGetSetaDSP(Address);
addCyclesInMemoryAccess;
return (byte);
case CMemory::MAP_SETA_RISC: case CMemory::MAP_SETA_RISC:
return (S9xGetST018(Address)); byte = S9xGetST018(Address);
addCyclesInMemoryAccess;
return (byte);
case CMemory::MAP_BSX: case CMemory::MAP_BSX:
return (S9xGetBSX(Address)); byte = S9xGetBSX(Address);
addCyclesInMemoryAccess;
return (byte);
case CMemory::MAP_NONE: case CMemory::MAP_NONE:
default: 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; int block = (Address & 0xffffff) >> MEMMAP_SHIFT;
uint8 *GetAddress = Memory.Map[block = ((Address & 0xffffff) >> MEMMAP_SHIFT)]; uint8 *GetAddress = Memory.Map[block];
int32 speed = memory_speed(Address);
if (!CPU.InDMAorHDMA) uint16 word;
CPU.Cycles += (Memory.MemorySpeed[block] << 1);
if (GetAddress >= (uint8 *) CMemory::MAP_LAST) 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]) if (Memory.BlockIsRAM[block])
CPU.WaitAddress = CPU.PBPCAtOpcodeStart; CPU.WaitAddress = CPU.PBPCAtOpcodeStart;
#endif #endif
return (READ_WORD(GetAddress + (Address & 0xffff))); word = READ_WORD(GetAddress + (Address & 0xffff));
addCyclesInMemoryAccess_x2;
return (word);
} }
switch ((pint) GetAddress) switch ((pint) GetAddress)
{ {
case CMemory::MAP_CPU: 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: case CMemory::MAP_PPU:
if (CPU.InDMAorHDMA) 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 (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_LOROM_SRAM:
case CMemory::MAP_SA1RAM: case CMemory::MAP_SA1RAM:
if (Memory.SRAMMask >= MEMMAP_MASK) 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 else
return ((*(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask))) | word = (*(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask))) |
((*(Memory.SRAM + (((((Address + 1) & 0xff0000) >> 1) | ((Address + 1) & 0x7fff)) & Memory.SRAMMask))) << 8)); ((*(Memory.SRAM + (((((Address + 1) & 0xff0000) >> 1) | ((Address + 1) & 0x7fff)) & Memory.SRAMMask))) << 8);
addCyclesInMemoryAccess_x2;
return (word);
case CMemory::MAP_LOROM_SRAM_B: case CMemory::MAP_LOROM_SRAM_B:
if (Multi.sramMaskB >= MEMMAP_MASK) 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 else
return ((*(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB))) | word = (*(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB))) |
((*(Multi.sramB + (((((Address + 1) & 0xff0000) >> 1) | ((Address + 1) & 0x7fff)) & Multi.sramMaskB))) << 8)); ((*(Multi.sramB + (((((Address + 1) & 0xff0000) >> 1) | ((Address + 1) & 0x7fff)) & Multi.sramMaskB))) << 8);
addCyclesInMemoryAccess_x2;
return (word);
case CMemory::MAP_HIROM_SRAM: case CMemory::MAP_HIROM_SRAM:
case CMemory::MAP_RONLY_SRAM: case CMemory::MAP_RONLY_SRAM:
if (Memory.SRAMMask >= MEMMAP_MASK) 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 else
return ((*(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask)) | word = (*(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask)) |
(*(Memory.SRAM + ((((Address + 1) & 0x7fff) - 0x6000 + (((Address + 1) & 0xf0000) >> 3)) & Memory.SRAMMask)) << 8))); (*(Memory.SRAM + ((((Address + 1) & 0x7fff) - 0x6000 + (((Address + 1) & 0xf0000) >> 3)) & Memory.SRAMMask)) << 8));
addCyclesInMemoryAccess_x2;
return (word);
case CMemory::MAP_BWRAM: 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: 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: 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: 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: 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: 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: 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: 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: 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: case CMemory::MAP_NONE:
default: 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; CPU.WaitAddress = 0xffffffff;
#endif #endif
int block; int block = (Address & 0xffffff) >> MEMMAP_SHIFT;
uint8 *SetAddress = Memory.WriteMap[block = ((Address & 0xffffff) >> MEMMAP_SHIFT)]; uint8 *SetAddress = Memory.WriteMap[block];
int32 speed = memory_speed(Address);
if (!CPU.InDMAorHDMA)
CPU.Cycles += Memory.MemorySpeed[block];
if (SetAddress >= (uint8 *) CMemory::MAP_LAST) if (SetAddress >= (uint8 *) CMemory::MAP_LAST)
{ {
#ifdef CPU_SHUTDOWN #ifdef CPU_SHUTDOWN
SetAddress += (Address & 0xffff); SetAddress += (Address & 0xffff);
*SetAddress = Byte; *SetAddress = Byte;
addCyclesInMemoryAccess;
if (Settings.SA1) if (Settings.SA1)
{ {
@ -404,6 +535,7 @@ inline void S9xSetByte (uint8 Byte, uint32 Address)
} }
#else #else
*(SetAddress + (Address & 0xffff)) = Byte; *(SetAddress + (Address & 0xffff)) = Byte;
addCyclesInMemoryAccess;
#endif #endif
return; return;
} }
@ -412,12 +544,15 @@ inline void S9xSetByte (uint8 Byte, uint32 Address)
{ {
case CMemory::MAP_CPU: case CMemory::MAP_CPU:
S9xSetCPU(Byte, Address & 0xffff); S9xSetCPU(Byte, Address & 0xffff);
addCyclesInMemoryAccess;
return; return;
case CMemory::MAP_PPU: case CMemory::MAP_PPU:
if (CPU.InDMAorHDMA && (Address & 0xff00) == 0x2100) if (CPU.InDMAorHDMA && (Address & 0xff00) == 0x2100)
return; return;
S9xSetPPU(Byte, Address & 0xffff); S9xSetPPU(Byte, Address & 0xffff);
addCyclesInMemoryAccess;
return; return;
case CMemory::MAP_LOROM_SRAM: case CMemory::MAP_LOROM_SRAM:
@ -427,6 +562,7 @@ inline void S9xSetByte (uint8 Byte, uint32 Address)
CPU.SRAMModified = TRUE; CPU.SRAMModified = TRUE;
} }
addCyclesInMemoryAccess;
return; return;
case CMemory::MAP_LOROM_SRAM_B: case CMemory::MAP_LOROM_SRAM_B:
@ -436,6 +572,7 @@ inline void S9xSetByte (uint8 Byte, uint32 Address)
CPU.SRAMModified = TRUE; CPU.SRAMModified = TRUE;
} }
addCyclesInMemoryAccess;
return; return;
case CMemory::MAP_HIROM_SRAM: case CMemory::MAP_HIROM_SRAM:
@ -445,44 +582,54 @@ inline void S9xSetByte (uint8 Byte, uint32 Address)
CPU.SRAMModified = TRUE; CPU.SRAMModified = TRUE;
} }
addCyclesInMemoryAccess;
return; return;
case CMemory::MAP_BWRAM: case CMemory::MAP_BWRAM:
*(Memory.BWRAM + ((Address & 0x7fff) - 0x6000)) = Byte; *(Memory.BWRAM + ((Address & 0x7fff) - 0x6000)) = Byte;
CPU.SRAMModified = TRUE; CPU.SRAMModified = TRUE;
addCyclesInMemoryAccess;
return; return;
case CMemory::MAP_SA1RAM: case CMemory::MAP_SA1RAM:
*(Memory.SRAM + (Address & 0xffff)) = Byte; *(Memory.SRAM + (Address & 0xffff)) = Byte;
SA1.Executing = !SA1.Waiting; SA1.Executing = !SA1.Waiting;
addCyclesInMemoryAccess;
return; return;
case CMemory::MAP_DSP: case CMemory::MAP_DSP:
S9xSetDSP(Byte, Address & 0xffff); S9xSetDSP(Byte, Address & 0xffff);
addCyclesInMemoryAccess;
return; return;
case CMemory::MAP_C4: case CMemory::MAP_C4:
S9xSetC4(Byte, Address & 0xffff); S9xSetC4(Byte, Address & 0xffff);
addCyclesInMemoryAccess;
return; return;
case CMemory::MAP_OBC_RAM: case CMemory::MAP_OBC_RAM:
S9xSetOBC1(Byte, Address & 0xffff); S9xSetOBC1(Byte, Address & 0xffff);
addCyclesInMemoryAccess;
return; return;
case CMemory::MAP_SETA_DSP: case CMemory::MAP_SETA_DSP:
S9xSetSetaDSP(Byte, Address); S9xSetSetaDSP(Byte, Address);
addCyclesInMemoryAccess;
return; return;
case CMemory::MAP_SETA_RISC: case CMemory::MAP_SETA_RISC:
S9xSetST018(Byte, Address); S9xSetST018(Byte, Address);
addCyclesInMemoryAccess;
return; return;
case CMemory::MAP_BSX: case CMemory::MAP_BSX:
S9xSetBSX(Byte, Address); S9xSetBSX(Byte, Address);
addCyclesInMemoryAccess;
return; return;
case CMemory::MAP_NONE: case CMemory::MAP_NONE:
default: default:
addCyclesInMemoryAccess;
return; return;
} }
} }
@ -527,17 +674,16 @@ inline void S9xSetWord (uint16 Word, uint32 Address, enum s9xwrap_t w = WRAP_NON
CPU.WaitAddress = 0xffffffff; CPU.WaitAddress = 0xffffffff;
#endif #endif
int block; int block = (Address & 0xffffff) >> MEMMAP_SHIFT;
uint8 *SetAddress = Memory.WriteMap[block = ((Address & 0xffffff) >> MEMMAP_SHIFT)]; uint8 *SetAddress = Memory.WriteMap[block];
int32 speed = memory_speed(Address);
if (!CPU.InDMAorHDMA)
CPU.Cycles += (Memory.MemorySpeed[block] << 1);
if (SetAddress >= (uint8 *) CMemory::MAP_LAST) if (SetAddress >= (uint8 *) CMemory::MAP_LAST)
{ {
#ifdef CPU_SHUTDOWN #ifdef CPU_SHUTDOWN
SetAddress += (Address & 0xffff); SetAddress += (Address & 0xffff);
WRITE_WORD(SetAddress, Word); WRITE_WORD(SetAddress, Word);
addCyclesInMemoryAccess_x2;
if (Settings.SA1) if (Settings.SA1)
{ {
@ -549,6 +695,7 @@ inline void S9xSetWord (uint16 Word, uint32 Address, enum s9xwrap_t w = WRAP_NON
} }
#else #else
WRITE_WORD(SetAddress + (Address & 0xffff), Word); WRITE_WORD(SetAddress + (Address & 0xffff), Word);
addCyclesInMemoryAccess_x2;
#endif #endif
return; return;
} }
@ -559,16 +706,20 @@ inline void S9xSetWord (uint16 Word, uint32 Address, enum s9xwrap_t w = WRAP_NON
if (o) if (o)
{ {
S9xSetCPU(Word >> 8, (Address + 1) & 0xffff); S9xSetCPU(Word >> 8, (Address + 1) & 0xffff);
addCyclesInMemoryAccess;
S9xSetCPU((uint8) Word, Address & 0xffff); S9xSetCPU((uint8) Word, Address & 0xffff);
addCyclesInMemoryAccess;
return;
} }
else else
{ {
S9xSetCPU((uint8) Word, Address & 0xffff); S9xSetCPU((uint8) Word, Address & 0xffff);
addCyclesInMemoryAccess;
S9xSetCPU(Word >> 8, (Address + 1) & 0xffff); S9xSetCPU(Word >> 8, (Address + 1) & 0xffff);
addCyclesInMemoryAccess;
return;
} }
return;
case CMemory::MAP_PPU: case CMemory::MAP_PPU:
if (CPU.InDMAorHDMA) if (CPU.InDMAorHDMA)
{ {
@ -582,16 +733,20 @@ inline void S9xSetWord (uint16 Word, uint32 Address, enum s9xwrap_t w = WRAP_NON
if (o) if (o)
{ {
S9xSetPPU(Word >> 8, (Address + 1) & 0xffff); S9xSetPPU(Word >> 8, (Address + 1) & 0xffff);
addCyclesInMemoryAccess;
S9xSetPPU((uint8) Word, Address & 0xffff); S9xSetPPU((uint8) Word, Address & 0xffff);
addCyclesInMemoryAccess;
return;
} }
else else
{ {
S9xSetPPU((uint8) Word, Address & 0xffff); S9xSetPPU((uint8) Word, Address & 0xffff);
addCyclesInMemoryAccess;
S9xSetPPU(Word >> 8, (Address + 1) & 0xffff); S9xSetPPU(Word >> 8, (Address + 1) & 0xffff);
addCyclesInMemoryAccess;
return;
} }
return;
case CMemory::MAP_LOROM_SRAM: case CMemory::MAP_LOROM_SRAM:
if (Memory.SRAMMask) if (Memory.SRAMMask)
{ {
@ -606,6 +761,7 @@ inline void S9xSetWord (uint16 Word, uint32 Address, enum s9xwrap_t w = WRAP_NON
CPU.SRAMModified = TRUE; CPU.SRAMModified = TRUE;
} }
addCyclesInMemoryAccess_x2;
return; return;
case CMemory::MAP_LOROM_SRAM_B: 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; CPU.SRAMModified = TRUE;
} }
addCyclesInMemoryAccess_x2;
return; return;
case CMemory::MAP_HIROM_SRAM: 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; CPU.SRAMModified = TRUE;
} }
addCyclesInMemoryAccess_x2;
return; return;
case CMemory::MAP_BWRAM: case CMemory::MAP_BWRAM:
WRITE_WORD(Memory.BWRAM + ((Address & 0x7fff) - 0x6000), Word); WRITE_WORD(Memory.BWRAM + ((Address & 0x7fff) - 0x6000), Word);
CPU.SRAMModified = TRUE; CPU.SRAMModified = TRUE;
addCyclesInMemoryAccess_x2;
return; return;
case CMemory::MAP_SA1RAM: case CMemory::MAP_SA1RAM:
WRITE_WORD(Memory.SRAM + (Address & 0xffff), Word); WRITE_WORD(Memory.SRAM + (Address & 0xffff), Word);
SA1.Executing = !SA1.Waiting; SA1.Executing = !SA1.Waiting;
addCyclesInMemoryAccess_x2;
return; return;
case CMemory::MAP_DSP: case CMemory::MAP_DSP:
if (o) if (o)
{ {
S9xSetDSP(Word >> 8, (Address + 1) & 0xffff); S9xSetDSP(Word >> 8, (Address + 1) & 0xffff);
addCyclesInMemoryAccess;
S9xSetDSP((uint8) Word, Address & 0xffff); S9xSetDSP((uint8) Word, Address & 0xffff);
addCyclesInMemoryAccess;
return;
} }
else else
{ {
S9xSetDSP((uint8) Word, Address & 0xffff); S9xSetDSP((uint8) Word, Address & 0xffff);
addCyclesInMemoryAccess;
S9xSetDSP(Word >> 8, (Address + 1) & 0xffff); S9xSetDSP(Word >> 8, (Address + 1) & 0xffff);
addCyclesInMemoryAccess;
return;
} }
return;
case CMemory::MAP_C4: case CMemory::MAP_C4:
if (o) if (o)
{ {
S9xSetC4(Word >> 8, (Address + 1) & 0xffff); S9xSetC4(Word >> 8, (Address + 1) & 0xffff);
addCyclesInMemoryAccess;
S9xSetC4((uint8) Word, Address & 0xffff); S9xSetC4((uint8) Word, Address & 0xffff);
addCyclesInMemoryAccess;
return;
} }
else else
{ {
S9xSetC4((uint8) Word, Address & 0xffff); S9xSetC4((uint8) Word, Address & 0xffff);
addCyclesInMemoryAccess;
S9xSetC4(Word >> 8, (Address + 1) & 0xffff); S9xSetC4(Word >> 8, (Address + 1) & 0xffff);
addCyclesInMemoryAccess;
return;
} }
return;
case CMemory::MAP_OBC_RAM: case CMemory::MAP_OBC_RAM:
if (o) if (o)
{ {
S9xSetOBC1(Word >> 8, (Address + 1) & 0xffff); S9xSetOBC1(Word >> 8, (Address + 1) & 0xffff);
addCyclesInMemoryAccess;
S9xSetOBC1((uint8) Word, Address & 0xffff); S9xSetOBC1((uint8) Word, Address & 0xffff);
addCyclesInMemoryAccess;
return;
} }
else else
{ {
S9xSetOBC1((uint8) Word, Address & 0xffff); S9xSetOBC1((uint8) Word, Address & 0xffff);
addCyclesInMemoryAccess;
S9xSetOBC1(Word >> 8, (Address + 1) & 0xffff); S9xSetOBC1(Word >> 8, (Address + 1) & 0xffff);
addCyclesInMemoryAccess;
return;
} }
return;
case CMemory::MAP_SETA_DSP: case CMemory::MAP_SETA_DSP:
if (o) if (o)
{ {
S9xSetSetaDSP(Word >> 8, Address + 1); S9xSetSetaDSP(Word >> 8, Address + 1);
addCyclesInMemoryAccess;
S9xSetSetaDSP((uint8) Word, Address); S9xSetSetaDSP((uint8) Word, Address);
addCyclesInMemoryAccess;
return;
} }
else else
{ {
S9xSetSetaDSP((uint8) Word, Address); S9xSetSetaDSP((uint8) Word, Address);
addCyclesInMemoryAccess;
S9xSetSetaDSP(Word >> 8, Address + 1); S9xSetSetaDSP(Word >> 8, Address + 1);
addCyclesInMemoryAccess;
return;
} }
return;
case CMemory::MAP_SETA_RISC: case CMemory::MAP_SETA_RISC:
if (o) if (o)
{ {
S9xSetST018(Word >> 8, Address + 1); S9xSetST018(Word >> 8, Address + 1);
addCyclesInMemoryAccess;
S9xSetST018((uint8) Word, Address); S9xSetST018((uint8) Word, Address);
addCyclesInMemoryAccess;
return;
} }
else else
{ {
S9xSetST018((uint8) Word, Address); S9xSetST018((uint8) Word, Address);
addCyclesInMemoryAccess;
S9xSetST018(Word >> 8, Address + 1); S9xSetST018(Word >> 8, Address + 1);
addCyclesInMemoryAccess;
return;
} }
return;
case CMemory::MAP_BSX: case CMemory::MAP_BSX:
if (o) if (o)
{ {
S9xSetBSX(Word >> 8, Address + 1); S9xSetBSX(Word >> 8, Address + 1);
addCyclesInMemoryAccess;
S9xSetBSX((uint8) Word, Address); S9xSetBSX((uint8) Word, Address);
addCyclesInMemoryAccess;
return;
} }
else else
{ {
S9xSetBSX((uint8) Word, Address); S9xSetBSX((uint8) Word, Address);
addCyclesInMemoryAccess;
S9xSetBSX(Word >> 8, Address + 1); S9xSetBSX(Word >> 8, Address + 1);
addCyclesInMemoryAccess;
return;
} }
return;
case CMemory::MAP_NONE: case CMemory::MAP_NONE:
default: default:
addCyclesInMemoryAccess_x2;
return; return;
} }
} }
@ -748,7 +933,7 @@ inline void S9xSetPCBase (uint32 Address)
int block; int block;
uint8 *GetAddress = Memory.Map[block = ((Address & 0xffffff) >> MEMMAP_SHIFT)]; uint8 *GetAddress = Memory.Map[block = ((Address & 0xffffff) >> MEMMAP_SHIFT)];
CPU.MemSpeed = Memory.MemorySpeed[block]; CPU.MemSpeed = memory_speed(Address);
CPU.MemSpeedx2 = CPU.MemSpeed << 1; CPU.MemSpeedx2 = CPU.MemSpeed << 1;
if (GetAddress >= (uint8 *) CMemory::MAP_LAST) if (GetAddress >= (uint8 *) CMemory::MAP_LAST)

View File

@ -2632,9 +2632,6 @@ void CMemory::InitROM (void)
Timings.NMIDMADelay = 24; Timings.NMIDMADelay = 24;
Timings.IRQPendCount = 0; Timings.IRQPendCount = 0;
CPU.FastROMSpeed = 0;
ResetSpeedMap();
IPPU.TotalEmulatedFrames = 0; IPPU.TotalEmulatedFrames = 0;
//// Hack games //// Hack games
@ -2676,36 +2673,6 @@ void CMemory::InitROM (void)
S9xVerifyControllers(); 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 // memory map
uint32 CMemory::map_mirror (uint32 size, uint32 pos) uint32 CMemory::map_mirror (uint32 size, uint32 pos)
@ -3617,37 +3584,6 @@ void CMemory::ApplyROMFixes (void)
Timings.HDMAStart = SNES_HDMA_START_HC + Settings.HDMATimingHack - 100; Timings.HDMAStart = SNES_HDMA_START_HC + Settings.HDMATimingHack - 100;
Timings.HBlankStart = SNES_HBLANK_START_HC + Timings.HDMAStart - SNES_HDMA_START_HC; 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) if (!Settings.DisableGameSpecificHacks)
{ {
// The delay to sync CPU and DMA which Snes9x cannot emulate. // The delay to sync CPU and DMA which Snes9x cannot emulate.
@ -3678,6 +3614,12 @@ void CMemory::ApplyROMFixes (void)
Timings.IRQPendCount = 2; Timings.IRQPendCount = 2;
printf("IRQ count hack: %d\n", Timings.IRQPendCount); 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) if (!Settings.DisableGameSpecificHacks)

View File

@ -242,7 +242,6 @@ struct CMemory
uint8 *WriteMap[MEMMAP_NUM_BLOCKS]; uint8 *WriteMap[MEMMAP_NUM_BLOCKS];
uint8 BlockIsRAM[MEMMAP_NUM_BLOCKS]; uint8 BlockIsRAM[MEMMAP_NUM_BLOCKS];
uint8 BlockIsROM[MEMMAP_NUM_BLOCKS]; uint8 BlockIsROM[MEMMAP_NUM_BLOCKS];
uint8 MemorySpeed[MEMMAP_NUM_BLOCKS];
uint8 ExtendedFormat; uint8 ExtendedFormat;
char ROMFilename[PATH_MAX + 1]; char ROMFilename[PATH_MAX + 1];
@ -290,8 +289,6 @@ struct CMemory
char * SafeANK (const char *); char * SafeANK (const char *);
void ParseSNESHeader (uint8 *); void ParseSNESHeader (uint8 *);
void InitROM (void); void InitROM (void);
void FixROMSpeed (void);
void ResetSpeedMap (void);
uint32 map_mirror (uint32, uint32); uint32 map_mirror (uint32, uint32);
void map_lorom (uint32, uint32, uint32, uint32, uint32); void map_lorom (uint32, uint32, uint32, uint32, uint32);

View File

@ -1565,8 +1565,6 @@ void S9xSetCPU (uint8 Byte, uint16 Address)
{ {
if (Address < 0x4200) if (Address < 0x4200)
{ {
CPU.Cycles += ONE_CYCLE; // XSlow
switch (Address) switch (Address)
{ {
case 0x4016: // JOYSER0 case 0x4016: // JOYSER0
@ -1851,8 +1849,6 @@ void S9xSetCPU (uint8 Byte, uint16 Address)
} }
else else
CPU.FastROMSpeed = SLOW_ONE_CYCLE; CPU.FastROMSpeed = SLOW_ONE_CYCLE;
Memory.FixROMSpeed();
} }
break; break;
@ -1911,8 +1907,6 @@ uint8 S9xGetCPU (uint16 Address)
} }
#endif #endif
CPU.Cycles += ONE_CYCLE; // XSlow
switch (Address) switch (Address)
{ {
case 0x4016: // JOYSER0 case 0x4016: // JOYSER0

View File

@ -788,13 +788,41 @@ static void S9xSA1CharConv2 (void)
uint32 offset = (SA1.in_char_dma & 7) ? 0 : 1; 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 depth = (Memory.FillRAM[0x2231] & 3) == 0 ? 8 : (Memory.FillRAM[0x2231] & 3) == 1 ? 4 : 2;
int bytes_per_char = 8 * depth; 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; uint8 *q = &Memory.ROM[CMemory::MAX_ROM_SIZE - 0x10000] + offset * 64;
switch (depth) switch (depth)
{ {
case 2: 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: 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; break;
case 8: case 8:

View File

@ -209,7 +209,7 @@ bool8 S9xDoScreenshot (int width, int height)
if (!png_ptr) if (!png_ptr)
{ {
fclose(fp); fclose(fp);
unlink(fname); remove(fname);
S9xMessage(S9X_ERROR, 0, "Failed to take screenshot."); S9xMessage(S9X_ERROR, 0, "Failed to take screenshot.");
return (FALSE); return (FALSE);
} }
@ -219,7 +219,7 @@ bool8 S9xDoScreenshot (int width, int height)
{ {
png_destroy_write_struct(&png_ptr, (png_infopp) NULL); png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
fclose(fp); fclose(fp);
unlink(fname); remove(fname);
S9xMessage(S9X_ERROR, 0, "Failed to take screenshot."); S9xMessage(S9X_ERROR, 0, "Failed to take screenshot.");
return (FALSE); return (FALSE);
} }
@ -228,7 +228,7 @@ bool8 S9xDoScreenshot (int width, int height)
{ {
png_destroy_write_struct(&png_ptr, &info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr);
fclose(fp); fclose(fp);
unlink(fname); remove(fname);
S9xMessage(S9X_ERROR, 0, "Failed to take screenshot."); S9xMessage(S9X_ERROR, 0, "Failed to take screenshot.");
return (FALSE); return (FALSE);
} }

View File

@ -1692,7 +1692,6 @@ int S9xUnfreezeFromStream (STREAM stream)
S9xSetPCBase(Registers.PBPC); S9xSetPCBase(Registers.PBPC);
S9xUnpackStatus(); S9xUnpackStatus();
S9xFixCycles(); S9xFixCycles();
Memory.FixROMSpeed();
for (int d = 0; d < 8; d++) for (int d = 0; d < 8; d++)
DMA[d] = dma_snap.dma[d]; DMA[d] = dma_snap.dma[d];

View File

@ -179,13 +179,15 @@
#define _SNES9X_H_ #define _SNES9X_H_
#ifndef VERSION #ifndef VERSION
#define VERSION "1.52" #define VERSION "1.53"
#endif #endif
#include "port.h" #include "port.h"
#include "65c816.h" #include "65c816.h"
#include "messages.h" #include "messages.h"
#define S9X_ACCURACY_LEVEL 3
#ifdef ZLIB #ifdef ZLIB
#include <zlib.h> #include <zlib.h>
#define STREAM gzFile #define STREAM gzFile