Skip to content

Sketch Glitch mechanics

Clément Gallet edited this page Jul 4, 2014 · 1 revision

Sketch Glitch entry point

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 $D2B77F so t = 0xFE. Then, the disposition of tiles in the enemy sprite is extracted starting address D = $(D2AC24 + 32 * t) = $D2DDC0. The height is then computed from the number of consecutive non-empty values in [D,D+0x20]. However, $D2DDC0 = 0 so it sets the height to 0.


More details

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.


Relevant addresses in normal conditions

  • $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
Clone this wiki locally