Merge branch 'master' into feature/zip-support

This commit is contained in:
WaluigiWare64 2020-08-05 15:06:15 +01:00 committed by GitHub
commit 6d71f9c832
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
54 changed files with 3342 additions and 2970 deletions

View File

@ -17,16 +17,22 @@ jobs:
steps: steps:
- uses: actions/checkout@v1 - uses: actions/checkout@v1
- name: Upgrade system
shell: bash
working-directory: ${{runner.workspace}}
run: |
sudo apt update
sudo apt full-upgrade
- name: Install dependencies - name: Install dependencies
shell: bash shell: bash
working-directory: ${{runner.workspace}} working-directory: ${{runner.workspace}}
run: | run: |
sudo dpkg --add-architecture arm64 \ sudo dpkg --add-architecture arm64
&& sudo sh -c "sed \"s|^deb \([a-z\.:/]*\) \([a-z\-]*\) \(.*\)$|deb [arch=amd64] \1 \2 \3\ndeb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports \2 \3|\" /etc/apt/sources.list > /etc/apt/sources.list.new" \ sudo sh -c "sed \"s|^deb \([a-z\.:/]*\) \([a-z\-]*\) \(.*\)$|deb [arch=amd64] \1 \2 \3\ndeb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports \2 \3|\" /etc/apt/sources.list > /etc/apt/sources.list.new"
&& sudo rm /etc/apt/sources.list \ sudo rm /etc/apt/sources.list
&& sudo mv /etc/apt/sources.list{.new,} \ sudo mv /etc/apt/sources.list{.new,}
&& sudo apt-get update \ sudo apt update
&& sudo apt-get install {gcc-10,g++-10,pkg-config}-aarch64-linux-gnu libsdl2-dev:arm64 libzip-dev:arm64 qtbase5-dev:arm64 sudo apt install {gcc-10,g++-10,pkg-config}-aarch64-linux-gnu libsdl2-dev:arm64 qtbase5-dev:arm64 libslirp-dev:arm64 libzip-dev:arm64
- name: Create build environment - name: Create build environment
run: mkdir ${{runner.workspace}}/build run: mkdir ${{runner.workspace}}/build
- name: Configure - name: Configure

View File

@ -23,17 +23,15 @@ jobs:
shell: bash shell: bash
working-directory: ${{runner.workspace}} working-directory: ${{runner.workspace}}
run: | # Fetch a new version of CMake, because the default is too old. run: | # Fetch a new version of CMake, because the default is too old.
wget -nv https://github.com/Kitware/CMake/releases/download/v$CMAKE_VERSION/cmake-$CMAKE_VERSION-Linux-x86_64.tar.gz \ sudo rm -f /etc/apt/sources.list.d/dotnetdev.list /etc/apt/sources.list.d/microsoft-prod.list \
&& tar -zxf cmake-$CMAKE_VERSION-Linux-x86_64.tar.gz \
&& sudo rm -f /etc/apt/sources.list.d/dotnetdev.list /etc/apt/sources.list.d/microsoft-prod.list \
&& sudo apt-get update \ && sudo apt-get update \
&& sudo apt-get install gtk+-3.0 libcurl4-gnutls-dev libpcap0.8-dev libsdl2-dev libzip-dev qt5-default && sudo apt-get install cmake libcurl4-gnutls-dev libpcap0.8-dev libsdl2-dev qt5-default libslirp-dev libzip-dev
- name: Create build environment - name: Create build environment
run: mkdir ${{runner.workspace}}/build run: mkdir ${{runner.workspace}}/build
- name: Configure - name: Configure
shell: bash shell: bash
working-directory: ${{runner.workspace}}/build working-directory: ${{runner.workspace}}/build
run: ${{runner.workspace}}/cmake-$CMAKE_VERSION-Linux-x86_64/bin/cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE
- name: Make - name: Make
shell: bash shell: bash
working-directory: ${{runner.workspace}}/build working-directory: ${{runner.workspace}}/build

View File

@ -21,11 +21,10 @@ jobs:
- name: Install MSYS2 - name: Install MSYS2
working-directory: ${{runner.workspace}} working-directory: ${{runner.workspace}}
run: | # Fetch MSYS2 build from XQEmu. Official distribution causes a CI failure due to permission errors. run: | # Fetch MSYS2 build from XQEmu. Official distribution causes a CI failure due to permission errors.
Invoke-WebRequest -Uri "https://github.com/xqemu/ci-environment-msys2/releases/latest/download/msys64.7z" -OutFile "msys64.7z" choco install msys2
7z x -y msys64.7z "-oC:\tools\"
C:\tools\msys64\usr\bin\bash.exe -lc "pacman -Syuq --noconfirm" C:\tools\msys64\usr\bin\bash.exe -lc "pacman -Syuq --noconfirm"
- name: Install dependencies - name: Install dependencies
run: C:\tools\msys64\usr\bin\bash.exe -lc "pacman -Sq --noconfirm git make mingw-w64-x86_64-{cmake,mesa,SDL2,qt5-static,libzip,toolchain}" run: C:\tools\msys64\usr\bin\bash.exe -lc "pacman -Sq --noconfirm git make mingw-w64-x86_64-{cmake,mesa,SDL2,qt5-static,libslirp,libzip,toolchain}"
- name: Create build environment - name: Create build environment
run: | run: |
New-Item -ItemType directory -Path ${{runner.workspace}}\melonDS\build New-Item -ItemType directory -Path ${{runner.workspace}}\melonDS\build

View File

@ -80,7 +80,7 @@ ARM::~ARM()
ARMv5::ARMv5() : ARM(0) ARMv5::ARMv5() : ARM(0)
{ {
#ifndef JIT_ENABLED #ifndef JIT_ENABLED
DTCM = new u8[DTCMSize]; DTCM = new u8[DTCMPhysicalSize];
#endif #endif
} }
@ -274,15 +274,15 @@ void ARMv5::JumpTo(u32 addr, bool restorecpsr)
if (addr & 0x2) if (addr & 0x2)
{ {
NextInstr[0] = CodeRead32(addr-2, true) >> 16; NextInstr[0] = CodeRead32(addr-2, true) >> 16;
Cycles -= CodeCycles; Cycles += CodeCycles;
NextInstr[1] = CodeRead32(addr+2, false); NextInstr[1] = CodeRead32(addr+2, false);
Cycles -= CodeCycles; Cycles += CodeCycles;
} }
else else
{ {
NextInstr[0] = CodeRead32(addr, true); NextInstr[0] = CodeRead32(addr, true);
NextInstr[1] = NextInstr[0] >> 16; NextInstr[1] = NextInstr[0] >> 16;
Cycles -= CodeCycles; Cycles += CodeCycles;
} }
CPSR |= 0x20; CPSR |= 0x20;
@ -295,9 +295,9 @@ void ARMv5::JumpTo(u32 addr, bool restorecpsr)
if (newregion != oldregion) SetupCodeMem(addr); if (newregion != oldregion) SetupCodeMem(addr);
NextInstr[0] = CodeRead32(addr, true); NextInstr[0] = CodeRead32(addr, true);
Cycles -= CodeCycles; Cycles += CodeCycles;
NextInstr[1] = CodeRead32(addr+4, false); NextInstr[1] = CodeRead32(addr+4, false);
Cycles -= CodeCycles; Cycles += CodeCycles;
CPSR &= ~0x20; CPSR &= ~0x20;
} }
@ -337,7 +337,7 @@ void ARMv4::JumpTo(u32 addr, bool restorecpsr)
NextInstr[0] = CodeRead16(addr); NextInstr[0] = CodeRead16(addr);
NextInstr[1] = CodeRead16(addr+2); NextInstr[1] = CodeRead16(addr+2);
Cycles -= NDS::ARM7MemTimings[CodeCycles][0] + NDS::ARM7MemTimings[CodeCycles][1]; Cycles += NDS::ARM7MemTimings[CodeCycles][0] + NDS::ARM7MemTimings[CodeCycles][1];
CPSR |= 0x20; CPSR |= 0x20;
} }
@ -350,7 +350,7 @@ void ARMv4::JumpTo(u32 addr, bool restorecpsr)
NextInstr[0] = CodeRead32(addr); NextInstr[0] = CodeRead32(addr);
NextInstr[1] = CodeRead32(addr+4); NextInstr[1] = CodeRead32(addr+4);
Cycles -= NDS::ARM7MemTimings[CodeCycles][2] + NDS::ARM7MemTimings[CodeCycles][3]; Cycles += NDS::ARM7MemTimings[CodeCycles][2] + NDS::ARM7MemTimings[CodeCycles][3];
CPSR &= ~0x20; CPSR &= ~0x20;
} }
@ -609,7 +609,7 @@ void ARMv5::Execute()
}*/ }*/
if (IRQ) TriggerIRQ(); if (IRQ) TriggerIRQ();
NDS::ARM9Timestamp -= Cycles; NDS::ARM9Timestamp += Cycles;
Cycles = 0; Cycles = 0;
} }
@ -643,9 +643,6 @@ void ARMv5::ExecuteJIT()
{ {
u32 instrAddr = R[15] - ((CPSR&0x20)?2:4); u32 instrAddr = R[15] - ((CPSR&0x20)?2:4);
// hack so Cycles <= 0 becomes Cycles < 0
Cycles = NDS::ARM9Target - NDS::ARM9Timestamp - 1;
if ((instrAddr < FastBlockLookupStart || instrAddr >= (FastBlockLookupStart + FastBlockLookupSize)) if ((instrAddr < FastBlockLookupStart || instrAddr >= (FastBlockLookupStart + FastBlockLookupSize))
&& !ARMJIT::SetupExecutableRegion(0, instrAddr, FastBlockLookup, FastBlockLookupStart, FastBlockLookupSize)) && !ARMJIT::SetupExecutableRegion(0, instrAddr, FastBlockLookup, FastBlockLookupStart, FastBlockLookupSize))
{ {
@ -661,24 +658,26 @@ void ARMv5::ExecuteJIT()
else else
ARMJIT::CompileBlock(this); ARMJIT::CompileBlock(this);
NDS::ARM9Timestamp = NDS::ARM9Target - Cycles - 1;
if (StopExecution) if (StopExecution)
{ {
// this order is crucial otherwise idle loops waiting for an IRQ won't function
if (IRQ) if (IRQ)
TriggerIRQ(); TriggerIRQ();
if (Halted || IdleLoop) if (Halted || IdleLoop)
{ {
bool idleLoop = IdleLoop; if ((Halted == 1 || IdleLoop) && NDS::ARM9Timestamp < NDS::ARM9Target)
IdleLoop = 0;
if ((Halted == 1 || idleLoop) && NDS::ARM9Timestamp < NDS::ARM9Target)
{ {
Cycles = 0;
NDS::ARM9Timestamp = NDS::ARM9Target; NDS::ARM9Timestamp = NDS::ARM9Target;
} }
IdleLoop = 0;
break; break;
} }
} }
NDS::ARM9Timestamp += Cycles;
Cycles = 0;
} }
if (Halted == 2) if (Halted == 2)
@ -755,7 +754,7 @@ void ARMv4::Execute()
}*/ }*/
if (IRQ) TriggerIRQ(); if (IRQ) TriggerIRQ();
NDS::ARM7Timestamp -= Cycles; NDS::ARM7Timestamp += Cycles;
Cycles = 0; Cycles = 0;
} }
@ -795,8 +794,6 @@ void ARMv4::ExecuteJIT()
{ {
u32 instrAddr = R[15] - ((CPSR&0x20)?2:4); u32 instrAddr = R[15] - ((CPSR&0x20)?2:4);
Cycles = NDS::ARM7Target - NDS::ARM7Timestamp - 1;
if ((instrAddr < FastBlockLookupStart || instrAddr >= (FastBlockLookupStart + FastBlockLookupSize)) if ((instrAddr < FastBlockLookupStart || instrAddr >= (FastBlockLookupStart + FastBlockLookupSize))
&& !ARMJIT::SetupExecutableRegion(1, instrAddr, FastBlockLookup, FastBlockLookupStart, FastBlockLookupSize)) && !ARMJIT::SetupExecutableRegion(1, instrAddr, FastBlockLookup, FastBlockLookupStart, FastBlockLookupSize))
{ {
@ -812,9 +809,6 @@ void ARMv4::ExecuteJIT()
else else
ARMJIT::CompileBlock(this); ARMJIT::CompileBlock(this);
NDS::ARM7Timestamp = NDS::ARM7Target - Cycles - 1;
// TODO optimize this shit!!!
if (StopExecution) if (StopExecution)
{ {
if (IRQ) if (IRQ)
@ -822,15 +816,18 @@ void ARMv4::ExecuteJIT()
if (Halted || IdleLoop) if (Halted || IdleLoop)
{ {
bool idleLoop = IdleLoop; if ((Halted == 1 || IdleLoop) && NDS::ARM7Timestamp < NDS::ARM7Target)
IdleLoop = 0;
if ((Halted == 1 || idleLoop) && NDS::ARM7Timestamp < NDS::ARM7Target)
{ {
Cycles = 0;
NDS::ARM7Timestamp = NDS::ARM7Target; NDS::ARM7Timestamp = NDS::ARM7Target;
} }
IdleLoop = 0;
break; break;
} }
} }
NDS::ARM7Timestamp += Cycles;
Cycles = 0;
} }
if (Halted == 2) if (Halted == 2)

View File

@ -57,7 +57,7 @@ public:
} }
virtual void Execute() = 0; virtual void Execute() = 0;
#ifdef ENABLE_JIT #ifdef JIT_ENABLED
virtual void ExecuteJIT() = 0; virtual void ExecuteJIT() = 0;
#endif #endif
@ -202,14 +202,14 @@ public:
{ {
// code only. always nonseq 32-bit for ARM9. // code only. always nonseq 32-bit for ARM9.
s32 numC = (R[15] & 0x2) ? 0 : CodeCycles; s32 numC = (R[15] & 0x2) ? 0 : CodeCycles;
Cycles -= numC; Cycles += numC;
} }
void AddCycles_CI(s32 numI) void AddCycles_CI(s32 numI)
{ {
// code+internal // code+internal
s32 numC = (R[15] & 0x2) ? 0 : CodeCycles; s32 numC = (R[15] & 0x2) ? 0 : CodeCycles;
Cycles -= numC + numI; Cycles += numC + numI;
} }
void AddCycles_CDI() void AddCycles_CDI()
@ -220,9 +220,9 @@ public:
s32 numD = DataCycles; s32 numD = DataCycles;
//if (DataRegion != CodeRegion) //if (DataRegion != CodeRegion)
Cycles -= std::max(numC + numD - 6, std::max(numC, numD)); Cycles += std::max(numC + numD - 6, std::max(numC, numD));
//else //else
// Cycles -= numC + numD; // Cycles += numC + numD;
} }
void AddCycles_CD() void AddCycles_CD()
@ -232,9 +232,9 @@ public:
s32 numD = DataCycles; s32 numD = DataCycles;
//if (DataRegion != CodeRegion) //if (DataRegion != CodeRegion)
Cycles -= std::max(numC + numD - 6, std::max(numC, numD)); Cycles += std::max(numC + numD - 6, std::max(numC, numD));
//else //else
// Cycles -= numC + numD; // Cycles += numC + numD;
} }
void GetCodeMemRegion(u32 addr, NDS::MemRegion* region); void GetCodeMemRegion(u32 addr, NDS::MemRegion* region);
@ -396,13 +396,13 @@ public:
void AddCycles_C() void AddCycles_C()
{ {
// code only. this code fetch is sequential. // code only. this code fetch is sequential.
Cycles -= NDS::ARM7MemTimings[CodeCycles][(CPSR&0x20)?1:3]; Cycles += NDS::ARM7MemTimings[CodeCycles][(CPSR&0x20)?1:3];
} }
void AddCycles_CI(s32 num) void AddCycles_CI(s32 num)
{ {
// code+internal. results in a nonseq code fetch. // code+internal. results in a nonseq code fetch.
Cycles -= NDS::ARM7MemTimings[CodeCycles][(CPSR&0x20)?0:2] + num; Cycles += NDS::ARM7MemTimings[CodeCycles][(CPSR&0x20)?0:2] + num;
} }
void AddCycles_CDI() void AddCycles_CDI()
@ -414,21 +414,21 @@ public:
if ((DataRegion >> 24) == 0x02) // mainRAM if ((DataRegion >> 24) == 0x02) // mainRAM
{ {
if (CodeRegion == 0x02) if (CodeRegion == 0x02)
Cycles -= numC + numD; Cycles += numC + numD;
else else
{ {
numC++; numC++;
Cycles -= std::max(numC + numD - 3, std::max(numC, numD)); Cycles += std::max(numC + numD - 3, std::max(numC, numD));
} }
} }
else if (CodeRegion == 0x02) else if (CodeRegion == 0x02)
{ {
numD++; numD++;
Cycles -= std::max(numC + numD - 3, std::max(numC, numD)); Cycles += std::max(numC + numD - 3, std::max(numC, numD));
} }
else else
{ {
Cycles -= numC + numD + 1; Cycles += numC + numD + 1;
} }
} }
@ -441,17 +441,17 @@ public:
if ((DataRegion >> 24) == 0x02) if ((DataRegion >> 24) == 0x02)
{ {
if (CodeRegion == 0x02) if (CodeRegion == 0x02)
Cycles -= numC + numD; Cycles += numC + numD;
else else
Cycles -= std::max(numC + numD - 3, std::max(numC, numD)); Cycles += std::max(numC + numD - 3, std::max(numC, numD));
} }
else if (CodeRegion == 0x02) else if (CodeRegion == 0x02)
{ {
Cycles -= std::max(numC + numD - 3, std::max(numC, numD)); Cycles += std::max(numC + numD - 3, std::max(numC, numD));
} }
else else
{ {
Cycles -= numC + numD; Cycles += numC + numD;
} }
} }
}; };

