Update to latest WIP

This commit is contained in:
OV2 2010-09-25 18:46:06 +02:00
parent d1666860e0
commit debd16c179
24 changed files with 968 additions and 457 deletions

View File

@ -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
apu/hermite_resampler.h Normal file
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 */

115
apu/linear_resampler.h Normal file
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"
#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 */

32
cpu.cpp
View File

@ -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;

View File

@ -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
}

View File

@ -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"

200
debug.cpp
View File

@ -317,6 +317,10 @@ static int AddrModes[256] =
4, 11, 9, 20, 26, 7, 7, 13, 0, 16, 0, 0, 23, 15, 15, 18 // F
};
static uint8 S9xDebugGetByte (uint32);
static uint16 S9xDebugGetWord (uint32);
static uint8 S9xDebugSA1GetByte (uint32);
static uint16 S9xDebugSA1GetWord (uint32);
static uint8 debug_cpu_op_print (char *, uint8, uint16);
static uint8 debug_sa1_op_print (char *, uint8, uint16);
static void debug_line_print (const char *);
@ -329,6 +333,107 @@ static void debug_whats_used (void);
static void debug_whats_missing (void);
static uint8 S9xDebugGetByte (uint32 Address)
{
int block = (Address & 0xffffff) >> MEMMAP_SHIFT;
uint8 *GetAddress = Memory.Map[block];
uint8 byte = 0;
if (GetAddress >= (uint8 *) CMemory::MAP_LAST)
{
byte = *(GetAddress + (Address & 0xffff));
return (byte);
}
switch ((pint) GetAddress)
{
case CMemory::MAP_LOROM_SRAM:
case CMemory::MAP_SA1RAM:
byte = *(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask));
return (byte);
case CMemory::MAP_LOROM_SRAM_B:
byte = *(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB));
return (byte);
case CMemory::MAP_HIROM_SRAM:
case CMemory::MAP_RONLY_SRAM:
byte = *(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask));
return (byte);
case CMemory::MAP_BWRAM:
byte = *(Memory.BWRAM + ((Address & 0x7fff) - 0x6000));
return (byte);
default:
return (byte);
}
}
static uint16 S9xDebugGetWord (uint32 Address)
{
uint16 word;
word = S9xDebugGetByte(Address);
word |= S9xDebugGetByte(Address + 1) << 8;
return (word);
}
static uint8 S9xDebugSA1GetByte (uint32 Address)
{
int block = (Address & 0xffffff) >> MEMMAP_SHIFT;
uint8 *GetAddress = SA1.Map[block];
uint8 byte = 0;
if (GetAddress >= (uint8 *) CMemory::MAP_LAST)
{
byte = *(GetAddress + (Address & 0xffff));
return (byte);
}
switch ((pint) GetAddress)
{
case CMemory::MAP_LOROM_SRAM:
case CMemory::MAP_SA1RAM:
byte = *(Memory.SRAM + (Address & 0xffff));
return (byte);
case CMemory::MAP_BWRAM:
byte = *(SA1.BWRAM + ((Address & 0x7fff) - 0x6000));
return (byte);
case CMemory::MAP_BWRAM_BITMAP:
Address -= 0x600000;
if (SA1.VirtualBitmapFormat == 2)
byte = (Memory.SRAM[(Address >> 2) & 0xffff] >> ((Address & 3) << 1)) & 3;
else
byte = (Memory.SRAM[(Address >> 1) & 0xffff] >> ((Address & 1) << 2)) & 15;
return (byte);
case CMemory::MAP_BWRAM_BITMAP2:
Address = (Address & 0xffff) - 0x6000;
if (SA1.VirtualBitmapFormat == 2)
byte = (SA1.BWRAM[(Address >> 2) & 0xffff] >> ((Address & 3) << 1)) & 3;
else
byte = (SA1.BWRAM[(Address >> 1) & 0xffff] >> ((Address & 1) << 2)) & 15;
return (byte);
default:
return (byte);
}
}
static uint16 S9xDebugSA1GetWord (uint32 Address)
{
uint16 word;
word = S9xDebugSA1GetByte(Address);
word |= S9xDebugSA1GetByte(Address + 1) << 8;
return (word);
}
static uint8 debug_cpu_op_print (char *Line, uint8 Bank, uint16 Address)
{
uint8 S9xOpcode;
@ -339,15 +444,12 @@ static uint8 debug_cpu_op_print (char *Line, uint8 Bank, uint16 Address)
int8 SByte;
uint8 Size = 0;
int32 Cycles = CPU.Cycles;
uint32 WaitAddress = CPU.WaitAddress;
S9xOpcode = S9xGetByte((Bank << 16) + Address);
S9xOpcode = S9xDebugGetByte((Bank << 16) + Address);
sprintf(Line, "$%02X:%04X %02X ", Bank, Address, S9xOpcode);
Operant[0] = S9xGetByte((Bank << 16) + Address + 1);
Operant[1] = S9xGetByte((Bank << 16) + Address + 2);
Operant[2] = S9xGetByte((Bank << 16) + Address + 3);
Operant[0] = S9xDebugGetByte((Bank << 16) + Address + 1);
Operant[1] = S9xDebugGetByte((Bank << 16) + Address + 2);
Operant[2] = S9xDebugGetByte((Bank << 16) + Address + 3);
switch (AddrModes[S9xOpcode])
{
@ -505,7 +607,7 @@ static uint8 debug_cpu_op_print (char *Line, uint8 Bank, uint16 Address)
Operant[0]);
Word = Operant[0];
Word += Registers.D.W;
Word = S9xGetWord(Word);
Word = S9xDebugGetWord(Word);
sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word);
Size = 2;
break;
@ -520,7 +622,7 @@ static uint8 debug_cpu_op_print (char *Line, uint8 Bank, uint16 Address)
Word = Operant[0];
Word += Registers.D.W;
Word += Registers.X.W;
Word = S9xGetWord(Word);
Word = S9xDebugGetWord(Word);
sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word);
Size = 2;
break;
@ -534,7 +636,7 @@ static uint8 debug_cpu_op_print (char *Line, uint8 Bank, uint16 Address)
Operant[0]);
Word = Operant[0];
Word += Registers.D.W;
Word = S9xGetWord(Word);
Word = S9xDebugGetWord(Word);
Word += Registers.Y.W;
sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word);
Size = 2;
@ -549,8 +651,8 @@ static uint8 debug_cpu_op_print (char *Line, uint8 Bank, uint16 Address)
Operant[0]);
Word = Operant[0];
Word += Registers.D.W;
Byte = S9xGetByte(Word + 2);
Word = S9xGetWord(Word);
Byte = S9xDebugGetByte(Word + 2);
Word = S9xDebugGetWord(Word);
sprintf(Line, "%-32s[$%02X:%04X]", Line, Byte, Word);
Size = 2;
break;
@ -564,8 +666,8 @@ static uint8 debug_cpu_op_print (char *Line, uint8 Bank, uint16 Address)
Operant[0]);
Word = Operant[0];
Word += Registers.D.W;
Byte = S9xGetByte(Word + 2);
Word = S9xGetWord(Word);
Byte = S9xDebugGetByte(Word + 2);
Word = S9xDebugGetWord(Word);
Word += Registers.Y.W;
sprintf(Line, "%-32s[$%02X:%04X]", Line, Byte, Word);
Size = 2;
@ -670,7 +772,7 @@ static uint8 debug_cpu_op_print (char *Line, uint8 Bank, uint16 Address)
Operant[0]);
Word = Registers.S.W;
Word += Operant[0];
Word = S9xGetWord(Word);
Word = S9xDebugGetWord(Word);
Word += Registers.Y.W;
sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.DB, Word);
Size = 2;
@ -686,7 +788,7 @@ static uint8 debug_cpu_op_print (char *Line, uint8 Bank, uint16 Address)
Operant[1],
Operant[0]);
Word = (Operant[1] << 8) | Operant[0];
Word = S9xGetWord(Word);
Word = S9xDebugGetWord(Word);
sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.PB, Word);
Size = 3;
break;
@ -701,8 +803,8 @@ static uint8 debug_cpu_op_print (char *Line, uint8 Bank, uint16 Address)
Operant[1],
Operant[0]);
Word = (Operant[1] << 8) | Operant[0];
Byte = S9xGetByte(Word + 2);
Word = S9xGetWord(Word);
Byte = S9xDebugGetByte(Word + 2);
Word = S9xDebugGetWord(Word);
sprintf(Line, "%-32s[$%02X:%04X]", Line, Byte, Word);
Size = 3;
break;
@ -718,7 +820,7 @@ static uint8 debug_cpu_op_print (char *Line, uint8 Bank, uint16 Address)
Operant[0]);
Word = (Operant[1] << 8) | Operant[0];
Word += Registers.X.W;
Word = S9xGetWord(ICPU.ShiftedPB + Word);
Word = S9xDebugGetWord(ICPU.ShiftedPB + Word);
sprintf(Line, "%-32s[$%02X:%04X]", Line, Registers.PB, Word);
Size = 3;
break;
@ -764,7 +866,7 @@ static uint8 debug_cpu_op_print (char *Line, uint8 Bank, uint16 Address)
Operant[0]);
Word = Operant[0];
Word += Registers.D.W;
Word = S9xGetWord(Word);
Word = S9xDebugGetWord(Word);
sprintf(Line, "%-32s[$%04X]", Line, Word);
Size = 2;
break;
@ -782,14 +884,11 @@ static uint8 debug_cpu_op_print (char *Line, uint8 Bank, uint16 Address)
CheckIRQ() ? 'I' : 'i',
CheckZero() ? 'Z' : 'z',
CheckCarry() ? 'C' : 'c',
(long) Cycles,
(long) CPU.Cycles,
(long) CPU.V_Counter,
IPPU.FrameCount,
CPU.IRQActive);
CPU.Cycles = Cycles;
CPU.WaitAddress = WaitAddress;
return (Size);
}
@ -803,12 +902,12 @@ static uint8 debug_sa1_op_print (char *Line, uint8 Bank, uint16 Address)
int8 SByte;
uint8 Size = 0;
S9xOpcode = S9xSA1GetByte((Bank << 16) + Address);
S9xOpcode = S9xDebugSA1GetByte((Bank << 16) + Address);
sprintf(Line, "$%02X:%04X %02X ", Bank, Address, S9xOpcode);
Operant[0] = S9xSA1GetByte((Bank << 16) + Address + 1);
Operant[1] = S9xSA1GetByte((Bank << 16) + Address + 2);
Operant[2] = S9xSA1GetByte((Bank << 16) + Address + 3);
Operant[0] = S9xDebugSA1GetByte((Bank << 16) + Address + 1);
Operant[1] = S9xDebugSA1GetByte((Bank << 16) + Address + 2);
Operant[2] = S9xDebugSA1GetByte((Bank << 16) + Address + 3);
switch (AddrModes[S9xOpcode])
{
@ -966,7 +1065,7 @@ static uint8 debug_sa1_op_print (char *Line, uint8 Bank, uint16 Address)
Operant[0]);
Word = Operant[0];
Word += SA1Registers.D.W;
Word = S9xSA1GetWord(Word);
Word = S9xDebugSA1GetWord(Word);
sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.DB, Word);
Size = 2;
break;
@ -981,7 +1080,7 @@ static uint8 debug_sa1_op_print (char *Line, uint8 Bank, uint16 Address)
Word = Operant[0];
Word += SA1Registers.D.W;
Word += SA1Registers.X.W;
Word = S9xSA1GetWord(Word);
Word = S9xDebugSA1GetWord(Word);
sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.DB, Word);
Size = 2;
break;
@ -995,7 +1094,7 @@ static uint8 debug_sa1_op_print (char *Line, uint8 Bank, uint16 Address)
Operant[0]);
Word = Operant[0];
Word += SA1Registers.D.W;
Word = S9xSA1GetWord(Word);
Word = S9xDebugSA1GetWord(Word);
Word += SA1Registers.Y.W;
sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.DB, Word);
Size = 2;
@ -1010,8 +1109,8 @@ static uint8 debug_sa1_op_print (char *Line, uint8 Bank, uint16 Address)
Operant[0]);
Word = Operant[0];
Word += SA1Registers.D.W;
Byte = S9xSA1GetByte(Word + 2);
Word = S9xSA1GetWord(Word);
Byte = S9xDebugSA1GetByte(Word + 2);
Word = S9xDebugSA1GetWord(Word);
sprintf(Line, "%-32s[$%02X:%04X]", Line, Byte, Word);
Size = 2;
break;
@ -1025,8 +1124,8 @@ static uint8 debug_sa1_op_print (char *Line, uint8 Bank, uint16 Address)
Operant[0]);
Word = Operant[0];
Word += SA1Registers.D.W;
Byte = S9xSA1GetByte(Word + 2);
Word = S9xSA1GetWord(Word);
Byte = S9xDebugSA1GetByte(Word + 2);
Word = S9xDebugSA1GetWord(Word);
Word += SA1Registers.Y.W;
sprintf(Line, "%-32s[$%02X:%04X]", Line, Byte, Word);
Size = 2;
@ -1131,7 +1230,7 @@ static uint8 debug_sa1_op_print (char *Line, uint8 Bank, uint16 Address)
Operant[0]);
Word = SA1Registers.S.W;
Word += Operant[0];
Word = S9xSA1GetWord(Word);
Word = S9xDebugSA1GetWord(Word);
Word += SA1Registers.Y.W;
sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.DB, Word);
Size = 2;
@ -1147,7 +1246,7 @@ static uint8 debug_sa1_op_print (char *Line, uint8 Bank, uint16 Address)
Operant[1],
Operant[0]);
Word = (Operant[1] << 8) | Operant[0];
Word = S9xSA1GetWord(Word);
Word = S9xDebugSA1GetWord(Word);
sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.PB, Word);
Size = 3;
break;
@ -1162,8 +1261,8 @@ static uint8 debug_sa1_op_print (char *Line, uint8 Bank, uint16 Address)
Operant[1],
Operant[0]);
Word = (Operant[1] << 8) | Operant[0];
Byte = S9xSA1GetByte(Word + 2);
Word = S9xSA1GetWord(Word);
Byte = S9xDebugSA1GetByte(Word + 2);
Word = S9xDebugSA1GetWord(Word);
sprintf(Line, "%-32s[$%02X:%04X]", Line, Byte, Word);
Size = 3;
break;
@ -1179,7 +1278,7 @@ static uint8 debug_sa1_op_print (char *Line, uint8 Bank, uint16 Address)
Operant[0]);
Word = (Operant[1] << 8) | Operant[0];
Word += SA1Registers.X.W;
Word = S9xSA1GetWord(SA1.ShiftedPB + Word);
Word = S9xDebugSA1GetWord(SA1.ShiftedPB + Word);
sprintf(Line, "%-32s[$%02X:%04X]", Line, SA1Registers.PB, Word);
Size = 3;
break;
@ -1275,7 +1374,7 @@ static void debug_process_command (char *Line)
if (fs)
{
for (int i = 0; i < Count; i++)
putc(S9xGetByte(Address + i), fs);
putc(S9xDebugGetByte(Address + i), fs);
fclose(fs);
}
else
@ -1292,17 +1391,17 @@ static void debug_process_command (char *Line)
printf("Vectors:\n");
sprintf(string, " 8 Bit 16 Bit ");
debug_line_print(string);
sprintf(string, "ABT $00:%04X|$00:%04X", S9xGetWord(0xFFF8), S9xGetWord(0xFFE8));
sprintf(string, "ABT $00:%04X|$00:%04X", S9xDebugGetWord(0xFFF8), S9xDebugGetWord(0xFFE8));
debug_line_print(string);
sprintf(string, "BRK $00:%04X|$00:%04X", S9xGetWord(0xFFFE), S9xGetWord(0xFFE6));
sprintf(string, "BRK $00:%04X|$00:%04X", S9xDebugGetWord(0xFFFE), S9xDebugGetWord(0xFFE6));
debug_line_print(string);
sprintf(string, "COP $00:%04X|$00:%04X", S9xGetWord(0xFFF4), S9xGetWord(0xFFE4));
sprintf(string, "COP $00:%04X|$00:%04X", S9xDebugGetWord(0xFFF4), S9xDebugGetWord(0xFFE4));
debug_line_print(string);
sprintf(string, "IRQ $00:%04X|$00:%04X", S9xGetWord(0xFFFE), S9xGetWord(0xFFEE));
sprintf(string, "IRQ $00:%04X|$00:%04X", S9xDebugGetWord(0xFFFE), S9xDebugGetWord(0xFFEE));
debug_line_print(string);
sprintf(string, "NMI $00:%04X|$00:%04X", S9xGetWord(0xFFFA), S9xGetWord(0xFFEA));
sprintf(string, "NMI $00:%04X|$00:%04X", S9xDebugGetWord(0xFFFA), S9xDebugGetWord(0xFFEA));
debug_line_print(string);
sprintf(string, "RES $00:%04X", S9xGetWord(0xFFFC));
sprintf(string, "RES $00:%04X", S9xDebugGetWord(0xFFFC));
debug_line_print(string);
}
@ -1733,7 +1832,6 @@ static void debug_process_command (char *Line)
int CLine;
int CByte;
uint8 MemoryByte;
int32 Cycles = CPU.Cycles;
if (Debug.Dump.Bank != 0 || Debug.Dump.Address != 0)
{
@ -1756,7 +1854,7 @@ static void debug_process_command (char *Line)
Address + CByte == 0x4210)
MemoryByte = 0;
else
MemoryByte = S9xGetByte((Bank << 16) + Address + CByte);
MemoryByte = S9xDebugGetByte((Bank << 16) + Address + CByte);
sprintf(string, "%s %02X", string, MemoryByte);
}
@ -1772,7 +1870,7 @@ static void debug_process_command (char *Line)
Address + CByte == 0x4210)
MemoryByte = 0;
else
MemoryByte = S9xGetByte((Bank << 16) + Address + CByte);
MemoryByte = S9xDebugGetByte((Bank << 16) + Address + CByte);
if (MemoryByte < 32 || MemoryByte >= 127)
MemoryByte = '?';
@ -1787,8 +1885,6 @@ static void debug_process_command (char *Line)
Debug.Dump.Bank = Bank;
Debug.Dump.Address = Address;
CPU.Cycles = Cycles;
}
if (*Line == 'q')

