mirror of
https://github.com/dborth/snes9xgx.git
synced 2024-12-17 23:01:51 +01:00
Fixes from Snes9x 1.51+
- Fixed invalid memory accesses in C4 and OBC1. MMX3 Toxic Seahorse stage now can be emulated with HDMA. (zones) - Updated snapshot to prevent desync. Added some variables related to APU and HDMA. (gocha)
This commit is contained in:
parent
2fc796d4b1
commit
adf61aef32
@ -255,8 +255,8 @@ void S9xResetAPU ()
|
||||
IAPU.WaitAddress2 = NULL;
|
||||
IAPU.WaitCounter = 0;
|
||||
#endif
|
||||
IAPU.NextAPUTimerPos = 0;
|
||||
IAPU.APUTimerCounter = 0;
|
||||
APU.NextAPUTimerPos = 0;
|
||||
APU.APUTimerCounter = 0;
|
||||
APU.ShowROM = TRUE;
|
||||
IAPU.RAM [0xf1] = 0x80;
|
||||
|
||||
@ -283,6 +283,9 @@ void S9xResetAPU ()
|
||||
|
||||
S9xResetSound (TRUE);
|
||||
S9xSetEchoEnable (0);
|
||||
|
||||
IAPU.OUTXNotifier = false;
|
||||
IAPU.ENVXNotifier = false;
|
||||
}
|
||||
|
||||
void S9xSetAPUDSP (uint8 byte)
|
||||
@ -913,18 +916,18 @@ void S9xSetAPUTimer (uint16 Address, uint8 byte)
|
||||
|
||||
void S9xAPUExecute (void)
|
||||
{
|
||||
while ((CPU.Cycles << SNES_APU_ACCURACY) >= IAPU.NextAPUTimerPos)
|
||||
while ((CPU.Cycles << SNES_APU_ACCURACY) >= APU.NextAPUTimerPos)
|
||||
{
|
||||
// catch up the APU timers
|
||||
if (IAPU.APUExecuting)
|
||||
{
|
||||
while (APU.Cycles < IAPU.NextAPUTimerPos)
|
||||
while (APU.Cycles < APU.NextAPUTimerPos)
|
||||
APU_EXECUTE1();
|
||||
}
|
||||
else
|
||||
APU.Cycles = IAPU.NextAPUTimerPos;
|
||||
APU.Cycles = APU.NextAPUTimerPos;
|
||||
|
||||
IAPU.NextAPUTimerPos += SNES_APUTIMER2_CYCLE_SCALED;
|
||||
APU.NextAPUTimerPos += SNES_APUTIMER2_CYCLE_SCALED;
|
||||
|
||||
if (APU.TimerEnabled [2])
|
||||
{
|
||||
@ -940,9 +943,9 @@ void S9xAPUExecute (void)
|
||||
}
|
||||
}
|
||||
|
||||
if (++IAPU.APUTimerCounter == 8)
|
||||
if (++APU.APUTimerCounter == 8)
|
||||
{
|
||||
IAPU.APUTimerCounter = 0;
|
||||
APU.APUTimerCounter = 0;
|
||||
|
||||
if (APU.TimerEnabled [0])
|
||||
{
|
||||
@ -992,8 +995,10 @@ uint8 S9xGetAPUDSP ()
|
||||
switch (reg)
|
||||
{
|
||||
case APU_KON:
|
||||
IAPU.KONNotifier = true;
|
||||
break;
|
||||
case APU_KOFF:
|
||||
IAPU.KOFFNotifier = true;
|
||||
break;
|
||||
|
||||
case APU_OUTX + 0x00:
|
||||
@ -1004,6 +1009,9 @@ uint8 S9xGetAPUDSP ()
|
||||
case APU_OUTX + 0x50:
|
||||
case APU_OUTX + 0x60:
|
||||
case APU_OUTX + 0x70:
|
||||
{
|
||||
IAPU.OUTXNotifier = true;
|
||||
|
||||
if(Settings.FakeMuteFix)
|
||||
{
|
||||
// hack that is off by default: fixes Terranigma desync
|
||||
@ -1015,6 +1023,7 @@ uint8 S9xGetAPUDSP ()
|
||||
return (0);
|
||||
return (int8) (SoundData.channels [reg >> 4].out_sample >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
case APU_ENVX + 0x00:
|
||||
case APU_ENVX + 0x10:
|
||||
@ -1024,9 +1033,14 @@ uint8 S9xGetAPUDSP ()
|
||||
case APU_ENVX + 0x50:
|
||||
case APU_ENVX + 0x60:
|
||||
case APU_ENVX + 0x70:
|
||||
{
|
||||
IAPU.ENVXNotifier = true;
|
||||
|
||||
return (S9xGetEnvelopeHeight (reg >> 4));
|
||||
}
|
||||
|
||||
case APU_ENDX:
|
||||
IAPU.ENDXNotifier = true;
|
||||
// To fix speech in Magical Drop 2 6/11/00
|
||||
// APU.DSP [APU_ENDX] = 0;
|
||||
break;
|
||||
|
@ -183,11 +183,14 @@ struct SIAPU
|
||||
uint8 _Zero;
|
||||
uint8 _Overflow;
|
||||
uint32 TimerErrorCounter;
|
||||
int32 NextAPUTimerPos;
|
||||
int32 APUTimerCounter;
|
||||
uint32 Scanline;
|
||||
int32 OneCycle;
|
||||
int32 TwoCycles;
|
||||
bool8 KONNotifier;
|
||||
bool8 KOFFNotifier;
|
||||
bool8 OUTXNotifier;
|
||||
bool8 ENVXNotifier;
|
||||
bool8 ENDXNotifier;
|
||||
};
|
||||
|
||||
struct SAPU
|
||||
@ -204,6 +207,8 @@ struct SAPU
|
||||
bool8 TimerEnabled [3];
|
||||
bool8 TimerValueWritten [3];
|
||||
int32 Cycles;
|
||||
int32 NextAPUTimerPos;
|
||||
int32 APUTimerCounter;
|
||||
};
|
||||
|
||||
EXTERN_C struct SAPU APU;
|
||||
|
@ -308,13 +308,18 @@ EXTERN_C void C4LoaDMem(char *C4RAM)
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8 *S9xGetBasePointerC4 (uint16 Address)
|
||||
uint8 * S9xGetBasePointerC4 (uint16 Address)
|
||||
{
|
||||
if((Address&~MEMMAP_MASK)>=(0x7f40&~MEMMAP_MASK) &&
|
||||
(Address&~MEMMAP_MASK)<=(0x7f5e&~MEMMAP_MASK)){
|
||||
return NULL;
|
||||
}
|
||||
return Memory.C4RAM-0x6000;
|
||||
if (Address >= 0x7f40 && Address <= 0x7f5e)
|
||||
return (NULL);
|
||||
return (Memory.C4RAM - 0x6000);
|
||||
}
|
||||
|
||||
uint8 * S9xGetMemPointerC4 (uint16 Address)
|
||||
{
|
||||
if (Address >= 0x7f40 && Address <= 0x7f5e)
|
||||
return (NULL);
|
||||
return (Memory.C4RAM - 0x6000 + (Address & 0xffff));
|
||||
}
|
||||
|
||||
}//end extern C
|
||||
|
@ -372,13 +372,13 @@ void S9xDoHEventProcessing (void)
|
||||
break;
|
||||
|
||||
case HC_HDMA_START_EVENT:
|
||||
if (IPPU.HDMA && CPU.V_Counter <= PPU.ScreenHeight)
|
||||
if (PPU.HDMA && CPU.V_Counter <= PPU.ScreenHeight)
|
||||
{
|
||||
#ifdef DEBUGGER
|
||||
sprintf(mes, "*** HDMA HC:%04d, Channel:%02x", CPU.Cycles, IPPU.HDMA);
|
||||
sprintf(mes, "*** HDMA HC:%04d, Channel:%02x", CPU.Cycles, PPU.HDMA);
|
||||
S9xTraceMessage(mes);
|
||||
#endif
|
||||
IPPU.HDMA = S9xDoHDMA(IPPU.HDMA);
|
||||
PPU.HDMA = S9xDoHDMA(PPU.HDMA);
|
||||
}
|
||||
|
||||
S9xCheckMissingHTimerPosition(Timings.HDMAStart);
|
||||
@ -403,7 +403,7 @@ void S9xDoHEventProcessing (void)
|
||||
#endif
|
||||
|
||||
CPU.Cycles -= Timings.H_Max;
|
||||
IAPU.NextAPUTimerPos -= (Timings.H_Max << SNES_APU_ACCURACY);
|
||||
APU.NextAPUTimerPos -= (Timings.H_Max << SNES_APU_ACCURACY);
|
||||
APU.Cycles -= (Timings.H_Max << SNES_APU_ACCURACY);
|
||||
|
||||
if ((Timings.NMITriggerPos != 0xffff) && (Timings.NMITriggerPos >= Timings.H_Max))
|
||||
@ -471,7 +471,7 @@ void S9xDoHEventProcessing (void)
|
||||
if (CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE) // VBlank starts from V=225(240).
|
||||
{
|
||||
S9xEndScreenRefresh();
|
||||
IPPU.HDMA = 0;
|
||||
PPU.HDMA = 0;
|
||||
// Bits 7 and 6 of $4212 are computed when read in S9xGetPPU.
|
||||
#ifdef DEBUGGER
|
||||
missing.dma_this_frame = 0;
|
||||
|
@ -1403,7 +1403,7 @@ static inline bool8 HDMAReadLineCount(int d){
|
||||
DMA[d].Repeat = FALSE;
|
||||
DMA[d].LineCount = 128;
|
||||
if(DMA[d].HDMAIndirectAddressing){
|
||||
if(IPPU.HDMA&(0xfe<<d)){
|
||||
if(PPU.HDMA&(0xfe<<d)){
|
||||
DMA[d].Address++;
|
||||
CPU.Cycles+=SLOW_ONE_CYCLE*2;
|
||||
} else {
|
||||
@ -1439,26 +1439,26 @@ static inline bool8 HDMAReadLineCount(int d){
|
||||
|
||||
void S9xStartHDMA () {
|
||||
if (Settings.DisableHDMA)
|
||||
IPPU.HDMA = 0;
|
||||
PPU.HDMA = 0;
|
||||
else
|
||||
missing.hdma_this_frame = IPPU.HDMA = Memory.FillRAM [0x420c];
|
||||
missing.hdma_this_frame = PPU.HDMA = Memory.FillRAM [0x420c];
|
||||
|
||||
IPPU.HDMAEnded = 0;
|
||||
PPU.HDMAEnded = 0;
|
||||
|
||||
CPU.InHDMA = TRUE;
|
||||
CPU.InDMAorHDMA = TRUE;
|
||||
|
||||
// XXX: Not quite right...
|
||||
if (IPPU.HDMA != 0) CPU.Cycles += Timings.DMACPUSync;
|
||||
if (PPU.HDMA != 0) CPU.Cycles += Timings.DMACPUSync;
|
||||
|
||||
for (uint8 i = 0; i < 8; i++)
|
||||
{
|
||||
if (IPPU.HDMA & (1 << i))
|
||||
if (PPU.HDMA & (1 << i))
|
||||
{
|
||||
DMA [i].Address = DMA[i].AAddress;
|
||||
if (!HDMAReadLineCount(i)) {
|
||||
IPPU.HDMA &= ~(1<<i);
|
||||
IPPU.HDMAEnded |= (1<<i);
|
||||
PPU.HDMA &= ~(1<<i);
|
||||
PPU.HDMAEnded |= (1<<i);
|
||||
}
|
||||
} else {
|
||||
DMA[i].DoTransfer = FALSE;
|
||||
@ -1469,7 +1469,7 @@ void S9xStartHDMA () {
|
||||
|
||||
CPU.InHDMA = FALSE;
|
||||
CPU.InDMAorHDMA = CPU.InDMA;
|
||||
CPU.HDMARanInDMA = CPU.InDMA ? IPPU.HDMA : 0;
|
||||
CPU.HDMARanInDMA = CPU.InDMA ? PPU.HDMA : 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUGGER
|
||||
@ -1734,7 +1734,7 @@ uint8 S9xDoHDMA (uint8 byte)
|
||||
if (!--p->LineCount) {
|
||||
if (!HDMAReadLineCount(d)) {
|
||||
byte &= ~mask;
|
||||
IPPU.HDMAEnded |= mask;
|
||||
PPU.HDMAEnded |= mask;
|
||||
p->DoTransfer = FALSE;
|
||||
continue;
|
||||
}
|
||||
|
@ -792,10 +792,10 @@ INLINE uint8 *GetBasePointer (uint32 Address)
|
||||
return (Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask) - (Address&0xffff));
|
||||
|
||||
case CMemory::MAP_C4:
|
||||
return S9xGetBasePointerC4(Address);
|
||||
return (S9xGetBasePointerC4(Address & 0xffff));
|
||||
|
||||
case CMemory::MAP_OBC_RAM:
|
||||
return GetBasePointerOBC1(Address);
|
||||
return (S9xGetBasePointerOBC1(Address & 0xffff));
|
||||
|
||||
case CMemory::MAP_DEBUG:
|
||||
#ifdef DEBUGGER
|
||||
@ -848,10 +848,10 @@ INLINE uint8 *S9xGetMemPointer (uint32 Address)
|
||||
return (Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask));
|
||||
|
||||
case CMemory::MAP_C4:
|
||||
return S9xGetBasePointerC4(Address) + (Address&0xffff);
|
||||
return (S9xGetMemPointerC4(Address & 0xffff));
|
||||
|
||||
case CMemory::MAP_OBC_RAM:
|
||||
return GetMemPointerOBC1(Address);
|
||||
return (S9xGetMemPointerOBC1(Address & 0xffff));
|
||||
|
||||
case CMemory::MAP_DEBUG:
|
||||
#ifdef DEBUGGER
|
||||
@ -930,11 +930,11 @@ INLINE void S9xSetPCBase (uint32 Address)
|
||||
return;
|
||||
|
||||
case CMemory::MAP_C4:
|
||||
CPU.PCBase = S9xGetBasePointerC4(Address);
|
||||
CPU.PCBase = S9xGetBasePointerC4(Address & 0xffff);
|
||||
return;
|
||||
|
||||
case CMemory::MAP_OBC_RAM:
|
||||
CPU.PCBase = GetBasePointerOBC1(Address);
|
||||
CPU.PCBase = S9xGetBasePointerOBC1(Address & 0xffff);
|
||||
return;
|
||||
|
||||
case CMemory::MAP_BSX:
|
||||
|
@ -382,7 +382,6 @@ void S9xStartScreenRefresh(){
|
||||
IPPU.RenderedFramesCount = 0;
|
||||
IPPU.FrameCount = 0;
|
||||
}
|
||||
++IPPU.TotalEmulatedFrames;
|
||||
}
|
||||
|
||||
void RenderLine(uint8 C) {
|
||||
@ -530,6 +529,7 @@ void S9xEndScreenRefresh() {
|
||||
}
|
||||
}
|
||||
}
|
||||
++IPPU.TotalEmulatedFrames;
|
||||
}
|
||||
|
||||
|
||||
|
@ -331,7 +331,7 @@ inline uint16 COLOR_SUB(uint16, uint16);
|
||||
|
||||
inline uint16 COLOR_SUB(uint16 C1, uint16 C2)
|
||||
{
|
||||
uint16 mC1, mC2, v = 0;
|
||||
uint16 mC1, mC2, v = ALPHA_BITS_MASK;
|
||||
|
||||
mC1 = C1 & FIRST_COLOR_MASK;
|
||||
mC2 = C2 & FIRST_COLOR_MASK;
|
||||
|
@ -173,9 +173,7 @@
|
||||
#include "fxemu.h"
|
||||
#include "gfx.h"
|
||||
#include "soundux.h"
|
||||
|
||||
#include "cheats.h"
|
||||
|
||||
#include "sa1.h"
|
||||
#include "bsx.h"
|
||||
#include "spc7110.h"
|
||||
@ -204,8 +202,6 @@ struct SAPURegisters APURegisters;
|
||||
|
||||
struct SSettings Settings;
|
||||
|
||||
struct SDSP1 DSP1;
|
||||
|
||||
struct SSA1Registers SA1Registers;
|
||||
|
||||
struct SSA1 SA1;
|
||||
@ -216,10 +212,6 @@ struct SMulti Multi;
|
||||
|
||||
SSoundData SoundData;
|
||||
|
||||
SnesModel M1SNES={1,3,2};
|
||||
SnesModel M2SNES={2,4,3};
|
||||
SnesModel* Model=&M1SNES;
|
||||
|
||||
#if defined(ZSNES_FX) || defined(ZSNES_C4)
|
||||
uint8 *ROM = NULL;
|
||||
uint8 *SRAM = NULL;
|
||||
@ -235,6 +227,12 @@ unsigned char OpenBus = 0;
|
||||
|
||||
END_EXTERN_C
|
||||
|
||||
struct SDSP1 DSP1;
|
||||
|
||||
SnesModel M1SNES={1,3,2};
|
||||
SnesModel M2SNES={2,4,3};
|
||||
SnesModel* Model=&M1SNES;
|
||||
|
||||
#ifndef ZSNES_FX
|
||||
struct FxInit_s SuperFX;
|
||||
#else
|
||||
@ -292,7 +290,6 @@ uint32 current_graphic_format = RGB565;
|
||||
#endif
|
||||
|
||||
uint8 GetBank = 0;
|
||||
|
||||
struct SCheatData Cheat;
|
||||
|
||||
volatile SoundStatus so;
|
||||
|
@ -1996,25 +1996,6 @@ void CMemory::InitROM (void)
|
||||
else
|
||||
Settings.PAL = FALSE;
|
||||
|
||||
|
||||
//// Initialize emulation
|
||||
|
||||
Timings.H_Max_Master = SNES_CYCLES_PER_SCANLINE;
|
||||
Timings.H_Max = Timings.H_Max_Master;
|
||||
Timings.HBlankStart = SNES_HBLANK_START_HC;
|
||||
Timings.HBlankEnd = SNES_HBLANK_END_HC;
|
||||
Timings.HDMAInit = SNES_HDMA_INIT_HC;
|
||||
Timings.HDMAStart = SNES_HDMA_START_HC;
|
||||
Timings.RenderPos = SNES_RENDER_START_HC;
|
||||
Timings.V_Max_Master = Settings.PAL ? SNES_MAX_PAL_VCOUNTER : SNES_MAX_NTSC_VCOUNTER;
|
||||
Timings.V_Max = Timings.V_Max_Master;
|
||||
/* From byuu: The total delay time for both the initial (H)DMA sync (to the DMA clock),
|
||||
and the end (H)DMA sync (back to the last CPU cycle's mcycle rate (6, 8, or 12)) always takes between 12-24 mcycles.
|
||||
Possible delays: { 12, 14, 16, 18, 20, 22, 24 }
|
||||
XXX: Snes9x can't emulate this timing :( so let's use the average value... */
|
||||
Timings.DMACPUSync = 18;
|
||||
|
||||
|
||||
if (Settings.PAL)
|
||||
{
|
||||
Settings.FrameTime = Settings.FrameTimePAL;
|
||||
@ -2057,6 +2038,23 @@ void CMemory::InitROM (void)
|
||||
SET_UI_COLOR(0, 128, 255);
|
||||
}
|
||||
|
||||
//// Initialize emulation
|
||||
|
||||
Timings.H_Max_Master = SNES_CYCLES_PER_SCANLINE;
|
||||
Timings.H_Max = Timings.H_Max_Master;
|
||||
Timings.HBlankStart = SNES_HBLANK_START_HC;
|
||||
Timings.HBlankEnd = SNES_HBLANK_END_HC;
|
||||
Timings.HDMAInit = SNES_HDMA_INIT_HC;
|
||||
Timings.HDMAStart = SNES_HDMA_START_HC;
|
||||
Timings.RenderPos = SNES_RENDER_START_HC;
|
||||
Timings.V_Max_Master = Settings.PAL ? SNES_MAX_PAL_VCOUNTER : SNES_MAX_NTSC_VCOUNTER;
|
||||
Timings.V_Max = Timings.V_Max_Master;
|
||||
/* From byuu: The total delay time for both the initial (H)DMA sync (to the DMA clock),
|
||||
and the end (H)DMA sync (back to the last CPU cycle's mcycle rate (6, 8, or 12)) always takes between 12-24 mcycles.
|
||||
Possible delays: { 12, 14, 16, 18, 20, 22, 24 }
|
||||
XXX: Snes9x can't emulate this timing :( so let's use the average value... */
|
||||
Timings.DMACPUSync = 18;
|
||||
|
||||
IAPU.OneCycle = SNES_APU_ONE_CYCLE_SCALED;
|
||||
|
||||
CPU.FastROMSpeed = 0;
|
||||
|
@ -252,20 +252,18 @@ void SetOBC1 (uint8 Byte, uint16 Address)
|
||||
OBC1_RAM[Address & 0x1fff] = Byte;
|
||||
}
|
||||
|
||||
uint8 *GetBasePointerOBC1(uint32 Address)
|
||||
uint8 * S9xGetBasePointerOBC1 (uint16 Address)
|
||||
{
|
||||
Address=Address&0xffff;
|
||||
if((Address&~MEMMAP_MASK)>=(0x7ff0&~MEMMAP_MASK) &&
|
||||
(Address&~MEMMAP_MASK)<=(0x7ff6&~MEMMAP_MASK)) return NULL;
|
||||
return OBC1_RAM + (Address & 0x1fff);
|
||||
if (Address >= 0x7ff0 && Address <= 0x7ff6)
|
||||
return (NULL);
|
||||
return (OBC1_RAM - 0x6000);
|
||||
}
|
||||
|
||||
uint8 *GetMemPointerOBC1(uint32 Address)
|
||||
uint8 * S9xGetMemPointerOBC1 (uint16 Address)
|
||||
{
|
||||
Address=Address&0xffff;
|
||||
if((Address&~MEMMAP_MASK)>=(0x7ff0&~MEMMAP_MASK) &&
|
||||
(Address&~MEMMAP_MASK)<=(0x7ff6&~MEMMAP_MASK)) return NULL;
|
||||
return OBC1_RAM + (Address & 0x1fff);
|
||||
if (Address >= 0x7ff0 && Address <= 0x7ff6)
|
||||
return (NULL);
|
||||
return (OBC1_RAM - 0x6000 + (Address & 0xffff));
|
||||
}
|
||||
|
||||
void ResetOBC1()
|
||||
|
@ -167,8 +167,8 @@
|
||||
START_EXTERN_C
|
||||
uint8 GetOBC1 (uint16 Address);
|
||||
void SetOBC1 (uint8 Byte, uint16 Address);
|
||||
uint8 *GetBasePointerOBC1(uint32 Address);
|
||||
uint8 *GetMemPointerOBC1(uint32 Address);
|
||||
uint8 * S9xGetBasePointerOBC1 (uint16);
|
||||
uint8 * S9xGetMemPointerOBC1 (uint16);
|
||||
void ResetOBC1();//bool8 full);
|
||||
END_EXTERN_C
|
||||
|
||||
|
@ -261,8 +261,6 @@ typedef unsigned long long uint64;
|
||||
# include <systypes.h>
|
||||
# else
|
||||
|
||||
#define SNES_JOY_READ_CALLBACKS
|
||||
|
||||
typedef unsigned char uint8;
|
||||
typedef unsigned short uint16;
|
||||
typedef signed char int8;
|
||||
@ -276,6 +274,16 @@ typedef long int32;
|
||||
# define RIGHTSHIFT_IS_SAR
|
||||
# endif
|
||||
|
||||
# if defined(_MSC_VER) && (_MSC_VER == 1400) /* VC8.0 */
|
||||
/* temporary solution for fatal error C1063 (cl.exe 14.00.50727.762) */
|
||||
# ifdef RIGHTSHIFT_IS_SAR
|
||||
# undef RIGHTSHIFT_IS_SAR
|
||||
# endif /* RIGHTSHIFT_IS_SAR */
|
||||
# define RIGHTSHIFT_INT8_IS_SAR
|
||||
# define RIGHTSHIFT_INT16_IS_SAR
|
||||
# define RIGHTSHIFT_INT32_IS_SAR
|
||||
# endif /* VC8.0 */
|
||||
|
||||
typedef unsigned int uint32;
|
||||
|
||||
# endif /* __BORLANDC__ */
|
||||
@ -335,9 +343,15 @@ void _splitpath (const char *path, char *drive, char *dir, char *fname,
|
||||
#else /* __WIN32__ */
|
||||
#define strcasecmp stricmp
|
||||
#define strncasecmp strnicmp
|
||||
|
||||
#define SNES_JOY_READ_CALLBACKS
|
||||
|
||||
#endif
|
||||
|
||||
EXTERN_C void S9xGenerateSound ();
|
||||
#ifdef __WIN32__
|
||||
EXTERN_C void S9xGenerateFrameSound ();
|
||||
#endif
|
||||
|
||||
#ifdef STORM
|
||||
EXTERN_C int soundsignal;
|
||||
|
@ -2088,10 +2088,10 @@ void S9xSetCPU (uint8 byte, uint16 Address)
|
||||
if (Settings.DisableHDMA)
|
||||
byte = 0;
|
||||
Memory.FillRAM[0x420c] = byte;
|
||||
//printf("$%02x is written to $420c at HC:%d, V:%d, IPPU.HDMA:$%02x, IPPU.HDMAEnded:$%02x\n", byte, CPU.Cycles, CPU.V_Counter, IPPU.HDMA, IPPU.HDMAEnded);
|
||||
//printf("$%02x is written to $420c at HC:%d, V:%d, PPU.HDMA:$%02x, PPU.HDMAEnded:$%02x\n", byte, CPU.Cycles, CPU.V_Counter, PPU.HDMA, PPU.HDMAEnded);
|
||||
// FIXME
|
||||
// Yoshi's Island / Genjyu Ryodan, Mortal Kombat, Tales of Phantasia
|
||||
IPPU.HDMA = byte&~IPPU.HDMAEnded;
|
||||
PPU.HDMA = byte&~PPU.HDMAEnded;
|
||||
break;
|
||||
|
||||
case 0x420d:
|
||||
@ -2306,7 +2306,7 @@ void S9xSetCPU (uint8 byte, uint16 Address)
|
||||
DMA[d].LineCount = 128;
|
||||
DMA[d].Repeat = !!(byte & 0x80);
|
||||
}
|
||||
//printf("$%02x is written to $43%da at HC:%d, V:%d, IPPU.HDMA:$%02x, IPPU.HDMAEnded:$%02x\n", byte, d, CPU.Cycles, CPU.V_Counter, IPPU.HDMA, IPPU.HDMAEnded);
|
||||
//printf("$%02x is written to $43%da at HC:%d, V:%d, PPU.HDMA:$%02x, PPU.HDMAEnded:$%02x\n", byte, d, CPU.Cycles, CPU.V_Counter, PPU.HDMA, PPU.HDMAEnded);
|
||||
return;
|
||||
|
||||
case 0x430B:
|
||||
@ -2422,11 +2422,14 @@ uint8 S9xGetCPU (uint16 Address)
|
||||
|
||||
if (Address < 0x4200)
|
||||
{
|
||||
#ifdef SNES_JOY_READ_CALLBACKS
|
||||
extern bool8 pad_read;
|
||||
if(Address==0x4016 || Address==0x4017)
|
||||
S9xOnSNESPadRead(), pad_read = true;
|
||||
{
|
||||
extern bool8 pad_read;
|
||||
#ifdef SNES_JOY_READ_CALLBACKS
|
||||
S9xOnSNESPadRead();
|
||||
#endif
|
||||
pad_read = true;
|
||||
}
|
||||
|
||||
CPU.Cycles += ONE_CYCLE;
|
||||
switch (Address)
|
||||
@ -2516,13 +2519,14 @@ uint8 S9xGetCPU (uint16 Address)
|
||||
case 0x421d:
|
||||
case 0x421e:
|
||||
case 0x421f:
|
||||
#ifdef SNES_JOY_READ_CALLBACKS
|
||||
if(Memory.FillRAM[0x4200] & 1)
|
||||
{
|
||||
extern bool8 pad_read;
|
||||
if(Memory.FillRAM[0x4200] & 1)
|
||||
S9xOnSNESPadRead(), pad_read = true;
|
||||
}
|
||||
#ifdef SNES_JOY_READ_CALLBACKS
|
||||
S9xOnSNESPadRead();
|
||||
#endif
|
||||
pad_read = true;
|
||||
}
|
||||
// Joypads 1-4 button and direction state.
|
||||
return (Memory.FillRAM [Address]);
|
||||
|
||||
@ -2824,8 +2828,8 @@ void S9xSoftResetPPU ()
|
||||
PPU.Need16x8Mulitply = FALSE;
|
||||
|
||||
IPPU.ColorsChanged = TRUE;
|
||||
IPPU.HDMA = 0;
|
||||
IPPU.HDMAEnded = 0;
|
||||
PPU.HDMA = 0;
|
||||
PPU.HDMAEnded = 0;
|
||||
IPPU.MaxBrightness = 0;
|
||||
IPPU.LatchedBlanking = 0;
|
||||
IPPU.OBJChanged = TRUE;
|
||||
|
@ -196,8 +196,6 @@ struct ClipData {
|
||||
|
||||
struct InternalPPU {
|
||||
bool8 ColorsChanged;
|
||||
uint8 HDMA;
|
||||
uint8 HDMAEnded;
|
||||
uint8 MaxBrightness;
|
||||
bool8 LatchedBlanking;
|
||||
bool8 OBJChanged;
|
||||
@ -344,6 +342,9 @@ struct SPPU {
|
||||
uint16 GunVLatch;
|
||||
uint16 GunHLatch;
|
||||
short VTimerPosition;
|
||||
|
||||
uint8 HDMA;
|
||||
uint8 HDMAEnded;
|
||||
};
|
||||
|
||||
#define CLIP_OR 0
|
||||
@ -407,7 +408,8 @@ void S9xSetC4 (uint8 Byte, uint16 Address);
|
||||
uint8 S9xGetC4 (uint16 Address);
|
||||
void S9xSetC4RAM (uint8 Byte, uint16 Address);
|
||||
uint8 S9xGetC4RAM (uint16 Address);
|
||||
uint8 *S9xGetBasePointerC4 (uint16 Address);
|
||||
uint8 * S9xGetBasePointerC4 (uint16);
|
||||
uint8 * S9xGetMemPointerC4 (uint16);
|
||||
|
||||
void S9xUpdateHVTimerPosition (void);
|
||||
void S9xCheckMissingHTimerPosition (int32);
|
||||
|
@ -499,6 +499,9 @@ static FreezeData SnapPPU [] = {
|
||||
INT_ENTRY(3, GunVLatch),
|
||||
INT_ENTRY(3, GunHLatch),
|
||||
INT_ENTRY(2, VTimerPosition),
|
||||
|
||||
INT_ENTRY(5, HDMA),
|
||||
INT_ENTRY(5, HDMAEnded),
|
||||
};
|
||||
|
||||
#undef STRUCT
|
||||
@ -545,6 +548,8 @@ static FreezeData SnapAPU [] = {
|
||||
ARRAY_ENTRY(1, TimerEnabled, 3, uint8_ARRAY_V),
|
||||
ARRAY_ENTRY(1, TimerValueWritten, 3, uint8_ARRAY_V),
|
||||
INT_ENTRY(4, Cycles),
|
||||
INT_ENTRY(5, NextAPUTimerPos),
|
||||
INT_ENTRY(5, APUTimerCounter),
|
||||
};
|
||||
|
||||
#undef STRUCT
|
||||
@ -936,10 +941,6 @@ void UnfreezeStructFromCopy (void *base, FreezeData *fields, int num_fields, uin
|
||||
|
||||
int UnfreezeBlockCopy (STREAM stream, char *name, uint8** block, int size);
|
||||
|
||||
void S9xCloseSnapshotFile (FILE *stream)
|
||||
{
|
||||
fclose(stream);
|
||||
}
|
||||
bool8 Snapshot (const char *filename)
|
||||
{
|
||||
return (S9xFreezeGame (filename));
|
||||
@ -956,8 +957,9 @@ bool8 S9xFreezeGame (const char *filename)
|
||||
S9xPrepareSoundForSnapshotSave (FALSE);
|
||||
|
||||
S9xFreezeToStream (stream);
|
||||
#ifndef NGC
|
||||
S9xCloseSnapshotFile (stream);
|
||||
|
||||
#endif
|
||||
S9xPrepareSoundForSnapshotSave (TRUE);
|
||||
|
||||
S9xResetSaveTimer (TRUE);
|
||||
@ -1043,7 +1045,9 @@ bool8 S9xUnfreezeGame (const char *filename)
|
||||
S9xMessage (S9X_ERROR, S9X_ROM_NOT_FOUND, String);
|
||||
break;
|
||||
}
|
||||
#ifndef NGC
|
||||
S9xCloseSnapshotFile (snapshot);
|
||||
#endif
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
@ -1658,8 +1662,13 @@ int S9xUnfreezeFromStream (STREAM stream)
|
||||
if (Settings.SDD1)
|
||||
S9xSDD1PostLoadState ();
|
||||
|
||||
IAPU.NextAPUTimerPos = (CPU.Cycles << SNES_APU_ACCURACY);
|
||||
IAPU.APUTimerCounter = 0;
|
||||
if (version < 5)
|
||||
{
|
||||
// This is not correct, it causes desyncs frequently.
|
||||
// So they have been stored in a snapshot since ver.5.
|
||||
APU.NextAPUTimerPos = (CPU.Cycles << SNES_APU_ACCURACY);
|
||||
APU.APUTimerCounter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (local_cpu) delete [] local_cpu;
|
||||
|
@ -167,7 +167,7 @@
|
||||
#include "snes9x.h"
|
||||
|
||||
#define SNAPSHOT_MAGIC "#!snes9x"
|
||||
#define SNAPSHOT_VERSION 4
|
||||
#define SNAPSHOT_VERSION 5
|
||||
|
||||
#define SUCCESS 1
|
||||
#define WRONG_FORMAT (-1)
|
||||
|
Loading…
Reference in New Issue
Block a user