Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

libnds - Fix swiSoftReset for DSi #254

Open
Lorenzooone opened this issue Jan 6, 2025 · 4 comments
Open

libnds - Fix swiSoftReset for DSi #254

Lorenzooone opened this issue Jan 6, 2025 · 4 comments
Labels
bug Something isn't working

Comments

@Lorenzooone
Copy link

Making the issue here, since libnds has issues blocked.
Hope it's fine!

Right now, swiSoftReset calls the corresponding swi. While this is fine on DSs, on DSis this results in hanging.
This function is also called from other pieces of code, like ResetARM7. So it's not just about telling the user not to use it on DSis.

@AntonioND
Copy link
Member

Is this even fixable? That swi is just not available on DSi according to GBATEK: https://problemkaputt.de/gbatek.htm#biosresetfunctions

Compare it to https://problemkaputt.de/gbatek.htm#biosmemorycopy with DSi7 and DSi9 in the list of supported platforms.

@AntonioND AntonioND added the bug Something isn't working label Jan 6, 2025
@Lorenzooone
Copy link
Author

The fix would be using this https://github.com/blocksds/libnds/blob/master/source/common/swiSoftReset.s when a DSi is detected.

@AntonioND
Copy link
Member

AntonioND commented Jan 8, 2025

Funnily enough, this used to be correct. It was broken during a patch to optimize swi calls: blocksds/libnds@23a669f

I've created this PR to revert the change to swiSoftReset() blocksds/libnds#153, but now I just get a guru meditation error when attempting an exit to loader on DSi. The address falls outside of what I get with objdump, so I guess the issue is in nds-hb-menu?

On the other hand, this explains #10.

Note that exit to loader still works on NDS as usual.

@AntonioND
Copy link
Member

The main issue I see is that the libnds implementation of swiSoftReset() doesn't actually do the same things as GBATEK says the BIOS does: https://problemkaputt.de/gbatek.htm#biosresetfunctions It doesn't clear any RAM or set any register. I need to see how the code works in nds-hb-menu in the exit hooks.

SWI 00h (GBA/NDS7/NDS9) - SoftReset

Clears 200h bytes of RAM (containing stacks, and BIOS IRQ vector/flags), initializes system, supervisor, and irq stack pointers, sets R0-R12, LR_svc, SPSR_svc, LR_irq, and SPSR_irq to zero, and enters system mode.
Note that the NDS9 stack registers are hardcoded (the DTCM base should be set to the default setting of 0800000h). The NDS9 function additionally flushes caches and write buffer, and sets the CP15 control register to 12078h.

 Host  sp_svc    sp_irq    sp_sys    zerofilled area       return address
 GBA   3007FE0h  3007FA0h  3007F00h  [3007E00h..3007FFFh]  Flag[3007FFAh]
 NDS7  380FFDCh  380FFB0h  380FF00h  [380FE00h..380FFFFh]  Addr[27FFE34h]
 NDS9  0803FC0h  0803FA0h  0803EC0h  [DTCM+3E00h..3FFFh]   Addr[27FFE24h]

The NDS7/NDS9 return addresses at [27FFE34h/27FFE24h] are usually containing copies of Cartridge Header [034h/024h] entry points, which may select ARM/THUMB state via bit0. The GBA return address 8bit flag is interpreted as 00h=8000000h (ROM), or 01h-FFh=2000000h (RAM), entered in ARM state.

Note: The reset is applied only to the CPU that has executed the SWI (ie. on the NDS, the other CPU will remain unaffected).

Return: Does not return to calling procedure, instead, loads the above return address into R14, and then jumps to that address by a "BX R14" opcode.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants