The Complex Code of Mega Man 2 and How Zipping Works - Behind the Code

แชร์
ฝัง
  • เผยแพร่เมื่อ 25 พ.ย. 2024

ความคิดเห็น • 275

  • @musickid43
    @musickid43 2 ปีที่แล้ว +361

    There are 2 things developers always struggle with. Cache invalidation, naming things, and off by one errors.

    • @VinsCool
      @VinsCool 2 ปีที่แล้ว +35

      I see what you did here
      Seems like a carry flag was also incorrectly set in this statement :p

    • @lazsynth
      @lazsynth 2 ปีที่แล้ว +2

      loooool

    • @CarbonRollerCaco
      @CarbonRollerCaco 2 ปีที่แล้ว +9

      *4 things
      Because the off-by-one here was positive.

    • @drygordspellweaver8761
      @drygordspellweaver8761 2 ปีที่แล้ว +1

      I *C* what you did there

    • @owenwexler7214
      @owenwexler7214 2 ปีที่แล้ว +14

      Not to
      asynchronous code
      mention

  • @Darxide23
    @Darxide23 2 ปีที่แล้ว +173

    Off-by-one is a plague that haunts the nightmares of coders.

    • @Phroggster
      @Phroggster 2 ปีที่แล้ว +3

      Fenceposts are just too darned challenging to accurately count.

    • @GameDevMadeEasy
      @GameDevMadeEasy 2 ปีที่แล้ว +5

      I recently had to fix an off-by-one bug in work code. Was a pain to find and fix, that's for sure.

    • @angeldude101
      @angeldude101 2 ปีที่แล้ว +10

      It's one of the 2 hard problems in computer science, alongside cache invalidation and naming things.

    • @dmas7749
      @dmas7749 ปีที่แล้ว

      @@angeldude101 naming things is easily the hardest because that requires creativity

    • @sourandbitter3062
      @sourandbitter3062 11 หลายเดือนก่อน

      For Of loops to the rescue

  • @NonRandomUser
    @NonRandomUser 2 ปีที่แล้ว +13

    "It's just one pixel; no one's going to notice that insignificant discrepancy."

  • @Brocknoth
    @Brocknoth 2 ปีที่แล้ว +44

    As a person who can't code to save his life that was really, really informative and easy to understand. Fascinating stuff honestly.

  • @arciks11
    @arciks11 2 ปีที่แล้ว +184

    2:30 To answer your rhetorical question. Yes, Mega Man 3 likes to REALLY slowdown. And I know there is an improvement hack for it that significantly minimizes the slowdown that occurs. So Comparing regular MM3 with that hack could shed some light on how that slowdown was fixed.
    In addition to that Mega Man 3 was the entry that removed a physics quirk where Mega Man would slightly slide forwards after stopping which made first 2 Mega Men feel kinda slippery, so that could also be looked into.
    Another Bug is with selecting Rush Items. If you say have Search Snake and go right on select screen you will select an empty Rush Item in that slot. If you then get weapon energy and use it, you will unlock access to it before you're meant to.
    I like Mega Man 3 but of all 6 NES entries it's the one that's held together by glue and prayers the most.

    • @DaWhiteTyger
      @DaWhiteTyger 2 ปีที่แล้ว +9

      I know that's right, I felt it growing up when it released and was like, "This feels different than MM2, like it's been added upon..." Thanks for helping to confirm what I've been pondering for years. Now, to find that 'hack' you mentioned. *Rubs hands together*

    • @arciks11
      @arciks11 2 ปีที่แล้ว +18

      @@DaWhiteTyger OK I think youtube ate my previous two comments due to mentioning site kinda directly.
      Hack is called Mega Man 3 Improvement.
      It's on a site that is heavily used for "romhacking" on the "net"

    • @vuurniacsquarewave5091
      @vuurniacsquarewave5091 2 ปีที่แล้ว +7

      There are definitely some performance issues there, a ton of unused content (sound effects, graphics, an intro that was never actually made) and even some sloppy MMC3 usage. Many times the IRQ fires one or two scanlines too early/late and screen splits are therefore not made at the right place. This is noticeable at the stage select screen and any boss fights where a moving enemy is part of the background. I personally wonder how difficult it could be to fix the weapon energy drain bug of the Top Spin. The energy seems to get drained when you are invulnerable after a hit and the enemy is not insta-killed by the attack.

    • @dudujencarelli
      @dudujencarelli 2 ปีที่แล้ว +5

      Which is ironic, considering that Mega Man 7 on the SNES looks like a polished work of 2D sidescrolling art, and that game was in fact put together in 3 months!

    • @Valientlink
      @Valientlink 2 ปีที่แล้ว +3

      I honestly liked the physics of megaman 1 and 2 more I think, he just felt so much more airborne. MM3 onwards you can really feel that "snap" to the floor

  • @meta04
    @meta04 2 ปีที่แล้ว +2

    3:25 An amazing sequel to Bismuth's deadpan "Usually this is done by repeatedly jumping, but that's not an option [in the A button challenge]. Figuring out why is left as an exercise to the viewer." delivery...

  • @alexhobbs1208
    @alexhobbs1208 2 ปีที่แล้ว +36

    I may not understand everything happening but I thoroughly enjoy these breakdowns

  • @Wyrdwad
    @Wyrdwad 2 ปีที่แล้ว +57

    Adding the extra purple pixel to Mega Man's center to indicate his actual position has the unintended side effect of making it look like he's sticking his tongue out all derpy-like. ;)
    Just figured I'd point that out! Heheh.
    Awesome video, as always!

    • @taben9jake
      @taben9jake 2 ปีที่แล้ว +5

      And thats why i read comments before i make one. It also kinda looks like he has a bit of catsup leftover from eating a hotdog.

    • @GabePuratekuta
      @GabePuratekuta 2 ปีที่แล้ว

      Nope, it's a clown nose.

  • @Guineh76
    @Guineh76 2 ปีที่แล้ว +14

    Oh, wow… I went through the code for MM2 a couple of years ago. I remember the environment collision check routines… took a bit of time to wrap my head around all of the bit shifting and packing to figure out how it was arriving at the address of the block it was checking. There was also the enemy spawn routine as you move through the level that was pretty interesting. If I remember there are two lists one for blocks (what you call dynamic) and one for level effects and enemies. It’s been a while since I’ve looked at it. Lots of interesting stuff in the code for sure.
    Loving your behind the code series, btw! I look forward to every episode!

  • @wishexploder
    @wishexploder 2 ปีที่แล้ว +16

    This has got to be one of the best video game coding related youtube videos I've seen that blends intermediate programming knowledge with easy to understand narration and examples. Can't wait to check out your other stuff!

    • @GabePuratekuta
      @GabePuratekuta 2 ปีที่แล้ว

      On par with Jon Burton's GameHut and Coding Secrets channels.

  • @thelastsidewalk
    @thelastsidewalk 2 ปีที่แล้ว +20

    I'm surprised to hear it was put together in 3 months.
    For such a short time, I feel the gameplay is a lot more polished than MM1.
    This was an amazing video by the way, fascinating. Thank you.

    • @vksasdgaming9472
      @vksasdgaming9472 2 ปีที่แล้ว +3

      I am certain Capcom was able to reuse lots of assets developed for Megaman. Graphics, movement and lots of animation was simply used again so time was saved. It still is very much improved over first. In my books series kept becoming technically better through it's NES-era even if presentation wasn't always as good.

  • @vineheart01
    @vineheart01 2 ปีที่แล้ว +20

    i often wonder if the person who wrote the specific code that allowed a rather significant bug realizes years later that they did that and just go /facepalm 'dammit, i see what i did wrong...' lol

    • @Dreamwriter4242
      @Dreamwriter4242 2 ปีที่แล้ว +9

      Often, they knew about the bug even before the game shipped. I worked back in the cartridge era before you could patch games, and we had a team of testers testing our games 8 hours a day for months. So we had a database with hundreds of known bugs in it. When the shipping date got close, bugs would start to...disappear. Because fixing bugs could accidentally create new bugs, at some point someone would go to the database and mark all "C-level bugs" as "won't fix". Later they would do that with all "B-level bugs", leaving only the worst bugs as ones to fix - like crash bugs or bugs that would cause the game to fail Nintendo's shipping tests. It was frustrating to know of a bug you had made, and know how to fix it, and not be allowed to.

    • @blarghblargh
      @blarghblargh 2 ปีที่แล้ว +4

      This is still how shipping works. For good reason. No matter how innocuous the fix and how it *shouldn't* cause ripple effects, there's a non-zero chance that it will. So if the bug wasn't deemed that important, then after a certain point in the schedule the reward is less than the risk. They did their jobs. This is from someone who has been in QA (for 6 years), dev (for 10), and production/project management (for 3). It's frustrating, but prioritization and cutting is always the right call.
      Plus, this bug may be exploitable by speedrunners, but these days generally consider that "a feature, not a bug". Especially if regular players are basically never going to notice it.

    • @sr.metang8193
      @sr.metang8193 2 ปีที่แล้ว

      @@blarghblargh speaking of which, this can be a pretty daunting task for independent developers with little to no beta testers availability most of the time, which in turn might end up in long, ever-postponing unfinished projects that always miss deadlines. Not exactly always perfectionism, but your mileage may vary about that. Is there any kind of concern a dev in such a situation should be considering before attempting to solve bugs before shipping?

    • @blarghblargh
      @blarghblargh 2 ปีที่แล้ว +2

      @@sr.metang8193 IMO. Small indie dev isn't the same beast as larger companies with more resources. Once their company and products hit a certain threshold, they will be judged the same metrics as other games. But until then they should focus on doing interesting work and not on doing bulletproof work. Ideally all groups should get some testers though, one way or another.
      Prioritization always exists. There will always be bugs. It's a question of how much they interfere with the enjoyment of the typical player, and what percentage of people end up having their experience go pear shaped.

    • @aaendi6661
      @aaendi6661 2 ปีที่แล้ว

      It's better than getting stuck in the wall.

  • @bdjeffyp
    @bdjeffyp 2 ปีที่แล้ว +30

    What an amazing and fascinating breakdown! I love how "off-by-one" errors can drastically affect things. One thing that I would love to see you do in the future, perhaps in a "Talkin' Code" segment, is how you go about analyzing the Assembly code and figuring out how the different subs work. I would imagine that you are using breakpoints and modifying values to see what changes in the game, but I would be interested in hearing your thoughts on how you research and figure out the code behavior for these "Behind the Code" videos.

    • @dchardin1
      @dchardin1 2 ปีที่แล้ว +1

      I second that!

    • @Gpig20
      @Gpig20 2 ปีที่แล้ว

      I think for some of the behind the code videos he walks through the process of analyzing the assembly code in the emulator. Off the top of my head I think the Mega Man charge shot video is a good example but I think there's more

    • @VinsCool
      @VinsCool 2 ปีที่แล้ว +1

      It would be nice to see a video of him tracking down a bug, unscripted, and hear his reaction as he explains why things broke and what could be the fix.
      Bonus points for fitting in a 3 bytes Game Genie code :p

    • @lazsynth
      @lazsynth 2 ปีที่แล้ว +1

      Good ideas (also hi Vins!)

    • @drygordspellweaver8761
      @drygordspellweaver8761 2 ปีที่แล้ว +1

      He just loads it using a disassembler. There wasn’t much need for obfuscation and anti reversing back then so it’s straight forward.

  • @CoolJosh3k
    @CoolJosh3k 2 ปีที่แล้ว +11

    I use that same Tile Detection method in my game Powers of Hex, except I have to deal with Unity’s reliance on floats, instead of carry bits.
    I have a arbitrary epsilon value that acts the same way as the carry bit would, but for detection.

  • @ryans5615
    @ryans5615 2 ปีที่แล้ว +2

    I'm just commenting to say that the purple dot on Mega Man's chin makes it look like he's sticking his tongue out, like the Duck Hunt dog or something. I just can't get past it.
    Also, I do appreciate all the deep dives into the code.
    I know many years ago, I found a website where someone decompiled all the code for the Mega Man games, and gave it good function names, kinda like what you've done, so that people can go take a look. I think it got DMCA'd because I no longer have the bookmark when it was taken down. But the programming in MM1 and 2 is just spectacular. I think it got better with 5 and 6, but those also had bigger ROM sizes which made it a lot easier. Thanks for the series, enjoying the channel!

    • @DisplacedGamers
      @DisplacedGamers  2 ปีที่แล้ว

      I was looking for some of that just to see if it was out there to help me along, but I didn't find a whole lot - at least for Mega Man 2. I kinda figured there would be more out there considering how intimately speedrunners seem to know the game.

  • @kooijbas
    @kooijbas 2 ปีที่แล้ว +1

    I love these video's. They have exactly the right amount of depth and complexity to make it interesting and technical, yet still clear enough to follow along.

  • @TheNei
    @TheNei 2 ปีที่แล้ว +1

    Megaman 2 and 3 are amazing! Nice graphics, Sounds, etc
    -Thanks for this amazing vídeo!

  • @TheSektorz
    @TheSektorz 2 ปีที่แล้ว +67

    Oi btw now that I see what "zipping" means - you can do the same thing in the original Sonic games. Would be fun if you make a vid on those too, Sonic 3 in particular I've seen people break the most using a similar technique.

    • @VincentGuillotine
      @VincentGuillotine 2 ปีที่แล้ว +17

      marble zone acts 2 and 3 basically don't exist in sonic 1 any% speedruns thanks to zipping

    • @CoolJosh3k
      @CoolJosh3k 2 ปีที่แล้ว +5

      It is all in the ejection method. A combination of “which direction” and “where to put the player”.
      Normally the visual indication is just the illusion of a solid wall and you never actually see the ejection take place. You do notice with zipping because the next render does not make sense in a natural way.

    • @Valientlink
      @Valientlink 2 ปีที่แล้ว +1

      yeah the instruction manual in sonic 3 suggests you enter the special stage or special zone because Tails will die to a zip for some reason if you don't lol

    • @manjackson2772
      @manjackson2772 11 หลายเดือนก่อน +1

      ​@@ValientlinkIt's not a zip. Ice Cap Act 1 is supposed to be a vertically looping stage. When you first enter the stage, the flag that makes it loop vertically is set during the snowboarding section at the beginning. But only Sonic goes through this section, Tails skips it and doesn't get the flag set. Reloading the level, like by dying or entering and leaving a special stage, does correctly set the flag, but If Tails reaches the looping part without doing any of that, he'll hit the bottom of the level and die.

    • @Valientlink
      @Valientlink 11 หลายเดือนก่อน +1

      @@manjackson2772 Yeah I've since figured out how this works, but thanks

  • @SkipperTheSuperGamer
    @SkipperTheSuperGamer 2 ปีที่แล้ว

    Your fix for the zipping works *almost* perfectly. I say almost because there is one tiny little quirk with it. If you go through a boss door in either the jumping or "tip-toe-ing" state, there's a chance that Mega Man will be standing on the ledge of the boss room instead of falling down. I would think that the easiest way of fixing this would be to very slightly increase the speed at which Mega Man travels while going through a boss door, but I've no idea how to do that.

  • @aurinator
    @aurinator 11 หลายเดือนก่อน +1

    Even more impressive is its soundtrack - best one IMO.

  • @fruitsnackia2012
    @fruitsnackia2012 2 ปีที่แล้ว

    mega man 2 engine is the base code for the rest of the mega man games on the nes. i can confirm this cause i made a code to controll the pitch and speed of the sound and music in the game and these codes work on every mega man game except mm1 without changing addresses.

  • @MangaDungeon
    @MangaDungeon 2 ปีที่แล้ว

    I dont know anything about codeing but this is the coolest thing I've seen in my life.
    Subbed, will now binge

  • @DouglasZwick
    @DouglasZwick 2 ปีที่แล้ว +2

    This is so excellent! Another video that's like it's tailor-made for me. And I'm excited about the prospect of more MM2 videos to come!

  • @AtariSwitch
    @AtariSwitch ปีที่แล้ว

    I discovered "zipping" when I noticed I could get significant horizontal movement by holding a direction and then entering and exiting the menu, which got me above a ceiling in the Bubble Man stage. I thought I was stuck, but when I tried to go left I zipped to the other side. Great video!

  • @bluemilkboysgaming
    @bluemilkboysgaming 2 ปีที่แล้ว

    This video is incredible. I took basic coding in high school and you were able to break this down enough for me to understand the concepts. The fact that you can comb and interpret code is amazing.

  • @oracleoftroy
    @oracleoftroy 2 ปีที่แล้ว +2

    I've been working on an NES emulator in my spare time, and the ADC and SBC instructions were the hardest parts of the CPU to get right. ADC was pretty easy to figure out what I had messed up, but SBC struck me as really weird and I didn't understand how the carry flag was being used until I found an old 6502 manual that walked through various examples (which made for a great test suit!).
    I can completely see a developer accidently clearing carry when they should have set it just before a subtraction! Its reassuring in a way to see that the makers of the games I loved growing up were confused by the same instructions that were giving me trouble. :)

    • @vuurniacsquarewave5091
      @vuurniacsquarewave5091 2 ปีที่แล้ว +1

      And it only gets more confusing once you bring signed and/or 16-bit integers into the mix. Sometimes it's easier to ADC a negative value, and sometimes it's easier to negate a value and then SBC it. It all depends on what you're doing and whether you need the carry afterwards to make a decision.

    • @ArneChristianRosenfeldt
      @ArneChristianRosenfeldt 11 หลายเดือนก่อน

      I think that Intel does not invert the carry for sbb. Intel also always had sub and add ? Anyway, the first time I read about ADC, I thought that a common (automatic) optimization would be for code to either have the carry clear or to deal with it locally and then have it clear. So unless we do some modulo stuff like waterfall or vram wrap around we would never need two instructions for a simple add or sub. One more xor gate and we could be there. Pebble was probably proud that he saved a single gate ( still 8 gates for the operand are still needed ).
      I have to admit that rotate through carry can leave it in any state. I guess what I wanna say: why so many unused opcodes, but no ADD or SUB ??

  • @Luigi1000
    @Luigi1000 2 ปีที่แล้ว +1

    I know a few people, my self included who would be interested in an exploration of MM2's collision code despite it's length, but don't have the time or technical skill to go through it themselves. If it's ever on the table I would love to see it even if it was broken down into multiple part videos.

  • @DaWhiteTyger
    @DaWhiteTyger 2 ปีที่แล้ว +1

    "Collision is occurring right now. Can you see it? Here, I'll turn it off." Megaman passes through floor and dies. LIGHTBULB MOMENT, A-HA! (this is why I wasn't a coder... :( ) But, yeah when you asked the prior question, ALL of the things you spatted off I was thinking of. This is why I envy gents like you, I can handle the physics, but not the actual numbers and code.

  • @kittah4
    @kittah4 2 ปีที่แล้ว

    "To insert Mega Man into the ceiling". I lost it at this said with a completely serious and deadpan voice.

  • @NrgSpoon
    @NrgSpoon 2 ปีที่แล้ว +1

    I always find it fascinating to compare the speed between each Mega Man game. For example, think about how long it takes the boss health to fill up in MM4, compared to MM5. The same can be said for screen transitions. Mega Man 5 feels like the most well optimized MM game because so many of the incidental animations are so speedy.

  • @michaelcalvin42
    @michaelcalvin42 2 ปีที่แล้ว

    I saw that "Merry Christmas" in there, you jolly joker. Thanks for another great video!

  • @mutexS4
    @mutexS4 2 ปีที่แล้ว

    Your channel is BEYOND awesome. I LOVE your deep-dives and lovingly painstaking step-by-step explanations. I have such fond memories of playing on my beloved NES in the late 80s, and your exploration of the mechanics of games (such as one of my all time favorites, Megaman 2) peels back the curtain and reveals the magic that made these games so amazing and mind-blowing to a child of that era.
    It's so awesome to see the breakdown of the 6502 instructions that make these games work. Please keep making videos like this! They are the highlight of my day/week/month when they show up in my feed! The more technical the better!

  • @IntoTheVerticalBlank
    @IntoTheVerticalBlank 2 ปีที่แล้ว +1

    Oh man, this is great. I'm making a scrolling shooter (Scramble) on right now on the Atari ST with 16x16 tiles on a scrolling background and this ia really helping me refine my collision detection logic.

  • @dionelr
    @dionelr 2 ปีที่แล้ว +1

    Great job. I've seen this being done by speedrunners for years but had no idea the code behind it.

    • @TopShelfTheology
      @TopShelfTheology 2 ปีที่แล้ว

      I'd seen that, and knew it had to do with squashing into hit detection in a wall instinctively. What I did not expect was it's bugged due to handling the edge case of disappearing/reappearing blocks, I never considered those.

  • @6mtzhp55
    @6mtzhp55 2 ปีที่แล้ว

    Instant like, been waiting intently ever since the tweet!

  • @Dedicatedtolivinginthepast
    @Dedicatedtolivinginthepast 2 ปีที่แล้ว +1

    I beat Megaman 2 kinda recently so it is super interesting seeing why some glitches I experienced happen!

  • @philrottkamp
    @philrottkamp 2 ปีที่แล้ว +14

    I’ve been speedrunning MM2 for over 4 years now. Zipping is fun but isn’t always easy, some vertical zips require a lot of effort and the Item 2 Bubble Man zip is extremely dangerous.

    • @f0ngers586
      @f0ngers586 2 ปีที่แล้ว +1

      Dangerous and basically frame perfect. Can't decide what's dumber, wood man or item 2 zip. Wait it's neither, it's soft locking in the quick man boss room😭

    • @philrottkamp
      @philrottkamp 2 ปีที่แล้ว +1

      @@f0ngers586 the soft locking is pretty frustrating, but after 4 years I’ve gotten better at it. Believe it or not, the Woodman zip isn’t that bad to execute - it’s really long, but with some practice and muscle memory, anyone can stand up to it.

    • @Jasonhoods
      @Jasonhoods 2 ปีที่แล้ว

      I speed run on the legacy collection and it's so fun. On Xbox I hold 15th place on MM1 Megamix

  • @Amiculi
    @Amiculi 2 ปีที่แล้ว +1

    Rude ass Megaman sticking his tongue out at us for almost the entire video, I'm surprised no one noticed to tell him to knock it off during filming!

  • @brunomoreno3666
    @brunomoreno3666 2 ปีที่แล้ว +1

    excellent video! keep the good work

  • @travezripley
    @travezripley 2 ปีที่แล้ว +1

    Yes!! Friday is gonna be awesome!

  • @wannabecinnabon
    @wannabecinnabon 2 ปีที่แล้ว +2

    I'd be very curious to see the coding of Mega Man 3 and Mega Man 4 compared at some point in the future, to perhaps see what makes 4 run so much more smoothly. Great video!

    • @renakunisaki
      @renakunisaki 2 ปีที่แล้ว

      Funny, MM4 runs smoothly, but it feels so slow because of the screen transitions... I wonder what the story is with those?

  • @infinitehush
    @infinitehush 2 ปีที่แล้ว

    I love these videos so much! Looking forward to the Mega Man Talkin' Code follow up that's surely coming soon.....!?

  • @Hylianpuffball
    @Hylianpuffball 2 ปีที่แล้ว

    As somebody who has just started tinkering with 6502 Assembly, it is actually a relief to know that even seasoned experts would mix up CLC and SEC, and it's not just my poor baby brain spoiled by modern languages.

  • @StriderGW2
    @StriderGW2 2 ปีที่แล้ว

    I love this video series, the detail and clarity is hugely appreciated

  • @graemevaughey7432
    @graemevaughey7432 2 ปีที่แล้ว +8

    Oh, wow: a retro gaming channel that actually knows he's talking about? (rather than just another bandwagon jumper). Thank you. Subscribed.
    Incidentally, I've been programming an SNES game for a couple of months now, and I had a similar bug with exact corner collisions (a very difficult thing to catch in playtesting). Basically, I was testing _independently_ for top-edge collisions and side-edge collisions on my player sprite, which resulted in a very rare occurrence of single-pixel overlap with level tile corners if you happened to hit them from the exact right angle. Whenever this occurred, neither the top-edge (using the _old_ side-edge value) nor the side-edge (using the _old_ top-edge value) would read it as a collision, so it would be allowed... for that single frame. Immediately afterwards, however, the next frame would perform the collision check, find that the player was already penetrated into the wall, and attempt to rectify the matter by catapulting the player across the level (or zipping, as you call it). I had to add a bunch of visual debuggers, record the gameplay on video, and go through it frame-by-frame to even work out what was happening! Collision programming is a nightmare.

    • @TopShelfTheology
      @TopShelfTheology 2 ปีที่แล้ว

      This is why my first coding project was implementing Battleship without a GUI, it was all in ASCII art, lol.

  • @asteroidchan
    @asteroidchan ปีที่แล้ว

    Wonderful video. Been developing games for quite some time now, never took the time to look into older systems until recently. Very insightful.

  • @williamdrum9899
    @williamdrum9899 2 ปีที่แล้ว

    7:20 Here we see the Hydra make its return from Blaster Master. Basically this is how a switch statement in C would be compiled into 6502 assembly. The advantage of this is that each case takes the same amount of time to process.

  • @snowgoer540
    @snowgoer540 2 ปีที่แล้ว

    This is awesome. I love these videos, and my OCD really appreciates that you provided and explained the fix too.

  • @sHiNkAoLaSu
    @sHiNkAoLaSu 2 ปีที่แล้ว +4

    hey, seriously, thank you for doing these, somehow, it feels like they're exactly at my level of understanding this stuff (took EE and CS as bachelor 20y ago)
    so yeah, I mean I do have some background, but the way you explain it is super clear and logical, at least to me^^
    thanks again and please keep them coming :) (Heard/saw the vid with Bob from retroRGB, it was funny/interesting you mentionned mister/fpga as a "dangerous topic" or something along those lines...I mean I get it, but I'm sure you looking at a fpga core to explain how a given game (arcade core/pcb?) or system does copy protection or scaling or cleverly whatever else would be super interesting, at least to me. (and it is a pragmatic way of saying fpga is only as good as you implement it, without triggering fanboys 😂)
    Greets from France!

  • @DarkHeroAkutare
    @DarkHeroAkutare 2 ปีที่แล้ว +2

    "Here, I'll turn it off."
    wait no don't hurt him NO-

  • @sanderbos4243
    @sanderbos4243 2 ปีที่แล้ว

    Loved this breakdown!

  • @toffeeFairy
    @toffeeFairy 2 ปีที่แล้ว +2

    Really enjoyed this one thanks

  • @DaWhiteTyger
    @DaWhiteTyger 2 ปีที่แล้ว

    ZIPPING?!?! Why haven't I EVER heard of this before now? And to think, I thought I knew most of what MegaMan 2 was able to be cheated upon... Thanks again for showing us "Behind the Code". I'd NEVER would have ever thought of, nor imagined this... Wonder if it still works in newer iterations of MM2.

  • @juanoncho
    @juanoncho 2 ปีที่แล้ว

    Thanks for this awesome video. Perfectly explained.

  • @reaper84
    @reaper84 2 ปีที่แล้ว

    Great video. Please more videos on level data, and collisions with level map data in the future! :)

  • @HaveYouTriedGuillotines
    @HaveYouTriedGuillotines 2 ปีที่แล้ว +6

    I bet you what happened is that he wrote both the left and right ejection back to back, copy and pasted a bunch of stuff, and tried to mirror the code logically. Since the carry and borrow function do the same thing in opposite directions, that ideally would work. ...But it didn't, as one is enabled by setting a flag, and the other is enabled by disabling a flag.
    Super easy mistake to make.

  • @igodreamer7096
    @igodreamer7096 2 ปีที่แล้ว +1

    Very interesting, never guessed that MegaMan could take a short cut through walls like that
    HAHAHAHA

  • @VinsCool
    @VinsCool 2 ปีที่แล้ว

    Oh joy, great video!
    Just in time as I was diving into 6502 ASM hell myself earlier today.
    Carry and Off by One errors were plentiful for me, but tonight I instead spent a full hour debugging something where a very specific condition triggered a glitch, only to find out an entirely unrelated section of my code had a STA instead of STX like it was intended, and by pure luck it was the very rarely not going to be a BMI branching so whenever I got the bits I needed this would incorrectly be set and then seemingly random effects occured inside of my code, which broke a lot of 16-bit addressing I had just made the day before as a much more compact code I rewrote to make it a lot faster.
    1 instruction, STA mistakenly used instead of STX, a specific condition, and chaos ensued, that was a fun hour tracking down what happened and narrowed it down to the single byte that was the culprit.
    I had a good laugh, and felt very stupid, but now my bug is fixed! Yay

  • @xfreakerx1
    @xfreakerx1 2 ปีที่แล้ว

    Awesome! Perfect timing too, I'm working on collision and physics for a coding project!

  • @atomicnoexcept
    @atomicnoexcept 2 ปีที่แล้ว +1

    Such a great video. I learn so much from you!

  • @thedagit
    @thedagit 2 ปีที่แล้ว +1

    I wanted to fix the bug where sometimes under the right conditions touching the side of the screen causes a screen transition where it normally isn't allowed. If you look up a mega man 2 tas you can find examples. The mega man 2 randomizer tends to cause the right conditions more often than vanilla and it was frustrating to players to touch a wall and accidentally get transitioned into some permastuck state or death.
    A japanese person had reverse engineered this particular bug (I think for TAS and speedrun purposes). The game tries to defer sound updates at certain times. I forget the exact conditions, but the analysis by japanese person was that the audio update code clobbers some of the registers. I think the code normally runs during an interrupt and thus registers are restored normally when returning from the interrupt handler. However, if the game were to run these routines in a deferred context instead of their typical context this would result in the Y register (I think?) having an essentially random value after the audio update. (Not actually random, but very hard to predict, the person I mentioned before was looking to make tools to predict the value to exploit it). The value in this register could, in some circumstances, be picked up by other routines as an input. One such routine could be the code that makes a judgement about transitions within a level.
    To fix this bug in the randomizer, I just replaced the jsr for the deferred audio processing with nops. The deferred audio processing typically happens during lag which means you can't really tell whether or not the deferred update happened. The end result is a rom where what we call "delay scrolling" is not possible and no noticeable impact on the audio experience.
    It's such an obscure bug that I think the developers simply had no way to test for it. We're quite fortunate with the modern tools we have.

    • @DisplacedGamers
      @DisplacedGamers  2 ปีที่แล้ว

      Wow. That's some fascinating stuff, thedagit.
      Based on the development timeline as well as the "work on it as a side project" approach, I think a lot of code was "patched" instead of "developed" in order to get it done.
      At a glance, it seems like a lot of code operates under assumptions (i.e. "so long as this one thing doesn't happen...we should be OK on these other things that follow...) that aren't very safe assumptions.

  • @namco003
    @namco003 2 ปีที่แล้ว

    I really appreciate these videos. While I'm not a programmer and have little knowledge of coding(I used to write my own games, and the ones I got in magazines on the Commodore 64 for fun when I was a kid), it's amazing to see all the hand written code that went into making these games possible. I don't get it, but I totally get it

  • @renardleblanc5030
    @renardleblanc5030 2 ปีที่แล้ว

    Speaking as a fine artist, one of the hardest subjects to tackle in figure drawing is "movement." This is the ability to depict (implicitly) the physical effort exerted by a human body to stand in place and upright, fighting against gravity. Effectively, the muscles are pushing the body *upward* at the same acceleration that gravity is pulling the body *downward,* which is *not* the same as being motionless, as such (for comparison, a reclining figure is not exerting muscle strength to fight gravity, the couch (or bed or floor or chaise lounge or dias) is doing that work for the figure... which is why a prone figure has a distinct appearance from a standing one, even if a viewpoint is positioned in the same angle/location relative to the figure). Similarly, a falling figure has a distinct appearance from a figure in freefall (skydivers look different from NASA astronauts... both are in freefall, but there are significant differences in how they exert effort to maintain or correct their posture/orientation).
    I bring this up, because @3:25 my first and only immediate thought was: "floor contact." Because gravity.
    Art and programming collide! :)
    Another good example of figure "movement" is mega mans "standing" sprite, which *looks* ready to spring into action, compared to his falling sprite, which is very clearly accepting whatever fate is be-*falling* him. (In freefall, a relaxed figure is not making an effort to resist gravity, hence no tension, ie no movement).
    Meanwhile: the graphic designer in me is screaming internally at that off-by-one "fencepost" error (if I have a page layout with 3 columns, and 1 gutter space between each, how many gutters do there need to be? Reflexive answer is 3, at a 1:1 ratio, the actual answer being 2).
    Bleaugh, I ramble. Fascinating video!

  • @crtinkering7323
    @crtinkering7323 2 ปีที่แล้ว

    Another top notch video!

  • @ThaNikilist
    @ThaNikilist 2 ปีที่แล้ว +3

    Love your videos! Any chance you could publish your commented code for some games? I'm curious to dig into them but starting off from the uncommented rom is a lot for someone who likes CS but didn't really study it.

    • @DisplacedGamers
      @DisplacedGamers  2 ปีที่แล้ว +2

      Thanks, Nicolas. I may publish the comments at some point in the future but do not have plans to do so at this time.
      Some games have had their source code released or reversed (Mega Man 3 might be among those) that are out there right now. They might be a lot more comprehensive than the work that I have done as I try to do just enough for a video and then move along. Not sure how much people have commented on them. Super Mario Bros. might be a good one.

  • @CarbonRollerCaco
    @CarbonRollerCaco 2 ปีที่แล้ว +2

    So why would they make the chip so you have to SET the carry flag to clear borrow and vice versa? Is the bug really in the game, or the hardware running it?
    And that was some neat-o compression trickery there. You do what you can to save space.

  • @Video-Games-Are-Fun
    @Video-Games-Are-Fun 2 ปีที่แล้ว

    I LOVE glitches! it's what made me love street fighter 2 (guile's shadow throw glitch was something I used in fighting all the time!) along with his handcuffs and dhalsim disappearing. they make the game that much more fun!

  • @GadgetUK164
    @GadgetUK164 2 ปีที่แล้ว

    Wonderful video =D

  • @Sixfortyfive
    @Sixfortyfive 2 ปีที่แล้ว

    Even though it's probably a bit beyond the scope you'd like to do, a deep dive into Wily Wars on Genesis would probably be illuminating. It's a port of Megaman 1-3 that's kind of notorious for slowdown. In particular, it tends to chug whenever too many sprites are onscreen when the NES originals were more likely to just flicker instead. Knowing that the original code in the NES versions was more elaborate and taxing than a typical NES game sheds a light as to why that port runs more poorly than you'd expect on more capable hardware; the developers of that version probably didn't have the time or resources to properly reoptimize everything.
    What makes Wily Wars really interesting to me though is that the rerelease of that game produced by Retro-Bit in the past year actually *did* reoptimize the game. It doesn't get rid of the slowdown entirely but there's definitely a noticeable improvement.

  • @paraflex5621
    @paraflex5621 2 ปีที่แล้ว +1

    Great video! It's fascinating to learn what the specific programmer errors were that resulted in glitches I've known about for years. Another MM2 glitch that might be interesting to explore is the warp from boss room to wily stage gate glitch. Another collision detection issue?

  • @createprince2093
    @createprince2093 2 ปีที่แล้ว

    these videos are golden

  • @MisterVercetti
    @MisterVercetti 2 ปีที่แล้ว

    I wonder if this is related to the bug where, in certain boss rooms, if you're riding Item 1 next to the boss door and take damage, you end up getting pushed into the next screen, which is typically the first screen of one of the Wily stages, but with the current stage's graphics and attributes loaded in.

  • @gresolio
    @gresolio 2 ปีที่แล้ว +1

    Thanks for great videos :) Can you please make more content about Battletoads or/and Battletoads & Double Dragon? Rare did a fantastic job at the time, there are a lot of gems in Battletoads on NES.

  • @emmanueloverrated
    @emmanueloverrated 2 ปีที่แล้ว

    Having written collision routines for games like MM2, I do understand the error he made. Now lets tackle slope collisions, it's going to be fun... :D

  • @sr.metang8193
    @sr.metang8193 2 ปีที่แล้ว

    Thanks for this! As a intermediate level programmer, it's amazing to see how people in the past did what they did with so much more limited resources than we currently have.
    But if I may ask one question: is this kind of code - written decades ago, by a professional programmer, hired by an AAA company, and part of a particularly successful piece of software - properly made with ideal programming habits in mind? Assuming, obviously, that there isn't a "correct", definitive way to code games, but rather distinctive logical checks and time/resource saving tactics that a less experienced developer would probably often miss or have no idea about, at all?

  • @1990heaven_
    @1990heaven_ 2 ปีที่แล้ว

    this is so freaking fascinating.

  • @Twenty_Six_Hundred
    @Twenty_Six_Hundred 2 ปีที่แล้ว

    I was using the ejection method with a homebrew game i was working on. Can't remember my code exactly however im fairly sure i scrapped it all together. Fairly sure i had a tile collision check before the input movement. So if the check detects an nonwalkable/solid tile the player movement input code was completely bypassed. Eliminated clipping issues, although i wasn't using any moving platforms that would create these issues of undesired player placement. I have noticed many devs use this method within the community and i did also. It can be buggy though and i understand for safe measures. I found with carefully placed X and Y cords along with collision data tables for tiles it's not really needed. For my projects anyway

  • @kri249
    @kri249 2 ปีที่แล้ว

    Totally worth the wait. If I knew about this in MM2 I would have exploited the hell out of it when I had it as a kid.

  • @diegocrusius
    @diegocrusius 2 ปีที่แล้ว

    informative and entertaining thank you

  • @matesafranka6110
    @matesafranka6110 2 ปีที่แล้ว +2

    Oh good old off-by-one errors, the null pointer exception's little brother in the family of most aggravating bugs XD

    • @DaWhiteTyger
      @DaWhiteTyger 2 ปีที่แล้ว

      Then, how many games can you exploit by this logic?

    • @matesafranka6110
      @matesafranka6110 2 ปีที่แล้ว +1

      @@DaWhiteTyger That's pretty much impossible to tell without poring through the source code of every game ever. Plus, OBE's (off-by-one errors) can occur in just about any algorithm, not just collision detection, so they can cause any number of different bugs in different games.

  • @guillermorodriguez836
    @guillermorodriguez836 2 ปีที่แล้ว +1

    If you end up doing a MM3 video, I would love to see why holding right on Controller 2 changes the gameplay soo much. I’m sure you’d have a great take whether it was intentional or a glitch.
    Also, an explanation on being able to select the rush marine, and rush jet before gaining those same power ups.

    • @renakunisaki
      @renakunisaki 2 ปีที่แล้ว +1

      I can't remember if it was 3 or 4 that accidentally left in some debug functions using controller 2.

    • @killerb255
      @killerb255 2 ปีที่แล้ว

      @@renakunisaki It’s MM3

  • @erikvincent5846
    @erikvincent5846 2 ปีที่แล้ว

    Nice video. This was my favorite game of this series, primarily due to nostalgia. A code curiosity I had with Megaman 2 was why is the music all screwed up, if one uses a game genie? I don't know any other games that has this problem, but it does mess with the sound in mm2.

  • @Humbird00
    @Humbird00 2 ปีที่แล้ว

    This game's approach to tile collision is surprisingly similar to how I handle collision in all of my own games.

  • @warmCabin
    @warmCabin 2 ปีที่แล้ว

    Wow. A one byte bug. That is truly amazing. Glad to know I'm not the only one who can't keep that carry crap straight!
    If you had to pick a zip to explain, I would do Good Wood. The route through the screwed up screen scroll logic still amazes me.
    Also...ever heard of delay scrolls?

  • @salvatronprime9882
    @salvatronprime9882 2 ปีที่แล้ว +1

    Wow I never knew MM2 was so rushed. It seemed like such a well-made game for the time.

  • @sourandbitter3062
    @sourandbitter3062 10 หลายเดือนก่อน

    I'd like to make a suggestion. I'd really like to know what exactly happens during the bug we call a delay scroll.
    I imagine it could happen because of a race condition? Causing a lag frame during a screen transition makes it so the next screen isn't loaded in time. And the code that does the transition is linked to the display of a new frame so it doesn't wait for the new screen to be loaded? I don't know, it must be more complex.
    And how can you create a lag frame? What operations should you chain together, what takes the most time to process? Item-1 2 or 3, a precise moment in the music, item drops, new enemies spawning etc? Is there randomness involved and if so can you manipulate the rng to help create a lag frame?
    Speedrunners could save about 8-10 seconds in Wily 1 by defeating the dragon with a delay scroll. At some point they could even try to delay scroll the last screen of Bubble Man stage, although that one looks to be crazy difficult, never been done RTA as far as I know. Finding a strat for this would be a huge change to the RTA run.

  • @ValkyrieTiara
    @ValkyrieTiara 2 ปีที่แล้ว

    This video was incredibly ineteresting! I would love to see more videos focused on explaining bugs (particularly speedrunning bugs, which would have the added benefit of more people being familiar with their operation making it easier for them to follow along). A possible candidate could be the double carpet speed bug in Mario 2?

  • @dchardin1
    @dchardin1 2 ปีที่แล้ว +3

    That part around 5:22 sounds familiar. I have been trying to get my head around that. It sounds a little bit like that Micro Mages video where the developers talk about the techniques they used to fit rich games into small rom sizes. I think they called it "meta-tiling?" I don't completely get it but it sounds like it's in the same ballpark, please let me know if I'm way off.

    • @madokalover
      @madokalover 2 ปีที่แล้ว

      i think thats right. the genesis sonic games do the same thing to make their giant levels.

    • @thomasmathew13
      @thomasmathew13 2 ปีที่แล้ว

      Yup. Similar to how micro mages does it. 8x8 is a tile, 16x16 is a meta tile, then they called 32x32 meta-meta tiles.

    • @vuurniacsquarewave5091
      @vuurniacsquarewave5091 2 ปีที่แล้ว

      @@thomasmathew13 You can actually keep expanding until you reach 256x256 to directly address rooms. Of course the screen resolution is technically 240 pixels vertically but the memory space actually exists in the game logic.

  • @spacepirateivynova
    @spacepirateivynova 2 ปีที่แล้ว

    the trained eye (ie, mine, because i've made collision detection algorithms for my own games) when you turned off collision, you only turned off the floor collision. I noticed that as he fell through the floor, megaman went backwards a bit there... and that was the wall collider saying 'hey, you can't be in the wall!' and the right side wall that pushed him backwards has priority when megaman faces right if you only turned the vertical collision off and faced left, BOOM, zip would have taken over. That one pixel issue is VERY common in programming (ESPECIALLY in memory management. It's like you have to think of the 1st floor of a building as the 0'th floor) We also call it the 'fence post error', i have 10 sections of fence, how many poles to I need? or, I have a fence that's 100 sections long. I have to removed 5 fence posts for another project... how many sections of fence do i have left? both questions require different fence post problem management.
    As a coder, I HAVE to use a certain level of 'zipping' in there, I like to check every frame the following for the 'floor collision' and design it so that it works in as few frames as possible so the game feels very responsive compared tot other ways I've done it (including how I was origially taught)... keep in mind I threw this together late night and i don't know if it works... :
    ' some basic code for you --- yes, this should actually work in qb64
    ' for this we will make some assumptions --
    ' 1 - Screen space is x = 0 and y = 0 locates at the upper left corner of the screen (as per normal.)
    ' 2 - Our 'hero' sprite, model, etc. etc is 16 pixels tall, and his origin is the upper left, putting his feet between
    ' player.x + 2 to player.x + 14, and player.y + 16 (player.y + 0 is the first actual line of the sprite)
    ' We'll call that pfeet.y = player.y + 16
    ' 3 - we have the player at say, 100x, 100y, and a floor box that's 100 wide and 10 pixels high from
    ' 50x to 150x and 200y to 210y
    ' 4 - gravity accelerates up to a maximum fall speed. Player starts at 0 fall (at apex of jump?) and falls at a
    ' of y = y + .2 and maxes out as say, 5 pixels per frame.
    ' 5 - his will be in it's own subroutine called from the main game loop. I could write it as a function, but i'll keep it
    ' as a GOSUB -> RETURN to keep it simple.
    ' set up graphics screen mode:
    screen.res% = _NEWIMAGE(800,600,32) ' give me window, 800 wide, 600 high, and 32 bit RGB value color
    SCREEN screen.res%, 0, 1, 0 ' Set the display port to that screen resolution, and double buffer me
    ' -----------------------------------------------
    ' Initialize some variables
    player.x = 100
    player.y = 100
    floor.x1 = 50
    floor.x2 = 150
    floor.y1 = 200
    floor.y2 = 210
    grav.accel = .2
    grav.max = 5
    ' main game loop:
    WHILE InKey$ = "" ' When I hit any key exit.
    GOSUB draw.floor ' we'll draw the floor in first because we're going to trigger on the non-black area
    GOSUB detect.collision ' Check for floor
    GOSUB physics.player ' Apply physics
    GOSUB draw.player ' Draw our player... thing...
    GOSUB draw.snow ' BONUS LEVEL!
    _LIMIT 60 ' FPS limiter, QB64 makes this nice and easy!
    ' The following prevents flicker from the graphics blitting process
    PCOPY 1, 0 ' We draw to graphics page zero, send that to the visible page 1
    CLS 0 ' Clear the draw screen
    WEND
    ' ---------------------------
    END ' close the program so it doesn't error out when it blarrgs through the subroutines and functions
    ' subs start here
    ' Move the player
    physics.player:
    if floor.detect = 0 then
    if player.y.speed < grav.max player.y.speed = player.y.speed + grav.accel
    else
    player.y.speed = 0 ' a bit of redundancy doesn't hurt. just make sure controls work around that!
    end if
    player.y = player.y + player.y.speed
    pfeet.y = player.y + 16
    RETURN
    ' Check for the floow
    detect.collision:
    floor.detect = 0 ' reset fall detection flag
    for y = 0 to int(player.y.speed) ' how far the player falls in a frame...
    for x = 2 to 14 ' how wide the player's landing area is
    if POINT(player.x + x, pfeet + y) then ' boolean operator, if x/y point isn't black... then
    player.y.speed = 0 ' stop falling
    floor.hit = y - 1 ' the pixel BEFORE the first drawn floor pixel. Fencepost errors!
    floor.detect = 1 ' set fall detection flag
    end if
    if floor.detect > 0 then EXIT FOR ' STOP the looping if triggered.
    next
    if floor.detect > 0 then EXIT FOR ' Again, exit second loop (we are checking a 2d area for floor collision)
    next
    if floor.detect > 0 then
    player.y = player.y + floor.hit ' ZIP the player to the floor

  • @bkid8626
    @bkid8626 2 ปีที่แล้ว

    Another great Behind the Code episode as usual. I swear I keep telling myself I'm going to learn 6502 assembly one of these days, and I will... One of these days.. 😑

  • @Zieldak
    @Zieldak 2 ปีที่แล้ว

    Apparently Mega Man gets stuck on door ledges with this modification after scroll transitions if Mega Man enters the door via jumping or tip-toeing for some reason. Don't really want to dissect MM2 to find out why. But thankfully there's a value at 0x0390FF which is added to Mega Man's X position fraction every frame during a screen transition.

  • @coolbrotherf127
    @coolbrotherf127 2 ปีที่แล้ว

    While I'm sure the programmers would have moved to have noticed and fixed all their errors in these games, bugs like this are what make these old games so interesting to look back at. Otherwise they wouldn't be quite as interesting.

  • @trzy
    @trzy 2 ปีที่แล้ว

    Sort of surprised by the collision logic only testing three "rays" rather than doing a box intersection test. Boxes are maybe a little more expensive but not *that* much. Sonic the Hedgehog also uses collision "probes" that extend downwards to determine the angle of the surface Sonic is standing on, which in turn is comprised of special bitmap collision tiles, rather than just a box collider and a surface slope.

  • @aaendi6661
    @aaendi6661 2 ปีที่แล้ว

    If the Mega Man games got slower as time went on, that pretty much explains the slowdown in Super Ghouls and Ghosts on the SNES. Probably used existing backwards compatable code from the Mega Man series.

  • @maverick_loneshark
    @maverick_loneshark 2 ปีที่แล้ว +1

    Merry Christmas

    • @maverick_loneshark
      @maverick_loneshark 2 ปีที่แล้ว +2

      "So we, of our own accord, got together, spent our own time, we worked really, really hard, you know, just 20-hour days to complete this, because we were making something we wanted to make. Probably in all my years of actually being in a video game company, that was the best time of my working at Capcom, because we were actually working toward a goal, we were laying it all on the line, we were doing what we wanted to do. And it really showed in the game, because it’s a game, once again, that we put all our time and effort and love, so to speak, into it, designing it."
      Keiji Inafune, April 2004

  • @commanderWill
    @commanderWill ปีที่แล้ว

    Thank you, this is good stuff.

  • @tunanoot
    @tunanoot 2 ปีที่แล้ว +1

    I would love to see a video about how Flash Man's timestop works!

  • @trippe2k
    @trippe2k 2 ปีที่แล้ว +1

    Megaman 2 is the best Megaman!

  • @carlosaugustorj
    @carlosaugustorj 2 ปีที่แล้ว

    very cool !! very interesting

  • @JamesLewis2
    @JamesLewis2 2 ปีที่แล้ว

    I just tried editing the ROM itself to include the fix mentioned at 14:00 and it turns out that the code was at bank 14, location 38986 (or in an iNES dump, 38996); the relevant code is in the same place in Rockman 2. I haven't yet figured out where the analogous change would be in the other Mega Man games for NES, but I did find that the only place in the original Mega Man where STA $00 SEC (85 00 38) occurs is in a section about how Elec Man moves, and it's a bit tedious to figure out which SEC should become a CLC by reading a disassembly, so I think I'll need to fire the games up in MESEN to use its debugger.
    Also, making that change causes TASes to desync early on, because Rockman will be one pixel too far to the left to make a particular jump, because when falling against a wall just before that, the fix stops him one pixel earlier; still, it's how I verified that the fix at least did something without having to practice setting up a horizontal zip (so I could then check whether *that* doesn't work with the fix either).