diff options
Diffstat (limited to 'engine')
133 files changed, 19080 insertions, 3925 deletions
diff --git a/engine/HoF_room_pc.asm b/engine/HoF_room_pc.asm index 7e08631c..c070e8c8 100755 --- a/engine/HoF_room_pc.asm +++ b/engine/HoF_room_pc.asm @@ -1,140 +1,130 @@ HallOfFamePC: - callba AnimateHallOfFame + callab FallingStarEnd call ClearScreen ld c, 100 call DelayFrames + call DisableLCD - ld hl, vFont - ld bc, $800 / 2 - call ZeroMemory - ld hl, vChars2 + $600 - ld bc, $200 / 2 - call ZeroMemory - ld hl, vChars2 + $7e0 - ld bc, $10 - ld a, $ff - call FillMemory + ld a, $a7 + ld [rWX], a + xor a + ld [rSCX], a + ld [rSCY], a + ld [hSCX], a + ld [hSCY], a + ld [hWY], a + ld [rWY], a + call CreditsLoadFont coord hl, 0, 0 call FillFourRowsWithBlack coord hl, 0, 14 call FillFourRowsWithBlack ld a, %11000000 ld [rBGP], a + call UpdateGBCPal_BGP call EnableLCD - ld a, $ff - call PlaySoundWaitForCurrent + call StopAllMusic + ld hl, vBGMap1 + call CreditsCopyTileMapToVRAM + ld hl, vBGMap0 + call CreditsCopyTileMapToVRAM ld c, BANK(Music_Credits) ld a, MUSIC_CREDITS call PlayMusic ld c, 128 call DelayFrames xor a - ld [wUnusedCD3D], a ; not read + ld [wHoFMonSpecies], a ld [wNumCreditsMonsDisplayed], a jp Credits FadeInCreditsText: + ld a, 1 + ld [H_AUTOBGTRANSFERENABLED], a ld hl, HoFGBPalettes ld b, 4 .loop ld a, [hli] ld [rBGP], a + call UpdateGBCPal_BGP ld c, 5 call DelayFrames dec b jr nz, .loop ret +HoFGBPalettes: + db %11000000 + db %11010000 + db %11100000 + db %11110000 + DisplayCreditsMon: + ld hl, vBGMap1 + call CreditsCopyTileMapToVRAM xor a ld [H_AUTOBGTRANSFERENABLED], a - call SaveScreenTilesToBuffer1 + ld hl, rLCDC + set 3, [hl] + call SaveScreenTilesToBuffer2 call FillMiddleOfScreenWithWhite - - ; display the next monster from CreditsMons - ld hl, wNumCreditsMonsDisplayed - ld c, [hl] ; how many monsters have we displayed so far? - inc [hl] - ld b, 0 - ld hl, CreditsMons - add hl, bc ; go that far in the list of monsters and get the next one - ld a, [hl] - ld [wcf91], a - ld [wd0b5], a - coord hl, 8, 6 - call GetMonHeader - call LoadFrontSpriteByMonIndex - ld hl, vBGMap0 + $c + call GetNextCreditsMon + ld hl, vBGMap0 + 12 call CreditsCopyTileMapToVRAM xor a ld [H_AUTOBGTRANSFERENABLED], a - call LoadScreenTilesFromBuffer1 + call LoadScreenTilesFromBuffer2DisableBGTransfer ld hl, vBGMap0 call CreditsCopyTileMapToVRAM - ld a, $A7 - ld [rWX], a - ld hl, vBGMap1 - call CreditsCopyTileMapToVRAM - call FillMiddleOfScreenWithWhite ld a, %11111100 ; make the mon a black silhouette ld [rBGP], a - -; scroll the mon left by one tile 7 times - ld bc, 7 -.scrollLoop1 + call UpdateGBCPal_BGP + ld hl, rLCDC + res 3, [hl] + ld a, 1 + ld [H_AUTOBGTRANSFERENABLED], a + ld b, 0 + ld c, 10 call ScrollCreditsMonLeft - dec c - jr nz, .scrollLoop1 - -; scroll the mon left by one tile 20 times -; This time, we have to move the window left too in order to hide the text that -; is wrapping around to the right side of the screen. - ld c, 20 -.scrollLoop2 + call FillLeftHalfOfScreenWithWhite + ld c, 10 + call ScrollCreditsMonLeft + call FillRightHalfOfScreenWithWhite + ld c, 8 call ScrollCreditsMonLeft - ld a, [rWX] - sub 8 - ld [rWX], a - dec c - jr nz, .scrollLoop2 - - xor a - ld [hWY], a ld a, %11000000 ld [rBGP], a + call UpdateGBCPal_BGP + xor a + ld [hSCX], a ret -INCLUDE "data/credit_mons.asm" - ScrollCreditsMonLeft: - ld h, b - ld l, $20 - call ScrollCreditsMonLeft_SetSCX - ld h, $0 - ld l, $70 - call ScrollCreditsMonLeft_SetSCX ld a, b - add $8 + ld [hSCX], a + add 8 ld b, a + call DelayFrame + dec c + jr nz, ScrollCreditsMonLeft ret -ScrollCreditsMonLeft_SetSCX: - ld a, [rLY] - cp l - jr nz, ScrollCreditsMonLeft_SetSCX - ld a, h - ld [rSCX], a -.loop - ld a, [rLY] - cp h - jr z, .loop +GetNextCreditsMon: + ld hl, wNumCreditsMonsDisplayed + ld c, [hl] + inc [hl] + ld b, 0 + ld hl, CreditsMons + add hl, bc + ld a, [hl] + ld [wcf91], a + ld [wd0b5], a + coord hl, 8, 6 + call GetMonHeader + call LoadFrontSpriteByMonIndex ret -HoFGBPalettes: - db %11000000 - db %11010000 - db %11100000 - db %11110000 +INCLUDE "data/credit_mons.asm" CreditsCopyTileMapToVRAM: ld a, l @@ -145,6 +135,23 @@ CreditsCopyTileMapToVRAM: ld [H_AUTOBGTRANSFERENABLED], a jp Delay3 +CreditsLoadFont: + call LoadFontTilePatterns + ld hl, vChars1 + ld bc, $40 * $10 + call ZeroMemory + + call LoadTextBoxTilePatterns + ld hl, vChars2 + $60 * $10 + ld bc, $10 * $10 + call ZeroMemory + + ld hl, vChars2 + $7e * $10 + ld bc, $1 * $10 + ld a, $ff + call FillMemory + ret + ZeroMemory: ; zero bc bytes at hl ld [hl], 0 @@ -167,7 +174,40 @@ FillMiddleOfScreenWithWhite: ld a, " " jp FillMemory -Credits: +FillLeftHalfOfScreenWithWhite: + coord hl, 0, 4 + push bc + call FillHalfOfScreenWithWhite + pop bc + ret + +FillRightHalfOfScreenWithWhite: + coord hl, 10, 4 + push bc + call FillHalfOfScreenWithWhite + pop bc + ret + +FillHalfOfScreenWithWhite: + ld b, 10 + ld c, 10 + ld a, " " +.loop + push bc + push hl +.innerLoop + ld [hli], a + dec c + jr nz, .innerLoop + pop hl + ld bc, SCREEN_WIDTH + add hl, bc + pop bc + dec b + jr nz, .loop + ret + +Credits: ; Roll credits ld de, CreditsOrder push de .nextCreditsScreen @@ -192,58 +232,48 @@ Credits: jr z, .showCopyrightText cp $fa jr z, .showTheEnd - push hl - push hl - ld hl, CreditsTextPointers - add a - ld c, a - ld b, 0 - add hl, bc - ld e, [hl] - inc hl - ld d, [hl] - ld a, [de] - inc de - ld c, a - ld b, $ff - pop hl - add hl, bc - call PlaceString - pop hl - ld bc, SCREEN_WIDTH * 2 - add hl, bc + call PlaceCreditsText + pop de + jr .nextCreditsCommand + +.showCopyrightText + callba LoadCopyrightTiles pop de jr .nextCreditsCommand + + .fadeInTextAndShowMon call FadeInCreditsText - ld c, 90 + ld c, 102 jr .next1 + .showTextAndShowMon - ld c, 110 + ld c, 122 .next1 call DelayFrames call DisplayCreditsMon jr .nextCreditsScreen + .fadeInText call FadeInCreditsText - ld c, 120 + ld c, 132 jr .next2 + .showText - ld c, 140 + ld c, 152 .next2 call DelayFrames jr .nextCreditsScreen -.showCopyrightText - push de - callba LoadCopyrightTiles - pop de - pop de - jr .nextCreditsCommand + .showTheEnd - ld c, 16 + call ShowTheEndGFX + pop de + ret + +ShowTheEndGFX: + ld c, 24 call DelayFrames call FillMiddleOfScreenWithWhite - pop de ld de, TheEndGfx ld hl, vChars2 + $600 lb bc, BANK(TheEndGfx), (TheEndGfxEnd - TheEndGfx) / $10 @@ -258,8 +288,31 @@ Credits: TheEndTextString: ; "T H E E N D" - db $60," ",$62," ",$64," ",$64," ",$66," ",$68,"@" - db $61," ",$63," ",$65," ",$65," ",$67," ",$69,"@" + db $60, " ", $62, " ", $64, " ", $64, " ", $66, " ", $68, "@" + db $61, " ", $63, " ", $65, " ", $65, " ", $67, " ", $69, "@" + +PlaceCreditsText: + push hl + push hl + ld hl, CreditsTextPointers + ld c, a + ld b, 0 + add hl, bc + add hl, bc + ld e, [hl] + inc hl + ld d, [hl] + pop hl + ld a, [de] + inc de + ld c, a + ld b, $ff + add hl, bc + call PlaceString + pop hl + ld bc, SCREEN_WIDTH * 2 + add hl, bc + ret INCLUDE "data/credits_order.asm" diff --git a/engine/add_mon.asm b/engine/add_mon.asm index b2feeb12..40b776d4 100644 --- a/engine/add_mon.asm +++ b/engine/add_mon.asm @@ -170,6 +170,12 @@ _AddPartyMon: inc de ld a, [hli] ; catch rate (held item in gen 2) ld [de], a + ld a, [wcf91] + cp KADABRA + jr nz, .skipGivingTwistedSpoon + ld a, $60 ; twistedspoon in gen 2 + ld [de], a +.skipGivingTwistedSpoon ld hl, wMonHMoves ld a, [hli] inc de diff --git a/engine/animated_objects_3e.asm b/engine/animated_objects_3e.asm new file mode 100755 index 00000000..2373e19e --- /dev/null +++ b/engine/animated_objects_3e.asm @@ -0,0 +1,394 @@ +ClearObjectAnimationBuffers: + ld hl, wAnimatedObjectsData + ld bc, wAnimatedObjectsDataEnd - wAnimatedObjectsData + xor a + call FillMemory + ret + +RunObjectAnimations: + ld hl, wAnimatedObjectDataStructs + ld e, 10 +.loop + ld a, [hl] + and a + jr z, .next + ld c, l + ld b, h + push hl + push de + call ExecuteCurrentAnimatedObjectCallback + call UpdateCurrentAnimatedObjectFrame + pop de + pop hl + jr c, .quit +.next + ld bc, $10 + add hl, bc + dec e + jr nz, .loop + ld a, [wCurrentAnimatedObjectOAMBufferOffset] + ld l, a + ld h, wOAMBuffer / $100 +.deinit_unused_oam_loop + ld a, l + cp wOAMBufferEnd % $100 + jr nc, .quit + xor a + ld [hli], a + jr .deinit_unused_oam_loop + +.quit + ret + +SpawnAnimatedObject: + push de + push af + ld hl, wAnimatedObjectDataStructs + ld e, 10 +.loop + ld a, [hl] + and a + jr z, .init + ld bc, $10 + add hl, bc + dec e + jr nz, .loop + pop af + pop de + scf + ret + +.init + pop af + ld c, l + ld b, h + ld hl, wNumLoadedAnimatedObjects + inc [hl] + ld e, a + ld d, $0 + ld a, [wAnimatedObjectSpawnStateDataPointer] + ld l, a + ld a, [wAnimatedObjectSpawnStateDataPointer + 1] + ld h, a + add hl, de + add hl, de + add hl, de + ld e, l + ld d, h + ld hl, $0 + add hl, bc + ld a, [wNumLoadedAnimatedObjects] + ld [hli], a + ld a, [de] + ld [hli], a + inc de + ld a, [de] + ld [hli], a + inc de + xor a + ld [hli], a + pop de + ld hl, $4 + add hl, bc + ld a, e + ld [hli], a + ld a, d + ld [hli], a + xor a + ld [hli], a + ld [hli], a + xor a + ld [hli], a + ld [hli], a + dec a + ld [hli], a + xor a + ld [hli], a + ld [hli], a + ld [hli], a + ld [hli], a + ld [hl], a + ret + +MaskCurrentAnimatedObjectStruct: + ld hl, $0 + add hl, bc + ld [hl], $0 + ret + +MaskAllAnimatedObjectStructs: + ld hl, wAnimatedObjectDataStructs + ld e, 10 +.loop + ld [hl], $0 + ld bc, $10 + add hl, bc + dec e + jr nz, .loop + ret + +UpdateCurrentAnimatedObjectFrame: + xor a + ld [wCurAnimatedObjectOAMAttributes], a + ld hl, $3 + add hl, bc + ld a, [hli] + ld [wCurrentAnimatedObjectVTileOffset], a + ld a, [hli] + ld [wCurrentAnimatedObjectXCoord], a + ld a, [hli] + ld [wCurrentAnimatedObjectYCoord], a + ld a, [hli] + ld [wCurrentAnimatedObjectXOffset], a + ld a, [hl] + ld [wCurrentAnimatedObjectYOffset], a + call UpdateDurationTimerAndFrameStateForCurrentAnimatedObject + cp $fd + jr z, .finish + cp $fc + jr z, .delete_animation + call GetCurrentAnimatedObjectOAMDataPointer + ld a, [wCurrentAnimatedObjectVTileOffset] + add [hl] + ld [wCurrentAnimatedObjectVTileOffset], a + inc hl + ld a, [hli] + ld h, [hl] + ld l, a + push bc + ld a, [wCurrentAnimatedObjectOAMBufferOffset] + ld e, a + ld d, wOAMBuffer / $100 + ld a, [hli] + ld c, a +.loop + ld a, [wCurrentAnimatedObjectYCoord] + ld b, a + ld a, [wCurrentAnimatedObjectYOffset] + add b + ld b, a + ld a, [wAnimatedObjectGlobalYOffset] + add b + ld b, a + call GetCurrentAnimatedObjectTileYCoordinate + add b + ld [de], a + inc hl + inc de + ld a, [wCurrentAnimatedObjectXCoord] + ld b, a + ld a, [wCurrentAnimatedObjectXOffset] + add b + ld b, a + ld a, [wAnimatedObjectGlobalXOffset] + add b + ld b, a + call GetCurrentAnimatedObjectTileXCoordinate + add b + ld [de], a + inc hl + inc de + ld a, [wCurrentAnimatedObjectVTileOffset] + add [hl] + ld [de], a + inc hl + inc de + call SetCurrentAnimatedObjectOAMAttributes + ld b, a + ld a, [wc634] + cp $7 + ld a, b + jr z, .skip_load + ld [de], a +.skip_load + inc hl + inc de + ld a, e + ld [wCurrentAnimatedObjectOAMBufferOffset], a + cp wOAMBufferEnd % $100 + jr nc, .oam_is_full + dec c + jr nz, .loop + pop bc + jr .finish + +.delete_animation + call MaskCurrentAnimatedObjectStruct +.finish + and a + ret + +.oam_is_full + pop bc + scf + ret + +GetCurrentAnimatedObjectTileYCoordinate: + push hl + ld a, [hl] + ld hl, wCurAnimatedObjectOAMAttributes + bit 6, [hl] + jr z, .no_flip + add $8 + xor $ff + inc a +.no_flip + pop hl + ret + +GetCurrentAnimatedObjectTileXCoordinate: + push hl + ld a, [hl] + ld hl, wCurAnimatedObjectOAMAttributes + bit 5, [hl] + jr z, .no_flip + add $8 + xor $ff + inc a +.no_flip + pop hl + ret + +SetCurrentAnimatedObjectOAMAttributes: + ld a, [wCurAnimatedObjectOAMAttributes] + ld b, a + ld a, [hl] + xor b + and $e0 + ld b, a + ld a, [hl] + and $10 + or b + bit 4, a + ret z + or $4 + ret + +GetCurrentAnimatedObjectOAMDataPointer: + ld e, a + ld d, $0 + ld a, [wAnimatedObjectOAMDataPointer] + ld l, a + ld a, [wAnimatedObjectOAMDataPointer + 1] + ld h, a + add hl, de + add hl, de + add hl, de + ret + +SetCurrentAnimatedObjectCallbackAndResetFrameStateRegisters: + ld hl, $1 + add hl, bc + ld [hl], a + ld hl, $8 + add hl, bc + ld [hl], $0 + ld hl, $9 + add hl, bc + ld [hl], $0 + ld hl, $a + add hl, bc + ld [hl], $ff + ret + +UpdateDurationTimerAndFrameStateForCurrentAnimatedObject: +.loop + ld hl, $8 + add hl, bc + ld a, [hl] + and a + jr z, .next_frame + dec [hl] + call GetPointerToCurrentAnimatedObjectFrameScript + ld a, [hli] + push af + jr .finish + +.next_frame + ld hl, $a + add hl, bc + inc [hl] + call GetPointerToCurrentAnimatedObjectFrameScript + ld a, [hli] + cp $fe + jr z, .restart_anim + cp $ff + jr z, .hold_last_frame_state + push af + ld a, [hl] + push hl + and $3f + ld hl, $9 + add hl, bc + add [hl] + ld hl, $8 + add hl, bc + ld [hl], a + pop hl +.finish + ld a, [hl] + and $c0 + srl a + ld [wCurAnimatedObjectOAMAttributes], a + pop af + ret + +.hold_last_frame_state + xor a + ld hl, $8 + add hl, bc + ld [hl], a + ld hl, $a + add hl, bc + dec [hl] + dec [hl] + jr .loop + +.restart_anim + xor a + ld hl, $8 + add hl, bc + ld [hl], a + dec a + ld hl, $a + add hl, bc + ld [hl], a + jr .loop + +GetPointerToCurrentAnimatedObjectFrameScript: + ld hl, $1 + add hl, bc + ld e, [hl] + ld d, $0 + ld a, [wAnimatedObjectFramesDataPointer] + ld l, a + ld a, [wAnimatedObjectFramesDataPointer + 1] + ld h, a + add hl, de + add hl, de + ld e, [hl] + inc hl + ld d, [hl] + ld hl, $a + add hl, bc + ld l, [hl] + ld h, $0 + add hl, hl + add hl, de + ret + +ExecuteCurrentAnimatedObjectCallback: + ld hl, $2 + add hl, bc + ld e, [hl] + ld d, $0 + ld a, [wAnimatedObjectJumptablePointer] + ld l, a + ld a, [wAnimatedObjectJumptablePointer + 1] + ld h, a + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + jp hl diff --git a/engine/bank30.bin b/engine/bank30.bin Binary files differnew file mode 100644 index 00000000..6309c149 --- /dev/null +++ b/engine/bank30.bin diff --git a/engine/bank3c.asm b/engine/bank3c.asm new file mode 100644 index 00000000..9c0e281f --- /dev/null +++ b/engine/bank3c.asm @@ -0,0 +1,189 @@ +INCLUDE "engine/pikachu_pcm.asm" +INCLUDE "engine/overworld/advance_player_sprite.asm" + +INCLUDE "engine/black_out.asm" + +SetMapSpecificScriptFlagsOnMapReload: + ld a, [wCurMap] + cp VERMILION_GYM ; ??? new thing about verm gym? + jr z, .verm_gym + ld c, a + ld hl, .MapList +.search_loop + ld a, [hli] + cp c + jr z, .in_list + cp a, $ff + jr nz, .search_loop + ret + +.verm_gym + ld hl, wCurrentMapScriptFlags + set 6, [hl] + ret + +.in_list + ld hl, wCurrentMapScriptFlags + set 5, [hl] + ret + +.MapList + db SILPH_CO_2F + db SILPH_CO_3F + db SILPH_CO_4F + db SILPH_CO_5F + db SILPH_CO_6F + db SILPH_CO_7F + db SILPH_CO_8F + db SILPH_CO_9F + db SILPH_CO_10F + db SILPH_CO_11F + db POKEMON_MANSION_2F + db POKEMON_MANSION_3F + db POKEMON_MANSION_B1F + db POKEMON_MANSION_1F + db CINNABAR_GYM + db GAME_CORNER + db ROCKET_HIDEOUT_B1F + db ROCKET_HIDEOUT_B4F + db VICTORY_ROAD_3F + db VICTORY_ROAD_1F + db VICTORY_ROAD_2F + db LANCES_ROOM + db LORELEIS_ROOM + db BRUNOS_ROOM + db AGATHAS_ROOM + db $ff + +BeachHouse_GFX: + INCBIN "gfx/tilesets/beachhouse.2bpp" + ds 384 + +BeachHouse_Block: + INCBIN "gfx/blocksets/beachhouse.bst" + +Func_f0a54: + ret + +LoadUnusedBluesHouseMissableObjectData: +; referenced in an unused function + ld hl, .MissableObjectsMaps +.loop + ld a, [hli] + cp a, $ff + ret z + ld b, a + ld a, [wCurMap] + cp b + jr z, .found + inc hl + inc hl + inc hl + jr .loop + +.found + ld a, [hli] + ld c, a + ld b, 0 + ld a, [hli] + ld h, [hl] + ld l, a + ld de, wMissableObjectList + call CopyData + ret + +.MissableObjectsMaps: + dbbw BLUES_HOUSE, .End - .Start, .Start + db $ff + +.Start: + db 1, HS_DAISY_SITTING_COPY + db 2, HS_DAISY_WALKING_COPY + db 3, HS_TOWN_MAP_COPY + db $ff +.End: + +TryApplyPikachuMovementData: + ld a, [wd472] + bit 7, a + ret z + ld a, [wWalkBikeSurfState] + and a + ret nz + push hl + push bc + callab GetPikachuFacingDirectionAndReturnToE + pop bc + pop hl + ld a, b + cp e + ret nz + push hl + ld a, [wUpdateSpritesEnabled] + push af + ld a, $ff + ld [wUpdateSpritesEnabled], a + callab LoadPikachuShadowIntoVRAM + pop af + ld [wUpdateSpritesEnabled], a + pop hl + call ApplyPikachuMovementData + callab RefreshPikachuFollow + ret + +Pic_f0abf: +INCBIN "gfx/pikachu/unknown_f0abf.pic" +GFX_f0b64: +INCBIN "gfx/pikachu/unknown_f0b64.2bpp" +Pic_f0cf4: +INCBIN "gfx/pikachu/unknown_f0cf4.pic" +GFX_f0d82: +INCBIN "gfx/pikachu/unknown_f0d82.2bpp" + +PokecenterChanseyText: + ld hl, NurseChanseyText + call PrintText + ld a, CHANSEY + call PlayCry + call WaitForSoundToFinish + ret + +NurseChanseyText: + TX_FAR _NurseChanseyText + db "@" + +INCLUDE "engine/HoF_room_pc.asm" +INCLUDE "scripts/ViridianCity2.asm" +INCLUDE "scripts/VermilionCity2.asm" +INCLUDE "scripts/CeladonCity2.asm" +INCLUDE "scripts/Route1_2.asm" +INCLUDE "scripts/Route22_2.asm" +INCLUDE "scripts/RedsHouse1F2.asm" +INCLUDE "scripts/OaksLab2.asm" +INCLUDE "scripts/ViridianSchoolHouse2.asm" +INCLUDE "scripts/Museum1F2.asm" +INCLUDE "scripts/PewterPokecenter2.asm" +INCLUDE "scripts/PokemonTower2F_2.asm" +INCLUDE "scripts/CeladonMart3F_2.asm" +INCLUDE "scripts/CeladonMansion1F_2.asm" +INCLUDE "scripts/CeladonMansion3F_2.asm" +INCLUDE "scripts/GameCorner2.asm" +INCLUDE "scripts/CeladonDiner2.asm" +INCLUDE "scripts/SafariZoneGate2.asm" +INCLUDE "scripts/CinnabarGym3.asm" +INCLUDE "scripts/MtMoonPokecenter2.asm" + +INCLUDE "data/mapHeaders/BeachHouse.asm" +INCLUDE "scripts/BeachHouse.asm" +BeachHouse_Blocks: +INCBIN "maps/BeachHouse.blk" +INCLUDE "data/mapObjects/BeachHouse.asm" + +INCLUDE "scripts/BeachHouse2.asm" +INCLUDE "scripts/BillsHouse2.asm" +INCLUDE "scripts/ViridianForest2.asm" +INCLUDE "scripts/SSAnne2FRooms_2.asm" +INCLUDE "scripts/SilphCo11F_2.asm" + +INCLUDE "engine/overworld/hidden_objects.asm" +INCLUDE "engine/vermilion_gym_trash_cans.asm" diff --git a/engine/bank3d.asm b/engine/bank3d.asm new file mode 100644 index 00000000..0cfdea08 --- /dev/null +++ b/engine/bank3d.asm @@ -0,0 +1,495 @@ +INCLUDE "engine/battle/common_text.asm" +INCLUDE "engine/battle/link_battle_versus_text.asm" +INCLUDE "engine/battle/unused_stats_functions.asm" +INCLUDE "engine/battle/scroll_draw_trainer_pic.asm" + +StarterPikachuBattleEntranceAnimation: + coord hl, 0, 5 + ld c, 0 +.loop1 + inc c + ld a, c + cp 9 + ret z + ld d, 7 * 13 + push bc + push hl +.loop2 + call .PlaceColumn + dec hl + ld a, d + sub 7 + ld d, a + dec c + jr nz, .loop2 + ld c, 2 + call DelayFrames + pop hl + pop bc + inc hl + jr .loop1 + +.PlaceColumn: + push hl + push de + push bc + ld e, 7 +.loop3 + ld a, d + cp 7 * 7 + jr nc, .okay + ld a, $7f +.okay + ld [hl], a + ld bc, SCREEN_WIDTH + add hl, bc + inc d + dec e + jr nz, .loop3 + pop bc + pop de + pop hl + ret + +INCLUDE "engine/battle/decrement_pp.asm" + +ModifyPikachuHappiness:: + ld a, d + cp PIKAHAPPY_GYMLEADER + jr z, .checkanywhereinparty + cp PIKAHAPPY_WALKING + jr z, .checkanywhereinparty + push de + callab IsThisPartymonStarterPikachu_Party + pop de + ret nc + jr .proceed + +.checkanywhereinparty + push de + callab IsStarterPikachuInOurParty + pop de + ret nc + +.proceed + push de + ; Divide [wPikachuHappiness] by 100. Hold the integer part in e. + ld e, $0 + ld a, [wPikachuHappiness] + cp 100 + jr c, .wPikachuHappiness_div_100 + inc e + cp 200 + jr c, .wPikachuHappiness_div_100 + inc e +.wPikachuHappiness_div_100 + ; Get the (d, e) entry from HappinessChangeTable. + ld c, d + dec c + ld b, $0 + ld hl, HappinessChangeTable + add hl, bc + add hl, bc + add hl, bc + ld d, $0 + add hl, de + ld a, [hl] + ; If [hl] is positive, take min(0xff, [hl] + [wPikachuHappiness]). + ; If [hl] is negative, take max(0x00, [hl] + [wPikachuHappiness]). + ; Inexplicably, we're using 100 as the threshold for comparison. + cp 100 + ld a, [wPikachuHappiness] + jr nc, .negative + add [hl] + jr nc, .okay + ld a, -1 + jr .okay + +.negative + add [hl] + jr c, .okay + xor a +.okay + ld [wPikachuHappiness], a + + ; Restore d and get the d'th entry in PikachuMoods. + pop de + dec d + ld hl, PikachuMoods + ld e, d + ld d, $0 + add hl, de + ld a, [hl] + ld b, a + ; Modify Pikachu's mood + cp $80 + jr z, .done + ld a, [wPikachuMood] + jr c, .decreased + cp b + jr nc, .done + ld a, [wd49c] + and a + jr nz, .done + jr .update_mood + +.decreased + cp b + jr c, .done +.update_mood + ld a, b + ld [wPikachuMood], a +.done + ret + +HappinessChangeTable: + ; Increase + db 5, 3, 2 ; Gained a level + db 5, 3, 2 ; HP restore + db 1, 1, 0 ; Used X item + db 3, 2, 1 ; Challenged Gym Leader + db 1, 1, 0 ; Teach TM/HM + db 2, 1, 1 ; Walking around + ; Decrease + db -3, -3, -5 ; Deposited + db -1, -1, -1 ; Fainted in battle + db -5, -5, -10 ; Fainted due to Poison outside of battle + db -5, -5, -10 ; Unknown (d = 10) + db -10, -10, -20 ; Unknown (d = 11) + +PikachuMoods: + ; Increase + db $8a ; Gained a level + db $83 ; HP restore + db $80 ; Teach TM/HM + db $80 ; Challenged Gym Leader + db $94 ; Unknown (d = 5) + db $80 ; Unknown (d = 6) + ; Decrease + db $62 ; Deposited + db $6c ; Fainted + db $62 ; Unknown (d = 9) + db $6c ; Unknown (d = 10) + db $00 ; Unknown (d = 11) + +RedPicBack: INCBIN "pic/trainer/redb.pic" +OldManPic: INCBIN "pic/trainer/oldman.pic" +ProfOakPicBack: INCBIN "pic/ytrainer/prof.oakb.pic" + +LoadYellowTitleScreenGFX: + ld hl, PokemonLogoGraphics + ld de, vChars2 + ld bc, 115 * $10 + ld a, BANK(PokemonLogoGraphics) ; redundant because this function is in bank3d + call FarCopyData + ld hl, YellowLogoGraphics + 35 * $10 + ld de, vChars0 + 253 * $10 + ld bc, 3 * $10 + ld a, BANK(YellowLogoGraphics) + call FarCopyData + ld hl, YellowLogoGraphics + 38 * $10 + ld de, vChars1 + ld bc, 64 * $10 + ld a, BANK(YellowLogoGraphics) + call FarCopyData + ld hl, YellowLogoGraphics + 102 * $10 + ld de, vChars0 + 240 * $10 + ld bc, 12 * $10 + ld a, BANK(YellowLogoGraphics) + call FarCopyData + ret + +TitleScreen_PlacePokemonLogo: + coord hl, 2, 1 + ld de, TitleScreenPokemonLogoTilemap + lb bc, 7, 16 + call Bank3D_CopyBox + ret + +TitleScreen_PlacePikaSpeechBubble: + coord hl, 6, 4 + ld de, TitleScreenPikaBubbleTilemap + lb bc, 4, 7 + call Bank3D_CopyBox + coord hl, 9, 8 + ld [hl], $64 + inc hl + ld [hl], $65 + ret + +TitleScreen_PlacePikachu: + coord hl, 4, 8 + ld de, TitleScreenPikachuTilemap + lb bc, 9, 12 + call Bank3D_CopyBox + coord hl, 16, 10 + ld [hl], $96 + coord hl, 16, 11 + ld [hl], $9d + coord hl, 16, 12 + ld [hl], $a7 + coord hl, 16, 13 + ld [hl], $b1 + ld hl, TitleScreenPikachuEyesOAMData + ld de, wOAMBuffer + ld bc, $20 + call CopyData + ret + +TitleScreenPikachuEyesOAMData: + db $60, $40, $f1, $22 + db $60, $48, $f0, $22 + db $68, $40, $f3, $22 + db $68, $48, $f2, $22 + db $60, $60, $f0, $02 + db $60, $68, $f1, $02 + db $68, $60, $f2, $02 + db $68, $68, $f3, $02 + +Bank3D_CopyBox: +; copy cxb (xy) screen area from de to hl +.row + push bc + push hl +.col + ld a, [de] + inc de + ld [hli], a + dec c + jr nz, .col + pop hl + ld bc, SCREEN_WIDTH + add hl, bc + pop bc + dec b + jr nz, .row + ret + +TitleScreenPokemonLogoTilemap: +; 16x7 (xy) + db $f4, $f4, $f4, $f4, $f4, $f4, $49, $f4, $72, $30, $f4, $f4, $f4, $f4, $f4, $f4 + db $fd, $01, $02, $03, $04, $05, $06, $07, $08, $09, $0a, $0b, $f4, $0d, $0e, $0f + db $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $1a, $1b, $1c, $1d, $1e, $1f + db $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $2a, $2b, $2c, $2d, $2e, $2f + db $f4, $31, $32, $33, $34, $35, $36, $37, $38, $39, $3a, $3b, $3c, $3d, $3e, $3f + db $f4, $41, $42, $43, $44, $45, $46, $47, $48, $f4, $4a, $4b, $4c, $4d, $4e, $4f + db $f4, $6a, $6b, $6c, $6d, $f4, $f4, $f4, $f4, $f4, $f4, $6e, $6f, $70, $71, $f4 + +Pointer_f4669: +; Unreferenced + db $47, $48, $49, $4a, $4b, $4c, $4d, $4e, $4f, $5f + +TitleScreenPikaBubbleTilemap: +; 7x4 (xy) + db $24, $25, $66, $67, $68, $69, $2a + db $50, $51, $52, $53, $54, $55, $56 + db $57, $58, $59, $5a, $5b, $5c, $5d + db $6d, $5e, $5f, $60, $61, $62, $63 + +TitleScreenPikachuTilemap: +; 12x9 (xy) + db $80, $81, $82, $83, $00, $00, $00, $00, $84, $85, $86, $87 + db $88, $89, $8a, $8b, $8c, $8d, $8d, $8e, $8f, $8a, $90, $91 + db $00, $92, $93, $8a, $8a, $8a, $8a, $8a, $8a, $94, $95, $00 + db $00, $00, $97, $8a, $8a, $98, $99, $8a, $8a, $9a, $9b, $9c + db $00, $00, $9e, $9f, $a0, $a1, $a2, $a3, $a4, $a5, $a6, $8a + db $00, $a8, $a9, $aa, $8a, $ab, $ac, $8a, $ad, $ae, $af, $b0 + db $00, $b2, $b3, $b4, $8a, $8a, $8a, $8a, $b5, $b6, $b7, $b8 + db $00, $b9, $ba, $8a, $8a, $8a, $8a, $8a, $8a, $bb, $bc, $00 + db $00, $00, $bd, $8a, $8a, $8a, $8a, $8a, $8a, $be, $bf, $00 + +PokemonLogoGraphics: INCBIN "gfx/pokemon_logo.2bpp" +PokemonLogoGraphicsEnd: +YellowLogoGraphics: INCBIN "gfx/yellow_titlescreen.2bpp" +YellowLogoGraphicsEnd: + +INCLUDE "engine/menu/link_menu.asm" + +HandleMenuInputDouble: + xor a + ld [wPartyMenuAnimMonEnabled], a + +HandleMenuInputPokemonSelectionDouble: + ld a, [H_DOWNARROWBLINKCNT1] + push af + ld a, [H_DOWNARROWBLINKCNT2] + push af ; save existing values on stack + xor a + ld [H_DOWNARROWBLINKCNT1], a ; blinking down arrow timing value 1 + ld a, $06 + ld [H_DOWNARROWBLINKCNT2], a ; blinking down arrow timing value 2 +.loop1 + xor a + ld [wAnimCounter], a ; counter for pokemon shaking animation + call .UpdateCursorTile + call JoypadLowSensitivity + ld a, [hJoy5] + and a ; was a key pressed? + jr nz, .keyPressed + pop af + ld [H_DOWNARROWBLINKCNT2], a + pop af + ld [H_DOWNARROWBLINKCNT1], a ; restore previous values + xor a + ld [wMenuWrappingEnabled], a ; disable menu wrapping + ret +.keyPressed + xor a + ld [wCheckFor180DegreeTurn], a + ld a, [hJoy5] + ld b, a + bit 6, a ; pressed Up key? + jr z, .checkIfDownPressed +.upPressed + ld a, [wCurrentMenuItem] ; selected menu item + and a ; already at the top of the menu? + jr z, .checkOtherKeys +.notAtTop + dec a + ld [wCurrentMenuItem], a ; move selected menu item up one space + jr .checkOtherKeys +.checkIfDownPressed + bit 7, a + jr z, .checkOtherKeys +.downPressed + ld a, [wCurrentMenuItem] + inc a + ld c, a + ld a, [wMaxMenuItem] + cp c + jr c, .checkOtherKeys + ld a, c + ld [wCurrentMenuItem], a +.checkOtherKeys + ld a, [wMenuWatchedKeys] + and b ; does the menu care about any of the pressed keys? + jp z, .loop1 +.checkIfAButtonOrBButtonPressed + ld a, [hJoy5] + and A_BUTTON | B_BUTTON + jr z, .skipPlayingSound +.AButtonOrBButtonPressed + ld a, SFX_PRESS_AB + call PlaySound ; play sound +.skipPlayingSound + pop af + ld [H_DOWNARROWBLINKCNT2], a + pop af + ld [H_DOWNARROWBLINKCNT1], a ; restore previous values + ld a, [hJoy5] + ret + +.UpdateCursorTile: + ld a, [wTopMenuItemY] + and a + jr z, .asm_f5ac0 + coord hl, 0, 0 + ld bc, SCREEN_WIDTH +.loop + add hl, bc + dec a + jr nz, .loop +.asm_f5ac0 + ld a, [wTopMenuItemX] + ld b, $0 + ld c, a + add hl, bc + push hl + ld a, [wLastMenuItem] + and a + jr z, .asm_f5ad5 + ld bc, $28 +.loop2 + add hl, bc + dec a + jr nz, .loop2 +.asm_f5ad5 + ld a, [hl] + cp "▶" + jr nz, .asm_f5ade + ld a, [wTileBehindCursor] + ld [hl], a +.asm_f5ade + pop hl + ld a, [wCurrentMenuItem] + and a + jr z, .asm_f5aec + ld bc, $28 +.loop3 + add hl, bc + dec a + jr nz, .loop3 +.asm_f5aec + ld a, [hl] + cp "▶" + jr z, .asm_f5af4 + ld [wTileBehindCursor], a +.asm_f5af4 + ld a, "▶" + ld [hl], a + ld a, l + ld [wMenuCursorLocation], a + ld a, h + ld [wMenuCursorLocation + 1], a + ld a, [wCurrentMenuItem] + ld [wLastMenuItem], a + ret + +INCLUDE "engine/overworld/field_move_messages.asm" + +INCLUDE "engine/items/inventory.asm" + +TrainerInfoTextBoxTileGraphics: INCBIN "gfx/trainer_info.2bpp" +TrainerInfoTextBoxTileGraphicsEnd: +BlankLeaderNames: INCBIN "gfx/blank_leader_names.2bpp" +CircleTile: INCBIN "gfx/circle_tile.2bpp" +BadgeNumbersTileGraphics: INCBIN "gfx/badge_numbers.2bpp" + +ReadSuperRodData: + ld a, [wCurMap] + ld c, a + ld hl, FishingSlots +.loop + ld a, [hli] + cp $ff + jr z, .notfound + cp c + jr z, .found + ld de, $8 + add hl, de + jr .loop +.found + call GenerateRandomFishingEncounter + ret +.notfound + ld de, $0 + ret + +GenerateRandomFishingEncounter: + call Random + cp $66 + jr c, .asm_f5ed6 + inc hl + inc hl + cp $b2 + jr c, .asm_f5ed6 + inc hl + inc hl + cp $e5 + jr c, .asm_f5ed6 + inc hl + inc hl +.asm_f5ed6 + ld e, [hl] + inc hl + ld d, [hl] + ret + +INCLUDE "data/super_rod.asm" +INCLUDE "engine/battle/bank3d_battle.asm" +INCLUDE "engine/items/tm_prices.asm" +INCLUDE "engine/multiply_divide.asm" +INCLUDE "engine/give_pokemon.asm" +INCLUDE "engine/battle/get_trainer_name.asm" +INCLUDE "engine/random.asm" +INCLUDE "engine/predefs.asm" diff --git a/engine/bank3e.asm b/engine/bank3e.asm new file mode 100644 index 00000000..32f5ebfd --- /dev/null +++ b/engine/bank3e.asm @@ -0,0 +1,5 @@ +INCLUDE "engine/surfing_minigame.asm" +INCLUDE "engine/yellow_intro.asm" +INCLUDE "data/animated_objects_3e_2.asm" +YellowIntroGraphics: INCBIN "gfx/yellow_intro.2bpp" +INCLUDE "engine/animated_objects_3e.asm" diff --git a/engine/bank3f.asm b/engine/bank3f.asm new file mode 100644 index 00000000..23eadbb1 --- /dev/null +++ b/engine/bank3f.asm @@ -0,0 +1,23 @@ +INCLUDE "data/map_songs.asm" +INCLUDE "data/map_header_pointers.asm" +INCLUDE "data/map_header_banks.asm" +INCLUDE "engine/pikachu_follow.asm" +INCLUDE "engine/pikachu_status.asm" +INCLUDE "engine/pikachu_emotions.asm" +INCLUDE "engine/pikachu_movement.asm" +INCLUDE "engine/pikachu_pic_animation.asm" + +Func_fe66e: + ret + +OfficerJennySprite: INCBIN "gfx/sprites/officer_jenny.2bpp" +PikachuSprite: INCBIN "gfx/sprites/pikachu.2bpp" +SandshrewSprite: INCBIN "gfx/sprites/sandshrew.2bpp" +OddishSprite: INCBIN "gfx/sprites/oddish.2bpp" +BulbasaurSprite: INCBIN "gfx/sprites/bulbasaur.2bpp" +JigglypuffSprite: INCBIN "gfx/sprites/jigglypuff.2bpp" +Clefairy2Sprite: INCBIN "gfx/sprites/clefairy2.2bpp" +ChanseySprite: INCBIN "gfx/sprites/chansey.2bpp" +SurfingPikachuSprite: INCBIN "gfx/sprites/surfing_pikachu.2bpp" +JessieSprite: INCBIN "gfx/sprites/jessie.2bpp" +JamesSprite: INCBIN "gfx/sprites/james.2bpp" diff --git a/engine/battle/animations.asm b/engine/battle/animations.asm index 74e48535..de1e67b9 100755 --- a/engine/battle/animations.asm +++ b/engine/battle/animations.asm @@ -15,6 +15,8 @@ DrawFrameBlock: ld a, [wFBTileCounter] inc a ld [wFBTileCounter], a + ld a, $2 + ld [wdef5], a ld a, [wSubAnimTransform] dec a jr z, .flipHorizontalAndVertical ; 1 @@ -46,13 +48,22 @@ DrawFrameBlock: .finishCopying ; finish copying values to OAM (when [wSubAnimTransform] not 1 or 2) add [hl] ; X offset ld [de], a ; store X + cp 88 + jr c, .asm_78056 + ld a, [wdef5] + inc a + ld [wdef5], a +.asm_78056 inc hl inc de ld a, [hli] - add $31 ; base tile ID for battle animations + add a, $31 ; base tile ID for battle animations ld [de], a ; store tile ID inc de ld a, [hli] + ld b, a + ld a, [wdef5] + or b ld [de], a ; store flags inc de jp .nextTile @@ -71,10 +82,16 @@ DrawFrameBlock: ld a, 168 sub b ; flip X coordinate ld [de], a ; store X + cp 88 + jr c, .asm_78087 + ld a, [wdef5] + inc a + ld [wdef5], a +.asm_78087 inc hl inc de ld a, [hli] - add $31 ; base tile ID for battle animations + add a, $31 ; base tile ID for battle animations ld [de], a ; store tile ID inc de ; toggle horizontal and vertical flip @@ -82,15 +99,16 @@ DrawFrameBlock: and a ld b, OAM_VFLIP | OAM_HFLIP jr z, .storeFlags1 - cp OAM_HFLIP + cp a, OAM_HFLIP ld b, OAM_VFLIP jr z, .storeFlags1 - cp OAM_VFLIP + cp a, OAM_VFLIP ld b, OAM_HFLIP jr z, .storeFlags1 ld b, 0 .storeFlags1 - ld a, b + ld a, [wdef5] + or b ld [de], a inc de jp .nextTile @@ -107,6 +125,12 @@ DrawFrameBlock: ld a, 168 sub b ; flip X coordinate ld [de], a ; store X + cp 88 + jr c, .asm_780c8 + ld a, [wdef5] + inc a + ld [wdef5], a +.asm_780c8 inc hl inc de ld a, [hli] @@ -122,6 +146,9 @@ DrawFrameBlock: .disableHorizontalFlip res 5, a .storeFlags2 + ld b, a + ld a, [wdef5] + or b ld [de], a inc de .nextTile @@ -245,11 +272,13 @@ PlayAnimation: push af ld a, [wAnimPalette] ld [rOBP0], a + call UpdateGBCPal_OBP0 call LoadAnimationTileset call LoadSubanimation call PlaySubanimation pop af ld [rOBP0], a + call UpdateGBCPal_OBP0 .nextAnimationCommand pop hl jr .animationLoop @@ -367,12 +396,7 @@ AnimationTileset2: INCBIN "gfx/attack_anim_2.2bpp" SlotMachineTiles2: -IF DEF(_RED) - INCBIN "gfx/red/slotmachine2.2bpp" -ENDC -IF DEF(_BLUE) - INCBIN "gfx/blue/slotmachine2.2bpp" -ENDC + INCBIN "gfx/slotmachine2.2bpp" MoveAnimation: push hl @@ -537,6 +561,8 @@ SetAnimationPalette: ld [rOBP0], a ld a, $6c ld [rOBP1], a + call UpdateGBCPal_OBP0 + call UpdateGBCPal_OBP1 ret .notSGB ld a, $e4 @@ -544,6 +570,28 @@ SetAnimationPalette: ld [rOBP0], a ld a, $6c ld [rOBP1], a + call UpdateGBCPal_OBP0 + call UpdateGBCPal_OBP1 + ret + +Func_78e98: + call SaveScreenTilesToBuffer2 + xor a + ld [H_AUTOBGTRANSFERENABLED], a + call ClearScreen + ld h, vBGMap0 / $100 + call WriteLowerByteOfBGMapAndEnableBGTransfer + call Delay3 + xor a + ld [H_AUTOBGTRANSFERENABLED], a + call LoadScreenTilesFromBuffer2 + ld h, vBGMap1 / $100 + +WriteLowerByteOfBGMapAndEnableBGTransfer: + ld l, vBGMap0 & $ff + call BattleAnimCopyTileMapToVRAM + ld a, $1 + ld [H_AUTOBGTRANSFERENABLED], a ret PlaySubanimation: @@ -691,7 +739,7 @@ AnimationIdSpecialEffects: dw DoExplodeSpecialEffects db SPORE - dw AnimationFlashScreen + dw FlashScreenEveryFourFrameBlocks db EXPLOSION dw DoExplodeSpecialEffects @@ -733,6 +781,7 @@ DoBallTossSpecialEffects: ld a, [rOBP0] xor %00111100 ; complement colors 1 and 2 ld [rOBP0], a + call UpdateGBCPal_OBP0 .skipFlashingEffect ld a, [wSubAnimCounter] cp 11 ; is it the beginning of the subanimation? @@ -922,7 +971,7 @@ TradeShakePokeball: jp PlaySound BallMoveDistances1: - db -12,-12,-8 + db -12, -12, -8 db $ff ; terminator ; function to make the pokeball jump up @@ -963,7 +1012,7 @@ TradeJumpPokeball: jr .loop BallMoveDistances2: - db 11,12,-12,-7,7,12,-8,8 + db 11, 12, -12, -7, 7, 12, -8, 8 db $ff ; terminator ; this function copies the current musical note graphic @@ -1102,6 +1151,7 @@ AnimationFlashScreenLong: cp $01 ; is it the end of the palettes? jr z, .endOfPalettes ld [rBGP], a + call UpdateGBCPal_BGP call FlashScreenLongDelay jr .innerLoop .endOfPalettes @@ -1164,14 +1214,17 @@ AnimationFlashScreen: push af ; save initial palette ld a, %00011011 ; 0, 1, 2, 3 (inverted colors) ld [rBGP], a + call UpdateGBCPal_BGP ld c, 2 call DelayFrames xor a ; white out background ld [rBGP], a + call UpdateGBCPal_BGP ld c, 2 call DelayFrames pop af ld [rBGP], a ; restore initial palette + call UpdateGBCPal_BGP ret AnimationDarkScreenPalette: @@ -1217,6 +1270,7 @@ SetAnimationBGPalette: ld a, c .next ld [rBGP], a + call UpdateGBCPal_BGP ret ld b, $5 @@ -1261,15 +1315,30 @@ AnimationWaterDropletsEverywhere: _AnimationWaterDroplets: ld hl, wOAMBuffer .loop + ld a, $1 + ld [wdef5], a ld a, [wBaseCoordY] ld [hli], a ; Y + cp 40 + jr c, .asm_792d7 + ld a, [wdef5] + inc a + ld [wdef5], a +.asm_792d7 ld a, [wBaseCoordX] add 27 ld [wBaseCoordX], a ld [hli], a ; X + cp 88 + jr c, .asm_792ee + ld a, [wdef5] + add $2 + and $3 + ld [wdef5], a +.asm_792ee ld a, [wDropletTile] ld [hli], a ; tile - xor a + ld a, [wdef5] ld [hli], a ; attribute ld a, [wBaseCoordX] cp 144 @@ -1412,16 +1481,30 @@ BattleAnimWriteOAMEntry: ; Y coordinate = e (increased by 8 each call, before the write to OAM) ; X coordinate = [wBaseCoordX] ; tile = d -; attributes = 0 +; attributes = variable (dependant on coords) + ld a, $1 + ld [wdef5], a ld a, e add 8 ld e, a ld [hli], a + cp 40 + jr c, .asm_793d8 + ld a, [wdef5] + inc a + ld [wdef5], a +.asm_793d8 ld a, [wBaseCoordX] ld [hli], a + cp 88 + jr c, .asm_793e8 + ld a, [wdef5] + add $2 + ld [wdef5], a +.asm_793e8 ld a, d ld [hli], a - xor a + ld a, [wdef5] ld [hli], a ret @@ -1473,7 +1556,7 @@ AdjustOAMBlockYPos2: ret AnimationBlinkEnemyMon: -; Make the enemy mon's sprite blink on and off for a second or two + ; Make the enemy mon's sprite blink on and off for a second or two ld hl, AnimationBlinkMon jp CallWithTurnFlipped @@ -1626,6 +1709,8 @@ AnimationSpiralBallsInward: ld a, [hl] cp $ff jr z, .done + ld a, $2 + ld [wdef5], a ld a, [wSpiralBallsBaseY] add [hl] ld [de], a ; Y @@ -1634,9 +1719,20 @@ AnimationSpiralBallsInward: ld a, [wSpiralBallsBaseX] add [hl] ld [de], a ; X + cp 88 + jr c, .asm_79524 + ld a, $3 + ld [wdef5], a +.asm_79524 inc hl inc de inc de + ld a, [de] + and $f0 + ld b, a + ld a, [wdef5] + or b + ld [de], a inc de dec c jr nz, .innerLoop @@ -1938,7 +2034,7 @@ _AnimationSlideMonOff: jr nz, .slideLoop ret -; Since mon pic tile numbers go from top to bottom, left to right in order, +; Since mon pic tile numbers go from top to bottom, left to right in order, ; adding the height of the mon pic in tiles to a tile number gives the tile ; number of the tile one column to the right (and thus subtracting the height ; gives the reverse). If the next tile would be past the edge of the pic, the 2 @@ -1948,10 +2044,8 @@ _AnimationSlideMonOff: .PlayerNextTile ld a, [hl] add 7 -; This is a bug. The lower right corner tile of the mon back pic is blanked -; while the mon is sliding off the screen. It should compare with the max tile -; plus one instead. - cp $61 +; bugfix: compares against the max tile + 1 as opposed to the max tile + cp $62 ret c ld a, " " ret @@ -2088,18 +2182,24 @@ AnimationSubstitute: CopySlowbroSpriteData: ld bc, $0010 ld a, BANK(SlowbroSprite) - jp FarCopyData2 + jp FarCopyData HideSubstituteShowMonAnim: ld a, [H_WHOSETURN] and a ld hl, wPlayerMonMinimized + ld de, wPlayerBattleStatus1 + ld bc, wPlayerMoveNum ld a, [wPlayerBattleStatus2] jr z, .next1 ld hl, wEnemyMonMinimized + ld de, wEnemyBattleStatus1 + ld bc, wEnemyMoveNum ld a, [wEnemyBattleStatus2] .next1 push hl + push de + push bc ; if the substitute broke, slide it down, else slide it offscreen horizontally bit HAS_SUBSTITUTE_UP, a jr nz, .substituteStillUp @@ -2108,12 +2208,65 @@ HideSubstituteShowMonAnim: .substituteStillUp call AnimationSlideMonOff .next2 + pop bc + pop de + ld a, [de] + bit INVULNERABLE, a pop hl + jr nz, .invulnerable + ld a, [bc] + cp FLY + jr z, .flyOrDig + cp DIG + jr z, .flyOrDig +.invulnerable ld a, [hl] and a jp nz, AnimationMinimizeMon call AnimationFlashMonPic jp AnimationShowMonPic +.flyOrDig + ld a, [H_WHOSETURN] + and a + jr nz, .enemy + ld a, [wPlayerMonMinimized] + and a + jr nz, .monIsMinimized + ld a, [wBattleMonSpecies] + ld [wcf91], a + ld [wd0b5], a + call GetMonHeader + predef LoadMonBackPic + ret +.enemy + ld a, [wEnemyMonMinimized] + and a + jr nz, .monIsMinimized + ld a, [wEnemyMonSpecies] + ld [wcf91], a + ld [wd0b5], a + call GetMonHeader + ld de, vFrontPic + jp LoadMonFrontSprite +.monIsMinimized + ld hl, wTempPic + push hl + xor a + ld bc, 7 * 7 * $10 + call FillMemory + pop hl + ld de, $194 + add hl, de + ld de, MinimizedMonSprite + ld c, MinimizedMonSpriteEnd - MinimizedMonSprite +.loop + ld a, [de] + ld [hli], a + ld [hli], a + inc de + dec c + jr nz, .loop + jp CopyTempPicToMonPic ReshowSubstituteAnim: call AnimationSlideMonOff @@ -2181,6 +2334,23 @@ AnimationHideEnemyMonPic: ld [H_AUTOBGTRANSFERENABLED], a jp Delay3 +Func_79929: + ld hl, wPlayerMonMinimized + ld a, [H_WHOSETURN] + and a + jr z, .playerTurn + ld hl, wEnemyMonMinimized +.playerTurn + ld a, [hl] + and a + jr z, .notMinimized + call AnimationMinimizeMon + ret +.notMinimized + call AnimationFlashMonPic + call AnimationShowMonPic + ret + InitMultipleObjectsOAM: ; Writes c OAM entries with tile d. ; Sets their Y coordinates to sequential multiples of 8, starting from 0. @@ -2202,6 +2372,8 @@ InitMultipleObjectsOAM: jr nz, .loop ret + ret ; unreferenced + AnimationHideMonPic: ; Hides the mon's sprite. ld a, [H_WHOSETURN] @@ -2228,7 +2400,7 @@ ClearMonPicFromTileMap: ret ; puts the tile map destination address of a mon sprite in hl, given the row count in b -; The usual row count is 7, but it may be smaller when sliding a mon sprite in/out, +; The usual row count is 7, but it may be smaller when sliding a mon sprite in/out, ; in order to show only a portion of the mon sprite. GetMonSpriteTileMapPointerFromRowCount: push de @@ -2364,172 +2536,172 @@ IsCryMove: MoveSoundTable: ; ID, pitch mod, tempo mod - db SFX_POUND, $00,$80 ; POUND - db SFX_BATTLE_0C, $10,$80 ; KARATE_CHOP - db SFX_DOUBLESLAP, $00,$80 ; DOUBLESLAP - db SFX_BATTLE_0B, $01,$80 ; COMET_PUNCH - db SFX_BATTLE_0D, $00,$40 ; MEGA_PUNCH - db SFX_SILPH_SCOPE, $00,$ff ; PAY_DAY - db SFX_BATTLE_0D, $10,$60 ; FIRE_PUNCH - db SFX_BATTLE_0D, $20,$80 ; ICE_PUNCH - db SFX_BATTLE_0D, $00,$a0 ; THUNDERPUNCH - db SFX_DAMAGE, $00,$80 ; SCRATCH - db SFX_BATTLE_0F, $20,$40 ; VICEGRIP - db SFX_BATTLE_0F, $00,$80 ; GUILLOTINE - db SFX_BATTLE_0E, $00,$a0 ; RAZOR_WIND - db SFX_NOT_VERY_EFFECTIVE,$10,$c0 ; SWORDS_DANCE - db SFX_NOT_VERY_EFFECTIVE,$00,$a0 ; CUT - db SFX_BATTLE_12, $00,$c0 ; GUST - db SFX_BATTLE_12, $10,$a0 ; WING_ATTACK - db SFX_BATTLE_13, $00,$e0 ; WHIRLWIND - db SFX_NOT_VERY_EFFECTIVE,$20,$c0 ; FLY - db SFX_BATTLE_14, $00,$80 ; BIND - db SFX_BATTLE_22, $00,$80 ; SLAM - db SFX_VINE_WHIP, $01,$80 ; VINE_WHIP - db SFX_BATTLE_20, $00,$80 ; STOMP - db SFX_BATTLE_17, $f0,$40 ; DOUBLE_KICK - db SFX_SUPER_EFFECTIVE, $00,$80 ; MEGA_KICK - db SFX_BATTLE_17, $00,$80 ; JUMP_KICK - db SFX_BATTLE_21, $10,$80 ; ROLLING_KICK - db SFX_BATTLE_1B, $01,$a0 ; SAND_ATTACK - db SFX_BATTLE_18, $00,$80 ; HEADBUTT - db SFX_BATTLE_1E, $00,$60 ; HORN_ATTACK - db SFX_BATTLE_1E, $01,$40 ; FURY_ATTACK - db SFX_HORN_DRILL, $00,$a0 ; HORN_DRILL - db SFX_SUPER_EFFECTIVE, $10,$a0 ; TACKLE - db SFX_BATTLE_20, $00,$c0 ; BODY_SLAM - db SFX_BATTLE_14, $10,$60 ; WRAP - db SFX_SUPER_EFFECTIVE, $00,$a0 ; TAKE_DOWN - db SFX_BATTLE_22, $11,$c0 ; THRASH - db SFX_SUPER_EFFECTIVE, $20,$c0 ; DOUBLE_EDGE - db SFX_BATTLE_21, $00,$80 ; TAIL_WHIP - db SFX_BATTLE_1B, $00,$80 ; POISON_STING - db SFX_BATTLE_1B, $20,$c0 ; TWINEEDLE - db SFX_BATTLE_19, $00,$80 ; PIN_MISSILE - db SFX_BATTLE_31, $ff,$40 ; LEER - db SFX_BATTLE_1E, $00,$80 ; BITE - db SFX_BATTLE_0B, $00,$c0 ; GROWL - db SFX_BATTLE_0B, $00,$40 ; ROAR - db SFX_BATTLE_35, $00,$80 ; SING - db SFX_BATTLE_27, $40,$60 ; SUPERSONIC - db SFX_BATTLE_27, $00,$80 ; SONICBOOM - db SFX_BATTLE_27, $ff,$40 ; DISABLE - db SFX_BATTLE_2A, $80,$c0 ; ACID - db SFX_BATTLE_19, $10,$a0 ; EMBER - db SFX_BATTLE_19, $21,$e0 ; FLAMETHROWER - db SFX_BATTLE_29, $00,$80 ; MIST - db SFX_BATTLE_24, $20,$60 ; WATER_GUN - db SFX_BATTLE_2A, $00,$80 ; HYDRO_PUMP - db SFX_BATTLE_2C, $00,$80 ; SURF - db SFX_BATTLE_28, $40,$80 ; ICE_BEAM - db SFX_BATTLE_29, $f0,$e0 ; BLIZZARD - db SFX_PSYBEAM, $00,$80 ; PSYBEAM - db SFX_BATTLE_2A, $f0,$60 ; BUBBLEBEAM - db SFX_BATTLE_28, $00,$80 ; AURORA_BEAM - db SFX_BATTLE_36, $00,$80 ; HYPER_BEAM - db SFX_PECK,$01, $a0 ; PECK - db SFX_BATTLE_13, $f0,$20 ; DRILL_PECK - db SFX_BATTLE_23, $01,$c0 ; SUBMISSION - db SFX_BATTLE_23, $00,$80 ; LOW_KICK - db SFX_SUPER_EFFECTIVE, $00,$e0 ; COUNTER - db SFX_BATTLE_26, $01,$60 ; SEISMIC_TOSS - db SFX_BATTLE_26, $20,$40 ; STRENGTH - db SFX_BATTLE_24, $00,$80 ; ABSORB - db SFX_BATTLE_24, $40,$c0 ; MEGA_DRAIN - db SFX_BATTLE_1B, $03,$60 ; LEECH_SEED - db SFX_BATTLE_25, $11,$e0 ; GROWTH - db SFX_BATTLE_12, $20,$e0 ; RAZOR_LEAF - db SFX_BATTLE_2E, $00,$80 ; SOLARBEAM - db SFX_BATTLE_1C, $00,$80 ; POISONPOWDER - db SFX_BATTLE_1C, $11,$a0 ; STUN_SPORE - db SFX_BATTLE_1C, $01,$c0 ; SLEEP_POWDER - db SFX_BATTLE_13, $14,$c0 ; PETAL_DANCE - db SFX_BATTLE_1B, $02,$a0 ; STRING_SHOT - db SFX_BATTLE_29, $f0,$80 ; DRAGON_RAGE - db SFX_BATTLE_29, $20,$c0 ; FIRE_SPIN - db SFX_BATTLE_2F, $00,$20 ; THUNDERSHOCK - db SFX_BATTLE_2F, $20,$80 ; THUNDERBOLT - db SFX_BATTLE_2E, $12,$60 ; THUNDER_WAVE - db SFX_BATTLE_26, $00,$80 ; THUNDER - db SFX_BATTLE_14, $01,$e0 ; ROCK_THROW - db SFX_BATTLE_29, $0f,$e0 ; EARTHQUAKE - db SFX_BATTLE_29, $11,$20 ; FISSURE - db SFX_DAMAGE, $10,$40 ; DIG - db SFX_BATTLE_0F, $10,$c0 ; TOXIC - db SFX_BATTLE_14, $00,$20 ; CONFUSION - db SFX_PSYCHIC_M, $00,$80 ; PSYCHIC_M - db SFX_BATTLE_35, $11,$18 ; HYPNOSIS - db SFX_BATTLE_09, $20,$c0 ; MEDITATE - db SFX_FAINT_FALL, $20,$c0 ; AGILITY - db SFX_BATTLE_25, $00,$10 ; QUICK_ATTACK - db SFX_BATTLE_26, $f0,$20 ; RAGE - db SFX_BATTLE_33, $f0,$c0 ; TELEPORT - db SFX_NOT_VERY_EFFECTIVE,$f0,$e0 ; NIGHT_SHADE - db SFX_BATTLE_09, $f0,$40 ; MIMIC - db SFX_BATTLE_31, $00,$80 ; SCREECH - db SFX_BATTLE_33, $80,$40 ; DOUBLE_TEAM - db SFX_BATTLE_33, $00,$80 ; RECOVER - db SFX_BATTLE_14, $11,$20 ; HARDEN - db SFX_BATTLE_14, $22,$10 ; MINIMIZE - db SFX_BATTLE_1B, $f1,$ff ; SMOKESCREEN - db SFX_BATTLE_13, $f1,$ff ; CONFUSE_RAY - db SFX_BATTLE_14, $33,$30 ; WITHDRAW - db SFX_BATTLE_32, $40,$c0 ; DEFENSE_CURL - db SFX_BATTLE_0E, $20,$20 ; BARRIER - db SFX_BATTLE_0E, $f0,$10 ; LIGHT_SCREEN - db SFX_BATTLE_0F, $f8,$10 ; HAZE - db SFX_NOT_VERY_EFFECTIVE,$f0,$10 ; REFLECT - db SFX_BATTLE_25, $00,$80 ; FOCUS_ENERGY - db SFX_BATTLE_18, $00,$c0 ; BIDE - db SFX_BATTLE_32, $c0,$ff ; METRONOME - db SFX_BATTLE_09, $f2,$20 ; MIRROR_MOVE - db SFX_BATTLE_34, $00,$80 ; SELFDESTRUCT - db SFX_BATTLE_34, $00,$40 ; EGG_BOMB - db SFX_BATTLE_09, $00,$40 ; LICK - db SFX_NOT_VERY_EFFECTIVE,$10,$ff ; SMOG - db SFX_BATTLE_2A, $20,$20 ; SLUDGE - db SFX_BATTLE_32, $00,$80 ; BONE_CLUB - db SFX_BATTLE_29, $1f,$20 ; FIRE_BLAST - db SFX_BATTLE_25, $2f,$80 ; WATERFALL - db SFX_BATTLE_0F, $1f,$ff ; CLAMP - db SFX_BATTLE_2B, $1f,$60 ; SWIFT - db SFX_BATTLE_26, $1e,$20 ; SKULL_BASH - db SFX_BATTLE_26, $1f,$18 ; SPIKE_CANNON - db SFX_BATTLE_14, $0f,$80 ; CONSTRICT - db SFX_BATTLE_09, $f8,$10 ; AMNESIA - db SFX_FAINT_FALL, $18,$20 ; KINESIS - db SFX_BATTLE_32, $08,$40 ; SOFTBOILED - db SFX_BATTLE_17, $01,$e0 ; HI_JUMP_KICK - db SFX_NOT_VERY_EFFECTIVE,$09,$ff ; GLARE - db SFX_BATTLE_35, $42,$01 ; DREAM_EATER - db SFX_BATTLE_1C, $00,$ff ; POISON_GAS - db SFX_BATTLE_32, $08,$e0 ; BARRAGE - db SFX_BATTLE_24, $00,$80 ; LEECH_LIFE - db SFX_BATTLE_09, $88,$10 ; LOVELY_KISS - db SFX_BATTLE_25, $48,$ff ; SKY_ATTACK - db SFX_FAINT_FALL, $ff,$ff ; TRANSFORM - db SFX_BATTLE_24, $ff,$10 ; BUBBLE - db SFX_FAINT_FALL, $ff,$04 ; DIZZY_PUNCH - db SFX_BATTLE_1C, $01,$ff ; SPORE - db SFX_BATTLE_13, $f8,$ff ; FLASH - db SFX_BATTLE_0C, $f0,$f0 ; PSYWAVE - db SFX_BATTLE_0F, $08,$10 ; SPLASH - db SFX_BATTLE_0D, $f0,$ff ; ACID_ARMOR - db SFX_SUPER_EFFECTIVE, $f0,$ff ; CRABHAMMER - db SFX_BATTLE_34, $10,$ff ; EXPLOSION - db SFX_BATTLE_0E, $f0,$20 ; FURY_SWIPES - db SFX_BATTLE_2B, $f0,$60 ; BONEMERANG - db SFX_BATTLE_21, $12,$10 ; REST - db SFX_BATTLE_36, $f0,$20 ; ROCK_SLIDE - db SFX_BATTLE_1E, $12,$ff ; HYPER_FANG - db SFX_BATTLE_31, $80,$04 ; SHARPEN - db SFX_BATTLE_33, $f0,$10 ; CONVERSION - db SFX_BATTLE_29, $f8,$ff ; TRI_ATTACK - db SFX_BATTLE_26, $f0,$ff ; SUPER_FANG - db SFX_NOT_VERY_EFFECTIVE,$01,$ff ; SLASH - db SFX_BATTLE_2C, $d8,$04 ; SUBSTITUTE - db SFX_BATTLE_0B, $00,$80 ; STRUGGLE - db SFX_BATTLE_0B, $00,$80 + db SFX_POUND, $00, $80 ; POUND + db SFX_BATTLE_0C, $10, $80 ; KARATE_CHOP + db SFX_DOUBLESLAP, $00, $80 ; DOUBLESLAP + db SFX_BATTLE_0B, $01, $80 ; COMET_PUNCH + db SFX_BATTLE_0D, $00, $40 ; MEGA_PUNCH + db SFX_SILPH_SCOPE, $00, $ff ; PAY_DAY + db SFX_BATTLE_0D, $10, $60 ; FIRE_PUNCH + db SFX_BATTLE_0D, $20, $80 ; ICE_PUNCH + db SFX_BATTLE_0D, $00, $a0 ; THUNDERPUNCH + db SFX_DAMAGE, $00, $80 ; SCRATCH + db SFX_BATTLE_0F, $20, $40 ; VICEGRIP + db SFX_BATTLE_0F, $00, $80 ; GUILLOTINE + db SFX_BATTLE_0E, $00, $a0 ; RAZOR_WIND + db SFX_NOT_VERY_EFFECTIVE, $10, $c0 ; SWORDS_DANCE + db SFX_NOT_VERY_EFFECTIVE, $00, $a0 ; CUT + db SFX_BATTLE_12, $00, $c0 ; GUST + db SFX_BATTLE_12, $10, $a0 ; WING_ATTACK + db SFX_BATTLE_13, $00, $e0 ; WHIRLWIND + db SFX_NOT_VERY_EFFECTIVE, $20, $c0 ; FLY + db SFX_BATTLE_14, $00, $80 ; BIND + db SFX_BATTLE_22, $00, $80 ; SLAM + db SFX_VINE_WHIP, $01, $80 ; VINE_WHIP + db SFX_BATTLE_20, $00, $80 ; STOMP + db SFX_BATTLE_17, $f0, $40 ; DOUBLE_KICK + db SFX_SUPER_EFFECTIVE, $00, $80 ; MEGA_KICK + db SFX_BATTLE_17, $00, $80 ; JUMP_KICK + db SFX_BATTLE_21, $10, $80 ; ROLLING_KICK + db SFX_BATTLE_1B, $01, $a0 ; SAND_ATTACK + db SFX_BATTLE_18, $00, $80 ; HEADBUTT + db SFX_BATTLE_1E, $00, $60 ; HORN_ATTACK + db SFX_BATTLE_1E, $01, $40 ; FURY_ATTACK + db SFX_HORN_DRILL, $00, $a0 ; HORN_DRILL + db SFX_SUPER_EFFECTIVE, $10, $a0 ; TACKLE + db SFX_BATTLE_20, $00, $c0 ; BODY_SLAM + db SFX_BATTLE_14, $10, $60 ; WRAP + db SFX_SUPER_EFFECTIVE, $00, $a0 ; TAKE_DOWN + db SFX_BATTLE_22, $11, $c0 ; THRASH + db SFX_SUPER_EFFECTIVE, $20, $c0 ; DOUBLE_EDGE + db SFX_BATTLE_21, $00, $80 ; TAIL_WHIP + db SFX_BATTLE_1B, $00, $80 ; POISON_STING + db SFX_BATTLE_1B, $20, $c0 ; TWINEEDLE + db SFX_BATTLE_19, $00, $80 ; PIN_MISSILE + db SFX_BATTLE_31, $ff, $40 ; LEER + db SFX_BATTLE_1E, $00, $80 ; BITE + db SFX_BATTLE_0B, $00, $c0 ; GROWL + db SFX_BATTLE_0B, $00, $40 ; ROAR + db SFX_BATTLE_35, $00, $80 ; SING + db SFX_BATTLE_27, $40, $60 ; SUPERSONIC + db SFX_BATTLE_27, $00, $80 ; SONICBOOM + db SFX_BATTLE_27, $ff, $40 ; DISABLE + db SFX_BATTLE_2A, $80, $c0 ; ACID + db SFX_BATTLE_19, $10, $a0 ; EMBER + db SFX_BATTLE_19, $21, $e0 ; FLAMETHROWER + db SFX_BATTLE_29, $00, $80 ; MIST + db SFX_BATTLE_24, $20, $60 ; WATER_GUN + db SFX_BATTLE_2A, $00, $80 ; HYDRO_PUMP + db SFX_BATTLE_2C, $00, $80 ; SURF + db SFX_BATTLE_28, $40, $80 ; ICE_BEAM + db SFX_BATTLE_29, $f0, $e0 ; BLIZZARD + db SFX_PSYBEAM, $00, $80 ; PSYBEAM + db SFX_BATTLE_2A, $f0, $60 ; BUBBLEBEAM + db SFX_BATTLE_28, $00, $80 ; AURORA_BEAM + db SFX_BATTLE_36, $00, $80 ; HYPER_BEAM + db SFX_PECK, $01, $a0 ; PECK + db SFX_BATTLE_13, $f0, $20 ; DRILL_PECK + db SFX_BATTLE_23, $01, $c0 ; SUBMISSION + db SFX_BATTLE_23, $00, $80 ; LOW_KICK + db SFX_SUPER_EFFECTIVE, $00, $e0 ; COUNTER + db SFX_BATTLE_26, $01, $60 ; SEISMIC_TOSS + db SFX_BATTLE_26, $20, $40 ; STRENGTH + db SFX_BATTLE_24, $00, $80 ; ABSORB + db SFX_BATTLE_24, $40, $c0 ; MEGA_DRAIN + db SFX_BATTLE_1B, $03, $60 ; LEECH_SEED + db SFX_BATTLE_25, $11, $e0 ; GROWTH + db SFX_BATTLE_12, $20, $e0 ; RAZOR_LEAF + db SFX_BATTLE_2E, $00, $80 ; SOLARBEAM + db SFX_BATTLE_1C, $00, $80 ; POISONPOWDER + db SFX_BATTLE_1C, $11, $a0 ; STUN_SPORE + db SFX_BATTLE_1C, $01, $c0 ; SLEEP_POWDER + db SFX_BATTLE_13, $14, $c0 ; PETAL_DANCE + db SFX_BATTLE_1B, $02, $a0 ; STRING_SHOT + db SFX_BATTLE_29, $f0, $80 ; DRAGON_RAGE + db SFX_BATTLE_29, $20, $c0 ; FIRE_SPIN + db SFX_BATTLE_2F, $00, $20 ; THUNDERSHOCK + db SFX_BATTLE_2F, $20, $80 ; THUNDERBOLT + db SFX_BATTLE_2E, $12, $60 ; THUNDER_WAVE + db SFX_BATTLE_26, $00, $80 ; THUNDER + db SFX_BATTLE_14, $01, $e0 ; ROCK_THROW + db SFX_BATTLE_29, $0f, $e0 ; EARTHQUAKE + db SFX_BATTLE_29, $11, $20 ; FISSURE + db SFX_DAMAGE, $10, $40 ; DIG + db SFX_BATTLE_0F, $10, $c0 ; TOXIC + db SFX_BATTLE_14, $00, $20 ; CONFUSION + db SFX_PSYCHIC_M, $00, $80 ; PSYCHIC_M + db SFX_BATTLE_35, $11, $18 ; HYPNOSIS + db SFX_BATTLE_09, $20, $c0 ; MEDITATE + db SFX_FAINT_FALL, $20, $c0 ; AGILITY + db SFX_BATTLE_25, $00, $10 ; QUICK_ATTACK + db SFX_BATTLE_26, $f0, $20 ; RAGE + db SFX_BATTLE_33, $f0, $c0 ; TELEPORT + db SFX_NOT_VERY_EFFECTIVE, $f0, $e0 ; NIGHT_SHADE + db SFX_BATTLE_09, $f0, $40 ; MIMIC + db SFX_BATTLE_31, $00, $80 ; SCREECH + db SFX_BATTLE_33, $80, $40 ; DOUBLE_TEAM + db SFX_BATTLE_33, $00, $80 ; RECOVER + db SFX_BATTLE_14, $11, $20 ; HARDEN + db SFX_BATTLE_14, $22, $10 ; MINIMIZE + db SFX_BATTLE_1B, $f1, $ff ; SMOKESCREEN + db SFX_BATTLE_13, $f1, $ff ; CONFUSE_RAY + db SFX_BATTLE_14, $33, $30 ; WITHDRAW + db SFX_BATTLE_32, $40, $c0 ; DEFENSE_CURL + db SFX_BATTLE_0E, $20, $20 ; BARRIER + db SFX_BATTLE_0E, $f0, $10 ; LIGHT_SCREEN + db SFX_BATTLE_0F, $f8, $10 ; HAZE + db SFX_NOT_VERY_EFFECTIVE, $f0, $10 ; REFLECT + db SFX_BATTLE_25, $00, $80 ; FOCUS_ENERGY + db SFX_BATTLE_18, $00, $c0 ; BIDE + db SFX_BATTLE_32, $c0, $ff ; METRONOME + db SFX_BATTLE_09, $f2, $20 ; MIRROR_MOVE + db SFX_BATTLE_34, $00, $80 ; SELFDESTRUCT + db SFX_BATTLE_34, $00, $40 ; EGG_BOMB + db SFX_BATTLE_09, $00, $40 ; LICK + db SFX_NOT_VERY_EFFECTIVE, $10, $ff ; SMOG + db SFX_BATTLE_2A, $20, $20 ; SLUDGE + db SFX_BATTLE_32, $00, $80 ; BONE_CLUB + db SFX_BATTLE_29, $1f, $20 ; FIRE_BLAST + db SFX_BATTLE_25, $2f, $80 ; WATERFALL + db SFX_BATTLE_0F, $1f, $ff ; CLAMP + db SFX_BATTLE_2B, $1f, $60 ; SWIFT + db SFX_BATTLE_26, $1e, $20 ; SKULL_BASH + db SFX_BATTLE_26, $1f, $18 ; SPIKE_CANNON + db SFX_BATTLE_14, $0f, $80 ; CONSTRICT + db SFX_BATTLE_09, $f8, $10 ; AMNESIA + db SFX_FAINT_FALL, $18, $20 ; KINESIS + db SFX_BATTLE_32, $08, $40 ; SOFTBOILED + db SFX_BATTLE_17, $01, $e0 ; HI_JUMP_KICK + db SFX_NOT_VERY_EFFECTIVE, $09, $ff ; GLARE + db SFX_BATTLE_35, $42, $01 ; DREAM_EATER + db SFX_BATTLE_1C, $00, $ff ; POISON_GAS + db SFX_BATTLE_32, $08, $e0 ; BARRAGE + db SFX_BATTLE_24, $00, $80 ; LEECH_LIFE + db SFX_BATTLE_09, $88, $10 ; LOVELY_KISS + db SFX_BATTLE_25, $48, $ff ; SKY_ATTACK + db SFX_FAINT_FALL, $ff, $ff ; TRANSFORM + db SFX_BATTLE_24, $ff, $10 ; BUBBLE + db SFX_FAINT_FALL, $ff, $04 ; DIZZY_PUNCH + db SFX_BATTLE_1C, $01, $ff ; SPORE + db SFX_BATTLE_13, $f8, $ff ; FLASH + db SFX_BATTLE_0C, $f0, $f0 ; PSYWAVE + db SFX_BATTLE_0F, $08, $10 ; SPLASH + db SFX_BATTLE_0D, $f0, $ff ; ACID_ARMOR + db SFX_SUPER_EFFECTIVE, $f0, $ff ; CRABHAMMER + db SFX_BATTLE_34, $10, $ff ; EXPLOSION + db SFX_BATTLE_0E, $f0, $20 ; FURY_SWIPES + db SFX_BATTLE_2B, $f0, $60 ; BONEMERANG + db SFX_BATTLE_21, $12, $10 ; REST + db SFX_BATTLE_36, $f0, $20 ; ROCK_SLIDE + db SFX_BATTLE_1E, $12, $ff ; HYPER_FANG + db SFX_BATTLE_31, $80, $04 ; SHARPEN + db SFX_BATTLE_33, $f0, $10 ; CONVERSION + db SFX_BATTLE_29, $f8, $ff ; TRI_ATTACK + db SFX_BATTLE_26, $f0, $ff ; SUPER_FANG + db SFX_NOT_VERY_EFFECTIVE, $01, $ff ; SLASH + db SFX_BATTLE_2C, $d8, $04 ; SUBSTITUTE + db SFX_BATTLE_0B, $00, $80 ; STRUGGLE + db SFX_BATTLE_0B, $00, $80 CopyPicTiles: ld a, [H_WHOSETURN] @@ -2587,112 +2759,108 @@ CopyTileIDs: ret TileIDListPointerTable: - dw Unknown_79b24 - dn 7, 7 - dw Unknown_79b55 - dn 5, 7 - dw Unknown_79b78 - dn 3, 7 + dw DownscaledMonTiles_7x7 + dn 7, 7 + dw DownscaledMonTiles_5x7 + dn 5, 7 + dw DownscaledMonTiles_3x7 + dn 3, 7 dw GengarIntroTiles1 - dn 7, 7 + dn 7, 7 dw GengarIntroTiles2 - dn 7, 7 + dn 7, 7 dw GengarIntroTiles3 - dn 7, 7 - dw Unknown_79c20 - dn 8, 6 - dw Unknown_79c50 - dn 3, 12 + dn 7, 7 + dw DownscaledMonTiles_79d7c + dn 8, 6 + dw DownscaledMonTiles_79dac + dn 3, 12 DownscaledMonTiles_5x5: - db $31,$38,$46,$54,$5B - db $32,$39,$47,$55,$5C - db $34,$3B,$49,$57,$5E - db $36,$3D,$4B,$59,$60 - db $37,$3E,$4C,$5A,$61 + db $31, $38, $46, $54, $5B + db $32, $39, $47, $55, $5C + db $34, $3B, $49, $57, $5E + db $36, $3D, $4B, $59, $60 + db $37, $3E, $4C, $5A, $61 DownscaledMonTiles_3x3: - db $31,$46,$5B - db $34,$49,$5E - db $37,$4C,$61 - -Unknown_79b24: - db $00,$07,$0E,$15,$1C,$23,$2A - db $01,$08,$0F,$16,$1D,$24,$2B - db $02,$09,$10,$17,$1E,$25,$2C - db $03,$0A,$11,$18,$1F,$26,$2D - db $04,$0B,$12,$19,$20,$27,$2E - db $05,$0C,$13,$1A,$21,$28,$2F - db $06,$0D,$14,$1B,$22,$29,$30 - -Unknown_79b55: - db $00,$07,$0E,$15,$1C,$23,$2A - db $01,$08,$0F,$16,$1D,$24,$2B - db $03,$0A,$11,$18,$1F,$26,$2D - db $04,$0B,$12,$19,$20,$27,$2E - db $05,$0C,$13,$1A,$21,$28,$2F - -Unknown_79b78: - db $00,$07,$0E,$15,$1C,$23,$2A - db $02,$09,$10,$17,$1E,$25,$2C - db $04,$0B,$12,$19,$20,$27,$2E + db $31, $46, $5B + db $34, $49, $5E + db $37, $4C, $61 + +DownscaledMonTiles_7x7: + db $00, $07, $0E, $15, $1C, $23, $2A + db $01, $08, $0F, $16, $1D, $24, $2B + db $02, $09, $10, $17, $1E, $25, $2C + db $03, $0A, $11, $18, $1F, $26, $2D + db $04, $0B, $12, $19, $20, $27, $2E + db $05, $0C, $13, $1A, $21, $28, $2F + db $06, $0D, $14, $1B, $22, $29, $30 + +DownscaledMonTiles_5x7: + db $00, $07, $0E, $15, $1C, $23, $2A + db $01, $08, $0F, $16, $1D, $24, $2B + db $03, $0A, $11, $18, $1F, $26, $2D + db $04, $0B, $12, $19, $20, $27, $2E + db $05, $0C, $13, $1A, $21, $28, $2F + +DownscaledMonTiles_3x7: + db $00, $07, $0E, $15, $1C, $23, $2A + db $02, $09, $10, $17, $1E, $25, $2C + db $04, $0B, $12, $19, $20, $27, $2E GengarIntroTiles1: - db $00,$00,$00,$00,$00,$00,$00 - db $00,$00,$00,$00,$00,$19,$00 - db $02,$06,$0B,$10,$14,$1A,$00 - db $00,$07,$0C,$11,$15,$1B,$00 - db $03,$08,$0D,$12,$16,$1C,$00 - db $04,$09,$0E,$13,$17,$1D,$1F - db $05,$0A,$0F,$01,$18,$1E,$20 + db $00, $00, $00, $00, $00, $00, $00 + db $00, $00, $00, $00, $00, $19, $00 + db $02, $06, $0B, $10, $14, $1A, $00 + db $00, $07, $0C, $11, $15, $1B, $00 + db $03, $08, $0D, $12, $16, $1C, $00 + db $04, $09, $0E, $13, $17, $1D, $1F + db $05, $0A, $0F, $01, $18, $1E, $20 GengarIntroTiles2: - db $00,$00,$00,$30,$00,$37,$00 - db $00,$00,$2B,$31,$34,$38,$3D - db $21,$26,$2C,$01,$35,$39,$3E - db $22,$27,$2D,$32,$36,$01,$00 - db $23,$28,$2E,$33,$01,$3A,$00 - db $24,$29,$2F,$01,$01,$3B,$00 - db $25,$2A,$01,$01,$01,$3C,$00 + db $00, $00, $00, $30, $00, $37, $00 + db $00, $00, $2B, $31, $34, $38, $3D + db $21, $26, $2C, $01, $35, $39, $3E + db $22, $27, $2D, $32, $36, $01, $00 + db $23, $28, $2E, $33, $01, $3A, $00 + db $24, $29, $2F, $01, $01, $3B, $00 + db $25, $2A, $01, $01, $01, $3C, $00 GengarIntroTiles3: - db $00,$00,$00,$00,$00,$00,$00 - db $00,$00,$47,$4D,$00,$00,$00 - db $00,$00,$48,$4E,$52,$56,$5B - db $3F,$43,$49,$4F,$53,$57,$5C - db $40,$44,$4A,$50,$54,$58,$00 - db $41,$45,$4B,$51,$4C,$59,$5D - db $42,$46,$4C,$4C,$55,$5A,$5E - -Unknown_79c20: - db $31,$32,$32,$32,$32,$33 - db $34,$35,$36,$36,$37,$38 - db $34,$39,$3A,$3A,$3B,$38 - db $3C,$3D,$3E,$3E,$3F,$40 - db $41,$42,$43,$43,$44,$45 - db $46,$47,$43,$48,$49,$4A - db $41,$43,$4B,$4C,$4D,$4E - db $4F,$50,$50,$50,$51,$52 - -Unknown_79c50: - db $43,$55,$56,$53,$53,$53,$53,$53,$53,$53,$53,$53 - db $43,$57,$58,$54,$54,$54,$54,$54,$54,$54,$54,$54 - db $43,$59,$5A,$43,$43,$43,$43,$43,$43,$43,$43,$43 + db $00, $00, $00, $00, $00, $00, $00 + db $00, $00, $47, $4D, $00, $00, $00 + db $00, $00, $48, $4E, $52, $56, $5B + db $3F, $43, $49, $4F, $53, $57, $5C + db $40, $44, $4A, $50, $54, $58, $00 + db $41, $45, $4B, $51, $4C, $59, $5D + db $42, $46, $4C, $4C, $55, $5A, $5E + +DownscaledMonTiles_79d7c: + db $31, $32, $32, $32, $32, $33 + db $34, $35, $36, $36, $37, $38 + db $34, $39, $3A, $3A, $3B, $38 + db $3C, $3D, $3E, $3E, $3F, $40 + db $41, $42, $43, $43, $44, $45 + db $46, $47, $43, $48, $49, $4A + db $41, $43, $4B, $4C, $4D, $4E + db $4F, $50, $50, $50, $51, $52 + +DownscaledMonTiles_79dac: + db $43, $55, $56, $53, $53, $53, $53, $53, $53, $53, $53, $53 + db $43, $57, $58, $54, $54, $54, $54, $54, $54, $54, $54, $54 + db $43, $59, $5A, $43, $43, $43, $43, $43, $43, $43, $43, $43 AnimationLeavesFalling: ; Makes leaves float down from the top of the screen. This is used ; in Razor Leaf's animation. - ld a, [rOBP0] - push af ld a, [wAnimPalette] ld [rOBP0], a + call UpdateGBCPal_OBP0 ld d, $37 ; leaf tile ld a, 3 ; number of leaves ld [wNumFallingObjects], a - call AnimationFallingObjects - pop af - ld [rOBP0], a - ret + jp AnimationFallingObjects AnimationPetalsFalling: ; Makes lots of petals fall down from the top of the screen. It's used in @@ -2747,6 +2915,8 @@ FallingObjects_UpdateOAMEntry: ; movement byte. ld hl, wOAMBuffer add hl, de + ld a, $1 + ld [wdef5], a ld a, [hl] inc a inc a @@ -2755,6 +2925,12 @@ FallingObjects_UpdateOAMEntry: ld a, 160 ; if Y >= 112, put it off-screen .next ld [hli], a ; Y + cp 40 + jr c, .asm_79e51 + ld a, [wdef5] + inc a + ld [wdef5], a +.asm_79e51 ld a, [wFallingObjectMovementByte] ld b, a ld de, FallingObjects_DeltaXs @@ -2771,6 +2947,13 @@ FallingObjects_UpdateOAMEntry: ld a, [de] add [hl] ld [hli], a ; X + cp 88 + jr c, .asm_79e75 + ld a, [wdef5] + add $2 + and $3 + ld [wdef5], a +.asm_79e75 inc hl xor a ; no horizontal flip jr .next2 @@ -2780,9 +2963,19 @@ FallingObjects_UpdateOAMEntry: ld a, [hl] sub b ld [hli], a ; X + cp 88 + jr c, .asm_79e5c + ld a, [wdef5] + add $2 + and $3 + ld [wdef5], a +.asm_79e5c inc hl ld a, (1 << OAM_X_FLIP) .next2 + ld b, a + ld a, [wdef5] + or b ld [hl], a ; attribute ret @@ -2822,7 +3015,7 @@ FallingObjects_InitXCoords: ret FallingObjects_InitialXCoords: - db $38,$40,$50,$60,$70,$88,$90,$56,$67,$4A,$77,$84,$98,$32,$22,$5C,$6C,$7D,$8E,$99 + db $38, $40, $50, $60, $70, $88, $90, $56, $67, $4A, $77, $84, $98, $32, $22, $5C, $6C, $7D, $8E, $99 FallingObjects_InitMovementData: ld hl, wFallingObjectsMovementData @@ -2838,7 +3031,7 @@ FallingObjects_InitMovementData: ret FallingObjects_InitialMovementData: - db $00,$84,$06,$81,$02,$88,$01,$83,$05,$89,$09,$80,$07,$87,$03,$82,$04,$85,$08,$86 + db $00, $84, $06, $81, $02, $88, $01, $83, $05, $89, $09, $80, $07, $87, $03, $82, $04, $85, $08, $86 AnimationShakeEnemyHUD: ; Shakes the enemy HUD. @@ -2867,6 +3060,14 @@ AnimationShakeEnemyHUD: ld hl, vBGMap1 - $20 * 7 call BattleAnimCopyTileMapToVRAM +; update BGMap attributes + ld a, [hGBC] + and a + jr z, .notGBC + ld c, 13 + callba LoadBGMapAttributes +.notGBC + ; Move the window so that the row below the enemy HUD (in BG map 0) lines up ; with the top row of the window on the screen. This makes it so that the window ; covers everything below the enemy HD with a copy that looks just like what @@ -2900,13 +3101,18 @@ AnimationShakeEnemyHUD: ld [hWY], a ld hl, vBGMap1 call BattleAnimCopyTileMapToVRAM +; update BGMap attributes + ld a, [hGBC] + and a + jr z, .notGBC2 + ld c, 11 + callba LoadBGMapAttributes +.notGBC2 xor a ld [hWY], a call SaveScreenTilesToBuffer1 ld hl, vBGMap0 call BattleAnimCopyTileMapToVRAM - call ClearScreen - call Delay3 call LoadScreenTilesFromBuffer1 ld hl, vBGMap1 jp BattleAnimCopyTileMapToVRAM @@ -2995,7 +3201,7 @@ TossBallAnimation: .PokeBallAnimations: ; sequence of animations that make up the Poké Ball toss - db POOF_ANIM,HIDEPIC_ANIM,SHAKE_ANIM,POOF_ANIM,SHOWPIC_ANIM + db POOF_ANIM, HIDEPIC_ANIM, SHAKE_ANIM, POOF_ANIM, SHOWPIC_ANIM .BlockBall ld a, TOSS_ANIM diff --git a/engine/battle/bank3d_battle.asm b/engine/battle/bank3d_battle.asm new file mode 100644 index 00000000..0cf24fe1 --- /dev/null +++ b/engine/battle/bank3d_battle.asm @@ -0,0 +1,291 @@ +InitBattle: + ld a, [wCurOpponent] + and a + jr z, asm_f6003 + +InitOpponent: + ld a, [wCurOpponent] + ld [wcf91], a + ld [wEnemyMonSpecies2], a + jr asm_f601d +asm_f6003: + ld a, [wd732] + bit 1, a + jr z, .asm_f600f + ld a, [hJoyHeld] + bit 1, a ; B button pressed? + ret nz +.asm_f600f + ld a, [wNumberOfNoRandomBattleStepsLeft] + and a + ret nz + callab TryDoWildEncounter + ret nz +asm_f601d: + ld a, [wMapPalOffset] + push af + ld hl, wLetterPrintingDelayFlags + ld a, [hl] + push af + res 1, [hl] + call InitBattleVariables + ld a, [wEnemyMonSpecies2] + sub OPP_ID_OFFSET + jp c, InitWildBattle + ld [wTrainerClass], a + call GetTrainerInformation + callab ReadTrainer + callab DoBattleTransitionAndInitBattleVariables + call _LoadTrainerPic + xor a + ld [wEnemyMonSpecies2], a + ld [$ffe1], a + dec a + ld [wAICount], a + coord hl, 12, 0 + predef CopyUncompressedPicToTilemap + ld a, $ff + ld [wEnemyMonPartyPos], a + ld a, $2 + ld [wIsInBattle], a + + ; Is this a major story battle? + ld a,[wLoneAttackNo] + and a + jp z,InitBattle_Common + callabd_ModifyPikachuHappiness PIKAHAPPY_GYMLEADER ; useless since already in bank3d + jp InitBattle_Common + +InitWildBattle: + ld a, $1 + ld [wIsInBattle], a + callab LoadEnemyMonData + callab DoBattleTransitionAndInitBattleVariables + ld a, [wCurOpponent] + cp MAROWAK + jr z, .isGhost + callab IsGhostBattle + jr nz, .isNoGhost +.isGhost + ld hl, wMonHSpriteDim + ld a, $66 + ld [hli], a ; write sprite dimensions + ld bc, GhostPic + ld a, c + ld [hli], a ; write front sprite pointer + ld [hl], b + ld hl, wEnemyMonNick ; set name to "GHOST" + ld a, "G" + ld [hli], a + ld a, "H" + ld [hli], a + ld a, "O" + ld [hli], a + ld a, "S" + ld [hli], a + ld a, "T" + ld [hli], a + ld [hl], "@" + ld a, [wcf91] + push af + ld a, MON_GHOST + ld [wcf91], a + ld de, vFrontPic + call LoadMonFrontSprite ; load ghost sprite + pop af + ld [wcf91], a + jr .spriteLoaded +.isNoGhost + ld de, vFrontPic + call LoadMonFrontSprite ; load mon sprite +.spriteLoaded + xor a + ld [wTrainerClass], a + ld [$ffe1], a + coord hl, 12, 0 + predef CopyUncompressedPicToTilemap + +; common code that executes after init battle code specific to trainer or wild battles +InitBattle_Common: + ld b, $0 + call RunPaletteCommand + callab SlidePlayerAndEnemySilhouettesOnScreen + xor a + ld [H_AUTOBGTRANSFERENABLED], a + ld hl, .emptyString + call PrintText + call SaveScreenTilesToBuffer1 + call ClearScreen + ld a, $98 + ld [$ffbd], a + ld a, $1 + ld [H_AUTOBGTRANSFERENABLED], a + call Delay3 + ld a, $9c + ld [$ffbd], a + call LoadScreenTilesFromBuffer1 + coord hl, 9, 7 + ld bc, $50a + call ClearScreenArea + coord hl, 1, 0 + ld bc, $40a + call ClearScreenArea + call ClearSprites + ld a, [wIsInBattle] + dec a ; is it a wild battle? + ld hl, DrawEnemyHUDAndHPBar + ld b,BANK(DrawEnemyHUDAndHPBar) + call z, Bankswitch ; draw enemy HUD and HP bar if it's a wild battle + callab StartBattle + callab EndOfBattle + pop af + ld [wLetterPrintingDelayFlags], a + pop af + ld [wMapPalOffset], a + ld a, [wSavedTilesetType] + ld [hTilesetType], a + scf + ret +.emptyString + db "@" + +_LoadTrainerPic: +; wd033-wd034 contain pointer to pic + ld a, [wTrainerPicPointer] + ld e, a + ld a, [wTrainerPicPointer + 1] + ld d, a ; de contains pointer to trainer pic + ld a, [wLinkState] + and a + ld a, Bank(TrainerPics) ; this is where all the trainer pics are (not counting Red's) + jr z, .loadSprite + ld a, Bank(RedPicFront) +.loadSprite + call UncompressSpriteFromDE + ld de, vFrontPic + ld a, $77 + ld c, a + jp LoadUncompressedSpriteData + +LoadMonBackPic: +; Assumes the monster's attributes have +; been loaded with GetMonHeader. + ld a, [wBattleMonSpecies2] + ld [wcf91], a + coord hl, 1, 5 + ld bc,$708 + call ClearScreenArea + ld hl, wMonHBackSprite - wMonHeader + call UncompressMonSprite + predef ScaleSpriteByTwo + ld de, vBackPic + call InterlaceMergeSpriteBuffers ; combine the two buffers to a single 2bpp sprite + ld hl, vSprites + ld de, vBackPic + ld c, (2*SPRITEBUFFERSIZE)/16 ; count of 16-byte chunks to be copied + ld a, [H_LOADEDROMBANK] + ld b, a + jp CopyVideoData + +AnimateSendingOutMon: + ld a, [wPredefRegisters] + ld h, a + ld a, [wPredefRegisters + 1] + ld l, a + ld a, [$ffe1] + ld [H_DOWNARROWBLINKCNT1], a + ld b, $4c + ld a, [wIsInBattle] + and a + jr z, .asm_f61ef + add b + ld [hl], a + call Delay3 + ld bc, -41 + add hl, bc + ld a, $1 + ld [wNumMovesMinusOne], a + ld bc, $303 + predef CopyDownscaledMonTiles + ld c, $4 + call DelayFrames + ld bc, -41 + add hl, bc + xor a + ld [wNumMovesMinusOne], a + ld bc, $505 + predef CopyDownscaledMonTiles + ld c, $5 + call DelayFrames + ld bc, -41 + jr .asm_f61f2 +.asm_f61ef + ld bc, -123 +.asm_f61f2 + add hl, bc + ld a, [H_DOWNARROWBLINKCNT1] + add $31 + jr CopyUncompressedPicToHL + +CopyUncompressedPicToTilemap: + ld a, [wPredefRegisters] + ld h, a + ld a, [wPredefRegisters + 1] + ld l, a + ld a, [$ffe1] +CopyUncompressedPicToHL: + ld bc, $707 + ld de, $14 + push af + ld a, [wSpriteFlipped] + and a + jr nz, .asm_f6220 + pop af +.asm_f6211 + push bc + push hl +.asm_f6213 + ld [hl], a + add hl, de + inc a + dec c + jr nz, .asm_f6213 + pop hl + inc hl + pop bc + dec b + jr nz, .asm_f6211 + ret + +.asm_f6220 + push bc + ld b, $0 + dec c + add hl, bc + pop bc + pop af +.asm_f6227 + push bc + push hl +.asm_f6229 + ld [hl], a + add hl, de + inc a + dec c + jr nz, .asm_f6229 + pop hl + dec hl + pop bc + dec b + jr nz, .asm_f6227 + ret + +INCLUDE "engine/battle/init_battle_variables.asm" +INCLUDE "engine/battle/moveEffects/focus_energy_effect.asm" +INCLUDE "engine/battle/moveEffects/heal_effect.asm" +INCLUDE "engine/battle/moveEffects/transform_effect.asm" +INCLUDE "engine/battle/moveEffects/reflect_light_screen_effect.asm" +INCLUDE "engine/battle/moveEffects/mist_effect.asm" +INCLUDE "engine/battle/moveEffects/one_hit_ko_effect.asm" +INCLUDE "engine/battle/moveEffects/pay_day_effect.asm" +INCLUDE "engine/battle/moveEffects/paralyze_effect.asm" diff --git a/engine/battle/bank_e_misc.asm b/engine/battle/bank_e_misc.asm index 33af6f6f..df9145f2 100755 --- a/engine/battle/bank_e_misc.asm +++ b/engine/battle/bank_e_misc.asm @@ -101,22 +101,3 @@ InitList: ld a, b ld [wItemPrices + 1], a ret - -; get species of mon e in list [wMonDataLocation] for LoadMonData -GetMonSpecies: - ld hl, wPartySpecies - ld a, [wMonDataLocation] - and a - jr z, .getSpecies - dec a - jr z, .enemyParty - ld hl, wBoxSpecies - jr .getSpecies -.enemyParty - ld hl, wEnemyPartyMons -.getSpecies - ld d, 0 - add hl, de - ld a, [hl] - ld [wcf91], a - ret diff --git a/engine/battle/battle_transitions.asm b/engine/battle/battle_transitions.asm index 436e38b5..e4392a01 100644 --- a/engine/battle/battle_transitions.asm +++ b/engine/battle/battle_transitions.asm @@ -196,6 +196,9 @@ BattleTransition_BlackScreen: ld [rBGP], a ld [rOBP0], a ld [rOBP1], a + call UpdateGBCPal_BGP + call UpdateGBCPal_OBP0 + call UpdateGBCPal_OBP1 ret ; for non-dungeon trainer battles @@ -359,6 +362,7 @@ BattleTransition_FlashScreen_: cp $1 jr z, .done ld [rBGP], a + call UpdateGBCPal_BGP ld c, 2 call DelayFrames jr .loop @@ -373,7 +377,7 @@ BattleTransition_FlashScreenPalettes: ; used for low level trainer dungeon battles BattleTransition_Shrink: - ld c, SCREEN_HEIGHT / 2 + ld c, 9 .loop push bc xor a @@ -407,7 +411,7 @@ BattleTransition_Shrink: ; used for high level trainer dungeon battles BattleTransition_Split: - ld c, SCREEN_HEIGHT / 2 + ld c, 9 xor a ld [H_AUTOBGTRANSFERENABLED], a .loop diff --git a/engine/battle/common_text.asm b/engine/battle/common_text.asm index 4a138048..e8f4f002 100644 --- a/engine/battle/common_text.asm +++ b/engine/battle/common_text.asm @@ -8,8 +8,20 @@ PrintBeginningBattleText: cp MR_FUJIS_HOUSE jr c, .pokemonTower .notPokemonTower + ld a,[wBattleType] + cp BATTLE_TYPE_PIKACHU + jr nz,.notPikachuBattle + callab IsPlayerPikachuAsleepInParty + ld e,$24 + jr c,.asm_f4026 + ld e,$a +.asm_f4026 + callab PlayPikachuSoundClip + jr .continue +.notPikachuBattle ld a, [wEnemyMonSpecies2] call PlayCry +.continue ld hl, WildMonAppearedText ld a, [wMoveMissed] and a @@ -23,9 +35,13 @@ PrintBeginningBattleText: call DelayFrames ld hl, TrainerWantsToFightText .wildBattle + ld a, [wBattleType] + and a + jr nz, .doNotDrawPokeballs push hl callab DrawAllPokeballs pop hl +.doNotDrawPokeballs call PrintText jr .done .pokemonTower diff --git a/engine/battle/core.asm b/engine/battle/core.asm index 2b00a812..60146902 100755 --- a/engine/battle/core.asm +++ b/engine/battle/core.asm @@ -157,6 +157,9 @@ SlidePlayerAndEnemySilhouettesOnScreen: ld [rBGP], a ld [rOBP0], a ld [rOBP1], a + call UpdateGBCPal_BGP + call UpdateGBCPal_OBP0 + call UpdateGBCPal_OBP1 .slideSilhouettesLoop ; slide silhouettes of the player's pic and the enemy's pic onto the screen ld h, b ld l, $40 @@ -246,10 +249,16 @@ StartBattle: call DelayFrames call SaveScreenTilesToBuffer1 .checkAnyPartyAlive + ld a, [wBattleType] + cp BATTLE_TYPE_RUN + jp z, .specialBattle + cp BATTLE_TYPE_PIKACHU + jp z, .specialBattle call AnyPartyAlive ld a, d and a jp z, HandlePlayerBlackOut ; jump if no mon is alive +.specialBattle call LoadScreenTilesFromBuffer1 ld a, [wBattleType] and a ; is it a normal battle? @@ -983,6 +992,11 @@ ReplaceFaintedEnemyMon: ld hl, wEnemyHPBarColor ld e, $30 call GetBattleHealthBarColor + setpal SHADE_BLACK, SHADE_DARK, SHADE_LIGHT, SHADE_WHITE + ld [rOBP0], a + ld [rOBP1], a + call UpdateGBCPal_OBP0 + call UpdateGBCPal_OBP1 callab DrawEnemyPokeballs ld a, [wLinkState] cp LINK_STATE_BATTLING @@ -1048,9 +1062,7 @@ TrainerDefeatedText: PlayBattleVictoryMusic: push af - ld a, $ff - ld [wNewSoundID], a - call PlaySoundWaitForCurrent + call StopAllMusic ld c, BANK(Music_DefeatedTrainer) pop af call PlayMusic @@ -1104,6 +1116,7 @@ RemoveFaintedPlayerMon: ld a, $ff ld [wLowHealthAlarm], a ;disable low health alarm call WaitForSoundToFinish + xor a .skipWaitForSound ; a is 0, so this zeroes the enemy's accumulated damage. ld hl, wEnemyBideAccumulatedDamage @@ -1128,10 +1141,36 @@ RemoveFaintedPlayerMon: and a ; was this called by HandleEnemyMonFainted? ret z ; if so, return + ld a, [wPlayerMonNumber] + ld [wWhichPokemon], a + callab IsThisPartymonStarterPikachu_Party + jr nc, .notPlayerPikachu + ld e, $3 + callab PlayPikachuSoundClip + jr .printText +.notPlayerPikachu ld a, [wBattleMonSpecies] call PlayCry +.printText ld hl, PlayerMonFaintedText - jp PrintText + call PrintText + ld a, [wPlayerMonNumber] + ld [wWhichPokemon], a + ld a, [wBattleMonLevel] + ld b, a + ld a, [wEnemyMonLevel] + sub b ; enemylevel - playerlevel + ; are we stronger than the opposing pokemon? + jr c, .regularFaint ; if so, deduct happiness regularly + + cp 30 ; is the enemy 30 levels greater than us? + jr nc, .carelessTrainer ; if so, punish the player for being careless, as they shouldn't be fighting a very high leveled trainer with such a level difference +.regularFaint + callabd_ModifyPikachuHappiness PIKAHAPPY_FAINTED + ret +.carelessTrainer + callabd_ModifyPikachuHappiness PIKAHAPPY_CARELESSTRAINER + ret PlayerMonFaintedText: TX_FAR _PlayerMonFaintedText @@ -1188,7 +1227,7 @@ ChooseNextMon: ld a, [wLinkState] cp LINK_STATE_BATTLING jr nz, .notLinkBattle - inc a + ld a, 1 ld [wActionResultOrTookBattleTurn], a call LinkBattleExchangeData .notLinkBattle @@ -1588,6 +1627,8 @@ TryRunningFromBattle: ld a, [wBattleType] cp BATTLE_TYPE_SAFARI jp z, .canEscape ; jump if it's a safari battle + cp BATTLE_TYPE_RUN + jp z, .canEscape ; hurry, get away? ld a, [wLinkState] cp LINK_STATE_BATTLING jp z, .canEscape @@ -1843,19 +1884,46 @@ SendOutMon: call RunPaletteCommand ld hl, wEnemyBattleStatus1 res USING_TRAPPING_MOVE, [hl] + callab IsThisPartymonStarterPikachu + jr c, .starterPikachu ld a, $1 ld [H_WHOSETURN], a ld a, POOF_ANIM call PlayMoveAnimation coord hl, 4, 11 predef AnimateSendingOutMon + jr .playRegularCry +.starterPikachu + xor a + ld [H_WHOSETURN], a + ld a, $1 + ld [H_AUTOBGTRANSFERENABLED], a + callab StarterPikachuBattleEntranceAnimation + callab IsPlayerPikachuAsleepInParty + ld e, $24 + jr c, .asm_3cd81 + ld e, $a +.asm_3cd81 + callab PlayPikachuSoundClip + jr .done +.playRegularCry ld a, [wcf91] call PlayCry +.done call PrintEmptyString jp SaveScreenTilesToBuffer1 ; show 2 stages of the player mon getting smaller before disappearing AnimateRetreatingPlayerMon: + ld a, [wWhichPokemon] + push af + ld a, [wPlayerMonNumber] + ld [wWhichPokemon], a + callab IsThisPartymonStarterPikachu + pop bc + ld a, b + ld [wWhichPokemon], a + jr c, .starterPikachu coord hl, 1, 5 lb bc, 7, 7 call ClearScreenArea @@ -1879,10 +1947,17 @@ AnimateRetreatingPlayerMon: call .clearScreenArea ld a, $4c Coorda 5, 11 + jr .clearScreenArea +.starterPikachu + xor a + ld [H_WHOSETURN], a + callab AnimationSlideMonOff + ret .clearScreenArea coord hl, 1, 5 lb bc, 7, 7 - jp ClearScreenArea + call ClearScreenArea + ret ; reads player's current mon's HP into wBattleMonHP ReadPlayerMonCurHPAndStatus: @@ -2104,36 +2179,49 @@ DisplayBattleMenu: ld [wTextBoxID], a call DisplayTextBoxID ld a, [wBattleType] - dec a - jp nz, .handleBattleMenuInput ; handle menu input if it's not the old man tutorial -; the following happens for the old man tutorial + cp BATTLE_TYPE_OLD_MAN + jr z, .doSimulatedMenuInput ; simulate menu input if it's the old man or prof. oak pikachu battle + cp BATTLE_TYPE_PIKACHU + jr z, .doSimulatedMenuInput + jp .handleBattleMenuInput +; the following happens for the old man tutorial and prof. oak pikachu battle +.doSimulatedMenuInput ld hl, wPlayerName ld de, wGrassRate ld bc, NAME_LENGTH call CopyData ; temporarily save the player name in unused space, ; which is supposed to get overwritten when entering a - ; map with wild Pokémon. Due to an oversight, the data + ; map with wild Pokémon. + ; In Red/Blue, due to an oversight, the data ; may not get overwritten (cinnabar) and the infamous - ; Missingno. glitch can show up. + ; Missingno. glitch can show up. However, + ; this has been fixed in yellow ld hl, .oldManName + ld a, [wBattleType] + dec a + jr z, .useOldManName + ld hl, .profOakName +.useOldManName ld de, wPlayerName ld bc, NAME_LENGTH call CopyData ; the following simulates the keystrokes by drawing menus on screen coord hl, 9, 14 ld [hl], "▶" - ld c, 80 + ld c, 20 call DelayFrames ld [hl], " " coord hl, 9, 16 ld [hl], "▶" - ld c, 50 + ld c, 20 call DelayFrames ld [hl], "▷" ld a, $2 ; select the "ITEM" menu jp .upperLeftMenuItemWasNotSelected .oldManName db "OLD MAN@" +.profOakName + db "PROF.OAK@" .handleBattleMenuInput ld a, [wBattleAndStartSavedMenuItem] ld [wCurrentMenuItem], a @@ -2216,6 +2304,9 @@ DisplayBattleMenu: .AButtonPressed call PlaceUnfilledArrowMenuCursor ld a, [wBattleType] + cp BATTLE_TYPE_RUN + jr z, .handleUnusedBattle + ld a, [wBattleType] cp BATTLE_TYPE_SAFARI ld a, [wCurrentMenuItem] ld [wBattleAndStartSavedMenuItem], a @@ -2247,7 +2338,18 @@ DisplayBattleMenu: .throwSafariBallWasSelected ld a, SAFARI_BALL ld [wcf91], a - jr UseBagItem + jp UseBagItem +.handleUnusedBattle + ld a, [wCurrentMenuItem] + cp $3 + jp z, BattleMenu_RunWasSelected + ld hl, .RunAwayText + call PrintText + jp DisplayBattleMenu + +.RunAwayText + TX_FAR _RunAwayText + db "@" .upperLeftMenuItemWasNotSelected ; a menu item other than the upper left item was selected cp $2 @@ -2284,19 +2386,23 @@ BagWasSelected: call DrawHUDsAndHPBars .next ld a, [wBattleType] - dec a ; is it the old man tutorial? - jr nz, DisplayPlayerBag ; no, it is a normal battle - ld hl, OldManItemList + cp BATTLE_TYPE_OLD_MAN ; is it the old man tutorial? + jr z, .simulatedInputBattle + cp BATTLE_TYPE_PIKACHU ; is it the prof oak battle with pikachu? + jr z, .simulatedInputBattle + jr DisplayPlayerBag +.simulatedInputBattle + ld hl, SimulatedInputBattleItemList ld a, l ld [wListPointer], a ld a, h ld [wListPointer + 1], a jr DisplayBagMenu -OldManItemList: - db 1 ; # items - db POKE_BALL, 50 - db -1 +SimulatedInputBattleItemList: + db 1 ; # of items + db POKE_BALL, 1 + db $ff DisplayPlayerBag: ; get the pointer to player's bag when in a normal battle @@ -2455,6 +2561,8 @@ PartyMenuOrRockOrRun: predef StatusScreen predef StatusScreen2 ; now we need to reload the enemy mon pic + ld a, 1 + ld [H_WHOSETURN], a ld a, [wEnemyBattleStatus2] bit HAS_SUBSTITUTE_UP, a ; does the enemy mon have a substitute? ld hl, AnimationSubstitute @@ -2559,13 +2667,13 @@ MoveSelectionMenu: .writemoves ld de, wMovesString - ld a, [hFlags_0xFFF6] + ld a, [hFlags_0xFFFA] set 2, a - ld [hFlags_0xFFF6], a + ld [hFlags_0xFFFA], a call PlaceString - ld a, [hFlags_0xFFF6] + ld a, [hFlags_0xFFFA] res 2, a - ld [hFlags_0xFFF6], a + ld [hFlags_0xFFFA], a ret .regularmenu @@ -2574,9 +2682,8 @@ MoveSelectionMenu: ld hl, wBattleMonMoves call .loadmoves coord hl, 4, 12 - ld b, 4 - ld c, 14 - di ; out of pure coincidence, it is possible for vblank to occur between the di and ei + lb bc, 4, 14 + di ; out of pure coincidence, it is possible for vblank to occur between the di and ei ; so it is necessary to put the di ei block to not cause tearing call TextBoxBorder coord hl, 4, 12 @@ -2593,8 +2700,7 @@ MoveSelectionMenu: ld hl, wEnemyMonMoves call .loadmoves coord hl, 0, 7 - ld b, 4 - ld c, 14 + lb bc, 4, 14 call TextBoxBorder coord hl, 2, 8 call .writemoves @@ -2608,8 +2714,7 @@ MoveSelectionMenu: call AddNTimes call .loadmoves coord hl, 4, 7 - ld b, 4 - ld c, 14 + lb bc, 4, 14 call TextBoxBorder coord hl, 6, 8 call .writemoves @@ -2623,8 +2728,6 @@ MoveSelectionMenu: ld a, [wMoveMenuType] cp $1 jr z, .selectedmoveknown - ld a, $1 - jr nc, .selectedmoveknown ld a, [wPlayerMoveListIndex] inc a .selectedmoveknown @@ -2685,10 +2788,10 @@ SelectMenuItem: call AddNTimes ld [hl], "▷" .select - ld hl, hFlags_0xFFF6 + ld hl, hFlags_0xFFFA set 1, [hl] call HandleMenuInput - ld hl, hFlags_0xFFF6 + ld hl, hFlags_0xFFFA res 1, [hl] bit 6, a jp nz, SelectMenuItem_CursorUp ; up @@ -2790,6 +2893,55 @@ SelectMenuItem_CursorDown: ld [wCurrentMenuItem], a jp SelectMenuItem +Func_3d4f5: + bit 3, a + ld a, $0 + jr nz, .asm_3d4fd + ld a, $1 +.asm_3d4fd + ld [H_WHOSETURN], a + call LoadScreenTilesFromBuffer1 + call Func_3d536 + ld a, [wTestBattlePlayerSelectedMove] + and a + jp z, MoveSelectionMenu + ld [wAnimationID], a + xor a + ld [wAnimationType], a + predef MoveAnimation + callab Func_78e98 + jp MoveSelectionMenu + +Func_3d523: + ld a, [wTestBattlePlayerSelectedMove] + dec a + jr asm_3d52d +Func_3d529: + ld a, [wTestBattlePlayerSelectedMove] + inc a +asm_3d52d: + ld [wTestBattlePlayerSelectedMove], a + call Func_3d536 + jp MoveSelectionMenu + +Func_3d536: + coord hl, 10, 16 + lb bc, 2, 10 + call ClearScreenArea + coord hl, 10, 17 + ld de, wTestBattlePlayerSelectedMove + lb bc, LEADING_ZEROES | 1, 3 + call PrintNumber + ld a, [wTestBattlePlayerSelectedMove] + and a + ret z + cp STRUGGLE + ret nc + ld [wd11e], a + call GetMoveName + coord hl, 13, 17 + jp PlaceString + AnyMoveToSelect: ; return z and Struggle as the selected move if all moves have 0 PP and/or are disabled ld a, STRUGGLE @@ -2823,7 +2975,10 @@ AnyMoveToSelect: or c jr .handleDisabledMovePPLoop .allMovesChecked - and a ; any PP left? +; bugfix: only check PP value and not PP up bits +; in case all other moves have no PP left and a move has a PP up used on it +; and a non-PP up move is disabled + and $3f ; any PP left? ret nz ; return if a move has PP left .noMovesLeft ld hl, NoMovesLeftText @@ -2838,6 +2993,9 @@ NoMovesLeftText: db "@" SwapMovesInMenu: + ld a, [wPlayerBattleStatus3] + bit TRANSFORMED, a + jp nz, MoveSelectionMenu ld a, [wMenuItemToSwap] and a jr z, .noMenuItemSelected @@ -2917,8 +3075,7 @@ PrintMenuItem: xor a ld [H_AUTOBGTRANSFERENABLED], a coord hl, 0, 8 - ld b, 3 - ld c, 9 + lb bc, 3, 9 call TextBoxBorder ld a, [wPlayerDisabledMove] and a @@ -2985,7 +3142,7 @@ PrintMenuItem: jp Delay3 DisabledText: - db "disabled!@" + db "Disabled!@" TypeText: db "TYPE@" @@ -3905,11 +4062,13 @@ DetermineExclamationPointTextNum: ret ExclamationPointMoveSets: +; a grammar mistake was fixed (only concerning japanese) +; BIDE is in category 3, moved from category 2 db SWORDS_DANCE, GROWTH db $00 - db RECOVER, BIDE, SELFDESTRUCT, AMNESIA + db RECOVER, SELFDESTRUCT, AMNESIA db $00 - db MEDITATE, AGILITY, TELEPORT, MIMIC, DOUBLE_TEAM, BARRAGE + db MEDITATE, AGILITY, TELEPORT, MIMIC, DOUBLE_TEAM, BIDE, BARRAGE db $00 db POUND, SCRATCH, VICEGRIP, WING_ATTACK, FLY, BIND, SLAM, HORN_ATTACK, BODY_SLAM db WRAP, THRASH, TAIL_WHIP, LEER, BITE, GROWL, ROAR, SING, PECK, COUNTER @@ -4593,31 +4752,31 @@ CalculateDamage: ld a, [H_QUOTIENT + 3] add b ld [H_QUOTIENT + 3], a - jr nc, .asm_3dfd0 + jr nc, .asm_3e142 ld a, [H_QUOTIENT + 2] inc a ld [H_QUOTIENT + 2], a and a - jr z, .asm_3e004 + jr z, .asm_3e176 -.asm_3dfd0 +.asm_3e142 ld a, [H_QUOTIENT] ld b, a ld a, [H_QUOTIENT + 1] or a - jr nz, .asm_3e004 + jr nz, .asm_3e176 ld a, [H_QUOTIENT + 2] cp 998 / $100 - jr c, .asm_3dfe8 + jr c, .asm_3e15a cp 998 / $100 + 1 - jr nc, .asm_3e004 + jr nc, .asm_3e176 ld a, [H_QUOTIENT + 3] cp 998 % $100 - jr nc, .asm_3e004 + jr nc, .asm_3e176 -.asm_3dfe8 +.asm_3e15a inc hl ld a, [H_QUOTIENT + 3] ld b, [hl] @@ -4628,26 +4787,26 @@ CalculateDamage: ld b, [hl] adc b ld [hl], a - jr c, .asm_3e004 + jr c, .asm_3e176 ld a, [hl] cp 998 / $100 - jr c, .asm_3e00a + jr c, .asm_3e17c cp 998 / $100 + 1 - jr nc, .asm_3e004 + jr nc, .asm_3e176 inc hl ld a, [hld] cp 998 % $100 - jr c, .asm_3e00a + jr c, .asm_3e17c -.asm_3e004 +.asm_3e176 ; cap at 997 ld a, 997 / $100 ld [hli], a ld a, 997 % $100 ld [hld], a -.asm_3e00a +.asm_3e17c ; add 2 inc hl ld a, [hl] @@ -4677,7 +4836,7 @@ UnusedHighCriticalMoves: db $FF ; determines if attack is a critical hit -; azure heights claims "the fastest pokémon (who are,not coincidentally, +; azure heights claims "the fastest pokémon (who are, not coincidentally, ; among the most popular) tend to CH about 20 to 25% of the time." CriticalHitTest: xor a @@ -5098,7 +5257,7 @@ AttackSubstitute: ld a, [H_WHOSETURN] xor $01 ld [H_WHOSETURN], a - callab HideSubstituteShowMonAnim ; animate the substitute breaking + callab Func_79929 ; animate the substitute breaking ; flip the turn back to the way it was ld a, [H_WHOSETURN] xor $01 @@ -5395,32 +5554,26 @@ AdjustDamageForMoveType: .done ret -; function to tell how effective the type of an enemy attack is on the player's current pokemon -; this doesn't take into account the effects that dual types can have -; (e.g. 4x weakness / resistance, weaknesses and resistances canceling) -; the result is stored in [wTypeEffectiveness] -; ($05 is not very effective, $10 is neutral, $14 is super effective) -; as far is can tell, this is only used once in some AI code to help decide which move to use AIGetTypeEffectiveness: ld a, [wEnemyMoveType] - ld d, a ; d = type of enemy move + ld d, a ; d = type of enemy move ld hl, wBattleMonType - ld b, [hl] ; b = type 1 of player's pokemon + ld b, [hl] ; b = type 1 of player's pokemon inc hl - ld c, [hl] ; c = type 2 of player's pokemon + ld c, [hl] ; c = type 2 of player's pokemon ld a, $10 - ld [wTypeEffectiveness], a ; initialize to neutral effectiveness + ld [wd11e], a ; initialize [wd11e] to neutral effectiveness ld hl, TypeEffects .loop ld a, [hli] cp $ff ret z - cp d ; match the type of the move + cp d ; match the type of the move jr nz, .nextTypePair1 ld a, [hli] - cp b ; match with type 1 of pokemon + cp b ; match with type 1 of pokemon jr z, .done - cp c ; or match with type 2 of pokemon + cp c ; or match with type 2 of pokemon jr z, .done jr .nextTypePair2 .nextTypePair1 @@ -5428,9 +5581,21 @@ AIGetTypeEffectiveness: .nextTypePair2 inc hl jr .loop + .done + ld a, [wTrainerClass] + cp LORELEI + jr nz, .ok + ld a, [wEnemyMonSpecies] + cp DEWGONG + jr nz, .ok + call BattleRandom + cp $66 ; 40 percent + ret c +.ok + ld a, [hl] - ld [wTypeEffectiveness], a ; store damage multiplier + ld [wd11e], a ; store damage multiplier ret INCLUDE "data/type_effects.asm" @@ -6409,10 +6574,13 @@ SwapPlayerAndEnemyLevels: ; (for use when scrolling the player sprite and enemy's silhouettes on screen) LoadPlayerBackPic: ld a, [wBattleType] - dec a ; is it the old man tutorial? - ld de, RedPicBack - jr nz, .next ld de, OldManPic + cp BATTLE_TYPE_OLD_MAN ; is it the old man tutorial? + jr z, .next + ld de, ProfOakPicBack + cp BATTLE_TYPE_PIKACHU ; is it the pikachu battle at the beginning of the game? + jr z, .next + ld de, RedPicBack .next ld a, BANK(RedPicBack) call UncompressSpriteFromDE @@ -6437,6 +6605,8 @@ LoadPlayerBackPic: ld [hli], a ; OAM tile number inc a ; increment tile number ld [hOAMTile], a + ld a, $2 + ld [hl], a inc hl dec c jr nz, .innerLoop @@ -6450,18 +6620,15 @@ LoadPlayerBackPic: jr nz, .loop ld de, vBackPic call InterlaceMergeSpriteBuffers - ld a, $a - ld [$0], a - xor a - ld [$4000], a + ld a, $0 + call SwitchSRAMBankAndLatchClockData ld hl, vSprites ld de, sSpriteBuffer1 ld a, [H_LOADEDROMBANK] ld b, a ld c, 7 * 7 call CopyVideoData - xor a - ld [$0], a + call PrepareRTCDataAndDisableSRAM ld a, $31 ld [hStartTileID], a coord hl, 1, 5 @@ -6832,292 +6999,10 @@ HandleExplodingAnimation: PlayMoveAnimation: ld [wAnimationID], a call Delay3 - predef_jump MoveAnimation - -InitBattle: - ld a, [wCurOpponent] - and a - jr z, DetermineWildOpponent - -InitOpponent: - ld a, [wCurOpponent] - ld [wcf91], a - ld [wEnemyMonSpecies2], a - jr InitBattleCommon - -DetermineWildOpponent: - ld a, [wd732] - bit 1, a - jr z, .asm_3ef2f - ld a, [hJoyHeld] - bit 1, a ; B button pressed? - ret nz -.asm_3ef2f - ld a, [wNumberOfNoRandomBattleStepsLeft] - and a - ret nz - callab TryDoWildEncounter - ret nz -InitBattleCommon: - ld a, [wMapPalOffset] - push af - ld hl, wLetterPrintingDelayFlags - ld a, [hl] - push af - res 1, [hl] - callab InitBattleVariables - ld a, [wEnemyMonSpecies2] - sub OPP_ID_OFFSET - jp c, InitWildBattle - ld [wTrainerClass], a - call GetTrainerInformation - callab ReadTrainer - call DoBattleTransitionAndInitBattleVariables - call _LoadTrainerPic - xor a - ld [wEnemyMonSpecies2], a - ld [hStartTileID], a - dec a - ld [wAICount], a - coord hl, 12, 0 - predef CopyUncompressedPicToTilemap - ld a, $ff - ld [wEnemyMonPartyPos], a - ld a, $2 - ld [wIsInBattle], a - jp _InitBattleCommon - -InitWildBattle: - ld a, $1 - ld [wIsInBattle], a - call LoadEnemyMonData - call DoBattleTransitionAndInitBattleVariables - ld a, [wCurOpponent] - cp MAROWAK - jr z, .isGhost - call IsGhostBattle - jr nz, .isNoGhost -.isGhost - ld hl, wMonHSpriteDim - ld a, $66 - ld [hli], a ; write sprite dimensions - ld bc, GhostPic - ld a, c - ld [hli], a ; write front sprite pointer - ld [hl], b - ld hl, wEnemyMonNick ; set name to "GHOST" - ld a, "G" - ld [hli], a - ld a, "H" - ld [hli], a - ld a, "O" - ld [hli], a - ld a, "S" - ld [hli], a - ld a, "T" - ld [hli], a - ld [hl], "@" - ld a, [wcf91] - push af - ld a, MON_GHOST - ld [wcf91], a - ld de, vFrontPic - call LoadMonFrontSprite ; load ghost sprite - pop af - ld [wcf91], a - jr .spriteLoaded -.isNoGhost - ld de, vFrontPic - call LoadMonFrontSprite ; load mon sprite -.spriteLoaded - xor a - ld [wTrainerClass], a - ld [hStartTileID], a - coord hl, 12, 0 - predef CopyUncompressedPicToTilemap - -; common code that executes after init battle code specific to trainer or wild battles -_InitBattleCommon: - ld b, SET_PAL_BATTLE_BLACK - call RunPaletteCommand - call SlidePlayerAndEnemySilhouettesOnScreen - xor a - ld [H_AUTOBGTRANSFERENABLED], a - ld hl, .emptyString - call PrintText - call SaveScreenTilesToBuffer1 - call ClearScreen - ld a, $98 - ld [H_AUTOBGTRANSFERDEST + 1], a - ld a, $1 - ld [H_AUTOBGTRANSFERENABLED], a - call Delay3 - ld a, $9c - ld [H_AUTOBGTRANSFERDEST + 1], a - call LoadScreenTilesFromBuffer1 - coord hl, 9, 7 - lb bc, 5, 10 - call ClearScreenArea - coord hl, 1, 0 - lb bc, 4, 10 - call ClearScreenArea - call ClearSprites - ld a, [wIsInBattle] - dec a ; is it a wild battle? - call z, DrawEnemyHUDAndHPBar ; draw enemy HUD and HP bar if it's a wild battle - call StartBattle - callab EndOfBattle - pop af - ld [wLetterPrintingDelayFlags], a - pop af - ld [wMapPalOffset], a - ld a, [wSavedTilesetType] - ld [hTilesetType], a - scf - ret -.emptyString - db "@" - -_LoadTrainerPic: -; wd033-wd034 contain pointer to pic - ld a, [wTrainerPicPointer] - ld e, a - ld a, [wTrainerPicPointer + 1] - ld d, a ; de contains pointer to trainer pic - ld a, [wLinkState] - and a - ld a, Bank(TrainerPics) ; this is where all the trainer pics are (not counting Red's) - jr z, .loadSprite - ld a, Bank(RedPicFront) -.loadSprite - call UncompressSpriteFromDE - ld de, vFrontPic - ld a, $77 - ld c, a - jp LoadUncompressedSpriteData - -; unreferenced -ResetCryModifiers: - xor a - ld [wFrequencyModifier], a - ld [wTempoModifier], a - jp PlaySound - -; animates the mon "growing" out of the pokeball -AnimateSendingOutMon: - ld a, [wPredefRegisters] - ld h, a - ld a, [wPredefRegisters + 1] - ld l, a - ld a, [hStartTileID] - ld [hBaseTileID], a - ld b, $4c - ld a, [wIsInBattle] - and a - jr z, .notInBattle - add b - ld [hl], a - call Delay3 - ld bc, -(SCREEN_WIDTH * 2 + 1) - add hl, bc - ld a, 1 - ld [wDownscaledMonSize], a - lb bc, 3, 3 - predef CopyDownscaledMonTiles - ld c, 4 - call DelayFrames - ld bc, -(SCREEN_WIDTH * 2 + 1) - add hl, bc - xor a - ld [wDownscaledMonSize], a - lb bc, 5, 5 - predef CopyDownscaledMonTiles - ld c, 5 - call DelayFrames - ld bc, -(SCREEN_WIDTH * 2 + 1) - jr .next -.notInBattle - ld bc, -(SCREEN_WIDTH * 6 + 3) -.next - add hl, bc - ld a, [hBaseTileID] - add $31 - jr CopyUncompressedPicToHL - -CopyUncompressedPicToTilemap: - ld a, [wPredefRegisters] - ld h, a - ld a, [wPredefRegisters + 1] - ld l, a - ld a, [hStartTileID] -CopyUncompressedPicToHL: - lb bc, 7, 7 - ld de, SCREEN_WIDTH - push af - ld a, [wSpriteFlipped] - and a - jr nz, .flipped - pop af -.loop - push bc - push hl -.innerLoop - ld [hl], a - add hl, de - inc a - dec c - jr nz, .innerLoop - pop hl - inc hl - pop bc - dec b - jr nz, .loop - ret - -.flipped - push bc - ld b, 0 - dec c - add hl, bc - pop bc - pop af -.flippedLoop - push bc - push hl -.flippedInnerLoop - ld [hl], a - add hl, de - inc a - dec c - jr nz, .flippedInnerLoop - pop hl - dec hl - pop bc - dec b - jr nz, .flippedLoop + predef MoveAnimation + callab Func_78e98 ret -LoadMonBackPic: -; Assumes the monster's attributes have -; been loaded with GetMonHeader. - ld a, [wBattleMonSpecies2] - ld [wcf91], a - coord hl, 1, 5 - ld b, 7 - ld c, 8 - call ClearScreenArea - ld hl, wMonHBackSprite - wMonHeader - call UncompressMonSprite - predef ScaleSpriteByTwo - ld de, vBackPic - call InterlaceMergeSpriteBuffers ; combine the two buffers to a single 2bpp sprite - ld hl, vSprites - ld de, vBackPic - ld c, (2*SPRITEBUFFERSIZE)/16 ; count of 16-byte chunks to be copied - ld a, [H_LOADEDROMBANK] - ld b, a - jp CopyVideoData - JumpMoveEffect: call _JumpMoveEffect ld b, $1 @@ -7266,6 +7151,16 @@ SleepEffect: call BattleRandom and $7 jr z, .setSleepCounter + ld b, a + ld a, [wUnknownSerialFlag_d499] + and a + jr z, .asm_3f1ba ; XXX stadium stuff? + ld a, b + and $3 + jr z, .setSleepCounter + ld b, a +.asm_3f1ba + ld a, b ld [de], a call PlayCurrentMoveAnimation2 ld hl, FellAsleepText @@ -7404,7 +7299,7 @@ FreezeBurnParalyzeEffect: ret nz ; return if they have a substitute, can't effect them ld a, [H_WHOSETURN] and a - jp nz, opponentAttacker + jp nz, .opponentAttacker ld a, [wEnemyMonStatus] and a jp nz, CheckDefrost ; can't inflict status if opponent is already statused @@ -7417,7 +7312,17 @@ FreezeBurnParalyzeEffect: cp b ; do target type 2 and move type match? ret z ; return if they match ld a, [wPlayerMoveEffect] - cp PARALYZE_SIDE_EFFECT1 + 1 ; 10% status effects are 04, 05, 06 so 07 will set carry for those + cp UNUSED_EFFECT_23 ; more stadium stuff + jr nz, .asm_3f2c7 + ld a, [wUnknownSerialFlag_d499] + and a + ld a, FREEZE_SIDE_EFFECT + ld b, $4d ; else use 0x4D/0x100 or 77/256 = 30.1%~ chance + jr z, .next1 + ld b, $1a ; 0x1A/0x100 or 26/256 = 10.2%~ chance + jr .next1 +.asm_3f2c7 + cp a, PARALYZE_SIDE_EFFECT1 + 1 ; 10% status effects are 04, 05, 06 so 07 will set carry for those ld b, $1a ; 0x1A/0x100 or 26/256 = 10.2%~ chance jr c, .next1 ; branch ahead if this is a 10% chance effect.. ld b, $4d ; else use 0x4D/0x100 or 77/256 = 30.1%~ chance @@ -7430,9 +7335,9 @@ FreezeBurnParalyzeEffect: ret nc ; do nothing if random value is >= 1A or 4D [no status applied] ld a, b ; what type of effect is this? cp BURN_SIDE_EFFECT1 - jr z, .burn + jr z, .burn1 cp FREEZE_SIDE_EFFECT - jr z, .freeze + jr z, .freeze1 ; .paralyze ld a, 1 << PAR ld [wEnemyMonStatus], a @@ -7440,7 +7345,7 @@ FreezeBurnParalyzeEffect: ld a, ANIM_A9 call PlayBattleAnimation jp PrintMayNotAttackText ; print paralysis text -.burn +.burn1 ld a, 1 << BRN ld [wEnemyMonStatus], a call HalveAttackDueToBurn ; halve attack of affected mon @@ -7448,7 +7353,7 @@ FreezeBurnParalyzeEffect: call PlayBattleAnimation ld hl, BurnedText jp PrintText -.freeze +.freeze1 call ClearHyperBeam ; resets hyper beam (recharge) condition from target ld a, 1 << FRZ ld [wEnemyMonStatus], a @@ -7456,7 +7361,7 @@ FreezeBurnParalyzeEffect: call PlayBattleAnimation ld hl, FrozenText jp PrintText -opponentAttacker: +.opponentAttacker ld a, [wBattleMonStatus] ; mostly same as above with addresses swapped for opponent and a jp nz, CheckDefrost @@ -7469,12 +7374,22 @@ opponentAttacker: cp b ret z ld a, [wEnemyMoveEffect] - cp PARALYZE_SIDE_EFFECT1 + 1 + cp UNUSED_EFFECT_23 ; more stadium stuff + jr nz, .asm_3f341 + ld a, [wUnknownSerialFlag_d499] + and a + ld a, FREEZE_SIDE_EFFECT + ld b, $4d ; else use 0x4D/0x100 or 77/256 = 30.1%~ chance + jr z, .next2 + ld b, $1a ; 0x1A/0x100 or 26/256 = 10.2%~ chance + jr .next2 +.asm_3f341 + cp a, PARALYZE_SIDE_EFFECT1 + 1 ld b, $1a - jr c, .next1 + jr c, .next2 ld b, $4d sub $1e -.next1 +.next2 push af call BattleRandom cp b @@ -7482,23 +7397,29 @@ opponentAttacker: ret nc ld a, b cp BURN_SIDE_EFFECT1 - jr z, .burn + jr z, .burn2 cp FREEZE_SIDE_EFFECT - jr z, .freeze + jr z, .freeze2 ld a, 1 << PAR ld [wBattleMonStatus], a call QuarterSpeedDueToParalysis + ld a, ANIM_C7 + call PlayBattleAnimation2 jp PrintMayNotAttackText -.burn +.burn2 ld a, 1 << BRN ld [wBattleMonStatus], a call HalveAttackDueToBurn + ld a, ANIM_C7 + call PlayBattleAnimation2 ld hl, BurnedText jp PrintText -.freeze +.freeze2 ; hyper beam bits aren't reseted for opponent's side ld a, 1 << FRZ ld [wBattleMonStatus], a + ld a, ANIM_C7 + call PlayBattleAnimation2 ld hl, FrozenText jp PrintText @@ -7663,25 +7584,25 @@ UpdateStatDone: ld bc, wPlayerMonMinimized ld a, [H_WHOSETURN] and a - jr z, .asm_3f4e6 + jr z, .playerTurn ld hl, wEnemyBattleStatus2 ld de, wEnemyMoveNum ld bc, wEnemyMonMinimized -.asm_3f4e6 +.playerTurn ld a, [de] cp MINIMIZE - jr nz, .asm_3f4f9 + jr nz, .notMinimize ; if a substitute is up, slide off the substitute and show the mon pic before ; playing the minimize animation bit HAS_SUBSTITUTE_UP, [hl] push af push bc + push de ld hl, HideSubstituteShowMonAnim ld b, BANK(HideSubstituteShowMonAnim) - push de call nz, Bankswitch pop de -.asm_3f4f9 +.notMinimize call PlayCurrentMoveAnimation ld a, [de] cp MINIMIZE @@ -8199,6 +8120,9 @@ FlinchSideEffect: ld hl, wPlayerBattleStatus1 ld de, wEnemyMoveEffect .flinchSideEffect + ld a, [wLinkState] + cp LINK_STATE_BATTLING + call z, ClearHyperBeam ld a, [de] cp FLINCH_SIDE_EFFECT1 ld b, $1a ; ~10% chance of flinch @@ -8240,10 +8164,27 @@ ChargeEffect: set INVULNERABLE, [hl] ; mon is now invulnerable to typical attacks (fly/dig) ld b, ANIM_C0 .notDigOrFly + push de + push bc + inc hl ; battle status 2 + push hl + ld a, [hl] + bit HAS_SUBSTITUTE_UP, a + ld hl, HideSubstituteShowMonAnim + ld b, BANK(HideSubstituteShowMonAnim) + call nz, Bankswitch + pop hl + pop bc xor a ld [wAnimationType], a ld a, b call PlayBattleAnimation + ld a, [hl] + bit HAS_SUBSTITUTE_UP, a + ld hl, ReshowSubstituteAnim + ld b, BANK(ReshowSubstituteAnim) + call nz, Bankswitch + pop de ld a, [de] ld [wChargeMoveNum], a ld hl, ChargeMoveEffectText @@ -8713,6 +8654,7 @@ PlayBattleAnimationGotID: push de push bc predef MoveAnimation + callab Func_78e98 pop bc pop de pop hl diff --git a/engine/battle/draw_hud_pokeball_gfx.asm b/engine/battle/draw_hud_pokeball_gfx.asm index 323dd167..96294774 100644 --- a/engine/battle/draw_hud_pokeball_gfx.asm +++ b/engine/battle/draw_hud_pokeball_gfx.asm @@ -27,6 +27,8 @@ SetupOwnPartyPokeballs: ld [hl], a ld a, 8 ld [wHUDPokeballGfxOffsetX], a + xor a + ld [wdef5], a ld hl, wOAMBuffer jp WritePokeballOAMData @@ -41,6 +43,8 @@ SetupEnemyPartyPokeballs: ld [hl], $20 ld a, -8 ld [wHUDPokeballGfxOffsetX], a + ld a, $1 + ld [wdef5], a ld hl, wOAMBuffer + PARTY_LENGTH * 4 jp WritePokeballOAMData @@ -104,7 +108,7 @@ WritePokeballOAMData: ld [hli], a ld a, [de] ld [hli], a - xor a + ld a, [wdef5] ld [hli], a ld a, [wBaseCoordX] ld b, a @@ -174,6 +178,8 @@ SetupPlayerAndEnemyPokeballs: ld [hl], $40 ld a, 8 ld [wHUDPokeballGfxOffsetX], a + xor a + ld [wdef5], a ld hl, wOAMBuffer call WritePokeballOAMData ld hl, wEnemyMons @@ -183,6 +189,8 @@ SetupPlayerAndEnemyPokeballs: ld a, $50 ld [hli], a ld [hl], $68 + ld a, $1 + ld [wdef5], a ld hl, wOAMBuffer + $18 jp WritePokeballOAMData diff --git a/engine/battle/end_of_battle.asm b/engine/battle/end_of_battle.asm index 830a23a1..5c0c3991 100755 --- a/engine/battle/end_of_battle.asm +++ b/engine/battle/end_of_battle.asm @@ -10,6 +10,8 @@ EndOfBattle: ld a, [wEnemyMonStatus] ld [hl], a call ClearScreen + ld b, SET_PAL_OVERWORLD + call RunPaletteCommand callab DisplayLinkBattleVersusTextBox ld a, [wBattleResult] cp $1 @@ -43,6 +45,8 @@ EndOfBattle: xor a ld [wForceEvolution], a predef EvolutionAfterBattle + ld d, $82 + callab UpdatePikachuMoodAfterBattle .resetVariables xor a ld [wLowHealthAlarm], a ;disable low health alarm diff --git a/engine/battle/experience.asm b/engine/battle/experience.asm index 24748338..722685c2 100644 --- a/engine/battle/experience.asm +++ b/engine/battle/experience.asm @@ -43,7 +43,7 @@ GainExperience: inc de jr .nextBaseStat .maxStatExp ; if the upper byte also overflowed, then we have hit the max stat exp - ld a, $ff + dec a ; a is 0 from previous check ld [de], a inc de ld [de], a @@ -233,13 +233,19 @@ GainExperience: .recalcStatChanges xor a ; battle mon ld [wCalculateWhoseStats], a - callab CalculateModifiedStats - callab ApplyBurnAndParalysisPenaltiesToPlayer - callab ApplyBadgeStatBoosts - callab DrawPlayerHUDAndHPBar - callab PrintEmptyString + ld hl, CalculateModifiedStats + call Bankswitch15ToF + ld hl, ApplyBurnAndParalysisPenaltiesToPlayer + call Bankswitch15ToF + ld hl, ApplyBadgeStatBoosts + call Bankswitch15ToF + ld hl, DrawPlayerHUDAndHPBar + call Bankswitch15ToF + ld hl, PrintEmptyString + call Bankswitch15ToF call SaveScreenTilesToBuffer1 .printGrewLevelText + callabd_ModifyPikachuHappiness PIKAHAPPY_LEVELUP ld hl, GrewLevelText call PrintText xor a ; PLAYER_PARTY_DATA @@ -339,6 +345,10 @@ BoostExp: ld [H_QUOTIENT + 2], a ret +Bankswitch15ToF: + ld b, BANK(BattleCore) + jp Bankswitch + GainedText: TX_FAR _GainedText TX_ASM diff --git a/engine/battle/ghost_marowak_anim.asm b/engine/battle/ghost_marowak_anim.asm index 7adb20d8..5bb3e308 100644 --- a/engine/battle/ghost_marowak_anim.asm +++ b/engine/battle/ghost_marowak_anim.asm @@ -2,6 +2,7 @@ MarowakAnim: ; animate the ghost being unveiled as a Marowak ld a, $e4 ld [rOBP1], a + call UpdateGBCPal_OBP1 call CopyMonPicFromBGToSpriteVRAM ; cover the BG ghost pic with a sprite ghost pic that looks the same ; now that the ghost pic is being displayed using sprites, clear the ghost pic from the BG tilemap coord hl, 12, 0 @@ -27,6 +28,7 @@ MarowakAnim: sla a sla a ld [rOBP1], a + call UpdateGBCPal_OBP1 jr nz, .fadeOutGhostLoop call ClearSprites call CopyMonPicFromBGToSpriteVRAM ; copy Marowak pic from BG to sprite VRAM @@ -40,6 +42,7 @@ MarowakAnim: srl b rra ld [rOBP1], a + call UpdateGBCPal_OBP1 ld a, b and a jr nz, .fadeInMarowakLoop @@ -74,7 +77,7 @@ CopyMonPicFromBGToSpriteVRAM: ld [hli], a ld a, d ld [hli], a - ld a, $10 ; use OBP1 + ld a, $14 ; use OBP1 ld [hli], a inc d dec c diff --git a/engine/battle/link_battle_versus_text.asm b/engine/battle/link_battle_versus_text.asm index 76559117..63142ba6 100644 --- a/engine/battle/link_battle_versus_text.asm +++ b/engine/battle/link_battle_versus_text.asm @@ -2,8 +2,7 @@ DisplayLinkBattleVersusTextBox: call LoadTextBoxTilePatterns coord hl, 3, 4 - ld b, 7 - ld c, 12 + lb bc, 7, 12 call TextBoxBorder coord hl, 4, 5 ld de, wPlayerName diff --git a/engine/battle/moveEffects/heal_effect.asm b/engine/battle/moveEffects/heal_effect.asm index 2e68acc0..97afa394 100644 --- a/engine/battle/moveEffects/heal_effect.asm +++ b/engine/battle/moveEffects/heal_effect.asm @@ -86,7 +86,7 @@ HealEffect_: ld [wHPBarNewHP], a .playAnim ld hl, PlayCurrentMoveAnimation - call BankswitchEtoF + call Bankswitch3DtoF ld a, [H_WHOSETURN] and a coord hl, 10, 9 @@ -98,14 +98,14 @@ HealEffect_: ld [wHPBarType], a predef UpdateHPBar2 ld hl, DrawHUDsAndHPBars - call BankswitchEtoF + call Bankswitch3DtoF ld hl, RegainedHealthText jp PrintText .failed ld c, 50 call DelayFrames ld hl, PrintButItFailedText_ - jp BankswitchEtoF + jp Bankswitch3DtoF StartedSleepingEffect: TX_FAR _StartedSleepingEffect diff --git a/engine/battle/moveEffects/reflect_light_screen_effect.asm b/engine/battle/moveEffects/reflect_light_screen_effect.asm index 2805a969..e5748b19 100644 --- a/engine/battle/moveEffects/reflect_light_screen_effect.asm +++ b/engine/battle/moveEffects/reflect_light_screen_effect.asm @@ -23,14 +23,14 @@ ReflectLightScreenEffect_: .playAnim push hl ld hl, PlayCurrentMoveAnimation - call BankswitchEtoF + call Bankswitch3DtoF pop hl jp PrintText .moveFailed ld c, 50 call DelayFrames ld hl, PrintButItFailedText_ - jp BankswitchEtoF + jp Bankswitch3DtoF LightScreenProtectedText: TX_FAR _LightScreenProtectedText @@ -40,6 +40,6 @@ ReflectGainedArmorText: TX_FAR _ReflectGainedArmorText db "@" -BankswitchEtoF: +Bankswitch3DtoF: ld b, BANK(BattleCore) jp Bankswitch diff --git a/engine/battle/moveEffects/transform_effect.asm b/engine/battle/moveEffects/transform_effect.asm index 9a5de9cc..ec07b303 100644 --- a/engine/battle/moveEffects/transform_effect.asm +++ b/engine/battle/moveEffects/transform_effect.asm @@ -100,18 +100,11 @@ TransformEffect_: and a jr z, .lessThanFourMoves ld a, $5 - ld [de], a - inc de - dec b - jr nz, .copyPPLoop - jr .copyStats .lessThanFourMoves -; 0 PP for blank moves - xor a ld [de], a inc de dec b - jr nz, .lessThanFourMoves + jr nz, .copyPPLoop .copyStats ; original (unmodified) stats and stat mods pop hl @@ -141,7 +134,7 @@ TransformEffect_: .failed ld hl, PrintButItFailedText_ - jp BankswitchEtoF + jp Bankswitch3DtoF TransformedText: TX_FAR _TransformedText diff --git a/engine/battle/read_trainer_party.asm b/engine/battle/read_trainer_party.asm index ba4f6f8e..b4ee46a0 100755 --- a/engine/battle/read_trainer_party.asm +++ b/engine/battle/read_trainer_party.asm @@ -15,8 +15,8 @@ ReadTrainer: ld [hl], a ; get the pointer to trainer data for this class - ld a, [wCurOpponent] - sub $C9 ; convert value from pokemon to trainer + ld a, [wTrainerClass] ; get trainer class + dec a add a ld hl, TrainerDataPointers ld c, a @@ -53,7 +53,7 @@ ReadTrainer: .LoopTrainerData ld a, [hli] and a ; have we reached the end of the trainer data? - jr z, .FinishUp + jp z, .AddAdditionalMoveData ld [wcf91], a ; write species somewhere (XXX why?) ld a, ENEMY_PARTY_DATA ld [wMonDataLocation], a @@ -68,7 +68,7 @@ ReadTrainer: ; - if [wLoneAttackNo] != 0, one pokemon on the team has a special move ld a, [hli] and a ; have we reached the end of the trainer data? - jr z, .AddLoneMove + jr z, .AddAdditionalMoveData ld [wCurEnemyLVL], a ld a, [hli] ld [wcf91], a @@ -78,69 +78,48 @@ ReadTrainer: call AddPartyMon pop hl jr .SpecialTrainer -.AddLoneMove -; does the trainer have a single monster with a different move - ld a, [wLoneAttackNo] ; Brock is 01, Misty is 02, Erika is 04, etc - and a - jr z, .AddTeamMove - dec a - add a +.AddAdditionalMoveData +; does the trainer have additional move data? + ld a, [wTrainerClass] + ld b, a + ld a, [wTrainerNo] ld c, a - ld b, 0 - ld hl, LoneMoves - add hl, bc + ld hl, SpecialTrainerMoves +.loopAdditionalMoveData + ld a, [hli] + cp $ff + jr z, .FinishUp + cp b + jr nz, .asm_39c46 ld a, [hli] - ld d, [hl] - ld hl, wEnemyMon1Moves + 2 + cp c + jr nz, .asm_39c46 + ld d, h + ld e, l +.writeAdditionalMoveDataLoop + ld a, [de] + inc de + and a + jp z, .FinishUp + dec a + ld hl, wEnemyMon1Moves ld bc, wEnemyMon2 - wEnemyMon1 call AddNTimes - ld [hl], d - jr .FinishUp -.AddTeamMove -; check if our trainer's team has special moves - -; get trainer class number - ld a, [wCurOpponent] - sub OPP_ID_OFFSET - ld b, a - ld hl, TeamMoves - -; iterate through entries in TeamMoves, checking each for our trainer class -.IterateTeamMoves + ld a, [de] + inc de + dec a + ld c, a + ld b, 0 + add hl,bc + ld a, [de] + inc de + ld [hl], a + jr .writeAdditionalMoveDataLoop +.asm_39c46 ld a, [hli] - cp b - jr z, .GiveTeamMoves ; is there a match? - inc hl ; if not, go to the next entry - inc a - jr nz, .IterateTeamMoves - -; no matches found. is this trainer champion rival? - ld a, b - cp SONY3 - jr z, .ChampionRival - jr .FinishUp ; nope -.GiveTeamMoves - ld a, [hl] - ld [wEnemyMon5Moves + 2], a - jr .FinishUp -.ChampionRival ; give moves to his team - -; pidgeot - ld a, SKY_ATTACK - ld [wEnemyMon1Moves + 2], a - -; starter - ld a, [wRivalStarter] - cp STARTER3 - ld b, MEGA_DRAIN - jr z, .GiveStarterMove - cp STARTER1 - ld b, FIRE_BLAST - jr z, .GiveStarterMove - ld b, BLIZZARD ; must be squirtle -.GiveStarterMove - ld a, b - ld [wEnemyMon6Moves + 2], a + and a + jr nz, .asm_39c46 + jr .loopAdditionalMoveData .FinishUp ; clear wAmountMoneyWon addresses xor a diff --git a/engine/battle/safari_zone.asm b/engine/battle/safari_zone.asm index 4672892d..88064f9a 100755 --- a/engine/battle/safari_zone.asm +++ b/engine/battle/safari_zone.asm @@ -2,18 +2,18 @@ PrintSafariZoneBattleText: ld hl, wSafariBaitFactor ld a, [hl] and a - jr z, .asm_4284 + jr z, .asm_411e dec [hl] ld hl, SafariZoneEatingText - jr .asm_429f -.asm_4284 + jr .asm_4138 +.asm_411e dec hl ld a, [hl] and a ret z dec [hl] ld hl, SafariZoneAngryText - jr nz, .asm_429f + jr nz, .asm_4138 push hl ld a, [wEnemyMonSpecies] ld [wd0b5], a @@ -21,7 +21,7 @@ PrintSafariZoneBattleText: ld a, [wMonHCatchRate] ld [wEnemyMonActualCatchRate], a pop hl -.asm_429f +.asm_4138 push hl call LoadScreenTilesFromBuffer1 pop hl diff --git a/engine/battle/scale_sprites.asm b/engine/battle/scale_sprites.asm index 98521528..c614d638 100644 --- a/engine/battle/scale_sprites.asm +++ b/engine/battle/scale_sprites.asm @@ -2,6 +2,13 @@ ; assumes that input sprite chunks are 4x4 tiles, and the rightmost and bottommost 4 pixels will be ignored ; resulting in a 7*7 tile output sprite chunk ScaleSpriteByTwo: + ld a, $0 + call SwitchSRAMBankAndLatchClockData + call ScaleSpriteByTwo_ + call PrepareRTCDataAndDisableSRAM + ret + +ScaleSpriteByTwo_: ld de, sSpriteBuffer1 + (4*4*8) - 5 ; last byte of input data, last 4 rows already skipped ld hl, sSpriteBuffer0 + SPRITEBUFFERSIZE - 1 ; end of destination buffer call ScaleLastSpriteColumnByTwo ; last tile column is special case diff --git a/engine/battle/trainer_ai.asm b/engine/battle/trainer_ai.asm index ac6c1a72..c8fdfb29 100644 --- a/engine/battle/trainer_ai.asm +++ b/engine/battle/trainer_ai.asm @@ -295,7 +295,7 @@ TrainerClassMoveChoiceModifications: db 1,0 ; GAMBLER db 1,3,0 ; BEAUTY db 1,2,0 ; PSYCHIC_TR - db 1,3,0 ; ROCKER + db 1,0 ; ROCKER db 1,0 ; JUGGLER db 1,0 ; TAMER db 1,0 ; BIRD_KEEPER @@ -311,11 +311,11 @@ TrainerClassMoveChoiceModifications: db 1,0 ; BRUNO db 1,0 ; BROCK db 1,3,0 ; MISTY - db 1,3,0 ; LT_SURGE + db 1,0 ; LT_SURGE db 1,3,0 ; ERIKA db 1,3,0 ; KOGA - db 1,3,0 ; BLAINE - db 1,3,0 ; SABRINA + db 1,0 ; BLAINE + db 1,0 ; SABRINA db 1,2,0 ; GENTLEMAN db 1,3,0 ; SONY2 db 1,3,0 ; SONY3 @@ -337,14 +337,20 @@ INCLUDE "data/trainer_moves.asm" INCLUDE "data/trainer_parties.asm" TrainerAI: - and a ld a, [wIsInBattle] dec a - ret z ; if not a trainer, we're done here + jr z, .done ; if not a trainer, we're done here ld a, [wLinkState] cp LINK_STATE_BATTLING - ret z - ld a, [wTrainerClass] ; what trainer class is this? + jr z, .done ; if in a link battle, we're done as well + ld a, [wEnemyBattleStatus1] + and 1 << CHARGING_UP | 1 << THRASHING_ABOUT | 1 << STORING_ENERGY ; %10011 + jr nz, .done ; don't follow trainer ai if opponent is in a locked state + ld a, [wEnemyBattleStatus2] + and 1 << USING_RAGE ; %1000000 + jr nz, .done ; don't follow trainer ai if opponent is locked in rage + ; note that this doesn't check for hyper beam recharge which can cause problems + ld a,[wTrainerClass] ; what trainer class is this? dec a ld c, a ld b, 0 @@ -354,7 +360,7 @@ TrainerAI: add hl, bc ld a, [wAICount] and a - ret z ; if no AI uses left, we're done here + jr z, .done; if no AI uses left, we're done here inc hl inc a jr nz, .getpointer @@ -367,6 +373,9 @@ TrainerAI: ld l, a call Random jp hl +.done + and a + ret TrainerAIPointers: ; one entry per trainer class @@ -476,22 +485,22 @@ ErikaAI: jp AIUseSuperPotion KogaAI: - cp 25 percent + 1 + cp 13 percent - 1 ret nc jp AIUseXAttack BlaineAI: cp 25 percent + 1 ret nc + ld a, 10 + call AICheckIfHPBelowFraction + ret nc jp AIUseSuperPotion SabrinaAI: cp 25 percent + 1 ret nc - ld a, 10 - call AICheckIfHPBelowFraction - ret nc - jp AIUseHyperPotion + jp AIUseXDefend Sony2AI: cp 13 percent - 1 diff --git a/engine/battle/wild_encounters.asm b/engine/battle/wild_encounters.asm index 231c46e7..0285346e 100644 --- a/engine/battle/wild_encounters.asm +++ b/engine/battle/wild_encounters.asm @@ -24,8 +24,9 @@ TryDoWildEncounter: ld [wRepelRemainingSteps], a .next ; determine if wild pokemon can appear in the half-block we're standing in -; is the bottom right tile (9,9) of the half-block we're standing in a grass/water tile? - coord hl, 9, 9 +; is the bottom left tile (8,9) of the half-block we're standing in a grass/water tile? +; note that by using the bottom left tile, this prevents the "left-shore" tiles from generating grass encounters + coord hl, 8, 9 ld c, [hl] ld a, [wGrassTile] cp c @@ -68,8 +69,6 @@ TryDoWildEncounter: cp $14 ; is the bottom left tile (8,9) of the half-block we're standing in a water tile? jr nz, .gotWildEncounterType ; else, it's treated as a grass tile by default ld hl, wWaterMons -; since the bottom right tile of a "left shore" half-block is $14 but the bottom left tile is not, -; "left shore" half-blocks (such as the one in the east coast of Cinnabar) load grass encounters. .gotWildEncounterType ld b, 0 add hl, bc diff --git a/engine/bcd.asm b/engine/bcd.asm index 2d0b43df..d84e504b 100644 --- a/engine/bcd.asm +++ b/engine/bcd.asm @@ -1,14 +1,17 @@ +; divide hMoney by hDivideBCDDivisor +; return output in hDivideBCDQuotient (same as hDivideBCDDivisor) +; used only to halve player money upon losing a fight DivideBCDPredef:: DivideBCDPredef2:: -DivideBCDPredef3:: +DivideBCDPredef3:: ; only used function DivideBCDPredef4:: call GetPredefRegisters DivideBCD:: xor a ld [hDivideBCDBuffer], a - ld [hDivideBCDBuffer+1], a - ld [hDivideBCDBuffer+2], a + ld [hDivideBCDBuffer + 1], a + ld [hDivideBCDBuffer + 2], a ld d, $1 .mulBy10Loop ; multiply the divisor by 10 until the leading digit is nonzero @@ -21,25 +24,26 @@ DivideBCD:: swap a and $f0 ld b, a - ld a, [hDivideBCDDivisor+1] + ld a, [hDivideBCDDivisor + 1] swap a - ld [hDivideBCDDivisor+1], a + ld [hDivideBCDDivisor + 1], a and $f or b ld [hDivideBCDDivisor], a - ld a, [hDivideBCDDivisor+1] + ld a, [hDivideBCDDivisor + 1] and $f0 ld b, a - ld a, [hDivideBCDDivisor+2] + ld a, [hDivideBCDDivisor + 2] swap a - ld [hDivideBCDDivisor+2], a + ld [hDivideBCDDivisor + 2], a and $f or b - ld [hDivideBCDDivisor+1], a - ld a, [hDivideBCDDivisor+2] + ld [hDivideBCDDivisor + 1], a + ld a, [hDivideBCDDivisor + 2] and $f0 - ld [hDivideBCDDivisor+2], a + ld [hDivideBCDDivisor + 2], a jr .mulBy10Loop + .next push de push de @@ -67,16 +71,16 @@ DivideBCD:: ld a, b swap a and $f0 - ld [hDivideBCDBuffer+1], a + ld [hDivideBCDBuffer + 1], a dec d jr z, .next2 push de call DivideBCD_divDivisorBy10 call DivideBCD_getNextDigit pop de - ld a, [hDivideBCDBuffer+1] + ld a, [hDivideBCDBuffer + 1] or b - ld [hDivideBCDBuffer+1], a + ld [hDivideBCDBuffer + 1], a dec d jr z, .next2 push de @@ -86,23 +90,23 @@ DivideBCD:: ld a, b swap a and $f0 - ld [hDivideBCDBuffer+2], a + ld [hDivideBCDBuffer + 2], a dec d jr z, .next2 push de call DivideBCD_divDivisorBy10 call DivideBCD_getNextDigit pop de - ld a, [hDivideBCDBuffer+2] + ld a, [hDivideBCDBuffer + 2] or b - ld [hDivideBCDBuffer+2], a + ld [hDivideBCDBuffer + 2], a .next2 ld a, [hDivideBCDBuffer] ld [hDivideBCDQuotient], a ; the same memory location as hDivideBCDDivisor - ld a, [hDivideBCDBuffer+1] - ld [hDivideBCDQuotient+1], a - ld a, [hDivideBCDBuffer+2] - ld [hDivideBCDQuotient+2], a + ld a, [hDivideBCDBuffer + 1] + ld [hDivideBCDQuotient + 1], a + ld a, [hDivideBCDBuffer + 2] + ld [hDivideBCDQuotient + 2], a pop de ld a, $6 sub d @@ -117,17 +121,17 @@ DivideBCD:: ret DivideBCD_divDivisorBy10: - ld a, [hDivideBCDDivisor+2] + ld a, [hDivideBCDDivisor + 2] swap a and $f ld b, a - ld a, [hDivideBCDDivisor+1] + ld a, [hDivideBCDDivisor + 1] swap a - ld [hDivideBCDDivisor+1], a + ld [hDivideBCDDivisor + 1], a and $f0 or b - ld [hDivideBCDDivisor+2], a - ld a, [hDivideBCDDivisor+1] + ld [hDivideBCDDivisor + 2], a + ld a, [hDivideBCDDivisor + 1] and $f ld b, a ld a, [hDivideBCDDivisor] @@ -135,7 +139,7 @@ DivideBCD_divDivisorBy10: ld [hDivideBCDDivisor], a and $f0 or b - ld [hDivideBCDDivisor+1], a + ld [hDivideBCDDivisor + 1], a ld a, [hDivideBCDDivisor] and $f ld [hDivideBCDDivisor], a @@ -151,8 +155,8 @@ DivideBCD_getNextDigit: pop bc ret c inc b - ld de, hMoney+2 ; since SubBCD works starting from the least significant digit - ld hl, hDivideBCDDivisor+2 + ld de, hMoney + 2 ; since SubBCD works starting from the least significant digit + ld hl, hDivideBCDDivisor + 2 push bc call SubBCD pop bc diff --git a/engine/bg_map_attributes.asm b/engine/bg_map_attributes.asm new file mode 100644 index 00000000..90df9e27 --- /dev/null +++ b/engine/bg_map_attributes.asm @@ -0,0 +1,219 @@ +INCLUDE "data/bg_map_attributes.asm" + +LoadBGMapAttributes:: + ld hl, BGMapAttributesPointers + ld a, c ; c = which packet + push af ; save for later (to determine if we're handling the trainer card or party menu) + dec a ; read this code as: + add a ; dec a + ld e, a ; add a + xor a ; ld e, a + ld d, a ; ld d, 0 + add hl, de ; add hl, de + ld a, [hli] ; ld a, [hli] + ld e, a ; ld h, [hl] + ld a, [hl] ; ld l, a + ld h, a + ld a, e + ld l, a + + di + ld a, $1 + ld [rVBK], a + push hl + ld a, [hl] + ld c, a ; save attribute count for later + ld de, $10 + add hl, de + ld a, h + ld [rHDMA1], a + ld a, l + ld [rHDMA2], a + ld de, vBGMap0 + ld a, d + ld [rHDMA3], a + ld a, e + ld [rHDMA4], a + + ld a, [rLCDC] + and rLCDC_ENABLE_MASK ; is LCD off? + jr z, .lcdOff ; if off, transfer immediately +; wait for VBlank if LCD is on +.waitForVBlankLoop1 + ld a, [rLY] + cp $90 + jr nz, .waitForVBlankLoop1 +.waitForAccessibleVRAMLoop1 + ld a, [rSTAT] + and %10 ; are we in HBlank or VBlank? + jr nz, .waitForAccessibleVRAMLoop1 ; loop until we're in a safe period to transfer to VRAM +.lcdOff + ld a, c ; number of BG attributes to transfer, plus 1 times 16 + ld [rHDMA5], a ; initiate transfer + call Func_3082 ; update audio so it doesn't "lag" + pop hl + ld a, [hli] + ld c, a ; number of BG attributes to transfer, plus 1 times 16 + ld a, [hli] + ld e, a + ld a, [hli] + ld d, a ; offset of the attributes + add hl, de ; hl = new pointer + ld a, h + ld [rHDMA1], a + ld a, l + ld [rHDMA2], a + ld de, vBGMap1 ; copy to vBGMap1 + ld a, d + ld [rHDMA3], a + ld a, e + ld [rHDMA4], a +; LCD check again + ld a, [rLCDC] + and rLCDC_ENABLE_MASK ; is LCD off? + jr z, .lcdOff2 ; if off, transfer immediately +; wait for VBlank if LCD is on +.waitForVBlankLoop2 + ld a, [rLY] + cp $90 + jr nz, .waitForVBlankLoop2 +.waitForAccessibleVRAMLoop2 + ld a, [rSTAT] + and %10 ; are we in HBlank or VBlank? + jr nz, .waitForAccessibleVRAMLoop2 ; loop until we're in a safe period to transfer to VRAM +.lcdOff2 + ld a, c + ld [rHDMA5], a + pop af + dec a + dec a + dec a + dec a + jr nz, .checkIfHandlingPartyMenu + call HandleBadgeFaceAttributes + jr .done +.checkIfHandlingPartyMenu + dec a + call z, HandlePartyHPBarAttributes +.done + call Func_3082 + ld a, [rIF] + res VBLANK, a + ld [rIF], a + xor a + ld [rVBK], a + ei + ret + +BGMapAttributesPointers: + dw BGMapAttributes_Unknown1 + dw BGMapAttributes_Unknown2 + dw BGMapAttributes_GameFreakIntro + dw BGMapAttributes_TrainerCard + dw BGMapAttributes_PartyMenu + dw BGMapAttributes_NidorinoIntro + dw BGMapAttributes_TitleScreen + dw BGMapAttributes_Slots + dw BGMapAttributes_Pokedex + dw BGMapAttributes_StatusScreen + dw BGMapAttributes_Battle + dw BGMapAttributes_WholeScreen + dw BGMapAttributes_Unknown13 + +HandleBadgeFaceAttributes: +; zero out the attributes if the player doesn't have the respective badge +; BOULDERBADGE + ld hl, vBGMap1 + $183 + ld de, wTrainerCardBadgeAttributes + 6 * 0 + ld a, [de] + and a + call z, ZeroOutCurrentBadgeAttributes +; CASCADEBADGE + ld hl, vBGMap1 + $187 + ld de, wTrainerCardBadgeAttributes + 6 * 1 + ld a, [de] + and a + call z, ZeroOutCurrentBadgeAttributes +; THUNDERBADGE + ld hl, vBGMap1 + $18b + ld de, wTrainerCardBadgeAttributes + 6 * 2 + ld a, [de] + and a + call z, ZeroOutCurrentBadgeAttributes +; RAINBOWBADGE + ld hl, vBGMap1 + $18f + ld de, wTrainerCardBadgeAttributes + 6 * 3 + ld a, [de] + and a + call z, ZeroOutCurrentBadgeAttributes +; SOULBADGE + ld hl, vBGMap1 + $1e3 + ld de, wTrainerCardBadgeAttributes + 6 * 6 + ld a, [de] + and a + call z, ZeroOutCurrentBadgeAttributes +; MARSHBADGE + ld hl, vBGMap1 + $1e7 + ld de, wTrainerCardBadgeAttributes + 6 * 7 + ld a, [de] + and a + call z, ZeroOutCurrentBadgeAttributes +; VOLCANOBADGE + ld hl, vBGMap1 + $1eb + ld de, wTrainerCardBadgeAttributes + 6 * 8 + ld a, [de] + and a + call z, ZeroOutCurrentBadgeAttributes +; EARTHBADGE + ld hl, vBGMap1 + $1ef + ld de, wTrainerCardBadgeAttributes + 6 * 9 + ld a, [de] + and a + call z, ZeroOutCurrentBadgeAttributes + ret + +ZeroOutCurrentBadgeAttributes: + push hl + xor a + ld [hli], a + ld [hl], a + ld bc, $1f + add hl, bc + ld [hli], a + ld [hl], a + pop hl + ret + +HandlePartyHPBarAttributes: +; hp bars require 3 (green, orange, red) colours, when there are only 2 "free" colours per palette +; therefore, we must transfer individual bg attributes where the locations of the hp bars are in vram + ld hl, vBGMap1 + $25 ; location of start of the HP bar in vram + ld de, wPartyHPBarAttributes + ld c, PARTY_LENGTH +.loop + push bc + push hl + ld a, [de] + and $3 ; 4 possible palettes + rept 7 ; hp bar length in tiles + ld [hli], a + endr + pop hl + ld bc, $40 ; get 2nd party location + add hl, bc + push hl + + push de ; (inefficiently) copy de to hl + pop hl + + ld bc, $6 + add hl, bc ; get the next palette + + push hl + pop de ; copy back to de + + pop hl + pop bc + dec c + jr nz, .loop + ret diff --git a/engine/black_out.asm b/engine/black_out.asm index 6c358ce3..0daa084b 100644 --- a/engine/black_out.asm +++ b/engine/black_out.asm @@ -1,6 +1,8 @@ ResetStatusAndHalveMoneyOnBlackout:: ; Reset player status on blackout. xor a + ld [wd435], a + xor a ; gamefreak copypasting functions (double xor a) ld [wBattleResult], a ld [wWalkBikeSurfState], a ld [wIsInBattle], a diff --git a/engine/cable_club.asm b/engine/cable_club.asm index 3e72daa9..a8dc5d8d 100755 --- a/engine/cable_club.asm +++ b/engine/cable_club.asm @@ -10,8 +10,7 @@ CableClub_DoBattleOrTrade: call LoadHpBarAndStatusTilePatterns call LoadTrainerInfoTextBoxTiles coord hl, 3, 8 - ld b, 2 - ld c, 12 + lb bc, 2, 12 call CableClub_TextBoxBorder coord hl, 4, 10 ld de, PleaseWaitString @@ -119,6 +118,7 @@ CableClub_DoBattleOrTradeAgain: ld [rSC], a .skipSendingTwoZeroBytes call Delay3 + call StopAllMusic ld a, (1 << SERIAL) ld [rIE], a ld hl, wSerialRandomNumberListBlock @@ -139,8 +139,6 @@ CableClub_DoBattleOrTradeAgain: call Serial_ExchangeBytes ld a, (1 << SERIAL) | (1 << TIMER) | (1 << VBLANK) ld [rIE], a - ld a, $ff - call PlaySound ld a, [hSerialConnectionStatus] cp USING_INTERNAL_CLOCK jr z, .skipCopyingRandomNumberList ; the list generated by the gameboy clocking the connection is used by both gameboys @@ -261,8 +259,7 @@ CableClub_DoBattleOrTradeAgain: ld [wUnusedCF8D + 1], a xor a ld [wTradeCenterPointerTableIndex], a - ld a, $ff - call PlaySound + call StopAllMusic ld a, [hSerialConnectionStatus] cp USING_INTERNAL_CLOCK ld c, 66 @@ -278,9 +275,17 @@ CableClub_DoBattleOrTradeAgain: ld [wCurOpponent], a call ClearScreen call Delay3 + ld b, $9 + call RunPaletteCommand ld hl, wOptions res 7, [hl] + ld a, [wLetterPrintingDelayFlags] + push af + xor a + ld [wLetterPrintingDelayFlags], a predef InitOpponent + pop af + ld [wLetterPrintingDelayFlags], a predef HealParty jp ReturnToCableClubRoom .trading @@ -308,6 +313,9 @@ CallCurrentTradeCenterFunction: TradeCenter_SelectMon: call ClearScreen + call Delay3 + ld b, $9 + call RunPaletteCommand call LoadTrainerInfoTextBoxTiles call TradeCenter_DrawPartyLists call TradeCenter_DrawCancelBox @@ -338,10 +346,10 @@ TradeCenter_SelectMon: ld a, 1 ld [wTopMenuItemX], a .enemyMonMenu_HandleInput - ld hl, hFlags_0xFFF6 + ld hl, hFlags_0xFFFA set 1, [hl] call HandleMenuInput - ld hl, hFlags_0xFFF6 + ld hl, hFlags_0xFFFA res 1, [hl] and a jp z, .getNewInput @@ -403,10 +411,10 @@ TradeCenter_SelectMon: lb bc, 6, 1 call ClearScreenArea .playerMonMenu_HandleInput - ld hl, hFlags_0xFFF6 + ld hl, hFlags_0xFFFA set 1, [hl] call HandleMenuInput - ld hl, hFlags_0xFFF6 + ld hl, hFlags_0xFFFA res 1, [hl] and a ; was anything pressed? jr nz, .playerMonMenu_SomethingPressed @@ -465,8 +473,7 @@ TradeCenter_SelectMon: .displayStatsTradeMenu push af coord hl, 0, 14 - ld b, 2 - ld c, 18 + lb bc, 2, 18 call CableClub_TextBoxBorder coord hl, 2, 16 ld de, .statsTrade @@ -601,8 +608,7 @@ TradeCenter_DrawCancelBox: ld bc, 2 * SCREEN_WIDTH + 9 call FillMemory coord hl, 0, 15 - ld b, 1 - ld c, 9 + lb bc, 1, 9 call CableClub_TextBoxBorder coord hl, 2, 16 ld de, CancelTextString @@ -624,6 +630,9 @@ TradeCenter_DisplayStats: ld [wWhichPokemon], a predef StatusScreen predef StatusScreen2 + call Delay3 + ld b, $9 + call RunPaletteCommand call GBPalNormal call LoadTrainerInfoTextBoxTiles call TradeCenter_DrawPartyLists @@ -631,12 +640,10 @@ TradeCenter_DisplayStats: TradeCenter_DrawPartyLists: coord hl, 0, 0 - ld b, 6 - ld c, 18 + lb bc, 6, 18 call CableClub_TextBoxBorder coord hl, 0, 8 - ld b, 6 - ld c, 18 + lb bc, 6, 18 call CableClub_TextBoxBorder coord hl, 5, 0 ld de, wPlayerName @@ -685,8 +692,7 @@ TradeCenter_Trade: ld [wMenuWatchMovingOutOfBounds], a ld [wMenuJoypadPollCount], a coord hl, 0, 12 - ld b, 4 - ld c, 18 + lb bc, 4, 18 call CableClub_TextBoxBorder ld a, [wTradingWhichPlayerMon] ld hl, wPartySpecies @@ -727,8 +733,7 @@ TradeCenter_Trade: ld a, $1 ld [wSerialExchangeNybbleSendData], a coord hl, 0, 12 - ld b, 4 - ld c, 18 + lb bc, 4, 18 call CableClub_TextBoxBorder coord hl, 1, 14 ld de, TradeCanceled @@ -744,8 +749,7 @@ TradeCenter_Trade: jr nz, .doTrade ; if the other person cancelled coord hl, 0, 12 - ld b, 4 - ld c, 18 + lb bc, 4, 18 call CableClub_TextBoxBorder coord hl, 1, 14 ld de, TradeCanceled @@ -792,6 +796,7 @@ TradeCenter_Trade: add hl, bc ld a, [hl] ld [wTradedPlayerMonSpecies], a + callabd_ModifyPikachuHappiness PIKAHAPPY_TRADE xor a ld [wRemoveMonFromBox], a call RemovePokemon @@ -826,7 +831,7 @@ TradeCenter_Trade: ld [wTradedEnemyMonSpecies], a ld a, 10 ld [wAudioFadeOutControl], a - ld a, $2 + ld a, BANK(Music_SafariZone) ld [wAudioSavedROMBank], a ld a, MUSIC_SAFARI_ZONE ld [wNewSoundID], a @@ -851,9 +856,11 @@ TradeCenter_Trade: call Serial_PrintWaitingTextAndSyncAndExchangeNybble ld c, 40 call DelayFrames + call Delay3 + ld b, $9 + call RunPaletteCommand coord hl, 0, 12 - ld b, 4 - ld c, 18 + lb bc, 4, 18 call CableClub_TextBoxBorder coord hl, 1, 14 ld de, TradeCompleted diff --git a/engine/clear_save.asm b/engine/clear_save.asm index b47cd6c4..f2acbf32 100755 --- a/engine/clear_save.asm +++ b/engine/clear_save.asm @@ -5,6 +5,8 @@ DoClearSaveDialogue: call LoadTextBoxTilePatterns ld hl, ClearSaveDataText call PrintText + ld a, B_BUTTON + ld [wJoyIgnore], a coord hl, 14, 7 lb bc, 8, 15 ld a, NO_YES_MENU @@ -12,6 +14,8 @@ DoClearSaveDialogue: ld a, TWO_OPTION_MENU ld [wTextBoxID], a call DisplayTextBoxID + ld a, 0 + ld [wJoyIgnore], a ld a, [wCurrentMenuItem] and a jp z, Init diff --git a/engine/debug1.asm b/engine/debug1.asm index a5eb7dde..a39e8cac 100644 --- a/engine/debug1.asm +++ b/engine/debug1.asm @@ -1,14 +1,6 @@ -; This function appears to never be used. -; It is likely a debugging feature to give the player Tsunekazu Ishihara's -; favorite Pokemon. This is indicated by the overpowered Exeggutor, which -; Ishihara (president of Creatures Inc.) said was his favorite Pokemon in an ABC -; interview on February 8, 2000. -; "Exeggutor is my favorite. That's because I was always using this character -; while I was debugging the program." -; http://www.ign.com/articles/2000/02/09/abc-news-pokamon-chat-transcript - -SetIshiharaTeam: - ld de, IshiharaTeam +; not IshiharaTeam +SetDebugTeam: + ld de, DebugTeam .loop ld a, [de] cp $ff @@ -21,12 +13,11 @@ SetIshiharaTeam: call AddPartyMon jr .loop -IshiharaTeam: - db EXEGGUTOR,90 - db MEW,20 - db JOLTEON,56 - db DUGTRIO,56 - db ARTICUNO,57 +DebugTeam: + db SNORLAX,80 + db PERSIAN,80 + db JIGGLYPUFF,15 + db PIKACHU,5 db $FF EmptyFunc: diff --git a/engine/diploma_3a.asm b/engine/diploma_3a.asm new file mode 100755 index 00000000..f4504ad7 --- /dev/null +++ b/engine/diploma_3a.asm @@ -0,0 +1,166 @@ +_DisplayDiploma: + call GBPalWhiteOutWithDelay3 + call ClearScreen + ld de, SurfingPikachu3Graphics + ld hl, vChars2 + lb bc, BANK(SurfingPikachu3Graphics), (SurfingPikachu3GraphicsEnd - SurfingPikachu3Graphics) / $10 + call CopyVideoData + + coord hl, 0, 0 + call Func_e9bdf + + coord hl, 0, 0 + call Func_e9beb + + coord hl, 19, 0 + call Func_e9beb + + ld a, $00 + coord hl, 0, 0 + ld [hl], a + coord hl, 19, 0 + ld [hl], a + + ld de, String_e9a73 + coord hl, 5, 2 + call PlaceString + + ld de, String_e9a7d + coord hl, 3, 4 + call PlaceString + + ld de, wPlayerName + coord hl, 10, 4 + call PlaceString + + ld de, String_e9a84 + coord hl, 2, 6 + call PlaceString + + ld de, String_e9ac8 + coord hl, 9, 16 + call PlaceString + + ld b, SET_PAL_GENERIC + call RunPaletteCommand + ld a, $01 + ld [$ffba], a + call Delay3 + call GBPalNormal + ret + +String_e9a73: + db $10, "Diploma", $10, "@" + +String_e9a7d: + db "Player@" + +String_e9a84: + db "Congrats! This" + next "diploma certifies" + next "that you have" + next "completed your" + next "#DEX.@" + +String_e9ac8: + db "GAME FREAK@" + +Func_e9ad3: + call ClearScreen + coord hl, 0, 17 + call Func_e9bdf + coord hl, 0, 0 + call Func_e9beb + coord hl, 19, 0 + call Func_e9beb + ld a, $00 + coord hl, 0, 17 + ld [hl], a + coord hl, 19, 17 + ld [hl], a + ld de, Tilemap_e9b3e + coord hl, 6, 2 + lb bc, 10, 12 + call Diploma_Surfing_CopyBox + ld de, Tilemap_e9bb6 + coord hl, 5, 13 + lb bc, 1, 11 + call Diploma_Surfing_CopyBox + ld de, String_e9bd5 + coord hl, 2, 15 + call PlaceString + coord hl, 12, 15 + ld de, wPlayTimeHours + lb bc, $40 | 1, 3 + call PrintNumber + ld [hl], $16 + inc hl + ld de, wPlayTimeMinutes + lb bc, $80 | 1, 2 + call PrintNumber + ld a, [wNumSetBits] + cp 151 + ret nz + ld de, TileMap_e9bc1 + coord hl, 2, 0 + lb bc, 4, 5 + call Diploma_Surfing_CopyBox + ret + +Tilemap_e9b3e: + db $7f, $7f, $7f, $1a, $1b, $7f, $7f, $7f, $7f, $7f + db $7f, $7f, $7f, $7f, $7f, $1c, $1d, $1e, $1f, $20 + db $7f, $21, $22, $23, $7f, $24, $25, $26, $27, $28 + db $29, $2a, $2b, $2c, $2d, $2e, $2f, $30, $31, $32 + db $33, $34, $35, $36, $37, $38, $39, $3a, $3b, $3c + db $7f, $3d, $3e, $3f, $40, $41, $42, $43, $29, $44 + db $45, $46, $47, $48, $49, $4a, $4b, $29, $29, $4c + db $4d, $4e, $4f, $50, $51, $52, $53, $54, $55, $56 + db $57, $58, $59, $7f, $7f, $7f, $5a, $5b, $5c, $5d + db $5e, $5f, $60, $61, $62, $7f, $7f, $7f, $7f, $63 + db $64, $65, $66, $67, $68, $7f, $7f, $7f, $7f, $7f + db $7f, $69, $6a, $6b, $6c, $6d, $6e, $7f, $7f, $7f + +Tilemap_e9bb6: + db $05 + db $06 + db $07 + db $08 + db $09 + db $0a + db $0b + db $0c + db $0d + db $0e + db $0f + +TileMap_e9bc1: + db $70, $71, $7f, $72, $7f + db $73, $74, $75, $76, $77 + db $7f, $78, $11, $12, $13 + db $7f, $7f, $14, $15, $7f + +String_e9bd5: db "PLAY TIME@" + +Func_e9bdf: + ld c, 10 +.asm_e9be1 + ld [hl], $02 + inc hl + ld [hl], $01 + inc hl + dec c + jr nz, .asm_e9be1 + ret + +Func_e9beb: + ld c, 9 + ld de, SCREEN_WIDTH +.asm_e9bed + ld [hl], $04 + add hl, de + ld [hl], $03 + add hl, de + dec c + jr nz, .asm_e9bed + ret diff --git a/engine/display_text_id_init.asm b/engine/display_text_id_init.asm index 59b3a5f8..0ef37370 100644 --- a/engine/display_text_id_init.asm +++ b/engine/display_text_id_init.asm @@ -14,19 +14,16 @@ DisplayTextIDInit: CheckEvent EVENT_GOT_POKEDEX ; start menu with pokedex coord hl, 10, 0 - ld b, $0e - ld c, $08 + lb bc, 14, 8 jr nz, .drawTextBoxBorder ; start menu without pokedex coord hl, 10, 0 - ld b, $0c - ld c, $08 + lb bc, 12, 8 jr .drawTextBoxBorder ; if text ID is not 0 (i.e. not the start menu) then do a standard dialogue text box .notStartMenu coord hl, 0, 12 - ld b, $04 - ld c, $12 + lb bc, 4, 18 .drawTextBoxBorder call TextBoxBorder .skipDrawingTextBoxBorder diff --git a/engine/evolution.asm b/engine/evolution.asm index 731735c5..7277e991 100755 --- a/engine/evolution.asm +++ b/engine/evolution.asm @@ -9,9 +9,7 @@ EvolveMon: xor a ld [wLowHealthAlarm], a ld [wChannelSoundIDs + Ch5], a - dec a - ld [wNewSoundID], a - call PlaySound + call StopAllMusic ld a, $1 ld [H_AUTOBGTRANSFERENABLED], a ld a, SFX_TINK @@ -67,9 +65,7 @@ EvolveMon: ld a, [wEvoNewSpecies] .done ld [wWholeScreenPaletteMonSpecies], a - ld a, $ff - ld [wNewSoundID], a - call PlaySound + call StopAllMusic ld a, [wWholeScreenPaletteMonSpecies] call PlayCry ld c, 0 diff --git a/engine/evolve_trade.asm b/engine/evolve_trade.asm deleted file mode 100755 index e17fc05c..00000000 --- a/engine/evolve_trade.asm +++ /dev/null @@ -1,44 +0,0 @@ -EvolveTradeMon: -; Verify the TradeMon's species name before -; attempting to initiate a trade evolution. - -; The names of the trade evolutions in Blue (JP) -; are checked. In that version, TradeMons that -; can evolve are Graveler and Haunter. - -; In localization, this check was translated -; before monster names were finalized. -; Then, Haunter's name was "Spectre". -; Since its name no longer starts with -; "SP", it is prevented from evolving. - -; This may have been why Red/Green's trades -; were used instead, where none can evolve. - -; This was fixed in Yellow. - - ld a, [wInGameTradeReceiveMonName] - - ; GRAVELER - cp "G" - jr z, .ok - - ; "SPECTRE" (HAUNTER) - cp "S" - ret nz - ld a, [wInGameTradeReceiveMonName + 1] - cp "P" - ret nz - -.ok - ld a, [wPartyCount] - dec a - ld [wWhichPokemon], a - ld a, $1 - ld [wForceEvolution], a - ld a, LINK_STATE_TRADING - ld [wLinkState], a - callab TryEvolvingMon - xor a ; LINK_STATE_NONE - ld [wLinkState], a - jp PlayDefaultMusic diff --git a/engine/evos_moves.asm b/engine/evos_moves.asm index f50f8081..8ec2c4c7 100755 --- a/engine/evos_moves.asm +++ b/engine/evos_moves.asm @@ -1,5 +1,6 @@ ; try to evolve the mon in [wWhichPokemon] TryEvolvingMon: +EvolveTradeMon: ld hl, wCanEvolveFlags xor a ld [hl], a @@ -93,9 +94,13 @@ Evolution_PartyMonLoop: ; loop over party mons jp c, Evolution_PartyMonLoop ; if so, go the next mon jr .doEvolution .checkItemEvo + ld a, [wIsInBattle] ; are we in battle? + and a ld a, [hli] + jp nz, .nextEvoEntry1 ; don't evolve if we're in a battle as wcf91 could be holding the last mon sent out + ld b, a ; evolution item - ld a, [wcf91] ; this is supposed to be the last item used, but it is also used to hold species numbers + ld a, [wcf91] ; last item used cp b ; was the evolution item in this entry used? jp nz, .nextEvoEntry1 ; if not, go to the next evolution entry .checkLevel @@ -140,7 +145,7 @@ Evolution_PartyMonLoop: ; loop over party mons ld [wEvoNewSpecies], a ld a, MONSTER_NAME ld [wNameListType], a - ld a, BANK(TrainerNames) ; bank is not used for monster names + ld a, BANK(MonsterNames) ; bank is not used for monster names ld [wPredefBank], a call GetName push hl @@ -318,23 +323,9 @@ Evolution_ReloadTilesetTilePatterns: jp ReloadTilesetTilePatterns LearnMoveFromLevelUp: - ld hl, EvosMovesPointerTable ld a, [wd11e] ; species ld [wcf91], a - dec a - ld bc, 0 - ld hl, EvosMovesPointerTable - add a - rl b - ld c, a - add hl, bc - ld a, [hli] - ld h, [hl] - ld l, a -.skipEvolutionDataLoop ; loop to skip past the evolution data, which comes before the move data - ld a, [hli] - and a ; have we reached the end of the evolution data? - jr nz, .skipEvolutionDataLoop ; if not, jump back up + call GetMonLearnset .learnSetLoop ; loop over the learn set until we reach a move that is learnt at the current level or the end of the list ld a, [hli] and a ; have we reached the end of the learn set? @@ -370,33 +361,180 @@ LearnMoveFromLevelUp: call GetMoveName call CopyStringToCF4B predef LearnMove + ld a, b + and a + jr z, .done + callab IsThisPartymonStarterPikachu_Party + jr nc, .done + ld a, [wMoveNum] + cp THUNDERBOLT + jr z, .foundThunderOrThunderbolt + cp THUNDER + jr nz, .done +.foundThunderOrThunderbolt + ld a, $5 + ld [wd49c], a + ld a, $85 + ld [wPikachuMood], a .done ld a, [wcf91] ld [wd11e], a ret -; writes the moves a mon has at level [wCurEnemyLVL] to [de] -; move slots are being filled up sequentially and shifted if all slots are full -WriteMonMoves: - call GetPredefRegisters - push hl - push de - push bc +Func_3b079: + ld a, [wcf91] + push af + call Func_3b0a2 + jr c, .asm_3b09c + + call Func_3b10f + jr nc, .asm_3b096 + + call Func_3b0a2 + jr c, .asm_3b09c + + call Func_3b10f + jr nc, .asm_3b096 + + call Func_3b0a2 + jr c, .asm_3b09c +.asm_3b096 + pop af + ld [wcf91], a + and a + ret +.asm_3b09c + pop af + ld [wcf91], a + scf + ret + +Func_3b0a2: +; XXX what is wcf91 entering this function? + ld a, [wd11e] + ld [wMoveNum], a + predef CanLearnTM + ld a, c + and a + jr nz, .asm_3b0ec + ld hl, Pointer_3b0ee + ld a, [wcf91] + ld de, $1 + call IsInArray + jr c, .asm_3b0d2 + ld a, $ff + ld [wMonHGrowthRate], a + ld a, [wd11e] + ld hl, wMonHMoves + ld de, $1 + call IsInArray + jr c, .asm_3b0ec +.asm_3b0d2 + ld a, [wd11e] + ld d, a + call GetMonLearnset +.loop + ld a, [hli] + and a + jr z, .asm_3b0ea + ld b, a + ld a, [wCurEnemyLVL] + cp b + jr c, .asm_3b0ea + ld a, [hli] + cp d + jr z, .asm_3b0ec + jr .loop +.asm_3b0ea + and a + ret +.asm_3b0ec + scf + ret + +Pointer_3b0ee: + db NIDOKING + db IVYSAUR + db EXEGGUTOR + db GENGAR + db NIDOQUEEN + db ARCANINE + db GYARADOS + db BLASTOISE + db GOLEM + db DRAGONITE + db NINETALES + db DRAGONAIR + db KABUTOPS + db OMASTAR + db JIGGLYPUFF + db FLAREON + db JOLTEON + db VAPOREON + db BEEDRILL + db BUTTERFREE + db MACHAMP + db CLOYSTER + db CLEFABLE + db ALAKAZAM + db STARMIE + db VENUSAUR + db TENTACRUEL + db CHARMELEON + db WARTORTLE + db CHARIZARD + db VILEPLUME + db VICTREEBEL + db $ff + +Func_3b10f: + ld c, $0 +.asm_3b111 ld hl, EvosMovesPointerTable - ld b, 0 - ld a, [wcf91] ; cur mon ID - dec a - add a - rl b - ld c, a + ld b, $0 + add hl, bc add hl, bc ld a, [hli] ld h, [hl] ld l, a -.skipEvoEntriesLoop +.asm_3b11b ld a, [hli] and a - jr nz, .skipEvoEntriesLoop + jr z, .asm_3b130 + cp $2 + jr nz, .asm_3b124 + inc hl +.asm_3b124 + inc hl + ld a, [wcf91] + cp [hl] + jr z, .asm_3b138 + inc hl + ld a, [hl] + and a + jr nz, .asm_3b11b +.asm_3b130 + inc c + ld a, c + cp VICTREEBEL + jr c, .asm_3b111 + and a + ret +.asm_3b138 + inc c + ld a, c + ld [wcf91], a + scf + ret + +; writes the moves a mon has at level [wCurEnemyLVL] to [de] +; move slots are being filled up sequentially and shifted if all slots are full +WriteMonMoves: + call GetPredefRegisters + push hl + push de + push bc + call GetMonLearnset jr .firstMove .nextMove pop de @@ -510,4 +648,21 @@ WriteMonMoves_ShiftMoveData: Evolution_FlagAction: predef_jump FlagActionPredef +GetMonLearnset: + ld hl, EvosMovesPointerTable + ld b, 0 + ld a, [wcf91] + dec a + ld c, a + add hl, bc + add hl, bc + ld a, [hli] + ld h, [hl] + ld l, a +.skipEvolutionDataLoop ; loop to skip past the evolution data, which comes before the move data + ld a, [hli] + and a ; have we reached the end of the evolution data? + jr nz, .skipEvolutionDataLoop ; if not, jump back up + ret + INCLUDE "data/evos_moves.asm" diff --git a/engine/gamefreak.asm b/engine/gamefreak.asm index 5226072b..5472a56e 100755 --- a/engine/gamefreak.asm +++ b/engine/gamefreak.asm @@ -3,6 +3,8 @@ LoadShootingStarGraphics: ld [rOBP0], a ld a, $a4 ld [rOBP1], a + call UpdateGBCPal_OBP0 + call UpdateGBCPal_OBP1 ld de, AnimationTileset2 + $30 ; star tile (top left quadrant) ld hl, vChars1 + $200 lb bc, BANK(AnimationTileset2), $01 @@ -75,6 +77,7 @@ AnimateShootingStar: ld hl, rOBP0 rrc [hl] rrc [hl] + call UpdateGBCPal_OBP0 ld c, 10 call CheckForUserInterruption ret c @@ -118,6 +121,15 @@ AnimateShootingStar: ld [hli], a ; X inc de inc hl + push bc + ld a, [de] + ld b,a + ld a, [hl] + and $f0 + or b + ld [hl], a + inc de + pop bc inc hl dec c jr nz, .smallStarsInnerLoop @@ -162,27 +174,35 @@ SmallStarsWaveCoordsPointerTable: SmallStarsWave1Coords: db $68,$30 - db $68,$40 + db $05,$68 + db $40,$05 db $68,$58 - db $68,$78 + db $04,$68 + db $78,$07 SmallStarsWave2Coords: db $68,$38 - db $68,$48 + db $05,$68 + db $48,$06 db $68,$60 - db $68,$70 + db $04,$68 + db $70,$07 SmallStarsWave3Coords: db $68,$34 - db $68,$4C + db $05,$68 + db $4c,$06 db $68,$54 - db $68,$64 + db $06,$68 + db $64,$07 SmallStarsWave4Coords: - db $68,$3C - db $68,$5C - db $68,$6C - db $68,$74 + db $68,$3c + db $05,$68 + db $5c,$04 + db $68,$6c + db $07,$68 + db $74,$07 SmallStarsEmptyWave: db $FF @@ -204,7 +224,7 @@ MoveDownSmallStars: ld a, [rOBP1] xor %10100000 ld [rOBP1], a - + call UpdateGBCPal_OBP1 ld c, 3 call CheckForUserInterruption ret c @@ -232,10 +252,10 @@ GameFreakLogoOAMData: GameFreakLogoOAMDataEnd: GameFreakShootingStarOAMData: - db $00,$A0,$A0,$10 - db $00,$A8,$A0,$30 - db $08,$A0,$A1,$10 - db $08,$A8,$A1,$30 + db $00,$A0,$A0,$14 + db $00,$A8,$A0,$34 + db $08,$A0,$A1,$14 + db $08,$A8,$A1,$34 GameFreakShootingStarOAMDataEnd: FallingStar: diff --git a/engine/give_pokemon.asm b/engine/give_pokemon.asm index 49596782..6fdca2ef 100755 --- a/engine/give_pokemon.asm +++ b/engine/give_pokemon.asm @@ -44,6 +44,8 @@ _GivePokemon: ret .addToParty call SetPokedexOwnedFlag + ld hl, UnknownTerminator_f6794 + call PrintText call AddPartyMon ld a, 1 ld [wDoNotWaitForButtonPressAfterDisplayingText], a @@ -68,6 +70,9 @@ SetPokedexOwnedFlag: ld hl, GotMonText jp PrintText +UnknownTerminator_f6794: + db "@" + GotMonText: TX_FAR _GotMonText TX_SFX_ITEM_1 diff --git a/engine/hall_of_fame.asm b/engine/hall_of_fame.asm index 3c9b1723..39a7a2e3 100755 --- a/engine/hall_of_fame.asm +++ b/engine/hall_of_fame.asm @@ -58,8 +58,7 @@ AnimateHallOfFame: ld c, 80 call DelayFrames coord hl, 2, 13 - ld b, 3 - ld c, 14 + lb bc, 3, 14 call TextBoxBorder coord hl, 4, 15 ld de, HallOfFameText @@ -77,7 +76,7 @@ AnimateHallOfFame: ld bc, HOF_MON call AddNTimes ld [hl], $ff - call SaveHallOfFameTeams + callab SaveHallOfFameTeams ; useless since in same bank xor a ld [wHoFMonSpecies], a inc a @@ -122,6 +121,7 @@ HoFShowMonOrPlayer: call RunPaletteCommand ld a, %11100100 ld [rBGP], a + call UpdateGBCPal_BGP ld c, $31 ; back pic call HoFLoadMonPlayerPicTileIDs ld d, $a0 @@ -154,12 +154,27 @@ HoFDisplayAndRecordMonInfo: ld hl, wPartyMonNicks call GetPartyMonName call HoFDisplayMonInfo + ld a, [wHoFPartyMonIndex] + ld [wWhichPokemon], a + callab IsThisPartymonStarterPikachu_Party + jr nc, .asm_70336 + ld e, $22 + callab PlayPikachuSoundClip + jr .asm_7033c +.asm_70336 + ld a,[wHoFMonSpecies] + call PlayCry +.asm_7033c jp HoFRecordMonInfo +Func_7033f: + call HoFDisplayMonInfo + ld a,[wHoFMonSpecies] + jp PlayCry + HoFDisplayMonInfo: coord hl, 0, 2 - ld b, 9 - ld c, 10 + lb bc, 9, 10 call TextBoxBorder coord hl, 2, 6 ld de, HoFMonInfoText @@ -174,8 +189,7 @@ HoFDisplayMonInfo: ld [wd0b5], a coord hl, 3, 9 predef PrintMonType - ld a, [wHoFMonSpecies] - jp PlayCry + ret HoFMonInfoText: db "LEVEL/" @@ -186,10 +200,13 @@ HoFLoadPlayerPics: ld de, RedPicFront ld a, BANK(RedPicFront) call UncompressSpriteFromDE + ld a,$0 + call SwitchSRAMBankAndLatchClockData ld hl, sSpriteBuffer1 ld de, sSpriteBuffer0 ld bc, $310 call CopyData + call PrepareRTCDataAndDisableSRAM ld de, vFrontPic call InterlaceMergeSpriteBuffers ld de, RedPicBack @@ -210,12 +227,10 @@ HoFDisplayPlayerStats: SetEvent EVENT_HALL_OF_FAME_DEX_RATING predef DisplayDexRating coord hl, 0, 4 - ld b, 6 - ld c, 10 + lb bc, 6, 10 call TextBoxBorder coord hl, 5, 0 - ld b, 2 - ld c, 9 + lb bc, 2, 9 call TextBoxBorder coord hl, 7, 2 ld de, wPlayerName diff --git a/engine/hidden_object_functions14.asm b/engine/hidden_object_functions14.asm index f8cdf44e..04f9cb35 100755 --- a/engine/hidden_object_functions14.asm +++ b/engine/hidden_object_functions14.asm @@ -89,7 +89,7 @@ FightingDojoText: db "@" PrintIndigoPlateauHQText: - ld a, [wSpriteStateData1 + 9] + ld a, [wSpritePlayerStateData1FacingDirection] cp SPRITE_FACING_UP ret nz call EnableAutoTextBoxDrawing diff --git a/engine/hidden_object_functions17.asm b/engine/hidden_object_functions17.asm index c1fa5aa4..8775fd39 100755 --- a/engine/hidden_object_functions17.asm +++ b/engine/hidden_object_functions17.asm @@ -14,7 +14,7 @@ RedBedroomPCText: TX_PLAYERS_PC Route15GateLeftBinoculars: - ld a, [wSpriteStateData1 + 9] + ld a, [wSpritePlayerStateData1FacingDirection] cp SPRITE_FACING_UP ret nz call EnableAutoTextBoxDrawing @@ -22,7 +22,10 @@ Route15GateLeftBinoculars: ld a, ARTICUNO ld [wcf91], a call PlayCry - jp DisplayMonFrontSpriteInBox + call DisplayMonFrontSpriteInBox + xor a + ld [H_AUTOBGTRANSFERENABLED], a + ret Route15UpstairsBinocularsText: TX_FAR _Route15UpstairsBinocularsText @@ -52,6 +55,30 @@ KabutopsFossilText: TX_FAR _KabutopsFossilText db "@" +FanClubPicture1: + ld a, RAPIDASH + ld [wcf91], a + call DisplayMonFrontSpriteInBox + call EnableAutoTextBoxDrawing + tx_pre FanClubPicture1Text + ret + +FanClubPicture1Text: + TX_FAR _FanClubPicture1Text + db "@" + +FanClubPicture2: + ld a, FEAROW + ld [wcf91], a + call DisplayMonFrontSpriteInBox + call EnableAutoTextBoxDrawing + tx_pre FanClubPicture2Text + ret + +FanClubPicture2Text: + TX_FAR _FanClubPicture2Text + db "@" + DisplayMonFrontSpriteInBox: ; Displays a pokemon's front sprite in a pop-up window. ; [wcf91] = pokemon internal id number @@ -110,8 +137,7 @@ LinkCableHelp: ld hl, wd730 set 6, [hl] coord hl, 0, 0 - ld b, 8 - ld c, 13 + lb bc, 8, 13 call TextBoxBorder coord hl, 2, 2 ld de, HowToLinkText @@ -339,53 +365,17 @@ GymTrashScript: .openFirstLock ; Next can is trying for the second switch. SetEvent EVENT_1ST_LOCK_OPENED - - ld hl, GymTrashCans - ld a, [wGymTrashCanIndex] - ; * 5 - ld b, a - add a - add a - add b - - ld d, 0 - ld e, a - add hl, de - ld a, [hli] - -; There is a bug in this code. It should calculate a value in the range [0, 3] -; but if the mask and random number don't have any 1 bits in common, then -; the result of the AND will be 0. When 1 is subtracted from that, the value -; will become $ff. This will result in 255 being added to hl, which will cause -; hl to point to one of the zero bytes that pad the end of the ROM bank. -; Trash can 0 was intended to be able to have the second lock only when the -; first lock was in trash can 1 or 3. However, due to this bug, trash can 0 can -; have the second lock regardless of which trash can had the first lock. - - ld [hGymTrashCanRandNumMask], a - push hl - call Random - swap a - ld b, a - ld a, [hGymTrashCanRandNumMask] - and b - dec a - pop hl - - ld d, 0 - ld e, a - add hl, de - ld a, [hl] - and $f - ld [wSecondLockTrashCanIndex], a - + callab Yellow_SampleSecondTrashCan tx_pre_id VermilionGymTrashSuccessText1 jr .done .trySecondLock - ld a, [wSecondLockTrashCanIndex] - ld b, a ld a, [wGymTrashCanIndex] + ld b, a + ld a, [wSecondLockTrashCanIndex] + cp b + jr z, .openSecondLock + ld a, [wSecondLockTrashCanIndex + 1] cp b jr z, .openSecondLock @@ -413,25 +403,26 @@ GymTrashScript: GymTrashCans: ; byte 0: mask for random number ; bytes 1-4: indices of the trash cans that can have the second lock -; (but see the comment above explaining a bug regarding this) ; Note that the mask is simply the number of valid trash can indices that -; follow. The remaining bytes are filled with 0 to pad the length of each entry +; follow. The remaining bytes are filled with -1 to pad the length of each entry ; to 5 bytes. - db 2, 1, 3, 0, 0 ; 0 - db 3, 0, 2, 4, 0 ; 1 - db 2, 1, 5, 0, 0 ; 2 - db 3, 0, 4, 6, 0 ; 3 +; This is functionally replaced with GymTrashCans3a but was never removed from source. + + db 2, 1, 3, -1, -1 ; 0 + db 3, 0, 2, 4, -1 ; 1 + db 2, 1, 5, -1, -1 ; 2 + db 3, 0, 4, 6, -1 ; 3 db 4, 1, 3, 5, 7 ; 4 - db 3, 2, 4, 8, 0 ; 5 - db 3, 3, 7, 9, 0 ; 6 + db 3, 2, 4, 8, -1 ; 5 + db 3, 3, 7, 9, -1 ; 6 db 4, 4, 6, 8, 10 ; 7 - db 3, 5, 7, 11, 0 ; 8 - db 3, 6, 10, 12, 0 ; 9 + db 3, 5, 7, 11, -1 ; 8 + db 3, 6, 10, 12, -1 ; 9 db 4, 7, 9, 11, 13 ; 10 - db 3, 8, 10, 14, 0 ; 11 - db 2, 9, 13, 0, 0 ; 12 - db 3, 10, 12, 14, 0 ; 13 - db 2, 11, 13, 0, 0 ; 14 + db 3, 8, 10, 14, -1 ; 11 + db 2, 9, 13, -1, -1 ; 12 + db 3, 10, 12, 14, -1 ; 13 + db 2, 11, 13, -1, -1 ; 14 VermilionGymTrashSuccessText1: TX_FAR _VermilionGymTrashSuccessText1 diff --git a/engine/hidden_object_functions18.asm b/engine/hidden_object_functions18.asm index c6fb3109..3fd5dd47 100755 --- a/engine/hidden_object_functions18.asm +++ b/engine/hidden_object_functions18.asm @@ -3,7 +3,7 @@ GymStatues: ; if in a gym and don’t have the corresponding badge, a = GymStatueText1_id and jp PrintPredefTextID ; else ret call EnableAutoTextBoxDrawing - ld a, [wSpriteStateData1 + 9] + ld a, [wSpritePlayerStateData1FacingDirection] cp SPRITE_FACING_UP ret nz ld hl, .BadgeFlags @@ -29,14 +29,14 @@ GymStatues: jp PrintPredefTextID .BadgeFlags: - db PEWTER_GYM, %00000001 - db CERULEAN_GYM, %00000010 - db VERMILION_GYM,%00000100 - db CELADON_GYM, %00001000 - db FUCHSIA_GYM, %00010000 - db SAFFRON_GYM, %00100000 - db CINNABAR_GYM, %01000000 - db VIRIDIAN_GYM, %10000000 + db PEWTER_GYM, %00000001 + db CERULEAN_GYM, %00000010 + db VERMILION_GYM, %00000100 + db CELADON_GYM, %00001000 + db FUCHSIA_GYM, %00010000 + db SAFFRON_GYM, %00100000 + db CINNABAR_GYM, %01000000 + db VIRIDIAN_GYM, %10000000 db $ff GymStatueText1: @@ -64,7 +64,7 @@ PrintBenchGuyText: .match ld a, [hli] ld b, a - ld a, [wSpriteStateData1 + 9] + ld a, [wSpritePlayerStateData1FacingDirection] cp b jr nz, .loop ; player isn't facing left at the bench guy ld a, [hl] @@ -72,30 +72,36 @@ PrintBenchGuyText: ; format: db map id, player sprite facing direction, text id of PredefTextIDPointerTable BenchGuyTextPointers: - db VIRIDIAN_POKECENTER, SPRITE_FACING_LEFT + db VIRIDIAN_POKECENTER, SPRITE_FACING_LEFT db_tx_pre ViridianCityPokecenterBenchGuyText - db PEWTER_POKECENTER, SPRITE_FACING_LEFT + db PEWTER_POKECENTER, SPRITE_FACING_LEFT db_tx_pre PewterCityPokecenterBenchGuyText - db CERULEAN_POKECENTER, SPRITE_FACING_LEFT + db CERULEAN_POKECENTER, SPRITE_FACING_LEFT db_tx_pre CeruleanCityPokecenterBenchGuyText - db LAVENDER_POKECENTER, SPRITE_FACING_LEFT + db LAVENDER_POKECENTER, SPRITE_FACING_LEFT db_tx_pre LavenderCityPokecenterBenchGuyText - db VERMILION_POKECENTER, SPRITE_FACING_LEFT + db VERMILION_POKECENTER, SPRITE_FACING_LEFT db_tx_pre VermilionCityPokecenterBenchGuyText - db CELADON_POKECENTER, SPRITE_FACING_LEFT + db CELADON_POKECENTER, SPRITE_FACING_LEFT db_tx_pre CeladonCityPokecenterBenchGuyText - db CELADON_HOTEL, SPRITE_FACING_LEFT + db CELADON_HOTEL, SPRITE_FACING_LEFT db_tx_pre CeladonCityHotelText - db FUCHSIA_POKECENTER, SPRITE_FACING_LEFT + db FUCHSIA_POKECENTER, SPRITE_FACING_LEFT db_tx_pre FuchsiaCityPokecenterBenchGuyText - db CINNABAR_POKECENTER, SPRITE_FACING_LEFT + db CINNABAR_POKECENTER, SPRITE_FACING_LEFT db_tx_pre CinnabarIslandPokecenterBenchGuyText - db SAFFRON_POKECENTER, SPRITE_FACING_LEFT + db SAFFRON_POKECENTER, SPRITE_FACING_LEFT db_tx_pre SaffronCityPokecenterBenchGuyText - db MT_MOON_POKECENTER, SPRITE_FACING_LEFT + db MT_MOON_POKECENTER, SPRITE_FACING_LEFT db_tx_pre MtMoonPokecenterBenchGuyText - db ROCK_TUNNEL_POKECENTER,SPRITE_FACING_LEFT + db ROCK_TUNNEL_POKECENTER, SPRITE_FACING_LEFT db_tx_pre RockTunnelPokecenterBenchGuyText + db SAFARI_ZONE_WEST_REST_HOUSE,SPRITE_FACING_LEFT + db_tx_pre UnusedBenchGuyText1 + db SAFARI_ZONE_EAST_REST_HOUSE,SPRITE_FACING_LEFT + db_tx_pre UnusedBenchGuyText2 + db SAFARI_ZONE_NORTH_REST_HOUSE,SPRITE_FACING_LEFT + db_tx_pre UnusedBenchGuyText3 db $FF ViridianCityPokecenterBenchGuyText: @@ -186,7 +192,7 @@ BookcaseText: db "@" OpenPokemonCenterPC: - ld a, [wSpriteStateData1 + 9] + ld a, [wSpritePlayerStateData1FacingDirection] cp SPRITE_FACING_UP ; check to see if player is facing up ret nz call EnableAutoTextBoxDrawing diff --git a/engine/hidden_object_functions3.asm b/engine/hidden_object_functions3.asm index aaedcbca..11aecd5b 100755 --- a/engine/hidden_object_functions3.asm +++ b/engine/hidden_object_functions3.asm @@ -1,6 +1,6 @@ ; prints text for bookshelves in buildings without sign events PrintBookshelfText: - ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction + ld a, [wSpritePlayerStateData1FacingDirection] ; player's sprite facing direction cp SPRITE_FACING_UP jr nz, .noMatch ; facing up diff --git a/engine/hidden_object_functions7.asm b/engine/hidden_object_functions7.asm index 89be94fc..2498c167 100755 --- a/engine/hidden_object_functions7.asm +++ b/engine/hidden_object_functions7.asm @@ -65,8 +65,7 @@ SafariZoneGameOver: call EnableAutoTextBoxDrawing xor a ld [wAudioFadeOutControl], a - dec a - call PlaySound + call StopAllMusic ld c, BANK(SFX_Safari_Zone_PA) ld a, SFX_SAFARI_ZONE_PA call PlayMusic @@ -117,7 +116,7 @@ GameOverText: db "@" PrintCinnabarQuiz: - ld a, [wSpriteStateData1 + 9] + ld a, [wSpritePlayerStateData1FacingDirection] cp SPRITE_FACING_UP ret nz call EnableAutoTextBoxDrawing @@ -127,6 +126,8 @@ CinnabarGymQuiz: TX_ASM xor a ld [wOpponentAfterWrongAnswer], a + ld hl, wd475 + res 7, [hl] ld a, [wHiddenObjectFunctionArgument] push af and $f @@ -135,7 +136,12 @@ CinnabarGymQuiz: and $f0 swap a ld [$ffdc], a + ld a, [hGymGateIndex] ld hl, CinnabarGymQuizIntroText + cp 1 + jr z, .onFirstQuestion + ld hl, CinnabarGymQuizShortIntroText +.onFirstQuestion call PrintText ld a, [hGymGateIndex] dec a @@ -153,10 +159,18 @@ CinnabarGymQuiz: call CinnabarGymQuiz_1ea92 jp TextScriptEnd +CinnabarGymQuizDummyIntroText: + TX_FAR _CinnabarGymQuizDummyIntroText + db "@" + CinnabarGymQuizIntroText: TX_FAR _CinnabarGymQuizIntroText db "@" +CinnabarGymQuizShortIntroText: + TX_FAR _CinnabarGymQuizShortIntroText + db "@" + CinnabarQuizQuestions: dw CinnabarQuizQuestionsText1 dw CinnabarQuizQuestionsText2 @@ -189,10 +203,6 @@ CinnabarQuizQuestionsText6: TX_FAR _CinnabarQuizQuestionsText6 db "@" -CinnabarGymGateFlagAction: - EventFlagAddress hl, EVENT_CINNABAR_GYM_GATE0_UNLOCKED - predef_jump FlagActionPredef - CinnabarGymQuiz_1ea92: call YesNoChoice ld a, [$ffdc] @@ -232,6 +242,8 @@ CinnabarGymQuiz_1ea92: ld a, [hGymGateIndex] add $2 ld [wOpponentAfterWrongAnswer], a + ld hl, wd475 + set 7, [hl] ret CinnabarGymQuizCorrectText: @@ -258,6 +270,10 @@ CinnabarGymQuizIncorrectText: TX_FAR _CinnabarGymQuizIncorrectText db "@" +CinnabarGymGateFlagAction: + EventFlagAddress hl, EVENT_CINNABAR_GYM_GATE0_UNLOCKED + predef_jump FlagActionPredef + UpdateCinnabarGymGateTileBlocks_: ; Update the overworld map with open floor blocks or locked gate blocks ; depending on event flags. @@ -295,10 +311,11 @@ UpdateCinnabarGymGateTileBlocks_: .next pop bc ld [wNewTileBlockID], a - predef ReplaceTileBlock + call CinnabarGym_ReplaceTileBlock ld hl, hGymGateIndex dec [hl] jr nz, .loop + callab RedrawMapView ret CinnabarGymGateCoords: @@ -311,6 +328,34 @@ CinnabarGymGateCoords: db $02,$06,$54,$00 db $02,$03,$54,$00 + +CinnabarGym_ReplaceTileBlock: +; basically a copy of the first half of ReplaceTileBlock +; before checking if it is necessary to redraw the map view + ld hl, wOverworldMap + ld a, [wCurMapWidth] + add $6 + ld e, a + ld d, $0 + add hl, de + add hl, de + add hl, de + ld e, $3 + add hl, de + ld e, a + ld a, b + and a + jr z, .addX +.addWidthYTimesLoop + add hl, de + dec b + jr nz, .addWidthYTimesLoop +.addX + add hl, bc + ld a, [wNewTileBlockID] + ld [hl], a + ret + PrintMagazinesText: call EnableAutoTextBoxDrawing tx_pre MagazinesText @@ -322,7 +367,7 @@ MagazinesText: BillsHousePC: call EnableAutoTextBoxDrawing - ld a, [wSpriteStateData1 + 9] + ld a, [wSpritePlayerStateData1FacingDirection] cp SPRITE_FACING_UP ret nz CheckEvent EVENT_LEFT_BILLS_HOUSE_AFTER_HELPING @@ -374,9 +419,7 @@ BillsHouseInitiatedText: TX_FAR _BillsHouseInitiatedText TX_BLINK TX_ASM - ld a, $ff - ld [wNewSoundID], a - call PlaySound + call StopAllMusic ld c, 16 call DelayFrames ld a, SFX_SWITCH @@ -407,8 +450,7 @@ BillsHousePokemonList: ld hl, wd730 set 6, [hl] coord hl, 0, 0 - ld b, 10 - ld c, 9 + lb bc, 10, 9 call TextBoxBorder coord hl, 2, 2 ld de, BillsMonListText @@ -456,11 +498,12 @@ BillsHousePokemonListText2: db "@" DisplayOakLabEmailText: - ld a, [wSpriteStateData1 + 9] + ld a, [wSpritePlayerStateData1FacingDirection] cp SPRITE_FACING_UP ret nz call EnableAutoTextBoxDrawing - tx_pre_jump OakLabEmailText + tx_pre OakLabEmailText + ret OakLabEmailText: TX_FAR _OakLabEmailText diff --git a/engine/hp_bar.asm b/engine/hp_bar.asm index 221bd7a9..566a7b61 100755 --- a/engine/hp_bar.asm +++ b/engine/hp_bar.asm @@ -213,13 +213,11 @@ UpdateHPBar_PrintHPNumber: ld a, [wHPBarOldHP + 1] ld [wHPBarTempHP], a push hl - ld a, [hFlags_0xFFF6] + ld de, $15 + ld a, [hFlags_0xFFFA] bit 0, a - jr z, .asm_fb15 + jr z, .next ld de, $9 - jr .next -.asm_fb15 - ld de, $15 .next add hl, de push hl diff --git a/engine/in_game_trades.asm b/engine/in_game_trades.asm index c01bc3c3..720920df 100755 --- a/engine/in_game_trades.asm +++ b/engine/in_game_trades.asm @@ -3,13 +3,8 @@ DoInGameTradeDialogue: call SaveScreenTilesToBuffer2 ld hl, TradeMons ld a, [wWhichTrade] - ld b, a - swap a - sub b - sub b - ld c, a - ld b, 0 - add hl, bc + ld bc, $e + call AddNTimes ld a, [hli] ld [wInGameTradeGiveMonSpecies], a ld a, [hli] @@ -35,18 +30,15 @@ DoInGameTradeDialogue: ld a, [wInGameTradeReceiveMonSpecies] ld de, wInGameTradeReceiveMonName call InGameTrade_GetMonName - ld hl, wCompletedInGameTradeFlags - ld a, [wWhichTrade] - ld c, a + ld a, $4 + ld [wInGameTradeTextPointerTableIndex], a ld b, FLAG_TEST - predef FlagActionPredef + call InGameTrade_FlagActionPredef ld a, c and a - ld a, $4 - ld [wInGameTradeTextPointerTableIndex], a jr nz, .printText ; if the trade hasn't been done yet - xor a + ld a, $0 ld [wInGameTradeTextPointerTableIndex], a call .printText ld a, $1 @@ -109,11 +101,8 @@ InGameTrade_DoTrade: call AddNTimes ld a, [hl] ld [wCurEnemyLVL], a - ld hl, wCompletedInGameTradeFlags - ld a, [wWhichTrade] - ld c, a ld b, FLAG_SET - predef FlagActionPredef + call InGameTrade_FlagActionPredef ld hl, ConnectCableText call PrintText ld a, [wWhichPokemon] @@ -137,7 +126,7 @@ InGameTrade_DoTrade: ld [wMonDataLocation], a call AddPartyMon call InGameTrade_CopyDataToReceivedMon - callab EvolveTradeMon + call InGameTrade_CheckForTradeEvo call ClearScreen call InGameTrade_RestoreScreen callba RedrawMapView @@ -229,6 +218,37 @@ InGameTrade_GetReceivedMonPointer: ld d, h ret +InGameTrade_FlagActionPredef: + ld hl,wCompletedInGameTradeFlags + ld a,[wWhichTrade] + ld c,a + predef_jump FlagActionPredef + +InGameTrade_CheckForTradeEvo: + ld a,[wInGameTradeReceiveMonSpecies] + cp KADABRA + jr z,.tradeEvo + cp GRAVELER + jr z,.tradeEvo + cp MACHOKE + jr z,.tradeEvo + cp HAUNTER + jr z,.tradeEvo + ret + +.tradeEvo + ld a,[wPartyCount] + dec a + ld [wWhichPokemon],a + ld a,$1 + ld [wForceEvolution],a + ld a,LINK_STATE_TRADING + ld [wLinkState],a + callab EvolveTradeMon + xor a ; LINK_STATE_NONE + ld [wLinkState],a + jp PlayDefaultMusic + InGameTrade_TrainerString: ; "TRAINER@@@@@@@@@@" db $5d, "@@@@@@@@@@" diff --git a/engine/init_player_data.asm b/engine/init_player_data.asm index c576e65a..5883547c 100644 --- a/engine/init_player_data.asm +++ b/engine/init_player_data.asm @@ -12,6 +12,11 @@ InitPlayerData2: ld a, $ff ld [wUnusedD71B], a + ld a, 90 ; initialize happiness to 90 + ld [wPikachuHappiness], a + ld a, $80 + ld [wPikachuMood], a ; initialize mood + ld hl, wPartyCount call InitializeEmptyList ld hl, wNumInBox diff --git a/engine/intro.asm b/engine/intro.asm index a016b365..00e892da 100755 --- a/engine/intro.asm +++ b/engine/intro.asm @@ -16,8 +16,7 @@ PlayIntro: inc a ld [H_AUTOBGTRANSFERENABLED], a call PlayShootingStar - call PlayIntroScene - call GBFadeOutToWhite + callab PlayIntroScene xor a ld [hSCX], a ld [H_AUTOBGTRANSFERENABLED], a @@ -25,162 +24,6 @@ PlayIntro: call DelayFrame ret -PlayIntroScene: - ld b, SET_PAL_NIDORINO_INTRO - call RunPaletteCommand - ldPal a, BLACK, DARK_GRAY, LIGHT_GRAY, WHITE - ld [rBGP], a - ld [rOBP0], a - ld [rOBP1], a - xor a - ld [hSCX], a - ld b, GENGAR_INTRO_TILES1 - call IntroCopyTiles - ld a, 0 - ld [wBaseCoordX], a - ld a, 80 - ld [wBaseCoordY], a - lb bc, 6, 6 - call InitIntroNidorinoOAM - lb de, 80 / 2, MOVE_NIDORINO_RIGHT - call IntroMoveMon - ret c - -; hip - ld a, SFX_INTRO_HIP - call PlaySound - xor a - ld [wIntroNidorinoBaseTile], a - ld de, IntroNidorinoAnimation1 - call AnimateIntroNidorino -; hop - ld a, SFX_INTRO_HOP - call PlaySound - ld de, IntroNidorinoAnimation2 - call AnimateIntroNidorino - ld c, 10 - call CheckForUserInterruption - ret c - -; hip - ld a, SFX_INTRO_HIP - call PlaySound - ld de, IntroNidorinoAnimation1 - call AnimateIntroNidorino -; hop - ld a, SFX_INTRO_HOP - call PlaySound - ld de, IntroNidorinoAnimation2 - call AnimateIntroNidorino - ld c, 30 - call CheckForUserInterruption - ret c - -; raise - ld b, GENGAR_INTRO_TILES2 - call IntroCopyTiles - ld a, SFX_INTRO_RAISE - call PlaySound - lb de, 8 / 2, MOVE_GENGAR_LEFT - call IntroMoveMon - ld c, 30 - call CheckForUserInterruption - ret c - -; slash - ld b, GENGAR_INTRO_TILES3 - call IntroCopyTiles - ld a, SFX_INTRO_CRASH - call PlaySound - lb de, 16 / 2, MOVE_GENGAR_RIGHT - call IntroMoveMon -; hip - ld a, SFX_INTRO_HIP - call PlaySound - ld a, (FightIntroFrontMon2 - FightIntroFrontMon) / BYTES_PER_TILE - ld [wIntroNidorinoBaseTile], a - ld de, IntroNidorinoAnimation3 - call AnimateIntroNidorino - ld c, 30 - call CheckForUserInterruption - ret c - - lb de, 8 / 2, MOVE_GENGAR_LEFT - call IntroMoveMon - ld b, GENGAR_INTRO_TILES1 - call IntroCopyTiles - ld c, 60 - call CheckForUserInterruption - ret c - -; hip - ld a, SFX_INTRO_HIP - call PlaySound - xor a - ld [wIntroNidorinoBaseTile], a - ld de, IntroNidorinoAnimation4 - call AnimateIntroNidorino -; hop - ld a, SFX_INTRO_HOP - call PlaySound - ld de, IntroNidorinoAnimation5 - call AnimateIntroNidorino - ld c, 20 - call CheckForUserInterruption - ret c - - ld a, (FightIntroFrontMon2 - FightIntroFrontMon) / BYTES_PER_TILE - ld [wIntroNidorinoBaseTile], a - ld de, IntroNidorinoAnimation6 - call AnimateIntroNidorino - ld c, 30 - call CheckForUserInterruption - ret c - -; lunge - ld a, SFX_INTRO_LUNGE - call PlaySound - ld a, (FightIntroFrontMon3 - FightIntroFrontMon) / BYTES_PER_TILE - ld [wIntroNidorinoBaseTile], a - ld de, IntroNidorinoAnimation7 - jp AnimateIntroNidorino - -AnimateIntroNidorino: - ld a, [de] - cp ANIMATION_END - ret z - ld [wBaseCoordY], a - inc de - ld a, [de] - ld [wBaseCoordX], a - push de - ld c, 6 * 6 - call UpdateIntroNidorinoOAM - ld c, 5 - call DelayFrames - pop de - inc de - jr AnimateIntroNidorino - -UpdateIntroNidorinoOAM: - ld hl, wOAMBuffer - ld a, [wIntroNidorinoBaseTile] - ld d, a -.loop - ld a, [wBaseCoordY] - add [hl] - ld [hli], a ; Y - ld a, [wBaseCoordX] - add [hl] - ld [hli], a ; X - ld a, d - ld [hli], a ; tile - inc hl - inc d - dec c - jr nz, .loop - ret - InitIntroNidorinoOAM: ld hl, wOAMBuffer ld d, 0 @@ -237,83 +80,17 @@ IntroPlaceBlackTiles: jr nz, .loop ret -IntroMoveMon: -; d = number of times to move the mon (2 pixels each time) - ld a, e - cp MOVE_NIDORINO_RIGHT - jr z, .moveNidorinoRight - cp MOVE_GENGAR_LEFT - jr z, .moveGengarLeft -; move Gengar right - ld a, [hSCX] - dec a - dec a - jr .next -.moveNidorinoRight - push de - ld a, 2 - ld [wBaseCoordX], a - xor a - ld [wBaseCoordY], a - ld c, 6 * 6 - call UpdateIntroNidorinoOAM - pop de -.moveGengarLeft - ld a, [hSCX] - inc a - inc a -.next - ld [hSCX], a - push de - ld c, 2 - call CheckForUserInterruption - pop de - ret c - dec d - jr nz, IntroMoveMon - ret - -IntroCopyTiles: - coord hl, 13, 7 - CopyTileIDsFromList_ZeroBaseTileID: ld c, 0 predef_jump CopyTileIDsFromList -PlayMoveSoundB: -; unused - predef GetMoveSoundB - ld a, b - jp PlaySound - -LoadIntroGraphics: - ld hl, FightIntroBackMon - ld de, vChars2 - ld bc, FightIntroBackMonEnd - FightIntroBackMon - ld a, BANK(FightIntroBackMon) - call FarCopyData2 - ld hl, GameFreakIntro - ld de, vChars2 + (FightIntroBackMonEnd - FightIntroBackMon) - ld bc, GameFreakIntroEnd - GameFreakIntro - ld a, BANK(GameFreakIntro) - call FarCopyData2 - ld hl, GameFreakIntro - ld de, vChars1 - ld bc, GameFreakIntroEnd - GameFreakIntro - ld a, BANK(GameFreakIntro) - call FarCopyData2 - ld hl, FightIntroFrontMon - ld de, vChars0 - ld bc, FightIntroFrontMonEnd - FightIntroFrontMon - ld a, BANK(FightIntroFrontMon) - jp FarCopyData2 - PlayShootingStar: ld b, SET_PAL_GAME_FREAK_INTRO call RunPaletteCommand callba LoadCopyrightAndTextBoxTiles ldPal a, BLACK, DARK_GRAY, LIGHT_GRAY, WHITE ld [rBGP], a + call UpdateGBCPal_BGP ld c, 180 call DelayFrames call ClearScreen @@ -321,7 +98,27 @@ PlayShootingStar: xor a ld [wCurOpponent], a call IntroDrawBlackBars - call LoadIntroGraphics +; write the black and white tiles + ld hl, vChars2 + ld bc, $10 + xor a + call FillMemory + ld hl, vChars2 + $10 + ld bc, $10 + ld a, $ff + call FillMemory +; copy gamefreak logo and others + ld hl, GameFreakIntro + ld de, vChars2 + $600 + ld bc, GameFreakIntroEnd - GameFreakIntro + ld a, BANK(GameFreakIntro) + call FarCopyData + ld hl, GameFreakIntro + ld de, vChars1 + ld bc, GameFreakIntroEnd - GameFreakIntro + ld a, BANK(GameFreakIntro) + call FarCopyData + call EnableLCD ld hl, rLCDC res 5, [hl] @@ -335,12 +132,6 @@ PlayShootingStar: ld c, 40 call DelayFrames .next - ld a, BANK(Music_IntroBattle) - ld [wAudioROMBank], a - ld [wAudioSavedROMBank], a - ld a, MUSIC_INTRO_BATTLE - ld [wNewSoundID], a - call PlaySound call IntroClearMiddleOfScreen call ClearSprites jp Delay3 @@ -364,79 +155,6 @@ IntroDrawBlackBars: EmptyFunc4: ret -IntroNidorinoAnimation0: - db 0, 0 - db ANIMATION_END - -IntroNidorinoAnimation1: -; This is a sequence of pixel movements for part of the Nidorino animation. This -; list describes how Nidorino should hop. -; First byte is y movement, second byte is x movement - db 0, 0 - db -2, 2 - db -1, 2 - db 1, 2 - db 2, 2 - db ANIMATION_END - -IntroNidorinoAnimation2: -; This is a sequence of pixel movements for part of the Nidorino animation. -; First byte is y movement, second byte is x movement - db 0, 0 - db -2, -2 - db -1, -2 - db 1, -2 - db 2, -2 - db ANIMATION_END - -IntroNidorinoAnimation3: -; This is a sequence of pixel movements for part of the Nidorino animation. -; First byte is y movement, second byte is x movement - db 0, 0 - db -12, 6 - db -8, 6 - db 8, 6 - db 12, 6 - db ANIMATION_END - -IntroNidorinoAnimation4: -; This is a sequence of pixel movements for part of the Nidorino animation. -; First byte is y movement, second byte is x movement - db 0, 0 - db -8, -4 - db -4, -4 - db 4, -4 - db 8, -4 - db ANIMATION_END - -IntroNidorinoAnimation5: -; This is a sequence of pixel movements for part of the Nidorino animation. -; First byte is y movement, second byte is x movement - db 0, 0 - db -8, 4 - db -4, 4 - db 4, 4 - db 8, 4 - db ANIMATION_END - -IntroNidorinoAnimation6: -; This is a sequence of pixel movements for part of the Nidorino animation. -; First byte is y movement, second byte is x movement - db 0, 0 - db 2, 0 - db 2, 0 - db 0, 0 - db ANIMATION_END - -IntroNidorinoAnimation7: -; This is a sequence of pixel movements for part of the Nidorino animation. -; First byte is y movement, second byte is x movement - db -8, -16 - db -7, -14 - db -6, -12 - db -4, -10 - db ANIMATION_END - GameFreakIntro: INCBIN "gfx/gamefreak_intro.2bpp" INCBIN "gfx/gamefreak_logo.2bpp" @@ -444,29 +162,3 @@ GameFreakIntro: db $00 ; blank tile endr GameFreakIntroEnd: - -FightIntroBackMon: - INCBIN "gfx/intro_fight.2bpp" -FightIntroBackMonEnd: - -FightIntroFrontMon: - -IF DEF(_RED) - INCBIN "gfx/red/intro_nido_1.2bpp" -FightIntroFrontMon2: - INCBIN "gfx/red/intro_nido_2.2bpp" -FightIntroFrontMon3: - INCBIN "gfx/red/intro_nido_3.2bpp" -ENDC - -IF DEF(_BLUE) - INCBIN "gfx/blue/intro_purin_1.2bpp" -FightIntroFrontMon2: - INCBIN "gfx/blue/intro_purin_2.2bpp" -FightIntroFrontMon3: - INCBIN "gfx/blue/intro_purin_3.2bpp" -ENDC - -FightIntroFrontMonEnd: - - ds $10 ; blank tile diff --git a/engine/items/inventory.asm b/engine/items/inventory.asm index d07f64eb..58bcf7e9 100644 --- a/engine/items/inventory.asm +++ b/engine/items/inventory.asm @@ -27,16 +27,17 @@ AddItemToInventory_: ld a, [hli] and a jr z, .addNewItem -.loop +.notAtEndOfInventory ld a, [hli] ld b, a ; b = ID of current item in table ld a, [wcf91] ; a = ID of item being added cp b ; does the current item in the table match the item being added? jp z, .increaseItemQuantity ; if so, increase the item's quantity inc hl +.loop ld a, [hl] - cp $ff ; is it the end of the table? - jr nz, .loop + cp a, $ff ; is it the end of the table? + jr nz, .notAtEndOfInventory .addNewItem ; add an item not yet in the inventory pop hl ld a, d @@ -101,7 +102,7 @@ RemoveItemFromInventory_: push hl inc hl ld a, [wWhichPokemon] ; index (within the inventory) of the item being removed - sla a + add a add l ld l, a jr nc, .noCarry diff --git a/engine/items/items.asm b/engine/items/items.asm index ec51a0d4..15c7c24f 100755 --- a/engine/items/items.asm +++ b/engine/items/items.asm @@ -113,7 +113,9 @@ ItemUseBall: ; If this is for the old man battle, skip checking if the party & box are full. ld a, [wBattleType] - dec a + cp BATTLE_TYPE_OLD_MAN + jr z, .canUseBall + cp BATTLE_TYPE_PIKACHU jr z, .canUseBall ld a, [wPartyCount] ; is party full? @@ -152,16 +154,26 @@ ItemUseBall: jp z, .setAnimData ld a, [wBattleType] - dec a - jr nz, .notOldManBattle + cp BATTLE_TYPE_OLD_MAN + jr z, .oldManBattle + cp BATTLE_TYPE_PIKACHU + jr z, .oldManBattle ; pikachu battle technically old man battle + jr .notOldManBattle .oldManBattle ld hl, wGrassRate ld de, wPlayerName ld bc, NAME_LENGTH call CopyData ; save the player's name in the Wild Monster data (part of the Cinnabar Island Missingno. glitch) + ld a, [wBattleType] + cp BATTLE_TYPE_OLD_MAN + jp nz,.captured + ld a,$1 + ld [wCapturedMonSpecies], a + CheckEvent EVENT_02F + ld b, $63 + jp nz,.setAnimData jp .captured - .notOldManBattle ; If the player is fighting the ghost Marowak, set the value that indicates the ; Pokémon can't be caught and skip the capture calculations. @@ -280,6 +292,7 @@ ItemUseBall: inc a .skip2 + ; Let W = ((MaxHP * 255) / BallFactor) / max(HP / 4, 1). Calculate W. ld [H_DIVISOR], a ld b, 4 @@ -347,6 +360,7 @@ ItemUseBall: jr z, .skip4 .skip4 + ; Let Y = (CatchRate * 100) / BallFactor2. Calculate Y. ld a, b ld [H_DIVISOR], a @@ -371,7 +385,7 @@ ItemUseBall: ld [H_DIVISOR], a ld b, 4 call Divide - + ; Determine Status2. ; no status ailment: Status2 = 0 ; Burn/Paralysis/Poison: Status2 = 5 @@ -511,9 +525,10 @@ ItemUseBall: ld [wcf91], a ld [wd11e], a ld a, [wBattleType] - dec a ; is this the old man battle? - jr z, .oldManCaughtMon ; if so, don't give the player the caught Pokémon - + cp BATTLE_TYPE_OLD_MAN ; is this the old man battle? + jp z, .oldManCaughtMon ; if so, don't give the player the caught Pokémon + cp BATTLE_TYPE_PIKACHU + jr z, .oldManCaughtMon ; same with Pikachu battle ld hl, ItemUseBallText05 call PrintText @@ -545,12 +560,18 @@ ItemUseBall: predef ShowPokedexData .skipShowingPokedexData + ld a, $1 + ld [wd49c], a + ld a, $85 + ld [wPikachuMood], a ld a, [wPartyCount] cp PARTY_LENGTH ; is party full? jr z, .sendToBox xor a ; PLAYER_PARTY_DATA ld [wMonDataLocation], a call ClearSprites + ld hl, .emptyString + call PrintText call AddPartyMon jr .done @@ -583,6 +604,9 @@ ItemUseBall: ld [wItemQuantity], a jp RemoveItemFromInventory +.emptyString + db "@" + ItemUseBallText00: ;"It dodged the thrown ball!" ;"This pokemon can't be caught" @@ -648,21 +672,28 @@ ItemUseBicycle: call ItemUseReloadOverworldData xor a ld [wWalkBikeSurfState], a ; change player state to walking + ld a, $00 + ld [wPikachuSpawnState], a call PlayDefaultMusic ; play walking music ld hl, GotOffBicycleText - jr .printText + jp PrintText + .tryToGetOnBike call IsBikeRidingAllowed jp nc, NoCyclingAllowedHere call ItemUseReloadOverworldData xor a ; no keys pressed ld [hJoyHeld], a ; current joypad state - inc a + ld a, $1 ld [wWalkBikeSurfState], a ; change player state to bicycling - ld hl, GotOnBicycleText call PlayDefaultMusic ; play bike riding music -.printText - jp PrintText + xor a + ld [wWalkBikeSurfState], a + ld hl, GotOnBicycleText + call PrintText + ld a, $1 + ld [wWalkBikeSurfState], a + ret ; used for Surf out-of-battle effect ItemUseSurfboard: @@ -672,7 +703,7 @@ ItemUseSurfboard: jr z, .tryToStopSurfing .tryToSurf call IsNextTileShoreOrWater - jp c, SurfingAttemptFailed + jp nc, SurfingAttemptFailed ld hl, TilePairCollisionsWater call CheckForTilePairCollisions jp c, SurfingAttemptFailed @@ -685,6 +716,7 @@ ItemUseSurfboard: call PlayDefaultMusic ; play surfing music ld hl, SurfingGotOnText jp PrintText + .tryToStopSurfing xor a ld [hSpriteIndexOrTextID], a @@ -697,23 +729,20 @@ ItemUseSurfboard: ld hl, TilePairCollisionsWater call CheckForTilePairCollisions jr c, .cannotStopSurfing - ld hl, wTilesetCollisionPtr ; pointer to list of passable tiles - ld a, [hli] - ld h, [hl] - ld l, a ; hl now points to passable tiles - ld a, [wTileInFrontOfPlayer] ; tile in front of the player - ld b, a -.passableTileLoop - ld a, [hli] - cp b - jr z, .stopSurfing - cp $ff - jr nz, .passableTileLoop + ld a, [wTileInFrontOfPlayer] + ld c, a + call IsTilePassable + jr nc, .stopSurfing .cannotStopSurfing ld hl, SurfingNoPlaceToGetOffText jp PrintText + .stopSurfing call .makePlayerMoveForward + ld a, $3 + ld [wPikachuSpawnState], a + ld hl, wPikachuOverworldStateFlags + set 5, [hl] ld hl, wd730 set 7, [hl] xor a @@ -721,7 +750,9 @@ ItemUseSurfboard: dec a ld [wJoyIgnore], a call PlayDefaultMusic ; play walking music + call GBPalWhiteOutWithDelay3 jp LoadWalkingPlayerSpriteGraphics + ; uses a simulated button press to make the player move forward .makePlayerMoveForward ld a, [wPlayerDirection] ; direction the player is going @@ -769,25 +800,43 @@ ItemUseEvoStone: ld a, $ff ld [wUpdateSpritesEnabled], a call DisplayPartyMenu + ld a, [wcf91] + ld [wLoadedMon], a pop bc jr c, .canceledItemUse ld a, b ld [wcf91], a - ld a, $01 - ld [wForceEvolution], a + call Func_d85d + jr nc, .noEffect + callab IsThisPartymonStarterPikachu_Party + jr nc, .notPlayerPikachu + ld e, $1b + callab PlayPikachuSoundClip + ld a, [wWhichPokemon] + ld hl, wPartyMonNicks + call GetPartyMonName + ld hl, RefusingText + call PrintText + ld a, $4 + ld [wd49c], a + ld a, $82 + ld [wPikachuMood], a + jr .canceledItemUse + +.notPlayerPikachu ld a, SFX_HEAL_AILMENT call PlaySoundWaitForCurrent call WaitForSoundToFinish + ld a, $01 + ld [wForceEvolution], a callab TryEvolvingMon ; try to evolve pokemon - ld a, [wEvolutionOccurred] - and a - jr z, .noEffect pop af ld [wWhichPokemon], a ld hl, wNumBagItems ld a, 1 ; remove 1 stone ld [wItemQuantity], a jp RemoveItemFromInventory + .noEffect call ItemUseNoEffect .canceledItemUse @@ -796,6 +845,55 @@ ItemUseEvoStone: pop af ret +Func_d85d: + ld hl, EvosMovesPointerTable + ld a, [wLoadedMon] + dec a + ld c, a + ld b, $0 + add hl, bc + add hl, bc + ld de, wcd6d + ld a, BANK(TryEvolvingMon) + ld bc, $2 + call FarCopyData + ld hl, wcd6d + ld a, [hli] + ld h, [hl] + ld l, a + ld de, wcd6d + ld a, BANK(TryEvolvingMon) + ld bc, 13 + call FarCopyData + ld hl, wcd6d +.loop + ld a, [hli] + and a + jr z, .cannotEvolveWithUsedStone + inc hl + inc hl + cp EV_ITEM + jr nz, .loop + dec hl + dec hl + ld b, [hl] + ld a, [wcf91] + inc hl + inc hl + inc hl + cp b + jr nz, .loop + scf + ret + +.cannotEvolveWithUsedStone + and a + ret + +RefusingText: + TX_FAR _RefusingText + db "@" + ItemUseVitamin: ld a, [wIsInBattle] and a @@ -804,7 +902,7 @@ ItemUseVitamin: ItemUseMedicine: ld a, [wPartyCount] and a - jp z, .emptyParty + jp z, Func_e4bf ld a, [wWhichPokemon] push af ld a, [wcf91] @@ -819,15 +917,6 @@ ItemUseMedicine: ; if using softboiled call GoBackToPartyMenu jr .getPartyMonDataAddress -.emptyParty - ld hl, .emptyPartyText - xor a - ld [wActionResultOrTookBattleTurn], a ; item use failed - jp PrintText -.emptyPartyText - text "You don't have" - line "any #MON!" - prompt .notUsingSoftboiled call DisplayPartyMenu .getPartyMonDataAddress @@ -843,6 +932,16 @@ ItemUseMedicine: ld e, a ld [wd0b5], a pop af + push af + cp $28 + jr nc, .asm_d906 + push hl + push de + callabd_ModifyPikachuHappiness PIKAHAPPY_USEDITEM + pop de + pop hl +.asm_d906 + pop af ld [wcf91], a pop af ld [wWhichPokemon], a @@ -910,6 +1009,7 @@ ItemUseMedicine: call CopyData ; copy party stats to in-battle stat data predef DoubleOrHalveSelectedStats jp .doneHealing + .healHP inc hl ; hl = address of current HP ld a, [hli] @@ -927,7 +1027,22 @@ ItemUseMedicine: cp MAX_REVIVE jr z, .updateInBattleFaintedData jp .healingItemNoEffect + .updateInBattleFaintedData + ld a, [wWhichPokemon] + push af + ld a, [wUsedItemOnWhichPokemon] + ld [wWhichPokemon], a + push hl + push de + push bc + callab Func_2fd6a + pop bc + pop de + pop hl + pop af + ld [wWhichPokemon], a + ld a, [wIsInBattle] and a jr z, .compareCurrentHPToMaxHP @@ -952,6 +1067,7 @@ ItemUseMedicine: pop de pop hl jr .compareCurrentHPToMaxHP + .notFainted ld a, [wcf91] cp REVIVE @@ -987,6 +1103,7 @@ ItemUseMedicine: dec hl dec hl jp .cureStatusAilment + .notFullHP ; if the pokemon's current HP doesn't equal its max HP xor a ld [wLowHealthAlarm], a ;disable low health alarm @@ -1050,15 +1167,15 @@ ItemUseMedicine: call AddNTimes ; calculate coordinates of HP bar of pokemon that used Softboiled ld a, SFX_HEAL_HP call PlaySoundWaitForCurrent - ld a, [hFlags_0xFFF6] + ld a, [hFlags_0xFFFA] set 0, a - ld [hFlags_0xFFF6], a + ld [hFlags_0xFFFA], a ld a, $02 ld [wHPBarType], a predef UpdateHPBar2 ; animate HP bar decrease of pokemon that used Softboiled - ld a, [hFlags_0xFFF6] + ld a, [hFlags_0xFFFA] res 0, a - ld [hFlags_0xFFF6], a + ld [hFlags_0xFFFA], a pop af ld b, a ; store heal amount (1/5 of max HP) ld hl, wHPBarOldHP + 1 @@ -1071,6 +1188,7 @@ ItemUseMedicine: pop af ld [hl], a jr .addHealAmount + .notUsingSoftboiled2 ld a, [wcf91] cp SODA_POP @@ -1125,6 +1243,7 @@ ItemUseMedicine: cp MAX_REVIVE jr z, .setCurrentHPToMaxHp ; if using a Max Revive jr .updateInBattleData + .setCurrentHPToHalfMaxHP dec hl dec de @@ -1139,6 +1258,7 @@ ItemUseMedicine: ld [wHPBarNewHP], a dec de jr .doneHealingPartyHP + .setCurrentHPToMaxHp ld a, [hli] ld [de], a @@ -1182,9 +1302,11 @@ ItemUseMedicine: dec d jr nz, .calculateHPBarCoordsLoop jr .doneHealing + .healingItemNoEffect call ItemUseNoEffect jp .done + .doneHealing ld a, [wPseudoItemID] and a ; using Softboiled? @@ -1200,15 +1322,15 @@ ItemUseMedicine: jr z, .playStatusAilmentCuringSound ld a, SFX_HEAL_HP call PlaySoundWaitForCurrent - ld a, [hFlags_0xFFF6] + ld a, [hFlags_0xFFFA] set 0, a - ld [hFlags_0xFFF6], a + ld [hFlags_0xFFFA], a ld a, $02 ld [wHPBarType], a predef UpdateHPBar2 ; animate the HP bar lengthening - ld a, [hFlags_0xFFF6] + ld a, [hFlags_0xFFFA] res 0, a - ld [hFlags_0xFFF6], a + ld [hFlags_0xFFFA], a ld a, REVIVE_MSG ld [wPartyMenuTypeOrMessageID], a ld a, [wcf91] @@ -1219,6 +1341,7 @@ ItemUseMedicine: ld a, POTION_MSG ld [wPartyMenuTypeOrMessageID], a jr .showHealingItemMessage + .playStatusAilmentCuringSound ld a, SFX_HEAL_AILMENT call PlaySoundWaitForCurrent @@ -1235,6 +1358,7 @@ ItemUseMedicine: call DelayFrames call WaitForTextScrollButtonPress jr .done + .canceledItemUse xor a ld [wActionResultOrTookBattleTurn], a ; item use failed @@ -1250,6 +1374,7 @@ ItemUseMedicine: and a ret nz jp ReloadMapData + .useVitamin push hl ld a, [hl] @@ -1305,6 +1430,7 @@ ItemUseMedicine: cp b jr nz, .statNameInnerLoop jr .statNameLoop + .gotStatName ld de, wcf4b ld bc, 10 @@ -1314,11 +1440,13 @@ ItemUseMedicine: ld hl, VitaminStatRoseText call PrintText jp RemoveUsedItem + .vitaminNoEffect pop hl ld hl, VitaminNoEffectText call PrintText jp GBPalWhiteOut + .recalculateStats ld bc, wPartyMon1Stats - wPartyMon1 add hl, bc @@ -1405,9 +1533,19 @@ ItemUseMedicine: xor a ; PLAYER_PARTY_DATA ld [wMonDataLocation], a predef LearnMoveFromLevelUp ; learn level up move, if any + xor a ld [wForceEvolution], a - callab TryEvolvingMon ; evolve pokemon, if appropriate + callabd_ModifyPikachuHappiness PIKAHAPPY_LEVELUP + ld a, [wWhichPokemon] + push af + ld a, [wUsedItemOnWhichPokemon] + ld [wWhichPokemon], a + callab Func_2fd6a ; evolve pokemon, if appropriate + pop af + ld [wWhichPokemon], a + + callab TryEvolvingMon ld a, $01 ld [wUpdateSpritesEnabled], a pop af @@ -1494,6 +1632,10 @@ ItemUseEscapeRope: ld a, [wCurMap] cp AGATHAS_ROOM jr z, .notUsable + cp BILLS_HOUSE + jr z, .notUsable + cp POKEMON_FAN_CLUB + jr z, .notUsable ld a, [wCurMapTileset] ld b, a ld hl, EscapeRopeTilesets @@ -1506,6 +1648,7 @@ ItemUseEscapeRope: ld hl, wd732 set 3, [hl] set 6, [hl] + call Func_1510 ld hl, wd72e res 4, [hl] ResetEvent EVENT_IN_SAFARI_ZONE @@ -1522,6 +1665,7 @@ ItemUseEscapeRope: ld c, 30 call DelayFrames jp RemoveUsedItem + .notUsable jp ItemUseNotTime @@ -1547,6 +1691,7 @@ ItemUseXAccuracy: jp z, ItemUseNotTime ld hl, wPlayerBattleStatus2 set USING_X_ACCURACY, [hl] ; X Accuracy bit + callabd_ModifyPikachuHappiness PIKAHAPPY_USEDXITEM jp PrintItemUseTextAndRemoveItem ; This function is bugged and never works. It always jumps to ItemUseNotTime. @@ -1560,11 +1705,13 @@ ItemUseCardKey: jr nz, .next0 ld hl, CardKeyTable1 jr .next1 + .next0 cp $24 jr nz, .next2 ld hl, CardKeyTable2 jr .next1 + .next2 cp $5e jp nz, ItemUseNotTime @@ -1587,6 +1734,7 @@ ItemUseCardKey: ld a, [hl] ld [wUnusedD71F], a jr .done + .nextEntry1 inc hl .nextEntry2 @@ -1594,6 +1742,7 @@ ItemUseCardKey: .nextEntry3 inc hl jr .loop + .done ld hl, ItemUseText00 call PrintText @@ -1612,34 +1761,34 @@ ItemUseCardKey: ; 03: ID? CardKeyTable1: - db SILPH_CO_2F,$04,$04,$00 - db SILPH_CO_2F,$04,$05,$01 - db SILPH_CO_4F,$0C,$04,$02 - db SILPH_CO_4F,$0C,$05,$03 - db SILPH_CO_7F,$06,$0A,$04 - db SILPH_CO_7F,$06,$0B,$05 - db SILPH_CO_9F,$04,$12,$06 - db SILPH_CO_9F,$04,$13,$07 - db SILPH_CO_10F,$08,$0A,$08 - db SILPH_CO_10F,$08,$0B,$09 + db SILPH_CO_2F, $04, $04, $00 + db SILPH_CO_2F, $04, $05, $01 + db SILPH_CO_4F, $0C, $04, $02 + db SILPH_CO_4F, $0C, $05, $03 + db SILPH_CO_7F, $06, $0A, $04 + db SILPH_CO_7F, $06, $0B, $05 + db SILPH_CO_9F, $04, $12, $06 + db SILPH_CO_9F, $04, $13, $07 + db SILPH_CO_10F, $08, $0A, $08 + db SILPH_CO_10F, $08, $0B, $09 db $ff CardKeyTable2: - db SILPH_CO_3F,$08,$09,$0A - db SILPH_CO_3F,$09,$09,$0B - db SILPH_CO_5F,$04,$07,$0C - db SILPH_CO_5F,$05,$07,$0D - db SILPH_CO_6F,$0C,$05,$0E - db SILPH_CO_6F,$0D,$05,$0F - db SILPH_CO_8F,$08,$07,$10 - db SILPH_CO_8F,$09,$07,$11 - db SILPH_CO_9F,$08,$03,$12 - db SILPH_CO_9F,$09,$03,$13 + db SILPH_CO_3F, $08, $09, $0A + db SILPH_CO_3F, $09, $09, $0B + db SILPH_CO_5F, $04, $07, $0C + db SILPH_CO_5F, $05, $07, $0D + db SILPH_CO_6F, $0C, $05, $0E + db SILPH_CO_6F, $0D, $05, $0F + db SILPH_CO_8F, $08, $07, $10 + db SILPH_CO_8F, $09, $07, $11 + db SILPH_CO_9F, $08, $03, $12 + db SILPH_CO_9F, $09, $03, $13 db $ff CardKeyTable3: - db SILPH_CO_11F,$08,$09,$14 - db SILPH_CO_11F,$09,$09,$15 + db SILPH_CO_11F, $08, $09, $14 + db SILPH_CO_11F, $09, $09, $15 db $ff ItemUsePokedoll: @@ -1654,6 +1803,15 @@ ItemUseGuardSpec: ld a, [wIsInBattle] and a jp z, ItemUseNotTime + + ld a, [wWhichPokemon] + push af + ld a, [wPlayerMonNumber] + ld [wWhichPokemon], a + callabd_ModifyPikachuHappiness PIKAHAPPY_USEDXITEM + pop af + ld [wWhichPokemon], a + ld hl, wPlayerBattleStatus2 set PROTECTED_BY_MIST, [hl] ; Mist bit jp PrintItemUseTextAndRemoveItem @@ -1670,6 +1828,15 @@ ItemUseDireHit: ld a, [wIsInBattle] and a jp z, ItemUseNotTime + + ld a, [wWhichPokemon] + push af + ld a, [wPlayerMonNumber] + ld [wWhichPokemon], a + callabd_ModifyPikachuHappiness PIKAHAPPY_USEDXITEM + pop af + ld [wWhichPokemon], a + ld hl, wPlayerBattleStatus2 set GETTING_PUMPED, [hl] ; Focus Energy bit jp PrintItemUseTextAndRemoveItem @@ -1682,6 +1849,7 @@ ItemUseXStat: ld a, 2 ld [wActionResultOrTookBattleTurn], a ; item not used ret + .inBattle ld hl, wPlayerMoveNum ld a, [hli] @@ -1700,6 +1868,15 @@ ItemUseXStat: xor a ld [H_WHOSETURN], a ; set turn to player's turn callba StatModifierUpEffect ; do stat increase move + + ld a, [wWhichPokemon] + push af + ld a, [wPlayerMonNumber] + ld [wWhichPokemon], a + callabd_ModifyPikachuHappiness PIKAHAPPY_USEDXITEM + pop af + ld [wWhichPokemon], a + pop hl pop af ld [hld], a ; restore [wPlayerMoveEffect] @@ -1717,31 +1894,48 @@ ItemUsePokeflute: cp ROUTE_12 jr nz, .notRoute12 CheckEvent EVENT_BEAT_ROUTE12_SNORLAX - jr nz, .noSnorlaxToWakeUp + jr nz, .noSnorlaxOrPikachuToWakeUp ; if the player hasn't beaten Route 12 Snorlax ld hl, Route12SnorlaxFluteCoords call ArePlayerCoordsInArray - jr nc, .noSnorlaxToWakeUp + jr nc, .noSnorlaxOrPikachuToWakeUp ld hl, PlayedFluteHadEffectText call PrintText SetEvent EVENT_FIGHT_ROUTE12_SNORLAX ret + .notRoute12 cp ROUTE_16 - jr nz, .noSnorlaxToWakeUp + jr nz, .notRoute16 CheckEvent EVENT_BEAT_ROUTE16_SNORLAX - jr nz, .noSnorlaxToWakeUp + jr nz, .noSnorlaxOrPikachuToWakeUp ; if the player hasn't beaten Route 16 Snorlax ld hl, Route16SnorlaxFluteCoords call ArePlayerCoordsInArray - jr nc, .noSnorlaxToWakeUp + jr nc, .noSnorlaxOrPikachuToWakeUp ld hl, PlayedFluteHadEffectText call PrintText SetEvent EVENT_FIGHT_ROUTE16_SNORLAX ret -.noSnorlaxToWakeUp + +.notRoute16 + cp PEWTER_POKECENTER + jr nz, .noSnorlaxOrPikachuToWakeUp + call CheckPikachuFollowingPlayer + jr z, .noSnorlaxOrPikachuToWakeUp + callab IsPikachuRightNextToPlayer + jr nc, .noSnorlaxOrPikachuToWakeUp + ld hl, PlayedFluteHadEffectText + call PrintText + call ItemUseReloadOverworldData + ldpikaemotion e, PikachuEmotion26 + callab PlaySpecificPikachuEmotion + ret + +.noSnorlaxOrPikachuToWakeUp ld hl, PlayedFluteNoEffectText jp PrintText + .inBattle xor a ld [wWereAnyMonsAsleep], a @@ -1761,8 +1955,15 @@ ItemUsePokeflute: ld [hl], a ld hl, wEnemyMonStatus ld a, [hl] + ld c, a and b ; remove Sleep status ld [hl], a + ld a, c + and SLP + jr z, .asm_e063 + ld a, $1 + ld [wWereAnyMonsAsleep], a +.asm_e063 call LoadScreenTilesFromBuffer2 ; restore saved screen ld a, [wWereAnyMonsAsleep] and a ; were any pokemon asleep before playing the flute? @@ -1814,18 +2015,18 @@ WakeUpEntireParty: ; 00: Y ; 01: X Route12SnorlaxFluteCoords: - db 62,9 ; one space West of Snorlax - db 61,10 ; one space North of Snorlax - db 63,10 ; one space South of Snorlax - db 62,11 ; one space East of Snorlax + db 62, 9 ; one space West of Snorlax + db 61, 10 ; one space North of Snorlax + db 63, 10 ; one space South of Snorlax + db 62, 11 ; one space East of Snorlax db $ff ; terminator ; Format: ; 00: Y ; 01: X Route16SnorlaxFluteCoords: - db 10,27 ; one space East of Snorlax - db 10,25 ; one space West of Snorlax + db 10, 27 ; one space East of Snorlax + db 10, 25 ; one space West of Snorlax db $ff ; terminator PlayedFluteNoEffectText: @@ -1844,8 +2045,7 @@ PlayedFluteHadEffectText: and a jr nz, .done ; play out-of-battle pokeflute music - ld a, $ff - call PlaySound ; turn off music + call StopAllMusic ; turn off music ld a, SFX_POKEFLUTE ld c, BANK(SFX_Pokeflute) call PlayMusic @@ -1906,13 +2106,28 @@ INCLUDE "data/good_rod.asm" ItemUseSuperRod: call FishingInit jp c, ItemUseNotTime - call ReadSuperRodData - ld a, e + callab ReadSuperRodData + ld c, e + ld b, d + ld a, $2 + ld [wRodResponse], a + ld a, c + and a ; are there fish in the map? + jr z, DoNotGenerateFishingEncounter ; if not, do not generate an encounter + ld a, $1 + ld [wRodResponse], a + call Random + and $1 + jr nz, RodResponse + xor a + ld [wRodResponse], a + jr DoNotGenerateFishingEncounter + RodResponse: ld [wRodResponse], a dec a ; is there a bite? - jr nz, .next + jr nz, DoNotGenerateFishingEncounter ; if yes, store level and species data ld a, 1 ld [wMoveMissed], a @@ -1921,7 +2136,7 @@ RodResponse: ld a, c ; species ld [wCurOpponent], a -.next +DoNotGenerateFishingEncounter: ld hl, wWalkBikeSurfState ld a, [hl] ; store the value in a push af @@ -1941,22 +2156,28 @@ FishingInit: jr z, .notInBattle scf ; can't fish during battle ret + .notInBattle call IsNextTileShoreOrWater - ret c + jr nc, .cannotFish ld a, [wWalkBikeSurfState] cp 2 ; Surfing? - jr z, .surfing + jr z, .cannotFish call ItemUseReloadOverworldData ld hl, ItemUseText00 call PrintText ld a, SFX_HEAL_AILMENT call PlaySound + ld a, $2 + ld [wd49c], a + ld a, $81 + ld [wPikachuMood], a ld c, 80 call DelayFrames and a ret -.surfing + +.cannotFish scf ; can't fish when surfing ret @@ -2009,7 +2230,23 @@ ItemUsePPRestore: call DisplayPartyMenu jr nc, .chooseMove jp .itemNotUsed + .chooseMove + ld a, [wIsInBattle] + and a + jr z, .usePPItem + ld a, [wWhichPokemon] + ld b, a + ld a, [wPlayerMonNumber] + cp b + jr nz, .usePPItem + ld a, [wPlayerBattleStatus3] + bit TRANSFORMED, a + jr z, .usePPItem + call ItemUseNotTime + jp .itemNotUsed + +.usePPItem ld a, [wPPRestoreItem] cp ELIXER jp nc, .useElixir ; if Elixir or Max Elixir @@ -2049,6 +2286,7 @@ ItemUsePPRestore: ld hl, PPMaxedOutText call PrintText jr .chooseMove + .PPNotMaxedOut ld a, [hl] add 1 << 6 ; increase PP Up count by 1 @@ -2056,6 +2294,8 @@ ItemUsePPRestore: ld a, 1 ; 1 PP Up used ld [wd11e], a call RestoreBonusPP ; add the bonus PP to current PP + ld a, SFX_HEAL_AILMENT + call PlaySound ld hl, PPIncreasedText call PrintText .done @@ -2064,6 +2304,7 @@ ItemUsePPRestore: call GBPalWhiteOut call RunDefaultPaletteCommand jp RemoveUsedItem + .afterRestoringPP ; after using a (Max) Ether/Elixir ld a, [wWhichPokemon] ld b, a @@ -2082,10 +2323,12 @@ ItemUsePPRestore: ld hl, PPRestoredText call PrintText jr .done + .useEther call .restorePP jr nz, .afterRestoringPP jp .noEffect + ; unsets zero flag if PP was restored, sets zero flag if not ; however, this is bugged for Max Ethers and Max Elixirs (see below) .restorePP @@ -2120,6 +2363,7 @@ ItemUsePPRestore: add b ld [hl], a ret + .fullyRestorePP ld a, [hl] ; move PP ; Note that this code has a bug. It doesn't mask out the upper two bits, which @@ -2129,6 +2373,7 @@ ItemUsePPRestore: cp b ; does current PP equal max PP? ret z jr .storeNewAmount + .useElixir ; decrement the item ID so that ELIXER becomes ETHER and MAX_ELIXER becomes MAX_ETHER ld hl, wPPRestoreItem @@ -2232,6 +2477,7 @@ ItemUseTMHM: ld a, 2 ld [wActionResultOrTookBattleTurn], a ; item not used ret + .useMachine ld a, [wWhichPokemon] push af @@ -2277,10 +2523,13 @@ ItemUseTMHM: ld hl, MonCannotLearnMachineMoveText call PrintText jr .chooseMon + .checkIfAlreadyLearnedMove callab CheckIfMoveIsKnown ; check if the pokemon already knows the move jr c, .chooseMon predef LearnMove ; teach move + ld a, [wWhichPokemon] + ld d, a pop af ld [wcf91], a pop af @@ -2288,6 +2537,28 @@ ItemUseTMHM: ld a, b and a ret z + + ld a, [wWhichPokemon] + push af + ld a, d + ld [wWhichPokemon], a + callabd_ModifyPikachuHappiness PIKAHAPPY_USEDTMHM + callab IsThisPartymonStarterPikachu_Party + jr nc, .notTeachingThunderboltOrThunderToPikachu + ld a, [wcf91] + cp TM_24 ; are we teaching thunderbolt to the player pikachu? + jr z, .teachingThunderboltOrThunderToPlayerPikachu + cp TM_25 ; are we teaching thunder then? + jr nz, .notTeachingThunderboltOrThunderToPikachu +.teachingThunderboltOrThunderToPlayerPikachu + ld a, $5 + ld [wd49c], a + ld a, $85 + ld [wPikachuMood], a +.notTeachingThunderboltOrThunderToPikachu + pop af + ld [wWhichPokemon], a + ld a, [wcf91] call IsItemHM ret c @@ -2334,6 +2605,12 @@ ItemUseNotYoursToUse: ld hl, ItemUseNotYoursToUseText jr ItemUseFailed +Func_e4bf: + ld a, $2 + ld [wActionResultOrTookBattleTurn], a + ld hl, DontHavePokemonText + jp PrintText + ThrowBallAtTrainerMon: call RunDefaultPaletteCommand call LoadScreenTilesFromBuffer1 ; restore saved screen @@ -2395,6 +2672,10 @@ BoxFullCannotThrowBallText: TX_FAR _BoxFullCannotThrowBallText db "@" +DontHavePokemonText: + TX_FAR _DontHavePokemonText + db "@" + ItemUseText00: TX_FAR _ItemUseText001 TX_LINE @@ -2529,6 +2810,7 @@ GetMaxPP: .sourceWithOneMon call GetSelectedMoveOffset2 jr .next + .sourceWithMultipleMon call GetSelectedMoveOffset .next @@ -2630,6 +2912,7 @@ TossItem_: pop hl and a ret + .tooImportantToToss push hl ld hl, TooImportantToTossText @@ -2696,7 +2979,7 @@ SendNewMonToBox: ld a, [wcf91] ld [wd0b5], a ld c, a -.asm_e7b1 +.asm_e6f5 inc de ld a, [de] ld b, a @@ -2704,13 +2987,13 @@ SendNewMonToBox: ld c, b ld [de], a cp $ff - jr nz, .asm_e7b1 + jr nz, .asm_e6f5 call GetMonHeader ld hl, wBoxMonOT ld bc, NAME_LENGTH ld a, [wNumInBox] dec a - jr z, .asm_e7ee + jr z, .asm_e732 dec a call AddNTimes push hl @@ -2722,7 +3005,7 @@ SendNewMonToBox: ld a, [wNumInBox] dec a ld b, a -.asm_e7db +.asm_e71f push bc push hl ld bc, NAME_LENGTH @@ -2734,15 +3017,15 @@ SendNewMonToBox: add hl, bc pop bc dec b - jr nz, .asm_e7db -.asm_e7ee + jr nz, .asm_e71f +.asm_e732 ld hl, wPlayerName ld de, wBoxMonOT ld bc, NAME_LENGTH call CopyData ld a, [wNumInBox] dec a - jr z, .asm_e82a + jr z, .asm_e76e ld hl, wBoxMonNicks ld bc, NAME_LENGTH dec a @@ -2756,7 +3039,7 @@ SendNewMonToBox: ld a, [wNumInBox] dec a ld b, a -.asm_e817 +.asm_e75b push bc push hl ld bc, NAME_LENGTH @@ -2768,15 +3051,15 @@ SendNewMonToBox: add hl, bc pop bc dec b - jr nz, .asm_e817 -.asm_e82a + jr nz, .asm_e75b +.asm_e76e ld hl, wBoxMonNicks ld a, NAME_MON_SCREEN ld [wNamingScreenType], a predef AskName ld a, [wNumInBox] dec a - jr z, .asm_e867 + jr z, .asm_e7ab ld hl, wBoxMons ld bc, wBoxMon2 - wBoxMon1 dec a @@ -2790,7 +3073,7 @@ SendNewMonToBox: ld a, [wNumInBox] dec a ld b, a -.asm_e854 +.asm_e798 push bc push hl ld bc, wBoxMon2 - wBoxMon1 @@ -2802,8 +3085,8 @@ SendNewMonToBox: add hl, bc pop bc dec b - jr nz, .asm_e854 -.asm_e867 + jr nz, .asm_e798 +.asm_e7ab ld a, [wEnemyMonLevel] ld [wEnemyMonBoxLevel], a ld hl, wEnemyMon @@ -2833,11 +3116,11 @@ SendNewMonToBox: inc de xor a ld b, NUM_STATS * 2 -.asm_e89f +.asm_e7e3 ld [de], a inc de dec b - jr nz, .asm_e89f + jr nz, .asm_e7e3 ld hl, wEnemyMonDVs ld a, [hli] ld [de], a @@ -2846,12 +3129,18 @@ SendNewMonToBox: ld [de], a ld hl, wEnemyMonPP ld b, NUM_MOVES -.asm_e8b1 +.asm_e7f5 ld a, [hli] inc de ld [de], a dec b - jr nz, .asm_e8b1 + jr nz, .asm_e7f5 + ld a, [wcf91] + cp KADABRA + jr nz, .notKadabra + ld a, $60 ; twistedspoon in gsc + ld [wBoxMon1CatchRate], a +.notKadabra ret ; checks if the tile in front of the player is a shore or water tile @@ -2861,24 +3150,21 @@ IsNextTileShoreOrWater: ld a, [wCurMapTileset] ld hl, WaterTilesets ld de, 1 - call IsInArray - jr nc, .notShoreOrWater + call IsInArray ; does the current map allow surfing? + ret nc ; if not, return + ld hl, WaterTile ld a, [wCurMapTileset] cp SHIP_PORT ; Vermilion Dock tileset - ld a, [wTileInFrontOfPlayer] ; tile in front of player jr z, .skipShoreTiles ; if it's the Vermilion Dock tileset - cp $48 ; eastern shore tile in Safari Zone - jr z, .shoreOrWater - cp $32 ; usual eastern shore tile - jr z, .shoreOrWater + cp GYM ; eastern shore tile in Safari Zone + jr z, .skipShoreTiles + cp DOJO ; usual eastern shore tile + jr z, .skipShoreTiles + ld hl, ShoreTiles .skipShoreTiles - cp $14 ; water tile - jr z, .shoreOrWater -.notShoreOrWater - scf - ret -.shoreOrWater - and a + ld a, [wTileInFrontOfPlayer] + ld de, $1 + call IsInArray ret ; tilesets with water @@ -2886,52 +3172,12 @@ WaterTilesets: db OVERWORLD, FOREST, DOJO, GYM, SHIP, SHIP_PORT, CAVERN, FACILITY, PLATEAU db $ff ; terminator -ReadSuperRodData: -; return e = 2 if no fish on this map -; return e = 1 if a bite, bc = level,species -; return e = 0 if no bite - ld a, [wCurMap] - ld de, 3 ; each fishing group is three bytes wide - ld hl, SuperRodData - call IsInArray - jr c, .ReadFishingGroup - ld e, $2 ; $2 if no fishing groups found - ret - -.ReadFishingGroup -; hl points to the fishing group entry in the index - inc hl ; skip map id - - ; read fishing group address - ld a, [hli] - ld h, [hl] - ld l, a - - ld b, [hl] ; how many mons in group - inc hl ; point to data - ld e, $0 ; no bite yet - -.RandomLoop - call Random - srl a - ret c ; 50% chance of no battle - - and %11 ; 2-bit random number - cp b - jr nc, .RandomLoop ; if a is greater than the number of mons, regenerate - - ; get the mon - add a - ld c, a - ld b, $0 - add hl, bc - ld b, [hl] ; level - inc hl - ld c, [hl] ; species - ld e, $1 ; $1 if there's a bite - ret - -INCLUDE "data/super_rod.asm" +; shore tiles +ShoreTiles: + db $48, $32 +WaterTile: + db $14 + db $ff ; terminator ; reloads map view and processes sprite data ; for items that cause the overworld to be displayed diff --git a/engine/items/tms.asm b/engine/items/tms.asm index da1b5e72..84770747 100755 --- a/engine/items/tms.asm +++ b/engine/items/tms.asm @@ -11,6 +11,8 @@ CanLearnTM: ld hl, TechnicalMachines .findTMloop ld a, [hli] + cp $ff ; reached terminator? + jr z, .done cp b jr z, .TMfoundLoop inc c @@ -19,6 +21,10 @@ CanLearnTM: pop hl ld b, FLAG_TEST predef_jump FlagActionPredef +.done + pop hl + ld c, 0 + ret ; converts TM/HM number in wd11e into move number ; HMs start at 51 diff --git a/engine/joypad.asm b/engine/joypad.asm index 31e197e2..4126568c 100644 --- a/engine/joypad.asm +++ b/engine/joypad.asm @@ -1,12 +1,48 @@ +ReadJoypad_:: +; Poll joypad input. +; Unlike the hardware register, button +; presses are indicated by a set bit. + ld a, [hDisableJoypadPolling] + and a + ret nz + + ld a, 1 << 5 ; select direction keys + ;ld c, 0 + + ld [rJOYP], a + ld a, [rJOYP] + ld a, [rJOYP] + cpl + and %1111 + swap a + ld b, a + + ld a, 1 << 4 ; select button keys + ld [rJOYP], a + rept 6 + ld a, [rJOYP] + endr + cpl + and %1111 + or b + + ld [hJoyInput], a + + ld a, 1 << 4 + 1 << 5 ; deselect keys + ld [rJOYP], a + ret + + _Joypad:: ; hJoyReleased: (hJoyLast ^ hJoyInput) & hJoyLast ; hJoyPressed: (hJoyLast ^ hJoyInput) & hJoyInput ld a, [hJoyInput] + ld b,a + and $4F cp A_BUTTON + B_BUTTON + SELECT + START ; soft reset jp z, TrySoftReset - ld b, a ld a, [hJoyLast] ld e, a xor b diff --git a/engine/learn_move.asm b/engine/learn_move.asm index 53c7f87e..021d0eeb 100755 --- a/engine/learn_move.asm +++ b/engine/learn_move.asm @@ -121,18 +121,17 @@ TryingToLearn: ld hl, WhichMoveToForgetText call PrintText coord hl, 4, 7 - ld b, 4 - ld c, 14 + lb bc, 4, 14 call TextBoxBorder coord hl, 6, 8 ld de, wMovesString - ld a, [hFlags_0xFFF6] + ld a, [hFlags_0xFFFA] set 2, a - ld [hFlags_0xFFF6], a + ld [hFlags_0xFFFA], a call PlaceString - ld a, [hFlags_0xFFF6] + ld a, [hFlags_0xFFFA] res 2, a - ld [hFlags_0xFFF6], a + ld [hFlags_0xFFFA], a ld hl, wTopMenuItemY ld a, 8 ld [hli], a ; wTopMenuItemY @@ -146,10 +145,10 @@ TryingToLearn: ld a, A_BUTTON | B_BUTTON ld [hli], a ; wMenuWatchedKeys ld [hl], 0 ; wLastMenuItem - ld hl, hFlags_0xFFF6 + ld hl, hFlags_0xFFFA set 1, [hl] call HandleMenuInput - ld hl, hFlags_0xFFF6 + ld hl, hFlags_0xFFFA res 1, [hl] push af call LoadScreenTilesFromBuffer1 @@ -206,11 +205,36 @@ TryingToLearnText: db "@" OneTwoAndText: +; bugfix: In Red/Blue, the SFX_SWAP sound was played in the wrong bank, which played an incorrect sound +; Yellow has fixed this by swapping to the correct bank TX_FAR _OneTwoAndText TX_DELAY TX_ASM + push af + push bc + push de + push hl + ld a, $1 + ld [wMuteAudioAndPauseMusic], a + call DelayFrame + ld a, [wAudioROMBank] + push af + ld a, BANK(SFX_Swap_1) + ld [wAudioROMBank], a + ld [wAudioSavedROMBank], a + call WaitForSoundToFinish ld a, SFX_SWAP - call PlaySoundWaitForCurrent + call PlaySound + call WaitForSoundToFinish + pop af + ld [wAudioROMBank], a + ld [wAudioSavedROMBank], a + xor a + ld [wMuteAudioAndPauseMusic], a + pop hl + pop de + pop bc + pop af ld hl, PoofText ret diff --git a/engine/load_mon_data.asm b/engine/load_mon_data.asm index a71a81c5..e708113f 100644 --- a/engine/load_mon_data.asm +++ b/engine/load_mon_data.asm @@ -15,7 +15,7 @@ LoadMonData_: ld a, [wWhichPokemon] ld e, a - callab GetMonSpecies + call GetMonSpecies .GetMonHeader ld a, [wcf91] @@ -47,3 +47,22 @@ LoadMonData_: ld de, wLoadedMon ld bc, wPartyMon2 - wPartyMon1 jp CopyData + +; get species of mon e in list [wMonDataLocation] for LoadMonData +GetMonSpecies: + ld hl, wPartySpecies + ld a, [wMonDataLocation] + and a + jr z, .getSpecies + dec a + jr z, .enemyParty + ld hl, wBoxSpecies + jr .getSpecies +.enemyParty + ld hl, wEnemyPartyMons +.getSpecies + ld d, 0 + add hl, de + ld a, [hl] + ld [wcf91], a + ret diff --git a/engine/menu/bills_pc.asm b/engine/menu/bills_pc.asm index 0864828a..41626310 100644 --- a/engine/menu/bills_pc.asm +++ b/engine/menu/bills_pc.asm @@ -11,18 +11,15 @@ DisplayPCMainMenu:: and a jr nz, .leaguePCAvailable coord hl, 0, 0 - ld b, 8 - ld c, 14 + lb bc, 8, 14 jr .next .noOaksPC coord hl, 0, 0 - ld b, 6 - ld c, 14 + lb bc, 6, 14 jr .next .leaguePCAvailable coord hl, 0, 0 - ld b, 10 - ld c, 14 + lb bc, 10, 14 .next call TextBoxBorder call UpdateSprites @@ -119,10 +116,13 @@ BillsPCMenu: lb bc, BANK(PokeballTileGraphics), $01 call CopyVideoData call LoadScreenTilesFromBuffer2DisableBGTransfer + coord hl, 0, 12 + lb bc, 4, 18 + call TextBoxBorder coord hl, 0, 0 - ld b, 10 - ld c, 12 + lb bc, 12, 12 call TextBoxBorder + call UpdateSprites coord hl, 2, 2 ld de, BillsPCMenuText call PlaceString @@ -133,7 +133,7 @@ BillsPCMenu: ld [hli], a ; wTopMenuItemX inc hl inc hl - ld a, 4 + ld a, 5 ld [hli], a ; wMaxMenuItem ld a, A_BUTTON | B_BUTTON ld [hli], a ; wMenuWatchedKeys @@ -144,11 +144,8 @@ BillsPCMenu: ld [hli], a ; wListScrollOffset ld [hl], a ; wMenuWatchMovingOutOfBounds ld [wPlayerMonNumber], a - ld hl, WhatText - call PrintText coord hl, 9, 14 - ld b, 2 - ld c, 9 + lb bc, 2, 9 call TextBoxBorder ld a, [wCurrentBoxNum] and $7f @@ -184,6 +181,8 @@ BillsPCMenu: jp z, BillsPCRelease ; release cp $3 jp z, BillsPCChangeBox ; change box + cp $4 + jp z, BillsPCPrintBox ExitBillsPC: ld a, [wFlags_0xcd60] @@ -204,6 +203,10 @@ ExitBillsPC: res 6, [hl] ret +BillsPCPrintBox: + callab PrintPCBox + jp BillsPCMenu + BillsPCDeposit: ld a, [wPartyCount] dec a @@ -222,11 +225,26 @@ BillsPCDeposit: ld hl, wPartyCount call DisplayMonListMenu jp c, BillsPCMenu + callab IsThisPartymonStarterPikachu_Party + jr nc, .asm_215ad + call CheckPikachuFollowingPlayer + jr z, .asm_215ad + ld hl, SleepingPikachuText2 + call PrintText + jp BillsPCMenu +.asm_215ad call DisplayDepositWithdrawMenu jp nc, BillsPCMenu + callab IsThisPartymonStarterPikachu_Party + jr nc, .asm_215c9 + ld e, $1b + callab PlayPikachuSoundClip + jr .asm_215cf +.asm_215c9 ld a, [wcf91] - call GetCryData - call PlaySoundWaitForCurrent + call PlayCry +.asm_215cf + callabd_ModifyPikachuHappiness PIKAHAPPY_DEPOSITED ld a, PARTY_TO_BOX ld [wMoveMonType], a call MoveMon @@ -253,6 +271,10 @@ BillsPCDeposit: call PrintText jp BillsPCMenu +SleepingPikachuText2: + TX_FAR _SleepingPikachuText2 + db "@" + BillsPCWithdraw: ld a, [wNumInBox] and a @@ -276,9 +298,15 @@ BillsPCWithdraw: ld a, [wWhichPokemon] ld hl, wBoxMonNicks call GetPartyMonName + callab IsThisPartymonStarterPikachu_Box + jr nc, .asm_21660 + ld e, $22 + callab PlayPikachuSoundClip + jr .asm_21666 +.asm_21660 ld a, [wcf91] - call GetCryData - call PlaySoundWaitForCurrent + call PlayCry +.asm_21666 xor a ; BOX_TO_PARTY ld [wMoveMonType], a call MoveMon @@ -301,6 +329,8 @@ BillsPCRelease: ld hl, wNumInBox call DisplayMonListMenu jp c, BillsPCMenu + callab IsThisPartymonStarterPikachu_Box + jr c, .asm_216cb ld hl, OnceReleasedText call PrintText call YesNoChoice @@ -317,6 +347,16 @@ BillsPCRelease: call PrintText jp BillsPCMenu +.asm_216cb + ld a, [wWhichPokemon] + ld hl, wBoxMonNicks + call GetPartyMonName + ld e, $27 + callab PlayPikachuSoundClip + ld hl, PikachuUnhappyText + call PrintText + jp BillsPCMenu + BillsPCChangeBox: callba ChangeBox jp BillsPCMenu @@ -343,6 +383,7 @@ BillsPCMenuText: next "DEPOSIT ", $4a next "RELEASE ", $4a next "CHANGE BOX" + next "PRINT BOX" next "SEE YA!" db "@" @@ -386,8 +427,7 @@ HMMoveArray: DisplayDepositWithdrawMenu: coord hl, 9, 10 - ld b, 6 - ld c, 9 + lb bc, 6, 9 call TextBoxBorder ld a, [wParentMenuItem] and a ; was the Deposit or Withdraw item selected in the parent menu? @@ -493,6 +533,10 @@ CantTakeMonText: TX_FAR _CantTakeMonText db "@" +PikachuUnhappyText: + TX_FAR _PikachuUnhappyText + db "@" + ReleaseWhichMonText: TX_FAR _ReleaseWhichMonText db "@" @@ -509,7 +553,7 @@ CableClubLeftGameboy:: ld a, [hSerialConnectionStatus] cp USING_EXTERNAL_CLOCK ret z - ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction + ld a, [wSpritePlayerStateData1FacingDirection] ; player's sprite facing direction cp SPRITE_FACING_RIGHT ret nz ld a, [wCurMap] @@ -526,7 +570,7 @@ CableClubRightGameboy:: ld a, [hSerialConnectionStatus] cp USING_INTERNAL_CLOCK ret z - ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction + ld a, [wSpritePlayerStateData1FacingDirection] ; player's sprite facing direction cp SPRITE_FACING_LEFT ret nz ld a, [wCurMap] @@ -543,12 +587,12 @@ JustAMomentText:: TX_FAR _JustAMomentText db "@" - ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction + ld a, [wSpritePlayerStateData1FacingDirection] ; player's sprite facing direction cp SPRITE_FACING_UP ret nz call EnableAutoTextBoxDrawing tx_pre_jump OpenBillsPCText OpenBillsPCText:: - db $FD ; FuncTX_BillsPC + TX_BILLS_PC diff --git a/engine/menu/diploma.asm b/engine/menu/diploma.asm index 09ba123e..3f309bd2 100755..100644 --- a/engine/menu/diploma.asm +++ b/engine/menu/diploma.asm @@ -6,108 +6,12 @@ DisplayDiploma: ld [wUpdateSpritesEnabled], a ld hl, wd730 set 6, [hl] - call DisableLCD - ld hl, CircleTile - ld de, vChars2 + $700 - ld bc, $0010 - ld a, BANK(CircleTile) - call FarCopyData2 - coord hl, 0, 0 - lb bc, 16, 18 - predef Diploma_TextBoxBorder - ld hl, DiplomaTextPointersAndCoords - ld c, $5 -.asm_56715 - push bc - ld a, [hli] - ld e, a - ld a, [hli] - ld d, a - ld a, [hli] - push hl - ld h, [hl] - ld l, a - call PlaceString - pop hl - inc hl - pop bc - dec c - jr nz, .asm_56715 - coord hl, 10, 4 - ld de, wPlayerName - call PlaceString - callba DrawPlayerCharacter - -; Move the player 33 pixels right and set the priority bit so he appears -; behind the background layer. - ld hl, wOAMBuffer + $01 - lb bc, $80, $28 -.adjustPlayerGfxLoop - ld a, [hl] ; X - add 33 - ld [hli], a - inc hl - ld a, b - ld [hli], a ; attributes - inc hl - dec c - jr nz, .adjustPlayerGfxLoop - - call EnableLCD - callba LoadTrainerInfoTextBoxTiles - ld b, SET_PAL_GENERIC - call RunPaletteCommand - call Delay3 - call GBPalNormal - ld a, $90 - ld [rOBP0], a + callab _DisplayDiploma call WaitForTextScrollButtonPress ld hl, wd730 res 6, [hl] call GBPalWhiteOutWithDelay3 + call ReloadTilesetTilePatterns call RestoreScreenTilesAndReloadTilePatterns call Delay3 jp GBPalNormal - -UnusedPlayerNameLengthFunc: -; Unused function that does a calculation involving the length of the player's -; name. - ld hl, wPlayerName - ld bc, $ff00 -.loop - ld a, [hli] - cp "@" - ret z - dec c - jr .loop - -DiplomaTextPointersAndCoords: - dw DiplomaText - dwCoord 5, 2 - dw DiplomaPlayer - dwCoord 3, 4 - dw DiplomaEmptyText - dwCoord 15, 4 - dw DiplomaCongrats - dwCoord 2, 6 - dw DiplomaGameFreak - dwCoord 9, 16 - -DiplomaText: - db $70,"Diploma",$70,"@" - -DiplomaPlayer: - db "Player@" - -DiplomaEmptyText: - db "@" - -DiplomaCongrats: - db "Congrats! This" - next "diploma certifies" - next "that you have" - next "completed your" - next "#DEX.@" - -DiplomaGameFreak: - db "GAME FREAK@" diff --git a/engine/menu/draw_start_menu.asm b/engine/menu/draw_start_menu.asm index 11777dc6..632b8c3a 100644 --- a/engine/menu/draw_start_menu.asm +++ b/engine/menu/draw_start_menu.asm @@ -3,13 +3,11 @@ DrawStartMenu: CheckEvent EVENT_GOT_POKEDEX ; menu with pokedex coord hl, 10, 0 - ld b, $0e - ld c, $08 - jr nz, .drawTextBoxBorder + lb bc, 14, 8 + jr nz,.drawTextBoxBorder ; shorter menu if the player doesn't have the pokedex coord hl, 10, 0 - ld b, $0c - ld c, $08 + lb bc, 12, 8 .drawTextBoxBorder call TextBoxBorder ld a, D_DOWN | D_UP | START | B_BUTTON | A_BUTTON @@ -63,7 +61,7 @@ StartMenuPokedexText: db "POKéDEX@" StartMenuPokemonText: - db "POKéMON@" + db "#MON@" StartMenuItemText: db "ITEM@" diff --git a/engine/menu/league_pc.asm b/engine/menu/league_pc.asm index 170c0ef3..9946b90d 100755 --- a/engine/menu/league_pc.asm +++ b/engine/menu/league_pc.asm @@ -100,8 +100,7 @@ LeaguePCShowMon: call LoadFrontSpriteByMonIndex call GBPalNormal coord hl, 0, 13 - ld b, 2 - ld c, $12 + lb bc, 2, 18 call TextBoxBorder coord hl, 1, 15 ld de, HallOfFameNoText @@ -110,7 +109,7 @@ LeaguePCShowMon: ld de, wHoFTeamNo lb bc, 1, 3 call PrintNumber - jpba HoFDisplayMonInfo + jpba Func_7033f HallOfFameNoText: db "HALL OF FAME No @" diff --git a/engine/menu/link_menu.asm b/engine/menu/link_menu.asm new file mode 100644 index 00000000..9bc28b31 --- /dev/null +++ b/engine/menu/link_menu.asm @@ -0,0 +1,910 @@ +Func_f531b:: + ld c,$14 + call DelayFrames + ld a,$1 + ld [wBuffer],a + xor a + ld [wUnknownSerialFlag_d499],a + coord hl, 0,0 + lb bc, 4, 5 + call TextBoxBorder + ld de,Text_f5791 + coord hl, 1,2 + call PlaceString + coord hl, 8,0 + lb bc, 8, 10 + call TextBoxBorder + coord hl, 10,2 + ld de,Text_f579c + call PlaceString + coord hl, 0,10 + lb bc, 6, 18 + call TextBoxBorder + call UpdateSprites + xor a + ld [wUnusedCD37],a + ld [wd72d],a + ld [wd11e],a + ld hl,wTopMenuItemY + ld a,$2 + ld [hli],a + ld a,$9 + ld [hli],a + xor a + ld [hli],a + inc hl + ld a,$3 + ld [hli],a + ld a,$3 + ld [hli],a + xor a + ld [hl],a +.asm_f5377 + call Func_f56bd + call HandleMenuInput + and $3 + add a + add a + ld b,a + ld a,[wCurrentMenuItem] + cp $3 + jr nz,.asm_f5390 + bit 2,b + jr z,.asm_f5390 + dec a + ld b,$8 +.asm_f5390 + add b + add $c0 + ld [wLinkMenuSelectionSendBuffer],a + ld [wLinkMenuSelectionSendBuffer+1],a +.asm_f5399 + ld hl,wLinkMenuSelectionSendBuffer + ld a,[hl] + ld [hSerialSendData],a + call Serial_ExchangeByte + push af + ld hl,wLinkMenuSelectionSendBuffer + ld a,[hl] + ld [hSerialSendData],a + call Serial_ExchangeByte + pop bc + cp b + jr nz,.asm_f5399 + and $f0 + cp $c0 + jr nz,.asm_f5399 + ld a,b + and $c + jr nz,.asm_f53c4 + ld a,[wLinkMenuSelectionSendBuffer] + and $c + jr z,.asm_f5377 + jr .asm_f53df +.asm_f53c4 + ld a,[wLinkMenuSelectionSendBuffer] + and $c + jr z,.asm_f53d1 + ld a,[hSerialConnectionStatus] + cp $2 + jr z,.asm_f53df +.asm_f53d1 + ld a,$1 + ld [wd11e],a + ld a,b + ld [wLinkMenuSelectionSendBuffer],a + and $3 + ld [wCurrentMenuItem],a +.asm_f53df + call DelayFrame + call DelayFrame + ld hl,wLinkMenuSelectionSendBuffer + ld a,[hl] + ld [hSerialSendData],a + call Serial_ExchangeByte + call Serial_ExchangeByte + ld b,$14 +.loop + call DelayFrame + call Serial_SendZeroByte + dec b + jr nz,.loop + ld b,$7f + ld c,$7f + ld d,$7f + ld e,$ec + ld a,[wLinkMenuSelectionSendBuffer] + bit 3,a + jr nz,.asm_f541a + ld b,e + ld e,c + ld a,[wCurrentMenuItem] + and a + jr z,.asm_f541a + ld c,b + ld b,d + dec a + jr z,.asm_f541a + ld d,c + ld c,b +.asm_f541a + ld a,b + Coorda 9,2 + ld a,c + Coorda 9,4 + ld a,d + Coorda 9,6 + ld a,e + Coorda 9,8 + ld c,40 + call DelayFrames + ld a,[wLinkMenuSelectionSendBuffer] + bit 3,a + jr nz,asm_f547f + ld a,[wCurrentMenuItem] + cp $3 + jr z,asm_f547f + inc a + ld [wUnknownSerialFlag_d499],a + ld a,[wCurrentMenuItem] + ld hl,PointerTable_f5488 + ld c,a + ld b,$0 + add hl,bc + add hl,bc + ld a,[hli] + ld h,[hl] + ld l,a + ld de,.returnaddress + push de + jp hl +.returnaddress + ld [wLinkMenuSelectionSendBuffer],a + xor a + ld [wUnknownSerialCounter],a + ld [wUnknownSerialCounter+1],a + call Serial_SyncAndExchangeNybble + ld a,[wLinkMenuSelectionSendBuffer] + and a + jr nz,asm_f547c + ld a, [wLinkMenuSelectionReceiveBuffer] + and a + jr nz, Func_f5476 + xor a + ld [wUnknownSerialCounter],a + ld [wUnknownSerialCounter+1],a + and a + ret + +Func_f5476:: + ld hl,ColosseumIneligibleText + call PrintText +asm_f547c:: + jp Func_f531b + +asm_f547f:: + xor a + ld [wUnknownSerialCounter],a + ld [wUnknownSerialCounter+1],a + scf + ret + +PointerTable_f5488:: + dw PokeCup + dw PikaCup + dw PetitCup + +PokeCup:: + ld hl,wPartyCount + ld a,[hli] + cp $3 + jp nz,NotThreeMonsInParty + ld b,$3 +.loop + ld a,[hli] + cp MEW + jp z,MewInParty + dec b + jr nz,.loop + dec hl + dec hl + cp [hl] ; is third mon second mon? + jp z,DuplicateSpecies + dec hl ; wPartySpecies + cp [hl] ; is third mon first mon? + jp z,DuplicateSpecies + ld a,[hli] + cp [hl] ; is first mon second mon? + jp z,DuplicateSpecies + ld a,[wPartyMon1Level] + cp 56 + jp nc,LevelAbove55 + cp 50 + jp c,LevelUnder50 + ld b,a + ld a,[wPartyMon2Level] + cp 56 + jp nc,LevelAbove55 + cp 50 + jp c,LevelUnder50 + ld c,a + ld a,[wPartyMon3Level] + cp 56 + jp nc,LevelAbove55 + cp 50 + jp c,LevelUnder50 + add b + add c + cp 156 + jp nc,CombinedLevelsGreaterThan155 + xor a + ret + +PikaCup:: + ld hl,wPartyCount + ld a,[hli] + cp $3 + jp nz,NotThreeMonsInParty + ld b,$3 +.loop + ld a,[hli] ; wPartySpecies + cp MEW + jp z,MewInParty + dec b + jr nz,.loop + dec hl + dec hl + cp [hl] ; is third mon second mon? + jp z,DuplicateSpecies + dec hl ; wPartySpecies + cp [hl] ; is third mon first mon? + jp z,DuplicateSpecies + ld a,[hli] + cp [hl] ; is first mon second mon? + jp z,DuplicateSpecies + ld a,[wPartyMon1Level] + cp 21 + jp nc,LevelAbove20 + cp 15 + jp c,LevelUnder15 + ld b,a + ld a,[wPartyMon2Level] + cp 21 + jp nc,LevelAbove20 + cp 15 + jp c,LevelUnder15 + ld c,a + ld a,[wPartyMon3Level] + cp 21 + jp nc,LevelAbove20 + cp 15 + jp c,LevelUnder15 + add b + add c + cp 51 + jp nc,CombinedLevelsAbove50 + xor a + ret + +PetitCup:: + ld hl,wPartyCount + ld a,[hli] + cp $3 + jp nz,NotThreeMonsInParty + ld b,$3 +.loop + ld a,[hli] + cp MEW + jp z,MewInParty + dec b + jr nz,.loop + dec hl + dec hl + cp [hl] ; is third mon second mon? + jp z,DuplicateSpecies + dec hl ; wPartySpecies + cp [hl] ; is third mon first mon? + jp z,DuplicateSpecies + ld a,[hli] + cp [hl] ; is first mon second mon? + jp z,DuplicateSpecies + dec hl + ld a,[hl] + ld [wcf91],a + push hl + callab Func_3b10f + pop hl + jp c,asm_f56ad + inc hl + ld a,[hl] + ld [wcf91],a + push hl + callab Func_3b10f + pop hl + jp c,asm_f56ad + inc hl + ld a,[hl] + ld [wcf91],a + push hl + callab Func_3b10f + pop hl + jp c,asm_f56ad + dec hl + dec hl + ld b,$3 +.bigloop + ld a,[hli] + push hl + push bc + push af + dec a + ld c,a + ld b,$0 + ld hl,PokedexEntryPointers + add hl,bc + add hl,bc + ld de,wcd6d + ld bc,$2 + ld a,BANK(PokedexEntryPointers) + call FarCopyData + ld hl,wcd6d + ld a,[hli] + ld h,[hl] + ld l,a + ld de,wcd6d + ld bc,$14 + ld a,BANK(PokedexEntryPointers) + call FarCopyData + ld hl,wcd6d +.loop2 + ld a,[hli] + cp "@" + jr nz,.loop2 + ld a,[hli] + cp $7 + jp nc,asm_f5689 + add a + add a + ld b,a + add a + add b + ld b,a + ld a,[hli] + add b + cp $51 + jp nc,asm_f5689 + ld a,[hli] + sub $b9 + ld a,[hl] + sbc $1 + jp nc,asm_f569b + pop af + pop bc + pop hl + dec b + jr nz,.bigloop + ld a,[wPartyMon1Level] + cp 31 + jp nc,LevelAbove30 + cp 25 + jp c,LevelUnder25 + ld b,a + ld a,[wPartyMon2Level] + cp 31 + jp nc,LevelAbove30 + cp 25 + jp c,LevelUnder25 + ld c,a + ld a,[wPartyMon3Level] + cp 31 + jp nc,LevelAbove30 + cp 25 + jp c,LevelUnder25 + add b + add c + cp 81 + jp nc,CombinedLevelsAbove80 + xor a + ret + +NotThreeMonsInParty:: + ld hl,Colosseum3MonsText + call PrintText + ld a,$1 + ret + +MewInParty:: + ld hl,ColosseumMewText + call PrintText + ld a,$2 + ret + +DuplicateSpecies:: + ld hl,ColosseumDifferentMonsText + call PrintText + ld a,$3 + ret + +LevelAbove55:: + ld hl,ColosseumMaxL55Text + call PrintText + ld a,$4 + ret + +LevelUnder50:: + ld hl,ColosseumMinL50Text + call PrintText + ld a,$5 + ret + +CombinedLevelsGreaterThan155:: + ld hl,ColosseumTotalL155Text + call PrintText + ld a,$6 + ret + +LevelAbove30:: + ld hl,ColosseumMaxL30Text + call PrintText + ld a,$7 + ret + +LevelUnder25:: + ld hl,ColosseumMinL25Text + call PrintText + ld a,$8 + ret + +CombinedLevelsAbove80:: + ld hl,ColosseumTotalL80Text + call PrintText + ld a,$9 + ret + +LevelAbove20:: + ld hl,ColosseumMaxL20Text + call PrintText + ld a,$a + ret + +LevelUnder15:: + ld hl,ColosseumMinL15Text + call PrintText + ld a,$b + ret + +CombinedLevelsAbove50:: + ld hl,ColosseumTotalL50Text + call PrintText + ld a,$c + ret + +asm_f5689:: + pop af + pop bc + pop hl + ld [wd11e],a + call GetMonName + ld hl,ColosseumHeightText + call PrintText + ld a,$d + ret + +asm_f569b:: + pop af + pop bc + pop hl + ld [wd11e],a + call GetMonName + ld hl,ColosseumWeightText + call PrintText + ld a,$e + ret + +asm_f56ad:: + ld a,[hl] + ld [wd11e],a + call GetMonName + ld hl,ColosseumEvolvedText + call PrintText + ld a,$f + ret + +Func_f56bd:: + xor a + ld [H_AUTOBGTRANSFERENABLED],a + coord hl, 1,11 + lb bc, 6, 18 + call ClearScreenArea + ld a,[wCurrentMenuItem] + cp $3 + jr nc,.asm_f56e6 + ld hl,PointerTable_f56ee + ld a,[wCurrentMenuItem] + ld c,a + ld b,$0 + add hl,bc + add hl,bc + ld a,[hli] + ld h,[hl] + ld l,a + ld d,h + ld e,l + coord hl, 1,12 + call PlaceString +.asm_f56e6 + call Delay3 + ld a,$1 + ld [H_AUTOBGTRANSFERENABLED],a + ret + +PointerTable_f56ee:: + dw Text_f56f4 + dw Text_f5728 + dw Text_f575b + +Text_f56f4:: + db "LVs of 3<pkmn>:50-55" + next "Sum of LVs:155 MAX" + next "MEW can't attend.@" + +Text_f5728:: + db "LVs of 3<pkmn>:15-20" + next "Sum of LVs:50 MAX" + next "MEW can't attend.@" + +Text_f575b:: + db "3 Basic <pkmn>.LV25-30" + next "Sum of LVs:80 MAX" + next "6′8″ and 44lb MAX@" + +Text_f5791:: + db "View" + next "Rules@" + +Text_f579c:: + db "# Cup" + next "Pika Cup" + next "Petit Cup" + next "CANCEL@" + +Colosseum3MonsText:: + TX_FAR _Colosseum3MonsText + db "@" + +ColosseumMewText:: + TX_FAR _ColosseumMewText + db "@" + +ColosseumDifferentMonsText:: + TX_FAR _ColosseumDifferentMonsText + db "@" + +ColosseumMaxL55Text:: + TX_FAR _ColosseumMaxL55Text + db "@" + +ColosseumMinL50Text:: + TX_FAR _ColosseumMinL50Text + db "@" + +ColosseumTotalL155Text:: + TX_FAR _ColosseumTotalL155Text + db "@" + +ColosseumMaxL30Text:: + TX_FAR _ColosseumMaxL30Text + db "@" + +ColosseumMinL25Text:: + TX_FAR _ColosseumMinL25Text + db "@" + +ColosseumTotalL80Text:: + TX_FAR _ColosseumTotalL80Text + db "@" + +ColosseumMaxL20Text:: + TX_FAR _ColosseumMaxL20Text + db "@" + +ColosseumMinL15Text:: + TX_FAR _ColosseumMinL15Text + db "@" + +ColosseumTotalL50Text:: + TX_FAR _ColosseumTotalL50Text + db "@" + +ColosseumHeightText:: + TX_FAR _ColosseumHeightText + db "@" + +ColosseumWeightText:: + TX_FAR _ColosseumWeightText + db "@" + +ColosseumEvolvedText:: + TX_FAR _ColosseumEvolvedText + db "@" + +ColosseumIneligibleText:: + TX_FAR _ColosseumIneligibleText + db "@" + +LinkMenu: + xor a + ld [wLetterPrintingDelayFlags], a + ld hl, wd72e + set 6, [hl] + ld hl, TextTerminator_f5a16 + call PrintText + call SaveScreenTilesToBuffer1 + ld hl, ColosseumWhereToText + call PrintText + coord hl, 5, 3 + lb bc, 8, 13 + call TextBoxBorder + call UpdateSprites + coord hl, 7, 5 + ld de, TradeCenterText + call PlaceString + xor a + ld [wUnusedCD37], a + ld [wd72d], a + ld [wd11e], a + ld hl, wTopMenuItemY + ld a, $5 + ld [hli], a + ld a, $6 + ld [hli], a + xor a + ld [hli], a + inc hl + ld a, $3 + ld [hli], a + ld [hli], a + xor a + ld [hl], a +.waitForInputLoop + call HandleMenuInput + and A_BUTTON | B_BUTTON + add a + add a + ld b, a + ld a, [wCurrentMenuItem] + cp $3 + jr nz,.asm_f586b + bit 2,b + jr z,.asm_f586b + dec a + ld b,$8 +.asm_f586b + add b + add $d0 + ld [wLinkMenuSelectionSendBuffer], a + ld [wLinkMenuSelectionSendBuffer + 1], a +.exchangeMenuSelectionLoop + call Serial_ExchangeLinkMenuSelection + ld a, [wLinkMenuSelectionReceiveBuffer] + ld b, a + and $f0 + cp $d0 + jr z, .asm_f5c7d + ld a, [wLinkMenuSelectionReceiveBuffer + 1] + ld b, a + and $f0 + cp $d0 + jr nz, .exchangeMenuSelectionLoop +.asm_f5c7d + ld a, b + and $c ; did the enemy press A or B? + jr nz, .enemyPressedAOrB +; the enemy didn't press A or B + ld a, [wLinkMenuSelectionSendBuffer] + and $c ; did the player press A or B? + jr z, .waitForInputLoop ; if neither the player nor the enemy pressed A or B, try again + jr .doneChoosingMenuSelection ; if the player pressed A or B but the enemy didn't, use the player's selection +.enemyPressedAOrB + ld a, [wLinkMenuSelectionSendBuffer] + and $c ; did the player press A or B? + jr z, .useEnemyMenuSelection ; if the enemy pressed A or B but the player didn't, use the enemy's selection +; the enemy and the player both pressed A or B +; The gameboy that is clocking the connection wins. + ld a, [hSerialConnectionStatus] + cp USING_INTERNAL_CLOCK + jr z, .doneChoosingMenuSelection +.useEnemyMenuSelection + ld a, $1 + ld [wd11e], a + ld a, b + ld [wLinkMenuSelectionSendBuffer], a + and $3 + ld [wCurrentMenuItem], a ; wCurrentMenuItem +.doneChoosingMenuSelection + ld a, [hSerialConnectionStatus] + cp USING_INTERNAL_CLOCK + jr nz, .skipStartingTransfer + call DelayFrame + call DelayFrame + ld a, START_TRANSFER_INTERNAL_CLOCK + ld [rSC], a +.skipStartingTransfer + ld b, " " + ld c, " " + ld d, " " + ld e, "▷" + ld a, [wLinkMenuSelectionSendBuffer] + and (B_BUTTON << 2) ; was B button pressed? + jr nz, .updateCursorPosition +; A button was pressed + ld a, [wCurrentMenuItem] + cp $2 + jp z, .asm_f5963 + ld b, e + ld e, c + ld a, [wCurrentMenuItem] + and a + jr z, .updateCursorPosition + ld c, b + ld b, d + dec a + jr z, .updateCursorPosition + ld d, c + ld c, b +.updateCursorPosition + call Func_f59ec + call LoadScreenTilesFromBuffer1 + ld a, [wLinkMenuSelectionSendBuffer] + and (B_BUTTON << 2) ; was B button pressed? + jr nz, .choseCancel ; cancel if B pressed + ld a, [wCurrentMenuItem] + cp $2 + jr z, .choseCancel + xor a + ld [wWalkBikeSurfState], a ; start walking + ld a, [wCurrentMenuItem] + and a + ld a, COLOSSEUM + jr nz, .next + ld a, TRADE_CENTER +.next + ld [wd72d], a + ld hl, ColosseumPleaseWaitText + call PrintText + ld c, 50 + call DelayFrames + ld hl, wd732 + res 1, [hl] + ld a, [wDefaultMap] + ld [wDestinationMap], a + callab SpecialWarpIn + ld c, 20 + call DelayFrames + xor a + ld [wMenuJoypadPollCount], a + ld [wSerialExchangeNybbleSendData], a + inc a ; LINK_STATE_IN_CABLE_CLUB + ld [wLinkState], a + ld [wEnteringCableClub], a + jpab SpecialEnterMap +.choseCancel + xor a + ld [wMenuJoypadPollCount], a + call Delay3 + callab CloseLinkConnection + ld hl, ColosseumCanceledText + call PrintText + ld hl, wd72e + res 6, [hl] + ret + +.asm_f5963 + ld a,[wd11e] + and a + jr nz,.asm_f5974 + ld b," " + ld c," " + ld d,"▷" + ld e," " + call Func_f59ec +.asm_f5974 + xor a + ld [wBuffer], a + ld a,$ff + ld [wSerialExchangeNybbleReceiveData],a + ld a, $b + ld [wLinkMenuSelectionSendBuffer], a + ld b,$78 +.loop + ld a,[hSerialConnectionStatus] + cp $2 + call z,DelayFrame + dec b + jr z,.asm_f59b2 + call Serial_ExchangeNybble + call DelayFrame + ld a,[wSerialExchangeNybbleReceiveData] + inc a + jr z,.loop + ld b,$f +.loop2 + call DelayFrame + call Serial_ExchangeNybble + dec b + jr nz,.loop2 + ld b,$f +.loop3 + call DelayFrame + call Serial_SendZeroByte + dec b + jr nz,.loop3 + jr .asm_f59d6 + +.asm_f59b2 + xor a + ld [wUnknownSerialCounter],a + ld [wUnknownSerialCounter+1],a + ld a,[wd11e] + and a + jr z,.asm_f59cd + ld b," " + ld c," " + ld d," " + ld e,"▷" + call Func_f59ec + jp .choseCancel + +.asm_f59cd + ld hl,ColosseumVersionText + call PrintText + jp .choseCancel + +.asm_f59d6 + ld b," " + ld c," " + ld d,"▷" + ld e," " + call Func_f59ec + call Func_f531b + jp c,.choseCancel + ld a,$f0 + jp .next + +Func_f59ec:: + ld a, b + Coorda 6, 5 + ld a, c + Coorda 6, 7 + ld a, d + Coorda 6, 9 + ld a, e + Coorda 6, 11 + ld c, 40 + call DelayFrames + ret + +ColosseumWhereToText: + TX_FAR _ColosseumWhereToText + db "@" + +ColosseumPleaseWaitText: + TX_FAR _ColosseumPleaseWaitText + db "@" + +ColosseumCanceledText: + TX_FAR _ColosseumCanceledText + db "@" + +ColosseumVersionText: + TX_FAR _ColosseumVersionText + db "@" + +TextTerminator_f5a16: + db "@" + +TradeCenterText: + db "TRADE CENTER" + next "COLOSSEUM" + next "COLOSSEUM2" + next "CANCEL@" diff --git a/engine/menu/main_menu.asm b/engine/menu/main_menu.asm index da2e98e4..ce27ebba 100755 --- a/engine/menu/main_menu.asm +++ b/engine/menu/main_menu.asm @@ -34,8 +34,7 @@ MainMenu: jr z, .noSaveFile ; there's a save file coord hl, 0, 0 - ld b, 6 - ld c, 13 + lb bc, 6, 13 call TextBoxBorder coord hl, 2, 2 ld de, ContinueText @@ -43,8 +42,7 @@ MainMenu: jr .next2 .noSaveFile coord hl, 0, 0 - ld b, 4 - ld c, 13 + lb bc, 4, 13 call TextBoxBorder coord hl, 2, 2 ld de, NewGameText @@ -129,185 +127,29 @@ InitOptions: ld [wLetterPrintingDelayFlags], a ld a, 3 ; medium speed ld [wOptions], a + ld a, 64 ; audio? + ld [wPrinterSettings], a ret -LinkMenu: - xor a - ld [wLetterPrintingDelayFlags], a - ld hl, wd72e - set 6, [hl] - ld hl, TextTerminator_6b20 - call PrintText - call SaveScreenTilesToBuffer1 - ld hl, WhereWouldYouLikeText - call PrintText - coord hl, 5, 5 - ld b, $6 - ld c, $d - call TextBoxBorder - call UpdateSprites - coord hl, 7, 7 - ld de, CableClubOptionsText - call PlaceString - xor a - ld [wUnusedCD37], a - ld [wd72d], a - ld hl, wTopMenuItemY - ld a, $7 - ld [hli], a - ld a, $6 - ld [hli], a - xor a - ld [hli], a - inc hl - ld a, $2 - ld [hli], a - inc a - ; ld a, A_BUTTON | B_BUTTON - ld [hli], a ; wMenuWatchedKeys - xor a - ld [hl], a -.waitForInputLoop - call HandleMenuInput - and A_BUTTON | B_BUTTON - add a - add a - ld b, a - ld a, [wCurrentMenuItem] - add b - add $d0 - ld [wLinkMenuSelectionSendBuffer], a - ld [wLinkMenuSelectionSendBuffer + 1], a -.exchangeMenuSelectionLoop - call Serial_ExchangeLinkMenuSelection - ld a, [wLinkMenuSelectionReceiveBuffer] - ld b, a - and $f0 - cp $d0 - jr z, .asm_5c7d - ld a, [wLinkMenuSelectionReceiveBuffer + 1] - ld b, a - and $f0 - cp $d0 - jr nz, .exchangeMenuSelectionLoop -.asm_5c7d - ld a, b - and $c ; did the enemy press A or B? - jr nz, .enemyPressedAOrB -; the enemy didn't press A or B - ld a, [wLinkMenuSelectionSendBuffer] - and $c ; did the player press A or B? - jr z, .waitForInputLoop ; if neither the player nor the enemy pressed A or B, try again - jr .doneChoosingMenuSelection ; if the player pressed A or B but the enemy didn't, use the player's selection -.enemyPressedAOrB - ld a, [wLinkMenuSelectionSendBuffer] - and $c ; did the player press A or B? - jr z, .useEnemyMenuSelection ; if the enemy pressed A or B but the player didn't, use the enemy's selection -; the enemy and the player both pressed A or B -; The gameboy that is clocking the connection wins. - ld a, [hSerialConnectionStatus] - cp USING_INTERNAL_CLOCK - jr z, .doneChoosingMenuSelection -.useEnemyMenuSelection - ld a, b - ld [wLinkMenuSelectionSendBuffer], a - and $3 - ld [wCurrentMenuItem], a -.doneChoosingMenuSelection - ld a, [hSerialConnectionStatus] - cp USING_INTERNAL_CLOCK - jr nz, .skipStartingTransfer - call DelayFrame - call DelayFrame - ld a, START_TRANSFER_INTERNAL_CLOCK - ld [rSC], a -.skipStartingTransfer - ld b, $7f - ld c, $7f - ld d, $ec - ld a, [wLinkMenuSelectionSendBuffer] - and (B_BUTTON << 2) ; was B button pressed? - jr nz, .updateCursorPosition -; A button was pressed - ld a, [wCurrentMenuItem] - cp $2 - jr z, .updateCursorPosition - ld c, d - ld d, b - dec a - jr z, .updateCursorPosition - ld b, c - ld c, d -.updateCursorPosition - ld a, b - Coorda 6, 7 - ld a, c - Coorda 6, 9 - ld a, d - Coorda 6, 11 - ld c, 40 - call DelayFrames - call LoadScreenTilesFromBuffer1 - ld a, [wLinkMenuSelectionSendBuffer] - and (B_BUTTON << 2) ; was B button pressed? - jr nz, .choseCancel ; cancel if B pressed - ld a, [wCurrentMenuItem] - cp $2 - jr z, .choseCancel - xor a - ld [wWalkBikeSurfState], a ; start walking - ld a, [wCurrentMenuItem] - and a - ld a, COLOSSEUM - jr nz, .next - ld a, TRADE_CENTER -.next - ld [wd72d], a - ld hl, PleaseWaitText +Func_5cc1: +; unused? + ld a, $6d + cp $80 + ret c ; will always be executed + ld hl, NotEnoughMemoryText call PrintText - ld c, 50 - call DelayFrames - ld hl, wd732 - res 1, [hl] - ld a, [wDefaultMap] - ld [wDestinationMap], a - call SpecialWarpIn - ld c, 20 - call DelayFrames - xor a - ld [wMenuJoypadPollCount], a - ld [wSerialExchangeNybbleSendData], a - inc a ; LINK_STATE_IN_CABLE_CLUB - ld [wLinkState], a - ld [wEnteringCableClub], a - jr SpecialEnterMap -.choseCancel - xor a - ld [wMenuJoypadPollCount], a - call Delay3 - call CloseLinkConnection - ld hl, LinkCanceledText - call PrintText - ld hl, wd72e - res 6, [hl] ret -WhereWouldYouLikeText: - TX_FAR _WhereWouldYouLikeText - db "@" - -PleaseWaitText: - TX_FAR _PleaseWaitText - db "@" - -LinkCanceledText: - TX_FAR _LinkCanceledText +NotEnoughMemoryText: + TX_FAR _NotEnoughMemoryText db "@" StartNewGame: ld hl, wd732 res 1, [hl] call OakSpeech + ld a, $8 + ld [wPlayerMovingDirection], a ld c, 20 call DelayFrames @@ -323,6 +165,7 @@ SpecialEnterMap: call ResetPlayerSpriteData ld c, 20 call DelayFrames + call Func_5cc1 ld a, [wEnteringCableClub] and a ret nz @@ -335,17 +178,11 @@ NewGameText: db "NEW GAME" next "OPTION@" -CableClubOptionsText: - db "TRADE CENTER" - next "COLOSSEUM" - next "CANCEL@" - DisplayContinueGameInfo: xor a ld [H_AUTOBGTRANSFERENABLED], a coord hl, 4, 7 - ld b, 8 - ld c, 14 + lb bc, 8, 14 call TextBoxBorder coord hl, 5, 9 ld de, SaveScreenInfoText @@ -368,8 +205,7 @@ PrintSaveScreenText: xor a ld [H_AUTOBGTRANSFERENABLED], a coord hl, 4, 0 - ld b, $8 - ld c, $e + lb bc, 8, 14 call TextBoxBorder call LoadTextBoxTilePatterns call UpdateSprites @@ -427,259 +263,8 @@ SaveScreenInfoText: next "TIME@" DisplayOptionMenu: - coord hl, 0, 0 - ld b, 3 - ld c, 18 - call TextBoxBorder - coord hl, 0, 5 - ld b, 3 - ld c, 18 - call TextBoxBorder - coord hl, 0, 10 - ld b, 3 - ld c, 18 - call TextBoxBorder - coord hl, 1, 1 - ld de, TextSpeedOptionText - call PlaceString - coord hl, 1, 6 - ld de, BattleAnimationOptionText - call PlaceString - coord hl, 1, 11 - ld de, BattleStyleOptionText - call PlaceString - coord hl, 2, 16 - ld de, OptionMenuCancelText - call PlaceString - xor a - ld [wCurrentMenuItem], a - ld [wLastMenuItem], a - inc a - ld [wLetterPrintingDelayFlags], a - ld [wUnusedCD40], a - ld a, 3 ; text speed cursor Y coordinate - ld [wTopMenuItemY], a - call SetCursorPositionsFromOptions - ld a, [wOptionsTextSpeedCursorX] ; text speed cursor X coordinate - ld [wTopMenuItemX], a - ld a, $01 - ld [H_AUTOBGTRANSFERENABLED], a ; enable auto background transfer - call Delay3 -.loop - call PlaceMenuCursor - call SetOptionsFromCursorPositions -.getJoypadStateLoop - call JoypadLowSensitivity - ld a, [hJoy5] - ld b, a - and A_BUTTON | B_BUTTON | START | D_RIGHT | D_LEFT | D_UP | D_DOWN ; any key besides select pressed? - jr z, .getJoypadStateLoop - bit 1, b ; B button pressed? - jr nz, .exitMenu - bit 3, b ; Start button pressed? - jr nz, .exitMenu - bit 0, b ; A button pressed? - jr z, .checkDirectionKeys - ld a, [wTopMenuItemY] - cp 16 ; is the cursor on Cancel? - jr nz, .loop -.exitMenu - ld a, SFX_PRESS_AB - call PlaySound + callab DisplayOptionMenu_ ret -.eraseOldMenuCursor - ld [wTopMenuItemX], a - call EraseMenuCursor - jp .loop -.checkDirectionKeys - ld a, [wTopMenuItemY] - bit 7, b ; Down pressed? - jr nz, .downPressed - bit 6, b ; Up pressed? - jr nz, .upPressed - cp 8 ; cursor in Battle Animation section? - jr z, .cursorInBattleAnimation - cp 13 ; cursor in Battle Style section? - jr z, .cursorInBattleStyle - cp 16 ; cursor on Cancel? - jr z, .loop -.cursorInTextSpeed - bit 5, b ; Left pressed? - jp nz, .pressedLeftInTextSpeed - jp .pressedRightInTextSpeed -.downPressed - cp 16 - ld b, -13 - ld hl, wOptionsTextSpeedCursorX - jr z, .updateMenuVariables - ld b, 5 - cp 3 - inc hl - jr z, .updateMenuVariables - cp 8 - inc hl - jr z, .updateMenuVariables - ld b, 3 - inc hl - jr .updateMenuVariables -.upPressed - cp 8 - ld b, -5 - ld hl, wOptionsTextSpeedCursorX - jr z, .updateMenuVariables - cp 13 - inc hl - jr z, .updateMenuVariables - cp 16 - ld b, -3 - inc hl - jr z, .updateMenuVariables - ld b, 13 - inc hl -.updateMenuVariables - add b - ld [wTopMenuItemY], a - ld a, [hl] - ld [wTopMenuItemX], a - call PlaceUnfilledArrowMenuCursor - jp .loop -.cursorInBattleAnimation - ld a, [wOptionsBattleAnimCursorX] ; battle animation cursor X coordinate - xor $0b ; toggle between 1 and 10 - ld [wOptionsBattleAnimCursorX], a - jp .eraseOldMenuCursor -.cursorInBattleStyle - ld a, [wOptionsBattleStyleCursorX] ; battle style cursor X coordinate - xor $0b ; toggle between 1 and 10 - ld [wOptionsBattleStyleCursorX], a - jp .eraseOldMenuCursor -.pressedLeftInTextSpeed - ld a, [wOptionsTextSpeedCursorX] ; text speed cursor X coordinate - cp 1 - jr z, .updateTextSpeedXCoord - cp 7 - jr nz, .fromSlowToMedium - sub 6 - jr .updateTextSpeedXCoord -.fromSlowToMedium - sub 7 - jr .updateTextSpeedXCoord -.pressedRightInTextSpeed - ld a, [wOptionsTextSpeedCursorX] ; text speed cursor X coordinate - cp 14 - jr z, .updateTextSpeedXCoord - cp 7 - jr nz, .fromFastToMedium - add 7 - jr .updateTextSpeedXCoord -.fromFastToMedium - add 6 -.updateTextSpeedXCoord - ld [wOptionsTextSpeedCursorX], a ; text speed cursor X coordinate - jp .eraseOldMenuCursor - -TextSpeedOptionText: - db "TEXT SPEED" - next " FAST MEDIUM SLOW@" - -BattleAnimationOptionText: - db "BATTLE ANIMATION" - next " ON OFF@" - -BattleStyleOptionText: - db "BATTLE STYLE" - next " SHIFT SET@" - -OptionMenuCancelText: - db "CANCEL@" - -; sets the options variable according to the current placement of the menu cursors in the options menu -SetOptionsFromCursorPositions: - ld hl, TextSpeedOptionData - ld a, [wOptionsTextSpeedCursorX] ; text speed cursor X coordinate - ld c, a -.loop - ld a, [hli] - cp c - jr z, .textSpeedMatchFound - inc hl - jr .loop -.textSpeedMatchFound - ld a, [hl] - ld d, a - ld a, [wOptionsBattleAnimCursorX] ; battle animation cursor X coordinate - dec a - jr z, .battleAnimationOn -.battleAnimationOff - set 7, d - jr .checkBattleStyle -.battleAnimationOn - res 7, d -.checkBattleStyle - ld a, [wOptionsBattleStyleCursorX] ; battle style cursor X coordinate - dec a - jr z, .battleStyleShift -.battleStyleSet - set 6, d - jr .storeOptions -.battleStyleShift - res 6, d -.storeOptions - ld a, d - ld [wOptions], a - ret - -; reads the options variable and places menu cursors in the correct positions within the options menu -SetCursorPositionsFromOptions: - ld hl, TextSpeedOptionData + 1 - ld a, [wOptions] - ld c, a - and $3f - push bc - ld de, 2 - call IsInArray - pop bc - dec hl - ld a, [hl] - ld [wOptionsTextSpeedCursorX], a ; text speed cursor X coordinate - coord hl, 0, 3 - call .placeUnfilledRightArrow - sla c - ld a, 1 ; On - jr nc, .storeBattleAnimationCursorX - ld a, 10 ; Off -.storeBattleAnimationCursorX - ld [wOptionsBattleAnimCursorX], a ; battle animation cursor X coordinate - coord hl, 0, 8 - call .placeUnfilledRightArrow - sla c - ld a, 1 - jr nc, .storeBattleStyleCursorX - ld a, 10 -.storeBattleStyleCursorX - ld [wOptionsBattleStyleCursorX], a ; battle style cursor X coordinate - coord hl, 0, 13 - call .placeUnfilledRightArrow -; cursor in front of Cancel - coord hl, 0, 16 - ld a, 1 -.placeUnfilledRightArrow - ld e, a - ld d, 0 - add hl, de - ld [hl], $ec ; unfilled right arrow menu cursor - ret - -; table that indicates how the 3 text speed options affect frame delays -; Format: -; 00: X coordinate of menu cursor -; 01: delay after printing a letter (in frames) -TextSpeedOptionData: - db 14,5 ; Slow - db 7,3 ; Medium - db 1,1 ; Fast - db 7 ; default X coordinate (Medium) - db $ff ; terminator CheckForPlayerNameInSRAM: ; Check if the player name data in SRAM has a string terminator character diff --git a/engine/menu/naming_screen.asm b/engine/menu/naming_screen.asm index 64065c4d..2560677a 100755 --- a/engine/menu/naming_screen.asm +++ b/engine/menu/naming_screen.asm @@ -5,8 +5,7 @@ AskName: ld a, [wIsInBattle] dec a coord hl, 0, 0 - ld b, 4 - ld c, 11 + lb bc, 4, 11 call z, ClearScreenArea ; only if in wild battle ld a, [wcf91] ld [wd11e], a @@ -94,8 +93,7 @@ DisplayNamingScreen: call LoadEDTile callba LoadMonPartySpriteGfx coord hl, 0, 4 - ld b, 9 - ld c, 18 + lb bc, 9, 18 call TextBoxBorder call PrintNamingText ld a, 3 @@ -324,12 +322,28 @@ DisplayNamingScreen: jp EraseMenuCursor LoadEDTile: +; In Red/Blue, the bank for the ED_tile was defined incorrectly as bank0 +; Luckily, the MBC3 treats loading $0 into $2000-$2fff range as loading bank1 into $4000-$7fff range +; Because Yellow uses the MBC5, loading $0 into $2000 - $2fff range will load bank0 instead of bank1 and thus incorrectly load the tile +; Instead of defining the correct bank, GameFreak decided to simply copy the ED_Tile in the function during HBlank ld de, ED_Tile ld hl, vFont + $700 - ld bc, (ED_TileEnd - ED_Tile) / $8 - ; to fix the graphical bug on poor emulators - ;lb bc, BANK(ED_Tile), (ED_TileEnd - ED_Tile) / $8 - jp CopyVideoDataDouble + ld c, $4 ; number of copies needed +.waitForHBlankLoop + ld a, [rSTAT] + and %10 ; in HBlank? + jr nz, .waitForHBlankLoop + ld a, [de] + ld [hli], a + ld [hli], a + inc de + ld a, [de] + ld [hli], a + ld [hli], a + inc de + dec c + jr nz, .waitForHBlankLoop + ret ED_Tile: INCBIN "gfx/ED_tile.1bpp" diff --git a/engine/menu/options.asm b/engine/menu/options.asm new file mode 100644 index 00000000..da89ad82 --- /dev/null +++ b/engine/menu/options.asm @@ -0,0 +1,443 @@ +DisplayOptionMenu_: + call InitOptionsMenu +.optionMenuLoop + call JoypadLowSensitivity + ld a, [hJoy5] + and START | B_BUTTON + jr nz, .exitOptionMenu + call OptionsControl + jr c, .dpadDelay + call GetOptionPointer + jr c, .exitOptionMenu +.dpadDelay + call OptionsMenu_UpdateCursorPosition + call DelayFrame + call DelayFrame + call DelayFrame + jr .optionMenuLoop +.exitOptionMenu + ret + +GetOptionPointer: + ld a, [wOptionsCursorLocation] + ld e, a + ld d, $0 + ld hl, OptionMenuJumpTable + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + jp hl ; jump to the function for the current highlighted option + +OptionMenuJumpTable: + dw OptionsMenu_TextSpeed + dw OptionsMenu_BattleAnimations + dw OptionsMenu_BattleStyle + dw OptionsMenu_SpeakerSettings + dw OptionsMenu_GBPrinterBrightness + dw OptionsMenu_Dummy + dw OptionsMenu_Dummy + dw OptionsMenu_Cancel + +OptionsMenu_TextSpeed: + call GetTextSpeed + ld a, [hJoy5] + bit 4, a ; right + jr nz, .pressedRight + bit 5, a + jr nz, .pressedLeft + jr .asm_41ce0 +.pressedRight + ld a, c + cp $2 + jr c, .asm_41cca + ld c, $ff +.asm_41cca + inc c + ld a, e + jr .asm_41cd6 +.pressedLeft + ld a, c + and a + jr nz, .asm_41cd4 + ld c, $3 +.asm_41cd4 + dec c + ld a, d +.asm_41cd6 + ld b, a + ld a, [wOptions] + and $f0 + or b + ld [wOptions], a +.asm_41ce0 + ld b, $0 + ld hl, TextSpeedStringsPointerTable + add hl, bc + add hl, bc + ld e, [hl] + inc hl + ld d, [hl] + coord hl, 14, 2 + call PlaceString + and a + ret + +TextSpeedStringsPointerTable: + dw FastText + dw MidText + dw SlowText + +FastText: + db "FAST@" +MidText: + db "MID @" +SlowText: + db "SLOW@" + +GetTextSpeed: + ld a, [wOptions] + and $f + cp $5 + jr z, .slowTextOption + cp $1 + jr z, .fastTextOption +; mid text option + ld c, $1 + lb de, 1, 5 + ret +.slowTextOption + ld c, $2 + lb de, 3, 1 + ret +.fastTextOption + ld c, $0 + lb de, 5, 3 + ret + +OptionsMenu_BattleAnimations: + ld a, [hJoy5] + and D_RIGHT | D_LEFT + jr nz, .asm_41d33 + ld a, [wOptions] + and $80 ; mask other bits + jr .asm_41d3b +.asm_41d33 + ld a, [wOptions] + xor $80 + ld [wOptions], a +.asm_41d3b + ld bc, $0 + sla a + rl c + ld hl, AnimationOptionStringsPointerTable + add hl, bc + add hl, bc + ld e, [hl] + inc hl + ld d, [hl] + coord hl, 14, 4 + call PlaceString + and a + ret + +AnimationOptionStringsPointerTable: + dw AnimationOnText + dw AnimationOffText + +AnimationOnText: + db "ON @" +AnimationOffText: + db "OFF@" + +OptionsMenu_BattleStyle: + ld a, [hJoy5] + and D_LEFT | D_RIGHT + jr nz, .asm_41d6b + ld a, [wOptions] + and $40 ; mask other bits + jr .asm_41d73 +.asm_41d6b + ld a, [wOptions] + xor $40 + ld [wOptions], a +.asm_41d73 + ld bc, $0 + sla a + sla a + rl c + ld hl, BattleStyleOptionStringsPointerTable + add hl, bc + add hl, bc + ld e, [hl] + inc hl + ld d, [hl] + coord hl, 14, 6 + call PlaceString + and a + ret + +BattleStyleOptionStringsPointerTable: + dw BattleStyleShiftText + dw BattleStyleSetText + +BattleStyleShiftText: + db "SHIFT@" +BattleStyleSetText: + db "SET @" + +OptionsMenu_SpeakerSettings: + ld a, [wOptions] + and $30 + swap a + ld c, a + ld a, [hJoy5] + bit 4, a + jr nz, .pressedRight + bit 5, a + jr nz, .pressedLeft + jr .asm_41dca +.pressedRight + ld a, c + inc a + and $3 + jr .asm_41dba +.pressedLeft + ld a, c + dec a + and $3 +.asm_41dba + ld c, a + swap a + ld b, a + xor a + ld [rNR51], a + ld a, [wOptions] + and $cf + or b + ld [wOptions], a +.asm_41dca + ld b, $0 + ld hl, SpeakerOptionStringsPointerTable + add hl, bc + add hl, bc + ld e, [hl] + inc hl + ld d, [hl] + coord hl, 8, 8 + call PlaceString + and a + ret + +SpeakerOptionStringsPointerTable: + dw MonoSoundText + dw Earphone1SoundText + dw Earphone2SoundText + dw Earphone3SoundText + +MonoSoundText: + db "MONO @" +Earphone1SoundText: + db "EARPHONE1@" +Earphone2SoundText: + db "EARPHONE2@" +Earphone3SoundText: + db "EARPHONE3@" + +OptionsMenu_GBPrinterBrightness: + call Func_41e7b + ld a, [hJoy5] + bit 4, a + jr nz, .pressedRight + bit 5, a + jr nz, .pressedLeft + jr .asm_41e32 +.pressedRight + ld a, c + cp $4 + jr c, .asm_41e22 + ld c, $ff +.asm_41e22 + inc c + ld a, e + jr .asm_41e2e +.pressedLeft + ld a, c + and a + jr nz, .asm_41e2c + ld c, $5 +.asm_41e2c + dec c + ld a, d +.asm_41e2e + ld b, a + ld [wPrinterSettings], a +.asm_41e32 + ld b, $0 + ld hl, GBPrinterOptionStringsPointerTable + add hl, bc + add hl, bc + ld e, [hl] + inc hl + ld d, [hl] + coord hl, 8, 10 + call PlaceString + and a + ret + +GBPrinterOptionStringsPointerTable: + dw LightestPrintText + dw LighterPrintText + dw NormalPrintText + dw DarkerPrintText + dw DarkestPrintText + +LightestPrintText: + db "LIGHTEST@" +LighterPrintText: + db "LIGHTER @" +NormalPrintText: + db "NORMAL @" +DarkerPrintText: + db "DARKER @" +DarkestPrintText: + db "DARKEST @" + +Func_41e7b: + ld a, [wPrinterSettings] + and a + jr z, .asm_41e93 + cp $20 + jr z, .asm_41e99 + cp $60 + jr z, .asm_41e9f + cp $7f + jr z, .asm_41ea5 + ld c, $2 + lb de, $20, $60 + ret +.asm_41e93 + ld c, $0 + lb de, $7f, $20 + ret +.asm_41e99 + ld c, $1 + lb de, $0, $40 + ret +.asm_41e9f + ld c, $3 + lb de, $40, $7f + ret +.asm_41ea5 + ld c, $4 + lb de, $60, $0 + ret + +OptionsMenu_Dummy: + and a + ret + +OptionsMenu_Cancel: + ld a, [hJoy5] + and A_BUTTON + jr nz, .pressedCancel + and a + ret +.pressedCancel + scf + ret + +OptionsControl: + ld hl, wOptionsCursorLocation + ld a, [hJoy5] + cp D_DOWN + jr z, .pressedDown + cp D_UP + jr z, .pressedUp + and a + ret +.pressedDown + ld a, [hl] + cp $7 + jr nz, .doNotWrapAround + ld [hl], $0 + scf + ret +.doNotWrapAround + cp $4 + jr c, .regularIncrement + ld [hl], $6 +.regularIncrement + inc [hl] + scf + ret +.pressedUp + ld a, [hl] + cp $7 + jr nz, .doNotMoveCursorToPrintOption + ld [hl], $4 + scf + ret +.doNotMoveCursorToPrintOption + and a + jr nz, .regularDecrement + ld [hl], $8 +.regularDecrement + dec [hl] + scf + ret + +OptionsMenu_UpdateCursorPosition: + coord hl, 1, 1 + ld de, SCREEN_WIDTH + ld c, 16 +.loop + ld [hl], " " + add hl, de + dec c + jr nz, .loop + coord hl, 1, 2 + ld bc, SCREEN_WIDTH * 2 + ld a, [wOptionsCursorLocation] + call AddNTimes + ld [hl], "▶" + ret + +InitOptionsMenu: + coord hl, 0, 0 + lb bc, SCREEN_HEIGHT - 2, SCREEN_WIDTH - 2 + call TextBoxBorder + coord hl, 2, 2 + ld de, AllOptionsText + call PlaceString + coord hl, 2, 16 + ld de, OptionMenuCancelText + call PlaceString + xor a + ld [wOptionsCursorLocation], a + ld c, 5 ; the number of options to loop through +.loop + push bc + call GetOptionPointer ; updates the next option + pop bc + ld hl, wOptionsCursorLocation + inc [hl] ; moves the cursor for the highlighted option + dec c + jr nz, .loop + xor a + ld [wOptionsCursorLocation], a + inc a + ld [H_AUTOBGTRANSFERENABLED], a + call Delay3 + ret + +AllOptionsText: + db "TEXT SPEED :" + next "ANIMATION :" + next "BATTLESTYLE:" + next "SOUND:" + next "PRINT:@" + +OptionMenuCancelText: + db "CANCEL@" diff --git a/engine/menu/party_menu.asm b/engine/menu/party_menu.asm index 8323d0eb..00c757be 100755 --- a/engine/menu/party_menu.asm +++ b/engine/menu/party_menu.asm @@ -49,9 +49,17 @@ RedrawPartyMenu_: call GetPartyMonName pop hl call PlaceString ; print the pokemon's name - callba WriteMonPartySpriteOAMByPartyIndex ; place the appropriate pokemon icon ld a, [hPartyMonIndex] ld [wWhichPokemon], a + callab IsThisPartymonStarterPikachu_Party + jr nc, .regularMon + call CheckPikachuFollowingPlayer + jr z, .regularMon + ld a, $ff + ld [hPartyMonIndex], a +.regularMon + callba WriteMonPartySpriteOAMByPartyIndex ; place the appropriate pokemon icon + ld a, [wWhichPokemon] inc a ld [hPartyMonIndex], a call LoadMonData @@ -88,14 +96,14 @@ RedrawPartyMenu_: pop hl push hl ld bc, SCREEN_WIDTH + 1 ; down 1 row and right 1 column - ld a, [hFlags_0xFFF6] + ld a, [hFlags_0xFFFA] set 0, a - ld [hFlags_0xFFF6], a + ld [hFlags_0xFFFA], a add hl, bc predef DrawHP2 ; draw HP bar and prints current / max HP - ld a, [hFlags_0xFFF6] + ld a, [hFlags_0xFFFA] res 0, a - ld [hFlags_0xFFF6], a + ld [hFlags_0xFFFA], a call SetPartyMenuHPBarColor ; color the HP bar (on SGB) pop hl jr .printLevel @@ -109,8 +117,8 @@ RedrawPartyMenu_: jr nz, .placeMoveLearnabilityString ld de, .notAbleToLearnMoveText .placeMoveLearnabilityString - ld bc, 20 + 9 ; down 1 row and right 9 columns push hl + ld bc, 20 + 9 ; down 1 row and right 9 columns add hl, bc call PlaceString pop hl @@ -176,9 +184,9 @@ RedrawPartyMenu_: ; if it does match ld de, .ableToEvolveText .placeEvolutionStoneString - ld bc, 20 + 9 ; down 1 row and right 9 columns pop hl push hl + ld bc, 20 + 9 ; down 1 row and right 9 columns add hl, bc call PlaceString pop hl diff --git a/engine/menu/players_pc.asm b/engine/menu/players_pc.asm index bc2be4ef..1cc02cbf 100755 --- a/engine/menu/players_pc.asm +++ b/engine/menu/players_pc.asm @@ -1,6 +1,4 @@ PlayerPC: - ld hl, wd730 - set 6, [hl] ld a, ITEM_NAME ld [wNameListType], a call SaveScreenTilesToBuffer1 @@ -17,14 +15,15 @@ PlayerPC: call PrintText PlayerPCMenu: + ld hl, wd730 + set 6, [hl] ld a, [wParentMenuItem] ld [wCurrentMenuItem], a ld hl, wFlags_0xcd60 set 5, [hl] call LoadScreenTilesFromBuffer2 coord hl, 0, 0 - ld b, $8 - ld c, $e + lb bc, 8, 14 call TextBoxBorder call UpdateSprites coord hl, 2, 2 diff --git a/engine/menu/pokedex.asm b/engine/menu/pokedex.asm index 8e1fd480..bc2a7e9b 100755 --- a/engine/menu/pokedex.asm +++ b/engine/menu/pokedex.asm @@ -12,9 +12,10 @@ ShowPokedexMenu: ld [wd11e], a ld [hJoy7], a .setUpGraphics + callab LoadPokedexTilePatterns +.loop ld b, SET_PAL_GENERIC call RunPaletteCommand - callab LoadPokedexTilePatterns .doPokemonListMenu ld hl, wTopMenuItemY ld a, 3 @@ -43,12 +44,15 @@ ShowPokedexMenu: call GBPalWhiteOutWithDelay3 call RunDefaultPaletteCommand jp ReloadMapData + .goToSideMenu call HandlePokedexSideMenu dec b jr z, .exitPokedex ; if the player chose Quit dec b jr z, .doPokemonListMenu ; if pokemon not seen or player pressed B button + dec b + jr z, .loop jp .setUpGraphics ; if pokemon data or area was shown ; handles the menu on the lower right in the pokedex screen @@ -79,20 +83,21 @@ HandlePokedexSideMenu: jr z, .exitSideMenu call PokedexToIndex ld hl, wTopMenuItemY - ld a, 10 + ld a, 8 ld [hli], a ; top menu item Y ld a, 15 ld [hli], a ; top menu item X xor a ld [hli], a ; current menu item ID inc hl - ld a, 3 + ld a, 4 ld [hli], a ; max menu item ID - ;ld a, A_BUTTON | B_BUTTON + ld a, A_BUTTON | B_BUTTON ld [hli], a ; menu watched keys (A button and B button) xor a ld [hli], a ; old menu item ID ld [wMenuWatchMovingOutOfBounds], a + ld [hJoy7], a .handleMenuInput call HandleMenuInput bit 1, a ; was the B button pressed? @@ -105,6 +110,8 @@ HandlePokedexSideMenu: jr z, .choseCry dec a jr z, .choseArea + dec a + jr z, .chosePrint .choseQuit ld b, 1 .exitSideMenu @@ -118,6 +125,8 @@ HandlePokedexSideMenu: ld [wLastMenuItem], a pop af ld [wCurrentMenuItem], a + ld a, $1 + ld [hJoy7], a push bc coord hl, 0, 3 ld de, 20 @@ -128,9 +137,9 @@ HandlePokedexSideMenu: .buttonBPressed push bc - coord hl, 15, 10 + coord hl, 15, 8 ld de, 20 - lb bc, " ", 7 + lb bc, " ", 9 call DrawTileLine ; cover up the menu cursor in the side menu pop bc jr .exitSideMenu @@ -152,13 +161,105 @@ HandlePokedexSideMenu: ld b, 0 jr .exitSideMenu +.chosePrint + ld a, [hTilesetType] + push af + xor a + ld [hTilesetType], a + ld a, [wd11e] + ld [wcf91], a + callab PrintPokedexEntry + xor a + ld [H_AUTOBGTRANSFERENABLED], a + call ClearScreen + pop af + ld [hTilesetType], a + ld b, $3 + jr .exitSideMenu + ; handles the list of pokemon on the left of the pokedex screen ; sets carry flag if player presses A, unsets carry flag if player presses B HandlePokedexListMenu: + call Pokedex_DrawInterface +.loop + call Pokedex_PlacePokemonList + call GBPalNormal + call HandleMenuInput + bit BIT_B_BUTTON, a ; was the B button pressed? + jp nz, .buttonBPressed + bit BIT_A_BUTTON, a ; was the A button pressed? + jp nz, .buttonAPressed +.checkIfUpPressed + bit BIT_D_UP, a ; was Up pressed? + jr z, .checkIfDownPressed +.upPressed ; scroll up one row + ld a, [wListScrollOffset] + and a + jp z, .loop + dec a + ld [wListScrollOffset], a + jp .loop + +.checkIfDownPressed + bit BIT_D_DOWN, a ; was Down pressed? + jr z, .checkIfRightPressed +.downPressed ; scroll down one row + ld a, [wDexMaxSeenMon] + cp a, 7 + jp c, .loop ; can't if the list is shorter than 7 + sub a, 7 + ld b, a + ld a, [wListScrollOffset] + cp b + jp z, .loop + inc a + ld [wListScrollOffset], a + jp .loop + +.checkIfRightPressed + bit BIT_D_RIGHT, a ; was Right pressed? + jr z, .checkIfLeftPressed +.rightPressed ; scroll down 7 rows + ld a, [wDexMaxSeenMon] + cp a, 7 + jp c, .loop ; can't if the list is shorter than 7 + sub a, 6 + ld b, a + ld a, [wListScrollOffset] + add a, 7 + ld [wListScrollOffset], a + cp b + jp c, .loop + dec b + ld a, b + ld [wListScrollOffset], a + jp .loop + +.checkIfLeftPressed ; scroll up 7 rows + bit BIT_D_LEFT, a ; was Left pressed? + jr z, .buttonAPressed +.leftPressed + ld a, [wListScrollOffset] + sub a, 7 + ld [wListScrollOffset], a + jp nc, .loop + xor a + ld [wListScrollOffset], a + jp .loop + +.buttonAPressed + scf + ret + +.buttonBPressed + and a + ret + +Pokedex_DrawInterface: xor a ld [H_AUTOBGTRANSFERENABLED], a ; draw the horizontal line separating the seen and owned amounts from the menu - coord hl, 15, 8 + coord hl, 15, 6 ld a, "─" ld [hli], a ld [hli], a @@ -175,26 +276,26 @@ HandlePokedexListMenu: ld b, wPokedexSeenEnd - wPokedexSeen call CountSetBits ld de, wNumSetBits - coord hl, 16, 3 + coord hl, 16, 2 lb bc, 1, 3 call PrintNumber ; print number of seen pokemon ld hl, wPokedexOwned ld b, wPokedexOwnedEnd - wPokedexOwned call CountSetBits ld de, wNumSetBits - coord hl, 16, 6 + coord hl, 16, 5 lb bc, 1, 3 call PrintNumber ; print number of owned pokemon - coord hl, 16, 2 + coord hl, 16, 1 ld de, PokedexSeenText call PlaceString - coord hl, 16, 5 + coord hl, 16, 4 ld de, PokedexOwnText call PlaceString coord hl, 1, 1 ld de, PokedexContentsText call PlaceString - coord hl, 16, 10 + coord hl, 16, 8 ld de, PokedexMenuItemsText call PlaceString ; find the highest pokedex number among the pokemon the player has seen @@ -214,7 +315,37 @@ HandlePokedexListMenu: .storeMaxSeenPokemon ld a, b ld [wDexMaxSeenMon], a + ret + +DrawPokedexVerticalLine: + ld c, 9 ; height of line + ld de, SCREEN_WIDTH ; width of screen + ld a, $71 ; vertical line tile .loop + ld [hl], a + add hl, de + xor a, 1 ; toggle between vertical line tile and box tile + dec c + jr nz, .loop + ret + +PokedexSeenText: + db "SEEN@" + +PokedexOwnText: + db "OWN@" + +PokedexContentsText: + db "CONTENTS@" + +PokedexMenuItemsText: + db "DATA" + next "CRY" + next "AREA" + next "PRNT" + next "QUIT@" + +Pokedex_PlacePokemonList: xor a ld [H_AUTOBGTRANSFERENABLED], a coord hl, 4, 2 @@ -282,98 +413,8 @@ HandlePokedexListMenu: ld a, 01 ld [H_AUTOBGTRANSFERENABLED], a call Delay3 - call GBPalNormal - call HandleMenuInput - bit 1, a ; was the B button pressed? - jp nz, .buttonBPressed -.checkIfUpPressed - bit 6, a ; was Up pressed? - jr z, .checkIfDownPressed -.upPressed ; scroll up one row - ld a, [wListScrollOffset] - and a - jp z, .loop - dec a - ld [wListScrollOffset], a - jp .loop -.checkIfDownPressed - bit 7, a ; was Down pressed? - jr z, .checkIfRightPressed -.downPressed ; scroll down one row - ld a, [wDexMaxSeenMon] - cp 7 - jp c, .loop ; can't if the list is shorter than 7 - sub 7 - ld b, a - ld a, [wListScrollOffset] - cp b - jp z, .loop - inc a - ld [wListScrollOffset], a - jp .loop -.checkIfRightPressed - bit 4, a ; was Right pressed? - jr z, .checkIfLeftPressed -.rightPressed ; scroll down 7 rows - ld a, [wDexMaxSeenMon] - cp 7 - jp c, .loop ; can't if the list is shorter than 7 - sub 6 - ld b, a - ld a, [wListScrollOffset] - add 7 - ld [wListScrollOffset], a - cp b - jp c, .loop - dec b - ld a, b - ld [wListScrollOffset], a - jp .loop -.checkIfLeftPressed ; scroll up 7 rows - bit 5, a ; was Left pressed? - jr z, .buttonAPressed -.leftPressed - ld a, [wListScrollOffset] - sub 7 - ld [wListScrollOffset], a - jp nc, .loop - xor a - ld [wListScrollOffset], a - jp .loop -.buttonAPressed - scf - ret -.buttonBPressed - and a ret -DrawPokedexVerticalLine: - ld c, 9 ; height of line - ld de, SCREEN_WIDTH - ld a, $71 ; vertical line tile -.loop - ld [hl], a - add hl, de - xor 1 ; toggle between vertical line tile and box tile - dec c - jr nz, .loop - ret - -PokedexSeenText: - db "SEEN@" - -PokedexOwnText: - db "OWN@" - -PokedexContentsText: - db "CONTENTS@" - -PokedexMenuItemsText: - db "DATA" - next "CRY" - next "AREA" - next "QUIT@" - ; tests if a pokemon's bit is set in the seen or owned pokemon bit fields ; INPUT: ; [wd11e] = pokedex number @@ -401,8 +442,11 @@ ShowPokedexDataInternal: set 1, [hl] ld a, $33 ; 3/7 volume ld [rNR50], a + ld a, [hTilesetType] + push af + xor a + ld [hTilesetType], a call GBPalWhiteOut ; zero all palettes - call ClearScreen ld a, [wd11e] ; pokemon ID ld [wcf91], a push af @@ -410,10 +454,44 @@ ShowPokedexDataInternal: call RunPaletteCommand pop af ld [wd11e], a - ld a, [hTilesetType] - push af - xor a + call DrawDexEntryOnScreen + call c, Pokedex_PrintFlavorTextAtRow11 +.waitForButtonPress + call JoypadLowSensitivity + ld a, [hJoy5] + and a, A_BUTTON | B_BUTTON + jr z, .waitForButtonPress + pop af ld [hTilesetType], a + call GBPalWhiteOut + call ClearScreen + call RunDefaultPaletteCommand + call LoadTextBoxTilePatterns + call GBPalNormal + ld hl, wd72c + res 1, [hl] + ld a, $77 ; max volume + ld [rNR50], a + ret + +HeightWeightText: + db "HT ?", $60, "??", $61 + next "WT ???lb@" + +; XXX does anything point to this? +PokeText: + db "#@" + +; horizontal line that divides the pokedex text description from the rest of the data +PokedexDataDividerLine: + db $68, $69, $6B, $69, $6B + db $69, $6B, $69, $6B, $6B + db $6B, $6B, $69, $6B, $69 + db $6B, $69, $6B, $69, $6A + db "@" + +DrawDexEntryOnScreen: + call ClearScreen coord hl, 0, 0 ld de, 1 @@ -512,7 +590,8 @@ ShowPokedexDataInternal: ld a, c and a - jp z, .waitForButtonPress ; if the pokemon has not been owned, don't print the height, weight, or description + ret z ; if the pokemon has not been owned, don't print the height, weight, or description + inc de ; de = address of feet (height) ld a, [de] ; reads feet, but a is overwritten without being used coord hl, 12, 6 @@ -565,45 +644,48 @@ ShowPokedexDataInternal: ld [hDexWeight], a ; restore original value of [hDexWeight] pop hl inc hl ; hl = address of pokedex description text + scf + ret + +Pokedex_PrintFlavorTextAtRow11: coord bc, 1, 11 +Pokedex_PrintFlavorTextAtBC: ld a, 2 - ld [$fff4], a + ld [$fff9], a call TextCommandProcessor ; print pokedex description text xor a - ld [$fff4], a -.waitForButtonPress - call JoypadLowSensitivity - ld a, [hJoy5] - and A_BUTTON | B_BUTTON - jr z, .waitForButtonPress - pop af - ld [hTilesetType], a - call GBPalWhiteOut - call ClearScreen - call RunDefaultPaletteCommand - call LoadTextBoxTilePatterns - call GBPalNormal - ld hl, wd72c - res 1, [hl] - ld a, $77 ; max volume - ld [rNR50], a + ld [$fff9], a ret -HeightWeightText: - db "HT ?",$60,"??",$61 - next "WT ???lb@" - -; XXX does anything point to this? -PokeText: - db "#@" - -; horizontal line that divides the pokedex text description from the rest of the data -PokedexDataDividerLine: - db $68,$69,$6B,$69,$6B - db $69,$6B,$69,$6B,$6B - db $6B,$6B,$69,$6B,$69 - db $6B,$69,$6B,$69,$6A - db "@" +Pokedex_PrepareDexEntryForPrinting: + coord hl, 0, 0 + ld de, SCREEN_WIDTH + lb bc, $66, $d + call DrawTileLine + coord hl, 19, 0 + ld b, $67 + call DrawTileLine + coord hl, 0, 13 + ld de, $1 + lb bc, $6f, SCREEN_WIDTH + call DrawTileLine + ld a, $6c + Coorda 0, 13 + ld a, $6e + Coorda 19, 13 + ld a, [wPrinterPokedexEntryTextPointer] + ld l, a + ld a, [wPrinterPokedexEntryTextPointer + 1] + ld h, a + coord bc, 1, 1 + ld a, [hFlags_0xFFFA] + set 3, a + ld [hFlags_0xFFFA], a + call Pokedex_PrintFlavorTextAtBC + ld a, [hFlags_0xFFFA] + res 3, a + ld [hFlags_0xFFFA], a + ret ; draws a line of tiles ; INPUT: diff --git a/engine/menu/prize_menu.asm b/engine/menu/prize_menu.asm index bcd0d4ea..405441c8 100755 --- a/engine/menu/prize_menu.asm +++ b/engine/menu/prize_menu.asm @@ -23,8 +23,7 @@ CeladonPrizeMenu: ld [wTopMenuItemX], a call PrintPrizePrice coord hl, 0, 2 - ld b, 8 - ld c, 16 + lb bc, 8, 16 call TextBoxBorder call GetPrizeMenuId call UpdateSprites @@ -145,12 +144,14 @@ GetPrizeMenuId: ld c, (1 << 7 | 2) jp PrintBCDNumber +NoThanksText: + db "NO THANKS@" + INCLUDE "data/prizes.asm" PrintPrizePrice: coord hl, 11, 0 - ld b, 1 - ld c, 7 + lb bc, 1, 7 call TextBoxBorder call UpdateSprites coord hl, 12, 0 diff --git a/engine/menu/start_menu.asm b/engine/menu/start_menu.asm index eb4b4f2d..498d1467 100755 --- a/engine/menu/start_menu.asm +++ b/engine/menu/start_menu.asm @@ -1,7 +1,5 @@ DisplayStartMenu:: - ld a, BANK(StartMenu_Pokedex) - ld [H_LOADEDROMBANK], a - ld [MBC1RomBank], a + switchbank StartMenu_Pokedex ; also bank for other functions ld a, [wWalkBikeSurfState] ; walking/biking/surfing ld [wWalkBikeSurfStateCopy], a ld a, SFX_START_MENU @@ -9,6 +7,7 @@ DisplayStartMenu:: RedisplayStartMenu:: callba DrawStartMenu +RedisplayStartMenu_DoNotDrawStartMenu: callba PrintSafariZoneSteps ; print Safari Zone info, if in Safari Zone call UpdateSprites .loop diff --git a/engine/menu/start_sub_menus.asm b/engine/menu/start_sub_menus.asm index 947837e3..abc8f000 100755 --- a/engine/menu/start_sub_menus.asm +++ b/engine/menu/start_sub_menus.asm @@ -144,11 +144,14 @@ StartMenu_Pokemon: call ChooseFlyDestination ld a, [wd732] bit 3, a ; did the player decide to fly? - jp nz, .goBackToMap + jr nz, .asm_5d4c call LoadFontTilePatterns ld hl, wd72e set 1, [hl] jp StartMenu_Pokemon +.asm_5d4c + call Func_1510 + jp .goBackToMap .cut bit 1, a ; does the player have the Cascade Badge? jp z, .newBadgeRequired @@ -165,15 +168,28 @@ StartMenu_Pokemon: bit 1, [hl] res 1, [hl] jp z, .loop - ld a, SURFBOARD + ld a, [wcf91] + cp PIKACHU ; is this surfing pikachu? + jr z, .surfingPikachu + ld a, $1 + jr .continue +.surfingPikachu + ld a, $2 +.continue + ld [wd473], a + ld a,SURFBOARD ld [wcf91], a ld [wPseudoItemID], a call UseItem ld a, [wActionResultOrTookBattleTurn] and a - jp z, .loop + jr z, .reloadNormalSprite call GBPalWhiteOutWithDelay3 jp .goBackToMap +.reloadNormalSprite + xor a + ld [wd473], a + jp .loop .strength bit 3, a ; does the player have the Rainbow Badge? jp z, .newBadgeRequired @@ -217,6 +233,7 @@ StartMenu_Pokemon: ld hl, wd732 set 3, [hl] set 6, [hl] + call Func_1510 ld hl, wd72e set 1, [hl] res 4, [hl] @@ -307,11 +324,10 @@ StartMenu_Item: call PrintText jr .exitMenu .notInCableClubRoom - ld bc, wNumBagItems ld hl, wListPointer - ld a, c - ld [hli], a - ld [hl], b ; store item bag pointer in wListPointer (for DisplayListMenuID) + ld [hl], wNumBagItems & $ff + inc hl + ld [hl], wNumBagItems / $100 ; store item bag pointer in wListPointer (for DisplayListMenuID) xor a ld [wPrintItemPrices], a ld a, ITEMLISTMENU @@ -515,10 +531,11 @@ StartMenu_TrainerInfo: call LoadScreenTilesFromBuffer2 ; restore saved screen call RunDefaultPaletteCommand call ReloadMapData + callba DrawStartMenu ; XXX what difference does this make? call LoadGBPal pop af ld [hTilesetType], a - jp RedisplayStartMenu + jp RedisplayStartMenu_DoNotDrawStartMenu ; loads tile patterns and draws everything except for gym leader faces / badges DrawTrainerInfo: @@ -552,7 +569,7 @@ DrawTrainerInfo: ld de, vChars2 + $200 ld bc, $0400 ld a, $03 - call FarCopyData2 + call FarCopyData ld hl, TextBoxGraphics ld de, $00d0 add hl, de ; hl = colon tile pattern @@ -560,7 +577,7 @@ DrawTrainerInfo: ld bc, $0010 ld a, $04 push bc - call FarCopyData2 + call FarCopyData pop bc ld hl, TrainerInfoTextBoxTileGraphics + $80 ; background tile pattern ld de, vChars1 + $570 @@ -612,7 +629,7 @@ DrawTrainerInfo: TrainerInfo_FarCopyData: ld a, BANK(TrainerInfoTextBoxTileGraphics) - jp FarCopyData2 + jp FarCopyData TrainerInfo_NameMoneyTimeText: db "NAME/" diff --git a/engine/menu/status_screen.asm b/engine/menu/status_screen.asm index ef94f13c..1e2ba889 100755 --- a/engine/menu/status_screen.asm +++ b/engine/menu/status_screen.asm @@ -40,7 +40,7 @@ DrawHP_: push hl call DrawHPBar pop hl - ld a, [hFlags_0xFFF6] + ld a, [hFlags_0xFFFA] bit 0, a jr z, .printFractionBelowBar ld bc, $9 ; right of bar @@ -170,8 +170,25 @@ StatusScreen: call GBPalNormal coord hl, 1, 0 call LoadFlippedFrontSpriteByMonIndex ; draw Pokémon picture + ld a, [wMonDataLocation] + cp ENEMY_PARTY_DATA + jr z, .playRegularCry + cp BOX_DATA + jr z, .checkBoxData + callab IsThisPartymonStarterPikachu_Party + jr nc, .playRegularCry + jr .playPikachuSoundClip +.checkBoxData + callab IsThisPartymonStarterPikachu_Box + jr nc, .playRegularCry +.playPikachuSoundClip + ld e, 16 + callab PlayPikachuSoundClip + jr .continue +.playRegularCry ld a, [wcf91] call PlayCry ; play Pokémon cry +.continue call WaitForTextScrollButtonPress ; wait for button pop af ld [hTilesetType], a @@ -250,16 +267,14 @@ PrintStatsBox: and a ; a is 0 from the status screen jr nz, .DifferentBox coord hl, 0, 8 - ld b, 8 - ld c, 8 + lb bc, 8, 8 call TextBoxBorder ; Draws the box coord hl, 1, 9 ; Start printing stats from here ld bc, $0019 ; Number offset jr .PrintStats .DifferentBox coord hl, 9, 2 - ld b, 8 - ld c, 9 + lb bc, 8, 9 call TextBoxBorder coord hl, 11, 3 ld bc, $0018 @@ -314,8 +329,7 @@ StatusScreen2: coord hl, 19, 3 ld [hl], $78 coord hl, 0, 8 - ld b, 8 - ld c, 18 + lb bc, 8, 18 call TextBoxBorder ; Draw move container coord hl, 2, 9 ld de, wMovesString diff --git a/engine/menu/text_box.asm b/engine/menu/text_box.asm index b9a36652..a109bff2 100644 --- a/engine/menu/text_box.asm +++ b/engine/menu/text_box.asm @@ -273,8 +273,7 @@ DisplayMoneyBox: ld [wTextBoxID], a call DisplayTextBoxID coord hl, 13, 1 - ld b, 1 - ld c, 6 + lb bc, 1, 6 call ClearScreenArea coord hl, 12, 1 ld de, wPlayerMoney @@ -416,36 +415,10 @@ DisplayTwoOptionMenu: pop hl add hl, bc call PlaceString - ld hl, wd730 - res 6, [hl] ; turn on the printing delay - ld a, [wTwoOptionMenuID] - cp NO_YES_MENU - jr nz, .notNoYesMenu -; No/Yes menu -; this menu type ignores the B button -; it only seems to be used when confirming the deletion of a save file - xor a - ld [wTwoOptionMenuID], a - ld a, [wFlags_0xcd60] - push af - push hl - ld hl, wFlags_0xcd60 - bit 5, [hl] - set 5, [hl] ; don't play sound when A or B is pressed in menu - pop hl -.noYesMenuInputLoop - call HandleMenuInput - bit 1, a ; A button pressed? - jr nz, .noYesMenuInputLoop ; try again if A was not pressed - pop af - pop hl - ld [wFlags_0xcd60], a - ld a, SFX_PRESS_AB - call PlaySound - jr .pressedAButton -.notNoYesMenu xor a ld [wTwoOptionMenuID], a + ld hl, wd730 + res 6, [hl] ; turn on the printing delay call HandleMenuInput pop hl bit 1, a ; A button pressed? @@ -577,8 +550,7 @@ DisplayFieldMoveMonMenu: ; no field moves coord hl, 11, 11 - ld b, 5 - ld c, 7 + lb bc, 5, 7 call TextBoxBorder call UpdateSprites ld a, 12 diff --git a/engine/menu/vending_machine.asm b/engine/menu/vending_machine.asm index aab4adf4..37d9b9e7 100755 --- a/engine/menu/vending_machine.asm +++ b/engine/menu/vending_machine.asm @@ -18,8 +18,7 @@ VendingMachineMenu: ld hl, wd730 set 6, [hl] coord hl, 0, 3 - ld b, 8 - ld c, 12 + lb bc, 8, 12 call TextBoxBorder call UpdateSprites coord hl, 2, 5 diff --git a/engine/mon_party_sprites.asm b/engine/mon_party_sprites.asm index 864ac136..6f17f876 100755 --- a/engine/mon_party_sprites.asm +++ b/engine/mon_party_sprites.asm @@ -91,7 +91,7 @@ PartyMonSpeeds: LoadMonPartySpriteGfx: ; Load mon party sprite tile patterns into VRAM during V-blank. ld hl, MonPartySpritePointers - ld a, $1c + ld a, $1e LoadAnimSpriteGfx: ; Load animated sprite tile patterns into VRAM during V-blank. hl is the address @@ -130,7 +130,7 @@ LoadMonPartySpriteGfxWithLCDDisabled: ; LCD. call DisableLCD ld hl, MonPartySpritePointers - ld a, $1c + ld a, $1e ld bc, $0 .loop push af @@ -151,7 +151,7 @@ LoadMonPartySpriteGfxWithLCDDisabled: inc hl ld d, [hl] pop hl - call FarCopyData2 + call FarCopyData pop hl pop bc ld a, $6 @@ -228,6 +228,11 @@ MonPartySpritePointers: db BANK(MonPartySprites) dw vSprites + $260 + dw PikachuSprite + db $40 / $10 ; $40 bytes + db BANK(PikachuSprite) + dw vSprites + $280 + dw MonPartySprites + $100 db $40 / $10 ; $40 bytes db BANK(MonPartySprites) @@ -298,6 +303,11 @@ MonPartySpritePointers: db BANK(MonPartySprites) dw vSprites + $660 + dw PikachuSprite + $C0 + db $40 / $10 ; $40 bytes + db BANK(PikachuSprite) + dw vSprites + $680 + dw MonPartySprites + $140 db $40 / $10 ; $40 bytes db BANK(MonPartySprites) @@ -309,6 +319,8 @@ WriteMonPartySpriteOAMByPartyIndex: push de push bc ld a, [hPartyMonIndex] + cp $ff + jr z, .asm_7191f ld hl, wPartySpecies ld e, a ld d, 0 @@ -322,6 +334,16 @@ WriteMonPartySpriteOAMByPartyIndex: pop hl ret +.asm_7191f + ld hl, wOAMBuffer + ld de, wMonPartySpritesSavedOAM + ld bc, $60 + call CopyData + pop bc + pop de + pop hl + ret + WriteMonPartySpriteOAMBySpecies: ; Write OAM blocks for the party sprite of the species in ; [wMonPartySpriteSpecies]. @@ -343,7 +365,7 @@ UnusedPartyMonSpriteFunction: ld hl, vSprites call .LoadTilePatterns pop af - add $54 + add $5A ld hl, vSprites + $40 call .LoadTilePatterns xor a diff --git a/engine/multiply_divide.asm b/engine/multiply_divide.asm index 52e86b36..d664c9d4 100755 --- a/engine/multiply_divide.asm +++ b/engine/multiply_divide.asm @@ -7,11 +7,12 @@ _Multiply: ld [H_MULTIPLYBUFFER+1], a ld [H_MULTIPLYBUFFER+2], a ld [H_MULTIPLYBUFFER+3], a -.loop +.multiplyLoop ld a, [H_MULTIPLIER] srl a - ld [H_MULTIPLIER], a ; (aliases: H_DIVISOR, H_MULTIPLIER, H_POWEROFTEN) - jr nc, .smallMultiplier + ld [H_MULTIPLIER], a + jr nc, .smallMultiplier ; less than $80 +; code to possibly multiply the multiplicand by 2 and divide the multiplier by 2? ld a, [H_MULTIPLYBUFFER+3] ld c, a ld a, [H_MULTIPLICAND+2] @@ -24,12 +25,12 @@ _Multiply: ld [H_MULTIPLYBUFFER+2], a ld a, [H_MULTIPLYBUFFER+1] ld c, a - ld a, [H_MULTIPLICAND] ; (aliases: H_MULTIPLICAND) + ld a, [H_MULTIPLICAND] adc c ld [H_MULTIPLYBUFFER+1], a ld a, [H_MULTIPLYBUFFER] ld c, a - ld a, [H_PRODUCT] ; (aliases: H_PRODUCT, H_PASTLEADINGZEROES, H_QUOTIENT) + ld a, [H_PRODUCT] adc c ld [H_MULTIPLYBUFFER], a .smallMultiplier @@ -47,7 +48,7 @@ _Multiply: ld a, [H_PRODUCT] rl a ld [H_PRODUCT], a - jr .loop + jr .multiplyLoop .done ld a, [H_MULTIPLYBUFFER+3] ld [H_PRODUCT+3], a @@ -68,28 +69,28 @@ _Divide: ld [H_DIVIDEBUFFER+4], a ld a, $9 ld e, a -.asm_37db3 +.asm_f6680 ld a, [H_DIVIDEBUFFER] ld c, a - ld a, [H_DIVIDEND+1] ; (aliases: H_MULTIPLICAND) + ld a, [H_DIVIDEND+1] sub c ld d, a - ld a, [H_DIVISOR] ; (aliases: H_DIVISOR, H_MULTIPLIER, H_POWEROFTEN) + ld a, [H_DIVISOR] ld c, a - ld a, [H_DIVIDEND] ; (aliases: H_PRODUCT, H_PASTLEADINGZEROES, H_QUOTIENT) + ld a, [H_DIVIDEND] sbc c - jr c, .asm_37dce - ld [H_DIVIDEND], a ; (aliases: H_PRODUCT, H_PASTLEADINGZEROES, H_QUOTIENT) + jr c, .asm_f669b + ld [H_DIVIDEND], a ld a, d - ld [H_DIVIDEND+1], a ; (aliases: H_MULTIPLICAND) + ld [H_DIVIDEND+1], a ld a, [H_DIVIDEBUFFER+4] inc a ld [H_DIVIDEBUFFER+4], a - jr .asm_37db3 -.asm_37dce + jr .asm_f6680 +.asm_f669b ld a, b cp $1 - jr z, .asm_37e18 + jr z, .done ld a, [H_DIVIDEBUFFER+4] sla a ld [H_DIVIDEBUFFER+4], a @@ -103,41 +104,41 @@ _Divide: rl a ld [H_DIVIDEBUFFER+1], a dec e - jr nz, .asm_37e04 + jr nz, .asm_f66d1 ld a, $8 ld e, a ld a, [H_DIVIDEBUFFER] - ld [H_DIVISOR], a ; (aliases: H_DIVISOR, H_MULTIPLIER, H_POWEROFTEN) + ld [H_DIVISOR], a xor a ld [H_DIVIDEBUFFER], a - ld a, [H_DIVIDEND+1] ; (aliases: H_MULTIPLICAND) - ld [H_DIVIDEND], a ; (aliases: H_PRODUCT, H_PASTLEADINGZEROES, H_QUOTIENT) + ld a, [H_DIVIDEND+1] + ld [H_DIVIDEND], a ld a, [H_DIVIDEND+2] - ld [H_DIVIDEND+1], a ; (aliases: H_MULTIPLICAND) + ld [H_DIVIDEND+1], a ld a, [H_DIVIDEND+3] ld [H_DIVIDEND+2], a -.asm_37e04 +.asm_f66d1 ld a, e cp $1 - jr nz, .asm_37e0a + jr nz, .asm_f66d7 dec b -.asm_37e0a - ld a, [H_DIVISOR] ; (aliases: H_DIVISOR, H_MULTIPLIER, H_POWEROFTEN) +.asm_f66d7 + ld a, [H_DIVISOR] srl a - ld [H_DIVISOR], a ; (aliases: H_DIVISOR, H_MULTIPLIER, H_POWEROFTEN) + ld [H_DIVISOR], a ld a, [H_DIVIDEBUFFER] rr a ld [H_DIVIDEBUFFER], a - jr .asm_37db3 -.asm_37e18 - ld a, [H_DIVIDEND+1] ; (aliases: H_MULTIPLICAND) - ld [H_REMAINDER], a ; (aliases: H_DIVISOR, H_MULTIPLIER, H_POWEROFTEN) + jr .asm_f6680 +.done + ld a, [H_DIVIDEND+1] + ld [H_REMAINDER], a ld a, [H_DIVIDEBUFFER+4] ld [H_QUOTIENT+3], a ld a, [H_DIVIDEBUFFER+3] ld [H_QUOTIENT+2], a ld a, [H_DIVIDEBUFFER+2] - ld [H_QUOTIENT+1], a ; (aliases: H_MULTIPLICAND) + ld [H_QUOTIENT+1], a ld a, [H_DIVIDEBUFFER+1] - ld [H_DIVIDEND], a ; (aliases: H_PRODUCT, H_PASTLEADINGZEROES, H_QUOTIENT) + ld [H_QUOTIENT], a ret diff --git a/engine/oak_speech.asm b/engine/oak_speech.asm index b1acfb65..8a537579 100755 --- a/engine/oak_speech.asm +++ b/engine/oak_speech.asm @@ -5,6 +5,8 @@ SetDefaultNames: push af ld a, [wd732] push af + ld a, [wPrinterSettings] + push af ld hl, wPlayerName ld bc, wBoxDataEnd - wPlayerName xor a @@ -13,6 +15,12 @@ SetDefaultNames: ld bc, $200 xor a call FillMemory + xor a + ld [wSurfingMinigameHiScore], a + ld [wSurfingMinigameHiScore + 1], a + ld [wSurfingMinigameHiScore + 2], a + pop af + ld [wPrinterSettings], a pop af ld [wd732], a pop af @@ -29,11 +37,11 @@ SetDefaultNames: ld hl, SonyText ld de, wRivalName ld bc, NAME_LENGTH - jp CopyData + call CopyData ; rip optimizations + ret OakSpeech: - ld a, $FF - call PlaySound ; stop music + call StopAllMusic ; stop music ld a, BANK(Music_Routes2) ld c, a ld a, MUSIC_ROUTES2 @@ -64,7 +72,7 @@ OakSpeech: call PrintText call GBFadeOutToWhite call ClearScreen - ld a, NIDORINO + ld a, PIKACHU ld [wd0b5], a ld [wcf91], a call GetMonHeader @@ -109,13 +117,13 @@ OakSpeech: ld a, SFX_SHRINK call PlaySound pop af - ld [H_LOADEDROMBANK], a - ld [MBC1RomBank], a + call BankswitchCommon ld c, 4 call DelayFrames - ld de, RedSprite ld hl, vSprites - lb bc, BANK(RedSprite), $0C + ld de, RedSprite + ld b, BANK(RedSprite) + ld c, $0C call CopyVideoData ld de, ShrinkPic1 lb bc, BANK(ShrinkPic1), $00 @@ -133,17 +141,13 @@ OakSpeech: ld [wAudioSavedROMBank], a ld a, 10 ld [wAudioFadeOutControl], a - ld a, $FF - ld [wNewSoundID], a - call PlaySound ; stop music + call StopAllMusic ; stop music pop af - ld [H_LOADEDROMBANK], a - ld [MBC1RomBank], a + call BankswitchCommon ld c, 20 call DelayFrames coord hl, 6, 5 - ld b, 7 - ld c, 7 + lb bc, 7, 7 call ClearScreenArea call LoadTextBoxTilePatterns ld a, 1 @@ -151,7 +155,9 @@ OakSpeech: ld c, 50 call DelayFrames call GBFadeOutToWhite - jp ClearScreen + call ClearScreen ; rip more tail-end optimizations + ret + OakSpeechText1: TX_FAR _OakSpeechText1 db "@" @@ -176,6 +182,7 @@ FadeInIntroPic: .next ld a, [hli] ld [rBGP], a + call UpdateGBCPal_BGP ld c, 10 call DelayFrames dec b @@ -197,6 +204,7 @@ MovePicLeft: ld a, %11100100 ld [rBGP], a + call UpdateGBCPal_BGP .next call DelayFrame ld a, [rWX] @@ -215,10 +223,13 @@ IntroDisplayPicCenteredOrUpperRight: push bc ld a, b call UncompressSpriteFromDE + ld a, $0 + call SwitchSRAMBankAndLatchClockData ld hl, sSpriteBuffer1 ld de, sSpriteBuffer0 ld bc, $310 call CopyData + call PrepareRTCDataAndDisableSRAM ld de, vFrontPic call InterlaceMergeSpriteBuffers pop bc diff --git a/engine/oak_speech2.asm b/engine/oak_speech2.asm index 1258c59b..80f1bafc 100755 --- a/engine/oak_speech2.asm +++ b/engine/oak_speech2.asm @@ -108,6 +108,7 @@ OakSpeechSlidePicCommon: .loop xor a ld [H_AUTOBGTRANSFERENABLED], a + ld [H_AUTOBGTRANSFERPORTION], a ld a, [hSlideDirection] and a jr nz, .slideLeft @@ -129,8 +130,8 @@ OakSpeechSlidePicCommon: ; If sliding left, we need to zero the last tile in the pic (there is no need ; to take a corresponding action when sliding right because hl initially points ; to a 0 tile in that case). - xor a dec hl + xor a ld [hl], a .next3 ld a, 1 @@ -162,8 +163,7 @@ OakSpeechSlidePicCommon: DisplayIntroNameTextBox: push de coord hl, 0, 0 - ld b, $a - ld c, $9 + lb bc, 10, 9 call TextBoxBorder coord hl, 3, 0 ld de, .namestring @@ -187,10 +187,9 @@ DisplayIntroNameTextBox: .namestring db "NAME@" -IF DEF(_RED) DefaultNamesPlayer: db "NEW NAME" - next "RED" + next "YELLOW" next "ASH" next "JACK" db "@" @@ -201,23 +200,6 @@ DefaultNamesRival: next "GARY" next "JOHN" db "@" -ENDC - -IF DEF(_BLUE) -DefaultNamesPlayer: - db "NEW NAME" - next "BLUE" - next "GARY" - next "JOHN" - db "@" - -DefaultNamesRival: - db "NEW NAME" - next "RED" - next "ASH" - next "JACK" - db "@" -ENDC GetDefaultName: ; a = name index @@ -243,30 +225,17 @@ GetDefaultName: ld bc, $14 jp CopyData -IF DEF(_RED) DefaultNamesPlayerList: db "NEW NAME@" - db "RED@" + db "YELLOW@" db "ASH@" db "JACK@" + DefaultNamesRivalList: db "NEW NAME@" db "BLUE@" db "GARY@" db "JOHN@" -ENDC -IF DEF(_BLUE) -DefaultNamesPlayerList: - db "NEW NAME@" - db "BLUE@" - db "GARY@" - db "JOHN@" -DefaultNamesRivalList: - db "NEW NAME@" - db "RED@" - db "ASH@" - db "JACK@" -ENDC TextTerminator_6b20: db "@" diff --git a/engine/overworld/advance_player_sprite.asm b/engine/overworld/advance_player_sprite.asm new file mode 100644 index 00000000..6b4a0cbb --- /dev/null +++ b/engine/overworld/advance_player_sprite.asm @@ -0,0 +1,241 @@ +_AdvancePlayerSprite:: + ld a,[wSpriteStateData1 + 3] ; delta Y + ld b,a + ld a,[wSpriteStateData1 + 5] ; delta X + ld c,a + ld hl,wWalkCounter ; walking animation counter + dec [hl] + jr nz,.afterUpdateMapCoords +; if it's the end of the animation, update the player's map coordinates + ld hl, wPikachuOverworldStateFlags + res 5, [hl] + ld a,[wYCoord] + add b + ld [wYCoord],a + ld a,[wXCoord] + add c + ld [wXCoord],a +.afterUpdateMapCoords + ld a,[wWalkCounter] ; walking animation counter + cp a,$07 + jp nz,.scrollBackgroundAndSprites +; if this is the first iteration of the animation + ld a,c + cp a,$01 + jr nz,.checkIfMovingWest +; moving east + ld a,[wMapViewVRAMPointer] + ld e,a + and $e0 + ld d,a + ld a,e + add $02 + and $1f + or d + ld [wMapViewVRAMPointer],a + jr .adjustXCoordWithinBlock +.checkIfMovingWest + cp a,$ff + jr nz,.checkIfMovingSouth +; moving west + ld a,[wMapViewVRAMPointer] + ld e,a + and a,$e0 + ld d,a + ld a,e + sub $02 + and $1f + or d + ld [wMapViewVRAMPointer],a + jr .adjustXCoordWithinBlock +.checkIfMovingSouth + ld a,b + cp a,$01 + jr nz,.checkIfMovingNorth +; moving south + ld a,[wMapViewVRAMPointer] + add $40 + ld [wMapViewVRAMPointer],a + jr nc,.adjustXCoordWithinBlock + ld a,[wMapViewVRAMPointer + 1] + inc a + and $03 + or $98 + ld [wMapViewVRAMPointer + 1],a + jr .adjustXCoordWithinBlock +.checkIfMovingNorth + cp a,$ff + jr nz,.adjustXCoordWithinBlock +; moving north + ld a,[wMapViewVRAMPointer] + sub $40 + ld [wMapViewVRAMPointer],a + jr nc,.adjustXCoordWithinBlock + ld a,[wMapViewVRAMPointer + 1] + dec a + and $03 + or $98 + ld [wMapViewVRAMPointer + 1],a +.adjustXCoordWithinBlock + ld a,c + and a + jr z,.pointlessJump ; mistake? +.pointlessJump + ld hl,wXBlockCoord + ld a,[hl] + add c + ld [hl],a + cp $02 + jr nz,.checkForMoveToWestBlock +; moved into the tile block to the east + xor a + ld [hl],a + ld hl,wXOffsetSinceLastSpecialWarp + inc [hl] + ld de,wCurrentTileBlockMapViewPointer + call MoveTileBlockMapPointerEast + jr .updateMapView +.checkForMoveToWestBlock + cp a,$ff + jr nz,.adjustYCoordWithinBlock +; moved into the tile block to the west + ld a,$1 + ld [hl],a + ld hl,wXOffsetSinceLastSpecialWarp + dec [hl] + ld de,wCurrentTileBlockMapViewPointer + call MoveTileBlockMapPointerWest + jr .updateMapView +.adjustYCoordWithinBlock + ld hl,wYBlockCoord + ld a,[hl] + add b + ld [hl],a + cp $2 + jr nz,.checkForMoveToNorthBlock +; moved into the tile block to the south + xor a + ld [hl],a + ld hl,wYOffsetSinceLastSpecialWarp + inc [hl] + ld de,wCurrentTileBlockMapViewPointer + ld a,[wCurMapWidth] + call MoveTileBlockMapPointerSouth + jr .updateMapView +.checkForMoveToNorthBlock + cp a,$ff + jr nz,.updateMapView +; moved into the tile block to the north + ld a,$1 + ld [hl],a + ld hl,wYOffsetSinceLastSpecialWarp + dec [hl] + ld de,wCurrentTileBlockMapViewPointer + ld a,[wCurMapWidth] + call MoveTileBlockMapPointerNorth +.updateMapView + call LoadCurrentMapView + ld a,[wSpriteStateData1 + 3] ; delta Y + cp $1 + jr nz,.checkIfMovingNorth2 +; if moving south + call ScheduleSouthRowRedraw + jr .scrollBackgroundAndSprites +.checkIfMovingNorth2 + cp $ff + jr nz,.checkIfMovingEast2 +; if moving north + call ScheduleNorthRowRedraw + jr .scrollBackgroundAndSprites +.checkIfMovingEast2 + ld a,[wSpriteStateData1 + 5] ; delta X + cp $1 + jr nz,.checkIfMovingWest2 +; if moving east + call ScheduleEastColumnRedraw + jr .scrollBackgroundAndSprites +.checkIfMovingWest2 + cp $ff + jr nz,.scrollBackgroundAndSprites +; if moving west + call ScheduleWestColumnRedraw +.scrollBackgroundAndSprites + ld a,[wSpriteStateData1 + 3] ; delta Y + add a + ld b,a + ld a,[wSpriteStateData1 + 5] ; delta X + add a + ld c,a +; shift all the sprites in the direction opposite of the player's motion +; so that the player appears to move relative to them + ld hl,wSpriteStateData1 + $14 + ld e,15 +.spriteShiftLoop + ld a,[hl] + sub b + ld [hli],a + inc l + ld a,[hl] + sub c + ld [hl],a + ld a,$0e + add l + ld l,a + dec e + jr nz,.spriteShiftLoop +.done + ld a,[hSCY] + add b + ld [hSCY],a ; update background scroll Y + ld a,[hSCX] + add c + ld [hSCX],a ; update background scroll X + ret + +MoveTileBlockMapPointerEast:: + ld a,[de] + add $1 + ld [de],a + ret nc + inc de + ld a,[de] + inc a + ld [de],a + ret + +MoveTileBlockMapPointerWest:: + ld a,[de] + sub $1 + ld [de],a + ret nc + inc de + ld a,[de] + dec a + ld [de],a + ret + +MoveTileBlockMapPointerSouth:: + add $6 + ld b,a + ld a,[de] + add b + ld [de],a + ret nc + inc de + ld a,[de] + inc a + ld [de],a + ret + +MoveTileBlockMapPointerNorth:: + add $6 + ld b,a + ld a,[de] + sub b + ld [de],a + ret nc + inc de + ld a,[de] + dec a + ld [de],a + ret diff --git a/engine/overworld/cable_club_npc.asm b/engine/overworld/cable_club_npc.asm index 08067412..12ce64a4 100755 --- a/engine/overworld/cable_club_npc.asm +++ b/engine/overworld/cable_club_npc.asm @@ -1,9 +1,12 @@ CableClubNPC: ld hl, CableClubNPCWelcomeText call PrintText + call CheckPikachuFollowingPlayer + jr nz, .asm_7048 CheckEvent EVENT_GOT_POKEDEX jp nz, .receivedPokedex ; if the player hasn't received the pokedex +.asm_7048 ld c, 60 call DelayFrames ld hl, CableClubNPCMakingPreparationsText @@ -107,7 +110,61 @@ CableClubNPC: xor a ld [hld], a ld [hl], a - jpab LinkMenu + ld a, [wLetterPrintingDelayFlags] + push af + callab LinkMenu + pop af + ld [wLetterPrintingDelayFlags], a + ret + +; seems to be similar of Serial_SyncAndExchangeNybble +Serial_SyncAndExchangeNybbleDouble: + ld a, $ff + ld [wSerialExchangeNybbleReceiveData], a +.loop + call Serial_ExchangeNybble + call DelayFrame + push hl + ld hl, wUnknownSerialCounter + 1 + dec [hl] + jr nz, .next + dec hl + dec [hl] + jr nz, .next + pop hl + jr .setUnknownSerialCounterToFFFF +.next + pop hl + ld a, [wSerialExchangeNybbleReceiveData] + inc a + jr z, .loop + call DelayFrame + ld a, $ff + ld [wSerialExchangeNybbleReceiveData], a + call Serial_ExchangeNybble + ld a, [wSerialExchangeNybbleReceiveData] + inc a + jr z, .loop + ld b, 10 +.syncLoop1 + call DelayFrame + call Serial_ExchangeNybble + dec b + jr nz, .syncLoop1 + ld b, 10 +.syncLoop2 + call DelayFrame + call Serial_SendZeroByte + dec b + jr nz, .syncLoop2 + ld a, [wSerialExchangeNybbleReceiveData] + ld [wSerialSyncAndExchangeNybbleReceiveData], a + ret +.setUnknownSerialCounterToFFFF + ld a, $ff + ld [wUnknownSerialCounter], a + ld [wUnknownSerialCounter + 1], a + ret CableClubNPCAreaReservedFor2FriendsLinkedByCableText: TX_FAR _CableClubNPCAreaReservedFor2FriendsLinkedByCableText diff --git a/engine/overworld/card_key.asm b/engine/overworld/card_key.asm index 35495c82..a4452b4a 100755 --- a/engine/overworld/card_key.asm +++ b/engine/overworld/card_key.asm @@ -8,7 +8,8 @@ PrintCardKeyText: ret z cp b jr nz, .silphCoMapListLoop - predef GetTileAndCoordsInFrontOfPlayer +; does not check for tile in front of player. This might be buggy + ;predef GetTileAndCoordsInFrontOfPlayer ld a, [wTileInFrontOfPlayer] cp $18 jr z, .cardKeyDoorInFrontOfPlayer @@ -25,12 +26,12 @@ PrintCardKeyText: ld b, CARD_KEY call IsItemInBag jr z, .noCardKey - call GetCoordsInFrontOfPlayer - push de + xor a + ld [wPlayerMovingDirection], a tx_pre_id CardKeySuccessText ld [hSpriteIndexOrTextID], a call PrintPredefTextID - pop de + call GetCoordsInFrontOfPlayer srl d ld a, d ld b, a @@ -88,7 +89,7 @@ GetCoordsInFrontOfPlayer: ld d, a ld a, [wXCoord] ld e, a - ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction + ld a, [wSpritePlayerStateData1FacingDirection] ; player's sprite facing direction and a jr nz, .notFacingDown ; facing down diff --git a/engine/overworld/cut.asm b/engine/overworld/cut.asm index f6ae6468..bc7d092d 100755 --- a/engine/overworld/cut.asm +++ b/engine/overworld/cut.asm @@ -76,6 +76,7 @@ InitCutAnimOAM: ld [wWhichAnimationOffsets], a ld a, %11100100 ld [rOBP1], a + call UpdateGBCPal_OBP1 ld a, [wCutTile] cp $52 jr z, .grass @@ -123,8 +124,8 @@ WriteCutOrBoulderDustAnimationOAMBlock: jp WriteOAMBlock CutOrBoulderDustAnimationTilesAndAttributes: - db $FC,$10,$FD,$10 - db $FE,$10,$FF,$10 + db $FC,$14,$FD,$14 + db $FE,$14,$FF,$14 GetCutOrBoulderDustAnimationOffsets: ld hl, wSpriteStateData1 + 4 @@ -187,7 +188,7 @@ ReplaceTreeTileBlock: ld h, [hl] ld l, a add hl, bc - ld a, [wSpriteStateData1 + 9] ; player sprite's facing direction + ld a, [wSpritePlayerStateData1FacingDirection] ; player sprite's facing direction and a jr z, .down cp SPRITE_FACING_UP diff --git a/engine/overworld/cut2.asm b/engine/overworld/cut2.asm index f16fed66..37490f95 100755 --- a/engine/overworld/cut2.asm +++ b/engine/overworld/cut2.asm @@ -18,6 +18,7 @@ AnimCut: ld a, [rOBP1] xor $64 ld [rOBP1], a + call UpdateGBCPal_OBP1 call DelayFrame pop bc dec c @@ -68,6 +69,7 @@ AnimCutGrass_UpdateOAMEntries: ld a, [rOBP1] xor $64 ld [rOBP1], a + call UpdateGBCPal_OBP1 call DelayFrame pop bc dec c diff --git a/engine/overworld/doors.asm b/engine/overworld/doors.asm index c39e096d..8bde8600 100755 --- a/engine/overworld/doors.asm +++ b/engine/overworld/doors.asm @@ -39,6 +39,7 @@ DoorTileIDPointers: dbw LAB, LabDoorTileIDs dbw FACILITY, FacilityDoorTileIDs dbw PLATEAU, PlateauDoorTileIDs + dbw INTERIOR, InteriorDoorTileIDs db $ff OverworldDoorTileIDs: @@ -73,3 +74,6 @@ FacilityDoorTileIDs: PlateauDoorTileIDs: db $3b,$1b,$00 + +InteriorDoorTileIDs: + db $04,$15,$00 diff --git a/engine/overworld/dungeon_warps.asm b/engine/overworld/dungeon_warps.asm new file mode 100644 index 00000000..f47dfb01 --- /dev/null +++ b/engine/overworld/dungeon_warps.asm @@ -0,0 +1,15 @@ +IsPlayerOnDungeonWarp: + xor a + ld [wWhichDungeonWarp], a + ld a, [wd72d] + bit 4, a + ret nz + call ArePlayerCoordsInArray + ret nc + ld a, [wCoordIndex] + ld [wWhichDungeonWarp], a + ld hl, wd72d + set 4, [hl] + ld hl, wd732 + set 4, [hl] + ret diff --git a/engine/overworld/elevator.asm b/engine/overworld/elevator.asm index d68e4f81..47ec78f9 100755 --- a/engine/overworld/elevator.asm +++ b/engine/overworld/elevator.asm @@ -4,8 +4,7 @@ ShakeElevator: ld de, SCREEN_HEIGHT * $20 call ShakeElevatorRedrawRow call Delay3 - ld a, $ff - call PlaySound + call StopAllMusic ld a, [hSCY] ld d, a ld e, $1 @@ -27,8 +26,7 @@ ShakeElevator: jr nz, .shakeLoop ld a, d ld [hSCY], a - ld a, $ff - call PlaySound + call StopAllMusic ld c, BANK(SFX_Safari_Zone_PA) ld a, SFX_SAFARI_ZONE_PA call PlayMusic diff --git a/engine/overworld/emotion_bubbles.asm b/engine/overworld/emotion_bubbles.asm index ac4276bd..3b02fd55 100755 --- a/engine/overworld/emotion_bubbles.asm +++ b/engine/overworld/emotion_bubbles.asm @@ -1,13 +1,16 @@ EmotionBubble: ld a, [wWhichEmotionBubble] + and $f + swap a ld c, a ld b, 0 - ld hl, EmotionBubblesPointerTable + ld hl, EmotionBubbles + add hl, bc ; each emotion bubble is 16 bytes, so calculate the offset directly instead of with a pointer table add hl, bc add hl, bc - ld e, [hl] - inc hl - ld d, [hl] + add hl, bc + ld e, l + ld d, h ld hl, vChars1 + $780 lb bc, BANK(EmotionBubbles), $04 call CopyVideoData @@ -59,12 +62,9 @@ EmotionBubble: pop af ld [wUpdateSpritesEnabled], a call DelayFrame - jp UpdateSprites + call UpdateSprites + ret -EmotionBubblesPointerTable: - dw EmotionBubbles - dw EmotionBubbles + $40 - dw EmotionBubbles + $80 EmotionBubblesOAM: db $F8,$00,$F9,$00 diff --git a/engine/overworld/field_move_messages.asm b/engine/overworld/field_move_messages.asm index b1506742..1d111917 100644 --- a/engine/overworld/field_move_messages.asm +++ b/engine/overworld/field_move_messages.asm @@ -32,7 +32,7 @@ IsSurfingAllowed: ret nz CheckBothEventsSet EVENT_SEAFOAM4_BOULDER1_DOWN_HOLE, EVENT_SEAFOAM4_BOULDER2_DOWN_HOLE ret z - ld hl, CoordsData_cdf7 + ld hl, CoordsData_f5b64 call ArePlayerCoordsInArray ret nc ld hl, wd728 @@ -45,7 +45,7 @@ IsSurfingAllowed: ld hl, CyclingIsFunText jp PrintText -CoordsData_cdf7: +CoordsData_f5b64: db $0B,$07,$FF CurrentTooFastText: diff --git a/engine/overworld/healing_machine.asm b/engine/overworld/healing_machine.asm index 38a44cfb..e5ba004e 100755 --- a/engine/overworld/healing_machine.asm +++ b/engine/overworld/healing_machine.asm @@ -12,14 +12,13 @@ AnimateHealingMachine: push af ld a, $e0 ld [rOBP1], a + call UpdateGBCPal_OBP1 ld hl, wOAMBuffer + $84 ld de, PokeCenterOAMData call CopyHealingMachineOAM ld a, 4 ld [wAudioFadeOutControl], a - ld a, $ff - ld [wNewSoundID], a - call PlaySound + call StopAllMusic .waitLoop ld a, [wAudioFadeOutControl] and a ; is fade-out finished? @@ -35,12 +34,10 @@ AnimateHealingMachine: dec b jr nz, .partyLoop ld a, [wAudioROMBank] - cp BANK(Audio3_UpdateMusic) + cp BANK(AudioEngine3) ld [wAudioSavedROMBank], a jr nz, .next - ld a, $ff - ld [wNewSoundID], a - call PlaySound + call StopAllMusic ld a, BANK(Music_PkmnHealed) ld [wAudioROMBank], a .next @@ -57,6 +54,7 @@ AnimateHealingMachine: call DelayFrames pop af ld [rOBP1], a + call UpdateGBCPal_OBP1 pop hl pop af ld [hl], a @@ -66,13 +64,13 @@ PokeCenterFlashingMonitorAndHealBall: INCBIN "gfx/pokecenter_ball.2bpp" PokeCenterOAMData: - db $24,$34,$7C,$10 ; heal machine monitor - db $2B,$30,$7D,$10 ; pokeballs 1-6 - db $2B,$38,$7D,$30 - db $30,$30,$7D,$10 - db $30,$38,$7D,$30 - db $35,$30,$7D,$10 - db $35,$38,$7D,$30 + db $24,$34,$7C,$14 ; heal machine monitor + db $2B,$30,$7D,$14 ; pokeballs 1-6 + db $2B,$38,$7D,$34 + db $30,$30,$7D,$14 + db $30,$38,$7D,$34 + db $35,$30,$7D,$14 + db $35,$38,$7D,$34 ; d = value to xor with palette FlashSprite8Times: @@ -81,6 +79,7 @@ FlashSprite8Times: ld a, [rOBP1] xor d ld [rOBP1], a + call UpdateGBCPal_OBP1 ld c, 10 call DelayFrames dec b diff --git a/engine/overworld/hidden_items.asm b/engine/overworld/hidden_items.asm index 32783f83..b64411c7 100755 --- a/engine/overworld/hidden_items.asm +++ b/engine/overworld/hidden_items.asm @@ -9,7 +9,7 @@ HiddenItems: predef FlagActionPredef ld a, c and a - ret nz + jr nz, .itemAlreadyFound call EnableAutoTextBoxDrawing ld a, 1 ld [wDoNotWaitForButtonPressAfterDisplayingText], a @@ -18,6 +18,11 @@ HiddenItems: call GetItemName tx_pre_jump FoundHiddenItemText +.itemAlreadyFound + ld a, $ff + ld [hItemAlreadyFound], a + ret + INCLUDE "data/hidden_item_coords.asm" FoundHiddenItemText: @@ -54,7 +59,7 @@ HiddenCoins: predef GetQuantityOfItemInBag ld a, b and a - ret z + jr z, .doNotPickUpCoins ld hl, HiddenCoinCoords call FindHiddenItemOrCoinsIndex ld [wHiddenItemOrCoinsIndex], a @@ -65,7 +70,7 @@ HiddenCoins: predef FlagActionPredef ld a, c and a - ret nz + jr nz, .doNotPickUpCoins xor a ld [hUnusedCoinsByte], a ld [hCoins], a @@ -79,6 +84,12 @@ HiddenCoins: cp 40 jr z, .bcd20 ; should be bcd40 jr .bcd100 + +.doNotPickUpCoins + ld a, $ff + ld [hItemAlreadyFound], a + ret + .bcd10 ld a, $10 ld [hCoins + 1], a diff --git a/engine/overworld/hidden_objects.asm b/engine/overworld/hidden_objects.asm index dcdf8537..66815b60 100755 --- a/engine/overworld/hidden_objects.asm +++ b/engine/overworld/hidden_objects.asm @@ -1,43 +1,17 @@ -IsPlayerOnDungeonWarp: - xor a - ld [wWhichDungeonWarp], a - ld a, [wd72d] - bit 4, a - ret nz - call ArePlayerCoordsInArray - ret nc - ld a, [wCoordIndex] - ld [wWhichDungeonWarp], a - ld hl, wd72d - set 4, [hl] - ld hl, wd732 - set 4, [hl] - ret - -; if a hidden object was found, stores $00 in [$ffee], else stores $ff +; if a hidden object was found, stores $00 in [hDidntFindAnyHiddenObject], else stores $ff CheckForHiddenObject: - ld hl, $ffeb + ld hl, hItemAlreadyFound xor a ld [hli], a ld [hli], a ld [hli], a ld [hl], a - ld de, $0 ld hl, HiddenObjectMaps -.hiddenMapLoop - ld a, [hli] - ld b, a - cp $ff - jr z, .noMatch + ld de, 3 ld a, [wCurMap] - cp b - jr z, .foundMatchingMap - inc de - inc de - jr .hiddenMapLoop -.foundMatchingMap - ld hl, HiddenObjectPointers - add hl, de + call IsInArray + jr nc, .noMatch + inc hl ld a, [hli] ld h, [hl] ld l, a @@ -81,13 +55,13 @@ CheckForHiddenObject: ret .noMatch ld a, $ff - ld [$ffee], a + ld [hDidntFindAnyHiddenObject], a ret ; checks if the coordinates in front of the player's sprite match Y in b and X in c ; [hCoordsInFrontOfPlayerMatch] = $00 if they match, $ff if they don't match CheckIfCoordsInFrontOfPlayerMatch: - ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction + ld a, [wSpritePlayerStateData1FacingDirection] ; player's sprite facing direction cp SPRITE_FACING_UP jr z, .facingUp cp SPRITE_FACING_LEFT diff --git a/engine/overworld/ledges.asm b/engine/overworld/ledges.asm index 342540b2..a44ddf8b 100755 --- a/engine/overworld/ledges.asm +++ b/engine/overworld/ledges.asm @@ -6,7 +6,7 @@ HandleLedges: and a ; OVERWORLD ret nz predef GetTileAndCoordsInFrontOfPlayer - ld a, [wSpriteStateData1 + 9] + ld a, [wSpritePlayerStateData1FacingDirection] ld b, a aCoord 8, 9 ld c, a @@ -71,10 +71,13 @@ LoadHoppingShadowOAM: ld de, LedgeHoppingShadow lb bc, BANK(LedgeHoppingShadow), (LedgeHoppingShadowEnd - LedgeHoppingShadow) / $8 call CopyVideoDataDouble - ld a, $9 - lb bc, $54, $48 ; b, c = y, x coordinates of shadow - ld de, LedgeHoppingShadowOAM - call WriteOAMBlock + ld hl, LedgeHoppingShadowOAM + ld de, wOAMBuffer + 36 * 4 + ld bc, LedgeHoppingShadowOAMEnd - LedgeHoppingShadowOAM + call CopyData + ld a, $a0 + ld [wOAMBuffer + 38 * 4], a + ld [wOAMBuffer + 39 * 4], a ret LedgeHoppingShadow: @@ -82,5 +85,6 @@ LedgeHoppingShadow: LedgeHoppingShadowEnd: LedgeHoppingShadowOAM: - db $FF,$10,$FF,$20 - db $FF,$40,$FF,$60 + db $58,$48,$FF,$00 + db $58,$50,$FF,$20 +LedgeHoppingShadowOAMEnd: diff --git a/engine/overworld/map_sprite_functions1.asm b/engine/overworld/map_sprite_functions1.asm index d1a411fa..2ad923fb 100644 --- a/engine/overworld/map_sprite_functions1.asm +++ b/engine/overworld/map_sprite_functions1.asm @@ -1,7 +1,7 @@ _UpdateSprites: - ld h, $c1 + ld h, wSpriteStateData1 / $100 inc h - ld a, $e ; wSpriteStateData2 + $0e + ld a, $e ; (wSpriteStateData2 + $0e) & $ff .spriteLoop ld l, a sub $e @@ -24,9 +24,12 @@ _UpdateSprites: jr nz, .spriteLoop ret .updateCurrentSprite - cp $1 - jp nz, UpdateNonPlayerSprite - jp UpdatePlayerSprite + ld a, [H_CURRENTSPRITEOFFSET] + and a + jp z, UpdatePlayerSprite + cp $f0 ; pikachu + jp z, SpawnPikachu + ld a, [hl] UpdateNonPlayerSprite: dec a @@ -51,11 +54,10 @@ UpdateNonPlayerSprite: ; The reason that 4 is added below to the coordinate is to make it align with a ; multiple of $10 to make comparisons easier. DetectCollisionBetweenSprites: - nop + ; nop ld h, wSpriteStateData1 / $100 ld a, [H_CURRENTSPRITEOFFSET] - add wSpriteStateData1 % $100 ld l, a ld a, [hl] ; a = [$c1i0] (picture) (0 if slot is unused) @@ -270,6 +272,17 @@ DetectCollisionBetweenSprites: jr nc, .next ; go to next sprite if distance is still positive after both adjustments .collision + ld a, l + and $f0 ; collision with pikachu? + jr nz, .asm_4cd9 + xor a + ld [wd434], a + ld a, [$ff8f] + cp $f + jr nz, .asm_4cd9 + call Func_4d0a + jr .asm_4cef +.asm_4cd9 ld a, [$ff91] ; a = 7 or 9 depending on sprite i's delta X ld b, a ld a, [$ff90] ; a = 7 or 9 depending on sprite i's delta Y @@ -294,6 +307,7 @@ DetectCollisionBetweenSprites: ; set bit in [$c1ie] or [$c1if] to indicate which sprite the collision occurred with inc l inc l +.asm_4cef ld a, [$ff8f] ; a = loop counter ld de, SpriteCollisionBitTable add a @@ -322,6 +336,26 @@ DetectCollisionBetweenSprites: ; c = 0 if delta X/Y is 0 ; c = 7 if delta X/Y is 1 ; c = 9 if delta X/Y is -1 +Func_4d0a: + ld a, [$ff91] + ld b, a + ld a, [$ff90] + inc l + cp b + jr c, .asm_4d17 + ld b, %1100 + jr .asm_4d19 +.asm_4d17 + ld b, %11 +.asm_4d19 + ld a, c + and b + ld [wd434], a + ld a, c + inc l + inc l + ret + SetSpriteCollisionValues: and a ld b, 0 diff --git a/engine/overworld/map_sprites.asm b/engine/overworld/map_sprites.asm index 8a6057a0..3e2c3912 100755 --- a/engine/overworld/map_sprites.asm +++ b/engine/overworld/map_sprites.asm @@ -8,261 +8,23 @@ ; fields, respectively, within loops. The X is the loop index. ; If there is an inner loop, Y is the inner loop index, i.e. $C1Y* and $C2Y* ; denote fields of the sprite slots iterated over in the inner loop. -InitMapSprites: +_InitMapSprites: call InitOutsideMapSprites ret c ; return if the map is an outside map (already handled by above call) ; if the map is an inside map (i.e. mapID >= $25) - ld hl, wSpriteStateData1 - ld de, wSpriteStateData2 + $0d -; Loop to copy picture ID's from $C1X0 to $C2XD for LoadMapSpriteTilePatterns. -.copyPictureIDLoop - ld a, [hl] ; $C1X0 (picture ID) - ld [de], a ; $C2XD - ld a, $10 - add e - ld e, a - ld a, $10 - add l - ld l, a - jr nz, .copyPictureIDLoop - -; This is used for both inside and outside maps, since it is called by -; InitOutsideMapSprites. -; Loads tile pattern data for sprites into VRAM. -LoadMapSpriteTilePatterns: - ld a, [wNumSprites] - and a ; are there any sprites? - jr nz, .spritesExist - ret -.spritesExist - ld c, a ; c = [wNumSprites] - ld b, $10 ; number of sprite slots - ld hl, wSpriteStateData2 + $0d - xor a - ld [hFourTileSpriteCount], a -.copyPictureIDLoop ; loop to copy picture ID from $C2XD to $C2XE - ld a, [hli] ; $C2XD (sprite picture ID) - ld [hld], a ; $C2XE - ld a, l - add $10 - ld l, a - dec b - jr nz, .copyPictureIDLoop - ld hl, wSpriteStateData2 + $1e -.loadTilePatternLoop - ld de, wSpriteStateData2 + $1d -; Check if the current picture ID has already had its tile patterns loaded. -; This done by looping through the previous sprite slots and seeing if any of -; their picture ID's match that of the current sprite slot. -.checkIfAlreadyLoadedLoop - ld a, e - and $f0 - ld b, a ; b = offset of the wSpriteStateData2 sprite slot being checked against - ld a, l - and $f0 ; a = offset of current wSpriteStateData2 sprite slot - cp b ; done checking all previous sprite slots? - jr z, .notAlreadyLoaded - ld a, [de] ; picture ID of the wSpriteStateData2 sprite slot being checked against - cp [hl] ; do the picture ID's match? - jp z, .alreadyLoaded - ld a, e - add $10 - ld e, a - jr .checkIfAlreadyLoadedLoop -.notAlreadyLoaded - ld de, wSpriteStateData2 + $0e - ld b, $01 -; loop to find the highest tile pattern VRAM slot (among the first 10 slots) used by a previous sprite slot -; this is done in order to find the first free VRAM slot available -.findNextVRAMSlotLoop - ld a, e - add $10 - ld e, a - ld a, l - cp e ; reached current slot? - jr z, .foundNextVRAMSlot - ld a, [de] ; $C2YE (VRAM slot) - cp 11 ; is it one of the first 10 slots? - jr nc, .findNextVRAMSlotLoop - cp b ; compare the slot being checked to the current max - jr c, .findNextVRAMSlotLoop ; if the slot being checked is less than the current max -; if the slot being checked is greater than or equal to the current max - ld b, a ; store new max VRAM slot - jr .findNextVRAMSlotLoop -.foundNextVRAMSlot - inc b ; increment previous max value to get next VRAM tile pattern slot - ld a, b ; a = next VRAM tile pattern slot - push af - ld a, [hl] ; $C2XE (sprite picture ID) - ld b, a ; b = current sprite picture ID - cp SPRITE_BALL ; is it a 4-tile sprite? - jr c, .notFourTileSprite - pop af - ld a, [hFourTileSpriteCount] - add 11 - jr .storeVRAMSlot -.notFourTileSprite - pop af -.storeVRAMSlot - ld [hl], a ; store VRAM slot at $C2XE - ld [hVRAMSlot], a ; used to determine if it's 4-tile sprite later - ld a, b ; a = current sprite picture ID - dec a - add a - add a - push bc - push hl - ld hl, SpriteSheetPointerTable - jr nc, .noCarry - inc h -.noCarry - add l - ld l, a - jr nc, .noCarry2 - inc h -.noCarry2 - push hl - call ReadSpriteSheetData - push af - push de - push bc - ld hl, vNPCSprites ; VRAM base address - ld bc, $c0 ; number of bytes per VRAM slot - ld a, [hVRAMSlot] - cp 11 ; is it a 4-tile sprite? - jr nc, .fourTileSpriteVRAMAddr - ld d, a - dec d -; Equivalent to multiplying $C0 (number of bytes in 12 tiles) times the VRAM -; slot and adding the result to $8000 (the VRAM base address). -.calculateVRAMAddrLoop - add hl, bc - dec d - jr nz, .calculateVRAMAddrLoop - jr .loadStillTilePattern -.fourTileSpriteVRAMAddr - ld hl, vSprites + $7c0 ; address for second 4-tile sprite - ld a, [hFourTileSpriteCount] - and a - jr nz, .loadStillTilePattern -; if it's the first 4-tile sprite - ld hl, vSprites + $780 ; address for first 4-tile sprite - inc a - ld [hFourTileSpriteCount], a -.loadStillTilePattern - pop bc - pop de - pop af - push hl - push hl - ld h, d - ld l, e - pop de - ld b, a - ld a, [wFontLoaded] - bit 0, a ; reloading upper half of tile patterns after displaying text? - jr nz, .skipFirstLoad ; if so, skip loading data into the lower half - ld a, b - ld b, 0 - call FarCopyData2 ; load tile pattern data for sprite when standing still -.skipFirstLoad - pop de - pop hl - ld a, [hVRAMSlot] - cp 11 ; is it a 4-tile sprite? - jr nc, .skipSecondLoad ; if so, there is no second block - push de - call ReadSpriteSheetData - push af - ld a, $c0 - add e - ld e, a - jr nc, .noCarry3 - inc d -.noCarry3 - ld a, [wFontLoaded] - bit 0, a ; reloading upper half of tile patterns after displaying text? - jr nz, .loadWhileLCDOn - pop af - pop hl - set 3, h ; add $800 to hl - push hl - ld h, d - ld l, e - pop de - call FarCopyData2 ; load tile pattern data for sprite when walking - jr .skipSecondLoad -; When reloading the upper half of tile patterns after displaying text, the LCD -; will be on, so CopyVideoData (which writes to VRAM only during V-blank) must -; be used instead of FarCopyData2. -.loadWhileLCDOn - pop af - pop hl - set 3, h ; add $800 to hl - ld b, a - swap c - call CopyVideoData ; load tile pattern data for sprite when walking -.skipSecondLoad - pop hl - pop bc - jr .nextSpriteSlot -.alreadyLoaded ; if the current picture ID has already had its tile patterns loaded - inc de - ld a, [de] ; a = VRAM slot for the current picture ID (from $C2YE) - ld [hl], a ; store VRAM slot in current wSpriteStateData2 sprite slot (at $C2XE) -.nextSpriteSlot - ld a, l - add $10 - ld l, a - dec c - jp nz, .loadTilePatternLoop - ld hl, wSpriteStateData2 + $0d - ld b, $10 -; the pictures ID's stored at $C2XD are no longer needed, so zero them -.zeroStoredPictureIDLoop - xor a - ld [hl], a ; $C2XD - ld a, $10 - add l - ld l, a - dec b - jr nz, .zeroStoredPictureIDLoop - ret - -; reads data from SpriteSheetPointerTable -; INPUT: -; hl = address of sprite sheet entry -; OUTPUT: -; de = pointer to sprite sheet -; bc = length in bytes -; a = ROM bank -ReadSpriteSheetData: - ld a, [hli] - ld e, a - ld a, [hli] - ld d, a - ld a, [hli] - ld c, a - xor a - ld b, a - ld a, [hli] + call LoadSpriteSetFromMapHeader + call LoadMapSpriteTilePatterns + call Func_14150 ret ; Loads sprite set for outside maps (cities and routes) and sets VRAM slots. ; sets carry if the map is a city or route, unsets carry if not InitOutsideMapSprites: ld a, [wCurMap] - cp REDS_HOUSE_1F ; is the map a city or a route (map ID less than $25)? + cp a, REDS_HOUSE_1F ; is the map a city or a route (map ID less than $25)? ret nc ; if not, return - ld hl, MapSpriteSets - add l - ld l, a - jr nc, .noCarry - inc h -.noCarry - ld a, [hl] ; a = spriteSetID - cp $f0 ; does the map have 2 sprite sets? - call nc, GetSplitMapSpriteSetID ; if so, choose the appropriate one + call GetSplitMapSpriteSetID +; if so, choose the appropriate one ld b, a ; b = spriteSetID ld a, [wFontLoaded] bit 0, a ; reloading upper half of tile patterns after displaying text? @@ -274,120 +36,285 @@ InitOutsideMapSprites: ld a, b ld [wSpriteSetID], a dec a - ld b, a - sla a ld c, a - sla a - sla a - add c - add b ; a = (spriteSetID - 1) * 11 - ld de, SpriteSets -; add a to de to get offset of sprite set - add e - ld e, a - jr nc, .noCarry2 - inc d -.noCarry2 - ld hl, wSpriteStateData2 + $0d - ld a, SPRITE_RED - ld [hl], a - ld bc, wSpriteSet -; Load the sprite set into RAM. -; This loop also fills $C2XD (sprite picture ID) where X is from $0 to $A -; with picture ID's. This is done so that LoadMapSpriteTilePatterns will -; load tile patterns for all sprite pictures in the sprite set. -.loadSpriteSetLoop - ld a, $10 - add l - ld l, a - ld a, [de] ; sprite picture ID from sprite set - ld [hl], a ; $C2XD (sprite picture ID) - ld [bc], a - inc de - inc bc - ld a, l - cp $bd ; reached 11th sprite slot? - jr nz, .loadSpriteSetLoop - ld b, 4 ; 4 remaining sprite slots -.zeroRemainingSlotsLoop ; loop to zero the picture ID's of the remaining sprite slots - ld a, $10 - add l - ld l, a - xor a - ld [hl], a ; $C2XD (sprite picture ID) - dec b - jr nz, .zeroRemainingSlotsLoop - ld a, [wNumSprites] - push af ; save number of sprites - ld a, 11 ; 11 sprites in sprite set - ld [wNumSprites], a + ld b, 0 + ld a, (wSpriteSetID - wSpriteSet) + ld hl, SpriteSets + call AddNTimes ; get sprite set offset + ld de, wSpriteSet + ld bc, (wSpriteSetID - wSpriteSet) + call CopyData ; copy it to wSpriteSet call LoadMapSpriteTilePatterns - pop af - ld [wNumSprites], a ; restore number of sprites - ld hl, wSpriteStateData2 + $1e - ld b, $0f -; The VRAM tile pattern slots that LoadMapSpriteTilePatterns set are in the -; order of the map's sprite set, not the order of the actual sprites loaded -; for the current map. So, they are not needed and are zeroed by this loop. -.zeroVRAMSlotsLoop - xor a - ld [hl], a ; $C2XE (VRAM slot) - ld a, $10 - add l - ld l, a - dec b - jr nz, .zeroVRAMSlotsLoop .skipLoadingSpriteSet - ld hl, wSpriteStateData1 + $10 + call Func_14150 + scf + ret + +LoadSpriteSetFromMapHeader: ; This loop stores the correct VRAM tile pattern slots according the sprite ; data from the map's header. Since the VRAM tile pattern slots are filled in ; the order of the sprite set, in order to find the VRAM tile pattern slot ; for a sprite slot, the picture ID for the sprite is looked up within the -; sprite set. The index of the picture ID within the sprite set plus one -; (since the Red sprite always has the first VRAM tile pattern slot) is the -; VRAM tile pattern slot. +; sprite set. The index of the picture ID within the sprite set plus two +; (since the Red sprite always has the first VRAM tile pattern slot and the +; Pikachu sprite reserves the second slot) is the VRAM tile pattern slot. + ld hl, wSpriteSet + ld bc, (wSpriteSetID - wSpriteSet) + xor a + call FillMemory + ld a, SPRITE_PIKACHU ; load Pikachu separately + ld [wSpriteSet], a + ld hl, wSprite01StateData1 + ld a, 14 .storeVRAMSlotsLoop - ld c, 0 + push af ld a, [hl] ; $C1X0 (picture ID) (zero if sprite slot is not used) and a ; is the sprite slot used? - jr z, .skipGettingPictureIndex ; if the sprite slot is not used - ld b, a ; b = picture ID + jr z, .continue ; if the sprite slot is not used + ld c, a + call CheckForFourTileSprite ; is this a four tile sprite? + jr nc, .isFourTileSprite +; loop through the space reserved for four tile picture IDs + ld de, wSpriteSet + 9 + ld b, 2 + call CheckIfPictureIDAlreadyLoaded + jr .continue + +.isFourTileSprite +; loop through the space reserved for regular picture IDs ld de, wSpriteSet -; Loop to find the index of the sprite's picture ID within the sprite set. -.getPictureIndexLoop - inc c + ld b, 9 + call CheckIfPictureIDAlreadyLoaded +.continue + ld de, wSprite02StateData1 - wSprite01StateData1 + add hl, de + pop af + dec a + jr nz, .storeVRAMSlotsLoop + ret + +CheckIfPictureIDAlreadyLoaded: +; Check if the current picture ID has already had its tile patterns loaded. +; This done by looping through the previous sprite slots and seeing if any of +; their picture ID's match that of the current sprite slot. +.loop ld a, [de] + and a ; is sprite set slot not taken up yet? + jr z, .spriteSlotNotTaken ; if so, load it as it signifies we've reached + ; the end of data for the last sprite set + + cp c ; is the tile pattern already loaded? + ret z ; don't redundantly load + dec b ; have we reached the end of the sprite set? + jr z, .spriteNotAlreadyLoaded ; if so, we're done here inc de - cp b ; does the picture ID match? - jr nz, .getPictureIndexLoop - inc c -.skipGettingPictureIndex - push hl - inc h - ld a, $0e - add l - ld l, a - ld a, c ; a = VRAM slot (zero if sprite slot is not used) - ld [hl], a ; $C2XE (VRAM slot) - pop hl - ld a, $10 - add l + jr .loop + +.spriteSlotNotTaken + ld a, c + ld [de], a + ret +.spriteNotAlreadyLoaded + scf + ret + +CheckForFourTileSprite: +; Checks for a sprite added in yellow +; Returns no carry if the sprite is Pikachu, as its sprite is handled separately +; Else, returns carry if the sprite uses 4 tiles + cp SPRITE_PIKACHU ; is this the Pikachu Sprite? + ret z ; return if yes + + cp SPRITE_BALL ; is this a four tile sprite? + jr nc, .notYellowSprite ; set carry if yes +; regular sprite + and a + ret + +.notYellowSprite + scf + ret + +LoadMapSpriteTilePatterns: + ld a, 0 +.loop + ld [hVRAMSlot], a + cp 9 + jr nc, .fourTileSprite + call LoadStillTilePattern + call LoadWalkingTilePattern + jr .continue + +.fourTileSprite + call LoadStillTilePattern +.continue + ld a, [hVRAMSlot] + inc a + cp 11 + jr nz, .loop + ret + +ReloadWalkingTilePatterns: + xor a +.loop + ld [hVRAMSlot], a + cp 9 + jr nc, .fourTileSprite + call LoadWalkingTilePattern +.fourTileSprite + ld a, [hVRAMSlot] + inc a + cp 11 + jr nz, .loop + ret + +LoadStillTilePattern: + ld a, [wFontLoaded] + bit 0, a ; reloading upper half of tile patterns after displaying text? + ret nz ; if so, skip loading data into the lower half + call ReadSpriteSheetData + ret nc + call GetSpriteVRAMAddress + call CopyVideoDataAlternate ; new yellow function + ret + +LoadWalkingTilePattern: + call ReadSpriteSheetData + ret nc + ld hl, $c0 + add hl, de + ld d, h + ld e, l + call GetSpriteVRAMAddress + set 3, h ; add $800 to hl + call CopyVideoDataAlternate + ret + +GetSpriteVRAMAddress: + push bc + ld a, [hVRAMSlot] + ld c, a + ld b, 0 + ld hl, SpriteVRAMAddresses + add hl, bc + add hl, bc + ld a, [hli] + ld h, [hl] ld l, a + pop bc + ret + +SpriteVRAMAddresses: +; Equivalent to multiplying $C0 (number of bytes in 12 tiles) times the VRAM +; slot and adding the result to $8000 (the VRAM base address). + dw vChars0 + $0c0 + dw vChars0 + $180 + dw vChars0 + $240 + dw vChars0 + $300 + dw vChars0 + $3c0 + dw vChars0 + $480 + dw vChars0 + $540 + dw vChars0 + $600 + dw vChars0 + $6c0 + dw vChars0 + $780 ; 4-tile sprites + dw vChars0 + $7c0 ; 4-tile sprites + +ReadSpriteSheetData: + ld a, [hVRAMSlot] + ld e, a + ld d, 0 + ld hl, wSpriteSet + add hl, de + ld a, [hl] and a - jr nz, .storeVRAMSlotsLoop + ret z + + dec a + ld l, a + ld h, 0 + add hl, hl + add hl, hl + ld de, SpriteSheetPointerTable + add hl, de + ld e, [hl] + inc hl + ld d, [hl] + inc hl + ld c, [hl] + swap c ; get the number of tiles, not the raw byte length + ; this is because of the use of CopyVideoDataAlternate + inc hl + ld b, [hl] + inc hl scf ret +Func_14150: + ld a, $1 + ld [wSpritePlayerStateData2ImageBaseOffset], a ; vram slot for player + ld a, $2 + ld [wSpritePikachuStateData2ImageBaseOffset], a ; vram slot for Pikachu + ld a, $e + ld hl, wSprite01StateData1 +.loop + ld [hVRAMSlot], a ; store current sprite set slot as a counter + ld a, [hl] ; $c1x0 (picture ID) + and a ; is the sprite unused? + jr z, .spriteUnused + call Func_14179 + push hl + ld de, (wSpritePlayerStateData2ImageBaseOffset) - (wSpriteStateData1) ; $10e + add hl, de ; get $c2xe (sprite image base offset) + ld [hl], a ; write offset + pop hl +.spriteUnused + ld de, wSprite02StateData1 - wSprite01StateData1 + add hl, de + ld a, [hVRAMSlot] + dec a + jr nz, .loop + ret + +Func_14179: + push de + push bc + ld c, a ; c = picture ID + ld b, 11 + ld de, wSpriteSet +.findSpriteImageBaseOffsetLoop + ld a, [de] ; a = sprite set picture ID + cp c ; have we found a match? + jr z, .foundSpritePictureID ; if so, get the sprite image base offset and return + inc de + dec b ; have we looped through all entries in wSpriteSet? + jr nz, .findSpriteImageBaseOffsetLoop ; continue looping if not + ld a, $1 ; assume slot one if this ever happens + jr .done +.foundSpritePictureID + ld a, 13 + sub b ; get sprite image base offset +.done + pop bc + pop de + ret + +GetSplitMapSpriteSetID: + ld e, a + ld d, 0 + ld hl, MapSpriteSets + add hl, de + ld a, [hl] ; a = spriteSetID + cp a, $f0 ; does the map have 2 sprite sets? + ret c ; Chooses the correct sprite set ID depending on the player's position within ; the map for maps with two sprite sets. -GetSplitMapSpriteSetID: cp $f8 jr z, .route20 ld hl, SplitMapSpriteSets and $0f dec a - sla a - sla a + add a + add a add l ld l, a jr nc, .noCarry diff --git a/engine/overworld/missable_objects.asm b/engine/overworld/missable_objects.asm index 8587c0f7..dd601451 100644 --- a/engine/overworld/missable_objects.asm +++ b/engine/overworld/missable_objects.asm @@ -17,33 +17,30 @@ MarkTownVisitedAndLoadMissableObjects: ld h, [hl] ; fall through -LoadMissableObjects: +; LoadMissableObjects: +; seems to not exist in yellow (predef replaced with something near TryPushingBoulder) ld l, a push hl - ld de, MapHS00 ; calculate difference between out pointer and the base pointer ld a, l - sub e - jr nc, .asm_f13c - dec h -.asm_f13c + sub MapHS00 & $ff ; calculate difference between out pointer and the base pointer ld l, a ld a, h - sub d + sbc MapHS00 / $100 ld h, a ld a, h ld [H_DIVIDEND], a ld a, l - ld [H_DIVIDEND+1], a + ld [H_DIVIDEND + 1], a xor a - ld [H_DIVIDEND+2], a - ld [H_DIVIDEND+3], a + ld [H_DIVIDEND + 2], a + ld [H_DIVIDEND + 3], a ld a, $3 ld [H_DIVISOR], a ld b, $2 call Divide ; divide difference by 3, resulting in the global offset (number of missable items before ours) ld a, [wCurMap] ld b, a - ld a, [H_DIVIDEND+3] + ld a, [H_DIVIDEND + 3] ld c, a ; store global offset in c ld de, wMissableObjectList pop hl diff --git a/engine/overworld/movement.asm b/engine/overworld/movement.asm index f272f497..f2334479 100644 --- a/engine/overworld/movement.asm +++ b/engine/overworld/movement.asm @@ -22,7 +22,13 @@ UpdatePlayerSprite: ld [wSpriteStateData1 + 2], a ret .lowerLeftTileIsMapTile + ld a, [wUpdateSpritesEnabled] + push af + ld a, $ff + ld [wUpdateSpritesEnabled], a call DetectCollisionBetweenSprites + pop af + ld [wUpdateSpritesEnabled], a ld h, wSpriteStateData1 / $100 ld a, [wWalkCounter] and a @@ -48,42 +54,24 @@ UpdatePlayerSprite: jr z, .notMoving ld a, SPRITE_FACING_RIGHT jr .next +.next + ld [wSpritePlayerStateData1FacingDirection], a ; facing direction + ld a, [wFontLoaded] + bit 0, a + jr z, .moving .notMoving ; zero the animation counters xor a ld [wSpriteStateData1 + 7], a ld [wSpriteStateData1 + 8], a - jr .calcImageIndex -.next - ld [wSpriteStateData1 + 9], a ; facing direction - ld a, [wFontLoaded] - bit 0, a - jr nz, .notMoving + call Func_4e32 + jr .skipSpriteAnim .moving ld a, [wd736] bit 7, a ; is the player sprite spinning due to a spin tile? jr nz, .skipSpriteAnim - ld a, [H_CURRENTSPRITEOFFSET] - add $7 - ld l, a - ld a, [hl] - inc a - ld [hl], a - cp 4 - jr nz, .calcImageIndex - xor a - ld [hl], a - inc hl - ld a, [hl] - inc a - and $3 - ld [hl], a -.calcImageIndex - ld a, [wSpriteStateData1 + 8] - ld b, a - ld a, [wSpriteStateData1 + 9] - add b - ld [wSpriteStateData1 + 2], a + call Func_5274 + call Func_4e32 .skipSpriteAnim ; If the player is standing on a grass tile, make the player's sprite have ; lower priority than the background so that it's partially obscured by the @@ -97,18 +85,15 @@ UpdatePlayerSprite: jr nz, .next2 ld a, $80 .next2 - ld [wSpriteStateData2 + 7], a + ld [wSpriteStateData2 + $07], a ret -UnusedReadSpriteDataFunction: - push bc - push af - ld a, [H_CURRENTSPRITEOFFSET] - ld c, a - pop af - add c - ld l, a - pop bc +Func_4e32: + ld a, [wSpriteStateData1 + 8] + ld b, a + ld a, [wSpritePlayerStateData1FacingDirection] + add b + ld [wSpriteStateData1 + 2], a ret UpdateNPCSprite: @@ -121,7 +106,7 @@ UpdateNPCSprite: ld l, a ld a, [hl] ; read movement byte 2 ld [wCurSpriteMovement2], a - ld h, $c1 + ld h, wSpriteStateData1 / $100 ld a, [H_CURRENTSPRITEOFFSET] ld l, a inc l @@ -130,7 +115,7 @@ UpdateNPCSprite: jp z, InitializeSpriteStatus call CheckSpriteAvailability ret c ; if sprite is invisible, on tile >=MAP_TILESET_SIZE, in grass or player is currently walking - ld h, $c1 + ld h, wSpriteStateData1 / $100 ld a, [H_CURRENTSPRITEOFFSET] ld l, a inc l @@ -146,19 +131,21 @@ UpdateNPCSprite: jp z, UpdateSpriteMovementDelay ; c1x1 == 2 cp $3 jp z, UpdateSpriteInWalkingAnimation ; c1x1 == 3 + cp $4 + jp z, Func_5357 ld a, [wWalkCounter] and a ret nz ; don't do anything yet if player is currently moving (redundant, already tested in CheckSpriteAvailability) call InitializeSpriteScreenPosition - ld h, $c2 + ld h, wSpriteStateData2 / $100 ld a, [H_CURRENTSPRITEOFFSET] add $6 ld l, a ld a, [hl] ; c2x6: movement byte 1 inc a - jr z, .randomMovement ; value $FF + jp z, .randomMovement ; value $FF inc a - jr z, .randomMovement ; value $FE + jp z, .randomMovement ; value $FE ; scripted movement dec a ld [hl], a ; increment movement byte 1 (movement data index) @@ -183,12 +170,18 @@ UpdateNPCSprite: ret .next cp WALK - jr nz, .determineDirection + jr nz, .asm_4ecb ; current NPC movement data is $fe. this seems buggy ld [hl], $1 ; set movement byte 1 to $1 ld de, wNPCMovementDirections call LoadDEPlusA ; a = [wNPCMovementDirections + $fe] (?) - jr .determineDirection +.asm_4ecb + push af + call Func_5288 + pop bc + ld a, b + jr nc, .determineDirection + ret .randomMovement call GetTileSpriteStandsOn call Random @@ -263,59 +256,25 @@ ChangeFacingDirection: ; set carry on failure, clears carry on success TryWalking: push hl - ld h, $c1 - ld a, [H_CURRENTSPRITEOFFSET] - add $9 - ld l, a - ld [hl], c ; c1x9 (update facing direction) - ld a, [H_CURRENTSPRITEOFFSET] - add $3 - ld l, a - ld [hl], d ; c1x3 (update Y movement delta) - inc l - inc l - ld [hl], e ; c1x5 (update X movement delta) + call Func_5337 pop hl push de - ld c, [hl] ; read tile to walk onto + ld c, [hl] call CanWalkOntoTile pop de - ret c ; cannot walk there (reinitialization of delay values already done) - ld h, $c2 + ret c + call Func_5349 ld a, [H_CURRENTSPRITEOFFSET] - add $4 ld l, a - ld a, [hl] ; c2x4: Y position - add d - ld [hli], a ; update Y position - ld a, [hl] ; c2x5: X position - add e - ld [hl], a ; update X position - ld a, [H_CURRENTSPRITEOFFSET] - ld l, a - ld [hl], $10 ; c2x0=16: walk animation counter + ld [hl], $10 ; c1x9 (update facing direction) dec h inc l - ld [hl], $3 ; c1x1: set movement status to walking + ld [hl], $3 jp UpdateSpriteImage ; update the walking animation parameters for a sprite that is currently walking UpdateSpriteInWalkingAnimation: - ld a, [H_CURRENTSPRITEOFFSET] - add $7 - ld l, a - ld a, [hl] ; c1x7 (counter until next walk animation frame) - inc a - ld [hl], a ; c1x7 += 1 - cp $4 - jr nz, .noNextAnimationFrame - xor a - ld [hl], a ; c1x7 = 0 - inc l - ld a, [hl] ; c1x8 (walk animation frame) - inc a - and $3 - ld [hl], a ; advance to next animation frame every 4 ticks (16 ticks total for one step) + call Func_5274 .noNextAnimationFrame ld a, [H_CURRENTSPRITEOFFSET] add $3 @@ -446,6 +405,7 @@ InitializeSpriteStatus: ld a, $8 ld [hli], a ; $c2x2: set Y displacement to 8 ld [hl], a ; $c2x3: set X displacement to 8 + call InitializeSpriteScreenPosition ; could have done fallthrough here ret ; calculates the sprite's screen position form its map position and the player position @@ -458,7 +418,7 @@ InitializeSpriteScreenPosition: ld b, a ld a, [hl] ; c2x4 (Y position + 4) sub b ; relative to player position - swap a ; * 16 + call Func_5033 sub $4 ; - 4 dec h ld [hli], a ; c1x4 (screen Y position) @@ -467,11 +427,23 @@ InitializeSpriteScreenPosition: ld b, a ld a, [hli] ; c2x6 (X position + 4) sub b ; relative to player position - swap a ; * 16 + call Func_5033 dec h ld [hl], a ; c1x6 (screen X position) ret +Func_5033: + jr nc, .asm_503c + cpl + inc a + swap a + cpl + inc a + ret +.asm_503c + swap a + ret + ; tests if sprite is off screen or otherwise unable to do anything CheckSpriteAvailability: predef IsObjectHidden @@ -591,17 +563,9 @@ CanWalkOntoTile: and a ret .notScripted - ld a, [wTilesetCollisionPtr] - ld l, a - ld a, [wTilesetCollisionPtr+1] - ld h, a -.tilePassableLoop - ld a, [hli] - cp $ff - jr z, .impassable - cp c - jr nz, .tilePassableLoop - ld h, $c2 + call _IsTilePassable + jr c, .impassable + ld h, wSpriteStateData2 / $100 ld a, [H_CURRENTSPRITEOFFSET] add $6 ld l, a @@ -624,7 +588,13 @@ CanWalkOntoTile: jr nc, .impassable ; don't walk off screen push de push bc + ld a, [wUpdateSpritesEnabled] + push af + ld a, $ff + ld [wUpdateSpritesEnabled], a call DetectCollisionBetweenSprites + pop af + ld [wUpdateSpritesEnabled], a pop bc pop de ld h, wSpriteStateData1 / $100 @@ -643,7 +613,7 @@ CanWalkOntoTile: jr nz, .upwards add d cp $5 - jr c, .impassable ; if c2x2+d < 5, don't go ;bug: this tests probably were supposed to prevent sprites + ;jr c, .impassable (bugfix) ; if c2x2+d < 5, don't go ;bug: this tests probably were supposed to prevent sprites jr .checkHorizontal ; from walking out too far, but this line makes sprites get stuck .upwards ; whenever they walked upwards 5 steps sub $1 ; on the other hand, the amount a sprite can walk out to the @@ -665,7 +635,7 @@ CanWalkOntoTile: and a ; clear carry (marking success) ret .impassable - ld h, $c1 + ld h, wSpriteStateData1 / $100 ld a, [H_CURRENTSPRITEOFFSET] inc a ld l, a @@ -697,7 +667,7 @@ GetTileSpriteStandsOn: ld l, a ld a, [hli] ; c1x4: screen Y position add $4 ; align to 2*2 tile blocks (Y position is always off 4 pixels to the top) - and $f0 ; in case object is currently moving + and $f8 ; in case object is currently moving (XXX why changed to $f8?) srl a ; screen Y tile * 4 ld c, a ld b, $0 @@ -863,20 +833,235 @@ AnimScriptedNPCMovement: ret AdvanceScriptedNPCAnimFrameCounter: + call Func_5274 + ld h, wSpriteStateData1 / $100 ld a, [H_CURRENTSPRITEOFFSET] - add $7 + add $8 ld l, a ld a, [hl] ; intra-animation frame counter + and $3 + ld [hSpriteAnimFrameCounter], a + ret + +Func_5274: + ld a, [H_CURRENTSPRITEOFFSET] + add $7 + ld l, a + ld h, wSpriteStateData1 / $100 + ld a, [hl] ; c1x7 (counter until next walk animation frame) inc a + and $3 + ld [hl], a ; c1x7 += 1 + ret nz ; c1x7 = 0 + inc l + ld a, [hl] ; c1x8 (walk animation frame) + inc a + and $3 + ld [hl], a ; advance to next animation frame every 4 ticks (16 ticks total for one step) + ret + +Func_5288: +; nice lookup table +; a is supposedly [wNPCMovementDirections + $fe] + cp $5 + jr z, .asm_52af + cp $4 + jr z, .asm_52aa + cp $6 + jr z, .asm_52b4 + cp $7 + jr z, .asm_52b9 + cp $11 + jr z, .asm_52c3 + cp $12 + jr z, .asm_52be + cp $13 + jr z, .asm_52c8 + cp $14 + jr z, .asm_52cd + xor a + ret +; set 1? +.asm_52aa + call Func_531f + jr .asm_52e6 +.asm_52af + call Func_5325 + jr .asm_52e6 +.asm_52b4 + call Func_5331 + jr .asm_52e6 +.asm_52b9 + call Func_532b + jr .asm_52e6 +; set 2? +.asm_52be + call Func_531f + jr .asm_52fa +.asm_52c3 + call Func_5325 + jr .asm_52fa +.asm_52c8 + call Func_5331 + jr .asm_52fa +.asm_52cd + call Func_532b + jr .asm_52fa +; set 3? (unused) +.asm_52d2 + call Func_531f + jr .asm_530b +.asm_52d7 + call Func_5325 + jr .asm_530b +.asm_52dc + call Func_5331 + jr .asm_530b +.asm_52e1 + call Func_532b + jr .asm_530b + +.asm_52e6 + call Func_5337 + call Func_5349 + ld a, [H_CURRENTSPRITEOFFSET] + ld l, a + ld [hl], $8 + dec h + inc l + ld [hl], $4 + call UpdateSpriteImage + scf + ret + +.asm_52fa + call Func_5337 + ld a, [H_CURRENTSPRITEOFFSET] + ld l, a + ld [hl], $8 + dec h + inc l + ld [hl], $3 + call UpdateSpriteImage + scf + ret + +.asm_530b + call Func_5337 + call Func_5349 + ld a, [H_CURRENTSPRITEOFFSET] + ld l, a + ld [hl], $8 + dec h + inc l + ld [hl], $3 + call UpdateSpriteImage + scf + ret + +Func_531f: + lb de, 1, 0 + ld c, SPRITE_FACING_DOWN + ret + +Func_5325: + lb de, -1, 0 + ld c, SPRITE_FACING_UP + ret + +Func_532b: + lb de, 0, 1 + ld c, SPRITE_FACING_RIGHT + ret + +Func_5331: + lb de, 0, -1 + ld c, SPRITE_FACING_LEFT + ret + +Func_5337: + ld a, [H_CURRENTSPRITEOFFSET] + add $9 + ld l, a + ld h, wSpriteStateData1 / $100 + ld [hl], c ; c1x9 (update facing direction) + ld a, [H_CURRENTSPRITEOFFSET] + add $3 + ld l, a + ld [hl], d ; c1x3 (update Y movement delta) + inc l + inc l + ld [hl], e ; c1x5 (update X movement delta) + ret + +Func_5349: + ld h, wSpriteStateData2 / $100 + ld a, [H_CURRENTSPRITEOFFSET] + add $4 + ld l, a + ld a, [hl] ; c2x4: Y position + add d + ld [hli], a ; update Y position + ld a, [hl] ; c2x5: X position + add e + ld [hl], a ; update X position + ret + +Func_5357: + call Func_5274 + ld a, [H_CURRENTSPRITEOFFSET] + add $3 + ld l, a + ld h, wSpriteStateData1 / $100 + ld a, [hli] + add a + ld b, a + ld a, [hl] + add b + ld [hli], a + ld a, [hli] + add a + ld b, a + ld a, [hl] + add b ld [hl], a - cp 4 + ld a, [H_CURRENTSPRITEOFFSET] + ld l, a + ld h, wSpriteStateData2 / $100 + dec [hl] ret nz + ld a, $6 + add l + ld l, a + ld a, [hl] + cp $fe + jr nc, .asm_5386 + ld a, [H_CURRENTSPRITEOFFSET] + inc a + ld l, a + ld h, wSpriteStateData1 / $100 + ld [hl], $1 + ret +.asm_5386 + call Random + ld a, [H_CURRENTSPRITEOFFSET] + add $8 + ld l, a + ld h, wSpriteStateData2 / $100 + ld a, [hRandomAdd] + and $7f + ld [hl], a + dec h + ld a, [H_CURRENTSPRITEOFFSET] + inc a + ld l, a + ld [hl], $2 + inc l + inc l xor a - ld [hl], a ; reset intra-animation frame counter + ld b, [hl] + ld [hli], a inc l - ld a, [hl] ; animation frame counter - inc a - and $3 + ld c, [hl] ld [hl], a - ld [hSpriteAnimFrameCounter], a ret diff --git a/engine/overworld/npc_movement.asm b/engine/overworld/npc_movement.asm index 968615f0..670cb121 100755 --- a/engine/overworld/npc_movement.asm +++ b/engine/overworld/npc_movement.asm @@ -37,8 +37,8 @@ _EndNPCMovementScript: res 1, [hl] xor a ld [wNPCMovementScriptSpriteOffset], a - ld [wNPCMovementScriptPointerTableNum], a ld [wNPCMovementScriptFunctionNum], a + ld [wNPCMovementScriptPointerTableNum], a ld [wWastedByteCD3A], a ld [wSimulatedJoypadStatesIndex], a ld [wSimulatedJoypadStatesEnd], a @@ -79,6 +79,10 @@ PalletMovementScript_OakMoveLeft: ld a, $3 ld [wNPCMovementScriptFunctionNum], a .done + ld a, BANK(Music_MuseumGuy) + ld c, a + ld a, MUSIC_MUSEUM_GUY + call PlayMusic ld hl, wFlags_D733 set 1, [hl] ld a, $fc @@ -127,8 +131,9 @@ PalletMovementScript_WalkToLab: ld [wNPCMovementScriptFunctionNum], a ret + RLEList_ProfOakWalkToLab: - db NPC_MOVEMENT_DOWN, $05 + db NPC_MOVEMENT_DOWN, $06 ; differs from red db NPC_MOVEMENT_LEFT, $01 db NPC_MOVEMENT_DOWN, $05 db NPC_MOVEMENT_RIGHT, $03 @@ -141,7 +146,7 @@ RLEList_PlayerWalkToLab: db D_RIGHT, $03 db D_DOWN, $05 db D_LEFT, $01 - db D_DOWN, $06 + db D_DOWN, $07 ; differs from red db $FF PalletMovementScript_Done: @@ -163,11 +168,9 @@ PewterMuseumGuyMovementScriptPointerTable: PewterMovementScript_WalkToMuseum: ld a, BANK(Music_MuseumGuy) - ld [wAudioROMBank], a - ld [wAudioSavedROMBank], a + ld c, a ld a, MUSIC_MUSEUM_GUY - ld [wNewSoundID], a - call PlaySound + call PlayMusic ld a, [wSpriteIndex] swap a ld [wNPCMovementScriptSpriteOffset], a @@ -179,7 +182,7 @@ PewterMovementScript_WalkToMuseum: ld [wSimulatedJoypadStatesIndex], a xor a ld [wWhichPewterGuy], a - predef PewterGuys + call PewterGuys ld hl, wNPCMovementDirections2 ld de, RLEList_PewterMuseumGuy call DecodeRLEList @@ -219,11 +222,9 @@ PewterGymGuyMovementScriptPointerTable: PewterMovementScript_WalkToGym: ld a, BANK(Music_MuseumGuy) - ld [wAudioROMBank], a - ld [wAudioSavedROMBank], a + ld c, a ld a, MUSIC_MUSEUM_GUY - ld [wNewSoundID], a - call PlaySound + call PlayMusic ld a, [wSpriteIndex] swap a ld [wNPCMovementScriptSpriteOffset], a @@ -236,7 +237,7 @@ PewterMovementScript_WalkToGym: ld [wSimulatedJoypadStatesIndex], a ld a, 1 ld [wWhichPewterGuy], a - predef PewterGuys + call PewterGuys ld hl, wNPCMovementDirections2 ld de, RLEList_PewterGymGuy call DecodeRLEList @@ -266,27 +267,4 @@ RLEList_PewterGymGuy: db NPC_MOVEMENT_RIGHT, $03 db $FF -FreezeEnemyTrainerSprite: - ld a, [wCurMap] - cp POKEMON_TOWER_7F - ret z ; the Rockets on Pokemon Tower 7F leave after battling, so don't freeze them - ld hl, RivalIDs - ld a, [wEngagedTrainerClass] - ld b, a -.loop - ld a, [hli] - cp $ff - jr z, .notRival - cp b - ret z ; the rival leaves after battling, so don't freeze him - jr .loop -.notRival - ld a, [wSpriteIndex] - ld [H_SPRITEINDEX], a - jp SetSpriteMovementBytesToFF - -RivalIDs: - db OPP_SONY1 - db OPP_SONY2 - db OPP_SONY3 - db $ff +INCLUDE "engine/overworld/pewter_guys.asm" diff --git a/engine/overworld/npc_movement_2.asm b/engine/overworld/npc_movement_2.asm new file mode 100755 index 00000000..93d1afce --- /dev/null +++ b/engine/overworld/npc_movement_2.asm @@ -0,0 +1,24 @@ +FreezeEnemyTrainerSprite: + ld a, [wCurMap] + cp POKEMON_TOWER_7F + ret z ; the Rockets on Pokemon Tower 7F leave after battling, so don't freeze them + ld hl, RivalIDs + ld a, [wEngagedTrainerClass] + ld b, a +.loop + ld a, [hli] + cp $ff + jr z, .notRival + cp b + ret z ; the rival leaves after battling, so don't freeze him + jr .loop +.notRival + ld a, [wSpriteIndex] + ld [H_SPRITEINDEX], a + jp SetSpriteMovementBytesToFF + +RivalIDs: + db OPP_SONY1 + db OPP_SONY2 + db OPP_SONY3 + db $ff diff --git a/engine/overworld/oam.asm b/engine/overworld/oam.asm index 2c2a3dff..5a831327 100644 --- a/engine/overworld/oam.asm +++ b/engine/overworld/oam.asm @@ -1,6 +1,8 @@ PrepareOAMData: ; 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 ld a, [wUpdateSpritesEnabled] dec a @@ -18,9 +20,9 @@ PrepareOAMData: .spriteLoop ld [hSpriteOffset2], a - ld d, wSpriteStateData1 / $100 - ld a, [hSpriteOffset2] ld e, a + ld d, wSpriteStateData1 / $100 + ld a, [de] ; c1x0 and a jp z, .nextSprite @@ -40,16 +42,22 @@ PrepareOAMData: jr c, .usefacing ; unchanging - and $f - add $10 ; skip to the second half of the table which doesn't account for facing direction + ld a, $0 jr .next .usefacing and $f .next +; read the entry from the table + ld c, a + ld b, 0 + ld hl, SpriteFacingAndAnimationTable + add hl, bc + add hl, bc + ld a, [hli] + ld h, [hl] ld l, a - ; get sprite priority push de inc d @@ -61,65 +69,46 @@ PrepareOAMData: ld [hSpritePriority], a ; temp store sprite priority pop de -; read the entry from the table - ld h, 0 - ld bc, SpriteFacingAndAnimationTable - add hl, hl - add hl, hl - add hl, bc - ld a, [hli] - ld c, a - ld a, [hli] - ld b, a - ld a, [hli] - ld h, [hl] - ld l, a call GetSpriteScreenXY ld a, [hOAMBufferOffset] + add [hl] + cp $a0 + jr z, .hidden + jr nc, .asm_4a41 +.hidden + call Func_4a7b + ld [wd5cd], a + ld a, [hOAMBufferOffset] + ld e, a ld d, wOAMBuffer / $100 .tileLoop + ld a, [hli] + ld c, a +.loop ld a, [hSpriteScreenY] ; temp for sprite Y position add $10 ; Y=16 is top of screen (Y=0 is invisible) add [hl] ; add Y offset from table ld [de], a ; write new sprite OAM Y position inc hl + inc e ld a, [hSpriteScreenX] ; temp for sprite X position add $8 ; X=8 is left of screen (X=0 is invisible) add [hl] ; add X offset from table + ld [de], a + inc hl inc e - ld [de], a ; write new sprite OAM X position - inc e - ld a, [bc] ; read pattern number offset (accommodates orientation (offset 0,4 or 8) and animation (offset 0 or $80)) - inc bc - push bc + ld a, [wd5cd] + add [hl] + cp $80 + jr c, .asm_4a1c ld b, a - - ld a, [wd5cd] ; temp copy of c1x2 - swap a ; high nybble determines sprite used (0 is always player sprite, next are some npcs) - and $f - - ; Sprites $a and $b have one face (and therefore 4 tiles instead of 12). - ; As a result, sprite $b's tile offset is less than normal. - cp $b - jr nz, .notFourTileSprite - ld a, $a * 12 + 4 - jr .next2 - -.notFourTileSprite - ; a *= 12 - sla a - sla a - ld c, a - sla a - add c - -.next2 - add b ; add the tile offset from the table (based on frame and facing direction) - pop bc + ld a, [$fffc] + add b +.asm_4a1c ld [de], a ; tile id inc hl inc e @@ -129,15 +118,19 @@ PrepareOAMData: ld a, [hSpritePriority] or [hl] .skipPriority - inc hl + and $f0 + bit 4, a ; OBP0 or OBP1 + jr z, .spriteusesOBP0 + or %100 ; palettes 4-7 are OBP1 +.spriteusesOBP0 ld [de], a + inc hl inc e - bit 0, a ; OAMFLAG_ENDOFDATA - jr z, .tileLoop + dec c + jr nz, .loop ld a, e ld [hOAMBufferOffset], a - .nextSprite ld a, [hSpriteOffset2] add $10 @@ -145,26 +138,31 @@ PrepareOAMData: jp nz, .spriteLoop ; Clear unused OAM. - ld a, [hOAMBufferOffset] - ld l, a - ld h, wOAMBuffer / $100 - ld de, $4 - ld b, $a0 +.asm_4a41 ld a, [wd736] bit 6, a ; jumping down ledge or fishing animation? - ld a, $a0 + ld c, $a0 jr z, .clear ; Don't clear the last 4 entries because they are used for the shadow in the ; jumping down ledge animation and the rod in the fishing animation. - ld a, $90 + ld c, $90 .clear - cp l - ret z + ld a, [hOAMBufferOffset] + cp c + ret nc + ld l, a + ld h, wOAMBuffer / $100 + ld a, c + ld de, $4 ; entry size + ld b, $a0 +.clearLoop ld [hl], b add hl, de - jr .clear + cp l + jr nz, .clearLoop + ret GetSpriteScreenXY: inc e @@ -187,3 +185,48 @@ GetSpriteScreenXY: and $f0 ld [de], a ; c1xb (x) ret + +Func_4a7b: + push bc + ld a, [wd5cd] ; temp copy of c1x2 + swap a ; high nybble determines sprite used (0 is always player sprite, next are some npcs) + and $f + + ; Sprites $a and $b have one face (and therefore 4 tiles instead of 12). + ; As a result, sprite $b's tile offset is less than normal. + cp $b + jr nz, .notFourTileSprite + ld a, $a * 12 + 4 ; $7c + jr .done + +.notFourTileSprite + ; a *= 12 + add a + add a + ld c, a + add a + add c +.done + pop bc + ret + +INCLUDE "engine/oam_dma.asm" + +_IsTilePassable:: + ld hl,wTilesetCollisionPtr ; pointer to list of passable tiles + ld a,[hli] + ld h,[hl] + ld l,a ; hl now points to passable tiles +.loop + ld a,[hli] + cp a,$ff + jr z,.tileNotPassable + cp c + jr nz,.loop + xor a + ret +.tileNotPassable + scf + ret + +INCLUDE "data/collision.asm" ; probably diff --git a/engine/overworld/player_animations.asm b/engine/overworld/player_animations.asm index a17e67bd..d4ecec53 100755 --- a/engine/overworld/player_animations.asm +++ b/engine/overworld/player_animations.asm @@ -13,8 +13,8 @@ EnterMapAnim: call PlaySound ld hl, wd732 bit 4, [hl] ; used dungeon warp? - res 4, [hl] pop hl + ;res 4, [hl] jr nz, .dungeonWarpAnimation call PlayerSpinWhileMovingDown ld a, SFX_TELEPORT_ENTER_2 @@ -34,21 +34,22 @@ EnterMapAnim: ld [hl], $ff ; wPlayerSpinInPlaceAnimSoundID ld hl, wFacingDirectionList call PlayerSpinInPlace + ld a, $1 + ld [wPikachuSpawnState], a .restoreDefaultMusic call PlayDefaultMusic .done + call Func_151d jp RestoreFacingDirectionAndYScreenPos .dungeonWarpAnimation ld c, 50 call DelayFrames call PlayerSpinWhileMovingDown + ld a, $0 + ld [wPikachuSpawnState], a jr .done .flyAnimation pop hl - ld de, BirdSprite - ld hl, vNPCSprites - lb bc, BANK(BirdSprite), $0c - call CopyVideoData call LoadBirdSpriteGraphics ld a, SFX_FLY call PlaySound @@ -61,6 +62,8 @@ EnterMapAnim: ld de, FlyAnimationEnterScreenCoords call DoFlyAnimation call LoadPlayerSpriteGraphics + ld a, $1 + ld [wPikachuSpawnState], a jr .restoreDefaultMusic FlyAnimationEnterScreenCoords: @@ -90,7 +93,9 @@ PlayerSpinWhileMovingDown: ld [hl], a ; wPlayerSpinWhileMovingUpOrDownAnimFrameDelay jp PlayerSpinWhileMovingUpOrDown + _LeaveMapAnim: + call Func_1510 call InitFacingDirectionList call IsPlayerStandingOnWarpPadOrHole ld a, b @@ -249,12 +254,14 @@ DoFlyAnimation: LoadBirdSpriteGraphics: ld de, BirdSprite + ld b, BANK(BirdSprite) + ld c, $c ld hl, vNPCSprites - lb bc, BANK(BirdSprite), $0c call CopyVideoData ld de, BirdSprite + $c0 ; moving animation sprite + ld b, BANK(BirdSprite) + ld c, $0c ld hl, vNPCSprites2 - lb bc, BANK(BirdSprite), $0c jp CopyVideoData InitFacingDirectionList: @@ -386,9 +393,10 @@ FishingAnim: call DelayFrames ld hl, wd736 set 6, [hl] ; reserve the last 4 OAM entries - ld de, RedSprite ld hl, vNPCSprites - lb bc, BANK(RedSprite), $c + ld de, RedSprite + ld b, BANK(RedSprite) + ld c, $c call CopyVideoData ld a, $4 ld hl, RedFishingTiles diff --git a/engine/overworld/player_state.asm b/engine/overworld/player_state.asm index 73c55da2..8cbacc61 100644 --- a/engine/overworld/player_state.asm +++ b/engine/overworld/player_state.asm @@ -70,7 +70,8 @@ CheckForceBikeOrSurf: ld a, $1 ld [wWalkBikeSurfState], a ld [wWalkBikeSurfStateCopy], a - jp ForceBikeOrSurf + call ForceBikeOrSurf + ret .incorrectMap inc hl .incorrectY @@ -80,7 +81,8 @@ CheckForceBikeOrSurf: ld a, $2 ld [wWalkBikeSurfState], a ld [wWalkBikeSurfStateCopy], a - jp ForceBikeOrSurf + call ForceBikeOrSurf + ret INCLUDE "data/force_bike_surf.asm" @@ -101,10 +103,10 @@ IsPlayerFacingEdgeOfMap: ld b, a ld a, [wXCoord] ld c, a - ld de, .asm_c41e + ld de, .returnaddress push de jp hl -.asm_c41e +.returnaddress pop bc pop de pop hl @@ -240,8 +242,7 @@ PrintSafariZoneSteps: cp CERULEAN_CAVE_2F ret nc coord hl, 0, 0 - ld b, 3 - ld c, 7 + lb bc, 3, 7 call TextBoxBorder coord hl, 1, 1 ld de, wSafariSteps @@ -255,11 +256,11 @@ PrintSafariZoneSteps: call PlaceString ld a, [wNumSafariBalls] cp 10 - jr nc, .asm_c56d + jr nc, .numSafariBallsTwoDigits coord hl, 5, 3 ld a, " " ld [hl], a -.asm_c56d +.numSafariBallsTwoDigits coord hl, 6, 3 ld de, wNumSafariBalls lb bc, 1, 2 @@ -361,16 +362,8 @@ GetTileTwoStepsInFrontOfPlayer: CheckForCollisionWhenPushingBoulder: call GetTileTwoStepsInFrontOfPlayer - ld hl, wTilesetCollisionPtr - ld a, [hli] - ld h, [hl] - ld l, a -.loop - ld a, [hli] - cp $ff - jr z, .done ; if the tile two steps ahead is not passable - cp c - jr nz, .loop + call IsTilePassable + jr c, .done ld hl, TilePairCollisionsLand call CheckForTilePairCollisions2 ld a, $ff diff --git a/engine/overworld/poison.asm b/engine/overworld/poison.asm index 5d8eb9fd..03fb8a65 100644 --- a/engine/overworld/poison.asm +++ b/engine/overworld/poison.asm @@ -2,13 +2,20 @@ ApplyOutOfBattlePoisonDamage: ld a, [wd730] add a jp c, .noBlackOut ; no black out if joypad states are being simulated + ld a, [wd492] + bit 7, a + jp nz, .noBlackOut + ld a, [wd72e] + bit 6, a + jp nz, .noBlackOut ld a, [wPartyCount] and a jp z, .noBlackOut call IncrementDayCareMonExp + call Func_c4c7 ld a, [wStepCounter] and $3 ; is the counter a multiple of 4? - jp nz, .noBlackOut ; only apply poison damage every fourth step + jp nz, .skipPoisonEffectAndSound ; only apply poison damage every fourth step ld [wWhichPokemon], a ld hl, wPartyMon1Status ld de, wPartySpecies @@ -54,6 +61,12 @@ ApplyOutOfBattlePoisonDamage: ld a, TEXT_MON_FAINTED ld [hSpriteIndexOrTextID], a call DisplayTextID + callab IsThisPartymonStarterPikachu_Party + jr nc, .curMonNotPlayerPikachu + ld e, $3 + callab PlayPikachuSoundClip + calladb_ModifyPikachuHappiness PIKAHAPPY_PSNFNT +.curMonNotPlayerPikachu pop de pop hl .nextMon @@ -110,3 +123,29 @@ ApplyOutOfBattlePoisonDamage: .done ld [wOutOfBattleBlackout], a ret + +Func_c4c7: + ld a, [wStepCounter] + and a + jr nz, .asm_c4de + call Random + and $1 + jr z, .asm_c4de + calladb_ModifyPikachuHappiness $6 +.asm_c4de + ld hl, wPikachuMood + ld a, [hl] + cp $80 + jr z, .asm_c4ef + jr c, .asm_c4ea + dec a + dec a +.asm_c4ea + inc a + ld [hl], a + cp $80 + ret nz +.asm_c4ef + xor a + ld [wd49c], a + ret diff --git a/engine/overworld/pokecenter.asm b/engine/overworld/pokecenter.asm index f26bedf8..cf0159f9 100755 --- a/engine/overworld/pokecenter.asm +++ b/engine/overworld/pokecenter.asm @@ -1,4 +1,13 @@ DisplayPokemonCenterDialogue_: + ld a, [wCurMap] + cp PEWTER_POKECENTER + jr nz, .regularCenter + call CheckPikachuFollowingPlayer + jr z, .regularCenter + ld hl, LooksContentText ; if pikachu is sleeping, don't heal + call PrintText + ret +.regularCenter call SaveScreenTilesToBuffer1 ; save screen ld hl, PokemonCenterWelcomeText call PrintText @@ -11,18 +20,36 @@ DisplayPokemonCenterDialogue_: call PrintText .skipShallWeHealYourPokemon call YesNoChoicePokeCenter ; yes/no menu + call UpdateSprites ld a, [wCurrentMenuItem] and a - jr nz, .declinedHealing ; if the player chose No + jp nz, .declinedHealing ; if the player chose No call SetLastBlackoutMap - call LoadScreenTilesFromBuffer1 ; restore screen + callab IsStarterPikachuInOurParty + jr nc, .notHealingPlayerPikachu + call CheckPikachuFollowingPlayer + jr nz, .notHealingPlayerPikachu + call LoadCurrentMapView + call Delay3 + call UpdateSprites + callab PikachuWalksToNurseJoy ; todo +.notHealingPlayerPikachu ld hl, NeedYourPokemonText call PrintText - ld a, $18 - ld [wSpriteStateData1 + $12], a ; make the nurse turn to face the machine - call Delay3 - predef HealParty + ld c, 64 + call DelayFrames + call CheckPikachuFollowingPlayer + jr nz, .playerPikachuNotOnScreen + call DisablePikachuOverworldSpriteDrawing + callab IsStarterPikachuInOurParty + call c, Func_6eaa +.playerPikachuNotOnScreen + lb bc, 1, 8 + call Func_6ebb + ld c, 30 + call DelayFrames callba AnimateHealingMachine ; do the healing machine animation + predef HealParty xor a ld [wAudioFadeOutControl], a ld a, [wAudioSavedROMBank] @@ -31,19 +58,69 @@ DisplayPokemonCenterDialogue_: ld [wLastMusicSoundID], a ld [wNewSoundID], a call PlaySound + call CheckPikachuFollowingPlayer + jr nz, .doNotReturnPikachu + callab IsStarterPikachuInOurParty + call c, Func_6eaa + ld a, $5 + ld [wPikachuSpawnState], a + call EnablePikachuOverworldSpriteDrawing +.doNotReturnPikachu + lb bc, 1, 0 + call Func_6ebb ld hl, PokemonFightingFitText call PrintText - ld a, $14 - ld [wSpriteStateData1 + $12], a ; make the nurse bow - ld c, a + callab IsStarterPikachuInOurParty + jr nc, .notInParty + lb bc, 15, 0 + call Func_6ebb +.notInParty + call LoadCurrentMapView + call Delay3 + call UpdateSprites + callab ReloadWalkingTilePatterns + ld a, $1 + ld [H_SPRITEINDEX], a + ld a, $1 + ld [hSpriteImageIndex], a + call SpriteFunc_34a1 + ld c, 40 call DelayFrames + call UpdateSprites + call LoadFontTilePatterns jr .done .declinedHealing call LoadScreenTilesFromBuffer1 ; restore screen .done ld hl, PokemonCenterFarewellText call PrintText - jp UpdateSprites + call UpdateSprites + ret + +Func_6eaa: + ld a, $1 + ld [H_SPRITEINDEX], a + ld a, $4 + ld [hSpriteImageIndex], a + call SpriteFunc_34a1 + ld c, 64 + call DelayFrames + ret + +Func_6ebb: + ld a, b + ld [H_SPRITEINDEX], a + ld a, c + ld [hSpriteImageIndex], a + push bc + call SetSpriteFacingDirectionAndDelay + pop bc + ld a, b + ld [H_SPRITEINDEX], a + ld a, c + ld [hSpriteImageIndex], a + call SpriteFunc_34a1 + ret PokemonCenterWelcomeText: TX_FAR _PokemonCenterWelcomeText @@ -66,3 +143,7 @@ PokemonCenterFarewellText: TX_DELAY TX_FAR _PokemonCenterFarewellText db "@" + +LooksContentText: + TX_FAR _LooksContentText + db "@" diff --git a/engine/overworld/push_boulder.asm b/engine/overworld/push_boulder.asm index c91605a8..8a385345 100644 --- a/engine/overworld/push_boulder.asm +++ b/engine/overworld/push_boulder.asm @@ -2,6 +2,8 @@ TryPushingBoulder: ld a, [wd728] bit 0, a ; using Strength? ret z +Func_f0a7: +; where LoadMissableObjects predef points to now ld a, [wFlags_0xcd60] bit 1, a ; has boulder dust animation from previous push played yet? ret nz @@ -36,7 +38,7 @@ TryPushingBoulder: jp nz, ResetBoulderPushFlags ld a, [hJoyHeld] ld b, a - ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction + ld a, [wSpritePlayerStateData1FacingDirection] ; player's sprite facing direction cp SPRITE_FACING_UP jr z, .pushBoulderUp cp SPRITE_FACING_LEFT diff --git a/engine/overworld/ssanne.asm b/engine/overworld/ssanne.asm index ea4747ce..cf3b1284 100755 --- a/engine/overworld/ssanne.asm +++ b/engine/overworld/ssanne.asm @@ -7,6 +7,7 @@ AnimateBoulderDust: ld [wUpdateSpritesEnabled], a ld a, %11100100 ld [rOBP1], a + call UpdateGBCPal_OBP1 call LoadSmokeTileFourTimes callba WriteCutOrBoulderDustAnimationOAMBlock ld c, 8 ; number of steps in animation @@ -21,6 +22,7 @@ AnimateBoulderDust: ld a, [rOBP1] xor %01100100 ld [rOBP1], a + call UpdateGBCPal_OBP1 call Delay3 pop bc dec c @@ -30,7 +32,7 @@ AnimateBoulderDust: jp LoadPlayerSpriteGraphics GetMoveBoulderDustFunctionPointer: - ld a, [wSpriteStateData1 + 9] ; player's sprite facing direction + ld a, [wSpritePlayerStateData1FacingDirection] ; player's sprite facing direction ld hl, MoveBoulderDustFunctionPointerTable ld c, a ld b, $0 diff --git a/engine/overworld/tileset_header.asm b/engine/overworld/tileset_header.asm index 6e33974f..05061651 100644 --- a/engine/overworld/tileset_header.asm +++ b/engine/overworld/tileset_header.asm @@ -5,23 +5,14 @@ LoadTilesetHeader: ld a, [wCurMapTileset] add a add a - ld b, a - add a - add b ; a = tileset * 12 - jr nc, .noCarry - inc d -.noCarry ld e, a ld hl, Tilesets add hl, de + add hl, de + add hl, de ld de, wTilesetBank - ld c, $b -.copyTilesetHeaderLoop - ld a, [hli] - ld [de], a - inc de - dec c - jr nz, .copyTilesetHeaderLoop + ld bc, $b + call CopyData ld a, [hl] ld [hTilesetType], a xor a @@ -35,13 +26,13 @@ LoadTilesetHeader: call IsInArray pop de pop hl - jr c, .asm_c797 + jr c, .notDungeonTileset ld a, [wCurMapTileset] ld b, a ld a, [hPreviousTileset] cp b jr z, .done -.asm_c797 +.notDungeonTileset ld a, [wDestinationWarpID] cp $ff jr z, .done diff --git a/engine/palettes.asm b/engine/palettes.asm index 39991d48..ec9816ab 100755 --- a/engine/palettes.asm +++ b/engine/palettes.asm @@ -19,7 +19,7 @@ _RunPaletteCommand: push de jp hl -SetPal_BattleBlack: +SetPal_Black: ld hl, PalPacket_Black ld de, BlkPacket_Battle ret @@ -30,11 +30,19 @@ SetPal_Battle: ld de, wPalPacket ld bc, $10 call CopyData - ld a, [wPlayerBattleStatus3] + ;ld a, [wPlayerBattleStatus3] ld hl, wBattleMonSpecies + ld a, [hl] + and a + jr z, .asm_71ef9 + ld hl, wPartyMon1 + ld a, [wPlayerMonNumber] + ld bc, wPartyMon2 - wPartyMon1 + call AddNTimes +.asm_71ef9 call DeterminePaletteID ld b, a - ld a, [wEnemyBattleStatus3] + ;ld a, [wEnemyBattleStatus3] ld hl, wEnemyMonSpecies2 call DeterminePaletteID ld c, a @@ -110,7 +118,7 @@ SetPal_Slots: ld de, BlkPacket_Slots ret -SetPal_TitleScreen: +SetPal_Titlescreen: ld hl, PalPacket_Titlescreen ld de, BlkPacket_Titlescreen ret @@ -155,6 +163,10 @@ SetPal_Overworld: jr z, .Lorelei cp BRUNOS_ROOM jr z, .caveOrBruno + cp TRADE_CENTER + jr z, .trade_center_colosseum + cp COLOSSEUM + jr z, .trade_center_colosseum .normalDungeonOrBuilding ld a, [wLastMap] ; town or route that current dungeon or building is located .townOrRoute @@ -178,6 +190,9 @@ SetPal_Overworld: .Lorelei xor a jr .town +.trade_center_colosseum + ld a, PAL_GREYMON - 1 + jr .town ; used when a Pokemon is the only thing on the screen ; such as evolution, trading and the Hall of Fame @@ -240,14 +255,24 @@ SetPal_TrainerCard: ld de, wTrainerCardBlkPacket ret +SendUnknownPalPacket_7205d:: + ld hl, UnknownPalPacket_72811 + ld de, BlkPacket_WholeScreen + ret + +SendUnknownPalPacket_72064:: + ld hl, UnknownPalPacket_72821 + ld de, UnknownPacket_72751 + ret + SetPalFunctions: - dw SetPal_BattleBlack + dw SetPal_Black dw SetPal_Battle dw SetPal_TownMap dw SetPal_StatusScreen dw SetPal_Pokedex dw SetPal_Slots - dw SetPal_TitleScreen + dw SetPal_Titlescreen dw SetPal_NidorinoIntro dw SetPal_Generic dw SetPal_Overworld @@ -255,6 +280,8 @@ SetPalFunctions: dw SetPal_PokemonWholeScreen dw SetPal_GameFreakIntro dw SetPal_TrainerCard + dw SendUnknownPalPacket_7205d + dw SendUnknownPalPacket_72064 ; The length of the blk data of each badge on the Trainer Card. ; The Rainbow Badge has 3 entries because of its many colors. @@ -269,9 +296,6 @@ BadgeBlkDataLengths: db 6 ; Earth Badge DeterminePaletteID: - bit TRANSFORMED, a ; a is battle status 3 - ld a, PAL_GREYMON ; if the mon has used Transform, use Ditto's palette - ret nz ld a, [hl] DeterminePaletteIDOutOfBattle: ld [wd11e], a @@ -289,6 +313,132 @@ DeterminePaletteIDOutOfBattle: ld a, [hl] ret +YellowIntroPaletteAction:: + ld a, e + and a + jr nz, .asm_720bd + ld hl, PalPacket_Generic + ld a, [hGBC] + and a + jp z, SendSGBPacket + jp InitGBCPalettes + +.asm_720bd + ld hl, UnknownPalPacket_72811 + ld a, [hGBC] + and a + jp z, SendSGBPacket + call InitGBCPalettes + ld hl, PalPacket_Generic + inc hl + ld a, [hli] + call GetGBCBasePalAddress + ld a, e + ld [wGBCBasePalPointers + 2], a + ld a, d + ld [wGBCBasePalPointers + 2 + 1], a + xor a ; CONVERT_BGP + call DMGPalToGBCPal + ld a, 1 + call TransferCurBGPData + ret + +LoadOverworldPikachuFrontpicPalettes:: + ld hl, PalPacket_Empty + ld de, wPalPacket + ld bc, $10 + call CopyData + call GetPal_Pikachu + ld hl, wPartyMenuBlkPacket + ld [hl], a + ld hl, wPartyMenuBlkPacket + 2 + ld a, $26 + ld [hl], a + ld hl, wPalPacket + ld a, [hGBC] + and a + jr nz, .cgb_1 + call SendSGBPacket + jr .okay_1 + +.cgb_1 + call InitGBCPalettes +.okay_1 + ld hl, BlkPacket_WholeScreen + ld de, wPalPacket + ld bc, $10 + call CopyData + ld hl, wPartyMenuBlkPacket + 2 + ld a, $5 + ld [hli], a + ld a, $7 + ld [hli], a + ld a, $6 + ld [hli], a + ld a, $b + ld [hli], a + ld a, $a + ld [hl], a + ld hl, wPalPacket + ld a, [hGBC] + and a + jr nz, .cgb_2 + call SendSGBPacket + jr .okay_2 + +.cgb_2 + call InitGBCPalettes +.okay_2 + ret + +GetPal_Pikachu:: +; similar to SetPal_Overworld + ld a, [wCurMapTileset] + cp CEMETERY + jr z, .PokemonTowerOrAgatha + cp CAVERN + jr z, .caveOrBruno + ld a, [wCurMap] + cp REDS_HOUSE_1F + jr c, .townOrRoute + cp CERULEAN_CAVE_2F + jr c, .normalDungeonOrBuilding + cp NAME_RATERS_HOUSE + jr c, .caveOrBruno + cp LORELEIS_ROOM + jr z, .Lorelei + cp BRUNOS_ROOM + jr z, .caveOrBruno + cp TRADE_CENTER + jr z, .battleOrTradeCenter + cp COLOSSEUM + jr z, .battleOrTradeCenter +.normalDungeonOrBuilding + ld a, [wLastMap] ; town or route that current dungeon or building is located +.townOrRoute + cp SAFFRON_CITY + 1 + jr c, .town + ld a, PAL_ROUTE - 1 +.town + inc a ; a town's pallete ID is its map ID + 1 + ret + +.PokemonTowerOrAgatha + ld a, PAL_GREYMON - 1 + jr .town + +.caveOrBruno + ld a, PAL_CAVE - 1 + jr .town + +.Lorelei + xor a ; PAL_PALLET - 1 + jr .town + +.battleOrTradeCenter + ld a, PAL_GREYMON - 1 + jr .town + InitPartyMenuBlkPacket: ld hl, BlkPacket_PartyMenu ld de, wPartyMenuBlkPacket @@ -324,6 +474,14 @@ UpdatePartyMenuBlkPacket: ret SendSGBPacket: + ld a, 1 + ld [hDisableJoypadPolling], a ; don't poll joypad while sending packet + call _SendSGBPacket + xor a + ld [hDisableJoypadPolling], a + ret + +_SendSGBPacket: ;check number of packets ld a, [hl] and $07 @@ -333,9 +491,6 @@ SendSGBPacket: .loop2 ; save B for later use push bc -; disable ReadJoypad to prevent it from interfering with sending the packet - ld a, 1 - ld [hDisableJoypadPolling], a ; send RESET signal (P14=LOW, P15=LOW) xor a ld [rJOYP], a @@ -352,18 +507,18 @@ SendSGBPacket: ld d, a .nextBit0 bit 0, d -; if 0th bit is not zero set P14=HIGH,P15=LOW (send bit 1) +; if 0th bit is not zero set P14=HIGH, P15=LOW (send bit 1) ld a, $10 jr nz, .next0 -; else (if 0th bit is zero) set P14=LOW,P15=HIGH (send bit 0) +; else (if 0th bit is zero) set P14=LOW, P15=HIGH (send bit 0) ld a, $20 .next0 ld [rJOYP], a -; must set P14=HIGH,P15=HIGH between each "pulse" +; must set P14=HIGH, P15=HIGH between each "pulse" ld a, $30 ld [rJOYP], a ; rotation will put next bit in 0th position (so we can always use command -; "bit 0,d" to fetch the bit that has to be sent) +; "bit 0, d" to fetch the bit that has to be sent) rr d ; decrease bit counter so we know when we have sent all 8 bits of current byte dec e @@ -373,11 +528,9 @@ SendSGBPacket: ; send bit 1 as a "stop bit" (end of parameter data) ld a, $20 ld [rJOYP], a -; set P14=HIGH,P15=HIGH +; set P14=HIGH, P15=HIGH ld a, $30 ld [rJOYP], a - xor a - ld [hDisableJoypadPolling], a ; wait for about 70000 cycles call Wait7000 ; restore (previously pushed) number of packets @@ -392,14 +545,17 @@ LoadSGB: xor a ld [wOnSGB], a call CheckSGB - ret nc - ld a, 1 - ld [wOnSGB], a - ld a, [wGBC] + jr c, .onSGB + ld a, [hGBC] and a - jr z, .notGBC + jr z, .onDMG + ld a, $1 + ld [wOnSGB], a +.onDMG ret -.notGBC +.onSGB + ld a, $1 + ld [wOnSGB], a di call PrepareSuperNintendoVRAMTransfer ei @@ -442,23 +598,19 @@ PrepareSuperNintendoVRAMTransfer: .packetPointers ; Only the first packet is needed. dw MaskEnFreezePacket - dw DataSnd_72548 - dw DataSnd_72558 - dw DataSnd_72568 - dw DataSnd_72578 - dw DataSnd_72588 - dw DataSnd_72598 - dw DataSnd_725a8 - dw DataSnd_725b8 + dw DataSnd_728a1 + dw DataSnd_728b1 + dw DataSnd_728c1 + dw DataSnd_728d1 + dw DataSnd_728e1 + dw DataSnd_728f1 + dw DataSnd_72901 + dw DataSnd_72911 CheckSGB: ; Returns whether the game is running on an SGB in carry. ld hl, MltReq2Packet - di call SendSGBPacket - ld a, 1 - ld [hDisableJoypadPolling], a - ei call Wait7000 ld a, [rJOYP] and $3 @@ -514,6 +666,7 @@ CopyGfxToSuperNintendoVRAM: call DisableLCD ld a, $e4 ld [rBGP], a + call _UpdateGBCPal_BGP_CheckDMG ld de, vChars1 ld a, [wCopyingSGBTileData] and a @@ -544,6 +697,7 @@ CopyGfxToSuperNintendoVRAM: call SendSGBPacket xor a ld [rBGP], a + call _UpdateGBCPal_BGP_CheckDMG ei ret @@ -561,13 +715,17 @@ Wait7000: ret SendSGBPackets: - ld a, [wGBC] + ld a, [hGBC] and a jr z, .notGBC push de call InitGBCPalettes pop hl - call EmptyFunc5 + call InitGBCPalettes + ld a, [rLCDC] + and rLCDC_ENABLE_MASK + ret z + call Delay3 ret .notGBC push de @@ -576,30 +734,349 @@ SendSGBPackets: jp SendSGBPacket InitGBCPalettes: - ld a, $80 ; index 0 with auto-increment - ld [rBGPI], a - inc hl - ld c, $20 -.loop - ld a, [hli] + ld a, [hl] + and $f8 + cp $20 + jp z, TranslatePalPacketToBGMapAttributes + inc hl + +index = 0 + + REPT NUM_ACTIVE_PALS + IF index > 0 + pop hl + ENDC + + ld a, [hli] + inc hl + + IF index < (NUM_ACTIVE_PALS + -1) + push hl + ENDC + + call GetGBCBasePalAddress + ld a, e + ld [wGBCBasePalPointers + index * 2], a + ld a, d + ld [wGBCBasePalPointers + index * 2 + 1], a + + xor a ; CONVERT_BGP + call DMGPalToGBCPal + ld a, index + call TransferCurBGPData + + ld a, CONVERT_OBP0 + call DMGPalToGBCPal + ld a, index + call TransferCurOBPData + + ld a, CONVERT_OBP1 + call DMGPalToGBCPal + ld a, index + 4 + call TransferCurOBPData + +index = index + 1 + ENDR + + ret + +GetGBCBasePalAddress:: +; Input: a = palette ID +; Output: de = palette address + push hl + ld l, a + xor a + ld h, a + add hl, hl + add hl, hl + add hl, hl + ld de, GBCBasePalettes + add hl, de + ld a, l + ld e, a + ld a, h + ld d, a + pop hl + ret + +DMGPalToGBCPal:: +; Populate wGBCPal with colors from a base palette, selected using one of the +; DMG palette registers. +; Input: +; a = which DMG palette register +; de = address of GBC base palette + and a + jr nz, .notBGP + ld a, [rBGP] + ld [wLastBGP], a + jr .convert +.notBGP + dec a + jr nz, .notOBP0 + ld a, [rOBP0] + ld [wLastOBP0], a + jr .convert +.notOBP0 + ld a, [rOBP1] + ld [wLastOBP1], a +.convert +color_index = 0 + REPT NUM_COLORS + ld b, a + and %11 + call .GetColorAddress + ld a, [hli] + ld [wGBCPal + color_index * 2], a + ld a, [hl] + ld [wGBCPal + color_index * 2 + 1], a + + IF color_index < (NUM_COLORS + -1) + ld a, b + rrca + rrca + ENDC + +color_index = color_index + 1 + ENDR + ret + +.GetColorAddress: + add a + ld l, a + xor a + ld h, a + add hl, de + ret + +TransferCurBGPData:: + push de add a add a add a - ld de, SuperPalettes - add e - jr nc, .noCarry - inc d -.noCarry + or $80 ; auto-increment + ld [rBGPI], a + ld de, rBGPD + ld hl, wGBCPal + ld b, %10 ; mask for non-V-blank/non-H-blank STAT mode + ld a, [rLCDC] + and rLCDC_ENABLE_MASK + jr nz, .lcdEnabled + rept NUM_COLORS + call TransferPalColorLCDDisabled + endr + jr .done +.lcdEnabled + rept NUM_COLORS + call TransferPalColorLCDEnabled + endr +.done + pop de + ret + +BufferBGPPal:: +; Copy wGBCPal to palette a in wBGPPalsBuffer. + push de + add a + add a + add a + ld l, a + xor a + ld h, a + ld de, wBGPPalsBuffer + add hl, de + ld de, wGBCPal + ld c, PAL_SIZE +.loop ld a, [de] - ld [rBGPD], a + ld [hli], a + inc de + dec c + jr nz, .loop + pop de + ret + +TransferBGPPals:: +; Transfer the buffered BG palettes. + ld a, [rLCDC] + and rLCDC_ENABLE_MASK + jr z, .lcdDisabled + di +.waitLoop + ld a, [rLY] + cp 144 + jr c, .waitLoop +.lcdDisabled + call .DoTransfer + ei + ret + +.DoTransfer: + xor a + or $80 ; auto-increment + ld [rBGPI], a + ld de, rBGPD + ld hl, wBGPPalsBuffer + ld c, 4 * PAL_SIZE +.loop + ld a, [hli] + ld [de], a dec c jr nz, .loop ret -EmptyFunc5: +TransferCurOBPData: + push de + add a + add a + add a + or $80 ; auto-increment + ld [rOBPI], a + ld de, rOBPD + ld hl, wGBCPal + ld b, %10 ; mask for non-V-blank/non-H-blank STAT mode + ld a, [rLCDC] + and rLCDC_ENABLE_MASK + jr nz, .lcdEnabled + rept NUM_COLORS + call TransferPalColorLCDDisabled + endr + jr .done +.lcdEnabled + rept NUM_COLORS + call TransferPalColorLCDEnabled + endr +.done + pop de + ret + +TransferPalColorLCDEnabled: +; Transfer a palette color while the LCD is enabled. + +; In case we're already in H-blank or V-blank, wait for it to end. This is a +; precaution so that the transfer doesn't extend past the blanking period. + ld a, [rSTAT] + and b + jr z, TransferPalColorLCDEnabled + +; Wait for H-blank or V-blank to begin. +.notInBlankingPeriod + ld a, [rSTAT] + and b + jr nz, .notInBlankingPeriod +; fall through + +TransferPalColorLCDDisabled: +; Transfer a palette color while the LCD is disabled. + ld a, [hli] + ld [de], a + ld a, [hli] + ld [de], a + ret + +_UpdateGBCPal_BGP_CheckDMG:: + ld a, [hGBC] + and a + ret z +; fall through + +_UpdateGBCPal_BGP:: +index = 0 + + REPT NUM_ACTIVE_PALS + ld a, [wGBCBasePalPointers + index * 2] + ld e, a + ld a, [wGBCBasePalPointers + index * 2 + 1] + ld d, a + xor a ; CONVERT_BGP + call DMGPalToGBCPal + ld a, index + call BufferBGPPal + +index = index + 1 + ENDR + + call TransferBGPPals + ret + +_UpdateGBCPal_OBP:: +index = 0 + + REPT NUM_ACTIVE_PALS + ld a, [wGBCBasePalPointers + index * 2] + ld e, a + ld a, [wGBCBasePalPointers + index * 2 + 1] + ld d, a + ld a, c + call DMGPalToGBCPal + ld a, c + dec a + rlca + rlca + + IF index > 0 + IF index == 1 + inc a + ELSE + add index + ENDC + ENDC + + call TransferCurOBPData + +index = index + 1 + ENDR + ret +TranslatePalPacketToBGMapAttributes:: +; translate the SGB pal packets into something usable for the GBC + push hl + pop de + ld hl, PalPacketPointers + ld a, [hli] + ld c, a +.loop + ld a, e +.innerLoop + cp [hl] + jr z, .checkHighByte + inc hl + inc hl + dec c + jr nz, .innerLoop + ret +.checkHighByte +; the low byte of pointer matched, so check the high byte + inc hl + ld a, d + cp [hl] + jr z, .foundMatchingPointer + inc hl + dec c + jr nz, .loop + ret +.foundMatchingPointer + callba LoadBGMapAttributes + ret + +PalPacketPointers:: + db (palPacketPointersEnd - palPacketPointers) / 2 +palPacketPointers + dw BlkPacket_WholeScreen + dw BlkPacket_Battle + dw BlkPacket_StatusScreen + dw BlkPacket_Pokedex + dw BlkPacket_Slots + dw BlkPacket_Titlescreen + dw BlkPacket_NidorinoIntro + dw wPartyMenuBlkPacket + dw wTrainerCardBlkPacket + dw BlkPacket_GameFreakIntro + dw wPalPacket + dw UnknownPacket_72751 +palPacketPointersEnd + CopySGBBorderTiles: ; SGB tile data is stored in a 4BPP planar format. ; Each tile is 32 bytes. The first 16 bytes contain bit planes 1 and 2, while @@ -607,9 +1084,7 @@ CopySGBBorderTiles: ; This function converts 2BPP planar data into this format by mapping ; 2BPP colors 0-3 to 4BPP colors 0-3. 4BPP colors 4-15 are not used. ld b, 128 - .tileLoop - ; Copy bit planes 1 and 2 of the tile data. ld c, 16 .copyLoop diff --git a/engine/pathfinding.asm b/engine/pathfinding.asm index ba052d38..f3d23b7c 100644 --- a/engine/pathfinding.asm +++ b/engine/pathfinding.asm @@ -14,22 +14,22 @@ FindPathToPlayer: call CalcDifference ld d, a and a - jr nz, .asm_f8da + jr nz, .asm_f76a ld a, [hFindPathFlags] set 0, a ; current end of path matches the player's Y coordinate ld [hFindPathFlags], a -.asm_f8da +.asm_f76a ld a, [hFindPathXProgress] ld b, a ld a, [hNPCPlayerXDistance] ; X distance in steps call CalcDifference ld e, a and a - jr nz, .asm_f8ec + jr nz, .asm_f77c ld a, [hFindPathFlags] set 1, a ; current end of path matches the player's X coordinate ld [hFindPathFlags], a -.asm_f8ec +.asm_f77c ld a, [hFindPathFlags] cp $3 ; has the end of the path reached the player's position? jr z, .done diff --git a/engine/pikachu_emotions.asm b/engine/pikachu_emotions.asm new file mode 100755 index 00000000..1518b28e --- /dev/null +++ b/engine/pikachu_emotions.asm @@ -0,0 +1,421 @@ +IsPlayerTalkingToPikachu: + ld a, [wd436] + and a + ret z + ld a, [hSpriteIndexOrTextID] + cp $f + ret nz + call InitializePikachuTextID + xor a + ld [hSpriteIndexOrTextID], a + ld [wd436], a + ret + +InitializePikachuTextID: + ld a, $d4 ; display + ld [hSpriteIndexOrTextID], a + xor a + ld [wPlayerMovingDirection], a + ld a, $1 + ld [wAutoTextBoxDrawingControl], a + call DisplayTextID + xor a + ld [wAutoTextBoxDrawingControl], a + ret + +DoStarterPikachuEmotions: + ld e, a + ld d, 0 + add hl, de + add hl, de + ld e, [hl] + inc hl + ld d, [hl] +.loop + ld a, [de] + inc de + cp $ff + jr z, .done + ld c, a + ld b, 0 + ld hl, StarterPikachuEmotionsJumptable + add hl, bc + add hl, bc + ld a, [hli] + ld h, [hl] + ld l, a + call JumpToAddress + jr .loop + +.done + ret + +StarterPikachuEmotionsJumptable: + dw StarterPikachuEmotionCommand_nop ; 0 + dw StarterPikachuEmotionCommand_text ; 1 + dw StarterPikachuEmotionCommand_pcm ; 2 + dw StarterPikachuEmotionCommand_emote ; 3 + dw StarterPikachuEmotionCommand_movement ; 4 + dw StarterPikachuEmotionCommand_pikapic ; 5 + dw StarterPikachuEmotionCommand_subcmd ; 6 + dw StarterPikachuEmotionCommand_delay ; 7 + dw StarterPikachuEmotionCommand_nop2 ; 8 + dw StarterPikachuEmotionCommand_9 ; 9 + dw StarterPikachuEmotionCommand_nop3 ; a + +StarterPikachuEmotionCommand_nop: +StarterPikachuEmotionCommand_nop3: + ret + +StarterPikachuEmotionCommand_text: + ld a, [de] + ld l, a + inc de + ld a, [de] + ld h, a + inc de + push de + call PrintText + pop de + ret + +StarterPikachuEmotionCommand_pcm: + ld a, [de] + inc de + push de + ld e, a + nop + call PlayPikachuSoundClip_ + pop de + ret + +PlayPikachuSoundClip_: + cp $ff + ret z + callab PlayPikachuSoundClip + ret + +StarterPikachuEmotionCommand_emote: + ld a, [wUpdateSpritesEnabled] + push af + ld a, $ff + ld [wUpdateSpritesEnabled], a + ld a, [de] + inc de + push de + call ShowPikachuEmoteBubble + pop de + pop af + ld [wUpdateSpritesEnabled], a + ret + +ShowPikachuEmoteBubble: + ld [wWhichEmotionBubble], a + ld a, $f ; Pikachu + ld [wEmotionBubbleSpriteIndex], a + predef EmotionBubble + ret + +StarterPikachuEmotionCommand_movement: + ld a, [de] + inc de + ld l, a + ld a, [de] + inc de + ld h, a + push de + ld b, BANK(DoStarterPikachuEmotions) + call ApplyPikachuMovementData_ + pop de + ret + +StarterPikachuEmotionCommand_delay: + ld a, [de] + inc de + push de + ld c, a + call DelayFrames + pop de + ret + +StarterPikachuEmotionCommand_subcmd: + ld a, [de] + inc de + push de + ld e, a + ld d, 0 + ld hl, .Subcommands + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + call JumpToAddress + pop de + ret + +.Subcommands: + dw LoadPikachuSpriteIntoVRAM + dw LoadFontTilePatterns + dw Pikachu_LoadCurrentMapViewUpdateSpritesAndDelay3 + dw WaitForTextScrollButtonPress + dw PikachuPewterPokecenterCheck + dw PikachuFanClubCheck + dw PikachuBillsHouseCheck + +StarterPikachuEmotionCommand_nop2: + ret + +StarterPikachuEmotionCommand_9: + push de + call StarterPikachuEmotionCommand_turnawayfromplayer + call UpdateSprites + pop de + ret + +StarterPikachuEmotionCommand_turnawayfromplayer: + ld a, [wSpritePlayerStateData1FacingDirection] + xor $4 + ld [wSpritePikachuStateData1FacingDirection], a + ret + +DeletedFunction_fcffb: +; Inexplicably empty. + rept 5 + nop + endr + ret + +PlaySpecificPikachuEmotion: + ld a, e + jr load_expression + +TalkToPikachu: + call MapSpecificPikachuExpression + jr c, load_expression + call GetPikaPicAnimationScriptIndex + call DeletedFunction_fcffb +load_expression: + ld [wExpressionNumber], a + ld hl, PikachuEmotionTable + call DoStarterPikachuEmotions + ret + +PikachuEmotionTable: +pikaemotion_def: MACRO +\1_id: dw \1 + endm + + pikaemotion_def PikachuEmotion0 + pikaemotion_def PikachuEmotion1 + pikaemotion_def PikachuEmotion2 + pikaemotion_def PikachuEmotion3 + pikaemotion_def PikachuEmotion4 + pikaemotion_def PikachuEmotion5 + pikaemotion_def PikachuEmotion6 + pikaemotion_def PikachuEmotion7 + pikaemotion_def PikachuEmotion8 + pikaemotion_def PikachuEmotion9 + pikaemotion_def PikachuEmotion10 + pikaemotion_def PikachuEmotion11 + pikaemotion_def PikachuEmotion12 + pikaemotion_def PikachuEmotion13 + pikaemotion_def PikachuEmotion14 + pikaemotion_def PikachuEmotion15 + pikaemotion_def PikachuEmotion16 + pikaemotion_def PikachuEmotion17 + pikaemotion_def PikachuEmotion18 + pikaemotion_def PikachuEmotion19 + pikaemotion_def PikachuEmotion20 + pikaemotion_def PikachuEmotion21 ; used a fishing rod + pikaemotion_def PikachuEmotion22 + pikaemotion_def PikachuEmotion23 + pikaemotion_def PikachuEmotion24 + pikaemotion_def PikachuEmotion25 + pikaemotion_def PikachuEmotion26 ; wake up pikachu in pewter pokemon center + pikaemotion_def PikachuEmotion27 + pikaemotion_def PikachuEmotion28 + pikaemotion_def PikachuEmotion29 + pikaemotion_def PikachuEmotion30 + pikaemotion_def PikachuEmotion31 + pikaemotion_def PikachuEmotion32 + pikaemotion_def PikachuEmotion33 + +PikachuEmotion33: + db $ff + +MapSpecificPikachuExpression: + ld a, [wCurMap] + cp POKEMON_FAN_CLUB + jr nz, .notFanClub + ld hl, wd492 + bit 7, [hl] + ldpikaemotion a, PikachuEmotion29 + jr z, .play_emotion + call CheckPikachuFollowingPlayer + ldpikaemotion a, PikachuEmotion30 + jr nz, .play_emotion + jr .check_pikachu_status + +.notFanClub + ld a, [wCurMap] + cp PEWTER_POKECENTER + jr nz, .notPewterPokecenter + call CheckPikachuFollowingPlayer + ldpikaemotion a, PikachuEmotion26 + jr nz, .play_emotion + jr .check_pikachu_status + +.notPewterPokecenter + callab Func_f24ae + ld a, e + cp $ff + jr nz, .play_emotion + jr .check_pikachu_status ; useless + +.check_pikachu_status + call IsPlayerPikachuAsleepInParty + ldpikaemotion a, PikachuEmotion11 + jr c, .play_emotion + callab CheckPikachuFaintedOrStatused ; same bank + ldpikaemotion a, PikachuEmotion28 + jr c, .play_emotion + ld a, [wCurMap] + cp POKEMON_TOWER_1F + jr c, .notInLavenderTower + cp POKEMON_TOWER_7F + 1 + ldpikaemotion a, PikachuEmotion22 + jr c, .play_emotion +.notInLavenderTower + ld a, [wd49c] + and a + jr z, .mood_based_emotion + dec a + ld c, a + ld b, $0 + ld hl, .Emotions + add hl, bc + ld a, [hl] + jr .play_emotion + +.mood_based_emotion + and a + ret + +.play_emotion + scf + ret + +.Emotions: + dpikaemotion PikachuEmotion18 + dpikaemotion PikachuEmotion21 + dpikaemotion PikachuEmotion23 + dpikaemotion PikachuEmotion24 + dpikaemotion PikachuEmotion25 + +IsPlayerPikachuAsleepInParty: + xor a + ld [wWhichPokemon], a +.loop + ld a, [wWhichPokemon] + ld c, a + ld b, 0 + ld hl, wPartySpecies + add hl, bc + ld a, [hl] + cp $ff + jr z, .done + cp PIKACHU + jr nz, .curMonNotStarterPikachu + callab IsThisPartymonStarterPikachu + jr nc, .curMonNotStarterPikachu + ld a, [wWhichPokemon] + ld hl, wPartyMon1Status + ld bc, wPartyMon2 - wPartyMon1 + call AddNTimes + ld a, [hl] + and SLP + jr z, .done + jr .curMonSleepingPikachu + +.curMonNotStarterPikachu + ld a, [wWhichPokemon] + cp PARTY_LENGTH - 1 + jr z, .done + inc a + ld [wWhichPokemon], a + jr .loop + +.curMonSleepingPikachu + scf + ret + +.done + and a + ret + +INCLUDE "data/pikachu_emotions.asm" + +PikachuWalksToNurseJoy: + ld a, $40 + ld [h_0xFFFC], a + call LoadPikachuSpriteIntoVRAM + call .GetMovementData + and a + jr z, .skip + call ApplyPikachuMovementData +.skip + xor a + ld [h_0xFFFC], a + ret + +.GetMovementData: + ld a, [wSpritePikachuStateData2MapY] + ld e, a + ld a, [wSpritePikachuStateData2MapX] + ld d, a + ld a, [wYCoord] + add 4 + cp e + jr z, .pikachu_at_same_y_as_player + jr nc, .pikachu_above_player + ld hl, .PikaMovementData1 + ld a, 1 + ret + +.pikachu_above_player + xor a + ret + +.pikachu_at_same_y_as_player + ld a, [wXCoord] + add 4 + cp d + jr c, .pikachu_to_right_of_player + ld hl, .PikaMovementData2 + ld a, 2 + ret + +.pikachu_to_right_of_player + ld hl, .PikaMovementData3 + ld a, 3 + ret + +.PikaMovementData1: + db $00 ; init + db $36 ; look up + db $2b ; walk up left + db $34 ; hop up right + db $3f ; ret + +.PikaMovementData2: + db $00 ; init + db $36 ; look up + db $34 ; hop up right + db $3f ; ret + +.PikaMovementData3: + db $00 ; init + db $36 ; look up + db $33 ; hop up left + db $3f ; ret diff --git a/engine/pikachu_follow.asm b/engine/pikachu_follow.asm new file mode 100755 index 00000000..d9dc91df --- /dev/null +++ b/engine/pikachu_follow.asm @@ -0,0 +1,1578 @@ +ShouldPikachuSpawn:: +; possibly to test if pika should be out? + ld a, [wPikachuOverworldStateFlags] + bit 5, a + jr nz, .hide + ld a, [wPikachuOverworldStateFlags] + bit 7, a + jr nz, .hide + call IsStarterPikachuInOurParty + jr nc, .hide + ld a, [wWalkBikeSurfState] + and a + jr nz, .hide + scf + ret + +.hide + and a + ret + +SchedulePikachuSpawnForAfterText:: + ld hl, wPikachuOverworldStateFlags + bit 4, [hl] + res 4, [hl] + jr nz, .normal_spawn_state + call EnablePikachuFollowingPlayer + call ClearPikachuSpriteStateData + ld a, $ff + ld [wSpritePikachuStateData1ImageIndex], a + call ClearPikachuFollowCommandBuffer + call CalculatePikachuFacingDirection + ret + +.normal_spawn_state + call CalculatePikachuPlacementCoords + xor a + ld [wPikachuSpawnState], a + ld a, [wSpritePlayerStateData1FacingDirection] + ld [wSpritePikachuStateData1FacingDirection], a + ret + +ClearPikachuSpriteStateData:: + ld hl, wSpritePikachuStateData1PictureID + call .clear + ld hl, wSpritePikachuStateData2 +.clear + ld bc, $10 + xor a + call FillMemory + ret + +CalculatePikachuSpawnCoordsAndFacing:: + call CalculatePikachuPlacementCoords + call CalculatePikachuFacingDirection + xor a + ld [wPikachuSpawnState], a + ret + +CalculatePikachuPlacementCoords:: + ld bc, wSpritePikachuStateData1PictureID + ld a, [wYCoord] + add $4 + ld e, a + ld a, [wXCoord] + add $4 + ld d, a + ld a, [wPikachuSpawnState] + and a + jr z, .load_coords + cp $1 + jr z, .right_of_player + cp $2 + jr z, .check_player_facing2 + cp $3 + jr z, .load_coords + cp $4 + jr z, .below_player + cp $5 + jr z, .above_player + cp $6 + jr z, .left_of_player + cp $7 + jr z, .check_player_facing + jr .right_of_player + +.check_player_facing + ld a, [wSpritePlayerStateData1FacingDirection] + and a ; SPRITE_FACING_DOWN + jr z, .below_player + cp SPRITE_FACING_UP + jr z, .above_player + cp SPRITE_FACING_LEFT + jr z, .left_of_player + cp SPRITE_FACING_RIGHT + jr z, .right_of_player +.check_player_facing2 + ld a, [wSpritePlayerStateData1FacingDirection] + and a + jr nz, .check_up + dec e + jr .load_coords + +.check_up + cp SPRITE_FACING_UP + jr nz, .check_left + inc e + jr .load_coords + +.check_left + cp SPRITE_FACING_LEFT + jr nz, .left_of_player_2 + inc d + jr .load_coords + +.left_of_player_2 + dec d + jr .load_coords + +.right_of_player + inc d + jr .load_coords + +.left_of_player + dec d + jr .load_coords + +.below_player + inc e + jr .load_coords + +.above_player + dec e + jr .load_coords ; useless jr +.load_coords + ld hl, wSpritePlayerStateData2MapY - wSpritePlayerStateData1 + add hl, bc + ld [hl], e + inc hl + ld [hl], d + inc hl + ld [hl], $fe + push hl + ld hl, wd472 + set 5, [hl] + pop hl + ret + +CalculatePikachuFacingDirection:: + ld a, $49 + ld [wSpritePikachuStateData1PictureID], a + ld a, $ff + ld [wSpritePikachuStateData1ImageIndex], a + ld a, [wPikachuSpawnState] + and a + jr z, .copy_player_facing + cp $1 + jr z, .copy_player_facing + cp $3 + jr z, .force_facing_down + cp $4 + jr z, .copy_player_facing + cp $6 + jr z, .copy_player_facing + cp $7 + jr z, .face_the_other_way + call ComputePikachuFacingDirection + ret + +.copy_player_facing + ld a, [wSpritePlayerStateData1FacingDirection] + ld [wSpritePikachuStateData1FacingDirection], a + ret + +.force_facing_down + ld a, SPRITE_FACING_DOWN + ld [wSpritePikachuStateData1FacingDirection], a + ret + +.face_the_other_way + ld a, [wSpritePlayerStateData1FacingDirection] + xor $4 + ld [wSpritePikachuStateData1FacingDirection], a + ret + +SetPikachuSpawnOutside:: + ld a, [wCurMap] + cp OAKS_LAB + jr z, .oaks_lab + cp ROUTE_22_GATE + jr z, .route_22_gate + cp MT_MOON_B1F + jr z, .mt_moon_2 + cp ROCK_TUNNEL_1F + jr z, .rock_tunnel_1 + ld a, [wCurMap] + ld hl, Pointer_fc64b + call Pikachu_IsInArray ; similar to IsInArray, but not the same + jr c, .map_list_1 + ld a, [wCurMap] + ld hl, Pointer_fc653 + call Pikachu_IsInArray + jr nc, .not_map_list_2 + ld a, [wSpritePlayerStateData1FacingDirection] + and a + jr nz, .not_map_list_2 + ld a, $3 + jr .load + +.route_22_gate + ld a, [wSpritePlayerStateData1FacingDirection] + and a + jr z, .rock_tunnel_1 + jr .not_map_list_2 + +.mt_moon_2 + ld a, $3 + jr .load + +.map_list_1 + ld a, $4 + jr .load + +.oaks_lab + ld a, $6 + jr .load + +.not_map_list_2 + ld a, $1 + jr .load + +.rock_tunnel_1 + ld a, $3 +.load + ld [wPikachuSpawnState], a + ret + +Pointer_fc64b:: + db VICTORY_ROAD_2F + db ROUTE_7_GATE + db ROUTE_8_GATE + db ROUTE_16_GATE_1F + db ROUTE_18_GATE_1F + db ROUTE_15_GATE_1F + db ROUTE_11_GATE_1F + db $ff + +Pointer_fc653:: + db VIRIDIAN_FOREST_NORTH_GATE + db CERULEAN_BADGE_HOUSE + db CERULEAN_TRASHED_HOUSE + db VERMILION_DOCK + db CELADON_MANSION_1F + db ROUTE_2_GATE + db FUCHSIA_GOOD_ROD_HOUSE + db $ff + +SetPikachuSpawnWarpPad:: + ld a, [wCurMap] + cp VIRIDIAN_FOREST_NORTH_GATE + jr z, .viridian_forest_exit + cp VIRIDIAN_FOREST_SOUTH_GATE + jr z, .viridian_forest_entrance + ld a, [wCurMap] + ld hl, Pointer_fc68e + call Pikachu_IsInArray + jr c, .in_array + jr .not_in_array + +.viridian_forest_exit + ld a, [wSpritePlayerStateData1FacingDirection] + cp SPRITE_FACING_UP + jr z, .in_array + jr .not_in_array + +.viridian_forest_entrance + ld a, [wSpritePlayerStateData1FacingDirection] + and a ; SPRITE_FACING_DOWN + jr z, .not_in_array + jr .in_array + +.not_in_array + ld a, $0 + jr .load_spawn_state + +.in_array + ld a, $1 +.load_spawn_state + ld [wPikachuSpawnState], a + ret + +Pointer_fc68e:: + db VIRIDIAN_FOREST + db SAFARI_ZONE_CENTER_REST_HOUSE + db SAFARI_ZONE_WEST_REST_HOUSE + db SAFARI_ZONE_EAST_REST_HOUSE + db SAFARI_ZONE_NORTH_REST_HOUSE + db SAFARI_ZONE_SECRET_HOUSE + db SILPH_CO_ELEVATOR + db CELADON_MART_ELEVATOR + db CINNABAR_LAB_TRADE_ROOM + db CINNABAR_LAB_METRONOME_ROOM + db CINNABAR_LAB_FOSSIL_ROOM + db $ff + +SetPikachuSpawnBackOutside:: + ld a, [wCurMap] + cp ROUTE_22_GATE + jr z, .asm_fc6a7 + cp ROUTE_2_GATE + jr z, .asm_fc6b0 + jr .asm_fc6bd + +.asm_fc6a7 + ld a, [wSpritePlayerStateData1FacingDirection] + cp SPRITE_FACING_UP + jr z, .asm_fc6b9 + jr .asm_fc6bd + +.asm_fc6b0 + ld a, [wSpritePlayerStateData1FacingDirection] + cp SPRITE_FACING_UP + jr z, .asm_fc6b9 + jr .asm_fc6bd + +.asm_fc6b9 + ld a, $1 + jr .asm_fc6c1 + +.asm_fc6bd + ld a, $3 + jr .asm_fc6c1 + +.asm_fc6c1 + ld [wPikachuSpawnState], a + ret + +SetPikachuOverworldStateFlag2:: + push hl + ld hl, wPikachuOverworldStateFlags + set 2, [hl] + pop hl + ret + +ResetPikachuOverworldStateFlag2:: + push hl + ld hl, wPikachuOverworldStateFlags + res 2, [hl] + pop hl + ret + +SpawnPikachu_:: + call ResetPikachuOverworldStateFlag2 + call TrySpawnPikachu + ret nc + + push bc + call WillPikachuSpawnOnTheScreen + pop bc + ret c + + ld bc, wSpritePikachuStateData1 + ld hl, wSpritePikachuStateData1MovementStatus - wSpritePikachuStateData1 + add hl, bc + bit 7, [hl] + jp nz, Func_fc745 + ld a, [wFontLoaded] + bit 0, a + jp nz, Func_fc76a + call CheckPikachuFollowingPlayer + jp nz, Func_fc76a + ld a, [hl] + and $7f + cp $a + jr c, .valid + xor a +.valid + add a + ld e, a + ld d, 0 + ld hl, PointerTable_fc710 + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + jp hl + +PointerTable_fc710: + dw Func_fc793 + dw Func_fc7aa + dw Func_fc803 + dw asm_fc9c3 + dw asm_fca1c + dw asm_fc9ee + dw asm_fc87f + dw asm_fc904 + dw asm_fc937 + dw asm_fc969 + dw .nop + +.nop: + ret + +TrySpawnPikachu: + call ShouldPikachuSpawn + jr nc, .dont_spawn + ld a, [wSpritePikachuStateData1MovementStatus] + and a + jr nz, .already_spawned + push bc + push hl + call CalculatePikachuSpawnCoordsAndFacing + pop hl + pop bc +.already_spawned + scf + ret + +.dont_spawn + ld hl, wSpritePikachuStateData1ImageIndex + ld [hl], $ff + dec hl + ld [hl], $0 + xor a + ret + +Func_fc745: + ld hl, wSpritePikachuStateData1MovementStatus - wSpritePikachuStateData1 + add hl, bc + res 7, [hl] + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + ld [hl], a + call CheckPikachuFollowingPlayer + jr nz, .okay + ; Have Pikachu face in the opposite direction of you + ld a, [wSpritePlayerStateData1FacingDirection] + xor $4 + ld hl, wSpritePikachuStateData1FacingDirection - wSpritePikachuStateData1 + add hl, bc + ld [hl], a +.okay + xor a + ld hl, wSpritePikachuStateData1IntraAnimFrameCounter - wSpritePikachuStateData1 + add hl, bc + ld [hli], a + ld [hl], a + call UpdatePikachuWalkingSprite + ret + +Func_fc76a: + xor a + ld hl, wSpritePikachuStateData1IntraAnimFrameCounter - wSpritePikachuStateData1 + add hl, bc + ld [hli], a + ld [hl], a + call UpdatePikachuWalkingSprite + call Func_fc82e + jr c, .skip + push bc + callab InitializeSpriteScreenPosition + pop bc +.skip + ld hl, wSpritePikachuStateData1MovementStatus - wSpritePikachuStateData1 + add hl, bc + ld [hl], $1 + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + ld [hl], $0 + call RefreshPikachuFollow + ret + +Func_fc793: + call RefreshPikachuFollow + push bc + callab InitializeSpriteScreenPosition + pop bc + ld hl, wSpritePikachuStateData1ImageIndex - wSpritePikachuStateData1 + add hl, bc + ld [hl], $ff + dec hl + ld [hl], $1 + ret + +Func_fc7aa: + call Func_fcc92 + jp c, Func_fc803 + dec a + ld l, a + ld h, $0 + add hl, hl + add hl, hl + ld de, Pointer_fc7e3 + add hl, de + ld d, h + ld e, l + ld a, [de] + inc de + ld hl, wSpritePikachuStateData1FacingDirection - wSpritePikachuStateData1 + add hl, bc + ld [hl], a + ld a, [de] + inc de + ld hl, wSpritePikachuStateData1XStepVector - wSpritePikachuStateData1 + add hl, bc + ld [hl], a + dec hl + dec hl + ld a, [de] + ld [hl], a + inc de + ld a, [de] + ld hl, wSpritePikachuStateData1MovementStatus - wSpritePikachuStateData1 + add hl, bc + ld [hl], a + cp $4 + jp z, Func_fca0a + call AreThereAtLeastTwoStepsInPikachuFollowCommandBuffer + jp c, FastPikachuFollow + jp NormalPikachuFollow + +Pointer_fc7e3: + db 0, 0 + db 1, 3 + db 4, 0 + db -1, 3 + db 8, -1 + db 0, 3 + db 12, 1 + db 0, 3 + db 0, 0 + db 1, 4 + db 4, 0 + db -1, 4 + db 8, -1 + db 0, 4 + db 12, 1 + db 0, 4 + +Func_fc803: + call Func_fcae2 + ret c + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + dec [hl] + jr nz, .asm_fc823 + push hl + call GetPikachuFollowCommand + pop hl + cp $5 + jr nc, Func_fc842 + ld [hl], $20 + call Random + and $c + ld hl, wSpritePikachuStateData1FacingDirection - wSpritePikachuStateData1 + add hl, bc + ld [hl], a +.asm_fc823 + xor a + ld hl, wSpritePikachuStateData1IntraAnimFrameCounter - wSpritePikachuStateData1 + add hl, bc + ld [hli], a + ld [hl], a + call UpdatePikachuWalkingSprite + ret + +Func_fc82e: + ld a, [wWalkCounter] + and a + ret z + scf + ret + +Func_fc835: + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + ld [hl], $10 + ld hl, wSpritePikachuStateData1MovementStatus - wSpritePikachuStateData1 + add hl, bc + ld [hl], $1 + ret + +Func_fc842: + ld hl, $0 + push af + call Random + ld a, [hRandomAdd] + and %11 + ld e, a + ld d, $0 + ld hl, PointerTable_fc85a + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + pop af + jp hl + +PointerTable_fc85a: + dw Func_fc862 + dw Func_fc8f8 + dw Func_fc92b + dw Func_fc95d + +Func_fc862: + dec a + add a + add a + and $c + ld hl, wSpritePikachuStateData1FacingDirection - wSpritePikachuStateData1 + add hl, bc + ld [hl], a + ld hl, wSpritePikachuStateData1MovementStatus - wSpritePikachuStateData1 + add hl, bc + ld [hl], $6 + xor a + ld [wd432], a + ld [wd433], a + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + ld [hl], $11 +asm_fc87f: + ld a, [wd432] + ld e, a + ld a, [wd433] + ld d, a + call Func_fc82e + jr c, Func_fc8c7 + call SetPikachuOverworldStateFlag2 + ld hl, wSpritePikachuStateData1YPixels - wSpritePikachuStateData1 + add hl, bc + ld a, [hl] + sub e + ld e, a + inc hl + inc hl + ld a, [hl] + sub d + ld d, a + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + ld a, [hl] + dec a + add a + add Pointer_fc8d6 % $100 + ld l, a + ld a, Pointer_fc8d6 / $100 + adc $0 + ld h, a + ld a, [hli] + ld [wd432], a + add e + ld e, a + ld a, [hl] + ld [wd433], a + add d + ld d, a + ld hl, wSpritePikachuStateData1YPixels - wSpritePikachuStateData1 + add hl, bc + ld [hl], e + inc hl + inc hl + ld [hl], d + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + dec [hl] + ret nz + jp Func_fc835 + +Func_fc8c7: + ld hl, wSpritePikachuStateData1YPixels - wSpritePikachuStateData1 + add hl, bc + ld a, [hl] + sub e + ld [hl], a + inc hl + inc hl + ld a, [hl] + sub d + ld [hl], a + jp Func_fc835 + +Pointer_fc8d6: + db 0, 0 + db -2, 1 + db -4, 2 + db -2, 3 + db 0, 4 + db -2, 3 + db -4, 2 + db -2, 1 + db 0, 0 + db -2, -1 + db -4, -2 + db -2, -3 + db 0, -4 + db -2, -3 + db -4, -2 + db -2, -1 + db 0, 0 + +Func_fc8f8: + ld hl, wSpritePikachuStateData1MovementStatus - wSpritePikachuStateData1 + add hl, bc + ld [hl], $7 + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + ld [hl], $30 +asm_fc904: + call Func_fc82e + jp c, Func_fc835 + call SetPikachuOverworldStateFlag2 + ld hl, wSpritePikachuStateData1IntraAnimFrameCounter - wSpritePikachuStateData1 + add hl, bc + ld a, [hl] + inc a + cp $8 + ld [hl], a + jr nz, .asm_fc91f + xor a + ld [hli], a + ld a, [hl] + inc a + and %11 + ld [hl], a +.asm_fc91f + call UpdatePikachuWalkingSprite + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + dec [hl] + ret nz + jp Func_fc835 + +Func_fc92b: + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + ld [hl], $20 + ld hl, wSpritePikachuStateData1MovementStatus - wSpritePikachuStateData1 + add hl, bc + ld [hl], $8 +asm_fc937: + call Func_fc82e + jp c, Func_fc835 + call SetPikachuOverworldStateFlag2 + ld hl, wSpritePikachuStateData1IntraAnimFrameCounter - wSpritePikachuStateData1 + add hl, bc + ld a, [hl] + inc a + cp $8 + ld [hl], a + jr nz, .asm_fc951 + xor a + ld [hli], a + ld a, [hl] + xor $1 + ld [hl], a +.asm_fc951 + call UpdatePikachuWalkingSprite + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + dec [hl] + ret nz + jp Func_fc835 + +Func_fc95d: + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + ld [hl], $20 + ld hl, wSpritePikachuStateData1MovementStatus - wSpritePikachuStateData1 + add hl, bc + ld [hl], $9 +asm_fc969: + call Func_fc82e + jp c, Func_fc835 + call SetPikachuOverworldStateFlag2 + ld hl, wSpritePikachuStateData1IntraAnimFrameCounter - wSpritePikachuStateData1 + add hl, bc + ld a, [hl] + inc a + cp $8 + ld [hl], a + jr nz, .skip + xor a + ld [hl], a + ld hl, wSpritePikachuStateData1FacingDirection - wSpritePikachuStateData1 + add hl, bc + ld a, [hl] + call .TurnClockwise + ld [hl], a +.skip + call UpdatePikachuWalkingSprite + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + dec [hl] + ret nz + jp Func_fc835 + +.TurnClockwise: + push hl + ld hl, .Facings + ld d, a +.loop + ld a, [hli] + cp d + jr nz, .loop + ld a, [hl] + pop hl + ret + +.TurnCounterclockwise: + push hl + ld hl, .Facings_End + ld d, a +.loop_ + ld a, [hld] + cp d + jr nz, .loop_ + ld a, [hl] + pop hl + ret + +.Facings: + db SPRITE_FACING_DOWN, SPRITE_FACING_LEFT, SPRITE_FACING_UP, SPRITE_FACING_RIGHT + db SPRITE_FACING_DOWN, SPRITE_FACING_LEFT, SPRITE_FACING_UP, SPRITE_FACING_RIGHT +.Facings_End: + +NormalPikachuFollow: + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + ld [hl], $8 + ld hl, wSpritePikachuStateData1MovementStatus - wSpritePikachuStateData1 + add hl, bc + ld [hl], $3 + call AddPikachuStepVector +asm_fc9c3: + call TryDoubleAddPikachuStepVectorToScreenPixelCoords + call GetPikachuWalkingAnimationSpeed + call UpdatePikachuWalkingSprite + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + dec [hl] + ret nz + call ResetPikachuStepVector + call ComputePikachuFacingDirection + ld hl, wSpritePikachuStateData1MovementStatus - wSpritePikachuStateData1 + add hl, bc + ld [hl], $1 + ret + +FastPikachuFollow: + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + ld [hl], $4 + ld hl, wSpritePikachuStateData1MovementStatus - wSpritePikachuStateData1 + add hl, bc + ld [hl], $5 + call AddPikachuStepVector +asm_fc9ee: + call DoubleAddPikachuStepVectorToScreenPixelCoords + call GetPikachuWalkingAnimationSpeed + call UpdatePikachuWalkingSprite + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + dec [hl] + ret nz + call ResetPikachuStepVector + call ComputePikachuFacingDirection + ld hl, wSpritePikachuStateData1MovementStatus - wSpritePikachuStateData1 + add hl, bc + ld [hl], $1 + ret + +Func_fca0a: + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + ld [hl], $8 + ld hl, wSpritePikachuStateData1MovementStatus - wSpritePikachuStateData1 + add hl, bc + ld [hl], $4 + call AddPikachuStepVector + call AddPikachuStepVector +asm_fca1c: + call DoubleAddPikachuStepVectorToScreenPixelCoords + call GetPikachuWalkingAnimationSpeed + call UpdatePikachuWalkingSprite + ld hl, wSpritePikachuStateData2WalkAnimationCounter - wSpritePikachuStateData1 + add hl, bc + dec [hl] + ret nz + call ResetPikachuStepVector + call ComputePikachuFacingDirection + ld hl, wSpritePikachuStateData1MovementStatus - wSpritePikachuStateData1 + add hl, bc + ld [hl], $1 + ret + +AddPikachuStepVector: + ld hl, wSpritePikachuStateData1YStepVector - wSpritePikachuStateData1 + add hl, bc + ld e, [hl] + inc hl + inc hl + ld d, [hl] + ld hl, wSpritePikachuStateData2MapY - wSpritePikachuStateData1 + add hl, bc + ld a, [hl] + add e + ld [hli], a + ld a, [hl] + add d + ld [hl], a + ret + +TryDoubleAddPikachuStepVectorToScreenPixelCoords: + ld a, [wWalkBikeSurfState] + cp $1 ; biking + jr nz, AddPikachuStepVectorToScreenPixelCoords + ld a, [wd736] + bit 6, a + jr nz, AddPikachuStepVectorToScreenPixelCoords +DoubleAddPikachuStepVectorToScreenPixelCoords: + ld hl, wSpritePikachuStateData1YStepVector - wSpritePikachuStateData1 + add hl, bc + ld a, [hli] + add a + add a + add [hl] + ld [hli], a + ld a, [hli] + add a + add a + add [hl] + ld [hl], a + ret + +AddPikachuStepVectorToScreenPixelCoords: + ld hl, wSpritePikachuStateData1YStepVector - wSpritePikachuStateData1 + add hl, bc + ld a, [hli] + add a + add [hl] + ld [hli], a + ld a, [hli] + add a + add [hl] + ld [hli], a + ret + +ResetPikachuStepVector: + ld hl, wSpritePikachuStateData1YStepVector - wSpritePikachuStateData1 + add hl, bc + xor a + ld [hli], a + inc hl + ld [hl], a + ret + +GetPikachuWalkingAnimationSpeed: + call ComparePikachuHappinessTo80 + ld d, $2 + jr nc, .happy + ld d, $5 +.happy + ld hl, wSpritePikachuStateData1IntraAnimFrameCounter - wSpritePikachuStateData1 + add hl, bc + ld a, [hl] + inc a + cp d + jr nz, .dont_reset + xor a +.dont_reset + ld [hli], a + ret nz + ld a, [hl] + inc a + and $3 + ld [hl], a + ret + +UpdatePikachuWalkingSprite: + ld a, [wPikachuOverworldStateFlags] + bit 3, a + jr nz, .uninitialized + ld hl, wSpritePikachuStateData2ImageBaseOffset - wSpritePikachuStateData1 + add hl, bc + ld a, [hl] + dec a + swap a + ld d, a + ld a, [wd736] + bit 7, a + jr nz, .copy_player + ld hl, wSpritePikachuStateData1FacingDirection - wSpritePikachuStateData1 + add hl, bc + ld a, [hl] + or d + ld d, a + ld a, [wFontLoaded] + bit 0, a + jr z, .normal_get_sprite_index + call Func_fcae2 + ret c + jr .load_sprite_index + +.normal_get_sprite_index + ld hl, wSpritePikachuStateData1AnimFrameCounter - wSpritePikachuStateData1 + add hl, bc + ld a, d + or [hl] + ld d, a +.load_sprite_index + ld hl, wSpritePikachuStateData1ImageIndex - wSpritePikachuStateData1 + add hl, bc + ld [hl], d + ret + +.uninitialized + ld hl, wSpritePikachuStateData1ImageIndex - wSpritePikachuStateData1 + add hl, bc + ld [hl], $ff + ret + +.copy_player + ld a, [wSpritePlayerStateData1ImageIndex] + and $f + or d + ld [wSpritePikachuStateData1ImageIndex], a + ret + +Func_fcae2: + ld hl, wSpritePikachuStateData2MapY - wSpritePikachuStateData1 + add hl, bc + ld a, [wYCoord] + add $4 + cp [hl] + jr nz, .on_screen + inc hl + ld a, [wXCoord] + add $4 + cp [hl] + jr nz, .on_screen + ld hl, wSpritePikachuStateData1ImageIndex - wSpritePikachuStateData1 + add hl, bc + ld [hl], $ff + scf + ret + +.on_screen + and a + ret + +IsPikachuRightNextToPlayer: + push bc + push de + push hl + ld bc, wSpritePikachuStateData1PictureID + ld a, [wXCoord] + add $4 + ld d, a + ld a, [wYCoord] + add $4 + ld e, a + ld hl, wSpritePlayerStateData2MapY - wSpritePlayerStateData1 + add hl, bc + ld a, [hl] + sub e + and a + jr z, .equal + cp $ff + jr z, .one_away + cp $1 + jr z, .one_away + jr .bad + +.one_away + ld hl, wSpritePlayerStateData2MapX - wSpritePlayerStateData1 + add hl, bc + ld a, [hl] + sub d + jr z, .good + jr .bad + +.equal + ld hl, wSpritePlayerStateData2MapX - wSpritePlayerStateData1 + add hl, bc + ld a, [hl] + sub d + cp $ff + jr z, .good + cp $1 + jr z, .good + and a + jr z, .good + jr .bad + +.good + pop hl + pop de + pop bc + scf + ret + +.bad + pop hl + pop de + pop bc + xor a + ret + +GetPikachuFacingDirectionAndReturnToE: + call GetPikachuFacingDirection + ld e, a + ret + +GetPikachuFacingDirection: + ld bc, wSpritePikachuStateData1PictureID + ld a, [wXCoord] + add $4 + ld d, a + ld a, [wYCoord] + add $4 + ld e, a + ld hl, wSpritePlayerStateData2MapY - wSpritePlayerStateData1 + add hl, bc + ld a, [hl] + cp e + jr z, .asm_fcb71 + jr nc, .asm_fcb6e + ld a, SPRITE_FACING_UP + ret + +.asm_fcb6e + ld a, SPRITE_FACING_DOWN + ret + +.asm_fcb71 + ld hl, wSpritePlayerStateData2MapX - wSpritePlayerStateData1 + add hl, bc + ld a, [hl] + cp d + jr z, .asm_fcb81 + jr nc, .asm_fcb7e + ld a, SPRITE_FACING_LEFT + ret + +.asm_fcb7e + ld a, SPRITE_FACING_RIGHT + ret + +.asm_fcb81 + ld a, $ff ; standing + ret + +ClearPikachuFollowCommandBuffer: + push bc + ld hl, wPikachuFollowCommandBufferSize + ld [hl], $ff + inc hl + ld bc, $10 + xor a + call FillMemory + pop bc + ret + +AppendPikachuFollowCommandToBuffer: + ld hl, wPikachuFollowCommandBufferSize + inc [hl] + ld e, [hl] + ld d, 0 + ld hl, wPikachuFollowCommandBuffer + add hl, de + ld [hl], a + ret + +RefreshPikachuFollow: + call ClearPikachuFollowCommandBuffer + call ComputePikachuFollowCommand + ret c + call AppendPikachuFollowCommandToBuffer + ret + +ComputePikachuFollowCommand: + ld bc, wSpritePikachuStateData1PictureID + ld hl, wSpritePlayerStateData2MapY - wSpritePlayerStateData1 + add hl, bc + ld a, [wYCoord] + add $4 + sub [hl] + jr z, .checkXCoord + jr c, .pikaAbovePlayer + call CheckAbsoluteValueLessThan2 + jr c, .return1 + ld a, $5 + and a + ret + +.return1 + ld a, $1 + and a + ret + +.pikaAbovePlayer + call CheckAbsoluteValueLessThan2 + jr c, .return2 + ld a, $6 + and a + ret + +.return2 + ld a, $2 + and a + ret + +.checkXCoord + ld hl, wSpritePlayerStateData2MapX - wSpritePlayerStateData1 + add hl, bc + ld a, [wXCoord] + add $4 + sub [hl] + jr z, .pikachuOnTopOfPlayer + jr c, .pikaToLeftOfPlayer + call CheckAbsoluteValueLessThan2 + jr c, .return4 + ld a, $8 + and a + ret + +.return4 + ld a, $4 + and a + ret + +.pikaToLeftOfPlayer + call CheckAbsoluteValueLessThan2 + jr c, .return3 + ld a, $7 + and a + ret + +.return3 + ld a, $3 + and a + ret + +.pikachuOnTopOfPlayer + scf + ret + +CheckAbsoluteValueLessThan2: + jr nc, .positive + cpl + inc a +.positive + cp $2 + ret + +Func_fcc08:: + call Func_fcc23 + ret nc + ld a, [wd736] + bit 6, a + jr nz, .asm_fcc1b + call Func_fcc42 + ret c + call AppendPikachuFollowCommandToBuffer + ret + +.asm_fcc1b + call Func_fcc64 + ret c + call AppendPikachuFollowCommandToBuffer + ret + +Func_fcc23: + ld a, [wPikachuOverworldStateFlags] + bit 5, a + jr nz, .asm_fcc40 + ld a, [wPikachuOverworldStateFlags] + bit 7, a + jr nz, .asm_fcc40 + ld a, [wd472] + bit 7, a + jr z, .asm_fcc40 + ld a, [wWalkBikeSurfState] + and a + jr nz, .asm_fcc40 + scf + ret + +.asm_fcc40 + and a + ret + +Func_fcc42: + xor a + ld a, [wPlayerDirection] + bit 3, a + jr nz, .asm_fcc58 + bit 2, a + jr nz, .asm_fcc5b + bit 1, a + jr nz, .asm_fcc5e + bit 0, a + jr nz, .asm_fcc61 + scf + ret + +.asm_fcc58 + ld a, $2 + ret + +.asm_fcc5b + ld a, $1 + ret + +.asm_fcc5e + ld a, $3 + ret + +.asm_fcc61 + ld a, $4 + ret + +Func_fcc64: + ld hl, wPikachuOverworldStateFlags + bit 6, [hl] + jr z, .asm_fcc6e + res 6, [hl] + ret + +.asm_fcc6e + set 6, [hl] + xor a + ld a, [wPlayerDirection] + bit 3, a + jr nz, .asm_fcc86 + bit 2, a + jr nz, .asm_fcc89 + bit 1, a + jr nz, .asm_fcc8c + bit 0, a + jr nz, .asm_fcc8f + scf + ret + +.asm_fcc86 + ld a, $6 + ret + +.asm_fcc89 + ld a, $5 + ret + +.asm_fcc8c + ld a, $7 + ret + +.asm_fcc8f + ld a, $8 + ret + +Func_fcc92: + ld hl, wPikachuFollowCommandBufferSize + ld a, [hl] + cp $ff + jr z, .asm_fccb0 + and a + jr z, .asm_fccb0 + dec [hl] + ld e, a + ld d, 0 + ld hl, wPikachuFollowCommandBuffer + add hl, de + inc e + ld a, $ff +.asm_fcca8 + ld d, [hl] + ldd [hl], a + ld a, d + dec e + jr nz, .asm_fcca8 + and a + ret + +.asm_fccb0 + scf + ret + +ComputePikachuFacingDirection:: + call GetPikachuFollowCommandIfBufferSizeNonzero + and a + jr z, .check_y + dec a + and $3 + add a + add a + jr .load + +.check_y + ld a, [wYCoord] + add $4 + ld d, a + ld a, [wXCoord] + add $4 + ld e, a + ld a, [wSpritePikachuStateData2MapY] + cp d + jr z, .check_x + ld a, SPRITE_FACING_DOWN + jr c, .load + ld a, SPRITE_FACING_UP + jr .load + +.check_x + ld a, [wSpritePikachuStateData2MapX] + cp e + jr z, .copy_from_player + ld a, SPRITE_FACING_RIGHT + jr c, .load + ld a, SPRITE_FACING_LEFT + jr .load + +.copy_from_player + ld a, [wSpritePlayerStateData1FacingDirection] +.load + ld [wSpritePikachuStateData1FacingDirection], a + ret + +GetPikachuFollowCommand: + ld hl, wPikachuFollowCommandBufferSize + ld a, [hl] + cp $ff + jr z, .asm_fccff + ld e, a + ld d, 0 + ld hl, wPikachuFollowCommandBuffer + add hl, de + ld a, [hl] + ret + +.asm_fccff + xor a + ret + +GetPikachuFollowCommandIfBufferSizeNonzero: + ld hl, wPikachuFollowCommandBufferSize + ld a, [hl] + cp $ff + jr z, .default + and a + jr z, .default + ld e, a + ld d, 0 + ld hl, wPikachuFollowCommandBuffer + add hl, de + ld a, [hl] + ret + +.default + xor a + ret + +AreThereAtLeastTwoStepsInPikachuFollowCommandBuffer: + ld a, [wPikachuFollowCommandBufferSize] + cp $ff + ret z + cp $2 + jr nc, .set_carry + and a + ret + +.set_carry + scf + ret + +WillPikachuSpawnOnTheScreen: + ld h, wSpriteStateData2 / $100 + ld a, [H_CURRENTSPRITEOFFSET] ; If we're here, this can only be $f0 + add wSpritePikachuStateData2MapY - wSpritePikachuStateData2 + ld l, a + ld b, [hl] + ld a, [wYCoord] + cp b + jr z, .same_y + jr nc, .not_on_screen + add (SCREEN_HEIGHT / 2) - 1 + cp b + jr c, .not_on_screen +.same_y + inc l + ld b, [hl] + ld a, [wXCoord] + cp b + jr z, .same_x + jr nc, .not_on_screen + add (SCREEN_WIDTH / 2) - 1 + cp b + jr c, .not_on_screen +.same_x + call .GetNPCCurrentTile + ld d, $60 + ld a, [hli] + ld e, a + cp d + jr nc, .not_on_screen + ld a, [hld] + cp d + jr nc, .not_on_screen + ld bc, -20 + add hl, bc + ld a, [hli] + cp d + jr nc, .not_on_screen + ld a, [hl] + cp d + jr c, .on_screen +.not_on_screen + ld h, wSpriteStateData1 / $100 + ld a, [H_CURRENTSPRITEOFFSET] + add wSpritePikachuStateData1ImageIndex - wSpritePikachuStateData1 + ld l, a + ld [hl], $ff + scf + jr .return + +.on_screen + ld h, wSpriteStateData2 / $100 + ld a, [H_CURRENTSPRITEOFFSET] + add wSpritePikachuStateData2GrassPriority - wSpritePikachuStateData2 + ld l, a + ld a, [wGrassTile] + cp e + ld a, $0 + jr nz, .priority + ld a, $80 +.priority + ld [hl], a + and a +.return + ret + +.GetNPCCurrentTile: + ld h, wSpriteStateData1 / $100 + ld a, [H_CURRENTSPRITEOFFSET] + add wSpritePikachuStateData1YPixels - wSpritePikachuStateData1 + ld l, a + ld a, [hli] + add $4 + and $f0 + srl a + ld c, a + ld b, $0 + inc l + ld a, [hl] + add $2 + srl a + srl a + srl a + add SCREEN_WIDTH + ld d, 0 + ld e, a + ld hl, wTileMap + rept 5 + add hl, bc + endr + add hl, de + ret + +ComparePikachuHappinessTo80: +; preserves a and bc + push bc + push af + ld a, [wPikachuHappiness] + cp 80 + pop bc + ld a, b + pop bc + ret diff --git a/engine/pikachu_movement.asm b/engine/pikachu_movement.asm new file mode 100755 index 00000000..938715a4 --- /dev/null +++ b/engine/pikachu_movement.asm @@ -0,0 +1,1048 @@ +ApplyPikachuMovementData_:: + ld a, b + ld [wPikachuMovementScriptBank], a + ld a, l + ld [wPikachuMovementScriptAddress], a + ld a, h + ld [wPikachuMovementScriptAddress + 1], a + call .SwapSpriteStateData +.loop + call LoadPikachuMovementCommandData + jr nc, .done + call ExecutePikachuMovementCommand + jr .loop + +.done + call .SwapSpriteStateData + call DelayFrame + ret + +.SwapSpriteStateData: + ld a, [wUpdateSpritesEnabled] + push af + ld a, $ff + ld [wUpdateSpritesEnabled], a + push hl + push de + push bc + + ld hl, wSpritePlayerStateData1 + ld de, wSpritePikachuStateData1 + ld c, $10 + call .SwapBytes + + ld hl, wSpritePlayerStateData2 + ld de, wSpritePikachuStateData2 + ld c, $10 + call .SwapBytes + + pop bc + pop de + pop hl + pop af + ld [wUpdateSpritesEnabled], a + ret + +.SwapBytes: + ld b, [hl] + ld a, [de] + ld [hli], a + ld a, b + ld [de], a + inc de + dec c + jr nz, .SwapBytes + ret + +LoadPikachuMovementCommandData: + call GetPikachuMovementScriptByte + cp $3f + ret z + ld c, a + ld b, 0 + ld hl, PikachuMovementDatabase + add hl, bc + add hl, bc + add hl, bc + add hl, bc + ld a, [hli] + ld [wCurPikaMovementFunc1], a + ld a, [hli] + cp $80 + jr nz, .no_param + call GetPikachuMovementScriptByte +.no_param + ld [wCurPikaMovementParam1], a + ld a, [hli] + ld [wCurPikaMovementFunc2], a + ld a, [hli] + cp $80 + jr nz, .no_param2 + call GetPikachuMovementScriptByte +.no_param2 + ld [wCurPikaMovementParam2], a + xor a + ld [wd451], a + scf + ret + +ExecutePikachuMovementCommand: + xor a + ld [wPikachuMovementFlags], a + ld [wPikachuStepTimer], a + ld [wPikachuStepSubtimer], a + ld a, [wSpritePlayerStateData2GrassPriority] + push af +.loop + ld bc, wSpritePlayerStateData1 ; Currently holds Pikachu's sprite state data + ld a, [wCurPikaMovementFunc1] + ld hl, PikaMovementFunc1Jumptable + call .JumpTable + ld a, [wCurPikaMovementFunc2] + ld hl, PikaMovementFunc2Jumptable + call .JumpTable + call GetCoordsForPikachuShadow + call AnimatePikachuShadow + call DelayFrame + call DelayFrame + ld hl, wPikachuMovementFlags + bit 7, [hl] + jr z, .loop + pop af + ld [wSpritePlayerStateData2GrassPriority], a + scf + ret + +.JumpTable: + ld e, a + ld d, 0 + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + jp hl + +GetCoordsForPikachuShadow: + ld hl, wSpritePlayerStateData1ImageIndex - wSpritePlayerStateData1 + add hl, bc + ld a, [wCurPikaMovementSpriteImageIdx] + ld [hl], a + ld a, [wPikaSpriteY] + ld d, a + ld a, [wPikachuMovementYOffset] + add d + ld hl, wSpritePlayerStateData1YPixels - wSpritePlayerStateData1 + add hl, bc + ld [hl], a + ld a, [wPikaSpriteX] + ld d, a + ld a, [wPikachuMovementXOffset] + add d + ld hl, wSpritePlayerStateData1XPixels - wSpritePlayerStateData1 + add hl, bc + ld [hl], a + ld hl, wPikachuMovementFlags + bit 6, [hl] + ret z + ld hl, wSpritePlayerStateData2GrassPriority - wSpritePlayerStateData1 + add hl, bc + ld [hl], 0 + ret + +AnimatePikachuShadow: + ld hl, wPikachuMovementFlags + bit 6, [hl] + res 6, [hl] + ld hl, wd736 + res 6, [hl] + ret z + set 6, [hl] + call LoadPikachuShadowOAMData + ret + +PikachuMovementDatabase: + db $01, 1 - 1, $00, 1 - 1 ; $00 start + + db $03, $80, $01, 1 - 1 ; $01 + db $04, $80, $01, 1 - 1 ; $02 + db $05, $80, $01, 1 - 1 ; $03 + db $06, $80, $01, 1 - 1 ; $04 + db $07, $80, $01, 1 - 1 ; $05 + db $08, $80, $01, 1 - 1 ; $06 + db $09, $80, $01, 1 - 1 ; $07 + db $0a, $80, $01, 1 - 1 ; $08 + + db $03, $80, $06, 1 - 1 ; $09 + db $04, $80, $06, 1 - 1 ; $0a + db $05, $80, $06, 1 - 1 ; $0b + db $06, $80, $06, 1 - 1 ; $0c + db $07, $80, $06, 1 - 1 ; $0d + db $08, $80, $06, 1 - 1 ; $0e + db $09, $80, $06, 1 - 1 ; $0f + db $0a, $80, $06, 1 - 1 ; $10 + + db $03, $80, $03, $80 ; $11 + db $04, $80, $03, $80 ; $12 + db $05, $80, $03, $80 ; $13 + db $06, $80, $03, $80 ; $14 + db $07, $80, $03, $80 ; $15 + db $08, $80, $03, $80 ; $16 + db $09, $80, $03, $80 ; $17 + db $0a, $80, $03, $80 ; $18 + + db $03, $80, $07, $80 ; $19 + db $04, $80, $07, $80 ; $1a + db $05, $80, $07, $80 ; $1b + db $06, $80, $07, $80 ; $1c + + db $0b, (1 << 5) | 8 - 1, $02, 1 - 1 ; $1d step down + db $0c, (1 << 5) | 8 - 1, $02, 1 - 1 ; $1e step up + db $0d, (1 << 5) | 8 - 1, $02, 1 - 1 ; $1f step left + db $0e, (1 << 5) | 8 - 1, $02, 1 - 1 ; $20 step right + db $0f, (1 << 5) | 8 - 1, $02, 1 - 1 ; $21 step down left + db $10, (1 << 5) | 8 - 1, $02, 1 - 1 ; $22 step down right + db $11, (1 << 5) | 8 - 1, $02, 1 - 1 ; $23 step up left + db $12, (1 << 5) | 8 - 1, $02, 1 - 1 ; $24 step up right + + db $0b, 16 - 1, $02, 1 - 1 ; $25 slide down + db $0c, 16 - 1, $02, 1 - 1 ; $26 slide up + db $0d, 16 - 1, $02, 1 - 1 ; $27 slide left + db $0e, 16 - 1, $02, 1 - 1 ; $28 slide right + db $0f, 16 - 1, $02, 1 - 1 ; $29 slide down left + db $10, 16 - 1, $02, 1 - 1 ; $2a slide down right + db $11, 16 - 1, $02, 1 - 1 ; $2b slide up left + db $12, 16 - 1, $02, 1 - 1 ; $2c slide up right + + db $0b, 16 - 1, $08, (1 << 4) | 8 - 1 ; $2d hop down + db $0c, 16 - 1, $08, (1 << 4) | 8 - 1 ; $2e hop up + db $0d, 16 - 1, $08, (1 << 4) | 8 - 1 ; $2f hop left + db $0e, 16 - 1, $08, (1 << 4) | 8 - 1 ; $30 hop right + db $0f, 16 - 1, $08, (1 << 4) | 8 - 1 ; $31 hop down left + db $10, 16 - 1, $08, (1 << 4) | 8 - 1 ; $32 hop down right + db $11, 16 - 1, $08, (1 << 4) | 8 - 1 ; $33 hop up left + db $12, 16 - 1, $08, (1 << 4) | 8 - 1 ; $34 hop up right + + db $13, 16 - 1, $06, 1 - 1 ; $35 look down + db $14, 16 - 1, $06, 1 - 1 ; $36 look up + db $15, 16 - 1, $06, 1 - 1 ; $37 look left + db $16, 16 - 1, $06, 1 - 1 ; $38 look right + + db $02, $80, $04, 1 - 1 ; $39 + db $02, $80, $05, 1 - 1 ; $3a + db $02, $80, $03, $80 ; $3b + db $02, $80, $07, $80 ; $3c + db $02, $80, $09, $80 ; $3d + db $02, $80, $06, 1 - 1 ; $3e + +PikaMovementFunc1Jumptable: + dw PikaMovementFunc1_EndCommand_ ; 00 + dw PikaMovementFunc1_LoadPikachuCurrentPosition ; 01 + dw PikaMovementFunc1_DelayFrames ; 02 + dw PikaMovementFunc1_WalkInCurrentFacingDirection ; 03 + dw PikaMovementFunc1_WalkInOppositeFacingDirection ; 04 + dw PikaMovementFunc1_StepTurningCounterclockwise ; 05 + dw PikaMovementFunc1_StepTurningClockwise ; 06 + dw PikaMovementFunc1_StepForwardLeft ; 07 + dw PikaMovementFunc1_StepForwardRight ; 08 + dw PikaMovementFunc1_StepBackwardLeft ; 09 + dw PikaMovementFunc1_StepBackwardRight ; 0a + dw PikaMovementFunc1_MoveDown ; 0b + dw PikaMovementFunc1_MoveUp ; 0c + dw PikaMovementFunc1_MoveLeft ; 0d + dw PikaMovementFunc1_MoveRight ; 0e + dw PikaMovementFunc1_MoveDownLeft ; 0f + dw PikaMovementFunc1_MoveDownRight ; 10 + dw PikaMovementFunc1_MoveUpLeft ; 11 + dw PikaMovementFunc1_MoveUpRight ; 12 + dw PikaMovementFunc1_LookDown ; 13 + dw PikaMovementFunc1_LookUp ; 14 + dw PikaMovementFunc1_LookLeft ; 15 + dw PikaMovementFunc1_LookRight ; 16 + dw PikaMovementFunc1_EndCommand_ ; 17 + +PikaMovementFunc1_EndCommand: + ld a, [wPikachuMovementFlags] + set 7, a + ld [wPikachuMovementFlags], a + ret + +PikaMovementFunc1_EndCommand_: + call PikaMovementFunc1_EndCommand + ret + +PikaMovementFunc1_LoadPikachuCurrentPosition: + ld hl, wSpritePlayerStateData1YPixels - wSpritePlayerStateData1 + add hl, bc + ld a, [hl] + ld [wPikaSpriteY], a + ld hl, wSpritePlayerStateData1XPixels - wSpritePlayerStateData1 + add hl, bc + ld a, [hl] + ld [wPikaSpriteX], a + xor a + ld [wPikachuMovementYOffset], a + ld [wPikachuMovementXOffset], a + call PikaMovementFunc1_EndCommand + ret + +PikaMovementFunc1_DelayFrames: + call CheckPikachuStepTimer1 + ret nz + call PikaMovementFunc1_EndCommand + ret + +PikaMovementFunc1_WalkInCurrentFacingDirection: + call GetPikachuFacing + jr PikaMovementFunc1_ApplyStepVector + +PikaMovementFunc1_WalkInOppositeFacingDirection: + call GetPikachuFacing + xor %100 + jr PikaMovementFunc1_ApplyStepVector + +PikaMovementFunc1_StepTurningCounterclockwise: + call GetPikachuFacing + ld hl, .Data + call PikaMovementFunc1_GetNextFacing + jr PikaMovementFunc1_ApplyStepVector + +.Data: + db SPRITE_FACING_DOWN, PIKASTEPDIR_RIGHT << 2 + db SPRITE_FACING_UP, PIKASTEPDIR_LEFT << 2 + db SPRITE_FACING_LEFT, PIKASTEPDIR_DOWN << 2 + db SPRITE_FACING_RIGHT, PIKASTEPDIR_UP << 2 + db $ff + +PikaMovementFunc1_StepTurningClockwise: + call GetPikachuFacing + ld hl, .Data + call PikaMovementFunc1_GetNextFacing + jr PikaMovementFunc1_ApplyStepVector + +.Data: + db SPRITE_FACING_DOWN, PIKASTEPDIR_LEFT << 2 + db SPRITE_FACING_UP, PIKASTEPDIR_RIGHT << 2 + db SPRITE_FACING_LEFT, PIKASTEPDIR_UP << 2 + db SPRITE_FACING_RIGHT, PIKASTEPDIR_DOWN << 2 + db $ff + +PikaMovementFunc1_StepForwardLeft: + call GetPikachuFacing + ld hl, .Data + call PikaMovementFunc1_GetNextFacing + jr PikaMovementFunc1_ApplyStepVector + +.Data: + db SPRITE_FACING_DOWN, PIKASTEPDIR_DOWN_RIGHT << 2 + db SPRITE_FACING_UP, PIKASTEPDIR_UP_LEFT << 2 + db SPRITE_FACING_LEFT, PIKASTEPDIR_DOWN_LEFT << 2 + db SPRITE_FACING_RIGHT, PIKASTEPDIR_UP_RIGHT << 2 + +PikaMovementFunc1_StepForwardRight: + call GetPikachuFacing + ld hl, .Data + call PikaMovementFunc1_GetNextFacing + jr PikaMovementFunc1_ApplyStepVector + +.Data: + db SPRITE_FACING_DOWN, PIKASTEPDIR_DOWN_LEFT << 2 + db SPRITE_FACING_UP, PIKASTEPDIR_UP_RIGHT << 2 + db SPRITE_FACING_LEFT, PIKASTEPDIR_UP_LEFT << 2 + db SPRITE_FACING_RIGHT, PIKASTEPDIR_DOWN_RIGHT << 2 + +PikaMovementFunc1_StepBackwardLeft: + call GetPikachuFacing + ld hl, .Data + call PikaMovementFunc1_GetNextFacing + jr PikaMovementFunc1_ApplyStepVector + +.Data: + db SPRITE_FACING_DOWN, PIKASTEPDIR_UP_RIGHT << 2 + db SPRITE_FACING_UP, PIKASTEPDIR_DOWN_LEFT << 2 + db SPRITE_FACING_LEFT, PIKASTEPDIR_DOWN_RIGHT << 2 + db SPRITE_FACING_RIGHT, PIKASTEPDIR_UP_LEFT << 2 + +PikaMovementFunc1_StepBackwardRight: + call GetPikachuFacing + ld hl, .Data + call PikaMovementFunc1_GetNextFacing + jr PikaMovementFunc1_ApplyStepVector + +.Data: + db SPRITE_FACING_DOWN, PIKASTEPDIR_UP_LEFT << 2 + db SPRITE_FACING_UP, PIKASTEPDIR_DOWN_RIGHT << 2 + db SPRITE_FACING_LEFT, PIKASTEPDIR_UP_RIGHT << 2 + db SPRITE_FACING_RIGHT, PIKASTEPDIR_DOWN_LEFT << 2 + +PikaMovementFunc1_ApplyStepVector: + rrca + rrca + and $7 + ld e, a + call GetPikachuStepVectorMagnitude + ld d, a + call UpdatePikachuPosition + call CheckPikachuStepTimer1 + ret nz + call PikaMovementFunc1_EndCommand + ret + +PikaMovementFunc1_GetNextFacing: + push de + ld d, a +.loop + ld a, [hli] + cp d + jr z, .found + inc hl + cp $ff + jr nz, .loop + pop de + ret + +.found + ld a, [hl] + pop de + scf + ret + +PikaMovementFunc1_MoveDown: + ld a, PIKASTEPDIR_DOWN + jr PikaMovementFunc1_ApplyFacingAndMove + +PikaMovementFunc1_MoveUp: + ld a, PIKASTEPDIR_UP + jr PikaMovementFunc1_ApplyFacingAndMove + +PikaMovementFunc1_MoveLeft: + ld a, PIKASTEPDIR_LEFT + jr PikaMovementFunc1_ApplyFacingAndMove + +PikaMovementFunc1_MoveRight: + ld a, PIKASTEPDIR_RIGHT + jr PikaMovementFunc1_ApplyFacingAndMove + +PikaMovementFunc1_MoveDownLeft: + ld e, PIKASTEPDIR_DOWN_LEFT + jr PikaMovementFunc1_MoveDiagonally + +PikaMovementFunc1_MoveDownRight: + ld e, PIKASTEPDIR_DOWN_RIGHT + jr PikaMovementFunc1_MoveDiagonally + +PikaMovementFunc1_MoveUpLeft: + ld e, PIKASTEPDIR_UP_LEFT + jr PikaMovementFunc1_MoveDiagonally + +PikaMovementFunc1_MoveUpRight: + ld e, PIKASTEPDIR_UP_RIGHT + jr PikaMovementFunc1_MoveDiagonally + +PikaMovementFunc1_ApplyFacingAndMove: + ld e, a + call SetPikachuFacing +PikaMovementFunc1_MoveDiagonally: + call GetPikachuStepVectorMagnitude + ld d, a + push de + call UpdatePikachuPosition + pop de + call CheckPikachuStepTimer1 + ret nz + ld a, e + call ApplyPikachuStepVector + call PikaMovementFunc1_EndCommand + ret + +PikaMovementFunc1_LookDown: + ld a, PIKASTEPDIR_DOWN + jr PikaMovementFunc1_ApplyFacing + +PikaMovementFunc1_LookUp: + ld a, PIKASTEPDIR_UP + jr PikaMovementFunc1_ApplyFacing + +PikaMovementFunc1_LookLeft: + ld a, PIKASTEPDIR_LEFT + jr PikaMovementFunc1_ApplyFacing + +PikaMovementFunc1_LookRight: + ld a, PIKASTEPDIR_RIGHT + jr PikaMovementFunc1_ApplyFacing + +PikaMovementFunc1_ApplyFacing: + call SetPikachuFacing + call PikaMovementFunc1_EndCommand + ret + +UpdatePikachuPosition: + push de + ld d, 0 + ld hl, .Jumptable + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + pop de + ld a, d + jp hl + +.Jumptable: + dw .Down + dw .Up + dw .Left + dw .Right + dw .DownLeft + dw .DownRight + dw .UpLeft + dw .UpRight + +.Down: + ld d, 0 + ld e, a + jr .ApplyVector + +.Up: + ld d, 0 + cpl + inc a + ld e, a + jr .ApplyVector + +.Left: + cpl + inc a + ld d, a + ld e, 0 + jr .ApplyVector + +.Right: + ld d, a + ld e, 0 + jr .ApplyVector + +.DownLeft: + ld e, a + cpl + inc a + ld d, a + jr .ApplyVector + +.DownRight: + ld e, a + ld d, a + jr .ApplyVector + +.UpLeft: + cpl + inc a + ld e, a + ld d, a + jr .ApplyVector + +.UpRight: + ld d, a + cpl + inc a + ld e, a + jr .ApplyVector + +.ApplyVector: + ld a, [wPikaSpriteX] + add d + ld [wPikaSpriteX], a + ld a, [wPikaSpriteY] + add e + ld [wPikaSpriteY], a + ret + +PikaMovementFunc2Jumptable: + dw PikaMovementFunc2_ResetFrameCounterAndFaceCurrent ; 0 + dw PikaMovementFunc2_UpdateSpriteImageIdxWithPreviousImageIdxDirection ; 1 + dw PikaMovementFunc2_UpdateSpriteImageIdxWithFacing ; 2 + dw PikaMovementFunc2_TurnParameter ; 3 + dw PikaMovementFunc2_TurnClockwise ; 4 + dw PikaMovementFunc2_TurnCounterClockwise ; 5 + dw PikaMovementFunc2_CopySpriteImageIdxDirectionToSpriteImageIdx ; 6 + dw PikaMovementFunc2_UpdateJumpWithPreviousImageIdxDirection ; 7 + dw PikaMovementFunc2_UpdateJumpWithFacing ; 8 + dw PikaMovementFunc2_CopyFacingToJump ; 9 + dw PikaMovementFunc2_nop ; 10 + +PikaMovement_SetSpawnShadow: + ld hl, wPikachuMovementFlags + set 6, [hl] + ret + +PikaMovementFunc2_ResetFrameCounterAndFaceCurrent: + ld hl, wSpritePlayerStateData1IntraAnimFrameCounter - wSpritePlayerStateData1 + add hl, bc + xor a + ld [hli], a + ld [hl], a + call PikaMovementFunc2_GetImageBaseOffset + ld d, a + call GetPikachuFacing + or d + ld [wCurPikaMovementSpriteImageIdx], a + ret + +PikaMovementFunc2_nop: + ret + +PikaMovementFunc2_CopySpriteImageIdxDirectionToSpriteImageIdx: + call PikaMovementFunc2_GetImageBaseOffset + ld d, a + call PikaMovementFunc2_GetSpriteImageIdxDirection + or d + ld [wCurPikaMovementSpriteImageIdx], a + ret + +PikaMovementFunc2_UpdateSpriteImageIdxWithFacing: + call PikaMovementFunc2_GetImageBaseOffset + ld d, a + call GetPikachuFacing + or d + ld d, a + jr PikaMovementFunc2_UpdateSpriteImageIdx + +PikaMovementFunc2_UpdateSpriteImageIdxWithPreviousImageIdxDirection: + call PikaMovementFunc2_GetImageBaseOffset + ld d, a + call PikaMovementFunc2_GetSpriteImageIdxDirection + or d + ld d, a +PikaMovementFunc2_UpdateSpriteImageIdx: + ld hl, wSpritePlayerStateData1AnimFrameCounter - wSpritePlayerStateData1 + add hl, bc + call CheckPikachuStepTimer2 ; does not preserve hl + jr nz, .skip + inc [hl] +.skip + ld a, [hl] + rrca + rrca + and 3 + or d + ld [wCurPikaMovementSpriteImageIdx], a + ret + +PikaMovementFunc2_UpdateJumpWithFacing: + call GetPikachuFacing + ld d, a + jr PikaMovementFunc2_UpdateJump + +PikaMovementFunc2_UpdateJumpWithPreviousImageIdxDirection: + call PikaMovementFunc2_GetSpriteImageIdxDirection + ld d, a +PikaMovementFunc2_UpdateJump: + call PikaMovementFunc2_GetImageBaseOffset + or d + ld d, a + call PikaMovementFunc2_Timer + or d + ld [wCurPikaMovementSpriteImageIdx], a + call PikaMovementFunc_Sine + ld [wPikachuMovementYOffset], a + and a + ret z + call PikaMovement_SetSpawnShadow + ret + +PikaMovementFunc2_CopyFacingToJump: + call GetPikachuFacing + ld d, a + call PikaMovementFunc2_GetImageBaseOffset + or d + ld [wCurPikaMovementSpriteImageIdx], a + call PikaMovementFunc_Sine + ld [wPikachuMovementYOffset], a + ret + +PikaMovementFunc2_TurnParameter: + ld a, [wCurPikaMovementParam2] + and $40 + cp $40 + jr z, PikaMovementFunc2_TurnClockwise + jr PikaMovementFunc2_TurnCounterClockwise + +PikaMovementFunc2_TurnClockwise: + call PikaMovementFunc2_GetSpriteImageIdxDirection + ld d, a + call CheckPikachuStepTimer2 + jr nz, .skip + ld hl, Data_fd731 +.loop + ld a, [hli] + cp d + jr nz, .loop + ld d, [hl] +.skip + call PikaMovementFunc2_GetImageBaseOffset + or d + ld [wCurPikaMovementSpriteImageIdx], a + ret + +PikaMovementFunc2_TurnCounterClockwise: + call PikaMovementFunc2_GetSpriteImageIdxDirection + ld d, a + call CheckPikachuStepTimer2 + jr nz, .skip + ld hl, Data_fd731End +.loop + ld a, [hld] + cp d + jr nz, .loop + ld d, [hl] +.skip + call PikaMovementFunc2_GetImageBaseOffset + or d + ld [wCurPikaMovementSpriteImageIdx], a + ret + +Data_fd731: + db SPRITE_FACING_DOWN + db SPRITE_FACING_LEFT + db SPRITE_FACING_UP + db SPRITE_FACING_RIGHT + db SPRITE_FACING_DOWN +Data_fd731End: + +PikaMovementFunc2_Timer: + push hl + ld hl, wSpritePlayerStateData1IntraAnimFrameCounter - wSpritePlayerStateData1 + add hl, bc + ld a, [hl] + inc a + and $3 + ld [hli], a + jr nz, .load_pop + ld a, [hl] + inc a + and $3 + ld [hl], a +.load_pop + ld a, [hl] + pop hl + ret + +PikaMovementFunc2_GetImageBaseOffset: + push hl + ld hl, wSpritePlayerStateData2ImageBaseOffset - wSpritePlayerStateData1 + add hl, bc + ld a, [hl] + dec a + swap a + pop hl + ret + +PikaMovementFunc2_GetSpriteImageIdxDirection: + push hl + ld hl, wSpritePlayerStateData1ImageIndex - wSpritePlayerStateData1 + add hl, bc + ld a, [hl] + and $c + pop hl + ret + +GetPikachuFacing: + push hl + ld hl, wSpritePlayerStateData1FacingDirection - wSpritePlayerStateData1 + add hl, bc + ld a, [hl] + and $c + pop hl + ret + +SetPikachuFacing: + push hl + ld hl, wSpritePlayerStateData1FacingDirection - wSpritePlayerStateData1 + add hl, bc + add a + add a + and $c + ld [hl], a + pop hl + ret + +CheckPikachuStepTimer1: + ld hl, wPikachuStepTimer + inc [hl] + ld a, [wCurPikaMovementParam1] + and $1f + inc a + cp [hl] + ret nz + ld [hl], 0 + ret + +GetPikachuStepVectorMagnitude: + ; *XX***** + ld a, [wCurPikaMovementParam1] + swap a + rrca + and $3 + inc a + ret + +CheckPikachuStepTimer2: + ld hl, wPikachuStepSubtimer + inc [hl] + ld a, [wCurPikaMovementParam2] + and $f + inc a + cp [hl] + ret nz + ld [hl], 0 + ret + +PikaMovementFunc_Sine: + call .GetArgument + ld a, [wPikachuStepSubtimer] + add e + ld [wPikachuStepSubtimer], a + add $20 + ld e, a + push hl + push bc + call Sine_e + pop bc + pop hl + ret + +.GetArgument: + ld a, [wCurPikaMovementParam2] + and $f + inc a + ld d, a + ld a, [wCurPikaMovementParam2] + swap a + and $7 + ld e, a + ld a, 1 + jr z, .okay +.loop + add a + dec e + jr nz, .loop +.okay + ld e, a + ret + +ApplyPikachuStepVector: + push bc + ld c, a + ld b, 0 + ld hl, .StepVectors + add hl, bc + add hl, bc + ld d, [hl] + inc hl + ld e, [hl] + pop bc + ld hl, wSpritePlayerStateData2MapY - wSpritePlayerStateData1 + add hl, bc + ld a, [hl] + add e + ld [hli], a + ld a, [hl] + add d + ld [hl], a + ret + +.StepVectors: + db 0, 1 + db 0, -1 + db -1, 0 + db 1, 0 + db -1, 1 + db 1, 1 + db -1, -1 + db 1, -1 + +LoadPikachuShadowOAMData: + push bc + push de + push hl + + ld bc, wOAMBuffer + 4 * 36 + ld a, [wPikaSpriteY] + ld e, a + ld a, [wPikaSpriteX] + ld d, a + ld hl, .OAMData + call .LoadOAMData + + pop hl + pop de + pop bc + ret + +.OAMData: + db 2 + db $0c, $00, $ff, 0 + db $0c, $08, $ff, 1 << OAM_X_FLIP + +.LoadOAMData: + ld a, e + add $10 + ld e, a + ld a, d + add $8 + ld d, a + ld a, [hli] +.loop + push af + ld a, [hli] + add e + ld [bc], a + inc bc + ld a, [hli] + add d + ld [bc], a + inc bc + ld a, [hli] + ld [bc], a + inc bc + ld a, [hli] + ld [bc], a + inc bc + pop af + dec a + jr nz, .loop + ret + +LoadPikachuShadowIntoVRAM: + ld hl, vNPCSprites2 + $7f * $10 + ld de, LedgeHoppingShadowGFX_3F + lb bc, BANK(LedgeHoppingShadowGFX_3F), (LedgeHoppingShadowGFX_3FEnd - LedgeHoppingShadowGFX_3F) / 8 + jp CopyVideoDataDoubleAlternate + +LedgeHoppingShadowGFX_3F: +INCBIN "gfx/ledge_hopping_shadow.1bpp" +LedgeHoppingShadowGFX_3FEnd: + +LoadPikachuBallIconIntoVRAM: + ld hl, vNPCSprites2 + $7e * $10 + ld de, GFX_fd86b + lb bc, BANK(GFX_fd86b), 1 + jp CopyVideoDataDoubleAlternate + +Func_fd851: + ld hl, vNPCSprites + $c * $10 + ld a, 3 +.loop + push af + push hl + ld de, GFX_fd86b + lb bc, BANK(GFX_fd86b), 4 + call CopyVideoDataAlternate + pop hl + ld de, 4 * $10 + add hl, de + pop af + dec a + jr nz, .loop + ret + +GFX_fd86b: +INCBIN "gfx/unknown_fd86b.2bpp" + +LoadPikachuSpriteIntoVRAM: + ld de, PikachuSprite + lb bc, BANK(PikachuSprite), (SandshrewSprite - PikachuSprite) / 32 + ld hl, vNPCSprites + $c * $10 + push bc + call CopyVideoDataAlternate + ld de, PikachuSprite + $c * $10 + ld hl, vNPCSprites2 + $c * $10 + ld a, [h_0xFFFC] + and a + jr z, .load + ld de, PikachuSprite + $c * $10 + ld hl, vNPCSprites2 + $4c * $10 +.load + pop bc + call CopyVideoDataAlternate + call LoadPikachuShadowIntoVRAM + call LoadPikachuBallIconIntoVRAM + ret + +PikachuPewterPokecenterCheck: + ld a, [wCurMap] + cp PEWTER_POKECENTER + ret nz + call EnablePikachuFollowingPlayer + call StarterPikachuEmotionCommand_turnawayfromplayer + ret + +PikachuFanClubCheck: + ld a, [wCurMap] + cp POKEMON_FAN_CLUB + ret nz + call EnablePikachuFollowingPlayer + call StarterPikachuEmotionCommand_turnawayfromplayer + ret + +PikachuBillsHouseCheck: + ld a, [wCurMap] + cp BILLS_HOUSE + ret nz + call EnablePikachuFollowingPlayer + ret + +Pikachu_LoadCurrentMapViewUpdateSpritesAndDelay3: + call LoadCurrentMapView + call UpdateSprites + call Delay3 + ret + +Cosine_e: ; cosine? + ld a, e + add $10 + jr asm_fd908 + +Sine_e: ; sine? + ld a, e +asm_fd908 + and $3f + cp $20 + jr nc, .asm_fd913 + call GetSine + ld a, h + ret + +.asm_fd913 + and $1f + call GetSine + ld a, h + cpl + inc a + ret + +GetSine: + ld e, a + ld a, d + ld d, 0 + ld hl, SineWave_3f + add hl, de + add hl, de + ld e, [hl] + inc hl + ld d, [hl] + ld hl, 0 +.asm_fd92b + srl a + jr nc, .asm_fd930 + add hl, de +.asm_fd930 + sla e + rl d + and a + jr nz, .asm_fd92b + ret + +SineWave_3f: + sine_wave $100 diff --git a/engine/pikachu_pcm.asm b/engine/pikachu_pcm.asm new file mode 100755 index 00000000..1e6f8dc2 --- /dev/null +++ b/engine/pikachu_pcm.asm @@ -0,0 +1,154 @@ +PlayPikachuSoundClip:: + ld a, e + ld e, a + ld d, $0 + ld hl, PikachuCriesPointerTable + add hl, de + add hl, de + add hl, de + ld b, [hl] ; bank of pikachu cry data + inc hl + ld a, [hli] ; cry data pointer + ld h, [hl] + ld l, a + ld c, $4 +.loop + dec c + jr z, .done_delay + call DelayFrame + jr .loop + +.done_delay + di + push bc + push hl + ld a, $80 + ld [rNR52], a + ld a, $77 + ld [rNR50], a + xor a + ld [rNR30], a + ld hl, $ff30 ; wave data + ld de, wRedrawRowOrColumnSrcTiles +.saveWaveDataLoop + ld a, [hl] + ld [de], a + inc de + ld a, $ff + ld [hli], a + ld a, l + cp $40 ; end of wave data + jr nz, .saveWaveDataLoop + ld a, $80 + ld [rNR30], a + ld a, [rNR51] + or $44 + ld [rNR51], a + ld a, $ff + ld [rNR31], a + ld a, $20 + ld [rNR32], a + ld a, $ff + ld [rNR33], a + ld a, $87 + ld [rNR34], a + pop hl + pop bc + call PlayPikachuPCM + xor a + ld [wc0f3], a + ld [wc0f4], a + ld a, $80 + ld [rNR52], a + xor a + ld [rNR30], a + ld hl, $ff30 + ld de, wRedrawRowOrColumnSrcTiles +.reloadWaveDataLoop + ld a, [de] + inc de + ld [hli], a + ld a, l + cp $40 ; end of wave data + jr nz, .reloadWaveDataLoop + ld a, $80 + ld [rNR30], a + ld a, [rNR51] + and $bb + ld [rNR51], a + xor a + ld [wChannelSoundIDs + Ch5], a + ld [wChannelSoundIDs + Ch6], a + ld [wChannelSoundIDs + Ch7], a + ld [wChannelSoundIDs + Ch8], a + ld a, [H_LOADEDROMBANK] + ei + ret + +PikachuCriesPointerTable: +; format: +; db bank +; dw pointer to cry + +; bank 21 + pikacry_def PikachuCry1 + pikacry_def PikachuCry2 + pikacry_def PikachuCry3 + pikacry_def PikachuCry4 + +; bank 22 + pikacry_def PikachuCry5 + pikacry_def PikachuCry6 + pikacry_def PikachuCry7 + +; bank 23 + pikacry_def PikachuCry8 + pikacry_def PikachuCry9 + pikacry_def PikachuCry10 + +; bank 24 + pikacry_def PikachuCry11 + pikacry_def PikachuCry12 + pikacry_def PikachuCry13 + +; bank 25 + pikacry_def PikachuCry14 + pikacry_def PikachuCry15 + +; banks 31-34, in no particular order + + pikacry_def PikachuCry16 + pikacry_def PikachuCry17 + pikacry_def PikachuCry18 + pikacry_def PikachuCry19 + pikacry_def PikachuCry20 + pikacry_def PikachuCry21 + pikacry_def PikachuCry22 + pikacry_def PikachuCry23 + pikacry_def PikachuCry24 + pikacry_def PikachuCry25 + pikacry_def PikachuCry26 + +; bank 35 + pikacry_def PikachuCry27 + pikacry_def PikachuCry28 + pikacry_def PikachuCry29 + pikacry_def PikachuCry30 + pikacry_def PikachuCry31 + +; bank 36 + pikacry_def PikachuCry32 + pikacry_def PikachuCry33 + pikacry_def PikachuCry34 + +; bank 37 + pikacry_def PikachuCry35 + pikacry_def PikachuCry36 + +; banks 36-38 + pikacry_def PikachuCry37 + pikacry_def PikachuCry38 + pikacry_def PikachuCry39 + pikacry_def PikachuCry40 + pikacry_def PikachuCry41 + pikacry_def PikachuCry42 diff --git a/engine/pikachu_pic_animation.asm b/engine/pikachu_pic_animation.asm new file mode 100755 index 00000000..c79d9add --- /dev/null +++ b/engine/pikachu_pic_animation.asm @@ -0,0 +1,851 @@ +GetPikaPicAnimationScriptIndex: + ld hl, PikachuMoodLookupTable + ld a, [wPikachuMood] + ld d, a +.get_mood_param + ld a, [hli] + inc hl + cp d + jr c, .get_mood_param + dec hl + ld e, [hl] + ld hl, PikaPicAnimationScriptPointerLookupTable + ld a, [wPikachuHappiness] + ld d, a + ld bc, 6 +.get_happiness_param + ld a, [hl] + cp d + jr nc, .got_animation + add hl, bc + jr .get_happiness_param + +.got_animation + ld d, 0 + add hl, de + ld a, [hl] + ret + +PikachuMoodLookupTable: +; First byte: mood threshold +; Second byte: column index in PikaPicAnimationScriptPointerLookupTable + db 40, 1 + db 127, 2 + db 128, 3 + db 210, 4 + db 255, 5 + +PikaPicAnimationScriptPointerLookupTable: +; First byte: happiness threshold +; Remaining bytes: loaded based on Pikachu's mood + db 50 + dpikapic PikaPicAnimScript14 + dpikapic PikaPicAnimScript14 + dpikapic PikaPicAnimScript6 + dpikapic PikaPicAnimScript13 + dpikapic PikaPicAnimScript13 + + db 100 + dpikapic PikaPicAnimScript9 + dpikapic PikaPicAnimScript9 + dpikapic PikaPicAnimScript5 + dpikapic PikaPicAnimScript12 + dpikapic PikaPicAnimScript12 + + db 130 + dpikapic PikaPicAnimScript3 + dpikapic PikaPicAnimScript3 + dpikapic PikaPicAnimScript1 + dpikapic PikaPicAnimScript8 + dpikapic PikaPicAnimScript8 + + db 160 + dpikapic PikaPicAnimScript3 + dpikapic PikaPicAnimScript3 + dpikapic PikaPicAnimScript4 + dpikapic PikaPicAnimScript15 + dpikapic PikaPicAnimScript15 + + db 200 + dpikapic PikaPicAnimScript17 + dpikapic PikaPicAnimScript17 + dpikapic PikaPicAnimScript7 + dpikapic PikaPicAnimScript2 + dpikapic PikaPicAnimScript2 + + db 250 + dpikapic PikaPicAnimScript17 + dpikapic PikaPicAnimScript17 + dpikapic PikaPicAnimScript16 + dpikapic PikaPicAnimScript10 + dpikapic PikaPicAnimScript10 + + db 255 + dpikapic PikaPicAnimScript17 + dpikapic PikaPicAnimScript17 + dpikapic PikaPicAnimScript19 + dpikapic PikaPicAnimScript20 + dpikapic PikaPicAnimScript20 + +StarterPikachuEmotionCommand_pikapic: + ld a, [H_AUTOBGTRANSFERENABLED] + push af + xor a + ld [H_AUTOBGTRANSFERENABLED], a + ld a, [de] + ld [wPikaPicAnimNumber], a + inc de + push de + call .RunPikapic + pop de + pop af + ld [H_AUTOBGTRANSFERENABLED], a + ret + +.RunPikapic: + call PlacePikapicTextBoxBorder + callab LoadOverworldPikachuFrontpicPalettes + call ResetPikaPicAnimBuffer + call LoadCurrentPikaPicAnimScriptPointer + call ExecutePikaPicAnimScript + call PlacePikapicTextBoxBorder + call RunDefaultPaletteCommand + ret + +ResetPikaPicAnimBuffer: + ld hl, wCurPikaMovementData + ld bc, wCurPikaMovementDataEnd - wCurPikaMovementData + xor a + call FillMemory + ld hl, wPikaPicAnimObjectDataBufferSize + ld bc, wPikaPicAnimObjectDataBufferEnd - wPikaPicAnimObjectDataBufferSize + xor a + call FillMemory + call ClearPikaPicUsedGFXBuffer + ld hl, 100 + ld a, l + ld [wPikaPicAnimTimer], a + ld a, h + ld [wPikaPicAnimTimer + 1], a + ld a, $7 + ld [wPikaPicPikaDrawStartX], a + ld a, $6 + ld [wPikaPicPikaDrawStartY], a + ret + +PlacePikapicTextBoxBorder: + xor a + ld [H_AUTOBGTRANSFERENABLED], a + coord hl, 6, 5 + lb bc, 5, 5 + call TextBoxBorder + call Delay3 + call UpdateSprites + ld a, $1 + ld [H_AUTOBGTRANSFERENABLED], a + call Delay3 + ret + +LoadCurrentPikaPicAnimScriptPointer: + ld a, [wPikaPicAnimNumber] + cp $1d + jr c, .valid + ld a, $0 +.valid + ld e, a + ld d, 0 + ld hl, PikaPicAnimPointers + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + call UpdatePikaPicAnimPointer + ret + +PikaPicAnimPointers: +pikapic_def: macro +\1_id: dw \1 +endm + + pikapic_def PikaPicAnimScript0 ; 00 + pikapic_def PikaPicAnimScript1 ; 01 + pikapic_def PikaPicAnimScript2 ; 02 + pikapic_def PikaPicAnimScript3 ; 03 + pikapic_def PikaPicAnimScript4 ; 04 + pikapic_def PikaPicAnimScript5 ; 05 + pikapic_def PikaPicAnimScript6 ; 06 + pikapic_def PikaPicAnimScript7 ; 07 + pikapic_def PikaPicAnimScript8 ; 08 + pikapic_def PikaPicAnimScript9 ; 09 + pikapic_def PikaPicAnimScript10 ; 0a + pikapic_def PikaPicAnimScript11 ; 0b + pikapic_def PikaPicAnimScript12 ; 0c + pikapic_def PikaPicAnimScript13 ; 0d + pikapic_def PikaPicAnimScript14 ; 0e + pikapic_def PikaPicAnimScript15 ; 0f + pikapic_def PikaPicAnimScript16 ; 10 + pikapic_def PikaPicAnimScript17 ; 11 + pikapic_def PikaPicAnimScript18 ; 12 + pikapic_def PikaPicAnimScript19 ; 13 + pikapic_def PikaPicAnimScript20 ; 14 + pikapic_def PikaPicAnimScript21 ; 15 + pikapic_def PikaPicAnimScript22 ; 16 + pikapic_def PikaPicAnimScript23 ; 17 + pikapic_def PikaPicAnimScript24 ; 18 + pikapic_def PikaPicAnimScript25 ; 19 + pikapic_def PikaPicAnimScript26 ; 1a + pikapic_def PikaPicAnimScript27 ; 1b + pikapic_def PikaPicAnimScript28 ; 1c + pikapic_def PikaPicAnimScript29 ; 1d + +ExecutePikaPicAnimScript: +.loop + xor a + ld [H_AUTOBGTRANSFERENABLED], a + call RunPikaPicAnimSetupScript + call DummyFunction_fdad5 + call AnimateCurrentPikaPicAnimFrame + call DummyFunction_fdad5 + ld a, $1 + ld [H_AUTOBGTRANSFERENABLED], a + call PikaPicAnimTimerAndJoypad + and a + jr z, .loop + ret + +PikaPicAnimTimerAndJoypad: + call Delay3 + call CheckPikaPicAnimTimer + and a + ret nz + call JoypadLowSensitivity + ld a, [hJoyPressed] + and A_BUTTON | B_BUTTON + ret + +CheckPikaPicAnimTimer: + ld hl, wPikaPicAnimTimer + dec [hl] + jr nz, .not_done_yet + inc hl + ld a, [hl] + and a + jr z, .timer_expired + dec [hl] +.not_done_yet + xor a + ret + +.timer_expired + ld a, $1 + ret + +DummyFunction_fdad5: + ret + +AnimateCurrentPikaPicAnimFrame: + ld bc, wPikaPicAnimObjectDataBuffer + ld a, 4 +.loop + push af + push bc + ld hl, 0 ; struct index + add hl, bc + ld a, [hli] + and a + jr z, .skip + ld a, [hli] + ld [wCurPikaPicAnimObjectScriptIdx], a + ld a, [hli] + ld [wCurPikaPicAnimObjectFrameIdx], a + ld a, [hli] + ld [wCurPikaPicAnimObjectFrameTimer], a + ld a, [hli] + ld [wCurPikaPicAnimObjectVTileOffset], a + ld a, [hli] + ld [wCurPikaPicAnimObjectXOffset], a + ld a, [hli] + ld [wCurPikaPicAnimObjectYOffset], a + ld a, [hli] + ld [wCurPikaPicAnimObject + 6], a + push bc + call LoadPikaPicAnimObjectData + pop bc + ld hl, 1 ; script index + add hl, bc + ld a, [wCurPikaPicAnimObjectScriptIdx] + ld [hli], a + ld a, [wCurPikaPicAnimObjectFrameIdx] + ld [hli], a + ld a, [wCurPikaPicAnimObjectFrameTimer] + ld [hli], a + ld a, [wCurPikaPicAnimObjectVTileOffset] + ld [hli], a + ld a, [wCurPikaPicAnimObjectXOffset] + ld [hli], a + ld a, [wCurPikaPicAnimObjectYOffset] + ld [hli], a + ld a, [wCurPikaPicAnimObject + 6] + ld [hl], a +.skip + pop bc + ld hl, 8 + add hl, bc + ld b, h + ld c, l + pop af + dec a + jr nz, .loop + ret + +PikaPicAnimCommand_object: + ld hl, wPikaPicAnimObjectDataBuffer + ld de, 8 + ld c, 4 +.loop + ld a, [hl] + and a + jr z, .found + add hl, de + dec c + jr nz, .loop + scf + ret + +.found + ld a, [wPikaPicAnimObjectDataBufferSize] + inc a + ld [wPikaPicAnimObjectDataBufferSize], a + ld [hli], a + call GetPikaPicAnimByte + ld [hli], a + call GetPikaPicAnimByte + ld [hl], a + xor a + ld [hli], a ; overloads + ld [hli], a + call GetPikaPicAnimByte + ld [hli], a + call GetPikaPicAnimByte + ld [hli], a + call GetPikaPicAnimByte + ld [hli], a + and a + ret + +PikaPicAnimCommand_deleteobject: + call GetPikaPicAnimByte + ld b, a + ld hl, wPikaPicAnimObjectDataBuffer + ld de, 8 + ld c, 4 +.search + ld a, [hl] + cp b + jr z, .delete + add hl, de + dec c + jr nz, .search + scf + ret + +.delete + xor a + ld [hl], a + ret + +LoadPikaPicAnimObjectData: +.loop + ld a, [wCurPikaPicAnimObjectScriptIdx] + cp $23 + jr c, .valid + ld a, $4 +.valid + ld e, a + ld d, 0 + ld hl, PikaPicAnimBGFramesPointers + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + ld a, [wCurPikaPicAnimObjectFrameIdx] + ld e, a + ld d, 0 + add hl, de + add hl, de + ld a, [hli] + cp $e0 + jr z, .end + jr .init + +.end + xor a + ld [wCurPikaPicAnimObjectFrameIdx], a + ld [wCurPikaPicAnimObjectFrameTimer], a + jr .loop + +.init + push hl + call LoadCurPikaPicObjectTilemap + pop hl + ld a, [hl] + and a + jr z, .not_done ; lasts forever + ld a, [wCurPikaPicAnimObjectFrameTimer] + inc a + ld [wCurPikaPicAnimObjectFrameTimer], a + cp [hl] + jr nz, .not_done + xor a + ld [wCurPikaPicAnimObjectFrameTimer], a + ld a, [wCurPikaPicAnimObjectFrameIdx] + inc a + ld [wCurPikaPicAnimObjectFrameIdx], a +.not_done + ret + +INCLUDE "data/pikachu_pic_objects.asm" + +LoadCurPikaPicObjectTilemap: + and a + ret z + ld e, a + ld d, 0 + ld hl, PikaPicTilemapPointers + add hl, de + add hl, de + ld e, [hl] + inc hl + ld d, [hl] + ld a, [de] + ld c, a + inc de + ld a, [de] + ld b, a + inc de + push de + push bc + call .GetStartCoords + pop bc + pop de +.row + push bc + push hl + ld a, [wCurPikaPicAnimObjectVTileOffset] ; tile id offset + ld c, a +.col + ld a, [de] + inc de + cp $ff + jr z, .skip + add c + ld [hl], a +.skip + inc hl + dec b + jr nz, .col + pop hl + ld bc, SCREEN_WIDTH + add hl, bc + pop bc + dec c + jr nz, .row + ret + +.GetStartCoords: + push bc + ld a, [wCurPikaPicAnimObjectYOffset] ; Y offset + ld b, a + ld a, [wPikaPicPikaDrawStartY] + add b + coord hl, 0, 0 + ld bc, SCREEN_WIDTH + call AddNTimes + ld a, [wCurPikaPicAnimObjectXOffset] ; X offset + ld c, a + ld a, [wPikaPicPikaDrawStartX] + add c + ld c, a + ld b, 0 + add hl, bc + pop bc + ret + +INCLUDE "data/pikachu_pic_tilemaps.asm" + +LoadPikaPicAnimGFXHeader: + push hl + ld e, a + ld d, 0 + ld hl, PikaPicAnimGFXHeaders + add hl, de + add hl, de + add hl, de + add hl, de + ld a, [hli] + ld c, a + ld a, [hli] + ld b, a + ld a, [hli] + ld e, a + ld a, [hli] + ld d, a + pop hl + ret + +RunPikaPicAnimSetupScript: + call .CheckAndAdvanceTimer + ret c + xor a + ld [wPikaPicAnimPointerSetupFinished], a +.loop + call GetPikaPicAnimByte + ld e, a + ld d, 0 + ld hl, .Jumptable + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + call JumpToAddress + ld a, [wPikaPicAnimPointerSetupFinished] + and a + jr z, .loop + ret + +.CheckAndAdvanceTimer: + ld a, [wPikaPicAnimDelay] + and a + ret z + dec a + ld [wPikaPicAnimDelay], a + scf + ret + +.Jumptable: + dw PikaPicAnimCommand_nop ; 00, 0 params + dw PikaPicAnimCommand_writebyte ; 01, 1 param + dw PikaPicAnimCommand_loadgfx ; 02, 1 param + dw PikaPicAnimCommand_object ; 03, 5 params + dw PikaPicAnimCommand_nop4 ; 04, 0 params + dw PikaPicAnimCommand_nop5 ; 05, 0 params + dw PikaPicAnimCommand_deleteobject ; 06, 1 param + dw PikaPicAnimCommand_nop7 ; 07, 0 params + dw PikaPicAnimCommand_nop8 ; 08, 0 params + dw PikaPicAnimCommand_jump ; 09, 1 dw param + dw PikaPicAnimCommand_setduration ; 0a, 1 dw param + dw PikaPicAnimCommand_cry ; 0b, 1 param + dw PikaPicAnimCommand_thunderbolt ; 0c, 0 params + dw PikaPicAnimCommand_run ; 0d, 0 params (ret) + dw PikaPicAnimCommand_ret ; 0e, 0 params (ret) + +PikaPicAnimCommand_nop: + ret + +PikaPicAnimCommand_ret: + ld a, 1 + ld [wPikaPicAnimTimer], a + xor a + ld [wPikaPicAnimTimer + 1], a + jr PikaPicAnimCommand_run + +; XXX + ret + +PikaPicAnimCommand_setduration: + call GetPikaPicAnimByte + ld [wPikaPicAnimTimer], a + call GetPikaPicAnimByte + ld [wPikaPicAnimTimer + 1], a + ret + +PikaPicAnimCommand_run: + ld a, $ff + ld [wPikaPicAnimPointerSetupFinished], a + ret + +PikaPicAnimCommand_writebyte: + call GetPikaPicAnimByte + ld [wPikaPicAnimDelay], a + ret + +PikaPicAnimCommand_nop4: +PikaPicAnimCommand_nop5: +PikaPicAnimCommand_nop7: +PikaPicAnimCommand_nop8: + ret + +PikaPicAnimCommand_jump: + call GetPikaPicAnimByte + ld l, a + call GetPikaPicAnimByte + ld h, a + call UpdatePikaPicAnimPointer + ret + +GetPikaPicAnimByte: + push hl + ld hl, wPikaPicAnimPointer + ld a, [hli] + ld h, [hl] + ld l, a + ld a, [hli] + call UpdatePikaPicAnimPointer + pop hl + ret + +UpdatePikaPicAnimPointer: + push af + ld a, l + ld [wPikaPicAnimPointer], a + ld a, h + ld [wPikaPicAnimPointer + 1], a + pop af + ret + +PikaPicAnimCommand_loadgfx: + ld a, [wUpdateSpritesEnabled] + push af + ld a, $ff + ld [wUpdateSpritesEnabled], a + ld a, [H_AUTOBGTRANSFERENABLED] + push af + xor a + ld [H_AUTOBGTRANSFERENABLED], a + ld a, [hTilesetType] + push af + xor a + ld [hTilesetType], a + call GetPikaPicAnimByte + ld [wPikaPicAnimCurGraphicID], a + ld a, [wPikaPicAnimCurGraphicID] + call LoadPikaPicAnimGFXHeader + ld a, c + cp a, $ff + jr z, .compressed + call RequestPikaPicAnimGFX + jr .done + +.compressed + call DecompressRequestPikaPicAnimGFX +.done + pop af + ld [hTilesetType], a + pop af + ld [H_AUTOBGTRANSFERENABLED], a + pop af + ld [wUpdateSpritesEnabled], a + ret + +RequestPikaPicAnimGFX: + push de + ld a, [wPikaPicAnimCurGraphicID] + ld d, a + ld e, c + call CheckIfThereIsRoomForPikaPicAnimGFX + pop de + jr c, .failed + call GetPikaPicVRAMAddressForNewGFX + call CopyVideoDataAlternate + and a +.failed + ret + +DecompressRequestPikaPicAnimGFX: + push de + ld a, [wPikaPicAnimCurGraphicID] + ld d, a + ld e, 5 * 5 + call CheckIfThereIsRoomForPikaPicAnimGFX + pop de + jr c, .failed + ld a, b + call UncompressSpriteFromDE + ld a, BANK(sSpriteBuffer1) + call SwitchSRAMBankAndLatchClockData + ld hl, sSpriteBuffer1 + ld de, sSpriteBuffer0 + ld bc, SPRITEBUFFERSIZE * 2 + call CopyData + call PrepareRTCDataAndDisableSRAM + ld a, [wPikaPicAnimCurGraphicID] + call LookUpTileOffsetForCurrentPikaPicAnimGFX + call GetPikaPicVRAMAddressForNewGFX + ld d, h + ld e, l + call InterlaceMergeSpriteBuffers +.failed + ret + +ClearPikaPicUsedGFXBuffer: + ld hl, wPikaPicUsedGFXCount + ld bc, wPikaPicUsedGFXEnd - wPikaPicUsedGFXCount + xor a + call FillMemory + ret + +GetPikaPicVRAMAddressForNewGFX: + ld hl, vNPCSprites + push bc + ld b, a + and $f + swap a + ld c, a + ld a, b + and $f0 + swap a + ld b, a + add hl, bc + pop bc + ret + +CheckIfThereIsRoomForPikaPicAnimGFX: +; d: idx +; e: size +; FATAL: If the graphic has already been loaded, or if there are +; already 8 graphics objects loaded, the game will execute arbitrary +; code. + push bc + push hl + ld hl, wPikaPicUsedGFX + ld c, 8 +.loop + ld a, [hl] + and a + jr z, .empty + cp d + jr z, .found + inc hl + inc hl + dec c + jr nz, .loop + scf + ret ; execute hl, then bc + +.found + inc hl + ld a, [hl] + ret ; execute hl, then bc + +.empty + ld [hl], d + inc hl + ld a, [wPikaPicUsedGFXCount] + add $80 + ld [hl], a + ld a, [wPikaPicUsedGFXCount] + add e + ld [wPikaPicUsedGFXCount], a + cp $80 + jr z, .okay + jr nc, .failed +.okay + ld a, [hl] + and a + jr .pop_ret + +.failed + scf +.pop_ret + pop hl + pop bc + ret + +LookUpTileOffsetForCurrentPikaPicAnimGFX: + push bc + push hl + ld b, a + ld hl, wPikaPicUsedGFX + ld c, 8 +.loop + ld a, [hli] + cp b + jr z, .found + inc hl + dec c + jr nz, .loop + scf + jr .pop_ret + +.found + ld a, [hl] + and a +.pop_ret + pop hl + pop bc + ret + +PikaPicAnimCommand_cry: + call GetPikaPicAnimByte + cp $ff + ret z + ld e, a + callab PlayPikachuSoundClip + ret + +PikaPicAnimCommand_thunderbolt: + ld a, $1 + ld [wMuteAudioAndPauseMusic], a + call DelayFrame + ld a, [wAudioROMBank] + push af + ld a, BANK(SFX_Battle_2F) + ld [wAudioROMBank], a + ld [wAudioSavedROMBank], a + call .LoadAudio + call PlaySound + call .FlashScreen + call WaitForSoundToFinish + pop af + ld [wAudioROMBank], a + ld [wAudioSavedROMBank], a + xor a + ld [wMuteAudioAndPauseMusic], a + ret + +.LoadAudio: + ld hl, MoveSoundTable + ld e, THUNDERBOLT + ld d, 0 + add hl, de + add hl, de + add hl, de + ld a, BANK(MoveSoundTable) + call GetFarByte + ld b, a + inc hl + ld a, BANK(MoveSoundTable) + call GetFarByte + inc hl + ld [wFrequencyModifier], a + ld a, BANK(MoveSoundTable) + call GetFarByte + ld [wTempoModifier], a + ld a, b + ret + +.FlashScreen: + ld hl, PikaPicAnimThunderboltPals +.loop + ld a, [hli] + cp $ff + ret z + ld c, a + ld b, [hl] + inc hl + push hl + call .UpdatePal + pop hl + jr .loop + +.UpdatePal: + ld a, b + ld [rBGP], a + call UpdateGBCPal_BGP + call DelayFrames + ret + +INCLUDE "data/pikachu_pic_animation.asm" diff --git a/engine/pikachu_status.asm b/engine/pikachu_status.asm new file mode 100755 index 00000000..c73d3b3f --- /dev/null +++ b/engine/pikachu_status.asm @@ -0,0 +1,258 @@ +IsStarterPikachuInOurParty:: + ld hl, wPartySpecies + ld de, wPartyMon1OTID + ld bc, wPartyMonOT + push hl +.loop + pop hl + ld a, [hli] + push hl + inc a + jr z, .noPlayerPikachu + cp PIKACHU + 1 + jr nz, .curMonNotPlayerPikachu + ld h, d + ld l, e + ld a, [wPlayerID] + cp [hl] + jr nz, .curMonNotPlayerPikachu + inc hl + ld a, [wPlayerID+1] + cp [hl] + jr nz, .curMonNotPlayerPikachu + push de + push bc + ld hl, wPlayerName + ld d, $6 ; possible player length - 1 +.nameCompareLoop + dec d + jr z, .sameOT + ld a, [bc] + inc bc + cp [hl] + inc hl + jr z, .nameCompareLoop + pop bc + pop de +.curMonNotPlayerPikachu + ld hl, wPartyMon2 - wPartyMon1 + add hl, de + ld d, h + ld e, l + ld hl, NAME_LENGTH + add hl, bc + ld b, h + ld c, l + jr .loop + +.sameOT + pop bc + pop de + ld h, d + ld l, e + ld bc, -NAME_LENGTH + add hl, bc + ld a, [hli] + or [hl] + jr z, .noPlayerPikachu ; XXX how is this determined? + pop hl + scf + ret + +.noPlayerPikachu + pop hl + and a + ret + +IsThisPartymonStarterPikachu_Box:: + ld hl, wBoxMon1 + ld bc, wBoxMon2 - wBoxMon1 + ld de, wBoxMonOT + jr asm_fce21 + +IsThisPartymonStarterPikachu_Party:: +IsThisPartymonStarterPikachu:: + ld hl, wPartyMon1 + ld bc, wPartyMon2 - wPartyMon1 + ld de, wPartyMonOT +asm_fce21: + ld a, [wWhichPokemon] + call AddNTimes + ld a, [hl] + cp PIKACHU + jr nz, .notPlayerPikachu + ld bc, wPartyMon1OTID - wPartyMon1 + add hl, bc + ld a, [wPlayerID] + cp [hl] + jr nz, .notPlayerPikachu + inc hl + ld a, [wPlayerID+1] + cp [hl] + jr nz, .notPlayerPikachu + ld h, d + ld l, e + ld a, [wWhichPokemon] + ld bc, NAME_LENGTH + call AddNTimes + ld de, wPlayerName + ld b, $6 +.loop + dec b + jr z, .isPlayerPikachu + ld a, [de] + inc de + cp [hl] + inc hl + jr z, .loop +.notPlayerPikachu + and a + ret + +.isPlayerPikachu + scf + ret + +UpdatePikachuMoodAfterBattle:: +; because d is always $82 at this function, it serves to +; ensure Pikachu's mood is at least 130 after battle + push de + call IsStarterPikachuInOurParty + pop de + ret nc + ld a, d + cp 128 + ld a, [wPikachuMood] + jr c, .d_less_than_128 ; we never jump + cp d + jr c, .load_d_into_mood + ret + +.d_less_than_128 + cp d + ret c +.load_d_into_mood + ld a, d + ld [wPikachuMood], a + ret + +CheckPikachuFaintedOrStatused:: +; function to test if Pikachu is alive? + xor a + ld [wWhichPokemon], a + ld hl, wPartyCount +.loop + inc hl + ld a, [hl] + cp $ff + jr z, .dead_or_not_in_party + push hl + call IsThisPartymonStarterPikachu_Party + pop hl + jr nc, .next + ld a, [wWhichPokemon] + ld hl, wPartyMon1HP + ld bc, wPartyMon2 - wPartyMon1 + call AddNTimes + ld a, [hli] + or [hl] + ld d, a + inc hl + inc hl + ld a, [hl] ; status + and a + jr nz, .alive + jr .dead_or_not_in_party + +.next + ld a, [wWhichPokemon] + inc a + ld [wWhichPokemon], a + jr .loop + +.alive + scf + ret + +.dead_or_not_in_party + and a + ret + +IsSurfingPikachuInThePlayersParty:: + ld hl, wPartySpecies + ld de, wPartyMon1Moves + ld bc, wPartyMonOT + push hl +.loop + pop hl + ld a, [hli] + push hl + inc a + jr z, .noSurfingPlayerPikachu + cp PIKACHU+1 + jr nz, .curMonNotSurfingPlayerPikachu + ld h, d + ld l, e + push hl + push bc + ld b, NUM_MOVES +.moveSearchLoop + ld a, [hli] + cp SURF + jr z, .foundSurfingPikachu + dec b + jr nz, .moveSearchLoop + pop bc + pop hl + jr .curMonNotSurfingPlayerPikachu + +.foundSurfingPikachu + pop bc + pop hl + inc hl + inc hl + inc hl + inc hl + ld a, [wPlayerID] + cp [hl] + jr nz, .curMonNotSurfingPlayerPikachu + inc hl + ld a, [wPlayerID+1] + cp [hl] + jr nz, .curMonNotSurfingPlayerPikachu + push de + push bc + ld hl, wPlayerName + ld d, $6 +.nameCompareLoop + dec d + jr z, .foundSurfingPlayerPikachu + ld a, [bc] + inc bc + cp [hl] + inc hl + jr z, .nameCompareLoop + pop bc + pop de +.curMonNotSurfingPlayerPikachu + ld hl, wPartyMon2 - wPartyMon1 + add hl, de + ld d, h + ld e, l + ld hl, NAME_LENGTH + add hl, bc + ld b, h + ld c, l + jr .loop + +.foundSurfingPlayerPikachu + pop bc + pop de + pop hl + scf + ret + +.noSurfingPlayerPikachu + pop hl + and a + ret diff --git a/engine/play_time.asm b/engine/play_time.asm deleted file mode 100755 index a5202cc6..00000000 --- a/engine/play_time.asm +++ /dev/null @@ -1,61 +0,0 @@ -TrackPlayTime: - call CountDownIgnoreInputBitReset - ld a, [wd732] - bit 0, a - ret z - ld a, [wPlayTimeMaxed] - and a - ret nz - ld a, [wPlayTimeFrames] - inc a - ld [wPlayTimeFrames], a - cp 60 - ret nz - xor a - ld [wPlayTimeFrames], a - ld a, [wPlayTimeSeconds] - inc a - ld [wPlayTimeSeconds], a - cp 60 - ret nz - xor a - ld [wPlayTimeSeconds], a - ld a, [wPlayTimeMinutes] - inc a - ld [wPlayTimeMinutes], a - cp 60 - ret nz - xor a - ld [wPlayTimeMinutes], a - ld a, [wPlayTimeHours] - inc a - ld [wPlayTimeHours], a - cp $ff - ret nz - ld a, $ff - ld [wPlayTimeMaxed], a - ret - -CountDownIgnoreInputBitReset: - ld a, [wIgnoreInputCounter] - and a - jr nz, .asm_18e40 - ld a, $ff - jr .asm_18e41 -.asm_18e40 - dec a -.asm_18e41 - ld [wIgnoreInputCounter], a - and a - ret nz - ld a, [wd730] - res 1, a - res 2, a - bit 5, a - res 5, a - ld [wd730], a - ret z - xor a - ld [hJoyPressed], a - ld [hJoyHeld], a - ret diff --git a/engine/pokedex_rating.asm b/engine/pokedex_rating.asm index f1aaf618..4dfb6b39 100755 --- a/engine/pokedex_rating.asm +++ b/engine/pokedex_rating.asm @@ -26,7 +26,7 @@ DisplayDexRating: CheckAndResetEventA EVENT_HALL_OF_FAME_DEX_RATING jr nz, .hallOfFame push hl - ld hl, PokedexRatingText_441cc + ld hl, DexCompletionText call PrintText pop hl call PrintText @@ -51,104 +51,104 @@ DisplayDexRating: ld [de], a ret -PokedexRatingText_441cc: - TX_FAR _OaksLabText_441cc +DexCompletionText: + TX_FAR _DexCompletionText db "@" DexRatingsTable: db 10 - dw PokedexRatingText_44201 + dw DexRatingText_Own0To9 db 20 - dw PokedexRatingText_44206 + dw DexRatingText_Own10To19 db 30 - dw PokedexRatingText_4420b + dw DexRatingText_Own20To29 db 40 - dw PokedexRatingText_44210 + dw DexRatingText_Own30To39 db 50 - dw PokedexRatingText_44215 + dw DexRatingText_Own40To49 db 60 - dw PokedexRatingText_4421a + dw DexRatingText_Own50To59 db 70 - dw PokedexRatingText_4421f + dw DexRatingText_Own60To69 db 80 - dw PokedexRatingText_44224 + dw DexRatingText_Own70To79 db 90 - dw PokedexRatingText_44229 + dw DexRatingText_Own80To89 db 100 - dw PokedexRatingText_4422e + dw DexRatingText_Own90To99 db 110 - dw PokedexRatingText_44233 + dw DexRatingText_Own100To109 db 120 - dw PokedexRatingText_44238 + dw DexRatingText_Own110To119 db 130 - dw PokedexRatingText_4423d + dw DexRatingText_Own120To129 db 140 - dw PokedexRatingText_44242 + dw DexRatingText_Own130To139 db 150 - dw PokedexRatingText_44247 + dw DexRatingText_Own140To149 db NUM_POKEMON + 1 - dw PokedexRatingText_4424c + dw DexRatingText_Own150To151 -PokedexRatingText_44201: - TX_FAR _OaksLabText_44201 +DexRatingText_Own0To9: + TX_FAR _DexRatingText_Own0To9 db "@" -PokedexRatingText_44206: - TX_FAR _OaksLabText_44206 +DexRatingText_Own10To19: + TX_FAR _DexRatingText_Own10To19 db "@" -PokedexRatingText_4420b: - TX_FAR _OaksLabText_4420b +DexRatingText_Own20To29: + TX_FAR _DexRatingText_Own20To29 db "@" -PokedexRatingText_44210: - TX_FAR _OaksLabText_44210 +DexRatingText_Own30To39: + TX_FAR _DexRatingText_Own30To39 db "@" -PokedexRatingText_44215: - TX_FAR _OaksLabText_44215 +DexRatingText_Own40To49: + TX_FAR _DexRatingText_Own40To49 db "@" -PokedexRatingText_4421a: - TX_FAR _OaksLabText_4421a +DexRatingText_Own50To59: + TX_FAR _DexRatingText_Own50To59 db "@" -PokedexRatingText_4421f: - TX_FAR _OaksLabText_4421f +DexRatingText_Own60To69: + TX_FAR _DexRatingText_Own60To69 db "@" -PokedexRatingText_44224: - TX_FAR _OaksLabText_44224 +DexRatingText_Own70To79: + TX_FAR _DexRatingText_Own70To79 db "@" -PokedexRatingText_44229: - TX_FAR _OaksLabText_44229 +DexRatingText_Own80To89: + TX_FAR _DexRatingText_Own80To89 db "@" -PokedexRatingText_4422e: - TX_FAR _OaksLabText_4422e +DexRatingText_Own90To99: + TX_FAR _DexRatingText_Own90To99 db "@" -PokedexRatingText_44233: - TX_FAR _OaksLabText_44233 +DexRatingText_Own100To109: + TX_FAR _DexRatingText_Own100To109 db "@" -PokedexRatingText_44238: - TX_FAR _OaksLabText_44238 +DexRatingText_Own110To119: + TX_FAR _DexRatingText_Own110To119 db "@" -PokedexRatingText_4423d: - TX_FAR _OaksLabText_4423d +DexRatingText_Own120To129: + TX_FAR _DexRatingText_Own120To129 db "@" -PokedexRatingText_44242: - TX_FAR _OaksLabText_44242 +DexRatingText_Own130To139: + TX_FAR _DexRatingText_Own130To139 db "@" -PokedexRatingText_44247: - TX_FAR _OaksLabText_44247 +DexRatingText_Own140To149: + TX_FAR _DexRatingText_Own140To149 db "@" -PokedexRatingText_4424c: - TX_FAR _OaksLabText_4424c +DexRatingText_Own150To151: + TX_FAR _DexRatingText_Own150To151 db "@" diff --git a/engine/predefs.asm b/engine/predefs.asm index 6f605043..cc6af5ac 100755 --- a/engine/predefs.asm +++ b/engine/predefs.asm @@ -1,8 +1,8 @@ GetPredefPointer: -; Store the contents of the register -; pairs (hl, de, bc) at wPredefRegisters. -; Then put the bank and address of predef -; wPredefID in [wPredefBank] and hl. + ; Store the contents of the register + ; pairs (hl, de, bc) at wPredefRegisters. + ; Then put the bank and address of predef + ; wPredefID in [wPredefBank] and hl. ld a, h ld [wPredefRegisters], a @@ -50,15 +50,16 @@ GetPredefPointer: ret PredefPointers:: -; these are pointers to ASM routines. -; they appear to be used in overworld map scripts. + ; these are pointers to ASM routines. + ; they appear to be used in overworld map scripts. + const_def add_predef DrawPlayerHUDAndHPBar add_predef CopyUncompressedPicToTilemap add_predef AnimateSendingOutMon add_predef ScaleSpriteByTwo add_predef LoadMonBackPic add_predef CopyDownscaledMonTiles - dbw $03,JumpMoveEffect ; wrong bank + add_predef Func_f0a7 add_predef HealParty add_predef MoveAnimation add_predef DivideBCDPredef @@ -81,8 +82,12 @@ PredefPointers:: add_predef LearnMoveFromLevelUp add_predef LearnMove add_predef GetQuantityOfItemInBag - dbw $03,CheckForHiddenObjectOrBookshelfOrCardKeyDoor ; home bank - dbw $03,GiveItem ; home bank + + predef_const CheckForHiddenObjectOrBookshelfOrCardKeyDoor + predef_const GiveItem + dbw $03, CheckForHiddenObjectOrBookshelfOrCardKeyDoor ; home bank + dbw $03, GiveItem ; home bank + add_predef ChangeBGPalColor0_4Frames add_predef FindPathToPlayer add_predef PredefShakeScreenVertically @@ -129,7 +134,7 @@ PredefPointers:: add_predef LoadTownMap_Nest add_predef PrintMonType add_predef EmotionBubble - add_predef EmptyFunc3; return immediately + add_predef EmptyFunc3 ; return immediately add_predef AskName add_predef PewterGuys add_predef SaveSAVtoSRAM2 @@ -139,6 +144,9 @@ PredefPointers:: add_predef DoInGameTradeDialogue add_predef HallOfFamePC add_predef DisplayDexRating + + predef_const _LeaveMapAnim + predef_const EnterMapAnim dbw $1E, _LeaveMapAnim ; wrong bank dbw $1E, EnterMapAnim ; wrong bank add_predef GetTileTwoStepsInFrontOfPlayer diff --git a/engine/predefs7.asm b/engine/predefs7.asm index 752bdd1a..bfa0ab57 100755 --- a/engine/predefs7.asm +++ b/engine/predefs7.asm @@ -1,6 +1,12 @@ DisplayElevatorFloorMenu: + ld hl, wd730 + ld a, [hl] + push af + set 6, [hl] ld hl, WhichFloorText call PrintText + pop af + ld [wd730], a ld hl, wItemList ld a, l ld [wListPointer], a diff --git a/engine/predefs12.asm b/engine/predefsA.asm index 95f0ea25..e25735c5 100755..100644 --- a/engine/predefs12.asm +++ b/engine/predefsA.asm @@ -1,14 +1,16 @@ -; b = new colour for BG colour 0 (usually white) for 4 frames +; inverts the BGP for 4 (6 on CGB due to lag) frames ChangeBGPalColor0_4Frames: - call GetPredefRegisters + call GetPredefRegisters ; leftover of red/blue, has no use here ld a, [rBGP] - or b + xor $ff ld [rBGP], a + call UpdateGBCPal_BGP ld c, 4 call DelayFrames ld a, [rBGP] - and %11111100 + xor $ff ld [rBGP], a + call UpdateGBCPal_BGP ret PredefShakeScreenVertically: diff --git a/engine/print_waiting_text.asm b/engine/print_waiting_text.asm index 7a95da2a..bd2180a1 100644 --- a/engine/print_waiting_text.asm +++ b/engine/print_waiting_text.asm @@ -1,15 +1,14 @@ PrintWaitingText: coord hl, 3, 10 - ld b, $1 - ld c, $b + lb bc, 1, 11 ld a, [wIsInBattle] and a - jr z, .asm_4c17 + jr z, .asm_4b9a call TextBoxBorder - jr .asm_4c1a -.asm_4c17 + jr .asm_4b9d +.asm_4b9a call CableClub_TextBoxBorder -.asm_4c1a +.asm_4b9d coord hl, 4, 11 ld de, WaitingText call PlaceString diff --git a/engine/printer.asm b/engine/printer.asm new file mode 100644 index 00000000..5be5286c --- /dev/null +++ b/engine/printer.asm @@ -0,0 +1,999 @@ + const_def + const PRINTER_STATUS_BLANK + const PRINTER_STATUS_CHECKING_LINK + const PRINTER_STATUS_TRANSMITTING + const PRINTER_STATUS_PRINTING + const PRINTER_ERROR_1 + const PRINTER_ERROR_2 + const PRINTER_ERROR_3 + const PRINTER_ERROR_4 + const PRINTER_ERROR_WRONG_DEVICE + +INCLUDE "engine/printer/serial.asm" + +PrintPokedexEntry: + ld a, [wUpdateSpritesEnabled] + push af + xor a + ld [wUpdateSpritesEnabled], a + ld [hCanceledPrinting], a + call Printer_PlayPrinterMusic + ld a, [rIE] + push af + xor a + ld [rIF], a + ld a, $9 + ld [rIE], a + xor a + ld [H_AUTOBGTRANSFERENABLED], a + call Printer_GetDexEntryRegisters + call Printer_StartTransmission + ld a, [wPrinterPokedexMonIsOwned] + and a + jr z, .not_caught + ld a, 16 + jr .got_size + +.not_caught + ld a, 19 +.got_size + ld [wcae2], a + call Printer_CopyTileMapToPrinterTileBuffer + call ClearScreen + callab Pokedex_DrawInterface + callab Pokedex_PlacePokemonList + ld a, $1 + ld [H_AUTOBGTRANSFERENABLED], a + call .TryPrintPage + jr c, .finish_printing + ld a, [wPrinterPokedexMonIsOwned] + and a + jr z, .finish_printing + xor a + ld [wPrinterConnectionOpen], a + ld [wPrinterOpcode], a + ld c, $c + call DelayFrames + call SaveScreenTilesToBuffer1 + xor a + ld [H_AUTOBGTRANSFERENABLED], a + call Printer_PrepareDexEntryForPrinting + ld a, $7 + call Printer_StartTransmission + ld a, $3 + ld [wcae2], a + call Printer_CopyTileMapToPrinterTileBuffer + call LoadScreenTilesFromBuffer1 + ld a, $1 + ld [H_AUTOBGTRANSFERENABLED], a + call .TryPrintPage +.finish_printing + xor a + ld [wPrinterConnectionOpen], a + ld [wPrinterOpcode], a + xor a + ld [rIF], a + pop af + ld [rIE], a + call ReloadMapAfterPrinter + call Printer_PlayMapMusic + pop af + ld [wUpdateSpritesEnabled], a + ret + +.TryPrintPage: + call Printer_ResetJoypadHRAM +.print_loop + call JoypadLowSensitivity + call Printer_CheckPressingB + jr c, .pressed_b + ld a, [wPrinterSendState] + bit 7, a + jr nz, .completed + call PrinterTransmissionJumptable + call GBPrinter_CheckForErrors + call GBPrinter_UpdateStatusMessage + call DelayFrame + jr .print_loop + +.completed + and a + ret + +.pressed_b + scf + ret + +Printer_GetDexEntryRegisters: + callab DrawDexEntryOnScreen + ld a, l + ld [wPrinterPokedexEntryTextPointer], a + ld a, h + ld [wPrinterPokedexEntryTextPointer + 1], a + ld a, $0 + rla ; copy carry flag state to bit 0 + ld [wPrinterPokedexMonIsOwned], a + and a + jr z, .not_caught + ld a, $5 + jr .got_num_rows + +.not_caught + ld a, $9 +.got_num_rows + ret + +Printer_PrepareDexEntryForPrinting: + call ClearScreen + callab Pokedex_PrepareDexEntryForPrinting + ret + +PrintSurfingMinigameHighScore: + xor a + ld [hCanceledPrinting], a + call Printer_PlayPrinterMusic + call Printer_PrepareSurfingMinigameHighScoreTileMap + ld a, [rIE] + push af + xor a + ld [rIF], a + ld a, $9 + ld [rIE], a + call StartTransmission_Send9Rows + ld a, $13 + ld [wcae2], a + call Printer_CopyTileMapToPrinterTileBuffer + call Printer_ResetJoypadHRAM +.loop + call JoypadLowSensitivity + call Printer_CheckPressingB + jr c, .quit + ld a, [wPrinterSendState] + bit 7, a + jr nz, .quit + call PrinterTransmissionJumptable + call GBPrinter_CheckForErrors + call GBPrinter_UpdateStatusMessage + call DelayFrame + jr .loop + +.quit + xor a + ld [wPrinterConnectionOpen], a + ld [wPrinterOpcode], a + call Printer_CopyTileMapFromPrinterTileBuffer + xor a + ld [rIF], a + pop af + ld [rIE], a + call ReloadMapAfterPrinter + call Printer_PlayMapMusic + ret + +PrintDiploma: + xor a + ld [hCanceledPrinting], a + call Printer_PlayPrinterMusic + call _DisplayDiploma + ld a, [rIE] + push af + xor a + ld [rIF], a + ld a, $9 + ld [rIE], a + call StartTransmission_Send9Rows + ld a, $10 + ld [wcae2], a + call Printer_CopyTileMapToPrinterTileBuffer + call Func_e8d11 + jr c, .asm_e8cfa + xor a + ld [wPrinterConnectionOpen], a + ld [wPrinterOpcode], a + ld c, $c + call DelayFrames + call SaveScreenTilesToBuffer1 + xor a + ld [H_AUTOBGTRANSFERENABLED], a + call Func_e9ad3 + call StartTransmission_Send9Rows + ld a, $3 + ld [wcae2], a + call Printer_CopyTileMapToPrinterTileBuffer + call LoadScreenTilesFromBuffer1 + call Func_e8d11 +.asm_e8cfa + xor a + ld [wPrinterConnectionOpen], a + ld [wPrinterOpcode], a + call Printer_CopyTileMapFromPrinterTileBuffer + xor a + ld [rIF], a + pop af + ld [rIE], a + call ReloadMapAfterPrinter + call Printer_PlayMapMusic + ret + +Func_e8d11: + call Printer_ResetJoypadHRAM +.asm_e8d14 + call JoypadLowSensitivity + call Printer_CheckPressingB + jr c, .asm_e8d33 + ld a, [wPrinterSendState] + bit 7, a + jr nz, .asm_e8d31 + call PrinterTransmissionJumptable + call GBPrinter_CheckForErrors + call GBPrinter_UpdateStatusMessage + call DelayFrame + jr .asm_e8d14 + +.asm_e8d31 + and a + ret + +.asm_e8d33 + scf + ret + +PrintPCBox:: + ld a, [wBoxDataStart] + and a + jp z, Func_e8df4 + ld a, [wUpdateSpritesEnabled] + push af + xor a + ld [wUpdateSpritesEnabled], a + ld [hCanceledPrinting], a + call Printer_PlayPrinterMusic + ld a, [rIE] + push af + xor a + ld [rIF], a + ld a, $9 + ld [rIE], a + call SaveScreenTilesToBuffer1 + xor a + ld [H_AUTOBGTRANSFERENABLED], a + call PrintPCBox_DrawPage1 + call StartTransmission_Send9Rows + ld a, $10 + ld [wcae2], a + call Printer_CopyTileMapToPrinterTileBuffer + call LoadScreenTilesFromBuffer1 + call Func_e8dfb + jr c, .asm_e8ddc + xor a + ld [wPrinterConnectionOpen], a + ld [wPrinterOpcode], a + ld c, 12 + call DelayFrames + xor a + ld [H_AUTOBGTRANSFERENABLED], a + call PrintPCBox_DrawPage2 + call StartTransmission_Send9Rows + ld a, $0 + ld [wcae2], a + call Printer_CopyTileMapToPrinterTileBuffer + call LoadScreenTilesFromBuffer1 + call Func_e8dfb + jr c, .asm_e8ddc + xor a + ld [wPrinterConnectionOpen], a + ld [wPrinterOpcode], a + ld c, 12 + call DelayFrames + xor a + ld [H_AUTOBGTRANSFERENABLED], a + call PrintPCBox_DrawPage3 + call StartTransmission_Send9Rows + ld a, $0 + ld [wcae2], a + call Printer_CopyTileMapToPrinterTileBuffer + call LoadScreenTilesFromBuffer1 + call Func_e8dfb + jr c, .asm_e8ddc + xor a + ld [wPrinterConnectionOpen], a + ld [wPrinterOpcode], a + ld c, 12 + call DelayFrames + xor a + ld [H_AUTOBGTRANSFERENABLED], a + call PrintPCBox_DrawPage4 + call StartTransmission_Send9Rows + ld a, $3 + ld [wcae2], a + call Printer_CopyTileMapToPrinterTileBuffer + call LoadScreenTilesFromBuffer1 + call Func_e8dfb +.asm_e8ddc + xor a + ld [wPrinterConnectionOpen], a + ld [wPrinterOpcode], a + xor a + ld [rIF], a + pop af + ld [rIE], a + call ReloadMapAfterPrinter + call Printer_PlayMapMusic + pop af + ld [wUpdateSpritesEnabled], a + ret + +Func_e8df4: + ld hl, String_e8e1f + call PrintText + ret + +Func_e8dfb: + call Printer_ResetJoypadHRAM +.asm_e8dfe + call JoypadLowSensitivity + call Printer_CheckPressingB + jr c, .asm_e8e1d + ld a, [wPrinterSendState] + bit 7, a + jr nz, .asm_e8e1b + call PrinterTransmissionJumptable + call GBPrinter_CheckForErrors + call GBPrinter_UpdateStatusMessage + call DelayFrame + jr .asm_e8dfe + +.asm_e8e1b + and a + ret + +.asm_e8e1d + scf + ret + +String_e8e1f: + TX_FAR _NoPokemonText + db "@" + +PrintFanClubPortrait: + xor a + ld [hCanceledPrinting], a + call Printer_PlayPrinterMusic + call Printer_GetMonStats + ld a, [rIE] + push af + xor a + ld [rIF], a + ld a, $9 + ld [rIE], a + call StartTransmission_Send9Rows + ld a, $13 + ld [wcae2], a + call Printer_CopyTileMapToPrinterTileBuffer + call Printer_ResetJoypadHRAM +.asm_e8e45 + call JoypadLowSensitivity + call Printer_CheckPressingB + jr c, .asm_e8e62 + ld a, [wPrinterSendState] + bit 7, a + jr nz, .asm_e8e62 + call PrinterTransmissionJumptable + call GBPrinter_CheckForErrors + call GBPrinter_UpdateStatusMessage + call DelayFrame + jr .asm_e8e45 + +.asm_e8e62 + xor a + ld [wPrinterConnectionOpen], a + ld [wPrinterOpcode], a + call Printer_CopyTileMapFromPrinterTileBuffer + xor a + ld [rIF], a + pop af + ld [rIE], a + call ReloadMapAfterPrinter + call Printer_PlayMapMusic + ret + +PrinterDebug: + push af + push bc + push de + push hl + call StopAllMusic + ld a, [rIE] + push af + xor a + ld [rIF], a + ld a, $9 + ld [rIE], a + call StartTransmission_Send9Rows + ld a, $13 + ld [wcae2], a + ld a, $1 + ld [H_AUTOBGTRANSFERENABLED], a + call Printer_CopyTileMapToPrinterTileBuffer + call PrinterDebug_LoadGFX +.loop + ld a, [wPrinterSendState] + bit 7, a + jr nz, .quit + call PrinterDebug_DoFunction + call PrinterDebug_ConvertStatusFlagsToTiles + call DelayFrame + jr .loop + +.quit + xor a + ld [wPrinterConnectionOpen], a + ld [wPrinterOpcode], a + ld hl, wOAMBuffer + 32 * 4 + ld bc, 8 * 4 + xor a + call FillMemory + xor a + ld [rIF], a + pop af + ld [rIE], a + pop hl + pop de + pop bc + pop af + ret + +Printer_CheckPressingB: + ld a, [hJoyHeld] + and B_BUTTON + jr nz, .quit + and a + ret + +.quit + ld a, [wPrinterSendState] + cp $c + jr nz, .already_done +.wait_current_task + ld a, [wPrinterOpcode] + and a + jr nz, .wait_current_task + ld a, $16 + ld [wPrinterOpcode], a + ld a, $88 + ld [rSB], a + ld a, $1 + ld [rSC], a + ld a, $81 + ld [rSC], a +.wait_send_cancel + ld a, [wPrinterOpcode] + and a + jr nz, .wait_send_cancel +.already_done + ld a, $1 + ld [hCanceledPrinting], a + scf + ret + +Printer_CopyTileMapToPrinterTileBuffer: + coord hl, 0, 0 + coord de, 0, 0, wPrinterTileBuffer + ld bc, SCREEN_HEIGHT * SCREEN_WIDTH + call CopyData + ret + +Printer_CopyTileMapFromPrinterTileBuffer: + coord hl, 0, 0, wPrinterTileBuffer + coord de, 0, 0 + ld bc, SCREEN_HEIGHT * SCREEN_WIDTH + call CopyData + ret + +Printer_ResetJoypadHRAM: + xor a + ld [hJoyLast], a + ld [hJoyReleased], a + ld [hJoyPressed], a + ld [hJoyHeld], a + ld [hJoy5], a + ld [hJoy6], a + ret + +Printer_PlayPrinterMusic: + call Printer_FadeOutMusicAndWait + ld a, [wAudioROMBank] + ld [wAudioSavedROMBank], a + ld a, BANK(Music_GBPrinter) + ld [wAudioROMBank], a + ld a, MUSIC_GB_PRINTER + ld [wNewSoundID], a + call PlaySound + ret + +Printer_PlayMapMusic: + call Printer_FadeOutMusicAndWait + call PlayDefaultMusic + ret + +Printer_FadeOutMusicAndWait: + ld a, $4 + ld [wAudioFadeOutControl], a + call StopAllMusic +.wait_music_stop + ld a, [wAudioFadeOutControl] + and a + jr nz, .wait_music_stop + ret + +GBPrinter_CheckForErrors: + ld a, [wPrinterHandshake] + cp $81 + jr z, .check_other_errors + ld a, [wPrinterStatusFlags] + cp $ff + jr z, .error2 + xor a + jr .load_status + +.check_other_errors + ld a, [wPrinterStatusFlags] + and %11100000 + ret z + bit 7, a + jr nz, .error1 + bit 6, a + jr nz, .error4 + ; error 3 + ld a, PRINTER_ERROR_3 + jr .load_status + +.error4 + ld a, PRINTER_ERROR_4 + jr .load_status + +.error1 + ld a, PRINTER_ERROR_1 + jr .load_status + +.error2 + ld a, PRINTER_ERROR_2 +.load_status + ld [wPrinterStatusIndicator], a + ret + +GBPrinter_UpdateStatusMessage: + ld a, [wPrinterStatusIndicator] + and a + ret z + push af + xor a + ld [H_AUTOBGTRANSFERENABLED], a + coord hl, 0, 5 + lb bc, 10, 18 + call TextBoxBorder + pop af + ld e, a + ld d, $0 + ld hl, .PrinterStatusMessages + add hl, de + add hl, de + ld e, [hl] + inc hl + ld d, [hl] + coord hl, 1, 7 + call PlaceString + coord hl, 2, 15 + ld de, .PressBToCancel + call PlaceString + ld a, $1 + ld [H_AUTOBGTRANSFERENABLED], a + xor a + ld [wPrinterStatusIndicator], a + ret + +.PressBToCancel: + db "Press B to Cancel@" + +.PrinterStatusMessages: + dw .Blank + dw .CheckingLink + dw .Transmitting + dw .Printing + dw .Error1 + dw .Error2 + dw .Error3 + dw .Error4 + dw .WrongDevice + +.Blank: + db "@" +.CheckingLink: + db "" + next " CHECKING LINK...@" +.Transmitting: + db "" + next " TRANSMITTING...@" +.Printing: + db "" + next " PRINTING...@" +.Error1: + db " Printer Error 1" + next "" + next "Check the Game Boy" + next "Printer Manual.@" +.Error2: + db " Printer Error 2" + next "" + next "Check the Game Boy" + next "Printer Manual.@" +.Error3: + db " Printer Error 3" + next "" + next "Check the Game Boy" + next "Printer Manual.@" +.Error4: + db " Printer Error 4" + next "" + next "Check the Game Boy" + next "Printer Manual.@" +.WrongDevice: + db "This is not the" + next "Game Boy Printer!@" + +Printer_PrepareSurfingMinigameHighScoreTileMap: + call GBPalWhiteOutWithDelay3 + call ClearScreen + ld de, SurfingPikachu2Graphics + ld hl, vChars2 + lb bc, BANK(SurfingPikachu2Graphics), (SurfingPikachu2GraphicsEnd - SurfingPikachu2Graphics) / $10 + call CopyVideoData + coord hl, 0, 0 + call .PlaceRowAlternatingTiles + coord hl, 0, 17 + call .PlaceRowAlternatingTiles + coord hl, 0, 0 + call .PlaceColumnAlternatingTiles + coord hl, 19, 0 + call .PlaceColumnAlternatingTiles + ld a, $4 + coord hl, 0, 0 + ld [hl], a + coord hl, 0, 17 + ld [hl], a + coord hl, 19, 0 + ld [hl], a + coord hl, 19, 17 + ld [hl], a + ld de, .Tilemap1 + coord hl, 10, 8 + lb bc, 3, 8 + call Diploma_Surfing_CopyBox + ld de, .Tilemap2 + coord hl, 2, 11 + lb bc, 6, 16 + call Diploma_Surfing_CopyBox + ld de, .PikachusBeachString + coord hl, 3, 2 + call PlaceString + ld de, .HiScoreString + coord hl, 9, 4 + call PlaceString + ld de, .PointsString + coord hl, 12, 6 + call PlaceString + ld de, wPlayerName + ld hl, wPlayerName + ld bc, 0 +.find_end_of_name + ld a, [hli] + inc c + cp "@" + jr nz, .find_end_of_name + ld a, 8 + sub c + jr nc, .got_name_length + xor a +.got_name_length + ld c, a + coord hl, 2, 4 + add hl, bc + call PlaceString + call CopySurfingMinigameScore + ld b, 8 + call RunPaletteCommand + ld a, $1 + ld [H_AUTOBGTRANSFERENABLED], a + call Delay3 + call GBPalNormal + ret + +.PlaceRowAlternatingTiles: + ld c, SCREEN_WIDTH / 2 +.row_loop + ld [hl], $0 + inc hl + ld [hl], $1 + inc hl + dec c + jr nz, .row_loop + ret + +.PlaceColumnAlternatingTiles: + ld c, SCREEN_HEIGHT / 2 + ld de, SCREEN_WIDTH +.col_loop + ld [hl], $2 + add hl, de + ld [hl], $3 + add hl, de + dec c + jr nz, .col_loop + ret + +.Tilemap1: + db $7f, $7f, $10, $11, $12, $13, $14, $15 + db $0f, $3c, $3d, $3e, $20, $21, $30, $31 + db $4c, $4d, $4e, $50, $34, $1a, $51, $2d + +.Tilemap2: + db $7f, $7f, $7f, $7f, $7f, $7f, $16, $17, $18, $19, $7f, $1b, $1c, $1d, $1e, $1f + db $7f, $7f, $22, $23, $24, $25, $26, $27, $28, $29, $2a, $2b, $2c, $7f, $2e, $2f + db $7f, $7f, $32, $33, $33, $35, $36, $37, $38, $39, $3a, $3b, $7f, $7f, $7f, $3f + db $40, $41, $42, $43, $44, $45, $46, $47, $48, $49, $4a, $4b, $40, $40, $40, $4f + db $52, $52, $52, $53, $54, $55, $56, $57, $58, $59, $5a, $5b, $5c, $5d, $5d, $5e + db $7f, $7f, $7f, $05, $06, $07, $08, $09, $0a, $0b, $0c, $0d, $0e, $7f, $7f, $7f + +.PikachusBeachString: + db "Pikachu's Beach@" +.HiScoreString: + db "'s Hi-Score@" +.PointsString: + db "Points@" + +Diploma_Surfing_CopyBox: +.y + push bc + push hl +.x + ld a, [de] + inc de + ld [hli], a + dec c + jr nz, .x + pop hl + ld bc, SCREEN_WIDTH + add hl, bc + pop bc + dec b + jr nz, .y + ret + +CopySurfingMinigameScore: + ld de, wSurfingMinigameHiScore + 1 + coord hl, 7, 6 + ld a, [de] + call .BCDConvertScore + ld a, [de] +.BCDConvertScore: + ld c, a + swap a + and $f + add -10 + ld [hli], a + ld a, c + and $f + add -10 + ld [hli], a + dec de + ret + +SurfingPikachu2Graphics: INCBIN "gfx/surfing_pikachu_2.2bpp" +SurfingPikachu2GraphicsEnd: + +PrintPCBox_DrawPage1: + xor a + ld [wBoxNumString], a + call ClearScreen + call PrintPCBox_PlaceHorizontalLines + coord hl, 0, 0 + ld bc, 11 * SCREEN_WIDTH + ld a, " " + call FillMemory + call PrintPCBox_DrawLeftAndRightBorders + call PrintPCBox_DrawTopBorder + coord hl, 4, 4 + ld de, .PokemonListString + call PlaceString + coord hl, 7, 6 + ld de, .BoxString + call PlaceString + coord hl, 11, 6 + ld a, [wCurrentBoxNum] + and $7f + cp 9 + jr c, .less_than_9 + sub 9 + ld [hl], "1" + inc hl + add "0" + jr .placed_box_number + +.less_than_9 + add "1" +.placed_box_number + ld [hl], a + coord hl, 4, 9 + ld de, wBoxSpecies + ld c, $3 + call PrintPCBox_PlaceBoxMonInfo + ret + +.PokemonListString: db "POKéMON LIST@" +.BoxString: db "BOX@" + +PrintPCBox_DrawPage2: + call ClearScreen + call PrintPCBox_PlaceHorizontalLines + call PrintPCBox_DrawLeftAndRightBorders + ld a, [wBoxDataStart] + cp 4 + ret c + coord hl, 4, 0 + ld de, wBoxSpecies + 3 + ld c, 6 + call PrintPCBox_PlaceBoxMonInfo + ret + +PrintPCBox_DrawPage3: + call ClearScreen + call PrintPCBox_PlaceHorizontalLines + call PrintPCBox_DrawLeftAndRightBorders + ld a, [wBoxDataStart] + cp 10 + ret c + coord hl, 4, 0 + ld de, wBoxSpecies + 9 + ld c, 6 + call PrintPCBox_PlaceBoxMonInfo + ret + +PrintPCBox_DrawPage4: + call ClearScreen + call PrintPCBox_PlaceHorizontalLines + call PrintPCBox_DrawLeftAndRightBorders + coord hl, 0, 15 + call PrintPCBox_DrawBottomBorderAtHL + coord hl, 0, 16 + ld bc, 2 * SCREEN_WIDTH + ld a, " " + call FillMemory + ld a, [wBoxDataStart] + cp 16 + ret c + coord hl, 4, 0 + ld de, wBoxSpecies + 15 + ld c, 5 + call PrintPCBox_PlaceBoxMonInfo + ret + +PrintPCBox_PlaceBoxMonInfo: +.loop + ld a, c + and a + jr z, .done + dec c + ld a, [de] + cp $ff + jr z, .done + ld [wd11e], a + push bc + push hl + push de + push hl + ld bc, 12 + ld a, " " + call FillMemory + pop hl + push hl + ld de, SCREEN_WIDTH + add hl, de + ld bc, 12 + ld a, " " + call FillMemory + pop hl + push hl + call GetMonName + pop hl + call PlaceString + push hl + ld hl, wBoxMonNicks + ld bc, NAME_LENGTH + ld a, [wBoxNumString] + call AddNTimes + ld e, l + ld d, h + pop hl + ld bc, SCREEN_WIDTH + 1 + add hl, bc + ld [hl], " " + inc hl + call PlaceString + ld hl, wBoxNumString + inc [hl] + pop de + pop hl + ld bc, 3 * SCREEN_WIDTH + add hl, bc + pop bc + inc de + jr .loop + +.done + ret + +PrintPCBox_DrawTopBorder: + coord hl, 0, 0 + ld a, $79 + ld [hli], a + ld a, $7a + ld c, SCREEN_WIDTH - 2 +.loop + ld [hli], a + dec c + jr nz, .loop + ld a, $7b + ld [hl], a + ret + +PrintPCBox_DrawLeftAndRightBorders: + coord hl, 0, 0 + ld de, SCREEN_WIDTH - 1 + ld c, SCREEN_HEIGHT +.loop + ld a, $7c + ld [hl], a + add hl, de + ld a, $7c + ld [hli], a + dec c + jr nz, .loop + ret + +PrintPCBox_DrawBottomBorder: + coord hl, 0, 17 +PrintPCBox_DrawBottomBorderAtHL: + ld a, $7d + ld [hli], a + ld a, $7a + ld c, SCREEN_WIDTH - 2 +.loop + ld [hli], a + dec c + jr nz, .loop + ld a, $7e + ld [hl], a + ret + +PrintPCBox_PlaceHorizontalLines: + coord hl, 4, 0 + ld c, 6 + call .PlaceHorizontalLine + coord hl, 6, 1 + ld c, 6 +.PlaceHorizontalLine: +.loop + push bc + push hl + ld de, .HorizontalLineString + call PlaceString + pop hl + ld bc, 3 * SCREEN_WIDTH + add hl, bc + pop bc + dec c + jr nz, .loop + ret + +.HorizontalLineString: + db "----------@" diff --git a/engine/printer/serial.asm b/engine/printer/serial.asm new file mode 100755 index 00000000..fa83eb9d --- /dev/null +++ b/engine/printer/serial.asm @@ -0,0 +1,621 @@ +StartTransmission_Send9Rows: + ld a, 9 +Printer_StartTransmission: + push af + ld hl, wPrinterData + ld bc, wPrinterDataEnd - wPrinterData + xor a + call Printer_FillMemory + xor a + ld [rSB], a + ld [rSC], a + ld [wPrinterOpcode], a + ld hl, wPrinterConnectionOpen + set 0, [hl] + ld a, [wPrinterSettings] + ld [wPrinterSettingsTempCopy], a + pop af + ld [wPrinterQueueLength], a + ret + +PrinterTransmissionJumptable: + ld a, [wPrinterSendState] + ld e, a + ld d, 0 + ld hl, .Jumptable + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + jp hl + +.Jumptable: + dw Printer_InitSerial ; 00 + dw Printer_CheckConnectionStatus ; 01 + dw Printer_WaitSerial ; 02 + dw Printer_StartTransmittingTilemap ; 03 + dw Printer_TransmissionLoop ; 04 + dw Printer_WaitSerialAndLoopBack2 ; 05 + dw Printer_EndTilemapTransmission ; 06 + dw Printer_TransmissionLoop ; 07 + dw Printer_WaitSerial ; 08 + + dw Printer_SignalSendHeader ; 09 + dw Printer_TransmissionLoop ; 0a + dw Printer_WaitSerial ; 0b + dw Printer_WaitUntilFinished ; 0c + dw Printer_Quit ; 0d + + dw Printer_Next_ ; 0e + dw Printer_WaitSerial ; 0f + dw Printer_SignalLoopBack ; 10 + dw Printer_LoopBack ; 11 + dw Printer_WaitLoopBack ; 12 + dw Printer_WaitLoopBack_ ; 13 + +Printer_Next: + ld hl, wPrinterSendState + inc [hl] + ret + +Printer_Back: + ld hl, wPrinterSendState + dec [hl] + ret + +Printer_Quit: + xor a + ld [wPrinterStatusFlags], a + ld hl, wPrinterSendState + set 7, [hl] + ret + +Printer_Next_: + call Printer_Next + ret + +Printer_LoopBack: + ld a, $1 + ld [wPrinterSendState], a + ret + +Printer_InitSerial: + call ResetPrinterData + ld hl, PrinterDataPacket1 + call CopyPrinterDataHeader + xor a + ld [wPrinterDataSize], a + ld [wPrinterDataSize + 1], a + ld a, [wPrinterQueueLength] + ld [wPrinterRowIndex], a + call Printer_Next + call Printer_PrepareToSend + ld a, PRINTER_STATUS_CHECKING_LINK + ld [wPrinterStatusIndicator], a + ret + +Printer_StartTransmittingTilemap: + call ResetPrinterData + ld hl, wPrinterRowIndex + ld a, [hl] + and a + jr z, Printer_EndTilemapTransmission + ld hl, PrinterDataPacket3 + call CopyPrinterDataHeader + call Printer_Convert2RowsTo2bpp + ld a, (wPrinterSendDataSource1End - wPrinterSendDataSource1) % $100 + ld [wPrinterDataSize], a + ld a, (wPrinterSendDataSource1End - wPrinterSendDataSource1) / $100 + ld [wPrinterDataSize + 1], a + call ComputePrinterChecksum + call Printer_Next + call Printer_PrepareToSend + ld a, PRINTER_STATUS_TRANSMITTING + ld [wPrinterStatusIndicator], a + ret + +Printer_EndTilemapTransmission: + ld a, $6 + ld [wPrinterSendState], a + ld hl, PrinterDataPacket4 + call CopyPrinterDataHeader + xor a + ld [wPrinterDataSize], a + ld [wPrinterDataSize + 1], a + call Printer_Next + call Printer_PrepareToSend + ret + +Printer_SignalSendHeader: + call ResetPrinterData + ld hl, PrinterDataPacket2 + call CopyPrinterDataHeader + call Printer_StageHeaderForSend + ld a, $4 + ld [wPrinterDataSize], a + ld a, $0 + ld [wPrinterDataSize + 1], a + call ComputePrinterChecksum + call Printer_Next + call Printer_PrepareToSend + ld a, PRINTER_STATUS_PRINTING + ld [wPrinterStatusIndicator], a + ret + +Printer_SignalLoopBack: + call ResetPrinterData + ld hl, PrinterDataPacket1 + call CopyPrinterDataHeader + xor a + ld [wPrinterDataSize], a + ld [wPrinterDataSize + 1], a + ld a, [wPrinterQueueLength] + ld [wPrinterRowIndex], a + call Printer_Next + call Printer_PrepareToSend + ret + +Printer_WaitSerial: + ld hl, wPrinterSerialFrameDelay + inc [hl] + ld a, [hl] + cp $6 + ret c + xor a + ld [hl], a + call Printer_Next + ret + +Printer_WaitSerialAndLoopBack2: + ld hl, wPrinterSerialFrameDelay + inc [hl] + ld a, [hl] + cp $6 + ret c + xor a + ld [hl], a + ld hl, wPrinterRowIndex + dec [hl] + call Printer_Back + call Printer_Back + ret + +Printer_CheckConnectionStatus: + ld a, [wPrinterOpcode] + and a + ret nz + ld a, [wPrinterHandshake] + cp $ff + jr nz, .asm_e88dc + ld a, [wPrinterStatusFlags] + cp $ff + jr z, .asm_e88f8 +.asm_e88dc + ld a, [wPrinterHandshake] + cp $81 + jr nz, .asm_e88f8 + ld a, [wPrinterStatusFlags] + cp $0 + jr nz, .asm_e88f8 + ld hl, wPrinterConnectionOpen + set 1, [hl] + ld a, $5 + ld [wHandshakeFrameDelay], a + call Printer_Next + ret + +.asm_e88f8 + ld a, $ff + ld [wPrinterHandshake], a + ld [wPrinterStatusFlags], a + ld a, $e + ld [wPrinterSendState], a + ret + +Printer_TransmissionLoop: + ld a, [wPrinterOpcode] + and a + ret nz + ld a, [wPrinterStatusFlags] + and $f0 + jr nz, .asm_e8921 + ld a, [wPrinterStatusFlags] + and $1 + jr nz, .asm_e891d + call Printer_Next + ret + +.asm_e891d + call Printer_Back + ret + +.asm_e8921 + ld a, $12 + ld [wPrinterSendState], a + ret + +Printer_WaitUntilFinished: + ld a, [wPrinterOpcode] + and a + ret nz + ld a, [wPrinterStatusFlags] + and $f3 + ret nz + call Printer_Next + ret + +Printer_WaitLoopBack: + call Printer_Next +Printer_WaitLoopBack_: + ld a, [wPrinterOpcode] + and a + ret nz + ld a, [wPrinterStatusFlags] + and $f0 + ret nz + xor a + ld [wPrinterSendState], a + ret + +Printer_PrepareToSend: +.wait_printer_operation + ld a, [wPrinterOpcode] + and a + jr nz, .wait_printer_operation + xor a + ld [wPrinterSendByteOffset], a + ld [wPrinterSendByteOffset + 1], a + ld a, $1 + ld [wPrinterOpcode], a + ld a, $88 + ld [rSB], a + ld a, $1 + ld [rSC], a + ld a, $81 + ld [rSC], a + ret + +CopyPrinterDataHeader: + ld a, [hli] + ld [wPrinterDataHeader], a + ld a, [hli] + ld [wPrinterDataHeader + 1], a + ld a, [hli] + ld [wPrinterDataHeader + 2], a + ld a, [hli] + ld [wPrinterDataHeader + 3], a + ld a, [hli] + ld [wPrinterChecksum], a + ld a, [hl] + ld [wPrinterChecksum + 1], a + ret + +ResetPrinterData: + xor a + ld hl, wPrinterDataHeader + ld [hli], a + ld [hli], a + ld [hli], a + ld [hl], a + ld hl, wPrinterChecksum + ld [hli], a + ld [hl], a + xor a + ld [wPrinterDataSize], a + ld [wPrinterDataSize + 1], a + ld hl, wPrinterSendDataSource1 + ld bc, wPrinterSendDataSource1End - wPrinterSendDataSource1 + call Printer_FillMemory + ret + +ComputePrinterChecksum: + ld hl, $0 + ld bc, $4 + ld de, wPrinterDataHeader + call .AddToChecksum + ld a, [wPrinterDataSize] + ld c, a + ld a, [wPrinterDataSize + 1] + ld b, a + ld de, wPrinterSendDataSource1 + call .AddToChecksum + ld a, l + ld [wPrinterChecksum], a + ld a, h + ld [wPrinterChecksum + 1], a + ret + +.AddToChecksum: +.loop + ld a, [de] + inc de + add l + jr nc, .no_carry + inc h +.no_carry + ld l, a + dec bc + ld a, c + or b + jr nz, .loop + ret + +Printer_StageHeaderForSend: + ld a, $1 + ld [wPrinterSendDataSource1], a + ld a, [wcae2] + ld [wPrinterSendDataSource1 + 1], a + ld a, %11100100 + ld [wPrinterSendDataSource1 + 2], a + ld a, [wPrinterSettingsTempCopy] + ld [wPrinterSendDataSource1 + 3], a + ret + +Printer_Convert2RowsTo2bpp: + ld a, [wPrinterRowIndex] + ld b, a + ld a, [wPrinterQueueLength] + sub b + ld hl, wPrinterTileBuffer + ld de, 2 * SCREEN_WIDTH +.get_row + and a + jr z, .got_row + add hl, de + dec a + jr .get_row + +.got_row + ld e, l + ld d, h + ld hl, wPrinterSendDataSource1 + ld c, 2 * SCREEN_WIDTH +.loop + ld a, [de] + inc de + push bc + push de + push hl + swap a + ld d, a + and $f0 + ld e, a + ld a, d + and $f + ld d, a + and $8 + ld a, d + jr nz, .vchars1 + or $90 + jr .got_addr + +.vchars1 + or $80 +.got_addr + ld d, a + lb bc, BANK(Printer_Convert2RowsTo2bpp), 1 + call CopyVideoData + pop hl + ld de, $10 + add hl, de + pop de + pop bc + dec c + jr nz, .loop + ret + +Printer_FillMemory: + push de + ld e, a +.loop + ld [hl], e + inc hl + dec bc + ld a, c + or b + jr nz, .loop + ld a, e + pop de + ret + +PrinterDataPacket1: + db 1, 0, $00, 0 + dw 1 +PrinterDataPacket2: + db 2, 0, $04, 0 + dw 0 +PrinterDataPacket3: + db 4, 0, $80, 2 + dw 0 +PrinterDataPacket4: + db 4, 0, $00, 0 + dw 4 +PrinterDataPacket5: ; unused + db 8, 0, $00, 0 + dw 8 +PrinterDataPacket6: ; unused + db 15, 0, $00, 0 + dw 15 + +PrinterSerial_: + ld a, [wPrinterOpcode] + ld e, a + ld d, 0 + ld hl, .Jumptable + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + jp hl + +.Jumptable: + dw .Nop + + dw .SignalTransmissionStart + dw .SendHeaderByte1 + dw .SendHeaderByte2 + dw .SendHeaderByte3 + dw .SendHeaderByte4 + dw .DataByte + dw .SendChecksumLo + dw .SendChecksumHi + dw .SignalTransmissionEnd + dw .Receive1 + dw .Receive2 + + dw .SignalTransmissionStart + dw .Send_0F + dw .Send_00 + dw .Send_00 + dw .Send_00 + dw .Send_0F + dw .Send_00 + dw .SignalTransmissionEnd + dw .Receive1 + dw .Receive2_ + + dw .SignalTransmissionStart + dw .SignalQuit + dw .Send_00 + dw .Send_00 + dw .Send_00 + dw .SignalQuit + dw .Send_00 + dw .SignalTransmissionEnd + dw .Receive1 + dw .Receive2 + +.NextInstruction: + ld hl, wPrinterOpcode + inc [hl] + ret + +.Nop: + ret + +.SignalTransmissionStart: + ld a, $33 + call .SendByte + call .NextInstruction + ret + +.SendHeaderByte1: + ld a, [wPrinterDataHeader] + call .SendByte + call .NextInstruction + ret + +.SendHeaderByte2: + ld a, [wPrinterDataHeader + 1] + call .SendByte + call .NextInstruction + ret + +.SendHeaderByte3: + ld a, [wPrinterDataHeader + 2] + call .SendByte + call .NextInstruction + ret + +.SendHeaderByte4: + ld a, [wPrinterDataHeader + 3] + call .SendByte + call .NextInstruction + ret + +.DataByte: + ld hl, wPrinterDataSize + ld e, [hl] + inc hl + ld d, [hl] + ld a, e + or d + jr z, .sent_last_byte + dec de + ld [hl], d + dec hl + ld [hl], e + ld a, [wPrinterSendByteOffset] + ld e, a + ld a, [wPrinterSendByteOffset + 1] + ld d, a + ld hl, wPrinterSendDataSource1 + add hl, de + inc de + ld a, e + ld [wPrinterSendByteOffset], a + ld a, d + ld [wPrinterSendByteOffset + 1], a + ld a, [hl] + call .SendByte + ret + +.sent_last_byte + call .NextInstruction +.SendChecksumLo: + ld a, [wPrinterChecksum] + call .SendByte + call .NextInstruction + ret + +.SendChecksumHi: + ld a, [wPrinterChecksum + 1] + call .SendByte + call .NextInstruction + ret + +.SignalTransmissionEnd: + ld a, $0 + call .SendByte + call .NextInstruction + ret + +.Receive1: + ld a, [rSB] + ld [wPrinterHandshake], a + ld a, $0 + call .SendByte + call .NextInstruction + ret + +.Receive2: + ld a, [rSB] + ld [wPrinterStatusFlags], a + xor a + ld [wPrinterOpcode], a + ret + +.Send_0F: + ld a, $f + call .SendByte + call .NextInstruction + ret + +.Send_00: + ld a, $0 + call .SendByte + call .NextInstruction + ret + +.SignalQuit: + ld a, $8 + call .SendByte + call .NextInstruction + ret + +.SendByte: + ld [rSB], a + ld a, $1 + ld [rSC], a + ld a, $81 + ld [rSC], a + ret + +.Receive2_: + ld a, [rSB] + ld [wPrinterStatusFlags], a + xor a + ld [wPrinterOpcode], a + ret diff --git a/engine/remove_pokemon.asm b/engine/remove_pokemon.asm index 1fcb5d09..f29a428d 100644 --- a/engine/remove_pokemon.asm +++ b/engine/remove_pokemon.asm @@ -2,9 +2,9 @@ _RemovePokemon: ld hl, wPartyCount ld a, [wRemoveMonFromBox] and a - jr z, .asm_7b74 + jr z, .usePartyCount ld hl, wNumInBox -.asm_7b74 +.usePartyCount ld a, [hl] dec a ld [hli], a @@ -15,28 +15,28 @@ _RemovePokemon: ld e, l ld d, h inc de -.asm_7b81 +.shiftMonSpeciesLoop ld a, [de] inc de ld [hli], a - inc a - jr nz, .asm_7b81 + inc a ; reached terminator? + jr nz, .shiftMonSpeciesLoop ; if not, continue shifting species ld hl, wPartyMonOT - ld d, $5 + ld d, PARTY_LENGTH - 1 ; max number of pokemon to shift ld a, [wRemoveMonFromBox] and a - jr z, .asm_7b97 + jr z, .usePartyMonOTs ld hl, wBoxMonOT - ld d, $13 -.asm_7b97 + ld d, MONS_PER_BOX - 1 +.usePartyMonOTs ld a, [wWhichPokemon] call SkipFixedLengthTextEntries ld a, [wWhichPokemon] - cp d - jr nz, .asm_7ba6 - ld [hl], $ff + cp d ; are we removing the last pokemon? + jr nz, .notRemovingLastMon ; if not, shift the pokemon below + ld [hl], $ff ; else, write the terminator and return ret -.asm_7ba6 +.notRemovingLastMon ld d, h ld e, l ld bc, NAME_LENGTH @@ -44,41 +44,41 @@ _RemovePokemon: ld bc, wPartyMonNicks ld a, [wRemoveMonFromBox] and a - jr z, .asm_7bb8 + jr z, .usePartyMonNicks ld bc, wBoxMonNicks -.asm_7bb8 +.usePartyMonNicks call CopyDataUntil ld hl, wPartyMons ld bc, wPartyMon2 - wPartyMon1 ld a, [wRemoveMonFromBox] and a - jr z, .asm_7bcd + jr z, .usePartyMonStructs ld hl, wBoxMons ld bc, wBoxMon2 - wBoxMon1 -.asm_7bcd +.usePartyMonStructs ld a, [wWhichPokemon] - call AddNTimes - ld d, h + call AddNTimes ; get address of the pokemon removed + ld d, h ; store in de for CopyDataUntil ld e, l ld a, [wRemoveMonFromBox] and a - jr z, .asm_7be4 + jr z, .copyUntilPartyMonOTs ld bc, wBoxMon2 - wBoxMon1 - add hl, bc - ld bc, wBoxMonOT - jr .asm_7beb -.asm_7be4 + add hl, bc ; get address of pokemon after the pokemon removed + ld bc, wBoxMonOT ; address of when to stop copying + jr .continue +.copyUntilPartyMonOTs ld bc, wPartyMon2 - wPartyMon1 - add hl, bc - ld bc, wPartyMonOT -.asm_7beb - call CopyDataUntil + add hl, bc ; get address of pokemon after the pokemon removed + ld bc, wPartyMonOT ; address of when to stop copying +.continue + call CopyDataUntil ; shift all pokemon data after the removed mon to the removed mon's location ld hl, wPartyMonNicks ld a, [wRemoveMonFromBox] and a - jr z, .asm_7bfa + jr z, .usePartyMonNicks2 ld hl, wBoxMonNicks -.asm_7bfa +.usePartyMonNicks2 ld bc, NAME_LENGTH ld a, [wWhichPokemon] call AddNTimes @@ -86,10 +86,10 @@ _RemovePokemon: ld e, l ld bc, NAME_LENGTH add hl, bc - ld bc, wPokedexOwned + ld bc, wPartyMonNicksEnd ld a, [wRemoveMonFromBox] and a - jr z, .asm_7c15 + jr z, .copyUntilPartyMonNicksEnd ld bc, wBoxMonNicksEnd -.asm_7c15 +.copyUntilPartyMonNicksEnd jp CopyDataUntil diff --git a/engine/save.asm b/engine/save.asm index 97935dbb..7f453bf0 100755 --- a/engine/save.asm +++ b/engine/save.asm @@ -32,10 +32,8 @@ FileDataDestroyedText: db "@" LoadSAV0: - ld a, SRAM_ENABLE - ld [MBC1SRamEnable], a + call EnableSRAMAndLatchClockData ld a, $1 - ld [MBC1SRamBankingMode], a ld [MBC1SRamBank], a ld hl, sPlayerName ; hero name located in SRAM ld bc, sMainDataCheckSum - sPlayerName ; but here checks the full SAV @@ -79,10 +77,8 @@ LoadSAV0: jp SAVGoodChecksum LoadSAV1: - ld a, SRAM_ENABLE - ld [MBC1SRamEnable], a + call EnableSRAMAndLatchClockData ld a, $1 - ld [MBC1SRamBankingMode], a ld [MBC1SRamBank], a ld hl, sPlayerName ; hero name located in SRAM ld bc, sMainDataCheckSum - sPlayerName ; but here checks the full SAV @@ -99,10 +95,8 @@ LoadSAV1: jp SAVGoodChecksum LoadSAV2: - ld a, SRAM_ENABLE - ld [MBC1SRamEnable], a + call EnableSRAMAndLatchClockData ld a, $1 - ld [MBC1SRamBankingMode], a ld [MBC1SRamBank], a ld hl, sPlayerName ; hero name located in SRAM ld bc, sMainDataCheckSum - sPlayerName ; but here checks the full SAV @@ -126,9 +120,7 @@ SAVBadCheckSum: scf SAVGoodChecksum: - ld a, $0 - ld [MBC1SRamBankingMode], a - ld [MBC1SRamEnable], a + call DisableSRAMAndPrepareClockData ret LoadSAVIgnoreBadCheckSum: @@ -139,12 +131,16 @@ LoadSAVIgnoreBadCheckSum: SaveSAV: callba PrintSaveScreenText + ld c, 10 + call DelayFrames ld hl, WouldYouLikeToSaveText call SaveSAVConfirm and a ;|0 = Yes|1 = No| ret nz + ld c, 10 + call DelayFrames ld a, [wSaveFileStatus] - dec a + cp $1 jr z, .save call SAVCheckRandomID jr z, .save @@ -154,24 +150,20 @@ SaveSAV: ret nz .save call SaveSAVtoSRAM - coord hl, 1, 13 - lb bc, 4, 18 - call ClearScreenArea - coord hl, 1, 14 - ld de, NowSavingString - call PlaceString - ld c, 120 + ld hl, SavingText + call PrintText + ld c, 128 call DelayFrames ld hl, GameSavedText call PrintText + ld c,10 + call DelayFrames ld a, SFX_SAVE call PlaySoundWaitForCurrent call WaitForSoundToFinish ld c, 30 - jp DelayFrames - -NowSavingString: - db "Now saving...@" + call DelayFrames + ret SaveSAVConfirm: call PrintText @@ -187,6 +179,10 @@ WouldYouLikeToSaveText: TX_FAR _WouldYouLikeToSaveText db "@" +SavingText: + TX_FAR _SavingText + db "@" + GameSavedText: TX_FAR _GameSavedText db "@" @@ -196,10 +192,8 @@ OlderFileWillBeErasedText: db "@" SaveSAVtoSRAM0: - ld a, SRAM_ENABLE - ld [MBC1SRamEnable], a + call EnableSRAMAndLatchClockData ld a, $1 - ld [MBC1SRamBankingMode], a ld [MBC1SRamBank], a ld hl, wPlayerName ld de, sPlayerName @@ -223,17 +217,13 @@ SaveSAVtoSRAM0: ld bc, sMainDataCheckSum - sPlayerName call SAVCheckSum ld [sMainDataCheckSum], a - xor a - ld [MBC1SRamBankingMode], a - ld [MBC1SRamEnable], a + call DisableSRAMAndPrepareClockData ret SaveSAVtoSRAM1: ; stored pokémon - ld a, SRAM_ENABLE - ld [MBC1SRamEnable], a + call EnableSRAMAndLatchClockData ld a, $1 - ld [MBC1SRamBankingMode], a ld [MBC1SRamBank], a ld hl, wBoxDataStart ld de, sCurBoxData @@ -243,16 +233,12 @@ SaveSAVtoSRAM1: ld bc, sMainDataCheckSum - sPlayerName call SAVCheckSum ld [sMainDataCheckSum], a - xor a - ld [MBC1SRamBankingMode], a - ld [MBC1SRamEnable], a + call DisableSRAMAndPrepareClockData ret SaveSAVtoSRAM2: - ld a, SRAM_ENABLE - ld [MBC1SRamEnable], a + call EnableSRAMAndLatchClockData ld a, $1 - ld [MBC1SRamBankingMode], a ld [MBC1SRamBank], a ld hl, wPartyDataStart ld de, sPartyData @@ -262,13 +248,18 @@ SaveSAVtoSRAM2: ld de, sMainData ld bc, wPokedexSeenEnd - wPokedexOwned call CopyData + ld hl, wPikachuHappiness + ld de, sMainData + $179 + ld a, [hli] + ld [de], a + inc de + ld a, [hl] + ld [de], a ld hl, sPlayerName ld bc, sMainDataCheckSum - sPlayerName call SAVCheckSum ld [sMainDataCheckSum], a - xor a - ld [MBC1SRamBankingMode], a - ld [MBC1SRamEnable], a + call DisableSRAMAndPrepareClockData ret SaveSAVtoSRAM: @@ -351,13 +342,16 @@ ChangeBox:: call z, EmptyAllSRAMBoxes ; if so, empty all boxes in SRAM call DisplayChangeBoxMenu call UpdateSprites - ld hl, hFlags_0xFFF6 + ld hl, hFlags_0xFFFA set 1, [hl] call HandleMenuInput - ld hl, hFlags_0xFFF6 + ld hl, hFlags_0xFFFA res 1, [hl] bit 1, a ; pressed b ret nz + ld a, $b6 + call PlaySoundWaitForCurrent + call WaitForSoundToFinish call GetBoxSRAMLocation ld e, l ld d, h @@ -380,9 +374,6 @@ ChangeBox:: call SaveSAVtoSRAM ld hl, wChangeBoxSavedMapTextPointer call SetMapTextPointer - ld a, SFX_SAVE - call PlaySoundWaitForCurrent - call WaitForSoundToFinish ret WhenYouChangeBoxText: @@ -392,10 +383,7 @@ WhenYouChangeBoxText: CopyBoxToOrFromSRAM: ; copy an entire box from hl to de with b as the SRAM bank push hl - ld a, SRAM_ENABLE - ld [MBC1SRamEnable], a - ld a, $1 - ld [MBC1SRamBankingMode], a + call EnableSRAMAndLatchClockData ld a, b ld [MBC1SRamBank], a ld bc, wBoxDataEnd - wBoxDataStart @@ -413,9 +401,7 @@ CopyBoxToOrFromSRAM: call SAVCheckSum ld [sBank2AllBoxesChecksum], a ; sBank3AllBoxesChecksum call CalcIndividualBoxCheckSums - xor a - ld [MBC1SRamBankingMode], a - ld [MBC1SRamEnable], a + call DisableSRAMAndPrepareClockData ret DisplayChangeBoxMenu: @@ -436,21 +422,19 @@ DisplayChangeBoxMenu: ld [wCurrentMenuItem], a ld [wLastMenuItem], a coord hl, 0, 0 - ld b, 2 - ld c, 9 + lb bc, 2, 9 call TextBoxBorder ld hl, ChooseABoxText call PrintText coord hl, 11, 0 - ld b, 12 - ld c, 7 + lb bc, 12, 7 call TextBoxBorder - ld hl, hFlags_0xFFF6 + ld hl, hFlags_0xFFFA set 2, [hl] ld de, BoxNames coord hl, 13, 1 call PlaceString - ld hl, hFlags_0xFFF6 + ld hl, hFlags_0xFFFA res 2, [hl] ld a, [wCurrentBoxNum] and $7f @@ -513,19 +497,14 @@ BoxNoText: EmptyAllSRAMBoxes: ; marks all boxes in SRAM as empty (initialisation for the first time the ; player changes the box) - ld a, SRAM_ENABLE - ld [MBC1SRamEnable], a - ld a, $1 - ld [MBC1SRamBankingMode], a + call EnableSRAMAndLatchClockData ld a, 2 ld [MBC1SRamBank], a call EmptySRAMBoxesInBank ld a, 3 ld [MBC1SRamBank], a call EmptySRAMBoxesInBank - xor a - ld [MBC1SRamBankingMode], a - ld [MBC1SRamEnable], a + call DisableSRAMAndPrepareClockData ret EmptySRAMBoxesInBank: @@ -559,19 +538,14 @@ EmptySRAMBox: GetMonCountsForAllBoxes: ld hl, wBoxMonCounts push hl - ld a, SRAM_ENABLE - ld [MBC1SRamEnable], a - ld a, $1 - ld [MBC1SRamBankingMode], a + call EnableSRAMAndLatchClockData ld a, $2 ld [MBC1SRamBank], a call GetMonCountsForBoxesInBank ld a, $3 ld [MBC1SRamBank], a call GetMonCountsForBoxesInBank - xor a - ld [MBC1SRamBankingMode], a - ld [MBC1SRamEnable], a + call DisableSRAMAndPrepareClockData pop hl ; copy the count for the current box from WRAM @@ -604,10 +578,8 @@ SAVCheckRandomID: ;checks if Sav file is the same by checking player's name 1st letter ($a598) ; and the two random numbers generated at game beginning ;(which are stored at wPlayerID)s - ld a, $0a - ld [MBC1SRamEnable], a - ld a, $01 - ld [MBC1SRamBankingMode], a + call EnableSRAMAndLatchClockData + ld a, $1 ld [MBC1SRamBank], a ld a, [sPlayerName] and a @@ -670,34 +642,23 @@ LoadHallOfFameTeams: ; fallthrough HallOfFame_Copy: - ld a, SRAM_ENABLE - ld [MBC1SRamEnable], a - ld a, $1 - ld [MBC1SRamBankingMode], a + call EnableSRAMAndLatchClockData xor a ld [MBC1SRamBank], a call CopyData - xor a - ld [MBC1SRamBankingMode], a - ld [MBC1SRamEnable], a + call DisableSRAMAndPrepareClockData ret ClearSAV: - ld a, SRAM_ENABLE - ld [MBC1SRamEnable], a - ld a, $1 - ld [MBC1SRamBankingMode], a - xor a - call PadSRAM_FF - ld a, $1 - call PadSRAM_FF - ld a, $2 - call PadSRAM_FF - ld a, $3 + call EnableSRAMAndLatchClockData + ld a, $4 +.loop + dec a + push af call PadSRAM_FF - xor a - ld [MBC1SRamBankingMode], a - ld [MBC1SRamEnable], a + pop af + jr nz, .loop + call DisableSRAMAndPrepareClockData ret PadSRAM_FF: @@ -706,3 +667,16 @@ PadSRAM_FF: ld bc, $2000 ld a, $ff jp FillMemory + +EnableSRAMAndLatchClockData: + ld a, $1 + ld [MBC1SRamBankingMode], a + ld a, SRAM_ENABLE + ld [MBC1SRamEnable], a + ret + +DisableSRAMAndPrepareClockData: + ld a, SRAM_DISABLE + ld [MBC1SRamBankingMode], a + ld [MBC1SRamEnable], a + ret diff --git a/engine/slot_machine.asm b/engine/slot_machine.asm index 3a46687f..b4514618 100755 --- a/engine/slot_machine.asm +++ b/engine/slot_machine.asm @@ -23,9 +23,11 @@ PromptUserToPlaySlots: call LoadFontTilePatterns ld b, SET_PAL_SLOTS call RunPaletteCommand + call Delay3 call GBPalNormal ld a, $e4 ld [rOBP0], a + call UpdateGBCPal_OBP0 ld hl, wd730 set 6, [hl] xor a @@ -80,8 +82,7 @@ MainSlotMachineLoop: ld [wLastMenuItem], a ld [wMenuWatchMovingOutOfBounds], a coord hl, 14, 11 - ld b, 5 - ld c, 4 + lb bc, 5, 4 call TextBoxBorder coord hl, 16, 12 ld de, CoinMultiplierSlotMachineText @@ -457,6 +458,7 @@ SlotMachine_CheckForMatches: ld a, [rBGP] xor $40 ld [rBGP], a + call UpdateGBCPal_BGP ld c, 5 call DelayFrames dec b @@ -473,6 +475,7 @@ SlotMachine_CheckForMatches: call SlotMachine_PrintPayoutCoins ld a, $e4 ld [rOBP0], a + call UpdateGBCPal_OBP0 jp .done SymbolLinedUpSlotMachineText: @@ -698,6 +701,7 @@ SlotMachine_PayCoinsToPlayer: ld a, [rOBP0] xor $40 ; make the slot wheel symbols flash ld [rOBP0], a + call UpdateGBCPal_OBP0 ld a, 5 .skip1 ld [wAnimCounter], a @@ -852,17 +856,17 @@ LoadSlotMachineTiles: ld de, vChars0 ld bc, $1c0 ld a, BANK(SlotMachineTiles2) - call FarCopyData2 + call FarCopyData ld hl, SlotMachineTiles1 ld de, vChars2 ld bc, $250 ld a, BANK(SlotMachineTiles1) - call FarCopyData2 + call FarCopyData ld hl, SlotMachineTiles2 ld de, vChars2 + $250 ld bc, $1c0 ld a, BANK(SlotMachineTiles2) - call FarCopyData2 + call FarCopyData ld hl, SlotMachineMap coord de, 0, 0 ld bc, SlotMachineMapEnd - SlotMachineMap @@ -884,9 +888,4 @@ SlotMachineMapEnd: INCLUDE "data/slot_machine_wheels.asm" SlotMachineTiles1: -IF DEF(_RED) - INCBIN "gfx/red/slotmachine1.2bpp" -ENDC -IF DEF(_BLUE) - INCBIN "gfx/blue/slotmachine1.2bpp" -ENDC + INCBIN "gfx/slotmachine1.2bpp" diff --git a/engine/surfing_minigame.asm b/engine/surfing_minigame.asm new file mode 100755 index 00000000..81e5296d --- /dev/null +++ b/engine/surfing_minigame.asm @@ -0,0 +1,2862 @@ +SurfingPikachuMinigame: + call SurfingPikachuMinigame_BlankPals + call DelayFrame + call DelayFrame + call DelayFrame + ld a, [hTilesetType] + push af + xor a + ld [hTilesetType], a + ld a, [wUpdateSpritesEnabled] + push af + ld a, $ff + ld [wUpdateSpritesEnabled], a + ld a, [rIE] + push af + xor a + ld [rIF], a + ld a, $f + ld [rIE], a + ld a, $8 + ld [rSTAT], a + ld a, [H_AUTOBGTRANSFERDEST + 1] + push af + ld a, $98 + ld [H_AUTOBGTRANSFERDEST + 1], a + call SurfingPikachuMinigameIntro + call SurfingPikachuLoop + xor a + ld [rBGP], a + ld [rOBP0], a + ld [rOBP1], a + call UpdateGBCPal_BGP + call UpdateGBCPal_OBP0 + call UpdateGBCPal_OBP1 + call ClearObjectAnimationBuffers + call ClearSprites + xor a + ld [hLCDCPointer], a + ld [hSCX], a + ld [hSCY], a + ld a, $90 + ld [hWY], a + call DelayFrame + pop af + ld [H_AUTOBGTRANSFERDEST + 1], a + xor a + ld [rIF], a + pop af + ld [rIE], a + xor a + ld [rSTAT], a + call RunDefaultPaletteCommand + call ReloadMapAfterSurfingMinigame + call PlayDefaultMusic + call GBPalNormal + pop af + ld [wUpdateSpritesEnabled], a + pop af + ld [hTilesetType], a + ret + +SurfingPikachuLoop: + call SurfingPikachuMinigame_LoadGFXAndLayout + call DelayFrame + ld b, $e + call RunPaletteCommand +.loop + ld a, [wSurfingMinigameRoutineNumber] + bit 7, a + ret nz + call SurfingPikachu_GetJoypad_3FrameBuffer + call SurfingPikachu_CheckPressedSelect + ret nz + call RunSurfingMinigameRoutine + ld a, $3c + ld [wCurrentAnimatedObjectOAMBufferOffset], a + call RunObjectAnimations + call SurfingMinigame_MoveClouds + call .DelayFrame + call SurfingMinigame_UpdateMusicTempo + jr .loop + +.DelayFrame: + call DelayFrame + ret + +SurfingPikachu_CheckPressedSelect: + ld hl, wd492 + bit 1, [hl] + ret z + ld a, [hJoyPressed] + and SELECT + ret + +Func_f80b7: + ld a, [hJoyPressed] + and START + ret z + ld hl, wc5e2 + ld a, [hl] + xor $1 + ld [hl], a + ret + +SurfingMinigame_UpdateMusicTempo: + ld a, [wc634] + and a + ret z + + ; check that all channels are on their last frame of note delay + ld hl, wChannelNoteDelayCounters + ld a, $1 + cp [hl] + ret nz + inc hl + cp [hl] + ret nz + inc hl + cp [hl] + ret nz + + ; de = ([wSurfingMinigamePikachuSpeed] & 0x3f) * 2 + ld a, [wSurfingMinigamePikachuSpeed] + ld e, a + ld a, [wSurfingMinigamePikachuSpeed + 1] + and $3 + ld d, a + sla e + rl d + ld e, d + ld d, $0 + ld hl, .Tempos + add hl, de + add hl, de + ld a, [hli] + ld [wMusicTempo + 1], a + ld a, [hl] + ld [wMusicTempo], a + ret + +.Tempos: + dw 117 + dw 109 + dw 101 + dw 93 + dw 85 + +SurfingMinigame_ResetMusicTempo: + ld hl, wChannelNoteDelayCounters + ld a, $1 + cp [hl] + ret nz + inc hl + cp [hl] + ret nz + inc hl + cp [hl] + ret nz + ld a, 117 + ld [wMusicTempo + 1], a + xor a + ld [wMusicTempo], a + ret + +SurfingPikachuMinigame_LoadGFXAndLayout: + call SurfingPikachu_ClearTileMap + call ClearSprites + call DisableLCD + ld hl, wSurfingMinigameData + ld bc, wSurfingMinigameDataEnd - wSurfingMinigameData + xor a + call FillMemory + ld hl, wLYOverrides + ld bc, wLYOverridesBufferEnd - wLYOverrides + xor a + call FillMemory + xor a + ld [H_AUTOBGTRANSFERENABLED], a + call ClearObjectAnimationBuffers + + ld hl, SurfingPikachu1Graphics1 + ld de, $9000 + ld bc, $500 + ld a, BANK(SurfingPikachu1Graphics1) + call FarCopyData + + ld hl, SurfingPikachu1Graphics2 + ld de, $8000 + ld bc, $1000 + ld a, BANK(SurfingPikachu1Graphics2) + call FarCopyData + + ld a, SurfingPikachuSpawnStateDataPointer % $100 + ld [wAnimatedObjectSpawnStateDataPointer], a + ld a, SurfingPikachuSpawnStateDataPointer / $100 + ld [wAnimatedObjectSpawnStateDataPointer + 1], a + + ld a, SurfingPikachuObjectJumptable % $100 + ld [wAnimatedObjectJumptablePointer], a + ld a, SurfingPikachuObjectJumptable / $100 + ld [wAnimatedObjectJumptablePointer + 1], a + + ld a, SurfingPikachuOAMData % $100 + ld [wAnimatedObjectOAMDataPointer], a + ld a, SurfingPikachuOAMData / $100 + ld [wAnimatedObjectOAMDataPointer + 1], a + + ld a, SurfingPikachuFrames % $100 + ld [wAnimatedObjectFramesDataPointer], a + ld a, SurfingPikachuFrames / $100 + ld [wAnimatedObjectFramesDataPointer + 1], a + + ld hl, vBGMap0 + ld bc, $800 + ld a, $0 + call FillMemory + + ld hl, $98c0 + ld bc, $180 + ld a, $b + call FillMemory + + ld a, $1 + lb de, $74, $58 + call SpawnAnimatedObject + + ld a, $74 + ld [wSurfingMinigamePikachuObjectHeight], a + + call SurfingMinigame_InitScanlineOverrides + + xor a + ld [hSCX], a + ld [hSCY], a + ld a, $7e + ld [hWY], a + ld a, rSCY - $ff00 + ld [hLCDCPointer], a + ld a, $40 + ld [wSurfingMinigamePikachuSpeed], a + xor a + ld [wSurfingMinigamePikachuSpeed + 1], a + xor a + ld [wSurfingMinigamePikachuHP], a + ld a, $60 + ld [wSurfingMinigamePikachuHP + 1], a + ld hl, wSurfingMinigameWaveHeight + ld bc, $14 + ld a, $74 + call FillMemory + call Func_f81ff + call Func_f8256 + ld a, $e3 + ld [rLCDC], a + call SurfingPikachuMinigame_SetBGPals + ld a, $e4 + ld [rOBP0], a + ld a, $e0 + ld [rOBP1], a + call UpdateGBCPal_OBP0 + call UpdateGBCPal_OBP1 + ret + +SurfingPikachuMinigame_SetBGPals: + ld a, [wOnSGB] + and a + jr nz, .sgb + ld a, $d0 + ld [rBGP], a + call UpdateGBCPal_BGP + ret + +.sgb + ld a, $e4 + ld [rBGP], a + call UpdateGBCPal_BGP + ret + +Func_f81ff: + ld hl, wSpriteDataEnd + ld de, Unkn_f8249 + ld b, $97 + ld c, $80 + ld a, $4 + call Func_f8233 + ld de, Unkn_f8248 + ld b, $96 + ld c, $50 + ld a, $1 + call Func_f8233 + ld de, Unkn_f824d + ld b, $14 + ld c, $20 + ld a, $5 + call Func_f8233 + ld de, Unkn_f8252 + ld b, $20 + ld c, $80 + ld a, $4 + call Func_f8233 + ret + +Func_f8233: +.asm_f8233 + push af + ld [hl], b + inc hl + ld [hl], c + inc hl + ld a, [de] + ld [hl], a + inc hl + ld [hl], $0 + inc hl + ld a, c + add $8 + ld c, a + inc de + pop af + dec a + jr nz, .asm_f8233 + ret + +Unkn_f8248: + db $fe + +Unkn_f8249: + db $d0 + db $d0 + db $d0 + db $d0 + +Unkn_f824d: + db $ec + db $ed + db $ed + db $ee + db $ef + +Unkn_f8252: + db $ec + db $ed + db $ee + db $ef + +Func_f8256: + ld de, $9c21 + ld hl, Unkn_f8279 + ld c, $9 +.asm_f825e + ld a, [hli] + ld [de], a + inc de + dec c + jr nz, .asm_f825e + ld hl, $9c01 + ld [hl], $15 + ld hl, $9c02 + ld [hl], $16 + ld hl, $9c2c + ld [hl], $1b + ld hl, $9c2d + ld [hl], $1c + ret + +Unkn_f8279: + db $17 + db $18 + db $19 + db $19 + db $19 + db $19 + db $19 + db $19 + db $19 + +RunSurfingMinigameRoutine: + ld a, [wSurfingMinigameRoutineNumber] + ld e, a + ld d, $0 + ld hl, .Jumptable + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + jp hl + +.Jumptable: + dw SurfingMinigameRoutine_SpawnPikachu ; 0 + dw SurfingMinigame_RunGame ; 1 + dw Func_f8324 ; 2 + dw Func_f835c ; 3 + dw SurfingMinigame_DrawResultsScreenAndWait ; 4 + dw SurfingMinigame_WriteHPLeftAndWait ; 5 + dw SurfingMinigame_WriteRadnessAndWait ; 6 + dw SurfingMinigame_WriteTotalAndWait ; 7 + dw SurfingMinigame_AddRemainingHPToTotalAndWait ; 8 + dw SurfingMinigame_AddRadnessToTotalAndWait ; 9 + dw SurfingMinigame_WaitLast ; a + dw SurfingMinigame_ExitOnPressA ; b + dw SurfingMinigame_GameOver ; c + +SurfingMinigameRoutine_SpawnPikachu: + ld a, $2 + lb de, $48, $e0 + call SpawnAnimatedObject + ld hl, wSurfingMinigameRoutineNumber + inc [hl] + ld a, $1 + ld [wc634], a + ret + +SurfingMinigame_RunGame: + ld a, [wc5e5] + cp $18 + jr nc, .asm_f82e8 + ld hl, wSurfingMinigamePikachuHP + ld a, [hli] + or [hl] + and a + jr z, .dead + call Random + ld [wc5d5], a + call SurfingMinigame_UpdateLYOverrides + call SurfingMinigame_SetPikachuHeight + call SurfingMinigame_ReadBGMapBuffer + call SurfingMinigame_ScrollAndGenerateBGMap + call SurfingMinigame_UpdatePikachuDistance + call SurfingMinigame_Deduct1HP + call SurfingMinigame_DrawHP + ret + +.asm_f82e8 + ld hl, wSurfingMinigameRoutineNumber + inc [hl] + xor a + ld [wc634], a + ld a, 192 + ld [wSurfingMinigameRoutineDelay], a + ret + +.dead + ld a, $1 + ld [wc630], a + ld a, $c + ld [wSurfingMinigameRoutineNumber], a + ld a, $80 + ld [wc631], a + ld a, $b + lb de, $88, $58 + call SpawnAnimatedObject + ld hl, ANIM_OBJ_Y_OFFSET + add hl, bc + ld [hl], $80 + ld hl, ANIM_OBJ_FIELD_B + add hl, bc + ld [hl], $80 + ld hl, ANIM_OBJ_FIELD_C + add hl, bc + ld [hl], $30 + xor a + ld [wc634], a + ret + +Func_f8324: + call SurfingMinigame_RunDelayTimer + jr c, .done_delay + xor a + ld [wc5d5], a + call SurfingMinigame_UpdateLYOverrides + call SurfingMinigame_SetPikachuHeight + call SurfingMinigame_ReadBGMapBuffer + call Func_f8c97 + call SurfingMinigame_ResetMusicTempo + ret + +.done_delay + ld hl, wSurfingMinigameRoutineNumber + inc [hl] + ld a, $90 + ld [hSCX], a + ld a, $72 + ld [wSurfingMinigameWaveFunctionNumber], a + ld a, $4 + ld [wc5d2], a + xor a + ld [hLCDCPointer], a + ld [wSurfingMinigameSCX], a + ld [wSurfingMinigameSCX + 1], a + ld [wSurfingMinigameSCX + 2], a + ret + +Func_f835c: + ld a, [hSCX] + and a + jr z, .asm_f837b + call SurfingMinigame_UpdateLYOverrides + call SurfingMinigame_SetPikachuHeight + call SurfingMinigame_ReadBGMapBuffer + ld a, [hSCX] + dec a + dec a + dec a + dec a + ld [hSCX], a + ld a, $e0 + ld [wSurfingMinigameXOffset], a + call SurfingMinigame_GenerateBGMap + ret + +.asm_f837b + xor a + ld [wSurfingMinigamePikachuSpeed], a + ld [wSurfingMinigamePikachuSpeed + 1], a + ld hl, wSurfingMinigameRoutineNumber + inc [hl] + ld a, $5 + ld [wc5d2], a + ret + +SurfingMinigame_DrawResultsScreenAndWait: + call SurfingMinigame_DrawResultsScreen + ld a, 32 + ld [wSurfingMinigameRoutineDelay], a + ld hl, wSurfingMinigameRoutineNumber + inc [hl] + ret + +SurfingMinigame_WriteHPLeftAndWait: + call SurfingMinigame_RunDelayTimer + ret nc + call SurfingMinigame_WriteHPLeft + ld a, 64 + ld [wSurfingMinigameRoutineDelay], a + ld hl, wSurfingMinigameRoutineNumber + inc [hl] + ret + +SurfingMinigame_WriteRadnessAndWait: + call SurfingMinigame_RunDelayTimer + ret nc + call SurfingMinigame_WriteRadness + ld a, 64 + ld [wSurfingMinigameRoutineDelay], a + ld hl, wSurfingMinigameRoutineNumber + inc [hl] + ret + +SurfingMinigame_WriteTotalAndWait: + call SurfingMinigame_RunDelayTimer + ret nc + call SurfingMinigame_WriteTotal + ld a, 64 + ld [wSurfingMinigameRoutineDelay], a + ld hl, wSurfingMinigameRoutineNumber + inc [hl] + ret + +SurfingMinigame_AddRemainingHPToTotalAndWait: + call SurfingMinigame_RunDelayTimer + ret nc + call SurfingMinigame_AddRemainingHPToTotal + push af + call SurfingMinigame_BCDPrintTotalScore + pop af + ret nc + ld a, 64 + ld [wSurfingMinigameRoutineDelay], a + ld hl, wSurfingMinigameRoutineNumber + inc [hl] + ret + +SurfingMinigame_AddRadnessToTotalAndWait: + call SurfingMinigame_RunDelayTimer + ret nc + call SurfingMinigame_AddRadnessToTotal + push af + call SurfingMinigame_BCDPrintTotalScore + pop af + ret nc + ld a, 128 + ld [wSurfingMinigameRoutineDelay], a + ld hl, wSurfingMinigameRoutineNumber + inc [hl] + call DidPlayerGetAHighScore + ret nc + call SurfingMinigame_PrintTextHiScore + ld a, $6 + ld [wc5d2], a + ret + +SurfingMinigame_WaitLast: + call SurfingMinigame_RunDelayTimer + ret nc + ld hl, wSurfingMinigameRoutineNumber + inc [hl] + ret + +SurfingMinigame_ExitOnPressA: + call SurfingMinigame_UpdateLYOverrides + ld a, [hJoyPressed] + and A_BUTTON + ret z + ld hl, wSurfingMinigameRoutineNumber + set 7, [hl] + ret + +SurfingMinigame_GameOver: + call SurfingMinigame_UpdateLYOverrides + call SurfingMinigame_SetPikachuHeight + call SurfingMinigame_ReadBGMapBuffer + call SurfingMinigame_ScrollAndGenerateBGMap + call SurfingMinigame_ResetMusicTempo + ld hl, wc631 + ld a, [hl] + and a + jr z, .wait_press_a + dec [hl] + ret + +.wait_press_a + ld a, [hJoyPressed] + and A_BUTTON + ret z + ld hl, wSurfingMinigameRoutineNumber + set 7, [hl] + ret + +SurfingMinigame_RunDelayTimer: + ld hl, wSurfingMinigameRoutineDelay + ld a, [hl] + and a + jr z, .set_carry + dec [hl] + and a + ret + +.set_carry + scf + ret + +SurfingMinigame_UpdatePikachuDistance: + ld a, [wc5e5 + 1] + ld h, a + ld a, [wc5e5 + 2] + ld l, a + ld a, [wSurfingMinigamePikachuSpeed] + ld e, a + ld a, [wSurfingMinigamePikachuSpeed + 1] + ld d, a + add hl, de + ld a, h + ld [wc5e5 + 1], a + ld a, l + ld [wc5e5 + 2], a + ret nc + ld hl, wc5e5 + inc [hl] + ld hl, wOAMBuffer + 4 * 4 + 1 + dec [hl] + dec [hl] + ret + +SurfingMinigameAnimatedObjectFn_Pikachu + ld a, [wc5d2] + ld e, a + ld d, $0 + ld hl, Jumptable_f847f + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + jp hl + +Jumptable_f847f: + dw Func_f848d + dw SurfingMinigame_ScoreCurrentWave + dw Func_f8516 + dw Func_f8545 + dw Func_f8561 + dw Func_f856d + dw Func_f8579 + +Func_f848d: + ld a, [wc630] + and a + jr nz, .asm_f84d2 + call Func_f87b5 + ld a, [wSurfingMinigamePikachuObjectHeight] + ld hl, ANIM_OBJ_Y_COORD + add hl, bc + ld [hl], a + call Func_f871e + jr c, .splash + call Func_f8742 + call SurfingMinigame_SpeedUpPikachu + ret + +.splash + call Func_f8742 + ld a, $1 ; on a wave + ld [wc5d2], a + xor a + ld hl, ANIM_OBJ_FIELD_C + add hl, bc + ld [hl], a + ld hl, ANIM_OBJ_FIELD_D + add hl, bc + ld [hl], a + ld hl, ANIM_OBJ_FIELD_E + add hl, bc + ld [hl], a + ld [wSurfingMinigameRadnessMeter], a + ld [wSurfingMinigameTrickFlags], a + xor a + ld [wChannelSoundIDs + Ch8], a + ld a, SFX_SURFING_JUMP + call PlaySound + ret + +.asm_f84d2 + xor a + ld [wSurfingMinigamePikachuSpeed], a + ld [wSurfingMinigamePikachuSpeed + 1], a + ld a, $4 + ld [wc5d2], a + call Func_f8742 + ret + +SurfingMinigame_ScoreCurrentWave: + call SurfingMinigame_DPadAction + call SurfingMinigame_UpdatePikachuHeight + ret nc + call SurfingMinigame_TileInteraction + jr c, .splash + call SurfingMinigame_CalculateAndAddRadnessFromStunt + ld hl, ANIM_OBJ_FIELD_C + add hl, bc + ld [hl], $0 + ld a, $2 + ld [wc5d2], a + ret + +.splash + ld a, $3 + ld [wc5d2], a + ld a, $60 + ld [wc5e1], a + ld a, $10 + call SetCurrentAnimatedObjectCallbackAndResetFrameStateRegisters + xor a + ld [wChannelSoundIDs + Ch8], a + ld a, SFX_SURFING_LAND + call PlaySound + ret + +Func_f8516: + ld hl, ANIM_OBJ_FIELD_C + add hl, bc + ld a, [hl] + cp $20 + jr nc, .asm_f8539 + inc [hl] + inc [hl] + inc [hl] + inc [hl] + ld d, $4 + call SurfingPikachu_Sine + ld hl, ANIM_OBJ_Y_OFFSET + add hl, bc + ld [hl], a + call Func_f87b5 + ld a, [wSurfingMinigamePikachuObjectHeight] + ld hl, ANIM_OBJ_Y_COORD + add hl, bc + ld [hl], a + ret + +.asm_f8539 + ld hl, ANIM_OBJ_Y_OFFSET + add hl, bc + ld [hl], $0 + ld a, $0 + ld [wc5d2], a + ret + +Func_f8545: + ld hl, wc5e1 + ld a, [hl] + and a + jr z, .asm_f8556 + dec [hl] + ld a, [wSurfingMinigamePikachuObjectHeight] + ld hl, ANIM_OBJ_Y_COORD + add hl, bc + ld [hl], a + ret + +.asm_f8556 + ld a, $0 + ld [wc5d2], a + ld a, $4 + call SetCurrentAnimatedObjectCallbackAndResetFrameStateRegisters + ret + +Func_f8561: + ld a, [wSurfingMinigamePikachuObjectHeight] + ld hl, ANIM_OBJ_Y_COORD + add hl, bc + ld [hl], a + call Func_f8742 + ret + +Func_f856d: + ld a, $f + call SetCurrentAnimatedObjectCallbackAndResetFrameStateRegisters + ld hl, ANIM_OBJ_FIELD_C + add hl, bc + ld [hl], $0 + ret + +Func_f8579: + ld hl, ANIM_OBJ_FIELD_C + add hl, bc + ld a, [hl] + inc [hl] + inc [hl] + and $3f + cp $20 + jr c, .asm_f8591 + ld d, $10 + call SurfingPikachu_Sine + ld hl, ANIM_OBJ_Y_OFFSET + add hl, bc + ld [hl], a + ret + +.asm_f8591 + ld hl, ANIM_OBJ_Y_OFFSET + add hl, bc + ld [hl], $0 + ret + +SurfingMinigame_DPadAction: + ld de, hJoy5 + ld a, [de] + and D_LEFT + jr nz, .d_left + ld a, [de] + and D_RIGHT + jr nz, .d_right + ret + +.d_left + ld hl, ANIM_OBJ_FIELD_E + add hl, bc + ld [hl], $0 + ld hl, ANIM_OBJ_FIELD_D + add hl, bc + ld a, [hl] + inc [hl] + cp $b + jr c, .d_left_skip + call .StartTrick + ld hl, wSurfingMinigameTrickFlags + set 0, [hl] +.d_left_skip + ld hl, ANIM_OBJ_FRAME_SET + add hl, bc + ld a, [hl] + cp $e + jr nc, .d_left_reset + inc [hl] + ret + +.d_left_reset + ld [hl], $1 + ret + +.d_right + ld hl, ANIM_OBJ_FIELD_D + add hl, bc + ld [hl], $0 + ld hl, ANIM_OBJ_FIELD_E + add hl, bc + ld a, [hl] + inc [hl] + cp $d + jr c, .d_right_skip + call .StartTrick + ld hl, wSurfingMinigameTrickFlags + set 1, [hl] +.d_right_skip + ld hl, ANIM_OBJ_FRAME_SET + add hl, bc + ld a, [hl] + cp $1 + jr z, .d_right_reset + dec [hl] + ret + +.d_right_reset + ld [hl], $e + ret + +.StartTrick: + call SurfingMinigame_IncreaseRadnessMeter + xor a + ld hl, ANIM_OBJ_FIELD_D + add hl, bc + ld [hl], a + ld hl, ANIM_OBJ_FIELD_E + add hl, bc + ld [hl], a + ld a, SFX_SURFING_FLIP + call PlaySound + ret + +SurfingMinigame_TileInteraction: + ld hl, ANIM_OBJ_FRAME_SET + add hl, bc + ld a, [wSurfingMinigameBGMapReadBuffer] + cp $6 + jr z, .tile_06 + cp $14 + jr z, .tile_14 + cp $12 + jr z, .tile_12 + cp $7 + jr z, .tile_07 + ld a, [hl] + cp $1 + jp z, .action_0 + cp $2 + jr z, .action_1 + cp $3 + jr z, .action_2 + cp $4 + jr z, .action_3 + cp $5 + jr z, .action_2 + cp $6 + jr z, .action_1 + cp $7 + jr z, .action_0 + jr .action_0 + +.tile_06 + ld a, [hl] + cp $1 + jr z, .action_0 + cp $2 + jr z, .action_0 + cp $3 + jr z, .action_0 + cp $4 + jr z, .action_1 + cp $5 + jr z, .action_2 + cp $6 + jr z, .action_3 + cp $7 + jr z, .action_2 + jr .action_0 + +.tile_07 + ld a, [hl] + cp $1 + jr z, .action_2 + cp $2 + jr z, .action_3 + cp $3 + jr z, .action_2 + cp $4 + jr z, .action_1 + cp $5 + jr z, .action_0 + cp $6 + jr z, .action_0 + cp $7 + jr z, .action_0 + jr .action_0 + +.tile_12 +.tile_14 + ld a, [hl] + cp $1 + jr z, .action_0 + cp $2 + jr z, .action_1 + cp $3 + jr z, .action_2 + cp $4 + jr z, .action_3 + cp $5 + jr z, .action_3 + cp $6 + jr z, .action_2 + cp $7 + jr z, .action_1 + jr .action_0 + +.action_1 + call SufingMinigame_ReduceSpeedBy128 + jr .action_3 + +.action_2 + call SufingMinigame_ReduceSpeedBy64 +.action_3 + xor a + ld [wChannelSoundIDs + Ch8], a + ld a, SFX_SURFING_CRASH + call PlaySound + and a + ret + +.action_0 + ld a, $40 + ld [wSurfingMinigamePikachuSpeed], a + xor a + ld [wSurfingMinigamePikachuSpeed + 1], a + scf + ret + +SurfingMinigame_SpeedUpPikachu: + ld a, [wSurfingMinigamePikachuSpeed + 1] + cp $2 + ret nc + ld h, a + ld a, [wSurfingMinigamePikachuSpeed] + ld l, a + ld de, $2 + add hl, de + ld a, h + ld [wSurfingMinigamePikachuSpeed + 1], a + ld a, l + ld [wSurfingMinigamePikachuSpeed], a + ret + +SufingMinigame_ReduceSpeedBy64: + ld a, [wSurfingMinigamePikachuSpeed + 1] + and a + jr nz, .go + ld a, [wSurfingMinigamePikachuSpeed] + cp $40 + jr nc, .go + xor a + ld [wSurfingMinigamePikachuSpeed], a + ret + +.go + ld a, [wSurfingMinigamePikachuSpeed + 1] + ld h, a + ld a, [wSurfingMinigamePikachuSpeed] + ld l, a + ld de, -$40 + add hl, de + ld a, h + ld [wSurfingMinigamePikachuSpeed + 1], a + ld a, l + ld [wSurfingMinigamePikachuSpeed], a + ret + +SufingMinigame_ReduceSpeedBy128: + ld a, [wSurfingMinigamePikachuSpeed + 1] + and a + jr nz, .go + ld a, [wSurfingMinigamePikachuSpeed] + cp $80 + jr nc, .go + xor a + ld [wSurfingMinigamePikachuSpeed], a + ret + +.go + ld a, [wSurfingMinigamePikachuSpeed + 1] + ld h, a + ld a, [wSurfingMinigamePikachuSpeed] + ld l, a + ld de, -$80 + add hl, de + ld a, h + ld [wSurfingMinigamePikachuSpeed + 1], a + ld a, l + ld [wSurfingMinigamePikachuSpeed], a + ret + +Func_f871e: + ld a, [hSCX] + and $7 + cp $3 + jr c, .asm_f8740 + cp $5 + jr nc, .asm_f8740 + ld a, [wSurfingMinigameBGMapReadBuffer] + cp $14 + jr nz, .asm_f8740 + call SufingMinigame_GetSpeedDividedBy32 + cp $a + jr c, .asm_f8740 + ld [wc5ec], a + call Func_f9284 + scf + ret + +.asm_f8740 + and a + ret + +Func_f8742: + ld a, [hSCX] + and $7 + cp $3 + ret c + cp $5 + ret nc + ld a, [wSurfingMinigameBGMapReadBuffer] + cp $6 + jr z, .asm_f8766 + cp $14 + jr z, .asm_f8766 + cp $7 + jr z, .asm_f876a + call Func_f8778 + ld a, $4 + ld hl, ANIM_OBJ_FRAME_SET + add hl, bc + ld [hl], a + ret + +.asm_f8766 + ld a, $6 + jr .asm_f876c + +.asm_f876a + ld a, $2 +.asm_f876c + ld e, a + ld a, [wc5de] + dec a + add e + ld hl, ANIM_OBJ_FRAME_SET + add hl, bc + ld [hl], a + ret + +Func_f8778: + ld hl, wc5e0 + ld a, [hl] + inc [hl] + and $7 + ret nz + ld a, [wc5df] + and a + jr z, .asm_f8796 + ld a, [wc5de] + and a + jr z, .asm_f8791 + dec a + ld [wc5de], a + ret + +.asm_f8791 + xor a + ld [wc5df], a + ret + +.asm_f8796 + ld a, [wc5de] + cp $2 + jr z, .asm_f87a2 + inc a + ld [wc5de], a + ret + +.asm_f87a2 + ld a, $1 + ld [wc5df], a + ret + +SufingMinigame_GetSpeedDividedBy32: + ld a, [wSurfingMinigamePikachuSpeed] + ld l, a + ld a, [wSurfingMinigamePikachuSpeed + 1] + ld h, a + add hl, hl + add hl, hl + add hl, hl + ld a, h + ret + +Func_f87b5: + ld hl, wc5eb + ld a, [hl] + inc [hl] + and $3 + ret nz + call .GetYCoord + ld d, a + ld hl, ANIM_OBJ_X_COORD + add hl, bc + ld e, [hl] + ld a, $a + push bc + call SpawnAnimatedObject + pop bc + ret + +.GetYCoord: + ld a, [hSCX] + and $8 + jr nz, .get_height_plus_9 + ld hl, wSurfingMinigameWaveHeight + 8 + jr .got_hl + +.get_height_plus_9 + ld hl, wSurfingMinigameWaveHeight + 9 +.got_hl + ld a, [wSurfingMinigameBGMapReadBuffer + 1] + cp $6 + jr z, .six_or_twenty + cp $14 + jr z, .six_or_twenty + cp $7 + jr z, .seven + ld a, [hl] + ret + +.six_or_twenty + ld a, [hSCX] + and $7 + ld e, a + ld a, [hl] + sub e + ret + +.seven + ld a, [hSCX] + and $7 + add [hl] + ret + +Func_f87fb: + ld hl, ANIM_OBJ_X_COORD + add hl, bc + ld a, [hl] + cp $58 + ret z + add $4 + ld [hl], a + ret + +Func_f8807: ; unreferenced + call MaskCurrentAnimatedObjectStruct + ret + +SurfingMinigameAnimatedObjectFn_FlippingPika: + ld hl, ANIM_OBJ_FIELD_B + add hl, bc + ld a, [hl] + and a + ret z + dec [hl] + dec [hl] + ld d, a + ld hl, ANIM_OBJ_FIELD_C + add hl, bc + ld a, [hl] + inc [hl] + call SurfingPikachu_Sine + cp $80 + jr nc, .positive + xor $ff + inc a +.positive + ld hl, ANIM_OBJ_Y_OFFSET + add hl, bc + ld [hl], a + ret + +SurfingMinigameAnimatedObjectFn_IntroAnimationPikachu: + ld hl, ANIM_OBJ_FIELD_B + add hl, bc + ld a, [hl] + inc [hl] + and $1 + ret z + ld hl, ANIM_OBJ_X_COORD + add hl, bc + ld a, [hl] + cp $c0 + jr z, .done + inc [hl] + ret + +.done + ld a, $1 + ld [wSurfingMinigameIntroAnimationFinished], a + call MaskCurrentAnimatedObjectStruct + ret + +SurfingMinigame_MoveClouds: + ld a, [wc635] + ld e, a + ld d, $0 + ld a, [wSurfingMinigamePikachuSpeed] + ld l, a + ld a, [wSurfingMinigamePikachuSpeed + 1] + ld h, a + add hl, de + ld a, l + ld [wc635], a + ld d, h + ld hl, wOAMBuffer + 5 * 4 + 1 + ld e, $9 +.loop + ld a, [hl] + add d + ld [hli], a + inc hl + inc hl + inc hl + dec e + jr nz, .loop + ret + +SurfingMinigame_ReadBGMapBuffer: + ld a, [wSurfingMinigameBGMapReadBuffer] ; ??? + ld a, [hSCX] + add $48 + ld e, a + srl e + srl e + srl e + ld d, $0 + ld hl, vBGMap0 + add hl, de + ld a, [wSurfingMinigamePikachuObjectHeight] + srl a + srl a + srl a + ld c, a +.loop + ld a, c + and a + jr z, .copy + dec c + ld de, $20 + add hl, de + ld a, h + and $3 + or $98 + ld h, a + jr .loop + +.copy + ld de, wSurfingMinigameBGMapReadBuffer + ld a, e + ld [H_VBCOPYDEST], a + ld a, d + ld [H_VBCOPYDEST + 1], a + ld a, l + ld [H_VBCOPYSRC], a + ld a, h + ld [H_VBCOPYSRC + 1], a + ld a, 16 / $10 + ld [H_VBCOPYSIZE], a + ret + +SurfingMinigame_SetPikachuHeight: + ld a, [hSCX] + and $8 + jr nz, .asm_f88b9 + ld hl, wSurfingMinigameWaveHeight + 7 + jr .asm_f88bc + +.asm_f88b9 + ld hl, wSurfingMinigameWaveHeight + 8 +.asm_f88bc + ld a, [wSurfingMinigameBGMapReadBuffer] + cp $6 + jr z, .asm_f88d0 + cp $14 + jr z, .asm_f88d0 + cp $7 + jr z, .asm_f88db + ld a, [hl] + ld [wSurfingMinigamePikachuObjectHeight], a + ret + +.asm_f88d0 + ld a, [hSCX] + and $7 + ld e, a + ld a, [hl] + sub e + ld [wSurfingMinigamePikachuObjectHeight], a + ret + +.asm_f88db + ld a, [hSCX] + and $7 + add [hl] + ld [wSurfingMinigamePikachuObjectHeight], a + ret + +SurfingMinigame_Deduct1HP: + ld hl, wSurfingMinigamePikachuHP + ld e, $99 + call .BCD_Deduct + ret nc + inc hl + ld e, $99 +.BCD_Deduct: + ld a, [hl] + and a + jr z, .roll_over + sub $1 + daa + ld [hl], a + and a + ret + +.roll_over + ld [hl], e + scf + ret + +SurfingMinigame_DrawHP: + ld de, wSurfingMinigamePikachuHP + 1 + ld hl, wOAMBuffer + 0 * 4 + 2 + ld a, [de] + call .PlaceBCDNumber + ld hl, wOAMBuffer + 2 * 4 + 2 + ld a, [de] +.PlaceBCDNumber: + ld c, a + swap a + and $f + add $d0 + ld [hli], a + inc hl + inc hl + inc hl + ld a, c + and $f + add $d0 + ld [hl], a + dec de + ret + +SurfingMinigame_DrawResultsScreen: + ld hl, wTileMap + ld bc, SCREEN_WIDTH * SCREEN_HEIGHT + xor a + call FillMemory + ld hl, .BeachTilemap + coord de, 0, 6 + ld bc, .BeachTilemapEnd - .BeachTilemap + call CopyData + call .PlaceTextbox + ld hl, wOAMBuffer + 5 * 4 + 1 + ld bc, 9 * 4 + xor a + call FillMemory + ld a, $1 + ld [H_AUTOBGTRANSFERENABLED], a + ret + +.BeachTilemap: +INCBIN "gfx/unknown_f8946.map" +.BeachTilemapEnd: + +.PlaceTextbox: + coord hl, 1, 1 + lb de, $3b, $3c + ld a, $40 + call .place_row + coord hl, 1, 2 + lb de, $3f, $3f + ld a, $ff + call .place_row + coord hl, 1, 3 + lb de, $3f, $3f + ld a, $ff + call .place_row + coord hl, 1, 4 + lb de, $3f, $3f + ld a, $ff + call .place_row + coord hl, 1, 5 + lb de, $3f, $3f + ld a, $ff + call .place_row + coord hl, 1, 6 + lb de, $3f, $3f + ld a, $ff + call .place_row + coord hl, 1, 7 + lb de, $3f, $3f + ld a, $ff + call .place_row + coord hl, 1, 8 + lb de, $3f, $3f + ld a, $ff + call .place_row + coord hl, 1, 9 + lb de, $3d, $3e + ld a, $40 + call .place_row + ret + +.place_row: + ld [hl], d + inc hl + ld c, $10 +.loop + ld [hli], a + dec c + jr nz, .loop + ld [hl], e + ret + +SurfingMinigame_PrintTextHiScore: + ld hl, .Hi_Score + coord de, 6, 8 + ld bc, $9 + call CopyData + ret + +.Hi_Score: + db $20,$2e,$2f,$30,$31,$2c,$32,$23,$33 ; Hi-Score!! + +SurfingMinigame_WriteHPLeft: + ld hl, .HP_Left + coord de, 2, 2 + ld bc, $7 + call CopyData + call SurfingMinigame_BCDPrintHPLeft + ret + +.HP_Left: + db $20,$21,$ff,$22,$23,$24,$25 ; HP Left + +SurfingMinigame_AddRemainingHPToTotal: + ld c, 99 +.loop + push bc + ld hl, wSurfingMinigamePikachuHP + ld a, [hli] + or [hl] + and a + jr z, .dead + call SurfingMinigame_Deduct1HP + ld e, $1 + call SurfingMinigame_AddPointsToTotal + pop bc + dec c + jr nz, .loop + ld a, SFX_SURFING_ADD_POINTS + call PlaySound + and a + ret + +.dead + pop bc + scf + ret + +SurfingMinigame_BCDPrintHPLeft: + coord hl, 10, 2 + ld de, wSurfingMinigamePikachuHP + 1 + ld a, [de] + call SurfingPikachu_PlaceBCDNumber + inc hl + ld a, [de] + call SurfingPikachu_PlaceBCDNumber + inc hl + inc hl + ld [hl], $21 ; P + inc hl + ld [hl], $25 ; t + inc hl + ld [hl], $26 ; s + ret + +SurfingMinigame_WriteRadness: + ld hl, .Radness + coord de, 2, 4 + ld bc, $7 + call CopyData + call SurfingMinigame_BCDPrintRadness + ret + +.Radness: + db $27,$28,$29,$2a,$23,$26,$26 ; Radness + +SurfingMinigame_AddRadnessToTotal: + ld c, 99 +.loop + push bc + ld hl, wSurfingMinigameRadnessScore + ld a, [hli] + ld e, a + or [hl] + jr z, .done + ld d, [hl] + ld a, e + sub $1 + daa + ld e, a + ld a, d + sbc $0 + daa + ld [hld], a + ld [hl], e + ld e, $1 + call SurfingMinigame_AddPointsToTotal + pop bc + dec c + jr nz, .loop + ld a, SFX_SURFING_ADD_POINTS + call PlaySound + and a + ret + +.done + pop bc + scf + ret + +SurfingMinigame_BCDPrintRadness: + ld a, [wSurfingMinigameRadnessScore + 1] + coord hl, 10, 4 + call SurfingPikachu_PlaceBCDNumber + ld a, [wSurfingMinigameRadnessScore] + coord hl, 12, 4 + call SurfingPikachu_PlaceBCDNumber + inc hl + inc hl + ld [hl], $21 ; P + inc hl + ld [hl], $25 ; t + inc hl + ld [hl], $26 ; s + ret + +SurfingMinigame_AddPointsToTotal: + ld a, [wSurfingMinigameTotalScore] + add e + daa + ld [wSurfingMinigameTotalScore], a + ld a, [wSurfingMinigameTotalScore + 1] + adc $0 + daa + ld [wSurfingMinigameTotalScore + 1], a + ret nc + ld a, $99 + ld [wSurfingMinigameTotalScore], a + ld [wSurfingMinigameTotalScore + 1], a + ret + +SurfingMinigame_BCDPrintTotalScore: + ld a, [wSurfingMinigameTotalScore + 1] + coord hl, 10, 6 + call SurfingPikachu_PlaceBCDNumber + ld a, [wSurfingMinigameTotalScore] + coord hl, 12, 6 + call SurfingPikachu_PlaceBCDNumber + inc hl + inc hl + ld [hl], $21 ; P + inc hl + ld [hl], $25 ; t + inc hl + ld [hl], $26 ; s + ret + +SurfingMinigame_WriteTotal: + ld hl, .Total + coord de, 2, 6 + ld bc, $5 + call CopyData + call SurfingMinigame_BCDPrintRadness + call SurfingMinigame_BCDPrintTotalScore + ret + +.Total: + db $2b,$2c,$25,$28,$2d ; Total + +DidPlayerGetAHighScore: + ld hl, wSurfingMinigameHiScore + 1 + ld a, [wSurfingMinigameTotalScore + 1] + cp [hl] + jr c, .not_high_score + jr nz, .high_score + dec hl + ld a, [wSurfingMinigameTotalScore] + cp [hl] + jr c, .not_high_score + jr nz, .high_score +.not_high_score + call WaitForSoundToFinish + ldpikacry e, PikachuCry28 + call SurfingMinigame_PlayPikaCryIfSurfingPikaInParty + and a + ret + +.high_score + ld a, [wSurfingMinigameTotalScore] + ld [wSurfingMinigameHiScore], a + ld a, [wSurfingMinigameTotalScore + 1] + ld [wSurfingMinigameHiScore + 1], a + call WaitForSoundToFinish + ldpikacry e, PikachuCry34 + call SurfingMinigame_PlayPikaCryIfSurfingPikaInParty + ld a, SFX_GET_ITEM2_4_2 + call PlaySound + scf + ret + +SurfingMinigame_PlayPikaCryIfSurfingPikaInParty: + push de + callab IsSurfingPikachuInThePlayersParty + pop de + ret nc + callab PlayPikachuSoundClip + ret + +SurfingMinigame_IncreaseRadnessMeter: + ld a, [wSurfingMinigameRadnessMeter] + inc a + cp $4 + jr c, .cap + ld a, $3 +.cap + ld [wSurfingMinigameRadnessMeter], a + ret + +SurfingMinigame_CalculateAndAddRadnessFromStunt: + ; Compute the amount of radness points from the + ; current trick based on the number of + ; consecutive flips + ; Single flip: +0050 + ; 2 of the same flip: +0150 + ; 3 or more of the same flip: +0350 + ; 2 different flips: +0180 + ; 3 or more different flips: +0500 + ld a, [wSurfingMinigameRadnessMeter] + and a + ret z + ld a, [wSurfingMinigameTrickFlags] + and $3 + cp $3 ; did a combination of front and back flips + jr z, .mixed_chain + ld a, [wSurfingMinigameRadnessMeter] + ld d, a + ld e, $1 + ld a, $0 +.get_amount_of_radness + add e + sla e + dec d + jr nz, .get_amount_of_radness +.add_radness_50_at_a_time + push af + ld e, $50 + call SurfingMinigame_AddRadness + pop af + dec a + jr nz, .add_radness_50_at_a_time + ld hl, ANIM_OBJ_Y_COORD + add hl, bc + ld a, [hl] + sub $10 + ld d, a + ld hl, ANIM_OBJ_X_COORD + add hl, bc + ld e, [hl] + ld a, [wSurfingMinigameRadnessMeter] + add $3 + push bc + call SpawnAnimatedObject + pop bc + ret + +.mixed_chain + ld a, [wSurfingMinigameRadnessMeter] + cp $3 + jr c, .add_180_radness_points + ld a, 10 +.add_500_radness_50_at_a_time + push af + ld e, $50 + call SurfingMinigame_AddRadness + pop af + dec a + jr nz, .add_500_radness_50_at_a_time + ld hl, ANIM_OBJ_Y_COORD + add hl, bc + ld a, [hl] + sub $10 + ld d, a + ld hl, ANIM_OBJ_X_COORD + add hl, bc + ld e, [hl] + ld a, $9 + push bc + call SpawnAnimatedObject + pop bc + ret + +.add_180_radness_points + ld e, $50 + call SurfingMinigame_AddRadness + ld e, $50 + call SurfingMinigame_AddRadness + ld e, $50 + call SurfingMinigame_AddRadness + ld e, $30 + call SurfingMinigame_AddRadness + ld hl, ANIM_OBJ_Y_COORD + add hl, bc + ld a, [hl] + sub $10 + ld d, a + ld hl, ANIM_OBJ_X_COORD + add hl, bc + ld e, [hl] + ld a, $8 + push bc + call SpawnAnimatedObject + pop bc + ret + +SurfingMinigame_AddRadness: + ld a, [wSurfingMinigameRadnessScore] + add e + daa + ld [wSurfingMinigameRadnessScore], a + ld a, [wSurfingMinigameRadnessScore + 1] + adc $0 + daa + ld [wSurfingMinigameRadnessScore + 1], a + ret nc + ld a, $99 + ld [wSurfingMinigameRadnessScore], a + ld [wSurfingMinigameRadnessScore + 1], a + ret + +Func_f8c97: + ld a, $a0 + ld [wSurfingMinigameXOffset], a + ld a, [hSCX] + ld h, a + ld a, [wSurfingMinigameSCX] + ld l, a + ld de, $900 + add hl, de + ld a, l + ld [wSurfingMinigameSCX], a + ld a, h + ld [hSCX], a + jr SurfingMinigame_GenerateBGMap + +SurfingMinigame_ScrollAndGenerateBGMap: + ld a, $a0 + ld [wSurfingMinigameXOffset], a + ld a, [hSCX] + ld h, a + ld a, [wSurfingMinigameSCX] + ld l, a + ld de, $180 + add hl, de + ld a, l + ld [wSurfingMinigameSCX], a + ld a, h + ld [hSCX], a +SurfingMinigame_GenerateBGMap: + ld hl, wSurfingMinigameSCX + 1 + ld a, [hSCX] + cp [hl] + ret z + ld [hl], a + and $f0 + ld hl, wSurfingMinigameSCX + 2 + cp [hl] + ret z + ld [hl], a + call SurfingMinigame_GetWaveDataPointers + ; b and c contain the height of the next wave to appear + ; on screen, in number of pixels from the top of the screen + ld a, b + ld [wSurfingMinigameWaveHeightBuffer], a + ld a, c + ld [wSurfingMinigameWaveHeightBuffer + 1], a + push de + ld hl, wSurfingMinigameWaveHeight + ld de, wSurfingMinigameWaveHeight + 2 + ld c, SCREEN_WIDTH - 2 +.copy_loop + ld a, [de] + inc de + ld [hli], a + dec c + jr nz, .copy_loop + ld a, [wSurfingMinigameWaveHeightBuffer] + ld [hli], a + ld a, [wSurfingMinigameWaveHeightBuffer + 1] + ld [hl], a + pop de + ld hl, wRedrawRowOrColumnSrcTiles + ld c, $8 +.loop + ld a, [de] + call .CopyRedrawSrcTiles + inc de + dec c + jr nz, .loop + ld a, [wSurfingMinigameXOffset] + ld e, a + ld a, [hSCX] + add e + and $f0 + srl a + srl a + srl a + ld e, a + ld d, $0 + ld hl, vBGMap0 + add hl, de + ld a, l + ld [hRedrawRowOrColumnDest], a + ld a, h + ld [hRedrawRowOrColumnDest + 1], a + ld a, $1 + ld [hRedrawRowOrColumnMode], a + ret + +.CopyRedrawSrcTiles: + push de + push hl + ld l, a + ld h, $0 + ld de, Unkn_f96e5 + add hl, hl + add hl, hl + add hl, de + ld e, l + ld d, h + pop hl + ld a, [de] + inc de + ld [hli], a + ld a, [de] + inc de + ld [hli], a + ld a, [de] + inc de + ld [hli], a + ld a, [de] + inc de + ld [hli], a + pop de + ret + +SurfingMinigame_GetWaveDataPointers: + ld a, [wSurfingMinigameWaveFunctionNumber] + ld e, a + ld d, $0 + ld hl, Jumptable_f8d53 + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + jp hl + +Jumptable_f8d53: + dw SurfingMinigameWaveFunction_NoWave ; 00 + + dw Func_f8f28 ; 01 + dw Func_f8f31 ; 02 + dw Func_f8f3a ; 03 + dw Func_f8f43 ; 04 + dw Func_f8e7d ; 05 + dw Func_f8f4c ; 06 + dw Func_f8f55 ; 07 + dw Func_f8f5e ; 08 + dw Func_f8e7d ; 09 + dw Func_f8e7d ; 0a + dw Func_f8e7d ; 0b + dw Func_f8e7d ; 0c + dw Func_f8f94 ; 0d + + dw Func_f8ec5 ; 0e + dw Func_f8ece ; 0f + dw Func_f8ed7 ; 10 + dw Func_f8ee0 ; 11 + dw Func_f8ee9 ; 12 + dw Func_f8ef2 ; 13 + dw Func_f8e7d ; 14 + dw Func_f8e7d ; 15 + dw Func_f8e7d ; 16 + dw Func_f8e7d ; 17 + dw Func_f8e7d ; 18 + dw Func_f8f94 ; 19 + + dw Func_f8efb ; 1a + dw Func_f8f04 ; 1b + dw Func_f8f0d ; 1c + dw Func_f8f16 ; 1d + dw Func_f8f1f ; 1e + dw Func_f8efb ; 1f + dw Func_f8f04 ; 20 + dw Func_f8f0d ; 21 + dw Func_f8f16 ; 22 + dw Func_f8f1f ; 23 + dw Func_f8e7d ; 24 + dw Func_f8e7d ; 25 + dw Func_f8e7d ; 26 + dw Func_f8e7d ; 27 + dw Func_f8f94 ; 28 + + dw Func_f8f28 ; 29 + dw Func_f8f31 ; 2a + dw Func_f8f3a ; 2b + dw Func_f8f43 ; 2c + dw Func_f8e7d ; 2d + dw Func_f8e7d ; 2e + dw Func_f8e7d ; 2f + dw Func_f8e7d ; 30 + dw Func_f8f94 ; 31 + + dw Func_f8f4c ; 32 + dw Func_f8f55 ; 33 + dw Func_f8f5e ; 34 + dw Func_f8f4c ; 35 + dw Func_f8f55 ; 36 + dw Func_f8f5e ; 37 + dw Func_f8f4c ; 38 + dw Func_f8f55 ; 39 + dw Func_f8f5e ; 3a + dw Func_f8e7d ; 3b + dw Func_f8e7d ; 3c + dw Func_f8e7d ; 3d + dw Func_f8e7d ; 3e + dw Func_f8f94 ; 3f + + dw Func_f8f67 ; 40 + dw Func_f8f70 ; 41 + dw Func_f8efb ; 42 + dw Func_f8f04 ; 43 + dw Func_f8f0d ; 44 + dw Func_f8f16 ; 45 + dw Func_f8f1f ; 46 + dw Func_f8f67 ; 47 + dw Func_f8f70 ; 48 + dw Func_f8e7d ; 49 + dw Func_f8e7d ; 4a + dw Func_f8e7d ; 4b + dw Func_f8f94 ; 4c + + dw Func_f8ec5 ; 4d + dw Func_f8ece ; 4e + dw Func_f8ed7 ; 4f + dw Func_f8ee0 ; 50 + dw Func_f8ee9 ; 51 + dw Func_f8ef2 ; 52 + dw Func_f8e7d ; 53 + dw Func_f8f67 ; 54 + dw Func_f8f70 ; 55 + dw Func_f8f67 ; 56 + dw Func_f8f70 ; 57 + dw Func_f8e7d ; 58 + dw Func_f8e7d ; 59 + dw Func_f8e7d ; 5a + dw Func_f8f94 ; 5b + + dw Func_f8efb ; 5c + dw Func_f8f04 ; 5d + dw Func_f8f0d ; 5e + dw Func_f8f16 ; 5f + dw Func_f8f1f ; 60 + dw Func_f8f28 ; 61 + dw Func_f8f31 ; 62 + dw Func_f8f3a ; 63 + dw Func_f8f43 ; 64 + dw Func_f8e7d ; 65 + dw Func_f8e7d ; 66 + dw Func_f8e7d ; 67 + dw Func_f8e7d ; 68 + dw Func_f8f94 ; 69 + + dw Func_f8e86 ; 6a + dw Func_f8e8f ; 6b + dw Func_f8e98 ; 6c + dw Func_f8ea1 ; 6d + dw Func_f8eaa ; 6e + dw Func_f8eb3 ; 6f + dw Func_f8ebc ; 70 + dw Func_f8f9d ; 71 + + dw Func_f8e7d ; 72 + dw Func_f8f79 ; 73 + dw Func_f8f82 ; 74 + dw Func_f8f82 ; 75 + dw Func_f8f82 ; 76 + dw Func_f8f82 ; 77 + dw Func_f8f82 ; 78 + dw Func_f8f82 ; 79 + dw Func_f8f82 ; 7a + dw Func_f8f8b ; 7b + +SurfingMinigameWaveFunction_NoWave: + ld a, [wc5e5] + cp $16 + jr c, .check_param + jr z, .big_kahuna + jr nc, .got_wave +.big_kahuna + ld a, $6a + jr .got_next_fn + +.check_param + ld a, [wc5d5] + and a + jr z, .got_wave + dec a + and $7 + ld e, a + ld d, $0 + ld hl, Unkn_f8e75 + add hl, de + ld a, [hl] +.got_next_fn + ld [wSurfingMinigameWaveFunctionNumber], a +.got_wave + lb bc, $74, $74 + ld de, Unkn_f973d + ret + +Unkn_f8e75: + db $01,$0e,$1a,$29,$32,$40,$4d,$5c + +Func_f8e7d: + lb bc, $74, $74 + ld de, Unkn_f973d + jp SurfingMinigameWaveFunction_GoToNextWaveFunction + +Func_f8e86: + lb bc, $74, $6c + ld de, Unkn_f9745 + jp SurfingMinigameWaveFunction_GoToNextWaveFunction + +Func_f8e8f: + lb bc, $64, $5c + ld de, Unkn_f974d + jp SurfingMinigameWaveFunction_GoToNextWaveFunction + +Func_f8e98: + lb bc, $54, $4c + ld de, Unkn_f9755 + jp SurfingMinigameWaveFunction_GoToNextWaveFunction + +Func_f8ea1: + lb bc, $44, $44 + ld de, Unkn_f975d + jp SurfingMinigameWaveFunction_GoToNextWaveFunction + +Func_f8eaa: + lb bc, $44, $4c + ld de, Unkn_f9765 + jp SurfingMinigameWaveFunction_GoToNextWaveFunction + +Func_f8eb3: + lb bc, $54, $5c + ld de, Unkn_f976d + jp SurfingMinigameWaveFunction_GoToNextWaveFunction + +Func_f8ebc: + lb bc, $64, $6c + ld de, Unkn_f9775 + jp SurfingMinigameWaveFunction_GoToNextWaveFunction + +Func_f8ec5: + lb bc, $74, $6c + ld de, Unkn_f977d + jp SurfingMinigameWaveFunction_GoToNextWaveFunction + +Func_f8ece: + lb bc, $64, $5c + ld de, Unkn_f9785 + jp SurfingMinigameWaveFunction_GoToNextWaveFunction + +Func_f8ed7: + lb bc, $54, $4c + ld de, Unkn_f978d + jp SurfingMinigameWaveFunction_GoToNextWaveFunction + +Func_f8ee0: + lb bc, $4c, $4c + ld de, Unkn_f9795 + jp SurfingMinigameWaveFunction_GoToNextWaveFunction + +Func_f8ee9: + lb bc, $54, $5c + ld de, Unkn_f979d + jp SurfingMinigameWaveFunction_GoToNextWaveFunction + +Func_f8ef2: + lb bc, $64, $6c + ld de, Unkn_f97a5 + jp SurfingMinigameWaveFunction_GoToNextWaveFunction + +Func_f8efb: + lb bc, $74, $6c + ld de, Unkn_f97ad + jp SurfingMinigameWaveFunction_GoToNextWaveFunction + +Func_f8f04: + lb bc, $64, $5c + ld de, Unkn_f97b5 + jp SurfingMinigameWaveFunction_GoToNextWaveFunction + +Func_f8f0d: + lb bc, $54, $54 + ld de, Unkn_f97bd + jp SurfingMinigameWaveFunction_GoToNextWaveFunction + +Func_f8f16: + lb bc, $54, $5c + ld de, Unkn_f97c5 + jp SurfingMinigameWaveFunction_GoToNextWaveFunction + +Func_f8f1f: + lb bc, $64, $6c + ld de, Unkn_f97cd + jp SurfingMinigameWaveFunction_GoToNextWaveFunction + +Func_f8f28: + lb bc, $74, $6c + ld de, Unkn_f97d5 + jp SurfingMinigameWaveFunction_GoToNextWaveFunction + +Func_f8f31: + lb bc, $64, $5c + ld de, Unkn_f97dd + jp SurfingMinigameWaveFunction_GoToNextWaveFunction + +Func_f8f3a: + lb bc, $5c, $5c + ld de, Unkn_f97e5 + jp SurfingMinigameWaveFunction_GoToNextWaveFunction + +Func_f8f43: + lb bc, $64, $6c + ld de, Unkn_f97ed + jp SurfingMinigameWaveFunction_GoToNextWaveFunction + +Func_f8f4c: + lb bc, $74, $6c + ld de, Unkn_f97f5 + jp SurfingMinigameWaveFunction_GoToNextWaveFunction + +Func_f8f55: + lb bc, $64, $64 + ld de, Unkn_f97fd + jp SurfingMinigameWaveFunction_GoToNextWaveFunction + +Func_f8f5e: + lb bc, $64, $6c + ld de, Unkn_f9805 + jp SurfingMinigameWaveFunction_GoToNextWaveFunction + +Func_f8f67: + lb bc, $74, $6c + ld de, Unkn_f980d + jp SurfingMinigameWaveFunction_GoToNextWaveFunction + +Func_f8f70: + lb bc, $6c, $6c + ld de, Unkn_f9815 + jp SurfingMinigameWaveFunction_GoToNextWaveFunction + +Func_f8f79: + lb bc, $74, $74 + ld de, Unkn_f981d + jp SurfingMinigameWaveFunction_GoToNextWaveFunction + +Func_f8f82: + lb bc, $74, $74 + ld de, Unkn_f9825 + jp SurfingMinigameWaveFunction_GoToNextWaveFunction + +Func_f8f8b: + lb bc, $74, $74 + ld de, Unkn_f9825 + jp SurfingMinigameWaveFunction_ResetWaveFunction + +Func_f8f94: + lb bc, $74, $74 + ld de, Unkn_f973d + jp SurfingMinigameWaveFunction_ResetWaveFunction + +Func_f8f9d: + lb bc, $74, $74 + ld de, Unkn_f973d + ret + +Func_f8fa4: ; unused + inc a + ld [wSurfingMinigameWaveFunctionNumber], a + ret + +SurfingMinigameWaveFunction_GoToNextWaveFunction: + ld hl, wSurfingMinigameWaveFunctionNumber + inc [hl] + ret + +SurfingMinigameWaveFunction_ResetWaveFunction: + xor a + ld [wSurfingMinigameWaveFunctionNumber], a + ret + +SurfingPikachuMinigameIntro: + call SurfingPikachu_ClearTileMap + call ClearSprites + call DisableLCD + xor a + ld [H_AUTOBGTRANSFERENABLED], a + call ClearObjectAnimationBuffers + ld hl, SurfingPikachu1Graphics3 + ld de, $8800 + ld bc, $900 + ld a, BANK(SurfingPikachu1Graphics3) + call FarCopyData + ld a, SurfingPikachuSpawnStateDataPointer % $100 + ld [wAnimatedObjectSpawnStateDataPointer], a + ld a, SurfingPikachuSpawnStateDataPointer / $100 + ld [wAnimatedObjectSpawnStateDataPointer + 1], a + ld a, SurfingPikachuObjectJumptable % $100 + ld [wAnimatedObjectJumptablePointer], a + ld a, SurfingPikachuObjectJumptable / $100 + ld [wAnimatedObjectJumptablePointer + 1], a + ld a, SurfingPikachuOAMData % $100 + ld [wAnimatedObjectOAMDataPointer], a + ld a, SurfingPikachuOAMData / $100 + ld [wAnimatedObjectOAMDataPointer + 1], a + ld a, SurfingPikachuFrames % $100 + ld [wAnimatedObjectFramesDataPointer], a + ld a, SurfingPikachuFrames / $100 + ld [wAnimatedObjectFramesDataPointer + 1], a + ld a, $c + lb de, $74, $58 + call SpawnAnimatedObject + call DrawSurfingPikachuMinigameIntroBackground + xor a + ld [hSCX], a + ld [hSCY], a + ld a, $90 + ld [hWY], a + ld b, $f + call RunPaletteCommand + ld a, $e3 + ld [rLCDC], a + ld a, $1 + ld [H_AUTOBGTRANSFERENABLED], a + call DelayFrame + call DelayFrame + call DelayFrame + call SurfingPikachuMinigame_SetBGPals + ld a, $e4 + ld [rOBP0], a + ld a, $e0 + ld [rOBP1], a + call UpdateGBCPal_OBP0 + call UpdateGBCPal_OBP1 + call DelayFrame + ld a, MUSIC_SURFING_PIKACHU + ld c, BANK(Music_SurfingPikachu) + call PlayMusic + xor a + ld [wSurfingMinigameIntroAnimationFinished], a +.loop + ld a, [wSurfingMinigameIntroAnimationFinished] + and a + ret nz + ld a, $0 + ld [wCurrentAnimatedObjectOAMBufferOffset], a + call RunObjectAnimations + call DelayFrame + jr .loop + +DrawSurfingPikachuMinigameIntroBackground: + ld hl, wTileMap + ld bc, SCREEN_WIDTH * SCREEN_HEIGHT + ld a, $ff + call FillMemory + ld hl, Tilemap_f90bc + coord de, 0, 6 + ld bc, 12 * SCREEN_WIDTH + call CopyData + ld de, Tilemap_f91c8 + coord hl, 4, 0 + lb bc, 6, 12 + call .CopyBox + coord hl, 3, 7 + lb bc, 3, 15 + call .FillBoxWithFF + ld hl, Tilemap_f91ac + coord de, 3, 7 + ld bc, 15 + call CopyData + ld hl, Tilemap_f91bb + coord de, 4, 9 + ld bc, 13 + call CopyData + ret + +.CopyBox: +.copy_row + push bc + push hl +.copy_col + ld a, [de] + inc de + ld [hli], a + dec c + jr nz, .copy_col + ld bc, SCREEN_WIDTH + pop hl + add hl, bc + pop bc + dec b + jr nz, .copy_row + ret + +.FillBoxWithFF: +.fill_row + push bc + push hl +.fill_col + ld [hl], $ff + inc hl + dec c + jr nz, .fill_col + pop hl + ld bc, SCREEN_WIDTH + add hl, bc + pop bc + dec b + jr nz, .fill_row + ret + +Tilemap_f90bc: INCBIN "gfx/unknown_f90bc.map" +Tilemap_f91ac: INCBIN "gfx/unknown_f91ac.map" +Tilemap_f91bb: INCBIN "gfx/unknown_f91bb.map" +Tilemap_f91c8: INCBIN "gfx/unknown_f91c8.map" + +SurfingMinigame_UpdateLYOverrides: + ld hl, wLYOverrides + $10 + ld de, wLYOverrides + $11 + ld c, $80 + ld a, [hl] + push af +.loop + ld a, [de] + inc de + ld [hli], a + dec c + jr nz, .loop + pop af + ld [hl], a + ret + +SurfingMinigame_InitScanlineOverrides: + ld hl, wLYOverrides + ld bc, wLYOverridesEnd - wLYOverrides + ld de, $0 +.loop + ld a, e + and $1f + ld e, a + push hl + ld hl, SurfingMinigame_LYOverridesInitialSineWave + add hl, de + ld a, [hl] + pop hl + ld [hli], a + inc e + dec bc + ld a, c + or b + jr nz, .loop + ret + +SurfingPikachu_GetJoypad_3FrameBuffer: + call Joypad + ld a, [H_FRAMECOUNTER] + and a + jr nz, .delayed + ld a, [hJoyHeld] + ld [hJoy5], a + ld a, $2 + ld [H_FRAMECOUNTER], a + ret + +.delayed + xor a + ld [hJoy5], a + ret + +SurfingPikachuMinigame_BlankPals: + xor a + ld [rBGP], a + ld [rOBP0], a + ld [rOBP1], a + call UpdateGBCPal_BGP + call UpdateGBCPal_OBP0 + call UpdateGBCPal_OBP1 + ret + +SurfingPikachuMinigame_NormalPals: + ld a, $e4 + ld [rBGP], a + ld [rOBP0], a + ld a, $e0 + ld [rOBP1], a + call UpdateGBCPal_BGP + call UpdateGBCPal_OBP0 + call UpdateGBCPal_OBP1 + ret + +SurfingPikachu_ClearTileMap: + ld hl, wTileMap + ld bc, SCREEN_WIDTH * SCREEN_HEIGHT + xor a + call FillMemory + ret + +Func_f9284: + xor a + ld [wc5ed], a + ld [wc5ee], a + ret + +SurfingMinigame_UpdatePikachuHeight: + ld a, [wc5ed] + and a + jr nz, .positive + ld a, [wc5ec] + ld d, a + ld a, [wc5ee] + or d + jr z, .done + ld a, [wc5ee] + ld e, a + ld hl, -$80 + add hl, de + ld a, l + ld [wc5ee], a + ld a, h + ld [wc5ec], a + + ; -(4 * a ** 2) + ld e, a + ld d, $0 + call SurfingMinigame_NTimesDE + ld e, l + ld d, h + ld a, $4 + call SurfingMinigame_NTimesDE + ld a, l + xor $ff + inc a + ld l, a + ld a, h + xor $ff + ld h, a + + push hl + ld hl, ANIM_OBJ_Y_COORD + add hl, bc + ld d, [hl] + ld hl, ANIM_OBJ_FIELD_C + add hl, bc + ld e, [hl] + pop hl + + add hl, de + ld e, l + ld d, h + + ld hl, ANIM_OBJ_Y_COORD + add hl, bc + ld [hl], d + ld hl, ANIM_OBJ_FIELD_C + add hl, bc + ld [hl], e + and a + ret + +.done + ld a, $1 + ld [wc5ed], a + and a + ret + +.positive + ld a, [wSurfingMinigamePikachuObjectHeight] + ld e, a + ld hl, ANIM_OBJ_Y_COORD + add hl, bc + ld a, [hl] + cp $90 + jr nc, .okay + cp e + jr nc, .reset +.okay + ld a, [wc5ec] + ld d, a + ld a, [wc5ee] + ld e, a + ld hl, $80 + add hl, de + ld a, l + ld [wc5ee], a + ld a, h + ld [wc5ec], a + + ; 4 * a ** 2 + ld e, a + ld d, $0 + call SurfingMinigame_NTimesDE + ld e, l + ld d, h + ld a, $4 + call SurfingMinigame_NTimesDE + + push hl + ld hl, ANIM_OBJ_Y_COORD + add hl, bc + ld d, [hl] + ld hl, ANIM_OBJ_FIELD_C + add hl, bc + ld e, [hl] + pop hl + + add hl, de + ld e, l + ld d, h + + ld hl, ANIM_OBJ_Y_COORD + add hl, bc + ld [hl], d + ld hl, ANIM_OBJ_FIELD_C + add hl, bc + ld [hl], e + and a + ret + +.reset + ld hl, ANIM_OBJ_Y_COORD + add hl, bc + ld a, [wSurfingMinigamePikachuObjectHeight] + ld [hl], a + ld hl, ANIM_OBJ_FIELD_C + add hl, bc + ld [hl], $0 + scf + ret + +SurfingMinigame_NTimesDE: + ld hl, $0 +.loop + srl a + jr nc, .no_add + add hl, de +.no_add + sla e + rl d + and a + jr nz, .loop + ret + +SurfingPikachu_PlaceBCDNumber: + ld c, a + swap a + and $f + add $d0 + ld [hli], a + ld a, c + and $f + add $d0 + ld [hl], a + dec de + ret + +SurfingPikachu_Cosine: ; cosine + add $10 +SurfingPikachu_Sine: ; sine + and $3f + cp $20 + jr nc, .positive + call .GetSine + ld a, h + ret + +.positive + and $1f + call .GetSine + ld a, h + xor $ff + inc a + ret + +.GetSine: + ld e, a + ld a, d + ld d, $0 + ld hl, .SineWave + add hl, de + add hl, de + ld e, [hl] + inc hl + ld d, [hl] + ld hl, $0 +.loop + srl a + jr nc, .no_add + add hl, de +.no_add + sla e + rl d + and a + jr nz, .loop + ret + +.SineWave: + sine_wave $100 + +SurfingPikachuSpawnStateDataPointer: + db $00, $00, $00 ; 0 + db $04, $01, $00 ; 1 + db $11, $02, $00 ; 2 + db $12, $02, $00 ; 3 + db $15, $00, $00 ; 4 + db $16, $00, $00 ; 5 + db $17, $00, $00 ; 6 + db $18, $00, $00 ; 7 + db $19, $00, $00 ; 8 + db $1a, $00, $00 ; 9 + db $14, $00, $00 ; a + db $13, $03, $00 ; b + db $1b, $04, $00 ; c + +SurfingPikachuObjectJumptable: + dw SurfingMinigameAnimatedObjectFn_nop ; 0 + dw SurfingMinigameAnimatedObjectFn_Pikachu ; 1 + dw Func_f87fb ; 2 + dw SurfingMinigameAnimatedObjectFn_FlippingPika ; 3 + dw SurfingMinigameAnimatedObjectFn_IntroAnimationPikachu ; 4 + +SurfingMinigameAnimatedObjectFn_nop: + ret + +INCLUDE "data/animated_objects_3e_1.asm" + +SurfingMinigame_LYOverridesInitialSineWave: +; a sine wave with amplitude 2 + db 0, 0, 0, 1, 1, 1, 1, 2 + db 2, 2, 1, 1, 1, 1, 0, 0 + db 0, 0, 0, -1, -1, -1, -1, -2 + db -2, -2, -1, -1, -1, -1, 0, 0 + +Unkn_f96e5: + db $00, $00, $00, $00 ; 00 + db $0b, $0b, $0b, $0b ; 01 + db $0b, $02, $02, $06 ; 02 + db $03, $0b, $07, $03 ; 03 + db $06, $06, $06, $06 ; 04 + db $07, $07, $07, $07 ; 05 + db $06, $04, $04, $08 ; 06 + db $05, $07, $08, $05 ; 07 + db $0b, $0b, $11, $12 ; 08 + db $0b, $0b, $13, $03 ; 09 + db $14, $12, $04, $08 ; 0a + db $13, $07, $08, $05 ; 0b + db $06, $14, $06, $14 ; 0c + db $13, $07, $13, $07 ; 0d + db $08, $08, $08, $08 ; 0e + db $14, $12, $14, $12 ; 0f + db $0b, $11, $02, $14 ; 10 + db $06, $14, $06, $14 ; 11 + db $0c, $0c, $0d, $0d ; 12 + db $0d, $0d, $0d, $0d ; 13 + db $0e, $0f, $10, $0b ; 14 + db $12, $13, $12, $13 ; 15 + +Unkn_f973d: + db $00, $00, $00, $01, $01, $01, $01, $01 +Unkn_f9745: + db $00, $00, $00, $01, $01, $02, $04, $06 +Unkn_f974d: + db $00, $00, $00, $01, $02, $04, $06, $0e +Unkn_f9755: + db $00, $00, $00, $10, $11, $06, $0e, $0e +Unkn_f975d: + db $00, $00, $00, $15, $15, $0e, $0e, $0e +Unkn_f9765: + db $00, $00, $00, $03, $05, $07, $0e, $0e +Unkn_f976d: + db $00, $00, $00, $01, $03, $05, $07, $0e +Unkn_f9775: + db $00, $00, $00, $01, $01, $03, $05, $07 +Unkn_f977d: + db $00, $00, $00, $01, $01, $02, $04, $06 +Unkn_f9785: + db $00, $00, $00, $01, $02, $04, $06, $0e +Unkn_f978d: + db $00, $00, $00, $08, $0f, $0a, $0e, $0e +Unkn_f9795: + db $00, $00, $00, $09, $0d, $0b, $0e, $0e +Unkn_f979d: + db $00, $00, $00, $01, $03, $05, $07, $0e +Unkn_f97a5: + db $00, $00, $00, $01, $01, $03, $05, $07 +Unkn_f97ad: + db $00, $00, $00, $01, $01, $02, $04, $06 +Unkn_f97b5: + db $00, $00, $00, $01, $10, $11, $06, $0e +Unkn_f97bd: + db $00, $00, $00, $01, $15, $15, $0e, $0e +Unkn_f97c5: + db $00, $00, $00, $01, $03, $05, $07, $0e +Unkn_f97cd: + db $00, $00, $00, $01, $01, $03, $05, $07 +Unkn_f97d5: + db $00, $00, $00, $01, $01, $02, $04, $06 +Unkn_f97dd: + db $00, $00, $00, $01, $08, $0f, $0a, $0e +Unkn_f97e5: + db $00, $00, $00, $01, $09, $0d, $0b, $0e +Unkn_f97ed: + db $00, $00, $00, $01, $01, $03, $05, $07 +Unkn_f97f5: + db $00, $00, $00, $01, $01, $10, $11, $06 +Unkn_f97fd: + db $00, $00, $00, $01, $01, $15, $15, $0e +Unkn_f9805: + db $00, $00, $00, $01, $01, $03, $05, $07 +Unkn_f980d: + db $00, $00, $00, $01, $01, $08, $0f, $0a +Unkn_f9815: + db $00, $00, $00, $01, $01, $09, $0d, $0b +Unkn_f981d: + db $00, $00, $00, $14, $14, $14, $14, $14 +Unkn_f9825: + db $00, $00, $00, $12, $13, $13, $13, $13 diff --git a/engine/titlescreen.asm b/engine/titlescreen.asm index 03a5832d..d4dd0fd3 100755 --- a/engine/titlescreen.asm +++ b/engine/titlescreen.asm @@ -1,8 +1,3 @@ -; copy text of fixed length NAME_LENGTH (like player name, rival name, mon names, ...) -CopyFixedLengthText: - ld bc, NAME_LENGTH - jp CopyData - SetDefaultNamesBeforeTitlescreen: ld hl, NintenText ld de, wPlayerName @@ -35,98 +30,35 @@ DisplayTitleScreen: call ClearScreen call DisableLCD call LoadFontTilePatterns +; todo: fix hl pointers ld hl, NintendoCopyrightLogoGraphics - ld de, vTitleLogo2 + $100 + ld de, vTitleLogo + $600 ld bc, $50 ld a, BANK(NintendoCopyrightLogoGraphics) - call FarCopyData2 + call FarCopyData + ld hl, NineTile + ld de, vTitleLogo + $6e0 + ld bc, $10 + ld a, BANK(NineTile) + call FarCopyData ld hl, GamefreakLogoGraphics - ld de, vTitleLogo2 + $100 + $50 - ld bc, $90 + ld de, vTitleLogo + 101 * $10 + ld bc, 9 * $10 ld a, BANK(GamefreakLogoGraphics) - call FarCopyData2 - ld hl, PokemonLogoGraphics - ld de, vTitleLogo - ld bc, $600 - ld a, BANK(PokemonLogoGraphics) - call FarCopyData2 ; first chunk - ld hl, PokemonLogoGraphics+$600 - ld de, vTitleLogo2 - ld bc, $100 - ld a, BANK(PokemonLogoGraphics) - call FarCopyData2 ; second chunk - ld hl, Version_GFX - ld de, vChars2 + $600 - (Version_GFXEnd - Version_GFX - $50) - ld bc, Version_GFXEnd - Version_GFX - ld a, BANK(Version_GFX) - call FarCopyDataDouble - call ClearBothBGMaps - -; place tiles for pokemon logo (except for the last row) - coord hl, 2, 1 - ld a, $80 - ld de, SCREEN_WIDTH - ld c, 6 -.pokemonLogoTileLoop - ld b, $10 - push hl -.pokemonLogoTileRowLoop ; place tiles for one row - ld [hli], a - inc a - dec b - jr nz, .pokemonLogoTileRowLoop - pop hl - add hl, de - dec c - jr nz, .pokemonLogoTileLoop - -; place tiles for the last row of the pokemon logo - coord hl, 2, 7 - ld a, $31 - ld b, $10 -.pokemonLogoLastTileRowLoop - ld [hli], a - inc a - dec b - jr nz, .pokemonLogoLastTileRowLoop - - call DrawPlayerCharacter - -; put a pokeball in the player's hand - ld hl, wOAMBuffer + $28 - ld a, $74 - ld [hl], a - -; place tiles for title screen copyright - coord hl, 2, 17 - ld de, .tileScreenCopyrightTiles - ld b, $10 -.tileScreenCopyrightTilesLoop - ld a, [de] - ld [hli], a - inc de - dec b - jr nz, .tileScreenCopyrightTilesLoop - - jr .next - -.tileScreenCopyrightTiles - db $41,$42,$43,$42,$44,$42,$45,$46,$47,$48,$49,$4A,$4B,$4C,$4D,$4E ; ©'95.'96.'98 GAME FREAK inc. - -.next + call FarCopyData + callab LoadYellowTitleScreenGFX + ld hl, vBGMap0 + ld bc, (vBGMap1 + $400) - vBGMap0 + ld a, " " + call FillMemory + callab TitleScreen_PlacePokemonLogo + call FillSpriteBuffer0WithAA + call .WriteCopyrightTiles call SaveScreenTilesToBuffer2 call LoadScreenTilesFromBuffer2 call EnableLCD -IF DEF(_RED) - ld a, CHARMANDER ; which Pokemon to show first on the title screen -ENDC -IF DEF(_BLUE) - ld a, SQUIRTLE ; which Pokemon to show first on the title screen -ENDC - - ld [wTitleMonSpecies], a - call LoadTitleMonSprite - ld a, (vBGMap0 + $300) / $100 + callab TitleScreen_PlacePikachu + ld a, $9b call TitleScreenCopyTileMapToVRAM call SaveScreenTilesToBuffer1 ld a, $40 @@ -137,8 +69,9 @@ ENDC ld b, SET_PAL_TITLE_SCREEN call RunPaletteCommand call GBPalNormal - ld a, %11100100 + ld a, %11100000 ld [rOBP0], a + call UpdateGBCPal_OBP0 ; make pokemon logo bounce up and down ld bc, hSCY ; background scroll Y @@ -180,6 +113,21 @@ ENDC jr nz, .ScrollTitleScreenPokemonLogo ret +; place tiles for title screen copyright +.WriteCopyrightTiles + coord hl, 2, 17 + ld de, .tileScreenCopyrightTiles +.titleScreenCopyrightTilesLoop + ld a, [de] + inc de + cp $ff + ret z + ld [hli], a + jr .titleScreenCopyrightTilesLoop + +.tileScreenCopyrightTiles + db $e0,$e1,$e2,$e3,$e1,$e2,$ee,$e5,$e6,$e7,$e8,$e9,$ea,$eb,$ec,$ed,$ff ; ©1995-1999 GAME FREAK inc. + .finishedBouncingPokemonLogo call LoadScreenTilesFromBuffer1 ld c, 36 @@ -188,52 +136,42 @@ ENDC call PlaySound ; scroll game version in from the right - call PrintGameVersionOnTitleScreen + callab TitleScreen_PlacePikaSpeechBubble ld a, SCREEN_HEIGHT_PIXELS ld [hWY], a - ld d, 144 -.scrollTitleScreenGameVersionLoop - ld h, d - ld l, 64 - call ScrollTitleScreenGameVersion - ld h, 0 - ld l, 80 - call ScrollTitleScreenGameVersion - ld a, d - add 4 - ld d, a - and a - jr nz, .scrollTitleScreenGameVersionLoop - - ld a, vBGMap1 / $100 - call TitleScreenCopyTileMapToVRAM - call LoadScreenTilesFromBuffer2 - call PrintGameVersionOnTitleScreen call Delay3 + ld e, 0 + call TitleScreen_PlayPikachuPCM call WaitForSoundToFinish + call StopAllMusic ld a, MUSIC_TITLE_SCREEN ld [wNewSoundID], a call PlaySound +.loop xor a ld [wUnusedCC5B], a - -; Keep scrolling in new mons indefinitely until the user performs input. -.awaitUserInterruptionLoop - ld c, 200 - call CheckForUserInterruption - jr c, .finishedWaiting - call TitleScreenScrollInMon - ld c, 1 - call CheckForUserInterruption - jr c, .finishedWaiting - callba TitleScreenAnimateBallIfStarterOut - call TitleScreenPickNewMon - jr .awaitUserInterruptionLoop - -.finishedWaiting - ld a, [wTitleMonSpecies] - call PlayCry - call WaitForSoundToFinish + ld [wTitleScreenScene], a + ld [wTitleScreenScene + 1], a + ld [wTitleScreenScene + 2], a + ld [wTitleScreenScene + 3], a + ld a, $f + ld [wTitleScreenScene + 4], a +.titleScreenLoop + call IncrementResetCounter + jp c, .doTitlescreenReset + call DelayFrame + call JoypadLowSensitivity + ld a, [hJoyHeld] + cp D_UP | SELECT | B_BUTTON + jr z, .go_to_main_menu + and A_BUTTON | START + jr nz, .go_to_main_menu + call DoTitleScreenFunction + jr .titleScreenLoop + +.go_to_main_menu + ld e, $a + call TitleScreen_PlayPikachuPCM call GBPalWhiteOutWithDelay3 call ClearSprites xor a @@ -254,108 +192,39 @@ ENDC jp z, .doClearSaveDialogue jp MainMenu -.doClearSaveDialogue - jpba DoClearSaveDialogue - -TitleScreenPickNewMon: - ld a, vBGMap0 / $100 - call TitleScreenCopyTileMapToVRAM - -.loop -; Keep looping until a mon different from the current one is picked. - call Random - and $f - ld c, a - ld b, 0 - ld hl, TitleMons - add hl, bc - ld a, [hl] - ld hl, wTitleMonSpecies - -; Can't be the same as before. - cp [hl] - jr z, .loop - - ld [hl], a - call LoadTitleMonSprite - - ld a, $90 - ld [hWY], a - ld d, 1 ; scroll out - callba TitleScroll - ret - -TitleScreenScrollInMon: - ld d, 0 ; scroll in - callba TitleScroll - xor a - ld [hWY], a - ret - -ScrollTitleScreenGameVersion: -.wait - ld a, [rLY] - cp l - jr nz, .wait - - ld a, h - ld [rSCX], a +.asm_42f0 +; unreferenced + callab PrinterDebug + jp .loop -.wait2 - ld a, [rLY] - cp h - jr z, .wait2 - ret - -DrawPlayerCharacter: - ld hl, PlayerCharacterTitleGraphics - ld de, vSprites - ld bc, PlayerCharacterTitleGraphicsEnd - PlayerCharacterTitleGraphics - ld a, BANK(PlayerCharacterTitleGraphics) - call FarCopyData2 - call ClearSprites - xor a - ld [wPlayerCharacterOAMTile], a - ld hl, wOAMBuffer - ld de, $605a - ld b, 7 -.loop - push de - ld c, 5 -.innerLoop - ld a, d - ld [hli], a ; Y - ld a, e - ld [hli], a ; X - add 8 - ld e, a - ld a, [wPlayerCharacterOAMTile] - ld [hli], a ; tile +.asm_42fb +; unreferenced + ld a, [wTitleScreenScene + 4] inc a - ld [wPlayerCharacterOAMTile], a - inc hl - dec c - jr nz, .innerLoop - pop de - ld a, 8 - add d - ld d, a - dec b - jr nz, .loop - ret + cp $2a + jr c, .asm_4305 + ld a, $f +.asm_4305 + ld [wTitleScreenScene + 4], a + ld e, a + callab PlayPikachuSoundClip + xor a + ld [wTitleScreenScene + 2], a + ld [wTitleScreenScene + 3], a + jp .titleScreenLoop + +.doTitlescreenReset + ld [wAudioFadeOutControl], a + call StopAllMusic +.audioFadeLoop + ld a, [wAudioFadeOutControl] + and a + jr nz, .audioFadeLoop + jp Init -ClearBothBGMaps: - ld hl, vBGMap0 - ld bc, $400 * 2 - ld a, " " - jp FillMemory +.doClearSaveDialogue + jpba DoClearSaveDialogue -LoadTitleMonSprite: - ld [wcf91], a - ld [wd0b5], a - coord hl, 5, 10 - call GetMonHeader - jp LoadFrontSpriteByMonIndex TitleScreenCopyTileMapToVRAM: ld [H_AUTOBGTRANSFERDEST + 1], a @@ -370,34 +239,132 @@ LoadCopyrightAndTextBoxTiles: LoadCopyrightTiles: ld de, NintendoCopyrightLogoGraphics ld hl, vChars2 + $600 - lb bc, BANK(NintendoCopyrightLogoGraphics), (GamefreakLogoGraphicsEnd - NintendoCopyrightLogoGraphics) / $10 + lb bc, BANK(NintendoCopyrightLogoGraphics), (TextBoxGraphics + $10 - NintendoCopyrightLogoGraphics) / $10 ; bug: overflows into text box graphics and copies the "A" tile call CopyVideoData coord hl, 2, 7 ld de, CopyrightTextString jp PlaceString CopyrightTextString: - db $60,$61,$62,$61,$63,$61,$64,$7F,$65,$66,$67,$68,$69,$6A ; ©'95.'96.'98 Nintendo - next $60,$61,$62,$61,$63,$61,$64,$7F,$6B,$6C,$6D,$6E,$6F,$70,$71,$72 ; ©'95.'96.'98 Creatures inc. - next $60,$61,$62,$61,$63,$61,$64,$7F,$73,$74,$75,$76,$77,$78,$79,$7A,$7B ; ©'95.'96.'98 GAME FREAK inc. + db $60,$61,$62,$63,$61,$62,$7c,$7f,$65,$66,$67,$68,$69,$6a ; ©1995-1999 Nintendo + next $60,$61,$62,$63,$61,$62,$7c,$7f,$6b,$6c,$6d,$6e,$6f,$70,$71,$72 ; ©1995-1999 Creatures inc. + next $60,$61,$62,$63,$61,$62,$7c,$7f,$73,$74,$75,$76,$77,$78,$79,$7a,$7b ; ©1995-1999 GAME FREAK inc. db "@" -INCLUDE "data/title_mons.asm" - -; prints version text (red, blue) -PrintGameVersionOnTitleScreen: - coord hl, 7, 8 - ld de, VersionOnTitleScreenText - jp PlaceString +TitleScreen_PlayPikachuPCM: + callab PlayPikachuSoundClip + ret + +DoTitleScreenFunction: + call .CheckTimer + ld a, [wTitleScreenScene] + ld e, a + ld d, 0 + ld hl, .Jumptable + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + jp hl + + +.Jumptable: + dw .Nop + dw .BlinkHalf + dw .BlinkWait + dw .BlinkWait + dw .BlinkClosed + dw .BlinkWait + dw .BlinkWait + dw .BlinkHalf + dw .BlinkWait + dw .BlinkWait + dw .BlinkOpen + dw .GoBackToStart + +.GoBackToStart: + xor a + ld [wTitleScreenScene], a +.Nop + ret + +.BlinkOpen: + ld e, 0 + jr .LoadBlinkFrame + +.BlinkHalf: + ld e, 4 + jr .LoadBlinkFrame + +.BlinkClosed: + ld e, 8 +.LoadBlinkFrame: + ld hl, wOAMBuffer + 2 + ld c, 8 +.loop + ld a, [hl] + and $f3 + or e + ld [hli], a + inc hl + inc hl + inc hl + dec c + jr nz, .loop +.BlinkWait: + ld hl, wTitleScreenScene + inc [hl] + ret + +.CheckTimer: + ld hl, wTitleScreenTimer + ld a, [hl] + inc [hl] + and a + jr z, .restart + cp $80 + jr z, .restart + cp $90 + ret nz +.restart + ld a, $1 + ld [wTitleScreenScene], a + ret -; these point to special tiles specifically loaded for that purpose and are not usual text -VersionOnTitleScreenText: -IF DEF(_RED) - db $60,$61,$7F,$65,$66,$67,$68,$69,"@" ; "Red Version" -ENDC -IF DEF(_BLUE) - db $61,$62,$63,$64,$65,$66,$67,$68,"@" ; "Blue Version" -ENDC +; copy text of fixed length NAME_LENGTH (like player name, rival name, mon names, ...) +CopyFixedLengthText: + ld bc, NAME_LENGTH + jp CopyData NintenText: db "NINTEN@" SonyText: db "SONY@" + +IncrementResetCounter: + ld hl, wTitleScreenScene + 2 + ld e, [hl] + inc hl + ld d, [hl] + inc de + ld a, d + cp $c + jr z, .doReset + ld [hl], d + dec hl + ld [hl], e + and a + ret + +.doReset + scf + ret + +FillSpriteBuffer0WithAA: + xor a + call SwitchSRAMBankAndLatchClockData + ld hl, sSpriteBuffer0 + ld bc, $20 + ld a, $aa + call FillMemory + call PrepareRTCDataAndDisableSRAM + ret diff --git a/engine/titlescreen2.asm b/engine/titlescreen2.asm index 2346fcc5..8b4bc4de 100755 --- a/engine/titlescreen2.asm +++ b/engine/titlescreen2.asm @@ -1,3 +1,5 @@ +; Leftover of Red/Blue. Seemingly unused + TitleScroll_WaitBall: ; Wait around for the TitleBall animation to play out. ; hi: speed @@ -89,7 +91,7 @@ TitleBallYTable: TitleScreenAnimateBallIfStarterOut: ; Animate the TitleBall if a starter just got scrolled out. - ld a, [wTitleMonSpecies] + ld a, [wTitleScreenScene] cp STARTER1 jr z, .ok cp STARTER2 diff --git a/engine/town_map.asm b/engine/town_map.asm index d417e0a3..7d32b5fe 100755 --- a/engine/town_map.asm +++ b/engine/town_map.asm @@ -103,6 +103,13 @@ DisplayTownMap: ld [wWhichTownMapLocation], a jp .townMapLoop +.asm_70f87 + ld a,[hJoy5] + and D_DOWN | D_UP + ret z + callab PlayPikachuSoundClip + ret + INCLUDE "data/town_map_order.asm" TownMapCursor: @@ -137,11 +144,14 @@ MonsNestText: LoadTownMap_Fly: call ClearSprites call LoadTownMap + ld a, $1 + ld [hJoy7], a call LoadPlayerSpriteGraphics call LoadFontTilePatterns ld de, BirdSprite + ld b, BANK(BirdSprite) + ld c, $c ld hl, vSprites + $40 - lb bc, BANK(BirdSprite), $c call CopyVideoData ld de, TownMapUpArrow ld hl, vChars1 + $6d0 @@ -179,7 +189,7 @@ LoadTownMap_Fly: ld c, 15 call DelayFrames coord hl, 18, 0 - ld [hl], "▲" + ld [hl], "▶" coord hl, 19, 0 ld [hl], "▼" pop hl @@ -213,6 +223,7 @@ LoadTownMap_Fly: .pressedB xor a ld [wTownMapSpriteBlinkingEnabled], a + ld [hJoy7], a call GBPalWhiteOutWithDelay3 pop hl pop af @@ -279,15 +290,14 @@ LoadTownMap: call ClearScreen call UpdateSprites coord hl, 0, 0 - ld b, $12 - ld c, $12 + lb bc, $12, $12 call TextBoxBorder call DisableLCD ld hl, WorldMapTileGraphics ld de, vChars2 + $600 ld bc, WorldMapTileGraphicsEnd - WorldMapTileGraphics ld a, BANK(WorldMapTileGraphics) - call FarCopyData2 + call FarCopyData ld hl, MonNestIcon ld de, vSprites + $40 ld bc, MonNestIconEnd - MonNestIcon @@ -397,8 +407,7 @@ DisplayWildLocations: jr nz, .drawPlayerSprite ; if no OAM entries were written, print area unknown text coord hl, 1, 7 - ld b, 2 - ld c, 15 + lb bc, 2, 15 call TextBoxBorder coord hl, 2, 9 ld de, AreaUnknownText diff --git a/engine/trade.asm b/engine/trade.asm index 8bc8e3bc..e4bc0768 100755 --- a/engine/trade.asm +++ b/engine/trade.asm @@ -20,12 +20,13 @@ ExternalClockTradeAnim: TradeAnimCommon: ld a, [wOptions] push af + and %110000 ; preserve speaker options + ld [wOptions], a ld a, [hSCY] push af ld a, [hSCX] push af xor a - ld [wOptions], a ld [hSCY], a ld [hSCX], a push de @@ -160,12 +161,12 @@ LoadTradingGFXAndMonNames: ld de, vChars2 + $310 ld bc, TradingAnimationGraphicsEnd - TradingAnimationGraphics ld a, BANK(TradingAnimationGraphics) - call FarCopyData2 + call FarCopyData ld hl, TradingAnimationGraphics2 ld de, vSprites + $7c0 ld bc, TradingAnimationGraphics2End - TradingAnimationGraphics2 ld a, BANK(TradingAnimationGraphics2) - call FarCopyData2 + call FarCopyData ld hl, vBGMap0 ld bc, $800 ld a, " " @@ -182,6 +183,7 @@ LoadTradingGFXAndMonNames: ld a, $f0 ; SGB OBP0 .next ld [rOBP0], a + call UpdateGBCPal_OBP0 call EnableLCD xor a ld [H_AUTOBGTRANSFERENABLED], a @@ -199,6 +201,7 @@ LoadTradingGFXAndMonNames: Trade_LoadMonPartySpriteGfx: ld a, %11010000 ld [rOBP1], a + call UpdateGBCPal_OBP1 jpba LoadMonPartySpriteGfx Trade_SwapNames: @@ -233,8 +236,7 @@ Trade_ShowPlayerMon: xor a ld [H_AUTOBGTRANSFERENABLED], a coord hl, 4, 0 - ld b, 6 - ld c, 10 + lb bc, 6, 10 call TextBoxBorder call Trade_PrintPlayerMonInfoText ld b, vBGMap0 / $100 @@ -303,6 +305,7 @@ Trade_AnimateBallEnteringLinkCable: call DelayFrames ld a, %11100100 ld [rOBP0], a + call UpdateGBCPal_OBP0 xor a ld [wLinkCableAnimBulgeToggle], a lb bc, $20, $60 @@ -354,8 +357,7 @@ Trade_ShowEnemyMon: call Trade_ShowAnimation call Trade_ShowClearedWindow coord hl, 4, 10 - ld b, 6 - ld c, 10 + lb bc, 6, 10 call TextBoxBorder call Trade_PrintEnemyMonInfoText call Trade_CopyTileMapToVRAM @@ -382,6 +384,7 @@ Trade_AnimLeftToRight: ld [wTradedMonMovingRight], a ld a, %11100100 ld [rOBP0], a + call UpdateGBCPal_OBP0 ld a, $54 ld [wBaseCoordX], a ld a, $1c @@ -446,6 +449,8 @@ Trade_InitGameboyTransferGfx: ld a, $1 ld [H_AUTOBGTRANSFERENABLED], a call ClearScreen + ld b, SET_PAL_GENERIC + call RunPaletteCommand xor a ld [H_AUTOBGTRANSFERENABLED], a call Trade_LoadMonPartySpriteGfx @@ -479,8 +484,7 @@ Trade_DrawLeftGameboy: ; draw text box with player name below gameboy pic coord hl, 4, 12 - ld b, 2 - ld c, 7 + lb bc, 2, 7 call TextBoxBorder coord hl, 5, 14 ld de, wPlayerName @@ -526,8 +530,7 @@ Trade_DrawRightGameboy: ; draw text box with enemy name above link cable coord hl, 6, 0 - ld b, 2 - ld c, 7 + lb bc, 2, 7 call TextBoxBorder coord hl, 7, 2 ld de, wLinkEnemyTrainerName @@ -599,6 +602,7 @@ Trade_AnimCircledMon: ld a, [rBGP] xor $3c ; make link cable flash ld [rBGP], a + call UpdateGBCPal_BGP ld hl, wOAMBuffer + $02 ld de, $4 ld c, $14 @@ -620,7 +624,7 @@ Trade_WriteCircledMonOAM: Trade_AddOffsetsToOAMCoords: ld hl, wOAMBuffer - ld c, $14 + ld c, $14 ; SCREEN_WIDTH? .loop ld a, [wBaseCoordY] add [hl] diff --git a/engine/turn_sprite.asm b/engine/turn_sprite.asm deleted file mode 100755 index e8a47a8f..00000000 --- a/engine/turn_sprite.asm +++ /dev/null @@ -1,25 +0,0 @@ -UpdateSpriteFacingOffsetAndDelayMovement: - ld h, $c2 - ld a, [H_CURRENTSPRITEOFFSET] - add $8 - ld l, a - ld a, $7f ; maximum movement delay - ld [hl], a ; c2x8 (movement delay) - dec h - ld a, [H_CURRENTSPRITEOFFSET] - add $9 - ld l, a - ld a, [hld] ; c1x9 (facing direction) - ld b, a - xor a - ld [hld], a - ld [hl], a ; c1x8 (walk animation frame) - ld a, [H_CURRENTSPRITEOFFSET] - add $2 - ld l, a - ld a, [hl] ; c1x2 (facing and animation table offset) - or b ; or in the facing direction - ld [hld], a - ld a, $2 ; delayed movement status - ld [hl], a ; c1x1 (movement status) - ret diff --git a/engine/unknown_ea3ea.asm b/engine/unknown_ea3ea.asm new file mode 100755 index 00000000..1908809b --- /dev/null +++ b/engine/unknown_ea3ea.asm @@ -0,0 +1,973 @@ +Printer_GetMonStats: + call GBPalWhiteOutWithDelay3 + call ClearScreen + call LoadHpBarAndStatusTilePatterns + ld de, GFX_ea563 + ld hl, vChars2 + $710 + lb bc, BANK(GFX_ea563), (GFX_ea563End - GFX_ea563) / 8 + call CopyVideoDataDouble + + ld de, GFX_ea56b + ld hl, vChars2 + $6e0 + lb bc, BANK(GFX_ea56b), (GFX_ea56bEnd - GFX_ea56b) / 8 + call CopyVideoDataDouble + + xor a + ld [H_AUTOBGTRANSFERENABLED], a + xor a + ld [wWhichTradeMonSelectionMenu], a + call LoadMonData + + ld hl, wTileMap + lb bc, 16, 18 + call TextBoxBorder + + coord hl, 0, 12 + lb bc, 4, 18 + call TextBoxBorder + + coord hl, 3, 10 + call PrintLevelFull + + coord hl, 2, 10 + ld a, $6e + ld [hli], a + ld [hl], " " + + coord hl, 2, 11 + ld [hl], "′" + + coord hl, 4, 11 + ld de, wLoadedMonMaxHP + lb bc, 2, 3 + call PrintNumber + + ld a, [wMonHeader] + ld [wPokeBallAnimData], a + ld [wd0b5], a + ld hl, wPartyMonNicks + call .GetNamePointer + coord hl, 8, 2 + call PlaceString + + call GetMonName + coord hl, 9, 3 + call PlaceString + + predef IndexToPokedex + coord hl, 2, 8 + ld [hl], "№" + inc hl + ld [hl], $f2 + inc hl + ld de, wPokeBallAnimData + lb bc, $80 | 1, 3 + call PrintNumber + + coord hl, 8, 4 + ld de, .OT + call PlaceString + + ld hl, wPartyMonOT + call .GetNamePointer + coord hl, 9, 5 + call PlaceString + + coord hl, 9, 6 + ld de, .IDNo + call PlaceString + + coord hl, 13, 6 + ld de, wLoadedMonOTID + lb bc, $80 | 2, 5 + call PrintNumber + + coord hl, 9, 8 + ld de, .Stats + ld a, [hFlags_0xFFFA] + set 2, a + ld [hFlags_0xFFFA], a + call PlaceString + ld a, [hFlags_0xFFFA] + res 2, a + ld [hFlags_0xFFFA], a + + coord hl, 16, 8 + ld de, wLoadedMonAttack + ld a, 4 +.loop + push af + push de + + push hl + lb bc, 2, 3 + call PrintNumber + pop hl + ld bc, SCREEN_WIDTH + add hl, bc + + pop de + inc de + inc de + pop af + dec a + jr nz, .loop + + coord hl, 1, 13 + ld a, [wLoadedMonMoves] + call .PlaceMoveName + + coord hl, 1, 14 + ld a, [wLoadedMonMoves + 1] + call .PlaceMoveName + + coord hl, 1, 15 + ld a, [wLoadedMonMoves + 2] + call .PlaceMoveName + + coord hl, 1, 16 + ld a, [wLoadedMonMoves + 3] + call .PlaceMoveName + + ld b, $4 ; SET_PAL_STATUS_SCREEN + call RunPaletteCommand + + ld a, $1 + ld [H_AUTOBGTRANSFERENABLED], a + call Delay3 + call GBPalNormal + coord hl, 1, 1 + call LoadFlippedFrontSpriteByMonIndex + ret + +.GetNamePointer: + ld bc, NAME_LENGTH + ld a, [wWhichPokemon] + call AddNTimes + ld e, l + ld d, h + ret + +.PlaceMoveName: + and a + jr z, .no_move + ld [wPokeBallAnimData], a + call GetMoveName + jr .place_string + +.no_move + ld de, .Blank +.place_string + call PlaceString + ret + +.OT: + db "OT/@" + +.IDNo: + db $73, "№/@" + +.Stats: + db "ATTACK" + next "DEFENSE" + next "SPEED" + next "SPECIAL@" + +.Blank: + db "--------------@" + +GFX_ea563: +INCBIN "gfx/stats_screen_hp.1bpp" +GFX_ea563End: + +GFX_ea56b: +INCBIN "gfx/stats_screen_lv.1bpp" +GFX_ea56bEnd: + +PrinterDebug_LoadGFX: + ld hl, vChars1 + $7e0 + ld de, GFX_ea597 + lb bc, BANK(GFX_ea597), (GFX_ea597End - GFX_ea597) / 16 + call CopyVideoData + + ld hl, wOAMBuffer + 32 * 4 + ld a, $8 + ld c, $8 +.loop + ld [hl], $10 + inc hl + ld [hl], a + inc hl + ld [hl], $fe + inc hl + ld [hl], $0 + inc hl + add $8 + dec c + jr nz, .loop + ret + +GFX_ea597: +INCBIN "gfx/zero_one_ea597.2bpp" +GFX_ea597End: + +PrinterDebug_ConvertStatusFlagsToTiles: + ld hl, wOAMBuffer + 32 * 4 + 2 + ld de, 4 + ld a, [wPrinterStatusFlags] + ld c, 8 +.loop + sla a + jr c, .place_1 + ld [hl], $fe + jr .okay + +.place_1 + ld [hl], $ff +.okay + add hl, de + dec c + jr nz, .loop + ret + +PrinterDebug_DoFunction: + ld a, [wPrinterSendState] + ld e, a + ld d, 0 + ld hl, .Jumptable + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + jp hl + +.Jumptable: + dw Func_ea623 + dw Func_ea6d2 + dw Func_ea6af + dw Func_ea645 + dw Func_ea701 + dw Func_ea6bd + dw Func_ea671 + dw Func_ea701 + dw Func_ea6af + dw Func_ea68a + dw Func_ea701 + dw Func_ea6af + dw Func_ea721 + dw Func_ea610 + dw Func_ea61a + dw Func_ea6af + dw Func_ea61e + dw Func_ea72f + dw Func_ea732 + +Func_ea606: + ld hl, wPrinterSendState + inc [hl] + ret + +Func_ea60b: + ld hl, wPrinterSendState + dec [hl] + ret + +Func_ea610: + xor a + ld [wPrinterStatusFlags], a + ld hl, wPrinterSendState + set 7, [hl] + ret + +Func_ea61a: + call Func_ea606 + ret + +Func_ea61e: + xor a + ld [wPrinterSendState], a + ret + +Func_ea623: + call Func_ea784 + ld hl, Data_ea9de + call Func_ea76b + xor a + ld [wPrinterDataSize], a + ld [wPrinterDataSize + 1], a + ld a, [wPrinterQueueLength] + ld [wPrinterRowIndex], a + call Func_ea606 + call Func_ea74c + ld a, $1 + ld [wPrinterStatusIndicator], a + ret + +Func_ea645: + call Func_ea784 + ld hl, wPrinterRowIndex + ld a, [hl] + and a + jr z, Func_ea671 + ld hl, Data_ea9ea + call Func_ea76b + call PrinterDebug_PrepOAMForPrinting + ld a, $80 + ld [wPrinterDataSize], a + ld a, $2 + ld [wPrinterDataSize + 1], a + call Func_ea7a2 + call Func_ea606 + call Func_ea74c + ld a, $2 + ld [wPrinterStatusIndicator], a + ret + +Func_ea671: + ld a, $6 + ld [wPrinterSendState], a + ld hl, Data_ea9f0 + call Func_ea76b + xor a + ld [wPrinterDataSize], a + ld [wPrinterDataSize + 1], a + call Func_ea606 + call Func_ea74c + ret + +Func_ea68a: + call Func_ea784 + ld hl, Data_ea9e4 + call Func_ea76b + call Func_ea7d2 + ld a, $4 + ld [wPrinterDataSize], a + ld a, $0 + ld [wPrinterDataSize + 1], a + call Func_ea7a2 + call Func_ea606 + call Func_ea74c + ld a, $3 + ld [wPrinterStatusIndicator], a + ret + +Func_ea6af: + ld hl, wPrinterSerialFrameDelay + inc [hl] + ld a, [hl] + cp a, $6 + ret c + xor a + ld [hl], a + call Func_ea606 + ret + +Func_ea6bd: + ld hl, wPrinterSerialFrameDelay + inc [hl] + ld a, [hl] + cp 6 + ret c + xor a + ld [hl], a + ld hl, wPrinterRowIndex + dec [hl] + call Func_ea60b + call Func_ea60b + ret + +Func_ea6d2: + call Func_ea742 + ret c + ld a, [wPrinterHandshake] + cp a, $ff + jr nz, .asm_ea6e4 + ld a, [wPrinterStatusFlags] + cp a, $ff + jr z, .asm_ea6fb +.asm_ea6e4 + ld a, [wPrinterHandshake] + cp a, $81 + jr nz, .asm_ea6fb + ld a, [wPrinterStatusFlags] + cp a, $0 + jr nz, .asm_ea6fb + ld hl, wPrinterConnectionOpen + set 1, [hl] + call Func_ea606 + ret + +.asm_ea6fb + ld a, $e + ld [wPrinterSendState], a + ret + +Func_ea701: + call Func_ea742 + ret c + ld a, [wPrinterStatusFlags] + and $f0 + jr nz, .asm_ea71b + ld a, [wPrinterStatusFlags] + and $1 + jr nz, .asm_ea717 + call Func_ea606 + ret + +.asm_ea717 + call Func_ea60b + ret + +.asm_ea71b + ld a, $11 + ld [wPrinterSendState], a + ret + +Func_ea721: + call Func_ea742 + ret c + ld a, [wPrinterStatusFlags] + and $f3 + ret nz + call Func_ea606 + ret + +Func_ea72f: + call Func_ea606 +Func_ea732: + ld a, [wPrinterOpcode] + and a + ret nz + ld a, [wPrinterStatusFlags] + and $f0 + ret nz + xor a + ld [wPrinterSendState], a + ret + +Func_ea742: + ld a, [wPrinterOpcode] + and a + jr nz, .asm_ea74a + and a + ret + +.asm_ea74a + scf + ret + +Func_ea74c: +.asm_ea74c + ld a, [wPrinterOpcode] + and a + jr nz, .asm_ea74c + ld a, $1 + ld [wPrinterOpcode], a + xor a + ld [wPrinterSendByteOffset], a + ld [wPrinterSendByteOffset + 1], a + ld a, $88 + ld [rSB], a + ld a, $1 + ld [rSC], a + ld a, $81 + ld [rSC], a + ret + +Func_ea76b: + ld a, [hli] + ld [wPrinterDataHeader], a + ld a, [hli] + ld [wPrinterDataHeader + 1], a + ld a, [hli] + ld [wPrinterDataHeader + 2], a + ld a, [hli] + ld [wPrinterDataHeader + 3], a + ld a, [hli] + ld [wPrinterDataHeader + 4], a + ld a, [hl] + ld [wPrinterDataHeader + 5], a + ret + +Func_ea784: + xor a + ld hl, wPrinterDataHeader + ld [hli], a + ld [hli], a + ld [hli], a + ld [hl], a + ld hl, wPrinterDataHeader + 4 + ld [hli], a + ld [hl], a + xor a + ld [wPrinterDataSize], a + ld [wPrinterDataSize + 1], a + ld hl, wPrinterSendDataSource1 + ld bc, $280 + call FillMemory + ret + +Func_ea7a2: + ld hl, $0 + ld bc, $4 + ld de, wPrinterDataHeader + call Func_ea7c5 + ld a, [wPrinterDataSize] + ld c, a + ld a, [wPrinterDataSize + 1] + ld b, a + ld de, wPrinterSendDataSource1 + call Func_ea7c5 + ld a, l + ld [wPrinterDataHeader + 4], a + ld a, h + ld [wPrinterDataHeader + 5], a + ret + +Func_ea7c5: +.asm_ea7c5 + ld a, [de] + inc de + add l + jr nc, .asm_ea7cb + inc h +.asm_ea7cb + ld l, a + dec bc + ld a, c + or b + jr nz, .asm_ea7c5 + ret + +Func_ea7d2: + ld a, $1 + ld [wPrinterSendDataSource1], a + ld a, [wcae2] + ld [wPrinterStatusReceived], a + ld a, $e4 + ld [wc6f2], a + ld a, [wPrinterSettingsTempCopy] + ld [wc6f3], a + ret + +PrinterDebug_PrepOAMForPrinting: + ld a, [wPrinterRowIndex] + ld b, a + ld a, [wPrinterQueueLength] + sub b + ld hl, wPrinterTileBuffer + ld de, $28 +.get_start_addr + and a + jr z, .start_working + add hl, de + dec a + jr .get_start_addr + +.start_working + ld e, l + ld d, h + ld hl, wPrinterSendDataSource1 + ld c, $28 +.prep_loop + ld a, [de] + inc de + push bc + push de + push hl + swap a + ld d, a + and $f0 + ld e, a + ld a, d + and $f + ld d, a + and $8 + ld a, d + jr nz, .vtiles1 + or $90 + jr .got_vram_address + +.vtiles1 + or $80 +.got_vram_address + ld d, a + lb bc, BANK(PrinterDebug_PrepOAMForPrinting), $1 + call CopyVideoData + pop hl + ld de, $10 + add hl, de + pop de + pop bc + dec c + jr nz, .prep_loop + call .UnnecessaryCall + ret + +.UnnecessaryCall: + ld hl, wcbdc + ld bc, $20 + xor a + call FillMemory + ld hl, wOAMBuffer + ld c, $28 +.master_loop + push bc + push hl + call .AreWePrintingThisSegment + jr nc, .skip_segment + call .GetVRAMAddress + call .GetOAMFlags + call .ApplyObjectPalettes + call .PlaceObject +.skip_segment + pop hl + inc hl + inc hl + inc hl + inc hl + pop bc + dec c + jr nz, .master_loop + ret + +.AreWePrintingThisSegment: + ld a, [wPrinterRowIndex] + ld b, a + ld a, [wPrinterQueueLength] + sub b + ld c, a + ld b, $10 +.add_n_times + ld a, c + and a + jr z, .check + ld a, b + add $10 + ld b, a + dec c + jr .add_n_times + +.check + ld a, b + ld e, a + add $10 + ld d, a + ld a, [hl] + cp e + jr c, .not_printing + cp d + jr nc, .not_printing + scf + ret + +.not_printing + and a + ret + +.GetVRAMAddress: + push hl + inc hl + inc hl + ld a, [hl] + swap a + ld d, a + and $f0 + ld e, a + ld a, d + and $f + or $80 + ld d, a + ld hl, wcbdc + lb bc, BANK(.GetVRAMAddress), $1 + call CopyVideoData + pop hl + ret + +.GetOAMFlags: + push hl + inc hl + inc hl + inc hl + ld a, [hl] + call .DoBitOperation + pop hl + ret + +.DoBitOperation: + and $60 + swap a + ld e, a + ld d, 0 + ld hl, .Jumptable + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + jp hl + +.Jumptable: + dw .nop + dw .xflip + dw .yflip + dw .both + +.nop: + ret + +.xflip: + call .XFlip + ret + +.yflip: + call .YFlip + ret + +.both: + call .XFlip + call .YFlip + ret + +.XFlip: + ld hl, wcbdc + ld c, 16 +.byte_loop + ld d, [hl] + ld a, 0 + ld b, 8 +.bit_loop + sla d + rr a + dec b + jr nz, .bit_loop + ld [hli], a + dec c + jr nz, .byte_loop + ret + +.YFlip: + ld hl, wcbdc + ld de, wcbea + ld c, $4 +.swap_loop + ld b, [hl] + ld a, [de] + ld [hli], a + ld a, b + ld [de], a + inc de + ld b, [hl] + ld a, [de] + ld [hli], a + ld a, b + ld [de], a + dec de + dec de + dec de + dec c + jr nz, .swap_loop + ret + +.ApplyObjectPalettes: + push hl + ld hl, wcbdc + ld de, wcbec + ld a, 8 +.loop1 + push af + ld bc, $0 + ld a, 8 +.loop2 + push af + xor a + rlc [hl] + rl a + inc hl + rlc [hl] + rl a + dec hl + push hl + push de + call .ExpandPalettesToBC + pop de + pop hl + pop af + dec a + jr nz, .loop2 + inc hl + inc hl + ld a, b + ld [de], a + inc de + ld a, c + ld [de], a + inc de + pop af + dec a + jr nz, .loop1 + pop hl + ret + +.ExpandPalettesToBC: + call .GetPaletteFunction + call .ApplyPaletteFunction + ret + +.GetPaletteFunction: + ld e, a + ld d, 0 + ld hl, .PalJumptable + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + jp hl + +.PalJumptable: + dw .Pal0 + dw .Pal1 + dw .Pal2 + dw .Pal3 + +.Pal0: + ld a, [rOBP0] + and $3 + ret + +.Pal2: + ld a, [rOBP0] + and $c + srl a + srl a + ret + +.Pal1: + ld a, [rOBP0] + and $30 + swap a + ret + +.Pal3: + ld a, [rOBP0] + and $c0 + rlca + rlca + ret + +.ApplyPaletteFunction: + ld e, a + ld d, 0 + ld hl, .PalFunJumptable + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + jp hl + +.PalFunJumptable: + dw .zero_zero + dw .xflip_zero + dw .zero_xflip + dw .xflip_xflip + +.zero_zero: + sla b + sla c + ret + +.xflip_zero: + scf + rl b + sla c + ret + +.zero_xflip: + sla b + scf + rl c + ret + +.xflip_xflip: + scf + rl b + scf + rl c + ret + +.PlaceObject: + push hl + ld a, [hli] + ld c, [hl] + and $8 + jr nz, .use_source_2 + ld hl, wPrinterSendDataSource1 + jr .got_data_source + +.use_source_2 + ld hl, wPrinterSendDataSource2 +.got_data_source + ld b, $0 + ld a, c + and %11111000 + sub $8 + ld c, a + sla c + rl b + add hl, bc + ld e, l + ld d, h + ld hl, wcbec + ld c, $8 +.coord_copy_loop + call .GetBitMask + ld a, [de] + and b + or [hl] + ld [de], a + inc hl + inc de + ld a, [de] + and b + or [hl] + ld [de], a + inc hl + inc de + dec c + jr nz, .coord_copy_loop + pop hl + ret + +.GetBitMask: + push hl + push de + ld de, -$10 + add hl, de + ld a, [hli] + or [hl] + xor $ff + ld b, a + pop de + pop hl + ret + +Data_ea9de: + db 1, 0, $00, 0 + dw 1 +Data_ea9e4: + db 2, 0, $04, 0 + dw 0 +Data_ea9ea: + db 4, 0, $80, 2 + dw 0 +Data_ea9f0: + db 4, 0, $00, 0 + dw 4 +Data_ea9f6: + db 8, 0, $00, 0 + dw 8 +Data_ea9fc: + db 15, 0, $00, 0 + dw 15 diff --git a/engine/vermilion_gym_trash_cans.asm b/engine/vermilion_gym_trash_cans.asm new file mode 100755 index 00000000..49dee50c --- /dev/null +++ b/engine/vermilion_gym_trash_cans.asm @@ -0,0 +1,108 @@ +TrashCanRandom: + ld d, 0 + ld hl, .Jumptable + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + call JumpToAddress + ld e, a + ld d, 0 + ret + +.Jumptable: + dw .zero + dw .one + dw .two + dw .three + dw .four + +.zero +.one + ld a, 0 + ret + +.two + call Random + and $1 + ret + +.three ; should return to a, instead returns to b + call Random + swap a + cp 1 * $ff / 3 + ld b, 0 + ret c + cp 2 * $ff / 3 + ld b, 1 + ret c + ld b, 2 + ret + +.four + call Random + and $3 + ret + +Yellow_SampleSecondTrashCan: + ld hl, GymTrashCans3c + ld a, [wGymTrashCanIndex] + ld c, a + ld b, 0 + ld a, 9 + call AddNTimes + call AddNTimes ; ???? + ld a, [hli] + ld [hGymTrashCanRandNumMask], a + ld e, a + push hl + call TrashCanRandom + pop hl + add hl, de + add hl, de + ld a, [hli] + ld [wSecondLockTrashCanIndex], a + ld a, [hl] + ld [wSecondLockTrashCanIndex + 1], a + ret + +GymTrashCans3c: +; First byte: number of trashcan entries +; Following four byte pairs: indices for the second trash can. +; BUG: Rows that have 3 trashcan entries are sampled incorrectly. +; The sampling occurs by taking a random number and seeing which +; third of the range 0-255 the number falls in. However, it returns +; that value to the wrong register, so the result is never used. +; Instead of using an offset in [0,1,2], the offset is instead +; in the full range 0-255. This results in truly random behavior. + db 4 + db 1,3, 3,1, 1,-1, 3,-1 + db 3 + db 0,2, 2,4, 4,0, -1,-1 + db 4 + db 1,5, 5,1, 1,-1, 5,-1 + db 3 + db 0,4, 4,6, 6,0, -1,-1 + db 4 + db 1,3, 3,1, 5,5, 7,7 + db 3 + db 2,4, 4,8, 8,2, -1,-1 + db 3 + db 3,7, 7,9, 9,3, -1,-1 + db 4 + db 4,8, 6,10, 8,4, 10,6 + db 3 + db 5,7, 7,11, 11,5, -1,-1 + db 3 + db 6,10, 10,12, 12,6, -1,-1 + db 4 + db 7,9, 9,7, 11,13, 13,11 + db 3 + db 8,10, 10,14, 14,8, -1,-1 + db 4 + db 9,13, 13,9, 9,-1, 13,-1 + db 3 + db 10,12, 12,14, 14,10, -1,-1 + db 4 + db 11,13, 13,11, 11,-1, 13,-1 diff --git a/engine/yellow_intro.asm b/engine/yellow_intro.asm new file mode 100755 index 00000000..9c9e26b3 --- /dev/null +++ b/engine/yellow_intro.asm @@ -0,0 +1,1081 @@ +PlayIntroScene: + ld a, [rIE] + push af + xor a + ld [rIF], a + ld a, $f + ld [rIE], a + ld a, $8 + ld [rSTAT], a + call InitYellowIntroGFXAndMusic + call DelayFrame +.loop + ld a, [wYellowIntroCurrentScene] + bit 7, a + jr nz, .go_to_title_screen + call JoypadLowSensitivity + ld a, [hJoyPressed] + and A_BUTTON | B_BUTTON | START + jr nz, .go_to_title_screen + call Func_f98fc + ld a, $0 + ld [wCurrentAnimatedObjectOAMBufferOffset], a + call RunObjectAnimations + ld a, [wYellowIntroCurrentScene] + cp $7 + call z, Func_f98a2 + cp $b + call z, Func_f98cb + call DelayFrame + jr .loop + +.go_to_title_screen + call YellowIntro_BlankPalettes + xor a + ld [hLCDCPointer], a + call DelayFrame + xor a + ld [rIF], a + pop af + ld [rIE], a + ld a, $90 + ld [hWY], a + call ClearObjectAnimationBuffers + ld hl, wTileMap + ld bc, SCREEN_WIDTH * SCREEN_HEIGHT + xor a + call Bank3E_FillMemory + call YellowIntro_BlankOAMBuffer + ld a, $1 + ld [H_AUTOBGTRANSFERENABLED], a + call DelayFrame + call DelayFrame + call DelayFrame + xor a + ld [H_AUTOBGTRANSFERENABLED], a + ret + +Func_f98a2: + ld a, [wOAMBuffer + 8 * 4 + 3] + or $1 + ld [wOAMBuffer + 8 * 4 + 3], a + ld a, [wOAMBuffer + 14 * 4 + 3] + or $1 + ld [wOAMBuffer + 14 * 4 + 3], a + ld a, [wOAMBuffer + 16 * 4 + 3] + or $1 + ld [wOAMBuffer + 16 * 4 + 3], a + ld a, [wOAMBuffer + 18 * 4 + 3] + or $1 + ld [wOAMBuffer + 18 * 4 + 3], a + ld a, [wOAMBuffer + 19 * 4 + 3] + or $1 + ld [wOAMBuffer + 19 * 4 + 3], a + ret + +Func_f98cb: + ld a, [wOAMBuffer + 18 * 4 + 3] + or $1 + ld [wOAMBuffer + 18 * 4 + 3], a + ld a, [wOAMBuffer + 19 * 4 + 3] + or $1 + ld [wOAMBuffer + 19 * 4 + 3], a + ld a, [wOAMBuffer + 20 * 4 + 3] + or $1 + ld [wOAMBuffer + 20 * 4 + 3], a + ld a, [wOAMBuffer + 25 * 4 + 3] + or $1 + ld [wOAMBuffer + 25 * 4 + 3], a + ld a, [wOAMBuffer + 26 * 4 + 3] + or $1 + ld [wOAMBuffer + 26 * 4 + 3], a + ld a, [wOAMBuffer + 28 * 4 + 3] + or $1 + ld [wOAMBuffer + 28 * 4 + 3], a + ret + +Func_f98fc: + ld a, [wYellowIntroCurrentScene] + ld hl, Jumptable_f9906 + call Func_fa06e + jp hl + +Jumptable_f9906: + dw YellowIntroScene0 ; running pika 1 + dw YellowIntroScene1 ; wait last + dw YellowIntroScene2 ; pikachu kick + dw YellowIntroScene3 ; wait last + dw YellowIntroScene4 ; running pika 2 + dw YellowIntroScene5 ; wait last + dw YellowIntroScene6 ; surfing pika + dw YellowIntroScene7 ; wait last + dw YellowIntroScene8 ; running pika 3 + dw YellowIntroScene9 ; wait last + dw YellowIntroScene10 ; flying pika + dw YellowIntroScene11 ; wait last + dw YellowIntroScene12 ; pika close up + dw YellowIntroScene13 ; wait last + dw YellowIntroScene14 ; pika thunderbolt + dw YellowIntroScene15 ; wait last + dw YellowIntroScene16 ; fade to white + dw YellowIntroScene17 ; wait and quit + +YellowIntro_NextScene: + ld hl, wYellowIntroCurrentScene + inc [hl] + ret + +YellowIntroScene0: + xor a + ld [hLCDCPointer], a + lb de, $58, $58 + ld a, $1 + call YellowIntro_SpawnAnimatedObjectAndSavePointer + xor a + ld [hSCX], a + ld [hSCY], a + ld a, $90 + ld [hWY], a + ld a, $e4 + ld [rBGP], a + ld [rOBP0], a + ld a, $c4 + ld [rOBP1], a + call UpdateGBCPal_BGP + call UpdateGBCPal_OBP0 + call UpdateGBCPal_OBP1 + ld a, 130 + ld [wYellowIntroSceneTimer], a + call YellowIntro_NextScene + ret + +YellowIntroScene1: + call YellowIntro_CheckFrameTimerDecrement + ret nc + call YellowIntro_MaskCurrentAnimatedObjectStruct + call YellowIntro_NextScene + ret + +YellowIntroScene2: + call YellowIntro_BlankPalsDelay2AndDisableLCD + ld c, $8 + call UpdateMusicCTimes + xor a + ld [hLCDCPointer], a + ld hl, vBGMap0 + ld bc, $400 + xor a + call Bank3E_FillMemory + call YellowIntroScene2_PlaceGraphic + lb de, $58, $b8 ; overloaded + ld a, $4 ; overloaded + call LoadYellowIntroFlyingSpeedBars + ld a, $1 + call Func_f9e9a + call YellowIntro_SetTimerFor128Frames + call YellowIntro_NextScene + ret + +YellowIntroScene2_PlaceGraphic: + ld hl, $98d4 ; (20, 6) + ld de, $20 + ld b, $6 + ld a, $90 +.row + ld c, $6 + push af + push hl +.col + ld [hli], a + inc a + dec c + jr nz, .col + pop hl + add hl, de + pop af + add $10 + dec b + jr nz, .row + ld a, [hGBC] + and a + jr z, .dmg_sgb + ; We can actually set palettes! + ld hl, $98d4 ; (20, 6) + ld de, $20 + ld b, $6 + ld a, $1 + ld [rVBK], a +.attr_row + ld c, $6 + push hl +.attr_col + ld [hli], a + dec c + jr nz, .attr_col + pop hl + add hl, de + dec b + jr nz, .attr_row + xor a + ld [rVBK], a +.dmg_sgb + ret + +LoadYellowIntroFlyingSpeedBars: + ld hl, YellowIntroFlyingSpeedBarData + ld a, $8 +.loop +; Spawn object $8 at indicated coordinates with indicated speeds + push af + ld e, [hl] + inc hl + ld d, [hl] + inc hl + ld a, [hli] + push hl + push af + ld a, $8 + call SpawnAnimatedObject + pop af + ld hl, $b + add hl, bc + ld [hl], a + pop hl + pop af + dec a + jr nz, .loop + ret + +YellowIntroFlyingSpeedBarData: + ; y, x, speed + db $d0, $20, $02 + db $f0, $30, $04 + db $d0, $40, $06 + db $c0, $50, $08 + db $e0, $60, $08 + db $c0, $70, $06 + db $e0, $80, $04 + db $f0, $90, $02 + +YellowIntroScene3: + call YellowIntro_CheckFrameTimerDecrement + jr c, .expired + ld a, [hSCX] + cp $68 + ret z + add $4 + ld [hSCX], a + ret + +.expired + call MaskAllAnimatedObjectStructs + call YellowIntro_NextScene + ret + +YellowIntroScene4: + call YellowIntro_BlankPalsDelay2AndDisableLCD + ld c, $5 + call UpdateMusicCTimes + ld a, [hGBC] + and a + jr z, .dmg_sgb + ; We can actually set palettes! + ld hl, $98d4 + ld de, $20 + ld b, $6 + ld a, $1 + ld [rVBK], a + xor a +.attr_row + ld c, $6 + push hl +.attr_col + ld [hli], a + dec c + jr nz, .attr_col + pop hl + add hl, de + dec b + jr nz, .attr_row + xor a + ld [rVBK], a +.dmg_sgb + xor a + ld [hLCDCPointer], a + call Func_f9e5f + lb de, $58, $58 + ld a, $2 + call YellowIntro_SpawnAnimatedObjectAndSavePointer + xor a + call Func_f9e9a + call YellowIntro_SetTimerFor128Frames + call YellowIntro_NextScene + ret + +YellowIntroScene5: + call YellowIntro_CheckFrameTimerDecrement + ret nc + call YellowIntro_MaskCurrentAnimatedObjectStruct + call YellowIntro_NextScene + ret + +YellowIntroScene6: + call YellowIntro_BlankPalsDelay2AndDisableLCD + ld c, $5 + call UpdateMusicCTimes + ld a, rSCY - $ff00 + ld [hLCDCPointer], a + call YellowIntro_Copy8BitSineWave + ld hl, vBGMap0 + ld bc, $60 + xor a + call Bank3E_FillMemory + ld hl, $9860 + ld c, $10 + ld a, $20 +.asm_f9a8b + ld [hli], a + inc a + ld [hli], a + dec a + dec c + jr nz, .asm_f9a8b + ld hl, $9880 + ld bc, $300 + ld a, $10 + call Bank3E_FillMemory + lb de, $40, $f8 + ld a, $5 + call YellowIntro_SpawnAnimatedObjectAndSavePointer + ld a, $1 + call Func_f9e9a + call YellowIntro_SetTimerFor88Frames + call YellowIntro_NextScene + ret + +YellowIntroScene7: + call YellowIntro_CheckFrameTimerDecrement + jr c, .expired + ld hl, hSCX + inc [hl] + inc [hl] + ld hl, wLYOverridesBuffer + ld de, wLYOverridesBuffer + 1 + ld a, [hl] + push af + ld c, $ff +.shift_loop + ld a, [de] + inc de + ld [hli], a + dec c + jr nz, .shift_loop + pop af + ld [hl], a + call Request7TileTransferFromC810ToC710 + ret + +.expired + call YellowIntro_MaskCurrentAnimatedObjectStruct + call YellowIntro_NextScene + ret + +YellowIntroScene8: + call YellowIntro_BlankPalsDelay2AndDisableLCD + ld c, $5 + call UpdateMusicCTimes + xor a + ld [hLCDCPointer], a + call Func_f9e5f + lb de, $58, $58 + ld a, $3 + call YellowIntro_SpawnAnimatedObjectAndSavePointer + xor a + call Func_f9e9a + call YellowIntro_SetTimerFor128Frames + call YellowIntro_NextScene + ret + +YellowIntroScene9: + call YellowIntro_CheckFrameTimerDecrement + ret nc + call YellowIntro_MaskCurrentAnimatedObjectStruct + call YellowIntro_NextScene + ret + +YellowIntroScene10: + call YellowIntro_BlankPalsDelay2AndDisableLCD + ld c, $5 + call UpdateMusicCTimes + xor a + ld [hLCDCPointer], a + ld hl, vBGMap0 + ld bc, $400 + xor a + call Bank3E_FillMemory + ld hl, vBGMap0 + ld bc, $100 + ld a, $2 + call Bank3E_FillMemory + ld hl, $9900 + ld de, Unkn_f9b6e + lb bc, 6, 20 + call .FillBGMapBox + ld hl, $988c + ld de, Unkn_f9be6 + lb bc, 3, 4 + call .FillBGMapBox + ld hl, $98e3 + ld de, Unkn_f9bf2 + lb bc, 2, 2 + call .FillBGMapBox + lb de, $98, $58 + ld a, $6 + call YellowIntro_SpawnAnimatedObjectAndSavePointer + ld a, $1 + call Func_f9e9a + call YellowIntro_SetTimerFor128Frames + call YellowIntro_NextScene + ret + +.FillBGMapBox: +.fill_row + push bc + push hl +.fill_col + ld a, [de] + inc de + ld [hli], a + dec c + jr nz, .fill_col + pop hl + ld bc, $20 + add hl, bc + pop bc + dec b + jr nz, .fill_row + ret + +Unkn_f9b6e: INCBIN "gfx/unknown_f9b6e.map" +Unkn_f9be6: INCBIN "gfx/unknown_f9be6.map" +Unkn_f9bf2: INCBIN "gfx/unknown_f9bf2.map" + +YellowIntroScene11: + call YellowIntro_CheckFrameTimerDecrement + jr c, .expired + ld a, [wYellowIntroSceneTimer] + and $7 + ret nz + ld a, [wYellowIntroSceneTimer] + and $8 + sla a + sla a + sla a + ld e, a + ld d, $0 + ld hl, YellowIntroCloudGFX1 + add hl, de + ld a, l + ld [H_VBCOPYSRC], a + ld a, h + ld [H_VBCOPYSRC + 1], a + xor a + ld [H_VBCOPYDEST], a + ld a, $96 + ld [H_VBCOPYDEST + 1], a + ld a, $4 + ld [H_VBCOPYSIZE], a + ret + +.expired + call YellowIntro_MaskCurrentAnimatedObjectStruct + call YellowIntro_NextScene + ret + +YellowIntroCloudGFX1: INCBIN "gfx/unknown_f9c2c.2bpp" +YellowIntroCloudGFX2: INCBIN "gfx/unknown_f9c6c.2bpp" ; indirectly referenced + +YellowIntroScene12: + call YellowIntro_BlankPalsDelay2AndDisableLCD + ld c, $5 + call UpdateMusicCTimes + xor a + ld [hLCDCPointer], a + ld hl, vBGMap0 + ld bc, $80 + ld a, $1 + call Bank3E_FillMemory + ld hl, $9880 + ld bc, $140 + xor a + call Bank3E_FillMemory + ld hl, $99c0 + ld bc, $80 + ld a, $1 + call Bank3E_FillMemory + + ; paste 8x12 graphic into vBGMap0 at (5, 6) starting at tile 4, skipping 4 vtiles at the end of each row + ld hl, $98c5 + ld de, $20 + ld a, $4 + ld b, 8 +.row + ld c, 12 + push hl +.col + ld [hli], a + inc a + dec c + jr nz, .col + pop hl + add hl, de + add $4 + dec b + jr nz, .row + + ld hl, $98c4 ; (4, 6) + ld [hl], $3 + ld hl, $98e4 ; (4, 7) + ld [hl], $74 + ld hl, $99a5 ; (5, 5) + ld [hl], $0 + lb de, $60, $58 + ld a, $9 + call YellowIntro_SpawnAnimatedObjectAndSavePointer + xor a + call Func_f9e9a + call YellowIntro_SetTimerFor128Frames + call YellowIntro_NextScene + ret + +YellowIntroScene13: + call YellowIntro_CheckFrameTimerDecrement + ret nc + lb de, $68, $58 + ld a, $a + call SpawnAnimatedObject + call YellowIntro_NextScene + ret + +YellowIntroScene14: + ld de, YellowIntroPalSequence_f9dd6 + call YellowIntro_LoadDMGPalAndIncrementCounter + jr c, .expired + ld [rBGP], a + ld [rOBP0], a + and $f0 + ld [rOBP1], a + call UpdateGBCPal_BGP + call UpdateGBCPal_OBP0 + call UpdateGBCPal_OBP1 + ret + +.expired + call MaskAllAnimatedObjectStructs + call YellowIntro_BlankOAMBuffer + ld hl, wTileMap + ld bc, $50 + ld a, $1 + call Bank3E_FillMemory + coord hl, 0, 4 + ld bc, CopyVideoDataAlternate + xor a + call Bank3E_FillMemory + coord hl, 0, 14 + ld bc, $50 + ld a, $1 + call Bank3E_FillMemory + ld a, $1 + ld [H_AUTOBGTRANSFERENABLED], a + call DelayFrame + call DelayFrame + call DelayFrame + xor a + ld [H_AUTOBGTRANSFERENABLED], a + ld a, $e4 + ld [rOBP0], a + ld [rBGP], a + call UpdateGBCPal_BGP + call UpdateGBCPal_OBP0 + lb de, $58, $58 + ld a, $7 + call YellowIntro_SpawnAnimatedObjectAndSavePointer + call YellowIntro_NextScene + ld a, $28 + ld [wYellowIntroSceneTimer], a + ret + +YellowIntroScene15: + call YellowIntro_CheckFrameTimerDecrement + jr c, .expired + ld a, [wYellowIntroSceneTimer] + and $3 + ret nz + ld a, [rOBP0] + xor $ff + ld [rOBP0], a + ld a, [rBGP] + xor $3 + ld [rBGP], a + call UpdateGBCPal_BGP + call UpdateGBCPal_OBP0 + ret + +.expired + xor a + ld [hLCDCPointer], a + ld a, $e4 + ld [rBGP], a + ld [rOBP0], a + call UpdateGBCPal_BGP + call UpdateGBCPal_OBP0 + call YellowIntro_NextScene +YellowIntroScene16: + ld de, YellowIntroPalSequence_f9e0a + call YellowIntro_LoadDMGPalAndIncrementCounter + jr c, .expired + ld [rOBP0], a + ld [rBGP], a + call UpdateGBCPal_BGP + call UpdateGBCPal_OBP0 + ret + +.expired + call YellowIntro_NextScene + ret + +YellowIntroPalSequence_f9dd6: + db $e4, $c0, $c0, $e4 + db $e4, $c0, $c0, $e4 + db $e4, $c0, $c0, $e4 + db $e4, $c0, $c0, $e4 + db $e4, $c0, $c0, $e4 + db $e4, $c0, $c0, $e4 + db $e4, $c0, $c0, $e4 + db $e4, $c0, $c0, $e4 + db $e4, $c0, $c0, $e4 + db $e4, $c0, $c0, $e4 + db $e4, $c0, $c0, $e4 + db $e4, $c0, $c0, $e4 + db $e4, $c0, $c0, $ff + +YellowIntroPalSequence_f9e0a: + db $e4, $90, $90, $40 + db $40, $00, $00, $ff + +YellowIntroScene17: + ld c, 64 + call DelayFrames + ld hl, wYellowIntroCurrentScene + set 7, [hl] + ret + +YellowIntro_SpawnAnimatedObjectAndSavePointer: + call SpawnAnimatedObject + ld a, c + ld [wYellowIntroAnimatedObjectStructPointer], a + ld a, b + ld [wYellowIntroAnimatedObjectStructPointer + 1], a + ret + +YellowIntro_MaskCurrentAnimatedObjectStruct: + ld a, [wYellowIntroAnimatedObjectStructPointer] + ld c, a + ld a, [wYellowIntroAnimatedObjectStructPointer + 1] + ld b, a + call MaskCurrentAnimatedObjectStruct + ret + +YellowIntro_SetTimerFor128Frames: + ld a, 128 + ld [wYellowIntroSceneTimer], a + ret + +YellowIntro_SetTimerFor88Frames: + ld a, 88 + ld [wYellowIntroSceneTimer], a + ret + +YellowIntro_CheckFrameTimerDecrement: + ld hl, wYellowIntroSceneTimer + ld a, [hl] + and a + jr z, .asm_f9e4b + dec [hl] + and a + ret + +.asm_f9e4b + scf + ret + +YellowIntro_LoadDMGPalAndIncrementCounter: + ld hl, wYellowIntroSceneTimer + ld a, [hl] + inc [hl] + ld l, a + ld h, $0 + add hl, de + ld a, [hl] + cp $ff + jr z, .asm_f9e5d + and a + ret + +.asm_f9e5d + scf + ret + +Func_f9e5f: + ld hl, vBGMap0 + ld bc, $80 + ld a, $1 + call Bank3E_FillMemory + ld hl, $9880 + ld bc, $140 + xor a + call Bank3E_FillMemory + ld hl, $99c0 + ld bc, $80 + ld a, $1 + call Bank3E_FillMemory + ret + +YellowIntro_BlankPalsDelay2AndDisableLCD: + xor a + ld [rBGP], a + ld [rOBP0], a + ld [rOBP1], a + call UpdateGBCPal_BGP + call UpdateGBCPal_OBP0 + call UpdateGBCPal_OBP1 + call DelayFrame + call DelayFrame + call DisableLCD + ret + +Func_f9e9a: + ld e, a + callab YellowIntroPaletteAction + xor a + ld [hSCX], a + ld [hSCY], a + ld a, $90 + ld [hWY], a + ld a, $e3 + ld [rLCDC], a + ld a, $e4 + ld [rBGP], a + ld [rOBP0], a + ld a, $e0 + ld [rOBP1], a + call UpdateGBCPal_BGP + call UpdateGBCPal_OBP0 + call UpdateGBCPal_OBP1 + ret + +YellowIntro_Copy8BitSineWave: + ; Copy this sine wave into wLYOverridesBuffer 8 times (end just before wc900) + ld de, wLYOverridesBuffer + ld a, $8 +.loop + push af + ld hl, .SineWave + ld bc, .SineWaveEnd - .SineWave + call Bank3E_CopyData + pop af + dec a + jr nz, .loop + ret + +.SineWave: +; a sine wave with amplitude 4 + db 0, 0, 1, 2, 2, 3, 3, 3 + db 4, 3, 3, 3, 2, 2, 1, 0 + db 0, 0, -1, -2, -2, -3, -3, -3 + db -4, -3, -3, -3, -2, -2, -1, 0 +.SineWaveEnd: + +Request7TileTransferFromC810ToC710: + ld a, $10 + ld [H_VBCOPYSRC], a + ld a, wLYOverridesBuffer / $100 + ld [H_VBCOPYSRC + 1], a + ld a, $10 + ld [H_VBCOPYDEST], a + ld a, wLYOverrides / $100 + ld [H_VBCOPYDEST + 1], a + ld a, $7 + ld [H_VBCOPYSIZE], a + ret + +InitYellowIntroGFXAndMusic: + xor a + ld [H_AUTOBGTRANSFERENABLED], a + ld [hSCX], a + ld [hSCY], a + ld [H_AUTOBGTRANSFERDEST], a + ld a, $98 + ld [H_AUTOBGTRANSFERDEST + 1], a + call YellowIntro_BlankTileMap + ld hl, wTileMap + ld bc, SCREEN_WIDTH * SCREEN_HEIGHT + ld a, $1 + call Bank3E_FillMemory + coord hl, 0, 4 + ld bc, CopyVideoDataAlternate + xor a + call Bank3E_FillMemory + ld a, $1 + ld [H_AUTOBGTRANSFERENABLED], a + call DelayFrame + call DelayFrame + call DelayFrame + xor a + ld [H_AUTOBGTRANSFERENABLED], a + ld de, $6b5a + ld hl, $8000 + ld bc, $3eff + call CopyVideoData + ld de, $635a + ld hl, $9000 + ld bc, $3e80 + call CopyVideoData + call ClearObjectAnimationBuffers + call LoadYellowIntroObjectAnimationDataPointers + ld b, $8 + call RunPaletteCommand + xor a + ld hl, wYellowIntroCurrentScene + ld [hli], a + ld [hli], a + ld [hli], a + ld [hl], a + ld a, MUSIC_YELLOW_INTRO + ld c, BANK(Music_YellowIntro) + call PlayMusic + ret + +LoadYellowIntroObjectAnimationDataPointers: + ld a, YellowIntro_AnimatedObjectSpawnStateData % $100 + ld [wAnimatedObjectSpawnStateDataPointer], a + ld a, YellowIntro_AnimatedObjectSpawnStateData / $100 + ld [wAnimatedObjectSpawnStateDataPointer + 1], a + ld a, YellowIntro_AnimatedObjectJumptable % $100 + ld [wAnimatedObjectJumptablePointer], a + ld a, YellowIntro_AnimatedObjectJumptable / $100 + ld [wAnimatedObjectJumptablePointer + 1], a + ld a, YellowIntro_AnimatedObjectOAMData % $100 + ld [wAnimatedObjectOAMDataPointer], a + ld a, YellowIntro_AnimatedObjectOAMData / $100 + ld [wAnimatedObjectOAMDataPointer + 1], a + ld a, YellowIntro_AnimatedObjectFramesData % $100 + ld [wAnimatedObjectFramesDataPointer], a + ld a, YellowIntro_AnimatedObjectFramesData / $100 + ld [wAnimatedObjectFramesDataPointer + 1], a + ret + +YellowIntro_BlankTileMap: + ld hl, wTileMap + ld bc, SCREEN_WIDTH * SCREEN_HEIGHT + ld a, $7f + call Bank3E_FillMemory + ret + +Bank3E_CopyData: +.loop + ld a, [hli] + ld [de], a + inc de + dec bc + ld a, c + or b + jr nz, .loop + ret + +Bank3E_FillMemory: + push de + ld e, a +.loop + ld a, e + ld [hli], a + dec bc + ld a, c + or b + jr nz, .loop + pop de + ret + +YellowIntro_BlankOAMBuffer: + ld hl, wOAMBuffer + ld bc, wOAMBufferEnd - wOAMBuffer + xor a + call Bank3E_FillMemory + ret + +YellowIntro_BlankPalettes: + xor a + ld [rBGP], a + ld [rOBP0], a + ld [rOBP1], a + call UpdateGBCPal_BGP + call UpdateGBCPal_OBP0 + call UpdateGBCPal_OBP1 + ret + +YellowIntro_AnimatedObjectSpawnStateData: + db $00, $00, $00 + db $01, $01, $00 + db $02, $01, $00 + db $03, $01, $00 + db $04, $02, $00 + db $05, $03, $00 + db $06, $04, $00 + db $07, $01, $00 + db $08, $05, $00 + db $09, $01, $00 + db $0a, $01, $00 + +YellowIntro_AnimatedObjectJumptable: + dw Func_fa007 + dw Func_fa007 + dw Func_fa008 + dw Func_fa014 + dw Func_fa02b + dw Func_fa062 + +Func_fa007: + ret + +Func_fa008: + ld hl, $4 + add hl, bc + ld a, [hl] + cp $58 + ret z + sub $4 + ld [hl], a + ret + +Func_fa014: + ld hl, $4 + add hl, bc + ld a, [hl] + cp $58 + jr z, .asm_fa020 + add $4 + ld [hl], a +.asm_fa020 + ld hl, $5 + add hl, bc + cp $58 + ret z + add $1 + ld [hl], a + ret + +Func_fa02b: + ld hl, $b + add hl, bc + ld e, [hl] + ld d, $0 + ld hl, Jumptable_fa03b + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + jp hl + +Jumptable_fa03b: + dw Func_fa03f + dw Func_fa051 + +Func_fa03f: + ld hl, $5 + add hl, bc + ld a, [hl] + cp $58 + jr z, .asm_fa04c + sub $2 + ld [hl], a + ret + +.asm_fa04c + ld hl, $b + add hl, bc + inc [hl] +Func_fa051: + ld hl, $c + add hl, bc + ld a, [hl] + inc [hl] + ld d, $8 + call Func_fa079 + ld hl, $7 + add hl, bc + ld [hl], a + ret + +Func_fa062: + ld hl, $b + add hl, bc + ld a, [hl] + ld hl, $4 + add hl, bc + add [hl] + ld [hl], a + ret + +Func_fa06e: + ld e, a + ld d, $0 + add hl, de + add hl, de + ld a, [hli] + ld h, [hl] + ld l, a + ret + +Func_fa077: ; cosine + add $10 +Func_fa079: + and $3f + cp $20 + jr nc, .asm_fa084 + call Func_fa08e + ld a, h + ret + +.asm_fa084 + and $1f + call Func_fa08e + ld a, h + xor $ff + inc a + ret + +Func_fa08e: + ld e, a + ld a, d + ld d, $0 + ld hl, Unkn_fa0aa + add hl, de + add hl, de + ld e, [hl] + inc hl + ld d, [hl] + ld hl, $0 +.asm_fa09d + srl a + jr nc, .asm_fa0a2 + add hl, de +.asm_fa0a2 + sla e + rl d + and a + jr nz, .asm_fa09d + ret + +Unkn_fa0aa: + sine_wave $100 |