Register - Login
Views: 99794023
Main - Memberlist - Active users - Calendar - Wiki - IRC Chat - Online users
Ranks - Rules/FAQ - Stats - Latest Posts - Color Chart - Smilies
05-03-22 05:09:09 AM
Jul - General Game/ROM Hacking - DS debugging/reverse engineering/whatever you call it New poll - New thread - New reply
Pages: 1 2Next newer thread | Next older thread
Ninji

Birdo
Why did my user title say I'm a toaster anyway
Level: 88


Posts: 196/2014
EXP: 6638525
For next: 12139

Since: 07-26-07

Pronouns: he/him or they/them
From: Glasgow, Scotland

Since last post: 113 days
Last activity: 6 days

Posted on 03-21-09 02:05:40 AM Link | Quote
This is my problem:

I want to try and figure out how NSMB loads levels and tilesets, since I can't figure out how each tileset number in the level file corresponds to each tileset file.

I could go through each tileset ID and hardcode the tileset filename, but that would be a pain, and I'm sure there must be an easier way. I've tried searching for a possible table in the ROM and the decompressed ARM9 binary which might list tileset file IDs, but got nowhere.

I've been trying to use a debugger to see if that helps - but I can't figure out how to do anything. I have No$GBA, Desmume and iDeaS. None of them help, since I don't know anything about ARM ASM, and the code is far too confusing for me to understand. Even if I knew what each instruction did - I have no way of identifying what a specific piece of code does easily.

Blackhole89 suggested that I place a Read breakpoint on the tileset area in ROM, which makes sense - but none of the emulators I've tried support this. Desmume and iDeaS both don't have breakpoints. I figured out how to place one in No$GBA after a bunch of searching in the help file but I couldn't get it to work - either I'm doing something wrong or this is just messed up.

Is there any way I could figure it out using a debugger, or using a different approach? Doing this is driving me crazy; I really want to be able to figure this out.

____________________
Ex-ex-ROM hacker. Good riddance, Mega-Moron. · Hacking Tools: Nitro Explorer · NARC Explorer
Hectamatatortron
Member
Level: 35


Posts: 119/232
EXP: 258215
For next: 21721

Since: 09-19-07


Since last post: 7.2 years
Last activity: 5.3 years

Posted on 03-21-09 10:16:13 PM Link | Quote
You think the file that's used is chosen by a number in the level data?

Wouldn't it then be easier to set a read breakpoint on that number and follow the code instead of on the data to be loaded and tracing backward?

Once you find the subroutine responsible for loading the tile sets, rewriting the assembly code in a C style format is pretty easy (if you know the instructions). If you don't, getting the disassembly to someone who does would be just as well. I've rewritten a few BIOS functions in Java myself (LZ77UnCompWram, anyone?).

____________________
Ninji

Birdo
Why did my user title say I'm a toaster anyway
Level: 88


Posts: 197/2014
EXP: 6638525
For next: 12139

Since: 07-26-07

Pronouns: he/him or they/them
From: Glasgow, Scotland

Since last post: 113 days
Last activity: 6 days

Posted on 03-21-09 11:20:24 PM Link | Quote
I tried doing this but it still didn't help. I'm not sure if I'm doing this right, but I pressed Ctrl-B and entered this: [0843fad4]? (The question mark is part of the string, not my sentence) and then ran the game and entered 1-1. I can see in the memory viewer that this offset is the one I want - but nothing happens. Changing that value in the memory viewer does affect the game, but obviously I can't get anything useful out of it..
I tried setting it to an invalid value (which usually freezes the game) to see what happened. But in the debugger all I can see is it getting stuck in an infinite loop with a bunch of crap I can't understand at all. Understanding uncommented ASM is not my strong point at all; even less so with ARM (which I have no idea about).

____________________
Ex-ex-ROM hacker. Good riddance, Mega-Moron. · Hacking Tools: Nitro Explorer · NARC Explorer
Hectamatatortron
Member
Level: 35


Posts: 120/232
EXP: 258215
For next: 21721

Since: 09-19-07


