1 2
17 18 19
24 25
Editor, Expert player (2330)
Joined: 5/15/2007
Posts: 3933
Location: Germany
Thanks but it still has oob memory reads. http://pastebin.com/hjWYDCUd
jdaster64
He/Him
Joined: 12/1/2012
Posts: 103
Location: New Donk City
Not familiar with BizHawk's memory domains, but actordata() should probably return the value at that address - 0x2000000 rather than just the value; not sure if there are other cases where I dereference an in-memory pointer. I can add support for J/E tonight and do the conversion if you'd like; what are you doing to tell the version of the current ROM, so I can keep it consistent with that?
Skilled player (1741)
Joined: 9/17/2009
Posts: 4981
Location: ̶C̶a̶n̶a̶d̶a̶ "Kanatah"
I'm not sure if this is the bug, but in line 599, you use EWRAM, yet in the comment below it says
 ACTOR_DATA_START=0x0fdc -- different in J    --iwram address
which I'm not sure if it is supposed to be a different memory region.
Editor, Expert player (2330)
Joined: 5/15/2007
Posts: 3933
Location: Germany
jdaster64 wrote:
Not familiar with BizHawk's memory domains, but actordata() should probably return the value at that address - 0x2000000 rather than just the value; not sure if there are other cases where I dereference an in-memory pointer. I can add support for J/E tonight and do the conversion if you'd like; what are you doing to tell the version of the current ROM, so I can keep it consistent with that?
Thanks that would be awesome.
Language: Lua

