Advertisement
Pyorot

SMS QFT Autosplitter (PAL .asl)

Nov 7th, 2022 (edited)
1,365
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 3.73 KB | Gaming | 0 0
  1. // == Memory Autosplitter for Super Mario Sunshine (PAL) on Dolphin ==
  2. // Date Modified: 2022/01/16
  3. // Based on Quarterframe Timer (Experimental) v0.5
  4.  
  5. // Made using Dolphin Autosplitter Template by Buurazu
  6. // https://github.com/Buurazu/AutoSplitters/blob/main/Dolphin%20Autosplitter%20Template.asl
  7.  
  8. state("Dolphin") {}
  9.  
  10. startup {
  11.     vars.timerModel = new TimerModel { CurrentState = timer };
  12.     refreshRate = 10;
  13.     vars.frameRate = 30f/1.001f;
  14.  
  15.     vars.gameID = "GMSP01";             // GameID used to check top of memory
  16.     vars.gameName = "SMS";              // for debugging output
  17.     vars.offsetTimerStop  = 0x017F00B2; // all versions
  18.     vars.offsetTimerValue = 0x017F00B4; // all versions
  19.     vars.offsetMapID      = 0x003E10CE; // 0x3E10CE for PAL; 0x3E600E for J; 0x3E970E for E
  20.    
  21.     // Big Endian to Little Endian utility
  22.     Func<int, int> BEtoLE = (beint) => {
  23.         byte[] bytes = BitConverter.GetBytes(beint);
  24.         Array.Reverse(bytes, 0, bytes.Length);
  25.         beint = BitConverter.ToInt32(bytes, 0);
  26.         return beint;
  27.     };
  28.     vars.BEtoLE = BEtoLE;
  29. }
  30.  
  31. init {  
  32.     vars.startLoc = IntPtr.Zero;
  33.     vars.checkedForGameID = -1;
  34.     vars.time = 0;
  35. }
  36.  
  37. update {
  38.     // 1. Dolphin sync 1/2: dynamically set Dolphin's memory region every 2s
  39.     if (vars.startLoc == IntPtr.Zero) {
  40.         vars.checkedForGameID += 1;
  41.        
  42.         if ((int)vars.checkedForGameID % (refreshRate * 2) == 0) {
  43.             print("Searching for " + vars.gameName + "'s memory header...");
  44.             foreach (var page in memory.MemoryPages(true))
  45.             {
  46.                 // print(page.BaseAddress.ToString("X") + " " + page.RegionSize.ToString());
  47.                 if ((int)page.RegionSize < 0x2000000) continue; //checking for 32MB exactly
  48.                 string hopefullyID = memory.ReadString((IntPtr)(page.BaseAddress), 6);
  49.                 if (hopefullyID == vars.gameID) {
  50.                     print(vars.gameName + " memory found at 0x" + page.BaseAddress.ToString("X"));
  51.                     vars.startLoc = page.BaseAddress;
  52.                     break;
  53.                 }
  54.             }
  55.         }
  56.         if (vars.startLoc == IntPtr.Zero) return false;     // require startLoc to have been set
  57.     }
  58.  
  59.     // 2. Dolphin sync 2/2: check game is still loaded (base address can change during reload)
  60.     var isGameStillLoaded = memory.ReadString((IntPtr)(vars.startLoc), 6);
  61.     if (isGameStillLoaded != vars.gameID) {
  62.         print(vars.gameName + " unloaded");
  63.         vars.startLoc = IntPtr.Zero;
  64.         if (settings.ResetEnabled) { vars.timerModel.Reset(); }
  65.         return false;
  66.     }
  67.    
  68.     // 3. game update routine
  69.     current.timerStop  = memory.ReadValue<byte>((IntPtr)(vars.startLoc + vars.offsetTimerStop));
  70.     current.timerValue = vars.BEtoLE(memory.ReadValue<int>((IntPtr)(vars.startLoc + vars.offsetTimerValue)));
  71.     current.mapID      = memory.ReadValue<byte>((IntPtr)(vars.startLoc + vars.offsetMapID));
  72.     if (old.timerStop == 0 && current.timerStop != 0) { vars.time += current.timerValue; }
  73.     if (old.mapID != 0xF && current.mapID == 0xF) { vars.time = 0; if (settings.ResetEnabled) { vars.timerModel.Reset(); } }
  74.     // reset routine has to be here because reset{} below isn't called when timer stops at end of run for some reason
  75. }
  76.  
  77. isLoading { return true; }                                                  // blocks real-time approximation to game time
  78. gameTime  { return TimeSpan.FromSeconds(vars.time/(4*vars.frameRate)); }    // qft value
  79. start     { return old.mapID == 0xF && current.mapID != 0xF; }              // exiting title screen
  80. reset     { return false; }                                                 // entering title screen (moved to update routine)
  81. split     { return old.timerStop == 0 && current.timerStop != 0; }          // qft stopped
  82.  
Tags: sms asl
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement