Advertisement
Faschz

DKR - Wrong Warp 101

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