summaryrefslogtreecommitdiff
path: root/src/engine/link/ir_functions.asm
blob: 140dccb28be482f55b0a7386d552f91f4db24f68 (plain)
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