-
Notifications
You must be signed in to change notification settings - Fork 1
Sketch Glitch mechanics
When sketching, the game looks up to the monster sprite data. Function C2/F5D2
:
C2:F5D2 A0 00 28 LDY #$2800
C2:F5D5 22 09 B1 C1 JSL $C1B109
C2:F5D9 AD 8D 89 LDA $898D
C2:F5DC 29 FE AND #$FE
C2:F5DE 8D 8D 89 STA $898D
C2:F5E1 A0 03 00 LDY #$0003
C2:F5E4 B1 76 LDA ($76),Y
C2:F5E6 0A ASL
C2:F5E7 AA TAX
C2:F5E8 C2 20 REP $20
C2:F5EA BD 01 20 LDA $2001,X
C2:F5ED AA TAX
C2:F5EE 7B TDC
C2:F5EF E2 20 SEP $20
C2:F5F1 22 D1 24 C1 JSL $C124D1
C2:F5F5 4C 09 F8 JMP $F809
When the sketch misses, instruction LDA ($76),Y
(loaded from 7E:2D71
according to masterZed) contains 0xFF instead of the enemy slot number (from 0 to 5). So LDA $2001,X
is fetching the 16-bit integer $7E:20FF - $7E:2100
which is in the middle of the spell table. $7E:20FF
contains information about the usability of the 28th spell (was used/available). $7E:2100
contains the aiming byte of the 28th spell. In an example of a working sketch glitch, the 16-bit integer $7E:20FF - $7E:2100
is 0x417f.
The function C1/24D1
and sub-functions are executed with X = 0x417F. X is used as an offset for many memory fetches, which will generate many mistakes. The main mistake will be to set the height of the enemy sprite to 0. Then, during a double loop to copy the enemy sprite from one place to another, the number of iterations of the loop will be 255, because the height will first be decreased by one (0 - 1 = 255) and the loop will stop when the height is zero.
The size template is taken as the address t = $(D27004 + (X << 2) + X). For X = 0x417F, the address becomes
After that the integer $7E:20FF - $7E:2100
has been wrongly interpreted as the enemy id, the following occurs:
- Function C1/24F5 is gathering information in the ROM about the monster visual specifications.
-
Function C1/215F is setting the array
$822D - $824C
which is supposed to contain the disposition of tiles in the enemy sprite. It also computes the enemy sprite width and height. -
Function C1/22A5 is copying the tiles from ROM to RAM at the right places based on
$822D - $824C
Because the enemy sprite height will be 0 in case of the glitch, the reads on table $822D - $824C
will go well over $824C
, so we need to determine how further addresses are set. Addresses $824C
to $8258
are temporary variables used in the previous functions, but addresses $8258+
are set during the battle startup, based on the formation mold in Function C1/3E72.
- $81A8-$81A9: encode the sprite location in memory
- $81AA: index to map used
- $81AB: Stencil bit
- $81AC: first bit is 8-bit or 16-bit color, rest is ??? (comes from $D27002+5*enemy_id)
- $824D: loop decrementor, inited as 0x10
- $824E: loop incrementor, inited as 0, incremented by 2, used as index X for next two variables:
- $824F-$8250: temp for $822D,X-$822E,X, shifted left every loop iteration, if highest bit is set, do the copy
- $8251: constant, set as sprite width
- $8252: loop decrementor, set as sprite width
- $8253: loop decrementor, set as sprite height
- $8254-$8255: loop incrementor, set as 0, incremented by 0x18 or 0x20 depending on color depth
- $8256: width/8
- $8257: height/8
- $8259: tiles offsets, array of 0x198 elements. Set in
C1/3E72
- $83F1, $8589, $8721: flipped copies of $8259
- $2000: group formation mold index
- $61-$62: RAM address to copy the sprite to
- $64-$66: actual pointer to the beginning of the monster sprite in ROM