Skip to content

Commit bbf7839

Browse files
committed
More strict/deliberate synchronization between instances
1 parent 69b52b6 commit bbf7839

File tree

2 files changed

+111
-125
lines changed

2 files changed

+111
-125
lines changed

src/core/sio1.cc

Lines changed: 74 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
PCSX::SIOPayload PCSX::SIO1::makeFlowControlMessage() {
2323
return SIOPayload{
2424
DataTransfer{},
25-
FlowControl{m_flowControl.dxr, m_flowControl.xts},
25+
FlowControl{m_regs.control},
2626
};
2727
}
2828

@@ -31,7 +31,7 @@ PCSX::SIOPayload PCSX::SIO1::makeDataMessage(std::string &&data) {
3131
DataTransfer{
3232
DataTransferData{std::move(data)},
3333
},
34-
FlowControl{},
34+
FlowControl{m_regs.control},
3535
};
3636
}
3737

@@ -60,20 +60,9 @@ void PCSX::SIO1::sendDataMessage() {
6060
void PCSX::SIO1::sendFlowControlMessage() {
6161
if (fifoError()) return;
6262

63-
pollFlowControl();
64-
if (!initialMessage) {
65-
if (m_flowControl == m_prevFlowControl) return;
66-
}
67-
m_prevFlowControl = m_flowControl;
68-
6963
SIOPayload payload = makeFlowControlMessage();
7064
std::string message = encodeMessage(payload);
7165
transmitMessage(std::move(message));
72-
73-
if (initialMessage) {
74-
if (!connecting() && !fifoError()) g_system->printf("%s", _("SIO1 client connected\n"));
75-
initialMessage = false;
76-
}
7766
}
7867

7968
void PCSX::SIO1::decodeMessage() {
@@ -96,34 +85,66 @@ void PCSX::SIO1::decodeMessage() {
9685
}
9786

9887
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()) {
10392
std::string &byte = payload.get<DataTransferField>().get<DataTransferData>().value;
10493
PCSX::Slice pushByte;
10594
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+
}
109112
}
110113
}
111114
}
112115

113-
void PCSX::SIO1::sio1StateMachine() {
116+
void PCSX::SIO1::sio1StateMachine(bool data) {
114117
if (fifoError()) return;
115118

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+
}
126145
}
146+
147+
decodeMessage();
127148
}
128149

129150
void PCSX::SIO1::interrupt() {
@@ -143,59 +164,39 @@ void PCSX::SIO1::interrupt() {
143164
}
144165

145166
uint8_t PCSX::SIO1::readData8() {
146-
updateStat();
147167
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();
152169
}
153-
updateStat();
170+
if (m_sio1Mode == SIO1Mode::Protobuf) sio1StateMachine();
154171
return m_regs.data;
155172
}
156173

157174
uint16_t PCSX::SIO1::readData16() {
158-
updateStat();
159175
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);
164177
}
165-
updateStat();
178+
if (m_sio1Mode == SIO1Mode::Protobuf) sio1StateMachine();
166179
return m_regs.data;
167180
}
168181

169182
uint32_t PCSX::SIO1::readData32() {
170-
updateStat();
171183
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);
176185
}
177-
updateStat();
186+
if (m_sio1Mode == SIO1Mode::Protobuf) sio1StateMachine();
178187
return m_regs.data;
179188
}
180189

181-
uint8_t PCSX::SIO1::readStat8() {
182-
updateStat();
183-
return m_regs.status;
184-
}
185-
186190
uint16_t PCSX::SIO1::readStat16() {
187-
updateStat();
191+
if (m_sio1Mode == SIO1Mode::Protobuf) sio1StateMachine();
188192
return m_regs.status;
189193
}
190194

191-
uint32_t PCSX::SIO1::readStat32() {
192-
updateStat();
193-
return m_regs.status;
194-
}
195+
uint32_t PCSX::SIO1::readStat32() { return m_regs.status; }
195196

196197
void PCSX::SIO1::receiveCallback() {
197-
updateStat();
198198
if (!m_sio1fifo || m_sio1fifo->eof()) return;
199+
// RX Interrupt
199200
if (m_regs.control & CR_RXIRQEN) {
200201
if (!(m_regs.status & SR_IRQ)) {
201202
switch ((m_regs.control & 0x300) >> 8) {
@@ -224,14 +225,14 @@ void PCSX::SIO1::transmitData() {
224225
switch (m_sio1Mode) {
225226
case SIO1Mode::Protobuf:
226227
if (fifoError()) return;
227-
sendDataMessage();
228+
sio1StateMachine(true);
228229
break;
229230
case SIO1Mode::Raw:
230231
if (!m_sio1fifo || m_sio1fifo->eof()) return;
231232
m_sio1fifo->write<uint8_t>(m_regs.data);
232233
break;
233234
}
234-
235+
// TX Interrupt
235236
if (m_regs.control & CR_TXIRQEN) {
236237
if (m_regs.status & SR_TXRDY || m_regs.status & SR_TXRDY2) {
237238
if (!(m_regs.status & SR_IRQ)) {
@@ -253,16 +254,15 @@ void PCSX::SIO1::updateStat() {
253254
} else {
254255
m_regs.status &= ~SR_RXRDY;
255256
}
256-
psxHu32ref(0x1054) = SWAP_LEu32(m_regs.status);
257257
}
258258

259259
void PCSX::SIO1::writeBaud16(uint16_t v) {
260260
m_regs.baud = v;
261-
psxHu8ref(0x105E) = m_regs.baud;
262261
calcCycleCount();
263262
}
264263

265264
void PCSX::SIO1::writeCtrl16(uint16_t v) {
265+
uint16_t control_backup = m_regs.control;
266266
m_regs.control = v;
267267

268268
if (m_regs.control & CR_ACK) {
@@ -284,33 +284,30 @@ void PCSX::SIO1::writeCtrl16(uint16_t v) {
284284
PCSX::g_emulator->m_cpu->m_regs.interrupt &= ~(1 << PCSX::PSXINT_SIO1);
285285
}
286286

287+
// Behavior to clear FIFO if RXEN is disabled
287288
if (!(m_regs.control & CR_RXEN)) {
288289
if (m_sio1fifo.isA<Fifo>()) {
289290
m_sio1fifo.asA<Fifo>()->reset();
290291
}
291292
}
292293

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();
295301
}
296302

297303
void PCSX::SIO1::writeData8(uint8_t v) {
298304
m_regs.data = v;
299-
if (isTransmitReady()) {
300-
transmitData();
301-
}
302-
psxHu8ref(0x1050) = m_regs.data;
305+
transmitData();
303306
}
304307

305308
void PCSX::SIO1::writeMode16(uint16_t v) { m_regs.mode = v; }
306309

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; }
314311

315312
void PCSX::SIO1::calcCycleCount() {
316313
int reload = m_reloadFactor[m_regs.mode & 0x3];

0 commit comments

Comments
 (0)