View File

@ -126,6 +126,11 @@ namespace ARMInterpreter
#define A_CALC_OP2_IMM \ #define A_CALC_OP2_IMM \
u32 b = ROR(cpu->CurInstr&0xFF, (cpu->CurInstr>>7)&0x1E); u32 b = ROR(cpu->CurInstr&0xFF, (cpu->CurInstr>>7)&0x1E);
#define A_CALC_OP2_IMM_S \
u32 b = ROR(cpu->CurInstr&0xFF, (cpu->CurInstr>>7)&0x1E); \
if ((cpu->CurInstr>>7)&0x1E) \
cpu->SetC(b & 0x80000000);
#define A_CALC_OP2_REG_SHIFT_IMM(shiftop) \ #define A_CALC_OP2_REG_SHIFT_IMM(shiftop) \
u32 b = cpu->R[cpu->CurInstr&0xF]; \ u32 b = cpu->R[cpu->CurInstr&0xF]; \
u32 s = (cpu->CurInstr>>7)&0x1F; \ u32 s = (cpu->CurInstr>>7)&0x1F; \
@ -186,7 +191,7 @@ void A_##x##_REG_ROR_REG(ARM* cpu) \
} \ } \
void A_##x##_IMM_S(ARM* cpu) \ void A_##x##_IMM_S(ARM* cpu) \
{ \ { \
A_CALC_OP2_IMM \ A_CALC_OP2_IMM##s \
A_##x##_S(0) \ A_##x##_S(0) \
} \ } \
void A_##x##_REG_LSL_IMM_S(ARM* cpu) \ void A_##x##_REG_LSL_IMM_S(ARM* cpu) \
@ -234,7 +239,7 @@ void A_##x##_REG_ROR_REG_S(ARM* cpu) \
\ \
void A_##x##_IMM(ARM* cpu) \ void A_##x##_IMM(ARM* cpu) \
{ \ { \
A_CALC_OP2_IMM \ A_CALC_OP2_IMM##s \
A_##x(0) \ A_##x(0) \
} \ } \
void A_##x##_REG_LSL_IMM(ARM* cpu) \ void A_##x##_REG_LSL_IMM(ARM* cpu) \
@ -1078,7 +1083,7 @@ void A_QDADD(ARM* cpu)
u32 rm = cpu->R[cpu->CurInstr & 0xF]; u32 rm = cpu->R[cpu->CurInstr & 0xF];
u32 rn = cpu->R[(cpu->CurInstr >> 16) & 0xF]; u32 rn = cpu->R[(cpu->CurInstr >> 16) & 0xF];
if (rn & 0x40000000) if (OVERFLOW_ADD(rn, rn, rn<<1))
{ {
rn = (rn & 0x80000000) ? 0x80000000 : 0x7FFFFFFF; rn = (rn & 0x80000000) ? 0x80000000 : 0x7FFFFFFF;
cpu->CPSR |= 0x08000000; // CHECKME cpu->CPSR |= 0x08000000; // CHECKME
@ -1104,7 +1109,7 @@ void A_QDSUB(ARM* cpu)
u32 rm = cpu->R[cpu->CurInstr & 0xF]; u32 rm = cpu->R[cpu->CurInstr & 0xF];
u32 rn = cpu->R[(cpu->CurInstr >> 16) & 0xF]; u32 rn = cpu->R[(cpu->CurInstr >> 16) & 0xF];
if (rn & 0x40000000) if (OVERFLOW_ADD(rn, rn, rn<<1))
{ {
rn = (rn & 0x80000000) ? 0x80000000 : 0x7FFFFFFF; rn = (rn & 0x80000000) ? 0x80000000 : 0x7FFFFFFF;
cpu->CPSR |= 0x08000000; // CHECKME cpu->CPSR |= 0x08000000; // CHECKME

File diff suppressed because it is too large Load Diff

View File

@ -434,6 +434,19 @@ void Compiler::A_Comp_GetOp2(bool S, Op2& op2)
if (CurInstr.Instr & (1 << 25)) if (CurInstr.Instr & (1 << 25))
{ {
Comp_AddCycles_C(); Comp_AddCycles_C();
u32 shift = (CurInstr.Instr >> 7) & 0x1E;
u32 imm = ROR(CurInstr.Instr & 0xFF, shift);
if (S && shift && (CurInstr.SetFlags & 0x2))
{
CPSRDirty = true;
if (imm & 0x80000000)
ORRI2R(RCPSR, RCPSR, 1 << 29);
else
ANDI2R(RCPSR, RCPSR, ~(1 << 29));
}
op2 = Op2(ROR(CurInstr.Instr & 0xFF, (CurInstr.Instr >> 7) & 0x1E)); op2 = Op2(ROR(CurInstr.Instr & 0xFF, (CurInstr.Instr >> 7) & 0x1E));
} }
else else

View File

@ -143,7 +143,7 @@ void Compiler::Comp_JumpTo(u32 addr, bool forceNonConstantCycles)
if ((Thumb || CurInstr.Cond() >= 0xE) && !forceNonConstantCycles) if ((Thumb || CurInstr.Cond() >= 0xE) && !forceNonConstantCycles)
ConstantCycles += cycles; ConstantCycles += cycles;
else else
SUB(RCycles, RCycles, cycles); ADD(RCycles, RCycles, cycles);
} }
@ -181,7 +181,7 @@ void* Compiler::Gen_JumpTo9(int kind)
STR(INDEX_UNSIGNED, W0, RCPU, offsetof(ARMv5, R[15])); STR(INDEX_UNSIGNED, W0, RCPU, offsetof(ARMv5, R[15]));
ADD(W1, W1, W1); ADD(W1, W1, W1);
SUB(RCycles, RCycles, W1); ADD(RCycles, RCycles, W1);
RET(); RET();
} }
@ -201,7 +201,7 @@ void* Compiler::Gen_JumpTo9(int kind)
ADD(W2, W1, W1); ADD(W2, W1, W1);
TSTI2R(W0, 0x2); TSTI2R(W0, 0x2);
CSEL(W1, W1, W2, CC_EQ); CSEL(W1, W1, W2, CC_EQ);
SUB(RCycles, RCycles, W1); ADD(RCycles, RCycles, W1);
RET(); RET();
} }
@ -229,7 +229,7 @@ void* Compiler::Gen_JumpTo7(int kind)
UBFX(W2, W3, 0, 8); UBFX(W2, W3, 0, 8);
UBFX(W3, W3, 8, 8); UBFX(W3, W3, 8, 8);
ADD(W2, W3, W2); ADD(W2, W3, W2);
SUB(RCycles, RCycles, W2); ADD(RCycles, RCycles, W2);
ANDI2R(W0, W0, ~3); ANDI2R(W0, W0, ~3);
@ -253,7 +253,7 @@ void* Compiler::Gen_JumpTo7(int kind)
UBFX(W2, W3, 16, 8); UBFX(W2, W3, 16, 8);
UBFX(W3, W3, 24, 8); UBFX(W3, W3, 24, 8);
ADD(W2, W3, W2); ADD(W2, W3, W2);
SUB(RCycles, RCycles, W2); ADD(RCycles, RCycles, W2);
ANDI2R(W0, W0, ~1); ANDI2R(W0, W0, ~1);

View File

@ -312,59 +312,93 @@ Compiler::Compiler()
RET(); RET();
} }
for (int num = 0; num < 2; num++) for (int consoleType = 0; consoleType < 2; consoleType++)
{ {
for (int size = 0; size < 3; size++) for (int num = 0; num < 2; num++)
{ {
for (int reg = 0; reg < 8; reg++) for (int size = 0; size < 3; size++)
{ {
ARM64Reg rdMapped = (ARM64Reg)(W19 + reg); for (int reg = 0; reg < 8; reg++)
PatchedStoreFuncs[num][size][reg] = GetRXPtr();
if (num == 0)
{ {
MOV(X1, RCPU); ARM64Reg rdMapped = (ARM64Reg)(W19 + reg);
MOV(W2, rdMapped); PatchedStoreFuncs[consoleType][num][size][reg] = GetRXPtr();
}
else
{
MOV(W1, rdMapped);
}
ABI_PushRegisters({30});
switch ((8 << size) | num)
{
case 32: QuickCallFunction(X3, SlowWrite9<u32>); break;
case 33: QuickCallFunction(X3, SlowWrite7<u32>); break;
case 16: QuickCallFunction(X3, SlowWrite9<u16>); break;
case 17: QuickCallFunction(X3, SlowWrite7<u16>); break;
case 8: QuickCallFunction(X3, SlowWrite9<u8>); break;
case 9: QuickCallFunction(X3, SlowWrite7<u8>); break;
}
ABI_PopRegisters({30});
RET();
for (int signextend = 0; signextend < 2; signextend++)
{
PatchedLoadFuncs[num][size][signextend][reg] = GetRXPtr();
if (num == 0) if (num == 0)
MOV(X1, RCPU);
ABI_PushRegisters({30});
switch ((8 << size) | num)
{ {
case 32: QuickCallFunction(X3, SlowRead9<u32>); break; MOV(X1, RCPU);
case 33: QuickCallFunction(X3, SlowRead7<u32>); break; MOV(W2, rdMapped);
case 16: QuickCallFunction(X3, SlowRead9<u16>); break;
case 17: QuickCallFunction(X3, SlowRead7<u16>); break;
case 8: QuickCallFunction(X3, SlowRead9<u8>); break;
case 9: QuickCallFunction(X3, SlowRead7<u8>); break;
} }
ABI_PopRegisters({30});
if (size == 32)
MOV(rdMapped, W0);
else if (signextend)
SBFX(rdMapped, W0, 0, 8 << size);
else else
UBFX(rdMapped, W0, 0, 8 << size); {
MOV(W1, rdMapped);
}
ABI_PushRegisters({30});
if (consoleType == 0)
{
switch ((8 << size) | num)
{
case 32: QuickCallFunction(X3, SlowWrite9<u32, 0>); break;
case 33: QuickCallFunction(X3, SlowWrite7<u32, 0>); break;
case 16: QuickCallFunction(X3, SlowWrite9<u16, 0>); break;
case 17: QuickCallFunction(X3, SlowWrite7<u16, 0>); break;
case 8: QuickCallFunction(X3, SlowWrite9<u8, 0>); break;
case 9: QuickCallFunction(X3, SlowWrite7<u8, 0>); break;
}
}
else
{
switch ((8 << size) | num)
{
case 32: QuickCallFunction(X3, SlowWrite9<u32, 1>); break;
case 33: QuickCallFunction(X3, SlowWrite7<u32, 1>); break;
case 16: QuickCallFunction(X3, SlowWrite9<u16, 1>); break;
case 17: QuickCallFunction(X3, SlowWrite7<u16, 1>); break;
case 8: QuickCallFunction(X3, SlowWrite9<u8, 1>); break;
case 9: QuickCallFunction(X3, SlowWrite7<u8, 1>); break;
}
}
ABI_PopRegisters({30});
RET(); RET();
for (int signextend = 0; signextend < 2; signextend++)
{
PatchedLoadFuncs[consoleType][num][size][signextend][reg] = GetRXPtr();
if (num == 0)
MOV(X1, RCPU);
ABI_PushRegisters({30});
if (consoleType == 0)
{
switch ((8 << size) | num)
{
case 32: QuickCallFunction(X3, SlowRead9<u32, 0>); break;
case 33: QuickCallFunction(X3, SlowRead7<u32, 0>); break;
case 16: QuickCallFunction(X3, SlowRead9<u16, 0>); break;
case 17: QuickCallFunction(X3, SlowRead7<u16, 0>); break;
case 8: QuickCallFunction(X3, SlowRead9<u8, 0>); break;
case 9: QuickCallFunction(X3, SlowRead7<u8, 0>); break;
}
}
else
{
switch ((8 << size) | num)
{
case 32: QuickCallFunction(X3, SlowRead9<u32, 1>); break;
case 33: QuickCallFunction(X3, SlowRead7<u32, 1>); break;
case 16: QuickCallFunction(X3, SlowRead9<u16, 1>); break;
case 17: QuickCallFunction(X3, SlowRead7<u16, 1>); break;
case 8: QuickCallFunction(X3, SlowRead9<u8, 1>); break;
case 9: QuickCallFunction(X3, SlowRead7<u8, 1>); break;
}
}
ABI_PopRegisters({30});
if (size == 32)
MOV(rdMapped, W0);
else if (signextend)
SBFX(rdMapped, W0, 0, 8 << size);
else
UBFX(rdMapped, W0, 0, 8 << size);
RET();
}
} }
} }
} }
@ -595,7 +629,7 @@ void Compiler::Comp_BranchSpecialBehaviour(bool taken)
{ {
RegCache.PrepareExit(); RegCache.PrepareExit();
SUB(RCycles, RCycles, ConstantCycles); ADD(RCycles, RCycles, ConstantCycles);
QuickTailCall(X0, ARM_Ret); QuickTailCall(X0, ARM_Ret);
} }
} }
@ -736,7 +770,7 @@ JitBlockEntry Compiler::CompileBlock(ARM* cpu, bool thumb, FetchedInstr instrs[]
RegCache.Flush(); RegCache.Flush();
SUB(RCycles, RCycles, ConstantCycles); ADD(RCycles, RCycles, ConstantCycles);
QuickTailCall(X0, ARM_Ret); QuickTailCall(X0, ARM_Ret);
FlushIcache(); FlushIcache();
@ -766,7 +800,7 @@ void Compiler::Comp_AddCycles_C(bool forceNonConstant)
if (forceNonConstant) if (forceNonConstant)
ConstantCycles += cycles; ConstantCycles += cycles;
else else
SUB(RCycles, RCycles, cycles); ADD(RCycles, RCycles, cycles);
} }
void Compiler::Comp_AddCycles_CI(u32 numI) void Compiler::Comp_AddCycles_CI(u32 numI)
@ -780,7 +814,7 @@ void Compiler::Comp_AddCycles_CI(u32 numI)
if (Thumb || CurInstr.Cond() == 0xE) if (Thumb || CurInstr.Cond() == 0xE)
ConstantCycles += cycles; ConstantCycles += cycles;
else else
SUB(RCycles, RCycles, cycles); ADD(RCycles, RCycles, cycles);
} }
void Compiler::Comp_AddCycles_CI(u32 c, ARM64Reg numI, ArithOption shift) void Compiler::Comp_AddCycles_CI(u32 c, ARM64Reg numI, ArithOption shift)
@ -791,11 +825,11 @@ void Compiler::Comp_AddCycles_CI(u32 c, ARM64Reg numI, ArithOption shift)
NDS::ARM7MemTimings[CurInstr.CodeCycles][Thumb ? 0 : 2] NDS::ARM7MemTimings[CurInstr.CodeCycles][Thumb ? 0 : 2]
: ((R15 & 0x2) ? 0 : CurInstr.CodeCycles)) + c; : ((R15 & 0x2) ? 0 : CurInstr.CodeCycles)) + c;
SUB(RCycles, RCycles, cycles); ADD(RCycles, RCycles, cycles);
if (Thumb || CurInstr.Cond() >= 0xE) if (Thumb || CurInstr.Cond() >= 0xE)
ConstantCycles += cycles; ConstantCycles += cycles;
else else
SUB(RCycles, RCycles, cycles); ADD(RCycles, RCycles, cycles);
} }
void Compiler::Comp_AddCycles_CDI() void Compiler::Comp_AddCycles_CDI()
@ -832,7 +866,7 @@ void Compiler::Comp_AddCycles_CDI()
} }
if (!Thumb && CurInstr.Cond() < 0xE) if (!Thumb && CurInstr.Cond() < 0xE)
SUB(RCycles, RCycles, cycles); ADD(RCycles, RCycles, cycles);
else else
ConstantCycles += cycles; ConstantCycles += cycles;
} }
@ -876,7 +910,7 @@ void Compiler::Comp_AddCycles_CD()
} }
if ((!Thumb && CurInstr.Cond() < 0xE) && IrregularCycles) if ((!Thumb && CurInstr.Cond() < 0xE) && IrregularCycles)
SUB(RCycles, RCycles, cycles); ADD(RCycles, RCycles, cycles);
else else
ConstantCycles += cycles; ConstantCycles += cycles;
} }

View File

@ -247,9 +247,9 @@ public:
std::unordered_map<ptrdiff_t, LoadStorePatch> LoadStorePatches; std::unordered_map<ptrdiff_t, LoadStorePatch> LoadStorePatches;
// [Num][Size][Sign Extend][Output register] // [Console Type][Num][Size][Sign Extend][Output register]
void* PatchedLoadFuncs[2][3][2][8]; void* PatchedLoadFuncs[2][2][3][2][8];
void* PatchedStoreFuncs[2][3][8]; void* PatchedStoreFuncs[2][2][3][8];
RegisterCache<Compiler, Arm64Gen::ARM64Reg> RegCache; RegisterCache<Compiler, Arm64Gen::ARM64Reg> RegCache;

View File

@ -2,9 +2,9 @@
.text .text
#define RCPSR W27 #define RCPSR w27
#define RCycles W28 #define RCycles w28
#define RCPU X29 #define RCPU x29
.p2align 4,,15 .p2align 4,,15

View File

@ -174,8 +174,8 @@ void Compiler::Comp_MemAccess(int rd, int rn, Op2 offset, int size, int flags)
LoadStorePatch patch; LoadStorePatch patch;
patch.PatchFunc = flags & memop_Store patch.PatchFunc = flags & memop_Store
? PatchedStoreFuncs[Num][__builtin_ctz(size) - 3][rdMapped - W19] ? PatchedStoreFuncs[NDS::ConsoleType][Num][__builtin_ctz(size) - 3][rdMapped - W19]
: PatchedLoadFuncs[Num][__builtin_ctz(size) - 3][!!(flags & memop_SignExtend)][rdMapped - W19]; : PatchedLoadFuncs[NDS::ConsoleType][Num][__builtin_ctz(size) - 3][!!(flags & memop_SignExtend)][rdMapped - W19];
assert(rdMapped - W19 >= 0 && rdMapped - W19 < 8); assert(rdMapped - W19 >= 0 && rdMapped - W19 < 8);
MOVP2R(X7, Num == 0 ? ARMJIT_Memory::FastMem9Start : ARMJIT_Memory::FastMem7Start); MOVP2R(X7, Num == 0 ? ARMJIT_Memory::FastMem9Start : ARMJIT_Memory::FastMem7Start);
@ -241,20 +241,26 @@ void Compiler::Comp_MemAccess(int rd, int rn, Op2 offset, int size, int flags)
if (flags & memop_Store) if (flags & memop_Store)
{ {
MOV(W2, rdMapped); MOV(W2, rdMapped);
switch (size) switch (size | NDS::ConsoleType)
{ {
case 32: QuickCallFunction(X3, SlowWrite9<u32>); break; case 32: QuickCallFunction(X3, SlowWrite9<u32, 0>); break;
case 16: QuickCallFunction(X3, SlowWrite9<u16>); break; case 33: QuickCallFunction(X3, SlowWrite9<u32, 1>); break;
case 8: QuickCallFunction(X3, SlowWrite9<u8>); break; case 16: QuickCallFunction(X3, SlowWrite9<u16, 0>); break;
case 17: QuickCallFunction(X3, SlowWrite9<u16, 1>); break;
case 8: QuickCallFunction(X3, SlowWrite9<u8, 0>); break;
case 9: QuickCallFunction(X3, SlowWrite9<u8, 1>); break;
} }
} }
else else
{ {
switch (size) switch (size | NDS::ConsoleType)
{ {
case 32: QuickCallFunction(X3, SlowRead9<u32>); break; case 32: QuickCallFunction(X3, SlowRead9<u32, 0>); break;
case 16: QuickCallFunction(X3, SlowRead9<u16>); break; case 33: QuickCallFunction(X3, SlowRead9<u32, 1>); break;
case 8: QuickCallFunction(X3, SlowRead9<u8>); break; case 16: QuickCallFunction(X3, SlowRead9<u16, 0>); break;
case 17: QuickCallFunction(X3, SlowRead9<u16, 1>); break;
case 8: QuickCallFunction(X3, SlowRead9<u8, 0>); break;
case 9: QuickCallFunction(X3, SlowRead9<u8, 1>); break;
} }
} }
} }
@ -263,20 +269,26 @@ void Compiler::Comp_MemAccess(int rd, int rn, Op2 offset, int size, int flags)
if (flags & memop_Store) if (flags & memop_Store)
{ {
MOV(W1, rdMapped); MOV(W1, rdMapped);
switch (size) switch (size | NDS::ConsoleType)
{ {
case 32: QuickCallFunction(X3, SlowWrite7<u32>); break; case 32: QuickCallFunction(X3, SlowWrite7<u32, 0>); break;
case 16: QuickCallFunction(X3, SlowWrite7<u16>); break; case 33: QuickCallFunction(X3, SlowWrite7<u32, 1>); break;
case 8: QuickCallFunction(X3, SlowWrite7<u8>); break; case 16: QuickCallFunction(X3, SlowWrite7<u16, 0>); break;
case 17: QuickCallFunction(X3, SlowWrite7<u16, 1>); break;
case 8: QuickCallFunction(X3, SlowWrite7<u8, 0>); break;
case 9: QuickCallFunction(X3, SlowWrite7<u8, 1>); break;
} }
} }
else else
{ {
switch (size) switch (size | NDS::ConsoleType)
{ {
case 32: QuickCallFunction(X3, SlowRead7<u32>); break; case 32: QuickCallFunction(X3, SlowRead7<u32, 0>); break;
case 16: QuickCallFunction(X3, SlowRead7<u16>); break; case 33: QuickCallFunction(X3, SlowRead7<u32, 1>); break;
case 8: QuickCallFunction(X3, SlowRead7<u8>); break; case 16: QuickCallFunction(X3, SlowRead7<u16, 0>); break;
case 17: QuickCallFunction(X3, SlowRead7<u16, 1>); break;
case 8: QuickCallFunction(X3, SlowRead7<u8, 0>); break;
case 9: QuickCallFunction(X3, SlowRead7<u8, 1>); break;
} }
} }
} }
@ -465,15 +477,25 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc
if (decrement) if (decrement)
{ {
SUB(W0, MapReg(rn), regsCount * 4); s32 offset = -regsCount * 4 + (preinc ? 0 : 4);
ANDI2R(W0, W0, ~3); if (offset)
preinc ^= true; {
ADDI2R(W0, MapReg(rn), offset);
ANDI2R(W0, W0, ~3);
}
else
{
ANDI2R(W0, MapReg(rn), ~3);
}
} }
else else
{ {
ANDI2R(W0, MapReg(rn), ~3); ANDI2R(W0, MapReg(rn), ~3);
if (preinc)
ADD(W0, W0, 4);
} }
u8* patchFunc;
if (compileFastPath) if (compileFastPath)
{ {
ptrdiff_t fastPathStart = GetCodeOffset(); ptrdiff_t fastPathStart = GetCodeOffset();
@ -482,7 +504,7 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc
MOVP2R(X1, Num == 0 ? ARMJIT_Memory::FastMem9Start : ARMJIT_Memory::FastMem7Start); MOVP2R(X1, Num == 0 ? ARMJIT_Memory::FastMem9Start : ARMJIT_Memory::FastMem7Start);
ADD(X1, X1, X0); ADD(X1, X1, X0);
u32 offset = preinc ? 4 : 0; u32 offset = 0;
BitSet16::Iterator it = regs.begin(); BitSet16::Iterator it = regs.begin();
u32 i = 0; u32 i = 0;
@ -545,7 +567,8 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc
LoadStorePatch patch; LoadStorePatch patch;
patch.PatchSize = GetCodeOffset() - fastPathStart; patch.PatchSize = GetCodeOffset() - fastPathStart;
SwapCodeRegion(); SwapCodeRegion();
patch.PatchFunc = GetRXPtr(); patchFunc = (u8*)GetRXPtr();
patch.PatchFunc = patchFunc;
for (i = 0; i < regsCount; i++) for (i = 0; i < regsCount; i++)
{ {
patch.PatchOffset = fastPathStart - loadStoreOffsets[i]; patch.PatchOffset = fastPathStart - loadStoreOffsets[i];
@ -620,22 +643,22 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc
if (Num == 0) if (Num == 0)
{ {
MOV(X3, RCPU); MOV(X3, RCPU);
switch (preinc * 2 | store) switch ((u32)store * 2 | NDS::ConsoleType)
{ {
case 0: QuickCallFunction(X4, SlowBlockTransfer9<false, false>); break; case 0: QuickCallFunction(X4, SlowBlockTransfer9<false, 0>); break;
case 1: QuickCallFunction(X4, SlowBlockTransfer9<false, true>); break; case 1: QuickCallFunction(X4, SlowBlockTransfer9<false, 1>); break;
case 2: QuickCallFunction(X4, SlowBlockTransfer9<true, false>); break; case 2: QuickCallFunction(X4, SlowBlockTransfer9<true, 0>); break;
case 3: QuickCallFunction(X4, SlowBlockTransfer9<true, true>); break; case 3: QuickCallFunction(X4, SlowBlockTransfer9<true, 1>); break;
} }
} }
else else
{ {
switch (preinc * 2 | store) switch ((u32)store * 2 | NDS::ConsoleType)
{ {
case 0: QuickCallFunction(X4, SlowBlockTransfer7<false, false>); break; case 0: QuickCallFunction(X4, SlowBlockTransfer7<false, 0>); break;
case 1: QuickCallFunction(X4, SlowBlockTransfer7<false, true>); break; case 1: QuickCallFunction(X4, SlowBlockTransfer7<false, 1>); break;
case 2: QuickCallFunction(X4, SlowBlockTransfer7<true, false>); break; case 2: QuickCallFunction(X4, SlowBlockTransfer7<true, 0>); break;
case 3: QuickCallFunction(X4, SlowBlockTransfer7<true, true>); break; case 3: QuickCallFunction(X4, SlowBlockTransfer7<true, 1>); break;
} }
} }
@ -705,7 +728,7 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc
ABI_PopRegisters({30}); ABI_PopRegisters({30});
RET(); RET();
FlushIcacheSection((u8*)patch.PatchFunc, (u8*)GetRXPtr()); FlushIcacheSection(patchFunc, (u8*)GetRXPtr());
SwapCodeRegion(); SwapCodeRegion();
} }

View File

@ -16,10 +16,10 @@ namespace ARMJIT
enum enum
{ {
branch_IdleBranch = 1 << 0, branch_IdleBranch = 1 << 0,
branch_FollowCondTaken = 1 << 1, branch_FollowCondTaken = 1 << 1,
branch_FollowCondNotTaken = 1 << 2, branch_FollowCondNotTaken = 1 << 2,
branch_StaticTarget = 1 << 3, branch_StaticTarget = 1 << 3,
}; };
struct FetchedInstr struct FetchedInstr
@ -39,155 +39,156 @@ struct FetchedInstr
return Instr >> 28; return Instr >> 28;
} }
u8 BranchFlags; u8 BranchFlags;
u8 SetFlags; u8 SetFlags;
u32 Instr; u32 Instr;
u32 Addr; u32 Addr;
u8 DataCycles; u8 DataCycles;
u16 CodeCycles; u16 CodeCycles;
u32 DataRegion; u32 DataRegion;
ARMInstrInfo::Info Info; ARMInstrInfo::Info Info;
}; };
/* /*
TinyVector TinyVector
- because reinventing the wheel is the best! - because reinventing the wheel is the best!
- meant to be used very often, with not so many elements - meant to be used very often, with not so many elements
max 1 << 16 elements max 1 << 16 elements
- doesn't allocate while no elements are inserted - doesn't allocate while no elements are inserted
- not stl confirmant of course - not stl confirmant of course
- probably only works with POD types - probably only works with POD types
- remove operations don't preserve order, but O(1)! - remove operations don't preserve order, but O(1)!
*/ */
template <typename T> template <typename T>
struct __attribute__((packed)) TinyVector struct __attribute__((packed)) TinyVector
{ {
T* Data = NULL; T* Data = NULL;
u16 Capacity = 0; u16 Capacity = 0;
u16 Length = 0; u16 Length = 0;
~TinyVector() ~TinyVector()
{ {
delete[] Data; delete[] Data;
} }
void MakeCapacity(u32 capacity) void MakeCapacity(u32 capacity)
{ {
assert(capacity <= UINT16_MAX); assert(capacity <= UINT16_MAX);
assert(capacity > Capacity); assert(capacity > Capacity);
T* newMem = new T[capacity]; T* newMem = new T[capacity];
if (Data != NULL) if (Data != NULL)
memcpy(newMem, Data, sizeof(T) * Length); memcpy(newMem, Data, sizeof(T) * Length);
T* oldData = Data; T* oldData = Data;
Data = newMem; Data = newMem;
if (oldData != NULL) if (oldData != NULL)
delete[] oldData; delete[] oldData;
Capacity = capacity; Capacity = capacity;
} }
void SetLength(u16 length) void SetLength(u16 length)
{ {
if (Capacity < length) if (Capacity < length)
MakeCapacity(length); MakeCapacity(length);
Length = length; Length = length;
} }
void Clear() void Clear()
{ {
Length = 0; Length = 0;
} }
void Add(T element) void Add(T element)
{ {
assert(Length + 1 <= UINT16_MAX); assert(Length + 1 <= UINT16_MAX);
if (Length + 1 > Capacity) if (Length + 1 > Capacity)
MakeCapacity(((Capacity + 4) * 3) / 2); MakeCapacity(((Capacity + 4) * 3) / 2);
Data[Length++] = element; Data[Length++] = element;
} }
void Remove(int index) void Remove(int index)
{ {
assert(index >= 0 && index < Length); assert(Length > 0);
assert(index >= 0 && index < Length);
Length--; Length--;
Data[index] = Data[Length]; Data[index] = Data[Length];
/*for (int i = index; i < Length; i++) /*for (int i = index; i < Length; i++)
Data[i] = Data[i + 1];*/ Data[i] = Data[i + 1];*/
} }
int Find(T needle) int Find(T needle)
{ {
for (int i = 0; i < Length; i++) for (int i = 0; i < Length; i++)
{ {
if (Data[i] == needle) if (Data[i] == needle)
return i; return i;
} }
return -1; return -1;
} }
bool RemoveByValue(T needle) bool RemoveByValue(T needle)
{ {
for (int i = 0; i < Length; i++) for (int i = 0; i < Length; i++)
{ {
if (Data[i] == needle) if (Data[i] == needle)
{ {
Remove(i); Remove(i);
return true; return true;
} }
} }
return false; return false;
} }
T& operator[](int index) T& operator[](int index)
{ {
assert(index >= 0 && index < Length); assert(index >= 0 && index < Length);
return Data[index]; return Data[index];
} }
}; };
class JitBlock class JitBlock
{ {
public: public:
JitBlock(u32 num, u32 literalHash, u32 numAddresses, u32 numLiterals) JitBlock(u32 num, u32 literalHash, u32 numAddresses, u32 numLiterals)
{ {
Num = num; Num = num;
NumAddresses = numAddresses; NumAddresses = numAddresses;
NumLiterals = numLiterals; NumLiterals = numLiterals;
Data.SetLength(numAddresses * 2 + numLiterals); Data.SetLength(numAddresses * 2 + numLiterals);
} }
u32 StartAddr; u32 StartAddr;
u32 StartAddrLocal; u32 StartAddrLocal;
u32 InstrHash, LiteralHash; u32 InstrHash, LiteralHash;
u8 Num; u8 Num;
u16 NumAddresses; u16 NumAddresses;
u16 NumLiterals; u16 NumLiterals;
JitBlockEntry EntryPoint; JitBlockEntry EntryPoint;
u32* AddressRanges() u32* AddressRanges()
{ return &Data[0]; } { return &Data[0]; }
u32* AddressMasks() u32* AddressMasks()
{ return &Data[NumAddresses]; } { return &Data[NumAddresses]; }
u32* Literals() u32* Literals()
{ return &Data[NumAddresses * 2]; } { return &Data[NumAddresses * 2]; }
private: private:
TinyVector<u32> Data; TinyVector<u32> Data;
}; };
// size should be 16 bytes because I'm to lazy to use mul and whatnot // size should be 16 bytes because I'm to lazy to use mul and whatnot
struct __attribute__((packed)) AddressRange struct __attribute__((packed)) AddressRange
{ {
TinyVector<JitBlock*> Blocks; TinyVector<JitBlock*> Blocks;
u32 Code; u32 Code;
}; };
@ -201,12 +202,12 @@ extern AddressRange* const CodeMemRegions[ARMJIT_Memory::memregions_Count];
inline bool PageContainsCode(AddressRange* range) inline bool PageContainsCode(AddressRange* range)
{ {
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
{ {
if (range[i].Blocks.Length > 0) if (range[i].Blocks.Length > 0)
return true; return true;
} }
return false; return false;
} }
u32 LocaliseCodeAddress(u32 num, u32 addr); u32 LocaliseCodeAddress(u32 num, u32 addr);

File diff suppressed because it is too large Load Diff

View File