Since last post: 7.2 years
Last activity: 5.3 years

Posted on 03-22-09 06:38:04 PM Link | Quote
That doesn't look like a valid address to me.

Are you sure it's not a mirror?

When it comes to mirrors, the debugger only breaks if you specify the exact address being used to access the memory location.

This is why it's hard to get breakpoints on addresses like 0x023FFXXX - lots of games access that area with the mirror, 0x027FFXXX.

Also, I have No$GBA 2.6a debugger. No need to worry about explaining to me how breakpoints work on it.

Keep in mind that if the address you're thinking of is in the .NDS file, there's no way to set a breakpoint on reads of that data directly. The card's memory is not mapped to the hardware, it is accessed serially through I/O registers.

In other words, if you're going about this the way people would when hacking a GBA game, where you can simply add 0x08000000 to the address of a byte in the ROM to get the address you want a breakpoint of, then it's not going to work. Since the address you have looks to be in that range, I'm guessing that was your mistake.

____________________
Ninji

Birdo
Why did my user title say I'm a toaster anyway
Level: 88


Posts: 198/2014
EXP: 6638525
For next: 12139

Since: 07-26-07

Pronouns: he/him or they/them
From: Glasgow, Scotland

Since last post: 113 days
Last activity: 6 days

Posted on 03-22-09 11:01:24 PM Link | Quote
Originally posted by Hectamatatortron
That doesn't look like a valid address to me.

Are you sure it's not a mirror?

When it comes to mirrors, the debugger only breaks if you specify the exact address being used to access the memory location.

This is why it's hard to get breakpoints on addresses like 0x023FFXXX - lots of games access that area with the mirror, 0x027FFXXX.

Also, I have No$GBA 2.6a debugger. No need to worry about explaining to me how breakpoints work on it.

Keep in mind that if the address you're thinking of is in the .NDS file, there's no way to set a breakpoint on reads of that data directly. The card's memory is not mapped to the hardware, it is accessed serially through I/O registers.

In other words, if you're going about this the way people would when hacking a GBA game, where you can simply add 0x08000000 to the address of a byte in the ROM to get the address you want a breakpoint of, then it's not going to work. Since the address you have looks to be in that range, I'm guessing that was your mistake.

Yeah, it's part of the ROM. No wonder it doesn't work that way.. but otherwise, what can I do? I don't know where the level data is loaded into memory.
I thought it would be possible to do this, since the ROM shows up in the memory viewer at 0x08000000 - but it still doesn't work. Is there anything else I can do?

____________________
Ex-ex-ROM hacker. Good riddance, Mega-Moron. · Hacking Tools: Nitro Explorer · NARC Explorer
Hectamatatortron
Member
Level: 35


Posts: 121/232
EXP: 258215
For next: 21721

Since: 09-19-07


Since last post: 7.2 years
Last activity: 5.3 years

Posted on 03-23-09 02:16:22 AM (last edited by Hectamatatortron at 03-22-09 11:17 PM) Link | Quote

40001A8h - NDS7/NDS9 - Gamecard bus 8-byte Command Out
The separate commands are described in the Cartridge Protocol chapter, however, once when the BIOS boot procedure has completed, one would usually only need command "B7aaaaaaaa000000h", for reading data (usually 200h bytes) from address aaaaaaaah (which should be usually aligned by 200h).

I guess you can probably look for a place in WRAM that is a buffer for that data (the data written to 0x040001A8) holding the address of that data you found.

GBATEK has more info.

____________________
Ninji

Birdo
Why did my user title say I'm a toaster anyway
Level: 88


Posts: 199/2014
EXP: 6638525
For next: 12139

Since: 07-26-07

Pronouns: he/him or they/them
From: Glasgow, Scotland

Since last post: 113 days
Last activity: 6 days

Posted on 03-23-09 01:21:59 PM Link | Quote
I managed to find the data by creating a hexdump of the memory, using an old app I had to parse No$GBA hexdumps (I made it when I wanted to extract the decompressed ARM9 binary from memory) and searching through the result.

