News:

11 March 2016 - Forum Rules

Main Menu

Handling NDS File Load at the ASM level?

Started by Xenesis, December 07, 2014, 09:22:22 PM

Previous topic - Next topic

Xenesis

So, I'm working on adding extra files loaded to an NDS game, but the game itself has an incredibly hacky file handler with a ton of hardcoded associations, so it hasn't been particularly easy to hijack those to load files of my own.

As such, I was basically trying to plop one together for my own use in as few ARM opcodes as possible to deal with the problem (which hopefully will be more generalised and less hacky) but I am not really good at understanding how to manipulate IRQs and the like and finding detailed information on how to manage this (compared to just using the NDS SDK) is rather sparse.

Trying to work this out my understanding of how to do a gamecart read is:

Write to 40001A0h (SPI I/O)
Write to 40001A8h with a "Read KEY2 Data" command (B7 + ROM Address of data)
Write to 40001A4h to specify data size/tell it to prepare data transfer
Write to 40001A2h with a value of 0x0 to initiate Data Transfer

Loop:
Check 40001A4h (Cartridge Control I/0) to determine Block Ready
Read the data stream from 4100010h

Clear the hold bit at 40001A0h
Transfer the last four bytes from 4100010h


I figure it's a touch more complicated than that, but I need help understanding the process and poking around with a debugger with the game's original FIFO isn't really helping...

henke37

Strange, pretty much all ds games use the provided runtime that includes easy to use file I/O functionality.

Anyway, which game in question are you talking about?

FAST6191

Hmm, there are plenty of games, including several Nintendo first party with NSMB being one of the more notable, that use file order/fileID rather than general names (in SDK parlance I think it was the fast file open function rather than standard file open and tends to see ndstool* rebuilt stuff break, hence tools like Nitro Explorer), and a few libraries (most notably the rad video one) do their own file handling, however I have not really heard of one described like that before. Mind you most people do not tend to investigate the file handler at any real level**, and if this is a Lua using/interpreted language game or one of those games that have their own archive format/filesystem on top of the standard one then who knows.
If it is just that hardcoded ID stuff then I would say pick a tool like Nitro Explorer and spare yourself the aggravation of doing things here.

*so ndstool, dslazy, dsbuff and possibly crystaltile2's rebuild functionality.

**realistically the only people that ever would have would have been those hacking DS games to work on GBA slot/slot 2 flash carts (so later 2009 for the very last stuff people did), and as those never quite got around to sorting the rad video using games then even there they might have been lacking a bit.

Afraid the only time I looked into these in depth was when we did not have a good DLDI based ROM dumper (so possibly 2006 or at latest early 2007) as the few occasions I do proper tracing work I tend to have the in game handler work well enough for my needs. I have done plenty with the DS file system itself, up to and including thinking about abusing the overlay system as a kind of file loader, but not really the hardware side of things so I would just be reading gbatek back to you at this point.

Depending upon what you are doing you might get something from https://github.com/Dirbaio/NSMBCR/tree/master/source , particularly https://github.com/Dirbaio/NSMBCR/blob/master/source/soundThread.cpp and https://github.com/Dirbaio/NSMBCR/blob/master/source/wavplayer.cpp and you will also want to read http://nsmbhd.net/thread/1281-how-asm-hacks-are-setup-tutorial/
The idea was that as the nitroSDK for the DS would remove library functionality if it was not used (in this case wave like strm support) if the game did not use it then Dirbaio added back in some wave streaming support. However that ends up compiled at some level so not ideal by any means.

Also are you using the file system or sitting outside it? If you are going outside it then I would say make sure to change the size value in the header just in case someone tries to trim the patched ROM. I know they shouldn't do it but for the sake of changing a couple of bytes in a known location...

Xenesis

Quote from: henke37 on December 08, 2014, 06:50:37 AM
Strange, pretty much all ds games use the provided runtime that includes easy to use file I/O functionality.

Anyway, which game in question are you talking about?

Advance Wars: Dual Strike. I wouldn't say "easy to use" would be the case here - it uses all three kinds of file access for the file I/O (Direct ROM offsets, File ID and Filename) interchangably and I haven't managed to grok how to sensibly exploit it without getting the game's internal FIFO to hang.

