diff options
Diffstat (limited to 'engine/link')
-rw-r--r-- | engine/link/link.asm | 2345 | ||||
-rw-r--r-- | engine/link/mystery_gift.asm | 1077 |
2 files changed, 3422 insertions, 0 deletions
diff --git a/engine/link/link.asm b/engine/link/link.asm new file mode 100644 index 00000000..fccb8f5c --- /dev/null +++ b/engine/link/link.asm @@ -0,0 +1,2345 @@ +LinkCommunications: + ld c, 80 + call DelayFrames + call ClearTilemap + call ClearSprites + call UpdateSprites + call WaitBGMap + call SetTradeRoomBGPals + xor a + ldh [hSCX], a + ldh [hSCY], a + ld c, 80 + call DelayFrames + call ClearTilemap + call UpdateSprites + call LoadStandardFont + call LoadFontsBattleExtra + call LoadTradeScreenBorder + call SetTradeRoomBGPals + call WaitBGMap + hlcoord 3, 8 + ld b, 2 + ld c, 12 + call LinkTextboxAtHL + hlcoord 4, 10 + ld de, String_PleaseWait + call PlaceString + ld hl, wce5d + xor a ; LOW($5000) + ld [hli], a + ld [hl], HIGH($5000) + ld a, [wLinkMode] + cp LINK_TIMECAPSULE + jp nz, Gen2ToGen2LinkComms + +Gen2ToGen1LinkComms: + call ClearLinkData + call Link_PrepPartyData_Gen1 + call FixDataForLinkTransfer + xor a + ld [wPlayerLinkAction], a + call WaitLinkTransfer + ldh a, [hSerialConnectionStatus] + cp USING_INTERNAL_CLOCK + jr nz, .player_1 + + ld c, 3 + call DelayFrames + xor a + ldh [hSerialSend], a + ld a, (0 << rSC_ON) | (1 << rSC_CLOCK) + ldh [rSC], a + ld a, (1 << rSC_ON) | (1 << rSC_CLOCK) + ldh [rSC], a + + call DelayFrame + xor a + ldh [hSerialSend], a + ld a, (0 << rSC_ON) | (1 << rSC_CLOCK) + ldh [rSC], a + ld a, (1 << rSC_ON) | (1 << rSC_CLOCK) + ldh [rSC], a + +.player_1 + ld de, MUSIC_NONE + call PlayMusic + ld c, 3 + call DelayFrames + xor a + ldh [rIF], a + ld a, 1 << SERIAL + ldh [rIE], a + ld hl, wd0dc + ld de, wEnemyMonSpecies + ld bc, $11 + call Serial_ExchangeBytes + ld a, SERIAL_NO_DATA_BYTE + ld [de], a + ld hl, wLinkData + ld de, wOTPlayerName + ld bc, $1a8 + call Serial_ExchangeBytes + ld a, SERIAL_NO_DATA_BYTE + ld [de], a + ld hl, wc508 + ld de, wTrademons + ld bc, wTrademons - wc508 + call Serial_ExchangeBytes + xor a + ldh [rIF], a + ld a, (1 << JOYPAD) | (1 << SERIAL) | (1 << TIMER) | (1 << VBLANK) + ldh [rIE], a + call Link_CopyRandomNumbers + ld hl, wOTPlayerName + call Link_FindFirstNonControlCharacter_SkipZero + push hl + ld bc, NAME_LENGTH + add hl, bc + ld a, [hl] + pop hl + and a + jp z, Function28b22 + cp $7 + jp nc, Function28b22 + ld de, wLinkData + ld bc, $1a2 + call Link_CopyOTData + ld de, wPlayerTrademonSpecies + ld hl, wTimeCapsulePartyMon1Species + ld c, 2 +.loop + ld a, [de] + inc de + and a + jr z, .loop + cp SERIAL_PREAMBLE_BYTE + jr z, .loop + cp SERIAL_NO_DATA_BYTE + jr z, .loop + cp SERIAL_PATCH_LIST_PART_TERMINATOR + jr z, .next + push hl + push bc + ld b, 0 + dec a + ld c, a + add hl, bc + ld a, SERIAL_NO_DATA_BYTE + ld [hl], a + pop bc + pop hl + jr .loop + +.next + ld hl, wc80f + dec c + jr nz, .loop + ld hl, wLinkPlayerName + ld de, wOTPlayerName + ld bc, NAME_LENGTH + call CopyBytes + ld de, wOTPartyCount + ld a, [hli] + ld [de], a + inc de +.party_loop + ld a, [hli] + cp -1 + jr z, .done_party + ld [wTempSpecies], a + push hl + push de + callfar ConvertMon_1to2 + pop de + pop hl + ld a, [wTempSpecies] + ld [de], a + inc de + jr .party_loop + +.done_party + ld [de], a + ld hl, wTimeCapsulePartyMon1Species + call Function2868a + ld a, LOW(wOTPartyMonOT) + ld [wUnusedCFFE], a + ld a, HIGH(wOTPartyMonOT) + ld [wUnusedCFFE + 1], a + ld de, MUSIC_NONE + call PlayMusic + ldh a, [hSerialConnectionStatus] + cp USING_INTERNAL_CLOCK + ld c, 66 + call z, DelayFrames + ld de, MUSIC_ROUTE_30 + call PlayMusic + jp InitTradeMenuDisplay + +Gen2ToGen2LinkComms: + call ClearLinkData + call Link_PrepPartyData_Gen2 + call FixDataForLinkTransfer + call Function29dba + ld a, [wScriptVar] + and a + jp z, LinkTimeout + ldh a, [hSerialConnectionStatus] + cp USING_INTERNAL_CLOCK + jr nz, .Player1 + + ld c, 3 + call DelayFrames + xor a + ldh [hSerialSend], a + ld a, (0 << rSC_ON) | (1 << rSC_CLOCK) + ldh [rSC], a + ld a, (1 << rSC_ON) | (1 << rSC_CLOCK) + ldh [rSC], a + + call DelayFrame + xor a + ldh [hSerialSend], a + ld a, (0 << rSC_ON) | (1 << rSC_CLOCK) + ldh [rSC], a + ld a, (1 << rSC_ON) | (1 << rSC_CLOCK) + ldh [rSC], a + +.Player1: + ld de, MUSIC_NONE + call PlayMusic + ld c, 3 + call DelayFrames + xor a + ldh [rIF], a + ld a, 1 << SERIAL + ldh [rIE], a + ld hl, wd0dc + ld de, wEnemyMonSpecies + ld bc, $11 + call Serial_ExchangeBytes + ld a, SERIAL_NO_DATA_BYTE + ld [de], a + ld hl, wLinkData + ld de, wOTPlayerName + ld bc, $1c2 + call Serial_ExchangeBytes + ld a, SERIAL_NO_DATA_BYTE + ld [de], a + ld hl, wc508 + ld de, wTrademons + ld bc, wTrademons - wc508 + call Serial_ExchangeBytes + ld a, [wLinkMode] + cp LINK_TRADECENTER + jr nz, .not_trading + ld hl, wc8f4 + ld de, wca84 + ld bc, $186 + call ExchangeBytes + +.not_trading + xor a + ldh [rIF], a + ld a, (1 << JOYPAD) | (1 << SERIAL) | (1 << TIMER) | (1 << VBLANK) + ldh [rIE], a + ld de, MUSIC_NONE + call PlayMusic + call Link_CopyRandomNumbers + ld hl, wOTPlayerName + call Link_FindFirstNonControlCharacter_SkipZero + ld de, wLinkData + ld bc, $1b9 + call Link_CopyOTData + ld de, wPlayerTrademonSpecies + ld hl, wLinkPlayerPartyMon1Species + ld c, 2 +.loop1 + ld a, [de] + inc de + and a + jr z, .loop1 + cp SERIAL_PREAMBLE_BYTE + jr z, .loop1 + cp SERIAL_NO_DATA_BYTE + jr z, .loop1 + cp SERIAL_PATCH_LIST_PART_TERMINATOR + jr z, .next1 + push hl + push bc + ld b, 0 + dec a + ld c, a + add hl, bc + ld a, SERIAL_NO_DATA_BYTE + ld [hl], a + pop bc + pop hl + jr .loop1 + +.next1 + ld hl, wc80f + dec c + jr nz, .loop1 + ld a, [wLinkMode] + cp LINK_TRADECENTER + jr nz, .skip_mail + ld hl, wca84 +.loop2 + ld a, [hli] + cp MAIL_MSG_LENGTH + jr nz, .loop2 +.loop3 + ld a, [hli] + cp SERIAL_NO_DATA_BYTE + jr z, .loop3 + cp MAIL_MSG_LENGTH + jr z, .loop3 + dec hl + ld de, wca84 + ld bc, $190 ; 400 + call CopyBytes + ld hl, wca84 + ld bc, $c6 ; 198 +.loop4 + ld a, [hl] + cp MAIL_MSG_LENGTH + 1 + jr nz, .okay1 + ld [hl], SERIAL_NO_DATA_BYTE +.okay1 + inc hl + dec bc + ld a, b + or c + jr nz, .loop4 + ld de, wcb9e +.loop5 + ld a, [de] + inc de + cp SERIAL_PATCH_LIST_PART_TERMINATOR + jr z, .start_copying_mail + ld hl, wcb4a + dec a + ld b, $0 + ld c, a + add hl, bc + ld [hl], SERIAL_NO_DATA_BYTE + jr .loop5 + +.start_copying_mail + ld hl, wca84 + ld de, wc8f4 + ld b, PARTY_LENGTH +.copy_mail_loop + push bc + ld bc, MAIL_MSG_LENGTH + 1 + call CopyBytes + ld a, LOW(MAIL_STRUCT_LENGTH - (MAIL_MSG_LENGTH + 1)) + add e + ld e, a + ld a, HIGH(MAIL_STRUCT_LENGTH - (MAIL_MSG_LENGTH + 1)) + adc d + ld d, a + pop bc + dec b + jr nz, .copy_mail_loop + ld de, wc8f4 + ld b, PARTY_LENGTH +.fix_mail_loop + push bc + ld a, LOW(MAIL_MSG_LENGTH + 1) + add e + ld e, a + ld a, HIGH(MAIL_MSG_LENGTH + 1) + adc d + ld d, a + ld bc, MAIL_STRUCT_LENGTH - (MAIL_MSG_LENGTH + 1) + call CopyBytes + pop bc + dec b + jr nz, .fix_mail_loop + ld de, wca0e + xor a + ld [de], a + +.skip_mail + ld hl, wLinkPlayerName + ld de, wOTPlayerName + ld bc, NAME_LENGTH + call CopyBytes + ld de, wOTPartyCount + ld bc, 1 + PARTY_LENGTH + 1 + call CopyBytes + ld de, wOTPlayerID + ld bc, 2 + call CopyBytes + ld de, wOTPartyMons + ld bc, wOTPartyDataEnd - wOTPartyMons + call CopyBytes + ld a, LOW(wOTPartyMonOT) + ld [wUnusedCFFE], a + ld a, HIGH(wOTPartyMonOT) + ld [wUnusedCFFE + 1], a + ld de, MUSIC_NONE + call PlayMusic + ldh a, [hSerialConnectionStatus] + cp USING_INTERNAL_CLOCK + ld c, 66 + call z, DelayFrames + ld a, [wLinkMode] + cp LINK_COLOSSEUM + jr nz, .ready_to_trade + ld a, CAL + ld [wOtherTrainerClass], a + call ClearTilemap + call WaitBGMap + ld hl, wOptions + ld a, [hl] + push af + and 1 << STEREO + or TEXT_DELAY_MED + ld [hl], a + ld hl, wOTPlayerName + ld de, wOTClassName + ld bc, NAME_LENGTH + call CopyBytes + call ReturnToMapFromSubmenu + + ; LET'S DO THIS + ld a, [wDisableTextAcceleration] + push af + ld a, 1 + ld [wDisableTextAcceleration], a + + predef StartBattle + + pop af + ld [wDisableTextAcceleration], a + pop af + ld [wOptions], a + farcall LoadPokemonData + jp Function28b22 + +.ready_to_trade + ld de, MUSIC_ROUTE_30 + call PlayMusic + jp InitTradeMenuDisplay + +LinkTimeout: + ld de, .LinkTimeoutText + ld b, 10 +.loop + call DelayFrame + call LinkDataReceived + dec b + jr nz, .loop + xor a + ld [hld], a + ld [hl], a + ldh [hVBlank], a + push de + hlcoord 0, 12 + ld b, 4 + ld c, 18 + call LinkTextboxAtHL + pop hl + bccoord 1, 14 + jp PlaceHLTextAtBC + +.LinkTimeoutText: + text_far _LinkTimeoutText + text_end + +ExchangeBytes: + ld a, TRUE + ldh [hSerialIgnoringInitialData], a +.loop + ld a, [hl] + ldh [hSerialSend], a + call Serial_ExchangeByte + push bc + ld b, a + inc hl + ld a, 48 +.delay_cycles + dec a + jr nz, .delay_cycles + ldh a, [hSerialIgnoringInitialData] + and a + ld a, b + pop bc + jr z, .load + dec hl + xor a + ldh [hSerialIgnoringInitialData], a + jr .loop + +.load + ld [de], a + inc de + dec bc + ld a, b + or c + jr nz, .loop + ret + +String_PleaseWait: + db "PLEASE WAIT!@" + +ClearLinkData: + ld hl, wLinkData + ld bc, wLinkDataEnd - wLinkData +.loop + xor a + ld [hli], a + dec bc + ld a, b + or c + jr nz, .loop + ret + +FixDataForLinkTransfer: + ld hl, wd0dc + ld a, SERIAL_PREAMBLE_BYTE + ld b, wLinkBattleRNs - wd0dc +.loop1 + ld [hli], a + dec b + jr nz, .loop1 + ld b, wTempEnemyMonSpecies - wLinkBattleRNs +.loop2 + call Random + cp SERIAL_PREAMBLE_BYTE + jr nc, .loop2 + ld [hli], a + dec b + jr nz, .loop2 + ld hl, wc508 + ld a, SERIAL_PREAMBLE_BYTE + ld [hli], a + ld [hli], a + ld [hli], a + ld b, $c8 + xor a +.loop3 + ld [hli], a + dec b + jr nz, .loop3 + ld hl, wTimeCapsulePartyMon1 - 1 + PARTY_LENGTH + ld de, wc512 + lb bc, 0, 0 +.loop4 + inc c + ld a, c + cp SERIAL_PREAMBLE_BYTE + jr z, .next1 + ld a, b + dec a + jr nz, .next2 + push bc + ld a, [wLinkMode] + cp LINK_TIMECAPSULE + ld b, $d + jr z, .got_value + ld b, $27 +.got_value + ld a, c + cp b + pop bc + jr z, .done +.next2 + inc hl + ld a, [hl] + cp SERIAL_NO_DATA_BYTE + jr nz, .loop4 + ld a, c + ld [de], a + inc de + ld [hl], SERIAL_PATCH_LIST_PART_TERMINATOR + jr .loop4 + +.next1 + ld a, SERIAL_PATCH_LIST_PART_TERMINATOR + ld [de], a + inc de + lb bc, 1, 0 + jr .loop4 + +.done + ld a, SERIAL_PATCH_LIST_PART_TERMINATOR + ld [de], a + ret + +Link_PrepPartyData_Gen1: + ld de, wLinkData + ld a, SERIAL_PREAMBLE_BYTE + ld b, PARTY_LENGTH +.loop1 + ld [de], a + inc de + dec b + jr nz, .loop1 + ld hl, wPlayerName + ld bc, NAME_LENGTH + call CopyBytes + push de + ld hl, wPartyCount + ld a, [hli] + ld [de], a + inc de +.loop2 + ld a, [hli] + cp -1 + jr z, .done_party + ld [wTempSpecies], a + push hl + push de + callfar ConvertMon_2to1 + pop de + pop hl + ld a, [wTempSpecies] + ld [de], a + inc de + jr .loop2 + +.done_party + ld [de], a + pop de + ld hl, 1 + PARTY_LENGTH + 1 + add hl, de + ld d, h + ld e, l + ld hl, wPartyMon1Species + ld c, PARTY_LENGTH +.mon_loop + push bc + call .ConvertPartyStruct2to1 + ld bc, PARTYMON_STRUCT_LENGTH + add hl, bc + pop bc + dec c + jr nz, .mon_loop + ld hl, wPartyMonOT + call .copy_ot_nicks + ld hl, wPartyMonNicknames +.copy_ot_nicks + ld bc, PARTY_LENGTH * NAME_LENGTH + jp CopyBytes + +.ConvertPartyStruct2to1: + ld b, h + ld c, l + push de + push bc + ld a, [hl] + ld [wTempSpecies], a + callfar ConvertMon_2to1 + pop bc + pop de + ld a, [wTempSpecies] + ld [de], a + inc de + ld hl, MON_HP + add hl, bc + ld a, [hli] + ld [de], a + inc de + ld a, [hl] + ld [de], a + inc de + xor a + ld [de], a + inc de + ld hl, MON_STATUS + add hl, bc + ld a, [hl] + ld [de], a + inc de + ld a, [bc] + cp MAGNEMITE + jr z, .steel_type + cp MAGNETON + jr nz, .skip_steel + +.steel_type + ld a, ELECTRIC + ld [de], a + inc de + ld [de], a + inc de + jr .done_steel + +.skip_steel + push bc + dec a + ld hl, BaseData + BASE_TYPES + ld bc, BASE_DATA_SIZE + call AddNTimes + ld bc, BASE_CATCH_RATE - BASE_TYPES + ld a, BANK(BaseData) + call FarCopyBytes + pop bc + +.done_steel + push bc + ld hl, MON_ITEM + add hl, bc + ld bc, MON_HAPPINESS - MON_ITEM + call CopyBytes + pop bc + + ld hl, MON_LEVEL + add hl, bc + ld a, [hl] + ld [de], a + ld [wCurPartyLevel], a + inc de + + push bc + ld hl, MON_MAXHP + add hl, bc + ld bc, MON_SAT - MON_MAXHP + call CopyBytes + pop bc + + push de + push bc + + ld a, [bc] + dec a + push bc + ld b, 0 + ld c, a + ld hl, KantoMonSpecials + add hl, bc + ld a, BANK(KantoMonSpecials) + call GetFarByte + ld [wBaseSpecialAttack], a + pop bc + + ld hl, MON_STAT_EXP - 1 + add hl, bc + ld c, STAT_SATK + ld b, TRUE + predef CalcMonStatC + + pop bc + pop de + + ldh a, [hQuotient + 2] + ld [de], a + inc de + ldh a, [hQuotient + 3] + ld [de], a + inc de + ld h, b + ld l, c + ret + +Link_PrepPartyData_Gen2: + ld de, wLinkData + ld a, SERIAL_PREAMBLE_BYTE + ld b, PARTY_LENGTH +.loop1 + ld [de], a + inc de + dec b + jr nz, .loop1 + ld hl, wPlayerName + ld bc, NAME_LENGTH + call CopyBytes + ld hl, wPartyCount + ld bc, 1 + PARTY_LENGTH + 1 + call CopyBytes + ld hl, wPlayerID + ld bc, 2 + call CopyBytes + ld hl, wPartyMon1Species + ld bc, PARTY_LENGTH * PARTYMON_STRUCT_LENGTH + call CopyBytes + ld hl, wPartyMonOT + ld bc, PARTY_LENGTH * NAME_LENGTH + call CopyBytes + ld hl, wPartyMonNicknames + ld bc, PARTY_LENGTH * MON_NAME_LENGTH + call CopyBytes + +; Okay, we did all that. Now, are we in the trade center? + ld a, [wLinkMode] + cp LINK_TRADECENTER + ret nz + +; Fill 5 bytes at wc8f4 with $20 + ld de, wc8f4 + ld a, $20 + call Function28682 + +; Copy all the mail messages to wc9f9 + ld a, BANK(sPartyMail) + call OpenSRAM + ld hl, sPartyMail + ld b, PARTY_LENGTH +.loop2 + push bc + ld bc, MAIL_MSG_LENGTH + 1 + call CopyBytes + ld bc, sPartyMon1MailEnd - sPartyMon1MailAuthor + add hl, bc + pop bc + dec b + jr nz, .loop2 +; Copy the mail data to wcabf + ld hl, sPartyMail + ld b, PARTY_LENGTH +.loop3 + push bc + ld bc, MAIL_MSG_LENGTH + 1 + add hl, bc + ld bc, sPartyMon1MailEnd - sPartyMon1MailAuthor + call CopyBytes + pop bc + dec b + jr nz, .loop3 + + call CloseSRAM + ld hl, wc8f9 + ld bc, PARTY_LENGTH * (sPartyMon1MailAuthor - sPartyMon1Mail) +.loop4 + ld a, [hl] + cp SERIAL_NO_DATA_BYTE + jr nz, .skip2 + ld [hl], sPartyMon1MailAuthor - sPartyMon1Mail + +.skip2 + inc hl + dec bc + ld a, b + or c + jr nz, .loop4 + ld hl, wc9bf + ld de, wca13 + ld b, PARTY_LENGTH * (sPartyMon1MailEnd - sPartyMon1MailAuthor) + ld c, $0 +.loop5 + inc c + ld a, [hl] + cp SERIAL_NO_DATA_BYTE + jr nz, .skip3 + ld [hl], SERIAL_PATCH_LIST_PART_TERMINATOR + ld a, c + ld [de], a + inc de + +.skip3 + inc hl + dec b + jr nz, .loop5 + ld a, SERIAL_PATCH_LIST_PART_TERMINATOR + ld [de], a + ret + +Function28682: + ld c, 5 +.loop + ld [de], a + inc de + dec c + jr nz, .loop + ret + +Function2868a: + push hl + ld d, h + ld e, l + ld bc, wLinkOTPartyMonTypes + ld hl, wcae8 + ld a, c + ld [hli], a + ld [hl], b + ld hl, wOTPartyMon1Species + ld c, PARTY_LENGTH +.loop + push bc + call .ConvertToGen2 + pop bc + dec c + jr nz, .loop + pop hl + ld bc, PARTY_LENGTH * REDMON_STRUCT_LENGTH + add hl, bc + ld de, wOTPartyMonOT + ld bc, PARTY_LENGTH * NAME_LENGTH + call CopyBytes + ld de, wOTPartyMonNicknames + ld bc, PARTY_LENGTH * MON_NAME_LENGTH + jp CopyBytes + +.ConvertToGen2: + ld b, h + ld c, l + ld a, [de] + inc de + push bc + push de + ld [wTempSpecies], a + callfar ConvertMon_1to2 + pop de + pop bc + ld a, [wTempSpecies] + ld [bc], a + ld [wCurSpecies], a + ld hl, MON_HP + add hl, bc + ld a, [de] + inc de + ld [hli], a + ld a, [de] + inc de + ld [hl], a + inc de + ld hl, MON_STATUS + add hl, bc + ld a, [de] + inc de + ld [hl], a + ld hl, wcae8 + ld a, [hli] + ld h, [hl] + ld l, a + ld a, [de] + ld [hli], a + inc de + ld a, [de] + ld [hli], a + inc de + ld a, l + ld [wcae8], a + ld a, h + ld [wcae8 + 1], a + push bc + ld hl, MON_ITEM + add hl, bc + push hl + ld h, d + ld l, e + pop de + push bc + ld a, [hli] + ld b, a + call TimeCapsule_ReplaceTeruSama + ld a, b + ld [de], a + inc de + pop bc + ld bc, $19 + call CopyBytes + pop bc + ld d, h + ld e, l + ld hl, $1f + add hl, bc + ld a, [de] + inc de + ld [hl], a + ld [wCurPartyLevel], a + push bc + ld hl, $24 + add hl, bc + push hl + ld h, d + ld l, e + pop de + ld bc, 8 + call CopyBytes + pop bc + call GetBaseData + push de + push bc + ld d, h + ld e, l + ld hl, MON_STAT_EXP - 1 + add hl, bc + ld c, STAT_SATK + ld b, TRUE + predef CalcMonStatC + pop bc + pop hl + ldh a, [hQuotient + 2] + ld [hli], a + ldh a, [hQuotient + 3] + ld [hli], a + push hl + push bc + ld hl, MON_STAT_EXP - 1 + add hl, bc + ld c, STAT_SDEF + ld b, TRUE + predef CalcMonStatC + pop bc + pop hl + ldh a, [hQuotient + 2] + ld [hli], a + ldh a, [hQuotient + 3] + ld [hli], a + push hl + ld hl, $1b + add hl, bc + ld a, $46 + ld [hli], a + xor a + ld [hli], a + ld [hli], a + ld [hl], a + pop hl + inc de + inc de + ret + +TimeCapsule_ReplaceTeruSama: + ld a, b + and a + ret z + push hl + ld hl, TimeCapsule_CatchRateItems +.loop + ld a, [hli] + and a + jr z, .end + cp b + jr z, .found + inc hl + jr .loop + +.found + ld b, [hl] + +.end + pop hl + ret + +INCLUDE "data/items/catch_rate_items.asm" + +Link_CopyOTData: +.loop + ld a, [hli] + cp SERIAL_NO_DATA_BYTE + jr z, .loop + ld [de], a + inc de + dec bc + ld a, b + or c + jr nz, .loop + ret + +Link_CopyRandomNumbers: + ldh a, [hSerialConnectionStatus] + cp USING_INTERNAL_CLOCK + ret z + ld hl, wEnemyMonSpecies + call Link_FindFirstNonControlCharacter_AllowZero + ld de, wLinkBattleRNs + ld c, 10 +.loop + ld a, [hli] + cp SERIAL_NO_DATA_BYTE + jr z, .loop + cp SERIAL_PREAMBLE_BYTE + jr z, .loop + ld [de], a + inc de + dec c + jr nz, .loop + ret + +Link_FindFirstNonControlCharacter_SkipZero: +.loop + ld a, [hli] + and a + jr z, .loop + cp SERIAL_PREAMBLE_BYTE + jr z, .loop + cp SERIAL_NO_DATA_BYTE + jr z, .loop + dec hl + ret + +Link_FindFirstNonControlCharacter_AllowZero: +.loop + ld a, [hli] + cp SERIAL_PREAMBLE_BYTE + jr z, .loop + cp SERIAL_NO_DATA_BYTE + jr z, .loop + dec hl + ret + +InitTradeMenuDisplay: + call ClearTilemap + call LoadTradeScreenBorder + call Function28dcf + call Function28a16 + xor a + ld hl, wOtherPlayerLinkMode + ld [hli], a + ld [hli], a + ld [hli], a + ld [hl], a + ld a, 1 + ld [wMenuCursorY], a + inc a + ld [wPlayerLinkAction], a + jp LinkTrade_PlayerPartyMenu + +LinkTrade_OTPartyMenu: + ld a, OTPARTYMON + ld [wMonType], a + ld a, A_BUTTON | D_UP | D_DOWN + ld [wMenuJoypadFilter], a + ld a, [wOTPartyCount] + ld [w2DMenuNumRows], a + ld a, 1 + ld [w2DMenuNumCols], a + ld a, 9 + ld [w2DMenuCursorInitY], a + ld a, 6 + ld [w2DMenuCursorInitX], a + ld a, 1 + ld [wMenuCursorX], a + ln a, 1, 0 + ld [w2DMenuCursorOffsets], a + ld a, MENU_UNUSED_3 + ld [w2DMenuFlags1], a + xor a + ld [w2DMenuFlags2], a + +LinkTradeOTPartymonMenuLoop: + call ScrollingMenuJoypad + and a + jp z, LinkTradePartiesMenuMasterLoop + bit A_BUTTON_F, a + jr z, .not_a_button + ld a, INIT_ENEMYOT_LIST + ld [wInitListType], a + callfar InitList + ld hl, wOTPartyMon1Species + call LinkMonStatsScreen + jp LinkTradePartiesMenuMasterLoop + +.not_a_button + bit D_UP_F, a + jr z, .not_d_up + ld a, [wMenuCursorY] + ld b, a + ld a, [wOTPartyCount] + cp b + jp nz, LinkTradePartiesMenuMasterLoop + xor a + ld [wMonType], a + call HideCursor + ld a, [wPartyCount] + ld [wMenuCursorY], a + jr LinkTrade_PlayerPartyMenu + +.not_d_up + bit D_DOWN_F, a + jp z, LinkTradePartiesMenuMasterLoop + jp Function28ac9 + +LinkTrade_PlayerPartyMenu: + xor a + ld [wMonType], a + ld a, A_BUTTON | D_UP | D_DOWN + ld [wMenuJoypadFilter], a + ld a, [wPartyCount] + ld [w2DMenuNumRows], a + ld a, 1 + ld [w2DMenuNumCols], a + ld a, 1 + ld [w2DMenuCursorInitY], a + ld a, 6 + ld [w2DMenuCursorInitX], a + ld a, 1 + ld [wMenuCursorX], a + ln a, 1, 0 + ld [w2DMenuCursorOffsets], a + ld a, MENU_UNUSED_3 + ld [w2DMenuFlags1], a + xor a + ld [w2DMenuFlags2], a + +LinkTradePartymonMenuLoop: + call ScrollingMenuJoypad + and a + jr nz, .check_joypad + jp LinkTradePartiesMenuMasterLoop + +.check_joypad + bit A_BUTTON_F, a + jr z, .not_a_button + jp Function28926 + +.not_a_button + bit D_DOWN_F, a + jr z, .not_d_down + ld a, [wMenuCursorY] + dec a + jp nz, LinkTradePartiesMenuMasterLoop + ld a, OTPARTYMON + ld [wMonType], a + call HideCursor + ld a, 1 + ld [wMenuCursorY], a + jp LinkTrade_OTPartyMenu + +.not_d_down + bit D_UP_F, a + jr z, LinkTradePartiesMenuMasterLoop + ld a, [wMenuCursorY] + ld b, a + ld a, [wPartyCount] + cp b + jr nz, LinkTradePartiesMenuMasterLoop + call HideCursor + ld a, 1 + ld [wMenuCursorY], a + jp LinkTrade_PlayerPartyMenu + +LinkTradePartiesMenuMasterLoop: + ld a, [wMonType] + and a + jp z, LinkTradePartymonMenuLoop ; PARTYMON + jp LinkTradeOTPartymonMenuLoop ; OTPARTYMON + +Function28926: + call HideCursor + call LoadTilemapToTempTilemap + call PlaceHollowCursor + ld a, [wMenuCursorY] + push af + hlcoord 0, 15 + ld b, 1 + ld c, 18 + call LinkTextboxAtHL + hlcoord 2, 16 + ld de, .String_Stats_Trade + call PlaceString + +.joy_loop + ld a, " " + ldcoord_a 11, 16 + ld a, A_BUTTON | B_BUTTON | D_RIGHT + ld [wMenuJoypadFilter], a + ld a, 1 + ld [w2DMenuNumRows], a + ld a, 1 + ld [w2DMenuNumCols], a + ld a, 16 + ld [w2DMenuCursorInitY], a + ld a, 1 + ld [w2DMenuCursorInitX], a + ld a, 1 + ld [wMenuCursorY], a + ld [wMenuCursorX], a + ln a, 2, 0 + ld [w2DMenuCursorOffsets], a + xor a + ld [w2DMenuFlags1], a + ld [w2DMenuFlags2], a + call ScrollingMenuJoypad + bit D_RIGHT_F, a + jr nz, .d_right + bit B_BUTTON_F, a + jr z, .show_stats +.b_button + pop af + ld [wMenuCursorY], a + call SafeLoadTempTilemapToTilemap + jp LinkTrade_PlayerPartyMenu + +.d_right + ld a, " " + ldcoord_a 1, 16 + ld a, A_BUTTON | B_BUTTON | D_LEFT + ld [wMenuJoypadFilter], a + ld a, 1 + ld [w2DMenuNumRows], a + ld a, 1 + ld [w2DMenuNumCols], a + ld a, 16 + ld [w2DMenuCursorInitY], a + ld a, 11 + ld [w2DMenuCursorInitX], a + ld a, 1 + ld [wMenuCursorY], a + ld [wMenuCursorX], a + ln a, 2, 0 + ld [w2DMenuCursorOffsets], a + xor a + ld [w2DMenuFlags1], a + ld [w2DMenuFlags2], a + call ScrollingMenuJoypad + bit D_LEFT_F, a + jp nz, .joy_loop + bit B_BUTTON_F, a + jr nz, .b_button + jr .try_trade + +.show_stats + pop af + ld [wMenuCursorY], a + ld a, INIT_PLAYEROT_LIST + ld [wInitListType], a + callfar InitList + call LinkMonStatsScreen + call SafeLoadTempTilemapToTilemap + jp LinkTrade_PlayerPartyMenu + +.try_trade + call PlaceHollowCursor + pop af + ld [wMenuCursorY], a + dec a + ld [wceed], a + ld [wPlayerLinkAction], a + call Serial_PrintWaitingTextAndSyncAndExchangeNybble + ld a, [wOtherPlayerLinkMode] + cp $f + jp z, InitTradeMenuDisplay + ld [wceee], a + call Function28a3c + ld c, 100 + call DelayFrames + farcall ValidateOTTrademon + jr c, .abnormal + farcall Functionfb6ed + jp nc, LinkTrade + xor a + ld [wce57], a + ld [wOtherPlayerLinkAction], a + hlcoord 0, 12 + ld b, 4 + ld c, 18 + call LinkTextboxAtHL + ld hl, .LinkTradeCantBattleText + bccoord 1, 14 + call PlaceHLTextAtBC + jr .cancel_trade + +.abnormal + xor a + ld [wce57], a + ld [wOtherPlayerLinkAction], a + ld a, [wceee] + ld hl, wOTPartySpecies + ld c, a + ld b, 0 + add hl, bc + ld a, [hl] + ld [wNamedObjectIndexBuffer], a + call GetPokemonName + hlcoord 0, 12 + ld b, 4 + ld c, 18 + call LinkTextboxAtHL + ld hl, .LinkAbnormalMonText + bccoord 1, 14 + call PlaceHLTextAtBC + +.cancel_trade + hlcoord 0, 12 + ld b, 4 + ld c, 18 + call LinkTextboxAtHL + hlcoord 1, 14 + ld de, String_TooBadTheTradeWasCanceled + call PlaceString + ld a, $1 + ld [wPlayerLinkAction], a + call Serial_PrintWaitingTextAndSyncAndExchangeNybble + ld c, 100 + call DelayFrames + jp InitTradeMenuDisplay + +.LinkTradeCantBattleText: + text_far _LinkTradeCantBattleText + text_end + +.String_Stats_Trade: + db "STATS TRADE@" + +.LinkAbnormalMonText: + text_far _LinkAbnormalMonText + text_end + +Function28ac9: + ld a, [wMenuCursorY] + cp 1 + jp nz, LinkTradePartiesMenuMasterLoop + call HideCursor +Function28ade: +.loop1 + ld a, "▶" + ldcoord_a 1, 16 +.loop2 + call JoyTextDelay + ldh a, [hJoyLast] + and a + jr z, .loop2 + bit A_BUTTON_F, a + jr nz, .a_button + bit D_UP_F, a + jr z, .loop2 + ld a, " " + ldcoord_a 1, 16 + ld a, [wOTPartyCount] + ld [wMenuCursorY], a + jp LinkTrade_OTPartyMenu + +.a_button + ld a, "▷" + ldcoord_a 1, 16 + ld a, $f + ld [wPlayerLinkAction], a + call Serial_PrintWaitingTextAndSyncAndExchangeNybble + ld a, [wOtherPlayerLinkMode] + cp $f + jr nz, .loop1 +Function28b22: + xor a + ld [wd8b7], a + xor a + ldh [rSB], a + ldh [hSerialSend], a + ld a, (0 << rSC_ON) | (1 << rSC_CLOCK) + ldh [rSC], a + ld a, (1 << rSC_ON) | (1 << rSC_CLOCK) + ldh [rSC], a + ret + +Function28a16: + hlcoord 0, 16 + ld a, "┘" + ld bc, 2 * SCREEN_WIDTH + call ByteFill + hlcoord 1, 16 + ld a, " " + ld bc, SCREEN_WIDTH - 2 + call ByteFill + hlcoord 2, 16 + ld de, .Cancel + jp PlaceString + +.Cancel: + db "CANCEL@" + +Function28a3c: + ld a, [wOtherPlayerLinkMode] + hlcoord 6, 9 + ld bc, SCREEN_WIDTH + call AddNTimes + ld [hl], "▷" + ret + +LinkMonStatsScreen: + ld a, [wMenuCursorY] + dec a + ld [wCurPartyMon], a + call LowVolume + predef StatsScreenInit + ld a, [wCurPartyMon] + inc a + ld [wMenuCursorY], a + call ClearTilemap + call ClearBGPalettes + call MaxVolume + call LoadTradeScreenBorder + call SetTradeRoomBGPals + call WaitBGMap + call Function28dcf + jp Function28a16 + +LinkTrade: + xor a + ld [wce57], a + ld [wOtherPlayerLinkAction], a + hlcoord 0, 12 + ld b, 4 + ld c, 18 + call LinkTextboxAtHL + ld a, [wceed] + ld hl, wPartySpecies + ld c, a + ld b, 0 + add hl, bc + ld a, [hl] + ld [wNamedObjectIndexBuffer], a + call GetPokemonName + ld hl, wStringBuffer1 + ld de, wceef + ld bc, MON_NAME_LENGTH + call CopyBytes + ld a, [wceee] + ld hl, wOTPartySpecies + ld c, a + ld b, 0 + add hl, bc + ld a, [hl] + ld [wNamedObjectIndexBuffer], a + call GetPokemonName + ld hl, LinkAskTradeForText + bccoord 1, 14 + call PlaceHLTextAtBC + call LoadTilemapToTempTilemap + hlcoord 10, 7 + ld b, 3 + ld c, 7 + call LinkTextboxAtHL + ld de, String28eab + hlcoord 12, 8 + call PlaceString + ld a, 8 + ld [w2DMenuCursorInitY], a + ld a, 11 + ld [w2DMenuCursorInitX], a + ld a, 1 + ld [w2DMenuNumCols], a + ld a, 2 + ld [w2DMenuNumRows], a + xor a + ld [w2DMenuFlags1], a + ld [w2DMenuFlags2], a + ld a, $20 + ld [w2DMenuCursorOffsets], a + ld a, A_BUTTON | B_BUTTON + ld [wMenuJoypadFilter], a + ld a, 1 + ld [wMenuCursorY], a + ld [wMenuCursorX], a + call ScrollingMenuJoypad + push af + call SafeLoadTempTilemapToTilemap + pop af + bit 1, a + jr nz, .asm_28c33 + ld a, [wMenuCursorY] + dec a + jr z, .asm_28c54 + +.asm_28c33 + ld a, $1 + ld [wPlayerLinkAction], a + hlcoord 0, 12 + ld b, 4 + ld c, 18 + call LinkTextboxAtHL + hlcoord 1, 14 + ld de, String_TooBadTheTradeWasCanceled + call PlaceString + call Serial_PrintWaitingTextAndSyncAndExchangeNybble + jp Function28ea3 + +.asm_28c54 + ld a, $2 + ld [wPlayerLinkAction], a + call Serial_PrintWaitingTextAndSyncAndExchangeNybble + ld a, [wOtherPlayerLinkMode] + dec a + jr nz, .asm_28c7b + hlcoord 0, 12 + ld b, 4 + ld c, 18 + call LinkTextboxAtHL + hlcoord 1, 14 + ld de, String_TooBadTheTradeWasCanceled + call PlaceString + jp Function28ea3 + +.asm_28c7b + ld hl, sPartyMail + ld a, [wceed] + ld bc, MAIL_STRUCT_LENGTH + call AddNTimes + ld a, BANK(sPartyMail) + call OpenSRAM + ld d, h + ld e, l + ld bc, MAIL_STRUCT_LENGTH + add hl, bc + ld a, [wceed] + ld c, a +.asm_28c96 + inc c + ld a, c + cp PARTY_LENGTH + jr z, .asm_28ca6 + push bc + ld bc, MAIL_STRUCT_LENGTH + call CopyBytes + pop bc + jr .asm_28c96 + +.asm_28ca6 + ld hl, sPartyMail + ld a, [wPartyCount] + dec a + ld bc, MAIL_STRUCT_LENGTH + call AddNTimes + push hl + ld hl, wc8f4 + ld a, [wceee] + ld bc, MAIL_STRUCT_LENGTH + call AddNTimes + pop de + ld bc, MAIL_STRUCT_LENGTH + call CopyBytes + call CloseSRAM + ld hl, wPlayerName + ld de, wPlayerTrademonSenderName + ld bc, NAME_LENGTH + call CopyBytes + ld a, [wceed] + ld hl, wPartySpecies + ld b, 0 + ld c, a + add hl, bc + ld a, [hl] + ld [wPlayerTrademonSpecies], a + push af + ld a, [wceed] + ld hl, wPartyMonOT + call SkipNames + ld de, wPlayerTrademonOTName + ld bc, NAME_LENGTH + call CopyBytes + ld hl, wPartyMon1ID + ld a, [wceed] + call GetPartyLocation + ld a, [hli] + ld [wPlayerTrademonID], a + ld a, [hl] + ld [wPlayerTrademonID + 1], a + ld hl, wPartyMon1DVs + ld a, [wceed] + call GetPartyLocation + ld a, [hli] + ld [wPlayerTrademonDVs], a + ld a, [hl] + ld [wPlayerTrademonDVs + 1], a + ld hl, wOTPlayerName + ld de, wOTTrademonSenderName + ld bc, NAME_LENGTH + call CopyBytes + ld a, [wceee] + ld hl, wOTPartySpecies + ld b, 0 + ld c, a + add hl, bc + ld a, [hl] + ld [wOTTrademonSpecies], a + ld a, [wceee] + ld hl, wOTPartyMonOT + call SkipNames + ld de, wOTTrademonOTName + ld bc, NAME_LENGTH + call CopyBytes + ld hl, wOTPartyMon1ID + ld a, [wceee] + call GetPartyLocation + ld a, [hli] + ld [wOTTrademonID], a + ld a, [hl] + ld [wOTTrademonID + 1], a + ld hl, wOTPartyMon1DVs + ld a, [wceee] + call GetPartyLocation + ld a, [hli] + ld [wOTTrademonDVs], a + ld a, [hl] + ld [wOTTrademonDVs + 1], a + ld a, [wceed] + ld [wCurPartyMon], a + ld hl, wPartySpecies + ld b, 0 + ld c, a + add hl, bc + ld a, [hl] + ld [wceed], a + xor a ; REMOVE_PARTY + ld [wPokemonWithdrawDepositParameter], a + callfar RemoveMonFromPartyOrBox + ld a, [wPartyCount] + dec a + ld [wCurPartyMon], a + ld a, TRUE + ld [wForceEvolution], a + ld a, [wceee] + push af + ld hl, wOTPartySpecies + ld b, 0 + ld c, a + add hl, bc + ld a, [hl] + ld [wceee], a + ld c, 100 + call DelayFrames + call ClearTilemap + call LoadFontsBattleExtra + ldh a, [hSerialConnectionStatus] + cp USING_EXTERNAL_CLOCK + jr z, .player_2 + predef TradeAnimation + jr .done_animation + +.player_2 + predef TradeAnimationPlayer2 + +.done_animation + pop af + ld c, a + ld [wCurPartyMon], a + ld hl, wOTPartySpecies + ld d, 0 + ld e, a + add hl, de + ld a, [hl] + ld [wCurPartySpecies], a + ld hl, wOTPartyMon1Species + ld a, c + call GetPartyLocation + ld de, wTempMonSpecies + ld bc, PARTYMON_STRUCT_LENGTH + call CopyBytes + predef AddTempmonToParty + ld a, [wPartyCount] + dec a + ld [wCurPartyMon], a + callfar EvolvePokemon + call ClearTilemap + call LoadTradeScreenBorder + call SetTradeRoomBGPals + call WaitBGMap + ld b, $1 + pop af + ld c, a + cp MEW + jr z, .loop + ld a, [wCurPartySpecies] + cp MEW + jr z, .loop + ld b, $2 + ld a, c + cp CELEBI + jr z, .loop + ld a, [wCurPartySpecies] + cp CELEBI + jr z, .loop + ld b, $0 + +.loop + ld a, b + ld [wPlayerLinkAction], a + push bc + call Serial_PrintWaitingTextAndSyncAndExchangeNybble + pop bc + ld a, [wLinkMode] + cp LINK_TIMECAPSULE + jr z, .save + ld a, b + and a + jr z, .save + ld a, [wOtherPlayerLinkAction] + cp b + jr nz, .loop + +.save + farcall SaveAfterLinkTrade + ld c, 40 + call DelayFrames + hlcoord 0, 12 + ld b, 4 + ld c, 18 + call LinkTextboxAtHL + hlcoord 1, 14 + ld de, String28ebd + call PlaceString + ld c, 50 + call DelayFrames + ld a, [wLinkMode] + cp LINK_TIMECAPSULE + jp z, Gen2ToGen1LinkComms + jp Gen2ToGen2LinkComms + +Function28ea3: + ld c, 100 + call DelayFrames + jp InitTradeMenuDisplay + +String28eab: + db "TRADE" + next "CANCEL@" + +LinkAskTradeForText: + text_far _LinkAskTradeForText + text_end + +String28ebd: + db "Trade completed!@" + +String_TooBadTheTradeWasCanceled: + db "Too bad! The trade" + next "was canceled!@" + +LinkTextboxAtHL: + push hl + ld a, $78 + ld [hli], a + inc a + call .PlaceRow + inc a + ld [hl], a + pop hl + ld de, SCREEN_WIDTH + add hl, de +.loop + push hl + ld a, $7b + ld [hli], a + ld a, " " + call .PlaceRow + ld [hl], $77 + pop hl + ld de, SCREEN_WIDTH + add hl, de + dec b + jr nz, .loop + + ld a, $7c + ld [hli], a + ld a, $76 + call .PlaceRow + ld [hl], $7d + ret + +.PlaceRow + ld d, c +.row_loop + ld [hli], a + dec d + jr nz, .row_loop + ret + +LoadTradeScreenBorder: + ld de, LinkCommsBorderGFX + ld hl, vTiles2 tile $76 + lb bc, BANK(LinkCommsBorderGFX), 9 + jp Get2bpp + +SetTradeRoomBGPals: + ld b, SCGB_DIPLOMA + call GetSGBLayout + jp SetPalettes + +Function28dcf: + hlcoord 0, 0 + ld b, 6 + ld c, 18 + call LinkTextboxAtHL + hlcoord 0, 8 + ld b, 6 + ld c, 18 + call LinkTextboxAtHL + farcall PlaceTradePartnerNamesAndParty + ret + +INCLUDE "engine/movie/trade_animation.asm" + +CheckTimeCapsuleCompatibility: +; Checks to see if your party is compatible with the Gen 1 games. +; Returns the following in wScriptVar: +; 0: Party is okay +; 1: At least one Pokémon was introduced in Gen 2 +; 2: At least one Pokémon has a move that was introduced in Gen 2 +; 3: At least one Pokémon is holding mail + +; If any party Pokémon was introduced in the Gen 2 games, don't let it in. + ld hl, wPartySpecies + ld b, PARTY_LENGTH +.loop + ld a, [hli] + cp -1 + jr z, .checkitem + cp JOHTO_POKEMON + jr nc, .mon_too_new + dec b + jr nz, .loop + +; If any party Pokémon is holding mail, don't let it in. +.checkitem + ld a, [wPartyCount] + ld b, a + ld hl, wPartyMon1Item +.itemloop + push hl + push bc + ld d, [hl] + farcall ItemIsMail + pop bc + pop hl + jr c, .mon_has_mail + ld de, PARTYMON_STRUCT_LENGTH + add hl, de + dec b + jr nz, .itemloop + +; If any party Pokémon has a move that was introduced in the Gen 2 games, don't let it in. + ld hl, wPartyMon1Moves + ld a, [wPartyCount] + ld b, a +.move_loop + ld c, NUM_MOVES +.move_next + ld a, [hli] + cp STRUGGLE + 1 + jr nc, .move_too_new + dec c + jr nz, .move_next + ld de, PARTYMON_STRUCT_LENGTH - NUM_MOVES + add hl, de + dec b + jr nz, .move_loop + xor a + jr .done + +.mon_too_new + ld [wNamedObjectIndexBuffer], a + call GetPokemonName + ld a, $1 + jr .done + +.move_too_new + push bc + ld [wNamedObjectIndexBuffer], a + call GetMoveName + call CopyName1 + pop bc + call Function29c67 + ld a, $2 + jr .done + +.mon_has_mail + call Function29c67 + ld a, $3 + +.done + ld [wScriptVar], a + ret + +Function29c67: + ld a, [wPartyCount] + sub b + ld c, a + inc c + ld b, 0 + ld hl, wPartyCount + add hl, bc + ld a, [hl] + ld [wNamedObjectIndexBuffer], a + call GetPokemonName + ret + +EnterTimeCapsule: + ld a, $4 + call Link_EnsureSync + ld c, 40 + call DelayFrames + xor a + ldh [hVBlank], a + inc a ; LINK_TIMECAPSULE + ld [wLinkMode], a + ret + +WaitForOtherPlayerToExit: + ld c, 3 + call DelayFrames + ld a, CONNECTION_NOT_ESTABLISHED + ldh [hSerialConnectionStatus], a + xor a + ldh [rSB], a + ldh [hSerialReceive], a + ld a, (0 << rSC_ON) | (1 << rSC_CLOCK) + ldh [rSC], a + ld a, (1 << rSC_ON) | (1 << rSC_CLOCK) + ldh [rSC], a + ld c, 3 + call DelayFrames + xor a + ldh [rSB], a + ldh [hSerialReceive], a + ld a, (0 << rSC_ON) | (0 << rSC_CLOCK) + ldh [rSC], a + ld a, (1 << rSC_ON) | (0 << rSC_CLOCK) + ldh [rSC], a + ld c, 3 + call DelayFrames + xor a + ldh [rSB], a + ldh [hSerialReceive], a + ldh [rSC], a + ld c, 3 + call DelayFrames + ld a, CONNECTION_NOT_ESTABLISHED + ldh [hSerialConnectionStatus], a + ld hl, wLinkTimeoutFrames + xor a + ld [hli], a + ld [hl], a + ldh [hVBlank], a + ld [wLinkMode], a + ret + +SetBitsForLinkTradeRequest: + ld a, LINK_TRADECENTER - 1 + ld [wPlayerLinkAction], a + ld [wChosenCableClubRoom], a + ret + +SetBitsForBattleRequest: + ld a, LINK_COLOSSEUM - 1 + ld [wPlayerLinkAction], a + ld [wChosenCableClubRoom], a + ret + +SetBitsForTimeCapsuleRequest: + ld a, $2 + ldh [rSB], a + xor a + ldh [hSerialReceive], a + ld a, (0 << rSC_ON) | (0 << rSC_CLOCK) + ldh [rSC], a + ld a, (1 << rSC_ON) | (0 << rSC_CLOCK) + ldh [rSC], a + xor a ; LINK_TIMECAPSULE - 1 + ld [wPlayerLinkAction], a + ld [wChosenCableClubRoom], a + ret + +WaitForLinkedFriend: + ld a, [wPlayerLinkAction] + and a + jr z, .no_link_action + ld a, $2 + ldh [rSB], a + xor a + ldh [hSerialReceive], a + ld a, (0 << rSC_ON) | (0 << rSC_CLOCK) + ldh [rSC], a + ld a, (1 << rSC_ON) | (0 << rSC_CLOCK) + ldh [rSC], a + call DelayFrame + call DelayFrame + call DelayFrame + +.no_link_action + ld a, $2 + ld [wLinkTimeoutFrames + 1], a + ld a, $ff + ld [wLinkTimeoutFrames], a +.loop + ldh a, [hSerialConnectionStatus] + cp USING_INTERNAL_CLOCK + jr z, .connected + cp USING_EXTERNAL_CLOCK + jr z, .connected + ld a, CONNECTION_NOT_ESTABLISHED + ldh [hSerialConnectionStatus], a + ld a, $2 + ldh [rSB], a + xor a + ldh [hSerialReceive], a + ld a, (0 << rSC_ON) | (0 << rSC_CLOCK) + ldh [rSC], a + ld a, (1 << rSC_ON) | (0 << rSC_CLOCK) + ldh [rSC], a + ld a, [wLinkTimeoutFrames] + dec a + ld [wLinkTimeoutFrames], a + jr nz, .not_done + ld a, [wLinkTimeoutFrames + 1] + dec a + ld [wLinkTimeoutFrames + 1], a + jr z, .done + +.not_done + ld a, $1 + ldh [rSB], a + ld a, (0 << rSC_ON) | (1 << rSC_CLOCK) + ldh [rSC], a + ld a, (1 << rSC_ON) | (1 << rSC_CLOCK) + ldh [rSC], a + call DelayFrame + jr .loop + +.connected + call LinkDataReceived + call DelayFrame + call LinkDataReceived + ld c, 50 + call DelayFrames + ld a, $1 + ld [wScriptVar], a + ret + +.done + xor a + ld [wScriptVar], a + ret + +CheckLinkTimeout: + ld a, $1 + ld [wPlayerLinkAction], a + ld hl, wLinkTimeoutFrames + ld a, $3 + ld [hli], a + xor a + ld [hl], a + call WaitBGMap + ld a, $2 + ldh [hVBlank], a + call DelayFrame + call DelayFrame + call Link_CheckCommunicationError + xor a + ldh [hVBlank], a + ld a, [wScriptVar] + and a + ret nz + jp Link_ResetSerialRegistersAfterLinkClosure + +Function29dba: + ld a, $5 + ld [wPlayerLinkAction], a + ld hl, wLinkTimeoutFrames + ld a, $3 + ld [hli], a + xor a + ld [hl], a + call WaitBGMap + ld a, $2 + ldh [hVBlank], a + call DelayFrame + call DelayFrame + call Link_CheckCommunicationError + ld a, [wScriptVar] + and a + jr z, .vblank + ld bc, -1 +.wait + dec bc + ld a, b + or c + jr nz, .wait + ld a, [wOtherPlayerLinkMode] + cp $5 + jr nz, .script_var + ld a, $6 + ld [wPlayerLinkAction], a + ld hl, wLinkTimeoutFrames + ld a, $1 + ld [hli], a + ld [hl], $32 + call Link_CheckCommunicationError + ld a, [wOtherPlayerLinkMode] + cp $6 + jr z, .vblank + +.script_var + xor a + ld [wScriptVar], a + ret + +.vblank + xor a + ldh [hVBlank], a + ret + +Link_CheckCommunicationError: + xor a + ldh [hSerialReceivedNewData], a + call WaitLinkTransfer + ld hl, wLinkTimeoutFrames + ld a, [hli] + inc a + jr nz, .load_true + ld a, [hl] + inc a + jr nz, .load_true + ld b, 10 + +.acknowledge_serial +.loop + call DelayFrame + call LinkDataReceived + dec b + jr nz, .loop + + xor a + jr .load_scriptvar + +.load_true + ld a, $1 + +.load_scriptvar + ld [wScriptVar], a + ld hl, wLinkTimeoutFrames + xor a + ld [hli], a + ld [hl], a + ret + +TryQuickSave: + ld a, [wChosenCableClubRoom] + push af + farcall Link_SaveGame + ld a, TRUE + jr nc, .return_result + xor a ; FALSE +.return_result + ld [wScriptVar], a + ld c, 30 + call DelayFrames + pop af + ld [wChosenCableClubRoom], a + ret + +CheckBothSelectedSameRoom: + ld a, [wChosenCableClubRoom] + call Link_EnsureSync + push af + call LinkDataReceived + call DelayFrame + call LinkDataReceived + pop af + ld b, a + ld a, [wChosenCableClubRoom] + cp b + jr nz, .fail + ld a, [wChosenCableClubRoom] + inc a + ld [wLinkMode], a + xor a + ldh [hVBlank], a + ld a, TRUE + ld [wScriptVar], a + ret + +.fail + xor a ; FALSE + ld [wScriptVar], a + ret + +TimeCapsule: + ld a, LINK_TIMECAPSULE + ld [wLinkMode], a + call DisableSpriteUpdates + callfar LinkCommunications + call EnableSpriteUpdates + xor a + ldh [hVBlank], a + ret + +TradeCenter: + ld a, LINK_TRADECENTER + ld [wLinkMode], a + call DisableSpriteUpdates + callfar LinkCommunications + call EnableSpriteUpdates + xor a + ldh [hVBlank], a + ret + +Colosseum: + ld a, LINK_COLOSSEUM + ld [wLinkMode], a + call DisableSpriteUpdates + callfar LinkCommunications + call EnableSpriteUpdates + xor a + ldh [hVBlank], a + ret + +CloseLink: + ld c, 3 + call DelayFrames + jp Link_ResetSerialRegistersAfterLinkClosure + +FailedLinkToPast: + ld c, 40 + call DelayFrames + ld a, $e + jp Link_EnsureSync + +Link_ResetSerialRegistersAfterLinkClosure: + ld c, 3 + call DelayFrames + ld a, CONNECTION_NOT_ESTABLISHED + ldh [hSerialConnectionStatus], a + ld a, $2 + ldh [rSB], a + xor a + ldh [hSerialReceive], a + ldh [rSC], a + ret + +Link_EnsureSync: + add $d0 + ld [wPlayerLinkAction], a + ld [wce57], a + ld a, $2 + ldh [hVBlank], a + call DelayFrame + call DelayFrame +.receive_loop + call Serial_ExchangeLinkMenuSelection + ld a, [wOtherPlayerLinkMode] + ld b, a + and $f0 + cp $d0 + jr z, .done + ld a, [wOtherPlayerLinkAction] + ld b, a + and $f0 + cp $d0 + jr nz, .receive_loop + +.done + xor a + ldh [hVBlank], a + ld a, b + and $f + ret + +CableClubCheckWhichChris: + ldh a, [hSerialConnectionStatus] + cp USING_EXTERNAL_CLOCK + ld a, TRUE + jr z, .yes + dec a ; FALSE + +.yes + ld [wScriptVar], a + ret + +LinkCommsBorderGFX: +INCBIN "gfx/trade/border_tiles.2bpp" + +Unreferenced_Function29fe4: + ld a, BANK(sPartyMail) + call OpenSRAM + ld d, FALSE + ld b, CHECK_FLAG + predef SmallFarFlagAction + call CloseSRAM + ld a, c + and a + ret diff --git a/engine/link/mystery_gift.asm b/engine/link/mystery_gift.asm new file mode 100644 index 00000000..55a35982 --- /dev/null +++ b/engine/link/mystery_gift.asm @@ -0,0 +1,1077 @@ +DoMysteryGift: + call ClearTilemap + call ClearSprites + call WaitBGMap + farcall InitMysteryGiftLayout + hlcoord 3, 8 + ld de, .String_PressAToLink_BToCancel + call PlaceString + call WaitBGMap + farcall PrepMysteryGiftDataToSend + call MysteryGift_ClearTrainerData + ld a, $2 + ld [wc901], a + ld a, $14 + ld [wc902], a + ldh a, [rIE] + push af + + call Function29fc9 + + ld d, a + xor a + ldh [rIF], a + pop af + ldh [rIE], a + push de + call ClearTilemap + call EnableLCD + call WaitBGMap + ld b, SCGB_DIPLOMA + call GetSGBLayout + call SetPalettes + pop de + hlcoord 2, 8 + ld a, d + ld de, .MysteryGiftCanceledText ; Link has been canceled + cp $10 + jp z, .LinkCanceled + cp $6c + jp nz, .CommunicationError + ld a, [wc800] + cp 3 + jr z, .skip_checks + call .CheckAlreadyGotFiveGiftsToday + ld hl, .MysteryGiftFiveADayText ; Only 5 gifts a day + jp nc, .PrintTextAndExit + call .CheckAlreadyGotAGiftFromThatPerson + ld hl, .MysteryGiftOneADayText ; Only one gift a day per person + jp c, .PrintTextAndExit +.skip_checks + ld a, [wMysteryGiftPlayerBackupItem] + and a + jr nz, .GiftWaiting + ld a, [wMysteryGiftPartnerBackupItem] + and a + jr nz, .FriendNotReady + ld a, [wc800] + cp 3 + jr z, .skip_append_save + call .AddMysteryGiftPartnerID + ld a, [wc800] + cp 4 + jr z, .skip_append_save + call .SaveMysteryGiftTrainerName +.skip_append_save + ld a, [wMysteryGiftPartnerSentDeco] + and a + jr z, .item + ld a, [wMysteryGiftPartnerWhichDeco] + ld c, a + farcall MysteryGiftGetDecoration + push bc + call MysteryGift_CheckAndSetDecorationAlreadyReceived + pop bc + jr nz, .item + callfar GetDecorationName_c + ld h, d + ld l, e + ld de, wStringBuffer1 + ld bc, ITEM_NAME_LENGTH + call CopyBytes + ld hl, .MysteryGiftSentHomeText ; sent decoration to home + jr .PrintTextAndExit + +.item + call GetMysteryGiftBank + ld a, [wMysteryGiftPartnerWhichItem] + ld c, a + farcall MysteryGiftGetItemHeldEffect + ld a, c + ld [sBackupMysteryGiftItem], a + ld [wNamedObjectIndexBuffer], a + call CloseSRAM + call GetItemName + ld hl, .MysteryGiftSentText ; sent item + jr .PrintTextAndExit + +.LinkCanceled: + ld hl, .MysteryGiftCanceledText ; Link has been canceled + jr .PrintTextAndExit + +.CommunicationError: + ld hl, .MysteryGiftCommErrorText ; Communication error + call PrintText + jp DoMysteryGift + +.GiftWaiting: + ld hl, .RetrieveMysteryGiftText ; receive gift at counter + jr .PrintTextAndExit + +.FriendNotReady: + ld hl, .YourFriendIsNotReadyText ; friend not ready + +.PrintTextAndExit: + call PrintText + ld a, LCDC_DEFAULT + ldh [rLCDC], a + ret + +.String_PressAToLink_BToCancel: + db "Press A to" + next "link IR-Device" + next "Press B to" + next "cancel it." + db "@" + +.MysteryGiftCanceledText: + text_far _MysteryGiftCanceledText + text_end + +.MysteryGiftCommErrorText: + text_far _MysteryGiftCommErrorText + text_end + +.RetrieveMysteryGiftText: + text_far _RetrieveMysteryGiftText + text_end + +.YourFriendIsNotReadyText: + text_far _YourFriendIsNotReadyText + text_end + +.MysteryGiftFiveADayText: + text_far _MysteryGiftFiveADayText + text_end + +.MysteryGiftOneADayText: + text_far _MysteryGiftOneADayText + text_end + +.MysteryGiftSentText: + text_far _MysteryGiftSentText + text_end + +.MysteryGiftSentHomeText: + text_far _MysteryGiftSentHomeText + text_end + +.CheckAlreadyGotFiveGiftsToday: + call GetMysteryGiftBank + ld a, [sNumDailyMysteryGiftPartnerIDs] + cp $5 + jp CloseSRAM + +.CheckAlreadyGotAGiftFromThatPerson: + call GetMysteryGiftBank + ld a, [wMysteryGiftPartnerID] + ld b, a + ld a, [wMysteryGiftPartnerID + 1] + ld c, a + ld a, [sNumDailyMysteryGiftPartnerIDs] + ld d, a + ld hl, sDailyMysteryGiftPartnerIDs +.loop + ld a, d + and a + jr z, .No + ld a, [hli] + cp b + jr nz, .skip + ld a, [hl] + cp c + jr z, .Yes +.skip + inc hl + dec d + jr .loop +.Yes: + scf +.No: + jp CloseSRAM + +.AddMysteryGiftPartnerID: + call GetMysteryGiftBank + ld hl, sNumDailyMysteryGiftPartnerIDs + ld a, [hl] + inc [hl] + ld hl, sDailyMysteryGiftPartnerIDs ; inc hl + ld e, a + ld d, $0 + add hl, de + add hl, de + ld a, [wMysteryGiftPartnerID] + ld [hli], a + ld a, [wMysteryGiftPartnerID + 1] + ld [hl], a + jp CloseSRAM + +.SaveMysteryGiftTrainerName: + call GetMysteryGiftBank + ld a, $1 + ld [sMysteryGiftTrainerHouseFlag], a + ld hl, wMysteryGiftPartnerName + ld de, sMysteryGiftPartnerName + ld bc, NAME_LENGTH + call CopyBytes + ld a, $1 + ld [de], a + inc de + ld hl, wMysteryGiftTrainerData + ld bc, (1 + 1 + NUM_MOVES) * PARTY_LENGTH + 2 + call CopyBytes + jp CloseSRAM + +Function29fc9: + farcall ClearChannels + call Function2a18c + +.loop2 + call Function2a1c4 + call Function2a20b + ldh a, [hMGStatusFlags] + cp $10 + jp z, Function2a103 + cp $6c + jr nz, .loop2 + + ldh a, [hPrintNumBuffer + 8] + cp $2 + jr z, Function2a055 + ld hl, hPrintNumBuffer + ld b, $1 + call Function2a184 + jr nz, .ly_loop + call Function2a07c + jp nz, Function2a103 + jr Function2a03d + ; Delay frame +.ly_loop + ldh a, [rLY] + cp LY_VBLANK + jr c, .ly_loop + ld c, LOW(rRP) + ld a, $c0 + ldh [c], a + ld b, 240 ; This might have been intended as a 4-second timeout buffer. + ; However, it is reset with each frame. +.loop3 + push bc + call MysteryGift_ReadJoypad + + ld b, $2 + ld c, LOW(rRP) + ; Delay frame +.ly_loop2 + ldh a, [c] + and b + ld b, a + ldh a, [rLY] + cp LY_VBLANK + jr nc, .ly_loop2 +.ly_loop3 + ldh a, [c] + and b + ld b, a + ldh a, [rLY] + cp LY_VBLANK + jr c, .ly_loop3 + + ld a, b + pop bc + dec b + jr z, .loop2 ; we never jump here + or a + jr nz, .loop2 + ; Check if we've pressed the B button + ldh a, [hMGJoypadReleased] + bit B_BUTTON_F, a + jr z, .loop3 + ld a, $10 + ldh [hMGStatusFlags], a + jp Function2a103 + +Function2a037: + call Function2a073 + jp nz, Function2a103 +; fall through +Function2a03d: + call Function2a166 + jp nz, Function2a103 + call Function2a0bb + jp nz, Function2a103 + call Function2a171 + jp nz, Function2a103 + call Function2a461 + jp Function2a103 + +Function2a055: + call Function2a0bb + jp nz, Function2a103 + call Function2a171 + jp nz, Function2a103 + call Function2a073 + jp nz, Function2a103 + call Function2a166 + jp nz, Function2a103 + call Function2a45c + jp Function2a103 + +Function2a073: + ld hl, hPrintNumBuffer + ld b, $1 + call Function2a184 + ret nz +; fall through +Function2a07c: + call Function2a461 + ldh a, [hMGStatusFlags] + cp $6c + ret nz + ldh a, [hPrintNumBuffer] + cp $96 + jp nz, Function2a160 + ld a, $90 + ldh [hPrintNumBuffer], a + call Function2a166 + ret nz + ld hl, hPrintNumBuffer + ld b, $1 + call Function2a17c + ret nz + call Function2a45c + ldh a, [hMGStatusFlags] + cp $6c + ret nz + call Function2a171 + ret nz + ld hl, wMysteryGiftTrainerData + ld a, [wc902] + ld b, a + call Function2a184 + ret nz + call Function2a461 + ldh a, [hMGStatusFlags] + cp $6c + ret + +Function2a0bb: + ld a, $96 + ldh [hPrintNumBuffer], a + ld hl, hPrintNumBuffer + ld b, $1 + call Function2a17c + ret nz + call Function2a45c + ldh a, [hMGStatusFlags] + cp $6c + ret nz + call Function2a171 + ret nz + ld hl, hPrintNumBuffer + ld b, $1 + call Function2a184 + ret nz + call Function2a461 + ldh a, [hMGStatusFlags] + cp $6c + ret nz + ldh a, [hPrintNumBuffer] + cp $90 + jp nz, Function2a160 + call Function2a166 + ret nz + ld hl, wLinkData + ld a, [wc902] + ld b, a + call Function2a17c + ret nz + call Function2a45c + ldh a, [hMGStatusFlags] + cp $6c + ret + +Function2a103: + nop + ldh a, [hMGStatusFlags] + cp $10 + jr z, .quit + cp $6c + jr nz, .quit + ld hl, wc901 + dec [hl] + jr z, .quit + ld hl, wMysteryGiftTrainerData + ld de, wMysteryGiftPartnerData + ld bc, wMysteryGiftPartnerDataEnd - wMysteryGiftPartnerData + call CopyBytes + ld a, [wMysteryGiftTrainerData] + cp $3 + jr nc, .quit + farcall StagePartyDataForMysteryGift + call MysteryGift_ClearTrainerData + ld a, $26 + ld [wc902], a + ldh a, [hPrintNumBuffer + 8] + cp $2 + jr z, .asm_2a143 + call Function2a171 + jr nz, Function2a103 + jp Function2a037 + +.asm_2a143 + call Function2a166 + jr nz, Function2a103 + jp Function2a055 + +.quit: + xor a + ldh [rIF], a + ldh a, [rIE] + or 1 << VBLANK + ldh [rIE], a + ei + call DelayFrame + ldh a, [hMGStatusFlags] + push af + call Function2a1ce + pop af + ret + +Function2a160: + ld a, $80 + ldh [hMGStatusFlags], a + and a + ret + +Function2a166: + call Function2a1c4 + call Function2a274 + ldh a, [hMGStatusFlags] + cp $6c + ret + +Function2a171: + call Function2a1c4 + call Function2a22c + ldh a, [hMGStatusFlags] + cp $6c + ret + +Function2a17c: + call Function2a2c1 + ldh a, [hMGStatusFlags] + cp $6c + ret + +Function2a184: + call Function2a385 + ldh a, [hMGStatusFlags] + cp $6c + ret + +Function2a18c: + call Function2a1a2 + ld a, 1 << TIMER + ldh [rIE], a + xor a + ldh [rIF], a + call Function2a1c4 + xor a + ld b, a +.asm_2a19b + inc a + jr nz, .asm_2a19b + inc b + jr nz, .asm_2a19b + ret + +Function2a1a2: + xor a + ldh [rTAC], a + ld a, $fe + ldh [rTMA], a + ldh [rTIMA], a + ld a, $2 + ldh [rTAC], a + or $4 + ldh [rTAC], a + ret + +Function2a1b4: + xor a + ldh [rTAC], a + ldh [rTMA], a + ldh [rTIMA], a + ld a, $2 + ldh [rTAC], a + or $4 + ldh [rTAC], a + ret + +Function2a1c4: + ld a, $c0 + call Function2a2ba + ld a, $1 + ldh [hPrintNumBuffer + 8], a + ret + +Function2a1ce: + xor a + call Function2a2ba + ld a, $2 + ldh [rTAC], a + ret + +Function2a1d7: + inc d + ret z + xor a + ldh [rIF], a + halt + ldh a, [c] + bit 1, a + jr z, Function2a1d7 + or a + ret + +Function2a1e5: + inc d + ret z + xor a + ldh [rIF], a + halt + ldh a, [c] + bit 1, a + jr nz, Function2a1e5 + or a + ret + +Function2a1f3: + ld a, $c1 + ldh [c], a +.wait + dec d + ret z + xor a + ldh [rIF], a + halt + jr .wait + +Function2a1ff: + ld a, $c0 + ldh [c], a +.wait + dec d + ret z + xor a + ldh [rIF], a + halt + jr .wait + +Function2a20b: + ld d, $0 + ld e, d + ld a, $1 + ldh [hPrintNumBuffer + 8], a +.loop + call MysteryGift_ReadJoypad + ld b, $2 + ld c, LOW(rRP) + ldh a, [hMGJoypadReleased] + bit B_BUTTON_F, a + jr z, .next + ld a, $10 + ldh [hMGStatusFlags], a + ret + +.next + bit 0, a + jr nz, Function2a268 + ldh a, [c] + and b + jr nz, .loop + +Function2a22c: + ld c, LOW(rRP) + ld d, $0 + ld e, d + call Function2a1e5 + jp z, Function2a370 + ld d, e + call Function2a1d7 + jp z, Function2a370 + call Function2a1e5 + jp z, Function2a370 + call Function2a1d7 + jp z, Function2a370 + ld a, $6c + ldh [hMGStatusFlags], a + ld d, $3d + call Function2a1ff + ld d, $5 + call Function2a1f3 + ld d, $15 + call Function2a1ff + ld d, $5 + call Function2a1f3 + ld d, $5 + call Function2a1ff + ret + +Function2a268: + ; Wait a random amount of time + call Random + ld e, a + and $f + ld d, a +.loop + dec de + ld a, d + or e + jr nz, .loop +Function2a274: + ld a, $2 + ldh [hPrintNumBuffer + 8], a + ld c, LOW(rRP) + ld d, $0 + ld e, d + ld d, $3d + call Function2a1ff + ld d, $5 + call Function2a1f3 + ld d, $15 + call Function2a1ff + ld d, $5 + call Function2a1f3 + ld d, $5 + call Function2a1ff + ld d, e + call Function2a1e5 + jp z, Function2a370 + ld d, e + call Function2a1d7 + jp z, Function2a370 + call Function2a1e5 + jp z, Function2a370 + call Function2a1d7 + jp z, Function2a370 + ld d, $3d + call Function2a1ff + ld a, $6c + ldh [hMGStatusFlags], a + ret + +Function2a2ba: + ldh [rRP], a + ld a, $ff + ldh [hMGStatusFlags], a + ret + +Function2a2c1: + xor a + ldh [hPrintNumBuffer + 4], a + ldh [hPrintNumBuffer + 5], a + push hl + push bc + ld c, LOW(rRP) + ld d, $3d + call Function2a1ff + ld hl, hPrintNumBuffer + 1 + ld a, $5a + ld [hli], a + ld [hl], b + dec hl + ld b, $2 + call Function2a304 + pop bc + pop hl + call Function2a304 + ldh a, [hPrintNumBuffer + 4] + ldh [hPrintNumBuffer + 1], a + ldh a, [hPrintNumBuffer + 5] + ldh [hPrintNumBuffer + 2], a + push hl + ld hl, hPrintNumBuffer + 1 + ld b, $2 + call Function2a304 + ld hl, hMGStatusFlags + ld b, $1 + call Function2a3dd + ldh a, [hPrintNumBuffer + 1] + ldh [hPrintNumBuffer + 4], a + ldh a, [hPrintNumBuffer + 2] + ldh [hPrintNumBuffer + 5], a + pop hl + ret + +Function2a304: + ld c, LOW(rRP) + ld d, $5 + call Function2a1ff + ld d, $5 + call Function2a1f3 + ld d, $15 + call Function2a1ff + ld a, b + cpl + ld b, a + ld a, $f4 + ldh [rTMA], a +.asm_2a31c + inc b + jr z, .asm_2a35c + ld a, $8 + ldh [hPrintNumBuffer + 3], a + ld a, [hli] + ld e, a + ldh a, [hPrintNumBuffer + 4] + add e + ldh [hPrintNumBuffer + 4], a + ldh a, [hPrintNumBuffer + 5] + adc 0 + ldh [hPrintNumBuffer + 5], a +.asm_2a330 + xor a + ldh [rIF], a + halt + ld a, $c1 + ldh [rRP], a + ld d, $1 + ld a, e + rlca + ld e, a + jr nc, .asm_2a341 + inc d +.asm_2a341 + ldh a, [rTIMA] + cp $f8 + jr c, .asm_2a341 + ld a, $c0 + ldh [rRP], a + dec d + jr z, .asm_2a353 + xor a + ldh [rIF], a + halt +.asm_2a353 + ldh a, [hPrintNumBuffer + 3] + dec a + jr z, .asm_2a31c + ldh [hPrintNumBuffer + 3], a + jr .asm_2a330 +.asm_2a35c + ld a, $fe + ldh [rTMA], a + xor a + ldh [rIF], a + halt + ld d, $5 + call Function2a1f3 + ld d, $11 + call Function2a1ff + ret + +Function2a370: + ldh a, [hMGStatusFlags] + or $2 + ldh [hMGStatusFlags], a + ret + +Function2a377: + ldh a, [hMGStatusFlags] + or $1 + ldh [hMGStatusFlags], a + ret + +Function2a37e: + ldh a, [hMGStatusFlags] + or $80 + ldh [hMGStatusFlags], a + ret + +Function2a385: + xor a + ldh [hPrintNumBuffer + 4], a + ldh [hPrintNumBuffer + 5], a + push bc + push hl + ld hl, hPrintNumBuffer + 1 + ld b, $2 + call Function2a3dd + ldh a, [hPrintNumBuffer + 2] + ldh [hPrintNumBuffer + 7], a + ld b, a + pop hl + pop af + cp b + jp c, Function2a37e + ldh a, [hPrintNumBuffer + 1] + cp $5a + jp nz, Function2a37e + call Function2a3dd + ldh a, [hPrintNumBuffer + 4] + ld d, a + ldh a, [hPrintNumBuffer + 5] + ld e, a + push hl + push de + ld hl, hPrintNumBuffer + 1 + ld b, $2 + call Function2a3dd + pop de + ld hl, hPrintNumBuffer + 1 + ld a, [hli] + xor d + ld b, a + ld a, [hl] + xor e + or b + call nz, Function2a377 + push de + ld d, $3d + call Function2a1ff + ld hl, hMGStatusFlags + ld b, $1 + call Function2a304 + pop de + pop hl + ld a, d + ldh [hPrintNumBuffer + 4], a + ld a, e + ldh [hPrintNumBuffer + 5], a + ret + +Function2a3dd: + ld c, LOW(rRP) + ld d, $0 + call Function2a1e5 + jp z, Function2a370 + ld d, $0 + call Function2a1d7 + jp z, Function2a370 + ld d, $0 + call Function2a1e5 + jp z, Function2a370 + ld a, b + cpl + ld b, a + xor a + ldh [hMGPrevTIMA], a + call Function2a1b4 +.asm_2a400 + inc b + jr z, .asm_2a448 + ld a, $8 + ldh [hPrintNumBuffer + 3], a +.asm_2a407 + ld d, $0 +.asm_2a409 + inc d + jr z, .asm_2a413 + ldh a, [c] + bit 1, a + jr z, .asm_2a409 + ld d, $0 +.asm_2a413 + inc d + jr z, .asm_2a41b + ldh a, [c] + bit 1, a + jr nz, .asm_2a413 +.asm_2a41b + ldh a, [hMGPrevTIMA] + ld d, a + ldh a, [rTIMA] + ldh [hMGPrevTIMA], a + sub d + cp $12 + jr c, .asm_2a42b + set 0, e + jr .asm_2a42d +.asm_2a42b + res 0, e +.asm_2a42d + ldh a, [hPrintNumBuffer + 3] + dec a + ldh [hPrintNumBuffer + 3], a + jr z, .asm_2a439 + ld a, e + rlca + ld e, a + jr .asm_2a407 +.asm_2a439 + ld a, e + ld [hli], a + ldh a, [hPrintNumBuffer + 4] + add e + ldh [hPrintNumBuffer + 4], a + ldh a, [hPrintNumBuffer + 5] + adc 0 + ldh [hPrintNumBuffer + 5], a + jr .asm_2a400 +.asm_2a448 + call Function2a1a2 + xor a + ldh [rIF], a + ld d, $0 + call Function2a1d7 + jp z, Function2a370 + ld d, $10 + call Function2a1ff + ret + +Function2a45c: + ld b, $0 + jp Function2a2c1 + +Function2a461: + ld b, $0 + jp Function2a385 + +MysteryGift_ReadJoypad: +; We can only get four inputs at a time. +; We take d-pad first for no particular reason. + ld a, R_DPAD + ldh [rJOYP], a +; Read twice to give the request time to take. + ldh a, [rJOYP] + ldh a, [rJOYP] + +; The Joypad register output is in the lo nybble (inversed). +; We make the hi nybble of our new container d-pad input. + cpl + and $f + swap a + +; We'll keep this in b for now. + ld b, a + +; Buttons make 8 total inputs (A, B, Select, Start). +; We can fit this into one byte. + ld a, R_BUTTONS + ldh [rJOYP], a +; Wait for input to stabilize. +rept 6 + ldh a, [rJOYP] +endr +; Buttons take the lo nybble. + cpl + and $f + or b + ld c, a +; To get the delta we xor the last frame's input with the new one. + ldh a, [hMGJoypadPressed] + xor c +; Released this frame: + and c + ldh [hMGJoypadReleased], a +; Pressed this frame: + ld a, c + ldh [hMGJoypadPressed], a + ld a, $30 +; Reset the joypad register since we're done with it. + ldh [rJOYP], a + ret + +MysteryGift_CheckAndSetDecorationAlreadyReceived: + call GetMysteryGiftBank + ld d, $0 + ld b, CHECK_FLAG + ld hl, sMysteryGiftDecorationsReceived + predef_id SmallFarFlagAction + push hl + push bc + call Predef + call CloseSRAM + ld a, c + and a + pop bc + pop hl + ret nz + call GetMysteryGiftBank + ld b, SET_FLAG + predef SmallFarFlagAction + call CloseSRAM + xor a + ret + +MysteryGift_CopyReceivedDecosToPC: + call GetMysteryGiftBank + ld c, $0 +.loop + push bc + ld d, $0 + ld b, CHECK_FLAG + ld hl, sMysteryGiftDecorationsReceived + predef SmallFarFlagAction + ld a, c + and a + pop bc + jr z, .skip + push bc + callfar SetSpecificDecorationFlag + pop bc +.skip + inc c + ld a, c + cp TrophyIDs - DecorationIDs + jr c, .loop + jp CloseSRAM + +UnlockMysteryGift: + call GetMysteryGiftBank + ld hl, sMysteryGiftUnlocked + ld a, [hl] + inc a + jr nz, .ok + ld [hld], a + ld [hl], a +.ok + jp CloseSRAM + +Function2a4f6: + call GetMysteryGiftBank + ld a, [sNumDailyMysteryGiftPartnerIDs] + cp $ff + jr z, .okay + xor a + ld [sNumDailyMysteryGiftPartnerIDs], a +.okay + jp CloseSRAM + +BackupMysteryGift: + call GetMysteryGiftBank + ld hl, sMysteryGiftItem + ld de, sBackupMysteryGiftItem + ld a, [hli] + ld [de], a + inc de + ld a, [hl] + ld [de], a + jp CloseSRAM + +RestoreMysteryGift: + call GetMysteryGiftBank + ld hl, sBackupMysteryGiftItem + ld de, sMysteryGiftItem + ld a, [hli] + ld [de], a + inc de + ld a, [hl] + ld [de], a + jp CloseSRAM + +MysteryGift_ClearTrainerData: + ld hl, wMysteryGiftTrainerData + xor a + ld b, wMysteryGiftTrainerDataEnd - wMysteryGiftTrainerData +.loop + ld [hli], a + dec b + jr nz, .loop + ret + +GetMysteryGiftBank: + ld a, BANK(sBackupMysteryGiftItem) + jp OpenSRAM |