I have the offset of the value I need now: 0x0235fde8. But I can't figure out what to do with it.
I set a read breakpoint on that value and it stopped here:



If I run it again, that value is read several times before it finally finishes and the level loads.

I have no idea what to do - I've been trying to trace through it, but I can't figure out what the code does, or if I'm looking at it from the wrong point. This is really frustrating.

____________________
Ex-ex-ROM hacker. Good riddance, Mega-Moron. · Hacking Tools: Nitro Explorer · NARC Explorer
Hectamatatortron
Member
Level: 35


Posts: 122/232
EXP: 258215
For next: 21721

Since: 09-19-07


Since last post: 7.2 years
Last activity: 5.3 years

Posted on 03-23-09 03:13:41 PM Link | Quote
It's using the loaded data differently based on whether or not it is the string "0DMB".

If the tileset index is 0x70, then you just need to follow the code using F7 and summarize what's happening to yourself as you go.

First you want to make sure that breakpoint is the one you want.

Change R02 to other tileset values when it breaks there and see if the tileset used in the level changes as a result.

Also, ARM isn't as scary as it looks (I was afraid of it too back when I learned Thumb). It should be easy to do something like


int r0, r1, r2 /*etc.*/;



And then just do things like


r0 += r1; //add r0, r0, r1



to dump the routine. GBATEK can help with understanding the opcodes, as can watching them be executed (which is where most of my assembly knowledge came from - watching instructions being executed when stepping through code in VBA-SDL-H's console window).

____________________
Ninji

Birdo
Why did my user title say I'm a toaster anyway
Level: 88


Posts: 200/2014
EXP: 6638525
For next: 12139

Since: 07-26-07

Pronouns: he/him or they/them
From: Glasgow, Scotland

Since last post: 113 days
Last activity: 6 days

Posted on 03-23-09 05:56:33 PM Link | Quote
I didn't know you could change the registers actually; I'll try that and see if it helps.

I guess understanding ARM isn't that hard; but it looks daunting to me, considering the only ASM I know is 6502 (with basic instructions etc). I couldn't find a good doc for it; I didn't know the GBATek doc listed the ARM instructions. That will probably be helpful.

What seems to make it harder is that apparently, the level data isn't always loaded into the same location in memory. The byte I mentioned (the 70) isn't the tileset value - it's the first byte in the level file. (Or maybe I just calculated wrong originally.. since the same byte works over several level loads.)

I ended up looking for the correct byte in the memory viewer and modified the register as you suggested. I had it break 4 times on the same byte, so I tried changing each one at a time and figured out the 3rd break changes it (r0 though, not r2)

[Note this post seems rather illogical since I wrote the first paragraph before I tried anything, at this point I'm trying to translate the code]

I tried using the GBATek document to figure out the instructions, but it's rather confusing.
I remember I learned 6502 ASM with this, which describes all the instructions and addressing modes: http://www.romhacking.net/docs/%5B110%5D6502asm.htm - is there anything similar I can use for ARM?

I'm trying to figure it out by stepping through the code and seeing what each instruction does, but not everything is obvious, and I'm just taking guesswork on some parts.
Like this:

ldr r1,=20CACBCh

strh r0,[r1]
bx r14

[At 0x20BB970]
ldr r1,=208B168h
mov r0,r4
ldr r2,[r1]
add r1,r4,400h


which I'm assuming means this:

r1 = 0x20CACBC;

memory[r1] = r0; // r0 is 0x08, which is the tileset value I'm using
goto r14; // r14 is 0x20BB970; assuming that's an address, since it's nearby

offset_20BB970:
r1 = 0x208B168;
r0 = r4;
r2 = memory[r1];
r1 = r4 + 0x400; // the part for ADD on the GBATek doc was the only part I could understand


Is there anywhere I've gone wrong in that? Some other things also confuse me - why use bx instead of b, for example? The GBATek doc doesn't help much as so much of it is just abbreviations and confusing expressions which might make more sense to an experienced ARM programmer; but not to me.

____________________
Ex-ex-ROM hacker. Good riddance, Mega-Moron. · Hacking Tools: Nitro Explorer · NARC Explorer
Hectamatatortron
Member
Level: 35


Posts: 123/232
EXP: 258215
For next: 21721

Since: 09-19-07


Since last post: 7.2 years
Last activity: 5.3 years

Posted on 03-23-09 06:17:33 PM (last edited by Hectamatatortron at 03-23-09 06:13 PM) Link | Quote
bx means branch exchange. It's an absolute branch with a register argument (the b instruction is a relative branch that takes an immediate argument, not a register) that is capable of switching between ARM/Thumb mode based on bit 0 of the target address.

bx lr (r14 is called "lr", which means Link Return. bl means "branch long" and works like "b" does, but with a larger range; when an address is bl'd to, lr is updated with the address to return from the subroutine being called by the bl) is commonly used for returning from subroutines.

Also, strh stores a halfword, so in your case, it was storing 0x0008, not 0x08. ldr loads a word (0xXXXXXXXX).

It looks like you got everything commented correctly.

Also, the correct way to say that something is at a specific address is to use the .org directive.


ldr	r1	=020CACBCh	@The GNU ARM assembler uses @ for comments.

@The above line loads 0x020CACBC into register 1 in the fashion "ldr r1, [pc (pc is r15), #0x(immediate offset)]"
strh r0, [r1] @Stores lower 16 bits of r0 at the address held by r1
bx r14 @Return

.org 0x020BB970
ldr r1, =0208B168h @Should know how this works by now
mov r0, r4 @r4 is a local variable, probably one placed here by a mov r4, r0 instruction near the
@beginning of the routine, which means that it was one of the arguments of the current function being executed
ldr r2, [r1] @r2 is set equal to the 32 bits at the address held by r1
add r1, r4, 400h @r1 = r4 + 0x400, as you've noticed


I recommend improving your whitespacing of assembly code.

Edit: I've just confirmed that setting a breakpoint on reads of a ROM address is indeed possible with No$GBA if you follow the documentation I've quoted from GBATEK (written by the same person No$GBA was written by).

Set a break on writes to 0x040001A8 and use No$GBA's conditional breakpoint feature to do it something like this:

[040001A8]!!, r(some register number; you may have to try r0 through r2) == 0xB7aaaaaa

Where aaaaaa is the upper 24 bits of the address you want to watch.

After you get a hit, setting a break on reads of 0x04100010 and continuing until that breakpoint is hit will show you the data at or around your address being loaded serially (4 bytes at a time, usually in groups of 0x200 bytes).

____________________
Ninji

Birdo
Why did my user title say I'm a toaster anyway
Level: 88


Posts: 201/2014
EXP: 6638525
For next: 12139

Since: 07-26-07

Pronouns: he/him or they/them
From: Glasgow, Scotland

Since last post: 113 days
Last activity: 6 days

Posted on 03-24-09 01:33:33 AM Link | Quote
I've managed to find out where the tileset code is loaded, I think.
I've also managed to understand pretty much everything, but I don't get this, what does it mean?

ldr r0,[r0,r2,lsl 2h]



Also, just to clarify: I'm assuming that [r#] means "the value of the address in r#", and =###h means "the direct value 0x###" (forgot what it's called, but it uses that value directly, instead of doing any memory or register lookups).

This also confuses me:

ldr r1,[r13,4h]


I'm assuming it means "set r1 to the value of the address (r13 + 4)" but I wanted to double check. Thanks for all your help with this, btw.

____________________
Ex-ex-ROM hacker. Good riddance, Mega-Moron. · Hacking Tools: Nitro Explorer · NARC Explorer
Hectamatatortron
Member
Level: 35


Posts: 124/232
EXP: 258215
For next: 21721

Since: 09-19-07


Since last post: 7.2 years
Last activity: 5.3 years

Posted on 03-24-09 02:01:30 AM (last edited by Hectamatatortron at 03-23-09 11:07 PM) Link | Quote

ldr r0,[r0,r2,lsl 2h]

r0 = [r0 + (r2 << 2)]


ldr r1,[r13,4h]

r1 = [sp (aka r13; sp means "stack pointer") + 4]

This means (since it's a stack offset) that it's loading a variable from the parent function's scope that was pushed or more likely (as the former makes no sense), a local variable that there was no room for in the register list that was pushed into extra stack space also allocated at the beginning of the function, usually by way of

add sp, #-0x8
str (some register), [sp]
str (the register later loaded into r1 in your example), [sp, #0x4]

Functions that do that will have

add sp, #0x8 (or whatever the number was depending on the amount of extra space needed)

before the

ldmia/pop sp!, {rlist} (sp is implied for pop instructions)

instructions that occur before the bx lr that functions end with. These functions will probably also use lots of other registers, which means intensive calculation and/or many arguments for that sub routine.

____________________
messiaen
Catgirl
Level: 68


Posts: 523/1085
EXP: 2596316
For next: 132484

Since: 11-20-07


Since last post: 8.1 years
Last activity: 7.2 years

Posted on 03-24-09 12:01:49 PM Link | Quote
Originally posted by Hectamatatortron

ldr r0,[r0,r2,lsl 2h]

r0 = [r0 + (r2 << 2)]




I don't know any ARM, but from my experience with MIPS and assuming that pointers/integers are 32-bit, remember that in many instances leftshifts by 2 are used to access a specific entry in a (function/pointer/anything) table/array:

int *integer_table_entry = table_pointer + (argument * 4);

Once you figure out similar 'chunks' of code like this understanding the ASM will be much easier.

____________________
Mario 64 notes @ http://sites.google.com/site/messiaen64/
Hectamatatortron
Member
Level: 35


Posts: 125/232
EXP: 258215
For next: 21721

Since: 09-19-07


Since last post: 7.2 years
Last activity: 5.3 years

Posted on 03-24-09 02:23:17 PM Link | Quote
Yes, that format is generally used for accessing arrays of data that have 4 byte entries.

Another common occurrence is:

add r0, r0, r1, lsl #0x2

Where r0 is the base address of some array and r1 is the index to access it by.

For some reason it's more common even though it could have included the load operation that is sure to follow by simply using the ldr instruction.

____________________
Ninji

Birdo
Why did my user title say I'm a toaster anyway
Level: 88


Posts: 202/2014
EXP: 6638525
For next: 12139

Since: 07-26-07

Pronouns: he/him or they/them
From: Glasgow, Scotland

Since last post: 113 days
Last activity: 6 days

Posted on 03-24-09 07:08:55 PM (last edited by Treeki at 03-24-09 10:23 PM) Link | Quote
I've managed to disassemble what is pretty much an entire routine, and translate it into pseudocode. (A bunch of the comments don't make much sense since I wrote them while working through the code in the debugger.)
However I have no idea what it's supposed to do. I can figure out one thing - the jump table which runs a different function depending on the tileset number (some tilesets use the same function, or have none). But the rest doesn't make much sense.

This is my pseudocode:


offset_20B54F4: // tileset routine; called many times while loading a level, untouched otherwise

push r4,r5,r14
r13 = r13 - 4
r4 = r1
r1 = r4 + 0xC00
r1 = memory[r1 + 0x10]
r5 = r0
if (r1 < 1) goto offset_20B5520
if (r1 <= 6) {
r13 = r13 + 4
pop r4,r5,r15 // return from sub
}
offset_20B5520:
r1 = 0x20CACBC
r0 = 0xFFFF
r3 = memory[r1] // tileset value chosen here
if (r3 == r0) goto offset_20B5570 // possible error checking? tileset 0xFFFF does not crash the game, just loads no tileset
r1 = 0x20CB640 // Looks like a jump table of some sort is here
r2 = r3 << 3 // Indexing?
r0 = memory[r1 + (r3 << 3)] // Why not just do memory[r1 + r2]...
if (r0 == 0) goto offset_20B5570
r3 = r1 + r2
r1 = memory[r3 + 4]
r0 = r5 + (r1 asr 1) // sets flag which is used later I assume
if (r1 == 0) zero_flag = true
r1 = r1 & 1 // Does not set flag seeing as the instruction was "ands"
if (!zero_flag) {
r2 = memory[r0]
r1 = memory[r3]
r2 = memory[r2 + r1]
}
r1 = r4
zero_flag = (r1 == 0)
if (zero_flag) r2 = memory[r3]
call_sub r2 // Process the jump table
offset_20B5570: // If the jump table lists 0 for a specific tileset, it skips directly here
r0 = 0x2085A84 // Seems to be another jump table, how nice..
r0 = memory[r0] // wtf?
r0 = (r0 == 0) ? 0 : 1
if (r0 != 0) goto offset_20B55F4
r3 = 0x20C7818
r2 = 0
r0 = memory[r3]
r1 = 0xFFFF
r14 = r2
if (r0 == r1) goto offset_20B55E0 // Oh look! More error checking? Except I don't think 24 is the tileset
r0 = r4 + 0xC00
r12 = memory[r0 + 0x10]
offset_20B55B0:
r0 = r2 + 1
r0 = r0 << 0x10
r2 = r0 >> 0x10
r0 = r2 << 1 // ??
r0 = memory[r3 + r0]
if (r12 == r0) {
r0 = r14 + 1
r0 = r0 << 0x10
r14 = r0 >> 0x10
goto offset_20B55E0
}
if (r0 != r1) goto offset_20B55B0 // nonsensical loop
offset_20B55E0:
if (r14 == 0) goto offset_20B55F4
r0 = r5
r1 = r4
call_sub offset_20B566C
offset_20B55F4:
r0 = r4 + 0xC00
r3 = memory[r0 + 0x0A]
r1 = memory[r0 + 0x1E]
r2 = 0x20CAFE0
r4 = memory[r0 + 0x10]
r2 = memory[r2 + (r3 << 2)]
r0 = r1 << 1
memory[r4] = memory[r2 + r0]
r13 += 4
pop r4,r5,r15 // return from sub




edit:
I've solved my problem yay. I didn't figure out the code, but with the help of some other code, I found the reason I couldn't find any tables in the memory - the game was indexing files differently to my filesystem viewer. I managed to find tables for pretty much everything graphics related so now I have almost-perfect graphics support in my editor. (Well, once I fix my object rendering, that is)

____________________
Ex-ex-ROM hacker. Good riddance, Mega-Moron. · Hacking Tools: Nitro Explorer · NARC Explorer
Ninji

Birdo
Why did my user title say I'm a toaster anyway
Level: 88


Posts: 203/2014
EXP: 6638525
For next: 12139

Since: 07-26-07

Pronouns: he/him or they/them
From: Glasgow, Scotland

Since last post: 113 days
Last activity: 6 days

Posted on 03-25-09 09:19:22 AM Link | Quote
Anyway, now I have another problem. I've been trying to figure out the overworld map format.
I managed to find a table which corresponds level area IDs to the files they use and confirmed it works. But now I've been trying to find out how the map format works.

With a lot of debugging I figured out that it loads the area ID from 0x2085A94. I traced it down using breakpoints and found out it was just copied from 0x21C839E. But for some reason, breakpoints on it won't work.

It's weird because I can set a read breakpoint and it will work fine. I can set a read/write breakpoint (with !!? at the end) and it will trigger on the read - but it never triggers for writing. The level just loads by itself. I can see the value changing in the memory viewer throughout various stages in the level loading. Am I doing anything wrong or just being stupid as usual, or have I somehow found an obscure bug in the emulator?

____________________
Ex-ex-ROM hacker. Good riddance, Mega-Moron. · Hacking Tools: Nitro Explorer · NARC Explorer
Hectamatatortron
Member
Level: 35


Posts: 126/232
EXP: 258215
For next: 21721

Since: 09-19-07


Since last post: 7.2 years
Last activity: 5.3 years

Posted on 03-25-09 05:59:01 PM Link | Quote
Did I mention that if a mirror address is used for the accessing instruction that the break won't hit?

Oh, wait...yes, I did.

That's probably your problem. It could take a while to try all the mirrors. Maybe try backtracing from the read until you get to the write? That could take a while too, but you've got to do one or the other, it seems.

Pick your poison.

____________________
Ninji

Birdo
Why did my user title say I'm a toaster anyway
Level: 88


Posts: 204/2014
EXP: 6638525
For next: 12139

Since: 07-26-07

Pronouns: he/him or they/them
From: Glasgow, Scotland

Since last post: 113 days
Last activity: 6 days

Posted on 03-25-09 06:21:04 PM Link | Quote
Originally posted by Hectamatatortron
Did I mention that if a mirror address is used for the accessing instruction that the break won't hit?

Oh, wait...yes, I did.

That's probably your problem. It could take a while to try all the mirrors. Maybe try backtracing from the read until you get to the write? That could take a while too, but you've got to do one or the other, it seems.

Pick your poison.


How many mirrors would exist for that address? Time isn't really an issue.
Assuming that each mirrored area is 0x400000 (4mb; the GBATek document says this is the size of the main memory) it would make sense that these work: 0x21C839E, 0x25C839E, 0x29C839E, 0x2DC839E - but none of those trigger a read breakpoint either. Unless there are more mirrors I'm missing..

____________________
My most sincere excuses for all my bullshit to you. -- Mega-Moron · Hacking Tools: Nitro Explorer · NARC Explorer
Hectamatatortron
Member
Level: 35


Posts: 127/232
EXP: 258215
For next: 21721

Since: 09-19-07


Since last post: 7.2 years
Last activity: 5.3 years

Posted on 03-25-09 10:39:58 PM (last edited by Hectamatatortron at 03-25-09 07:42 PM) Link | Quote
I did say that was "probably" your problem.

Try the other way (backtracing).

Unless I have my hands on it, I won't know how to fuck with it to get what I want.

That's what you have to do sometimes. Just keep picking at things remotely relevant until you either think of something you wish you had thought of earlier or find a hint.

Edit: Try word aligned addresses (address & 0xFFFFFFFC); I was trying to emphasize before that word accesses of halfwords and similar situations are the leading cause of grief when it comes to the incapacity No$GBA has of breaking on mirrors, which is caused by the same problem (the access address has to match precisely).

____________________
Deleted User
Collection of nobodies
Posted on 04-02-09 01:38:39 PM Link | Quote
Originally posted by Treeki
...
edit:
I've solved my problem yay. I didn't figure out the code, but with the help of some other code, I found the reason I couldn't find any tables in the memory - the game was indexing files differently to my filesystem viewer. I managed to find tables for pretty much everything graphics related so now I have almost-perfect graphics support in my editor. (Well, once I fix my object rendering, that is)


Well, that's great. Except one thing:

It appears the tables you've found are located in the ARM9 code/data region of the ROM. You shouldn't rely on anything from that region for a reason: different versions of the same ROM may have their code/data regions different (for example one bugfix in a newer version results in different code). This can be true for any ROM. Thus, for example, if you were using an USA ROM, the tables may be located elsewhere in an EUR rom, or even use a different format. If it is the case, of course the game will still work, as it most likely accesses the tables through relative offsets (like (PC+table_offset+(tileset<<2)), if the table is located right after the routine that loads the tilesets), but your software won't. That means if you use an hardcoded offset to load the graphics tables, some versions of NSMB may be incompatible with your software.

So you'd better use hardcoded tables inside the software, rather than using the ones in the code/data region of the ROM.

____________________


===================
[Posted by Limonex]
Pages: 1 2Next newer thread | Next older thread
Jul - General Game/ROM Hacking - DS debugging/reverse engineering/whatever you call it New poll - New thread - New reply


Rusted Logic

Acmlmboard - commit 47be4dc [2021-08-23]
©2000-2022 Acmlm, Xkeeper, Kaito Sinclaire, et al.

30 database queries, 16 query cache hits.
Query execution time: 0.110373 seconds
Script execution time: 0.038985 seconds
Total render time: 0.149358 seconds