Move all code out of home.asm into home/

This results in 64 home/*.asm files, comparable to pokecrystal's 57.
This commit is contained in:
Rangi 2020-07-07 18:50:58 -04:00
parent 51ac538c25
commit bbf2f51a02
35 changed files with 1754 additions and 1758 deletions

1795
home.asm

File diff suppressed because it is too large Load diff

21
home/array.asm Normal file
View file

@ -0,0 +1,21 @@
; skips a text entries, each of size NAME_LENGTH (like trainer name, OT name, rival name, ...)
; hl: base pointer, will be incremented by NAME_LENGTH * a
SkipFixedLengthTextEntries::
and a
ret z
ld bc, NAME_LENGTH
.skipLoop
add hl, bc
dec a
jr nz, .skipLoop
ret
AddNTimes::
; add bc to hl a times
and a
ret z
.loop
add hl, bc
dec a
jr nz, .loop
ret

47
home/array2.asm Normal file
View file

@ -0,0 +1,47 @@
CallFunctionInTable::
; Call function a in jumptable hl.
; de is not preserved.
push hl
push de
push bc
add a
ld d, 0
ld e, a
add hl, de
ld a, [hli]
ld h, [hl]
ld l, a
ld de, .returnAddress
push de
jp hl
.returnAddress
pop bc
pop de
pop hl
ret
IsInArray::
; Search an array at hl for the value in a.
; Entry size is de bytes.
; Return count b and carry if found.
ld b, 0
IsInRestOfArray::
ld c, a
.loop
ld a, [hl]
cp -1
jr z, .notfound
cp c
jr z, .found
inc b
add hl, de
jr .loop
.notfound
and a
ret
.found
scf
ret

11
home/compare.asm Normal file
View file

@ -0,0 +1,11 @@
; Compare strings, c bytes in length, at de and hl.
; Often used to compare big endian numbers in battle calculations.
StringCmp::
ld a, [de]
cp [hl]
ret nz
inc de
inc hl
dec c
jr nz, StringCmp
ret

13
home/copy_string.asm Normal file
View file

@ -0,0 +1,13 @@
; copies a string from [de] to [wcf4b]
CopyStringToCF4B::
ld hl, wcf4b
; fall through
; copies a string from [de] to [hl]
CopyString::
ld a, [de]
inc de
ld [hli], a
cp "@"
jr nz, CopyString
ret

24
home/count_set_bits.asm Normal file
View file

@ -0,0 +1,24 @@
; 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

31
home/delay.asm Normal file
View file

@ -0,0 +1,31 @@
DelayFrames::
; wait c frames
call DelayFrame
dec c
jr nz, DelayFrames
ret
PlaySoundWaitForCurrent::
push af
call WaitForSoundToFinish
pop af
jp PlaySound
; Wait for sound to finish playing
WaitForSoundToFinish::
ld a, [wLowHealthAlarm]
and $80
ret nz
push hl
.waitLoop
ld hl, wChannelSoundIDs + Ch5
xor a
or [hl]
inc hl
or [hl]
inc hl
inc hl
or [hl]
jr nz, .waitLoop
pop hl
ret

48
home/fade_audio.asm Normal file
View file

@ -0,0 +1,48 @@
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

26
home/give.asm Normal file
View file

@ -0,0 +1,26 @@
GiveItem::
; Give player quantity c of item b,
; and copy the item's name to wcf4b.
; Return carry on success.
ld a, b
ld [wd11e], a
ld [wcf91], a
ld a, c
ld [wItemQuantity], a
ld hl, wNumBagItems
call AddItemToInventory
ret nc
call GetItemName
call CopyStringToCF4B
scf
ret
GivePokemon::
; Give the player monster b at level c.
ld a, b
ld [wcf91], a
ld a, c
ld [wCurEnemyLVL], a
xor a ; PLAYER_PARTY_DATA
ld [wMonDataLocation], a
farjp _GivePokemon

39
home/hidden_objects.asm Normal file
View file

@ -0,0 +1,39 @@
UpdateCinnabarGymGateTileBlocks::
farjp UpdateCinnabarGymGateTileBlocks_
CheckForHiddenObjectOrBookshelfOrCardKeyDoor::
ldh a, [hLoadedROMBank]
push af
ldh a, [hJoyHeld]
bit 0, a ; A button
jr z, .nothingFound
; A button is pressed
ld a, BANK(CheckForHiddenObject)
ld [MBC1RomBank], a
ldh [hLoadedROMBank], a
call CheckForHiddenObject
ldh a, [hDidntFindAnyHiddenObject]
and a
jr nz, .hiddenObjectNotFound
ld a, [wHiddenObjectFunctionRomBank]
ld [MBC1RomBank], a
ldh [hLoadedROMBank], a
ld de, .returnAddress
push de
jp hl
.returnAddress
xor a
jr .done
.hiddenObjectNotFound
farcall PrintBookshelfText
ldh a, [hFFDB]
and a
jr z, .done
.nothingFound
ld a, $ff
.done
ldh [hItemAlreadyFound], a
pop af
ld [MBC1RomBank], a
ldh [hLoadedROMBank], a
ret

55
home/inventory.asm Normal file
View file

@ -0,0 +1,55 @@
; subtracts the amount the player paid from their money
; OUTPUT: carry = 0(success) or 1(fail because there is not enough money)
SubtractAmountPaidFromMoney::
farjp 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

49
home/item.asm Normal file
View file

@ -0,0 +1,49 @@
; 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::
farjp 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
farcall IsKeyItem_
pop bc
pop de
pop hl
ret

44
home/item_price.asm Normal file
View file

@ -0,0 +1,44 @@
GetItemPrice::
; Stores item's price as BCD at hItemPrice (3 bytes)
; Input: [wcf91] = item id
ldh a, [hLoadedROMBank]
push af
ld a, [wListMenuID]
cp MOVESLISTMENU
ld a, BANK(ItemPrices)
jr nz, .ok
ld a, $f ; hardcoded Bank
.ok
ldh [hLoadedROMBank], a
ld [MBC1RomBank], a
ld hl, wItemPrices
ld a, [hli]
ld h, [hl]
ld l, a
ld a, [wcf91] ; a contains item id
cp HM01
jr nc, .getTMPrice
ld bc, $3
.loop
add hl, bc
dec a
jr nz, .loop
dec hl
ld a, [hld]
ldh [hItemPrice + 2], a
ld a, [hld]
ldh [hItemPrice + 1], a
ld a, [hl]
ldh [hItemPrice], a
jr .done
.getTMPrice
ld a, BANK(GetMachinePrice)
ldh [hLoadedROMBank], a
ld [MBC1RomBank], a
call GetMachinePrice
.done
ld de, hItemPrice
pop af
ldh [hLoadedROMBank], a
ld [MBC1RomBank], a
ret

95
home/joypad2.asm Normal file
View file

@ -0,0 +1,95 @@
; this function is used when lower button sensitivity is wanted (e.g. menus)
; OUTPUT: [hJoy5] = pressed buttons in usual format
; there are two flags that control its functionality, [hJoy6] and [hJoy7]
; there are essentially three modes of operation
; 1. Get newly pressed buttons only
; ([hJoy7] == 0, [hJoy6] == any)
; Just copies [hJoyPressed] to [hJoy5].
; 2. Get currently pressed buttons at low sample rate with delay
; ([hJoy7] == 1, [hJoy6] != 0)
; If the user holds down buttons for more than half a second,
; report buttons as being pressed up to 12 times per second thereafter.
; If the user holds down buttons for less than half a second,
; report only one button press.
; 3. Same as 2, but report no buttons as pressed if A or B is held down.
; ([hJoy7] == 1, [hJoy6] == 0)
JoypadLowSensitivity::
call Joypad
ldh a, [hJoy7] ; flag
and a ; get all currently pressed buttons or only newly pressed buttons?
ldh a, [hJoyPressed] ; newly pressed buttons
jr z, .storeButtonState
ldh a, [hJoyHeld] ; all currently pressed buttons
.storeButtonState
ldh [hJoy5], a
ldh a, [hJoyPressed] ; newly pressed buttons
and a ; have any buttons been newly pressed since last check?
jr z, .noNewlyPressedButtons
.newlyPressedButtons
ld a, 30 ; half a second delay
ldh [hFrameCounter], a
ret
.noNewlyPressedButtons
ldh a, [hFrameCounter]
and a ; is the delay over?
jr z, .delayOver
.delayNotOver
xor a
ldh [hJoy5], a ; report no buttons as pressed
ret
.delayOver
; if [hJoy6] = 0 and A or B is pressed, report no buttons as pressed
ldh a, [hJoyHeld]
and A_BUTTON | B_BUTTON
jr z, .setShortDelay
ldh a, [hJoy6] ; flag
and a
jr nz, .setShortDelay
xor a
ldh [hJoy5], a
.setShortDelay
ld a, 5 ; 1/12 of a second delay
ldh [hFrameCounter], a
ret
WaitForTextScrollButtonPress::
ldh a, [hDownArrowBlinkCount1]
push af
ldh a, [hDownArrowBlinkCount2]
push af
xor a
ldh [hDownArrowBlinkCount1], a
ld a, $6
ldh [hDownArrowBlinkCount2], a
.loop
push hl
ld a, [wTownMapSpriteBlinkingEnabled]
and a
jr z, .skipAnimation
call TownMapSpriteBlinkingAnimation
.skipAnimation
hlcoord 18, 16
call HandleDownArrowBlinkTiming
pop hl
call JoypadLowSensitivity
predef CableClub_Run
ldh a, [hJoy5]
and A_BUTTON | B_BUTTON
jr z, .loop
pop af
ldh [hDownArrowBlinkCount2], a
pop af
ldh [hDownArrowBlinkCount1], a
ret
; (unless in link battle) waits for A or B being pressed and outputs the scrolling sound effect
ManualTextScroll::
ld a, [wLinkState]
cp LINK_STATE_BATTLING
jr z, .inLinkBattle
call WaitForTextScrollButtonPress
ld a, SFX_PRESS_AB
jp PlaySound
.inLinkBattle
ld c, 65
jp DelayFrames

47
home/load_font.asm Normal file
View file

@ -0,0 +1,47 @@
LoadFontTilePatterns::
ldh a, [rLCDC]
bit 7, a ; is the LCD enabled?
jr nz, .on
.off
ld hl, FontGraphics
ld de, vFont
ld bc, FontGraphicsEnd - FontGraphics
ld a, BANK(FontGraphics)
jp FarCopyDataDouble ; if LCD is off, transfer all at once
.on
ld de, FontGraphics
ld hl, vFont
lb bc, BANK(FontGraphics), (FontGraphicsEnd - FontGraphics) / $8
jp CopyVideoDataDouble ; if LCD is on, transfer during V-blank
LoadTextBoxTilePatterns::
ldh a, [rLCDC]
bit 7, a ; is the LCD enabled?
jr nz, .on
.off
ld hl, TextBoxGraphics
ld de, vChars2 tile $60
ld bc, TextBoxGraphicsEnd - TextBoxGraphics
ld a, BANK(TextBoxGraphics)
jp FarCopyData2 ; if LCD is off, transfer all at once
.on
ld de, TextBoxGraphics
ld hl, vChars2 tile $60
lb bc, BANK(TextBoxGraphics), (TextBoxGraphicsEnd - TextBoxGraphics) / $10
jp CopyVideoData ; if LCD is on, transfer during V-blank
LoadHpBarAndStatusTilePatterns::
ldh a, [rLCDC]
bit 7, a ; is the LCD enabled?
jr nz, .on
.off
ld hl, HpBarAndStatusGraphics
ld de, vChars2 tile $62
ld bc, HpBarAndStatusGraphicsEnd - HpBarAndStatusGraphics
ld a, BANK(HpBarAndStatusGraphics)
jp FarCopyData2 ; if LCD is off, transfer all at once
.on
ld de, HpBarAndStatusGraphics
ld hl, vChars2 tile $62
lb bc, BANK(HpBarAndStatusGraphics), (HpBarAndStatusGraphicsEnd - HpBarAndStatusGraphics) / $10
jp CopyVideoData ; if LCD is on, transfer during V-blank

248
home/map_objects.asm Normal file
View file

@ -0,0 +1,248 @@
; 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
farjp _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 <byte value> <repetitions>
; 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

41
home/math.asm Normal file
View file

@ -0,0 +1,41 @@
; function to do multiplication
; all values are big endian
; INPUT
; FF96-FF98 = multiplicand
; FF99 = multiplier
; OUTPUT
; FF95-FF98 = product
Multiply::
push hl
push bc
callfar _Multiply
pop bc
pop hl
ret
; function to do division
; all values are big endian
; INPUT
; FF95-FF98 = dividend
; FF99 = divisor
; b = number of bytes in the dividend (starting from FF95)
; OUTPUT
; FF95-FF98 = quotient
; FF99 = remainder
Divide::
push hl
push de
push bc
ldh a, [hLoadedROMBank]
push af
ld a, BANK(_Divide)
ldh [hLoadedROMBank], a
ld [MBC1RomBank], a
call _Divide
pop af
ldh [hLoadedROMBank], a
ld [MBC1RomBank], a
pop bc
pop de
pop hl
ret

15
home/money.asm Normal file
View file

@ -0,0 +1,15 @@
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

View file

@ -1,3 +1,18 @@
; Copies [hl, bc) to [de, de + bc - hl).
; In other words, the source data is from hl up to but not including bc,
; and the destination is de.
CopyDataUntil::
ld a, [hli]
ld [de], a
inc de
ld a, h
cp b
jr nz, CopyDataUntil
ld a, l
cp c
jr nz, CopyDataUntil
ret
; Function to remove a pokemon from the party or the current box. ; Function to remove a pokemon from the party or the current box.
; wWhichPokemon determines the pokemon. ; wWhichPokemon determines the pokemon.
; [wRemoveMonFromBox] == 0 specifies the party. ; [wRemoveMonFromBox] == 0 specifies the party.

54
home/npc_movement.asm Normal file
View file

@ -0,0 +1,54 @@
; 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
farjp PlayerStepOutFromDoor
EndNPCMovementScript::
farjp _EndNPCMovementScript
EmptyFunc2::
ret

36
home/oam.asm Normal file
View file

@ -0,0 +1,36 @@
; INPUT:
; a = oam block index (each block is 4 oam entries)
; b = Y coordinate of upper left corner of sprite
; c = X coordinate of upper left corner of sprite
; de = base address of 4 tile number and attribute pairs
WriteOAMBlock::
ld h, HIGH(wOAMBuffer)
swap a ; multiply by 16
ld l, a
call .writeOneEntry ; upper left
push bc
ld a, 8
add c
ld c, a
call .writeOneEntry ; upper right
pop bc
ld a, 8
add b
ld b, a
call .writeOneEntry ; lower left
ld a, 8
add c
ld c, a
; lower right
.writeOneEntry
ld [hl], b ; Y coordinate
inc hl
ld [hl], c ; X coordinate
inc hl
ld a, [de] ; tile number
inc de
ld [hli], a
ld a, [de] ; attribute
inc de
ld [hli], a
ret

View file

@ -2421,3 +2421,54 @@ ForceBikeOrSurf::
ld hl, LoadPlayerSpriteGraphics ld hl, LoadPlayerSpriteGraphics
call Bankswitch call Bankswitch
jp PlayDefaultMusic ; update map/player state? jp PlayDefaultMusic ; update map/player state?
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

57
home/palettes.asm Normal file
View file

@ -0,0 +1,57 @@
RestoreScreenTilesAndReloadTilePatterns::
call ClearSprites
ld a, $1
ld [wUpdateSpritesEnabled], a
call ReloadMapSpriteTilePatterns
call LoadScreenTilesFromBuffer2
call LoadTextBoxTilePatterns
call RunDefaultPaletteCommand
jr Delay3
GBPalWhiteOutWithDelay3::
call GBPalWhiteOut
Delay3::
; The bg map is updated each frame in thirds.
; Wait three frames to let the bg map fully update.
ld c, 3
jp DelayFrames
GBPalNormal::
; Reset BGP and OBP0.
ld a, %11100100 ; 3210
ldh [rBGP], a
ld a, %11010000 ; 3100
ldh [rOBP0], a
ret
GBPalWhiteOut::
; White out all palettes.
xor a
ldh [rBGP], a
ldh [rOBP0], a
ldh [rOBP1], a
ret
RunDefaultPaletteCommand::
ld b, SET_PAL_DEFAULT
RunPaletteCommand::
ld a, [wOnSGB]
and a
ret z
predef_jump _RunPaletteCommand
GetHealthBarColor::
; Return at hl the palette of
; an HP bar e pixels long.
ld a, e
cp 27
ld d, 0 ; green
jr nc, .gotColor
cp 10
inc d ; yellow
jr nc, .gotColor
inc d ; red
.gotColor
ld [hl], d
ret

65
home/pathfinding.asm Normal file
View file

@ -0,0 +1,65 @@
; calculates the difference |a-b|, setting carry flag if a<b
CalcDifference::
sub b
ret nc
cpl
add $1
scf
ret
MoveSprite::
; move the sprite [hSpriteIndex] with the movement pointed to by de
; actually only copies the movement data to wNPCMovementDirections for later
call SetSpriteMovementBytesToFF
MoveSprite_::
push hl
push bc
call GetSpriteMovementByte1Pointer
xor a
ld [hl], a
ld hl, wNPCMovementDirections
ld c, 0
.loop
ld a, [de]
ld [hli], a
inc de
inc c
cp $FF ; have we reached the end of the movement data?
jr nz, .loop
ld a, c
ld [wNPCNumScriptedSteps], a ; number of steps taken
pop bc
ld hl, wd730
set 0, [hl]
pop hl
xor a
ld [wOverrideSimulatedJoypadStatesMask], a
ld [wSimulatedJoypadStatesEnd], a
dec a
ld [wJoyIgnore], a
ld [wWastedByteCD3A], a
ret
; divides [hDividend2] by [hDivisor2] and stores the quotient in [hQuotient2]
DivideBytes::
push hl
ld hl, hQuotient2
xor a
ld [hld], a
ld a, [hld]
and a
jr z, .done
ld a, [hli]
.loop
sub [hl]
jr c, .done
inc hl
inc [hl]
dec hl
jr .loop
.done
pop hl
ret

28
home/predef_text.asm Normal file
View file

@ -0,0 +1,28 @@
PrintPredefTextID::
ldh [hSpriteIndexOrTextID], a
ld hl, TextPredefs
call SetMapTextPointer
ld hl, wTextPredefFlag
set 0, [hl]
call DisplayTextID
RestoreMapTextPointer::
ld hl, wMapTextPtr
ldh a, [hSavedMapTextPtr]
ld [hli], a
ldh a, [hSavedMapTextPtr + 1]
ld [hl], a
ret
SetMapTextPointer::
ld a, [wMapTextPtr]
ldh [hSavedMapTextPtr], a
ld a, [wMapTextPtr + 1]
ldh [hSavedMapTextPtr + 1], a
ld a, l
ld [wMapTextPtr], a
ld a, h
ld [wMapTextPtr + 1], a
ret
INCLUDE "data/text_predef_pointers.asm"

45
home/print_text.asm Normal file
View file

@ -0,0 +1,45 @@
; This function is used to wait a short period after printing a letter to the
; screen unless the player presses the A/B button or the delay is turned off
; through the [wd730] or [wLetterPrintingDelayFlags] flags.
PrintLetterDelay::
ld a, [wd730]
bit 6, a
ret nz
ld a, [wLetterPrintingDelayFlags]
bit 1, a
ret z
push hl
push de
push bc
ld a, [wLetterPrintingDelayFlags]
bit 0, a
jr z, .waitOneFrame
ld a, [wOptions]
and $f
ldh [hFrameCounter], a
jr .checkButtons
.waitOneFrame
ld a, 1
ldh [hFrameCounter], a
.checkButtons
call Joypad
ldh a, [hJoyHeld]
.checkAButton
bit 0, a ; is the A button pressed?
jr z, .checkBButton
jr .endWait
.checkBButton
bit 1, a ; is the B button pressed?
jr z, .buttonsNotPressed
.endWait
call DelayFrame
jr .done
.buttonsNotPressed ; if neither A nor B is pressed
ldh a, [hFrameCounter]
and a
jr nz, .checkButtons
.done
pop bc
pop de
pop hl
ret

12
home/random.asm Normal file
View file

@ -0,0 +1,12 @@
Random::
; Return a random number in a.
; For battles, use BattleRandom.
push hl
push de
push bc
farcall Random_
ldh a, [hRandomAdd]
pop bc
pop de
pop hl
ret

19
home/reload_sprites.asm Normal file
View file

@ -0,0 +1,19 @@
; Copy the current map's sprites' tile patterns to VRAM again after they have
; been overwritten by other tile patterns.
ReloadMapSpriteTilePatterns::
ld hl, wFontLoaded
ld a, [hl]
push af
res 0, [hl]
push hl
xor a
ld [wSpriteSetID], a
call DisableLCD
farcall InitMapSprites
call EnableLCD
pop hl
pop af
ld [hl], a
call LoadPlayerSpriteGraphics
call LoadFontTilePatterns
jp UpdateSprites

41
home/reload_tiles.asm Normal file
View file

@ -0,0 +1,41 @@
; 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]
farjp 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

View file

@ -0,0 +1,20 @@
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

16
home/textbox.asm Normal file
View file

@ -0,0 +1,16 @@
; 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

61
home/tilemap.asm Normal file
View file

@ -0,0 +1,61 @@
FillMemory::
; Fill bc bytes at hl with a.
push de
ld d, a
.loop
ld a, d
ld [hli], a
dec bc
ld a, b
or c
jr nz, .loop
pop de
ret
UncompressSpriteFromDE::
; Decompress pic at a:de.
ld hl, wSpriteInputPtr
ld [hl], e
inc hl
ld [hl], d
jp UncompressSpriteData
SaveScreenTilesToBuffer2::
hlcoord 0, 0
ld de, wTileMapBackup2
ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
call CopyData
ret
LoadScreenTilesFromBuffer2::
call LoadScreenTilesFromBuffer2DisableBGTransfer
ld a, 1
ldh [hAutoBGTransferEnabled], a
ret
; loads screen tiles stored in wTileMapBackup2 but leaves hAutoBGTransferEnabled disabled
LoadScreenTilesFromBuffer2DisableBGTransfer::
xor a
ldh [hAutoBGTransferEnabled], a
ld hl, wTileMapBackup2
decoord 0, 0
ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
call CopyData
ret
SaveScreenTilesToBuffer1::
hlcoord 0, 0
ld de, wTileMapBackup
ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
jp CopyData
LoadScreenTilesFromBuffer1::
xor a
ldh [hAutoBGTransferEnabled], a
ld hl, wTileMapBackup
decoord 0, 0
ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
call CopyData
ld a, 1
ldh [hAutoBGTransferEnabled], a
ret

35
home/trainers2.asm Normal file
View file

@ -0,0 +1,35 @@
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::
farjp GetTrainerName_

14
home/update_sprites.asm Normal file
View file

@ -0,0 +1,14 @@
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

294
home/window.asm Normal file
View file

@ -0,0 +1,294 @@
HandleMenuInput::
xor a
ld [wPartyMenuAnimMonEnabled], a
HandleMenuInput_::
ldh a, [hDownArrowBlinkCount1]
push af
ldh a, [hDownArrowBlinkCount2]
push af ; save existing values on stack
xor a
ldh [hDownArrowBlinkCount1], a ; blinking down arrow timing value 1
ld a, 6
ldh [hDownArrowBlinkCount2], a ; blinking down arrow timing value 2
.loop1
xor a
ld [wAnimCounter], a ; counter for pokemon shaking animation
call PlaceMenuCursor
call Delay3
.loop2
push hl
ld a, [wPartyMenuAnimMonEnabled]
and a ; is it a pokemon selection menu?
jr z, .getJoypadState
farcall AnimatePartyMon ; shake mini sprite of selected pokemon
.getJoypadState
pop hl
call JoypadLowSensitivity
ldh a, [hJoy5]
and a ; was a key pressed?
jr nz, .keyPressed
push hl
hlcoord 18, 11 ; coordinates of blinking down arrow in some menus
call HandleDownArrowBlinkTiming ; blink down arrow (if any)
pop hl
ld a, [wMenuJoypadPollCount]
dec a
jr z, .giveUpWaiting
jr .loop2
.giveUpWaiting
; if a key wasn't pressed within the specified number of checks
pop af
ldh [hDownArrowBlinkCount2], a
pop af
ldh [hDownArrowBlinkCount1], a ; restore previous values
xor a
ld [wMenuWrappingEnabled], a ; disable menu wrapping
ret
.keyPressed
xor a
ld [wCheckFor180DegreeTurn], a
ldh 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, .alreadyAtTop
.notAtTop
dec a
ld [wCurrentMenuItem], a ; move selected menu item up one space
jr .checkOtherKeys
.alreadyAtTop
ld a, [wMenuWrappingEnabled]
and a ; is wrapping around enabled?
jr z, .noWrappingAround
ld a, [wMaxMenuItem]
ld [wCurrentMenuItem], a ; wrap to the bottom of the menu
jr .checkOtherKeys
.checkIfDownPressed
bit 7, a
jr z, .checkOtherKeys
.downPressed
ld a, [wCurrentMenuItem]
inc a
ld c, a
ld a, [wMaxMenuItem]
cp c
jr nc, .notAtBottom
.alreadyAtBottom
ld a, [wMenuWrappingEnabled]
and a ; is wrapping around enabled?
jr z, .noWrappingAround
ld c, $00 ; wrap from bottom to top
.notAtBottom
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
ldh a, [hJoy5]
and A_BUTTON | B_BUTTON
jr z, .skipPlayingSound
.AButtonOrBButtonPressed
push hl
ld hl, wFlags_0xcd60
bit 5, [hl]
pop hl
jr nz, .skipPlayingSound
ld a, SFX_PRESS_AB
call PlaySound
.skipPlayingSound
pop af
ldh [hDownArrowBlinkCount2], a
pop af
ldh [hDownArrowBlinkCount1], a ; restore previous values
xor a
ld [wMenuWrappingEnabled], a ; disable menu wrapping
ldh a, [hJoy5]
ret
.noWrappingAround
ld a, [wMenuWatchMovingOutOfBounds]
and a ; should we return if the user tried to go past the top or bottom?
jr z, .checkOtherKeys
jr .checkIfAButtonOrBButtonPressed
PlaceMenuCursor::
ld a, [wTopMenuItemY]
and a ; is the y coordinate 0?
jr z, .adjustForXCoord
hlcoord 0, 0
ld bc, SCREEN_WIDTH
.topMenuItemLoop
add hl, bc
dec a
jr nz, .topMenuItemLoop
.adjustForXCoord
ld a, [wTopMenuItemX]
ld b, 0
ld c, a
add hl, bc
push hl
ld a, [wLastMenuItem]
and a ; was the previous menu id 0?
jr z, .checkForArrow1
push af
ldh a, [hFlagsFFF6]
bit 1, a ; is the menu double spaced?
jr z, .doubleSpaced1
ld bc, 20
jr .getOldMenuItemScreenPosition
.doubleSpaced1
ld bc, 40
.getOldMenuItemScreenPosition
pop af
.oldMenuItemLoop
add hl, bc
dec a
jr nz, .oldMenuItemLoop
.checkForArrow1
ld a, [hl]
cp "▶" ; was an arrow next to the previously selected menu item?
jr nz, .skipClearingArrow
.clearArrow
ld a, [wTileBehindCursor]
ld [hl], a
.skipClearingArrow
pop hl
ld a, [wCurrentMenuItem]
and a
jr z, .checkForArrow2
push af
ldh a, [hFlagsFFF6]
bit 1, a ; is the menu double spaced?
jr z, .doubleSpaced2
ld bc, 20
jr .getCurrentMenuItemScreenPosition
.doubleSpaced2
ld bc, 40
.getCurrentMenuItemScreenPosition
pop af
.currentMenuItemLoop
add hl, bc
dec a
jr nz, .currentMenuItemLoop
.checkForArrow2
ld a, [hl]
cp "▶" ; has the right arrow already been placed?
jr z, .skipSavingTile ; if so, don't lose the saved tile
ld [wTileBehindCursor], a ; save tile before overwriting with right arrow
.skipSavingTile
ld a, "▶" ; place right arrow
ld [hl], a
ld a, l
ld [wMenuCursorLocation], a
ld a, h
ld [wMenuCursorLocation + 1], a
ld a, [wCurrentMenuItem]
ld [wLastMenuItem], a
ret
; This is used to mark a menu cursor other than the one currently being
; manipulated. In the case of submenus, this is used to show the location of
; the menu cursor in the parent menu. In the case of swapping items in list,
; this is used to mark the item that was first chosen to be swapped.
PlaceUnfilledArrowMenuCursor::
ld b, a
ld a, [wMenuCursorLocation]
ld l, a
ld a, [wMenuCursorLocation + 1]
ld h, a
ld [hl], $ec ; outline of right arrow
ld a, b
ret
; Replaces the menu cursor with a blank space.
EraseMenuCursor::
ld a, [wMenuCursorLocation]
ld l, a
ld a, [wMenuCursorLocation + 1]
ld h, a
ld [hl], " "
ret
; This toggles a blinking down arrow at hl on and off after a delay has passed.
; This is often called even when no blinking is occurring.
; The reason is that most functions that call this initialize hDownArrowBlinkCount1 to 0.
; The effect is that if the tile at hl is initialized with a down arrow,
; this function will toggle that down arrow on and off, but if the tile isn't
; initialized with a down arrow, this function does nothing.
; That allows this to be called without worrying about if a down arrow should
; be blinking.
HandleDownArrowBlinkTiming::
ld a, [hl]
ld b, a
ld a, "▼"
cp b
jr nz, .downArrowOff
.downArrowOn
ldh a, [hDownArrowBlinkCount1]
dec a
ldh [hDownArrowBlinkCount1], a
ret nz
ldh a, [hDownArrowBlinkCount2]
dec a
ldh [hDownArrowBlinkCount2], a
ret nz
ld a, " "
ld [hl], a
ld a, $ff
ldh [hDownArrowBlinkCount1], a
ld a, $06
ldh [hDownArrowBlinkCount2], a
ret
.downArrowOff
ldh a, [hDownArrowBlinkCount1]
and a
ret z
dec a
ldh [hDownArrowBlinkCount1], a
ret nz
dec a
ldh [hDownArrowBlinkCount1], a
ldh a, [hDownArrowBlinkCount2]
dec a
ldh [hDownArrowBlinkCount2], a
ret nz
ld a, $06
ldh [hDownArrowBlinkCount2], a
ld a, "▼"
ld [hl], a
ret
; The following code either enables or disables the automatic drawing of
; text boxes by DisplayTextID. Both functions cause DisplayTextID to wait
; for a button press after displaying text (unless [wEnteringCableClub] is set).
EnableAutoTextBoxDrawing::
xor a
jr AutoTextBoxDrawingCommon
DisableAutoTextBoxDrawing::
ld a, $01
AutoTextBoxDrawingCommon::
ld [wAutoTextBoxDrawingControl], a
xor a
ld [wDoNotWaitForButtonPressAfterDisplayingText], a ; make DisplayTextID wait for button press
ret
PrintText::
; Print text hl at (1, 14).
push hl
ld a, MESSAGE_BOX
ld [wTextBoxID], a
call DisplayTextBoxID
call UpdateSprites
call Delay3
pop hl
PrintText_NoCreatingTextBox::
bccoord 1, 14
jp TextCommandProcessor