1 #include <cassert>
2 #include <cstring>
3 #include <vector>
4 #include "Iop_Sio2.h"
5 #include "../Log.h"
6 #include "../states/RegisterStateFile.h"
7 #include "../states/MemoryStateFile.h"
8
9 #define LOG_NAME ("iop_sio2")
10
11 #define STATE_REGS ("sio2/regs")
12 #define STATE_CTRL1 ("sio2/ctrl1")
13 #define STATE_CTRL2 ("sio2/ctrl2")
14 #define STATE_PAD ("sio2/pad")
15 #define STATE_INPUT ("sio2/input")
16 #define STATE_OUTPUT ("sio2/output")
17
18 #define STATE_REGS_XML ("sio2/regs.xml")
19 #define STATE_REGS_CURRENTREGINDEX ("CurrentRegIndex")
20
21 using namespace Iop;
22
23 static const uint8 DUALSHOCK2_MODEL[6] =
24 {
25 0x03, //Model
26 0x02, //Mode Count
27 0x00, //Mode Current Offset
28 0x02, //Actuator Count
29 0x01, //Actuator Comb Count
30 0x00};
31
32 static const uint8 DUALSHOCK2_ID[5][5] =
33 {
34 {0x00, 0x01, 0x02, 0x00, 0x0A}, //Actuator 0 info
35 {0x00, 0x01, 0x01, 0x01, 0x14}, //Actuator 1 info
36 {0x00, 0x02, 0x00, 0x01, 0x00}, //Actuator Comb 0 info
37 {0x00, 0x00, 0x04, 0x00, 0x00}, //Mode 0 info
38 {0x00, 0x00, 0x07, 0x00, 0x00} //Mode 1 info
39 };
40
41 #define ID_DIGITAL 0x41
42 #define ID_ANALOG 0x73
43 #define ID_ANALOGP 0x79
44 #define ID_CONFIG 0xF3
45
CSio2(Iop::CIntc & intc)46 CSio2::CSio2(Iop::CIntc& intc)
47 : m_intc(intc)
48 {
49 Reset();
50 }
51
Reset()52 void CSio2::Reset()
53 {
54 m_currentRegIndex = 0;
55 m_outputBuffer.clear();
56 m_inputBuffer.clear();
57 memset(m_regs, 0, sizeof(m_regs));
58 memset(m_ctrl1, 0, sizeof(m_ctrl1));
59 memset(m_ctrl2, 0, sizeof(m_ctrl2));
60 memset(&m_padState, 0, sizeof(m_padState));
61 for(auto& padInfo : m_padState)
62 {
63 padInfo.buttonState = 0xFFFF;
64 padInfo.mode = ID_ANALOG;
65 padInfo.pollMask[0] = 0xFF;
66 padInfo.pollMask[1] = 0xFF;
67 padInfo.pollMask[2] = 0x03;
68 memset(padInfo.analogStickState, 0x7F, sizeof(padInfo.analogStickState));
69 }
70 }
71
LoadState(Framework::CZipArchiveReader & archive)72 void CSio2::LoadState(Framework::CZipArchiveReader& archive)
73 {
74 static const auto readBuffer =
75 [](ByteBufferType& outputBuffer, Framework::CStream& inputStream) {
76 outputBuffer.clear();
77 while(!inputStream.IsEOF())
78 {
79 uint8 buffer[256];
80 uint32 read = inputStream.Read(buffer, 256);
81 outputBuffer.insert(outputBuffer.end(), buffer, buffer + read);
82 }
83 };
84
85 {
86 CRegisterStateFile registerFile(*archive.BeginReadFile(STATE_REGS_XML));
87 m_currentRegIndex = registerFile.GetRegister32(STATE_REGS_CURRENTREGINDEX);
88 }
89
90 archive.BeginReadFile(STATE_REGS)->Read(&m_regs, sizeof(m_regs));
91 archive.BeginReadFile(STATE_CTRL1)->Read(&m_ctrl1, sizeof(m_ctrl1));
92 archive.BeginReadFile(STATE_CTRL2)->Read(&m_ctrl2, sizeof(m_ctrl2));
93 archive.BeginReadFile(STATE_PAD)->Read(&m_padState, sizeof(m_padState));
94
95 readBuffer(m_outputBuffer, *archive.BeginReadFile(STATE_OUTPUT));
96 readBuffer(m_inputBuffer, *archive.BeginReadFile(STATE_INPUT));
97 }
98
SaveState(Framework::CZipArchiveWriter & archive)99 void CSio2::SaveState(Framework::CZipArchiveWriter& archive)
100 {
101 auto inputBuffer = std::vector<uint8>(m_inputBuffer.begin(), m_inputBuffer.end());
102 auto outputBuffer = std::vector<uint8>(m_outputBuffer.begin(), m_outputBuffer.end());
103
104 {
105 auto registerFile = new CRegisterStateFile(STATE_REGS_XML);
106 registerFile->SetRegister32(STATE_REGS_CURRENTREGINDEX, m_currentRegIndex);
107 archive.InsertFile(registerFile);
108 }
109
110 archive.InsertFile(new CMemoryStateFile(STATE_REGS, &m_regs, sizeof(m_regs)));
111 archive.InsertFile(new CMemoryStateFile(STATE_CTRL1, &m_ctrl1, sizeof(m_ctrl1)));
112 archive.InsertFile(new CMemoryStateFile(STATE_CTRL2, &m_ctrl2, sizeof(m_ctrl2)));
113 archive.InsertFile(new CMemoryStateFile(STATE_PAD, &m_padState, sizeof(m_padState)));
114 archive.InsertFile(new CMemoryStateFile(STATE_INPUT, inputBuffer.data(), inputBuffer.size()));
115 archive.InsertFile(new CMemoryStateFile(STATE_OUTPUT, outputBuffer.data(), outputBuffer.size()));
116 }
117
SetButtonState(unsigned int padNumber,PS2::CControllerInfo::BUTTON button,bool pressed,uint8 * ram)118 void CSio2::SetButtonState(unsigned int padNumber, PS2::CControllerInfo::BUTTON button, bool pressed, uint8* ram)
119 {
120 assert(padNumber < MAX_PADS);
121 if(padNumber >= MAX_PADS) return;
122
123 auto& padState = m_padState[padNumber];
124 auto buttonMask = static_cast<uint16>(GetButtonMask(button));
125 padState.buttonState &= ~buttonMask;
126 if(!pressed)
127 {
128 padState.buttonState |= buttonMask;
129 }
130 }
131
SetAxisState(unsigned int padNumber,PS2::CControllerInfo::BUTTON axis,uint8 axisValue,uint8 * ram)132 void CSio2::SetAxisState(unsigned int padNumber, PS2::CControllerInfo::BUTTON axis, uint8 axisValue, uint8* ram)
133 {
134 assert(padNumber < MAX_PADS);
135 if(padNumber >= MAX_PADS) return;
136
137 assert(axis < 4);
138 if(axis >= 4) return;
139
140 static const unsigned int axisIndex[4] =
141 {
142 2,
143 3,
144 0,
145 1};
146
147 auto& padState = m_padState[padNumber];
148 padState.analogStickState[axisIndex[axis]] = axisValue;
149 }
150
ReadRegister(uint32 address)151 uint32 CSio2::ReadRegister(uint32 address)
152 {
153 uint32 value = 0;
154 switch(address)
155 {
156 case REG_DATA_IN:
157 value = m_outputBuffer.front();
158 m_outputBuffer.pop_front();
159 break;
160 }
161 #ifdef _DEBUG
162 DisassembleRead(address, value);
163 #endif
164 return value;
165 }
166
WriteRegister(uint32 address,uint32 value)167 void CSio2::WriteRegister(uint32 address, uint32 value)
168 {
169 if(address >= REG_BASE && address <= REG_BASE_END)
170 {
171 m_regs[(address - REG_BASE) / 4] = value;
172 }
173 else
174 {
175 switch(address)
176 {
177 case REG_PORT0_CTRL1:
178 case REG_PORT1_CTRL1:
179 case REG_PORT2_CTRL1:
180 case REG_PORT3_CTRL1:
181 {
182 unsigned int portId = (address - REG_PORT0_CTRL1) / 8;
183 m_ctrl1[portId] = value;
184 }
185 break;
186 case REG_PORT0_CTRL2:
187 case REG_PORT1_CTRL2:
188 case REG_PORT2_CTRL2:
189 case REG_PORT3_CTRL2:
190 {
191 unsigned int portId = (address - REG_PORT0_CTRL2) / 8;
192 m_ctrl2[portId] = value;
193 }
194 break;
195 case REG_CTRL:
196 if(value == 0x0C)
197 {
198 m_currentRegIndex = 0;
199 }
200 if(value == 0x01)
201 {
202 //Ok, done transferring, generate interrupt.
203 m_intc.AssertLine(CIntc::LINE_SIO2);
204 }
205 break;
206 case REG_DATA_OUT:
207 m_inputBuffer.push_back(static_cast<uint8>(value));
208 ProcessCommand();
209 break;
210 }
211 }
212 #ifdef _DEBUG
213 DisassembleWrite(address, value);
214 #endif
215 }
216
ReceiveDmaIn(uint8 * buffer,uint32 blockSize,uint32 blockAmount)217 uint32 CSio2::ReceiveDmaIn(uint8* buffer, uint32 blockSize, uint32 blockAmount)
218 {
219 assert(m_currentRegIndex == 0);
220 for(uint32 i = 0; i < blockAmount; i++)
221 {
222 m_inputBuffer.insert(std::end(m_inputBuffer), buffer, buffer + blockSize);
223 buffer += blockSize;
224 ProcessCommand();
225 }
226 assert(m_currentRegIndex == blockAmount);
227 return blockAmount;
228 }
229
ReceiveDmaOut(uint8 * buffer,uint32 blockSize,uint32 blockAmount)230 uint32 CSio2::ReceiveDmaOut(uint8* buffer, uint32 blockSize, uint32 blockAmount)
231 {
232 assert(m_currentRegIndex == blockAmount);
233 for(uint32 i = 0; i < blockAmount; i++)
234 {
235 uint32 currentReg = m_regs[i];
236 uint32 dstSize = (currentReg >> 18) & 0x1FF;
237 for(uint32 j = 0; j < dstSize; j++)
238 {
239 buffer[j] = m_outputBuffer.front();
240 m_outputBuffer.pop_front();
241 }
242 buffer += blockSize;
243 }
244 return blockAmount;
245 }
246
ProcessCommand()247 void CSio2::ProcessCommand()
248 {
249 uint32 currentReg = m_regs[m_currentRegIndex];
250 uint32 srcSize = (currentReg >> 8) & 0x1FF;
251 uint32 dstSize = (currentReg >> 18) & 0x1FF;
252 if(m_inputBuffer.size() >= srcSize)
253 {
254 unsigned int portId = currentReg & 0x03;
255 uint32 deviceId = m_ctrl2[portId];
256 size_t outputOffset = m_outputBuffer.size();
257
258 for(unsigned int i = 0; i < dstSize; i++)
259 {
260 m_outputBuffer.push_back(0xFF);
261 }
262
263 if(deviceId == 0x00030064)
264 {
265 ProcessMultitap(portId, outputOffset, dstSize, srcSize);
266 }
267 else if(deviceId == 0x5FFFF)
268 {
269 ProcessMemoryCard(portId, outputOffset, dstSize, srcSize);
270 }
271 else
272 {
273 ProcessController(portId, outputOffset, dstSize, srcSize);
274 }
275
276 assert((m_outputBuffer.size() - outputOffset) == dstSize);
277
278 m_inputBuffer.clear();
279 m_currentRegIndex++;
280 }
281 }
282
ProcessController(unsigned int portId,size_t outputOffset,uint32 dstSize,uint32 srcSize)283 void CSio2::ProcessController(unsigned int portId, size_t outputOffset, uint32 dstSize, uint32 srcSize)
284 {
285 if(portId < MAX_PADS)
286 {
287 assert(dstSize >= 3);
288 assert(srcSize >= 3);
289
290 unsigned int padId = portId & 0x01;
291 auto& padState = m_padState[padId];
292
293 //Write header
294 m_outputBuffer[outputOffset + 0x00] = 0xFF;
295 m_outputBuffer[outputOffset + 0x01] = padState.configMode ? ID_CONFIG : padState.mode;
296 m_outputBuffer[outputOffset + 0x02] = 0x5A; //?
297
298 uint8 cmd = m_inputBuffer[1];
299 switch(cmd)
300 {
301 case 0x40:
302 assert(dstSize == 9);
303 m_outputBuffer[outputOffset + 0x03] = 0x00;
304 m_outputBuffer[outputOffset + 0x04] = 0x00;
305 m_outputBuffer[outputOffset + 0x05] = 0x02;
306 m_outputBuffer[outputOffset + 0x06] = 0x00;
307 m_outputBuffer[outputOffset + 0x07] = 0x00;
308 m_outputBuffer[outputOffset + 0x08] = 0x5A;
309 CLog::GetInstance().Print(LOG_NAME, "Pad %d: SetVrefParam();\r\n", padId);
310 break;
311 case 0x41:
312 assert(dstSize == 9);
313 if(padState.mode == ID_DIGITAL)
314 {
315 m_outputBuffer[outputOffset + 0x03] = 0x00;
316 m_outputBuffer[outputOffset + 0x04] = 0x00;
317 m_outputBuffer[outputOffset + 0x05] = 0x00;
318 m_outputBuffer[outputOffset + 0x06] = 0x00;
319 m_outputBuffer[outputOffset + 0x07] = 0x00;
320 m_outputBuffer[outputOffset + 0x08] = 0x00;
321 }
322 else
323 {
324 m_outputBuffer[outputOffset + 0x03] = padState.pollMask[0];
325 m_outputBuffer[outputOffset + 0x04] = padState.pollMask[1];
326 m_outputBuffer[outputOffset + 0x05] = padState.pollMask[2];
327 m_outputBuffer[outputOffset + 0x06] = 0x00;
328 m_outputBuffer[outputOffset + 0x07] = 0x00;
329 m_outputBuffer[outputOffset + 0x08] = 0x5A;
330 }
331 CLog::GetInstance().Print(LOG_NAME, "Pad %d: QueryButtonMask();\r\n", padId);
332 break;
333 case 0x42: //Read Data
334 assert(dstSize == 5 || dstSize == 9 || dstSize == 21);
335 //Pad data goes here
336 m_outputBuffer[outputOffset + 0x03] = static_cast<uint8>(padState.buttonState >> 8);
337 m_outputBuffer[outputOffset + 0x04] = static_cast<uint8>(padState.buttonState & 0xFF);
338 if(dstSize >= 9)
339 {
340 //Analog stuff
341 m_outputBuffer[outputOffset + 0x05] = padState.analogStickState[0];
342 m_outputBuffer[outputOffset + 0x06] = padState.analogStickState[1];
343 m_outputBuffer[outputOffset + 0x07] = padState.analogStickState[2];
344 m_outputBuffer[outputOffset + 0x08] = padState.analogStickState[3];
345
346 if(dstSize == 21)
347 {
348 //Pressure stuff
349 m_outputBuffer[outputOffset + 0x09] = ((padState.buttonState & 0x2000) == 0) ? 0xFF : 0x00; //Left
350 m_outputBuffer[outputOffset + 0x0A] = ((padState.buttonState & 0x8000) == 0) ? 0xFF : 0x00; //Right
351 m_outputBuffer[outputOffset + 0x0B] = ((padState.buttonState & 0x1000) == 0) ? 0xFF : 0x00; //Up
352 m_outputBuffer[outputOffset + 0x0C] = ((padState.buttonState & 0x4000) == 0) ? 0xFF : 0x00; //Down
353
354 m_outputBuffer[outputOffset + 0x0D] = ((padState.buttonState & 0x0010) == 0) ? 0xFF : 0x00; //Triangle
355 m_outputBuffer[outputOffset + 0x0E] = ((padState.buttonState & 0x0020) == 0) ? 0xFF : 0x00; //Circle
356 m_outputBuffer[outputOffset + 0x0F] = ((padState.buttonState & 0x0040) == 0) ? 0xFF : 0x00; //Cross
357 m_outputBuffer[outputOffset + 0x10] = ((padState.buttonState & 0x0080) == 0) ? 0xFF : 0x00; //Square
358
359 m_outputBuffer[outputOffset + 0x11] = ((padState.buttonState & 0x0004) == 0) ? 0xFF : 0x00; //L1
360 m_outputBuffer[outputOffset + 0x12] = ((padState.buttonState & 0x0008) == 0) ? 0xFF : 0x00; //R1
361 m_outputBuffer[outputOffset + 0x13] = ((padState.buttonState & 0x0001) == 0) ? 0xFF : 0x00; //L2
362 m_outputBuffer[outputOffset + 0x14] = ((padState.buttonState & 0x0002) == 0) ? 0xFF : 0x00; //R2
363 }
364 }
365 CLog::GetInstance().Print(LOG_NAME, "Pad %d: ReadData();\r\n", padId);
366 break;
367 case 0x43: //Enter Config Mode
368 padState.configMode = (m_inputBuffer[3] == 0x01);
369 CLog::GetInstance().Print(LOG_NAME, "Pad %d: EnterConfigMode(config = %d);\r\n", padId, m_inputBuffer[3]);
370 break;
371 case 0x44: //Set Mode & Lock
372 {
373 assert(dstSize == 5 || dstSize == 9);
374 uint8 mode = m_inputBuffer[3];
375 uint8 lock = m_inputBuffer[4];
376 //cmdBuffer[4] == 0x03 -> Mode Lock
377 m_outputBuffer[outputOffset + 0x03] = 0x00;
378 m_outputBuffer[outputOffset + 0x04] = 0x00;
379 if(dstSize == 9)
380 {
381 m_outputBuffer[outputOffset + 0x05] = 0x00;
382 m_outputBuffer[outputOffset + 0x06] = 0x00;
383 m_outputBuffer[outputOffset + 0x07] = 0x00;
384 m_outputBuffer[outputOffset + 0x08] = 0x00;
385 }
386 padState.mode = (mode == 0x01) ? ID_ANALOG : ID_DIGITAL;
387 CLog::GetInstance().Print(LOG_NAME, "Pad %d: SetModeAndLock(mode = %d, lock = %d);\r\n", padId, mode, lock);
388 }
389 break;
390 case 0x45: //Query Model
391 assert(dstSize == 9);
392 assert(padState.configMode);
393 std::copy(std::begin(DUALSHOCK2_MODEL), std::end(DUALSHOCK2_MODEL), m_outputBuffer.begin() + outputOffset + 0x03);
394 m_outputBuffer[outputOffset + 5] = (padState.mode == ID_DIGITAL) ? 0x00 : 0x01; //0x01 if analog pad
395 CLog::GetInstance().Print(LOG_NAME, "Pad %d: QueryModel();\r\n", padId);
396 break;
397 case 0x46:
398 assert(dstSize == 9);
399 assert(padState.configMode);
400 if(m_inputBuffer[3] == 0x00)
401 {
402 std::copy(std::begin(DUALSHOCK2_ID[0]), std::end(DUALSHOCK2_ID[0]), m_outputBuffer.begin() + outputOffset + 0x04);
403 }
404 else
405 {
406 std::copy(std::begin(DUALSHOCK2_ID[1]), std::end(DUALSHOCK2_ID[1]), m_outputBuffer.begin() + outputOffset + 0x04);
407 }
408 CLog::GetInstance().Print(LOG_NAME, "Pad %d: QueryAct(mode = %d);\r\n", padId, m_inputBuffer[3]);
409 break;
410 case 0x47:
411 assert(dstSize == 9);
412 assert(padState.configMode);
413 std::copy(std::begin(DUALSHOCK2_ID[2]), std::end(DUALSHOCK2_ID[2]), m_outputBuffer.begin() + outputOffset + 0x04);
414 CLog::GetInstance().Print(LOG_NAME, "Pad %d: QueryComb();\r\n", padId);
415 break;
416 case 0x4C:
417 assert(dstSize == 9);
418 assert(padState.configMode);
419 if(m_inputBuffer[3] == 0x00)
420 {
421 std::copy(std::begin(DUALSHOCK2_ID[3]), std::end(DUALSHOCK2_ID[3]), m_outputBuffer.begin() + outputOffset + 0x04);
422 }
423 else
424 {
425 std::copy(std::begin(DUALSHOCK2_ID[4]), std::end(DUALSHOCK2_ID[4]), m_outputBuffer.begin() + outputOffset + 0x04);
426 }
427 CLog::GetInstance().Print(LOG_NAME, "Pad %d: QueryMode(mode = %d);\r\n", padId, m_inputBuffer[3]);
428 break;
429 case 0x4D: //SetVibration
430 assert(dstSize == 9);
431 CLog::GetInstance().Print(LOG_NAME, "Pad %d: SetVibration();\r\n", padId);
432 break;
433 case 0x4F: //SetPollMask
434 assert(dstSize == 9);
435 assert(padState.configMode);
436 padState.mode = ID_ANALOGP;
437 m_outputBuffer[outputOffset + 0x03] = 0x00;
438 m_outputBuffer[outputOffset + 0x04] = 0x00;
439 m_outputBuffer[outputOffset + 0x05] = 0x00;
440 m_outputBuffer[outputOffset + 0x06] = 0x00;
441 m_outputBuffer[outputOffset + 0x07] = 0x00;
442 m_outputBuffer[outputOffset + 0x08] = 0x5A;
443 padState.pollMask[0] = m_inputBuffer[3];
444 padState.pollMask[1] = m_inputBuffer[4];
445 padState.pollMask[2] = m_inputBuffer[5];
446 CLog::GetInstance().Print(LOG_NAME, "Pad %d: SetPollMask(mask = { 0x%02X, 0x%02X, 0x%02X });\r\n",
447 padId, padState.pollMask[0], padState.pollMask[1], padState.pollMask[2]);
448 break;
449 default:
450 CLog::GetInstance().Print(LOG_NAME, "Pad %d: Unknown command received (0x%02X).\r\n", padId, cmd);
451 break;
452 }
453 }
454 else
455 {
456 CLog::GetInstance().Print(LOG_NAME, "Sending command to unsupported pad (%d).\r\n", portId);
457 }
458 }
459
ProcessMultitap(unsigned int portId,size_t outputOffset,uint32 dstSize,uint32 srcSize)460 void CSio2::ProcessMultitap(unsigned int portId, size_t outputOffset, uint32 dstSize, uint32 srcSize)
461 {
462 uint8 cmd = m_inputBuffer[1];
463 switch(cmd)
464 {
465 case 0x12:
466 case 0x13:
467 //GetSlotNumber
468 m_outputBuffer[outputOffset + 0x03] = 1;
469 CLog::GetInstance().Print(LOG_NAME, "Multitap: GetSlotNumber();\r\n");
470 break;
471 case 0x21:
472 case 0x22:
473 //ChangeSlot
474 m_outputBuffer[outputOffset + 0x05] = 0;
475 CLog::GetInstance().Print(LOG_NAME, "Multitap: ChangeSlot();\r\n");
476 break;
477 }
478 }
479
ComputeEDC(const std::deque<uint8> & bytes,uint32 offset,uint32 size)480 static uint8 ComputeEDC(const std::deque<uint8>& bytes, uint32 offset, uint32 size)
481 {
482 uint8 checksum = 0;
483 for(uint32 i = 0; i < size; i++)
484 {
485 checksum ^= bytes.at(offset + i);
486 }
487 return static_cast<uint8>(checksum);
488 }
489
ProcessMemoryCard(unsigned int portId,size_t outputOffset,uint32 dstSize,uint32 srcSize)490 void CSio2::ProcessMemoryCard(unsigned int portId, size_t outputOffset, uint32 dstSize, uint32 srcSize)
491 {
492 static uint8 g_terminationCode = 0x55;
493 static uint32 g_currentPage = 0;
494 static const uint16 pageSize = 0x200;
495 static const uint16 rawPageSize = 0x210;
496 uint8 cmd = m_inputBuffer[1];
497 switch(cmd)
498 {
499 case 0x11:
500 m_outputBuffer[outputOffset + 0x03] = g_terminationCode;
501 CLog::GetInstance().Print(LOG_NAME, "MemoryCard: CardChanged();\r\n");
502 break;
503 case 0x12:
504 //Erase page?
505 m_outputBuffer[outputOffset + 0x03] = g_terminationCode;
506 CLog::GetInstance().Print(LOG_NAME, "MemoryCard: Cmd_12();\r\n");
507 break;
508 case 0x21:
509 //Erase page?
510 m_outputBuffer[outputOffset + 0x08] = g_terminationCode;
511 CLog::GetInstance().Print(LOG_NAME, "MemoryCard: Cmd_21();\r\n");
512 break;
513 case 0x22:
514 //Write page?
515 m_outputBuffer[outputOffset + 0x08] = g_terminationCode;
516 CLog::GetInstance().Print(LOG_NAME, "MemoryCard: Cmd_22();\r\n");
517 break;
518 case 0x23:
519 {
520 uint32 page = (m_inputBuffer[3] << 8) | m_inputBuffer[2];
521 g_currentPage = page;
522 }
523 m_outputBuffer[outputOffset + 0x08] = g_terminationCode;
524 CLog::GetInstance().Print(LOG_NAME, "MemoryCard: SeekPage();\r\n");
525 break;
526 case 0x26:
527 m_outputBuffer[outputOffset + 0x02] = 0; //flags
528 m_outputBuffer[outputOffset + 0x03] = static_cast<uint8>(pageSize); //pageSizeLo
529 m_outputBuffer[outputOffset + 0x04] = static_cast<uint8>(pageSize >> 8); //pageSizeHi (512 bytes)
530 m_outputBuffer[outputOffset + 0x05] = 0; //blockSizeLo
531 m_outputBuffer[outputOffset + 0x06] = 0x20; //blockSizeHi
532 m_outputBuffer[outputOffset + 0x07] = 0; //cardSize0
533 m_outputBuffer[outputOffset + 0x08] = 0; //cardSize1
534 m_outputBuffer[outputOffset + 0x09] = 0x80; //cardSize2
535 m_outputBuffer[outputOffset + 0x0A] = 0; //cardSize3
536 m_outputBuffer[outputOffset + 0x0B] = ComputeEDC(m_outputBuffer, outputOffset + 3, 8);
537 m_outputBuffer[outputOffset + 0x0C] = g_terminationCode;
538 CLog::GetInstance().Print(LOG_NAME, "MemoryCard: GetCardSpec();\r\n");
539 break;
540 case 0x27:
541 g_terminationCode = m_inputBuffer[2];
542 m_outputBuffer[outputOffset + 0x04] = g_terminationCode;
543 CLog::GetInstance().Print(LOG_NAME, "MemoryCard: Probe2();\r\n");
544 break;
545 case 0x28:
546 m_outputBuffer[outputOffset + 0x04] = 0x66;
547 CLog::GetInstance().Print(LOG_NAME, "MemoryCard: Probe1();\r\n");
548 break;
549 case 0x42:
550 {
551 uint8 writeCount = m_inputBuffer[2];
552 m_outputBuffer[outputOffset + writeCount + 0x05] = g_terminationCode;
553 }
554 CLog::GetInstance().Print(LOG_NAME, "MemoryCard: WritePage();\r\n");
555 break;
556 case 0x43:
557 {
558 uint8 readCount = m_inputBuffer[2];
559 for(uint32 i = 0; i < readCount; i++)
560 {
561 m_outputBuffer[outputOffset + 0x04 + i] = 0xCC;
562 }
563 g_currentPage += 1;
564 m_outputBuffer[outputOffset + 0x04 + readCount + 0] = ComputeEDC(m_outputBuffer, outputOffset + 0x04, readCount);
565 m_outputBuffer[outputOffset + 0x04 + readCount + 1] = g_terminationCode;
566 }
567 CLog::GetInstance().Print(LOG_NAME, "MemoryCard: ReadPage();\r\n");
568 break;
569 case 0x81:
570 m_outputBuffer[outputOffset + 0x03] = g_terminationCode;
571 CLog::GetInstance().Print(LOG_NAME, "MemoryCard: Cmd_81();\r\n");
572 break;
573 case 0x82:
574 m_outputBuffer[outputOffset + 0x03] = g_terminationCode;
575 CLog::GetInstance().Print(LOG_NAME, "MemoryCard: Cmd_82();\r\n");
576 break;
577 case 0xBF:
578 m_outputBuffer[outputOffset + 0x04] = g_terminationCode;
579 CLog::GetInstance().Print(LOG_NAME, "MemoryCard: Cmd_BF();\r\n");
580 break;
581 case 0xF3:
582 m_outputBuffer[outputOffset + 0x03] = 0x2B;
583 CLog::GetInstance().Print(LOG_NAME, "MemoryCard: ResetAuth();\r\n");
584 break;
585 default:
586 assert(false);
587 break;
588 }
589 }
590
DisassembleRead(uint32 address,uint32 value)591 void CSio2::DisassembleRead(uint32 address, uint32 value)
592 {
593 switch(address)
594 {
595 case REG_DATA_IN:
596 CLog::GetInstance().Print(LOG_NAME, "= DATA_IN = 0x%08X\r\n", value);
597 break;
598 case REG_CTRL:
599 CLog::GetInstance().Print(LOG_NAME, "= REG_CTRL = 0x%08X\r\n", value);
600 break;
601 default:
602 CLog::GetInstance().Print(LOG_NAME, "Read an unknown register 0x%08X.\r\n", address);
603 break;
604 }
605 }
606
DisassembleWrite(uint32 address,uint32 value)607 void CSio2::DisassembleWrite(uint32 address, uint32 value)
608 {
609 switch(address)
610 {
611 case REG_PORT0_CTRL1:
612 CLog::GetInstance().Print(LOG_NAME, "REG_PORT0_CTRL1 = 0x%08X\r\n", value);
613 break;
614 case REG_PORT0_CTRL2:
615 CLog::GetInstance().Print(LOG_NAME, "REG_PORT0_CTRL2 = 0x%08X\r\n", value);
616 break;
617 case REG_PORT1_CTRL1:
618 CLog::GetInstance().Print(LOG_NAME, "REG_PORT1_CTRL1 = 0x%08X\r\n", value);
619 break;
620 case REG_PORT1_CTRL2:
621 CLog::GetInstance().Print(LOG_NAME, "REG_PORT1_CTRL2 = 0x%08X\r\n", value);
622 break;
623 case REG_PORT2_CTRL1:
624 CLog::GetInstance().Print(LOG_NAME, "REG_PORT2_CTRL1 = 0x%08X\r\n", value);
625 break;
626 case REG_PORT2_CTRL2:
627 CLog::GetInstance().Print(LOG_NAME, "REG_PORT2_CTRL2 = 0x%08X\r\n", value);
628 break;
629 case REG_PORT3_CTRL1:
630 CLog::GetInstance().Print(LOG_NAME, "REG_PORT3_CTRL1 = 0x%08X\r\n", value);
631 break;
632 case REG_PORT3_CTRL2:
633 CLog::GetInstance().Print(LOG_NAME, "REG_PORT3_CTRL2 = 0x%08X\r\n", value);
634 break;
635 case REG_DATA_OUT:
636 CLog::GetInstance().Print(LOG_NAME, "DATA_OUT = 0x%08X\r\n", value);
637 break;
638 case REG_CTRL:
639 CLog::GetInstance().Print(LOG_NAME, "CTRL = 0x%08X\r\n", value);
640 break;
641 default:
642 CLog::GetInstance().Print(LOG_NAME, "Write 0x%08X to an unknown register 0x%08X.\r\n", value, address);
643 break;
644 }
645 }
646