diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f89c314..18f79671 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,6 +67,13 @@ endif() if (ENABLE_JIT) add_definitions(-DJIT_ENABLED) + + option(ENABLE_JIT_PROFILING "Enable JIT profiling with VTune" OFF) + + if (ENABLE_JIT_PROFILING) + include(cmake/FindVTune.cmake) + add_definitions(-DJIT_PROFILING_ENABLED) + endif() endif() if (CMAKE_BUILD_TYPE STREQUAL Release) diff --git a/cmake/FindVTune.cmake b/cmake/FindVTune.cmake new file mode 100644 index 00000000..3c16dba6 --- /dev/null +++ b/cmake/FindVTune.cmake @@ -0,0 +1,5 @@ + +find_path(VTUNE_PATH "") + +include_directories("${VTUNE_PATH}/include") +link_directories("${VTUNE_PATH}/lib64") diff --git a/src/ARMJIT.cpp b/src/ARMJIT.cpp index 361801b7..3ffb31db 100644 --- a/src/ARMJIT.cpp +++ b/src/ARMJIT.cpp @@ -43,9 +43,6 @@ #include "Wifi.h" #include "NDSCart.h" -#if defined(__APPLE__) && defined(__aarch64__) - #include -#endif #include "ARMJIT_x64/ARMJIT_Offsets.h" static_assert(offsetof(ARM, CPSR) == ARM_CPSR_offset, ""); @@ -320,9 +317,7 @@ void Init() void DeInit() { - #if defined(__APPLE__) && defined(__aarch64__) - pthread_jit_write_protect_np(false); - #endif + JitEnableWrite(); ResetBlockCache(); ARMJIT_Memory::DeInit(); @@ -331,9 +326,7 @@ void DeInit() void Reset() { - #if defined(__APPLE__) && defined(__aarch64__) - pthread_jit_write_protect_np(false); - #endif + JitEnableWrite(); ResetBlockCache(); ARMJIT_Memory::Reset(); @@ -918,13 +911,10 @@ void CompileBlock(ARM* cpu) block->StartAddrLocal = localAddr; FloodFillSetFlags(instrs, i - 1, 0xF); - #if defined(__APPLE__) && defined(__aarch64__) - pthread_jit_write_protect_np(false); - #endif + + JitEnableWrite(); block->EntryPoint = JITCompiler->CompileBlock(cpu, thumb, instrs, i, hasMemoryInstr); - #if defined(__APPLE__) && defined(__aarch64__) - pthread_jit_write_protect_np(true); - #endif + JitEnableExecute(); JIT_DEBUGPRINT("block start %p\n", block->EntryPoint); } @@ -1168,4 +1158,20 @@ void ResetBlockCache() JITCompiler->Reset(); } +void JitEnableWrite() +{ + #if defined(__APPLE__) && defined(__aarch64__) + if (__builtin_available(macOS 11.0, *)) + pthread_jit_write_protect_np(false); + #endif +} + +void JitEnableExecute() +{ + #if defined(__APPLE__) && defined(__aarch64__) + if (__builtin_available(macOS 11.0, *)) + pthread_jit_write_protect_np(true); + #endif +} + } diff --git a/src/ARMJIT.h b/src/ARMJIT.h index 381068eb..43e087a3 100644 --- a/src/ARMJIT.h +++ b/src/ARMJIT.h @@ -24,6 +24,10 @@ #include "ARM.h" #include "ARM_InstrInfo.h" +#if defined(__APPLE__) && defined(__aarch64__) + #include +#endif + namespace ARMJIT { @@ -48,6 +52,8 @@ void ResetBlockCache(); JitBlockEntry LookUpBlock(u32 num, u64* entries, u32 offset, u32 addr); bool SetupExecutableRegion(u32 num, u32 blockAddr, u64*& entry, u32& start, u32& size); +void JitEnableWrite(); +void JitEnableExecute(); } extern "C" void ARM_Dispatch(ARM* cpu, ARMJIT::JitBlockEntry entry); diff --git a/src/ARMJIT_A64/ARMJIT_Compiler.cpp b/src/ARMJIT_A64/ARMJIT_Compiler.cpp index 7dc854ae..5941656f 100644 --- a/src/ARMJIT_A64/ARMJIT_Compiler.cpp +++ b/src/ARMJIT_A64/ARMJIT_Compiler.cpp @@ -33,10 +33,6 @@ extern char __start__; #include -#ifdef __APPLE__ - #include -#endif - using namespace Arm64Gen; extern "C" void ARM_Ret(); @@ -266,7 +262,7 @@ Compiler::Compiler() u64 alignedSize = (((u64)JitMem + sizeof(JitMem)) & ~(pageSize - 1)) - (u64)pageAligned; #ifdef __APPLE__ pageAligned = (u8*)mmap(NULL, 1024*1024*16, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS | MAP_JIT,-1, 0); - pthread_jit_write_protect_np(false); + JitEnableWrite(); #else mprotect(pageAligned, alignedSize, PROT_EXEC | PROT_READ | PROT_WRITE); #endif @@ -685,7 +681,8 @@ void Compiler::Comp_BranchSpecialBehaviour(bool taken) { RegCache.PrepareExit(); - ADD(RCycles, RCycles, ConstantCycles); + if (ConstantCycles) + ADD(RCycles, RCycles, ConstantCycles); QuickTailCall(X0, ARM_Ret); } } @@ -836,7 +833,8 @@ JitBlockEntry Compiler::CompileBlock(ARM* cpu, bool thumb, FetchedInstr instrs[] RegCache.Flush(); - ADD(RCycles, RCycles, ConstantCycles); + if (ConstantCycles) + ADD(RCycles, RCycles, ConstantCycles); QuickTailCall(X0, ARM_Ret); FlushIcache(); diff --git a/src/ARMJIT_A64/ARMJIT_Compiler.h b/src/ARMJIT_A64/ARMJIT_Compiler.h index 24e730b1..235155f4 100644 --- a/src/ARMJIT_A64/ARMJIT_Compiler.h +++ b/src/ARMJIT_A64/ARMJIT_Compiler.h @@ -185,7 +185,7 @@ public: void T_Comp_BL_LONG_2(); void T_Comp_BL_Merged(); - s32 Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc, bool decrement, bool usermode); + s32 Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc, bool decrement, bool usermode, bool skipLoadingRn); void Comp_Mul_Mla(bool S, bool mla, Arm64Gen::ARM64Reg rd, Arm64Gen::ARM64Reg rm, Arm64Gen::ARM64Reg rs, Arm64Gen::ARM64Reg rn); diff --git a/src/ARMJIT_A64/ARMJIT_LoadStore.cpp b/src/ARMJIT_A64/ARMJIT_LoadStore.cpp index 5ac629b1..8aa14099 100644 --- a/src/ARMJIT_A64/ARMJIT_LoadStore.cpp +++ b/src/ARMJIT_A64/ARMJIT_LoadStore.cpp @@ -465,7 +465,7 @@ void Compiler::T_Comp_MemSPRel() Comp_MemAccess(CurInstr.T_Reg(8), 13, Op2(offset), 32, load ? 0 : memop_Store); } -s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc, bool decrement, bool usermode) +s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc, bool decrement, bool usermode, bool skipLoadingRn) { IrregularCycles = true; @@ -474,7 +474,8 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc if (regsCount == 0) return 0; // actually not the right behaviour TODO: fix me - if (regsCount == 1 && !usermode && RegCache.LoadedRegs & (1 << *regs.begin())) + int firstReg = *regs.begin(); + if (regsCount == 1 && !usermode && RegCache.LoadedRegs & (1 << firstReg) && !(firstReg == rn && skipLoadingRn)) { int flags = 0; if (store) @@ -483,7 +484,7 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc flags |= memop_SubtractOffset; Op2 offset = preinc ? Op2(4) : Op2(0); - Comp_MemAccess(*regs.begin(), rn, offset, 32, flags); + Comp_MemAccess(firstReg, rn, offset, 32, flags); return decrement ? -4 : 4; } @@ -539,12 +540,16 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc loadStoreOffsets[i++] = GetCodeOffset(); if (store) + { STR(INDEX_UNSIGNED, first, X1, offset); - else + } + else if (!(reg == rn && skipLoadingRn)) + { LDR(INDEX_UNSIGNED, first, X1, offset); - if (!(RegCache.LoadedRegs & (1 << reg)) && !store) - SaveReg(reg, first); + if (!(RegCache.LoadedRegs & (1 << reg))) + SaveReg(reg, first); + } offset += 4; } @@ -558,13 +563,23 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc ARM64Reg first = W3, second = W4; if (RegCache.LoadedRegs & (1 << reg)) - first = MapReg(reg); + { + if (!(reg == rn && skipLoadingRn)) + first = MapReg(reg); + } else if (store) + { LoadReg(reg, first); + } if (RegCache.LoadedRegs & (1 << nextReg)) - second = MapReg(nextReg); + { + if (!(nextReg == rn && skipLoadingRn)) + second = MapReg(nextReg); + } else if (store) + { LoadReg(nextReg, second); + } loadStoreOffsets[i++] = GetCodeOffset(); if (store) @@ -705,20 +720,23 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc LDR(INDEX_UNSIGNED, W3, SP, i * 8); MOVI2R(W1, reg - 8); BL(WriteBanked); - FixupBranch alreadyWritten = CBNZ(W4); - if (RegCache.LoadedRegs & (1 << reg)) - MOV(MapReg(reg), W3); - else - SaveReg(reg, W3); - SetJumpTarget(alreadyWritten); + if (!(reg == rn && skipLoadingRn)) + { + FixupBranch alreadyWritten = CBNZ(W4); + if (RegCache.LoadedRegs & (1 << reg)) + MOV(MapReg(reg), W3); + else + SaveReg(reg, W3); + SetJumpTarget(alreadyWritten); + } } else if (!usermode && nextReg != regs.end()) { ARM64Reg first = W3, second = W4; - if (RegCache.LoadedRegs & (1 << reg)) + if (RegCache.LoadedRegs & (1 << reg) && !(reg == rn && skipLoadingRn)) first = MapReg(reg); - if (RegCache.LoadedRegs & (1 << *nextReg)) + if (RegCache.LoadedRegs & (1 << *nextReg) && !(*nextReg == rn && skipLoadingRn)) second = MapReg(*nextReg); LDP(INDEX_SIGNED, EncodeRegTo64(first), EncodeRegTo64(second), SP, i * 8); @@ -733,8 +751,11 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc } else if (RegCache.LoadedRegs & (1 << reg)) { - ARM64Reg mapped = MapReg(reg); - LDR(INDEX_UNSIGNED, mapped, SP, i * 8); + if (!(reg == rn && skipLoadingRn)) + { + ARM64Reg mapped = MapReg(reg); + LDR(INDEX_UNSIGNED, mapped, SP, i * 8); + } } else { @@ -778,13 +799,13 @@ void Compiler::A_Comp_LDM_STM() ARM64Reg rn = MapReg(CurInstr.A_Reg(16)); - s32 offset = Comp_MemAccessBlock(CurInstr.A_Reg(16), regs, !load, pre, !add, usermode); - if (load && writeback && regs[CurInstr.A_Reg(16)]) writeback = Num == 0 - ? (!(regs & ~BitSet16(1 << CurInstr.A_Reg(16)))) || (regs & ~BitSet16((2 << CurInstr.A_Reg(16)) - 1)) - : false; - if (writeback) + && (!(regs & ~BitSet16(1 << CurInstr.A_Reg(16)))) || (regs & ~BitSet16((2 << CurInstr.A_Reg(16)) - 1)); + + s32 offset = Comp_MemAccessBlock(CurInstr.A_Reg(16), regs, !load, pre, !add, usermode, load && writeback); + + if (writeback && offset) { if (offset > 0) ADD(rn, rn, offset); @@ -806,12 +827,15 @@ void Compiler::T_Comp_PUSH_POP() } ARM64Reg sp = MapReg(13); - s32 offset = Comp_MemAccessBlock(13, regs, !load, !load, !load, false); + s32 offset = Comp_MemAccessBlock(13, regs, !load, !load, !load, false, false); - if (offset > 0) + if (offset) + { + if (offset > 0) ADD(sp, sp, offset); else SUB(sp, sp, -offset); + } } void Compiler::T_Comp_LDMIA_STMIA() @@ -820,10 +844,12 @@ void Compiler::T_Comp_LDMIA_STMIA() ARM64Reg rb = MapReg(CurInstr.T_Reg(8)); bool load = CurInstr.Instr & (1 << 11); u32 regsCount = regs.Count(); - - s32 offset = Comp_MemAccessBlock(CurInstr.T_Reg(8), regs, !load, false, false, false); - if (!load || !regs[CurInstr.T_Reg(8)]) + bool writeback = !load || !regs[CurInstr.T_Reg(8)]; + + s32 offset = Comp_MemAccessBlock(CurInstr.T_Reg(8), regs, !load, false, false, false, load && writeback); + + if (writeback && offset) { if (offset > 0) ADD(rb, rb, offset); diff --git a/src/ARMJIT_x64/ARMJIT_Compiler.cpp b/src/ARMJIT_x64/ARMJIT_Compiler.cpp index aef8b91b..81786849 100644 --- a/src/ARMJIT_x64/ARMJIT_Compiler.cpp +++ b/src/ARMJIT_x64/ARMJIT_Compiler.cpp @@ -22,6 +22,7 @@ #include "../Config.h" #include +#include #include "../dolphin/CommonFuncs.h" @@ -298,6 +299,10 @@ Compiler::Compiler() SetJumpTarget(und); MOV(32, R(RSCRATCH3), MComplex(RCPU, RSCRATCH2, SCALE_4, offsetof(ARM, R_UND))); RET(); + +#ifdef JIT_PROFILING_ENABLED + CreateMethod("ReadBanked", ReadBanked); +#endif } { // RSCRATCH mode @@ -341,6 +346,10 @@ Compiler::Compiler() MOV(32, MComplex(RCPU, RSCRATCH2, SCALE_4, offsetof(ARM, R_UND)), R(RSCRATCH3)); CLC(); RET(); + +#ifdef JIT_PROFILING_ENABLED + CreateMethod("WriteBanked", WriteBanked); +#endif } for (int consoleType = 0; consoleType < 2; consoleType++) @@ -401,6 +410,10 @@ Compiler::Compiler() ABI_PopRegistersAndAdjustStack(CallerSavedPushRegs, 8); RET(); +#ifdef JIT_PROFILING_ENABLED + CreateMethod("FastMemStorePatch%d_%d_%d", PatchedStoreFuncs[consoleType][num][size][reg], num, size, reg); +#endif + for (int signextend = 0; signextend < 2; signextend++) { PatchedLoadFuncs[consoleType][num][size][signextend][reg] = GetWritableCodePtr(); @@ -439,6 +452,10 @@ Compiler::Compiler() else MOVZX(32, 8 << size, rdMapped, R(RSCRATCH)); RET(); + +#ifdef JIT_PROFILING_ENABLED + CreateMethod("FastMemLoadPatch%d_%d_%d_%d", PatchedLoadFuncs[consoleType][num][size][signextend][reg], num, size, reg, signextend); +#endif } } } @@ -663,11 +680,34 @@ void Compiler::Comp_SpecialBranchBehaviour(bool taken) { RegCache.PrepareExit(); - ADD(32, MDisp(RCPU, offsetof(ARM, Cycles)), Imm32(ConstantCycles)); + if (ConstantCycles) + ADD(32, MDisp(RCPU, offsetof(ARM, Cycles)), Imm32(ConstantCycles)); JMP((u8*)&ARM_Ret, true); } } +#ifdef JIT_PROFILING_ENABLED +void Compiler::CreateMethod(const char* namefmt, void* start, ...) +{ + if (iJIT_IsProfilingActive()) + { + va_list args; + va_start(args, start); + char name[64]; + vsprintf(name, namefmt, args); + va_end(args); + + iJIT_Method_Load method = {0}; + method.method_id = iJIT_GetNewMethodID(); + method.method_name = name; + method.method_load_address = start; + method.method_size = GetWritableCodePtr() - (u8*)start; + + iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, (void*)&method); + } +} +#endif + JitBlockEntry Compiler::CompileBlock(ARM* cpu, bool thumb, FetchedInstr instrs[], int instrsCount, bool hasMemoryInstr) { if (NearSize - (GetCodePtr() - NearStart) < 1024 * 32) // guess... @@ -802,9 +842,14 @@ JitBlockEntry Compiler::CompileBlock(ARM* cpu, bool thumb, FetchedInstr instrs[] RegCache.Flush(); - ADD(32, MDisp(RCPU, offsetof(ARM, Cycles)), Imm32(ConstantCycles)); + if (ConstantCycles) + ADD(32, MDisp(RCPU, offsetof(ARM, Cycles)), Imm32(ConstantCycles)); JMP((u8*)ARM_Ret, true); +#ifdef JIT_PROFILING_ENABLED + CreateMethod("JIT_Block_%d_%d_%08X", (void*)res, Num, Thumb, instrs[0].Addr); +#endif + /*FILE* codeout = fopen("codeout", "a"); fprintf(codeout, "beginning block argargarg__ %x!!!", instrs[0].Addr); fwrite((u8*)res, GetWritableCodePtr() - (u8*)res, 1, codeout); diff --git a/src/ARMJIT_x64/ARMJIT_Compiler.h b/src/ARMJIT_x64/ARMJIT_Compiler.h index eedfc1ae..5046c884 100644 --- a/src/ARMJIT_x64/ARMJIT_Compiler.h +++ b/src/ARMJIT_x64/ARMJIT_Compiler.h @@ -25,6 +25,10 @@ #include "../ARMJIT_Internal.h" #include "../ARMJIT_RegisterCache.h" +#ifdef JIT_PROFILING_ENABLED +#include +#endif + #include namespace ARMJIT @@ -163,7 +167,7 @@ public: memop_SubtractOffset = 1 << 4 }; void Comp_MemAccess(int rd, int rn, const Op2& op2, int size, int flags); - s32 Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc, bool decrement, bool usermode); + s32 Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc, bool decrement, bool usermode, bool skipLoadingRn); bool Comp_MemLoadLiteral(int size, bool signExtend, int rd, u32 addr); void Comp_ArithTriOp(void (Compiler::*op)(int, const Gen::OpArg&, const Gen::OpArg&), @@ -230,6 +234,10 @@ public: u8* RewriteMemAccess(u8* pc); +#ifdef JIT_PROFILING_ENABLED + void CreateMethod(const char* namefmt, void* start, ...); +#endif + u8* FarCode; u8* NearCode; u32 FarSize; diff --git a/src/ARMJIT_x64/ARMJIT_LoadStore.cpp b/src/ARMJIT_x64/ARMJIT_LoadStore.cpp index 88c0a9b8..776d641e 100644 --- a/src/ARMJIT_x64/ARMJIT_LoadStore.cpp +++ b/src/ARMJIT_x64/ARMJIT_LoadStore.cpp @@ -399,14 +399,15 @@ void Compiler::Comp_MemAccess(int rd, int rn, const Op2& op2, int size, int flag } } -s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc, bool decrement, bool usermode) +s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc, bool decrement, bool usermode, bool skipLoadingRn) { int regsCount = regs.Count(); if (regsCount == 0) return 0; // actually not the right behaviour TODO: fix me - if (regsCount == 1 && !usermode && RegCache.LoadedRegs & (1 << *regs.begin())) + int firstReg = *regs.begin(); + if (regsCount == 1 && !usermode && RegCache.LoadedRegs & (1 << firstReg) && !(firstReg == rn && skipLoadingRn)) { int flags = 0; if (store) @@ -415,7 +416,7 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc flags |= memop_SubtractOffset; Op2 offset = preinc ? Op2(4) : Op2(0); - Comp_MemAccess(*regs.begin(), rn, offset, 32, flags); + Comp_MemAccess(firstReg, rn, offset, 32, flags); return decrement ? -4 : 4; } @@ -482,7 +483,10 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc { if (RegCache.LoadedRegs & (1 << reg)) { - MOV(32, MapReg(reg), mem); + if (!(reg == rn && skipLoadingRn)) + MOV(32, MapReg(reg), mem); + else + MOV(32, R(RSCRATCH), mem); // just touch the memory } else { @@ -548,12 +552,15 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc MOV(32, R(RSCRATCH2), Imm32(reg - 8)); POP(RSCRATCH3); CALL(WriteBanked); - FixupBranch sucessfulWritten = J_CC(CC_NC); - if (RegCache.LoadedRegs & (1 << reg)) - MOV(32, R(RegCache.Mapping[reg]), R(RSCRATCH3)); - else - SaveReg(reg, RSCRATCH3); - SetJumpTarget(sucessfulWritten); + if (!(reg == rn && skipLoadingRn)) + { + FixupBranch sucessfulWritten = J_CC(CC_NC); + if (RegCache.LoadedRegs & (1 << reg)) + MOV(32, R(RegCache.Mapping[reg]), R(RSCRATCH3)); + else + SaveReg(reg, RSCRATCH3); + SetJumpTarget(sucessfulWritten); + } } else if (!(RegCache.LoadedRegs & (1 << reg))) { @@ -562,6 +569,10 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc POP(RSCRATCH); SaveReg(reg, RSCRATCH); } + else if (reg == rn && skipLoadingRn) + { + ADD(64, R(RSP), Imm8(8)); + } else { POP(MapReg(reg).GetSimpleReg()); @@ -748,14 +759,14 @@ void Compiler::A_Comp_LDM_STM() OpArg rn = MapReg(CurInstr.A_Reg(16)); - s32 offset = Comp_MemAccessBlock(CurInstr.A_Reg(16), regs, !load, pre, !add, usermode); - if (load && writeback && regs[CurInstr.A_Reg(16)]) writeback = Num == 0 - ? (!(regs & ~BitSet16(1 << CurInstr.A_Reg(16)))) || (regs & ~BitSet16((2 << CurInstr.A_Reg(16)) - 1)) - : false; - if (writeback) - ADD(32, rn, offset >= INT8_MIN && offset < INT8_MAX ? Imm8(offset) : Imm32(offset)); + && (!(regs & ~BitSet16(1 << CurInstr.A_Reg(16)))) || (regs & ~BitSet16((2 << CurInstr.A_Reg(16)) - 1)); + + s32 offset = Comp_MemAccessBlock(CurInstr.A_Reg(16), regs, !load, pre, !add, usermode, load && writeback); + + if (writeback && offset) + ADD(32, rn, Imm32(offset)); } void Compiler::T_Comp_MemImm() @@ -825,9 +836,10 @@ void Compiler::T_Comp_PUSH_POP() } OpArg sp = MapReg(13); - s32 offset = Comp_MemAccessBlock(13, regs, !load, !load, !load, false); + s32 offset = Comp_MemAccessBlock(13, regs, !load, !load, !load, false, false); - ADD(32, sp, Imm8(offset)); // offset will be always be in range since PUSH accesses 9 regs max + if (offset) + ADD(32, sp, Imm8(offset)); // offset will be always be in range since PUSH accesses 9 regs max } void Compiler::T_Comp_LDMIA_STMIA() @@ -836,9 +848,11 @@ void Compiler::T_Comp_LDMIA_STMIA() OpArg rb = MapReg(CurInstr.T_Reg(8)); bool load = CurInstr.Instr & (1 << 11); - s32 offset = Comp_MemAccessBlock(CurInstr.T_Reg(8), regs, !load, false, false, false); + bool writeback = !load || !regs[CurInstr.T_Reg(8)]; - if (!load || !regs[CurInstr.T_Reg(8)]) + s32 offset = Comp_MemAccessBlock(CurInstr.T_Reg(8), regs, !load, false, false, false, load && writeback); + + if (writeback && offset) ADD(32, rb, Imm8(offset)); } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 56039435..f604a396 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -124,3 +124,7 @@ else() target_link_libraries(core rt) endif() endif() + +if (ENABLE_JIT_PROFILING) + target_link_libraries(core jitprofiling) +endif() \ No newline at end of file diff --git a/src/DSi.cpp b/src/DSi.cpp index b55992ca..b22dc8f8 100644 --- a/src/DSi.cpp +++ b/src/DSi.cpp @@ -162,6 +162,7 @@ void Reset() SCFG_EXT[1] = 0x93FFFB06; SCFG_MC = 0x0010;//0x0011; SCFG_RST = 0; + DSi_DSP::SetRstLine(false); // LCD init flag @@ -185,6 +186,39 @@ void Reset() ARM7Write16(eaddr+0x42, 0x0001); } +void SetupDirectBoot() +{ + // If loading a NDS directly, this value should be set + // depending on the console type in the header at offset 12h + switch (NDSCart::Header.UnitCode) + { + case 0x00: /* NDS Image */ + // on a pure NDS Image, we disable all extended features + // TODO: For now keep the features enabled, as you can run pure NDS in NDS Emulation anyway + SCFG_BIOS = 0x0303; + break; + case 0x02: /* DSi Enhanced Image */ + SCFG_BIOS = 0x0303; + break; + default: + SCFG_BIOS = 0x0101; // TODO: should be zero when booting from BIOS + break; + } + // no NWRAM Mapping + for (int i = 0; i < 4; i++) + MapNWRAM_A(i, 0); + for (int i = 0; i < 8; i++) + MapNWRAM_B(i, 0); + for (int i = 0; i < 8; i++) + MapNWRAM_C(i, 0); + // No NWRAM Window + for (int i = 0; i < 3; i++) + { + MapNWRAMRange(0, i, 0); + MapNWRAMRange(1, i, 0); + } +} + void SoftReset() { // TODO: check exactly what is reset @@ -572,6 +606,10 @@ void StopNDMAs(u32 cpu, u32 mode) void MapNWRAM_A(u32 num, u8 val) { + // NWRAM Bank A does not allow all bits to be set + // possible non working combinations are caught by later code, but these are not set-able at all + val &= ~0x72; + if (MBK[0][8] & (1 << num)) { printf("trying to map NWRAM_A %d to %02X, but it is write-protected (%08X)\n", num, val, MBK[0][8]); @@ -591,22 +629,35 @@ void MapNWRAM_A(u32 num, u8 val) MBK[0][mbkn] |= (val << mbks); MBK[1][mbkn] = MBK[0][mbkn]; - u8* ptr = &NWRAM_A[num << 16]; - - if (oldval & 0x80) + // When we only update the mapping on the written MBK, we will + // have priority of the last witten MBK over the others + // However the hardware has a fixed order. Therefor + // we need to iterate through them all in a fixed order and update + // the mapping, so the result is independend on the MBK write order + for (unsigned int part = 0; part < 4; part++) { - if (NWRAMMap_A[oldval & 0x01][(oldval >> 2) & 0x3] == ptr) - NWRAMMap_A[oldval & 0x01][(oldval >> 2) & 0x3] = NULL; + NWRAMMap_A[0][part] = NULL; + NWRAMMap_A[1][part] = NULL; } - - if (val & 0x80) + for (int part = 3; part >= 0; part--) { - NWRAMMap_A[val & 0x01][(val >> 2) & 0x3] = ptr; + u8* ptr = &NWRAM_A[part << 16]; + + if ((MBK[0][0 + (part / 4)] >> ((part % 4) * 8)) & 0x80) + { + u8 mVal = (MBK[0][0 + (part / 4)] >> ((part % 4) * 8)) & 0xfd; + + NWRAMMap_A[mVal & 0x03][(mVal >> 2) & 0x3] = ptr; + } } } void MapNWRAM_B(u32 num, u8 val) { + // NWRAM Bank B does not allow all bits to be set + // possible non working combinations are caught by later code, but these are not set-able at all + val &= ~0x60; + if (MBK[0][8] & (1 << (8+num))) { printf("trying to map NWRAM_B %d to %02X, but it is write-protected (%08X)\n", num, val, MBK[0][8]); @@ -626,28 +677,42 @@ void MapNWRAM_B(u32 num, u8 val) MBK[0][mbkn] |= (val << mbks); MBK[1][mbkn] = MBK[0][mbkn]; - u8* ptr = &NWRAM_B[num << 15]; - - DSi_DSP::OnMBKCfg('B', num, oldval, val, ptr); - - if (oldval & 0x80) + // When we only update the mapping on the written MBK, we will + // have priority of the last witten MBK over the others + // However the hardware has a fixed order. Therefor + // we need to iterate through them all in a fixed order and update + // the mapping, so the result is independend on the MBK write order + for (unsigned int part = 0; part < 8; part++) { - if (oldval & 0x02) oldval &= 0xFE; - - if (NWRAMMap_B[oldval & 0x03][(oldval >> 2) & 0x7] == ptr) - NWRAMMap_B[oldval & 0x03][(oldval >> 2) & 0x7] = NULL; + NWRAMMap_B[0][part] = NULL; + NWRAMMap_B[1][part] = NULL; + NWRAMMap_B[2][part] = NULL; } - - if (val & 0x80) + for (int part = 7; part >= 0; part--) { - if (val & 0x02) val &= 0xFE; + u8* ptr = &NWRAM_B[part << 15]; - NWRAMMap_B[val & 0x03][(val >> 2) & 0x7] = ptr; + if (part == num) + { + DSi_DSP::OnMBKCfg('B', num, oldval, val, ptr); + } + + if ((MBK[0][1 + (part / 4)] >> ((part % 4) * 8)) & 0x80) + { + u8 mVal = (MBK[0][1 + (part / 4)] >> ((part % 4) * 8)) & 0xff; + if (mVal & 0x02) mVal &= 0xFE; + + NWRAMMap_B[mVal & 0x03][(mVal >> 2) & 0x7] = ptr; + } } } void MapNWRAM_C(u32 num, u8 val) { + // NWRAM Bank C does not allow all bits to be set + // possible non working combinations are caught by later code, but these are not set-able at all + val &= ~0x60; + if (MBK[0][8] & (1 << (16+num))) { printf("trying to map NWRAM_C %d to %02X, but it is write-protected (%08X)\n", num, val, MBK[0][8]); @@ -667,28 +732,51 @@ void MapNWRAM_C(u32 num, u8 val) MBK[0][mbkn] |= (val << mbks); MBK[1][mbkn] = MBK[0][mbkn]; - u8* ptr = &NWRAM_C[num << 15]; - - DSi_DSP::OnMBKCfg('C', num, oldval, val, ptr); - - if (oldval & 0x80) + // When we only update the mapping on the written MBK, we will + // have priority of the last witten MBK over the others + // However the hardware has a fixed order. Therefor + // we need to iterate through them all in a fixed order and update + // the mapping, so the result is independend on the MBK write order + for (unsigned int part = 0; part < 8; part++) { - if (oldval & 0x02) oldval &= 0xFE; - - if (NWRAMMap_C[oldval & 0x03][(oldval >> 2) & 0x7] == ptr) - NWRAMMap_C[oldval & 0x03][(oldval >> 2) & 0x7] = NULL; + NWRAMMap_C[0][part] = NULL; + NWRAMMap_C[1][part] = NULL; + NWRAMMap_C[2][part] = NULL; } - - if (val & 0x80) + for (int part = 7; part >= 0; part--) { - if (val & 0x02) val &= 0xFE; + u8* ptr = &NWRAM_C[part << 15]; - NWRAMMap_C[val & 0x03][(val >> 2) & 0x7] = ptr; + if (part == num) + { + DSi_DSP::OnMBKCfg('C', num, oldval, val, ptr); + } + + if ((MBK[0][3 + (part / 4)] >> ((part % 4) * 8)) & 0x80) + { + u8 mVal = MBK[0][3 + (part / 4)] >> ((part % 4) *8) & 0xff; + if (mVal & 0x02) mVal &= 0xFE; + NWRAMMap_C[mVal & 0x03][(mVal >> 2) & 0x7] = ptr; + } } } void MapNWRAMRange(u32 cpu, u32 num, u32 val) { + // The windowing registers are not writeable in all bits + // We need to do this before the change test, so we do not + // get false "was changed" fall throughs + switch (num) + { + case 0: + val &= ~0xE00FC00F; + break; + case 1: + case 2: + val &= ~0xE007C007; + break; + } + u32 oldval = MBK[cpu][5+num]; if (oldval == val) return; @@ -698,7 +786,14 @@ void MapNWRAMRange(u32 cpu, u32 num, u32 val) MBK[cpu][5+num] = val; - // TODO: what happens when the ranges are 'out of range'???? + // Was TODO: What happens when the ranges are 'out of range'???? + // Answer: The actual range is limited to 0x03000000 to 0x03ffffff + // The NWRAM can not map into the HW Register ranges and is never + // mapped there. However the end indizes are allowed to have a value + // exceeding that range, in which the accessed area is just cut + // at the end of the region + // since melonDS does this cut by the case switch in the read/write + // functions, we do not need to care here. if (num == 0) { u32 start = 0x03000000 + (((val >> 4) & 0xFF) << 16); @@ -802,20 +897,24 @@ u8 ARM9Read8(u32 addr) switch (addr & 0xFF000000) { case 0x03000000: - if (addr >= NWRAMStart[0][0] && addr < NWRAMEnd[0][0]) + case 0x03800000: + if (SCFG_EXT[0] & (1 << 25)) { - u8* ptr = NWRAMMap_A[0][(addr >> 16) & NWRAMMask[0][0]]; - return ptr ? *(u8*)&ptr[addr & 0xFFFF] : 0; - } - if (addr >= NWRAMStart[0][1] && addr < NWRAMEnd[0][1]) - { - u8* ptr = NWRAMMap_B[0][(addr >> 15) & NWRAMMask[0][1]]; - return ptr ? *(u8*)&ptr[addr & 0x7FFF] : 0; - } - if (addr >= NWRAMStart[0][2] && addr < NWRAMEnd[0][2]) - { - u8* ptr = NWRAMMap_C[0][(addr >> 15) & NWRAMMask[0][2]]; - return ptr ? *(u8*)&ptr[addr & 0x7FFF] : 0; + if (addr >= NWRAMStart[0][0] && addr < NWRAMEnd[0][0]) + { + u8* ptr = NWRAMMap_A[0][(addr >> 16) & NWRAMMask[0][0]]; + return ptr ? *(u8*)&ptr[addr & 0xFFFF] : 0; + } + if (addr >= NWRAMStart[0][1] && addr < NWRAMEnd[0][1]) + { + u8* ptr = NWRAMMap_B[0][(addr >> 15) & NWRAMMask[0][1]]; + return ptr ? *(u8*)&ptr[addr & 0x7FFF] : 0; + } + if (addr >= NWRAMStart[0][2] && addr < NWRAMEnd[0][2]) + { + u8* ptr = NWRAMMap_C[0][(addr >> 15) & NWRAMMask[0][2]]; + return ptr ? *(u8*)&ptr[addr & 0x7FFF] : 0; + } } return NDS::ARM9Read8(addr); @@ -844,20 +943,24 @@ u16 ARM9Read16(u32 addr) switch (addr & 0xFF000000) { case 0x03000000: - if (addr >= NWRAMStart[0][0] && addr < NWRAMEnd[0][0]) + case 0x03800000: + if (SCFG_EXT[0] & (1 << 25)) { - u8* ptr = NWRAMMap_A[0][(addr >> 16) & NWRAMMask[0][0]]; - return ptr ? *(u16*)&ptr[addr & 0xFFFF] : 0; - } - if (addr >= NWRAMStart[0][1] && addr < NWRAMEnd[0][1]) - { - u8* ptr = NWRAMMap_B[0][(addr >> 15) & NWRAMMask[0][1]]; - return ptr ? *(u16*)&ptr[addr & 0x7FFF] : 0; - } - if (addr >= NWRAMStart[0][2] && addr < NWRAMEnd[0][2]) - { - u8* ptr = NWRAMMap_C[0][(addr >> 15) & NWRAMMask[0][2]]; - return ptr ? *(u16*)&ptr[addr & 0x7FFF] : 0; + if (addr >= NWRAMStart[0][0] && addr < NWRAMEnd[0][0]) + { + u8* ptr = NWRAMMap_A[0][(addr >> 16) & NWRAMMask[0][0]]; + return ptr ? *(u16*)&ptr[addr & 0xFFFF] : 0; + } + if (addr >= NWRAMStart[0][1] && addr < NWRAMEnd[0][1]) + { + u8* ptr = NWRAMMap_B[0][(addr >> 15) & NWRAMMask[0][1]]; + return ptr ? *(u16*)&ptr[addr & 0x7FFF] : 0; + } + if (addr >= NWRAMStart[0][2] && addr < NWRAMEnd[0][2]) + { + u8* ptr = NWRAMMap_C[0][(addr >> 15) & NWRAMMask[0][2]]; + return ptr ? *(u16*)&ptr[addr & 0x7FFF] : 0; + } } return NDS::ARM9Read16(addr); @@ -879,7 +982,6 @@ u32 ARM9Read32(u32 addr) { if ((addr >= 0xFFFF8000) && (SCFG_BIOS & (1<<0))) return 0xFFFFFFFF; - return *(u32*)&ARM9iBIOS[addr & 0xFFFF]; } @@ -892,20 +994,24 @@ u32 ARM9Read32(u32 addr) break; case 0x03000000: - if (addr >= NWRAMStart[0][0] && addr < NWRAMEnd[0][0]) + case 0x03800000: + if (SCFG_EXT[0] & (1 << 25)) { - u8* ptr = NWRAMMap_A[0][(addr >> 16) & NWRAMMask[0][0]]; - return ptr ? *(u32*)&ptr[addr & 0xFFFF] : 0; - } - if (addr >= NWRAMStart[0][1] && addr < NWRAMEnd[0][1]) - { - u8* ptr = NWRAMMap_B[0][(addr >> 15) & NWRAMMask[0][1]]; - return ptr ? *(u32*)&ptr[addr & 0x7FFF] : 0; - } - if (addr >= NWRAMStart[0][2] && addr < NWRAMEnd[0][2]) - { - u8* ptr = NWRAMMap_C[0][(addr >> 15) & NWRAMMask[0][2]]; - return ptr ? *(u32*)&ptr[addr & 0x7FFF] : 0; + if (addr >= NWRAMStart[0][0] && addr < NWRAMEnd[0][0]) + { + u8* ptr = NWRAMMap_A[0][(addr >> 16) & NWRAMMask[0][0]]; + return ptr ? *(u32*)&ptr[addr & 0xFFFF] : 0; + } + if (addr >= NWRAMStart[0][1] && addr < NWRAMEnd[0][1]) + { + u8* ptr = NWRAMMap_B[0][(addr >> 15) & NWRAMMask[0][1]]; + return ptr ? *(u32*)&ptr[addr & 0x7FFF] : 0; + } + if (addr >= NWRAMStart[0][2] && addr < NWRAMEnd[0][2]) + { + u8* ptr = NWRAMMap_C[0][(addr >> 15) & NWRAMMask[0][2]]; + return ptr ? *(u32*)&ptr[addr & 0x7FFF] : 0; + } } return NDS::ARM9Read32(addr); @@ -926,41 +1032,69 @@ void ARM9Write8(u32 addr, u8 val) switch (addr & 0xFF000000) { case 0x03000000: - if (addr >= NWRAMStart[0][0] && addr < NWRAMEnd[0][0]) + case 0x03800000: + if (SCFG_EXT[0] & (1 << 25)) { - u8* ptr = NWRAMMap_A[0][(addr >> 16) & NWRAMMask[0][0]]; - if (ptr) + if (addr >= NWRAMStart[0][0] && addr < NWRAMEnd[0][0]) { - *(u8*)&ptr[addr & 0xFFFF] = val; + // Write to a bank is special, as it writes to all + // parts that are mapped and not just the highest priority + // See http://melonds.kuribo64.net/board/thread.php?pid=3974#3974 + // so we need to iterate through all parts and write to all mapped here + unsigned int destPartSetting = ((addr >> 13) & (NWRAMMask[0][0] << 3)) | 0x80; + for (int page = 0; page < 4; page++) + { + unsigned int bankInfo = (MBK[0][0 + (page / 4)] >> ((page % 4) * 8)) & 0xff; + if (bankInfo != destPartSetting) + continue; + u8* ptr = &NWRAM_A[page * 0x8000]; + *(u8*)&ptr[addr & 0x7FFF] = val; #ifdef JIT_ENABLED - ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_A>(addr); + ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_A>(addr); #endif + } + return; } - return; - } - if (addr >= NWRAMStart[0][1] && addr < NWRAMEnd[0][1]) - { - u8* ptr = NWRAMMap_B[0][(addr >> 15) & NWRAMMask[0][1]]; - if (ptr) + if (addr >= NWRAMStart[0][1] && addr < NWRAMEnd[0][1]) { - *(u8*)&ptr[addr & 0x7FFF] = val; + // Write to a bank is special, as it writes to all + // parts that are mapped and not just the highest priority + // See http://melonds.kuribo64.net/board/thread.php?pid=3974#3974 + // so we need to iterate through all parts and write to all mapped here + unsigned int destPartSetting = ((addr >> 13) & (NWRAMMask[0][1] << 2)) | 0x80; + for (int page = 0; page < 8; page++) + { + unsigned int bankInfo = (MBK[0][1 + (page / 4)] >> ((page % 4) * 8)) & 0xff; + if (bankInfo != destPartSetting) + continue; + u8* ptr = &NWRAM_B[page * 0x8000]; + *(u8*)&ptr[addr & 0x7FFF] = val; #ifdef JIT_ENABLED - ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_B>(addr); + ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_B>(addr); #endif + } + return; } - return; - } - if (addr >= NWRAMStart[0][2] && addr < NWRAMEnd[0][2]) - { - u8* ptr = NWRAMMap_C[0][(addr >> 15) & NWRAMMask[0][2]]; - if (ptr) + if (addr >= NWRAMStart[0][2] && addr < NWRAMEnd[0][2]) { - *(u8*)&ptr[addr & 0x7FFF] = val; + // Write to a bank is special, as it writes to all + // parts that are mapped and not just the highest priority + // See http://melonds.kuribo64.net/board/thread.php?pid=3974#3974 + // so we need to iterate through all parts and write to all mapped here + unsigned int destPartSetting = ((addr >> 13) & (NWRAMMask[0][2] << 2)) | 0x80; + for (int page = 0; page < 8; page++) + { + unsigned int bankInfo = (MBK[0][3 + (page / 4)] >> ((page % 4) * 8)) & 0xff; + if (bankInfo != destPartSetting) + continue; + u8* ptr = &NWRAM_C[page * 0x8000]; + *(u8*)&ptr[addr & 0x7FFF] = val; #ifdef JIT_ENABLED - ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_C>(addr); + ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_C>(addr); #endif + } + return; } - return; } return NDS::ARM9Write8(addr, val); @@ -996,41 +1130,69 @@ void ARM9Write16(u32 addr, u16 val) switch (addr & 0xFF000000) { case 0x03000000: - if (addr >= NWRAMStart[0][0] && addr < NWRAMEnd[0][0]) + case 0x03800000: + if (SCFG_EXT[0] & (1 << 25)) { - u8* ptr = NWRAMMap_A[0][(addr >> 16) & NWRAMMask[0][0]]; - if (ptr) + if (addr >= NWRAMStart[0][0] && addr < NWRAMEnd[0][0]) { - *(u16*)&ptr[addr & 0xFFFF] = val; + // Write to a bank is special, as it writes to all + // parts that are mapped and not just the highest priority + // See http://melonds.kuribo64.net/board/thread.php?pid=3974#3974 + // so we need to iterate through all parts and write to all mapped here + unsigned int destPartSetting = ((addr >> 13) & (NWRAMMask[0][0] << 3)) | 0x80; + for (int page = 0; page < 4; page++) + { + unsigned int bankInfo = (MBK[0][0 + (page / 4)] >> ((page % 4) * 8)) & 0xff; + if (bankInfo != destPartSetting) + continue; + u8* ptr = &NWRAM_A[page * 0x8000]; + *(u16*)&ptr[addr & 0x7FFF] = val; #ifdef JIT_ENABLED - ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_A>(addr); + ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_A>(addr); #endif + } + return; } - return; - } - if (addr >= NWRAMStart[0][1] && addr < NWRAMEnd[0][1]) - { - u8* ptr = NWRAMMap_B[0][(addr >> 15) & NWRAMMask[0][1]]; - if (ptr) + if (addr >= NWRAMStart[0][1] && addr < NWRAMEnd[0][1]) { - *(u16*)&ptr[addr & 0x7FFF] = val; + // Write to a bank is special, as it writes to all + // parts that are mapped and not just the highest priority + // See http://melonds.kuribo64.net/board/thread.php?pid=3974#3974 + // so we need to iterate through all parts and write to all mapped here + unsigned int destPartSetting = ((addr >> 13) & (NWRAMMask[0][1] << 2)) | 0x80; + for (int page = 0; page < 8; page++) + { + unsigned int bankInfo = (MBK[0][1 + (page / 4)] >> ((page % 4) * 8)) & 0xff; + if (bankInfo != destPartSetting) + continue; + u8* ptr = &NWRAM_B[page * 0x8000]; + *(u16*)&ptr[addr & 0x7FFF] = val; #ifdef JIT_ENABLED - ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_B>(addr); + ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_B>(addr); #endif + } + return; } - return; - } - if (addr >= NWRAMStart[0][2] && addr < NWRAMEnd[0][2]) - { - u8* ptr = NWRAMMap_C[0][(addr >> 15) & NWRAMMask[0][2]]; - if (ptr) + if (addr >= NWRAMStart[0][2] && addr < NWRAMEnd[0][2]) { - *(u16*)&ptr[addr & 0x7FFF] = val; + // Write to a bank is special, as it writes to all + // parts that are mapped and not just the highest priority + // See http://melonds.kuribo64.net/board/thread.php?pid=3974#3974 + // so we need to iterate through all parts and write to all mapped here + unsigned int destPartSetting = ((addr >> 13) & (NWRAMMask[0][2] << 2)) | 0x80; + for (int page = 0; page < 8; page++) + { + unsigned int bankInfo = (MBK[0][3 + (page / 4)] >> ((page % 4) * 8)) & 0xff; + if (bankInfo != destPartSetting) + continue; + u8* ptr = &NWRAM_C[page * 0x8000]; + *(u16*)&ptr[addr & 0x7FFF] = val; #ifdef JIT_ENABLED - ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_C>(addr); + ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_C>(addr); #endif + } + return; } - return; } return NDS::ARM9Write16(addr, val); @@ -1052,41 +1214,69 @@ void ARM9Write32(u32 addr, u32 val) switch (addr & 0xFF000000) { case 0x03000000: - if (addr >= NWRAMStart[0][0] && addr < NWRAMEnd[0][0]) + case 0x03800000: + if (SCFG_EXT[0] & (1 << 25)) { - u8* ptr = NWRAMMap_A[0][(addr >> 16) & NWRAMMask[0][0]]; - if (ptr) + if (addr >= NWRAMStart[0][0] && addr < NWRAMEnd[0][0]) { - *(u32*)&ptr[addr & 0xFFFF] = val; + // Write to a bank is special, as it writes to all + // parts that are mapped and not just the highest priority + // See http://melonds.kuribo64.net/board/thread.php?pid=3974#3974 + // so we need to iterate through all parts and write to all mapped here + unsigned int destPartSetting = ((addr >> 13) & (NWRAMMask[0][0] << 3)) | 0x80; + for (int page = 0; page < 4; page++) + { + unsigned int bankInfo = (MBK[0][0 + (page / 4)] >> ((page % 4) * 8)) & 0xff; + if (bankInfo != destPartSetting) + continue; + u8* ptr = &NWRAM_A[page * 0x8000]; + *(u32*)&ptr[addr & 0x7FFF] = val; #ifdef JIT_ENABLED - ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_A>(addr); + ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_A>(addr); #endif + } + return; } - return; - } - if (addr >= NWRAMStart[0][1] && addr < NWRAMEnd[0][1]) - { - u8* ptr = NWRAMMap_B[0][(addr >> 15) & NWRAMMask[0][1]]; - if (ptr) + if (addr >= NWRAMStart[0][1] && addr < NWRAMEnd[0][1]) { - *(u32*)&ptr[addr & 0x7FFF] = val; + // Write to a bank is special, as it writes to all + // parts that are mapped and not just the highest priority + // See http://melonds.kuribo64.net/board/thread.php?pid=3974#3974 + // so we need to iterate through all parts and write to all mapped here + unsigned int destPartSetting = ((addr >> 13) & (NWRAMMask[0][1] << 2)) | 0x80; + for (int page = 0; page < 8; page++) + { + unsigned int bankInfo = (MBK[0][1 + (page / 4)] >> ((page % 4) * 8)) & 0xff; + if (bankInfo != destPartSetting) + continue; + u8* ptr = &NWRAM_B[page * 0x8000]; + *(u32*)&ptr[addr & 0x7FFF] = val; #ifdef JIT_ENABLED - ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_B>(addr); + ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_B>(addr); #endif + } + return; } - return; - } - if (addr >= NWRAMStart[0][2] && addr < NWRAMEnd[0][2]) - { - u8* ptr = NWRAMMap_C[0][(addr >> 15) & NWRAMMask[0][2]]; - if (ptr) + if (addr >= NWRAMStart[0][2] && addr < NWRAMEnd[0][2]) { - *(u32*)&ptr[addr & 0x7FFF] = val; + // Write to a bank is special, as it writes to all + // parts that are mapped and not just the highest priority + // See http://melonds.kuribo64.net/board/thread.php?pid=3974#3974 + // so we need to iterate through all parts and write to all mapped here + unsigned int destPartSetting = ((addr >> 13) & (NWRAMMask[0][2] << 2)) | 0x80; + for (int page = 0; page < 8; page++) + { + unsigned int bankInfo = (MBK[0][3 + (page / 4)] >> ((page % 4) * 8)) & 0xff; + if (bankInfo != destPartSetting) + continue; + u8* ptr = &NWRAM_C[page * 0x8000]; + *(u32*)&ptr[addr & 0x7FFF] = val; #ifdef JIT_ENABLED - ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_C>(addr); + ARMJIT::CheckAndInvalidate<0, ARMJIT_Memory::memregion_NewSharedWRAM_C>(addr); #endif + } + return; } - return; } return NDS::ARM9Write32(addr, val); @@ -1151,26 +1341,30 @@ u8 ARM7Read8(u32 addr) if (addr < NDS::ARM7BIOSProt && NDS::ARM7->R[15] >= NDS::ARM7BIOSProt) return 0xFF; - return *(u8*)&ARM7iBIOS[addr]; + return *(u8*)&ARM7iBIOS[addr & 0xFFFF]; } switch (addr & 0xFF800000) { case 0x03000000: - if (addr >= NWRAMStart[1][0] && addr < NWRAMEnd[1][0]) + case 0x03800000: + if (SCFG_EXT[1] & (1 << 25)) { - u8* ptr = NWRAMMap_A[1][(addr >> 16) & NWRAMMask[1][0]]; - return ptr ? *(u8*)&ptr[addr & 0xFFFF] : 0; - } - if (addr >= NWRAMStart[1][1] && addr < NWRAMEnd[1][1]) - { - u8* ptr = NWRAMMap_B[1][(addr >> 15) & NWRAMMask[1][1]]; - return ptr ? *(u8*)&ptr[addr & 0x7FFF] : 0; - } - if (addr >= NWRAMStart[1][2] && addr < NWRAMEnd[1][2]) - { - u8* ptr = NWRAMMap_C[1][(addr >> 15) & NWRAMMask[1][2]]; - return ptr ? *(u8*)&ptr[addr & 0x7FFF] : 0; + if (addr >= NWRAMStart[1][0] && addr < NWRAMEnd[1][0]) + { + u8* ptr = NWRAMMap_A[1][(addr >> 16) & NWRAMMask[1][0]]; + return ptr ? *(u8*)&ptr[addr & 0xFFFF] : 0; + } + if (addr >= NWRAMStart[1][1] && addr < NWRAMEnd[1][1]) + { + u8* ptr = NWRAMMap_B[1][(addr >> 15) & NWRAMMask[1][1]]; + return ptr ? *(u8*)&ptr[addr & 0x7FFF] : 0; + } + if (addr >= NWRAMStart[1][2] && addr < NWRAMEnd[1][2]) + { + u8* ptr = NWRAMMap_C[1][(addr >> 15) & NWRAMMask[1][2]]; + return ptr ? *(u8*)&ptr[addr & 0x7FFF] : 0; + } } return NDS::ARM7Read8(addr); @@ -1200,26 +1394,30 @@ u16 ARM7Read16(u32 addr) if (addr < NDS::ARM7BIOSProt && NDS::ARM7->R[15] >= NDS::ARM7BIOSProt) return 0xFFFF; - return *(u16*)&ARM7iBIOS[addr]; + return *(u16*)&ARM7iBIOS[addr & 0xFFFF]; } switch (addr & 0xFF800000) { case 0x03000000: - if (addr >= NWRAMStart[1][0] && addr < NWRAMEnd[1][0]) + case 0x03800000: + if (SCFG_EXT[1] & (1 << 25)) { - u8* ptr = NWRAMMap_A[1][(addr >> 16) & NWRAMMask[1][0]]; - return ptr ? *(u16*)&ptr[addr & 0xFFFF] : 0; - } - if (addr >= NWRAMStart[1][1] && addr < NWRAMEnd[1][1]) - { - u8* ptr = NWRAMMap_B[1][(addr >> 15) & NWRAMMask[1][1]]; - return ptr ? *(u16*)&ptr[addr & 0x7FFF] : 0; - } - if (addr >= NWRAMStart[1][2] && addr < NWRAMEnd[1][2]) - { - u8* ptr = NWRAMMap_C[1][(addr >> 15) & NWRAMMask[1][2]]; - return ptr ? *(u16*)&ptr[addr & 0x7FFF] : 0; + if (addr >= NWRAMStart[1][0] && addr < NWRAMEnd[1][0]) + { + u8* ptr = NWRAMMap_A[1][(addr >> 16) & NWRAMMask[1][0]]; + return ptr ? *(u16*)&ptr[addr & 0xFFFF] : 0; + } + if (addr >= NWRAMStart[1][1] && addr < NWRAMEnd[1][1]) + { + u8* ptr = NWRAMMap_B[1][(addr >> 15) & NWRAMMask[1][1]]; + return ptr ? *(u16*)&ptr[addr & 0x7FFF] : 0; + } + if (addr >= NWRAMStart[1][2] && addr < NWRAMEnd[1][2]) + { + u8* ptr = NWRAMMap_C[1][(addr >> 15) & NWRAMMask[1][2]]; + return ptr ? *(u16*)&ptr[addr & 0x7FFF] : 0; + } } return NDS::ARM7Read16(addr); @@ -1249,26 +1447,30 @@ u32 ARM7Read32(u32 addr) if (addr < NDS::ARM7BIOSProt && NDS::ARM7->R[15] >= NDS::ARM7BIOSProt) return 0xFFFFFFFF; - return *(u32*)&ARM7iBIOS[addr]; + return *(u32*)&ARM7iBIOS[addr & 0xFFFF]; } switch (addr & 0xFF800000) { case 0x03000000: - if (addr >= NWRAMStart[1][0] && addr < NWRAMEnd[1][0]) + case 0x03800000: + if (SCFG_EXT[1] & (1 << 25)) { - u8* ptr = NWRAMMap_A[1][(addr >> 16) & NWRAMMask[1][0]]; - return ptr ? *(u32*)&ptr[addr & 0xFFFF] : 0; - } - if (addr >= NWRAMStart[1][1] && addr < NWRAMEnd[1][1]) - { - u8* ptr = NWRAMMap_B[1][(addr >> 15) & NWRAMMask[1][1]]; - return ptr ? *(u32*)&ptr[addr & 0x7FFF] : 0; - } - if (addr >= NWRAMStart[1][2] && addr < NWRAMEnd[1][2]) - { - u8* ptr = NWRAMMap_C[1][(addr >> 15) & NWRAMMask[1][2]]; - return ptr ? *(u32*)&ptr[addr & 0x7FFF] : 0; + if (addr >= NWRAMStart[1][0] && addr < NWRAMEnd[1][0]) + { + u8* ptr = NWRAMMap_A[1][(addr >> 16) & NWRAMMask[1][0]]; + return ptr ? *(u32*)&ptr[addr & 0xFFFF] : 0; + } + if (addr >= NWRAMStart[1][1] && addr < NWRAMEnd[1][1]) + { + u8* ptr = NWRAMMap_B[1][(addr >> 15) & NWRAMMask[1][1]]; + return ptr ? *(u32*)&ptr[addr & 0x7FFF] : 0; + } + if (addr >= NWRAMStart[1][2] && addr < NWRAMEnd[1][2]) + { + u8* ptr = NWRAMMap_C[1][(addr >> 15) & NWRAMMask[1][2]]; + return ptr ? *(u32*)&ptr[addr & 0x7FFF] : 0; + } } return NDS::ARM7Read32(addr); @@ -1292,41 +1494,69 @@ void ARM7Write8(u32 addr, u8 val) switch (addr & 0xFF800000) { case 0x03000000: - if (addr >= NWRAMStart[1][0] && addr < NWRAMEnd[1][0]) + case 0x03800000: + if (SCFG_EXT[1] & (1 << 25)) { - u8* ptr = NWRAMMap_A[1][(addr >> 16) & NWRAMMask[1][0]]; - if (ptr) + if (addr >= NWRAMStart[1][0] && addr < NWRAMEnd[1][0]) { - *(u8*)&ptr[addr & 0xFFFF] = val; + // Write to a bank is special, as it writes to all + // parts that are mapped and not just the highest priority + // See http://melonds.kuribo64.net/board/thread.php?pid=3974#3974 + // so we need to iterate through all parts and write to all mapped here + unsigned int destPartSetting = ((addr >> 13) & (NWRAMMask[1][0] << 3)) | 0x81; + for (int page = 0; page < 4; page++) + { + unsigned int bankInfo = (MBK[1][0 + (page / 4)] >> ((page % 4) * 8)) & 0xff; + if (bankInfo != destPartSetting) + continue; + u8* ptr = &NWRAM_A[page * 0x8000]; + *(u8*)&ptr[addr & 0x7FFF] = val; #ifdef JIT_ENABLED - ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_A>(addr); + ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_A>(addr); #endif + } + return; } - return; - } - if (addr >= NWRAMStart[1][1] && addr < NWRAMEnd[1][1]) - { - u8* ptr = NWRAMMap_B[1][(addr >> 15) & NWRAMMask[1][1]]; - if (ptr) + if (addr >= NWRAMStart[1][1] && addr < NWRAMEnd[1][1]) { - *(u8*)&ptr[addr & 0x7FFF] = val; + // Write to a bank is special, as it writes to all + // parts that are mapped and not just the highest priority + // See http://melonds.kuribo64.net/board/thread.php?pid=3974#3974 + // so we need to iterate through all parts and write to all mapped here + unsigned int destPartSetting = ((addr >> 13) & (NWRAMMask[1][1] << 2)) | 0x81; + for (int page = 0; page < 8; page++) + { + unsigned int bankInfo = (MBK[1][1 + (page / 4)] >> ((page % 4) * 8)) & 0xff; + if (bankInfo != destPartSetting) + continue; + u8* ptr = &NWRAM_B[page * 0x8000]; + *(u8*)&ptr[addr & 0x7FFF] = val; #ifdef JIT_ENABLED - ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_B>(addr); + ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_B>(addr); #endif + } + return; } - return; - } - if (addr >= NWRAMStart[1][2] && addr < NWRAMEnd[1][2]) - { - u8* ptr = NWRAMMap_C[1][(addr >> 15) & NWRAMMask[1][2]]; - if (ptr) + if (addr >= NWRAMStart[1][2] && addr < NWRAMEnd[1][2]) { - *(u8*)&ptr[addr & 0x7FFF] = val; + // Write to a bank is special, as it writes to all + // parts that are mapped and not just the highest priority + // See http://melonds.kuribo64.net/board/thread.php?pid=3974#3974 + // so we need to iterate through all parts and write to all mapped here + unsigned int destPartSetting = ((addr >> 13) & (NWRAMMask[1][2] << 2)) | 0x81; + for (int page = 0; page < 8; page++) + { + unsigned int bankInfo = (MBK[1][3 + (page / 4)] >> ((page % 4) * 8)) & 0xff; + if (bankInfo != destPartSetting) + continue; + u8* ptr = &NWRAM_C[page * 0x8000]; + *(u8*)&ptr[addr & 0x7FFF] = val; #ifdef JIT_ENABLED - ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_C>(addr); + ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_C>(addr); #endif + } + return; } - return; } return NDS::ARM7Write8(addr, val); @@ -1351,41 +1581,69 @@ void ARM7Write16(u32 addr, u16 val) switch (addr & 0xFF800000) { case 0x03000000: - if (addr >= NWRAMStart[1][0] && addr < NWRAMEnd[1][0]) + case 0x03800000: + if (SCFG_EXT[1] & (1 << 25)) { - u8* ptr = NWRAMMap_A[1][(addr >> 16) & NWRAMMask[1][0]]; - if (ptr) + if (addr >= NWRAMStart[1][0] && addr < NWRAMEnd[1][0]) { - *(u16*)&ptr[addr & 0xFFFF] = val; + // Write to a bank is special, as it writes to all + // parts that are mapped and not just the highest priority + // See http://melonds.kuribo64.net/board/thread.php?pid=3974#3974 + // so we need to iterate through all parts and write to all mapped here + unsigned int destPartSetting = ((addr >> 13) & (NWRAMMask[1][0] << 3)) | 0x81; + for (int page = 0; page < 4; page++) + { + unsigned int bankInfo = (MBK[1][0 + (page / 4)] >> ((page % 4) * 8)) & 0xff; + if (bankInfo != destPartSetting) + continue; + u8* ptr = &NWRAM_A[page * 0x8000]; + *(u16*)&ptr[addr & 0x7FFF] = val; #ifdef JIT_ENABLED - ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_A>(addr); + ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_A>(addr); #endif + } + return; } - return; - } - if (addr >= NWRAMStart[1][1] && addr < NWRAMEnd[1][1]) - { - u8* ptr = NWRAMMap_B[1][(addr >> 15) & NWRAMMask[1][1]]; - if (ptr) + if (addr >= NWRAMStart[1][1] && addr < NWRAMEnd[1][1]) { - *(u16*)&ptr[addr & 0x7FFF] = val; + // Write to a bank is special, as it writes to all + // parts that are mapped and not just the highest priority + // See http://melonds.kuribo64.net/board/thread.php?pid=3974#3974 + // so we need to iterate through all parts and write to all mapped here + unsigned int destPartSetting = ((addr >> 13) & (NWRAMMask[1][1] << 2)) | 0x81; + for (int page = 0; page < 8; page++) + { + unsigned int bankInfo = (MBK[1][1 + (page / 4)] >> ((page % 4) * 8)) & 0xff; + if (bankInfo != destPartSetting) + continue; + u8* ptr = &NWRAM_B[page * 0x8000]; + *(u16*)&ptr[addr & 0x7FFF] = val; #ifdef JIT_ENABLED - ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_B>(addr); + ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_B>(addr); #endif + } + return; } - return; - } - if (addr >= NWRAMStart[1][2] && addr < NWRAMEnd[1][2]) - { - u8* ptr = NWRAMMap_C[1][(addr >> 15) & NWRAMMask[1][2]]; - if (ptr) + if (addr >= NWRAMStart[1][2] && addr < NWRAMEnd[1][2]) { - *(u16*)&ptr[addr & 0x7FFF] = val; + // Write to a bank is special, as it writes to all + // parts that are mapped and not just the highest priority + // See http://melonds.kuribo64.net/board/thread.php?pid=3974#3974 + // so we need to iterate through all parts and write to all mapped here + unsigned int destPartSetting = ((addr >> 13) & (NWRAMMask[1][2] << 2)) | 0x81; + for (int page = 0; page < 8; page++) + { + unsigned int bankInfo = (MBK[1][3 + (page / 4)] >> ((page % 4) * 8)) & 0xff; + if (bankInfo != destPartSetting) + continue; + u8* ptr = &NWRAM_C[page * 0x8000]; + *(u16*)&ptr[addr & 0x7FFF] = val; #ifdef JIT_ENABLED - ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_C>(addr); + ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_C>(addr); #endif + } + return; } - return; } return NDS::ARM7Write16(addr, val); @@ -1410,41 +1668,69 @@ void ARM7Write32(u32 addr, u32 val) switch (addr & 0xFF800000) { case 0x03000000: - if (addr >= NWRAMStart[1][0] && addr < NWRAMEnd[1][0]) + case 0x03800000: + if (SCFG_EXT[1] & (1 << 25)) { - u8* ptr = NWRAMMap_A[1][(addr >> 16) & NWRAMMask[1][0]]; - if (ptr) + if (addr >= NWRAMStart[1][0] && addr < NWRAMEnd[1][0]) { - *(u32*)&ptr[addr & 0xFFFF] = val; + // Write to a bank is special, as it writes to all + // parts that are mapped and not just the highest priority + // See http://melonds.kuribo64.net/board/thread.php?pid=3974#3974 + // so we need to iterate through all parts and write to all mapped here + unsigned int destPartSetting = ((addr >> 13) & (NWRAMMask[1][0] << 3)) | 0x81; + for (int page = 0; page < 4; page++) + { + unsigned int bankInfo = (MBK[1][0 + (page / 4)] >> ((page % 4) * 8)) & 0xff; + if (bankInfo != destPartSetting) + continue; + u8* ptr = &NWRAM_A[page * 0x8000]; + *(u32*)&ptr[addr & 0x7FFF] = val; #ifdef JIT_ENABLED - ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_A>(addr); + ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_A>(addr); #endif + } + return; } - return; - } - if (addr >= NWRAMStart[1][1] && addr < NWRAMEnd[1][1]) - { - u8* ptr = NWRAMMap_B[1][(addr >> 15) & NWRAMMask[1][1]]; - if (ptr) + if (addr >= NWRAMStart[1][1] && addr < NWRAMEnd[1][1]) { - *(u32*)&ptr[addr & 0x7FFF] = val; + // Write to a bank is special, as it writes to all + // parts that are mapped and not just the highest priority + // See http://melonds.kuribo64.net/board/thread.php?pid=3974#3974 + // so we need to iterate through all parts and write to all mapped here + unsigned int destPartSetting = ((addr >> 13) & (NWRAMMask[1][1] << 2)) | 0x81; + for (int page = 0; page < 8; page++) + { + unsigned int bankInfo = (MBK[1][1 + (page / 4)] >> ((page % 4) * 8)) & 0xff; + if (bankInfo != destPartSetting) + continue; + u8* ptr = &NWRAM_B[page * 0x8000]; + *(u32*)&ptr[addr & 0x7FFF] = val; #ifdef JIT_ENABLED - ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_B>(addr); + ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_B>(addr); #endif + } + return; } - return; - } - if (addr >= NWRAMStart[1][2] && addr < NWRAMEnd[1][2]) - { - u8* ptr = NWRAMMap_C[1][(addr >> 15) & NWRAMMask[1][2]]; - if (ptr) + if (addr >= NWRAMStart[1][2] && addr < NWRAMEnd[1][2]) { - *(u32*)&ptr[addr & 0x7FFF] = val; + // Write to a bank is special, as it writes to all + // parts that are mapped and not just the highest priority + // See http://melonds.kuribo64.net/board/thread.php?pid=3974#3974 + // so we need to iterate through all parts and write to all mapped here + unsigned int destPartSetting = ((addr >> 13) & (NWRAMMask[1][2] << 2)) | 0x81; + for (int page = 0; page < 8; page++) + { + unsigned int bankInfo = (MBK[1][3 + (page / 4)] >> ((page % 4) * 8)) & 0xff; + if (bankInfo != destPartSetting) + continue; + u8* ptr = &NWRAM_C[page * 0x8000]; + *(u32*)&ptr[addr & 0x7FFF] = val; #ifdef JIT_ENABLED - ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_C>(addr); + ARMJIT::CheckAndInvalidate<1, ARMJIT_Memory::memregion_NewSharedWRAM_C>(addr); #endif + } + return; } - return; } return NDS::ARM7Write32(addr, val); @@ -1643,30 +1929,44 @@ void ARM9IOWrite8(u32 addr, u8 val) return; case 0x04004006: + if (!(SCFG_EXT[1] & (1 << 31))) /* no access to SCFG Registers if disabled*/ + return; SCFG_RST = (SCFG_RST & 0xFF00) | val; DSi_DSP::SetRstLine(val & 1); return; - case 0x04004040: MapNWRAM_A(0, val); return; - case 0x04004041: MapNWRAM_A(1, val); return; - case 0x04004042: MapNWRAM_A(2, val); return; - case 0x04004043: MapNWRAM_A(3, val); return; - case 0x04004044: MapNWRAM_B(0, val); return; - case 0x04004045: MapNWRAM_B(1, val); return; - case 0x04004046: MapNWRAM_B(2, val); return; - case 0x04004047: MapNWRAM_B(3, val); return; - case 0x04004048: MapNWRAM_B(4, val); return; - case 0x04004049: MapNWRAM_B(5, val); return; - case 0x0400404A: MapNWRAM_B(6, val); return; - case 0x0400404B: MapNWRAM_B(7, val); return; - case 0x0400404C: MapNWRAM_C(0, val); return; - case 0x0400404D: MapNWRAM_C(1, val); return; - case 0x0400404E: MapNWRAM_C(2, val); return; - case 0x0400404F: MapNWRAM_C(3, val); return; - case 0x04004050: MapNWRAM_C(4, val); return; - case 0x04004051: MapNWRAM_C(5, val); return; - case 0x04004052: MapNWRAM_C(6, val); return; - case 0x04004053: MapNWRAM_C(7, val); return; + case 0x04004040: + case 0x04004041: + case 0x04004042: + case 0x04004043: + if (!(SCFG_EXT[1] & (1 << 31))) /* no access to SCFG Registers if disabled*/ + return; + MapNWRAM_A(addr & 3, val); + return; + case 0x04004044: + case 0x04004045: + case 0x04004046: + case 0x04004047: + case 0x04004048: + case 0x04004049: + case 0x0400404A: + case 0x0400404B: + if (!(SCFG_EXT[1] & (1 << 31))) /* no access to SCFG Registers if disabled*/ + return; + MapNWRAM_B((addr - 0x04) & 7, val); + return; + case 0x0400404C: + case 0x0400404D: + case 0x0400404E: + case 0x0400404F: + case 0x04004050: + case 0x04004051: + case 0x04004052: + case 0x04004053: + if (!(SCFG_EXT[1] & (1 << 31))) /* no access to SCFG Registers if disabled*/ + return; + MapNWRAM_C((addr-0x0C) & 7, val); + return; } if ((addr & 0xFFFFFF00) == 0x04004200) @@ -1689,53 +1989,43 @@ void ARM9IOWrite16(u32 addr, u16 val) switch (addr) { case 0x04004004: + if (!(SCFG_EXT[0] & (1 << 31))) /* no access to SCFG Registers if disabled*/ + return; Set_SCFG_Clock9(val); return; case 0x04004006: + if (!(SCFG_EXT[0] & (1 << 31))) /* no access to SCFG Registers if disabled*/ + return; SCFG_RST = val; DSi_DSP::SetRstLine(val & 1); return; case 0x04004040: - MapNWRAM_A(0, val & 0xFF); - MapNWRAM_A(1, val >> 8); - return; case 0x04004042: - MapNWRAM_A(2, val & 0xFF); - MapNWRAM_A(3, val >> 8); + if (!(SCFG_EXT[0] & (1 << 31))) /* no access to SCFG Registers if disabled*/ + return; + MapNWRAM_A((addr & 2), val & 0xFF); + MapNWRAM_A((addr & 2) + 1, val >> 8); return; + case 0x04004044: - MapNWRAM_B(0, val & 0xFF); - MapNWRAM_B(1, val >> 8); - return; case 0x04004046: - MapNWRAM_B(2, val & 0xFF); - MapNWRAM_B(3, val >> 8); - return; case 0x04004048: - MapNWRAM_B(4, val & 0xFF); - MapNWRAM_B(5, val >> 8); - return; case 0x0400404A: - MapNWRAM_B(6, val & 0xFF); - MapNWRAM_B(7, val >> 8); + if (!(SCFG_EXT[0] & (1 << 31))) /* no access to SCFG Registers if disabled*/ + return; + MapNWRAM_B(((addr - 0x04) & 6), val & 0xFF); + MapNWRAM_B(((addr - 0x04) & 6) + 1, val >> 8); return; case 0x0400404C: - MapNWRAM_C(0, val & 0xFF); - MapNWRAM_C(1, val >> 8); - return; case 0x0400404E: - MapNWRAM_C(2, val & 0xFF); - MapNWRAM_C(3, val >> 8); - return; case 0x04004050: - MapNWRAM_C(4, val & 0xFF); - MapNWRAM_C(5, val >> 8); - return; case 0x04004052: - MapNWRAM_C(6, val & 0xFF); - MapNWRAM_C(7, val >> 8); + if (!(SCFG_EXT[0] & (1 << 31))) /* no access to SCFG Registers if disabled*/ + return; + MapNWRAM_C(((addr - 0x0C) & 6), val & 0xFF); + MapNWRAM_C(((addr - 0x0C) & 6) + 1, val >> 8); return; } @@ -1759,6 +2049,8 @@ void ARM9IOWrite32(u32 addr, u32 val) switch (addr) { case 0x04004004: + if (!(SCFG_EXT[0] & (1 << 31))) /* no access to SCFG Registers if disabled*/ + return; Set_SCFG_Clock9(val & 0xFFFF); SCFG_RST = val >> 16; DSi_DSP::SetRstLine((val >> 16) & 1); @@ -1766,6 +2058,8 @@ void ARM9IOWrite32(u32 addr, u32 val) case 0x04004008: { + if (!(SCFG_EXT[0] & (1 << 31))) /* no access to SCFG Registers if disabled*/ + return; u32 oldram = (SCFG_EXT[0] >> 14) & 0x3; u32 newram = (val >> 14) & 0x3; @@ -1799,38 +2093,60 @@ void ARM9IOWrite32(u32 addr, u32 val) return; case 0x04004040: + if (!(SCFG_EXT[0] & (1 << 31))) /* no access to SCFG Registers if disabled*/ + return; MapNWRAM_A(0, val & 0xFF); MapNWRAM_A(1, (val >> 8) & 0xFF); MapNWRAM_A(2, (val >> 16) & 0xFF); MapNWRAM_A(3, val >> 24); return; case 0x04004044: + if (!(SCFG_EXT[0] & (1 << 31))) /* no access to SCFG Registers if disabled*/ + return; MapNWRAM_B(0, val & 0xFF); MapNWRAM_B(1, (val >> 8) & 0xFF); MapNWRAM_B(2, (val >> 16) & 0xFF); MapNWRAM_B(3, val >> 24); return; case 0x04004048: + if (!(SCFG_EXT[0] & (1 << 31))) /* no access to SCFG Registers if disabled*/ + return; MapNWRAM_B(4, val & 0xFF); MapNWRAM_B(5, (val >> 8) & 0xFF); MapNWRAM_B(6, (val >> 16) & 0xFF); MapNWRAM_B(7, val >> 24); return; case 0x0400404C: + if (!(SCFG_EXT[0] & (1 << 31))) /* no access to SCFG Registers if disabled*/ + return; MapNWRAM_C(0, val & 0xFF); MapNWRAM_C(1, (val >> 8) & 0xFF); MapNWRAM_C(2, (val >> 16) & 0xFF); MapNWRAM_C(3, val >> 24); return; case 0x04004050: + if (!(SCFG_EXT[0] & (1 << 31))) /* no access to SCFG Registers if disabled*/ + return; MapNWRAM_C(4, val & 0xFF); MapNWRAM_C(5, (val >> 8) & 0xFF); MapNWRAM_C(6, (val >> 16) & 0xFF); MapNWRAM_C(7, val >> 24); return; - case 0x04004054: MapNWRAMRange(0, 0, val); return; - case 0x04004058: MapNWRAMRange(0, 1, val); return; - case 0x0400405C: MapNWRAMRange(0, 2, val); return; + case 0x04004054: + if (!(SCFG_EXT[0] & (1 << 31))) /* no access to SCFG Registers if disabled*/ + return; + MapNWRAMRange(0, 0, val); + return; + case 0x04004058: + if (!(SCFG_EXT[0] & (1 << 31))) /* no access to SCFG Registers if disabled*/ + return; + MapNWRAMRange(0, 1, val); + return; + case 0x0400405C: + if (!(SCFG_EXT[0] & (1 << 31))) /* no access to SCFG Registers if disabled*/ + return; + MapNWRAMRange(0, 2, val); + return; case 0x04004100: NDMACnt[0] = val & 0x800F0000; return; case 0x04004104: NDMAs[0]->SrcAddr = val & 0xFFFFFFFC; return; @@ -1877,7 +2193,8 @@ u8 ARM7IORead8(u32 addr) { switch (addr) { - case 0x04004000: return SCFG_BIOS & 0xFF; + case 0x04004000: + return SCFG_BIOS & 0xFF; case 0x04004001: return SCFG_BIOS >> 8; CASE_READ8_32BIT(0x04004040, MBK[1][0]) @@ -2026,11 +2343,29 @@ void ARM7IOWrite8(u32 addr, u8 val) switch (addr) { case 0x04004000: + if (!(SCFG_EXT[1] & (1 << 31))) /* no access to SCFG Registers if disabled*/ + return; SCFG_BIOS |= (val & 0x03); return; case 0x04004001: + if (!(SCFG_EXT[1] & (1 << 31))) /* no access to SCFG Registers if disabled*/ + return; SCFG_BIOS |= ((val & 0x07) << 8); return; + case 0x04004060: + case 0x04004061: + case 0x04004062: + case 0x04004063: + { + if (!(SCFG_EXT[1] & (1 << 31))) /* no access to SCFG Registers if disabled*/ + return; + u32 tmp = MBK[0][8]; + tmp &= ~(0xff << ((addr % 4) * 8)); + tmp |= (val << ((addr % 4) * 8)); + MBK[0][8] = tmp & 0x00FFFF0F; + MBK[1][8] = MBK[0][8]; + return; + } case 0x04004500: DSi_I2C::WriteData(val); return; case 0x04004501: DSi_I2C::WriteCnt(val); return; @@ -2043,18 +2378,34 @@ void ARM7IOWrite16(u32 addr, u16 val) { switch (addr) { - case 0x04000218: NDS::IE2 = (val & 0x7FF7); NDS::UpdateIRQ(1); return; - case 0x0400021C: NDS::IF2 &= ~(val & 0x7FF7); NDS::UpdateIRQ(1); return; + case 0x04000218: NDS::IE2 = (val & 0x7FF7); NDS::UpdateIRQ(1); return; + case 0x0400021C: NDS::IF2 &= ~(val & 0x7FF7); NDS::UpdateIRQ(1); return; - case 0x04004000: - SCFG_BIOS |= (val & 0x0703); - return; - case 0x04004004: - SCFG_Clock7 = val & 0x0187; - return; - case 0x04004010: - Set_SCFG_MC((SCFG_MC & 0xFFFF0000) | val); - return; + case 0x04004000: + if (!(SCFG_EXT[1] & (1 << 31))) /* no access to SCFG Registers if disabled*/ + return; + SCFG_BIOS |= (val & 0x0703); + return; + case 0x04004004: + if (!(SCFG_EXT[1] & (1 << 31))) /* no access to SCFG Registers if disabled*/ + return; + SCFG_Clock7 = val & 0x0187; + return; + case 0x04004010: + if (!(SCFG_EXT[1] & (1 << 31))) /* no access to SCFG Registers if disabled*/ + return; + Set_SCFG_MC((SCFG_MC & 0xFFFF0000) | val); + return; + case 0x04004060: + case 0x04004062: + if (!(SCFG_EXT[1] & (1 << 31))) /* no access to SCFG Registers if disabled*/ + return; + u32 tmp = MBK[0][8]; + tmp &= ~(0xffff << ((addr % 4) * 8)); + tmp |= (val << ((addr % 4) * 8)); + MBK[0][8] = tmp & 0x00FFFF0F; + MBK[1][8] = MBK[0][8]; + return; } if (addr >= 0x04004800 && addr < 0x04004A00) @@ -2079,9 +2430,13 @@ void ARM7IOWrite32(u32 addr, u32 val) case 0x0400021C: NDS::IF2 &= ~(val & 0x7FF7); NDS::UpdateIRQ(1); return; case 0x04004000: + if (!(SCFG_EXT[1] & (1 << 31))) /* no access to SCFG Registers if disabled*/ + return; SCFG_BIOS |= (val & 0x0703); return; case 0x04004008: + if (!(SCFG_EXT[1] & (1 << 31))) /* no access to SCFG Registers if disabled*/ + return; SCFG_EXT[0] &= ~0x03000000; SCFG_EXT[0] |= (val & 0x03000000); SCFG_EXT[1] &= ~0x93FF0F07; @@ -2089,13 +2444,33 @@ void ARM7IOWrite32(u32 addr, u32 val) printf("SCFG_EXT = %08X / %08X (val7 %08X)\n", SCFG_EXT[0], SCFG_EXT[1], val); return; case 0x04004010: + if (!(SCFG_EXT[1] & (1 << 31))) /* no access to SCFG Registers if disabled*/ + return; Set_SCFG_MC(val); return; - case 0x04004054: MapNWRAMRange(1, 0, val); return; - case 0x04004058: MapNWRAMRange(1, 1, val); return; - case 0x0400405C: MapNWRAMRange(1, 2, val); return; - case 0x04004060: val &= 0x00FFFF0F; MBK[0][8] = val; MBK[1][8] = val; return; + case 0x04004054: + if (!(SCFG_EXT[1] & (1 << 31))) /* no access to SCFG Registers if disabled*/ + return; + MapNWRAMRange(1, 0, val); + return; + case 0x04004058: + if (!(SCFG_EXT[1] & (1 << 31))) /* no access to SCFG Registers if disabled*/ + return; + MapNWRAMRange(1, 1, val); + return; + case 0x0400405C: + if (!(SCFG_EXT[1] & (1 << 31))) /* no access to SCFG Registers if disabled*/ + return; + MapNWRAMRange(1, 2, val); + return; + case 0x04004060: + if (!(SCFG_EXT[1] & (1 << 31))) /* no access to SCFG Registers if disabled*/ + return; + val &= 0x00FFFF0F; + MBK[0][8] = val; + MBK[1][8] = val; + return; case 0x04004100: NDMACnt[1] = val & 0x800F0000; return; case 0x04004104: NDMAs[4]->SrcAddr = val & 0xFFFFFFFC; return; diff --git a/src/DSi.h b/src/DSi.h index a56df663..187dc52e 100644 --- a/src/DSi.h +++ b/src/DSi.h @@ -60,6 +60,7 @@ bool Init(); void DeInit(); void Reset(); +void SetupDirectBoot(); void SoftReset(); bool LoadBIOS(); diff --git a/src/NDS.cpp b/src/NDS.cpp index 699b3a6e..cd0cb92c 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -164,7 +164,6 @@ bool Running; bool RunningGame; - void DivDone(u32 param); void SqrtDone(u32 param); void RunTimer(u32 tid, s32 cycles); @@ -342,8 +341,13 @@ void SetupDirectBoot() { if (ConsoleType == 1) { - printf("!! DIRECT BOOT NOT SUPPORTED IN DSI MODE\n"); - return; + // With the BIOS select in SCFG_BIOS and the initialization od + // SCFG_BIOS depending on the Header->UnitType, we can now boot + // directly in the roms. + // There are some more SCFG Settings that change depending on + // the unit type, so this is experimental + printf("!! DIRECT BOOT NOT STABLE IN DSI MODE\n"); + DSi::SetupDirectBoot(); } u32 bootparams[8]; diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 4d416aeb..ce0ff849 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -106,6 +106,8 @@ u32 micExtBufferWritePos; u32 micWavLength; s16* micWavBuffer; +void micCallback(void* data, Uint8* stream, int len); + void audioCallback(void* data, Uint8* stream, int len) { @@ -143,6 +145,40 @@ void audioCallback(void* data, Uint8* stream, int len) } +void micOpen() +{ + if (Config::MicInputType != 1) + { + micDevice = 0; + return; + } + + SDL_AudioSpec whatIwant, whatIget; + memset(&whatIwant, 0, sizeof(SDL_AudioSpec)); + whatIwant.freq = 44100; + whatIwant.format = AUDIO_S16LSB; + whatIwant.channels = 1; + whatIwant.samples = 1024; + whatIwant.callback = micCallback; + micDevice = SDL_OpenAudioDevice(NULL, 1, &whatIwant, &whatIget, 0); + if (!micDevice) + { + printf("Mic init failed: %s\n", SDL_GetError()); + } + else + { + SDL_PauseAudioDevice(micDevice, 0); + } +} + +void micClose() +{ + if (micDevice) + SDL_CloseAudioDevice(micDevice); + + micDevice = 0; +} + void micLoadWav(const char* name) { SDL_AudioSpec format; @@ -625,7 +661,7 @@ void EmuThread::emuRun() // checkme emit windowEmuStart(); if (audioDevice) SDL_PauseAudioDevice(audioDevice, 0); - if (micDevice) SDL_PauseAudioDevice(micDevice, 0); + micOpen(); } void EmuThread::emuPause() @@ -638,7 +674,7 @@ void EmuThread::emuPause() while (EmuStatus != 2); if (audioDevice) SDL_PauseAudioDevice(audioDevice, 1); - if (micDevice) SDL_PauseAudioDevice(micDevice, 1); + micClose(); } void EmuThread::emuUnpause() @@ -651,7 +687,7 @@ void EmuThread::emuUnpause() EmuRunning = PrevEmuStatus; if (audioDevice) SDL_PauseAudioDevice(audioDevice, 0); - if (micDevice) SDL_PauseAudioDevice(micDevice, 0); + micOpen(); } void EmuThread::emuStop() @@ -660,7 +696,7 @@ void EmuThread::emuStop() EmuPause = 0; if (audioDevice) SDL_PauseAudioDevice(audioDevice, 1); - if (micDevice) SDL_PauseAudioDevice(micDevice, 1); + micClose(); } void EmuThread::emuFrameStep() @@ -2401,6 +2437,8 @@ void MainWindow::onUpdateAudioSettings() void MainWindow::onAudioSettingsFinished(int res) { + micClose(); + SPU::SetInterpolation(Config::AudioInterp); if (Config::MicInputType == 3) @@ -2418,6 +2456,8 @@ void MainWindow::onAudioSettingsFinished(int res) else Frontend::Mic_SetExternalBuffer(NULL, 0); } + + micOpen(); } void MainWindow::onOpenWifiSettings() @@ -2762,21 +2802,7 @@ int main(int argc, char** argv) SDL_PauseAudioDevice(audioDevice, 1); } - memset(&whatIwant, 0, sizeof(SDL_AudioSpec)); - whatIwant.freq = 44100; - whatIwant.format = AUDIO_S16LSB; - whatIwant.channels = 1; - whatIwant.samples = 1024; - whatIwant.callback = micCallback; - micDevice = SDL_OpenAudioDevice(NULL, 1, &whatIwant, &whatIget, 0); - if (!micDevice) - { - printf("Mic init failed: %s\n", SDL_GetError()); - } - else - { - SDL_PauseAudioDevice(micDevice, 1); - } + micDevice = 0; memset(micExtBuffer, 0, sizeof(micExtBuffer)); @@ -2847,7 +2873,7 @@ int main(int argc, char** argv) Frontend::DeInit_ROM(); if (audioDevice) SDL_CloseAudioDevice(audioDevice); - if (micDevice) SDL_CloseAudioDevice(micDevice); + micClose(); SDL_DestroyCond(audioSync); SDL_DestroyMutex(audioSyncLock);