ref: 446f1846b1c614ab1538d1ce11aa2781c22717f2
parent: 2738858985dbcff55c2ec237ac6075b4263f3120
author: Rangi <remy.oukaour+rangi42@gmail.com>
date: Tue Oct 27 09:22:27 EDT 2020
Identify remaining Mystery Gift labels and constants Source: https://projectpokemon.org/home/forums/topic/43930-mystery-gift-reverse-engineering-of-ir-protocol/
--- a/constants/hardware_constants.asm
+++ b/constants/hardware_constants.asm
@@ -71,10 +71,10 @@
rTMA EQU $ff06 ; Timer Modulo (R/W)
rTAC EQU $ff07 ; Timer Control (R/W)
rTAC_ON EQU 2
-rTAC_4096_HZ EQU 0
-rTAC_262144_HZ EQU 1
-rTAC_65536_HZ EQU 2
-rTAC_16384_HZ EQU 3
+rTAC_4096_HZ EQU %00
+rTAC_262144_HZ EQU %01
+rTAC_65536_HZ EQU %10
+rTAC_16384_HZ EQU %11
rIF EQU $ff0f ; Interrupt Flag (R/W)
rNR10 EQU $ff10 ; Channel 1 Sweep register (R/W)
rNR11 EQU $ff11 ; Channel 1 Sound length/Wave pattern duty (R/W)
@@ -147,6 +147,9 @@
rHDMA4 EQU $ff54 ; CGB Mode Only - New DMA Destination, Low
rHDMA5 EQU $ff55 ; CGB Mode Only - New DMA Length/Mode/Start
rRP EQU $ff56 ; CGB Mode Only - Infrared Communications Port
+rRP_LED_ON EQU 0
+rRP_RECEIVING EQU 1
+rRP_ENABLE_READ_MASK EQU %11000000
rBGPI EQU $ff68 ; CGB Mode Only - Background Palette Index
rBGPI_AUTO_INCREMENT EQU 7 ; increment rBGPI after write to rBGPD
rBGPD EQU $ff69 ; CGB Mode Only - Background Palette Data
--- a/constants/misc_constants.asm
+++ b/constants/misc_constants.asm
@@ -14,6 +14,8 @@
; G/S version ID: 0 = Gold, 1 = Silver (used by checkver)
GS_VERSION EQU 0
+; Pokémon Pikachu 2, a step counter / virtual pet device (used by Mystery Gift)
+POKEMON_PIKACHU_2_VERSION EQU 3
; save file corruption check values
SAVE_CHECK_VALUE_1 EQU 99
--- a/constants/serial_constants.asm
+++ b/constants/serial_constants.asm
@@ -30,3 +30,5 @@
SERIAL_PATCH_LIST_PART_TERMINATOR EQU $ff
SERIAL_PREAMBLE_LENGTH EQU 6
+
+MAX_MYSTERY_GIFT_PARTNERS EQU 5
--- a/engine/link/mystery_gift.asm
+++ b/engine/link/mystery_gift.asm
@@ -1,3 +1,27 @@
+; hMGRole values
+IR_RECEIVER EQU 1
+IR_SENDER EQU 2
+
+; hMGStatusFlags error bits
+MG_WRONG_CHECKSUM_F EQU 0
+MG_TIMED_OUT_F EQU 1
+MG_CANCELED_F EQU 4
+MG_WRONG_PREFIX_F EQU 7
+
+; hMGStatusFlags values
+MG_WRONG_CHECKSUM EQU 1 << MG_WRONG_CHECKSUM_F
+MG_TIMED_OUT EQU 1 << MG_TIMED_OUT_F
+MG_CANCELED EQU 1 << MG_CANCELED_F
+MG_WRONG_PREFIX EQU 1 << MG_WRONG_PREFIX_F
+MG_NOT_OKAY EQU MG_WRONG_CHECKSUM | MG_TIMED_OUT | MG_CANCELED | MG_WRONG_PREFIX
+MG_OKAY EQU $ff ^ MG_NOT_OKAY
+MG_START_END EQU %11111111
+
+REGION_PREFIX EQU $96
+REGION_CODE EQU $90 ; USA
+
+MESSAGE_PREFIX EQU $5a
+
DoMysteryGift:
call ClearTilemap
call ClearSprites
@@ -7,22 +31,24 @@
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
- ldh a, [rIE]
- push af
- call Function104a95
+ ; Prepare the first of two messages for wMysteryGiftPartnerData
+ farcall StageDataForMysteryGift
+ call ClearMysteryGiftTrainer
+ ld a, 2
+ ld [wMysteryGiftMessageCount], a
+ ld a, wMysteryGiftPartnerDataEnd - wMysteryGiftPartnerData
+ ld [wMysteryGiftStagedDataLength], a
+ ldh a, [rIE]
+ push af
+ call ExchangeMysteryGiftData
ld d, a
xor a
ldh [rIF], a
pop af
ldh [rIE], a
+
push de
call ClearTilemap
call EnableLCD
@@ -31,15 +57,16 @@
call GetSGBLayout
call SetPalettes
pop de
+
hlcoord 2, 8
ld a, d
ld de, .MysteryGiftCanceledText ; Link has been canceled
- cp $10
+ cp MG_CANCELED
jp z, .LinkCanceled
- cp $6c
+ cp MG_OKAY
jp nz, .CommunicationError
- ld a, [wc900]
- cp 3
+ ld a, [wMysteryGiftGameVersion]
+ cp POKEMON_PIKACHU_2_VERSION
jr z, .skip_checks
call .CheckAlreadyGotFiveGiftsToday
ld hl, .MysteryGiftFiveADayText ; Only 5 gifts a day
@@ -54,12 +81,12 @@
ld a, [wMysteryGiftPartnerBackupItem]
and a
jp nz, .FriendNotReady
- ld a, [wc900]
- cp 3
+ ld a, [wMysteryGiftGameVersion]
+ cp POKEMON_PIKACHU_2_VERSION
jr z, .skip_append_save
call .AddMysteryGiftPartnerID
- ld a, [wc900]
- cp 4
+ ld a, [wMysteryGiftGameVersion]
+ cp 4 ; ???
jr z, .skip_append_save
call .SaveMysteryGiftTrainerName
farcall RestoreMobileEventIndex
@@ -68,14 +95,16 @@
.skip_append_save
ld a, [wMysteryGiftPartnerSentDeco]
and a
- jr z, .item
+ jr z, .SentItem
+; sent decoration
ld a, [wMysteryGiftPartnerWhichDeco]
ld c, a
farcall MysteryGiftGetDecoration
push bc
- call MysteryGift_CheckAndSetDecorationAlreadyReceived
+ call CheckAndSetMysteryGiftDecorationAlreadyReceived
pop bc
- jr nz, .item
+ jr nz, .SentItem
+; keep the decoration if it wasn't already received
callfar GetDecorationName_c
ld h, d
ld l, e
@@ -85,17 +114,17 @@
ld hl, .MysteryGiftSentHomeText ; sent decoration to home
jr .PrintTextAndExit
-.item
+.SentItem:
call GetMysteryGiftBank
ld a, [wMysteryGiftPartnerWhichItem]
ld c, a
- farcall MysteryGiftGetItemHeldEffect
+ farcall MysteryGiftGetItem
ld a, c
ld [sBackupMysteryGiftItem], a
ld [wNamedObjectIndexBuffer], a
call CloseSRAM
call GetItemName
- ld hl, .MysteryGiftSentText ; sent item
+ ld hl, .MysteryGiftSentText ; sent item/decoration
jr .PrintTextAndExit
.LinkCanceled:
@@ -113,6 +142,7 @@
.FriendNotReady:
ld hl, .YourFriendIsNotReadyText ; friend not ready
+ ; fallthrough
.PrintTextAndExit:
call PrintText
@@ -162,7 +192,7 @@
.CheckAlreadyGotFiveGiftsToday:
call GetMysteryGiftBank
ld a, [sNumDailyMysteryGiftPartnerIDs]
- cp $5
+ cp MAX_MYSTERY_GIFT_PARTNERS
jp CloseSRAM
.CheckAlreadyGotAGiftFromThatPerson:
@@ -198,9 +228,9 @@
ld hl, sNumDailyMysteryGiftPartnerIDs
ld a, [hl]
inc [hl]
- ld hl, sDailyMysteryGiftPartnerIDs ; inc hl
+ ld hl, sDailyMysteryGiftPartnerIDs ; could have done "inc hl" instead
ld e, a
- ld d, $0
+ ld d, 0
add hl, de
add hl, de
ld a, [wMysteryGiftPartnerID]
@@ -211,226 +241,268 @@
.SaveMysteryGiftTrainerName:
call GetMysteryGiftBank
- ld a, $1
+ ld a, TRUE
ld [sMysteryGiftTrainerHouseFlag], a
ld hl, wMysteryGiftPartnerName
ld de, sMysteryGiftPartnerName
ld bc, NAME_LENGTH
call CopyBytes
- ld a, $1
+ assert sMysteryGiftPartnerName + NAME_LENGTH == sMysteryGiftUnusedFlag
+ ld a, TRUE
ld [de], a
inc de
- ld hl, wMysteryGiftTrainerData
- ld bc, (1 + 1 + NUM_MOVES) * PARTY_LENGTH + 2
+ assert sMysteryGiftUnusedFlag + 1 == sMysteryGiftTrainer
+ ld hl, wMysteryGiftTrainer
+ ld bc, wMysteryGiftTrainerEnd - wMysteryGiftTrainer
call CopyBytes
jp CloseSRAM
-Function104a95:
+ExchangeMysteryGiftData:
di
farcall ClearChannels
- call Function104d5e
+ call InitializeMysteryGiftInterrupts
-.loop2
- call Function104d96
- call Function104ddd
+.restart
+ call BeginIRCommunication
+ call InitializeIRCommunicationRoles
ldh a, [hMGStatusFlags]
- cp $10
- jp z, Function104bd0
- cp $6c
- jr nz, .loop2
+ cp MG_CANCELED
+ jp z, EndOrContinueIRCommunication
+ cp MG_OKAY
+ jr nz, .restart
- ldh a, [hPrintNumBuffer + 8]
- cp $2
- jr z, Function104b22
- ld hl, hPrintNumBuffer
- ld b, $1
- call Function104d56
- jr nz, .ly_loop
- call Function104b49
- jp nz, Function104bd0
- jr Function104b0a
+ ldh a, [hMGRole]
+ cp IR_SENDER
+ jr z, SenderExchangeMysteryGiftDataPayloads
+; receiver
+ ld hl, hMGExchangedByte
+ ld b, 1
+ call TryReceivingIRDataBlock
+ jr nz, .failed
+ call ReceiveIRDataPayload_GotRegionPrefix
+ jp nz, EndOrContinueIRCommunication
+ jr ReceiverExchangeMysteryGiftDataPayloads_GotPayload
+
+.failed
; Delay frame
-.ly_loop
+.wait_frame
ldh a, [rLY]
cp LY_VBLANK
- jr c, .ly_loop
+ jr c, .wait_frame
+
ld c, LOW(rRP)
- ld a, $c0
+ ld a, rRP_ENABLE_READ_MASK
ldh [c], a
- ld b, 240 ; This might have been intended as a 4-second timeout buffer.
- ; However, it is reset with each frame.
-.loop3
- push bc
- call MysteryGift_ReadJoypad
- ld b, $2
+ ld b, 60 * 4 ; 4 seconds
+.continue
+ push bc
+ call MysteryGift_UpdateJoypad
+ ld b, 1 << rRP_RECEIVING
ld c, LOW(rRP)
- ; Delay frame
-.ly_loop2
+.in_vblank
ldh a, [c]
and b
ld b, a
ldh a, [rLY]
cp LY_VBLANK
- jr nc, .ly_loop2
-.ly_loop3
+ jr nc, .in_vblank
+.wait_vblank
ldh a, [c]
and b
ld b, a
ldh a, [rLY]
cp LY_VBLANK
- jr c, .ly_loop3
-
+ jr c, .wait_vblank
ld a, b
pop bc
+ ; Restart if the 4-second timeout has elapsed
dec b
- jr z, .loop2 ; we never jump here
+ jr z, .restart
+ ; Restart if rRP is not receiving data
or a
- jr nz, .loop2
- ; Check if we've pressed the B button
+ jr nz, .restart
+ ; Check if we've pressed the B button to cancel
ldh a, [hMGJoypadReleased]
bit B_BUTTON_F, a
- jr z, .loop3
- ld a, $10
+ jr z, .continue
+ ld a, MG_CANCELED
ldh [hMGStatusFlags], a
- jp Function104bd0
+ jp EndOrContinueIRCommunication
-Function104b04:
- call Function104b40
- jp nz, Function104bd0
-Function104b0a:
- call Function104d38
- jp nz, Function104bd0
- call Function104b88
- jp nz, Function104bd0
- call Function104d43
- jp nz, Function104bd0
- call Function105033
- jp Function104bd0
+ReceiverExchangeMysteryGiftDataPayloads:
+ ; Receive the data payload
+ call ReceiveIRDataPayload
+ jp nz, EndOrContinueIRCommunication
+ ; fallthrough
+ReceiverExchangeMysteryGiftDataPayloads_GotPayload:
+ ; Switch roles
+ call BeginSendingIRCommunication
+ jp nz, EndOrContinueIRCommunication
+ ; Send the data payload
+ call SendIRDataPayload
+ jp nz, EndOrContinueIRCommunication
+ ; Switch roles
+ call BeginReceivingIRCommunication
+ jp nz, EndOrContinueIRCommunication
+ ; Receive an empty block
+ call ReceiveEmptyIRDataBlock
+ jp EndOrContinueIRCommunication
-Function104b22:
- call Function104b88
- jp nz, Function104bd0
- call Function104d43
- jp nz, Function104bd0
- call Function104b40
- jp nz, Function104bd0
- call Function104d38
- jp nz, Function104bd0
- call Function10502e
- jp Function104bd0
+SenderExchangeMysteryGiftDataPayloads:
+ ; Send the data payload
+ call SendIRDataPayload
+ jp nz, EndOrContinueIRCommunication
+ ; Switch roles
+ call BeginReceivingIRCommunication
+ jp nz, EndOrContinueIRCommunication
+ ; Receive the data payload
+ call ReceiveIRDataPayload
+ jp nz, EndOrContinueIRCommunication
+ ; Switch roles
+ call BeginSendingIRCommunication
+ jp nz, EndOrContinueIRCommunication
+ ; Send an empty block
+ call SendEmptyIRDataBlock
+ jp EndOrContinueIRCommunication
-Function104b40:
- ld hl, hPrintNumBuffer
- ld b, $1
- call Function104d56
+ReceiveIRDataPayload:
+ ; Receive the region prefix
+ ld hl, hMGExchangedByte
+ ld b, 1
+ call TryReceivingIRDataBlock
ret nz
-
-Function104b49:
- call Function105033
+ ; fallthrough
+ReceiveIRDataPayload_GotRegionPrefix:
+ ; Receive an empty block
+ call ReceiveEmptyIRDataBlock
ldh a, [hMGStatusFlags]
- cp $6c
+ cp MG_OKAY
ret nz
- ldh a, [hPrintNumBuffer]
- cp $96
- jp nz, Function104d32
- ld a, $90
- ldh [hPrintNumBuffer], a
- call Function104d38
+ ; Verify the received region prefix
+ ldh a, [hMGExchangedByte]
+ cp REGION_PREFIX
+ jp nz, WrongMysteryGiftRegion
+ ld a, REGION_CODE
+ ldh [hMGExchangedByte], a
+ ; Switch roles
+ call BeginSendingIRCommunication
ret nz
- ld hl, hPrintNumBuffer
- ld b, $1
- call Function104d4e
+ ; Send the region code
+ ld hl, hMGExchangedByte
+ ld b, 1
+ call TrySendingIRDataBlock
ret nz
- call Function10502e
+ ; Send an empty block
+ call SendEmptyIRDataBlock
ldh a, [hMGStatusFlags]
- cp $6c
+ cp MG_OKAY
ret nz
- call Function104d43
+ ; Switch roles
+ call BeginReceivingIRCommunication
ret nz
- ld hl, wMysteryGiftTrainerData
- ld a, [wca02]
+ ; Receive the staged data
+ ld hl, wMysteryGiftTrainer
+ ld a, [wMysteryGiftStagedDataLength]
ld b, a
- call Function104d56
+ call TryReceivingIRDataBlock
ret nz
- call Function105033
+ ; Receive an empty block
+ call ReceiveEmptyIRDataBlock
ldh a, [hMGStatusFlags]
- cp $6c
+ cp MG_OKAY
ret
-Function104b88:
- ld a, $96
- ldh [hPrintNumBuffer], a
- ld hl, hPrintNumBuffer
- ld b, $1
- call Function104d4e
+SendIRDataPayload:
+ ; Send the region prefix
+ ld a, REGION_PREFIX
+ ldh [hMGExchangedByte], a
+ ld hl, hMGExchangedByte
+ ld b, 1
+ call TrySendingIRDataBlock
ret nz
- call Function10502e
+ ; Send an empty block
+ call SendEmptyIRDataBlock
ldh a, [hMGStatusFlags]
- cp $6c
+ cp MG_OKAY
ret nz
- call Function104d43
+ ; Switch roles
+ call BeginReceivingIRCommunication
ret nz
- ld hl, hPrintNumBuffer
- ld b, $1
- call Function104d56
+ ; Receive the region code
+ ld hl, hMGExchangedByte
+ ld b, 1
+ call TryReceivingIRDataBlock
ret nz
- call Function105033
+ ; Receive an empty block
+ call ReceiveEmptyIRDataBlock
ldh a, [hMGStatusFlags]
- cp $6c
+ cp MG_OKAY
ret nz
- ldh a, [hPrintNumBuffer]
- cp $90
- jp nz, Function104d32
- call Function104d38
+ ; Verify the received region code
+ ldh a, [hMGExchangedByte]
+ cp REGION_CODE
+ jp nz, WrongMysteryGiftRegion
+ ; Switch roles
+ call BeginSendingIRCommunication
ret nz
- ld hl, wLinkData
- ld a, [wca02]
+ ; Send the staged data
+ ld hl, wMysteryGiftStaging
+ ld a, [wMysteryGiftStagedDataLength]
ld b, a
- call Function104d4e
+ call TrySendingIRDataBlock
ret nz
- call Function10502e
+ ; Send an empty block
+ call SendEmptyIRDataBlock
ldh a, [hMGStatusFlags]
- cp $6c
+ cp MG_OKAY
ret
-Function104bd0:
+EndOrContinueIRCommunication:
nop
ldh a, [hMGStatusFlags]
- cp $10
+ ; Quit if player canceled
+ cp MG_CANCELED
jr z, .quit
- cp $6c
+ ; Quit if there was a communication error
+ cp MG_OKAY
jr nz, .quit
- ld hl, wca01
+ ; Quit if all messages are sent/received
+ ld hl, wMysteryGiftMessageCount
dec [hl]
jr z, .quit
- ld hl, wMysteryGiftTrainerData
+ ; Quit if communicating with Pokémon Pikachu 2 device
+ ld hl, wMysteryGiftTrainer
ld de, wMysteryGiftPartnerData
ld bc, wMysteryGiftPartnerDataEnd - wMysteryGiftPartnerData
call CopyBytes
- ld a, [wMysteryGiftTrainerData]
- cp $3
+ ld a, [wMysteryGiftTrainer] ; first byte is the version
+ cp POKEMON_PIKACHU_2_VERSION
jr nc, .quit
+
+ ; Prepare the second message for wMysteryGiftTrainer
farcall StagePartyDataForMysteryGift
- call MysteryGift_ClearTrainerData
- ld a, $26
- ld [wca02], a
- ldh a, [hPrintNumBuffer + 8]
- cp $2
- jr z, .asm_104c10
- call Function104d43
- jr nz, Function104bd0
- jp Function104b04
+ call ClearMysteryGiftTrainer
+ ld a, wMysteryGiftTrainerEnd - wMysteryGiftTrainer
+ ld [wMysteryGiftStagedDataLength], a
-.asm_104c10
- call Function104d38
- jr nz, Function104bd0
- jp Function104b22
+ ldh a, [hMGRole]
+ cp IR_SENDER
+ jr z, .sender
+; receiver
+ call BeginReceivingIRCommunication
+ jr nz, EndOrContinueIRCommunication
+ jp ReceiverExchangeMysteryGiftDataPayloads
+.sender
+ call BeginSendingIRCommunication
+ jr nz, EndOrContinueIRCommunication
+ jp SenderExchangeMysteryGiftDataPayloads
+
.quit
ldh a, [hMGStatusFlags]
push af
- call Function104da0
+ call EndIRCommunication
xor a
ldh [rIF], a
ldh a, [rIE]
@@ -444,111 +516,115 @@
Function104c2d:
di
farcall ClearChannels
- call Function104d5e
-.asm_104c37
- call Function104d96
- call Function104ddd
+ call InitializeMysteryGiftInterrupts
+
+.loop2
+ call BeginIRCommunication
+ call InitializeIRCommunicationRoles
ldh a, [hMGStatusFlags]
- cp $10
+ cp MG_CANCELED
jp z, Function104d1c
- cp $6c
- jr nz, .asm_104c37
- ldh a, [hPrintNumBuffer + 8]
- cp $2
- jr z, .asm_104c6c
+ cp MG_OKAY
+ jr nz, .loop2
+
+ ldh a, [hMGRole]
+ cp IR_SENDER
+ jr z, .sender
+; receiver
call Function104c8a
jp nz, Function104d1c
- call Function104d38
+ call BeginSendingIRCommunication
jp nz, Function104d1c
call Function104cd2
jp nz, Function104d1c
- call Function104d43
+ call BeginReceivingIRCommunication
jp nz, Function104d1c
- call Function105033
+ call ReceiveEmptyIRDataBlock
jp Function104d1c
-.asm_104c6c
+
+.sender
call Function104cd2
jp nz, Function104d1c
- call Function104d43
+ call BeginReceivingIRCommunication
jp nz, Function104d1c
call Function104c8a
jp nz, Function104d1c
- call Function104d38
+ call BeginSendingIRCommunication
jp nz, Function104d1c
- call Function10502e
+ call SendEmptyIRDataBlock
jp Function104d1c
Function104c8a:
- ld hl, hPrintNumBuffer
- ld b, $1
- call Function104d56
+ ld hl, hMGExchangedByte
+ ld b, 1
+ call TryReceivingIRDataBlock
ret nz
- call Function105033
+ call ReceiveEmptyIRDataBlock
ldh a, [hMGStatusFlags]
- cp $6c
+ cp MG_OKAY
ret nz
- ldh a, [hPrintNumBuffer]
+ ldh a, [hMGExchangedByte]
cp $3c
- jp nz, Function104d32
+ jp nz, WrongMysteryGiftRegion
swap a
- ldh [hPrintNumBuffer], a
- call Function104d38
+ ldh [hMGExchangedByte], a
+ call BeginSendingIRCommunication
ret nz
- ld hl, hPrintNumBuffer
- ld b, $1
- call Function104d4e
+ ld hl, hMGExchangedByte
+ ld b, 1
+ call TrySendingIRDataBlock
ret nz
- call Function10502e
+ call SendEmptyIRDataBlock
ldh a, [hMGStatusFlags]
- cp $6c
+ cp MG_OKAY
ret nz
- call Function104d43
+ call BeginReceivingIRCommunication
ret nz
- ld hl, wMysteryGiftTrainerData
- ld a, [wca02]
+ ld hl, wMysteryGiftTrainer
+ ld a, [wMysteryGiftStagedDataLength]
ld b, a
- call Function104d56
+ call TryReceivingIRDataBlock
ret nz
- call Function105033
+ call ReceiveEmptyIRDataBlock
ldh a, [hMGStatusFlags]
- cp $6c
+ cp MG_OKAY
ret
Function104cd2:
ld a, $3c
- ldh [hPrintNumBuffer], a
- ld hl, hPrintNumBuffer
- ld b, $1
- call Function104d4e
+ ldh [hMGExchangedByte], a
+ ld hl, hMGExchangedByte
+ ld b, 1
+ call TrySendingIRDataBlock
ret nz
- call Function10502e
+ call SendEmptyIRDataBlock
ldh a, [hMGStatusFlags]
- cp $6c
+ cp MG_OKAY
ret nz
- call Function104d43
+ call BeginReceivingIRCommunication
ret nz
- ld hl, hPrintNumBuffer
- ld b, $1
- call Function104d56
+ ld hl, hMGExchangedByte
+ ld b, 1
+ call TryReceivingIRDataBlock
ret nz
- call Function105033
+ call ReceiveEmptyIRDataBlock
ldh a, [hMGStatusFlags]
- cp $6c
+ cp MG_OKAY
ret nz
- ldh a, [hPrintNumBuffer]
+ ldh a, [hMGExchangedByte]
swap a
cp $3c
- jp nz, Function104d32
- call Function104d38
+ jp nz, WrongMysteryGiftRegion
+ call BeginSendingIRCommunication
ret nz
- ld hl, wLinkData
- ld a, [wca02]
+ ld hl, wMysteryGiftStaging
+ ld a, [wMysteryGiftStagedDataLength]
ld b, a
- call Function104d4e
+ call TrySendingIRDataBlock
ret nz
- call Function10502e
+ call SendEmptyIRDataBlock
ldh a, [hMGStatusFlags]
- cp $6c
+ cp MG_OKAY
ret
Function104d1c:
@@ -555,7 +631,7 @@
nop
ldh a, [hMGStatusFlags]
push af
- call Function104da0
+ call EndIRCommunication
xor a
ldh [rIF], a
ldh a, [rIE]
@@ -566,46 +642,46 @@
pop af
ret
-Function104d32:
- ld a, $80
+WrongMysteryGiftRegion:
+ ld a, MG_WRONG_PREFIX
ldh [hMGStatusFlags], a
and a
ret
-Function104d38:
- call Function104d96
- call Function104e46
+BeginSendingIRCommunication:
+ call BeginIRCommunication
+ call SendIRHelloMessage
ldh a, [hMGStatusFlags]
- cp $6c
+ cp MG_OKAY
ret
-Function104d43:
- call Function104d96
- call Function104dfe
+BeginReceivingIRCommunication:
+ call BeginIRCommunication
+ call ReceiveIRHelloMessage
ldh a, [hMGStatusFlags]
- cp $6c
+ cp MG_OKAY
ret
-Function104d4e:
- call Function104e93
+TrySendingIRDataBlock:
+ call SendIRDataBlock
ldh a, [hMGStatusFlags]
- cp $6c
+ cp MG_OKAY
ret
-Function104d56:
- call Function104f57
+TryReceivingIRDataBlock:
+ call ReceiveIRDataBlock
ldh a, [hMGStatusFlags]
- cp $6c
+ cp MG_OKAY
ret
-Function104d5e:
- call Function104d74
+InitializeMysteryGiftInterrupts:
+ call StartFastIRTimer
ld a, 1 << TIMER
ldh [rIE], a
xor a
ldh [rIF], a
- call Function104d96
-; runs for ~$40400 cycles
+ call BeginIRCommunication
+; waits for ~$40400 cycles = ~0.25 seconds
xor a
ld b, a
.busy_wait
@@ -615,44 +691,48 @@
jr nz, .busy_wait
ret
-Function104d74:
+StartFastIRTimer:
+; Starts a 65,536 Hz timer that interrupts every 3 increments (21,845 Hz).
xor a
ldh [rTAC], a
- ld a, $fe
+ ld a, -2
ldh [rTMA], a
ldh [rTIMA], a
- ld a, $2
+ ld a, rTAC_65536_HZ
ldh [rTAC], a
- or $4
+ or 1 << rTAC_ON
ldh [rTAC], a
ret
-Function104d86:
+StartSlowIRTimer:
+; Starts a 65,536 Hz timer that interrupts every 256 increments (256 Hz).
xor a
ldh [rTAC], a
ldh [rTMA], a
ldh [rTIMA], a
- ld a, $2
+ ld a, rTAC_65536_HZ
ldh [rTAC], a
- or $4
+ or 1 << rTAC_ON
ldh [rTAC], a
ret
-Function104d96:
- ld a, $c0
- call Function104e8c
- ld a, $1
- ldh [hPrintNumBuffer + 8], a
+BeginIRCommunication:
+ ld a, rRP_ENABLE_READ_MASK
+ call ToggleIRCommunication
+ ld a, IR_RECEIVER
+ ldh [hMGRole], a
ret
-Function104da0:
+EndIRCommunication:
xor a
- call Function104e8c
- ld a, $2
+ call ToggleIRCommunication
+ ld a, rTAC_65536_HZ
ldh [rTAC], a
ret
-Function104da9:
+ReceiveInfraredLEDOn:
+; Count interrupts of the partner's IR LED on; quit after 256-d interrupts.
+.recv_loop
inc d
ret z
xor a
@@ -659,12 +739,14 @@
ldh [rIF], a
halt
ldh a, [c]
- bit 1, a
- jr z, Function104da9
+ bit rRP_RECEIVING, a
+ jr z, .recv_loop
or a
ret
-Function104db7:
+ReceiveInfraredLEDOff:
+; Count interrupts of the partner's IR LED off; quit after 256-d interrupts.
+.no_recv_loop
inc d
ret z
xor a
@@ -671,13 +753,14 @@
ldh [rIF], a
halt
ldh a, [c]
- bit 1, a
- jr nz, Function104db7
+ bit rRP_RECEIVING, a
+ jr nz, .no_recv_loop
or a
ret
-Function104dc5:
- ld a, $c1
+SendInfraredLEDOn:
+; Holds the IR LED on for d-1 interrupts.
+ ld a, rRP_ENABLE_READ_MASK | (1 << rRP_LED_ON)
ldh [c], a
.wait
dec d
@@ -687,8 +770,9 @@
halt
jr .wait
-Function104dd1:
- ld a, $c0
+SendInfraredLEDOff:
+; Holds the IR LED off for d-1 interrupts.
+ ld a, rRP_ENABLE_READ_MASK
ldh [c], a
.wait
dec d
@@ -698,175 +782,204 @@
halt
jr .wait
-Function104ddd:
- ld d, $0
+InitializeIRCommunicationRoles:
+ ld d, 0
ld e, d
- ld a, $1
- ldh [hPrintNumBuffer + 8], a
+
+ ld a, IR_RECEIVER
+ ldh [hMGRole], a
.loop
- call MysteryGift_ReadJoypad
- ld b, $2
+ call MysteryGift_UpdateJoypad
+ ld b, 1 << rRP_RECEIVING
ld c, LOW(rRP)
+ ; Check if we've pressed the B button to cancel
ldh a, [hMGJoypadReleased]
bit B_BUTTON_F, a
- jr z, .next
- ld a, $10
+ jr z, .not_canceled
+ ld a, MG_CANCELED
ldh [hMGStatusFlags], a
ret
-.next
- bit 0, a
- jr nz, Function104e3a
+.not_canceled
+ ; Check if we've pressed the A button to start sending
+ bit A_BUTTON_F, a
+ jr nz, SendIRHelloMessageAfterDelay
+ ; If rRP is not receiving data, keep checking for input
ldh a, [c]
and b
jr nz, .loop
+ ; fallthrough
-Function104dfe:
+ReceiveIRHelloMessage:
ld c, LOW(rRP)
- ld d, $0
+ ld d, 0
ld e, d
- call Function104db7
- jp z, Function104f42
+
+ call ReceiveInfraredLEDOff
+ jp z, InfraredLEDReceiveTimedOut
ld d, e
- call Function104da9
- jp z, Function104f42
- call Function104db7
- jp z, Function104f42
- call Function104da9
- jp z, Function104f42
- ld a, $6c
+ call ReceiveInfraredLEDOn
+ jp z, InfraredLEDReceiveTimedOut
+ call ReceiveInfraredLEDOff
+ jp z, InfraredLEDReceiveTimedOut
+ call ReceiveInfraredLEDOn
+ jp z, InfraredLEDReceiveTimedOut
+
+ ld a, MG_OKAY
ldh [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
+
+ ld d, 61
+ call SendInfraredLEDOff
+ ld d, 5
+ call SendInfraredLEDOn
+ ld d, 21
+ call SendInfraredLEDOff
+ ld d, 5
+ call SendInfraredLEDOn
+ ld d, 5
+ call SendInfraredLEDOff
ret
-Function104e3a:
+SendIRHelloMessageAfterDelay:
; Wait a random amount of time
call Random
ld e, a
and $f
ld d, a
-.loop
+.wait_loop
dec de
ld a, d
or e
- jr nz, .loop
-Function104e46:
- ld a, $2
- ldh [hPrintNumBuffer + 8], a
+ jr nz, .wait_loop
+ ; fallthrough
+
+SendIRHelloMessage:
+ ld a, IR_SENDER
+ ldh [hMGRole], a
+
ld c, LOW(rRP)
- ld d, $0
+ 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, 61
+ call SendInfraredLEDOff
+ ld d, 5
+ call SendInfraredLEDOn
+ ld d, 21
+ call SendInfraredLEDOff
+ ld d, 5
+ call SendInfraredLEDOn
+ ld d, 5
+ call SendInfraredLEDOff
+
ld d, e
- call Function104db7
- jp z, Function104f42
+ call ReceiveInfraredLEDOff
+ jp z, InfraredLEDReceiveTimedOut
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
+ call ReceiveInfraredLEDOn
+ jp z, InfraredLEDReceiveTimedOut
+ call ReceiveInfraredLEDOff
+ jp z, InfraredLEDReceiveTimedOut
+ call ReceiveInfraredLEDOn
+ jp z, InfraredLEDReceiveTimedOut
+
+ ld d, 61
+ call SendInfraredLEDOff
+
+ ld a, MG_OKAY
ldh [hMGStatusFlags], a
ret
-Function104e8c:
+ToggleIRCommunication:
ldh [rRP], a
- ld a, $ff
+ ld a, MG_START_END
ldh [hMGStatusFlags], a
ret
-Function104e93:
+SendIRDataBlock:
+; Send b bytes of data in three messages:
+; 1. two bytes: MESSAGE_PREFIX and the length b
+; 2. b bytes: the actual data
+; 3. two bytes: a little-endian checksum
+; Then receive a one-byte acknowledgement message: the status.
xor a
- ldh [hPrintNumBuffer + 4], a
- ldh [hPrintNumBuffer + 5], a
+ ldh [hMGChecksum + 0], a
+ ldh [hMGChecksum + 1], a
push hl
push bc
ld c, LOW(rRP)
- ld d, $3d
- call Function104dd1
- ld hl, hPrintNumBuffer + 1
- ld a, $5a
+ ld d, 61
+ call SendInfraredLEDOff
+ ld hl, hMGExchangedWord
+ ld a, MESSAGE_PREFIX
ld [hli], a
ld [hl], b
dec hl
- ld b, $2
- call Function104ed6
+ ld b, 2
+ call SendIRDataMessage
pop bc
pop hl
- call Function104ed6
- ldh a, [hPrintNumBuffer + 4]
- ldh [hPrintNumBuffer + 1], a
- ldh a, [hPrintNumBuffer + 5]
- ldh [hPrintNumBuffer + 2], a
+ call SendIRDataMessage
+ ldh a, [hMGChecksum + 0]
+ ldh [hMGExchangedWord + 0], a
+ ldh a, [hMGChecksum + 1]
+ ldh [hMGExchangedWord + 1], a
push hl
- ld hl, hPrintNumBuffer + 1
- ld b, $2
- call Function104ed6
+ ld hl, hMGExchangedWord
+ ld b, 2
+ call SendIRDataMessage
ld hl, hMGStatusFlags
- ld b, $1
- call Function104faf
- ldh a, [hPrintNumBuffer + 1]
- ldh [hPrintNumBuffer + 4], a
- ldh a, [hPrintNumBuffer + 2]
- ldh [hPrintNumBuffer + 5], a
+ ld b, 1
+ call ReceiveIRDataMessage
+ ldh a, [hMGExchangedWord + 0]
+ ldh [hMGChecksum + 0], a
+ ldh a, [hMGExchangedWord + 1]
+ ldh [hMGChecksum + 1], a
pop hl
ret
-Function104ed6:
+SendIRDataMessage:
+; Send b bytes of data one bit at a time, and update the checksum.
ld c, LOW(rRP)
- ld d, $5
- call Function104dd1
- ld d, $5
- call Function104dc5
- ld d, $15
- call Function104dd1
+
+ ld d, 5
+ call SendInfraredLEDOff
+ ld d, 5
+ call SendInfraredLEDOn
+ ld d, 21
+ call SendInfraredLEDOff
+
+ ; b = -b - 1; then count up to 0
ld a, b
cpl
ld b, a
- ld a, $f4
+
+ ld a, -12
ldh [rTMA], a
-.main_loop
+.byte_loop
inc b
jr z, .done
- ld a, $8
- ldh [hPrintNumBuffer + 3], a
+ ld a, 8
+ ldh [hMGNumBits], a
+ ; Get the next data byte
ld a, [hli]
ld e, a
- ldh a, [hPrintNumBuffer + 4]
+ ; Add the next data byte to the checksum
+ ldh a, [hMGChecksum + 0]
add e
- ldh [hPrintNumBuffer + 4], a
- ldh a, [hPrintNumBuffer + 5]
+ ldh [hMGChecksum + 0], a
+ ldh a, [hMGChecksum + 1]
adc 0
- ldh [hPrintNumBuffer + 5], a
-.inner_loop
+ ldh [hMGChecksum + 1], a
+ ; Send each bit of the byte
+.bit_loop
xor a
ldh [rIF], a
halt
- ld a, $c1
+ ld a, rRP_ENABLE_READ_MASK | (1 << rRP_LED_ON)
ldh [rRP], a
- ld d, $1
+ ; Turn the LED off for longer if the bit is 1
+ ld d, 1
ld a, e
rlca
ld e, a
@@ -874,9 +987,9 @@
inc d
.wait
ldh a, [rTIMA]
- cp $f8
+ cp -8
jr c, .wait
- ld a, $c0
+ ld a, rRP_ENABLE_READ_MASK
ldh [rRP], a
dec d
jr z, .no_halt
@@ -884,73 +997,79 @@
ldh [rIF], a
halt
.no_halt
- ldh a, [hPrintNumBuffer + 3]
+ ldh a, [hMGNumBits]
dec a
- jr z, .main_loop
- ldh [hPrintNumBuffer + 3], a
- jr .inner_loop
+ jr z, .byte_loop
+ ldh [hMGNumBits], a
+ jr .bit_loop
.done
- ld a, $fe
+ ld a, -2
ldh [rTMA], a
xor a
ldh [rIF], a
halt
- ld d, $5
- call Function104dc5
- ld d, $11
- call Function104dd1
+
+ ld d, 5
+ call SendInfraredLEDOn
+ ld d, 17
+ call SendInfraredLEDOff
ret
-Function104f42:
+InfraredLEDReceiveTimedOut:
ldh a, [hMGStatusFlags]
- or $2
+ or MG_TIMED_OUT
ldh [hMGStatusFlags], a
ret
-Function104f49:
+ReceivedWrongIRChecksum:
ldh a, [hMGStatusFlags]
- or $1
+ or MG_WRONG_CHECKSUM
ldh [hMGStatusFlags], a
ret
-Function104f50:
+ReceivedWrongIRMessagePrefix:
ldh a, [hMGStatusFlags]
- or $80
+ or MG_WRONG_PREFIX
ldh [hMGStatusFlags], a
ret
-Function104f57:
+ReceiveIRDataBlock:
+; Receive b bytes of data in three messages:
+; 1. two bytes: MESSAGE_PREFIX and the length b
+; 2. b bytes: the actual data
+; 3. two bytes: a little-endian checksum
+; Then send a one-byte acknowledgement message: the status.
xor a
- ldh [hPrintNumBuffer + 4], a
- ldh [hPrintNumBuffer + 5], a
+ ldh [hMGChecksum + 0], a
+ ldh [hMGChecksum + 1], a
push bc
push hl
- ld hl, hPrintNumBuffer + 1
- ld b, $2
- call Function104faf
- ldh a, [hPrintNumBuffer + 2]
- ldh [hPrintNumBuffer + 7], a
+ ld hl, hMGExchangedWord
+ ld b, 2
+ call ReceiveIRDataMessage
+ ldh a, [hMGExchangedWord + 1]
+ ldh [hMGUnusedMsgLength], a
ld b, a
pop hl
pop af
cp b
- jp c, Function104f50
- ldh a, [hPrintNumBuffer + 1]
- cp $5a
- jp nz, Function104f50
- call Function104faf
- ldh a, [hPrintNumBuffer + 4]
+ jp c, ReceivedWrongIRMessagePrefix
+ ldh a, [hMGExchangedWord + 0]
+ cp MESSAGE_PREFIX
+ jp nz, ReceivedWrongIRMessagePrefix
+ call ReceiveIRDataMessage
+ ldh a, [hMGChecksum + 0]
ld d, a
- ldh a, [hPrintNumBuffer + 5]
+ ldh a, [hMGChecksum + 1]
ld e, a
push hl
push de
- ld hl, hPrintNumBuffer + 1
- ld b, $2
- call Function104faf
+ ld hl, hMGExchangedWord
+ ld b, 2
+ call ReceiveIRDataMessage
pop de
- ld hl, hPrintNumBuffer + 1
+ ld hl, hMGExchangedWord
ld a, [hli]
xor d
ld b, a
@@ -957,60 +1076,66 @@
ld a, [hl]
xor e
or b
- call nz, Function104f49
+ call nz, ReceivedWrongIRChecksum
push de
- ld d, $3d
- call Function104dd1
+
+ ld d, 61
+ call SendInfraredLEDOff
+
ld hl, hMGStatusFlags
- ld b, $1
- call Function104ed6
+ ld b, 1
+ call SendIRDataMessage
+
pop de
pop hl
ld a, d
- ldh [hPrintNumBuffer + 4], a
+ ldh [hMGChecksum + 0], a
ld a, e
- ldh [hPrintNumBuffer + 5], a
+ ldh [hMGChecksum + 1], a
ret
-Function104faf:
+ReceiveIRDataMessage:
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 d, 0
+ call ReceiveInfraredLEDOff
+ jp z, InfraredLEDReceiveTimedOut
+ ld d, 0
+ call ReceiveInfraredLEDOn
+ jp z, InfraredLEDReceiveTimedOut
+ ld d, 0
+ call ReceiveInfraredLEDOff
+ jp z, InfraredLEDReceiveTimedOut
+
ld a, b
cpl
ld b, a
xor a
ldh [hMGPrevTIMA], a
- call Function104d86
+
+ call StartSlowIRTimer
.main_loop
inc b
jr z, .done
- ld a, $8
- ldh [hPrintNumBuffer + 3], a
+ ld a, 8
+ ldh [hMGNumBits], a
.inner_loop
- ld d, $0
-.wait_one
+ ld d, 0
+.recv_loop
inc d
- jr z, .got_one
+ jr z, .recv_done
ldh a, [c]
- bit 1, a
- jr z, .wait_one
- ld d, $0
-.got_one
-.wait_zero
+ bit rRP_RECEIVING, a
+ jr z, .recv_loop
+ ld d, 0
+.recv_done
+.send_loop
inc d
- jr z, .got_zero
+ jr z, .send_done
ldh a, [c]
- bit 1, a
- jr nz, .wait_zero
-.got_zero
+ bit rRP_RECEIVING, a
+ jr nz, .send_loop
+.send_done
ldh a, [hMGPrevTIMA]
ld d, a
ldh a, [rTIMA]
@@ -1023,9 +1148,9 @@
.zero
res 0, e
.ok
- ldh a, [hPrintNumBuffer + 3]
+ ldh a, [hMGNumBits]
dec a
- ldh [hPrintNumBuffer + 3], a
+ ldh [hMGNumBits], a
jr z, .continue
ld a, e
rlca
@@ -1035,34 +1160,34 @@
.continue
ld a, e
ld [hli], a
- ldh a, [hPrintNumBuffer + 4]
+ ldh a, [hMGChecksum + 0]
add e
- ldh [hPrintNumBuffer + 4], a
- ldh a, [hPrintNumBuffer + 5]
+ ldh [hMGChecksum + 0], a
+ ldh a, [hMGChecksum + 1]
adc 0
- ldh [hPrintNumBuffer + 5], a
+ ldh [hMGChecksum + 1], a
jr .main_loop
.done
- call Function104d74
+ call StartFastIRTimer
xor a
ldh [rIF], a
- ld d, $0
- call Function104da9
- jp z, Function104f42
- ld d, $10
- call Function104dd1
+ ld d, 0
+ call ReceiveInfraredLEDOn
+ jp z, InfraredLEDReceiveTimedOut
+ ld d, 16
+ call SendInfraredLEDOff
ret
-Function10502e:
- ld b, $0
- jp Function104e93
+SendEmptyIRDataBlock:
+ ld b, 0
+ jp SendIRDataBlock
-Function105033:
- ld b, $0
- jp Function104f57
+ReceiveEmptyIRDataBlock:
+ ld b, 0
+ jp ReceiveIRDataBlock
-MysteryGift_ReadJoypad:
+MysteryGift_UpdateJoypad:
; We can only get four inputs at a time.
; We take d-pad first for no particular reason.
ld a, R_DPAD
@@ -1107,9 +1232,10 @@
ldh [rJOYP], a
ret
-MysteryGift_CheckAndSetDecorationAlreadyReceived:
+CheckAndSetMysteryGiftDecorationAlreadyReceived:
+; Return nz if decoration c was already received; otherwise receive it.
call GetMysteryGiftBank
- ld d, $0
+ ld d, 0
ld b, CHECK_FLAG
ld hl, sMysteryGiftDecorationsReceived
lda_predef SmallFarFlagAction
@@ -1129,12 +1255,12 @@
xor a
ret
-MysteryGift_CopyReceivedDecosToPC:
+CopyMysteryGiftReceivedDecorationsToPC:
call GetMysteryGiftBank
- ld c, $0
+ ld c, 0
.loop
push bc
- ld d, $0
+ ld d, 0
ld b, CHECK_FLAG
ld hl, sMysteryGiftDecorationsReceived
predef SmallFarFlagAction
@@ -1153,6 +1279,8 @@
jp CloseSRAM
UnlockMysteryGift:
+; If [sMysteryGiftUnlocked] was -1, this sets both
+; [sMysteryGiftUnlocked] and [sMysteryGiftItem] to 0.
call GetMysteryGiftBank
ld hl, sMysteryGiftUnlocked
ld a, [hl]
@@ -1159,21 +1287,24 @@
inc a
jr nz, .ok
ld [hld], a
+ assert sMysteryGiftUnlocked - 1 == sMysteryGiftItem
ld [hl], a
.ok
jp CloseSRAM
-Function1050c8:
+ResetDailyMysteryGiftLimitIfUnlocked:
call GetMysteryGiftBank
ld a, [sNumDailyMysteryGiftPartnerIDs]
- cp $ff
- jr z, .okay
+ cp -1 ; locked?
+ jr z, .dont_clear
xor a
ld [sNumDailyMysteryGiftPartnerIDs], a
-.okay
+.dont_clear
jp CloseSRAM
BackupMysteryGift:
+; Copies [sMysteryGiftItem] to [sBackupMysteryGiftItem],
+; and [sMysteryGiftUnlocked] to [sNumDailyMysteryGiftPartnerIDs].
call GetMysteryGiftBank
ld hl, sMysteryGiftItem
ld de, sBackupMysteryGiftItem
@@ -1180,11 +1311,15 @@
ld a, [hli]
ld [de], a
inc de
+ assert sMysteryGiftItem + 1 == sMysteryGiftUnlocked
+ assert sBackupMysteryGiftItem + 1 == sNumDailyMysteryGiftPartnerIDs
ld a, [hl]
ld [de], a
jp CloseSRAM
RestoreMysteryGift:
+; Copies [sBackupMysteryGiftItem] to [sMysteryGiftItem],
+; and [sNumDailyMysteryGiftPartnerIDs] to [sMysteryGiftUnlocked].
call GetMysteryGiftBank
ld hl, sBackupMysteryGiftItem
ld de, sMysteryGiftItem
@@ -1191,14 +1326,16 @@
ld a, [hli]
ld [de], a
inc de
+ assert sBackupMysteryGiftItem + 1 == sNumDailyMysteryGiftPartnerIDs
+ assert sMysteryGiftItem + 1 == sMysteryGiftUnlocked
ld a, [hl]
ld [de], a
jp CloseSRAM
-MysteryGift_ClearTrainerData:
- ld hl, wMysteryGiftTrainerData
+ClearMysteryGiftTrainer:
+ ld hl, wMysteryGiftTrainer
xor a
- ld b, wMysteryGiftTrainerDataEnd - wMysteryGiftTrainerData
+ ld b, wMysteryGiftTrainerEnd - wMysteryGiftTrainer
.loop
ld [hli], a
dec b
@@ -1206,7 +1343,7 @@
ret
GetMysteryGiftBank:
- ld a, BANK(sBackupMysteryGiftItem)
+ ld a, BANK(sMysteryGiftData)
jp OpenSRAM
StagePartyDataForMysteryGift:
@@ -1256,8 +1393,8 @@
.party_end
ld a, -1
ld [de], a
- ld a, $26
- ld [wca00], a
+ ld a, wMysteryGiftTrainerEnd - wMysteryGiftTrainer
+ ld [wUnusedMysteryGiftStagedDataLength], a
jp CloseSRAM
InitMysteryGiftLayout:
@@ -1409,9 +1546,9 @@
call PlaceString
call WaitBGMap
call Function10578c
- call MysteryGift_ClearTrainerData
+ call ClearMysteryGiftTrainer
ld a, $24
- ld [wca02], a
+ ld [wMysteryGiftStagedDataLength], a
ldh a, [rIE]
push af
call Function104c2d
@@ -1423,7 +1560,7 @@
ld a, d
cp $10
jp z, Function105712
- cp $6c
+ cp %01101100
jp nz, Function10571a
call Function1056eb
ld c, 60
@@ -1431,7 +1568,7 @@
call Function105777
ld hl, MysteryGiftReceivedCardText
call PrintText
- ld de, wMysteryGiftTrainerData
+ ld de, wMysteryGiftTrainer
farcall Function8ac70
ld a, c
ld [wDeciramBuffer], a
--- a/engine/link/mystery_gift_2.asm
+++ b/engine/link/mystery_gift_2.asm
@@ -1,6 +1,6 @@
-PrepMysteryGiftDataToSend:
+StageDataForMysteryGift:
ld de, wMysteryGiftStaging
- ld a, $1 + GS_VERSION
+ ld a, GS_VERSION + 1
ld [de], a
inc de ; wMysteryGiftStaging+1
ld a, BANK(sGameData)
@@ -46,10 +46,10 @@
ld a, [sBackupMysteryGiftItem]
ld [de], a
inc de
- ld a, [sBackupMysteryGiftItem + 1]
+ ld a, [sNumDailyMysteryGiftPartnerIDs]
ld [de], a
- ld a, $14
- ld [wca00], a
+ ld a, wMysteryGiftPlayerDataEnd - wMysteryGiftPlayerData
+ ld [wUnusedMysteryGiftStagedDataLength], a
call CloseSRAM
ld hl, wMysteryGiftStaging
ld de, wMysteryGiftPlayerData
@@ -121,7 +121,7 @@
pop de
ret
-MysteryGiftGetItemHeldEffect:
+MysteryGiftGetItem:
ld a, c
cp MysteryGiftItems.End - MysteryGiftItems
jr nc, MysteryGiftFallbackItem
--- a/engine/menus/intro_menu.asm
+++ b/engine/menus/intro_menu.asm
@@ -173,12 +173,13 @@
ld [wRoamMon2MapNumber], a
ld [wRoamMon3MapNumber], a
- ld a, BANK(sMysteryGiftItem)
+ ld a, BANK(sMysteryGiftItem) ; aka BANK(sMysteryGiftUnlocked)
call OpenSRAM
ld hl, sMysteryGiftItem
xor a
ld [hli], a
- dec a
+ assert sMysteryGiftItem + 1 == sMysteryGiftUnlocked
+ dec a ; -1
ld [hl], a
call CloseSRAM
@@ -370,7 +371,7 @@
ld c, 20
call DelayFrames
farcall JumpRoamMons
- farcall MysteryGift_CopyReceivedDecosToPC
+ farcall CopyMysteryGiftReceivedDecorationsToPC
farcall ClockContinue
ld a, [wSpawnAfterChampion]
cp SPAWN_LANCE
--- a/engine/menus/main_menu.asm
+++ b/engine/menus/main_menu.asm
@@ -206,7 +206,7 @@
ld a, BANK(sNumDailyMysteryGiftPartnerIDs)
call OpenSRAM
ld a, [sNumDailyMysteryGiftPartnerIDs]
- cp -1
+ cp -1 ; locked?
call CloseSRAM
jr nz, .mystery_gift
; This check makes no difference.
--- a/engine/overworld/time.asm
+++ b/engine/overworld/time.asm
@@ -272,7 +272,7 @@
ld hl, wBuffer1
call InitOneDayCountdown
call CloseSRAM
- farcall Function1050c8
+ farcall ResetDailyMysteryGiftLimitIfUnlocked
.not_timed_out
ld a, BANK(sMysteryGiftTimer)
--- a/hram.asm
+++ b/hram.asm
@@ -88,8 +88,14 @@
hPrintNumBuffer:: ds 10
NEXTU
-; miscellaneous
- ds 9
+; Mystery Gift
+hMGExchangedByte:: db
+hMGExchangedWord:: dw
+hMGNumBits:: db
+hMGChecksum:: dw
+ ds 1
+hMGUnusedMsgLength:: db
+hMGRole:: db
hMGStatusFlags:: db
ENDU
--- a/sram.asm
+++ b/sram.asm
@@ -47,11 +47,12 @@
sMailbox9Backup:: mailmsg sMailbox9Backup
sMailbox10Backup:: mailmsg sMailbox10Backup
+sMysteryGiftData::
sMysteryGiftItem:: db
sMysteryGiftUnlocked:: db
sBackupMysteryGiftItem:: db
sNumDailyMysteryGiftPartnerIDs:: db
-sDailyMysteryGiftPartnerIDs:: ds 5 * 2 ; maximum 5 per day, 2 bytes per ID
+sDailyMysteryGiftPartnerIDs:: ds MAX_MYSTERY_GIFT_PARTNERS * 2
sMysteryGiftDecorationsReceived:: flag_array NUM_NON_TROPHY_DECOS
ds 4
sMysteryGiftTimer:: dw
@@ -58,8 +59,8 @@
ds 1
sMysteryGiftTrainerHouseFlag:: db
sMysteryGiftPartnerName:: ds NAME_LENGTH
- ds 1
-sMysteryGiftTrainer:: ds (1 + 1 + NUM_MOVES) * PARTY_LENGTH + 2
+sMysteryGiftUnusedFlag:: db
+sMysteryGiftTrainer:: ds wMysteryGiftTrainerEnd - wMysteryGiftTrainer
sBackupMysteryGiftItemEnd::
ds $30
--- a/wram.asm
+++ b/wram.asm
@@ -1000,29 +1000,11 @@
NEXTU
; mystery gift data
-UNION
-wMysteryGiftPartyTemp:: ds (1 + 1 + NUM_MOVES) * PARTY_LENGTH
-
-NEXTU
wMysteryGiftStaging:: ds 80
-NEXTU
- ds 7
-wc807:: ds 1
- ds 10
-wMobileSDK_PacketChecksum:: dw
- ds 4
-wMobileSDK_AdapterType:: db
- ds 5
-wMobileSDK_SendCommandID:: db
- ds 2
-wc821:: ds 1
-wc822:: ds 46
-ENDU
-
UNION
-wMysteryGiftTrainerData:: ds (1 + 1 + NUM_MOVES) * PARTY_LENGTH + 2
-wMysteryGiftTrainerDataEnd::
+wMysteryGiftTrainer:: ds 1 + (1 + 1 + NUM_MOVES) * PARTY_LENGTH + 1
+wMysteryGiftTrainerEnd::
NEXTU
wMysteryGiftCardHolderName:: ds PLAYER_NAME_LENGTH
@@ -1031,7 +1013,7 @@
ds 138
wMysteryGiftPartnerData::
-wc900:: db
+wMysteryGiftGameVersion:: db
wMysteryGiftPartnerID:: dw
wMysteryGiftPartnerName:: ds NAME_LENGTH
wMysteryGiftPartnerDexCaught:: db
@@ -1069,9 +1051,9 @@
NEXTU
; mystery gift data
-wca00:: db
-wca01:: db
-wca02:: db
+wUnusedMysteryGiftStagedDataLength:: db
+wMysteryGiftMessageCount:: db
+wMysteryGiftStagedDataLength:: db
NEXTU
; link data
@@ -1107,6 +1089,20 @@
wccb8:: ds 1
wccb9:: ds 1
wccba:: ds 102
+
+NEXTU
+; mobile
+ ds 7
+wc807:: ds 1
+ ds 10
+wMobileSDK_PacketChecksum:: dw
+ ds 4
+wMobileSDK_AdapterType:: db
+ ds 5
+wMobileSDK_SendCommandID:: db
+ ds 2
+wc821:: ds 1
+wc822:: ds 46
if DEF(_DEBUG)
NEXTU