Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Analysis of the glitch item Q;MP- (0x72):
- (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.)
- 1. This Yellow glitch item runs 1BCD
- 2. 1BCD is in the middle of VBlankCopyBgMap, which is supposed to be run from the start at 1BB5.
- *VBlankCopyBgMap is a routine for VBlank - see https://gbdev.io/pandocs/Interrupt_Sources.html
- 3. According to the Pokémon Yellow disassembly, VBlankCopyBgMap:
- ; Copies [hVBlankCopyBGNumRows] rows from hVBlankCopyBGSource to hVBlankCopyBGDest.
- ; If hVBlankCopyBGSource is XX00, the transfer is disabled.
- 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.
- 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:
- af=CD[00]
- bc=00E2
- de=00E1
- hl=1BCD
- sp=DFF5
- (There can be variations in sp (corrupting it in advance?), ly, stat, cnt)
- >
- pop de ; stack pointer +2 - de=original stack pointer's containing bytes
- ld (hl),e ; loads into 1BCD, but is ROM; so unchanged
- ; 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.
- At the end of the loop and start of ld a,0D , I have these values for de, hl and the sp;
- de=6873
- hl=1BE0
- sp=E009
- E009 is Echo RAM for C009
- l (E0) is added to a, resulting in ED
- jr nc,1BAA (passes because the carry flag is not set)
- 1BAA: dec b - underflow from 00 to FF ; n and h flags are now set
- - conditional jump back to 1B72 because z in not set
- ;cycle 1 -
- af=0D40
- bc=FEE2
- de=0000
- hl=1B0D
- sp=E01D
- ;cycle 2 -
- af=2D40
- bc=FDE2
- de=0008
- hl=1B2D
- sp=E031
- ;cycle 46 -
- af=c0c0
- bc=00e2
- de=7c7f
- hl=9cc0
- sp=c418
- - z flag is now set ; n flag also set, h unset, c unset
- > 1bad: a is overwritten with ffbf (hSPTemp) and again for ffc0 (+1) ; the stack pointer temporary becomes hl, loaded into the actual stack pointer
- ldh a, [hSPTemp]
- ld l, a
- ldh a, [hSPTemp + 1]
- ld h, a
- ld sp, hl
- ret
- Stack pointer now equals E32F. On the ret, 1E09 is our next destination containing a call at 1E09 to VBlankCopyBgMap.
- Calls are made to the following (and more)
- 00:1BB5 VBlankCopyBgMap
- - ; Skipped some analysis, it makes it to the next call to RedrawRoworColumn and our registers before the call are
- af=E3C0
- bc=00E2
- de=1010
- hl=E32F
- sp=E331
- 00:1ADA RedrawRowOrColumn
- ; Yes it made it to VBlankCopy
- af=00A0
- bc=00E2
- de=1010
- hl=E32F
- sp=E331
- 00:1C21 VBlankCopy
- VBlankCopy:: Disassembly says -
- ; Copy [hVBlankCopySize] 2bpp tiles (or 16 * [hVBlankCopySize] tile map entries)
- ; from hVBlankCopySource to hVBlankCopyDest.
- ; Source and destination addresses are updated,
- ; so transfer can continue in subsequent calls.
- -In this case, the copy size is 00 (from a) (or 16 * 0 tile map entries??) (is this really x256?)
- -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).
- af=00a0
- bc=00e2
- de=1010
- hl=e32f
- sp=e331
- 00:1BD1 VBlankCopyDouble
- Disassembly says
- VBlankCopyDouble::
- ; Copy [hVBlankCopyDoubleSize] 1bpp tiles
- ; from hVBlankCopyDoubleSource to hVBlankCopyDoubleDest.
- ; While we're here, convert to 2bpp.
- ; The process is straightforward:
- ; copy each byte twice.
- [hVBlankCopyDoubleSize] is FFCB; is 00, followed by and a - z flag is set ; again seems to end without copying anything.
- 00:1C75 UpdateMovingBgTiles
- af=00A0
- bc=00E2
- de=1010
- hl=E32F
- sp=E331
- (z flag set, n unset, h set, c unset)
- UpdateMovingBgTiles::
- ; Animate water and flower
- ; tiles in the overworld.
- FFD7 (hTileAnimations) > a (00)
- ret z (z flag is set so seemingly nothing.. again lol)
- @1E18
- af=00A0
- bc=00E2
- de=1010
- hl=E32F
- sp=E331
- lcdc=E3
- stat=88
- ly=02
- cnt=68
- ie=0d
- if=F2
- call FF80 (OAM DMA routine)
- - Runs OAM DMA ; does timing - runs the E32F @1E1B which was next on the stack (really just past the earlier call FF80)
- 1E1B - Switch to ROM bank 1
- @1e22 Call 1:499B (PrepareOAMData)
- af=01c0
- bc=00e2
- de=1010
- hl=e32f
- sp=e331
- cfca (update sprites enabled)>a (01)
- -0 into oam buffer offset (ff90) and ff8f (sprite loop)
- C1(de)
- ; Determine OAM data for currently visible
- ; sprites and write it to wOAMBuffer.
- ; Yellow code has been changed to use registers more efficiently
- ; as well as tweaking the code to show gbc palettes
- (Come back to later)
Add Comment
Please, Sign In to add comment