Bug Summary

File:Source/Core/Core/Src/HW/SI_DeviceAMBaseboard.cpp
Location:line 255, column 9
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
19
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
20
Control jumps to 'case 79:' at line 233
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 true. Entering loop body
13
Loop condition is true. Entering loop body
14
Loop condition is false. Execution continues on line 248
21
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];
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))
15
Loop condition is false. Execution continues on line 373
22
Loop condition is true. Entering loop body
253 {
254
255 int cmd = *jvs_io++;
23
Assigned value is garbage or undefined
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)
16
Assuming 'i' is >= 'len'
17
Loop condition is false. Execution continues on line 382
381 res[resp++] = buf[i];
382 break;
18
Execution continues on line 391
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}