The Boss Skip that had been observed during a live run during AGDQ 2017 can be seen here: https://www.youtube.com/watch?v=g5Hq2eA ... e&t=28m55s
I have observed that $03FB will increment after you defeat a boss. From the beginning of the game this is set at value 0, then value 1 after the first boss, and then at value 3 after the second boss. In other words, if you overwrite the value of 3 into $03FB just before entering the second boss fight then you will observe what we see in the video. The game thinks the boss was already defeated. I have observed that $03FB increments the same frame that $03FD reaches a value of 128. $03FD starts at 0 from the beginning of the game and only does a 255 to 0 count down at the beginning of each boss fight, and then counts up from 0 to 128 upon the death of the boss. When this value reaches 128 then $03FB, the address that tracks what bosses have been defeated, will increment.
Observation #1 The first boss loads normally which means that $03FB is at value 0 when entering the first boss fight. If this value was 1 or higher then the boss would not spawn. The first moment that $03FB normally increments is upon the death of the first boss, in which case it increments to 1.
Observation #2 Upon entering the second boss fight the boss did not load which means that $03FB was already at a value of 3.
Conclusion: At some point this address is incremented again. My first suspicion is that it occurs after the first boss fight, that some how it is incremented twice. The later portion of this message shows "conditions" upon an overflow may occur that could possibly corrupt this address but it is still unclear exactly how these conditions could be met.
This is the most pertinent information that I have been able to find at this time.
I played around a little with the Chou-Wakusei Senki - MetaFight (J).nes ROM (GoodNES 3.14) after seeing that happen and will summarize some info here. Hopefully this will serve as a starting point for figuring out the glitch. I used FCEUX 2.2.3 and only played as far as the second boss fight.
After the scrolling ends when you enter a boss room, the following code is executed:
$0014 is the value (current area - 1) at this point. At $B62B, you find a sequence of increasing powers of two, starting with 0x01. Per Data Crystal's RAM map, $03FB indicates which bosses have been defeated. So this checks if the boss of the current area has been defeated. If it has but the item has not been obtained, then the item is displayed. That seems to be what happened during the race.
If the boss has not been defeated, then the room flashes, the boss loads (including its health), and you proceed with the fight. It appears that the health of the first two bosses is hard-coded into the ROM. For area 1, the pertinent code is:
For area 2, the pertinent code is:
The value from $0053 eventually ends up somewhere around $0470, but the exact RAM address varies. If you change the health to 0x00 before starting the fight (e.g., set execution breakpoint on $9C17, change A from 0x80 to 0x00, then continue emulation), the boss graphics load but immediately go into the death animation. This leads me to believe that whatever Skavenger did may have corrupted $03FB. There are likely other possibilities, but I will let someone with more time and experience take over.
Actually, one other thing. This is the code that is executed when a boss is defeated:
Most if it should be familiar from that first block, but the last two lines update the value at $03FB rather than testing it.
And another analysis:
I haven't looked at Blaster Master before, but this glitch got me curious, so a few observations from looking at the code in case they give anyone any ideas. Note that these are all from the English ROM (the only version I have handy), so if the glitch turns out to be JP-only then none of this may be of much use...
- The only stores to $03FB are the one Dacicus quoted which is done on boss kill, and a few that store literal 0 or 255 (and the 255 clearly can't be the case because the rest of the bosses showed up properly). The store after the area 1 boss kill in that run can't have set the wrong bit, because then the boss would immediately respawn when the room was reloaded after the boss death.
- The only indexed stores that could reach $03FB are the stores to the PPU RAM write buffer at $0300. I played up to area 2 to check, but the buffer high water mark was $0340, and a cursory review of the code suggests it's pretty good at flushing the buffer before it overflows, so it seems unlikely to me that a buffer overflow is the cause. (Also, in order to have disabled only the second boss, the store value would have to have been $02 or $03, which seems unlikely for an arbitrary PPU data store; and if the buffer overflowed all the way up to $03FB then it would stomp on lots of other stuff in the $03xx range, which would probably cause more problems than just a missing boss.) On the other hand, Personman's example of a case when both a boss and its item were missing could indicate a buffer overflow that wrongly set bits in both $03FB and $03FC, so I dunno.
- The boss-defeated store to $03FB has this stack trace (again, addresses are from the English ROM - bank 4 is mapped to $8000 here):
For $A07B to reach the store to $03FB, the following have to be true:
- $0053 = 0
- The low bit of $0010 is clear
- $03FD >= 127
It does look like this routine is called for other purposes as well, so conceivably there could be a case where all those preconditions are (incorrectly) met, which would trigger the glitch.
Here's the relevant part of that routine:
I have observed that $03FB will increment after you defeat a boss. From the beginning of the game this is set at value 0, then value 1 after the first boss, and then at value 3 after the second boss. In other words, if you overwrite the value of 3 into $03FB just before entering the second boss fight then you will observe what we see in the video. The game thinks the boss was already defeated. I have observed that $03FB increments the same frame that $03FD reaches a value of 128. $03FD starts at 0 from the beginning of the game and only does a 255 to 0 count down at the beginning of each boss fight, and then counts up from 0 to 128 upon the death of the boss. When this value reaches 128 then $03FB, the address that tracks what bosses have been defeated, will increment.
Observation #1 The first boss loads normally which means that $03FB is at value 0 when entering the first boss fight. If this value was 1 or higher then the boss would not spawn. The first moment that $03FB normally increments is upon the death of the first boss, in which case it increments to 1.
Observation #2 Upon entering the second boss fight the boss did not load which means that $03FB was already at a value of 3.
Conclusion: At some point this address is incremented again. My first suspicion is that it occurs after the first boss fight, that some how it is incremented twice. The later portion of this message shows "conditions" upon an overflow may occur that could possibly corrupt this address but it is still unclear exactly how these conditions could be met.
This is the most pertinent information that I have been able to find at this time.
I played around a little with the Chou-Wakusei Senki - MetaFight (J).nes ROM (GoodNES 3.14) after seeing that happen and will summarize some info here. Hopefully this will serve as a starting point for figuring out the glitch. I used FCEUX 2.2.3 and only played as far as the second boss fight.
After the scrolling ends when you enter a boss room, the following code is executed:
Code:
$971A:A5 14 LDA $0014
$971C:29 07 AND #$07
$971E:AA TAX
$971F:BD 2B B6 LDA $B62B,X
$9722:60 RTS
$9627:2D FB 03 AND $03FB <-- This is the important check
$962A:D0 0F BNE $963B <-- Branch taken if boss defeated
$962C:A9 C0 LDA #$C0
$962E:85 51 STA $0051
$9630:A9 08 LDA #$08
$9632:20 8C C1 JSR $C18C
$9635:20 CD 97 JSR $97CD
$9638:E6 46 INC $0046
$963A:60 RTS
$963B:20 1A 97 JSR $971A
$971C:29 07 AND #$07
$971E:AA TAX
$971F:BD 2B B6 LDA $B62B,X
$9722:60 RTS
$9627:2D FB 03 AND $03FB <-- This is the important check
$962A:D0 0F BNE $963B <-- Branch taken if boss defeated
$962C:A9 C0 LDA #$C0
$962E:85 51 STA $0051
$9630:A9 08 LDA #$08
$9632:20 8C C1 JSR $C18C
$9635:20 CD 97 JSR $97CD
$9638:E6 46 INC $0046
$963A:60 RTS
$963B:20 1A 97 JSR $971A
$0014 is the value (current area - 1) at this point. At $B62B, you find a sequence of increasing powers of two, starting with 0x01. Per Data Crystal's RAM map, $03FB indicates which bosses have been defeated. So this checks if the boss of the current area has been defeated. If it has but the item has not been obtained, then the item is displayed. That seems to be what happened during the race.
If the boss has not been defeated, then the room flashes, the boss loads (including its health), and you proceed with the fight. It appears that the health of the first two bosses is hard-coded into the ROM. For area 1, the pertinent code is:
Code:
$9C15:A9 80 LDA #$80
$9C17:85 53 STA $0053
$9C17:85 53 STA $0053
For area 2, the pertinent code is:
Code:
$91FD:A9 40 LDA #$40
$91FF:85 53 STA $0053
$91FF:85 53 STA $0053
The value from $0053 eventually ends up somewhere around $0470, but the exact RAM address varies. If you change the health to 0x00 before starting the fight (e.g., set execution breakpoint on $9C17, change A from 0x80 to 0x00, then continue emulation), the boss graphics load but immediately go into the death animation. This leads me to believe that whatever Skavenger did may have corrupted $03FB. There are likely other possibilities, but I will let someone with more time and experience take over.
Actually, one other thing. This is the code that is executed when a boss is defeated:
Code:
$971A:A5 14 LDA $0014
$971C:29 07 AND #$07
$971E:AA TAX
$971F:BD 2B B6 LDA $B62B,X
$9722:60 RTS
$97A7:0D FB 03 ORA $03FB
$97AA:8D FB 03 STA $03FB
$971C:29 07 AND #$07
$971E:AA TAX
$971F:BD 2B B6 LDA $B62B,X
$9722:60 RTS
$97A7:0D FB 03 ORA $03FB
$97AA:8D FB 03 STA $03FB
Most if it should be familiar from that first block, but the last two lines update the value at $03FB rather than testing it.
And another analysis:
I haven't looked at Blaster Master before, but this glitch got me curious, so a few observations from looking at the code in case they give anyone any ideas. Note that these are all from the English ROM (the only version I have handy), so if the glitch turns out to be JP-only then none of this may be of much use...
- The only stores to $03FB are the one Dacicus quoted which is done on boss kill, and a few that store literal 0 or 255 (and the 255 clearly can't be the case because the rest of the bosses showed up properly). The store after the area 1 boss kill in that run can't have set the wrong bit, because then the boss would immediately respawn when the room was reloaded after the boss death.
- The only indexed stores that could reach $03FB are the stores to the PPU RAM write buffer at $0300. I played up to area 2 to check, but the buffer high water mark was $0340, and a cursory review of the code suggests it's pretty good at flushing the buffer before it overflows, so it seems unlikely to me that a buffer overflow is the cause. (Also, in order to have disabled only the second boss, the store value would have to have been $02 or $03, which seems unlikely for an arbitrary PPU data store; and if the buffer overflowed all the way up to $03FB then it would stomp on lots of other stuff in the $03xx range, which would probably cause more problems than just a missing boss.) On the other hand, Personman's example of a case when both a boss and its item were missing could indicate a buffer overflow that wrongly set bits in both $03FB and $03FC, so I dunno.
- The boss-defeated store to $03FB has this stack trace (again, addresses are from the English ROM - bank 4 is mapped to $8000 here):
Code:
(0) A109: sta $03FB
(1) A58C: jsr $A07B
(2) C9D3: jmp ($007A) = $A58C
(3) C987: jsr $C9A4
(4) C3D8: jsr $C971
(1) A58C: jsr $A07B
(2) C9D3: jmp ($007A) = $A58C
(3) C987: jsr $C9A4
(4) C3D8: jsr $C971
For $A07B to reach the store to $03FB, the following have to be true:
- $0053 = 0
- The low bit of $0010 is clear
- $03FD >= 127
It does look like this routine is called for other purposes as well, so conceivably there could be a case where all those preconditions are (incorrectly) met, which would trigger the glitch.
Here's the relevant part of that routine:
Code:
A07B: A5 53 lda $53
A07D: F0 10 beq $A08F
A07F: AD FD 03 lda $03FD
A082: F0 7B beq $A0FF
A084: CE FD 03 dec $03FD
A087: D0 76 bne $A0FF
A089: 20 18 A1 jsr $A118
A08C: 4C FC A0 jmp $A0FC
A08F: A5 10 lda $10
A091: 4A lsr a
A092: B0 19 bcs $A0AD
A094: AD FD 03 lda $03FD
A097: D0 0A bne $A0A3
A099: A9 0A lda #$0A
A09B: 20 16 C2 jsr $C216
A09E: A9 0B lda #$0B
A0A0: 20 16 C2 jsr $C216
A0A3: EE FD 03 inc $03FD
A0A6: AD FD 03 lda $03FD
A0A9: C9 80 cmp #$80
A0AB: B0 53 bcs $A100
(...)
A100: 20 0E C1 jsr $C10E // Only reachable from branch at $A0AB
A103: 20 72 A0 jsr $A072 // Get bit for current area (encapsulates "lda $14" etc.)
A106: 0D FB 03 ora $03FB // Set boss-killed flag for current area
A109: 8D FB 03 sta $03FB // Store updated flag byte
A10C: A9 5A lda #$5A
A10E: 85 46 sta $46
A110: A9 00 lda #$00
A112: 20 1A C1 jsr $C11A
A115: 68 pla
A116: 68 pla
A117: 60 rts
A07D: F0 10 beq $A08F
A07F: AD FD 03 lda $03FD
A082: F0 7B beq $A0FF
A084: CE FD 03 dec $03FD
A087: D0 76 bne $A0FF
A089: 20 18 A1 jsr $A118
A08C: 4C FC A0 jmp $A0FC
A08F: A5 10 lda $10
A091: 4A lsr a
A092: B0 19 bcs $A0AD
A094: AD FD 03 lda $03FD
A097: D0 0A bne $A0A3
A099: A9 0A lda #$0A
A09B: 20 16 C2 jsr $C216
A09E: A9 0B lda #$0B
A0A0: 20 16 C2 jsr $C216
A0A3: EE FD 03 inc $03FD
A0A6: AD FD 03 lda $03FD
A0A9: C9 80 cmp #$80
A0AB: B0 53 bcs $A100
(...)
A100: 20 0E C1 jsr $C10E // Only reachable from branch at $A0AB
A103: 20 72 A0 jsr $A072 // Get bit for current area (encapsulates "lda $14" etc.)
A106: 0D FB 03 ora $03FB // Set boss-killed flag for current area
A109: 8D FB 03 sta $03FB // Store updated flag byte
A10C: A9 5A lda #$5A
A10E: 85 46 sta $46
A110: A9 00 lda #$00
A112: 20 1A C1 jsr $C11A
A115: 68 pla
A116: 68 pla
A117: 60 rts