110
dma.cpp
View File

@ -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);
}
}

View File

@ -291,11 +291,6 @@
<p>
Called once a complete SNES screen has been rendered into the <code>GFX.Screen</code> memory buffer, now is your chance to copy the SNES rendered screen to the host computer's screen memory. The problem is that you have to cope with different sized SNES rendered screens: 256*224, 256*239, 512*224, 512*239, 512*448 and 512*478.
</p>
<h3><code>bool8 S9xContinueUpdate (int width, int height)</code></h3>
<p>
Similar to <code>S9xDeinitUpdate</code>, but in interlace mode (512*448 or 512*478) only. Called once an even frame has been rendered into the <code>GFX.Screen</code> memory buffer.
</p>
<h3><code>void S9xMessage (int type, int number, const char *message)</code></h3>
<p>
When Snes9x wants to display an error, information or warning message, it calls this function. Check in <code>messages.h</code> for the types and individual message numbers that Snes9x currently passes as parameters.<br>
@ -384,7 +379,7 @@
The sound generation rate on a SNES is directly proportional to the video output rate. Displays that synchronize with the vertical refresh but have a slightly lower refresh-rate than the emulated system can experience sound drop-outs. It may be beneficial to provide an option for users to configure <code>Settings.SoundInputRate</code> to suit their own systems. Setting <code>Settings.SoundInputRate</code> to a value that matches the actual output rate (i.e. 31977hz for 59.96hz) or lower will allow the users to eliminate crackling. A range of 31000hz to 33000hz should be inclusive enough for all displays. Use of this setting paired with the <code>S9xSyncSound</code> function can eliminate sound discontinuity.
</p>
<div style="text-align:right; margin-top:3em">
Updated most recently by: 2010/01/09 zones
Updated most recently by: 2009/12/20 zones
</div>
</body>
</html>