Quote from: FAST6191 on December 08, 2014, 07:23:11 AM
Hmm, there are plenty of games, including several Nintendo first party with NSMB being one of the more notable, that use file order/fileID rather than general names (in SDK parlance I think it was the fast file open function rather than standard file open and tends to see ndstool* rebuilt stuff break, hence tools like Nitro Explorer), and a few libraries (most notably the rad video one) do their own file handling, however I have not really heard of one described like that before. Mind you most people do not tend to investigate the file handler at any real level**, and if this is a Lua using/interpreted language game or one of those games that have their own archive format/filesystem on top of the standard one then who knows.
If it is just that hardcoded ID stuff then I would say pick a tool like Nitro Explorer and spare yourself the aggravation of doing things here.

*so ndstool, dslazy, dsbuff and possibly crystaltile2's rebuild functionality.

**realistically the only people that ever would have would have been those hacking DS games to work on GBA slot/slot 2 flash carts (so later 2009 for the very last stuff people did), and as those never quite got around to sorting the rad video using games then even there they might have been lacking a bit.

Afraid the only time I looked into these in depth was when we did not have a good DLDI based ROM dumper (so possibly 2006 or at latest early 2007) as the few occasions I do proper tracing work I tend to have the in game handler work well enough for my needs. I have done plenty with the DS file system itself, up to and including thinking about abusing the overlay system as a kind of file loader, but not really the hardware side of things so I would just be reading gbatek back to you at this point.

Depending upon what you are doing you might get something from https://github.com/Dirbaio/NSMBCR/tree/master/source , particularly https://github.com/Dirbaio/NSMBCR/blob/master/source/soundThread.cpp and https://github.com/Dirbaio/NSMBCR/blob/master/source/wavplayer.cpp and you will also want to read http://nsmbhd.net/thread/1281-how-asm-hacks-are-setup-tutorial/
The idea was that as the nitroSDK for the DS would remove library functionality if it was not used (in this case wave like strm support) if the game did not use it then Dirbaio added back in some wave streaming support. However that ends up compiled at some level so not ideal by any means.

Also are you using the file system or sitting outside it? If you are going outside it then I would say make sure to change the size value in the header just in case someone tries to trim the patched ROM. I know they shouldn't do it but for the sake of changing a couple of bytes in a known location...

Plan is to mostly exploit the file system, add bits to it if I have to. The data organisation in the game is terrible - things like map data is all stuffed into a single overlay rather than using a dynamic file load like they figured out how to do in the sequel, but obvious places for ASM expansion code are trimmed fairly tight, with the ARM9.bin and such trimmed to have ~200 bytes of wiggle room.

Rebuilding the filesystem in other ways is probably a good idea, but it doesn't really give me much flexibility in loading up more space so that I can add new ARM code to the game. I'll have a look at your links though.

FAST6191

Heh, never seen a non homebrew title have hardcoded ROM addresses before. Reads are certainly done that way but usually only after reading a header value/archive type setup to generate the required values for such a read.

henke37


Xenesis

Quote from: henke37 on December 08, 2014, 11:30:11 AM
Overlays are dynamically loaded.

Yeah, but AWDS uses two of the overlays as static files and has the entirety of the game's supporting data in it (stuff like maps, TSA, etc.) loaded on boot and remains in a static location in RAM.

It's best to think of it as a GBA game stuffed in an NDS wrapper :P

FAST6191

Could be worse; Rockman EXE OSS has everything in overlays and there 1114 of them.

Xenesis

Not the solution I wanted (which was dynamic file loading using the file system), but it'll work for now:

Discovered that the boot up sequence loads Overlay0 -> Overlay4, then reloads Overlay0 at the same RAM address (and is quite redundant because of it)

Overlay4 happens to be ~100kb, while Overlay0 is ~650 kb.
Expanded Overlay4 in the arm9ovltable.bin and appended it to the file.

Captured the return function from the FIFO with a conditional branch that will only work the moment Overlay4 has loaded.
Copy the extra overlay data to free areas of RAM.

Wahoo. I've now got ~300kb of RAM to play around with for ASM code. Won't be much if I start going graphics crazy, but that has its own problems and solutions.