summaryrefslogtreecommitdiff
path: root/engine/link
diff options
context:
space:
mode:
Diffstat (limited to 'engine/link')
-rw-r--r--engine/link/init_list.asm54
-rw-r--r--engine/link/link.asm2589
-rw-r--r--engine/link/link_2.asm95
-rw-r--r--engine/link/link_trade.asm363
-rw-r--r--engine/link/mystery_gift.asm1735
-rw-r--r--engine/link/mystery_gift_2.asm152
-rw-r--r--engine/link/place_waiting_text.asm24
-rw-r--r--engine/link/time_capsule.asm147
-rw-r--r--engine/link/time_capsule_2.asm39
9 files changed, 5198 insertions, 0 deletions
diff --git a/engine/link/init_list.asm b/engine/link/init_list.asm
new file mode 100644
index 000000000..26c77b5bb
--- /dev/null
+++ b/engine/link/init_list.asm
@@ -0,0 +1,54 @@
+InitList: ; 50db9
+ ld a, [wInitListType]
+
+ cp INIT_ENEMYOT_LIST
+ jr nz, .check_party_ot_name
+ ld hl, wOTPartyCount
+ ld de, wOTPartyMonOT
+ ld a, ENEMY_OT_NAME
+ jr .done
+
+.check_party_ot_name
+ cp INIT_PLAYEROT_LIST
+ jr nz, .check_mon_name
+ ld hl, wPartyCount
+ ld de, wPartyMonOT
+ ld a, PARTY_OT_NAME
+ jr .done
+
+.check_mon_name
+ cp INIT_MON_LIST
+ jr nz, .check_item_name
+ ld hl, wCurMart
+ ld de, PokemonNames
+ ld a, MON_NAME
+ jr .done
+
+.check_item_name
+ cp INIT_BAG_ITEM_LIST
+ jr nz, .check_ob_item_name
+ ld hl, wNumItems
+ ld de, ItemNames
+ ld a, ITEM_NAME
+ jr .done
+
+.check_ob_item_name
+ ld hl, wCurMart
+ ld de, ItemNames
+ ld a, ITEM_NAME
+.done
+ ld [wNamedObjectTypeBuffer], a
+ ld a, l
+ ld [wListPointer], a
+ ld a, h
+ ld [wListPointer + 1], a
+ ld a, e
+ ld [wUnusedD102], a
+ ld a, d
+ ld [wUnusedD102 + 1], a
+ ld bc, ItemAttributes
+ ld a, c
+ ld [wItemAttributesPtr], a
+ ld a, b
+ ld [wItemAttributesPtr + 1], a
+ ret
diff --git a/engine/link/link.asm b/engine/link/link.asm
new file mode 100644
index 000000000..e0b7f7972
--- /dev/null
+++ b/engine/link/link.asm
@@ -0,0 +1,2589 @@
+LinkCommunications: ; 28000
+ call ClearBGPalettes
+ ld c, 80
+ call DelayFrames
+ call ClearScreen
+ call ClearSprites
+ call UpdateSprites
+ xor a
+ ld [hSCX], a
+ ld [hSCY], a
+ ld c, 80
+ call DelayFrames
+ call ClearScreen
+ call UpdateSprites
+ call LoadStandardFont
+ call LoadFontsBattleExtra
+ farcall LinkComms_LoadPleaseWaitTextboxBorderGFX
+ call WaitBGMap2
+ hlcoord 3, 8
+ ld b, 2
+ ld c, 12
+ ld d, h
+ ld e, l
+ farcall LinkTextbox2
+ hlcoord 4, 10
+ ld de, String_PleaseWait
+ call PlaceString
+ call SetTradeRoomBGPals
+ call WaitBGMap2
+ ld hl, wcf5d
+ xor a ; LOW($5000)
+ ld [hli], a
+ ld [hl], HIGH($5000)
+ ld a, [wLinkMode]
+ cp LINK_TIMECAPSULE
+ jp nz, Gen2ToGen2LinkComms
+
+Gen2ToGen1LinkComms: ; 2805d
+ call ClearLinkData
+ call Link_PrepPartyData_Gen1
+ call FixDataForLinkTransfer
+ xor a
+ ld [wPlayerLinkAction], a
+ call WaitLinkTransfer
+ ld a, [hSerialConnectionStatus]
+ cp USING_INTERNAL_CLOCK
+ jr nz, .player_1
+
+ ld c, 3
+ call DelayFrames
+ xor a
+ ld [hSerialSend], a
+ ld a, (0 << rSC_ON) | 1
+ ld [rSC], a
+ ld a, (1 << rSC_ON) | 1
+ ld [rSC], a
+
+ call DelayFrame
+ xor a
+ ld [hSerialSend], a
+ ld a, (0 << rSC_ON) | 1
+ ld [rSC], a
+ ld a, (1 << rSC_ON) | 1
+ ld [rSC], a
+
+.player_1
+ ld de, MUSIC_NONE
+ call PlayMusic
+ ld c, 3
+ call DelayFrames
+ xor a
+ ld [rIF], a
+ ld a, $8
+ ld [rIE], a
+ ld hl, wd1f3
+ 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, wLink_c608
+ ld de, wTrademons
+ ld bc, wTrademons - wLink_c608
+ call Serial_ExchangeBytes
+ xor a
+ ld [rIF], a
+ ld a, $1d
+ ld [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, wc90f
+ 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 [wd265], a
+ push hl
+ push de
+ callfar ConvertMon_1to2
+ pop de
+ pop hl
+ ld a, [wd265]
+ ld [de], a
+ inc de
+ jr .party_loop
+
+.done_party
+ ld [de], a
+ ld hl, wTimeCapsulePartyMon1Species
+ call Function2868a
+ ld a, LOW(wOTPartyMonOT)
+ ld [wUnusedD102], a
+ ld a, HIGH(wOTPartyMonOT)
+ ld [wUnusedD102 + 1], a
+ ld de, MUSIC_NONE
+ call PlayMusic
+ ld a, [hSerialConnectionStatus]
+ cp USING_INTERNAL_CLOCK
+ ld c, 66
+ call z, DelayFrames
+ ld de, MUSIC_ROUTE_30
+ call PlayMusic
+ jp InitTradeMenuDisplay
+; 28177
+
+Gen2ToGen2LinkComms: ; 28177
+ call ClearLinkData
+ call Link_PrepPartyData_Gen2
+ call FixDataForLinkTransfer
+ call Function29dba
+ ld a, [wScriptVar]
+ and a
+ jp z, LinkTimeout
+ ld a, [hSerialConnectionStatus]
+ cp USING_INTERNAL_CLOCK
+ jr nz, .Player1
+
+ ld c, 3
+ call DelayFrames
+ xor a
+ ld [hSerialSend], a
+ ld a, (0 << rSC_ON) | 1
+ ld [rSC], a
+ ld a, (1 << rSC_ON) | 1
+ ld [rSC], a
+
+ call DelayFrame
+ xor a
+ ld [hSerialSend], a
+ ld a, (0 << rSC_ON) | 1
+ ld [rSC], a
+ ld a, (1 << rSC_ON) | 1
+ ld [rSC], a
+
+.Player1:
+ ld de, MUSIC_NONE
+ call PlayMusic
+ ld c, 3
+ call DelayFrames
+ xor a
+ ld [rIF], a
+ ld a, $8
+ ld [rIE], a
+ ld hl, wd1f3
+ 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, wLink_c608
+ ld de, wTrademons
+ ld bc, wTrademons - wLink_c608
+ call Serial_ExchangeBytes
+ ld a, [wLinkMode]
+ cp LINK_TRADECENTER
+ jr nz, .not_trading
+ ld hl, wc9f4
+ ld de, wcb84
+ ld bc, $186
+ call ExchangeBytes
+
+.not_trading
+ xor a
+ ld [rIF], a
+ ld a, $1d
+ ld [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, wc90f
+ dec c
+ jr nz, .loop1
+ ld a, [wLinkMode]
+ cp LINK_TRADECENTER
+ jp nz, .skip_mail
+ ld hl, wcb84
+.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, wcb84
+ ld bc, $190 ; 400
+ call CopyBytes
+ ld hl, wcb84
+ 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, wcc9e
+.loop5
+ ld a, [de]
+ inc de
+ cp SERIAL_PATCH_LIST_PART_TERMINATOR
+ jr z, .start_copying_mail
+ ld hl, wcc4a
+ dec a
+ ld b, $0
+ ld c, a
+ add hl, bc
+ ld [hl], SERIAL_NO_DATA_BYTE
+ jr .loop5
+
+.start_copying_mail
+ ld hl, wcb84
+ ld de, wc9f4
+ 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, wc9f4
+ ld b, PARTY_LENGTH
+.copy_author_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, .copy_author_loop
+ ld b, PARTY_LENGTH
+ ld de, wc9f4
+.fix_mail_loop
+ push bc
+ push de
+ farcall IsMailEuropean
+ ld a, c
+ or a
+ jr z, .next
+ sub $3
+ jr nc, .skip
+ farcall DeutenEnglischenPost
+ jr .next
+
+.skip
+ cp $2
+ jr nc, .next
+ farcall HandleSpanishItalianMail
+
+.next
+ pop de
+ ld hl, MAIL_STRUCT_LENGTH
+ add hl, de
+ ld d, h
+ ld e, l
+ pop bc
+ dec b
+ jr nz, .fix_mail_loop
+ ld de, wcb0e
+ 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 [wUnusedD102], a
+ ld a, HIGH(wOTPartyMonOT)
+ ld [wUnusedD102 + 1], a
+ ld de, MUSIC_NONE
+ call PlayMusic
+ ld 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 ClearScreen
+ farcall Link_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
+ ld a, [rIE]
+ push af
+ ld a, [rIF]
+ push af
+ xor a
+ ld [rIF], a
+ ld a, [rIE]
+ set 1, a
+ ld [rIE], a
+ pop af
+ ld [rIF], a
+
+ predef StartBattle
+
+ ld a, [rIF]
+ ld h, a
+ xor a
+ ld [rIF], a
+ pop af
+ ld [rIE], a
+ ld a, h
+ ld [rIF], a
+ 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
+; 283b2
+
+LinkTimeout: ; 283b2
+ ld de, .TooMuchTimeHasElapsed
+ ld b, 10
+.loop
+ call DelayFrame
+ call LinkDataReceived
+ dec b
+ jr nz, .loop
+ xor a
+ ld [hld], a
+ ld [hl], a
+ ld [hVBlank], a
+ push de
+ hlcoord 0, 12
+ ld b, 4
+ ld c, 18
+ push de
+ ld d, h
+ ld e, l
+ farcall LinkTextbox2
+ pop de
+ pop hl
+ bccoord 1, 14
+ call PlaceHLTextAtBC
+ call RotateThreePalettesRight
+ call ClearScreen
+ ld b, SCGB_DIPLOMA
+ call GetSGBLayout
+ call WaitBGMap2
+ ret
+; 283ed
+
+.TooMuchTimeHasElapsed: ; 0x283ed
+ ; Too much time has elapsed. Please try again.
+ text_jump UnknownText_0x1c4183
+ db "@"
+; 0x283f2
+
+ExchangeBytes: ; 283f2
+ ld a, TRUE
+ ld [hSerialIgnoringInitialData], a
+.loop
+ ld a, [hl]
+ ld [hSerialSend], a
+ call Serial_ExchangeByte
+ push bc
+ ld b, a
+ inc hl
+ ld a, 48
+.delay_cycles
+ dec a
+ jr nz, .delay_cycles
+ ld a, [hSerialIgnoringInitialData]
+ and a
+ ld a, b
+ pop bc
+ jr z, .load
+ dec hl
+ xor a
+ ld [hSerialIgnoringInitialData], a
+ jr .loop
+
+.load
+ ld [de], a
+ inc de
+ dec bc
+ ld a, b
+ or c
+ jr nz, .loop
+ ret
+; 28419
+
+String_PleaseWait: ; 28419
+ db "PLEASE WAIT!@"
+; 28426
+
+ClearLinkData: ; 28426
+ ld hl, wLinkData
+ ld bc, wLinkDataEnd - wLinkData
+.loop
+ xor a
+ ld [hli], a
+ dec bc
+ ld a, b
+ or c
+ jr nz, .loop
+ ret
+; 28434
+
+FixDataForLinkTransfer: ; 28434
+ ld hl, wd1f3
+ ld a, SERIAL_PREAMBLE_BYTE
+ ld b, wLinkBattleRNs - wd1f3
+.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, wLink_c608
+ 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 + 6
+ ld de, wc612
+ 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
+; 28499
+
+Link_PrepPartyData_Gen1: ; 28499
+ 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 [wd265], a
+ push hl
+ push de
+ callfar ConvertMon_2to1
+ pop de
+ pop hl
+ ld a, [wd265]
+ 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
+; 284f6
+
+.ConvertPartyStruct2to1: ; 284f6
+ ld b, h
+ ld c, l
+ push de
+ push bc
+ ld a, [hl]
+ ld [wd265], a
+ callfar ConvertMon_2to1
+ pop bc
+ pop de
+ ld a, [wd265]
+ 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
+
+ ld a, [hQuotient + 1]
+ ld [de], a
+ inc de
+ ld a, [hQuotient + 2]
+ ld [de], a
+ inc de
+ ld h, b
+ ld l, c
+ ret
+; 28595
+
+Link_PrepPartyData_Gen2: ; 28595
+ 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 wc9f4 with $20
+ ld de, wc9f4
+ ld a, $20
+ call Function28682
+
+; Copy all the mail messages to wc9f9
+ ld a, BANK(sPartyMail)
+ call GetSRAMBank
+ 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
+
+ ld b, PARTY_LENGTH
+ ld de, sPartyMail
+ ld hl, wc9f9
+.loop4
+ push bc
+ push hl
+ push de
+ push hl
+ farcall IsMailEuropean
+ pop de
+ ld a, c
+ or a
+ jr z, .next
+ sub $3
+ jr nc, .italian_spanish
+ farcall HandleFrenchGermanMail
+ jr .next
+
+.italian_spanish
+ cp $2
+ jr nc, .next
+ farcall HandleSpanishItalianMail
+
+.next
+ pop de
+ ld hl, MAIL_STRUCT_LENGTH
+ add hl, de
+ ld d, h
+ ld e, l
+ pop hl
+ ld bc, sPartyMon1MailAuthor - sPartyMon1Mail
+ add hl, bc
+ pop bc
+ dec b
+ jr nz, .loop4
+ call CloseSRAM
+ ld hl, wc9f9
+ ld bc, PARTY_LENGTH * (sPartyMon1MailAuthor - sPartyMon1Mail)
+.loop5
+ 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, .loop5
+ ld hl, wcabf
+ ld de, wcb13
+ ld b, PARTY_LENGTH * (sPartyMon1MailEnd - sPartyMon1MailAuthor)
+ ld c, $0
+.loop6
+ 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, .loop6
+ ld a, SERIAL_PATCH_LIST_PART_TERMINATOR
+ ld [de], a
+ ret
+; 28682
+
+Function28682: ; 28682
+ ld c, 5
+.loop
+ ld [de], a
+ inc de
+ dec c
+ jr nz, .loop
+ ret
+; 2868a
+
+Function2868a: ; 2868a
+ push hl
+ ld d, h
+ ld e, l
+ ld bc, wLinkOTPartyMonTypes
+ ld hl, wcbe8
+ 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
+; 286ba
+
+.ConvertToGen2: ; 286ba
+ ld b, h
+ ld c, l
+ ld a, [de]
+ inc de
+ push bc
+ push de
+ ld [wd265], a
+ callfar ConvertMon_1to2
+ pop de
+ pop bc
+ ld a, [wd265]
+ 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, wcbe8
+ 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 [wcbe8], a
+ ld a, h
+ ld [wcbe8 + 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
+ ld a, [hQuotient + 1]
+ ld [hli], a
+ ld a, [hQuotient + 2]
+ 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
+ ld a, [hQuotient + 1]
+ ld [hli], a
+ ld a, [hQuotient + 2]
+ 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
+; 28771
+
+TimeCapsule_ReplaceTeruSama: ; 28771
+ 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: ; 2879e
+.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
+; 287ab
+
+Link_CopyRandomNumbers: ; 287ab
+ ld 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
+; 287ca
+
+Link_FindFirstNonControlCharacter_SkipZero: ; 287ca
+.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
+; 287d8
+
+Link_FindFirstNonControlCharacter_AllowZero: ; 287d8
+.loop
+ ld a, [hli]
+ cp SERIAL_PREAMBLE_BYTE
+ jr z, .loop
+ cp SERIAL_NO_DATA_BYTE
+ jr z, .loop
+ dec hl
+ ret
+; 287e3
+
+InitTradeMenuDisplay: ; 287e3
+ call ClearScreen
+ call LoadTradeScreenBorder
+ farcall InitTradeSpeciesList
+ 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
+; 28803
+
+LinkTrade_OTPartyMenu: ; 28803
+ 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: ; 28835
+ farcall LinkTradeMenu
+ ld a, d
+ 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
+ farcall 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
+ push hl
+ push bc
+ ld bc, NAME_LENGTH
+ add hl, bc
+ ld [hl], " "
+ pop bc
+ pop hl
+ ld a, [wPartyCount]
+ ld [wMenuCursorY], a
+ jr LinkTrade_PlayerPartyMenu
+
+.not_d_up
+ bit D_DOWN_F, a
+ jp z, LinkTradePartiesMenuMasterLoop
+ jp Function28ac9
+; 2888b
+
+LinkTrade_PlayerPartyMenu: ; 2888b
+ farcall InitMG_Mobile_LinkTradePalMap
+ 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
+ call WaitBGMap2
+
+LinkTradePartymonMenuLoop: ; 288c5
+ farcall LinkTradeMenu
+ ld a, d
+ 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
+ push hl
+ push bc
+ ld bc, NAME_LENGTH
+ add hl, bc
+ ld [hl], " "
+ pop bc
+ pop hl
+ 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
+ push hl
+ push bc
+ ld bc, NAME_LENGTH
+ add hl, bc
+ ld [hl], " "
+ pop bc
+ pop hl
+ jp Function28ade
+; 2891c
+
+LinkTradePartiesMenuMasterLoop: ; 2891c
+ ld a, [wMonType]
+ and a
+ jp z, LinkTradePartymonMenuLoop ; PARTYMON
+ jp LinkTradeOTPartymonMenuLoop ; OTPARTYMON
+; 28926
+
+Function28926: ; 28926
+ call LoadTileMapToTempTileMap
+ 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
+ farcall Link_WaitBGMap
+
+.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 Call_LoadTempTileMapToTileMap
+ 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
+ farcall LinkMonStatsScreen
+ call Call_LoadTempTileMapToTileMap
+ hlcoord 6, 1
+ lb bc, 6, 1
+ ld a, " "
+ call LinkEngine_FillBox
+ hlcoord 17, 1
+ lb bc, 6, 1
+ ld a, " "
+ call LinkEngine_FillBox
+ jp LinkTrade_PlayerPartyMenu
+
+.try_trade
+ call PlaceHollowCursor
+ pop af
+ ld [wMenuCursorY], a
+ dec a
+ ld [wd002], a
+ ld [wPlayerLinkAction], a
+ farcall Function16d6ce
+ ld a, [wOtherPlayerLinkMode]
+ cp $f
+ jp z, InitTradeMenuDisplay
+ ld [wd003], a
+ call Function28b68
+ ld c, 100
+ call DelayFrames
+ farcall ValidateOTTrademon
+ jr c, .abnormal
+ farcall Functionfb5dd
+ jp nc, LinkTrade
+ xor a
+ ld [wcf57], a
+ ld [wOtherPlayerLinkAction], a
+ hlcoord 0, 12
+ ld b, 4
+ ld c, 18
+ call LinkTextboxAtHL
+ farcall Link_WaitBGMap
+ ld hl, .Text_CantTradeLastMon
+ bccoord 1, 14
+ call PlaceHLTextAtBC
+ jr .cancel_trade
+
+.abnormal
+ xor a
+ ld [wcf57], a
+ ld [wOtherPlayerLinkAction], a
+ ld a, [wd003]
+ ld hl, wOTPartySpecies
+ ld c, a
+ ld b, 0
+ add hl, bc
+ ld a, [hl]
+ ld [wd265], a
+ call GetPokemonName
+ hlcoord 0, 12
+ ld b, 4
+ ld c, 18
+ call LinkTextboxAtHL
+ farcall Link_WaitBGMap
+ ld hl, .Text_Abnormal
+ 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
+ farcall Function16d6ce
+ ld c, 100
+ call DelayFrames
+ jp InitTradeMenuDisplay
+; 28aaf
+
+
+.Text_CantTradeLastMon: ; 0x28aaf
+ ; If you trade that #MON, you won't be able to battle.
+ text_jump UnknownText_0x1c41b1
+ db "@"
+; 0x28ab4
+
+.String_Stats_Trade: ; 28ab4
+ db "STATS TRADE@"
+
+.Text_Abnormal: ; 0x28ac4
+ ; Your friend's @ appears to be abnormal!
+ text_jump UnknownText_0x1c41e6
+ db "@"
+; 0x28ac9
+
+
+Function28ac9: ; 28ac9
+ ld a, [wMenuCursorY]
+ cp 1
+ jp nz, LinkTradePartiesMenuMasterLoop
+ call HideCursor
+ push hl
+ push bc
+ ld bc, NAME_LENGTH
+ add hl, bc
+ ld [hl], " "
+ pop bc
+ pop hl
+Function28ade: ; 28ade
+.loop1
+ ld a, "▶"
+ ldcoord_a 9, 17
+.loop2
+ call JoyTextDelay
+ ld a, [hJoyLast]
+ and a
+ jr z, .loop2
+ bit A_BUTTON_F, a
+ jr nz, .a_button
+ push af
+ ld a, " "
+ ldcoord_a 9, 17
+ pop af
+ bit D_UP_F, a
+ jr z, .d_up
+ ld a, [wOTPartyCount]
+ ld [wMenuCursorY], a
+ jp LinkTrade_OTPartyMenu
+
+.d_up
+ ld a, $1
+ ld [wMenuCursorY], a
+ jp LinkTrade_PlayerPartyMenu
+
+.a_button
+ ld a, "▷"
+ ldcoord_a 9, 17
+ ld a, $f
+ ld [wPlayerLinkAction], a
+ farcall Function16d6ce
+ ld a, [wOtherPlayerLinkMode]
+ cp $f
+ jr nz, .loop1
+Function28b22: ; 28b22
+ call RotateThreePalettesRight
+ call ClearScreen
+ ld b, SCGB_DIPLOMA
+ call GetSGBLayout
+ call WaitBGMap2
+ xor a
+ ld [wcfbb], a
+ xor a
+ ld [rSB], a
+ ld [hSerialSend], a
+ ld a, (0 << rSC_ON) | 1
+ ld [rSC], a
+ ld a, (1 << rSC_ON) | 1
+ ld [rSC], a
+ ret
+; 28b42
+
+Unreferenced_Function28b42: ; 28b42
+ 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
+; 28b61
+
+.Cancel: ; 28b61
+ db "CANCEL@"
+; 28b68
+
+Function28b68: ; 28b68
+ ld a, [wOtherPlayerLinkMode]
+ hlcoord 6, 9
+ ld bc, SCREEN_WIDTH
+ call AddNTimes
+ ld [hl], "▷"
+ ret
+; 28b77
+
+LinkEngine_FillBox: ; 28b77
+.row
+ push bc
+ push hl
+.col
+ ld [hli], a
+ dec c
+ jr nz, .col
+ pop hl
+ ld bc, SCREEN_WIDTH
+ add hl, bc
+ pop bc
+ dec b
+ jr nz, .row
+ ret
+; 28b87
+
+LinkTrade: ; 28b87
+ xor a
+ ld [wcf57], a
+ ld [wOtherPlayerLinkAction], a
+ hlcoord 0, 12
+ ld b, 4
+ ld c, 18
+ call LinkTextboxAtHL
+ farcall Link_WaitBGMap
+ ld a, [wd002]
+ ld hl, wPartySpecies
+ ld c, a
+ ld b, 0
+ add hl, bc
+ ld a, [hl]
+ ld [wd265], a
+ call GetPokemonName
+ ld hl, wStringBuffer1
+ ld de, wd004
+ ld bc, MON_NAME_LENGTH
+ call CopyBytes
+ ld a, [wd003]
+ ld hl, wOTPartySpecies
+ ld c, a
+ ld b, 0
+ add hl, bc
+ ld a, [hl]
+ ld [wd265], a
+ call GetPokemonName
+ ld hl, UnknownText_0x28eb8
+ bccoord 1, 14
+ call PlaceHLTextAtBC
+ call LoadStandardMenuHeader
+ 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
+ farcall Link_WaitBGMap
+ call ScrollingMenuJoypad
+ push af
+ call Call_ExitMenu
+ call WaitBGMap2
+ 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
+ farcall Function16d6ce
+ jp Function28ea3
+
+.asm_28c54
+ ld a, $2
+ ld [wPlayerLinkAction], a
+ farcall Function16d6ce
+ 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, [wd002]
+ ld bc, MAIL_STRUCT_LENGTH
+ call AddNTimes
+ ld a, BANK(sPartyMail)
+ call GetSRAMBank
+ ld d, h
+ ld e, l
+ ld bc, MAIL_STRUCT_LENGTH
+ add hl, bc
+ ld a, [wd002]
+ 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, wc9f4
+ ld a, [wd003]
+ 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, [wd002]
+ ld hl, wPartySpecies
+ ld b, 0
+ ld c, a
+ add hl, bc
+ ld a, [hl]
+ ld [wPlayerTrademonSpecies], a
+ push af
+ ld a, [wd002]
+ ld hl, wPartyMonOT
+ call SkipNames
+ ld de, wPlayerTrademonOTName
+ ld bc, NAME_LENGTH
+ call CopyBytes
+ ld hl, wPartyMon1ID
+ ld a, [wd002]
+ call GetPartyLocation
+ ld a, [hli]
+ ld [wPlayerTrademonID], a
+ ld a, [hl]
+ ld [wPlayerTrademonID + 1], a
+ ld hl, wPartyMon1DVs
+ ld a, [wd002]
+ call GetPartyLocation
+ ld a, [hli]
+ ld [wPlayerTrademonDVs], a
+ ld a, [hl]
+ ld [wPlayerTrademonDVs + 1], a
+ ld a, [wd002]
+ ld hl, wPartyMon1Species
+ call GetPartyLocation
+ ld b, h
+ ld c, l
+ farcall GetCaughtGender
+ ld a, c
+ ld [wPlayerTrademonCaughtData], a
+ ld hl, wOTPlayerName
+ ld de, wOTTrademonSenderName
+ ld bc, NAME_LENGTH
+ call CopyBytes
+ ld a, [wd003]
+ ld hl, wOTPartySpecies
+ ld b, 0
+ ld c, a
+ add hl, bc
+ ld a, [hl]
+ ld [wOTTrademonSpecies], a
+ ld a, [wd003]
+ ld hl, wOTPartyMonOT
+ call SkipNames
+ ld de, wOTTrademonOTName
+ ld bc, NAME_LENGTH
+ call CopyBytes
+ ld hl, wOTPartyMon1ID
+ ld a, [wd003]
+ call GetPartyLocation
+ ld a, [hli]
+ ld [wOTTrademonID], a
+ ld a, [hl]
+ ld [wOTTrademonID + 1], a
+ ld hl, wOTPartyMon1DVs
+ ld a, [wd003]
+ call GetPartyLocation
+ ld a, [hli]
+ ld [wOTTrademonDVs], a
+ ld a, [hl]
+ ld [wOTTrademonDVs + 1], a
+ ld a, [wd003]
+ ld hl, wOTPartyMon1Species
+ call GetPartyLocation
+ ld b, h
+ ld c, l
+ farcall GetCaughtGender
+ ld a, c
+ ld [wOTTrademonCaughtData], a
+ ld a, [wd002]
+ ld [wCurPartyMon], a
+ ld hl, wPartySpecies
+ ld b, 0
+ ld c, a
+ add hl, bc
+ ld a, [hl]
+ ld [wd002], 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, [wd003]
+ push af
+ ld hl, wOTPartySpecies
+ ld b, 0
+ ld c, a
+ add hl, bc
+ ld a, [hl]
+ ld [wd003], a
+ ld c, 100
+ call DelayFrames
+ call ClearTileMap
+ call LoadFontsBattleExtra
+ ld b, SCGB_DIPLOMA
+ call GetSGBLayout
+ ld 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 ClearScreen
+ call LoadTradeScreenBorder
+ call SetTradeRoomBGPals
+ farcall Link_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
+ farcall StubbedTrainerRankings_Trades
+ farcall BackupMobileEventIndex
+ ld c, 40
+ call DelayFrames
+ hlcoord 0, 12
+ ld b, 4
+ ld c, 18
+ call LinkTextboxAtHL
+ hlcoord 1, 14
+ ld de, String28ebd
+ call PlaceString
+ farcall Link_WaitBGMap
+ ld c, 50
+ call DelayFrames
+ ld a, [wLinkMode]
+ cp LINK_TIMECAPSULE
+ jp z, Gen2ToGen1LinkComms
+ jp Gen2ToGen2LinkComms
+; 28ea3
+
+Function28ea3: ; 28ea3
+ ld c, 100
+ call DelayFrames
+ jp InitTradeMenuDisplay
+; 28eab
+
+String28eab: ; 28eab
+ db "TRADE"
+ next "CANCEL@"
+
+UnknownText_0x28eb8: ; 0x28eb8
+ ; Trade @ for @ ?
+ text_jump UnknownText_0x1c4212
+ db "@"
+; 0x28ebd
+
+String28ebd: ; 28ebd
+ db "Trade completed!@"
+
+String_TooBadTheTradeWasCanceled: ; 28ece
+ db "Too bad! The trade"
+ next "was canceled!@"
+
+
+LinkTextboxAtHL: ; 28eef
+ ld d, h
+ ld e, l
+ farcall LinkTextbox
+ ret
+; 28ef8
+
+LoadTradeScreenBorder: ; 28ef8
+ farcall _LoadTradeScreenBorder
+ ret
+; 28eff
+
+SetTradeRoomBGPals: ; 28eff
+ farcall LoadTradeRoomBGPals_ ; just a nested farcall; so wasteful
+ call SetPalettes
+ ret
+; 28f09
+
+Unreferenced_Function28f09: ; 28f09
+ 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
+; 28f24
+
+INCLUDE "engine/movie/trade_animation.asm"
+
+CheckTimeCapsuleCompatibility: ; 29bfb
+; 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, wPartyMon2 - (wPartyMon1 + NUM_MOVES)
+ add hl, de
+ dec b
+ jr nz, .move_loop
+ xor a
+ jr .done
+
+.mon_too_new
+ ld [wd265], a
+ call GetPokemonName
+ ld a, $1
+ jr .done
+
+.move_too_new
+ push bc
+ ld [wd265], 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
+; 29c67
+
+Function29c67: ; 29c67
+ ld a, [wPartyCount]
+ sub b
+ ld c, a
+ inc c
+ ld b, 0
+ ld hl, wPartyCount
+ add hl, bc
+ ld a, [hl]
+ ld [wd265], a
+ call GetPokemonName
+ ret
+; 29c7b
+
+EnterTimeCapsule: ; 29c7b
+ ld c, 10
+ call DelayFrames
+ ld a, $4
+ call Link_EnsureSync
+ ld c, 40
+ call DelayFrames
+ xor a
+ ld [hVBlank], a
+ inc a
+ ld [wLinkMode], a
+ ret
+; 29c92
+
+WaitForOtherPlayerToExit: ; 29c92
+ ld c, 3
+ call DelayFrames
+ ld a, CONNECTION_NOT_ESTABLISHED
+ ld [hSerialConnectionStatus], a
+ xor a
+ ld [rSB], a
+ ld [hSerialReceive], a
+ ld a, (0 << rSC_ON) | 1
+ ld [rSC], a
+ ld a, (1 << rSC_ON) | 1
+ ld [rSC], a
+ ld c, 3
+ call DelayFrames
+ xor a
+ ld [rSB], a
+ ld [hSerialReceive], a
+ ld a, (0 << rSC_ON) | 0
+ ld [rSC], a
+ ld a, (1 << rSC_ON) | 0
+ ld [rSC], a
+ ld c, 3
+ call DelayFrames
+ xor a
+ ld [rSB], a
+ ld [hSerialReceive], a
+ ld [rSC], a
+ ld c, 3
+ call DelayFrames
+ ld a, CONNECTION_NOT_ESTABLISHED
+ ld [hSerialConnectionStatus], a
+ ld a, [rIF]
+ push af
+ xor a
+ ld [rIF], a
+ ld a, $f
+ ld [rIE], a
+ pop af
+ ld [rIF], a
+ ld hl, wLinkTimeoutFrames
+ xor a
+ ld [hli], a
+ ld [hl], a
+ ld [hVBlank], a
+ ld [wLinkMode], a
+ ret
+; 29ce8
+
+SetBitsForLinkTradeRequest: ; 29ce8
+ ld a, LINK_TRADECENTER - 1
+ ld [wPlayerLinkAction], a
+ ld [wd265], a
+ ret
+; 29cf1
+
+SetBitsForBattleRequest: ; 29cf1
+ ld a, LINK_COLOSSEUM - 1
+ ld [wPlayerLinkAction], a
+ ld [wd265], a
+ ret
+; 29cfa
+
+SetBitsForTimeCapsuleRequest: ; 29cfa
+ ld a, $2
+ ld [rSB], a
+ xor a
+ ld [hSerialReceive], a
+ ld a, (0 << rSC_ON) | 0
+ ld [rSC], a
+ ld a, (1 << rSC_ON) | 0
+ ld [rSC], a
+ xor a ; LINK_TIMECAPSULE - 1
+ ld [wPlayerLinkAction], a
+ ld [wd265], a
+ ret
+; 29d11
+
+WaitForLinkedFriend: ; 29d11
+ ld a, [wPlayerLinkAction]
+ and a
+ jr z, .no_link_action
+ ld a, $2
+ ld [rSB], a
+ xor a
+ ld [hSerialReceive], a
+ ld a, (0 << rSC_ON) | 0
+ ld [rSC], a
+ ld a, (1 << rSC_ON) | 0
+ ld [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
+ ld a, [hSerialConnectionStatus]
+ cp USING_INTERNAL_CLOCK
+ jr z, .connected
+ cp USING_EXTERNAL_CLOCK
+ jr z, .connected
+ ld a, CONNECTION_NOT_ESTABLISHED
+ ld [hSerialConnectionStatus], a
+ ld a, $2
+ ld [rSB], a
+ xor a
+ ld [hSerialReceive], a
+ ld a, (0 << rSC_ON) | 0
+ ld [rSC], a
+ ld a, (1 << rSC_ON) | 0
+ ld [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
+ ld [rSB], a
+ ld a, (0 << rSC_ON) | 1
+ ld [rSC], a
+ ld a, (1 << rSC_ON) | 1
+ ld [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
+; 29d92
+
+CheckLinkTimeout: ; 29d92
+ 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
+ ld [hVBlank], a
+ call DelayFrame
+ call DelayFrame
+ call Link_CheckCommunicationError
+ xor a
+ ld [hVBlank], a
+ ld a, [wScriptVar]
+ and a
+ ret nz
+ jp Link_ResetSerialRegistersAfterLinkClosure
+; 29dba
+
+Function29dba: ; 29dba
+ 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
+ ld [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
+ ld [hVBlank], a
+ ret
+; 29e0c
+
+Link_CheckCommunicationError: ; 29e0c
+ xor a
+ ld [hSerialReceivedNewData], a
+ ld a, [wLinkTimeoutFrames]
+ ld h, a
+ ld a, [wLinkTimeoutFrames + 1]
+ ld l, a
+ push hl
+ call .CheckConnected
+ pop hl
+ jr nz, .load_true
+ call .AcknowledgeSerial
+ call .ConvertDW
+ call .CheckConnected
+ jr nz, .load_true
+ call .AcknowledgeSerial
+ 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
+; 29e3b
+
+.CheckConnected: ; 29e3b
+ call WaitLinkTransfer
+ ld hl, wLinkTimeoutFrames
+ ld a, [hli]
+ inc a
+ ret nz
+ ld a, [hl]
+ inc a
+ ret
+; 29e47
+
+.AcknowledgeSerial: ; 29e47
+ ld b, 10
+.loop
+ call DelayFrame
+ call LinkDataReceived
+ dec b
+ jr nz, .loop
+ ret
+; 29e53
+
+.ConvertDW: ; 29e53
+ ; [wLinkTimeoutFrames] = ((hl - $100) / 4) + $100
+ ; = (hl / 4) + $c0
+ dec h
+ srl h
+ rr l
+ srl h
+ rr l
+ inc h
+ ld a, h
+ ld [wLinkTimeoutFrames], a
+ ld a, l
+ ld [wLinkTimeoutFrames + 1], a
+ ret
+; 29e66
+
+TryQuickSave: ; 29e66
+ ld a, [wd265]
+ 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 [wd265], a
+ ret
+; 29e82
+
+CheckBothSelectedSameRoom: ; 29e82
+ ld a, [wd265]
+ call Link_EnsureSync
+ push af
+ call LinkDataReceived
+ call DelayFrame
+ call LinkDataReceived
+ pop af
+ ld b, a
+ ld a, [wd265]
+ cp b
+ jr nz, .fail
+ ld a, [wd265]
+ inc a
+ ld [wLinkMode], a
+ xor a
+ ld [hVBlank], a
+ ld a, TRUE
+ ld [wScriptVar], a
+ ret
+
+.fail
+ xor a ; FALSE
+ ld [wScriptVar], a
+ ret
+; 29eaf
+
+TimeCapsule: ; 29eaf
+ ld a, LINK_TIMECAPSULE
+ ld [wLinkMode], a
+ call DisableSpriteUpdates
+ callfar LinkCommunications
+ call EnableSpriteUpdates
+ xor a
+ ld [hVBlank], a
+ ret
+; 29ec4
+
+TradeCenter: ; 29ec4
+ ld a, LINK_TRADECENTER
+ ld [wLinkMode], a
+ call DisableSpriteUpdates
+ callfar LinkCommunications
+ call EnableSpriteUpdates
+ xor a
+ ld [hVBlank], a
+ ret
+; 29ed9
+
+Colosseum: ; 29ed9
+ ld a, LINK_COLOSSEUM
+ ld [wLinkMode], a
+ call DisableSpriteUpdates
+ callfar LinkCommunications
+ call EnableSpriteUpdates
+ xor a
+ ld [hVBlank], a
+ ret
+; 29eee
+
+CloseLink: ; 29eee
+ xor a
+ ld [wLinkMode], a
+ ld c, 3
+ call DelayFrames
+ jp Link_ResetSerialRegistersAfterLinkClosure
+; 29efa
+
+FailedLinkToPast: ; 29efa
+ ld c, 40
+ call DelayFrames
+ ld a, $e
+ jp Link_EnsureSync
+; 29f04
+
+Link_ResetSerialRegistersAfterLinkClosure: ; 29f04
+ ld c, 3
+ call DelayFrames
+ ld a, CONNECTION_NOT_ESTABLISHED
+ ld [hSerialConnectionStatus], a
+ ld a, $2
+ ld [rSB], a
+ xor a
+ ld [hSerialReceive], a
+ ld [rSC], a
+ ret
+; 29f17
+
+Link_EnsureSync: ; 29f17
+ add $d0
+ ld [wPlayerLinkAction], a
+ ld [wcf57], a
+ ld a, $2
+ ld [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
+ ld [hVBlank], a
+ ld a, b
+ and $f
+ ret
+; 29f47
+
+CableClubCheckWhichChris: ; 29f47
+ ld a, [hSerialConnectionStatus]
+ cp USING_EXTERNAL_CLOCK
+ ld a, TRUE
+ jr z, .yes
+ dec a ; FALSE
+
+.yes
+ ld [wScriptVar], a
+ ret
+; 29f54
+
+Unreferenced_Gen1LinkCommsBorderGFX: ; 29f54
+INCBIN "gfx/trade/unused_gen_1_border_tiles.2bpp"
+; 29fe4
+
+Unreferenced_Function29fe4:
+ ld a, BANK(sPartyMail)
+ call GetSRAMBank
+ ld d, FALSE
+ ld b, CHECK_FLAG
+ predef SmallFarFlagAction
+ call CloseSRAM
+ ld a, c
+ and a
+ ret
diff --git a/engine/link/link_2.asm b/engine/link/link_2.asm
new file mode 100644
index 000000000..e2fe47dc5
--- /dev/null
+++ b/engine/link/link_2.asm
@@ -0,0 +1,95 @@
+LinkMonStatsScreen: ; 4d319
+ ld a, [wMenuCursorY]
+ dec a
+ ld [wCurPartyMon], a
+ call LowVolume
+ predef StatsScreenInit
+ ld a, [wCurPartyMon]
+ inc a
+ ld [wMenuCursorY], a
+ call ClearScreen
+ call ClearBGPalettes
+ call MaxVolume
+ farcall LoadTradeScreenBorder
+ farcall Link_WaitBGMap
+ farcall InitTradeSpeciesList
+ farcall SetTradeRoomBGPals
+ call WaitBGMap2
+ ret
+
+Link_WaitBGMap: ; 4d354
+ call WaitBGMap
+ call WaitBGMap2
+ ret
+
+LinkTextbox2: ; 4d35b
+ ld h, d
+ ld l, e
+ push bc
+ push hl
+ call .PlaceBorder
+ pop hl
+ pop bc
+
+ ld de, wAttrMap - wTileMap
+ add hl, de
+ inc b
+ inc b
+ inc c
+ inc c
+ ld a, PAL_BG_TEXT
+.row
+ push bc
+ push hl
+.col
+ ld [hli], a
+ dec c
+ jr nz, .col
+ pop hl
+ ld de, SCREEN_WIDTH
+ add hl, de
+ pop bc
+ dec b
+ jr nz, .row
+ ret
+; 4d37e
+
+.PlaceBorder: ; 4d37e
+ push hl
+ ld a, $76
+ 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, "┌"
+ ld [hli], a
+ ld a, " "
+ call .PlaceRow
+ ld [hl], "─"
+ pop hl
+ ld de, SCREEN_WIDTH
+ add hl, de
+ dec b
+ jr nz, .loop
+
+ ld a, "┐"
+ ld [hli], a
+ ld a, "│"
+ call .PlaceRow
+ ld [hl], "└"
+ ret
+; 4d3ab
+
+.PlaceRow: ; 4d3ab
+ ld d, c
+.row_loop
+ ld [hli], a
+ dec d
+ jr nz, .row_loop
+ ret
diff --git a/engine/link/link_trade.asm b/engine/link/link_trade.asm
new file mode 100644
index 000000000..4c2af0842
--- /dev/null
+++ b/engine/link/link_trade.asm
@@ -0,0 +1,363 @@
+LinkCommsBorderGFX:
+INCBIN "gfx/trade/border_tiles.2bpp"
+; 16d421
+
+__LoadTradeScreenBorder: ; 16d421
+ ld de, LinkCommsBorderGFX
+ ld hl, vTiles2
+ lb bc, BANK(LinkCommsBorderGFX), 70
+ call Get2bpp
+ ret
+; 16d42e
+
+Function16d42e: ; 16d42e
+ ld hl, Tilemap_MobileTradeBorderFullscreen
+ decoord 0, 0
+ ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+ call CopyBytes
+ ret
+; 16d43b
+
+Function16d43b: ; 16d43b
+ call LoadStandardMenuHeader
+ call ClearBGPalettes
+ call ClearTileMap
+ call ClearSprites
+ farcall __LoadTradeScreenBorder ; useless to farcall
+ farcall Function16d42e ; useless to farcall
+ ld b, SCGB_DIPLOMA
+ call GetSGBLayout
+ call SetPalettes
+ call WaitBGMap
+ call JoyWaitAorB
+ call Call_ExitMenu
+ ret
+; 16d465
+
+Tilemap_MobileTradeBorderFullscreen:
+INCBIN "gfx/trade/border_mobile_fullscreen.tilemap"
+
+Tilemap_CableTradeBorderTop:
+INCBIN "gfx/trade/border_cable_top.tilemap"
+
+Tilemap_CableTradeBorderBottom:
+INCBIN "gfx/trade/border_cable_bottom.tilemap"
+
+_LinkTextbox: ; 16d61d
+ ld h, d
+ ld l, e
+ push bc
+ push hl
+ call .PlaceBorder
+ pop hl
+ pop bc
+
+ ld de, wAttrMap - wTileMap
+ add hl, de
+ inc b
+ inc b
+ inc c
+ inc c
+ ld a, PAL_BG_TEXT
+.row
+ push bc
+ push hl
+.col
+ ld [hli], a
+ dec c
+ jr nz, .col
+ pop hl
+ ld de, SCREEN_WIDTH
+ add hl, de
+ pop bc
+ dec b
+ jr nz, .row
+ ret
+; 16d640
+
+.PlaceBorder ; 16d640
+ push hl
+ ld a, $30
+ 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, $33
+ ld [hli], a
+ ld a, " "
+ call .PlaceRow
+ ld [hl], $34
+ pop hl
+ ld de, SCREEN_WIDTH
+ add hl, de
+ dec b
+ jr nz, .loop
+
+ ld a, $35
+ ld [hli], a
+ ld a, $36
+ call .PlaceRow
+ ld [hl], $37
+ ret
+; 16d66d
+
+.PlaceRow ; 16d66d
+ ld d, c
+.row_loop
+ ld [hli], a
+ dec d
+ jr nz, .row_loop
+ ret
+; 16d673
+
+InitTradeSpeciesList: ; 16d673
+ call _LoadTradeScreenBorder
+ call Function16d6ae
+ farcall InitMG_Mobile_LinkTradePalMap
+ farcall PlaceTradePartnerNamesAndParty
+ hlcoord 10, 17
+ ld de, .CANCEL
+ call PlaceString
+ ret
+; 16d68f
+
+.CANCEL: ; 16d68f
+ db "CANCEL@"
+; 16d696
+
+_LoadTradeScreenBorder: ; 16d696
+ call __LoadTradeScreenBorder
+ ret
+; 16d69a
+
+
+LinkComms_LoadPleaseWaitTextboxBorderGFX: ; 16d69a
+ ld de, LinkCommsBorderGFX + $30 tiles
+ ld hl, vTiles2 tile $76
+ lb bc, BANK(LinkCommsBorderGFX), 8
+ call Get2bpp
+ ret
+; 16d6a7
+
+LoadTradeRoomBGPals_: ; 16d6a7
+ farcall LoadTradeRoomBGPals
+ ret
+; 16d6ae
+
+Function16d6ae: ; 16d6ae
+ call Function16d42e
+ ld hl, Tilemap_CableTradeBorderTop
+ decoord 0, 0
+ ld bc, 2 * SCREEN_WIDTH
+ call CopyBytes
+ ld hl, Tilemap_CableTradeBorderBottom
+ decoord 0, 16
+ ld bc, 2 * SCREEN_WIDTH
+ call CopyBytes
+ ret
+; 16d6ca
+
+LinkTextbox: ; 16d6ca
+ call _LinkTextbox
+ ret
+; 16d6ce
+
+Function16d6ce: ; 16d6ce
+ call LoadStandardMenuHeader
+ call Function16d6e1
+ farcall WaitLinkTransfer
+ call Call_ExitMenu
+ call WaitBGMap2
+ ret
+; 16d6e1
+
+Function16d6e1: ; 16d6e1
+ hlcoord 4, 10
+ ld b, 1
+ ld c, 10
+ predef LinkTextboxAtHL
+ hlcoord 5, 11
+ ld de, .Waiting
+ call PlaceString
+ call WaitBGMap
+ call WaitBGMap2
+ ld c, 50
+ jp DelayFrames
+; 16d701
+
+.Waiting: ; 16d701
+ db "WAITING..!@"
+; 16d70c
+
+LinkTradeMenu: ; 16d70c
+ call .MenuAction
+ call .GetJoypad
+ ret
+; 16d713
+
+.GetJoypad: ; 16d713
+ push bc
+ push af
+ ld a, [hJoyLast]
+ and D_PAD
+ ld b, a
+ ld a, [hJoyPressed]
+ and BUTTONS
+ or b
+ ld b, a
+ pop af
+ ld a, b
+ pop bc
+ ld d, a
+ ret
+; 16d725
+
+.MenuAction: ; 16d725
+ ld hl, w2DMenuFlags2
+ res 7, [hl]
+ ld a, [hBGMapMode]
+ push af
+ call .loop
+ pop af
+ ld [hBGMapMode], a
+ ret
+
+.loop
+ call .UpdateCursor
+ call .UpdateBGMapAndOAM
+ call .loop2
+ jr nc, .done
+ farcall _2DMenuInterpretJoypad
+ jr c, .done
+ ld a, [w2DMenuFlags1]
+ bit 7, a
+ jr nz, .done
+ call .GetJoypad
+ ld b, a
+ ld a, [wMenuJoypadFilter]
+ and b
+ jr z, .loop
+
+.done
+ ret
+; 16d759
+
+.UpdateBGMapAndOAM: ; 16d759
+ ld a, [hOAMUpdate]
+ push af
+ ld a, $1
+ ld [hOAMUpdate], a
+ call WaitBGMap
+ pop af
+ ld [hOAMUpdate], a
+ xor a
+ ld [hBGMapMode], a
+ ret
+
+.loop2
+ call RTC
+ call .TryAnims
+ ret c
+ ld a, [w2DMenuFlags1]
+ bit 7, a
+ jr z, .loop2
+ and a
+ ret
+; 16d77a
+
+.UpdateCursor: ; 16d77a
+ ld hl, wCursorCurrentTile
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld a, [hl]
+ cp $1f
+ jr nz, .not_currently_selected
+ ld a, [wCursorOffCharacter]
+ ld [hl], a
+ push hl
+ push bc
+ ld bc, MON_NAME_LENGTH
+ add hl, bc
+ ld [hl], a
+ pop bc
+ pop hl
+
+.not_currently_selected
+ ld a, [w2DMenuCursorInitY]
+ ld b, a
+ ld a, [w2DMenuCursorInitX]
+ ld c, a
+ call Coord2Tile
+ ld a, [w2DMenuCursorOffsets]
+ swap a
+ and $f
+ ld c, a
+ ld a, [wMenuCursorY]
+ ld b, a
+ xor a
+ dec b
+ jr z, .skip
+.loop3
+ add c
+ dec b
+ jr nz, .loop3
+
+.skip
+ ld c, SCREEN_WIDTH
+ call AddNTimes
+ ld a, [w2DMenuCursorOffsets]
+ and $f
+ ld c, a
+ ld a, [wMenuCursorX]
+ ld b, a
+ xor a
+ dec b
+ jr z, .skip2
+.loop4
+ add c
+ dec b
+ jr nz, .loop4
+
+.skip2
+ ld c, a
+ add hl, bc
+ ld a, [hl]
+ cp $1f
+ jr z, .cursor_already_there
+ ld [wCursorOffCharacter], a
+ ld [hl], $1f
+ push hl
+ push bc
+ ld bc, MON_NAME_LENGTH
+ add hl, bc
+ ld [hl], $1f
+ pop bc
+ pop hl
+.cursor_already_there
+ ld a, l
+ ld [wCursorCurrentTile], a
+ ld a, h
+ ld [wCursorCurrentTile + 1], a
+ ret
+; 16d7e7
+
+.TryAnims: ; 16d7e7
+ ld a, [w2DMenuFlags1]
+ bit 6, a
+ jr z, .skip_anims
+ farcall PlaySpriteAnimationsAndDelayFrame
+.skip_anims
+ call JoyTextDelay
+ call .GetJoypad
+ and a
+ ret z
+ scf
+ ret
+; 16d7fe
diff --git a/engine/link/mystery_gift.asm b/engine/link/mystery_gift.asm
new file mode 100644
index 000000000..4aed9ee70
--- /dev/null
+++ b/engine/link/mystery_gift.asm
@@ -0,0 +1,1735 @@
+DoMysteryGift: ; 1048ba (41:48ba)
+ call ClearTileMap
+ call ClearSprites
+ call WaitBGMap
+ call InitMysteryGiftLayout
+ hlcoord 3, 8
+ ld de, .String_PressAToLink_BToCancel
+ call PlaceString
+ call WaitBGMap
+ farcall PrepMysteryGiftDataToSend
+ call MysteryGift_ClearTrainerData
+ ld a, $2
+ ld [wca01], a
+ ld a, $14
+ ld [wca02], a
+ ld a, [rIE]
+ push af
+
+ call Function104a95
+
+ ld d, a
+ xor a
+ ld [rIF], a
+ pop af
+ ld [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, .Text_LinkCanceled ; Link has been canceled
+ cp $10
+ jp z, .LinkCanceled
+ cp $6c
+ jp nz, .CommunicationError
+ ld a, [wc900]
+ cp 3
+ jr z, .skip_checks
+ call .CheckAlreadyGotFiveGiftsToday
+ ld hl, .Text_MaxFiveGifts ; Only 5 gifts a day
+ jp nc, .PrintTextAndExit
+ call .CheckAlreadyGotAGiftFromThatPerson
+ ld hl, .Text_MaxOneGiftPerPerson ; Only one gift a day per person
+ jp c, .PrintTextAndExit
+.skip_checks
+ ld a, [wMysteryGiftPlayerBackupItem]
+ and a
+ jp nz, .GiftWaiting
+ ld a, [wMysteryGiftPartnerBackupItem]
+ and a
+ jp nz, .FriendNotReady
+ ld a, [wc900]
+ cp 3
+ jr z, .skip_append_save
+ call .AddMysteryGiftPartnerID
+ ld a, [wc900]
+ cp 4
+ jr z, .skip_append_save
+ call .SaveMysteryGiftTrainerName
+ farcall RestoreMobileEventIndex
+ farcall StubbedTrainerRankings_MysteryGift
+ farcall BackupMobileEventIndex
+.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, .Text_SentToHome ; 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, .Text_Sent ; sent item
+ jr .PrintTextAndExit
+
+.LinkCanceled: ; 1049af (41:49af)
+ ld hl, .Text_LinkCanceled ; Link has been canceled
+ jr .PrintTextAndExit
+
+.CommunicationError: ; 1049b4 (41:49b4)
+ ld hl, .Text_CommunicationError ; Communication error
+ call PrintText
+ jp DoMysteryGift
+
+.GiftWaiting: ; 1049bd (41:49bd)
+ ld hl, .Text_ReceiveGiftAtCounter ; receive gift at counter
+ jr .PrintTextAndExit
+
+.FriendNotReady: ; 1049c2 (41:49c2)
+ ld hl, .Text_FriendNotReady ; friend not ready
+
+.PrintTextAndExit: ; 1049c5 (41:49c5)
+ call PrintText
+ ld a, LCDC_DEFAULT
+ ld [rLCDC], a
+ ret
+; 1049cd (41:49cd)
+
+.String_PressAToLink_BToCancel: ; 1049cd
+ db "Press A to"
+ next "link IR-Device"
+ next "Press B to"
+ next "cancel it."
+ db "@"
+; 1049fd
+
+.Text_LinkCanceled: ; 1049fd
+ text_jump UnknownText_0x1c0436
+ db "@"
+; 104a02
+
+.Text_CommunicationError: ; 104a02
+ text_jump UnknownText_0x1c0454
+ db "@"
+; 104a07
+
+.Text_ReceiveGiftAtCounter: ; 104a07
+ text_jump UnknownText_0x1c046a
+ db "@"
+; 104a0c
+
+.Text_FriendNotReady: ; 104a0c
+ text_jump UnknownText_0x1c048e
+ db "@"
+; 104a11
+
+.Text_MaxFiveGifts: ; 104a11
+ text_jump UnknownText_0x1c04a7
+ db "@"
+; 104a16
+
+.Text_MaxOneGiftPerPerson: ; 104a16
+ text_jump UnknownText_0x1c04c6
+ db "@"
+; 104a1b
+
+.Text_Sent: ; 104a1b
+ text_jump UnknownText_0x1c04e9
+ db "@"
+; 104a20
+
+.Text_SentToHome: ; 104a20
+ text_jump UnknownText_0x1c04fa
+ db "@"
+; 104a25
+
+.CheckAlreadyGotFiveGiftsToday: ; 104a25 (41:4a25)
+ call GetMysteryGiftBank
+ ld a, [sNumDailyMysteryGiftPartnerIDs]
+ cp $5
+ jp CloseSRAM
+
+.CheckAlreadyGotAGiftFromThatPerson: ; 104a30 (41:4a30)
+ 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: ; 104a56 (41:4a56)
+ 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: ; 104a71 (41:4a71)
+ 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
+
+Function104a95: ; 104a95 (41:4a95)
+ di
+ farcall ClearChannels
+ call Function104d5e
+
+.loop2
+ call Function104d96
+ call Function104ddd
+ ld a, [hMGStatusFlags]
+ cp $10
+ jp z, Function104bd0
+ cp $6c
+ jr nz, .loop2
+
+ ld a, [hPrintNum9]
+ cp $2
+ jr z, Function104b22
+ ld hl, hPrintNum1
+ ld b, $1
+ call Function104d56
+ jr nz, .ly_loop
+ call Function104b49
+ jp nz, Function104bd0
+ jr Function104b0a
+ ; Delay frame
+.ly_loop
+ ld a, [rLY]
+ cp LY_VBLANK
+ jr c, .ly_loop
+ ld c, LOW(rRP)
+ ld a, $c0
+ ld [$ff00+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
+ ld a, [$ff00+c]
+ and b
+ ld b, a
+ ld a, [rLY]
+ cp LY_VBLANK
+ jr nc, .ly_loop2
+.ly_loop3
+ ld a, [$ff00+c]
+ and b
+ ld b, a
+ ld 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
+ ld a, [hMGJoypadReleased]
+ bit B_BUTTON_F, a
+ jr z, .loop3
+ ld a, $10
+ ld [hMGStatusFlags], a
+ jp Function104bd0
+
+Function104b04: ; 104b04 (41:4b04)
+ call Function104b40
+ jp nz, Function104bd0
+Function104b0a: ; 104b0a (41:4b0a)
+ call Function104d38
+ jp nz, Function104bd0
+ call Function104b88
+ jp nz, Function104bd0
+ call Function104d43
+ jp nz, Function104bd0
+ call Function105033
+ jp Function104bd0
+
+Function104b22: ; 104b22 (41:4b22)
+ call Function104b88
+ jp nz, Function104bd0
+ call Function104d43
+ jp nz, Function104bd0
+ call Function104b40
+ jp nz, Function104bd0
+ call Function104d38
+ jp nz, Function104bd0
+ call Function10502e
+ jp Function104bd0
+
+Function104b40: ; 104b40 (41:4b40)
+ ld hl, hPrintNum1
+ ld b, $1
+ call Function104d56
+ ret nz
+
+Function104b49: ; 104b49 (41:4b49)
+ call Function105033
+ ld a, [hMGStatusFlags]
+ cp $6c
+ ret nz
+ ld a, [hPrintNum1]
+ cp $96
+ jp nz, Function104d32
+ ld a, $90
+ ld [hPrintNum1], a
+ call Function104d38
+ ret nz
+ ld hl, hPrintNum1
+ ld b, $1
+ call Function104d4e
+ ret nz
+ call Function10502e
+ ld a, [hMGStatusFlags]
+ cp $6c
+ ret nz
+ call Function104d43
+ ret nz
+ ld hl, wMysteryGiftTrainerData
+ ld a, [wca02]
+ ld b, a
+ call Function104d56
+ ret nz
+ call Function105033
+ ld a, [hMGStatusFlags]
+ cp $6c
+ ret
+
+Function104b88: ; 104b88 (41:4b88)
+ ld a, $96
+ ld [hPrintNum1], a
+ ld hl, hPrintNum1
+ ld b, $1
+ call Function104d4e
+ ret nz
+ call Function10502e
+ ld a, [hMGStatusFlags]
+ cp $6c
+ ret nz
+ call Function104d43
+ ret nz
+ ld hl, hPrintNum1
+ ld b, $1
+ call Function104d56
+ ret nz
+ call Function105033
+ ld a, [hMGStatusFlags]
+ cp $6c
+ ret nz
+ ld a, [hPrintNum1]
+ cp $90
+ jp nz, Function104d32
+ call Function104d38
+ ret nz
+ ld hl, wLinkData
+ ld a, [wca02]
+ ld b, a
+ call Function104d4e
+ ret nz
+ call Function10502e
+ ld a, [hMGStatusFlags]
+ cp $6c
+ ret
+
+Function104bd0: ; 104bd0 (41:4bd0)
+ nop
+ ld a, [hMGStatusFlags]
+ cp $10
+ jr z, .quit
+ cp $6c
+ jr nz, .quit
+ ld hl, wca01
+ 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 [wca02], a
+ ld a, [hPrintNum9]
+ cp $2
+ jr z, .asm_104c10
+ call Function104d43
+ jr nz, Function104bd0
+ jp Function104b04
+
+.asm_104c10
+ call Function104d38
+ jr nz, Function104bd0
+ jp Function104b22
+
+.quit
+ ld a, [hMGStatusFlags]
+ push af
+ call Function104da0
+ xor a
+ ld [rIF], a
+ ld a, [rIE]
+ or $1
+ ld [rIE], a
+ ei
+ call DelayFrame
+ pop af
+ ret
+
+Function104c2d: ; 104c2d (41:4c2d)
+ di
+ farcall ClearChannels
+ call Function104d5e
+.asm_104c37
+ call Function104d96
+ call Function104ddd
+ ld a, [hMGStatusFlags]
+ cp $10
+ jp z, Function104d1c
+ cp $6c
+ jr nz, .asm_104c37
+ ld a, [hPrintNum9]
+ cp $2
+ jr z, .asm_104c6c
+ call Function104c8a
+ jp nz, Function104d1c
+ call Function104d38
+ jp nz, Function104d1c
+ call Function104cd2
+ jp nz, Function104d1c
+ call Function104d43
+ jp nz, Function104d1c
+ call Function105033
+ jp Function104d1c
+.asm_104c6c
+ call Function104cd2
+ jp nz, Function104d1c
+ call Function104d43
+ jp nz, Function104d1c
+ call Function104c8a
+ jp nz, Function104d1c
+ call Function104d38
+ jp nz, Function104d1c
+ call Function10502e
+ jp Function104d1c
+
+Function104c8a: ; 104c8a (41:4c8a)
+ ld hl, hPrintNum1
+ ld b, $1
+ call Function104d56
+ ret nz
+ call Function105033
+ ld a, [hMGStatusFlags]
+ cp $6c
+ ret nz
+ ld a, [hPrintNum1]
+ cp $3c
+ jp nz, Function104d32
+ swap a
+ ld [hPrintNum1], a
+ call Function104d38
+ ret nz
+ ld hl, hPrintNum1
+ ld b, $1
+ call Function104d4e
+ ret nz
+ call Function10502e
+ ld a, [hMGStatusFlags]
+ cp $6c
+ ret nz
+ call Function104d43
+ ret nz
+ ld hl, wMysteryGiftTrainerData
+ ld a, [wca02]
+ ld b, a
+ call Function104d56
+ ret nz
+ call Function105033
+ ld a, [hMGStatusFlags]
+ cp $6c
+ ret
+
+Function104cd2: ; 104cd2 (41:4cd2)
+ ld a, $3c
+ ld [hPrintNum1], a
+ ld hl, hPrintNum1
+ ld b, $1
+ call Function104d4e
+ ret nz
+ call Function10502e
+ ld a, [hMGStatusFlags]
+ cp $6c
+ ret nz
+ call Function104d43
+ ret nz
+ ld hl, hPrintNum1
+ ld b, $1
+ call Function104d56
+ ret nz
+ call Function105033
+ ld a, [hMGStatusFlags]
+ cp $6c
+ ret nz
+ ld a, [hPrintNum1]
+ swap a
+ cp $3c
+ jp nz, Function104d32
+ call Function104d38
+ ret nz
+ ld hl, wLinkData
+ ld a, [wca02]
+ ld b, a
+ call Function104d4e
+ ret nz
+ call Function10502e
+ ld a, [hMGStatusFlags]
+ cp $6c
+ ret
+
+Function104d1c: ; 104d1c (41:4d1c)
+ nop
+ ld a, [hMGStatusFlags]
+ push af
+ call Function104da0
+ xor a
+ ld [rIF], a
+ ld a, [rIE]
+ or $1
+ ld [rIE], a
+ ei
+ call DelayFrame
+ pop af
+ ret
+
+Function104d32: ; 104d32 (41:4d32)
+ ld a, $80
+ ld [hMGStatusFlags], a
+ and a
+ ret
+
+Function104d38: ; 104d38 (41:4d38)
+ call Function104d96
+ call Function104e46
+ ld a, [hMGStatusFlags]
+ cp $6c
+ ret
+
+Function104d43: ; 104d43 (41:4d43)
+ call Function104d96
+ call Function104dfe
+ ld a, [hMGStatusFlags]
+ cp $6c
+ ret
+
+Function104d4e: ; 104d4e (41:4d4e)
+ call Function104e93
+ ld a, [hMGStatusFlags]
+ cp $6c
+ ret
+
+Function104d56: ; 104d56 (41:4d56)
+ call Function104f57
+ ld a, [hMGStatusFlags]
+ cp $6c
+ ret
+
+Function104d5e: ; 104d5e (41:4d5e)
+ call Function104d74
+ ld a, $4
+ ld [rIE], a
+ xor a
+ ld [rIF], a
+ call Function104d96
+ xor a
+ ld b, a
+.asm_104d6d
+ inc a
+ jr nz, .asm_104d6d
+ inc b
+ jr nz, .asm_104d6d
+ ret
+
+Function104d74: ; 104d74 (41:4d74)
+ xor a
+ ld [rTAC], a
+ ld a, $fe
+ ld [rTMA], a
+ ld [rTIMA], a
+ ld a, $2
+ ld [rTAC], a
+ or $4
+ ld [rTAC], a
+ ret
+
+Function104d86: ; 104d86 (41:4d86)
+ xor a
+ ld [rTAC], a
+ ld [rTMA], a
+ ld [rTIMA], a
+ ld a, $2
+ ld [rTAC], a
+ or $4
+ ld [rTAC], a
+ ret
+
+Function104d96: ; 104d96 (41:4d96)
+ ld a, $c0
+ call Function104e8c
+ ld a, $1
+ ld [hPrintNum9], a
+ ret
+
+Function104da0: ; 104da0 (41:4da0)
+ xor a
+ call Function104e8c
+ ld a, $2
+ ld [rTAC], a
+ ret
+
+Function104da9: ; 104da9 (41:4da9)
+ inc d
+ ret z
+ xor a
+ ld [rIF], a
+ halt
+ ld a, [$ff00+c]
+ bit 1, a
+ jr z, Function104da9
+ or a
+ ret
+
+Function104db7: ; 104db7 (41:4db7)
+ inc d
+ ret z
+ xor a
+ ld [rIF], a
+ halt
+ ld a, [$ff00+c]
+ bit 1, a
+ jr nz, Function104db7
+ or a
+ ret
+
+Function104dc5: ; 104dc5 (41:4dc5)
+ ld a, $c1
+ ld [$ff00+c], a
+.wait
+ dec d
+ ret z
+ xor a
+ ld [rIF], a
+ halt
+ jr .wait
+
+Function104dd1: ; 104dd1 (41:4dd1)
+ ld a, $c0
+ ld [$ff00+c], a
+.wait
+ dec d
+ ret z
+ xor a
+ ld [rIF], a
+ halt
+ jr .wait
+
+Function104ddd: ; 104ddd (41:4ddd)
+ ld d, $0
+ ld e, d
+ ld a, $1
+ ld [hPrintNum9], a
+.loop
+ call MysteryGift_ReadJoypad
+ ld b, $2
+ ld c, LOW(rRP)
+ ld a, [hMGJoypadReleased]
+ bit B_BUTTON_F, a
+ jr z, .next
+ ld a, $10
+ ld [hMGStatusFlags], a
+ ret
+
+.next
+ bit 0, a
+ jr nz, Function104e3a
+ ld a, [$ff00+c]
+ and b
+ jr nz, .loop
+
+Function104dfe: ; 104dfe (41:4dfe)
+ ld c, LOW(rRP)
+ ld d, $0
+ ld e, d
+ call Function104db7
+ jp z, Function104f42
+ ld d, e
+ call Function104da9
+ jp z, Function104f42
+ call Function104db7
+ jp z, Function104f42
+ call Function104da9
+ jp z, Function104f42
+ ld a, $6c
+ ld [hMGStatusFlags], a
+ ld d, $3d
+ call Function104dd1
+ ld d, $5
+ call Function104dc5
+ ld d, $15
+ call Function104dd1
+ ld d, $5
+ call Function104dc5
+ ld d, $5
+ call Function104dd1
+ ret
+
+Function104e3a: ; 104e3a (41:4e3a)
+ ; 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
+Function104e46: ; 104e46 (41:4e46)
+ ld a, $2
+ ld [hPrintNum9], a
+ ld c, LOW(rRP)
+ ld d, $0
+ ld e, d
+ ld d, $3d
+ call Function104dd1
+ ld d, $5
+ call Function104dc5
+ ld d, $15
+ call Function104dd1
+ ld d, $5
+ call Function104dc5
+ ld d, $5
+ call Function104dd1
+ ld d, e
+ call Function104db7
+ jp z, Function104f42
+ ld d, e
+ call Function104da9
+ jp z, Function104f42
+ call Function104db7
+ jp z, Function104f42
+ call Function104da9
+ jp z, Function104f42
+ ld d, $3d
+ call Function104dd1
+ ld a, $6c
+ ld [hMGStatusFlags], a
+ ret
+
+Function104e8c: ; 104e8c (41:4e8c)
+ ld [rRP], a
+ ld a, $ff
+ ld [hMGStatusFlags], a
+ ret
+
+Function104e93: ; 104e93 (41:4e93)
+ xor a
+ ld [hPrintNum5], a
+ ld [hPrintNum6], a
+ push hl
+ push bc
+ ld c, LOW(rRP)
+ ld d, $3d
+ call Function104dd1
+ ld hl, hPrintNum2
+ ld a, $5a
+ ld [hli], a
+ ld [hl], b
+ dec hl
+ ld b, $2
+ call Function104ed6
+ pop bc
+ pop hl
+ call Function104ed6
+ ld a, [hPrintNum5]
+ ld [hPrintNum2], a
+ ld a, [hPrintNum6]
+ ld [hPrintNum3], a
+ push hl
+ ld hl, hPrintNum2
+ ld b, $2
+ call Function104ed6
+ ld hl, hMGStatusFlags
+ ld b, $1
+ call Function104faf
+ ld a, [hPrintNum2]
+ ld [hPrintNum5], a
+ ld a, [hPrintNum3]
+ ld [hPrintNum6], a
+ pop hl
+ ret
+
+Function104ed6: ; 104ed6 (41:4ed6)
+ ld c, LOW(rRP)
+ ld d, $5
+ call Function104dd1
+ ld d, $5
+ call Function104dc5
+ ld d, $15
+ call Function104dd1
+ ld a, b
+ cpl
+ ld b, a
+ ld a, $f4
+ ld [rTMA], a
+.asm_104eee
+ inc b
+ jr z, .asm_104f2e
+ ld a, $8
+ ld [hPrintNum4], a
+ ld a, [hli]
+ ld e, a
+ ld a, [hPrintNum5]
+ add e
+ ld [hPrintNum5], a
+ ld a, [hPrintNum6]
+ adc 0
+ ld [hPrintNum6], a
+.asm_104f02
+ xor a
+ ld [rIF], a
+ halt
+ ld a, $c1
+ ld [rRP], a
+ ld d, $1
+ ld a, e
+ rlca
+ ld e, a
+ jr nc, .asm_104f13
+ inc d
+.asm_104f13
+ ld a, [rTIMA]
+ cp $f8
+ jr c, .asm_104f13
+ ld a, $c0
+ ld [rRP], a
+ dec d
+ jr z, .asm_104f25
+ xor a
+ ld [rIF], a
+ halt
+.asm_104f25
+ ld a, [hPrintNum4]
+ dec a
+ jr z, .asm_104eee
+ ld [hPrintNum4], a
+ jr .asm_104f02
+.asm_104f2e
+ ld a, $fe
+ ld [rTMA], a
+ xor a
+ ld [rIF], a
+ halt
+ ld d, $5
+ call Function104dc5
+ ld d, $11
+ call Function104dd1
+ ret
+
+Function104f42: ; 104f42 (41:4f42)
+ ld a, [hMGStatusFlags]
+ or $2
+ ld [hMGStatusFlags], a
+ ret
+
+Function104f49: ; 104f49 (41:4f49)
+ ld a, [hMGStatusFlags]
+ or $1
+ ld [hMGStatusFlags], a
+ ret
+
+Function104f50: ; 104f50 (41:4f50)
+ ld a, [hMGStatusFlags]
+ or $80
+ ld [hMGStatusFlags], a
+ ret
+
+Function104f57: ; 104f57 (41:4f57)
+ xor a
+ ld [hPrintNum5], a
+ ld [hPrintNum6], a
+ push bc
+ push hl
+ ld hl, hPrintNum2
+ ld b, $2
+ call Function104faf
+ ld a, [hPrintNum3]
+ ld [hPrintNum8], a
+ ld b, a
+ pop hl
+ pop af
+ cp b
+ jp c, Function104f50
+ ld a, [hPrintNum2]
+ cp $5a
+ jp nz, Function104f50
+ call Function104faf
+ ld a, [hPrintNum5]
+ ld d, a
+ ld a, [hPrintNum6]
+ ld e, a
+ push hl
+ push de
+ ld hl, hPrintNum2
+ ld b, $2
+ call Function104faf
+ pop de
+ ld hl, hPrintNum2
+ ld a, [hli]
+ xor d
+ ld b, a
+ ld a, [hl]
+ xor e
+ or b
+ call nz, Function104f49
+ push de
+ ld d, $3d
+ call Function104dd1
+ ld hl, hMGStatusFlags
+ ld b, $1
+ call Function104ed6
+ pop de
+ pop hl
+ ld a, d
+ ld [hPrintNum5], a
+ ld a, e
+ ld [hPrintNum6], a
+ ret
+
+Function104faf: ; 104faf (41:4faf)
+ ld c, LOW(rRP)
+ ld d, $0
+ call Function104db7
+ jp z, Function104f42
+ ld d, $0
+ call Function104da9
+ jp z, Function104f42
+ ld d, $0
+ call Function104db7
+ jp z, Function104f42
+ ld a, b
+ cpl
+ ld b, a
+ xor a
+ ld [hMGJoypadPressed + 2], a
+ call Function104d86
+.asm_104fd2
+ inc b
+ jr z, .asm_10501a
+ ld a, $8
+ ld [hPrintNum4], a
+.asm_104fd9
+ ld d, $0
+.asm_104fdb
+ inc d
+ jr z, .asm_104fe5
+ ld a, [$ff00+c]
+ bit 1, a
+ jr z, .asm_104fdb
+ ld d, $0
+.asm_104fe5
+ inc d
+ jr z, .asm_104fed
+ ld a, [$ff00+c]
+ bit 1, a
+ jr nz, .asm_104fe5
+.asm_104fed
+ ld a, [hMGJoypadPressed + 2]
+ ld d, a
+ ld a, [rTIMA]
+ ld [hMGJoypadPressed + 2], a
+ sub d
+ cp $12
+ jr c, .asm_104ffd
+ set 0, e
+ jr .asm_104fff
+.asm_104ffd
+ res 0, e
+.asm_104fff
+ ld a, [hPrintNum4]
+ dec a
+ ld [hPrintNum4], a
+ jr z, .asm_10500b
+ ld a, e
+ rlca
+ ld e, a
+ jr .asm_104fd9
+.asm_10500b
+ ld a, e
+ ld [hli], a
+ ld a, [hPrintNum5]
+ add e
+ ld [hPrintNum5], a
+ ld a, [hPrintNum6]
+ adc 0
+ ld [hPrintNum6], a
+ jr .asm_104fd2
+.asm_10501a
+ call Function104d74
+ xor a
+ ld [rIF], a
+ ld d, $0
+ call Function104da9
+ jp z, Function104f42
+ ld d, $10
+ call Function104dd1
+ ret
+
+Function10502e: ; 10502e (41:502e)
+ ld b, $0
+ jp Function104e93
+
+Function105033: ; 105033 (41:5033)
+ ld b, $0
+ jp Function104f57
+
+MysteryGift_ReadJoypad: ; 105038 (41:5038)
+; We can only get four inputs at a time.
+; We take d-pad first for no particular reason.
+ ld a, R_DPAD
+ ld [rJOYP], a
+; Read twice to give the request time to take.
+ ld a, [rJOYP]
+ ld 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
+ ld [rJOYP], a
+; Wait for input to stabilize.
+rept 6
+ ld 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.
+ ld a, [hMGJoypadPressed]
+ xor c
+; Released this frame:
+ and c
+ ld [hMGJoypadReleased], a
+; Pressed this frame:
+ ld a, c
+ ld [hMGJoypadPressed], a
+ ld a, $30
+; Reset the joypad register since we're done with it.
+ ld [rJOYP], a
+ ret
+
+MysteryGift_CheckAndSetDecorationAlreadyReceived: ; 105069 (41:5069)
+ 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: ; 105091 (41:5091)
+ 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: ; 1050b9
+ call GetMysteryGiftBank
+ ld hl, sMysteryGiftUnlocked
+ ld a, [hl]
+ inc a
+ jr nz, .ok
+ ld [hld], a
+ ld [hl], a
+.ok
+ jp CloseSRAM
+; 1050c8
+
+Function1050c8: ; 1050c8
+ call GetMysteryGiftBank
+ ld a, [sNumDailyMysteryGiftPartnerIDs]
+ cp $ff
+ jr z, .okay
+ xor a
+ ld [sNumDailyMysteryGiftPartnerIDs], a
+.okay
+ jp CloseSRAM
+; 1050d9
+
+
+BackupMysteryGift: ; 1050d9
+ call GetMysteryGiftBank
+ ld hl, sMysteryGiftItem
+ ld de, sBackupMysteryGiftItem
+ ld a, [hli]
+ ld [de], a
+ inc de
+ ld a, [hl]
+ ld [de], a
+ jp CloseSRAM
+; 1050ea
+
+
+RestoreMysteryGift: ; 1050ea (41:50ea)
+ 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: ; 1050fb (41:50fb)
+ ld hl, wMysteryGiftTrainerData
+ xor a
+ ld b, wMysteryGiftTrainerDataEnd - wMysteryGiftTrainerData
+.loop
+ ld [hli], a
+ dec b
+ jr nz, .loop
+ ret
+
+
+GetMysteryGiftBank: ; 105106
+ ld a, BANK(sBackupMysteryGiftItem)
+ jp GetSRAMBank
+; 10510b
+
+
+StagePartyDataForMysteryGift: ; 10510b (41:510b)
+; You will be sending this data to your mystery gift partner.
+; Structure is the same as a trainer with species and moves
+; defined.
+ ld a, BANK(sPokemonData)
+ call GetSRAMBank
+ ld de, wMysteryGiftStaging
+ ld bc, sPokemonData + wPartyMons - wPokemonData
+ ld hl, sPokemonData + wPartySpecies - wPokemonData
+.loop
+ ld a, [hli]
+ cp -1
+ jr z, .party_end
+ cp EGG
+ jr z, .next
+ push hl
+ ; copy level
+ ld hl, MON_LEVEL
+ add hl, bc
+ ld a, [hl]
+ ld [de], a
+ inc de
+ ; copy species
+ ld hl, MON_SPECIES
+ add hl, bc
+ ld a, [hl]
+ ld [de], a
+ inc de
+ ; copy moves
+ ld hl, MON_MOVES
+ add hl, bc
+ push bc
+ ld bc, NUM_MOVES
+ call CopyBytes
+ pop bc
+ pop hl
+.next
+ push hl
+ ld hl, PARTYMON_STRUCT_LENGTH
+ add hl, bc
+ ld b, h
+ ld c, l
+ pop hl
+ jr .loop
+.party_end
+ ld a, -1
+ ld [de], a
+ ld a, $26
+ ld [wca00], a
+ jp CloseSRAM
+
+InitMysteryGiftLayout: ; 105153 (41:5153)
+ call ClearBGPalettes
+ call DisableLCD
+ ld hl, MysteryGiftGFX
+ ld de, vTiles2 tile $00
+ ld a, BANK(MysteryGiftGFX)
+ ld bc, MysteryGiftGFX.End - MysteryGiftGFX
+ call FarCopyBytes
+ hlcoord 0, 0
+ ld a, $42
+ ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
+ call ByteFill
+ hlcoord 3, 7
+ lb bc, 9, 15
+ call ClearBox
+ hlcoord 0, 0
+ ld a, $0
+ ld [hli], a
+ inc a
+ ld [hl], a
+ hlcoord 0, 1
+ inc a
+ ld [hli], a
+ inc a
+ ld [hl], a
+ hlcoord 7, 1
+ ld a, $12
+ call .Load5GFX
+ hlcoord 2, 2
+ ld a, $17
+ call .Load16GFX
+ hlcoord 2, 3
+ ld a, $27
+ call .Load16GFX
+ hlcoord 9, 4
+ ld a, $37
+ ld [hli], a
+ inc a
+ ld [hl], a
+ hlcoord 1, 2
+ ld [hl], $4
+ hlcoord 1, 3
+ ld a, $5
+ call .Load14Column
+ ld a, $9
+ hlcoord 18, 5
+ call .Load11Column
+ hlcoord 2, 5
+ ld a, $b
+ call .Load16Row
+ hlcoord 2, 16
+ ld a, $7
+ call .Load16Row
+ hlcoord 2, 5
+ ld a, $d
+ call .Load5GFX
+ hlcoord 7, 5
+ ld [hl], $c
+ hlcoord 18, 5
+ ld [hl], $a
+ hlcoord 18, 16
+ ld [hl], $8
+ hlcoord 1, 16
+ ld [hl], $6
+ hlcoord 2, 6
+ ld a, $3a
+ call .Load16Row
+ hlcoord 2, 15
+ ld a, $40
+ call .Load16Row
+ hlcoord 2, 6
+ ld a, $3c
+ call .Load9Column
+ hlcoord 17, 6
+ ld a, $3e
+ call .Load9Column
+ hlcoord 2, 6
+ ld [hl], $39
+ hlcoord 17, 6
+ ld [hl], $3b
+ hlcoord 2, 15
+ ld [hl], $3f
+ hlcoord 17, 15
+ ld [hl], $41
+ call EnableLCD
+ call WaitBGMap
+ ld b, SCGB_MYSTERY_GIFT
+ call GetSGBLayout
+ call SetPalettes
+ ret
+
+.Load5GFX: ; 10522e (41:522e)
+ ld b, 5
+ jr .gfx_loop
+; 105232 (41:5232)
+
+.Unreferenced_Load6GFX:
+ ld b, 6
+ jr .gfx_loop
+
+.Load16GFX: ; 105236 (41:5236)
+ ld b, 16
+
+.gfx_loop ; 105238 (41:5238)
+ ld [hli], a
+ inc a
+ dec b
+ jr nz, .gfx_loop
+ ret
+
+.Load9Column: ; 10523e (41:523e)
+ ld b, 9
+ jr .col_loop
+
+.Load11Column: ; 105242 (41:5242)
+ ld b, 11
+ jr .col_loop
+
+.Load14Column: ; 105246 (41:5246)
+ ld b, 14
+
+.col_loop ; 105248 (41:5248)
+ ld [hl], a
+ ld de, SCREEN_WIDTH
+ add hl, de
+ dec b
+ jr nz, .col_loop
+ ret
+
+.Load16Row: ; 105251 (41:5251)
+ ld b, 16
+.row_loop
+ ld [hli], a
+ dec b
+ jr nz, .row_loop
+ ret
+
+MysteryGiftGFX: ; 105258
+INCBIN "gfx/mystery_gift/mystery_gift.2bpp"
+.End
+
+Function105688: ; 105688 (41:5688)
+ call ClearTileMap
+ call ClearSprites
+ call WaitBGMap
+ call Function1057d7
+ hlcoord 3, 8
+ ld de, String_PressAToLink_BToCancel_JP
+ call PlaceString
+ call WaitBGMap
+ call Function10578c
+ call MysteryGift_ClearTrainerData
+ ld a, $24
+ ld [wca02], a
+ ld a, [rIE]
+ push af
+ call Function104c2d
+ ld d, a
+ xor a
+ ld [rIF], a
+ pop af
+ ld [rIE], a
+ ld a, d
+ cp $10
+ jp z, Function105712
+ cp $6c
+ jp nz, Function10571a
+ call Function1056eb
+ ld c, 60
+ call DelayFrames
+ call Function105777
+ ld hl, Text_ReceivedCard
+ call PrintText
+ ld de, wMysteryGiftTrainerData
+ farcall Function8ac70
+ ld a, c
+ ld [wd265], a
+ ld hl, Text_CardNotRegistered
+ jr c, PrintTextAndExit_JP
+ ld hl, Text_ListedCardAsNumber
+ jr PrintTextAndExit_JP
+
+Function1056eb: ; 1056eb (41:56eb)
+ ld c, 16
+.loop
+ ld hl, wVirtualOAMSprite00YCoord
+ ld b, 8
+.dec_y_loop
+ dec [hl]
+rept SPRITEOAMSTRUCT_LENGTH
+ inc hl
+endr
+ dec b
+ jr nz, .dec_y_loop
+ ld hl, wVirtualOAMSprite08YCoord
+ ld b, 8
+.inc_y_loop
+ inc [hl]
+rept SPRITEOAMSTRUCT_LENGTH
+ inc hl
+endr
+ dec b
+ jr nz, .inc_y_loop
+ dec c
+ ret z
+ push bc
+ ld c, 4
+ call DelayFrames
+ pop bc
+ jr .loop
+
+Function105712: ; 105712 (41:5712)
+ call Function105777
+ ld hl, Text_MGLinkCanceled
+ jr PrintTextAndExit_JP
+
+Function10571a: ; 10571a (41:571a)
+ call Function105777
+ ld hl, Text_MGCommError
+ call PrintText
+ jp Function105688
+
+PrintTextAndExit_JP: ; 105726 (41:5726)
+ call PrintText
+ ld a, LCDC_DEFAULT
+ ld [rLCDC], a
+ ret
+; 10572e (41:572e)
+
+String_PressAToLink_BToCancel_JP: ; 10572e
+ db "エーボタン<WO>おすと"
+ next "つうしん<PKMN>おこなわれるよ!"
+ next "ビーボタン<WO>おすと"
+ next "つうしん<WO>ちゅうし します"
+ db "@"
+
+; 10575e
+
+Text_ReceivedCard: ; 10575e
+ text_jump UnknownText_0x1c051a
+ db "@"
+
+Text_ListedCardAsNumber: ; 105763
+ text_jump UnknownText_0x1c0531
+ db "@"
+
+Text_CardNotRegistered: ; 105768
+ text_jump UnknownText_0x1c0555
+ db "@"
+
+Text_MGLinkCanceled: ; 10576d
+ text_jump UnknownText_0x1c0573
+ db "@"
+
+Text_MGCommError: ; 105772
+ text_jump UnknownText_0x1c0591
+ db "@"
+; 105777
+
+Function105777: ; 105777 (41:5777)
+ call ClearSprites
+ call ClearTileMap
+ call EnableLCD
+ call WaitBGMap
+ ld b, SCGB_DIPLOMA
+ call GetSGBLayout
+ call SetPalettes
+ ret
+
+Function10578c: ; 10578c (41:578c)
+ ld de, wLinkData
+ ld a, BANK(sPlayerData)
+ call GetSRAMBank
+ ld hl, sPlayerData + wPlayerName - wPlayerData
+ ld bc, NAME_LENGTH
+ call CopyBytes
+ ld hl, sPlayerData + wPlayerID - wPlayerData
+ ld bc, 2
+ call CopyBytes
+ ld hl, sPlayerData + wSecretID - wPlayerData
+ ld bc, 2
+ call CopyBytes
+ call CloseSRAM
+ ld a, BANK(sCrystalData)
+ call GetSRAMBank
+ ld a, [sCrystalData + 0]
+ ld [de], a
+ inc de
+ ld a, 4 ; MBC30 bank used by JP Crystal; inaccessible by MBC3
+ call GetSRAMBank
+ ld hl, $a603 ; address of MBC30 bank
+ ld bc, $8
+ call CopyBytes
+ ld hl, $a007 ; address of MBC30 bank
+ ld bc, $c
+ call CopyBytes
+ call CloseSRAM
+ ret
+
+Function1057d7: ; 1057d7 (41:57d7)
+ call ClearBGPalettes
+ call DisableLCD
+ ld hl, MysteryGiftJP_GFX
+ ld de, vTiles2 tile $00
+ ld a, BANK(MysteryGiftJP_GFX)
+ lb bc, 4, 0
+ call FarCopyBytes
+ ld hl, MysteryGiftJP_GFX + $40 tiles
+ ld de, vTiles0 tile $00
+ ld a, BANK(MysteryGiftJP_GFX)
+ ld bc, $80
+ call FarCopyBytes
+ hlcoord 0, 0
+ ld a, $3f
+ ld bc, SCREEN_HEIGHT * SCREEN_WIDTH
+ call ByteFill
+ hlcoord 3, 7
+ lb bc, 9, 15
+ call ClearBox
+ hlcoord 0, 0
+ ld a, $0
+ ld [hli], a
+ inc a
+ ld [hl], a
+ hlcoord 0, 1
+ inc a
+ ld [hli], a
+ inc a
+ ld [hl], a
+ hlcoord 4, 2
+ ld a, $13
+ call .Load11Row
+ hlcoord 4, 3
+ ld a, $1e
+ call .Load12Row
+ hlcoord 4, 4
+ ld a, $2a
+ call .Load12Row
+ hlcoord 1, 2
+ ld [hl], $4
+ hlcoord 1, 3
+ ld a, $5
+ call .Load14Column
+ ld a, $9
+ hlcoord 18, 5
+ call .Load11Column
+ hlcoord 2, 5
+ ld a, $b
+ call .Load16Row
+ hlcoord 2, 16
+ ld a, $7
+ call .Load16Row
+ hlcoord 2, 5
+ ld a, $d
+ call .Load6Row
+ hlcoord 8, 5
+ ld [hl], $c
+ hlcoord 18, 5
+ ld [hl], $a
+ hlcoord 18, 16
+ ld [hl], $8
+ hlcoord 1, 16
+ ld [hl], $6
+ hlcoord 2, 6
+ ld a, $37
+ call .Load16Row
+ hlcoord 2, 15
+ ld a, $3d
+ call .Load16Row
+ hlcoord 2, 6
+ ld a, $39
+ call .Load9Column
+ hlcoord 17, 6
+ ld a, $3b
+ call .Load9Column
+ hlcoord 2, 6
+ ld [hl], $36
+ hlcoord 17, 6
+ ld [hl], $38
+ hlcoord 2, 15
+ ld [hl], $3c
+ hlcoord 17, 15
+ ld [hl], $3e
+ ld de, wVirtualOAMSprite00
+ ld hl, .OAM_data
+ ld bc, 16 * SPRITEOAMSTRUCT_LENGTH
+ call CopyBytes
+ call EnableLCD
+ call WaitBGMap
+ ld b, $2
+ farcall GetMysteryGift_MobileAdapterLayout
+ jp SetPalettes
+
+.Load6Row: ; 1058c6 (41:58c6)
+ ld b, 6
+ jr .row_loop
+
+.Load11Row: ; 1058ca (41:58ca)
+ ld b, 11
+ jr .row_loop
+
+.Load12Row: ; 1058ce (41:58ce)
+ ld b, 12
+
+.row_loop ; 1058d0 (41:58d0)
+ ld [hli], a
+ inc a
+ dec b
+ jr nz, .row_loop
+ ret
+
+.Load9Column: ; 1058d6 (41:58d6)
+ ld b, 9
+ jr .column_loop
+
+.Load11Column: ; 1058da (41:58da)
+ ld b, 11
+ jr .column_loop
+
+.Load14Column: ; 1058de (41:58de)
+ ld b, 14
+
+.column_loop ; 1058e0 (41:58e0)
+ ld [hl], a
+ ld de, SCREEN_WIDTH
+ add hl, de
+ dec b
+ jr nz, .column_loop
+ ret
+
+.Load16Row: ; 1058e9 (41:58e9)
+ ld b, 16
+.row_loop_no_inc
+ ld [hli], a
+ dec b
+ jr nz, .row_loop_no_inc
+ ret
+; 1058f0 (41:58f0)
+
+.OAM_data: ; 1058f0
+ dsprite 2, 1, 6, 4, $00, 0
+ dsprite 2, 1, 7, 4, $01, 0
+ dsprite 2, 1, 8, 4, $02, 0
+ dsprite 2, 1, 9, 4, $03, 0
+ dsprite 3, 1, 6, 4, $04, 0
+ dsprite 3, 1, 7, 4, $05, 0
+ dsprite 3, 1, 8, 4, $06, 0
+ dsprite 3, 1, 9, 4, $07, 0
+ dsprite 0, 1, 11, 4, $00, 0
+ dsprite 0, 1, 12, 4, $01, 0
+ dsprite 0, 1, 13, 4, $02, 0
+ dsprite 0, 1, 14, 4, $03, 0
+ dsprite 1, 1, 11, 4, $04, 0
+ dsprite 1, 1, 12, 4, $05, 0
+ dsprite 1, 1, 13, 4, $06, 0
+ dsprite 1, 1, 14, 4, $07, 0
+
+; japanese mystery gift gfx
+MysteryGiftJP_GFX: ; 105930
+INCBIN "gfx/mystery_gift/mystery_gift_jp.2bpp"
diff --git a/engine/link/mystery_gift_2.asm b/engine/link/mystery_gift_2.asm
new file mode 100644
index 000000000..e0e2e88fd
--- /dev/null
+++ b/engine/link/mystery_gift_2.asm
@@ -0,0 +1,152 @@
+PrepMysteryGiftDataToSend: ; 2c642 (b:4642)
+ ld de, wMysteryGiftStaging
+ ld a, $1
+ ld [de], a
+ inc de ; wc801
+ ld a, BANK(sGameData)
+ call GetSRAMBank
+ ld hl, sPlayerData + wPlayerID - wPlayerData
+ ld a, [hli]
+ ld [de], a
+ ld b, a
+ inc de ; wc802
+ ld a, [hl]
+ ld [de], a
+ ld c, a
+ inc de ; wc803
+ push bc
+ ld hl, sPlayerData + wPlayerName - wPlayerData
+ ld bc, NAME_LENGTH
+ call CopyBytes
+ push de ; wc80e
+ ld hl, sPokemonData + wPokedexCaught - wPokemonData
+ ld b, wEndPokedexCaught - wPokedexCaught
+ call CountSetBits
+ pop de
+ pop bc
+ ld a, [wd265]
+ ld [de], a
+ inc de ; wc80f
+ call CloseSRAM
+ call Random
+ and 1
+ ld [de], a
+ inc de ; wc810
+ call .RandomSample
+ ld [de], a
+ inc de ; wc811
+ ld a, c
+ ld c, b
+ ld b, a
+ call .RandomSample
+ ld [de], a
+ inc de ; wc812
+ ld a, BANK(sBackupMysteryGiftItem)
+ call GetSRAMBank
+ ld a, [sBackupMysteryGiftItem]
+ ld [de], a
+ inc de
+ ld a, [sBackupMysteryGiftItem + 1]
+ ld [de], a
+ ld a, $14
+ ld [wca00], a
+ call CloseSRAM
+ ld hl, wMysteryGiftStaging
+ ld de, wMysteryGiftPlayerData
+ ld bc, wMysteryGiftPlayerDataEnd - wMysteryGiftPlayerData
+ jp CopyBytes
+
+.RandomSample: ; 2c6ac (b:46ac)
+ push de
+ call Random
+ cp 10 percent
+ jr c, .tenpercent
+ call Random
+ and %111
+ ld d, a
+ rl d
+ ld e, $80
+.loop
+ rlc e
+ dec a
+ jr nz, .loop
+ ld a, e
+ and c
+ jr z, .skip
+ ld a, $1
+.skip
+ add d
+ jr .done
+
+.tenpercent
+ call Random
+ cp 20 percent - 1
+ jr c, .twopercent
+ call Random
+ and %011
+ ld d, a
+ rl d
+ ld e, $80
+.loop2
+ rlc e
+ dec a
+ jr nz, .loop2
+ ld a, e
+ and b
+ jr z, .skip2
+ ld a, $1
+.skip2
+ add d
+ add $10
+ jr .done
+
+.twopercent
+ call Random
+ cp 20 percent - 1
+ jr c, .pointfourpercent
+ ld a, b
+ swap a
+ and $7
+ add $18
+ jr .done
+
+.pointfourpercent
+ ld a, b
+ and $80
+ ld a, $20
+ jr z, .done
+ ld a, $21
+
+.done
+ pop de
+ ret
+
+MysteryGiftGetItemHeldEffect: ; 2c708 (b:4708)
+ ld a, c
+ cp MysteryGiftItems.End - MysteryGiftItems
+ jr nc, MysteryGiftFallbackItem
+ ld hl, MysteryGiftItems
+ ld b, 0
+ add hl, bc
+ ld c, [hl]
+ ret
+
+MysteryGiftGetDecoration: ; 2c715 (b:4715)
+ ld a, c
+ cp MysteryGiftDecos.End - MysteryGiftDecos
+ jr nc, MysteryGiftFallbackItem
+ ld hl, MysteryGiftDecos
+ ld b, 0
+ add hl, bc
+ ld c, [hl]
+ ret
+
+MysteryGiftFallbackItem: ; 2c722 (b:4722)
+ ld c, DECO_POLKADOT_BED ; GREAT_BALL
+ ret
+; 2c725 (b:4725)
+
+
+INCLUDE "data/items/mystery_gift_items.asm"
+
+INCLUDE "data/decorations/mystery_gift_decos.asm"
diff --git a/engine/link/place_waiting_text.asm b/engine/link/place_waiting_text.asm
new file mode 100644
index 000000000..9b2260722
--- /dev/null
+++ b/engine/link/place_waiting_text.asm
@@ -0,0 +1,24 @@
+PlaceWaitingText:: ; 4000
+ hlcoord 3, 10
+ ld b, 1
+ ld c, 11
+
+ ld a, [wBattleMode]
+ and a
+ jr z, .notinbattle
+
+ call TextBox
+ jr .proceed
+
+.notinbattle
+ predef LinkTextboxAtHL
+
+.proceed
+ hlcoord 4, 11
+ ld de, .Waiting
+ call PlaceString
+ ld c, 50
+ jp DelayFrames
+
+.Waiting: ; 4025
+ db "Waiting...!@"
diff --git a/engine/link/time_capsule.asm b/engine/link/time_capsule.asm
new file mode 100644
index 000000000..f90b7e249
--- /dev/null
+++ b/engine/link/time_capsule.asm
@@ -0,0 +1,147 @@
+; These functions seem to be related to backwards compatibility
+
+ValidateOTTrademon: ; fb57e
+ ld a, [wd003]
+ ld hl, wOTPartyMon1Species
+ call GetPartyLocation
+ push hl
+ ld a, [wd003]
+ inc a
+ ld c, a
+ ld b, 0
+ ld hl, wOTPartyCount
+ add hl, bc
+ ld a, [hl]
+ pop hl
+ cp EGG
+ jr z, .matching_or_egg
+ cp [hl]
+ jr nz, .abnormal
+
+.matching_or_egg
+ ld b, h
+ ld c, l
+ ld hl, MON_LEVEL
+ add hl, bc
+ ld a, [hl]
+ cp MAX_LEVEL + 1
+ jr nc, .abnormal
+ ld a, [wLinkMode]
+ cp LINK_TIMECAPSULE
+ jr nz, .normal
+ ld hl, wOTPartySpecies
+ ld a, [wd003]
+ ld c, a
+ ld b, 0
+ add hl, bc
+ ld a, [hl]
+
+ ; Magnemite and Magneton's types changed
+ ; from Electric to Electric/Steel.
+ cp MAGNEMITE
+ jr z, .normal
+ cp MAGNETON
+ jr z, .normal
+
+ ld [wCurSpecies], a
+ call GetBaseData
+ ld hl, wLinkOTPartyMonTypes
+ add hl, bc
+ add hl, bc
+ ld a, [wBaseType1]
+ cp [hl]
+ jr nz, .abnormal
+ inc hl
+ ld a, [wBaseType2]
+ cp [hl]
+ jr nz, .abnormal
+
+.normal
+ and a
+ ret
+
+.abnormal
+ scf
+ ret
+; fb5dd
+
+Functionfb5dd: ; fb5dd
+ ld a, [wd002]
+ ld d, a
+ ld a, [wPartyCount]
+ ld b, a
+ ld c, $0
+.loop
+ ld a, c
+ cp d
+ jr z, .next
+ push bc
+ ld a, c
+ ld hl, wPartyMon1HP
+ call GetPartyLocation
+ pop bc
+ ld a, [hli]
+ or [hl]
+ jr nz, .done
+
+.next
+ inc c
+ dec b
+ jr nz, .loop
+ ld a, [wd003]
+ ld hl, wOTPartyMon1HP
+ call GetPartyLocation
+ ld a, [hli]
+ or [hl]
+ jr nz, .done
+ scf
+ ret
+
+.done
+ and a
+ ret
+; fb60d
+
+PlaceTradePartnerNamesAndParty: ; fb60d
+ hlcoord 4, 0
+ ld de, wPlayerName
+ call PlaceString
+ ld a, $14
+ ld [bc], a
+ hlcoord 4, 8
+ ld de, wOTPlayerName
+ call PlaceString
+ ld a, $14
+ ld [bc], a
+ hlcoord 7, 1
+ ld de, wPartySpecies
+ call .PlaceSpeciesNames
+ hlcoord 7, 9
+ ld de, wOTPartySpecies
+.PlaceSpeciesNames: ; fb634
+ ld c, $0
+.loop
+ ld a, [de]
+ cp -1
+ ret z
+ ld [wd265], a
+ push bc
+ push hl
+ push de
+ push hl
+ ld a, c
+ ld [hProduct], a
+ call GetPokemonName
+ pop hl
+ call PlaceString
+ pop de
+ inc de
+ pop hl
+ ld bc, SCREEN_WIDTH
+ add hl, bc
+ pop bc
+ inc c
+ jr .loop
+; fb656
+
+INCLUDE "data/pokemon/gen1_base_special.asm"
diff --git a/engine/link/time_capsule_2.asm b/engine/link/time_capsule_2.asm
new file mode 100644
index 000000000..a56e51785
--- /dev/null
+++ b/engine/link/time_capsule_2.asm
@@ -0,0 +1,39 @@
+ConvertMon_2to1: ; fb8f1
+; Takes the Gen-2 Pokemon number stored in wd265, finds it in the Pokered_MonIndices table, and returns its index in wd265.
+ push bc
+ push hl
+ ld a, [wd265]
+ ld b, a
+ ld c, 0
+ ld hl, Pokered_MonIndices
+.loop
+ inc c
+ ld a, [hli]
+ cp b
+ jr nz, .loop
+ ld a, c
+ ld [wd265], a
+ pop hl
+ pop bc
+ ret
+; fb908
+
+ConvertMon_1to2: ; fb908
+; Takes the Gen-1 Pokemon number stored in wd265 and returns the corresponding value from Pokered_MonIndices in wd265.
+ push bc
+ push hl
+ ld a, [wd265]
+ dec a
+ ld hl, Pokered_MonIndices
+ ld b, 0
+ ld c, a
+ add hl, bc
+ ld a, [hl]
+ ld [wd265], a
+ pop hl
+ pop bc
+ ret
+; fb91c
+
+
+INCLUDE "data/pokemon/gen1_order.asm"