Tuesday, July 4, 2017

Boss flash bloopers

The boss of Sandopolis Zone 2 uses two different palettes: one for the metallic interior, loaded over the enemy palette, and another for the stone shell, loaded over the palette for the stage's background, which is obscured at this point. It's actually this second palette that flashes when the boss takes damage.


Something seems a bit off, though: the two darkest colors of the shell don't flash, resulting in this strange outline effect. A quick look at the code reveals the cause:
loc_7820A:
    moveq   #0,d0
    btst    #0,$20(a0)
    bne.s   loc_78218
    addi.w  #$A,d0

loc_78218:
    bsr.w   sub_7825E
    subq.b  #1,$20(a0)
    ...
; ---------------------------------------------------------------------------

sub_7825E:
    lea     word_7826C(pc),a1
    lea     word_78276(pc,d0.w),a2
    jmp     (CopyWordData_3).l
; ---------------------------------------------------------------------------
word_7826C:
    dc.w  $FC6C, $FC6E, $FC70, $FC72, $FC74
word_78276:
    dc.w    $6E,  $24C,   $28,     4,     2
    dc.w   $AAA,  $CCC,  $CCC,  $EEE,  $EEE
There are five addresses, and two sets of five colors, but the copy function being called is CopyWordData_3. As such, only the first three colors will get pushed to CRAM. Replacing it with a call to CopyWordData_5 resolves the issue.


Lava Reef Zone 1 and Sky Sanctuary Zone also have something strange about their boss flashes. Some of the flash colors are actually much darker than the regular colors; that can't possibly be right.


Below is the the code used by the Lava Reef boss. Can you spot the defect?
loc_78C3A:
    moveq   #0,d0
    btst    #0,$20(a0)
    bne.s   loc_78C48
    addi.w  #4,d0

loc_78C48:
    bsr.w   sub_78C98
    subq.b  #1,$20(a0)
    ...
; ---------------------------------------------------------------------------

sub_78C98:
    lea     word_78CA6(pc),a1
    lea     word_78CB2(pc,d0.w),a2
    jmp     (CopyWordData_6).l
; ---------------------------------------------------------------------------
word_78CA6:
    dc.w  $FC26, $FC28, $FC30, $FC38, $FC3A, $FC3C
word_78CB2:
    dc.w    $2A,     6,     2,  $644,  $422,     0
    dc.w   $888,  $AAA,  $CCC,  $AAA,  $CCC,  $EEE
There are six addresses, two sets of six colors, and the copy function being called is CopyWordData_6. At first glance, everything seems to check out.

Look closer. When $20(a0) is even, d0 is incremented to skip the first set of colors and read from the second. But here, it's being incremented by 4, skipping only the first two colors. CopyWordData_6 will then dutifully copy over the next six colors, which are the last four entries from the regular set, and the first two entries from the flashing set.

A similar defect occurs in the Sky Sanctuary boss. Setting d0 to the correct value resolves the issue:


These defects clearly originate from human error. Each boss has its own flash code, so later bosses probably had their code copied and adapted from existing ones, but the programmer forgot to change the function call or the value of d0.

What's interesting to me is how both oversights are self-correcting: once the boss stops flashing, the normal colors are always restored, so it's hard to notice the problem. You have to be paying close attention to the boss while it's flashing, and you need to know the colors are wrong in advance.

1 comment:

  1. I remember seeing that this was corrected on your Twitter, so that's something interesting. I do feel like noting that this also seems to make the HUD blink even more sharply than before.

    ReplyDelete