Untamed Heart: Wahoo is more popular than Yahoo!

Untamed Heart Klonoa Collective Untamed Heart Klonoa Collective Untamed Heart Klonoa Collective

Author Topic: Reverse engineering  (Read 24260 times)

0 Members and 1 Guest are viewing this topic.

Offline Voka~Daemyn

  • Old Tree
  • Global Moderator
  • *
  • Posts: 1767
  • Dreamer Rating: 70
  • Squiiirrrrrrrrrrrrrrrrle
Re: Reverse engineering
« Reply #30 on: April 28, 2017, 09:04:09 pm »
I went and checked a bunch of moos spawning for a while. Also I'm going ot keep recording this stuff in case I screw up again. AMD relive saved me a bit of headache on losing addresses this time.

I still don't know if this can help much but I think in theory if I keep getting samples of enemies spawning then maybe the ranges of memory addresses can be figured out for the moos.

Edit: Sometimes 1-1 Moo spawn 2 and 1-1 Moo spawn 3 can swap around to each other but I haven't seen this for other Moos yet.

Code: [Select]
0C02A8   d   u   0   MainRAM   1-1 Moo spawn 1 address1
0BF3A8   d   u   0   MainRAM   1-1 Moo spawn 2 address1
0C08E8   d   u   0   MainRAM   1-1 Moo spawn 3 address1
0C0168   d   u   0   MainRAM   1-1 Moo spawn 2 address2
0C0028   d   u   0   MainRAM   1-1 Moo spawn 3 address2
0C0B68   d   u   0   MainRAM   1-1 Moo spawn 4 [hover thing] address1
0C03E8   d   u   0   MainRAM   1-1 Moo spawn 3 address 3
0C0CA8   d   u   0   MainRAM   1-1 Moo spawn 4 Teaton [hover thing] address 2
0C0A28   d   u   0   MainRAM   1-1 purple running enemy near the wind flower address 1
0C0F28   d   u   0   MainRAM   1-1 moo in before and in front of Balue's unfinished tower
0BF3A8   d   u   0   MainRAM   1-1 flying moo past balue's unfinished tower
0C07A8   d   u   0   MainRAM   1-1 Moo spawn 4 Teaton [hover thing] address 3
0C1568   d   u   0   MainRAM   1-1 1st pinkie [purple running enemy] near the wind flower address 2
0C0F28   d   u   0   MainRAM   1-1 moo in before and in front of Balue's unfinished tower address 2
0BF9E8   d   u   0   MainRAM   1-1 2nd flying moo past balue's unfinished tower address 1
0C03E8   d   u   0   MainRAM   1-2 1st Moo spawn address 1
0BFB28   d   u   0   MainRAM   1-2 Moo and Pinky early part behind under ledge moo spanw that spawns two enemies address 1
0C0028   d   u   0   MainRAM   1-2 post mine cart area Moo in front of egg address 1
0BF8A8   d   u   0   MainRAM   1-2 post mine cart [cave] shield moo 1 address 1
0C0028   d   u   0   MainRAM   1-2 post mine cart area Moo in front of egg address 2
0BF3A8   d   u   0   MainRAM   1-2 post mine cart area Moo in front of egg address 3
0BF8A8   d   u   0   MainRAM   1-2 post mine cart [cave] shield moo1 address 2
0BFB28   d   u   0   MainRAM   1-2 post mine cart [cave] shield moo 2 address 1
0C0B68   d   u   0   MainRAM   1-2 last cave part. 1st moo before large falling rock address 1
0C1A68   d   u   0   MainRAM   1-2 last cave part 1st moo alt path behind rock address 1
0C1068   d   u   0   MainRAM   1-2 last cave part. 1st pinkie [purple running enemy] beyond large falling rock address 1
0C12E8   d   u   0   MainRAM   1-2 last cave part. 1st pink boing beyond large falling rock address 1

Those 2 videos are long and extremely boring also amd relive sound messed up. but I posted them in case somehow I missed something while searching for addresses and also just because..
Sorry but you are not allowed to view spoiler contents.
« Last Edit: April 29, 2017, 05:11:55 pm by Vokadae »

Offline cows

  • Moo
  • *
  • Posts: 27
  • Dreamer Rating: 8
Re: Reverse engineering
« Reply #31 on: May 02, 2017, 04:32:56 am »
Huh, well I notice all of the addresses you've found end with 8, which honestly is more than I've discovered lately. As for exactly why they'd all end in 8, it looks like there's some kind of alignment going on that I can't fully explain. I think the game was originally coded in C, (this shouldn't be too hard to confirm, I just haven't done it yet), so I'm guessing the moos are part of a C "struct." I know the PlayStation can work with 8-byte floating point values (as well as words of 4 bytes and "half words" of 2 bytes), so all values stored in structs are likely "padded" to be able to fit the largest one. I think the stack pointer also needs to be 8-byte aligned, which is probably not relevant here*. Neither of those things can account for why the addresses wouldn't end in either 8 or 0, though, which is what I'd expect if they were actually 8-byte aligned and not 16-byte aligned. I'm also not sure why other values in memory don't follow that convention, other than the fact that they're presumably not in structs.

