diff options
author | Nebuleon Fumika | 2013-02-08 05:50:22 -0500 |
---|---|---|
committer | Nebuleon Fumika | 2013-02-08 05:50:22 -0500 |
commit | 927d456306672110870eb3386742c1c1ef8eb4f6 (patch) | |
tree | 509da9ac1727570b02572068aefb9cdf102ad75b /source | |
parent | 433749b6ef1e2b070755c3bb7fc0d81b5ecaa7b1 (diff) | |
parent | d4fcf2697c9a45594e3ee0b8bf82e480ddd0b69b (diff) | |
download | snesemu-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.cpp | 35 | ||||
-rw-r--r-- | source/apu.h | 2 | ||||
-rw-r--r-- | source/c4emu.cpp | 1 | ||||
-rw-r--r-- | source/cheats.cpp | 3 | ||||
-rw-r--r-- | source/cheats2.cpp | 1 | ||||
-rw-r--r-- | source/clip.cpp | 12 | ||||
-rw-r--r-- | source/cpuexec.cpp | 462 | ||||
-rw-r--r-- | source/cpuexec.h | 11 | ||||
-rw-r--r-- | source/display.h | 3 | ||||
-rw-r--r-- | source/dma.cpp | 8 | ||||
-rw-r--r-- | source/dsp1.cpp | 259 | ||||
-rw-r--r-- | source/gfx.cpp | 33 | ||||
-rw-r--r-- | source/loadzip.cpp | 8 | ||||
-rw-r--r-- | source/memmap.cpp | 161 | ||||
-rw-r--r-- | source/nds/dma_adj.c | 26 | ||||
-rw-r--r-- | source/nds/dma_adj.h | 29 | ||||
-rw-r--r-- | source/nds/ds2_main.c | 5 | ||||
-rw-r--r-- | source/nds/ds2sound.h | 21 | ||||
-rw-r--r-- | source/nds/entry.cpp | 620 | ||||
-rw-r--r-- | source/nds/entry.h | 4 | ||||
-rw-r--r-- | source/nds/gui.c | 704 | ||||
-rw-r--r-- | source/nds/gui.h | 22 | ||||
-rw-r--r-- | source/nds/message.h | 37 | ||||
-rw-r--r-- | source/ppu.cpp | 33 | ||||
-rw-r--r-- | source/ppu.h | 3 | ||||
-rw-r--r-- | source/sa1.cpp | 4 | ||||
-rw-r--r-- | source/snaporig.cpp | 6 | ||||
-rw-r--r-- | source/snapshot.cpp | 14 | ||||
-rw-r--r-- | source/soundux.cpp | 112 | ||||
-rw-r--r-- | source/soundux.h | 2 | ||||
-rw-r--r-- | source/srtc.cpp | 12 | ||||
-rw-r--r-- | source/tile.cpp | 65 |
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(¤t_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, |