local GameVersion=0 local GameVersionText="" if gameinfo.getromhash()=="7C303CDDE5061EE329296948060B875CB50BA410" then GameVersion=1 -- usa GameVersionText="USA" elseif gameinfo.getromhash()=="EDC538AC505BFCD337ABDD03B3A6F2744D81EAAB" then GameVersion=2 -- jp GameVersionText="Japan" elseif gameinfo.getromhash()=="FA2314C2FBE0DB1AB17175F8BE7CCEB0AB084EFC" then GameVersion=3 -- eu GameVersionText="Europe" else GameVersion=4 GameVersionText="Game not recognized" end
Can you make your damage prediction with parameters for bro pow, enemy def, etc.? Will make it easier to make a calculator. @jlun2, I honestly had no idea what I was doing.
jdaster64
He/Him
Joined: 12/1/2012
Posts: 103
Location: New Donk City
Just finished refactoring the script to support J/E; I'll convert to BizHawk support in the next couple of days, and might add STACHE discounts as well. Currently, the script's only going to accept enemy target and number of hits as parameters, and use the current stats of Mario/Luigi and the target enemy to calculate damage; if you want to have it calculated on an arbitrary set of inputs, I can add that functionality, but that might take a bit longer; this would have to be a minimal set of inputs to do all calculations: DamageCalculatorInput { PlayerPow = ... PlayerPowMult = ... PlayerBadgeEffect = ... EnemyType (ID) = ... EnemyDef = ... EnemyDefMult = ... GreatForce = ... MushroomCounts = ... CurrentHammer = ... IsLucky = ... } It would be doable, although for my sanity's sake, I'd rather it still autodetect the game region, as that'd be a major pain to make configurable (plus, you could always change the GameVersion/Region before doing the call and set it back afterwards).
jdaster64
He/Him
Joined: 12/1/2012
Posts: 103
Location: New Donk City
All right, I finished updating the script for VBA; before I port it to BizHawk, let me make sure these interfaces seem all right... Damage calculation: For damage calculation, you need to pass this struct:
DamageCalculationInput = {
    EnemyID,
    PlayerID,
    
    PlayerPow,
    PlayerPowMult,
    PlayerBadgeEffect,
    EnemyType,
    EnemyDef,
    EnemyDefMult,
    MushroomCounts = {n, s, u, m},
    CurrentHammer,
    GreatForce,
    IsLucky
}
You can either set EnemyID to an actor # (0-5) and it'll calculate the attack power based on the in-game battle data, or set all of the inputs after PlayerID to calculate what the attack power would be without using the in-game data. PlayerID should never be set; it will be set automatically if you use EnemyID, based on which attack you request the power of. The functions you call with that data are as follows: Solo attacks: {mario | luigi}{Jump | Hammer | Hand | CounterJ | CounterH}(dci) Examples: marioJump(dci), luigiCounterH(dci) Bros. attacks: {splash | bounce | chopper | knockback | fire | thunder | swing | cyclone}{Bros | BrosAdv}(dci, (hits/strength if applicable)) Examples: splashBros(dci), knockbackBrosAdv(dci, hits), swingBros(dci, strength) Lucky! chance: To calculate the chance of a Lucky! hit, use the following struct:
LuckyCalculationInput = {
    EnemyID,
    PlayerID,

    PlayerStache,
    PlayerLevel,
    EnemyStache,
    EnemyLevel,
    LuckyAttack
}
Populate EnemyID & PlayerID (use MarioActorID or LuigiActorID for that) to read from memory in battle, or the rest of the values to try out arbitrary inputs, then call the function luckyChance(lci). Doesn't support the Lucky Mushroom effect, nor do I intend to support it since it's implicitly supported in the in-battle case anyway. Stache discounts: Call buyPrice(base,dg,stache) or sellPrice(base,dg,stache), using the base price (not the sell price) of the item, its discount group (0 to 5), and the appropriate STACHE value (Mario's or Luigi's alone if only he can use the item, or their average rounded down if either can). RNG stuff: nthRandRange(n,range): Returns the result of rand(0,range) using the Nth RNG value. N is 0-indexed, not 1-indexed, and the function isn't guaranteed to work for N greater than 290-ish. untwistInRange(n,range): Given a desired value N as the result of rand(0, range), returns an RNG seed value that produces the desired result. Can be useful for testing something with a desired random value, although it won't be of any help if the random engine is pointing near the end of the random buffer.
jdaster64
He/Him
Joined: 12/1/2012
Posts: 103
Location: New Donk City
Here's the script for BizHawk; let me know if anything else needs explanation. https://www.dropbox.com/s/psvlichjvegg3o3/jdaster64_mlss_scripts_v2.lua?dl=0
Editor, Expert player (2330)
Joined: 5/15/2007
Posts: 3933
Location: Germany
@jdaster: I don't know if I will figure it out. But I'll take a look at it later. --- Some strange bugs: Link to video (starts 5:30) - Hint guy's dialogue box is glitching up. Link to video - Thunder Hand on Mario, falling off ledge in Roy's room. Causes glitchy movement, similar to the ancient Thunderhand clip stuff... Edit: Roy's room glitch is confirmed now. Will probably do some investigating later. It happens because Mario is pushed back onto the ground he just fell off. The game doesn't expect this to happen and glitches up.
Editor, Expert player (2330)
Joined: 5/15/2007
Posts: 3933
Location: Germany
Does Super and Ultra hammer boost your power, and if so how much?
Former player
Joined: 4/18/2015
Posts: 168
Location: Canada
MUGG wrote:
Does Super and Ultra hammer boost your power, and if so how much?
EDIT: My bad, my information was wrong.
jdaster64
He/Him
Joined: 12/1/2012
Posts: 103
Location: New Donk City
False, they do actually affect your power. Luigi's average damage goes down a bit each upgrade (although the maximum goes up a bit); don't know about Mario's offhand, but it does change as well. The constants are taken into account in the damage calculation scripts, at any rate. Edit, relative powers: Mario Normal - 0.9, 1.0, 1.1 Mario Super - 0.8, 1.0, 1.2 Mario Ultra - 0.8, 1.05, 1.3 Mario Lucky - 2.1 Luigi Normal - 1.0, 1.15, 1.3 Luigi Super - 0.9, 1.13, 1.36 Luigi Ultra - 0.8, 1.1, 1.4 Luigi Lucky - 2.5 Edit again: No difference on Bros. attacks, since I didn't say so explicitly.
Editor, Expert player (2330)
Joined: 5/15/2007
Posts: 3933
Location: Germany
MUGG wrote:
ThatEpicYoshi♣ on Youtube has commented on my glitch compilation video about a potential new glitch: as i got to the air port area i was messing around with mario and luigi's abilities (mainly fire-thunderhand) i was near the block, i actually hit the block a few inches away from the save album. then i ended up testing the elemental hand near the save album and suddleny it just started floating to the other block (that one was a wide M & L block.) then it stayed. i couldn't hit the save album because it was literally inside the wide one so i went to another area and back and it was in it's rightufl place. i'm not exactly sure what caused it. it might've been the wide block. idk, but this seems to be an un-discovered glitch. They said they used normal VBA 1.8.0-beta 3. Just posting this here for future reference.
Glitch has been confirmed on mgba. Will make video later I think. How to The place is top right on this map. 1) hit the wide block 2) before the wide block becomes solid, hit the saveblock, then cancel. 3) wait until the wide block should become solid. Instead of becoming solid, the saveblock will move. Info When hitting the wide block, it occupies event layer 2. Remember, I wrote information on event layers here. It seems to put event pointers on what I think is some kind of stack, at $004AD0 and $004AE0. Additionally, $004B8C acts as a timer that determines when the wide block should become solid. But if you hit the nearby saveblock, the stacked event pointers are overwritten. And weird stuff happens -> The saveblock moves. I remember seeing similar weirdness when I tested events back when I added the functionality to my luascript. Random sprites would move in random directions etc. Because the game jumped to a bad ROM pointer. Now, if this could be done somewhere else in the game..... Or if it can be influenced..... Needs testing. You can hit the saveblock at close to the same time the wide block gets solid for some strange outcomes, e.g.: Screen may fade black without sending you to the save screen If you hit the saveblock while it is moving, it will stop and the wide block will be alive forever. You can farm free money forever from this block since the timer already reached the end (but the block is not solid). It will turn solid when you leave the room, though. Edit: Actually, the overwritten events aren't the cause of the bug, it seems. It seems to be a very minor oversight that the event is handled slightly differently. $004C14 turns different values between the "hit saveblock" and "don't hit saveblock" cases at the time the wide block is supposed to get solid. Not sure what this address does but it's related to the bug. Edit: There is a similar room in Roy's room in Bowser's castle. But when you hit the saveblock and cancel, the wide block is solid immediately. The only way to make the glitch work there is to hit it just before the wide block is going to turn solid. The saveblock will move to the left, into the wide block. There don't seem to be any more places in the game where a wide block is near a saveblock. Link to video -------- @jdaster, sorry I have not added your snippets to my script yet. I will get to it before I make the new TAS which will hopefully happen sometime in my life.
Editor
Joined: 11/3/2013
Posts: 506
Nice find! Obviously no speedrunning application but a fun little glitch. Considering how easy it is to perform in real time, it's pretty amazing it went undiscovered so long.
Skilled player (1741)
Joined: 9/17/2009
Posts: 4981
Location: ̶C̶a̶n̶a̶d̶a̶ "Kanatah"
MUGG wrote:
But if you hit the nearby saveblock, the stacked event pointers are overwritten. And weird stuff happens -> The saveblock moves. I remember seeing similar weirdness when I tested events back when I added the functionality to my luascript. Random sprites would move in random directions etc. Because the game jumped to a bad ROM pointer. Now, if this could be done somewhere else in the game..... Or if it can be influenced..... Needs testing. You can hit the saveblock at close to the same time the wide block gets solid for some strange outcomes, e.g.: Screen may fade black without sending you to the save screen If you hit the saveblock while it is moving, it will stop and the wide block will be alive forever. You can farm free money forever from this block since the timer already reached the end (but the block is not solid). It will turn solid when you leave the room, though. Edit: Actually, the overwritten events aren't the cause of the bug, it seems. It seems to be a very minor oversight that the event is handled slightly differently. $004C14 turns different values between the "hit saveblock" and "don't hit saveblock" cases at the time the wide block is supposed to get solid. Not sure what this address does but it's related to the bug.
Wait, so is there any actual effect when event pointers get overwritten to something else? That seems like some exploit waiting to happen if so.
Editor, Expert player (2330)
Joined: 5/15/2007
Posts: 3933
Location: Germany
That was my initial impression but I think that's not what happens. If I edit those stacked event pointers back, it doesn't change the outcome. Not sure if it can be exploited but I'll be testing some more ideas (such as 10-coin blocks with saveblocks, if I can find such places).
Editor, Expert player (2330)
Joined: 5/15/2007
Posts: 3933
Location: Germany
I'm starting to understand the bug better. When hitting the wide block, layer 2 holds event pointer related to it. But if you do something that occupies layer 2 as well - such as hitting a saveblock or standing in front of a person or map - then the movement bug happens. It doesn't seem like anything else happens instead of the movement. Edit: There is a wide block in Joke's end (+ a fire place with a cutscene) and in Fungitown (+ 2 NPCs) but the glitch effects aren't very special. The two Toads in Fungitown can't be talked to after the glitch, but no movement happens. You can walk around with speech bubbles there too. If you do it at the Joke's end fire place, the cutscene event can be stopped which can cause the screen to be stuck forever. Edit: Some loading zones are tied to events. That's why this happens. In this case, Mario and Luigi are the object that moves to the wideblock. Note how the wide block disappears. You can also, alternatively, make a brother disappear (which can softlock the game somewhat). Edit:
Editor, Expert player (2330)
Joined: 5/15/2007
Posts: 3933
Location: Germany
If you do these steps, you can have Mario back early during the "Mario is sick" part in Little Fungitown: 1) activate wide block in the entrance room of the embassy 2) right before the timer runs out ($004b8c), enter left room. If done correctly, screen fades to black and stays black. Luigi will be trying to walk towards the wide block. You can pause and unpause to make screen to normal again. 3) hit the wide block before you reach the middle. If you reach the middle, Luigi disappears and game is softlocked. But if you hit the block, the block disappears. 4) This is the strange thing: Mario is now considered active. You can press B and he will fly into the room. You can touch him and then walk around with both brothers. I will make a video. Details: - If you enter the room where Mario rests as Mario, game softlocks. If you enter it as Luigi, you lose control of Mario. But if you leave the room and press Start, he will appear again and you can control them separately. - When separated, you can switch between the two brothers across screens. But if you go to the middle part of Fungitown, you can't switch anymore - not even when controlling both brothers. You will then have to go back and touch the bro that was left behind. - Using the lift with both brothers or as single Mario will softlock the game. - You can use the green pipe and do something else. - If you control both brothers and use the flagpole, you can separate the brothers while in that room. They will reunite when leaving the room. - If you get the herb and try to go to the embassy (as Luigi in front), the "Peach is kidnapped" cutscene plays. The brothers will be in the top left wall but can jump out of it. If you enter the room where Mario rests now as Mario in front, the cutscene where Luigi wakes up Mario is skipped. You will have to walk back to the castle and possibly will have to glitch through the throne room door to make the cutscene continue. There are a number of event-related glitches now. But we can't abuse them really... Link to video Edit: There is more strange stuff you can do with the block in Little Fungitown. Maybe another video is coming.
Editor, Expert player (2330)
Joined: 5/15/2007
Posts: 3933
Location: Germany
I investigated the Information Store Dialogue Glitch by trial and error testing. The main culprit seems to be $014579 (Combined WRAM). This part of memory handles speech bubbles, text/character pointers, etc. When you repeatedly talk to the hint guy, the address above will eventually decrease by 0x12 over and over. When you first enter the store, it will be 0x4A. The glitch occurs if it is 0x26 before you talk to the guy, unless you click the dialogue away. I'm not sure what exactly is the purpose of that address but speech bubble graphics glitch if it has a bad value. Testing on each system/emulator: VBA-M: The finder used this emu. Game survives the glitch. Strange memory corruption/glitchiness. mGBA 0.4.0 core in Bizhawk: Game freezes after you select a dialogue option VBA v24 svn480: untested Real console: untested? VBA-Next core in Bizhawk: untested ~~~ The glitch does survive in mGBA 0.4.0 if you edit the address to different values. Then something glitchy like this could occur: The outcomes can be severe (game crashing when pausing or re-entering the room). ~~~ Here is a lua I use to investigate wideblock/dialogue glitches. There seems to be a speech bubble pointer for each room, so they would have to be searched all the time... I'm thinking the bug is because of the speech bubble that can't be clicked away immediately. So I'm looking for more NPCs that have those.
Editor, Expert player (2330)
Joined: 5/15/2007
Posts: 3933
Location: Germany
Why is it that enemies have 0 POW in battle (as can be seen when using the MLSS script) but they do have a non-zero POW in the guide? I tried editing an enemy's Pow address but its attack damage didn't change. Its attack damage only changed after editing his Pow modifier. Def, Stache, HP, Speed are loaded to enemy slots, but Pow isn't.
jdaster64
He/Him
Joined: 12/1/2012
Posts: 103
Location: New Donk City
POW is determined by the attack used, not the enemy; there isn't a "POW stat" per se.
Post subject: turn html off
Editor, Expert player (2330)
Joined: 5/15/2007
Posts: 3933
Location: Germany
Research on audio. This is for the US version but it probably works the same in all versions.
$000910 ~ $000913 -- This location changes when brothers jump (not sure why). Can be used to make game change BGM to unused tracks probably due to a glitch.
(2D 00 06 00 sets it to unused music that hasn't been documented on tcrf yet. Not sure if those values always work.)

$000915 -- if 0x01, BGM plays. If frozen at 0x00, it's muted or hangs.

$000918 ~ $00091D -- Volume of sound channels. 0xFF means full, 0x80 means half, 0x00 means silence.
* $000919 = SFX (Most but not all)
* $00091B = BGM

$000924 -- SFX pace. 0x4B seems default. <0x4B means faster. >0x4B means slower. 0x00 = game freeze (when attempting to play music)

$000928 -- BGM pace. 0x4B seems default. <0x4B means faster. >0x4B means slower. 0x00 = game freeze (when attempting to play music)

$00092C -- ? pace.
Todo: I think there is an audio pitch address but I can't find it right now. Maybe some people will know why I did this research..... (yes, Youtube copyright claims etc.) I might add functionality relating to audio to the luascript later. I finished adding it to the script and it will be in the next version. (Although next version may be a while.. I can post my current script if there is interest though.)
Editor, Expert player (2330)
Joined: 5/15/2007
Posts: 3933
Location: Germany
I'm looking to add some savegame functionalities to the script, and I need some help. $001e7e (EWRAM), first three bits are flags for whether the three savegames are occupied. Savegame memory range: 1) $001e88 - $00257f 2) $002580 - $002c77 3) $002c78 - $00336f $0d40 (IWRAM), the 2nd or 3rd or 4th bit is set depending which savegame is currently played on. When no bit is set, it seems to default to file 1).
  • Edit:Doesn't seem quite right. 2nd bit is set when a savegame is already saved. 3rd bit is set if savegame 2 is used. 4th bit is set when savegame 3 is used. If 3rd and 4th bit aren't set, it's savegame 1.
    	if bit.check(memory.read_u8(0x0d40),2) then
    		--current slot: 2
    	elseif bit.check(memory.read_u8(0x0d40),3) then
    		--current slot: 3
    	else
    		--current slot: 1
    	end
My question: When I use lua to copy all values from 1) to 2) and set the flag in $001e7e, it keeps it and treats it like a savegame. But when I reset the game, it wipes the dirty file, even after I use a saveblock. How does the game determine if it's dirty? Where is the checksum and how does it work? Edit: Looks like this topic has the answer: http://s3.zetaboards.com/Lighthouse_of_Yoshi/topic/7375916/1/ I'm going to try it later. (add all bytes of a savegame and write last 8 bits to certain address)
Skilled player (1741)
Joined: 9/17/2009
Posts: 4981
Location: ̶C̶a̶n̶a̶d̶a̶ "Kanatah"
Have you tried opening the savefiles in a hexeditor? Also, if it helps, I know at least one game where at the beginning of the save, it keeps track of the amount of bytes saved at the beginning, so if it doesn't match with file size, it deletes the save. Maybe some check like that?
Editor, Expert player (2330)
Joined: 5/15/2007
Posts: 3933
Location: Germany
The zetaboards topic says it adds all bytes between $001e8C - $00257f and saves the trailing 8 bit to $001e89 (the checksum). <-- I doubt that's really the checksum... Savegame (File 1) range is actually $001e88 - $00257f. That's all addresses that get zeroed if you attempt to delete. If I copy from File 1 to File 2 it keeps it, but when I use lua to write to File 2 (and the values are exactly the same), it wipes it off on reset. Help is appreciated. Edit: My savegame script so far. (Bizhawk 1.11.6) http://pastebin.com/zcjfCFkz Again, the goal is to make it so that you can copy from e.g. slot 1 to 2 and it should keep it when resetting the game.
Skilled player (1741)
Joined: 9/17/2009
Posts: 4981
Location: ̶C̶a̶n̶a̶d̶a̶ "Kanatah"
Have you tried comparing a savefile with only File 1 and a savefile with File 1 copied to File 2 using a hex editor? Maybe the bytes that add up take that into account? Or maybe, comparing the copied File 2 with a savefile that does just that (File 1 -> File 2), but with some value in File 2 advanced by 1 and see what gets changed.
1 2
17 18 19
24 25