Views: 23,259,279 | Homepage | Main | Rules/FAQ | Memberlist | Active users | Last posts | Calendar | Stats | Online users | Search | 12-04-24 10:40 PM |
Guest: |
0 users reading the DSi RAM size shitshow | 1 bot |
Main - Development - the DSi RAM size shitshow | Hide post layouts | New reply |
Arisotura |
| ||
Big fire melon magical melon girl Level: 58 Posts: 763/945 EXP: 1539610 Next: 37936 Since: 03-28-17 From: France Last post: 34 days ago Last view: 18 min. ago |
basically: melonDS doesn't currently emulate the DSi RAM size setting. the use is restricting the RAM to 4MB when running DS games.
thing is: in melonDS, the ARM9 changes the RAM size while the ARM7 is still busy clearing RAM, causing the ARM9 code to be erased -- you guess how this goes. I replicated the code doing all that, and played around with it. observations: * when changed, the new RAM size reflects instantly on the ARM7 side. * seems to be some weird timing issue -- on hardware, the ARM7 actually has the time to do all its RAM clearing work and wait for VCount to be 0 before the RAM size will be changed. but, that's the thing -- the ARM7 has a bunch of memory regions to clear/relocate, mostly in main RAM. in comparison, the ARM9 has nothing to do beyond clearing its DTCM, which should be quick. I don't see how the ARM9 can take so long (or the ARM7 be so quick). ____________________ Kuribo64 |
Generic aka RSDuck |
| ||
Big fire melon Administrator Level: 45 Posts: 403/610 EXP: 653294 Next: 6870 Since: 10-12-19 Last post: 63 days ago Last view: 1 day ago |
Posted by Arisotura what about icache? Shouldn't that allow the ARM9 to continue running? ____________________ Take me to your heart / never let me go! "clearly you need to mow more lawns and buy a better pc" - Hydr8gon |
Arisotura |
| ||
Big fire melon magical melon girl Level: 58 Posts: 764/945 EXP: 1539610 Next: 37936 Since: 03-28-17 From: France Last post: 34 days ago Last view: 18 min. ago |
Generic aka RSDuck |
| ||
Big fire melon Administrator Level: 45 Posts: 404/610 EXP: 653294 Next: 6870 Since: 10-12-19 Last post: 63 days ago Last view: 1 day ago |
Posted by Arisotura well then shouldn't the execution from uncached main ram be incredibly slow for the ARM9? ____________________ Take me to your heart / never let me go! "clearly you need to mow more lawns and buy a better pc" - Hydr8gon |
Arisotura |
| ||
Big fire melon magical melon girl Level: 58 Posts: 765/945 EXP: 1539610 Next: 37936 Since: 03-28-17 From: France Last post: 34 days ago Last view: 18 min. ago |
it would be, but the ARM9 hardly does any task besides clearing its ITCM. by comparison, the ARM7 clears a whole bunch of the main RAM, so it should take much more time to complete its task. ____________________ Kuribo64 |
Arisotura |
| ||
Big fire melon magical melon girl Level: 58 Posts: 768/945 EXP: 1539610 Next: 37936 Since: 03-28-17 From: France Last post: 34 days ago Last view: 18 min. ago |
according to my observations: the ARM9 is running abysmally slow due to concurrent mainRAM access from the ARM7 (removing the ARM7-side memory clearing makes it have timing much closer to that of melonDS).
that's super shitty. actual data: ARM9 takes 5230691 cycles, from the beginning of its part to the moment the RAM size register is changed. ARM7 takes 6764360 cycles to complete its RAM relocating/clearing. ARM9 completes the same workload in 66266 cycles if the ARM7 isn't clearing RAM. timings are as such because EXMEMCNT is configured as to give mainRAM priority to the ARM7. giving priority to the ARM9 causes it to crash, and, if the RAM size change is removed, ARM9 takes 47825 cycles and ARM7 takes a whopping 37908444 cycles. ____________________ Kuribo64 |
Mighy Max |
| ||
Member Normal user Level: 7 Posts: 8/10 EXP: 1116 Next: 332 Since: 07-08-21 Last post: 322 days ago Last view: 322 days ago |
This seems really like a bug in the boot code.
The following is my try of reversing that part I did a while ago. Between IPC Sync Value 5 and 0 is the part that gives you the problem. There is no sync/barrier between the mem access and the SCFG write. The memory regions used are passed from the actual app/stage2 while the boot relict code seems to be SDK code, as it is also present in (some?) other apps. Imho there are two options here: have the timings correct, or patch the loader. Both have some serious issues: the timings will vary often until melonDS is mature. It will repeat to break within the development process. Patching the laoder does not reflect the actual console and its code, so the console and melon would move a step apart and detecting the boot relict code is tricky, as it might be used in multiple apps and might appear in different versions. oid bootClearMemory(uint32_t *target, uint32_t length) ;
void bootClearMemoryListEntries(uint32_t *memoryList) ; void bootSimpleCopy(uint32_t *source, uint32_t *target, uint32_t count) ; void bootReverseCopy(uint32_t *source, uint32_t *target, uint32_t count) ; typedef void (*ARM9BOOTFUNC)(void) ; void bootBootRelictCode(SBOOTCONFIG *cfg, uint32_t *memoryList, uint32_t memoryListLength, uint32_t stackPtr) { bootReverseCopy((uint32_t *)cfg, (uint32_t *)(stackPtr - 0x110), 0xe0) ; SBOOTCONFIG *cfgCopy = (SBOOTCONFIG *)(stackPtr - 0x110) ; /* sync with arm7 */ WaitForIPCSyncValue(4) ; SetIPCSyncValue(4) ; /* copy list of memory to be cleared to the new stack */ bootReverseCopy(memoryList, (uint32_t *)(stackPtr + 0x110), memoryListLength) ; bootClearMemoryListEntries(memoryList) ; /* wait for arm7 to complete memory clear up */ WaitForIPCSyncValue(5) ; /* Set up new WRAM Settings */ if (cfgCopy->wramFlag != 0) { bootSimpleCopy(cfgCopy->wramSettings, (uint32_t *)0x04004040, sizeof(cfgCopy->wramSettings)) ; *(volatile uint8_t *)0x4000247 = *(uint8_t *)(cfgCopy->wramCnt >> 24) & 3 ; } /* tell arm7 we set up the wram */ SetIPCSyncValue(5) ; ARM9BOOTFUNC arm9boot = *(ARM9BOOTFUNC *)(cfgCopy->entry) ; uint32_t targetScfgExt = cfgCopy->sfcg_ext ; bool setSCFG = !((cfgCopy->unknown_04 | cfgCopy->unknown_08) & 0x80000000) ; // TODO (or not) the memory list are actually 4 consequtive lists terminated with 0 // the first is only used. // the second list is used for copying data blocks from start to end // the third list is used for copying data blocks from end to start // and the lsit is to clear again // Since the memory list is hardcoded in the calling method, we know that // the last 3 lists are never used so we skip it // clear the bootloader stack bootClearMemory((uint32_t *)0x02fe0000, 0x3fc0) ; // Clear the memory of that list too and the cfgCopy bootClearMemory((uint32_t *)(stackPtr - (0x110 + memoryListLength)), 0x110 + memoryListLength) ; if (setSCFG) { *(volatile uint32_t *)0x04004008 = targetScfgExt ; } /* sync with arm7 */ WaitForIPCSyncValue(0) ; SetIPCSyncValue(0) ; /* start new code or die! */ if (arm9boot != 0) arm9boot() ; while (true) ; } void bootSimpleCopy(uint32_t *source, uint32_t *target, uint32_t count) { uint32_t *end = target + count / 4; while (target < end) { *(target++) = *(source++) ; } } void bootReverseCopy(uint32_t *source, uint32_t *target, uint32_t count) { uint32_t *curTarget = target + count / 4 ; uint32_t *curSource = source + count / 4; while (target < curTarget) { *(--curTarget) = *(--curSource) ; } } void bootClearMemory(uint32_t *target, uint32_t length) { while (length >= 4) { *(target++) = 0 ; length -= 4 ; } } void bootClearMemoryListEntries(uint32_t *memoryList) { while (true) { if (!*memoryList) break; bootClearMemory((uint32_t *)(memoryList[0]), memoryList[1]) ; memoryList += 2 ; } } Below is the code for the arm7 at the same time between ipc 5 and 0 (out of ghidra): 037b84b8 05 00 a0 e3 mov r0,#0x5 037b84bc 54 00 00 eb bl SetIPCSyncValue_1 undefined SetIPCSyncValue_1() 037b84c0 58 00 00 eb bl WaitForIPCSyncValue_1 undefined WaitForIPCSyncValue_1() 037b84c4 00 00 58 e3 cmp r8,#0x0 037b84c8 40 00 8b 12 addne r0,r11,#0x40 037b84cc 54 10 87 12 addne r1,r7,#0x54 037b84d0 10 20 a0 13 movne r2,#0x10 037b84d4 1d 00 00 1b blne bootSimpleCopy undefined bootSimpleCopy() 037b84d8 40 0f 9b e8 ldmia r11,{r6 r8 r9 r10 r11} 037b84dc 0a a0 89 e1 orr r10,r9,r10 LAB_037b84e0 XREF[1]: 037b84ec(j) 037b84e0 45 00 00 eb bl bootGetMemoryListEntry undefined bootGetMemoryListEntry() 037b84e4 01 00 00 0a beq LAB_037b84f0 037b84e8 18 00 00 eb bl bootSimpleCopy undefined bootSimpleCopy() 037b84ec fb ff ff ea b LAB_037b84e0 LAB_037b84f0 XREF[2]: 037b84e4(j), 037b84fc(j) 037b84f0 41 00 00 eb bl bootGetMemoryListEntry undefined bootGetMemoryListEntry() 037b84f4 01 00 00 0a beq LAB_037b8500 037b84f8 1a 00 00 eb bl bootReverseCopy undefined bootReverseCopy() 037b84fc fb ff ff ea b LAB_037b84f0 LAB_037b8500 XREF[1]: 037b84f4(j) 037b8500 35 00 00 eb bl FUN_037b85dc undefined FUN_037b85dc() 037b8504 05 10 4d e0 sub r1,sp,r5 037b8508 05 20 a0 e1 cpy r2,r5 037b850c 1d 00 00 eb bl bootClearMemory undefined bootClearMemory() 037b8510 00 00 a0 e3 mov r0,#0x0 037b8514 3e 00 00 eb bl SetIPCSyncValue_1 undefined SetIPCSyncValue_1() |
Main - Development - the DSi RAM size shitshow | Hide post layouts | New reply |
Page rendered in 0.069 seconds. (2048KB of memory used) MySQL - queries: 30, rows: 91/91, time: 0.033 seconds. Acmlmboard 2.064 (2018-07-20) © 2005-2008 Acmlm, Xkeeper, blackhole89 et al. |