mirror of
https://github.com/dborth/snes9xgx.git
synced 2024-11-27 21:14:21 +01:00
upstream changes. change sound defaults
This commit is contained in:
parent
723010768b
commit
4e752fceb8
@ -450,11 +450,12 @@ DefaultSettings ()
|
||||
Settings.HDMATimingHack = 100;
|
||||
|
||||
// Sound defaults. On Wii this is 32Khz/16bit/Stereo
|
||||
Settings.SoundSync = true;
|
||||
Settings.SixteenBitSound = true;
|
||||
Settings.Stereo = true;
|
||||
Settings.ReverseStereo = true;
|
||||
Settings.SoundPlaybackRate = 32000;
|
||||
Settings.SoundInputRate = 31950;
|
||||
Settings.SoundInputRate = 32000;
|
||||
|
||||
// Graphics
|
||||
Settings.Transparency = true;
|
||||
|
@ -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();
|
||||
}
|
||||
|
144
source/snes9x/apu/hermite_resampler.h
Normal file
144
source/snes9x/apu/hermite_resampler.h
Normal 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
115
source/snes9x/apu/linear_resampler.h
Normal file
115
source/snes9x/apu/linear_resampler.h
Normal 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 */
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -2632,9 +2632,6 @@ void CMemory::InitROM (void)
|
||||
Timings.NMIDMADelay = 24;
|
||||
Timings.IRQPendCount = 0;
|
||||
|
||||
CPU.FastROMSpeed = 0;
|
||||
ResetSpeedMap();
|
||||
|
||||
IPPU.TotalEmulatedFrames = 0;
|
||||
|
||||
//// Hack games
|
||||
@ -2676,36 +2673,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)
|
||||
@ -3617,37 +3584,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.
|
||||
@ -3678,6 +3614,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)
|
||||
|
@ -242,7 +242,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];
|
||||
@ -290,8 +289,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);
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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];
|
||||
|
@ -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 <zlib.h>
|
||||
#define STREAM gzFile
|
||||
|
Loading…
Reference in New Issue
Block a user