Bug Summary

File:Source/Core/Core/Src/HW/SI_DeviceGCController.cpp
Location:line 67, column 24
Description:The left operand of '>>' is a garbage value

Annotated Source Code

1// Copyright 2013 Dolphin Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#include <stdio.h>
6#include <stdlib.h>
7
8#include "SI.h"
9#include "SI_Device.h"
10#include "SI_DeviceGCController.h"
11
12#include "EXI_Device.h"
13#include "EXI_DeviceMic.h"
14
15#include "GCPad.h"
16
17#include "../Movie.h"
18
19#include "../CoreTiming.h"
20#include "SystemTimers.h"
21#include "ProcessorInterface.h"
22#include "../Core.h"
23
24// --- standard gamecube controller ---
25CSIDevice_GCController::CSIDevice_GCController(SIDevices device, int _iDeviceNumber)
26 : ISIDevice(device, _iDeviceNumber)
27 , m_TButtonComboStart(0)
28 , m_TButtonCombo(0)
29 , m_LastButtonCombo(COMBO_NONE)
30{
31 memset(&m_Origin, 0, sizeof(SOrigin));
32 m_Origin.uCommand = CMD_ORIGIN;
33 m_Origin.uOriginStickX = 0x80; // center
34 m_Origin.uOriginStickY = 0x80;
35 m_Origin.uSubStickStickX = 0x80;
36 m_Origin.uSubStickStickY = 0x80;
37 m_Origin.uTrigger_L = 0x1F; // 0-30 is the lower deadzone
38 m_Origin.uTrigger_R = 0x1F;
39
40 // Dunno if we need to do this, game/lib should set it?
41 m_Mode = 0x03;
42}
43
44int CSIDevice_GCController::RunBuffer(u8* _pBuffer, int _iLength)
45{
46 // For debug logging only
47 ISIDevice::RunBuffer(_pBuffer, _iLength);
48
49 // Read the command
50 EBufferCommands command = static_cast<EBufferCommands>(_pBuffer[3]);
51
52 // Handle it
53 switch (command)
1
Control jumps to 'case CMD_DIRECT:' at line 59
54 {
55 case CMD_RESET:
56 *(u32*)&_pBuffer[0] = SI_GC_CONTROLLER;
57 break;
58
59 case CMD_DIRECT:
60 {
61 INFO_LOG(SERIALINTERFACE, "PAD - Direct (Length: %d)", _iLength)do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO
, LogTypes::SERIALINTERFACE, "/home/anal/dolphin-emu/Source/Core/Core/Src/HW/SI_DeviceGCController.cpp"
, 61, "PAD - Direct (Length: %d)", _iLength); } } while (0)
;
62 u32 high, low;
2
Variable 'low' declared without an initial value
63 GetData(high, low);
3
Calling 'GetData'
15
Returning from 'GetData'
64 for (int i = 0; i < (_iLength - 1) / 2; i++)
16
Loop condition is true. Entering loop body
65 {
66 _pBuffer[0 + i] = (high >> (i * 8)) & 0xff;
67 _pBuffer[4 + i] = (low >> (i * 8)) & 0xff;
17
The left operand of '>>' is a garbage value
68 }
69 }
70 break;
71
72 case CMD_ORIGIN:
73 {
74 INFO_LOG(SERIALINTERFACE, "PAD - Get Origin")do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO
, LogTypes::SERIALINTERFACE, "/home/anal/dolphin-emu/Source/Core/Core/Src/HW/SI_DeviceGCController.cpp"
, 74, "PAD - Get Origin"); } } while (0)
;
75 u8* pCalibration = reinterpret_cast<u8*>(&m_Origin);
76 for (int i = 0; i < (int)sizeof(SOrigin); i++)
77 {
78 _pBuffer[i ^ 3] = *pCalibration++;
79 }
80 }
81 break;
82
83 // Recalibrate (FiRES: i am not 100 percent sure about this)
84 case CMD_RECALIBRATE:
85 {
86 INFO_LOG(SERIALINTERFACE, "PAD - Recalibrate")do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO
, LogTypes::SERIALINTERFACE, "/home/anal/dolphin-emu/Source/Core/Core/Src/HW/SI_DeviceGCController.cpp"
, 86, "PAD - Recalibrate"); } } while (0)
;
87 u8* pCalibration = reinterpret_cast<u8*>(&m_Origin);
88 for (int i = 0; i < (int)sizeof(SOrigin); i++)
89 {
90 _pBuffer[i ^ 3] = *pCalibration++;
91 }
92 }
93 break;
94
95 // DEFAULT
96 default:
97 {
98 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_DeviceGCController.cpp"
, 98, "Unknown SI command (0x%x)", command); } } while (0
)
;
99 PanicAlert("SI: Unknown command (0x%x)", command)MsgAlert(false, WARNING, "SI: Unknown command (0x%x)", command
)
;
100 }
101 break;
102 }
103
104 return _iLength;
105}
106
107
108// GetData
109
110// Return true on new data (max 7 Bytes and 6 bits ;)
111// [00?SYXBA] [1LRZUDRL] [x] [y] [cx] [cy] [l] [r]
112// |\_ ERR_LATCH (error latched - check SISR)
113// |_ ERR_STATUS (error on last GetData or SendCmd?)
114bool CSIDevice_GCController::GetData(u32& _Hi, u32& _Low)
115{
116 SPADStatus PadStatus;
117 memset(&PadStatus, 0, sizeof(PadStatus));
118
119 Pad::GetStatus(ISIDevice::m_iDeviceNumber, &PadStatus);
120 Movie::CallInputManip(&PadStatus, ISIDevice::m_iDeviceNumber);
121
122 u32 netValues[2];
123 if (NetPlay_GetInput(ISIDevice::m_iDeviceNumber, PadStatus, netValues))
4
Taking false branch
124 {
125 _Hi = netValues[0]; // first 4 bytes
126 _Low = netValues[1]; // last 4 bytes
127 return true;
128 }
129
130 Movie::SetPolledDevice();
131
132 if(Movie::IsPlayingInput())
5
Taking true branch
133 {
134 Movie::PlayController(&PadStatus, ISIDevice::m_iDeviceNumber);
135 Movie::InputUpdate();
136 }
137 else if(Movie::IsRecordingInput())
138 {
139 Movie::RecordInput(&PadStatus, ISIDevice::m_iDeviceNumber);
140 Movie::InputUpdate();
141 }
142 else
143 {
144 Movie::CheckPadStatus(&PadStatus, ISIDevice::m_iDeviceNumber);
145 }
146
147 // Thankfully changing mode does not change the high bits ;)
148 _Hi = (u32)((u8)PadStatus.stickY);
149 _Hi |= (u32)((u8)PadStatus.stickX << 8);
150 _Hi |= (u32)((u16)(PadStatus.button | PAD_USE_ORIGIN0x0080) << 16);
151
152 // Low bits are packed differently per mode
153 if (m_Mode == 0 || m_Mode == 5 || m_Mode == 6 || m_Mode == 7)
6
Taking false branch
154 {
155 _Low = (u8)(PadStatus.analogB >> 4); // Top 4 bits
156 _Low |= (u32)((u8)(PadStatus.analogA >> 4) << 4); // Top 4 bits
157 _Low |= (u32)((u8)(PadStatus.triggerRight >> 4) << 8); // Top 4 bits
158 _Low |= (u32)((u8)(PadStatus.triggerLeft >> 4) << 12); // Top 4 bits
159 _Low |= (u32)((u8)(PadStatus.substickY) << 16); // All 8 bits
160 _Low |= (u32)((u8)(PadStatus.substickX) << 24); // All 8 bits
161 }
162 else if (m_Mode == 1)
7
Taking false branch
163 {
164 _Low = (u8)(PadStatus.analogB >> 4); // Top 4 bits
165 _Low |= (u32)((u8)(PadStatus.analogA >> 4) << 4); // Top 4 bits
166 _Low |= (u32)((u8)PadStatus.triggerRight << 8); // All 8 bits
167 _Low |= (u32)((u8)PadStatus.triggerLeft << 16); // All 8 bits
168 _Low |= (u32)((u8)PadStatus.substickY << 24); // Top 4 bits
169 _Low |= (u32)((u8)PadStatus.substickX << 28); // Top 4 bits
170 }
171 else if (m_Mode == 2)
8
Taking false branch
172 {
173 _Low = (u8)(PadStatus.analogB); // All 8 bits
174 _Low |= (u32)((u8)(PadStatus.analogA) << 8); // All 8 bits
175 _Low |= (u32)((u8)(PadStatus.triggerRight >> 4) << 16); // Top 4 bits
176 _Low |= (u32)((u8)(PadStatus.triggerLeft >> 4) << 20); // Top 4 bits
177 _Low |= (u32)((u8)PadStatus.substickY << 24); // Top 4 bits
178 _Low |= (u32)((u8)PadStatus.substickX << 28); // Top 4 bits
179 }
180 else if (m_Mode == 3)
9
Taking false branch
181 {
182 // Analog A/B are always 0
183 _Low = (u8)PadStatus.triggerRight; // All 8 bits
184 _Low |= (u32)((u8)PadStatus.triggerLeft << 8); // All 8 bits
185 _Low |= (u32)((u8)PadStatus.substickY << 16); // All 8 bits
186 _Low |= (u32)((u8)PadStatus.substickX << 24); // All 8 bits
187 }
188 else if (m_Mode == 4)
10
Taking false branch
189 {
190 _Low = (u8)(PadStatus.analogB); // All 8 bits
191 _Low |= (u32)((u8)(PadStatus.analogA) << 8); // All 8 bits
192 // triggerLeft/Right are always 0
193 _Low |= (u32)((u8)PadStatus.substickY << 16); // All 8 bits
194 _Low |= (u32)((u8)PadStatus.substickX << 24); // All 8 bits
195 }
196
197 // Keep track of the special button combos (embedded in controller hardware... :( )
198 EButtonCombo tempCombo;
199 if ((PadStatus.button & 0xff00) == (PAD_BUTTON_Y0x0800|PAD_BUTTON_X0x0400|PAD_BUTTON_START0x1000))
11
Taking false branch
200 tempCombo = COMBO_ORIGIN;
201 else if ((PadStatus.button & 0xff00) == (PAD_BUTTON_B0x0200|PAD_BUTTON_X0x0400|PAD_BUTTON_START0x1000))
12
Taking false branch
202 tempCombo = COMBO_RESET;
203 else
204 tempCombo = COMBO_NONE;
205 if (tempCombo != m_LastButtonCombo)
13
Taking false branch
206 {
207 m_LastButtonCombo = tempCombo;
208 if (m_LastButtonCombo != COMBO_NONE)
209 m_TButtonComboStart = CoreTiming::GetTicks();
210 }
211 if (m_LastButtonCombo != COMBO_NONE)
14
Taking false branch
212 {
213 m_TButtonCombo = CoreTiming::GetTicks();
214 if ((m_TButtonCombo - m_TButtonComboStart) > SystemTimers::GetTicksPerSecond() * 3)
215 {
216 if (m_LastButtonCombo == COMBO_RESET)
217 ProcessorInterface::ResetButton_Tap();
218 else if (m_LastButtonCombo == COMBO_ORIGIN)
219 {
220 m_Origin.uOriginStickX = PadStatus.stickX;
221 m_Origin.uOriginStickY = PadStatus.stickY;
222 m_Origin.uSubStickStickX = PadStatus.substickX;
223 m_Origin.uSubStickStickY = PadStatus.substickY;
224 m_Origin.uTrigger_L = PadStatus.triggerLeft;
225 m_Origin.uTrigger_R = PadStatus.triggerRight;
226 }
227 m_LastButtonCombo = COMBO_NONE;
228 }
229 }
230
231 return true;
232}
233
234
235// SendCommand
236void CSIDevice_GCController::SendCommand(u32 _Cmd, u8 _Poll)
237{
238 UCommand command(_Cmd);
239
240 switch (command.Command)
241 {
242 // Costis sent it in some demos :)
243 case 0x00:
244 break;
245
246 case CMD_WRITE:
247 {
248 unsigned int uType = command.Parameter1; // 0 = stop, 1 = rumble, 2 = stop hard
249 unsigned int uStrength = command.Parameter2;
250
251 // get the correct pad number that should rumble locally when using netplay
252 const u8 numPAD = NetPlay_GetPadNum(ISIDevice::m_iDeviceNumber);
253
254 if (numPAD < 4)
255 Pad::Rumble(numPAD, uType, uStrength);
256
257 if (!_Poll)
258 {
259 m_Mode = command.Parameter2;
260 INFO_LOG(SERIALINTERFACE, "PAD %i set to mode %i", ISIDevice::m_iDeviceNumber, m_Mode)do { { if (LogTypes::LINFO <= 3) GenericLog(LogTypes::LINFO
, LogTypes::SERIALINTERFACE, "/home/anal/dolphin-emu/Source/Core/Core/Src/HW/SI_DeviceGCController.cpp"
, 260, "PAD %i set to mode %i", ISIDevice::m_iDeviceNumber, m_Mode
); } } while (0)
;
261 }
262 }
263 break;
264
265 default:
266 {
267 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_DeviceGCController.cpp"
, 267, "Unknown direct command (0x%x)", _Cmd); } } while (
0)
;
268 PanicAlert("SI: Unknown direct command")MsgAlert(false, WARNING, "SI: Unknown direct command");
269 }
270 break;
271 }
272}
273
274// Savestate support
275void CSIDevice_GCController::DoState(PointerWrap& p)
276{
277 p.Do(m_Origin);
278 p.Do(m_Mode);
279 p.Do(m_TButtonComboStart);
280 p.Do(m_TButtonCombo);
281 p.Do(m_LastButtonCombo);
282}