diff options
author | entrpntr <entrpntr@gmail.com> | 2020-04-30 23:37:15 -0400 |
---|---|---|
committer | entrpntr <entrpntr@gmail.com> | 2020-04-30 23:50:43 -0400 |
commit | 03bc01bf4efea42661600089af1a8ff787a093a5 (patch) | |
tree | cade8dc8d5d3aff4d849d0275d5f7b99022f3d13 /engine/link/link.asm | |
parent | 35f6c55eac49c0357bb7939f0e4c2667f09821d3 (diff) |
Add engine/link/link.asm and engine/link/mystery_gift.asm
Diffstat (limited to 'engine/link/link.asm')
-rw-r--r-- | engine/link/link.asm | 2345 |
1 files changed, 2345 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 |