TID ; target: wait7 wait6: 50675 (C5F3) wait7: 09947 (26DB) wait8: 33475 (82C3) Cynda ; target: f15 - f12: d - f13: l - f14: r - f15: u (89F7) - f16: d->u - f17: u (EB36/EC37/ED38) - f18: l->r R29 ; target: f4-f7 (f8 also routed) - f3: l - f4: u - f5: u->r - f6: d->u - f7: u->l - f8: r - f9: u =~=~=~=~=~=~= R29 Manip (works on IGT frames 8-14) [4-8] D R R R R D D D D // D D D D [4] (npc: u) A+L L L L D D D D D L L L L L L L L L L L L L L L L L D L D D D D L L L L L L D D L L L L L U L U L U U U U R R R R R U U U U L L L L L L L L L L L L L L L U U L L L L L D D L L L L L L L [5] (npc: u->r) A+L L L L D D D D D L L L L L L L L L L L L L L D D L D D D D L L L L D L L L L L L L L L L L A+L U U U U U U R R R R R U U U U L L L L L L L L L L L L L L L U U L L L L L D D A+L L L L L L L [6] (npc: d->u) A+L L L L D D D D D L L L L L L L L L L L L L L D D L A+L L L D D D L L L L L D D L L L L L L U L U L U U U U R R R R R U U U U L L L L L L L L L L L L L L L U U L L L L L D D L L L L L L L [7] (npc: u->l) D D D L L L L D D L L L L L L L A+L L L L L L D D D D L L D D L L L L D L L L L L L L L L L U U L L U U U U R R R R R U U U U L L L L L L L L L L L L L L L U U L L D L L D D L L L L L L L L -- [8] (npc: r) A+L L L L D D D D D L L L L L L L A+L L L L D D D D L L L L D L L L L L L L L D D L L L L L L L A+L U U U U U U R R R R R U U U U L L L L L L L L L L L L L L L U U L L L L D D A+L L L L L L L L =~=~=~=~=~=~= Practice ROM: https://cdn.discordapp.com/attachments/143862450712739840/618087960650448906/crysany-practice.zip - (presumably) requires flashcart with RTC for manips to work on console - Down+Select+B on title screen to load practice menu > A to load save > SEL to display diff of the current save compared to the expected save (note: wRTC values will be off when practicing) - if playing from new game, the "expected" wRTC second (204B) is 1 lower than realistic at cynda, so don't worry if that's off - wKenjiBreakTimer (27E6) is randomly rolled (between 3-6), but doesn't change between cynda/collision, so value doesn't matter Collision window (described by the last address in the sav that is written to before the power-off; assumes correct IGT, etc.) - v.early (3+ frames) = nothing written; save for cynda manip still present - early (2009-289B) = invalid checksum (save data is overwritten by cynda save after continue; 4 lagframes loading backup) - TARGET (289C-298C) = successful checksum collision; window size ~= 12488 cycles = 0.178 frames (or 1.00/5.62) = 2.98ms - late (298D-2B82) = invalid checksum (save data is overwritten by cynda save after continue; 4 lagframes loading backup) - v.late (7+ frames) = proper save with valid checksum, but cyndaquil's nickname (and everything after it) is written Miscellaneous notes - gifvex's paste w/route outline: https://pastebin.com/yJnfZbwF - pokecrystal wram/sav addresses: https://raw.githubusercontent.com/pokemon-speedrunning/symfiles/master/savwram/out/pokecrystal.txt - Other collision requirements: > buffered movement to the cynda save tile (for wPlayerField1c), then unbuffered save menu (to deload aide NPC data) > don't bonk into Elm (for wPlayerObjectStepFrame) > wait 4 frames after turnframe on collision save tile before menuing (for wPlayerObjectStepFrame) ; collision can still work, but IGT window changes by +2 (frame perfect) or +1 (2 frames worse than frame perfect) > unexpected wRTC boundaries being crossed (due to slow intro, etc.) can change the required IGT window by -1 > intended collision cluster is on IGT frames 9-12; above r29 manip works on 8-14 to cover common mess-ups getting "lucky" - Other ACE requirements > only works if current box is Box 2 ; have to S&Q after boxes to clear string buffers, so switching wastes no time (and is fastest way to save anyway) > 2nd/5th/8th characters of Box 6 are irrelevant (2nd/5th are overwritten by ACE, 8th is never reached) =~=~=~=~=~=~= Flowtimer Config (offsets for GBI, save file as crysany.json) - NOTE: Stairs/S&Q is 2 sec slower than what is possible with TAS; 1 second faster is very plausible for RTA > can reduce offsets by 1.005 seconds (60 frames) to always do 1st cycle > alternatively, add beeps so you can do either 1st or 2nd cycle, depending on speed of intro (335ms * 3 beeps = 1005ms) > TAS only wastes 18 frames to get the *true* 1st cycle, which is not very realistic for RTA [{ "numBeeps": 5, "offsets": "34670/64600", "name": "TID/SS0", "removeButton": false, "interval": 335 }, { "numBeeps": 5, "offsets": "73381/76155", "name": "Stairs/S&Q", "removeButton": true, "interval": 335 }, { "numBeeps": 5, "offsets": "11519/47048/49333", "name": "Cyn/Sav/Col", "removeButton": true, "interval": 335 }, { "numBeeps": 5, "offsets": "11361", "name": "R29", "removeButton": true, "interval": 335 }] =~=~=~=~=~=~= =~=~=~=~=~=~= SOURCE CODE (plus other dark secrets and mysteries) 15 00 control code ACE ; $15 in [$d10c] = wItemQuantityChangeBuffer ; $00 in [$d10d] = wItemQuantityBuffer ($d10e :: start of wTempMon struct) ; $9b in wTempMonSpecies (sbc e) ; $ad in wTempMonItem (xor l) ; $21 in $00+wTempMonMoves (ld hl, $002b) ; $2b in $01+wTempMonMoves +===========================================================================+ | TID: $26db (ld h, $db) loaded at wTempMonID (RNG manip to get h=$db) | +===========================================================================+ ; 125xp in wTempMonExp (add a) +===========================================================================+ | DVs: $89f7 ; RNG manip to jump to section of wram ~= box names | +===========================================================================+ regs when pc=$d123 (wTempMonDVs) ; af=0200 ; bc=c569 ; de=00ff ; hl=db2b > DV1: $89 = adc c / ld l,a \ > DV2: $f7 = rst $30 = { pop de } \ jp hl / > l = a = $6b ($02+$69) > jp $db6b > [$db6b] = [$f9+wEventFlags] = $80 (add b) > [$db72] = [wCurBox] = $01 (ld bc, xxxx) ; ld bc, $0000 regs when pc=$db75 (wBoxNames) | goals from ACE | ; af=3030 | [$dcad] = [$fcad] = [wBackupMapGroup] = $03 ; bc=0000 | [$dcae] = [$fcae] = [wBackupMapNumber] = $4c ; de=d125 | [$dcd7] = [$fcd7] = [wPartyCount] = $00 ; hl=db6b ($80) | [$db5e] = [$fb5e] = [$ec+wEventFlags] = $00 ; bit 2 = EVENT_RED_IN_MT_SILVER = 0 (he's there) >> BOX1: ( é d 5 'v H sbc d ld [$fb92], a ; $5e sub $87 >> BOX2: é g 5 'v 's é n 6 ld [$fb95], a ; $d7 sub $d4 ld [$fcad], a ; $03 >> BOX3: × M é o 6 pop af adc h ld [$fcae], a ; $4c >> BOX4+BOX5: keep their original names ; 'X' ($97) in "BOX" is sub a (a=$00) ; '4' ($fa) is ld a, [xxxx] (a=[?]) ; '@' ($50) (box terminator) (a=$c3 from ld a, [$0050]) ; 'X' ($97) in "BOX" is sub a (a=$00) ; '5' ($fb) is ei (a=$00) ; '@' ($50) is ld d, b (a=$00 going into BOX6) >> BOX6: é é 5 é é 6 'd ld [$fbxx], a ; $00 | xx @ $fb92 (xx <- $5e) ld [$fcxx], a ; $00 | xx @ $fb95 (xx <- $d7) ret nc