Merged with coreupdate branch, so now the master branch has improved IRQ and SA-1. / Remove i386 asm codes.

This commit is contained in:
zones 2011-01-16 17:15:13 +09:00
commit 82435ab5db
47 changed files with 688 additions and 16283 deletions

11
c4.cpp
View File

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

13
c4.h
View File

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

View File

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

View File

@ -425,7 +425,6 @@ static const int ptrspeeds[4] = { 1, 1, 4, 8 };
S(ToggleBG2), \
S(ToggleBG3), \
S(ToggleEmuTurbo), \
S(ToggleHDMA), \
S(ToggleSprites), \
S(ToggleTransparency) \
@ -2454,11 +2453,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);

14
cpu.cpp
View File

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

View File

@ -187,102 +187,91 @@
#include "missing.h"
#endif
static inline void S9xReschedule (void);
void S9xMainLoop (void)
{
for (;;)
{
if (CPU.Flags)
if (CPU.NMILine)
{
if (CPU.Flags & NMI_FLAG)
if (Timings.NMITriggerPos <= CPU.Cycles)
{
if (Timings.NMITriggerPos <= CPU.Cycles)
CPU.NMILine = FALSE;
Timings.NMITriggerPos = 0xffff;
if (CPU.WaitingForInterrupt)
{
CPU.Flags &= ~NMI_FLAG;
Timings.NMITriggerPos = 0xffff;
if (CPU.WaitingForInterrupt)
{
CPU.WaitingForInterrupt = FALSE;
Registers.PCw++;
}
S9xOpcode_NMI();
CPU.WaitingForInterrupt = FALSE;
Registers.PCw++;
}
S9xOpcode_NMI();
}
#ifdef DEBUGGER
if ((CPU.Flags & BREAK_FLAG) && !(CPU.Flags & SINGLE_STEP_FLAG))
{
for (int Break = 0; Break != 6; Break++)
{
if (S9xBreakpoint[Break].Enabled &&
S9xBreakpoint[Break].Bank == Registers.PB &&
S9xBreakpoint[Break].Address == Registers.PCw)
{
if (S9xBreakpoint[Break].Enabled == 2)
S9xBreakpoint[Break].Enabled = TRUE;
else
CPU.Flags |= DEBUG_MODE_FLAG;
}
}
}
#endif
if (CPU.Flags & IRQ_FLAG)
{
if (CPU.IRQPending)
// FIXME: In case of IRQ during WRAM refresh
CPU.IRQPending--;
else
{
if (CPU.WaitingForInterrupt)
{
CPU.WaitingForInterrupt = FALSE;
Registers.PCw++;
}
if (CPU.IRQActive && !Settings.DisableIRQ)
{
if (!CheckFlag(IRQ))
// in IRQ handler $4211 is supposed to be read, so IRQ_FLAG should be cleared.
S9xOpcode_IRQ();
}
else
CPU.Flags &= ~IRQ_FLAG;
}
}
if (CPU.Flags & SCAN_KEYS_FLAG)
break;
#ifdef DEBUGGER
if (CPU.Flags & DEBUG_MODE_FLAG)
break;
if (CPU.Flags & TRACE_FLAG)
S9xTrace();
if (CPU.Flags & SINGLE_STEP_FLAG)
{
CPU.Flags &= ~SINGLE_STEP_FLAG;
CPU.Flags |= DEBUG_MODE_FLAG;
}
#endif
}
#ifdef CPU_SHUTDOWN
CPU.PBPCAtOpcodeStart = Registers.PBPC;
if (CPU.IRQTransition || CPU.IRQExternal)
{
if (CPU.IRQPending)
CPU.IRQPending--;
else
{
if (CPU.WaitingForInterrupt)
{
CPU.WaitingForInterrupt = FALSE;
Registers.PCw++;
}
CPU.IRQTransition = FALSE;
CPU.IRQPending = Timings.IRQPendCount;
if (!CheckFlag(IRQ))
S9xOpcode_IRQ();
}
}
#ifdef DEBUGGER
if ((CPU.Flags & BREAK_FLAG) && !(CPU.Flags & SINGLE_STEP_FLAG))
{
for (int Break = 0; Break != 6; Break++)
{
if (S9xBreakpoint[Break].Enabled &&
S9xBreakpoint[Break].Bank == Registers.PB &&
S9xBreakpoint[Break].Address == Registers.PCw)
{
if (S9xBreakpoint[Break].Enabled == 2)
S9xBreakpoint[Break].Enabled = TRUE;
else
CPU.Flags |= DEBUG_MODE_FLAG;
}
}
}
if (CPU.Flags & DEBUG_MODE_FLAG)
break;
if (CPU.Flags & TRACE_FLAG)
S9xTrace();
if (CPU.Flags & SINGLE_STEP_FLAG)
{
CPU.Flags &= ~SINGLE_STEP_FLAG;
CPU.Flags |= DEBUG_MODE_FLAG;
}
#endif
if (CPU.Flags & SCAN_KEYS_FLAG)
break;
register uint8 Op;
register struct SOpcodes *Opcodes;
CPU.PrevCycles = CPU.Cycles;
if (CPU.PCBase)
{
Op = CPU.PCBase[Registers.PCw];
CPU.PrevCycles = CPU.Cycles;
CPU.Cycles += CPU.MemSpeed;
S9xCheckInterrupts();
Opcodes = ICPU.S9xOpcodes;
}
else
@ -304,13 +293,8 @@ void S9xMainLoop (void)
Registers.PCw++;
(*Opcodes[Op].S9xOpcode)();
if (SA1.Executing)
if (Settings.SA1)
S9xSA1MainLoop();
#if (S9X_ACCURACY_LEVEL <= 2)
while (CPU.Cycles >= CPU.NextEvent)
S9xDoHEventProcessing();
#endif
}
S9xPackStatus();
@ -325,54 +309,54 @@ void S9xMainLoop (void)
}
}
void S9xSetIRQ (uint32 source)
static inline void S9xReschedule (void)
{
CPU.IRQActive |= source;
CPU.IRQPending = Timings.IRQPendCount;
CPU.Flags |= IRQ_FLAG;
if (CPU.WaitingForInterrupt)
switch (CPU.WhichEvent)
{
// Force IRQ to trigger immediately after WAI -
// Final Fantasy Mystic Quest crashes without this.
CPU.WaitingForInterrupt = FALSE;
Registers.PCw++;
case HC_HBLANK_START_EVENT:
CPU.WhichEvent = HC_HDMA_START_EVENT;
CPU.NextEvent = Timings.HDMAStart;
break;
case HC_HDMA_START_EVENT:
CPU.WhichEvent = HC_HCOUNTER_MAX_EVENT;
CPU.NextEvent = Timings.H_Max;
break;
case HC_HCOUNTER_MAX_EVENT:
CPU.WhichEvent = HC_HDMA_INIT_EVENT;
CPU.NextEvent = Timings.HDMAInit;
break;
case HC_HDMA_INIT_EVENT:
CPU.WhichEvent = HC_RENDER_EVENT;
CPU.NextEvent = Timings.RenderPos;
break;
case HC_RENDER_EVENT:
CPU.WhichEvent = HC_WRAM_REFRESH_EVENT;
CPU.NextEvent = Timings.WRAMRefreshPos;
break;
case HC_WRAM_REFRESH_EVENT:
CPU.WhichEvent = HC_HBLANK_START_EVENT;
CPU.NextEvent = Timings.HBlankStart;
break;
}
#ifdef DEBUGGER
S9xTraceMessage("--- /IRQ low");
#endif
}
void S9xClearIRQ (uint32 source)
{
CPU.IRQActive &= ~source;
if (!CPU.IRQActive)
CPU.Flags &= ~IRQ_FLAG;
#ifdef DEBUGGER
S9xTraceMessage("--- /IRQ high");
#endif
}
void S9xDoHEventProcessing (void)
{
#ifdef DEBUGGER
static char eventname[13][32] =
static char eventname[7][32] =
{
"",
"HC_HBLANK_START_EVENT",
"HC_IRQ_1_3_EVENT ",
"HC_HDMA_START_EVENT ",
"HC_IRQ_3_5_EVENT ",
"HC_HCOUNTER_MAX_EVENT",
"HC_IRQ_5_7_EVENT ",
"HC_HDMA_INIT_EVENT ",
"HC_IRQ_7_9_EVENT ",
"HC_RENDER_EVENT ",
"HC_IRQ_9_A_EVENT ",
"HC_WRAM_REFRESH_EVENT",
"HC_IRQ_A_1_EVENT "
"HC_WRAM_REFRESH_EVENT"
};
#endif
@ -382,19 +366,13 @@ void S9xDoHEventProcessing (void)
eventname[CPU.WhichEvent], CPU.NextEvent, CPU.Cycles);
#endif
#ifdef CPU_SHUTDOWN
CPU.WaitCounter++;
#endif
switch (CPU.WhichEvent)
{
case HC_HBLANK_START_EVENT:
S9xCheckMissingHTimerPosition(Timings.HBlankStart);
S9xReschedule();
break;
case HC_HDMA_START_EVENT:
S9xCheckMissingHTimerPosition(Timings.HDMAStart);
S9xReschedule();
if (PPU.HDMA && CPU.V_Counter <= PPU.ScreenHeight)
@ -408,19 +386,16 @@ void S9xDoHEventProcessing (void)
break;
case HC_HCOUNTER_MAX_EVENT:
#ifndef ZSNES_FX
if (Settings.SuperFX)
{
if (!SuperFX.oneLineDone)
S9xSuperFXExec();
SuperFX.oneLineDone = FALSE;
}
#else
S9xSuperFXExec();
#endif
S9xAPUEndScanline();
CPU.Cycles -= Timings.H_Max;
CPU.PrevCycles -= Timings.H_Max;
S9xAPUSetReferenceTime(CPU.Cycles);
if ((Timings.NMITriggerPos != 0xffff) && (Timings.NMITriggerPos >= Timings.H_Max))
@ -449,7 +424,7 @@ void S9xDoHEventProcessing (void)
// FIXME: reading $4210 will wait 2 cycles, then perform reading, then wait 4 more cycles.
Memory.FillRAM[0x4210] = Model->_5A22;
CPU.Flags &= ~NMI_FLAG;
CPU.NMILine = FALSE;
Timings.NMITriggerPos = 0xffff;
ICPU.Frame++;
@ -481,8 +456,6 @@ void S9xDoHEventProcessing (void)
else
Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v1;
S9xCheckMissingHTimerPosition(0);
if (CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE) // VBlank starts from V=225(240).
{
S9xEndScreenRefresh();
@ -517,7 +490,7 @@ void S9xDoHEventProcessing (void)
{
// 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 = 6 + 6;
}
@ -532,13 +505,11 @@ void S9xDoHEventProcessing (void)
if (CPU.V_Counter == FIRST_VISIBLE_LINE) // V=1
S9xStartScreenRefresh();
CPU.NextEvent = -1;
S9xReschedule();
break;
case HC_HDMA_INIT_EVENT:
S9xCheckMissingHTimerPosition(Timings.HDMAInit);
S9xReschedule();
if (CPU.V_Counter == 0)
@ -555,7 +526,6 @@ void S9xDoHEventProcessing (void)
if (CPU.V_Counter >= FIRST_VISIBLE_LINE && CPU.V_Counter <= PPU.ScreenHeight)
RenderLine((uint8) (CPU.V_Counter - FIRST_VISIBLE_LINE));
S9xCheckMissingHTimerPosition(Timings.RenderPos);
S9xReschedule();
break;
@ -565,27 +535,12 @@ void S9xDoHEventProcessing (void)
S9xTraceFormattedMessage("*** WRAM Refresh HC:%04d", CPU.Cycles);
#endif
S9xCheckMissingHTimerHalt(Timings.WRAMRefreshPos, SNES_WRAM_REFRESH_CYCLES);
CPU.PrevCycles = CPU.Cycles;
CPU.Cycles += SNES_WRAM_REFRESH_CYCLES;
S9xCheckMissingHTimerPosition(Timings.WRAMRefreshPos);
S9xReschedule();
break;
case HC_IRQ_1_3_EVENT:
case HC_IRQ_3_5_EVENT:
case HC_IRQ_5_7_EVENT:
case HC_IRQ_7_9_EVENT:
case HC_IRQ_9_A_EVENT:
case HC_IRQ_A_1_EVENT:
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);
S9xCheckInterrupts();
S9xReschedule();
break;
}

101
cpuexec.h
View File

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

View File

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

View File

@ -188,13 +188,9 @@
#endif
#ifdef SA1_OPCODES
#define AddCycles(n) { }
#define AddCycles(n) { SA1.Cycles += (n); }
#else
#if (S9X_ACCURACY_LEVEL >= 3)
#define AddCycles(n) { CPU.Cycles += (n); while (CPU.Cycles >= CPU.NextEvent) S9xDoHEventProcessing(); }
#else
#define AddCycles(n) { CPU.Cycles += (n); }
#endif
#define AddCycles(n) { CPU.PrevCycles = CPU.Cycles; CPU.Cycles += (n); S9xCheckInterrupts(); while (CPU.Cycles >= CPU.NextEvent) S9xDoHEventProcessing(); }
#endif
#include "cpuaddr.h"
@ -659,9 +655,6 @@ rOPX (CCSlow, AbsoluteSlow, WRAP_NONE, CPY)
static void Op3AM1 (void)
{
AddCycles(ONE_CYCLE);
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
Registers.AL--;
SetZN(Registers.AL);
}
@ -669,9 +662,6 @@ static void Op3AM1 (void)
static void Op3AM0 (void)
{
AddCycles(ONE_CYCLE);
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
Registers.A.W--;
SetZN(Registers.A.W);
}
@ -679,9 +669,6 @@ static void Op3AM0 (void)
static void Op3ASlow (void)
{
AddCycles(ONE_CYCLE);
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
if (CheckMemory())
{
@ -813,9 +800,6 @@ rOPM (53Slow, StackRelativeIndirectIndexedSlow, WRAP_NONE, EOR)
static void Op1AM1 (void)
{
AddCycles(ONE_CYCLE);
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
Registers.AL++;
SetZN(Registers.AL);
}
@ -823,9 +807,6 @@ static void Op1AM1 (void)
static void Op1AM0 (void)
{
AddCycles(ONE_CYCLE);
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
Registers.A.W++;
SetZN(Registers.A.W);
}
@ -833,9 +814,6 @@ static void Op1AM0 (void)
static void Op1ASlow (void)
{
AddCycles(ONE_CYCLE);
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
if (CheckMemory())
{
@ -1550,54 +1528,6 @@ mOPM (0CSlow, AbsoluteSlow, WRAP_BANK, TSB)
/* Branch Instructions ***************************************************** */
#ifdef CPU_SHUTDOWN
#ifndef SA1_OPCODES
inline void CPUShutdown (void)
{
if (Settings.Shutdown && Registers.PBPC == CPU.WaitAddress)
{
// Don't skip cycles with a pending NMI or IRQ - could cause delayed interrupt.
if (CPU.WaitCounter == 0 && !(CPU.Flags & (IRQ_FLAG | NMI_FLAG)))
{
CPU.WaitAddress = 0xffffffff;
if (Settings.SA1)
S9xSA1ExecuteDuringSleep();
CPU.Cycles = CPU.NextEvent;
ICPU.CPUExecuting = FALSE;
S9xAPUExecute();
ICPU.CPUExecuting = TRUE;
}
else
if (CPU.WaitCounter >= 2)
CPU.WaitCounter = 1;
else
CPU.WaitCounter--;
}
}
#else
inline void CPUShutdown (void)
{
if (Settings.Shutdown && Registers.PBPC == CPU.WaitAddress)
{
if (CPU.WaitCounter >= 1)
SA1.Executing = FALSE;
else
CPU.WaitCounter++;
}
}
#endif
#else
#define CPUShutdown()
#endif
// BCC
bOP(90E0, Relative, !CheckCarry(), 0, 0)
bOP(90E1, Relative, !CheckCarry(), 0, 1)
@ -1692,7 +1622,7 @@ static void Op58 (void)
{
ClearIRQ();
AddCycles(ONE_CYCLE);
//CHECK_FOR_IRQ();
CHECK_FOR_IRQ();
}
// SEI
@ -1714,9 +1644,6 @@ static void OpB8 (void)
static void OpCAX1 (void)
{
AddCycles(ONE_CYCLE);
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
Registers.XL--;
SetZN(Registers.XL);
}
@ -1724,9 +1651,6 @@ static void OpCAX1 (void)
static void OpCAX0 (void)
{
AddCycles(ONE_CYCLE);
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
Registers.X.W--;
SetZN(Registers.X.W);
}
@ -1734,9 +1658,6 @@ static void OpCAX0 (void)
static void OpCASlow (void)
{
AddCycles(ONE_CYCLE);
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
if (CheckIndex())
{
@ -1753,9 +1674,6 @@ static void OpCASlow (void)
static void Op88X1 (void)
{
AddCycles(ONE_CYCLE);
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
Registers.YL--;
SetZN(Registers.YL);
}
@ -1763,9 +1681,6 @@ static void Op88X1 (void)
static void Op88X0 (void)
{
AddCycles(ONE_CYCLE);
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
Registers.Y.W--;
SetZN(Registers.Y.W);
}
@ -1773,9 +1688,6 @@ static void Op88X0 (void)
static void Op88Slow (void)
{
AddCycles(ONE_CYCLE);
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
if (CheckIndex())
{
@ -1794,9 +1706,6 @@ static void Op88Slow (void)
static void OpE8X1 (void)
{
AddCycles(ONE_CYCLE);
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
Registers.XL++;
SetZN(Registers.XL);
}
@ -1804,9 +1713,6 @@ static void OpE8X1 (void)
static void OpE8X0 (void)
{
AddCycles(ONE_CYCLE);
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
Registers.X.W++;
SetZN(Registers.X.W);
}
@ -1814,9 +1720,6 @@ static void OpE8X0 (void)
static void OpE8Slow (void)
{
AddCycles(ONE_CYCLE);
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
if (CheckIndex())
{
@ -1833,9 +1736,6 @@ static void OpE8Slow (void)
static void OpC8X1 (void)
{
AddCycles(ONE_CYCLE);
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
Registers.YL++;
SetZN(Registers.YL);
}
@ -1843,9 +1743,6 @@ static void OpC8X1 (void)
static void OpC8X0 (void)
{
AddCycles(ONE_CYCLE);
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
Registers.Y.W++;
SetZN(Registers.Y.W);
}
@ -1853,9 +1750,6 @@ static void OpC8X0 (void)
static void OpC8Slow (void)
{
AddCycles(ONE_CYCLE);
#ifdef CPU_SHUTDOWN
CPU.WaitAddress = 0xffffffff;
#endif
if (CheckIndex())
{
@ -2371,7 +2265,7 @@ static void Op28E1 (void)
SetFlags(MemoryFlag | IndexFlag);
S9xUnpackStatus();
S9xFixCycles();
//CHECK_FOR_IRQ();
CHECK_FOR_IRQ();
}
static void Op28E0 (void)
@ -2388,7 +2282,7 @@ static void Op28E0 (void)
}
S9xFixCycles();
//CHECK_FOR_IRQ();
CHECK_FOR_IRQ();
}
static void Op28Slow (void)
@ -2416,7 +2310,7 @@ static void Op28Slow (void)
}
S9xFixCycles();
//CHECK_FOR_IRQ();
CHECK_FOR_IRQ();
}
// PLX
@ -3069,17 +2963,11 @@ static void Op5CSlow (void)
static void Op4C (void)
{
S9xSetPCBase(ICPU.ShiftedPB + ((uint16) Absolute(JUMP)));
#if defined(CPU_SHUTDOWN) && defined(SA1_OPCODES)
CPUShutdown();
#endif
}
static void Op4CSlow (void)
{
S9xSetPCBase(ICPU.ShiftedPB + ((uint16) AbsoluteSlow(JUMP)));
#if defined(CPU_SHUTDOWN) && defined(SA1_OPCODES)
CPUShutdown();
#endif
}
static void Op6C (void)
@ -3425,7 +3313,7 @@ static void OpC2 (void)
}
S9xFixCycles();
//CHECK_FOR_IRQ();
CHECK_FOR_IRQ();
}
static void OpC2Slow (void)
@ -3454,7 +3342,7 @@ static void OpC2Slow (void)
}
S9xFixCycles();
//CHECK_FOR_IRQ();
CHECK_FOR_IRQ();
}
static void OpE2 (void)
@ -3562,7 +3450,7 @@ static void Op40Slow (void)
}
S9xFixCycles();
//CHECK_FOR_IRQ();
CHECK_FOR_IRQ();
}
/* STP/WAI ***************************************************************** */
@ -3570,44 +3458,15 @@ static void Op40Slow (void)
// WAI
static void OpCB (void)
{
// Ok, let's just C-ify the ASM versions separately.
#ifdef SA1_OPCODES
SA1.WaitingForInterrupt = TRUE;
Registers.PCw--;
#if 0
// XXX: FIXME
if (Settings.Shutdown)
{
SA1.Cycles = SA1.NextEvent;
SA1.Executing = FALSE;
//S9xAPUExecute(); // FIXME
SA1.Executing = TRUE;
}
AddCycles(TWO_CYCLES);
#else
CPU.WaitingForInterrupt = TRUE;
Registers.PCw--;
AddCycles(TWO_CYCLES);
#endif
#else // SA1_OPCODES
#if 0
if (CPU.IRQActive)
AddCycles(TWO_CYCLES);
else
#endif
{
CPU.WaitingForInterrupt = TRUE;
Registers.PCw--;
#ifdef CPU_SHUTDOWN
if (Settings.Shutdown)
{
CPU.Cycles = CPU.NextEvent;
ICPU.CPUExecuting = FALSE;
S9xAPUExecute();
ICPU.CPUExecuting = TRUE;
}
else
AddCycles(TWO_CYCLES);
#else
AddCycles(TWO_CYCLES);
#endif
}
#endif // SA1_OPCODES
}
// STP

View File

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

View File

@ -872,7 +872,7 @@ static uint8 debug_cpu_op_print (char *Line, uint8 Bank, uint16 Address)
break;
}
sprintf(Line, "%-44s A:%04X X:%04X Y:%04X D:%04X DB:%02X S:%04X P:%c%c%c%c%c%c%c%c%c HC:%04ld VC:%03ld FC:%02d %02x",
sprintf(Line, "%-44s A:%04X X:%04X Y:%04X D:%04X DB:%02X S:%04X P:%c%c%c%c%c%c%c%c%c HC:%04ld VC:%03ld FC:%02d %03x",
Line, Registers.A.W, Registers.X.W, Registers.Y.W,
Registers.D.W, Registers.DB, Registers.S.W,
CheckEmulation() ? 'E' : 'e',
@ -887,7 +887,7 @@ static uint8 debug_cpu_op_print (char *Line, uint8 Bank, uint16 Address)
(long) CPU.Cycles,
(long) CPU.V_Counter,
IPPU.FrameCount,
CPU.IRQActive);
(CPU.IRQExternal ? 0x100 : 0) | (PPU.HTimerEnabled ? 0x10 : 0) | (PPU.VTimerEnabled ? 0x01 : 0));
return (Size);
}

