From d20543c119d623fef4636edd78063e00803020d6 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Tue, 31 Aug 2021 02:28:34 +0200 Subject: [PATCH] DMA timing renovation (#1207) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * make timers usable for measurement shito without being assfuckingly unreliable * bürp * Arisotura can you ever clean up your goddamn code also regroup the timer code instead of having it split weirdly * make the set-timing functions a tad less hacky * congrats Arisotura you made an ass-enum * add timing region tables, and separate timings for ARM9 DMA (exempt of 3c penalty) * temp work on DMA timings, not finished also, did you know? 'increment/reload' is also a thing for the source address * begin work * add some of the GBA slot/wifi timings * complete it, I guess * make some progress * getting somewhere * sdsdfs * see, Arisotura, was it that hard? blarg. --- src/CMakeLists.txt | 1 + src/CP15.cpp | 30 +-- src/DMA.cpp | 468 ++++++++++++++++++++++++++++++++++++--------- src/DMA.h | 12 +- src/DMA_Timings.h | 245 ++++++++++++++++++++++++ src/DSi.cpp | 2 +- src/NDS.cpp | 210 ++++++++++---------- src/NDS.h | 35 +++- 8 files changed, 786 insertions(+), 217 deletions(-) create mode 100644 src/DMA_Timings.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 54d08992..1f5d00bc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -15,6 +15,7 @@ add_library(core STATIC CP15.cpp CRC32.cpp DMA.cpp + DMA_Timings.h DSi.cpp DSi_AES.cpp DSi_Camera.cpp diff --git a/src/CP15.cpp b/src/CP15.cpp index 56c98309..f30ed9eb 100644 --- a/src/CP15.cpp +++ b/src/CP15.cpp @@ -225,7 +225,8 @@ void ARMv5::UpdatePURegion(u32 n) usermask |= 0x40; } - //printf("PU region %d: %08X-%08X, user=%02X priv=%02X\n", n, start<<12, end<<12, usermask, privmask); + printf("PU region %d: %08X-%08X, user=%02X priv=%02X\n", n, start<<12, end<<12, usermask, privmask); + printf("%08X/%08X\n", PU_DataRW, PU_CodeRW); for (u32 i = start; i < end; i++) { @@ -233,7 +234,7 @@ void ARMv5::UpdatePURegion(u32 n) PU_PrivMap[i] = privmask; } - UpdateRegionTimings(start<<12, end<<12); + UpdateRegionTimings(start, end); } void ARMv5::UpdatePURegions(bool update_all) @@ -249,7 +250,7 @@ void ARMv5::UpdatePURegions(bool update_all) memset(PU_UserMap, mask, 0x100000); memset(PU_PrivMap, mask, 0x100000); - UpdateRegionTimings(0x00000000, 0xFFFFFFFF); + UpdateRegionTimings(0x00000, 0x100000); return; } @@ -266,16 +267,11 @@ void ARMv5::UpdatePURegions(bool update_all) // TODO: this is way unoptimized // should be okay unless the game keeps changing shit, tho - if (update_all) UpdateRegionTimings(0x00000000, 0xFFFFFFFF); + if (update_all) UpdateRegionTimings(0x00000, 0x100000); } void ARMv5::UpdateRegionTimings(u32 addrstart, u32 addrend) { - addrstart >>= 12; - addrend >>= 12; - - if (addrend == 0xFFFFF) addrend++; - for (u32 i = addrstart; i < addrend; i++) { u8 pu = PU_Map[i]; @@ -420,7 +416,7 @@ void ARMv5::ICacheInvalidateAll() void ARMv5::CP15Write(u32 id, u32 val) { - //printf("CP15 write op %03X %08X %08X\n", id, val, R[15]); + //if(id!=0x704)printf("CP15 write op %03X %08X %08X\n", id, val, R[15]); switch (id) { @@ -520,7 +516,7 @@ void ARMv5::CP15Write(u32 id, u32 val) return; case 0x502: // data permissions - { + {printf("SET DATAPERM %08X (%08X %08X)\n", val,PU_DataRW,PU_DataRW ^ val); u32 diff = PU_DataRW ^ val; PU_DataRW = val; for (u32 i = 0; i < 8; i++) @@ -814,6 +810,12 @@ void ARMv5::DataRead16(u32 addr, u32* val) void ARMv5::DataRead32(u32 addr, u32* val) { + /*if (!(PU_Map[addr>>12] & 0x01)) + {printf("addr %08X very bad\n", addr); + DataAbort(); + return; + }*/ + DataRegion = addr; addr &= ~3; @@ -908,6 +910,12 @@ void ARMv5::DataWrite16(u32 addr, u16 val) void ARMv5::DataWrite32(u32 addr, u32 val) { + /*if (!(PU_Map[addr>>12] & 0x02)) + {printf("addr %08X wr very bad\n", addr); + DataAbort(); + return; + }*/ + DataRegion = addr; addr &= ~3; diff --git a/src/DMA.cpp b/src/DMA.cpp index e7473fbf..e6018719 100644 --- a/src/DMA.cpp +++ b/src/DMA.cpp @@ -21,6 +21,7 @@ #include "DSi.h" #include "DMA.h" #include "GPU.h" +#include "DMA_Timings.h" @@ -77,6 +78,7 @@ void DMA::Reset() Running = false; InProgress = false; + MRAMBurstCount = 0; } void DMA::DoSavestate(Savestate* file) @@ -94,12 +96,13 @@ void DMA::DoSavestate(Savestate* file) file->Var32(&CurDstAddr); file->Var32(&RemCount); file->Var32(&IterCount); - file->Var32(&SrcAddrInc); - file->Var32(&DstAddrInc); + file->Var32((u32*)&SrcAddrInc); + file->Var32((u32*)&DstAddrInc); file->Var32(&Running); file->Bool32(&InProgress); file->Bool32(&IsGXFIFODMA); + file->Var32(&MRAMBurstCount); } void DMA::WriteCnt(u32 val) @@ -125,7 +128,7 @@ void DMA::WriteCnt(u32 val) case 0x00000000: SrcAddrInc = 1; break; case 0x00800000: SrcAddrInc = -1; break; case 0x01000000: SrcAddrInc = 0; break; - case 0x01800000: SrcAddrInc = 1; printf("BAD DMA SRC INC MODE 3\n"); break; + case 0x01800000: SrcAddrInc = 1; break; } if (CPU == 0) @@ -165,6 +168,9 @@ void DMA::Start() else IterCount = RemCount; + if ((Cnt & 0x01800000) == 0x01800000) + CurSrcAddr = SrcAddr; + if ((Cnt & 0x00600000) == 0x00600000) CurDstAddr = DstAddr; @@ -174,15 +180,369 @@ void DMA::Start() // TODO eventually: not stop if we're running code in ITCM - if (NDS::DMAsRunning(CPU)) - Running = 1; - else - Running = 2; + Running = 2; + + // safety measure + MRAMBurstTable = DMATiming::MRAMDummy; InProgress = true; NDS::StopCPU(CPU, 1<> 14; + u32 dst_id = CurDstAddr >> 14; + + u32 src_rgn = NDS::ARM9Regions[src_id]; + u32 dst_rgn = NDS::ARM9Regions[dst_id]; + + u32 src_n, src_s, dst_n, dst_s; + src_n = NDS::ARM9MemTimings[src_id][4]; + src_s = NDS::ARM9MemTimings[src_id][5]; + dst_n = NDS::ARM9MemTimings[dst_id][4]; + dst_s = NDS::ARM9MemTimings[dst_id][5]; + + if (src_rgn == NDS::Mem9_MainRAM) + { + if (dst_rgn == NDS::Mem9_MainRAM) + return 16; + + if (SrcAddrInc > 0) + { + if (burststart || MRAMBurstTable[MRAMBurstCount] == 0) + { + MRAMBurstCount = 0; + + if (dst_rgn == NDS::Mem9_GBAROM) + { + if (dst_s == 4) + MRAMBurstTable = DMATiming::MRAMRead16Bursts[1]; + else + MRAMBurstTable = DMATiming::MRAMRead16Bursts[2]; + } + else + MRAMBurstTable = DMATiming::MRAMRead16Bursts[0]; + } + + u32 ret = MRAMBurstTable[MRAMBurstCount++]; + return ret; + } + else + { + // TODO: not quite right for GBA slot + return (((CurSrcAddr & 0x1F) == 0x1E) ? 7 : 8) + + (burststart ? dst_n : dst_s); + } + } + else if (dst_rgn == NDS::Mem9_MainRAM) + { + if (DstAddrInc > 0) + { + if (burststart || MRAMBurstTable[MRAMBurstCount] == 0) + { + MRAMBurstCount = 0; + + if (src_rgn == NDS::Mem9_GBAROM) + { + if (src_s == 4) + MRAMBurstTable = DMATiming::MRAMWrite16Bursts[1]; + else + MRAMBurstTable = DMATiming::MRAMWrite16Bursts[2]; + } + else + MRAMBurstTable = DMATiming::MRAMWrite16Bursts[0]; + } + + u32 ret = MRAMBurstTable[MRAMBurstCount++]; + return ret; + } + else + { + return (burststart ? src_n : src_s) + 7; + } + } + else if (src_rgn & dst_rgn) + { + return src_n + dst_n + 1; + } + else + { + if (burststart) + return src_n + dst_n; + else + return src_s + dst_s; + } +} + +u32 DMA::UnitTimings9_32(bool burststart) +{ + u32 src_id = CurSrcAddr >> 14; + u32 dst_id = CurDstAddr >> 14; + + u32 src_rgn = NDS::ARM9Regions[src_id]; + u32 dst_rgn = NDS::ARM9Regions[dst_id]; + + u32 src_n, src_s, dst_n, dst_s; + src_n = NDS::ARM9MemTimings[src_id][6]; + src_s = NDS::ARM9MemTimings[src_id][7]; + dst_n = NDS::ARM9MemTimings[dst_id][6]; + dst_s = NDS::ARM9MemTimings[dst_id][7]; + + if (src_rgn == NDS::Mem9_MainRAM) + { + if (dst_rgn == NDS::Mem9_MainRAM) + return 18; + + if (SrcAddrInc > 0) + { + if (burststart || MRAMBurstTable[MRAMBurstCount] == 0) + { + MRAMBurstCount = 0; + + if (dst_rgn == NDS::Mem9_GBAROM) + { + if (dst_s == 8) + MRAMBurstTable = DMATiming::MRAMRead32Bursts[2]; + else + MRAMBurstTable = DMATiming::MRAMRead32Bursts[3]; + } + else if (dst_n == 2) + MRAMBurstTable = DMATiming::MRAMRead32Bursts[0]; + else + MRAMBurstTable = DMATiming::MRAMRead32Bursts[1]; + } + + u32 ret = MRAMBurstTable[MRAMBurstCount++]; + return ret; + } + else + { + // TODO: not quite right for GBA slot + return (((CurSrcAddr & 0x1F) == 0x1C) ? (dst_n==2 ? 7:8) : 9) + + (burststart ? dst_n : dst_s); + } + } + else if (dst_rgn == NDS::Mem9_MainRAM) + { + if (DstAddrInc > 0) + { + if (burststart || MRAMBurstTable[MRAMBurstCount] == 0) + { + MRAMBurstCount = 0; + + if (src_rgn == NDS::Mem9_GBAROM) + { + if (src_s == 8) + MRAMBurstTable = DMATiming::MRAMWrite32Bursts[2]; + else + MRAMBurstTable = DMATiming::MRAMWrite32Bursts[3]; + } + else if (src_n == 2) + MRAMBurstTable = DMATiming::MRAMWrite32Bursts[0]; + else + MRAMBurstTable = DMATiming::MRAMWrite32Bursts[1]; + } + + u32 ret = MRAMBurstTable[MRAMBurstCount++]; + return ret; + } + else + { + return (burststart ? src_n : src_s) + 8; + } + } + else if (src_rgn & dst_rgn) + { + return src_n + dst_n + 1; + } + else + { + if (burststart) + return src_n + dst_n; + else + return src_s + dst_s; + } +} + +// TODO: the ARM7 ones don't take into account that the two wifi regions have different timings + +u32 DMA::UnitTimings7_16(bool burststart) +{ + u32 src_id = CurSrcAddr >> 15; + u32 dst_id = CurDstAddr >> 15; + + u32 src_rgn = NDS::ARM7Regions[src_id]; + u32 dst_rgn = NDS::ARM7Regions[dst_id]; + + u32 src_n, src_s, dst_n, dst_s; + src_n = NDS::ARM7MemTimings[src_id][0]; + src_s = NDS::ARM7MemTimings[src_id][1]; + dst_n = NDS::ARM7MemTimings[dst_id][0]; + dst_s = NDS::ARM7MemTimings[dst_id][1]; + + if (src_rgn == NDS::Mem7_MainRAM) + { + if (dst_rgn == NDS::Mem7_MainRAM) + return 16; + + if (SrcAddrInc > 0) + { + if (burststart || MRAMBurstTable[MRAMBurstCount] == 0) + { + MRAMBurstCount = 0; + + if (dst_rgn == NDS::Mem7_GBAROM || dst_rgn == NDS::Mem7_Wifi0 || dst_rgn == NDS::Mem7_Wifi1) + { + if (dst_s == 4) + MRAMBurstTable = DMATiming::MRAMRead16Bursts[1]; + else + MRAMBurstTable = DMATiming::MRAMRead16Bursts[2]; + } + else + MRAMBurstTable = DMATiming::MRAMRead16Bursts[0]; + } + + u32 ret = MRAMBurstTable[MRAMBurstCount++]; + return ret; + } + else + { + // TODO: not quite right for GBA slot + return (((CurSrcAddr & 0x1F) == 0x1E) ? 7 : 8) + + (burststart ? dst_n : dst_s); + } + } + else if (dst_rgn == NDS::Mem7_MainRAM) + { + if (DstAddrInc > 0) + { + if (burststart || MRAMBurstTable[MRAMBurstCount] == 0) + { + MRAMBurstCount = 0; + + if (src_rgn == NDS::Mem7_GBAROM || src_rgn == NDS::Mem7_Wifi0 || src_rgn == NDS::Mem7_Wifi1) + { + if (src_s == 4) + MRAMBurstTable = DMATiming::MRAMWrite16Bursts[1]; + else + MRAMBurstTable = DMATiming::MRAMWrite16Bursts[2]; + } + else + MRAMBurstTable = DMATiming::MRAMWrite16Bursts[0]; + } + + u32 ret = MRAMBurstTable[MRAMBurstCount++]; + return ret; + } + else + { + return (burststart ? src_n : src_s) + 7; + } + } + else if (src_rgn & dst_rgn) + { + return src_n + dst_n + 1; + } + else + { + if (burststart) + return src_n + dst_n; + else + return src_s + dst_s; + } +} + +u32 DMA::UnitTimings7_32(bool burststart) +{ + u32 src_id = CurSrcAddr >> 15; + u32 dst_id = CurDstAddr >> 15; + + u32 src_rgn = NDS::ARM7Regions[src_id]; + u32 dst_rgn = NDS::ARM7Regions[dst_id]; + + u32 src_n, src_s, dst_n, dst_s; + src_n = NDS::ARM7MemTimings[src_id][2]; + src_s = NDS::ARM7MemTimings[src_id][3]; + dst_n = NDS::ARM7MemTimings[dst_id][2]; + dst_s = NDS::ARM7MemTimings[dst_id][3]; + + if (src_rgn == NDS::Mem7_MainRAM) + { + if (dst_rgn == NDS::Mem7_MainRAM) + return 18; + + if (SrcAddrInc > 0) + { + if (burststart || MRAMBurstTable[MRAMBurstCount] == 0) + { + MRAMBurstCount = 0; + + if (dst_rgn == NDS::Mem7_GBAROM || dst_rgn == NDS::Mem7_Wifi0 || dst_rgn == NDS::Mem7_Wifi1) + { + if (dst_s == 8) + MRAMBurstTable = DMATiming::MRAMRead32Bursts[2]; + else + MRAMBurstTable = DMATiming::MRAMRead32Bursts[3]; + } + else if (dst_n == 2) + MRAMBurstTable = DMATiming::MRAMRead32Bursts[0]; + else + MRAMBurstTable = DMATiming::MRAMRead32Bursts[1]; + } + + u32 ret = MRAMBurstTable[MRAMBurstCount++]; + return ret; + } + else + { + // TODO: not quite right for GBA slot + return (((CurSrcAddr & 0x1F) == 0x1C) ? (dst_n==2 ? 7:8) : 9) + + (burststart ? dst_n : dst_s); + } + } + else if (dst_rgn == NDS::Mem7_MainRAM) + { + if (DstAddrInc > 0) + { + if (burststart || MRAMBurstTable[MRAMBurstCount] == 0) + { + MRAMBurstCount = 0; + + if (src_rgn == NDS::Mem7_GBAROM || src_rgn == NDS::Mem7_Wifi0 || src_rgn == NDS::Mem7_Wifi1) + { + if (src_s == 8) + MRAMBurstTable = DMATiming::MRAMWrite32Bursts[2]; + else + MRAMBurstTable = DMATiming::MRAMWrite32Bursts[3]; + } + else if (src_n == 2) + MRAMBurstTable = DMATiming::MRAMWrite32Bursts[0]; + else + MRAMBurstTable = DMATiming::MRAMWrite32Bursts[1]; + } + + u32 ret = MRAMBurstTable[MRAMBurstCount++]; + return ret; + } + else + { + return (burststart ? src_n : src_s) + 8; + } + } + else if (src_rgn & dst_rgn) + { + return src_n + dst_n + 1; + } + else + { + if (burststart) + return src_n + dst_n; + else + return src_s + dst_s; + } +} + template void DMA::Run9() { @@ -194,32 +554,12 @@ void DMA::Run9() bool burststart = (Running == 2); Running = 1; - s32 unitcycles; - //s32 lastcycles = cycles; - if (!(Cnt & (1<<26))) { - if ((CurSrcAddr >> 24) == 0x02 && (CurDstAddr >> 24) == 0x02) - { - unitcycles = NDS::ARM9MemTimings[CurSrcAddr >> 14][0] + NDS::ARM9MemTimings[CurDstAddr >> 14][0]; - } - else - { - unitcycles = NDS::ARM9MemTimings[CurSrcAddr >> 14][1] + NDS::ARM9MemTimings[CurDstAddr >> 14][1]; - if ((CurSrcAddr >> 24) == (CurDstAddr >> 24)) - unitcycles++; - - /*if (burststart) - { - cycles -= 2; - cycles -= (NDS::ARM9MemTimings[CurSrcAddr >> 14][0] + NDS::ARM9MemTimings[CurDstAddr >> 14][0]); - cycles += unitcycles; - }*/ - } - while (IterCount > 0 && !Stall) { - NDS::ARM9Timestamp += (unitcycles << NDS::ARM9ClockShift); + NDS::ARM9Timestamp += (UnitTimings9_16(burststart) << NDS::ARM9ClockShift); + burststart = false; if (ConsoleType == 1) DSi::ARM9Write16(CurDstAddr, DSi::ARM9Read16(CurSrcAddr)); @@ -236,29 +576,10 @@ void DMA::Run9() } else { - 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); + NDS::ARM9Timestamp += (UnitTimings9_32(burststart) << NDS::ARM9ClockShift); + burststart = false; if (ConsoleType == 1) DSi::ARM9Write32(CurDstAddr, DSi::ARM9Read32(CurSrcAddr)); @@ -313,32 +634,12 @@ void DMA::Run7() bool burststart = (Running == 2); Running = 1; - s32 unitcycles; - //s32 lastcycles = cycles; - if (!(Cnt & (1<<26))) { - if ((CurSrcAddr >> 24) == 0x02 && (CurDstAddr >> 24) == 0x02) - { - unitcycles = NDS::ARM7MemTimings[CurSrcAddr >> 15][0] + NDS::ARM7MemTimings[CurDstAddr >> 15][0]; - } - else - { - unitcycles = NDS::ARM7MemTimings[CurSrcAddr >> 15][1] + NDS::ARM7MemTimings[CurDstAddr >> 15][1]; - if ((CurSrcAddr >> 23) == (CurDstAddr >> 23)) - unitcycles++; - - /*if (burststart) - { - cycles -= 2; - cycles -= (NDS::ARM7MemTimings[CurSrcAddr >> 15][0] + NDS::ARM7MemTimings[CurDstAddr >> 15][0]); - cycles += unitcycles; - }*/ - } - while (IterCount > 0 && !Stall) { - NDS::ARM7Timestamp += unitcycles; + NDS::ARM7Timestamp += UnitTimings7_16(burststart); + burststart = false; if (ConsoleType == 1) DSi::ARM7Write16(CurDstAddr, DSi::ARM7Read16(CurSrcAddr)); @@ -355,29 +656,10 @@ void DMA::Run7() } else { - 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; + NDS::ARM7Timestamp += UnitTimings7_32(burststart); + burststart = false; if (ConsoleType == 1) DSi::ARM7Write32(CurDstAddr, DSi::ARM7Read32(CurSrcAddr)); diff --git a/src/DMA.h b/src/DMA.h index b86796d3..17cb6181 100644 --- a/src/DMA.h +++ b/src/DMA.h @@ -34,6 +34,11 @@ public: void WriteCnt(u32 val); void Start(); + u32 UnitTimings9_16(bool burststart); + u32 UnitTimings9_32(bool burststart); + u32 UnitTimings7_16(bool burststart); + u32 UnitTimings7_32(bool burststart); + template void Run(); @@ -78,8 +83,8 @@ private: u32 CurDstAddr; u32 RemCount; u32 IterCount; - u32 SrcAddrInc; - u32 DstAddrInc; + s32 SrcAddrInc; + s32 DstAddrInc; u32 CountMask; u32 Running; @@ -89,6 +94,9 @@ private: bool Stall; bool IsGXFIFODMA; + + u32 MRAMBurstCount; + u8* MRAMBurstTable; }; #endif diff --git a/src/DMA_Timings.h b/src/DMA_Timings.h new file mode 100644 index 00000000..1d86750a --- /dev/null +++ b/src/DMA_Timings.h @@ -0,0 +1,245 @@ +/* + Copyright 2016-2021 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#ifndef DMA_TIMINGS_H +#define DMA_TIMINGS_H + +namespace DMATiming +{ + +// DMA timing tables +// +// DMA timings on the DS are normally straightforward, except in one case: when +// main RAM is involved. +// Main RAM to main RAM is the easy case: 16c/unit in 16bit mode, 18c/unit in 32bit +// mode. +// It gets more complicated when transferring from main RAM to somewhere else, or +// vice versa: main RAM supports burst accesses, but the rules dictating how long +// bursts can be are weird and inconsistent. Main RAM also supports parallel +// memory operations, to some extent. +// I haven't figured out the full logic behind it, let alone how to emulate it +// efficiently, so for now we will use these tables. +// A zero denotes the end of a burst pattern. +// +// Note: burst patterns only apply when the main RAM address is incrementing. +// A fixed or decrementing address results in nonsequential accesses. +// +// Note about GBA slot/wifi timings: these take into account the sequential timing +// setting. Timings are such that the nonseq setting only matters for the first +// access, and minor edge cases (like the last of a 0x20000-byte block). + +u8 MRAMDummy[1] = {0}; + +u8 MRAMRead16Bursts[][256] = +{ + // main RAM to regular 16bit or 32bit bus (similar) + {7, 3, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, + 7, 3, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, + 7, 3, + 0}, + // main RAM to GBA/wifi, seq=4 + {8, 6, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, + 0}, + // main RAM to GBA/wifi, seq=6 + {10, 8, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, + 12, 8, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, + 12, 8, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, + 12, 8, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, + 12, 8, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, + 12, 8, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, + 12, 8, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, + 12, 8, + 0}, +}; + +u8 MRAMRead32Bursts[][256] = +{ + // main RAM to regular 16bit bus + {9, 4, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 9, + 0}, + // main RAM to regular 32bit bus + {9, 3, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 0}, + // main RAM to GBA/wifi, seq=4 + {14, 10, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, + 13, 10, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, + 13, 10, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, + 13, 10, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, + 13, 10, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, + 13, + 0}, + // main RAM to GBA/wifi, seq=6 + {18, 14, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, + 17, 14, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, + 17, 14, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, + 17, 14, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, + 17, 14, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, + 17, + 0}, +}; + +u8 MRAMWrite16Bursts[][256] = +{ + // regular 16bit or 32bit bus to main RAM (similar) + {8, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 0}, + // GBA/wifi to main RAM, seq=4 + {10, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, + 0}, + // GBA/wifi to main RAM, seq=6 + {9, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, + 0}, +}; + +u8 MRAMWrite32Bursts[][256] = +{ + // regular 16bit bus to main RAM + {9, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 0}, + // regular 32bit bus to main RAM + {9, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 0}, + // GBA/wifi to main RAM, seq=4 + {15, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, + 0}, + // GBA/wifi to main RAM, seq=6 + {16, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, + 0}, +}; + +} + +#endif // DMA_TIMINGS_H diff --git a/src/DSi.cpp b/src/DSi.cpp index 01e501b6..d453ee27 100644 --- a/src/DSi.cpp +++ b/src/DSi.cpp @@ -1139,7 +1139,7 @@ void Set_SCFG_Clock9(u16 val) NDS::ARM9Timestamp <<= NDS::ARM9ClockShift; NDS::ARM9Target <<= NDS::ARM9ClockShift; - NDS::ARM9->UpdateRegionTimings(0x00000000, 0xFFFFFFFF); + NDS::ARM9->UpdateRegionTimings(0x00000, 0x100000); } void Set_SCFG_MC(u32 val) diff --git a/src/NDS.cpp b/src/NDS.cpp index 00cbad3e..83416878 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -71,8 +71,10 @@ namespace NDS int ConsoleType; -u8 ARM9MemTimings[0x40000][4]; +u8 ARM9MemTimings[0x40000][8]; +u32 ARM9Regions[0x40000]; u8 ARM7MemTimings[0x20000][4]; +u32 ARM7Regions[0x20000]; ARMv5* ARM9; ARMv4* ARM7; @@ -236,14 +238,12 @@ void DeInit() } -void SetARM9RegionTimings(u32 addrstart, u32 addrend, int buswidth, int nonseq, int seq) +void SetARM9RegionTimings(u32 addrstart, u32 addrend, u32 region, int buswidth, int nonseq, int seq) { - addrstart >>= 14; - addrend >>= 14; + addrstart >>= 2; + addrend >>= 2; - if (addrend == 0x3FFFF) addrend++; - - int N16, S16, N32, S32; + int N16, S16, N32, S32, cpuN; N16 = nonseq; S16 = seq; if (buswidth == 16) @@ -257,25 +257,33 @@ void SetARM9RegionTimings(u32 addrstart, u32 addrend, int buswidth, int nonseq, S32 = S16; } + // nonseq accesses on the CPU get a 3-cycle penalty for all regions except main RAM + cpuN = (region == Mem9_MainRAM) ? 0 : 3; + for (u32 i = addrstart; i < addrend; i++) { - ARM9MemTimings[i][0] = N16; + // CPU timings + ARM9MemTimings[i][0] = N16 + cpuN; ARM9MemTimings[i][1] = S16; - ARM9MemTimings[i][2] = N32; + ARM9MemTimings[i][2] = N32 + cpuN; ARM9MemTimings[i][3] = S32; + + // DMA timings + ARM9MemTimings[i][4] = N16; + ARM9MemTimings[i][5] = S16; + ARM9MemTimings[i][6] = N32; + ARM9MemTimings[i][7] = S32; + + ARM9Regions[i] = region; } - ARM9->UpdateRegionTimings(addrstart<<14, addrend == 0x40000 - ? 0xFFFFFFFF - : (addrend<<14)); + ARM9->UpdateRegionTimings(addrstart<<2, addrend<<2); } -void SetARM7RegionTimings(u32 addrstart, u32 addrend, int buswidth, int nonseq, int seq) +void SetARM7RegionTimings(u32 addrstart, u32 addrend, u32 region, int buswidth, int nonseq, int seq) { - addrstart >>= 15; - addrend >>= 15; - - if (addrend == 0x1FFFF) addrend++; + addrstart >>= 3; + addrend >>= 3; int N16, S16, N32, S32; N16 = nonseq; @@ -293,10 +301,13 @@ void SetARM7RegionTimings(u32 addrstart, u32 addrend, int buswidth, int nonseq, for (u32 i = addrstart; i < addrend; i++) { + // CPU and DMA timings are the same ARM7MemTimings[i][0] = N16; ARM7MemTimings[i][1] = S16; ARM7MemTimings[i][2] = N32; ARM7MemTimings[i][3] = S32; + + ARM7Regions[i] = region; } } @@ -307,32 +318,32 @@ void InitTimings() // Similarly for any unmapped VRAM area. // Need to check whether supporting these timing characteristics would impact performance // (especially wrt VRAM mirroring and overlapping and whatnot). + // Also, each VRAM bank is its own memory region. This would matter when DMAing from a VRAM + // bank to another (if this is a thing) for example. - // ARM9 - // TODO: +3c nonseq waitstate doesn't apply to DMA! - // but of course mainRAM always gets 8c nonseq waitstate + // TODO: check in detail how WRAM works, although it seems to be one region. // TODO: DSi-specific timings!! - SetARM9RegionTimings(0x00000000, 0xFFFFFFFF, 32, 1 + 3, 1); // void + SetARM9RegionTimings(0x00000, 0x100000, 0, 32, 1, 1); // void - SetARM9RegionTimings(0xFFFF0000, 0xFFFFFFFF, 32, 1 + 3, 1); // BIOS - SetARM9RegionTimings(0x02000000, 0x03000000, 16, 8, 1); // main RAM - SetARM9RegionTimings(0x03000000, 0x04000000, 32, 1 + 3, 1); // ARM9/shared WRAM - SetARM9RegionTimings(0x04000000, 0x05000000, 32, 1 + 3, 1); // IO - SetARM9RegionTimings(0x05000000, 0x06000000, 16, 1 + 3, 1); // palette - SetARM9RegionTimings(0x06000000, 0x07000000, 16, 1 + 3, 1); // VRAM - SetARM9RegionTimings(0x07000000, 0x08000000, 32, 1 + 3, 1); // OAM + SetARM9RegionTimings(0xFFFF0, 0x100000, Mem9_BIOS, 32, 1, 1); // BIOS + SetARM9RegionTimings(0x02000, 0x03000, Mem9_MainRAM, 16, 8, 1); // main RAM + SetARM9RegionTimings(0x03000, 0x04000, Mem9_WRAM, 32, 1, 1); // ARM9/shared WRAM + SetARM9RegionTimings(0x04000, 0x05000, Mem9_IO, 32, 1, 1); // IO + SetARM9RegionTimings(0x05000, 0x06000, Mem9_Pal, 16, 1, 1); // palette + SetARM9RegionTimings(0x06000, 0x07000, Mem9_VRAM, 16, 1, 1); // VRAM + SetARM9RegionTimings(0x07000, 0x08000, Mem9_OAM, 32, 1, 1); // OAM // ARM7 - SetARM7RegionTimings(0x00000000, 0xFFFFFFFF, 32, 1, 1); // void + SetARM7RegionTimings(0x00000, 0x100000, 0, 32, 1, 1); // void - SetARM7RegionTimings(0x00000000, 0x00010000, 32, 1, 1); // BIOS - SetARM7RegionTimings(0x02000000, 0x03000000, 16, 8, 1); // main RAM - SetARM7RegionTimings(0x03000000, 0x04000000, 32, 1, 1); // ARM7/shared WRAM - SetARM7RegionTimings(0x04000000, 0x04800000, 32, 1, 1); // IO - SetARM7RegionTimings(0x06000000, 0x07000000, 16, 1, 1); // ARM7 VRAM + SetARM7RegionTimings(0x00000, 0x00010, Mem7_BIOS, 32, 1, 1); // BIOS + SetARM7RegionTimings(0x02000, 0x03000, Mem7_MainRAM, 16, 8, 1); // main RAM + SetARM7RegionTimings(0x03000, 0x04000, Mem7_WRAM, 32, 1, 1); // ARM7/shared WRAM + SetARM7RegionTimings(0x04000, 0x04800, Mem7_IO, 32, 1, 1); // IO + SetARM7RegionTimings(0x06000, 0x07000, Mem7_VRAM, 16, 1, 1); // ARM7 VRAM // handled later: GBA slot, wifi } @@ -1242,8 +1253,8 @@ void SetWifiWaitCnt(u16 val) WifiWaitCnt = val; const int ntimings[4] = {10, 8, 6, 18}; - SetARM7RegionTimings(0x04800000, 0x04808000, 16, ntimings[val & 0x3], (val & 0x4) ? 4 : 6); - SetARM7RegionTimings(0x04808000, 0x04810000, 16, ntimings[(val>>3) & 0x3], (val & 0x20) ? 4 : 10); + SetARM7RegionTimings(0x04800, 0x04808, Mem7_Wifi0, 16, ntimings[val & 0x3], (val & 0x4) ? 4 : 6); + SetARM7RegionTimings(0x04808, 0x04810, Mem7_Wifi1, 16, ntimings[(val>>3) & 0x3], (val & 0x20) ? 4 : 10); } void SetGBASlotTimings() @@ -1251,31 +1262,36 @@ void SetGBASlotTimings() const int ntimings[4] = {10, 8, 6, 18}; const u16 openbus[4] = {0xFE08, 0x0000, 0x0000, 0xFFFF}; - u16 curcnt; - int ramN, romN, romS; + u16 curcpu = (ExMemCnt[0] >> 7) & 0x1; + u16 curcnt = ExMemCnt[curcpu]; + int ramN = ntimings[curcnt & 0x3]; + int romN = ntimings[(curcnt>>2) & 0x3]; + int romS = (curcnt & 0x10) ? 4 : 6; - curcnt = ExMemCnt[0]; - ramN = ntimings[curcnt & 0x3]; - romN = ntimings[(curcnt>>2) & 0x3]; - romS = (curcnt & 0x10) ? 4 : 6; + // GBA slot timings only apply on the selected side - SetARM9RegionTimings(0x08000000, 0x0A000000, 16, romN + 3, romS); - SetARM9RegionTimings(0x0A000000, 0x0B000000, 8, ramN + 3, ramN); + if (curcpu == 0) + { + SetARM9RegionTimings(0x08000, 0x0A000, Mem9_GBAROM, 16, romN, romS); + SetARM9RegionTimings(0x0A000, 0x0B000, Mem9_GBARAM, 8, ramN, ramN); - curcnt = ExMemCnt[1]; - ramN = ntimings[curcnt & 0x3]; - romN = ntimings[(curcnt>>2) & 0x3]; - romS = (curcnt & 0x10) ? 4 : 6; + SetARM7RegionTimings(0x08000, 0x0A000, 0, 32, 1, 1); + SetARM7RegionTimings(0x0A000, 0x0B000, 0, 32, 1, 1); + } + else + { + SetARM9RegionTimings(0x08000, 0x0A000, 0, 32, 1, 1); + SetARM9RegionTimings(0x0A000, 0x0B000, 0, 32, 1, 1); - SetARM7RegionTimings(0x08000000, 0x0A000000, 16, romN, romS); - SetARM7RegionTimings(0x0A000000, 0x0B000000, 8, ramN, ramN); + SetARM7RegionTimings(0x08000, 0x0A000, Mem7_GBAROM, 16, romN, romS); + SetARM7RegionTimings(0x0A000, 0x0B000, Mem7_GBARAM, 8, ramN, ramN); + } // this open-bus implementation is a rough way of simulating the way values // lingering on the bus decay after a while, which is visible at higher waitstates // for example, the Cartridge Construction Kit relies on this to determine that // the GBA slot is empty - curcnt = ExMemCnt[(ExMemCnt[0]>>7) & 0x1]; GBACart::SetOpenBusDecay(openbus[(curcnt>>2) & 0x3]); } @@ -1556,10 +1572,7 @@ void RunTimer(u32 tid, s32 cycles) { Timer* timer = &Timers[tid]; - u32 oldcount = timer->Counter; timer->Counter += (cycles << timer->CycleShift); - //if (timer->Counter < oldcount) - // HandleTimerOverflow(tid); while (timer->Counter >> 26) { timer->Counter -= (1 << 26); @@ -1585,6 +1598,38 @@ void RunTimers(u32 cpu) TimerTimestamp[cpu] += cycles; } +const s32 TimerPrescaler[4] = {0, 6, 8, 10}; + +u16 TimerGetCounter(u32 timer) +{ + RunTimers(timer>>2); + u32 ret = Timers[timer].Counter; + + return ret >> 10; +} + +void TimerStart(u32 id, u16 cnt) +{ + Timer* timer = &Timers[id]; + u16 curstart = timer->Cnt & (1<<7); + u16 newstart = cnt & (1<<7); + + RunTimers(id>>2); + + timer->Cnt = cnt; + timer->CycleShift = 10 - TimerPrescaler[cnt & 0x03]; + + if ((!curstart) && newstart) + { + timer->Counter = timer->Reload << 10; + } + + if ((cnt & 0x84) == 0x80) + TimerCheckMask[id>>2] |= 0x01 << (id&0x3); + else + TimerCheckMask[id>>2] &= ~(0x01 << (id&0x3)); +} + // matching NDMA modes for DSi @@ -1673,55 +1718,6 @@ void StopDMAs(u32 cpu, u32 mode) - -const s32 TimerPrescaler[4] = {0, 6, 8, 10}; - -u16 TimerGetCounter(u32 timer) -{ - RunTimers(timer>>2); - u32 ret = Timers[timer].Counter; - - return ret >> 10; -} - -void TimerStart(u32 id, u16 cnt) -{ - Timer* timer = &Timers[id]; - u16 curstart = timer->Cnt & (1<<7); - u16 newstart = cnt & (1<<7); - - timer->Cnt = cnt; - timer->CycleShift = 10 - TimerPrescaler[cnt & 0x03]; - - if ((!curstart) && newstart) - { - timer->Counter = timer->Reload << 10; - - /*if ((cnt & 0x84) == 0x80) - { - u32 delay = (0x10000 - timer->Reload) << TimerPrescaler[cnt & 0x03]; - printf("timer%d IRQ: start %d, reload=%04X cnt=%08X\n", id, delay, timer->Reload, timer->Counter); - CancelEvent(Event_TimerIRQ_0 + id); - ScheduleEvent(Event_TimerIRQ_0 + id, false, delay, HandleTimerOverflow, id); - }*/ - } - - if ((cnt & 0x84) == 0x80) - { - u32 tmask; - //if ((cnt & 0x03) == 0) - tmask = 0x01 << (id&0x3); - //else - // tmask = 0x10 << (id&0x3); - - TimerCheckMask[id>>2] |= tmask; - } - else - TimerCheckMask[id>>2] &= ~(0x11 << (id&0x3)); -} - - - void DivDone(u32 param) { DivCnt &= ~0xC000; @@ -2014,7 +2010,7 @@ u16 ARM9Read16(u32 addr) (GBACart::SRAMRead(addr+1) << 8); } - if (addr) printf("unknown arm9 read16 %08X %08X\n", addr, ARM9->R[15]); + //if (addr) printf("unknown arm9 read16 %08X %08X\n", addr, ARM9->R[15]); return 0; } @@ -2075,7 +2071,7 @@ u32 ARM9Read32(u32 addr) (GBACart::SRAMRead(addr+3) << 24); } - printf("unknown arm9 read32 %08X | %08X %08X\n", addr, ARM9->R[15], ARM9->R[12]); + //printf("unknown arm9 read32 %08X | %08X %08X\n", addr, ARM9->R[15], ARM9->R[12]); return 0; } @@ -2183,7 +2179,7 @@ void ARM9Write16(u32 addr, u16 val) return; } - if (addr) printf("unknown arm9 write16 %08X %04X\n", addr, val); + //if (addr) printf("unknown arm9 write16 %08X %04X\n", addr, val); } void ARM9Write32(u32 addr, u32 val) @@ -2250,7 +2246,7 @@ void ARM9Write32(u32 addr, u32 val) return; } - printf("unknown arm9 write32 %08X %08X | %08X\n", addr, val, ARM9->R[15]); + //printf("unknown arm9 write32 %08X %08X | %08X\n", addr, val, ARM9->R[15]); } bool ARM9GetMemRegion(u32 addr, bool write, MemRegion* region) diff --git a/src/NDS.h b/src/NDS.h index 3e7f2b70..33063c13 100644 --- a/src/NDS.h +++ b/src/NDS.h @@ -129,6 +129,33 @@ struct Timer u32 CycleShift; }; +enum +{ + Mem9_ITCM = 0x00000001, + Mem9_DTCM = 0x00000002, + Mem9_BIOS = 0x00000004, + Mem9_MainRAM = 0x00000008, + Mem9_WRAM = 0x00000010, + Mem9_IO = 0x00000020, + Mem9_Pal = 0x00000040, + Mem9_OAM = 0x00000080, + Mem9_VRAM = 0x00000100, + Mem9_GBAROM = 0x00020000, + Mem9_GBARAM = 0x00040000, + + Mem7_BIOS = 0x00000001, + Mem7_MainRAM = 0x00000002, + Mem7_WRAM = 0x00000004, + Mem7_IO = 0x00000008, + Mem7_Wifi0 = 0x00000010, + Mem7_Wifi1 = 0x00000020, + Mem7_VRAM = 0x00000040, + Mem7_GBAROM = 0x00000100, + Mem7_GBARAM = 0x00000200, + + // TODO: add DSi regions! +}; + struct MemRegion { u8* Mem; @@ -138,8 +165,10 @@ struct MemRegion extern int ConsoleType; extern int CurCPU; -extern u8 ARM9MemTimings[0x40000][4]; +extern u8 ARM9MemTimings[0x40000][8]; +extern u32 ARM9Regions[0x40000]; extern u8 ARM7MemTimings[0x20000][4]; +extern u32 ARM7Regions[0x20000]; extern u32 NumFrames; extern u32 NumLagFrames; @@ -191,8 +220,8 @@ void Stop(); 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); +void SetARM9RegionTimings(u32 addrstart, u32 addrend, u32 region, int buswidth, int nonseq, int seq); +void SetARM7RegionTimings(u32 addrstart, u32 addrend, u32 region, int buswidth, int nonseq, int seq); // 0=DS 1=DSi void SetConsoleType(int type);