mirror of
https://github.com/dborth/snes9xgx.git
synced 2024-11-27 13:04:21 +01:00
core update - improved IRQ and SA-1
This commit is contained in:
parent
32f8662987
commit
5d7331ead0
@ -328,14 +328,3 @@ uint8 * S9xGetMemPointerC4 (uint16 Address)
|
||||
return (NULL);
|
||||
return (Memory.C4RAM - 0x6000 + (Address & 0xffff));
|
||||
}
|
||||
|
||||
#ifdef ZSNES_C4
|
||||
START_EXTERN_C
|
||||
|
||||
void C4LoaDMem (char *C4RAM)
|
||||
{
|
||||
memmove(C4RAM + (READ_WORD(C4RAM + 0x1f45) & 0x1fff), C4GetMemPointer(READ_3WORD(C4RAM + 0x1f40)), READ_WORD(C4RAM + 0x1f43));
|
||||
}
|
||||
|
||||
END_EXTERN_C
|
||||
#endif
|
||||
|
@ -178,10 +178,6 @@
|
||||
#ifndef _C4_H_
|
||||
#define _C4_H_
|
||||
|
||||
#ifdef ZSNES_C4
|
||||
START_EXTERN_C
|
||||
#endif
|
||||
|
||||
extern int16 C4WFXVal;
|
||||
extern int16 C4WFYVal;
|
||||
extern int16 C4WFZVal;
|
||||
@ -195,10 +191,6 @@ extern int16 C41FAngleRes;
|
||||
extern int16 C41FDist;
|
||||
extern int16 C41FDistVal;
|
||||
|
||||
#ifdef ZSNES_C4
|
||||
extern uint8 *C4Ram;
|
||||
#endif
|
||||
|
||||
void C4TransfWireFrame (void);
|
||||
void C4TransfWireFrame2 (void);
|
||||
void C4CalcWireFrame (void);
|
||||
@ -208,11 +200,6 @@ void C4Op1F (void);
|
||||
void S9xInitC4 (void);
|
||||
void S9xSetC4 (uint8, uint16);
|
||||
uint8 S9xGetC4 (uint16);
|
||||
|
||||
#ifdef ZSNES_C4
|
||||
END_EXTERN_C
|
||||
#endif
|
||||
|
||||
uint8 * S9xGetBasePointerC4 (uint16);
|
||||
uint8 * S9xGetMemPointerC4 (uint16);
|
||||
|
||||
|
@ -186,12 +186,9 @@ static void S9xSetByteFree (uint8, uint32);
|
||||
static uint8 S9xGetByteFree (uint32 address)
|
||||
{
|
||||
uint32 Cycles = CPU.Cycles;
|
||||
uint32 WaitAddress = CPU.WaitAddress;
|
||||
uint8 byte;
|
||||
|
||||
byte = S9xGetByte(address);
|
||||
|
||||
CPU.WaitAddress = WaitAddress;
|
||||
CPU.Cycles = Cycles;
|
||||
|
||||
return (byte);
|
||||
@ -200,11 +197,8 @@ static uint8 S9xGetByteFree (uint32 address)
|
||||
static void S9xSetByteFree (uint8 byte, uint32 address)
|
||||
{
|
||||
uint32 Cycles = CPU.Cycles;
|
||||
uint32 WaitAddress = CPU.WaitAddress;
|
||||
|
||||
S9xSetByte(byte, address);
|
||||
|
||||
CPU.WaitAddress = WaitAddress;
|
||||
CPU.Cycles = Cycles;
|
||||
}
|
||||
|
||||
|
@ -429,7 +429,6 @@ static const int ptrspeeds[4] = { 1, 1, 4, 8 };
|
||||
S(ToggleBG2), \
|
||||
S(ToggleBG3), \
|
||||
S(ToggleEmuTurbo), \
|
||||
S(ToggleHDMA), \
|
||||
S(ToggleSprites), \
|
||||
S(ToggleTransparency) \
|
||||
|
||||
@ -2458,11 +2457,6 @@ void S9xApplyCommand (s9xcommand_t cmd, int16 data1, int16 data2)
|
||||
DisplayStateChange("Sprites", !(Settings.BG_Forced & 16));
|
||||
break;
|
||||
|
||||
case ToggleHDMA:
|
||||
Settings.DisableHDMA = !Settings.DisableHDMA;
|
||||
DisplayStateChange("HDMA emulation", !Settings.DisableHDMA);
|
||||
break;
|
||||
|
||||
case ToggleTransparency:
|
||||
Settings.Transparency = !Settings.Transparency;
|
||||
DisplayStateChange("Transparency effects", Settings.Transparency);
|
||||
|
@ -208,12 +208,16 @@ static void S9xResetCPU (void)
|
||||
static void S9xSoftResetCPU (void)
|
||||
{
|
||||
CPU.Cycles = 182; // Or 188. This is the cycle count just after the jump to the Reset Vector.
|
||||
CPU.PrevCycles = -1;
|
||||
CPU.PrevCycles = CPU.Cycles;
|
||||
CPU.V_Counter = 0;
|
||||
CPU.Flags = CPU.Flags & (DEBUG_MODE_FLAG | TRACE_FLAG);
|
||||
CPU.PCBase = NULL;
|
||||
CPU.IRQActive = FALSE;
|
||||
CPU.IRQPending = 0;
|
||||
CPU.NMILine = FALSE;
|
||||
CPU.IRQLine = FALSE;
|
||||
CPU.IRQTransition = FALSE;
|
||||
CPU.IRQLastState = FALSE;
|
||||
CPU.IRQExternal = FALSE;
|
||||
CPU.IRQPending = Timings.IRQPendCount;
|
||||
CPU.MemSpeed = SLOW_ONE_CYCLE;
|
||||
CPU.MemSpeedx2 = SLOW_ONE_CYCLE * 2;
|
||||
CPU.FastROMSpeed = SLOW_ONE_CYCLE;
|
||||
@ -226,9 +230,6 @@ static void S9xSoftResetCPU (void)
|
||||
CPU.WhichEvent = HC_RENDER_EVENT;
|
||||
CPU.NextEvent = Timings.RenderPos;
|
||||
CPU.WaitingForInterrupt = FALSE;
|
||||
CPU.WaitAddress = 0xffffffff;
|
||||
CPU.WaitCounter = 0;
|
||||
CPU.PBPCAtOpcodeStart = 0xffffffff;
|
||||
CPU.AutoSaveTimer = 0;
|
||||
CPU.SRAMModified = FALSE;
|
||||
|
||||
@ -261,7 +262,6 @@ static void S9xSoftResetCPU (void)
|
||||
|
||||
ICPU.S9xOpcodes = S9xOpcodesE1;
|
||||
ICPU.S9xOpLengths = S9xOpLengthsM1X1;
|
||||
ICPU.CPUExecuting = TRUE;
|
||||
|
||||
S9xUnpackStatus();
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -179,6 +179,9 @@
|
||||
#define _CPUEXEC_H_
|
||||
|
||||
#include "ppu.h"
|
||||
#ifdef DEBUGGER
|
||||
#include "debug.h"
|
||||
#endif
|
||||
|
||||
struct SOpcodes
|
||||
{
|
||||
@ -193,7 +196,6 @@ struct SICPU
|
||||
uint8 _Zero;
|
||||
uint8 _Negative;
|
||||
uint8 _Overflow;
|
||||
bool8 CPUExecuting;
|
||||
uint32 ShiftedPB;
|
||||
uint32 ShiftedDB;
|
||||
uint32 Frame;
|
||||
@ -217,8 +219,6 @@ void S9xMainLoop (void);
|
||||
void S9xReset (void);
|
||||
void S9xSoftReset (void);
|
||||
void S9xDoHEventProcessing (void);
|
||||
void S9xClearIRQ (uint32);
|
||||
void S9xSetIRQ (uint32);
|
||||
|
||||
static inline void S9xUnpackStatus (void)
|
||||
{
|
||||
@ -270,84 +270,43 @@ static inline void S9xFixCycles (void)
|
||||
}
|
||||
}
|
||||
|
||||
static inline void S9xReschedule (void)
|
||||
static inline void S9xCheckInterrupts (void)
|
||||
{
|
||||
uint8 next = 0;
|
||||
int32 hpos = 0;
|
||||
bool8 thisIRQ = PPU.HTimerEnabled || PPU.VTimerEnabled;
|
||||
|
||||
switch (CPU.WhichEvent)
|
||||
if (CPU.IRQLine && thisIRQ)
|
||||
CPU.IRQTransition = TRUE;
|
||||
|
||||
if (PPU.HTimerEnabled)
|
||||
{
|
||||
case HC_HBLANK_START_EVENT:
|
||||
case HC_IRQ_1_3_EVENT:
|
||||
next = HC_HDMA_START_EVENT;
|
||||
hpos = Timings.HDMAStart;
|
||||
break;
|
||||
int32 htimepos = PPU.HTimerPosition;
|
||||
if (CPU.Cycles >= Timings.H_Max)
|
||||
htimepos += Timings.H_Max;
|
||||
|
||||
case HC_HDMA_START_EVENT:
|
||||
case HC_IRQ_3_5_EVENT:
|
||||
next = HC_HCOUNTER_MAX_EVENT;
|
||||
hpos = Timings.H_Max;
|
||||
break;
|
||||
|
||||
case HC_HCOUNTER_MAX_EVENT:
|
||||
case HC_IRQ_5_7_EVENT:
|
||||
next = HC_HDMA_INIT_EVENT;
|
||||
hpos = Timings.HDMAInit;
|
||||
break;
|
||||
|
||||
case HC_HDMA_INIT_EVENT:
|
||||
case HC_IRQ_7_9_EVENT:
|
||||
next = HC_RENDER_EVENT;
|
||||
hpos = Timings.RenderPos;
|
||||
break;
|
||||
|
||||
case HC_RENDER_EVENT:
|
||||
case HC_IRQ_9_A_EVENT:
|
||||
next = HC_WRAM_REFRESH_EVENT;
|
||||
hpos = Timings.WRAMRefreshPos;
|
||||
break;
|
||||
|
||||
case HC_WRAM_REFRESH_EVENT:
|
||||
case HC_IRQ_A_1_EVENT:
|
||||
next = HC_HBLANK_START_EVENT;
|
||||
hpos = Timings.HBlankStart;
|
||||
break;
|
||||
if (CPU.PrevCycles >= htimepos || CPU.Cycles < htimepos)
|
||||
thisIRQ = FALSE;
|
||||
}
|
||||
|
||||
if (((int32) PPU.HTimerPosition > CPU.NextEvent) && ((int32) PPU.HTimerPosition < hpos))
|
||||
if (PPU.VTimerEnabled)
|
||||
{
|
||||
hpos = (int32) PPU.HTimerPosition;
|
||||
int32 vcounter = CPU.V_Counter;
|
||||
if (CPU.Cycles >= Timings.H_Max)
|
||||
vcounter++;
|
||||
|
||||
switch (next)
|
||||
{
|
||||
case HC_HDMA_START_EVENT:
|
||||
next = HC_IRQ_1_3_EVENT;
|
||||
break;
|
||||
|
||||
case HC_HCOUNTER_MAX_EVENT:
|
||||
next = HC_IRQ_3_5_EVENT;
|
||||
break;
|
||||
|
||||
case HC_HDMA_INIT_EVENT:
|
||||
next = HC_IRQ_5_7_EVENT;
|
||||
break;
|
||||
|
||||
case HC_RENDER_EVENT:
|
||||
next = HC_IRQ_7_9_EVENT;
|
||||
break;
|
||||
|
||||
case HC_WRAM_REFRESH_EVENT:
|
||||
next = HC_IRQ_9_A_EVENT;
|
||||
break;
|
||||
|
||||
case HC_HBLANK_START_EVENT:
|
||||
next = HC_IRQ_A_1_EVENT;
|
||||
break;
|
||||
}
|
||||
if (vcounter != PPU.VTimerPosition)
|
||||
thisIRQ = FALSE;
|
||||
}
|
||||
|
||||
CPU.NextEvent = hpos;
|
||||
CPU.WhichEvent = next;
|
||||
if (!CPU.IRQLastState && thisIRQ)
|
||||
{
|
||||
#ifdef DEBUGGER
|
||||
S9xTraceFormattedMessage("--- /IRQ High->Low prev HC:%04d curr HC:%04d HTimer:%d Pos:%04d VTimer:%d Pos:%03d",
|
||||
CPU.PrevCycles, CPU.Cycles, PPU.HTimerEnabled, PPU.HTimerPosition, PPU.VTimerEnabled, PPU.VTimerPosition);
|
||||
#endif
|
||||
CPU.IRQLine = TRUE;
|
||||
}
|
||||
|
||||
CPU.IRQLastState = thisIRQ;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -280,7 +280,6 @@ static void Op##OP (void) \
|
||||
S9xSetPCBase(ICPU.ShiftedPB + newPC.W); \
|
||||
else \
|
||||
Registers.PCw = newPC.W; \
|
||||
CPUShutdown(); \
|
||||
} \
|
||||
}
|
||||
|
||||
@ -515,9 +514,6 @@ static inline void CPY (uint8 val)
|
||||
|
||||
static inline void DEC16 (uint32 OpAddress, s9xwrap_t w)
|
||||
{
|
||||
#ifdef CPU_SHUTDOWN
|
||||
CPU.WaitAddress = 0xffffffff;
|
||||
#endif
|
||||
uint16 Work16 = S9xGetWord(OpAddress, w) - 1;
|
||||
AddCycles(ONE_CYCLE);
|
||||
S9xSetWord(Work16, OpAddress, w, WRITE_10);
|
||||
@ -527,9 +523,6 @@ static inline void DEC16 (uint32 OpAddress, s9xwrap_t w)
|
||||
|
||||
static inline void DEC8 (uint32 OpAddress)
|
||||
{
|
||||
#ifdef CPU_SHUTDOWN
|
||||
CPU.WaitAddress = 0xffffffff;
|
||||
#endif
|
||||
uint8 Work8 = S9xGetByte(OpAddress) - 1;
|
||||
AddCycles(ONE_CYCLE);
|
||||
S9xSetByte(Work8, OpAddress);
|
||||
@ -551,9 +544,6 @@ static inline void EOR (uint8 val)
|
||||
|
||||
static inline void INC16 (uint32 OpAddress, s9xwrap_t w)
|
||||
{
|
||||
#ifdef CPU_SHUTDOWN
|
||||
CPU.WaitAddress = 0xffffffff;
|
||||
#endif
|
||||
uint16 Work16 = S9xGetWord(OpAddress, w) + 1;
|
||||
AddCycles(ONE_CYCLE);
|
||||
S9xSetWord(Work16, OpAddress, w, WRITE_10);
|
||||
@ -563,9 +553,6 @@ static inline void INC16 (uint32 OpAddress, s9xwrap_t w)
|
||||
|
||||
static inline void INC8 (uint32 OpAddress)
|
||||
{
|
||||
#ifdef CPU_SHUTDOWN
|
||||
CPU.WaitAddress = 0xffffffff;
|
||||
#endif
|
||||
uint8 Work8 = S9xGetByte(OpAddress) + 1;
|
||||
AddCycles(ONE_CYCLE);
|
||||
S9xSetByte(Work8, OpAddress);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -181,8 +181,9 @@
|
||||
void S9xOpcode_NMI (void);
|
||||
void S9xOpcode_IRQ (void);
|
||||
|
||||
#define CHECK_FOR_IRQ() \
|
||||
if (CPU.IRQActive && !CheckFlag(IRQ) && !Settings.DisableIRQ) \
|
||||
S9xOpcode_IRQ()
|
||||
|
||||
#ifndef SA1_OPCODES
|
||||
#define CHECK_FOR_IRQ() {} // if (CPU.IRQLine) S9xOpcode_IRQ(); }
|
||||
#else
|
||||
#define CHECK_FOR_IRQ() {}
|
||||
#endif
|
||||
#endif
|
||||
|
@ -185,7 +185,7 @@
|
||||
#include "missing.h"
|
||||
#endif
|
||||
|
||||
#define ADD_CYCLES(n) CPU.Cycles += (n)
|
||||
#define ADD_CYCLES(n) { CPU.PrevCycles = CPU.Cycles; CPU.Cycles += (n); S9xCheckInterrupts(); }
|
||||
|
||||
extern uint8 *HDMAMemPointers[8];
|
||||
extern int HDMA_ModeByteCounts[8];
|
||||
@ -741,9 +741,6 @@ bool8 S9xDoDMA (uint8 Channel)
|
||||
break;
|
||||
|
||||
case 0x18: // VMDATAL
|
||||
#ifndef CORRECT_VRAM_READS
|
||||
IPPU.FirstVRAMRead = TRUE;
|
||||
#endif
|
||||
if (!PPU.VMA.FullGraphicCount)
|
||||
{
|
||||
do
|
||||
@ -766,9 +763,6 @@ bool8 S9xDoDMA (uint8 Channel)
|
||||
break;
|
||||
|
||||
case 0x19: // VMDATAH
|
||||
#ifndef CORRECT_VRAM_READS
|
||||
IPPU.FirstVRAMRead = TRUE;
|
||||
#endif
|
||||
if (!PPU.VMA.FullGraphicCount)
|
||||
{
|
||||
do
|
||||
@ -837,9 +831,6 @@ bool8 S9xDoDMA (uint8 Channel)
|
||||
if (d->BAddress == 0x18)
|
||||
{
|
||||
// VMDATAL
|
||||
#ifndef CORRECT_VRAM_READS
|
||||
IPPU.FirstVRAMRead = TRUE;
|
||||
#endif
|
||||
if (!PPU.VMA.FullGraphicCount)
|
||||
{
|
||||
switch (b)
|
||||
@ -1282,7 +1273,7 @@ bool8 S9xDoDMA (uint8 Channel)
|
||||
}
|
||||
}
|
||||
|
||||
if ((CPU.Flags & NMI_FLAG) && (Timings.NMITriggerPos != 0xffff))
|
||||
if (CPU.NMILine && (Timings.NMITriggerPos != 0xffff))
|
||||
{
|
||||
Timings.NMITriggerPos = CPU.Cycles + Timings.NMIDMADelay;
|
||||
if (Timings.NMITriggerPos >= Timings.H_Max)
|
||||
@ -1373,10 +1364,7 @@ static inline bool8 HDMAReadLineCount (int d)
|
||||
|
||||
void S9xStartHDMA (void)
|
||||
{
|
||||
if (Settings.DisableHDMA)
|
||||
PPU.HDMA = 0;
|
||||
else
|
||||
PPU.HDMA = Memory.FillRAM[0x420c];
|
||||
PPU.HDMA = Memory.FillRAM[0x420c];
|
||||
|
||||
#ifdef DEBUGGER
|
||||
missing.hdma_this_frame = PPU.HDMA;
|
||||
|
@ -202,6 +202,7 @@ void S9xResetSuperFX (void)
|
||||
SuperFX.speedPerLine = (uint32) (0.417 * 10.5e6 * ((1.0 / (float) Memory.ROMFramesPerSecond) / ((float) (Timings.V_Max))));
|
||||
SuperFX.oneLineDone = FALSE;
|
||||
SuperFX.vFlags = 0;
|
||||
CPU.IRQExternal = FALSE;
|
||||
FxReset(&SuperFX);
|
||||
}
|
||||
|
||||
@ -299,13 +300,10 @@ uint8 S9xGetSuperFX (uint16 address)
|
||||
uint8 byte;
|
||||
|
||||
byte = Memory.FillRAM[address];
|
||||
#ifdef CPU_SHUTDOWN
|
||||
if (address == 0x3030)
|
||||
CPU.WaitAddress = CPU.PBPCAtOpcodeStart;
|
||||
#endif
|
||||
|
||||
if (address == 0x3031)
|
||||
{
|
||||
S9xClearIRQ(GSU_IRQ_SOURCE);
|
||||
CPU.IRQExternal = FALSE;
|
||||
Memory.FillRAM[0x3031] = byte & 0x7f;
|
||||
}
|
||||
|
||||
@ -320,7 +318,7 @@ void S9xSuperFXExec (void)
|
||||
|
||||
uint16 GSUStatus = Memory.FillRAM[0x3000 + GSU_SFR] | (Memory.FillRAM[0x3000 + GSU_SFR + 1] << 8);
|
||||
if ((GSUStatus & (FLG_G | FLG_IRQ)) == FLG_IRQ)
|
||||
S9xSetIRQ(GSU_IRQ_SOURCE);
|
||||
CPU.IRQExternal = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -178,7 +178,8 @@
|
||||
#ifndef _FXEMU_H_
|
||||
#define _FXEMU_H_
|
||||
|
||||
#ifndef ZSNES_FX
|
||||
#define FX_BREAKPOINT (-1)
|
||||
#define FX_ERROR_ILLEGAL_ADDRESS (-2)
|
||||
|
||||
// The FxInfo_s structure, the link between the FxEmulator and the Snes Emulator
|
||||
struct FxInfo_s
|
||||
@ -196,41 +197,12 @@ struct FxInfo_s
|
||||
extern struct FxInfo_s SuperFX;
|
||||
|
||||
void S9xInitSuperFX (void);
|
||||
void S9xResetSuperFX (void);
|
||||
void S9xSuperFXExec (void);
|
||||
void S9xSetSuperFX (uint8, uint16);
|
||||
uint8 S9xGetSuperFX (uint16);
|
||||
void fx_flushCache (void);
|
||||
void fx_computeScreenPointers (void);
|
||||
uint32 fx_run (uint32);
|
||||
|
||||
#define FX_BREAKPOINT (-1)
|
||||
#define FX_ERROR_ILLEGAL_ADDRESS (-2)
|
||||
|
||||
#else
|
||||
|
||||
#define S9xSetSuperFX S9xSuperFXWriteReg
|
||||
#define S9xGetSuperFX S9xSuperFXReadReg
|
||||
|
||||
START_EXTERN_C
|
||||
extern uint8 *SFXPlotTable;
|
||||
|
||||
void S9xSuperFXWriteReg (uint8, uint32);
|
||||
uint8 S9xSuperFXReadReg (uint32);
|
||||
void S9xSuperFXPreSaveState (void);
|
||||
void S9xSuperFXPostSaveState (void);
|
||||
void S9xSuperFXPostLoadState (void);
|
||||
END_EXTERN_C
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef ZSNES_FX
|
||||
START_EXTERN_C
|
||||
#endif
|
||||
|
||||
void S9xResetSuperFX (void);
|
||||
void S9xSuperFXExec (void);
|
||||
|
||||
#ifdef ZSNES_FX
|
||||
END_EXTERN_C
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -178,8 +178,6 @@
|
||||
#ifndef _FXINST_H_
|
||||
#define _FXINST_H_
|
||||
|
||||
#ifndef ZSNES_FX
|
||||
|
||||
/*
|
||||
* FxChip(GSU) register space specification
|
||||
* (Register address space 3000-32ff)
|
||||
@ -542,5 +540,3 @@ extern void (*fx_OpcodeTable[]) (void);
|
||||
#define BRANCH_DELAY_RELATIVE
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -187,12 +187,12 @@
|
||||
#include "seta.h"
|
||||
#include "bsx.h"
|
||||
|
||||
#if (S9X_ACCURACY_LEVEL >= 2)
|
||||
|
||||
#define addCyclesInMemoryAccess \
|
||||
if (!CPU.InDMAorHDMA) \
|
||||
{ \
|
||||
CPU.PrevCycles = CPU.Cycles; \
|
||||
CPU.Cycles += speed; \
|
||||
S9xCheckInterrupts(); \
|
||||
while (CPU.Cycles >= CPU.NextEvent) \
|
||||
S9xDoHEventProcessing(); \
|
||||
}
|
||||
@ -200,23 +200,13 @@
|
||||
#define addCyclesInMemoryAccess_x2 \
|
||||
if (!CPU.InDMAorHDMA) \
|
||||
{ \
|
||||
CPU.PrevCycles = CPU.Cycles; \
|
||||
CPU.Cycles += speed << 1; \
|
||||
S9xCheckInterrupts(); \
|
||||
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)
|
||||
@ -247,10 +237,6 @@ inline uint8 S9xGetByte (uint32 Address)
|
||||
|
||||
if (GetAddress >= (uint8 *) CMemory::MAP_LAST)
|
||||
{
|
||||
#ifdef CPU_SHUTDOWN
|
||||
if (Memory.BlockIsRAM[block])
|
||||
CPU.WaitAddress = CPU.PBPCAtOpcodeStart;
|
||||
#endif
|
||||
byte = *(GetAddress + (Address & 0xffff));
|
||||
addCyclesInMemoryAccess;
|
||||
return (byte);
|
||||
@ -379,10 +365,6 @@ inline uint16 S9xGetWord (uint32 Address, enum s9xwrap_t w = WRAP_NONE)
|
||||
|
||||
if (GetAddress >= (uint8 *) CMemory::MAP_LAST)
|
||||
{
|
||||
#ifdef CPU_SHUTDOWN
|
||||
if (Memory.BlockIsRAM[block])
|
||||
CPU.WaitAddress = CPU.PBPCAtOpcodeStart;
|
||||
#endif
|
||||
word = READ_WORD(GetAddress + (Address & 0xffff));
|
||||
addCyclesInMemoryAccess_x2;
|
||||
return (word);
|
||||
@ -510,33 +492,14 @@ inline uint16 S9xGetWord (uint32 Address, enum s9xwrap_t w = WRAP_NONE)
|
||||
|
||||
inline void S9xSetByte (uint8 Byte, uint32 Address)
|
||||
{
|
||||
#ifdef CPU_SHUTDOWN
|
||||
CPU.WaitAddress = 0xffffffff;
|
||||
#endif
|
||||
|
||||
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)
|
||||
{
|
||||
if (SetAddress == SA1.WaitByteAddress1 || SetAddress == SA1.WaitByteAddress2)
|
||||
{
|
||||
SA1.Executing = SA1.S9xOpcodes != NULL;
|
||||
SA1.WaitCounter = 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
*(SetAddress + (Address & 0xffff)) = Byte;
|
||||
addCyclesInMemoryAccess;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
@ -593,7 +556,6 @@ inline void S9xSetByte (uint8 Byte, uint32 Address)
|
||||
|
||||
case CMemory::MAP_SA1RAM:
|
||||
*(Memory.SRAM + (Address & 0xffff)) = Byte;
|
||||
SA1.Executing = !SA1.Waiting;
|
||||
addCyclesInMemoryAccess;
|
||||
return;
|
||||
|
||||
@ -670,33 +632,14 @@ inline void S9xSetWord (uint16 Word, uint32 Address, enum s9xwrap_t w = WRAP_NON
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CPU_SHUTDOWN
|
||||
CPU.WaitAddress = 0xffffffff;
|
||||
#endif
|
||||
|
||||
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)
|
||||
{
|
||||
if (SetAddress == SA1.WaitByteAddress1 || SetAddress == SA1.WaitByteAddress2)
|
||||
{
|
||||
SA1.Executing = SA1.S9xOpcodes != NULL;
|
||||
SA1.WaitCounter = 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
WRITE_WORD(SetAddress + (Address & 0xffff), Word);
|
||||
addCyclesInMemoryAccess_x2;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
@ -806,7 +749,6 @@ inline void S9xSetWord (uint16 Word, uint32 Address, enum s9xwrap_t w = WRAP_NON
|
||||
|
||||
case CMemory::MAP_SA1RAM:
|
||||
WRITE_WORD(Memory.SRAM + (Address & 0xffff), Word);
|
||||
SA1.Executing = !SA1.Waiting;
|
||||
addCyclesInMemoryAccess_x2;
|
||||
return;
|
||||
|
||||
|
@ -209,6 +209,8 @@ struct SDSP3 DSP3;
|
||||
struct SDSP4 DSP4;
|
||||
struct SSA1 SA1;
|
||||
struct SSA1Registers SA1Registers;
|
||||
struct FxRegs_s GSU;
|
||||
struct FxInfo_s SuperFX;
|
||||
struct SST010 ST010;
|
||||
struct SST011 ST011;
|
||||
struct SST018 ST018;
|
||||
@ -228,10 +230,6 @@ struct Missing missing;
|
||||
#endif
|
||||
struct SCheatData Cheat;
|
||||
struct Watch watches[16];
|
||||
#ifndef ZSNES_FX
|
||||
struct FxRegs_s GSU;
|
||||
struct FxInfo_s SuperFX;
|
||||
#endif
|
||||
CMemory Memory;
|
||||
|
||||
char String[513];
|
||||
@ -244,15 +242,6 @@ 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;
|
||||
uint8 *RegRAM = NULL;
|
||||
#endif
|
||||
#ifdef ZSNES_FX
|
||||
uint8 *SFXPlotTable = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef GFX_MULTI_FORMAT
|
||||
uint32 RED_LOW_BIT_MASK = RED_LOW_BIT_MASK_RGB565;
|
||||
uint32 GREEN_LOW_BIT_MASK = GREEN_LOW_BIT_MASK_RGB565;
|
||||
|
@ -1144,21 +1144,11 @@ bool8 CMemory::Init (void)
|
||||
BIOSROM = ROM + 0x300000; // BS
|
||||
BSRAM = ROM + 0x400000; // BS
|
||||
|
||||
#if defined(ZSNES_FX) || defined(ZSNES_C4)
|
||||
::ROM = ROM;
|
||||
::SRAM = SRAM;
|
||||
::RegRAM = FillRAM;
|
||||
#endif
|
||||
|
||||
#ifdef ZSNES_FX
|
||||
SFXPlotTable = ROM + 0x400000;
|
||||
#else
|
||||
SuperFX.pvRegisters = FillRAM + 0x3000;
|
||||
SuperFX.nRamBanks = 2; // Most only use 1. 1=64KB=512Mb, 2=128KB=1024Mb
|
||||
SuperFX.pvRam = SRAM;
|
||||
SuperFX.nRomBanks = (2 * 1024 * 1024) / (32 * 1024);
|
||||
SuperFX.pvRom = (uint8 *) ROM;
|
||||
#endif
|
||||
|
||||
PostRomInitFunc = NULL;
|
||||
|
||||
@ -2280,10 +2270,8 @@ void CMemory::InitROM (void)
|
||||
Settings.SETA = 0;
|
||||
Settings.SRTC = FALSE;
|
||||
Settings.BS = FALSE;
|
||||
#ifndef ZSNES_FX
|
||||
|
||||
SuperFX.nRomBanks = CalculatedSize >> 15;
|
||||
#endif
|
||||
SA1.Executing = FALSE;
|
||||
|
||||
//// Parse ROM header and read ROM informatoin
|
||||
|
||||
@ -2409,9 +2397,7 @@ void CMemory::InitROM (void)
|
||||
case 0x1520:
|
||||
case 0x1A20:
|
||||
Settings.SuperFX = TRUE;
|
||||
#ifndef ZSNES_FX
|
||||
S9xInitSuperFX();
|
||||
#endif
|
||||
if (ROM[0x7FDA] == 0x33)
|
||||
SRAMSize = ROM[0x7FBD];
|
||||
else
|
||||
@ -3510,7 +3496,6 @@ bool8 CMemory::match_id (const char *str)
|
||||
|
||||
void CMemory::ApplyROMFixes (void)
|
||||
{
|
||||
Settings.Shutdown = Settings.ShutdownMaster;
|
||||
Settings.BlockInvalidVRAMAccess = Settings.BlockInvalidVRAMAccessMaster;
|
||||
|
||||
//// Warnings
|
||||
@ -3587,6 +3572,7 @@ 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;
|
||||
Timings.IRQTriggerCycles = 10;
|
||||
|
||||
if (!Settings.DisableGameSpecificHacks)
|
||||
{
|
||||
@ -3601,14 +3587,6 @@ void CMemory::ApplyROMFixes (void)
|
||||
|
||||
if (!Settings.DisableGameSpecificHacks)
|
||||
{
|
||||
// Opcode-based emulators cannot escape from "reading $4211/BPL" infinite loop...
|
||||
// The true IRQ can be triggered inside an opcode.
|
||||
if (match_na("TRAVERSE")) // Traverse - Starlight & Prairie
|
||||
{
|
||||
Timings.IRQPendCount = 1;
|
||||
printf("IRQ count hack: %d\n", Timings.IRQPendCount);
|
||||
}
|
||||
|
||||
// An infinite loop reads $4212 and waits V-blank end, whereas VIRQ is set V=0.
|
||||
// If Snes9x succeeds to escape from the loop before jumping into the IRQ handler, the game goes further.
|
||||
// If Snes9x jumps into the IRQ handler before escaping from the loop,
|
||||
@ -3618,12 +3596,6 @@ 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)
|
||||
@ -3636,242 +3608,6 @@ void CMemory::ApplyROMFixes (void)
|
||||
}
|
||||
}
|
||||
|
||||
//// CPU speed-ups (CPU_Shutdown())
|
||||
|
||||
// Force disabling a speed-up hack
|
||||
// Games which spool sound samples between the SNES and sound CPU using
|
||||
// H-DMA as the sample is playing.
|
||||
if (match_na("EARTHWORM JIM 2") || // Earth Worm Jim 2
|
||||
match_na("PRIMAL RAGE") || // Primal Rage
|
||||
match_na("CLAY FIGHTER") || // Clay Fighter
|
||||
match_na("ClayFighter 2") || // Clay Fighter 2
|
||||
match_na("WeaponLord") || // Weapon Lord
|
||||
match_nn("WAR 2410") || // War 2410
|
||||
match_id("ARF") || // Star Ocean
|
||||
match_id("A4WJ") || // Mini Yonku Shining Scorpion - Let's & Go!!
|
||||
match_nn("NHL") ||
|
||||
match_nc("MADDEN"))
|
||||
{
|
||||
if (Settings.Shutdown)
|
||||
printf("Disabled CPU shutdown hack.\n");
|
||||
Settings.Shutdown = FALSE;
|
||||
}
|
||||
|
||||
// SA-1
|
||||
SA1.WaitAddress = 0xffffffff;
|
||||
SA1.WaitByteAddress1 = NULL;
|
||||
SA1.WaitByteAddress2 = NULL;
|
||||
|
||||
if (Settings.SA1)
|
||||
{
|
||||
// Itoi Shigesato no Bass Tsuri No.1 (J)
|
||||
if (match_id("ZBPJ"))
|
||||
{
|
||||
SA1.WaitAddress = 0x0093f1;
|
||||
SA1.WaitByteAddress1 = FillRAM + 0x304a;
|
||||
}
|
||||
|
||||
// Daisenryaku Expert WWII (J)
|
||||
if (match_id("AEVJ"))
|
||||
{
|
||||
SA1.WaitAddress = 0x0ed18d;
|
||||
SA1.WaitByteAddress1 = FillRAM + 0x3000;
|
||||
}
|
||||
|
||||
// Derby Jockey 2 (J)
|
||||
if (match_id("A2DJ"))
|
||||
{
|
||||
SA1.WaitAddress = 0x008b62;
|
||||
}
|
||||
|
||||
// Dragon Ball Z - Hyper Dimension (J)
|
||||
if (match_id("AZIJ"))
|
||||
{
|
||||
SA1.WaitAddress = 0x008083;
|
||||
SA1.WaitByteAddress1 = FillRAM + 0x3020;
|
||||
}
|
||||
|
||||
// SD Gundam G NEXT (J)
|
||||
if (match_id("ZX3J"))
|
||||
{
|
||||
SA1.WaitAddress = 0x0087f2;
|
||||
SA1.WaitByteAddress1 = FillRAM + 0x30c4;
|
||||
}
|
||||
|
||||
// Shougi no Hanamichi (J)
|
||||
if (match_id("AARJ"))
|
||||
{
|
||||
SA1.WaitAddress = 0xc1f85a;
|
||||
SA1.WaitByteAddress1 = SRAM + 0x0c64;
|
||||
SA1.WaitByteAddress2 = SRAM + 0x0c66;
|
||||
}
|
||||
|
||||
// Asahi Shinbun Rensai Katou Hifumi Kudan Shougi Shingiryu (J)
|
||||
if (match_id("A23J"))
|
||||
{
|
||||
SA1.WaitAddress = 0xc25037;
|
||||
SA1.WaitByteAddress1 = SRAM + 0x0c06;
|
||||
SA1.WaitByteAddress2 = SRAM + 0x0c08;
|
||||
}
|
||||
|
||||
// Taikyoku Igo - Idaten (J)
|
||||
if (match_id("AIIJ"))
|
||||
{
|
||||
SA1.WaitAddress = 0xc100be;
|
||||
SA1.WaitByteAddress1 = SRAM + 0x1002;
|
||||
SA1.WaitByteAddress2 = SRAM + 0x1004;
|
||||
}
|
||||
|
||||
// Takemiya Masaki Kudan no Igo Taishou (J)
|
||||
if (match_id("AITJ"))
|
||||
{
|
||||
SA1.WaitAddress = 0x0080b7;
|
||||
}
|
||||
|
||||
// J. League '96 Dream Stadium (J)
|
||||
if (match_id("AJ6J"))
|
||||
{
|
||||
SA1.WaitAddress = 0xc0f74a;
|
||||
}
|
||||
|
||||
// Jumpin' Derby (J)
|
||||
if (match_id("AJUJ"))
|
||||
{
|
||||
SA1.WaitAddress = 0x00d926;
|
||||
}
|
||||
|
||||
// Kakinoki Shougi (J)
|
||||
if (match_id("AKAJ"))
|
||||
{
|
||||
SA1.WaitAddress = 0x00f070;
|
||||
}
|
||||
|
||||
// Hoshi no Kirby 3 (J), Kirby's Dream Land 3 (U)
|
||||
if (match_id("AFJJ") || match_id("AFJE"))
|
||||
{
|
||||
SA1.WaitAddress = 0x0082d4;
|
||||
SA1.WaitByteAddress1 = SRAM + 0x72a4;
|
||||
}
|
||||
|
||||
// Hoshi no Kirby - Super Deluxe (J)
|
||||
if (match_id("AKFJ"))
|
||||
{
|
||||
SA1.WaitAddress = 0x008c93;
|
||||
SA1.WaitByteAddress1 = FillRAM + 0x300a;
|
||||
SA1.WaitByteAddress2 = FillRAM + 0x300e;
|
||||
}
|
||||
|
||||
// Kirby Super Star (U)
|
||||
if (match_id("AKFE"))
|
||||
{
|
||||
SA1.WaitAddress = 0x008cb8;
|
||||
SA1.WaitByteAddress1 = FillRAM + 0x300a;
|
||||
SA1.WaitByteAddress2 = FillRAM + 0x300e;
|
||||
}
|
||||
|
||||
// Super Mario RPG (J), (U)
|
||||
if (match_id("ARWJ") || match_id("ARWE"))
|
||||
{
|
||||
SA1.WaitAddress = 0xc0816f;
|
||||
SA1.WaitByteAddress1 = FillRAM + 0x3000;
|
||||
}
|
||||
|
||||
// Marvelous (J)
|
||||
if (match_id("AVRJ"))
|
||||
{
|
||||
SA1.WaitAddress = 0x0085f2;
|
||||
SA1.WaitByteAddress1 = FillRAM + 0x3024;
|
||||
}
|
||||
|
||||
// Harukanaru Augusta 3 - Masters New (J)
|
||||
if (match_id("AO3J"))
|
||||
{
|
||||
SA1.WaitAddress = 0x00dddb;
|
||||
SA1.WaitByteAddress1 = FillRAM + 0x37b4;
|
||||
}
|
||||
|
||||
// Jikkyou Oshaberi Parodius (J)
|
||||
if (match_id("AJOJ"))
|
||||
{
|
||||
SA1.WaitAddress = 0x8084e5;
|
||||
}
|
||||
|
||||
// Super Bomberman - Panic Bomber W (J)
|
||||
if (match_id("APBJ"))
|
||||
{
|
||||
SA1.WaitAddress = 0x00857a;
|
||||
}
|
||||
|
||||
// Pebble Beach no Hatou New - Tournament Edition (J)
|
||||
if (match_id("AONJ"))
|
||||
{
|
||||
SA1.WaitAddress = 0x00df33;
|
||||
SA1.WaitByteAddress1 = FillRAM + 0x37b4;
|
||||
}
|
||||
|
||||
// PGA European Tour (U)
|
||||
if (match_id("AEPE"))
|
||||
{
|
||||
SA1.WaitAddress = 0x003700;
|
||||
SA1.WaitByteAddress1 = FillRAM + 0x3102;
|
||||
}
|
||||
|
||||
// PGA Tour 96 (U)
|
||||
if (match_id("A3GE"))
|
||||
{
|
||||
SA1.WaitAddress = 0x003700;
|
||||
SA1.WaitByteAddress1 = FillRAM + 0x3102;
|
||||
}
|
||||
|
||||
// Power Rangers Zeo - Battle Racers (U)
|
||||
if (match_id("A4RE"))
|
||||
{
|
||||
SA1.WaitAddress = 0x009899;
|
||||
SA1.WaitByteAddress1 = FillRAM + 0x3000;
|
||||
}
|
||||
|
||||
// SD F-1 Grand Prix (J)
|
||||
if (match_id("AGFJ"))
|
||||
{
|
||||
SA1.WaitAddress = 0x0181bc;
|
||||
}
|
||||
|
||||
// Saikousoku Shikou Shougi Mahjong (J)
|
||||
if (match_id("ASYJ"))
|
||||
{
|
||||
SA1.WaitAddress = 0x00f2cc;
|
||||
SA1.WaitByteAddress1 = SRAM + 0x7ffe;
|
||||
SA1.WaitByteAddress2 = SRAM + 0x7ffc;
|
||||
}
|
||||
|
||||
// Shougi Saikyou II (J)
|
||||
if (match_id("AX2J"))
|
||||
{
|
||||
SA1.WaitAddress = 0x00d675;
|
||||
}
|
||||
|
||||
// Mini Yonku Shining Scorpion - Let's & Go!! (J)
|
||||
if (match_id("A4WJ"))
|
||||
{
|
||||
SA1.WaitAddress = 0xc048be;
|
||||
}
|
||||
|
||||
// Shin Shougi Club (J)
|
||||
if (match_id("AHJJ"))
|
||||
{
|
||||
SA1.WaitAddress = 0xc1002a;
|
||||
SA1.WaitByteAddress1 = SRAM + 0x0806;
|
||||
SA1.WaitByteAddress2 = SRAM + 0x0808;
|
||||
}
|
||||
|
||||
// rest games:
|
||||
// Habu Meijin no Omoshiro Shougi (J)
|
||||
// Hayashi Kaihou Kudan no Igo Taidou (J)
|
||||
// Shougi Saikyou (J)
|
||||
// Super Robot Wars Gaiden (J)
|
||||
// Super Shougi 3 - Kitaihei (J)
|
||||
}
|
||||
|
||||
//// SRAM initial value
|
||||
|
||||
if (!Settings.DisableGameSpecificHacks)
|
||||
|
@ -360,14 +360,6 @@ struct SMulti
|
||||
extern CMemory Memory;
|
||||
extern SMulti Multi;
|
||||
|
||||
#if defined(ZSNES_FX) || defined(ZSNES_C4)
|
||||
START_EXTERN_C
|
||||
extern uint8 *ROM;
|
||||
extern uint8 *SRAM;
|
||||
extern uint8 *RegRAM;
|
||||
END_EXTERN_C
|
||||
#endif
|
||||
|
||||
void S9xAutoSaveSRAM (void);
|
||||
bool8 LoadZip(const char *, int32 *, int32 *, uint8 *);
|
||||
|
||||
|
@ -745,7 +745,8 @@ int S9xMovieUnfreeze (uint8 *buf, uint32 size)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (current_frame > Movie.MaxFrame || current_sample > Movie.MaxSample || memcmp(Movie.InputBuffer, ptr, space_needed))
|
||||
uint32 space_processed = (Movie.BytesPerSample * (current_sample + 1));
|
||||
if (current_frame > Movie.MaxFrame || current_sample > Movie.MaxSample || memcmp(Movie.InputBuffer, ptr, space_processed))
|
||||
return (SNAPSHOT_INCONSISTENT);
|
||||
|
||||
change_state(MOVIE_STATE_PLAY);
|
||||
@ -786,8 +787,8 @@ int S9xMovieOpen (const char *filename, bool8 read_only)
|
||||
|
||||
read_movie_extrarominfo(fd, &Movie);
|
||||
|
||||
fn = dup(fileno(fd));
|
||||
fclose(fd);
|
||||
fflush(fd);
|
||||
fn = fileno(fd);
|
||||
|
||||
store_previous_settings();
|
||||
restore_movie_settings();
|
||||
@ -853,7 +854,6 @@ int S9xMovieCreate (const char *filename, uint8 controllers_mask, uint8 opts, co
|
||||
{
|
||||
FILE *fd;
|
||||
STREAM stream;
|
||||
int fn;
|
||||
|
||||
if (controllers_mask == 0)
|
||||
return (WRONG_FORMAT);
|
||||
@ -902,10 +902,9 @@ int S9xMovieCreate (const char *filename, uint8 controllers_mask, uint8 opts, co
|
||||
|
||||
write_movie_extrarominfo(fd, &Movie);
|
||||
|
||||
fn = dup(fileno(fd));
|
||||
fclose(fd);
|
||||
|
||||
stream = REOPEN_STREAM(fn, "ab");
|
||||
stream = OPEN_STREAM(filename, "ab");
|
||||
if (!stream)
|
||||
return (FILE_NOT_FOUND);
|
||||
|
||||
@ -1009,9 +1008,10 @@ int S9xMovieGetInfo (const char *filename, struct MovieInfo *info)
|
||||
strncpy(info->ROMName, local_movie.ROMName, 23);
|
||||
|
||||
fclose(fd);
|
||||
|
||||
if (access(filename, W_OK))
|
||||
if ((fd = fopen(filename, "r+")) == NULL)
|
||||
info->ReadOnly = true;
|
||||
else
|
||||
fclose(fd);
|
||||
|
||||
return (SUCCESS);
|
||||
}
|
||||
|
@ -204,9 +204,6 @@ static inline void S9xLatchCounters (bool force)
|
||||
#ifdef DEBUGGER
|
||||
missing.h_v_latch = 1;
|
||||
#endif
|
||||
#if 0 // #ifdef CPU_SHUTDOWN
|
||||
CPU.WaitAddress = CPU.PCAtOpcodeStart;
|
||||
#endif
|
||||
|
||||
PPU.HVBeamCounterLatched = 1;
|
||||
PPU.VBeamPosLatched = (uint16) CPU.V_Counter;
|
||||
@ -245,9 +242,6 @@ static inline void S9xTryGunLatch (bool force)
|
||||
#ifdef DEBUGGER
|
||||
missing.h_v_latch = 1;
|
||||
#endif
|
||||
#if 0 // #ifdef CPU_SHUTDOWN
|
||||
CPU.WaitAddress = CPU.PCAtOpcodeStart;
|
||||
#endif
|
||||
|
||||
PPU.HVBeamCounterLatched = 1;
|
||||
PPU.VBeamPosLatched = (uint16) PPU.GunVLatch;
|
||||
@ -260,72 +254,16 @@ static inline void S9xTryGunLatch (bool force)
|
||||
}
|
||||
}
|
||||
|
||||
void S9xCheckMissingHTimerPosition (int32 hc)
|
||||
{
|
||||
if (PPU.HTimerPosition == hc)
|
||||
{
|
||||
if (PPU.HTimerEnabled && (!PPU.VTimerEnabled || (CPU.V_Counter == PPU.VTimerPosition)))
|
||||
S9xSetIRQ(PPU_IRQ_SOURCE);
|
||||
else
|
||||
if (PPU.VTimerEnabled && (CPU.V_Counter == PPU.VTimerPosition))
|
||||
S9xSetIRQ(PPU_IRQ_SOURCE);
|
||||
}
|
||||
}
|
||||
|
||||
void S9xCheckMissingHTimerHalt (int32 hc_from, int32 range)
|
||||
{
|
||||
if ((PPU.HTimerPosition >= hc_from) && (PPU.HTimerPosition < (hc_from + range)))
|
||||
{
|
||||
if (PPU.HTimerEnabled && (!PPU.VTimerEnabled || (CPU.V_Counter == PPU.VTimerPosition)))
|
||||
CPU.IRQPending = 1;
|
||||
else
|
||||
if (PPU.VTimerEnabled && (CPU.V_Counter == PPU.VTimerPosition))
|
||||
CPU.IRQPending = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void S9xCheckMissingHTimerRange (int32 hc_from, int32 range)
|
||||
{
|
||||
if ((PPU.HTimerPosition >= hc_from) && (PPU.HTimerPosition < (hc_from + range)))
|
||||
{
|
||||
if (PPU.HTimerEnabled && (!PPU.VTimerEnabled || (CPU.V_Counter == PPU.VTimerPosition)))
|
||||
S9xSetIRQ(PPU_IRQ_SOURCE);
|
||||
else
|
||||
if (PPU.VTimerEnabled && (CPU.V_Counter == PPU.VTimerPosition))
|
||||
S9xSetIRQ(PPU_IRQ_SOURCE);
|
||||
}
|
||||
}
|
||||
|
||||
void S9xUpdateHVTimerPosition (void)
|
||||
{
|
||||
if (PPU.HTimerEnabled)
|
||||
PPU.HTimerPosition = PPU.IRQHBeamPos * ONE_DOT_CYCLE + Timings.IRQTriggerCycles;
|
||||
if (Timings.H_Max == Timings.H_Max_Master) // 1364
|
||||
{
|
||||
#ifdef DEBUGGER
|
||||
missing.hirq_pos = PPU.IRQHBeamPos;
|
||||
#endif
|
||||
if (PPU.IRQHBeamPos != 0)
|
||||
{
|
||||
// IRQ_read
|
||||
PPU.HTimerPosition = PPU.IRQHBeamPos * ONE_DOT_CYCLE;
|
||||
if (Timings.H_Max == Timings.H_Max_Master) // 1364
|
||||
{
|
||||
if (PPU.IRQHBeamPos > 322)
|
||||
PPU.HTimerPosition += (ONE_DOT_CYCLE / 2);
|
||||
if (PPU.IRQHBeamPos > 326)
|
||||
PPU.HTimerPosition += (ONE_DOT_CYCLE / 2);
|
||||
}
|
||||
|
||||
PPU.HTimerPosition += 14;
|
||||
// /IRQ
|
||||
PPU.HTimerPosition += 4;
|
||||
// after CPU executing
|
||||
PPU.HTimerPosition += 6;
|
||||
}
|
||||
else
|
||||
PPU.HTimerPosition = 10 + 4 + 6;
|
||||
if (PPU.IRQHBeamPos > 322)
|
||||
PPU.HTimerPosition += (ONE_DOT_CYCLE / 2);
|
||||
if (PPU.IRQHBeamPos > 326)
|
||||
PPU.HTimerPosition += (ONE_DOT_CYCLE / 2);
|
||||
}
|
||||
else
|
||||
PPU.HTimerPosition = 10 + 4 + 6;
|
||||
|
||||
PPU.VTimerPosition = PPU.IRQVBeamPos;
|
||||
|
||||
@ -338,111 +276,9 @@ void S9xUpdateHVTimerPosition (void)
|
||||
PPU.VTimerPosition = 0;
|
||||
}
|
||||
|
||||
if (PPU.HTimerPosition < CPU.Cycles)
|
||||
{
|
||||
switch (CPU.WhichEvent)
|
||||
{
|
||||
case HC_IRQ_1_3_EVENT:
|
||||
CPU.WhichEvent = HC_HDMA_START_EVENT;
|
||||
CPU.NextEvent = Timings.HDMAStart;
|
||||
break;
|
||||
|
||||
case HC_IRQ_3_5_EVENT:
|
||||
CPU.WhichEvent = HC_HCOUNTER_MAX_EVENT;
|
||||
CPU.NextEvent = Timings.H_Max;
|
||||
break;
|
||||
|
||||
case HC_IRQ_5_7_EVENT:
|
||||
CPU.WhichEvent = HC_HDMA_INIT_EVENT;
|
||||
CPU.NextEvent = Timings.HDMAInit;
|
||||
break;
|
||||
|
||||
case HC_IRQ_7_9_EVENT:
|
||||
CPU.WhichEvent = HC_RENDER_EVENT;
|
||||
CPU.NextEvent = Timings.RenderPos;
|
||||
break;
|
||||
|
||||
case HC_IRQ_9_A_EVENT:
|
||||
CPU.WhichEvent = HC_WRAM_REFRESH_EVENT;
|
||||
CPU.NextEvent = Timings.WRAMRefreshPos;
|
||||
break;
|
||||
|
||||
case HC_IRQ_A_1_EVENT:
|
||||
CPU.WhichEvent = HC_HBLANK_START_EVENT;
|
||||
CPU.NextEvent = Timings.HBlankStart;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
if ((PPU.HTimerPosition < CPU.NextEvent) || (!(CPU.WhichEvent & 1) && (PPU.HTimerPosition == CPU.NextEvent)))
|
||||
{
|
||||
CPU.NextEvent = PPU.HTimerPosition;
|
||||
|
||||
switch (CPU.WhichEvent)
|
||||
{
|
||||
case HC_HDMA_START_EVENT:
|
||||
CPU.WhichEvent = HC_IRQ_1_3_EVENT;
|
||||
break;
|
||||
|
||||
case HC_HCOUNTER_MAX_EVENT:
|
||||
CPU.WhichEvent = HC_IRQ_3_5_EVENT;
|
||||
break;
|
||||
|
||||
case HC_HDMA_INIT_EVENT:
|
||||
CPU.WhichEvent = HC_IRQ_5_7_EVENT;
|
||||
break;
|
||||
|
||||
case HC_RENDER_EVENT:
|
||||
CPU.WhichEvent = HC_IRQ_7_9_EVENT;
|
||||
break;
|
||||
|
||||
case HC_WRAM_REFRESH_EVENT:
|
||||
CPU.WhichEvent = HC_IRQ_9_A_EVENT;
|
||||
break;
|
||||
|
||||
case HC_HBLANK_START_EVENT:
|
||||
CPU.WhichEvent = HC_IRQ_A_1_EVENT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (CPU.WhichEvent)
|
||||
{
|
||||
case HC_IRQ_1_3_EVENT:
|
||||
CPU.WhichEvent = HC_HDMA_START_EVENT;
|
||||
CPU.NextEvent = Timings.HDMAStart;
|
||||
break;
|
||||
|
||||
case HC_IRQ_3_5_EVENT:
|
||||
CPU.WhichEvent = HC_HCOUNTER_MAX_EVENT;
|
||||
CPU.NextEvent = Timings.H_Max;
|
||||
break;
|
||||
|
||||
case HC_IRQ_5_7_EVENT:
|
||||
CPU.WhichEvent = HC_HDMA_INIT_EVENT;
|
||||
CPU.NextEvent = Timings.HDMAInit;
|
||||
break;
|
||||
|
||||
case HC_IRQ_7_9_EVENT:
|
||||
CPU.WhichEvent = HC_RENDER_EVENT;
|
||||
CPU.NextEvent = Timings.RenderPos;
|
||||
break;
|
||||
|
||||
case HC_IRQ_9_A_EVENT:
|
||||
CPU.WhichEvent = HC_WRAM_REFRESH_EVENT;
|
||||
CPU.NextEvent = Timings.WRAMRefreshPos;
|
||||
break;
|
||||
|
||||
case HC_IRQ_A_1_EVENT:
|
||||
CPU.WhichEvent = HC_HBLANK_START_EVENT;
|
||||
CPU.NextEvent = Timings.HBlankStart;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUGGER
|
||||
S9xTraceFormattedMessage("--- IRQ settings: H:%d V:%d (%04d, %03d)", PPU.HTimerEnabled, PPU.VTimerEnabled, PPU.HTimerPosition, PPU.VTimerPosition);
|
||||
S9xTraceFormattedMessage("--- IRQ Timer set HTimer:%d Pos:%04d VTimer:%d Pos:%03d",
|
||||
PPU.HTimerEnabled, PPU.HTimerPosition, PPU.VTimerEnabled, PPU.VTimerPosition);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -787,7 +623,7 @@ void S9xSetPPU (uint8 Byte, uint16 Address)
|
||||
case 0x2116: // VMADDL
|
||||
PPU.VMA.Address &= 0xff00;
|
||||
PPU.VMA.Address |= Byte;
|
||||
#ifdef CORRECT_VRAM_READS
|
||||
|
||||
if (PPU.VMA.FullGraphicCount)
|
||||
{
|
||||
uint32 addr = PPU.VMA.Address;
|
||||
@ -797,15 +633,13 @@ void S9xSetPPU (uint8 Byte, uint16 Address)
|
||||
}
|
||||
else
|
||||
IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((PPU.VMA.Address << 1) & 0xffff));
|
||||
#else
|
||||
IPPU.FirstVRAMRead = TRUE;
|
||||
#endif
|
||||
|
||||
break;
|
||||
|
||||
case 0x2117: // VMADDH
|
||||
PPU.VMA.Address &= 0x00ff;
|
||||
PPU.VMA.Address |= Byte << 8;
|
||||
#ifdef CORRECT_VRAM_READS
|
||||
|
||||
if (PPU.VMA.FullGraphicCount)
|
||||
{
|
||||
uint32 addr = PPU.VMA.Address;
|
||||
@ -815,22 +649,14 @@ void S9xSetPPU (uint8 Byte, uint16 Address)
|
||||
}
|
||||
else
|
||||
IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((PPU.VMA.Address << 1) & 0xffff));
|
||||
#else
|
||||
IPPU.FirstVRAMRead = TRUE;
|
||||
#endif
|
||||
|
||||
break;
|
||||
|
||||
case 0x2118: // VMDATAL
|
||||
#ifndef CORRECT_VRAM_READS
|
||||
IPPU.FirstVRAMRead = TRUE;
|
||||
#endif
|
||||
REGISTER_2118(Byte);
|
||||
break;
|
||||
|
||||
case 0x2119: // VMDATAH
|
||||
#ifndef CORRECT_VRAM_READS
|
||||
IPPU.FirstVRAMRead = TRUE;
|
||||
#endif
|
||||
REGISTER_2119(Byte);
|
||||
break;
|
||||
|
||||
@ -1382,7 +1208,6 @@ uint8 S9xGetPPU (uint16 Address)
|
||||
return (PPU.OpenBus1 = byte);
|
||||
|
||||
case 0x2139: // VMDATALREAD
|
||||
#ifdef CORRECT_VRAM_READS
|
||||
byte = IPPU.VRAMReadBuffer & 0xff;
|
||||
if (!PPU.VMA.High)
|
||||
{
|
||||
@ -1398,33 +1223,13 @@ uint8 S9xGetPPU (uint16 Address)
|
||||
|
||||
PPU.VMA.Address += PPU.VMA.Increment;
|
||||
}
|
||||
#else
|
||||
if (IPPU.FirstVRAMRead)
|
||||
byte = Memory.VRAM[(PPU.VMA.Address << 1) & 0xffff];
|
||||
else
|
||||
if (PPU.VMA.FullGraphicCount)
|
||||
{
|
||||
uint32 addr = PPU.VMA.Address - 1;
|
||||
uint32 rem = addr & PPU.VMA.Mask1;
|
||||
uint32 address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3);
|
||||
byte = Memory.VRAM[((address << 1) - 2) & 0xffff];
|
||||
}
|
||||
else
|
||||
byte = Memory.VRAM[((PPU.VMA.Address << 1) - 2) & 0xffff];
|
||||
|
||||
if (!PPU.VMA.High)
|
||||
{
|
||||
PPU.VMA.Address += PPU.VMA.Increment;
|
||||
IPPU.FirstVRAMRead = FALSE;
|
||||
}
|
||||
#endif
|
||||
#ifdef DEBUGGER
|
||||
missing.vram_read = 1;
|
||||
#endif
|
||||
return (PPU.OpenBus1 = byte);
|
||||
|
||||
case 0x213a: // VMDATAHREAD
|
||||
#ifdef CORRECT_VRAM_READS
|
||||
byte = (IPPU.VRAMReadBuffer >> 8) & 0xff;
|
||||
if (PPU.VMA.High)
|
||||
{
|
||||
@ -1440,26 +1245,6 @@ uint8 S9xGetPPU (uint16 Address)
|
||||
|
||||
PPU.VMA.Address += PPU.VMA.Increment;
|
||||
}
|
||||
#else
|
||||
if (IPPU.FirstVRAMRead)
|
||||
byte = Memory.VRAM[((PPU.VMA.Address << 1) + 1) & 0xffff];
|
||||
else
|
||||
if (PPU.VMA.FullGraphicCount)
|
||||
{
|
||||
uint32 addr = PPU.VMA.Address - 1;
|
||||
uint32 rem = addr & PPU.VMA.Mask1;
|
||||
uint32 address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3);
|
||||
byte = Memory.VRAM[((address << 1) - 1) & 0xffff];
|
||||
}
|
||||
else
|
||||
byte = Memory.VRAM[((PPU.VMA.Address << 1) - 1) & 0xffff];
|
||||
|
||||
if (PPU.VMA.High)
|
||||
{
|
||||
PPU.VMA.Address += PPU.VMA.Increment;
|
||||
IPPU.FirstVRAMRead = FALSE;
|
||||
}
|
||||
#endif
|
||||
#ifdef DEBUGGER
|
||||
missing.vram_read = 1;
|
||||
#endif
|
||||
@ -1697,14 +1482,14 @@ void S9xSetCPU (uint8 Byte, uint16 Address)
|
||||
else
|
||||
PPU.HTimerEnabled = FALSE;
|
||||
|
||||
S9xUpdateHVTimerPosition();
|
||||
if (CPU.IRQLine && !PPU.HTimerEnabled && PPU.VTimerEnabled)
|
||||
CPU.IRQTransition = TRUE;
|
||||
|
||||
// The case that IRQ will trigger in an instruction such as STA $4200.
|
||||
// FIXME: not true but good enough for Snes9x, I think.
|
||||
S9xCheckMissingHTimerRange(CPU.PrevCycles, CPU.Cycles - CPU.PrevCycles);
|
||||
|
||||
if (!(Byte & 0x30))
|
||||
S9xClearIRQ(PPU_IRQ_SOURCE);
|
||||
if (!PPU.HTimerEnabled && !PPU.VTimerEnabled)
|
||||
{
|
||||
CPU.IRQLine = FALSE;
|
||||
CPU.IRQTransition = FALSE;
|
||||
}
|
||||
|
||||
// NMI can trigger immediately during VBlank as long as NMI_read ($4210) wasn't cleard.
|
||||
if ((Byte & 0x80) && !(Memory.FillRAM[0x4200] & 0x80) &&
|
||||
@ -1712,7 +1497,7 @@ void S9xSetCPU (uint8 Byte, uint16 Address)
|
||||
{
|
||||
// FIXME: triggered at HC+=6, checked just before the final CPU cycle,
|
||||
// then, when to call S9xOpcode_NMI()?
|
||||
CPU.Flags |= NMI_FLAG;
|
||||
CPU.NMILine = TRUE;
|
||||
Timings.NMITriggerPos = CPU.Cycles + 6 + 6;
|
||||
}
|
||||
|
||||
@ -1826,8 +1611,6 @@ void S9xSetCPU (uint8 Byte, uint16 Address)
|
||||
case 0x420c: // HDMAEN
|
||||
if (CPU.InDMAorHDMA)
|
||||
return;
|
||||
if (Settings.DisableHDMA)
|
||||
Byte = 0;
|
||||
Memory.FillRAM[0x420c] = Byte;
|
||||
// Yoshi's Island, Genjyu Ryodan, Mortal Kombat, Tales of Phantasia
|
||||
PPU.HDMA = Byte & ~PPU.HDMAEnded;
|
||||
@ -1854,17 +1637,7 @@ void S9xSetCPU (uint8 Byte, uint16 Address)
|
||||
break;
|
||||
|
||||
case 0x4210: // RDNMI
|
||||
#if 0
|
||||
Memory.FillRAM[0x4210] = Model->_5A22;
|
||||
#endif
|
||||
return;
|
||||
|
||||
case 0x4211: // TIMEUP
|
||||
#if 0
|
||||
S9xClearIRQ(PPU_IRQ_SOURCE);
|
||||
#endif
|
||||
return;
|
||||
|
||||
case 0x4212: // HVBJOY
|
||||
case 0x4213: // RDIO
|
||||
case 0x4214: // RDDIVL
|
||||
@ -1980,22 +1753,17 @@ uint8 S9xGetCPU (uint16 Address)
|
||||
switch (Address)
|
||||
{
|
||||
case 0x4210: // RDNMI
|
||||
#ifdef CPU_SHUTDOWN
|
||||
CPU.WaitAddress = CPU.PBPCAtOpcodeStart;
|
||||
#endif
|
||||
byte = Memory.FillRAM[0x4210];
|
||||
Memory.FillRAM[0x4210] = Model->_5A22;
|
||||
return ((byte & 0x80) | (OpenBus & 0x70) | Model->_5A22);
|
||||
|
||||
case 0x4211: // TIMEUP
|
||||
byte = (CPU.IRQActive & PPU_IRQ_SOURCE) ? 0x80 : 0;
|
||||
S9xClearIRQ(PPU_IRQ_SOURCE);
|
||||
byte = CPU.IRQLine ? 0x80 : 0;
|
||||
CPU.IRQLine = FALSE;
|
||||
CPU.IRQTransition = FALSE;
|
||||
return (byte | (OpenBus & 0x7f));
|
||||
|
||||
case 0x4212: // HVBJOY
|
||||
#ifdef CPU_SHUTDOWN
|
||||
CPU.WaitAddress = CPU.PBPCAtOpcodeStart;
|
||||
#endif
|
||||
return (REGISTER_4212() | (OpenBus & 0x3e));
|
||||
|
||||
case 0x4213: // RDIO
|
||||
@ -2189,11 +1957,7 @@ void S9xSoftResetPPU (void)
|
||||
ZeroMemory(IPPU.TileCached[TILE_2BIT_ODD], MAX_2BIT_TILES);
|
||||
ZeroMemory(IPPU.TileCached[TILE_4BIT_EVEN], MAX_4BIT_TILES);
|
||||
ZeroMemory(IPPU.TileCached[TILE_4BIT_ODD], MAX_4BIT_TILES);
|
||||
#ifdef CORRECT_VRAM_READS
|
||||
IPPU.VRAMReadBuffer = 0; // XXX: FIXME: anything better?
|
||||
#else
|
||||
IPPU.FirstVRAMRead = FALSE;
|
||||
#endif
|
||||
IPPU.Interlace = FALSE;
|
||||
IPPU.InterlaceOBJ = FALSE;
|
||||
IPPU.DoubleWidthPixels = FALSE;
|
||||
|
@ -197,11 +197,6 @@
|
||||
#define CLIP_XOR 2
|
||||
#define CLIP_XNOR 3
|
||||
|
||||
#define PPU_IRQ_SOURCE (1 << 1)
|
||||
#define GSU_IRQ_SOURCE (1 << 2)
|
||||
#define SA1_IRQ_SOURCE (1 << 7)
|
||||
#define SA1_DMA_IRQ_SOURCE (1 << 5)
|
||||
|
||||
struct ClipData
|
||||
{
|
||||
uint8 Count;
|
||||
@ -218,11 +213,7 @@ struct InternalPPU
|
||||
bool8 DirectColourMapsNeedRebuild;
|
||||
uint8 *TileCache[7];
|
||||
uint8 *TileCached[7];
|
||||
#ifdef CORRECT_VRAM_READS
|
||||
uint16 VRAMReadBuffer;
|
||||
#else
|
||||
bool8 FirstVRAMRead;
|
||||
#endif
|
||||
bool8 Interlace;
|
||||
bool8 InterlaceOBJ;
|
||||
bool8 PseudoHires;
|
||||
@ -385,9 +376,6 @@ uint8 S9xGetPPU (uint16);
|
||||
void S9xSetCPU (uint8, uint16);
|
||||
uint8 S9xGetCPU (uint16);
|
||||
void S9xUpdateHVTimerPosition (void);
|
||||
void S9xCheckMissingHTimerPosition (int32);
|
||||
void S9xCheckMissingHTimerRange (int32, int32);
|
||||
void S9xCheckMissingHTimerHalt (int32, int32);
|
||||
void S9xFixColourBrightness (void);
|
||||
void S9xDoAutoJoypad (void);
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -198,32 +198,33 @@ struct SSA1
|
||||
uint8 _Zero;
|
||||
uint8 _Negative;
|
||||
uint8 _Overflow;
|
||||
bool8 CPUExecuting;
|
||||
uint32 ShiftedPB;
|
||||
uint32 ShiftedDB;
|
||||
|
||||
uint32 Flags;
|
||||
int32 Cycles;
|
||||
int32 PrevCycles;
|
||||
uint8 *PCBase;
|
||||
bool8 IRQActive;
|
||||
bool8 Waiting;
|
||||
bool8 WaitingForInterrupt;
|
||||
uint32 WaitAddress;
|
||||
uint32 WaitCounter;
|
||||
uint32 PBPCAtOpcodeStart;
|
||||
uint8 *WaitByteAddress1;
|
||||
uint8 *WaitByteAddress2;
|
||||
|
||||
uint8 *Map[MEMMAP_NUM_BLOCKS];
|
||||
uint8 *WriteMap[MEMMAP_NUM_BLOCKS];
|
||||
uint8 *BWRAM;
|
||||
|
||||
bool8 Executing;
|
||||
bool8 overflow;
|
||||
bool8 in_char_dma;
|
||||
int16 op1;
|
||||
int16 op2;
|
||||
bool8 TimerIRQLastState;
|
||||
uint16 HTimerIRQPos;
|
||||
uint16 VTimerIRQPos;
|
||||
int16 HCounter;
|
||||
int16 VCounter;
|
||||
int16 PrevHCounter;
|
||||
int32 MemSpeed;
|
||||
int32 MemSpeedx2;
|
||||
int32 arithmetic_op;
|
||||
int64 sum;
|
||||
uint16 op1;
|
||||
uint16 op2;
|
||||
uint64 sum;
|
||||
bool8 overflow;
|
||||
uint8 VirtualBitmapFormat;
|
||||
uint8 variable_bit_pos;
|
||||
};
|
||||
@ -263,13 +264,8 @@ uint8 S9xGetSA1 (uint32);
|
||||
void S9xSetSA1 (uint8, uint32);
|
||||
void S9xSA1Init (void);
|
||||
void S9xSA1MainLoop (void);
|
||||
void S9xSA1ExecuteDuringSleep (void);
|
||||
void S9xSA1PostLoadState (void);
|
||||
|
||||
#define SNES_IRQ_SOURCE (1 << 7)
|
||||
#define TIMER_IRQ_SOURCE (1 << 6)
|
||||
#define DMA_IRQ_SOURCE (1 << 5)
|
||||
|
||||
static inline void S9xSA1UnpackStatus (void)
|
||||
{
|
||||
SA1._Zero = (SA1Registers.PL & Zero) == 0;
|
||||
|
@ -1,303 +1,399 @@
|
||||
/***********************************************************************************
|
||||
Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
|
||||
|
||||
(c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com),
|
||||
Jerremy Koot (jkoot@snes9x.com)
|
||||
|
||||
(c) Copyright 2002 - 2004 Matthew Kendora
|
||||
|
||||
(c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org)
|
||||
|
||||
(c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/)
|
||||
|
||||
(c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net)
|
||||
|
||||
(c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca),
|
||||
Kris Bleakley (codeviolation@hotmail.com)
|
||||
|
||||
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
|
||||
Nach (n-a-c-h@users.sourceforge.net),
|
||||
zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2006 - 2007 nitsuja
|
||||
|
||||
(c) Copyright 2009 - 2010 BearOso,
|
||||
OV2
|
||||
|
||||
|
||||
BS-X C emulator code
|
||||
(c) Copyright 2005 - 2006 Dreamer Nom,
|
||||
zones
|
||||
|
||||
C4 x86 assembler and some C emulation code
|
||||
(c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com),
|
||||
Nach,
|
||||
zsKnight (zsknight@zsnes.com)
|
||||
|
||||
C4 C++ code
|
||||
(c) Copyright 2003 - 2006 Brad Jorsch,
|
||||
Nach
|
||||
|
||||
DSP-1 emulator code
|
||||
(c) Copyright 1998 - 2006 _Demo_,
|
||||
Andreas Naive (andreasnaive@gmail.com),
|
||||
Gary Henderson,
|
||||
Ivar (ivar@snes9x.com),
|
||||
John Weidman,
|
||||
Kris Bleakley,
|
||||
Matthew Kendora,
|
||||
Nach,
|
||||
neviksti (neviksti@hotmail.com)
|
||||
|
||||
DSP-2 emulator code
|
||||
(c) Copyright 2003 John Weidman,
|
||||
Kris Bleakley,
|
||||
Lord Nightmare (lord_nightmare@users.sourceforge.net),
|
||||
Matthew Kendora,
|
||||
neviksti
|
||||
|
||||
DSP-3 emulator code
|
||||
(c) Copyright 2003 - 2006 John Weidman,
|
||||
Kris Bleakley,
|
||||
Lancer,
|
||||
z80 gaiden
|
||||
|
||||
DSP-4 emulator code
|
||||
(c) Copyright 2004 - 2006 Dreamer Nom,
|
||||
John Weidman,
|
||||
Kris Bleakley,
|
||||
Nach,
|
||||
z80 gaiden
|
||||
|
||||
OBC1 emulator code
|
||||
(c) Copyright 2001 - 2004 zsKnight,
|
||||
pagefault (pagefault@zsnes.com),
|
||||
Kris Bleakley
|
||||
Ported from x86 assembler to C by sanmaiwashi
|
||||
|
||||
SPC7110 and RTC C++ emulator code used in 1.39-1.51
|
||||
(c) Copyright 2002 Matthew Kendora with research by
|
||||
zsKnight,
|
||||
John Weidman,
|
||||
Dark Force
|
||||
|
||||
SPC7110 and RTC C++ emulator code used in 1.52+
|
||||
(c) Copyright 2009 byuu,
|
||||
neviksti
|
||||
|
||||
S-DD1 C emulator code
|
||||
(c) Copyright 2003 Brad Jorsch with research by
|
||||
Andreas Naive,
|
||||
John Weidman
|
||||
|
||||
S-RTC C emulator code
|
||||
(c) Copyright 2001 - 2006 byuu,
|
||||
John Weidman
|
||||
|
||||
ST010 C++ emulator code
|
||||
(c) Copyright 2003 Feather,
|
||||
John Weidman,
|
||||
Kris Bleakley,
|
||||
Matthew Kendora
|
||||
|
||||
Super FX x86 assembler emulator code
|
||||
(c) Copyright 1998 - 2003 _Demo_,
|
||||
pagefault,
|
||||
zsKnight
|
||||
|
||||
Super FX C emulator code
|
||||
(c) Copyright 1997 - 1999 Ivar,
|
||||
Gary Henderson,
|
||||
John Weidman
|
||||
|
||||
Sound emulator code used in 1.5-1.51
|
||||
(c) Copyright 1998 - 2003 Brad Martin
|
||||
(c) Copyright 1998 - 2006 Charles Bilyue'
|
||||
|
||||
Sound emulator code used in 1.52+
|
||||
(c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com)
|
||||
|
||||
SH assembler code partly based on x86 assembler code
|
||||
(c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
|
||||
|
||||
2xSaI filter
|
||||
(c) Copyright 1999 - 2001 Derek Liauw Kie Fa
|
||||
|
||||
HQ2x, HQ3x, HQ4x filters
|
||||
(c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com)
|
||||
|
||||
NTSC filter
|
||||
(c) Copyright 2006 - 2007 Shay Green
|
||||
|
||||
GTK+ GUI code
|
||||
(c) Copyright 2004 - 2010 BearOso
|
||||
|
||||
Win32 GUI code
|
||||
(c) Copyright 2003 - 2006 blip,
|
||||
funkyass,
|
||||
Matthew Kendora,
|
||||
Nach,
|
||||
nitsuja
|
||||
(c) Copyright 2009 - 2010 OV2
|
||||
|
||||
Mac OS GUI code
|
||||
(c) Copyright 1998 - 2001 John Stiles
|
||||
(c) Copyright 2001 - 2010 zones
|
||||
|
||||
|
||||
Specific ports contains the works of other authors. See headers in
|
||||
individual files.
|
||||
|
||||
|
||||
Snes9x homepage: http://www.snes9x.com/
|
||||
|
||||
Permission to use, copy, modify and/or distribute Snes9x in both binary
|
||||
and source form, for non-commercial purposes, is hereby granted without
|
||||
fee, providing that this license information and copyright notice appear
|
||||
with all copies and any derived work.
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event shall the authors be held liable for any damages
|
||||
arising from the use of this software or it's derivatives.
|
||||
|
||||
Snes9x is freeware for PERSONAL USE only. Commercial users should
|
||||
seek permission of the copyright holders first. Commercial use includes,
|
||||
but is not limited to, charging money for Snes9x or software derived from
|
||||
Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
|
||||
using Snes9x as a promotion for your commercial product.
|
||||
|
||||
The copyright holders request that bug fixes and improvements to the code
|
||||
should be forwarded to them so everyone can benefit from the modifications
|
||||
in future versions.
|
||||
|
||||
Super NES and Super Nintendo Entertainment System are trademarks of
|
||||
Nintendo Co., Limited and its subsidiary companies.
|
||||
***********************************************************************************/
|
||||
|
||||
|
||||
#include "snes9x.h"
|
||||
#include "memmap.h"
|
||||
|
||||
#define CPU SA1
|
||||
#define ICPU SA1
|
||||
#define Registers SA1Registers
|
||||
#define OpenBus SA1OpenBus
|
||||
#define S9xGetByte S9xSA1GetByte
|
||||
#define S9xGetWord S9xSA1GetWord
|
||||
#define S9xSetByte S9xSA1SetByte
|
||||
#define S9xSetWord S9xSA1SetWord
|
||||
#define S9xSetPCBase S9xSA1SetPCBase
|
||||
#define S9xOpcodesM1X1 S9xSA1OpcodesM1X1
|
||||
#define S9xOpcodesM1X0 S9xSA1OpcodesM1X0
|
||||
#define S9xOpcodesM0X1 S9xSA1OpcodesM0X1
|
||||
#define S9xOpcodesM0X0 S9xSA1OpcodesM0X0
|
||||
#define S9xOpcodesE1 S9xSA1OpcodesE1
|
||||
#define S9xOpcodesSlow S9xSA1OpcodesSlow
|
||||
#define S9xOpcode_IRQ S9xSA1Opcode_IRQ
|
||||
#define S9xOpcode_NMI S9xSA1Opcode_NMI
|
||||
#define S9xUnpackStatus S9xSA1UnpackStatus
|
||||
#define S9xPackStatus S9xSA1PackStatus
|
||||
#define S9xFixCycles S9xSA1FixCycles
|
||||
#define Immediate8 SA1Immediate8
|
||||
#define Immediate16 SA1Immediate16
|
||||
#define Relative SA1Relative
|
||||
#define RelativeLong SA1RelativeLong
|
||||
#define Absolute SA1Absolute
|
||||
#define AbsoluteLong SA1AbsoluteLong
|
||||
#define AbsoluteIndirect SA1AbsoluteIndirect
|
||||
#define AbsoluteIndirectLong SA1AbsoluteIndirectLong
|
||||
#define AbsoluteIndexedIndirect SA1AbsoluteIndexedIndirect
|
||||
#define Direct SA1Direct
|
||||
#define DirectIndirectIndexed SA1DirectIndirectIndexed
|
||||
#define DirectIndirectIndexedLong SA1DirectIndirectIndexedLong
|
||||
#define DirectIndexedIndirect SA1DirectIndexedIndirect
|
||||
#define DirectIndexedX SA1DirectIndexedX
|
||||
#define DirectIndexedY SA1DirectIndexedY
|
||||
#define AbsoluteIndexedX SA1AbsoluteIndexedX
|
||||
#define AbsoluteIndexedY SA1AbsoluteIndexedY
|
||||
#define AbsoluteLongIndexedX SA1AbsoluteLongIndexedX
|
||||
#define DirectIndirect SA1DirectIndirect
|
||||
#define DirectIndirectLong SA1DirectIndirectLong
|
||||
#define StackRelative SA1StackRelative
|
||||
#define StackRelativeIndirectIndexed SA1StackRelativeIndirectIndexed
|
||||
|
||||
//#undef CPU_SHUTDOWN
|
||||
#define SA1_OPCODES
|
||||
|
||||
#include "cpuops.cpp"
|
||||
|
||||
|
||||
void S9xSA1MainLoop (void)
|
||||
{
|
||||
if (SA1.Flags & NMI_FLAG)
|
||||
{
|
||||
if (Memory.FillRAM[0x2200] & 0x10)
|
||||
{
|
||||
SA1.Flags &= ~NMI_FLAG;
|
||||
Memory.FillRAM[0x2301] |= 0x10;
|
||||
|
||||
if (SA1.WaitingForInterrupt)
|
||||
{
|
||||
SA1.WaitingForInterrupt = FALSE;
|
||||
SA1Registers.PCw++;
|
||||
}
|
||||
|
||||
S9xSA1Opcode_NMI();
|
||||
}
|
||||
}
|
||||
|
||||
if (SA1.Flags & IRQ_FLAG)
|
||||
{
|
||||
if (SA1.IRQActive)
|
||||
{
|
||||
if (SA1.WaitingForInterrupt)
|
||||
{
|
||||
SA1.WaitingForInterrupt = FALSE;
|
||||
SA1Registers.PCw++;
|
||||
}
|
||||
|
||||
if (!SA1CheckFlag(IRQ))
|
||||
S9xSA1Opcode_IRQ();
|
||||
}
|
||||
else
|
||||
SA1.Flags &= ~IRQ_FLAG;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3 && SA1.Executing; i++)
|
||||
{
|
||||
#ifdef DEBUGGER
|
||||
if (SA1.Flags & TRACE_FLAG)
|
||||
S9xSA1Trace();
|
||||
#endif
|
||||
|
||||
#ifdef CPU_SHUTDOWN
|
||||
SA1.PBPCAtOpcodeStart = SA1Registers.PBPC;
|
||||
#endif
|
||||
|
||||
register uint8 Op;
|
||||
register struct SOpcodes *Opcodes;
|
||||
|
||||
if (SA1.PCBase)
|
||||
{
|
||||
SA1OpenBus = Op = SA1.PCBase[Registers.PCw];
|
||||
Opcodes = SA1.S9xOpcodes;
|
||||
}
|
||||
else
|
||||
{
|
||||
Op = S9xSA1GetByte(Registers.PBPC);
|
||||
Opcodes = S9xOpcodesSlow;
|
||||
}
|
||||
|
||||
if ((SA1Registers.PCw & MEMMAP_MASK) + SA1.S9xOpLengths[Op] >= MEMMAP_BLOCK_SIZE)
|
||||
{
|
||||
uint32 oldPC = SA1Registers.PBPC;
|
||||
S9xSA1SetPCBase(SA1Registers.PBPC);
|
||||
SA1Registers.PBPC = oldPC;
|
||||
Opcodes = S9xSA1OpcodesSlow;
|
||||
}
|
||||
|
||||
Registers.PCw++;
|
||||
(*Opcodes[Op].S9xOpcode)();
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************************
|
||||
Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
|
||||
|
||||
(c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com),
|
||||
Jerremy Koot (jkoot@snes9x.com)
|
||||
|
||||
(c) Copyright 2002 - 2004 Matthew Kendora
|
||||
|
||||
(c) Copyright 2002 - 2005 Peter Bortas (peter@bortas.org)
|
||||
|
||||
(c) Copyright 2004 - 2005 Joel Yliluoma (http://iki.fi/bisqwit/)
|
||||
|
||||
(c) Copyright 2001 - 2006 John Weidman (jweidman@slip.net)
|
||||
|
||||
(c) Copyright 2002 - 2006 funkyass (funkyass@spam.shaw.ca),
|
||||
Kris Bleakley (codeviolation@hotmail.com)
|
||||
|
||||
(c) Copyright 2002 - 2010 Brad Jorsch (anomie@users.sourceforge.net),
|
||||
Nach (n-a-c-h@users.sourceforge.net),
|
||||
zones (kasumitokoduck@yahoo.com)
|
||||
|
||||
(c) Copyright 2006 - 2007 nitsuja
|
||||
|
||||
(c) Copyright 2009 - 2010 BearOso,
|
||||
OV2
|
||||
|
||||
|
||||
BS-X C emulator code
|
||||
(c) Copyright 2005 - 2006 Dreamer Nom,
|
||||
zones
|
||||
|
||||
C4 x86 assembler and some C emulation code
|
||||
(c) Copyright 2000 - 2003 _Demo_ (_demo_@zsnes.com),
|
||||
Nach,
|
||||
zsKnight (zsknight@zsnes.com)
|
||||
|
||||
C4 C++ code
|
||||
(c) Copyright 2003 - 2006 Brad Jorsch,
|
||||
Nach
|
||||
|
||||
DSP-1 emulator code
|
||||
(c) Copyright 1998 - 2006 _Demo_,
|
||||
Andreas Naive (andreasnaive@gmail.com),
|
||||
Gary Henderson,
|
||||
Ivar (ivar@snes9x.com),
|
||||
John Weidman,
|
||||
Kris Bleakley,
|
||||
Matthew Kendora,
|
||||
Nach,
|
||||
neviksti (neviksti@hotmail.com)
|
||||
|
||||
DSP-2 emulator code
|
||||
(c) Copyright 2003 John Weidman,
|
||||
Kris Bleakley,
|
||||
Lord Nightmare (lord_nightmare@users.sourceforge.net),
|
||||
Matthew Kendora,
|
||||
neviksti
|
||||
|
||||
DSP-3 emulator code
|
||||
(c) Copyright 2003 - 2006 John Weidman,
|
||||
Kris Bleakley,
|
||||
Lancer,
|
||||
z80 gaiden
|
||||
|
||||
DSP-4 emulator code
|
||||
(c) Copyright 2004 - 2006 Dreamer Nom,
|
||||
John Weidman,
|
||||
Kris Bleakley,
|
||||
Nach,
|
||||
z80 gaiden
|
||||
|
||||
OBC1 emulator code
|
||||
(c) Copyright 2001 - 2004 zsKnight,
|
||||
pagefault (pagefault@zsnes.com),
|
||||
Kris Bleakley
|
||||
Ported from x86 assembler to C by sanmaiwashi
|
||||
|
||||
SPC7110 and RTC C++ emulator code used in 1.39-1.51
|
||||
(c) Copyright 2002 Matthew Kendora with research by
|
||||
zsKnight,
|
||||
John Weidman,
|
||||
Dark Force
|
||||
|
||||
SPC7110 and RTC C++ emulator code used in 1.52+
|
||||
(c) Copyright 2009 byuu,
|
||||
neviksti
|
||||
|
||||
S-DD1 C emulator code
|
||||
(c) Copyright 2003 Brad Jorsch with research by
|
||||
Andreas Naive,
|
||||
John Weidman
|
||||
|
||||
S-RTC C emulator code
|
||||
(c) Copyright 2001 - 2006 byuu,
|
||||
John Weidman
|
||||
|
||||
ST010 C++ emulator code
|
||||
(c) Copyright 2003 Feather,
|
||||
John Weidman,
|
||||
Kris Bleakley,
|
||||
Matthew Kendora
|
||||
|
||||
Super FX x86 assembler emulator code
|
||||
(c) Copyright 1998 - 2003 _Demo_,
|
||||
pagefault,
|
||||
zsKnight
|
||||
|
||||
Super FX C emulator code
|
||||
(c) Copyright 1997 - 1999 Ivar,
|
||||
Gary Henderson,
|
||||
John Weidman
|
||||
|
||||
Sound emulator code used in 1.5-1.51
|
||||
(c) Copyright 1998 - 2003 Brad Martin
|
||||
(c) Copyright 1998 - 2006 Charles Bilyue'
|
||||
|
||||
Sound emulator code used in 1.52+
|
||||
(c) Copyright 2004 - 2007 Shay Green (gblargg@gmail.com)
|
||||
|
||||
SH assembler code partly based on x86 assembler code
|
||||
(c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se)
|
||||
|
||||
2xSaI filter
|
||||
(c) Copyright 1999 - 2001 Derek Liauw Kie Fa
|
||||
|
||||
HQ2x, HQ3x, HQ4x filters
|
||||
(c) Copyright 2003 Maxim Stepin (maxim@hiend3d.com)
|
||||
|
||||
NTSC filter
|
||||
(c) Copyright 2006 - 2007 Shay Green
|
||||
|
||||
GTK+ GUI code
|
||||
(c) Copyright 2004 - 2010 BearOso
|
||||
|
||||
Win32 GUI code
|
||||
(c) Copyright 2003 - 2006 blip,
|
||||
funkyass,
|
||||
Matthew Kendora,
|
||||
Nach,
|
||||
nitsuja
|
||||
(c) Copyright 2009 - 2010 OV2
|
||||
|
||||
Mac OS GUI code
|
||||
(c) Copyright 1998 - 2001 John Stiles
|
||||
(c) Copyright 2001 - 2010 zones
|
||||
|
||||
|
||||
Specific ports contains the works of other authors. See headers in
|
||||
individual files.
|
||||
|
||||
|
||||
Snes9x homepage: http://www.snes9x.com/
|
||||
|
||||
Permission to use, copy, modify and/or distribute Snes9x in both binary
|
||||
and source form, for non-commercial purposes, is hereby granted without
|
||||
fee, providing that this license information and copyright notice appear
|
||||
with all copies and any derived work.
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event shall the authors be held liable for any damages
|
||||
arising from the use of this software or it's derivatives.
|
||||
|
||||
Snes9x is freeware for PERSONAL USE only. Commercial users should
|
||||
seek permission of the copyright holders first. Commercial use includes,
|
||||
but is not limited to, charging money for Snes9x or software derived from
|
||||
Snes9x, including Snes9x or derivatives in commercial game bundles, and/or
|
||||
using Snes9x as a promotion for your commercial product.
|
||||
|
||||
The copyright holders request that bug fixes and improvements to the code
|
||||
should be forwarded to them so everyone can benefit from the modifications
|
||||
in future versions.
|
||||
|
||||
Super NES and Super Nintendo Entertainment System are trademarks of
|
||||
Nintendo Co., Limited and its subsidiary companies.
|
||||
***********************************************************************************/
|
||||
|
||||
|
||||
#include "snes9x.h"
|
||||
#include "memmap.h"
|
||||
|
||||
#define CPU SA1
|
||||
#define ICPU SA1
|
||||
#define Registers SA1Registers
|
||||
#define OpenBus SA1OpenBus
|
||||
#define S9xGetByte S9xSA1GetByte
|
||||
#define S9xGetWord S9xSA1GetWord
|
||||
#define S9xSetByte S9xSA1SetByte
|
||||
#define S9xSetWord S9xSA1SetWord
|
||||
#define S9xSetPCBase S9xSA1SetPCBase
|
||||
#define S9xOpcodesM1X1 S9xSA1OpcodesM1X1
|
||||
#define S9xOpcodesM1X0 S9xSA1OpcodesM1X0
|
||||
#define S9xOpcodesM0X1 S9xSA1OpcodesM0X1
|
||||
#define S9xOpcodesM0X0 S9xSA1OpcodesM0X0
|
||||
#define S9xOpcodesE1 S9xSA1OpcodesE1
|
||||
#define S9xOpcodesSlow S9xSA1OpcodesSlow
|
||||
#define S9xOpcode_IRQ S9xSA1Opcode_IRQ
|
||||
#define S9xOpcode_NMI S9xSA1Opcode_NMI
|
||||
#define S9xUnpackStatus S9xSA1UnpackStatus
|
||||
#define S9xPackStatus S9xSA1PackStatus
|
||||
#define S9xFixCycles S9xSA1FixCycles
|
||||
#define Immediate8 SA1Immediate8
|
||||
#define Immediate16 SA1Immediate16
|
||||
#define Relative SA1Relative
|
||||
#define RelativeLong SA1RelativeLong
|
||||
#define Absolute SA1Absolute
|
||||
#define AbsoluteLong SA1AbsoluteLong
|
||||
#define AbsoluteIndirect SA1AbsoluteIndirect
|
||||
#define AbsoluteIndirectLong SA1AbsoluteIndirectLong
|
||||
#define AbsoluteIndexedIndirect SA1AbsoluteIndexedIndirect
|
||||
#define Direct SA1Direct
|
||||
#define DirectIndirectIndexed SA1DirectIndirectIndexed
|
||||
#define DirectIndirectIndexedLong SA1DirectIndirectIndexedLong
|
||||
#define DirectIndexedIndirect SA1DirectIndexedIndirect
|
||||
#define DirectIndexedX SA1DirectIndexedX
|
||||
#define DirectIndexedY SA1DirectIndexedY
|
||||
#define AbsoluteIndexedX SA1AbsoluteIndexedX
|
||||
#define AbsoluteIndexedY SA1AbsoluteIndexedY
|
||||
#define AbsoluteLongIndexedX SA1AbsoluteLongIndexedX
|
||||
#define DirectIndirect SA1DirectIndirect
|
||||
#define DirectIndirectLong SA1DirectIndirectLong
|
||||
#define StackRelative SA1StackRelative
|
||||
#define StackRelativeIndirectIndexed SA1StackRelativeIndirectIndexed
|
||||
|
||||
#define SA1_OPCODES
|
||||
|
||||
#include "cpuops.cpp"
|
||||
|
||||
static void S9xSA1UpdateTimer (void);
|
||||
|
||||
|
||||
void S9xSA1MainLoop (void)
|
||||
{
|
||||
if (Memory.FillRAM[0x2200] & 0x60)
|
||||
{
|
||||
SA1.Cycles += 6; // FIXME
|
||||
S9xSA1UpdateTimer();
|
||||
return;
|
||||
}
|
||||
|
||||
// SA-1 NMI
|
||||
if ((Memory.FillRAM[0x2200] & 0x10) && !(Memory.FillRAM[0x220b] & 0x10))
|
||||
{
|
||||
Memory.FillRAM[0x2301] |= 0x10;
|
||||
Memory.FillRAM[0x220b] |= 0x10;
|
||||
|
||||
if (SA1.WaitingForInterrupt)
|
||||
{
|
||||
SA1.WaitingForInterrupt = FALSE;
|
||||
SA1Registers.PCw++;
|
||||
}
|
||||
|
||||
S9xSA1Opcode_NMI();
|
||||
}
|
||||
else
|
||||
if (!SA1CheckFlag(IRQ))
|
||||
{
|
||||
// SA-1 Timer IRQ
|
||||
if ((Memory.FillRAM[0x220a] & 0x40) && !(Memory.FillRAM[0x220b] & 0x40))
|
||||
{
|
||||
Memory.FillRAM[0x2301] |= 0x40;
|
||||
|
||||
if (SA1.WaitingForInterrupt)
|
||||
{
|
||||
SA1.WaitingForInterrupt = FALSE;
|
||||
SA1Registers.PCw++;
|
||||
}
|
||||
|
||||
S9xSA1Opcode_IRQ();
|
||||
}
|
||||
else
|
||||
// SA-1 DMA IRQ
|
||||
if ((Memory.FillRAM[0x220a] & 0x20) && !(Memory.FillRAM[0x220b] & 0x20))
|
||||
{
|
||||
Memory.FillRAM[0x2301] |= 0x20;
|
||||
|
||||
if (SA1.WaitingForInterrupt)
|
||||
{
|
||||
SA1.WaitingForInterrupt = FALSE;
|
||||
SA1Registers.PCw++;
|
||||
}
|
||||
|
||||
S9xSA1Opcode_IRQ();
|
||||
}
|
||||
else
|
||||
// SA-1 IRQ
|
||||
if ((Memory.FillRAM[0x2200] & 0x80) && !(Memory.FillRAM[0x220b] & 0x80))
|
||||
{
|
||||
Memory.FillRAM[0x2301] |= 0x80;
|
||||
|
||||
if (SA1.WaitingForInterrupt)
|
||||
{
|
||||
SA1.WaitingForInterrupt = FALSE;
|
||||
SA1Registers.PCw++;
|
||||
}
|
||||
|
||||
S9xSA1Opcode_IRQ();
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3 && !(Memory.FillRAM[0x2200] & 0x60); i++)
|
||||
{
|
||||
#ifdef DEBUGGER
|
||||
if (SA1.Flags & TRACE_FLAG)
|
||||
S9xSA1Trace();
|
||||
#endif
|
||||
|
||||
register uint8 Op;
|
||||
register struct SOpcodes *Opcodes;
|
||||
|
||||
if (SA1.PCBase)
|
||||
{
|
||||
SA1OpenBus = Op = SA1.PCBase[Registers.PCw];
|
||||
Opcodes = SA1.S9xOpcodes;
|
||||
}
|
||||
else
|
||||
{
|
||||
Op = S9xSA1GetByte(Registers.PBPC);
|
||||
Opcodes = S9xOpcodesSlow;
|
||||
}
|
||||
|
||||
if ((SA1Registers.PCw & MEMMAP_MASK) + SA1.S9xOpLengths[Op] >= MEMMAP_BLOCK_SIZE)
|
||||
{
|
||||
uint32 oldPC = SA1Registers.PBPC;
|
||||
S9xSA1SetPCBase(SA1Registers.PBPC);
|
||||
SA1Registers.PBPC = oldPC;
|
||||
Opcodes = S9xSA1OpcodesSlow;
|
||||
}
|
||||
|
||||
Registers.PCw++;
|
||||
(*Opcodes[Op].S9xOpcode)();
|
||||
}
|
||||
|
||||
S9xSA1UpdateTimer();
|
||||
}
|
||||
|
||||
static void S9xSA1UpdateTimer (void) // FIXME
|
||||
{
|
||||
SA1.PrevHCounter = SA1.HCounter;
|
||||
|
||||
if (Memory.FillRAM[0x2210] & 0x80)
|
||||
{
|
||||
SA1.HCounter += (SA1.Cycles - SA1.PrevCycles);
|
||||
if (SA1.HCounter >= 0x800)
|
||||
{
|
||||
SA1.HCounter -= 0x800;
|
||||
SA1.PrevHCounter -= 0x800;
|
||||
if (++SA1.VCounter >= 0x200)
|
||||
SA1.VCounter = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SA1.HCounter += (SA1.Cycles - SA1.PrevCycles);
|
||||
if (SA1.HCounter >= Timings.H_Max_Master)
|
||||
{
|
||||
SA1.HCounter -= Timings.H_Max_Master;
|
||||
SA1.PrevHCounter -= Timings.H_Max_Master;
|
||||
if (++SA1.VCounter >= Timings.V_Max_Master)
|
||||
SA1.VCounter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (SA1.Cycles >= Timings.H_Max_Master)
|
||||
SA1.Cycles -= Timings.H_Max_Master;
|
||||
|
||||
SA1.PrevCycles = SA1.Cycles;
|
||||
|
||||
bool8 thisIRQ = Memory.FillRAM[0x2210] & 0x03;
|
||||
|
||||
if (Memory.FillRAM[0x2210] & 0x01)
|
||||
{
|
||||
if (SA1.PrevHCounter >= SA1.HTimerIRQPos * ONE_DOT_CYCLE || SA1.HCounter < SA1.HTimerIRQPos * ONE_DOT_CYCLE)
|
||||
thisIRQ = FALSE;
|
||||
}
|
||||
|
||||
if (Memory.FillRAM[0x2210] & 0x02)
|
||||
{
|
||||
if (SA1.VCounter != SA1.VTimerIRQPos * ONE_DOT_CYCLE)
|
||||
thisIRQ = FALSE;
|
||||
}
|
||||
|
||||
// SA-1 Timer IRQ control
|
||||
if (!SA1.TimerIRQLastState && thisIRQ)
|
||||
{
|
||||
Memory.FillRAM[0x2301] |= 0x40;
|
||||
if (Memory.FillRAM[0x220a] & 0x40)
|
||||
{
|
||||
Memory.FillRAM[0x220b] &= ~0x40;
|
||||
#ifdef DEBUGGER
|
||||
S9xTraceFormattedMessage("--- SA-1 Timer IRQ triggered prev HC:%04d curr HC:%04d HTimer:%d Pos:%04d VTimer:%d Pos:%03d",
|
||||
SA1.PrevHCounter, SA1.HCounter,
|
||||
(Memory.FillRAM[0x2210] & 0x01) ? 1 : 0, SA1.HTimerIRQPos * ONE_DOT_CYCLE,
|
||||
(Memory.FillRAM[0x2210] & 0x02) ? 1 : 0, SA1.VTimerIRQPos);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
SA1.TimerIRQLastState = thisIRQ;
|
||||
}
|
||||
|
@ -342,7 +342,7 @@ struct SnapshotScreenshotInfo
|
||||
|
||||
static struct Obsolete
|
||||
{
|
||||
uint8 reserved;
|
||||
uint8 CPU_IRQActive;
|
||||
} Obsolete;
|
||||
|
||||
#define STRUCT struct SCPUState
|
||||
@ -353,7 +353,7 @@ static FreezeData SnapCPU[] =
|
||||
INT_ENTRY(6, PrevCycles),
|
||||
INT_ENTRY(6, V_Counter),
|
||||
INT_ENTRY(6, Flags),
|
||||
INT_ENTRY(6, IRQActive),
|
||||
OBSOLETE_INT_ENTRY(6, 7, CPU_IRQActive),
|
||||
INT_ENTRY(6, IRQPending),
|
||||
INT_ENTRY(6, MemSpeed),
|
||||
INT_ENTRY(6, MemSpeedx2),
|
||||
@ -366,9 +366,14 @@ static FreezeData SnapCPU[] =
|
||||
INT_ENTRY(6, WhichEvent),
|
||||
INT_ENTRY(6, NextEvent),
|
||||
INT_ENTRY(6, WaitingForInterrupt),
|
||||
INT_ENTRY(6, WaitAddress),
|
||||
INT_ENTRY(6, WaitCounter),
|
||||
INT_ENTRY(6, PBPCAtOpcodeStart)
|
||||
DELETED_INT_ENTRY(6, 7, WaitAddress, 4),
|
||||
DELETED_INT_ENTRY(6, 7, WaitCounter, 4),
|
||||
DELETED_INT_ENTRY(6, 7, PBPCAtOpcodeStart, 4),
|
||||
INT_ENTRY(7, NMILine),
|
||||
INT_ENTRY(7, IRQLine),
|
||||
INT_ENTRY(7, IRQTransition),
|
||||
INT_ENTRY(7, IRQLastState),
|
||||
INT_ENTRY(7, IRQExternal)
|
||||
};
|
||||
|
||||
#undef STRUCT
|
||||
@ -576,11 +581,11 @@ static FreezeData SnapTimings[] =
|
||||
INT_ENTRY(6, DMACPUSync),
|
||||
INT_ENTRY(6, NMIDMADelay),
|
||||
INT_ENTRY(6, IRQPendCount),
|
||||
INT_ENTRY(6, APUSpeedup)
|
||||
INT_ENTRY(6, APUSpeedup),
|
||||
INT_ENTRY(7, IRQTriggerCycles),
|
||||
INT_ENTRY(7, APUAllowTimeOverflow)
|
||||
};
|
||||
|
||||
#ifndef ZSNES_FX
|
||||
|
||||
#undef STRUCT
|
||||
#define STRUCT struct FxRegs_s
|
||||
|
||||
@ -642,24 +647,22 @@ static FreezeData SnapFX[] =
|
||||
INT_ENTRY(6, vSCBRDirty)
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#undef STRUCT
|
||||
#define STRUCT struct SSA1
|
||||
|
||||
static FreezeData SnapSA1[] =
|
||||
{
|
||||
INT_ENTRY(6, CPUExecuting),
|
||||
DELETED_INT_ENTRY(6, 7, CPUExecuting, 1),
|
||||
INT_ENTRY(6, ShiftedPB),
|
||||
INT_ENTRY(6, ShiftedDB),
|
||||
INT_ENTRY(6, Flags),
|
||||
INT_ENTRY(6, IRQActive),
|
||||
INT_ENTRY(6, Waiting),
|
||||
DELETED_INT_ENTRY(6, 7, IRQActive, 1),
|
||||
DELETED_INT_ENTRY(6, 7, Waiting, 1),
|
||||
INT_ENTRY(6, WaitingForInterrupt),
|
||||
INT_ENTRY(6, WaitAddress),
|
||||
INT_ENTRY(6, WaitCounter),
|
||||
INT_ENTRY(6, PBPCAtOpcodeStart),
|
||||
INT_ENTRY(6, Executing),
|
||||
DELETED_INT_ENTRY(6, 7, WaitAddress, 4),
|
||||
DELETED_INT_ENTRY(6, 7, WaitCounter, 4),
|
||||
DELETED_INT_ENTRY(6, 7, PBPCAtOpcodeStart, 4),
|
||||
DELETED_INT_ENTRY(6, 7, Executing, 1),
|
||||
INT_ENTRY(6, overflow),
|
||||
INT_ENTRY(6, in_char_dma),
|
||||
INT_ENTRY(6, op1),
|
||||
@ -667,7 +670,17 @@ static FreezeData SnapSA1[] =
|
||||
INT_ENTRY(6, arithmetic_op),
|
||||
INT_ENTRY(6, sum),
|
||||
INT_ENTRY(6, VirtualBitmapFormat),
|
||||
INT_ENTRY(6, variable_bit_pos)
|
||||
INT_ENTRY(6, variable_bit_pos),
|
||||
INT_ENTRY(7, Cycles),
|
||||
INT_ENTRY(7, PrevCycles),
|
||||
INT_ENTRY(7, TimerIRQLastState),
|
||||
INT_ENTRY(7, HTimerIRQPos),
|
||||
INT_ENTRY(7, VTimerIRQPos),
|
||||
INT_ENTRY(7, HCounter),
|
||||
INT_ENTRY(7, VCounter),
|
||||
INT_ENTRY(7, PrevHCounter),
|
||||
INT_ENTRY(7, MemSpeed),
|
||||
INT_ENTRY(7, MemSpeedx2)
|
||||
};
|
||||
|
||||
#undef STRUCT
|
||||
@ -1255,15 +1268,10 @@ bool8 S9xUnfreezeGame (const char *filename)
|
||||
void S9xFreezeToStream (STREAM stream)
|
||||
{
|
||||
char buffer[1024];
|
||||
uint8 *soundsnapshot = new uint8[SPC_SAVE_STATE_BLOCK_SIZE];
|
||||
uint8 *soundsnapshot = new uint8[SPC_SAVE_STATE_BLOCK_SIZE];
|
||||
|
||||
S9xSetSoundMute(TRUE);
|
||||
|
||||
#ifdef ZSNES_FX
|
||||
if (Settings.SuperFX)
|
||||
S9xSuperFXPreSaveState();
|
||||
#endif
|
||||
|
||||
sprintf(buffer, "%s:%04d\n", SNAPSHOT_MAGIC, SNAPSHOT_VERSION);
|
||||
WRITE_STREAM(buffer, strlen(buffer), stream);
|
||||
|
||||
@ -1298,13 +1306,11 @@ void S9xFreezeToStream (STREAM stream)
|
||||
|
||||
FreezeStruct(stream, "TIM", &Timings, SnapTimings, COUNT(SnapTimings));
|
||||
|
||||
#ifndef ZSNES_FX
|
||||
if (Settings.SuperFX)
|
||||
{
|
||||
GSU.avRegAddr = (uint8 *) &GSU.avReg;
|
||||
FreezeStruct(stream, "SFX", &GSU, SnapFX, COUNT(SnapFX));
|
||||
}
|
||||
#endif
|
||||
|
||||
if (Settings.SA1)
|
||||
{
|
||||
@ -1323,11 +1329,7 @@ void S9xFreezeToStream (STREAM stream)
|
||||
FreezeStruct(stream, "DP4", &DSP4, SnapDSP4, COUNT(SnapDSP4));
|
||||
|
||||
if (Settings.C4)
|
||||
#ifndef ZSNES_C4
|
||||
FreezeBlock (stream, "CX4", Memory.C4RAM, 8192);
|
||||
#else
|
||||
FreezeBlock (stream, "CX4", C4Ram, 8192);
|
||||
#endif
|
||||
|
||||
if (Settings.SETA == ST_010)
|
||||
FreezeStruct(stream, "ST0", &ST010, SnapST010, COUNT(SnapST010));
|
||||
@ -1405,11 +1407,6 @@ void S9xFreezeToStream (STREAM stream)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ZSNES_FX
|
||||
if (Settings.SuperFX)
|
||||
S9xSuperFXPostSaveState();
|
||||
#endif
|
||||
|
||||
S9xSetSoundMute(FALSE);
|
||||
|
||||
delete [] soundsnapshot;
|
||||
@ -1510,11 +1507,9 @@ int S9xUnfreezeFromStream (STREAM stream)
|
||||
if (result != SUCCESS)
|
||||
break;
|
||||
|
||||
#ifndef ZSNES_FX
|
||||
result = UnfreezeStructCopy(stream, "SFX", &local_superfx, SnapFX, COUNT(SnapFX), version);
|
||||
if (result != SUCCESS && Settings.SuperFX)
|
||||
break;
|
||||
#endif
|
||||
|
||||
result = UnfreezeStructCopy(stream, "SA1", &local_sa1, SnapSA1, COUNT(SnapSA1), version);
|
||||
if (result != SUCCESS && Settings.SA1)
|
||||
@ -1637,13 +1632,11 @@ int S9xUnfreezeFromStream (STREAM stream)
|
||||
|
||||
UnfreezeStructFromCopy(&Timings, SnapTimings, COUNT(SnapTimings), local_timing_data, version);
|
||||
|
||||
#ifndef ZSNES_FX
|
||||
if (local_superfx)
|
||||
{
|
||||
GSU.avRegAddr = (uint8 *) &GSU.avReg;
|
||||
UnfreezeStructFromCopy(&GSU, SnapFX, COUNT(SnapFX), local_superfx, version);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (local_sa1)
|
||||
UnfreezeStructFromCopy(&SA1, SnapSA1, COUNT(SnapSA1), local_sa1, version);
|
||||
@ -1661,11 +1654,7 @@ int S9xUnfreezeFromStream (STREAM stream)
|
||||
UnfreezeStructFromCopy(&DSP4, SnapDSP4, COUNT(SnapDSP4), local_dsp4, version);
|
||||
|
||||
if (local_cx4_data)
|
||||
#ifndef ZSNES_C4
|
||||
memcpy(Memory.C4RAM, local_cx4_data, 8192);
|
||||
#else
|
||||
memcpy(C4Ram, local_cx4_data, 8192);
|
||||
#endif
|
||||
|
||||
if (local_st010)
|
||||
UnfreezeStructFromCopy(&ST010, SnapST010, COUNT(SnapST010), local_st010, version);
|
||||
@ -1688,6 +1677,40 @@ int S9xUnfreezeFromStream (STREAM stream)
|
||||
if (local_bsx_data)
|
||||
UnfreezeStructFromCopy(&BSX, SnapBSX, COUNT(SnapBSX), local_bsx_data, version);
|
||||
|
||||
if (version < SNAPSHOT_VERSION)
|
||||
{
|
||||
printf("Converting old snapshot version %d to %d\n...", version, SNAPSHOT_VERSION);
|
||||
|
||||
CPU.NMILine = (CPU.Flags & (1 << 7)) ? TRUE : FALSE;
|
||||
CPU.IRQLine = (CPU.Flags & (1 << 11)) ? TRUE : FALSE;
|
||||
CPU.IRQTransition = FALSE;
|
||||
CPU.IRQLastState = FALSE;
|
||||
CPU.IRQExternal = (Obsolete.CPU_IRQActive & ~(1 << 1)) ? TRUE : FALSE;
|
||||
|
||||
switch (CPU.WhichEvent)
|
||||
{
|
||||
case 12: case 1: CPU.WhichEvent = 1; break;
|
||||
case 2: case 3: CPU.WhichEvent = 2; break;
|
||||
case 4: case 5: CPU.WhichEvent = 3; break;
|
||||
case 6: case 7: CPU.WhichEvent = 4; break;
|
||||
case 8: case 9: CPU.WhichEvent = 5; break;
|
||||
case 10: case 11: CPU.WhichEvent = 6; break;
|
||||
}
|
||||
|
||||
if (local_sa1) // FIXME
|
||||
{
|
||||
SA1.Cycles = SA1.PrevCycles = 0;
|
||||
SA1.TimerIRQLastState = FALSE;
|
||||
SA1.HTimerIRQPos = Memory.FillRAM[0x2212] | (Memory.FillRAM[0x2213] << 8);
|
||||
SA1.VTimerIRQPos = Memory.FillRAM[0x2214] | (Memory.FillRAM[0x2215] << 8);
|
||||
SA1.HCounter = 0;
|
||||
SA1.VCounter = 0;
|
||||
SA1.PrevHCounter = 0;
|
||||
SA1.MemSpeed = SLOW_ONE_CYCLE;
|
||||
SA1.MemSpeedx2 = SLOW_ONE_CYCLE * 2;
|
||||
}
|
||||
}
|
||||
|
||||
CPU.Flags |= old_flags & (DEBUG_MODE_FLAG | TRACE_FLAG | SINGLE_STEP_FLAG | FRAME_ADVANCE_FLAG);
|
||||
ICPU.ShiftedPB = Registers.PB << 16;
|
||||
ICPU.ShiftedDB = Registers.DB << 16;
|
||||
@ -1711,16 +1734,11 @@ int S9xUnfreezeFromStream (STREAM stream)
|
||||
|
||||
S9xControlPostLoadState(&ctl_snap);
|
||||
|
||||
#ifndef ZSNES_FX
|
||||
if (local_superfx)
|
||||
{
|
||||
GSU.pfPlot = fx_PlotTable[GSU.vMode];
|
||||
GSU.pfRpix = fx_PlotTable[GSU.vMode + 5];
|
||||
}
|
||||
#else
|
||||
if (Settings.SuperFX)
|
||||
S9xSuperFXPostLoadState();
|
||||
#endif
|
||||
|
||||
if (local_sa1 && local_sa1_registers)
|
||||
{
|
||||
@ -2280,4 +2298,3 @@ bool8 S9xSPCDump (const char *filename)
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
|
@ -179,7 +179,7 @@
|
||||
#define _SNAPSHOT_H_
|
||||
|
||||
#define SNAPSHOT_MAGIC "#!s9xsnp"
|
||||
#define SNAPSHOT_VERSION 6
|
||||
#define SNAPSHOT_VERSION 7
|
||||
|
||||
#define SUCCESS 1
|
||||
#define WRONG_FORMAT (-1)
|
||||
|
@ -186,8 +186,6 @@
|
||||
#include "65c816.h"
|
||||
#include "messages.h"
|
||||
|
||||
#define S9X_ACCURACY_LEVEL 3
|
||||
|
||||
#ifdef ZLIB
|
||||
#include <zlib.h>
|
||||
#define STREAM gzFile
|
||||
@ -263,8 +261,6 @@
|
||||
#define TRACE_FLAG (1 << 1) // debugger
|
||||
#define SINGLE_STEP_FLAG (1 << 2) // debugger
|
||||
#define BREAK_FLAG (1 << 3) // debugger
|
||||
#define NMI_FLAG (1 << 7) // CPU
|
||||
#define IRQ_FLAG (1 << 11) // CPU
|
||||
#define SCAN_KEYS_FLAG (1 << 4) // CPU
|
||||
#define HALTED_FLAG (1 << 12) // APU
|
||||
#define FRAME_ADVANCE_FLAG (1 << 9)
|
||||
@ -274,12 +270,16 @@
|
||||
|
||||
struct SCPUState
|
||||
{
|
||||
uint32 Flags;
|
||||
int32 Cycles;
|
||||
int32 PrevCycles;
|
||||
int32 V_Counter;
|
||||
uint32 Flags;
|
||||
uint8 *PCBase;
|
||||
bool8 IRQActive;
|
||||
bool8 NMILine;
|
||||
bool8 IRQLine;
|
||||
bool8 IRQTransition;
|
||||
bool8 IRQLastState;
|
||||
bool8 IRQExternal;
|
||||
int32 IRQPending;
|
||||
int32 MemSpeed;
|
||||
int32 MemSpeedx2;
|
||||
@ -293,9 +293,6 @@ struct SCPUState
|
||||
uint8 WhichEvent;
|
||||
int32 NextEvent;
|
||||
bool8 WaitingForInterrupt;
|
||||
uint32 WaitAddress;
|
||||
uint32 WaitCounter;
|
||||
uint32 PBPCAtOpcodeStart;
|
||||
uint32 AutoSaveTimer;
|
||||
bool8 SRAMModified;
|
||||
};
|
||||
@ -303,17 +300,11 @@ struct SCPUState
|
||||
enum
|
||||
{
|
||||
HC_HBLANK_START_EVENT = 1,
|
||||
HC_IRQ_1_3_EVENT = 2,
|
||||
HC_HDMA_START_EVENT = 3,
|
||||
HC_IRQ_3_5_EVENT = 4,
|
||||
HC_HCOUNTER_MAX_EVENT = 5,
|
||||
HC_IRQ_5_7_EVENT = 6,
|
||||
HC_HDMA_INIT_EVENT = 7,
|
||||
HC_IRQ_7_9_EVENT = 8,
|
||||
HC_RENDER_EVENT = 9,
|
||||
HC_IRQ_9_A_EVENT = 10,
|
||||
HC_WRAM_REFRESH_EVENT = 11,
|
||||
HC_IRQ_A_1_EVENT = 12
|
||||
HC_HDMA_START_EVENT = 2,
|
||||
HC_HCOUNTER_MAX_EVENT = 3,
|
||||
HC_HDMA_INIT_EVENT = 4,
|
||||
HC_RENDER_EVENT = 5,
|
||||
HC_WRAM_REFRESH_EVENT = 6
|
||||
};
|
||||
|
||||
struct STimings
|
||||
@ -327,12 +318,13 @@ struct STimings
|
||||
int32 HDMAInit;
|
||||
int32 HDMAStart;
|
||||
int32 NMITriggerPos;
|
||||
int32 IRQTriggerCycles;
|
||||
int32 WRAMRefreshPos;
|
||||
int32 RenderPos;
|
||||
bool8 InterlaceField;
|
||||
int32 DMACPUSync; // The cycles to synchronize DMA and CPU. Snes9x cannot emulate correctly.
|
||||
int32 NMIDMADelay; // The delay of NMI trigger after DMA transfers. Snes9x cannot emulate correctly.
|
||||
int32 IRQPendCount; // This value is just a hack, because Snes9x cannot emulate any events in an opcode.
|
||||
int32 IRQPendCount; // This value is just a hack.
|
||||
int32 APUSpeedup;
|
||||
bool8 APUAllowTimeOverflow;
|
||||
};
|
||||
@ -405,12 +397,8 @@ struct SSettings
|
||||
char CartBName[PATH_MAX + 1];
|
||||
|
||||
bool8 DisableGameSpecificHacks;
|
||||
bool8 ShutdownMaster;
|
||||
bool8 Shutdown;
|
||||
bool8 BlockInvalidVRAMAccessMaster;
|
||||
bool8 BlockInvalidVRAMAccess;
|
||||
bool8 DisableIRQ;
|
||||
bool8 DisableHDMA;
|
||||
int32 HDMATimingHack;
|
||||
|
||||
bool8 ForcedPause;
|
||||
|
Loading…
Reference in New Issue
Block a user