pokecrystal-board/engine/link/mystery_gift.asm

1924 lines
35 KiB
NASM
Raw Normal View History

; hMGRole values
DEF IR_RECEIVER EQU 1
DEF IR_SENDER EQU 2
; hMGStatusFlags error bits
DEF MG_WRONG_CHECKSUM_F EQU 0
DEF MG_TIMED_OUT_F EQU 1
DEF MG_CANCELED_F EQU 4
DEF MG_WRONG_PREFIX_F EQU 7
; hMGStatusFlags values
DEF MG_WRONG_CHECKSUM EQU 1 << MG_WRONG_CHECKSUM_F
DEF MG_TIMED_OUT EQU 1 << MG_TIMED_OUT_F
DEF MG_CANCELED EQU 1 << MG_CANCELED_F
DEF MG_WRONG_PREFIX EQU 1 << MG_WRONG_PREFIX_F
DEF MG_NOT_OKAY EQU MG_WRONG_CHECKSUM | MG_TIMED_OUT | MG_CANCELED | MG_WRONG_PREFIX
DEF MG_OKAY EQU ~MG_NOT_OKAY
DEF MG_START_END EQU %11111111
DEF REGION_PREFIX EQU $96
DEF REGION_CODE EQU $90 ; USA
DEF MESSAGE_PREFIX EQU $5a
DEF NAME_CARD_PREFIX EQU $3c
2018-06-24 07:09:41 -07:00
DoMysteryGift:
call ClearTilemap
2015-11-22 21:21:21 -08:00
call ClearSprites
call WaitBGMap
2016-06-07 05:08:51 -07:00
call InitMysteryGiftLayout
2015-11-22 21:21:21 -08:00
hlcoord 3, 8
ld de, .String_PressAToLink_BToCancel
call PlaceString
call WaitBGMap
2015-12-14 17:06:41 -08:00
; Prepare the first of two messages for wMysteryGiftPartnerData
farcall StageDataForMysteryGift
call ClearMysteryGiftTrainer
vc_patch Infrared_stage_party_data
if DEF(_CRYSTAL11_VC)
farcall StagePartyDataForMysteryGift
call ClearMysteryGiftTrainer
nop
else
ld a, 2
ld [wMysteryGiftMessageCount], a
ld a, wMysteryGiftPartnerDataEnd - wMysteryGiftPartnerData
ld [wMysteryGiftStagedDataLength], a
endc
vc_patch_end
2015-12-14 17:06:41 -08:00
ldh a, [rIE]
push af
call ExchangeMysteryGiftData
vc_hook Infrared_ExchangeMysteryGiftData_end
2015-11-22 21:21:21 -08:00
ld d, a
xor a
ldh [rIF], a
2015-11-22 21:21:21 -08:00
pop af
ldh [rIE], a
2015-11-22 21:21:21 -08:00
push de
call ClearTilemap
2015-11-22 21:21:21 -08:00
call EnableLCD
call WaitBGMap
2016-06-06 15:23:00 -07:00
ld b, SCGB_DIPLOMA
2015-11-22 21:21:21 -08:00
call GetSGBLayout
call SetPalettes
pop de
2015-11-22 21:21:21 -08:00
hlcoord 2, 8
ld a, d
ld de, .MysteryGiftCanceledText ; Link has been canceled
cp MG_CANCELED
2015-11-22 21:21:21 -08:00
jp z, .LinkCanceled
cp MG_OKAY
2015-11-22 21:21:21 -08:00
jp nz, .CommunicationError
ld a, [wMysteryGiftGameVersion]
cp POKEMON_PIKACHU_2_VERSION
2015-11-22 21:21:21 -08:00
jr z, .skip_checks
call .CheckAlreadyGotFiveGiftsToday
ld hl, .MysteryGiftFiveADayText ; Only 5 gifts a day
2015-11-22 21:21:21 -08:00
jp nc, .PrintTextAndExit
call .CheckAlreadyGotAGiftFromThatPerson
ld hl, .MysteryGiftOneADayText ; Only one gift a day per person
2015-11-22 21:21:21 -08:00
jp c, .PrintTextAndExit
.skip_checks
2015-12-14 17:06:41 -08:00
ld a, [wMysteryGiftPlayerBackupItem]
2015-11-22 21:21:21 -08:00
and a
jp nz, .GiftWaiting
ld a, [wMysteryGiftPartnerBackupItem]
2015-11-22 21:21:21 -08:00
and a
jp nz, .FriendNotReady
ld a, [wMysteryGiftGameVersion]
cp POKEMON_PIKACHU_2_VERSION
2015-11-22 21:21:21 -08:00
jr z, .skip_append_save
call .AddMysteryGiftPartnerID
ld a, [wMysteryGiftGameVersion]
2020-11-17 08:09:02 -08:00
cp RESERVED_GAME_VERSION
2015-11-22 21:21:21 -08:00
jr z, .skip_append_save
call .SaveMysteryGiftTrainerName
2017-12-24 09:47:30 -08:00
farcall RestoreMobileEventIndex
farcall StubbedTrainerRankings_MysteryGift
2017-12-24 09:47:30 -08:00
farcall BackupMobileEventIndex
2015-11-22 21:21:21 -08:00
.skip_append_save
2015-12-14 17:06:41 -08:00
ld a, [wMysteryGiftPartnerSentDeco]
2015-11-22 21:21:21 -08:00
and a
jr z, .SentItem
; sent decoration
2015-12-14 17:06:41 -08:00
ld a, [wMysteryGiftPartnerWhichDeco]
2015-11-22 21:21:21 -08:00
ld c, a
2017-12-24 09:47:30 -08:00
farcall MysteryGiftGetDecoration
2015-11-22 21:21:21 -08:00
push bc
call CheckAndSetMysteryGiftDecorationAlreadyReceived
2015-11-22 21:21:21 -08:00
pop bc
jr nz, .SentItem
; keep the decoration if it wasn't already received
2017-12-24 09:47:30 -08:00
callfar GetDecorationName_c
2015-11-22 21:21:21 -08:00
ld h, d
ld l, e
2018-01-23 14:39:09 -08:00
ld de, wStringBuffer1
2015-11-22 21:21:21 -08:00
ld bc, ITEM_NAME_LENGTH
call CopyBytes
ld hl, .MysteryGiftSentHomeText ; sent decoration to home
2015-11-22 21:21:21 -08:00
jr .PrintTextAndExit
.SentItem:
2015-11-22 21:21:21 -08:00
call GetMysteryGiftBank
2015-12-14 17:06:41 -08:00
ld a, [wMysteryGiftPartnerWhichItem]
2015-11-22 21:21:21 -08:00
ld c, a
farcall MysteryGiftGetItem
2015-11-22 21:21:21 -08:00
ld a, c
ld [sBackupMysteryGiftItem], a
ld [wNamedObjectIndex], a
2015-11-22 21:21:21 -08:00
call CloseSRAM
call GetItemName
ld hl, .MysteryGiftSentText ; sent item/decoration
2015-11-22 21:21:21 -08:00
jr .PrintTextAndExit
2018-06-24 07:09:41 -07:00
.LinkCanceled:
ld hl, .MysteryGiftCanceledText ; Link has been canceled
2015-11-22 21:21:21 -08:00
jr .PrintTextAndExit
2018-06-24 07:09:41 -07:00
.CommunicationError:
ld hl, .MysteryGiftCommErrorText ; Communication error
2015-11-22 21:21:21 -08:00
call PrintText
jp DoMysteryGift
2018-06-24 07:09:41 -07:00
.GiftWaiting:
ld hl, .RetrieveMysteryGiftText ; receive gift at counter
2015-11-22 21:21:21 -08:00
jr .PrintTextAndExit
2018-06-24 07:09:41 -07:00
.FriendNotReady:
ld hl, .YourFriendIsNotReadyText ; friend not ready
; fallthrough
2015-11-22 21:21:21 -08:00
2018-06-24 07:09:41 -07:00
.PrintTextAndExit:
2015-11-22 21:21:21 -08:00
call PrintText
2017-12-29 10:22:33 -08:00
ld a, LCDC_DEFAULT
ldh [rLCDC], a
2015-11-22 21:21:21 -08:00
ret
2018-06-24 07:09:41 -07:00
.String_PressAToLink_BToCancel:
2015-11-22 21:21:21 -08:00
db "Press A to"
next "link IR-Device"
next "Press B to"
next "cancel it."
db "@"
.MysteryGiftCanceledText:
text_far _MysteryGiftCanceledText
text_end
2015-11-22 21:21:21 -08:00
.MysteryGiftCommErrorText:
text_far _MysteryGiftCommErrorText
text_end
2015-11-22 21:21:21 -08:00
.RetrieveMysteryGiftText:
text_far _RetrieveMysteryGiftText
text_end
2015-11-22 21:21:21 -08:00
.YourFriendIsNotReadyText:
text_far _YourFriendIsNotReadyText
text_end
2015-11-22 21:21:21 -08:00
.MysteryGiftFiveADayText:
text_far _MysteryGiftFiveADayText
text_end
2015-11-22 21:21:21 -08:00
.MysteryGiftOneADayText:
text_far _MysteryGiftOneADayText
text_end
2015-11-22 21:21:21 -08:00
.MysteryGiftSentText:
text_far _MysteryGiftSentText
text_end
2015-11-22 21:21:21 -08:00
.MysteryGiftSentHomeText:
text_far _MysteryGiftSentHomeText
text_end
2015-11-22 21:21:21 -08:00
2018-06-24 07:09:41 -07:00
.CheckAlreadyGotFiveGiftsToday:
2015-11-22 21:21:21 -08:00
call GetMysteryGiftBank
ld a, [sNumDailyMysteryGiftPartnerIDs]
cp MAX_MYSTERY_GIFT_PARTNERS
2015-11-22 21:21:21 -08:00
jp CloseSRAM
2018-06-24 07:09:41 -07:00
.CheckAlreadyGotAGiftFromThatPerson:
2015-11-22 21:21:21 -08:00
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:
2015-11-22 21:21:21 -08:00
scf
.No:
2015-11-22 21:21:21 -08:00
jp CloseSRAM
2018-06-24 07:09:41 -07:00
.AddMysteryGiftPartnerID:
2015-11-22 21:21:21 -08:00
call GetMysteryGiftBank
ld hl, sNumDailyMysteryGiftPartnerIDs
ld a, [hl]
inc [hl]
ld hl, sDailyMysteryGiftPartnerIDs ; could have done "inc hl" instead
2015-11-22 21:21:21 -08:00
ld e, a
ld d, 0
2015-11-22 21:21:21 -08:00
add hl, de
2015-12-26 18:59:03 -08:00
add hl, de
2015-11-22 21:21:21 -08:00
ld a, [wMysteryGiftPartnerID]
ld [hli], a
ld a, [wMysteryGiftPartnerID + 1]
ld [hl], a
jp CloseSRAM
2018-06-24 07:09:41 -07:00
.SaveMysteryGiftTrainerName:
2015-11-22 21:21:21 -08:00
call GetMysteryGiftBank
ld a, TRUE
2015-11-22 21:21:21 -08:00
ld [sMysteryGiftTrainerHouseFlag], a
ld hl, wMysteryGiftPartnerName
ld de, sMysteryGiftPartnerName
ld bc, NAME_LENGTH
call CopyBytes
assert sMysteryGiftPartnerName + NAME_LENGTH == sMysteryGiftUnusedFlag
ld a, TRUE
2015-11-22 21:21:21 -08:00
ld [de], a
inc de
assert sMysteryGiftUnusedFlag + 1 == sMysteryGiftTrainer
ld hl, wMysteryGiftTrainer
ld bc, wMysteryGiftTrainerEnd - wMysteryGiftTrainer
2015-11-22 21:21:21 -08:00
call CopyBytes
jp CloseSRAM
ExchangeMysteryGiftData:
vc_hook Infrared_ExchangeMysteryGiftData_start
vc_patch Infrared_ExchangeMysteryGiftData_function
if DEF(_CRYSTAL11_VC)
ld d, $ef
.loop
dec d
ld a, d
or a
jr nz, .loop
vc_hook Infrared_ExchangeMysteryGiftData_loop_done
nop
cp MG_CANCELED
.restart ; same location as unpatched .restart
ret z
nop
nop
cp MG_OKAY
jr nz, ExchangeMysteryGiftData
ret
else
2015-11-22 21:21:21 -08:00
di
2017-12-24 09:47:30 -08:00
farcall ClearChannels
call InitializeIRCommunicationInterrupts
2016-06-07 05:08:51 -07:00
.restart
call BeginIRCommunication
call InitializeIRCommunicationRoles
ldh a, [hMGStatusFlags]
endc
vc_patch_end
cp MG_CANCELED
jp z, EndOrContinueMysteryGiftIRCommunication
cp MG_OKAY
jr nz, .restart
ldh a, [hMGRole]
cp IR_SENDER
jr z, SenderExchangeMysteryGiftDataPayloads
; receiver
ld hl, hMGExchangedByte
ld b, 1
call TryReceivingIRDataBlock
jr nz, .failed
call ReceiveMysteryGiftDataPayload_GotRegionPrefix
jp nz, EndOrContinueMysteryGiftIRCommunication
jr ReceiverExchangeMysteryGiftDataPayloads_GotPayload
.failed
2016-06-07 05:08:51 -07:00
; Delay frame
.wait_frame
ldh a, [rLY]
2017-12-29 09:53:21 -08:00
cp LY_VBLANK
jr c, .wait_frame
ld c, LOW(rRP)
ld a, rRP_ENABLE_READ_MASK
2019-02-16 09:17:55 -08:00
ldh [c], a
2016-06-07 05:08:51 -07:00
ld b, 60 * 4 ; 4 seconds
.continue
push bc
call MysteryGift_UpdateJoypad
ld b, 1 << rRP_RECEIVING
ld c, LOW(rRP)
.in_vblank
2019-02-16 09:17:55 -08:00
ldh a, [c]
2015-11-22 21:21:21 -08:00
and b
ld b, a
ldh a, [rLY]
2017-12-29 09:53:21 -08:00
cp LY_VBLANK
jr nc, .in_vblank
.wait_vblank
2019-02-16 09:17:55 -08:00
ldh a, [c]
2015-11-22 21:21:21 -08:00
and b
ld b, a
ldh a, [rLY]
2017-12-29 09:53:21 -08:00
cp LY_VBLANK
jr c, .wait_vblank
2015-11-22 21:21:21 -08:00
ld a, b
pop bc
; Restart if the 4-second timeout has elapsed
2015-11-22 21:21:21 -08:00
dec b
jr z, .restart
; Restart if rRP is not receiving data
2015-11-22 21:21:21 -08:00
or a
jr nz, .restart
; Check if we've pressed the B button to cancel
ldh a, [hMGJoypadReleased]
2016-06-07 05:08:51 -07:00
bit B_BUTTON_F, a
jr z, .continue
ld a, MG_CANCELED
ldh [hMGStatusFlags], a
jp EndOrContinueMysteryGiftIRCommunication
ReceiverExchangeMysteryGiftDataPayloads:
; Receive the data payload
call ReceiveMysteryGiftDataPayload
jp nz, EndOrContinueMysteryGiftIRCommunication
; fallthrough
ReceiverExchangeMysteryGiftDataPayloads_GotPayload:
; Switch roles
call BeginSendingIRCommunication
jp nz, EndOrContinueMysteryGiftIRCommunication
; Send the data payload
call SendMysteryGiftDataPayload
jp nz, EndOrContinueMysteryGiftIRCommunication
; Switch roles
call BeginReceivingIRCommunication
jp nz, EndOrContinueMysteryGiftIRCommunication
; Receive an empty block
call ReceiveEmptyIRDataBlock
jp EndOrContinueMysteryGiftIRCommunication
SenderExchangeMysteryGiftDataPayloads:
; Send the data payload
call SendMysteryGiftDataPayload
jp nz, EndOrContinueMysteryGiftIRCommunication
; Switch roles
call BeginReceivingIRCommunication
jp nz, EndOrContinueMysteryGiftIRCommunication
; Receive the data payload
call ReceiveMysteryGiftDataPayload
jp nz, EndOrContinueMysteryGiftIRCommunication
; Switch roles
call BeginSendingIRCommunication
jp nz, EndOrContinueMysteryGiftIRCommunication
; Send an empty block
call SendEmptyIRDataBlock
jp EndOrContinueMysteryGiftIRCommunication
ReceiveMysteryGiftDataPayload:
; Receive the region prefix
ld hl, hMGExchangedByte
ld b, 1
call TryReceivingIRDataBlock
2015-11-22 21:21:21 -08:00
ret nz
; fallthrough
ReceiveMysteryGiftDataPayload_GotRegionPrefix:
; Receive an empty block
call ReceiveEmptyIRDataBlock
ldh a, [hMGStatusFlags]
cp MG_OKAY
2015-11-22 21:21:21 -08:00
ret nz
; 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
2015-11-22 21:21:21 -08:00
ret nz
; Send the region code
ld hl, hMGExchangedByte
ld b, 1
call TrySendingIRDataBlock
2015-11-22 21:21:21 -08:00
ret nz
; Send an empty block
call SendEmptyIRDataBlock
ldh a, [hMGStatusFlags]
cp MG_OKAY
2015-11-22 21:21:21 -08:00
ret nz
; Switch roles
call BeginReceivingIRCommunication
2015-11-22 21:21:21 -08:00
ret nz
; Receive the staged data
ld hl, wMysteryGiftTrainer
ld a, [wMysteryGiftStagedDataLength]
2015-11-22 21:21:21 -08:00
ld b, a
call TryReceivingIRDataBlock
2015-11-22 21:21:21 -08:00
ret nz
; Receive an empty block
call ReceiveEmptyIRDataBlock
ldh a, [hMGStatusFlags]
cp MG_OKAY
2015-11-22 21:21:21 -08:00
ret
SendMysteryGiftDataPayload:
; Send the region prefix
ld a, REGION_PREFIX
ldh [hMGExchangedByte], a
ld hl, hMGExchangedByte
ld b, 1
call TrySendingIRDataBlock
2015-11-22 21:21:21 -08:00
ret nz
; Send an empty block
call SendEmptyIRDataBlock
ldh a, [hMGStatusFlags]
cp MG_OKAY
2015-11-22 21:21:21 -08:00
ret nz
; Switch roles
call BeginReceivingIRCommunication
2015-11-22 21:21:21 -08:00
ret nz
; Receive the region code
ld hl, hMGExchangedByte
ld b, 1
call TryReceivingIRDataBlock
2015-11-22 21:21:21 -08:00
ret nz
; Receive an empty block
call ReceiveEmptyIRDataBlock
ldh a, [hMGStatusFlags]
cp MG_OKAY
2015-11-22 21:21:21 -08:00
ret nz
; Verify the received region code
ldh a, [hMGExchangedByte]
cp REGION_CODE
jp nz, WrongMysteryGiftRegion
; Switch roles
call BeginSendingIRCommunication
2015-11-22 21:21:21 -08:00
ret nz
; Send the staged data
ld hl, wMysteryGiftStaging
ld a, [wMysteryGiftStagedDataLength]
2015-11-22 21:21:21 -08:00
ld b, a
call TrySendingIRDataBlock
2015-11-22 21:21:21 -08:00
ret nz
; Send an empty block
call SendEmptyIRDataBlock
ldh a, [hMGStatusFlags]
cp MG_OKAY
2015-11-22 21:21:21 -08:00
ret
EndOrContinueMysteryGiftIRCommunication:
2015-11-22 21:21:21 -08:00
nop
ldh a, [hMGStatusFlags]
; Quit if player canceled
cp MG_CANCELED
2016-06-07 05:08:51 -07:00
jr z, .quit
; Quit if there was a communication error
cp MG_OKAY
2016-06-07 05:08:51 -07:00
jr nz, .quit
; Quit if all messages are sent/received
ld hl, wMysteryGiftMessageCount
2015-11-22 21:21:21 -08:00
dec [hl]
2016-06-07 05:08:51 -07:00
jr z, .quit
; Quit if communicating with Pokémon Pikachu 2 device
ld hl, wMysteryGiftTrainer
2015-12-14 17:06:41 -08:00
ld de, wMysteryGiftPartnerData
ld bc, wMysteryGiftPartnerDataEnd - wMysteryGiftPartnerData
2015-11-22 21:21:21 -08:00
call CopyBytes
ld a, [wMysteryGiftTrainer] ; first byte is the version
cp POKEMON_PIKACHU_2_VERSION
2016-06-07 05:08:51 -07:00
jr nc, .quit
; Prepare the second message for wMysteryGiftTrainer
2017-12-24 09:47:30 -08:00
farcall StagePartyDataForMysteryGift
call ClearMysteryGiftTrainer
ld a, wMysteryGiftTrainerEnd - wMysteryGiftTrainer
ld [wMysteryGiftStagedDataLength], a
ldh a, [hMGRole]
cp IR_SENDER
jr z, .sender
; receiver
call BeginReceivingIRCommunication
jr nz, EndOrContinueMysteryGiftIRCommunication
jp ReceiverExchangeMysteryGiftDataPayloads
.sender
call BeginSendingIRCommunication
jr nz, EndOrContinueMysteryGiftIRCommunication
jp SenderExchangeMysteryGiftDataPayloads
2016-06-07 05:08:51 -07:00
.quit
ldh a, [hMGStatusFlags]
2015-11-22 21:21:21 -08:00
push af
call EndIRCommunication
2015-11-22 21:21:21 -08:00
xor a
ldh [rIF], a
ldh a, [rIE]
2019-05-05 09:14:46 -07:00
or 1 << VBLANK
ldh [rIE], a
2015-11-22 21:21:21 -08:00
ei
call DelayFrame
pop af
ret
ExchangeNameCardData:
2015-11-22 21:21:21 -08:00
di
2017-12-24 09:47:30 -08:00
farcall ClearChannels
call InitializeIRCommunicationInterrupts
.restart
call BeginIRCommunication
call InitializeIRCommunicationRoles
ldh a, [hMGStatusFlags]
cp MG_CANCELED
jp z, EndNameCardIRCommunication
cp MG_OKAY
jr nz, .restart
ldh a, [hMGRole]
cp IR_SENDER
jr z, .sender
; receiver
; Receive the data payload
call ReceiveNameCardDataPayload
jp nz, EndNameCardIRCommunication
; Switch roles
call BeginSendingIRCommunication
jp nz, EndNameCardIRCommunication
; Send the data payload
call SendNameCardDataPayload
jp nz, EndNameCardIRCommunication
; Switch roles
call BeginReceivingIRCommunication
jp nz, EndNameCardIRCommunication
; Receive an empty block
call ReceiveEmptyIRDataBlock
jp EndNameCardIRCommunication
.sender
; Send the data payload
call SendNameCardDataPayload
jp nz, EndNameCardIRCommunication
; Switch roles
call BeginReceivingIRCommunication
jp nz, EndNameCardIRCommunication
; Receive the data payload
call ReceiveNameCardDataPayload
jp nz, EndNameCardIRCommunication
; Switch roles
call BeginSendingIRCommunication
jp nz, EndNameCardIRCommunication
; Send an empty block
call SendEmptyIRDataBlock
jp EndNameCardIRCommunication
2015-11-22 21:21:21 -08:00
ReceiveNameCardDataPayload:
; Receive the Name Card prefix
ld hl, hMGExchangedByte
ld b, 1
call TryReceivingIRDataBlock
2015-11-22 21:21:21 -08:00
ret nz
; Receive an empty block
call ReceiveEmptyIRDataBlock
ldh a, [hMGStatusFlags]
cp MG_OKAY
2015-11-22 21:21:21 -08:00
ret nz
; Verify the received Name Card prefix
ldh a, [hMGExchangedByte]
cp NAME_CARD_PREFIX
jp nz, WrongMysteryGiftRegion
2015-11-22 21:21:21 -08:00
swap a
ldh [hMGExchangedByte], a
; Switch roles
call BeginSendingIRCommunication
2015-11-22 21:21:21 -08:00
ret nz
; Send the swapped Name Card prefix
ld hl, hMGExchangedByte
ld b, 1
call TrySendingIRDataBlock
2015-11-22 21:21:21 -08:00
ret nz
; Send an empty block
call SendEmptyIRDataBlock
ldh a, [hMGStatusFlags]
cp MG_OKAY
2015-11-22 21:21:21 -08:00
ret nz
; Switch roles
call BeginReceivingIRCommunication
2015-11-22 21:21:21 -08:00
ret nz
; Receive the staged data
ld hl, wNameCardData
ld a, [wMysteryGiftStagedDataLength]
2015-11-22 21:21:21 -08:00
ld b, a
call TryReceivingIRDataBlock
2015-11-22 21:21:21 -08:00
ret nz
; Receive an empty block
call ReceiveEmptyIRDataBlock
ldh a, [hMGStatusFlags]
cp MG_OKAY
2015-11-22 21:21:21 -08:00
ret
SendNameCardDataPayload:
; Send the Name Card prefix
ld a, NAME_CARD_PREFIX
ldh [hMGExchangedByte], a
ld hl, hMGExchangedByte
ld b, 1
call TrySendingIRDataBlock
2015-11-22 21:21:21 -08:00
ret nz
; Send an empty block
call SendEmptyIRDataBlock
ldh a, [hMGStatusFlags]
cp MG_OKAY
2015-11-22 21:21:21 -08:00
ret nz
; Switch roles
call BeginReceivingIRCommunication
2015-11-22 21:21:21 -08:00
ret nz
; Receive the swapped Name Card prefix
ld hl, hMGExchangedByte
ld b, 1
call TryReceivingIRDataBlock
2015-11-22 21:21:21 -08:00
ret nz
; Receive an empty block
call ReceiveEmptyIRDataBlock
ldh a, [hMGStatusFlags]
cp MG_OKAY
2015-11-22 21:21:21 -08:00
ret nz
; Verify the received swapped Name Card prefix
ldh a, [hMGExchangedByte]
2015-11-22 21:21:21 -08:00
swap a
cp NAME_CARD_PREFIX
jp nz, WrongMysteryGiftRegion
; Switch roles
call BeginSendingIRCommunication
2015-11-22 21:21:21 -08:00
ret nz
; Send the staged data
ld hl, wMysteryGiftStaging
ld a, [wMysteryGiftStagedDataLength]
2015-11-22 21:21:21 -08:00
ld b, a
call TrySendingIRDataBlock
2015-11-22 21:21:21 -08:00
ret nz
; Send an empty block
call SendEmptyIRDataBlock
ldh a, [hMGStatusFlags]
cp MG_OKAY
2015-11-22 21:21:21 -08:00
ret
EndNameCardIRCommunication:
2015-11-22 21:21:21 -08:00
nop
ldh a, [hMGStatusFlags]
2015-11-22 21:21:21 -08:00
push af
call EndIRCommunication
2015-11-22 21:21:21 -08:00
xor a
ldh [rIF], a
ldh a, [rIE]
2019-05-05 09:14:46 -07:00
or 1 << VBLANK
ldh [rIE], a
2015-11-22 21:21:21 -08:00
ei
call DelayFrame
pop af
ret
WrongMysteryGiftRegion:
ld a, MG_WRONG_PREFIX
ldh [hMGStatusFlags], a
2015-11-22 21:21:21 -08:00
and a
ret
BeginSendingIRCommunication:
call BeginIRCommunication
call SendIRHelloMessage
ldh a, [hMGStatusFlags]
cp MG_OKAY
2015-11-22 21:21:21 -08:00
ret
BeginReceivingIRCommunication:
call BeginIRCommunication
call ReceiveIRHelloMessage
ldh a, [hMGStatusFlags]
cp MG_OKAY
2015-11-22 21:21:21 -08:00
ret
TrySendingIRDataBlock:
call SendIRDataBlock
ldh a, [hMGStatusFlags]
cp MG_OKAY
2015-11-22 21:21:21 -08:00
ret
TryReceivingIRDataBlock:
call ReceiveIRDataBlock
ldh a, [hMGStatusFlags]
cp MG_OKAY
2015-11-22 21:21:21 -08:00
ret
InitializeIRCommunicationInterrupts:
call StartFastIRTimer
2019-05-05 09:14:46 -07:00
ld a, 1 << TIMER
ldh [rIE], a
2015-11-22 21:21:21 -08:00
xor a
ldh [rIF], a
call BeginIRCommunication
; waits for ~$40400 cycles = ~0.25 seconds
2015-11-22 21:21:21 -08:00
xor a
ld b, a
2020-10-23 13:04:15 -07:00
.busy_wait
2015-11-22 21:21:21 -08:00
inc a
2020-10-23 13:04:15 -07:00
jr nz, .busy_wait
2015-11-22 21:21:21 -08:00
inc b
2020-10-23 13:04:15 -07:00
jr nz, .busy_wait
2015-11-22 21:21:21 -08:00
ret
StartFastIRTimer:
; Starts a 65,536 Hz timer that interrupts every 3 increments (21,845 Hz).
2015-11-22 21:21:21 -08:00
xor a
ldh [rTAC], a
ld a, -2
ldh [rTMA], a
ldh [rTIMA], a
ld a, rTAC_65536_HZ
ldh [rTAC], a
or 1 << rTAC_ON
ldh [rTAC], a
2015-11-22 21:21:21 -08:00
ret
StartSlowIRTimer:
; Starts a 65,536 Hz timer that interrupts every 256 increments (256 Hz).
2015-11-22 21:21:21 -08:00
xor a
ldh [rTAC], a
ldh [rTMA], a
ldh [rTIMA], a
ld a, rTAC_65536_HZ
ldh [rTAC], a
or 1 << rTAC_ON
ldh [rTAC], a
2015-11-22 21:21:21 -08:00
ret
BeginIRCommunication:
ld a, rRP_ENABLE_READ_MASK
call ToggleIRCommunication
ld a, IR_RECEIVER
ldh [hMGRole], a
2015-11-22 21:21:21 -08:00
ret
EndIRCommunication:
2015-11-22 21:21:21 -08:00
xor a
call ToggleIRCommunication
ld a, rTAC_65536_HZ
ldh [rTAC], a
2015-11-22 21:21:21 -08:00
ret
ReceiveInfraredLEDOn:
; Count interrupts of the partner's IR LED on; quit after 256-d interrupts.
.recv_loop
2015-11-22 21:21:21 -08:00
inc d
ret z
xor a
ldh [rIF], a
2015-11-22 21:21:21 -08:00
halt
2022-10-02 19:03:53 -07:00
nop
2019-02-16 09:17:55 -08:00
ldh a, [c]
bit rRP_RECEIVING, a
jr z, .recv_loop
2015-11-22 21:21:21 -08:00
or a
ret
ReceiveInfraredLEDOff:
; Count interrupts of the partner's IR LED off; quit after 256-d interrupts.
.no_recv_loop
2015-11-22 21:21:21 -08:00
inc d
ret z
xor a
ldh [rIF], a
2015-11-22 21:21:21 -08:00
halt
2022-10-02 19:03:53 -07:00
nop
2019-02-16 09:17:55 -08:00
ldh a, [c]
bit rRP_RECEIVING, a
jr nz, .no_recv_loop
2015-11-22 21:21:21 -08:00
or a
ret
SendInfraredLEDOn:
; Holds the IR LED on for d-1 interrupts.
ld a, rRP_ENABLE_READ_MASK | (1 << rRP_LED_ON)
2019-02-16 09:17:55 -08:00
ldh [c], a
.wait
2015-11-22 21:21:21 -08:00
dec d
ret z
xor a
ldh [rIF], a
2015-11-22 21:21:21 -08:00
halt
2022-10-02 19:03:53 -07:00
nop
jr .wait
2015-11-22 21:21:21 -08:00
SendInfraredLEDOff:
; Holds the IR LED off for d-1 interrupts.
ld a, rRP_ENABLE_READ_MASK
2019-02-16 09:17:55 -08:00
ldh [c], a
.wait
2015-11-22 21:21:21 -08:00
dec d
ret z
xor a
ldh [rIF], a
2015-11-22 21:21:21 -08:00
halt
2022-10-02 19:03:53 -07:00
nop
jr .wait
2015-11-22 21:21:21 -08:00
InitializeIRCommunicationRoles:
ld d, 0
2015-11-22 21:21:21 -08:00
ld e, d
ld a, IR_RECEIVER
ldh [hMGRole], a
2015-12-06 19:36:09 -08:00
.loop
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]
2016-06-07 05:08:51 -07:00
bit B_BUTTON_F, a
jr z, .not_canceled
ld a, MG_CANCELED
ldh [hMGStatusFlags], a
2015-11-22 21:21:21 -08:00
ret
2015-12-06 19:36:09 -08:00
.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
2019-02-16 09:17:55 -08:00
ldh a, [c]
2015-11-22 21:21:21 -08:00
and b
2015-12-06 19:36:09 -08:00
jr nz, .loop
; fallthrough
2015-11-22 21:21:21 -08:00
ReceiveIRHelloMessage:
ld c, LOW(rRP)
ld d, 0
2015-11-22 21:21:21 -08:00
ld e, d
call ReceiveInfraredLEDOff
jp z, InfraredLEDReceiveTimedOut
2015-11-22 21:21:21 -08:00
ld d, e
call ReceiveInfraredLEDOn
jp z, InfraredLEDReceiveTimedOut
call ReceiveInfraredLEDOff
jp z, InfraredLEDReceiveTimedOut
call ReceiveInfraredLEDOn
jp z, InfraredLEDReceiveTimedOut
ld a, MG_OKAY
ldh [hMGStatusFlags], a
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
2015-11-22 21:21:21 -08:00
ret
SendIRHelloMessageAfterDelay:
2016-06-07 05:08:51 -07:00
; Wait a random amount of time
2015-11-22 21:21:21 -08:00
call Random
ld e, a
and $f
ld d, a
.wait_loop
2015-11-22 21:21:21 -08:00
dec de
ld a, d
or e
jr nz, .wait_loop
; fallthrough
SendIRHelloMessage:
ld a, IR_SENDER
ldh [hMGRole], a
ld c, LOW(rRP)
ld d, 0
2015-11-22 21:21:21 -08:00
ld e, d
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
2015-11-22 21:21:21 -08:00
ld d, e
call ReceiveInfraredLEDOff
jp z, InfraredLEDReceiveTimedOut
2015-11-22 21:21:21 -08:00
ld d, e
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
2015-11-22 21:21:21 -08:00
ret
ToggleIRCommunication:
ldh [rRP], a
ld a, MG_START_END
ldh [hMGStatusFlags], a
2015-11-22 21:21:21 -08:00
ret
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.
2015-11-22 21:21:21 -08:00
xor a
ldh [hMGChecksum + 0], a
ldh [hMGChecksum + 1], a
2015-11-22 21:21:21 -08:00
push hl
push bc
ld c, LOW(rRP)
ld d, 61
call SendInfraredLEDOff
ld hl, hMGExchangedWord
ld a, MESSAGE_PREFIX
2015-11-22 21:21:21 -08:00
ld [hli], a
ld [hl], b
dec hl
ld b, 2
call SendIRDataMessage
2015-11-22 21:21:21 -08:00
pop bc
pop hl
call SendIRDataMessage
ldh a, [hMGChecksum + 0]
ldh [hMGExchangedWord + 0], a
ldh a, [hMGChecksum + 1]
ldh [hMGExchangedWord + 1], a
2015-11-22 21:21:21 -08:00
push hl
ld hl, hMGExchangedWord
ld b, 2
call SendIRDataMessage
2016-06-07 05:08:51 -07:00
ld hl, hMGStatusFlags
ld b, 1
call ReceiveIRDataMessage
ldh a, [hMGExchangedWord + 0]
ldh [hMGChecksum + 0], a
ldh a, [hMGExchangedWord + 1]
ldh [hMGChecksum + 1], a
2015-11-22 21:21:21 -08:00
pop hl
ret
SendIRDataMessage:
; Send b bytes of data one bit at a time, and update the checksum.
ld c, LOW(rRP)
ld d, 5
call SendInfraredLEDOff
ld d, 5
call SendInfraredLEDOn
ld d, 21
call SendInfraredLEDOff
; b = -b - 1; then count up to 0
2015-11-22 21:21:21 -08:00
ld a, b
cpl
ld b, a
ld a, -12
ldh [rTMA], a
.byte_loop
2015-11-22 21:21:21 -08:00
inc b
2020-10-23 13:04:15 -07:00
jr z, .done
ld a, 8
ldh [hMGNumBits], a
; Get the next data byte
2015-11-22 21:21:21 -08:00
ld a, [hli]
ld e, a
; Add the next data byte to the checksum
ldh a, [hMGChecksum + 0]
2015-11-22 21:21:21 -08:00
add e
ldh [hMGChecksum + 0], a
ldh a, [hMGChecksum + 1]
2018-02-04 10:16:40 -08:00
adc 0
ldh [hMGChecksum + 1], a
; Send each bit of the byte
.bit_loop
2015-11-22 21:21:21 -08:00
xor a
ldh [rIF], a
2015-11-22 21:21:21 -08:00
halt
2022-10-02 19:03:53 -07:00
nop
ld a, rRP_ENABLE_READ_MASK | (1 << rRP_LED_ON)
ldh [rRP], a
; Turn the LED off for longer if the bit is 1
ld d, 1
2015-11-22 21:21:21 -08:00
ld a, e
rlca
ld e, a
2020-10-23 13:04:15 -07:00
jr nc, .wait
2015-11-22 21:21:21 -08:00
inc d
2020-10-23 13:04:15 -07:00
.wait
ldh a, [rTIMA]
cp -8
2020-10-23 13:04:15 -07:00
jr c, .wait
ld a, rRP_ENABLE_READ_MASK
ldh [rRP], a
2015-11-22 21:21:21 -08:00
dec d
2020-10-23 13:04:15 -07:00
jr z, .no_halt
2015-11-22 21:21:21 -08:00
xor a
ldh [rIF], a
2015-11-22 21:21:21 -08:00
halt
2022-10-02 19:03:53 -07:00
nop
2020-10-23 13:04:15 -07:00
.no_halt
ldh a, [hMGNumBits]
2015-11-22 21:21:21 -08:00
dec a
jr z, .byte_loop
ldh [hMGNumBits], a
jr .bit_loop
2020-10-23 13:04:15 -07:00
.done
ld a, -2
ldh [rTMA], a
2015-11-22 21:21:21 -08:00
xor a
ldh [rIF], a
2015-11-22 21:21:21 -08:00
halt
2022-10-02 19:03:53 -07:00
nop
ld d, 5
call SendInfraredLEDOn
ld d, 17
call SendInfraredLEDOff
2015-11-22 21:21:21 -08:00
ret
InfraredLEDReceiveTimedOut:
ldh a, [hMGStatusFlags]
or MG_TIMED_OUT
ldh [hMGStatusFlags], a
2015-11-22 21:21:21 -08:00
ret
ReceivedWrongIRChecksum:
ldh a, [hMGStatusFlags]
or MG_WRONG_CHECKSUM
ldh [hMGStatusFlags], a
2015-11-22 21:21:21 -08:00
ret
ReceivedWrongIRMessagePrefix:
ldh a, [hMGStatusFlags]
or MG_WRONG_PREFIX
ldh [hMGStatusFlags], a
2015-11-22 21:21:21 -08:00
ret
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.
2015-11-22 21:21:21 -08:00
xor a
ldh [hMGChecksum + 0], a
ldh [hMGChecksum + 1], a
2015-11-22 21:21:21 -08:00
push bc
push hl
ld hl, hMGExchangedWord
ld b, 2
call ReceiveIRDataMessage
ldh a, [hMGExchangedWord + 1]
ldh [hMGUnusedMsgLength], a
2015-11-22 21:21:21 -08:00
ld b, a
pop hl
pop af
cp b
jp c, ReceivedWrongIRMessagePrefix
ldh a, [hMGExchangedWord + 0]
cp MESSAGE_PREFIX
jp nz, ReceivedWrongIRMessagePrefix
call ReceiveIRDataMessage
ldh a, [hMGChecksum + 0]
2015-11-22 21:21:21 -08:00
ld d, a
ldh a, [hMGChecksum + 1]
2015-11-22 21:21:21 -08:00
ld e, a
push hl
push de
ld hl, hMGExchangedWord
ld b, 2
call ReceiveIRDataMessage
2015-11-22 21:21:21 -08:00
pop de
ld hl, hMGExchangedWord
2015-11-22 21:21:21 -08:00
ld a, [hli]
xor d
ld b, a
ld a, [hl]
xor e
or b
call nz, ReceivedWrongIRChecksum
2015-11-22 21:21:21 -08:00
push de
ld d, 61
call SendInfraredLEDOff
2016-06-07 05:08:51 -07:00
ld hl, hMGStatusFlags
ld b, 1
call SendIRDataMessage
2015-11-22 21:21:21 -08:00
pop de
pop hl
ld a, d
ldh [hMGChecksum + 0], a
2015-11-22 21:21:21 -08:00
ld a, e
ldh [hMGChecksum + 1], a
2015-11-22 21:21:21 -08:00
ret
ReceiveIRDataMessage:
ld c, LOW(rRP)
ld d, 0
call ReceiveInfraredLEDOff
jp z, InfraredLEDReceiveTimedOut
ld d, 0
call ReceiveInfraredLEDOn
jp z, InfraredLEDReceiveTimedOut
ld d, 0
call ReceiveInfraredLEDOff
jp z, InfraredLEDReceiveTimedOut
2015-11-22 21:21:21 -08:00
ld a, b
cpl
ld b, a
xor a
2020-04-16 06:30:50 -07:00
ldh [hMGPrevTIMA], a
call StartSlowIRTimer
2020-10-23 13:04:15 -07:00
.main_loop
2015-11-22 21:21:21 -08:00
inc b
2020-10-23 13:04:15 -07:00
jr z, .done
ld a, 8
ldh [hMGNumBits], a
2020-10-23 13:04:15 -07:00
.inner_loop
ld d, 0
.recv_loop
2015-11-22 21:21:21 -08:00
inc d
jr z, .recv_done
2019-02-16 09:17:55 -08:00
ldh a, [c]
bit rRP_RECEIVING, a
jr z, .recv_loop
ld d, 0
.recv_done
.send_loop
2015-11-22 21:21:21 -08:00
inc d
jr z, .send_done
2019-02-16 09:17:55 -08:00
ldh a, [c]
bit rRP_RECEIVING, a
jr nz, .send_loop
.send_done
2020-04-16 06:30:50 -07:00
ldh a, [hMGPrevTIMA]
2015-11-22 21:21:21 -08:00
ld d, a
ldh a, [rTIMA]
2020-04-16 06:30:50 -07:00
ldh [hMGPrevTIMA], a
2015-11-22 21:21:21 -08:00
sub d
cp $12
2020-10-23 13:04:15 -07:00
jr c, .zero
2015-11-22 21:21:21 -08:00
set 0, e
2020-10-23 13:04:15 -07:00
jr .ok
.zero
2015-11-22 21:21:21 -08:00
res 0, e
2020-10-23 13:04:15 -07:00
.ok
ldh a, [hMGNumBits]
2015-11-22 21:21:21 -08:00
dec a
ldh [hMGNumBits], a
2020-10-23 13:04:15 -07:00
jr z, .continue
2015-11-22 21:21:21 -08:00
ld a, e
rlca
ld e, a
2020-10-23 13:04:15 -07:00
jr .inner_loop
.continue
2015-11-22 21:21:21 -08:00
ld a, e
ld [hli], a
ldh a, [hMGChecksum + 0]
2015-11-22 21:21:21 -08:00
add e
ldh [hMGChecksum + 0], a
ldh a, [hMGChecksum + 1]
2018-02-04 10:16:40 -08:00
adc 0
ldh [hMGChecksum + 1], a
2020-10-23 13:04:15 -07:00
jr .main_loop
.done
call StartFastIRTimer
2015-11-22 21:21:21 -08:00
xor a
ldh [rIF], a
ld d, 0
call ReceiveInfraredLEDOn
jp z, InfraredLEDReceiveTimedOut
ld d, 16
call SendInfraredLEDOff
2015-11-22 21:21:21 -08:00
ret
SendEmptyIRDataBlock:
ld b, 0
jp SendIRDataBlock
2015-11-22 21:21:21 -08:00
ReceiveEmptyIRDataBlock:
ld b, 0
jp ReceiveIRDataBlock
2015-11-22 21:21:21 -08:00
MysteryGift_UpdateJoypad:
2016-06-07 05:08:51 -07:00
; We can only get four inputs at a time.
; We take d-pad first for no particular reason.
ld a, R_DPAD
ldh [rJOYP], a
2016-06-07 05:08:51 -07:00
; Read twice to give the request time to take.
ldh a, [rJOYP]
ldh a, [rJOYP]
2016-06-07 05:08:51 -07:00
; The Joypad register output is in the lo nybble (inversed).
; We make the hi nybble of our new container d-pad input.
2015-11-22 21:21:21 -08:00
cpl
and $f
swap a
2016-06-07 05:08:51 -07:00
; We'll keep this in b for now.
2015-11-22 21:21:21 -08:00
ld b, a
2016-06-07 05:08:51 -07:00
; Buttons make 8 total inputs (A, B, Select, Start).
; We can fit this into one byte.
ld a, R_BUTTONS
ldh [rJOYP], a
2016-06-07 05:08:51 -07:00
; Wait for input to stabilize.
2015-11-22 21:21:21 -08:00
rept 6
ldh a, [rJOYP]
2015-11-22 21:21:21 -08:00
endr
2016-06-07 05:08:51 -07:00
; Buttons take the lo nybble.
2015-11-22 21:21:21 -08:00
cpl
and $f
or b
ld c, a
2016-06-07 05:08:51 -07:00
; To get the delta we xor the last frame's input with the new one.
ldh a, [hMGJoypadPressed]
2015-11-22 21:21:21 -08:00
xor c
2016-06-07 05:08:51 -07:00
; Released this frame:
2015-11-22 21:21:21 -08:00
and c
ldh [hMGJoypadReleased], a
2016-06-07 05:08:51 -07:00
; Pressed this frame:
2015-11-22 21:21:21 -08:00
ld a, c
ldh [hMGJoypadPressed], a
2015-11-22 21:21:21 -08:00
ld a, $30
2016-06-07 05:08:51 -07:00
; Reset the joypad register since we're done with it.
ldh [rJOYP], a
2015-11-22 21:21:21 -08:00
ret
CheckAndSetMysteryGiftDecorationAlreadyReceived:
; Return nz if decoration c was already received; otherwise receive it.
2015-11-22 21:21:21 -08:00
call GetMysteryGiftBank
ld d, 0
2015-11-22 21:21:21 -08:00
ld b, CHECK_FLAG
ld hl, sMysteryGiftDecorationsReceived
lda_predef SmallFarFlagAction
2015-11-22 21:21:21 -08:00
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
2015-11-22 21:21:21 -08:00
call CloseSRAM
xor a
ret
CopyMysteryGiftReceivedDecorationsToPC:
2015-11-22 21:21:21 -08:00
call GetMysteryGiftBank
ld c, 0
2015-11-22 21:21:21 -08:00
.loop
push bc
ld d, 0
2015-11-22 21:21:21 -08:00
ld b, CHECK_FLAG
ld hl, sMysteryGiftDecorationsReceived
predef SmallFarFlagAction
2015-11-22 21:21:21 -08:00
ld a, c
and a
pop bc
jr z, .skip
push bc
2017-12-24 09:47:30 -08:00
callfar SetSpecificDecorationFlag
2015-11-22 21:21:21 -08:00
pop bc
.skip
inc c
ld a, c
cp NUM_NON_TROPHY_DECOS
2015-11-22 21:21:21 -08:00
jr c, .loop
jp CloseSRAM
2018-06-24 07:09:41 -07:00
UnlockMysteryGift:
; If [sMysteryGiftUnlocked] was -1, this sets both
; [sMysteryGiftUnlocked] and [sMysteryGiftItem] to 0.
2015-11-22 21:21:21 -08:00
call GetMysteryGiftBank
ld hl, sMysteryGiftUnlocked
ld a, [hl]
inc a
jr nz, .ok
ld [hld], a
assert sMysteryGiftUnlocked - 1 == sMysteryGiftItem
2015-11-22 21:21:21 -08:00
ld [hl], a
.ok
jp CloseSRAM
ResetDailyMysteryGiftLimitIfUnlocked:
2015-11-22 21:21:21 -08:00
call GetMysteryGiftBank
ld a, [sNumDailyMysteryGiftPartnerIDs]
cp -1 ; locked?
jr z, .dont_clear
2015-11-22 21:21:21 -08:00
xor a
ld [sNumDailyMysteryGiftPartnerIDs], a
.dont_clear
2015-11-22 21:21:21 -08:00
jp CloseSRAM
2018-06-24 07:09:41 -07:00
BackupMysteryGift:
; Copies [sMysteryGiftItem] to [sBackupMysteryGiftItem],
; and [sMysteryGiftUnlocked] to [sNumDailyMysteryGiftPartnerIDs].
2015-11-22 21:21:21 -08:00
call GetMysteryGiftBank
ld hl, sMysteryGiftItem
ld de, sBackupMysteryGiftItem
ld a, [hli]
ld [de], a
inc de
assert sMysteryGiftItem + 1 == sMysteryGiftUnlocked
assert sBackupMysteryGiftItem + 1 == sNumDailyMysteryGiftPartnerIDs
2015-11-22 21:21:21 -08:00
ld a, [hl]
ld [de], a
jp CloseSRAM
2018-06-24 07:09:41 -07:00
RestoreMysteryGift:
; Copies [sBackupMysteryGiftItem] to [sMysteryGiftItem],
; and [sNumDailyMysteryGiftPartnerIDs] to [sMysteryGiftUnlocked].
2015-11-22 21:21:21 -08:00
call GetMysteryGiftBank
ld hl, sBackupMysteryGiftItem
ld de, sMysteryGiftItem
ld a, [hli]
ld [de], a
inc de
assert sBackupMysteryGiftItem + 1 == sNumDailyMysteryGiftPartnerIDs
assert sMysteryGiftItem + 1 == sMysteryGiftUnlocked
2015-11-22 21:21:21 -08:00
ld a, [hl]
ld [de], a
jp CloseSRAM
ClearMysteryGiftTrainer:
ld hl, wMysteryGiftTrainer
2015-11-22 21:21:21 -08:00
xor a
ld b, wMysteryGiftTrainerEnd - wMysteryGiftTrainer
2015-12-06 19:36:09 -08:00
.loop
2015-11-22 21:21:21 -08:00
ld [hli], a
dec b
2015-12-06 19:36:09 -08:00
jr nz, .loop
2015-11-22 21:21:21 -08:00
ret
2018-06-24 07:09:41 -07:00
GetMysteryGiftBank:
ld a, BANK(sMysteryGiftData)
jp OpenSRAM
2015-11-22 21:21:21 -08:00
2018-06-24 07:09:41 -07:00
StagePartyDataForMysteryGift:
2015-12-14 17:06:41 -08:00
; You will be sending this data to your mystery gift partner.
; Structure is the same as a trainer with species and moves
; defined.
2015-11-22 21:21:21 -08:00
ld a, BANK(sPokemonData)
call OpenSRAM
2015-12-14 17:06:41 -08:00
ld de, wMysteryGiftStaging
2018-01-23 14:39:09 -08:00
ld bc, sPokemonData + wPartyMons - wPokemonData
ld hl, sPokemonData + wPartySpecies - wPokemonData
2015-12-14 17:06:41 -08:00
.loop
2015-11-22 21:21:21 -08:00
ld a, [hli]
2015-12-14 17:06:41 -08:00
cp -1
jr z, .party_end
2015-11-22 21:21:21 -08:00
cp EGG
2015-12-14 17:06:41 -08:00
jr z, .next
2015-11-22 21:21:21 -08:00
push hl
2015-12-14 17:06:41 -08:00
; copy level
2015-11-22 21:21:21 -08:00
ld hl, MON_LEVEL
add hl, bc
ld a, [hl]
ld [de], a
inc de
2015-12-14 17:06:41 -08:00
; copy species
2015-11-22 21:21:21 -08:00
ld hl, MON_SPECIES
add hl, bc
ld a, [hl]
ld [de], a
inc de
2015-12-14 17:06:41 -08:00
; copy moves
2015-11-22 21:21:21 -08:00
ld hl, MON_MOVES
add hl, bc
push bc
ld bc, NUM_MOVES
call CopyBytes
pop bc
pop hl
2015-12-14 17:06:41 -08:00
.next
2015-11-22 21:21:21 -08:00
push hl
ld hl, PARTYMON_STRUCT_LENGTH
add hl, bc
ld b, h
ld c, l
pop hl
2015-12-14 17:06:41 -08:00
jr .loop
.party_end
ld a, -1
2015-11-22 21:21:21 -08:00
ld [de], a
ld a, wMysteryGiftTrainerEnd - wMysteryGiftTrainer
ld [wUnusedMysteryGiftStagedDataLength], a
2015-11-22 21:21:21 -08:00
jp CloseSRAM
2018-06-24 07:09:41 -07:00
InitMysteryGiftLayout:
2015-11-22 21:21:21 -08:00
call ClearBGPalettes
call DisableLCD
ld hl, MysteryGiftGFX
2017-12-28 04:32:33 -08:00
ld de, vTiles2 tile $00
2015-11-22 21:21:21 -08:00
ld a, BANK(MysteryGiftGFX)
ld bc, $43 tiles
2015-11-22 21:21:21 -08:00
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
2015-12-14 17:06:41 -08:00
call .Load5GFX
2015-11-22 21:21:21 -08:00
hlcoord 2, 2
ld a, $17
2015-12-14 17:06:41 -08:00
call .Load16GFX
2015-11-22 21:21:21 -08:00
hlcoord 2, 3
ld a, $27
2015-12-14 17:06:41 -08:00
call .Load16GFX
2015-11-22 21:21:21 -08:00
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
2015-12-14 17:06:41 -08:00
call .Load14Column
2015-11-22 21:21:21 -08:00
ld a, $9
hlcoord 18, 5
2015-12-14 17:06:41 -08:00
call .Load11Column
2015-11-22 21:21:21 -08:00
hlcoord 2, 5
ld a, $b
2015-12-14 17:06:41 -08:00
call .Load16Row
2015-11-22 21:21:21 -08:00
hlcoord 2, 16
ld a, $7
2015-12-14 17:06:41 -08:00
call .Load16Row
2015-11-22 21:21:21 -08:00
hlcoord 2, 5
ld a, $d
2015-12-14 17:06:41 -08:00
call .Load5GFX
2015-11-22 21:21:21 -08:00
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
2015-12-14 17:06:41 -08:00
call .Load16Row
2015-11-22 21:21:21 -08:00
hlcoord 2, 15
ld a, $40
2015-12-14 17:06:41 -08:00
call .Load16Row
2015-11-22 21:21:21 -08:00
hlcoord 2, 6
ld a, $3c
2015-12-14 17:06:41 -08:00
call .Load9Column
2015-11-22 21:21:21 -08:00
hlcoord 17, 6
ld a, $3e
2015-12-14 17:06:41 -08:00
call .Load9Column
2015-11-22 21:21:21 -08:00
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
2016-06-06 15:23:00 -07:00
ld b, SCGB_MYSTERY_GIFT
2015-11-22 21:21:21 -08:00
call GetSGBLayout
call SetPalettes
ret
2018-06-24 07:09:41 -07:00
.Load5GFX:
ld b, 5
2015-12-14 17:06:41 -08:00
jr .gfx_loop
2015-11-22 21:21:21 -08:00
.Load6GFX: ; unreferenced
ld b, 6
2015-12-14 17:06:41 -08:00
jr .gfx_loop
2015-11-22 21:21:21 -08:00
2018-06-24 07:09:41 -07:00
.Load16GFX:
2015-12-14 17:06:41 -08:00
ld b, 16
2015-11-22 21:21:21 -08:00
2018-06-24 07:09:41 -07:00
.gfx_loop
2015-11-22 21:21:21 -08:00
ld [hli], a
inc a
dec b
2015-12-14 17:06:41 -08:00
jr nz, .gfx_loop
2015-11-22 21:21:21 -08:00
ret
2018-06-24 07:09:41 -07:00
.Load9Column:
ld b, 9
2015-12-14 17:06:41 -08:00
jr .col_loop
2015-11-22 21:21:21 -08:00
2018-06-24 07:09:41 -07:00
.Load11Column:
2015-12-14 17:06:41 -08:00
ld b, 11
jr .col_loop
2015-11-22 21:21:21 -08:00
2018-06-24 07:09:41 -07:00
.Load14Column:
2015-12-14 17:06:41 -08:00
ld b, 14
2015-11-22 21:21:21 -08:00
2018-06-24 07:09:41 -07:00
.col_loop
2015-11-22 21:21:21 -08:00
ld [hl], a
2015-12-14 17:06:41 -08:00
ld de, SCREEN_WIDTH
2015-11-22 21:21:21 -08:00
add hl, de
dec b
2015-12-14 17:06:41 -08:00
jr nz, .col_loop
2015-11-22 21:21:21 -08:00
ret
2018-06-24 07:09:41 -07:00
.Load16Row:
2015-12-14 17:06:41 -08:00
ld b, 16
.row_loop
2015-11-22 21:21:21 -08:00
ld [hli], a
dec b
2015-12-14 17:06:41 -08:00
jr nz, .row_loop
2015-11-22 21:21:21 -08:00
ret
2018-06-24 07:09:41 -07:00
MysteryGiftGFX:
INCBIN "gfx/mystery_gift/mystery_gift.2bpp"
2015-11-22 21:21:21 -08:00
DoNameCardSwap:
call ClearTilemap
2015-11-22 21:21:21 -08:00
call ClearSprites
call WaitBGMap
call InitNameCardLayout
2015-11-22 21:21:21 -08:00
hlcoord 3, 8
ld de, .String_PressAToLink_BToCancel_JP
2015-11-22 21:21:21 -08:00
call PlaceString
call WaitBGMap
call StageDataForNameCard
call ClearMysteryGiftTrainer
ld a, wNameCardDataEnd - wNameCardData
ld [wMysteryGiftStagedDataLength], a
ldh a, [rIE]
2015-11-22 21:21:21 -08:00
push af
call ExchangeNameCardData
2015-11-22 21:21:21 -08:00
ld d, a
xor a
ldh [rIF], a
2015-11-22 21:21:21 -08:00
pop af
ldh [rIE], a
2015-11-22 21:21:21 -08:00
ld a, d
cp $10
jp z, .LinkCanceled
cp MG_OKAY
jp nz, .CommunicationError
call .SlideNameCardUpOffScreen
2015-11-22 21:21:21 -08:00
ld c, 60
call DelayFrames
call .ClearScreen
ld hl, .NameCardReceivedCardText
2015-11-22 21:21:21 -08:00
call PrintText
ld de, wNameCardData
2017-12-24 09:47:30 -08:00
farcall Function8ac70
2015-11-22 21:21:21 -08:00
ld a, c
ld [wTextDecimalByte], a
ld hl, .NameCardNotRegisteredCardText
jr c, .PrintTextAndExit
ld hl, .NameCardListedCardText
jr .PrintTextAndExit
2015-11-22 21:21:21 -08:00
.SlideNameCardUpOffScreen:
2018-01-10 10:47:57 -08:00
ld c, 16
.loop
ld hl, wShadowOAMSprite00YCoord
2018-01-10 10:47:57 -08:00
ld b, 8
.dec_y_loop
2015-11-22 21:21:21 -08:00
dec [hl]
2018-01-10 10:47:57 -08:00
rept SPRITEOAMSTRUCT_LENGTH
2015-11-22 21:21:21 -08:00
inc hl
endr
dec b
2018-01-10 10:47:57 -08:00
jr nz, .dec_y_loop
ld hl, wShadowOAMSprite08YCoord
2018-01-10 10:47:57 -08:00
ld b, 8
.inc_y_loop
2015-11-22 21:21:21 -08:00
inc [hl]
2018-01-10 10:47:57 -08:00
rept SPRITEOAMSTRUCT_LENGTH
2015-11-22 21:21:21 -08:00
inc hl
endr
dec b
2018-01-10 10:47:57 -08:00
jr nz, .inc_y_loop
2015-11-22 21:21:21 -08:00
dec c
ret z
push bc
ld c, 4
call DelayFrames
pop bc
2018-01-10 10:47:57 -08:00
jr .loop
2015-11-22 21:21:21 -08:00
.LinkCanceled:
call .ClearScreen
ld hl, .NameCardLinkCancelledText
jr .PrintTextAndExit
2015-11-22 21:21:21 -08:00
.CommunicationError:
call .ClearScreen
ld hl, .NameCardCommErrorText
2015-11-22 21:21:21 -08:00
call PrintText
jp DoNameCardSwap
2015-11-22 21:21:21 -08:00
.PrintTextAndExit:
2015-11-22 21:21:21 -08:00
call PrintText
2017-12-29 10:22:33 -08:00
ld a, LCDC_DEFAULT
ldh [rLCDC], a
2015-11-22 21:21:21 -08:00
ret
.String_PressAToLink_BToCancel_JP:
2018-03-02 16:39:16 -08:00
db "エーボタン<WO>おすと"
next "つうしん<PKMN>おこなわれるよ!"
2018-03-02 16:39:16 -08:00
next "ビーボタン<WO>おすと"
next "つうしん<WO>ちゅうし します"
2015-11-22 21:21:21 -08:00
db "@"
.NameCardReceivedCardText:
text_far _NameCardReceivedCardText
text_end
2015-11-22 21:21:21 -08:00
.NameCardListedCardText:
text_far _NameCardListedCardText
text_end
2015-11-22 21:21:21 -08:00
.NameCardNotRegisteredCardText:
text_far _NameCardNotRegisteredCardText
text_end
2015-11-22 21:21:21 -08:00
.NameCardLinkCancelledText:
text_far _NameCardLinkCancelledText
text_end
2015-11-22 21:21:21 -08:00
.NameCardCommErrorText:
text_far _NameCardLinkCommErrorText
text_end
2015-11-22 21:21:21 -08:00
.ClearScreen:
2015-11-22 21:21:21 -08:00
call ClearSprites
call ClearTilemap
2015-11-22 21:21:21 -08:00
call EnableLCD
call WaitBGMap
2016-06-06 15:23:00 -07:00
ld b, SCGB_DIPLOMA
2015-11-22 21:21:21 -08:00
call GetSGBLayout
call SetPalettes
ret
StageDataForNameCard:
ld de, wMysteryGiftStaging
2015-11-22 21:21:21 -08:00
ld a, BANK(sPlayerData)
call OpenSRAM
2018-01-23 14:39:09 -08:00
ld hl, sPlayerData + wPlayerName - wPlayerData
2015-11-22 21:21:21 -08:00
ld bc, NAME_LENGTH
call CopyBytes
2018-01-23 14:39:09 -08:00
ld hl, sPlayerData + wPlayerID - wPlayerData
2015-11-22 21:21:21 -08:00
ld bc, 2
call CopyBytes
ld hl, sPlayerData + wSecretID - wPlayerData
ld bc, 2
call CopyBytes
call CloseSRAM
ld a, BANK(sCrystalData)
call OpenSRAM
2015-11-22 21:21:21 -08:00
ld a, [sCrystalData + 0]
ld [de], a
inc de
ld a, BANK(s4_a603) ; aka BANK(s4_a007) ; MBC30 bank used by JP Crystal; inaccessible by MBC3
call OpenSRAM
ld hl, s4_a603 ; address of MBC30 bank
ld bc, 8
2015-11-22 21:21:21 -08:00
call CopyBytes
ld hl, s4_a007 ; address of MBC30 bank
ld bc, 12
2015-11-22 21:21:21 -08:00
call CopyBytes
call CloseSRAM
ret
InitNameCardLayout:
2015-11-22 21:21:21 -08:00
call ClearBGPalettes
call DisableLCD
ld hl, CardTradeGFX
2017-12-28 04:32:33 -08:00
ld de, vTiles2 tile $00
ld a, BANK(CardTradeGFX)
ld bc, $40 tiles
2015-11-22 21:21:21 -08:00
call FarCopyBytes
ld hl, CardTradeSpriteGFX
2017-12-28 04:32:33 -08:00
ld de, vTiles0 tile $00
ld a, BANK(CardTradeSpriteGFX)
ld bc, 8 tiles
2015-11-22 21:21:21 -08:00
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
2015-12-14 17:06:41 -08:00
call .Load11Row
2015-11-22 21:21:21 -08:00
hlcoord 4, 3
ld a, $1e
2015-12-14 17:06:41 -08:00
call .Load12Row
2015-11-22 21:21:21 -08:00
hlcoord 4, 4
ld a, $2a
2015-12-14 17:06:41 -08:00
call .Load12Row
2015-11-22 21:21:21 -08:00
hlcoord 1, 2
ld [hl], $4
hlcoord 1, 3
ld a, $5
2015-12-14 17:06:41 -08:00
call .Load14Column
2015-11-22 21:21:21 -08:00
ld a, $9
hlcoord 18, 5
2015-12-14 17:06:41 -08:00
call .Load11Column
2015-11-22 21:21:21 -08:00
hlcoord 2, 5
ld a, $b
2015-12-14 17:06:41 -08:00
call .Load16Row
2015-11-22 21:21:21 -08:00
hlcoord 2, 16
ld a, $7
2015-12-14 17:06:41 -08:00
call .Load16Row
2015-11-22 21:21:21 -08:00
hlcoord 2, 5
ld a, $d
2015-12-14 17:06:41 -08:00
call .Load6Row
2015-11-22 21:21:21 -08:00
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
2015-12-14 17:06:41 -08:00
call .Load16Row
2015-11-22 21:21:21 -08:00
hlcoord 2, 15
ld a, $3d
2015-12-14 17:06:41 -08:00
call .Load16Row
2015-11-22 21:21:21 -08:00
hlcoord 2, 6
ld a, $39
2015-12-14 17:06:41 -08:00
call .Load9Column
2015-11-22 21:21:21 -08:00
hlcoord 17, 6
ld a, $3b
2015-12-14 17:06:41 -08:00
call .Load9Column
2015-11-22 21:21:21 -08:00
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, wShadowOAMSprite00
ld hl, .NameCardOAMData
2018-01-10 10:47:57 -08:00
ld bc, 16 * SPRITEOAMSTRUCT_LENGTH
2015-11-22 21:21:21 -08:00
call CopyBytes
call EnableLCD
call WaitBGMap
ld b, CRYSTAL_CGB_NAME_CARD
farcall GetCrystalCGBLayout
2015-11-22 21:21:21 -08:00
jp SetPalettes
2018-06-24 07:09:41 -07:00
.Load6Row:
2015-12-14 17:06:41 -08:00
ld b, 6
jr .row_loop
2015-11-22 21:21:21 -08:00
2018-06-24 07:09:41 -07:00
.Load11Row:
2015-12-14 17:06:41 -08:00
ld b, 11
jr .row_loop
2015-11-22 21:21:21 -08:00
2018-06-24 07:09:41 -07:00
.Load12Row:
2015-12-14 17:06:41 -08:00
ld b, 12
2015-11-22 21:21:21 -08:00
2018-06-24 07:09:41 -07:00
.row_loop
2015-11-22 21:21:21 -08:00
ld [hli], a
inc a
dec b
2015-12-14 17:06:41 -08:00
jr nz, .row_loop
2015-11-22 21:21:21 -08:00
ret
2018-06-24 07:09:41 -07:00
.Load9Column:
2015-12-14 17:06:41 -08:00
ld b, 9
jr .column_loop
2015-11-22 21:21:21 -08:00
2018-06-24 07:09:41 -07:00
.Load11Column:
2015-12-14 17:06:41 -08:00
ld b, 11
jr .column_loop
2015-11-22 21:21:21 -08:00
2018-06-24 07:09:41 -07:00
.Load14Column:
2015-12-14 17:06:41 -08:00
ld b, 14
2015-11-22 21:21:21 -08:00
2018-06-24 07:09:41 -07:00
.column_loop
2015-11-22 21:21:21 -08:00
ld [hl], a
ld de, SCREEN_WIDTH
add hl, de
dec b
2015-12-14 17:06:41 -08:00
jr nz, .column_loop
2015-11-22 21:21:21 -08:00
ret
2018-06-24 07:09:41 -07:00
.Load16Row:
2015-12-14 17:06:41 -08:00
ld b, 16
.row_loop_no_inc
2015-11-22 21:21:21 -08:00
ld [hli], a
dec b
2015-12-14 17:06:41 -08:00
jr nz, .row_loop_no_inc
2015-11-22 21:21:21 -08:00
ret
.NameCardOAMData:
dbsprite 6, 2, 4, 1, $00, 0
dbsprite 7, 2, 4, 1, $01, 0
dbsprite 8, 2, 4, 1, $02, 0
dbsprite 9, 2, 4, 1, $03, 0
dbsprite 6, 3, 4, 1, $04, 0
dbsprite 7, 3, 4, 1, $05, 0
dbsprite 8, 3, 4, 1, $06, 0
dbsprite 9, 3, 4, 1, $07, 0
dbsprite 11, 0, 4, 1, $00, 0
dbsprite 12, 0, 4, 1, $01, 0
dbsprite 13, 0, 4, 1, $02, 0
dbsprite 14, 0, 4, 1, $03, 0
dbsprite 11, 1, 4, 1, $04, 0
dbsprite 12, 1, 4, 1, $05, 0
dbsprite 13, 1, 4, 1, $06, 0
dbsprite 14, 1, 4, 1, $07, 0
2015-11-22 21:21:21 -08:00
CardTradeGFX:
INCBIN "gfx/mystery_gift/card_trade.2bpp"
CardTradeSpriteGFX:
INCBIN "gfx/mystery_gift/card_sprite.2bpp"