Bug Summary

File:Source/Core/Core/Src/HW/SI_DeviceAMBaseboard.cpp
Location:line 248, column 8
Description:Assigned value is garbage or undefined

Annotated Source Code

1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5
6#include "SI.h"
7#include "SI_Device.h"
8#include "SI_DeviceAMBaseboard.h"
9
10#include "GCPadStatus.h"
11#include "GCPad.h"
12
13// where to put baseboard debug
14#define AMBASEBOARDDEBUGOSREPORT OSREPORT
15
16// "JAMMA Video Standard" I/O
17class JVSIOMessage
18{
19public:
20 int m_ptr, m_last_start, m_csum;
21 unsigned char m_msg[0x80];
22
23 JVSIOMessage()
24 {
25 m_ptr = 0;
26 m_last_start = 0;
27 }
28
29 void start(int node)
30 {
31 m_last_start = m_ptr;
32 unsigned char hdr[3] = {0xe0, (unsigned char)node, 0};
33 m_csum = 0;
34 addData(hdr, 3, 1);
35 }
36 void addData(const void *data, size_t len)
37 {
38 addData((const unsigned char*)data, len);
39 }
40 void addData(const char *data)
41 {
42 addData(data, strlen(data));
43 }
44 void addData(int n)
45 {
46 unsigned char cs = n;
47 addData(&cs, 1);
48 }
49
50 void end()
51 {
52 int len = m_ptr - m_last_start;
53 m_msg[m_last_start + 2] = len - 2; // assuming len <0xD0
54 addData(m_csum + len - 2);
55 }
56
57 void addData(const unsigned char *dst, size_t len, int sync = 0)
58 {
59 while (len--)
60 {
61 int c = *dst++;
62 if (!sync && ((c == 0xE0) || (c == 0xD0)))
63 {
64 m_msg[m_ptr++] = 0xD0;
65 m_msg[m_ptr++] = c - 1;
66 }
67 else
68 {
69 m_msg[m_ptr++] = c;
70 }
71
72 if (!sync)
73 m_csum += c;
74 sync = 0;
75 if (m_ptr >= 0x80)
76 PanicAlert("JVSIOMessage overrun!")MsgAlert(false, WARNING, "JVSIOMessage overrun!");
77 }
78 }
79}; // end class JVSIOMessage
80
81
82// AM-Baseboard device on SI
83CSIDevice_AMBaseboard::CSIDevice_AMBaseboard(SIDevices device, int _iDeviceNumber)
84 : ISIDevice(device, _iDeviceNumber)
85{
86}
87
88int CSIDevice_AMBaseboard::RunBuffer(u8* _pBuffer, int _iLength)
89{
90 // for debug logging only
91 ISIDevice::RunBuffer(_pBuffer, _iLength);
92
93 int iPosition = 0;
94 while(iPosition < _iLength)
1
Assuming 'iPosition' is < '_iLength'
2
Loop condition is true. Entering loop body
95 {
96 // read the command
97 EBufferCommands command = static_cast<EBufferCommands>(_pBuffer[iPosition ^ 3]);
98 iPosition++;
99
100 // handle it
101 switch(command)
3
Control jumps to 'case CMD_GCAM:' at line 109
102 {
103 case CMD_RESET: // returns ID and dip switches
104 {
105 *(u32*)&_pBuffer[0] = SI_AM_BASEBOARD|0x100; // 0x100 is progressive flag according to dip switch
106 iPosition = _iLength; // break the while loop
107 }
108 break;
109 case CMD_GCAM:
110 {
111 int i;
112
113 // calculate checksum over buffer
114 int csum = 0;
115 for (i=0; i<_iLength; ++i)
4
Loop condition is true. Entering loop body
5
Assuming 'i' is >= '_iLength'
6
Loop condition is false. Execution continues on line 118
116 csum += _pBuffer[i];
117
118 unsigned char res[0x80];
119 int resp = 0;
120
121 int real_len = _pBuffer[1^3];
122 int p = 2;
123
124 static int d10_1 = 0xfe;
125
126 memset(res, 0, 0x80);
127 res[resp++] = 1;
128 res[resp++] = 1;
129
130#define ptr(x) _pBuffer[(p + x)^3]
131 while (p < real_len+2)
7
Loop condition is true. Entering loop body
10
Loop condition is true. Entering loop body
132 {
133 switch (ptr(0))
8
Control jumps to the 'default' case at line 387
11
Control jumps to 'case 64:' at line 218
134 {
135 case 0x10:
136 {
137 DEBUG_LOG(AMBASEBOARDDEBUG, "GC-AM: Command 10, %02x (READ STATUS&SWITCHES)", ptr(1))do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG
, LogTypes::OSREPORT, "/home/anal/dolphin-emu/Source/Core/Core/Src/HW/SI_DeviceAMBaseboard.cpp"
, 137, "GC-AM: Command 10, %02x (READ STATUS&SWITCHES)", ptr
(1)); } } while (0)
;
138 SPADStatus PadStatus;
139 memset(&PadStatus, 0 ,sizeof(PadStatus));
140 Pad::GetStatus(ISIDevice::m_iDeviceNumber, &PadStatus);
141 res[resp++] = 0x10;
142 res[resp++] = 0x2;
143 int d10_0 = 0xdf;
144
145 if (PadStatus.triggerLeft)
146 d10_0 &= ~0x80;
147 if (PadStatus.triggerRight)
148 d10_0 &= ~0x40;
149
150 res[resp++] = d10_0;
151 res[resp++] = d10_1;
152 break;
153 }
154 case 0x12:
155 ERROR_LOG(AMBASEBOARDDEBUG, "GC-AM: Command 12, %02x %02x", ptr(1), ptr(2))do { { if (LogTypes::LERROR <= 3) GenericLog(LogTypes::LERROR
, LogTypes::OSREPORT, "/home/anal/dolphin-emu/Source/Core/Core/Src/HW/SI_DeviceAMBaseboard.cpp"
, 155, "GC-AM: Command 12, %02x %02x", ptr(1), ptr(2)); } } while
(0)
;
156 res[resp++] = 0x12;
157 res[resp++] = 0x00;
158 break;
159 case 0x11:
160 {
161 ERROR_LOG(AMBASEBOARDDEBUG, "GC-AM: Command 11, %02x (READ SERIAL NR)", ptr(1))do { { if (LogTypes::LERROR <= 3) GenericLog(LogTypes::LERROR
, LogTypes::OSREPORT, "/home/anal/dolphin-emu/Source/Core/Core/Src/HW/SI_DeviceAMBaseboard.cpp"
, 161, "GC-AM: Command 11, %02x (READ SERIAL NR)", ptr(1)); }
} while (0)
;
162 char string[] = "AADE-01A14964511";
163 res[resp++] = 0x11;
164 res[resp++] = 0x10;
165 memcpy(res + resp, string, 0x10);
166 resp += 0x10;
167 break;
168 }
169 case 0x15:
170 ERROR_LOG(AMBASEBOARDDEBUG, "GC-AM: CMD 15, %02x (READ FIRM VERSION)", ptr(1))do { { if (LogTypes::LERROR <= 3) GenericLog(LogTypes::LERROR
, LogTypes::OSREPORT, "/home/anal/dolphin-emu/Source/Core/Core/Src/HW/SI_DeviceAMBaseboard.cpp"
, 170, "GC-AM: CMD 15, %02x (READ FIRM VERSION)", ptr(1)); } }
while (0)
;
171 res[resp++] = 0x15;
172 res[resp++] = 0x02;
173 res[resp++] = 0x00;
174 res[resp++] = 0x29; // FIRM VERSION
175 break;
176 case 0x16:
177 ERROR_LOG(AMBASEBOARDDEBUG, "GC-AM: Command 16, %02x (READ FPGA VERSION)", ptr(1))do { { if (LogTypes::LERROR <= 3) GenericLog(LogTypes::LERROR
, LogTypes::OSREPORT, "/home/anal/dolphin-emu/Source/Core/Core/Src/HW/SI_DeviceAMBaseboard.cpp"
, 177, "GC-AM: Command 16, %02x (READ FPGA VERSION)", ptr(1))
; } } while (0)
;
178 res[resp++] = 0x16;
179 res[resp++] = 0x02;
180 res[resp++] = 0x07;
181 res[resp++] = 0x06; // FPGAVERSION
182 /*
183 res[resp++] = 0x16;
184 res[resp++] = 0x00;
185 p += 2;
186 */
187 break;
188 case 0x1f:
189 {
190 ERROR_LOG(AMBASEBOARDDEBUG, "GC-AM: Command 1f, %02x %02x %02x %02x %02x (REGION)", ptr(1), ptr(2), ptr(3), ptr(4), ptr(5))do { { if (LogTypes::LERROR <= 3) GenericLog(LogTypes::LERROR
, LogTypes::OSREPORT, "/home/anal/dolphin-emu/Source/Core/Core/Src/HW/SI_DeviceAMBaseboard.cpp"
, 190, "GC-AM: Command 1f, %02x %02x %02x %02x %02x (REGION)"
, ptr(1), ptr(2), ptr(3), ptr(4), ptr(5)); } } while (0)
;
191 unsigned char string[] =
192 "\x00\x00\x30\x00"
193 //"\x01\xfe\x00\x00" // JAPAN
194 "\x02\xfd\x00\x00" // USA
195 //"\x03\xfc\x00\x00" // export
196 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff";
197 res[resp++] = 0x1f;
198 res[resp++] = 0x14;
199
200 for (i=0; i<0x14; ++i)
201 res[resp++] = string[i];
202 break;
203 }
204 case 0x31:
205 ERROR_LOG(AMBASEBOARDDEBUG, "GC-AM: Command 31 (UNKNOWN)")do { { if (LogTypes::LERROR <= 3) GenericLog(LogTypes::LERROR
, LogTypes::OSREPORT, "/home/anal/dolphin-emu/Source/Core/Core/Src/HW/SI_DeviceAMBaseboard.cpp"
, 205, "GC-AM: Command 31 (UNKNOWN)"); } } while (0)
;
206 res[resp++] = 0x31;
207 res[resp++] = 0x02;
208 res[resp++] = 0x00;
209 res[resp++] = 0x00;
210 break;
211 case 0x32:
212 ERROR_LOG(AMBASEBOARDDEBUG, "GC-AM: Command 32 (UNKNOWN)")do { { if (LogTypes::LERROR <= 3) GenericLog(LogTypes::LERROR
, LogTypes::OSREPORT, "/home/anal/dolphin-emu/Source/Core/Core/Src/HW/SI_DeviceAMBaseboard.cpp"
, 212, "GC-AM: Command 32 (UNKNOWN)"); } } while (0)
;
213 res[resp++] = 0x32;
214 res[resp++] = 0x02;
215 res[resp++] = 0x00;
216 res[resp++] = 0x00;
217 break;
218 case 0x40:
219 case 0x41:
220 case 0x42:
221 case 0x43:
222 case 0x44:
223 case 0x45:
224 case 0x46:
225 case 0x47:
226 case 0x48:
227 case 0x49:
228 case 0x4a:
229 case 0x4b:
230 case 0x4c:
231 case 0x4d:
232 case 0x4e:
233 case 0x4f:
234 {
235 DEBUG_LOG(AMBASEBOARDDEBUG, "GC-AM: Command %02x, %02x %02x %02x %02x %02x %02x %02x (JVS IO)",do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG
, LogTypes::OSREPORT, "/home/anal/dolphin-emu/Source/Core/Core/Src/HW/SI_DeviceAMBaseboard.cpp"
, 236, "GC-AM: Command %02x, %02x %02x %02x %02x %02x %02x %02x (JVS IO)"
, ptr(0), ptr(1), ptr(2), ptr(3), ptr(4), ptr(5), ptr(6), ptr
(7)); } } while (0)
236 ptr(0), ptr(1), ptr(2), ptr(3), ptr(4), ptr(5), ptr(6), ptr(7))do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG
, LogTypes::OSREPORT, "/home/anal/dolphin-emu/Source/Core/Core/Src/HW/SI_DeviceAMBaseboard.cpp"
, 236, "GC-AM: Command %02x, %02x %02x %02x %02x %02x %02x %02x (JVS IO)"
, ptr(0), ptr(1), ptr(2), ptr(3), ptr(4), ptr(5), ptr(6), ptr
(7)); } } while (0)
;
237 int pptr = 2;
238 JVSIOMessage msg;
239
240 msg.start(0);
241 msg.addData(1);
242
243 unsigned char jvs_io_buffer[0x80];
244 int nr_bytes = ptr(pptr + 2); // byte after e0 xx
245 int jvs_io_length = 0;
246 for (i=0; i<nr_bytes + 3; ++i)
12
Loop condition is false. Execution continues on line 248
247 jvs_io_buffer[jvs_io_length++] = ptr(pptr + i);
248 int node = jvs_io_buffer[1];
13
Assigned value is garbage or undefined
249
250 unsigned char *jvs_io = jvs_io_buffer + 3;
251 jvs_io_length--; // checksum
252 while (jvs_io < (jvs_io_buffer + jvs_io_length))
253 {
254
255 int cmd = *jvs_io++;
256 DEBUG_LOG(AMBASEBOARDDEBUG, "JVS IO, node=%d, command=%02x", node, cmd)do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG
, LogTypes::OSREPORT, "/home/anal/dolphin-emu/Source/Core/Core/Src/HW/SI_DeviceAMBaseboard.cpp"
, 256, "JVS IO, node=%d, command=%02x", node, cmd); } } while
(0)
;
257
258 switch (cmd)
259 {
260 case 0x10: // get ID
261 msg.addData(1);
262 {
263 char buffer[12];
264 sprintf(buffer, "JVS-node %02x", node);
265 //msg.addData(buffer);
266 msg.addData("JAMMA I/O CONTROLLER");
267 }
268 msg.addData(0);
269 break;
270 case 0x11: // cmd revision
271 msg.addData(1);
272 msg.addData(0x11);
273 break;
274 case 0x12: // jvs revision
275 msg.addData(1);
276 msg.addData(0x12);
277 break;
278 case 0x13: // com revision
279 msg.addData(1);
280 msg.addData(0x13);
281 break;
282 case 0x14: // get features
283 msg.addData(1);
284 msg.addData((void *)"\x01\x02\x0a\x00", 4); // 2 player, 10 bit
285 msg.addData((void *)"\x02\x02\x00\x00", 4); // 2 coin slots
286 //msg.addData((void *)"\x03\x02\x08\x00", 4);
287 msg.addData((void *)"\x00\x00\x00\x00", 4);
288 break;
289 case 0x15:
290 while (*jvs_io++) {};
291 msg.addData(1);
292 break;
293 case 0x20:
294 {
295 int nr_players = *jvs_io++;
296 int bytes_per_player = *jvs_io++; /* ??? */
297 int j;
298 msg.addData(1);
299
300 msg.addData(0); // tilt
301 for (i=0; i<nr_players; ++i)
302 {
303 SPADStatus PadStatus;
304 Pad::GetStatus(i, &PadStatus);
305 unsigned char player_data[2] = {0,0};
306 if (PadStatus.button & PAD_BUTTON_START0x1000)
307 player_data[0] |= 0x80;
308 if (PadStatus.button & PAD_BUTTON_UP0x0008)
309 player_data[0] |= 0x20;
310 if (PadStatus.button & PAD_BUTTON_DOWN0x0004)
311 player_data[0] |= 0x10;
312 if (PadStatus.button & PAD_BUTTON_LEFT0x0001)
313 player_data[0] |= 0x08;
314 if (PadStatus.button & PAD_BUTTON_RIGHT0x0002)
315 player_data[0] |= 0x04;
316
317 if (PadStatus.button & PAD_BUTTON_A0x0100)
318 player_data[0] |= 0x02;
319 if (PadStatus.button & PAD_BUTTON_B0x0200)
320 player_data[0] |= 0x01;
321
322 if (PadStatus.button & PAD_BUTTON_X0x0400)
323 player_data[1] |= 0x80;
324 if (PadStatus.button & PAD_BUTTON_Y0x0800)
325 player_data[1] |= 0x40;
326 if (PadStatus.button & PAD_TRIGGER_L0x0040)
327 player_data[1] |= 0x20;
328 if (PadStatus.button & PAD_TRIGGER_R0x0020)
329 player_data[1] |= 0x10;
330
331 for (j=0; j<bytes_per_player; ++j)
332 msg.addData(player_data[j&1]);
333 }
334 break;
335 }
336 case 0x21: // coin
337 {
338 int slots = *jvs_io++;
339 msg.addData(1);
340 SPADStatus PadStatus;
341 Pad::GetStatus(0, &PadStatus);
342 while (slots--)
343 {
344 msg.addData(0);
345 msg.addData((PadStatus.button & PAD_BUTTON_START0x1000) ? 1 : 0);
346 }
347 break;
348 }
349 case 0x22: // analog
350 {
351 break;
352 }
353 case 0xf0:
354 if (*jvs_io++ == 0xD9)
355 ERROR_LOG(AMBASEBOARDDEBUG, "JVS RESET")do { { if (LogTypes::LERROR <= 3) GenericLog(LogTypes::LERROR
, LogTypes::OSREPORT, "/home/anal/dolphin-emu/Source/Core/Core/Src/HW/SI_DeviceAMBaseboard.cpp"
, 355, "JVS RESET"); } } while (0)
;
356 msg.addData(1);
357
358 d10_1 |= 1;
359 break;
360 case 0xf1:
361 node = *jvs_io++;
362 ERROR_LOG(AMBASEBOARDDEBUG, "JVS SET ADDRESS, node=%d", node)do { { if (LogTypes::LERROR <= 3) GenericLog(LogTypes::LERROR
, LogTypes::OSREPORT, "/home/anal/dolphin-emu/Source/Core/Core/Src/HW/SI_DeviceAMBaseboard.cpp"
, 362, "JVS SET ADDRESS, node=%d", node); } } while (0)
;
363 msg.addData(node == 1);
364 break;
365 default:
366 break;
367 }
368
369 pptr += jvs_io_length;
370
371 }
372
373 msg.end();
374
375 res[resp++] = ptr(0);
376
377 unsigned char *buf = msg.m_msg;
378 int len = msg.m_ptr;
379 res[resp++] = len;
380 for (i=0; i<len; ++i)
381 res[resp++] = buf[i];
382 break;
383 }
384 case 0x60:
385 ERROR_LOG(AMBASEBOARDDEBUG, "GC-AM: Command 60, %02x %02x %02x", ptr(1), ptr(2), ptr(3))do { { if (LogTypes::LERROR <= 3) GenericLog(LogTypes::LERROR
, LogTypes::OSREPORT, "/home/anal/dolphin-emu/Source/Core/Core/Src/HW/SI_DeviceAMBaseboard.cpp"
, 385, "GC-AM: Command 60, %02x %02x %02x", ptr(1), ptr(2), ptr
(3)); } } while (0)
;
386 break;
387 default:
388 ERROR_LOG(AMBASEBOARDDEBUG, "GC-AM: Command %02x (unknown) %02x %02x %02x %02x %02x", ptr(0), ptr(1), ptr(2), ptr(3), ptr(4), ptr(5))do { { if (LogTypes::LERROR <= 3) GenericLog(LogTypes::LERROR
, LogTypes::OSREPORT, "/home/anal/dolphin-emu/Source/Core/Core/Src/HW/SI_DeviceAMBaseboard.cpp"
, 388, "GC-AM: Command %02x (unknown) %02x %02x %02x %02x %02x"
, ptr(0), ptr(1), ptr(2), ptr(3), ptr(4), ptr(5)); } } while (
0)
;
389 break;
9
Execution continues on line 391
390 }
391 p += ptr(1) + 2;
392 }
393 memset(_pBuffer, 0, _iLength);
394
395 int len = resp - 2;
396
397 p = 0;
398 res[1] = len;
399 csum = 0;
400 char logptr[1024];
401 char *log = logptr;
402 for (i=0; i<0x7F; ++i)
403 {
404 csum += ptr(i) = res[i];
405 log += sprintf(log, "%02x ", ptr(i));
406 }
407 ptr(0x7f) = ~csum;
408 DEBUG_LOG(AMBASEBOARDDEBUG, "Command send back: %s", logptr)do { { if (LogTypes::LDEBUG <= 3) GenericLog(LogTypes::LDEBUG
, LogTypes::OSREPORT, "/home/anal/dolphin-emu/Source/Core/Core/Src/HW/SI_DeviceAMBaseboard.cpp"
, 408, "Command send back: %s", logptr); } } while (0)
;
409#undef ptr
410
411
412 // (tmbinc) hotfix: delay output by one command to work around their broken parser. this took me a month to find. ARG!
413 static unsigned char last[2][0x80];
414 static int lastptr[2];
415
416 {
417 memcpy(last + 1, _pBuffer, 0x80);
418 memcpy(_pBuffer, last, 0x80);
419 memcpy(last, last + 1, 0x80);
420
421 lastptr[1] = _iLength;
422 _iLength = lastptr[0];
423 lastptr[0] = lastptr[1];
424 }
425
426 iPosition = _iLength;
427 break;
428 }
429 // DEFAULT
430 default:
431 {
432 ERROR_LOG(SERIALINTERFACE, "Unknown SI command (0x%x)", command)do { { if (LogTypes::LERROR <= 3) GenericLog(LogTypes::LERROR
, LogTypes::SERIALINTERFACE, "/home/anal/dolphin-emu/Source/Core/Core/Src/HW/SI_DeviceAMBaseboard.cpp"
, 432, "Unknown SI command (0x%x)", command); } } while (
0)
;
433 PanicAlert("SI: Unknown command")MsgAlert(false, WARNING, "SI: Unknown command");
434 iPosition = _iLength;
435 }
436 break;
437 }
438 }
439
440 return iPosition;
441}
442
443// Not really used on GC-AM
444bool CSIDevice_AMBaseboard::GetData(u32& _Hi, u32& _Low)
445{
446 _Low = 0;
447 _Hi = 0x00800000;
448
449 return true;
450}
451
452void CSIDevice_AMBaseboard::SendCommand(u32 _Cmd, u8 _Poll)
453{
454 ERROR_LOG(SERIALINTERFACE, "Unknown direct command (0x%x)", _Cmd)do { { if (LogTypes::LERROR <= 3) GenericLog(LogTypes::LERROR
, LogTypes::SERIALINTERFACE, "/home/anal/dolphin-emu/Source/Core/Core/Src/HW/SI_DeviceAMBaseboard.cpp"
, 454, "Unknown direct command (0x%x)", _Cmd); } } while (
0)
;
455 PanicAlert("SI: (GCAM) Unknown direct command")MsgAlert(false, WARNING, "SI: (GCAM) Unknown direct command");
456}