Alchemy
Loading...
Searching...
No Matches

serial_runtime.h

Go to the documentation of this file.
1#ifndef ALCHEMY_SERIAL_RUNTIME_H
2#define ALCHEMY_SERIAL_RUNTIME_H
3
4/// @file
5/// The link cable's runtime: serial packets, registers and transfer state.
6
7#include "edition.h"
8#include "types.h"
9#include "static_assert.h"
10#include "system.h"
11#include "io_reg.h"
12#include "dma.h"
13#include "irq.h"
14#include "dma.h"
15
16/// A link cable packet: its sequence number, the consoles not yet heard from,
17/// its checksum and a 24-byte payload.
19 u8 sequence; ///< SerialRuntime's sequence when the packet was built
20 /// The consoles heard from before but not this frame (receivedMask ^
21 /// currentMask); a receiver complements it once the checksum is good.
23 /// The complement of the sum of the packet's first 14 halfwords, taken with
24 /// this field 0.
27 u8 reservedTail[4]; ///< past the 14 halfwords sent; never written
28};
29
30STATIC_ASSERT(sizeof(struct SerialPacket) == 32);
31STATIC_ASSERT(offsetof(struct SerialPacket, sequence) == 0);
32STATIC_ASSERT(offsetof(struct SerialPacket, missingMask) == 1);
33STATIC_ASSERT(offsetof(struct SerialPacket, checksum) == 2);
34STATIC_ASSERT(offsetof(struct SerialPacket, payload) == 4);
35STATIC_ASSERT(offsetof(struct SerialPacket, reservedTail) == 28);
36
37/// The serial data registers read as two words or four halfwords; no TBS code
38/// names this union.
42};
43
44/// The link cable's runtime: its mode and phase, the consoles heard from, the
45/// send position and the packet buffers the interrupt handler fills.
47 /// SIOCNT's bits 7 and 3 when this console armed timer 3 to clock the
48 /// transfers: 8 then, else 0; 8 adds 0x80 to the link status.
50 u8 phase; ///< 0 looking for the partner, 1 connected
51 u8 receivedMask; ///< the consoles heard from since the link began
52 u8 currentMask; ///< the consoles heard from this frame
53 /// Set by the interrupt for each console and cleared each frame.
54 /// bits: 1 heard while isParent was set | 0 a packet completed
56 /// Nonzero lets a new packet restart timer 3.
58 /// SIOCNT's bit 6, copied by each transfer interrupt; nonzero adds 0x1000
59 /// to the link status.
61 u8 reserved0a; ///< not named by TBS code
62 /// The packet sequence number, counted up each frame once connected.
64 u8 reserved0c[8]; ///< not named by TBS code
65 /// The halfword of sendBuffer[1] sent next; -1 between packets, when 0xfefe
66 /// is sent and the two send buffers swap.
68 /// Each console's next halfword in its incomingBuffer; -1 after an idle
69 /// 0xfefe.
71 u8 reserved20[8]; ///< not named by TBS code
72 /// The packet being built ([0]) and the packet being sent ([1]).
74 /// Each console's packet being received; two are used.
76 /// Each console's last complete packet, swapped in by the interrupt.
78 /// The packets the frame code checks and copies, swapped with readyBuffer
79 /// each frame.
81 /// The buffers' memory: two 32-byte send buffers, then 96 bytes a console
82 /// for its incoming, ready and pending packets.
83 u8 storage[0x100];
84};
85
86STATIC_ASSERT(sizeof(struct SerialRuntime) == 0x160);
88STATIC_ASSERT(offsetof(struct SerialRuntime, transferEnabled) == 8);
89STATIC_ASSERT(offsetof(struct SerialRuntime, sendIndex) == 0x14);
90STATIC_ASSERT(offsetof(struct SerialRuntime, storage) == 0x60);
91
92/// A console's block transfer state, exchanged with the partner each VBlank:
93/// its block sequence, its status and flags, and a 20-byte block.
95 /// The sequence number of the block in payload; as receiver, the one it
96 /// expects with bit 7 set to ask for a resend; 1 when a transfer starts.
98 /// 0x80 sending or 0x81 receiving when started; the receiver counts blocks
99 /// (status + 1, with bit 7) and sets 0 after the last.
101 /// The receive state: 1 receiving, 2 the last block taken, 0 idle.
103 /// The send state: 1 a block with more to follow, 2 the last block, 0 idle.
105 u8 payload[20]; ///< one block of the data sent
106};
107
108STATIC_ASSERT(sizeof(struct SerialTransferState) == 24);
114
115#define SERIAL_RUNTIME (&gSerialRuntime)
116
118extern struct SerialRuntime gSerialRuntime;
121/// volatile: tagged where it steers, in SerialRuntime_StepBlockTransfer (tbs
122/// runtime.c)
123extern volatile u16 gSerialSendSize;
125/// volatile: tagged where it steers, in BattleLink_ReceiveActions (tbs
126/// battle.c) and LinkLobby_ReceivePartyRecords (tbs lobby.c)
127extern volatile u16 gSerialReceivedSize;
128extern u8 gSerialPeerPayloads[4][24];
129/// volatile: tagged where it steers, in SerialRuntime_StepBlockTransfer (tbs
130/// runtime.c)
131extern volatile u8 gSerialBlockSequence;
133/// Link status, updated by the VBlank exchange handler.
134/* FAKEMATCH: volatile makes every access to this cell a load or store of its
135 * own; without it, in tbs-en, SaveMenu_Run: differ 221, 923 instructions for
136 * 920, and SerialRuntime_WaitForStatusMask: differ 18, 21 for 23. */
137extern volatile u16 gLinkStatus;
138
139static inline s32 SerialRuntime_AddParentFlag(s32 status) {
140 if (gSerialRuntime.isParent != 0)
141 status |= 0x1000;
142 return status;
143}
144
145static __inline__ void SerialRuntime_ResetTransferState(void) {
146 struct SerialTransferState *state;
147 volatile u16 *ime;
148 u32 saved;
149 u32 zero;
150
151 /* FAKEMATCH(one-pass): the blocks preserve IME write order; the repeated
152 * state assignment keeps its allocation priority above the IME pointer. */
153 do {
154 state = &gSerialTransfer;
155 ime = &REG_IME;
156 } while (0);
157 do {
158 saved = *ime;
159 *ime = (u16)(u32)ime;
160 } while (0);
161 do {
162 zero = 0;
163 state = &gSerialTransfer;
164 } while (0);
165 state->status = 0x80;
166 gSerialSendSource = zero;
167 gSerialSendSize = zero;
168 gSerialReceiveDest = zero;
169 *(u8 *)&state->peerFlags = zero;
170 *(u8 *)&state->flags = zero;
171 gSerialReceivedSize = zero;
172 *ime = saved;
173}
174
175#endif
DMA channel registers, and the DMA and CPU fills.
The edition's language, for C to compare (LANGUAGE == LANGUAGE_GERMAN).
The hardware's I/O registers and their bits, as pret names them.
#define REG_IME
Definition io_reg.h:308
The hardware's interrupt sources and the interrupt handler table.
s32 gSerialReceiveDest
volatile u16 gLinkStatus
Link status, updated by the VBlank exchange handler.
volatile u16 gSerialSendSize
volatile: tagged where it steers, in SerialRuntime_StepBlockTransfer (tbs runtime....
static s32 SerialRuntime_AddParentFlag(s32 status)
struct SerialRuntime gSerialRuntime
u8 gLinkExchangeState
volatile u8 gSerialBlockSequence
volatile: tagged where it steers, in SerialRuntime_StepBlockTransfer (tbs runtime....
volatile u16 gSerialReceivedSize
volatile: tagged where it steers, in BattleLink_ReceiveActions (tbs battle.c) and LinkLobby_ReceivePa...
u16 gSerialExchangeActive
static __inline__ void SerialRuntime_ResetTransferState(void)
u8 gSerialPeerPayloads[4][24]
s32 gSerialSendSource
struct SerialTransferState gSerialTransfer
STATIC_ASSERT, a compile-time check that emits nothing.
#define STATIC_ASSERT(condition)
C89 permits repeated extern declarations of the same array.
#define offsetof(type, member)
Definition stddef.h:19
A link cable packet: its sequence number, the consoles not yet heard from, its checksum and a 24-byte...
u16 checksum
The complement of the sum of the packet's first 14 halfwords, taken with this field 0.
u8 sequence
SerialRuntime's sequence when the packet was built.
u8 reservedTail[4]
past the 14 halfwords sent; never written
u8 missingMask
The consoles heard from before but not this frame (receivedMask ^ currentMask); a receiver complement...
The link cable's runtime: its mode and phase, the consoles heard from, the send position and the pack...
u8 storage[0x100]
The buffers' memory: two 32-byte send buffers, then 96 bytes a console for its incoming,...
u8 mode
SIOCNT's bits 7 and 3 when this console armed timer 3 to clock the transfers: 8 then,...
u16 * readyBuffer[4]
Each console's last complete packet, swapped in by the interrupt.
u16 * sendBuffer[2]
The packet being built ([0]) and the packet being sent ([1]).
u8 channelFlags[4]
Set by the interrupt for each console and cleared each frame.
s32 sendIndex
The halfword of sendBuffer[1] sent next; -1 between packets, when 0xfefe is sent and the two send buf...
s32 receiveIndex[2]
Each console's next halfword in its incomingBuffer; -1 after an idle 0xfefe.
u8 transferEnabled
Nonzero lets a new packet restart timer 3.
u8 phase
0 looking for the partner, 1 connected
u16 * incomingBuffer[4]
Each console's packet being received; two are used.
u8 currentMask
the consoles heard from this frame
u8 reserved0c[8]
not named by TBS code
u8 reserved20[8]
not named by TBS code
u8 reserved0a
not named by TBS code
u8 sequence
The packet sequence number, counted up each frame once connected.
u16 * pendingBuffer[4]
The packets the frame code checks and copies, swapped with readyBuffer each frame.
u8 isParent
SIOCNT's bit 6, copied by each transfer interrupt; nonzero adds 0x1000 to the link status.
u8 receivedMask
the consoles heard from since the link began
A console's block transfer state, exchanged with the partner each VBlank: its block sequence,...
u8 peerFlags
The send state: 1 a block with more to follow, 2 the last block, 0 idle.
u8 flags
The receive state: 1 receiving, 2 the last block taken, 0 idle.
u8 status
0x80 sending or 0x81 receiving when started; the receiver counts blocks (status + 1,...
u8 payload[20]
one block of the data sent
u8 active
The sequence number of the block in payload; as receiver, the one it expects with bit 7 set to ask fo...
The system's routines and globals: interrupts, BIOS sound bias, random numbers and sleep.
The integer types, TRUE, UNUSED and the fixed-address macros.
signed int s32
Definition types.h:14
unsigned int u32
Definition types.h:15
unsigned short u16
Definition types.h:13
unsigned char u8
Definition types.h:11
The serial data registers read as two words or four halfwords; no TBS code names this union.