1 2
5 6 7
Alyosha
He/Him
Editor, Emulator Coder, Expert player (3807)
Joined: 11/30/2014
Posts: 2827
Location: US
So I started looking into the warp that Cartina posted here So far, I have at least found the address that can call stage end sequence. If you set $002C to 08, it will end the stage exactly as is done in the twitch video. Normally, the game sets this value to 8 after the last hit on the boss. (In normal play it is 4.) In terms of what this does, 002C is used to set the jump address for Jumps from 0002, which is where jumps are executed from in a normal frame. The first jump is always to CE30 The second Jump changes from CEE3 when 002C is 4, to CFEA when it is 8. The next step after this is D01F when it is 9. I haven;t tracked down exactly where 002C is changed from 4 to 8 normally yet, but this seems like a good start. EDIT: working backwards a bit, the same behavior can be obtained by changing 003B to 1 (it's normally 0) EDIT 2: ok, here is how 003B is normally changed to 1:
$E626:BD B8 04  LDA $04B8,X @ $04C7 = #$03                   A:00 X:0F Y:00 S:F4 P:nvUbdIzc 
           $E629:F0 2A     BEQ $E655                                    A:03 X:0F Y:00 S:F4 P:nvUbdIzc 
           $E62B:86 83     STX $0083 = #$04                             A:03 X:0F Y:00 S:F4 P:nvUbdIzc 
           $E62D:0A        ASL                                          A:03 X:0F Y:00 S:F4 P:nvUbdIzc 
           $E62E:85 04     STA $0004 = #$09                             A:06 X:0F Y:00 S:F4 P:nvUbdIzc 
           $E630:20 59 E6  JSR $E659                                    A:06 X:0F Y:00 S:F4 P:nvUbdIzc 
             $E659:BD 28 05  LDA $0528,X @ $0537 = #$11                   A:06 X:0F Y:00 S:F2 P:nvUbdIzc 
             $E65C:0A        ASL                                          A:11 X:0F Y:00 S:F2 P:nvUbdIzc 
             $E65D:A8        TAY                                          A:22 X:0F Y:00 S:F2 P:nvUbdIzc 
             $E65E:4A        LSR                                          A:22 X:0F Y:22 S:F2 P:nvUbdIzc 
             $E65F:C9 10     CMP #$10                                     A:11 X:0F Y:22 S:F2 P:nvUbdIzc 
             $E661:B0 18     BCS $E67B                                    A:11 X:0F Y:22 S:F2 P:nvUbdIzC 
             $E67B:98        TYA                                          A:11 X:0F Y:22 S:F2 P:nvUbdIzC 
             $E67C:E9 20     SBC #$20                                     A:22 X:0F Y:22 S:F2 P:nvUbdIzC 
             $E67E:A8        TAY                                          A:02 X:0F Y:22 S:F2 P:nvUbdIzC 
             $E67F:B1 80     LDA ($80),Y @ $E6CA = #$C7                   A:02 X:0F Y:02 S:F2 P:nvUbdIzC 
             $E681:85 02     STA $0002 = #$B0                             A:C7 X:0F Y:02 S:F2 P:NvUbdIzC 
             $E683:C8        INY                                          A:C7 X:0F Y:02 S:F2 P:NvUbdIzC 
             $E684:B1 80     LDA ($80),Y @ $E6CB = #$8B                   A:C7 X:0F Y:03 S:F2 P:nvUbdIzC 
             $E686:4C 6B E6  JMP $E66B                                    A:8B X:0F Y:03 S:F2 P:NvUbdIzC 
             $E66B:85 03     STA $0003 = #$D5                             A:8B X:0F Y:03 S:F2 P:NvUbdIzC 
             $E66D:A4 04     LDY $0004 = #$06                             A:8B X:0F Y:03 S:F2 P:NvUbdIzC 
             $E66F:B1 02     LDA ($02),Y @ $8BCD = #$40                   A:8B X:0F Y:06 S:F2 P:nvUbdIzC 
             $E671:85 04     STA $0004 = #$06                             A:40 X:0F Y:06 S:F2 P:nvUbdIzC 
             $E673:C8        INY                                          A:40 X:0F Y:06 S:F2 P:nvUbdIzC 
             $E674:B1 02     LDA ($02),Y @ $8BCE = #$E7                   A:40 X:0F Y:07 S:F2 P:nvUbdIzC 
             $E676:85 05     STA $0005 = #$00                             A:E7 X:0F Y:07 S:F2 P:NvUbdIzC 
             $E678:6C 04 00  JMP ($0004) = $E740                          A:E7 X:0F Y:07 S:F2 P:NvUbdIzC 
             $E740:20 83 C1  JSR $C183                                    A:E7 X:0F Y:07 S:F2 P:NvUbdIzC 
04C7 is the state of the enemy in that slot. Normally, this will be the boss. His state changes to 3 after the last hit. Now, other enemies can normally occupy that slot too. And their state also changes to 3 when they die. That is why the next check at 0537 occurs. This checks for the ID of the enemy in that slot. The boss has ID #$11, so this is the only time when the check BCS $E67B passes. After the check passes, the code continues onwards until eventually changing 003B to 1, the jump to E740 is what we need. Now when I change 0537 to 11 when another normal enemy has just died (has state 3) the explosion sequence occurs as if the last boss died. When I just change 003B to 1 manually, no explosion sequence happens. In the twich video, there is no explosion sequence, so I believe either 003B or 00C2 is being changed independently somewhere. But, there are very few places where this occurs, not sure where to look from here for edge cases where this might happen. Very little is happening at the time of the glitch. EDIT 3: hmmmm, there is something in the normal level that spawns with ID $#12. If I can get this object to spawn in 04C7, perhaps somehting interesting will happen? Well, looks like 12 is the bridges, so probably nothing there. EDIT 4: So I've been playing around with object IDs and their associated state variable. So far there are several combinations that cause glitchy things (or crash the game altogether) I haven't found anything so far that looks like a bad jump to end the level though. One neat thing I did find though is that the running backpack enemies actually have a gun. If you set their state variable to 4, they will point a gun at you, and on rare occasions will even shoot (a single bullet.) I guess this was something that was just never used.
adelikat
He/Him
Emulator Coder, Site Developer, Site Owner, Expert player (3570)
Joined: 11/3/2004
Posts: 4754
Location: Tennessee
Alyosha wrote:
One neat thing I did find though is that the running backpack enemies actually have a gun. If you set their state variable to 4, they will point a gun at you, and on rare occasions will even shoot (a single bullet.) I guess this was something that was just never used.
These states can be seen in Stage 5 and onwards, backpack enemies will regularly attempt to shoot at you.
It's hard to look this good. My TAS projects
Site Admin, Skilled player (1250)
Joined: 4/17/2010
Posts: 11473
Location: Lake Char­gogg­a­gogg­man­chaugg­a­gogg­chau­bun­a­gung­a­maugg
Good try, you might also try frame perfect reproduction of the source video, maybe it just happens that way. PS: please don't put empty lines in trace logs.
Warning: When making decisions, I try to collect as much data as possible before actually deciding. I try to abstract away and see the principles behind real world events and people's opinions. I try to generalize them and turn into something clear and reusable. I hate depending on unpredictable and having to make lottery guesses. Any problem can be solved by systems thinking and acting.
Alyosha
He/Him
Editor, Emulator Coder, Expert player (3807)
Joined: 11/30/2014
Posts: 2827
Location: US
Oh so that's why the backpack guy can shoot, ok thanks (clearly I've never played Contra, and certainly never made it to level 5.) Anyway, about the only interesting thing I can make happen so far is by giving a bullet a bad state, I can overflow the table , since the stationary guns that rise from the ground shoot bullets faster then they are cleared from the table. But all it does is crash, and so far I have no plausible way to give any object a bad state. So I think I will look over the ROM and see how else I might set the stage end variable. I also might try to recreate the video but am not very confident I can do it. Well its fun to experiment at least, the first level of contra must have been played tens of millions of times, I'm surprised such a glitch is unexplored. Of course it's also possible its just a random error, only 1 bit needs to be changed to end the level.
Player (32)
Joined: 2/24/2011
Posts: 11
feos wrote:
Good try, you might also try frame perfect reproduction of the source video, maybe it just happens that way.
DK28 was recording that attempt locally and sent it to a handful of people, so if anyone goes this route, here was the recording he had, from the first attempt after powering-on to when the glitch happened. Might be easier to replicate with this video instead of DK28's VOD since this is in 60FPS. http://www.mediafire.com/download/z5ljwv55qbrr317/ContraWW_HQ.mp4
Arc
Editor, Experienced player (814)
Joined: 3/8/2004
Posts: 534
Location: Arizona
Ah, so he used the 'end' option multiple times instead of starting from a fresh power-on. As we saw in Ghosts 'n Goblins, it's possible that something wasn't reset. It might be worth noting that on his attempt immediately before the glitch, he made it to the boss. Interesting to note what happened when the glitch occurred. The character stopped responding (even though he was holding right and tapped the button once) and the end-of-level music came up before he had the falling death. The death part seems irrelevant.
Joined: 9/9/2015
Posts: 5
Arc wrote:
Ah, so he used the 'end' option multiple times instead of starting from a fresh power-on. As we saw in Ghosts 'n Goblins, it's possible that something wasn't reset. It might be worth noting that on his attempt immediately before the glitch, he made it to the boss. Interesting to note what happened when the glitch occurred. The character stopped responding (even though he was holding right and tapped the button once) and the end-of-level music came up before he had the falling death. The death part seems irrelevant.
I believe the stop on the platform technically is irrelevant too. As before the loss of control the explosion sequence should occur if the stage is ended. Once you kill a boss it takes a few seconds before you actually lose control. But him using the "End" option instead of reset was something I was not aware off. That changes my view on this glitch.
Alyosha
He/Him
Editor, Emulator Coder, Expert player (3807)
Joined: 11/30/2014
Posts: 2827
Location: US
Oh nice a video, thanks zallard. Pressing 'end' definitely doesn't clear everything, but it does clear the object table. Well, so far here is what I know about how a level ends. When boss's HP hits zero, his state changes from 2 to 3 (wherever it spawns in the table between 04B8 and 04C7.) This triggers a routine which eventually sets 003B=1. When the main loop sees that 003B=1 , it changes 002C from 4 to 8 (via loading #$08 into accumulator and storing it in 002C.) This state remains until the explosion animation is finished. I haven't found the address for the timer yet. After the animation ends, 002C goes up to 9. The player loses control at this point. This is curiously done with an INC instruction, even though every other case is not. After that, if you are on the ground, the next frame 002C gets set to #$81 and the ending animation takes over. If you happen to be in the air, it won't change to #$81 until you hit the ground. To end the level as in the video, setting 003B to either 1 or 81 both work. Setting 002C to 08 works. Setting it to 9 eventually ends the level, but not in the same way as the video, at least not in my testing so far. So far I can't find anyway to distinguish between these working cases, it would be nice to narrow it down further.
Alyosha
He/Him
Editor, Emulator Coder, Expert player (3807)
Joined: 11/30/2014
Posts: 2827
Location: US
Well I narrowed down on a few places where some slight glitches happen in the boss fight, where memory also doesn't get reset after dying and hitting end. The first case is address 016A. It changes to 7D as the boss comes on screen and it starts scrolling on its own into the boss area. If you happen to die while it is still scrolling, it gets stuck on 7D. The screen still stops scrolling properly, but normally it goes to 80 if you don't die. Then it goes to 83 after a few frames. It can also get stuck on 80 when dying. This doesn't seem to effect too much, but it is at least a glimpse of non-standard behavior. More interestingly, there is some uninitialized stack memory between 01C0 and 01FF. The game initializes memory in an interesting way. First, it initializes 0000-01BF to 00. Then, it sets 0200-07DF to 00. Then, for 07F0-07FF it sets to F1-FF for whatever reason. 07E0-07EF get set individually to various values. 07ED seems the most interesting. It is set to the value of $8000. So I'm guessing this has something to do with memory banks. Anyway this leaves 01C0-01FF untouched, presumably expecting this to be the maximum extent of the stack. This interesting because values kind of close to this are changed at the boss stage. For example $0195 also seems to control scrolling in some way. So right now my guess is that something went wrong with the stack, most likely related to choosing end after dying on the first boss. Oh one other important thing I noticed is $0196. 0195 seems to keep track of what screen number you are on, while 0196 seems to count how long you have been on that screen. However, sometimes 0196 behaves oddly. Usually it increments once per second, but occasionally it increments much quicker, I haven't figured out exactly why but it is the next thing I will look at.
Skilled player (1737)
Joined: 9/17/2009
Posts: 4979
Location: ̶C̶a̶n̶a̶d̶a̶ "Kanatah"
I know these uses a reset, which likely kills off any time improvement, but I hope something comes out of this where setting it up saves more time than lost.
Alyosha
He/Him
Editor, Emulator Coder, Expert player (3807)
Joined: 11/30/2014
Posts: 2827
Location: US
ok, so 0196 is counting how many backpack guys come on screen for a given section of the level. So at the time the glitch happens, we have 0195 at 09, and 0196 at zero. Now when the glitch happens, this could be when a backpack guy is about to appear on screen, which would change 0196 to 1, this happens a few frames before he visually appears on screen. If the stack pointer got down to there, and then 0196 changed like that mid-frame, it could change a return address to something that could end the level. Unfortunately, I've never seen the stack get below 01DD, so if this is indeed how the glitch is caused, we would need to find another glitch that corrupts the stack somehow first before recreating it. 0196 is also the highest address in the stack region that gets changed by the game code (at least in level 1), so if the glitch is related to the stack getting overwritten somewhere, there is a good chance it is here. EDIT: well, since the game doesn't use or initialize part of the stack anyway, I edited the ROM to jump to RAM each frame in the unused area. From there I tried to edit the stack values to make weird jumps but so far all I do is crash things. Even if I jump to the routine that normally sets stage end flag it crashes. So, no leads at this point.
Alyosha
He/Him
Editor, Emulator Coder, Expert player (3807)
Joined: 11/30/2014
Posts: 2827
Location: US
I thought I might post some of my notes in case anyone else is also interested in this. By comparing the HQ video and my input file with 003B hex edited to 1, it seems like the glitch ending the stage occurs a few frames before the player hits the ground. This would seem to exclude the landing routine from playing a part in the glitch. So, this leaves not a lot happening. I so far have no way to effect the object table, no way to mess with the stack pointer, and even if I did no way to reproduce the glitch as demonstrated on the video. The stray values that didn't get reset when selecting 'end' seem only to be impacting sound effects and have no real impact. So I've focused in on the random backpack guy generation as the only likely candidate for something that can produce this glitch. This is about all I have to work with that involves random variables and nothing visually happening on screen. The basics of the code are that first, it checks the frame counter, it only attempts to generate a backpack guy every other frame. TIf it passes this check, it rolls the RNG 16 times, if it gets a value that sets a carry flag, 0079 is set to 2, indicating a backpack guy needs to be generated. Otherwise nothing happens. This doesn't necessarily create the enemy either though. The next frame, when 0079 is set to 2, another routine is executed that decides whether to create one or not and where to put him. This involves both random variables and the players Y coordinate. I haven't made it that far into this section though. So my working hypothesis is that an edge case of this generation code causes the glitch, possibly linked to your y location on screen. Basically because I have run out of any other viable alternative ideas. On a more optimistic note, this might mean that the reset isn't involved in the glitch, so might have a chance at being a time saver. Anyway anyone interested in looking into this can also find useful info here: http://acmlm.kafuka.org/board/thread.php?id=6035 The backpack guy generation can be found in bank 2 around $B5XX
Joined: 9/9/2015
Posts: 5
Wanna thank you for taking your time and looking into this. Hopefully you can sort out if it's viable to use in a TAS or if it was just a one-time thing. I do find the theory about backpack guy causing so much fuzz kinda amusing however.
Alyosha
He/Him
Editor, Emulator Coder, Expert player (3807)
Joined: 11/30/2014
Posts: 2827
Location: US
well the backpack guy is a long shot indeed. I looked through the second half of the code, and nothing seems to stick out that would make anything strange happen. But, I do have another lead. After looking back where 003B gets set again, I found out that a timer at 002A gets set to FF and counts down. There is no other indication that this has happened. Once it hits zero, the stage ends just the same. So this pushes back the timing for the initiation of the glitch by ~4.25 seconds. In the video, this corresponds to when much more is happening and more possibilities for glitches exist. So I will start investigating this as a real possibility. EDIT: This point seems to be where an item is appearing out of a grey wall box and a red gun guy is getting hit by a bullet, might really be something here! Another thing I found is that I can make a jump to $EAEA to set $003B to 1 and $002A to FF without breaking the game. This is convenient since you only need to do 20 EA EA, and EA is coincidentally NOP code. The problem is that this alone won't set the flags to run the subroutine to run the timer, so the stage won't end, and I can't currently run the complete routine at $E740 without a crash. EDIT 2: So looking at subroutine EAEA a bit, it seems that main input is the accumulator. It runs slightly different for different values, based on the level you are in I would suppose. It will always set 002A to FF and 003B to 1 though. But, if a boss isn't loaded into a table slot, 002A will never get a signal to decrement, and if it stays at FF will never do so. So the interesting thing is, a glitch that calls EAEA could actually be relatively common, and you would never know it happened under most circumstances of the accumulator. It might simply be a rare case of the glitch that actually causes the level to end. How this might occur though is still unresolved.
Former player
Joined: 9/13/2010
Posts: 138
Location: Tallahassee, FL
Just here to say your work is not going unnoticed. Me, DK, Mayor K, zallard1 and a few others are keeping up with your updates. I really hope you can make this happen. On a side note, a long while back Andrewg mentioned to me something very similar to this when he was playing Super C. In stage 3 with the mec spider mini boss, after he killed it the stage end music started and he lost control and the stage ended. He said he vaguely remembers it and does not have a recording of any kind. I wrote it off because of lack of detail and nothing to go on other than vague memories. I would assume the games are coded in a similar way so this may be possible on both games if this does get cracked. I dont mean to get you side tracked with this but perhaps the situations are linked some how. Maybe look at the Ram/code of Super C and maybe it could help here?
Alyosha
He/Him
Editor, Emulator Coder, Expert player (3807)
Joined: 11/30/2014
Posts: 2827
Location: US
Thanks for the new info. I admit I don't really have any leads at the moment. I think I will indeed try to look at super C and see if anything comes of it. It's unfortunate that there are no visual ques of any kind to go off of, and even if the glitch occurs, since you can't see the RAM in real time play you would never know. I haven't given up though. I am confident an invalid call to EAEA is causing this glitch, I just need to find a way to make it happen. Either that or it's a one time event hardware error, but I don't really think so. EDIT: well investigating Super C a bit, it does share the same vulnerability that Contra does, in that changing a single bit at any time will end the level. Once again though its not obvious how this might occur outside the normal pathway. The coding style is also extremely similar to contra, so a hypothetical glitch would probably function the same way.
Former player
Joined: 9/13/2010
Posts: 138
Location: Tallahassee, FL
Any updates?
Alyosha
He/Him
Editor, Emulator Coder, Expert player (3807)
Joined: 11/30/2014
Posts: 2827
Location: US
Heidman wrote:
Any updates?
At the moment I am out of leads. The most likely scenario is starting to seem like random hardware error. The thing is that flipping one bit at any time will end the level, and there are about 3 bits that would have this same effect as demonstrated in the movie, so a random error has 3 chances of success. But personally I'm not really comfortable with that explanation so the search continues, even though I have so far found nothing remotely interesting. To sum up what's been looked at so far: Object table corruption: Nothing interesting, gets reset on game reset Stack corruption: game uses stack memory for sound effects and some variables related to backpack guy, clears the stack up to about 01CF. Strange effects could result if the stack pointer got low enough, but doesn't even come close without hacking. Backpack guy generation edge case: nothing relevant. General glitch hunt: nothing interesting, the game seems to do things pretty carefully. If anyone has any theories, I'd be happy to hear them!
Site Admin, Skilled player (1250)
Joined: 4/17/2010
Posts: 11473
Location: Lake Char­gogg­a­gogg­man­chaugg­a­gogg­chau­bun­a­gung­a­maugg
Warning: When making decisions, I try to collect as much data as possible before actually deciding. I try to abstract away and see the principles behind real world events and people's opinions. I try to generalize them and turn into something clear and reusable. I hate depending on unpredictable and having to make lottery guesses. Any problem can be solved by systems thinking and acting.
Former player
Joined: 9/13/2010
Posts: 138
Location: Tallahassee, FL
I have no idea what the first link is but I really hope it leads to something
Site Admin, Skilled player (1250)
Joined: 4/17/2010
Posts: 11473
Location: Lake Char­gogg­a­gogg­man­chaugg­a­gogg­chau­bun­a­gung­a­maugg
IDA Pro database converted from http://acmlm.kafuka.org/board/thread.php?id=6035.
Warning: When making decisions, I try to collect as much data as possible before actually deciding. I try to abstract away and see the principles behind real world events and people's opinions. I try to generalize them and turn into something clear and reusable. I hate depending on unpredictable and having to make lottery guesses. Any problem can be solved by systems thinking and acting.
Alyosha
He/Him
Editor, Emulator Coder, Expert player (3807)
Joined: 11/30/2014
Posts: 2827
Location: US
Cool thanks feos, I'll take a look at that myself in a few days when I have more time. As for me my current (and only ) line of research is looking at lag . After a lot of random messing about I finally got a lag frame to generate in normal level 1 play through . I had generated lag before but only by cheating backpack guys to appear every frame . This is the first time I've done it without cheating. So my working theory is that if a new interrupt occurs at just the right time something will go awry. I'm still in the early stages of investigating this , but so far nothing looks suspect . The game uses address 001B as a flag that tells it when a new interrupt happens if it is still working in the previous frame . It then modifies what subroutines it works on for the lag frame. Since backpack guy generation can be a long and variable process each frame, the range within each frame that the next interrupt can occur in during lag is pretty large, maybe enough for something unexpected ? But so far hardware error still seems the most likely candidate.
Site Admin, Skilled player (1250)
Joined: 4/17/2010
Posts: 11473
Location: Lake Char­gogg­a­gogg­man­chaugg­a­gogg­chau­bun­a­gung­a­maugg
If you have an idea of what condition you need, there's a common mean to use bot: that's how Rockman DelayStateClear was proven to be possible - FinalFighter foretold it before it actually happened "simply" by breaking into code.
Warning: When making decisions, I try to collect as much data as possible before actually deciding. I try to abstract away and see the principles behind real world events and people's opinions. I try to generalize them and turn into something clear and reusable. I hate depending on unpredictable and having to make lottery guesses. Any problem can be solved by systems thinking and acting.
Alyosha
He/Him
Editor, Emulator Coder, Expert player (3807)
Joined: 11/30/2014
Posts: 2827
Location: US
feos wrote:
If you have an idea of what condition you need, there's a common mean to use bot: that's how Rockman DelayStateClear was proven to be possible - FinalFighter foretold it before it actually happened "simply" by breaking into code.
unfortunately I do not know. Assuming the mechanism is functionally the same as delaystageclear the closest bank swap to my current NMI in the lag frame is about 2000 instructions away. Probably reachable but no idea how at the moment. The real problem is that watching the movie of the glitch, I do not see any situations where lag should show up, so I have serious doubts that it is similar to Rockman. I'm only really looking at it for thoroughness and maybe learning something new to get a new lead. The lag frame itself seems to deal almost entirely in sound. The programmers were really careful here, I couldn't find a case they might have missed so far. One possibility that is a bit similar to delaystageclear is manipulating 07ED, which tells the game what bank to use for various operations across frames, but again I have seen no glitches in it yet. (If you cheat it to 0 though you get some neat 'fireworks'.)
Former player
Joined: 9/13/2010
Posts: 138
Location: Tallahassee, FL
Can you elaborate a bit on sound causing lag please. In my experience in playing the game I have heard many audio errors and I always find it amusing especially in Super C. Though the sounds usually occur/involve something (any 1 hp enemy or weapon pod) is dying. I get this mostly in waterfall in Contra and stage 2 in Super C but I have had them happen in all stages.
1 2
5 6 7