18
dma.cpp
View File

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

View File

@ -12,7 +12,7 @@
<body>
<h1 style="text-align:center">How to Port Snes9x to a New Platform</h1>
<div style="text-align:right">
Version: 1.52<br>
Version: 1.53<br>
(c) Copyright 1998 Gary Henderson
</div>
<h2>Introduction</h2>
@ -56,22 +56,10 @@
<p>
Define this if your compiler uses shift right arithmetic for signed values. For example, GCC and Visual C++ use shift right arithmetic.
</p>
<h3><code>CPU_SHUTDOWN</code></h3>
<p>
This is a speed-up hack. When defined and if <code>Settings.ShutdownMaster</code> is <code>true</code>, Snes9x starts watching for when CPU is in a simply loop waiting for a known event to happen - like the end of the current scanline. If Snes9x spots CPU in such a loop, it simply skips the emulation of its instructions until the event happens. It can be a big win with lots of SNES games, but will break a small number of games. In this case, set <code>Settings.ShutdownMaster</code> to <code>false</code> before you load a ROM image. Note that this hack is forcibly disabled in some games. See <code>Memory.ApplyROMFixes</code> function for the list of such games.
</p>
<h3><code>CORRECT_VRAM_READS</code></h3>
<p>
You must define this. It allows correct VRAM reads.
</p>
<h3><code>ZLIB / UNZIP_SUPPORT / JMA_SUPPORT</code></h3>
<p>
Define these if you want to support GZIP/ZIP/JMA compressed ROM images and GZIP compressed freeze-game files.
</p>
<h3><code>ZSNES_FX / ZSNES_C4</code></h3>
<p>
Define these if your CPU is x86 compatible and you're going to use the ZSNES Super FX and C4 assembler codes.
</p>
<h3><code>USE_OPENGL</code></h3>
<p>
Define this and set <code>Settings.OpenGLEnable</code> to <code>true</code>, then you'll get the rendered SNES image as one OpenGL texture.
@ -81,9 +69,7 @@
ZLIB<br>
UNZIP_SUPPORT<br>
JMA_SUPPORT<br>
CPU_SHUTDOWN<br>
RIGHTSHIFT_IS_SAR<br>
CORRECT_VRAM_READS
</code></p>
<h2>Editing port.h</h2>
<p>
@ -379,7 +365,7 @@
The sound generation rate on a SNES is directly proportional to the video output rate. Displays that synchronize with the vertical refresh but have a slightly lower refresh-rate than the emulated system can experience sound drop-outs. It may be beneficial to provide an option for users to configure <code>Settings.SoundInputRate</code> to suit their own systems. Setting <code>Settings.SoundInputRate</code> to a value that matches the actual output rate (i.e. 31977hz for 59.96hz) or lower will allow the users to eliminate crackling. A range of 31000hz to 33000hz should be inclusive enough for all displays. Use of this setting paired with the <code>S9xSyncSound</code> function can eliminate sound discontinuity.
</p>
<div style="text-align:right; margin-top:3em">
Updated most recently by: 2009/12/20 zones
Updated most recently by: 2011/1/16 zones
</div>
</body>
</html>

View File

@ -67,8 +67,6 @@ Justifier2Crosshair = 4 MagicPink/Black
EnableGameSpecificHacks = TRUE
AllowInvalidVRAMAccess = FALSE
SpeedHacks = FALSE
DisableIRQ = FALSE
DisableHDMA = FALSE
HDMATiming = 100
[Netplay]
@ -231,7 +229,6 @@ K00:4 = ToggleBG3
K00:5 = ToggleSprites
K00:9 = ToggleTransparency
K00:BackSpace = ClipWindows
K00:0 = ToggleHDMA
K00:A+Escape = Debugger
M00:Pointer = Pointer Mouse1+Superscope+Justifier1
M00:B0 = {Mouse1 L,Superscope Fire,Justifier1 Trigger}

View File

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

36
fxemu.h
View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,834 +0,0 @@
;Copyright (C) 1997-2001 ZSNES Team ( zsknight@zsnes.com / _demo_@zsnes.com )
;
;This program is free software; you can redistribute it and/or
;modify it under the terms of the GNU General Public License
;as published by the Free Software Foundation; either
;version 2 of the License, or (at your option) any later
;version.
;
;This program is distributed in the hope that it will be useful,
;but WITHOUT ANY WARRANTY; without even the implied warranty of
;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;GNU General Public License for more details.
;
;You should have received a copy of the GNU General Public License
;along with this program; if not, write to the Free Software
;Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
%macro FETCHPIPE 0
; mov edx,[SfxPBR]
; mov edx,[SfxMemTable+edx*4]
; mov edx,[SfxCPB]
; mov edx,[SfxR15]
mov cl,[ebp]
%endmacro
%macro UpdateR14 0
; mov edx,[SfxROMBR]
; mov edx,[SfxMemTable+edx*4]
mov eax,[SfxCROM]
; and dword[SfxR14],0FFFFh
add eax,[SfxR14]
mov [SfxRomBuffer],eax
%endmacro
%macro UpdateR15 0
mov ebp,[SfxCPB]
add ebp,[SfxR15]
%endmacro
%macro CLRFLAGS 0
;and dword [SfxSFR],0FFFFh-0100h-0200h-1000h ; Clear ALT1,ALT2 and B Flags
; xor ch,ch
; mov dword [SfxB],0 ; Clear B Flag
; mov esi,SfxR0
; mov edi,SfxR0
%endmacro
%macro TORN 1 ; V
FETCHPIPE
mov edi, SfxR0+%1*4
inc ebp ; Increase program counter
call [FxTable+ecx*4]
mov edi,SfxR0
ret
%endmacro
%macro WITH 1 ; Verified.
FETCHPIPE
mov esi,SfxR0+%1*4
mov edi,SfxR0+%1*4
mov dword [SfxB],1
inc ebp ; Increase program counter
call [FxTablec+ecx*4]
mov esi,SfxR0
mov edi,SfxR0
mov dword [SfxB],0 ; Clear B Flag
ret
%endmacro
%macro STWRN 1 ; V
mov eax,[SfxR0+%1*4] ; Read register
mov ebx,[SfxRAMMem]
mov dword [SfxLastRamAdr],eax ; Save last ram address
add dword [SfxLastRamAdr],ebx ; Save last ram address
mov edx,[esi] ; Read Source
FETCHPIPE
mov [ebx+eax],dl ; Store Word
xor eax,1
inc ebp ; Increase program counter
mov [ebx+eax],dh ; Store Word
CLRFLAGS
ret
%endmacro
%macro STBRN 1 ; V
mov eax,[SfxR0+%1*4] ; Read register
FETCHPIPE
add eax,[SfxRAMMem]
mov dword [SfxLastRamAdr],eax ; Save last ram address
mov ebx,[esi] ; Read Source
mov byte [eax],bl ; Store Byte
CLRFLAGS
inc ebp ; Increase program counter
ret
%endmacro
%macro LDWRN 1 ; V
mov eax,[SfxR0+%1*4] ; Read register
mov ebx,[SfxRAMMem]
mov dword [SfxLastRamAdr],eax ; Save last ram address
FETCHPIPE
mov dl,[ebx+eax] ; Store Word
add dword [SfxLastRamAdr],ebx ; Save last ram address
xor eax,1
and edx,0FFFFh
inc ebp ; Increase program counter
mov dh,[ebx+eax] ; Store Word
mov [edi],edx ; Read Source
CLRFLAGS
ret
%endmacro
%macro LDBRN 1 ; V
mov eax,[SfxR0+%1*4] ; Read register
FETCHPIPE
add eax,[SfxRAMMem]
xor ebx,ebx
mov dword [SfxLastRamAdr],eax ; Save last ram address
mov bl,[eax] ; Read Byte
inc ebp ; Increase program counter
mov [edi],ebx ; Store Result
CLRFLAGS
ret
%endmacro
; test byte[SfxPOR],01h
; jnz .nozerocheck
; test byte[SfxPOR],02h
; jz .nodither
; **** Can pre-calculate [SfxSCBR] << 10 + [sfxramdata]
; Pre-calculate fxbit values from color register
%macro drawpix4b 0
and [eax],edx
and [eax+16],edx
xor edx,0FFFFFFFFh
mov ebx,[fxbit01pcal]
and ebx,edx
or [eax], ebx
and edx,[fxbit23pcal]
or [eax+16], edx
%endmacro
%macro drawpix4bd 0
and [eax],edx
and [eax+16],edx
xor edx,0FFFFFFFFh
mov ebx,[fxbit45pcal]
and ebx,edx
or [eax], ebx
and edx,[fxbit67pcal]
or [eax+16], edx
%endmacro
%macro drawpix2b 0
and [eax],edx
xor edx,0FFFFFFFFh
and edx,[fxbit01pcal]
or [eax], edx
%endmacro
%macro drawpix2bd 0
and [eax],edx
xor edx,0FFFFFFFFh
and edx,[fxbit45pcal]
or [eax], edx
%endmacro
%macro drawpix8b 0
and [eax],edx
and [eax+16],edx
and [eax+32],edx
and [eax+48],edx
xor edx,0FFFFFFFFh
mov ebx,[fxbit01pcal]
and ebx,edx
or [eax], ebx
mov ebx,[fxbit23pcal]
and ebx,edx
or [eax+16], ebx
mov ebx,[fxbit45pcal]
and ebx,edx
or [eax+32], ebx
and edx,[fxbit67pcal]
or [eax+48], edx
%endmacro
%macro drawpix8bd 0
and [eax],edx
and [eax+16],edx
and [eax+32],edx
and [eax+48],edx
xor edx,0FFFFFFFFh
mov ebx,[fxbit45pcal]
and ebx,edx
or [eax], ebx
mov ebx,[fxbit67pcal]
and ebx,edx
or [eax+16], ebx
mov ebx,[fxbit01pcal]
and ebx,edx
or [eax+32], ebx
and edx,[fxbit23pcal]
or [eax+48], edx
%endmacro
%macro plotb 5
shl eax,%3
and ebx,07h
add ebx,ebx
add eax,ebx
add eax,[SCBRrel]
mov bl,[SfxR1]
mov edx,[fxxand+ebx*4]
%2
%endmacro
%macro plotbz 5
shl eax,%3
and ebx,07h
add ebx,ebx
add eax,ebx
add eax,[SCBRrel]
mov bl,[SfxR1]
mov edx,[fxxand+ebx*4]
test byte[SfxCOLR],%5
jz .nodraw
%2
%endmacro
%macro plotbd 5
shl eax,%3
and ebx,07h
add ebx,ebx
add eax,ebx
add eax,[SCBRrel]
mov bl,[SfxR1]
mov edx,[fxxand+ebx*4]
mov bl,[SfxR1]
xor bl,[SfxR2]
test bl,01h
jz near .nodither4b
%4
inc word [SfxR1]
%1
.nodither4b
%2
%endmacro
%macro plotbzd 5
shl eax,%3
and ebx,07h
add ebx,ebx
add eax,ebx
add eax,[SCBRrel]
mov bl,[SfxR1]
mov edx,[fxxand+ebx*4]
test byte[SfxCOLR],%5
jz near .nodraw
mov bl,[SfxR1]
xor bl,[SfxR2]
test bl,01h
jz .nodither4b
%4
inc word [SfxR1]
%1
.nodither4b
%2
%endmacro
%macro plotlines4b 1
mov ebx,[SfxR2]
FETCHPIPE
mov bh,[SfxR1]
mov eax,[sfxclineloc]
inc ebp
mov eax,[eax+ebx*4]
cmp eax,0FFFFFFFFh
je near .nodraw
%1 ret, drawpix4b, 5, drawpix4bd, 0Fh
.nodraw
inc word [SfxR1]
ret
%endmacro
%macro plotlines4bb 1
mov ebx,[SfxR2]
FETCHPIPE
mov bh,[SfxR1]
mov eax,[sfxclineloc]
inc ebp
mov eax,[eax+ebx*4]
cmp eax,0FFFFFFFFh
je near .nodraw
%1 FXReturn, drawpix4b, 5, drawpix4bd, 0Fh
.nodraw
inc word [SfxR1]
FXReturn
%endmacro
%macro plotlines2b 1
mov ebx,[SfxR2]
FETCHPIPE
mov bh,[SfxR1]
mov eax,[sfxclineloc]
inc ebp
mov eax,[eax+ebx*4]
cmp eax,0FFFFFFFFh
je near .nodraw
%1 ret, drawpix2b, 4, drawpix2bd, 03h
.nodraw
inc word [SfxR1]
ret
%endmacro
%macro plotlines2bb 1
mov ebx,[SfxR2]
FETCHPIPE
mov bh,[SfxR1]
mov eax,[sfxclineloc]
inc ebp
mov eax,[eax+ebx*4]
cmp eax,0FFFFFFFFh
je near .nodraw
%1 FXReturn, drawpix2b, 4, drawpix2bd, 03h
.nodraw
inc word [SfxR1]
FXReturn
%endmacro
%macro plotlines8b 1
mov ebx,[SfxR2]
FETCHPIPE
mov bh,[SfxR1]
mov eax,[sfxclineloc]
inc ebp
mov eax,[eax+ebx*4]
cmp eax,0FFFFFFFFh
je near .nodraw
%1 ret, drawpix8b, 6, drawpix8bd, 0FFh
.nodraw
inc word [SfxR1]
ret
%endmacro
%macro plotlines8bb 1
mov ebx,[SfxR2]
FETCHPIPE
mov bh,[SfxR1]
mov eax,[sfxclineloc]
inc ebp
mov eax,[eax+ebx*4]
cmp eax,0FFFFFFFFh
je near .nodraw
%1 FXReturn, drawpix8b, 6, drawpix8bd, 0FFh
.nodraw
inc word [SfxR1]
FXReturn
%endmacro
%macro plotlines8bl 1
mov ebx,[SfxR2]
FETCHPIPE
mov bh,[SfxR1]
mov eax,[sfxclineloc]
inc ebp
mov eax,[eax+ebx*4]
cmp eax,0FFFFFFFFh
je near .nodraw
%1 ret, drawpix8b, 6, drawpix8bd, 0Fh
.nodraw
inc word [SfxR1]
ret
%endmacro
%macro plotlines8bbl 1
mov ebx,[SfxR2]
FETCHPIPE
mov bh,[SfxR1]
mov eax,[sfxclineloc]
inc ebp
mov eax,[eax+ebx*4]
cmp eax,0FFFFFFFFh
je near .nodraw
%1 FXReturn, drawpix8b, 6, drawpix8bd, 0Fh
.nodraw
inc word [SfxR1]
FXReturn
%endmacro
%macro ADDRN 1 ; V
mov eax, [esi] ; Read Source
mov ebx, [SfxR0+%1*4]
FETCHPIPE
add ax,bx
seto byte[SfxOverflow]
setc byte[SfxCarry]
mov [SfxSignZero],eax
inc ebp ; Increase program counter
mov [edi],eax ; Write Destination
CLRFLAGS
ret
%endmacro
%macro ADCRN 1 ; V
FETCHPIPE
mov eax, [esi] ; Read Source
mov ebx, [SfxR0+%1*4]
shr byte[SfxCarry],1
adc ax,bx
seto byte[SfxOverflow]
setc byte[SfxCarry]
mov [SfxSignZero],eax
inc ebp ; Increase program counter
mov [edi],eax ; Write Destination
CLRFLAGS
ret
%endmacro
%macro ADIRN 1 ; V
mov eax, [esi] ; Read Source
FETCHPIPE
add ax,%1
seto byte[SfxOverflow]
setc byte[SfxCarry]
mov [SfxSignZero],eax
inc ebp ; Increase program counter
mov [edi],eax ; Write Destination
CLRFLAGS
ret
%endmacro
%macro ADCIRN 1 ; V
FETCHPIPE
mov eax, [esi] ; Read Source
shr byte[SfxCarry],1
adc ax,%1
seto byte[SfxOverflow]
setc byte[SfxCarry]
mov [SfxSignZero],eax
inc ebp ; Increase program counter
mov [edi],eax ; Write Destination
CLRFLAGS
ret
%endmacro
%macro SUBRN 1 ; V
mov eax,[esi] ; Read Source
mov ebx,[SfxR0+%1*4]
FETCHPIPE
sub ax,bx
seto byte[SfxOverflow]
setc byte[SfxCarry]
xor byte[SfxCarry],1
inc ebp ; Increase program counter
mov [edi],eax ; Write Destination
mov [SfxSignZero],eax
CLRFLAGS
ret
%endmacro
%macro SBCRN 1 ; V
FETCHPIPE
mov eax,[esi] ; Read Source
mov ebx,[SfxR0+%1*4]
cmp byte[SfxCarry],1
sbb ax,bx
seto byte[SfxOverflow]
setc byte[SfxCarry]
xor byte[SfxCarry],1
inc ebp ; Increase program counter
mov [edi],eax ; Write Destination
mov [SfxSignZero],eax
CLRFLAGS
ret
%endmacro
%macro SUBIRN 1 ; V
mov eax,[esi] ; Read Source
FETCHPIPE
sub ax,%1
seto byte[SfxOverflow]
setc byte[SfxCarry]
xor byte[SfxCarry],1
inc ebp ; Increase program counter
mov [edi],eax ; Write Destination
mov [SfxSignZero],eax
CLRFLAGS
ret
%endmacro
%macro CMPRN 1 ; V
mov eax,[esi] ; Read Source
mov ebx,[SfxR0+%1*4]
FETCHPIPE
sub ax,bx
seto byte[SfxOverflow]
setc byte[SfxCarry]
xor byte[SfxCarry],1
mov [SfxSignZero],eax
CLRFLAGS
inc ebp ; Increase program counter
ret
%endmacro
%macro ANDRN 1 ; V
mov eax,[esi] ; Read Source
mov ebx,[SfxR0+%1*4] ; Read RN
FETCHPIPE
and eax,ebx
inc ebp
mov dword [SfxSignZero],eax
mov [edi],eax ; Write Destination
CLRFLAGS
ret
%endmacro
%macro BICRN 1 ; V
mov ebx,[SfxR0+%1*4] ; Read RN
mov eax,[esi] ; Read Source
xor ebx,0FFFFh
FETCHPIPE
and eax,ebx
inc ebp
mov dword [SfxSignZero],eax
mov [edi],eax ; Write Destination
CLRFLAGS
ret
%endmacro
%macro ANDIRN 1 ; V
mov eax,[esi] ; Read Source
FETCHPIPE
and eax,%1
inc ebp
mov dword [SfxSignZero],eax
mov [edi],eax ; Write Destination
CLRFLAGS
ret
%endmacro
%macro BICIRN 1 ; V
mov eax,[esi] ; Read Source
FETCHPIPE
and eax,%1
inc ebp
mov dword [SfxSignZero],eax
mov [edi],eax ; Write Destination
CLRFLAGS
ret
%endmacro
%macro MULTRN 1 ; V
mov al,byte [esi] ; Read Source
mov bl,byte [SfxR0+%1*4] ; Read RN
FETCHPIPE
imul bl
inc ebp
and eax,0FFFFh
mov [SfxSignZero],eax
mov [edi],eax ; Write Destination
CLRFLAGS
ret
%endmacro
%macro UMULTRN 1 ; V
mov al,byte [esi] ; Read Source
mov bl,byte [SfxR0+%1*4] ; Read RN
FETCHPIPE
mul bl
inc ebp
and eax,0FFFFh
mov [SfxSignZero],eax
mov [edi],eax ; Write Destination
CLRFLAGS
ret
%endmacro
%macro MULTIRN 1 ; V
mov al,byte [esi] ; Read Source
mov bl,%1 ; Read RN
FETCHPIPE
imul bl
inc ebp
and eax,0FFFFh
mov [SfxSignZero],eax
mov [edi],eax ; Write Destination
CLRFLAGS
ret
%endmacro
%macro UMULTIRN 1 ; V
mov al,byte [esi] ; Read Source
mov bl,%1 ; Read RN
FETCHPIPE
mul bl
inc ebp
and eax,0FFFFh
mov [SfxSignZero],eax
mov [edi],eax ; Write Destination
CLRFLAGS
ret
%endmacro
%macro LINK 1 ; Verified.
mov eax,ebp
sub eax,[SfxCPB]
add eax,%1
FETCHPIPE
mov word [SfxR11],ax
CLRFLAGS
inc ebp
ret
%endmacro
%macro JMPRN 1 ; V
FETCHPIPE
mov eax,[SfxR0+%1*4] ; Read RN
mov ebp,[SfxCPB]
add ebp,eax
CLRFLAGS
ret
%endmacro
%macro LJMPRN 1 ; V
FETCHPIPE
mov eax,[SfxR0+%1*4]
and eax,07Fh
mov byte[SfxPBR],al
; mov byte[fxtrace+eax],1
mov eax,[SfxMemTable+eax*4]
mov [SfxCPB],eax
mov ebp,eax
add ebp,[esi] ; Read RN
mov dword [SfxCacheActive],0
push ecx
call FxOp02
pop ecx
dec ebp
ret
%endmacro
%macro IBTRN 1 ; V
movsx eax,byte[ebp]
mov cl,[ebp+1]
add ebp,2
mov [SfxR0+%1*4],ax
CLRFLAGS
ret
%endmacro
%macro LMSRN 1 ; Verified.
xor eax,eax
mov al,[ebp]
add eax,eax
inc ebp
add eax,[SfxRAMMem]
mov cl,[ebp]
mov dword [SfxLastRamAdr],eax
mov ebx,[eax] ; Read word from ram
inc ebp
mov [SfxR0+%1*4],bx ; Write data
CLRFLAGS
ret
%endmacro
%macro SMSRN 1 ; Verified.
xor eax,eax
mov al,[ebp]
inc ebp
add eax,eax
mov cl,[ebp]
add eax,[SfxRAMMem]
mov ebx,[SfxR0+%1*4] ; Read data
mov dword [SfxLastRamAdr],eax
inc ebp
mov [eax],bx ; Write word to ram
CLRFLAGS
ret
%endmacro
%macro FROMRN 1 ; V
FETCHPIPE
mov esi,SfxR0+%1*4
inc ebp ; Increase program counter
call [FxTable+ecx*4]
mov esi,SfxR0
ret
%endmacro
%macro ORRN 1 ; V
mov eax,[esi] ; Read Source
mov ebx,[SfxR0+%1*4] ; Read
FETCHPIPE
or eax,ebx
inc ebp
mov [edi],eax ; Write DREG
mov [SfxSignZero],eax
CLRFLAGS
ret
%endmacro
%macro XORRN 1 ; V
mov eax,[esi] ; Read Source
mov ebx,[SfxR0+%1*4] ; Read
FETCHPIPE
xor eax,ebx
inc ebp
mov [edi],eax ; Write DREG
mov [SfxSignZero],eax
CLRFLAGS
ret
%endmacro
%macro ORI 1 ; V
mov eax,[esi] ; Read Source
FETCHPIPE
or eax,%1
inc ebp
mov [edi],eax ; Write DREG
mov [SfxSignZero],eax
CLRFLAGS
ret
%endmacro
%macro XORI 1 ; V
mov eax,[esi] ; Read Source
FETCHPIPE
xor eax,%1
inc ebp
mov [edi],eax ; Write DREG
mov [SfxSignZero],eax
CLRFLAGS
ret
%endmacro
%macro INCRN 1 ; Verified
inc word[SfxR0+%1*4]
FETCHPIPE
mov eax,[SfxR0+%1*4] ; Read Source
mov [SfxSignZero],eax
CLRFLAGS
inc ebp
ret
%endmacro
%macro DECRN 1 ; Verified
dec word[SfxR0+%1*4]
FETCHPIPE
mov eax,[SfxR0+%1*4] ; Read Source
mov [SfxR0+%1*4],eax
mov [SfxSignZero],eax
CLRFLAGS
inc ebp
ret
%endmacro
%macro IWTRN 1 ; aka LEA ; Verified.
mov eax,[ebp]
mov cl,[ebp+2]
and eax,0FFFFh
add ebp,3
mov [SfxR0+%1*4],eax
CLRFLAGS
ret
%endmacro
%macro LMRN 1 ; Verified!
xor eax,eax
mov cl,[ebp+2]
mov ax,[ebp]
mov ebx,[SfxRAMMem]
mov [SfxLastRamAdr],eax
add [SfxLastRamAdr],ebx
mov dl,[eax+ebx]
xor eax,1
add ebp,3
mov dh,[eax+ebx]
mov word [SfxR0+%1*4],dx ; Store Word
CLRFLAGS
ret
%endmacro
%macro SMRN 1 ; Verified
mov ebx,[SfxR0+%1*4]
mov eax,[ebp]
mov cl,[ebp+2]
and eax,0FFFFh
mov dx,bx
mov ebx,[SfxRAMMem]
mov [SfxLastRamAdr],eax
add [SfxLastRamAdr],ebx
mov [eax+ebx],dl
xor eax,1
add ebp,3
mov [eax+ebx],dh
CLRFLAGS
ret
%endmacro
%macro PackEsiEdi 0
mov eax,[SfxSREG]
shl eax,2
add eax,SfxR0
mov esi,eax
mov eax,[SfxDREG]
shl eax,2
add eax,SfxR0
mov edi,eax
mov eax,[SfxRAMBR]
shl eax,16
add eax,[sfxramdata]
mov dword [SfxRAMMem],eax
%endmacro
%macro UnPackEsiEdi 0
mov eax,esi
sub eax,SfxR0
shr eax,2
mov [SfxSREG],eax
mov eax,edi
sub eax,SfxR0
shr eax,2
mov [SfxDREG],eax
%endmacro

