Editor, Expert player (2327)
Joined: 5/15/2007
Posts: 3915
Location: Germany
If I understand right, you want to start a game where the save file is all 0xFF, except for the 4 bytes before the timer? What are those bytes for? Do they ever change when saving in game?
Right. However, as I found out, those 4 bytes before the in-game timer can be ignored since they are not counted to the checksum. I don't know what they are used for...
Editor, Expert player (2327)
Joined: 5/15/2007
Posts: 3915
Location: Germany
I finished a run in 11 minutes and 7 seconds. Bk2: https://tasvideos.org/UserFiles/Info/638638997623551530
  • Bizhawk 2.9.1, mGBA-core,
  • Mario & Luigi RPG (J)
Link to video General The game uses three savegames which are located in the SRAM memory domain. Savegame 1 is located in $0010-$0707. Savegame 2 is located in $0708-$0DFF. Savegame 3 is located in $0E00-$14F7. Before being saved over or wiped for the first time, the memory in the SRAM memory domain is in an "uninitialized state". At the time of writing this, not much is known about this but the general sentiment seems to be that the memory inside the SRAM battery in the game's cartridge could have any possible values and Nintendo doesn't actually wipe values to 0xFF or 0x00 nor set the memory to any specific pre-set. Bizhawk - along with other emulators - sets the SRAM memory to be filled with 0xFF as a measure to be somewhat more deterministic and to do things in a more sane way. This speedrun is possible if one assumes the SRAM memory starts out like that. If we were to work with any other "uninitialized state" where the SRAM memory could have any other possible values, a much faster speedrun could be possible in theory. The memory would have to align in such a way that the game interprets it as a valid savegame with a correct checksum. The photosprite ID for Mario and Luigi must be a good value so the game doesn't crash on the file select screen. And the starting room must be one that leads into the ending cinematics (30, 455, 478 or 479). Then it would be possible to load up the game, see a savegame is already there and loading that savegame places us right at the ending cinematics. Savegame-corruption! Each savegame has a 1-byte checksum which is the sum of values in $0010-$0013, $0018-$06FF and $0704-$0707. (Add 0x06F8 for slot 2 and 0x06F8*2 for slot 3) Also some bytes need to have certain values for the game to consider a savegame as active and valid. Because of how the game works, the game keeps savegame memory not only in SRAM but also in EWRAM. Upon loading up the game, SRAM memory is copied to EWRAM memory and when saving or copying, EWRAM memory is copied to SRAM memory. Now, in order to corrupt memory in SRAM, these tools are available to us: 1) Saving - copies values to SRAM, 8 bytes per frame, from top to bottom. 2) Copying - copies values to SRAM like saving does. 3) Deleting - sets values in SRAM to 0, 8 bytes per frame, from top to bottom. 4) "wipe all saves" - like a normal delete from top to bottom, but for all three savegames plus the Mario Bros. highscore. Done by holding L+R+A+B+Select when the game starts up and choosing yes twice. You can interrupt each of these with a hard-reset. It is not recommended to do with the real hardware as it is said that the game cartridge or the battery could take damage, but for all intents and purposes, here, it just interrupts what the game was doing. If the checksum is still correct and the bytes are telling that the savegame is active*, then the savegame will be valid even though the saving/copying/deletion procedure did not finish. (*One flag that tells if the savegame is ok is set first thing when saving and copying; said flag is unset first thing when deleting; And said flag is set to 0x00 first thing when "wiping all saves".) How savegame corruption is used in the run The values inside a savegame are ordered like this (just to give a general idea.): - Mario current room - Luigi current room, - Mario stats, direction, photo sprite ID, - Luigi stats, direction, photo sprite ID, - Items - Bunch of flags, in this order (We are thinking in 8 bytes since the game saves and deletes in 8 byte blocks:) -- "Can go to Bowser's Castle" -- "Escaping from Bowser's Castle" -- current unlocked Action Commands (in $0227~$022F, $0920~$0927 for slot 2) -- "Can use Bros Attack, items, flee in battle" (in $0230~$0237, $0928~$092F for slot 2) -- "Block Action Commands" flag (in $0240~$0247, $0938~$093F for slot 2) -- Green Pipes flag (in $0248~$024F, $0940~$0947 for slot 2) -- "Loading zone in 3rd room in Koopa Cruiser exists" flag (in $02A8~$02AF, $09A0~$09A7 for slot 2) -- "Collision box in 3rd room in Koopa Cruiser exists" flag (in $0300~$0307, $09F8~$09FF for slot 2) -- Splash Bros. Uses, Bounce Bros. Uses, etc. (in $0577~$057F, $0C6F~$0C78 for slot 2) In Toad Town is where we get our first opportunity to save the game. The saving is interrupted by hard-reset which allows anything past Luigi's photo sprite ID value to remain as 0xFF. Since the photo sprite ID must not be 0xFF (to prevent the game from crashing on the file select screen) this is the earliest point we can interrupt the saving procedure. A few frames are spent waiting before the saving starts so the in-game time advances in order to make the checksum match correctly. Now, one would think this savegame which has all flags set to 0xFF would be perfect for the purpose of advancing forward and finishing the game. Most cutscenes won't play since the game thinks we already watched them. But there were a few hurdles that needed to be gotten rid of, in the form of undesirable flags. There is a "Block all Action Commands" flag that prevents us from using any action commands on the overworld (even prevents the front brother from jumping) which must be set to 0. Let's punch smaller 0x00 holes into our savegame You can punch 256-byte sized "0x00 holes" into a savegame that was filled with 0xFF - by copying, delete & hard-reset, copy& hard-reset - and come out with the correct checksum. That's because the checksum is only 1 byte and overflows (The checksum plus 0x256 is the same value). Even though you can do that, it is not a viable option here since there are other crucial flags that must not be set to 0, such as one flag that enables the next loading zone in Koopa Cruiser, one flag that disables a collision box in Koopa Cruiser, and of course the "have spinjump / highjump / hammer / hand" flags. So a special method needed to be used to place 0x00 sections that are smaller than 256-bytes. A careful eye will have spotted that we were playing on slot 2. We did a factory wipe at the beginning of the run to set some of slot 1's memory to 0x00, up until $039F. The savegame we just made in slot 2 is now copied to slot 1 until we interrupt by hard-reset. This effectively means a small hole of 0x00 was placed in slot 1 in $0308~$039F ($0300~$0307 being the last 8-byte block that needed to be 0xFF, as it contains the "collision box in Koopa Cruiser flag"). At this point, slot 1 is still considered invalid since the checksum is incorrect, but the data remains there indefinitely. Now, slot 2 is copied to slot 3 completely. Then, slot 2 is deleted until we interrupt by hard-reset. Slot 2 is invalid. Then, slot 3 is copied back to slot 2 and we interrupt again. Slot 2 is valid again. This created a 256 byte sized hole of 0x00 in slot 2, in $0938~$0A37. Finally, slot 2 is copied to slot 1, which is interrupted, causing slot 1 to have two smaller holes of 0x00, both summing up to 256 bytes of 0x00 which causes its checksum to match and be valid. The two smaller holes of 0x00 in slot 1 are located in $0240~$02A7 and $0308~$039F. Any values before $0240 and after $02A7 and before $0308 must be 0xFF because important flags are located there. And we wanted to squish $0240~$0247 to zero as it contains the bad flag that blocks action commands. If we hadn't done this, we would have gotten stuck in Koopa Cruiser (missing loading zone or collision box stopping us) or would have had other problems with progression (no action commands, no jumping in Stardust Fields). Using glitched Badge When items in memory are set as 0xFF, the game reads that as "the player doesn't have it". Because all items are set as 0xFF, the player doesn't have any badge or pants but is still allowed to switch them. In this case, a glitch happens where the player can choose their clothing or badge in a list of glitched options. Strangely, this list is different depending what room you are in. I choose a badge for Mario and Luigi that raises Pow and allows me to defeat Fawful by jumping once each. Choosing this badge turned out to be fastest to do in the 2nd room of Koopa Cruiser. Why go to Hohooros? For certain gameplay events, the game uses a special timer (called "event timer"). This timer is used by a surfing minigame in Oho Ocean, a jumping minigame in Guffawha Ruins, a time-limit block in Gwarhar Lagoon, a time-limit block in Bowser's Castle and the escape from Bowser's Castle (there may be more). If you enter Bowser's Castle when the game thinks you are escaping, it checks for the event timer to trigger a game-over if it reaches 0. You can bypass that if you make sure the event timer is non-zero, such as when failing the Hohooros minigame and then leaving. There is no other way around it. Since most flags are set to 0xFF, Hohooros is considered to be already beaten, but the flag for the check if you are touching the ground is also active, allowing us to do the minigame again. I was also considering going to the surfing minigame instead (we have set the green pipes flag Edit: Nvm, I lied. But we could set it if we want.), but I think it would take longer. Firedash glitch This glitch only works on the Japanese version of the game. It is used in this run in order to travel through the mountain area faster. This glitch happens if you use Firedash right before a ledge which causes the brothers to enter a glitched state because Luigi is allowed to move on when Mario behind Luigi is not ready yet. While working on this run, I found a different Firedash glitch which I will call "Firedash speed glitch". Firedash speed glitch When doing a firedash that has Luigi fall off a ledge, if Luigi gets boosted by an adjacent ledge, then it is possible that the brothers will be allowed to move around the room at 768 or even 1024 speed (512 speed is normal walking speed). Deathwarping? I tried saving in Hoohoo Village and deathwarping after getting the event timer at Hohooros, but this turned out to be about 10 seconds slower. Why not submit this I think some rooms should still be looked at for improvements before this should be submitted to TASvideos. One NPC boost off a blue Toad couldn't be manipulated at the Toad Town plaza. One NPC had bad placement in Hoohoo Village so I had to go around. I didn't spend too much time on optimizing the Firedash glitch in the mountain area. "Firedash speed glitch" has potential for use in Koopa Cruiser. New Luascript Version 0.13 of my luascript, which allows the script to run on the latest Bizhawk and fixes many things, will be released soon™. I will make a new post when the time comes. EDIT: I renamed "factory wipe" to "wipe all saves". The word factory wipe implies that the SRAM battery is shipped with all 0x00, but the game's manual does not mention the word "factory wipe".
Migu
He/Him
Player (181)
Joined: 10/3/2015
Posts: 61
Location: Louisiana
Wow, that was quick after finding the save corruption! But I guess there wasn't much to optimize. So those 4 bytes are first set to 0 when you save (or earlier?) and then when you corrupt the save, as long as they stay 0, it works? I guess you can't change the map you saved on to something useful because you're only writing FF?
Editor, Expert player (2327)
Joined: 5/15/2007
Posts: 3915
Location: Germany
Migu wrote:
Wow, that was quick after finding the save corruption! But I guess there wasn't much to optimize.
I did some optimizing, but a few rooms could probably be improved. If you are interested, you can help me optimize this run before we are submitting to TASvideos.
So those 4 bytes are first set to 0 when you save (or earlier?) and then when you corrupt the save, as long as they stay 0, it works?
I think you are refering to older information. Please read my information write-up in the previous post. The in-game timer, which is the last 4 bytes of a savegame, is set to 0xFFFF when saving and hard-resetting in Toad Town. The 4 bytes prior to that have an unknown purpose and are not counted to the savegame's checksum. I erroneously counted them to the savegame's checksum before, which is why I came up with the wrong assumption that they are used as a counter-measure against savegame corruption.
I guess you can't change the map you saved on to something useful because you're only writing FF?
I have not tried for it extensively but theoretically you can visit map 0, which is useless for a speedrun. Otherwise, you can only set it to 0xFFFF (65535) which crashes. Other values may be possible if subframe resets become available.
Editor, Expert player (2327)
Joined: 5/15/2007
Posts: 3915
Location: Germany
MLSS Luascript v0.13
Changes in 0.13			14th Oct 2024
- The script now runs in Bizhawk 2.9.x.
- The script now uses Arial font by default.
- On displays that use up and down arrows, you can now scroll up or down via mouse wheel.
- The emulator will assume the user's original window size after the script stops.
- Fixed errors arising from loading a branch in TAStudio.
- Fixed that displays could become positioned offscreen if reducing padding in the settings or by closing "Actors"/"Overview".
- The script will recognize the two new E3 proto ROMs but there is currently no support.
- Flags: Added some room-related flags.
- Actors: Added a button to enable viewing collision boxes.
- Actors: Added a button to enable showing loading zones (still in an unfinished state).
- Actors: Fixed issue where the actors list could become empty if loading a state from ingame while on the title screen.
- Run Event: Removed Mine Cart Minigame on the Japanese version (crashes).
- Savegames: "Auto-Apply Checksum" now triggers on each frame when the client is paused
- Savegames: Checksum will be updated each frame when client is paused or when a movie is active.
- Savegames: Now shows the required checksum next to the current checksum.
- Savegames: Valid savegame will be shown with a green mark; invalid savegame will be shown with a red !-sign.
- Savegames: Fixed a problem where the checksum was not calculated correctly if bytes near the end of the file were non-zero.
- Savegames: Added "Auto-Apply Bytes" which continuously sets bytes required for the savegames to be valid on top of a correct checksum.
- Savegames: Added some Item addresses, increasing entries from 107 to 178.
- Notifications: Fixed that value changes were printed when the Actors display was active and loading a state from ingame while on the title screen. 
Skilled player (1735)
Joined: 9/17/2009
Posts: 4975
Location: ̶C̶a̶n̶a̶d̶a̶ "Kanatah"
Woah, a glitched run finally exists! I looked through this thread every time it got an update, and I knew a glitched run was attempted for years without success. Congrats! 1. Does save corruption exist for the other Mario & Luigi games? 2. Assuming a run that does this gets published, would you or others still try to do that ACE run as a "no save glitch" category? 3. What other stuff can you do with this? Anything fun?

1729290126