@ -18,28 +18,28 @@ void Reset();
enum enum
{ {
memregion_Other = 0, memregion_Other = 0,
memregion_ITCM, memregion_ITCM,
memregion_DTCM, memregion_DTCM,
memregion_BIOS9, memregion_BIOS9,
memregion_MainRAM, memregion_MainRAM,
memregion_SharedWRAM, memregion_SharedWRAM,
memregion_IO9, memregion_IO9,
memregion_VRAM, memregion_VRAM,
memregion_BIOS7, memregion_BIOS7,
memregion_WRAM7, memregion_WRAM7,
memregion_IO7, memregion_IO7,
memregion_Wifi, memregion_Wifi,
memregion_VWRAM, memregion_VWRAM,
// DSi // DSi
memregion_BIOS9DSi, memregion_BIOS9DSi,
memregion_BIOS7DSi, memregion_BIOS7DSi,
memregion_NewSharedWRAM_A, memregion_NewSharedWRAM_A,
memregion_NewSharedWRAM_B, memregion_NewSharedWRAM_B,
memregion_NewSharedWRAM_C, memregion_NewSharedWRAM_C,
memregions_Count memregions_Count
}; };
int ClassifyAddress9(u32 addr); int ClassifyAddress9(u32 addr);

View File

@ -18,8 +18,8 @@ public:
RegisterCache() RegisterCache()
{} {}
RegisterCache(T* compiler, FetchedInstr instrs[], int instrsCount, bool pcAllocatableAsSrc = false) RegisterCache(T* compiler, FetchedInstr instrs[], int instrsCount, bool pcAllocatableAsSrc = false)
: Compiler(compiler), Instrs(instrs), InstrsCount(instrsCount) : Compiler(compiler), Instrs(instrs), InstrsCount(instrsCount)
{ {
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++)
Mapping[i] = (Reg)-1; Mapping[i] = (Reg)-1;
@ -95,7 +95,7 @@ public:
LiteralsLoaded = 0; LiteralsLoaded = 0;
} }
void Prepare(bool thumb, int i) void Prepare(bool thumb, int i)
{ {
FetchedInstr instr = Instrs[i]; FetchedInstr instr = Instrs[i];
@ -175,23 +175,23 @@ public:
DirtyRegs |= (LoadedRegs & instr.Info.DstRegs) & ~(1 << 15); DirtyRegs |= (LoadedRegs & instr.Info.DstRegs) & ~(1 << 15);
} }
static const Reg NativeRegAllocOrder[]; static const Reg NativeRegAllocOrder[];
static const int NativeRegsAvailable; static const int NativeRegsAvailable;
Reg Mapping[16]; Reg Mapping[16];
u32 LiteralValues[16]; u32 LiteralValues[16];
u16 LiteralsLoaded = 0; u16 LiteralsLoaded = 0;
u32 NativeRegsUsed = 0; u32 NativeRegsUsed = 0;
u16 LoadedRegs = 0; u16 LoadedRegs = 0;
u16 DirtyRegs = 0; u16 DirtyRegs = 0;
u16 PCAllocatableAsSrc = 0; u16 PCAllocatableAsSrc = 0;
T* Compiler; T* Compiler;
FetchedInstr* Instrs; FetchedInstr* Instrs;
int InstrsCount; int InstrsCount;
}; };
} }

View File