View File

@ -1,617 +0,0 @@
;Copyright (C) 1997-2001 ZSNES Team ( zsknight@zsnes.com / _demo_@zsnes.com )
;
;This program is free software; you can redistribute it and/or
;modify it under the terms of the GNU General Public License
;as published by the Free Software Foundation; either
;version 2 of the License, or (at your option) any later
;version.
;
;This program is distributed in the hope that it will be useful,
;but WITHOUT ANY WARRANTY; without even the implied warranty of
;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;GNU General Public License for more details.
;
;You should have received a copy of the GNU General Public License
;along with this program; if not, write to the Free Software
;Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
%include "macros.mac"
EXTSYM FxTable,FxTableb,FxTablec,SfxB,SfxCPB,SfxCROM,SfxCarry,SfxOverflow
EXTSYM SfxR0,SfxR14,SfxR15,SfxRomBuffer,SfxSignZero,withr15sk
NEWSYM FxEmu2BAsmStart
%include "fxemu2.mac"
%include "fxemu2b.mac"
NEWSYM FxOpb05 ; BRA branch always ; Verified.
movsx eax,byte[ebp]
mov cl,[ebp+1]
inc ebp
add ebp,eax
call [FxTableb+ecx*4]
ret
NEWSYM FxOpb06 ; BGE branch on greater or equals ; Verified.
movsx eax,byte[ebp]
mov ebx,[SfxSignZero]
shr ebx,15
inc ebp
xor bl,[SfxOverflow]
mov cl,[ebp]
test bl,01h
jnz .nojump
add ebp,eax
call [FxTableb+ecx*4]
ret
.nojump
inc ebp
call [FxTableb+ecx*4]
ret
NEWSYM FxOpb07 ; BLT branch on lesss than ; Verified.
movsx eax,byte[ebp]
mov ebx,[SfxSignZero]
shr ebx,15
inc ebp
xor bl,[SfxOverflow]
mov cl,[ebp]
test bl,01h
jz .nojump
add ebp,eax
call [FxTableb+ecx*4]
ret
.nojump
inc ebp
call [FxTableb+ecx*4]
ret
NEWSYM FxOpb08 ; BNE branch on not equal ; Verified.
movsx eax,byte[ebp]
inc ebp
test dword[SfxSignZero],0FFFFh
mov cl,[ebp]
jz .nojump
add ebp,eax
call [FxTableb+ecx*4]
ret
.nojump
inc ebp
call [FxTableb+ecx*4]
ret
NEWSYM FxOpb09 ; BEQ branch on equal (z=1) ; Verified.
movsx eax,byte[ebp]
inc ebp
test dword[SfxSignZero],0FFFFh
mov cl,[ebp]
jnz .nojump
add ebp,eax
call [FxTableb+ecx*4]
ret
.nojump
inc ebp
call [FxTableb+ecx*4]
ret
NEWSYM FxOpb0A ; BPL branch on plus ; Verified.
movsx eax,byte[ebp]
inc ebp
test dword[SfxSignZero],088000h
mov cl,[ebp]
jnz .nojump
add ebp,eax
call [FxTableb+ecx*4]
ret
.nojump
inc ebp
call [FxTableb+ecx*4]
ret
NEWSYM FxOpb0B ; BMI branch on minus ; Verified.
movsx eax,byte[ebp]
inc ebp
test dword[SfxSignZero],088000h
mov cl,[ebp]
jz .nojump
add ebp,eax
call [FxTableb+ecx*4]
ret
.nojump
inc ebp
call [FxTableb+ecx*4]
ret
NEWSYM FxOpb0C ; BCC branch on carry clear ; Verified.
movsx eax,byte[ebp]
inc ebp
test byte[SfxCarry],01h
mov cl,[ebp]
jnz .nojump
add ebp,eax
call [FxTableb+ecx*4]
ret
.nojump
inc ebp
call [FxTableb+ecx*4]
ret
NEWSYM FxOpb0D ; BCS branch on carry set ; Verified.
movsx eax,byte[ebp]
inc ebp
test byte[SfxCarry],01h
mov cl,[ebp]
jz .nojump
add ebp,eax
call [FxTableb+ecx*4]
ret
.nojump
inc ebp
call [FxTableb+ecx*4]
ret
NEWSYM FxOpb0E ; BVC branch on overflow clear ; Verified.
movsx eax,byte[ebp]
inc ebp
test byte[SfxOverflow],01h
mov cl,[ebp]
jnz .nojump
add ebp,eax
call [FxTableb+ecx*4]
ret
.nojump
inc ebp
call [FxTableb+ecx*4]
ret
NEWSYM FxOpb0F ; BVS branch on overflow set ; Verified.
movsx eax,byte[ebp]
inc ebp
test byte[SfxOverflow],01h
mov cl,[ebp]
jz .nojump
add ebp,eax
call [FxTableb+ecx*4]
ret
.nojump
inc ebp
call [FxTableb+ecx*4]
ret
NEWSYM FxOpb10 ; TO RN set register n as destination register
TORNb 0
NEWSYM FxOpb11 ; TO RN set register n as destination register
TORNb 1
NEWSYM FxOpb12 ; TO RN set register n as destination register
TORNb 2
NEWSYM FxOpb13 ; TO RN set register n as destination register
TORNb 3
NEWSYM FxOpb14 ; TO RN set register n as destination register
TORNb 4
NEWSYM FxOpb15 ; TO RN set register n as destination register
TORNb 5
NEWSYM FxOpb16 ; TO RN set register n as destination register
TORNb 6
NEWSYM FxOpb17 ; TO RN set register n as destination register
TORNb 7
NEWSYM FxOpb18 ; TO RN set register n as destination register
TORNb 8
NEWSYM FxOpb19 ; TO RN set register n as destination register
TORNb 9
NEWSYM FxOpb1A ; TO RN set register n as destination register
TORNb 10
NEWSYM FxOpb1B ; TO RN set register n as destination register
TORNb 11
NEWSYM FxOpb1C ; TO RN set register n as destination register
TORNb 12
NEWSYM FxOpb1D ; TO RN set register n as destination register
TORNb 13
NEWSYM FxOpb1E ; TO RN set register n as destination register
FETCHPIPE
test dword [SfxB],1
jnz .VersionB
mov edi,SfxR0+14*4
inc ebp
mov eax,ebp
sub eax,[SfxCPB]
mov dword[withr15sk],1
mov [SfxR15],eax
call [FxTableb+ecx*4]
mov edi,SfxR0
UpdateR14
ret
.VersionB
mov eax,[esi] ; Read Source
mov dword[withr15sk],1
mov [SfxR0+14*4],eax ; Write
CLRFLAGS
UpdateR14
inc ebp ; Increase program counter
ret
NEWSYM FxOpb1F ; TO RN set register n as destination register
FETCHPIPE
test dword [SfxB],1
jnz .VersionB
mov edi,SfxR0+15*4
inc ebp
mov eax,ebp
sub eax,[SfxCPB]
mov [SfxR15],eax
call [FxTableb+ecx*4]
mov ebp,[SfxCPB]
mov dword[withr15sk],1
add ebp,[SfxR15]
mov edi,SfxR0
ret
.VersionB
mov eax,[esi] ; Read Source
mov ebp,[SfxCPB]
mov dword[withr15sk],1
add ebp,eax
CLRFLAGS
ret
NEWSYM FxOpb3D ; ALT1 set alt1 mode ; Verified.
FETCHPIPE
mov dword [SfxB],0
or ch,01h
inc ebp
mov eax,ebp
sub eax,[SfxCPB]
mov [SfxR15],eax
call [FxTableb+ecx*4]
xor ch,ch
ret
NEWSYM FxOpb3E ; ALT2 set alt1 mode ; Verified.
FETCHPIPE
mov dword [SfxB],0
or ch,02h
inc ebp
mov eax,ebp
sub eax,[SfxCPB]
mov [SfxR15],eax
call [FxTable+ecx*4]
xor ch,ch
ret
NEWSYM FxOpb3F ; ALT3 set alt3 mode ; Verified.
FETCHPIPE
mov dword [SfxB],0
or ch,03h
inc ebp
mov eax,ebp
sub eax,[SfxCPB]
mov [SfxR15],eax
call [FxTable+ecx*4]
xor ch,ch
ret
NEWSYM FxOpbB0 ; FROM rn set source register
FROMRNb 0
NEWSYM FxOpbB1 ; FROM rn set source register
FROMRNb 1
NEWSYM FxOpbB2 ; FROM rn set source register
FROMRNb 2
NEWSYM FxOpbB3 ; FROM rn set source register
FROMRNb 3
NEWSYM FxOpbB4 ; FROM rn set source register
FROMRNb 4
NEWSYM FxOpbB5 ; FROM rn set source register
FROMRNb 5
NEWSYM FxOpbB6 ; FROM rn set source register
FROMRNb 6
NEWSYM FxOpbB7 ; FROM rn set source register
FROMRNb 7
NEWSYM FxOpbB8 ; FROM rn set source register
FROMRNb 8
NEWSYM FxOpbB9 ; FROM rn set source register
FROMRNb 9
NEWSYM FxOpbBA ; FROM rn set source register
FROMRNb 10
NEWSYM FxOpbBB ; FROM rn set source register
FROMRNb 11
NEWSYM FxOpbBC ; FROM rn set source register
FROMRNb 12
NEWSYM FxOpbBD ; FROM rn set source register
FROMRNb 13
NEWSYM FxOpbBE ; FROM rn set source register
FROMRNb 14
NEWSYM FxOpbBF ; FROM rn set source register
test dword [SfxB],1
jnz .VersionB
mov esi,SfxR0+15*4
inc ebp ; Increase program counter
mov eax,ebp
sub eax,[SfxCPB]
mov [SfxR15],eax
call [FxTableb+ecx*4]
mov esi,SfxR0
ret
.VersionB
FETCHPIPE
mov eax,ebp
sub eax,[SfxCPB]
inc ebp
mov [edi],eax ; Write Destination
mov [SfxSignZero],eax
shr al,7
mov byte[SfxOverflow],al
CLRFLAGS
ret
NEWSYM FxOpc05 ; BRA branch always ; Verified.
movsx eax,byte[ebp]
mov cl,[ebp+1]
inc ebp
add ebp,eax
call [FxTablec+ecx*4]
ret
NEWSYM FxOpc06 ; BGE branch on greater or equals ; Verified.
movsx eax,byte[ebp]
mov ebx,[SfxSignZero]
shr ebx,15
inc ebp
xor bl,[SfxOverflow]
mov cl,[ebp]
test bl,01h
jnz .nojump
add ebp,eax
call [FxTablec+ecx*4]
ret
.nojump
inc ebp
call [FxTablec+ecx*4]
ret
NEWSYM FxOpc07 ; BLT branch on lesss than ; Verified.
movsx eax,byte[ebp]
mov ebx,[SfxSignZero]
shr ebx,15
inc ebp
xor bl,[SfxOverflow]
mov cl,[ebp]
test bl,01h
jz .nojump
add ebp,eax
call [FxTablec+ecx*4]
ret
.nojump
inc ebp
call [FxTablec+ecx*4]
ret
NEWSYM FxOpc08 ; BNE branch on not equal ; Verified.
movsx eax,byte[ebp]
inc ebp
test dword[SfxSignZero],0FFFFh
mov cl,[ebp]
jz .nojump
add ebp,eax
call [FxTablec+ecx*4]
ret
.nojump
inc ebp
call [FxTablec+ecx*4]
ret
NEWSYM FxOpc09 ; BEQ branch on equal (z=1) ; Verified.
movsx eax,byte[ebp]
inc ebp
test dword[SfxSignZero],0FFFFh
mov cl,[ebp]
jnz .nojump
add ebp,eax
call [FxTablec+ecx*4]
ret
.nojump
inc ebp
call [FxTablec+ecx*4]
ret
NEWSYM FxOpc0A ; BPL branch on plus ; Verified.
movsx eax,byte[ebp]
inc ebp
test dword[SfxSignZero],088000h
mov cl,[ebp]
jnz .nojump
add ebp,eax
call [FxTablec+ecx*4]
ret
.nojump
inc ebp
call [FxTablec+ecx*4]
ret
NEWSYM FxOpc0B ; BMI branch on minus ; Verified.
movsx eax,byte[ebp]
inc ebp
test dword[SfxSignZero],088000h
mov cl,[ebp]
jz .nojump
add ebp,eax
call [FxTablec+ecx*4]
ret
.nojump
inc ebp
call [FxTablec+ecx*4]
ret
NEWSYM FxOpc0C ; BCC branch on carry clear ; Verified.
movsx eax,byte[ebp]
inc ebp
test byte[SfxCarry],01h
mov cl,[ebp]
jnz .nojump
add ebp,eax
call [FxTablec+ecx*4]
ret
.nojump
inc ebp
call [FxTablec+ecx*4]
ret
NEWSYM FxOpc0D ; BCS branch on carry set ; Verified.
movsx eax,byte[ebp]
inc ebp
test byte[SfxCarry],01h
mov cl,[ebp]
jz .nojump
add ebp,eax
call [FxTablec+ecx*4]
ret
.nojump
inc ebp
call [FxTablec+ecx*4]
ret
NEWSYM FxOpc0E ; BVC branch on overflow clear ; Verified.
movsx eax,byte[ebp]
inc ebp
test byte[SfxOverflow],01h
mov cl,[ebp]
jnz .nojump
add ebp,eax
call [FxTablec+ecx*4]
ret
.nojump
inc ebp
call [FxTablec+ecx*4]
ret
NEWSYM FxOpc0F ; BVS branch on overflow set ; Verified.
movsx eax,byte[ebp]
inc ebp
test byte[SfxOverflow],01h
mov cl,[ebp]
jz .nojump
add ebp,eax
call [FxTablec+ecx*4]
ret
.nojump
inc ebp
call [FxTablec+ecx*4]
ret
NEWSYM FxOpc10 ; TO RN set register n as destination register
TORNc 0
NEWSYM FxOpc11 ; TO RN set register n as destination register
TORNc 1
NEWSYM FxOpc12 ; TO RN set register n as destination register
TORNc 2
NEWSYM FxOpc13 ; TO RN set register n as destination register
TORNc 3
NEWSYM FxOpc14 ; TO RN set register n as destination register
TORNc 4
NEWSYM FxOpc15 ; TO RN set register n as destination register
TORNc 5
NEWSYM FxOpc16 ; TO RN set register n as destination register
TORNc 6
NEWSYM FxOpc17 ; TO RN set register n as destination register
TORNc 7
NEWSYM FxOpc18 ; TO RN set register n as destination register
TORNc 8
NEWSYM FxOpc19 ; TO RN set register n as destination register
TORNc 9
NEWSYM FxOpc1A ; TO RN set register n as destination register
TORNc 10
NEWSYM FxOpc1B ; TO RN set register n as destination register
TORNc 11
NEWSYM FxOpc1C ; TO RN set register n as destination register
TORNc 12
NEWSYM FxOpc1D ; TO RN set register n as destination register
TORNc 13
NEWSYM FxOpc1E ; TO RN set register n as destination register
FETCHPIPE
mov eax,[esi] ; Read Source
mov [SfxR0+14*4],eax ; Write
CLRFLAGS
UpdateR14
inc ebp ; Increase program counter
ret
NEWSYM FxOpc1F ; TO RN set register n as destination register
FETCHPIPE
mov eax,[esi] ; Read Source
mov ebp,[SfxCPB]
mov [SfxR15],eax
add ebp,eax
CLRFLAGS
ret
NEWSYM FxOpc3D ; ALT1 set alt1 mode ; Verified.
FETCHPIPE
mov dword [SfxB],0
or ch,01h
inc ebp
call [FxTablec+ecx*4]
xor ch,ch
ret
NEWSYM FxOpc3E ; ALT2 set alt1 mode ; Verified.
FETCHPIPE
mov dword [SfxB],0
or ch,02h
inc ebp
call [FxTablec+ecx*4]
xor ch,ch
ret
NEWSYM FxOpc3F ; ALT3 set alt3 mode ; Verified.
FETCHPIPE
mov dword [SfxB],0
or ch,03h
inc ebp
call [FxTablec+ecx*4]
xor ch,ch
ret
NEWSYM FxOpcB0 ; FROM rn set source register
FROMRNc 0
NEWSYM FxOpcB1 ; FROM rn set source register
FROMRNc 1
NEWSYM FxOpcB2 ; FROM rn set source register
FROMRNc 2
NEWSYM FxOpcB3 ; FROM rn set source register
FROMRNc 3
NEWSYM FxOpcB4 ; FROM rn set source register
FROMRNc 4
NEWSYM FxOpcB5 ; FROM rn set source register
FROMRNc 5
NEWSYM FxOpcB6 ; FROM rn set source register
FROMRNc 6
NEWSYM FxOpcB7 ; FROM rn set source register
FROMRNc 7
NEWSYM FxOpcB8 ; FROM rn set source register
FROMRNc 8
NEWSYM FxOpcB9 ; FROM rn set source register
FROMRNc 9
NEWSYM FxOpcBA ; FROM rn set source register
FROMRNc 10
NEWSYM FxOpcBB ; FROM rn set source register
FROMRNc 11
NEWSYM FxOpcBC ; FROM rn set source register
FROMRNc 12
NEWSYM FxOpcBD ; FROM rn set source register
FROMRNc 13
NEWSYM FxOpcBE ; FROM rn set source register
FROMRNc 14
NEWSYM FxOpcBF ; FROM rn set source register
FETCHPIPE
mov eax,ebp
sub eax,[SfxCPB]
inc ebp
mov [edi],eax ; Write Destination
mov [SfxSignZero],eax
shr al,7
mov byte[SfxOverflow],al
CLRFLAGS
ret
NEWSYM FxEmu2BAsmEnd

