reconcile DSi and JIT, fastmem for x64 and Windows
This commit is contained in:
parent
ea6d03581b
commit
c5381d2911
23
src/ARM.cpp
23
src/ARM.cpp
|
@ -21,12 +21,15 @@
|
||||||
#include "DSi.h"
|
#include "DSi.h"
|
||||||
#include "ARM.h"
|
#include "ARM.h"
|
||||||
#include "ARMInterpreter.h"
|
#include "ARMInterpreter.h"
|
||||||
#include "ARMJIT.h"
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "AREngine.h"
|
#include "AREngine.h"
|
||||||
#include "ARMJIT.h"
|
#include "ARMJIT.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
|
#ifdef JIT_ENABLED
|
||||||
|
#include "ARMJIT.h"
|
||||||
|
#include "ARMJIT_Memory.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
// instruction timing notes
|
// instruction timing notes
|
||||||
//
|
//
|
||||||
|
@ -109,6 +112,12 @@ void ARM::Reset()
|
||||||
|
|
||||||
CodeMem.Mem = NULL;
|
CodeMem.Mem = NULL;
|
||||||
|
|
||||||
|
#ifdef JIT_ENABLED
|
||||||
|
FastBlockLookup = NULL;
|
||||||
|
FastBlockLookupStart = 0;
|
||||||
|
FastBlockLookupSize = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
// zorp
|
// zorp
|
||||||
JumpTo(ExceptionBase);
|
JumpTo(ExceptionBase);
|
||||||
}
|
}
|
||||||
|
@ -752,6 +761,12 @@ void ARMv4::Execute()
|
||||||
|
|
||||||
if (Halted == 2)
|
if (Halted == 2)
|
||||||
Halted = 0;
|
Halted = 0;
|
||||||
|
|
||||||
|
if (Halted == 4)
|
||||||
|
{
|
||||||
|
DSi::SoftReset();
|
||||||
|
Halted = 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef JIT_ENABLED
|
#ifdef JIT_ENABLED
|
||||||
|
@ -820,6 +835,12 @@ void ARMv4::ExecuteJIT()
|
||||||
|
|
||||||
if (Halted == 2)
|
if (Halted == 2)
|
||||||
Halted = 0;
|
Halted = 0;
|
||||||
|
|
||||||
|
if (Halted == 4)
|
||||||
|
{
|
||||||
|
DSi::SoftReset();
|
||||||
|
Halted = 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -147,7 +147,7 @@ public:
|
||||||
NDS::MemRegion CodeMem;
|
NDS::MemRegion CodeMem;
|
||||||
|
|
||||||
#ifdef JIT_ENABLED
|
#ifdef JIT_ENABLED
|
||||||
u32 FastBlockLookupStart = 0, FastBlockLookupSize = 0;
|
u32 FastBlockLookupStart, FastBlockLookupSize;
|
||||||
u64* FastBlockLookup;
|
u64* FastBlockLookup;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
271
src/ARMJIT.cpp
271
src/ARMJIT.cpp
|
@ -18,6 +18,7 @@
|
||||||
#include "ARMInterpreter_Branch.h"
|
#include "ARMInterpreter_Branch.h"
|
||||||
#include "ARMInterpreter.h"
|
#include "ARMInterpreter.h"
|
||||||
|
|
||||||
|
#include "DSi.h"
|
||||||
#include "GPU.h"
|
#include "GPU.h"
|
||||||
#include "GPU3D.h"
|
#include "GPU3D.h"
|
||||||
#include "SPU.h"
|
#include "SPU.h"
|
||||||
|
@ -38,25 +39,35 @@ namespace ARMJIT
|
||||||
Compiler* JITCompiler;
|
Compiler* JITCompiler;
|
||||||
|
|
||||||
AddressRange CodeIndexITCM[ITCMPhysicalSize / 512];
|
AddressRange CodeIndexITCM[ITCMPhysicalSize / 512];
|
||||||
AddressRange CodeIndexMainRAM[NDS::MainRAMSize / 512];
|
AddressRange CodeIndexMainRAM[NDS::MainRAMMaxSize / 512];
|
||||||
AddressRange CodeIndexSWRAM[NDS::SharedWRAMSize / 512];
|
AddressRange CodeIndexSWRAM[NDS::SharedWRAMSize / 512];
|
||||||
AddressRange CodeIndexVRAM[0x100000 / 512];
|
AddressRange CodeIndexVRAM[0x100000 / 512];
|
||||||
AddressRange CodeIndexARM9BIOS[sizeof(NDS::ARM9BIOS) / 512];
|
AddressRange CodeIndexARM9BIOS[sizeof(NDS::ARM9BIOS) / 512];
|
||||||
AddressRange CodeIndexARM7BIOS[sizeof(NDS::ARM7BIOS) / 512];
|
AddressRange CodeIndexARM7BIOS[sizeof(NDS::ARM7BIOS) / 512];
|
||||||
AddressRange CodeIndexARM7WRAM[NDS::ARM7WRAMSize / 512];
|
AddressRange CodeIndexARM7WRAM[NDS::ARM7WRAMSize / 512];
|
||||||
AddressRange CodeIndexARM7WVRAM[0x40000 / 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*> JitBlocks9;
|
||||||
std::unordered_map<u32, JitBlock*> JitBlocks7;
|
std::unordered_map<u32, JitBlock*> JitBlocks7;
|
||||||
|
|
||||||
u64 FastBlockLookupITCM[ITCMPhysicalSize / 2];
|
u64 FastBlockLookupITCM[ITCMPhysicalSize / 2];
|
||||||
u64 FastBlockLookupMainRAM[NDS::MainRAMSize / 2];
|
u64 FastBlockLookupMainRAM[NDS::MainRAMMaxSize / 2];
|
||||||
u64 FastBlockLookupSWRAM[NDS::SharedWRAMSize / 2];
|
u64 FastBlockLookupSWRAM[NDS::SharedWRAMSize / 2];
|
||||||
u64 FastBlockLookupVRAM[0x100000 / 2];
|
u64 FastBlockLookupVRAM[0x100000 / 2];
|
||||||
u64 FastBlockLookupARM9BIOS[sizeof(NDS::ARM9BIOS) / 2];
|
u64 FastBlockLookupARM9BIOS[sizeof(NDS::ARM9BIOS) / 2];
|
||||||
u64 FastBlockLookupARM7BIOS[sizeof(NDS::ARM7BIOS) / 2];
|
u64 FastBlockLookupARM7BIOS[sizeof(NDS::ARM7BIOS) / 2];
|
||||||
u64 FastBlockLookupARM7WRAM[NDS::ARM7WRAMSize / 2];
|
u64 FastBlockLookupARM7WRAM[NDS::ARM7WRAMSize / 2];
|
||||||
u64 FastBlockLookupARM7WVRAM[0x40000 / 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] =
|
const u32 CodeRegionSizes[ARMJIT_Memory::memregions_Count] =
|
||||||
{
|
{
|
||||||
|
@ -64,7 +75,7 @@ const u32 CodeRegionSizes[ARMJIT_Memory::memregions_Count] =
|
||||||
ITCMPhysicalSize,
|
ITCMPhysicalSize,
|
||||||
0,
|
0,
|
||||||
sizeof(NDS::ARM9BIOS),
|
sizeof(NDS::ARM9BIOS),
|
||||||
NDS::MainRAMSize,
|
NDS::MainRAMMaxSize,
|
||||||
NDS::SharedWRAMSize,
|
NDS::SharedWRAMSize,
|
||||||
0,
|
0,
|
||||||
0x100000,
|
0x100000,
|
||||||
|
@ -73,6 +84,11 @@ const u32 CodeRegionSizes[ARMJIT_Memory::memregions_Count] =
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0x40000,
|
0x40000,
|
||||||
|
0x10000,
|
||||||
|
0x10000,
|
||||||
|
sizeof(DSi::NWRAM_A),
|
||||||
|
sizeof(DSi::NWRAM_B),
|
||||||
|
sizeof(DSi::NWRAM_C),
|
||||||
};
|
};
|
||||||
|
|
||||||
AddressRange* const CodeMemRegions[ARMJIT_Memory::memregions_Count] =
|
AddressRange* const CodeMemRegions[ARMJIT_Memory::memregions_Count] =
|
||||||
|
@ -90,6 +106,11 @@ AddressRange* const CodeMemRegions[ARMJIT_Memory::memregions_Count] =
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
CodeIndexARM7WVRAM,
|
CodeIndexARM7WVRAM,
|
||||||
|
CodeIndexBIOS9DSi,
|
||||||
|
CodeIndexBIOS7DSi,
|
||||||
|
CodeIndexNWRAM_A,
|
||||||
|
CodeIndexNWRAM_B,
|
||||||
|
CodeIndexNWRAM_C
|
||||||
};
|
};
|
||||||
|
|
||||||
u64* const FastBlockLookupRegions[ARMJIT_Memory::memregions_Count] =
|
u64* const FastBlockLookupRegions[ARMJIT_Memory::memregions_Count] =
|
||||||
|
@ -106,7 +127,12 @@ u64* const FastBlockLookupRegions[ARMJIT_Memory::memregions_Count] =
|
||||||
FastBlockLookupARM7WRAM,
|
FastBlockLookupARM7WRAM,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
FastBlockLookupARM7WVRAM
|
FastBlockLookupARM7WVRAM,
|
||||||
|
FastBlockLookupBIOS9DSi,
|
||||||
|
FastBlockLookupBIOS7DSi,
|
||||||
|
FastBlockLookupNWRAM_A,
|
||||||
|
FastBlockLookupNWRAM_B,
|
||||||
|
FastBlockLookupNWRAM_C
|
||||||
};
|
};
|
||||||
|
|
||||||
u32 LocaliseCodeAddress(u32 num, u32 addr)
|
u32 LocaliseCodeAddress(u32 num, u32 addr)
|
||||||
|
@ -115,21 +141,14 @@ u32 LocaliseCodeAddress(u32 num, u32 addr)
|
||||||
? ARMJIT_Memory::ClassifyAddress9(addr)
|
? ARMJIT_Memory::ClassifyAddress9(addr)
|
||||||
: ARMJIT_Memory::ClassifyAddress7(addr);
|
: ARMJIT_Memory::ClassifyAddress7(addr);
|
||||||
|
|
||||||
u32 mappingStart, mappingSize, memoryOffset, memorySize;
|
if (CodeMemRegions[region])
|
||||||
if (ARMJIT_Memory::GetRegionMapping(region, num, mappingStart,
|
return ARMJIT_Memory::LocaliseAddress(region, num, addr);
|
||||||
mappingSize, memoryOffset, memorySize)
|
|
||||||
&& CodeMemRegions[region])
|
|
||||||
{
|
|
||||||
addr = ((addr - mappingStart) & (memorySize - 1)) + memoryOffset;
|
|
||||||
addr |= (u32)region << 28;
|
|
||||||
return addr;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
TinyVector<u32> InvalidLiterals;
|
TinyVector<u32> InvalidLiterals;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, int ConsoleType>
|
||||||
T SlowRead9(u32 addr, ARMv5* cpu)
|
T SlowRead9(u32 addr, ARMv5* cpu)
|
||||||
{
|
{
|
||||||
u32 offset = addr & 0x3;
|
u32 offset = addr & 0x3;
|
||||||
|
@ -141,11 +160,11 @@ T SlowRead9(u32 addr, ARMv5* cpu)
|
||||||
else if (addr >= cpu->DTCMBase && addr < (cpu->DTCMBase + cpu->DTCMSize))
|
else if (addr >= cpu->DTCMBase && addr < (cpu->DTCMBase + cpu->DTCMSize))
|
||||||
val = *(T*)&cpu->DTCM[(addr - cpu->DTCMBase) & 0x3FFF];
|
val = *(T*)&cpu->DTCM[(addr - cpu->DTCMBase) & 0x3FFF];
|
||||||
else if (std::is_same<T, u32>::value)
|
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)
|
else if (std::is_same<T, u16>::value)
|
||||||
val = NDS::ARM9Read16(addr);
|
val = (ConsoleType == 0 ? NDS::ARM9Read16 : DSi::ARM9Read16)(addr);
|
||||||
else
|
else
|
||||||
val = NDS::ARM9Read8(addr);
|
val = (ConsoleType == 0 ? NDS::ARM9Read8 : DSi::ARM9Read8)(addr);
|
||||||
|
|
||||||
if (std::is_same<T, u32>::value)
|
if (std::is_same<T, u32>::value)
|
||||||
return ROR(val, offset << 3);
|
return ROR(val, offset << 3);
|
||||||
|
@ -153,7 +172,7 @@ T SlowRead9(u32 addr, ARMv5* cpu)
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, int ConsoleType>
|
||||||
void SlowWrite9(u32 addr, ARMv5* cpu, T val)
|
void SlowWrite9(u32 addr, ARMv5* cpu, T val)
|
||||||
{
|
{
|
||||||
addr &= ~(sizeof(T) - 1);
|
addr &= ~(sizeof(T) - 1);
|
||||||
|
@ -169,27 +188,19 @@ void SlowWrite9(u32 addr, ARMv5* cpu, T val)
|
||||||
}
|
}
|
||||||
else if (std::is_same<T, u32>::value)
|
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)
|
else if (std::is_same<T, u16>::value)
|
||||||
{
|
{
|
||||||
NDS::ARM9Write16(addr, val);
|
(ConsoleType == 0 ? NDS::ARM9Write16 : DSi::ARM9Write16)(addr, val);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NDS::ARM9Write8(addr, val);
|
(ConsoleType == 0 ? NDS::ARM9Write8 : DSi::ARM9Write8)(addr, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template void SlowWrite9<u32>(u32, ARMv5*, u32);
|
template <typename T, int ConsoleType>
|
||||||
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>
|
|
||||||
T SlowRead7(u32 addr)
|
T SlowRead7(u32 addr)
|
||||||
{
|
{
|
||||||
u32 offset = addr & 0x3;
|
u32 offset = addr & 0x3;
|
||||||
|
@ -197,11 +208,11 @@ T SlowRead7(u32 addr)
|
||||||
|
|
||||||
T val;
|
T val;
|
||||||
if (std::is_same<T, u32>::value)
|
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)
|
else if (std::is_same<T, u16>::value)
|
||||||
val = NDS::ARM7Read16(addr);
|
val = (ConsoleType == 0 ? NDS::ARM7Read16 : DSi::ARM7Read16)(addr);
|
||||||
else
|
else
|
||||||
val = NDS::ARM7Read8(addr);
|
val = (ConsoleType == 0 ? NDS::ARM7Read8 : DSi::ARM7Read8)(addr);
|
||||||
|
|
||||||
if (std::is_same<T, u32>::value)
|
if (std::is_same<T, u32>::value)
|
||||||
return ROR(val, offset << 3);
|
return ROR(val, offset << 3);
|
||||||
|
@ -209,67 +220,71 @@ T SlowRead7(u32 addr)
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, int ConsoleType>
|
||||||
void SlowWrite7(u32 addr, T val)
|
void SlowWrite7(u32 addr, T val)
|
||||||
{
|
{
|
||||||
addr &= ~(sizeof(T) - 1);
|
addr &= ~(sizeof(T) - 1);
|
||||||
|
|
||||||
if (std::is_same<T, u32>::value)
|
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)
|
else if (std::is_same<T, u16>::value)
|
||||||
NDS::ARM7Write16(addr, val);
|
(ConsoleType == 0 ? NDS::ARM7Write16 : DSi::ARM7Write16)(addr, val);
|
||||||
else
|
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)
|
void SlowBlockTransfer9(u32 addr, u64* data, u32 num, ARMv5* cpu)
|
||||||
{
|
{
|
||||||
addr &= ~0x3;
|
addr &= ~0x3;
|
||||||
if (PreInc)
|
|
||||||
addr += 4;
|
|
||||||
for (int i = 0; i < num; i++)
|
for (int i = 0; i < num; i++)
|
||||||
{
|
{
|
||||||
if (Write)
|
if (Write)
|
||||||
SlowWrite9<u32>(addr, cpu, data[i]);
|
SlowWrite9<u32, ConsoleType>(addr, cpu, data[i]);
|
||||||
else
|
else
|
||||||
data[i] = SlowRead9<u32>(addr, cpu);
|
data[i] = SlowRead9<u32, ConsoleType>(addr, cpu);
|
||||||
addr += 4;
|
addr += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool PreInc, bool Write>
|
template <bool Write, int ConsoleType>
|
||||||
void SlowBlockTransfer7(u32 addr, u64* data, u32 num)
|
void SlowBlockTransfer7(u32 addr, u64* data, u32 num)
|
||||||
{
|
{
|
||||||
addr &= ~0x3;
|
addr &= ~0x3;
|
||||||
if (PreInc)
|
|
||||||
addr += 4;
|
|
||||||
for (int i = 0; i < num; i++)
|
for (int i = 0; i < num; i++)
|
||||||
{
|
{
|
||||||
if (Write)
|
if (Write)
|
||||||
SlowWrite7<u32>(addr, data[i]);
|
SlowWrite7<u32, ConsoleType>(addr, data[i]);
|
||||||
else
|
else
|
||||||
data[i] = SlowRead7<u32>(addr);
|
data[i] = SlowRead7<u32, ConsoleType>(addr);
|
||||||
addr += 4;
|
addr += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template void SlowWrite7<u32>(u32, u32);
|
#define INSTANTIATE_SLOWMEM(consoleType) \
|
||||||
template void SlowWrite7<u16>(u32, u16);
|
template void SlowWrite9<u32, consoleType>(u32, ARMv5*, u32); \
|
||||||
template void SlowWrite7<u8>(u32, u8);
|
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); \
|
||||||
|
|
||||||
template u32 SlowRead7<u32>(u32);
|
INSTANTIATE_SLOWMEM(0)
|
||||||
template u16 SlowRead7<u16>(u32);
|
INSTANTIATE_SLOWMEM(1)
|
||||||
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);
|
|
||||||
|
|
||||||
template <typename K, typename V, int Size, V InvalidValue>
|
template <typename K, typename V, int Size, V InvalidValue>
|
||||||
struct UnreliableHashTable
|
struct UnreliableHashTable
|
||||||
|
@ -616,6 +631,12 @@ void CompileBlock(ARM* cpu)
|
||||||
|
|
||||||
u32 blockAddr = cpu->R[15] - (thumb ? 2 : 4);
|
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& map = cpu->Num == 0 ? JitBlocks9 : JitBlocks7;
|
||||||
auto existingBlockIt = map.find(blockAddr);
|
auto existingBlockIt = map.find(blockAddr);
|
||||||
if (existingBlockIt != map.end())
|
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
|
// 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
|
// could be that there are two blocks at the same physical addr
|
||||||
// but different mirrors
|
// but different mirrors
|
||||||
u32 localAddr = existingBlockIt->second->StartAddrLocal;
|
u32 otherLocalAddr = existingBlockIt->second->StartAddrLocal;
|
||||||
|
|
||||||
u64* entry = &FastBlockLookupRegions[localAddr >> 28][localAddr & 0xFFFFFFF];
|
if (localAddr == otherLocalAddr)
|
||||||
*entry = ((u64)blockAddr | cpu->Num) << 32;
|
{
|
||||||
*entry |= JITCompiler->SubEntryOffset(existingBlockIt->second->EntryPoint);
|
JIT_DEBUGPRINT("switching out block %x %x %x\n", localAddr, blockAddr, existingBlockIt->second->StartAddr);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 localAddr = LocaliseCodeAddress(cpu->Num, blockAddr);
|
u64* entry = &FastBlockLookupRegions[localAddr >> 27][(localAddr & 0x7FFFFFF) / 2];
|
||||||
if (!localAddr)
|
*entry = ((u64)blockAddr | cpu->Num) << 32;
|
||||||
{
|
*entry |= JITCompiler->SubEntryOffset(existingBlockIt->second->EntryPoint);
|
||||||
printf("trying to compile non executable code? %x\n", blockAddr);
|
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];
|
FetchedInstr instrs[Config::JIT_MaxBlockSize];
|
||||||
|
@ -655,7 +682,7 @@ void CompileBlock(ARM* cpu)
|
||||||
u32 nextInstr[2] = {cpu->NextInstr[0], cpu->NextInstr[1]};
|
u32 nextInstr[2] = {cpu->NextInstr[0], cpu->NextInstr[1]};
|
||||||
u32 nextInstrAddr[2] = {blockAddr, r15};
|
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 lastSegmentStart = blockAddr;
|
||||||
u32 lr;
|
u32 lr;
|
||||||
|
@ -678,7 +705,7 @@ void CompileBlock(ARM* cpu)
|
||||||
instrValues[i] = instrs[i].Instr;
|
instrValues[i] = instrs[i].Instr;
|
||||||
|
|
||||||
u32 translatedAddr = LocaliseCodeAddress(cpu->Num, instrs[i].Addr);
|
u32 translatedAddr = LocaliseCodeAddress(cpu->Num, instrs[i].Addr);
|
||||||
assert(translatedAddr);
|
assert(translatedAddr >> 27);
|
||||||
u32 translatedAddrRounded = translatedAddr & ~0x1FF;
|
u32 translatedAddrRounded = translatedAddr & ~0x1FF;
|
||||||
if (i == 0 || translatedAddrRounded != addressRanges[numAddressRanges - 1])
|
if (i == 0 || translatedAddrRounded != addressRanges[numAddressRanges - 1])
|
||||||
{
|
{
|
||||||
|
@ -727,7 +754,10 @@ void CompileBlock(ARM* cpu)
|
||||||
cpu->CurInstr = instrs[i].Instr;
|
cpu->CurInstr = instrs[i].Instr;
|
||||||
cpu->CodeCycles = instrs[i].CodeCycles;
|
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;
|
hasLink = false;
|
||||||
|
|
||||||
if (thumb)
|
if (thumb)
|
||||||
|
@ -792,7 +822,7 @@ void CompileBlock(ARM* cpu)
|
||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (instrs[i].Info.Branches() && Config::JIT_BrancheOptimisations)
|
if (instrs[i].Info.Branches() && Config::JIT_BranchOptimisations)
|
||||||
{
|
{
|
||||||
bool hasBranched = cpu->R[15] != r15;
|
bool hasBranched = cpu->R[15] != r15;
|
||||||
|
|
||||||
|
@ -830,8 +860,6 @@ void CompileBlock(ARM* cpu)
|
||||||
}
|
}
|
||||||
else if (hasBranched && !isBackJump && i + 1 < Config::JIT_MaxBlockSize)
|
else if (hasBranched && !isBackJump && i + 1 < Config::JIT_MaxBlockSize)
|
||||||
{
|
{
|
||||||
u32 targetLocalised = LocaliseCodeAddress(cpu->Num, target);
|
|
||||||
|
|
||||||
if (link)
|
if (link)
|
||||||
{
|
{
|
||||||
lr = linkAddr;
|
lr = linkAddr;
|
||||||
|
@ -927,6 +955,8 @@ void CompileBlock(ARM* cpu)
|
||||||
FloodFillSetFlags(instrs, i - 1, 0xF);
|
FloodFillSetFlags(instrs, i - 1, 0xF);
|
||||||
|
|
||||||
block->EntryPoint = JITCompiler->CompileBlock(cpu, thumb, instrs, i);
|
block->EntryPoint = JITCompiler->CompileBlock(cpu, thumb, instrs, i);
|
||||||
|
|
||||||
|
JIT_DEBUGPRINT("block start %p\n", block->EntryPoint);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -940,12 +970,12 @@ void CompileBlock(ARM* cpu)
|
||||||
assert(addressMasks[j] == block->AddressMasks()[j]);
|
assert(addressMasks[j] == block->AddressMasks()[j]);
|
||||||
assert(addressMasks[j] != 0);
|
assert(addressMasks[j] != 0);
|
||||||
|
|
||||||
AddressRange* region = CodeMemRegions[addressRanges[j] >> 28];
|
AddressRange* region = CodeMemRegions[addressRanges[j] >> 27];
|
||||||
|
|
||||||
if (!PageContainsCode(®ion[(addressRanges[j] & 0xFFFF000) / 512]))
|
if (!PageContainsCode(®ion[(addressRanges[j] & 0x7FFF000) / 512]))
|
||||||
ARMJIT_Memory::SetCodeProtection(addressRanges[j] >> 28, addressRanges[j] & 0xFFFFFFF, true);
|
ARMJIT_Memory::SetCodeProtection(addressRanges[j] >> 27, addressRanges[j] & 0x7FFFFFF, true);
|
||||||
|
|
||||||
AddressRange* range = ®ion[(addressRanges[j] & 0xFFFFFFF) / 512];
|
AddressRange* range = ®ion[(addressRanges[j] & 0x7FFFFFF) / 512];
|
||||||
range->Code |= addressMasks[j];
|
range->Code |= addressMasks[j];
|
||||||
range->Blocks.Add(block);
|
range->Blocks.Add(block);
|
||||||
}
|
}
|
||||||
|
@ -955,7 +985,7 @@ void CompileBlock(ARM* cpu)
|
||||||
else
|
else
|
||||||
JitBlocks7[blockAddr] = block;
|
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 = ((u64)blockAddr | cpu->Num) << 32;
|
||||||
*entry |= JITCompiler->SubEntryOffset(block->EntryPoint);
|
*entry |= JITCompiler->SubEntryOffset(block->EntryPoint);
|
||||||
}
|
}
|
||||||
|
@ -964,8 +994,8 @@ void InvalidateByAddr(u32 localAddr)
|
||||||
{
|
{
|
||||||
JIT_DEBUGPRINT("invalidating by addr %x\n", localAddr);
|
JIT_DEBUGPRINT("invalidating by addr %x\n", localAddr);
|
||||||
|
|
||||||
AddressRange* region = CodeMemRegions[localAddr >> 28];
|
AddressRange* region = CodeMemRegions[localAddr >> 27];
|
||||||
AddressRange* range = ®ion[(localAddr & 0xFFFFFFF) / 512];
|
AddressRange* range = ®ion[(localAddr & 0x7FFFFFF) / 512];
|
||||||
u32 mask = 1 << ((localAddr & 0x1FF) / 16);
|
u32 mask = 1 << ((localAddr & 0x1FF) / 16);
|
||||||
|
|
||||||
range->Code = 0;
|
range->Code = 0;
|
||||||
|
@ -994,9 +1024,9 @@ void InvalidateByAddr(u32 localAddr)
|
||||||
range->Blocks.Remove(i);
|
range->Blocks.Remove(i);
|
||||||
|
|
||||||
if (range->Blocks.Length == 0
|
if (range->Blocks.Length == 0
|
||||||
&& !PageContainsCode(®ion[(localAddr & 0xFFFF000) / 512]))
|
&& !PageContainsCode(®ion[(localAddr & 0x7FFF000) / 512]))
|
||||||
{
|
{
|
||||||
ARMJIT_Memory::SetCodeProtection(localAddr >> 28, localAddr & 0xFFFFFFF, false);
|
ARMJIT_Memory::SetCodeProtection(localAddr >> 27, localAddr & 0x7FFFFFF, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool literalInvalidation = false;
|
bool literalInvalidation = false;
|
||||||
|
@ -1019,8 +1049,8 @@ void InvalidateByAddr(u32 localAddr)
|
||||||
u32 addr = block->AddressRanges()[j];
|
u32 addr = block->AddressRanges()[j];
|
||||||
if ((addr / 512) != (localAddr / 512))
|
if ((addr / 512) != (localAddr / 512))
|
||||||
{
|
{
|
||||||
AddressRange* otherRegion = CodeMemRegions[addr >> 28];
|
AddressRange* otherRegion = CodeMemRegions[addr >> 27];
|
||||||
AddressRange* otherRange = &otherRegion[(addr & 0xFFFFFFF) / 512];
|
AddressRange* otherRange = &otherRegion[(addr & 0x7FFFFFF) / 512];
|
||||||
assert(otherRange != range);
|
assert(otherRange != range);
|
||||||
|
|
||||||
bool removed = otherRange->Blocks.RemoveByValue(block);
|
bool removed = otherRange->Blocks.RemoveByValue(block);
|
||||||
|
@ -1028,15 +1058,15 @@ void InvalidateByAddr(u32 localAddr)
|
||||||
|
|
||||||
if (otherRange->Blocks.Length == 0)
|
if (otherRange->Blocks.Length == 0)
|
||||||
{
|
{
|
||||||
if (!PageContainsCode(&otherRegion[(addr & 0xFFFF000) / 512]))
|
if (!PageContainsCode(&otherRegion[(addr & 0x7FFF000) / 512]))
|
||||||
ARMJIT_Memory::SetCodeProtection(addr >> 28, addr & 0xFFFFFFF, false);
|
ARMJIT_Memory::SetCodeProtection(addr >> 27, addr & 0x7FFFFFF, false);
|
||||||
|
|
||||||
otherRange->Code = 0;
|
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)
|
if (block->Num == 0)
|
||||||
JitBlocks9.erase(block->StartAddr);
|
JitBlocks9.erase(block->StartAddr);
|
||||||
else
|
else
|
||||||
|
@ -1055,17 +1085,23 @@ void InvalidateByAddr(u32 localAddr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CheckAndInvalidateITCM()
|
||||||
|
{
|
||||||
|
for (u32 i = 0; i < ITCMPhysicalSize; i+=16)
|
||||||
|
{
|
||||||
|
if (CodeIndexITCM[i / 512].Code & (1 << ((i & 0x1FF) / 16)))
|
||||||
|
{
|
||||||
|
InvalidateByAddr(i | (ARMJIT_Memory::memregion_ITCM << 27));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <u32 num, int region>
|
template <u32 num, int region>
|
||||||
void CheckAndInvalidate(u32 addr)
|
void CheckAndInvalidate(u32 addr)
|
||||||
{
|
{
|
||||||
// let's hope this gets all properly inlined
|
u32 localAddr = ARMJIT_Memory::LocaliseAddress(region, num, addr);
|
||||||
u32 mappingStart, mappingSize, memoryOffset, memorySize;
|
if (CodeMemRegions[region][(localAddr & 0x7FFFFFF) / 512].Code & (1 << ((localAddr & 0x1FF) / 16)))
|
||||||
if (ARMJIT_Memory::GetRegionMapping(region, num, mappingStart, mappingSize, memoryOffset, memorySize))
|
InvalidateByAddr(localAddr);
|
||||||
{
|
|
||||||
u32 localAddr = ((addr - mappingStart) & (memorySize - 1)) + memoryOffset;
|
|
||||||
if (CodeMemRegions[region][localAddr / 512].Code & (1 << ((localAddr & 0x1FF) / 16)))
|
|
||||||
InvalidateByAddr(localAddr | (region << 28));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JitBlockEntry LookUpBlock(u32 num, u64* entries, u32 offset, u32 addr)
|
JitBlockEntry LookUpBlock(u32 num, u64* entries, u32 offset, u32 addr)
|
||||||
|
@ -1076,35 +1112,44 @@ JitBlockEntry LookUpBlock(u32 num, u64* entries, u32 offset, u32 addr)
|
||||||
return NULL;
|
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)
|
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
|
int region = num == 0
|
||||||
? ARMJIT_Memory::ClassifyAddress9(blockAddr)
|
? ARMJIT_Memory::ClassifyAddress9(blockAddr)
|
||||||
: ARMJIT_Memory::ClassifyAddress7(blockAddr);
|
: ARMJIT_Memory::ClassifyAddress7(blockAddr);
|
||||||
|
|
||||||
u32 mappingStart, mappingSize, memoryOffset, memorySize;
|
u32 memoryOffset;
|
||||||
if (CodeMemRegions[region]
|
if (FastBlockLookupRegions[region]
|
||||||
&& ARMJIT_Memory::GetRegionMapping(region, num, mappingStart,
|
&& ARMJIT_Memory::GetMirrorLocation(region, num, blockAddr, memoryOffset, start, size))
|
||||||
mappingSize, memoryOffset, memorySize))
|
|
||||||
{
|
{
|
||||||
|
//printf("setup exec region %d %d %08x %08x %x %x\n", num, region, blockAddr, start, size, memoryOffset);
|
||||||
entry = FastBlockLookupRegions[region] + memoryOffset / 2;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
return false;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template void CheckAndInvalidate<0, ARMJIT_Memory::memregion_MainRAM>(u32);
|
template void CheckAndInvalidate<0, ARMJIT_Memory::memregion_MainRAM>(u32);
|
||||||
template void CheckAndInvalidate<1, 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<0, ARMJIT_Memory::memregion_SharedWRAM>(u32);
|
||||||
template void CheckAndInvalidate<1, ARMJIT_Memory::memregion_SWRAM>(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_WRAM7>(u32);
|
||||||
template void CheckAndInvalidate<1, ARMJIT_Memory::memregion_VWRAM>(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_VRAM>(u32);
|
||||||
template void CheckAndInvalidate<0, ARMJIT_Memory::memregion_ITCM>(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()
|
void ResetBlockCache()
|
||||||
{
|
{
|
||||||
|
@ -1133,7 +1178,7 @@ void ResetBlockCache()
|
||||||
for (int j = 0; j < block->NumAddresses; j++)
|
for (int j = 0; j < block->NumAddresses; j++)
|
||||||
{
|
{
|
||||||
u32 addr = block->AddressRanges()[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->Blocks.Clear();
|
||||||
range->Code = 0;
|
range->Code = 0;
|
||||||
}
|
}
|
||||||
|
@ -1145,7 +1190,7 @@ void ResetBlockCache()
|
||||||
for (int j = 0; j < block->NumAddresses; j++)
|
for (int j = 0; j < block->NumAddresses; j++)
|
||||||
{
|
{
|
||||||
u32 addr = block->AddressRanges()[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->Blocks.Clear();
|
||||||
range->Code = 0;
|
range->Code = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,8 @@ void DeInit();
|
||||||
|
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
||||||
|
void CheckAndInvalidateITCM();
|
||||||
|
|
||||||
void InvalidateByAddr(u32 pseudoPhysical);
|
void InvalidateByAddr(u32 pseudoPhysical);
|
||||||
|
|
||||||
template <u32 num, int region>
|
template <u32 num, int region>
|
||||||
|
|
|
@ -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::ClassifyAddress9(addrIsStatic ? staticAddress : CurInstr.DataRegion)
|
||||||
: ARMJIT_Memory::ClassifyAddress7(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();
|
ptrdiff_t memopStart = GetCodeOffset();
|
||||||
LoadStorePatch patch;
|
LoadStorePatch patch;
|
||||||
|
@ -461,7 +461,7 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc
|
||||||
: ARMJIT_Memory::ClassifyAddress7(CurInstr.DataRegion);
|
: ARMJIT_Memory::ClassifyAddress7(CurInstr.DataRegion);
|
||||||
|
|
||||||
bool compileFastPath = Config::JIT_FastMemory
|
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)
|
if (decrement)
|
||||||
{
|
{
|
||||||
|
|
|
@ -214,13 +214,13 @@ u32 LocaliseCodeAddress(u32 num, u32 addr);
|
||||||
template <u32 Num>
|
template <u32 Num>
|
||||||
void LinkBlock(ARM* cpu, u32 codeOffset);
|
void LinkBlock(ARM* cpu, u32 codeOffset);
|
||||||
|
|
||||||
template <typename T> T SlowRead9(u32 addr, ARMv5* cpu);
|
template <typename T, int ConsoleType> T SlowRead9(u32 addr, ARMv5* cpu);
|
||||||
template <typename T> void SlowWrite9(u32 addr, ARMv5* cpu, T val);
|
template <typename T, int ConsoleType> void SlowWrite9(u32 addr, ARMv5* cpu, T val);
|
||||||
template <typename T> T SlowRead7(u32 addr);
|
template <typename T, int ConsoleType> T SlowRead7(u32 addr);
|
||||||
template <typename T> void SlowWrite7(u32 addr, T val);
|
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 Write, int ConsoleType> 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 SlowBlockTransfer7(u32 addr, u64* data, u32 num);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#ifdef __SWITCH__
|
#if defined(__SWITCH__)
|
||||||
#include "switch/compat_switch.h"
|
#include "switch/compat_switch.h"
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "ARMJIT_Memory.h"
|
#include "ARMJIT_Memory.h"
|
||||||
|
@ -7,6 +9,7 @@
|
||||||
#include "ARMJIT_Internal.h"
|
#include "ARMJIT_Internal.h"
|
||||||
#include "ARMJIT_Compiler.h"
|
#include "ARMJIT_Compiler.h"
|
||||||
|
|
||||||
|
#include "DSi.h"
|
||||||
#include "GPU.h"
|
#include "GPU.h"
|
||||||
#include "GPU3D.h"
|
#include "GPU3D.h"
|
||||||
#include "Wifi.h"
|
#include "Wifi.h"
|
||||||
|
@ -37,66 +40,24 @@
|
||||||
|
|
||||||
namespace ARMJIT_Memory
|
namespace ARMJIT_Memory
|
||||||
{
|
{
|
||||||
#ifdef __aarch64__
|
|
||||||
struct FaultDescription
|
struct FaultDescription
|
||||||
{
|
{
|
||||||
u64 IntegerRegisters[33];
|
u32 EmulatedFaultAddr;
|
||||||
u64 FaultAddr;
|
u64 FaultPC;
|
||||||
|
|
||||||
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);
|
bool FaultHandler(FaultDescription* faultDesc, s32& offset);
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void FaultHandler(FaultDescription* faultDesc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(__SWITCH__)
|
||||||
#ifdef __aarch64__
|
|
||||||
|
|
||||||
extern "C" void ARM_RestoreContext(u64* registers) __attribute__((noreturn));
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __SWITCH__
|
|
||||||
// with LTO the symbols seem to be not properly overriden
|
// with LTO the symbols seem to be not properly overriden
|
||||||
// if they're somewhere else
|
// if they're somewhere else
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
|
|
||||||
|
void ARM_RestoreContext(u64* registers) __attribute__((noreturn));
|
||||||
|
|
||||||
extern char __start__;
|
extern char __start__;
|
||||||
extern char __rodata_start;
|
extern char __rodata_start;
|
||||||
|
|
||||||
|
@ -106,57 +67,85 @@ u64 __nx_exception_stack_size = 0x8000;
|
||||||
void __libnx_exception_handler(ThreadExceptionDump* ctx)
|
void __libnx_exception_handler(ThreadExceptionDump* ctx)
|
||||||
{
|
{
|
||||||
ARMJIT_Memory::FaultDescription desc;
|
ARMJIT_Memory::FaultDescription desc;
|
||||||
memcpy(desc.IntegerRegisters, &ctx->cpu_gprs[0].x, 8*29);
|
desc.EmulatedFaultAddr = ctx->cpu_gprs[0].w;
|
||||||
desc.IntegerRegisters[29] = ctx->fp.x;
|
desc.FaultPC = ctx->pc.x;
|
||||||
desc.IntegerRegisters[30] = ctx->lr.x;
|
|
||||||
desc.IntegerRegisters[31] = ctx->sp.x;
|
|
||||||
desc.IntegerRegisters[32] = ctx->pc.x;
|
|
||||||
|
|
||||||
ARMJIT_Memory::FaultHandler(&desc);
|
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;
|
||||||
|
|
||||||
|
ARM_RestoreContext(integerRegisters);
|
||||||
|
}
|
||||||
|
|
||||||
if (ctx->pc.x >= (u64)&__start__ && ctx->pc.x < (u64)&__rodata_start)
|
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);
|
ctx->pc.x - (u64)&__start__, ctx->error_desc, ctx->far.x);
|
||||||
}
|
}
|
||||||
else
|
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
|
#endif
|
||||||
|
|
||||||
namespace ARMJIT_Memory
|
namespace ARMJIT_Memory
|
||||||
{
|
{
|
||||||
|
|
||||||
#ifdef __aarch64__
|
void* FastMem9Start, *FastMem7Start;
|
||||||
void FaultDescription::RestoreAndRepeat(s64 offset)
|
|
||||||
{
|
|
||||||
IntegerRegisters[32] += offset;
|
|
||||||
|
|
||||||
ARM_RestoreContext(IntegerRegisters);
|
#ifdef _WIN32
|
||||||
|
inline u32 RoundUp(u32 size)
|
||||||
|
{
|
||||||
|
return (size + 0xFFFF) & ~0xFFFF;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
void FaultDescription::RestoreAndRepeat(s64 offset)
|
inline u32 RoundUp(u32 size)
|
||||||
{
|
{
|
||||||
|
return size;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void* FastMem9Start, *FastMem7Start;
|
|
||||||
|
|
||||||
const u32 MemoryTotalSize =
|
|
||||||
NDS::MainRAMSize
|
|
||||||
+ NDS::SharedWRAMSize
|
|
||||||
+ NDS::ARM7WRAMSize
|
|
||||||
+ DTCMPhysicalSize;
|
|
||||||
|
|
||||||
const u32 MemBlockMainRAMOffset = 0;
|
const u32 MemBlockMainRAMOffset = 0;
|
||||||
const u32 MemBlockSWRAMOffset = NDS::MainRAMSize;
|
const u32 MemBlockSWRAMOffset = RoundUp(NDS::MainRAMMaxSize);
|
||||||
const u32 MemBlockARM7WRAMOffset = NDS::MainRAMSize + NDS::SharedWRAMSize;
|
const u32 MemBlockARM7WRAMOffset = MemBlockSWRAMOffset + RoundUp(NDS::SharedWRAMSize);
|
||||||
const u32 MemBlockDTCMOffset = NDS::MainRAMSize + NDS::SharedWRAMSize + NDS::ARM7WRAMSize;
|
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] =
|
const u32 OffsetsPerRegion[memregions_Count] =
|
||||||
{
|
{
|
||||||
|
@ -173,6 +162,11 @@ const u32 OffsetsPerRegion[memregions_Count] =
|
||||||
UINT32_MAX,
|
UINT32_MAX,
|
||||||
UINT32_MAX,
|
UINT32_MAX,
|
||||||
UINT32_MAX,
|
UINT32_MAX,
|
||||||
|
UINT32_MAX,
|
||||||
|
UINT32_MAX,
|
||||||
|
MemBlockNWRAM_AOffset,
|
||||||
|
MemBlockNWRAM_BOffset,
|
||||||
|
MemBlockNWRAM_COffset
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -186,11 +180,13 @@ enum
|
||||||
u8 MappingStatus9[1 << (32-12)];
|
u8 MappingStatus9[1 << (32-12)];
|
||||||
u8 MappingStatus7[1 << (32-12)];
|
u8 MappingStatus7[1 << (32-12)];
|
||||||
|
|
||||||
#ifdef __SWITCH__
|
#if defined(__SWITCH__)
|
||||||
u8* MemoryBase;
|
u8* MemoryBase;
|
||||||
u8* MemoryBaseCodeMem;
|
u8* MemoryBaseCodeMem;
|
||||||
#else
|
#elif defined(_WIN32)
|
||||||
u8* MemoryBase;
|
u8* MemoryBase;
|
||||||
|
HANDLE MemoryFile;
|
||||||
|
LPVOID ExceptionHandlerHandle;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool MapIntoRange(u32 addr, u32 num, u32 offset, u32 size)
|
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(),
|
Result r = (svcMapProcessMemory(dst, envGetOwnProcessHandle(),
|
||||||
(u64)(MemoryBaseCodeMem + offset), size));
|
(u64)(MemoryBaseCodeMem + offset), size));
|
||||||
return R_SUCCEEDED(r);
|
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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,8 +208,24 @@ bool UnmapFromRange(u32 addr, u32 num, u32 offset, u32 size)
|
||||||
#ifdef __SWITCH__
|
#ifdef __SWITCH__
|
||||||
Result r = svcUnmapProcessMemory(dst, envGetOwnProcessHandle(),
|
Result r = svcUnmapProcessMemory(dst, envGetOwnProcessHandle(),
|
||||||
(u64)(MemoryBaseCodeMem + offset), size);
|
(u64)(MemoryBaseCodeMem + offset), size);
|
||||||
printf("%x\n", r);
|
|
||||||
return R_SUCCEEDED(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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,7 +245,6 @@ struct Mapping
|
||||||
if (skipDTCM && Addr + offset == NDS::ARM9->DTCMBase)
|
if (skipDTCM && Addr + offset == NDS::ARM9->DTCMBase)
|
||||||
{
|
{
|
||||||
offset += NDS::ARM9->DTCMSize;
|
offset += NDS::ARM9->DTCMSize;
|
||||||
printf("%x skip\n", NDS::ARM9->DTCMSize);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -245,6 +259,7 @@ struct Mapping
|
||||||
offset += 0x1000;
|
offset += 0x1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __SWITCH__
|
||||||
if (status == memstate_MappedRW)
|
if (status == memstate_MappedRW)
|
||||||
{
|
{
|
||||||
u32 segmentSize = offset - segmentOffset;
|
u32 segmentSize = offset - segmentOffset;
|
||||||
|
@ -252,8 +267,12 @@ struct Mapping
|
||||||
bool success = UnmapFromRange(Addr + segmentOffset, Num, segmentOffset + LocalOffset + OffsetsPerRegion[region], segmentSize);
|
bool success = UnmapFromRange(Addr + segmentOffset, Num, segmentOffset + LocalOffset + OffsetsPerRegion[region], segmentSize);
|
||||||
assert(success);
|
assert(success);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if defined(_WIN32)
|
||||||
|
UnmapFromRange(Addr, Num, OffsetsPerRegion[region] + LocalOffset, Size);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
ARMJIT::TinyVector<Mapping> Mappings[memregions_Count];
|
ARMJIT::TinyVector<Mapping> Mappings[memregions_Count];
|
||||||
|
@ -268,6 +287,8 @@ void SetCodeProtection(int region, u32 offset, bool protect)
|
||||||
Mapping& mapping = Mappings[region][i];
|
Mapping& mapping = Mappings[region][i];
|
||||||
|
|
||||||
u32 effectiveAddr = mapping.Addr + (offset - mapping.LocalOffset);
|
u32 effectiveAddr = mapping.Addr + (offset - mapping.LocalOffset);
|
||||||
|
if (offset < mapping.LocalOffset || offset >= mapping.LocalOffset + mapping.Size)
|
||||||
|
continue;
|
||||||
if (mapping.Num == 0
|
if (mapping.Num == 0
|
||||||
&& region != memregion_DTCM
|
&& region != memregion_DTCM
|
||||||
&& effectiveAddr >= NDS::ARM9->DTCMBase
|
&& effectiveAddr >= NDS::ARM9->DTCMBase
|
||||||
|
@ -276,16 +297,20 @@ void SetCodeProtection(int region, u32 offset, bool protect)
|
||||||
|
|
||||||
u8* states = (u8*)(mapping.Num == 0 ? MappingStatus9 : MappingStatus7);
|
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));
|
assert(states[effectiveAddr >> 12] == (protect ? memstate_MappedRW : memstate_MappedProtected));
|
||||||
states[effectiveAddr >> 12] = protect ? memstate_MappedProtected : memstate_MappedRW;
|
states[effectiveAddr >> 12] = protect ? memstate_MappedProtected : memstate_MappedRW;
|
||||||
|
|
||||||
|
#if defined(__SWITCH__)
|
||||||
bool success;
|
bool success;
|
||||||
if (protect)
|
if (protect)
|
||||||
success = UnmapFromRange(effectiveAddr, mapping.Num, OffsetsPerRegion[region] + offset, 0x1000);
|
success = UnmapFromRange(effectiveAddr, mapping.Num, OffsetsPerRegion[region] + offset, 0x1000);
|
||||||
else
|
else
|
||||||
success = MapIntoRange(effectiveAddr, mapping.Num, OffsetsPerRegion[region] + offset, 0x1000);
|
success = MapIntoRange(effectiveAddr, mapping.Num, OffsetsPerRegion[region] + offset, 0x1000);
|
||||||
assert(success);
|
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);
|
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 oldOverlap = NDS::ARM9->DTCMSize > 0 && !(oldDTCMBase >= end || oldDTCBEnd < start);
|
||||||
bool newOverlap = newSize > 0 && ((newBase >= start && newBase < end) || (newEnd >= start && newEnd < end));
|
bool newOverlap = newSize > 0 && !(newBase >= end || newEnd < start);
|
||||||
|
|
||||||
if (mapping.Num == 0 && (oldOverlap || newOverlap))
|
if (mapping.Num == 0 && (oldOverlap || newOverlap))
|
||||||
{
|
{
|
||||||
|
@ -336,19 +361,50 @@ void RemapDTCM(u32 newBase, u32 newSize)
|
||||||
Mappings[memregion_DTCM].Clear();
|
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()
|
void RemapSWRAM()
|
||||||
{
|
{
|
||||||
printf("remapping SWRAM\n");
|
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++)
|
for (int i = 0; i < Mappings[memregion_WRAM7].Length; i++)
|
||||||
{
|
{
|
||||||
Mappings[memregion_WRAM7][i].Unmap(memregion_WRAM7);
|
Mappings[memregion_WRAM7][i].Unmap(memregion_WRAM7);
|
||||||
}
|
}
|
||||||
Mappings[memregion_WRAM7].Clear();
|
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)
|
bool MapAtAddress(u32 addr)
|
||||||
|
@ -359,33 +415,36 @@ bool MapAtAddress(u32 addr)
|
||||||
? ClassifyAddress9(addr)
|
? ClassifyAddress9(addr)
|
||||||
: ClassifyAddress7(addr);
|
: ClassifyAddress7(addr);
|
||||||
|
|
||||||
if (!IsMappable(region))
|
if (!IsFastmemCompatible(region))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
u32 mappingStart, mappingSize, memoryOffset, memorySize;
|
return false;
|
||||||
bool isMapped = GetRegionMapping(region, num, mappingStart, mappingSize, memoryOffset, memorySize);
|
|
||||||
|
|
||||||
|
u32 mirrorStart, mirrorSize, memoryOffset;
|
||||||
|
bool isMapped = GetMirrorLocation(region, num, addr, memoryOffset, mirrorStart, mirrorSize);
|
||||||
if (!isMapped)
|
if (!isMapped)
|
||||||
return false;
|
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;
|
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];
|
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
|
// this overcomplicated piece of code basically just finds whole pieces of code memory
|
||||||
// which can be mapped
|
// which can be mapped
|
||||||
u32 offset = 0;
|
u32 offset = 0;
|
||||||
bool skipDTCM = num == 0 && region != memregion_DTCM;
|
bool skipDTCM = num == 0 && region != memregion_DTCM;
|
||||||
while (offset < memorySize)
|
while (offset < mirrorSize)
|
||||||
{
|
{
|
||||||
if (skipDTCM && mirrorStart + offset == NDS::ARM9->DTCMBase)
|
if (skipDTCM && mirrorStart + offset == NDS::ARM9->DTCMBase)
|
||||||
{
|
{
|
||||||
|
SetCodeProtectionRange(NDS::ARM9->DTCMBase, NDS::ARM9->DTCMSize, 0, 0);
|
||||||
offset += NDS::ARM9->DTCMSize;
|
offset += NDS::ARM9->DTCMSize;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -393,7 +452,7 @@ bool MapAtAddress(u32 addr)
|
||||||
u32 sectionOffset = offset;
|
u32 sectionOffset = offset;
|
||||||
bool hasCode = isExecutable && ARMJIT::PageContainsCode(&range[offset / 512]);
|
bool hasCode = isExecutable && ARMJIT::PageContainsCode(&range[offset / 512]);
|
||||||
while ((!isExecutable || ARMJIT::PageContainsCode(&range[offset / 512]) == hasCode)
|
while ((!isExecutable || ARMJIT::PageContainsCode(&range[offset / 512]) == hasCode)
|
||||||
&& offset < memorySize
|
&& offset < mirrorSize
|
||||||
&& (!skipDTCM || mirrorStart + offset != NDS::ARM9->DTCMBase))
|
&& (!skipDTCM || mirrorStart + offset != NDS::ARM9->DTCMBase))
|
||||||
{
|
{
|
||||||
assert(states[(mirrorStart + offset) >> 12] == memstate_Unmapped);
|
assert(states[(mirrorStart + offset) >> 12] == memstate_Unmapped);
|
||||||
|
@ -403,41 +462,49 @@ bool MapAtAddress(u32 addr)
|
||||||
|
|
||||||
u32 sectionSize = offset - sectionOffset;
|
u32 sectionSize = offset - sectionOffset;
|
||||||
|
|
||||||
|
#if defined(__SWITCH__)
|
||||||
if (!hasCode)
|
if (!hasCode)
|
||||||
{
|
{
|
||||||
printf("trying to map %x (size: %x) from %x\n", mirrorStart + sectionOffset, sectionSize, sectionOffset + memoryOffset + OffsetsPerRegion[region]);
|
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);
|
bool succeded = MapIntoRange(mirrorStart + sectionOffset, num, sectionOffset + memoryOffset + OffsetsPerRegion[region], sectionSize);
|
||||||
assert(succeded);
|
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);
|
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;
|
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;
|
bool rewriteToSlowPath = true;
|
||||||
|
|
||||||
u32 addr = faultDesc->GetEmulatedAddr();
|
u32 addr = faultDesc->EmulatedFaultAddr;
|
||||||
|
|
||||||
if ((NDS::CurCPU == 0 ? MappingStatus9 : MappingStatus7)[addr >> 12] == memstate_Unmapped)
|
if ((NDS::CurCPU == 0 ? MappingStatus9 : MappingStatus7)[addr >> 12] == memstate_Unmapped)
|
||||||
rewriteToSlowPath = !MapAtAddress(faultDesc->GetEmulatedAddr());
|
rewriteToSlowPath = !MapAtAddress(faultDesc->EmulatedFaultAddr);
|
||||||
|
|
||||||
s64 offset = 0;
|
|
||||||
if (rewriteToSlowPath)
|
if (rewriteToSlowPath)
|
||||||
{
|
{
|
||||||
offset = ARMJIT::JITCompiler->RewriteMemAccess(faultDesc->GetPC());
|
offset = ARMJIT::JITCompiler->RewriteMemAccess(faultDesc->FaultPC);
|
||||||
}
|
}
|
||||||
faultDesc->RestoreAndRepeat(offset);
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Init()
|
void Init()
|
||||||
|
@ -459,18 +526,34 @@ void Init()
|
||||||
FastMem7Start = virtmemReserve(0x100000000);
|
FastMem7Start = virtmemReserve(0x100000000);
|
||||||
assert(FastMem7Start);
|
assert(FastMem7Start);
|
||||||
|
|
||||||
NDS::MainRAM = MemoryBaseCodeMem + MemBlockMainRAMOffset;
|
u8* basePtr = MemoryBaseCodeMem;
|
||||||
NDS::SharedWRAM = MemoryBaseCodeMem + MemBlockSWRAMOffset;
|
#elif defined(_WIN32)
|
||||||
NDS::ARM7WRAM = MemoryBaseCodeMem + MemBlockARM7WRAMOffset;
|
ExceptionHandlerHandle = AddVectoredExceptionHandler(1, ExceptionHandler);
|
||||||
NDS::ARM9->DTCM = MemoryBaseCodeMem + MemBlockDTCMOffset;
|
|
||||||
#else
|
|
||||||
MemoryBase = new u8[MemoryTotalSize];
|
|
||||||
|
|
||||||
NDS::MainRAM = MemoryBase + MemBlockMainRAMOffset;
|
MemoryFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, MemoryTotalSize, NULL);
|
||||||
NDS::SharedWRAM = MemoryBase + MemBlockSWRAMOffset;
|
|
||||||
NDS::ARM7WRAM = MemoryBase + MemBlockARM7WRAMOffset;
|
MemoryBase = (u8*)VirtualAlloc(NULL, MemoryTotalSize, MEM_RESERVE, PAGE_READWRITE);
|
||||||
NDS::ARM9->DTCM = MemoryBase + MemBlockDTCMOffset;
|
|
||||||
|
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
|
#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()
|
void DeInit()
|
||||||
|
@ -482,8 +565,11 @@ void DeInit()
|
||||||
svcUnmapProcessCodeMemory(envGetOwnProcessHandle(), (u64)MemoryBaseCodeMem, (u64)MemoryBase, MemoryTotalSize);
|
svcUnmapProcessCodeMemory(envGetOwnProcessHandle(), (u64)MemoryBaseCodeMem, (u64)MemoryBase, MemoryTotalSize);
|
||||||
virtmemFree(MemoryBaseCodeMem, MemoryTotalSize);
|
virtmemFree(MemoryBaseCodeMem, MemoryTotalSize);
|
||||||
free(MemoryBase);
|
free(MemoryBase);
|
||||||
#else
|
#elif defined(_WIN32)
|
||||||
delete[] MemoryBase;
|
assert(UnmapViewOfFile(MemoryBase));
|
||||||
|
CloseHandle(MemoryFile);
|
||||||
|
|
||||||
|
RemoveVectoredExceptionHandler(ExceptionHandlerHandle);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -505,12 +591,23 @@ void Reset()
|
||||||
printf("done resetting jit mem\n");
|
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;
|
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;
|
memoryOffset = 0;
|
||||||
switch (region)
|
switch (region)
|
||||||
|
@ -518,137 +615,251 @@ bool GetRegionMapping(int region, u32 num, u32& mappingStart, u32& mappingSize,
|
||||||
case memregion_ITCM:
|
case memregion_ITCM:
|
||||||
if (num == 0)
|
if (num == 0)
|
||||||
{
|
{
|
||||||
mappingStart = 0;
|
mirrorStart = addr & ~(ITCMPhysicalSize - 1);
|
||||||
mappingSize = NDS::ARM9->ITCMSize;
|
mirrorSize = ITCMPhysicalSize;
|
||||||
memorySize = ITCMPhysicalSize;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
case memregion_DTCM:
|
|
||||||
if (num == 0)
|
|
||||||
{
|
|
||||||
mappingStart = NDS::ARM9->DTCMBase;
|
|
||||||
mappingSize = NDS::ARM9->DTCMSize;
|
|
||||||
memorySize = DTCMPhysicalSize;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
case memregion_BIOS9:
|
|
||||||
if (num == 0)
|
|
||||||
{
|
|
||||||
mappingStart = 0xFFFF0000;
|
|
||||||
mappingSize = 0x10000;
|
|
||||||
memorySize = 0x1000;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
case memregion_MainRAM:
|
case memregion_MainRAM:
|
||||||
mappingStart = 0x2000000;
|
mirrorStart = addr & ~NDS::MainRAMMask;
|
||||||
mappingSize = 0x1000000;
|
mirrorSize = NDS::MainRAMMask + 1;
|
||||||
memorySize = NDS::MainRAMSize;
|
|
||||||
return true;
|
return true;
|
||||||
case memregion_SWRAM:
|
case memregion_BIOS9:
|
||||||
mappingStart = 0x3000000;
|
|
||||||
if (num == 0 && NDS::SWRAM_ARM9.Mem)
|
|
||||||
{
|
|
||||||
mappingSize = 0x1000000;
|
|
||||||
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;
|
|
||||||
memoryOffset = NDS::SWRAM_ARM7.Mem - NDS::SharedWRAM;
|
|
||||||
memorySize = NDS::SWRAM_ARM7.Mask + 1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
case memregion_VRAM:
|
|
||||||
if (num == 0)
|
if (num == 0)
|
||||||
{
|
{
|
||||||
// this is a gross simplification
|
mirrorStart = addr & ~0xFFF;
|
||||||
// mostly to make code on vram working
|
mirrorSize = 0x1000;
|
||||||
// it doesn't take any of the actual VRAM mappings into account
|
|
||||||
mappingStart = 0x6000000;
|
|
||||||
mappingSize = 0x1000000;
|
|
||||||
memorySize = 0x100000;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
case memregion_BIOS7:
|
case memregion_BIOS7:
|
||||||
if (num == 1)
|
if (num == 1)
|
||||||
{
|
{
|
||||||
mappingStart = 0;
|
mirrorStart = 0;
|
||||||
mappingSize = 0x4000;
|
mirrorSize = 0x4000;
|
||||||
memorySize = 0x4000;
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case memregion_SharedWRAM:
|
||||||
|
if (num == 0 && NDS::SWRAM_ARM9.Mem)
|
||||||
|
{
|
||||||
|
mirrorStart = addr & ~NDS::SWRAM_ARM9.Mask;
|
||||||
|
mirrorSize = NDS::SWRAM_ARM9.Mask + 1;
|
||||||
|
memoryOffset = NDS::SWRAM_ARM9.Mem - NDS::SharedWRAM;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (num == 1 && NDS::SWRAM_ARM7.Mem)
|
||||||
|
{
|
||||||
|
mirrorStart = addr & ~NDS::SWRAM_ARM7.Mask;
|
||||||
|
mirrorSize = NDS::SWRAM_ARM7.Mask + 1;
|
||||||
|
memoryOffset = NDS::SWRAM_ARM7.Mem - NDS::SharedWRAM;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
case memregion_WRAM7:
|
case memregion_WRAM7:
|
||||||
if (num == 1)
|
if (num == 1)
|
||||||
{
|
{
|
||||||
if (NDS::SWRAM_ARM7.Mem)
|
mirrorStart = addr & ~(NDS::ARM7WRAMSize - 1);
|
||||||
{
|
mirrorSize = NDS::ARM7WRAMSize;
|
||||||
mappingStart = 0x3800000;
|
|
||||||
mappingSize = 0x800000;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mappingStart = 0x3000000;
|
|
||||||
mappingSize = 0x1000000;
|
|
||||||
}
|
|
||||||
memorySize = NDS::ARM7WRAMSize;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
case memregion_VRAM:
|
||||||
|
if (num == 0)
|
||||||
|
{
|
||||||
|
mirrorStart = addr & ~0xFFFFF;
|
||||||
|
mirrorSize = 0x100000;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
case memregion_VWRAM:
|
case memregion_VWRAM:
|
||||||
if (num == 1)
|
if (num == 1)
|
||||||
{
|
{
|
||||||
mappingStart = 0x6000000;
|
mirrorStart = addr & ~0x3FFFF;
|
||||||
mappingSize = 0x1000000;
|
mirrorSize = 0x40000;
|
||||||
memorySize = 0x20000;
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case memregion_NewSharedWRAM_A:
|
||||||
|
{
|
||||||
|
u8* ptr = DSi::NWRAMMap_A[num][(addr >> 16) & DSi::NWRAMMask[num][0]];
|
||||||
|
if (ptr)
|
||||||
|
{
|
||||||
|
memoryOffset = ptr - DSi::NWRAM_A;
|
||||||
|
mirrorStart = addr & ~0xFFFF;
|
||||||
|
mirrorSize = 0x10000;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false; // zero filled memory
|
||||||
|
}
|
||||||
|
case memregion_NewSharedWRAM_B:
|
||||||
|
{
|
||||||
|
u8* ptr = DSi::NWRAMMap_B[num][(addr >> 15) & DSi::NWRAMMask[num][1]];
|
||||||
|
if (ptr)
|
||||||
|
{
|
||||||
|
memoryOffset = ptr - DSi::NWRAM_B;
|
||||||
|
mirrorStart = addr & ~0x7FFF;
|
||||||
|
mirrorSize = 0x8000;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
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_BIOS7DSi:
|
||||||
|
if (num == 1)
|
||||||
|
{
|
||||||
|
mirrorStart = addr & ~0xFFFF;
|
||||||
|
mirrorSize = DSi::SCFG_BIOS & (1<<8) ? 0x8000 : 0x10000;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
default:
|
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;
|
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)
|
int ClassifyAddress9(u32 addr)
|
||||||
{
|
{
|
||||||
if (addr < NDS::ARM9->ITCMSize)
|
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
|
|
||||||
{
|
{
|
||||||
|
return memregion_ITCM;
|
||||||
|
}
|
||||||
|
else if (addr >= NDS::ARM9->DTCMBase && addr < (NDS::ARM9->DTCMBase + NDS::ARM9->DTCMSize))
|
||||||
|
{
|
||||||
|
return memregion_DTCM;
|
||||||
|
}
|
||||||
|
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)
|
switch (addr & 0xFF000000)
|
||||||
{
|
{
|
||||||
case 0x02000000:
|
case 0x02000000:
|
||||||
return memregion_MainRAM;
|
return memregion_MainRAM;
|
||||||
case 0x03000000:
|
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)
|
if (NDS::SWRAM_ARM9.Mem)
|
||||||
return memregion_SWRAM;
|
return memregion_SharedWRAM;
|
||||||
else
|
return memregion_Other;
|
||||||
return memregion_Other;
|
|
||||||
case 0x04000000:
|
case 0x04000000:
|
||||||
return memregion_IO9;
|
return memregion_IO9;
|
||||||
case 0x06000000:
|
case 0x06000000:
|
||||||
return memregion_VRAM;
|
return memregion_VRAM;
|
||||||
|
default:
|
||||||
|
return memregion_Other;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return memregion_Other;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ClassifyAddress7(u32 addr)
|
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;
|
return memregion_BIOS7;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
switch (addr & 0xFF800000)
|
switch (addr & 0xFF800000)
|
||||||
|
@ -657,10 +868,19 @@ int ClassifyAddress7(u32 addr)
|
||||||
case 0x02800000:
|
case 0x02800000:
|
||||||
return memregion_MainRAM;
|
return memregion_MainRAM;
|
||||||
case 0x03000000:
|
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)
|
if (NDS::SWRAM_ARM7.Mem)
|
||||||
return memregion_SWRAM;
|
return memregion_SharedWRAM;
|
||||||
else
|
return memregion_WRAM7;
|
||||||
return memregion_WRAM7;
|
|
||||||
case 0x03800000:
|
case 0x03800000:
|
||||||
return memregion_WRAM7;
|
return memregion_WRAM7;
|
||||||
case 0x04000000:
|
case 0x04000000:
|
||||||
|
@ -740,14 +960,29 @@ void* GetFuncForAddr(ARM* cpu, u32 addr, bool store, int size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (size | store)
|
if (NDS::ConsoleType == 0)
|
||||||
{
|
{
|
||||||
case 8: return (void*)NDS::ARM9IORead8;
|
switch (size | store)
|
||||||
case 9: return (void*)NDS::ARM9IOWrite8;
|
{
|
||||||
case 16: return (void*)NDS::ARM9IORead16;
|
case 8: return (void*)NDS::ARM9IORead8;
|
||||||
case 17: return (void*)NDS::ARM9IOWrite16;
|
case 9: return (void*)NDS::ARM9IOWrite8;
|
||||||
case 32: return (void*)NDS::ARM9IORead32;
|
case 16: return (void*)NDS::ARM9IORead16;
|
||||||
case 33: return (void*)NDS::ARM9IOWrite32;
|
case 17: return (void*)NDS::ARM9IOWrite16;
|
||||||
|
case 32: return (void*)NDS::ARM9IORead32;
|
||||||
|
case 33: return (void*)NDS::ARM9IOWrite32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
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;
|
break;
|
||||||
case 0x06000000:
|
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;
|
switch (size | store)
|
||||||
case 9: return (void*)NDS::ARM7IOWrite8;
|
{
|
||||||
case 16: return (void*)NDS::ARM7IORead16;
|
case 8: return (void*)NDS::ARM7IORead8;
|
||||||
case 17: return (void*)NDS::ARM7IOWrite16;
|
case 9: return (void*)NDS::ARM7IOWrite8;
|
||||||
case 32: return (void*)NDS::ARM7IORead32;
|
case 16: return (void*)NDS::ARM7IORead16;
|
||||||
case 33: return (void*)NDS::ARM7IOWrite32;
|
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;
|
break;
|
||||||
case 0x04800000:
|
case 0x04800000:
|
||||||
|
|
|
@ -23,7 +23,7 @@ enum
|
||||||
memregion_DTCM,
|
memregion_DTCM,
|
||||||
memregion_BIOS9,
|
memregion_BIOS9,
|
||||||
memregion_MainRAM,
|
memregion_MainRAM,
|
||||||
memregion_SWRAM,
|
memregion_SharedWRAM,
|
||||||
memregion_IO9,
|
memregion_IO9,
|
||||||
memregion_VRAM,
|
memregion_VRAM,
|
||||||
memregion_BIOS7,
|
memregion_BIOS7,
|
||||||
|
@ -31,18 +31,28 @@ enum
|
||||||
memregion_IO7,
|
memregion_IO7,
|
||||||
memregion_Wifi,
|
memregion_Wifi,
|
||||||
memregion_VWRAM,
|
memregion_VWRAM,
|
||||||
|
|
||||||
|
// DSi
|
||||||
|
memregion_BIOS9DSi,
|
||||||
|
memregion_BIOS7DSi,
|
||||||
|
memregion_NewSharedWRAM_A,
|
||||||
|
memregion_NewSharedWRAM_B,
|
||||||
|
memregion_NewSharedWRAM_C,
|
||||||
|
|
||||||
memregions_Count
|
memregions_Count
|
||||||
};
|
};
|
||||||
|
|
||||||
int ClassifyAddress9(u32 addr);
|
int ClassifyAddress9(u32 addr);
|
||||||
int ClassifyAddress7(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 RemapDTCM(u32 newBase, u32 newSize);
|
||||||
void RemapSWRAM();
|
void RemapSWRAM();
|
||||||
|
void RemapNWRAM(int num);
|
||||||
|
|
||||||
void SetCodeProtection(int region, u32 offset, bool protect);
|
void SetCodeProtection(int region, u32 offset, bool protect);
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,12 @@ const int RegisterCache<Compiler, X64Reg>::NativeRegsAvailable =
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
const BitSet32 CallerSavedPushRegs({R10, R11});
|
||||||
|
#else
|
||||||
|
const BitSet32 CallerSavedPushRegs({R9, R10, R11});
|
||||||
|
#endif
|
||||||
|
|
||||||
void Compiler::PushRegs(bool saveHiRegs)
|
void Compiler::PushRegs(bool saveHiRegs)
|
||||||
{
|
{
|
||||||
BitSet32 loadedRegs(RegCache.LoadedRegs);
|
BitSet32 loadedRegs(RegCache.LoadedRegs);
|
||||||
|
@ -301,6 +307,107 @@ Compiler::Compiler()
|
||||||
RET();
|
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
|
// move the region forward to prevent overwriting the generated functions
|
||||||
CodeMemSize -= GetWritableCodePtr() - ResetStart;
|
CodeMemSize -= GetWritableCodePtr() - ResetStart;
|
||||||
ResetStart = GetWritableCodePtr();
|
ResetStart = GetWritableCodePtr();
|
||||||
|
@ -500,6 +607,8 @@ void Compiler::Reset()
|
||||||
|
|
||||||
NearCode = NearStart;
|
NearCode = NearStart;
|
||||||
FarCode = FarStart;
|
FarCode = FarStart;
|
||||||
|
|
||||||
|
LoadStorePatches.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Compiler::IsJITFault(u64 addr)
|
bool Compiler::IsJITFault(u64 addr)
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
#include "../ARMJIT_Internal.h"
|
#include "../ARMJIT_Internal.h"
|
||||||
#include "../ARMJIT_RegisterCache.h"
|
#include "../ARMJIT_RegisterCache.h"
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace ARMJIT
|
namespace ARMJIT
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -18,6 +20,13 @@ const Gen::X64Reg RSCRATCH2 = Gen::EDX;
|
||||||
const Gen::X64Reg RSCRATCH3 = Gen::ECX;
|
const Gen::X64Reg RSCRATCH3 = Gen::ECX;
|
||||||
const Gen::X64Reg RSCRATCH4 = Gen::R8;
|
const Gen::X64Reg RSCRATCH4 = Gen::R8;
|
||||||
|
|
||||||
|
struct LoadStorePatch
|
||||||
|
{
|
||||||
|
void* PatchFunc;
|
||||||
|
s16 Offset;
|
||||||
|
u16 Size;
|
||||||
|
};
|
||||||
|
|
||||||
struct Op2
|
struct Op2
|
||||||
{
|
{
|
||||||
Op2()
|
Op2()
|
||||||
|
@ -211,6 +220,11 @@ public:
|
||||||
u8* NearStart;
|
u8* NearStart;
|
||||||
u8* FarStart;
|
u8* FarStart;
|
||||||
|
|
||||||
|
void* PatchedStoreFuncs[2][2][3][16];
|
||||||
|
void* PatchedLoadFuncs[2][2][3][2][16];
|
||||||
|
|
||||||
|
std::unordered_map<u8*, LoadStorePatch> LoadStorePatches;
|
||||||
|
|
||||||
u8* ResetStart;
|
u8* ResetStart;
|
||||||
u32 CodeMemSize;
|
u32 CodeMemSize;
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,30 @@ int squeezePointer(T* ptr)
|
||||||
|
|
||||||
s32 Compiler::RewriteMemAccess(u64 pc)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flags & memop_Store)
|
||||||
{
|
{
|
||||||
if (flags & memop_Store)
|
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);
|
||||||
|
|
||||||
|
OpArg rnMapped = MapReg(rn);
|
||||||
|
if (Thumb && rn == 15)
|
||||||
|
rnMapped = Imm32(R15 & ~0x2);
|
||||||
|
|
||||||
|
X64Reg finalAddr = RSCRATCH3;
|
||||||
|
if (flags & memop_Post)
|
||||||
|
{
|
||||||
|
MOV(32, R(RSCRATCH3), rnMapped);
|
||||||
|
|
||||||
|
finalAddr = rnMapped.GetSimpleReg();
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
Comp_AddCycles_CD();
|
LEA(32, finalAddr,
|
||||||
|
MComplex(rnMapped.GetSimpleReg(), rm.GetSimpleReg(), 1 << op2.Reg.Amount, 0));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Comp_AddCycles_CDI();
|
bool throwAway;
|
||||||
}
|
OpArg offset =
|
||||||
|
Comp_RegShiftImm(op2.Reg.Op, op2.Reg.Amount, rm, false, throwAway);
|
||||||
|
|
||||||
bool addrIsStatic = Config::JIT_LiteralOptimisations
|
if (flags & memop_SubtractOffset)
|
||||||
&& 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);
|
|
||||||
|
|
||||||
X64Reg finalAddr = RSCRATCH3;
|
|
||||||
if (flags & memop_Post)
|
|
||||||
{
|
{
|
||||||
MOV(32, R(RSCRATCH3), rnMapped);
|
if (R(finalAddr) != rnMapped)
|
||||||
|
MOV(32, R(finalAddr), rnMapped);
|
||||||
finalAddr = rnMapped.GetSimpleReg();
|
if (!offset.IsZero())
|
||||||
}
|
SUB(32, R(finalAddr), offset);
|
||||||
|
|
||||||
if (op2.IsImm)
|
|
||||||
{
|
|
||||||
MOV_sum(32, finalAddr, rnMapped, Imm32(op2.Imm * ((flags & memop_SubtractOffset) ? -1 : 1)));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
MOV_sum(32, finalAddr, rnMapped, offset);
|
||||||
OpArg rm = MapReg(op2.Reg.Reg);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!(flags & memop_SubtractOffset) && rm.IsSimpleReg() && rnMapped.IsSimpleReg()
|
if ((flags & memop_Writeback) && !(flags & memop_Post))
|
||||||
&& op2.Reg.Op == 0 && op2.Reg.Amount > 0 && op2.Reg.Amount <= 3)
|
MOV(32, rnMapped, R(finalAddr));
|
||||||
{
|
|
||||||
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)
|
u32 expectedTarget = Num == 0
|
||||||
{
|
? ARMJIT_Memory::ClassifyAddress9(CurInstr.DataRegion)
|
||||||
if (R(finalAddr) != rnMapped)
|
: ARMJIT_Memory::ClassifyAddress7(CurInstr.DataRegion);
|
||||||
MOV(32, R(finalAddr), rnMapped);
|
|
||||||
if (!offset.IsZero())
|
|
||||||
SUB(32, R(finalAddr), offset);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
MOV_sum(32, finalAddr, rnMapped, offset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((flags & memop_Writeback) && !(flags & memop_Post))
|
if (Config::JIT_FastMemory && ((!Thumb && CurInstr.Cond() != 0xE) || ARMJIT_Memory::IsFastmemCompatible(expectedTarget)))
|
||||||
MOV(32, rnMapped, R(finalAddr));
|
{
|
||||||
|
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()];
|
||||||
|
|
||||||
|
assert(patch.PatchFunc != NULL);
|
||||||
|
|
||||||
|
MOV(64, R(RSCRATCH), ImmPtr(Num == 0 ? ARMJIT_Memory::FastMem9Start : ARMJIT_Memory::FastMem7Start));
|
||||||
|
|
||||||
|
X64Reg maskedAddr = RSCRATCH3;
|
||||||
|
if (size > 8)
|
||||||
|
{
|
||||||
|
maskedAddr = RSCRATCH2;
|
||||||
|
MOV(32, R(RSCRATCH2), R(RSCRATCH3));
|
||||||
|
AND(32, R(RSCRATCH2), Imm8(addressMask));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*int expectedTarget = Num == 0
|
u8* memopLoadStoreLocation = GetWritableCodePtr();
|
||||||
? ClassifyAddress9(addrIsStatic ? staticAddress : CurInstr.DataRegion)
|
if (flags & memop_Store)
|
||||||
: ClassifyAddress7(addrIsStatic ? staticAddress : CurInstr.DataRegion);
|
|
||||||
if (CurInstr.Cond() < 0xE)
|
|
||||||
expectedTarget = memregion_Other;
|
|
||||||
|
|
||||||
bool compileFastPath = false, compileSlowPath = !addrIsStatic || (flags & memop_Store);
|
|
||||||
|
|
||||||
switch (expectedTarget)
|
|
||||||
{
|
{
|
||||||
case memregion_MainRAM:
|
MOV(size, MRegSum(RSCRATCH, maskedAddr), rdMapped);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (addrIsStatic && !compileFastPath)
|
|
||||||
{
|
{
|
||||||
compileFastPath = false;
|
if (flags & memop_SignExtend)
|
||||||
compileSlowPath = true;
|
MOVSX(32, size, rdMapped.GetSimpleReg(), MRegSum(RSCRATCH, maskedAddr));
|
||||||
}
|
|
||||||
|
|
||||||
if (addrIsStatic && compileSlowPath)
|
|
||||||
MOV(32, R(RSCRATCH3), Imm32(staticAddress));
|
|
||||||
*/
|
|
||||||
/*if (compileFastPath)
|
|
||||||
{
|
|
||||||
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 (expectedTarget == memregion_MainRAM || expectedTarget == memregion_WRAM7
|
|
||||||
|| expectedTarget == memregion_BIOS9)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
|
MOVZX(32, size, rdMapped.GetSimpleReg(), MRegSum(RSCRATCH, maskedAddr));
|
||||||
|
|
||||||
|
if (size == 32)
|
||||||
{
|
{
|
||||||
u32 maskedDataRegion;
|
AND(32, R(RSCRATCH3), Imm8(0x3));
|
||||||
|
SHL(32, R(RSCRATCH3), Imm8(3));
|
||||||
if (addrIsStatic)
|
ROR_(32, rdMapped, R(RSCRATCH3));
|
||||||
{
|
|
||||||
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);
|
|
||||||
|
|
||||||
if (flags & memop_Store)
|
|
||||||
{
|
|
||||||
PushRegs(false);
|
|
||||||
|
|
||||||
MOV(32, R(ABI_PARAM2), rdMapped);
|
|
||||||
|
|
||||||
ABI_CallFunction((void(*)())func);
|
|
||||||
|
|
||||||
PopRegs(false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((size == 32 && !(flags & memop_Store)))
|
|
||||||
{
|
|
||||||
if (addrIsStatic)
|
|
||||||
{
|
|
||||||
if (staticAddress & 0x3)
|
|
||||||
ROR_(32, rdMapped, Imm8((staticAddress & 0x3) * 8));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AND(32, R(RSCRATCH3), Imm8(0x3));
|
|
||||||
SHL(32, R(RSCRATCH3), Imm8(3));
|
|
||||||
ROR_(32, rdMapped, R(RSCRATCH3));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (compileSlowPath)
|
|
||||||
{
|
|
||||||
SwitchToFarCode();
|
|
||||||
SetJumpTarget(slowPath);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
if (true)
|
patch.Offset = memopStart - memopLoadStoreLocation;
|
||||||
|
patch.Size = GetWritableCodePtr() - memopStart;
|
||||||
|
|
||||||
|
assert(patch.Size >= 5);
|
||||||
|
|
||||||
|
LoadStorePatches[memopLoadStoreLocation] = patch;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PushRegs(false);
|
||||||
|
|
||||||
|
if (Num == 0)
|
||||||
{
|
{
|
||||||
PushRegs(false);
|
MOV(64, R(ABI_PARAM2), R(RCPU));
|
||||||
|
if (ABI_PARAM1 != RSCRATCH3)
|
||||||
if (Num == 0)
|
MOV(32, R(ABI_PARAM1), R(RSCRATCH3));
|
||||||
|
if (flags & memop_Store)
|
||||||
{
|
{
|
||||||
MOV(64, R(ABI_PARAM2), R(RCPU));
|
MOV(32, R(ABI_PARAM3), rdMapped);
|
||||||
if (ABI_PARAM1 != RSCRATCH3)
|
|
||||||
MOV(32, R(ABI_PARAM1), R(RSCRATCH3));
|
|
||||||
if (flags & memop_Store)
|
|
||||||
{
|
|
||||||
MOV(32, R(ABI_PARAM3), rdMapped);
|
|
||||||
|
|
||||||
switch (size)
|
switch (size | NDS::ConsoleType)
|
||||||
{
|
|
||||||
case 32: CALL((void*)&SlowWrite9<u32>); break;
|
|
||||||
case 16: CALL((void*)&SlowWrite9<u16>); break;
|
|
||||||
case 8: CALL((void*)&SlowWrite9<u8>); break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
switch (size)
|
case 32: CALL((void*)&SlowWrite9<u32, 0>); break;
|
||||||
{
|
case 16: CALL((void*)&SlowWrite9<u16, 0>); break;
|
||||||
case 32: CALL((void*)&SlowRead9<u32>); break;
|
case 8: CALL((void*)&SlowWrite9<u8, 0>); break;
|
||||||
case 16: CALL((void*)&SlowRead9<u16>); break;
|
case 33: CALL((void*)&SlowWrite9<u32, 1>); break;
|
||||||
case 8: CALL((void*)&SlowRead9<u8>); break;
|
case 17: CALL((void*)&SlowWrite9<u16, 1>); break;
|
||||||
}
|
case 9: CALL((void*)&SlowWrite9<u8, 1>); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (ABI_PARAM1 != RSCRATCH3)
|
switch (size | NDS::ConsoleType)
|
||||||
MOV(32, R(ABI_PARAM1), R(RSCRATCH3));
|
|
||||||
if (flags & memop_Store)
|
|
||||||
{
|
{
|
||||||
MOV(32, R(ABI_PARAM2), rdMapped);
|
case 32: CALL((void*)&SlowRead9<u32, 0>); break;
|
||||||
|
case 16: CALL((void*)&SlowRead9<u16, 0>); break;
|
||||||
switch (size)
|
case 8: CALL((void*)&SlowRead9<u8, 0>); break;
|
||||||
{
|
case 33: CALL((void*)&SlowRead9<u32, 1>); break;
|
||||||
case 32: CALL((void*)&SlowWrite7<u32>); break;
|
case 17: CALL((void*)&SlowRead9<u16, 1>); break;
|
||||||
case 16: CALL((void*)&SlowWrite7<u16>); break;
|
case 9: CALL((void*)&SlowRead9<u8, 1>); 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
else
|
||||||
if (compileFastPath && compileSlowPath)
|
|
||||||
{
|
{
|
||||||
FixupBranch ret = J(true);
|
if (ABI_PARAM1 != RSCRATCH3)
|
||||||
SwitchToNearCode();
|
MOV(32, R(ABI_PARAM1), R(RSCRATCH3));
|
||||||
SetJumpTarget(ret);
|
if (flags & memop_Store)
|
||||||
}*/
|
|
||||||
|
|
||||||
if (!(flags & memop_Store) && rd == 15)
|
|
||||||
{
|
|
||||||
if (size < 32)
|
|
||||||
printf("!!! LDR <32 bit PC %08X %x\n", R15, CurInstr.Instr);
|
|
||||||
{
|
{
|
||||||
if (Num == 1)
|
MOV(32, R(ABI_PARAM2), rdMapped);
|
||||||
AND(32, rdMapped, Imm8(0xFE)); // immediate is sign extended
|
|
||||||
Comp_JumpTo(rdMapped.GetSimpleReg());
|
switch (size | NDS::ConsoleType)
|
||||||
|
{
|
||||||
|
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
|
||||||
|
{
|
||||||
|
switch (size | NDS::ConsoleType)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (!(flags & memop_Store))
|
||||||
|
{
|
||||||
|
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 (size < 32)
|
||||||
|
printf("!!! LDR <32 bit PC %08X %x\n", R15, CurInstr.Instr);
|
||||||
|
{
|
||||||
|
if (Num == 1)
|
||||||
|
{
|
||||||
|
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;
|
int flags = 0;
|
||||||
if (store)
|
if (store)
|
||||||
flags |= memop_Store;
|
flags |= memop_Store;
|
||||||
if (decrement)
|
if (decrement && preinc)
|
||||||
flags |= memop_SubtractOffset;
|
flags |= memop_SubtractOffset;
|
||||||
Op2 offset = preinc ? Op2(4) : Op2(0);
|
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);
|
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
|
int expectedTarget = Num == 0
|
||||||
? ClassifyAddress9(CurInstr.DataRegion)
|
? ARMJIT_Memory::ClassifyAddress9(CurInstr.DataRegion)
|
||||||
: ClassifyAddress7(CurInstr.DataRegion);
|
: ARMJIT_Memory::ClassifyAddress7(CurInstr.DataRegion);
|
||||||
if (usermode || CurInstr.Cond() < 0xE)
|
|
||||||
expectedTarget = memregion_Other;
|
|
||||||
|
|
||||||
bool compileFastPath = false;
|
|
||||||
|
|
||||||
switch (expectedTarget)
|
|
||||||
{
|
|
||||||
case memregion_DTCM:
|
|
||||||
case memregion_MainRAM:
|
|
||||||
case memregion_SWRAM9:
|
|
||||||
case memregion_SWRAM7:
|
|
||||||
case memregion_WRAM7:
|
|
||||||
compileFastPath = true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
if (!store)
|
if (!store)
|
||||||
Comp_AddCycles_CDI();
|
Comp_AddCycles_CDI();
|
||||||
else
|
else
|
||||||
Comp_AddCycles_CD();
|
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)
|
if (decrement)
|
||||||
{
|
MOV_sum(32, RSCRATCH4, MapReg(rn), Imm32(-regsCount * 4 + (preinc ? 0 : 4)));
|
||||||
MOV_sum(32, RSCRATCH4, MapReg(rn), Imm32(-regsCount * 4));
|
|
||||||
preinc ^= true;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
MOV(32, R(RSCRATCH4), MapReg(rn));
|
MOV_sum(32, RSCRATCH4, MapReg(rn), Imm32(preinc ? 4 : 0));
|
||||||
/*
|
|
||||||
if (compileFastPath)
|
if (compileFastPath)
|
||||||
{
|
{
|
||||||
assert(!usermode);
|
AND(32, R(RSCRATCH4), Imm8(~3));
|
||||||
|
|
||||||
MOV(32, R(RSCRATCH), R(RSCRATCH4));
|
u8* fastPathStart = GetWritableCodePtr();
|
||||||
SHR(32, R(RSCRATCH), Imm8(9));
|
u8* firstLoadStoreAddr;
|
||||||
|
|
||||||
if (store)
|
bool firstLoadStore = true;
|
||||||
{
|
|
||||||
CMP(8, MDisp(RSCRATCH, squeezePointer(Num == 0 ? MemoryStatus9 : MemoryStatus7)), Imm8(expectedTarget));
|
MOV(64, R(RSCRATCH2), ImmPtr(Num == 0 ? ARMJIT_Memory::FastMem9Start : ARMJIT_Memory::FastMem7Start));
|
||||||
}
|
ADD(64, R(RSCRATCH2), R(RSCRATCH4));
|
||||||
else
|
MOV(32, R(RSCRATCH3), R(RSCRATCH4));
|
||||||
{
|
|
||||||
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);
|
|
||||||
|
|
||||||
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;
|
u32 offset = 0;
|
||||||
for (int reg : regs)
|
for (int reg : regs)
|
||||||
{
|
{
|
||||||
if (preinc)
|
if (firstLoadStore)
|
||||||
offset += 4;
|
firstLoadStoreAddr = GetWritableCodePtr();
|
||||||
OpArg mem = MDisp(RSCRATCH4, offset);
|
|
||||||
|
OpArg mem = MDisp(RSCRATCH2, offset);
|
||||||
if (store)
|
if (store)
|
||||||
{
|
{
|
||||||
if (RegCache.LoadedRegs & (1 << reg))
|
if (RegCache.LoadedRegs & (1 << reg))
|
||||||
|
@ -580,6 +403,8 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LoadReg(reg, RSCRATCH);
|
LoadReg(reg, RSCRATCH);
|
||||||
|
if (firstLoadStore)
|
||||||
|
firstLoadStoreAddr = GetWritableCodePtr();
|
||||||
MOV(32, mem, R(RSCRATCH));
|
MOV(32, mem, R(RSCRATCH));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -595,13 +420,19 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc
|
||||||
SaveReg(reg, RSCRATCH);
|
SaveReg(reg, RSCRATCH);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!preinc)
|
offset += 4;
|
||||||
offset += 4;
|
|
||||||
|
firstLoadStore = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LoadStorePatch patch;
|
||||||
|
patch.Size = GetWritableCodePtr() - fastPathStart;
|
||||||
|
patch.Offset = fastPathStart - firstLoadStoreAddr;
|
||||||
SwitchToFarCode();
|
SwitchToFarCode();
|
||||||
SetJumpTarget(slowPath);
|
patch.PatchFunc = GetWritableCodePtr();
|
||||||
}*/
|
|
||||||
|
LoadStorePatches[firstLoadStoreAddr] = patch;
|
||||||
|
}
|
||||||
|
|
||||||
if (!store)
|
if (!store)
|
||||||
{
|
{
|
||||||
|
@ -618,12 +449,12 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc
|
||||||
if (Num == 0)
|
if (Num == 0)
|
||||||
MOV(64, R(ABI_PARAM4), R(RCPU));
|
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 0: CALL((void*)&SlowBlockTransfer9<false, 0>); break;
|
||||||
case 1: CALL((void*)&SlowBlockTransfer9<true, false>); break;
|
case 1: CALL((void*)&SlowBlockTransfer9<false, 1>); break;
|
||||||
case 2: CALL((void*)&SlowBlockTransfer7<false, false>); break;
|
case 2: CALL((void*)&SlowBlockTransfer7<false, 0>); break;
|
||||||
case 3: CALL((void*)&SlowBlockTransfer7<true, false>); break;
|
case 3: CALL((void*)&SlowBlockTransfer7<false, 1>); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
PopRegs(false);
|
PopRegs(false);
|
||||||
|
@ -715,25 +546,24 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc
|
||||||
if (Num == 0)
|
if (Num == 0)
|
||||||
MOV(64, R(ABI_PARAM4), R(RCPU));
|
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 0: CALL((void*)&SlowBlockTransfer9<true, 0>); break;
|
||||||
case 1: CALL((void*)&SlowBlockTransfer9<true, true>); break;
|
case 1: CALL((void*)&SlowBlockTransfer9<true, 1>); break;
|
||||||
case 2: CALL((void*)&SlowBlockTransfer7<false, true>); break;
|
case 2: CALL((void*)&SlowBlockTransfer7<true, 0>); break;
|
||||||
case 3: CALL((void*)&SlowBlockTransfer7<true, true>); break;
|
case 3: CALL((void*)&SlowBlockTransfer7<true, 1>); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ADD(64, R(RSP), stackAlloc <= INT8_MAX ? Imm8(stackAlloc) : Imm32(stackAlloc));
|
ADD(64, R(RSP), stackAlloc <= INT8_MAX ? Imm8(stackAlloc) : Imm32(stackAlloc));
|
||||||
|
|
||||||
PopRegs(false);
|
PopRegs(false);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
if (compileFastPath)
|
if (compileFastPath)
|
||||||
{
|
{
|
||||||
FixupBranch ret = J(true);
|
RET();
|
||||||
SwitchToNearCode();
|
SwitchToNearCode();
|
||||||
SetJumpTarget(ret);
|
}
|
||||||
}*/
|
|
||||||
|
|
||||||
if (!store && regs[15])
|
if (!store && regs[15])
|
||||||
{
|
{
|
||||||
|
|
21
src/CP15.cpp
21
src/CP15.cpp
|
@ -608,6 +608,27 @@ void ARMv5::CP15Write(u32 id, u32 val)
|
||||||
ITCMSetting = val;
|
ITCMSetting = val;
|
||||||
UpdateITCMSetting();
|
UpdateITCMSetting();
|
||||||
return;
|
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)
|
if ((id&0xF00)!=0x700)
|
||||||
|
|
|
@ -40,14 +40,7 @@ char DSiNANDPath[1024];
|
||||||
#ifdef JIT_ENABLED
|
#ifdef JIT_ENABLED
|
||||||
int JIT_Enable = false;
|
int JIT_Enable = false;
|
||||||
int JIT_MaxBlockSize = 32;
|
int JIT_MaxBlockSize = 32;
|
||||||
int JIT_BrancheOptimisations = 2;
|
int JIT_BranchOptimisations = 2;
|
||||||
int JIT_LiteralOptimisations = true;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef JIT_ENABLED
|
|
||||||
int JIT_Enable = false;
|
|
||||||
int JIT_MaxBlockSize = 32;
|
|
||||||
int JIT_BrancheOptimisations = true;
|
|
||||||
int JIT_LiteralOptimisations = true;
|
int JIT_LiteralOptimisations = true;
|
||||||
int JIT_FastMemory = true;
|
int JIT_FastMemory = true;
|
||||||
#endif
|
#endif
|
||||||
|
@ -66,16 +59,9 @@ ConfigEntry ConfigFile[] =
|
||||||
#ifdef JIT_ENABLED
|
#ifdef JIT_ENABLED
|
||||||
{"JIT_Enable", 0, &JIT_Enable, 0, NULL, 0},
|
{"JIT_Enable", 0, &JIT_Enable, 0, NULL, 0},
|
||||||
{"JIT_MaxBlockSize", 0, &JIT_MaxBlockSize, 32, NULL, 0},
|
{"JIT_MaxBlockSize", 0, &JIT_MaxBlockSize, 32, NULL, 0},
|
||||||
{"JIT_BranchOptimisations", 0, &JIT_BrancheOptimisations, 2, NULL, 0},
|
{"JIT_BranchOptimisations", 0, &JIT_BranchOptimisations, 2, NULL, 0},
|
||||||
{"JIT_LiteralOptimisations", 0, &JIT_LiteralOptimisations, 1, NULL, 0},
|
{"JIT_LiteralOptimisations", 0, &JIT_LiteralOptimisations, 1, NULL, 0},
|
||||||
#endif
|
{"JIT_FastMemory", 0, &JIT_FastMemory, 1, NULL, 0},
|
||||||
|
|
||||||
#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_LiteralOptimisations", 0, &JIT_LiteralOptimisations, 1, NULL, 0},
|
|
||||||
{"JIT_FastMem", 0, &JIT_FastMemory, 1, NULL, 0},
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
{"", -1, NULL, 0, NULL, 0}
|
{"", -1, NULL, 0, NULL, 0}
|
||||||
|
|
|
@ -54,14 +54,7 @@ extern char DSiNANDPath[1024];
|
||||||
#ifdef JIT_ENABLED
|
#ifdef JIT_ENABLED
|
||||||
extern int JIT_Enable;
|
extern int JIT_Enable;
|
||||||
extern int JIT_MaxBlockSize;
|
extern int JIT_MaxBlockSize;
|
||||||
extern int JIT_BrancheOptimisations;
|
extern int JIT_BranchOptimisations;
|
||||||
extern int JIT_LiteralOptimisations;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef JIT_ENABLED
|
|
||||||
extern int JIT_Enable;
|
|
||||||
extern int JIT_MaxBlockSize;
|
|
||||||
extern int JIT_BrancheOptimisations;
|
|
||||||
extern int JIT_LiteralOptimisations;
|
extern int JIT_LiteralOptimisations;
|
||||||
extern int JIT_FastMemory;
|
extern int JIT_FastMemory;
|
||||||
#endif
|
#endif
|
||||||
|
|
167
src/DSi.cpp
167
src/DSi.cpp
|
@ -26,6 +26,11 @@
|
||||||
#include "NDSCart.h"
|
#include "NDSCart.h"
|
||||||
#include "Platform.h"
|
#include "Platform.h"
|
||||||
|
|
||||||
|
#ifdef JIT_ENABLED
|
||||||
|
#include "ARMJIT.h"
|
||||||
|
#include "ARMJIT_Memory.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "DSi_NDMA.h"
|
#include "DSi_NDMA.h"
|
||||||
#include "DSi_I2C.h"
|
#include "DSi_I2C.h"
|
||||||
#include "DSi_SD.h"
|
#include "DSi_SD.h"
|
||||||
|
@ -34,15 +39,6 @@
|
||||||
#include "tiny-AES-c/aes.hpp"
|
#include "tiny-AES-c/aes.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace NDS
|
|
||||||
{
|
|
||||||
|
|
||||||
extern ARMv5* ARM9;
|
|
||||||
extern ARMv4* ARM7;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
namespace DSi
|
namespace DSi
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -59,9 +55,9 @@ u8 ARM7iBIOS[0x10000];
|
||||||
|
|
||||||
u32 MBK[2][9];
|
u32 MBK[2][9];
|
||||||
|
|
||||||
u8 NWRAM_A[0x40000];
|
u8* NWRAM_A;
|
||||||
u8 NWRAM_B[0x40000];
|
u8* NWRAM_B;
|
||||||
u8 NWRAM_C[0x40000];
|
u8* NWRAM_C;
|
||||||
|
|
||||||
u8* NWRAMMap_A[2][4];
|
u8* NWRAMMap_A[2][4];
|
||||||
u8* NWRAMMap_B[3][8];
|
u8* NWRAMMap_B[3][8];
|
||||||
|
@ -86,6 +82,12 @@ u8 ARM7Init[0x3C00];
|
||||||
|
|
||||||
bool Init()
|
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_I2C::Init()) return false;
|
||||||
if (!DSi_AES::Init()) return false;
|
if (!DSi_AES::Init()) return false;
|
||||||
|
|
||||||
|
@ -106,6 +108,12 @@ bool Init()
|
||||||
|
|
||||||
void DeInit()
|
void DeInit()
|
||||||
{
|
{
|
||||||
|
#ifndef JIT_ENABLED
|
||||||
|
delete[] NWRAM_A;
|
||||||
|
delete[] NWRAM_B;
|
||||||
|
delete[] NWRAM_C;
|
||||||
|
#endif
|
||||||
|
|
||||||
DSi_I2C::DeInit();
|
DSi_I2C::DeInit();
|
||||||
DSi_AES::DeInit();
|
DSi_AES::DeInit();
|
||||||
|
|
||||||
|
@ -176,7 +184,12 @@ void SoftReset()
|
||||||
NDS::ARM9->Reset();
|
NDS::ARM9->Reset();
|
||||||
NDS::ARM7->Reset();
|
NDS::ARM7->Reset();
|
||||||
|
|
||||||
|
NDS::ARM9->CP15Reset();
|
||||||
|
|
||||||
memcpy(NDS::ARM9->ITCM, ITCMInit, 0x8000);
|
memcpy(NDS::ARM9->ITCM, ITCMInit, 0x8000);
|
||||||
|
#ifdef JIT_ENABLED
|
||||||
|
ARMJIT::CheckAndInvalidateITCM();
|
||||||
|
#endif
|
||||||
|
|
||||||
DSi_AES::Reset();
|
DSi_AES::Reset();
|
||||||
|
|
||||||
|
@ -274,9 +287,9 @@ bool LoadNAND()
|
||||||
{
|
{
|
||||||
printf("Loading DSi NAND\n");
|
printf("Loading DSi NAND\n");
|
||||||
|
|
||||||
memset(NWRAM_A, 0, 0x40000);
|
memset(NWRAM_A, 0, NWRAMSize);
|
||||||
memset(NWRAM_B, 0, 0x40000);
|
memset(NWRAM_B, 0, NWRAMSize);
|
||||||
memset(NWRAM_C, 0, 0x40000);
|
memset(NWRAM_C, 0, NWRAMSize);
|
||||||
|
|
||||||
memset(MBK, 0, sizeof(MBK));
|
memset(MBK, 0, sizeof(MBK));
|
||||||
memset(NWRAMMap_A, 0, sizeof(NWRAMMap_A));
|
memset(NWRAMMap_A, 0, sizeof(NWRAMMap_A));
|
||||||
|
@ -527,6 +540,8 @@ void MapNWRAM_A(u32 num, u8 val)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ARMJIT_Memory::RemapNWRAM(0);
|
||||||
|
|
||||||
int mbkn = 0, mbks = 8*num;
|
int mbkn = 0, mbks = 8*num;
|
||||||
|
|
||||||
u8 oldval = (MBK[0][mbkn] >> mbks) & 0xFF;
|
u8 oldval = (MBK[0][mbkn] >> mbks) & 0xFF;
|
||||||
|
@ -558,6 +573,8 @@ void MapNWRAM_B(u32 num, u8 val)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ARMJIT_Memory::RemapNWRAM(1);
|
||||||
|
|
||||||
int mbkn = 1+(num>>2), mbks = 8*(num&3);
|
int mbkn = 1+(num>>2), mbks = 8*(num&3);
|
||||||
|
|
||||||
u8 oldval = (MBK[0][mbkn] >> mbks) & 0xFF;
|
u8 oldval = (MBK[0][mbkn] >> mbks) & 0xFF;
|
||||||
|
@ -593,6 +610,8 @@ void MapNWRAM_C(u32 num, u8 val)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ARMJIT_Memory::RemapNWRAM(2);
|
||||||
|
|
||||||
int mbkn = 3+(num>>2), mbks = 8*(num&3);
|
int mbkn = 3+(num>>2), mbks = 8*(num&3);
|
||||||
|
|
||||||
u8 oldval = (MBK[0][mbkn] >> mbks) & 0xFF;
|
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];
|
u32 oldval = MBK[cpu][5+num];
|
||||||
if (oldval == val) return;
|
if (oldval == val) return;
|
||||||
|
|
||||||
|
ARMJIT_Memory::RemapNWRAM(num);
|
||||||
|
|
||||||
MBK[cpu][5+num] = val;
|
MBK[cpu][5+num] = val;
|
||||||
|
|
||||||
// TODO: what happens when the ranges are 'out of range'????
|
// 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])
|
if (addr >= NWRAMStart[0][0] && addr < NWRAMEnd[0][0])
|
||||||
{
|
{
|
||||||
u8* ptr = NWRAMMap_A[0][(addr >> 16) & NWRAMMask[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;
|
return;
|
||||||
}
|
}
|
||||||
if (addr >= NWRAMStart[0][1] && addr < NWRAMEnd[0][1])
|
if (addr >= NWRAMStart[0][1] && addr < NWRAMEnd[0][1])
|
||||||
{
|
{
|
||||||
u8* ptr = NWRAMMap_B[0][(addr >> 15) & NWRAMMask[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;
|
return;
|
||||||
}
|
}
|
||||||
if (addr >= NWRAMStart[0][2] && addr < NWRAMEnd[0][2])
|
if (addr >= NWRAMStart[0][2] && addr < NWRAMEnd[0][2])
|
||||||
{
|
{
|
||||||
u8* ptr = NWRAMMap_C[0][(addr >> 15) & NWRAMMask[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;
|
||||||
}
|
}
|
||||||
return NDS::ARM9Write8(addr, val);
|
return NDS::ARM9Write8(addr, val);
|
||||||
|
@ -859,19 +892,31 @@ void ARM9Write16(u32 addr, u16 val)
|
||||||
if (addr >= NWRAMStart[0][0] && addr < NWRAMEnd[0][0])
|
if (addr >= NWRAMStart[0][0] && addr < NWRAMEnd[0][0])
|
||||||
{
|
{
|
||||||
u8* ptr = NWRAMMap_A[0][(addr >> 16) & NWRAMMask[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;
|
return;
|
||||||
}
|
}
|
||||||
if (addr >= NWRAMStart[0][1] && addr < NWRAMEnd[0][1])
|
if (addr >= NWRAMStart[0][1] && addr < NWRAMEnd[0][1])
|
||||||
{
|
{
|
||||||
u8* ptr = NWRAMMap_B[0][(addr >> 15) & NWRAMMask[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;
|
return;
|
||||||
}
|
}
|
||||||
if (addr >= NWRAMStart[0][2] && addr < NWRAMEnd[0][2])
|
if (addr >= NWRAMStart[0][2] && addr < NWRAMEnd[0][2])
|
||||||
{
|
{
|
||||||
u8* ptr = NWRAMMap_C[0][(addr >> 15) & NWRAMMask[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;
|
||||||
}
|
}
|
||||||
return NDS::ARM9Write16(addr, val);
|
return NDS::ARM9Write16(addr, val);
|
||||||
|
@ -892,19 +937,31 @@ void ARM9Write32(u32 addr, u32 val)
|
||||||
if (addr >= NWRAMStart[0][0] && addr < NWRAMEnd[0][0])
|
if (addr >= NWRAMStart[0][0] && addr < NWRAMEnd[0][0])
|
||||||
{
|
{
|
||||||
u8* ptr = NWRAMMap_A[0][(addr >> 16) & NWRAMMask[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;
|
return;
|
||||||
}
|
}
|
||||||
if (addr >= NWRAMStart[0][1] && addr < NWRAMEnd[0][1])
|
if (addr >= NWRAMStart[0][1] && addr < NWRAMEnd[0][1])
|
||||||
{
|
{
|
||||||
u8* ptr = NWRAMMap_B[0][(addr >> 15) & NWRAMMask[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;
|
return;
|
||||||
}
|
}
|
||||||
if (addr >= NWRAMStart[0][2] && addr < NWRAMEnd[0][2])
|
if (addr >= NWRAMStart[0][2] && addr < NWRAMEnd[0][2])
|
||||||
{
|
{
|
||||||
u8* ptr = NWRAMMap_C[0][(addr >> 15) & NWRAMMask[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;
|
||||||
}
|
}
|
||||||
return NDS::ARM9Write32(addr, val);
|
return NDS::ARM9Write32(addr, val);
|
||||||
|
@ -1085,19 +1142,37 @@ void ARM7Write8(u32 addr, u8 val)
|
||||||
if (addr >= NWRAMStart[1][0] && addr < NWRAMEnd[1][0])
|
if (addr >= NWRAMStart[1][0] && addr < NWRAMEnd[1][0])
|
||||||
{
|
{
|
||||||
u8* ptr = NWRAMMap_A[1][(addr >> 16) & NWRAMMask[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;
|
return;
|
||||||
}
|
}
|
||||||
if (addr >= NWRAMStart[1][1] && addr < NWRAMEnd[1][1])
|
if (addr >= NWRAMStart[1][1] && addr < NWRAMEnd[1][1])
|
||||||
{
|
{
|
||||||
u8* ptr = NWRAMMap_B[1][(addr >> 15) & NWRAMMask[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;
|
return;
|
||||||
}
|
}
|
||||||
if (addr >= NWRAMStart[1][2] && addr < NWRAMEnd[1][2])
|
if (addr >= NWRAMStart[1][2] && addr < NWRAMEnd[1][2])
|
||||||
{
|
{
|
||||||
u8* ptr = NWRAMMap_C[1][(addr >> 15) & NWRAMMask[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;
|
||||||
}
|
}
|
||||||
return NDS::ARM7Write8(addr, val);
|
return NDS::ARM7Write8(addr, val);
|
||||||
|
@ -1118,19 +1193,31 @@ void ARM7Write16(u32 addr, u16 val)
|
||||||
if (addr >= NWRAMStart[1][0] && addr < NWRAMEnd[1][0])
|
if (addr >= NWRAMStart[1][0] && addr < NWRAMEnd[1][0])
|
||||||
{
|
{
|
||||||
u8* ptr = NWRAMMap_A[1][(addr >> 16) & NWRAMMask[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;
|
return;
|
||||||
}
|
}
|
||||||
if (addr >= NWRAMStart[1][1] && addr < NWRAMEnd[1][1])
|
if (addr >= NWRAMStart[1][1] && addr < NWRAMEnd[1][1])
|
||||||
{
|
{
|
||||||
u8* ptr = NWRAMMap_B[1][(addr >> 15) & NWRAMMask[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;
|
return;
|
||||||
}
|
}
|
||||||
if (addr >= NWRAMStart[1][2] && addr < NWRAMEnd[1][2])
|
if (addr >= NWRAMStart[1][2] && addr < NWRAMEnd[1][2])
|
||||||
{
|
{
|
||||||
u8* ptr = NWRAMMap_C[1][(addr >> 15) & NWRAMMask[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;
|
||||||
}
|
}
|
||||||
return NDS::ARM7Write16(addr, val);
|
return NDS::ARM7Write16(addr, val);
|
||||||
|
@ -1151,19 +1238,31 @@ void ARM7Write32(u32 addr, u32 val)
|
||||||
if (addr >= NWRAMStart[1][0] && addr < NWRAMEnd[1][0])
|
if (addr >= NWRAMStart[1][0] && addr < NWRAMEnd[1][0])
|
||||||
{
|
{
|
||||||
u8* ptr = NWRAMMap_A[1][(addr >> 16) & NWRAMMask[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;
|
return;
|
||||||
}
|
}
|
||||||
if (addr >= NWRAMStart[1][1] && addr < NWRAMEnd[1][1])
|
if (addr >= NWRAMStart[1][1] && addr < NWRAMEnd[1][1])
|
||||||
{
|
{
|
||||||
u8* ptr = NWRAMMap_B[1][(addr >> 15) & NWRAMMask[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;
|
return;
|
||||||
}
|
}
|
||||||
if (addr >= NWRAMStart[1][2] && addr < NWRAMEnd[1][2])
|
if (addr >= NWRAMStart[1][2] && addr < NWRAMEnd[1][2])
|
||||||
{
|
{
|
||||||
u8* ptr = NWRAMMap_C[1][(addr >> 15) & NWRAMMask[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;
|
||||||
}
|
}
|
||||||
return NDS::ARM7Write32(addr, val);
|
return NDS::ARM7Write32(addr, val);
|
||||||
|
@ -1521,7 +1620,7 @@ u8 ARM7IORead8(u32 addr)
|
||||||
case 0x04004501: return DSi_I2C::Cnt;
|
case 0x04004501: return DSi_I2C::Cnt;
|
||||||
|
|
||||||
case 0x04004D00: if (SCFG_BIOS & (1<<10)) return 0; return ConsoleID & 0xFF;
|
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 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 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;
|
case 0x04004D04: if (SCFG_BIOS & (1<<10)) return 0; return (ConsoleID >> 32) & 0xFF;
|
||||||
|
|
15
src/DSi.h
15
src/DSi.h
|
@ -25,6 +25,8 @@
|
||||||
namespace DSi
|
namespace DSi
|
||||||
{
|
{
|
||||||
|
|
||||||
|
extern u16 SCFG_BIOS;
|
||||||
|
|
||||||
extern u8 ARM9iBIOS[0x10000];
|
extern u8 ARM9iBIOS[0x10000];
|
||||||
extern u8 ARM7iBIOS[0x10000];
|
extern u8 ARM7iBIOS[0x10000];
|
||||||
|
|
||||||
|
@ -34,6 +36,19 @@ extern u64 ConsoleID;
|
||||||
extern DSi_SDHost* SDMMC;
|
extern DSi_SDHost* SDMMC;
|
||||||
extern DSi_SDHost* SDIO;
|
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();
|
bool Init();
|
||||||
void DeInit();
|
void DeInit();
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "DSi.h"
|
#include "DSi.h"
|
||||||
#include "DSi_I2C.h"
|
#include "DSi_I2C.h"
|
||||||
#include "DSi_Camera.h"
|
#include "DSi_Camera.h"
|
||||||
|
#include "ARM.h"
|
||||||
|
|
||||||
|
|
||||||
namespace DSi_BPTWL
|
namespace DSi_BPTWL
|
||||||
|
@ -108,7 +109,8 @@ void Write(u8 val, bool last)
|
||||||
printf("BPTWL: soft-reset\n");
|
printf("BPTWL: soft-reset\n");
|
||||||
val = 0; // checkme
|
val = 0; // checkme
|
||||||
// TODO: soft-reset might need to be scheduled later!
|
// 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;
|
CurPos = -1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
41
src/NDS.cpp
41
src/NDS.cpp
|
@ -32,8 +32,11 @@
|
||||||
#include "Wifi.h"
|
#include "Wifi.h"
|
||||||
#include "AREngine.h"
|
#include "AREngine.h"
|
||||||
#include "Platform.h"
|
#include "Platform.h"
|
||||||
|
|
||||||
|
#ifdef JIT_ENABLED
|
||||||
#include "ARMJIT.h"
|
#include "ARMJIT.h"
|
||||||
#include "ARMJIT_Memory.h"
|
#include "ARMJIT_Memory.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "DSi.h"
|
#include "DSi.h"
|
||||||
#include "DSi_SPI_TSC.h"
|
#include "DSi_SPI_TSC.h"
|
||||||
|
@ -173,7 +176,7 @@ bool Init()
|
||||||
#ifdef JIT_ENABLED
|
#ifdef JIT_ENABLED
|
||||||
ARMJIT::Init();
|
ARMJIT::Init();
|
||||||
#else
|
#else
|
||||||
MainRAM = new u8[MainRAMSize];
|
MainRAM = new u8[0x1000000];
|
||||||
ARM7WRAM = new u8[ARM7WRAMSize];
|
ARM7WRAM = new u8[ARM7WRAMSize];
|
||||||
SharedWRAM = new u8[SharedWRAMSize];
|
SharedWRAM = new u8[SharedWRAMSize];
|
||||||
#endif
|
#endif
|
||||||
|
@ -1837,7 +1840,7 @@ u8 ARM9Read8(u32 addr)
|
||||||
switch (addr & 0xFF000000)
|
switch (addr & 0xFF000000)
|
||||||
{
|
{
|
||||||
case 0x02000000:
|
case 0x02000000:
|
||||||
return *(u8*)&MainRAM[addr & (MainRAMSize - 1)];
|
return *(u8*)&MainRAM[addr & MainRAMMask];
|
||||||
|
|
||||||
case 0x03000000:
|
case 0x03000000:
|
||||||
if (SWRAM_ARM9.Mem)
|
if (SWRAM_ARM9.Mem)
|
||||||
|
@ -1902,7 +1905,7 @@ u16 ARM9Read16(u32 addr)
|
||||||
switch (addr & 0xFF000000)
|
switch (addr & 0xFF000000)
|
||||||
{
|
{
|
||||||
case 0x02000000:
|
case 0x02000000:
|
||||||
return *(u16*)&MainRAM[addr & (MainRAMSize - 1)];
|
return *(u16*)&MainRAM[addr & MainRAMMask];
|
||||||
|
|
||||||
case 0x03000000:
|
case 0x03000000:
|
||||||
if (SWRAM_ARM9.Mem)
|
if (SWRAM_ARM9.Mem)
|
||||||
|
@ -2031,16 +2034,13 @@ void ARM9Write8(u32 addr, u8 val)
|
||||||
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_MainRAM>(addr);
|
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_MainRAM>(addr);
|
||||||
#endif
|
#endif
|
||||||
*(u8*)&MainRAM[addr & MainRAMMask] = val;
|
*(u8*)&MainRAM[addr & MainRAMMask] = val;
|
||||||
#ifdef JIT_ENABLED
|
|
||||||
ARMJIT::InvalidateMainRAMIfNecessary(addr);
|
|
||||||
#endif
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x03000000:
|
case 0x03000000:
|
||||||
if (SWRAM_ARM9.Mem)
|
if (SWRAM_ARM9.Mem)
|
||||||
{
|
{
|
||||||
#ifdef JIT_ENABLED
|
#ifdef JIT_ENABLED
|
||||||
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_SWRAM>(addr);
|
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_SharedWRAM>(addr);
|
||||||
#endif
|
#endif
|
||||||
*(u8*)&SWRAM_ARM9.Mem[addr & SWRAM_ARM9.Mask] = val;
|
*(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);
|
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_MainRAM>(addr);
|
||||||
#endif
|
#endif
|
||||||
*(u16*)&MainRAM[addr & MainRAMMask] = val;
|
*(u16*)&MainRAM[addr & MainRAMMask] = val;
|
||||||
#ifdef JIT_ENABLED
|
|
||||||
ARMJIT::InvalidateMainRAMIfNecessary(addr);
|
|
||||||
#endif
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x03000000:
|
case 0x03000000:
|
||||||
if (SWRAM_ARM9.Mem)
|
if (SWRAM_ARM9.Mem)
|
||||||
{
|
{
|
||||||
#ifdef JIT_ENABLED
|
#ifdef JIT_ENABLED
|
||||||
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_SWRAM>(addr);
|
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_SharedWRAM>(addr);
|
||||||
#endif
|
#endif
|
||||||
*(u16*)&SWRAM_ARM9.Mem[addr & SWRAM_ARM9.Mask] = val;
|
*(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);
|
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_MainRAM>(addr);
|
||||||
#endif
|
#endif
|
||||||
*(u32*)&MainRAM[addr & MainRAMMask] = val;
|
*(u32*)&MainRAM[addr & MainRAMMask] = val;
|
||||||
#ifdef JIT_ENABLED
|
|
||||||
ARMJIT::InvalidateMainRAMIfNecessary(addr);
|
|
||||||
#endif
|
|
||||||
return ;
|
return ;
|
||||||
|
|
||||||
case 0x03000000:
|
case 0x03000000:
|
||||||
if (SWRAM_ARM9.Mem)
|
if (SWRAM_ARM9.Mem)
|
||||||
{
|
{
|
||||||
#ifdef JIT_ENABLED
|
#ifdef JIT_ENABLED
|
||||||
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_SWRAM>(addr);
|
ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_SharedWRAM>(addr);
|
||||||
#endif
|
#endif
|
||||||
*(u32*)&SWRAM_ARM9.Mem[addr & SWRAM_ARM9.Mask] = val;
|
*(u32*)&SWRAM_ARM9.Mem[addr & SWRAM_ARM9.Mask] = val;
|
||||||
}
|
}
|
||||||
|
@ -2235,7 +2229,7 @@ void ARM9Write32(u32 addr, u32 val)
|
||||||
return;
|
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)
|
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);
|
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_MainRAM>(addr);
|
||||||
#endif
|
#endif
|
||||||
*(u8*)&MainRAM[addr & MainRAMMask] = val;
|
*(u8*)&MainRAM[addr & MainRAMMask] = val;
|
||||||
#ifdef JIT_ENABLED
|
|
||||||
ARMJIT::InvalidateMainRAMIfNecessary(addr);
|
|
||||||
#endif
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x03000000:
|
case 0x03000000:
|
||||||
if (SWRAM_ARM7.Mem)
|
if (SWRAM_ARM7.Mem)
|
||||||
{
|
{
|
||||||
#ifdef JIT_ENABLED
|
#ifdef JIT_ENABLED
|
||||||
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_SWRAM>(addr);
|
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_SharedWRAM>(addr);
|
||||||
#endif
|
#endif
|
||||||
*(u8*)&SWRAM_ARM7.Mem[addr & SWRAM_ARM7.Mask] = val;
|
*(u8*)&SWRAM_ARM7.Mem[addr & SWRAM_ARM7.Mask] = val;
|
||||||
return;
|
return;
|
||||||
|
@ -2552,16 +2543,13 @@ void ARM7Write16(u32 addr, u16 val)
|
||||||
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_MainRAM>(addr);
|
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_MainRAM>(addr);
|
||||||
#endif
|
#endif
|
||||||
*(u16*)&MainRAM[addr & MainRAMMask] = val;
|
*(u16*)&MainRAM[addr & MainRAMMask] = val;
|
||||||
#ifdef JIT_ENABLED
|
|
||||||
ARMJIT::InvalidateMainRAMIfNecessary(addr);
|
|
||||||
#endif
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x03000000:
|
case 0x03000000:
|
||||||
if (SWRAM_ARM7.Mem)
|
if (SWRAM_ARM7.Mem)
|
||||||
{
|
{
|
||||||
#ifdef JIT_ENABLED
|
#ifdef JIT_ENABLED
|
||||||
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_SWRAM>(addr);
|
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_SharedWRAM>(addr);
|
||||||
#endif
|
#endif
|
||||||
*(u16*)&SWRAM_ARM7.Mem[addr & SWRAM_ARM7.Mask] = val;
|
*(u16*)&SWRAM_ARM7.Mem[addr & SWRAM_ARM7.Mask] = val;
|
||||||
return;
|
return;
|
||||||
|
@ -2639,16 +2627,13 @@ void ARM7Write32(u32 addr, u32 val)
|
||||||
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_MainRAM>(addr);
|
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_MainRAM>(addr);
|
||||||
#endif
|
#endif
|
||||||
*(u32*)&MainRAM[addr & MainRAMMask] = val;
|
*(u32*)&MainRAM[addr & MainRAMMask] = val;
|
||||||
#ifdef JIT_ENABLED
|
|
||||||
ARMJIT::InvalidateMainRAMIfNecessary(addr);
|
|
||||||
#endif
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x03000000:
|
case 0x03000000:
|
||||||
if (SWRAM_ARM7.Mem)
|
if (SWRAM_ARM7.Mem)
|
||||||
{
|
{
|
||||||
#ifdef JIT_ENABLED
|
#ifdef JIT_ENABLED
|
||||||
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_SWRAM>(addr);
|
ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_SharedWRAM>(addr);
|
||||||
#endif
|
#endif
|
||||||
*(u32*)&SWRAM_ARM7.Mem[addr & SWRAM_ARM7.Mask] = val;
|
*(u32*)&SWRAM_ARM7.Mem[addr & SWRAM_ARM7.Mask] = val;
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -165,6 +165,8 @@ extern u16 ARM7BIOSProt;
|
||||||
extern u8* MainRAM;
|
extern u8* MainRAM;
|
||||||
extern u32 MainRAMMask;
|
extern u32 MainRAMMask;
|
||||||
|
|
||||||
|
const u32 MainRAMMaxSize = 0x1000000;
|
||||||
|
|
||||||
const u32 SharedWRAMSize = 0x8000;
|
const u32 SharedWRAMSize = 0x8000;
|
||||||
extern u8* SharedWRAM;
|
extern u8* SharedWRAM;
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
EmuSettingsDialog* EmuSettingsDialog::currentDlg = nullptr;
|
EmuSettingsDialog* EmuSettingsDialog::currentDlg = nullptr;
|
||||||
|
|
||||||
extern char* EmuDirectory;
|
extern char* EmuDirectory;
|
||||||
|
extern bool RunningSomething;
|
||||||
|
|
||||||
|
|
||||||
EmuSettingsDialog::EmuSettingsDialog(QWidget* parent) : QDialog(parent), ui(new Ui::EmuSettingsDialog)
|
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->cbxConsoleType->setCurrentIndex(Config::ConsoleType);
|
||||||
|
|
||||||
ui->chkDirectBoot->setChecked(Config::DirectBoot != 0);
|
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()
|
EmuSettingsDialog::~EmuSettingsDialog()
|
||||||
|
@ -102,29 +119,78 @@ void EmuSettingsDialog::verifyFirmware()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuSettingsDialog::on_EmuSettingsDialog_accepted()
|
void EmuSettingsDialog::done(int r)
|
||||||
{
|
{
|
||||||
verifyFirmware();
|
if (r == QDialog::Accepted)
|
||||||
|
{
|
||||||
|
verifyFirmware();
|
||||||
|
|
||||||
strncpy(Config::BIOS9Path, ui->txtBIOS9Path->text().toStdString().c_str(), 1023); Config::BIOS9Path[1023] = '\0';
|
int consoleType = ui->cbxConsoleType->currentIndex();
|
||||||
strncpy(Config::BIOS7Path, ui->txtBIOS7Path->text().toStdString().c_str(), 1023); Config::BIOS7Path[1023] = '\0';
|
int directBoot = ui->chkDirectBoot->isChecked() ? 1: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';
|
int jitEnable = ui->chkEnableJIT->isChecked() ? 1:0;
|
||||||
strncpy(Config::DSiBIOS7Path, ui->txtDSiBIOS7Path->text().toStdString().c_str(), 1023); Config::DSiBIOS7Path[1023] = '\0';
|
int jitMaxBlockSize = ui->spnJITMaximumBlockSize->value();
|
||||||
strncpy(Config::DSiFirmwarePath, ui->txtDSiFirmwarePath->text().toStdString().c_str(), 1023); Config::DSiFirmwarePath[1023] = '\0';
|
int jitBranchOptimisations = ui->chkJITBranchOptimisations->isChecked() ? 1:0;
|
||||||
strncpy(Config::DSiNANDPath, ui->txtDSiNANDPath->text().toStdString().c_str(), 1023); Config::DSiNANDPath[1023] = '\0';
|
int jitLiteralOptimisations = ui->chkJITLiteralOptimisations->isChecked() ? 1:0;
|
||||||
|
int jitFastMemory = ui->chkJITFastMemory->isChecked() ? 1:0;
|
||||||
|
|
||||||
Config::ConsoleType = ui->cbxConsoleType->currentIndex();
|
std::string bios9Path = ui->txtBIOS9Path->text().toStdString();
|
||||||
Config::DirectBoot = ui->chkDirectBoot->isChecked() ? 1:0;
|
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();
|
||||||
|
|
||||||
Config::Save();
|
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;
|
||||||
|
|
||||||
closeDlg();
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QDialog::done(r);
|
||||||
|
|
||||||
void EmuSettingsDialog::on_EmuSettingsDialog_rejected()
|
|
||||||
{
|
|
||||||
closeDlg();
|
closeDlg();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,3 +277,12 @@ void EmuSettingsDialog::on_btnDSiNANDBrowse_clicked()
|
||||||
|
|
||||||
ui->txtDSiNANDPath->setText(file);
|
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);
|
||||||
|
}
|
|
@ -51,8 +51,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void on_EmuSettingsDialog_accepted();
|
void done(int r);
|
||||||
void on_EmuSettingsDialog_rejected();
|
|
||||||
|
|
||||||
void on_btnBIOS9Browse_clicked();
|
void on_btnBIOS9Browse_clicked();
|
||||||
void on_btnBIOS7Browse_clicked();
|
void on_btnBIOS7Browse_clicked();
|
||||||
|
@ -63,6 +62,8 @@ private slots:
|
||||||
void on_btnDSiFirmwareBrowse_clicked();
|
void on_btnDSiFirmwareBrowse_clicked();
|
||||||
void on_btnDSiNANDBrowse_clicked();
|
void on_btnDSiNANDBrowse_clicked();
|
||||||
|
|
||||||
|
void on_chkEnableJIT_toggled();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void verifyFirmware();
|
void verifyFirmware();
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>490</width>
|
<width>514</width>
|
||||||
<height>392</height>
|
<height>359</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
|
@ -24,243 +24,336 @@
|
||||||
<enum>QLayout::SetFixedSize</enum>
|
<enum>QLayout::SetFixedSize</enum>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="groupBox">
|
<widget class="QTabWidget" name="tabWidget">
|
||||||
<property name="title">
|
<property name="currentIndex">
|
||||||
<string>DS mode</string>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_2">
|
<widget class="QWidget" name="tab">
|
||||||
<item row="0" column="1">
|
<attribute name="title">
|
||||||
<widget class="QLineEdit" name="txtBIOS9Path">
|
<string>General</string>
|
||||||
<property name="sizePolicy">
|
</attribute>
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
<layout class="QFormLayout" name="formLayout_4">
|
||||||
<horstretch>0</horstretch>
|
<item row="1" column="1">
|
||||||
<verstretch>0</verstretch>
|
<widget class="QComboBox" name="cbxConsoleType">
|
||||||
</sizepolicy>
|
<property name="sizePolicy">
|
||||||
</property>
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||||
<property name="minimumSize">
|
<horstretch>0</horstretch>
|
||||||
<size>
|
<verstretch>0</verstretch>
|
||||||
<width>290</width>
|
</sizepolicy>
|
||||||
<height>0</height>
|
</property>
|
||||||
</size>
|
<property name="whatsThis">
|
||||||
</property>
|
<string><html><head/><body><p>The type of console to emulate</p></body></html></string>
|
||||||
<property name="statusTip">
|
</property>
|
||||||
<string/>
|
</widget>
|
||||||
</property>
|
</item>
|
||||||
<property name="whatsThis">
|
<item row="2" column="1">
|
||||||
<string><html><head/><body><p>DS-mode ARM9 BIOS</p><p>Size should be 4 KB</p></body></html></string>
|
<widget class="QCheckBox" name="chkDirectBoot">
|
||||||
</property>
|
<property name="whatsThis">
|
||||||
</widget>
|
<string><html><head/><body><p>When loading a ROM, completely skip the regular boot process (&quot;Nintendo DS&quot; screen) to boot the ROM directly.</p><p><br/></p><p>Note: if your firmware dump isn't bootable, the ROM will be booted directly regardless of this setting.</p></body></html></string>
|
||||||
</item>
|
</property>
|
||||||
<item row="2" column="0">
|
<property name="text">
|
||||||
<widget class="QLabel" name="label_3">
|
<string>Boot game directly</string>
|
||||||
<property name="text">
|
</property>
|
||||||
<string>DS firmware:</string>
|
</widget>
|
||||||
</property>
|
</item>
|
||||||
</widget>
|
<item row="3" column="0">
|
||||||
</item>
|
<spacer name="verticalSpacer_2">
|
||||||
<item row="1" column="0">
|
<property name="orientation">
|
||||||
<widget class="QLabel" name="label_2">
|
<enum>Qt::Vertical</enum>
|
||||||
<property name="text">
|
</property>
|
||||||
<string>DS ARM7 BIOS:</string>
|
<property name="sizeHint" stdset="0">
|
||||||
</property>
|
<size>
|
||||||
</widget>
|
<width>20</width>
|
||||||
</item>
|
<height>40</height>
|
||||||
<item row="0" column="0">
|
</size>
|
||||||
<widget class="QLabel" name="label">
|
</property>
|
||||||
<property name="text">
|
</spacer>
|
||||||
<string>DS ARM9 BIOS:</string>
|
</item>
|
||||||
</property>
|
<item row="1" column="0">
|
||||||
</widget>
|
<widget class="QLabel" name="label_4">
|
||||||
</item>
|
<property name="sizePolicy">
|
||||||
<item row="0" column="2">
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
<widget class="QPushButton" name="btnBIOS9Browse">
|
<horstretch>0</horstretch>
|
||||||
<property name="sizePolicy">
|
<verstretch>0</verstretch>
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
</sizepolicy>
|
||||||
<horstretch>0</horstretch>
|
</property>
|
||||||
<verstretch>0</verstretch>
|
<property name="text">
|
||||||
</sizepolicy>
|
<string>Console type:</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
</widget>
|
||||||
<string>Browse...</string>
|
</item>
|
||||||
</property>
|
</layout>
|
||||||
<property name="autoDefault">
|
</widget>
|
||||||
<bool>true</bool>
|
<widget class="QWidget" name="tab_2">
|
||||||
</property>
|
<attribute name="title">
|
||||||
</widget>
|
<string>BIOS Files</string>
|
||||||
</item>
|
</attribute>
|
||||||
<item row="1" column="1">
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
<widget class="QLineEdit" name="txtBIOS7Path">
|
<item>
|
||||||
<property name="whatsThis">
|
<widget class="QGroupBox" name="groupBox">
|
||||||
<string><html><head/><body><p>DS-mode ARM7 BIOS</p><p>Size should be 16 KB</p></body></html></string>
|
<property name="title">
|
||||||
</property>
|
<string>DS mode</string>
|
||||||
</widget>
|
</property>
|
||||||
</item>
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
<item row="1" column="2">
|
<item row="2" column="0">
|
||||||
<widget class="QPushButton" name="btnBIOS7Browse">
|
<widget class="QLabel" name="label_3">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Browse...</string>
|
<string>DS firmware:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="1">
|
<item row="2" column="1">
|
||||||
<widget class="QLineEdit" name="txtFirmwarePath">
|
<widget class="QLineEdit" name="txtFirmwarePath">
|
||||||
<property name="whatsThis">
|
<property name="whatsThis">
|
||||||
<string><html><head/><body><p>DS-mode firmware</p><p><br/></p><p>Possible firmwares:</p><p>* 128 KB: DS-mode firmware from a DSi or 3DS. Not bootable.</p><p>* 256 KB: regular DS firmware.</p><p>* 512 KB: iQue DS firmware.</p></body></html></string>
|
<string><html><head/><body><p>DS-mode firmware</p><p><br/></p><p>Possible firmwares:</p><p>* 128 KB: DS-mode firmware from a DSi or 3DS. Not bootable.</p><p>* 256 KB: regular DS firmware.</p><p>* 512 KB: iQue DS firmware.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="2">
|
<item row="1" column="1">
|
||||||
<widget class="QPushButton" name="btnFirmwareBrowse">
|
<widget class="QLineEdit" name="txtBIOS7Path">
|
||||||
<property name="text">
|
<property name="whatsThis">
|
||||||
<string>Browse...</string>
|
<string><html><head/><body><p>DS-mode ARM7 BIOS</p><p>Size should be 16 KB</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
<item row="0" column="2">
|
||||||
</widget>
|
<widget class="QPushButton" name="btnBIOS9Browse">
|
||||||
</item>
|
<property name="sizePolicy">
|
||||||
<item>
|
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||||
<widget class="QGroupBox" name="groupBox_3">
|
<horstretch>0</horstretch>
|
||||||
<property name="title">
|
<verstretch>0</verstretch>
|
||||||
<string>DSi mode</string>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_3">
|
<property name="text">
|
||||||
<item row="0" column="2">
|
<string>Browse...</string>
|
||||||
<widget class="QPushButton" name="btnDSiBIOS9Browse">
|
</property>
|
||||||
<property name="text">
|
<property name="autoDefault">
|
||||||
<string>Browse...</string>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="0">
|
<item row="2" column="2">
|
||||||
<widget class="QLabel" name="label_5">
|
<widget class="QPushButton" name="btnFirmwareBrowse">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>DSi ARM9 BIOS:</string>
|
<string>Browse...</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="2">
|
<item row="1" column="0">
|
||||||
<widget class="QPushButton" name="btnDSiFirmwareBrowse">
|
<widget class="QLabel" name="label_2">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Browse...</string>
|
<string>DS ARM7 BIOS:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="1">
|
<item row="0" column="0">
|
||||||
<widget class="QLineEdit" name="txtDSiBIOS7Path">
|
<widget class="QLabel" name="label">
|
||||||
<property name="whatsThis">
|
<property name="text">
|
||||||
<string><html><head/><body><p>DSi-mode ARM7 BIOS</p><p><br/></p><p>Size should be 64 KB</p></body></html></string>
|
<string>DS ARM9 BIOS:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="1">
|
<item row="1" column="2">
|
||||||
<widget class="QLineEdit" name="txtDSiFirmwarePath">
|
<widget class="QPushButton" name="btnBIOS7Browse">
|
||||||
<property name="whatsThis">
|
<property name="text">
|
||||||
<string><html><head/><body><p>DSi-mode firmware (used for DS-mode backwards compatibility)</p><p><br/></p><p>Size should be 128 KB</p></body></html></string>
|
<string>Browse...</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
<item row="0" column="1">
|
||||||
<widget class="QLabel" name="label_6">
|
<widget class="QLineEdit" name="txtBIOS9Path">
|
||||||
<property name="text">
|
<property name="sizePolicy">
|
||||||
<string>DSi ARM7 BIOS:</string>
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
</property>
|
<horstretch>0</horstretch>
|
||||||
</widget>
|
<verstretch>0</verstretch>
|
||||||
</item>
|
</sizepolicy>
|
||||||
<item row="2" column="0">
|
</property>
|
||||||
<widget class="QLabel" name="label_7">
|
<property name="minimumSize">
|
||||||
<property name="text">
|
<size>
|
||||||
<string>DSi firmware:</string>
|
<width>290</width>
|
||||||
</property>
|
<height>0</height>
|
||||||
</widget>
|
</size>
|
||||||
</item>
|
</property>
|
||||||
<item row="1" column="2">
|
<property name="statusTip">
|
||||||
<widget class="QPushButton" name="btnDSiBIOS7Browse">
|
<string/>
|
||||||
<property name="text">
|
</property>
|
||||||
<string>Browse...</string>
|
<property name="whatsThis">
|
||||||
</property>
|
<string><html><head/><body><p>DS-mode ARM9 BIOS</p><p>Size should be 4 KB</p></body></html></string>
|
||||||
</widget>
|
</property>
|
||||||
</item>
|
</widget>
|
||||||
<item row="0" column="1">
|
</item>
|
||||||
<widget class="QLineEdit" name="txtDSiBIOS9Path">
|
</layout>
|
||||||
<property name="sizePolicy">
|
</widget>
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
</item>
|
||||||
<horstretch>0</horstretch>
|
<item>
|
||||||
<verstretch>0</verstretch>
|
<widget class="QGroupBox" name="groupBox_3">
|
||||||
</sizepolicy>
|
<property name="title">
|
||||||
</property>
|
<string>DSi mode</string>
|
||||||
<property name="whatsThis">
|
</property>
|
||||||
<string><html><head/><body><p>DSi-mode ARM9 BIOS</p><p><br/></p><p>Size should be 64 KB</p></body></html></string>
|
<layout class="QGridLayout" name="gridLayout_3">
|
||||||
</property>
|
<item row="0" column="2">
|
||||||
</widget>
|
<widget class="QPushButton" name="btnDSiBIOS9Browse">
|
||||||
</item>
|
<property name="text">
|
||||||
<item row="3" column="0">
|
<string>Browse...</string>
|
||||||
<widget class="QLabel" name="label_8">
|
</property>
|
||||||
<property name="text">
|
</widget>
|
||||||
<string>DSi NAND:</string>
|
</item>
|
||||||
</property>
|
<item row="0" column="0">
|
||||||
</widget>
|
<widget class="QLabel" name="label_5">
|
||||||
</item>
|
<property name="text">
|
||||||
<item row="3" column="1">
|
<string>DSi ARM9 BIOS:</string>
|
||||||
<widget class="QLineEdit" name="txtDSiNANDPath">
|
</property>
|
||||||
<property name="whatsThis">
|
</widget>
|
||||||
<string><html><head/><body><p>DSi NAND dump</p><p><br/></p><p>Should have 'nocash footer' at the end</p></body></html></string>
|
</item>
|
||||||
</property>
|
<item row="2" column="2">
|
||||||
</widget>
|
<widget class="QPushButton" name="btnDSiFirmwareBrowse">
|
||||||
</item>
|
<property name="text">
|
||||||
<item row="3" column="2">
|
<string>Browse...</string>
|
||||||
<widget class="QPushButton" name="btnDSiNANDBrowse">
|
</property>
|
||||||
<property name="text">
|
</widget>
|
||||||
<string>Browse...</string>
|
</item>
|
||||||
</property>
|
<item row="1" column="1">
|
||||||
</widget>
|
<widget class="QLineEdit" name="txtDSiBIOS7Path">
|
||||||
</item>
|
<property name="whatsThis">
|
||||||
</layout>
|
<string><html><head/><body><p>DSi-mode ARM7 BIOS</p><p><br/></p><p>Size should be 64 KB</p></body></html></string>
|
||||||
</widget>
|
</property>
|
||||||
</item>
|
</widget>
|
||||||
<item>
|
</item>
|
||||||
<widget class="QGroupBox" name="groupBox_2">
|
<item row="2" column="1">
|
||||||
<property name="title">
|
<widget class="QLineEdit" name="txtDSiFirmwarePath">
|
||||||
<string>General</string>
|
<property name="whatsThis">
|
||||||
</property>
|
<string><html><head/><body><p>DSi-mode firmware (used for DS-mode backwards compatibility)</p><p><br/></p><p>Size should be 128 KB</p></body></html></string>
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
</property>
|
||||||
<item row="0" column="0">
|
</widget>
|
||||||
<widget class="QLabel" name="label_4">
|
</item>
|
||||||
<property name="sizePolicy">
|
<item row="1" column="0">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
<widget class="QLabel" name="label_6">
|
||||||
<horstretch>0</horstretch>
|
<property name="text">
|
||||||
<verstretch>0</verstretch>
|
<string>DSi ARM7 BIOS:</string>
|
||||||
</sizepolicy>
|
</property>
|
||||||
</property>
|
</widget>
|
||||||
<property name="text">
|
</item>
|
||||||
<string>Console type:</string>
|
<item row="2" column="0">
|
||||||
</property>
|
<widget class="QLabel" name="label_7">
|
||||||
</widget>
|
<property name="text">
|
||||||
</item>
|
<string>DSi firmware:</string>
|
||||||
<item row="0" column="1">
|
</property>
|
||||||
<widget class="QComboBox" name="cbxConsoleType">
|
</widget>
|
||||||
<property name="sizePolicy">
|
</item>
|
||||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
<item row="1" column="2">
|
||||||
<horstretch>0</horstretch>
|
<widget class="QPushButton" name="btnDSiBIOS7Browse">
|
||||||
<verstretch>0</verstretch>
|
<property name="text">
|
||||||
</sizepolicy>
|
<string>Browse...</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="whatsThis">
|
</widget>
|
||||||
<string><html><head/><body><p>The type of console to emulate</p></body></html></string>
|
</item>
|
||||||
</property>
|
<item row="0" column="1">
|
||||||
</widget>
|
<widget class="QLineEdit" name="txtDSiBIOS9Path">
|
||||||
</item>
|
<property name="sizePolicy">
|
||||||
<item row="1" column="0" colspan="2">
|
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||||
<widget class="QCheckBox" name="chkDirectBoot">
|
<horstretch>0</horstretch>
|
||||||
<property name="whatsThis">
|
<verstretch>0</verstretch>
|
||||||
<string><html><head/><body><p>When loading a ROM, completely skip the regular boot process (&quot;Nintendo DS&quot; screen) to boot the ROM directly.</p><p><br/></p><p>Note: if your firmware dump isn't bootable, the ROM will be booted directly regardless of this setting.</p></body></html></string>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="whatsThis">
|
||||||
<string>Boot game directly</string>
|
<string><html><head/><body><p>DSi-mode ARM9 BIOS</p><p><br/></p><p>Size should be 64 KB</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
<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><html><head/><body><p>DSi NAND dump</p><p><br/></p><p>Should have 'nocash footer' at the end</p></body></html></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>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
@ -275,6 +368,27 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</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/>
|
<resources/>
|
||||||
<connections>
|
<connections>
|
||||||
<connection>
|
<connection>
|
||||||
|
@ -284,8 +398,8 @@
|
||||||
<slot>accept()</slot>
|
<slot>accept()</slot>
|
||||||
<hints>
|
<hints>
|
||||||
<hint type="sourcelabel">
|
<hint type="sourcelabel">
|
||||||
<x>248</x>
|
<x>257</x>
|
||||||
<y>254</y>
|
<y>349</y>
|
||||||
</hint>
|
</hint>
|
||||||
<hint type="destinationlabel">
|
<hint type="destinationlabel">
|
||||||
<x>157</x>
|
<x>157</x>
|
||||||
|
@ -300,8 +414,8 @@
|
||||||
<slot>reject()</slot>
|
<slot>reject()</slot>
|
||||||
<hints>
|
<hints>
|
||||||
<hint type="sourcelabel">
|
<hint type="sourcelabel">
|
||||||
<x>316</x>
|
<x>325</x>
|
||||||
<y>260</y>
|
<y>349</y>
|
||||||
</hint>
|
</hint>
|
||||||
<hint type="destinationlabel">
|
<hint type="destinationlabel">
|
||||||
<x>286</x>
|
<x>286</x>
|
||||||
|
|
|
@ -1641,7 +1641,14 @@ void MainWindow::onStop()
|
||||||
|
|
||||||
void MainWindow::onOpenEmuSettings()
|
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()
|
void MainWindow::onOpenInputConfig()
|
||||||
|
|
|
@ -199,6 +199,7 @@ private slots:
|
||||||
void onStop();
|
void onStop();
|
||||||
|
|
||||||
void onOpenEmuSettings();
|
void onOpenEmuSettings();
|
||||||
|
void onEmuSettingsDialogFinished(int res);
|
||||||
void onOpenInputConfig();
|
void onOpenInputConfig();
|
||||||
void onInputConfigFinished(int res);
|
void onInputConfigFinished(int res);
|
||||||
void onOpenVideoSettings();
|
void onOpenVideoSettings();
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -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
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue