pokecrystal/home/serial.asm

410 lines
6.9 KiB
NASM
Raw Normal View History

2018-06-24 14:09:41 +00:00
Serial::
; The serial interrupt.
push af
push bc
push de
push hl
ldh a, [hMobileReceive]
and a
2015-12-15 23:59:49 +00:00
jr nz, .mobile
2016-05-11 21:16:03 +00:00
ld a, [wPrinterConnectionOpen]
bit 0, a
2015-12-15 23:59:49 +00:00
jr nz, .printer
ldh a, [hSerialConnectionStatus]
inc a ; is it equal to CONNECTION_NOT_ESTABLISHED?
jr z, .establish_connection
ldh a, [rSB]
ldh [hSerialReceive], a
ldh a, [hSerialSend]
ldh [rSB], a
ldh a, [hSerialConnectionStatus]
cp USING_INTERNAL_CLOCK
2015-12-15 23:59:49 +00:00
jr z, .player2
2019-05-05 16:14:46 +00:00
ld a, (0 << rSC_ON) | (0 << rSC_CLOCK)
ldh [rSC], a
2019-05-05 16:14:46 +00:00
ld a, (1 << rSC_ON) | (0 << rSC_CLOCK)
ldh [rSC], a
2015-12-15 23:59:49 +00:00
jr .player2
2015-12-15 23:59:49 +00:00
.mobile
call MobileReceive
jr .end
2015-12-15 23:59:49 +00:00
.printer
call PrinterReceive
jr .end
.establish_connection
ldh a, [rSB]
cp USING_EXTERNAL_CLOCK
2015-12-15 23:59:49 +00:00
jr z, .player1
cp USING_INTERNAL_CLOCK
2015-12-15 23:59:49 +00:00
jr nz, .player2
2015-12-15 23:59:49 +00:00
.player1
ldh [hSerialReceive], a
ldh [hSerialConnectionStatus], a
cp USING_INTERNAL_CLOCK
2015-12-15 23:59:49 +00:00
jr z, ._player2
xor a
ldh [rSB], a
ld a, 3
ldh [rDIV], a
.delay_loop
ldh a, [rDIV]
bit 7, a
jr nz, .delay_loop
2019-05-05 16:14:46 +00:00
ld a, (0 << rSC_ON) | (0 << rSC_CLOCK)
ldh [rSC], a
2019-05-05 16:14:46 +00:00
ld a, (1 << rSC_ON) | (0 << rSC_CLOCK)
ldh [rSC], a
2015-12-15 23:59:49 +00:00
jr .player2
2015-12-15 23:59:49 +00:00
._player2
xor a
ldh [rSB], a
2015-12-15 23:59:49 +00:00
.player2
ld a, TRUE
ldh [hSerialReceivedNewData], a
ld a, SERIAL_NO_DATA_BYTE
ldh [hSerialSend], a
2015-12-15 23:59:49 +00:00
.end
pop hl
pop de
pop bc
pop af
reti
2018-06-24 14:09:41 +00:00
Serial_ExchangeBytes::
; send bc bytes from hl, receive bc bytes to de
ld a, TRUE
ldh [hSerialIgnoringInitialData], a
.loop
ld a, [hl]
ldh [hSerialSend], a
call Serial_ExchangeByte
push bc
ld b, a
inc hl
ld a, 48
.wait
dec a
jr nz, .wait
ldh a, [hSerialIgnoringInitialData]
and a
ld a, b
pop bc
jr z, .load
dec hl
cp SERIAL_PREAMBLE_BYTE
jr nz, .loop
xor a
ldh [hSerialIgnoringInitialData], a
jr .loop
.load
ld [de], a
inc de
dec bc
ld a, b
or c
jr nz, .loop
ret
2018-06-24 14:09:41 +00:00
Serial_ExchangeByte::
.timeout_loop
xor a
ldh [hSerialReceivedNewData], a
ldh a, [hSerialConnectionStatus]
cp USING_INTERNAL_CLOCK
jr nz, .not_player_2
2019-05-05 16:14:46 +00:00
ld a, (0 << rSC_ON) | (1 << rSC_CLOCK)
ldh [rSC], a
2019-05-05 16:14:46 +00:00
ld a, (1 << rSC_ON) | (1 << rSC_CLOCK)
ldh [rSC], a
.not_player_2
.loop
ldh a, [hSerialReceivedNewData]
and a
jr nz, .await_new_data
ldh a, [hSerialConnectionStatus]
cp USING_EXTERNAL_CLOCK
jr nz, .not_player_1_or_timed_out
call CheckLinkTimeoutFramesNonzero
jr z, .not_player_1_or_timed_out
call .ShortDelay
push hl
2016-05-16 01:50:31 +00:00
ld hl, wLinkTimeoutFrames + 1
inc [hl]
jr nz, .no_rollover_up
dec hl
inc [hl]
.no_rollover_up
pop hl
call CheckLinkTimeoutFramesNonzero
jr nz, .loop
jp SerialDisconnected
.not_player_1_or_timed_out
ldh a, [rIE]
and (1 << SERIAL) | (1 << TIMER) | (1 << LCD_STAT) | (1 << VBLANK)
cp 1 << SERIAL
jr nz, .loop
ld a, [wLinkByteTimeout]
dec a
ld [wLinkByteTimeout], a
jr nz, .loop
ld a, [wLinkByteTimeout + 1]
dec a
ld [wLinkByteTimeout + 1], a
jr nz, .loop
ldh a, [hSerialConnectionStatus]
cp USING_EXTERNAL_CLOCK
jr z, .await_new_data
2016-05-16 01:50:31 +00:00
ld a, 255
.long_delay_loop
dec a
jr nz, .long_delay_loop
.await_new_data
xor a
ldh [hSerialReceivedNewData], a
ldh a, [rIE]
and (1 << SERIAL) | (1 << TIMER) | (1 << LCD_STAT) | (1 << VBLANK)
sub 1 << SERIAL
jr nz, .non_serial_interrupts_enabled
2016-05-16 01:50:31 +00:00
2020-10-29 20:43:28 +00:00
; a == 0
assert LOW(SERIAL_LINK_BYTE_TIMEOUT) == 0
ld [wLinkByteTimeout], a
2020-10-29 20:43:28 +00:00
ld a, HIGH(SERIAL_LINK_BYTE_TIMEOUT)
ld [wLinkByteTimeout + 1], a
.non_serial_interrupts_enabled
ldh a, [hSerialReceive]
cp SERIAL_NO_DATA_BYTE
ret nz
call CheckLinkTimeoutFramesNonzero
jr z, .timed_out
push hl
2016-05-16 01:50:31 +00:00
ld hl, wLinkTimeoutFrames + 1
ld a, [hl]
dec a
ld [hld], a
inc a
jr nz, .no_rollover
dec [hl]
.no_rollover
pop hl
call CheckLinkTimeoutFramesNonzero
jr z, SerialDisconnected
.timed_out
ldh a, [rIE]
and (1 << SERIAL) | (1 << TIMER) | (1 << LCD_STAT) | (1 << VBLANK)
cp 1 << SERIAL
ld a, SERIAL_NO_DATA_BYTE
ret z
ld a, [hl]
ldh [hSerialSend], a
call DelayFrame
jp .timeout_loop
.ShortDelay:
ld a, 15
.short_delay_loop
dec a
jr nz, .short_delay_loop
ret
CheckLinkTimeoutFramesNonzero::
push hl
2016-05-16 01:50:31 +00:00
ld hl, wLinkTimeoutFrames
ld a, [hli]
or [hl]
pop hl
ret
; This sets wLinkTimeoutFrames to $ffff, since
; a is always 0 when it is called.
2018-06-24 14:09:41 +00:00
SerialDisconnected::
dec a
2016-05-16 01:50:31 +00:00
ld [wLinkTimeoutFrames], a
ld [wLinkTimeoutFrames + 1], a
ret
; This is used to exchange the button press and selected menu item on the link menu.
; The data is sent thrice and read twice to increase reliability.
2018-06-24 14:09:41 +00:00
Serial_ExchangeLinkMenuSelection::
2015-11-23 21:04:53 +00:00
ld hl, wPlayerLinkAction
ld de, wOtherPlayerLinkMode
ld c, 2
ld a, TRUE
ldh [hSerialIgnoringInitialData], a
2020-10-05 15:24:47 +00:00
.exchange
call DelayFrame
ld a, [hl]
ldh [hSerialSend], a
call Serial_ExchangeByte
ld b, a
inc hl
ldh a, [hSerialIgnoringInitialData]
and a
ld a, FALSE
ldh [hSerialIgnoringInitialData], a
2020-10-05 15:24:47 +00:00
jr nz, .exchange
ld a, b
ld [de], a
inc de
dec c
2020-10-05 15:24:47 +00:00
jr nz, .exchange
ret
2018-06-24 14:09:41 +00:00
Serial_PrintWaitingTextAndSyncAndExchangeNybble::
call LoadTilemapToTempTilemap
2017-12-24 17:47:30 +00:00
callfar PlaceWaitingText
2016-05-16 01:50:31 +00:00
call WaitLinkTransfer
jp SafeLoadTempTilemapToTilemap
Serial_SyncAndExchangeNybble:: ; unreferenced
call LoadTilemapToTempTilemap
2017-12-24 17:47:30 +00:00
callfar PlaceWaitingText
jp WaitLinkTransfer ; pointless
2018-06-24 14:09:41 +00:00
WaitLinkTransfer::
ld a, $ff
2015-11-23 21:04:53 +00:00
ld [wOtherPlayerLinkAction], a
.loop
call LinkTransfer
call DelayFrame
call CheckLinkTimeoutFramesNonzero
2015-11-23 21:04:53 +00:00
jr z, .check
push hl
2016-05-16 01:50:31 +00:00
ld hl, wLinkTimeoutFrames + 1
dec [hl]
2015-11-23 21:04:53 +00:00
jr nz, .skip
dec hl
dec [hl]
2015-11-23 21:04:53 +00:00
jr nz, .skip
; We might be disconnected
pop hl
xor a
jp SerialDisconnected
2015-11-23 21:04:53 +00:00
.skip
pop hl
2015-11-23 21:04:53 +00:00
.check
ld a, [wOtherPlayerLinkAction]
inc a
2015-11-23 21:04:53 +00:00
jr z, .loop
ld b, 10
.receive
call DelayFrame
call LinkTransfer
dec b
2015-11-23 21:04:53 +00:00
jr nz, .receive
ld b, 10
.acknowledge
call DelayFrame
call LinkDataReceived
dec b
2015-11-23 21:04:53 +00:00
jr nz, .acknowledge
ld a, [wOtherPlayerLinkAction]
ld [wOtherPlayerLinkMode], a
ret
2018-06-24 14:09:41 +00:00
LinkTransfer::
push bc
2015-11-23 21:04:53 +00:00
ld b, SERIAL_TIMECAPSULE
ld a, [wLinkMode]
2015-11-23 21:04:53 +00:00
cp LINK_TIMECAPSULE
jr z, .got_high_nybble
ld b, SERIAL_TIMECAPSULE
jr c, .got_high_nybble
cp LINK_TRADECENTER
ld b, SERIAL_TRADECENTER
jr z, .got_high_nybble
ld b, SERIAL_BATTLE
.got_high_nybble
call .Receive
ld a, [wPlayerLinkAction]
add b
ldh [hSerialSend], a
ldh a, [hSerialConnectionStatus]
cp USING_INTERNAL_CLOCK
2015-11-23 21:04:53 +00:00
jr nz, .player_1
2019-05-05 16:14:46 +00:00
ld a, (0 << rSC_ON) | (1 << rSC_CLOCK)
ldh [rSC], a
2019-05-05 16:14:46 +00:00
ld a, (1 << rSC_ON) | (1 << rSC_CLOCK)
ldh [rSC], a
2015-11-23 21:04:53 +00:00
.player_1
call .Receive
pop bc
ret
2018-06-24 14:09:41 +00:00
.Receive:
ldh a, [hSerialReceive]
2015-11-23 21:04:53 +00:00
ld [wOtherPlayerLinkMode], a
and $f0
cp b
ret nz
xor a
ldh [hSerialReceive], a
2015-11-23 21:04:53 +00:00
ld a, [wOtherPlayerLinkMode]
and $f
2015-11-23 21:04:53 +00:00
ld [wOtherPlayerLinkAction], a
ret
2018-06-24 14:09:41 +00:00
LinkDataReceived::
2015-11-23 21:04:53 +00:00
; Let the other system know that the data has been received.
xor a
ldh [hSerialSend], a
ldh a, [hSerialConnectionStatus]
cp USING_INTERNAL_CLOCK
ret nz
2019-05-05 16:14:46 +00:00
ld a, (0 << rSC_ON) | (1 << rSC_CLOCK)
ldh [rSC], a
2019-05-05 16:14:46 +00:00
ld a, (1 << rSC_ON) | (1 << rSC_CLOCK)
ldh [rSC], a
ret
SetBitsForTimeCapsuleRequestIfNotLinked:: ; unreferenced
; Similar to SetBitsForTimeCapsuleRequest (see engine/link/link.asm).
ld a, [wLinkMode]
and a
ret nz
ld a, USING_INTERNAL_CLOCK
ldh [rSB], a
xor a
ldh [hSerialReceive], a
2019-05-05 16:14:46 +00:00
ld a, (0 << rSC_ON) | (0 << rSC_CLOCK)
ldh [rSC], a
2019-05-05 16:14:46 +00:00
ld a, (1 << rSC_ON) | (0 << rSC_CLOCK)
ldh [rSC], a
ret