View File

@ -1,88 +0,0 @@
;Copyright (C) 1997-2001 ZSNES Team ( zsknight@zsnes.com / _demo_@zsnes.com )
;
;This program is free software; you can redistribute it and/or
;modify it under the terms of the GNU General Public License
;as published by the Free Software Foundation; either
;version 2 of the License, or (at your option) any later
;version.
;
;This program is distributed in the hope that it will be useful,
;but WITHOUT ANY WARRANTY; without even the implied warranty of
;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;GNU General Public License for more details.
;
;You should have received a copy of the GNU General Public License
;along with this program; if not, write to the Free Software
;Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
%macro TORNb 1 ; V
FETCHPIPE
test dword [SfxB],1
jnz .VersionB
mov edi, SfxR0+%1*4
inc ebp ; Increase program counter
mov eax,ebp
sub eax,[SfxCPB]
mov dword[withr15sk],1
mov [SfxR15],eax
call [FxTableb+ecx*4]
mov edi,SfxR0
ret
.VersionB
mov eax,[esi] ; Read Source
mov dword[withr15sk],1
inc ebp ; Increase program counter
mov [SfxR0+%1*4],eax ; Write
CLRFLAGS
ret
%endmacro
%macro FROMRNb 1 ; V
FETCHPIPE
test dword [SfxB],1
jnz .VersionB
mov esi,SfxR0+%1*4
inc ebp ; Increase program counter
call [FxTable+ecx*4]
mov esi,SfxR0
ret
.VersionB
mov eax,[SfxR0+%1*4] ; Read
inc ebp
mov [edi],eax ; Write Destination
mov [SfxSignZero],eax
shr al,7
mov byte[SfxOverflow],al
CLRFLAGS
ret
%endmacro
%macro TORNc 1 ; V
FETCHPIPE
mov eax,[esi] ; Read Source
inc ebp ; Increase program counter
mov [SfxR0+%1*4],eax ; Write
CLRFLAGS
ret
%endmacro
%macro FROMRNc 1 ; V
FETCHPIPE
mov eax,[SfxR0+%1*4] ; Read
inc ebp
mov [edi],eax ; Write Destination
mov [SfxSignZero],eax
shr al,7
mov byte[SfxOverflow],al
CLRFLAGS
ret
%endmacro

File diff suppressed because it is too large Load Diff

View File

@ -1,528 +0,0 @@
;Copyright (C) 1997-2001 ZSNES Team ( zsknight@zsnes.com / _demo_@zsnes.com )
;
;This program is free software; you can redistribute it and/or
;modify it under the terms of the GNU General Public License
;as published by the Free Software Foundation; either
;version 2 of the License, or (at your option) any later
;version.
;
;This program is distributed in the hope that it will be useful,
;but WITHOUT ANY WARRANTY; without even the implied warranty of
;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;GNU General Public License for more details.
;
;You should have received a copy of the GNU General Public License
;along with this program; if not, write to the Free Software
;Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
%macro FXReturn 0
dec dword [NumberOfOpcodes]
jmp [FxTabled+ecx*4]
ALIGN32
%endmacro
%macro FXReturn2 0
dec dword [NumberOfOpcodes]
js %%endloop
jmp [FxTabled+ecx*4]
%%endloop
jmp FXEndLoop
; jmp [FxTabled+ecx*4]
ALIGN32
%endmacro
%macro TORNd 1 ; V
FETCHPIPE
mov edi, SfxR0+%1*4
inc ebp ; Increase program counter
call [FxTable+ecx*4]
mov edi,SfxR0
FXReturn
%endmacro
%macro WITHc 1 ; Verified.
FETCHPIPE
mov esi,SfxR0+%1*4
mov edi,SfxR0+%1*4
mov dword [SfxB],1
inc ebp ; Increase program counter
call [FxTablec+ecx*4]
mov esi,SfxR0
mov edi,SfxR0
mov dword [SfxB],0 ; Clear B Flag
FXReturn
%endmacro
%macro STWRNc 1 ; V
mov eax,[SfxR0+%1*4] ; Read register
mov ebx,[SfxRAMMem]
mov dword [SfxLastRamAdr],eax ; Save last ram address
add dword [SfxLastRamAdr],ebx ; Save last ram address
mov edx,[esi] ; Read Source
FETCHPIPE
mov [ebx+eax],dl ; Store Word
xor eax,1
inc ebp ; Increase program counter
mov [ebx+eax],dh ; Store Word
CLRFLAGS
FXReturn
%endmacro
%macro STBRNc 1 ; V
mov eax,[SfxR0+%1*4] ; Read register
FETCHPIPE
add eax,[SfxRAMMem]
mov dword [SfxLastRamAdr],eax ; Save last ram address
mov ebx,[esi] ; Read Source
mov byte [eax],bl ; Store Byte
CLRFLAGS
inc ebp ; Increase program counter
FXReturn
%endmacro
%macro LDWRNc 1 ; V
mov eax,[SfxR0+%1*4] ; Read register
mov ebx,[SfxRAMMem]
mov dword [SfxLastRamAdr],eax ; Save last ram address
FETCHPIPE
mov dl,[ebx+eax] ; Store Word
add dword [SfxLastRamAdr],ebx ; Save last ram address
xor eax,1
and edx,0FFFFh
inc ebp ; Increase program counter
mov dh,[ebx+eax] ; Store Word
mov [edi],edx ; Read Source
CLRFLAGS
FXReturn
%endmacro
%macro LDBRNc 1 ; V
mov eax,[SfxR0+%1*4] ; Read register
FETCHPIPE
add eax,[SfxRAMMem]
xor ebx,ebx
mov dword [SfxLastRamAdr],eax ; Save last ram address
mov bl,[eax] ; Read Byte
inc ebp ; Increase program counter
mov [edi],ebx ; Store Result
CLRFLAGS
FXReturn
%endmacro
%macro ADDRNc 1 ; V
mov eax, [esi] ; Read Source
mov ebx, [SfxR0+%1*4]
FETCHPIPE
add ax,bx
seto byte[SfxOverflow]
setc byte[SfxCarry]
mov [SfxSignZero],eax
inc ebp ; Increase program counter
mov [edi],eax ; Write Destination
CLRFLAGS
FXReturn
%endmacro
%macro ADCRNc 1 ; V
FETCHPIPE
mov eax, [esi] ; Read Source
mov ebx, [SfxR0+%1*4]
shr byte[SfxCarry],1
adc ax,bx
seto byte[SfxOverflow]
setc byte[SfxCarry]
mov [SfxSignZero],eax
inc ebp ; Increase program counter
mov [edi],eax ; Write Destination
CLRFLAGS
FXReturn
%endmacro
%macro ADIRNc 1 ; V
mov eax, [esi] ; Read Source
FETCHPIPE
add ax,%1
seto byte[SfxOverflow]
setc byte[SfxCarry]
mov [SfxSignZero],eax
inc ebp ; Increase program counter
mov [edi],eax ; Write Destination
CLRFLAGS
FXReturn
%endmacro
%macro ADCIRNc 1 ; V
FETCHPIPE
mov eax, [esi] ; Read Source
shr byte[SfxCarry],1
adc ax,%1
seto byte[SfxOverflow]
setc byte[SfxCarry]
mov [SfxSignZero],eax
inc ebp ; Increase program counter
mov [edi],eax ; Write Destination
CLRFLAGS
FXReturn
%endmacro
%macro SUBRNc 1 ; V
mov eax,[esi] ; Read Source
mov ebx,[SfxR0+%1*4]
FETCHPIPE
sub ax,bx
seto byte[SfxOverflow]
setc byte[SfxCarry]
xor byte[SfxCarry],1
inc ebp ; Increase program counter
mov [edi],eax ; Write Destination
mov [SfxSignZero],eax
CLRFLAGS
FXReturn
%endmacro
%macro SBCRNc 1 ; V
FETCHPIPE
mov eax,[esi] ; Read Source
mov ebx,[SfxR0+%1*4]
cmp byte[SfxCarry],1
sbb ax,bx
seto byte[SfxOverflow]
setc byte[SfxCarry]
xor byte[SfxCarry],1
inc ebp ; Increase program counter
mov [edi],eax ; Write Destination
mov [SfxSignZero],eax
CLRFLAGS
FXReturn
%endmacro
%macro SUBIRNc 1 ; V
mov eax,[esi] ; Read Source
FETCHPIPE
sub ax,%1
seto byte[SfxOverflow]
setc byte[SfxCarry]
xor byte[SfxCarry],1
inc ebp ; Increase program counter
mov [edi],eax ; Write Destination
mov [SfxSignZero],eax
CLRFLAGS
FXReturn
%endmacro
%macro CMPRNc 1 ; V
mov eax,[esi] ; Read Source
mov ebx,[SfxR0+%1*4]
FETCHPIPE
sub ax,bx
seto byte[SfxOverflow]
setc byte[SfxCarry]
xor byte[SfxCarry],1
mov [SfxSignZero],eax
CLRFLAGS
inc ebp ; Increase program counter
FXReturn
%endmacro
%macro ANDRNc 1 ; V
mov eax,[esi] ; Read Source
mov ebx,[SfxR0+%1*4] ; Read RN
FETCHPIPE
and eax,ebx
inc ebp
mov dword [SfxSignZero],eax
mov [edi],eax ; Write Destination
CLRFLAGS
FXReturn
%endmacro
%macro BICRNc 1 ; V
mov ebx,[SfxR0+%1*4] ; Read RN
mov eax,[esi] ; Read Source
xor ebx,0FFFFh
FETCHPIPE
and eax,ebx
inc ebp
mov dword [SfxSignZero],eax
mov [edi],eax ; Write Destination
CLRFLAGS
FXReturn
%endmacro
%macro ANDIRNc 1 ; V
mov eax,[esi] ; Read Source
FETCHPIPE
and eax,%1
inc ebp
mov dword [SfxSignZero],eax
mov [edi],eax ; Write Destination
CLRFLAGS
FXReturn
%endmacro
%macro BICIRNc 1 ; V
mov eax,[esi] ; Read Source
FETCHPIPE
and eax,%1
inc ebp
mov dword [SfxSignZero],eax
mov [edi],eax ; Write Destination
CLRFLAGS
FXReturn
%endmacro
%macro MULTRNc 1 ; V
mov al,byte [esi] ; Read Source
mov bl,byte [SfxR0+%1*4] ; Read RN
FETCHPIPE
imul bl
inc ebp
and eax,0FFFFh
mov [SfxSignZero],eax
mov [edi],eax ; Write Destination
CLRFLAGS
FXReturn
%endmacro
%macro UMULTRNc 1 ; V
mov al,byte [esi] ; Read Source
mov bl,byte [SfxR0+%1*4] ; Read RN
FETCHPIPE
mul bl
inc ebp
and eax,0FFFFh
mov [SfxSignZero],eax
mov [edi],eax ; Write Destination
CLRFLAGS
FXReturn
%endmacro
%macro MULTIRNc 1 ; V
mov al,byte [esi] ; Read Source
mov bl,%1 ; Read RN
FETCHPIPE
imul bl
inc ebp
and eax,0FFFFh
mov [SfxSignZero],eax
mov [edi],eax ; Write Destination
CLRFLAGS
FXReturn
%endmacro
%macro UMULTIRNc 1 ; V
mov al,byte [esi] ; Read Source
mov bl,%1 ; Read RN
FETCHPIPE
mul bl
inc ebp
and eax,0FFFFh
mov [SfxSignZero],eax
mov [edi],eax ; Write Destination
CLRFLAGS
FXReturn
%endmacro
%macro LINKc 1 ; Verified.
mov eax,ebp
sub eax,[SfxCPB]
add eax,%1
FETCHPIPE
mov word [SfxR11],ax
CLRFLAGS
inc ebp
FXReturn
%endmacro
%macro JMPRNc 1 ; V
FETCHPIPE
mov eax,[SfxR0+%1*4] ; Read RN
mov ebp,[SfxCPB]
add ebp,eax
CLRFLAGS
FXReturn
%endmacro
%macro LJMPRNc 1 ; V
FETCHPIPE
mov eax,[SfxR0+%1*4]
and eax,07Fh
mov byte[SfxPBR],al
; mov byte[fxtrace+eax],1
mov eax,[SfxMemTable+eax*4]
mov [SfxCPB],eax
mov ebp,eax
add ebp,[esi] ; Read RN
mov dword [SfxCacheActive],0
push ecx
call FxOp02
pop ecx
dec ebp
FXReturn
%endmacro
%macro IBTRNc 1 ; V
movsx eax,byte[ebp]
mov cl,[ebp+1]
add ebp,2
mov [SfxR0+%1*4],ax
CLRFLAGS
FXReturn
%endmacro
%macro LMSRNc 1 ; Verified.
xor eax,eax
mov al,[ebp]
add eax,eax
inc ebp
add eax,[SfxRAMMem]
mov cl,[ebp]
mov dword [SfxLastRamAdr],eax
mov ebx,[eax] ; Read word from ram
inc ebp
mov [SfxR0+%1*4],bx ; Write data
CLRFLAGS
FXReturn
%endmacro
%macro SMSRNc 1 ; Verified.
xor eax,eax
mov al,[ebp]
inc ebp
add eax,eax
mov cl,[ebp]
add eax,[SfxRAMMem]
mov ebx,[SfxR0+%1*4] ; Read data
mov dword [SfxLastRamAdr],eax
inc ebp
mov [eax],bx ; Write word to ram
CLRFLAGS
FXReturn
%endmacro
%macro FROMRNd 1 ; V
FETCHPIPE
mov esi,SfxR0+%1*4
inc ebp ; Increase program counter
call [FxTable+ecx*4]
mov esi,SfxR0
FXReturn
%endmacro
%macro ORRNc 1 ; V
mov eax,[esi] ; Read Source
mov ebx,[SfxR0+%1*4] ; Read
FETCHPIPE
or eax,ebx
inc ebp
mov [edi],eax ; Write DREG
mov [SfxSignZero],eax
CLRFLAGS
FXReturn
%endmacro
%macro XORRNc 1 ; V
mov eax,[esi] ; Read Source
mov ebx,[SfxR0+%1*4] ; Read
FETCHPIPE
xor eax,ebx
inc ebp
mov [edi],eax ; Write DREG
mov [SfxSignZero],eax
CLRFLAGS
FXReturn
%endmacro
%macro ORIc 1 ; V
mov eax,[esi] ; Read Source
FETCHPIPE
or eax,%1
inc ebp
mov [edi],eax ; Write DREG
mov [SfxSignZero],eax
CLRFLAGS
FXReturn
%endmacro
%macro XORIc 1 ; V
mov eax,[esi] ; Read Source
FETCHPIPE
xor eax,%1
inc ebp
mov [edi],eax ; Write DREG
mov [SfxSignZero],eax
CLRFLAGS
FXReturn
%endmacro
%macro INCRNc 1 ; Verified
inc word[SfxR0+%1*4]
FETCHPIPE
mov eax,[SfxR0+%1*4] ; Read Source
mov [SfxSignZero],eax
CLRFLAGS
inc ebp
FXReturn
%endmacro
%macro DECRNc 1 ; Verified
dec word[SfxR0+%1*4]
FETCHPIPE
mov eax,[SfxR0+%1*4] ; Read Source
mov [SfxR0+%1*4],eax
mov [SfxSignZero],eax
CLRFLAGS
inc ebp
FXReturn
%endmacro
%macro IWTRNc 1 ; aka LEA ; Verified.
mov eax,[ebp]
mov cl,[ebp+2]
and eax,0FFFFh
add ebp,3
mov [SfxR0+%1*4],eax
CLRFLAGS
FXReturn
%endmacro
%macro LMRNc 1 ; Verified!
xor eax,eax
mov cl,[ebp+2]
mov ax,[ebp]
mov ebx,[SfxRAMMem]
mov [SfxLastRamAdr],eax
add [SfxLastRamAdr],ebx
mov dl,[eax+ebx]
xor eax,1
add ebp,3
mov dh,[eax+ebx]
mov word [SfxR0+%1*4],dx ; Store Word
CLRFLAGS
FXReturn
%endmacro
%macro SMRNc 1 ; Verified
mov ebx,[SfxR0+%1*4]
mov eax,[ebp]
mov cl,[ebp+2]
and eax,0FFFFh
mov dx,bx
mov ebx,[SfxRAMMem]
mov [SfxLastRamAdr],eax
add [SfxLastRamAdr],ebx
mov [eax+ebx],dl
xor eax,1
add ebp,3
mov [eax+ebx],dh
CLRFLAGS
FXReturn
%endmacro

