aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRSDuck <rsduck@users.noreply.github.com>2020-06-30 23:50:41 +0200
committerRSDuck <rsduck@users.noreply.github.com>2020-06-30 23:50:41 +0200
commitc5381d2911d47fb1fcbd6ec27a83f5da3606c4bd (patch)
tree1dbf9eb1bbe418d14f07dc3a0e30821fb5deb258 /src
parentea6d03581b689738d0d1930b28d1588019cf4077 (diff)
reconcile DSi and JIT, fastmem for x64 and Windows
Diffstat (limited to 'src')
-rw-r--r--src/ARM.cpp23
-rw-r--r--src/ARM.h2
-rw-r--r--src/ARMJIT.cpp273
-rw-r--r--src/ARMJIT.h2
-rw-r--r--src/ARMJIT_A64/ARMJIT_LoadStore.cpp4
-rw-r--r--src/ARMJIT_Internal.h12
-rw-r--r--src/ARMJIT_Memory.cpp636
-rw-r--r--src/ARMJIT_Memory.h16
-rw-r--r--src/ARMJIT_x64/ARMJIT_Compiler.cpp109
-rw-r--r--src/ARMJIT_x64/ARMJIT_Compiler.h14
-rw-r--r--src/ARMJIT_x64/ARMJIT_LoadStore.cpp632
-rw-r--r--src/CP15.cpp21
-rw-r--r--src/Config.cpp20
-rw-r--r--src/Config.h9
-rw-r--r--src/DSi.cpp167
-rw-r--r--src/DSi.h15
-rw-r--r--src/DSi_I2C.cpp4
-rw-r--r--src/NDS.cpp41
-rw-r--r--src/NDS.h2
-rw-r--r--src/frontend/qt_sdl/EmuSettingsDialog.cpp115
-rw-r--r--src/frontend/qt_sdl/EmuSettingsDialog.h5
-rw-r--r--src/frontend/qt_sdl/EmuSettingsDialog.ui598
-rw-r--r--src/frontend/qt_sdl/main.cpp9
-rw-r--r--src/frontend/qt_sdl/main.h1
-rw-r--r--src/libui_sdl/DlgEmuSettings.cpp252
-rw-r--r--src/libui_sdl/libui/ui.h764
-rw-r--r--src/libui_sdl/libui/unix/stddialogs.c126
-rw-r--r--src/libui_sdl/libui/windows/stddialogs.cpp180
-rw-r--r--src/libui_sdl/main.cpp3061
29 files changed, 1656 insertions, 5457 deletions
diff --git a/src/ARM.cpp b/src/ARM.cpp
index e529be8..8530795 100644
--- a/src/ARM.cpp
+++ b/src/ARM.cpp
@@ -21,12 +21,15 @@
#include "DSi.h"
#include "ARM.h"
#include "ARMInterpreter.h"
-#include "ARMJIT.h"
#include "Config.h"
#include "AREngine.h"
#include "ARMJIT.h"
#include "Config.h"
+#ifdef JIT_ENABLED
+#include "ARMJIT.h"
+#include "ARMJIT_Memory.h"
+#endif
// instruction timing notes
//
@@ -109,6 +112,12 @@ void ARM::Reset()
CodeMem.Mem = NULL;
+#ifdef JIT_ENABLED
+ FastBlockLookup = NULL;
+ FastBlockLookupStart = 0;
+ FastBlockLookupSize = 0;
+#endif
+
// zorp
JumpTo(ExceptionBase);
}
@@ -752,6 +761,12 @@ void ARMv4::Execute()
if (Halted == 2)
Halted = 0;
+
+ if (Halted == 4)
+ {
+ DSi::SoftReset();
+ Halted = 2;
+ }
}
#ifdef JIT_ENABLED
@@ -820,6 +835,12 @@ void ARMv4::ExecuteJIT()
if (Halted == 2)
Halted = 0;
+
+ if (Halted == 4)
+ {
+ DSi::SoftReset();
+ Halted = 2;
+ }
}
#endif
diff --git a/src/ARM.h b/src/ARM.h
index b7f16d6..0248e26 100644
--- a/src/ARM.h
+++ b/src/ARM.h
@@ -147,7 +147,7 @@ public:
NDS::MemRegion CodeMem;
#ifdef JIT_ENABLED
- u32 FastBlockLookupStart = 0, FastBlockLookupSize = 0;
+ u32 FastBlockLookupStart, FastBlockLookupSize;
u64* FastBlockLookup;
#endif
diff --git a/src/ARMJIT.cpp b/src/ARMJIT.cpp
index 53b28c1..2a61c38 100644
--- a/src/ARMJIT.cpp
+++ b/src/ARMJIT.cpp
@@ -18,6 +18,7 @@
#include "ARMInterpreter_Branch.h"
#include "ARMInterpreter.h"
+#include "DSi.h"
#include "GPU.h"
#include "GPU3D.h"
#include "SPU.h"
@@ -38,25 +39,35 @@ namespace ARMJIT
Compiler* JITCompiler;
AddressRange CodeIndexITCM[ITCMPhysicalSize / 512];
-AddressRange CodeIndexMainRAM[NDS::MainRAMSize / 512];
+AddressRange CodeIndexMainRAM[NDS::MainRAMMaxSize / 512];
AddressRange CodeIndexSWRAM[NDS::SharedWRAMSize / 512];
AddressRange CodeIndexVRAM[0x100000 / 512];
AddressRange CodeIndexARM9BIOS[sizeof(NDS::ARM9BIOS) / 512];
AddressRange CodeIndexARM7BIOS[sizeof(NDS::ARM7BIOS) / 512];
AddressRange CodeIndexARM7WRAM[NDS::ARM7WRAMSize / 512];
AddressRange CodeIndexARM7WVRAM[0x40000 / 512];
+AddressRange CodeIndexBIOS9DSi[0x10000 / 512];
+AddressRange CodeIndexBIOS7DSi[0x10000 / 512];
+AddressRange CodeIndexNWRAM_A[DSi::NWRAMSize / 512];
+AddressRange CodeIndexNWRAM_B[DSi::NWRAMSize / 512];
+AddressRange CodeIndexNWRAM_C[DSi::NWRAMSize / 512];
std::unordered_map<u32, JitBlock*> JitBlocks9;
std::unordered_map<u32, JitBlock*> JitBlocks7;
u64 FastBlockLookupITCM[ITCMPhysicalSize / 2];
-u64 FastBlockLookupMainRAM[NDS::MainRAMSize / 2];
+u64 FastBlockLookupMainRAM[NDS::MainRAMMaxSize / 2];
u64 FastBlockLookupSWRAM[NDS::SharedWRAMSize / 2];
u64 FastBlockLookupVRAM[0x100000 / 2];
u64 FastBlockLookupARM9BIOS[sizeof(NDS::ARM9BIOS) / 2];
u64 FastBlockLookupARM7BIOS[sizeof(NDS::ARM7BIOS) / 2];
u64 FastBlockLookupARM7WRAM[NDS::ARM7WRAMSize / 2];
u64 FastBlockLookupARM7WVRAM[0x40000 / 2];
+u64 FastBlockLookupBIOS9DSi[0x10000 / 2];
+u64 FastBlockLookupBIOS7DSi[0x10000 / 2];
+u64 FastBlockLookupNWRAM_A[DSi::NWRAMSize / 2];
+u64 FastBlockLookupNWRAM_B[DSi::NWRAMSize / 2];
+u64 FastBlockLookupNWRAM_C[DSi::NWRAMSize / 2];
const u32 CodeRegionSizes[ARMJIT_Memory::memregions_Count] =
{
@@ -64,7 +75,7 @@ const u32 CodeRegionSizes[ARMJIT_Memory::memregions_Count] =
ITCMPhysicalSize,
0,
sizeof(NDS::ARM9BIOS),
- NDS::MainRAMSize,
+ NDS::MainRAMMaxSize,
NDS::SharedWRAMSize,
0,
0x100000,
@@ -73,6 +84,11 @@ const u32 CodeRegionSizes[ARMJIT_Memory::memregions_Count] =
0,
0,
0x40000,
+ 0x10000,
+ 0x10000,
+ sizeof(DSi::NWRAM_A),
+ sizeof(DSi::NWRAM_B),
+ sizeof(DSi::NWRAM_C),
};
AddressRange* const CodeMemRegions[ARMJIT_Memory::memregions_Count] =
@@ -90,6 +106,11 @@ AddressRange* const CodeMemRegions[ARMJIT_Memory::memregions_Count] =
NULL,
NULL,
CodeIndexARM7WVRAM,
+ CodeIndexBIOS9DSi,
+ CodeIndexBIOS7DSi,
+ CodeIndexNWRAM_A,
+ CodeIndexNWRAM_B,
+ CodeIndexNWRAM_C
};
u64* const FastBlockLookupRegions[ARMJIT_Memory::memregions_Count] =
@@ -106,7 +127,12 @@ u64* const FastBlockLookupRegions[ARMJIT_Memory::memregions_Count] =
FastBlockLookupARM7WRAM,
NULL,
NULL,
- FastBlockLookupARM7WVRAM
+ FastBlockLookupARM7WVRAM,
+ FastBlockLookupBIOS9DSi,
+ FastBlockLookupBIOS7DSi,
+ FastBlockLookupNWRAM_A,
+ FastBlockLookupNWRAM_B,
+ FastBlockLookupNWRAM_C
};
u32 LocaliseCodeAddress(u32 num, u32 addr)
@@ -115,21 +141,14 @@ u32 LocaliseCodeAddress(u32 num, u32 addr)
? ARMJIT_Memory::ClassifyAddress9(addr)
: ARMJIT_Memory::ClassifyAddress7(addr);
- u32 mappingStart, mappingSize, memoryOffset, memorySize;
- if (ARMJIT_Memory::GetRegionMapping(region, num, mappingStart,
- mappingSize, memoryOffset, memorySize)
- && CodeMemRegions[region])
- {
- addr = ((addr - mappingStart) & (memorySize - 1)) + memoryOffset;
- addr |= (u32)region << 28;
- return addr;
- }
+ if (CodeMemRegions[region])
+ return ARMJIT_Memory::LocaliseAddress(region, num, addr);
return 0;
}
TinyVector<u32> InvalidLiterals;
-template <typename T>
+template <typename T, int ConsoleType>
T SlowRead9(u32 addr, ARMv5* cpu)
{
u32 offset = addr & 0x3;
@@ -141,11 +160,11 @@ T SlowRead9(u32 addr, ARMv5* cpu)
else if (addr >= cpu->DTCMBase && addr < (cpu->DTCMBase + cpu->DTCMSize))
val = *(T*)&cpu->DTCM[(addr - cpu->DTCMBase) & 0x3FFF];
else if (std::is_same<T, u32>::value)
- val = NDS::ARM9Read32(addr);
+ val = (ConsoleType == 0 ? NDS::ARM9Read32 : DSi::ARM9Read32)(addr);
else if (std::is_same<T, u16>::value)
- val = NDS::ARM9Read16(addr);
+ val = (ConsoleType == 0 ? NDS::ARM9Read16 : DSi::ARM9Read16)(addr);
else
- val = NDS::ARM9Read8(addr);
+ val = (ConsoleType == 0 ? NDS::ARM9Read8 : DSi::ARM9Read8)(addr);
if (std::is_same<T, u32>::value)
return ROR(val, offset << 3);
@@ -153,7 +172,7 @@ T SlowRead9(u32 addr, ARMv5* cpu)
return val;
}
-template <typename T>
+template <typename T, int ConsoleType>
void SlowWrite9(u32 addr, ARMv5* cpu, T val)
{
addr &= ~(sizeof(T) - 1);
@@ -169,27 +188,19 @@ void SlowWrite9(u32 addr, ARMv5* cpu, T val)
}
else if (std::is_same<T, u32>::value)
{
- NDS::ARM9Write32(addr, val);
+ (ConsoleType == 0 ? NDS::ARM9Write32 : DSi::ARM9Write32)(addr, val);
}
else if (std::is_same<T, u16>::value)
{
- NDS::ARM9Write16(addr, val);
+ (ConsoleType == 0 ? NDS::ARM9Write16 : DSi::ARM9Write16)(addr, val);
}
else
{
- NDS::ARM9Write8(addr, val);
+ (ConsoleType == 0 ? NDS::ARM9Write8 : DSi::ARM9Write8)(addr, val);
}
}
-template void SlowWrite9<u32>(u32, ARMv5*, u32);
-template void SlowWrite9<u16>(u32, ARMv5*, u16);
-template void SlowWrite9<u8>(u32, ARMv5*, u8);
-
-template u32 SlowRead9<u32>(u32, ARMv5*);
-template u16 SlowRead9<u16>(u32, ARMv5*);
-template u8 SlowRead9<u8>(u32, ARMv5*);
-
-template <typename T>
+template <typename T, int ConsoleType>
T SlowRead7(u32 addr)
{
u32 offset = addr & 0x3;
@@ -197,11 +208,11 @@ T SlowRead7(u32 addr)
T val;
if (std::is_same<T, u32>::value)
- val = NDS::ARM7Read32(addr);
+ val = (ConsoleType == 0 ? NDS::ARM7Read32 : DSi::ARM7Read32)(addr);
else if (std::is_same<T, u16>::value)
- val = NDS::ARM7Read16(addr);
+ val = (ConsoleType == 0 ? NDS::ARM7Read16 : DSi::ARM7Read16)(addr);
else
- val = NDS::ARM7Read8(addr);
+ val = (ConsoleType == 0 ? NDS::ARM7Read8 : DSi::ARM7Read8)(addr);
if (std::is_same<T, u32>::value)
return ROR(val, offset << 3);
@@ -209,67 +220,71 @@ T SlowRead7(u32 addr)
return val;
}
-template <typename T>
+template <typename T, int ConsoleType>
void SlowWrite7(u32 addr, T val)
{
addr &= ~(sizeof(T) - 1);
if (std::is_same<T, u32>::value)
- NDS::ARM7Write32(addr, val);
+ (ConsoleType == 0 ? NDS::ARM7Write32 : DSi::ARM7Write32)(addr, val);
else if (std::is_same<T, u16>::value)
- NDS::ARM7Write16(addr, val);
+ (ConsoleType == 0 ? NDS::ARM7Write16 : DSi::ARM7Write16)(addr, val);
else
- NDS::ARM7Write8(addr, val);
+ (ConsoleType == 0 ? NDS::ARM7Write8 : DSi::ARM7Write8)(addr, val);
}
-template <bool PreInc, bool Write>
+template <bool Write, int ConsoleType>
void SlowBlockTransfer9(u32 addr, u64* data, u32 num, ARMv5* cpu)
{
addr &= ~0x3;
- if (PreInc)
- addr += 4;
for (int i = 0; i < num; i++)
{
if (Write)
- SlowWrite9<u32>(addr, cpu, data[i]);
+ SlowWrite9<u32, ConsoleType>(addr, cpu, data[i]);
else
- data[i] = SlowRead9<u32>(addr, cpu);
+ data[i] = SlowRead9<u32, ConsoleType>(addr, cpu);
addr += 4;
}
}
-template <bool PreInc, bool Write>
+template <bool Write, int ConsoleType>
void SlowBlockTransfer7(u32 addr, u64* data, u32 num)
{
addr &= ~0x3;
- if (PreInc)
- addr += 4;
for (int i = 0; i < num; i++)
{
if (Write)
- SlowWrite7<u32>(addr, data[i]);
+ SlowWrite7<u32, ConsoleType>(addr, data[i]);
else
- data[i] = SlowRead7<u32>(addr);
+ data[i] = SlowRead7<u32, ConsoleType>(addr);
addr += 4;
}
}
-template void SlowWrite7<u32>(u32, u32);
-template void SlowWrite7<u16>(u32, u16);
-template void SlowWrite7<u8>(u32, u8);
-
-template u32 SlowRead7<u32>(u32);
-template u16 SlowRead7<u16>(u32);
-template u8 SlowRead7<u8>(u32);
-
-template void SlowBlockTransfer9<false, false>(u32, u64*, u32, ARMv5*);
-template void SlowBlockTransfer9<false, true>(u32, u64*, u32, ARMv5*);
-template void SlowBlockTransfer9<true, false>(u32, u64*, u32, ARMv5*);
-template void SlowBlockTransfer9<true, true>(u32, u64*, u32, ARMv5*);
-template void SlowBlockTransfer7<false, false>(u32 addr, u64* data, u32 num);
-template void SlowBlockTransfer7<false, true>(u32 addr, u64* data, u32 num);
-template void SlowBlockTransfer7<true, false>(u32 addr, u64* data, u32 num);
-template void SlowBlockTransfer7<true, true>(u32 addr, u64* data, u32 num);
+#define INSTANTIATE_SLOWMEM(consoleType) \
+ template void SlowWrite9<u32, consoleType>(u32, ARMv5*, u32); \
+ template void SlowWrite9<u16, consoleType>(u32, ARMv5*, u16); \
+ template void SlowWrite9<u8, consoleType>(u32, ARMv5*, u8); \
+ \
+ template u32 SlowRead9<u32, consoleType>(u32, ARMv5*); \
+ template u16 SlowRead9<u16, consoleType>(u32, ARMv5*); \
+ template u8 SlowRead9<u8, consoleType>(u32, ARMv5*); \
+ \
+ template void SlowWrite7<u32, consoleType>(u32, u32); \
+ template void SlowWrite7<u16, consoleType>(u32, u16); \
+ template void SlowWrite7<u8, consoleType>(u32, u8); \
+ \
+ template u32 SlowRead7<u32, consoleType>(u32); \
+ template u16 SlowRead7<u16, consoleType>(u32); \
+ template u8 SlowRead7<u8, consoleType>(u32); \
+ \
+ template void SlowBlockTransfer9<false, consoleType>(u32, u64*, u32, ARMv5*); \
+ template void SlowBlockTransfer9<true, consoleType>(u32, u64*, u32, ARMv5*); \
+ template void SlowBlockTransfer7<false, consoleType>(u32 addr, u64* data, u32 num); \
+ template void SlowBlockTransfer7<true, consoleType>(u32 addr, u64* data, u32 num); \
+
+INSTANTIATE_SLOWMEM(0)
+INSTANTIATE_SLOWMEM(1)
template <typename K, typename V, int Size, V InvalidValue>
struct UnreliableHashTable
@@ -616,6 +631,12 @@ void CompileBlock(ARM* cpu)
u32 blockAddr = cpu->R[15] - (thumb ? 2 : 4);
+ u32 localAddr = LocaliseCodeAddress(cpu->Num, blockAddr);
+ if (!localAddr)
+ {
+ printf("trying to compile non executable code? %x\n", blockAddr);
+ }
+
auto& map = cpu->Num == 0 ? JitBlocks9 : JitBlocks7;
auto existingBlockIt = map.find(blockAddr);
if (existingBlockIt != map.end())
@@ -623,18 +644,24 @@ void CompileBlock(ARM* cpu)
// there's already a block, though it's not inside the fast map
// could be that there are two blocks at the same physical addr
// but different mirrors
- u32 localAddr = existingBlockIt->second->StartAddrLocal;
+ u32 otherLocalAddr = existingBlockIt->second->StartAddrLocal;
- u64* entry = &FastBlockLookupRegions[localAddr >> 28][localAddr & 0xFFFFFFF];
- *entry = ((u64)blockAddr | cpu->Num) << 32;
- *entry |= JITCompiler->SubEntryOffset(existingBlockIt->second->EntryPoint);
- return;
- }
+ if (localAddr == otherLocalAddr)
+ {
+ JIT_DEBUGPRINT("switching out block %x %x %x\n", localAddr, blockAddr, existingBlockIt->second->StartAddr);
- u32 localAddr = LocaliseCodeAddress(cpu->Num, blockAddr);
- if (!localAddr)
- {
- printf("trying to compile non executable code? %x\n", blockAddr);
+ u64* entry = &FastBlockLookupRegions[localAddr >> 27][(localAddr & 0x7FFFFFF) / 2];
+ *entry = ((u64)blockAddr | cpu->Num) << 32;
+ *entry |= JITCompiler->SubEntryOffset(existingBlockIt->second->EntryPoint);
+ return;
+ }
+
+ // some memory has been remapped
+ JitBlock* prevBlock = RestoreCandidates.Insert(existingBlockIt->second->InstrHash, existingBlockIt->second);
+ if (prevBlock)
+ delete prevBlock;
+
+ map.erase(existingBlockIt);
}
FetchedInstr instrs[Config::JIT_MaxBlockSize];
@@ -655,7 +682,7 @@ void CompileBlock(ARM* cpu)
u32 nextInstr[2] = {cpu->NextInstr[0], cpu->NextInstr[1]};
u32 nextInstrAddr[2] = {blockAddr, r15};
- JIT_DEBUGPRINT("start block %x %08x (%x)\n", blockAddr, cpu->CPSR, pseudoPhysicalAddr);
+ JIT_DEBUGPRINT("start block %x %08x (%x)\n", blockAddr, cpu->CPSR, localAddr);
u32 lastSegmentStart = blockAddr;
u32 lr;
@@ -678,7 +705,7 @@ void CompileBlock(ARM* cpu)
instrValues[i] = instrs[i].Instr;
u32 translatedAddr = LocaliseCodeAddress(cpu->Num, instrs[i].Addr);
- assert(translatedAddr);
+ assert(translatedAddr >> 27);
u32 translatedAddrRounded = translatedAddr & ~0x1FF;
if (i == 0 || translatedAddrRounded != addressRanges[numAddressRanges - 1])
{
@@ -727,7 +754,10 @@ void CompileBlock(ARM* cpu)
cpu->CurInstr = instrs[i].Instr;
cpu->CodeCycles = instrs[i].CodeCycles;
- if (instrs[i].Info.DstRegs & (1 << 14))
+ if (instrs[i].Info.DstRegs & (1 << 14)
+ || (!thumb
+ && (instrs[i].Info.Kind == ARMInstrInfo::ak_MSR_IMM || instrs[i].Info.Kind == ARMInstrInfo::ak_MSR_REG)
+ && instrs[i].Instr & (1 << 16)))
hasLink = false;
if (thumb)
@@ -792,7 +822,7 @@ void CompileBlock(ARM* cpu)
i--;
}
- if (instrs[i].Info.Branches() && Config::JIT_BrancheOptimisations)
+ if (instrs[i].Info.Branches() && Config::JIT_BranchOptimisations)
{
bool hasBranched = cpu->R[15] != r15;
@@ -830,8 +860,6 @@ void CompileBlock(ARM* cpu)
}
else if (hasBranched && !isBackJump && i + 1 < Config::JIT_MaxBlockSize)
{
- u32 targetLocalised = LocaliseCodeAddress(cpu->Num, target);
-
if (link)
{
lr = linkAddr;
@@ -927,6 +955,8 @@ void CompileBlock(ARM* cpu)
FloodFillSetFlags(instrs, i - 1, 0xF);
block->EntryPoint = JITCompiler->CompileBlock(cpu, thumb, instrs, i);
+
+ JIT_DEBUGPRINT("block start %p\n", block->EntryPoint);
}
else
{
@@ -940,12 +970,12 @@ void CompileBlock(ARM* cpu)
assert(addressMasks[j] == block->AddressMasks()[j]);
assert(addressMasks[j] != 0);
- AddressRange* region = CodeMemRegions[addressRanges[j] >> 28];
+ AddressRange* region = CodeMemRegions[addressRanges[j] >> 27];
- if (!PageContainsCode(&region[(addressRanges[j] & 0xFFFF000) / 512]))
- ARMJIT_Memory::SetCodeProtection(addressRanges[j] >> 28, addressRanges[j] & 0xFFFFFFF, true);
+ if (!PageContainsCode(&region[(addressRanges[j] & 0x7FFF000) / 512]))
+ ARMJIT_Memory::SetCodeProtection(addressRanges[j] >> 27, addressRanges[j] & 0x7FFFFFF, true);
- AddressRange* range = &region[(addressRanges[j] & 0xFFFFFFF) / 512];
+ AddressRange* range = &region[(addressRanges[j] & 0x7FFFFFF) / 512];
range->Code |= addressMasks[j];
range->Blocks.Add(block);
}
@@ -955,7 +985,7 @@ void CompileBlock(ARM* cpu)
else
JitBlocks7[blockAddr] = block;
- u64* entry = &FastBlockLookupRegions[(localAddr >> 28)][(localAddr & 0xFFFFFFF) / 2];
+ u64* entry = &FastBlockLookupRegions[(localAddr >> 27)][(localAddr & 0x7FFFFFF) / 2];
*entry = ((u64)blockAddr | cpu->Num) << 32;
*entry |= JITCompiler->SubEntryOffset(block->EntryPoint);
}
@@ -964,8 +994,8 @@ void InvalidateByAddr(u32 localAddr)
{
JIT_DEBUGPRINT("invalidating by addr %x\n", localAddr);
- AddressRange* region = CodeMemRegions[localAddr >> 28];
- AddressRange* range = &region[(localAddr & 0xFFFFFFF) / 512];
+ AddressRange* region = CodeMemRegions[localAddr >> 27];
+ AddressRange* range = &region[(localAddr & 0x7FFFFFF) / 512];
u32 mask = 1 << ((localAddr & 0x1FF) / 16);
range->Code = 0;
@@ -994,9 +1024,9 @@ void InvalidateByAddr(u32 localAddr)
range->Blocks.Remove(i);
if (range->Blocks.Length == 0
- && !PageContainsCode(&region[(localAddr & 0xFFFF000) / 512]))
+ && !PageContainsCode(&region[(localAddr & 0x7FFF000) / 512]))
{
- ARMJIT_Memory::SetCodeProtection(localAddr >> 28, localAddr & 0xFFFFFFF, false);
+ ARMJIT_Memory::SetCodeProtection(localAddr >> 27, localAddr & 0x7FFFFFF, false);
}
bool literalInvalidation = false;
@@ -1019,8 +1049,8 @@ void InvalidateByAddr(u32 localAddr)
u32 addr = block->AddressRanges()[j];
if ((addr / 512) != (localAddr / 512))
{
- AddressRange* otherRegion = CodeMemRegions[addr >> 28];
- AddressRange* otherRange = &otherRegion[(addr & 0xFFFFFFF) / 512];
+ AddressRange* otherRegion = CodeMemRegions[addr >> 27];
+ AddressRange* otherRange = &otherRegion[(addr & 0x7FFFFFF) / 512];
assert(otherRange != range);
bool removed = otherRange->Blocks.RemoveByValue(block);
@@ -1028,15 +1058,15 @@ void InvalidateByAddr(u32 localAddr)
if (otherRange->Blocks.Length == 0)
{
- if (!PageContainsCode(&otherRegion[(addr & 0xFFFF000) / 512]))
- ARMJIT_Memory::SetCodeProtection(addr >> 28, addr & 0xFFFFFFF, false);
+ if (!PageContainsCode(&otherRegion[(addr & 0x7FFF000) / 512]))
+ ARMJIT_Memory::SetCodeProtection(addr >> 27, addr & 0x7FFFFFF, false);
otherRange->Code = 0;
}
}
}
- FastBlockLookupRegions[block->StartAddrLocal >> 28][(block->StartAddrLocal & 0xFFFFFFF) / 2] = (u64)UINT32_MAX << 32;
+ FastBlockLookupRegions[block->StartAddrLocal >> 27][(block->StartAddrLocal & 0x7FFFFFF) / 2] = (u64)UINT32_MAX << 32;
if (block->Num == 0)
JitBlocks9.erase(block->StartAddr);
else
@@ -1055,19 +1085,25 @@ void InvalidateByAddr(u32 localAddr)
}
}
-template <u32 num, int region>
-void CheckAndInvalidate(u32 addr)
+void CheckAndInvalidateITCM()
{
- // let's hope this gets all properly inlined
- u32 mappingStart, mappingSize, memoryOffset, memorySize;
- if (ARMJIT_Memory::GetRegionMapping(region, num, mappingStart, mappingSize, memoryOffset, memorySize))
+ for (u32 i = 0; i < ITCMPhysicalSize; i+=16)
{
- u32 localAddr = ((addr - mappingStart) & (memorySize - 1)) + memoryOffset;
- if (CodeMemRegions[region][localAddr / 512].Code & (1 << ((localAddr & 0x1FF) / 16)))
- InvalidateByAddr(localAddr | (region << 28));
+ if (CodeIndexITCM[i / 512].Code & (1 << ((i & 0x1FF) / 16)))
+ {
+ InvalidateByAddr(i | (ARMJIT_Memory::memregion_ITCM << 27));
+ }
}
}
+template <u32 num, int region>
+void CheckAndInvalidate(u32 addr)
+{
+ u32 localAddr = ARMJIT_Memory::LocaliseAddress(region, num, addr);
+ if (CodeMemRegions[region][(localAddr & 0x7FFFFFF) / 512].Code & (1 << ((localAddr & 0x1FF) / 16)))
+ InvalidateByAddr(localAddr);
+}
+
JitBlockEntry LookUpBlock(u32 num, u64* entries, u32 offset, u32 addr)
{
u64* entry = &entries[offset / 2];
@@ -1076,35 +1112,44 @@ JitBlockEntry LookUpBlock(u32 num, u64* entries, u32 offset, u32 addr)
return NULL;
}
+void blockSanityCheck(u32 num, u32 blockAddr, JitBlockEntry entry)
+{
+ u32 localAddr = LocaliseCodeAddress(num, blockAddr);
+ assert(JITCompiler->AddEntryOffset((u32)FastBlockLookupRegions[localAddr >> 27][(localAddr & 0x7FFFFFF) / 2]) == entry);
+}
+
bool SetupExecutableRegion(u32 num, u32 blockAddr, u64*& entry, u32& start, u32& size)
{
+ // amazingly ignoring the DTCM is the proper behaviour for code fetches
int region = num == 0
? ARMJIT_Memory::ClassifyAddress9(blockAddr)
: ARMJIT_Memory::ClassifyAddress7(blockAddr);
- u32 mappingStart, mappingSize, memoryOffset, memorySize;
- if (CodeMemRegions[region]
- && ARMJIT_Memory::GetRegionMapping(region, num, mappingStart,
- mappingSize, memoryOffset, memorySize))
+ u32 memoryOffset;
+ if (FastBlockLookupRegions[region]
+ && ARMJIT_Memory::GetMirrorLocation(region, num, blockAddr, memoryOffset, start, size))
{
+ //printf("setup exec region %d %d %08x %08x %x %x\n", num, region, blockAddr, start, size, memoryOffset);
entry = FastBlockLookupRegions[region] + memoryOffset / 2;
- // evil, though it should work for everything except DTCM which is not relevant here
- start = blockAddr & ~(memorySize - 1);
- size = memorySize;
return true;
}
- else
- return false;
+ return false;
}
template void CheckAndInvalidate<0, ARMJIT_Memory::memregion_MainRAM>(u32);
template void CheckAndInvalidate<1, ARMJIT_Memory::memregion_MainRAM>(u32);
-template void CheckAndInvalidate<0, ARMJIT_Memory::memregion_SWRAM>(u32);
-template void CheckAndInvalidate<1, ARMJIT_Memory::memregion_SWRAM>(u32);
+template void CheckAndInvalidate<0, ARMJIT_Memory::memregion_SharedWRAM>(u32);
+template void CheckAndInvalidate<1, ARMJIT_Memory::memregion_SharedWRAM>(u32);
template void CheckAndInvalidate<1, ARMJIT_Memory::memregion_WRAM7>(u32);
template void CheckAndInvalidate<1, ARMJIT_Memory::memregion_VWRAM>(u32);
template void CheckAndInvalidate<0, ARMJIT_Memory::memregion_VRAM>(u32);
template void CheckAndInvalidate<0, ARMJIT_Memory::memregion_ITCM>(u32);
+template void CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_A>(u32);
+template void CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_A>(u32);
+template void CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_B>(u32);
+template void CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_B>(u32);
+template void CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_C>(u32);
+template void CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_C>(u32);
void ResetBlockCache()
{
@@ -1133,7 +1178,7 @@ void ResetBlockCache()
for (int j = 0; j < block->NumAddresses; j++)
{
u32 addr = block->AddressRanges()[j];
- AddressRange* range = &CodeMemRegions[addr >> 28][(addr & 0xFFFFFFF) / 512];
+ AddressRange* range = &CodeMemRegions[addr >> 27][(addr & 0x7FFFFFF) / 512];
range->Blocks.Clear();
range->Code = 0;
}
@@ -1145,7 +1190,7 @@ void ResetBlockCache()
for (int j = 0; j < block->NumAddresses; j++)
{
u32 addr = block->AddressRanges()[j];
- AddressRange* range = &CodeMemRegions[addr >> 28][(addr & 0xFFFFFFF) / 512];
+ AddressRange* range = &CodeMemRegions[addr >> 27][(addr & 0x7FFFFFF) / 512];
range->Blocks.Clear();
range->Code = 0;
}
diff --git a/src/ARMJIT.h b/src/ARMJIT.h
index 2320b7b..04add59 100644
--- a/src/ARMJIT.h
+++ b/src/ARMJIT.h
@@ -16,6 +16,8 @@ void DeInit();
void Reset();
+void CheckAndInvalidateITCM();
+
void InvalidateByAddr(u32 pseudoPhysical);
template <u32 num, int region>
diff --git a/src/ARMJIT_A64/ARMJIT_LoadStore.cpp b/src/ARMJIT_A64/ARMJIT_LoadStore.cpp
index b307d0e..c1b23a7 100644
--- a/src/ARMJIT_A64/ARMJIT_LoadStore.cpp
+++ b/src/ARMJIT_A64/ARMJIT_LoadStore.cpp
@@ -168,7 +168,7 @@ void Compiler::Comp_MemAccess(int rd, int rn, Op2 offset, int size, int flags)
? ARMJIT_Memory::ClassifyAddress9(addrIsStatic ? staticAddress : CurInstr.DataRegion)
: ARMJIT_Memory::ClassifyAddress7(addrIsStatic ? staticAddress : CurInstr.DataRegion);
- if (Config::JIT_FastMemory && ((!Thumb && CurInstr.Cond() != 0xE) || ARMJIT_Memory::IsMappable(expectedTarget)))
+ if (Config::JIT_FastMemory && ((!Thumb && CurInstr.Cond() != 0xE) || ARMJIT_Memory::IsFastmemCompatible(expectedTarget)))
{
ptrdiff_t memopStart = GetCodeOffset();
LoadStorePatch patch;
@@ -461,7 +461,7 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc
: ARMJIT_Memory::ClassifyAddress7(CurInstr.DataRegion);
bool compileFastPath = Config::JIT_FastMemory
- && store && !usermode && (CurInstr.Cond() < 0xE || ARMJIT_Memory::IsMappable(expectedTarget));
+ && store && !usermode && (CurInstr.Cond() < 0xE || ARMJIT_Memory::IsFastmemCompatible(expectedTarget));
if (decrement)
{
diff --git a/src/ARMJIT_Internal.h b/src/ARMJIT_Internal.h
index 19684c4..c87e1b3 100644
--- a/src/ARMJIT_Internal.h
+++ b/src/ARMJIT_Internal.h
@@ -214,13 +214,13 @@ u32 LocaliseCodeAddress(u32 num, u32 addr);
template <u32 Num>
void LinkBlock(ARM* cpu, u32 codeOffset);
-template <typename T> T SlowRead9(u32 addr, ARMv5* cpu);
-template <typename T> void SlowWrite9(u32 addr, ARMv5* cpu, T val);
-template <typename T> T SlowRead7(u32 addr);
-template <typename T> void SlowWrite7(u32 addr, T val);
+template <typename T, int ConsoleType> T SlowRead9(u32 addr, ARMv5* cpu);
+template <typename T, int ConsoleType> void SlowWrite9(u32 addr, ARMv5* cpu, T val);
+template <typename T, int ConsoleType> T SlowRead7(u32 addr);
+template <typename T, int ConsoleType> void SlowWrite7(u32 addr, T val);
-template <bool PreInc, bool Write> void SlowBlockTransfer9(u32 addr, u64* data, u32 num, ARMv5* cpu);
-template <bool PreInc, bool Write> void SlowBlockTransfer7(u32 addr, u64* data, u32 num);
+template <bool Write, int ConsoleType> void SlowBlockTransfer9(u32 addr, u64* data, u32 num, ARMv5* cpu);
+template <bool Write, int ConsoleType> void SlowBlockTransfer7(u32 addr, u64* data, u32 num);
}
diff --git a/src/ARMJIT_Memory.cpp b/src/ARMJIT_Memory.cpp
index 162827d..0276c65 100644
--- a/src/ARMJIT_Memory.cpp
+++ b/src/ARMJIT_Memory.cpp
@@ -1,5 +1,7 @@
-#ifdef __SWITCH__
+#if defined(__SWITCH__)
#include "switch/compat_switch.h"
+#elif defined(_WIN32)
+#include <windows.h>
#endif
#include "ARMJIT_Memory.h"
@@ -7,6 +9,7 @@
#include "ARMJIT_Internal.h"
#include "ARMJIT_Compiler.h"
+#include "DSi.h"
#include "GPU.h"
#include "GPU3D.h"
#include "Wifi.h"
@@ -37,66 +40,24 @@
namespace ARMJIT_Memory
{
-#ifdef __aarch64__
-struct FaultDescription
-{
- u64 IntegerRegisters[33];
- u64 FaultAddr;
-
- u32 GetEmulatedAddr()
- {
- // now this is podracing
- return (u32)IntegerRegisters[0];
- }
- u64 RealAddr()
- {
- return FaultAddr;
- }
-
- u64 GetPC()
- {
- return IntegerRegisters[32];
- }
-
- void RestoreAndRepeat(s64 offset);
-};
-#else
struct FaultDescription
{
- u64 GetPC()
- {
- return 0;
- }
-
- u32 GetEmulatedAddr()
- {
- return 0;
- }
- u64 RealAddr()
- {
- return 0;
- }
-
- void RestoreAndRepeat(s64 offset);
+ u32 EmulatedFaultAddr;
+ u64 FaultPC;
};
-#endif
-void FaultHandler(FaultDescription* faultDesc);
+bool FaultHandler(FaultDescription* faultDesc, s32& offset);
}
-
-#ifdef __aarch64__
-
-extern "C" void ARM_RestoreContext(u64* registers) __attribute__((noreturn));
-
-#endif
-
-#ifdef __SWITCH__
+#if defined(__SWITCH__)
// with LTO the symbols seem to be not properly overriden
// if they're somewhere else
extern "C"
{
+
+void ARM_RestoreContext(u64* registers) __attribute__((noreturn));
+
extern char __start__;
extern char __rodata_start;
@@ -106,57 +67,85 @@ u64 __nx_exception_stack_size = 0x8000;
void __libnx_exception_handler(ThreadExceptionDump* ctx)
{
ARMJIT_Memory::FaultDescription desc;
- memcpy(desc.IntegerRegisters, &ctx->cpu_gprs[0].x, 8*29);
- desc.IntegerRegisters[29] = ctx->fp.x;
- desc.IntegerRegisters[30] = ctx->lr.x;
- desc.IntegerRegisters[31] = ctx->sp.x;
- desc.IntegerRegisters[32] = ctx->pc.x;
+ desc.EmulatedFaultAddr = ctx->cpu_gprs[0].w;
+ desc.FaultPC = ctx->pc.x;
+
+ u64 integerRegisters[33];
+ memcpy(integerRegisters, &ctx->cpu_gprs[0].x, 8*29);
+ integerRegisters[29] = ctx->fp.x;
+ integerRegisters[30] = ctx->lr.x;
+ integerRegisters[31] = ctx->sp.x;
+ integerRegisters[32] = ctx->pc.x;
+
+ s32 offset;
+ if (ARMJIT_Memory::FaultHandler(&desc, offset))
+ {
+ integerRegisters[32] += offset;
- ARMJIT_Memory::FaultHandler(&desc);
+ ARM_RestoreContext(integerRegisters);
+ }
if (ctx->pc.x >= (u64)&__start__ && ctx->pc.x < (u64)&__rodata_start)
{
- printf("non JIT fault in .text at 0x%x (type %d) (trying to access 0x%x?)\n",
+ printf("unintentional fault in .text at 0x%x (type %d) (trying to access 0x%x?)\n",
ctx->pc.x - (u64)&__start__, ctx->error_desc, ctx->far.x);
}
else
{
- printf("non JIT fault somewhere in deep (address) space at %x (type %d)\n", ctx->pc.x, ctx->error_desc);
+ printf("unintentional fault somewhere in deep (address) space at %x (type %d)\n", ctx->pc.x, ctx->error_desc);
}
}
}
+
+#elif defined(_WIN32)
+
+static LONG ExceptionHandler(EXCEPTION_POINTERS* exceptionInfo)
+{
+ if (exceptionInfo->ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION)
+ return EXCEPTION_CONTINUE_SEARCH;
+
+ ARMJIT_Memory::FaultDescription desc;
+ desc.EmulatedFaultAddr = exceptionInfo->ContextRecord->Rcx;
+ desc.FaultPC = exceptionInfo->ContextRecord->Rip;
+
+ s32 offset = 0;
+ if (ARMJIT_Memory::FaultHandler(&desc, offset))
+ {
+ exceptionInfo->ContextRecord->Rip += offset;
+ return EXCEPTION_CONTINUE_EXECUTION;
+ }
+
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+
#endif
namespace ARMJIT_Memory
{
-#ifdef __aarch64__
-void FaultDescription::RestoreAndRepeat(s64 offset)
-{
- IntegerRegisters[32] += offset;
+void* FastMem9Start, *FastMem7Start;
- ARM_RestoreContext(IntegerRegisters);
+#ifdef _WIN32
+inline u32 RoundUp(u32 size)
+{
+ return (size + 0xFFFF) & ~0xFFFF;
}
#else
-void FaultDescription::RestoreAndRepeat(s64 offset)
+inline u32 RoundUp(u32 size)
{
-
+ return size;
}
#endif
-void* FastMem9Start, *FastMem7Start;
-
-const u32 MemoryTotalSize =
- NDS::MainRAMSize
- + NDS::SharedWRAMSize
- + NDS::ARM7WRAMSize
- + DTCMPhysicalSize;
-
const u32 MemBlockMainRAMOffset = 0;
-const u32 MemBlockSWRAMOffset = NDS::MainRAMSize;
-const u32 MemBlockARM7WRAMOffset = NDS::MainRAMSize + NDS::SharedWRAMSize;
-const u32 MemBlockDTCMOffset = NDS::MainRAMSize + NDS::SharedWRAMSize + NDS::ARM7WRAMSize;
+const u32 MemBlockSWRAMOffset = RoundUp(NDS::MainRAMMaxSize);
+const u32 MemBlockARM7WRAMOffset = MemBlockSWRAMOffset + RoundUp(NDS::SharedWRAMSize);
+const u32 MemBlockDTCMOffset = MemBlockARM7WRAMOffset + RoundUp(NDS::ARM7WRAMSize);
+const u32 MemBlockNWRAM_AOffset = MemBlockDTCMOffset + RoundUp(DTCMPhysicalSize);
+const u32 MemBlockNWRAM_BOffset = MemBlockNWRAM_AOffset + RoundUp(DSi::NWRAMSize);
+const u32 MemBlockNWRAM_COffset = MemBlockNWRAM_BOffset + RoundUp(DSi::NWRAMSize);
+const u32 MemoryTotalSize = MemBlockNWRAM_COffset + RoundUp(DSi::NWRAMSize);
const u32 OffsetsPerRegion[memregions_Count] =
{
@@ -173,6 +162,11 @@ const u32 OffsetsPerRegion[memregions_Count] =
UINT32_MAX,
UINT32_MAX,
UINT32_MAX,
+ UINT32_MAX,
+ UINT32_MAX,
+ MemBlockNWRAM_AOffset,
+ MemBlockNWRAM_BOffset,
+ MemBlockNWRAM_COffset
};
enum
@@ -186,11 +180,13 @@ enum
u8 MappingStatus9[1 << (32-12)];
u8 MappingStatus7[1 << (32-12)];
-#ifdef __SWITCH__
+#if defined(__SWITCH__)
u8* MemoryBase;
u8* MemoryBaseCodeMem;
-#else
+#elif defined(_WIN32)
u8* MemoryBase;
+HANDLE MemoryFile;
+LPVOID ExceptionHandlerHandle;
#endif
bool MapIntoRange(u32 addr, u32 num, u32 offset, u32 size)
@@ -200,6 +196,9 @@ bool MapIntoRange(u32 addr, u32 num, u32 offset, u32 size)
Result r = (svcMapProcessMemory(dst, envGetOwnProcessHandle(),
(u64)(MemoryBaseCodeMem + offset), size));
return R_SUCCEEDED(r);
+#elif defined(_WIN32)
+ bool r = MapViewOfFileEx(MemoryFile, FILE_MAP_READ | FILE_MAP_WRITE, 0, offset, size, dst) == dst;
+ return r;
#endif
}
@@ -209,8 +208,24 @@ bool UnmapFromRange(u32 addr, u32 num, u32 offset, u32 size)
#ifdef __SWITCH__
Result r = svcUnmapProcessMemory(dst, envGetOwnProcessHandle(),
(u64)(MemoryBaseCodeMem + offset), size);
- printf("%x\n", r);
return R_SUCCEEDED(r);
+#else
+ return UnmapViewOfFile(dst);
+#endif
+}
+
+void SetCodeProtectionRange(u32 addr, u32 size, u32 num, int protection)
+{
+ u8* dst = (u8*)(num == 0 ? FastMem9Start : FastMem7Start) + addr;
+#if defined(_WIN32)
+ DWORD winProtection, oldProtection;
+ if (protection == 0)
+ winProtection = PAGE_NOACCESS;
+ else if (protection == 1)
+ winProtection = PAGE_READONLY;
+ else
+ winProtection = PAGE_READWRITE;
+ VirtualProtect(dst, size, winProtection, &oldProtection);
#endif
}
@@ -230,7 +245,6 @@ struct Mapping
if (skipDTCM && Addr + offset == NDS::ARM9->DTCMBase)
{
offset += NDS::ARM9->DTCMSize;
- printf("%x skip\n", NDS::ARM9->DTCMSize);
}
else
{
@@ -245,6 +259,7 @@ struct Mapping
offset += 0x1000;
}
+#ifdef __SWITCH__
if (status == memstate_MappedRW)
{
u32 segmentSize = offset - segmentOffset;
@@ -252,8 +267,12 @@ struct Mapping
bool success = UnmapFromRange(Addr + segmentOffset, Num, segmentOffset + LocalOffset + OffsetsPerRegion[region], segmentSize);
assert(success);
}
+#endif
}
}
+#if defined(_WIN32)
+ UnmapFromRange(Addr, Num, OffsetsPerRegion[region] + LocalOffset, Size);
+#endif
}
};
ARMJIT::TinyVector<Mapping> Mappings[memregions_Count];
@@ -268,6 +287,8 @@ void SetCodeProtection(int region, u32 offset, bool protect)
Mapping& mapping = Mappings[region][i];
u32 effectiveAddr = mapping.Addr + (offset - mapping.LocalOffset);
+ if (offset < mapping.LocalOffset || offset >= mapping.LocalOffset + mapping.Size)
+ continue;
if (mapping.Num == 0
&& region != memregion_DTCM
&& effectiveAddr >= NDS::ARM9->DTCMBase
@@ -276,16 +297,20 @@ void SetCodeProtection(int region, u32 offset, bool protect)
u8* states = (u8*)(mapping.Num == 0 ? MappingStatus9 : MappingStatus7);
- printf("%d %x %d\n", states[effectiveAddr >> 12], effectiveAddr, mapping.Num);
+ printf("%x %d %x %x %x %d\n", effectiveAddr, mapping.Num, mapping.Addr, mapping.LocalOffset, mapping.Size, states[effectiveAddr >> 12]);
assert(states[effectiveAddr >> 12] == (protect ? memstate_MappedRW : memstate_MappedProtected));
states[effectiveAddr >> 12] = protect ? memstate_MappedProtected : memstate_MappedRW;
+#if defined(__SWITCH__)
bool success;
if (protect)
success = UnmapFromRange(effectiveAddr, mapping.Num, OffsetsPerRegion[region] + offset, 0x1000);
else
success = MapIntoRange(effectiveAddr, mapping.Num, OffsetsPerRegion[region] + offset, 0x1000);
assert(success);
+#elif defined(_WIN32)
+ SetCodeProtectionRange(effectiveAddr, 0x1000, mapping.Num, protect ? 1 : 2);
+#endif
}
}
@@ -314,8 +339,8 @@ void RemapDTCM(u32 newBase, u32 newSize)
printf("mapping %d %x %x %x %x\n", region, mapping.Addr, mapping.Size, mapping.Num, mapping.LocalOffset);
- bool oldOverlap = NDS::ARM9->DTCMSize > 0 && ((oldDTCMBase >= start && oldDTCMBase < end) || (oldDTCBEnd >= start && oldDTCBEnd < end));
- bool newOverlap = newSize > 0 && ((newBase >= start && newBase < end) || (newEnd >= start && newEnd < end));
+ bool oldOverlap = NDS::ARM9->DTCMSize > 0 && !(oldDTCMBase >= end || oldDTCBEnd < start);
+ bool newOverlap = newSize > 0 && !(newBase >= end || newEnd < start);
if (mapping.Num == 0 && (oldOverlap || newOverlap))
{
@@ -336,19 +361,50 @@ void RemapDTCM(u32 newBase, u32 newSize)
Mappings[memregion_DTCM].Clear();
}
+void RemapNWRAM(int num)
+{
+ for (int i = 0; i < Mappings[memregion_SharedWRAM].Length;)
+ {
+ Mapping& mapping = Mappings[memregion_SharedWRAM][i];
+ if (!(DSi::NWRAMStart[mapping.Num][num] >= mapping.Addr + mapping.Size
+ || DSi::NWRAMEnd[mapping.Num][num] < mapping.Addr))
+ {
+ mapping.Unmap(memregion_SharedWRAM);
+ Mappings[memregion_SharedWRAM].Remove(i);
+ }
+ else
+ {
+ i++;
+ }
+ }
+ for (int i = 0; i < Mappings[memregion_NewSharedWRAM_A + num].Length; i++)
+ {
+ Mappings[memregion_NewSharedWRAM_A + num][i].Unmap(memregion_NewSharedWRAM_A + num);
+ }
+ Mappings[memregion_NewSharedWRAM_A + num].Clear();
+}
+
void RemapSWRAM()
{
printf("remapping SWRAM\n");
- for (int i = 0; i < Mappings[memregion_SWRAM].Length; i++)
+ for (int i = 0; i < Mappings[memregion_SharedWRAM].Length; i++)
{
- Mappings[memregion_SWRAM][i].Unmap(memregion_SWRAM);
+ Mappings[memregion_SharedWRAM][i].Unmap(memregion_SharedWRAM);
}
- Mappings[memregion_SWRAM].Clear();
+ Mappings[memregion_SharedWRAM].Clear();
for (int i = 0; i < Mappings[memregion_WRAM7].Length; i++)
{
Mappings[memregion_WRAM7][i].Unmap(memregion_WRAM7);
}
Mappings[memregion_WRAM7].Clear();
+ for (int j = 0; j < 3; j++)
+ {
+ for (int i = 0; i < Mappings[memregion_NewSharedWRAM_A + j].Length; i++)
+ {
+ Mappings[memregion_NewSharedWRAM_A + j][i].Unmap(memregion_NewSharedWRAM_A + j);
+ }
+ Mappings[memregion_NewSharedWRAM_A + j].Clear();
+ }
}
bool MapAtAddress(u32 addr)
@@ -359,33 +415,36 @@ bool MapAtAddress(u32 addr)
? ClassifyAddress9(addr)
: ClassifyAddress7(addr);
- if (!IsMappable(region))
+ if (!IsFastmemCompatible(region))
return false;
- u32 mappingStart, mappingSize, memoryOffset, memorySize;
- bool isMapped = GetRegionMapping(region, num, mappingStart, mappingSize, memoryOffset, memorySize);
+ return false;
+ u32 mirrorStart, mirrorSize, memoryOffset;
+ bool isMapped = GetMirrorLocation(region, num, addr, memoryOffset, mirrorStart, mirrorSize);
if (!isMapped)
return false;
- // this calculation even works with DTCM
- // which doesn't have to be aligned to it's own size
- u32 mirrorStart = (addr - mappingStart) / memorySize * memorySize + mappingStart;
-
u8* states = num == 0 ? MappingStatus9 : MappingStatus7;
- printf("trying to create mapping %08x %d %x %d %x\n", addr, num, memorySize, region, memoryOffset);
+ printf("trying to create mapping %x, %x %d %d\n", mirrorStart, mirrorSize, region, num);
bool isExecutable = ARMJIT::CodeMemRegions[region];
- ARMJIT::AddressRange* range = ARMJIT::CodeMemRegions[region] + memoryOffset;
+#if defined(_WIN32)
+ bool succeded = MapIntoRange(mirrorStart, num, OffsetsPerRegion[region] + memoryOffset, mirrorSize);
+ assert(succeded);
+#endif
+
+ ARMJIT::AddressRange* range = ARMJIT::CodeMemRegions[region] + memoryOffset / 512;
// this overcomplicated piece of code basically just finds whole pieces of code memory
// which can be mapped
u32 offset = 0;
bool skipDTCM = num == 0 && region != memregion_DTCM;
- while (offset < memorySize)
+ while (offset < mirrorSize)
{
if (skipDTCM && mirrorStart + offset == NDS::ARM9->DTCMBase)
{
+ SetCodeProtectionRange(NDS::ARM9->DTCMBase, NDS::ARM9->DTCMSize, 0, 0);
offset += NDS::ARM9->DTCMSize;
}
else
@@ -393,7 +452,7 @@ bool MapAtAddress(u32 addr)
u32 sectionOffset = offset;
bool hasCode = isExecutable && ARMJIT::PageContainsCode(&range[offset / 512]);
while ((!isExecutable || ARMJIT::PageContainsCode(&range[offset / 512]) == hasCode)
- && offset < memorySize
+ && offset < mirrorSize
&& (!skipDTCM || mirrorStart + offset != NDS::ARM9->DTCMBase))
{
assert(states[(mirrorStart + offset) >> 12] == memstate_Unmapped);
@@ -403,41 +462,49 @@ bool MapAtAddress(u32 addr)
u32 sectionSize = offset - sectionOffset;
+#if defined(__SWITCH__)
if (!hasCode)
{
printf("trying to map %x (size: %x) from %x\n", mirrorStart + sectionOffset, sectionSize, sectionOffset + memoryOffset + OffsetsPerRegion[region]);
bool succeded = MapIntoRange(mirrorStart + sectionOffset, num, sectionOffset + memoryOffset + OffsetsPerRegion[region], sectionSize);
assert(succeded);
}
+#elif defined(_WIN32)
+ if (hasCode)
+ {
+ SetCodeProtectionRange(mirrorStart + offset, sectionSize, num, 1);
+ }
+#endif
}
}
- Mapping mapping{mirrorStart, memorySize, memoryOffset, num};
+ assert(num == 0 || num == 1);
+ Mapping mapping{mirrorStart, mirrorSize, memoryOffset, num};
Mappings[region].Add(mapping);
- printf("mapped mirror at %08x-%08x\n", mirrorStart, mirrorStart + memorySize - 1);
+ printf("mapped mirror at %08x-%08x\n", mirrorStart, mirrorStart + mirrorSize - 1);
return true;
}
-void FaultHandler(FaultDescription* faultDesc)
+bool FaultHandler(FaultDescription* faultDesc, s32& offset)
{
- if (ARMJIT::JITCompiler->IsJITFault(faultDesc->GetPC()))
+ if (ARMJIT::JITCompiler->IsJITFault(faultDesc->FaultPC))
{
bool rewriteToSlowPath = true;
- u32 addr = faultDesc->GetEmulatedAddr();
+ u32 addr = faultDesc->EmulatedFaultAddr;
if ((NDS::CurCPU == 0 ? MappingStatus9 : MappingStatus7)[addr >> 12] == memstate_Unmapped)
- rewriteToSlowPath = !MapAtAddress(faultDesc->GetEmulatedAddr());
+ rewriteToSlowPath = !MapAtAddress(faultDesc->EmulatedFaultAddr);
- s64 offset = 0;
if (rewriteToSlowPath)
{
- offset = ARMJIT::JITCompiler->RewriteMemAccess(faultDesc->GetPC());
+ offset = ARMJIT::JITCompiler->RewriteMemAccess(faultDesc->FaultPC);
}
- faultDesc->RestoreAndRepeat(offset);
+ return true;
}
+ return false;
}
void Init()
@@ -459,18 +526,34 @@ void Init()
FastMem7Start = virtmemReserve(0x100000000);
assert(FastMem7Start);
- NDS::MainRAM = MemoryBaseCodeMem + MemBlockMainRAMOffset;
- NDS::SharedWRAM = MemoryBaseCodeMem + MemBlockSWRAMOffset;
- NDS::ARM7WRAM = MemoryBaseCodeMem + MemBlockARM7WRAMOffset;
- NDS::ARM9->DTCM = MemoryBaseCodeMem + MemBlockDTCMOffset;
-#else
- MemoryBase = new u8[MemoryTotalSize];
+ u8* basePtr = MemoryBaseCodeMem;
+#elif defined(_WIN32)
+ ExceptionHandlerHandle = AddVectoredExceptionHandler(1, ExceptionHandler);
+
+ MemoryFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, MemoryTotalSize, NULL);
- NDS::MainRAM = MemoryBase + MemBlockMainRAMOffset;
- NDS::SharedWRAM = MemoryBase + MemBlockSWRAMOffset;
- NDS::ARM7WRAM = MemoryBase + MemBlockARM7WRAMOffset;
- NDS::ARM9->DTCM = MemoryBase + MemBlockDTCMOffset;
+ MemoryBase = (u8*)VirtualAlloc(NULL, MemoryTotalSize, MEM_RESERVE, PAGE_READWRITE);
+
+ FastMem9Start = VirtualAlloc(NULL, 0x100000000, MEM_RESERVE, PAGE_READWRITE);
+ FastMem7Start = VirtualAlloc(NULL, 0x100000000, MEM_RESERVE, PAGE_READWRITE);
+
+ // only free them after they have all been reserved
+ // so they can't overlap
+ VirtualFree(MemoryBase, 0, MEM_RELEASE);
+ VirtualFree(FastMem9Start, 0, MEM_RELEASE);
+ VirtualFree(FastMem7Start, 0, MEM_RELEASE);
+
+ MapViewOfFileEx(MemoryFile, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, MemoryTotalSize, MemoryBase);
+
+ u8* basePtr = MemoryBase;
#endif
+ NDS::MainRAM = basePtr + MemBlockMainRAMOffset;
+ NDS::SharedWRAM = basePtr + MemBlockSWRAMOffset;
+ NDS::ARM7WRAM = basePtr + MemBlockARM7WRAMOffset;
+ NDS::ARM9->DTCM = basePtr + MemBlockDTCMOffset;
+ DSi::NWRAM_A = basePtr + MemBlockNWRAM_AOffset;
+ DSi::NWRAM_B = basePtr + MemBlockNWRAM_BOffset;
+ DSi::NWRAM_C = basePtr + MemBlockNWRAM_COffset;
}
void DeInit()
@@ -482,8 +565,11 @@ void DeInit()
svcUnmapProcessCodeMemory(envGetOwnProcessHandle(), (u64)MemoryBaseCodeMem, (u64)MemoryBase, MemoryTotalSize);
virtmemFree(MemoryBaseCodeMem, MemoryTotalSize);
free(MemoryBase);
-#else
- delete[] MemoryBase;
+#elif defined(_WIN32)
+ assert(UnmapViewOfFile(MemoryBase));
+ CloseHandle(MemoryFile);
+
+ RemoveVectoredExceptionHandler(ExceptionHandlerHandle);
#endif
}
@@ -505,12 +591,23 @@ void Reset()
printf("done resetting jit mem\n");
}
-bool IsMappable(int region)
+bool IsFastmemCompatible(int region)
{
+#ifdef _WIN32
+ /*
+ TODO: with some hacks, the smaller shared WRAM regions
+ could be mapped in some occaisons as well
+ */
+ if (region == memregion_DTCM
+ || region == memregion_SharedWRAM
+ || region == memregion_NewSharedWRAM_B
+ || region == memregion_NewSharedWRAM_C)
+ return false;
+#endif
return OffsetsPerRegion[region] != UINT32_MAX;
}
-bool GetRegionMapping(int region, u32 num, u32& mappingStart, u32& mappingSize, u32& memoryOffset, u32& memorySize)
+bool GetMirrorLocation(int region, u32 num, u32 addr, u32& memoryOffset, u32& mirrorStart, u32& mirrorSize)
{
memoryOffset = 0;
switch (region)
@@ -518,137 +615,251 @@ bool GetRegionMapping(int region, u32 num, u32& mappingStart, u32& mappingSize,
case memregion_ITCM:
if (num == 0)
{
- mappingStart = 0;
- mappingSize = NDS::ARM9->ITCMSize;
- memorySize = ITCMPhysicalSize;
+ mirrorStart = addr & ~(ITCMPhysicalSize - 1);
+ mirrorSize = ITCMPhysicalSize;
return true;
}
return false;
- case memregion_DTCM:
+ case memregion_MainRAM:
+ mirrorStart = addr & ~NDS::MainRAMMask;
+ mirrorSize = NDS::MainRAMMask + 1;
+ return true;
+ case memregion_BIOS9:
if (num == 0)
{
- mappingStart = NDS::ARM9->DTCMBase;
- mappingSize = NDS::ARM9->DTCMSize;
- memorySize = DTCMPhysicalSize;
+ mirrorStart = addr & ~0xFFF;
+ mirrorSize = 0x1000;
return true;
}
return false;
- case memregion_BIOS9:
- if (num == 0)
+ case memregion_BIOS7:
+ if (num == 1)
{
- mappingStart = 0xFFFF0000;
- mappingSize = 0x10000;
- memorySize = 0x1000;
+ mirrorStart = 0;
+ mirrorSize = 0x4000;
return true;
}
return false;
- case memregion_MainRAM:
- mappingStart = 0x2000000;
- mappingSize = 0x1000000;
- memorySize = NDS::MainRAMSize;
- return true;
- case memregion_SWRAM:
- mappingStart = 0x3000000;
+ case memregion_SharedWRAM:
if (num == 0 && NDS::SWRAM_ARM9.Mem)
{
- mappingSize = 0x1000000;
+ mirrorStart = addr & ~NDS::SWRAM_ARM9.Mask;
+ mirrorSize = NDS::SWRAM_ARM9.Mask + 1;
memoryOffset = NDS::SWRAM_ARM9.Mem - NDS::SharedWRAM;
- memorySize = NDS::SWRAM_ARM9.Mask + 1;
return true;
}
else if (num == 1 && NDS::SWRAM_ARM7.Mem)
{
- mappingSize = 0x800000;
+ mirrorStart = addr & ~NDS::SWRAM_ARM7.Mask;
+ mirrorSize = NDS::SWRAM_ARM7.Mask + 1;
memoryOffset = NDS::SWRAM_ARM7.Mem - NDS::SharedWRAM;
- memorySize = NDS::SWRAM_ARM7.Mask + 1;
+ return true;
+ }
+ return false;
+ case memregion_WRAM7:
+ if (num == 1)
+ {
+ mirrorStart = addr & ~(NDS::ARM7WRAMSize - 1);
+ mirrorSize = NDS::ARM7WRAMSize;
return true;
}
return false;
case memregion_VRAM:
if (num == 0)
{
- // this is a gross simplification
- // mostly to make code on vram working
- // it doesn't take any of the actual VRAM mappings into account
- mappingStart = 0x6000000;
- mappingSize = 0x1000000;
- memorySize = 0x100000;
- return true;
+ mirrorStart = addr & ~0xFFFFF;
+ mirrorSize = 0x100000;
}
return false;
- case memregion_BIOS7:
+ case memregion_VWRAM:
if (num == 1)
{
- mappingStart = 0;
- mappingSize = 0x4000;
- memorySize = 0x4000;
+ mirrorStart = addr & ~0x3FFFF;
+ mirrorSize = 0x40000;
return true;
}
return false;
- case memregion_WRAM7:
- if (num == 1)
+ case memregion_NewSharedWRAM_A:
{
- if (NDS::SWRAM_ARM7.Mem)
+ u8* ptr = DSi::NWRAMMap_A[num][(addr >> 16) & DSi::NWRAMMask[num][0]];
+ if (ptr)
{
- mappingStart = 0x3800000;
- mappingSize = 0x800000;
+ memoryOffset = ptr - DSi::NWRAM_A;
+ mirrorStart = addr & ~0xFFFF;
+ mirrorSize = 0x10000;
+ return true;
}
- else
+ return false; // zero filled memory
+ }
+ case memregion_NewSharedWRAM_B:
+ {
+ u8* ptr = DSi::NWRAMMap_B[num][(addr >> 15) & DSi::NWRAMMask[num][1]];
+ if (ptr)
{
- mappingStart = 0x3000000;
- mappingSize = 0x1000000;
+ memoryOffset = ptr - DSi::NWRAM_B;
+ mirrorStart = addr & ~0x7FFF;
+ mirrorSize = 0x8000;
+ return true;
}
- memorySize = NDS::ARM7WRAMSize;
+ return false; // zero filled memory
+ }
+ case memregion_NewSharedWRAM_C:
+ {
+ u8* ptr = DSi::NWRAMMap_C[num][(addr >> 15) & DSi::NWRAMMask[num][2]];
+ if (ptr)
+ {
+ memoryOffset = ptr - DSi::NWRAM_C;
+ mirrorStart = addr & ~0x7FFF;
+ mirrorSize = 0x8000;
+ return true;
+ }
+ return false; // zero filled memory
+ }
+ case memregion_BIOS9DSi:
+ if (num == 0)
+ {
+ mirrorStart = addr & ~0xFFFF;
+ mirrorSize = DSi::SCFG_BIOS & (1<<0) ? 0x8000 : 0x10000;
return true;
}
return false;
- case memregion_VWRAM:
+ case memregion_BIOS7DSi:
if (num == 1)
{
- mappingStart = 0x6000000;
- mappingSize = 0x1000000;
- memorySize = 0x20000;
+ mirrorStart = addr & ~0xFFFF;
+ mirrorSize = DSi::SCFG_BIOS & (1<<8) ? 0x8000 : 0x10000;
return true;
}
return false;
default:
- // for the JIT we don't are about the rest
+ assert(false && "For the time being this should only be used for code");
return false;
}
}
+u32 LocaliseAddress(int region, u32 num, u32 addr)
+{
+ switch (region)
+ {
+ case memregion_ITCM:
+ return (addr & (ITCMPhysicalSize - 1)) | (memregion_ITCM << 27);
+ case memregion_MainRAM:
+ return (addr & NDS::MainRAMMask) | (memregion_MainRAM << 27);
+ case memregion_BIOS9:
+ return (addr & 0xFFF) | (memregion_BIOS9 << 27);
+ case memregion_BIOS7:
+ return (addr & 0x3FFF) | (memregion_BIOS7 << 27);
+ case memregion_SharedWRAM:
+ if (num == 0)
+ return ((addr & NDS::SWRAM_ARM9.Mask) + (NDS::SWRAM_ARM9.Mem - NDS::SharedWRAM)) | (memregion_SharedWRAM << 27);
+ else
+ return ((addr & NDS::SWRAM_ARM7.Mask) + (NDS::SWRAM_ARM7.Mem - NDS::SharedWRAM)) | (memregion_SharedWRAM << 27);
+ case memregion_WRAM7:
+ return (addr & (NDS::ARM7WRAMSize - 1)) | (memregion_WRAM7 << 27);
+ case memregion_VRAM:
+ // TODO: take mapping properly into account
+ return (addr & 0xFFFFF) | (memregion_VRAM << 27);
+ case memregion_VWRAM:
+ // same here
+ return (addr & 0x3FFFF) | (memregion_VWRAM << 27);
+ case memregion_NewSharedWRAM_A:
+ {
+ u8* ptr = DSi::NWRAMMap_A[num][(addr >> 16) & DSi::NWRAMMask[num][0]];
+ if (ptr)
+ return (ptr - DSi::NWRAM_A + (addr & 0xFFFF)) | (memregion_NewSharedWRAM_A << 27);
+ else
+ return memregion_Other << 27; // zero filled memory
+ }
+ case memregion_NewSharedWRAM_B:
+ {
+ u8* ptr = DSi::NWRAMMap_B[num][(addr >> 15) & DSi::NWRAMMask[num][1]];
+ if (ptr)
+ return (ptr - DSi::NWRAM_B + (addr & 0x7FFF)) | (memregion_NewSharedWRAM_B << 27);
+ else
+ return memregion_Other << 27;
+ }
+ case memregion_NewSharedWRAM_C:
+ {
+ u8* ptr = DSi::NWRAMMap_C[num][(addr >> 15) & DSi::NWRAMMask[num][2]];
+ if (ptr)
+ return (ptr - DSi::NWRAM_C + (addr & 0x7FFF)) | (memregion_NewSharedWRAM_C << 27);
+ else
+ return memregion_Other << 27;
+ }
+ case memregion_BIOS9DSi:
+ case memregion_BIOS7DSi:
+ return (addr & 0xFFFF) | (region << 27);
+ default:
+ assert(false && "This should only be needed for regions which can contain code");
+ return memregion_Other << 27;
+ }
+}
+
int ClassifyAddress9(u32 addr)
{
if (addr < NDS::ARM9->ITCMSize)
+ {
return memregion_ITCM;
+ }
else if (addr >= NDS::ARM9->DTCMBase && addr < (NDS::ARM9->DTCMBase + NDS::ARM9->DTCMSize))
+ {
return memregion_DTCM;
- else if ((addr & 0xFFFFF000) == 0xFFFF0000)
- return memregion_BIOS9;
- else
+ }
+ else
{
+ if (NDS::ConsoleType == 1 && addr >= 0xFFFF0000 && !(DSi::SCFG_BIOS & (1<<1)))
+ {
+ if ((addr >= 0xFFFF8000) && (DSi::SCFG_BIOS & (1<<0)))
+ return memregion_Other;
+
+ return memregion_BIOS9DSi;
+ }
+ else if ((addr & 0xFFFFF000) == 0xFFFF0000)
+ {
+ return memregion_BIOS9;
+ }
+
switch (addr & 0xFF000000)
{
case 0x02000000:
return memregion_MainRAM;
case 0x03000000:
+ if (NDS::ConsoleType == 1)
+ {
+ if (addr >= DSi::NWRAMStart[0][0] && addr < DSi::NWRAMEnd[0][0])
+ return memregion_NewSharedWRAM_A;
+ if (addr >= DSi::NWRAMStart[0][1] && addr < DSi::NWRAMEnd[0][1])
+ return memregion_NewSharedWRAM_B;
+ if (addr >= DSi::NWRAMStart[0][2] && addr < DSi::NWRAMEnd[0][2])
+ return memregion_NewSharedWRAM_C;
+ }
+
if (NDS::SWRAM_ARM9.Mem)
- return memregion_SWRAM;
- else
- return memregion_Other;
+ return memregion_SharedWRAM;
+ return memregion_Other;
case 0x04000000:
return memregion_IO9;
case 0x06000000:
return memregion_VRAM;
+ default:
+ return memregion_Other;
}
}
- return memregion_Other;
}
int ClassifyAddress7(u32 addr)
{
- if (addr < 0x00004000)
+ if (NDS::ConsoleType == 1 && addr < 0x00010000 && !(DSi::SCFG_BIOS & (1<<9)))
+ {
+ if (addr >= 0x00008000 && DSi::SCFG_BIOS & (1<<8))
+ return memregion_Other;
+
+ return memregion_BIOS7DSi;
+ }
+ else if (addr < 0x00004000)
+ {
return memregion_BIOS7;
+ }
else
{
switch (addr & 0xFF800000)
@@ -657,10 +868,19 @@ int ClassifyAddress7(u32 addr)
case 0x02800000:
return memregion_MainRAM;
case 0x03000000:
+ if (NDS::ConsoleType == 1)
+ {
+ if (addr >= DSi::NWRAMStart[1][0] && addr < DSi::NWRAMEnd[1][0])
+ return memregion_NewSharedWRAM_A;
+ if (addr >= DSi::NWRAMStart[1][1] && addr < DSi::NWRAMEnd[1][1])
+ return memregion_NewSharedWRAM_B;
+ if (addr >= DSi::NWRAMStart[1][2] && addr < DSi::NWRAMEnd[1][2])
+ return memregion_NewSharedWRAM_C;
+ }
+
if (NDS::SWRAM_ARM7.Mem)
- return memregion_SWRAM;
- else
- return memregion_WRAM7;
+ return memregion_SharedWRAM;
+ return memregion_WRAM7;
case 0x03800000:
return memregion_WRAM7;
case 0x04000000:
@@ -740,14 +960,29 @@ void* GetFuncForAddr(ARM* cpu, u32 addr, bool store, int size)
}
}
- switch (size | store)
+ if (NDS::ConsoleType == 0)
+ {
+ switch (size | store)
+ {
+ case 8: return (void*)NDS::ARM9IORead8;
+ case 9: return (void*)NDS::ARM9IOWrite8;
+ case 16: return (void*)NDS::ARM9IORead16;
+ case 17: return (void*)NDS::ARM9IOWrite16;
+ case 32: return (void*)NDS::ARM9IORead32;
+ case 33: return (void*)NDS::ARM9IOWrite32;
+ }
+ }
+ else
{
- case 8: return (void*)NDS::ARM9IORead8;
- case 9: return (void*)NDS::ARM9IOWrite8;
- case 16: return (void*)NDS::ARM9IORead16;
- case 17: return (void*)NDS::ARM9IOWrite16;
- case 32: return (void*)NDS::ARM9IORead32;
- case 33: return (void*)NDS::ARM9IOWrite32;
+ switch (size | store)
+ {
+ case 8: return (void*)DSi::ARM9IORead8;
+ case 9: return (void*)DSi::ARM9IOWrite8;
+ case 16: return (void*)DSi::ARM9IORead16;
+ case 17: return (void*)DSi::ARM9IOWrite16;
+ case 32: return (void*)DSi::ARM9IORead32;
+ case 33: return (void*)DSi::ARM9IOWrite32;
+ }
}
break;
case 0x06000000:
@@ -781,14 +1016,29 @@ void* GetFuncForAddr(ARM* cpu, u32 addr, bool store, int size)
}
}
- switch (size | store)
+ if (NDS::ConsoleType == 0)
{
- case 8: return (void*)NDS::ARM7IORead8;
- case 9: return (void*)NDS::ARM7IOWrite8;
- case 16: return (void*)NDS::ARM7IORead16;
- case 17: return (void*)NDS::ARM7IOWrite16;
- case 32: return (void*)NDS::ARM7IORead32;
- case 33: return (void*)NDS::ARM7IOWrite32;
+ switch (size | store)
+ {
+ case 8: return (void*)NDS::ARM7IORead8;
+ case 9: return (void*)NDS::ARM7IOWrite8;
+ case 16: return (void*)NDS::ARM7IORead16;
+ case 17: return (void*)NDS::ARM7IOWrite16;
+ case 32: return (void*)NDS::ARM7IORead32;
+ case 33: return (void*)NDS::ARM7IOWrite32;
+ }
+ }
+ else
+ {
+ switch (size | store)
+ {
+ case 8: return (void*)DSi::ARM7IORead8;
+ case 9: return (void*)DSi::ARM7IOWrite8;
+ case 16: return (void*)DSi::ARM7IORead16;
+ case 17: return (void*)DSi::ARM7IOWrite16;
+ case 32: return (void*)DSi::ARM7IORead32;
+ case 33: return (void*)DSi::ARM7IOWrite32;
+ }
}
break;
case 0x04800000:
diff --git a/src/ARMJIT_Memory.h b/src/ARMJIT_Memory.h
index 1a59d98..123e18e 100644
--- a/src/ARMJIT_Memory.h
+++ b/src/ARMJIT_Memory.h
@@ -23,7 +23,7 @@ enum
memregion_DTCM,
memregion_BIOS9,
memregion_MainRAM,
- memregion_SWRAM,
+ memregion_SharedWRAM,
memregion_IO9,
memregion_VRAM,
memregion_BIOS7,
@@ -31,18 +31,28 @@ enum
memregion_IO7,
memregion_Wifi,
memregion_VWRAM,
+
+ // DSi
+ memregion_BIOS9DSi,
+ memregion_BIOS7DSi,
+ memregion_NewSharedWRAM_A,
+ memregion_NewSharedWRAM_B,
+ memregion_NewSharedWRAM_C,
+
memregions_Count
};
int ClassifyAddress9(u32 addr);
int ClassifyAddress7(u32 addr);
-bool GetRegionMapping(int region, u32 num, u32& mappingStart, u32& mappingSize, u32& memoryOffset, u32& memorySize);
+bool GetMirrorLocation(int region, u32 num, u32 addr, u32& memoryOffset, u32& mirrorStart, u32& mirrorSize);
+u32 LocaliseAddress(int region, u32 num, u32 addr);
-bool IsMappable(int region);
+bool IsFastmemCompatible(int region);
void RemapDTCM(u32 newBase, u32 newSize);
void RemapSWRAM();
+void RemapNWRAM(int num);
void SetCodeProtection(int region, u32 offset, bool protect);
diff --git a/src/ARMJIT_x64/ARMJIT_Compiler.cpp b/src/ARMJIT_x64/ARMJIT_Compiler.cpp
index 34c1c91..d8bdd56 100644
--- a/src/ARMJIT_x64/ARMJIT_Compiler.cpp
+++ b/src/ARMJIT_x64/ARMJIT_Compiler.cpp
@@ -40,6 +40,12 @@ const int RegisterCache<Compiler, X64Reg>::NativeRegsAvailable =
#endif
;
+#ifdef _WIN32
+const BitSet32 CallerSavedPushRegs({R10, R11});
+#else
+const BitSet32 CallerSavedPushRegs({R9, R10, R11});
+#endif
+
void Compiler::PushRegs(bool saveHiRegs)
{
BitSet32 loadedRegs(RegCache.LoadedRegs);
@@ -301,6 +307,107 @@ Compiler::Compiler()
RET();
}
+ for (int consoleType = 0; consoleType < 2; consoleType++)
+ {
+ for (int num = 0; num < 2; num++)
+ {
+ for (int size = 0; size < 3; size++)
+ {
+ for (int reg = 0; reg < 16; reg++)
+ {
+ if (reg == RSCRATCH || reg == ABI_PARAM1 || reg == ABI_PARAM2 || reg == ABI_PARAM3)
+ {
+ PatchedStoreFuncs[consoleType][num][size][reg] = NULL;
+ PatchedLoadFuncs[consoleType][num][size][0][reg] = NULL;
+ PatchedLoadFuncs[consoleType][num][size][1][reg] = NULL;
+ continue;
+ }
+
+ X64Reg rdMapped = (X64Reg)reg;
+ PatchedStoreFuncs[consoleType][num][size][reg] = GetWritableCodePtr();
+ if (RSCRATCH3 != ABI_PARAM1)
+ MOV(32, R(ABI_PARAM1), R(RSCRATCH3));
+ if (num == 0)
+ {
+ MOV(64, R(ABI_PARAM2), R(RCPU));
+ MOV(32, R(ABI_PARAM3), R(rdMapped));
+ }
+ else
+ {
+ MOV(32, R(ABI_PARAM2), R(rdMapped));
+ }
+ ABI_PushRegistersAndAdjustStack(CallerSavedPushRegs, 8);
+ if (consoleType == 0)
+ {
+ switch ((8 << size) | num)
+ {
+ case 32: ABI_CallFunction(SlowWrite9<u32, 0>); break;
+ case 33: ABI_CallFunction(SlowWrite7<u32, 0>); break;
+ case 16: ABI_CallFunction(SlowWrite9<u16, 0>); break;
+ case 17: ABI_CallFunction(SlowWrite7<u16, 0>); break;
+ case 8: ABI_CallFunction(SlowWrite9<u8, 0>); break;
+ case 9: ABI_CallFunction(SlowWrite7<u8, 0>); break;
+ }
+ }
+ else
+ {
+ switch ((8 << size) | num)
+ {
+ case 32: ABI_CallFunction(SlowWrite9<u32, 1>); break;
+ case 33: ABI_CallFunction(SlowWrite7<u32, 1>); break;
+ case 16: ABI_CallFunction(SlowWrite9<u16, 1>); break;
+ case 17: ABI_CallFunction(SlowWrite7<u16, 1>); break;
+ case 8: ABI_CallFunction(SlowWrite9<u8, 1>); break;
+ case 9: ABI_CallFunction(SlowWrite7<u8, 1>); break;
+ }
+ }
+ ABI_PopRegistersAndAdjustStack(CallerSavedPushRegs, 8);
+ RET();
+
+ for (int signextend = 0; signextend < 2; signextend++)
+ {
+ PatchedLoadFuncs[consoleType][num][size][signextend][reg] = GetWritableCodePtr();
+ if (RSCRATCH3 != ABI_PARAM1)
+ MOV(32, R(ABI_PARAM1), R(RSCRATCH3));
+ if (num == 0)
+ MOV(64, R(ABI_PARAM2), R(RCPU));
+ ABI_PushRegistersAndAdjustStack(CallerSavedPushRegs, 8);
+ if (consoleType == 0)
+ {
+ switch ((8 << size) | num)
+ {
+ case 32: ABI_CallFunction(SlowRead9<u32, 0>); break;
+ case 33: ABI_CallFunction(SlowRead7<u32, 0>); break;
+ case 16: ABI_CallFunction(SlowRead9<u16, 0>); break;
+ case 17: ABI_CallFunction(SlowRead7<u16, 0>); break;
+ case 8: ABI_CallFunction(SlowRead9<u8, 0>); break;
+ case 9: ABI_CallFunction(SlowRead7<u8, 0>); break;
+ }
+ }
+ else
+ {
+ switch ((8 << size) | num)
+ {
+ case 32: ABI_CallFunction(SlowRead9<u32, 1>); break;
+ case 33: ABI_CallFunction(SlowRead7<u32, 1>); break;
+ case 16: ABI_CallFunction(SlowRead9<u16, 1>); break;
+ case 17: ABI_CallFunction(SlowRead7<u16, 1>); break;
+ case 8: ABI_CallFunction(SlowRead9<u8, 1>); break;
+ case 9: ABI_CallFunction(SlowRead7<u8, 1>); break;
+ }
+ }
+ ABI_PopRegistersAndAdjustStack(CallerSavedPushRegs, 8);
+ if (signextend)
+ MOVSX(32, 8 << size, rdMapped, R(RSCRATCH));
+ else
+ MOVZX(32, 8 << size, rdMapped, R(RSCRATCH));
+ RET();
+ }
+ }
+ }
+ }
+ }
+
// move the region forward to prevent overwriting the generated functions
CodeMemSize -= GetWritableCodePtr() - ResetStart;
ResetStart = GetWritableCodePtr();
@@ -500,6 +607,8 @@ void Compiler::Reset()
NearCode = NearStart;
FarCode = FarStart;
+
+ LoadStorePatches.clear();
}
bool Compiler::IsJITFault(u64 addr)
diff --git a/src/ARMJIT_x64/ARMJIT_Compiler.h b/src/ARMJIT_x64/ARMJIT_Compiler.h
index d1a6c07..0fe0147 100644
--- a/src/ARMJIT_x64/ARMJIT_Compiler.h
+++ b/src/ARMJIT_x64/ARMJIT_Compiler.h
@@ -7,6 +7,8 @@
#include "../ARMJIT_Internal.h"
#include "../ARMJIT_RegisterCache.h"
+#include <unordered_map>
+
namespace ARMJIT
{
@@ -18,6 +20,13 @@ const Gen::X64Reg RSCRATCH2 = Gen::EDX;
const Gen::X64Reg RSCRATCH3 = Gen::ECX;
const Gen::X64Reg RSCRATCH4 = Gen::R8;
+struct LoadStorePatch
+{
+ void* PatchFunc;
+ s16 Offset;
+ u16 Size;
+};
+
struct Op2
{
Op2()
@@ -211,6 +220,11 @@ public:
u8* NearStart;
u8* FarStart;
+ void* PatchedStoreFuncs[2][2][3][16];
+ void* PatchedLoadFuncs[2][2][3][2][16];
+
+ std::unordered_map<u8*, LoadStorePatch> LoadStorePatches;
+
u8* ResetStart;
u32 CodeMemSize;
diff --git a/src/ARMJIT_x64/ARMJIT_LoadStore.cpp b/src/ARMJIT_x64/ARMJIT_LoadStore.cpp
index b780c55..2da113b 100644
--- a/src/ARMJIT_x64/ARMJIT_LoadStore.cpp
+++ b/src/ARMJIT_x64/ARMJIT_LoadStore.cpp
@@ -17,7 +17,30 @@ int squeezePointer(T* ptr)
s32 Compiler::RewriteMemAccess(u64 pc)
{
- return 0;
+ auto it = LoadStorePatches.find((u8*)pc);
+ if (it != LoadStorePatches.end())
+ {
+ LoadStorePatch patch = it->second;
+ LoadStorePatches.erase(it);
+
+ u8* curCodePtr = GetWritableCodePtr();
+ u8* rewritePtr = (u8*)pc + (ptrdiff_t)patch.Offset;
+ SetCodePtr(rewritePtr);
+
+ CALL(patch.PatchFunc);
+ u32 remainingSize = patch.Size - (GetWritableCodePtr() - rewritePtr);
+ if (remainingSize > 0)
+ NOP(remainingSize);
+
+ //printf("rewriting memory access %p %d %d\n", patch.PatchFunc, patch.Offset, patch.Size);
+
+ SetCodePtr(curCodePtr);
+
+ return patch.Offset;
+ }
+
+ printf("this is a JIT bug %x\n", pc);
+ abort();
}
/*
@@ -91,369 +114,213 @@ void Compiler::Comp_MemAccess(int rd, int rn, const Op2& op2, int size, int flag
return;
}
+ if (flags & memop_Store)
{
- if (flags & memop_Store)
- {
- Comp_AddCycles_CD();
- }
- else
- {
- Comp_AddCycles_CDI();
- }
+ Comp_AddCycles_CD();
+ }
+ else
+ {
+ Comp_AddCycles_CDI();
+ }
- bool addrIsStatic = Config::JIT_LiteralOptimisations
- && RegCache.IsLiteral(rn) && op2.IsImm && !(flags & (memop_Writeback|memop_Post));
- u32 staticAddress;
- if (addrIsStatic)
- staticAddress = RegCache.LiteralValues[rn] + op2.Imm * ((flags & memop_SubtractOffset) ? -1 : 1);
- OpArg rdMapped = MapReg(rd);
+ bool addrIsStatic = Config::JIT_LiteralOptimisations
+ && RegCache.IsLiteral(rn) && op2.IsImm && !(flags & (memop_Writeback|memop_Post));
+ u32 staticAddress;
+ if (addrIsStatic)
+ staticAddress = RegCache.LiteralValues[rn] + op2.Imm * ((flags & memop_SubtractOffset) ? -1 : 1);
+ OpArg rdMapped = MapReg(rd);
- if (true)
- {
- OpArg rnMapped = MapReg(rn);
- if (Thumb && rn == 15)
- rnMapped = Imm32(R15 & ~0x2);
+ OpArg rnMapped = MapReg(rn);
+ if (Thumb && rn == 15)
+ rnMapped = Imm32(R15 & ~0x2);
- X64Reg finalAddr = RSCRATCH3;
- if (flags & memop_Post)
- {
- MOV(32, R(RSCRATCH3), rnMapped);
+ X64Reg finalAddr = RSCRATCH3;
+ if (flags & memop_Post)
+ {
+ MOV(32, R(RSCRATCH3), rnMapped);
- finalAddr = rnMapped.GetSimpleReg();
- }
+ finalAddr = rnMapped.GetSimpleReg();
+ }
- if (op2.IsImm)
+ if (op2.IsImm)
+ {
+ MOV_sum(32, finalAddr, rnMapped, Imm32(op2.Imm * ((flags & memop_SubtractOffset) ? -1 : 1)));
+ }
+ else
+ {
+ OpArg rm = MapReg(op2.Reg.Reg);
+
+ if (!(flags & memop_SubtractOffset) && rm.IsSimpleReg() && rnMapped.IsSimpleReg()
+ && op2.Reg.Op == 0 && op2.Reg.Amount > 0 && op2.Reg.Amount <= 3)
+ {
+ LEA(32, finalAddr,
+ MComplex(rnMapped.GetSimpleReg(), rm.GetSimpleReg(), 1 << op2.Reg.Amount, 0));
+ }
+ else
+ {
+ bool throwAway;
+ OpArg offset =
+ Comp_RegShiftImm(op2.Reg.Op, op2.Reg.Amount, rm, false, throwAway);
+
+ if (flags & memop_SubtractOffset)
{
- MOV_sum(32, finalAddr, rnMapped, Imm32(op2.Imm * ((flags & memop_SubtractOffset) ? -1 : 1)));
+ if (R(finalAddr) != rnMapped)
+ MOV(32, R(finalAddr), rnMapped);
+ if (!offset.IsZero())
+ SUB(32, R(finalAddr), offset);
}
else
- {
- OpArg rm = MapReg(op2.Reg.Reg);
+ MOV_sum(32, finalAddr, rnMapped, offset);
+ }
+ }
- if (!(flags & memop_SubtractOffset) && rm.IsSimpleReg() && rnMapped.IsSimpleReg()
- && op2.Reg.Op == 0 && op2.Reg.Amount > 0 && op2.Reg.Amount <= 3)
- {
- LEA(32, finalAddr,
- MComplex(rnMapped.GetSimpleReg(), rm.GetSimpleReg(), 1 << op2.Reg.Amount, 0));
- }
- else
- {
- bool throwAway;
- OpArg offset =
- Comp_RegShiftImm(op2.Reg.Op, op2.Reg.Amount, rm, false, throwAway);
+ if ((flags & memop_Writeback) && !(flags & memop_Post))
+ MOV(32, rnMapped, R(finalAddr));
- if (flags & memop_SubtractOffset)
- {
- if (R(finalAddr) != rnMapped)
- MOV(32, R(finalAddr), rnMapped);
- if (!offset.IsZero())
- SUB(32, R(finalAddr), offset);
- }
- else
- MOV_sum(32, finalAddr, rnMapped, offset);
- }
- }
+ u32 expectedTarget = Num == 0
+ ? ARMJIT_Memory::ClassifyAddress9(CurInstr.DataRegion)
+ : ARMJIT_Memory::ClassifyAddress7(CurInstr.DataRegion);
- if ((flags & memop_Writeback) && !(flags & memop_Post))
- MOV(32, rnMapped, R(finalAddr));
- }
+ if (Config::JIT_FastMemory && ((!Thumb && CurInstr.Cond() != 0xE) || ARMJIT_Memory::IsFastmemCompatible(expectedTarget)))
+ {
+ u8* memopStart = GetWritableCodePtr();
+ LoadStorePatch patch;
+
+ patch.PatchFunc = flags & memop_Store
+ ? PatchedStoreFuncs[NDS::ConsoleType][Num][__builtin_ctz(size) - 3][rdMapped.GetSimpleReg()]
+ : PatchedLoadFuncs[NDS::ConsoleType][Num][__builtin_ctz(size) - 3][!!(flags & memop_SignExtend)][rdMapped.GetSimpleReg()];
- /*int expectedTarget = Num == 0
- ? ClassifyAddress9(addrIsStatic ? staticAddress : CurInstr.DataRegion)
- : ClassifyAddress7(addrIsStatic ? staticAddress : CurInstr.DataRegion);
- if (CurInstr.Cond() < 0xE)
- expectedTarget = memregion_Other;
+ assert(patch.PatchFunc != NULL);
- bool compileFastPath = false, compileSlowPath = !addrIsStatic || (flags & memop_Store);
+ MOV(64, R(RSCRATCH), ImmPtr(Num == 0 ? ARMJIT_Memory::FastMem9Start : ARMJIT_Memory::FastMem7Start));
- switch (expectedTarget)
+ X64Reg maskedAddr = RSCRATCH3;
+ if (size > 8)
{
- case memregion_MainRAM:
- case memregion_DTCM:
- case memregion_WRAM7:
- case memregion_SWRAM9:
- case memregion_SWRAM7:
- case memregion_IO9:
- case memregion_IO7:
- case memregion_VWRAM:
- compileFastPath = true;
- break;
- case memregion_Wifi:
- compileFastPath = size >= 16;
- break;
- case memregion_VRAM:
- compileFastPath = !(flags & memop_Store) || size >= 16;
- case memregion_BIOS9:
- compileFastPath = !(flags & memop_Store);
- break;
- default: break;
+ maskedAddr = RSCRATCH2;
+ MOV(32, R(RSCRATCH2), R(RSCRATCH3));
+ AND(32, R(RSCRATCH2), Imm8(addressMask));
}
- if (addrIsStatic && !compileFastPath)
+ u8* memopLoadStoreLocation = GetWritableCodePtr();
+ if (flags & memop_Store)
{
- compileFastPath = false;
- compileSlowPath = true;
+ MOV(size, MRegSum(RSCRATCH, maskedAddr), rdMapped);
}
-
- if (addrIsStatic && compileSlowPath)
- MOV(32, R(RSCRATCH3), Imm32(staticAddress));
-*/
- /*if (compileFastPath)
+ else
{
- FixupBranch slowPath;
- if (compileSlowPath)
- {
- MOV(32, R(RSCRATCH), R(RSCRATCH3));
- SHR(32, R(RSCRATCH), Imm8(9));
- if (flags & memop_Store)
- {
- CMP(8, MDisp(RSCRATCH, squeezePointer(Num == 0 ? MemoryStatus9 : MemoryStatus7)), Imm8(expectedTarget));
- }
- else
- {
- MOVZX(32, 8, RSCRATCH, MDisp(RSCRATCH, squeezePointer(Num == 0 ? MemoryStatus9 : MemoryStatus7)));
- AND(32, R(RSCRATCH), Imm8(~0x80));
- CMP(32, R(RSCRATCH), Imm8(expectedTarget));
- }
-
- slowPath = J_CC(CC_NE, true);
- }
+ if (flags & memop_SignExtend)
+ MOVSX(32, size, rdMapped.GetSimpleReg(), MRegSum(RSCRATCH, maskedAddr));
+ else
+ MOVZX(32, size, rdMapped.GetSimpleReg(), MRegSum(RSCRATCH, maskedAddr));
- if (expectedTarget == memregion_MainRAM || expectedTarget == memregion_WRAM7
- || expectedTarget == memregion_BIOS9)
+ if (size == 32)
{
- u8* data;
- u32 mask;
- if (expectedTarget == memregion_MainRAM)
- {
- data = NDS::MainRAM;
- mask = MAIN_RAM_SIZE - 1;
- }
- else if (expectedTarget == memregion_BIOS9)
- {
- data = NDS::ARM9BIOS;
- mask = 0xFFF;
- }
- else
- {
- data = NDS::ARM7WRAM;
- mask = 0xFFFF;
- }
- OpArg memLoc;
- if (addrIsStatic)
- {
- memLoc = M(data + ((staticAddress & mask & addressMask)));
- }
- else
- {
- MOV(32, R(RSCRATCH), R(RSCRATCH3));
- AND(32, R(RSCRATCH), Imm32(mask & addressMask));
- memLoc = MDisp(RSCRATCH, squeezePointer(data));
- }
- if (flags & memop_Store)
- MOV(size, memLoc, rdMapped);
- else if (flags & memop_SignExtend)
- MOVSX(32, size, rdMapped.GetSimpleReg(), memLoc);
- else
- MOVZX(32, size, rdMapped.GetSimpleReg(), memLoc);
- }
- else if (expectedTarget == memregion_DTCM)
- {
- if (addrIsStatic)
- MOV(32, R(RSCRATCH), Imm32(staticAddress));
- else
- MOV(32, R(RSCRATCH), R(RSCRATCH3));
- SUB(32, R(RSCRATCH), MDisp(RCPU, offsetof(ARMv5, DTCMBase)));
- AND(32, R(RSCRATCH), Imm32(0x3FFF & addressMask));
- OpArg memLoc = MComplex(RCPU, RSCRATCH, SCALE_1, offsetof(ARMv5, DTCM));
- if (flags & memop_Store)
- MOV(size, memLoc, rdMapped);
- else if (flags & memop_SignExtend)
- MOVSX(32, size, rdMapped.GetSimpleReg(), memLoc);
- else
- MOVZX(32, size, rdMapped.GetSimpleReg(), memLoc);
- }
- else if (expectedTarget == memregion_SWRAM9 || expectedTarget == memregion_SWRAM7)
- {
- MOV(64, R(RSCRATCH2), M(expectedTarget == memregion_SWRAM9 ? &NDS::SWRAM_ARM9 : &NDS::SWRAM_ARM7));
- if (addrIsStatic)
- {
- MOV(32, R(RSCRATCH), Imm32(staticAddress & addressMask));
- }
- else
- {
- MOV(32, R(RSCRATCH), R(RSCRATCH3));
- AND(32, R(RSCRATCH), Imm8(addressMask));
- }
- AND(32, R(RSCRATCH), M(expectedTarget == memregion_SWRAM9 ? &NDS::SWRAM_ARM9Mask : &NDS::SWRAM_ARM7Mask));
- OpArg memLoc = MRegSum(RSCRATCH, RSCRATCH2);
- if (flags & memop_Store)
- MOV(size, memLoc, rdMapped);
- else if (flags & memop_SignExtend)
- MOVSX(32, size, rdMapped.GetSimpleReg(), memLoc);
- else
- MOVZX(32, size, rdMapped.GetSimpleReg(), memLoc);
+ AND(32, R(RSCRATCH3), Imm8(0x3));
+ SHL(32, R(RSCRATCH3), Imm8(3));
+ ROR_(32, rdMapped, R(RSCRATCH3));
}
- else
- {
- u32 maskedDataRegion;
-
- if (addrIsStatic)
- {
- maskedDataRegion = staticAddress;
- MOV(32, R(ABI_PARAM1), Imm32(staticAddress));
- }
- else
- {
- if (ABI_PARAM1 != RSCRATCH3)
- MOV(32, R(ABI_PARAM1), R(RSCRATCH3));
- AND(32, R(ABI_PARAM1), Imm8(addressMask));
-
- maskedDataRegion = CurInstr.DataRegion;
- if (Num == 0)
- maskedDataRegion &= ~0xFFFFFF;
- else
- maskedDataRegion &= ~0x7FFFFF;
- }
+ }
- void* func = GetFuncForAddr(CurCPU, maskedDataRegion, flags & memop_Store, size);
+ patch.Offset = memopStart - memopLoadStoreLocation;
+ patch.Size = GetWritableCodePtr() - memopStart;
- if (flags & memop_Store)
- {
- PushRegs(false);
+ assert(patch.Size >= 5);
- MOV(32, R(ABI_PARAM2), rdMapped);
+ LoadStorePatches[memopLoadStoreLocation] = patch;
+ }
+ else
+ {
+ PushRegs(false);
- ABI_CallFunction((void(*)())func);
+ if (Num == 0)
+ {
+ MOV(64, R(ABI_PARAM2), R(RCPU));
+ if (ABI_PARAM1 != RSCRATCH3)
+ MOV(32, R(ABI_PARAM1), R(RSCRATCH3));
+ if (flags & memop_Store)
+ {
+ MOV(32, R(ABI_PARAM3), rdMapped);
- PopRegs(false);
- }
- else
+ switch (size | NDS::ConsoleType)
{
- if (!addrIsStatic)
- MOV(32, rdMapped, R(RSCRATCH3));
-
- PushRegs(false);
-
- ABI_CallFunction((void(*)())func);
-
- PopRegs(false);
-
- if (!addrIsStatic)
- MOV(32, R(RSCRATCH3), rdMapped);
-
- if (flags & memop_SignExtend)
- MOVSX(32, size, rdMapped.GetSimpleReg(), R(RSCRATCH));
- else
- MOVZX(32, size, rdMapped.GetSimpleReg(), R(RSCRATCH));
+ case 32: CALL((void*)&SlowWrite9<u32, 0>); break;
+ case 16: CALL((void*)&SlowWrite9<u16, 0>); break;
+ case 8: CALL((void*)&SlowWrite9<u8, 0>); break;
+ case 33: CALL((void*)&SlowWrite9<u32, 1>); break;
+ case 17: CALL((void*)&SlowWrite9<u16, 1>); break;
+ case 9: CALL((void*)&SlowWrite9<u8, 1>); break;
}
}
-
- if ((size == 32 && !(flags & memop_Store)))
+ else
{
- if (addrIsStatic)
- {
- if (staticAddress & 0x3)
- ROR_(32, rdMapped, Imm8((staticAddress & 0x3) * 8));
- }
- else
+ switch (size | NDS::ConsoleType)
{
- AND(32, R(RSCRATCH3), Imm8(0x3));
- SHL(32, R(RSCRATCH3), Imm8(3));
- ROR_(32, rdMapped, R(RSCRATCH3));
+ case 32: CALL((void*)&SlowRead9<u32, 0>); break;
+ case 16: CALL((void*)&SlowRead9<u16, 0>); break;
+ case 8: CALL((void*)&SlowRead9<u8, 0>); break;
+ case 33: CALL((void*)&SlowRead9<u32, 1>); break;
+ case 17: CALL((void*)&SlowRead9<u16, 1>); break;
+ case 9: CALL((void*)&SlowRead9<u8, 1>); break;
}
}
-
- if (compileSlowPath)
- {
- SwitchToFarCode();
- SetJumpTarget(slowPath);
- }
}
-*/
- if (true)
+ else
{
- PushRegs(false);
-
- if (Num == 0)
+ if (ABI_PARAM1 != RSCRATCH3)
+ MOV(32, R(ABI_PARAM1), R(RSCRATCH3));
+ if (flags & memop_Store)
{
- MOV(64, R(ABI_PARAM2), R(RCPU));
- if (ABI_PARAM1 != RSCRATCH3)
- MOV(32, R(ABI_PARAM1), R(RSCRATCH3));
- if (flags & memop_Store)
- {
- MOV(32, R(ABI_PARAM3), rdMapped);
+ MOV(32, R(ABI_PARAM2), rdMapped);
- switch (size)
- {
- case 32: CALL((void*)&SlowWrite9<u32>); break;
- case 16: CALL((void*)&SlowWrite9<u16>); break;
- case 8: CALL((void*)&SlowWrite9<u8>); break;
- }
- }
- else
+ switch (size | NDS::ConsoleType)
{
- switch (size)
- {
- case 32: CALL((void*)&SlowRead9<u32>); break;
- case 16: CALL((void*)&SlowRead9<u16>); break;
- case 8: CALL((void*)&SlowRead9<u8>); break;
- }
+ case 32: CALL((void*)&SlowWrite7<u32, 0>); break;
+ case 16: CALL((void*)&SlowWrite7<u16, 0>); break;
+ case 8: CALL((void*)&SlowWrite7<u8, 0>); break;
+ case 33: CALL((void*)&SlowWrite7<u32, 1>); break;
+ case 17: CALL((void*)&SlowWrite7<u16, 1>); break;
+ case 9: CALL((void*)&SlowWrite7<u8, 1>); break;
}
}
else
{
- if (ABI_PARAM1 != RSCRATCH3)
- MOV(32, R(ABI_PARAM1), R(RSCRATCH3));
- if (flags & memop_Store)
+ switch (size | NDS::ConsoleType)
{
- MOV(32, R(ABI_PARAM2), rdMapped);
-
- switch (size)
- {
- case 32: CALL((void*)&SlowWrite7<u32>); break;
- case 16: CALL((void*)&SlowWrite7<u16>); break;
- case 8: CALL((void*)&SlowWrite7<u8>); break;
- }
- }
- else
- {
- switch (size)
- {
- case 32: CALL((void*)&SlowRead7<u32>); break;
- case 16: CALL((void*)&SlowRead7<u16>); break;
- case 8: CALL((void*)&SlowRead7<u8>); break;
- }
+ case 32: CALL((void*)&SlowRead7<u32, 0>); break;
+ case 16: CALL((void*)&SlowRead7<u16, 0>); break;
+ case 8: CALL((void*)&SlowRead7<u8, 0>); break;
+ case 33: CALL((void*)&SlowRead7<u32, 1>); break;
+ case 17: CALL((void*)&SlowRead7<u16, 1>); break;
+ case 9: CALL((void*)&SlowRead7<u8, 1>); break;
}
}
+ }
- PopRegs(false);
+ PopRegs(false);
- if (!(flags & memop_Store))
- {
- if (flags & memop_SignExtend)
- MOVSX(32, size, rdMapped.GetSimpleReg(), R(RSCRATCH));
- else
- MOVZX(32, size, rdMapped.GetSimpleReg(), R(RSCRATCH));
- }
- }
-/*
- if (compileFastPath && compileSlowPath)
+ if (!(flags & memop_Store))
{
- FixupBranch ret = J(true);
- SwitchToNearCode();
- SetJumpTarget(ret);
- }*/
+ if (flags & memop_SignExtend)
+ MOVSX(32, size, rdMapped.GetSimpleReg(), R(RSCRATCH));
+ else
+ MOVZX(32, size, rdMapped.GetSimpleReg(), R(RSCRATCH));
+ }
+ }
- if (!(flags & memop_Store) && rd == 15)
+ if (!(flags & memop_Store) && rd == 15)
+ {
+ if (size < 32)
+ printf("!!! LDR <32 bit PC %08X %x\n", R15, CurInstr.Instr);
{
- if (size < 32)
- printf("!!! LDR <32 bit PC %08X %x\n", R15, CurInstr.Instr);
+ if (Num == 1)
{
- if (Num == 1)
- AND(32, rdMapped, Imm8(0xFE)); // immediate is sign extended
- Comp_JumpTo(rdMapped.GetSimpleReg());
+ if (Thumb)
+ OR(32, rdMapped, Imm8(0x1));
+ else
+ AND(32, rdMapped, Imm8(0xFE));
}
+ Comp_JumpTo(rdMapped.GetSimpleReg());
}
}
}
@@ -470,7 +337,7 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc
int flags = 0;
if (store)
flags |= memop_Store;
- if (decrement)
+ if (decrement && preinc)
flags |= memop_SubtractOffset;
Op2 offset = preinc ? Op2(4) : Op2(0);
@@ -481,96 +348,52 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc
s32 offset = (regsCount * 4) * (decrement ? -1 : 1);
- // we need to make sure that the stack stays aligned to 16 bytes
-#ifdef _WIN32
- // include shadow
- u32 stackAlloc = ((regsCount + 4 + 1) & ~1) * 8;
-#else
- u32 stackAlloc = ((regsCount + 1) & ~1) * 8;
-#endif
- u32 allocOffset = stackAlloc - regsCount * 8;
-/*
int expectedTarget = Num == 0
- ? ClassifyAddress9(CurInstr.DataRegion)
- : ClassifyAddress7(CurInstr.DataRegion);
- if (usermode || CurInstr.Cond() < 0xE)
- expectedTarget = memregion_Other;
-
- bool compileFastPath = false;
+ ? ARMJIT_Memory::ClassifyAddress9(CurInstr.DataRegion)
+ : ARMJIT_Memory::ClassifyAddress7(CurInstr.DataRegion);
- switch (expectedTarget)
- {
- case memregion_DTCM:
- case memregion_MainRAM:
- case memregion_SWRAM9:
- case memregion_SWRAM7:
- case memregion_WRAM7:
- compileFastPath = true;
- break;
- default:
- break;
- }
-*/
if (!store)
Comp_AddCycles_CDI();
else
Comp_AddCycles_CD();
+ bool compileFastPath = Config::JIT_FastMemory
+ && !usermode && (CurInstr.Cond() < 0xE || ARMJIT_Memory::IsFastmemCompatible(expectedTarget));
+
+ // we need to make sure that the stack stays aligned to 16 bytes
+#ifdef _WIN32
+ // include shadow
+ u32 stackAlloc = (((regsCount + 4 + 1) & ~1) + (compileFastPath ? 1 : 0)) * 8;
+#else
+ u32 stackAlloc = (((regsCount + 1) & ~1) + (compileFastPath ? 1 : 0)) * 8;
+#endif
+ u32 allocOffset = stackAlloc - regsCount * 8;
+
if (decrement)
- {
- MOV_sum(32, RSCRATCH4, MapReg(rn), Imm32(-regsCount * 4));
- preinc ^= true;
- }
+ MOV_sum(32, RSCRATCH4, MapReg(rn), Imm32(-regsCount * 4 + (preinc ? 0 : 4)));
else
- MOV(32, R(RSCRATCH4), MapReg(rn));
-/*
+ MOV_sum(32, RSCRATCH4, MapReg(rn), Imm32(preinc ? 4 : 0));
+
if (compileFastPath)
{
- assert(!usermode);
+ AND(32, R(RSCRATCH4), Imm8(~3));
- MOV(32, R(RSCRATCH), R(RSCRATCH4));
- SHR(32, R(RSCRATCH), Imm8(9));
+ u8* fastPathStart = GetWritableCodePtr();
+ u8* firstLoadStoreAddr;
- if (store)
- {
- CMP(8, MDisp(RSCRATCH, squeezePointer(Num == 0 ? MemoryStatus9 : MemoryStatus7)), Imm8(expectedTarget));
- }
- else
- {
- MOVZX(32, 8, RSCRATCH, MDisp(RSCRATCH, squeezePointer(Num == 0 ? MemoryStatus9 : MemoryStatus7)));
- AND(32, R(RSCRATCH), Imm8(~0x80));
- CMP(32, R(RSCRATCH), Imm8(expectedTarget));
- }
- FixupBranch slowPath = J_CC(CC_NE, true);
+ bool firstLoadStore = true;
+
+ MOV(64, R(RSCRATCH2), ImmPtr(Num == 0 ? ARMJIT_Memory::FastMem9Start : ARMJIT_Memory::FastMem7Start));
+ ADD(64, R(RSCRATCH2), R(RSCRATCH4));
+ MOV(32, R(RSCRATCH3), R(RSCRATCH4));
- if (expectedTarget == memregion_DTCM)
- {
- SUB(32, R(RSCRATCH4), MDisp(RCPU, offsetof(ARMv5, DTCMBase)));
- AND(32, R(RSCRATCH4), Imm32(0x3FFF & ~3));
- LEA(64, RSCRATCH4, MComplex(RCPU, RSCRATCH4, 1, offsetof(ARMv5, DTCM)));
- }
- else if (expectedTarget == memregion_MainRAM)
- {
- AND(32, R(RSCRATCH4), Imm32((MAIN_RAM_SIZE - 1) & ~3));
- ADD(64, R(RSCRATCH4), Imm32(squeezePointer(NDS::MainRAM)));
- }
- else if (expectedTarget == memregion_WRAM7)
- {
- AND(32, R(RSCRATCH4), Imm32(0xFFFF & ~3));
- ADD(64, R(RSCRATCH4), Imm32(squeezePointer(NDS::ARM7WRAM)));
- }
- else // SWRAM
- {
- AND(32, R(RSCRATCH4), Imm8(~3));
- AND(32, R(RSCRATCH4), M(expectedTarget == memregion_SWRAM9 ? &NDS::SWRAM_ARM9Mask : &NDS::SWRAM_ARM7Mask));
- ADD(64, R(RSCRATCH4), M(expectedTarget == memregion_SWRAM9 ? &NDS::SWRAM_ARM9 : &NDS::SWRAM_ARM7));
- }
u32 offset = 0;
for (int reg : regs)
{
- if (preinc)
- offset += 4;
- OpArg mem = MDisp(RSCRATCH4, offset);
+ if (firstLoadStore)
+ firstLoadStoreAddr = GetWritableCodePtr();
+
+ OpArg mem = MDisp(RSCRATCH2, offset);
if (store)
{
if (RegCache.LoadedRegs & (1 << reg))
@@ -580,6 +403,8 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc
else
{
LoadReg(reg, RSCRATCH);
+ if (firstLoadStore)
+ firstLoadStoreAddr = GetWritableCodePtr();
MOV(32, mem, R(RSCRATCH));
}
}
@@ -595,13 +420,19 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc
SaveReg(reg, RSCRATCH);
}
}
- if (!preinc)
- offset += 4;
+ offset += 4;
+
+ firstLoadStore = false;
}
+ LoadStorePatch patch;
+ patch.Size = GetWritableCodePtr() - fastPathStart;
+ patch.Offset = fastPathStart - firstLoadStoreAddr;
SwitchToFarCode();
- SetJumpTarget(slowPath);
- }*/
+ patch.PatchFunc = GetWritableCodePtr();
+
+ LoadStorePatches[firstLoadStoreAddr] = patch;
+ }
if (!store)
{
@@ -618,12 +449,12 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc
if (Num == 0)
MOV(64, R(ABI_PARAM4), R(RCPU));
- switch (Num * 2 | preinc)
+ switch (Num * 2 | NDS::ConsoleType)
{
- case 0: CALL((void*)&SlowBlockTransfer9<false, false>); break;
- case 1: CALL((void*)&SlowBlockTransfer9<true, false>); break;
- case 2: CALL((void*)&SlowBlockTransfer7<false, false>); break;
- case 3: CALL((void*)&SlowBlockTransfer7<true, false>); break;
+ case 0: CALL((void*)&SlowBlockTransfer9<false, 0>); break;
+ case 1: CALL((void*)&SlowBlockTransfer9<false, 1>); break;
+ case 2: CALL((void*)&SlowBlockTransfer7<false, 0>); break;
+ case 3: CALL((void*)&SlowBlockTransfer7<false, 1>); break;
}
PopRegs(false);
@@ -715,25 +546,24 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc
if (Num == 0)
MOV(64, R(ABI_PARAM4), R(RCPU));
- switch (Num * 2 | preinc)
+ switch (Num * 2 | NDS::ConsoleType)
{
- case 0: CALL((void*)&SlowBlockTransfer9<false, true>); break;
- case 1: CALL((void*)&SlowBlockTransfer9<true, true>); break;
- case 2: CALL((void*)&SlowBlockTransfer7<false, true>); break;
- case 3: CALL((void*)&SlowBlockTransfer7<true, true>); break;
+ case 0: CALL((void*)&SlowBlockTransfer9<true, 0>); break;
+ case 1: CALL((void*)&SlowBlockTransfer9<true, 1>); break;
+ case 2: CALL((void*)&SlowBlockTransfer7<true, 0>); break;
+ case 3: CALL((void*)&SlowBlockTransfer7<true, 1>); break;
}
ADD(64, R(RSP), stackAlloc <= INT8_MAX ? Imm8(stackAlloc) : Imm32(stackAlloc));
PopRegs(false);
}
-/*
+
if (compileFastPath)
{
- FixupBranch ret = J(true);
+ RET();
SwitchToNearCode();
- SetJumpTarget(ret);
- }*/
+ }
if (!store && regs[15])
{
diff --git a/src/CP15.cpp b/src/CP15.cpp
index 3d64259..992c83f 100644
--- a/src/CP15.cpp
+++ b/src/CP15.cpp
@@ -608,6 +608,27 @@ void ARMv5::CP15Write(u32 id, u32 val)
ITCMSetting = val;
UpdateITCMSetting();
return;
+
+ case 0xF00:
+ //printf("cache debug index register %08X\n", val);
+ return;
+
+ case 0xF10:
+ //printf("cache debug instruction tag %08X\n", val);
+ return;
+
+ case 0xF20:
+ //printf("cache debug data tag %08X\n", val);
+ return;
+
+ case 0xF30:
+ //printf("cache debug instruction cache %08X\n", val);
+ return;
+
+ case 0xF40:
+ //printf("cache debug data cache %08X\n", val);
+ return;
+
}
if ((id&0xF00)!=0x700)
diff --git a/src/Config.cpp b/src/Config.cpp
index edf84f2..de1c70d 100644
--- a/src/Config.cpp
+++ b/src/Config.cpp
@@ -40,14 +40,7 @@ char DSiNANDPath[1024];
#ifdef JIT_ENABLED
int JIT_Enable = false;
int JIT_MaxBlockSize = 32;
-int JIT_BrancheOptimisations = 2;
-int JIT_LiteralOptimisations = true;
-#endif
-
-#ifdef JIT_ENABLED
-int JIT_Enable = false;
-int JIT_MaxBlockSize = 32;
-int JIT_BrancheOptimisations = true;
+int JIT_BranchOptimisations = 2;
int JIT_LiteralOptimisations = true;
int JIT_FastMemory = true;
#endif
@@ -66,16 +59,9 @@ ConfigEntry ConfigFile[] =
#ifdef JIT_ENABLED
{"JIT_Enable", 0, &JIT_Enable, 0, NULL, 0},
{"JIT_MaxBlockSize", 0, &JIT_MaxBlockSize, 32, NULL, 0},
- {"JIT_BranchOptimisations", 0, &JIT_BrancheOptimisations, 2, NULL, 0},
- {"JIT_LiteralOptimisations", 0, &JIT_LiteralOptimisations, 1, NULL, 0},
-#endif
-
-#ifdef JIT_ENABLED
- {"JIT_Enable", 0, &JIT_Enable, 0, NULL, 0},
- {"JIT_MaxBlockSize", 0, &JIT_MaxBlockSize, 32, NULL, 0},
- {"JIT_BranchOptimisations", 0, &JIT_BrancheOptimisations, 1, NULL, 0},
+ {"JIT_BranchOptimisations", 0, &JIT_BranchOptimisations, 2, NULL, 0},
{"JIT_LiteralOptimisations", 0, &JIT_LiteralOptimisations, 1, NULL, 0},
- {"JIT_FastMem", 0, &JIT_FastMemory, 1, NULL, 0},
+ {"JIT_FastMemory", 0, &JIT_FastMemory, 1, NULL, 0},
#endif
{"", -1, NULL, 0, NULL, 0}
diff --git a/src/Config.h b/src/Config.h
index 7b19a4b..5916b4a 100644
--- a/src/Config.h
+++ b/src/Config.h
@@ -54,14 +54,7 @@ extern char DSiNANDPath[1024];
#ifdef JIT_ENABLED
extern int JIT_Enable;
extern int JIT_MaxBlockSize;
-extern int JIT_BrancheOptimisations;
-extern int JIT_LiteralOptimisations;
-#endif
-
-#ifdef JIT_ENABLED
-extern int JIT_Enable;
-extern int JIT_MaxBlockSize;
-extern int JIT_BrancheOptimisations;
+extern int JIT_BranchOptimisations;
extern int JIT_LiteralOptimisations;
extern int JIT_FastMemory;
#endif
diff --git a/src/DSi.cpp b/src/DSi.cpp
index 216f724..97a63cd 100644
--- a/src/DSi.cpp
+++ b/src/DSi.cpp
@@ -26,6 +26,11 @@
#include "NDSCart.h"
#include "Platform.h"
+#ifdef JIT_ENABLED
+#include "ARMJIT.h"
+#include "ARMJIT_Memory.h"
+#endif
+
#include "DSi_NDMA.h"
#include "DSi_I2C.h"
#include "DSi_SD.h"
@@ -34,15 +39,6 @@
#include "tiny-AES-c/aes.hpp"
-namespace NDS
-{
-
-extern ARMv5* ARM9;
-extern ARMv4* ARM7;
-
-}
-
-
namespace DSi
{
@@ -59,9 +55,9 @@ u8 ARM7iBIOS[0x10000];
u32 MBK[2][9];
-u8 NWRAM_A[0x40000];
-u8 NWRAM_B[0x40000];
-u8 NWRAM_C[0x40000];
+u8* NWRAM_A;
+u8* NWRAM_B;
+u8* NWRAM_C;
u8* NWRAMMap_A[2][4];
u8* NWRAMMap_B[3][8];
@@ -86,6 +82,12 @@ u8 ARM7Init[0x3C00];
bool Init()
{
+#ifndef JIT_ENABLED
+ NWRAM_A = new u8[NWRAMSize];
+ NWRAM_B = new u8[NWRAMSize];
+ NWRAM_C = new u8[NWRAMSize];
+#endif
+
if (!DSi_I2C::Init()) return false;
if (!DSi_AES::Init()) return false;
@@ -106,6 +108,12 @@ bool Init()
void DeInit()
{
+#ifndef JIT_ENABLED
+ delete[] NWRAM_A;
+ delete[] NWRAM_B;
+ delete[] NWRAM_C;
+#endif
+
DSi_I2C::DeInit();
DSi_AES::DeInit();
@@ -176,7 +184,12 @@ void SoftReset()
NDS::ARM9->Reset();
NDS::ARM7->Reset();
+ NDS::ARM9->CP15Reset();
+
memcpy(NDS::ARM9->ITCM, ITCMInit, 0x8000);
+#ifdef JIT_ENABLED
+ ARMJIT::CheckAndInvalidateITCM();
+#endif
DSi_AES::Reset();
@@ -274,9 +287,9 @@ bool LoadNAND()
{
printf("Loading DSi NAND\n");
- memset(NWRAM_A, 0, 0x40000);
- memset(NWRAM_B, 0, 0x40000);
- memset(NWRAM_C, 0, 0x40000);
+ memset(NWRAM_A, 0, NWRAMSize);
+ memset(NWRAM_B, 0, NWRAMSize);
+ memset(NWRAM_C, 0, NWRAMSize);
memset(MBK, 0, sizeof(MBK));
memset(NWRAMMap_A, 0, sizeof(NWRAMMap_A));
@@ -527,6 +540,8 @@ void MapNWRAM_A(u32 num, u8 val)
return;
}
+ ARMJIT_Memory::RemapNWRAM(0);
+
int mbkn = 0, mbks = 8*num;
u8 oldval = (MBK[0][mbkn] >> mbks) & 0xFF;
@@ -558,6 +573,8 @@ void MapNWRAM_B(u32 num, u8 val)
return;
}
+ ARMJIT_Memory::RemapNWRAM(1);
+
int mbkn = 1+(num>>2), mbks = 8*(num&3);
u8 oldval = (MBK[0][mbkn] >> mbks) & 0xFF;
@@ -593,6 +610,8 @@ void MapNWRAM_C(u32 num, u8 val)
return;
}
+ ARMJIT_Memory::RemapNWRAM(2);
+
int mbkn = 3+(num>>2), mbks = 8*(num&3);
u8 oldval = (MBK[0][mbkn] >> mbks) & 0xFF;
@@ -625,6 +644,8 @@ void MapNWRAMRange(u32 cpu, u32 num, u32 val)
u32 oldval = MBK[cpu][5+num];
if (oldval == val) return;
+ ARMJIT_Memory::RemapNWRAM(num);
+
MBK[cpu][5+num] = val;
// TODO: what happens when the ranges are 'out of range'????
@@ -826,19 +847,31 @@ void ARM9Write8(u32 addr, u8 val)
if (addr >= NWRAMStart[0][0] && addr < NWRAMEnd[0][0])
{
u8* ptr = NWRAMMap_A[0][(addr >> 16) & NWRAMMask[0][0]];
- if (ptr) *(u8*)&ptr[addr & 0xFFFF] = val;
+ if (ptr)
+ {
+ *(u8*)&ptr[addr & 0xFFFF] = val;
+ ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_A>(addr);
+ }
return;
}
if (addr >= NWRAMStart[0][1] && addr < NWRAMEnd[0][1])
{
u8* ptr = NWRAMMap_B[0][(addr >> 15) & NWRAMMask[0][1]];
- if (ptr) *(u8*)&ptr[addr & 0x7FFF] = val;
+ if (ptr)
+ {
+ *(u8*)&ptr[addr & 0x7FFF] = val;
+ ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_B>(addr);
+ }
return;
}
if (addr >= NWRAMStart[0][2] && addr < NWRAMEnd[0][2])
{
u8* ptr = NWRAMMap_C[0][(addr >> 15) & NWRAMMask[0][2]];
- if (ptr) *(u8*)&ptr[addr & 0x7FFF] = val;
+ if (ptr)
+ {
+ *(u8*)&ptr[addr & 0x7FFF] = val;
+ ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_C>(addr);
+ }
return;
}
return NDS::ARM9Write8(addr, val);
@@ -859,19 +892,31 @@ void ARM9Write16(u32 addr, u16 val)
if (addr >= NWRAMStart[0][0] && addr < NWRAMEnd[0][0])
{
u8* ptr = NWRAMMap_A[0][(addr >> 16) & NWRAMMask[0][0]];
- if (ptr) *(u16*)&ptr[addr & 0xFFFF] = val;
+ if (ptr)
+ {
+ *(u16*)&ptr[addr & 0xFFFF] = val;
+ ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_A>(addr);
+ }
return;
}
if (addr >= NWRAMStart[0][1] && addr < NWRAMEnd[0][1])
{
u8* ptr = NWRAMMap_B[0][(addr >> 15) & NWRAMMask[0][1]];
- if (ptr) *(u16*)&ptr[addr & 0x7FFF] = val;
+ if (ptr)
+ {
+ *(u16*)&ptr[addr & 0x7FFF] = val;
+ ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_B>(addr);
+ }
return;
}
if (addr >= NWRAMStart[0][2] && addr < NWRAMEnd[0][2])
{
u8* ptr = NWRAMMap_C[0][(addr >> 15) & NWRAMMask[0][2]];
- if (ptr) *(u16*)&ptr[addr & 0x7FFF] = val;
+ if (ptr)
+ {
+ *(u16*)&ptr[addr & 0x7FFF] = val;
+ ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_C>(addr);
+ }
return;
}
return NDS::ARM9Write16(addr, val);
@@ -892,19 +937,31 @@ void ARM9Write32(u32 addr, u32 val)
if (addr >= NWRAMStart[0][0] && addr < NWRAMEnd[0][0])
{
u8* ptr = NWRAMMap_A[0][(addr >> 16) & NWRAMMask[0][0]];
- if (ptr) *(u32*)&ptr[addr & 0xFFFF] = val;
+ if (ptr)
+ {
+ *(u32*)&ptr[addr & 0xFFFF] = val;
+ ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_A>(addr);
+ }
return;
}
if (addr >= NWRAMStart[0][1] && addr < NWRAMEnd[0][1])
{
u8* ptr = NWRAMMap_B[0][(addr >> 15) & NWRAMMask[0][1]];
- if (ptr) *(u32*)&ptr[addr & 0x7FFF] = val;
+ if (ptr)
+ {
+ *(u32*)&ptr[addr & 0x7FFF] = val;
+ ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_B>(addr);
+ }
return;
}
if (addr >= NWRAMStart[0][2] && addr < NWRAMEnd[0][2])
{
u8* ptr = NWRAMMap_C[0][(addr >> 15) & NWRAMMask[0][2]];
- if (ptr) *(u32*)&ptr[addr & 0x7FFF] = val;
+ if (ptr)
+ {
+ *(u32*)&ptr[addr & 0x7FFF] = val;
+ ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_C>(addr);
+ }
return;
}
return NDS::ARM9Write32(addr, val);
@@ -1085,19 +1142,37 @@ void ARM7Write8(u32 addr, u8 val)
if (addr >= NWRAMStart[1][0] && addr < NWRAMEnd[1][0])
{
u8* ptr = NWRAMMap_A[1][(addr >> 16) & NWRAMMask[1][0]];
- if (ptr) *(u8*)&ptr[addr & 0xFFFF] = val;
+ if (ptr)
+ {
+ *(u8*)&ptr[addr & 0xFFFF] = val;
+#ifdef JIT_ENABLED
+ ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_A>(addr);
+#endif
+ }
return;
}
if (addr >= NWRAMStart[1][1] && addr < NWRAMEnd[1][1])
{
u8* ptr = NWRAMMap_B[1][(addr >> 15) & NWRAMMask[1][1]];
- if (ptr) *(u8*)&ptr[addr & 0x7FFF] = val;
+ if (ptr)
+ {
+ *(u8*)&ptr[addr & 0x7FFF] = val;
+#ifdef JIT_ENABLED
+ ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_B>(addr);
+#endif
+ }
return;
}
if (addr >= NWRAMStart[1][2] && addr < NWRAMEnd[1][2])
{
u8* ptr = NWRAMMap_C[1][(addr >> 15) & NWRAMMask[1][2]];
- if (ptr) *(u8*)&ptr[addr & 0x7FFF] = val;
+ if (ptr)
+ {
+ *(u8*)&ptr[addr & 0x7FFF] = val;
+#ifdef JIT_ENABLED
+ ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_C>(addr);
+#endif
+ }
return;
}
return NDS::ARM7Write8(addr, val);
@@ -1118,19 +1193,31 @@ void ARM7Write16(u32 addr, u16 val)
if (addr >= NWRAMStart[1][0] && addr < NWRAMEnd[1][0])
{
u8* ptr = NWRAMMap_A[1][(addr >> 16) & NWRAMMask[1][0]];
- if (ptr) *(u16*)&ptr[addr & 0xFFFF] = val;
+ if (ptr)
+ {
+ *(u16*)&ptr[addr & 0xFFFF] = val;
+ ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_A>(addr);
+ }
return;
}
if (addr >= NWRAMStart[1][1] && addr < NWRAMEnd[1][1])
{
u8* ptr = NWRAMMap_B[1][(addr >> 15) & NWRAMMask[1][1]];
- if (ptr) *(u16*)&ptr[addr & 0x7FFF] = val;
+ if (ptr)
+ {
+ *(u16*)&ptr[addr & 0x7FFF] = val;
+ ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_B>(addr);
+ }
return;
}
if (addr >= NWRAMStart[1][2] && addr < NWRAMEnd[1][2])
{
u8* ptr = NWRAMMap_C[1][(addr >> 15) & NWRAMMask[1][2]];
- if (ptr) *(u16*)&ptr[addr & 0x7FFF] = val;
+ if (ptr)
+ {
+ *(u16*)&ptr[addr & 0x7FFF] = val;
+ ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_C>(addr);
+ }
return;
}
return NDS::ARM7Write16(addr, val);
@@ -1151,19 +1238,31 @@ void ARM7Write32(u32 addr, u32 val)
if (addr >= NWRAMStart[1][0] && addr < NWRAMEnd[1][0])
{
u8* ptr = NWRAMMap_A[1][(addr >> 16) & NWRAMMask[1][0]];
- if (ptr) *(u32*)&ptr[addr & 0xFFFF] = val;
+ if (ptr)
+ {
+ *(u32*)&ptr[addr & 0xFFFF] = val;
+ ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_A>(addr);
+ }
return;
}
if (addr >= NWRAMStart[1][1] && addr < NWRAMEnd[1][1])
{
u8* ptr = NWRAMMap_B[1][(addr >> 15) & NWRAMMask[1][1]];
- if (ptr) *(u32*)&ptr[addr & 0x7FFF] = val;
+ if (ptr)
+ {
+ *(u32*)&ptr[addr & 0x7FFF] = val;
+ ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_B>(addr);
+ }
return;
}
if (addr >= NWRAMStart[1][2] && addr < NWRAMEnd[1][2])
{
u8* ptr = NWRAMMap_C[1][(addr >> 15) & NWRAMMask[1][2]];
- if (ptr) *(u32*)&ptr[addr & 0x7FFF] = val;
+ if (ptr)
+ {
+ *(u32*)&ptr[addr & 0x7FFF] = val;
+ ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_C>(addr);
+ }
return;
}
return NDS::ARM7Write32(addr, val);
@@ -1521,7 +1620,7 @@ u8 ARM7IORead8(u32 addr)
case 0x04004501: return DSi_I2C::Cnt;
case 0x04004D00: if (SCFG_BIOS & (1<<10)) return 0; return ConsoleID & 0xFF;
- case 0x04004D01: if (SCFG_BIOS & (1<<10)) return 0; return (ConsoleID >> 8) & 0xFF;
+ case 0x04004fD01: if (SCFG_BIOS & (1<<10)) return 0; return (ConsoleID >> 8) & 0xFF;
case 0x04004D02: if (SCFG_BIOS & (1<<10)) return 0; return (ConsoleID >> 16) & 0xFF;
case 0x04004D03: if (SCFG_BIOS & (1<<10)) return 0; return (ConsoleID >> 24) & 0xFF;
case 0x04004D04: if (SCFG_BIOS & (1<<10)) return 0; return (ConsoleID >> 32) & 0xFF;
diff --git a/src/DSi.h b/src/DSi.h
index 8cc8fd5..40f22bb 100644
--- a/src/DSi.h
+++ b/src/DSi.h
@@ -25,6 +25,8 @@
namespace DSi
{
+extern u16 SCFG_BIOS;
+
extern u8 ARM9iBIOS[0x10000];
extern u8 ARM7iBIOS[0x10000];
@@ -34,6 +36,19 @@ extern u64 ConsoleID;
extern DSi_SDHost* SDMMC;
extern DSi_SDHost* SDIO;
+const u32 NWRAMSize = 0x40000;
+
+extern u8* NWRAM_A;
+extern u8* NWRAM_B;
+extern u8* NWRAM_C;
+
+extern u8* NWRAMMap_A[2][4];
+extern u8* NWRAMMap_B[3][8];
+extern u8* NWRAMMap_C[3][8];
+
+extern u32 NWRAMStart[2][3];
+extern u32 NWRAMEnd[2][3];
+extern u32 NWRAMMask[2][3];
bool Init();
void DeInit();
diff --git a/src/DSi_I2C.cpp b/src/DSi_I2C.cpp
index 9984f5e..e22c708 100644
--- a/src/DSi_I2C.cpp
+++ b/src/DSi_I2C.cpp
@@ -21,6 +21,7 @@
#include "DSi.h"
#include "DSi_I2C.h"
#include "DSi_Camera.h"
+#include "ARM.h"
namespace DSi_BPTWL
@@ -108,7 +109,8 @@ void Write(u8 val, bool last)
printf("BPTWL: soft-reset\n");
val = 0; // checkme
// TODO: soft-reset might need to be scheduled later!
- DSi::SoftReset();
+ // TODO: this has been moved for the JIT to work, nothing is confirmed here
+ NDS::ARM7->Halt(4);
CurPos = -1;
return;
}
diff --git a/src/NDS.cpp b/src/NDS.cpp
index 3d65482..6981a42 100644
--- a/src/NDS.cpp
+++ b/src/NDS.cpp
@@ -32,8 +32,11 @@
#include "Wifi.h"
#include "AREngine.h"
#include "Platform.h"
+
+#ifdef JIT_ENABLED
#include "ARMJIT.h"
#include "ARMJIT_Memory.h"
+#endif
#include "DSi.h"
#include "DSi_SPI_TSC.h"
@@ -173,7 +176,7 @@ bool Init()
#ifdef JIT_ENABLED
ARMJIT::Init();
#else
- MainRAM = new u8[MainRAMSize];
+ MainRAM = new u8[0x1000000];
ARM7WRAM = new u8[ARM7WRAMSize];
SharedWRAM = new u8[SharedWRAMSize];
#endif
@@ -1837,7 +1840,7 @@ u8 ARM9Read8(u32 addr)
switch (addr & 0xFF000000)
{
case 0x02000000:
- return *(u8*)&MainRAM[addr & (MainRAMSize - 1)];
+ return *(u8*)&MainRAM[addr & MainRAMMask];
case 0x03000000:
if (SWRAM_ARM9.Mem)
@@ -1902,7 +1905,7 @@ u16 ARM9Read16(u32 addr)
switch (addr & 0xFF000000)
{
case 0x02000000:
- return *(u16*)&MainRAM[addr & (MainRAMSize - 1)];
+ return *(u16*)&MainRAM[addr & MainRAMMask];
case 0x03000000:
if (SWRAM_ARM9.Mem)
@@ -2031,16 +2034,13 @@ void ARM9Write8(u32 addr, u8 val)
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_MainRAM>(addr);
#endif
*(u8*)&MainRAM[addr & MainRAMMask] = val;
-#ifdef JIT_ENABLED
- ARMJIT::InvalidateMainRAMIfNecessary(addr);
-#endif
return;
case 0x03000000:
if (SWRAM_ARM9.Mem)
{
#ifdef JIT_ENABLED
- ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_SWRAM>(addr);
+ ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_SharedWRAM>(addr);
#endif
*(u8*)&SWRAM_ARM9.Mem[addr & SWRAM_ARM9.Mask] = val;
}
@@ -2090,16 +2090,13 @@ void ARM9Write16(u32 addr, u16 val)
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_MainRAM>(addr);
#endif
*(u16*)&MainRAM[addr & MainRAMMask] = val;
-#ifdef JIT_ENABLED
- ARMJIT::InvalidateMainRAMIfNecessary(addr);
-#endif
return;
case 0x03000000:
if (SWRAM_ARM9.Mem)
{
#ifdef JIT_ENABLED
- ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_SWRAM>(addr);
+ ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_SharedWRAM>(addr);
#endif
*(u16*)&SWRAM_ARM9.Mem[addr & SWRAM_ARM9.Mask] = val;
}
@@ -2168,16 +2165,13 @@ void ARM9Write32(u32 addr, u32 val)
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_MainRAM>(addr);
#endif
*(u32*)&MainRAM[addr & MainRAMMask] = val;
-#ifdef JIT_ENABLED
- ARMJIT::InvalidateMainRAMIfNecessary(addr);
-#endif
return ;
case 0x03000000:
if (SWRAM_ARM9.Mem)
{
#ifdef JIT_ENABLED
- ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_SWRAM>(addr);
+ ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_SharedWRAM>(addr);
#endif
*(u32*)&SWRAM_ARM9.Mem[addr & SWRAM_ARM9.Mask] = val;
}
@@ -2235,7 +2229,7 @@ void ARM9Write32(u32 addr, u32 val)
return;
}
- printf("unknown arm9 write32 %08X %08X | %08X\n", addr, val, ARM9->R[15]);
+ //printf("unknown arm9 write32 %08X %08X | %08X\n", addr, val, ARM9->R[15]);
}
bool ARM9GetMemRegion(u32 addr, bool write, MemRegion* region)
@@ -2475,16 +2469,13 @@ void ARM7Write8(u32 addr, u8 val)
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_MainRAM>(addr);
#endif
*(u8*)&MainRAM[addr & MainRAMMask] = val;
-#ifdef JIT_ENABLED
- ARMJIT::InvalidateMainRAMIfNecessary(addr);
-#endif
return;
case 0x03000000:
if (SWRAM_ARM7.Mem)
{
#ifdef JIT_ENABLED
- ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_SWRAM>(addr);
+ ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_SharedWRAM>(addr);
#endif
*(u8*)&SWRAM_ARM7.Mem[addr & SWRAM_ARM7.Mask] = val;
return;
@@ -2552,16 +2543,13 @@ void ARM7Write16(u32 addr, u16 val)
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_MainRAM>(addr);
#endif
*(u16*)&MainRAM[addr & MainRAMMask] = val;
-#ifdef JIT_ENABLED
- ARMJIT::InvalidateMainRAMIfNecessary(addr);
-#endif
return;
case 0x03000000:
if (SWRAM_ARM7.Mem)
{
#ifdef JIT_ENABLED
- ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_SWRAM>(addr);
+ ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_SharedWRAM>(addr);
#endif
*(u16*)&SWRAM_ARM7.Mem[addr & SWRAM_ARM7.Mask] = val;
return;
@@ -2639,16 +2627,13 @@ void ARM7Write32(u32 addr, u32 val)
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_MainRAM>(addr);
#endif
*(u32*)&MainRAM[addr & MainRAMMask] = val;
-#ifdef JIT_ENABLED
- ARMJIT::InvalidateMainRAMIfNecessary(addr);
-#endif
return;
case 0x03000000:
if (SWRAM_ARM7.Mem)
{
#ifdef JIT_ENABLED
- ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_SWRAM>(addr);
+ ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_SharedWRAM>(addr);
#endif
*(u32*)&SWRAM_ARM7.Mem[addr & SWRAM_ARM7.Mask] = val;
return;
diff --git a/src/NDS.h b/src/NDS.h
index 4b4f9a1..e0a5045 100644
--- a/src/NDS.h
+++ b/src/NDS.h
@@ -165,6 +165,8 @@ extern u16 ARM7BIOSProt;
extern u8* MainRAM;
extern u32 MainRAMMask;
+const u32 MainRAMMaxSize = 0x1000000;
+
const u32 SharedWRAMSize = 0x8000;
extern u8* SharedWRAM;
diff --git a/src/frontend/qt_sdl/EmuSettingsDialog.cpp b/src/frontend/qt_sdl/EmuSettingsDialog.cpp
index 09faf4e..9ee7b9a 100644
--- a/src/frontend/qt_sdl/EmuSettingsDialog.cpp
+++ b/src/frontend/qt_sdl/EmuSettingsDialog.cpp
@@ -32,6 +32,7 @@
EmuSettingsDialog* EmuSettingsDialog::currentDlg = nullptr;
extern char* EmuDirectory;
+extern bool RunningSomething;
EmuSettingsDialog::EmuSettingsDialog(QWidget* parent) : QDialog(parent), ui(new Ui::EmuSettingsDialog)
@@ -53,6 +54,22 @@ EmuSettingsDialog::EmuSettingsDialog(QWidget* parent) : QDialog(parent), ui(new
ui->cbxConsoleType->setCurrentIndex(Config::ConsoleType);
ui->chkDirectBoot->setChecked(Config::DirectBoot != 0);
+
+#ifdef JIT_ENABLED
+ ui->chkEnableJIT->setChecked(Config::JIT_Enable != 0);
+ ui->chkJITBranchOptimisations->setChecked(Config::JIT_BranchOptimisations != 0);
+ ui->chkJITLiteralOptimisations->setChecked(Config::JIT_LiteralOptimisations != 0);
+ ui->chkJITFastMemory->setChecked(Config::JIT_FastMemory != 0);
+ ui->spnJITMaximumBlockSize->setValue(Config::JIT_MaxBlockSize);
+#else
+ ui->chkEnableJIT->setDisabled(true);
+ ui->chkJITBranchOptimisations->setDisabled(true);
+ ui->chkJITLiteralOptimisations->setDisabled(true);
+ ui->chkJITFastMemory->setDisabled(true);
+ ui->spnJITMaximumBlockSize->setDisabled(true);
+#endif
+
+ on_chkEnableJIT_toggled();
}
EmuSettingsDialog::~EmuSettingsDialog()
@@ -102,29 +119,78 @@ void EmuSettingsDialog::verifyFirmware()
}
}
-void EmuSettingsDialog::on_EmuSettingsDialog_accepted()
+void EmuSettingsDialog::done(int r)
{
- verifyFirmware();
-
- strncpy(Config::BIOS9Path, ui->txtBIOS9Path->text().toStdString().c_str(), 1023); Config::BIOS9Path[1023] = '\0';
- strncpy(Config::BIOS7Path, ui->txtBIOS7Path->text().toStdString().c_str(), 1023); Config::BIOS7Path[1023] = '\0';
- strncpy(Config::FirmwarePath, ui->txtFirmwarePath->text().toStdString().c_str(), 1023); Config::FirmwarePath[1023] = '\0';
-
- strncpy(Config::DSiBIOS9Path, ui->txtDSiBIOS9Path->text().toStdString().c_str(), 1023); Config::DSiBIOS9Path[1023] = '\0';
- strncpy(Config::DSiBIOS7Path, ui->txtDSiBIOS7Path->text().toStdString().c_str(), 1023); Config::DSiBIOS7Path[1023] = '\0';
- strncpy(Config::DSiFirmwarePath, ui->txtDSiFirmwarePath->text().toStdString().c_str(), 1023); Config::DSiFirmwarePath[1023] = '\0';
- strncpy(Config::DSiNANDPath, ui->txtDSiNANDPath->text().toStdString().c_str(), 1023); Config::DSiNANDPath[1023] = '\0';
-
- Config::ConsoleType = ui->cbxConsoleType->currentIndex();
- Config::DirectBoot = ui->chkDirectBoot->isChecked() ? 1:0;
-
- Config::Save();
+ if (r == QDialog::Accepted)
+ {
+ verifyFirmware();
+
+ int consoleType = ui->cbxConsoleType->currentIndex();
+ int directBoot = ui->chkDirectBoot->isChecked() ? 1:0;
+
+ int jitEnable = ui->chkEnableJIT->isChecked() ? 1:0;
+ int jitMaxBlockSize = ui->spnJITMaximumBlockSize->value();
+ int jitBranchOptimisations = ui->chkJITBranchOptimisations->isChecked() ? 1:0;
+ int jitLiteralOptimisations = ui->chkJITLiteralOptimisations->isChecked() ? 1:0;
+ int jitFastMemory = ui->chkJITFastMemory->isChecked() ? 1:0;
+
+ std::string bios9Path = ui->txtBIOS9Path->text().toStdString();
+ std::string bios7Path = ui->txtBIOS7Path->text().toStdString();
+ std::string firmwarePath = ui->txtFirmwarePath->text().toStdString();
+ std::string dsiBios9Path = ui->txtDSiBIOS9Path->text().toStdString();
+ std::string dsiBios7Path = ui->txtDSiBIOS7Path->text().toStdString();
+ std::string dsiFirmwarePath = ui->txtDSiFirmwarePath->text().toStdString();
+ std::string dsiNANDPath = ui->txtDSiNANDPath->text().toStdString();
+
+ if (consoleType != Config::ConsoleType
+ || directBoot != Config::DirectBoot
+#ifdef JIT_ENABLED
+ || jitEnable != Config::JIT_Enable
+ || jitMaxBlockSize != Config::JIT_MaxBlockSize
+ || jitBranchOptimisations != Config::JIT_BranchOptimisations
+ || jitLiteralOptimisations != Config::JIT_LiteralOptimisations
+ || jitFastMemory != Config::JIT_FastMemory
+#endif
+ || strcmp(Config::BIOS9Path, bios9Path.c_str()) != 0
+ || strcmp(Config::BIOS7Path, bios7Path.c_str()) != 0
+ || strcmp(Config::FirmwarePath, firmwarePath.c_str()) != 0
+ || strcmp(Config::DSiBIOS9Path, dsiBios9Path.c_str()) != 0
+ || strcmp(Config::DSiBIOS7Path, dsiBios7Path.c_str()) != 0
+ || strcmp(Config::DSiFirmwarePath, dsiFirmwarePath.c_str()) != 0
+ || strcmp(Config::DSiNANDPath, dsiNANDPath.c_str()) != 0)
+ {
+ if (RunningSomething
+ && QMessageBox::warning(this, "Reset necessary to apply changes",
+ "The emulation will be reset for the changes to take place",
+ QMessageBox::Yes, QMessageBox::Cancel) != QMessageBox::Yes)
+ return;
+
+ strncpy(Config::BIOS9Path, bios9Path.c_str(), 1023); Config::BIOS9Path[1023] = '\0';
+ strncpy(Config::BIOS7Path, bios7Path.c_str(), 1023); Config::BIOS7Path[1023] = '\0';
+ strncpy(Config::FirmwarePath, firmwarePath.c_str(), 1023); Config::FirmwarePath[1023] = '\0';
+
+ strncpy(Config::DSiBIOS9Path, dsiBios9Path.c_str(), 1023); Config::DSiBIOS9Path[1023] = '\0';
+ strncpy(Config::DSiBIOS7Path, dsiBios7Path.c_str(), 1023); Config::DSiBIOS7Path[1023] = '\0';
+ strncpy(Config::DSiFirmwarePath, dsiFirmwarePath.c_str(), 1023); Config::DSiFirmwarePath[1023] = '\0';
+ strncpy(Config::DSiNANDPath, dsiNANDPath.c_str(), 1023); Config::DSiNANDPath[1023] = '\0';
+
+ #ifdef JIT_ENABLED
+ Config::JIT_Enable = jitEnable;
+ Config::JIT_MaxBlockSize = jitMaxBlockSize;
+ Config::JIT_BranchOptimisations = jitBranchOptimisations;
+ Config::JIT_LiteralOptimisations = jitLiteralOptimisations;
+ Config::JIT_FastMemory = jitFastMemory;
+ #endif
+
+ Config::ConsoleType = consoleType;
+ Config::DirectBoot = directBoot;
+
+ Config::Save();
+ }
+ }
- closeDlg();
-}
+ QDialog::done(r);
-void EmuSettingsDialog::on_EmuSettingsDialog_rejected()
-{
closeDlg();
}
@@ -211,3 +277,12 @@ void EmuSettingsDialog::on_btnDSiNANDBrowse_clicked()
ui->txtDSiNANDPath->setText(file);
}
+
+void EmuSettingsDialog::on_chkEnableJIT_toggled()
+{
+ bool disabled = !ui->chkEnableJIT->isChecked();
+ ui->chkJITBranchOptimisations->setDisabled(disabled);
+ ui->chkJITLiteralOptimisations->setDisabled(disabled);
+ ui->chkJITFastMemory->setDisabled(disabled);
+ ui->spnJITMaximumBlockSize->setDisabled(disabled);
+} \ No newline at end of file
diff --git a/src/frontend/qt_sdl/EmuSettingsDialog.h b/src/frontend/qt_sdl/EmuSettingsDialog.h
index f604ba5..268036c 100644
--- a/src/frontend/qt_sdl/EmuSettingsDialog.h
+++ b/src/frontend/qt_sdl/EmuSettingsDialog.h
@@ -51,8 +51,7 @@ public:
}
private slots:
- void on_EmuSettingsDialog_accepted();
- void on_EmuSettingsDialog_rejected();
+ void done(int r);
void on_btnBIOS9Browse_clicked();
void on_btnBIOS7Browse_clicked();
@@ -63,6 +62,8 @@ private slots:
void on_btnDSiFirmwareBrowse_clicked();
void on_btnDSiNANDBrowse_clicked();
+ void on_chkEnableJIT_toggled();
+
private:
void verifyFirmware();
diff --git a/src/frontend/qt_sdl/EmuSettingsDialog.ui b/src/frontend/qt_sdl/EmuSettingsDialog.ui
index 4894fa5..11d48cc 100644
--- a/src/frontend/qt_sdl/EmuSettingsDialog.ui
+++ b/src/frontend/qt_sdl/EmuSettingsDialog.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>490</width>
- <height>392</height>
+ <width>514</width>
+ <height>359</height>
</rect>
</property>
<property name="sizePolicy">
@@ -24,243 +24,336 @@
<enum>QLayout::SetFixedSize</enum>
</property>
<item>
- <widget class="QGroupBox" name="groupBox">
- <property name="title">
- <string>DS mode</string>
+ <widget class="QTabWidget" name="tabWidget">
+ <property name="currentIndex">
+ <number>0</number>
</property>
- <layout class="QGridLayout" name="gridLayout_2">
- <item row="0" column="1">
- <widget class="QLineEdit" name="txtBIOS9Path">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>290</width>
- <height>0</height>
- </size>
- </property>
- <property name="statusTip">
- <string/>
- </property>
- <property name="whatsThis">
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;DS-mode ARM9 BIOS&lt;/p&gt;&lt;p&gt;Size should be 4 KB&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_3">
- <property name="text">
- <string>DS firmware:</string>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_2">
- <property name="text">
- <string>DS ARM7 BIOS:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="0">
- <widget class="QLabel" name="label">
- <property name="text">
- <string>DS ARM9 BIOS:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="2">
- <widget class="QPushButton" name="btnBIOS9Browse">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Browse...</string>
- </property>
- <property name="autoDefault">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QLineEdit" name="txtBIOS7Path">
- <property name="whatsThis">
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;DS-mode ARM7 BIOS&lt;/p&gt;&lt;p&gt;Size should be 16 KB&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
- </property>
- </widget>
- </item>
- <item row="1" column="2">
- <widget class="QPushButton" name="btnBIOS7Browse">
- <property name="text">
- <string>Browse...</string>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QLineEdit" name="txtFirmwarePath">
- <property name="whatsThis">
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;DS-mode firmware&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;Possible firmwares:&lt;/p&gt;&lt;p&gt;* 128 KB: DS-mode firmware from a DSi or 3DS. Not bootable.&lt;/p&gt;&lt;p&gt;* 256 KB: regular DS firmware.&lt;/p&gt;&lt;p&gt;* 512 KB: iQue DS firmware.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
- </property>
- </widget>
- </item>
- <item row="2" column="2">
- <widget class="QPushButton" name="btnFirmwareBrowse">
- <property name="text">
- <string>Browse...</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QGroupBox" name="groupBox_3">
- <property name="title">
- <string>DSi mode</string>
- </property>
- <layout class="QGridLayout" name="gridLayout_3">
- <item row="0" column="2">
- <widget class="QPushButton" name="btnDSiBIOS9Browse">
- <property name="text">
- <string>Browse...</string>
- </property>
- </widget>
- </item>
- <item row="0" column="0">
- <widget class="QLabel" name="label_5">
- <property name="text">
- <string>DSi ARM9 BIOS:</string>
- </property>
- </widget>
- </item>
- <item row="2" column="2">
- <widget class="QPushButton" name="btnDSiFirmwareBrowse">
- <property name="text">
- <string>Browse...</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QLineEdit" name="txtDSiBIOS7Path">
- <property name="whatsThis">
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;DSi-mode ARM7 BIOS&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;Size should be 64 KB&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QLineEdit" name="txtDSiFirmwarePath">
- <property name="whatsThis">
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;DSi-mode firmware (used for DS-mode backwards compatibility)&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;Size should be 128 KB&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
- </property>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_6">
- <property name="text">
- <string>DSi ARM7 BIOS:</string>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_7">
- <property name="text">
- <string>DSi firmware:</string>
- </property>
- </widget>
- </item>
- <item row="1" column="2">
- <widget class="QPushButton" name="btnDSiBIOS7Browse">
- <property name="text">
- <string>Browse...</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QLineEdit" name="txtDSiBIOS9Path">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="whatsThis">
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;DSi-mode ARM9 BIOS&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;Size should be 64 KB&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
- </property>
- </widget>
- </item>
- <item row="3" column="0">
- <widget class="QLabel" name="label_8">
- <property name="text">
- <string>DSi NAND:</string>
- </property>
- </widget>
- </item>
- <item row="3" column="1">
- <widget class="QLineEdit" name="txtDSiNANDPath">
- <property name="whatsThis">
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;DSi NAND dump&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;Should have 'nocash footer' at the end&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
- </property>
- </widget>
- </item>
- <item row="3" column="2">
- <widget class="QPushButton" name="btnDSiNANDBrowse">
- <property name="text">
- <string>Browse...</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QGroupBox" name="groupBox_2">
- <property name="title">
- <string>General</string>
- </property>
- <layout class="QGridLayout" name="gridLayout">
- <item row="0" column="0">
- <widget class="QLabel" name="label_4">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Console type:</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QComboBox" name="cbxConsoleType">
- <property name="sizePolicy">
- <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="whatsThis">
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The type of console to emulate&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
- </property>
- </widget>
- </item>
- <item row="1" column="0" colspan="2">
- <widget class="QCheckBox" name="chkDirectBoot">
- <property name="whatsThis">
- <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;When loading a ROM, completely skip the regular boot process (&amp;quot;Nintendo DS&amp;quot; screen) to boot the ROM directly.&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;Note: if your firmware dump isn't bootable, the ROM will be booted directly regardless of this setting.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
- </property>
- <property name="text">
- <string>Boot game directly</string>
- </property>
- </widget>
- </item>
- </layout>
+ <widget class="QWidget" name="tab">
+ <attribute name="title">
+ <string>General</string>
+ </attribute>
+ <layout class="QFormLayout" name="formLayout_4">
+ <item row="1" column="1">
+ <widget class="QComboBox" name="cbxConsoleType">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The type of console to emulate&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QCheckBox" name="chkDirectBoot">
+ <property name="whatsThis">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;When loading a ROM, completely skip the regular boot process (&amp;quot;Nintendo DS&amp;quot; screen) to boot the ROM directly.&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;Note: if your firmware dump isn't bootable, the ROM will be booted directly regardless of this setting.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string>Boot game directly</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <spacer name="verticalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_4">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Console type:</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tab_2">
+ <attribute name="title">
+ <string>BIOS Files</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>DS mode</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>DS firmware:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLineEdit" name="txtFirmwarePath">
+ <property name="whatsThis">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;DS-mode firmware&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;Possible firmwares:&lt;/p&gt;&lt;p&gt;* 128 KB: DS-mode firmware from a DSi or 3DS. Not bootable.&lt;/p&gt;&lt;p&gt;* 256 KB: regular DS firmware.&lt;/p&gt;&lt;p&gt;* 512 KB: iQue DS firmware.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="txtBIOS7Path">
+ <property name="whatsThis">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;DS-mode ARM7 BIOS&lt;/p&gt;&lt;p&gt;Size should be 16 KB&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QPushButton" name="btnBIOS9Browse">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Browse...</string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2">
+ <widget class="QPushButton" name="btnFirmwareBrowse">
+ <property name="text">
+ <string>Browse...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>DS ARM7 BIOS:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>DS ARM9 BIOS:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QPushButton" name="btnBIOS7Browse">
+ <property name="text">
+ <string>Browse...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="txtBIOS9Path">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>290</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="statusTip">
+ <string/>
+ </property>
+ <property name="whatsThis">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;DS-mode ARM9 BIOS&lt;/p&gt;&lt;p&gt;Size should be 4 KB&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox_3">
+ <property name="title">
+ <string>DSi mode</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_3">
+ <item row="0" column="2">
+ <widget class="QPushButton" name="btnDSiBIOS9Browse">
+ <property name="text">
+ <string>Browse...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_5">
+ <property name="text">
+ <string>DSi ARM9 BIOS:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="2">
+ <widget class="QPushButton" name="btnDSiFirmwareBrowse">
+ <property name="text">
+ <string>Browse...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="txtDSiBIOS7Path">
+ <property name="whatsThis">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;DSi-mode ARM7 BIOS&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;Size should be 64 KB&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLineEdit" name="txtDSiFirmwarePath">
+ <property name="whatsThis">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;DSi-mode firmware (used for DS-mode backwards compatibility)&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;Size should be 128 KB&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_6">
+ <property name="text">
+ <string>DSi ARM7 BIOS:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_7">
+ <property name="text">
+ <string>DSi firmware:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QPushButton" name="btnDSiBIOS7Browse">
+ <property name="text">
+ <string>Browse...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="txtDSiBIOS9Path">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;DSi-mode ARM9 BIOS&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;Size should be 64 KB&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="label_8">
+ <property name="text">
+ <string>DSi NAND:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QLineEdit" name="txtDSiNANDPath">
+ <property name="whatsThis">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;DSi NAND dump&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;Should have 'nocash footer' at the end&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="2">
+ <widget class="QPushButton" name="btnDSiNANDBrowse">
+ <property name="text">
+ <string>Browse...</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tab_3">
+ <attribute name="title">
+ <string>CPU Emulation</string>
+ </attribute>
+ <layout class="QFormLayout" name="formLayout_5">
+ <item row="0" column="0">
+ <widget class="QCheckBox" name="chkEnableJIT">
+ <property name="text">
+ <string>Enable JIT recompiler</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_9">
+ <property name="text">
+ <string>Maximum JIT block size:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QSpinBox" name="spnJITMaximumBlockSize">
+ <property name="minimum">
+ <number>1</number>
+ </property>
+ <property name="maximum">
+ <number>32</number>
+ </property>
+ <property name="value">
+ <number>32</number>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QCheckBox" name="chkJITBranchOptimisations">
+ <property name="text">
+ <string>Branch Optimisations</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QCheckBox" name="chkJITLiteralOptimisations">
+ <property name="text">
+ <string>Literal Optimisations</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0">
+ <widget class="QCheckBox" name="chkJITFastMemory">
+ <property name="text">
+ <string>Fast Memory</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0">
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
</widget>
</item>
<item>
@@ -275,6 +368,27 @@
</item>
</layout>
</widget>
+ <tabstops>
+ <tabstop>tabWidget</tabstop>
+ <tabstop>cbxConsoleType</tabstop>
+ <tabstop>chkDirectBoot</tabstop>
+ <tabstop>txtBIOS9Path</tabstop>
+ <tabstop>txtBIOS7Path</tabstop>
+ <tabstop>txtFirmwarePath</tabstop>
+ <tabstop>txtDSiBIOS9Path</tabstop>
+ <tabstop>txtDSiBIOS7Path</tabstop>
+ <tabstop>txtDSiFirmwarePath</tabstop>
+ <tabstop>txtDSiNANDPath</tabstop>
+ <tabstop>btnBIOS9Browse</tabstop>
+ <tabstop>btnBIOS7Browse</tabstop>
+ <tabstop>btnFirmwareBrowse</tabstop>
+ <tabstop>btnDSiBIOS9Browse</tabstop>
+ <tabstop>btnDSiBIOS7Browse</tabstop>
+ <tabstop>btnDSiFirmwareBrowse</tabstop>
+ <tabstop>btnDSiNANDBrowse</tabstop>
+ <tabstop>chkEnableJIT</tabstop>
+ <tabstop>spnJITMaximumBlockSize</tabstop>
+ </tabstops>
<resources/>
<connections>
<connection>
@@ -284,8 +398,8 @@
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
- <x>248</x>
- <y>254</y>
+ <x>257</x>
+ <y>349</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
@@ -300,8 +414,8 @@
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
- <x>316</x>
- <y>260</y>
+ <x>325</x>
+ <y>349</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp
index fa542ad..4557d0e 100644
--- a/src/frontend/qt_sdl/main.cpp
+++ b/src/frontend/qt_sdl/main.cpp
@@ -1641,7 +1641,14 @@ void MainWindow::onStop()
void MainWindow::onOpenEmuSettings()
{
- EmuSettingsDialog::openDlg(this);
+ EmuSettingsDialog* dlg = EmuSettingsDialog::openDlg(this);
+ connect(dlg, &EmuSettingsDialog::finished, this, &MainWindow::onEmuSettingsDialogFinished);
+}
+
+void MainWindow::onEmuSettingsDialogFinished(int res)
+{
+ if (RunningSomething)
+ onReset();
}
void MainWindow::onOpenInputConfig()
diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h
index 279aed8..eec2a48 100644
--- a/src/frontend/qt_sdl/main.h
+++ b/src/frontend/qt_sdl/main.h
@@ -199,6 +199,7 @@ private slots:
void onStop();
void onOpenEmuSettings();
+ void onEmuSettingsDialogFinished(int res);
void onOpenInputConfig();
void onInputConfigFinished(int res);
void onOpenVideoSettings();
diff --git a/src/libui_sdl/DlgEmuSettings.cpp b/src/libui_sdl/DlgEmuSettings.cpp
deleted file mode 100644
index 0df9c6c..0000000
--- a/src/libui_sdl/DlgEmuSettings.cpp
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- Copyright 2016-2020 Arisotura
-
- This file is part of melonDS.
-
- melonDS is free software: you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
-
- melonDS is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with melonDS. If not, see http://www.gnu.org/licenses/.
-*/
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "libui/ui.h"
-
-#include "../types.h"
-#include "PlatformConfig.h"
-
-#include "DlgEmuSettings.h"
-
-
-void ApplyNewSettings(int type);
-
-extern bool RunningSomething;
-
-namespace DlgEmuSettings
-{
-
-bool opened;
-uiWindow* win;
-
-uiCheckbox* cbDirectBoot;
-
-#ifdef JIT_ENABLED
-uiCheckbox* cbJITEnabled;
-uiEntry* enJITMaxBlockSize;
-uiCheckbox* cbJITBranchOptimisations;
-uiCheckbox* cbJITLiteralOptimisations;
-#endif
-
-int OnCloseWindow(uiWindow* window, void* blarg)
-{
- opened = false;
- return 1;
-}
-
-void OnCancel(uiButton* btn, void* blarg)
-{
- uiControlDestroy(uiControl(win));
- opened = false;
-}
-
-void OnOk(uiButton* btn, void* blarg)
-{
-#ifdef JIT_ENABLED
- bool restart = false;
-
- bool enableJit = uiCheckboxChecked(cbJITEnabled);
- char* maxBlockSizeStr = uiEntryText(enJITMaxBlockSize);
- long blockSize = strtol(maxBlockSizeStr, NULL, 10);
- bool branchOptimisations = uiCheckboxChecked(cbJITBranchOptimisations);
- bool literalOptimisations = uiCheckboxChecked(cbJITLiteralOptimisations);
- uiFreeText(maxBlockSizeStr);
- if (blockSize < 1)
- blockSize = 1;
- if (blockSize > 32)
- blockSize = 32;
-
- if (enableJit != Config::JIT_Enable || blockSize != Config::JIT_MaxBlockSize
- || branchOptimisations != Config::JIT_BrancheOptimisations
- || literalOptimisations != Config::JIT_LiteralOptimisations)
- {
- if (RunningSomething &&
- !uiMsgBoxConfirm(win, "Reset emulator",
- "Changing JIT settings requires a reset.\n\nDo you want to continue?"))
- return;
-
- Config::JIT_Enable = enableJit;
- Config::JIT_MaxBlockSize = blockSize;
- Config::JIT_BrancheOptimisations = branchOptimisations;
- Config::JIT_LiteralOptimisations = literalOptimisations;
-
- restart = true;
- }
-#endif
-
- Config::DirectBoot = uiCheckboxChecked(cbDirectBoot);
-
- Config::Save();
-
- uiControlDestroy(uiControl(win));
- opened = false;
-
-#ifdef JIT_ENABLED
- if (restart)
- ApplyNewSettings(4);
-#endif
-}
-
-#ifdef JIT_ENABLED
-void OnJITStateChanged(uiCheckbox* cb, void* blarg)
-{
- if (uiCheckboxChecked(cb))
- {
- uiControlEnable(uiControl(enJITMaxBlockSize));
- uiControlEnable(uiControl(cbJITBranchOptimisations));
- uiControlEnable(uiControl(cbJITLiteralOptimisations));
- }
- else
- {
- uiControlDisable(uiControl(enJITMaxBlockSize));
- uiControlDisable(uiControl(cbJITBranchOptimisations));
- uiControlDisable(uiControl(cbJITLiteralOptimisations));
- }
-}
-#endif
-
-void Open()
-{
- if (opened)
- {
- uiControlSetFocus(uiControl(win));
- return;
- }
-
- opened = true;
- win = uiNewWindow("Emu settings - melonDS", 300, 50, 0, 0, 0);
- uiWindowSetMargined(win, 1);
- uiWindowOnClosing(win, OnCloseWindow, NULL);
-
- uiBox* top = uiNewVerticalBox();
- uiWindowSetChild(win, uiControl(top));
-
- {
- uiBox* in_ctrl = uiNewVerticalBox();
- uiBoxAppend(top, uiControl(in_ctrl), 0);
-
- cbDirectBoot = uiNewCheckbox("Boot game directly");
- uiBoxAppend(in_ctrl, uiControl(cbDirectBoot), 0);
- }
-
-#ifdef JIT_ENABLED
- {
- uiLabel* dummy = uiNewLabel("");
- uiBoxAppend(top, uiControl(dummy), 0);
- }
-
- {
- uiGroup* grp = uiNewGroup("JIT");
- uiBoxAppend(top, uiControl(grp), 1);
-
- uiBox* in_ctrl = uiNewVerticalBox();
- uiGroupSetChild(grp, uiControl(in_ctrl));
-
- cbJITEnabled = uiNewCheckbox("Enable JIT recompiler");
- uiBoxAppend(in_ctrl, uiControl(cbJITEnabled), 0);
-
- uiCheckboxOnToggled(cbJITEnabled, OnJITStateChanged, NULL);
-
- {
- uiBox* row = uiNewHorizontalBox();
- uiBoxAppend(in_ctrl, uiControl(row), 0);
-
- uiLabel* lbl = uiNewLabel("Maximum block size (1-32): ");
- uiBoxAppend(row, uiControl(lbl), 0);
-
- enJITMaxBlockSize = uiNewEntry();
- uiBoxAppend(row, uiControl(enJITMaxBlockSize), 0);
- }
-
- {
- uiBox* row = uiNewHorizontalBox();
- uiBoxAppend(in_ctrl, uiControl(row), 0);
-
- uiLabel* lbl = uiNewLabel("If you experience problems with a certain game, you can try disabling these options:");
- uiBoxAppend(row, uiControl(lbl), 0);
- }
-
- {
- uiBox* row = uiNewHorizontalBox();
- uiBoxAppend(in_ctrl, uiControl(row), 0);
-
- cbJITBranchOptimisations = uiNewCheckbox("Branch optimisations");
- uiBoxAppend(row, uiControl(cbJITBranchOptimisations), 0);
- }
-
- {
- uiBox* row = uiNewHorizontalBox();
- uiBoxAppend(in_ctrl, uiControl(row), 0);
-
- cbJITLiteralOptimisations = uiNewCheckbox("Literal optimisations");
- uiBoxAppend(row, uiControl(cbJITLiteralOptimisations), 0);
- }
- }
-#endif
-
- {
- uiLabel* dummy = uiNewLabel("");
- uiBoxAppend(top, uiControl(dummy), 0);
- }
-
- {
- uiBox* in_ctrl = uiNewHorizontalBox();
- uiBoxSetPadded(in_ctrl, 1);
- uiBoxAppend(top, uiControl(in_ctrl), 0);
-
- uiLabel* dummy = uiNewLabel("");
- uiBoxAppend(in_ctrl, uiControl(dummy), 1);
-
- uiButton* btncancel = uiNewButton("Cancel");
- uiButtonOnClicked(btncancel, OnCancel, NULL);
- uiBoxAppend(in_ctrl, uiControl(btncancel), 0);
-
- uiButton* btnok = uiNewButton("Ok");
- uiButtonOnClicked(btnok, OnOk, NULL);
- uiBoxAppend(in_ctrl, uiControl(btnok), 0);
- }
-
- uiCheckboxSetChecked(cbDirectBoot, Config::DirectBoot);
-
-#ifdef JIT_ENABLED
- uiCheckboxSetChecked(cbJITEnabled, Config::JIT_Enable);
- {
- char maxBlockSizeStr[10];
- sprintf(maxBlockSizeStr, "%d", Config::JIT_MaxBlockSize);
- uiEntrySetText(enJITMaxBlockSize, maxBlockSizeStr);
- }
- OnJITStateChanged(cbJITEnabled, NULL);
-
- uiCheckboxSetChecked(cbJITBranchOptimisations, Config::JIT_BrancheOptimisations);
- uiCheckboxSetChecked(cbJITLiteralOptimisations, Config::JIT_LiteralOptimisations);
-#endif
-
- uiControlShow(uiControl(win));
-}
-
-void Close()
-{
- if (!opened) return;
- uiControlDestroy(uiControl(win));
- opened = false;
-}
-
-}
diff --git a/src/libui_sdl/libui/ui.h b/src/libui_sdl/libui/ui.h
deleted file mode 100644
index e45fe91..0000000
--- a/src/libui_sdl/libui/ui.h
+++ /dev/null
@@ -1,764 +0,0 @@
-// 6 april 2015
-
-// TODO add a uiVerifyControlType() function that can be used by control implementations to verify controls
-
-#ifndef __LIBUI_UI_H__
-#define __LIBUI_UI_H__
-
-#include <stddef.h>
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// this macro is generated by cmake
-#ifdef libui_EXPORTS
-#ifdef _WIN32
-#define _UI_EXTERN __declspec(dllexport) extern
-#else
-#define _UI_EXTERN __attribute__((visibility("default"))) extern
-#endif
-#else
-// TODO add __declspec(dllimport) on windows, but only if not static
-#define _UI_EXTERN extern
-#endif
-
-// C++ is really really really really really really dumb about enums, so screw that and just make them anonymous
-// This has the advantage of being ABI-able should we ever need an ABI...
-#define _UI_ENUM(s) typedef unsigned int s; enum
-
-// This constant is provided because M_PI is nonstandard.
-// This comes from Go's math.Pi, which in turn comes from http://oeis.org/A000796.
-#define uiPi 3.14159265358979323846264338327950288419716939937510582097494459
-
-// TODO uiBool?
-
-typedef struct uiInitOptions uiInitOptions;
-
-struct uiInitOptions {
- size_t Size;
-};
-
-_UI_EXTERN const char *uiInit(uiInitOptions *options);
-_UI_EXTERN void uiUninit(void);
-_UI_EXTERN void uiFreeInitError(const char *err);
-
-_UI_EXTERN void uiMain(void);
-_UI_EXTERN void uiMainSteps(void);
-_UI_EXTERN int uiMainStep(int wait);
-_UI_EXTERN void uiQuit(void);
-
-_UI_EXTERN void uiQueueMain(void (*f)(void *data), void *data);
-
-_UI_EXTERN void uiOnShouldQuit(int (*f)(void *data), void *data);
-
-_UI_EXTERN void uiFreeText(char *text);
-
-typedef struct uiControl uiControl;
-
-struct uiControl {
- uint32_t Signature;
- uint32_t OSSignature;
- uint32_t TypeSignature;
- void (*Destroy)(uiControl *);
- uintptr_t (*Handle)(uiControl *);
- uiControl *(*Parent)(uiControl *);
- void (*SetParent)(uiControl *, uiControl *);
- int (*Toplevel)(uiControl *);
- int (*Visible)(uiControl *);
- void (*Show)(uiControl *);
- void (*Hide)(uiControl *);
- int (*Enabled)(uiControl *);
- void (*Enable)(uiControl *);
- void (*Disable)(uiControl *);
- void (*SetFocus)(uiControl *);
- void (*SetMinSize)(uiControl*, int, int);
-
- int MinWidth, MinHeight;
-
- void* UserData;
-};
-// TOOD add argument names to all arguments
-#define uiControl(this) ((uiControl *) (this))
-_UI_EXTERN void uiControlDestroy(uiControl *);
-_UI_EXTERN uintptr_t uiControlHandle(uiControl *);
-_UI_EXTERN uiControl *uiControlParent(uiControl *);
-_UI_EXTERN void uiControlSetParent(uiControl *, uiControl *);
-_UI_EXTERN int uiControlToplevel(uiControl *);
-_UI_EXTERN int uiControlVisible(uiControl *);
-_UI_EXTERN void uiControlShow(uiControl *);
-_UI_EXTERN void uiControlHide(uiControl *);
-_UI_EXTERN int uiControlEnabled(uiControl *);
-_UI_EXTERN void uiControlEnable(uiControl *);
-_UI_EXTERN void uiControlDisable(uiControl *);
-_UI_EXTERN void uiControlSetFocus(uiControl *);
-_UI_EXTERN void uiControlSetMinSize(uiControl *, int w, int h); // -1 = no minimum
-
-_UI_EXTERN uiControl *uiAllocControl(size_t n, uint32_t OSsig, uint32_t typesig, const char *typenamestr);
-_UI_EXTERN void uiFreeControl(uiControl *);
-
-// TODO make sure all controls have these
-_UI_EXTERN void uiControlVerifySetParent(uiControl *, uiControl *);
-_UI_EXTERN int uiControlEnabledToUser(uiControl *);
-
-_UI_EXTERN void uiUserBugCannotSetParentOnToplevel(const char *type);
-
-typedef struct uiWindow uiWindow;
-#define uiWindow(this) ((uiWindow *) (this))
-_UI_EXTERN char *uiWindowTitle(uiWindow *w);
-_UI_EXTERN void uiWindowSetTitle(uiWindow *w, const char *title);
-_UI_EXTERN void uiWindowPosition(uiWindow *w, int *x, int *y);
-_UI_EXTERN void uiWindowSetPosition(uiWindow *w, int x, int y);
-_UI_EXTERN void uiWindowContentSize(uiWindow *w, int *width, int *height);
-_UI_EXTERN void uiWindowSetContentSize(uiWindow *w, int width, int height);
-_UI_EXTERN int uiWindowMinimized(uiWindow *w);
-_UI_EXTERN void uiWindowSetMinimized(uiWindow *w, int minimized);
-_UI_EXTERN int uiWindowMaximized(uiWindow *w);
-_UI_EXTERN void uiWindowSetMaximized(uiWindow *w, int maximized);
-_UI_EXTERN int uiWindowFullscreen(uiWindow *w);
-_UI_EXTERN void uiWindowSetFullscreen(uiWindow *w, int fullscreen);
-_UI_EXTERN int uiWindowBorderless(uiWindow *w);
-_UI_EXTERN void uiWindowSetBorderless(uiWindow *w, int borderless);
-_UI_EXTERN void uiWindowSetChild(uiWindow *w, uiControl *child);
-_UI_EXTERN int uiWindowMargined(uiWindow *w);
-_UI_EXTERN void uiWindowSetMargined(uiWindow *w, int margined);
-_UI_EXTERN void uiWindowSetDropTarget(uiWindow* w, int drop);
-_UI_EXTERN uiWindow *uiNewWindow(const char *title, int width, int height, int maximized, int hasMenubar, int resizable);
-
-_UI_EXTERN void uiWindowOnContentSizeChanged(uiWindow *w, void (*f)(uiWindow *, void *), void *data);
-_UI_EXTERN void uiWindowOnClosing(uiWindow *w, int (*f)(uiWindow *w, void *data), void *data);
-_UI_EXTERN void uiWindowOnDropFile(uiWindow *w, void (*f)(uiWindow *w, char *file, void *data), void *data);
-_UI_EXTERN void uiWindowOnGetFocus(uiWindow *w, void (*f)(uiWindow *w, void *data), void *data);
-_UI_EXTERN void uiWindowOnLoseFocus(uiWindow *w, void (*f)(uiWindow *w, void *data), void *data);
-
-typedef struct uiButton uiButton;
-#define uiButton(this) ((uiButton *) (this))
-_UI_EXTERN char *uiButtonText(uiButton *b);
-_UI_EXTERN void uiButtonSetText(uiButton *b, const char *text);
-_UI_EXTERN void uiButtonOnClicked(uiButton *b, void (*f)(uiButton *b, void *data), void *data);
-_UI_EXTERN uiButton *uiNewButton(const char *text);
-
-typedef struct uiBox uiBox;
-#define uiBox(this) ((uiBox *) (this))
-_UI_EXTERN void uiBoxAppend(uiBox *b, uiControl *child, int stretchy);
-_UI_EXTERN void uiBoxDelete(uiBox *b, int index);
-_UI_EXTERN int uiBoxPadded(uiBox *b);
-_UI_EXTERN void uiBoxSetPadded(uiBox *b, int padded);
-_UI_EXTERN uiBox *uiNewHorizontalBox(void);
-_UI_EXTERN uiBox *uiNewVerticalBox(void);
-
-typedef struct uiCheckbox uiCheckbox;
-#define uiCheckbox(this) ((uiCheckbox *) (this))
-_UI_EXTERN char *uiCheckboxText(uiCheckbox *c);
-_UI_EXTERN void uiCheckboxSetText(uiCheckbox *c, const char *text);
-_UI_EXTERN void uiCheckboxOnToggled(uiCheckbox *c, void (*f)(uiCheckbox *c, void *data), void *data);
-_UI_EXTERN int uiCheckboxChecked(uiCheckbox *c);
-_UI_EXTERN void uiCheckboxSetChecked(uiCheckbox *c, int checked);
-_UI_EXTERN uiCheckbox *uiNewCheckbox(const char *text);
-
-typedef struct uiEntry uiEntry;
-#define uiEntry(this) ((uiEntry *) (this))
-_UI_EXTERN char *uiEntryText(uiEntry *e);
-_UI_EXTERN void uiEntrySetText(uiEntry *e, const char *text);
-_UI_EXTERN void uiEntryOnChanged(uiEntry *e, void (*f)(uiEntry *e, void *data), void *data);
-_UI_EXTERN int uiEntryReadOnly(uiEntry *e);
-_UI_EXTERN void uiEntrySetReadOnly(uiEntry *e, int readonly);
-_UI_EXTERN uiEntry *uiNewEntry(void);
-_UI_EXTERN uiEntry *uiNewPasswordEntry(void);
-_UI_EXTERN uiEntry *uiNewSearchEntry(void);
-
-typedef struct uiLabel uiLabel;
-#define uiLabel(this) ((uiLabel *) (this))
-_UI_EXTERN char *uiLabelText(uiLabel *l);
-_UI_EXTERN void uiLabelSetText(uiLabel *l, const char *text);
-_UI_EXTERN uiLabel *uiNewLabel(const char *text);
-
-typedef struct uiTab uiTab;
-#define uiTab(this) ((uiTab *) (this))
-_UI_EXTERN void uiTabAppend(uiTab *t, const char *name, uiControl *c);
-_UI_EXTERN void uiTabInsertAt(uiTab *t, const char *name, int before, uiControl *c);
-_UI_EXTERN void uiTabDelete(uiTab *t, int index);
-_UI_EXTERN int uiTabNumPages(uiTab *t);
-_UI_EXTERN int uiTabMargined(uiTab *t, int page);
-_UI_EXTERN void uiTabSetMargined(uiTab *t, int page, int margined);
-_UI_EXTERN uiTab *uiNewTab(void);
-
-typedef struct uiGroup uiGroup;
-#define uiGroup(this) ((uiGroup *) (this))
-_UI_EXTERN char *uiGroupTitle(uiGroup *g);
-_UI_EXTERN void uiGroupSetTitle(uiGroup *g, const char *title);
-_UI_EXTERN void uiGroupSetChild(uiGroup *g, uiControl *c);
-_UI_EXTERN int uiGroupMargined(uiGroup *g);
-_UI_EXTERN void uiGroupSetMargined(uiGroup *g, int margined);
-_UI_EXTERN uiGroup *uiNewGroup(const char *title);
-
-// spinbox/slider rules:
-// setting value outside of range will automatically clamp
-// initial value is minimum
-// complaint if min >= max?
-
-typedef struct uiSpinbox uiSpinbox;
-#define uiSpinbox(this) ((uiSpinbox *) (this))
-_UI_EXTERN int uiSpinboxValue(uiSpinbox *s);
-_UI_EXTERN void uiSpinboxSetValue(uiSpinbox *s, int value);
-_UI_EXTERN void uiSpinboxOnChanged(uiSpinbox *s, void (*f)(uiSpinbox *s, void *data), void *data);
-_UI_EXTERN uiSpinbox *uiNewSpinbox(int min, int max);
-
-typedef struct uiSlider uiSlider;
-#define uiSlider(this) ((uiSlider *) (this))
-_UI_EXTERN int uiSliderValue(uiSlider *s);
-_UI_EXTERN void uiSliderSetValue(uiSlider *s, int value);
-_UI_EXTERN void uiSliderOnChanged(uiSlider *s, void (*f)(uiSlider *s, void *data), void *data);
-_UI_EXTERN uiSlider *uiNewSlider(int min, int max);
-
-typedef struct uiProgressBar uiProgressBar;
-#define uiProgressBar(this) ((uiProgressBar *) (this))
-_UI_EXTERN int uiProgressBarValue(uiProgressBar *p);
-_UI_EXTERN void uiProgressBarSetValue(uiProgressBar *p, int n);
-_UI_EXTERN uiProgressBar *uiNewProgressBar(void);
-
-typedef struct uiSeparator uiSeparator;
-#define uiSeparator(this) ((uiSeparator *) (this))
-_UI_EXTERN uiSeparator *uiNewHorizontalSeparator(void);
-_UI_EXTERN uiSeparator *uiNewVerticalSeparator(void);
-
-typedef struct uiCombobox uiCombobox;
-#define uiCombobox(this) ((uiCombobox *) (this))
-_UI_EXTERN void uiComboboxAppend(uiCombobox *c, const char *text);
-_UI_EXTERN int uiComboboxSelected(uiCombobox *c);
-_UI_EXTERN void uiComboboxSetSelected(uiCombobox *c, int n);
-_UI_EXTERN void uiComboboxOnSelected(uiCombobox *c, void (*f)(uiCombobox *c, void *data), void *data);
-_UI_EXTERN uiCombobox *uiNewCombobox(void);
-
-typedef struct uiEditableCombobox uiEditableCombobox;
-#define uiEditableCombobox(this) ((uiEditableCombobox *) (this))
-_UI_EXTERN void uiEditableComboboxAppend(uiEditableCombobox *c, const char *text);
-_UI_EXTERN char *uiEditableComboboxText(uiEditableCombobox *c);
-_UI_EXTERN void uiEditableComboboxSetText(uiEditableCombobox *c, const char *text);
-// TODO what do we call a function that sets the currently selected item and fills the text field with it? editable comboboxes have no consistent concept of selected item
-_UI_EXTERN void uiEditableComboboxOnChanged(uiEditableCombobox *c, void (*f)(uiEditableCombobox *c, void *data), void *data);
-_UI_EXTERN uiEditableCombobox *uiNewEditableCombobox(void);
-
-typedef struct uiRadioButtons uiRadioButtons;
-#define uiRadioButtons(this) ((uiRadioButtons *) (this))
-_UI_EXTERN void uiRadioButtonsAppend(uiRadioButtons *r, const char *text);
-_UI_EXTERN int uiRadioButtonsSelected(uiRadioButtons *r);
-_UI_EXTERN void uiRadioButtonsSetSelected(uiRadioButtons *r, int n);
-_UI_EXTERN void uiRadioButtonsOnSelected(uiRadioButtons *r, void (*f)(uiRadioButtons *, void *), void *data);
-_UI_EXTERN uiRadioButtons *uiNewRadioButtons(void);
-
-typedef struct uiDateTimePicker uiDateTimePicker;
-#define uiDateTimePicker(this) ((uiDateTimePicker *) (this))
-_UI_EXTERN uiDateTimePicker *uiNewDateTimePicker(void);
-_UI_EXTERN uiDateTimePicker *uiNewDatePicker(void);
-_UI_EXTERN uiDateTimePicker *uiNewTimePicker(void);
-
-// TODO provide a facility for entering tab stops?
-typedef struct uiMultilineEntry uiMultilineEntry;
-#define uiMultilineEntry(this) ((uiMultilineEntry *) (this))
-_UI_EXTERN char *uiMultilineEntryText(uiMultilineEntry *e);
-_UI_EXTERN void uiMultilineEntrySetText(uiMultilineEntry *e, const char *text);
-_UI_EXTERN void uiMultilineEntryAppend(uiMultilineEntry *e, const char *text);
-_UI_EXTERN void uiMultilineEntryOnChanged(uiMultilineEntry *e, void (*f)(uiMultilineEntry *e, void *data), void *data);
-_UI_EXTERN int uiMultilineEntryReadOnly(uiMultilineEntry *e);
-_UI_EXTERN void uiMultilineEntrySetReadOnly(uiMultilineEntry *e, int readonly);
-_UI_EXTERN uiMultilineEntry *uiNewMultilineEntry(void);
-_UI_EXTERN uiMultilineEntry *uiNewNonWrappingMultilineEntry(void);
-
-typedef struct uiMenuItem uiMenuItem;
-#define uiMenuItem(this) ((uiMenuItem *) (this))
-_UI_EXTERN void uiMenuItemEnable(uiMenuItem *m);
-_UI_EXTERN void uiMenuItemDisable(uiMenuItem *m);
-_UI_EXTERN void uiMenuItemOnClicked(uiMenuItem *m, void (*f)(uiMenuItem *sender, uiWindow *window, void *data), void *data);
-_UI_EXTERN int uiMenuItemChecked(uiMenuItem *m);
-_UI_EXTERN void uiMenuItemSetChecked(uiMenuItem *m, int checked);
-
-typedef struct uiMenu uiMenu;
-#define uiMenu(this) ((uiMenu *) (this))
-_UI_EXTERN uiMenuItem *uiMenuAppendItem(uiMenu *m, const char *name);
-_UI_EXTERN uiMenuItem *uiMenuAppendCheckItem(uiMenu *m, const char *name);
-_UI_EXTERN uiMenuItem *uiMenuAppendQuitItem(uiMenu *m);
-_UI_EXTERN uiMenuItem *uiMenuAppendPreferencesItem(uiMenu *m);
-_UI_EXTERN uiMenuItem *uiMenuAppendAboutItem(uiMenu *m);
-_UI_EXTERN uiMenuItem *uiMenuAppendSubmenu(uiMenu *m, uiMenu* child);
-_UI_EXTERN void uiMenuAppendSeparator(uiMenu *m);
-_UI_EXTERN uiMenu *uiNewMenu(const char *name);
-
-_UI_EXTERN char *uiOpenFile(uiWindow *parent, const char* filter, const char* initpath);
-_UI_EXTERN char *uiSaveFile(uiWindow *parent, const char* filter, const char* initpath);
-_UI_EXTERN void uiMsgBox(uiWindow *parent, const char *title, const char *description);
-_UI_EXTERN void uiMsgBoxError(uiWindow *parent, const char *title, const char *description);
-_UI_EXTERN int uiMsgBoxConfirm(uiWindow * parent, const char *title, const char *description);
-
-typedef struct uiArea uiArea;
-typedef struct uiAreaHandler uiAreaHandler;
-typedef struct uiAreaDrawParams uiAreaDrawParams;
-typedef struct uiAreaMouseEvent uiAreaMouseEvent;
-typedef struct uiAreaKeyEvent uiAreaKeyEvent;
-
-typedef struct uiDrawContext uiDrawContext;
-
-// TO CONSIDER: the uiAreaHandler param there seems useless
-// (might use individual callbacks instead of handler struct?)
-struct uiAreaHandler {
- void (*Draw)(uiAreaHandler *, uiArea *, uiAreaDrawParams *);
- // TODO document that resizes cause a full redraw for non-scrolling areas; implementation-defined for scrolling areas
- void (*MouseEvent)(uiAreaHandler *, uiArea *, uiAreaMouseEvent *);
- // TODO document that on first show if the mouse is already in the uiArea then one gets sent with left=0
- // TODO what about when the area is hidden and then shown again?
- void (*MouseCrossed)(uiAreaHandler *, uiArea *, int left);
- void (*DragBroken)(uiAreaHandler *, uiArea *);
- int (*KeyEvent)(uiAreaHandler *, uiArea *, uiAreaKeyEvent *);
- void (*Resize)(uiAreaHandler *, uiArea *, int, int);
-};
-
-// TODO RTL layouts?
-// TODO reconcile edge and corner naming
-_UI_ENUM(uiWindowResizeEdge) {
- uiWindowResizeEdgeLeft,
- uiWindowResizeEdgeTop,
- uiWindowResizeEdgeRight,
- uiWindowResizeEdgeBottom,
- uiWindowResizeEdgeTopLeft,
- uiWindowResizeEdgeTopRight,
- uiWindowResizeEdgeBottomLeft,
- uiWindowResizeEdgeBottomRight,
- // TODO have one for keyboard resizes?
- // TODO GDK doesn't seem to have any others, including for keyboards...
- // TODO way to bring up the system menu instead?
-};
-
-#define uiGLVersion(major, minor) ((major) | ((minor)<<16))
-#define uiGLVerMajor(ver) ((ver) & 0xFFFF)
-#define uiGLVerMinor(ver) ((ver) >> 16)
-
-#define uiArea(this) ((uiArea *) (this))
-// TODO give a better name
-// TODO document the types of width and height
-_UI_EXTERN void uiAreaSetSize(uiArea *a, int width, int height);
-// TODO uiAreaQueueRedraw()
-_UI_EXTERN void uiAreaQueueRedrawAll(uiArea *a);
-_UI_EXTERN void uiAreaScrollTo(uiArea *a, double x, double y, double width, double height);
-// TODO document these can only be called within Mouse() handlers
-// TODO should these be allowed on scrolling areas?
-// TODO decide which mouse events should be accepted; Down is the only one guaranteed to work right now
-// TODO what happens to events after calling this up to and including the next mouse up?
-// TODO release capture?
-_UI_EXTERN void uiAreaBeginUserWindowMove(uiArea *a);
-_UI_EXTERN void uiAreaBeginUserWindowResize(uiArea *a, uiWindowResizeEdge edge);
-_UI_EXTERN void uiAreaSetBackgroundColor(uiArea *a, int r, int g, int b);
-_UI_EXTERN uiArea *uiNewArea(uiAreaHandler *ah);
-_UI_EXTERN uiArea *uiNewGLArea(uiAreaHandler *ah, const unsigned int* req_versions);
-_UI_EXTERN uiArea *uiNewScrollingArea(uiAreaHandler *ah, int width, int height);
-
-struct uiAreaDrawParams {
- uiDrawContext *Context;
-
- // TODO document that this is only defined for nonscrolling areas
- double AreaWidth;
- double AreaHeight;
-
- double ClipX;
- double ClipY;
- double ClipWidth;
- double ClipHeight;
-};
-
-typedef struct uiDrawPath uiDrawPath;
-typedef struct uiDrawBrush uiDrawBrush;
-typedef struct uiDrawStrokeParams uiDrawStrokeParams;
-typedef struct uiDrawMatrix uiDrawMatrix;
-
-typedef struct uiDrawBrushGradientStop uiDrawBrushGradientStop;
-
-typedef struct uiDrawBitmap uiDrawBitmap;
-
-_UI_ENUM(uiDrawBrushType) {
- uiDrawBrushTypeSolid,
- uiDrawBrushTypeLinearGradient,
- uiDrawBrushTypeRadialGradient,
- uiDrawBrushTypeImage,
-};
-
-_UI_ENUM(uiDrawLineCap) {
- uiDrawLineCapFlat,
- uiDrawLineCapRound,
- uiDrawLineCapSquare,
-};
-
-_UI_ENUM(uiDrawLineJoin) {
- uiDrawLineJoinMiter,
- uiDrawLineJoinRound,
- uiDrawLineJoinBevel,
-};
-
-// this is the default for botoh cairo and Direct2D (in the latter case, from the C++ helper functions)
-// Core Graphics doesn't explicitly specify a default, but NSBezierPath allows you to choose one, and this is the initial value
-// so we're good to use it too!
-#define uiDrawDefaultMiterLimit 10.0
-
-_UI_ENUM(uiDrawFillMode) {
- uiDrawFillModeWinding,
- uiDrawFillModeAlternate,
-};
-
-struct uiDrawMatrix {
- double M11;
- double M12;
- double M21;
- double M22;
- double M31;
- double M32;
-};
-
-struct uiDrawBrush {
- uiDrawBrushType Type;
-
- // solid brushes
- double R;
- double G;
- double B;
- double A;
-
- // gradient brushes
- double X0; // linear: start X, radial: start X
- double Y0; // linear: start Y, radial: start Y
- double X1; // linear: end X, radial: outer circle center X
- double Y1; // linear: end Y, radial: outer circle center Y
- double OuterRadius; // radial gradients only
- uiDrawBrushGradientStop *Stops;
- size_t NumStops;
- // TODO extend mode
- // cairo: none, repeat, reflect, pad; no individual control
- // Direct2D: repeat, reflect, pad; no individual control
- // Core Graphics: none, pad; before and after individually
- // TODO cairo documentation is inconsistent about pad
-
- // TODO images
-
- // TODO transforms
-};
-
-struct uiDrawBrushGradientStop {
- double Pos;
- double R;
- double G;
- double B;
- double A;
-};
-
-struct uiDrawStrokeParams {
- uiDrawLineCap Cap;
- uiDrawLineJoin Join;
- // TODO what if this is 0? on windows there will be a crash with dashing
- double Thickness;
- double MiterLimit;
- double *Dashes;
- // TOOD what if this is 1 on Direct2D?
- // TODO what if a dash is 0 on Cairo or Quartz?
- size_t NumDashes;
- double DashPhase;
-};
-
-struct uiRect {
- int X;
- int Y;
- int Width;
- int Height;
-};
-
-typedef struct uiRect uiRect;
-
-_UI_EXTERN uiDrawPath *uiDrawNewPath(uiDrawFillMode fillMode);
-_UI_EXTERN void uiDrawFreePath(uiDrawPath *p);
-
-_UI_EXTERN void uiDrawPathNewFigure(uiDrawPath *p, double x, double y);
-_UI_EXTERN void uiDrawPathNewFigureWithArc(uiDrawPath *p, double xCenter, double yCenter, double radius, double startAngle, double sweep, int negative);
-_UI_EXTERN void uiDrawPathLineTo(uiDrawPath *p, double x, double y);
-// notes: angles are both relative to 0 and go counterclockwise
-// TODO is the initial line segment on cairo and OS X a proper join?
-// TODO what if sweep < 0?
-_UI_EXTERN void uiDrawPathArcTo(uiDrawPath *p, double xCenter, double yCenter, double radius, double startAngle, double sweep, int negative);
-_UI_EXTERN void uiDrawPathBezierTo(uiDrawPath *p, double c1x, double c1y, double c2x, double c2y, double endX, double endY);
-// TODO quadratic bezier
-_UI_EXTERN void uiDrawPathCloseFigure(uiDrawPath *p);
-
-// TODO effect of these when a figure is already started
-_UI_EXTERN void uiDrawPathAddRectangle(uiDrawPath *p, double x, double y, double width, double height);
-
-_UI_EXTERN void uiDrawPathEnd(uiDrawPath *p);
-
-_UI_EXTERN void uiDrawStroke(uiDrawContext *c, uiDrawPath *path, uiDrawBrush *b, uiDrawStrokeParams *p);
-_UI_EXTERN void uiDrawFill(uiDrawContext *c, uiDrawPath *path, uiDrawBrush *b);
-
-// TODO primitives:
-// - rounded rectangles
-// - elliptical arcs
-// - quadratic bezier curves
-
-_UI_EXTERN void uiDrawMatrixSetIdentity(uiDrawMatrix *m);
-_UI_EXTERN void uiDrawMatrixTranslate(uiDrawMatrix *m, double x, double y);
-_UI_EXTERN void uiDrawMatrixScale(uiDrawMatrix *m, double xCenter, double yCenter, double x, double y);
-_UI_EXTERN void uiDrawMatrixRotate(uiDrawMatrix *m, double x, double y, double amount);
-_UI_EXTERN void uiDrawMatrixSkew(uiDrawMatrix *m, double x, double y, double xamount, double yamount);
-_UI_EXTERN void uiDrawMatrixMultiply(uiDrawMatrix *dest, uiDrawMatrix *src);
-_UI_EXTERN int uiDrawMatrixInvertible(uiDrawMatrix *m);
-_UI_EXTERN int uiDrawMatrixInvert(uiDrawMatrix *m);
-_UI_EXTERN void uiDrawMatrixTransformPoint(uiDrawMatrix *m, double *x, double *y);
-_UI_EXTERN void uiDrawMatrixTransformSize(uiDrawMatrix *m, double *x, double *y);
-
-_UI_EXTERN void uiDrawTransform(uiDrawContext *c, uiDrawMatrix *m);
-
-// TODO add a uiDrawPathStrokeToFill() or something like that
-_UI_EXTERN void uiDrawClip(uiDrawContext *c, uiDrawPath *path);
-
-_UI_EXTERN void uiDrawSave(uiDrawContext *c);
-_UI_EXTERN void uiDrawRestore(uiDrawContext *c);
-
-// bitmap API
-_UI_EXTERN uiDrawBitmap* uiDrawNewBitmap(uiDrawContext* c, int width, int height, int alpha);
-_UI_EXTERN void uiDrawBitmapUpdate(uiDrawBitmap* bmp, const void* data);
-_UI_EXTERN void uiDrawBitmapDraw(uiDrawContext* c, uiDrawBitmap* bmp, uiRect* srcrect, uiRect* dstrect, int filter);
-_UI_EXTERN void uiDrawFreeBitmap(uiDrawBitmap* bmp);
-
-// TODO manage the use of Text, Font, and TextFont, and of the uiDrawText prefix in general
-
-///// TODO reconsider this
-typedef struct uiDrawFontFamilies uiDrawFontFamilies;
-
-_UI_EXTERN uiDrawFontFamilies *uiDrawListFontFamilies(void);
-_UI_EXTERN int uiDrawFontFamiliesNumFamilies(uiDrawFontFamilies *ff);
-_UI_EXTERN char *uiDrawFontFamiliesFamily(uiDrawFontFamilies *ff, int n);
-_UI_EXTERN void uiDrawFreeFontFamilies(uiDrawFontFamilies *ff);
-///// END TODO
-
-typedef struct uiDrawTextLayout uiDrawTextLayout;
-typedef struct uiDrawTextFont uiDrawTextFont;
-typedef struct uiDrawTextFontDescriptor uiDrawTextFontDescriptor;
-typedef struct uiDrawTextFontMetrics uiDrawTextFontMetrics;
-
-_UI_ENUM(uiDrawTextWeight) {
- uiDrawTextWeightThin,
- uiDrawTextWeightUltraLight,
- uiDrawTextWeightLight,
- uiDrawTextWeightBook,
- uiDrawTextWeightNormal,
- uiDrawTextWeightMedium,
- uiDrawTextWeightSemiBold,
- uiDrawTextWeightBold,
- uiDrawTextWeightUltraBold,
- uiDrawTextWeightHeavy,
- uiDrawTextWeightUltraHeavy,
-};
-
-_UI_ENUM(uiDrawTextItalic) {
- uiDrawTextItalicNormal,
- uiDrawTextItalicOblique,
- uiDrawTextItalicItalic,
-};
-
-_UI_ENUM(uiDrawTextStretch) {
- uiDrawTextStretchUltraCondensed,
- uiDrawTextStretchExtraCondensed,
- uiDrawTextStretchCondensed,
- uiDrawTextStretchSemiCondensed,
- uiDrawTextStretchNormal,
- uiDrawTextStretchSemiExpanded,
- uiDrawTextStretchExpanded,
- uiDrawTextStretchExtraExpanded,
- uiDrawTextStretchUltraExpanded,
-};
-
-struct uiDrawTextFontDescriptor {
- const char *Family;
- double Size;
- uiDrawTextWeight Weight;
- uiDrawTextItalic Italic;
- uiDrawTextStretch Stretch;
-};
-
-struct uiDrawTextFontMetrics {
- double Ascent;
- double Descent;
- double Leading;
- // TODO do these two mean the same across all platforms?
- double UnderlinePos;
- double UnderlineThickness;
-};
-
-_UI_EXTERN uiDrawTextFont *uiDrawLoadClosestFont(const uiDrawTextFontDescriptor *desc);
-_UI_EXTERN void uiDrawFreeTextFont(uiDrawTextFont *font);
-_UI_EXTERN uintptr_t uiDrawTextFontHandle(uiDrawTextFont *font);
-_UI_EXTERN void uiDrawTextFontDescribe(uiDrawTextFont *font, uiDrawTextFontDescriptor *desc);
-// TODO make copy with given attributes methods?
-// TODO yuck this name
-_UI_EXTERN void uiDrawTextFontGetMetrics(uiDrawTextFont *font, uiDrawTextFontMetrics *metrics);
-
-// TODO initial line spacing? and what about leading?
-_UI_EXTERN uiDrawTextLayout *uiDrawNewTextLayout(const char *text, uiDrawTextFont *defaultFont, double width);
-_UI_EXTERN void uiDrawFreeTextLayout(uiDrawTextLayout *layout);
-// TODO get width
-_UI_EXTERN void uiDrawTextLayoutSetWidth(uiDrawTextLayout *layout, double width);
-_UI_EXTERN void uiDrawTextLayoutExtents(uiDrawTextLayout *layout, double *width, double *height);
-
-// and the attributes that you can set on a text layout
-_UI_EXTERN void uiDrawTextLayoutSetColor(uiDrawTextLayout *layout, int startChar, int endChar, double r, double g, double b, double a);
-
-_UI_EXTERN void uiDrawText(uiDrawContext *c, double x, double y, uiDrawTextLayout *layout);
-
-
-// OpenGL support
-
-typedef struct uiGLContext uiGLContext;
-
-_UI_EXTERN uiGLContext *uiAreaGetGLContext(uiArea* a);
-_UI_EXTERN void uiGLMakeContextCurrent(uiGLContext* ctx);
-_UI_EXTERN void uiGLBegin(uiGLContext* ctx);
-_UI_EXTERN void uiGLEnd(uiGLContext* ctx);
-_UI_EXTERN unsigned int uiGLGetVersion(uiGLContext* ctx);
-_UI_EXTERN void *uiGLGetProcAddress(const char* proc);
-_UI_EXTERN int uiGLGetFramebuffer(uiGLContext* ctx);
-_UI_EXTERN float uiGLGetFramebufferScale(uiGLContext* ctx);
-_UI_EXTERN void uiGLSwapBuffers(uiGLContext* ctx);
-_UI_EXTERN void uiGLSetVSync(int sync);
-
-
-_UI_ENUM(uiModifiers) {
- uiModifierCtrl = 1 << 0,
- uiModifierAlt = 1 << 1,
- uiModifierShift = 1 << 2,
- uiModifierSuper = 1 << 3,
-};
-
-// TODO document drag captures
-struct uiAreaMouseEvent {
- // TODO document what these mean for scrolling areas
- double X;
- double Y;
-
- // TODO see draw above
- double AreaWidth;
- double AreaHeight;
-
- int Down;
- int Up;
-
- int Count;
-
- uiModifiers Modifiers;
-
- uint64_t Held1To64;
-};
-
-_UI_ENUM(uiExtKey) {
- uiExtKeyEscape = 1,
- uiExtKeyInsert, // equivalent to "Help" on Apple keyboards
- uiExtKeyDelete,
- uiExtKeyHome,
- uiExtKeyEnd,
- uiExtKeyPageUp,
- uiExtKeyPageDown,
- uiExtKeyUp,
- uiExtKeyDown,
- uiExtKeyLeft,
- uiExtKeyRight,
- uiExtKeyF1, // F1..F12 are guaranteed to be consecutive
- uiExtKeyF2,
- uiExtKeyF3,
- uiExtKeyF4,
- uiExtKeyF5,
- uiExtKeyF6,
- uiExtKeyF7,
- uiExtKeyF8,
- uiExtKeyF9,
- uiExtKeyF10,
- uiExtKeyF11,
- uiExtKeyF12,
- uiExtKeyN0, // numpad keys; independent of Num Lock state
- uiExtKeyN1, // N0..N9 are guaranteed to be consecutive
- uiExtKeyN2,
- uiExtKeyN3,
- uiExtKeyN4,
- uiExtKeyN5,
- uiExtKeyN6,
- uiExtKeyN7,
- uiExtKeyN8,
- uiExtKeyN9,
- uiExtKeyNDot,
- uiExtKeyNEnter,
- uiExtKeyNAdd,
- uiExtKeyNSubtract,
- uiExtKeyNMultiply,
- uiExtKeyNDivide,
-};
-
-struct uiAreaKeyEvent {
- char Key;
- uiExtKey ExtKey;
- uiModifiers Modifier;
-
- uiModifiers Modifiers;
-
- // additional things
- int Scancode; // bit0-7: scancode, bit8: ext flag
-
- int Up;
- int Repeat;
-};
-
-typedef struct uiFontButton uiFontButton;
-#define uiFontButton(this) ((uiFontButton *) (this))
-// TODO document this returns a new font
-_UI_EXTERN uiDrawTextFont *uiFontButtonFont(uiFontButton *b);
-// TOOD SetFont, mechanics
-_UI_EXTERN void uiFontButtonOnChanged(uiFontButton *b, void (*f)(uiFontButton *, void *), void *data);
-_UI_EXTERN uiFontButton *uiNewFontButton(void);
-
-typedef struct uiColorButton uiColorButton;
-#define uiColorButton(this) ((uiColorButton *) (this))
-_UI_EXTERN void uiColorButtonColor(uiColorButton *b, double *r, double *g, double *bl, double *a);
-_UI_EXTERN void uiColorButtonSetColor(uiColorButton *b, double r, double g, double bl, double a);
-_UI_EXTERN void uiColorButtonOnChanged(uiColorButton *b, void (*f)(uiColorButton *, void *), void *data);
-_UI_EXTERN uiColorButton *uiNewColorButton(void);
-
-typedef struct uiForm uiForm;
-#define uiForm(this) ((uiForm *) (this))
-_UI_EXTERN void uiFormAppend(uiForm *f, const char *label, uiControl *c, int stretchy);
-_UI_EXTERN void uiFormDelete(uiForm *f, int index);
-_UI_EXTERN int uiFormPadded(uiForm *f);
-_UI_EXTERN void uiFormSetPadded(uiForm *f, int padded);
-_UI_EXTERN uiForm *uiNewForm(void);
-
-_UI_ENUM(uiAlign) {
- uiAlignFill,
- uiAlignStart,
- uiAlignCenter,
- uiAlignEnd,
-};
-
-_UI_ENUM(uiAt) {
- uiAtLeading,
- uiAtTop,
- uiAtTrailing,
- uiAtBottom,
-};
-
-typedef struct uiGrid uiGrid;
-#define uiGrid(this) ((uiGrid *) (this))
-_UI_EXTERN void uiGridAppend(uiGrid *g, uiControl *c, int left, int top, int xspan, int yspan, int hexpand, uiAlign halign, int vexpand, uiAlign valign);
-_UI_EXTERN void uiGridInsertAt(uiGrid *g, uiControl *c, uiControl *existing, uiAt at, int xspan, int yspan, int hexpand, uiAlign halign, int vexpand, uiAlign valign);
-_UI_EXTERN int uiGridPadded(uiGrid *g);
-_UI_EXTERN void uiGridSetPadded(uiGrid *g, int padded);
-_UI_EXTERN uiGrid *uiNewGrid(void);
-
-
-// misc.
-
-_UI_EXTERN char* uiKeyName(int scancode);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/src/libui_sdl/libui/unix/stddialogs.c b/src/libui_sdl/libui/unix/stddialogs.c
deleted file mode 100644
index 10c598d..0000000
--- a/src/libui_sdl/libui/unix/stddialogs.c
+++ /dev/null
@@ -1,126 +0,0 @@
-// 26 june 2015
-#include "uipriv_unix.h"
-
-// LONGTERM figure out why, and describe, that this is the desired behavior
-// LONGTERM also point out that font and color buttons also work like this
-
-#define windowWindow(w) ((w)?(GTK_WINDOW(uiControlHandle(uiControl(w)))):NULL)
-
-static char *filedialog(GtkWindow *parent, GtkFileChooserAction mode, const gchar *confirm, const char* filter, const char* initpath)
-{
- GtkWidget *fcd;
- GtkFileChooser *fc;
- gint response;
- char *filename;
-
- fcd = gtk_file_chooser_dialog_new(NULL, parent, mode,
- "_Cancel", GTK_RESPONSE_CANCEL,
- confirm, GTK_RESPONSE_ACCEPT,
- NULL);
- fc = GTK_FILE_CHOOSER(fcd);
-
- // filters
- {
- gchar _filter[256];
- gchar* fp = &_filter[0]; int s = 0;
- gchar* fname;
- for (int i = 0; i < 255; i++)
- {
- if (filter[i] == '|' || filter[i] == '\0')
- {
- _filter[i] = '\0';
- if (s & 1)
- {
- GtkFileFilter* filter = gtk_file_filter_new();
- gtk_file_filter_set_name(filter, fname);
-
- for (gchar* j = fp; ; j++)
- {
- if (*j == ';')
- {
- *j = '\0';
- gtk_file_filter_add_pattern(filter, fp);
- fp = j+1;
- }
- else if (*j == '\0')
- {
- gtk_file_filter_add_pattern(filter, fp);
- break;
- }
- }
-
- gtk_file_chooser_add_filter(fc, filter);
- }
- else
- {
- fname = fp;
- }
- fp = &_filter[i+1];
- s++;
- if (s >= 8) break;
- if (filter[i] == '\0') break;
- }
- else
- _filter[i] = filter[i];
- }
- }
-
- gtk_file_chooser_set_local_only(fc, FALSE);
- gtk_file_chooser_set_select_multiple(fc, FALSE);
- gtk_file_chooser_set_show_hidden(fc, TRUE);
- gtk_file_chooser_set_do_overwrite_confirmation(fc, TRUE);
- gtk_file_chooser_set_create_folders(fc, TRUE);
- if (initpath && strlen(initpath)>0)
- gtk_file_chooser_set_current_folder(fc, initpath);
-
- response = gtk_dialog_run(GTK_DIALOG(fcd));
- if (response != GTK_RESPONSE_ACCEPT) {
- gtk_widget_destroy(fcd);
- return NULL;
- }
- filename = uiUnixStrdupText(gtk_file_chooser_get_filename(fc));
- gtk_widget_destroy(fcd);
- return filename;
-}
-
-char *uiOpenFile(uiWindow *parent, const char* filter, const char* initpath)
-{
- return filedialog(windowWindow(parent), GTK_FILE_CHOOSER_ACTION_OPEN, "_Open", filter, initpath);
-}
-
-char *uiSaveFile(uiWindow *parent, const char* filter, const char* initpath)
-{
- return filedialog(windowWindow(parent), GTK_FILE_CHOOSER_ACTION_SAVE, "_Save", filter, initpath);
-}
-
-static int msgbox(GtkWindow *parent, const char *title, const char *description, GtkMessageType type, GtkButtonsType buttons)
-{
- GtkWidget *md;
-
- md = gtk_message_dialog_new(parent, GTK_DIALOG_MODAL,
- type, buttons,
- "%s", title);
- gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(md), "%s", description);
- int result = gtk_dialog_run(GTK_DIALOG(md));
- gtk_widget_destroy(md);
-
- return result;
-}
-
-void uiMsgBox(uiWindow *parent, const char *title, const char *description)
-{
- msgbox(windowWindow(parent), title, description, GTK_MESSAGE_OTHER, GTK_BUTTONS_OK);
-}
-
-void uiMsgBoxError(uiWindow *parent, const char *title, const char *description)
-{
- msgbox(windowWindow(parent), title, description, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK);
-}
-
-int uiMsgBoxConfirm(uiWindow * parent, const char *title, const char *description)
-{
- int result =
- msgbox(windowWindow(parent), title, description, GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL);
-
- return result == GTK_RESPONSE_OK;
-} \ No newline at end of file
diff --git a/src/libui_sdl/libui/windows/stddialogs.cpp b/src/libui_sdl/libui/windows/stddialogs.cpp
deleted file mode 100644
index 7537015..0000000
--- a/src/libui_sdl/libui/windows/stddialogs.cpp
+++ /dev/null
@@ -1,180 +0,0 @@
-// 22 may 2015
-#include "uipriv_windows.hpp"
-
-// TODO document all this is what we want
-// TODO do the same for font and color buttons
-
-// notes:
-// - FOS_SUPPORTSTREAMABLEITEMS doesn't seem to be supported on windows vista, or at least not with the flags we use
-// - even with FOS_NOVALIDATE the dialogs will reject invalid filenames (at least on Vista, anyway)
-// - lack of FOS_NOREADONLYRETURN doesn't seem to matter on Windows 7
-
-// TODO
-// - http://blogs.msdn.com/b/wpfsdk/archive/2006/10/26/uncommon-dialogs--font-chooser-and-color-picker-dialogs.aspx
-// - when a dialog is active, tab navigation in other windows stops working
-// - when adding uiOpenFolder(), use IFileDialog as well - https://msdn.microsoft.com/en-us/library/windows/desktop/bb762115%28v=vs.85%29.aspx
-
-#define windowHWND(w) (w ? (HWND) uiControlHandle(uiControl(w)) : NULL)
-
-char *commonItemDialog(HWND parent, REFCLSID clsid, REFIID iid, const char* filter, const char* initpath, FILEOPENDIALOGOPTIONS optsadd)
-{
- IFileDialog *d = NULL;
- FILEOPENDIALOGOPTIONS opts;
- IShellItem *result = NULL;
- WCHAR *wname = NULL;
- char *name = NULL;
- HRESULT hr;
-
- hr = CoCreateInstance(clsid,
- NULL, CLSCTX_INPROC_SERVER,
- iid, (LPVOID *) (&d));
- if (hr != S_OK) {
- logHRESULT(L"error creating common item dialog", hr);
- // always return NULL on error
- goto out;
- }
- hr = d->GetOptions(&opts);
- if (hr != S_OK) {
- logHRESULT(L"error getting current options", hr);
- goto out;
- }
- opts |= optsadd;
- // the other platforms don't check read-only; we won't either
- opts &= ~FOS_NOREADONLYRETURN;
- hr = d->SetOptions(opts);
- if (hr != S_OK) {
- logHRESULT(L"error setting options", hr);
- goto out;
- }
-
- // filters
- {
- COMDLG_FILTERSPEC filterspec[8];
- wchar_t _filter[256];
- wchar_t* fp = &_filter[0]; int s = 0;
- wchar_t* fname;
- for (int i = 0; i < 255; i++)
- {
- if (filter[i] == '|' || filter[i] == '\0')
- {
- _filter[i] = '\0';
- if (s & 1)
- {
- filterspec[s>>1].pszName = fname;
- filterspec[s>>1].pszSpec = fp;
- }
- else
- {
- fname = fp;
- }
- fp = &_filter[i+1];
- s++;
- if (s >= 8) break;
- if (filter[i] == '\0') break;
- }
- else
- _filter[i] = filter[i];
- }
- d->SetFileTypes(s>>1, filterspec);
- }
-
- hr = d->Show(parent);
- if (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED))
- // cancelled; return NULL like we have ready
- goto out;
- if (hr != S_OK) {
- logHRESULT(L"error showing dialog", hr);
- goto out;
- }
- hr = d->GetResult(&result);
- if (hr != S_OK) {
- logHRESULT(L"error getting dialog result", hr);
- goto out;
- }
- hr = result->GetDisplayName(SIGDN_FILESYSPATH, &wname);
- if (hr != S_OK) {
- logHRESULT(L"error getting filename", hr);
- goto out;
- }
- name = toUTF8(wname);
-
-out:
- if (wname != NULL)
- CoTaskMemFree(wname);
- if (result != NULL)
- result->Release();
- if (d != NULL)
- d->Release();
- return name;
-}
-
-char *uiOpenFile(uiWindow *parent, const char* filter, const char* initpath)
-{
- char *res;
-
- disableAllWindowsExcept(parent);
- res = commonItemDialog(windowHWND(parent),
- CLSID_FileOpenDialog, IID_IFileOpenDialog,
- filter, initpath,
- FOS_NOCHANGEDIR | FOS_FORCEFILESYSTEM | FOS_NOVALIDATE | FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST | FOS_SHAREAWARE | FOS_NOTESTFILECREATE | FOS_FORCESHOWHIDDEN | FOS_DEFAULTNOMINIMODE);
- enableAllWindowsExcept(parent);
- return res;
-}
-
-char *uiSaveFile(uiWindow *parent, const char* filter, const char* initpath)
-{
- char *res;
-
- disableAllWindowsExcept(parent);
- res = commonItemDialog(windowHWND(parent),
- CLSID_FileSaveDialog, IID_IFileSaveDialog,
- filter, initpath,
- FOS_OVERWRITEPROMPT | FOS_NOCHANGEDIR | FOS_FORCEFILESYSTEM | FOS_NOVALIDATE | FOS_SHAREAWARE | FOS_NOTESTFILECREATE | FOS_FORCESHOWHIDDEN | FOS_DEFAULTNOMINIMODE);
- enableAllWindowsExcept(parent);
- return res;
-}
-
-// TODO switch to TaskDialogIndirect()?
-
-static int msgbox(HWND parent, const char *title, const char *description, TASKDIALOG_COMMON_BUTTON_FLAGS buttons, PCWSTR icon)
-{
- WCHAR *wtitle, *wdescription;
- HRESULT hr;
-
- wtitle = toUTF16(title);
- wdescription = toUTF16(description);
-
- int result;
- hr = TaskDialog(parent, NULL, NULL, wtitle, wdescription, buttons, icon, &result);
- if (hr != S_OK)
- logHRESULT(L"error showing task dialog", hr);
-
- uiFree(wdescription);
- uiFree(wtitle);
-
- return result;
-}
-
-void uiMsgBox(uiWindow *parent, const char *title, const char *description)
-{
- disableAllWindowsExcept(parent);
- msgbox(windowHWND(parent), title, description, TDCBF_OK_BUTTON, NULL);
- enableAllWindowsExcept(parent);
-}
-
-void uiMsgBoxError(uiWindow *parent, const char *title, const char *description)
-{
- disableAllWindowsExcept(parent);
- msgbox(windowHWND(parent), title, description, TDCBF_OK_BUTTON, TD_ERROR_ICON);
- enableAllWindowsExcept(parent);
-}
-
-int uiMsgBoxConfirm(uiWindow * parent, const char *title, const char *description)
-{
- disableAllWindowsExcept(parent);
- int result =
- msgbox(windowHWND(parent), title, description, TDCBF_OK_BUTTON | TDCBF_CANCEL_BUTTON, TD_WARNING_ICON);
- enableAllWindowsExcept(parent);
-
- return result == IDOK;
-} \ No newline at end of file
diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp
deleted file mode 100644
index 0066668..0000000
--- a/src/libui_sdl/main.cpp
+++ /dev/null
@@ -1,3061 +0,0 @@
-/*
- Copyright 2016-2020 Arisotura
-
- This file is part of melonDS.
-
- melonDS is free software: you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
-
- melonDS is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with melonDS. If not, see http://www.gnu.org/licenses/.
-*/
-
-#include <stdlib.h>
-#include <time.h>
-#include <stdio.h>
-#include <string.h>
-
-#ifndef __WIN32__
-#include <glib.h>
-#endif
-
-#include <SDL2/SDL.h>
-#include "libui/ui.h"
-
-#include "../OpenGLSupport.h"
-#include "main_shaders.h"
-
-#include "../types.h"
-#include "../version.h"
-#include "PlatformConfig.h"
-
-#include "DlgEmuSettings.h"
-#include "DlgInputConfig.h"
-#include "DlgVideoSettings.h"
-#include "DlgAudioSettings.h"
-#include "DlgWifiSettings.h"
-
-#include "../NDS.h"
-#include "../GBACart.h"
-#include "../GPU.h"
-#include "../SPU.h"
-#include "../Wifi.h"
-#include "../Platform.h"
-#include "../Config.h"
-#include "../ARMJIT.h"
-
-#include "../Savestate.h"
-
-#include "OSD.h"
-
-#ifdef MELONCAP
-#include "MelonCap.h"
-#endif // MELONCAP
-
-
-// savestate slot mapping
-// 1-8: regular slots (quick access)
-// '9': load/save arbitrary file
-const int kSavestateNum[9] = {1, 2, 3, 4, 5, 6, 7, 8, 0};
-
-const int kScreenSize[4] = {1, 2, 3, 4};
-const int kScreenRot[4] = {0, 1, 2, 3};
-const int kScreenGap[6] = {0, 1, 8, 64, 90, 128};
-const int kScreenLayout[3] = {0, 1, 2};
-const int kScreenSizing[4] = {0, 1, 2, 3};
-
-
-char* EmuDirectory;
-
-
-uiWindow* MainWindow;
-uiArea* MainDrawArea;
-uiAreaHandler MainDrawAreaHandler;
-
-const u32 kGLVersions[] = {uiGLVersion(3,2), uiGLVersion(3,1), 0};
-uiGLContext* GLContext;
-
-int WindowWidth, WindowHeight;
-
-uiMenuItem* MenuItem_SaveState;
-uiMenuItem* MenuItem_LoadState;
-uiMenuItem* MenuItem_UndoStateLoad;
-
-uiMenuItem* MenuItem_SaveStateSlot[9];
-uiMenuItem* MenuItem_LoadStateSlot[9];
-
-uiMenuItem* MenuItem_Pause;
-uiMenuItem* MenuItem_Reset;
-uiMenuItem* MenuItem_Stop;
-
-uiMenuItem* MenuItem_SavestateSRAMReloc;
-
-uiMenuItem* MenuItem_ScreenRot[4];
-uiMenuItem* MenuItem_ScreenGap[6];
-uiMenuItem* MenuItem_ScreenLayout[3];
-uiMenuItem* MenuItem_ScreenSizing[4];
-
-uiMenuItem* MenuItem_ScreenFilter;
-uiMenuItem* MenuItem_LimitFPS;
-uiMenuItem* MenuItem_AudioSync;
-uiMenuItem* MenuItem_ShowOSD;
-
-SDL_Thread* EmuThread;
-int EmuRunning;
-volatile int EmuStatus;
-
-bool RunningSomething;
-char ROMPath[2][1024];
-char SRAMPath[2][1024];
-char PrevSRAMPath[2][1024]; // for savestate 'undo load'
-
-bool SavestateLoaded;
-
-bool Screen_UseGL;
-
-bool ScreenDrawInited = false;
-uiDrawBitmap* ScreenBitmap[2] = {NULL,NULL};
-
-GLuint GL_ScreenShader[3];
-GLuint GL_ScreenShaderAccel[3];
-GLuint GL_ScreenShaderOSD[3];
-struct
-{
- float uScreenSize[2];
- u32 u3DScale;
- u32 uFilterMode;
-
-} GL_ShaderConfig;
-GLuint GL_ShaderConfigUBO;
-GLuint GL_ScreenVertexArrayID, GL_ScreenVertexBufferID;
-float GL_ScreenVertices[2 * 3*2 * 4]; // position/texcoord
-GLuint GL_ScreenTexture;
-bool GL_ScreenSizeDirty;
-
-int GL_3DScale;
-
-bool GL_VSyncStatus;
-
-int ScreenGap = 0;
-int ScreenLayout = 0;
-int ScreenSizing = 0;
-int ScreenRotation = 0;
-
-int MainScreenPos[3];
-int AutoScreenSizing;
-
-uiRect TopScreenRect;
-uiRect BottomScreenRect;
-uiDrawMatrix TopScreenTrans;
-uiDrawMatrix BottomScreenTrans;
-
-bool Touching = false;
-
-u32 KeyInputMask, JoyInputMask;
-u32 KeyHotkeyMask, JoyHotkeyMask;
-u32 HotkeyMask, LastHotkeyMask;
-u32 HotkeyPress, HotkeyRelease;
-
-#define HotkeyDown(hk) (HotkeyMask & (1<<(hk)))
-#define HotkeyPressed(hk) (HotkeyPress & (1<<(hk)))
-#define HotkeyReleased(hk) (HotkeyRelease & (1<<(hk)))
-
-bool LidStatus;
-
-int JoystickID;
-SDL_Joystick* Joystick;
-
-int AudioFreq;
-float AudioSampleFrac;
-SDL_AudioDeviceID AudioDevice, MicDevice;
-
-SDL_cond* AudioSync;
-SDL_mutex* AudioSyncLock;
-
-u32 MicBufferLength = 2048;
-s16 MicBuffer[2048];
-u32 MicBufferReadPos, MicBufferWritePos;
-
-u32 MicWavLength;
-s16* MicWavBuffer;
-
-void SetupScreenRects(int width, int height);
-
-void TogglePause(void* blarg);
-void Reset(void* blarg);
-
-void SetupSRAMPath(int slot);
-
-void SaveState(int slot);
-void LoadState(int slot);
-void UndoStateLoad();
-void GetSavestateName(int slot, char* filename, int len);
-
-void CreateMainWindow(bool opengl);
-void DestroyMainWindow();
-void RecreateMainWindow(bool opengl);
-
-
-
-bool GLScreen_InitShader(GLuint* shader, const char* fs)
-{
- if (!OpenGL_BuildShaderProgram(kScreenVS, fs, shader, "ScreenShader"))
- return false;
-
- glBindAttribLocation(shader[2], 0, "vPosition");
- glBindAttribLocation(shader[2], 1, "vTexcoord");
- glBindFragDataLocation(shader[2], 0, "oColor");
-
- if (!OpenGL_LinkShaderProgram(shader))
- return false;
-
- GLuint uni_id;
-
- uni_id = glGetUniformBlockIndex(shader[2], "uConfig");
- glUniformBlockBinding(shader[2], uni_id, 16);
-
- glUseProgram(shader[2]);
- uni_id = glGetUniformLocation(shader[2], "ScreenTex");
- glUniform1i(uni_id, 0);
- uni_id = glGetUniformLocation(shader[2], "_3DTex");
- glUniform1i(uni_id, 1);
-
- return true;
-}
-
-bool GLScreen_InitOSDShader(GLuint* shader)
-{
- if (!OpenGL_BuildShaderProgram(kScreenVS_OSD, kScreenFS_OSD, shader, "ScreenShaderOSD"))
- return false;
-
- glBindAttribLocation(shader[2], 0, "vPosition");
- glBindFragDataLocation(shader[2], 0, "oColor");
-
- if (!OpenGL_LinkShaderProgram(shader))
- return false;
-
- GLuint uni_id;
-
- uni_id = glGetUniformBlockIndex(shader[2], "uConfig");
- glUniformBlockBinding(shader[2], uni_id, 16);
-
- glUseProgram(shader[2]);
- uni_id = glGetUniformLocation(shader[2], "OSDTex");
- glUniform1i(uni_id, 0);
-
- return true;
-}
-
-bool GLScreen_Init()
-{
- GL_VSyncStatus = Config::ScreenVSync;
-
- // TODO: consider using epoxy?
- if (!OpenGL_Init())
- return false;
-
- const GLubyte* renderer = glGetString(GL_RENDERER); // get renderer string
- const GLubyte* version = glGetString(GL_VERSION); // version as a string
- printf("OpenGL: renderer: %s\n", renderer);
- printf("OpenGL: version: %s\n", version);
-
- if (!GLScreen_InitShader(GL_ScreenShader, kScreenFS))
- return false;
- if (!GLScreen_InitShader(GL_ScreenShaderAccel, kScreenFS_Accel))
- return false;
- if (!GLScreen_InitOSDShader(GL_ScreenShaderOSD))
- return false;
-
- memset(&GL_ShaderConfig, 0, sizeof(GL_ShaderConfig));
-
- glGenBuffers(1, &GL_ShaderConfigUBO);
- glBindBuffer(GL_UNIFORM_BUFFER, GL_ShaderConfigUBO);
- glBufferData(GL_UNIFORM_BUFFER, sizeof(GL_ShaderConfig), &GL_ShaderConfig, GL_STATIC_DRAW);
- glBindBufferBase(GL_UNIFORM_BUFFER, 16, GL_ShaderConfigUBO);
-
- glGenBuffers(1, &GL_ScreenVertexBufferID);
- glBindBuffer(GL_ARRAY_BUFFER, GL_ScreenVertexBufferID);
- glBufferData(GL_ARRAY_BUFFER, sizeof(GL_ScreenVertices), NULL, GL_STATIC_DRAW);
-
- glGenVertexArrays(1, &GL_ScreenVertexArrayID);
- glBindVertexArray(GL_ScreenVertexArrayID);
- glEnableVertexAttribArray(0); // position
- glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4*4, (void*)(0));
- glEnableVertexAttribArray(1); // texcoord
- glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4*4, (void*)(2*4));
-
- glGenTextures(1, &GL_ScreenTexture);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, GL_ScreenTexture);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, 256*3 + 1, 192*2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, NULL);
-
- GL_ScreenSizeDirty = true;
-
- return true;
-}
-
-void GLScreen_DeInit()
-{
- glDeleteTextures(1, &GL_ScreenTexture);
-
- glDeleteVertexArrays(1, &GL_ScreenVertexArrayID);
- glDeleteBuffers(1, &GL_ScreenVertexBufferID);
-
- OpenGL_DeleteShaderProgram(GL_ScreenShader);
- OpenGL_DeleteShaderProgram(GL_ScreenShaderAccel);
- OpenGL_DeleteShaderProgram(GL_ScreenShaderOSD);
-}
-
-void GLScreen_DrawScreen()
-{
- bool vsync = Config::ScreenVSync && !HotkeyDown(HK_FastForward);
- if (vsync != GL_VSyncStatus)
- {
- GL_VSyncStatus = vsync;
- uiGLSetVSync(vsync);
- }
-
- float scale = uiGLGetFramebufferScale(GLContext);
-
- glBindFramebuffer(GL_FRAMEBUFFER, uiGLGetFramebuffer(GLContext));
-
- if (GL_ScreenSizeDirty)
- {
- GL_ScreenSizeDirty = false;
-
- GL_ShaderConfig.uScreenSize[0] = WindowWidth;
- GL_ShaderConfig.uScreenSize[1] = WindowHeight;
- GL_ShaderConfig.u3DScale = GL_3DScale;
-
- glBindBuffer(GL_UNIFORM_BUFFER, GL_ShaderConfigUBO);
- void* unibuf = glMapBuffer(GL_UNIFORM_BUFFER, GL_WRITE_ONLY);
- if (unibuf) memcpy(unibuf, &GL_ShaderConfig, sizeof(GL_ShaderConfig));
- glUnmapBuffer(GL_UNIFORM_BUFFER);
-
- float scwidth, scheight;
-
- float x0, y0, x1, y1;
- float s0, s1, s2, s3;
- float t0, t1, t2, t3;
-
-#define SETVERTEX(i, x, y, s, t) \
- GL_ScreenVertices[4*(i) + 0] = x; \
- GL_ScreenVertices[4*(i) + 1] = y; \
- GL_ScreenVertices[4*(i) + 2] = s; \
- GL_ScreenVertices[4*(i) + 3] = t;
-
- x0 = TopScreenRect.X;
- y0 = TopScreenRect.Y;
- x1 = TopScreenRect.X + TopScreenRect.Width;
- y1 = TopScreenRect.Y + TopScreenRect.Height;
-
- scwidth = 256;
- scheight = 192;
-
- switch (ScreenRotation)
- {
- case 0:
- s0 = 0; t0 = 0;
- s1 = scwidth; t1 = 0;
- s2 = 0; t2 = scheight;
- s3 = scwidth; t3 = scheight;
- break;
-
- case 1:
- s0 = 0; t0 = scheight;
- s1 = 0; t1 = 0;
- s2 = scwidth; t2 = scheight;
- s3 = scwidth; t3 = 0;
- break;
-
- case 2:
- s0 = scwidth; t0 = scheight;
- s1 = 0; t1 = scheight;
- s2 = scwidth; t2 = 0;
- s3 = 0; t3 = 0;
- break;
-
- case 3:
- s0 = scwidth; t0 = 0;
- s1 = scwidth; t1 = scheight;
- s2 = 0; t2 = 0;
- s3 = 0; t3 = scheight;
- break;
- }
-
- SETVERTEX(0, x0, y0, s0, t0);
- SETVERTEX(1, x1, y1, s3, t3);
- SETVERTEX(2, x1, y0, s1, t1);
- SETVERTEX(3, x0, y0, s0, t0);
- SETVERTEX(4, x0, y1, s2, t2);
- SETVERTEX(5, x1, y1, s3, t3);
-
- x0 = BottomScreenRect.X;
- y0 = BottomScreenRect.Y;
- x1 = BottomScreenRect.X + BottomScreenRect.Width;
- y1 = BottomScreenRect.Y + BottomScreenRect.Height;
-
- scwidth = 256;
- scheight = 192;
-
- switch (ScreenRotation)
- {
- case 0:
- s0 = 0; t0 = 192;
- s1 = scwidth; t1 = 192;
- s2 = 0; t2 = 192+scheight;
- s3 = scwidth; t3 = 192+scheight;
- break;
-
- case 1:
- s0 = 0; t0 = 192+scheight;
- s1 = 0; t1 = 192;
- s2 = scwidth; t2 = 192+scheight;
- s3 = scwidth; t3 = 192;
- break;
-
- case 2:
- s0 = scwidth; t0 = 192+scheight;
- s1 = 0; t1 = 192+scheight;
- s2 = scwidth; t2 = 192;
- s3 = 0; t3 = 192;
- break;
-
- case 3:
- s0 = scwidth; t0 = 192;
- s1 = scwidth; t1 = 192+scheight;
- s2 = 0; t2 = 192;
- s3 = 0; t3 = 192+scheight;
- break;
- }
-
- SETVERTEX(6, x0, y0, s0, t0);
- SETVERTEX(7, x1, y1, s3, t3);
- SETVERTEX(8, x1, y0, s1, t1);
- SETVERTEX(9, x0, y0, s0, t0);
- SETVERTEX(10, x0, y1, s2, t2);
- SETVERTEX(11, x1, y1, s3, t3);
-
-#undef SETVERTEX
-
- glBindBuffer(GL_ARRAY_BUFFER, GL_ScreenVertexBufferID);
- glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GL_ScreenVertices), GL_ScreenVertices);
- }
-
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_STENCIL_TEST);
- glDisable(GL_BLEND);
- glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
-
- glViewport(0, 0, WindowWidth*scale, WindowHeight*scale);
-
- if (GPU3D::Renderer == 0)
- OpenGL_UseShaderProgram(GL_ScreenShader);
- else
- OpenGL_UseShaderProgram(GL_ScreenShaderAccel);
-
- glClearColor(0, 0, 0, 1);
- glClear(GL_COLOR_BUFFER_BIT);
-
- if (RunningSomething)
- {
- int frontbuf = GPU::FrontBuffer;
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, GL_ScreenTexture);
-
- if (GPU::Framebuffer[frontbuf][0] && GPU::Framebuffer[frontbuf][1])
- {
- if (GPU3D::Renderer == 0)
- {
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, 192, GL_RGBA_INTEGER,
- GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][0]);
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 192, 256, 192, GL_RGBA_INTEGER,
- GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][1]);
- }
- else
- {
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256*3 + 1, 192, GL_RGBA_INTEGER,
- GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][0]);
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 192, 256*3 + 1, 192, GL_RGBA_INTEGER,
- GL_UNSIGNED_BYTE, GPU::Framebuffer[frontbuf][1]);
- }
- }
-
- glActiveTexture(GL_TEXTURE1);
- if (GPU3D::Renderer != 0)
- GPU3D::GLRenderer::SetupAccelFrame();
-
- glBindBuffer(GL_ARRAY_BUFFER, GL_ScreenVertexBufferID);
- glBindVertexArray(GL_ScreenVertexArrayID);
- glDrawArrays(GL_TRIANGLES, 0, 4*3);
- }
-
- OpenGL_UseShaderProgram(GL_ScreenShaderOSD);
- OSD::Update(true, NULL);
-
- glFlush();
- uiGLSwapBuffers(GLContext);
-}
-
-void MicLoadWav(char* name)
-{
- SDL_AudioSpec format;
- memset(&format, 0, sizeof(SDL_AudioSpec));
-
- if (MicWavBuffer) delete[] MicWavBuffer;
- MicWavBuffer = NULL;
- MicWavLength = 0;
-
- u8* buf;
- u32 len;
- if (!SDL_LoadWAV(name, &format, &buf, &len))
- return;
-
- const u64 dstfreq = 44100;
-
- if (format.format == AUDIO_S16 || format.format == AUDIO_U16)
- {
- int srcinc = format.channels;
- len /= (2 * srcinc);
-
- MicWavLength = (len * dstfreq) / format.freq;
- if (MicWavLength < 735) MicWavLength = 735;
- MicWavBuffer = new s16[MicWavLength];
-
- float res_incr = len / (float)MicWavLength;
- float res_timer = 0;
- int res_pos = 0;
-
- for (int i = 0; i < MicWavLength; i++)
- {
- u16 val = ((u16*)buf)[res_pos];
- if (SDL_AUDIO_ISUNSIGNED(format.format)) val ^= 0x8000;
-
- MicWavBuffer[i] = val;
-
- res_timer += res_incr;
- while (res_timer >= 1.0)
- {
- res_timer -= 1.0;
- res_pos += srcinc;
- }
- }
- }
- else if (format.format == AUDIO_S8 || format.format == AUDIO_U8)
- {
- int srcinc = format.channels;
- len /= srcinc;
-
- MicWavLength = (len * dstfreq) / format.freq;
- if (MicWavLength < 735) MicWavLength = 735;
- MicWavBuffer = new s16[MicWavLength];
-
- float res_incr = len / (float)MicWavLength;
- float res_timer = 0;
- int res_pos = 0;
-
- for (int i = 0; i < MicWavLength; i++)
- {
- u16 val = buf[res_pos] << 8;
- if (SDL_AUDIO_ISUNSIGNED(format.format)) val ^= 0x8000;
-
- MicWavBuffer[i] = val;
-
- res_timer += res_incr;
- while (res_timer >= 1.0)
- {
- res_timer -= 1.0;
- res_pos += srcinc;
- }
- }
- }
- else
- printf("bad WAV format %08X\n", format.format);
-
- SDL_FreeWAV(buf);
-}
-
-void AudioCallback(void* data, Uint8* stream, int len)
-{
- len /= (sizeof(s16) * 2);
-
- // resample incoming audio to match the output sample rate
-
- float f_len_in = (len * 32823.6328125) / (float)AudioFreq;
- f_len_in += AudioSampleFrac;
- int len_in = (int)floor(f_len_in);
- AudioSampleFrac = f_len_in - len_in;
-
- s16 buf_in[1024*2];
- s16* buf_out = (s16*)stream;
-
- int num_in;
- int num_out = len;
-
- SDL_LockMutex(AudioSyncLock);
- num_in = SPU::ReadOutput(buf_in, len_in);
- SDL_CondSignal(AudioSync);
- SDL_UnlockMutex(AudioSyncLock);
-
- if (num_in < 1)
- {
- memset(stream, 0, len*sizeof(s16)*2);
- return;
- }
-
- int margin = 6;
- if (num_in < len_in-margin)
- {
- int last = num_in-1;
- if (last < 0) last = 0;
-
- for (int i = num_in; i < len_in-margin; i++)
- ((u32*)buf_in)[i] = ((u32*)buf_in)[last];
-
- num_in = len_in-margin;
- }
-
- float res_incr = num_in / (float)num_out;
- float res_timer = 0;
- int res_pos = 0;
-
- int volume = Config::AudioVolume;
-
- for (int i = 0; i < len; i++)
- {
- buf_out[i*2 ] = (buf_in[res_pos*2 ] * volume) >> 8;
- buf_out[i*2+1] = (buf_in[res_pos*2+1] * volume) >> 8;
-
- /*s16 s_l = buf_in[res_pos*2 ];
- s16 s_r = buf_in[res_pos*2+1];
-
- float a = res_timer;
- float b = 1.0 - a;
- s_l = (s_l * a) + (buf_in[(res_pos-1)*2 ] * b);
- s_r = (s_r * a) + (buf_in[(res_pos-1)*2+1] * b);
-
- buf_out[i*2 ] = (s_l * volume) >> 8;
- buf_out[i*2+1] = (s_r * volume) >> 8;*/
-
- res_timer += res_incr;
- while (res_timer >= 1.0)
- {
- res_timer -= 1.0;
- res_pos++;
- }
- }
-}
-
-void MicCallback(void* data, Uint8* stream, int len)
-{
- if (Config::MicInputType != 1) return;
-
- s16* input = (s16*)stream;
- len /= sizeof(s16);
-
- if ((MicBufferWritePos + len) > MicBufferLength)
- {
- u32 len1 = MicBufferLength - MicBufferWritePos;
- memcpy(&MicBuffer[MicBufferWritePos], &input[0], len1*sizeof(s16));
- memcpy(&MicBuffer[0], &input[len1], (len - len1)*sizeof(s16));
- MicBufferWritePos = len - len1;
- }
- else
- {
- memcpy(&MicBuffer[MicBufferWritePos], input, len*sizeof(s16));
- MicBufferWritePos += len;
- }
-}
-
-void FeedMicInput()
-{
- int type = Config::MicInputType;
- bool cmd = HotkeyDown(HK_Mic);
-
- if ((type != 1 && !cmd) ||
- (type == 1 && MicBufferLength == 0) ||
- (type == 3 && MicWavBuffer == NULL))
- {
- type = 0;
- MicBufferReadPos = 0;
- }
-
- switch (type)
- {
- case 0: // no mic
- NDS::MicInputFrame(NULL, 0);
- break;
-
- case 1: // host mic
- if ((MicBufferReadPos + 735) > MicBufferLength)
- {
- s16 tmp[735];
- u32 len1 = MicBufferLength - MicBufferReadPos;
- memcpy(&tmp[0], &MicBuffer[MicBufferReadPos], len1*sizeof(s16));
- memcpy(&tmp[len1], &MicBuffer[0], (735 - len1)*sizeof(s16));
-
- NDS::MicInputFrame(tmp, 735);
- MicBufferReadPos = 735 - len1;
- }
- else
- {
- NDS::MicInputFrame(&MicBuffer[MicBufferReadPos], 735);
- MicBufferReadPos += 735;
- }
- break;
-
- case 2: // white noise
- {
- s16 tmp[735];
- for (int i = 0; i < 735; i++) tmp[i] = rand() & 0xFFFF;
- NDS::MicInputFrame(tmp, 735);
- }
- break;
-
- case 3: // WAV
- if ((MicBufferReadPos + 735) > MicWavLength)
- {
- s16 tmp[735];
- u32 len1 = MicWavLength - MicBufferReadPos;
- memcpy(&tmp[0], &MicWavBuffer[MicBufferReadPos], len1*sizeof(s16));
- memcpy(&tmp[len1], &MicWavBuffer[0], (735 - len1)*sizeof(s16));
-
- NDS::MicInputFrame(tmp, 735);
- MicBufferReadPos = 735 - len1;
- }
- else
- {
- NDS::MicInputFrame(&MicWavBuffer[MicBufferReadPos], 735);
- MicBufferReadPos += 735;
- }
- break;
- }
-}
-
-void OpenJoystick()
-{
- if (Joystick) SDL_JoystickClose(Joystick);
-
- int num = SDL_NumJoysticks();
- if (num < 1)
- {
- Joystick = NULL;
- return;
- }
-
- if (JoystickID >= num)
- JoystickID = 0;
-
- Joystick = SDL_JoystickOpen(JoystickID);
-}
-
-bool JoystickButtonDown(int val)
-{
- if (val == -1) return false;
-
- bool hasbtn = ((val & 0xFFFF) != 0xFFFF);
-
- if (hasbtn)
- {
- if (val & 0x100)
- {
- int hatnum = (val >> 4) & 0xF;
- int hatdir = val & 0xF;
- Uint8 hatval = SDL_JoystickGetHat(Joystick, hatnum);
-
- bool pressed = false;
- if (hatdir == 0x1) pressed = (hatval & SDL_HAT_UP);
- else if (hatdir == 0x4) pressed = (hatval & SDL_HAT_DOWN);
- else if (hatdir == 0x2) pressed = (hatval & SDL_HAT_RIGHT);
- else if (hatdir == 0x8) pressed = (hatval & SDL_HAT_LEFT);
-
- if (pressed) return true;
- }
- else
- {
- int btnnum = val & 0xFFFF;
- Uint8 btnval = SDL_JoystickGetButton(Joystick, btnnum);
-
- if (btnval) return true;
- }
- }
-
- if (val & 0x10000)
- {
- int axisnum = (val >> 24) & 0xF;
- int axisdir = (val >> 20) & 0xF;
- Sint16 axisval = SDL_JoystickGetAxis(Joystick, axisnum);
-
- switch (axisdir)
- {
- case 0: // positive
- if (axisval > 16384) return true;
- break;
-
- case 1: // negative
- if (axisval < -16384) return true;
- break;
-
- case 2: // trigger
- if (axisval > 0) return true;
- break;
- }
- }
-
- return false;
-}
-
-void ProcessInput()
-{
- SDL_JoystickUpdate();
-
- if (Joystick)
- {
- if (!SDL_JoystickGetAttached(Joystick))
- {
- SDL_JoystickClose(Joystick);
- Joystick = NULL;
- }
- }
- if (!Joystick && (SDL_NumJoysticks() > 0))
- {
- JoystickID = Config::JoystickID;
- OpenJoystick();
- }
-
- JoyInputMask = 0xFFF;
- for (int i = 0; i < 12; i++)
- if (JoystickButtonDown(Config::JoyMapping[i]))
- JoyInputMask &= ~(1<<i);
-
- JoyHotkeyMask = 0;
- for (int i = 0; i < HK_MAX; i++)
- if (JoystickButtonDown(Config::HKJoyMapping[i]))
- JoyHotkeyMask |= (1<<i);
-
- HotkeyMask = KeyHotkeyMask | JoyHotkeyMask;
- HotkeyPress = HotkeyMask & ~LastHotkeyMask;
- HotkeyRelease = LastHotkeyMask & ~HotkeyMask;
- LastHotkeyMask = HotkeyMask;
-}
-
-bool JoyButtonPressed(int btnid, int njoybuttons, Uint8* joybuttons, Uint32 hat)
-{
- if (btnid < 0) return false;
-
- hat &= ~(hat >> 4);
-
- bool pressed = false;
- if (btnid == 0x101) // up
- pressed = (hat & SDL_HAT_UP);
- else if (btnid == 0x104) // down
- pressed = (hat & SDL_HAT_DOWN);
- else if (btnid == 0x102) // right
- pressed = (hat & SDL_HAT_RIGHT);
- else if (btnid == 0x108) // left
- pressed = (hat & SDL_HAT_LEFT);
- else if (btnid < njoybuttons)
- pressed = (joybuttons[btnid] & ~(joybuttons[btnid] >> 1)) & 0x01;
-
- return pressed;
-}
-
-bool JoyButtonHeld(int btnid, int njoybuttons, Uint8* joybuttons, Uint32 hat)
-{
- if (btnid < 0) return false;
-
- bool pressed = false;
- if (btnid == 0x101) // up
- pressed = (hat & SDL_HAT_UP);
- else if (btnid == 0x104) // down
- pressed = (hat & SDL_HAT_DOWN);
- else if (btnid == 0x102) // right
- pressed = (hat & SDL_HAT_RIGHT);
- else if (btnid == 0x108) // left
- pressed = (hat & SDL_HAT_LEFT);
- else if (btnid < njoybuttons)
- pressed = joybuttons[btnid] & 0x01;
-
- return pressed;
-}
-
-void UpdateWindowTitle(void* data)
-{
- if (EmuStatus == 0) return;
- void** dataarray = (void**)data;
- SDL_LockMutex((SDL_mutex*)dataarray[1]);
- uiWindowSetTitle(MainWindow, (const char*)dataarray[0]);
- SDL_UnlockMutex((SDL_mutex*)dataarray[1]);
-}
-
-void UpdateFPSLimit(void* data)
-{
- uiMenuItemSetChecked(MenuItem_LimitFPS, Config::LimitFPS==1);
-}
-
-int EmuThreadFunc(void* burp)
-{
- NDS::Init();
-
- MainScreenPos[0] = 0;
- MainScreenPos[1] = 0;
- MainScreenPos[2] = 0;
- AutoScreenSizing = 0;
-
- if (Screen_UseGL)
- {
- uiGLMakeContextCurrent(GLContext);
- GPU3D::InitRenderer(true);
- uiGLMakeContextCurrent(NULL);
- }
- else
- {
- GPU3D::InitRenderer(false);
- }
-
- Touching = false;
- KeyInputMask = 0xFFF;
- JoyInputMask = 0xFFF;
- KeyHotkeyMask = 0;
- JoyHotkeyMask = 0;
- HotkeyMask = 0;
- LastHotkeyMask = 0;
- LidStatus = false;
-
- u32 nframes = 0;
- u32 starttick = SDL_GetTicks();
- u32 lasttick = starttick;
- u32 lastmeasuretick = lasttick;
- u32 fpslimitcount = 0;
- u64 perfcount = SDL_GetPerformanceCounter();
- u64 perffreq = SDL_GetPerformanceFrequency();
- float samplesleft = 0;
- u32 nsamples = 0;
-
- char melontitle[100];
- SDL_mutex* titlemutex = SDL_CreateMutex();
- void* titledata[2] = {melontitle, titlemutex};
-
- while (EmuRunning != 0)
- {
- ProcessInput();
-
- if (HotkeyPressed(HK_FastForwardToggle))
- {
- Config::LimitFPS = !Config::LimitFPS;
- uiQueueMain(UpdateFPSLimit, NULL);
- }
- // TODO: similar hotkeys for video/audio sync?
-
- if (HotkeyPressed(HK_Pause)) uiQueueMain(TogglePause, NULL);
- if (HotkeyPressed(HK_Reset)) uiQueueMain(Reset, NULL);
-
- if (GBACart::CartInserted && GBACart::HasSolarSensor)
- {
- if (HotkeyPressed(HK_SolarSensorDecrease))
- {
- if (GBACart_SolarSensor::LightLevel > 0) GBACart_SolarSensor::LightLevel--;
- char msg[64];
- sprintf(msg, "Solar sensor level set to %d", GBACart_SolarSensor::LightLevel);
- OSD::AddMessage(0, msg);
- }
- if (HotkeyPressed(HK_SolarSensorIncrease))
- {
- if (GBACart_SolarSensor::LightLevel < 10) GBACart_SolarSensor::LightLevel++;
- char msg[64];
- sprintf(msg, "Solar sensor level set to %d", GBACart_SolarSensor::LightLevel);
- OSD::AddMessage(0, msg);
- }
- }
-
- if (EmuRunning == 1)
- {
- EmuStatus = 1;
-
- // process input and hotkeys
- NDS::SetKeyMask(KeyInputMask & JoyInputMask);
-
- if (HotkeyPressed(HK_Lid))
- {
- LidStatus = !LidStatus;
- NDS::SetLidClosed(LidStatus);
- OSD::AddMessage(0, LidStatus ? "Lid closed" : "Lid opened");
- }
-
- // microphone input
- FeedMicInput();
-
- if (Screen_UseGL)
- {
- uiGLBegin(GLContext);
- uiGLMakeContextCurrent(GLContext);
- }
-
- // auto screen layout
- {
- MainScreenPos[2] = MainScreenPos[1];
- MainScreenPos[1] = MainScreenPos[0];
- MainScreenPos[0] = NDS::PowerControl9 >> 15;
-
- int guess;
- if (MainScreenPos[0] == MainScreenPos[2] &&
- MainScreenPos[0] != MainScreenPos[1])
- {
- // constant flickering, likely displaying 3D on both screens
- // TODO: when both screens are used for 2D only...???
- guess = 0;
- }
- else
- {
- if (MainScreenPos[0] == 1)
- guess = 1;
- else
- guess = 2;
- }
-
- if (guess != AutoScreenSizing)
- {
- AutoScreenSizing = guess;
- SetupScreenRects(WindowWidth, WindowHeight);
- }
- }
-
- // emulate
- u32 nlines = NDS::RunFrame();
-
-#ifdef MELONCAP
- MelonCap::Update();
-#endif // MELONCAP
-
- if (EmuRunning == 0) break;
-
- if (Screen_UseGL)
- {
- GLScreen_DrawScreen();
- uiGLEnd(GLContext);
- }
- uiAreaQueueRedrawAll(MainDrawArea);
-
- bool fastforward = HotkeyDown(HK_FastForward);
-
- if (Config::AudioSync && !fastforward)
- {
- SDL_LockMutex(AudioSyncLock);
- while (SPU::GetOutputSize() > 1024)
- {
- int ret = SDL_CondWaitTimeout(AudioSync, AudioSyncLock, 500);
- if (ret == SDL_MUTEX_TIMEDOUT) break;
- }
- SDL_UnlockMutex(AudioSyncLock);
- }
- else
- {
- // ensure the audio FIFO doesn't overflow
- //SPU::TrimOutput();
- }
-
- float framerate = (1000.0f * nlines) / (60.0f * 263.0f);
-
- {
- u32 curtick = SDL_GetTicks();
- u32 delay = curtick - lasttick;
-
- bool limitfps = Config::LimitFPS && !fastforward;
- if (limitfps)
- {
- float wantedtickF = starttick + (framerate * (fpslimitcount+1));
- u32 wantedtick = (u32)ceil(wantedtickF);
- if (curtick < wantedtick) SDL_Delay(wantedtick - curtick);
-
- lasttick = SDL_GetTicks();
- fpslimitcount++;
- if ((abs(wantedtickF - (float)wantedtick) < 0.001312) || (fpslimitcount > 60))
- {
- fpslimitcount = 0;
- nsamples = 0;
- starttick = lasttick;
- }
- }
- else
- {
- if (delay < 1) SDL_Delay(1);
- lasttick = SDL_GetTicks();
- }
- }
-
- nframes++;
- if (nframes >= 30)
- {
- u32 tick = SDL_GetTicks();
- u32 diff = tick - lastmeasuretick;
- lastmeasuretick = tick;
-
- u32 fps;
- if (diff < 1) fps = 77777;
- else fps = (nframes * 1000) / diff;
- nframes = 0;
-
- float fpstarget;
- if (framerate < 1) fpstarget = 999;
- else fpstarget = 1000.0f/framerate;
-
- SDL_LockMutex(titlemutex);
- sprintf(melontitle, "[%d/%.0f] melonDS " MELONDS_VERSION, fps, fpstarget);
- SDL_UnlockMutex(titlemutex);
- uiQueueMain(UpdateWindowTitle, titledata);
- }
- }
- else
- {
- // paused
- nframes = 0;
- lasttick = SDL_GetTicks();
- starttick = lasttick;
- lastmeasuretick = lasttick;
- fpslimitcount = 0;
-
- if (EmuRunning == 2)
- {
- if (Screen_UseGL)
- {
- uiGLBegin(GLContext);
- uiGLMakeContextCurrent(GLContext);
- GLScreen_DrawScreen();
- uiGLEnd(GLContext);
- }
- uiAreaQueueRedrawAll(MainDrawArea);
- }
-
- if (Screen_UseGL) uiGLMakeContextCurrent(NULL);
-
- EmuStatus = EmuRunning;
-
- SDL_Delay(100);
- }
- }
-
- EmuStatus = 0;
-
- SDL_DestroyMutex(titlemutex);
-
- if (Screen_UseGL) uiGLMakeContextCurrent(GLContext);
-
- NDS::DeInit();
- Platform::LAN_DeInit();
-
- if (Screen_UseGL)
- {
- OSD::DeInit(true);
- GLScreen_DeInit();
- }
- else
- OSD::DeInit(false);
-
- if (Screen_UseGL) uiGLMakeContextCurrent(NULL);
-
- return 44203;
-}
-
-void StopEmuThread()
-{
- EmuRunning = 0;
- SDL_WaitThread(EmuThread, NULL);
-}
-
-
-void OnAreaDraw(uiAreaHandler* handler, uiArea* area, uiAreaDrawParams* params)
-{
- if (!ScreenDrawInited)
- {
- if (ScreenBitmap[0]) uiDrawFreeBitmap(ScreenBitmap[0]);
- if (ScreenBitmap[1]) uiDrawFreeBitmap(ScreenBitmap[1]);
-
- ScreenDrawInited = true;
- ScreenBitmap[0] = uiDrawNewBitmap(params->Context, 256, 192, 0);
- ScreenBitmap[1] = uiDrawNewBitmap(params->Context, 256, 192, 0);
- }
-
- int frontbuf = GPU::FrontBuffer;
- if (!ScreenBitmap[0] || !ScreenBitmap[1]) return;
- if (!GPU::Framebuffer[frontbuf][0] || !GPU::Framebuffer[frontbuf][1]) return;
-
- uiRect top = {0, 0, 256, 192};
- uiRect bot = {0, 0, 256, 192};
-
- uiDrawBitmapUpdate(ScreenBitmap[0], GPU::Framebuffer[frontbuf][0]);
- uiDrawBitmapUpdate(ScreenBitmap[1], GPU::Framebuffer[frontbuf][1]);
-
- uiDrawSave(params->Context);
- uiDrawTransform(params->Context, &TopScreenTrans);
- uiDrawBitmapDraw(params->Context, ScreenBitmap[0], &top, &TopScreenRect, Config::ScreenFilter==1);
- uiDrawRestore(params->Context);
-
- uiDrawSave(params->Context);
- uiDrawTransform(params->Context, &BottomScreenTrans);
- uiDrawBitmapDraw(params->Context, ScreenBitmap[1], &bot, &BottomScreenRect, Config::ScreenFilter==1);
- uiDrawRestore(params->Context);
-
- OSD::Update(false, params);
-}
-
-void OnAreaMouseEvent(uiAreaHandler* handler, uiArea* area, uiAreaMouseEvent* evt)
-{
- int x = (int)evt->X;
- int y = (int)evt->Y;
-
- if (Touching && (evt->Up == 1))
- {
- Touching = false;
- NDS::ReleaseKey(16+6);
- NDS::ReleaseScreen();
- }
- else if (!Touching && (evt->Down == 1) &&
- (x >= BottomScreenRect.X) && (y >= BottomScreenRect.Y) &&
- (x < (BottomScreenRect.X+BottomScreenRect.Width)) && (y < (BottomScreenRect.Y+BottomScreenRect.Height)))
- {
- Touching = true;
- NDS::PressKey(16+6);
- }
-
- if (Touching)
- {
- x -= BottomScreenRect.X;
- y -= BottomScreenRect.Y;
-
- if (ScreenRotation == 0 || ScreenRotation == 2)
- {
- if (BottomScreenRect.Width != 256)
- x = (x * 256) / BottomScreenRect.Width;
- if (BottomScreenRect.Height != 192)
- y = (y * 192) / BottomScreenRect.Height;
-
- if (ScreenRotation == 2)
- {
- x = 255 - x;
- y = 191 - y;
- }
- }
- else
- {
- if (BottomScreenRect.Width != 192)
- x = (x * 192) / BottomScreenRect.Width;
- if (BottomScreenRect.Height != 256)
- y = (y * 256) / BottomScreenRect.Height;
-
- if (ScreenRotation == 1)
- {
- int tmp = x;
- x = y;
- y = 191 - tmp;
- }
- else
- {
- int tmp = x;
- x = 255 - y;
- y = tmp;
- }
- }
-
- // clamp
- if (x < 0) x = 0;
- else if (x > 255) x = 255;
- if (y < 0) y = 0;
- else if (y > 191) y = 191;
-
- // TODO: take advantage of possible extra precision when possible? (scaled window for example)
- NDS::TouchScreen(x, y);
- }
-}
-
-void OnAreaMouseCrossed(uiAreaHandler* handler, uiArea* area, int left)
-{
-}
-
-void OnAreaDragBroken(uiAreaHandler* handler, uiArea* area)
-{
-}
-
-bool EventMatchesKey(uiAreaKeyEvent* evt, int val, bool checkmod)
-{
- if (val == -1) return false;
-
- int key = val & 0xFFFF;
- int mod = val >> 16;
- return evt->Scancode == key && (!checkmod || evt->Modifiers == mod);
-}
-
-int OnAreaKeyEvent(uiAreaHandler* handler, uiArea* area, uiAreaKeyEvent* evt)
-{
- // TODO: release all keys if the window loses focus? or somehow global key input?
- if (evt->Scancode == 0x38) // ALT
- return 0;
- if (evt->Modifiers == 0x2) // ALT+key
- return 0;
-
- if (evt->Up)
- {
- for (int i = 0; i < 12; i++)
- if (EventMatchesKey(evt, Config::KeyMapping[i], false))
- KeyInputMask |= (1<<i);
-
- for (int i = 0; i < HK_MAX; i++)
- if (EventMatchesKey(evt, Config::HKKeyMapping[i], true))
- KeyHotkeyMask &= ~(1<<i);
- }
- else if (!evt->Repeat)
- {
- // TODO, eventually: make savestate keys configurable?
- // F keys: 3B-44, 57-58 | SHIFT: mod. 0x4
- if (evt->Scancode >= 0x3B && evt->Scancode <= 0x42) // F1-F8, quick savestate
- {
- if (evt->Modifiers == 0x4) SaveState(1 + (evt->Scancode - 0x3B));
- else if (evt->Modifiers == 0x0) LoadState(1 + (evt->Scancode - 0x3B));
- }
- else if (evt->Scancode == 0x43) // F9, savestate from/to file
- {
- if (evt->Modifiers == 0x4) SaveState(0);
- else if (evt->Modifiers == 0x0) LoadState(0);
- }
- else if (evt->Scancode == 0x58) // F12, undo savestate
- {
- if (evt->Modifiers == 0x0) UndoStateLoad();
- }
-
- for (int i = 0; i < 12; i++)
- if (EventMatchesKey(evt, Config::KeyMapping[i], false))
- KeyInputMask &= ~(1<<i);
-
- for (int i = 0; i < HK_MAX; i++)
- if (EventMatchesKey(evt, Config::HKKeyMapping[i], true))
- KeyHotkeyMask |= (1<<i);
-
- // REMOVE ME
- //if (evt->Scancode == 0x57) // F11
- // NDS::debug(0);
- }
-
- return 1;
-}
-
-void SetupScreenRects(int width, int height)
-{
- bool horizontal = false;
- bool sideways = false;
-
- if (ScreenRotation == 1 || ScreenRotation == 3)
- sideways = true;
-
- if (ScreenLayout == 2) horizontal = true;
- else if (ScreenLayout == 0)
- {
- if (sideways)
- horizontal = true;
- }
-
- int sizemode;
- if (ScreenSizing == 3)
- sizemode = AutoScreenSizing;
- else
- sizemode = ScreenSizing;
-
- int screenW, screenH, gap;
- if (sideways)
- {
- screenW = 192;
- screenH = 256;
- }
- else
- {
- screenW = 256;
- screenH = 192;
- }
-
- gap = ScreenGap;
-
- uiRect *topscreen, *bottomscreen;
- if (ScreenRotation == 1 || ScreenRotation == 2)
- {
- topscreen = &BottomScreenRect;
- bottomscreen = &TopScreenRect;
- }
- else
- {
- topscreen = &TopScreenRect;
- bottomscreen = &BottomScreenRect;
- }
-
- if (horizontal)
- {
- // side-by-side
-
- int heightreq;
- int startX = 0;
-
- width -= gap;
-
- if (sizemode == 0) // even
- {
- heightreq = (width * screenH) / (screenW*2);
- if (heightreq > height)
- {
- int newwidth = (height * width) / heightreq;
- startX = (width - newwidth) / 2;
- heightreq = height;
- width = newwidth;
- }
- }
- else // emph. top/bottom
- {
- heightreq = ((width - screenW) * screenH) / screenW;
- if (heightreq > height)
- {
- int newwidth = ((height * (width - screenW)) / heightreq) + screenW;
- startX = (width - newwidth) / 2;
- heightreq = height;
- width = newwidth;
- }
- }
-
- if (sizemode == 2)
- {
- topscreen->Width = screenW;
- topscreen->Height = screenH;
- }
- else
- {
- topscreen->Width = (sizemode==0) ? (width / 2) : (width - screenW);
- topscreen->Height = heightreq;
- }
- topscreen->X = startX;
- topscreen->Y = ((height - heightreq) / 2) + (heightreq - topscreen->Height);
-
- bottomscreen->X = topscreen->X + topscreen->Width + gap;
-
- if (sizemode == 1)
- {
- bottomscreen->Width = screenW;
- bottomscreen->Height = screenH;
- }
- else
- {
- bottomscreen->Width = width - topscreen->Width;
- bottomscreen->Height = heightreq;
- }
- bottomscreen->Y = ((height - heightreq) / 2) + (heightreq - bottomscreen->Height);
- }
- else
- {
- // top then bottom
-
- int widthreq;
- int startY = 0;
-
- height -= gap;
-
- if (sizemode == 0) // even
- {
- widthreq = (height * screenW) / (screenH*2);
- if (widthreq > width)
- {
- int newheight = (width * height) / widthreq;
- startY = (height - newheight) / 2;
- widthreq = width;
- height = newheight;
- }
- }
- else // emph. top/bottom
- {
- widthreq = ((height - screenH) * screenW) / screenH;
- if (widthreq > width)
- {
- int newheight = ((width * (height - screenH)) / widthreq) + screenH;
- startY = (height - newheight) / 2;
- widthreq = width;
- height = newheight;
- }
- }
-
- if (sizemode == 2)
- {
- topscreen->Width = screenW;
- topscreen->Height = screenH;
- }
- else
- {
- topscreen->Width = widthreq;
- topscreen->Height = (sizemode==0) ? (height / 2) : (height - screenH);
- }
- topscreen->Y = startY;
- topscreen->X = (width - topscreen->Width) / 2;
-
- bottomscreen->Y = topscreen->Y + topscreen->Height + gap;
-
- if (sizemode == 1)
- {
- bottomscreen->Width = screenW;
- bottomscreen->Height = screenH;
- }
- else
- {
- bottomscreen->Width = widthreq;
- bottomscreen->Height = height - topscreen->Height;
- }
- bottomscreen->X = (width - bottomscreen->Width) / 2;
- }
-
- // setup matrices for potential rotation
-
- uiDrawMatrixSetIdentity(&TopScreenTrans);
- uiDrawMatrixSetIdentity(&BottomScreenTrans);
-
- switch (ScreenRotation)
- {
- case 1: // 90°
- {
- uiDrawMatrixTranslate(&TopScreenTrans, -TopScreenRect.X, -TopScreenRect.Y);
- uiDrawMatrixRotate(&TopScreenTrans, 0, 0, M_PI/2.0f);
- uiDrawMatrixScale(&TopScreenTrans, 0, 0,
- TopScreenRect.Width/(double)TopScreenRect.Height,
- TopScreenRect.Height/(double)TopScreenRect.Width);
- uiDrawMatrixTranslate(&TopScreenTrans, TopScreenRect.X+TopScreenRect.Width, TopScreenRect.Y);
-
- uiDrawMatrixTranslate(&BottomScreenTrans, -BottomScreenRect.X, -BottomScreenRect.Y);
- uiDrawMatrixRotate(&BottomScreenTrans, 0, 0, M_PI/2.0f);
- uiDrawMatrixScale(&BottomScreenTrans, 0, 0,
- BottomScreenRect.Width/(double)BottomScreenRect.Height,
- BottomScreenRect.Height/(double)BottomScreenRect.Width);
- uiDrawMatrixTranslate(&BottomScreenTrans, BottomScreenRect.X+BottomScreenRect.Width, BottomScreenRect.Y);
- }
- break;
-
- case 2: // 180°
- {
- uiDrawMatrixTranslate(&TopScreenTrans, -TopScreenRect.X, -TopScreenRect.Y);
- uiDrawMatrixRotate(&TopScreenTrans, 0, 0, M_PI);
- uiDrawMatrixTranslate(&TopScreenTrans, TopScreenRect.X+TopScreenRect.Width, TopScreenRect.Y+TopScreenRect.Height);
-
- uiDrawMatrixTranslate(&BottomScreenTrans, -BottomScreenRect.X, -BottomScreenRect.Y);
- uiDrawMatrixRotate(&BottomScreenTrans, 0, 0, M_PI);
- uiDrawMatrixTranslate(&BottomScreenTrans, BottomScreenRect.X+BottomScreenRect.Width, BottomScreenRect.Y+BottomScreenRect.Height);
- }
- break;
-
- case 3: // 270°
- {
- uiDrawMatrixTranslate(&TopScreenTrans, -TopScreenRect.X, -TopScreenRect.Y);
- uiDrawMatrixRotate(&TopScreenTrans, 0, 0, -M_PI/2.0f);
- uiDrawMatrixScale(&TopScreenTrans, 0, 0,
- TopScreenRect.Width/(double)TopScreenRect.Height,
- TopScreenRect.Height/(double)TopScreenRect.Width);
- uiDrawMatrixTranslate(&TopScreenTrans, TopScreenRect.X, TopScreenRect.Y+TopScreenRect.Height);
-
- uiDrawMatrixTranslate(&BottomScreenTrans, -BottomScreenRect.X, -BottomScreenRect.Y);
- uiDrawMatrixRotate(&BottomScreenTrans, 0, 0, -M_PI/2.0f);
- uiDrawMatrixScale(&BottomScreenTrans, 0, 0,
- BottomScreenRect.Width/(double)BottomScreenRect.Height,
- BottomScreenRect.Height/(double)BottomScreenRect.Width);
- uiDrawMatrixTranslate(&BottomScreenTrans, BottomScreenRect.X, BottomScreenRect.Y+BottomScreenRect.Height);
- }
- break;
- }
-
- GL_ScreenSizeDirty = true;
-}
-
-void SetMinSize(int w, int h)
-{
- int cw, ch;
- uiWindowContentSize(MainWindow, &cw, &ch);
-
- uiControlSetMinSize(uiControl(MainDrawArea), w, h);
- if ((cw < w) || (ch < h))
- {
- if (cw < w) cw = w;
- if (ch < h) ch = h;
- uiWindowSetContentSize(MainWindow, cw, ch);
- }
-}
-
-void OnAreaResize(uiAreaHandler* handler, uiArea* area, int width, int height)
-{
- SetupScreenRects(width, height);
-
- // TODO:
- // should those be the size of the uiArea, or the size of the window client area?
- // for now the uiArea fills the whole window anyway
- // but... we never know, I guess
- WindowWidth = width;
- WindowHeight = height;
-
- int ismax = uiWindowMaximized(MainWindow);
- int ismin = uiWindowMinimized(MainWindow);
-
- Config::WindowMaximized = ismax;
- if (!ismax && !ismin)
- {
- Config::WindowWidth = width;
- Config::WindowHeight = height;
- }
-
- OSD::WindowResized(Screen_UseGL);
-}
-
-
-void Run()
-{
- EmuRunning = 1;
- RunningSomething = true;
-
- SPU::InitOutput();
- AudioSampleFrac = 0;
- SDL_PauseAudioDevice(AudioDevice, 0);
- SDL_PauseAudioDevice(MicDevice, 0);
-
- uiMenuItemEnable(MenuItem_SaveState);
- uiMenuItemEnable(MenuItem_LoadState);
-
- if (SavestateLoaded)
- uiMenuItemEnable(MenuItem_UndoStateLoad);
- else
- uiMenuItemDisable(MenuItem_UndoStateLoad);
-
- for (int i = 0; i < 8; i++)
- {
- char ssfile[1024];
- GetSavestateName(i+1, ssfile, 1024);
- if (Platform::FileExists(ssfile)) uiMenuItemEnable(MenuItem_LoadStateSlot[i]);
- else uiMenuItemDisable(MenuItem_LoadStateSlot[i]);
- }
-
- for (int i = 0; i < 9; i++) uiMenuItemEnable(MenuItem_SaveStateSlot[i]);
- uiMenuItemEnable(MenuItem_LoadStateSlot[8]);
-
- uiMenuItemEnable(MenuItem_Pause);
- uiMenuItemEnable(MenuItem_Reset);
- uiMenuItemEnable(MenuItem_Stop);
- uiMenuItemSetChecked(MenuItem_Pause, 0);
-}
-
-void TogglePause(void* blarg)
-{
- if (!RunningSomething) return;
-
- if (EmuRunning == 1)
- {
- // enable pause
- EmuRunning = 2;
- uiMenuItemSetChecked(MenuItem_Pause, 1);
-
- SPU::DrainOutput();
- SDL_PauseAudioDevice(AudioDevice, 1);
- SDL_PauseAudioDevice(MicDevice, 1);
-
- OSD::AddMessage(0, "Paused");
- }
- else
- {
- // disable pause
- EmuRunning = 1;
- uiMenuItemSetChecked(MenuItem_Pause, 0);
-
- SPU::InitOutput();
- AudioSampleFrac = 0;
- SDL_PauseAudioDevice(AudioDevice, 0);
- SDL_PauseAudioDevice(MicDevice, 0);
-
- OSD::AddMessage(0, "Resumed");
- }
-}
-
-void Reset(void* blarg)
-{
- if (!RunningSomething) return;
-
- EmuRunning = 2;
- while (EmuStatus != 2);
-
- SavestateLoaded = false;
- uiMenuItemDisable(MenuItem_UndoStateLoad);
-
- if (ROMPath[0][0] == '\0')
- NDS::LoadBIOS();
- else
- {
- SetupSRAMPath(0);
- NDS::LoadROM(ROMPath[0], SRAMPath[0], Config::DirectBoot);
- }
-
- if (ROMPath[1][0] != '\0')
- {
- SetupSRAMPath(1);
- NDS::LoadGBAROM(ROMPath[1], SRAMPath[1]);
- }
-
- Run();
-
- OSD::AddMessage(0, "Reset");
-}
-
-void Stop(bool internal)
-{
- EmuRunning = 2;
- if (!internal) // if shutting down from the UI thread, wait till the emu thread has stopped
- while (EmuStatus != 2);
- RunningSomething = false;
-
- // eject any inserted GBA cartridge
- GBACart::Eject();
- ROMPath[1][0] = '\0';
-
- uiWindowSetTitle(MainWindow, "melonDS " MELONDS_VERSION);
-
- for (int i = 0; i < 9; i++) uiMenuItemDisable(MenuItem_SaveStateSlot[i]);
- for (int i = 0; i < 9; i++) uiMenuItemDisable(MenuItem_LoadStateSlot[i]);
- uiMenuItemDisable(MenuItem_UndoStateLoad);
-
- uiMenuItemDisable(MenuItem_Pause);
- uiMenuItemDisable(MenuItem_Reset);
- uiMenuItemDisable(MenuItem_Stop);
- uiMenuItemSetChecked(MenuItem_Pause, 0);
-
- uiAreaQueueRedrawAll(MainDrawArea);
-
- SPU::DrainOutput();
- SDL_PauseAudioDevice(AudioDevice, 1);
- SDL_PauseAudioDevice(MicDevice, 1);
-
- OSD::AddMessage(0xFFC040, "Shutdown");
-}
-
-void SetupSRAMPath(int slot)
-{
- strncpy(SRAMPath[slot], ROMPath[slot], 1023);
- SRAMPath[slot][1023] = '\0';
- strncpy(SRAMPath[slot] + strlen(ROMPath[slot]) - 3, "sav", 3);
-}
-
-void TryLoadROM(char* file, int slot, int prevstatus)
-{
- char oldpath[1024];
- char oldsram[1024];
- strncpy(oldpath, ROMPath[slot], 1024);
- strncpy(oldsram, SRAMPath[slot], 1024);
-
- strncpy(ROMPath[slot], file, 1023);
- ROMPath[slot][1023] = '\0';
-
- SetupSRAMPath(0);
- SetupSRAMPath(1);
-
- if (slot == 0 && NDS::LoadROM(ROMPath[slot], SRAMPath[slot], Config::DirectBoot))
- {
- SavestateLoaded = false;
- uiMenuItemDisable(MenuItem_UndoStateLoad);
-
- // Reload the inserted GBA cartridge (if any)
- if (ROMPath[1][0] != '\0') NDS::LoadGBAROM(ROMPath[1], SRAMPath[1]);
-
- strncpy(PrevSRAMPath[slot], SRAMPath[slot], 1024); // safety
- Run();
- }
- else if (slot == 1 && NDS::LoadGBAROM(ROMPath[slot], SRAMPath[slot]))
- {
- SavestateLoaded = false;
- uiMenuItemDisable(MenuItem_UndoStateLoad);
-
- strncpy(PrevSRAMPath[slot], SRAMPath[slot], 1024); // safety
- if (RunningSomething) Run(); // do not start just from a GBA cart
- }
- else
- {
- uiMsgBoxError(MainWindow,
- "Failed to load the ROM",
- "Make sure the file can be accessed and isn't opened in another application.");
-
- strncpy(ROMPath[slot], oldpath, 1024);
- strncpy(SRAMPath[slot], oldsram, 1024);
- EmuRunning = prevstatus;
- }
-}
-
-
-// SAVESTATE TODO
-// * configurable paths. not everyone wants their ROM directory to be polluted, I guess.
-
-void GetSavestateName(int slot, char* filename, int len)
-{
- int pos;
-
- if (ROMPath[0][0] == '\0') // running firmware, no ROM
- {
- strcpy(filename, "firmware");
- pos = 8;
- }
- else
- {
- int l = strlen(ROMPath[0]);
- pos = l;
- while (ROMPath[0][pos] != '.' && pos > 0) pos--;
- if (pos == 0) pos = l;
-
- // avoid buffer overflow. shoddy
- if (pos > len-5) pos = len-5;
-
- strncpy(&filename[0], ROMPath[0], pos);
- }
- strcpy(&filename[pos], ".ml");
- filename[pos+3] = '0'+slot;
- filename[pos+4] = '\0';
-}
-
-void LoadState(int slot)
-{
- int prevstatus = EmuRunning;
- EmuRunning = 2;
- while (EmuStatus != 2);
-
- char filename[1024];
-
- if (slot > 0)
- {
- GetSavestateName(slot, filename, 1024);
- }
- else
- {
- char* file = uiOpenFile(MainWindow, "melonDS savestate (any)|*.ml1;*.ml2;*.ml3;*.ml4;*.ml5;*.ml6;*.ml7;*.ml8;*.mln", Config::LastROMFolder);
- if (!file)
- {
- EmuRunning = prevstatus;
- return;
- }
-
- strncpy(filename, file, 1023);
- filename[1023] = '\0';
- uiFreeText(file);
- }
-
- if (!Platform::FileExists(filename))
- {
- char msg[64];
- if (slot > 0) sprintf(msg, "State slot %d is empty", slot);
- else sprintf(msg, "State file does not exist");
- OSD::AddMessage(0xFFA0A0, msg);
-
- EmuRunning = prevstatus;
- return;
- }
-
- u32 oldGBACartCRC = GBACart::CartCRC;
-
- // backup
- Savestate* backup = new Savestate("timewarp.mln", true);
- NDS::DoSavestate(backup);
- delete backup;
-
- bool failed = false;
-
- Savestate* state = new Savestate(filename, false);
- if (state->Error)
- {
- delete state;
-
- uiMsgBoxError(MainWindow, "Error", "Could not load savestate file.");
-
- // current state might be crapoed, so restore from sane backup
- state = new Savestate("timewarp.mln", false);
- failed = true;
- }
-
- NDS::DoSavestate(state);
- delete state;
-
- if (!failed)
- {
- if (Config::SavestateRelocSRAM && ROMPath[0][0]!='\0')
- {
- strncpy(PrevSRAMPath[0], SRAMPath[0], 1024);
-
- strncpy(SRAMPath[0], filename, 1019);
- int len = strlen(SRAMPath[0]);
- strcpy(&SRAMPath[0][len], ".sav");
- SRAMPath[0][len+4] = '\0';
-
- NDS::RelocateSave(SRAMPath[0], false);
- }
-
- bool loadedPartialGBAROM = false;
-
- // in case we have a GBA cart inserted, and the GBA ROM changes
- // due to having loaded a save state, we do not want to reload
- // the previous cartridge on reset, or commit writes to any
- // loaded save file. therefore, their paths are "nulled".
- if (GBACart::CartInserted && GBACart::CartCRC != oldGBACartCRC)
- {
- ROMPath[1][0] = '\0';
- SRAMPath[1][0] = '\0';
- loadedPartialGBAROM = true;
- }
-
- char msg[64];
- if (slot > 0) sprintf(msg, "State loaded from slot %d%s",
- slot, loadedPartialGBAROM ? " (GBA ROM header only)" : "");
- else sprintf(msg, "State loaded from file%s",
- loadedPartialGBAROM ? " (GBA ROM header only)" : "");
- OSD::AddMessage(0, msg);
-
- SavestateLoaded = true;
- uiMenuItemEnable(MenuItem_UndoStateLoad);
- }
-
- EmuRunning = prevstatus;
-}
-
-void SaveState(int slot)
-{
- int prevstatus = EmuRunning;
- EmuRunning = 2;
- while (EmuStatus != 2);
-
- char filename[1024];
-
- if (slot > 0)
- {
- GetSavestateName(slot, filename, 1024);
- }
- else
- {
- char* file = uiSaveFile(MainWindow, "melonDS savestate (*.mln)|*.mln", Config::LastROMFolder);
- if (!file)
- {
- EmuRunning = prevstatus;
- return;
- }
-
- strncpy(filename, file, 1023);
- filename[1023] = '\0';
- uiFreeText(file);
- }
-
- Savestate* state = new Savestate(filename, true);
- if (state->Error)
- {
- delete state;
-
- uiMsgBoxError(MainWindow, "Error", "Could not save state.");
- }
- else
- {
- NDS::DoSavestate(state);
- delete state;
-
- if (slot > 0)
- uiMenuItemEnable(MenuItem_LoadStateSlot[slot-1]);
-
- if (Config::SavestateRelocSRAM && ROMPath[0][0]!='\0')
- {
- strncpy(SRAMPath[0], filename, 1019);
- int len = strlen(SRAMPath[0]);
- strcpy(&SRAMPath[0][len], ".sav");
- SRAMPath[0][len+4] = '\0';
-
- NDS::RelocateSave(SRAMPath[0], true);
- }
- }
-
- char msg[64];
- if (slot > 0) sprintf(msg, "State saved to slot %d", slot);
- else sprintf(msg, "State saved to file");
- OSD::AddMessage(0, msg);
-
- EmuRunning = prevstatus;
-}
-
-void UndoStateLoad()
-{
- if (!SavestateLoaded) return;
-
- int prevstatus = EmuRunning;
- EmuRunning = 2;
- while (EmuStatus != 2);
-
- // pray that this works
- // what do we do if it doesn't???
- // but it should work.
- Savestate* backup = new Savestate("timewarp.mln", false);
- NDS::DoSavestate(backup);
- delete backup;
-
- if (ROMPath[0][0]!='\0')
- {
- strncpy(SRAMPath[0], PrevSRAMPath[0], 1024);
- NDS::RelocateSave(SRAMPath[0], false);
- }
-
- OSD::AddMessage(0, "State load undone");
-
- EmuRunning = prevstatus;
-}
-
-
-void CloseAllDialogs()
-{
- DlgAudioSettings::Close();
- DlgEmuSettings::Close();
- DlgInputConfig::Close(0);
- DlgInputConfig::Close(1);
- DlgVideoSettings::Close();
- DlgWifiSettings::Close();
-}
-
-
-int OnCloseWindow(uiWindow* window, void* blarg)
-{
- EmuRunning = 3;
- while (EmuStatus != 3);
-
- CloseAllDialogs();
- StopEmuThread();
- uiQuit();
- return 1;
-}
-
-void OnDropFile(uiWindow* window, char* file, void* blarg)
-{
- char* ext = &file[strlen(file)-3];
- int prevstatus = EmuRunning;
-
- if (!strcasecmp(ext, "nds") || !strcasecmp(ext, "srl"))
- {
- if (RunningSomething)
- {
- EmuRunning = 2;
- while (EmuStatus != 2);
- }
-
- TryLoadROM(file, 0, prevstatus);
- }
- else if (!strcasecmp(ext, "gba"))
- {
- TryLoadROM(file, 1, prevstatus);
- }
-}
-
-void OnGetFocus(uiWindow* window, void* blarg)
-{
- uiControlSetFocus(uiControl(MainDrawArea));
-}
-
-void OnLoseFocus(uiWindow* window, void* blarg)
-{
- // TODO: shit here?
-}
-
-void OnCloseByMenu(uiMenuItem* item, uiWindow* window, void* blarg)
-{
- EmuRunning = 3;
- while (EmuStatus != 3);
-
- CloseAllDialogs();
- StopEmuThread();
- DestroyMainWindow();
- uiQuit();
-}
-
-void OnOpenFile(uiMenuItem* item, uiWindow* window, void* blarg)
-{
- int prevstatus = EmuRunning;
- EmuRunning = 2;
- while (EmuStatus != 2);
-
- char* file = uiOpenFile(window, "DS ROM (*.nds)|*.nds;*.srl|GBA ROM (*.gba)|*.gba|Any file|*.*", Config::LastROMFolder);
- if (!file)
- {
- EmuRunning = prevstatus;
- return;
- }
-
- int pos = strlen(file)-1;
- while (file[pos] != '/' && file[pos] != '\\' && pos > 0) pos--;
- strncpy(Config::LastROMFolder, file, pos);
- Config::LastROMFolder[pos] = '\0';
- char* ext = &file[strlen(file)-3];
-
- if (!strcasecmp(ext, "gba"))
- {
- TryLoadROM(file, 1, prevstatus);
- }
- else
- {
- TryLoadROM(file, 0, prevstatus);
- }
-
- uiFreeText(file);
-}
-
-void OnSaveState(uiMenuItem* item, uiWindow* window, void* param)
-{
- int slot = *(int*)param;
- SaveState(slot);
-}
-
-void OnLoadState(uiMenuItem* item, uiWindow* window, void* param)
-{
- int slot = *(int*)param;
- LoadState(slot);
-}
-
-void OnUndoStateLoad(uiMenuItem* item, uiWindow* window, void* param)
-{
- UndoStateLoad();
-}
-
-void OnRun(uiMenuItem* item, uiWindow* window, void* blarg)
-{
- if (!RunningSomething)
- {
- ROMPath[0][0] = '\0';
- NDS::LoadBIOS();
-
- if (ROMPath[1][0] != '\0')
- {
- SetupSRAMPath(1);
- NDS::LoadGBAROM(ROMPath[1], SRAMPath[1]);
- }
- }
-
- Run();
-}
-
-void OnPause(uiMenuItem* item, uiWindow* window, void* blarg)
-{
- TogglePause(NULL);
-}
-
-void OnReset(uiMenuItem* item, uiWindow* window, void* blarg)
-{
- Reset(NULL);
-}
-
-void OnStop(uiMenuItem* item, uiWindow* window, void* blarg)
-{
- if (!RunningSomething) return;
-
- Stop(false);
-}
-
-void OnOpenEmuSettings(uiMenuItem* item, uiWindow* window, void* blarg)
-{
- DlgEmuSettings::Open();
-}
-
-void OnOpenInputConfig(uiMenuItem* item, uiWindow* window, void* blarg)
-{
- DlgInputConfig::Open(0);
-}
-
-void OnOpenHotkeyConfig(uiMenuItem* item, uiWindow* window, void* blarg)
-{
- DlgInputConfig::Open(1);
-}
-
-void OnOpenVideoSettings(uiMenuItem* item, uiWindow* window, void* blarg)
-{
- DlgVideoSettings::Open();
-}
-
-void OnOpenAudioSettings(uiMenuItem* item, uiWindow* window, void* blarg)
-{
- DlgAudioSettings::Open();
-}
-
-void OnOpenWifiSettings(uiMenuItem* item, uiWindow* window, void* blarg)
-{
- DlgWifiSettings::Open();
-}
-
-
-void OnSetSavestateSRAMReloc(uiMenuItem* item, uiWindow* window, void* param)
-{
- Config::SavestateRelocSRAM = uiMenuItemChecked(item) ? 1:0;
-}
-
-
-void EnsureProperMinSize()
-{
- bool isHori = (ScreenRotation == 1 || ScreenRotation == 3);
-
- int w0 = 256;
- int h0 = 192;
- int w1 = 256;
- int h1 = 192;
-
- if (ScreenLayout == 0) // natural
- {
- if (isHori)
- SetMinSize(h0+ScreenGap+h1, std::max(w0,w1));
- else
- SetMinSize(std::max(w0,w1), h0+ScreenGap+h1);
- }
- else if (ScreenLayout == 1) // vertical
- {
- if (isHori)
- SetMinSize(std::max(h0,h1), w0+ScreenGap+w1);
- else
- SetMinSize(std::max(w0,w1), h0+ScreenGap+h1);
- }
- else // horizontal
- {
- if (isHori)
- SetMinSize(h0+ScreenGap+h1, std::max(w0,w1));
- else
- SetMinSize(w0+ScreenGap+w1, std::max(h0,h1));
- }
-}
-
-void OnSetScreenSize(uiMenuItem* item, uiWindow* window, void* param)
-{
- int factor = *(int*)param;
- bool isHori = (ScreenRotation == 1 || ScreenRotation == 3);
-
- int w = 256*factor;
- int h = 192*factor;
-
- // FIXME
-
- if (ScreenLayout == 0) // natural
- {
- if (isHori)
- uiWindowSetContentSize(window, (h*2)+ScreenGap, w);
- else
- uiWindowSetContentSize(window, w, (h*2)+ScreenGap);
- }
- else if (ScreenLayout == 1) // vertical
- {
- if (isHori)
- uiWindowSetContentSize(window, h, (w*2)+ScreenGap);
- else
- uiWindowSetContentSize(window, w, (h*2)+ScreenGap);
- }
- else // horizontal
- {
- if (isHori)
- uiWindowSetContentSize(window, (h*2)+ScreenGap, w);
- else
- uiWindowSetContentSize(window, (w*2)+ScreenGap, h);
- }
-}
-
-void OnSetScreenRotation(uiMenuItem* item, uiWindow* window, void* param)
-{
- int rot = *(int*)param;
-
- int oldrot = ScreenRotation;
- ScreenRotation = rot;
-
- int w, h;
- uiWindowContentSize(window, &w, &h);
-
- bool isHori = (rot == 1 || rot == 3);
- bool wasHori = (oldrot == 1 || oldrot == 3);
-
- EnsureProperMinSize();
-
- if (ScreenLayout == 0) // natural
- {
- if (isHori ^ wasHori)
- {
- int blarg = h;
- h = w;
- w = blarg;
-
- uiWindowSetContentSize(window, w, h);
- }
- }
-
- SetupScreenRects(w, h);
-
- for (int i = 0; i < 4; i++)
- uiMenuItemSetChecked(MenuItem_ScreenRot[i], i==ScreenRotation);
-}
-
-void OnSetScreenGap(uiMenuItem* item, uiWindow* window, void* param)
-{
- int gap = *(int*)param;
-
- //int oldgap = ScreenGap;
- ScreenGap = gap;
-
- EnsureProperMinSize();
- SetupScreenRects(WindowWidth, WindowHeight);
-
- for (int i = 0; i < 6; i++)
- uiMenuItemSetChecked(MenuItem_ScreenGap[i], kScreenGap[i]==ScreenGap);
-}
-
-void OnSetScreenLayout(uiMenuItem* item, uiWindow* window, void* param)
-{
- int layout = *(int*)param;
- ScreenLayout = layout;
-
- EnsureProperMinSize();
- SetupScreenRects(WindowWidth, WindowHeight);
-
- for (int i = 0; i < 3; i++)
- uiMenuItemSetChecked(MenuItem_ScreenLayout[i], i==ScreenLayout);
-}
-
-void OnSetScreenSizing(uiMenuItem* item, uiWindow* window, void* param)
-{
- int sizing = *(int*)param;
- ScreenSizing = sizing;
-
- SetupScreenRects(WindowWidth, WindowHeight);
-
- for (int i = 0; i < 4; i++)
- uiMenuItemSetChecked(MenuItem_ScreenSizing[i], i==ScreenSizing);
-}
-
-void OnSetScreenFiltering(uiMenuItem* item, uiWindow* window, void* blarg)
-{
- int chk = uiMenuItemChecked(item);
- if (chk != 0) Config::ScreenFilter = 1;
- else Config::ScreenFilter = 0;
-}
-
-void OnSetLimitFPS(uiMenuItem* item, uiWindow* window, void* blarg)
-{
- int chk = uiMenuItemChecked(item);
- if (chk != 0) Config::LimitFPS = true;
- else Config::LimitFPS = false;
-}
-
-void OnSetAudioSync(uiMenuItem* item, uiWindow* window, void* blarg)
-{
- int chk = uiMenuItemChecked(item);
- if (chk != 0) Config::AudioSync = true;
- else Config::AudioSync = false;
-}
-
-void OnSetShowOSD(uiMenuItem* item, uiWindow* window, void* blarg)
-{
- int chk = uiMenuItemChecked(item);
- if (chk != 0) Config::ShowOSD = true;
- else Config::ShowOSD = false;
-}
-
-void ApplyNewSettings(int type)
-{
-#ifdef JIT_ENABLED
- if (type == 4)
- {
- Reset(NULL);
- return;
- }
-#endif
-
- if (!RunningSomething)
- {
- if (type == 1) return;
- }
-
- int prevstatus = EmuRunning;
- EmuRunning = 3;
- while (EmuStatus != 3);
-
- if (type == 0) // 3D renderer settings
- {
- if (Screen_UseGL) uiGLMakeContextCurrent(GLContext);
- GPU3D::UpdateRendererConfig();
- if (Screen_UseGL) uiGLMakeContextCurrent(NULL);
-
- GL_3DScale = Config::GL_ScaleFactor; // dorp
- GL_ScreenSizeDirty = true;
- }
- else if (type == 1) // wifi settings
- {
- if (Wifi::MPInited)
- {
- Platform::MP_DeInit();
- Platform::MP_Init();
- }
-
- Platform::LAN_DeInit();
- Platform::LAN_Init();
- }
- else if (type == 2) // video output method
- {
- bool usegl = Config::ScreenUseGL || (Config::_3DRenderer != 0);
- if (usegl != Screen_UseGL)
- {
- if (Screen_UseGL) uiGLMakeContextCurrent(GLContext);
- GPU3D::DeInitRenderer();
- OSD::DeInit(Screen_UseGL);
- if (Screen_UseGL) uiGLMakeContextCurrent(NULL);
-
- Screen_UseGL = usegl;
- RecreateMainWindow(usegl);
-
- if (Screen_UseGL) uiGLMakeContextCurrent(GLContext);
- GPU3D::InitRenderer(Screen_UseGL);
- if (Screen_UseGL) uiGLMakeContextCurrent(NULL);
- }
- }
- else if (type == 3) // 3D renderer
- {
- if (Screen_UseGL) uiGLMakeContextCurrent(GLContext);
- GPU3D::DeInitRenderer();
- GPU3D::InitRenderer(Screen_UseGL);
- if (Screen_UseGL) uiGLMakeContextCurrent(NULL);
- }
- EmuRunning = prevstatus;
-}
-
-
-void CreateMainWindowMenu()
-{
- uiMenu* menu;
- uiMenuItem* menuitem;
-
- menu = uiNewMenu("File");
- menuitem = uiMenuAppendItem(menu, "Open ROM...");
- uiMenuItemOnClicked(menuitem, OnOpenFile, NULL);
- uiMenuAppendSeparator(menu);
- {
- uiMenu* submenu = uiNewMenu("Save state");
-
- for (int i = 0; i < 9; i++)
- {
- char name[32];
- if (i < 8)
- sprintf(name, "%d\tShift+F%d", kSavestateNum[i], kSavestateNum[i]);
- else
- strcpy(name, "File...\tShift+F9");
-
- uiMenuItem* ssitem = uiMenuAppendItem(submenu, name);
- uiMenuItemOnClicked(ssitem, OnSaveState, (void*)&kSavestateNum[i]);
-
- MenuItem_SaveStateSlot[i] = ssitem;
- }
-
- MenuItem_SaveState = uiMenuAppendSubmenu(menu, submenu);
- }
- {
- uiMenu* submenu = uiNewMenu("Load state");
-
- for (int i = 0; i < 9; i++)
- {
- char name[32];
- if (i < 8)
- sprintf(name, "%d\tF%d", kSavestateNum[i], kSavestateNum[i]);
- else
- strcpy(name, "File...\tF9");
-
- uiMenuItem* ssitem = uiMenuAppendItem(submenu, name);
- uiMenuItemOnClicked(ssitem, OnLoadState, (void*)&kSavestateNum[i]);
-
- MenuItem_LoadStateSlot[i] = ssitem;
- }
-
- MenuItem_LoadState = uiMenuAppendSubmenu(menu, submenu);
- }
- menuitem = uiMenuAppendItem(menu, "Undo state load\tF12");
- uiMenuItemOnClicked(menuitem, OnUndoStateLoad, NULL);
- MenuItem_UndoStateLoad = menuitem;
- uiMenuAppendSeparator(menu);
- menuitem = uiMenuAppendItem(menu, "Quit");
- uiMenuItemOnClicked(menuitem, OnCloseByMenu, NULL);
-
- menu = uiNewMenu("System");
- menuitem = uiMenuAppendItem(menu, "Run");
- uiMenuItemOnClicked(menuitem, OnRun, NULL);
- menuitem = uiMenuAppendCheckItem(menu, "Pause");
- uiMenuItemOnClicked(menuitem, OnPause, NULL);
- MenuItem_Pause = menuitem;
- uiMenuAppendSeparator(menu);
- menuitem = uiMenuAppendItem(menu, "Reset");
- uiMenuItemOnClicked(menuitem, OnReset, NULL);
- MenuItem_Reset = menuitem;
- menuitem = uiMenuAppendItem(menu, "Stop");
- uiMenuItemOnClicked(menuitem, OnStop, NULL);
- MenuItem_Stop = menuitem;
-
- menu = uiNewMenu("Config");
- {
- menuitem = uiMenuAppendItem(menu, "Emu settings");
- uiMenuItemOnClicked(menuitem, OnOpenEmuSettings, NULL);
- menuitem = uiMenuAppendItem(menu, "Input config");
- uiMenuItemOnClicked(menuitem, OnOpenInputConfig, NULL);
- menuitem = uiMenuAppendItem(menu, "Hotkey config");
- uiMenuItemOnClicked(menuitem, OnOpenHotkeyConfig, NULL);
- menuitem = uiMenuAppendItem(menu, "Video settings");
- uiMenuItemOnClicked(menuitem, OnOpenVideoSettings, NULL);
- menuitem = uiMenuAppendItem(menu, "Audio settings");
- uiMenuItemOnClicked(menuitem, OnOpenAudioSettings, NULL);
- menuitem = uiMenuAppendItem(menu, "Wifi settings");
- uiMenuItemOnClicked(menuitem, OnOpenWifiSettings, NULL);
- }
- uiMenuAppendSeparator(menu);
- {
- uiMenu* submenu = uiNewMenu("Savestate settings");
-
- MenuItem_SavestateSRAMReloc = uiMenuAppendCheckItem(submenu, "Separate savefiles");
- uiMenuItemOnClicked(MenuItem_SavestateSRAMReloc, OnSetSavestateSRAMReloc, NULL);
-
- uiMenuAppendSubmenu(menu, submenu);
- }
- uiMenuAppendSeparator(menu);
- {
- uiMenu* submenu = uiNewMenu("Screen size");
-
- for (int i = 0; i < 4; i++)
- {
- char name[32];
- sprintf(name, "%dx", kScreenSize[i]);
- uiMenuItem* item = uiMenuAppendItem(submenu, name);
- uiMenuItemOnClicked(item, OnSetScreenSize, (void*)&kScreenSize[i]);
- }
-
- uiMenuAppendSubmenu(menu, submenu);
- }
- {
- uiMenu* submenu = uiNewMenu("Screen rotation");
-
- for (int i = 0; i < 4; i++)
- {
- char name[32];
- sprintf(name, "%d", kScreenRot[i]*90);
- MenuItem_ScreenRot[i] = uiMenuAppendCheckItem(submenu, name);
- uiMenuItemOnClicked(MenuItem_ScreenRot[i], OnSetScreenRotation, (void*)&kScreenRot[i]);
- }
-
- uiMenuAppendSubmenu(menu, submenu);
- }
- {
- uiMenu* submenu = uiNewMenu("Mid-screen gap");
-
- //for (int i = 0; kScreenGap[i] != -1; i++)
- for (int i = 0; i < 6; i++)
- {
- char name[32];
- sprintf(name, "%d pixels", kScreenGap[i]);
- MenuItem_ScreenGap[i] = uiMenuAppendCheckItem(submenu, name);
- uiMenuItemOnClicked(MenuItem_ScreenGap[i], OnSetScreenGap, (void*)&kScreenGap[i]);
- }
-
- uiMenuAppendSubmenu(menu, submenu);
- }
- {
- uiMenu* submenu = uiNewMenu("Screen layout");
-
- MenuItem_ScreenLayout[0] = uiMenuAppendCheckItem(submenu, "Natural");
- uiMenuItemOnClicked(MenuItem_ScreenLayout[0], OnSetScreenLayout, (void*)&kScreenLayout[0]);
- MenuItem_ScreenLayout[1] = uiMenuAppendCheckItem(submenu, "Vertical");
- uiMenuItemOnClicked(MenuItem_ScreenLayout[1], OnSetScreenLayout, (void*)&kScreenLayout[1]);
- MenuItem_ScreenLayout[2] = uiMenuAppendCheckItem(submenu, "Horizontal");
- uiMenuItemOnClicked(MenuItem_ScreenLayout[2], OnSetScreenLayout, (void*)&kScreenLayout[2]);
-
- uiMenuAppendSubmenu(menu, submenu);
- }
- {
- uiMenu* submenu = uiNewMenu("Screen sizing");
-
- MenuItem_ScreenSizing[0] = uiMenuAppendCheckItem(submenu, "Even");
- uiMenuItemOnClicked(MenuItem_ScreenSizing[0], OnSetScreenSizing, (void*)&kScreenSizing[0]);
- MenuItem_ScreenSizing[1] = uiMenuAppendCheckItem(submenu, "Emphasize top");
- uiMenuItemOnClicked(MenuItem_ScreenSizing[1], OnSetScreenSizing, (void*)&kScreenSizing[1]);
- MenuItem_ScreenSizing[2] = uiMenuAppendCheckItem(submenu, "Emphasize bottom");
- uiMenuItemOnClicked(MenuItem_ScreenSizing[2], OnSetScreenSizing, (void*)&kScreenSizing[2]);
- MenuItem_ScreenSizing[3] = uiMenuAppendCheckItem(submenu, "Auto");
- uiMenuItemOnClicked(MenuItem_ScreenSizing[3], OnSetScreenSizing, (void*)&kScreenSizing[3]);
-
- uiMenuAppendSubmenu(menu, submenu);
- }
-
- MenuItem_ScreenFilter = uiMenuAppendCheckItem(menu, "Screen filtering");
- uiMenuItemOnClicked(MenuItem_ScreenFilter, OnSetScreenFiltering, NULL);
-
- MenuItem_ShowOSD = uiMenuAppendCheckItem(menu, "Show OSD");
- uiMenuItemOnClicked(MenuItem_ShowOSD, OnSetShowOSD, NULL);
-
- uiMenuAppendSeparator(menu);
-
- MenuItem_LimitFPS = uiMenuAppendCheckItem(menu, "Limit framerate");
- uiMenuItemOnClicked(MenuItem_LimitFPS, OnSetLimitFPS, NULL);
-
- MenuItem_AudioSync = uiMenuAppendCheckItem(menu, "Audio sync");
- uiMenuItemOnClicked(MenuItem_AudioSync, OnSetAudioSync, NULL);
-}
-
-void CreateMainWindow(bool opengl)
-{
- MainWindow = uiNewWindow("melonDS " MELONDS_VERSION,
- WindowWidth, WindowHeight,
- Config::WindowMaximized, 1, 1);
- uiWindowOnClosing(MainWindow, OnCloseWindow, NULL);
-
- uiWindowSetDropTarget(MainWindow, 1);
- uiWindowOnDropFile(MainWindow, OnDropFile, NULL);
-
- uiWindowOnGetFocus(MainWindow, OnGetFocus, NULL);
- uiWindowOnLoseFocus(MainWindow, OnLoseFocus, NULL);
-
- ScreenDrawInited = false;
- bool opengl_good = opengl;
-
- if (!opengl) MainDrawArea = uiNewArea(&MainDrawAreaHandler);
- else MainDrawArea = uiNewGLArea(&MainDrawAreaHandler, kGLVersions);
-
- uiWindowSetChild(MainWindow, uiControl(MainDrawArea));
- uiControlSetMinSize(uiControl(MainDrawArea), 256, 384);
- uiAreaSetBackgroundColor(MainDrawArea, 0, 0, 0);
-
- uiControlShow(uiControl(MainWindow));
- uiControlSetFocus(uiControl(MainDrawArea));
-
- if (opengl_good)
- {
- GLContext = uiAreaGetGLContext(MainDrawArea);
- if (!GLContext) opengl_good = false;
- }
- if (opengl_good)
- {
- uiGLMakeContextCurrent(GLContext);
- uiGLSetVSync(Config::ScreenVSync);
- if (!GLScreen_Init()) opengl_good = false;
- if (opengl_good)
- {
- OpenGL_UseShaderProgram(GL_ScreenShaderOSD);
- OSD::Init(true);
- }
- uiGLMakeContextCurrent(NULL);
- }
-
- if (opengl && !opengl_good)
- {
- printf("OpenGL: initialization failed\n");
- RecreateMainWindow(false);
- Screen_UseGL = false;
- }
-
- if (!opengl) OSD::Init(false);
-}
-
-void DestroyMainWindow()
-{
- uiControlDestroy(uiControl(MainWindow));
-
- if (ScreenBitmap[0]) uiDrawFreeBitmap(ScreenBitmap[0]);
- if (ScreenBitmap[1]) uiDrawFreeBitmap(ScreenBitmap[1]);
-
- ScreenBitmap[0] = NULL;
- ScreenBitmap[1] = NULL;
-}
-
-void RecreateMainWindow(bool opengl)
-{
- int winX, winY, maxi;
- uiWindowPosition(MainWindow, &winX, &winY);
- maxi = uiWindowMaximized(MainWindow);
- DestroyMainWindow();
- CreateMainWindow(opengl);
- uiWindowSetPosition(MainWindow, winX, winY);
- uiWindowSetMaximized(MainWindow, maxi);
-}
-
-
-int main(int argc, char** argv)
-{
- srand(time(NULL));
-
- printf("melonDS " MELONDS_VERSION "\n");
- printf(MELONDS_URL "\n");
-
-#if defined(__WIN32__) || defined(UNIX_PORTABLE)
- if (argc > 0 && strlen(argv[0]) > 0)
- {
- int len = strlen(argv[0]);
- while (len > 0)
- {
- if (argv[0][len] == '/') break;
- if (argv[0][len] == '\\') break;
- len--;
- }
- if (len > 0)
- {
- EmuDirectory = new char[len+1];
- strncpy(EmuDirectory, argv[0], len);
- EmuDirectory[len] = '\0';
- }
- else
- {
- EmuDirectory = new char[2];
- strcpy(EmuDirectory, ".");
- }
- }
- else
- {
- EmuDirectory = new char[2];
- strcpy(EmuDirectory, ".");
- }
-#else
- const char* confdir = g_get_user_config_dir();
- const char* confname = "/melonDS";
- EmuDirectory = new char[strlen(confdir) + strlen(confname) + 1];
- strcat(EmuDirectory, confdir);
- strcat(EmuDirectory, confname);
-#endif
-
- // http://stackoverflow.com/questions/14543333/joystick-wont-work-using-sdl
- SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1");
-
- if (SDL_Init(SDL_INIT_HAPTIC) < 0)
- {
- printf("SDL couldn't init rumble\n");
- }
- if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0)
- {
- printf("SDL shat itself :(\n");
- return 1;
- }
-
- SDL_JoystickEventState(SDL_ENABLE);
-
- uiInitOptions ui_opt;
- memset(&ui_opt, 0, sizeof(uiInitOptions));
- const char* ui_err = uiInit(&ui_opt);
- if (ui_err != NULL)
- {
- printf("libui shat itself :( %s\n", ui_err);
- uiFreeInitError(ui_err);
- return 1;
- }
-
- Config::Load();
-
- if (Config::AudioVolume < 0) Config::AudioVolume = 0;
- else if (Config::AudioVolume > 256) Config::AudioVolume = 256;
-
- if (!Platform::LocalFileExists("bios7.bin") ||
- !Platform::LocalFileExists("bios9.bin") ||
- !Platform::LocalFileExists("firmware.bin"))
- {
-#if defined(__WIN32__) || defined(UNIX_PORTABLE)
- const char* locationName = "the directory you run melonDS from";
-#else
- char* locationName = EmuDirectory;
-#endif
- char msgboxtext[512];
- sprintf(msgboxtext,
- "One or more of the following required files don't exist or couldn't be accessed:\n\n"
- "bios7.bin -- ARM7 BIOS\n"
- "bios9.bin -- ARM9 BIOS\n"
- "firmware.bin -- firmware image\n\n"
- "Dump the files from your DS and place them in %s.\n"
- "Make sure that the files can be accessed.",
- locationName
- );
-
- uiMsgBoxError(NULL, "BIOS/Firmware not found", msgboxtext);
-
- uiUninit();
- SDL_Quit();
- return 0;
- }
- if (!Platform::LocalFileExists("firmware.bin.bak"))
- {
- // verify the firmware
- //
- // there are dumps of an old hacked firmware floating around on the internet
- // and those are problematic
- // the hack predates WFC, and, due to this, any game that alters the WFC
- // access point data will brick that firmware due to it having critical
- // data in the same area. it has the same problem on hardware.
- //
- // but this should help stop users from reporting that issue over and over
- // again, when the issue is not from melonDS but from their firmware dump.
- //
- // I don't know about all the firmware hacks in existence, but the one I
- // looked at has 0x180 bytes from the header repeated at 0x3FC80, but
- // bytes 0x0C-0x14 are different.
-
- FILE* f = Platform::OpenLocalFile("firmware.bin", "rb");
- u8 chk1[0x180], chk2[0x180];
-
- fseek(f, 0, SEEK_SET);
- fread(chk1, 1, 0x180, f);
- fseek(f, -0x380, SEEK_END);
- fread(chk2, 1, 0x180, f);
-
- memset(&chk1[0x0C], 0, 8);
- memset(&chk2[0x0C], 0, 8);
-
- fclose(f);
-
- if (!memcmp(chk1, chk2, 0x180))
- {
- uiMsgBoxError(NULL,
- "Problematic firmware dump",
- "You are using an old hacked firmware dump.\n"
- "Firmware boot will stop working if you run any game that alters WFC settings.\n\n"
- "Note that the issue is not from melonDS, it would also happen on an actual DS.");
- }
- }
- {
- const char* romlist_missing = "Save memory type detection will not work correctly.\n\n"
- "You should use the latest version of romlist.bin (provided in melonDS release packages).";
-#if !defined(UNIX_PORTABLE) && !defined(__WIN32__)
- std::string missingstr = std::string(romlist_missing) +
- "\n\nThe ROM list should be placed in " + g_get_user_data_dir() + "/melonds/, otherwise "
- "melonDS will search for it in the current working directory.";
- const char* romlist_missing_text = missingstr.c_str();
-#else
- const char* romlist_missing_text = romlist_missing;
-#endif
-
- FILE* f = Platform::OpenDataFile("romlist.bin");
- if (f)
- {
- u32 data;
- fread(&data, 4, 1, f);
- fclose(f);
-
- if ((data >> 24) == 0) // old CRC-based list
- {
- uiMsgBoxError(NULL, "Your version of romlist.bin is outdated.", romlist_missing_text);
- }
- }
- else
- {
- uiMsgBoxError(NULL, "romlist.bin not found.", romlist_missing_text);
- }
- }
-
- CreateMainWindowMenu();
-
- MainDrawAreaHandler.Draw = OnAreaDraw;
- MainDrawAreaHandler.MouseEvent = OnAreaMouseEvent;
- MainDrawAreaHandler.MouseCrossed = OnAreaMouseCrossed;
- MainDrawAreaHandler.DragBroken = OnAreaDragBroken;
- MainDrawAreaHandler.KeyEvent = OnAreaKeyEvent;
- MainDrawAreaHandler.Resize = OnAreaResize;
-
- WindowWidth = Config::WindowWidth;
- WindowHeight = Config::WindowHeight;
-
- Screen_UseGL = Config::ScreenUseGL || (Config::_3DRenderer != 0);
-
- GL_3DScale = Config::GL_ScaleFactor;
- if (GL_3DScale < 1) GL_3DScale = 1;
- else if (GL_3DScale > 8) GL_3DScale = 8;
-
- CreateMainWindow(Screen_UseGL);
-
- ScreenRotation = Config::ScreenRotation;
- ScreenGap = Config::ScreenGap;
- ScreenLayout = Config::ScreenLayout;
- ScreenSizing = Config::ScreenSizing;
-
-#define SANITIZE(var, min, max) if ((var < min) || (var > max)) var = 0;
- SANITIZE(ScreenRotation, 0, 3);
- SANITIZE(ScreenLayout, 0, 2);
- SANITIZE(ScreenSizing, 0, 3);
-#undef SANITIZE
-
- for (int i = 0; i < 9; i++) uiMenuItemDisable(MenuItem_SaveStateSlot[i]);
- for (int i = 0; i < 9; i++) uiMenuItemDisable(MenuItem_LoadStateSlot[i]);
- uiMenuItemDisable(MenuItem_UndoStateLoad);
-
- uiMenuItemDisable(MenuItem_Pause);
- uiMenuItemDisable(MenuItem_Reset);
- uiMenuItemDisable(MenuItem_Stop);
-
- uiMenuItemSetChecked(MenuItem_SavestateSRAMReloc, Config::SavestateRelocSRAM?1:0);
-
- uiMenuItemSetChecked(MenuItem_ScreenRot[ScreenRotation], 1);
- uiMenuItemSetChecked(MenuItem_ScreenLayout[ScreenLayout], 1);
- uiMenuItemSetChecked(MenuItem_ScreenSizing[ScreenSizing], 1);
-
- for (int i = 0; i < 6; i++)
- {
- if (ScreenGap == kScreenGap[i])
- uiMenuItemSetChecked(MenuItem_ScreenGap[i], 1);
- }
-
- OnSetScreenRotation(MenuItem_ScreenRot[ScreenRotation], MainWindow, (void*)&kScreenRot[ScreenRotation]);
-
- uiMenuItemSetChecked(MenuItem_ScreenFilter, Config::ScreenFilter==1);
- uiMenuItemSetChecked(MenuItem_LimitFPS, Config::LimitFPS==1);
- uiMenuItemSetChecked(MenuItem_AudioSync, Config::AudioSync==1);
- uiMenuItemSetChecked(MenuItem_ShowOSD, Config::ShowOSD==1);
-
-#ifdef MELONCAP
- MelonCap::Init();
-#endif // MELONCAP
-
- AudioSync = SDL_CreateCond();
- AudioSyncLock = SDL_CreateMutex();
-
- AudioFreq = 48000; // TODO: make configurable?
- SDL_AudioSpec whatIwant, whatIget;
- memset(&whatIwant, 0, sizeof(SDL_AudioSpec));
- whatIwant.freq = AudioFreq;
- whatIwant.format = AUDIO_S16LSB;
- whatIwant.channels = 2;
- whatIwant.samples = 1024;
- whatIwant.callback = AudioCallback;
- AudioDevice = SDL_OpenAudioDevice(NULL, 0, &whatIwant, &whatIget, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
- if (!AudioDevice)
- {
- printf("Audio init failed: %s\n", SDL_GetError());
- }
- else
- {
- AudioFreq = whatIget.freq;
- printf("Audio output frequency: %d Hz\n", AudioFreq);
- SDL_PauseAudioDevice(AudioDevice, 1);
- }
-
- memset(&whatIwant, 0, sizeof(SDL_AudioSpec));
- whatIwant.freq = 44100;
- whatIwant.format = AUDIO_S16LSB;
- whatIwant.channels = 1;
- whatIwant.samples = 1024;
- whatIwant.callback = MicCallback;
- MicDevice = SDL_OpenAudioDevice(NULL, 1, &whatIwant, &whatIget, 0);
- if (!MicDevice)
- {
- printf("Mic init failed: %s\n", SDL_GetError());
- MicBufferLength = 0;
- }
- else
- {
- SDL_PauseAudioDevice(MicDevice, 1);
- }
-
- memset(MicBuffer, 0, sizeof(MicBuffer));
- MicBufferReadPos = 0;
- MicBufferWritePos = 0;
-
- MicWavBuffer = NULL;
- if (Config::MicInputType == 3) MicLoadWav(Config::MicWavPath);
-
- JoystickID = Config::JoystickID;
- Joystick = NULL;
- OpenJoystick();
-
- EmuRunning = 2;
- RunningSomething = false;
- EmuThread = SDL_CreateThread(EmuThreadFunc, "melonDS magic", NULL);
-
- if (argc > 1)
- {
- char* file = argv[1];
- char* ext = &file[strlen(file)-3];
-
- if (!strcasecmp(ext, "nds") || !strcasecmp(ext, "srl"))
- {
- strncpy(ROMPath[0], file, 1023);
- ROMPath[0][1023] = '\0';
-
- SetupSRAMPath(0);
-
- if (NDS::LoadROM(ROMPath[0], SRAMPath[0], Config::DirectBoot))
- Run();
- }
-
- if (argc > 2)
- {
- file = argv[2];
- ext = &file[strlen(file)-3];
-
- if (!strcasecmp(ext, "gba"))
- {
- strncpy(ROMPath[1], file, 1023);
- ROMPath[1][1023] = '\0';
-
- SetupSRAMPath(1);
-
- NDS::LoadGBAROM(ROMPath[1], SRAMPath[1]);
- }
- }
- }
-
- uiMain();
-
- if (Joystick) SDL_JoystickClose(Joystick);
- if (AudioDevice) SDL_CloseAudioDevice(AudioDevice);
- if (MicDevice) SDL_CloseAudioDevice(MicDevice);
-
- SDL_DestroyCond(AudioSync);
- SDL_DestroyMutex(AudioSyncLock);
-
- if (MicWavBuffer) delete[] MicWavBuffer;
-
-#ifdef MELONCAP
- MelonCap::DeInit();
-#endif // MELONCAP
-
- if (ScreenBitmap[0]) uiDrawFreeBitmap(ScreenBitmap[0]);
- if (ScreenBitmap[1]) uiDrawFreeBitmap(ScreenBitmap[1]);
-
- Config::ScreenRotation = ScreenRotation;
- Config::ScreenGap = ScreenGap;
- Config::ScreenLayout = ScreenLayout;
- Config::ScreenSizing = ScreenSizing;
-
- Config::Save();
-
- uiUninit();
- SDL_Quit();
- delete[] EmuDirectory;
- return 0;
-}
-
-#ifdef __WIN32__
-
-#include <windows.h>
-
-int CALLBACK WinMain(HINSTANCE hinst, HINSTANCE hprev, LPSTR cmdline, int cmdshow)
-{
- int argc = 0;
- wchar_t** argv_w = CommandLineToArgvW(GetCommandLineW(), &argc);
- char* nullarg = "";
-
- char** argv = new char*[argc];
- for (int i = 0; i < argc; i++)
- {
- int len = WideCharToMultiByte(CP_UTF8, 0, argv_w[i], -1, NULL, 0, NULL, NULL);
- if (len < 1) return NULL;
- argv[i] = new char[len];
- int res = WideCharToMultiByte(CP_UTF8, 0, argv_w[i], -1, argv[i], len, NULL, NULL);
- if (res != len) { delete[] argv[i]; argv[i] = nullarg; }
- }
-
- if (AttachConsole(ATTACH_PARENT_PROCESS))
- {
- freopen("CONOUT$", "w", stdout);
- freopen("CONOUT$", "w", stderr);
- printf("\n");
- }
-
- int ret = main(argc, argv);
-
- printf("\n\n>");
-
- for (int i = 0; i < argc; i++) if (argv[i] != nullarg) delete[] argv[i];
- delete[] argv;
-
- return ret;
-}
-
-#endif