Torchickens

Pokémon Yellow a little analysis of QMP (0x72) glitch item

May 23rd, 2022 (edited)
123
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.79 KB | None | 0 0
  1. Analysis of the glitch item Q;MP- (0x72):
  2.  
  3. (I'm unsure if this has already been known just restricted to speedrunning circles; the below is an incomplete analysis of Q;MP- in more detail.)
  4.  
  5. 1. This Yellow glitch item runs 1BCD
  6. 2. 1BCD is in the middle of VBlankCopyBgMap, which is supposed to be run from the start at 1BB5.
  7. *VBlankCopyBgMap is a routine for VBlank - see https://gbdev.io/pandocs/Interrupt_Sources.html
  8.  
  9. 3. According to the Pokémon Yellow disassembly, VBlankCopyBgMap:
  10.  
  11. ; Copies [hVBlankCopyBGNumRows] rows from hVBlankCopyBGSource to hVBlankCopyBGDest.
  12. ; If hVBlankCopyBGSource is XX00, the transfer is disabled.
  13.  
  14. 4. At 1BCD (the execution pointer of this glitch item), the game will skip over some manipulation of the registers, z flag (if applicable; i.e. "If hVBlankCopyBGSource is XX00, the transfer is disabled.") and the stack pointer is not saved. It will proceed to run TransferBgRows via a relative jump that follows in the code even if hVBlankCopyBGSource is XX00.
  15.  
  16. 5. Setting a breakpoint to using the glitch item, the registers were as such - so any analysis that follows will be based on this data:
  17.  
  18. af=CD[00]
  19. bc=00E2
  20. de=00E1
  21. hl=1BCD
  22. sp=DFF5
  23.  
  24. (There can be variations in sp (corrupting it in advance?), ly, stat, cnt)
  25.  
  26. >
  27.  
  28. pop de ; stack pointer +2 - de=original stack pointer's containing bytes
  29. ld (hl),e ; loads into 1BCD, but is ROM; so unchanged
  30. ; various writes to ROM, code repeats (including parts written in repetition) - in total 10x pop de ; so I guess stack pointer is +20 of the original.
  31.  
  32. At the end of the loop and start of ld a,0D , I have these values for de, hl and the sp;
  33.  
  34. de=6873
  35. hl=1BE0
  36. sp=E009
  37.  
  38. E009 is Echo RAM for C009
  39.  
  40. l (E0) is added to a, resulting in ED
  41.  
  42. jr nc,1BAA (passes because the carry flag is not set)
  43.  
  44. 1BAA: dec b - underflow from 00 to FF ; n and h flags are now set
  45.  
  46. - conditional jump back to 1B72 because z in not set
  47.  
  48. ;cycle 1 -
  49.  
  50. af=0D40
  51. bc=FEE2
  52. de=0000
  53. hl=1B0D
  54. sp=E01D
  55.  
  56. ;cycle 2 -
  57.  
  58. af=2D40
  59. bc=FDE2
  60. de=0008
  61. hl=1B2D
  62. sp=E031
  63.  
  64. ;cycle 46 -
  65.  
  66. af=c0c0
  67. bc=00e2
  68. de=7c7f
  69. hl=9cc0
  70. sp=c418
  71.  
  72. - z flag is now set ; n flag also set, h unset, c unset
  73.  
  74. > 1bad: a is overwritten with ffbf (hSPTemp) and again for ffc0 (+1) ; the stack pointer temporary becomes hl, loaded into the actual stack pointer
  75.  
  76. ldh a, [hSPTemp]
  77. ld l, a
  78. ldh a, [hSPTemp + 1]
  79. ld h, a
  80. ld sp, hl
  81. ret
  82.  
  83. Stack pointer now equals E32F. On the ret, 1E09 is our next destination containing a call at 1E09 to VBlankCopyBgMap.
  84.  
  85. Calls are made to the following (and more)
  86.  
  87. 00:1BB5 VBlankCopyBgMap
  88.  
  89. - ; Skipped some analysis, it makes it to the next call to RedrawRoworColumn and our registers before the call are
  90.  
  91. af=E3C0
  92. bc=00E2
  93. de=1010
  94. hl=E32F
  95. sp=E331
  96.  
  97. 00:1ADA RedrawRowOrColumn
  98.  
  99. ; Yes it made it to VBlankCopy
  100.  
  101. af=00A0
  102. bc=00E2
  103. de=1010
  104. hl=E32F
  105. sp=E331
  106.  
  107.  
  108. 00:1C21 VBlankCopy
  109.  
  110.  
  111. VBlankCopy:: Disassembly says -
  112. ; Copy [hVBlankCopySize] 2bpp tiles (or 16 * [hVBlankCopySize] tile map entries)
  113. ; from hVBlankCopySource to hVBlankCopyDest.
  114.  
  115. ; Source and destination addresses are updated,
  116. ; so transfer can continue in subsequent calls.
  117.  
  118. -In this case, the copy size is 00 (from a) (or 16 * 0 tile map entries??) (is this really x256?)
  119. -but the z flag is set and before the main code is a ret z. Perhaps again, nothing is really copied (the BG Map code tried to write to ROM, and this ended from a ret z @1c24).
  120.  
  121.  
  122. af=00a0
  123. bc=00e2
  124. de=1010
  125. hl=e32f
  126. sp=e331
  127.  
  128. 00:1BD1 VBlankCopyDouble
  129.  
  130. Disassembly says
  131.  
  132. VBlankCopyDouble::
  133. ; Copy [hVBlankCopyDoubleSize] 1bpp tiles
  134. ; from hVBlankCopyDoubleSource to hVBlankCopyDoubleDest.
  135.  
  136. ; While we're here, convert to 2bpp.
  137. ; The process is straightforward:
  138. ; copy each byte twice.
  139.  
  140. [hVBlankCopyDoubleSize] is FFCB; is 00, followed by and a - z flag is set ; again seems to end without copying anything.
  141.  
  142.  
  143.  
  144. 00:1C75 UpdateMovingBgTiles
  145.  
  146. af=00A0
  147. bc=00E2
  148. de=1010
  149. hl=E32F
  150. sp=E331
  151.  
  152. (z flag set, n unset, h set, c unset)
  153.  
  154.  
  155. UpdateMovingBgTiles::
  156. ; Animate water and flower
  157. ; tiles in the overworld.
  158.  
  159.  
  160. FFD7 (hTileAnimations) > a (00)
  161. ret z (z flag is set so seemingly nothing.. again lol)
  162.  
  163. @1E18
  164.  
  165. af=00A0
  166. bc=00E2
  167. de=1010
  168. hl=E32F
  169. sp=E331
  170.  
  171. lcdc=E3
  172. stat=88
  173. ly=02
  174. cnt=68
  175. ie=0d
  176. if=F2
  177.  
  178. call FF80 (OAM DMA routine)
  179.  
  180. - Runs OAM DMA ; does timing - runs the E32F @1E1B which was next on the stack (really just past the earlier call FF80)
  181.  
  182. 1E1B - Switch to ROM bank 1
  183. @1e22 Call 1:499B (PrepareOAMData)
  184.  
  185. af=01c0
  186. bc=00e2
  187. de=1010
  188. hl=e32f
  189. sp=e331
  190.  
  191.  
  192. cfca (update sprites enabled)>a (01)
  193. -0 into oam buffer offset (ff90) and ff8f (sprite loop)
  194.  
  195. C1(de)
  196.  
  197. ; Determine OAM data for currently visible
  198. ; sprites and write it to wOAMBuffer.
  199. ; Yellow code has been changed to use registers more efficiently
  200. ; as well as tweaking the code to show gbc palettes
  201.  
  202. (Come back to later)
Add Comment
Please, Sign In to add comment