File diff suppressed because it is too large Load Diff

View File

@ -1,80 +0,0 @@
;Copyright (C) 1997-2006 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach )
;
;http://www.zsnes.com
;http://sourceforge.net/projects/zsnes
;
;This program is free software; you can redistribute it and/or
;modify it under the terms of the GNU General Public License
;version 2 as published by the Free Software Foundation.
;
;This program is distributed in the hope that it will be useful,
;but WITHOUT ANY WARRANTY; without even the implied warranty of
;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;GNU General Public License for more details.
;
;You should have received a copy of the GNU General Public License
;along with this program; if not, write to the Free Software
;Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
%ifidn __OUTPUT_FORMAT__,elf
section .note.GNU-stack noalloc noexec nowrite progbits
%endif
%ifdef __AMD64__
bits 64
%else
bits 32
%endif
section .text
; Zsnes required macros
%define ZVERSION 'Pre 1.43'
%ifdef MACHO
section .text align=16
section .data align=4
section .bss align=4
%endif
%ifdef ELF
%imacro newsym 1
GLOBAL %1
%1:
%endmacro
%imacro newsym 2+
GLOBAL %1
%1: %2
%endmacro
%define EXTSYM EXTERN
%else
%imacro newsym 1
GLOBAL _%1
_%1:
%1:
%endmacro
%imacro newsym 2+
GLOBAL _%1
_%1:
%1: %2
%endmacro
%imacro EXTSYM 1-*
%rep %0
EXTERN _%1
%define %1 _%1
%rotate 1
%endrep
%endmacro
%endif
%macro ALIGN32 0
times ($$-$) & 1Fh nop ; Long word alignment
%endmacro
%macro ALIGN16 0
times ($$-$) & 1Fh nop ; Long word alignment
%endmacro

View File

@ -1,101 +0,0 @@
; Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
;
; Super FX assembler emulator code
; (c) Copyright 1998, 1999 zsKnight and _Demo_.
;
; Permission to use, copy, modify and 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.
;
; Snes9x is freeware for PERSONAL USE only. Commercial users should
; seek permission of the copyright holders first. Commercial use includes
; charging money for Snes9x or software derived from Snes9x.
;
; 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.
;
;*******************************************************
; InitReg Initializes Registers
;*******************************************************
%macro setreg 2
mov edi,%1
add edi,[regptr]
mov eax,%2
mov [edi],eax
%endmacro
;*******************************************************
; Registers Note : Remember to restore AH, ECX, & DX
;*******************************************************
%macro checkmultchange 0
; execute multiplication
cmp byte[multchange],0
je .nomult
push edx
push eax
xor bh,bh
mov bl,[mode7B+1]
mov ax,[mode7A]
test bl,80h
jz .noneg
mov bh,0FFh
.noneg
imul bx
mov [compmult],ax
mov [compmult+2],dl
pop eax
pop edx
mov byte[multchange],0
.nomult
%endmacro
%macro mouse4016doxA 2
cmp byte[JoyAPos],%1
jne .nx7
mov bx,[mousexpos]
shr bx,%2
and bx,1
mov al,bl
.nx7
%endmacro
%macro mouse4016doyA 2
cmp byte[JoyAPos],%1
jne .ny7
mov bx,[mouseypos]
shr bx,%2
and bx,1
mov al,bl
.ny7
%endmacro
%macro mouse4017dox 2
cmp byte[JoyBPos],%1
jne .nx7
mov bx,[mousexpos]
shr bx,%2
and bx,1
mov al,bl
.nx7
%endmacro
%macro mouse4017doy 2
cmp byte[JoyBPos],%1
jne .ny7
mov bx,[mouseypos]
shr bx,%2
and bx,1
mov al,bl
.ny7
%endmacro

View File

@ -1,51 +0,0 @@
; Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
;
; Super FX assembler emulator code
; (c) Copyright 1998, 1999 zsKnight and _Demo_.
;
; Permission to use, copy, modify and 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.
;
; Snes9x is freeware for PERSONAL USE only. Commercial users should
; seek permission of the copyright holders first. Commercial use includes
; charging money for Snes9x or software derived from Snes9x.
;
; 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.
;
;*******************************************************
; InitRegW Initializes Write Registers
;*******************************************************
%macro reenablespc 0
cmp dword[cycpbl],1000000h
jb %%enspc
mov dword[cycpbl],0
test byte[curexecstate],02h
jnz %%enspc
or byte[curexecstate],02h
push ebx
xor ebx,ebx
mov bl,dl
EXTSYM tableadc
mov edi,[tableadc+ebx*4]
pop ebx
%%enspc
%endmacro
%macro setregw 2
mov edi,%1
add edi,[regptw]
mov eax,%2
mov [edi],eax
%endmacro

View File

@ -1,678 +0,0 @@
;Copyright (C) 1997-2001 ZSNES Team ( zsknight@zsnes.com / _demo_@zsnes.com )
;
;This program is free software; you can redistribute it and/or
;modify it under the terms of the GNU General Public License
;as published by the Free Software Foundation; either
;version 2 of the License, or (at your option) any later
;version.
;
;This program is distributed in the hope that it will be useful,
;but WITHOUT ANY WARRANTY; without even the implied warranty of
;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;GNU General Public License for more details.
;
;You should have received a copy of the GNU General Public License
;along with this program; if not, write to the Free Software
;Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
%include "macros.mac"
EXTSYM NumberOfOpcodes,SfxB,SfxBRAMR,SfxCBR,SfxCFGR,SfxCLSR,SfxCPB,SfxCROM
EXTSYM SfxCarry,SfxMemTable,SfxOverflow,SfxPBR,SfxPIPE,SfxR0,SfxR1,SfxR10
EXTSYM SfxR11,SfxR12,SfxR13,SfxR14,SfxR15,SfxR2,SfxR3,SfxR4,SfxR5,SfxR6
EXTSYM SfxR7,SfxR8,SfxR9,SfxRAMBR,SfxRAMMem,SfxROMBR,SfxSCBR,SfxSCMR,SfxSFR
EXTSYM SfxSignZero,SfxnRamBanks,StartSFX,regptr,regptw,sfxramdata
EXTSYM SfxPOR,sfxclineloc,UpdatePORSCMR,UpdateCLSR,UpdateSCBRCOLR,SfxAC
EXTSYM sfx128lineloc,sfx160lineloc,sfx192lineloc,sfxobjlineloc
NEWSYM SfxProcAsmStart
%include "regs.mac"
%include "regsw.mac"
%macro AssembleSFXFlags 0
and word[SfxSFR],8F60h
test byte[SfxCarry],1
jz .nosfxcarry
or word[SfxSFR],04h
.nosfxcarry
cmp word[SfxSignZero],0
jne .nozero
or word[SfxSFR],02h
.nozero
test word[SfxSignZero],8000h
jz .noneg
or word[SfxSFR],08h
.noneg
cmp byte[SfxOverflow],0
je .noof
or word[SfxSFR],10h
.noof
cmp byte[SfxB],0
je .bzero
or word[SfxSFR],1000h
.bzero
%endmacro
NEWSYM initsfxregsr
setreg 3000h*4,reg3000r
setreg 3001h*4,reg3001r
setreg 3002h*4,reg3002r
setreg 3003h*4,reg3003r
setreg 3004h*4,reg3004r
setreg 3005h*4,reg3005r
setreg 3006h*4,reg3006r
setreg 3007h*4,reg3007r
setreg 3008h*4,reg3008r
setreg 3009h*4,reg3009r
setreg 300Ah*4,reg300Ar
setreg 300Bh*4,reg300Br
setreg 300Ch*4,reg300Cr
setreg 300Dh*4,reg300Dr
setreg 300Eh*4,reg300Er
setreg 300Fh*4,reg300Fr
setreg 3010h*4,reg3010r
setreg 3011h*4,reg3011r
setreg 3012h*4,reg3012r
setreg 3013h*4,reg3013r
setreg 3014h*4,reg3014r
setreg 3015h*4,reg3015r
setreg 3016h*4,reg3016r
setreg 3017h*4,reg3017r
setreg 3018h*4,reg3018r
setreg 3019h*4,reg3019r
setreg 301Ah*4,reg301Ar
setreg 301Bh*4,reg301Br
setreg 301Ch*4,reg301Cr
setreg 301Dh*4,reg301Dr
setreg 301Eh*4,reg301Er
setreg 301Fh*4,reg301Fr
setreg 3030h*4,reg3030r
setreg 3031h*4,reg3031r
setreg 3032h*4,reg3032r
setreg 3033h*4,reg3033r
setreg 3034h*4,reg3034r
setreg 3035h*4,reg3035r
setreg 3036h*4,reg3036r
setreg 3037h*4,reg3037r
setreg 3038h*4,reg3038r
setreg 3039h*4,reg3039r
setreg 303Ah*4,reg303Ar
setreg 303Bh*4,reg303Br
setreg 303Ch*4,reg303Cr
setreg 303Dh*4,reg303Dr
setreg 303Eh*4,reg303Er
setreg 303Fh*4,reg303Fr
; set 3100-31FF to cacheregr
mov edi,3100h*4
add edi,[regptr]
mov eax,cacheregr
mov ecx,200h
.loop
mov [edi],eax
add edi,4
dec ecx
jnz .loop
ret
NEWSYM initsfxregsw
setregw 3000h*4,reg3000w
setregw 3001h*4,reg3001w
setregw 3002h*4,reg3002w
setregw 3003h*4,reg3003w
setregw 3004h*4,reg3004w
setregw 3005h*4,reg3005w
setregw 3006h*4,reg3006w
setregw 3007h*4,reg3007w
setregw 3008h*4,reg3008w
setregw 3009h*4,reg3009w
setregw 300Ah*4,reg300Aw
setregw 300Bh*4,reg300Bw
setregw 300Ch*4,reg300Cw
setregw 300Dh*4,reg300Dw
setregw 300Eh*4,reg300Ew
setregw 300Fh*4,reg300Fw
setregw 3010h*4,reg3010w
setregw 3011h*4,reg3011w
setregw 3012h*4,reg3012w
setregw 3013h*4,reg3013w
setregw 3014h*4,reg3014w
setregw 3015h*4,reg3015w
setregw 3016h*4,reg3016w
setregw 3017h*4,reg3017w
setregw 3018h*4,reg3018w
setregw 3019h*4,reg3019w
setregw 301Ah*4,reg301Aw
setregw 301Bh*4,reg301Bw
setregw 301Ch*4,reg301Cw
setregw 301Dh*4,reg301Dw
setregw 301Eh*4,reg301Ew
setregw 301Fh*4,reg301Fw
setregw 3030h*4,reg3030w
setregw 3031h*4,reg3031w
setregw 3032h*4,reg3032w
setregw 3033h*4,reg3033w
setregw 3034h*4,reg3034w
setregw 3035h*4,reg3035w
setregw 3036h*4,reg3036w
setregw 3037h*4,reg3037w
setregw 3038h*4,reg3038w
setregw 3039h*4,reg3039w
setregw 303Ah*4,reg303Aw
setregw 303Bh*4,reg303Bw
setregw 303Ch*4,reg303Cw
setregw 303Dh*4,reg303Dw
setregw 303Eh*4,reg303Ew
setregw 303Fh*4,reg303Fw
; set 3100-31FF to cacheregw
mov edi,3100h*4
add edi,[regptw]
mov eax,cacheregw
mov ecx,200h
.loop
mov [edi],eax
add edi,4
dec ecx
jnz .loop
ret
NEWSYM cacheregr
or byte[cachewarning],1
ret
NEWSYM cacheregw
or byte[cachewarning],2
ret
SECTION .bss
NEWSYM cachewarning, resb 1
NEWSYM SFXProc, resd 1
NEWSYM ChangeOps, resd 1
SECTION .text
; SFX Registers
NEWSYM reg3000r
mov al,[SfxR0]
ret
NEWSYM reg3001r
mov al,[SfxR0+1]
ret
NEWSYM reg3002r
mov al,[SfxR1]
ret
NEWSYM reg3003r
mov al,[SfxR1+1]
ret
NEWSYM reg3004r
mov al,[SfxR2]
ret
NEWSYM reg3005r
mov al,[SfxR2+1]
ret
NEWSYM reg3006r
mov al,[SfxR3]
ret
NEWSYM reg3007r
mov al,[SfxR3+1]
ret
NEWSYM reg3008r
mov al,[SfxR4]
ret
NEWSYM reg3009r
mov al,[SfxR4+1]
ret
NEWSYM reg300Ar
mov al,[SfxR5]
ret
NEWSYM reg300Br
mov al,[SfxR5+1]
ret
NEWSYM reg300Cr
mov al,[SfxR6]
ret
NEWSYM reg300Dr
mov al,[SfxR6+1]
ret
NEWSYM reg300Er
mov al,[SfxR7]
ret
NEWSYM reg300Fr
mov al,[SfxR7+1]
ret
NEWSYM reg3010r
mov al,[SfxR8]
ret
NEWSYM reg3011r
mov al,[SfxR8+1]
ret
NEWSYM reg3012r
mov al,[SfxR9]
ret
NEWSYM reg3013r
mov al,[SfxR9+1]
ret
NEWSYM reg3014r
mov al,[SfxR10]
ret
NEWSYM reg3015r
mov al,[SfxR10+1]
ret
NEWSYM reg3016r
mov al,[SfxR11]
ret
NEWSYM reg3017r
mov al,[SfxR11+1]
ret
NEWSYM reg3018r
mov al,[SfxR12]
ret
NEWSYM reg3019r
mov al,[SfxR12+1]
ret
NEWSYM reg301Ar
mov al,[SfxR13]
ret
NEWSYM reg301Br
mov al,[SfxR13+1]
ret
NEWSYM reg301Cr
mov al,[SfxR14]
ret
NEWSYM reg301Dr
mov al,[SfxR14+1]
ret
NEWSYM reg301Er
mov al,[SfxR15]
ret
NEWSYM reg301Fr
mov al,[SfxR15+1]
ret
; Other SFX stuff
NEWSYM reg3030r
AssembleSFXFlags
mov al,[SfxSFR]
ret
NEWSYM reg3031r
cmp byte[SfxAC],1
je .alwaysclear
cmp dword[ChangeOps],-350*240
jl .noclear
.alwaysclear
and byte[SfxSFR+1],07fh ; clear IRQ flag
jmp .cleared
.noclear
cmp dword[ChangeOps],-350*240*4
jge .clear
mov dword[ChangeOps],-350*240*4
jmp .cleared
.clear
add dword[ChangeOps],350*240
.cleared
mov al,[SfxSFR+1]
ret
SECTION .bss
.test resb 1
SECTION .text
NEWSYM reg3032r ; Unused
xor al,al
ret
NEWSYM reg3033r ; BRAMR Backup Ram Read only on/off (bits 1-15 unused)
mov al,[SfxBRAMR]
ret
NEWSYM reg3034r ; PBR (Program Bank)
mov al,[SfxPBR]
ret
NEWSYM reg3035r ; Unused
xor al,al
ret
NEWSYM reg3036r ; ROMBR (Gamepak Rom Bank Register)
mov al,[SfxROMBR]
ret
NEWSYM reg3037r ; CFGR (Control Flags Register)
mov al,[SfxCFGR]
ret
NEWSYM reg3038r ; SCBR (Screen Bank Register)
mov al,[SfxSCBR]
ret
NEWSYM reg3039r ; CLSR (Clock Speed Register)
mov al,[SfxCLSR]
ret
NEWSYM reg303Ar ; SCMR (Screen Mode Register)
mov al,[SfxSCMR]
test byte[SfxPOR],10h
jnz .objmode
mov al,[SfxSCMR]
and al,00100100b ; 4 + 32
cmp al,4
je .lines160
cmp al,32
je .lines192
cmp al,36
je .objmode
mov eax,[sfx128lineloc]
jmp .donelines
.lines160
mov eax,[sfx160lineloc]
jmp .donelines
.lines192
mov eax,[sfx192lineloc]
jmp .donelines
.objmode
mov eax,[sfxobjlineloc]
.donelines
mov [sfxclineloc],eax
ret
NEWSYM reg303Br ; VCR (Version Code Register)
mov al,20h
ret
NEWSYM reg303Cr ; RAMBR (Ram bank register)
mov al,[SfxRAMBR]
ret
NEWSYM reg303Dr ; Unused
xor al,al
ret
NEWSYM reg303Er ; CBR (Cache Base Register), lower byte
mov al,[SfxCBR]
ret
NEWSYM reg303Fr ; CBR (Cache Base Register), upper byte
mov al,[SfxCBR+1]
ret
; SFX Write Registers
NEWSYM reg3000w
mov [SfxR0],al
ret
NEWSYM reg3001w
mov [SfxR0+1],al
ret
NEWSYM reg3002w
mov [SfxR1],al
ret
NEWSYM reg3003w
mov [SfxR1+1],al
ret
NEWSYM reg3004w
mov [SfxR2],al
ret
NEWSYM reg3005w
mov [SfxR2+1],al
ret
NEWSYM reg3006w
mov [SfxR3],al
ret
NEWSYM reg3007w
mov [SfxR3+1],al
ret
NEWSYM reg3008w
mov [SfxR4],al
ret
NEWSYM reg3009w
mov [SfxR4+1],al
ret
NEWSYM reg300Aw
mov [SfxR5],al
ret
NEWSYM reg300Bw
mov [SfxR5+1],al
ret
NEWSYM reg300Cw
mov [SfxR6],al
ret
NEWSYM reg300Dw
mov [SfxR6+1],al
ret
NEWSYM reg300Ew
mov [SfxR7],al
ret
NEWSYM reg300Fw
mov [SfxR7+1],al
ret
NEWSYM reg3010w
mov [SfxR8],al
ret
NEWSYM reg3011w
mov [SfxR8+1],al
ret
NEWSYM reg3012w
mov [SfxR9],al
ret
NEWSYM reg3013w
mov [SfxR9+1],al
ret
NEWSYM reg3014w
mov [SfxR10],al
ret
NEWSYM reg3015w
mov [SfxR10+1],al
ret
NEWSYM reg3016w
mov [SfxR11],al
ret
NEWSYM reg3017w
mov [SfxR11+1],al
ret
NEWSYM reg3018w
mov [SfxR12],al
ret
NEWSYM reg3019w
mov [SfxR12+1],al
ret
NEWSYM reg301Aw
mov [SfxR13],al
ret
NEWSYM reg301Bw
mov [SfxR13+1],al
ret
NEWSYM reg301Cw
mov [SfxR14],al
ret
NEWSYM reg301Dw
mov [SfxR14+1],al
ret
NEWSYM reg301Ew
mov [SfxR15],al
ret
NEWSYM reg301Fw
mov [SfxR15+1],al
; start execution
push edx
mov edx,[SfxPBR]
mov edx,[SfxMemTable+edx*4]
add edx,[SfxR15]
mov dl,[edx]
mov [SfxPIPE],dl
pop edx
inc word[SfxR15]
or byte[SfxSFR],20h
or dword [SfxSFR],08000h ; Set IRQ Flag
mov dword[SFXProc],1
; call StartSFXret
ret
; Other SFX stuff
NEWSYM reg3030w
mov [SfxSFR],al
; mov dh,10
; Disassemble Flags
test al,20h
jz .noexec
mov dword [NumberOfOpcodes],100
call StartSFX
.noexec
ret
NEWSYM reg3031w
mov [SfxSFR+1],al
ret
NEWSYM reg3032w ; Unused
ret
NEWSYM reg3033w ; BRAMR Backup Ram Read only on/off (bits 1-15 unused)
and al,0FEh
mov [SfxBRAMR],al
ret
NEWSYM reg3034w ; PBR (Program Bank)
mov [SfxPBR],al
xor ebx,ebx
mov bl,al
mov ebx,[SfxMemTable+ebx*4]
mov [SfxCPB],ebx
ret
NEWSYM reg3035w ; Unused
ret
NEWSYM reg3036w ; ROMBR (Gamepak Rom Bank Register)
mov [SfxROMBR],al
xor ebx,ebx
mov bl,al
mov ebx,[SfxMemTable+ebx*4]
mov [SfxCROM],ebx
ret
NEWSYM reg3037w ; CFGR (Control Flags Register)
mov [SfxCFGR],al
ret
NEWSYM reg3038w ; SCBR (Screen Bank Register)
mov [SfxSCBR],al
call UpdateSCBRCOLR
ret
NEWSYM reg3039w ; CLSR (Clock Speed Register)
and al,0FEh
mov [SfxCLSR],al
call UpdateCLSR
ret
NEWSYM reg303Aw ; SCMR (Screen Mode Register)
mov [SfxSCMR],al
call UpdatePORSCMR
ret
NEWSYM reg303Bw ; VCR (Version Code Register)
ret
NEWSYM reg303Cw ; RAMBR (Ram bank register)
mov bl,[SfxnRamBanks]
dec bl
and al,bl
mov ebx,[SfxnRamBanks]
dec ebx
and eax,ebx
mov [SfxRAMBR],eax
xor ebx,ebx
mov bl,al
shl ebx,16
add ebx,[sfxramdata]
mov dword [SfxRAMMem],ebx
ret
NEWSYM reg303Dw ; Unused
ret
NEWSYM reg303Ew ; CBR (Cache Base Register), lower byte
mov [SfxCBR],al
ret
NEWSYM reg303Fw ; CBR (Cache Base Register), upper byte
mov [SfxCBR+1],al
ret
NEWSYM sfxaccessbankr8
mov ebx,[sfxramdata]
mov al,[ebx+ecx]
xor ebx,ebx
ret
NEWSYM sfxaccessbankw8
mov ebx,[sfxramdata]
mov [ebx+ecx],al
xor ebx,ebx
ret
NEWSYM sfxaccessbankr16
mov ebx,[sfxramdata]
mov ax,[ebx+ecx]
xor ebx,ebx
ret
NEWSYM sfxaccessbankw16
mov ebx,[sfxramdata]
mov [ebx+ecx],ax
xor ebx,ebx
ret
NEWSYM sfxaccessbankr8b
mov ebx,[sfxramdata]
mov al,[ebx+ecx+65536]
xor ebx,ebx
ret
NEWSYM sfxaccessbankw8b
mov ebx,[sfxramdata]
mov [ebx+ecx+65536],al
xor ebx,ebx
ret
NEWSYM sfxaccessbankr16b
mov ebx,[sfxramdata]
mov ax,[ebx+ecx+65536]
xor ebx,ebx
ret
NEWSYM sfxaccessbankw16b
mov ebx,[sfxramdata]
mov [ebx+ecx+65536],ax
xor ebx,ebx
ret
NEWSYM sfxaccessbankr8c
mov ebx,[sfxramdata]
mov al,[ebx+ecx+65536*2]
xor ebx,ebx
ret
NEWSYM sfxaccessbankw8c
mov ebx,[sfxramdata]
mov [ebx+ecx+65536*2],al
xor ebx,ebx
ret
NEWSYM sfxaccessbankr16c
mov ebx,[sfxramdata]
mov ax,[ebx+ecx+65536*2]
xor ebx,ebx
ret
NEWSYM sfxaccessbankw16c
mov ebx,[sfxramdata]
mov [ebx+ecx+65536*2],ax
xor ebx,ebx
ret
NEWSYM sfxaccessbankr8d
mov ebx,[sfxramdata]
mov al,[ebx+ecx+65536*3]
xor ebx,ebx
ret
NEWSYM sfxaccessbankw8d
mov ebx,[sfxramdata]
mov [ebx+ecx+65536*3],al
xor ebx,ebx
ret
NEWSYM sfxaccessbankr16d
mov ebx,[sfxramdata]
mov ax,[ebx+ecx+65536*3]
xor ebx,ebx
ret
NEWSYM sfxaccessbankw16d
mov ebx,[sfxramdata]
mov [ebx+ecx+65536*3],ax
xor ebx,ebx
ret
NEWSYM SfxProcAsmEnd