I still haven't worked out how memory for enemies is being allocated. I happened to discover pretty much by accident that there's a bios call that allocates memory, listed in appendix B of this document. That's lucky, because otherwise I probably would have taken much longer to realize that that was even a thing that could exist (if you're curious, the Wikipedia article explains why that's not really a thing in modern programs). Is this how the memory for enemies is being allocated? I have no idea. In fact, I don't know if that's even slightly plausible. I'm definitely going to check, though, because it's probably a lot easier to check if that's happening than it is to work backwards until I find where the enemies' location in memory came from. In any event, I have a bunch more reading to do now.

Also, apologies if my weird ramblings are not especially helpful to anyone. I'm trying to outline my thinking in a way that someone could conceivably follow along (and also so I can remind myself what I'm doing), but my posts are definitely pretty unclear and disorganized. Everyone should feel free to ask me if there's something they'd like to follow along with but can't due to my awkward "explanations."

*I should actually make sure the values I'm looking at are in fact stored in some kind of heap space (memory set aside for dynamic allocation) rather than on the stack (memory set aside for passing values "into" functions).

Offline Voka~Daemyn

  • Old Tree
  • Global Moderator
  • *
  • Posts: 1767
  • Dreamer Rating: 70
  • Squiiirrrrrrrrrrrrrrrrle
Re: Reverse engineering
« Reply #32 on: May 03, 2017, 06:20:41 pm »
Ah I don't mind the rambles and extra notes. especially if it can make an opportunity for people to help figure it out.

Ah I wish you best of of luck on this. It's been fun so far :)

Offline cows

  • Moo
  • *
  • Posts: 27
  • Dreamer Rating: 8
Re: Reverse engineering
« Reply #33 on: May 08, 2017, 04:04:49 am »
Unfortunately only a very short update this weekend, as I'm still kind of perplexed by these BIOS calls. It doesn't seem like the "malloc()" "calloc()" or "realloc()" functions ever get called by the game, which isn't too surprising as I wouldn't be surprised if the game maintains its own heap (or potentially does something else that I'm not yet aware of). What's weird, though, is that there is code in memory that calls the "free" BIOS function. This only makes sense if the memory is being allocated in the same way, as the BIOS would only have knowledge of its own heap (so telling it to "free" memory that it's not keeping track of should, at best, do nothing).

That said, it's possible I just missed a call to one of the allocation functions, through my own carelessness or through it calling the function in a less straightforward way than I expected. In any event, I think at this point working backwards is probably going to be the easier path forward.

Offline Voka~Daemyn

  • Old Tree
  • Global Moderator
  • *
  • Posts: 1767
  • Dreamer Rating: 70
  • Squiiirrrrrrrrrrrrrrrrle
Re: Reverse engineering
« Reply #34 on: May 13, 2017, 07:10:29 am »
Ah I've not had a lot of time to check stuff but I did get some main camera addresses however the only affect certain parts of vision 1-1 so far like the beginning area and just after you exit balue's unfinished tower in vision 1-1
Code: [Select]
0C9F34 d 3 0 MainRAM camera y axis 1-1
0C9F30 d 3 0 MainRAM camera x axis 1.1

I also tried to find the mew mew's projectiles "little mouse things that spawn spike balls in vision 1-2. but it seems they are also on dynamically changing addresses :( I can't seem to affect the balls much aside from the position if I am lucky enough to find it.

Code: [Select]
0C1CF0 d u 0 MainRAM 1-2 2nd mew mew spike ball
0C1A70 d u 0 MainRAM 1-2 1st mewmew spike ball
0C1994 d u 0 MainRAM 1-1 1st mew mew spike ball location x ?
10845C d u 0 MainRAM 1-1 3rd mew mew. confusing and strange address related to spike balls
108510 d u 0 MainRAM 1-1 3rd mew mew. confusing and strange address related to spike balls address 2

Offline cows

  • Moo
  • *
  • Posts: 27
  • Dreamer Rating: 8
Re: Reverse engineering
« Reply #35 on: May 16, 2017, 04:24:38 am »
Only incremental progress on my end again. I'm starting to piece together the data structure for a single enemy, but still haven't found exactly when, where, and how it gets stored. So far,

-enemy position only updates when the enemy is actually onscreen; in fact, I wouldn't be surprised if the enemies get "deleted" altogether once they're off-screen, and simply recreated once Klonoa gets within range of where they're supposed to be
-moos when a moo stops moving on its own, a timer controls when the moo should start moving again, and they always stop for the same amount of time
-there isn't a timer that controls when a moo stops moving, so it probably decides to do this when it reaches certain specific positions
-the stopping positions seem to be stored in the moo structure, but I'm not 100% sure about this
-enemies retain the same format even while being thrown, rather than being replaced with a new data type

Finally, I've noticed that the first enemies always seem to be stored in the same place if you skip the first in-game cutscene as quickly as possible. This makes sense, since the "heap" (or wherever enemies are stored; it still could be a fixed list of some kind or even something else) probably gets (re-?)initialized after the cinematic, and skipping the cutscene probably ensures that the same amount of stuff gets stored before the enemies are created. This is actually a pretty promising development, since it makes it possible to know in advance where an enemy will be stored so that breakpoints can be set based on when that particular bit of memory is first used. In related news, it turns out that memory breakpoints don't always work in no$psx (they do in the PSX 1.13 emulator, though) which definitely caused me a fair amount of confusion.

Offline Voka~Daemyn

  • Old Tree
  • Global Moderator
  • *
  • Posts: 1767
  • Dreamer Rating: 70
  • Squiiirrrrrrrrrrrrrrrrle
Re: Reverse engineering
« Reply #36 on: May 16, 2017, 08:56:03 am »
 :O the scene skipping stuff sounds like good news. I'm going to assume projectiles are also in the enemies data structures. I tried to figure out more by going to where I was seeing on off on off for the projectile release but I couldn't make sense of much anything aside from it having a lot of similar addresses doing stuff in tandom, Freezing most of then didn't affect anything though.

* Vokadae legit wanted a mew mew spewing out 30 spiked balls  :embarassed:

Offline cows

  • Moo
  • *
  • Posts: 27
  • Dreamer Rating: 8
Re: Reverse engineering
« Reply #37 on: May 31, 2017, 01:27:46 am »
I have finally managed to make some actual progress. Specifically, I've found that

a) there's a general sprite object initialization function at 80076324
b) in the specific case of moos, this function is called from 8005DA94

