Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // func_800818B4 is a function with a switch statement. Since the wrong warp
- // sets the gamemode to a case not in the switch, a variable is never set
- // causing the game to read stale data on the stack. This value is supposed to
- // be used to determine which map you load. The value getting pulled off the
- // stack is a return address, thus can't be manipulated. However, since code has
- // changed between versions there are different results.
- // Bits 7-9 determine how it is used
- // 0x0200: The last 7 bits are the map
- // 0x0100:
- // 0x0080: The last 7 bits are an index
- // Here is the stale data in all 3 versions.
- // J = 8006C8F0, Index Table (80122CC0 + F0 & 7F = 80122D30)
- // 1.0 = 8006C820, Loop?
- // 1.1 = 8006CA60, Last Byte (60 & 7F = 60, since 60 > 41, 0)
- // On Japanese, the calculated address + 0x02 determines the map. So 80122D32 is
- // where the map gets pulled from. This is manipulated by some other function
- // and is what causes the different outcomes on J.
- // On 1.1, the map is directly a part of the pointer pulled from the stack.
- // Since the resulting byte is 0x60, and is larger than the number of maps there
- // are. It just defaults to loading the overworld.
- // EDIT: Since the writing of this pastebin, the code has been decompiled and it is
- // a lot easier to follow in C here:
- // https://github.com/DavidSM64/Diddy-Kong-Racing/blob/9a60c84b6747c6eec93a5487623b17eb9e84d480/src/game.c#L1612
- // The code here is for NTSC-U 1.0, so addresses are slightly different, but the idea
- // still stands. The Japanese version is attempting to access D_80121250 with an OoB read.
- // This means it is setting the gPlayableMapId from inside the gMainSched.
- // 0x80121250 is 16 bytes so gMainSched starts at 0x80121260. 0x60 into gMainSched is
- // the interrupt buffer for os messages
- // The code sort of looks like this, but a lot more cases... and it does more.
- u32 get_load(){
- u32 ret;
- // Notice that if the mode was any value besides 0, 1, or 2. It'll bypass
- // whatever is in the switch-statement because there is no default. It'll
- // return ret even though it was never set.
- switch(mode){
- case 0:
- ret = func_mode0();
- break;
- case 1:
- ret = func_mode1();
- break;
- case 2:
- ret = func_mode2();
- break;
- }
- return ret;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement