INCLUDE "constants.asm" SECTION "NULL", ROM0 NULL:: INCLUDE "home/header.asm" SECTION "High Home", ROM0 INCLUDE "home/lcd.asm" INCLUDE "home/clear_sprites.asm" INCLUDE "home/copy.asm" SECTION "Home", ROM0 INCLUDE "home/start.asm" INCLUDE "home/joypad.asm" INCLUDE "data/maps/map_header_pointers.asm" INCLUDE "home/overworld.asm" CheckForUserInterruption:: ; Return carry if Up+Select+B, Start or A are pressed in c frames. ; Used only in the intro and title screen. call DelayFrame push bc call JoypadLowSensitivity pop bc ldh a, [hJoyHeld] cp D_UP + SELECT + B_BUTTON jr z, .input ldh a, [hJoy5] and START | A_BUTTON jr nz, .input dec c jr nz, CheckForUserInterruption and a ret .input scf ret ; function to load position data for destination warp when switching maps ; INPUT: ; a = ID of destination warp within destination map LoadDestinationWarpPosition:: ld b, a ldh a, [hLoadedROMBank] push af ld a, [wPredefParentBank] ldh [hLoadedROMBank], a ld [MBC1RomBank], a ld a, b add a add a ld c, a ld b, 0 add hl, bc ld bc, 4 ld de, wCurrentTileBlockMapViewPointer call CopyData pop af ldh [hLoadedROMBank], a ld [MBC1RomBank], a ret INCLUDE "home/pokemon.asm" INCLUDE "home/print_bcd.asm" INCLUDE "home/pics.asm" INCLUDE "data/tilesets/collision_tile_ids.asm" INCLUDE "home/copy2.asm" INCLUDE "home/text.asm" INCLUDE "home/vcopy.asm" INCLUDE "home/init.asm" INCLUDE "home/vblank.asm" INCLUDE "home/fade.asm" INCLUDE "home/serial.asm" INCLUDE "home/timer.asm" INCLUDE "home/audio.asm" UpdateSprites:: ld a, [wUpdateSpritesEnabled] dec a ret nz ldh a, [hLoadedROMBank] push af ld a, BANK(_UpdateSprites) ldh [hLoadedROMBank], a ld [MBC1RomBank], a call _UpdateSprites pop af ldh [hLoadedROMBank], a ld [MBC1RomBank], a ret INCLUDE "data/items/marts.asm" INCLUDE "home/overworld_text.asm" INCLUDE "home/uncompress.asm" ResetPlayerSpriteData:: ld hl, wSpriteStateData1 call ResetPlayerSpriteData_ClearSpriteData ld hl, wSpriteStateData2 call ResetPlayerSpriteData_ClearSpriteData ld a, $1 ld [wSpritePlayerStateData1PictureID], a ld [wSpritePlayerStateData2ImageBaseOffset], a ld hl, wSpritePlayerStateData1YPixels ld [hl], $3c ; set Y screen pos inc hl inc hl ld [hl], $40 ; set X screen pos ret ; overwrites sprite data with zeroes ResetPlayerSpriteData_ClearSpriteData:: ld bc, $10 xor a jp FillMemory FadeOutAudio:: ld a, [wAudioFadeOutControl] and a ; currently fading out audio? jr nz, .fadingOut ld a, [wd72c] bit 1, a ret nz ld a, $77 ldh [rNR50], a ret .fadingOut ld a, [wAudioFadeOutCounter] and a jr z, .counterReachedZero dec a ld [wAudioFadeOutCounter], a ret .counterReachedZero ld a, [wAudioFadeOutCounterReloadValue] ld [wAudioFadeOutCounter], a ldh a, [rNR50] and a ; has the volume reached 0? jr z, .fadeOutComplete ld b, a and $f dec a ld c, a ld a, b and $f0 swap a dec a swap a or c ldh [rNR50], a ret .fadeOutComplete ld a, [wAudioFadeOutControl] ld b, a xor a ld [wAudioFadeOutControl], a ld a, SFX_STOP_ALL_MUSIC ld [wNewSoundID], a call PlaySound ld a, [wAudioSavedROMBank] ld [wAudioROMBank], a ld a, b ld [wNewSoundID], a jp PlaySound INCLUDE "home/text_script.asm" INCLUDE "home/start_menu.asm" ; function to count how many bits are set in a string of bytes ; INPUT: ; hl = address of string of bytes ; b = length of string of bytes ; OUTPUT: ; [wNumSetBits] = number of set bits CountSetBits:: ld c, 0 .loop ld a, [hli] ld e, a ld d, 8 .innerLoop ; count how many bits are set in the current byte srl e ld a, 0 adc c ld c, a dec d jr nz, .innerLoop dec b jr nz, .loop ld a, c ld [wNumSetBits], a ret ; subtracts the amount the player paid from their money ; OUTPUT: carry = 0(success) or 1(fail because there is not enough money) SubtractAmountPaidFromMoney:: jpba SubtractAmountPaidFromMoney_ ; adds the amount the player sold to their money AddAmountSoldToMoney:: ld de, wPlayerMoney + 2 ld hl, hMoney + 2 ; total price of items ld c, 3 ; length of money in bytes predef AddBCDPredef ; add total price to money ld a, MONEY_BOX ld [wTextBoxID], a call DisplayTextBoxID ; redraw money text box ld a, SFX_PURCHASE call PlaySoundWaitForCurrent jp WaitForSoundToFinish ; function to remove an item (in varying quantities) from the player's bag or PC box ; INPUT: ; HL = address of inventory (either wNumBagItems or wNumBoxItems) ; [wWhichPokemon] = index (within the inventory) of the item to remove ; [wItemQuantity] = quantity to remove RemoveItemFromInventory:: ldh a, [hLoadedROMBank] push af ld a, BANK(RemoveItemFromInventory_) ldh [hLoadedROMBank], a ld [MBC1RomBank], a call RemoveItemFromInventory_ pop af ldh [hLoadedROMBank], a ld [MBC1RomBank], a ret ; function to add an item (in varying quantities) to the player's bag or PC box ; INPUT: ; HL = address of inventory (either wNumBagItems or wNumBoxItems) ; [wcf91] = item ID ; [wItemQuantity] = item quantity ; sets carry flag if successful, unsets carry flag if unsuccessful AddItemToInventory:: push bc ldh a, [hLoadedROMBank] push af ld a, BANK(AddItemToInventory_) ldh [hLoadedROMBank], a ld [MBC1RomBank], a call AddItemToInventory_ pop bc ld a, b ldh [hLoadedROMBank], a ld [MBC1RomBank], a pop bc ret INCLUDE "home/list_menu.asm" INCLUDE "home/names.asm" ; reloads text box tile patterns, current map view, and tileset tile patterns ReloadMapData:: ldh a, [hLoadedROMBank] push af ld a, [wCurMap] call SwitchToMapRomBank call DisableLCD call LoadTextBoxTilePatterns call LoadCurrentMapView call LoadTilesetTilePatternData call EnableLCD pop af ldh [hLoadedROMBank], a ld [MBC1RomBank], a ret ; reloads tileset tile patterns ReloadTilesetTilePatterns:: ldh a, [hLoadedROMBank] push af ld a, [wCurMap] call SwitchToMapRomBank call DisableLCD call LoadTilesetTilePatternData call EnableLCD pop af ldh [hLoadedROMBank], a ld [MBC1RomBank], a ret ; shows the town map and lets the player choose a destination to fly to ChooseFlyDestination:: ld hl, wd72e res 4, [hl] jpba LoadTownMap_Fly ; causes the text box to close without waiting for a button press after displaying text DisableWaitingAfterTextDisplay:: ld a, $01 ld [wDoNotWaitForButtonPressAfterDisplayingText], a ret ; uses an item ; UseItem is used with dummy items to perform certain other functions as well ; INPUT: ; [wcf91] = item ID ; OUTPUT: ; [wActionResultOrTookBattleTurn] = success ; 00: unsuccessful ; 01: successful ; 02: not able to be used right now, no extra menu displayed (only certain items use this) UseItem:: jpba UseItem_ ; confirms the item toss and then tosses the item ; INPUT: ; hl = address of inventory (either wNumBagItems or wNumBoxItems) ; [wcf91] = item ID ; [wWhichPokemon] = index of item within inventory ; [wItemQuantity] = quantity to toss ; OUTPUT: ; clears carry flag if the item is tossed, sets carry flag if not TossItem:: ldh a, [hLoadedROMBank] push af ld a, BANK(TossItem_) ldh [hLoadedROMBank], a ld [MBC1RomBank], a call TossItem_ pop de ld a, d ldh [hLoadedROMBank], a ld [MBC1RomBank], a ret ; checks if an item is a key item ; INPUT: ; [wcf91] = item ID ; OUTPUT: ; [wIsKeyItem] = result ; 00: item is not key item ; 01: item is key item IsKeyItem:: push hl push de push bc callba IsKeyItem_ pop bc pop de pop hl ret ; function to draw various text boxes ; INPUT: ; [wTextBoxID] = text box ID ; b, c = y, x cursor position (TWO_OPTION_MENU only) DisplayTextBoxID:: ldh a, [hLoadedROMBank] push af ld a, BANK(DisplayTextBoxID_) ldh [hLoadedROMBank], a ld [MBC1RomBank], a call DisplayTextBoxID_ pop bc ld a, b ldh [hLoadedROMBank], a ld [MBC1RomBank], a ret ; not zero if an NPC movement script is running, the player character is ; automatically stepping down from a door, or joypad states are being simulated IsPlayerCharacterBeingControlledByGame:: ld a, [wNPCMovementScriptPointerTableNum] and a ret nz ld a, [wd736] bit 1, a ; currently stepping down from door bit ret nz ld a, [wd730] and $80 ret RunNPCMovementScript:: ld hl, wd736 bit 0, [hl] res 0, [hl] jr nz, .playerStepOutFromDoor ld a, [wNPCMovementScriptPointerTableNum] and a ret z dec a add a ld d, 0 ld e, a ld hl, .NPCMovementScriptPointerTables add hl, de ld a, [hli] ld h, [hl] ld l, a ldh a, [hLoadedROMBank] push af ld a, [wNPCMovementScriptBank] ldh [hLoadedROMBank], a ld [MBC1RomBank], a ld a, [wNPCMovementScriptFunctionNum] call CallFunctionInTable pop af ldh [hLoadedROMBank], a ld [MBC1RomBank], a ret .NPCMovementScriptPointerTables dw PalletMovementScriptPointerTable dw PewterMuseumGuyMovementScriptPointerTable dw PewterGymGuyMovementScriptPointerTable .playerStepOutFromDoor jpba PlayerStepOutFromDoor EndNPCMovementScript:: jpba _EndNPCMovementScript EmptyFunc2:: ret INCLUDE "home/trainers.asm" ; checks if the player's coordinates match an arrow movement tile's coordinates ; and if so, decodes the RLE movement data ; b = player Y ; c = player X DecodeArrowMovementRLE:: ld a, [hli] cp $ff ret z ; no match in the list cp b jr nz, .nextArrowMovementTileEntry1 ld a, [hli] cp c jr nz, .nextArrowMovementTileEntry2 ld a, [hli] ld d, [hl] ld e, a ld hl, wSimulatedJoypadStatesEnd call DecodeRLEList dec a ld [wSimulatedJoypadStatesIndex], a ret .nextArrowMovementTileEntry1 inc hl .nextArrowMovementTileEntry2 inc hl inc hl jr DecodeArrowMovementRLE TextScript_ItemStoragePC:: call SaveScreenTilesToBuffer2 ld b, BANK(PlayerPC) ld hl, PlayerPC jr bankswitchAndContinue TextScript_BillsPC:: call SaveScreenTilesToBuffer2 ld b, BANK(BillsPC_) ld hl, BillsPC_ jr bankswitchAndContinue TextScript_GameCornerPrizeMenu:: ; XXX find a better name for this function ; special_F7 ld b, BANK(CeladonPrizeMenu) ld hl, CeladonPrizeMenu bankswitchAndContinue:: call Bankswitch jp HoldTextDisplayOpen ; continue to main text-engine function TextScript_PokemonCenterPC:: ld b, BANK(ActivatePC) ld hl, ActivatePC jr bankswitchAndContinue StartSimulatingJoypadStates:: xor a ld [wOverrideSimulatedJoypadStatesMask], a ld [wSpritePlayerStateData2MovementByte1], a ld hl, wd730 set 7, [hl] ret IsItemInBag:: ; given an item_id in b ; set zero flag if item isn't in player's bag ; else reset zero flag ; related to Pokémon Tower and ghosts predef GetQuantityOfItemInBag ld a, b and a ret DisplayPokedex:: ld [wd11e], a jpba _DisplayPokedex SetSpriteFacingDirectionAndDelay:: call SetSpriteFacingDirection ld c, 6 jp DelayFrames SetSpriteFacingDirection:: ld a, $9 ldh [hSpriteDataOffset], a call GetPointerWithinSpriteStateData1 ldh a, [hSpriteFacingDirection] ld [hl], a ret SetSpriteImageIndexAfterSettingFacingDirection:: ld de, -7 add hl, de ld [hl], a ret ; tests if the player's coordinates are in a specified array ; INPUT: ; hl = address of array ; OUTPUT: ; [wCoordIndex] = if there is match, the matching array index ; sets carry if the coordinates are in the array, clears carry if not ArePlayerCoordsInArray:: ld a, [wYCoord] ld b, a ld a, [wXCoord] ld c, a ; fallthrough CheckCoords:: xor a ld [wCoordIndex], a .loop ld a, [hli] cp $ff ; reached terminator? jr z, .notInArray push hl ld hl, wCoordIndex inc [hl] pop hl .compareYCoord cp b jr z, .compareXCoord inc hl jr .loop .compareXCoord ld a, [hli] cp c jr nz, .loop .inArray scf ret .notInArray and a ret ; tests if a boulder's coordinates are in a specified array ; INPUT: ; hl = address of array ; [hSpriteIndex] = index of boulder sprite ; OUTPUT: ; [wCoordIndex] = if there is match, the matching array index ; sets carry if the coordinates are in the array, clears carry if not CheckBoulderCoords:: push hl ld hl, wSpritePlayerStateData2MapY ldh a, [hSpriteIndex] swap a ld d, $0 ld e, a add hl, de ld a, [hli] sub $4 ; because sprite coordinates are offset by 4 ld b, a ld a, [hl] sub $4 ; because sprite coordinates are offset by 4 ld c, a pop hl jp CheckCoords GetPointerWithinSpriteStateData1:: ld h, $c1 jr _GetPointerWithinSpriteStateData GetPointerWithinSpriteStateData2:: ld h, $c2 _GetPointerWithinSpriteStateData: ldh a, [hSpriteDataOffset] ld b, a ldh a, [hSpriteIndex] swap a add b ld l, a ret ; decodes a $ff-terminated RLEncoded list ; each entry is a pair of bytes ; the final $ff will be replicated in the output list and a contains the number of bytes written ; de: input list ; hl: output list DecodeRLEList:: xor a ld [wRLEByteCount], a ; count written bytes here .listLoop ld a, [de] cp $ff jr z, .endOfList ldh [hRLEByteValue], a ; store byte value to be written inc de ld a, [de] ld b, $0 ld c, a ; number of bytes to be written ld a, [wRLEByteCount] add c ld [wRLEByteCount], a ; update total number of written bytes ldh a, [hRLEByteValue] call FillMemory ; write a c-times to output inc de jr .listLoop .endOfList ld a, $ff ld [hl], a ; write final $ff ld a, [wRLEByteCount] inc a ; include sentinel in counting ret ; sets movement byte 1 for sprite [hSpriteIndex] to $FE and byte 2 to [hSpriteMovementByte2] SetSpriteMovementBytesToFE:: push hl call GetSpriteMovementByte1Pointer ld [hl], $fe call GetSpriteMovementByte2Pointer ldh a, [hSpriteMovementByte2] ld [hl], a pop hl ret ; sets both movement bytes for sprite [hSpriteIndex] to $FF SetSpriteMovementBytesToFF:: push hl call GetSpriteMovementByte1Pointer ld [hl], $FF call GetSpriteMovementByte2Pointer ld [hl], $FF ; prevent person from walking? pop hl ret ; returns the sprite movement byte 1 pointer for sprite [hSpriteIndex] in hl GetSpriteMovementByte1Pointer:: ld h, $C2 ldh a, [hSpriteIndex] swap a add 6 ld l, a ret ; returns the sprite movement byte 2 pointer for sprite [hSpriteIndex] in hl GetSpriteMovementByte2Pointer:: push de ld hl, wMapSpriteData ldh a, [hSpriteIndex] dec a add a ld d, 0 ld e, a add hl, de pop de ret GetTrainerInformation:: call GetTrainerName ld a, [wLinkState] and a jr nz, .linkBattle ld a, BANK(TrainerPicAndMoneyPointers) call BankswitchHome ld a, [wTrainerClass] dec a ld hl, TrainerPicAndMoneyPointers ld bc, $5 call AddNTimes ld de, wTrainerPicPointer ld a, [hli] ld [de], a inc de ld a, [hli] ld [de], a ld de, wTrainerBaseMoney ld a, [hli] ld [de], a inc de ld a, [hli] ld [de], a jp BankswitchBack .linkBattle ld hl, wTrainerPicPointer ld de, RedPicFront ld [hl], e inc hl ld [hl], d ret GetTrainerName:: jpba GetTrainerName_ HasEnoughMoney:: ; Check if the player has at least as much ; money as the 3-byte BCD value at hMoney. ld de, wPlayerMoney ld hl, hMoney ld c, 3 jp StringCmp HasEnoughCoins:: ; Check if the player has at least as many ; coins as the 2-byte BCD value at hCoins. ld de, wPlayerCoins ld hl, hCoins ld c, 2 jp StringCmp INCLUDE "home/bankswitch.asm" INCLUDE "home/yes_no.asm" ; calculates the difference |a-b|, setting carry flag if a