1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
|
; hl = text ID
LoadLinkConnectingScene:
push hl
call SetSpriteAnimationsAsVBlankFunction
ld a, SCENE_GAMEBOY_LINK_CONNECTING
lb bc, 0, 0
call LoadScene
pop hl
call DrawWideTextBox_PrintText
call EnableLCD
ret
; shows Link Not Connected scene
; then asks the player whether they want to try again
; if the player selects "no", return carry
; input:
; - hl = text ID
LoadLinkNotConnectedSceneAndAskWhetherToTryAgain:
push hl
call RestoreVBlankFunction
call SetSpriteAnimationsAsVBlankFunction
ld a, SCENE_GAMEBOY_LINK_NOT_CONNECTED
lb bc, 0, 0
call LoadScene
pop hl
call DrawWideTextBox_WaitForInput
ldtx hl, WouldYouLikeToTryAgainText
call YesOrNoMenuWithText_SetCursorToYes
; fallthrough
ClearRPAndRestoreVBlankFunction:
push af
call ClearRP
call RestoreVBlankFunction
pop af
ret
; prepares IR communication parameter data
; a = a IRPARAM_* constant for the function of this connection
InitIRCommunications:
ld hl, wOwnIRCommunicationParams
ld [hl], a
inc hl
ld [hl], $50
inc hl
ld [hl], $4b
inc hl
ld [hl], $31
ld a, $ff
ld [wIRCommunicationErrorCode], a
ld a, PLAYER_TURN
ldh [hWhoseTurn], a
; clear wNameBuffer and wOpponentName
xor a
ld [wNameBuffer], a
ld hl, wOpponentName
ld [hli], a
ld [hl], a
; loads player's name from SRAM
; to wDefaultText
call EnableSRAM
ld hl, sPlayerName
ld de, wDefaultText
ld c, NAME_BUFFER_LENGTH
.loop
ld a, [hli]
ld [de], a
inc de
dec c
jr nz, .loop
call DisableSRAM
ret
; returns carry if communication was unsuccessful
; if a = 0, then it was a communication error
; if a = 1, then operation was cancelled by the player
PrepareSendCardOrDeckConfigurationThroughIR:
call InitIRCommunications
; pressing A button triggers request for IR communication
.loop_frame
call DoFrame
ldh a, [hKeysPressed]
bit B_BUTTON_F, a
jr nz, .b_btn
ldh a, [hKeysHeld]
bit A_BUTTON_F, a
jr z, .loop_frame
; a btn
call TrySendIRRequest
jr nc, .request_success
or a
jr z, .loop_frame
xor a
scf
ret
.b_btn
; cancelled by the player
ld a, $01
scf
ret
.request_success
call ExchangeIRCommunicationParameters
ret c
ld a, [wOtherIRCommunicationParams + 3]
cp $31
jr nz, SetIRCommunicationErrorCode_Error
or a
ret
; exchanges player names and IR communication parameters
; checks whether parameters for communication match
; and if they don't, an error is issued
ExchangeIRCommunicationParameters:
ld hl, wOwnIRCommunicationParams
ld de, wOtherIRCommunicationParams
ld c, 4
call RequestDataTransmissionThroughIR
jr c, .error
ld hl, wOtherIRCommunicationParams + 1
ld a, [hli]
cp $50
jr nz, .error
ld a, [hli]
cp $4b
jr nz, .error
ld a, [wOwnIRCommunicationParams]
ld hl, wOtherIRCommunicationParams
cp [hl] ; do parameters match?
jr nz, SetIRCommunicationErrorCode_Error
; receives wDefaultText from other device
; and writes it to wNameBuffer
ld hl, wDefaultText
ld de, wNameBuffer
ld c, NAME_BUFFER_LENGTH
call RequestDataTransmissionThroughIR
jr c, .error
; transmits wDefaultText to be
; written in wNameBuffer in the other device
ld hl, wDefaultText
ld de, wNameBuffer
ld c, NAME_BUFFER_LENGTH
call RequestDataReceivalThroughIR
jr c, .error
or a
ret
.error
xor a
scf
ret
SetIRCommunicationErrorCode_Error:
ld hl, wIRCommunicationErrorCode
ld [hl], $01
ld de, wIRCommunicationErrorCode
ld c, 1
call RequestDataReceivalThroughIR
call RequestCloseIRCommunication
ld a, $01
scf
ret
SetIRCommunicationErrorCode_NoError:
ld hl, wOwnIRCommunicationParams
ld [hl], $00
ld de, wIRCommunicationErrorCode
ld c, 1
call RequestDataReceivalThroughIR
ret c
call RequestCloseIRCommunication
or a
ret
; makes device receptive to receive data from other device
; to write in wDuelTempList (either list of cards or a deck configuration)
; returns carry if some error occurred
TryReceiveCardOrDeckConfigurationThroughIR:
call InitIRCommunications
.loop_receive_request
xor a
ld [wDuelTempList], a
call TryReceiveIRRequest
jr nc, .receive_data
bit 1, a
jr nz, .cancelled
jr .loop_receive_request
.receive_data
call ExecuteReceivedIRCommands
ld a, [wIRCommunicationErrorCode]
or a
ret z ; no error
xor a
scf
ret
.cancelled
ld a, $01
scf
ret
; returns carry if card(s) wasn't successfully sent
_SendCard:
call StopMusic
ldtx hl, SendingACardText
call LoadLinkConnectingScene
ld a, IRPARAM_SEND_CARDS
call PrepareSendCardOrDeckConfigurationThroughIR
jr c, .fail
; send cards
xor a
ld [wDuelTempList + DECK_SIZE], a
ld hl, wDuelTempList
ld e, l
ld d, h
ld c, DECK_SIZE + 1
call RequestDataReceivalThroughIR
jr c, .fail
call SetIRCommunicationErrorCode_NoError
jr c, .fail
call ExecuteReceivedIRCommands
jr c, .fail
ld a, [wOwnIRCommunicationParams + 1]
cp $4f
jr nz, .fail
call PlayCardPopSong
xor a
call ClearRPAndRestoreVBlankFunction
ret
.fail
call PlayCardPopSong
ldtx hl, CardTransferWasntSuccessful1Text
call LoadLinkNotConnectedSceneAndAskWhetherToTryAgain
jr nc, _SendCard ; loop back and try again
; failed
scf
ret
PlayCardPopSong:
ld a, MUSIC_CARD_POP
jp PlaySong
_ReceiveCard:
call StopMusic
ldtx hl, ReceivingACardText
call LoadLinkConnectingScene
ld a, IRPARAM_SEND_CARDS
call TryReceiveCardOrDeckConfigurationThroughIR
ld a, $4f
ld [wOwnIRCommunicationParams + 1], a
ld hl, wOwnIRCommunicationParams
ld e, l
ld d, h
ld c, 4
call RequestDataReceivalThroughIR
jr c, .fail
call RequestCloseIRCommunication
jr c, .fail
call PlayCardPopSong
or a
call ClearRPAndRestoreVBlankFunction
ret
.fail
call PlayCardPopSong
ldtx hl, CardTransferWasntSuccessful2Text
call LoadLinkNotConnectedSceneAndAskWhetherToTryAgain
jr nc, _ReceiveCard
scf
ret
_SendDeckConfiguration:
call StopMusic
ldtx hl, SendingADeckConfigurationText
call LoadLinkConnectingScene
ld a, IRPARAM_SEND_DECK
call PrepareSendCardOrDeckConfigurationThroughIR
jr c, .fail
ld hl, wDuelTempList
ld e, l
ld d, h
ld c, DECK_STRUCT_SIZE
call RequestDataReceivalThroughIR
jr c, .fail
call SetIRCommunicationErrorCode_NoError
jr c, .fail
call PlayCardPopSong
call ClearRPAndRestoreVBlankFunction
or a
ret
.fail
call PlayCardPopSong
ldtx hl, DeckConfigurationTransferWasntSuccessful1Text
call LoadLinkNotConnectedSceneAndAskWhetherToTryAgain
jr nc, _SendDeckConfiguration
scf
ret
_ReceiveDeckConfiguration:
call StopMusic
ldtx hl, ReceivingDeckConfigurationText
call LoadLinkConnectingScene
ld a, IRPARAM_SEND_DECK
call TryReceiveCardOrDeckConfigurationThroughIR
jr c, .fail
call PlayCardPopSong
call ClearRPAndRestoreVBlankFunction
or a
ret
.fail
call PlayCardPopSong
ldtx hl, DeckConfigurationTransferWasntSuccessful2Text
call LoadLinkNotConnectedSceneAndAskWhetherToTryAgain
jr nc, _ReceiveDeckConfiguration ; loop back and try again
scf
ret
|