22
22
PCSX::SIOPayload PCSX::SIO1::makeFlowControlMessage () {
23
23
return SIOPayload{
24
24
DataTransfer{},
25
- FlowControl{m_flowControl. dxr , m_flowControl. xts },
25
+ FlowControl{m_regs. control },
26
26
};
27
27
}
28
28
@@ -31,7 +31,7 @@ PCSX::SIOPayload PCSX::SIO1::makeDataMessage(std::string &&data) {
31
31
DataTransfer{
32
32
DataTransferData{std::move (data)},
33
33
},
34
- FlowControl{},
34
+ FlowControl{m_regs. control },
35
35
};
36
36
}
37
37
@@ -60,20 +60,9 @@ void PCSX::SIO1::sendDataMessage() {
60
60
void PCSX::SIO1::sendFlowControlMessage () {
61
61
if (fifoError ()) return ;
62
62
63
- pollFlowControl ();
64
- if (!initialMessage) {
65
- if (m_flowControl == m_prevFlowControl) return ;
66
- }
67
- m_prevFlowControl = m_flowControl;
68
-
69
63
SIOPayload payload = makeFlowControlMessage ();
70
64
std::string message = encodeMessage (payload);
71
65
transmitMessage (std::move (message));
72
-
73
- if (initialMessage) {
74
- if (!connecting () && !fifoError ()) g_system->printf (" %s" , _ (" SIO1 client connected\n " ));
75
- initialMessage = false ;
76
- }
77
66
}
78
67
79
68
void PCSX::SIO1::decodeMessage () {
@@ -96,34 +85,66 @@ void PCSX::SIO1::decodeMessage() {
96
85
}
97
86
98
87
void PCSX::SIO1::processMessage (SIOPayload payload) {
99
- if (!payload. get <DataTransferField>(). get <DataTransferData>(). hasData ()) {
100
- setDsr (payload.get <FlowControlField>().get <FlowControlDXR >().value );
101
- setCts (payload.get <FlowControlField>().get <FlowControlXTS >().value );
102
- } else {
88
+ // Flow control is always sent/received to ensure synchronization
89
+ setDsr (payload.get <FlowControlField>().get <FlowControlReg >().value & CR_DTR );
90
+ setCts (payload.get <FlowControlField>().get <FlowControlReg >().value & CR_RTS );
91
+ if (payload. get <DataTransferField>(). get <DataTransferData>(). hasData ()) {
103
92
std::string &byte = payload.get <DataTransferField>().get <DataTransferData>().value ;
104
93
PCSX::Slice pushByte;
105
94
pushByte.acquire (std::move (byte));
106
- if (m_regs.control & CR_RTS) {
107
- m_sio1fifo.asA <Fifo>()->pushSlice (std::move (pushByte));
108
- receiveCallback ();
95
+ m_sio1fifo.asA <Fifo>()->pushSlice (std::move (pushByte));
96
+ receiveCallback ();
97
+ }
98
+
99
+ if (m_sio1fifo->size () > 8 ) {
100
+ m_regs.status |= SR_RXOVERRUN;
101
+ }
102
+
103
+ updateStat ();
104
+
105
+ // DSR Interrupt
106
+ if (m_regs.control & CR_DSRIRQEN) {
107
+ if (m_regs.status & SR_DSR) {
108
+ if (!(m_regs.status & SR_IRQ)) {
109
+ scheduleInterrupt (m_cycleCount);
110
+ m_regs.status |= SR_IRQ;
111
+ }
109
112
}
110
113
}
111
114
}
112
115
113
- void PCSX::SIO1::sio1StateMachine () {
116
+ void PCSX::SIO1::sio1StateMachine (bool data ) {
114
117
if (fifoError ()) return ;
115
118
116
- switch (m_decodeState) {
117
- case READ_SIZE:
118
- while (m_fifo->size () >= 1 ) {
119
- messageSize = m_fifo->byte ();
120
- m_decodeState = READ_MESSAGE;
121
- case READ_MESSAGE:
122
- if (m_fifo->size () < messageSize) return ;
123
- decodeMessage ();
124
- m_decodeState = READ_SIZE;
125
- }
119
+ // Server is master - send first, receive after
120
+ if (g_emulator->m_sio1Server ->getServerStatus () == SIO1Server::SIO1ServerStatus::SERVER_STARTED) {
121
+ if (data) {
122
+ sendDataMessage ();
123
+ } else {
124
+ sendFlowControlMessage ();
125
+ }
126
+
127
+ waitOnMessage (); // Wait for the next message to be fully received
128
+ }
129
+
130
+ // Client is slave - receive first, send after
131
+ if (g_emulator->m_sio1Client ->getClientStatus () == SIO1Client::SIO1ClientStatus::CLIENT_STARTED) {
132
+ // If connection is new, run slave delay
133
+ if (m_slaveDelay) {
134
+ slaveDelay ();
135
+ return ;
136
+ }
137
+
138
+ waitOnMessage (); // Wait for the next message to be fully received
139
+
140
+ if (data) {
141
+ sendDataMessage ();
142
+ } else {
143
+ sendFlowControlMessage ();
144
+ }
126
145
}
146
+
147
+ decodeMessage ();
127
148
}
128
149
129
150
void PCSX::SIO1::interrupt () {
@@ -143,59 +164,39 @@ void PCSX::SIO1::interrupt() {
143
164
}
144
165
145
166
uint8_t PCSX::SIO1::readData8 () {
146
- updateStat ();
147
167
if (m_sio1fifo || !m_sio1fifo->eof ()) {
148
- if (m_regs.status & SR_RXRDY) {
149
- m_regs.data = m_sio1fifo->byte ();
150
- psxHu8 (0x1050 ) = m_regs.data ;
151
- }
168
+ m_regs.data = m_sio1fifo->byte ();
152
169
}
153
- updateStat ();
170
+ if (m_sio1Mode == SIO1Mode::Protobuf) sio1StateMachine ();
154
171
return m_regs.data ;
155
172
}
156
173
157
174
uint16_t PCSX::SIO1::readData16 () {
158
- updateStat ();
159
175
if (m_sio1fifo || !m_sio1fifo->eof ()) {
160
- if (m_regs.status & SR_RXRDY) {
161
- m_sio1fifo->read (&m_regs.data , 2 );
162
- psxHu16 (0x1050 ) = m_regs.data ;
163
- }
176
+ m_sio1fifo->read (&m_regs.data , 2 );
164
177
}
165
- updateStat ();
178
+ if (m_sio1Mode == SIO1Mode::Protobuf) sio1StateMachine ();
166
179
return m_regs.data ;
167
180
}
168
181
169
182
uint32_t PCSX::SIO1::readData32 () {
170
- updateStat ();
171
183
if (m_sio1fifo || !m_sio1fifo->eof ()) {
172
- if (m_regs.status & SR_RXRDY) {
173
- m_sio1fifo->read (&m_regs.data , 4 );
174
- psxHu32 (0x1050 ) = m_regs.data ;
175
- }
184
+ m_sio1fifo->read (&m_regs.data , 4 );
176
185
}
177
- updateStat ();
186
+ if (m_sio1Mode == SIO1Mode::Protobuf) sio1StateMachine ();
178
187
return m_regs.data ;
179
188
}
180
189
181
- uint8_t PCSX::SIO1::readStat8 () {
182
- updateStat ();
183
- return m_regs.status ;
184
- }
185
-
186
190
uint16_t PCSX::SIO1::readStat16 () {
187
- updateStat ();
191
+ if (m_sio1Mode == SIO1Mode::Protobuf) sio1StateMachine ();
188
192
return m_regs.status ;
189
193
}
190
194
191
- uint32_t PCSX::SIO1::readStat32 () {
192
- updateStat ();
193
- return m_regs.status ;
194
- }
195
+ uint32_t PCSX::SIO1::readStat32 () { return m_regs.status ; }
195
196
196
197
void PCSX::SIO1::receiveCallback () {
197
- updateStat ();
198
198
if (!m_sio1fifo || m_sio1fifo->eof ()) return ;
199
+ // RX Interrupt
199
200
if (m_regs.control & CR_RXIRQEN) {
200
201
if (!(m_regs.status & SR_IRQ)) {
201
202
switch ((m_regs.control & 0x300 ) >> 8 ) {
@@ -224,14 +225,14 @@ void PCSX::SIO1::transmitData() {
224
225
switch (m_sio1Mode) {
225
226
case SIO1Mode::Protobuf:
226
227
if (fifoError ()) return ;
227
- sendDataMessage ( );
228
+ sio1StateMachine ( true );
228
229
break ;
229
230
case SIO1Mode::Raw:
230
231
if (!m_sio1fifo || m_sio1fifo->eof ()) return ;
231
232
m_sio1fifo->write <uint8_t >(m_regs.data );
232
233
break ;
233
234
}
234
-
235
+ // TX Interrupt
235
236
if (m_regs.control & CR_TXIRQEN) {
236
237
if (m_regs.status & SR_TXRDY || m_regs.status & SR_TXRDY2) {
237
238
if (!(m_regs.status & SR_IRQ)) {
@@ -253,16 +254,15 @@ void PCSX::SIO1::updateStat() {
253
254
} else {
254
255
m_regs.status &= ~SR_RXRDY;
255
256
}
256
- psxHu32ref (0x1054 ) = SWAP_LEu32 (m_regs.status );
257
257
}
258
258
259
259
void PCSX::SIO1::writeBaud16 (uint16_t v) {
260
260
m_regs.baud = v;
261
- psxHu8ref (0x105E ) = m_regs.baud ;
262
261
calcCycleCount ();
263
262
}
264
263
265
264
void PCSX::SIO1::writeCtrl16 (uint16_t v) {
265
+ uint16_t control_backup = m_regs.control ;
266
266
m_regs.control = v;
267
267
268
268
if (m_regs.control & CR_ACK) {
@@ -284,33 +284,30 @@ void PCSX::SIO1::writeCtrl16(uint16_t v) {
284
284
PCSX::g_emulator->m_cpu ->m_regs .interrupt &= ~(1 << PCSX::PSXINT_SIO1);
285
285
}
286
286
287
+ // Behavior to clear FIFO if RXEN is disabled
287
288
if (!(m_regs.control & CR_RXEN)) {
288
289
if (m_sio1fifo.isA <Fifo>()) {
289
290
m_sio1fifo.asA <Fifo>()->reset ();
290
291
}
291
292
}
292
293
293
- if (m_sio1Mode == SIO1Mode::Protobuf) sendFlowControlMessage ();
294
- psxHu16ref (0x105A ) = SWAP_LE16 (m_regs.control );
294
+ if (((m_regs.control >> 8 ) & 0x03 ) != ((control_backup >> 8 ) & 0x03 )) {
295
+ if (m_sio1fifo.isA <Fifo>()) {
296
+ m_sio1fifo.asA <Fifo>()->reset ();
297
+ }
298
+ }
299
+
300
+ if (m_sio1Mode == SIO1Mode::Protobuf) sio1StateMachine ();
295
301
}
296
302
297
303
void PCSX::SIO1::writeData8 (uint8_t v) {
298
304
m_regs.data = v;
299
- if (isTransmitReady ()) {
300
- transmitData ();
301
- }
302
- psxHu8ref (0x1050 ) = m_regs.data ;
305
+ transmitData ();
303
306
}
304
307
305
308
void PCSX::SIO1::writeMode16 (uint16_t v) { m_regs.mode = v; }
306
309
307
- void PCSX::SIO1::writeStat32 (uint32_t v) {
308
- m_regs.status = v;
309
- if (isTransmitReady ()) {
310
- transmitData ();
311
- }
312
- psxHu32ref (0x1054 ) = SWAP_LE32 (m_regs.status );
313
- }
310
+ void PCSX::SIO1::writeStat16 (uint16_t v) { m_regs.status = v; }
314
311
315
312
void PCSX::SIO1::calcCycleCount () {
316
313
int reload = m_reloadFactor[m_regs.mode & 0x3 ];
0 commit comments