@ -103,16 +103,30 @@ void Compiler::Comp_CmpOp(int op, Gen::OpArg rn, Gen::OpArg op2, bool carryUsed)
// also calculates cycles // also calculates cycles
OpArg Compiler::A_Comp_GetALUOp2(bool S, bool& carryUsed) OpArg Compiler::A_Comp_GetALUOp2(bool S, bool& carryUsed)
{ {
S = S && (CurInstr.SetFlags & 0x2);
if (CurInstr.Instr & (1 << 25)) if (CurInstr.Instr & (1 << 25))
{ {
Comp_AddCycles_C(); Comp_AddCycles_C();
u32 shift = (CurInstr.Instr >> 7) & 0x1E;
u32 imm = ROR(CurInstr.Instr & 0xFF, shift);
carryUsed = false; carryUsed = false;
return Imm32(ROR(CurInstr.Instr & 0xFF, (CurInstr.Instr >> 7) & 0x1E)); if (S && shift)
{
CPSRDirty = true;
carryUsed = true;
if (imm & 0x80000000)
MOV(32, R(RSCRATCH2), Imm32(1));
else
XOR(32, R(RSCRATCH2), R(RSCRATCH2));
}
return Imm32(imm);
} }
else else
{ {
S = S && (CurInstr.SetFlags & 0x2);
int op = (CurInstr.Instr >> 5) & 0x3; int op = (CurInstr.Instr >> 5) & 0x3;
if (CurInstr.Instr & (1 << 4)) if (CurInstr.Instr & (1 << 4))
{ {

View File

@ -127,7 +127,7 @@ void Compiler::Comp_JumpTo(u32 addr, bool forceNonConstantCycles)
if ((Thumb || CurInstr.Cond() >= 0xE) && !forceNonConstantCycles) if ((Thumb || CurInstr.Cond() >= 0xE) && !forceNonConstantCycles)
ConstantCycles += cycles; ConstantCycles += cycles;
else else
SUB(32, MDisp(RCPU, offsetof(ARM, Cycles)), Imm8(cycles)); ADD(32, MDisp(RCPU, offsetof(ARM, Cycles)), Imm8(cycles));
} }
void Compiler::Comp_JumpTo(Gen::X64Reg addr, bool restoreCPSR) void Compiler::Comp_JumpTo(Gen::X64Reg addr, bool restoreCPSR)

View File

@ -315,7 +315,7 @@ Compiler::Compiler()
{ {
for (int reg = 0; reg < 16; reg++) for (int reg = 0; reg < 16; reg++)
{ {
if (reg == RSCRATCH || reg == ABI_PARAM1 || reg == ABI_PARAM2 || reg == ABI_PARAM3) if (reg == RSCRATCH || reg == ABI_PARAM1 || reg == ABI_PARAM2)
{ {
PatchedStoreFuncs[consoleType][num][size][reg] = NULL; PatchedStoreFuncs[consoleType][num][size][reg] = NULL;
PatchedLoadFuncs[consoleType][num][size][0][reg] = NULL; PatchedLoadFuncs[consoleType][num][size][0][reg] = NULL;
@ -330,7 +330,8 @@ Compiler::Compiler()
if (num == 0) if (num == 0)
{ {
MOV(64, R(ABI_PARAM2), R(RCPU)); MOV(64, R(ABI_PARAM2), R(RCPU));
MOV(32, R(ABI_PARAM3), R(rdMapped)); if (rdMapped != ABI_PARAM3)
MOV(32, R(ABI_PARAM3), R(rdMapped));
} }
else else
{ {
@ -626,7 +627,7 @@ void Compiler::Comp_SpecialBranchBehaviour(bool taken)
{ {
RegCache.PrepareExit(); RegCache.PrepareExit();
SUB(32, MDisp(RCPU, offsetof(ARM, Cycles)), Imm32(ConstantCycles)); ADD(32, MDisp(RCPU, offsetof(ARM, Cycles)), Imm32(ConstantCycles));
JMP((u8*)&ARM_Ret, true); JMP((u8*)&ARM_Ret, true);
} }
} }
@ -759,7 +760,7 @@ JitBlockEntry Compiler::CompileBlock(ARM* cpu, bool thumb, FetchedInstr instrs[]
RegCache.Flush(); RegCache.Flush();
SUB(32, MDisp(RCPU, offsetof(ARM, Cycles)), Imm32(ConstantCycles)); ADD(32, MDisp(RCPU, offsetof(ARM, Cycles)), Imm32(ConstantCycles));
JMP((u8*)ARM_Ret, true); JMP((u8*)ARM_Ret, true);
/*FILE* codeout = fopen("codeout", "a"); /*FILE* codeout = fopen("codeout", "a");
@ -778,7 +779,7 @@ void Compiler::Comp_AddCycles_C(bool forceNonConstant)
: ((R15 & 0x2) ? 0 : CurInstr.CodeCycles); : ((R15 & 0x2) ? 0 : CurInstr.CodeCycles);
if ((!Thumb && CurInstr.Cond() < 0xE) || forceNonConstant) if ((!Thumb && CurInstr.Cond() < 0xE) || forceNonConstant)
SUB(32, MDisp(RCPU, offsetof(ARM, Cycles)), Imm8(cycles)); ADD(32, MDisp(RCPU, offsetof(ARM, Cycles)), Imm8(cycles));
else else
ConstantCycles += cycles; ConstantCycles += cycles;
} }
@ -790,7 +791,7 @@ void Compiler::Comp_AddCycles_CI(u32 i)
: ((R15 & 0x2) ? 0 : CurInstr.CodeCycles)) + i; : ((R15 & 0x2) ? 0 : CurInstr.CodeCycles)) + i;
if (!Thumb && CurInstr.Cond() < 0xE) if (!Thumb && CurInstr.Cond() < 0xE)
SUB(32, MDisp(RCPU, offsetof(ARM, Cycles)), Imm8(cycles)); ADD(32, MDisp(RCPU, offsetof(ARM, Cycles)), Imm8(cycles));
else else
ConstantCycles += cycles; ConstantCycles += cycles;
} }
@ -804,12 +805,12 @@ void Compiler::Comp_AddCycles_CI(Gen::X64Reg i, int add)
if (!Thumb && CurInstr.Cond() < 0xE) if (!Thumb && CurInstr.Cond() < 0xE)
{ {
LEA(32, RSCRATCH, MDisp(i, add + cycles)); LEA(32, RSCRATCH, MDisp(i, add + cycles));
SUB(32, MDisp(RCPU, offsetof(ARM, Cycles)), R(RSCRATCH)); ADD(32, MDisp(RCPU, offsetof(ARM, Cycles)), R(RSCRATCH));
} }
else else
{ {
ConstantCycles += cycles; ConstantCycles += cycles;
SUB(32, MDisp(RCPU, offsetof(ARM, Cycles)), R(i)); ADD(32, MDisp(RCPU, offsetof(ARM, Cycles)), R(i));
} }
} }
@ -847,7 +848,7 @@ void Compiler::Comp_AddCycles_CDI()
} }
if (!Thumb && CurInstr.Cond() < 0xE) if (!Thumb && CurInstr.Cond() < 0xE)
SUB(32, MDisp(RCPU, offsetof(ARM, Cycles)), Imm8(cycles)); ADD(32, MDisp(RCPU, offsetof(ARM, Cycles)), Imm8(cycles));
else else
ConstantCycles += cycles; ConstantCycles += cycles;
} }
@ -891,7 +892,7 @@ void Compiler::Comp_AddCycles_CD()
} }
if (IrregularCycles && !Thumb && CurInstr.Cond() < 0xE) if (IrregularCycles && !Thumb && CurInstr.Cond() < 0xE)
SUB(32, MDisp(RCPU, offsetof(ARM, Cycles)), Imm8(cycles)); ADD(32, MDisp(RCPU, offsetof(ARM, Cycles)), Imm8(cycles));
else else
ConstantCycles += cycles; ConstantCycles += cycles;
} }

View File

@ -7,7 +7,7 @@
namespace ARMInstrInfo namespace ARMInstrInfo
{ {
#define ak(x) ((x) << 22) #define ak(x) ((x) << 23)
enum { enum {
A_Read0 = 1 << 0, A_Read0 = 1 << 0,
@ -37,9 +37,10 @@ enum {
A_RRXReadC = 1 << 17, A_RRXReadC = 1 << 17,
A_StaticShiftSetC = 1 << 18, A_StaticShiftSetC = 1 << 18,
A_SetC = 1 << 19, A_SetC = 1 << 19,
A_SetCImm = 1 << 20,
A_WriteMem = 1 << 20, A_WriteMem = 1 << 21,
A_LoadMem = 1 << 21 A_LoadMem = 1 << 22
}; };
#define A_BIOP A_Read16 #define A_BIOP A_Read16
@ -52,7 +53,7 @@ enum {
#define A_ARITH_SHIFT_REG A_SetCV #define A_ARITH_SHIFT_REG A_SetCV
#define A_LOGIC_SHIFT_REG A_SetMaybeC #define A_LOGIC_SHIFT_REG A_SetMaybeC
#define A_ARITH_IMM A_SetCV #define A_ARITH_IMM A_SetCV
#define A_LOGIC_IMM 0 #define A_LOGIC_IMM A_SetCImm
#define A_IMPLEMENT_ALU_OP(x,k,a,c) \ #define A_IMPLEMENT_ALU_OP(x,k,a,c) \
const u32 A_##x##_IMM = A_Write12 | c | A_##k | ak(ak_##x##_IMM); \ const u32 A_##x##_IMM = A_Write12 | c | A_##k | ak(ak_##x##_IMM); \
@ -410,7 +411,7 @@ Info Decode(bool thumb, u32 num, u32 instr)
if (data & A_UnkOnARM7 && num == 1) if (data & A_UnkOnARM7 && num == 1)
data = A_UNK; data = A_UNK;
res.Kind = (data >> 22) & 0x1FF; res.Kind = (data >> 23) & 0x1FF;
if (res.Kind >= ak_SMLAxy && res.Kind <= ak_SMULxy && num == 1) if (res.Kind >= ak_SMLAxy && res.Kind <= ak_SMULxy && num == 1)
{ {
@ -496,7 +497,9 @@ Info Decode(bool thumb, u32 num, u32 instr)
res.ReadFlags |= flag_C; res.ReadFlags |= flag_C;
if ((data & A_RRXReadC) && !((instr >> 7) & 0x1F)) if ((data & A_RRXReadC) && !((instr >> 7) & 0x1F))
res.ReadFlags |= flag_C; res.ReadFlags |= flag_C;
if ((data & A_SetC) || ((data & A_StaticShiftSetC) && ((instr >> 7) & 0x1F))) if ((data & A_SetC)
|| ((data & A_StaticShiftSetC) && ((instr >> 7) & 0x1F))
|| ((data & A_SetCImm) && ((instr >> 7) & 0x1E)))
res.WriteFlags |= flag_C; res.WriteFlags |= flag_C;
if (data & A_WriteMem) if (data & A_WriteMem)

View File

@ -90,6 +90,7 @@ if (ENABLE_JIT)
ARMJIT_A64/ARMJIT_Linkage.s ARMJIT_A64/ARMJIT_Linkage.s
) )
set_source_files_properties(ARMJIT_A64/ARMJIT_Linkage.s PROPERTIES COMPILE_FLAGS "-x assembler-with-cpp")
endif() endif()
endif() endif()

View File

@ -21,9 +21,11 @@
#include "NDS.h" #include "NDS.h"
#include "DSi.h" #include "DSi.h"
#include "ARM.h" #include "ARM.h"
#ifdef JIT_ENABLED
#include "ARMJIT.h" #include "ARMJIT.h"
#include "ARMJIT_Memory.h" #include "ARMJIT_Memory.h"
#endif
// access timing for cached regions // access timing for cached regions
// this would be an average between cache hits and cache misses // this would be an average between cache hits and cache misses
@ -105,7 +107,7 @@ void ARMv5::UpdateDTCMSetting()
{ {
newDTCMBase = DTCMSetting & 0xFFFFF000; newDTCMBase = DTCMSetting & 0xFFFFF000;
newDTCMSize = 0x200 << ((DTCMSetting >> 1) & 0x1F); newDTCMSize = 0x200 << ((DTCMSetting >> 1) & 0x1F);
//printf("DTCM [%08X] enabled at %08X, size %X\n", DTCMSetting, DTCMBase, DTCMSize); //printf("DTCM [%08X] enabled at %08X, size %X\n", DTCMSetting, newDTCMBase, newDTCMSize);
} }
else else
{ {
@ -115,7 +117,9 @@ void ARMv5::UpdateDTCMSetting()
} }
if (newDTCMBase != DTCMBase || newDTCMSize != DTCMSize) if (newDTCMBase != DTCMBase || newDTCMSize != DTCMSize)
{ {
#ifdef JIT_ENABLED
ARMJIT_Memory::RemapDTCM(newDTCMBase, newDTCMSize); ARMJIT_Memory::RemapDTCM(newDTCMBase, newDTCMSize);
#endif
DTCMBase = newDTCMBase; DTCMBase = newDTCMBase;
DTCMSize = newDTCMSize; DTCMSize = newDTCMSize;
} }
@ -631,7 +635,10 @@ void ARMv5::CP15Write(u32 id, u32 val)
} }
if ((id&0xF00)!=0x700) if ((id & 0xF00) == 0xF00) // test/debug shit?
return;
if ((id & 0xF00) != 0x700)
printf("unknown CP15 write op %03X %08X\n", id, val); printf("unknown CP15 write op %03X %08X\n", id, val);
} }
@ -725,6 +732,9 @@ u32 ARMv5::CP15Read(u32 id)
return ITCMSetting; return ITCMSetting;
} }
if ((id & 0xF00) == 0xF00) // test/debug shit?
return 0;
printf("unknown CP15 read op %03X\n", id); printf("unknown CP15 read op %03X\n", id);
return 0; return 0;
} }

View File

@ -1,5 +1,5 @@
/* /*
Copyright 2016-2019 Arisotura Copyright 2016-2020 Arisotura
This file is part of melonDS. This file is part of melonDS.
@ -181,15 +181,17 @@ void SoftReset()
// also, BPTWL[0x70] could be abused to quickly boot specific titles // also, BPTWL[0x70] could be abused to quickly boot specific titles
#ifdef JIT_ENABLED
ARMJIT_Memory::Reset();
ARMJIT::CheckAndInvalidateITCM();
#endif
NDS::ARM9->Reset(); NDS::ARM9->Reset();
NDS::ARM7->Reset(); NDS::ARM7->Reset();
NDS::ARM9->CP15Reset(); 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();
@ -540,7 +542,9 @@ void MapNWRAM_A(u32 num, u8 val)
return; return;
} }
#ifdef JIT_ENABLED
ARMJIT_Memory::RemapNWRAM(0); ARMJIT_Memory::RemapNWRAM(0);
#endif
int mbkn = 0, mbks = 8*num; int mbkn = 0, mbks = 8*num;
@ -573,7 +577,9 @@ void MapNWRAM_B(u32 num, u8 val)
return; return;
} }
#ifdef JIT_ENABLED
ARMJIT_Memory::RemapNWRAM(1); ARMJIT_Memory::RemapNWRAM(1);
#endif
int mbkn = 1+(num>>2), mbks = 8*(num&3); int mbkn = 1+(num>>2), mbks = 8*(num&3);
@ -610,7 +616,9 @@ void MapNWRAM_C(u32 num, u8 val)
return; return;
} }
#ifdef JIT_ENABLED
ARMJIT_Memory::RemapNWRAM(2); ARMJIT_Memory::RemapNWRAM(2);
#endif
int mbkn = 3+(num>>2), mbks = 8*(num&3); int mbkn = 3+(num>>2), mbks = 8*(num&3);
@ -644,7 +652,9 @@ 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;
#ifdef JIT_ENABLED
ARMJIT_Memory::RemapNWRAM(num); ARMJIT_Memory::RemapNWRAM(num);
#endif
MBK[cpu][5+num] = val; MBK[cpu][5+num] = val;
@ -850,7 +860,9 @@ void ARM9Write8(u32 addr, u8 val)
if (ptr) if (ptr)
{ {
*(u8*)&ptr[addr & 0xFFFF] = val; *(u8*)&ptr[addr & 0xFFFF] = 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;
} }
@ -860,7 +872,9 @@ void ARM9Write8(u32 addr, u8 val)
if (ptr) if (ptr)
{ {
*(u8*)&ptr[addr & 0x7FFF] = val; *(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;
} }
@ -870,7 +884,9 @@ void ARM9Write8(u32 addr, u8 val)
if (ptr) if (ptr)
{ {
*(u8*)&ptr[addr & 0x7FFF] = val; *(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;
} }
@ -895,7 +911,9 @@ void ARM9Write16(u32 addr, u16 val)
if (ptr) if (ptr)
{ {
*(u16*)&ptr[addr & 0xFFFF] = val; *(u16*)&ptr[addr & 0xFFFF] = 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;
} }
@ -905,7 +923,9 @@ void ARM9Write16(u32 addr, u16 val)
if (ptr) if (ptr)
{ {
*(u16*)&ptr[addr & 0x7FFF] = val; *(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;
} }
@ -915,7 +935,9 @@ void ARM9Write16(u32 addr, u16 val)
if (ptr) if (ptr)
{ {
*(u16*)&ptr[addr & 0x7FFF] = val; *(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;
} }
@ -940,7 +962,9 @@ void ARM9Write32(u32 addr, u32 val)
if (ptr) if (ptr)
{ {
*(u32*)&ptr[addr & 0xFFFF] = val; *(u32*)&ptr[addr & 0xFFFF] = 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;
} }
@ -950,7 +974,9 @@ void ARM9Write32(u32 addr, u32 val)
if (ptr) if (ptr)
{ {
*(u32*)&ptr[addr & 0x7FFF] = val; *(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;
} }
@ -960,7 +986,9 @@ void ARM9Write32(u32 addr, u32 val)
if (ptr) if (ptr)
{ {
*(u32*)&ptr[addr & 0x7FFF] = val; *(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;
} }
@ -1196,7 +1224,9 @@ void ARM7Write16(u32 addr, u16 val)
if (ptr) if (ptr)
{ {
*(u16*)&ptr[addr & 0xFFFF] = val; *(u16*)&ptr[addr & 0xFFFF] = 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;
} }
@ -1206,7 +1236,9 @@ void ARM7Write16(u32 addr, u16 val)
if (ptr) if (ptr)
{ {
*(u16*)&ptr[addr & 0x7FFF] = val; *(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;
} }
@ -1216,7 +1248,9 @@ void ARM7Write16(u32 addr, u16 val)
if (ptr) if (ptr)
{ {
*(u16*)&ptr[addr & 0x7FFF] = val; *(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;
} }
@ -1241,7 +1275,9 @@ void ARM7Write32(u32 addr, u32 val)
if (ptr) if (ptr)
{ {
*(u32*)&ptr[addr & 0xFFFF] = val; *(u32*)&ptr[addr & 0xFFFF] = 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;
} }
@ -1251,7 +1287,9 @@ void ARM7Write32(u32 addr, u32 val)
if (ptr) if (ptr)
{ {
*(u32*)&ptr[addr & 0x7FFF] = val; *(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;
} }
@ -1261,7 +1299,9 @@ void ARM7Write32(u32 addr, u32 val)
if (ptr) if (ptr)
{ {
*(u32*)&ptr[addr & 0x7FFF] = val; *(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;
} }

View File

@ -1,5 +1,5 @@
/* /*
Copyright 2016-2019 Arisotura Copyright 2016-2020 Arisotura
This file is part of melonDS. This file is part of melonDS.

View File

@ -1,5 +1,5 @@
/* /*
Copyright 2016-2019 Arisotura Copyright 2016-2020 Arisotura
This file is part of melonDS. This file is part of melonDS.
@ -165,9 +165,37 @@ void ProcessBlock_CCM_Decrypt()
//printf("AES-CCM: "); _printhex2(data, 16); //printf("AES-CCM: "); _printhex2(data, 16);
Swap16(data_rev, data); Swap16(data_rev, data);
AES_CTR_xcrypt_buffer(&Ctx, data_rev, 16); AES_CTR_xcrypt_buffer(&Ctx, data_rev, 16);
for (int i = 0; i < 16; i++) CurMAC[i] ^= data_rev[i];
AES_ECB_encrypt(&Ctx, CurMAC);
Swap16(data, data_rev);
//printf(" -> "); _printhex2(data, 16);
OutputFIFO->Write(*(u32*)&data[0]);
OutputFIFO->Write(*(u32*)&data[4]);
OutputFIFO->Write(*(u32*)&data[8]);
OutputFIFO->Write(*(u32*)&data[12]);
}
void ProcessBlock_CCM_Encrypt()
{
u8 data[16];
u8 data_rev[16];
*(u32*)&data[0] = InputFIFO->Read();
*(u32*)&data[4] = InputFIFO->Read();
*(u32*)&data[8] = InputFIFO->Read();
*(u32*)&data[12] = InputFIFO->Read();
//printf("AES-CCM: "); _printhex2(data, 16);
Swap16(data_rev, data);
for (int i = 0; i < 16; i++) CurMAC[i] ^= data_rev[i]; for (int i = 0; i < 16; i++) CurMAC[i] ^= data_rev[i];
AES_CTR_xcrypt_buffer(&Ctx, data_rev, 16);
AES_ECB_encrypt(&Ctx, CurMAC); AES_ECB_encrypt(&Ctx, CurMAC);
Swap16(data, data_rev); Swap16(data, data_rev);
@ -232,7 +260,6 @@ void WriteCnt(u32 val)
OutputDMASize = dmasize_out[(val >> 14) & 0x3]; OutputDMASize = dmasize_out[(val >> 14) & 0x3];
AESMode = (val >> 28) & 0x3; AESMode = (val >> 28) & 0x3;
if (AESMode == 1) printf("AES-CCM TODO\n");
if (val & (1<<24)) if (val & (1<<24))
{ {
@ -245,6 +272,8 @@ void WriteCnt(u32 val)
// transfer start (checkme) // transfer start (checkme)
RemBlocks = BlkCnt >> 16; RemBlocks = BlkCnt >> 16;
if (AESMode == 0 && (!(val & (1<<20)))) printf("AES: CCM-DECRYPT MAC FROM WRFIFO, TODO\n");
if (RemBlocks > 0) if (RemBlocks > 0)
{ {
u8 key[16]; u8 key[16];
@ -365,14 +394,9 @@ void Update()
switch (AESMode) switch (AESMode)
{ {
case 0: ProcessBlock_CCM_Decrypt(); break; case 0: ProcessBlock_CCM_Decrypt(); break;
case 1: ProcessBlock_CCM_Encrypt(); break;
case 2: case 2:
case 3: ProcessBlock_CTR(); break; case 3: ProcessBlock_CTR(); break;
default:
// dorp
OutputFIFO->Write(InputFIFO->Read());
OutputFIFO->Write(InputFIFO->Read());
OutputFIFO->Write(InputFIFO->Read());
OutputFIFO->Write(InputFIFO->Read());
} }
RemBlocks--; RemBlocks--;
@ -398,6 +422,24 @@ void Update()
if (CurMAC[15-i] != MAC[i]) Cnt &= ~(1<<21); if (CurMAC[15-i] != MAC[i]) Cnt &= ~(1<<21);
} }
} }
else if (AESMode == 1)
{
Ctx.Iv[13] = 0x00;
Ctx.Iv[14] = 0x00;
Ctx.Iv[15] = 0x00;
AES_CTR_xcrypt_buffer(&Ctx, CurMAC, 16);
u8 finalmac[16];
Swap16(finalmac, CurMAC);
OutputFIFO->Write(*(u32*)&finalmac[0]);
OutputFIFO->Write(*(u32*)&finalmac[4]);
OutputFIFO->Write(*(u32*)&finalmac[8]);
OutputFIFO->Write(*(u32*)&finalmac[12]);
// CHECKME
Cnt &= ~(1<<21);
}
else else
{ {
// CHECKME // CHECKME

View File

@ -1,5 +1,5 @@
/* /*
Copyright 2016-2019 Arisotura Copyright 2016-2020 Arisotura
This file is part of melonDS. This file is part of melonDS.

View File

@ -1,5 +1,5 @@
/* /*
Copyright 2016-2019 Arisotura Copyright 2016-2020 Arisotura
This file is part of melonDS. This file is part of melonDS.

View File

@ -1,5 +1,5 @@
/* /*
Copyright 2016-2019 Arisotura Copyright 2016-2020 Arisotura
This file is part of melonDS. This file is part of melonDS.

View File

@ -1,5 +1,5 @@
/* /*
Copyright 2016-2019 Arisotura Copyright 2016-2020 Arisotura
This file is part of melonDS. This file is part of melonDS.

View File

@ -1,5 +1,5 @@
/* /*
Copyright 2016-2019 Arisotura Copyright 2016-2020 Arisotura
This file is part of melonDS. This file is part of melonDS.

View File

@ -1,5 +1,5 @@
/* /*
Copyright 2016-2019 Arisotura Copyright 2016-2020 Arisotura
This file is part of melonDS. This file is part of melonDS.

View File

@ -1,5 +1,5 @@
/* /*
Copyright 2016-2019 Arisotura Copyright 2016-2020 Arisotura
This file is part of melonDS. This file is part of melonDS.

View File

@ -1,5 +1,5 @@
/* /*
Copyright 2016-2019 Arisotura Copyright 2016-2020 Arisotura
This file is part of melonDS. This file is part of melonDS.
@ -21,6 +21,8 @@
#include "DSi.h" #include "DSi.h"
#include "DSi_NWifi.h" #include "DSi_NWifi.h"
#include "SPI.h" #include "SPI.h"
#include "WifiAP.h"
#include "Platform.h"
const u8 CIS0[256] = const u8 CIS0[256] =
@ -111,15 +113,37 @@ const u8 CIS1[256] =
}; };
// hax DSi_NWifi* Ctx = nullptr;
DSi_NWifi* hax_wifi;
void triggerirq(u32 param)
{
hax_wifi->SetIRQ_F1_Counter(0);
}
DSi_NWifi::DSi_NWifi(DSi_SDHost* host) : DSi_SDDevice(host) DSi_NWifi::DSi_NWifi(DSi_SDHost* host) : DSi_SDDevice(host)
{
// HACK
// the mailboxes are supposed to be 0x80 bytes
// however, as we do things instantly, emulating this is meaningless
// and only adds complication
for (int i = 0; i < 8; i++)
Mailbox[i] = new FIFO<u8>(0x600);//0x80);
// extra mailbox acting as a bigger RX buffer
Mailbox[8] = new FIFO<u8>(0x8000);
// this seems to control whether the firmware upload is done
EEPROMReady = 0;
Ctx = this;
}
DSi_NWifi::~DSi_NWifi()
{
for (int i = 0; i < 9; i++)
delete Mailbox[i];
NDS::CancelEvent(NDS::Event_DSi_NWifi);
Ctx = nullptr;
}
void DSi_NWifi::Reset()
{ {
TransferCmd = 0xFFFFFFFF; TransferCmd = 0xFFFFFFFF;
RemSize = 0; RemSize = 0;
@ -134,9 +158,8 @@ DSi_NWifi::DSi_NWifi(DSi_SDHost* host) : DSi_SDDevice(host)
WindowReadAddr = 0; WindowReadAddr = 0;
WindowWriteAddr = 0; WindowWriteAddr = 0;
// TODO: check the actual mailbox size (presumably 0x200) for (int i = 0; i < 9; i++)
for (int i = 0; i < 8; i++) Mailbox[i]->Clear();
Mailbox[i] = new FIFO<u8>(0x200);
u8* mac = SPI_Firmware::GetWifiMAC(); u8* mac = SPI_Firmware::GetWifiMAC();
printf("NWifi MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", printf("NWifi MAC: %02X:%02X:%02X:%02X:%02X:%02X\n",
@ -158,15 +181,17 @@ DSi_NWifi::DSi_NWifi(DSi_SDHost* host) : DSi_SDDevice(host)
*(u16*)&EEPROM[0x004] = chk; *(u16*)&EEPROM[0x004] = chk;
EEPROMReady = 0; // TODO: SDIO reset shouldn't reset this
// this is reset by the internal reset register, and that also resets EEPROM init
BootPhase = 0; BootPhase = 0;
}
DSi_NWifi::~DSi_NWifi() ErrorMask = 0;
{ ScanTimer = 0;
for (int i = 0; i < 8; i++)
delete Mailbox[i]; BeaconTimer = 0x10A2220ULL;
ConnectionStatus = 0;
NDS::CancelEvent(NDS::Event_DSi_NWifi);
} }
@ -283,6 +308,7 @@ u8 DSi_NWifi::F1_Read(u32 addr)
if (addr < 0x100) if (addr < 0x100)
{ {
u8 ret = Mailbox[4]->Read(); u8 ret = Mailbox[4]->Read();
if (addr == 0xFF) DrainRXBuffer();
UpdateIRQ_F1(); UpdateIRQ_F1();
return ret; return ret;
} }
@ -348,6 +374,7 @@ u8 DSi_NWifi::F1_Read(u32 addr)
else if (addr < 0x1000) else if (addr < 0x1000)
{ {
u8 ret = Mailbox[4]->Read(); u8 ret = Mailbox[4]->Read();
if (addr == 0xFFF) DrainRXBuffer();
UpdateIRQ_F1(); UpdateIRQ_F1();
return ret; return ret;
} }
@ -372,11 +399,12 @@ u8 DSi_NWifi::F1_Read(u32 addr)
else else
{ {
u8 ret = Mailbox[4]->Read(); u8 ret = Mailbox[4]->Read();
if (addr == 0x3FFF) DrainRXBuffer();
UpdateIRQ_F1(); UpdateIRQ_F1();
return ret; return ret;
} }
printf("NWIFI: unknown func1 read %05X\n", addr); //printf("NWIFI: unknown func1 read %05X\n", addr);
return 0; return 0;
} }
@ -663,13 +691,13 @@ void DSi_NWifi::HandleCommand()
switch (BootPhase) switch (BootPhase)
{ {
case 0: return BMI_Command(); case 0: return BMI_Command();
case 1: return WMI_Command(); case 1: return HTC_Command();
case 2: return WMI_Command();
} }
} }
void DSi_NWifi::BMI_Command() void DSi_NWifi::BMI_Command()
{ {
// HLE command handling stub
u32 cmd = MB_Read32(0); u32 cmd = MB_Read32(0);
switch (cmd) switch (cmd)
@ -678,8 +706,8 @@ void DSi_NWifi::BMI_Command()
{ {
printf("BMI_DONE\n"); printf("BMI_DONE\n");
EEPROMReady = 1; // GROSS FUCKING HACK EEPROMReady = 1; // GROSS FUCKING HACK
u8 ready_msg[8] = {0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00}; u8 ready_msg[6] = {0x0A, 0x00, 0x08, 0x06, 0x16, 0x00};
SendWMIFrame(ready_msg, 8, 0, 0x00, 0x0000); SendWMIEvent(0, 0x0001, ready_msg, 6);
BootPhase = 1; BootPhase = 1;
} }
return; return;
@ -743,7 +771,7 @@ void DSi_NWifi::BMI_Command()
{ {
u32 len = MB_Read32(0); u32 len = MB_Read32(0);
printf("BMI LZ write %08X\n", len); printf("BMI LZ write %08X\n", len);
//FILE* f = fopen("wififirm.bin", "ab"); //FILE* f = fopen("debug/wififirm.bin", "ab");
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++)
{ {
@ -762,15 +790,13 @@ void DSi_NWifi::BMI_Command()
} }
} }
void DSi_NWifi::WMI_Command() void DSi_NWifi::HTC_Command()
{ {
// HLE command handling stub
u16 h0 = MB_Read16(0); u16 h0 = MB_Read16(0);
u16 len = MB_Read16(0); u16 len = MB_Read16(0);
u16 h2 = MB_Read16(0); u16 h2 = MB_Read16(0);
u16 cmd = MB_Read16(0); u16 cmd = MB_Read16(0);
printf("WMI: cmd %04X\n", cmd);
switch (cmd) switch (cmd)
{ {
@ -778,59 +804,631 @@ void DSi_NWifi::WMI_Command()
{ {
u16 svc_id = MB_Read16(0); u16 svc_id = MB_Read16(0);
u16 conn_flags = MB_Read16(0); u16 conn_flags = MB_Read16(0);
printf("service connect %04X %04X %04X\n", svc_id, conn_flags, MB_Read16(0));
u8 svc_resp[10]; u8 svc_resp[8];
*(u16*)&svc_resp[0] = 0x0003; // responses from hardware:
*(u16*)&svc_resp[2] = svc_id; // 0003 0100 00 01 0602 00 00
svc_resp[4] = 0; // 0003 0101 00 02 0600 00 00
svc_resp[5] = (svc_id & 0xFF) + 1; // 0003 0102 00 03 0600 00 00
*(u16*)&svc_resp[6] = 0x0001; // 0003 0103 00 04 0600 00 00
*(u16*)&svc_resp[8] = 0x0001; // 0003 0104 00 05 0600 00 00
SendWMIFrame(svc_resp, 10, 0, 0x00, 0x0000); *(u16*)&svc_resp[0] = svc_id;
svc_resp[2] = 0;
svc_resp[3] = (svc_id & 0xFF) + 1;
*(u16*)&svc_resp[4] = (svc_id==0x0100) ? 0x0602 : 0x0600; // max message size
*(u16*)&svc_resp[6] = 0x0000;
SendWMIEvent(0, 0x0003, svc_resp, 8);
} }
break; break;
case 0x0004: // setup complete case 0x0004: // setup complete
{ {
u8 ready_evt[14]; u8 ready_evt[12];
memset(ready_evt, 0, 14); memcpy(&ready_evt[0], SPI_Firmware::GetWifiMAC(), 6);
*(u16*)&ready_evt[0] = 0x1001; ready_evt[6] = 0x02;
memcpy(&ready_evt[2], SPI_Firmware::GetWifiMAC(), 6); ready_evt[7] = 0;
ready_evt[8] = 0x02; *(u32*)&ready_evt[8] = 0x2300006C;
*(u32*)&ready_evt[10] = 0x23000024; SendWMIEvent(1, 0x1001, ready_evt, 12);
// ctrl[0] = trailer size
// trailer[1] = trailer extra size u8 regdomain_evt[4];
// trailer[0] = trailer type??? *(u32*)&regdomain_evt[0] = 0x80000000 | (*(u16*)&EEPROM[0x008] & 0x0FFF);
SendWMIFrame(ready_evt, 14, 1, 0x00, 0x0000); SendWMIEvent(1, 0x1006, regdomain_evt, 4);
BootPhase = 2;
NDS::ScheduleEvent(NDS::Event_DSi_NWifi, true, 33611, MSTimer, 0);
} }
break; break;
default: default:
printf("unknown WMI command %04X\n", cmd); printf("unknown HTC command %04X\n", cmd);
for (int i = 0; i < len; i++)
{
printf("%02X ", Mailbox[0]->Read());
if ((i&0xF)==0xF) printf("\n");
}
printf("\n");
break; break;
} }
MB_Drain(0); MB_Drain(0);
} }
void DSi_NWifi::SendWMIFrame(u8* data, u32 len, u8 ep, u8 flags, u16 ctrl) void DSi_NWifi::WMI_Command()
{ {
u32 wlen = 0; u16 h0 = MB_Read16(0);
u16 len = MB_Read16(0);
u16 h2 = MB_Read16(0);
Mailbox[4]->Write(ep); // eid u8 ep = h0 & 0xFF;
Mailbox[4]->Write(flags); // flags if (ep > 0x01) // data endpoints
MB_Write16(4, len); // payload length {
MB_Write16(4, ctrl); // ctrl WMI_SendPacket(len);
wlen += 6; }
else
{
u16 cmd = MB_Read16(0);
switch (cmd)
{
case 0x0001: // connect to network
{
WMI_ConnectToNetwork();
}
break;
case 0x0003: // disconnect
{
if (ConnectionStatus != 1)
printf("WMI: ?? trying to disconnect while not connected\n");
printf("WMI: disconnect\n");
ConnectionStatus = 0;
u8 reply[11];
*(u16*)&reply[0] = 3; // checkme
memcpy(&reply[2], WifiAP::APMac, 6);
reply[8] = 3; // disconnect reason (via cmd)
reply[9] = 0; // assoc-response length (none here)
reply[10] = 0; // we need atleast one byte here, even if there is no assoc-response
SendWMIEvent(1, 0x1003, reply, 11);
}
break;
case 0x0004: // synchronize
{
Mailbox[0]->Read();
// TODO??
}
break;
case 0x0005: // create priority stream
{
// TODO???
// there's a lot of crap in there.
}
break;
case 0x0007: // start scan
{
u32 forcefg = MB_Read32(0);
u32 legacy = MB_Read32(0);
u32 scantime = MB_Read32(0);
u32 forceinterval = MB_Read32(0);
u8 scantype = Mailbox[0]->Read();
u8 nchannels = Mailbox[0]->Read();
printf("WMI: start scan, forceFG=%d, legacy=%d, scanTime=%d, interval=%d, scanType=%d, chan=%d\n",
forcefg, legacy, scantime, forceinterval, scantype, nchannels);
if (ScanTimer > 0)
{
printf("!! CHECKME: START SCAN BUT WAS ALREADY SCANNING (%d)\n", ScanTimer);
}
// checkme
ScanTimer = scantime*5;
}
break;
case 0x0008: // set scan params
{
// TODO: do something with the params!!
}
break;
case 0x0009: // set BSS filter
{
// TODO: do something with the params!!
u8 bssfilter = Mailbox[0]->Read();
Mailbox[0]->Read();
Mailbox[0]->Read();
Mailbox[0]->Read();
u32 iemask = MB_Read32(0);
printf("WMI: set BSS filter, filter=%02X, iemask=%08X\n", bssfilter, iemask);
}
break;
case 0x000A: // set probed BSSID
{
u8 id = Mailbox[0]->Read();
u8 flags = Mailbox[0]->Read();
u8 len = Mailbox[0]->Read();
char ssid[33] = {0};
for (int i = 0; i < len && i < 32; i++)
ssid[i] = Mailbox[0]->Read();
// TODO: store it somewhere
printf("WMI: set probed SSID: id=%d, flags=%02X, len=%d, SSID=%s\n", id, flags, len, ssid);
}
break;
case 0x000D: // set disconnect timeout
{
Mailbox[0]->Read();
// TODO??
}
break;
case 0x000E: // get channel list
{
int nchan = 11; // TODO: customize??
u8 reply[2 + (nchan*2) + 2];
reply[0] = 0;
reply[1] = nchan;
for (int i = 0; i < nchan; i++)
*(u16*)&reply[2 + (i*2)] = 2412 + (i*5);
*(u16*)&reply[2 + (nchan*2)] = 0;
SendWMIEvent(1, 0x000E, reply, 4+(nchan*2));
}
break;
case 0x0011: // set channel params
{
Mailbox[0]->Read();
u8 scan = Mailbox[0]->Read();
u8 phymode = Mailbox[0]->Read();
u8 len = Mailbox[0]->Read();
u16 channels[32];
for (int i = 0; i < len && i < 32; i++)
channels[i] = MB_Read16(0);
// TODO: store it somewhere
printf("WMI: set channel params: scan=%d, phymode=%d, len=%d, channels=", scan, phymode, len);
for (int i = 0; i < len && i < 32; i++)
printf("%d,", channels[i]);
printf("\n");
}
break;
case 0x0012: // set power mode
{
Mailbox[0]->Read();
// TODO??
}
break;
case 0x0017: // dummy?
Mailbox[0]->Read();
break;
case 0x0022: // set error bitmask
{
ErrorMask = MB_Read32(0);
}
break;
case 0x002E: // extension shit
{
u32 extcmd = MB_Read32(0);
switch (extcmd)
{
case 0x2008: // 'heartbeat'??
{
u32 cookie = MB_Read32(0);
u32 source = MB_Read32(0);
u8 reply[12];
*(u32*)&reply[0] = 0x3007;
*(u32*)&reply[4] = cookie;
*(u32*)&reply[8] = source;
SendWMIEvent(1, 0x1010, reply, 12);
}
break;
default:
printf("WMI: unknown ext cmd 002E:%04X\n", extcmd);
break;
}
}
break;
case 0x003D: // set keepalive interval
{
Mailbox[0]->Read();
// TODO??
}
break;
case 0x0041: // 'WMI_SET_WSC_STATUS_CMD'
{
Mailbox[0]->Read();
// TODO??
}
break;
case 0x0047: // cmd47 -- timer shenanigans??
{
//
}
break;
case 0x0048: // not supported by DSi??
{
MB_Read32(0);
MB_Read32(0);
Mailbox[0]->Read();
Mailbox[0]->Read();
}
break;
case 0x0049: // 'host exit notify'
{
//
}
break;
case 0xF000: // set bitrate
{
// TODO!
Mailbox[0]->Read();
Mailbox[0]->Read();
Mailbox[0]->Read();
}
break;
default:
printf("unknown WMI command %04X (header: %04X:%04X:%04X)\n", cmd, h0, len, h2);
for (int i = 0; i < len-2; i++)
{
printf("%02X ", Mailbox[0]->Read());
if ((i&0xF)==0xF) printf("\n");
}
printf("\n");
break;
}
}
if (h0 & (1<<8))
SendWMIAck(ep);
MB_Drain(0);
}
void DSi_NWifi::WMI_ConnectToNetwork()
{
u8 type = Mailbox[0]->Read();
u8 auth11 = Mailbox[0]->Read();
u8 auth = Mailbox[0]->Read();
u8 pCryptoType = Mailbox[0]->Read();
u8 pCryptoLen = Mailbox[0]->Read();
u8 gCryptoType = Mailbox[0]->Read();
u8 gCryptoLen = Mailbox[0]->Read();
u8 ssidLen = Mailbox[0]->Read();
char ssid[33] = {0};
for (int i = 0; i < 32; i++)
ssid[i] = Mailbox[0]->Read();
if (ssidLen <= 32)
ssid[ssidLen] = '\0';
u16 channel = MB_Read16(0);
u8 bssid[6];
*(u32*)&bssid[0] = MB_Read32(0);
*(u16*)&bssid[4] = MB_Read16(0);
u32 flags = MB_Read32(0);
if ((type != 0x01) ||
(auth11 != 0x01) ||
(auth != 0x01) ||
(pCryptoType != 0x01) ||
(gCryptoType != 0x01) ||
(memcmp(bssid, WifiAP::APMac, 6)))
{
printf("WMI_Connect: bad parameters\n");
// TODO: send disconnect??
return;
}
printf("WMI: connecting to network %s\n", ssid);
u8 reply[20];
// hope this is right!
*(u16*)&reply[0] = 2437; // channel
memcpy(&reply[2], WifiAP::APMac, 6); // BSSID
*(u16*)&reply[8] = 128; // listen interval
*(u16*)&reply[10] = 128; // beacon interval
*(u32*)&reply[12] = 0x01; // network type
reply[16] = 0x16; // beaconIeLen ???
reply[17] = 0x2F; // assocReqLen
reply[18] = 0x16; // assocRespLen
reply[19] = 0; // ?????
SendWMIEvent(1, 0x1002, reply, 20);
ConnectionStatus = 1;
}
void DSi_NWifi::WMI_SendPacket(u16 len)
{
if (ConnectionStatus != 1)
{
printf("WMI: !! trying to send shit while not connected\n");
// TODO: report error??
return;
}
// header???
// packets with bit1=1 are something special (sync??)
// otherwise, ????
// header is 001C on ARP frames, 0000 otherwise
u16 hdr = MB_Read16(0);
hdr = ((hdr & 0xFF00) >> 8) | ((hdr & 0x00FF) << 8);
u16 type = hdr & 0x0003;
if (type == 2) // data sync
{
printf("WMI: data sync\n");
/*Mailbox[8]->Write(2); // eid
Mailbox[8]->Write(0x00); // flags
MB_Write16(8, 2); // data length
Mailbox[8]->Write(0); //
Mailbox[8]->Write(0); //
MB_Write16(8, 0x0200); //
DrainRXBuffer();*/
return;
}
if (type)
{
printf("WMI: special frame %04X len=%d\n", hdr, len);
for (int i = 0; i < len-2; i++)
{
printf("%02X ", Mailbox[0]->Read());
if ((i&0xF)==0xF) printf("\n");
}
printf("\n");
return;
}
printf("WMI: send packet, hdr=%04X, len=%d\n", hdr, len);
u8 dstmac[6];
u8 srcmac[6];
u16 plen;
*(u32*)&dstmac[0] = MB_Read32(0);
*(u16*)&dstmac[4] = MB_Read16(0);
*(u32*)&srcmac[0] = MB_Read32(0);
*(u16*)&srcmac[4] = MB_Read16(0);
plen = MB_Read16(0);
plen = ((plen & 0xFF00) >> 8) | ((plen & 0x00FF) << 8);
if (plen > len-16)
{
printf("WMI: bad packet length %d > %d\n", plen, len-16);
return;
}
u32 h0 = MB_Read32(0);
u16 h1 = MB_Read16(0);
if (h0 != 0x0003AAAA || h1 != 0x0000)
{
printf("WMI: bad LLC/SLIP header\n");
return;
}
u16 ethertype = MB_Read16(0);
int lan_len = (plen - 8) + 14;
memcpy(&LANBuffer[0], dstmac, 6); // destination MAC
memcpy(&LANBuffer[6], srcmac, 6); // source MAC
*(u16*)&LANBuffer[12] = ethertype; // type
for (int i = 0; i < lan_len-14; i++)
{
LANBuffer[14+i] = Mailbox[0]->Read();
}
/*for (int i = 0; i < lan_len; i++)
{
printf("%02X ", LANBuffer[i]);
if ((i&0xF)==0xF) printf("\n");
}
printf("\n");*/
Platform::LAN_SendPacket(LANBuffer, lan_len);
}
void DSi_NWifi::SendWMIEvent(u8 ep, u16 id, u8* data, u32 len)
{
if (!Mailbox[8]->CanFit(6+len+2+8))
{
printf("NWifi: !! not enough space in RX buffer for WMI event %04X\n", id);
return;
}
Mailbox[8]->Write(ep); // eid
Mailbox[8]->Write(0x02); // flags (trailer)
MB_Write16(8, len+2+8); // data length (plus event ID and trailer)
Mailbox[8]->Write(8); // trailer length
Mailbox[8]->Write(0); //
MB_Write16(8, id); // event ID
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++)
{ {
Mailbox[4]->Write(data[i]); Mailbox[8]->Write(data[i]);
wlen++;
} }
for (; wlen & 0x7F; wlen++) // trailer
Mailbox[4]->Write(0); Mailbox[8]->Write(0x02);
Mailbox[8]->Write(0x06);
Mailbox[8]->Write(0x00);
Mailbox[8]->Write(0x00);
Mailbox[8]->Write(0x00);
Mailbox[8]->Write(0x00);
Mailbox[8]->Write(0x00);
Mailbox[8]->Write(0x00);
DrainRXBuffer();
}
void DSi_NWifi::SendWMIAck(u8 ep)
{
if (!Mailbox[8]->CanFit(6+12))
{
printf("NWifi: !! not enough space in RX buffer for WMI ack (ep #%d)\n", ep);
return;
}
Mailbox[8]->Write(0); // eid
Mailbox[8]->Write(0x02); // flags (trailer)
MB_Write16(8, 0xC); // data length (plus trailer)
Mailbox[8]->Write(0xC); // trailer length
Mailbox[8]->Write(0); //
// credit report
Mailbox[8]->Write(0x01);
Mailbox[8]->Write(0x02);
Mailbox[8]->Write(ep);
Mailbox[8]->Write(0x01);
// lookahead
Mailbox[8]->Write(0x02);
Mailbox[8]->Write(0x06);
Mailbox[8]->Write(0x00);
Mailbox[8]->Write(0x00);
Mailbox[8]->Write(0x00);
Mailbox[8]->Write(0x00);
Mailbox[8]->Write(0x00);
Mailbox[8]->Write(0x00);
DrainRXBuffer();
}
void DSi_NWifi::SendWMIBSSInfo(u8 type, u8* data, u32 len)
{
if (!Mailbox[8]->CanFit(6+len+2+16))
{
printf("NWifi: !! not enough space in RX buffer for WMI BSSINFO event\n");
return;
}
// TODO: check when version>=2 frame type is used?
// I observed the version<2 variant on my DSi
Mailbox[8]->Write(1); // eid
Mailbox[8]->Write(0x00); // flags
MB_Write16(8, len+2+16); // data length (plus event ID and trailer)
Mailbox[8]->Write(0xFF); // trailer length
Mailbox[8]->Write(0xFF); //
MB_Write16(8, 0x1004); // event ID
MB_Write16(8, 2437); // channel (6) (checkme!)
Mailbox[8]->Write(type);
Mailbox[8]->Write(0x1B); // 'snr'
MB_Write16(8, 0xFFBC); // RSSI
MB_Write32(8, *(u32*)&WifiAP::APMac[0]);
MB_Write16(8, *(u16*)&WifiAP::APMac[4]);
MB_Write32(8, 0); // ieMask
for (int i = 0; i < len; i++)
{
Mailbox[8]->Write(data[i]);
}
DrainRXBuffer();
}
void DSi_NWifi::CheckRX()
{
if (!Mailbox[8]->CanFit(2048))
return;
int rxlen = Platform::LAN_RecvPacket(LANBuffer);
if (rxlen > 0)
{
//printf("WMI packet recv %04X %04X %04X\n", *(u16*)&LANBuffer[0], *(u16*)&LANBuffer[2], *(u16*)&LANBuffer[4]);
// check destination MAC
if (*(u32*)&LANBuffer[0] != 0xFFFFFFFF || *(u16*)&LANBuffer[4] != 0xFFFF)
{
if (memcmp(&LANBuffer[0], &EEPROM[0x00A], 6))
return;
}
// check source MAC, in case we get a packet we just sent out
if (!memcmp(&LANBuffer[6], &EEPROM[0x00A], 6))
return;
// packet is good
printf("WMI: receive packet %04X, len=%d\n", *(u16*)&LANBuffer[12], rxlen);
/*for (int i = 0; i < rxlen; i++)
{
printf("%02X ", LANBuffer[i]);
if ((i&0xF)==0xF) printf("\n");
}
printf("\n");*/
int datalen = rxlen - 14; // length of packet body
u16 hdr = 0x0000;
//if (*(u16*)&LANBuffer[12] == 0x0608) // HAX!!!
// hdr = 0x1C00;
hdr = 0x80;
// TODO: not hardcode the endpoint ID!!
u8 ep = 2;
Mailbox[8]->Write(ep);
Mailbox[8]->Write(0x00);
MB_Write16(8, 16 + 8 + datalen);
Mailbox[8]->Write(0);
Mailbox[8]->Write(0);
MB_Write16(8, hdr);
MB_Write32(8, *(u32*)&LANBuffer[0]);
MB_Write16(8, *(u16*)&LANBuffer[4]);
MB_Write32(8, *(u32*)&LANBuffer[6]);
MB_Write16(8, *(u16*)&LANBuffer[10]);
u16 plen = datalen + 8;
plen = ((plen & 0xFF00) >> 8) | ((plen & 0x00FF) << 8);
MB_Write16(8, plen);
MB_Write16(8, 0xAAAA);
MB_Write16(8, 0x0003);
MB_Write16(8, 0x0000);
MB_Write16(8, *(u16*)&LANBuffer[12]);
for (int i = 0; i < datalen; i++)
Mailbox[8]->Write(LANBuffer[14+i]);
DrainRXBuffer();
}
} }
@ -849,7 +1447,7 @@ u32 DSi_NWifi::WindowRead(u32 addr)
// base address of EEPROM data // base address of EEPROM data
// TODO find what the actual address is! // TODO find what the actual address is!
return 0x1FFC00; return 0x1FFC00;
case 0x58: return EEPROMReady; // hax case 0x58: return EEPROMReady;
} }
return 0; return 0;
@ -879,3 +1477,69 @@ void DSi_NWifi::WindowWrite(u32 addr, u32 val)
{ {
printf("NWifi: window write %08X %08X\n", addr, val); printf("NWifi: window write %08X %08X\n", addr, val);
} }
void DSi_NWifi::_MSTimer()
{
BeaconTimer++;
if (ScanTimer > 0)
{
ScanTimer--;
// send a beacon
if (!(BeaconTimer & 0x7F))
{
u8 beacon[] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // timestamp
0x80, 0x00, // beacon interval
0x21, 0x00, // capability,
0x01, 0x08, 0x82, 0x84, 0x8B, 0x96, 0x0C, 0x12, 0x18, 0x24, // rates
0x03, 0x01, 0x06, // channel
0x05, 0x04, 0x00, 0x00, 0x00, 0x00, // TIM
0x00, 0x07, 'm', 'e', 'l', 'o', 'n', 'A', 'P', // SSID
};
SendWMIBSSInfo(0x01, beacon, sizeof(beacon));
printf("send beacon\n");
}
if (ScanTimer == 0)
{
u32 status = 0;
SendWMIEvent(1, 0x100A, (u8*)&status, 4);
}
}
if (ConnectionStatus == 1)
{
//if (Mailbox[4]->IsEmpty())
CheckRX();
}
}
void DSi_NWifi::DrainRXBuffer()
{
while (Mailbox[8]->Level() >= 6)
{
u16 len = Mailbox[8]->Peek(2) | (Mailbox[8]->Peek(3) << 8);
u32 totallen = len + 6;
u32 required = (totallen + 0x7F) & ~0x7F;
if (!Mailbox[4]->CanFit(required))
break;
u32 i = 0;
for (; i < totallen; i++) Mailbox[4]->Write(Mailbox[8]->Read());
for (; i < required; i++) Mailbox[4]->Write(0);
}
UpdateIRQ_F1();
}
void DSi_NWifi::MSTimer(u32 param)
{
Ctx->_MSTimer();
NDS::ScheduleEvent(NDS::Event_DSi_NWifi, true, 33611, MSTimer, 0);
}

View File

@ -1,5 +1,5 @@
/* /*
Copyright 2016-2019 Arisotura Copyright 2016-2020 Arisotura
This file is part of melonDS. This file is part of melonDS.
@ -28,6 +28,8 @@ public:
DSi_NWifi(DSi_SDHost* host); DSi_NWifi(DSi_SDHost* host);
~DSi_NWifi(); ~DSi_NWifi();
void Reset();
void SendCMD(u8 cmd, u32 param); void SendCMD(u8 cmd, u32 param);
void SendACMD(u8 cmd, u32 param); void SendACMD(u8 cmd, u32 param);
@ -35,6 +37,10 @@ public:
void SetIRQ_F1_Counter(u32 n); void SetIRQ_F1_Counter(u32 n);
void _MSTimer();
static void MSTimer(u32 param);
private: private:
u32 TransferCmd; u32 TransferCmd;
u32 TransferAddr; u32 TransferAddr;
@ -60,9 +66,18 @@ private:
void HandleCommand(); void HandleCommand();
void BMI_Command(); void BMI_Command();
void HTC_Command();
void WMI_Command(); void WMI_Command();
void SendWMIFrame(u8* data, u32 len, u8 ep, u8 flags, u16 ctrl); void WMI_ConnectToNetwork();
void WMI_SendPacket(u16 len);
void SendWMIEvent(u8 ep, u16 id, u8* data, u32 len);
void SendWMIAck(u8 ep);
void SendWMIBSSInfo(u8 type, u8* data, u32 len);
void CheckRX();
void DrainRXBuffer();
u32 WindowRead(u32 addr); u32 WindowRead(u32 addr);
void WindowWrite(u32 addr, u32 val); void WindowWrite(u32 addr, u32 val);
@ -102,7 +117,7 @@ private:
while (!Mailbox[n]->IsEmpty()) Mailbox[n]->Read(); while (!Mailbox[n]->IsEmpty()) Mailbox[n]->Read();
} }
FIFO<u8>* Mailbox[8]; FIFO<u8>* Mailbox[9];
u8 F0_IRQEnable; u8 F0_IRQEnable;
u8 F0_IRQStatus; u8 F0_IRQStatus;
@ -116,6 +131,14 @@ private:
u32 EEPROMReady; u32 EEPROMReady;
u32 BootPhase; u32 BootPhase;
u32 ErrorMask;
u32 ScanTimer;
u64 BeaconTimer;
u32 ConnectionStatus;
u8 LANBuffer[2048];
}; };
#endif // DSI_NWIFI_H #endif // DSI_NWIFI_H

View File

@ -1,5 +1,5 @@
/* /*
Copyright 2016-2019 Arisotura Copyright 2016-2020 Arisotura
This file is part of melonDS. This file is part of melonDS.
@ -112,8 +112,8 @@ void DSi_SDHost::Reset()
if (Ports[0]) delete Ports[0]; if (Ports[0]) delete Ports[0];
if (Ports[1]) delete Ports[1]; if (Ports[1]) delete Ports[1];
Ports[0] = NULL; Ports[0] = nullptr;
Ports[1] = NULL; Ports[1] = nullptr;
if (Num == 0) if (Num == 0)
{ {
@ -135,6 +135,9 @@ void DSi_SDHost::Reset()
Ports[0] = nwifi; Ports[0] = nwifi;
} }
if (Ports[0]) Ports[0]->Reset();
if (Ports[1]) Ports[1]->Reset();
} }
void DSi_SDHost::DoSavestate(Savestate* file) void DSi_SDHost::DoSavestate(Savestate* file)
@ -205,6 +208,18 @@ void DSi_SDHost::SetCardIRQ()
} }
} }
void DSi_SDHost::UpdateCardIRQ(u16 oldmask)
{
u16 oldflags = CardIRQStatus & ~oldmask;
u16 newflags = CardIRQStatus & ~CardIRQMask;
if ((oldflags == 0) && (newflags != 0)) // checkme
{
NDS::SetIRQ2(Num ? NDS::IRQ2_DSi_SDIO : NDS::IRQ2_DSi_SDMMC);
NDS::SetIRQ2(Num ? NDS::IRQ2_DSi_SDIO_Data1 : NDS::IRQ2_DSi_SD_Data1);
}
}
void DSi_SDHost::SendResponse(u32 val, bool last) void DSi_SDHost::SendResponse(u32 val, bool last)
{ {
*(u32*)&ResponseBuffer[6] = *(u32*)&ResponseBuffer[4]; *(u32*)&ResponseBuffer[6] = *(u32*)&ResponseBuffer[4];
@ -448,6 +463,7 @@ u16 DSi_SDHost::Read(u32 addr)
case 0x0F6: return 0; // MMC write protect (always 0) case 0x0F6: return 0; // MMC write protect (always 0)
case 0x100: return Data32IRQ; case 0x100: return Data32IRQ;
case 0x102: return 0;
case 0x104: return BlockLen32; case 0x104: return BlockLen32;
case 0x108: return BlockCount32; case 0x108: return BlockCount32;
} }
@ -549,8 +565,8 @@ void DSi_SDHost::Write(u32 addr, u16 val)
u32 oldmask = IRQMask; u32 oldmask = IRQMask;
IRQMask = (IRQMask & 0x0000031D) | ((val & 0x8B7F) << 16); IRQMask = (IRQMask & 0x0000031D) | ((val & 0x8B7F) << 16);
UpdateIRQ(oldmask); UpdateIRQ(oldmask);
if (!DataFIFO[CurFIFO]->IsEmpty()) SetIRQ(24); // checkme //if (!DataFIFO[CurFIFO]->IsEmpty()) SetIRQ(24); // checkme
if (DataFIFO[CurFIFO]->IsEmpty()) SetIRQ(25); // checkme //if (DataFIFO[CurFIFO]->IsEmpty()) SetIRQ(25); // checkme
} }
return; return;
@ -571,8 +587,13 @@ void DSi_SDHost::Write(u32 addr, u16 val)
CardIRQStatus &= val; CardIRQStatus &= val;
return; return;
case 0x038: case 0x038:
CardIRQMask = val & 0xC007; {
SetCardIRQ(); u16 oldmask = CardIRQMask;
CardIRQMask = val & 0xC007;
UpdateCardIRQ(oldmask);
}
//CardIRQMask = val & 0xC007;
//SetCardIRQ();
return; return;
case 0x0D8: case 0x0D8:
@ -592,6 +613,9 @@ void DSi_SDHost::Write(u32 addr, u16 val)
SDOption = 0x40EE; SDOption = 0x40EE;
// TODO: CARD_IRQ_STAT // TODO: CARD_IRQ_STAT
// TODO: FIFO16 shit // TODO: FIFO16 shit
if (Ports[0]) Ports[0]->Reset();
if (Ports[1]) Ports[1]->Reset();
} }
SoftReset = 0x0006 | (val & 0x0001); SoftReset = 0x0006 | (val & 0x0001);
return; return;
@ -601,6 +625,7 @@ void DSi_SDHost::Write(u32 addr, u16 val)
if (val & (1<<10)) DataFIFO32->Clear(); if (val & (1<<10)) DataFIFO32->Clear();
DataMode = ((DataCtl >> 1) & 0x1) & ((Data32IRQ >> 1) & 0x1); DataMode = ((DataCtl >> 1) & 0x1) & ((Data32IRQ >> 1) & 0x1);
return; return;
case 0x102: return;
case 0x104: BlockLen32 = val & 0x03FF; return; case 0x104: BlockLen32 = val & 0x03FF; return;
case 0x108: BlockCount32 = val; return; case 0x108: BlockCount32 = val; return;
} }
@ -701,6 +726,16 @@ DSi_MMCStorage::DSi_MMCStorage(DSi_SDHost* host, bool internal, const char* path
File = Platform::OpenLocalFile(path, "w+b"); File = Platform::OpenLocalFile(path, "w+b");
} }
} }
}
DSi_MMCStorage::~DSi_MMCStorage()
{
if (File) fclose(File);
}
void DSi_MMCStorage::Reset()
{
// TODO: reset file access????
CSR = 0x00000100; // checkme CSR = 0x00000100; // checkme
@ -723,11 +758,6 @@ DSi_MMCStorage::DSi_MMCStorage(DSi_SDHost* host, bool internal, const char* path
RWCommand = 0; RWCommand = 0;
} }
DSi_MMCStorage::~DSi_MMCStorage()
{
if (File) fclose(File);
}
void DSi_MMCStorage::SendCMD(u8 cmd, u32 param) void DSi_MMCStorage::SendCMD(u8 cmd, u32 param)
{ {
if (CSR & (1<<5)) if (CSR & (1<<5))

View File

@ -1,5 +1,5 @@
/* /*
Copyright 2016-2019 Arisotura Copyright 2016-2020 Arisotura
This file is part of melonDS. This file is part of melonDS.
@ -95,6 +95,7 @@ private:
void ClearIRQ(u32 irq); void ClearIRQ(u32 irq);
void SetIRQ(u32 irq); void SetIRQ(u32 irq);
void UpdateIRQ(u32 oldmask); void UpdateIRQ(u32 oldmask);
void UpdateCardIRQ(u16 oldmask);
}; };
@ -104,6 +105,8 @@ public:
DSi_SDDevice(DSi_SDHost* host) { Host = host; IRQ = false; } DSi_SDDevice(DSi_SDHost* host) { Host = host; IRQ = false; }
~DSi_SDDevice() {} ~DSi_SDDevice() {}
virtual void Reset() = 0;
virtual void SendCMD(u8 cmd, u32 param) = 0; virtual void SendCMD(u8 cmd, u32 param) = 0;
virtual void ContinueTransfer() = 0; virtual void ContinueTransfer() = 0;
@ -120,6 +123,8 @@ public:
DSi_MMCStorage(DSi_SDHost* host, bool internal, const char* path); DSi_MMCStorage(DSi_SDHost* host, bool internal, const char* path);
~DSi_MMCStorage(); ~DSi_MMCStorage();
void Reset();
void SetCID(u8* cid) { memcpy(CID, cid, 16); } void SetCID(u8* cid) { memcpy(CID, cid, 16); }
void SendCMD(u8 cmd, u32 param); void SendCMD(u8 cmd, u32 param);

View File

@ -1,5 +1,5 @@
/* /*
Copyright 2016-2019 Arisotura Copyright 2016-2020 Arisotura
This file is part of melonDS. This file is part of melonDS.

View File

@ -1,5 +1,5 @@
/* /*
Copyright 2016-2019 Arisotura Copyright 2016-2020 Arisotura
This file is part of melonDS. This file is part of melonDS.

View File

@ -102,6 +102,8 @@ public:
bool IsEmpty() { return NumOccupied == 0; } bool IsEmpty() { return NumOccupied == 0; }
bool IsFull() { return NumOccupied >= NumEntries; } bool IsFull() { return NumOccupied >= NumEntries; }
bool CanFit(u32 num) { return ((NumOccupied + num) <= NumEntries); }
private: private:
u32 NumEntries; u32 NumEntries;
T* Entries; T* Entries;

View File

@ -493,7 +493,7 @@ void Reset()
printf("ARM7 BIOS loaded\n"); printf("ARM7 BIOS loaded\n");
fclose(f); fclose(f);
} }
#ifdef JIT_ENABLED #ifdef JIT_ENABLED
ARMJIT::Reset(); ARMJIT::Reset();
#endif #endif
@ -1137,7 +1137,9 @@ void MapSharedWRAM(u8 val)
if (val == WRAMCnt) if (val == WRAMCnt)
return; return;
#ifdef JIT_ENABLED
ARMJIT_Memory::RemapSWRAM(); ARMJIT_Memory::RemapSWRAM();
#endif
WRAMCnt = val; WRAMCnt = val;
@ -1268,6 +1270,9 @@ bool HaltInterrupted(u32 cpu)
if (IF[cpu] & IE[cpu]) if (IF[cpu] & IE[cpu])
return true; return true;
if ((ConsoleType == 1) && cpu && (IF2 & IE2))
return true;
return false; return false;
} }
@ -1813,14 +1818,14 @@ void debug(u32 param)
} }
fclose(shit);*/ fclose(shit);*/
FILE* FILE*
/*shit = fopen("debug/dump9.bin", "wb"); shit = fopen("debug/dump9.bin", "wb");
for (u32 i = 0x02000000; i < 0x04000000; i+=4) for (u32 i = 0x02000000; i < 0x04000000; i+=4)
{ {
u32 val = DSi::ARM9Read32(i); u32 val = DSi::ARM9Read32(i);
fwrite(&val, 4, 1, shit); fwrite(&val, 4, 1, shit);
} }
fclose(shit);*/ fclose(shit);
shit = fopen("debug/dump7_2.bin", "wb"); shit = fopen("debug/dump7.bin", "wb");
for (u32 i = 0x02000000; i < 0x04000000; i+=4) for (u32 i = 0x02000000; i < 0x04000000; i+=4)
{ {
u32 val = DSi::ARM7Read32(i); u32 val = DSi::ARM7Read32(i);

View File

@ -106,7 +106,6 @@ u8 BCD(u8 val)
void ByteIn(u8 val) void ByteIn(u8 val)
{ {
//printf("RTC IN: %02X\n", val);
if (InputPos == 0) if (InputPos == 0)
{ {
if ((val & 0xF0) == 0x60) if ((val & 0xF0) == 0x60)
@ -175,7 +174,6 @@ void ByteIn(u8 val)
case 0x70: Output[0] = FreeReg; break; case 0x70: Output[0] = FreeReg; break;
} }
} }
InputPos++;
return; return;
} }
@ -221,8 +219,6 @@ void ByteIn(u8 val)
if (InputPos == 1) FreeReg = val; if (InputPos == 1) FreeReg = val;
break; break;
} }
InputPos++;
} }

