diff options
author | YamaArashi <shadow962@live.com> | 2012-01-31 23:43:28 -0800 |
---|---|---|
committer | YamaArashi <shadow962@live.com> | 2012-01-31 23:43:28 -0800 |
commit | 2e67759f9daf0d833d21bac3aea38444d0578974 (patch) | |
tree | 79d4752e23f01f2cb15040725aaa67ccd6e9c314 | |
parent | c82b5f5e3d62c585bb4e842e039107947ab19ac6 (diff) |
disasm of some battle animation code
hg-commit-id: 5c2a07265f14
-rw-r--r-- | constants.asm | 38 | ||||
-rw-r--r-- | main.asm | 612 |
2 files changed, 578 insertions, 72 deletions
diff --git a/constants.asm b/constants.asm index e55e5a26..32f0b9b4 100644 --- a/constants.asm +++ b/constants.asm @@ -156,6 +156,8 @@ W_ENEMYMONEVASIONMOD EQU $CD33 W_WHICHTRADE EQU $CD3D ; which entry from TradeMons to select +W_ANIMSOUNDID EQU $CF07 ; sound ID during battle animations + W_WHICHPOKEMON EQU $CF92 ; which pokemon you selected W_WALKCOUNTER EQU $CFC5 ; walk animation counter @@ -269,6 +271,39 @@ W_ENEMYDISABLEDMOVE EQU $D072 W_NUMHITS EQU $D074 ; number of hits in attacks like Doubleslap, etc. +W_ANIMATIONID EQU $D07C ; ID number of the current battle animation + +; base coordinates of frame block +W_BASECOORDX EQU $D081 +W_BASECOORDY EQU $D082 + +W_FBTILECOUNTER EQU $D084 ; counts how many tiles of the current frame block have been drawn + +W_SUBANIMFRAMEDELAY EQU $D086 ; duration of each frame of the current subanimation in terms of screen refreshes + +W_SUBANIMSIZE EQU $D087 ; number of frame blocks in the current subanimation + +W_NUMFBTILES EQU $D089 ; number of tiles in current battle animation frame block + +W_SUBANIMTRANSFORM EQU $D08B ; controls what transformations are applied to the subanimation +; 01: flip horizontally and vertically +; 02: flip horizontally and translate downwards 40 pixels +; 03: translate base coordinates of frame blocks, but don't change their internal coordinates or flip their tiles +; 04: reverse the subanimation + +W_SUBANIMADDRPTR EQU $D094 ; the address _of the address_ of the current subanimation entry (2 bytes) + +W_SUBANIMSUBENTRYADDR EQU $D096 ; the address of the current subentry of the current subanimation (2 bytes) + +W_FBDESTADDR EQU $D09C ; current destination address in OAM for frame blocks (2 bytes, big endian) + +W_FBMODE EQU $D09E ; controls how the frame blocks are put together to form frames +; specifically, after finishing drawing the frame block, the frame block's mode determines what happens +; 00: clean OAM buffer and delay +; 02: move onto the next frame block with no delay and no cleaning OAM buffer +; 03: delay, but don't clean OAM buffer +; 04: delay, without cleaning OAM buffer, and do not advance [W_FBDESTADDR], so that the next frame block will overwrite this one + W_DAMAGE EQU $D0D7 ; List type @@ -833,6 +868,9 @@ rWY EQU $FF4A rWX EQU $FF4B rIE EQU $FFFF +; OAM attribute flags +OAM_HFLIP EQU %00100000 ; horizontal flip +OAM_VFLIP EQU %01000000 ; vertical flip ; pokemon name constants RHYDON EQU $01 @@ -63774,50 +63774,212 @@ INCBIN "baserom.gbc",$76857,$76880 - $76857 SECTION "bank1E",DATA,BANK[$1E] -INCBIN "baserom.gbc",$78000,$F1 +; Draws a "frame block". Frame blocks are blocks of tiles that are put +; together to form frames in battle animations. +DrawFrameBlock: ; 4000 + ld l,c + ld h,b + ld a,[hli] + ld [W_NUMFBTILES],a + ld a,[W_FBDESTADDR + 1] + ld e,a + ld a,[W_FBDESTADDR] + ld d,a + xor a + ld [W_FBTILECOUNTER],a ; loop counter +.loop\@ + ld a,[W_FBTILECOUNTER] + inc a + ld [W_FBTILECOUNTER],a + ld a,[W_SUBANIMTRANSFORM] + dec a + jr z,.flipHorizontalAndVertical\@ ; 1 + dec a + jp z,.flipHorizontalTranslateDown\@ ; 2 + dec a + jr z,.flipBaseCoords\@ ; 3 +.noTransformation\@ + ld a,[W_BASECOORDY] + add [hl] + ld [de],a ; store Y + inc hl + inc de + ld a,[W_BASECOORDX] + jr .finishCopying\@ +.flipBaseCoords\@ + ld a,[W_BASECOORDY] + ld b,a + ld a,136 + sub b ; flip Y base coordinate + add [hl] ; Y offset + ld [de],a ; store Y + inc hl + inc de + ld a,[W_BASECOORDX] + ld b,a + ld a,168 + sub b ; flip X base coordinate +.finishCopying\@ ; finish copying values to OAM (when [W_SUBANIMTRANSFORM] not 1 or 2) + add [hl] ; X offset + ld [de],a ; store X + inc hl + inc de + ld a,[hli] + add a,$31 ; base tile ID for battle animations + ld [de],a ; store tile ID + inc de + ld a,[hli] + ld [de],a ; store flags + inc de + jp .nextTile\@ +.flipHorizontalAndVertical\@ + ld a,[W_BASECOORDY] + add [hl] ; Y offset + ld b,a + ld a,136 + sub b ; flip Y coordinate + ld [de],a ; store Y + inc hl + inc de + ld a,[W_BASECOORDX] + add [hl] ; X offset + ld b,a + ld a,168 + sub b ; flip X coordinate + ld [de],a ; store X + inc hl + inc de + ld a,[hli] + add a,$31 ; base tile ID for battle animations + ld [de],a ; store tile ID + inc de +; toggle horizontal and vertical flip + ld a,[hli] ; flags + and a + ld b,OAM_VFLIP | OAM_HFLIP + jr z,.storeFlags1\@ + cp a,OAM_HFLIP + ld b,OAM_VFLIP + jr z,.storeFlags1\@ + cp a,OAM_VFLIP + ld b,OAM_HFLIP + jr z,.storeFlags1\@ + ld b,0 +.storeFlags1\@ + ld a,b + ld [de],a + inc de + jp .nextTile\@ +.flipHorizontalTranslateDown\@ + ld a,[W_BASECOORDY] + add [hl] + add a,40 ; translate Y coordinate downwards + ld [de],a ; store Y + inc hl + inc de + ld a,[W_BASECOORDX] + add [hl] + ld b,a + ld a,168 + sub b ; flip X coordinate + ld [de],a ; store X + inc hl + inc de + ld a,[hli] + add a,$31 ; base tile ID for battle animations + ld [de],a ; store tile ID + inc de + ld a,[hli] + bit 5,a ; is horizontal flip enabled? + jr nz,.disableHorizontalFlip\@ +.enableHorizontalFlip\@ + set 5,a + jr .storeFlags2\@ +.disableHorizontalFlip\@ + res 5,a +.storeFlags2\@ + ld [de],a + inc de +.nextTile\@ + ld a,[W_FBTILECOUNTER] + ld c,a + ld a,[W_NUMFBTILES] + cp c + jp nz,.loop\@ ; go back up if there are more tiles to draw +.afterDrawingTiles\@ + ld a,[W_FBMODE] + cp a,2 + jr z,.advanceFrameBlockDestAddr\@; skip delay and don't clean OAM buffer + ld a,[W_SUBANIMFRAMEDELAY] + ld c,a + call DelayFrames + ld a,[W_FBMODE] + cp a,3 + jr z,.advanceFrameBlockDestAddr\@ ; skip cleaning OAM buffer + cp a,4 + jr z,.done\@ ; skip cleaning OAM buffer and don't advance the frame block destination address + ld a,[W_ANIMATIONID] + cp a,GROWL + jr z,.resetFrameBlockDestAddr\@ + call AnimationCleanOAM +.resetFrameBlockDestAddr\@ + ld hl,$C300 ; OAM buffer + ld a,l + ld [W_FBDESTADDR + 1],a + ld a,h + ld [W_FBDESTADDR],a ; set destination address to beginning of OAM buffer + ret +.advanceFrameBlockDestAddr\@ + ld a,e + ld [W_FBDESTADDR + 1],a + ld a,d + ld [W_FBDESTADDR],a +.done\@ + ret PlayAnimation: ; 40F1 xor a ld [$FF8B],a - ld [$D08B],a - ld a,[$D07C] ; get animation number + ld [W_SUBANIMTRANSFORM],a + ld a,[W_ANIMATIONID] ; get animation number dec a ld l,a ld h,0 add hl,hl - ld de,$607D + ld de,$607D ; animation command stream pointers add hl,de ld a,[hli] ld h,[hl] ld l,a -.next7\@ +.animationLoop\@ ld a,[hli] cp a,$FF jr z,.AnimationOver\@ - cp a,$C0 ; is this animation for a monster onscreen? - jr c,.next2\@ + cp a,$C0 ; is this subanimation or a special effect? + jr c,.playSubanimation\@ +.doSpecialEffect\@ ld c,a - ld de,$50DA -.next4\@ + ld de,SpecialEffectPointers +.searchSpecialEffectTableLoop\@ ld a,[de] cp c - jr z,.next3\@ + jr z,.foundMatch\@ inc de inc de inc de - jr .next4\@ -.next3\@ + jr .searchSpecialEffectTableLoop\@ +.foundMatch\@ ld a,[hli] - cp a,$FF - jr z,.next5\@ - ld [$CF07],a + cp a,$FF ; is there a sound to play? + jr z,.skipPlayingSound\@ + ld [$CF07],a ; store sound push hl push de call $586F call $23B1 pop de pop hl -.next5\@ +.skipPlayingSound\@ push hl inc de ld a,[de] @@ -63825,33 +63987,33 @@ PlayAnimation: ; 40F1 inc de ld a,[de] ld h,a - ld de,.next6\@ + ld de,.nextAnimationCommand\@ push de - jp [hl] -.next2\@ + jp [hl] ; jump to special effect function +.playSubanimation\@ ld c,a - and a,$3F - ld [$D086],a + and a,63 + ld [W_SUBANIMFRAMEDELAY],a xor a sla c rla sla c rla - ld [$D09F],a - ld a,[hli] - ld [$CF07],a - ld a,[hli] + ld [$D09F],a ; tile select + ld a,[hli] ; sound + ld [$CF07],a ; store sound + ld a,[hli] ; subanimation ID ld c,l ld b,h ld l,a ld h,0 add hl,hl - ld de,$676D + ld de,$676D ; subanimation pointer table add hl,de ld a,l - ld [$D094],a + ld [W_SUBANIMADDRPTR],a ld a,h - ld [$D095],a + ld [W_SUBANIMADDRPTR + 1],a ld l,c ld h,b push hl @@ -63859,18 +64021,126 @@ PlayAnimation: ; 40F1 push af ld a,[$CC79] ld [rOBP0],a - call $41D2 - call $417C - call RealPlayAnimation + call LoadAnimationTileset + call LoadSubanimation + call PlaySubanimation pop af ld [rOBP0],a -.next6\@ +.nextAnimationCommand\@ pop hl - jr .next7\@ + jr .animationLoop\@ .AnimationOver\@ ; 417B ret -INCBIN "baserom.gbc",$7817C,$78BDE - $7817C +LoadSubanimation: ; 417C + ld a,[W_SUBANIMADDRPTR + 1] + ld h,a + ld a,[W_SUBANIMADDRPTR] + ld l,a + ld a,[hli] + ld e,a + ld a,[hl] + ld d,a ; de = address of subanimation + ld a,[de] + ld b,a + and a,31 + ld [W_SUBANIMSIZE],a ; number of frame blocks + ld a,b + and a,%11100000 + cp a,5 << 5 ; is subanimation type 5? + jr nz,.isNotType5\@ +.isType5\@ + call GetSubanimationTransform2 + jr .saveTransformation\@ +.isNotType5\@ + call GetSubanimationTransform1 +.saveTransformation\@ +; place the upper 3 bits of a into bits 0-2 of a before storing + srl a + swap a + ld [W_SUBANIMTRANSFORM],a + cp a,4 ; is the animation reversed? + ld hl,0 + jr nz,.storeSubentryAddr\@ +; if the animation is reversed, then place the initial subentry address at the end of the list of subentries + ld a,[W_SUBANIMSIZE] + dec a + ld bc,3 +.loop\@ + add hl,bc + dec a + jr nz,.loop\@ +.storeSubentryAddr\@ + inc de + add hl,de + ld a,l + ld [W_SUBANIMSUBENTRYADDR],a + ld a,h + ld [W_SUBANIMSUBENTRYADDR + 1],a + ret + +; called if the subanimation type is not 5 +; sets the transform to 0 (i.e. no transform) if it's the player's turn +; sets the transform to the subanimation type if it's the enemy's turn +GetSubanimationTransform1: ; 41C2 + ld b,a + ld a,[H_WHOSETURN] + and a + ld a,b + ret nz + xor a + ret + +; called if the subanimation type is 5 +; sets the transform to 2 (i.e. horizontal and vertical flip) if it's the player's turn +; sets the transform to 0 (i.e. no transform) if it's the enemy's turn +GetSubanimationTransform2: ; 41CA + ld a,[H_WHOSETURN] + and a + ld a,2 << 5 + ret z + xor a + ret + +; loads tile patterns for battle animations +LoadAnimationTileset: ; 41D2 + ld a,[$D09F] ; tileset select + add a + add a + ld hl,AnimationTilesetPointers + ld e,a + ld d,0 + add hl,de + ld a,[hli] + ld [$D07D],a ; number of tiles + ld a,[hli] + ld e,a + ld a,[hl] + ld d,a ; de = address of tileset + ld hl,$8310 ; destination address in VRAM + ld b,$1E ; ROM bank + ld a,[$D07D] + ld c,a ; number of tiles + jp $1848 ; load tileset + +AnimationTilesetPointers: ; 41F2 +db 79 ; number of tiles +dw AnimationTileset1 +db $FF + +db 79 ; number of tiles +dw AnimationTileset2 +db $FF + +db 64 ; number of tiles +dw AnimationTileset1 +db $FF + +AnimationTileset1: ; 41FE +INCBIN "baserom.gbc",$781FE,79 * 16 + +AnimationTileset2: ; 46EE +INCBIN "baserom.gbc",$786EE,79 * 16 IF _RED INCBIN "gfx/red/slotmachine2.2bpp" @@ -63886,7 +64156,7 @@ MoveAnimation: ; 4D5E push af call $3748 call $4E23 - ld a,[$D07C] + ld a,[W_ANIMATIONID] and a jr z,.AnimationFinished\@ @@ -63932,7 +64202,7 @@ ShareMoveAnimations: ; 4DA6 ; opponent’s turn - ld a,[$D07C] + ld a,[W_ANIMATIONID] cp a,AMNESIA ld b,CONF_ANIM @@ -63944,7 +64214,7 @@ ShareMoveAnimations: ; 4DA6 .Replace\@ ld a,b - ld [$D07C],a + ld [W_ANIMATIONID],a ret Function4DBD: ; 4DBD @@ -63967,24 +64237,25 @@ Pointer4DCF: ; 4DCF INCBIN "baserom.gbc",$78DDB,$78E53-$78DDB -RealPlayAnimation: ; 4E53 - ld a,[$CF07] ; get animation # − 1 +PlaySubanimation: ; 4E53 + ld a,[W_ANIMSOUNDID] cp a,$FF - jr z,.Next4E60 + jr z,.skipPlayingSound\@ call $586F call $23B1 ; play sound effect -.Next4E60 - ld hl,$C300 +.skipPlayingSound\@ + ld hl,$C300 ; base address of OAM buffer ld a,l - ld [$D09D],a + ld [W_FBDESTADDR + 1],a ld a,h - ld [$D09C],a - ld a,[$D097] + ld [W_FBDESTADDR],a + ld a,[W_SUBANIMSUBENTRYADDR + 1] ld h,a - ld a,[$D096] + ld a,[W_SUBANIMSUBENTRYADDR] ld l,a +.loop\@ push hl - ld c,[hl] + ld c,[hl] ; frame block ID ld b,0 ld hl,PointerTable6F74 add hl,bc @@ -63996,43 +64267,240 @@ RealPlayAnimation: ; 4E53 pop hl inc hl push hl - ld e,[hl] + ld e,[hl] ; base coordinate ID ld d,0 - ld hl,$7C85 + ld hl,$7C85 ; base coordinate table add hl,de add hl,de ld a,[hli] - ld [$D082],a + ld [W_BASECOORDY],a ld a,[hl] - ld [$D081],a + ld [W_BASECOORDX],a pop hl inc hl - ld a,[hl] - ld [$D09E],a - call $4000 - call $4ED7 - ld a,[$D087] + ld a,[hl] ; frame block mode + ld [W_FBMODE],a + call DrawFrameBlock + call $4ED7 ; run animation-specific function (if there is one) + ld a,[W_SUBANIMSIZE] dec a - ld [$D087],a + ld [W_SUBANIMSIZE],a ret z - ld a,[$D097] + ld a,[W_SUBANIMSUBENTRYADDR + 1] ld h,a - ld a,[$D096] + ld a,[W_SUBANIMSUBENTRYADDR] ld l,a - ld a,[$D08B] - cp a,4 + ld a,[W_SUBANIMTRANSFORM] + cp a,4 ; is the animation reversed? ld bc,3 - jr nz,.Next4EBC - ld bc,$FFFD -.Next4EBC + jr nz,.nextSubanimationSubentry\@ + ld bc,-3 +.nextSubanimationSubentry\@ add hl,bc ld a,h - ld [$D097],a + ld [W_SUBANIMSUBENTRYADDR + 1],a ld a,l - ld [$D096],a - jp $4E73 + ld [W_SUBANIMSUBENTRYADDR],a + jp .loop\@ -INCBIN "baserom.gbc",$78EC8,$7986F - $78EC8 +AnimationCleanOAM: ; 4EC8 + push hl + push de + push bc + push af + call DelayFrame + call CleanLCD_OAM + pop af + pop bc + pop de + pop hl + ret + +; this runs after each frame block is drawn in a subanimation +; it runs a particular special effect based on the animation ID +DoSpecialEffectByAnimationId: ; 4ED7 + push hl + push de + push bc + ld a,[W_ANIMATIONID] + ld hl,AnimationIdSpecialEffects + ld de,3 + call IsInArray + jr nc,.done\@ + inc hl + ld a,[hli] + ld h,[hl] + ld l,a + ld de,.done\@ + push de + jp [hl] +.done\@ + pop bc + pop de + pop hl + ret + +; Format: Animation ID (1 byte), Address (2 bytes) +AnimationIdSpecialEffects: ; 4EF5 + db MEGA_PUNCH + dw $51BE + + db GUILLOTINE + dw $51BE + + db MEGA_KICK + dw $51BE + + db HEADBUTT + dw $51BE + + db TAIL_WHIP + dw $50D0 + + db GROWL + dw $50BC + + db DISABLE + dw $51BE + + db BLIZZARD + dw $5016 + + db BUBBLEBEAM + dw $51BE + + db HYPER_BEAM + dw $5000 + + db THUNDERBOLT + dw $4FF7 + + db REFLECT + dw $51BE + + db SELFDESTRUCT + dw $5009 + + db SPORE + dw $51BE + + db EXPLOSION + dw $5009 + + db ROCK_SLIDE + dw $4FD9 + + db $AA + dw $5041 + + db $AB + dw $504C + + db $AC + dw $507C + + db TOSS_ANIM + dw $4F3E + + db $C2 + dw $4F96 + + db POOF_ANIM + dw $4FCE + + db GREATTOSS_ANIM + dw $4F3E + + db ULTRATOSS_ANIM + dw $4F3E + + db $FF ; terminator + +INCBIN "baserom.gbc",$78F3E,$790DA - $78F3E + +; Format: Special Effect ID (1 byte), Address (2 bytes) +SpecialEffectPointers: ; 50DA + db $FE + dw $51BE + db $FD + dw $51D6 + db $FC + dw $51EA + db $FB + dw $520E + db $FA + dw $5215 + db $F9 + dw $51DB + db $F8 + dw $5165 + db $F7 + dw $527A + db $F6 + dw $5297 + db $F5 + dw $5389 + db $F4 + dw $52AF + db $F3 + dw $536F + db $F2 + dw $53F9 + db $F1 + dw $5415 + db $F0 + dw $51F4 + db $EF + dw $5801 + db $EE + dw $54A1 + db $ED + dw $54F9 + db $EC + dw $5566 + db $EB + dw $577A + db $EA + dw $559F + db $E9 + dw $55C9 + db $E8 + dw $5787 + db $E7 + dw $5C74 + db $E6 + dw $5C8A + db $E5 + dw $5645 + db $E4 + dw $5D77 + db $E3 + dw $5D77 + db $E2 + dw $5424 + db $E1 + dw $5150 + db $E0 + dw $5398 + db $DF + dw $57D8 + db $DE + dw $5369 + db $DD + dw $539E + db $DC + dw $53AB + db $DB + dw $52B9 + db $DA + dw $53B1 + db $D9 + dw $56E0 + db $D8 + dw $5666 + db $FF + +INCBIN "baserom.gbc",$79150,$7986F - $79150 Func586F: ; 0x7986F 586F ld hl,MoveSoundTable @@ -64075,7 +64543,7 @@ Func586F: ; 0x7986F 586F ret IsCryMove: ; 0x798ad ; set carry if the move animation involves playing a monster cry - ld a,[$D07C] + ld a,[W_ANIMATIONID] cp a,GROWL jr z,.CryMove cp a,ROAR @@ -64288,7 +64756,7 @@ TossBallAnimation: ; 5E16 .done\@ ld a,b .PlayNextAnimation\@ - ld [$D07C],a + ld [W_ANIMATIONID],a push bc push hl call PlayAnimation @@ -64305,12 +64773,12 @@ TossBallAnimation: ; 5E16 .BlockBall\@ ; 5E55 ld a,$C1 - ld [$D07C],a + ld [W_ANIMATIONID],a call PlayAnimation ld a,$95 call $23B1 ; play sound effect ld a,BLOCKBALL_ANIM - ld [$D07C],a + ld [W_ANIMATIONID],a jp PlayAnimation INCBIN "baserom.gbc",$79E6A,$7AF74 - $79E6A |