By modifying the function at 80076324, it's possible to prevent all or most sprite objects from appearing. The 3D geometry is unaffected. Unfortunately, the game isn't playable in this state, since it seems like Klonoa himself is initialized through this function. More usefully, by preventing this function from being entered ONLY from 8005DA94, the game is playable, but moos never appear. Nothing else seems to be affected by this (different enemy types appear as usual), and, interestingly, moos that enter from a scripted location of screen DO appear, but disappear as soon as they "land." Presumably the "scripted" moos are a different type of object than the "real" ones, and the game simply destroys the scripted ones and adds real ones in their place.

If I can figure out where other types of enemies are initialized, it should be possible to replace one type of enemy with another, which would be a pretty good breakthrough. Unfortunately, the process I'm using is still slow and awkward, so this could take a while. Basically, I'm doing the following:

-Use Bizhawk to locate where an enemy's attributes are stored in RAM using its search and watch tools
-Blindly hope that I can figure out a way to reliably make the same object appear at the same address in PSX 1.13 (since I haven't bothered figuring out a way to share save states between the two)
-Use a Memory breakpoint in PSX 1.13 to find where in the code these attributes get stored (since PSX 1.13 seems to be the only debugger that actually works with memory breakpoints)
-Load the game yet again in no$psx and add a breakpoint at the instruction I found in PSX 1.13
-Print out a code trace leading up to that instruction
-Work backwards to figure out what's actually going on leading up to this point
-Change some of the instructions to see if the logic actually works the way I think it does.

Offline Voka~Daemyn

  • Old Tree
  • Global Moderator
  • *
  • Posts: 1767
  • Dreamer Rating: 70
  • Squiiirrrrrrrrrrrrrrrrle
Re: Reverse engineering
« Reply #38 on: May 31, 2017, 07:21:25 am »
 :O holy crap that is..  actually happening despite sounding really long and convoluted to pull off.

It is quite exciting :smile2:

Offline cows

  • Moo
  • *
  • Posts: 27
  • Dreamer Rating: 8
Re: Reverse engineering
« Reply #39 on: June 09, 2017, 05:27:54 am »
I've managed to remove all of the enemies in the game, and I've identified some of the other enemy types, but I still haven't quite managed to replace one enemy type with another. Also, I realized that the initialization function I mentioned actually is responsible for updating enemies each frame. If an enemy is created successfully, that function continues to be called for each enemy, but if there are no enemies at all, it never gets called. In both cases that should yield more clues about where the game loops through all of the enemies and where the enemies are stored in memory.