This guide details how/where key game items are stored in RAM and how to change them — at the time of writing this I am playing the PAL version of Crash Fusion on Bizhawk 2.8 (mGBA core). As a result of this RAM search I was also able to decipher this game's percentage system, cf. the end of this guide.
Also, abbreviations that will be used frequently throughout this guide are: HEX (a number in hexadecimal), DEC (a number in the standard decimal system), and BIN (a number in binary).
RAM
First, to access and change the RAM values mentioned down below open the Bizhawk hex editor
and change the memory domain to Combined WRAM:
Aside from the current RNG value which — like in Spyro Fusion — is located at 0x000000 in Combined WRAM, all values mentioned down below can be found at 0x006··· or 0x00F···
Findings
Everything I was able to identify in these memory regions is documented in this spreadsheet. The rest of this section will contain explanations and further information complementing the spreadsheet in question.
Wumpas & Aku Aku
The Wumpa count is a plain 4-bit value in RAM, located at 0x006F2C:
While this can be changed at will (and the game will display any value you enter), if you give yourself more than 9999 wumpa, changing the wumpa count in-game in any way will set it back to the game's maximum value 0F270000 (=9999 in DEC).
Also, your current amount of Aku Aku masks (0, 1, 2) is stored in 0x006F50, although manipulating it does not seem as straightforward because freezing the value does not keep your mask count stable throughout taking damage.
Crystals, bosses, level completion
This is a bit more difficult since there is no single value corresponding to things like the overall crystal count. Instead, multiple addresses keep track of which levels the player got the crystal in already, which bonus levels have been completed etc. The corresponding region is 0x006ED8 to 0x006EE1 (change the Data Size in the options to 1 byte to see it like this):
The way this works is that every byte consists of 8 bits, and each bit tracks a different thing. With that in mind, this memory region keeps track of the following information (click on the image to enlarge it or look at it in the spreadsheet):
As you see there's not only the crystals, but also which bonus levels have been completed, which shops have been visited already, and which bosses have been defeated.
Changing RAM: binary & hexadecimal
Let us take a quick detour to understand how we can change these RAM values to our liking by means of two examples.
- Let's say we want our game to think that we just completed the world 1 bonus level Crate Smash as well as the crystal for the level "Sheep stampede". As per the spreadsheet, this corresponds to the byte 0x006ED8, more specifically the second and the sixth bit within that byte. Thus, the bitstring our request corresponds to is 0 1 0 0 0 1 0 0. All we have to do now is to convert this to the corresponding HEX value, e.g., via a binary-hex-conversion website. Either way it turns out that 01000100 binary is 44 HEX, so changing byte 0x006ED8 (highlighted in light red in the picture above) to 44 will do the job; do this by clicking on the byte and entering the number on your keyboard. NB: We still have to make the game adopt this change to the save file; this will be detailed down below.
- Now assume that you played the game for a while and byte 0x006ED8 already has the value 44, and we want the game to think that, additionally, we already got the crystal for the level "Tanks for the memories" (fifth bit as per the spreadsheet). From the first example we already know that 44 HEX is 01000100 in binary, so we could just flip the fifth bit to a 1 to get 01001100, and the HEX converter lets us know that this is 4C in HEX. Alternatively, if we don't want to deconstruct the HEX value in the RAM, we can use a HEX calculator: as per the first row in the spreadsheet, the fifth bit corresponds to the HEX value 8, so we have to add 44 + 8 (in HEX!) which comes out to 4C, as it should.
Party tab
Note that the minigames unlocked in the party mode are separate from the RAM values for completed levels discussed previously. The reason for this is that a minigame is unlocked in party mode as soon as it is entered. This is kept track in the memory region right before the crystals, 0x006ECC through 0x006ED6:
Gems
The gems are stored similarly to the crystals, in the memory region right after (0x006EE4 through 0x006EED). Another interesting thing that is stored here is whether the animation where you get the trading card after a boss fight has played already.
Barriers, cutscenes, overworld cards
Then there's more game-internal events: the two bytes 0x006EF0 and 0x006EF1 store which of the wumpa barriers (between the first and second half of a world) and which of the barriers before each boss (crystals) and after the fourth Boss Ripto (20-gem barrier) have been deactivated yet. It is worth pointing out that the unlock condition of the crystal and gem barriers is that the player has at least as many crystals/gems as the barrier requires (that is, unlocking a 20-crystal barrier while having 22 crystals works). In casual play, of course, you can never have more crystals or gems than a certain barrier requires, but it some point this may become relevant knowledge, say, by means of some glitch we find in the future.
Then the next two bytes 0x006EF2 and 0x006EF3 keep track of which overworld cards (i.e., cards which can be found openly in the hub worlds) have been collected so far.
Finally, the bytes 0x006EF4 and 0x006EF5 track which cutscenes have played already.
Cards
Trading cards are being kept track of twice: once for whether the player currently owns this cards, and once for whether a card has been owned at some point and then, e.g., been traded away (in this case the card is greyed out). The corresponding memory regions are 0x00F0AC - 0x00F0C4 and 0x00F0D8 - 0x00F0F0, respectively:
The requirement to get the card animation in the main menu which signifies that you got all 200 cards is that none of these card bit has a 0 in both these memory regions at the same time. In other words, if you have or at some point had every card that's enough.
Missing stuff
While this concludes everything I managed to find and identify, there are some things that have eluded my grasp:
- While the game obviously has to store Crash's current checkpoint somewhere, I wasn't able to find where and how that happens.
- I was able to find and manipulate Crash's current x- and y-coordinate; these are both 2-byte values ranging from 0 to a couple hundred thousand. The problem is that their location isn't static, as in, the responsible addresses seem to hop around in RAM. So while these values exist and are confirmed to be changeable, I haven't found a consistent way of doing so.
- The memory region 0x006EF7 - 0x006F08 somehow keeps track of what world the player is currently in and where they came from, resp. which adjacent worlds/areas the player can go to. I was able to warp between non-adjacent worlds (e.g., from world 1 to world 5 through the W1 end portal and manipulating byte 0x006F08), but I couldn't figure out how this whole memory region works exactly.
Now there are two things we still have to address:
How to make RAM changes permanent
If we change something in RAM, how do we force the game to make these changes permanent, i.e., transfer these changes to our save file? Luckily, this game saves quite often so all we have to do is force the game into this state, without it loading the current save into RAM before that. With this in mind, the game saves whenever you:
- exit (not enter!) a level, shop, or boss fight, either by completing it or simply by quitting out via the menu
- change the overworld you're currently in, either by changing which half of a world you're in, or which world you're in altogether
- collect an overworld card. Beware that picking up a card in limbo does only save some of the memory values, namely 0x006EF2 - 0x006EF7 (collected overworld cards & played cutscenes) as well as both card regions (0x00F0AC - and 0x00F0D80 - 0x00F0F0).
Also, the current save is loaded into RAM whenever you enter story mode or party mode in the main menu.
Percentage count
Finally, throughout this little project I was able to figure out how percentage works in this game:
- Each crystal gives 2%, so 25 crystals amount to 50% completion
- Each gem gives 1%, so 25 gems amount to an additional 25% completion
- Defeating a boss gives 3%, that is, 5 bosses give 15% combined.
- Completing a Crunch weightlift minigame gives 2% each, so the five of these that exist grant 10% completion
- So far we tracked 100% of completion, so the final 5% have to come from trading cards. The way this works is that every 25 cards you get 1%. So 25 cards up the counter by 1%, 50 cards by 2%, and so on until you have 125 cards which gives you 5%.
Adding all these numbers gives 104% for everything + 120 cards, and 105% for everything + 200 cards (although 100, resp. 125 cards would be enough if we were to just go by the percentage count).
The last thing I want to share is a "minimal 100% RAM string", that is, the smallest possible string which, when inserted at 0x006ED8 — just copy-paste works in HEX editor — yields a save with 100% completion:
BE023E03BE01BE01BE0480006A01E600760074027401
So if you start a new game, paste this string into RAM, exit out of a level to transfer this to the save file, you will have a 100% file where absolutely nothing else is done: nothing has been visited yet and the party tab is empty (aside from the level you used to save the RAM), no additional cards have been collected, and all barriers, cutscenes & overworld cards are where they're supposed to be.