aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Talavera <jesse@jesse.tg>2023-12-05 10:47:16 -0500
committerGitHub <noreply@github.com>2023-12-05 16:47:16 +0100
commit090627b3c19488e36677113e2f1ac16bdb4e2d05 (patch)
treed731b7b302801c9317c34584cdebb811b93739d0
parentae91d89f7c18f6b4153deeef7e3ebe14a1d849fe (diff)
Remove the last `ConfigEntry` state (#1902)
* Get rid of `ConfigEntry::ExternalBIOSEnable` - Now the BIOS files themselves are checked - The frontend's `Config::ExternalBIOSEnable` is not affected * Add `JITArgs` * Pass the JIT status to the `ARM` constructors * Encapsulate `NDS::EnableJIT` * Pass `JITArgs` to `ARMJIT`'s constructor * Remove the `JIT_*` `ConfigEntry`s in favor of members - Allow all the JIT args to be set with `NDS::SetJITArgs` - Encapsulate the JIT-related parameters in `ARMJIT` so they can reset the block cache if changed - Update the active (or newly-created) console in the frontend with adjusted JIT args * Make audio bit depth and interpolation configurable in `NDSArgs` - Define enums for both - Give those settings default values in `NDSArgs` - Remove `ConfigEntry::AudioBitDepth` - Initialize these settings in the relevant SPU constructors * Move the last DSi-specific logic in `Reset` to its own subclass * Remove `ConfigEntry::DSi_FullBIOSBoot` - Add members to `DSi` instead for getting and setting this - Update the frontend to accommodate these changes * Oops, missed a spot * Remove `ConfigEntry::Firm_MAC` and `Platform::GetConfigArray` - Also move the MAC parsing code to `ROMManager` * Remove the last `ConfigEntry` state - Make GDB support configurable via members * Add some `#ifdef`s that I'd almost forgotten
-rw-r--r--src/ARM.cpp16
-rw-r--r--src/ARM.h10
-rw-r--r--src/ARMJIT.cpp60
-rw-r--r--src/ARMJIT.h27
-rw-r--r--src/ARMJIT_A64/ARMJIT_LoadStore.cpp10
-rw-r--r--src/ARMJIT_x64/ARMJIT_LoadStore.cpp10
-rw-r--r--src/Args.h42
-rw-r--r--src/DSi.cpp10
-rw-r--r--src/DSi.h3
-rw-r--r--src/NDS.cpp58
-rw-r--r--src/NDS.h10
-rw-r--r--src/NDSCart.cpp6
-rw-r--r--src/NDSCart.h2
-rw-r--r--src/Platform.h33
-rw-r--r--src/SPU.cpp69
-rw-r--r--src/SPU.h24
-rw-r--r--src/frontend/qt_sdl/AudioInOut.cpp2
-rw-r--r--src/frontend/qt_sdl/Platform.cpp84
-rw-r--r--src/frontend/qt_sdl/ROMManager.cpp32
-rw-r--r--src/frontend/qt_sdl/main.cpp45
20 files changed, 323 insertions, 230 deletions
diff --git a/src/ARM.cpp b/src/ARM.cpp
index 659d303..2c19fa3 100644
--- a/src/ARM.cpp
+++ b/src/ARM.cpp
@@ -106,17 +106,17 @@ const u32 ARM::ConditionTable[16] =
0x0000 // NE
};
-ARM::ARM(u32 num, melonDS::NDS& nds) :
+ARM::ARM(u32 num, bool jit, std::optional<GDBArgs> gdb, melonDS::NDS& nds) :
#ifdef GDBSTUB_ENABLED
- GdbStub(this, Platform::GetConfigInt(num ? Platform::GdbPortARM7 : Platform::GdbPortARM9)),
+ GdbStub(this, gdb ? (num ? gdb->PortARM7 : gdb->PortARM9) : 0),
#endif
Num(num), // well uh
NDS(nds)
{
#ifdef GDBSTUB_ENABLED
- if (Platform::GetConfigBool(Platform::GdbEnabled)
+ if (gdb
#ifdef JIT_ENABLED
- && !Platform::GetConfigBool(Platform::JIT_Enable)
+ && !jit // TODO: Should we support toggling the GdbStub without destroying the ARM?
#endif
)
GdbStub.Init();
@@ -129,14 +129,14 @@ ARM::~ARM()
// dorp
}
-ARMv5::ARMv5(melonDS::NDS& nds) : ARM(0, nds)
+ARMv5::ARMv5(melonDS::NDS& nds, std::optional<GDBArgs> gdb, bool jit) : ARM(0, jit, gdb, nds)
{
DTCM = NDS.JIT.Memory.GetARM9DTCM();
PU_Map = PU_PrivMap;
}
-ARMv4::ARMv4(melonDS::NDS& nds) : ARM(1, nds)
+ARMv4::ARMv4(melonDS::NDS& nds, std::optional<GDBArgs> gdb, bool jit) : ARM(1, jit, gdb, nds)
{
//
}
@@ -187,8 +187,6 @@ void ARM::Reset()
#ifdef GDBSTUB_ENABLED
IsSingleStep = false;
BreakReq = false;
- BreakOnStartup = Platform::GetConfigBool(
- Num ? Platform::GdbARM7BreakOnStartup : Platform::GdbARM9BreakOnStartup);
#endif
// zorp
@@ -224,7 +222,7 @@ void ARM::DoSavestate(Savestate* file)
file->VarArray(R_UND, 3*sizeof(u32));
file->Var32(&CurInstr);
#ifdef JIT_ENABLED
- if (file->Saving && NDS.EnableJIT)
+ if (file->Saving && NDS.IsJITEnabled())
{
// hack, the JIT doesn't really pipeline
// but we still want JIT save states to be
diff --git a/src/ARM.h b/src/ARM.h
index 4becff0..65f78ab 100644
--- a/src/ARM.h
+++ b/src/ARM.h
@@ -20,6 +20,7 @@
#define ARM_H
#include <algorithm>
+#include <optional>
#include "types.h"
#include "MemRegion.h"
@@ -44,7 +45,7 @@ enum
const u32 ITCMPhysicalSize = 0x8000;
const u32 DTCMPhysicalSize = 0x4000;
-
+struct GDBArgs;
class ARMJIT;
class GPU;
class ARMJIT_Memory;
@@ -57,7 +58,7 @@ class ARM
#endif
{
public:
- ARM(u32 num, NDS& nds);
+ ARM(u32 num, bool jit, std::optional<GDBArgs> gdb, NDS& nds);
virtual ~ARM(); // destroy shit
virtual void Reset();
@@ -202,6 +203,7 @@ protected:
bool IsSingleStep;
bool BreakReq;
bool BreakOnStartup;
+ u16 Port;
public:
int GetCPU() const override { return Num ? 7 : 9; }
@@ -225,7 +227,7 @@ protected:
class ARMv5 : public ARM
{
public:
- ARMv5(melonDS::NDS& nds);
+ ARMv5(melonDS::NDS& nds, std::optional<GDBArgs> gdb, bool jit);
~ARMv5();
void Reset() override;
@@ -377,7 +379,7 @@ protected:
class ARMv4 : public ARM
{
public:
- ARMv4(melonDS::NDS& nds);
+ ARMv4(melonDS::NDS& nds, std::optional<GDBArgs> gdb, bool jit);
void FillPipeline() override;
diff --git a/src/ARMJIT.cpp b/src/ARMJIT.cpp
index b938dfb..5e0e207 100644
--- a/src/ARMJIT.cpp
+++ b/src/ARMJIT.cpp
@@ -237,16 +237,6 @@ ARMJIT::~ARMJIT() noexcept
void ARMJIT::Reset() noexcept
{
- MaxBlockSize = Platform::GetConfigInt(Platform::JIT_MaxBlockSize);
- LiteralOptimizations = Platform::GetConfigBool(Platform::JIT_LiteralOptimizations);
- BranchOptimizations = Platform::GetConfigBool(Platform::JIT_BranchOptimizations);
- FastMemory = Platform::GetConfigBool(Platform::JIT_FastMemory);
-
- if (MaxBlockSize < 1)
- MaxBlockSize = 1;
- if (MaxBlockSize > 32)
- MaxBlockSize = 32;
-
JitEnableWrite();
ResetBlockCache();
@@ -491,6 +481,56 @@ void ARMJIT::RetireJitBlock(JitBlock* block) noexcept
}
}
+void ARMJIT::SetJITArgs(JITArgs args) noexcept
+{
+ args.MaxBlockSize = std::clamp(args.MaxBlockSize, 1u, 32u);
+
+ if (MaxBlockSize != args.MaxBlockSize
+ || LiteralOptimizations != args.LiteralOptimizations
+ || BranchOptimizations != args.BranchOptimizations
+ || FastMemory != args.FastMemory)
+ ResetBlockCache();
+
+ MaxBlockSize = args.MaxBlockSize;
+ LiteralOptimizations = args.LiteralOptimizations;
+ BranchOptimizations = args.BranchOptimizations;
+ FastMemory = args.FastMemory;
+}
+
+void ARMJIT::SetMaxBlockSize(int size) noexcept
+{
+ size = std::clamp(size, 1, 32);
+
+ if (size != MaxBlockSize)
+ ResetBlockCache();
+
+ MaxBlockSize = size;
+}
+
+void ARMJIT::SetLiteralOptimizations(bool enabled) noexcept
+{
+ if (LiteralOptimizations != enabled)
+ ResetBlockCache();
+
+ LiteralOptimizations = enabled;
+}
+
+void ARMJIT::SetBranchOptimizations(bool enabled) noexcept
+{
+ if (BranchOptimizations != enabled)
+ ResetBlockCache();
+
+ BranchOptimizations = enabled;
+}
+
+void ARMJIT::SetFastMemory(bool enabled) noexcept
+{
+ if (FastMemory != enabled)
+ ResetBlockCache();
+
+ FastMemory = enabled;
+}
+
void ARMJIT::CompileBlock(ARM* cpu) noexcept
{
bool thumb = cpu->CPSR & 0x20;
diff --git a/src/ARMJIT.h b/src/ARMJIT.h
index 9e1ca07..6390855 100644
--- a/src/ARMJIT.h
+++ b/src/ARMJIT.h
@@ -19,6 +19,8 @@
#ifndef ARMJIT_H
#define ARMJIT_H
+#include <algorithm>
+#include <optional>
#include <memory>
#include "types.h"
@@ -30,6 +32,7 @@
#endif
#include "ARMJIT_Compiler.h"
+#include "Args.h"
#include "MemConstants.h"
namespace melonDS
@@ -40,7 +43,15 @@ class JitBlock;
class ARMJIT
{
public:
- ARMJIT(melonDS::NDS& nds) noexcept : NDS(nds), Memory(nds), JITCompiler(nds) {};
+ ARMJIT(melonDS::NDS& nds, std::optional<JITArgs> jit) noexcept :
+ NDS(nds),
+ Memory(nds),
+ JITCompiler(nds),
+ MaxBlockSize(jit.has_value() ? std::clamp(jit->MaxBlockSize, 1u, 32u) : 32),
+ LiteralOptimizations(jit.has_value() ? jit->LiteralOptimizations : false),
+ BranchOptimizations(jit.has_value() ? jit->BranchOptimizations : false),
+ FastMemory(jit.has_value() ? jit->FastMemory : false)
+ {}
~ARMJIT() noexcept NOOP_IF_NO_JIT;
void InvalidateByAddr(u32) noexcept NOOP_IF_NO_JIT;
void CheckAndInvalidateWVRAM(int) noexcept NOOP_IF_NO_JIT;
@@ -68,17 +79,29 @@ public:
#endif
ARMJIT_Memory Memory;
+private:
int MaxBlockSize {};
bool LiteralOptimizations = false;
bool BranchOptimizations = false;
bool FastMemory = false;
-
+public:
melonDS::NDS& NDS;
TinyVector<u32> InvalidLiterals {};
friend class ARMJIT_Memory;
void blockSanityCheck(u32 num, u32 blockAddr, JitBlockEntry entry) noexcept;
void RetireJitBlock(JitBlock* block) noexcept;
+ int GetMaxBlockSize() const noexcept { return MaxBlockSize; }
+ bool LiteralOptimizationsEnabled() const noexcept { return LiteralOptimizations; }
+ bool BranchOptimizationsEnabled() const noexcept { return BranchOptimizations; }
+ bool FastMemoryEnabled() const noexcept { return FastMemory; }
+
+ void SetJITArgs(JITArgs args) noexcept;
+ void SetMaxBlockSize(int size) noexcept;
+ void SetLiteralOptimizations(bool enabled) noexcept;
+ void SetBranchOptimizations(bool enabled) noexcept;
+ void SetFastMemory(bool enabled) noexcept;
+
Compiler JITCompiler;
std::unordered_map<u32, JitBlock*> JitBlocks9 {};
std::unordered_map<u32, JitBlock*> JitBlocks7 {};
diff --git a/src/ARMJIT_A64/ARMJIT_LoadStore.cpp b/src/ARMJIT_A64/ARMJIT_LoadStore.cpp
index 22a410a..4007138 100644
--- a/src/ARMJIT_A64/ARMJIT_LoadStore.cpp
+++ b/src/ARMJIT_A64/ARMJIT_LoadStore.cpp
@@ -112,7 +112,7 @@ void Compiler::Comp_MemAccess(int rd, int rn, Op2 offset, int size, int flags)
if (size == 16)
addressMask = ~1;
- if (NDS.JIT.LiteralOptimizations && rn == 15 && rd != 15 && offset.IsImm && !(flags & (memop_Post|memop_Store|memop_Writeback)))
+ if (NDS.JIT.LiteralOptimizationsEnabled() && rn == 15 && rd != 15 && offset.IsImm && !(flags & (memop_Post|memop_Store|memop_Writeback)))
{
u32 addr = R15 + offset.Imm * ((flags & memop_SubtractOffset) ? -1 : 1);
@@ -147,7 +147,7 @@ void Compiler::Comp_MemAccess(int rd, int rn, Op2 offset, int size, int flags)
MOV(W0, rnMapped);
}
- bool addrIsStatic = NDS.JIT.LiteralOptimizations
+ bool addrIsStatic = NDS.JIT.LiteralOptimizationsEnabled()
&& RegCache.IsLiteral(rn) && offset.IsImm && !(flags & (memop_Writeback|memop_Post));
u32 staticAddress;
if (addrIsStatic)
@@ -189,7 +189,7 @@ void Compiler::Comp_MemAccess(int rd, int rn, Op2 offset, int size, int flags)
? NDS.JIT.Memory.ClassifyAddress9(addrIsStatic ? staticAddress : CurInstr.DataRegion)
: NDS.JIT.Memory.ClassifyAddress7(addrIsStatic ? staticAddress : CurInstr.DataRegion);
- if (NDS.JIT.FastMemory && ((!Thumb && CurInstr.Cond() != 0xE) || NDS.JIT.Memory.IsFastmemCompatible(expectedTarget)))
+ if (NDS.JIT.FastMemoryEnabled() && ((!Thumb && CurInstr.Cond() != 0xE) || NDS.JIT.Memory.IsFastmemCompatible(expectedTarget)))
{
ptrdiff_t memopStart = GetCodeOffset();
LoadStorePatch patch;
@@ -453,7 +453,7 @@ void Compiler::T_Comp_LoadPCRel()
u32 offset = ((CurInstr.Instr & 0xFF) << 2);
u32 addr = (R15 & ~0x2) + offset;
- if (!NDS.JIT.LiteralOptimizations || !Comp_MemLoadLiteral(32, false, CurInstr.T_Reg(8), addr))
+ if (!NDS.JIT.LiteralOptimizationsEnabled() || !Comp_MemLoadLiteral(32, false, CurInstr.T_Reg(8), addr))
Comp_MemAccess(CurInstr.T_Reg(8), 15, Op2(offset), 32, 0);
}
@@ -498,7 +498,7 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc
? NDS.JIT.Memory.ClassifyAddress9(CurInstr.DataRegion)
: NDS.JIT.Memory.ClassifyAddress7(CurInstr.DataRegion);
- bool compileFastPath = NDS.JIT.FastMemory
+ bool compileFastPath = NDS.JIT.FastMemoryEnabled()
&& store && !usermode && (CurInstr.Cond() < 0xE || NDS.JIT.Memory.IsFastmemCompatible(expectedTarget));
{
diff --git a/src/ARMJIT_x64/ARMJIT_LoadStore.cpp b/src/ARMJIT_x64/ARMJIT_LoadStore.cpp
index 72a073d..8520beb 100644
--- a/src/ARMJIT_x64/ARMJIT_LoadStore.cpp
+++ b/src/ARMJIT_x64/ARMJIT_LoadStore.cpp
@@ -119,7 +119,7 @@ void Compiler::Comp_MemAccess(int rd, int rn, const Op2& op2, int size, int flag
if (size == 16)
addressMask = ~1;
- if (NDS.JIT.LiteralOptimizations && rn == 15 && rd != 15 && op2.IsImm && !(flags & (memop_Post|memop_Store|memop_Writeback)))
+ if (NDS.JIT.LiteralOptimizationsEnabled() && rn == 15 && rd != 15 && op2.IsImm && !(flags & (memop_Post|memop_Store|memop_Writeback)))
{
u32 addr = R15 + op2.Imm * ((flags & memop_SubtractOffset) ? -1 : 1);
@@ -136,7 +136,7 @@ void Compiler::Comp_MemAccess(int rd, int rn, const Op2& op2, int size, int flag
Comp_AddCycles_CDI();
}
- bool addrIsStatic = NDS.JIT.LiteralOptimizations
+ bool addrIsStatic = NDS.JIT.LiteralOptimizationsEnabled()
&& RegCache.IsLiteral(rn) && op2.IsImm && !(flags & (memop_Writeback|memop_Post));
u32 staticAddress;
if (addrIsStatic)
@@ -200,7 +200,7 @@ void Compiler::Comp_MemAccess(int rd, int rn, const Op2& op2, int size, int flag
? NDS.JIT.Memory.ClassifyAddress9(CurInstr.DataRegion)
: NDS.JIT.Memory.ClassifyAddress7(CurInstr.DataRegion);
- if (NDS.JIT.FastMemory && ((!Thumb && CurInstr.Cond() != 0xE) || NDS.JIT.Memory.IsFastmemCompatible(expectedTarget)))
+ if (NDS.JIT.FastMemoryEnabled() && ((!Thumb && CurInstr.Cond() != 0xE) || NDS.JIT.Memory.IsFastmemCompatible(expectedTarget)))
{
if (rdMapped.IsImm())
{
@@ -431,7 +431,7 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc
else
Comp_AddCycles_CD();
- bool compileFastPath = NDS.JIT.FastMemory
+ bool compileFastPath = NDS.JIT.FastMemoryEnabled()
&& !usermode && (CurInstr.Cond() < 0xE || NDS.JIT.Memory.IsFastmemCompatible(expectedTarget));
// we need to make sure that the stack stays aligned to 16 bytes
@@ -809,7 +809,7 @@ void Compiler::T_Comp_LoadPCRel()
{
u32 offset = (CurInstr.Instr & 0xFF) << 2;
u32 addr = (R15 & ~0x2) + offset;
- if (!NDS.JIT.LiteralOptimizations || !Comp_MemLoadLiteral(32, false, CurInstr.T_Reg(8), addr))
+ if (!NDS.JIT.LiteralOptimizationsEnabled() || !Comp_MemLoadLiteral(32, false, CurInstr.T_Reg(8), addr))
Comp_MemAccess(CurInstr.T_Reg(8), 15, Op2(offset), 32, 0);
}
diff --git a/src/Args.h b/src/Args.h
index bfa1b13..c6d131c 100644
--- a/src/Args.h
+++ b/src/Args.h
@@ -23,12 +23,15 @@
#include <optional>
#include <memory>
+#include "NDSCart.h"
+#include "GBACart.h"
#include "types.h"
#include "MemConstants.h"
#include "DSi_NAND.h"
#include "FATStorage.h"
#include "FreeBIOS.h"
#include "SPI_Firmware.h"
+#include "SPU.h"
namespace melonDS
{
@@ -50,6 +53,29 @@ constexpr std::array<u8, N> BrokenBIOS = []() constexpr {
return broken;
}();
+/// Arguments that configure the JIT.
+/// Ignored in builds that don't have the JIT included.
+struct JITArgs
+{
+ unsigned MaxBlockSize = 32;
+ bool LiteralOptimizations = true;
+ bool BranchOptimizations = true;
+
+ /// Ignored in builds that have fast memory excluded
+ /// (even if the JIT is otherwise available).
+ /// Enabled by default, but frontends should disable this when debugging
+ /// so the constants segfaults don't hinder debugging.
+ bool FastMemory = true;
+};
+
+struct GDBArgs
+{
+ u16 PortARM7 = 0;
+ u16 PortARM9 = 0;
+ bool ARM7BreakOnStartup = false;
+ bool ARM9BreakOnStartup = false;
+};
+
/// Arguments to pass into the NDS constructor.
/// New fields here should have default values if possible.
struct NDSArgs
@@ -78,6 +104,20 @@ struct NDSArgs
/// Defaults to generated NDS firmware.
/// Generated firmware is not compatible with DSi mode.
melonDS::Firmware Firmware {0};
+
+ /// How the JIT should be configured when initializing.
+ /// Defaults to enabled, with default settings.
+ /// To disable the JIT, set this to std::nullopt.
+ /// Ignored in builds that don't have the JIT included.
+ std::optional<JITArgs> JIT = JITArgs();
+
+ AudioBitDepth BitDepth = AudioBitDepth::Auto;
+ AudioInterpolation Interpolation = AudioInterpolation::None;
+
+ /// How the GDB stub should be handled.
+ /// Defaults to disabled.
+ /// Ignored in builds that don't have the GDB stub included.
+ std::optional<GDBArgs> GDB = std::nullopt;
};
/// Arguments to pass into the DSi constructor.
@@ -95,6 +135,8 @@ struct DSiArgs final : public NDSArgs
/// SD card to install.
/// Defaults to std::nullopt, which means no SD card.
std::optional<FATStorage> DSiSDCard;
+
+ bool FullBIOSBoot = false;
};
}
#endif //MELONDS_ARGS_H
diff --git a/src/DSi.cpp b/src/DSi.cpp
index 5dcd419..a5403d2 100644
--- a/src/DSi.cpp
+++ b/src/DSi.cpp
@@ -111,6 +111,8 @@ void DSi::Reset()
//ARM9.CP15Write(0x100, ARM9.CP15Read(0x100) | 0x00050000);
NDS::Reset();
+ // The SOUNDBIAS register does nothing on DSi
+ SPU.SetApplyBias(false);
KeyInput &= ~(1 << (16+6));
MapSharedWRAM(3);
@@ -128,7 +130,7 @@ void DSi::Reset()
AES.Reset();
- if (Platform::GetConfigBool(Platform::DSi_FullBIOSBoot))
+ if (FullBIOSBoot)
{
SCFG_BIOS = 0x0000;
}
@@ -679,7 +681,7 @@ void DSi::SoftReset()
AES.Reset();
- if (Platform::GetConfigBool(Platform::DSi_FullBIOSBoot))
+ if (FullBIOSBoot)
{
SCFG_BIOS = 0x0000;
}
@@ -741,7 +743,7 @@ bool DSi::LoadNAND()
memset(NWRAMMask, 0, sizeof(NWRAMMask));
u32 bootparams[8];
- if (Platform::GetConfigBool(Platform::DSi_FullBIOSBoot))
+ if (FullBIOSBoot)
{
// TODO: figure out default MBK mapping
// MBK1..5: disable mappings
@@ -879,7 +881,7 @@ bool DSi::LoadNAND()
Log(LogLevel::Debug, "eMMC CID: %08llX%08llX\n", *(const u64*)&emmccid[0], *(const u64*)&emmccid[8]);
Log(LogLevel::Debug, "Console ID: %" PRIx64 "\n", image->GetConsoleID());
- if (Platform::GetConfigBool(Platform::DSi_FullBIOSBoot))
+ if (FullBIOSBoot)
{
// point CPUs to boot ROM reset vectors
ARM9.JumpTo(0xFFFF0000);
diff --git a/src/DSi.h b/src/DSi.h
index acd85c1..90bb0d4 100644
--- a/src/DSi.h
+++ b/src/DSi.h
@@ -172,7 +172,10 @@ public:
u8 GPIO_IE;
u8 GPIO_WiFi;
+ bool GetFullBIOSBoot() const noexcept { return FullBIOSBoot; }
+ void SetFullBIOSBoot(bool full) noexcept { FullBIOSBoot = full; }
private:
+ bool FullBIOSBoot;
void Set_SCFG_Clock9(u16 val);
void Set_SCFG_MC(u32 val);
void DecryptModcryptArea(u32 offset, u32 size, u8* iv);
diff --git a/src/NDS.cpp b/src/NDS.cpp
index f3e5a1a..54aa270 100644
--- a/src/NDS.cpp
+++ b/src/NDS.cpp
@@ -92,8 +92,8 @@ NDS::NDS(NDSArgs&& args, int type) noexcept :
ConsoleType(type),
ARM7BIOS(args.ARM7BIOS),
ARM9BIOS(args.ARM9BIOS),
- JIT(*this),
- SPU(*this),
+ JIT(*this, args.JIT),
+ SPU(*this, args.BitDepth, args.Interpolation),
GPU(*this),
SPI(*this, std::move(args.Firmware)),
RTC(*this),
@@ -101,8 +101,8 @@ NDS::NDS(NDSArgs&& args, int type) noexcept :
NDSCartSlot(*this, std::move(args.NDSROM)),
GBACartSlot(type == 1 ? nullptr : std::move(args.GBAROM)),
AREngine(*this),
- ARM9(*this),
- ARM7(*this),
+ ARM9(*this, args.GDB, args.JIT.has_value()),
+ ARM7(*this, args.GDB, args.JIT.has_value()),
DMAs {
DMA(0, 0, *this),
DMA(0, 1, *this),
@@ -203,6 +203,22 @@ void NDS::SetARM7RegionTimings(u32 addrstart, u32 addrend, u32 region, int buswi
}
}
+#ifdef JIT_ENABLED
+void NDS::SetJITArgs(std::optional<JITArgs> args) noexcept
+{
+ if (args)
+ { // If we want to turn the JIT on...
+ JIT.SetJITArgs(*args);
+ }
+ else if (args.has_value() != EnableJIT)
+ { // Else if we want to turn the JIT off, and it wasn't already off...
+ JIT.ResetBlockCache();
+ }
+
+ EnableJIT = args.has_value();
+}
+#endif
+
void NDS::InitTimings()
{
// TODO, eventually:
@@ -249,12 +265,12 @@ bool NDS::NeedsDirectBoot()
}
else
{
- // internal BIOS does not support direct boot
- if (!Platform::GetConfigBool(Platform::ExternalBIOSEnable))
+ // DSi/3DS firmwares aren't bootable, neither is the generated firmware
+ if (!SPI.GetFirmware().IsBootable())
return true;
- // DSi/3DS firmwares aren't bootable
- if (!SPI.GetFirmware().IsBootable())
+ // FreeBIOS requires direct boot (it can't boot firmware)
+ if (IsLoadedARM7BIOSBuiltIn() || IsLoadedARM9BIOSBuiltIn())
return true;
return false;
@@ -394,10 +410,6 @@ void NDS::Reset()
Platform::FileHandle* f;
u32 i;
-#ifdef JIT_ENABLED
- EnableJIT = Platform::GetConfigBool(Platform::JIT_Enable);
-#endif
-
RunningGame = false;
LastSysClockCycles = 0;
@@ -505,28 +517,6 @@ void NDS::Reset()
SPI.Reset();
RTC.Reset();
Wifi.Reset();
-
- // TODO: move the SOUNDBIAS/degrade logic to SPU?
-
- // The SOUNDBIAS register does nothing on DSi
- SPU.SetApplyBias(ConsoleType == 0);
-
- bool degradeAudio = true;
-
- if (ConsoleType == 1)
- {
- //DSi::Reset();
- KeyInput &= ~(1 << (16+6));
- degradeAudio = false;
- }
-
- int bitDepth = Platform::GetConfigInt(Platform::AudioBitDepth);
- if (bitDepth == 1) // Always 10-bit
- degradeAudio = true;
- else if (bitDepth == 2) // Always 16-bit
- degradeAudio = false;
-
- SPU.SetDegrade10Bit(degradeAudio);
}
void NDS::Start()
diff --git a/src/NDS.h b/src/NDS.h
index b9f8291..c0b429e 100644
--- a/src/NDS.h
+++ b/src/NDS.h
@@ -219,11 +219,12 @@ class ARMJIT;
class NDS
{
-public:
-
+private:
#ifdef JIT_ENABLED
bool EnableJIT;
#endif
+
+public:
int ConsoleType;
int CurCPU;
@@ -433,6 +434,11 @@ public:
virtual void ARM7IOWrite16(u32 addr, u16 val);
virtual void ARM7IOWrite32(u32 addr, u32 val);
+#ifdef JIT_ENABLED
+ [[nodiscard]] bool IsJITEnabled() const noexcept { return EnableJIT; }
+ void SetJITArgs(std::optional<JITArgs> args) noexcept;
+#endif
+
private:
void InitTimings();
u32 SchedListMask;
diff --git a/src/NDSCart.cpp b/src/NDSCart.cpp
index 848c619..65309e3 100644
--- a/src/NDSCart.cpp
+++ b/src/NDSCart.cpp
@@ -109,9 +109,9 @@ void NDSCartSlot::Key1_ApplyKeycode(u32* keycode, u32 mod) noexcept
}
}
-void NDSCartSlot::Key1_LoadKeyBuf(bool dsi, bool externalBios, u8 *bios, u32 biosLength) noexcept
+void NDSCartSlot::Key1_LoadKeyBuf(bool dsi, u8 *bios, u32 biosLength) noexcept
{
- if (externalBios)
+ if (!NDS.IsLoadedARM7BIOSBuiltIn())
{
u32 expected_bios_length = dsi ? 0x10000 : 0x4000;
if (biosLength != expected_bios_length)
@@ -138,7 +138,7 @@ void NDSCartSlot::Key1_LoadKeyBuf(bool dsi, bool externalBios, u8 *bios, u32 bio
void NDSCartSlot::Key1_InitKeycode(bool dsi, u32 idcode, u32 level, u32 mod, u8 *bios, u32 biosLength) noexcept
{
- Key1_LoadKeyBuf(dsi, Platform::GetConfigBool(Platform::ExternalBIOSEnable), bios, biosLength);
+ Key1_LoadKeyBuf(dsi, bios, biosLength);
u32 keycode[3] = {idcode, idcode>>1, idcode<<1};
if (level >= 1) Key1_ApplyKeycode(keycode, mod);
diff --git a/src/NDSCart.h b/src/NDSCart.h
index 43bf1fc..03e16e9 100644
--- a/src/NDSCart.h
+++ b/src/NDSCart.h
@@ -357,7 +357,7 @@ private:
void Key1_Encrypt(u32* data) noexcept;
void Key1_Decrypt(u32* data) noexcept;
void Key1_ApplyKeycode(u32* keycode, u32 mod) noexcept;
- void Key1_LoadKeyBuf(bool dsi, bool externalBios, u8 *bios, u32 biosLength) noexcept;
+ void Key1_LoadKeyBuf(bool dsi, u8 *bios, u32 biosLength) noexcept;
void Key1_InitKeycode(bool dsi, u32 idcode, u32 level, u32 mod, u8 *bios, u32 biosLength) noexcept;
void Key2_Encrypt(u8* data, u32 len) noexcept;
void ROMEndTransfer(u32 param) noexcept;
diff --git a/src/Platform.h b/src/Platform.h
index 2c9a6a4..21b3d46 100644
--- a/src/Platform.h
+++ b/src/Platform.h
@@ -92,39 +92,6 @@ int InstanceID();
*/
std::string InstanceFileSuffix();
-// configuration values
-
-enum ConfigEntry
-{
-#ifdef JIT_ENABLED
- JIT_Enable,
- JIT_MaxBlockSize,
- JIT_LiteralOptimizations,
- JIT_BranchOptimizations,
- JIT_FastMemory,
-#endif
-
- ExternalBIOSEnable,
-
- Firm_MAC,
-
- AudioBitDepth,
-
- DSi_FullBIOSBoot,
-
-#ifdef GDBSTUB_ENABLED
- GdbEnabled,
- GdbPortARM7,
- GdbPortARM9,
- GdbARM7BreakOnStartup,
- GdbARM9BreakOnStartup,
-#endif
-};
-
-int GetConfigInt(ConfigEntry entry);
-bool GetConfigBool(ConfigEntry entry);
-bool GetConfigArray(ConfigEntry entry, void* data);
-
/**
* Denotes how a file will be opened and accessed.
* Flags may or may not correspond to the operating system's file API.
diff --git a/src/SPU.cpp b/src/SPU.cpp
index 1ec3c90..f1df9cf 100644
--- a/src/SPU.cpp
+++ b/src/SPU.cpp
@@ -140,31 +140,32 @@ constexpr array2d<s16, 0x100, 4> InterpCubic = []() constexpr {
return interp;
}();
-SPU::SPU(melonDS::NDS& nds) :
+SPU::SPU(melonDS::NDS& nds, AudioBitDepth bitdepth, AudioInterpolation interpolation) :
NDS(nds),
Channels {
- SPUChannel(0, nds),
- SPUChannel(1, nds),
- SPUChannel(2, nds),
- SPUChannel(3, nds),
- SPUChannel(4, nds),
- SPUChannel(5, nds),
- SPUChannel(6, nds),
- SPUChannel(7, nds),
- SPUChannel(8, nds),
- SPUChannel(9, nds),
- SPUChannel(10, nds),
- SPUChannel(11, nds),
- SPUChannel(12, nds),
- SPUChannel(13, nds),
- SPUChannel(14, nds),
- SPUChannel(15, nds),
+ SPUChannel(0, nds, interpolation),
+ SPUChannel(1, nds, interpolation),
+ SPUChannel(2, nds, interpolation),
+ SPUChannel(3, nds, interpolation),
+ SPUChannel(4, nds, interpolation),
+ SPUChannel(5, nds, interpolation),
+ SPUChannel(6, nds, interpolation),
+ SPUChannel(7, nds, interpolation),
+ SPUChannel(8, nds, interpolation),
+ SPUChannel(9, nds, interpolation),
+ SPUChannel(10, nds, interpolation),
+ SPUChannel(11, nds, interpolation),
+ SPUChannel(12, nds, interpolation),
+ SPUChannel(13, nds, interpolation),
+ SPUChannel(14, nds, interpolation),
+ SPUChannel(15, nds, interpolation),
},
Capture {
SPUCaptureUnit(0, nds),
SPUCaptureUnit(1, nds),
},
- AudioLock(Platform::Mutex_Create())
+ AudioLock(Platform::Mutex_Create()),
+ Degrade10Bit(bitdepth == AudioBitDepth::_10Bit || (nds.ConsoleType == 1 && bitdepth == AudioBitDepth::Auto))
{
NDS.RegisterEventFunc(Event_SPU, 0, MemberEventFunc(SPU, Mix));
@@ -236,7 +237,7 @@ void SPU::SetPowerCnt(u32 val)
}
-void SPU::SetInterpolation(int type)
+void SPU::SetInterpolation(AudioInterpolation type)
{
for (SPUChannel& channel : Channels)
channel.InterpType = type;
@@ -257,8 +258,26 @@ void SPU::SetDegrade10Bit(bool enable)
Degrade10Bit = enable;
}
+void SPU::SetDegrade10Bit(AudioBitDepth depth)
+{
+ switch (depth)
+ {
+ case AudioBitDepth::Auto:
+ Degrade10Bit = (NDS.ConsoleType == 0);
+ break;
+ case AudioBitDepth::_10Bit:
+ Degrade10Bit = true;
+ break;
+ case AudioBitDepth::_16Bit:
+ Degrade10Bit = false;
+ break;
+ }
+}
-SPUChannel::SPUChannel(u32 num, melonDS::NDS& nds) : NDS(nds), Num(num)
+SPUChannel::SPUChannel(u32 num, melonDS::NDS& nds, AudioInterpolation interpolation) :
+ NDS(nds),
+ Num(num),
+ InterpType(interpolation)
{
}
@@ -559,7 +578,7 @@ s32 SPUChannel::Run()
// for optional interpolation: save previous samples
// the interpolated audio will be delayed by a couple samples,
// but it's easier to deal with this way
- if ((type < 3) && (InterpType != 0))
+ if ((type < 3) && (InterpType != AudioInterpolation::None))
{
PrevSample[2] = PrevSample[1];
PrevSample[1] = PrevSample[0];
@@ -579,24 +598,24 @@ s32 SPUChannel::Run()
s32 val = (s32)CurSample;
// interpolation (emulation improvement, not a hardware feature)
- if ((type < 3) && (InterpType != 0))
+ if ((type < 3) && (InterpType != AudioInterpolation::None))
{
s32 samplepos = ((Timer - TimerReload) * 0x100) / (0x10000 - TimerReload);
if (samplepos > 0xFF) samplepos = 0xFF;
switch (InterpType)
{
- case 1: // linear
+ case AudioInterpolation::Linear:
val = ((val * samplepos) +
(PrevSample[0] * (0xFF-samplepos))) >> 8;
break;
- case 2: // cosine
+ case AudioInterpolation::Cosine:
val = ((val * InterpCos[samplepos]) +
(PrevSample[0] * InterpCos[0xFF-samplepos])) >> 14;
break;
- case 3: // cubic
+ case AudioInterpolation::Cubic:
val = ((PrevSample[2] * InterpCubic[samplepos][0]) +
(PrevSample[1] * InterpCubic[samplepos][1]) +
(PrevSample[0] * InterpCubic[samplepos][2]) +
diff --git a/src/SPU.h b/src/SPU.h
index 03d476e..1541c68 100644
--- a/src/SPU.h
+++ b/src/SPU.h
@@ -27,10 +27,25 @@ namespace melonDS
class NDS;
class SPU;
+enum class AudioBitDepth
+{
+ Auto,
+ _10Bit,
+ _16Bit,
+};
+
+enum class AudioInterpolation
+{
+ None,
+ Linear,
+ Cosine,
+ Cubic,
+};
+
class SPUChannel
{
public:
- SPUChannel(u32 num, melonDS::NDS& nds);
+ SPUChannel(u32 num, melonDS::NDS& nds, AudioInterpolation interpolation);
void Reset();
void DoSavestate(Savestate* file);
@@ -40,7 +55,7 @@ public:
// audio interpolation is an improvement upon the original hardware
// (which performs no interpolation)
- int InterpType = 0;
+ AudioInterpolation InterpType = AudioInterpolation::None;
const u32 Num;
@@ -200,7 +215,7 @@ private:
class SPU
{
public:
- explicit SPU(melonDS::NDS& nds);
+ explicit SPU(melonDS::NDS& nds, AudioBitDepth bitdepth, AudioInterpolation interpolation);
~SPU();
void Reset();
void DoSavestate(Savestate* file);
@@ -210,10 +225,11 @@ public:
void SetPowerCnt(u32 val);
// 0=none 1=linear 2=cosine 3=cubic
- void SetInterpolation(int type);
+ void SetInterpolation(AudioInterpolation type);
void SetBias(u16 bias);
void SetDegrade10Bit(bool enable);
+ void SetDegrade10Bit(AudioBitDepth depth);
void SetApplyBias(bool enable);
void Mix(u32 dummy);
diff --git a/src/frontend/qt_sdl/AudioInOut.cpp b/src/frontend/qt_sdl/AudioInOut.cpp
index ae5529d..1f1ee1c 100644
--- a/src/frontend/qt_sdl/AudioInOut.cpp
+++ b/src/frontend/qt_sdl/AudioInOut.cpp
@@ -369,7 +369,7 @@ void UpdateSettings(NDS& nds)
{
MicClose();
- nds.SPU.SetInterpolation(Config::AudioInterp);
+ nds.SPU.SetInterpolation(static_cast<AudioInterpolation>(Config::AudioInterp));
SetupMicInputData();
MicOpen();
diff --git a/src/frontend/qt_sdl/Platform.cpp b/src/frontend/qt_sdl/Platform.cpp
index d410d4f..4630582 100644
--- a/src/frontend/qt_sdl/Platform.cpp
+++ b/src/frontend/qt_sdl/Platform.cpp
@@ -193,90 +193,6 @@ std::string InstanceFileSuffix()
return suffix;
}
-
-int GetConfigInt(ConfigEntry entry)
-{
- const int imgsizes[] = {0, 256, 512, 1024, 2048, 4096};
-
- switch (entry)
- {
-#ifdef JIT_ENABLED
- case JIT_MaxBlockSize: return Config::JIT_MaxBlockSize;
-#endif
-
- case AudioBitDepth: return Config::AudioBitDepth;
-
-#ifdef GDBSTUB_ENABLED
- case GdbPortARM7: return Config::GdbPortARM7;
- case GdbPortARM9: return Config::GdbPortARM9;
-#endif
- }
-
- return 0;
-}
-
-bool GetConfigBool(ConfigEntry entry)
-{
- switch (entry)
- {
-#ifdef JIT_ENABLED
- case JIT_Enable: return Config::JIT_Enable != 0;
- case JIT_LiteralOptimizations: return Config::JIT_LiteralOptimisations != 0;
- case JIT_BranchOptimizations: return Config::JIT_BranchOptimisations != 0;
- case JIT_FastMemory: return Config::JIT_FastMemory != 0;
-#endif
-
- case ExternalBIOSEnable: return Config::ExternalBIOSEnable != 0;
-
- case DSi_FullBIOSBoot: return Config::DSiFullBIOSBoot != 0;
-
-#ifdef GDBSTUB_ENABLED
- case GdbEnabled: return Config::GdbEnabled;
- case GdbARM7BreakOnStartup: return Config::GdbARM7BreakOnStartup;
- case GdbARM9BreakOnStartup: return Config::GdbARM9BreakOnStartup;
-#endif
- }
-
- return false;
-}
-
-bool GetConfigArray(ConfigEntry entry, void* data)
-{
- switch (entry)
- {
- case Firm_MAC:
- {
- std::string& mac_in = Config::FirmwareMAC;
- u8* mac_out = (u8*)data;
-
- int o = 0;
- u8 tmp = 0;
- for (int i = 0; i < 18; i++)
- {
- char c = mac_in[i];
- if (c == '\0') break;
-
- int n;
- if (c >= '0' && c <= '9') n = c - '0';
- else if (c >= 'a' && c <= 'f') n = c - 'a' + 10;
- else if (c >= 'A' && c <= 'F') n = c - 'A' + 10;
- else continue;
-
- if (!(o & 1))
- tmp = n;
- else
- mac_out[o >> 1] = n | (tmp << 4);
-
- o++;
- if (o >= 12) return true;
- }
- }
- return false;
- }
-
- return false;
-}
-
constexpr char AccessMode(FileMode mode, bool file_exists)
{
if (!(mode & FileMode::Write))
diff --git a/src/frontend/qt_sdl/ROMManager.cpp b/src/frontend/qt_sdl/ROMManager.cpp
index fda043a..b065ad1 100644
--- a/src/frontend/qt_sdl/ROMManager.cpp
+++ b/src/frontend/qt_sdl/ROMManager.cpp
@@ -1078,6 +1078,36 @@ pair<unique_ptr<Firmware>, string> GenerateDefaultFirmware()
return std::make_pair(std::move(firmware), std::move(wfcsettingspath));
}
+bool ParseMacAddress(void* data)
+{
+ const std::string& mac_in = Config::FirmwareMAC;
+ u8* mac_out = (u8*)data;
+
+ int o = 0;
+ u8 tmp = 0;
+ for (int i = 0; i < 18; i++)
+ {
+ char c = mac_in[i];
+ if (c == '\0') break;
+
+ int n;
+ if (c >= '0' && c <= '9') n = c - '0';
+ else if (c >= 'a' && c <= 'f') n = c - 'a' + 10;
+ else if (c >= 'A' && c <= 'F') n = c - 'A' + 10;
+ else continue;
+
+ if (!(o & 1))
+ tmp = n;
+ else
+ mac_out[o >> 1] = n | (tmp << 4);
+
+ o++;
+ if (o >= 12) return true;
+ }
+
+ return false;
+}
+
void CustomizeFirmware(Firmware& firmware) noexcept
{
auto& currentData = firmware.GetEffectiveUserData();
@@ -1136,7 +1166,7 @@ void CustomizeFirmware(Firmware& firmware) noexcept
MacAddress configuredMac;
- rep = Platform::GetConfigArray(Platform::Firm_MAC, &configuredMac);
+ rep = ParseMacAddress(&configuredMac);
rep &= (configuredMac != MacAddress());
if (rep)
diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp
index 5bd4d1b..30ea0ab 100644
--- a/src/frontend/qt_sdl/main.cpp
+++ b/src/frontend/qt_sdl/main.cpp
@@ -222,12 +222,42 @@ std::unique_ptr<NDS> EmuThread::CreateConsole(
if (!firmware)
return nullptr;
+#ifdef JIT_ENABLED
+ JITArgs jitargs {
+ static_cast<unsigned>(Config::JIT_MaxBlockSize),
+ Config::JIT_LiteralOptimisations,
+ Config::JIT_BranchOptimisations,
+ Config::JIT_FastMemory,
+ };
+#endif
+
+#ifdef GDBSTUB_ENABLED
+ GDBArgs gdbargs {
+ static_cast<u16>(Config::GdbPortARM7),
+ static_cast<u16>(Config::GdbPortARM9),
+ Config::GdbARM7BreakOnStartup,
+ Config::GdbARM9BreakOnStartup,
+ };
+#endif
+
NDSArgs ndsargs {
std::move(ndscart),
std::move(gbacart),
*arm9bios,
*arm7bios,
std::move(*firmware),
+#ifdef JIT_ENABLED
+ Config::JIT_Enable ? std::make_optional(jitargs) : std::nullopt,
+#else
+ std::nullopt,
+#endif
+ static_cast<AudioBitDepth>(Config::AudioBitDepth),
+ static_cast<AudioInterpolation>(Config::AudioInterp),
+#ifdef GDBSTUB_ENABLED
+ Config::GdbEnabled ? std::make_optional(gdbargs) : std::nullopt,
+#else
+ std::nullopt,
+#endif
};
if (Config::ConsoleType == 1)
@@ -251,6 +281,7 @@ std::unique_ptr<NDS> EmuThread::CreateConsole(
*arm7ibios,
std::move(*nand),
std::move(sdcard),
+ Config::DSiFullBIOSBoot,
};
args.GBAROM = nullptr;
@@ -339,6 +370,7 @@ bool EmuThread::UpdateConsole(UpdateConsoleNDSArgs&& ndsargs, UpdateConsoleGBAAr
auto dsisdcard = ROMManager::LoadDSiSDCard();
+ dsi.SetFullBIOSBoot(Config::DSiFullBIOSBoot);
dsi.ARM7iBIOS = *arm7ibios;
dsi.ARM9iBIOS = *arm9ibios;
dsi.SetNAND(std::move(*nandimage));
@@ -354,10 +386,19 @@ bool EmuThread::UpdateConsole(UpdateConsoleNDSArgs&& ndsargs, UpdateConsoleGBAAr
NDS->SetGBACart(std::move(nextgbacart));
}
+ JITArgs jitargs {
+ static_cast<unsigned>(Config::JIT_MaxBlockSize),
+ Config::JIT_LiteralOptimisations,
+ Config::JIT_BranchOptimisations,
+ Config::JIT_FastMemory,
+ };
NDS->ARM7BIOS = *arm7bios;
NDS->ARM9BIOS = *arm9bios;
NDS->SetFirmware(std::move(*firmware));
NDS->SetNDSCart(std::move(nextndscart));
+ NDS->SetJITArgs(Config::JIT_Enable ? std::make_optional(jitargs) : std::nullopt);
+ NDS->SPU.SetInterpolation(static_cast<AudioInterpolation>(Config::AudioInterp));
+ NDS->SPU.SetDegrade10Bit(static_cast<AudioBitDepth>(Config::AudioBitDepth));
NDS::Current = NDS.get();
@@ -510,8 +551,6 @@ void EmuThread::run()
NDS->GPU.SetRenderer3D(std::move(glrenderer));
}
- NDS->SPU.SetInterpolation(Config::AudioInterp);
-
Input::Init();
u32 nframes = 0;
@@ -3137,7 +3176,7 @@ void MainWindow::onPathSettingsFinished(int res)
void MainWindow::onUpdateAudioSettings()
{
assert(emuThread->NDS != nullptr);
- emuThread->NDS->SPU.SetInterpolation(Config::AudioInterp);
+ emuThread->NDS->SPU.SetInterpolation(static_cast<AudioInterpolation>(Config::AudioInterp));
if (Config::AudioBitDepth == 0)
emuThread->NDS->SPU.SetDegrade10Bit(emuThread->NDS->ConsoleType == 0);