View File

@ -1,376 +0,0 @@
; Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
;
; Super FX assembler emulator code
; (c) Copyright 1998, 1999 zsKnight and _Demo_.
;
; Permission to use, copy, modify and 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.
;
; Snes9x is freeware for PERSONAL USE only. Commercial users should
; seek permission of the copyright holders first. Commercial use includes
; charging money for Snes9x or software derived from Snes9x.
;
; 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.
;
; ZSNES SuperFX emulation code and wrappers
; (C) Copyright 1997-8 zsKnight and _Demo_
; Used with the kind permission of the copyright holders.
;
%include "macros.mac"
EXTSYM SfxR1,SfxR2,InitFxTables,SfxSFR,SfxSCMR,initsfxregsw,initsfxregsr
EXTSYM SfxPBR,NumberOfOpcodes,SfxCLSR,MainLoop,SfxCROM
EXTSYM SfxRomBuffer,SfxRAMMem,SfxLastRamAdr,SfxR0
EXTSYM PHnum2writesfxreg, SfxCPB, SfxROMBR, SfxRAMBR, SfxnRamBanks
EXTSYM SfxSignZero
[BITS 32]
SECTION .data
NEWSYM flagnz, dd 0
NEWSYM romdata, dd 0 ; rom data (4MB = 4194304)
NEWSYM regptr, dd 0 ; pointer to registers
NEWSYM regptw, dd 0 ; pointer to registers
NEWSYM regptra, times 49152 db 0
NEWSYM regptwa, times 49152 db 0
NEWSYM debstop, db 0
NEWSYM sfxramdata, dd 0 ; SuperFX Ram Data
NEWSYM sfxplottable, dd 0
NEWSYM FxTable, times 256 dd 0
NEWSYM FxTableA1, times 256 dd 0
NEWSYM FxTableA2, times 256 dd 0
NEWSYM FxTableA3, times 256 dd 0
NEWSYM FxTableb, times 256 dd 0
NEWSYM FxTablebA1, times 256 dd 0
NEWSYM FxTablebA2, times 256 dd 0
NEWSYM FxTablebA3, times 256 dd 0
NEWSYM FxTablec, times 256 dd 0
NEWSYM FxTablecA1, times 256 dd 0
NEWSYM FxTablecA2, times 256 dd 0
NEWSYM FxTablecA3, times 256 dd 0
NEWSYM FxTabled, times 256 dd 0
NEWSYM FxTabledA1, times 256 dd 0
NEWSYM FxTabledA2, times 256 dd 0
NEWSYM FxTabledA3, times 256 dd 0
NEWSYM SfxMemTable, times 256 dd 0
NEWSYM fxxand, times 256 dd 0
NEWSYM fxbit01, times 256 dd 0
NEWSYM fxbit23, times 256 dd 0
NEWSYM fxbit45, times 256 dd 0
NEWSYM fxbit67, times 256 dd 0
NEWSYM PLOTJmpa, times 64 dd 0
NEWSYM PLOTJmpb, times 64 dd 0
NEWSYM NumberOfOpcodes2, dd 350
NEWSYM SFXCounter, dd 0
NEWSYM SfxAC, dd 0
;%INCLUDE "fxtable.asm"
;%INCLUDE "sfxproc.asm"
;%INCLUDE "fxemu2.asm"
;%INCLUDE "fxemu2b.asm"
;%INCLUDE "fxemu2c.asm"
;
; Snes9x wrapper functions for the zsnes SuperFX code
; (C) Copyright 1998 Gary Henderson
SECTION .data
EXTSYM SRAM,ROM,RegRAM,SFXPlotTable
SECTION .text
NEWSYM StartSFX
NEWSYM StartSFXret
jmp S9xSuperFXExec
NEWSYM S9xResetSuperFX
push ebx
push esi
push edi
push ebp
mov dword[SfxR1],0
mov dword[SfxR2],0
mov dword[SfxSignZero],1 ; clear z flag
mov eax,dword[SRAM]
mov dword[sfxramdata],eax
mov eax,dword[ROM]
mov dword[romdata],eax
mov eax,dword[SFXPlotTable]
mov dword[sfxplottable],eax
call InitFxTables
mov dword[SfxSFR],0
mov byte[SfxSCMR],0
mov dword[regptr],regptra
sub dword[regptr],8000h ; Since register address starts @ 2000h
mov dword[regptw],regptwa
sub dword[regptw],8000h ; Since register address starts @ 2000h
call initsfxregsw
call initsfxregsr
NEWSYM preparesfx
mov byte[SFXCounter],0
mov esi,[romdata]
add esi,07FC0h
cmp dword[esi],'FX S'
je .yessfxcounter
cmp dword[esi],'Stun'
jne .nosfxcounter
.yessfxcounter
mov byte[SFXCounter],1
.nosfxcounter
; make table
mov byte[SfxAC],0
mov eax,[romdata]
cmp dword[eax+02B80h],0AB6CAB6Ch
jne .noac
mov byte[SfxAC],1
.noac
call UpdateSFX
pop ebp
pop edi
pop esi
pop ebx
ret
NEWSYM S9xSuperFXWriteReg
mov eax,dword[esp+4]
mov ecx,dword[esp+8]
push ebx
push esi
push edi
push ebp
test dword[regptwa+ecx*4-8000h], ~0
jz .skipwrite
call dword[regptwa+ecx*4-8000h]
.skipwrite:
pop ebp
pop edi
pop esi
pop ebx
ret
NEWSYM S9xSuperFXReadReg
mov ecx,dword[esp+4]
push ebx
push esi
push edi
push ebp
test dword[regptra+ecx*4-8000h], ~0
jz .skipread
call dword[regptra+ecx*4-8000h]
.skipread:
pop ebp
pop edi
pop esi
pop ebx
and eax, 255
endfx:
ret
EXTSYM SCBRrel,SfxSCBR,SfxCOLR,SfxPOR
EXTSYM sfx128lineloc,sfx160lineloc,sfx192lineloc,sfxobjlineloc,sfxclineloc
EXTSYM fxbit01pcal,fxbit23pcal,fxbit45pcal,fxbit67pcal
NEWSYM S9xSuperFXExec
test byte[SfxSFR],20h
jz endfx
push ebx
push esi
push edi
push ebp
xor ebx,ebx
mov bl,[SfxPBR]
mov al,[SfxSCMR]
and bl,7Fh
cmp bl,70h
jae .ram
test al,10h
jz .noaccess
jmp .noram
.ram
test al,08h
jz .noaccess
.noram
mov eax,[NumberOfOpcodes2]
mov [NumberOfOpcodes],eax
call MainLoop
.noaccess
pop ebp
pop edi
pop esi
pop edx
ret
NEWSYM S9xSuperFXPreSaveState
mov ecx,dword[SfxCROM]
sub dword[SfxRomBuffer],ecx
mov ecx,dword[SfxRAMMem]
sub dword[SfxLastRamAdr],ecx
; Copy num2writesfxreg bytes from SfxR0 to a free area in RegRAM.
push ebx
mov ecx,SfxR0
mov edx,dword[RegRAM]
add edx,7000h
mov ebx,[PHnum2writesfxreg]
.loop
mov al,[ecx]
mov [edx],al
inc ecx
inc edx
dec ebx
jnz .loop
pop ebx
mov ecx,dword[SfxCROM]
add dword[SfxRomBuffer],ecx
mov ecx,dword[SfxRAMMem]
add dword[SfxLastRamAdr],ecx
ret
NEWSYM S9xSuperFXPostSaveState
ret
NEWSYM S9xSuperFXPostLoadState
; Copy num2writesfxreg bytes from a free area in RegRAM to SfxR0
push ebx
mov ecx,SfxR0
mov edx,dword[RegRAM]
add edx,7000h
mov ebx,[PHnum2writesfxreg]
.loop
mov al,[edx]
mov [ecx],al
inc ecx
inc edx
dec ebx
jnz .loop
pop ebx
xor ecx,ecx
mov cl,byte[SfxPBR]
mov ecx,dword[SfxMemTable+ecx*4]
mov dword[SfxCPB],ecx
xor ecx,ecx
mov cl,byte[SfxROMBR]
mov ecx,dword[SfxMemTable+ecx*4]
mov dword[SfxCROM],ecx
xor ecx,ecx
mov cl,byte[SfxRAMBR]
shl ecx,16
add ecx,dword[sfxramdata]
mov dword [SfxRAMMem],ecx
mov ecx,dword[SfxCROM]
add dword[SfxRomBuffer],ecx
mov ecx,dword[SfxRAMMem]
add dword[SfxLastRamAdr],ecx
; Fix for mystery zeroing of SfxnRamBanks, allowing junk RAMBR values to be
; set in turn causing a crash when the code tries to access the junk RAM bank.
mov dword [SfxnRamBanks], 4
call UpdateSFX
ret
NEWSYM UpdatePORSCMR
push ebx
push eax
test byte[SfxPOR],10h
jnz .objmode
mov al,[SfxSCMR]
and al,00100100b ; 4 + 32
cmp al,4
je .lines160
cmp al,32
je .lines192
cmp al,36
je .objmode
mov eax,[sfx128lineloc]
jmp .donelines
.lines160
mov eax,[sfx160lineloc]
jmp .donelines
.lines192
mov eax,[sfx192lineloc]
jmp .donelines
.objmode
mov eax,[sfxobjlineloc]
.donelines
mov [sfxclineloc],eax
mov al,[SfxSCMR]
and eax,00000011b
mov bl,[SfxPOR]
and bl,0Fh
shl bl,2
or al,bl
mov ebx,[PLOTJmpb+eax*4]
mov eax,[PLOTJmpa+eax*4]
mov dword [FxTable+4Ch*4],eax
mov dword [FxTableb+4Ch*4],eax
mov dword [FxTablec+4Ch*4],eax
mov dword [FxTabled+4Ch*4],ebx
pop eax
pop ebx
ret
NEWSYM UpdateSCBRCOLR
push eax
push ebx
mov ebx,[SfxSCBR]
shl ebx,10
add ebx,[sfxramdata]
mov [SCBRrel],ebx
mov eax,[SfxCOLR]
mov ebx,[fxbit01+eax*4]
mov [fxbit01pcal],ebx
mov ebx,[fxbit23+eax*4]
mov [fxbit23pcal],ebx
mov ebx,[fxbit45+eax*4]
mov [fxbit45pcal],ebx
mov ebx,[fxbit67+eax*4]
mov [fxbit67pcal],ebx
pop ebx
pop eax
ret
NEWSYM UpdateCLSR
mov dword [NumberOfOpcodes2],350 ; 0FFFFFFFh;350
test byte[SfxCLSR],01h
jz .nohighsfx
mov dword [NumberOfOpcodes2],700 ;700
.nohighsfx
cmp byte[SFXCounter],1
je .noyi
mov dword [NumberOfOpcodes2],0FFFFFFFh
.noyi
ret
NEWSYM UpdateSFX
call UpdatePORSCMR
call UpdatePORSCMR
call UpdateCLSR
ret

View File

@ -1,92 +0,0 @@
; Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
;
; Super FX assembler emulator code
; (c) Copyright 1998, 1999 zsKnight and _Demo_.
;
; Permission to use, copy, modify and 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.
;
; Snes9x is freeware for PERSONAL USE only. Commercial users should
; seek permission of the copyright holders first. Commercial use includes
; charging money for Snes9x or software derived from Snes9x.
;
; 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.
;
; ZSNES SuperFX emulation code and wrappers
; (C) Copyright 1997-8 zsKnight and _Demo_
; Used with the kind permission of the copyright holders.
;
%include "macros.mac"
EXTSYM InitC4, C4RegFunction, C4ReadReg, C4WriteReg
EXTSYM romdata
[BITS 32]
SECTION .data
NEWSYM C4Ram, dd 0
NEWSYM C4RamR, dd 0
NEWSYM C4RamW, dd 0
NEWSYM pressed, dd 0 ; used by C4Edit (unused function)
NEWSYM vidbuffer,dd 0 ; used by C4Edit
NEWSYM oamram, times 544 db 0 ; Sprite PPU data used by C4 routines
;
; Snes9x wrapper functions for the zsnes C4 code
; (C) Copyright 2000 Gary Henderson
SECTION .data
EXTSYM ROM,RegRAM
SECTION .text
NEWSYM S9xInitC4
pushad
mov eax,dword[ROM]
mov dword[romdata],eax
call InitC4
; mov eax,dword[RegRAM]
; add eax,06000h
; mov dword[C4Ram],eax
popad
ret
NEWSYM S9xSetC4
NEWSYM S9xSetC4RAM
mov ecx, dword[esp+8]
mov eax, dword[esp+4]
and ecx, 0ffffh
push ebx
push esi
push edi
push ebp
sub ecx, 6000h
call C4RegFunction
pop ebp
pop edi
pop esi
pop ebx
ret
NEWSYM S9xGetC4
NEWSYM S9xGetC4RAM
mov ecx, dword[esp+4]
xor eax, eax
and ecx, 0ffffh
sub ecx, 06000h
jmp C4ReadReg

View File

@ -1134,21 +1134,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;
@ -2263,10 +2253,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
@ -2392,9 +2380,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
@ -3493,7 +3479,6 @@ bool8 CMemory::match_id (const char *str)
void CMemory::ApplyROMFixes (void)
{
Settings.Shutdown = Settings.ShutdownMaster;
Settings.BlockInvalidVRAMAccess = Settings.BlockInvalidVRAMAccessMaster;
//// Warnings
@ -3570,6 +3555,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)
{
@ -3584,14 +3570,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,
@ -3601,12 +3579,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)
@ -3619,242 +3591,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)

View File

@ -357,14 +357,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 *);

282
ppu.cpp
View File

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

12
ppu.h
View File

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

559
sa1.cpp
View File