View File

@ -371,7 +371,7 @@ struct FxRegs_s
uint32 vCounter;
uint32 vInstCount;
uint32 vSCBRDirty; // If SCBR is written, our cached screen pointers need updating
uint8 *avRegAddr; // To reference avReg in snapshot.cpp
};

335
getset.h
View File

@ -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)

14
gfx.cpp
View File

@ -2013,6 +2013,20 @@ static void DisplayStringFromBottom (const char *string, int linesFromBottom, in
static void DisplayFrameRate (void)
{
char string[10];
static uint32 lastFrameCount = 0, calcFps = 0;
static time_t lastTime = time(NULL);
time_t currTime = time(NULL);
if (lastTime != currTime) {
if (lastFrameCount < IPPU.TotalEmulatedFrames) {
calcFps = (IPPU.TotalEmulatedFrames - lastFrameCount) / (uint32)(currTime - lastTime);
}
lastTime = currTime;
lastFrameCount = IPPU.TotalEmulatedFrames;
}
sprintf(string, "%u fps", calcFps);
S9xDisplayString(string, 2, IPPU.RenderedScreenWidth - (font_width - 1) * strlen(string) - 1, false);
#ifdef DEBUGGER
const int len = 8;
sprintf(string, "%02d/%02d %02d", (int) IPPU.DisplayedRenderedFrameCount, (int) Memory.ROMFramesPerSecond, (int) IPPU.FrameCount);

View File

@ -20,37 +20,53 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#define __PORTABLE_H
#include <string.h>
#ifdef __GNUC__
#include <stdint.h>
typedef signed char INT8;
typedef unsigned char UINT8;
typedef short INT16;
typedef unsigned short UINT16;
typedef long INT32;
typedef unsigned long UINT32;
typedef int8_t INT8;
typedef uint8_t UINT8;
typedef int16_t INT16;
typedef uint16_t UINT16;
typedef int32_t INT32;
typedef uint32_t UINT32;
typedef int64_t INT64;
typedef uint64_t UINT64;
typedef uintptr_t UINT_PTR;
//Not correct, but should work for Snes9x
typedef int INT64;
typedef unsigned int UINT64;
//typedef long long INT64;
//typedef unsigned long long UINT64;
#else
typedef UINT8 BYTE;
typedef signed char INT8;
typedef unsigned char UINT8;
typedef short INT16;
typedef unsigned short UINT16;
typedef int INT32;
typedef unsigned int UINT32;
#ifdef _MSC_VER
typedef __int64 INT64;
typedef unsigned __int64 UINT64;
#else
typedef long long INT64;
typedef unsigned long long UINT64;
#endif
typedef unsigned UINT_PTR;
#endif
typedef UINT8 BYTE;
typedef UINT16 WORD;
typedef UINT32 DWORD;
typedef unsigned UINT_PTR;
typedef int BOOL;
#define FALSE 0
#define TRUE 1
#define TRUE 1
#define HRESULT int
#define S_OK 0
#define E_INVALIDARG -1
#define E_OUTOFMEMORY -2
#define E_FAIL -3
#define HRESULT int
#define S_OK 0
#define E_INVALIDARG -1
#define E_OUTOFMEMORY -2
#define E_FAIL -3
#define E_INTERNAL_ERROR -4
#define E_INVALIDDATA -5
#define E_INVALIDDATA -5
template <class T> inline T MyMin(T a, T b) {
return a < b ? a : b;
@ -63,24 +79,24 @@ template <class T> inline T MyMax(T a, T b) {
#define RETURN_IF_NOT_S_OK(x) { HRESULT __aResult_ = (x); if(__aResult_ != S_OK) return __aResult_; }
#define UINT_SIZE (4)
#define USHORT_SIZE (2)
#define UINT_SIZE ((int)sizeof(unsigned int))
#define USHORT_SIZE ((int)sizeof(unsigned short))
//Convert an array of 4 bytes back into an integer
inline unsigned int charp_to_uint(const unsigned char buffer[UINT_SIZE])
inline UINT32 charp_to_uint(const UINT8 buffer[UINT_SIZE])
{
unsigned int num = (unsigned int)buffer[3];
num |= ((unsigned int)buffer[2]) << 8;
num |= ((unsigned int)buffer[1]) << 16;
num |= ((unsigned int)buffer[0]) << 24;
UINT32 num = (UINT32)buffer[3];
num |= ((UINT32)buffer[2]) << 8;
num |= ((UINT32)buffer[1]) << 16;
num |= ((UINT32)buffer[0]) << 24;
return(num);
}
//Convert an array of 2 bytes back into a short integer
inline unsigned short charp_to_ushort(const unsigned char buffer[USHORT_SIZE])
inline UINT16 charp_to_ushort(const UINT8 buffer[USHORT_SIZE])
{
unsigned short num = (unsigned short)buffer[1];
num |= ((unsigned short)buffer[0]) << 8;
UINT16 num = (UINT16)buffer[1];
num |= ((UINT16)buffer[0]) << 8;
return(num);
}

View File

@ -64,8 +64,9 @@ public:
MoveBlockBackward();
BYTE *p = m_Buffer + m_Pos;
aDistance++;
BYTE *p2 = p - aDistance;
for(UINT32 i = 0; i < aLen; i++)
p[i] = p[i - aDistance];
p[i] = p2[i];
m_Pos += aLen;
}

View File

@ -2611,9 +2611,6 @@ void CMemory::InitROM (void)
Timings.NMIDMADelay = 24;
Timings.IRQPendCount = 0;
CPU.FastROMSpeed = 0;
ResetSpeedMap();
IPPU.TotalEmulatedFrames = 0;
//// Hack games
@ -2655,36 +2652,6 @@ void CMemory::InitROM (void)
S9xVerifyControllers();
}
void CMemory::FixROMSpeed (void)
{
if (CPU.FastROMSpeed == 0)
CPU.FastROMSpeed = SLOW_ONE_CYCLE;
// [80-bf]:[8000-ffff], [c0-ff]:[0000-ffff]
for (int c = 0x800; c < 0x1000; c++)
{
if (c & 0x8 || c & 0x400)
MemorySpeed[c] = (uint8) CPU.FastROMSpeed;
}
}
void CMemory::ResetSpeedMap (void)
{
memset(MemorySpeed, SLOW_ONE_CYCLE, 0x1000);
// Fast - [00-3f|80-bf]:[2000-3fff|4200-5fff]
// XSlow - [00-3f|80-bf]:[4000-41ff] see also S9xGet/SetCPU()
for (int i = 0; i < 0x400; i += 0x10)
{
MemorySpeed[i + 2] = MemorySpeed[0x800 + i + 2] = ONE_CYCLE;
MemorySpeed[i + 3] = MemorySpeed[0x800 + i + 3] = ONE_CYCLE;
MemorySpeed[i + 4] = MemorySpeed[0x800 + i + 4] = ONE_CYCLE;
MemorySpeed[i + 5] = MemorySpeed[0x800 + i + 5] = ONE_CYCLE;
}
FixROMSpeed();
}
// memory map
uint32 CMemory::map_mirror (uint32 size, uint32 pos)
@ -3596,37 +3563,6 @@ void CMemory::ApplyROMFixes (void)
Timings.HDMAStart = SNES_HDMA_START_HC + Settings.HDMATimingHack - 100;
Timings.HBlankStart = SNES_HBLANK_START_HC + Timings.HDMAStart - SNES_HDMA_START_HC;
if (!Settings.DisableGameSpecificHacks)
{
// The HC counter (CPU.Cycles for snes9x) passes over the WRAM refresh point (HC~536)
// while preparing to jump to the IRQ vector address.
// That is to say, the WRAM refresh point is passed over in S9xOpcode_IRQ().
// Then, HDMA starts just after $210e is half updated, and it causes the flicker of the ground.
// IRQ timing is bad? HDMA timing is bad? else?
if (match_na("GUNDAMW ENDLESSDUEL")) // Shin Kidou Senki Gundam W - Endless Duel
{
Timings.HDMAStart -= 10;
Timings.HBlankStart -= 10;
printf("HDMA timing hack: %d\n", Timings.HDMAStart);
}
// Due to Snes9x's very inaccurate timings,
// HDMA transfer to $210D-$2114 between the first and second writings to the same addresses.
if (match_na("POWER RANGERS FIGHT")) // Mighty Morphin Power Rangers - The Fighting Edition
{
Timings.HDMAStart -= 10;
Timings.HBlankStart -= 10;
printf("HDMA timing hack: %d\n", Timings.HDMAStart);
}
if (match_na("SFX SUPERBUTOUDEN2")) // Dragon Ball Z - Super Butouden 2
{
Timings.HDMAStart += 20;
Timings.HBlankStart += 20;
printf("HDMA timing hack: %d\n", Timings.HDMAStart);
}
}
if (!Settings.DisableGameSpecificHacks)
{
// The delay to sync CPU and DMA which Snes9x cannot emulate.
@ -3657,6 +3593,12 @@ void CMemory::ApplyROMFixes (void)
Timings.IRQPendCount = 2;
printf("IRQ count hack: %d\n", Timings.IRQPendCount);
}
if (match_na("BATTLE BLAZE"))
{
Timings.IRQPendCount = 1;
printf("IRQ count hack: %d\n", Timings.IRQPendCount);
}
}
if (!Settings.DisableGameSpecificHacks)

View File

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

View File

@ -194,7 +194,7 @@
#include "win32/wsnes9x.h"
#define ioctl ioctlsocket
#define close closesocket
#define close(h) if(h){closesocket(h);}
#define read(a,b,c) recv(a, b, c, 0)
#define write(a,b,c) send(a, b, c, 0)
#else

8
port.h
View File

@ -224,11 +224,15 @@ typedef uint32_t uint32;
typedef int64_t int64;
typedef uint64_t uint64;
#else // HAVE_STDINT_H
#ifdef __WIN32__
typedef intptr_t pint;
#else // __WIN32__
#ifdef PTR_NOT_INT
typedef long pint;
#else
typedef int pint;
#endif
#endif // __WIN32__
#ifdef __WIN32__
#ifdef __BORLANDC__
#include <systypes.h>
@ -300,6 +304,8 @@ void _makepath (char *, const char *, const char *, const char *, const char *);
#define strncasecmp strnicmp
void WinDisplayStringFromBottom(const char *string, int linesFromBottom, int pixelsFromLeft, bool allowWrap);
#define S9xDisplayString WinDisplayStringFromBottom
void SetInfoDlgColor(unsigned char, unsigned char, unsigned char);
#define SET_UI_COLOR(r,g,b) SetInfoDlgColor(r,g,b)
#endif
#ifdef __DJGPP
@ -323,7 +329,7 @@ void WinDisplayStringFromBottom(const char *string, int linesFromBottom, int pix
#define TITLE "Snes9x"
#endif
#if defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(__x86_64__) || defined(__alpha__) || defined(__MIPSEL__) || defined(_M_IX86)
#if defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(__x86_64__) || defined(__alpha__) || defined(__MIPSEL__) || defined(_M_IX86) || defined(_M_X64)
#define LSB_FIRST
#define FAST_LSB_WORD_ACCESS
#else

View File

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

30
sa1.cpp
View File

@ -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:

View File

@ -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);
}

View File

@ -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];

View File

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