aboutsummaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorNebuleon Fumika2013-02-08 05:50:22 -0500
committerNebuleon Fumika2013-02-08 05:50:22 -0500
commit927d456306672110870eb3386742c1c1ef8eb4f6 (patch)
tree509da9ac1727570b02572068aefb9cdf102ad75b /source
parent433749b6ef1e2b070755c3bb7fc0d81b5ecaa7b1 (diff)
parentd4fcf2697c9a45594e3ee0b8bf82e480ddd0b69b (diff)
downloadsnesemu-927d456306672110870eb3386742c1c1ef8eb4f6.tar.gz
snesemu-927d456306672110870eb3386742c1c1ef8eb4f6.tar.bz2
snesemu-927d456306672110870eb3386742c1c1ef8eb4f6.zip
Merge branch 'master' into 8bitsound
Conflicts: source/nds/entry.cpp
Diffstat (limited to 'source')
-rw-r--r--source/apu.cpp35
-rw-r--r--source/apu.h2
-rw-r--r--source/c4emu.cpp1
-rw-r--r--source/cheats.cpp3
-rw-r--r--source/cheats2.cpp1
-rw-r--r--source/clip.cpp12
-rw-r--r--source/cpuexec.cpp462
-rw-r--r--source/cpuexec.h11
-rw-r--r--source/display.h3
-rw-r--r--source/dma.cpp8
-rw-r--r--source/dsp1.cpp259
-rw-r--r--source/gfx.cpp33
-rw-r--r--source/loadzip.cpp8
-rw-r--r--source/memmap.cpp161
-rw-r--r--source/nds/dma_adj.c26
-rw-r--r--source/nds/dma_adj.h29
-rw-r--r--source/nds/ds2_main.c5
-rw-r--r--source/nds/ds2sound.h21
-rw-r--r--source/nds/entry.cpp620
-rw-r--r--source/nds/entry.h4
-rw-r--r--source/nds/gui.c704
-rw-r--r--source/nds/gui.h22
-rw-r--r--source/nds/message.h37
-rw-r--r--source/ppu.cpp33
-rw-r--r--source/ppu.h3
-rw-r--r--source/sa1.cpp4
-rw-r--r--source/snaporig.cpp6
-rw-r--r--source/snapshot.cpp14
-rw-r--r--source/soundux.cpp112
-rw-r--r--source/soundux.h2
-rw-r--r--source/srtc.cpp12
-rw-r--r--source/tile.cpp65
32 files changed, 1770 insertions, 948 deletions
diff --git a/source/apu.cpp b/source/apu.cpp
index 3c1a5d3..769d2bc 100644
--- a/source/apu.cpp
+++ b/source/apu.cpp
@@ -116,18 +116,14 @@ void S9xTraceSoundDSP (const char *s, int i1 = 0, int i2 = 0, int i3 = 0,
bool8 S9xInitAPU ()
{
IAPU.RAM = (uint8 *) malloc (0x10000);
- IAPU.ShadowRAM = (uint8 *) malloc (0x10000);
- IAPU.CachedSamples = (uint8 *) malloc (0x40000);
- if (!IAPU.RAM || !IAPU.ShadowRAM || !IAPU.CachedSamples)
+ if (!IAPU.RAM)
{
S9xDeinitAPU ();
return (FALSE);
}
memset(IAPU.RAM, 0, 0x10000);
- memset(IAPU.ShadowRAM, 0, 0x10000);
- memset(IAPU.CachedSamples, 0, 0x40000);
return (TRUE);
}
@@ -139,16 +135,6 @@ void S9xDeinitAPU ()
free ((char *) IAPU.RAM);
IAPU.RAM = NULL;
}
- if (IAPU.ShadowRAM)
- {
- free ((char *) IAPU.ShadowRAM);
- IAPU.ShadowRAM = NULL;
- }
- if (IAPU.CachedSamples)
- {
- free ((char *) IAPU.CachedSamples);
- IAPU.CachedSamples = NULL;
- }
}
EXTERN_C uint8 APUROM [64];
@@ -171,14 +157,15 @@ void S9xResetAPU ()
{
memcpy(IAPU.RAM+(i<<8), IAPU.RAM, 0x100);
}
-
- memcpy (IAPU.ShadowRAM, IAPU.RAM, 0x10000);
- ZeroMemory (IAPU.CachedSamples, 0x40000);
ZeroMemory (APU.OutPorts, 4);
IAPU.DirectPage = IAPU.RAM;
- memmove (&IAPU.RAM [0xffc0], APUROM, sizeof (APUROM));
- memmove (APU.ExtraRAM, APUROM, sizeof (APUROM));
+ // memmove converted: Different mallocs [Neb]
+ // DS2 DMA notes: The APU ROM is not 32-byte aligned [Neb]
+ memcpy (&IAPU.RAM [0xffc0], APUROM, sizeof (APUROM));
+ // memmove converted: Different mallocs [Neb]
+ // DS2 DMA notes: The APU ROM is not 32-byte aligned [Neb]
+ memcpy (APU.ExtraRAM, APUROM, sizeof (APUROM));
IAPU.PC = IAPU.RAM + IAPU.RAM [0xfffe] + (IAPU.RAM [0xffff] << 8);
APU.Cycles = 0;
IAPU.Registers.YA.W = 0;
@@ -874,7 +861,9 @@ void S9xSetAPUControl (uint8 byte)
{
if (!APU.ShowROM)
{
- memmove (&IAPU.RAM [0xffc0], APUROM, sizeof (APUROM));
+ // memmove converted: Different mallocs [Neb]
+ // DS2 DMA notes: The APU ROM is not 32-byte aligned [Neb]
+ memcpy (&IAPU.RAM [0xffc0], APUROM, sizeof (APUROM));
APU.ShowROM = TRUE;
}
}
@@ -883,7 +872,9 @@ void S9xSetAPUControl (uint8 byte)
if (APU.ShowROM)
{
APU.ShowROM = FALSE;
- memmove (&IAPU.RAM [0xffc0], APU.ExtraRAM, sizeof (APUROM));
+ // memmove converted: Different mallocs [Neb]
+ // DS2 DMA notes: The APU ROM is not 32-byte aligned [Neb]
+ memcpy (&IAPU.RAM [0xffc0], APU.ExtraRAM, sizeof (APUROM));
}
}
IAPU.RAM [0xf1] = byte;
diff --git a/source/apu.h b/source/apu.h
index 67b2525..b675dfd 100644
--- a/source/apu.h
+++ b/source/apu.h
@@ -104,8 +104,6 @@ struct SIAPU
uint8 *WaitAddress1;
uint8 *WaitAddress2;
uint32 WaitCounter;
- uint8 *ShadowRAM;
- uint8 *CachedSamples;
uint8 _Carry;
uint8 _Zero;
uint8 _Overflow;
diff --git a/source/c4emu.cpp b/source/c4emu.cpp
index a8fcce9..be08f07 100644
--- a/source/c4emu.cpp
+++ b/source/c4emu.cpp
@@ -878,6 +878,7 @@ void S9xSetC4 (uint8 byte, uint16 Address)
if(byte != 0) printf("C4 load: non-0 written to $7f47! Wrote %02x\n", byte);
if(READ_WORD(Memory.C4RAM+0x1f45) < 0x6000 || (READ_WORD(Memory.C4RAM+0x1f45) + READ_WORD(Memory.C4RAM+0x1f43)) > 0x6c00) printf("C4 load: Dest unusual! It's %04x\n", READ_WORD(Memory.C4RAM+0x1f45));
#endif
+ // memmove required: Can overlap arbitrarily [Neb]
memmove(Memory.C4RAM+(READ_WORD(Memory.C4RAM+0x1f45)&0x1fff),
S9xGetMemPointer(READ_3WORD(Memory.C4RAM+0x1f40)),
READ_WORD(Memory.C4RAM+0x1f43));
diff --git a/source/cheats.cpp b/source/cheats.cpp
index dc388d2..9c4a8f2 100644
--- a/source/cheats.cpp
+++ b/source/cheats.cpp
@@ -190,8 +190,11 @@ const char *S9xGameGenieToRaw (const char *code, uint32 *address, uint8 *byte)
void S9xStartCheatSearch (SCheatData *d)
{
+ // memmove may be required: Source is usually a different malloc, but could be pointed to d->CWRAM [Neb]
memmove (d->CWRAM, d->RAM, 0x20000);
+ // memmove may be required: Source is usually a different malloc, but could be pointed to d->CSRAM [Neb]
memmove (d->CSRAM, d->SRAM, 0x10000);
+ // memmove may be required: Source is usually a different malloc, but could be pointed to d->CIRAM [Neb]
memmove (d->CIRAM, &d->FillRAM [0x3000], 0x2000);
memset ((char *) d->WRAM_BITS, 0xff, 0x20000 >> 3);
memset ((char *) d->SRAM_BITS, 0xff, 0x10000 >> 3);
diff --git a/source/cheats2.cpp b/source/cheats2.cpp
index e5a7b0f..59855b9 100644
--- a/source/cheats2.cpp
+++ b/source/cheats2.cpp
@@ -128,6 +128,7 @@ void S9xDeleteCheat (uint32 which1)
if (Cheat.c [which1].enabled)
S9xRemoveCheat (which1);
+ // memmove required: Overlapping addresses [Neb]
memmove (&Cheat.c [which1], &Cheat.c [which1 + 1],
sizeof (Cheat.c [0]) * (Cheat.num_cheats - which1 - 1));
Cheat.num_cheats--; //MK: This used to set it to 0??
diff --git a/source/clip.cpp b/source/clip.cpp
index 57204ac..7147abf 100644
--- a/source/clip.cpp
+++ b/source/clip.cpp
@@ -291,7 +291,8 @@ void ComputeClipWindows ()
if (BAND_EMPTY(Win1[0]))
{
B = Window2Enabled;
- memmove (Bands, Win2,
+ // memmove converted: Different stack allocations [Neb]
+ memcpy (Bands, Win2,
sizeof(Win2[0]) * Window2Enabled);
}
else
@@ -355,7 +356,8 @@ void ComputeClipWindows ()
// use window 1 as the clipping (which
// could also be empty).
B = Window1Enabled;
- memmove (Bands, Win1,
+ // memmove converted: Different stack allocations [Neb]
+ memcpy (Bands, Win1,
sizeof(Win1[0]) * Window1Enabled);
}
else
@@ -468,14 +470,16 @@ void ComputeClipWindows ()
if (Window1Enabled == 1 && BAND_EMPTY(Win1[0]))
{
B = Window2Enabled;
- memmove (Bands, Win2,
+ // memmove converted: Different stack allocations [Neb]
+ memcpy (Bands, Win2,
sizeof(Win2[0]) * Window2Enabled);
}
else
if (Window2Enabled == 1 && BAND_EMPTY(Win2[0]))
{
B = Window1Enabled;
- memmove (Bands, Win1,
+ // memmove converted: Different stack allocations [Neb]
+ memcpy (Bands, Win1,
sizeof(Win1[0]) * Window1Enabled);
}
else
diff --git a/source/cpuexec.cpp b/source/cpuexec.cpp
index c4836ec..30dff21 100644
--- a/source/cpuexec.cpp
+++ b/source/cpuexec.cpp
@@ -105,14 +105,42 @@
#include "sa1.h"
#include "spc7110.h"
-#ifdef SYNC_JOYPAD_AT_HBLANK
+#ifdef ACCUMULATE_JOYPAD
#include "display.h"
#endif
extern void S9xProcessSound (unsigned int);
+void S9xMainLoop_SA1_SFX (void);
+void S9xMainLoop_SA1_NoSFX (void);
+void S9xMainLoop_NoSA1_SFX (void);
+void S9xMainLoop_NoSA1_NoSFX (void);
+
+/*
+ * This is a CATSFC modification inspired by a Snes9x-Euphoria modification.
+ * The emulator selects a main loop based on the chips used in an entire
+ * frame. This avoids the constant SA1.Executing and Settings.SuperFX checks.
+ *
+ * The original version of S9xMainLoop is S9xMainLoop_SA1_SFX below. Remember
+ * to propagate modifications to the SA1_NoSFX, NoSA1_SFX and NoSA1_NoSFX
+ * versions.
+ */
void S9xMainLoop (void)
{
+ if (Settings.SA1)
+ {
+ if (Settings.SuperFX) S9xMainLoop_SA1_SFX ();
+ else /* if (!Settings.SuperFX) */ S9xMainLoop_SA1_NoSFX ();
+ }
+ else /* if (!Settings.SA1) */
+ {
+ if (Settings.SuperFX) S9xMainLoop_NoSA1_SFX ();
+ else /* if (!Settings.SuperFX) */ S9xMainLoop_NoSA1_NoSFX ();
+ }
+}
+
+void S9xMainLoop_SA1_SFX (void)
+{
for (;;)
{
APU_EXECUTE ();
@@ -168,7 +196,7 @@ void S9xMainLoop (void)
if (SA1.Executing)
S9xSA1MainLoop ();
- DO_HBLANK_CHECK();
+ DO_HBLANK_CHECK_SFX();
}
ICPU.Registers.PC = CPU.PC - CPU.PCBase;
@@ -191,6 +219,224 @@ void S9xMainLoop (void)
#endif
}
+void S9xMainLoop_SA1_NoSFX (void)
+{
+ for (;;)
+ {
+ APU_EXECUTE ();
+
+ if (CPU.Flags)
+ {
+ if (CPU.Flags & NMI_FLAG)
+ {
+ if (--CPU.NMICycleCount == 0) {
+ CPU.Flags &= ~NMI_FLAG;
+ if (CPU.WaitingForInterrupt) {
+ CPU.WaitingForInterrupt = FALSE;
+ CPU.PC++;
+ }
+ S9xOpcode_NMI ();
+ }
+ }
+
+ CHECK_SOUND ();
+
+ if (CPU.Flags & IRQ_PENDING_FLAG)
+ {
+ if (CPU.IRQCycleCount == 0)
+ {
+ if (CPU.WaitingForInterrupt) {
+ CPU.WaitingForInterrupt = FALSE;
+ CPU.PC++;
+ }
+ if (CPU.IRQActive && !Settings.DisableIRQ) {
+ if (!CheckFlag (IRQ))
+ S9xOpcode_IRQ ();
+ }
+ else
+ CPU.Flags &= ~IRQ_PENDING_FLAG;
+ }
+ else
+ {
+ if(--CPU.IRQCycleCount==0 && CheckFlag (IRQ))
+ CPU.IRQCycleCount=1;
+ }
+ }
+
+ if (CPU.Flags & SCAN_KEYS_FLAG)
+ break;
+ }
+
+#ifdef CPU_SHUTDOWN
+ CPU.PCAtOpcodeStart = CPU.PC;
+#endif
+ CPU.Cycles += CPU.MemSpeed;
+
+ (*ICPU.S9xOpcodes [*CPU.PC++].S9xOpcode) ();
+
+ if (SA1.Executing)
+ S9xSA1MainLoop ();
+ DO_HBLANK_CHECK_NoSFX();
+ }
+
+ ICPU.Registers.PC = CPU.PC - CPU.PCBase;
+ S9xPackStatus ();
+ IAPU.Registers.PC = IAPU.PC - IAPU.RAM;
+ S9xAPUPackStatus ();
+ if (CPU.Flags & SCAN_KEYS_FLAG)
+ {
+ S9xSyncSpeed ();
+ CPU.Flags &= ~SCAN_KEYS_FLAG;
+ }
+}
+
+void S9xMainLoop_NoSA1_SFX (void)
+{
+ for (;;)
+ {
+ APU_EXECUTE ();
+
+ if (CPU.Flags)
+ {
+ if (CPU.Flags & NMI_FLAG)
+ {
+ if (--CPU.NMICycleCount == 0) {
+ CPU.Flags &= ~NMI_FLAG;
+ if (CPU.WaitingForInterrupt) {
+ CPU.WaitingForInterrupt = FALSE;
+ CPU.PC++;
+ }
+ S9xOpcode_NMI ();
+ }
+ }
+
+ CHECK_SOUND ();
+
+ if (CPU.Flags & IRQ_PENDING_FLAG)
+ {
+ if (CPU.IRQCycleCount == 0)
+ {
+ if (CPU.WaitingForInterrupt) {
+ CPU.WaitingForInterrupt = FALSE;
+ CPU.PC++;
+ }
+ if (CPU.IRQActive && !Settings.DisableIRQ) {
+ if (!CheckFlag (IRQ))
+ S9xOpcode_IRQ ();
+ }
+ else
+ CPU.Flags &= ~IRQ_PENDING_FLAG;
+ }
+ else
+ {
+ if(--CPU.IRQCycleCount==0 && CheckFlag (IRQ))
+ CPU.IRQCycleCount=1;
+ }
+ }
+
+ if (CPU.Flags & SCAN_KEYS_FLAG)
+ break;
+ }
+
+#ifdef CPU_SHUTDOWN
+ CPU.PCAtOpcodeStart = CPU.PC;
+#endif
+ CPU.Cycles += CPU.MemSpeed;
+
+ (*ICPU.S9xOpcodes [*CPU.PC++].S9xOpcode) ();
+
+ DO_HBLANK_CHECK_SFX();
+ }
+
+ ICPU.Registers.PC = CPU.PC - CPU.PCBase;
+ S9xPackStatus ();
+ IAPU.Registers.PC = IAPU.PC - IAPU.RAM;
+ S9xAPUPackStatus ();
+ if (CPU.Flags & SCAN_KEYS_FLAG)
+ {
+ S9xSyncSpeed ();
+ CPU.Flags &= ~SCAN_KEYS_FLAG;
+ }
+
+#ifdef DETECT_NASTY_FX_INTERLEAVE
+ if (CPU.BRKTriggered && Settings.SuperFX && !CPU.TriedInterleavedMode2)
+ {
+ CPU.TriedInterleavedMode2 = TRUE;
+ CPU.BRKTriggered = FALSE;
+ S9xDeinterleaveMode2 ();
+ }
+#endif
+}
+
+void S9xMainLoop_NoSA1_NoSFX (void)
+{
+ for (;;)
+ {
+ APU_EXECUTE ();
+
+ if (CPU.Flags)
+ {
+ if (CPU.Flags & NMI_FLAG)
+ {
+ if (--CPU.NMICycleCount == 0) {
+ CPU.Flags &= ~NMI_FLAG;
+ if (CPU.WaitingForInterrupt) {
+ CPU.WaitingForInterrupt = FALSE;
+ CPU.PC++;
+ }
+ S9xOpcode_NMI ();
+ }
+ }
+
+ CHECK_SOUND ();
+
+ if (CPU.Flags & IRQ_PENDING_FLAG)
+ {
+ if (CPU.IRQCycleCount == 0)
+ {
+ if (CPU.WaitingForInterrupt) {
+ CPU.WaitingForInterrupt = FALSE;
+ CPU.PC++;
+ }
+ if (CPU.IRQActive && !Settings.DisableIRQ) {
+ if (!CheckFlag (IRQ))
+ S9xOpcode_IRQ ();
+ }
+ else
+ CPU.Flags &= ~IRQ_PENDING_FLAG;
+ }
+ else
+ {
+ if(--CPU.IRQCycleCount==0 && CheckFlag (IRQ))
+ CPU.IRQCycleCount=1;
+ }
+ }
+
+ if (CPU.Flags & SCAN_KEYS_FLAG)
+ break;
+ }
+
+#ifdef CPU_SHUTDOWN
+ CPU.PCAtOpcodeStart = CPU.PC;
+#endif
+ CPU.Cycles += CPU.MemSpeed;
+
+ (*ICPU.S9xOpcodes [*CPU.PC++].S9xOpcode) ();
+
+ DO_HBLANK_CHECK_NoSFX();
+ }
+
+ ICPU.Registers.PC = CPU.PC - CPU.PCBase;
+ S9xPackStatus ();
+ IAPU.Registers.PC = IAPU.PC - IAPU.RAM;
+ S9xAPUPackStatus ();
+ if (CPU.Flags & SCAN_KEYS_FLAG)
+ {
+ S9xSyncSpeed ();
+ CPU.Flags &= ~SCAN_KEYS_FLAG;
+ }
+}
+
void S9xSetIRQ (uint32 source)
{
CPU.IRQActive |= source;
@@ -211,7 +457,15 @@ void S9xClearIRQ (uint32 source)
CLEAR_IRQ_SOURCE (source);
}
-void S9xDoHBlankProcessing ()
+/*
+ * This is a CATSFC modification inspired by a Snes9x-Euphoria modification.
+ * The emulator selects an HBlank processor based on the chips used in an
+ * entire frame. This avoids the constant Settings.SuperFX checks.
+ *
+ * The original version of S9xDoHBlankProcessing is S9xDoHBlankProcessing_SFX
+ * below. Remember to propagate modifications to the NoSFX version.
+ */
+void S9xDoHBlankProcessing_SFX ()
{
#ifdef CPU_SHUTDOWN
CPU.WaitCounter++;
@@ -219,15 +473,202 @@ void S9xDoHBlankProcessing ()
switch (CPU.WhichEvent)
{
case HBLANK_START_EVENT:
-#ifdef SYNC_JOYPAD_AT_HBLANK
- // Re-get the controls every hblank. A resolution algorithm in
- // ppu.cpp will determine with greater accuracy whether a key was
- // pressed or released during the frame.
- uint32 i;
- for (i = 0; i < 5; i++)
+#ifdef ACCUMULATE_JOYPAD
+/*
+ * This call allows NDSSFC to synchronise the DS controller more often.
+ * If porting a later version of Snes9x into NDSSFC, it is essential to
+ * preserve it.
+ */
+ if ((CPU.V_Counter & 0xF) == 0)
+ NDSSFCAccumulateJoypad ();
+#endif
+ if (IPPU.HDMA && CPU.V_Counter <= PPU.ScreenHeight)
+ IPPU.HDMA = S9xDoHDMA (IPPU.HDMA);
+
+ break;
+
+ case HBLANK_END_EVENT:
+ S9xSuperFXExec ();
+
+#ifndef STORM
+ if (Settings.SoundSync)
+ S9xGenerateSound ();
+#endif
+
+ CPU.Cycles -= Settings.H_Max;
+ if (IAPU.APUExecuting)
+ {
+ APU.Cycles -= Settings.H_Max;
+#ifdef MK_APU
+ S9xCatchupCount();
+#endif
+ }
+ else
+ APU.Cycles = 0;
+
+ CPU.NextEvent = -1;
+ ICPU.Scanline++;
+
+ if (++CPU.V_Counter >= (Settings.PAL ? SNES_MAX_PAL_VCOUNTER : SNES_MAX_NTSC_VCOUNTER))
+ {
+ CPU.V_Counter = 0;
+ Memory.FillRAM[0x213F]^=0x80;
+ PPU.RangeTimeOver = 0;
+ CPU.NMIActive = FALSE;
+ ICPU.Frame++;
+ PPU.HVBeamCounterLatched = 0;
+ CPU.Flags |= SCAN_KEYS_FLAG;
+ S9xStartHDMA ();
+ }
+
+ S9xProcessSound (0);
+
+ if (PPU.VTimerEnabled && !PPU.HTimerEnabled && CPU.V_Counter == PPU.IRQVBeamPos)
{
- IPPU.JoypadsAtHBlanks [i][CPU.V_Counter] = S9xReadJoypad (i);
+ S9xSetIRQ (PPU_V_BEAM_IRQ_SOURCE);
}
+
+ if (CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE)
+ {
+ // Start of V-blank
+ S9xEndScreenRefresh ();
+ IPPU.HDMA = 0;
+ // Bits 7 and 6 of $4212 are computed when read in S9xGetPPU.
+ missing.dma_this_frame = 0;
+ IPPU.MaxBrightness = PPU.Brightness;
+ PPU.ForcedBlanking = (Memory.FillRAM [0x2100] >> 7) & 1;
+
+ if(!PPU.ForcedBlanking)
+ {
+ PPU.OAMAddr = PPU.SavedOAMAddr;
+
+ uint8 tmp = 0;
+ if(PPU.OAMPriorityRotation)
+ tmp = (PPU.OAMAddr&0xFE)>>1;
+ if((PPU.OAMFlip&1) || PPU.FirstSprite!=tmp)
+ {
+ PPU.FirstSprite=tmp;
+ IPPU.OBJChanged=TRUE;
+ }
+
+ PPU.OAMFlip = 0;
+ }
+
+ Memory.FillRAM[0x4210] = 0x80 |Model->_5A22;
+ if (Memory.FillRAM[0x4200] & 0x80)
+ {
+ CPU.NMIActive = TRUE;
+ CPU.Flags |= NMI_FLAG;
+ CPU.NMICycleCount = CPU.NMITriggerPoint;
+ }
+
+#ifdef OLD_SNAPSHOT_CODE
+ if (CPU.Flags & SAVE_SNAPSHOT_FLAG)
+ {
+ CPU.Flags &= ~SAVE_SNAPSHOT_FLAG;
+ Registers.PC = CPU.PC - CPU.PCBase;
+ S9xPackStatus ();
+ S9xAPUPackStatus ();
+ Snapshot (NULL);
+ }
+#endif
+ }
+
+ if (CPU.V_Counter == PPU.ScreenHeight + 3)
+ S9xUpdateJoypads ();
+
+ if (CPU.V_Counter == FIRST_VISIBLE_LINE)
+ {
+ Memory.FillRAM[0x4210] = Model->_5A22;
+ CPU.Flags &= ~NMI_FLAG;
+ S9xStartScreenRefresh ();
+ }
+ if (CPU.V_Counter >= FIRST_VISIBLE_LINE &&
+ CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE)
+ {
+ RenderLine (CPU.V_Counter - FIRST_VISIBLE_LINE);
+ }
+ // Use TimerErrorCounter to skip update of SPC700 timers once
+ // every 128 updates. Needed because this section of code is called
+ // once every emulated 63.5 microseconds, which coresponds to
+ // 15.750KHz, but the SPC700 timers need to be updated at multiples
+ // of 8KHz, hence the error correction.
+// IAPU.TimerErrorCounter++;
+// if (IAPU.TimerErrorCounter >= )
+// IAPU.TimerErrorCounter = 0;
+// else
+ {
+ if (APU.TimerEnabled [2])
+ {
+ APU.Timer [2] += 4;
+ while (APU.Timer [2] >= APU.TimerTarget [2])
+ {
+ IAPU.RAM [0xff] = (IAPU.RAM [0xff] + 1) & 0xf;
+ APU.Timer [2] -= APU.TimerTarget [2];
+#ifdef SPC700_SHUTDOWN
+ IAPU.WaitCounter++;
+ IAPU.APUExecuting = TRUE;
+#endif
+ }
+ }
+ if (CPU.V_Counter & 1)
+ {
+ if (APU.TimerEnabled [0])
+ {
+ APU.Timer [0]++;
+ if (APU.Timer [0] >= APU.TimerTarget [0])
+ {
+ IAPU.RAM [0xfd] = (IAPU.RAM [0xfd] + 1) & 0xf;
+ APU.Timer [0] = 0;
+#ifdef SPC700_SHUTDOWN
+ IAPU.WaitCounter++;
+ IAPU.APUExecuting = TRUE;
+#endif
+ }
+ }
+ if (APU.TimerEnabled [1])
+ {
+ APU.Timer [1]++;
+ if (APU.Timer [1] >= APU.TimerTarget [1])
+ {
+ IAPU.RAM [0xfe] = (IAPU.RAM [0xfe] + 1) & 0xf;
+ APU.Timer [1] = 0;
+#ifdef SPC700_SHUTDOWN
+ IAPU.WaitCounter++;
+ IAPU.APUExecuting = TRUE;
+#endif
+ }
+ }
+ }
+ }
+ break;
+
+ case HTIMER_BEFORE_EVENT:
+ case HTIMER_AFTER_EVENT:
+ if (PPU.HTimerEnabled && (!PPU.VTimerEnabled || CPU.V_Counter == PPU.IRQVBeamPos))
+ {
+ S9xSetIRQ (PPU_H_BEAM_IRQ_SOURCE);
+ }
+ break;
+ }
+
+ S9xReschedule ();
+}
+void S9xDoHBlankProcessing_NoSFX ()
+{
+#ifdef CPU_SHUTDOWN
+ CPU.WaitCounter++;
+#endif
+ switch (CPU.WhichEvent)
+ {
+ case HBLANK_START_EVENT:
+#ifdef ACCUMULATE_JOYPAD
+/*
+ * This call allows NDSSFC to synchronise the DS controller more often.
+ * If porting a later version of Snes9x into NDSSFC, it is essential to
+ * preserve it.
+ */
+ NDSSFCAccumulateJoypad ();
#endif
if (IPPU.HDMA && CPU.V_Counter <= PPU.ScreenHeight)
IPPU.HDMA = S9xDoHDMA (IPPU.HDMA);
@@ -235,7 +676,6 @@ void S9xDoHBlankProcessing ()
break;
case HBLANK_END_EVENT:
- S9xSuperFXExec ();
#ifndef STORM
if (Settings.SoundSync)
diff --git a/source/cpuexec.h b/source/cpuexec.h
index a094220..dab9099 100644
--- a/source/cpuexec.h
+++ b/source/cpuexec.h
@@ -93,9 +93,13 @@
#include "memmap.h"
#include "65c816.h"
-#define DO_HBLANK_CHECK() \
+#define DO_HBLANK_CHECK_SFX() \
if (CPU.Cycles >= CPU.NextEvent) \
- S9xDoHBlankProcessing ();
+ S9xDoHBlankProcessing_SFX ();
+
+#define DO_HBLANK_CHECK_NoSFX() \
+ if (CPU.Cycles >= CPU.NextEvent) \
+ S9xDoHBlankProcessing_NoSFX ();
struct SOpcodes {
#ifdef __WIN32__
@@ -126,7 +130,8 @@ START_EXTERN_C
void S9xMainLoop (void);
void S9xReset (void);
void S9xSoftReset (void);
-void S9xDoHBlankProcessing ();
+void S9xDoHBlankProcessing_SFX ();
+void S9xDoHBlankProcessing_NoSFX ();
void S9xClearIRQ (uint32);
void S9xSetIRQ (uint32);
diff --git a/source/display.h b/source/display.h
index 8e65885..d00c5ed 100644
--- a/source/display.h
+++ b/source/display.h
@@ -97,6 +97,9 @@ void S9xGraphicsMode ();
char *S9xParseArgs (char **argv, int argc);
void S9xParseArg (char **argv, int &index, int argc);
void S9xExtraUsage ();
+#ifdef ACCUMULATE_JOYPAD
+void NDSSFCAccumulateJoypad ();
+#endif
uint32 S9xReadJoypad (int which1_0_to_4);
bool8 S9xReadMousePosition (int which1_0_to_1, int &x, int &y, uint32 &buttons);
bool8 S9xReadSuperScopePosition (int &x, int &y, uint32 &buttons);
diff --git a/source/dma.cpp b/source/dma.cpp
index 2addceb..96f705f 100644
--- a/source/dma.cpp
+++ b/source/dma.cpp
@@ -855,8 +855,12 @@ void S9xDoDMA (uint8 Channel)
IAPU.APUExecuting = Settings.APUEnabled;
APU_EXECUTE ();
#endif
- while (CPU.Cycles > CPU.NextEvent)
- S9xDoHBlankProcessing ();
+ if (Settings.SuperFX)
+ while (CPU.Cycles > CPU.NextEvent)
+ S9xDoHBlankProcessing_SFX ();
+ else /* if (!Settings.SuperFX) */
+ while (CPU.Cycles > CPU.NextEvent)
+ S9xDoHBlankProcessing_NoSFX ();
if(Settings.SPC7110&&spc7110_dma)
{
diff --git a/source/dsp1.cpp b/source/dsp1.cpp
index 2628447..244d8b0 100644
--- a/source/dsp1.cpp
+++ b/source/dsp1.cpp
@@ -941,136 +941,137 @@ uint8 DSP2GetByte(uint16 address)
//Disable non-working chips?
#ifdef DSP_DUMMY_LOOPS
-
+//static const uint16 DSP1ROM[1024] from SNES9X v1.53
uint16 Dsp3Rom[1024] = {
- 0x8000, 0x4000, 0x2000, 0x1000, 0x0800, 0x0400, 0x0200, 0x0100,
- 0x0080, 0x0040, 0x0020, 0x0010, 0x0008, 0x0004, 0x0002, 0x0001,
- 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100,
- 0x0000, 0x000f, 0x0400, 0x0200, 0x0140, 0x0400, 0x0200, 0x0040,
- 0x007d, 0x007e, 0x007e, 0x007b, 0x007c, 0x007d, 0x007b, 0x007c,
- 0x0002, 0x0020, 0x0030, 0x0000, 0x000d, 0x0019, 0x0026, 0x0032,
- 0x003e, 0x004a, 0x0056, 0x0062, 0x006d, 0x0079, 0x0084, 0x008e,
- 0x0098, 0x00a2, 0x00ac, 0x00b5, 0x00be, 0x00c6, 0x00ce, 0x00d5,
- 0x00dc, 0x00e2, 0x00e7, 0x00ec, 0x00f1, 0x00f5, 0x00f8, 0x00fb,
- 0x00fd, 0x00ff, 0x0100, 0x0100, 0x0100, 0x00ff, 0x00fd, 0x00fb,
- 0x00f8, 0x00f5, 0x00f1, 0x00ed, 0x00e7, 0x00e2, 0x00dc, 0x00d5,
- 0x00ce, 0x00c6, 0x00be, 0x00b5, 0x00ac, 0x00a2, 0x0099, 0x008e,
- 0x0084, 0x0079, 0x006e, 0x0062, 0x0056, 0x004a, 0x003e, 0x0032,
- 0x0026, 0x0019, 0x000d, 0x0000, 0xfff3, 0xffe7, 0xffdb, 0xffce,
- 0xffc2, 0xffb6, 0xffaa, 0xff9e, 0xff93, 0xff87, 0xff7d, 0xff72,
- 0xff68, 0xff5e, 0xff54, 0xff4b, 0xff42, 0xff3a, 0xff32, 0xff2b,
- 0xff25, 0xff1e, 0xff19, 0xff14, 0xff0f, 0xff0b, 0xff08, 0xff05,
- 0xff03, 0xff01, 0xff00, 0xff00, 0xff00, 0xff01, 0xff03, 0xff05,
- 0xff08, 0xff0b, 0xff0f, 0xff13, 0xff18, 0xff1e, 0xff24, 0xff2b,
- 0xff32, 0xff3a, 0xff42, 0xff4b, 0xff54, 0xff5d, 0xff67, 0xff72,
- 0xff7c, 0xff87, 0xff92, 0xff9e, 0xffa9, 0xffb5, 0xffc2, 0xffce,
- 0xffda, 0xffe7, 0xfff3, 0x002b, 0x007f, 0x0020, 0x00ff, 0xff00,
- 0xffbe, 0x0000, 0x0044, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0xffc1, 0x0001, 0x0002, 0x0045,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0xffc5, 0x0003, 0x0004, 0x0005, 0x0047, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0xffca, 0x0006, 0x0007, 0x0008,
- 0x0009, 0x004a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0xffd0, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x004e, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0xffd7, 0x000f, 0x0010, 0x0011,
- 0x0012, 0x0013, 0x0014, 0x0053, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0xffdf, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b,
- 0x0059, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0xffe8, 0x001c, 0x001d, 0x001e,
- 0x001f, 0x0020, 0x0021, 0x0022, 0x0023, 0x0060, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0xfff2, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a,
- 0x002b, 0x002c, 0x0068, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0xfffd, 0x002d, 0x002e, 0x002f,
- 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0071,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0xffc7, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d,
- 0x003e, 0x003f, 0x0040, 0x0041, 0x007b, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0xffd4, 0x0000, 0x0001, 0x0002,
- 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a,
- 0x000b, 0x0044, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0xffe2, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010, 0x0011, 0x0012,
- 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0050, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0xfff1, 0x0019, 0x001a, 0x001b,
- 0x001c, 0x001d, 0x001e, 0x001f, 0x0020, 0x0021, 0x0022, 0x0023,
- 0x0024, 0x0025, 0x0026, 0x005d, 0x0000, 0x0000, 0x0000, 0x0000,
- 0xffcb, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d,
- 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035,
- 0x006b, 0x0000, 0x0000, 0x0000, 0xffdc, 0x0000, 0x0001, 0x0002,
- 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a,
- 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0x0044, 0x0000, 0x0000,
- 0xffee, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016,
- 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e,
- 0x001f, 0x0020, 0x0054, 0x0000, 0xffee, 0x0021, 0x0022, 0x0023,
- 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b,
- 0x002c, 0x002d, 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0x0065,
- 0xffbe, 0x0000, 0xfeac, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0xffc1, 0x0001, 0x0002, 0xfead,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0xffc5, 0x0003, 0x0004, 0x0005, 0xfeaf, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0xffca, 0x0006, 0x0007, 0x0008,
- 0x0009, 0xfeb2, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0xffd0, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0xfeb6, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0xffd7, 0x000f, 0x0010, 0x0011,
- 0x0012, 0x0013, 0x0014, 0xfebb, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0xffdf, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b,
- 0xfec1, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0xffe8, 0x001c, 0x001d, 0x001e,
- 0x001f, 0x0020, 0x0021, 0x0022, 0x0023, 0xfec8, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0xfff2, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a,
- 0x002b, 0x002c, 0xfed0, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0xfffd, 0x002d, 0x002e, 0x002f,
- 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0xfed9,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0xffc7, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d,
- 0x003e, 0x003f, 0x0040, 0x0041, 0xfee3, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0xffd4, 0x0000, 0x0001, 0x0002,
- 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a,
- 0x000b, 0xfeac, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
- 0xffe2, 0x000c, 0x000d, 0x000e, 0x000f, 0x0010, 0x0011, 0x0012,
- 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0xfeb8, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000, 0xfff1, 0x0019, 0x001a, 0x001b,
- 0x001c, 0x001d, 0x001e, 0x001f, 0x0020, 0x0021, 0x0022, 0x0023,
- 0x0024, 0x0025, 0x0026, 0xfec5, 0x0000, 0x0000, 0x0000, 0x0000,
- 0xffcb, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d,
- 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035,
- 0xfed3, 0x0000, 0x0000, 0x0000, 0xffdc, 0x0000, 0x0001, 0x0002,
- 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a,
- 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, 0xfeac, 0x0000, 0x0000,
- 0xffee, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016,
- 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e,
- 0x001f, 0x0020, 0xfebc, 0x0000, 0xffee, 0x0021, 0x0022, 0x0023,
- 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b,
- 0x002c, 0x002d, 0x002e, 0x002f, 0x0030, 0x0031, 0x0032, 0xfecd,
- 0x0154, 0x0218, 0x0110, 0x00b0, 0x00cc, 0x00b0, 0x0088, 0x00b0,
- 0x0044, 0x00b0, 0x0000, 0x00b0, 0x00fe, 0xff07, 0x0002, 0x00ff,
- 0x00f8, 0x0007, 0x00fe, 0x00ee, 0x07ff, 0x0200, 0x00ef, 0xf800,
- 0x0700, 0x00ee, 0xffff, 0xffff, 0xffff, 0x0000, 0x0000, 0x0001,
- 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff,
- 0xffff, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000,
- 0x0000, 0xffff, 0xffff, 0x0000, 0xffff, 0x0001, 0x0000, 0x0001,
- 0x0001, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000,
- 0xffff, 0x0001, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0xffff,
- 0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0044, 0x0088, 0x00cc,
- 0x0110, 0x0154, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
- 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020,
+ 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000,
+ 0x4000, 0x7fff, 0x4000, 0x2000, 0x1000, 0x0800, 0x0400, 0x0200,
+ 0x0100, 0x0080, 0x0040, 0x0020, 0x0001, 0x0008, 0x0004, 0x0002,
+ 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x8000, 0xffe5, 0x0100, 0x7fff, 0x7f02, 0x7e08,
+ 0x7d12, 0x7c1f, 0x7b30, 0x7a45, 0x795d, 0x7878, 0x7797, 0x76ba,
+ 0x75df, 0x7507, 0x7433, 0x7361, 0x7293, 0x71c7, 0x70fe, 0x7038,
+ 0x6f75, 0x6eb4, 0x6df6, 0x6d3a, 0x6c81, 0x6bca, 0x6b16, 0x6a64,
+ 0x69b4, 0x6907, 0x685b, 0x67b2, 0x670b, 0x6666, 0x65c4, 0x6523,
+ 0x6484, 0x63e7, 0x634c, 0x62b3, 0x621c, 0x6186, 0x60f2, 0x6060,
+ 0x5fd0, 0x5f41, 0x5eb5, 0x5e29, 0x5d9f, 0x5d17, 0x5c91, 0x5c0c,
+ 0x5b88, 0x5b06, 0x5a85, 0x5a06, 0x5988, 0x590b, 0x5890, 0x5816,
+ 0x579d, 0x5726, 0x56b0, 0x563b, 0x55c8, 0x5555, 0x54e4, 0x5474,
+ 0x5405, 0x5398, 0x532b, 0x52bf, 0x5255, 0x51ec, 0x5183, 0x511c,
+ 0x50b6, 0x5050, 0x4fec, 0x4f89, 0x4f26, 0x4ec5, 0x4e64, 0x4e05,
+ 0x4da6, 0x4d48, 0x4cec, 0x4c90, 0x4c34, 0x4bda, 0x4b81, 0x4b28,
+ 0x4ad0, 0x4a79, 0x4a23, 0x49cd, 0x4979, 0x4925, 0x48d1, 0x487f,
+ 0x482d, 0x47dc, 0x478c, 0x473c, 0x46ed, 0x469f, 0x4651, 0x4604,
+ 0x45b8, 0x456c, 0x4521, 0x44d7, 0x448d, 0x4444, 0x43fc, 0x43b4,
+ 0x436d, 0x4326, 0x42e0, 0x429a, 0x4255, 0x4211, 0x41cd, 0x4189,
+ 0x4146, 0x4104, 0x40c2, 0x4081, 0x4040, 0x3fff, 0x41f7, 0x43e1,
+ 0x45bd, 0x478d, 0x4951, 0x4b0b, 0x4cbb, 0x4e61, 0x4fff, 0x5194,
+ 0x5322, 0x54a9, 0x5628, 0x57a2, 0x5914, 0x5a81, 0x5be9, 0x5d4a,
+ 0x5ea7, 0x5fff, 0x6152, 0x62a0, 0x63ea, 0x6530, 0x6672, 0x67b0,
+ 0x68ea, 0x6a20, 0x6b53, 0x6c83, 0x6daf, 0x6ed9, 0x6fff, 0x7122,
+ 0x7242, 0x735f, 0x747a, 0x7592, 0x76a7, 0x77ba, 0x78cb, 0x79d9,
+ 0x7ae5, 0x7bee, 0x7cf5, 0x7dfa, 0x7efe, 0x7fff, 0x0000, 0x0324,
+ 0x0647, 0x096a, 0x0c8b, 0x0fab, 0x12c8, 0x15e2, 0x18f8, 0x1c0b,
+ 0x1f19, 0x2223, 0x2528, 0x2826, 0x2b1f, 0x2e11, 0x30fb, 0x33de,
+ 0x36ba, 0x398c, 0x3c56, 0x3f17, 0x41ce, 0x447a, 0x471c, 0x49b4,
+ 0x4c3f, 0x4ebf, 0x5133, 0x539b, 0x55f5, 0x5842, 0x5a82, 0x5cb4,
+ 0x5ed7, 0x60ec, 0x62f2, 0x64e8, 0x66cf, 0x68a6, 0x6a6d, 0x6c24,
+ 0x6dca, 0x6f5f, 0x70e2, 0x7255, 0x73b5, 0x7504, 0x7641, 0x776c,
+ 0x7884, 0x798a, 0x7a7d, 0x7b5d, 0x7c29, 0x7ce3, 0x7d8a, 0x7e1d,
+ 0x7e9d, 0x7f09, 0x7f62, 0x7fa7, 0x7fd8, 0x7ff6, 0x7fff, 0x7ff6,
+ 0x7fd8, 0x7fa7, 0x7f62, 0x7f09, 0x7e9d, 0x7e1d, 0x7d8a, 0x7ce3,
+ 0x7c29, 0x7b5d, 0x7a7d, 0x798a, 0x7884, 0x776c, 0x7641, 0x7504,
+ 0x73b5, 0x7255, 0x70e2, 0x6f5f, 0x6dca, 0x6c24, 0x6a6d, 0x68a6,
+ 0x66cf, 0x64e8, 0x62f2, 0x60ec, 0x5ed7, 0x5cb4, 0x5a82, 0x5842,
+ 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4, 0x471c, 0x447a,
+ 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33de, 0x30fb, 0x2e11,
+ 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f19, 0x1c0b, 0x18f8, 0x15e2,
+ 0x12c8, 0x0fab, 0x0c8b, 0x096a, 0x0647, 0x0324, 0x7fff, 0x7ff6,
+ 0x7fd8, 0x7fa7, 0x7f62, 0x7f09, 0x7e9d, 0x7e1d, 0x7d8a, 0x7ce3,
+ 0x7c29, 0x7b5d, 0x7a7d, 0x798a, 0x7884, 0x776c, 0x7641, 0x7504,
+ 0x73b5, 0x7255, 0x70e2, 0x6f5f, 0x6dca, 0x6c24, 0x6a6d, 0x68a6,
+ 0x66cf, 0x64e8, 0x62f2, 0x60ec, 0x5ed7, 0x5cb4, 0x5a82, 0x5842,
+ 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4, 0x471c, 0x447a,
+ 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33de, 0x30fb, 0x2e11,
+ 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f19, 0x1c0b, 0x18f8, 0x15e2,
+ 0x12c8, 0x0fab, 0x0c8b, 0x096a, 0x0647, 0x0324, 0x0000, 0xfcdc,
+ 0xf9b9, 0xf696, 0xf375, 0xf055, 0xed38, 0xea1e, 0xe708, 0xe3f5,
+ 0xe0e7, 0xdddd, 0xdad8, 0xd7da, 0xd4e1, 0xd1ef, 0xcf05, 0xcc22,
+ 0xc946, 0xc674, 0xc3aa, 0xc0e9, 0xbe32, 0xbb86, 0xb8e4, 0xb64c,
+ 0xb3c1, 0xb141, 0xaecd, 0xac65, 0xaa0b, 0xa7be, 0xa57e, 0xa34c,
+ 0xa129, 0x9f14, 0x9d0e, 0x9b18, 0x9931, 0x975a, 0x9593, 0x93dc,
+ 0x9236, 0x90a1, 0x8f1e, 0x8dab, 0x8c4b, 0x8afc, 0x89bf, 0x8894,
+ 0x877c, 0x8676, 0x8583, 0x84a3, 0x83d7, 0x831d, 0x8276, 0x81e3,
+ 0x8163, 0x80f7, 0x809e, 0x8059, 0x8028, 0x800a, 0x6488, 0x0080,
+ 0x03ff, 0x0116, 0x0002, 0x0080, 0x4000, 0x3fd7, 0x3faf, 0x3f86,
+ 0x3f5d, 0x3f34, 0x3f0c, 0x3ee3, 0x3eba, 0x3e91, 0x3e68, 0x3e40,
+ 0x3e17, 0x3dee, 0x3dc5, 0x3d9c, 0x3d74, 0x3d4b, 0x3d22, 0x3cf9,
+ 0x3cd0, 0x3ca7, 0x3c7f, 0x3c56, 0x3c2d, 0x3c04, 0x3bdb, 0x3bb2,
+ 0x3b89, 0x3b60, 0x3b37, 0x3b0e, 0x3ae5, 0x3abc, 0x3a93, 0x3a69,
+ 0x3a40, 0x3a17, 0x39ee, 0x39c5, 0x399c, 0x3972, 0x3949, 0x3920,
+ 0x38f6, 0x38cd, 0x38a4, 0x387a, 0x3851, 0x3827, 0x37fe, 0x37d4,
+ 0x37aa, 0x3781, 0x3757, 0x372d, 0x3704, 0x36da, 0x36b0, 0x3686,
+ 0x365c, 0x3632, 0x3609, 0x35df, 0x35b4, 0x358a, 0x3560, 0x3536,
+ 0x350c, 0x34e1, 0x34b7, 0x348d, 0x3462, 0x3438, 0x340d, 0x33e3,
+ 0x33b8, 0x338d, 0x3363, 0x3338, 0x330d, 0x32e2, 0x32b7, 0x328c,
+ 0x3261, 0x3236, 0x320b, 0x31df, 0x31b4, 0x3188, 0x315d, 0x3131,
+ 0x3106, 0x30da, 0x30ae, 0x3083, 0x3057, 0x302b, 0x2fff, 0x2fd2,
+ 0x2fa6, 0x2f7a, 0x2f4d, 0x2f21, 0x2ef4, 0x2ec8, 0x2e9b, 0x2e6e,
+ 0x2e41, 0x2e14, 0x2de7, 0x2dba, 0x2d8d, 0x2d60, 0x2d32, 0x2d05,
+ 0x2cd7, 0x2ca9, 0x2c7b, 0x2c4d, 0x2c1f, 0x2bf1, 0x2bc3, 0x2b94,
+ 0x2b66, 0x2b37, 0x2b09, 0x2ada, 0x2aab, 0x2a7c, 0x2a4c, 0x2a1d,
+ 0x29ed, 0x29be, 0x298e, 0x295e, 0x292e, 0x28fe, 0x28ce, 0x289d,
+ 0x286d, 0x283c, 0x280b, 0x27da, 0x27a9, 0x2777, 0x2746, 0x2714,
+ 0x26e2, 0x26b0, 0x267e, 0x264c, 0x2619, 0x25e7, 0x25b4, 0x2581,
+ 0x254d, 0x251a, 0x24e6, 0x24b2, 0x247e, 0x244a, 0x2415, 0x23e1,
+ 0x23ac, 0x2376, 0x2341, 0x230b, 0x22d6, 0x229f, 0x2269, 0x2232,
+ 0x21fc, 0x21c4, 0x218d, 0x2155, 0x211d, 0x20e5, 0x20ad, 0x2074,
+ 0x203b, 0x2001, 0x1fc7, 0x1f8d, 0x1f53, 0x1f18, 0x1edd, 0x1ea1,
+ 0x1e66, 0x1e29, 0x1ded, 0x1db0, 0x1d72, 0x1d35, 0x1cf6, 0x1cb8,
+ 0x1c79, 0x1c39, 0x1bf9, 0x1bb8, 0x1b77, 0x1b36, 0x1af4, 0x1ab1,
+ 0x1a6e, 0x1a2a, 0x19e6, 0x19a1, 0x195c, 0x1915, 0x18ce, 0x1887,
+ 0x183f, 0x17f5, 0x17ac, 0x1761, 0x1715, 0x16c9, 0x167c, 0x162e,
+ 0x15df, 0x158e, 0x153d, 0x14eb, 0x1497, 0x1442, 0x13ec, 0x1395,
+ 0x133c, 0x12e2, 0x1286, 0x1228, 0x11c9, 0x1167, 0x1104, 0x109e,
+ 0x1036, 0x0fcc, 0x0f5f, 0x0eef, 0x0e7b, 0x0e04, 0x0d89, 0x0d0a,
+ 0x0c86, 0x0bfd, 0x0b6d, 0x0ad6, 0x0a36, 0x098d, 0x08d7, 0x0811,
+ 0x0736, 0x063e, 0x0519, 0x039a, 0x0000, 0x7fff, 0x0100, 0x0080,
+ 0x021d, 0x00c8, 0x00ce, 0x0048, 0x0a26, 0x277a, 0x00ce, 0x6488,
+ 0x14ac, 0x0001, 0x00f9, 0x00fc, 0x00ff, 0x00fc, 0x00f9, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
+
};
void DSP3SetByte(uint8 byte, uint16 address)
diff --git a/source/gfx.cpp b/source/gfx.cpp
index d2b8b6e..9ea0a97 100644
--- a/source/gfx.cpp
+++ b/source/gfx.cpp
@@ -154,10 +154,12 @@ extern uint8 Mode7Depths [2];
if (IPPU.DoubleHeightPixels && ((PPU.BGMode != 5 && PPU.BGMode != 6) || !IPPU.Interlace)) \
for (uint32 y = GFX.StartY; y <= GFX.EndY; y++) \
{ \
- memmove (SCREEN + (y * 2 + 1) * GFX.Pitch2, \
- SCREEN + y * 2 * GFX.Pitch2, \
- GFX.Pitch2); \
+ /* memmove converted: Same malloc, non-overlapping addresses [Neb] */ \
+ memcpy (SCREEN + (y * 2 + 1) * GFX.Pitch2, \
+ SCREEN + y * 2 * GFX.Pitch2, \
+ GFX.Pitch2); \
if(DO_DEPTH){ \
+ /* memmove required: Same malloc, potentially overlapping addresses [Neb] */ \
memmove (DEPTH + (y * 2 + 1) * (GFX.PPLx2>>1), \
DEPTH + y * GFX.PPL, \
GFX.PPLx2>>1); \
@@ -1167,6 +1169,14 @@ void S9xSetupOBJ ()
static void DrawOBJS (bool8 OnMain = FALSE, uint8 D = 0)
{
+#ifdef ACCUMULATE_JOYPAD
+/*
+ * This call allows NDSSFC to synchronise the DS controller more often.
+ * If porting a later version of Snes9x into NDSSFC, it is essential to
+ * preserve it.
+ */
+ NDSSFCAccumulateJoypad ();
+#endif
#ifdef MK_DEBUG_RTO
if(Settings.BGLayering) fprintf(stderr, "Entering DrawOBJS() for %d-%d\n", GFX.StartY, GFX.EndY);
#endif
@@ -1207,6 +1217,7 @@ static void DrawOBJS (bool8 OnMain = FALSE, uint8 D = 0)
if(j<i && Windows[j].Pos==GFX.pCurrentClip->Left[clip][4]){
Windows[j].Value = TRUE;
} else {
+ // memmove required: Overlapping addresses [Neb]
if(j<i) memmove(&Windows[j+1], &Windows[j], sizeof(Windows[0])*(i-j));
Windows[j].Pos = GFX.pCurrentClip->Left[clip][4];
Windows[j].Value = TRUE;
@@ -1214,6 +1225,7 @@ static void DrawOBJS (bool8 OnMain = FALSE, uint8 D = 0)
}
for(j=0; j<i && Windows[j].Pos<GFX.pCurrentClip->Right[clip][4]; j++);
if(j>=i || Windows[j].Pos!=GFX.pCurrentClip->Right[clip][4]){
+ // memmove required: Overlapping addresses [Neb]
if(j<i) memmove(&Windows[j+1], &Windows[j], sizeof(Windows[0])*(i-j));
Windows[j].Pos = GFX.pCurrentClip->Right[clip][4];
Windows[j].Value = FALSE;
@@ -2310,6 +2322,14 @@ static void DrawBackgroundMode5 (uint32 /* BGMODE */, uint32 bg, uint8 Z1, uint8
static void DrawBackground (uint32 BGMode, uint32 bg, uint8 Z1, uint8 Z2)
{
+#ifdef ACCUMULATE_JOYPAD
+/*
+ * This call allows NDSSFC to synchronise the DS controller more often.
+ * If porting a later version of Snes9x into NDSSFC, it is essential to
+ * preserve it.
+ */
+ NDSSFCAccumulateJoypad ();
+#endif
GFX.PixSize = 1;
BG.TileSize = BGSizes [PPU.BG[bg].BGSize];
@@ -3723,10 +3743,13 @@ void S9xUpdateScreen ()
// part way down the screen. Scale everything.
for (register int32 y = (int32) GFX.StartY - 1; y >= 0; y--)
{
- memmove (GFX.Screen + y * 2 * GFX.Pitch2,
+ // memmove converted: Same malloc, different addresses, and identical addresses at line 0 [Neb]
+ // DS2 DMA notes: This code path is unused [Neb]
+ memcpy (GFX.Screen + y * 2 * GFX.Pitch2,
GFX.Screen + y * GFX.Pitch2,
GFX.Pitch2);
- memmove (GFX.Screen + (y * 2 + 1) * GFX.Pitch2,
+ // memmove converted: Same malloc, different addresses [Neb]
+ memcpy (GFX.Screen + (y * 2 + 1) * GFX.Pitch2,
GFX.Screen + y * GFX.Pitch2,
GFX.Pitch2);
}
diff --git a/source/loadzip.cpp b/source/loadzip.cpp
index 4ee3bcb..d3e24a1 100644
--- a/source/loadzip.cpp
+++ b/source/loadzip.cpp
@@ -132,8 +132,7 @@ bool8 LoadZip(const char* zipname,
char name[132];
unzGetCurrentFileInfo(file, &info, name,128, NULL,0, NULL,0);
- int calc_size = info.uncompressed_size / 0x2000;
- calc_size *= 0x2000;
+ int calc_size = info.uncompressed_size & ~0x1FFF; // round to lower 0x2000
if(!(info.uncompressed_size - calc_size == 512 || info.uncompressed_size == calc_size))
{
port = unzGoToNextFile(file);
@@ -190,8 +189,7 @@ bool8 LoadZip(const char* zipname,
// assert(info.uncompressed_size <= CMemory::MAX_ROM_SIZE + 512);
int FileSize = info.uncompressed_size;
- int calc_size = FileSize / 0x2000;
- calc_size *= 0x2000;
+ int calc_size = FileSize & ~0x1FFF; // round to lower 0x2000
int l = unzReadCurrentFile(file,ptr,FileSize);
if(unzCloseCurrentFile(file) == UNZ_CRCERROR)
@@ -224,6 +222,8 @@ bool8 LoadZip(const char* zipname,
if ((FileSize - calc_size == 512 && !Settings.ForceNoHeader) ||
Settings.ForceHeader)
{
+ // memmove required: Overlapping addresses [Neb]
+ // DS2 DMA notes: Can be split into 512-byte DMA blocks [Neb]
memmove (ptr, ptr + 512, calc_size);
(*headers)++;
FileSize -= 512;
diff --git a/source/memmap.cpp b/source/memmap.cpp
index 04bc621..20110f9 100644
--- a/source/memmap.cpp
+++ b/source/memmap.cpp
@@ -113,6 +113,12 @@
#include "unzip/unzip.h"
+#ifdef DS2_DMA
+#include "ds2_cpu.h"
+#include "ds2_dma.h"
+#include "dma_adj.h"
+#endif
+
#ifdef __W32_HEAP
#include <malloc.h>
#endif
@@ -214,6 +220,7 @@ void S9xDeinterleaveType1(int TotalFileSize, uint8 * base)
blocks [i * 2] = i + nblocks;
blocks [i * 2 + 1] = i;
}
+ // DS2 DMA notes: base may or may not be 32-byte aligned
uint8 *tmp = (uint8 *) malloc (0x8000);
if (tmp)
{
@@ -223,10 +230,14 @@ void S9xDeinterleaveType1(int TotalFileSize, uint8 * base)
{
if (blocks [j] == i)
{
- memmove (tmp, &base [blocks [j] * 0x8000], 0x8000);
- memmove (&base [blocks [j] * 0x8000],
+ // memmove converted: Different mallocs [Neb]
+ memcpy (tmp, &base [blocks [j] * 0x8000], 0x8000);
+ // memmove converted: Different addresses, or identical for blocks[i] == blocks[j] [Neb]
+ // DS2 DMA notes: Don't do DMA at all if blocks[i] == blocks[j]
+ memcpy (&base [blocks [j] * 0x8000],
&base [blocks [i] * 0x8000], 0x8000);
- memmove (&base [blocks [i] * 0x8000], tmp, 0x8000);
+ // memmove converted: Different mallocs [Neb]
+ memcpy (&base [blocks [i] * 0x8000], tmp, 0x8000);
uint8 b = blocks [j];
blocks [j] = blocks [i];
blocks [i] = b;
@@ -250,13 +261,18 @@ void S9xDeinterleaveGD24(int TotalFileSize, uint8 * base)
SET_UI_COLOR(0,255,255);
}
+ // DS2 DMA notes: base may or may not be 32-byte aligned
uint8 *tmp = (uint8 *) malloc (0x80000);
if (tmp)
{
- memmove(tmp, &base[0x180000], 0x80000);
- memmove(&base[0x180000], &base[0x200000], 0x80000);
- memmove(&base[0x200000], &base[0x280000], 0x80000);
- memmove(&base[0x280000], tmp, 0x80000);
+ // memmove converted: Different mallocs [Neb]
+ memcpy(tmp, &base[0x180000], 0x80000);
+ // memmove converted: Different addresses [Neb]
+ memcpy(&base[0x180000], &base[0x200000], 0x80000);
+ // memmove converted: Different addresses [Neb]
+ memcpy(&base[0x200000], &base[0x280000], 0x80000);
+ // memmove converted: Different mallocs [Neb]
+ memcpy(&base[0x280000], tmp, 0x80000);
free ((char *) tmp);
S9xDeinterleaveType1(TotalFileSize, base);
@@ -399,14 +415,22 @@ char *CMemory::Safe (const char *s)
/**********************************************************************************************/
bool8 CMemory::Init ()
{
+ // DS2 DMA notes: These would do well to be allocated with 32 extra bytes
+ // so they can be 32-byte aligned. [Neb]
RAM = (uint8 *) malloc (0x20000);
SRAM = (uint8 *) malloc (0x20000);
VRAM = (uint8 *) malloc (0x10000);
+#ifdef DS2_DMA
+ ROM = (uint8 *) AlignedMalloc (MAX_ROM_SIZE + 0x200 + 0x8000, 32, &PtrAdj.ROM);
+#else
ROM = (uint8 *) malloc (MAX_ROM_SIZE + 0x200 + 0x8000);
+#endif
memset (RAM, 0, 0x20000);
memset (SRAM, 0, 0x20000);
memset (VRAM, 0, 0x10000);
- memset (ROM, 0, MAX_ROM_SIZE + 0x200 + 0x8000);
+ // This needs to be initialised with a ROM first anyway, so don't
+ // bother memsetting. [Neb]
+ // memset (ROM, 0, MAX_ROM_SIZE + 0x200 + 0x8000);
BSRAM = (uint8 *) malloc (0x80000);
memset (BSRAM, 0, 0x80000);
@@ -437,9 +461,9 @@ bool8 CMemory::Init ()
// Add 0x8000 to ROM image pointer to stop SuperFX code accessing
// unallocated memory (can cause crash on some ports).
- ROM += 0x8000;
+ ROM += 0x8000; // still 32-byte aligned
- C4RAM = ROM + 0x400000 + 8192 * 8;
+ C4RAM = ROM + 0x400000 + 8192 * 8; // still 32-byte aligned
::ROM = ROM;
::SRAM = SRAM;
::RegRAM = FillRAM;
@@ -453,7 +477,7 @@ bool8 CMemory::Init ()
SuperFX.nRomBanks = (2 * 1024 * 1024) / (32 * 1024);
SuperFX.pvRom = (uint8 *) ROM;
#endif
-
+
ZeroMemory (IPPU.TileCache [TILE_2BIT], MAX_2BIT_TILES * 128);
ZeroMemory (IPPU.TileCache [TILE_4BIT], MAX_4BIT_TILES * 128);
ZeroMemory (IPPU.TileCache [TILE_8BIT], MAX_8BIT_TILES * 128);
@@ -493,7 +517,11 @@ void CMemory::Deinit ()
if (ROM)
{
ROM -= 0x8000;
+#ifdef DS2_RAM
+ AlignedFree ((char *) ROM, PtrAdj.ROM);
+#else
free ((char *) ROM);
+#endif
ROM = NULL;
}
@@ -627,7 +655,21 @@ again:
((hi_score > lo_score && ScoreHiROM (TRUE) > hi_score) ||
(hi_score <= lo_score && ScoreLoROM (TRUE) > lo_score)))
{
+#ifdef DS2_DMA
+ __dcache_writeback_all();
+ {
+ unsigned int i;
+ for (i = 0; i < TotalFileSize; i += 512)
+ {
+ ds2_DMAcopy_32Byte (2 /* channel: emu internal */, Memory.ROM + i, Memory.ROM + i + 512, 512);
+ ds2_DMA_wait(2);
+ ds2_DMA_stop(2);
+ }
+ }
+#else
+ // memmove required: Overlapping addresses [Neb]
memmove (Memory.ROM, Memory.ROM + 512, TotalFileSize - 512);
+#endif
TotalFileSize -= 512;
S9xMessage (S9X_INFO, S9X_HEADER_WARNING,
"Try specifying the -nhd command line option if the game doesn't work\n");
@@ -636,7 +678,7 @@ again:
orig_lo_score = lo_score = ScoreLoROM (FALSE);
}
- CalculatedSize = (TotalFileSize / 0x2000) * 0x2000;
+ CalculatedSize = TotalFileSize & ~0x1FFF; // round down to lower 0x2000
ZeroMemory (ROM + CalculatedSize, MAX_ROM_SIZE - CalculatedSize);
if(CalculatedSize >0x400000&&
@@ -871,6 +913,7 @@ uint32 CMemory::FileLoader (uint8* buffer, const char* filename, int32 maxsize)
_makepath (fname, drive, dir, name, ext);
#ifdef __WIN32__
+ // memmove required: Overlapping addresses [Neb]
memmove (&ext [0], &ext[1], 4);
#endif
@@ -936,12 +979,27 @@ uint32 CMemory::FileLoader (uint8* buffer, const char* filename, int32 maxsize)
FileSize = fread (ptr, 1, maxsize + 0x200 - (ptr - ROM), ROMFile);
fclose (ROMFile);
- int calc_size = (FileSize / 0x2000) * 0x2000;
+ int calc_size = FileSize & ~0x1FFF; // round to the lower 0x2000
if ((FileSize - calc_size == 512 && !Settings.ForceNoHeader) ||
Settings.ForceHeader)
{
+ // memmove required: Overlapping addresses [Neb]
+ // DS2 DMA notes: Can be split into 512-byte DMA blocks [Neb]
+#ifdef DS2_DMA
+ __dcache_writeback_all();
+ {
+ unsigned int i;
+ for (i = 0; i < calc_size; i += 512)
+ {
+ ds2_DMAcopy_32Byte (2 /* channel: emu internal */, ptr + i, ptr + i + 512, 512);
+ ds2_DMA_wait(2);
+ ds2_DMA_stop(2);
+ }
+ }
+#else
memmove (ptr, ptr + 512, calc_size);
+#endif
HeaderCount++;
FileSize -= 512;
}
@@ -958,6 +1016,7 @@ uint32 CMemory::FileLoader (uint8* buffer, const char* filename, int32 maxsize)
more = TRUE;
ext [0]++;
#ifdef __WIN32__
+ // memmove required: Overlapping addresses [Neb]
memmove (&ext [1], &ext [0], 4);
ext [0] = '.';
#endif
@@ -972,6 +1031,7 @@ uint32 CMemory::FileLoader (uint8* buffer, const char* filename, int32 maxsize)
more = TRUE;
name [len - 1]++;
#ifdef __WIN32__
+ // memmove required: Overlapping addresses [Neb]
memmove (&ext [1], &ext [0], 4);
ext [0] = '.';
#endif
@@ -1180,21 +1240,48 @@ void S9xDeinterleaveType2 (bool8 reset)
blocks [i] = (i & ~0xF) | ((i & 3) << 2) |
((i & 12) >> 2);
}
-
+
+#ifdef DS2_DMA
+ unsigned int TmpAdj;
+ uint8 *tmp = (uint8 *) AlignedMalloc (0x10000, 32, &TmpAdj);
+#else
uint8 *tmp = (uint8 *) malloc (0x10000);
+#endif
if (tmp)
{
+#ifdef DS2_DMA
+ __dcache_writeback_all();
+#endif
for (i = 0; i < nblocks * 2; i++)
{
for (int j = i; j < nblocks * 2; j++)
{
if (blocks [j] == i)
{
- memmove (tmp, &Memory.ROM [blocks [j] * 0x10000], 0x10000);
- memmove (&Memory.ROM [blocks [j] * 0x10000],
+#ifdef DS2_DMA
+ ds2_DMAcopy_32Byte (2 /* channel: emu internal */, tmp, &Memory.ROM [blocks [j] * 0x10000], 0x10000);
+ ds2_DMA_wait(2);
+ ds2_DMA_stop(2);
+
+ ds2_DMAcopy_32Byte (2 /* channel: emu internal */, &Memory.ROM [blocks [j] * 0x10000],
&Memory.ROM [blocks [i] * 0x10000], 0x10000);
- memmove (&Memory.ROM [blocks [i] * 0x10000], tmp, 0x10000);
+ ds2_DMA_wait(2);
+ ds2_DMA_stop(2);
+
+ ds2_DMAcopy_32Byte (2 /* channel: emu internal */, &Memory.ROM [blocks [i] * 0x10000], tmp, 0x10000);
+ ds2_DMA_wait(2);
+ ds2_DMA_stop(2);
+#else
+ // memmove converted: Different mallocs [Neb]
+ memcpy (tmp, &Memory.ROM [blocks [j] * 0x10000], 0x10000);
+
+ // memmove converted: Different addresses, or identical if blocks[i] == blocks[j] [Neb]
+ memcpy (&Memory.ROM [blocks [j] * 0x10000],
+ &Memory.ROM [blocks [i] * 0x10000], 0x10000);
+ // memmove converted: Different mallocs [Neb]
+ memcpy (&Memory.ROM [blocks [i] * 0x10000], tmp, 0x10000);
+#endif
uint8 b = blocks [j];
blocks [j] = blocks [i];
blocks [i] = b;
@@ -1605,6 +1692,7 @@ bool8 CMemory::LoadSRAM (const char *filename)
if (len - size == 512)
{
// S-RAM file has a header - remove it
+ // memmove required: Overlapping addresses [Neb]
memmove (::SRAM, ::SRAM + 512, size);
}
if (len == size + SRTC_SRAM_PAD)
@@ -1705,7 +1793,8 @@ void CMemory::ResetSpeedMap()
void CMemory::WriteProtectROM ()
{
- memmove ((void *) WriteMap, (void *) Map, sizeof (Map));
+ // memmove converted: Different mallocs [Neb]
+ memcpy ((void *) WriteMap, (void *) Map, sizeof (Map));
for (int c = 0; c < 0x1000; c++)
{
if (BlockIsROM [c])
@@ -2543,10 +2632,24 @@ void CMemory::SuperFXROMMap ()
// Replicate the first 2Mb of the ROM at ROM + 2MB such that each 32K
// block is repeated twice in each 64K block.
+#ifdef DS2_DMA
+ __dcache_writeback_all();
+#endif
for (c = 0; c < 64; c++)
{
- memmove (&ROM [0x200000 + c * 0x10000], &ROM [c * 0x8000], 0x8000);
- memmove (&ROM [0x208000 + c * 0x10000], &ROM [c * 0x8000], 0x8000);
+#ifdef DS2_DMA
+ ds2_DMAcopy_32Byte(2 /* channel: emu internal */, &ROM [0x200000 + c * 0x10000], &ROM [c * 0x8000], 0x8000);
+ ds2_DMAcopy_32Byte(3 /* channel: emu internal 2 */, &ROM [0x208000 + c * 0x10000], &ROM [c * 0x8000], 0x8000);
+ ds2_DMA_wait(2);
+ ds2_DMA_wait(3);
+ ds2_DMA_stop(2);
+ ds2_DMA_stop(3);
+#else
+ // memmove converted: Different addresses [Neb]
+ memcpy (&ROM [0x200000 + c * 0x10000], &ROM [c * 0x8000], 0x8000);
+ // memmove converted: Different addresses [Neb]
+ memcpy (&ROM [0x208000 + c * 0x10000], &ROM [c * 0x8000], 0x8000);
+#endif
}
WriteProtectROM ();
@@ -2612,8 +2715,10 @@ void CMemory::SA1ROMMap ()
WriteProtectROM ();
// Now copy the map and correct it for the SA1 CPU.
- memmove ((void *) SA1.WriteMap, (void *) WriteMap, sizeof (WriteMap));
- memmove ((void *) SA1.Map, (void *) Map, sizeof (Map));
+ // memmove converted: Different mallocs [Neb]
+ memcpy ((void *) SA1.WriteMap, (void *) WriteMap, sizeof (WriteMap));
+ // memmove converted: Different mallocs [Neb]
+ memcpy ((void *) SA1.Map, (void *) Map, sizeof (Map));
// Banks 00->3f and 80->bf
for (c = 0; c < 0x400; c += 16)
@@ -3025,8 +3130,10 @@ void CMemory::GNextROMMap ()
WriteProtectROM ();
// Now copy the map and correct it for the SA1 CPU.
- memmove ((void *) SA1.WriteMap, (void *) WriteMap, sizeof (WriteMap));
- memmove ((void *) SA1.Map, (void *) Map, sizeof (Map));
+ // memmove converted: Different mallocs [Neb]
+ memcpy ((void *) SA1.WriteMap, (void *) WriteMap, sizeof (WriteMap));
+ // memmove converted: Different mallocs [Neb]
+ memcpy ((void *) SA1.Map, (void *) Map, sizeof (Map));
// Banks 00->3f and 80->bf
for (c = 0; c < 0x400; c += 16)
@@ -4385,9 +4492,11 @@ void CMemory::ParseSNESHeader(uint8* RomHeader)
ROMChecksum = RomHeader [0x2e] + (RomHeader [0x2f] << 8);
ROMComplementChecksum = RomHeader [0x2c] + (RomHeader [0x2d] << 8);
ROMRegion= RomHeader[0x29];
- memmove (ROMId, &RomHeader [0x2], 4);
+ // memmove converted: Different mallocs [Neb]
+ memcpy (ROMId, &RomHeader [0x2], 4);
if(RomHeader[0x2A]==0x33)
- memmove (CompanyId, &RomHeader [0], 2);
+ // memmove converted: Different mallocs [Neb]
+ memcpy (CompanyId, &RomHeader [0], 2);
else sprintf(CompanyId, "%02X", RomHeader[0x2A]);
}
diff --git a/source/nds/dma_adj.c b/source/nds/dma_adj.c
new file mode 100644
index 0000000..8b6f9ad
--- /dev/null
+++ b/source/nds/dma_adj.c
@@ -0,0 +1,26 @@
+#include "ds2_malloc.h"
+#include "dma_adj.h"
+
+#ifdef DS2_DMA
+
+struct SPointerAdjustments PtrAdj;
+
+void* AlignedMalloc (unsigned int Size, unsigned int Alignment, unsigned int* Adjustment)
+{
+ if (Alignment == 0) Alignment = 1;
+
+ unsigned char* result = (unsigned char*) malloc(Size + Alignment);
+ if (!result) {
+ return result;
+ } else {
+ *Adjustment = Alignment - ((unsigned int) result & (Alignment - 1));
+ return (void*) (result + *Adjustment);
+ }
+}
+
+void AlignedFree (void* Memory, unsigned int Adjustment)
+{
+ free((void*) ((unsigned char*) Memory - Adjustment));
+}
+
+#endif // DS2_DMA
diff --git a/source/nds/dma_adj.h b/source/nds/dma_adj.h
new file mode 100644
index 0000000..3852f09
--- /dev/null
+++ b/source/nds/dma_adj.h
@@ -0,0 +1,29 @@
+#ifndef _DMA_ADJ_H_
+#define _DMA_ADJ_H_
+
+#ifdef DS2_DMA
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct SPointerAdjustments {
+ /* These are used by the DSTWO-NDS side code. */
+ unsigned int GFXScreen;
+
+ /* These are used by Snes9x. */
+ unsigned int ROM;
+};
+
+extern struct SPointerAdjustments PtrAdj;
+
+extern void* AlignedMalloc (unsigned int Size, unsigned int Alignment, unsigned int* Adjustment);
+extern void AlignedFree (void* Memory, unsigned int Adjustment);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // DS2_DMA
+
+#endif // !_DMA_ADJ_H_
diff --git a/source/nds/ds2_main.c b/source/nds/ds2_main.c
index f9b29d5..af81df3 100644
--- a/source/nds/ds2_main.c
+++ b/source/nds/ds2_main.c
@@ -17,6 +17,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include "port.h"
+
#include <stdio.h>
#include "console.h"
#include "fs_api.h"
@@ -25,6 +27,7 @@
#include "ds2_timer.h"
#include "ds2_malloc.h"
#include "ds2sound.h"
+#include "gui.h"
#define BLACK_COLOR RGB15(0, 0, 0)
#define WHITE_COLOR RGB15(31, 31, 31)
@@ -47,7 +50,7 @@ void ddump_mem(unsigned char* addr, unsigned int len)
void ds2_main(void)
{
int err;
- ds2_setCPUclocklevel(13);
+ HighFrequencyCPU();
//Initial video and audio and other input and output
err = ds2io_initb(DS2_BUFFER_SIZE, SND_SAMPLE_RATE, 0, 0);
if(err) goto _failure;
diff --git a/source/nds/ds2sound.h b/source/nds/ds2sound.h
index f51a6e1..8c0e2bf 100644
--- a/source/nds/ds2sound.h
+++ b/source/nds/ds2sound.h
@@ -1,21 +1,24 @@
// The sound buffer sizes used on the DS2's side, for each value of
// Settings.SoundPlaybackRate.
+// * Don't buffer too much, otherwise audio is delayed from video.
+// * Don't go below one frame (20 milliseconds).
+// * Buffer sizes must be multiples of 128.
#define DS2_BUFFER_SIZE_4 512 /* tested working */
-#define DS2_BUFFER_SIZE_5 1024 /* like the SNES! tested working, but slow */
-#define DS2_BUFFER_SIZE_6 1024 /* tested working, slow because of upsampling */
-#define DS2_BUFFER_SIZE_7 1024 /* tested working, slow because of upsampling */
+#define DS2_BUFFER_SIZE_5 640 /* like the SNES! tested working */
+#define DS2_BUFFER_SIZE_6 896 /* tested working */
+#define DS2_BUFFER_SIZE_7 1024 /* tested working */
// The sampling rate for the sound, in Hz, for each value of
// Settings.SoundPlaybackRate.
#define SND_SAMPLE_RATE_1 8000
#define SND_SAMPLE_RATE_2 11025
#define SND_SAMPLE_RATE_3 16000
-#define SND_SAMPLE_RATE_4 22050
-#define SND_SAMPLE_RATE_5 32000
+#define SND_SAMPLE_RATE_4 22050 /* NDSSFC 1.06 - CATSFC 1.28 used this one */
+#define SND_SAMPLE_RATE_5 32000 /* like the SNES! */
#define SND_SAMPLE_RATE_6 44100
-#define SND_SAMPLE_RATE_7 48000
+#define SND_SAMPLE_RATE_7 48000 /* CATSFC 1.25 made using this one possible */
// Settings in use. The number should match in all three settings.
-#define DS2_BUFFER_SIZE DS2_BUFFER_SIZE_4
-#define SND_SAMPLE_RATE SND_SAMPLE_RATE_4
-#define SNES9X_SRATE_ID 4
+#define DS2_BUFFER_SIZE DS2_BUFFER_SIZE_5
+#define SND_SAMPLE_RATE SND_SAMPLE_RATE_5
+#define SNES9X_SRATE_ID 5
diff --git a/source/nds/entry.cpp b/source/nds/entry.cpp
index 702442e..c4cc389 100644
--- a/source/nds/entry.cpp
+++ b/source/nds/entry.cpp
@@ -23,6 +23,11 @@
#include "entry.h"
#include "ds2sound.h"
+#ifdef DS2_DMA
+#include "ds2_dma.h"
+#include "dma_adj.h"
+#endif
+
void S9xProcessSound (unsigned int);
char *rom_filename = NULL;
@@ -58,7 +63,11 @@ void S9xExtraUsage ()
*/
void S9xDeinitDisplay (void)
{
+#ifdef DS2_DMA
+ if(GFX.Screen) AlignedFree(GFX.Screen, PtrAdj.GFXScreen);
+#else
if(GFX.Screen) free(GFX.Screen);
+#endif
if(GFX.SubScreen) free(GFX.SubScreen);
if(GFX.ZBuffer) free(GFX.ZBuffer);
if(GFX.SubZBuffer) free(GFX.SubZBuffer);
@@ -69,7 +78,11 @@ void S9xInitDisplay (int, char **)
int h = IMAGE_HEIGHT;
GFX.Pitch = IMAGE_WIDTH * 2;
+#ifdef DS2_DMA
+ GFX.Screen = (unsigned char*) AlignedMalloc (GFX.Pitch * h, 32, &PtrAdj.GFXScreen);
+#else
GFX.Screen = (unsigned char*) malloc (GFX.Pitch * h);
+#endif
GFX.SubScreen = (unsigned char*) malloc (GFX.Pitch * h);
GFX.ZBuffer = (unsigned char*) malloc ((GFX.Pitch >> 1) * h);
GFX.SubZBuffer =(unsigned char*) malloc ((GFX.Pitch >> 1) * h);
@@ -86,7 +99,7 @@ void S9xParseDisplayArg (char **argv, int &ind, int)
void S9xExit ()
{
- ds2_setCPUclocklevel(13); // Crank it up to exit quickly
+ HighFrequencyCPU(); // Crank it up to exit quickly
if(Settings.SPC7110)
(*CleanUp7110)();
@@ -130,17 +143,38 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/)
{
//Up
case 1:
+#ifdef DS2_DMA
+ __dcache_writeback_all();
+ ds2_DMAcopy_32Byte(1 /* channel: graphics */, up_screen_addr, GFX.Screen + 256 * 32 * 2, 256 * 192 * 2);
+ ds2_DMA_wait(1);
+ ds2_DMA_stop(1);
+#else
memcpy(up_screen_addr, GFX.Screen+256*32*2, 256*192*2);
+#endif
break;
//Down
case 2:
+#ifdef DS2_DMA
+ __dcache_writeback_all();
+ ds2_DMAcopy_32Byte(1 /* channel: graphics */, up_screen_addr, GFX.Screen, 256 * 192 * 2);
+ ds2_DMA_wait(1);
+ ds2_DMA_stop(1);
+#else
memcpy(up_screen_addr, GFX.Screen, 256*192*2);
+#endif
break;
//Both
case 3:
+#ifdef DS2_DMA
+ __dcache_writeback_all();
+ ds2_DMAcopy_32Byte(1 /* channel: graphics */, up_screen_addr, GFX.Screen + 256 * 16 * 2, 256 * 192 * 2);
+ ds2_DMA_wait(1);
+ ds2_DMA_stop(1);
+#else
memcpy(up_screen_addr, GFX.Screen+256*16*2, 256*192*2);
+#endif
break;
case 4:
@@ -150,14 +184,23 @@ bool8 S9xDeinitUpdate (int Width, int Height, bool8 /*sixteen_bit*/)
default:
{
- unsigned char *src, *dst;
- unsigned int m;
+#ifdef DS2_DMA
+ __dcache_writeback_all();
+#endif
+ register unsigned char *src, *dst;
+ register unsigned int m;
src = GFX.Screen;
dst = (unsigned char*)up_screen_addr;
for(m = 0; m < 32; m++)
{
+#ifdef DS2_DMA
+ ds2_DMAcopy_32Byte(1 /* channel: graphics */, dst, src, 256 * 6 * 2);
+ ds2_DMA_wait(1);
+ ds2_DMA_stop(1);
+#else
memcpy(dst, src, 256*6*2);
+#endif
dst += 256*6*2;
src += 256*7*2;
}
@@ -350,6 +393,18 @@ void game_set_frameskip()
Settings.SkipFrames = game_config.frameskip_value - 1 /* 1 -> 0 and so on */;
}
}
+
+void game_set_fluidity()
+{
+ if( game_config.SoundSync == 1)
+ {
+ Settings.SoundSync = TRUE;
+ }
+ else
+ {
+ Settings.SoundSync = FALSE;
+ }
+}
void init_sfc_setting(void)
{
@@ -370,6 +425,7 @@ void init_sfc_setting(void)
//sound settings
Settings.APUEnabled = Settings.NextAPUEnabled = TRUE;
Settings.FixFrequency = 1;
+
S9xSetEightBitConsoleSound (TRUE);
@@ -403,7 +459,7 @@ void init_sfc_setting(void)
#endif
Settings.ApplyCheats = TRUE;
Settings.TurboMode = FALSE;
- Settings.TurboSkipFrames = 40;
+ Settings.TurboSkipFrames = 10;
Settings.StretchScreenshots = 1;
Settings.HBlankStart = (256 * Settings.H_Max) / SNES_HCOUNTER_MAX;
@@ -444,7 +500,7 @@ void game_restart(void)
S9xReset ();
}
-int load_gamepak(char* file)
+int load_gamepak(const char* file)
{
CPU.Flags = 0;
// mdelay(50); // Delete this delay
@@ -540,6 +596,7 @@ int sfc_main (int argc, char **argv)
#endif
Settings.Paused = 1;
+ bool8 FirstInvocation = TRUE;
while (1)
{
@@ -564,7 +621,8 @@ int sfc_main (int argc, char **argv)
unsigned short screen[256*192];
copy_screen((void*)screen, up_screen_addr, 0, 0, 256, 192);
- menu(screen);
+ menu(screen, FirstInvocation);
+ FirstInvocation = FALSE;
game_disableAudio();
Settings.Paused = 0;
}
@@ -582,7 +640,6 @@ int sfc_main (int argc, char **argv)
static unsigned int sync_last= 0;
static unsigned int sync_next = 0;
-static unsigned int auto_equivalent_skip = 0;
static unsigned int skip_rate= 0;
@@ -590,6 +647,7 @@ void S9xSyncSpeed ()
{
uint32 syncnow;
int32 syncdif;
+ unsigned int LastAutoCPUFrequency = AutoCPUFrequency;
#if 0
if (Settings.SoundSync == 2)
@@ -601,12 +659,14 @@ void S9xSyncSpeed ()
#endif
syncnow = getSysTime();
- if (game_fast_forward || temporary_fast_forward /* hotkey is held */)
+ bool8 FastForward = game_fast_forward || temporary_fast_forward /* hotkey is held */;
+
+ if (FastForward)
{
sync_last = syncnow;
sync_next = syncnow;
- if(++skip_rate < 10)
+ if(++skip_rate < Settings.TurboSkipFrames)
IPPU.RenderThisFrame = false;
else
{
@@ -614,110 +674,132 @@ void S9xSyncSpeed ()
IPPU.RenderThisFrame = true;
}
}
- else if (Settings.SkipFrames == AUTO_FRAMERATE /* && !game_fast_forward && !temporary_fast_forward */)
+ else
{
- // frame_time is in getSysTime units: 42.667 microseconds.
- int32 frame_time = Settings.PAL ? 468 /* = 20.0 ms */ : 391 /* = 16.67 ms */;
- if (sync_last > syncnow) // Overflow occurred! (every 50 hrs)
+ // Manual or automatic frame skipping, no fast-forward.
+ if (Settings.SkipFrames == AUTO_FRAMERATE)
{
- // Render this frame regardless, set the
- // sync_next, and get the hell out.
- IPPU.RenderThisFrame = TRUE;
+ // frame_time is in getSysTime units: 42.667 microseconds.
+ int32 frame_time = Settings.PAL ? 468 /* = 20.0 ms */ : 391 /* = 16.67 ms */;
+ if (sync_last > syncnow) // Overflow occurred! (every 50 hrs)
+ {
+ // Render this frame regardless, set the
+ // sync_next, and get the hell out.
+ IPPU.RenderThisFrame = TRUE;
+ sync_last = syncnow;
+ sync_next = syncnow + frame_time;
+ return;
+ }
sync_last = syncnow;
- sync_next = syncnow + frame_time;
- return;
- }
- sync_last = syncnow;
- // If this is positive, we have syncdif*42.66 microseconds to
- // spare.
- // If this is negative, we're late by syncdif*42.66
- // microseconds.
- syncdif = sync_next - syncnow;
- if (syncdif < 0 && syncdif >= -(frame_time / 2))
- {
- // We're late, but by less than half a frame. Draw it
- // anyway. If the next frame is too late, it'll be
- // skipped.
- skip_rate = 0;
- IPPU.RenderThisFrame = true;
- sync_next += frame_time;
- }
- else if(syncdif < 0)
- {
- /*
- * If we're consistently late, delay up to 8 frames.
- *
- * That really helps with certain games, such as
- * Super Mario RPG and Yoshi's Island.
- */
- if(++skip_rate < 10)
+ // If this is positive, we have syncdif*42.66 microseconds to
+ // spare.
+ // If this is negative, we're late by syncdif*42.66
+ // microseconds.
+ syncdif = sync_next - syncnow;
+ if(skip_rate < 2 /* did not skip 2 frames yet */)
{
- if(syncdif >= -11719 /* not more than 500.0 ms late */)
+ // Skip a minimum of 2 frames between rendered frames.
+ // This prevents the DSTwo-DS link from being too busy
+ // to return button statuses.
+ ++skip_rate;
+ IPPU.RenderThisFrame = FALSE;
+ sync_next += frame_time;
+ }
+ else if(syncdif < 0)
+ {
+ /*
+ * If we're consistently late, delay up to 8 frames.
+ *
+ * That really helps with certain games, such as
+ * Super Mario RPG and Yoshi's Island.
+ */
+ if(++skip_rate < 10)
{
- IPPU.RenderThisFrame = FALSE;
- sync_next += frame_time;
+ if(syncdif >= -11719 /* not more than 500.0 ms late */)
+ {
+ IPPU.RenderThisFrame = FALSE;
+ sync_next += frame_time;
+ }
+ else
+ { //lag more than 0.5s, maybe paused
+ IPPU.RenderThisFrame = TRUE;
+ sync_next = syncnow + frame_time;
+ }
}
else
- { //lag more than 0.5s, maybe paused
+ {
+ skip_rate = 0;
IPPU.RenderThisFrame = TRUE;
sync_next = syncnow + frame_time;
}
}
- else
+ else // Early
{
skip_rate = 0;
+ if (syncdif > 0)
+ {
+ do {
+ S9xProcessSound (0);
+#ifdef ACCUMULATE_JOYPAD
+/*
+ * This call allows NDSSFC to synchronise the DS controller more often.
+ * If porting a later version of Snes9x into NDSSFC, it is essential to
+ * preserve it.
+ */
+ NDSSFCAccumulateJoypad ();
+#endif
+ syncdif = sync_next - getSysTime();
+ } while (syncdif > 0);
+ }
+
IPPU.RenderThisFrame = TRUE;
- sync_next = syncnow + frame_time;
+ sync_next += frame_time;
}
- }
- else // Early
- {
- skip_rate = 0;
- ds2_setCPUclocklevel(0);
- if (syncdif > 0)
- udelay(syncdif * 128 / 3 /* times 42 + 2/3 microseconds */);
- set_cpu_clock(clock_speed_number);
- S9xProcessSound (0);
-
- IPPU.RenderThisFrame = TRUE;
- sync_next += frame_time;
- }
#if 0
- if(++framenum >= 60)
+ if(++framenum >= 60)
+ {
+ syncdif = syncnow - sync_last;
+ sync_last = syncnow;
+ framenum = 0;
+ //printf("T %d %d\n", syncdif*42667/1000, realframe);
+ realframe = 0;
+ }
+#endif
+ }
+ else /* if (Settings.SkipFrames != AUTO_FRAMERATE) */
{
- syncdif = syncnow - sync_last;
+ // frame_time is in getSysTime units: 42.667 microseconds.
+ uint32 frame_time = Settings.PAL ? 468 /* = 20.0 ms */ : 391 /* = 16.67 ms */;
sync_last = syncnow;
- framenum = 0;
- //printf("T %d %d\n", syncdif*42667/1000, realframe);
- realframe = 0;
- }
+ if (++skip_rate > Settings.SkipFrames)
+ {
+ skip_rate = 0;
+ IPPU.RenderThisFrame = TRUE;
+ // Are we early?
+ syncdif = sync_next - syncnow;
+ if (syncdif > 0)
+ {
+ do {
+ S9xProcessSound (0);
+#ifdef ACCUMULATE_JOYPAD
+/*
+ * This call allows NDSSFC to synchronise the DS controller more often.
+ * If porting a later version of Snes9x into NDSSFC, it is essential to
+ * preserve it.
+ */
+ NDSSFCAccumulateJoypad ();
#endif
- }
- else /* if (Settings.SkipFrames != AUTO_FRAMERATE && !game_fast_forward && !temporary_fast_forward) */
- {
- // frame_time is in getSysTime units: 42.667 microseconds.
- uint32 frame_time = Settings.PAL ? 468 /* = 20.0 ms */ : 391 /* = 16.67 ms */;
- sync_last = syncnow;
- if (++skip_rate > Settings.SkipFrames)
- {
- skip_rate = 0;
- IPPU.RenderThisFrame = TRUE;
- // Are we early?
- syncdif = sync_next - syncnow;
- if (syncdif > 0)
+ syncdif = sync_next - getSysTime();
+ } while (syncdif > 0);
+ // After that little delay, what time is it?
+ syncnow = getSysTime();
+ }
+ sync_next = syncnow + frame_time * (Settings.SkipFrames + 1);
+ }
+ else
{
- ds2_setCPUclocklevel(0);
- udelay(syncdif * 128 / 3 /* times 42 + 2/3 microseconds */);
- set_cpu_clock(clock_speed_number);
- S9xProcessSound (0);
- // After that little delay, what time is it?
- syncnow = getSysTime();
+ IPPU.RenderThisFrame = FALSE;
}
- sync_next = syncnow + frame_time * (Settings.SkipFrames + 1);
- }
- else
- {
- IPPU.RenderThisFrame = FALSE;
}
}
@@ -901,150 +983,189 @@ void S9xGenerateSound ()
}
}
-void S9xProcessSound (unsigned int)
-{
- unsigned short *audiobuff;
+#define SOUND_EMISSION_INTERVAL ((unsigned int) ((((unsigned long long) DS2_BUFFER_SIZE * 1000000) / SND_SAMPLE_RATE) * 3 / 128))
+#define TRUE_SOUND_EMISSION_INTERVAL ((((double) DS2_BUFFER_SIZE * 1000000) / SND_SAMPLE_RATE) * 3 / 128)
+#define SOUND_EMISSION_INTERVAL_ERROR ((int) ((TRUE_SOUND_EMISSION_INTERVAL - SOUND_EMISSION_INTERVAL) * FIXED_POINT))
+static unsigned int LastSoundEmissionTime = 0;
- if (so.mute_sound || !game_enable_audio)
- return;
+/*
+ * Accumulated error in the sound emission time. The unit is as follows:
+ * FIXED_POINT = 42.667 microseconds.
+ * As the error goes past FIXED_POINT, the new target for sound emission
+ * becomes 42.667 microseconds LATER. This helps with sound buffer overruns,
+ * correctly dealing with the fact that 42.667 microseconds does not fit
+ * an integer number of times in 1/32000 second (or whatever sampling rate).
+ */
+static unsigned int SoundEmissionTimeError = 0;
- if(ds2_checkAudiobuff() > 4)
+void S9xProcessSound (unsigned int)
+{
+ if (!game_enable_audio)
return;
- /* Number of samples to generate now */
- int sample_count;
- sample_count = so.buffer_size;
-#ifndef FOREVER_16_BIT_SOUND
- if (so.sixteen_bit)
+ unsigned int Now = getSysTime();
+ if (Now - LastSoundEmissionTime >= SOUND_EMISSION_INTERVAL)
{
-#endif
- /* to prevent running out of buffer space,
- * create less samples
- */
- sample_count >>= 1;
-#ifndef FOREVER_16_BIT_SOUND
- }
-#endif
+ if(ds2_checkAudiobuff() > AUDIO_BUFFER_COUNT - 1)
+ {
+ LastSoundEmissionTime++;
+ return;
+ }
- audiobuff = (unsigned short*)ds2_getAudiobuff();
- if(NULL == audiobuff) //There are audio queue in sending or wait to send
- {
- return;
- }
+ unsigned short *audiobuff;
- /* If we need more audio samples */
- if (so.samples_mixed_so_far < sample_count)
- {
- /* Where to put the samples to */
+ if (Now - LastSoundEmissionTime >= 11719 /* 500 milliseconds */)
+ {
+ LastSoundEmissionTime = Now;
+ // We were probably paused. Restart sending sound,
+ // synchronising from now.
+ }
+ else
+ {
+ LastSoundEmissionTime += SOUND_EMISSION_INTERVAL;
+ SoundEmissionTimeError += SOUND_EMISSION_INTERVAL_ERROR;
+ if (SoundEmissionTimeError >= FIXED_POINT)
+ {
+ LastSoundEmissionTime += SoundEmissionTimeError >> FIXED_POINT_SHIFT;
+ SoundEmissionTimeError &= FIXED_POINT_REMAINDER;
+ }
+ }
+ /* Number of samples to generate now */
+ int sample_count = so.buffer_size;
#ifndef FOREVER_16_BIT_SOUND
- unsigned byte_offset = (so.play_position +
- (so.sixteen_bit ? (so.samples_mixed_so_far << 1) : so.samples_mixed_so_far)) & SOUND_BUFFER_SIZE_MASK;
-#else
- unsigned byte_offset = (so.play_position +
- (so.samples_mixed_so_far << 1)) & SOUND_BUFFER_SIZE_MASK;
+ if (so.sixteen_bit)
+ {
+#endif
+ /* to prevent running out of buffer space,
+ * create less samples
+ */
+ sample_count >>= 1;
+#ifndef FOREVER_16_BIT_SOUND
+ }
#endif
- //printf ("%d:", sample_count - so.samples_mixed_so_far); fflush (stdout);
- if (Settings.SoundSync == 2)
+ audiobuff = (unsigned short*)ds2_getAudiobuff();
+ while (audiobuff == NULL) //There are audio queue in sending or wait to send
{
- /*memset (Buf + (byte_offset & SOUND_BUFFER_SIZE_MASK), 0,
- sample_count - so.samples_mixed_so_far);*/
+#ifdef ACCUMULATE_JOYPAD
+ NDSSFCAccumulateJoypad ();
+#endif
+ audiobuff = (unsigned short*)ds2_getAudiobuff();
}
- else
+
+ /* If we need more audio samples */
+ if (so.samples_mixed_so_far < sample_count)
{
- /* Mix the missing samples */
+ /* Where to put the samples to */
#ifndef FOREVER_16_BIT_SOUND
- int bytes_so_far = so.sixteen_bit ? (so.samples_mixed_so_far << 1) :
- so.samples_mixed_so_far;
+ unsigned byte_offset = (so.play_position +
+ (so.sixteen_bit ? (so.samples_mixed_so_far << 1) : so.samples_mixed_so_far)) & SOUND_BUFFER_SIZE_MASK;
#else
- int bytes_so_far = so.samples_mixed_so_far << 1;
+ unsigned byte_offset = (so.play_position +
+ (so.samples_mixed_so_far << 1)) & SOUND_BUFFER_SIZE_MASK;
#endif
- uint32 samples_to_write = sample_count - so.samples_mixed_so_far;
- do
+ if (Settings.SoundSync == 2)
{
- int bytes_this_run = samples_to_write;
+ /*memset (Buf + (byte_offset & SOUND_BUFFER_SIZE_MASK), 0,
+ sample_count - so.samples_mixed_so_far);*/
+ }
+ else
+ {
+ /* Mix the missing samples */
#ifndef FOREVER_16_BIT_SOUND
- if (so.sixteen_bit)
+ int bytes_so_far = so.sixteen_bit ? (so.samples_mixed_so_far << 1) :
+ so.samples_mixed_so_far;
+#else
+ int bytes_so_far = so.samples_mixed_so_far << 1;
#endif
- bytes_this_run <<= 1;
- if (byte_offset + bytes_this_run > SOUND_BUFFER_SIZE)
+ uint32 samples_to_write = sample_count - so.samples_mixed_so_far;
+ do
{
- bytes_this_run = SOUND_BUFFER_SIZE - byte_offset;
- }
+ int bytes_this_run = samples_to_write;
+#ifndef FOREVER_16_BIT_SOUND
+ if (so.sixteen_bit)
+#endif
+ bytes_this_run <<= 1;
- if (bytes_so_far + bytes_this_run > so.buffer_size)
- {
- bytes_this_run = so.buffer_size - bytes_so_far;
- if (bytes_this_run == 0)
- break;
- }
+ if (byte_offset + bytes_this_run > SOUND_BUFFER_SIZE)
+ {
+ bytes_this_run = SOUND_BUFFER_SIZE - byte_offset;
+ }
- int samples_this_run = bytes_this_run;
+ if (bytes_so_far + bytes_this_run > so.buffer_size)
+ {
+ bytes_this_run = so.buffer_size - bytes_so_far;
+ if (bytes_this_run == 0)
+ break;
+ }
+
+ int samples_this_run = bytes_this_run;
#ifndef FOREVER_16_BIT_SOUND
- if (so.sixteen_bit)
+ if (so.sixteen_bit)
#endif
- samples_this_run >>= 1;
+ samples_this_run >>= 1;
- S9xMixSamples (Buf + byte_offset, samples_this_run);
- so.samples_mixed_so_far += samples_this_run;
- samples_to_write -= samples_this_run;
+ S9xMixSamples (Buf + byte_offset, samples_this_run);
+ so.samples_mixed_so_far += samples_this_run;
+ samples_to_write -= samples_this_run;
#ifndef FOREVER_16_BIT_SOUND
- bytes_so_far += so.sixteen_bit ? (samples_this_run << 1) :
- samples_this_run;
+ bytes_so_far += so.sixteen_bit ? (samples_this_run << 1) :
+ samples_this_run;
#else
- bytes_so_far += samples_this_run << 1;
+ bytes_so_far += samples_this_run << 1;
#endif
- byte_offset = (byte_offset + bytes_this_run) & SOUND_BUFFER_SIZE_MASK;
- } while (samples_to_write > 0);
+ byte_offset = (byte_offset + bytes_this_run) & SOUND_BUFFER_SIZE_MASK;
+ } while (samples_to_write > 0);
+ }
}
- }
-// if (!so.mute_sound)
- {
- unsigned bytes_to_write = sample_count;
+ // if (!so.mute_sound)
+ {
+ unsigned bytes_to_write = sample_count;
#ifndef FOREVER_16_BIT_SOUND
- if(so.sixteen_bit)
+ if(so.sixteen_bit)
#endif
- bytes_to_write <<= 1;
+ bytes_to_write <<= 1;
- unsigned byte_offset = so.play_position;
- so.play_position = (so.play_position + bytes_to_write) & SOUND_BUFFER_SIZE_MASK; /* wrap to beginning */
+ unsigned byte_offset = so.play_position;
+ so.play_position = (so.play_position + bytes_to_write) & SOUND_BUFFER_SIZE_MASK; /* wrap to beginning */
- unsigned short *dst_pt = audiobuff;
- unsigned short *dst_pt1 = dst_pt + DS2_BUFFER_SIZE;
+ unsigned short *dst_pt = audiobuff;
+ unsigned short *dst_pt1 = dst_pt + DS2_BUFFER_SIZE;
- /* Feed the samples to the soundcard until nothing is left */
- for(;;)
- {
- int I = bytes_to_write;
- if (byte_offset + I > SOUND_BUFFER_SIZE)
+ /* Feed the samples to the soundcard until nothing is left */
+ for(;;)
{
- I = SOUND_BUFFER_SIZE - byte_offset;
- }
- if(I == 0) break;
+ int I = bytes_to_write;
+ if (byte_offset + I > SOUND_BUFFER_SIZE)
+ {
+ I = SOUND_BUFFER_SIZE - byte_offset;
+ }
+ if(I == 0) break;
-// memcpy(dst_pt, (char *) Buf + byte_offset, I);
-// dst_pt += I;
+ // memcpy(dst_pt, (char *) Buf + byte_offset, I);
+ // dst_pt += I;
- unsigned short *src_pt= (unsigned short*)(Buf + byte_offset);
- for(int m= 0; m < I/4; m++)
- {
- *dst_pt++= *src_pt++;//(*src_pt++) <<1;
- *dst_pt1++= *src_pt++;//(*src_pt++) <<1;
+ unsigned short *src_pt= (unsigned short*)(Buf + byte_offset);
+ for(int m= 0; m < I/4; m++)
+ {
+ *dst_pt++= *src_pt++;//(*src_pt++) <<1;
+ *dst_pt1++= *src_pt++;//(*src_pt++) <<1;
+ }
+
+ bytes_to_write -= I;
+ byte_offset = (byte_offset + I) & SOUND_BUFFER_SIZE_MASK; /* wrap */
}
- bytes_to_write -= I;
- byte_offset = (byte_offset + I) & SOUND_BUFFER_SIZE_MASK; /* wrap */
- }
+ ds2_updateAudio();
- ds2_updateAudio();
+ /* All data sent. */
+ }
- /* All data sent. */
+ so.samples_mixed_so_far -= sample_count;
}
-
- so.samples_mixed_so_far -= sample_count;
}
/*
@@ -1066,68 +1187,99 @@ const unsigned int keymap[12] = {
static bool8 SoundToggleWasHeld = FALSE;
-unsigned int S9xReadJoypad (int which1)
-{
- struct key_buf inputdata;
+#ifdef ACCUMULATE_JOYPAD
+// These are kept as DS key bitfields until it's time to send them to Snes9x.
+static uint32 PreviousControls = 0x00000000;
+static uint32 ControlsPressed = 0x00000000;
+static uint32 ControlsReleased = 0x00000000;
+void NDSSFCAccumulateJoypad ()
+{
+ struct key_buf inputdata;
ds2_getrawInput(&inputdata);
- if (inputdata.key & KEY_LID)
+ ControlsPressed |= inputdata.key & ~PreviousControls;
+ ControlsReleased |= PreviousControls & ~inputdata.key;
+}
+#endif // ACCUMULATE_JOYPAD
+
+uint32 S9xReadJoypad (int which1)
+{
+ if(which1 < 1)
{
- ds2_setCPUclocklevel(0);
- ds2_setSupend();
- do {
+ uint32 Controls;
+#ifdef ACCUMULATE_JOYPAD
+ Controls = (PreviousControls | ControlsPressed) & ~ControlsReleased;
+ PreviousControls = Controls;
+ ControlsPressed = ControlsReleased = 0x00000000;
+#else
+ {
+ struct key_buf inputdata;
ds2_getrawInput(&inputdata);
- mdelay(1);
- } while (inputdata.key & KEY_LID);
- ds2_wakeup();
- set_cpu_clock(clock_speed_number);
- }
- u32 HotkeyReturnToMenu = game_config.HotkeyReturnToMenu != 0 ? game_config.HotkeyReturnToMenu : emu_config.HotkeyReturnToMenu;
- u32 HotkeyTemporaryFastForward = game_config.HotkeyTemporaryFastForward != 0 ? game_config.HotkeyTemporaryFastForward : emu_config.HotkeyTemporaryFastForward;
- u32 HotkeyToggleSound = game_config.HotkeyToggleSound != 0 ? game_config.HotkeyToggleSound : emu_config.HotkeyToggleSound;
+ Controls = inputdata.key;
+ }
+#endif
- if(inputdata.key & KEY_TOUCH ||
- (HotkeyReturnToMenu && ((inputdata.key & HotkeyReturnToMenu) == HotkeyReturnToMenu))
- ) //Active menu
- Settings.Paused = 1;
+ if (Controls & KEY_LID)
+ {
+ LowFrequencyCPU();
+ ds2_setSupend();
+ struct key_buf inputdata;
+ do {
+ ds2_getrawInput(&inputdata);
+ mdelay(1);
+ } while (inputdata.key & KEY_LID);
+ ds2_wakeup();
+ // Before starting to emulate again, turn off the lower
+ // screen's backlight.
+ mdelay(100); // needed to avoid ds2_setBacklight crashing
+ ds2_setBacklight(2);
+ GameFrequencyCPU();
+ }
- temporary_fast_forward =
- (HotkeyTemporaryFastForward && ((inputdata.key & HotkeyTemporaryFastForward) == HotkeyTemporaryFastForward))
- ;
+ u32 HotkeyReturnToMenu = game_config.HotkeyReturnToMenu != 0 ? game_config.HotkeyReturnToMenu : emu_config.HotkeyReturnToMenu;
+ u32 HotkeyTemporaryFastForward = game_config.HotkeyTemporaryFastForward != 0 ? game_config.HotkeyTemporaryFastForward : emu_config.HotkeyTemporaryFastForward;
+ u32 HotkeyToggleSound = game_config.HotkeyToggleSound != 0 ? game_config.HotkeyToggleSound : emu_config.HotkeyToggleSound;
- bool8 SoundToggleIsHeld =
- (HotkeyToggleSound && ((inputdata.key & HotkeyToggleSound) == HotkeyToggleSound))
- ;
+ if(Controls & KEY_TOUCH ||
+ (HotkeyReturnToMenu && ((Controls & HotkeyReturnToMenu) == HotkeyReturnToMenu))
+ ) //Active menu
+ Settings.Paused = 1;
- if (SoundToggleIsHeld && !SoundToggleWasHeld)
- {
- game_enable_audio = !game_enable_audio;
- game_disableAudio();
- }
+ temporary_fast_forward =
+ (HotkeyTemporaryFastForward && ((Controls & HotkeyTemporaryFastForward) == HotkeyTemporaryFastForward))
+ ;
- SoundToggleWasHeld = SoundToggleIsHeld;
+ bool8 SoundToggleIsHeld =
+ (HotkeyToggleSound && ((Controls & HotkeyToggleSound) == HotkeyToggleSound))
+ ;
- if(which1 < 1)
- {
- unsigned int key;
+ if (SoundToggleIsHeld && !SoundToggleWasHeld)
+ {
+ game_enable_audio = !game_enable_audio;
+ game_disableAudio();
+ }
+
+ SoundToggleWasHeld = SoundToggleIsHeld;
+
+ uint32 key = 0x80000000; // Required by Snes9x
// DS -> SNES
- key = (inputdata.key & KEY_A ) << 7; // 0x0001 -> 0x0080
- key |= (inputdata.key & KEY_B ) << 14; // 0x0002 -> 0x8000
- key |= (inputdata.key & KEY_SELECT) << 11; // 0x0004 -> 0x2000
- key |= (inputdata.key & KEY_START ) << 9; // 0x0008 -> 0x1000
- key |= (inputdata.key & KEY_UP ) << 5; // 0x0040 -> 0x0800
+ key |= (Controls & KEY_A ) << 7; // 0x0001 -> 0x0080
+ key |= (Controls & KEY_B ) << 14; // 0x0002 -> 0x8000
+ key |= (Controls & KEY_SELECT) << 11; // 0x0004 -> 0x2000
+ key |= (Controls & KEY_START ) << 9; // 0x0008 -> 0x1000
+ key |= (Controls & KEY_UP ) << 5; // 0x0040 -> 0x0800
// 0x0010 -> 0x0100; 0x0020 -> 0x0200
// 0x0030 -> 0x0300
- key |= (inputdata.key & (KEY_RIGHT | KEY_LEFT)) << 4;
+ key |= (Controls & (KEY_RIGHT | KEY_LEFT)) << 4;
// 0x0100 -> 0x0010; 0x0200 -> 0x0020; 0x0400 -> 0x0040
// 0x0700 -> 0x0070
- key |= (inputdata.key & (KEY_R | KEY_L | KEY_X)) >> 4;
+ key |= (Controls & (KEY_R | KEY_L | KEY_X)) >> 4;
// 0x0080 -> 0x0400; 0x0800 -> 0x4000
// 0x0880 -> 0x4400
- key |= (inputdata.key & (KEY_DOWN | KEY_Y)) << 3;
+ key |= (Controls & (KEY_DOWN | KEY_Y)) << 3;
/*
for(i= 0; i < 12; i++) //remap key
{
@@ -1135,7 +1287,7 @@ unsigned int S9xReadJoypad (int which1)
}
*/
- return (key | 0x80000000);
+ return key;
}
else
return 0;
diff --git a/source/nds/entry.h b/source/nds/entry.h
index a6bd350..0728768 100644
--- a/source/nds/entry.h
+++ b/source/nds/entry.h
@@ -7,7 +7,9 @@ extern "C" {
void game_restart(void);
- int load_gamepak(char* file);
+ int load_gamepak(const char* file);
+
+ extern unsigned int AutoCPUFrequency;
#ifdef __cplusplus
}
#endif
diff --git a/source/nds/gui.c b/source/nds/gui.c
index 09e01ac..4299db2 100644
--- a/source/nds/gui.c
+++ b/source/nds/gui.c
@@ -45,23 +45,27 @@ char rom_path[MAX_PATH];
char gamepak_name[MAX_PATH];
char gcheat_filename[MAX_PATH];
+//program arguments
+char argv[2][MAX_PATH];
+
// If adding a language, make sure you update the size of the array in
// message.h too.
-char *lang[3] =
- {
+char *lang[4] =
+ {
"English", // 0
"简体中文", // 1
- "Français", // 2
+ "Français", // 2
+ "Deutsch", // 3
};
-char *language_options[] = { (char *) &lang[0], (char *) &lang[1], (char *) &lang[2] };
+char *language_options[] = { (char *) &lang[0], (char *) &lang[1], (char *) &lang[2], (char *) &lang[3] };
/******************************************************************************
* Macro definition
******************************************************************************/
#define SUBMENU_ROW_NUM 6
-#define NDSSFC_VERSION "1.23"
+#define NDSSFC_VERSION "1.28"
#define SAVE_STATE_SLOT_NUM 16
@@ -289,7 +293,6 @@ u32 game_enable_audio = 1;
/******************************************************************************
******************************************************************************/
static u32 menu_cheat_page = 0;
-u32 clock_speed_number = 5;
u32 gamepad_config_menu;
/******************************************************************************
@@ -324,6 +327,21 @@ gui_action_type get_gui_input(void)
key = getKey();
+ if (key & KEY_LID)
+ {
+ ds2_setSupend();
+ struct key_buf inputdata;
+ do {
+ ds2_getrawInput(&inputdata);
+ mdelay(1);
+ } while (inputdata.key & KEY_LID);
+ ds2_wakeup();
+ // In the menu, the lower screen's backlight needs to be on,
+ // and it is on right away after resuming from suspend.
+ // mdelay(100); // needed to avoid ds2_setBacklight crashing
+ // ds2_setBacklight(3);
+ }
+
switch(key)
{
case KEY_UP:
@@ -420,53 +438,52 @@ void change_ext(char *src, char *buffer, char *extension)
--------------------------------------------------------*/
static int sort_function(const void *dest_str_ptr, const void *src_str_ptr)
{
- char *dest_str = *((char **)dest_str_ptr);
- char *src_str = *((char **)src_str_ptr);
+ char *dest_str = ((char *)dest_str_ptr);
+ char *src_str = ((char *)src_str_ptr);
// For files and directories, . and .. sort first.
- if(src_str[0] == '.')
+ if(src_str[0] == '.' && dest_str[0] != '.')
return 1;
- if(dest_str[0] == '.')
+ if(dest_str[0] == '.' && src_str[0] != '.')
return -1;
return strcasecmp(dest_str, src_str);
}
-static int my_array_partion(void *array, int left, int right)
+static int my_array_partion(void **array, int left, int right)
{
- unsigned int pivot= *((unsigned int*)array + left);
-
- while(left < right)
- {
- while(sort_function((void*)((unsigned int*)array+left), (void*)((unsigned int *)array+right)) < 0) {
- right--;
- }
-
- if(right== left) break;
- *((unsigned int*)array + left) = *((unsigned int*)array + right);
- *((unsigned int*)array + right) = pivot;
-
- if(left < right)
- {
- left++;
- if(right== left) break;
- }
-
- while(sort_function((void*)((unsigned int*)array+right), (void*)((unsigned int *)array+left)) > 0) {
- left++;
- }
+ // Choose a pivot, left <= pivot <= right
+ unsigned int pivotIndex = left + (right - left) / 2;
+
+ // Move pivot value to the end
+ void *temp = array[pivotIndex];
+ array[pivotIndex] = array[right];
+ array[right] = temp;
+
+ // Move values that sort before the pivot value to before the new
+ // pivot's location
+ unsigned int storeIndex = left, i;
+ for (i = left; i <= right - 1; i++)
+ {
+ if (sort_function(array[i], array[right]) < 0)
+ {
+ temp = array[i];
+ array[i] = array[storeIndex];
+ array[storeIndex] = temp;
+ storeIndex++;
+ }
+ }
- if(left== right) break;
- *((unsigned int*)array + right) = *((unsigned int*)array + left);
- *((unsigned int*)array + left) = pivot;
- right--;
- }
+ // Move the pivot value to its correct location
+ temp = array[storeIndex];
+ array[storeIndex] = array[right];
+ array[right] = temp;
- return left;
+ return storeIndex;
}
-static void my_qsort(void *array, int left, int right)
+static void my_qsort(void **array, int left, int right)
{
if(left < right)
{
@@ -558,7 +575,7 @@ static int manage_filelist_info(struct FILE_LIST_INFO *filelist_infop, int flag)
int i;
void *pt;
- //Increase all
+ //Increase all
if(flag & 0x1)
{
i = NAME_MEM_SIZE;
@@ -733,9 +750,9 @@ static int load_file_list(struct FILE_LIST_INFO *filelist_infop)
#if 0
my_qsort((void *)file_list, 0, num_files-1);
#else //to support ".." directory, but take it as file
- my_qsort((void *)file_list, 1, num_files-1);
+ my_qsort((void **)file_list, 1, num_files-1);
#endif
- my_qsort((void *)dir_list, 0, num_dirs-1);
+ my_qsort((void **)dir_list, 0, num_dirs-1);
return 0;
}
@@ -820,6 +837,7 @@ s32 load_file(char **wildcards, char *result, char *default_dir_name)
{
case CURSOR_TOUCH:
ds2_getrawInput(&inputdata);
+ wait_Allkey_release(0);
// ___ 33 This screen has 6 possible rows. Touches
// ___ 60 above or below these are ignored.
// . . . (+27)
@@ -985,6 +1003,7 @@ s32 load_file(char **wildcards, char *result, char *default_dir_name)
break;
case CURSOR_SELECT:
+ wait_Allkey_release(0);
//file selected
if(selected_item_on_list + 1 <= num_files)
{
@@ -1024,6 +1043,7 @@ s32 load_file(char **wildcards, char *result, char *default_dir_name)
case CURSOR_BACK:
{
+ wait_Allkey_release(0);
char *ext_pos;
strcpy(filelist_info.current_path, default_dir_name);
@@ -1041,6 +1061,7 @@ s32 load_file(char **wildcards, char *result, char *default_dir_name)
}
case CURSOR_EXIT:
+ wait_Allkey_release(0);
return_value = -1;
repeat = 0;
break;
@@ -1082,7 +1103,7 @@ s32 load_file(char **wildcards, char *result, char *default_dir_name)
//Path
if(-1 == redraw) {
draw_hscroll_over(0);
- draw_hscroll_init(down_screen_addr, 49, 10, 170, COLOR_TRANS,
+ draw_hscroll_init(down_screen_addr, 49, 10, 170, COLOR_TRANS,
COLOR_WHITE, default_dir_name);
path_scroll = 0x8000; //first scroll left
}
@@ -1129,7 +1150,7 @@ s32 load_file(char **wildcards, char *result, char *default_dir_name)
pt = file_list[m];
}
- draw_hscroll_init(down_screen_addr, 41, 40 + k*27, 185,
+ draw_hscroll_init(down_screen_addr, 41, 40 + k*27, 185,
COLOR_TRANS, color, pt);
}
@@ -1260,7 +1281,7 @@ u32 play_screen_snapshot(void)
if(draw_yesno_dialog(DOWN_SCREEN, 115, msg[MSG_GENERAL_CONFIRM_WITH_A], msg[MSG_GENERAL_CANCEL_WITH_B]))
return 1;
- else
+ else
return 0;
}
@@ -1365,7 +1386,7 @@ u32 play_screen_snapshot(void)
time1= time0;
}
break;
-
+
case CURSOR_DOWN:
if(!pause)
{
@@ -1373,21 +1394,21 @@ u32 play_screen_snapshot(void)
time1= time0;
}
break;
-
+
case CURSOR_LEFT:
time1 = ticks;
if(i > 1) i -= 2;
else if(i == 1) i= file_num -1;
else i= file_num -2;
break;
-
+
case CURSOR_RIGHT:
time1 = ticks;
break;
-
+
case CURSOR_SELECT:
if(!pause)
- {
+ {
time1 = -1;
pause= 1;
}
@@ -1395,15 +1416,15 @@ u32 play_screen_snapshot(void)
{
time1 = ticks;
pause= 0;
- }
+ }
break;
-
- case CURSOR_BACK:
+
+ case CURSOR_BACK:
if(screenp) free((void*)screenp);
//deconstruct filelist_info struct
manage_filelist_info(&filelist_info, -1);
repeat = 0;
- break;
+ break;
default: gui_action= CURSOR_NONE;
break;
@@ -1443,7 +1464,7 @@ int search_dir(char *directory, char* directory_path)
//while((current_file = readdir(current_dir)) != NULL)
while((current_file = readdir_ex(current_dir, &st)) != NULL)
{
- //Is directory
+ //Is directory
if(S_ISDIR(st.st_mode))
{
if(strcmp(".", current_file->d_name) || strcmp("..", current_file->d_name))
@@ -1622,7 +1643,7 @@ int save_state(char* file, void* screen)
n = ftell(fp);
ds2_getTime(&time);
- sprintf(str, "%02d-%02d %02d:%02d:%02d",
+ sprintf(str, "%02d-%02d %02d:%02d:%02d",
time.month, time.day, time.hours, time.minutes, time.seconds);
PRINT_STRING_BG(screen, str, COLOR_WHITE, COLOR_BLACK, 0, 0);
@@ -1637,12 +1658,22 @@ int save_state(char* file, void* screen)
return 0;
}
-void set_cpu_clock(u32 num)
+void LowFrequencyCPU()
{
- u32 clock_speed_table[6] = {6, 9, 10, 11, 12, 13}; //240, 300, 336, 360, 384, 394
+ ds2_setCPUclocklevel(0); // 60 MHz
+}
- if(num <= 5)
- ds2_setCPUclocklevel(clock_speed_table[num]);
+void HighFrequencyCPU()
+{
+ ds2_setCPUclocklevel(13); // 396 MHz
+}
+
+void GameFrequencyCPU()
+{
+ u32 clock_speed_table[6] = {6, 9, 10, 11, 12, 13}; //240, 300, 336, 360, 384, 396
+
+ if(game_config.clock_speed_number <= 5)
+ ds2_setCPUclocklevel(clock_speed_table[game_config.clock_speed_number]);
}
void savefast_int(void)
@@ -1668,7 +1699,7 @@ unsigned int frame_interval;
/*--------------------------------------------------------
Main Menu
--------------------------------------------------------*/
-u32 menu(u16 *screen)
+u32 menu(u16 *screen, bool8 FirstInvocation)
{
gui_action_type gui_action;
u32 i;
@@ -1684,7 +1715,7 @@ u32 menu(u16 *screen)
MENU_TYPE *current_menu = NULL;
MENU_OPTION_TYPE *current_option = NULL;
MENU_OPTION_TYPE *display_option = NULL;
-
+
u32 current_option_num;
// u32 parent_option_num;
u32 string_select;
@@ -1692,6 +1723,9 @@ u32 menu(u16 *screen)
u16 *bg_screenp;
u32 bg_screenp_color;
+ GAME_CONFIG PreviousGameConfig; // Compared with current settings to
+ EMU_CONFIG PreviousEmuConfig; // determine if they need to be saved
+
auto void choose_menu();
auto void menu_return();
auto void menu_exit();
@@ -1732,7 +1766,9 @@ u32 menu(u16 *screen)
auto void latest_game_menu_end();
auto void language_set();
auto void game_fastforward();
+#ifdef ENABLE_FREE_SPACE
auto void show_card_space();
+#endif
auto void savestate_selitem(u32 sel, u32 y_pos);
auto void game_state_menu_passive();
auto void gamestate_delette_menu_passive();
@@ -1747,131 +1783,94 @@ u32 menu(u16 *screen)
void menu_exit()
{
- ds2_setCPUclocklevel(13); // Crank it up, leave quickly
- if(gamepak_name[0] != 0)
- {
- game_config.clock_speed_number = clock_speed_number;
-
- reorder_latest_file();
+ HighFrequencyCPU(); // Crank it up, leave quickly
+ if(gamepak_name[0] != 0)
+ {
S9xAutoSaveSRAM ();
- save_game_config_file();
}
- save_emu_config_file();
quit();
}
- void menu_load()
+ void SaveConfigsIfNeeded()
{
- char *file_ext[] = { ".smc", ".sfc", ".zip", NULL };
-
- if(gamepak_name[0] != 0)
- {
- S9xAutoSaveSRAM ();
+ if (memcmp(&PreviousGameConfig, &game_config, sizeof(GAME_CONFIG)) != 0)
save_game_config_file();
- }
+ if (memcmp(&PreviousEmuConfig, &emu_config, sizeof(EMU_CONFIG)) != 0)
+ save_emu_config_file();
+ }
- if(load_file(file_ext, tmp_filename, g_default_rom_dir) != -1)
- {
- strcpy(line_buffer, g_default_rom_dir);
- strcat(line_buffer, "/");
- strcat(line_buffer, tmp_filename);
+ void PreserveConfigs()
+ {
+ memcpy(&PreviousGameConfig, &game_config, sizeof(GAME_CONFIG));
+ memcpy(&PreviousEmuConfig, &emu_config, sizeof(EMU_CONFIG));
+ }
- draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, bg_screenp_color);
- draw_string_vcenter(down_screen_addr, 36, 100, 190, COLOR_MSSG, msg[MSG_PROGRESS_LOADING_GAME]);
- ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD);
+ int LoadGameAndItsData(char *filename){
+ if (gamepak_name[0] != '\0') {
+ S9xAutoSaveSRAM();
+ }
- ds2_setCPUclocklevel(13);
- int load_result = load_gamepak(line_buffer);
- ds2_setCPUclocklevel(0);
- if(load_result == -1)
- {
- first_load = 1;
- gamepak_name[0] = '\0';
- return;
- }
+ draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, bg_screenp_color);
+ draw_string_vcenter(down_screen_addr, 36, 100, 190, COLOR_MSSG, msg[MSG_PROGRESS_LOADING_GAME]);
+ ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD);
- strcpy(gamepak_name, tmp_filename);
- first_load = 0;
- load_game_config_file();
-// time_period_action();
+ HighFrequencyCPU();
+ int load_result = load_gamepak(filename);
+ LowFrequencyCPU();
- return_value = 1;
- repeat = 0;
+ if(load_result == -1)
+ {
+ first_load = 1;
+ gamepak_name[0] = '\0';
+ return 0;
+ }
- reorder_latest_file();
- get_savestate_filelist();
+ char tempPath[MAX_PATH];
+ strcpy(tempPath, filename);
- game_fast_forward= 0;
- }
- else
- {
- choose_menu(current_menu);
- }
- }
-
- bool Get_Args(char *file, char **filebuf)
- {
- FILE* dat = fat_fopen(file, "rb");
- if(dat)
- {
- int i = 0;
- while(!fat_feof (dat))
- {
- fat_fgets(filebuf[i], 512, dat);
- int len = strlen(filebuf[i]);
- if(filebuf[i][len - 1] == '\n')
- filebuf[i][len - 1] = '\0';
- i++;
- }
-
- fat_fclose(dat);
- fat_remove(file);
- return i;
- }
- return 0;
- }
+ //update folders and names for settings/config uses
+ char *dirEnd = strrchr(tempPath, '/');
+ //make sure a valid path was provided
+ if(!dirEnd)
+ return 0;
- int CheckLoad_Arg()
- {
- char args[2][512];
- char *argarray[2];
-
- argarray[0] = args[0];
- argarray[1] = args[1];
-
- if(!Get_Args("/plgargs.dat", argarray))
- return 0;
-
- fat_remove("plgargs.dat");
-
- draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, bg_screenp_color);
- draw_string_vcenter(down_screen_addr, 36, 100, 190, COLOR_MSSG, msg[MSG_PROGRESS_LOADING_GAME]);
- ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD);
+ //copy file name as gamepak_name
+ strcpy(gamepak_name, dirEnd+1);
+ //then strip filename from directory path and set it
+ *dirEnd = '\0';
+ strcpy(g_default_rom_dir, tempPath);
- ds2_setCPUclocklevel(13);
- int load_result = load_gamepak(args[1]);
- ds2_setCPUclocklevel(0);
+ first_load = 0;
+ load_game_config_file();
+ PreserveConfigs(); // Make the emulator not save what we've JUST read
+ // but it will save the emulator configuration below for latest files
- if(load_result == -1)
- {
- first_load = 1;
- gamepak_name[0] = '\0';
- return 0;
- }
+ return_value = 1;
+ repeat = 0;
- strcpy(gamepak_name, args[1]);
- first_load = 0;
- load_game_config_file();
+ reorder_latest_file();
+ get_savestate_filelist();
- return_value = 1;
- repeat = 0;
+ game_fast_forward= 0;
+ return 1;
+ }
- reorder_latest_file();
- get_savestate_filelist();
+ void menu_load()
+ {
+ char *file_ext[] = { ".smc", ".sfc", ".zip", NULL };
+
+ if(load_file(file_ext, tmp_filename, g_default_rom_dir) != -1)
+ {
+ strcpy(line_buffer, g_default_rom_dir);
+ strcat(line_buffer, "/");
+ strcat(line_buffer, tmp_filename);
- game_fast_forward= 0;
- return 1;
-
+ LoadGameAndItsData(line_buffer);
+ }
+ else
+ {
+ choose_menu(current_menu);
+ }
}
void menu_restart()
@@ -2060,9 +2059,9 @@ u32 menu(u16 *screen)
draw_string_vcenter(down_screen_addr, 36, 100, 190, COLOR_MSSG, msg[MSG_PROGRESS_SAVED_STATE_CREATING]);
ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD);
- ds2_setCPUclocklevel(13);
+ HighFrequencyCPU();
int flag = save_state(tmp_filename, (void*)screen);
- ds2_setCPUclocklevel(0);
+ LowFrequencyCPU();
//clear message
draw_message(down_screen_addr, NULL, 28, 31, 227, 96, 0);
if(flag < 0)
@@ -2076,17 +2075,13 @@ u32 menu(u16 *screen)
ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD);
- //save game config
- reorder_latest_file();
- save_game_config_file();
-
SavedStateCacheInvalidate ();
mdelay(500); // let the progress message linger
}
}
}
-
+
void menu_load_state()
{
if(!first_load)
@@ -2126,12 +2121,12 @@ u32 menu(u16 *screen)
//right
if(gui_action == CURSOR_SELECT)
{
- draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, bg_screenp_color);
+ draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, bg_screenp_color);
draw_string_vcenter(up_screen_addr, 36, 75, 190, COLOR_MSSG, msg[MSG_PROGRESS_SAVED_STATE_LOADING]);
- ds2_setCPUclocklevel(13);
+ HighFrequencyCPU();
int flag = load_state(tmp_filename);
- ds2_setCPUclocklevel(0);
+ LowFrequencyCPU();
if(0 == flag)
{
return_value = 1;
@@ -2146,9 +2141,9 @@ u32 menu(u16 *screen)
}
else //load screen snapshot
{
- ds2_setCPUclocklevel(13);
+ HighFrequencyCPU();
load_game_stat_snapshot(tmp_filename);
- ds2_setCPUclocklevel(0);
+ LowFrequencyCPU();
}
}
else
@@ -2210,7 +2205,7 @@ u32 menu(u16 *screen)
}
else if(current_option_num == 2) //delette single
{
- draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, bg_screenp_color);
+ draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, bg_screenp_color);
if(SavedStateFileExists(delette_savestate_num))
{
@@ -2278,7 +2273,7 @@ u32 menu(u16 *screen)
{
m= current_menu->screen_focus -1;
draw_hscroll_over(m+1);
- draw_hscroll_init(down_screen_addr, 23, 40 + m*27, 200,
+ draw_hscroll_init(down_screen_addr, 23, 40 + m*27, 200,
COLOR_TRANS, COLOR_INACTIVE_ITEM, *dynamic_cheat_options[current_option_num].display_string);
}
else
@@ -2288,7 +2283,7 @@ u32 menu(u16 *screen)
m= current_menu->focus_option - current_menu->screen_focus+2;
for(n= 0; n < SUBMENU_ROW_NUM-1; n++)
- draw_hscroll_init(down_screen_addr, 23, 40 + n*27, 200,
+ draw_hscroll_init(down_screen_addr, 23, 40 + n*27, 200,
COLOR_TRANS, COLOR_INACTIVE_ITEM, *dynamic_cheat_options[m+n].display_string);
}
}
@@ -2296,7 +2291,7 @@ u32 menu(u16 *screen)
if(current_option_num == 0)
{
draw_hscroll_over(0);
- draw_hscroll_init(down_screen_addr, 50, 9, 180,
+ draw_hscroll_init(down_screen_addr, 50, 9, 180,
COLOR_TRANS, COLOR_ACTIVE_ITEM, *dynamic_cheat_options[0].display_string);
}
@@ -2309,7 +2304,7 @@ u32 menu(u16 *screen)
if(m >= SUBMENU_ROW_NUM) m -= 1;
draw_hscroll_over(m+1);
- draw_hscroll_init(down_screen_addr, 23, 40 + m*27, 200,
+ draw_hscroll_init(down_screen_addr, 23, 40 + m*27, 200,
COLOR_TRANS, COLOR_ACTIVE_ITEM, *dynamic_cheat_options[current_option_num].display_string);
}
@@ -2323,7 +2318,7 @@ u32 menu(u16 *screen)
{
m = current_menu->screen_focus -1;
draw_hscroll_over(m+1);
- draw_hscroll_init(down_screen_addr, 23, 40 + m*27, 200,
+ draw_hscroll_init(down_screen_addr, 23, 40 + m*27, 200,
COLOR_TRANS, COLOR_INACTIVE_ITEM, *dynamic_cheat_options[current_option_num].display_string);
}
else
@@ -2338,7 +2333,7 @@ u32 menu(u16 *screen)
if(k > SUBMENU_ROW_NUM) k = SUBMENU_ROW_NUM;
for(n= 1; n < k; n++)
- draw_hscroll_init(down_screen_addr, 23, 40 + n*27, 200,
+ draw_hscroll_init(down_screen_addr, 23, 40 + n*27, 200,
COLOR_TRANS, COLOR_INACTIVE_ITEM, *dynamic_cheat_options[m+n].display_string);
}
}
@@ -2350,7 +2345,7 @@ u32 menu(u16 *screen)
if(current_option_num == 0)
{
draw_hscroll_over(0);
- draw_hscroll_init(down_screen_addr, 50, 9, 180,
+ draw_hscroll_init(down_screen_addr, 50, 9, 180,
COLOR_TRANS, COLOR_ACTIVE_ITEM, *dynamic_cheat_options[0].display_string);
}
}
@@ -2365,7 +2360,7 @@ u32 menu(u16 *screen)
m = current_menu->screen_focus -1;
draw_hscroll_over(m+1);
- draw_hscroll_init(down_screen_addr, 23, 40 + m*27, 200,
+ draw_hscroll_init(down_screen_addr, 23, 40 + m*27, 200,
COLOR_TRANS, COLOR_ACTIVE_ITEM, *dynamic_cheat_options[current_option_num].display_string);
}
break;
@@ -2641,7 +2636,7 @@ u32 menu(u16 *screen)
mm = *(display_option->current_option);
sprintf(line_buffer, *(display_option->display_string), str[mm]);
-
+
PRINT_STRING_BG(down_screen_addr, line_buffer, color, COLOR_TRANS, 27,
38 + (display_option-> line_number)*32);
}
@@ -2718,22 +2713,9 @@ u32 menu(u16 *screen)
{
if(gui_action == CURSOR_LEFT || gui_action == CURSOR_RIGHT)
{
- ds2_setCPUclocklevel(13); // crank it up
- if(bg_screenp != NULL)
- {
- bg_screenp_color = COLOR16(43, 11, 11);
- memcpy(bg_screenp, down_screen_addr, 256*192*2);
- }
- else
- bg_screenp_color = COLOR_BG;
+ HighFrequencyCPU(); // crank it up
- draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, bg_screenp_color);
- draw_string_vcenter(down_screen_addr, 36, 75, 190, COLOR_MSSG, msg[MSG_CHANGE_LANGUAGE]);
- draw_string_vcenter(down_screen_addr, 36, 95, 190, COLOR_MSSG, msg[MSG_CHANGE_LANGUAGE_WAITING]);
- ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD);
-
- load_language_msg(LANGUAGE_PACK, emu_config.language);
- // gui_change_icon(emu_config.language); // uncomment if images change per language [Neb]
+ load_language_msg(LANGUAGE_PACK, emu_config.language);
if(first_load)
{
@@ -2742,12 +2724,11 @@ u32 menu(u16 *screen)
ds2_flipScreen(UP_SCREEN, 1);
}
- save_emu_config_file();
- ds2_setCPUclocklevel(0); // and back down
- wait_Allkey_release(0);
+ LowFrequencyCPU(); // and back down
}
}
+#ifdef ENABLE_FREE_SPACE
unsigned int freespace;
void show_card_space ()
{
@@ -2791,6 +2772,7 @@ u32 menu(u16 *screen)
PRINT_STRING_BG(down_screen_addr, line_buffer, COLOR_INACTIVE_ITEM, COLOR_TRANS, 147,
40 + (display_option->line_number)*27);
}
+#endif
char *screen_ratio_options[] = { (char*)&msg[MSG_VIDEO_ASPECT_RATIO_0],
(char*)&msg[MSG_VIDEO_ASPECT_RATIO_1],
@@ -2800,6 +2782,10 @@ u32 menu(u16 *screen)
char *frameskip_options[] = { (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_AUTOMATIC], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_0], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_1], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_2], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_3], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_4], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_5], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_6], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_7], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_8], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_9], (char*)&msg[MSG_VIDEO_FRAME_SKIPPING_10] };
+ char *cpu_frequency_options[] = { (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_0], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_1], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_2], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_3], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_4], (char*)&msg[MSG_OPTIONS_CPU_FREQUENCY_5] };
+
+ char *fluidity_options[] = { (char*)&msg[MSG_VIDEO_AUDIO_FLUIDITY_PREFER_VIDEO], (char*)&msg[MSG_VIDEO_AUDIO_FLUIDITY_PREFER_AUDIO] };
+
char *on_off_options[] = { (char*)&msg[MSG_GENERAL_OFF], (char*)&msg[MSG_GENERAL_ON] };
char *sound_seletion[] = { (char*)&msg[MSG_AUDIO_MUTED], (char*)&msg[MSG_AUDIO_ENABLED] };
@@ -2815,17 +2801,20 @@ u32 menu(u16 *screen)
{
/* 00 */ SUBMENU_OPTION(NULL, &msg[MSG_MAIN_MENU_VIDEO_AUDIO], NULL, 0),
- /* 01 */ STRING_SELECTION_OPTION(NULL, NULL, &msg[FMT_VIDEO_ASPECT_RATIO], screen_ratio_options,
+ /* 01 */ STRING_SELECTION_OPTION(NULL, NULL, &msg[FMT_VIDEO_ASPECT_RATIO], screen_ratio_options,
&game_config.graphic, 5, NULL, PASSIVE_TYPE, 1),
- /* 02 */ STRING_SELECTION_OPTION(game_fastforward, NULL, &msg[FMT_VIDEO_FAST_FORWARD], on_off_options,
+ /* 02 */ STRING_SELECTION_OPTION(game_fastforward, NULL, &msg[FMT_VIDEO_FAST_FORWARD], on_off_options,
&game_fast_forward, 2, NULL, ACTION_TYPE, 2),
-
+
/* 03 */ STRING_SELECTION_OPTION(game_disableAudio, NULL, &msg[FMT_AUDIO_SOUND], sound_seletion,
&game_enable_audio, 2, NULL, ACTION_TYPE, 3),
-
- /* 04 */ STRING_SELECTION_OPTION(game_set_frameskip, NULL, &msg[FMT_VIDEO_FRAME_SKIPPING], frameskip_options,
- &game_config.frameskip_value, 12 /* auto (0) and 0..10 (1..11) make 12 option values */, NULL, ACTION_TYPE, 4)
+
+ /* 04 */ STRING_SELECTION_OPTION(game_set_fluidity, NULL, &msg[FMT_VIDEO_AUDIO_FLUIDITY_PREFERENCE], fluidity_options,
+ &game_config.SoundSync, 2, NULL, ACTION_TYPE, 4),
+
+ /* 05 */ STRING_SELECTION_OPTION(game_set_frameskip, NULL, &msg[FMT_VIDEO_FRAME_SKIPPING], frameskip_options,
+ &game_config.frameskip_value, 12 /* auto (0) and 0..10 (1..11) make 12 option values */, NULL, ACTION_TYPE, 5)
};
MAKE_MENU(graphics, NULL, NULL, NULL, NULL, 0, 0);
@@ -2854,10 +2843,12 @@ u32 menu(u16 *screen)
{
/* 00 */ SUBMENU_OPTION(NULL, &msg[MSG_MAIN_MENU_SAVED_STATES], NULL, 0),
- /* 01 */ NUMERIC_SELECTION_ACTION_OPTION(menu_save_state, NULL, &msg[FMT_SAVED_STATE_CREATE], &savestate_index, SAVE_STATE_SLOT_NUM, NULL, 1),
+ // savestate_index is still a signed int
+ /* 01 */ NUMERIC_SELECTION_ACTION_OPTION(menu_save_state, NULL, &msg[FMT_SAVED_STATE_CREATE], (u32*) &savestate_index, SAVE_STATE_SLOT_NUM, NULL, 1),
+ // savestate_index is still a signed int
/* 02 */ NUMERIC_SELECTION_ACTION_OPTION(menu_load_state, NULL,
- &msg[FMT_SAVED_STATE_LOAD], &savestate_index, SAVE_STATE_SLOT_NUM, NULL, 2),
+ &msg[FMT_SAVED_STATE_LOAD], (u32*) &savestate_index, SAVE_STATE_SLOT_NUM, NULL, 2),
/* 03 */ SUBMENU_OPTION(&gamestate_delette_menu, &msg[MSG_SAVED_STATE_DELETE_GENERAL], NULL, 5),
};
@@ -2871,9 +2862,9 @@ u32 menu(u16 *screen)
{
/* 00 */ SUBMENU_OPTION(NULL, &msg[MSG_MAIN_MENU_CHEATS], NULL,0),
- /* 01 */ CHEAT_OPTION(cheat_option_action, cheat_option_passive,
+ /* 01 */ CHEAT_OPTION(cheat_option_action, cheat_option_passive,
((CHEATS_PER_PAGE * menu_cheat_page) + 0), 1),
- /* 02 */ CHEAT_OPTION(cheat_option_action, cheat_option_passive,
+ /* 02 */ CHEAT_OPTION(cheat_option_action, cheat_option_passive,
((CHEATS_PER_PAGE * menu_cheat_page) + 1), 2),
/* 03 */ CHEAT_OPTION(cheat_option_action, cheat_option_passive,
((CHEATS_PER_PAGE * menu_cheat_page) + 2), 3),
@@ -2940,7 +2931,7 @@ u32 menu(u16 *screen)
/*--------------------------------------------------------
Tools
--------------------------------------------------------*/
- MENU_OPTION_TYPE tools_options[] =
+ MENU_OPTION_TYPE tools_options[] =
{
/* 00 */ SUBMENU_OPTION(NULL, &msg[MSG_MAIN_MENU_TOOLS], NULL, 0),
@@ -2952,10 +2943,10 @@ u32 menu(u16 *screen)
// /* 02 */ SUBMENU_OPTION(&tools_keyremap_menu, &msg[MSG_SUB_MENU_31], NULL, 2),
-// /* 03 */ STRING_SELECTION_OPTION(time_backward_action, NULL, &msg[MSG_SUB_MENU_302], on_off_options,
+// /* 03 */ STRING_SELECTION_OPTION(time_backward_action, NULL, &msg[MSG_SUB_MENU_302], on_off_options,
// &game_config.backward, 2, NULL, ACTION_TYPE, 3),
-// /* 04 */ NUMERIC_SELECTION_ACTION_OPTION(time_period_action, time_period_passive, &msg[MSG_SUB_MENU_32],
+// /* 04 */ NUMERIC_SELECTION_ACTION_OPTION(time_period_action, time_period_passive, &msg[MSG_SUB_MENU_32],
// &game_config.backward_time, 6, NULL, 4)
};
@@ -2969,18 +2960,33 @@ u32 menu(u16 *screen)
{
/* 00 */ SUBMENU_OPTION(NULL, &msg[MSG_MAIN_MENU_OPTIONS], NULL, 0),
- //CPU speed
- /* 01 */ NUMERIC_SELECTION_OPTION(NULL, &msg[FMT_OPTIONS_CPU_FREQUENCY], &clock_speed_number, 6, NULL, 1),
+ //CPU speed (string: shows MHz)
+ /* 01 */ STRING_SELECTION_OPTION(NULL, NULL, &msg[FMT_OPTIONS_CPU_FREQUENCY], cpu_frequency_options,
+ &game_config.clock_speed_number, 6, NULL, PASSIVE_TYPE, 1),
/* 02 */ STRING_SELECTION_OPTION(language_set, NULL, &msg[FMT_OPTIONS_LANGUAGE], language_options,
&emu_config.language, sizeof(language_options) / sizeof(language_options[0]) /* number of possible languages */, NULL, ACTION_TYPE, 2),
+#ifdef ENABLE_FREE_SPACE
/* 03 */ STRING_SELECTION_OPTION(NULL, show_card_space, &msg[MSG_OPTIONS_CARD_CAPACITY], NULL,
&desert, 2, NULL, PASSIVE_TYPE | HIDEN_TYPE, 3),
+#endif
- /* 04 */ ACTION_OPTION(load_default_setting, NULL, &msg[MSG_OPTIONS_RESET], NULL, 4),
+ /* 04 */ ACTION_OPTION(load_default_setting, NULL, &msg[MSG_OPTIONS_RESET], NULL,
+#ifdef ENABLE_FREE_SPACE
+ 4
+#else
+ 3
+#endif
+ ),
- /* 05 */ ACTION_OPTION(check_gbaemu_version, NULL, &msg[MSG_OPTIONS_VERSION], NULL, 5),
+ /* 05 */ ACTION_OPTION(check_gbaemu_version, NULL, &msg[MSG_OPTIONS_VERSION], NULL,
+#ifdef ENABLE_FREE_SPACE
+ 5
+#else
+ 4
+#endif
+ ),
};
MAKE_MENU(others, others_menu_init, NULL, NULL, NULL, 1, 1);
@@ -2989,7 +2995,7 @@ u32 menu(u16 *screen)
Load_game
--------------------------------------------------------*/
MENU_TYPE latest_game_menu;
-
+
MENU_OPTION_TYPE load_game_options[] =
{
/* 00 */ SUBMENU_OPTION(NULL, &msg[MSG_LOAD_GAME_MENU_TITLE], NULL, 0),
@@ -3120,7 +3126,7 @@ u32 menu(u16 *screen)
show_icon(down_screen_addr, &ICON_MSEL, 173, 131);
}
else {
- show_icon(down_screen_addr, &ICON_NEXIT, 187, 75);
+ show_icon(down_screen_addr, &ICON_NEXIT, 187, 75);
show_icon(down_screen_addr, &ICON_MNSEL, 173, 131);
}
draw_string_vcenter(down_screen_addr, 175, 131, 75, COLOR_WHITE, line_buffer);
@@ -3315,7 +3321,7 @@ u32 menu(u16 *screen)
{
ext_pos= strrchr(emu_config.latest_file[k], '/');
if(ext_pos != NULL)
- draw_hscroll_init(down_screen_addr, 26, 40 + k*27, 200,
+ draw_hscroll_init(down_screen_addr, 26, 40 + k*27, 200,
COLOR_TRANS, COLOR_INACTIVE_ITEM, ext_pos+1);
else
break;
@@ -3373,7 +3379,7 @@ u32 menu(u16 *screen)
void latest_game_menu_end()
{
u32 k;
-
+
for(k= 0; k < 5; k++)
{
if(emu_config.latest_file[k][0] != '\0')
@@ -3393,12 +3399,12 @@ u32 menu(u16 *screen)
{
draw_hscroll_over(current_option_num-1);
ext_pos= strrchr(emu_config.latest_file[current_option_num-1], '/');
- draw_hscroll_init(down_screen_addr, 26, 40 + (current_option_num-1)*27, 200,
+ draw_hscroll_init(down_screen_addr, 26, 40 + (current_option_num-1)*27, 200,
COLOR_TRANS, COLOR_INACTIVE_ITEM, ext_pos+1);
}
current_option_num += 1;
- if(current_option_num >= latest_game_menu.num_options)
+ if(current_option_num >= latest_game_menu.num_options)
current_option_num = 0;
current_option = current_menu->options + current_option_num;
@@ -3407,7 +3413,7 @@ u32 menu(u16 *screen)
{
draw_hscroll_over(current_option_num-1);
ext_pos= strrchr(emu_config.latest_file[current_option_num-1], '/');
- draw_hscroll_init(down_screen_addr, 26, 40 + (current_option_num-1)*27, 200,
+ draw_hscroll_init(down_screen_addr, 26, 40 + (current_option_num-1)*27, 200,
COLOR_TRANS, COLOR_ACTIVE_ITEM, ext_pos+1);
}
@@ -3419,7 +3425,7 @@ u32 menu(u16 *screen)
{
draw_hscroll_over(current_option_num-1);
ext_pos= strrchr(emu_config.latest_file[current_option_num-1], '/');
- draw_hscroll_init(down_screen_addr, 26, 40 + (current_option_num-1)*27, 200,
+ draw_hscroll_init(down_screen_addr, 26, 40 + (current_option_num-1)*27, 200,
COLOR_TRANS, COLOR_INACTIVE_ITEM, ext_pos+1);
}
@@ -3432,7 +3438,7 @@ u32 menu(u16 *screen)
{
draw_hscroll_over(current_option_num-1);
ext_pos= strrchr(emu_config.latest_file[current_option_num-1], '/');
- draw_hscroll_init(down_screen_addr, 26, 40 + (current_option_num-1)*27, 200,
+ draw_hscroll_init(down_screen_addr, 26, 40 + (current_option_num-1)*27, 200,
COLOR_TRANS, COLOR_ACTIVE_ITEM, ext_pos+1);
}
@@ -3455,16 +3461,6 @@ u32 menu(u16 *screen)
{
char *ext_pos;
- draw_message(down_screen_addr, bg_screenp, 28, 31, 227, 165, 0);
- draw_string_vcenter(down_screen_addr, 36, 100, 190, COLOR_MSSG, msg[MSG_PROGRESS_LOADING_GAME]);
- ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD);
-
- if(gamepak_name[0] != 0)
- {
- S9xAutoSaveSRAM ();
- save_game_config_file();
- }
-
if(bg_screenp != NULL) {
bg_screenp_color = COLOR16(43, 11, 11);
}
@@ -3478,42 +3474,19 @@ u32 menu(u16 *screen)
ext_pos = emu_config.latest_file[current_option_num -1];
- ds2_setCPUclocklevel(13);
- int load_result = load_gamepak(ext_pos);
- ds2_setCPUclocklevel(0);
-
- if(load_result == -1) {
- first_load = 1;
- return;
- }
-
- strcpy(g_default_rom_dir, ext_pos);
- ext_pos = strrchr(g_default_rom_dir, '/');
- *ext_pos= '\0';
- strcpy(gamepak_name, ext_pos+1);
-
-
- load_game_config_file();
-// time_period_action();
-
- reorder_latest_file();
- get_savestate_filelist();
- game_fast_forward= 0;
+ LoadGameAndItsData(ext_pos);
get_newest_savestate(tmp_filename);
if(tmp_filename[0] != '\0')
{
load_state(tmp_filename);
}
-
- return_value = 1;
- repeat = 0;
}
void game_fastforward()
{
}
-
+
void reload_cheats_page()
@@ -3527,11 +3500,13 @@ u32 menu(u16 *screen)
void others_menu_init()
{
+#ifdef ENABLE_FREE_SPACE
unsigned int total, used;
//get card space info
freespace = 0;
fat_getDiskSpaceInfo("fat:", &total, &used, &freespace);
+#endif
}
void choose_menu(MENU_TYPE *new_menu)
@@ -3542,23 +3517,28 @@ u32 menu(u16 *screen)
if(NULL != current_menu) {
if(current_menu->end_function)
current_menu->end_function();
+ SaveConfigsIfNeeded();
}
current_menu = new_menu;
current_option_num= current_menu -> focus_option;
current_option = new_menu->options + current_option_num;
+ PreserveConfigs();
if(current_menu->init_function)
current_menu->init_function();
}
//----------------------------------------------------------------------------//
// Menu Start
- ds2_setCPUclocklevel(0);
- mdelay(100); // to prevent ds2_setBacklight() from crashing
- ds2_setBacklight(3);
-
-
- wait_Allkey_release(0);
+ LowFrequencyCPU();
+ if (!FirstInvocation)
+ { // assume that the backlight is already at 3 when the emulator starts
+ mdelay(100); // to prevent ds2_setBacklight() from crashing
+ ds2_setBacklight(3);
+ // also allow the user to press A for New Game right away
+ wait_Allkey_release(0);
+ }
+
bg_screenp= (u16*)malloc(256*192*2);
repeat = 1;
@@ -3566,7 +3546,8 @@ u32 menu(u16 *screen)
if(gamepak_name[0] == 0)
{
first_load = 1;
- if(CheckLoad_Arg())
+ //try auto loading games passed through argv first
+ if(strlen(argv[1]) > 0 && LoadGameAndItsData(argv[1]))
repeat = 0;
else
{
@@ -3589,7 +3570,7 @@ u32 menu(u16 *screen)
choose_menu(&main_menu);
// Menu loop
-
+
while(repeat)
{
display_option = current_menu->options;
@@ -3638,7 +3619,7 @@ u32 menu(u16 *screen)
focus_option = line_num;
}
current_menu -> focus_option = focus_option;
-
+
i = focus_option - screen_focus;
display_option += i +1;
@@ -3684,7 +3665,7 @@ u32 menu(u16 *screen)
color= COLOR_ACTIVE_ITEM;
else
color= COLOR_INACTIVE_ITEM;
-
+
PRINT_STRING_BG(down_screen_addr, line_buffer, color, COLOR_TRANS, 23, 40 + i*27);
}
}
@@ -3697,6 +3678,7 @@ u32 menu(u16 *screen)
{
case CURSOR_TOUCH:
ds2_getrawInput(&inputdata);
+ wait_Allkey_release(0);
/* Back button at the top of every menu but the main one */
if(current_menu != &main_menu && inputdata.x > 231 && inputdata.y <= 25)
{
@@ -3714,7 +3696,7 @@ u32 menu(u16 *screen)
current_option_num = (inputdata.y / 80) * 3 + (inputdata.x / 86);
current_option = current_menu->options + current_option_num;
-
+
if(current_option -> option_type & HIDEN_TYPE)
break;
else if(current_option->option_type & ACTION_TYPE)
@@ -3723,11 +3705,10 @@ u32 menu(u16 *screen)
choose_menu(current_option->sub_menu);
}
/* This is the majority case, covering all menus except save states, screen shots, and game loading */
- else if(current_menu != (main_menu.options + 1)->sub_menu
+ else if(current_menu != (main_menu.options + 1)->sub_menu
&& current_menu != ((main_menu.options +1)->sub_menu->options + 3)->sub_menu
- && current_menu != (main_menu.options +3)->sub_menu
+ && current_menu != (main_menu.options +3)->sub_menu
&& current_menu != ((main_menu.options +3)->sub_menu->options + 1)->sub_menu
- && current_menu != ((main_menu.options +3)->sub_menu->options + 2)->sub_menu
&& current_menu != (main_menu.options +6)->sub_menu
&& current_menu != ((main_menu.options +6)->sub_menu->options + 2)->sub_menu)
{
@@ -3794,9 +3775,9 @@ u32 menu(u16 *screen)
next_option_num = 3;
else
break;
-
+
struct _MENU_OPTION_TYPE *next_option = current_menu->options + next_option_num;
-
+
if(next_option_num == 1 /* write */ || next_option_num == 2 /* read */)
{
u32 current_option_val = *(next_option->current_option);
@@ -3841,7 +3822,7 @@ u32 menu(u16 *screen)
}
break;
}
-
+
gui_action = CURSOR_SELECT;
if(next_option -> option_type & HIDEN_TYPE)
break;
@@ -3868,9 +3849,9 @@ u32 menu(u16 *screen)
next_option_num = 2;
else
break;
-
+
struct _MENU_OPTION_TYPE *next_option = current_menu->options + next_option_num;
-
+
if(next_option_num == 2)
{
u32 current_option_val = *(next_option->current_option);
@@ -3908,7 +3889,7 @@ u32 menu(u16 *screen)
}
break;
}
-
+
gui_action = CURSOR_SELECT;
if(next_option -> option_type & HIDEN_TYPE)
break;
@@ -4032,16 +4013,19 @@ u32 menu(u16 *screen)
break;
case CURSOR_EXIT:
+ wait_Allkey_release(0);
break;
case CURSOR_SELECT:
+ wait_Allkey_release(0);
if(current_option->option_type & ACTION_TYPE)
current_option->action_function();
else if(current_option->option_type & SUBMENU_TYPE)
choose_menu(current_option->sub_menu);
break;
- case CURSOR_BACK:
+ case CURSOR_BACK:
+ wait_Allkey_release(0);
if(current_menu != &main_menu)
choose_menu(current_menu->options->sub_menu);
else
@@ -4057,20 +4041,11 @@ u32 menu(u16 *screen)
if (current_menu && current_menu->end_function)
current_menu->end_function();
+ SaveConfigsIfNeeded();
destroy_dynamic_cheats();
if(bg_screenp != NULL) free((void*)bg_screenp);
-
- if(gamepak_name[0] != 0)
- {
- game_config.clock_speed_number = clock_speed_number;
- reorder_latest_file();
- S9xAutoSaveSRAM ();
- save_game_config_file();
- }
- save_emu_config_file();
-
ds2_clearScreen(DOWN_SCREEN, 0);
ds2_flipScreen(DOWN_SCREEN, DOWN_SCREEN_UPDATE_METHOD);
copy_screen(up_screen_addr, (void*) screen, 0, 0, 256, 192);
@@ -4080,7 +4055,7 @@ u32 menu(u16 *screen)
mdelay(100); // to prevent ds2_setBacklight() from crashing
ds2_setBacklight(2);
- set_cpu_clock(clock_speed_number);
+ GameFrequencyCPU();
return return_value;
}
@@ -4132,6 +4107,10 @@ int load_language_msg(char *filename, u32 language)
strcpy(start, "STARTFRENCH");
strcpy(end, "ENDFRENCH");
break;
+ case GERMAN:
+ strcpy(start, "STARTGERMAN");
+ strcpy(end, "ENDGERMAN");
+ break;
}
u32 cmplen = strlen(start);
@@ -4175,7 +4154,61 @@ int load_language_msg(char *filename, u32 language)
break;
len= strlen(pt);
- memcpy(dst, pt, len);
+ // memcpy(dst, pt, len);
+
+ // Replace key definitions (*letter) with Pictochat icons
+ // while copying.
+ unsigned int curChar;
+ for (curChar = 0; curChar < len; curChar++)
+ {
+ if (pt[curChar] == '*')
+ {
+ switch (pt[curChar + 1])
+ {
+ case 'A':
+ memcpy(&dst[curChar], HOTKEY_A_DISPLAY, 2);
+ curChar++;
+ break;
+ case 'B':
+ memcpy(&dst[curChar], HOTKEY_B_DISPLAY, 2);
+ curChar++;
+ break;
+ case 'X':
+ memcpy(&dst[curChar], HOTKEY_X_DISPLAY, 2);
+ curChar++;
+ break;
+ case 'Y':
+ memcpy(&dst[curChar], HOTKEY_Y_DISPLAY, 2);
+ curChar++;
+ break;
+ case 'L':
+ memcpy(&dst[curChar], HOTKEY_L_DISPLAY, 2);
+ curChar++;
+ break;
+ case 'R':
+ memcpy(&dst[curChar], HOTKEY_R_DISPLAY, 2);
+ curChar++;
+ break;
+ case 'S':
+ memcpy(&dst[curChar], HOTKEY_START_DISPLAY, 2);
+ curChar++;
+ break;
+ case 's':
+ memcpy(&dst[curChar], HOTKEY_SELECT_DISPLAY, 2);
+ curChar++;
+ break;
+ case '\0':
+ dst[curChar] = pt[curChar];
+ break;
+ default:
+ memcpy(&dst[curChar], &pt[curChar], 2);
+ curChar++;
+ break;
+ }
+ }
+ else
+ dst[curChar] = pt[curChar];
+ }
dst += len;
//at a line return, when "\n" paded, this message not end
@@ -4198,7 +4231,7 @@ int load_language_msg(char *filename, u32 language)
else//a message end
{
if(*(dst-2) == 0x0D)
- dst -= 1;
+ dst -= 1;
*(dst-1) = '\0';
msg[++loop] = dst;
}
@@ -4235,9 +4268,9 @@ u32 load_font()
void init_game_config(void)
{
game_config.clock_speed_number = 5; // 396 MHz by default
- clock_speed_number = 5;
game_config.graphic = 3; // By default, have a good-looking aspect ratio
game_config.frameskip_value = 0; // Automatic frame skipping
+ game_config.SoundSync = 0; // Prefer fluid images by default
game_config.backward = 0; //time backward disable
game_config.backward_time = 2; //time backward granularity 1s
@@ -4290,8 +4323,8 @@ void load_game_config_file(void)
{
fread(&game_config, 1, sizeof(GAME_CONFIG), fp);
- clock_speed_number = game_config.clock_speed_number;
- Settings.SkipFrames = (game_config.frameskip_value == 0 ? AUTO_FRAMERATE : game_config.frameskip_value - 1 /* 1 -> 0 and so on */);
+ game_set_frameskip();
+ game_set_fluidity();
}
fclose(fp);
@@ -4322,6 +4355,10 @@ int load_emu_config_file(void)
fclose(fp);
return 0;
}
+ else
+ {
+ fclose(fp);
+ }
}
//have no confiure file, set default
@@ -4342,7 +4379,7 @@ int save_game_config_file(void)
sprintf(game_config_filename, "%s/%s", DEFAULT_CFG_DIR, gamepak_name);
pt = strrchr(game_config_filename, '.');
- if(NULL == pt)
+ if(NULL == pt)
return -1;
*pt = '\0';
@@ -4418,7 +4455,7 @@ void reorder_latest_file(void)
else
break;
}
-
+
strcpy(emu_config.latest_file[i-1], full_file);
}
return ;
@@ -4584,7 +4621,7 @@ void get_newest_savestate(char *name_buffer)
get_savestate_filename(latest_save, name_buffer);
}
-static void get_timestamp_string(char *buffer, u16 msg_id, u16 year, u16 mon,
+static void get_timestamp_string(char *buffer, u16 msg_id, u16 year, u16 mon,
u16 day, u16 wday, u16 hour, u16 min, u16 sec, u32 msec)
{
char *weekday_strings[] =
@@ -4592,7 +4629,7 @@ static void get_timestamp_string(char *buffer, u16 msg_id, u16 year, u16 mon,
"SUN", "MON", "TUE", "WED", "TUR", "FRI", "SAT"
};
- sprintf(buffer, "%s %02d/%02d/%04d %02d:%02d:%02d", weekday_strings[wday],
+ sprintf(buffer, "%s %02d/%02d/%04d %02d:%02d:%02d", weekday_strings[wday],
day, mon, year, hour, min, sec);
}
@@ -4617,7 +4654,7 @@ static u32 save_ss_bmp(u16 *image)
change_ext(gamepak_name, ss_filename, "_");
ds2_getTime(&current_time);
- sprintf(save_ss_path, "%s/%s%02d%02d%02d%02d%02d.bmp", DEFAULT_SS_DIR, ss_filename,
+ sprintf(save_ss_path, "%s/%s%02d%02d%02d%02d%02d.bmp", DEFAULT_SS_DIR, ss_filename,
current_time.month, current_time.day, current_time.hours, current_time.minutes, current_time.seconds);
for(y = 0; y < 192; y++)
@@ -4652,7 +4689,7 @@ void quit(void)
__asm__ __volatile__("or %0, $0, $ra"
: "=r" (reg_ra)
:);
-
+
dbg_printf("return address= %08x\n", reg_ra);
*/
@@ -4678,11 +4715,44 @@ u32 file_length(FILE* file)
/*
* GUI Initialize
*/
+static bool Get_Args(char *file, char **filebuf){
+ FILE* dat = fat_fopen(file, "rb");
+ if(dat){
+ int i = 0;
+ while(!fat_feof (dat)){
+ fat_fgets(filebuf[i], 512, dat);
+ int len = strlen(filebuf[i]);
+ if(filebuf[i][len - 1] == '\n')
+ filebuf[i][len - 1] = '\0';
+ i++;
+ }
+
+ fat_fclose(dat);
+ fat_remove(file);
+ return i;
+ }
+ return 0;
+}
+
+int CheckLoad_Arg(){
+ argv[0][0] = '\0'; // Initialise the first byte to be a NULL in case
+ argv[1][0] = '\0'; // there are no arguments to avoid uninit. memory
+ char *argarray[2];
+ argarray[0] = argv[0];
+ argarray[1] = argv[1];
+
+ if(!Get_Args("/plgargs.dat", argarray))
+ return 0;
+
+ fat_remove("plgargs.dat");
+ return 1;
+}
+
void gui_init(u32 lang_id)
{
int flag;
- ds2_setCPUclocklevel(13); // Crank it up. When the menu starts, -> 0.
+ HighFrequencyCPU(); // Crank it up. When the menu starts, -> 0.
// Start with no saved state existing, as no game is loaded yet.
int i;
@@ -4695,7 +4765,17 @@ void gui_init(u32 lang_id)
//Find the "CATSFC" system directory
DIR *current_dir;
- strcpy(main_path, "fat:/CATSFC");
+ if(CheckLoad_Arg()){
+ //copy new folder location
+ strcpy(main_path, "fat:");
+ strcat(main_path, argv[0]);
+ //strip off the binary name
+ char *endStr = strrchr(main_path, '/');
+ *endStr = '\0';
+ }
+ else
+ strcpy(main_path, "fat:/CATSFC");
+
current_dir = opendir(main_path);
if(current_dir)
closedir(current_dir);
diff --git a/source/nds/gui.h b/source/nds/gui.h
index 87c14e4..290a927 100644
--- a/source/nds/gui.h
+++ b/source/nds/gui.h
@@ -59,7 +59,20 @@ struct _GAME_CONFIG
u32 HotkeyReturnToMenu;
u32 HotkeyTemporaryFastForward;
u32 HotkeyToggleSound;
- u32 Reserved2[45];
+ u32 SoundSync;
+ /*
+ * PreviouslyUsed_20130206_1 was for a second meaning of
+ * frameskip_value that is now dropped.
+ * THIS VALUE IS NOT GUARANTEED TO BE RESERVED AND SET TO 0.
+ */
+ u32 PreviouslyUsed_20130206_1;
+ /*
+ * PreviouslyUsed_20130206_2 was for a second meaning of
+ * clock_speed_number that is now dropped.
+ * THIS VALUE IS NOT GUARANTEED TO BE RESERVED AND SET TO 0.
+ */
+ u32 PreviouslyUsed_20130206_2;
+ u32 Reserved2[42];
};
typedef enum
@@ -124,10 +137,13 @@ extern GAME_CONFIG game_config;
/******************************************************************************
******************************************************************************/
extern void gui_init(u32 lang_id);
-extern u32 menu(u16 *original_screen);
+extern u32 menu(u16 *original_screen, bool8 FirstInvocation);
extern void game_disableAudio();
extern void game_set_frameskip();
-extern void set_cpu_clock(u32 num);
+extern void game_set_fluidity();
+extern void LowFrequencyCPU();
+extern void HighFrequencyCPU();
+extern void GameFrequencyCPU();
extern int load_language_msg(char *filename, u32 language);
#ifdef __cplusplus
diff --git a/source/nds/message.h b/source/nds/message.h
index 0aff8d9..538bc3b 100644
--- a/source/nds/message.h
+++ b/source/nds/message.h
@@ -31,6 +31,9 @@ enum MSG
MSG_MAIN_MENU_TOOLS,
MSG_MAIN_MENU_OPTIONS,
MSG_MAIN_MENU_EXIT,
+ FMT_VIDEO_AUDIO_FLUIDITY_PREFERENCE,
+ MSG_VIDEO_AUDIO_FLUIDITY_PREFER_VIDEO,
+ MSG_VIDEO_AUDIO_FLUIDITY_PREFER_AUDIO,
FMT_VIDEO_ASPECT_RATIO,
FMT_VIDEO_FAST_FORWARD,
FMT_VIDEO_FRAME_SKIPPING,
@@ -41,21 +44,27 @@ enum MSG
FMT_CHEAT_PAGE,
MSG_CHEAT_LOAD_FROM_FILE,
MSG_TOOLS_SCREENSHOT_GENERAL,
- MSG_TOOLS_GLOBAL_HOTKEY_GENERAL, // currently unused
- MSG_TOOLS_GAME_HOTKEY_GENERAL, // currently unused
+ MSG_TOOLS_GLOBAL_HOTKEY_GENERAL,
+ MSG_TOOLS_GAME_HOTKEY_GENERAL,
FMT_OPTIONS_LANGUAGE,
FMT_OPTIONS_CPU_FREQUENCY,
- MSG_OPTIONS_CARD_CAPACITY,
+ MSG_OPTIONS_CPU_FREQUENCY_0,
+ MSG_OPTIONS_CPU_FREQUENCY_1,
+ MSG_OPTIONS_CPU_FREQUENCY_2,
+ MSG_OPTIONS_CPU_FREQUENCY_3,
+ MSG_OPTIONS_CPU_FREQUENCY_4,
+ MSG_OPTIONS_CPU_FREQUENCY_5,
+ MSG_OPTIONS_CARD_CAPACITY /* unused if !defined(ENABLE_FREE_SPACE) */,
MSG_OPTIONS_RESET,
MSG_OPTIONS_VERSION,
MSG_SCREENSHOT_CREATE,
MSG_SCREENSHOT_BROWSE,
- MSG_HOTKEY_MAIN_MENU, // currently unused
- MSG_HOTKEY_TEMPORARY_FAST_FORWARD, // currently unused
- MSG_HOTKEY_SOUND_TOGGLE, // currently unused
- MSG_PROGRESS_HOTKEY_WAITING_FOR_KEYS, // currently unused
- MSG_HOTKEY_DELETE_WITH_A, // currently unused
- MSG_HOTKEY_CANCEL_WITH_B, // currently unused
+ MSG_HOTKEY_MAIN_MENU,
+ MSG_HOTKEY_TEMPORARY_FAST_FORWARD,
+ MSG_HOTKEY_SOUND_TOGGLE,
+ MSG_PROGRESS_HOTKEY_WAITING_FOR_KEYS,
+ MSG_HOTKEY_DELETE_WITH_A,
+ MSG_HOTKEY_CANCEL_WITH_B,
MSG_LOAD_GAME_RECENTLY_PLAYED,
MSG_LOAD_GAME_FROM_CARD,
MSG_LOAD_GAME_MENU_TITLE,
@@ -112,9 +121,6 @@ enum MSG
MSG_PROGRESS_SCREENSHOT_CREATION_SUCCEEDED,
MSG_PROGRESS_SCREENSHOT_CREATION_FAILED,
- MSG_CHANGE_LANGUAGE,
- MSG_CHANGE_LANGUAGE_WAITING,
-
MSG_NO_SLIDE,
MSG_PLAYING_SLIDE,
MSG_PAUSE_SLIDE,
@@ -139,13 +145,14 @@ enum MSG
enum LANGUAGE {
ENGLISH,
CHINESE_SIMPLIFIED,
- FRENCH
+ FRENCH,
+ GERMAN
};
-extern char* lang[3]; // Allocated in gui.c, needs to match the languages ^
+extern char* lang[4]; // Allocated in gui.c, needs to match the languages ^
char *msg[MSG_END+1];
-char msg_data[16 * 1024];
+char msg_data[32 * 1024];
#endif //__MESSAGE_H__
diff --git a/source/ppu.cpp b/source/ppu.cpp
index ad937c4..179838d 100644
--- a/source/ppu.cpp
+++ b/source/ppu.cpp
@@ -2853,43 +2853,10 @@ void S9xUpdateJoypads ()
{
uint32 i;
-#ifdef SYNC_JOYPAD_AT_HBLANK
- uint32 j, k, KeyValue;
- bool8 StartedPressed;
-
- // For each joypad
- for (i = 0; i < 5; i++)
- {
- IPPU.Joypads [i] = 0;
- // Sync each key
- for (k = 1; k != 0; k <<= 1)
- {
- KeyValue = IPPU.JoypadsAtHBlanks[i][0] & k;
- StartedPressed = KeyValue != 0;
- // from each line.
- // If, initially, the key is NOT pressed, one line of it being
- // pressed means that the key MUST be pressed.
- // Otherwise, the key MUST be depressed if it starts pressed.
- for (j = 1; j < (Settings.PAL ? SNES_MAX_PAL_VCOUNTER : SNES_MAX_NTSC_VCOUNTER); j++)
- {
- if ((StartedPressed) && ((IPPU.JoypadsAtHBlanks[i][j] & k) == 0)) {
- KeyValue = 0;
- break;
- }
- else if ((!StartedPressed) && ((IPPU.JoypadsAtHBlanks[i][j] & k) != 0)) {
- KeyValue = k;
- break;
- }
- }
- IPPU.Joypads [i] |= KeyValue;
- }
- }
-#else
for (i = 0; i < 5; i++)
{
IPPU.Joypads [i] = S9xReadJoypad (i);
}
-#endif
// S9xMovieUpdate();
diff --git a/source/ppu.h b/source/ppu.h
index 1d3c7b7..8f8b8e7 100644
--- a/source/ppu.h
+++ b/source/ppu.h
@@ -152,9 +152,6 @@ struct InternalPPU {
int CurrentLine;
int Controller;
uint32 Joypads[5];
-#ifdef SYNC_JOYPAD_AT_HBLANK
- uint32 JoypadsAtHBlanks[5][SNES_MAX_PAL_VCOUNTER];
-#endif
uint32 SuperScope;
uint32 Mouse[2];
int PrevMouseX[2];
diff --git a/source/sa1.cpp b/source/sa1.cpp
index 4dbf9b0..addeed7 100644
--- a/source/sa1.cpp
+++ b/source/sa1.cpp
@@ -742,7 +742,8 @@ void S9xSetSA1 (uint8 byte, uint32 address)
if ((Memory.FillRAM [0x2230] & 0xb0) == 0xa0)
{
// Char conversion 2 DMA enabled
- memmove (&Memory.ROM [CMemory::MAX_ROM_SIZE - 0x10000] + SA1.in_char_dma * 16,
+ // memmove converted: Same malloc but constant non-overlapping addresses [Neb]
+ memcpy (&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;
if ((SA1.in_char_dma & 3) == 0)
@@ -895,6 +896,7 @@ static void S9xSA1DMA ()
len &= 0x3ff;
d = &Memory.FillRAM [0x3000] + dst;
}
+ // memmove required: Can overlap arbitrarily [Neb]
memmove (d, s, len);
Memory.FillRAM [0x2301] |= 0x20;
diff --git a/source/snaporig.cpp b/source/snaporig.cpp
index ac2045c..62674f2 100644
--- a/source/snaporig.cpp
+++ b/source/snaporig.cpp
@@ -313,12 +313,14 @@ static int ReadOrigSnapshot (STREAM snap)
PPU.OBJSizeSelect = OrigPPU.OBJSizeSelect;
PPU.OBJNameBase = OrigPPU.OBJNameBase;
PPU.OAMReadFlip = OrigPPU.OAMReadFlip;
- memmove (PPU.OAMData, OrigPPU.OAMData, sizeof (PPU.OAMData));
+ // memmove converted: Different data segments [Neb]
+ memcpy (PPU.OAMData, OrigPPU.OAMData, sizeof (PPU.OAMData));
PPU.VTimerEnabled = OrigPPU.VTimerEnabled;
PPU.HTimerEnabled = OrigPPU.HTimerEnabled;
PPU.HTimerPosition = OrigPPU.HTimerPosition;
PPU.Mosaic = OrigPPU.Mosaic;
- memmove (PPU.BGMosaic, OrigPPU.BGMosaic, sizeof (PPU.BGMosaic));
+ // memmove converted: Different data segments [Neb]
+ memcpy (PPU.BGMosaic, OrigPPU.BGMosaic, sizeof (PPU.BGMosaic));
PPU.Mode7HFlip = OrigPPU.Mode7HFlip;
PPU.Mode7VFlip = OrigPPU.Mode7VFlip;
PPU.Mode7Repeat = OrigPPU.Mode7Repeat;
diff --git a/source/snapshot.cpp b/source/snapshot.cpp
index ad9b131..c414dc2 100644
--- a/source/snapshot.cpp
+++ b/source/snapshot.cpp
@@ -1036,7 +1036,8 @@ void FreezeStruct (STREAM stream, char *name, void *base, FreezeData *fields,
}
break;
case uint8_ARRAY_V:
- memmove (ptr, (uint8 *) base + fields [i].offset, fields [i].size);
+ // memmove converted: Different mallocs [Neb]
+ memcpy (ptr, (uint8 *) base + fields [i].offset, fields [i].size);
ptr += fields [i].size;
break;
case uint16_ARRAY_V:
@@ -1139,7 +1140,8 @@ int UnfreezeStruct (STREAM stream, char *name, void *base, FreezeData *fields,
}
break;
case uint8_ARRAY_V:
- memmove ((uint8 *) base + fields [i].offset, ptr, fields [i].size);
+ // memmove converted: Different mallocs [Neb]
+ memcpy ((uint8 *) base + fields [i].offset, ptr, fields [i].size);
ptr += fields [i].size;
break;
case uint16_ARRAY_V:
@@ -1264,6 +1266,7 @@ void UnfreezeStructFromCopy (void *base, FreezeData *fields, int num_fields, uin
}
break;
case uint8_ARRAY_V:
+ // memmove required: Source could point within dest [Neb]
memmove ((uint8 *) base + fields [i].offset, ptr, fields [i].size);
ptr += fields [i].size;
break;
@@ -1581,7 +1584,8 @@ bool8 S9xUnfreezeZSNES (const char *filename)
APU.Timer [1] = t [45];
APU.Timer [2] = t [46];
- memmove (APU.ExtraRAM, &t [48], 64);
+ // memmove converted: Different mallocs [Neb]
+ memcpy (APU.ExtraRAM, &t [48], 64);
// Internal ZSNES sound DSP state
fread (t, 1, 1068, fs);
@@ -1657,7 +1661,9 @@ bool8 S9xUnfreezeZSNES (const char *filename)
SA1.Registers.PC = READ_DWORD (&t [636]);
SA1.Registers.P.W = t [620] | (t [624] << 8);
- memmove (&Memory.FillRAM [0x3000], t + 692, 2 * 1024);
+ // memmove converted: Different mallocs [Neb]
+ // DS2 DMA notes: This code path is not used [Neb]
+ memcpy (&Memory.FillRAM [0x3000], t + 692, 2 * 1024);
fread (::SRAM, 1, 64 * 1024, fs);
fseek (fs, 64 * 1024, SEEK_CUR);
diff --git a/source/soundux.cpp b/source/soundux.cpp
index fda2e25..d8ce223 100644
--- a/source/soundux.cpp
+++ b/source/soundux.cpp
@@ -131,18 +131,20 @@
#include "memmap.h"
#include "cpuexec.h"
-extern int Echo [24000];
-extern int DummyEchoBuffer [SOUND_BUFFER_SIZE];
-extern int MixBuffer [SOUND_BUFFER_SIZE];
-extern int EchoBuffer [SOUND_BUFFER_SIZE];
-extern int FilterTaps [8];
+extern int32 Echo [24000];
+extern int32 DummyEchoBuffer [SOUND_BUFFER_SIZE];
+extern int32 MixBuffer [SOUND_BUFFER_SIZE];
+extern int32 EchoBuffer [SOUND_BUFFER_SIZE];
+extern int32 FilterTaps [8];
+static uint8 FilterTapDefinitionBitfield;
+// In the above, bit I is set if FilterTaps[I] is non-zero.
extern unsigned long Z;
-extern int Loop [16];
+extern int32 Loop [16];
extern long FilterValues[4][2];
-extern int NoiseFreq [32];
+extern int32 NoiseFreq [32];
-static int noise_gen;
+static int32 noise_gen;
#undef ABS
#define ABS(a) ((a) < 0 ? -(a) : (a))
@@ -415,15 +417,11 @@ void S9xFixSoundAfterSnapshotLoad ()
void S9xSetFilterCoefficient (int tap, int value)
{
- FilterTaps [tap & 7] = value;
- SoundData.no_filter = (FilterTaps [0] == 127 || FilterTaps [0] == 0) &&
- FilterTaps [1] == 0 &&
- FilterTaps [2] == 0 &&
- FilterTaps [3] == 0 &&
- FilterTaps [4] == 0 &&
- FilterTaps [5] == 0 &&
- FilterTaps [6] == 0 &&
- FilterTaps [7] == 0;
+ FilterTaps [tap & 7] = value;
+ if (value == 0 || (tap == 0 && value == 127))
+ FilterTapDefinitionBitfield &= ~(1 << (tap & 7));
+ else
+ FilterTapDefinitionBitfield |= 1 << (tap & 7);
}
void S9xSetSoundADSR (int channel, int attack_rate, int decay_rate,
@@ -997,10 +995,9 @@ void DecodeBlock (Channel *ch)
ch->block_pointer += 9;
}
-
static inline void MixStereo (int sample_count)
{
- static int wave[SOUND_BUFFER_SIZE];
+ static int32 wave[SOUND_BUFFER_SIZE];
int pitch_mod = SoundData.pitch_mod & ~APU.DSP[APU_NON];
@@ -1342,6 +1339,15 @@ static inline void MixMono (int sample_count)
for (uint32 I = 0; I < (uint32) sample_count; I++)
{
+#ifdef ACCUMULATE_JOYPAD
+/*
+ * This call allows NDSSFC to synchronise the DS controller more often.
+ * If porting a later version of Snes9x into NDSSFC, it is essential to
+ * preserve it.
+ */
+ if ((I & 0x7F) == 0x7F)
+ NDSSFCAccumulateJoypad ();
+#endif
unsigned long freq = freq0;
if (mod)
@@ -1608,9 +1614,9 @@ void S9xMixSamples (uint8 *buffer, int sample_count)
if (!so.mute_sound)
{
- memset (MixBuffer, 0, sample_count * sizeof (MixBuffer [0]));
if (SoundData.echo_enable)
memset (EchoBuffer, 0, sample_count * sizeof (EchoBuffer [0]));
+ memset (MixBuffer, 0, sample_count * sizeof (MixBuffer [0]));
#ifndef FOREVER_STEREO
if (so.stereo)
@@ -1643,7 +1649,7 @@ void S9xMixSamples (uint8 *buffer, int sample_count)
{
#endif
// 16-bit stereo sound with echo enabled ...
- if (SoundData.no_filter)
+ if (FilterTapDefinitionBitfield == 0)
{
// ... but no filter defined.
for (J = 0; J < sample_count; J++)
@@ -1673,13 +1679,13 @@ void S9xMixSamples (uint8 *buffer, int sample_count)
Loop [(Z - 0) & 15] = E;
E = E * FilterTaps [0];
- E += Loop [(Z - 2) & 15] * FilterTaps [1];
- E += Loop [(Z - 4) & 15] * FilterTaps [2];
- E += Loop [(Z - 6) & 15] * FilterTaps [3];
- E += Loop [(Z - 8) & 15] * FilterTaps [4];
- E += Loop [(Z - 10) & 15] * FilterTaps [5];
- E += Loop [(Z - 12) & 15] * FilterTaps [6];
- E += Loop [(Z - 14) & 15] * FilterTaps [7];
+ if (FilterTapDefinitionBitfield & 0x02) E += Loop [(Z - 2) & 15] * FilterTaps [1];
+ if (FilterTapDefinitionBitfield & 0x04) E += Loop [(Z - 4) & 15] * FilterTaps [2];
+ if (FilterTapDefinitionBitfield & 0x08) E += Loop [(Z - 6) & 15] * FilterTaps [3];
+ if (FilterTapDefinitionBitfield & 0x10) E += Loop [(Z - 8) & 15] * FilterTaps [4];
+ if (FilterTapDefinitionBitfield & 0x20) E += Loop [(Z - 10) & 15] * FilterTaps [5];
+ if (FilterTapDefinitionBitfield & 0x40) E += Loop [(Z - 12) & 15] * FilterTaps [6];
+ if (FilterTapDefinitionBitfield & 0x80) E += Loop [(Z - 14) & 15] * FilterTaps [7];
E /= 128;
Z++;
@@ -1702,7 +1708,7 @@ void S9xMixSamples (uint8 *buffer, int sample_count)
else
{
// 16-bit mono sound with echo enabled...
- if (SoundData.no_filter)
+ if (FilterTapDefinitionBitfield == 0)
{
// ... no filter defined
for (J = 0; J < sample_count; J++)
@@ -1731,13 +1737,13 @@ void S9xMixSamples (uint8 *buffer, int sample_count)
Loop [(Z - 0) & 7] = E;
E = E * FilterTaps [0];
- E += Loop [(Z - 1) & 7] * FilterTaps [1];
- E += Loop [(Z - 2) & 7] * FilterTaps [2];
- E += Loop [(Z - 3) & 7] * FilterTaps [3];
- E += Loop [(Z - 4) & 7] * FilterTaps [4];
- E += Loop [(Z - 5) & 7] * FilterTaps [5];
- E += Loop [(Z - 6) & 7] * FilterTaps [6];
- E += Loop [(Z - 7) & 7] * FilterTaps [7];
+ if (FilterTapDefinitionBitfield & 0x02) E += Loop [(Z - 1) & 7] * FilterTaps [1];
+ if (FilterTapDefinitionBitfield & 0x04) E += Loop [(Z - 2) & 7] * FilterTaps [2];
+ if (FilterTapDefinitionBitfield & 0x08) E += Loop [(Z - 3) & 7] * FilterTaps [3];
+ if (FilterTapDefinitionBitfield & 0x10) E += Loop [(Z - 4) & 7] * FilterTaps [4];
+ if (FilterTapDefinitionBitfield & 0x20) E += Loop [(Z - 5) & 7] * FilterTaps [5];
+ if (FilterTapDefinitionBitfield & 0x40) E += Loop [(Z - 6) & 7] * FilterTaps [6];
+ if (FilterTapDefinitionBitfield & 0x80) E += Loop [(Z - 7) & 7] * FilterTaps [7];
E /= 128;
Z++;
@@ -1797,7 +1803,7 @@ void S9xMixSamples (uint8 *buffer, int sample_count)
if (so.stereo)
{
// 8-bit stereo sound with echo enabled...
- if (SoundData.no_filter)
+ if (FilterTapDefinitionBitfield == 0)
{
// ... but no filter
for (J = 0; J < sample_count; J++)
@@ -1826,13 +1832,13 @@ void S9xMixSamples (uint8 *buffer, int sample_count)
Loop [(Z - 0) & 15] = E;
E = E * FilterTaps [0];
- E += Loop [(Z - 2) & 15] * FilterTaps [1];
- E += Loop [(Z - 4) & 15] * FilterTaps [2];
- E += Loop [(Z - 6) & 15] * FilterTaps [3];
- E += Loop [(Z - 8) & 15] * FilterTaps [4];
- E += Loop [(Z - 10) & 15] * FilterTaps [5];
- E += Loop [(Z - 12) & 15] * FilterTaps [6];
- E += Loop [(Z - 14) & 15] * FilterTaps [7];
+ if (FilterTapDefinitionBitfield & 0x02) E += Loop [(Z - 2) & 15] * FilterTaps [1];
+ if (FilterTapDefinitionBitfield & 0x04) E += Loop [(Z - 4) & 15] * FilterTaps [2];
+ if (FilterTapDefinitionBitfield & 0x08) E += Loop [(Z - 6) & 15] * FilterTaps [3];
+ if (FilterTapDefinitionBitfield & 0x10) E += Loop [(Z - 8) & 15] * FilterTaps [4];
+ if (FilterTapDefinitionBitfield & 0x20) E += Loop [(Z - 10) & 15] * FilterTaps [5];
+ if (FilterTapDefinitionBitfield & 0x40) E += Loop [(Z - 12) & 15] * FilterTaps [6];
+ if (FilterTapDefinitionBitfield & 0x80) E += Loop [(Z - 14) & 15] * FilterTaps [7];
E /= 128;
Z++;
@@ -1853,7 +1859,7 @@ void S9xMixSamples (uint8 *buffer, int sample_count)
else
{
// 8-bit mono sound with echo enabled...
- if (SoundData.no_filter)
+ if (FilterTapDefinitionBitfield == 0)
{
// ... but no filter.
for (J = 0; J < sample_count; J++)
@@ -1881,13 +1887,13 @@ void S9xMixSamples (uint8 *buffer, int sample_count)
Loop [(Z - 0) & 7] = E;
E = E * FilterTaps [0];
- E += Loop [(Z - 1) & 7] * FilterTaps [1];
- E += Loop [(Z - 2) & 7] * FilterTaps [2];
- E += Loop [(Z - 3) & 7] * FilterTaps [3];
- E += Loop [(Z - 4) & 7] * FilterTaps [4];
- E += Loop [(Z - 5) & 7] * FilterTaps [5];
- E += Loop [(Z - 6) & 7] * FilterTaps [6];
- E += Loop [(Z - 7) & 7] * FilterTaps [7];
+ if (FilterTapDefinitionBitfield & 0x02) E += Loop [(Z - 1) & 7] * FilterTaps [1];
+ if (FilterTapDefinitionBitfield & 0x04) E += Loop [(Z - 2) & 7] * FilterTaps [2];
+ if (FilterTapDefinitionBitfield & 0x08) E += Loop [(Z - 3) & 7] * FilterTaps [3];
+ if (FilterTapDefinitionBitfield & 0x10) E += Loop [(Z - 4) & 7] * FilterTaps [4];
+ if (FilterTapDefinitionBitfield & 0x20) E += Loop [(Z - 5) & 7] * FilterTaps [5];
+ if (FilterTapDefinitionBitfield & 0x40) E += Loop [(Z - 6) & 7] * FilterTaps [6];
+ if (FilterTapDefinitionBitfield & 0x80) E += Loop [(Z - 7) & 7] * FilterTaps [7];
E /= 128;
Z++;
@@ -1962,6 +1968,7 @@ void S9xResetSound (bool8 full)
FilterTaps [5] = 0;
FilterTaps [6] = 0;
FilterTaps [7] = 0;
+ FilterTapDefinitionBitfield = 0;
so.mute_sound = TRUE;
noise_gen = 1;
so.sound_switch = 255;
@@ -2000,7 +2007,6 @@ void S9xResetSound (bool8 full)
so.err_rate = (uint32) (FIXED_POINT * SNES_SCANLINE_TIME / (1.0 / so.playback_rate));
else
so.err_rate = 0;
- SoundData.no_filter = TRUE;
}
void S9xSetPlaybackRate (uint32 playback_rate)
diff --git a/source/soundux.h b/source/soundux.h
index 224d24a..b57e945 100644
--- a/source/soundux.h
+++ b/source/soundux.h
@@ -212,7 +212,7 @@ typedef struct
// Just incase they are needed in the future, for snapshot compatibility.
uint32 dummy [3];
Channel channels [NUM_CHANNELS];
- bool8 no_filter;
+ // bool8 no_filter;
int master_volume [2]; /* range is -128 .. 127 */
int echo_volume [2]; /* range is -128 .. 127 */
int noise_hertz;
diff --git a/source/srtc.cpp b/source/srtc.cpp
index 48add97..0e6f30e 100644
--- a/source/srtc.cpp
+++ b/source/srtc.cpp
@@ -525,12 +525,14 @@ void S9xSRTCPreSaveState ()
SRAM [s + 0] = rtc.needs_init;
SRAM [s + 1] = rtc.count_enable;
- memmove (&SRAM [s + 2], rtc.data, MAX_RTC_INDEX + 1);
+ // memmove converted: Different mallocs [Neb]
+ memcpy (&SRAM [s + 2], rtc.data, MAX_RTC_INDEX + 1);
SRAM [s + 3 + MAX_RTC_INDEX] = rtc.index;
SRAM [s + 4 + MAX_RTC_INDEX] = rtc.mode;
#ifdef LSB_FIRST
- memmove (&SRAM [s + 5 + MAX_RTC_INDEX], &rtc.system_timestamp, 8);
+ // memmove converted: Different mallocs [Neb]
+ memcpy (&SRAM [s + 5 + MAX_RTC_INDEX], &rtc.system_timestamp, 8);
#else
SRAM [s + 5 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 0);
SRAM [s + 6 + MAX_RTC_INDEX] = (uint8) (rtc.system_timestamp >> 8);
@@ -555,12 +557,14 @@ void S9xSRTCPostLoadState ()
rtc.needs_init = SRAM [s + 0];
rtc.count_enable = SRAM [s + 1];
- memmove (rtc.data, &SRAM [s + 2], MAX_RTC_INDEX + 1);
+ // memmove converted: Different mallocs [Neb]
+ memcpy (rtc.data, &SRAM [s + 2], MAX_RTC_INDEX + 1);
rtc.index = SRAM [s + 3 + MAX_RTC_INDEX];
rtc.mode = SRAM [s + 4 + MAX_RTC_INDEX];
#ifdef LSB_FIRST
- memmove (&rtc.system_timestamp, &SRAM [s + 5 + MAX_RTC_INDEX], 8);
+ // memmove converted: Different mallocs [Neb]
+ memcpy (&rtc.system_timestamp, &SRAM [s + 5 + MAX_RTC_INDEX], 8);
#else
rtc.system_timestamp |= (SRAM [s + 5 + MAX_RTC_INDEX] << 0);
rtc.system_timestamp |= (SRAM [s + 6 + MAX_RTC_INDEX] << 8);
diff --git a/source/tile.cpp b/source/tile.cpp
index 653a6d7..87d1fac 100644
--- a/source/tile.cpp
+++ b/source/tile.cpp
@@ -589,71 +589,8 @@ void DrawTile16 (uint32 Tile, uint32 Offset, uint32 StartLine,
{
TILE_PREAMBLE
register uint8 *bp;
- uint8 Pixel;
- uint16 *Screen = (uint16 *) GFX.S + Offset;
- uint8 *Depth = GFX.DB + Offset;
- switch (Tile & (H_FLIP | V_FLIP))
- {
- case 0:
- bp = pCache + StartLine;
- for (l = LineCount; l != 0; l--, bp += 8, Screen += GFX.PPL, Depth += GFX.PPL)
- {
- for (uint8 N = 0; N < 8; N++)
- {
- if (GFX.Z1 > Depth [N] && (Pixel = bp[N]))
- {
- Screen [N] = ScreenColors [Pixel];
- Depth [N] = GFX.Z2;
- }
- }
- }
- break;
- case H_FLIP:
- bp = pCache + StartLine;
- for (l = LineCount; l != 0; l--, bp += 8, Screen += GFX.PPL, Depth += GFX.PPL)
- {
- for (uint8 N = 0; N < 8; N++)
- {
- if (GFX.Z1 > Depth [N] && (Pixel = bp[7 - N]))
- {
- Screen [N] = ScreenColors [Pixel];
- Depth [N] = GFX.Z2;
- }
- }
- }
- break;
- case H_FLIP | V_FLIP:
- bp = pCache + 56 - StartLine;
- for (l = LineCount; l != 0; l--, bp -= 8, Screen += GFX.PPL, Depth += GFX.PPL)
- {
- for (uint8 N = 0; N < 8; N++)
- {
- if (GFX.Z1 > Depth [N] && (Pixel = bp[7 - N]))
- {
- Screen [N] = ScreenColors [Pixel];
- Depth [N] = GFX.Z2;
- }
- }
- }
- break;
- case V_FLIP:
- bp = pCache + 56 - StartLine;
- for (l = LineCount; l != 0; l--, bp -= 8, Screen += GFX.PPL, Depth += GFX.PPL)
- {
- for (uint8 N = 0; N < 8; N++)
- {
- if (GFX.Z1 > Depth [N] && (Pixel = bp[N]))
- {
- Screen [N] = ScreenColors [Pixel];
- Depth [N] = GFX.Z2;
- }
- }
- }
- break;
- default:
- break;
- }
+ RENDER_TILE(WRITE_4PIXELS16, WRITE_4PIXELS16_FLIPPED, 4)
}
void DrawClippedTile16 (uint32 Tile, uint32 Offset,