Graph based tool for Crash Bash MM exploration
Since the PSX Main RAM covers only all of 0x80XXXXXX
, the first 2 digits will often times be
omited when refering to addresses.
Notable values:
- Index of A:
0
- Index of CANCEL:
29
- Address of current index value:
0x0BF19C
- Address offset per index unit:
168 bytes
- Address of index 0:
0x0BDB58
Here is the dumped RAM for the object at index 0 (address 0x0BDB58
):
Offset | 0 4 8 C
0x00 | 10008000 00000000 00000000 00000000
0x10 | 00000000 00000000 00000000 00000000
0x20 | 00001000 00001000 00001000 00000000
0x30 | 00000000 00000000 00000000 00000000
0x40 | 00000000 00000000 00000000 00000000
0x50 | 00010400 8001C448 8001CC08 800BDC00
0x60 | 00000000 00000000 00000000 800B38A4
0x70 | 0000D0FF 000000FF 00000000 00000002
0x80 | 00000000 00000000 00000000 00000000
0x90 | 00000000 00000000 00000000 00000000
0xA0 | 00000000 00000000
In the above RAM dump, offsets 0x70
, 0x74
and 0x7C
are all modified upon selection or
deselection of the item. More specifically, 0x70
and 0x74
move like crazy as long as the item is
selected, while 0x7C
becomes and remains 0x00000002
. Upon deselction, they take the values
0x0000D0FF
, 0x000000FF
and 0x00000000
respectively.
Starting at offset 0x54
, up until offset 0x6C
, all the values seem to represent addresses in
memory (notice how all non-0 values start with 0x80
). Comparing with the rest of the items, we
notice that...
- offsets
0x54
and0x58
never change and have the values0x8001C448
and0x8001CC08
respectively, for all items. - offset
0x5C
changes for all items and represent the address of the next selectable in the list/array. - offset
0x60
also changes for all items and represent the address of the previous selectable in the list/array. We are most likely dealing with a doubly-chained list. - offsets
0x64
and0x68
seem to always have the value0x00000000
. - offset
0x6C
changes, and seem to always have a value of 4 greater than the same offset of the previous item, starting at0x800B38A4
for item 0.
Knowing this, addresse 0x8001C448
, 0x8001CC08
both represent addresses worth investigating, but
addresses 0x800B38A4
+ all have a greater chance at representing interesting values.
Address | 0 4 8 C
0B38A0 | 00000041 00000042 00000043
0B38B0 | 00000044 00000045 00000046 00000047
0B38C0 | 00000048 00000049 0000004A 0000004B
0B38D0 | 0000004C 0000004D 0000004E 0000004F
0B38E0 | 00000050 00000051 00000052 00000053
0B38F0 | 00000054 00000055 00000056 00000057
0B3900 | 00000058 00000059 0000005A 00000040
0B3910 | 0000003C #Starting with RAM addresses again
Yeah... I was wrong in thinking this would be useful. Those are just the ASCII values of all the characters in the grid. Turns out that segment of memory is all text. Yay!
Even though I tried, I couldn't really make out anything of what was going on in there. It looked very much like garbage, and changing the values down there really didn't seem to affect the behavior of the cursor position (which, by the way, is what we've been searching for all along).
I decided to start with the most logical starting point: Item 0. I started by poking all the addresses upwards of that starting point until I noticed a certain pattern – parentheses, lowercase "x"s, capital "P"s and "8"s forming columns in the ASCII translation of the RAM. Of course, as they are, these characters mean nothing, but they do catch the eye. Modifying a single one of these values succesfully changed the behavior of moving the cursor from the A item.
Starting at address 0x0BD5D0
, we have a series of values which seem to control exactly what
happens for each action and each selection. There is apparently 16 bytes associated to each index.
These are distributed as such:
- 2 bytes for the X position of the item (read on load)
- 2 bytes for tye Y position of the item (read on load)
- 4 bytes pointing to a string to write down in the field up there (remember, we're actually supposed to write a savefile name here)
- 4 bytes that control the horizontal movement
- 4 bytes that control the vertical movement
By the way, if you change address 0x0BD720
to have the value 0x01FF00
, the whole thing now
becomes impossible, as the cursor simply doesn't go out of bounds anymore. ¯\_(ツ)_/¯ A little
bit of testing is all that would have been required to avoid this game breaking glitch. Thank you
Eurocom for overlooking this :)
Well, finding this is very, very useful to me. It is now possible to predict exactly how the cursor will move through memory, and that for all 8 directions and all indexes. All I'll need is a dumping of the PSX RAM before the whole process starts.
It should be noted though, that this discovery is a little bit of a game changer for the algorithm I will be developping. It will be unchanging for most values, but every 3/20 indexes (rough calculation, may be wrong), there is a chance its behavior will have been modified by a previously visited index.
I still need to investigate exactly how they will be affected, but I am confident it will be important to take this fact into account when creating the graph that will eventually represent all of Bash's Memory Manipulation possibilities.
Index | Address | Good/Bad | Effect | Notes |
---|---|---|---|---|
-63 | 0x0BB270 |
Name selection screen crashes on load. | Temporary — Recovers on hub reload. | |
-72 | 0x0BAC94 |
Bad | Navigating Left in name selection screen stops functioning as expected. | Temporary — Recovers on hub reload. |
-945 | Visual (bad) | Camera in some games is left unmoving at the origin. | Not playable RTA. Not enjoyable for TAS. | |
-974 | Visual | Rules dialog boxes and collectible selection boxes are not visible. | ||
-979 | Bad | Opening the Pause menu or displaying a Rules box crashes. | ||
-989 | Visual | Warp room skybox spins at warp speed. | Pun intended. | |
-1014 | Bad | Loads fail to start (softlock). | ||
-1018 | Bad | Loads crash at the end. | ||
-1039 | Bad | Loads fail to start (crash/softlock). | ||
-1064 | Bad | Crashes on exiting name selection screen. | ||
-1100 | Visual | Collectibles in save selection screen overlap each other. | ||
-1207 | Bad | Crashes during Panic rounds. | ||
-1313 | Bad | Crashes during Bash rounds. | ||
-1314 | Bad | Crashes at the start of a Bash round. | ||
-1347 | Bad | Causes Fox challenges to fail playing out, with a locked camera. | Crashes if stopping on that index. | |
-1348 | Bad | Crashes on exiting save selection screen. | ||
-1373 | Bad | Crashes on exiting name selection screen. | ||
-1375 | Bad | Crashes on exiting name selection screen. | ||
-1388 | Bad | Crash during Melt Panic rounds and in Metal Fox player death. | Could be more levels, but those are the observed effects. | |
-1397 | Bad | Crashes at the start of any (?) round. | ||
-1420 | Bad | Crashes on exiting name selection screen. | ||
-1482 | Visual | Pause menu gets visually corrupted. | ||
-1511 | Bad | Cannot proceed out of Rules box (X does nothing). | ||
-1664 | Bad | Crashes on exiting save selection screen. | ||
-1954 | Bad | Crashes on the spot. | ||
-2024 | Neutral | Melt panic platform upper section behaves as if it was mostly melted. Toxic Dash often crashes some time into the rounds. | TAS may be able to avoid the Toxic Dash crashs. | |
-2205 | Bad | Freezes the name selection screen almost completely. | Temporary — Recovers upon exiting screen. | |
-2255 | Bad | Freezes the name selection screen almost completely. | Temporary — Recovers upon exiting screen. | |
-2271 | Bad | Freezes the name selection screen almost completely. | Temporary — Recovers upon exiting screen. | |
-2275 | Bad | Freezes the name selection screen almost completely. | Temporary — Recovers upon exiting screen. | |
-2277 | Bad | Freezes the name selection screen almost completely. | Temporary — Recovers upon exiting screen. | |
-2280 | Bad | Freezes the name selection screen almost completely. | Temporary — Recovers upon exiting screen. | |
-2282 | Bad | Freezes the name selection screen almost completely. | Temporary — Recovers upon exiting screen. |
-1615, Timer: Starts at different times depending on level
Log from 2016/07/26 (http://pastebin.com/kewAgjvH)
So. Stuff happened in Crash Bash lately, and as the first real Memory Manipulation to be discovered in a game I have some remote interest in (It's a PS1 game of the Sprash sort...), I needed to jump in an try to uncover its secrets. Quickly, after playing around with it, I found the memory adress that contains which letter/action of the "ENTER NAME" screen is selected... Those actions are in a simple array, with A being 0 and CANCEL being 29, and it happens that they never fool-proofed pressing Down-left on V, which takes you to ID 34. Great. Now from there you can do 5 things:
- Press DOWN: Nothing happens...
- Press LEFT: You move to 45, then you're stuck.
- Press UP: You move to 48, then you're stuck.
- Press UP-LEFT: You move to 59, from here only pressing UP does something, and it brings you on H.
- Press RIGHT: Here is where all the magic happens. It brings you to -94.
Now the wonderful thing is that it probably uses that number as the index of the array in which all these actions are stored. I noticed that after every press of a button that does not leave the cursor in place, one value becomes 2, while the one that was previously changed to 2 becomes 0. My guess: 2 means "Selected", while 0 means "Not selected". In the end, every visited address becomes 0, except for the last which remains 2, and that for as long as the game is not restarted (We're directly modifying the game code after all...)
By observing the RAM throughout the Panic Dash code, I managed to find a small change in the index,
and map it to 2 addresses. There should therefore be a change of 3 "units" between addresses
0B83E4
and 0B85DC
, which gives us 504 bytes or 168 bytes per "unit". In this case, this size
also corresponds to the size of the letter/action objects in memory. I confirmed this by comparing
the change in modified addresses and the change in index to multiple steps in the code, and it
corresponds perfectly.
So what now? Well, knowing this, we can theorize that ANY 4-byte in memory that has a 168-byte
integral offset from address 0x000004
can be changed to 2, and then to 0. What's beautiful with
this is that 0 is a magic value in computers. It represents "nothing" and if, say, the value
modified was a pointer to a function, then the whole sequence of operations executed by that
function will be skipped.
Now, I have not investigated what the changed values represent, and still do not understand how some of these changes can cause confusing things like enable Instawin, or (this strangest effect if you ask me), make the timer jump from 1:00 to 0:05 consistently... Anyway... Finding exactly which value does what would take too long, and to be honest I don't really want to be the one breaking the game even more. All I wanted here was to help understand what was happening under the hood, and give us a better understanding of what could be possible using this glitch.
Verdict: We are lucky that this glitch has so many useful effects. Some of them were completely unpredictable, while some others make sense. Actually scrap that. They are all completely unpredictable. I mean, what? Instawin on everything, timer jumping to 5 seconds, auto-receiving wumpa fruits and stuff? Wow. With a little bit of wizardry, I wouldn't be surprised if we could use it to bypass requirements, but that's as far as it could go in the WARP rooms.
Also, no Pokémon-like programming will be possible with this kind of memory manipulation. It's too basic. This makes me a bit sad :(
Anyway, I wanted to spend the rest of this bin exploring the effect of each of the possible actions on the index, which is, here, clearly the magical value. Unfortunately, as the following table shows, the changes seem to follow no logic whatsoever. I do not know whether or not we will eventually be able to find a specific logic, but either way it seems it wouldn't help to know the specifics, unlike what I initially thought. What we should keep in mind though, is that the behavior for each input is set per value. We are just blindly navigating a one-way portals maze, and the entrance is intersection "34"... I don't know, I felt like that was a nice metaphor :^)
v d
-> 34 | |
R -> -94 | -120 |
D -> -143 | -49 |
U -> -199 | -56 |
L -> -161 | 38 |
U -> -145 | 16 |
L -> -134 | 11 |
D -> -131 | 3 |
R -> -259 | -128 |
D -> -387 | -128 |
L -> -476 | -89 |
L -> -473 | 3 |
R -> -457 | 16 |
U -> -456 | 1 |
R -> -578 | -122 |
L -> -576 | 2 |
U -> -568 | 8 |
L -> -504 | 64 |
R -> -593 | -89 |
U -> -693 | -100 |
L -> -784 | -91 |
L -> -716 | 68 |
L -> -780 | -64 |
R -> -886 | -106 |
R -> -866 | 20 |
U -> -838 | 28 |
R -> -919 | -81 |
L -> -917 | 2 |
L -> -1005 | -88 |
L -> -1070 | -65 |
D -> -1071 | -1 |
R -> -1051 | 20 |
L -> -1142 | -91 |
R -> -1223 | -81 |
U -> -1190 | 33 |
Using my observations, I decided to rework the currently used codes. I figured I could make them "better", or at least shorter. Considering a shorter code means fewer destroyed memory, I came to the conclusion that a shorter code was likely to make the game more stable, with low risks of breaking it further.
Following here are my updated/new codes. Keep in mind that I have not tested them as thoroughly as I should have and therefore they need to be confirmed viable before being used in runs. I used a similar format as the most recent post on the forum, since the codes most likely won't be used individually anyway.
"Panic Dash": (Final value = -1190)
(was R D U L U L D R D L L R U R L U L R U L L L R R U R L L L D R L R U)
now R L L R R L R R R U L R U L L L L L L R
Side effects: Cannot use WARP room changer right after using the code... Crash out of N. Ballism?
"PD" -> "Time code": (Final value = -1608)
(was L R U L R R L D R L R L U D L R R)
now R L L R U R
"PD" -> "Instaboss": (Final value = -1399)
(was R L R U D L U L U U L)
now Couldn't find anything shorter
"TC" -> "Instaboss": (Final value = -1399)
(was NONE)
now U L L U U L
Note: Doesn't seem to crash. Doesn't crash Bear, nor Papu. Didn't test the other 3 freaks...
"IB" -> "Instawin": (Final value = -1569)
(was L R U D L R L R L L L R L R R L U R D U U R R L R L U R U)
now L R U D L D R R U U D U R U
crsh U _ (Note: Index -1381 actually fucks up AI and other stuff real bad...)
Note: Seems to work with everything. Removes scary Fox visual shenanigans.
"All in one": (To be fair, that's all we really care about isn't it?)
R L L R R L R R R U L R U L L L L L L R R L L R U R U L L U U L L R U D L D R R U U D U R U
List of values that cause a crash:
- 1381
- 1383
- 1400
- 1409