@ -180,7 +180,6 @@
uint8 SA1OpenBus;
static void S9xSA1Reset (void);
static void S9xSA1SetBWRAMMemMap (uint8);
static void S9xSetSA1MemMap (uint32, uint8);
static void S9xSA1CharConv2 (void);
@ -190,31 +189,37 @@ static void S9xSA1ReadVariableLengthData (bool8, bool8);
void S9xSA1Init (void)
{
SA1.IRQActive = FALSE;
SA1.WaitingForInterrupt = FALSE;
SA1.Waiting = FALSE;
SA1.Cycles = 0;
SA1.PrevCycles = 0;
SA1.Flags = 0;
SA1.Executing = FALSE;
SA1.WaitingForInterrupt = FALSE;
memset(&Memory.FillRAM[0x2200], 0, 0x200);
Memory.FillRAM[0x2200] = 0x20;
Memory.FillRAM[0x2220] = 0x00;
Memory.FillRAM[0x2221] = 0x01;
Memory.FillRAM[0x2222] = 0x02;
Memory.FillRAM[0x2223] = 0x03;
Memory.FillRAM[0x2228] = 0xff;
Memory.FillRAM[0x2228] = 0x0f;
SA1.in_char_dma = FALSE;
SA1.TimerIRQLastState = FALSE;
SA1.HTimerIRQPos = 0;
SA1.VTimerIRQPos = 0;
SA1.HCounter = 0;
SA1.VCounter = 0;
SA1.PrevHCounter = 0;
SA1.arithmetic_op = 0;
SA1.op1 = 0;
SA1.op2 = 0;
SA1.arithmetic_op = 0;
SA1.sum = 0;
SA1.overflow = FALSE;
SA1.S9xOpcodes = NULL;
}
SA1.VirtualBitmapFormat = 0;
SA1.variable_bit_pos = 0;
static void S9xSA1Reset (void)
{
SA1Registers.PBPC = 0;
SA1Registers.PB = 0;
SA1Registers.PCw = Memory.FillRAM[0x2203] | (Memory.FillRAM[0x2204] << 8);
SA1Registers.PCw = 0;
SA1Registers.D.W = 0;
SA1Registers.DB = 0;
SA1Registers.SH = 1;
@ -228,17 +233,20 @@ static void S9xSA1Reset (void)
SA1SetFlags(MemoryFlag | IndexFlag | IRQ | Emulation);
SA1ClearFlags(Decimal);
SA1.WaitingForInterrupt = FALSE;
SA1.PCBase = NULL;
S9xSA1SetPCBase(SA1Registers.PBPC);
SA1.MemSpeed = SLOW_ONE_CYCLE;
SA1.MemSpeedx2 = SLOW_ONE_CYCLE * 2;
SA1.S9xOpcodes = S9xSA1OpcodesM1X1;
SA1.S9xOpLengths = S9xOpLengthsM1X1;
S9xSA1SetPCBase(SA1Registers.PBPC);
S9xSA1UnpackStatus();
S9xSA1FixCycles();
SA1.Executing = TRUE;
SA1.BWRAM = Memory.SRAM;
Memory.FillRAM[0x2225] = 0;
CPU.IRQExternal = FALSE;
}
static void S9xSA1SetBWRAMMemMap (uint8 val)
@ -280,23 +288,6 @@ void S9xSA1PostLoadState (void)
SA1.VirtualBitmapFormat = (Memory.FillRAM[0x223f] & 0x80) ? 2 : 4;
Memory.BWRAM = Memory.SRAM + (Memory.FillRAM[0x2224] & 7) * 0x2000;
S9xSA1SetBWRAMMemMap(Memory.FillRAM[0x2225]);
SA1.Waiting = (Memory.FillRAM[0x2200] & 0x60) != 0;
SA1.Executing = !SA1.Waiting;
}
void S9xSA1ExecuteDuringSleep (void)
{
#if 0
if (SA1.Executing)
{
while (CPU.Cycles < CPU.NextEvent)
{
S9xSA1MainLoop();
CPU.Cycles += TWO_CYCLES * 2;
}
}
#endif
}
static void S9xSetSA1MemMap (uint32 which1, uint8 map)
@ -326,31 +317,48 @@ uint8 S9xGetSA1 (uint32 address)
{
switch (address)
{
case 0x2300:
return ((uint8) ((Memory.FillRAM[0x2209] & 0x5f) | (CPU.IRQActive & (SA1_IRQ_SOURCE | SA1_DMA_IRQ_SOURCE))));
case 0x2300: // S-CPU flag
return ((Memory.FillRAM[0x2209] & 0x5f) | (Memory.FillRAM[0x2300] & 0xa0));
case 0x2301:
return ((Memory.FillRAM[0x2200] & 0xf) | (Memory.FillRAM[0x2301] & 0xf0));
case 0x2301: // SA-1 flag
return ((Memory.FillRAM[0x2200] & 0x0f) | (Memory.FillRAM[0x2301] & 0xf0));
case 0x2306:
case 0x2302: // H counter (L)
SA1.HTimerIRQPos = SA1.HCounter / ONE_DOT_CYCLE;
SA1.VTimerIRQPos = SA1.VCounter;
return ((uint8) SA1.HTimerIRQPos);
case 0x2303: // H counter (H)
return ((uint8) (SA1.HTimerIRQPos >> 8));
case 0x2304: // V counter (L)
return ((uint8) SA1.VTimerIRQPos);
case 0x2305: // V counter (H)
return ((uint8) (SA1.VTimerIRQPos >> 8));
case 0x2306: // arithmetic result (LLL)
return ((uint8) SA1.sum);
case 0x2307:
case 0x2307: // arithmetic result (LLH)
return ((uint8) (SA1.sum >> 8));
case 0x2308:
case 0x2308: // arithmetic result (LHL)
return ((uint8) (SA1.sum >> 16));
case 0x2309:
case 0x2309: // arithmetic result (LLH)
return ((uint8) (SA1.sum >> 24));
case 0x230a:
case 0x230a: // arithmetic result (HLL)
return ((uint8) (SA1.sum >> 32));
case 0x230c:
case 0x230b: // arithmetic overflow
return (SA1.overflow ? 0x80 : 0);
case 0x230c: // variable-length data read port (L)
return (Memory.FillRAM[0x230c]);
case 0x230d:
case 0x230d: // variable-length data read port (H)
{
uint8 byte = Memory.FillRAM[0x230d];
@ -360,8 +368,10 @@ uint8 S9xGetSA1 (uint32 address)
return (byte);
}
case 0x230e: // version code register
return (0x01);
default:
//printf("R: %04x\n", address);
break;
}
@ -372,337 +382,279 @@ void S9xSetSA1 (uint8 byte, uint32 address)
{
switch (address)
{
case 0x2200:
SA1.Waiting = (byte & 0x60) != 0;
//SA1.Executing = !SA1.Waiting && SA1.S9xOpcodes;
case 0x2200: // SA-1 control
#ifdef DEBUGGER
if (byte & 0x60)
printf("SA-1 sleep\n");
#endif
if (!(byte & 0x20) && (Memory.FillRAM[0x2200] & 0x20))
S9xSA1Reset();
// SA-1 reset
if (!(byte & 0x80) && (Memory.FillRAM[0x2200] & 0x20))
{
#ifdef DEBUGGER
printf("SA-1 reset\n");
#endif
SA1Registers.PBPC = 0;
SA1Registers.PB = 0;
SA1Registers.PCw = Memory.FillRAM[0x2203] | (Memory.FillRAM[0x2204] << 8);
S9xSA1SetPCBase(SA1Registers.PBPC);
}
// SA-1 IRQ control
if (byte & 0x80)
{
Memory.FillRAM[0x2301] |= 0x80;
if (Memory.FillRAM[0x220a] & 0x80)
{
SA1.Flags |= IRQ_FLAG;
SA1.IRQActive |= SNES_IRQ_SOURCE;
SA1.Executing = !SA1.Waiting && SA1.S9xOpcodes;
}
Memory.FillRAM[0x220b] &= ~0x80;
}
// SA-1 NMI control
if (byte & 0x10)
{
Memory.FillRAM[0x2301] |= 0x10;
if (Memory.FillRAM[0x220a] & 0x10)
Memory.FillRAM[0x220b] &= ~0x10;
}
break;
case 0x2201: // S-CPU interrupt enable
// S-CPU IRQ enable
if (((byte ^ Memory.FillRAM[0x2201]) & 0x80) && (Memory.FillRAM[0x2300] & byte & 0x80))
{
Memory.FillRAM[0x2202] &= ~0x80;
CPU.IRQExternal = TRUE;
}
// S-CPU CHDMA IRQ enable
if (((byte ^ Memory.FillRAM[0x2201]) & 0x20) && (Memory.FillRAM[0x2300] & byte & 0x20))
{
Memory.FillRAM[0x2202] &= ~0x20;
CPU.IRQExternal = TRUE;
}
break;
case 0x2202: // S-CPU interrupt clear
// S-CPU IRQ clear
if (byte & 0x80)
Memory.FillRAM[0x2300] &= ~0x80;
// S-CPU CHDMA IRQ clear
if (byte & 0x20)
Memory.FillRAM[0x2300] &= ~0x20;
if (!(Memory.FillRAM[0x2300] & 0xa0))
CPU.IRQExternal = FALSE;
break;
case 0x2203: // SA-1 reset vector (L)
case 0x2204: // SA-1 reset vector (H)
case 0x2205: // SA-1 NMI vector (L)
case 0x2206: // SA-1 NMI vector (H)
case 0x2207: // SA-1 IRQ vector (L)
case 0x2208: // SA-1 IRQ vector (H)
break;
case 0x2209: // S-CPU control
// 0x40: S-CPU IRQ overwrite
// 0x20: S-CPU NMI overwrite
// S-CPU IRQ control
if (byte & 0x80)
{
Memory.FillRAM[0x2300] |= 0x80;
if (Memory.FillRAM[0x2201] & 0x80)
{
SA1.Flags |= NMI_FLAG;
SA1.Executing = !SA1.Waiting && SA1.S9xOpcodes;
Memory.FillRAM[0x2202] &= ~0x80;
CPU.IRQExternal = TRUE;
}
}
break;
case 0x2201:
if (((byte ^ Memory.FillRAM[0x2201]) & 0x80) && (Memory.FillRAM[0x2300] & byte & 0x80))
S9xSetIRQ(SA1_IRQ_SOURCE);
if (((byte ^ Memory.FillRAM[0x2201]) & 0x20) && (Memory.FillRAM[0x2300] & byte & 0x20))
S9xSetIRQ(SA1_DMA_IRQ_SOURCE);
break;
case 0x2202:
if (byte & 0x80)
{
Memory.FillRAM[0x2300] &= ~0x80;
S9xClearIRQ(SA1_IRQ_SOURCE);
}
if (byte & 0x20)
{
Memory.FillRAM[0x2300] &= ~0x20;
S9xClearIRQ(SA1_DMA_IRQ_SOURCE);
}
break;
case 0x2203:
//printf("SA1 reset vector: %04x\n", byte | (Memory.FillRAM[0x2204] << 8));
break;
case 0x2204:
//printf("SA1 reset vector: %04x\n", (byte << 8) | Memory.FillRAM[0x2203]);
break;
case 0x2205:
//printf("SA1 NMI vector: %04x\n", byte | (Memory.FillRAM[0x2206] << 8));
break;
case 0x2206:
//printf("SA1 NMI vector: %04x\n", (byte << 8) | Memory.FillRAM[0x2205]);
break;
case 0x2207:
//printf("SA1 IRQ vector: %04x\n", byte | (Memory.FillRAM[0x2208] << 8));
break;
case 0x2208:
//printf("SA1 IRQ vector: %04x\n", (byte << 8) | Memory.FillRAM[0x2207]);
break;
case 0x2209:
Memory.FillRAM[0x2209] = byte;
if (byte & 0x80)
Memory.FillRAM[0x2300] |= 0x80;
if (byte & Memory.FillRAM[0x2201] & 0x80)
S9xSetIRQ(SA1_IRQ_SOURCE);
break;
case 0x220a:
case 0x220a: // SA-1 interrupt enable
// SA-1 IRQ enable
if (((byte ^ Memory.FillRAM[0x220a]) & 0x80) && (Memory.FillRAM[0x2301] & byte & 0x80))
{
SA1.Flags |= IRQ_FLAG;
SA1.IRQActive |= SNES_IRQ_SOURCE;
//SA1.Executing = !SA1.Waiting;
}
Memory.FillRAM[0x220b] &= ~0x80;
// SA-1 timer IRQ enable
if (((byte ^ Memory.FillRAM[0x220a]) & 0x40) && (Memory.FillRAM[0x2301] & byte & 0x40))
{
SA1.Flags |= IRQ_FLAG;
SA1.IRQActive |= TIMER_IRQ_SOURCE;
//SA1.Executing = !SA1.Waiting;
}
Memory.FillRAM[0x220b] &= ~0x40;
// SA-1 DMA IRQ enable
if (((byte ^ Memory.FillRAM[0x220a]) & 0x20) && (Memory.FillRAM[0x2301] & byte & 0x20))
{
SA1.Flags |= IRQ_FLAG;
SA1.IRQActive |= DMA_IRQ_SOURCE;
//SA1.Executing = !SA1.Waiting;
}
Memory.FillRAM[0x220b] &= ~0x20;
// SA-1 NMI enable
if (((byte ^ Memory.FillRAM[0x220a]) & 0x10) && (Memory.FillRAM[0x2301] & byte & 0x10))
{
SA1.Flags |= NMI_FLAG;
//SA1.Executing = !SA1.Waiting;
}
Memory.FillRAM[0x220b] &= ~0x10;
break;
case 0x220b:
case 0x220b: // SA-1 interrupt clear
// SA-1 IRQ clear
if (byte & 0x80)
{
SA1.IRQActive &= ~SNES_IRQ_SOURCE;
Memory.FillRAM[0x2301] &= ~0x80;
}
// SA-1 timer IRQ clear
if (byte & 0x40)
{
SA1.IRQActive &= ~TIMER_IRQ_SOURCE;
Memory.FillRAM[0x2301] &= ~0x40;
}
// SA-1 DMA IRQ clear
if (byte & 0x20)
{
SA1.IRQActive &= ~DMA_IRQ_SOURCE;
Memory.FillRAM[0x2301] &= ~0x20;
}
// SA-1 NMI clear
if (byte & 0x10)
Memory.FillRAM[0x2301] &= ~0x10;
if (!SA1.IRQActive)
SA1.Flags &= ~IRQ_FLAG;
break;
case 0x220c:
//printf("SNES NMI vector: %04x\n", byte | (Memory.FillRAM[0x220d] << 8));
case 0x220c: // S-CPU NMI vector (L)
case 0x220d: // S-CPU NMI vector (H)
case 0x220e: // S-CPU IRQ vector (L)
case 0x220f: // S-CPU IRQ vector (H)
break;
case 0x220d:
//printf("SNES NMI vector: %04x\n", (byte << 8) | Memory.FillRAM[0x220c]);
break;
case 0x220e:
//printf("SNES IRQ vector: %04x\n", byte | (Memory.FillRAM[0x220f] << 8));
break;
case 0x220f:
//printf("SNES IRQ vector: %04x\n", (byte << 8) | Memory.FillRAM[0x220e]);
break;
case 0x2210:
#if 0
printf("Timer %s\n", (byte & 0x80) ? "linear" : "HV");
printf("Timer H-IRQ %s\n", (byte & 1) ? "enabled" : "disabled");
printf("Timer V-IRQ %s\n", (byte & 2) ? "enabled" : "disabled");
case 0x2210: // SA-1 timer control
// 0x80: mode (linear / HV)
// 0x02: V timer enable
// 0x01: H timer enable
#ifdef DEBUGGER
printf("SA-1 timer control write:%02x\n", byte);
#endif
break;
case 0x2211:
//printf("Timer reset\n");
case 0x2211: // SA-1 timer reset
SA1.HCounter = 0;
SA1.VCounter = 0;
break;
case 0x2212:
//printf("H-Timer %04x\n", byte | (Memory.FillRAM[0x2213] << 8));
case 0x2212: // SA-1 H-timer (L)
SA1.HTimerIRQPos = byte | (Memory.FillRAM[0x2213] << 8);
break;
case 0x2213:
//printf("H-Timer %04x\n", (byte << 8) | Memory.FillRAM[0x2212]);
case 0x2213: // SA-1 H-timer (H)
SA1.HTimerIRQPos = (byte << 8) | Memory.FillRAM[0x2212];
break;
case 0x2214:
//printf("V-Timer %04x\n", byte | (Memory.FillRAM[0x2215] << 8));
case 0x2214: // SA-1 V-timer (L)
SA1.VTimerIRQPos = byte | (Memory.FillRAM[0x2215] << 8);
break;
case 0x2215:
//printf("V-Timer %04x\n", (byte << 8) | Memory.FillRAM[0x2214]);
case 0x2215: // SA-1 V-timer (H)
SA1.VTimerIRQPos = (byte << 8) | Memory.FillRAM[0x2214];
break;
case 0x2220:
case 0x2221:
case 0x2222:
case 0x2223:
//printf("MMC: %02x\n", byte);
case 0x2220: // MMC bank C
case 0x2221: // MMC bank D
case 0x2222: // MMC bank E
case 0x2223: // MMC bank F
S9xSetSA1MemMap(address - 0x2220, byte);
break;
case 0x2224:
//printf("BWRAM image SNES %02x -> 0x6000\n", byte);
case 0x2224: // S-CPU BW-RAM mapping
Memory.BWRAM = Memory.SRAM + (byte & 7) * 0x2000;
break;
case 0x2225:
//printf("BWRAM image SA1 %02x -> 0x6000 (%02x)\n", byte, Memory.FillRAM[0x2225]);
case 0x2225: // SA-1 BW-RAM mapping
if (byte != Memory.FillRAM[0x2225])
S9xSA1SetBWRAMMemMap(byte);
break;
case 0x2226:
//printf("BW-RAM SNES write %s\n", (byte & 0x80) ? "enabled" : "disabled");
case 0x2226: // S-CPU BW-RAM write enable
case 0x2227: // SA-1 BW-RAM write enable
case 0x2228: // BW-RAM write-protected area
case 0x2229: // S-CPU I-RAM write protection
case 0x222a: // SA-1 I-RAM write protection
break;
case 0x2227:
//printf("BW-RAM SA1 write %s\n", (byte & 0x80) ? "enabled" : "disabled");
case 0x2230: // DMA control
// 0x80: enable
// 0x40: priority (DMA / SA-1)
// 0x20: character conversion / normal
// 0x10: BW-RAM -> I-RAM / SA-1 -> I-RAM
// 0x04: destinatin (BW-RAM / I-RAM)
// 0x03: source
break;
case 0x2228:
//printf("BW-RAM write protect area %02x\n", byte);
break;
case 0x2229:
//printf("I-RAM SNES write protect area %02x\n", byte);
break;
case 0x222a:
//printf("I-RAM SA1 write protect area %02x\n", byte);
break;
case 0x2230:
#if 0
printf("SA1 DMA %s\n", (byte & 0x80) ? "enabled" : "disabled");
printf("DMA priority %s\n", (byte & 0x40) ? "DMA" : "SA1");
printf("DMA %s\n", (byte & 0x20) ? "char conv" : "normal");
printf("DMA type %s\n", (byte & 0x10) ? "BW-RAM -> I-RAM" : "SA1 -> I-RAM");
printf("DMA distination %s\n", (byte & 4) ? "BW-RAM" : "I-RAM");
printf("DMA source %s\n", DMAsource[byte & 3]);
#endif
break;
case 0x2231:
case 0x2231: // character conversion DMA parameters
// 0x80: CHDEND (complete / incomplete)
// 0x03: color mode
// (byte >> 2) & 7: virtual VRAM width
if (byte & 0x80)
SA1.in_char_dma = FALSE;
#if 0
printf("CHDEND %s\n", (byte & 0x80) ? "complete" : "incomplete");
printf("DMA colour mode %d\n", byte & 3);
printf("virtual VRAM width %d\n", (byte >> 2) & 7);
#endif
break;
case 0x2232:
case 0x2233:
case 0x2234:
Memory.FillRAM[address] = byte;
#if 0
printf("DMA source start %06x\n", Memory.FillRAM[0x2232] | (Memory.FillRAM[0x2233] << 8) | (Memory.FillRAM[0x2234] << 16));
#endif
case 0x2232: // DMA source start address (LL)
case 0x2233: // DMA source start address (LH)
case 0x2234: // DMA source start address (HL)
break;
case 0x2235:
Memory.FillRAM[0x2235] = byte;
case 0x2235: // DMA destination start address (LL)
break;
case 0x2236:
case 0x2236: // DMA destination start address (LH)
Memory.FillRAM[0x2236] = byte;
if ((Memory.FillRAM[0x2230] & 0xa4) == 0x80) // Normal DMA to I-RAM
S9xSA1DMA();
else
if ((Memory.FillRAM[0x2230] & 0xb0) == 0xb0)
if ((Memory.FillRAM[0x2230] & 0xb0) == 0xb0) // CC1
{
SA1.in_char_dma = TRUE;
Memory.FillRAM[0x2300] |= 0x20;
if (Memory.FillRAM[0x2201] & 0x20)
S9xSetIRQ(SA1_DMA_IRQ_SOURCE);
SA1.in_char_dma = TRUE;
{
Memory.FillRAM[0x2202] &= ~0x20;
CPU.IRQExternal = TRUE;
}
}
break;
case 0x2237:
case 0x2237: // DMA destination start address (HL)
Memory.FillRAM[0x2237] = byte;
if ((Memory.FillRAM[0x2230] & 0xa4) == 0x84) // Normal DMA to BW-RAM
S9xSA1DMA();
#if 0
printf("DMA dest address %06x\n", Memory.FillRAM[0x2235] | (Memory.FillRAM[0x2236] << 8) | (Memory.FillRAM[0x2237] << 16));
#endif
break;
case 0x2238:
case 0x2239:
Memory.FillRAM[address] = byte;
#if 0
printf("DMA length %04x\n", Memory.FillRAM[0x2238] | (Memory.FillRAM[0x2239] << 8));
#endif
case 0x2238: // DMA terminal counter (L)
case 0x2239: // DMA terminal counter (H)
break;
case 0x223f:
//printf("virtual VRAM depth %d\n", (byte & 0x80) ? 2 : 4);
case 0x223f: // BW-RAM bitmap format
SA1.VirtualBitmapFormat = (byte & 0x80) ? 2 : 4;
break;
case 0x2240:
case 0x2241:
case 0x2242:
case 0x2243:
case 0x2244:
case 0x2245:
case 0x2246:
case 0x2247:
case 0x2248:
case 0x2249:
case 0x224a:
case 0x224b:
case 0x224c:
case 0x224d:
case 0x224e:
#if 0
if (!(SA1.Flags & TRACE_FLAG))
{
TraceSA1();
Trace();
}
#endif
Memory.FillRAM[address] = byte;
case 0x2240: // bitmap register 0
case 0x2241: // bitmap register 1
case 0x2242: // bitmap register 2
case 0x2243: // bitmap register 3
case 0x2244: // bitmap register 4
case 0x2245: // bitmap register 5
case 0x2246: // bitmap register 6
case 0x2247: // bitmap register 7
case 0x2248: // bitmap register 8
case 0x2249: // bitmap register 9
case 0x224a: // bitmap register A
case 0x224b: // bitmap register B
case 0x224c: // bitmap register C
case 0x224d: // bitmap register D
case 0x224e: // bitmap register E
break;
case 0x224f:
case 0x224f: // bitmap register F
Memory.FillRAM[0x224f] = byte;
if ((Memory.FillRAM[0x2230] & 0xb0) == 0xa0) // Char conversion 2 DMA enabled
if ((Memory.FillRAM[0x2230] & 0xb0) == 0xa0) // CC2
{
memmove(&Memory.ROM[CMemory::MAX_ROM_SIZE - 0x10000] + SA1.in_char_dma * 16, &Memory.FillRAM[0x2240], 16);
SA1.in_char_dma = (SA1.in_char_dma + 1) & 7;
@ -712,58 +664,67 @@ void S9xSetSA1 (uint8 byte, uint32 address)
break;
case 0x2250:
case 0x2250: // arithmetic control
if (byte & 2)
SA1.sum = 0;
SA1.arithmetic_op = byte & 3;
break;
case 0x2251:
SA1.op1 = (SA1.op1 & 0xff00) | byte;
case 0x2251: // multiplicand / dividend (L)
SA1.op1 = (SA1.op1 & 0xff00) | byte;
break;
case 0x2252:
SA1.op1 = (SA1.op1 & 0xff) | (byte << 8);
case 0x2252: // multiplicand / dividend (H)
SA1.op1 = (SA1.op1 & 0x00ff) | (byte << 8);
break;
case 0x2253:
SA1.op2 = (SA1.op2 & 0xff00) | byte;
case 0x2253: // multiplier / divisor (L)
SA1.op2 = (SA1.op2 & 0xff00) | byte;
break;
case 0x2254:
SA1.op2 = (SA1.op2 & 0xff) | (byte << 8);
case 0x2254: // multiplier / divisor (H)
SA1.op2 = (SA1.op2 & 0x00ff) | (byte << 8);
switch (SA1.arithmetic_op)
{
case 0: // multiply
SA1.sum = SA1.op1 * SA1.op2;
case 0: // signed multiplication
SA1.sum = (int16) SA1.op1 * (int16) SA1.op2;
SA1.op2 = 0;
break;
case 1: // divide
case 1: // unsigned division
if (SA1.op2 == 0)
SA1.sum = SA1.op1 << 16;
SA1.sum = 0;
else
SA1.sum = (SA1.op1 / (int) ((uint16) SA1.op2)) | ((SA1.op1 % (int) ((uint16) SA1.op2)) << 16);
{
int16 quotient = (int16) SA1.op1 / (uint16) SA1.op2;
uint16 remainder = (int16) SA1.op1 % (uint16) SA1.op2;
SA1.sum = (remainder << 16) | quotient;
}
SA1.op1 = 0;
SA1.op2 = 0;
break;
case 2: // cumulative sum
default:
SA1.sum += SA1.op1 * SA1.op2;
if (SA1.sum & ((int64) 0xffffff << 32))
SA1.overflow = TRUE;
SA1.sum += (int16) SA1.op1 * (int16) SA1.op2;
SA1.overflow = (SA1.sum >= (1ULL << 40));
SA1.sum &= (1ULL << 40) - 1;
SA1.op2 = 0;
break;
}
break;
case 0x2258: // Variable bit-field length/auto inc/start.
case 0x2258: // variable bit-field length / auto inc / start
Memory.FillRAM[0x2258] = byte;
S9xSA1ReadVariableLengthData(TRUE, FALSE);
return;
case 0x2259: // Variable bit-field start address
case 0x225a:
case 0x225b:
case 0x2259: // variable bit-field start address (LL)
case 0x225a: // variable bit-field start address (LH)
case 0x225b: // variable bit-field start address (HL)
Memory.FillRAM[address] = byte;
// XXX: ???
SA1.variable_bit_pos = 0;
@ -771,7 +732,6 @@ void S9xSetSA1 (uint8 byte, uint32 address)
return;
default:
//printf("W: %02x->%04x\n", byte, address);
break;
}
@ -890,14 +850,11 @@ static void S9xSA1DMA (void)
}
memmove(d, s, len);
Memory.FillRAM[0x2301] |= 0x20;
// SA-1 DMA IRQ control
Memory.FillRAM[0x2301] |= 0x20;
if (Memory.FillRAM[0x220a] & 0x20)
{
SA1.Flags |= IRQ_FLAG;
SA1.IRQActive |= DMA_IRQ_SOURCE;
//SA1.Executing = !SA1.Waiting;
}
Memory.FillRAM[0x220b] &= ~0x20;
}
static void S9xSA1ReadVariableLengthData (bool8 inc, bool8 no_shift)
@ -1096,6 +1053,10 @@ void S9xSA1SetPCBase (uint32 address)
SA1Registers.PBPC = address & 0xffffff;
SA1.ShiftedPB = address & 0xff0000;
// FIXME
SA1.MemSpeed = memory_speed(address);
SA1.MemSpeedx2 = SA1.MemSpeed << 1;
uint8 *GetAddress = SA1.Map[(address & 0xffffff) >> MEMMAP_SHIFT];
if (GetAddress >= (uint8 *) CMemory::MAP_LAST)

32
sa1.h
View File

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

View File

@ -221,59 +221,89 @@
#define StackRelative SA1StackRelative
#define StackRelativeIndirectIndexed SA1StackRelativeIndirectIndexed
//#undef CPU_SHUTDOWN
#define SA1_OPCODES
#include "cpuops.cpp"
static void S9xSA1UpdateTimer (void);
void S9xSA1MainLoop (void)
{
if (SA1.Flags & NMI_FLAG)
if (Memory.FillRAM[0x2200] & 0x60)
{
if (Memory.FillRAM[0x2200] & 0x10)
{
SA1.Flags &= ~NMI_FLAG;
Memory.FillRAM[0x2301] |= 0x10;
if (SA1.WaitingForInterrupt)
{
SA1.WaitingForInterrupt = FALSE;
SA1Registers.PCw++;
}
S9xSA1Opcode_NMI();
}
SA1.Cycles += 6; // FIXME
S9xSA1UpdateTimer();
return;
}
if (SA1.Flags & IRQ_FLAG)
// SA-1 NMI
if ((Memory.FillRAM[0x2200] & 0x10) && !(Memory.FillRAM[0x220b] & 0x10))
{
if (SA1.IRQActive)
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++;
}
if (!SA1CheckFlag(IRQ))
S9xSA1Opcode_IRQ();
S9xSA1Opcode_IRQ();
}
else
SA1.Flags &= ~IRQ_FLAG;
// 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 && SA1.Executing; i++)
for (int i = 0; i < 3 && !(Memory.FillRAM[0x2200] & 0x60); 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;
@ -299,4 +329,71 @@ void S9xSA1MainLoop (void)
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;
}

View File

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

View File

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

View File

@ -467,9 +467,6 @@ void S9xLoadConfigFiles (char **argv, int argc)
Settings.DisableGameSpecificHacks = !conf.GetBool("Hack::EnableGameSpecificHacks", true);
Settings.BlockInvalidVRAMAccessMaster = !conf.GetBool("Hack::AllowInvalidVRAMAccess", false);
Settings.ShutdownMaster = conf.GetBool("Hack::SpeedHacks", false);
Settings.DisableIRQ = conf.GetBool("Hack::DisableIRQ", false);
Settings.DisableHDMA = conf.GetBool("Hack::DisableHDMA", false);
Settings.HDMATimingHack = conf.GetInt ("Hack::HDMATiming", 100);
// Netplay
@ -586,10 +583,7 @@ void S9xUsage (void)
S9xMessage(S9X_INFO, S9X_USAGE, "-debug Set the Debugger flag");
S9xMessage(S9X_INFO, S9X_USAGE, "-trace Begin CPU instruction tracing");
#endif
S9xMessage(S9X_INFO, S9X_USAGE, "-noirq (Not recommended) Disable IRQ emulation");
S9xMessage(S9X_INFO, S9X_USAGE, "-nohdma (Not recommended) Disable HDMA emulation");
S9xMessage(S9X_INFO, S9X_USAGE, "-hdmatiming <1-199> (Not recommended) Changes HDMA transfer timings");
S9xMessage(S9X_INFO, S9X_USAGE, "-cpushutdown (Not recommended) Skip emulation until the next");
S9xMessage(S9X_INFO, S9X_USAGE, " event comes");
S9xMessage(S9X_INFO, S9X_USAGE, "-invalidvramaccess (Not recommended) Allow invalid VRAM access");
S9xMessage(S9X_INFO, S9X_USAGE, "");
@ -851,12 +845,6 @@ char * S9xParseArgs (char **argv, int argc)
else
#endif
if (!strcasecmp(argv[i], "-noirq"))
Settings.DisableIRQ = TRUE;
else
if (!strcasecmp(argv[i], "-nohdma"))
Settings.DisableHDMA = TRUE;
else
if (!strcasecmp(argv[i], "-hdmatiming"))
{
if (i + 1 < argc)
@ -869,9 +857,6 @@ char * S9xParseArgs (char **argv, int argc)
S9xUsage();
}
else
if (!strcasecmp(argv[i], "-cpushutdown"))
Settings.ShutdownMaster = TRUE;
else
if (!strcasecmp(argv[i], "-invalidvramaccess"))
Settings.BlockInvalidVRAMAccessMaster = FALSE;
else

View File

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

View File

@ -1,5 +1,3 @@
@S9XZSNESFX@
@S9XZSNESC4@
@S9XDEBUGGER@
@S9XNETPLAY@
@S9XZIP@
@ -9,26 +7,11 @@
OS = `uname -s -r -m|sed \"s/ /-/g\"|tr \"[A-Z]\" \"[a-z]\"|tr \"/()\" \"___\"`
BUILDDIR = .
OBJECTS = ../apu/apu.o ../apu/SNES_SPC.o ../apu/SNES_SPC_misc.o ../apu/SNES_SPC_state.o ../apu/SPC_DSP.o ../apu/SPC_Filter.o ../bsx.o ../cheats.o ../cheats2.o ../clip.o ../conffile.o ../controls.o ../cpu.o ../cpuexec.o ../cpuops.o ../crosshairs.o ../dma.o ../dsp.o ../dsp1.o ../dsp2.o ../dsp3.o ../dsp4.o ../gfx.o ../globals.o ../logger.o ../memmap.o ../movie.o ../obc1.o ../ppu.o ../reader.o ../sa1.o ../sa1cpu.o ../screenshot.o ../sdd1.o ../sdd1emu.o ../seta.o ../seta010.o ../seta011.o ../seta018.o ../snapshot.o ../snes9x.o ../spc7110.o ../srtc.o ../tile.o ../filter/2xsai.o ../filter/blit.o ../filter/epx.o ../filter/hq2x.o ../filter/snes_ntsc.o unix.o x11.o
DEFS = -DMITSHM -DCPU_SHUTDOWN -DSPC700_SHUTDOWN -DCORRECT_VRAM_READS
ifdef S9XZSNESFX
OBJECTS += ../i386/fxemu2.o ../i386/fxemu2b.o ../i386/fxemu2c.o ../i386/fxtable.o ../i386/sfxproc.o ../i386/zsnes.o
else
OBJECTS += ../fxinst.o ../fxemu.o
ifdef S9XDEBUGGER
OBJECTS += ../fxdbg.o
endif
endif
ifdef S9XZSNESC4
OBJECTS += ../i386/c4.o ../i386/zsnesc4.o ../c4.o
else
OBJECTS += ../c4.o ../c4emu.o
endif
OBJECTS = ../apu/apu.o ../apu/SNES_SPC.o ../apu/SNES_SPC_misc.o ../apu/SNES_SPC_state.o ../apu/SPC_DSP.o ../apu/SPC_Filter.o ../bsx.o ../c4.o ../c4emu.o ../cheats.o ../cheats2.o ../clip.o ../conffile.o ../controls.o ../cpu.o ../cpuexec.o ../cpuops.o ../crosshairs.o ../dma.o ../dsp.o ../dsp1.o ../dsp2.o ../dsp3.o ../dsp4.o ../fxinst.o ../fxemu.o ../gfx.o ../globals.o ../logger.o ../memmap.o ../movie.o ../obc1.o ../ppu.o ../reader.o ../sa1.o ../sa1cpu.o ../screenshot.o ../sdd1.o ../sdd1emu.o ../seta.o ../seta010.o ../seta011.o ../seta018.o ../snapshot.o ../snes9x.o ../spc7110.o ../srtc.o ../tile.o ../filter/2xsai.o ../filter/blit.o ../filter/epx.o ../filter/hq2x.o ../filter/snes_ntsc.o unix.o x11.o
DEFS = -DMITSHM
ifdef S9XDEBUGGER
OBJECTS += ../debug.o
OBJECTS += ../debug.o ../fxdbg.o
endif
ifdef S9XNETPLAY
@ -45,14 +28,13 @@ endif
CCC = @CXX@
CC = @CC@
NASM = @S9XNASM@
GASM = @CXX@
INCLUDES = -I. -I.. -I../apu/ -I../unzip/ -I../jma/ -I../filter/
CCFLAGS = @S9XFLGS@ @S9XDEFS@ $(DEFS)
CFLAGS = $(CCFLAGS)
.SUFFIXES: .o .cpp .c .cc .h .m .i .s .asm .obj
.SUFFIXES: .o .cpp .c .cc .h .m .i .s .obj
all: Makefile configure snes9x
@ -108,9 +90,6 @@ snes9x: $(OBJECTS)
@echo Compiling $*.s
sh-elf-as -little $*.s -o $@
.asm.o:
$(NASM) -f elf -DELF @S9XDEFS@ -i../i386/ -o $@ $*.asm
.obj.o:
cp $*.obj $*.o

View File

@ -1,6 +1,6 @@
AC_PREREQ([2.60])
AC_INIT([Snes9x], [1.52], [], [snes9x])
AC_REVISION([$Revision: 1.52 $])
AC_INIT([Snes9x], [1.53], [], [snes9x])
AC_REVISION([$Revision: 1.53 $])
AC_CONFIG_SRCDIR([unix.cpp])
@ -106,52 +106,6 @@ AC_S9X_COMPILER_FLAG([-Wall], [Wall])
AC_S9X_COMPILER_FLAG([-W], [W])
AC_S9X_COMPILER_FLAG([-Wno-unused-parameter], [Wno_unused_parameter])
# Check if the CPU is x86.
AC_MSG_CHECKING([whether the CPU is x86])
AC_CACHE_VAL([snes9x_cv_x86_cpu],
[
case "$target" in
i686-*-* | i586-*-* | i486-*-* | i386-*-*)
snes9x_cv_x86_cpu="yes"
;;
*)
snes9x_cv_x86_cpu="no"
;;
esac
])
AC_MSG_RESULT([$snes9x_cv_x86_cpu])
# Enable ZSNES C4 and SuperFX assembler cores if CPU is x86.
S9XZSNESFX="#S9XZSNESFX=1"
S9XZSNESC4="#S9XZSNESC4=1"
S9XNASM=""
AC_ARG_ENABLE([zsnes_asm],
[AS_HELP_STRING([--enable-zsnes-asm],
[build with ZSNES C4 and SuperFX assembler cores if available (default: no)])],
[], [enable_zsnes_asm="no"])
if test "x$enable_zsnes_asm" = "xyes"; then
if test "x$snes9x_cv_x86_cpu" = "xyes"; then
AC_PATH_PROG([S9XNASM], [nasm], [no])
if test "x$S9XNASM" != "xno"; then
S9XZSNESFX="S9XZSNESFX=1"
S9XZSNESC4="S9XZSNESC4=1"
S9XDEFS="$S9XDEFS -DZSNES_FX -DZSNES_C4"
else
AC_MSG_WARN([nasm not found. Build without ZSNES assembler cores.])
enable_zsnes_asm="no"
fi
else
AC_MSG_WARN([Your CPU is not x86. Build without ZSNES assembler cores.])
enable_zsnes_asm="no"
fi
fi
# Check if the OS is Linux.
AC_MSG_CHECKING([whether the OS is Linux])
@ -464,9 +418,6 @@ S9XLIBS="`echo \"$S9XLIBS\" | sed -e 's/^ *//'`"
AC_SUBST(S9XFLGS)
AC_SUBST(S9XDEFS)
AC_SUBST(S9XLIBS)
AC_SUBST(S9XZSNESFX)
AC_SUBST(S9XZSNESC4)
AC_SUBST(S9XNASM)
AC_SUBST(S9XDEBUGGER)
AC_SUBST(S9XNETPLAY)
AC_SUBST(S9XZIP)
@ -491,7 +442,6 @@ gamepad support...... $enable_gamepad
GZIP support......... $enable_gzip
ZIP support.......... $enable_zip
JMA support.......... $enable_jma
using ZSNES asm...... $enable_zsnes_asm
debugger............. $enable_debugger
EOF

View File

@ -451,7 +451,6 @@ const char * S9xParseDisplayConfig (ConfigFile &conf, int pass)
keymaps.push_back(strpair_t("K00:3", "ToggleBG2"));
keymaps.push_back(strpair_t("K00:4", "ToggleBG3"));
keymaps.push_back(strpair_t("K00:5", "ToggleSprites"));
keymaps.push_back(strpair_t("K00:0", "ToggleHDMA"));
keymaps.push_back(strpair_t("K00:9", "ToggleTransparency"));
keymaps.push_back(strpair_t("K00:BackSpace", "ClipWindows"));
keymaps.push_back(strpair_t("K00:A+Escape", "Debugger"));