View File

@ -162,22 +162,26 @@ void Reset()
UserSettings = userdata; UserSettings = userdata;
// fix touchscreen coords // TODO evetually: do this in DSi mode
#if 0 if (NDS::ConsoleType == 0)
*(u16*)&Firmware[userdata+0x58] = 0; {
*(u16*)&Firmware[userdata+0x5A] = 0; // fix touchscreen coords
Firmware[userdata+0x5C] = 0; *(u16*)&Firmware[userdata+0x58] = 0;
Firmware[userdata+0x5D] = 0; *(u16*)&Firmware[userdata+0x5A] = 0;
*(u16*)&Firmware[userdata+0x5E] = 255<<4; Firmware[userdata+0x5C] = 0;
*(u16*)&Firmware[userdata+0x60] = 191<<4; Firmware[userdata+0x5D] = 0;
Firmware[userdata+0x62] = 255; *(u16*)&Firmware[userdata+0x5E] = 255<<4;
Firmware[userdata+0x63] = 191; *(u16*)&Firmware[userdata+0x60] = 191<<4;
Firmware[userdata+0x62] = 255;
Firmware[userdata+0x63] = 191;
// disable autoboot // disable autoboot
//Firmware[userdata+0x64] &= 0xBF; //Firmware[userdata+0x64] &= 0xBF;
*(u16*)&Firmware[userdata+0x72] = CRC16(&Firmware[userdata], 0x70, 0xFFFF); *(u16*)&Firmware[userdata+0x72] = CRC16(&Firmware[userdata], 0x70, 0xFFFF);
}
#if 0
// replace MAC address with random address // replace MAC address with random address
// TODO: make optional? // TODO: make optional?
Firmware[0x36] = 0x00; Firmware[0x36] = 0x00;

