ML+ Hack! Add to, subtract from, or set your max health!

Nov 8, 2009 at 6:32 AM
Been here way too long...
"Ha! Ha! Ha! Mega Man is no match for my Mimiga Man!"
Join Date: Jun 22, 2008
Posts: 251
Well, I found myself with a little bit of spare time on my hands, and I was itching to work with assembly, cause I hadn't in a few months, so I made this hack to ML+.

The best part of this hack is that you can implement it into a mod at any time, and it won't screw up any ML+'s that you already are using. Before I go on, though, I should say:


Now, thats not to say don't use it. As long as you pay attention to what you are doing, you will be fine. Now, here is how to use the hack:

Saying ML+0XXX will still add XXX to your max and current health. This means you don't have to change your existing ML+'s unless you were adding more than 1000 health at once. Note: before I hacked this function, there was an automatic limit to your max health of 232. I had to remove this limit to save space, and I don't know what effects that will have. You won't run into this unless you plan to give quote more than 232 health anyway.

Saying ML+1XXX will subtract XXX from your max and current health. But be wary: If you subtract enough health that your max OR your current health is zero or less than zero, Cave Story will crash. You should be able to get around this by adding a LI+9999 before subtracting health.

Saying ML+2XXX will set your current and max health to XXX.

And, some examples!

<MSG<GIT1006Got a =Life Capsule=!<WAI0160<NOD<RMU<ML+0003
Max health increased by 3!<NOD<END

<MSG<GIT1006Got a =Life Capsule=!<WAI0160<NOD<RMU<ML+1003
Max health decreased by 3!<NOD<END

<MSG<GIT1006Got a =Life Capsule=!<WAI0160<NOD<RMU<ML+2003
Max health set to 3!<NOD<END

Event 400 adds 3 health

Event 401 subtracts 3 health

Event 402 sets your health to 3

For you assembly junkies, here is the fully commented code used in this hack:

00419CA6  PUSH EBP                                 ;  saves old stack base
00419CA7  MOV EBP,ESP                              ;  new stack base at current stack top
00419CA9  MOVSX EAX,WORD PTR SS:[EBP+8]            ;  puts ML+ param into EAX
00419CAD  CMP EAX,7D0                              ;  compare ML+ param with 2000
00419CB2  JLE SHORT Doukutsu.00419CCD              ;  jump to next test
00419CB4  SUB EAX,7D0                              ;  subtracts 2000 from ML+ param, leaving the new number
00419CB9  MOV WORD PTR DS:[49E6D0],AX              ;  low 2 bytes of new health put into max health
00419CBF  MOV WORD PTR DS:[49E6CC],AX              ;  low 2 bytes of new health put into current health
00419CC5  MOV WORD PTR DS:[49E6D4],AX              ;  low 2 bytes of new health put into displayed health (yellow bar)
00419CCB  JMP SHORT Doukutsu.00419D0E              ;  jump to function exit point
00419CCD  CMP EAX,3E8                              ;  compares ML+ param with 1000
00419CD2  JLE SHORT Doukutsu.00419CF0              ;  jump to next test
00419CD4  SUB EAX,3E8                              ;  subtract 1000 from ML+ leaving number to be removed
00419CD9  SUB WORD PTR DS:[49E6D0],AX              ;  subtract number from max health
00419CE0  SUB WORD PTR DS:[49E6CC],AX              ;  subtract number from current health
00419CE7  SUB WORD PTR DS:[49E6D4],AX              ;  subtract number from displayed health (yellow bar)
00419CEE  JMP SHORT Doukutsu.00419D0E              ;  jump to function exit point
00419CF0  ADD WORD PTR DS:[49E6D0],AX              ;  add number to max health
00419CF7  ADD WORD PTR DS:[49E6CC],AX              ;  add number to current health
00419CFE  ADD WORD PTR DS:[49E6D4],AX              ;  add number to displayed health (yellow bar)
00419D05  NOP
00419D06  NOP
00419D07  NOP
00419D08  NOP
00419D09  NOP
00419D0A  NOP
00419D0B  NOP
00419D0C  NOP
00419D0D  NOP
00419D0E  POP EBP                                  ;  return stack pointer from previous function
00419D0F  RETN                                     ;  return to caller

Since I changed the function entry point, I also had to change the one call to the function to reflect that. (Interesting note: I was a single byte short of being able to fit this in without having to change the call location. I considered removing the push/pop of EBP in the original function, but decided not to since I had already changed the call location anyway)

00422730  CALL Doukutsu.00419CA6

And, of course, I have a pre-hacked executable that you can use without needing to know any assembly at all. If you want to add this to an in progress mod, you may need to change some other settings, but starting a mod from scratch using this executable will work with no additional changes. It will even work in normal Cave Story.

Link. Enjoy!
Nov 8, 2009 at 8:11 PM
Been here way too long...
"Life begins and ends with Nu."
Join Date: Jan 4, 2008
Location: Lingerie, but also, like, fancy curtains
Posts: 3054
Nice work, this'll prove useful for a lot of people.
Of course, you could just use ml=, but that would need people to be a lot more tsc savvy then they currently are.
Also, looking at this, I sorta realize how damn smart you are compared to me.

Nov 8, 2009 at 10:22 PM
"Life begins and ends with Nu."
Join Date: Dec 30, 2005
Location: Germany
Posts: 3218
Age: 30
Dooey, which programm do you use? RuneLancers Assembly compiler is missing some commands and I want to use all.
Great work btw.
Nov 9, 2009 at 12:30 AM
"Life begins and ends with Nu."
Join Date: Dec 30, 2005
Location: Germany
Posts: 3218
Age: 30
Hm :/ Any different programm? A easy assembly compiler like Runelancer wrote?
Nov 9, 2009 at 2:27 AM
Level 73 Procrastinator
"Life begins and ends with Nu."
Join Date: Apr 6, 2009
Location: Forgotten Tower
Posts: 2052
More shortcuts!

Assembly shortcuts :D;
I'm already thinking up uses for this...
Your assembly know-how just amazes me.