From 841122bc51156f3f1d351c47c8ac17af7a605e56 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Tue, 18 Jun 2019 21:12:39 +0200 Subject: prevent old DMA from being a shitshow. --- src/DMA.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'src/DMA.cpp') diff --git a/src/DMA.cpp b/src/DMA.cpp index 51ce825..2814264 100644 --- a/src/DMA.cpp +++ b/src/DMA.cpp @@ -18,6 +18,7 @@ #include #include "NDS.h" +#include "DSi.h" #include "DMA.h" #include "NDSCart.h" #include "GPU.h" @@ -232,7 +233,8 @@ void DMA::Run9() { NDS::ARM9Timestamp += (unitcycles << NDS::ARM9ClockShift); - NDS::ARM9Write16(CurDstAddr, NDS::ARM9Read16(CurSrcAddr)); + //NDS::ARM9Write16(CurDstAddr, NDS::ARM9Read16(CurSrcAddr)); + DSi::ARM9Write16(CurDstAddr, DSi::ARM9Read16(CurSrcAddr)); CurSrcAddr += SrcAddrInc<<1; CurDstAddr += DstAddrInc<<1; @@ -268,7 +270,8 @@ void DMA::Run9() { NDS::ARM9Timestamp += (unitcycles << NDS::ARM9ClockShift); - NDS::ARM9Write32(CurDstAddr, NDS::ARM9Read32(CurSrcAddr)); + //NDS::ARM9Write32(CurDstAddr, NDS::ARM9Read32(CurSrcAddr)); + DSi::ARM9Write32(CurDstAddr, DSi::ARM9Read32(CurSrcAddr)); CurSrcAddr += SrcAddrInc<<2; CurDstAddr += DstAddrInc<<2; @@ -344,7 +347,8 @@ void DMA::Run7() { NDS::ARM7Timestamp += unitcycles; - NDS::ARM7Write16(CurDstAddr, NDS::ARM7Read16(CurSrcAddr)); + //NDS::ARM7Write16(CurDstAddr, NDS::ARM7Read16(CurSrcAddr)); + DSi::ARM7Write16(CurDstAddr, DSi::ARM7Read16(CurSrcAddr)); CurSrcAddr += SrcAddrInc<<1; CurDstAddr += DstAddrInc<<1; @@ -380,7 +384,8 @@ void DMA::Run7() { NDS::ARM7Timestamp += unitcycles; - NDS::ARM7Write32(CurDstAddr, NDS::ARM7Read32(CurSrcAddr)); + //NDS::ARM7Write32(CurDstAddr, NDS::ARM7Read32(CurSrcAddr)); + DSi::ARM7Write32(CurDstAddr, DSi::ARM7Read32(CurSrcAddr)); CurSrcAddr += SrcAddrInc<<2; CurDstAddr += DstAddrInc<<2; -- cgit v1.2.3 From d6bbc6f0f1ede57f0805137617ba670a49f7506f Mon Sep 17 00:00:00 2001 From: Arisotura Date: Tue, 18 Jun 2019 22:54:07 +0200 Subject: tremble upon the NDMA implementation that doesn't do much beyond getting stuck --- src/DMA.cpp | 6 -- src/DSi.cpp | 171 +++++++++++++++++++++++++++++++ src/DSi.h | 4 + src/DSi_NDMA.cpp | 301 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/DSi_NDMA.h | 74 +++++++++++++- src/NDS.cpp | 4 + src/NDS.h | 5 +- 7 files changed, 556 insertions(+), 9 deletions(-) (limited to 'src/DMA.cpp') diff --git a/src/DMA.cpp b/src/DMA.cpp index 2814264..0826d7a 100644 --- a/src/DMA.cpp +++ b/src/DMA.cpp @@ -20,15 +20,9 @@ #include "NDS.h" #include "DSi.h" #include "DMA.h" -#include "NDSCart.h" #include "GPU.h" -// NOTES ON DMA SHIT -// -// * could use optimized code paths for common types of DMA transfers. for example, VRAM -// have to profile it to see if it's actually worth doing - // DMA TIMINGS // diff --git a/src/DSi.cpp b/src/DSi.cpp index abd3bd6..0c9c26c 100644 --- a/src/DSi.cpp +++ b/src/DSi.cpp @@ -25,6 +25,7 @@ #include "sha1/sha1.h" #include "Platform.h" +#include "DSi_NDMA.h" #include "DSi_I2C.h" #include "DSi_SD.h" @@ -57,6 +58,9 @@ u32 NWRAMStart[2][3]; u32 NWRAMEnd[2][3]; u32 NWRAMMask[2][3]; +u32 NDMACnt[2]; +DSi_NDMA* NDMAs[8]; + DSi_SDHost* SDMMC; DSi_SDHost* SDIO; @@ -68,6 +72,15 @@ bool Init() { if (!DSi_I2C::Init()) return false; + NDMAs[0] = new DSi_NDMA(0, 0); + NDMAs[1] = new DSi_NDMA(0, 1); + NDMAs[2] = new DSi_NDMA(0, 2); + NDMAs[3] = new DSi_NDMA(0, 3); + NDMAs[4] = new DSi_NDMA(1, 0); + NDMAs[5] = new DSi_NDMA(1, 1); + NDMAs[6] = new DSi_NDMA(1, 2); + NDMAs[7] = new DSi_NDMA(1, 3); + SDMMC = new DSi_SDHost(0); SDIO = new DSi_SDHost(1); @@ -78,6 +91,8 @@ void DeInit() { DSi_I2C::DeInit(); + for (int i = 0; i < 8; i++) delete NDMAs[i]; + delete SDMMC; delete SDIO; } @@ -91,6 +106,9 @@ void Reset() NDS::ARM9->JumpTo(BootAddr[0]); NDS::ARM7->JumpTo(BootAddr[1]); + NDMACnt[0] = 0; NDMACnt[1] = 0; + for (int i = 0; i < 8; i++) NDMAs[i]->Reset(); + DSi_I2C::Reset(); SDMMC->Reset(); @@ -279,6 +297,40 @@ bool LoadNAND() } +void RunNDMAs(u32 cpu) +{ + // TODO: round-robin mode (requires DMA channels to have a subblock delay set) + + if (cpu == 0) + { + if (NDS::ARM9Timestamp >= NDS::ARM9Target) return; + + // + } + else + { + if (NDS::ARM7Timestamp >= NDS::ARM7Target) return; + + // + } +} + +void StallNDMAs() +{ + // TODO +} + +bool NDMAsRunning(u32 cpu) +{ + cpu <<= 2; + if (NDMAs[cpu+0]->IsRunning()) return true; + if (NDMAs[cpu+1]->IsRunning()) return true; + if (NDMAs[cpu+2]->IsRunning()) return true; + if (NDMAs[cpu+3]->IsRunning()) return true; + return false; +} + + // new WRAM mapping // TODO: find out what happens upon overlapping slots!! @@ -872,6 +924,36 @@ u32 ARM9IORead32(u32 addr) switch (addr) { case 0x04004010: return 1; // todo + + case 0x04004100: return NDMACnt[0]; + case 0x04004104: return NDMAs[0]->SrcAddr; + case 0x04004108: return NDMAs[0]->DstAddr; + case 0x0400410C: return NDMAs[0]->TotalLength; + case 0x04004110: return NDMAs[0]->BlockLength; + case 0x04004114: return NDMAs[0]->SubblockTimer; + case 0x04004118: return NDMAs[0]->FillData; + case 0x0400411C: return NDMAs[0]->Cnt; + case 0x04004120: return NDMAs[1]->SrcAddr; + case 0x04004124: return NDMAs[1]->DstAddr; + case 0x04004128: return NDMAs[1]->TotalLength; + case 0x0400412C: return NDMAs[1]->BlockLength; + case 0x04004130: return NDMAs[1]->SubblockTimer; + case 0x04004134: return NDMAs[1]->FillData; + case 0x04004138: return NDMAs[1]->Cnt; + case 0x0400413C: return NDMAs[2]->SrcAddr; + case 0x04004140: return NDMAs[2]->DstAddr; + case 0x04004144: return NDMAs[2]->TotalLength; + case 0x04004148: return NDMAs[2]->BlockLength; + case 0x0400414C: return NDMAs[2]->SubblockTimer; + case 0x04004150: return NDMAs[2]->FillData; + case 0x04004154: return NDMAs[2]->Cnt; + case 0x04004158: return NDMAs[3]->SrcAddr; + case 0x0400415C: return NDMAs[3]->DstAddr; + case 0x04004160: return NDMAs[3]->TotalLength; + case 0x04004164: return NDMAs[3]->BlockLength; + case 0x04004168: return NDMAs[3]->SubblockTimer; + case 0x0400416C: return NDMAs[3]->FillData; + case 0x04004170: return NDMAs[3]->Cnt; } return NDS::ARM9IORead32(addr); @@ -899,6 +981,35 @@ void ARM9IOWrite32(u32 addr, u32 val) { switch (addr) { + case 0x04004100: NDMACnt[0] = val & 0x800F0000; return; + case 0x04004104: NDMAs[0]->SrcAddr = val & 0xFFFFFFFC; return; + case 0x04004108: NDMAs[0]->DstAddr = val & 0xFFFFFFFC; return; + case 0x0400410C: NDMAs[0]->TotalLength = val & 0x0FFFFFFF; return; + case 0x04004110: NDMAs[0]->BlockLength = val & 0x00FFFFFF; return; + case 0x04004114: NDMAs[0]->SubblockTimer = val & 0x0003FFFF; return; + case 0x04004118: NDMAs[0]->FillData = val; return; + case 0x0400411C: NDMAs[0]->WriteCnt(val); return; + case 0x04004120: NDMAs[1]->SrcAddr = val & 0xFFFFFFFC; return; + case 0x04004124: NDMAs[1]->DstAddr = val & 0xFFFFFFFC; return; + case 0x04004128: NDMAs[1]->TotalLength = val & 0x0FFFFFFF; return; + case 0x0400412C: NDMAs[1]->BlockLength = val & 0x00FFFFFF; return; + case 0x04004130: NDMAs[1]->SubblockTimer = val & 0x0003FFFF; return; + case 0x04004134: NDMAs[1]->FillData = val; return; + case 0x04004138: NDMAs[1]->WriteCnt(val); return; + case 0x0400413C: NDMAs[2]->SrcAddr = val & 0xFFFFFFFC; return; + case 0x04004140: NDMAs[2]->DstAddr = val & 0xFFFFFFFC; return; + case 0x04004144: NDMAs[2]->TotalLength = val & 0x0FFFFFFF; return; + case 0x04004148: NDMAs[2]->BlockLength = val & 0x00FFFFFF; return; + case 0x0400414C: NDMAs[2]->SubblockTimer = val & 0x0003FFFF; return; + case 0x04004150: NDMAs[2]->FillData = val; return; + case 0x04004154: NDMAs[2]->WriteCnt(val); return; + case 0x04004158: NDMAs[3]->SrcAddr = val & 0xFFFFFFFC; return; + case 0x0400415C: NDMAs[3]->DstAddr = val & 0xFFFFFFFC; return; + case 0x04004160: NDMAs[3]->TotalLength = val & 0x0FFFFFFF; return; + case 0x04004164: NDMAs[3]->BlockLength = val & 0x00FFFFFF; return; + case 0x04004168: NDMAs[3]->SubblockTimer = val & 0x0003FFFF; return; + case 0x0400416C: NDMAs[3]->FillData = val; return; + case 0x04004170: NDMAs[3]->WriteCnt(val); return; } return NDS::ARM9IOWrite32(addr, val); @@ -950,6 +1061,36 @@ u32 ARM7IORead32(u32 addr) case 0x0400021C: return NDS::IF2; case 0x04004008: return 0x80000000; // HAX + + case 0x04004100: return NDMACnt[1]; + case 0x04004104: return NDMAs[4]->SrcAddr; + case 0x04004108: return NDMAs[4]->DstAddr; + case 0x0400410C: return NDMAs[4]->TotalLength; + case 0x04004110: return NDMAs[4]->BlockLength; + case 0x04004114: return NDMAs[4]->SubblockTimer; + case 0x04004118: return NDMAs[4]->FillData; + case 0x0400411C: return NDMAs[4]->Cnt; + case 0x04004120: return NDMAs[5]->SrcAddr; + case 0x04004124: return NDMAs[5]->DstAddr; + case 0x04004128: return NDMAs[5]->TotalLength; + case 0x0400412C: return NDMAs[5]->BlockLength; + case 0x04004130: return NDMAs[5]->SubblockTimer; + case 0x04004134: return NDMAs[5]->FillData; + case 0x04004138: return NDMAs[5]->Cnt; + case 0x0400413C: return NDMAs[6]->SrcAddr; + case 0x04004140: return NDMAs[6]->DstAddr; + case 0x04004144: return NDMAs[6]->TotalLength; + case 0x04004148: return NDMAs[6]->BlockLength; + case 0x0400414C: return NDMAs[6]->SubblockTimer; + case 0x04004150: return NDMAs[6]->FillData; + case 0x04004154: return NDMAs[6]->Cnt; + case 0x04004158: return NDMAs[7]->SrcAddr; + case 0x0400415C: return NDMAs[7]->DstAddr; + case 0x04004160: return NDMAs[7]->TotalLength; + case 0x04004164: return NDMAs[7]->BlockLength; + case 0x04004168: return NDMAs[7]->SubblockTimer; + case 0x0400416C: return NDMAs[7]->FillData; + case 0x04004170: return NDMAs[7]->Cnt; } if (addr >= 0x04004800 && addr < 0x04004A00) @@ -1003,6 +1144,36 @@ void ARM7IOWrite32(u32 addr, u32 val) { case 0x04000218: NDS::IE2 = (val & 0x7FF7); NDS::UpdateIRQ(1); return; case 0x0400021C: NDS::IF2 &= ~(val & 0x7FF7); NDS::UpdateIRQ(1); return; + + case 0x04004100: NDMACnt[1] = val & 0x800F0000; return; + case 0x04004104: NDMAs[4]->SrcAddr = val & 0xFFFFFFFC; return; + case 0x04004108: NDMAs[4]->DstAddr = val & 0xFFFFFFFC; return; + case 0x0400410C: NDMAs[4]->TotalLength = val & 0x0FFFFFFF; return; + case 0x04004110: NDMAs[4]->BlockLength = val & 0x00FFFFFF; return; + case 0x04004114: NDMAs[4]->SubblockTimer = val & 0x0003FFFF; return; + case 0x04004118: NDMAs[4]->FillData = val; return; + case 0x0400411C: NDMAs[4]->WriteCnt(val); return; + case 0x04004120: NDMAs[5]->SrcAddr = val & 0xFFFFFFFC; return; + case 0x04004124: NDMAs[5]->DstAddr = val & 0xFFFFFFFC; return; + case 0x04004128: NDMAs[5]->TotalLength = val & 0x0FFFFFFF; return; + case 0x0400412C: NDMAs[5]->BlockLength = val & 0x00FFFFFF; return; + case 0x04004130: NDMAs[5]->SubblockTimer = val & 0x0003FFFF; return; + case 0x04004134: NDMAs[5]->FillData = val; return; + case 0x04004138: NDMAs[5]->WriteCnt(val); return; + case 0x0400413C: NDMAs[6]->SrcAddr = val & 0xFFFFFFFC; return; + case 0x04004140: NDMAs[6]->DstAddr = val & 0xFFFFFFFC; return; + case 0x04004144: NDMAs[6]->TotalLength = val & 0x0FFFFFFF; return; + case 0x04004148: NDMAs[6]->BlockLength = val & 0x00FFFFFF; return; + case 0x0400414C: NDMAs[6]->SubblockTimer = val & 0x0003FFFF; return; + case 0x04004150: NDMAs[6]->FillData = val; return; + case 0x04004154: NDMAs[6]->WriteCnt(val); return; + case 0x04004158: NDMAs[7]->SrcAddr = val & 0xFFFFFFFC; return; + case 0x0400415C: NDMAs[7]->DstAddr = val & 0xFFFFFFFC; return; + case 0x04004160: NDMAs[7]->TotalLength = val & 0x0FFFFFFF; return; + case 0x04004164: NDMAs[7]->BlockLength = val & 0x00FFFFFF; return; + case 0x04004168: NDMAs[7]->SubblockTimer = val & 0x0003FFFF; return; + case 0x0400416C: NDMAs[7]->FillData = val; return; + case 0x04004170: NDMAs[7]->WriteCnt(val); return; } if (addr >= 0x04004800 && addr < 0x04004A00) diff --git a/src/DSi.h b/src/DSi.h index efd533a..32253a7 100644 --- a/src/DSi.h +++ b/src/DSi.h @@ -38,6 +38,10 @@ void Reset(); bool LoadBIOS(); bool LoadNAND(); +void RunNDMAs(u32 cpu); +void StallNDMAs(); +bool NDMAsRunning(u32 cpu); + void MapNWRAM_A(u32 num, u8 val); void MapNWRAM_B(u32 num, u8 val); void MapNWRAM_C(u32 num, u8 val); diff --git a/src/DSi_NDMA.cpp b/src/DSi_NDMA.cpp index 6a524dd..a8055eb 100644 --- a/src/DSi_NDMA.cpp +++ b/src/DSi_NDMA.cpp @@ -15,3 +15,304 @@ You should have received a copy of the GNU General Public License along with melonDS. If not, see http://www.gnu.org/licenses/. */ + +#include +#include "NDS.h" +#include "DSi.h" +#include "DSi_NDMA.h" +#include "GPU.h" + + + +DSi_NDMA::DSi_NDMA(u32 cpu, u32 num) +{ + CPU = cpu; + Num = num; + + Reset(); +} + +DSi_NDMA::~DSi_NDMA() +{ +} + +void DSi_NDMA::Reset() +{ + SrcAddr = 0; + DstAddr = 0; + TotalLength = 0; + BlockLength = 0; + SubblockTimer = 0; + FillData = 0; + Cnt = 0; + + StartMode = 0; + CurSrcAddr = 0; + CurDstAddr = 0; + SubblockLength = 0; + RemCount = 0; + IterCount = 0; + TotalRemCount = 0; + SrcAddrInc = 0; + DstAddrInc = 0; + + Running = false; + InProgress = false; +} + +void DSi_NDMA::DoSavestate(Savestate* file) +{ + // TODO! +} + +void DSi_NDMA::WriteCnt(u32 val) +{ + u32 oldcnt = Cnt; + Cnt = val; + + if ((!(oldcnt & 0x80000000)) && (val & 0x80000000)) // checkme + { + CurSrcAddr = SrcAddr; + CurDstAddr = DstAddr; + TotalRemCount = TotalLength; + + switch ((Cnt >> 10) & 0x3) + { + case 0: DstAddrInc = 1; break; + case 1: DstAddrInc = -1; break; + case 2: DstAddrInc = 0; break; + case 3: DstAddrInc = 1; printf("BAD NDMA DST INC MODE 3\n"); break; + } + + switch ((Cnt >> 13) & 0x3) + { + case 0: SrcAddrInc = 1; break; + case 1: SrcAddrInc = -1; break; + case 2: SrcAddrInc = 0; break; + case 3: SrcAddrInc = 0; break; // fill mode + } + + StartMode = (Cnt >> 24) & 0x1F; + if (StartMode > 0x10) StartMode = 0x10; + if (CPU == 1) StartMode |= 0x20; + + if ((StartMode & 0x1F) == 0x10) + Start(); + + if (StartMode != 0x10 && StartMode != 0x30) + printf("UNIMPLEMENTED ARM%d NDMA%d START MODE %02X, %08X->%08X\n", CPU?7:9, Num, StartMode, SrcAddr, DstAddr); + } +} + +void DSi_NDMA::Start() +{ + if (Running) return; + + if (!InProgress) + { + RemCount = BlockLength; + if (!RemCount) + RemCount = 0x1000000; + } + + // TODO: how does GXFIFO DMA work with all the block shito? + IterCount = RemCount; + + if (IterCount > TotalRemCount) + IterCount = TotalRemCount; + + if (Cnt & (1<<12)) CurDstAddr = DstAddr; + if (Cnt & (1<<15)) CurSrcAddr = SrcAddr; + + printf("ARM%d NDMA%d %08X %02X %08X->%08X %d bytes\n", CPU?7:9, Num, Cnt, StartMode, CurSrcAddr, CurDstAddr, RemCount*4); + + //IsGXFIFODMA = (CPU == 0 && (CurSrcAddr>>24) == 0x02 && CurDstAddr == 0x04000400 && DstAddrInc == 0); + + // TODO eventually: not stop if we're running code in ITCM + + if (SubblockTimer & 0xFFFF) + printf("TODO! NDMA SUBBLOCK TIMER: %08X\n", SubblockTimer); + + if (NDS::DMAsRunning(CPU)) + Running = 1; + else + Running = 2; + + InProgress = true; + NDS::StopCPU(CPU, 1<<(Num+4)); +} + +void DSi_NDMA::Run() +{ + if (!Running) return; + if (CPU == 0) return Run9(); + else return Run7(); +} + +void DSi_NDMA::Run9() +{ + if (NDS::ARM9Timestamp >= NDS::ARM9Target) return; + + Executing = true; + + // add NS penalty for first accesses in burst + bool burststart = (Running == 2); + Running = 1; + + s32 unitcycles; + //s32 lastcycles = cycles; + + bool dofill = ((Cnt >> 13) & 0x3) == 3; + + if ((CurSrcAddr >> 24) == 0x02 && (CurDstAddr >> 24) == 0x02) + { + unitcycles = NDS::ARM9MemTimings[CurSrcAddr >> 14][2] + NDS::ARM9MemTimings[CurDstAddr >> 14][2]; + } + else + { + unitcycles = NDS::ARM9MemTimings[CurSrcAddr >> 14][3] + NDS::ARM9MemTimings[CurDstAddr >> 14][3]; + if ((CurSrcAddr >> 24) == (CurDstAddr >> 24)) + unitcycles++; + else if ((CurSrcAddr >> 24) == 0x02) + unitcycles--; + + /*if (burststart) + { + cycles -= 2; + cycles -= (NDS::ARM9MemTimings[CurSrcAddr >> 14][2] + NDS::ARM9MemTimings[CurDstAddr >> 14][2]); + cycles += unitcycles; + }*/ + } + + while (IterCount > 0 && !Stall) + { + NDS::ARM9Timestamp += (unitcycles << NDS::ARM9ClockShift); + + if (dofill) + DSi::ARM9Write32(CurDstAddr, FillData); + else + DSi::ARM9Write32(CurDstAddr, DSi::ARM9Read32(CurSrcAddr)); + + CurSrcAddr += SrcAddrInc<<2; + CurDstAddr += DstAddrInc<<2; + IterCount--; + RemCount--; + TotalRemCount--; + + if (NDS::ARM9Timestamp >= NDS::ARM9Target) break; + } + + Executing = false; + Stall = false; + + if (RemCount) + { + if (IterCount == 0) + { + Running = 0; + NDS::ResumeCPU(0, 1<<(Num+4)); + + //if (StartMode == 0x07) + // GPU3D::CheckFIFODMA(); + } + + return; + } + + if ((StartMode & 0x1F) == 0x10) // CHECKME + Cnt &= ~(1<<31); + else if (!(Cnt & (1<<29))) + { + if (TotalRemCount == 0) + Cnt &= ~(1<<31); + } + + if (Cnt & (1<<30)) + NDS::SetIRQ(0, NDS::IRQ_DSi_NDMA0 + Num); + + Running = 0; + InProgress = false; + NDS::ResumeCPU(0, 1<<(Num+4)); +} + +void DSi_NDMA::Run7() +{ + if (NDS::ARM7Timestamp >= NDS::ARM7Target) return; + + Executing = true; + + // add NS penalty for first accesses in burst + bool burststart = (Running == 2); + Running = 1; + + s32 unitcycles; + //s32 lastcycles = cycles; + + bool dofill = ((Cnt >> 13) & 0x3) == 3; + + if ((CurSrcAddr >> 24) == 0x02 && (CurDstAddr >> 24) == 0x02) + { + unitcycles = NDS::ARM7MemTimings[CurSrcAddr >> 15][2] + NDS::ARM7MemTimings[CurDstAddr >> 15][2]; + } + else + { + unitcycles = NDS::ARM7MemTimings[CurSrcAddr >> 15][3] + NDS::ARM7MemTimings[CurDstAddr >> 15][3]; + if ((CurSrcAddr >> 23) == (CurDstAddr >> 23)) + unitcycles++; + else if ((CurSrcAddr >> 24) == 0x02) + unitcycles--; + + /*if (burststart) + { + cycles -= 2; + cycles -= (NDS::ARM7MemTimings[CurSrcAddr >> 15][2] + NDS::ARM7MemTimings[CurDstAddr >> 15][2]); + cycles += unitcycles; + }*/ + } + + while (IterCount > 0 && !Stall) + { + NDS::ARM7Timestamp += unitcycles; + + if (dofill) + DSi::ARM7Write32(CurDstAddr, FillData); + else + DSi::ARM7Write32(CurDstAddr, DSi::ARM7Read32(CurSrcAddr)); + + CurSrcAddr += SrcAddrInc<<2; + CurDstAddr += DstAddrInc<<2; + IterCount--; + RemCount--; + + if (NDS::ARM7Timestamp >= NDS::ARM7Target) break; + } + + Executing = false; + Stall = false; + + if (RemCount) + { + if (IterCount == 0) + { + Running = 0; + NDS::ResumeCPU(1, 1<<(Num+4)); + } + + return; + } + + if ((StartMode & 0x1F) == 0x10) // CHECKME + Cnt &= ~(1<<31); + else if (!(Cnt & (1<<29))) + { + if (TotalRemCount == 0) + Cnt &= ~(1<<31); + } + + if (Cnt & (1<<30)) + NDS::SetIRQ(1, NDS::IRQ_DSi_NDMA0 + Num); + + Running = 0; + InProgress = false; + NDS::ResumeCPU(1, 1<<(Num+4)); +} diff --git a/src/DSi_NDMA.h b/src/DSi_NDMA.h index 6661652..d7b7483 100644 --- a/src/DSi_NDMA.h +++ b/src/DSi_NDMA.h @@ -19,6 +19,78 @@ #ifndef DSI_NDMA_H #define DSI_NDMA_H -// +#include "types.h" + +class DSi_NDMA +{ +public: + DSi_NDMA(u32 cpu, u32 num); + ~DSi_NDMA(); + + void Reset(); + + void DoSavestate(Savestate* file); + + void WriteCnt(u32 val); + void Start(); + + void Run(); + + void Run9(); + void Run7(); + + bool IsInMode(u32 mode) + { + return ((mode == StartMode) && (Cnt & 0x80000000)); + } + + bool IsRunning() { return Running!=0; } + + void StartIfNeeded(u32 mode) + { + if ((mode == StartMode) && (Cnt & 0x80000000)) + Start(); + } + + void StopIfNeeded(u32 mode) + { + if (mode == StartMode) + Cnt &= ~0x80000000; + } + + void StallIfRunning() + { + if (Executing) Stall = true; + } + + u32 SrcAddr; + u32 DstAddr; + u32 TotalLength; // total length, when transferring multiple blocks + u32 BlockLength; // length of one transfer + u32 SubblockTimer; // optional delay between subblocks (only in round-robin mode) + u32 FillData; + u32 Cnt; + +private: + u32 CPU, Num; + + u32 StartMode; + u32 CurSrcAddr; + u32 CurDstAddr; + u32 SubblockLength; // length transferred per run when delay is used + u32 RemCount; + u32 IterCount; + u32 TotalRemCount; + u32 SrcAddrInc; + u32 DstAddrInc; + + u32 Running; + bool InProgress; + + bool Executing; + bool Stall; + + bool IsGXFIFODMA; +}; #endif // DSI_NDMA_H diff --git a/src/NDS.cpp b/src/NDS.cpp index 414f87c..e20f62f 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -827,6 +827,7 @@ u32 RunFrame() if (!(CPUStop & 0x80000000)) DMAs[1]->Run(); if (!(CPUStop & 0x80000000)) DMAs[2]->Run(); if (!(CPUStop & 0x80000000)) DMAs[3]->Run(); + DSi::RunNDMAs(0); } else { @@ -849,6 +850,7 @@ u32 RunFrame() DMAs[5]->Run(); DMAs[6]->Run(); DMAs[7]->Run(); + DSi::RunNDMAs(1); } else { @@ -1153,6 +1155,7 @@ void GXFIFOStall() DMAs[1]->StallIfRunning(); DMAs[2]->StallIfRunning(); DMAs[3]->StallIfRunning(); + DSi::StallNDMAs(); } } @@ -1367,6 +1370,7 @@ bool DMAsRunning(u32 cpu) if (DMAs[cpu+1]->IsRunning()) return true; if (DMAs[cpu+2]->IsRunning()) return true; if (DMAs[cpu+3]->IsRunning()) return true; + if (DSi::NDMAsRunning(cpu>>2)) return true; return false; } diff --git a/src/NDS.h b/src/NDS.h index f87ffed..850e829 100644 --- a/src/NDS.h +++ b/src/NDS.h @@ -101,7 +101,7 @@ enum IRQ2_DSi_GPIO18_0 = 0, IRQ2_DSi_GPIO18_1, IRQ2_DSi_GPIO18_2, - IRQ2_DSi_Unused35, + IRQ2_DSi_Unused3, IRQ2_DSi_GPIO33_0, IRQ2_DSi_Headphone, IRQ2_DSi_PowerButton, @@ -138,7 +138,6 @@ extern u64 ARM9Timestamp, ARM9Target; extern u64 ARM7Timestamp, ARM7Target; extern u32 ARM9ClockShift; -// hax extern u32 IME[2]; extern u32 IE[2]; extern u32 IF[2]; @@ -146,6 +145,8 @@ extern u32 IE2; extern u32 IF2; extern Timer Timers[8]; +extern u32 CPUStop; + extern u16 PowerControl9; extern u16 ExMemCnt[2]; -- cgit v1.2.3 From 43e045357f7d74eecff61b0c8af8068b31e963b3 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Mon, 1 Jun 2020 20:36:30 +0200 Subject: make it able to switch between DS and DSi modes --- src/ARM.cpp | 46 +++++++++ src/ARM.h | 43 ++++---- src/CP15.cpp | 30 ++---- src/DMA.cpp | 29 ++++-- src/DMA.h | 5 + src/DSi.cpp | 7 +- src/NDS.cpp | 54 +++++++--- src/NDS.h | 5 + src/NDSCart.cpp | 15 ++- src/SPI.cpp | 32 ++++-- src/SPU.cpp | 16 ++- src/SPU.h | 6 ++ src/frontend/FrontendUtil.h | 9 ++ src/frontend/Util_ROM.cpp | 163 +++++++++++++++++++++++++++--- src/frontend/qt_sdl/EmuSettingsDialog.cpp | 2 +- src/frontend/qt_sdl/main.cpp | 45 +++++++-- 16 files changed, 396 insertions(+), 111 deletions(-) (limited to 'src/DMA.cpp') diff --git a/src/ARM.cpp b/src/ARM.cpp index 2d8c807..68cac59 100644 --- a/src/ARM.cpp +++ b/src/ARM.cpp @@ -18,6 +18,7 @@ #include #include "NDS.h" +#include "DSi.h" #include "ARM.h" #include "ARMInterpreter.h" #include "AREngine.h" @@ -101,10 +102,55 @@ void ARM::Reset() void ARMv5::Reset() { + if (NDS::ConsoleType == 1) + { + BusRead8 = DSi::ARM9Read8; + BusRead16 = DSi::ARM9Read16; + BusRead32 = DSi::ARM9Read32; + BusWrite8 = DSi::ARM9Write8; + BusWrite16 = DSi::ARM9Write16; + BusWrite32 = DSi::ARM9Write32; + GetMemRegion = DSi::ARM9GetMemRegion; + } + else + { + BusRead8 = NDS::ARM9Read8; + BusRead16 = NDS::ARM9Read16; + BusRead32 = NDS::ARM9Read32; + BusWrite8 = NDS::ARM9Write8; + BusWrite16 = NDS::ARM9Write16; + BusWrite32 = NDS::ARM9Write32; + GetMemRegion = NDS::ARM9GetMemRegion; + } + CP15Reset(); ARM::Reset(); } +void ARMv4::Reset() +{ + if (NDS::ConsoleType) + { + BusRead8 = DSi::ARM7Read8; + BusRead16 = DSi::ARM7Read16; + BusRead32 = DSi::ARM7Read32; + BusWrite8 = DSi::ARM7Write8; + BusWrite16 = DSi::ARM7Write16; + BusWrite32 = DSi::ARM7Write32; + } + else + { + BusRead8 = NDS::ARM7Read8; + BusRead16 = NDS::ARM7Read16; + BusRead32 = NDS::ARM7Read32; + BusWrite8 = NDS::ARM7Write8; + BusWrite16 = NDS::ARM7Write16; + BusWrite32 = NDS::ARM7Write32; + } + + ARM::Reset(); +} + void ARM::DoSavestate(Savestate* file) { diff --git a/src/ARM.h b/src/ARM.h index 95c41d4..e0832e2 100644 --- a/src/ARM.h +++ b/src/ARM.h @@ -23,7 +23,6 @@ #include "types.h" #include "NDS.h" -#include "DSi.h" #define ROR(x, n) (((x) >> (n)) | ((x) << (32-(n)))) @@ -133,6 +132,14 @@ public: NDS::MemRegion CodeMem; static u32 ConditionTable[16]; + +protected: + u8 (*BusRead8)(u32 addr); + u16 (*BusRead16)(u32 addr); + u32 (*BusRead32)(u32 addr); + void (*BusWrite8)(u32 addr, u8 val); + void (*BusWrite16)(u32 addr, u16 val); + void (*BusWrite32)(u32 addr, u32 val); }; class ARMv5 : public ARM @@ -260,6 +267,8 @@ public: s32 RegionCodeCycles; u8* CurICacheLine; + + bool (*GetMemRegion)(u32 addr, bool write, NDS::MemRegion* region); }; class ARMv4 : public ARM @@ -267,26 +276,25 @@ class ARMv4 : public ARM public: ARMv4(); + void Reset(); + void JumpTo(u32 addr, bool restorecpsr = false); void Execute(); u16 CodeRead16(u32 addr) { - //return NDS::ARM7Read16(addr); - return DSi::ARM7Read16(addr); + return BusRead16(addr); } u32 CodeRead32(u32 addr) { - //return NDS::ARM7Read32(addr); - return DSi::ARM7Read32(addr); + return BusRead32(addr); } void DataRead8(u32 addr, u32* val) { - *val = DSi::ARM7Read8(addr); - //*val = NDS::ARM7Read8(addr); + *val = BusRead8(addr); DataRegion = addr >> 24; DataCycles = NDS::ARM7MemTimings[DataRegion][0]; } @@ -295,8 +303,7 @@ public: { addr &= ~1; - *val = DSi::ARM7Read16(addr); - //*val = NDS::ARM7Read16(addr); + *val = BusRead16(addr); DataRegion = addr >> 24; DataCycles = NDS::ARM7MemTimings[DataRegion][0]; } @@ -305,8 +312,7 @@ public: { addr &= ~3; - *val = DSi::ARM7Read32(addr); - //*val = NDS::ARM7Read32(addr); + *val = BusRead32(addr); DataRegion = addr >> 24; DataCycles = NDS::ARM7MemTimings[DataRegion][2]; } @@ -315,15 +321,13 @@ public: { addr &= ~3; - *val = DSi::ARM7Read32(addr); - //*val = NDS::ARM7Read32(addr); + *val = BusRead32(addr); DataCycles += NDS::ARM7MemTimings[DataRegion][3]; } void DataWrite8(u32 addr, u8 val) { - DSi::ARM7Write8(addr, val); - //NDS::ARM7Write8(addr, val); + BusWrite8(addr, val); DataRegion = addr >> 24; DataCycles = NDS::ARM7MemTimings[DataRegion][0]; } @@ -332,8 +336,7 @@ public: { addr &= ~1; - DSi::ARM7Write16(addr, val); - //NDS::ARM7Write16(addr, val); + BusWrite16(addr, val); DataRegion = addr >> 24; DataCycles = NDS::ARM7MemTimings[DataRegion][0]; } @@ -342,8 +345,7 @@ public: { addr &= ~3; - DSi::ARM7Write32(addr, val); - //NDS::ARM7Write32(addr, val); + BusWrite32(addr, val); DataRegion = addr >> 24; DataCycles = NDS::ARM7MemTimings[DataRegion][2]; } @@ -352,8 +354,7 @@ public: { addr &= ~3; - DSi::ARM7Write32(addr, val); - //NDS::ARM7Write32(addr, val); + BusWrite32(addr, val); DataCycles += NDS::ARM7MemTimings[DataRegion][3]; } diff --git a/src/CP15.cpp b/src/CP15.cpp index b61cc45..d340b9e 100644 --- a/src/CP15.cpp +++ b/src/CP15.cpp @@ -720,8 +720,7 @@ u32 ARMv5::CodeRead32(u32 addr, bool branch) if (CodeMem.Mem) return *(u32*)&CodeMem.Mem[addr & CodeMem.Mask]; - //return NDS::ARM9Read32(addr); - return DSi::ARM9Read32(addr); + return BusRead32(addr); } @@ -740,8 +739,7 @@ void ARMv5::DataRead8(u32 addr, u32* val) return; } - *val = DSi::ARM9Read8(addr); - //*val = NDS::ARM9Read8(addr); + *val = BusRead8(addr); DataCycles = MemTimings[addr >> 12][1]; } @@ -762,8 +760,7 @@ void ARMv5::DataRead16(u32 addr, u32* val) return; } - *val = DSi::ARM9Read16(addr); - //*val = NDS::ARM9Read16(addr); + *val = BusRead16(addr); DataCycles = MemTimings[addr >> 12][1]; } @@ -784,8 +781,7 @@ void ARMv5::DataRead32(u32 addr, u32* val) return; } - *val = DSi::ARM9Read32(addr); - //*val = NDS::ARM9Read32(addr); + *val = BusRead32(addr); DataCycles = MemTimings[addr >> 12][2]; } @@ -806,8 +802,7 @@ void ARMv5::DataRead32S(u32 addr, u32* val) return; } - *val = DSi::ARM9Read32(addr); - //*val = NDS::ARM9Read32(addr); + *val = BusRead32(addr); DataCycles += MemTimings[addr >> 12][3]; } @@ -826,8 +821,7 @@ void ARMv5::DataWrite8(u32 addr, u8 val) return; } - DSi::ARM9Write8(addr, val); - //NDS::ARM9Write8(addr, val); + BusWrite8(addr, val); DataCycles = MemTimings[addr >> 12][1]; } @@ -848,8 +842,7 @@ void ARMv5::DataWrite16(u32 addr, u16 val) return; } - DSi::ARM9Write16(addr, val); - //NDS::ARM9Write16(addr, val); + BusWrite16(addr, val); DataCycles = MemTimings[addr >> 12][1]; } @@ -870,8 +863,7 @@ void ARMv5::DataWrite32(u32 addr, u32 val) return; } - DSi::ARM9Write32(addr, val); - //NDS::ARM9Write32(addr, val); + BusWrite32(addr, val); DataCycles = MemTimings[addr >> 12][2]; } @@ -892,8 +884,7 @@ void ARMv5::DataWrite32S(u32 addr, u32 val) return; } - DSi::ARM9Write32(addr, val); - //NDS::ARM9Write32(addr, val); + BusWrite32(addr, val); DataCycles += MemTimings[addr >> 12][3]; } @@ -906,7 +897,6 @@ void ARMv5::GetCodeMemRegion(u32 addr, NDS::MemRegion* region) return; }*/ - DSi::ARM9GetMemRegion(addr, false, &CodeMem); - //NDS::ARM9GetMemRegion(addr, false, &CodeMem); + GetMemRegion(addr, false, &CodeMem); } diff --git a/src/DMA.cpp b/src/DMA.cpp index 8e294fc..cd2df45 100644 --- a/src/DMA.cpp +++ b/src/DMA.cpp @@ -53,8 +53,6 @@ DMA::DMA(u32 cpu, u32 num) CountMask = 0x001FFFFF; else CountMask = (num==3 ? 0x0000FFFF : 0x00003FFF); - - Reset(); } DMA::~DMA() @@ -77,6 +75,21 @@ void DMA::Reset() Running = false; InProgress = false; + + if (NDS::ConsoleType == 1) + { + BusRead16 = (CPU==0) ? DSi::ARM9Read16 : DSi::ARM7Read16; + BusRead32 = (CPU==0) ? DSi::ARM9Read32 : DSi::ARM7Read32; + BusWrite16 = (CPU==0) ? DSi::ARM9Write16 : DSi::ARM7Write16; + BusWrite32 = (CPU==0) ? DSi::ARM9Write32 : DSi::ARM7Write32; + } + else + { + BusRead16 = (CPU==0) ? NDS::ARM9Read16 : NDS::ARM7Read16; + BusRead32 = (CPU==0) ? NDS::ARM9Read32 : NDS::ARM7Read32; + BusWrite16 = (CPU==0) ? NDS::ARM9Write16 : NDS::ARM7Write16; + BusWrite32 = (CPU==0) ? NDS::ARM9Write32 : NDS::ARM7Write32; + } } void DMA::DoSavestate(Savestate* file) @@ -227,8 +240,7 @@ void DMA::Run9() { NDS::ARM9Timestamp += (unitcycles << NDS::ARM9ClockShift); - //NDS::ARM9Write16(CurDstAddr, NDS::ARM9Read16(CurSrcAddr)); - DSi::ARM9Write16(CurDstAddr, DSi::ARM9Read16(CurSrcAddr)); + BusWrite16(CurDstAddr, BusRead16(CurSrcAddr)); CurSrcAddr += SrcAddrInc<<1; CurDstAddr += DstAddrInc<<1; @@ -264,8 +276,7 @@ void DMA::Run9() { NDS::ARM9Timestamp += (unitcycles << NDS::ARM9ClockShift); - //NDS::ARM9Write32(CurDstAddr, NDS::ARM9Read32(CurSrcAddr)); - DSi::ARM9Write32(CurDstAddr, DSi::ARM9Read32(CurSrcAddr)); + BusWrite32(CurDstAddr, BusRead32(CurSrcAddr)); CurSrcAddr += SrcAddrInc<<2; CurDstAddr += DstAddrInc<<2; @@ -341,8 +352,7 @@ void DMA::Run7() { NDS::ARM7Timestamp += unitcycles; - //NDS::ARM7Write16(CurDstAddr, NDS::ARM7Read16(CurSrcAddr)); - DSi::ARM7Write16(CurDstAddr, DSi::ARM7Read16(CurSrcAddr)); + BusWrite16(CurDstAddr, BusRead16(CurSrcAddr)); CurSrcAddr += SrcAddrInc<<1; CurDstAddr += DstAddrInc<<1; @@ -378,8 +388,7 @@ void DMA::Run7() { NDS::ARM7Timestamp += unitcycles; - //NDS::ARM7Write32(CurDstAddr, NDS::ARM7Read32(CurSrcAddr)); - DSi::ARM7Write32(CurDstAddr, DSi::ARM7Read32(CurSrcAddr)); + BusWrite32(CurDstAddr, BusRead32(CurSrcAddr)); CurSrcAddr += SrcAddrInc<<2; CurDstAddr += DstAddrInc<<2; diff --git a/src/DMA.h b/src/DMA.h index 2e7678c..0344fba 100644 --- a/src/DMA.h +++ b/src/DMA.h @@ -86,6 +86,11 @@ private: bool Stall; bool IsGXFIFODMA; + + u16 (*BusRead16)(u32 addr); + u32 (*BusRead32)(u32 addr); + void (*BusWrite16)(u32 addr, u16 val); + void (*BusWrite32)(u32 addr, u32 val); }; #endif diff --git a/src/DSi.cpp b/src/DSi.cpp index 58f39c2..520b269 100644 --- a/src/DSi.cpp +++ b/src/DSi.cpp @@ -18,6 +18,7 @@ #include #include +#include "Config.h" #include "NDS.h" #include "DSi.h" #include "ARM.h" @@ -221,7 +222,7 @@ bool LoadBIOS() memset(ARM9iBIOS, 0, 0x10000); memset(ARM7iBIOS, 0, 0x10000); - f = Platform::OpenLocalFile("bios9i.bin", "rb"); + f = Platform::OpenLocalFile(Config::DSiBIOS9Path, "rb"); if (!f) { printf("ARM9i BIOS not found\n"); @@ -238,7 +239,7 @@ bool LoadBIOS() fclose(f); } - f = Platform::OpenLocalFile("bios7i.bin", "rb"); + f = Platform::OpenLocalFile(Config::DSiBIOS7Path, "rb"); if (!f) { printf("ARM7i BIOS not found\n"); @@ -283,7 +284,7 @@ bool LoadNAND() memset(NWRAMEnd, 0, sizeof(NWRAMEnd)); memset(NWRAMMask, 0, sizeof(NWRAMMask)); - FILE* f = Platform::OpenLocalFile("nand.bin", "rb"); + FILE* f = Platform::OpenLocalFile(Config::DSiNANDPath, "rb"); if (f) { u32 bootparams[8]; diff --git a/src/NDS.cpp b/src/NDS.cpp index 001dfe6..22368ae 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -62,6 +62,8 @@ namespace NDS // // timings for GBA slot and wifi are set up at runtime +int ConsoleType; + u8 ARM9MemTimings[0x40000][4]; u8 ARM7MemTimings[0x20000][4]; @@ -296,6 +298,8 @@ void InitTimings() // TODO: +3c nonseq waitstate doesn't apply to DMA! // but of course mainRAM always gets 8c nonseq waitstate + // TODO: DSi-specific timings!! + SetARM9RegionTimings(0x00000000, 0xFFFFFFFF, 32, 1 + 3, 1); // void SetARM9RegionTimings(0xFFFF0000, 0xFFFFFFFF, 32, 1 + 3, 1); // BIOS @@ -321,6 +325,12 @@ void InitTimings() void SetupDirectBoot() { + if (ConsoleType == 1) + { + printf("!! DIRECT BOOT NOT SUPPORTED IN DSI MODE\n"); + return; + } + u32 bootparams[8]; memcpy(bootparams, &NDSCart::CartROM[0x20], 8*4); @@ -469,7 +479,7 @@ void Reset() fclose(f); } - if (true) + if (ConsoleType == 1) { DSi::LoadBIOS(); DSi::LoadNAND(); @@ -559,8 +569,11 @@ void Reset() RTC::Reset(); Wifi::Reset(); - DSi::Reset(); - KeyInput &= ~(1 << (16+6)); // TODO + if (ConsoleType == 1) + { + DSi::Reset(); + KeyInput &= ~(1 << (16+6)); + } AREngine::Reset(); } @@ -670,6 +683,11 @@ bool DoSavestate(Savestate* file) { file->Section("NDSG"); + // TODO: + // * do something for bool's (sizeof=1) + // * do something for 'loading DSi-mode savestate in DS mode' and vice-versa + // * add IE2/IF2 there + file->VarArray(MainRAM, 0x400000); file->VarArray(SharedWRAM, 0x8000); file->VarArray(ARM7WRAM, 0x10000); @@ -772,6 +790,11 @@ bool DoSavestate(Savestate* file) return true; } +void SetConsoleType(int type) +{ + ConsoleType = type; +} + bool LoadROM(const char* path, const char* sram, bool direct) { if (NDSCart::LoadROM(path, sram, direct)) @@ -883,7 +906,7 @@ u32 RunFrame() if (!(CPUStop & 0x80000000)) DMAs[1]->Run(); if (!(CPUStop & 0x80000000)) DMAs[2]->Run(); if (!(CPUStop & 0x80000000)) DMAs[3]->Run(); - DSi::RunNDMAs(0); + if (ConsoleType == 1) DSi::RunNDMAs(0); } else { @@ -906,7 +929,7 @@ u32 RunFrame() DMAs[5]->Run(); DMAs[6]->Run(); DMAs[7]->Run(); - DSi::RunNDMAs(1); + if (ConsoleType == 1) DSi::RunNDMAs(1); } else { @@ -990,7 +1013,7 @@ void CancelEvent(u32 id) void TouchScreen(u16 x, u16 y) { - if (true) // TODO!! + if (ConsoleType == 1) { DSi_SPI_TSC::SetTouchCoords(x, y); } @@ -1003,7 +1026,7 @@ void TouchScreen(u16 x, u16 y) void ReleaseScreen() { - if (true) // TODO!! + if (ConsoleType == 1) { DSi_SPI_TSC::SetTouchCoords(0x000, 0xFFF); } @@ -1144,7 +1167,8 @@ void UpdateIRQ(u32 cpu) if (IME[cpu] & 0x1) { arm->IRQ = IE[cpu] & IF[cpu]; - if (cpu) arm->IRQ |= (IE2 & IF2); + if ((ConsoleType == 1) && cpu) + arm->IRQ |= (IE2 & IF2); } else { @@ -1223,7 +1247,7 @@ void GXFIFOStall() DMAs[1]->StallIfRunning(); DMAs[2]->StallIfRunning(); DMAs[3]->StallIfRunning(); - DSi::StallNDMAs(); + if (ConsoleType == 1) DSi::StallNDMAs(); } } @@ -1361,6 +1385,7 @@ void NocashPrint(u32 ncpu, u32 addr) void MonitorARM9Jump(u32 addr) { // checkme: can the entrypoint addr be THUMB? + // also TODO: make it work in DSi mode if ((!RunningGame) && NDSCart::CartROM) { @@ -1468,7 +1493,7 @@ bool DMAsInMode(u32 cpu, u32 mode) if (DMAs[cpu+2]->IsInMode(mode)) return true; if (DMAs[cpu+3]->IsInMode(mode)) return true; - if (true) + if (ConsoleType == 1) { cpu >>= 2; return DSi::NDMAsInMode(cpu, NDMAModes[mode]); @@ -1484,7 +1509,10 @@ bool DMAsRunning(u32 cpu) if (DMAs[cpu+1]->IsRunning()) return true; if (DMAs[cpu+2]->IsRunning()) return true; if (DMAs[cpu+3]->IsRunning()) return true; - if (DSi::NDMAsRunning(cpu>>2)) return true; + if (ConsoleType == 1) + { + if (DSi::NDMAsRunning(cpu>>2)) return true; + } return false; } @@ -1496,7 +1524,7 @@ void CheckDMAs(u32 cpu, u32 mode) DMAs[cpu+2]->StartIfNeeded(mode); DMAs[cpu+3]->StartIfNeeded(mode); - if (true) + if (ConsoleType == 1) { cpu >>= 2; DSi::CheckNDMAs(cpu, NDMAModes[mode]); @@ -1511,7 +1539,7 @@ void StopDMAs(u32 cpu, u32 mode) DMAs[cpu+2]->StopIfNeeded(mode); DMAs[cpu+3]->StopIfNeeded(mode); - if (true) + if (ConsoleType == 1) { cpu >>= 2; DSi::StopNDMAs(cpu, NDMAModes[mode]); diff --git a/src/NDS.h b/src/NDS.h index 26931de..9c5fe3d 100644 --- a/src/NDS.h +++ b/src/NDS.h @@ -133,6 +133,8 @@ typedef struct } MemRegion; +extern int ConsoleType; + extern u8 ARM9MemTimings[0x40000][4]; extern u8 ARM7MemTimings[0x20000][4]; @@ -174,6 +176,9 @@ bool DoSavestate(Savestate* file); void SetARM9RegionTimings(u32 addrstart, u32 addrend, int buswidth, int nonseq, int seq); void SetARM7RegionTimings(u32 addrstart, u32 addrend, int buswidth, int nonseq, int seq); +// 0=DS 1=DSi +void SetConsoleType(int type); + bool LoadROM(const char* path, const char* sram, bool direct); bool LoadGBAROM(const char* path, const char* sram); void LoadBIOS(); diff --git a/src/NDSCart.cpp b/src/NDSCart.cpp index 9497d33..b326dd6 100644 --- a/src/NDSCart.cpp +++ b/src/NDSCart.cpp @@ -561,11 +561,18 @@ void Key1_ApplyKeycode(u32* keycode, u32 mod) void Key1_InitKeycode(bool dsi, u32 idcode, u32 level, u32 mod) { - //memcpy(Key1_KeyBuf, &NDS::ARM7BIOS[0x30], 0x1048); // hax - if (dsi) - memcpy(Key1_KeyBuf, &DSi::ARM7Init[0x254], 0x1048); // hax + // TODO: source the key data from different possible places + if (NDS::ConsoleType == 1) + { + if (dsi) + memcpy(Key1_KeyBuf, &DSi::ARM7Init[0x254], 0x1048); // hax + else + memcpy(Key1_KeyBuf, &DSi::ITCMInit[0x4894], 0x1048); // hax + } else - memcpy(Key1_KeyBuf, &DSi::ITCMInit[0x4894], 0x1048); // hax + { + memcpy(Key1_KeyBuf, &NDS::ARM7BIOS[0x30], 0x1048); // hax + } u32 keycode[3] = {idcode, idcode>>1, idcode<<1}; if (level >= 1) Key1_ApplyKeycode(keycode, mod); diff --git a/src/SPI.cpp b/src/SPI.cpp index 29f3321..ac40707 100644 --- a/src/SPI.cpp +++ b/src/SPI.cpp @@ -93,7 +93,10 @@ void Reset() if (Firmware) delete[] Firmware; Firmware = NULL; - strncpy(FirmwarePath, Config::FirmwarePath, 1023); + if (NDS::ConsoleType == 1) + strncpy(FirmwarePath, Config::DSiFirmwarePath, 1023); + else + strncpy(FirmwarePath, Config::FirmwarePath, 1023); FILE* f = Platform::OpenLocalFile(FirmwarePath, "rb"); if (!f) @@ -620,7 +623,7 @@ void Reset() SPI_Firmware::Reset(); SPI_Powerman::Reset(); SPI_TSC::Reset(); - DSi_SPI_TSC::Reset(); + if (NDS::ConsoleType == 1) DSi_SPI_TSC::Reset(); } void DoSavestate(Savestate* file) @@ -633,7 +636,7 @@ void DoSavestate(Savestate* file) SPI_Firmware::DoSavestate(file); SPI_Powerman::DoSavestate(file); SPI_TSC::DoSavestate(file); - DSi_SPI_TSC::DoSavestate(file); + if (NDS::ConsoleType == 1) DSi_SPI_TSC::DoSavestate(file); } @@ -647,8 +650,12 @@ void WriteCnt(u16 val) { case 0x0000: SPI_Powerman::Hold = 0; break; case 0x0100: SPI_Firmware::Hold = 0; break; - //case 0x0200: SPI_TSC::DataPos = 0; break; - case 0x0200: DSi_SPI_TSC::DataPos = 0; break; + case 0x0200: + if (NDS::ConsoleType == 1) + DSi_SPI_TSC::DataPos = 0; + else + SPI_TSC::DataPos = 0; + break; } } @@ -674,8 +681,11 @@ u8 ReadData() { case 0x0000: return SPI_Powerman::Read(); case 0x0100: return SPI_Firmware::Read(); - //case 0x0200: return SPI_TSC::Read(); - case 0x0200: return DSi_SPI_TSC::Read(); + case 0x0200: + if (NDS::ConsoleType == 1) + return DSi_SPI_TSC::Read(); + else + return SPI_TSC::Read(); default: return 0; } } @@ -691,8 +701,12 @@ void WriteData(u8 val) { case 0x0000: SPI_Powerman::Write(val, Cnt&(1<<11)); break; case 0x0100: SPI_Firmware::Write(val, Cnt&(1<<11)); break; - //case 0x0200: SPI_TSC::Write(val, Cnt&(1<<11)); break; - case 0x0200: DSi_SPI_TSC::Write(val, Cnt&(1<<11)); break; + case 0x0200: + if (NDS::ConsoleType == 1) + DSi_SPI_TSC::Write(val, Cnt&(1<<11)); + else + SPI_TSC::Write(val, Cnt&(1<<11)); + break; default: printf("SPI to unknown device %04X %02X\n", Cnt, val); break; } diff --git a/src/SPU.cpp b/src/SPU.cpp index 959de12..9f6b107 100644 --- a/src/SPU.cpp +++ b/src/SPU.cpp @@ -155,6 +155,11 @@ Channel::~Channel() void Channel::Reset() { + if (NDS::ConsoleType == 1) + BusRead32 = DSi::ARM7Read32; + else + BusRead32 = NDS::ARM7Read32; + SetCnt(0); SrcAddr = 0; TimerReload = 0; @@ -217,8 +222,7 @@ void Channel::FIFO_BufferData() for (u32 i = 0; i < burstlen; i += 4) { - //FIFO[FIFOWritePos] = NDS::ARM7Read32(SrcAddr + FIFOReadOffset); - FIFO[FIFOWritePos] = DSi::ARM7Read32(SrcAddr + FIFOReadOffset); + FIFO[FIFOWritePos] = BusRead32(SrcAddr + FIFOReadOffset); FIFOReadOffset += 4; FIFOWritePos++; FIFOWritePos &= 0x7; @@ -466,6 +470,11 @@ CaptureUnit::~CaptureUnit() void CaptureUnit::Reset() { + if (NDS::ConsoleType == 1) + BusWrite32 = DSi::ARM7Write32; + else + BusWrite32 = NDS::ARM7Write32; + SetCnt(0); DstAddr = 0; TimerReload = 0; @@ -501,8 +510,7 @@ void CaptureUnit::FIFO_FlushData() { for (u32 i = 0; i < 4; i++) { - //NDS::ARM7Write32(DstAddr + FIFOWriteOffset, FIFO[FIFOReadPos]); - DSi::ARM7Write32(DstAddr + FIFOWriteOffset, FIFO[FIFOReadPos]); + BusWrite32(DstAddr + FIFOWriteOffset, FIFO[FIFOReadPos]); FIFOReadPos++; FIFOReadPos &= 0x3; diff --git a/src/SPU.h b/src/SPU.h index 74a4471..8ab17a0 100644 --- a/src/SPU.h +++ b/src/SPU.h @@ -142,6 +142,9 @@ public: } void PanOutput(s32* inbuf, u32 samples, s32* leftbuf, s32* rightbuf); + +private: + u32 (*BusRead32)(u32 addr); }; class CaptureUnit @@ -196,6 +199,9 @@ public: } void Run(s32 sample); + +private: + void (*BusWrite32)(u32 addr, u32 val); }; } diff --git a/src/frontend/FrontendUtil.h b/src/frontend/FrontendUtil.h index 6b83cbc..099583f 100644 --- a/src/frontend/FrontendUtil.h +++ b/src/frontend/FrontendUtil.h @@ -46,6 +46,15 @@ enum Load_FirmwareBad, Load_FirmwareNotBootable, + Load_DSiBIOS9Missing, + Load_DSiBIOS9Bad, + + Load_DSiBIOS7Missing, + Load_DSiBIOS7Bad, + + Load_DSiNANDMissing, + Load_DSiNANDBad, + // TODO: more precise errors for ROM loading Load_ROMLoadError, }; diff --git a/src/frontend/Util_ROM.cpp b/src/frontend/Util_ROM.cpp index d410550..8116a93 100644 --- a/src/frontend/Util_ROM.cpp +++ b/src/frontend/Util_ROM.cpp @@ -96,6 +96,42 @@ int VerifyDSBIOS() return Load_OK; } +int VerifyDSiBIOS() +{ + FILE* f; + long len; + + // TODO: check the first 32 bytes + + f = Platform::OpenLocalFile(Config::DSiBIOS9Path, "rb"); + if (!f) return Load_DSiBIOS9Missing; + + fseek(f, 0, SEEK_END); + len = ftell(f); + if (len != 0x10000) + { + fclose(f); + return Load_DSiBIOS9Bad; + } + + fclose(f); + + f = Platform::OpenLocalFile(Config::DSiBIOS7Path, "rb"); + if (!f) return Load_DSiBIOS7Missing; + + fseek(f, 0, SEEK_END); + len = ftell(f); + if (len != 0x10000) + { + fclose(f); + return Load_DSiBIOS7Bad; + } + + fclose(f); + + return Load_OK; +} + int VerifyDSFirmware() { FILE* f; @@ -110,7 +146,6 @@ int VerifyDSFirmware() { // 128KB firmware, not bootable fclose(f); - return Load_OK; // FIXME!!!! return Load_FirmwareNotBootable; } else if (len != 0x40000 && len != 0x80000) @@ -124,6 +159,45 @@ int VerifyDSFirmware() return Load_OK; } +int VerifyDSiFirmware() +{ + FILE* f; + long len; + + f = Platform::OpenLocalFile(Config::DSiFirmwarePath, "rb"); + if (!f) return Load_FirmwareMissing; + + fseek(f, 0, SEEK_END); + len = ftell(f); + if (len != 0x20000) + { + // not 128KB + // TODO: check whether those work + fclose(f); + return Load_FirmwareBad; + } + + fclose(f); + + return Load_OK; +} + +int VerifyDSiNAND() +{ + FILE* f; + long len; + + f = Platform::OpenLocalFile(Config::DSiNANDPath, "rb"); + if (!f) return Load_DSiNANDMissing; + + // TODO: some basic checks + // check that it has the nocash footer, and all + + fclose(f); + + return Load_OK; +} + int LoadBIOS() { int res; @@ -131,8 +205,22 @@ int LoadBIOS() res = VerifyDSBIOS(); if (res != Load_OK) return res; - res = VerifyDSFirmware(); - if (res != Load_OK) return res; + if (Config::ConsoleType == 1) + { + res = VerifyDSiBIOS(); + if (res != Load_OK) return res; + + res = VerifyDSiFirmware(); + if (res != Load_OK) return res; + + res = VerifyDSiNAND(); + if (res != Load_OK) return res; + } + else + { + res = VerifyDSFirmware(); + if (res != Load_OK) return res; + } // TODO: // original code in the libui frontend called NDS::LoadGBAROM() if needed @@ -142,6 +230,7 @@ int LoadBIOS() ROMPath[ROMSlot_NDS][0] = '\0'; SRAMPath[ROMSlot_NDS][0] = '\0'; + NDS::SetConsoleType(Config::ConsoleType); NDS::LoadBIOS(); SavestateLoaded = false; @@ -154,16 +243,39 @@ int LoadROM(const char* file, int slot) int res; bool directboot = Config::DirectBoot != 0; + if (Config::ConsoleType == 1 && slot == 1) + { + // cannot load a GBA ROM into a DSi + return Load_ROMLoadError; + } + res = VerifyDSBIOS(); if (res != Load_OK) return res; - res = VerifyDSFirmware(); - if (res != Load_OK) + if (Config::ConsoleType == 1) { - if (res == Load_FirmwareNotBootable) - directboot = true; - else - return res; + res = VerifyDSiBIOS(); + if (res != Load_OK) return res; + + res = VerifyDSiFirmware(); + if (res != Load_OK) return res; + + res = VerifyDSiNAND(); + if (res != Load_OK) return res; + + GBACart::Eject(); + ROMPath[ROMSlot_GBA][0] = '\0'; + } + else + { + res = VerifyDSFirmware(); + if (res != Load_OK) + { + if (res == Load_FirmwareNotBootable) + directboot = true; + else + return res; + } } char oldpath[1024]; @@ -177,6 +289,8 @@ int LoadROM(const char* file, int slot) SetupSRAMPath(0); SetupSRAMPath(1); + NDS::SetConsoleType(Config::ConsoleType); + if (slot == ROMSlot_NDS && NDS::LoadROM(ROMPath[slot], SRAMPath[slot], directboot)) { SavestateLoaded = false; @@ -225,17 +339,36 @@ int Reset() res = VerifyDSBIOS(); if (res != Load_OK) return res; - res = VerifyDSFirmware(); - if (res != Load_OK) + if (Config::ConsoleType == 1) { - if (res == Load_FirmwareNotBootable) - directboot = true; - else - return res; + res = VerifyDSiBIOS(); + if (res != Load_OK) return res; + + res = VerifyDSiFirmware(); + if (res != Load_OK) return res; + + res = VerifyDSiNAND(); + if (res != Load_OK) return res; + + GBACart::Eject(); + ROMPath[ROMSlot_GBA][0] = '\0'; + } + else + { + res = VerifyDSFirmware(); + if (res != Load_OK) + { + if (res == Load_FirmwareNotBootable) + directboot = true; + else + return res; + } } SavestateLoaded = false; + NDS::SetConsoleType(Config::ConsoleType); + if (ROMPath[ROMSlot_NDS][0] == '\0') { NDS::LoadBIOS(); diff --git a/src/frontend/qt_sdl/EmuSettingsDialog.cpp b/src/frontend/qt_sdl/EmuSettingsDialog.cpp index 7760a88..09faf4e 100644 --- a/src/frontend/qt_sdl/EmuSettingsDialog.cpp +++ b/src/frontend/qt_sdl/EmuSettingsDialog.cpp @@ -49,7 +49,7 @@ EmuSettingsDialog::EmuSettingsDialog(QWidget* parent) : QDialog(parent), ui(new ui->txtDSiNANDPath->setText(Config::DSiNANDPath); ui->cbxConsoleType->addItem("DS"); - ui->cbxConsoleType->addItem("DSi"); + ui->cbxConsoleType->addItem("DSi (experimental)"); ui->cbxConsoleType->setCurrentIndex(Config::ConsoleType); ui->chkDirectBoot->setChecked(Config::DirectBoot != 0); diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index ef21bc7..7b3d5cd 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -1360,17 +1360,40 @@ QString MainWindow::loadErrorStr(int error) { switch (error) { - case Frontend::Load_BIOS9Missing: return "DS ARM9 BIOS was not found or could not be accessed. Check your emu settings."; - case Frontend::Load_BIOS9Bad: return "DS ARM9 BIOS is not a valid BIOS dump."; - - case Frontend::Load_BIOS7Missing: return "DS ARM7 BIOS was not found or could not be accessed. Check your emu settings."; - case Frontend::Load_BIOS7Bad: return "DS ARM7 BIOS is not a valid BIOS dump."; - - case Frontend::Load_FirmwareMissing: return "DS firmware was not found or could not be accessed. Check your emu settings."; - case Frontend::Load_FirmwareBad: return "DS firmware is not a valid firmware dump."; - case Frontend::Load_FirmwareNotBootable: return "DS firmware is not bootable."; - - case Frontend::Load_ROMLoadError: return "Failed to load the ROM. Make sure the file is accessible and isn't used by another application."; + case Frontend::Load_BIOS9Missing: + return "DS ARM9 BIOS was not found or could not be accessed. Check your emu settings."; + case Frontend::Load_BIOS9Bad: + return "DS ARM9 BIOS is not a valid BIOS dump."; + + case Frontend::Load_BIOS7Missing: + return "DS ARM7 BIOS was not found or could not be accessed. Check your emu settings."; + case Frontend::Load_BIOS7Bad: + return "DS ARM7 BIOS is not a valid BIOS dump."; + + case Frontend::Load_FirmwareMissing: + return "DS firmware was not found or could not be accessed. Check your emu settings."; + case Frontend::Load_FirmwareBad: + return "DS firmware is not a valid firmware dump."; + case Frontend::Load_FirmwareNotBootable: + return "DS firmware is not bootable."; + + case Frontend::Load_DSiBIOS9Missing: + return "DSi ARM9 BIOS was not found or could not be accessed. Check your emu settings."; + case Frontend::Load_DSiBIOS9Bad: + return "DSi ARM9 BIOS is not a valid BIOS dump."; + + case Frontend::Load_DSiBIOS7Missing: + return "DSi ARM7 BIOS was not found or could not be accessed. Check your emu settings."; + case Frontend::Load_DSiBIOS7Bad: + return "DSi ARM7 BIOS is not a valid BIOS dump."; + + case Frontend::Load_DSiNANDMissing: + return "DSi NAND was not found or could not be accessed. Check your emu settings."; + case Frontend::Load_DSiNANDBad: + return "DSi NAND is not a valid NAND dump."; + + case Frontend::Load_ROMLoadError: + return "Failed to load the ROM. Make sure the file is accessible and isn't used by another application."; default: return "Unknown error during launch; smack Arisotura."; } -- cgit v1.2.3