View File

@ -160,6 +160,8 @@ void Channel::Reset()
else else
BusRead32 = NDS::ARM7Read32; BusRead32 = NDS::ARM7Read32;
KeyOn = false;
SetCnt(0); SetCnt(0);
SrcAddr = 0; SrcAddr = 0;
TimerReload = 0; TimerReload = 0;
@ -187,6 +189,7 @@ void Channel::DoSavestate(Savestate* file)
file->Var8(&VolumeShift); file->Var8(&VolumeShift);
file->Var8(&Pan); file->Var8(&Pan);
file->Var8((u8*)&KeyOn);
file->Var32(&Timer); file->Var32(&Timer);
file->Var32((u32*)&Pos); file->Var32((u32*)&Pos);
file->Var16((u16*)&CurSample); file->Var16((u16*)&CurSample);
@ -417,6 +420,12 @@ void Channel::Run(s32* buf, u32 samples)
{ {
if (!(Cnt & (1<<31))) return; if (!(Cnt & (1<<31))) return;
if (KeyOn)
{
Start();
KeyOn = false;
}
for (u32 s = 0; s < samples; s++) for (u32 s = 0; s < samples; s++)
{ {
Timer += 512; // 1 sample = 512 cycles at 16MHz Timer += 512; // 1 sample = 512 cycles at 16MHz

View File

@ -69,6 +69,7 @@ public:
u8 VolumeShift; u8 VolumeShift;
u8 Pan; u8 Pan;
bool KeyOn;
u32 Timer; u32 Timer;
s32 Pos; s32 Pos;
s16 CurSample; s16 CurSample;
@ -105,7 +106,7 @@ public:
if ((val & (1<<31)) && !(oldcnt & (1<<31))) if ((val & (1<<31)) && !(oldcnt & (1<<31)))
{ {
Start(); KeyOn = true;
} }
} }

View File

@ -188,6 +188,8 @@ void Reset()
IOPORT(0x000) = 0x1440; IOPORT(0x000) = 0x1440;
else if (console == 0x20) else if (console == 0x20)
IOPORT(0x000) = 0xC340; IOPORT(0x000) = 0xC340;
else if (NDS::ConsoleType == 1 && console == 0x57)
IOPORT(0x000) = 0xC340; // DSi has the modern DS-wifi variant
else else
{ {
printf("wifi: unknown console type %02X\n", console); printf("wifi: unknown console type %02X\n", console);

View File

@ -30,9 +30,6 @@
namespace WifiAP namespace WifiAP
{ {
#define AP_MAC 0x00, 0xF0, 0x77, 0x77, 0x77, 0x77
#define AP_NAME "melonAP"
const u8 APMac[6] = {AP_MAC}; const u8 APMac[6] = {AP_MAC};
#define PWRITE_8(p, v) *p++ = v; #define PWRITE_8(p, v) *p++ = v;
@ -130,6 +127,18 @@ void USTimer()
} }
} }
void MSTimer()
{
USCounter += 0x400;
u32 chk = (u32)USCounter;
if (!(chk & 0x1FC00))
{
// send beacon every 128ms
BeaconDue = true;
}
}
int HandleManagementFrame(u8* data, int len) int HandleManagementFrame(u8* data, int len)
{ {

View File

@ -22,11 +22,17 @@
namespace WifiAP namespace WifiAP
{ {
#define AP_MAC 0x00, 0xF0, 0x77, 0x77, 0x77, 0x77
#define AP_NAME "melonAP"
extern const u8 APMac[6];
bool Init(); bool Init();
void DeInit(); void DeInit();
void Reset(); void Reset();
void USTimer(); void USTimer();
void MSTimer();
// packet format: 12-byte TX header + original 802.11 frame // packet format: 12-byte TX header + original 802.11 frame
int SendPacket(u8* data, int len); int SendPacket(u8* data, int len);

View File

@ -46,7 +46,9 @@ set(CMAKE_AUTORCC ON)
find_package(Threads REQUIRED) find_package(Threads REQUIRED)
find_package(PkgConfig REQUIRED) find_package(PkgConfig REQUIRED)
find_package(Iconv REQUIRED)
pkg_check_modules(SDL2 REQUIRED sdl2) pkg_check_modules(SDL2 REQUIRED sdl2)
pkg_check_modules(SLIRP REQUIRED slirp)
pkg_check_modules(LIBZIP REQUIRED libzip) pkg_check_modules(LIBZIP REQUIRED libzip)
if (WIN32 AND (CMAKE_BUILD_TYPE STREQUAL Release)) if (WIN32 AND (CMAKE_BUILD_TYPE STREQUAL Release))
@ -58,6 +60,7 @@ endif()
target_link_libraries(melonDS ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries(melonDS ${CMAKE_THREAD_LIBS_INIT})
target_include_directories(melonDS PRIVATE ${SDL2_INCLUDE_DIRS}) target_include_directories(melonDS PRIVATE ${SDL2_INCLUDE_DIRS})
target_include_directories(melonDS PRIVATE ${SLIRP_INCLUDE_DIRS})
target_include_directories(melonDS PRIVATE ${LIBZIP_INCLUDE_DIRS}) target_include_directories(melonDS PRIVATE ${LIBZIP_INCLUDE_DIRS})
target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..") target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..")
@ -65,9 +68,13 @@ target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../..")
target_link_libraries(melonDS core) target_link_libraries(melonDS core)
if (BUILD_STATIC) if (BUILD_STATIC)
target_link_libraries(melonDS -static ${SDL2_LIBRARIES} ${LIBZIP_STATIC_LIBRARIES}) target_link_libraries(melonDS -static ${SDL2_STATIC_LIBRARIES} ${SLIRP_STATIC_LIBRARIES} ${LIBZIP_STATIC_LIBRARIES})
else() else()
target_link_libraries(melonDS ${SDL2_LIBRARIES} ${LIBZIP_LIBRARIES}) target_link_libraries(melonDS ${SDL2_LIBRARIES} ${SLIRP_LIBRARIES} ${LIBZIP_LIBRARIES})
endif()
if (NOT Iconv_IS_BUILT_IN)
target_link_libraries(melonDS iconv)
endif() endif()
if (UNIX) if (UNIX)

View File

@ -98,6 +98,7 @@ void EmuSettingsDialog::verifyFirmware()
char filename[1024]; char filename[1024];
strncpy(filename, ui->txtFirmwarePath->text().toStdString().c_str(), 1023); filename[1023] = '\0'; strncpy(filename, ui->txtFirmwarePath->text().toStdString().c_str(), 1023); filename[1023] = '\0';
FILE* f = Platform::OpenLocalFile(filename, "rb"); FILE* f = Platform::OpenLocalFile(filename, "rb");
if (!f) return;
u8 chk1[0x180], chk2[0x180]; u8 chk1[0x180], chk2[0x180];
fseek(f, 0, SEEK_SET); fseek(f, 0, SEEK_SET);
@ -163,9 +164,9 @@ void EmuSettingsDialog::done(int r)
|| strcmp(Config::DSiNANDPath, dsiNANDPath.c_str()) != 0) || strcmp(Config::DSiNANDPath, dsiNANDPath.c_str()) != 0)
{ {
if (RunningSomething if (RunningSomething
&& QMessageBox::warning(this, "Reset necessary to apply changes", && QMessageBox::warning(this, "Reset necessary to apply changes",
"The emulation will be reset for the changes to take place", "The emulation will be reset for the changes to take place.",
QMessageBox::Yes, QMessageBox::Cancel) != QMessageBox::Yes) QMessageBox::Ok, QMessageBox::Cancel) != QMessageBox::Ok)
return; return;
strncpy(Config::BIOS9Path, bios9Path.c_str(), 1023); Config::BIOS9Path[1023] = '\0'; strncpy(Config::BIOS9Path, bios9Path.c_str(), 1023); Config::BIOS9Path[1023] = '\0';
@ -290,4 +291,4 @@ void EmuSettingsDialog::on_chkEnableJIT_toggled()
ui->chkJITLiteralOptimisations->setDisabled(disabled); ui->chkJITLiteralOptimisations->setDisabled(disabled);
ui->chkJITFastMemory->setDisabled(disabled); ui->chkJITFastMemory->setDisabled(disabled);
ui->spnJITMaximumBlockSize->setDisabled(disabled); ui->spnJITMaximumBlockSize->setDisabled(disabled);
} }

File diff suppressed because it is too large Load Diff

View File

@ -111,6 +111,7 @@ void Init(int argc, char** argv)
confdir = config.absolutePath() + "/melonDS/"; confdir = config.absolutePath() + "/melonDS/";
EmuDirectory = new char[confdir.length() + 1]; EmuDirectory = new char[confdir.length() + 1];
memcpy(EmuDirectory, confdir.toUtf8().data(), confdir.length()); memcpy(EmuDirectory, confdir.toUtf8().data(), confdir.length());
EmuDirectory[confdir.length()] = '\0';
#endif #endif
} }

View File

@ -259,6 +259,7 @@ EmuThread::EmuThread(QObject* parent) : QThread(parent)
{ {
EmuStatus = 0; EmuStatus = 0;
EmuRunning = 2; EmuRunning = 2;
EmuPause = 0;
RunningSomething = false; RunningSomething = false;
connect(this, SIGNAL(windowUpdate()), mainWindow->panel, SLOT(update())); connect(this, SIGNAL(windowUpdate()), mainWindow->panel, SLOT(update()));
@ -568,6 +569,7 @@ void EmuThread::changeWindowTitle(char* title)
void EmuThread::emuRun() void EmuThread::emuRun()
{ {
EmuRunning = 1; EmuRunning = 1;
EmuPause = 0;
RunningSomething = true; RunningSomething = true;
// checkme // checkme
@ -578,6 +580,9 @@ void EmuThread::emuRun()
void EmuThread::emuPause() void EmuThread::emuPause()
{ {
EmuPause++;
if (EmuPause > 1) return;
PrevEmuStatus = EmuRunning; PrevEmuStatus = EmuRunning;
EmuRunning = 2; EmuRunning = 2;
while (EmuStatus != 2); while (EmuStatus != 2);
@ -588,6 +593,11 @@ void EmuThread::emuPause()
void EmuThread::emuUnpause() void EmuThread::emuUnpause()
{ {
if (EmuPause < 1) return;
EmuPause--;
if (EmuPause > 0) return;
EmuRunning = PrevEmuStatus; EmuRunning = PrevEmuStatus;
if (audioDevice) SDL_PauseAudioDevice(audioDevice, 0); if (audioDevice) SDL_PauseAudioDevice(audioDevice, 0);
@ -597,6 +607,7 @@ void EmuThread::emuUnpause()
void EmuThread::emuStop() void EmuThread::emuStop()
{ {
EmuRunning = 0; EmuRunning = 0;
EmuPause = 0;
if (audioDevice) SDL_PauseAudioDevice(audioDevice, 1); if (audioDevice) SDL_PauseAudioDevice(audioDevice, 1);
if (micDevice) SDL_PauseAudioDevice(micDevice, 1); if (micDevice) SDL_PauseAudioDevice(micDevice, 1);
@ -1289,6 +1300,8 @@ void MainWindow::keyPressEvent(QKeyEvent* event)
{ {
if (event->isAutoRepeat()) return; if (event->isAutoRepeat()) return;
if (event->key() == Qt::Key_F11) NDS::debug(0);
Input::KeyPress(event); Input::KeyPress(event);
} }
@ -1694,11 +1707,10 @@ void MainWindow::onOpenEmuSettings()
void MainWindow::onEmuSettingsDialogFinished(int res) void MainWindow::onEmuSettingsDialogFinished(int res)
{ {
emuThread->emuUnpause();
if (EmuSettingsDialog::needsReset) if (EmuSettingsDialog::needsReset)
{
emuThread->emuUnpause();
onReset(); onReset();
}
} }
void MainWindow::onOpenInputConfig() void MainWindow::onOpenInputConfig()
@ -2128,12 +2140,12 @@ int CALLBACK WinMain(HINSTANCE hinst, HINSTANCE hprev, LPSTR cmdline, int cmdsho
if (argv_w) LocalFree(argv_w); if (argv_w) LocalFree(argv_w);
if (AttachConsole(ATTACH_PARENT_PROCESS)) /*if (AttachConsole(ATTACH_PARENT_PROCESS))
{ {
freopen("CONOUT$", "w", stdout); freopen("CONOUT$", "w", stdout);
freopen("CONOUT$", "w", stderr); freopen("CONOUT$", "w", stderr);
printf("\n"); printf("\n");
} }*/
int ret = main(argc, argv); int ret = main(argc, argv);

View File

@ -74,6 +74,7 @@ private:
volatile int EmuStatus; volatile int EmuStatus;
int PrevEmuStatus; int PrevEmuStatus;
int EmuRunning; int EmuRunning;
int EmuPause;
QOffscreenSurface* oglSurface; QOffscreenSurface* oglSurface;
QOpenGLContext* oglContext; QOpenGLContext* oglContext;