mirror of
https://github.com/dborth/snes9xgx.git
synced 2024-11-24 03:29:22 +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.WaitAddress2 = NULL;
|
||||||
IAPU.WaitCounter = 0;
|
IAPU.WaitCounter = 0;
|
||||||
#endif
|
#endif
|
||||||
IAPU.NextAPUTimerPos = 0;
|
APU.NextAPUTimerPos = 0;
|
||||||
IAPU.APUTimerCounter = 0;
|
APU.APUTimerCounter = 0;
|
||||||
APU.ShowROM = TRUE;
|
APU.ShowROM = TRUE;
|
||||||
IAPU.RAM [0xf1] = 0x80;
|
IAPU.RAM [0xf1] = 0x80;
|
||||||
|
|
||||||
@ -283,6 +283,9 @@ void S9xResetAPU ()
|
|||||||
|
|
||||||
S9xResetSound (TRUE);
|
S9xResetSound (TRUE);
|
||||||
S9xSetEchoEnable (0);
|
S9xSetEchoEnable (0);
|
||||||
|
|
||||||
|
IAPU.OUTXNotifier = false;
|
||||||
|
IAPU.ENVXNotifier = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void S9xSetAPUDSP (uint8 byte)
|
void S9xSetAPUDSP (uint8 byte)
|
||||||
@ -913,18 +916,18 @@ void S9xSetAPUTimer (uint16 Address, uint8 byte)
|
|||||||
|
|
||||||
void S9xAPUExecute (void)
|
void S9xAPUExecute (void)
|
||||||
{
|
{
|
||||||
while ((CPU.Cycles << SNES_APU_ACCURACY) >= IAPU.NextAPUTimerPos)
|
while ((CPU.Cycles << SNES_APU_ACCURACY) >= APU.NextAPUTimerPos)
|
||||||
{
|
{
|
||||||
// catch up the APU timers
|
// catch up the APU timers
|
||||||
if (IAPU.APUExecuting)
|
if (IAPU.APUExecuting)
|
||||||
{
|
{
|
||||||
while (APU.Cycles < IAPU.NextAPUTimerPos)
|
while (APU.Cycles < APU.NextAPUTimerPos)
|
||||||
APU_EXECUTE1();
|
APU_EXECUTE1();
|
||||||
}
|
}
|
||||||
else
|
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])
|
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])
|
if (APU.TimerEnabled [0])
|
||||||
{
|
{
|
||||||
@ -992,8 +995,10 @@ uint8 S9xGetAPUDSP ()
|
|||||||
switch (reg)
|
switch (reg)
|
||||||
{
|
{
|
||||||
case APU_KON:
|
case APU_KON:
|
||||||
|
IAPU.KONNotifier = true;
|
||||||
break;
|
break;
|
||||||
case APU_KOFF:
|
case APU_KOFF:
|
||||||
|
IAPU.KOFFNotifier = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case APU_OUTX + 0x00:
|
case APU_OUTX + 0x00:
|
||||||
@ -1004,16 +1009,20 @@ uint8 S9xGetAPUDSP ()
|
|||||||
case APU_OUTX + 0x50:
|
case APU_OUTX + 0x50:
|
||||||
case APU_OUTX + 0x60:
|
case APU_OUTX + 0x60:
|
||||||
case APU_OUTX + 0x70:
|
case APU_OUTX + 0x70:
|
||||||
if(Settings.FakeMuteFix)
|
|
||||||
{
|
{
|
||||||
// hack that is off by default: fixes Terranigma desync
|
IAPU.OUTXNotifier = true;
|
||||||
return (0);
|
|
||||||
}
|
if(Settings.FakeMuteFix)
|
||||||
else
|
{
|
||||||
{
|
// hack that is off by default: fixes Terranigma desync
|
||||||
if (SoundData.channels [reg >> 4].state == SOUND_SILENT)
|
|
||||||
return (0);
|
return (0);
|
||||||
return (int8) (SoundData.channels [reg >> 4].out_sample >> 8);
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (SoundData.channels [reg >> 4].state == SOUND_SILENT)
|
||||||
|
return (0);
|
||||||
|
return (int8) (SoundData.channels [reg >> 4].out_sample >> 8);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case APU_ENVX + 0x00:
|
case APU_ENVX + 0x00:
|
||||||
@ -1024,9 +1033,14 @@ uint8 S9xGetAPUDSP ()
|
|||||||
case APU_ENVX + 0x50:
|
case APU_ENVX + 0x50:
|
||||||
case APU_ENVX + 0x60:
|
case APU_ENVX + 0x60:
|
||||||
case APU_ENVX + 0x70:
|
case APU_ENVX + 0x70:
|
||||||
|
{
|
||||||
|
IAPU.ENVXNotifier = true;
|
||||||
|
|
||||||
return (S9xGetEnvelopeHeight (reg >> 4));
|
return (S9xGetEnvelopeHeight (reg >> 4));
|
||||||
|
}
|
||||||
|
|
||||||
case APU_ENDX:
|
case APU_ENDX:
|
||||||
|
IAPU.ENDXNotifier = true;
|
||||||
// To fix speech in Magical Drop 2 6/11/00
|
// To fix speech in Magical Drop 2 6/11/00
|
||||||
// APU.DSP [APU_ENDX] = 0;
|
// APU.DSP [APU_ENDX] = 0;
|
||||||
break;
|
break;
|
||||||
|
@ -183,11 +183,14 @@ struct SIAPU
|
|||||||
uint8 _Zero;
|
uint8 _Zero;
|
||||||
uint8 _Overflow;
|
uint8 _Overflow;
|
||||||
uint32 TimerErrorCounter;
|
uint32 TimerErrorCounter;
|
||||||
int32 NextAPUTimerPos;
|
|
||||||
int32 APUTimerCounter;
|
|
||||||
uint32 Scanline;
|
uint32 Scanline;
|
||||||
int32 OneCycle;
|
int32 OneCycle;
|
||||||
int32 TwoCycles;
|
int32 TwoCycles;
|
||||||
|
bool8 KONNotifier;
|
||||||
|
bool8 KOFFNotifier;
|
||||||
|
bool8 OUTXNotifier;
|
||||||
|
bool8 ENVXNotifier;
|
||||||
|
bool8 ENDXNotifier;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SAPU
|
struct SAPU
|
||||||
@ -204,6 +207,8 @@ struct SAPU
|
|||||||
bool8 TimerEnabled [3];
|
bool8 TimerEnabled [3];
|
||||||
bool8 TimerValueWritten [3];
|
bool8 TimerValueWritten [3];
|
||||||
int32 Cycles;
|
int32 Cycles;
|
||||||
|
int32 NextAPUTimerPos;
|
||||||
|
int32 APUTimerCounter;
|
||||||
};
|
};
|
||||||
|
|
||||||
EXTERN_C struct SAPU APU;
|
EXTERN_C struct SAPU APU;
|
||||||
|
@ -308,13 +308,18 @@ EXTERN_C void C4LoaDMem(char *C4RAM)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint8 *S9xGetBasePointerC4 (uint16 Address)
|
uint8 * S9xGetBasePointerC4 (uint16 Address)
|
||||||
{
|
{
|
||||||
if((Address&~MEMMAP_MASK)>=(0x7f40&~MEMMAP_MASK) &&
|
if (Address >= 0x7f40 && Address <= 0x7f5e)
|
||||||
(Address&~MEMMAP_MASK)<=(0x7f5e&~MEMMAP_MASK)){
|
return (NULL);
|
||||||
return NULL;
|
return (Memory.C4RAM - 0x6000);
|
||||||
}
|
}
|
||||||
return Memory.C4RAM-0x6000;
|
|
||||||
|
uint8 * S9xGetMemPointerC4 (uint16 Address)
|
||||||
|
{
|
||||||
|
if (Address >= 0x7f40 && Address <= 0x7f5e)
|
||||||
|
return (NULL);
|
||||||
|
return (Memory.C4RAM - 0x6000 + (Address & 0xffff));
|
||||||
}
|
}
|
||||||
|
|
||||||
}//end extern C
|
}//end extern C
|
||||||
|
@ -372,13 +372,13 @@ void S9xDoHEventProcessing (void)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case HC_HDMA_START_EVENT:
|
case HC_HDMA_START_EVENT:
|
||||||
if (IPPU.HDMA && CPU.V_Counter <= PPU.ScreenHeight)
|
if (PPU.HDMA && CPU.V_Counter <= PPU.ScreenHeight)
|
||||||
{
|
{
|
||||||
#ifdef DEBUGGER
|
#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);
|
S9xTraceMessage(mes);
|
||||||
#endif
|
#endif
|
||||||
IPPU.HDMA = S9xDoHDMA(IPPU.HDMA);
|
PPU.HDMA = S9xDoHDMA(PPU.HDMA);
|
||||||
}
|
}
|
||||||
|
|
||||||
S9xCheckMissingHTimerPosition(Timings.HDMAStart);
|
S9xCheckMissingHTimerPosition(Timings.HDMAStart);
|
||||||
@ -403,7 +403,7 @@ void S9xDoHEventProcessing (void)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
CPU.Cycles -= Timings.H_Max;
|
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);
|
APU.Cycles -= (Timings.H_Max << SNES_APU_ACCURACY);
|
||||||
|
|
||||||
if ((Timings.NMITriggerPos != 0xffff) && (Timings.NMITriggerPos >= Timings.H_Max))
|
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).
|
if (CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE) // VBlank starts from V=225(240).
|
||||||
{
|
{
|
||||||
S9xEndScreenRefresh();
|
S9xEndScreenRefresh();
|
||||||
IPPU.HDMA = 0;
|
PPU.HDMA = 0;
|
||||||
// Bits 7 and 6 of $4212 are computed when read in S9xGetPPU.
|
// Bits 7 and 6 of $4212 are computed when read in S9xGetPPU.
|
||||||
#ifdef DEBUGGER
|
#ifdef DEBUGGER
|
||||||
missing.dma_this_frame = 0;
|
missing.dma_this_frame = 0;
|
||||||
|
@ -1403,7 +1403,7 @@ static inline bool8 HDMAReadLineCount(int d){
|
|||||||
DMA[d].Repeat = FALSE;
|
DMA[d].Repeat = FALSE;
|
||||||
DMA[d].LineCount = 128;
|
DMA[d].LineCount = 128;
|
||||||
if(DMA[d].HDMAIndirectAddressing){
|
if(DMA[d].HDMAIndirectAddressing){
|
||||||
if(IPPU.HDMA&(0xfe<<d)){
|
if(PPU.HDMA&(0xfe<<d)){
|
||||||
DMA[d].Address++;
|
DMA[d].Address++;
|
||||||
CPU.Cycles+=SLOW_ONE_CYCLE*2;
|
CPU.Cycles+=SLOW_ONE_CYCLE*2;
|
||||||
} else {
|
} else {
|
||||||
@ -1439,26 +1439,26 @@ static inline bool8 HDMAReadLineCount(int d){
|
|||||||
|
|
||||||
void S9xStartHDMA () {
|
void S9xStartHDMA () {
|
||||||
if (Settings.DisableHDMA)
|
if (Settings.DisableHDMA)
|
||||||
IPPU.HDMA = 0;
|
PPU.HDMA = 0;
|
||||||
else
|
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.InHDMA = TRUE;
|
||||||
CPU.InDMAorHDMA = TRUE;
|
CPU.InDMAorHDMA = TRUE;
|
||||||
|
|
||||||
// XXX: Not quite right...
|
// 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++)
|
for (uint8 i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
if (IPPU.HDMA & (1 << i))
|
if (PPU.HDMA & (1 << i))
|
||||||
{
|
{
|
||||||
DMA [i].Address = DMA[i].AAddress;
|
DMA [i].Address = DMA[i].AAddress;
|
||||||
if (!HDMAReadLineCount(i)) {
|
if (!HDMAReadLineCount(i)) {
|
||||||
IPPU.HDMA &= ~(1<<i);
|
PPU.HDMA &= ~(1<<i);
|
||||||
IPPU.HDMAEnded |= (1<<i);
|
PPU.HDMAEnded |= (1<<i);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
DMA[i].DoTransfer = FALSE;
|
DMA[i].DoTransfer = FALSE;
|
||||||
@ -1469,7 +1469,7 @@ void S9xStartHDMA () {
|
|||||||
|
|
||||||
CPU.InHDMA = FALSE;
|
CPU.InHDMA = FALSE;
|
||||||
CPU.InDMAorHDMA = CPU.InDMA;
|
CPU.InDMAorHDMA = CPU.InDMA;
|
||||||
CPU.HDMARanInDMA = CPU.InDMA ? IPPU.HDMA : 0;
|
CPU.HDMARanInDMA = CPU.InDMA ? PPU.HDMA : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUGGER
|
#ifdef DEBUGGER
|
||||||
@ -1734,7 +1734,7 @@ uint8 S9xDoHDMA (uint8 byte)
|
|||||||
if (!--p->LineCount) {
|
if (!--p->LineCount) {
|
||||||
if (!HDMAReadLineCount(d)) {
|
if (!HDMAReadLineCount(d)) {
|
||||||
byte &= ~mask;
|
byte &= ~mask;
|
||||||
IPPU.HDMAEnded |= mask;
|
PPU.HDMAEnded |= mask;
|
||||||
p->DoTransfer = FALSE;
|
p->DoTransfer = FALSE;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -792,10 +792,10 @@ INLINE uint8 *GetBasePointer (uint32 Address)
|
|||||||
return (Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask) - (Address&0xffff));
|
return (Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask) - (Address&0xffff));
|
||||||
|
|
||||||
case CMemory::MAP_C4:
|
case CMemory::MAP_C4:
|
||||||
return S9xGetBasePointerC4(Address);
|
return (S9xGetBasePointerC4(Address & 0xffff));
|
||||||
|
|
||||||
case CMemory::MAP_OBC_RAM:
|
case CMemory::MAP_OBC_RAM:
|
||||||
return GetBasePointerOBC1(Address);
|
return (S9xGetBasePointerOBC1(Address & 0xffff));
|
||||||
|
|
||||||
case CMemory::MAP_DEBUG:
|
case CMemory::MAP_DEBUG:
|
||||||
#ifdef DEBUGGER
|
#ifdef DEBUGGER
|
||||||
@ -848,10 +848,10 @@ INLINE uint8 *S9xGetMemPointer (uint32 Address)
|
|||||||
return (Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask));
|
return (Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask));
|
||||||
|
|
||||||
case CMemory::MAP_C4:
|
case CMemory::MAP_C4:
|
||||||
return S9xGetBasePointerC4(Address) + (Address&0xffff);
|
return (S9xGetMemPointerC4(Address & 0xffff));
|
||||||
|
|
||||||
case CMemory::MAP_OBC_RAM:
|
case CMemory::MAP_OBC_RAM:
|
||||||
return GetMemPointerOBC1(Address);
|
return (S9xGetMemPointerOBC1(Address & 0xffff));
|
||||||
|
|
||||||
case CMemory::MAP_DEBUG:
|
case CMemory::MAP_DEBUG:
|
||||||
#ifdef DEBUGGER
|
#ifdef DEBUGGER
|
||||||
@ -930,11 +930,11 @@ INLINE void S9xSetPCBase (uint32 Address)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case CMemory::MAP_C4:
|
case CMemory::MAP_C4:
|
||||||
CPU.PCBase = S9xGetBasePointerC4(Address);
|
CPU.PCBase = S9xGetBasePointerC4(Address & 0xffff);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case CMemory::MAP_OBC_RAM:
|
case CMemory::MAP_OBC_RAM:
|
||||||
CPU.PCBase = GetBasePointerOBC1(Address);
|
CPU.PCBase = S9xGetBasePointerOBC1(Address & 0xffff);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case CMemory::MAP_BSX:
|
case CMemory::MAP_BSX:
|
||||||
|
@ -382,7 +382,6 @@ void S9xStartScreenRefresh(){
|
|||||||
IPPU.RenderedFramesCount = 0;
|
IPPU.RenderedFramesCount = 0;
|
||||||
IPPU.FrameCount = 0;
|
IPPU.FrameCount = 0;
|
||||||
}
|
}
|
||||||
++IPPU.TotalEmulatedFrames;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderLine(uint8 C) {
|
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)
|
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;
|
mC1 = C1 & FIRST_COLOR_MASK;
|
||||||
mC2 = C2 & FIRST_COLOR_MASK;
|
mC2 = C2 & FIRST_COLOR_MASK;
|
||||||
|
@ -173,9 +173,7 @@
|
|||||||
#include "fxemu.h"
|
#include "fxemu.h"
|
||||||
#include "gfx.h"
|
#include "gfx.h"
|
||||||
#include "soundux.h"
|
#include "soundux.h"
|
||||||
|
|
||||||
#include "cheats.h"
|
#include "cheats.h"
|
||||||
|
|
||||||
#include "sa1.h"
|
#include "sa1.h"
|
||||||
#include "bsx.h"
|
#include "bsx.h"
|
||||||
#include "spc7110.h"
|
#include "spc7110.h"
|
||||||
@ -204,8 +202,6 @@ struct SAPURegisters APURegisters;
|
|||||||
|
|
||||||
struct SSettings Settings;
|
struct SSettings Settings;
|
||||||
|
|
||||||
struct SDSP1 DSP1;
|
|
||||||
|
|
||||||
struct SSA1Registers SA1Registers;
|
struct SSA1Registers SA1Registers;
|
||||||
|
|
||||||
struct SSA1 SA1;
|
struct SSA1 SA1;
|
||||||
@ -216,10 +212,6 @@ struct SMulti Multi;
|
|||||||
|
|
||||||
SSoundData SoundData;
|
SSoundData SoundData;
|
||||||
|
|
||||||
SnesModel M1SNES={1,3,2};
|
|
||||||
SnesModel M2SNES={2,4,3};
|
|
||||||
SnesModel* Model=&M1SNES;
|
|
||||||
|
|
||||||
#if defined(ZSNES_FX) || defined(ZSNES_C4)
|
#if defined(ZSNES_FX) || defined(ZSNES_C4)
|
||||||
uint8 *ROM = NULL;
|
uint8 *ROM = NULL;
|
||||||
uint8 *SRAM = NULL;
|
uint8 *SRAM = NULL;
|
||||||
@ -235,6 +227,12 @@ unsigned char OpenBus = 0;
|
|||||||
|
|
||||||
END_EXTERN_C
|
END_EXTERN_C
|
||||||
|
|
||||||
|
struct SDSP1 DSP1;
|
||||||
|
|
||||||
|
SnesModel M1SNES={1,3,2};
|
||||||
|
SnesModel M2SNES={2,4,3};
|
||||||
|
SnesModel* Model=&M1SNES;
|
||||||
|
|
||||||
#ifndef ZSNES_FX
|
#ifndef ZSNES_FX
|
||||||
struct FxInit_s SuperFX;
|
struct FxInit_s SuperFX;
|
||||||
#else
|
#else
|
||||||
@ -292,7 +290,6 @@ uint32 current_graphic_format = RGB565;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint8 GetBank = 0;
|
uint8 GetBank = 0;
|
||||||
|
|
||||||
struct SCheatData Cheat;
|
struct SCheatData Cheat;
|
||||||
|
|
||||||
volatile SoundStatus so;
|
volatile SoundStatus so;
|
||||||
|
@ -1996,25 +1996,6 @@ void CMemory::InitROM (void)
|
|||||||
else
|
else
|
||||||
Settings.PAL = FALSE;
|
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)
|
if (Settings.PAL)
|
||||||
{
|
{
|
||||||
Settings.FrameTime = Settings.FrameTimePAL;
|
Settings.FrameTime = Settings.FrameTimePAL;
|
||||||
@ -2057,6 +2038,23 @@ void CMemory::InitROM (void)
|
|||||||
SET_UI_COLOR(0, 128, 255);
|
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;
|
IAPU.OneCycle = SNES_APU_ONE_CYCLE_SCALED;
|
||||||
|
|
||||||
CPU.FastROMSpeed = 0;
|
CPU.FastROMSpeed = 0;
|
||||||
|
@ -252,20 +252,18 @@ void SetOBC1 (uint8 Byte, uint16 Address)
|
|||||||
OBC1_RAM[Address & 0x1fff] = Byte;
|
OBC1_RAM[Address & 0x1fff] = Byte;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 *GetBasePointerOBC1(uint32 Address)
|
uint8 * S9xGetBasePointerOBC1 (uint16 Address)
|
||||||
{
|
{
|
||||||
Address=Address&0xffff;
|
if (Address >= 0x7ff0 && Address <= 0x7ff6)
|
||||||
if((Address&~MEMMAP_MASK)>=(0x7ff0&~MEMMAP_MASK) &&
|
return (NULL);
|
||||||
(Address&~MEMMAP_MASK)<=(0x7ff6&~MEMMAP_MASK)) return NULL;
|
return (OBC1_RAM - 0x6000);
|
||||||
return OBC1_RAM + (Address & 0x1fff);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 *GetMemPointerOBC1(uint32 Address)
|
uint8 * S9xGetMemPointerOBC1 (uint16 Address)
|
||||||
{
|
{
|
||||||
Address=Address&0xffff;
|
if (Address >= 0x7ff0 && Address <= 0x7ff6)
|
||||||
if((Address&~MEMMAP_MASK)>=(0x7ff0&~MEMMAP_MASK) &&
|
return (NULL);
|
||||||
(Address&~MEMMAP_MASK)<=(0x7ff6&~MEMMAP_MASK)) return NULL;
|
return (OBC1_RAM - 0x6000 + (Address & 0xffff));
|
||||||
return OBC1_RAM + (Address & 0x1fff);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResetOBC1()
|
void ResetOBC1()
|
||||||
|
@ -167,8 +167,8 @@
|
|||||||
START_EXTERN_C
|
START_EXTERN_C
|
||||||
uint8 GetOBC1 (uint16 Address);
|
uint8 GetOBC1 (uint16 Address);
|
||||||
void SetOBC1 (uint8 Byte, uint16 Address);
|
void SetOBC1 (uint8 Byte, uint16 Address);
|
||||||
uint8 *GetBasePointerOBC1(uint32 Address);
|
uint8 * S9xGetBasePointerOBC1 (uint16);
|
||||||
uint8 *GetMemPointerOBC1(uint32 Address);
|
uint8 * S9xGetMemPointerOBC1 (uint16);
|
||||||
void ResetOBC1();//bool8 full);
|
void ResetOBC1();//bool8 full);
|
||||||
END_EXTERN_C
|
END_EXTERN_C
|
||||||
|
|
||||||
|
@ -261,8 +261,6 @@ typedef unsigned long long uint64;
|
|||||||
# include <systypes.h>
|
# include <systypes.h>
|
||||||
# else
|
# else
|
||||||
|
|
||||||
#define SNES_JOY_READ_CALLBACKS
|
|
||||||
|
|
||||||
typedef unsigned char uint8;
|
typedef unsigned char uint8;
|
||||||
typedef unsigned short uint16;
|
typedef unsigned short uint16;
|
||||||
typedef signed char int8;
|
typedef signed char int8;
|
||||||
@ -276,6 +274,16 @@ typedef long int32;
|
|||||||
# define RIGHTSHIFT_IS_SAR
|
# define RIGHTSHIFT_IS_SAR
|
||||||
# endif
|
# 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;
|
typedef unsigned int uint32;
|
||||||
|
|
||||||
# endif /* __BORLANDC__ */
|
# endif /* __BORLANDC__ */
|
||||||
@ -335,9 +343,15 @@ void _splitpath (const char *path, char *drive, char *dir, char *fname,
|
|||||||
#else /* __WIN32__ */
|
#else /* __WIN32__ */
|
||||||
#define strcasecmp stricmp
|
#define strcasecmp stricmp
|
||||||
#define strncasecmp strnicmp
|
#define strncasecmp strnicmp
|
||||||
|
|
||||||
|
#define SNES_JOY_READ_CALLBACKS
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
EXTERN_C void S9xGenerateSound ();
|
EXTERN_C void S9xGenerateSound ();
|
||||||
|
#ifdef __WIN32__
|
||||||
|
EXTERN_C void S9xGenerateFrameSound ();
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef STORM
|
#ifdef STORM
|
||||||
EXTERN_C int soundsignal;
|
EXTERN_C int soundsignal;
|
||||||
|
@ -2088,10 +2088,10 @@ void S9xSetCPU (uint8 byte, uint16 Address)
|
|||||||
if (Settings.DisableHDMA)
|
if (Settings.DisableHDMA)
|
||||||
byte = 0;
|
byte = 0;
|
||||||
Memory.FillRAM[0x420c] = byte;
|
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
|
// FIXME
|
||||||
// Yoshi's Island / Genjyu Ryodan, Mortal Kombat, Tales of Phantasia
|
// Yoshi's Island / Genjyu Ryodan, Mortal Kombat, Tales of Phantasia
|
||||||
IPPU.HDMA = byte&~IPPU.HDMAEnded;
|
PPU.HDMA = byte&~PPU.HDMAEnded;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x420d:
|
case 0x420d:
|
||||||
@ -2306,7 +2306,7 @@ void S9xSetCPU (uint8 byte, uint16 Address)
|
|||||||
DMA[d].LineCount = 128;
|
DMA[d].LineCount = 128;
|
||||||
DMA[d].Repeat = !!(byte & 0x80);
|
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;
|
return;
|
||||||
|
|
||||||
case 0x430B:
|
case 0x430B:
|
||||||
@ -2422,11 +2422,14 @@ uint8 S9xGetCPU (uint16 Address)
|
|||||||
|
|
||||||
if (Address < 0x4200)
|
if (Address < 0x4200)
|
||||||
{
|
{
|
||||||
#ifdef SNES_JOY_READ_CALLBACKS
|
|
||||||
extern bool8 pad_read;
|
|
||||||
if(Address==0x4016 || Address==0x4017)
|
if(Address==0x4016 || Address==0x4017)
|
||||||
S9xOnSNESPadRead(), pad_read = true;
|
{
|
||||||
|
extern bool8 pad_read;
|
||||||
|
#ifdef SNES_JOY_READ_CALLBACKS
|
||||||
|
S9xOnSNESPadRead();
|
||||||
#endif
|
#endif
|
||||||
|
pad_read = true;
|
||||||
|
}
|
||||||
|
|
||||||
CPU.Cycles += ONE_CYCLE;
|
CPU.Cycles += ONE_CYCLE;
|
||||||
switch (Address)
|
switch (Address)
|
||||||
@ -2516,13 +2519,14 @@ uint8 S9xGetCPU (uint16 Address)
|
|||||||
case 0x421d:
|
case 0x421d:
|
||||||
case 0x421e:
|
case 0x421e:
|
||||||
case 0x421f:
|
case 0x421f:
|
||||||
#ifdef SNES_JOY_READ_CALLBACKS
|
|
||||||
{
|
|
||||||
extern bool8 pad_read;
|
|
||||||
if(Memory.FillRAM[0x4200] & 1)
|
if(Memory.FillRAM[0x4200] & 1)
|
||||||
S9xOnSNESPadRead(), pad_read = true;
|
{
|
||||||
}
|
extern bool8 pad_read;
|
||||||
|
#ifdef SNES_JOY_READ_CALLBACKS
|
||||||
|
S9xOnSNESPadRead();
|
||||||
#endif
|
#endif
|
||||||
|
pad_read = true;
|
||||||
|
}
|
||||||
// Joypads 1-4 button and direction state.
|
// Joypads 1-4 button and direction state.
|
||||||
return (Memory.FillRAM [Address]);
|
return (Memory.FillRAM [Address]);
|
||||||
|
|
||||||
@ -2824,8 +2828,8 @@ void S9xSoftResetPPU ()
|
|||||||
PPU.Need16x8Mulitply = FALSE;
|
PPU.Need16x8Mulitply = FALSE;
|
||||||
|
|
||||||
IPPU.ColorsChanged = TRUE;
|
IPPU.ColorsChanged = TRUE;
|
||||||
IPPU.HDMA = 0;
|
PPU.HDMA = 0;
|
||||||
IPPU.HDMAEnded = 0;
|
PPU.HDMAEnded = 0;
|
||||||
IPPU.MaxBrightness = 0;
|
IPPU.MaxBrightness = 0;
|
||||||
IPPU.LatchedBlanking = 0;
|
IPPU.LatchedBlanking = 0;
|
||||||
IPPU.OBJChanged = TRUE;
|
IPPU.OBJChanged = TRUE;
|
||||||
|
@ -196,8 +196,6 @@ struct ClipData {
|
|||||||
|
|
||||||
struct InternalPPU {
|
struct InternalPPU {
|
||||||
bool8 ColorsChanged;
|
bool8 ColorsChanged;
|
||||||
uint8 HDMA;
|
|
||||||
uint8 HDMAEnded;
|
|
||||||
uint8 MaxBrightness;
|
uint8 MaxBrightness;
|
||||||
bool8 LatchedBlanking;
|
bool8 LatchedBlanking;
|
||||||
bool8 OBJChanged;
|
bool8 OBJChanged;
|
||||||
@ -344,6 +342,9 @@ struct SPPU {
|
|||||||
uint16 GunVLatch;
|
uint16 GunVLatch;
|
||||||
uint16 GunHLatch;
|
uint16 GunHLatch;
|
||||||
short VTimerPosition;
|
short VTimerPosition;
|
||||||
|
|
||||||
|
uint8 HDMA;
|
||||||
|
uint8 HDMAEnded;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CLIP_OR 0
|
#define CLIP_OR 0
|
||||||
@ -407,7 +408,8 @@ void S9xSetC4 (uint8 Byte, uint16 Address);
|
|||||||
uint8 S9xGetC4 (uint16 Address);
|
uint8 S9xGetC4 (uint16 Address);
|
||||||
void S9xSetC4RAM (uint8 Byte, uint16 Address);
|
void S9xSetC4RAM (uint8 Byte, uint16 Address);
|
||||||
uint8 S9xGetC4RAM (uint16 Address);
|
uint8 S9xGetC4RAM (uint16 Address);
|
||||||
uint8 *S9xGetBasePointerC4 (uint16 Address);
|
uint8 * S9xGetBasePointerC4 (uint16);
|
||||||
|
uint8 * S9xGetMemPointerC4 (uint16);
|
||||||
|
|
||||||
void S9xUpdateHVTimerPosition (void);
|
void S9xUpdateHVTimerPosition (void);
|
||||||
void S9xCheckMissingHTimerPosition (int32);
|
void S9xCheckMissingHTimerPosition (int32);
|
||||||
|
@ -499,6 +499,9 @@ static FreezeData SnapPPU [] = {
|
|||||||
INT_ENTRY(3, GunVLatch),
|
INT_ENTRY(3, GunVLatch),
|
||||||
INT_ENTRY(3, GunHLatch),
|
INT_ENTRY(3, GunHLatch),
|
||||||
INT_ENTRY(2, VTimerPosition),
|
INT_ENTRY(2, VTimerPosition),
|
||||||
|
|
||||||
|
INT_ENTRY(5, HDMA),
|
||||||
|
INT_ENTRY(5, HDMAEnded),
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef STRUCT
|
#undef STRUCT
|
||||||
@ -545,6 +548,8 @@ static FreezeData SnapAPU [] = {
|
|||||||
ARRAY_ENTRY(1, TimerEnabled, 3, uint8_ARRAY_V),
|
ARRAY_ENTRY(1, TimerEnabled, 3, uint8_ARRAY_V),
|
||||||
ARRAY_ENTRY(1, TimerValueWritten, 3, uint8_ARRAY_V),
|
ARRAY_ENTRY(1, TimerValueWritten, 3, uint8_ARRAY_V),
|
||||||
INT_ENTRY(4, Cycles),
|
INT_ENTRY(4, Cycles),
|
||||||
|
INT_ENTRY(5, NextAPUTimerPos),
|
||||||
|
INT_ENTRY(5, APUTimerCounter),
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef STRUCT
|
#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);
|
int UnfreezeBlockCopy (STREAM stream, char *name, uint8** block, int size);
|
||||||
|
|
||||||
void S9xCloseSnapshotFile (FILE *stream)
|
|
||||||
{
|
|
||||||
fclose(stream);
|
|
||||||
}
|
|
||||||
bool8 Snapshot (const char *filename)
|
bool8 Snapshot (const char *filename)
|
||||||
{
|
{
|
||||||
return (S9xFreezeGame (filename));
|
return (S9xFreezeGame (filename));
|
||||||
@ -956,8 +957,9 @@ bool8 S9xFreezeGame (const char *filename)
|
|||||||
S9xPrepareSoundForSnapshotSave (FALSE);
|
S9xPrepareSoundForSnapshotSave (FALSE);
|
||||||
|
|
||||||
S9xFreezeToStream (stream);
|
S9xFreezeToStream (stream);
|
||||||
|
#ifndef NGC
|
||||||
S9xCloseSnapshotFile (stream);
|
S9xCloseSnapshotFile (stream);
|
||||||
|
#endif
|
||||||
S9xPrepareSoundForSnapshotSave (TRUE);
|
S9xPrepareSoundForSnapshotSave (TRUE);
|
||||||
|
|
||||||
S9xResetSaveTimer (TRUE);
|
S9xResetSaveTimer (TRUE);
|
||||||
@ -1043,7 +1045,9 @@ bool8 S9xUnfreezeGame (const char *filename)
|
|||||||
S9xMessage (S9X_ERROR, S9X_ROM_NOT_FOUND, String);
|
S9xMessage (S9X_ERROR, S9X_ROM_NOT_FOUND, String);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#ifndef NGC
|
||||||
S9xCloseSnapshotFile (snapshot);
|
S9xCloseSnapshotFile (snapshot);
|
||||||
|
#endif
|
||||||
return (FALSE);
|
return (FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1658,8 +1662,13 @@ int S9xUnfreezeFromStream (STREAM stream)
|
|||||||
if (Settings.SDD1)
|
if (Settings.SDD1)
|
||||||
S9xSDD1PostLoadState ();
|
S9xSDD1PostLoadState ();
|
||||||
|
|
||||||
IAPU.NextAPUTimerPos = (CPU.Cycles << SNES_APU_ACCURACY);
|
if (version < 5)
|
||||||
IAPU.APUTimerCounter = 0;
|
{
|
||||||
|
// 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;
|
if (local_cpu) delete [] local_cpu;
|
||||||
|
@ -167,7 +167,7 @@
|
|||||||
#include "snes9x.h"
|
#include "snes9x.h"
|
||||||
|
|
||||||
#define SNAPSHOT_MAGIC "#!snes9x"
|
#define SNAPSHOT_MAGIC "#!snes9x"
|
||||||
#define SNAPSHOT_VERSION 4
|
#define SNAPSHOT_VERSION 5
|
||||||
|
|
||||||
#define SUCCESS 1
|
#define SUCCESS 1
|
||||||
#define WRONG_FORMAT (-1)
|
#define WRONG_FORMAT (-1)
|
||||||
|
Loading…
Reference in New Issue
Block a user