Update svn:eol-style=native ( r1442 ) for Source/*.cpp

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2384 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
LPFaint99
2009-02-23 06:15:48 +00:00
parent 472582022b
commit 578c402d2c
41 changed files with 13757 additions and 13757 deletions

View File

@ -1,56 +1,56 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "ColorUtil.h"
namespace ColorUtil
{
const int lut5to8[] = { 0x00,0x08,0x10,0x18,0x20,0x29,0x31,0x39,
0x41,0x4A,0x52,0x5A,0x62,0x6A,0x73,0x7B,
0x83,0x8B,0x94,0x9C,0xA4,0xAC,0xB4,0xBD,
0xC5,0xCD,0xD5,0xDE,0xE6,0xEE,0xF6,0xFF };
const int lut4to8[] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,
0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF };
const int lut3to8[] = { 0x00,0x24,0x48,0x6D,0x91,0xB6,0xDA,0xFF };
u32 Decode5A3(u16 val)
{
const u32 bg_color = 0x00000000;
int r, g, b, a;
if (val & 0x8000)
{
r = lut5to8[(val >> 10) & 0x1f];
g = lut5to8[(val >> 5) & 0x1f];
b = lut5to8[(val) & 0x1f];
a = 0xFF;
}
else
{
a = lut3to8[(val >> 12) & 0x7];
r = (lut4to8[(val >> 8) & 0xf] * a + (bg_color & 0xFF) * (255 - a)) / 255;
g = (lut4to8[(val >> 4) & 0xf] * a + ((bg_color >> 8) & 0xFF) * (255 - a)) / 255;
b = (lut4to8[(val) & 0xf] * a + ((bg_color >> 16) & 0xFF) * (255 - a)) / 255;
a = 0xFF;
}
return (a << 24) | (r << 16) | (g << 8) | b;
}
} // namespace
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "ColorUtil.h"
namespace ColorUtil
{
const int lut5to8[] = { 0x00,0x08,0x10,0x18,0x20,0x29,0x31,0x39,
0x41,0x4A,0x52,0x5A,0x62,0x6A,0x73,0x7B,
0x83,0x8B,0x94,0x9C,0xA4,0xAC,0xB4,0xBD,
0xC5,0xCD,0xD5,0xDE,0xE6,0xEE,0xF6,0xFF };
const int lut4to8[] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,
0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF };
const int lut3to8[] = { 0x00,0x24,0x48,0x6D,0x91,0xB6,0xDA,0xFF };
u32 Decode5A3(u16 val)
{
const u32 bg_color = 0x00000000;
int r, g, b, a;
if (val & 0x8000)
{
r = lut5to8[(val >> 10) & 0x1f];
g = lut5to8[(val >> 5) & 0x1f];
b = lut5to8[(val) & 0x1f];
a = 0xFF;
}
else
{
a = lut3to8[(val >> 12) & 0x7];
r = (lut4to8[(val >> 8) & 0xf] * a + (bg_color & 0xFF) * (255 - a)) / 255;
g = (lut4to8[(val >> 4) & 0xf] * a + ((bg_color >> 8) & 0xFF) * (255 - a)) / 255;
b = (lut4to8[(val) & 0xf] * a + ((bg_color >> 16) & 0xFF) * (255 - a)) / 255;
a = 0xFF;
}
return (a << 24) | (r << 16) | (g << 8) | b;
}
} // namespace

View File

@ -1,198 +1,198 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// Includes
#include <string> // System: To be able to add strings with "+"
#include <stdio.h>
#ifdef _WIN32
#include <windows.h>
#else
#include <stdarg.h>
#endif
#include "Common.h"
#include "ConsoleWindow.h" // Common
// Declarations and definitions
namespace Console
{
// Create handles
FILE* __fStdOut = NULL;
#ifdef _WIN32
HANDLE __hStdOut = NULL;
#endif
/* Start console window - width and height is the size of console window, if you enable
File the output will also be written to this file. */
void Open(int Width, int Height, char * Name, bool File)
{
#ifdef _WIN32
// Open the console window and create the window handle for GetStdHandle()
AllocConsole();
// Save the window handle that AllocConsole() created
__hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
// Set the console window title
SetConsoleTitle(Name);
// Set the total letter space
COORD co = {Width, Height};
SetConsoleScreenBufferSize(__hStdOut, co);
/* Set the window size in number of letters. The height is hardcoded here because it can
be changed with MoveWindow() later */
SMALL_RECT coo = {0,0, (Width - 1),50}; // Top, left, right, bottom
SetConsoleWindowInfo(__hStdOut, TRUE, &coo);
#endif
// Create a file and a file handle if File is enabled and we don't already have a file handle
if(File && !__fStdOut)
{
// Edit the log file name
std::string FileEnding = ".log";
std::string FileName = Name;
std::string FullFilename = (FileName + FileEnding);
// Open the file handle
__fStdOut = fopen(FullFilename.c_str(), "w");
}
}
/* Close the console window and close the eventual file handle */
void Close()
{
#ifdef _WIN32
FreeConsole(); // Close the console window
#endif
if(__fStdOut) fclose(__fStdOut); // Close the file handle
}
// Print to screen and file
int Print(const char *fmt, ...)
{
// Maximum bytes, mind this value to avoid an overrun
static const int MAX_BYTES = 1024*20;
#if defined(_WIN32)
if(__hStdOut)
{
#endif
char s[MAX_BYTES];
va_list argptr;
int cnt; // To store the vsnprintf return message
va_start(argptr, fmt);
cnt = vsnprintf(s, MAX_BYTES, fmt, argptr);
va_end(argptr);
#if defined(_WIN32)
DWORD cCharsWritten; // We will get a value back here
WriteConsole(__hStdOut, s, (DWORD)strlen(s), &cCharsWritten, NULL);
#else
fprintf(stderr, "%s", s);
#endif
// Write to the file
if(__fStdOut)
{
fprintf(__fStdOut, "%s", s);
fflush(__fStdOut); // Write file now, don't wait
}
return(cnt);
#if defined(_WIN32)
} else
{
return 0;
}
#endif
}
// Clear console screen
void ClearScreen()
{
#if defined(_WIN32)
if(__hStdOut) // Check that we have a window handle
{
COORD coordScreen = { 0, 0 };
DWORD cCharsWritten;
CONSOLE_SCREEN_BUFFER_INFO csbi;
DWORD dwConSize;
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hConsole, &csbi);
dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize,
coordScreen, &cCharsWritten);
GetConsoleScreenBufferInfo(hConsole, &csbi);
FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize,
coordScreen, &cCharsWritten);
SetConsoleCursorPosition(hConsole, coordScreen);
}
#endif
}
/* Get window handle of console window to be able to resize it. We use
GetConsoleTitle() and FindWindow() to locate the console window handle. */
#if defined(_WIN32)
HWND GetHwnd(void)
{
#define MY_BUFSIZE 1024 // Buffer size for console window titles
HWND hwndFound; // This is what is returned to the caller
char pszNewWindowTitle[MY_BUFSIZE]; // Contains fabricated WindowTitle
char pszOldWindowTitle[MY_BUFSIZE]; // Contains original WindowTitle
// Fetch current window title.
GetConsoleTitle(pszOldWindowTitle, MY_BUFSIZE);
// Format a "unique" NewWindowTitle
wsprintf(pszNewWindowTitle, "%d/%d", GetTickCount(), GetCurrentProcessId());
// Change current window title
SetConsoleTitle(pszNewWindowTitle);
// Ensure window title has been updated
Sleep(40);
// Look for NewWindowTitle
hwndFound = FindWindow(NULL, pszNewWindowTitle);
// Restore original window title
SetConsoleTitle(pszOldWindowTitle);
return(hwndFound);
}
#endif // _WIN32
} // namespace
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// Includes
#include <string> // System: To be able to add strings with "+"
#include <stdio.h>
#ifdef _WIN32
#include <windows.h>
#else
#include <stdarg.h>
#endif
#include "Common.h"
#include "ConsoleWindow.h" // Common
// Declarations and definitions
namespace Console
{
// Create handles
FILE* __fStdOut = NULL;
#ifdef _WIN32
HANDLE __hStdOut = NULL;
#endif
/* Start console window - width and height is the size of console window, if you enable
File the output will also be written to this file. */
void Open(int Width, int Height, char * Name, bool File)
{
#ifdef _WIN32
// Open the console window and create the window handle for GetStdHandle()
AllocConsole();
// Save the window handle that AllocConsole() created
__hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
// Set the console window title
SetConsoleTitle(Name);
// Set the total letter space
COORD co = {Width, Height};
SetConsoleScreenBufferSize(__hStdOut, co);
/* Set the window size in number of letters. The height is hardcoded here because it can
be changed with MoveWindow() later */
SMALL_RECT coo = {0,0, (Width - 1),50}; // Top, left, right, bottom
SetConsoleWindowInfo(__hStdOut, TRUE, &coo);
#endif
// Create a file and a file handle if File is enabled and we don't already have a file handle
if(File && !__fStdOut)
{
// Edit the log file name
std::string FileEnding = ".log";
std::string FileName = Name;
std::string FullFilename = (FileName + FileEnding);
// Open the file handle
__fStdOut = fopen(FullFilename.c_str(), "w");
}
}
/* Close the console window and close the eventual file handle */
void Close()
{
#ifdef _WIN32
FreeConsole(); // Close the console window
#endif
if(__fStdOut) fclose(__fStdOut); // Close the file handle
}
// Print to screen and file
int Print(const char *fmt, ...)
{
// Maximum bytes, mind this value to avoid an overrun
static const int MAX_BYTES = 1024*20;
#if defined(_WIN32)
if(__hStdOut)
{
#endif
char s[MAX_BYTES];
va_list argptr;
int cnt; // To store the vsnprintf return message
va_start(argptr, fmt);
cnt = vsnprintf(s, MAX_BYTES, fmt, argptr);
va_end(argptr);
#if defined(_WIN32)
DWORD cCharsWritten; // We will get a value back here
WriteConsole(__hStdOut, s, (DWORD)strlen(s), &cCharsWritten, NULL);
#else
fprintf(stderr, "%s", s);
#endif
// Write to the file
if(__fStdOut)
{
fprintf(__fStdOut, "%s", s);
fflush(__fStdOut); // Write file now, don't wait
}
return(cnt);
#if defined(_WIN32)
} else
{
return 0;
}
#endif
}
// Clear console screen
void ClearScreen()
{
#if defined(_WIN32)
if(__hStdOut) // Check that we have a window handle
{
COORD coordScreen = { 0, 0 };
DWORD cCharsWritten;
CONSOLE_SCREEN_BUFFER_INFO csbi;
DWORD dwConSize;
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hConsole, &csbi);
dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize,
coordScreen, &cCharsWritten);
GetConsoleScreenBufferInfo(hConsole, &csbi);
FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize,
coordScreen, &cCharsWritten);
SetConsoleCursorPosition(hConsole, coordScreen);
}
#endif
}
/* Get window handle of console window to be able to resize it. We use
GetConsoleTitle() and FindWindow() to locate the console window handle. */
#if defined(_WIN32)
HWND GetHwnd(void)
{
#define MY_BUFSIZE 1024 // Buffer size for console window titles
HWND hwndFound; // This is what is returned to the caller
char pszNewWindowTitle[MY_BUFSIZE]; // Contains fabricated WindowTitle
char pszOldWindowTitle[MY_BUFSIZE]; // Contains original WindowTitle
// Fetch current window title.
GetConsoleTitle(pszOldWindowTitle, MY_BUFSIZE);
// Format a "unique" NewWindowTitle
wsprintf(pszNewWindowTitle, "%d/%d", GetTickCount(), GetCurrentProcessId());
// Change current window title
SetConsoleTitle(pszNewWindowTitle);
// Ensure window title has been updated
Sleep(40);
// Look for NewWindowTitle
hwndFound = FindWindow(NULL, pszNewWindowTitle);
// Restore original window title
SetConsoleTitle(pszOldWindowTitle);
return(hwndFound);
}
#endif // _WIN32
} // namespace

View File

@ -1,82 +1,82 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
//////////////////////////////////////////////////////////////////////////////////////
// Include and declarations
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#include <stdio.h> // System
#include "Common.h" // Local
#include "StringUtil.h"
bool DefaultMsgHandler(const char* caption, const char* text, bool yes_no, int Style);
static MsgAlertHandler msg_handler = DefaultMsgHandler;
/////////////////////////////
/* Select which of these functions that are used for message boxes. If wxWidgets is enabled
we will use wxMsgAlert() that is defined in main.cpp */
void RegisterMsgAlertHandler(MsgAlertHandler handler)
{
msg_handler = handler;
}
/////////////////////////////////////////////////////////////
/* This is the first stop for messages where the log is updated and the correct windows
is shown */
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
bool MsgAlert(const char* caption, bool yes_no, int Style, const char* format, ...)
{
// ---------------------------------
// Read message and write it to the log
// -----------
char buffer[2048];
bool ret = false;
va_list args;
va_start(args, format);
CharArrayFromFormatV(buffer, 2047, format, args);
va_end(args);
LOG(MASTER_LOG, "%s: %s", caption, buffer);
// -----------
if (msg_handler) {
ret = msg_handler(caption, buffer, yes_no, Style);
}
return ret;
}
/////////////////////////////////////////////////////////////
/* This is used in the No-GUI build */
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
bool DefaultMsgHandler(const char* caption, const char* text, bool yes_no, int Style)
{
#ifdef _WIN32
int STYLE = MB_ICONINFORMATION;
if (Style == QUESTION) STYLE = MB_ICONQUESTION;
if (Style == WARNING) STYLE = MB_ICONWARNING;
return IDYES == MessageBox(0, text, caption, STYLE | (yes_no ? MB_YESNO : MB_OK));
#else
printf("%s\n", text);
return true;
#endif
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
//////////////////////////////////////////////////////////////////////////////////////
// Include and declarations
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#include <stdio.h> // System
#include "Common.h" // Local
#include "StringUtil.h"
bool DefaultMsgHandler(const char* caption, const char* text, bool yes_no, int Style);
static MsgAlertHandler msg_handler = DefaultMsgHandler;
/////////////////////////////
/* Select which of these functions that are used for message boxes. If wxWidgets is enabled
we will use wxMsgAlert() that is defined in main.cpp */
void RegisterMsgAlertHandler(MsgAlertHandler handler)
{
msg_handler = handler;
}
/////////////////////////////////////////////////////////////
/* This is the first stop for messages where the log is updated and the correct windows
is shown */
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
bool MsgAlert(const char* caption, bool yes_no, int Style, const char* format, ...)
{
// ---------------------------------
// Read message and write it to the log
// -----------
char buffer[2048];
bool ret = false;
va_list args;
va_start(args, format);
CharArrayFromFormatV(buffer, 2047, format, args);
va_end(args);
LOG(MASTER_LOG, "%s: %s", caption, buffer);
// -----------
if (msg_handler) {
ret = msg_handler(caption, buffer, yes_no, Style);
}
return ret;
}
/////////////////////////////////////////////////////////////
/* This is used in the No-GUI build */
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
bool DefaultMsgHandler(const char* caption, const char* text, bool yes_no, int Style)
{
#ifdef _WIN32
int STYLE = MB_ICONINFORMATION;
if (Style == QUESTION) STYLE = MB_ICONQUESTION;
if (Style == WARNING) STYLE = MB_ICONWARNING;
return IDYES == MessageBox(0, text, caption, STYLE | (yes_no ? MB_YESNO : MB_OK));
#else
printf("%s\n", text);
return true;
#endif
}

View File

@ -1,279 +1,279 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Boot.h"
#include "../PowerPC/PowerPC.h"
#include "../HLE/HLE.h"
#include "../HW/Memmap.h"
#include "../ConfigManager.h"
#include "Blob.h"
#include "MappedFile.h"
#include "Boot_DOL.h"
#include "Boot_WiiWAD.h"
#include "AES/aes.h"
#include "MathUtil.h"
class CBlobBigEndianReader
{
public:
CBlobBigEndianReader(DiscIO::IBlobReader& _rReader) : m_rReader(_rReader) {}
u32 Read32(u64 _Offset)
{
u32 Temp;
m_rReader.Read(_Offset, 4, (u8*)&Temp);
return(Common::swap32(Temp));
}
private:
DiscIO::IBlobReader& m_rReader;
};
std::vector<STileMetaContent> m_TileMetaContent;
u16 m_BootIndex = -1;
void AESDecode(u8* _pKey, u8* _IV, u8* _pSrc, u32 _Size, u8* _pDest)
{
AES_KEY AESKey;
AES_set_decrypt_key(_pKey, 128, &AESKey);
AES_cbc_encrypt(_pSrc, _pDest, _Size, &AESKey, _IV, AES_DECRYPT);
}
u8* CreateWADEntry(DiscIO::IBlobReader& _rReader, u32 _Size, u64 _Offset)
{
if (_Size > 0)
{
u8* pTmpBuffer = new u8[_Size];
_dbg_assert_msg_(BOOT, pTmpBuffer!=0, "WiiWAD: Cant allocate memory for WAD entry");
if (!_rReader.Read(_Offset, _Size, pTmpBuffer))
{
PanicAlert("WiiWAD: Could not read from file");
}
return pTmpBuffer;
}
return NULL;
}
void GetKeyFromTicket(u8* pTicket, u8* pTicketKey)
{
u8 CommonKey[16];
FILE* pMasterKeyFile = fopen(WII_MASTERKEY_FILE, "rb");
_dbg_assert_msg_(BOOT, pMasterKeyFile!=0x0, "WiiWAD: Cant open MasterKeyFile for WII");
if (pMasterKeyFile)
{
fread(CommonKey, 16, 1, pMasterKeyFile);
fclose(pMasterKeyFile);
u8 IV[16];
memset(IV, 0, sizeof IV);
memcpy(IV, pTicket + 0x01dc, 8);
AESDecode(CommonKey, IV, pTicket + 0x01bf, 16, pTicketKey);
}
}
bool ParseTMD(u8* pDataApp, u32 pDataAppSize, u8* pTicket, u8* pTMD)
{
u8 DecryptTitleKey[16];
u8 IV[16];
GetKeyFromTicket(pTicket, DecryptTitleKey);
u32 numEntries = Common::swap16(pTMD + 0x01de);
m_BootIndex = Common::swap16(pTMD + 0x01e0);
u8* p = pDataApp;
m_TileMetaContent.resize(numEntries);
for (u32 i=0; i<numEntries; i++)
{
STileMetaContent& rContent = m_TileMetaContent[i];
rContent.m_ContentID = Common::swap32(pTMD + 0x01e4 + 0x24*i);
rContent.m_Index = Common::swap16(pTMD + 0x01e8 + 0x24*i);
rContent.m_Type = Common::swap16(pTMD + 0x01ea + 0x24*i);
rContent.m_Size= (u32)ROUND_UP(Common::swap64(pTMD + 0x01ec + 0x24*i), 0x40);
rContent.m_pData = new u8[rContent.m_Size];
memset(IV, 0, sizeof IV);
memcpy(IV, pTMD + 0x01e8 + 0x24*i, 2);
AESDecode(DecryptTitleKey, IV, p, rContent.m_Size, rContent.m_pData);
p += rContent.m_Size;
}
return true;
}
bool ParseWAD(DiscIO::IBlobReader& _rReader)
{
CBlobBigEndianReader ReaderBig(_rReader);
// get header size
u32 HeaderSize = ReaderBig.Read32(0);
if (HeaderSize != 0x20)
{
_dbg_assert_msg_(BOOT, (HeaderSize==0x20), "WiiWAD: Header size != 0x20");
return false;
}
// get header
u8 Header[0x20];
_rReader.Read(0, HeaderSize, Header);
u32 HeaderType = ReaderBig.Read32(0x4);
if ((0x49730000 != HeaderType) && (0x69620000 != HeaderType))
return false;
u32 CertificateChainSize = ReaderBig.Read32(0x8);
u32 Reserved = ReaderBig.Read32(0xC);
u32 TicketSize = ReaderBig.Read32(0x10);
u32 TMDSize = ReaderBig.Read32(0x14);
u32 DataAppSize = ReaderBig.Read32(0x18);
u32 FooterSize = ReaderBig.Read32(0x1C);
_dbg_assert_msg_(BOOT, Reserved==0x00, "WiiWAD: Reserved must be 0x00");
u32 Offset = 0x40;
u8* pCertificateChain = CreateWADEntry(_rReader, CertificateChainSize, Offset); Offset += ROUND_UP(CertificateChainSize, 0x40);
u8* pTicket = CreateWADEntry(_rReader, TicketSize, Offset); Offset += ROUND_UP(TicketSize, 0x40);
u8* pTMD = CreateWADEntry(_rReader, TMDSize, Offset); Offset += ROUND_UP(TMDSize, 0x40);
u8* pDataApp = CreateWADEntry(_rReader, DataAppSize, Offset); Offset += ROUND_UP(DataAppSize, 0x40);
u8* pFooter = CreateWADEntry(_rReader, FooterSize, Offset); Offset += ROUND_UP(FooterSize, 0x40);
bool Result = ParseTMD(pDataApp, DataAppSize, pTicket, pTMD);
return Result;
}
bool CBoot::IsWiiWAD(const char* _pFileName)
{
DiscIO::IBlobReader* pReader = DiscIO::CreateBlobReader(_pFileName);
if (pReader == NULL)
return false;
CBlobBigEndianReader Reader(*pReader);
bool Result = false;
// check for wii wad
if (Reader.Read32(0x00) == 0x20)
{
u32 WADTYpe = Reader.Read32(0x04);
switch(WADTYpe)
{
case 0x49730000:
case 0x69620000:
Result = true;
}
}
delete pReader;
return Result;
}
void SetupWiiMem()
{
//
// TODO: REDUDANT CODE SUX ....
//
Memory::Write_U32(0x5d1c9ea3, 0x00000018); // Magic word it is a wii disc
Memory::Write_U32(0x0D15EA5E, 0x00000020); // Another magic word
Memory::Write_U32(0x00000001, 0x00000024); // Unknown
Memory::Write_U32(0x01800000, 0x00000028); // MEM1 size 24MB
Memory::Write_U32(0x00000023, 0x0000002c); // Production Board Model
Memory::Write_U32(0x00000000, 0x00000030); // Init
Memory::Write_U32(0x817FEC60, 0x00000034); // Init
// 38, 3C should get start, size of FST through apploader
Memory::Write_U32(0x38a00040, 0x00000060); // Exception init
Memory::Write_U32(0x8008f7b8, 0x000000e4); // Thread Init
Memory::Write_U32(0x01800000, 0x000000f0); // "Simulated memory size" (debug mode?)
Memory::Write_U32(0x8179b500, 0x000000f4); // __start
Memory::Write_U32(0x0e7be2c0, 0x000000f8); // Bus speed
Memory::Write_U32(0x2B73A840, 0x000000fc); // CPU speed
Memory::Write_U16(0x0000, 0x000030e6); // Console type
Memory::Write_U32(0x00000000, 0x000030c0); // EXI
Memory::Write_U32(0x00000000, 0x000030c4); // EXI
Memory::Write_U32(0x00000000, 0x000030dc); // Time
Memory::Write_U32(0x00000000, 0x000030d8); // Time
Memory::Write_U32(0x00000000, 0x000030f0); // Apploader
Memory::Write_U32(0x01800000, 0x00003100); // BAT
Memory::Write_U32(0x01800000, 0x00003104); // BAT
Memory::Write_U32(0x00000000, 0x0000310c); // Init
Memory::Write_U32(0x8179d500, 0x00003110); // Init
Memory::Write_U32(0x04000000, 0x00003118); // Unknown
Memory::Write_U32(0x04000000, 0x0000311c); // BAT
Memory::Write_U32(0x93400000, 0x00003120); // BAT
Memory::Write_U32(0x90000800, 0x00003124); // Init - MEM2 low
Memory::Write_U32(0x933e0000, 0x00003128); // Init - MEM2 high
Memory::Write_U32(0x933e0000, 0x00003130); // IOS MEM2 low
Memory::Write_U32(0x93400000, 0x00003134); // IOS MEM2 high
Memory::Write_U32(0x00000011, 0x00003138); // Console type
Memory::Write_U64(0x0009020400062507ULL, 0x00003140); // IOS Version
Memory::Write_U16(0x0113, 0x0000315e); // Apploader
Memory::Write_U32(0x0000FF16, 0x00003158); // DDR ram vendor code
Memory::Write_U8(0x80, 0x0000315c); // OSInit
Memory::Write_U8(0x00, 0x00000006); // DVDInit
Memory::Write_U8(0x00, 0x00000007); // DVDInit
Memory::Write_U16(0x0000, 0x000030e0); // PADInit
// Fake the VI Init of the BIOS
Memory::Write_U32(SConfig::GetInstance().m_LocalCoreStartupParameter.bNTSC ? 0 : 1, 0x000000CC);
// Clear exception handler. Why? Don't we begin with only zeroes?
for (int i = 0x3000; i <= 0x3038; i += 4)
{
Memory::Write_U32(0x00000000, 0x80000000 + i);
}
/* This is some kind of consistency check that is compared to the 0x00
values as the game boots. This location keep the 4 byte ID for as long
as the game is running. The 6 byte ID at 0x00 is overwritten sometime
after this check during booting. */
// VolumeHandler::ReadToPtr(Memory::GetPointer(0x3180), 0, 4);
// Memory::Write_U8(0x80, 0x00003184);
// ================
}
bool CBoot::Boot_WiiWAD(const char* _pFilename)
{
DiscIO::IBlobReader* pReader = DiscIO::CreateBlobReader(_pFilename);
if (pReader == NULL)
return false;
bool Result = ParseWAD(*pReader);
delete pReader;
if (!Result)
return false;
SetupWiiMem();
// DOL
STileMetaContent& rContent = m_TileMetaContent[m_BootIndex];
CDolLoader DolLoader(rContent.m_pData, rContent.m_Size);
PC = DolLoader.GetEntryPoint() | 0x80000000;
return true;
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Boot.h"
#include "../PowerPC/PowerPC.h"
#include "../HLE/HLE.h"
#include "../HW/Memmap.h"
#include "../ConfigManager.h"
#include "Blob.h"
#include "MappedFile.h"
#include "Boot_DOL.h"
#include "Boot_WiiWAD.h"
#include "AES/aes.h"
#include "MathUtil.h"
class CBlobBigEndianReader
{
public:
CBlobBigEndianReader(DiscIO::IBlobReader& _rReader) : m_rReader(_rReader) {}
u32 Read32(u64 _Offset)
{
u32 Temp;
m_rReader.Read(_Offset, 4, (u8*)&Temp);
return(Common::swap32(Temp));
}
private:
DiscIO::IBlobReader& m_rReader;
};
std::vector<STileMetaContent> m_TileMetaContent;
u16 m_BootIndex = -1;
void AESDecode(u8* _pKey, u8* _IV, u8* _pSrc, u32 _Size, u8* _pDest)
{
AES_KEY AESKey;
AES_set_decrypt_key(_pKey, 128, &AESKey);
AES_cbc_encrypt(_pSrc, _pDest, _Size, &AESKey, _IV, AES_DECRYPT);
}
u8* CreateWADEntry(DiscIO::IBlobReader& _rReader, u32 _Size, u64 _Offset)
{
if (_Size > 0)
{
u8* pTmpBuffer = new u8[_Size];
_dbg_assert_msg_(BOOT, pTmpBuffer!=0, "WiiWAD: Cant allocate memory for WAD entry");
if (!_rReader.Read(_Offset, _Size, pTmpBuffer))
{
PanicAlert("WiiWAD: Could not read from file");
}
return pTmpBuffer;
}
return NULL;
}
void GetKeyFromTicket(u8* pTicket, u8* pTicketKey)
{
u8 CommonKey[16];
FILE* pMasterKeyFile = fopen(WII_MASTERKEY_FILE, "rb");
_dbg_assert_msg_(BOOT, pMasterKeyFile!=0x0, "WiiWAD: Cant open MasterKeyFile for WII");
if (pMasterKeyFile)
{
fread(CommonKey, 16, 1, pMasterKeyFile);
fclose(pMasterKeyFile);
u8 IV[16];
memset(IV, 0, sizeof IV);
memcpy(IV, pTicket + 0x01dc, 8);
AESDecode(CommonKey, IV, pTicket + 0x01bf, 16, pTicketKey);
}
}
bool ParseTMD(u8* pDataApp, u32 pDataAppSize, u8* pTicket, u8* pTMD)
{
u8 DecryptTitleKey[16];
u8 IV[16];
GetKeyFromTicket(pTicket, DecryptTitleKey);
u32 numEntries = Common::swap16(pTMD + 0x01de);
m_BootIndex = Common::swap16(pTMD + 0x01e0);
u8* p = pDataApp;
m_TileMetaContent.resize(numEntries);
for (u32 i=0; i<numEntries; i++)
{
STileMetaContent& rContent = m_TileMetaContent[i];
rContent.m_ContentID = Common::swap32(pTMD + 0x01e4 + 0x24*i);
rContent.m_Index = Common::swap16(pTMD + 0x01e8 + 0x24*i);
rContent.m_Type = Common::swap16(pTMD + 0x01ea + 0x24*i);
rContent.m_Size= (u32)ROUND_UP(Common::swap64(pTMD + 0x01ec + 0x24*i), 0x40);
rContent.m_pData = new u8[rContent.m_Size];
memset(IV, 0, sizeof IV);
memcpy(IV, pTMD + 0x01e8 + 0x24*i, 2);
AESDecode(DecryptTitleKey, IV, p, rContent.m_Size, rContent.m_pData);
p += rContent.m_Size;
}
return true;
}
bool ParseWAD(DiscIO::IBlobReader& _rReader)
{
CBlobBigEndianReader ReaderBig(_rReader);
// get header size
u32 HeaderSize = ReaderBig.Read32(0);
if (HeaderSize != 0x20)
{
_dbg_assert_msg_(BOOT, (HeaderSize==0x20), "WiiWAD: Header size != 0x20");
return false;
}
// get header
u8 Header[0x20];
_rReader.Read(0, HeaderSize, Header);
u32 HeaderType = ReaderBig.Read32(0x4);
if ((0x49730000 != HeaderType) && (0x69620000 != HeaderType))
return false;
u32 CertificateChainSize = ReaderBig.Read32(0x8);
u32 Reserved = ReaderBig.Read32(0xC);
u32 TicketSize = ReaderBig.Read32(0x10);
u32 TMDSize = ReaderBig.Read32(0x14);
u32 DataAppSize = ReaderBig.Read32(0x18);
u32 FooterSize = ReaderBig.Read32(0x1C);
_dbg_assert_msg_(BOOT, Reserved==0x00, "WiiWAD: Reserved must be 0x00");
u32 Offset = 0x40;
u8* pCertificateChain = CreateWADEntry(_rReader, CertificateChainSize, Offset); Offset += ROUND_UP(CertificateChainSize, 0x40);
u8* pTicket = CreateWADEntry(_rReader, TicketSize, Offset); Offset += ROUND_UP(TicketSize, 0x40);
u8* pTMD = CreateWADEntry(_rReader, TMDSize, Offset); Offset += ROUND_UP(TMDSize, 0x40);
u8* pDataApp = CreateWADEntry(_rReader, DataAppSize, Offset); Offset += ROUND_UP(DataAppSize, 0x40);
u8* pFooter = CreateWADEntry(_rReader, FooterSize, Offset); Offset += ROUND_UP(FooterSize, 0x40);
bool Result = ParseTMD(pDataApp, DataAppSize, pTicket, pTMD);
return Result;
}
bool CBoot::IsWiiWAD(const char* _pFileName)
{
DiscIO::IBlobReader* pReader = DiscIO::CreateBlobReader(_pFileName);
if (pReader == NULL)
return false;
CBlobBigEndianReader Reader(*pReader);
bool Result = false;
// check for wii wad
if (Reader.Read32(0x00) == 0x20)
{
u32 WADTYpe = Reader.Read32(0x04);
switch(WADTYpe)
{
case 0x49730000:
case 0x69620000:
Result = true;
}
}
delete pReader;
return Result;
}
void SetupWiiMem()
{
//
// TODO: REDUDANT CODE SUX ....
//
Memory::Write_U32(0x5d1c9ea3, 0x00000018); // Magic word it is a wii disc
Memory::Write_U32(0x0D15EA5E, 0x00000020); // Another magic word
Memory::Write_U32(0x00000001, 0x00000024); // Unknown
Memory::Write_U32(0x01800000, 0x00000028); // MEM1 size 24MB
Memory::Write_U32(0x00000023, 0x0000002c); // Production Board Model
Memory::Write_U32(0x00000000, 0x00000030); // Init
Memory::Write_U32(0x817FEC60, 0x00000034); // Init
// 38, 3C should get start, size of FST through apploader
Memory::Write_U32(0x38a00040, 0x00000060); // Exception init
Memory::Write_U32(0x8008f7b8, 0x000000e4); // Thread Init
Memory::Write_U32(0x01800000, 0x000000f0); // "Simulated memory size" (debug mode?)
Memory::Write_U32(0x8179b500, 0x000000f4); // __start
Memory::Write_U32(0x0e7be2c0, 0x000000f8); // Bus speed
Memory::Write_U32(0x2B73A840, 0x000000fc); // CPU speed
Memory::Write_U16(0x0000, 0x000030e6); // Console type
Memory::Write_U32(0x00000000, 0x000030c0); // EXI
Memory::Write_U32(0x00000000, 0x000030c4); // EXI
Memory::Write_U32(0x00000000, 0x000030dc); // Time
Memory::Write_U32(0x00000000, 0x000030d8); // Time
Memory::Write_U32(0x00000000, 0x000030f0); // Apploader
Memory::Write_U32(0x01800000, 0x00003100); // BAT
Memory::Write_U32(0x01800000, 0x00003104); // BAT
Memory::Write_U32(0x00000000, 0x0000310c); // Init
Memory::Write_U32(0x8179d500, 0x00003110); // Init
Memory::Write_U32(0x04000000, 0x00003118); // Unknown
Memory::Write_U32(0x04000000, 0x0000311c); // BAT
Memory::Write_U32(0x93400000, 0x00003120); // BAT
Memory::Write_U32(0x90000800, 0x00003124); // Init - MEM2 low
Memory::Write_U32(0x933e0000, 0x00003128); // Init - MEM2 high
Memory::Write_U32(0x933e0000, 0x00003130); // IOS MEM2 low
Memory::Write_U32(0x93400000, 0x00003134); // IOS MEM2 high
Memory::Write_U32(0x00000011, 0x00003138); // Console type
Memory::Write_U64(0x0009020400062507ULL, 0x00003140); // IOS Version
Memory::Write_U16(0x0113, 0x0000315e); // Apploader
Memory::Write_U32(0x0000FF16, 0x00003158); // DDR ram vendor code
Memory::Write_U8(0x80, 0x0000315c); // OSInit
Memory::Write_U8(0x00, 0x00000006); // DVDInit
Memory::Write_U8(0x00, 0x00000007); // DVDInit
Memory::Write_U16(0x0000, 0x000030e0); // PADInit
// Fake the VI Init of the BIOS
Memory::Write_U32(SConfig::GetInstance().m_LocalCoreStartupParameter.bNTSC ? 0 : 1, 0x000000CC);
// Clear exception handler. Why? Don't we begin with only zeroes?
for (int i = 0x3000; i <= 0x3038; i += 4)
{
Memory::Write_U32(0x00000000, 0x80000000 + i);
}
/* This is some kind of consistency check that is compared to the 0x00
values as the game boots. This location keep the 4 byte ID for as long
as the game is running. The 6 byte ID at 0x00 is overwritten sometime
after this check during booting. */
// VolumeHandler::ReadToPtr(Memory::GetPointer(0x3180), 0, 4);
// Memory::Write_U8(0x80, 0x00003184);
// ================
}
bool CBoot::Boot_WiiWAD(const char* _pFilename)
{
DiscIO::IBlobReader* pReader = DiscIO::CreateBlobReader(_pFilename);
if (pReader == NULL)
return false;
bool Result = ParseWAD(*pReader);
delete pReader;
if (!Result)
return false;
SetupWiiMem();
// DOL
STileMetaContent& rContent = m_TileMetaContent[m_BootIndex];
CDolLoader DolLoader(rContent.m_pData, rContent.m_Size);
PC = DolLoader.GetEntryPoint() | 0x80000000;
return true;
}

View File

@ -1,251 +1,251 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Setup.h"
#ifdef RERECORDING
//////////////////////////////////////////////////////////////////////////////////////////
// Include
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#ifdef _WIN32
#include <windows.h>
#endif
#include "Thread.h" // Common
#include "Timer.h"
#include "Common.h"
#include "ConsoleWindow.h"
#include "Console.h"
#include "Core.h"
#include "CPUDetect.h"
#include "CoreTiming.h"
#include "Boot/Boot.h"
#include "PatchEngine.h"
#include "HW/Memmap.h"
#include "HW/PeripheralInterface.h"
#include "HW/GPFifo.h"
#include "HW/CPU.h"
#include "HW/CPUCompare.h"
#include "HW/HW.h"
#include "HW/DSP.h"
#include "HW/GPFifo.h"
#include "HW/AudioInterface.h"
#include "HW/VideoInterface.h"
#include "HW/CommandProcessor.h"
#include "HW/PixelEngine.h"
#include "HW/SystemTimers.h"
#include "PowerPC/PowerPC.h"
#include "PluginManager.h"
#include "ConfigManager.h"
#include "MemTools.h"
#include "Host.h"
#include "LogManager.h"
////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// File description: Rerecording Functions
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
How the timer works: We measure the time between drawn frames, not when the game is paused. So time
should be a fairly comparable measure of the time it took to play the game. However the time it takes
to draw a frame will be lower on a fast computer. Therefore we could perhaps measure time as an
internal game time that is adjusted by the average time it takes to draw a frame. Also if it only takes
ten or twenty milliseconds to draw a frame I'm not certain about how accurate the mmsystem timers are for
such short periods.
//////////////////////////////////////*/
namespace Core
{
///////////////////////////////////////////////////////////////////////////////////////////
// Declarations and definitions
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int g_FrameCounter = 0;
bool g_FrameStep = false;
Common::Timer ReRecTimer;
////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// Control Run, Pause, Stop and the Timer.
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Subtract the paused time when we run again
void Run()
{
ReRecTimer.AddTimeDifference();
}
// Update the time
void Pause()
{
ReRecTimer.Update();
}
// Start the timer when a game is booted
void RerecordingStart()
{
g_FrameCounter = 0;
ReRecTimer.Start();
// Logging
//Console::Print("RerecordingStart: %i\n", g_FrameCounter);
}
// Reset the frame counter
void RerecordingStop()
{
// Write the final time and Stop the timer
ReRecTimer.Stop();
// Update status bar
WriteStatus();
}
/* Wind back the frame counter when a save state is loaded. Currently we don't know what that means in
time so we just guess that the time is proportional the the number of frames
Todo: There are many assumptions here: We probably want to replace the time here by the actual time
that we save together with the save state or the input recording for example. And have it adjusted
for full speed playback (whether it's 30 fps or 60 fps or some other speed that the game is natively
capped at). Also the input interrupts do not occur as often as the frame renderings, they occur more
often. So we may want to move the input recording to fram updates, or perhaps sync the input interrupts
to frame updates.
*/
void WindBack(int Counter)
{
/* Counter should be smaller than g_FrameCounter, however it currently updates faster than the
frames so currently it may not be the same. Therefore I use the abs() function. */
int AbsoluteFrameDifference = abs(g_FrameCounter - Counter);
float FractionalFrameDifference = (float) AbsoluteFrameDifference / (float) g_FrameCounter;
// Update the frame counter
g_FrameCounter = Counter;
// Approximate a time to wind back the clock to
// Get the current time
u64 CurrentTimeMs = ReRecTimer.GetTimeElapsed();
// Save the current time in seconds in a new double
double CurrentTimeSeconds = (double) (CurrentTimeMs / 1000);
// Reduce it by the same proportion as the counter was wound back
CurrentTimeSeconds = CurrentTimeSeconds * FractionalFrameDifference;
// Update the clock
ReRecTimer.WindBackStartingTime((u64)CurrentTimeSeconds * 1000);
// Logging
Console::Print("WindBack: %i %u\n", Counter, (u64)CurrentTimeSeconds);
}
////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// Frame advance
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void FrameAdvance()
{
// Update status bar
WriteStatus();
// If a game is not started, return
if (Core::GetState() == Core::CORE_UNINITIALIZED) return;
// Play to the next frame
if (g_FrameStep)
{
Run();
Core::SetState(Core::CORE_RUN);
}
}
// Turn on frame stepping
void FrameStepOnOff()
{
/* Turn frame step on or off. If a game is running and we turn this on it means that the game
will pause after the next frame update */
g_FrameStep = !g_FrameStep;
// Update status bar
WriteStatus();
// If a game is not started, return
if(Core::GetState() == Core::CORE_UNINITIALIZED) return;
// Run the emulation if we turned off framestepping
if (!g_FrameStep)
{
Run();
Core::SetState(Core::CORE_RUN);
}
}
////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// General functions
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Write to the status bar
void WriteStatus()
{
std::string TmpStr = "Time: " + ReRecTimer.GetTimeElapsedFormatted();
TmpStr += StringFromFormat(" Frame: %s", ThS(g_FrameCounter).c_str());
// The FPS is the total average since the game was booted
TmpStr += StringFromFormat(" FPS: %i", (g_FrameCounter * 1000) / ReRecTimer.GetTimeElapsed());
TmpStr += StringFromFormat(" FrameStep: %s", g_FrameStep ? "On" : "Off");
Host_UpdateStatusBar(TmpStr.c_str(), 1);
}
// When a new frame is drawn
void FrameUpdate()
{
// Write to the status bar
WriteStatus();
/* I don't think the frequent update has any material speed inpact at all, but should it
have you can controls the update speed by changing the "% 10" in this line */
//if (g_FrameCounter % 10 == 0) WriteStatus();
// Pause if frame stepping is on
if(g_FrameStep)
{
Pause();
Core::SetState(Core::CORE_PAUSE);
}
// Count one frame
g_FrameCounter++;
}
////////////////////////////////////////
} // Core
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Setup.h"
#ifdef RERECORDING
//////////////////////////////////////////////////////////////////////////////////////////
// Include
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#ifdef _WIN32
#include <windows.h>
#endif
#include "Thread.h" // Common
#include "Timer.h"
#include "Common.h"
#include "ConsoleWindow.h"
#include "Console.h"
#include "Core.h"
#include "CPUDetect.h"
#include "CoreTiming.h"
#include "Boot/Boot.h"
#include "PatchEngine.h"
#include "HW/Memmap.h"
#include "HW/PeripheralInterface.h"
#include "HW/GPFifo.h"
#include "HW/CPU.h"
#include "HW/CPUCompare.h"
#include "HW/HW.h"
#include "HW/DSP.h"
#include "HW/GPFifo.h"
#include "HW/AudioInterface.h"
#include "HW/VideoInterface.h"
#include "HW/CommandProcessor.h"
#include "HW/PixelEngine.h"
#include "HW/SystemTimers.h"
#include "PowerPC/PowerPC.h"
#include "PluginManager.h"
#include "ConfigManager.h"
#include "MemTools.h"
#include "Host.h"
#include "LogManager.h"
////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// File description: Rerecording Functions
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
How the timer works: We measure the time between drawn frames, not when the game is paused. So time
should be a fairly comparable measure of the time it took to play the game. However the time it takes
to draw a frame will be lower on a fast computer. Therefore we could perhaps measure time as an
internal game time that is adjusted by the average time it takes to draw a frame. Also if it only takes
ten or twenty milliseconds to draw a frame I'm not certain about how accurate the mmsystem timers are for
such short periods.
//////////////////////////////////////*/
namespace Core
{
///////////////////////////////////////////////////////////////////////////////////////////
// Declarations and definitions
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int g_FrameCounter = 0;
bool g_FrameStep = false;
Common::Timer ReRecTimer;
////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// Control Run, Pause, Stop and the Timer.
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Subtract the paused time when we run again
void Run()
{
ReRecTimer.AddTimeDifference();
}
// Update the time
void Pause()
{
ReRecTimer.Update();
}
// Start the timer when a game is booted
void RerecordingStart()
{
g_FrameCounter = 0;
ReRecTimer.Start();
// Logging
//Console::Print("RerecordingStart: %i\n", g_FrameCounter);
}
// Reset the frame counter
void RerecordingStop()
{
// Write the final time and Stop the timer
ReRecTimer.Stop();
// Update status bar
WriteStatus();
}
/* Wind back the frame counter when a save state is loaded. Currently we don't know what that means in
time so we just guess that the time is proportional the the number of frames
Todo: There are many assumptions here: We probably want to replace the time here by the actual time
that we save together with the save state or the input recording for example. And have it adjusted
for full speed playback (whether it's 30 fps or 60 fps or some other speed that the game is natively
capped at). Also the input interrupts do not occur as often as the frame renderings, they occur more
often. So we may want to move the input recording to fram updates, or perhaps sync the input interrupts
to frame updates.
*/
void WindBack(int Counter)
{
/* Counter should be smaller than g_FrameCounter, however it currently updates faster than the
frames so currently it may not be the same. Therefore I use the abs() function. */
int AbsoluteFrameDifference = abs(g_FrameCounter - Counter);
float FractionalFrameDifference = (float) AbsoluteFrameDifference / (float) g_FrameCounter;
// Update the frame counter
g_FrameCounter = Counter;
// Approximate a time to wind back the clock to
// Get the current time
u64 CurrentTimeMs = ReRecTimer.GetTimeElapsed();
// Save the current time in seconds in a new double
double CurrentTimeSeconds = (double) (CurrentTimeMs / 1000);
// Reduce it by the same proportion as the counter was wound back
CurrentTimeSeconds = CurrentTimeSeconds * FractionalFrameDifference;
// Update the clock
ReRecTimer.WindBackStartingTime((u64)CurrentTimeSeconds * 1000);
// Logging
Console::Print("WindBack: %i %u\n", Counter, (u64)CurrentTimeSeconds);
}
////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// Frame advance
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void FrameAdvance()
{
// Update status bar
WriteStatus();
// If a game is not started, return
if (Core::GetState() == Core::CORE_UNINITIALIZED) return;
// Play to the next frame
if (g_FrameStep)
{
Run();
Core::SetState(Core::CORE_RUN);
}
}
// Turn on frame stepping
void FrameStepOnOff()
{
/* Turn frame step on or off. If a game is running and we turn this on it means that the game
will pause after the next frame update */
g_FrameStep = !g_FrameStep;
// Update status bar
WriteStatus();
// If a game is not started, return
if(Core::GetState() == Core::CORE_UNINITIALIZED) return;
// Run the emulation if we turned off framestepping
if (!g_FrameStep)
{
Run();
Core::SetState(Core::CORE_RUN);
}
}
////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// General functions
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Write to the status bar
void WriteStatus()
{
std::string TmpStr = "Time: " + ReRecTimer.GetTimeElapsedFormatted();
TmpStr += StringFromFormat(" Frame: %s", ThS(g_FrameCounter).c_str());
// The FPS is the total average since the game was booted
TmpStr += StringFromFormat(" FPS: %i", (g_FrameCounter * 1000) / ReRecTimer.GetTimeElapsed());
TmpStr += StringFromFormat(" FrameStep: %s", g_FrameStep ? "On" : "Off");
Host_UpdateStatusBar(TmpStr.c_str(), 1);
}
// When a new frame is drawn
void FrameUpdate()
{
// Write to the status bar
WriteStatus();
/* I don't think the frequent update has any material speed inpact at all, but should it
have you can controls the update speed by changing the "% 10" in this line */
//if (g_FrameCounter % 10 == 0) WriteStatus();
// Pause if frame stepping is on
if(g_FrameStep)
{
Pause();
Core::SetState(Core::CORE_PAUSE);
}
// Count one frame
g_FrameCounter++;
}
////////////////////////////////////////
} // Core
#endif // RERECORDING

File diff suppressed because it is too large Load Diff

View File

@ -1,97 +1,97 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "SI_Device.h"
#include "SI_DeviceGCController.h"
#include "SI_DeviceGBA.h"
//////////////////////////////////////////////////////////////////////////
// --- interface ISIDevice ---
//////////////////////////////////////////////////////////////////////////
int ISIDevice::RunBuffer(u8* _pBuffer, int _iLength)
{
#ifdef _DEBUG
LOG(SERIALINTERFACE, "Send Data Device(%i) - Length(%i) ", ISIDevice::m_iDeviceNumber,_iLength);
char szTemp[256] = "";
int num = 0;
while(num < _iLength)
{
char szTemp2[128] = "";
sprintf(szTemp2, "0x%02x ", _pBuffer[num^3]);
strcat(szTemp, szTemp2);
num++;
if ((num % 8) == 0)
{
LOG(SERIALINTERFACE, szTemp);
szTemp[0] = '\0';
}
}
LOG(SERIALINTERFACE, szTemp);
#endif
return 0;
};
//////////////////////////////////////////////////////////////////////////
// --- class CSIDummy ---
//////////////////////////////////////////////////////////////////////////
// Just a dummy that logs reads and writes
// to be used for SI devices we haven't emulated
class CSIDevice_Dummy : public ISIDevice
{
public:
CSIDevice_Dummy(int _iDeviceNumber) :
ISIDevice(_iDeviceNumber)
{}
virtual ~CSIDevice_Dummy(){}
int RunBuffer(u8* _pBuffer, int _iLength)
{
// (shuffle2) Logging of this function will be done above, in ISIDevice::RunBuffer
// No device. (shuffle2) Maybe this should be SI_ERROR_NO_RESPONSE?
reinterpret_cast<u32*>(_pBuffer)[0] = 0x00000000;
return 4;
}
bool GetData(u32& _Hi, u32& _Low) {LOG(SERIALINTERFACE, "SI DUMMY %i GetData", this->m_iDeviceNumber); return false;}
void SendCommand(u32 _Cmd) {LOG(SERIALINTERFACE, "SI DUMMY %i SendCommand: %08x", this->m_iDeviceNumber, _Cmd);}
};
//////////////////////////////////////////////////////////////////////////
// F A C T O R Y /////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
ISIDevice* SIDevice_Create(TSIDevices _SIDevice, int _iDeviceNumber)
{
switch(_SIDevice)
{
case SI_DUMMY:
return new CSIDevice_Dummy(_iDeviceNumber);
break;
case SI_GC_CONTROLLER:
return new CSIDevice_GCController(_iDeviceNumber);
break;
case SI_GBA:
return new CSIDevice_GBA(_iDeviceNumber);
break;
}
return NULL;
}
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "SI_Device.h"
#include "SI_DeviceGCController.h"
#include "SI_DeviceGBA.h"
//////////////////////////////////////////////////////////////////////////
// --- interface ISIDevice ---
//////////////////////////////////////////////////////////////////////////
int ISIDevice::RunBuffer(u8* _pBuffer, int _iLength)
{
#ifdef _DEBUG
LOG(SERIALINTERFACE, "Send Data Device(%i) - Length(%i) ", ISIDevice::m_iDeviceNumber,_iLength);
char szTemp[256] = "";
int num = 0;
while(num < _iLength)
{
char szTemp2[128] = "";
sprintf(szTemp2, "0x%02x ", _pBuffer[num^3]);
strcat(szTemp, szTemp2);
num++;
if ((num % 8) == 0)
{
LOG(SERIALINTERFACE, szTemp);
szTemp[0] = '\0';
}
}
LOG(SERIALINTERFACE, szTemp);
#endif
return 0;
};
//////////////////////////////////////////////////////////////////////////
// --- class CSIDummy ---
//////////////////////////////////////////////////////////////////////////
// Just a dummy that logs reads and writes
// to be used for SI devices we haven't emulated
class CSIDevice_Dummy : public ISIDevice
{
public:
CSIDevice_Dummy(int _iDeviceNumber) :
ISIDevice(_iDeviceNumber)
{}
virtual ~CSIDevice_Dummy(){}
int RunBuffer(u8* _pBuffer, int _iLength)
{
// (shuffle2) Logging of this function will be done above, in ISIDevice::RunBuffer
// No device. (shuffle2) Maybe this should be SI_ERROR_NO_RESPONSE?
reinterpret_cast<u32*>(_pBuffer)[0] = 0x00000000;
return 4;
}
bool GetData(u32& _Hi, u32& _Low) {LOG(SERIALINTERFACE, "SI DUMMY %i GetData", this->m_iDeviceNumber); return false;}
void SendCommand(u32 _Cmd) {LOG(SERIALINTERFACE, "SI DUMMY %i SendCommand: %08x", this->m_iDeviceNumber, _Cmd);}
};
//////////////////////////////////////////////////////////////////////////
// F A C T O R Y /////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
ISIDevice* SIDevice_Create(TSIDevices _SIDevice, int _iDeviceNumber)
{
switch(_SIDevice)
{
case SI_DUMMY:
return new CSIDevice_Dummy(_iDeviceNumber);
break;
case SI_GC_CONTROLLER:
return new CSIDevice_GCController(_iDeviceNumber);
break;
case SI_GBA:
return new CSIDevice_GBA(_iDeviceNumber);
break;
}
return NULL;
}

View File

@ -1,173 +1,173 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <stdio.h>
#include <stdlib.h>
#include "SI_Device.h"
#include "SI_DeviceGCController.h"
#include "../PluginManager.h"
#include "EXI_Device.h"
#include "EXI_DeviceMic.h"
//////////////////////////////////////////////////////////////////////////
// --- standard gamecube controller ---
//////////////////////////////////////////////////////////////////////////
CSIDevice_GCController::CSIDevice_GCController(int _iDeviceNumber) :
ISIDevice(_iDeviceNumber)
{
memset(&m_origin, 0, sizeof(SOrigin));
m_origin.uCommand = 0x41;
m_origin.uOriginStickX = 0x80;
m_origin.uOriginStickY = 0x80;
m_origin.uSubStickStickX = 0x80;
m_origin.uSubStickStickY = 0x80;
m_origin.uTrigger_L = 0x1F;
m_origin.uTrigger_R = 0x1F;
}
int CSIDevice_GCController::RunBuffer(u8* _pBuffer, int _iLength)
{
// For debug logging only
ISIDevice::RunBuffer(_pBuffer, _iLength);
int iPosition = 0;
while(iPosition < _iLength)
{
// Read the command
EBufferCommands command = static_cast<EBufferCommands>(_pBuffer[iPosition ^ 3]);
iPosition++;
// Handle it
switch(command)
{
case CMD_RESET:
{
*(u32*)&_pBuffer[0] = SI_GC_CONTROLLER; // | SI_GC_NOMOTOR;
iPosition = _iLength; // Break the while loop
}
break;
case CMD_ORIGIN:
{
LOG(SERIALINTERFACE, "PAD - Get Origin");
u8* pCalibration = reinterpret_cast<u8*>(&m_origin);
for (int i = 0; i < (int)sizeof(SOrigin); i++)
{
_pBuffer[i ^ 3] = *pCalibration++;
}
}
iPosition = _iLength;
break;
// Recalibrate (FiRES: i am not 100 percent sure about this)
case CMD_RECALIBRATE:
{
LOG(SERIALINTERFACE, "PAD - Recalibrate");
u8* pCalibration = reinterpret_cast<u8*>(&m_origin);
for (int i = 0; i < (int)sizeof(SOrigin); i++)
{
_pBuffer[i ^ 3] = *pCalibration++;
}
}
iPosition = _iLength;
break;
// WII Something
case 0xCE:
LOG(SERIALINTERFACE, "Unknown Wii SI Command");
break;
// DEFAULT
default:
{
LOG(SERIALINTERFACE, "unknown SI command (0x%x)", command);
PanicAlert("SI: Unknown command");
iPosition = _iLength;
}
break;
}
}
return iPosition;
}
//////////////////////////////////////////////////////////////////////////
// GetData
//////////////////////////////////////////////////////////////////////////
// Return true on new data (max 7 Bytes and 6 bits ;)
bool
CSIDevice_GCController::GetData(u32& _Hi, u32& _Low)
{
SPADStatus PadStatus;
memset(&PadStatus, 0 ,sizeof(PadStatus));
Common::PluginPAD* pad = CPluginManager::GetInstance().GetPad(ISIDevice::m_iDeviceNumber);
pad->PAD_GetStatus(ISIDevice::m_iDeviceNumber, &PadStatus);
_Hi = (u32)((u8)PadStatus.stickY);
_Hi |= (u32)((u8)PadStatus.stickX << 8);
_Hi |= (u32)((u16)PadStatus.button << 16);
_Low = (u8)PadStatus.triggerRight;
_Low |= (u32)((u8)PadStatus.triggerLeft << 8);
_Low |= (u32)((u8)PadStatus.substickY << 16);
_Low |= (u32)((u8)PadStatus.substickX << 24);
SetMic(PadStatus.MicButton); // This is dumb and should not be here
// F|RES:
// i dunno if i should force it here
// means that the pad must be "combined" with the origin to math the "final" OSPad-Struct
_Hi |= 0x00800000;
return true;
}
//////////////////////////////////////////////////////////////////////////
// SendCommand
//////////////////////////////////////////////////////////////////////////
void
CSIDevice_GCController::SendCommand(u32 _Cmd)
{
Common::PluginPAD* pad = CPluginManager::GetInstance().GetPad(ISIDevice::m_iDeviceNumber);
UCommand command(_Cmd);
switch(command.Command)
{
// Costis sent it in some demos :)
case 0x00:
break;
case CMD_RUMBLE:
{
unsigned int uType = command.Parameter1; // 0 = stop, 1 = rumble, 2 = stop hard
unsigned int uStrength = command.Parameter2;
if (pad->PAD_Rumble)
pad->PAD_Rumble(ISIDevice::m_iDeviceNumber, uType, uStrength);
}
break;
default:
{
LOG(SERIALINTERFACE, "unknown direct command (0x%x)", _Cmd);
PanicAlert("SI: Unknown direct command");
}
break;
}
}
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <stdio.h>
#include <stdlib.h>
#include "SI_Device.h"
#include "SI_DeviceGCController.h"
#include "../PluginManager.h"
#include "EXI_Device.h"
#include "EXI_DeviceMic.h"
//////////////////////////////////////////////////////////////////////////
// --- standard gamecube controller ---
//////////////////////////////////////////////////////////////////////////
CSIDevice_GCController::CSIDevice_GCController(int _iDeviceNumber) :
ISIDevice(_iDeviceNumber)
{
memset(&m_origin, 0, sizeof(SOrigin));
m_origin.uCommand = 0x41;
m_origin.uOriginStickX = 0x80;
m_origin.uOriginStickY = 0x80;
m_origin.uSubStickStickX = 0x80;
m_origin.uSubStickStickY = 0x80;
m_origin.uTrigger_L = 0x1F;
m_origin.uTrigger_R = 0x1F;
}
int CSIDevice_GCController::RunBuffer(u8* _pBuffer, int _iLength)
{
// For debug logging only
ISIDevice::RunBuffer(_pBuffer, _iLength);
int iPosition = 0;
while(iPosition < _iLength)
{
// Read the command
EBufferCommands command = static_cast<EBufferCommands>(_pBuffer[iPosition ^ 3]);
iPosition++;
// Handle it
switch(command)
{
case CMD_RESET:
{
*(u32*)&_pBuffer[0] = SI_GC_CONTROLLER; // | SI_GC_NOMOTOR;
iPosition = _iLength; // Break the while loop
}
break;
case CMD_ORIGIN:
{
LOG(SERIALINTERFACE, "PAD - Get Origin");
u8* pCalibration = reinterpret_cast<u8*>(&m_origin);
for (int i = 0; i < (int)sizeof(SOrigin); i++)
{
_pBuffer[i ^ 3] = *pCalibration++;
}
}
iPosition = _iLength;
break;
// Recalibrate (FiRES: i am not 100 percent sure about this)
case CMD_RECALIBRATE:
{
LOG(SERIALINTERFACE, "PAD - Recalibrate");
u8* pCalibration = reinterpret_cast<u8*>(&m_origin);
for (int i = 0; i < (int)sizeof(SOrigin); i++)
{
_pBuffer[i ^ 3] = *pCalibration++;
}
}
iPosition = _iLength;
break;
// WII Something
case 0xCE:
LOG(SERIALINTERFACE, "Unknown Wii SI Command");
break;
// DEFAULT
default:
{
LOG(SERIALINTERFACE, "unknown SI command (0x%x)", command);
PanicAlert("SI: Unknown command");
iPosition = _iLength;
}
break;
}
}
return iPosition;
}
//////////////////////////////////////////////////////////////////////////
// GetData
//////////////////////////////////////////////////////////////////////////
// Return true on new data (max 7 Bytes and 6 bits ;)
bool
CSIDevice_GCController::GetData(u32& _Hi, u32& _Low)
{
SPADStatus PadStatus;
memset(&PadStatus, 0 ,sizeof(PadStatus));
Common::PluginPAD* pad = CPluginManager::GetInstance().GetPad(ISIDevice::m_iDeviceNumber);
pad->PAD_GetStatus(ISIDevice::m_iDeviceNumber, &PadStatus);
_Hi = (u32)((u8)PadStatus.stickY);
_Hi |= (u32)((u8)PadStatus.stickX << 8);
_Hi |= (u32)((u16)PadStatus.button << 16);
_Low = (u8)PadStatus.triggerRight;
_Low |= (u32)((u8)PadStatus.triggerLeft << 8);
_Low |= (u32)((u8)PadStatus.substickY << 16);
_Low |= (u32)((u8)PadStatus.substickX << 24);
SetMic(PadStatus.MicButton); // This is dumb and should not be here
// F|RES:
// i dunno if i should force it here
// means that the pad must be "combined" with the origin to math the "final" OSPad-Struct
_Hi |= 0x00800000;
return true;
}
//////////////////////////////////////////////////////////////////////////
// SendCommand
//////////////////////////////////////////////////////////////////////////
void
CSIDevice_GCController::SendCommand(u32 _Cmd)
{
Common::PluginPAD* pad = CPluginManager::GetInstance().GetPad(ISIDevice::m_iDeviceNumber);
UCommand command(_Cmd);
switch(command.Command)
{
// Costis sent it in some demos :)
case 0x00:
break;
case CMD_RUMBLE:
{
unsigned int uType = command.Parameter1; // 0 = stop, 1 = rumble, 2 = stop hard
unsigned int uStrength = command.Parameter2;
if (pad->PAD_Rumble)
pad->PAD_Rumble(ISIDevice::m_iDeviceNumber, uType, uStrength);
}
break;
default:
{
LOG(SERIALINTERFACE, "unknown direct command (0x%x)", _Cmd);
PanicAlert("SI: Unknown direct command");
}
break;
}
}

View File

@ -1,43 +1,43 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// HW Address: 0d07xxxx
#include "SDInterface.h"
namespace SDInterface
{
bool g_bIsCardInserted = false;
bool g_bIsDumpFile = false;
std::string sourcePath = "";
bool IsCardInserted()
{
return g_bIsCardInserted;
}
void SetSourceType(bool isDumpFile)
{
g_bIsDumpFile = isDumpFile;
}
void SetSourcePath(const std::string path)
{
sourcePath = path;
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// HW Address: 0d07xxxx
#include "SDInterface.h"
namespace SDInterface
{
bool g_bIsCardInserted = false;
bool g_bIsDumpFile = false;
std::string sourcePath = "";
bool IsCardInserted()
{
return g_bIsCardInserted;
}
void SetSourceType(bool isDumpFile)
{
g_bIsDumpFile = isDumpFile;
}
void SetSourcePath(const std::string path)
{
sourcePath = path;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,498 +1,498 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
//////////////////////////////////////////////////////////////////////////////////////////
// Include
// ¯¯¯¯¯¯¯¯¯¯
#include "Common.h"
#include <wx/button.h>
#include <wx/textctrl.h>
#include <wx/textdlg.h>
#include <wx/listctrl.h>
#include <wx/thread.h>
#include <wx/mstream.h>
#include <wx/tipwin.h>
#include <wx/fontdlg.h>
// ugly that this lib included code from the main
#include "../../DolphinWX/Src/Globals.h"
#include "Host.h"
#include "Debugger.h"
#include "RegisterWindow.h"
#include "LogWindow.h"
#include "BreakpointWindow.h"
#include "MemoryWindow.h"
#include "JitWindow.h"
#include "CodeWindow.h"
#include "CodeView.h"
#include "FileUtil.h"
#include "Core.h"
#include "HLE/HLE.h"
#include "Boot/Boot.h"
#include "LogManager.h"
#include "HW/CPU.h"
#include "PowerPC/PowerPC.h"
#include "Debugger/PPCDebugInterface.h"
#include "Debugger/Debugger_SymbolMap.h"
#include "PowerPC/PPCAnalyst.h"
#include "PowerPC/Profiler.h"
#include "PowerPC/SymbolDB.h"
#include "PowerPC/SignatureDB.h"
#include "PowerPC/PPCTables.h"
#include "PowerPC/Jit64/Jit.h"
#include "PowerPC/Jit64/JitCache.h" // for ClearCache()
#include "PluginManager.h"
#include "ConfigManager.h"
extern "C" // Bitmaps
{
#include "../resources/toolbar_play.c"
#include "../resources/toolbar_pause.c"
#include "../resources/toolbar_add_memorycheck.c"
#include "../resources/toolbar_delete.c"
#include "../resources/toolbar_add_breakpoint.c"
}
///////////////////////////////////
void CCodeWindow::CreateSymbolsMenu()
{
wxMenu *pSymbolsMenu = new wxMenu;
pSymbolsMenu->Append(IDM_CLEARSYMBOLS, _T("&Clear symbols"));
// pSymbolsMenu->Append(IDM_CLEANSYMBOLS, _T("&Clean symbols (zz)"));
pSymbolsMenu->Append(IDM_SCANFUNCTIONS, _T("&Generate symbol map"));
pSymbolsMenu->AppendSeparator();
pSymbolsMenu->Append(IDM_LOADMAPFILE, _T("&Load symbol map"));
pSymbolsMenu->Append(IDM_SAVEMAPFILE, _T("&Save symbol map"));
pSymbolsMenu->AppendSeparator();
pSymbolsMenu->Append(IDM_SAVEMAPFILEWITHCODES, _T("Save code"),
wxString::FromAscii("Save the entire disassembled code. This may take a several seconds"
" and may require between 50 and 100 MB of hard drive space. It will only save code"
" that are in the first 4 MB of memory, if you are debugging a game that load .rel"
" files with code to memory you may want to increase that to perhaps 8 MB, you can do"
" that from SymbolDB::SaveMap().")
);
pSymbolsMenu->AppendSeparator();
pSymbolsMenu->Append(IDM_CREATESIGNATUREFILE, _T("&Create signature file..."));
pSymbolsMenu->Append(IDM_USESIGNATUREFILE, _T("&Use signature file..."));
pSymbolsMenu->AppendSeparator();
pSymbolsMenu->Append(IDM_PATCHHLEFUNCTIONS, _T("&Patch HLE functions"));
pMenuBar->Append(pSymbolsMenu, _T("&Symbols"));
wxMenu *pJitMenu = new wxMenu;
pJitMenu->Append(IDM_CLEARCODECACHE, _T("&Clear code cache"));
pJitMenu->Append(IDM_LOGINSTRUCTIONS, _T("&Log JIT instruction coverage"));
pMenuBar->Append(pJitMenu, _T("&JIT"));
wxMenu *pProfilerMenu = new wxMenu;
pProfilerMenu->Append(IDM_PROFILEBLOCKS, _T("&Profile blocks"), wxEmptyString, wxITEM_CHECK);
pProfilerMenu->AppendSeparator();
pProfilerMenu->Append(IDM_WRITEPROFILE, _T("&Write to profile.txt, show"));
pMenuBar->Append(pProfilerMenu, _T("&Profiler"));
}
void CCodeWindow::OnProfilerMenu(wxCommandEvent& event)
{
if (Core::GetState() == Core::CORE_RUN) {
event.Skip();
return;
}
switch (event.GetId())
{
case IDM_PROFILEBLOCKS:
jit.ClearCache();
Profiler::g_ProfileBlocks = GetMenuBar()->IsChecked(IDM_PROFILEBLOCKS);
break;
case IDM_WRITEPROFILE:
Profiler::WriteProfileResults("profiler.txt");
File::Launch("profiler.txt");
break;
}
}
void CCodeWindow::OnSymbolsMenu(wxCommandEvent& event)
{
if (Core::GetState() == Core::CORE_UNINITIALIZED)
{
// TODO: disable menu items instead :P
return;
}
std::string mapfile = CBoot::GenerateMapFilename();
switch (event.GetId())
{
case IDM_CLEARSYMBOLS:
g_symbolDB.Clear();
Host_NotifyMapLoaded();
break;
case IDM_CLEANSYMBOLS:
g_symbolDB.Clear("zz");
Host_NotifyMapLoaded();
break;
case IDM_SCANFUNCTIONS:
{
PPCAnalyst::FindFunctions(0x80000000, 0x80400000, &g_symbolDB);
SignatureDB db;
if (db.Load(TOTALDB_FILE))
db.Apply(&g_symbolDB);
// HLE::PatchFunctions();
NotifyMapLoaded();
break;
}
case IDM_LOADMAPFILE:
if (!File::Exists(mapfile.c_str()))
{
g_symbolDB.Clear();
PPCAnalyst::FindFunctions(0x80000000, 0x80400000, &g_symbolDB);
SignatureDB db;
if (db.Load(TOTALDB_FILE))
db.Apply(&g_symbolDB);
} else {
g_symbolDB.LoadMap(mapfile.c_str());
}
NotifyMapLoaded();
break;
case IDM_SAVEMAPFILE:
g_symbolDB.SaveMap(mapfile.c_str());
break;
case IDM_SAVEMAPFILEWITHCODES:
g_symbolDB.SaveMap(mapfile.c_str(), true);
break;
case IDM_CREATESIGNATUREFILE:
{
wxTextEntryDialog input_prefix(this, wxString::FromAscii("Only export symbols with prefix:"), wxGetTextFromUserPromptStr, _T("."));
if (input_prefix.ShowModal() == wxID_OK) {
std::string prefix(input_prefix.GetValue().mb_str());
wxString path = wxFileSelector(
_T("Save signature as"), wxEmptyString, wxEmptyString, wxEmptyString,
_T("Dolphin Signature File (*.dsy)|*.dsy;"), wxFD_SAVE,
this);
if (path) {
SignatureDB db;
db.Initialize(&g_symbolDB, prefix.c_str());
std::string filename(path.ToAscii()); // PPCAnalyst::SaveSignatureDB(
db.Save(path.ToAscii());
}
}
}
break;
case IDM_USESIGNATUREFILE:
{
wxString path = wxFileSelector(
_T("Apply signature file"), wxEmptyString, wxEmptyString, wxEmptyString,
_T("Dolphin Signature File (*.dsy)|*.dsy;"), wxFD_OPEN | wxFD_FILE_MUST_EXIST,
this);
if (path) {
SignatureDB db;
db.Load(path.ToAscii());
db.Apply(&g_symbolDB);
}
}
NotifyMapLoaded();
break;
case IDM_PATCHHLEFUNCTIONS:
HLE::PatchFunctions();
Update();
break;
}
}
void CCodeWindow::NotifyMapLoaded()
{
g_symbolDB.FillInCallers();
//symbols->Show(false); // hide it for faster filling
symbols->Freeze(); // HyperIris: wx style fast filling
symbols->Clear();
for (SymbolDB::XFuncMap::iterator iter = g_symbolDB.GetIterator(); iter != g_symbolDB.End(); iter++)
{
int idx = symbols->Append(wxString::FromAscii(iter->second.name.c_str()));
symbols->SetClientData(idx, (void*)&iter->second);
}
symbols->Thaw();
//symbols->Show(true);
Update();
}
void CCodeWindow::OnSymbolListChange(wxCommandEvent& event)
{
int index = symbols->GetSelection();
if (index >= 0) {
Symbol* pSymbol = static_cast<Symbol *>(symbols->GetClientData(index));
if (pSymbol != NULL)
{
if(pSymbol->type == Symbol::SYMBOL_DATA)
{
if(m_MemoryWindow && m_MemoryWindow->IsVisible())
m_MemoryWindow->JumpToAddress(pSymbol->address);
}
else
{
JumpToAddress(pSymbol->address);
}
}
}
}
void CCodeWindow::OnSymbolListContextMenu(wxContextMenuEvent& event)
{
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// Show and hide windows
/////////////////////////////////////////////////////////////////////////////////////////////////
void CCodeWindow::OnToggleLogWindow(wxCommandEvent& event)
{
if (LogManager::Enabled())
{
bool show = GetMenuBar()->IsChecked(event.GetId());
if (show)
{
if (!m_LogWindow)
{
m_LogWindow = new CLogWindow(this);
}
m_LogWindow->Show(true);
}
else // hide
{
// If m_dialog is NULL, then possibly the system
// didn't report the checked menu item status correctly.
// It should be true just after the menu item was selected,
// if there was no modeless dialog yet.
wxASSERT(m_LogWindow != NULL);
if (m_LogWindow)
{
m_LogWindow->Hide();
}
}
}
}
void CCodeWindow::OnToggleRegisterWindow(wxCommandEvent& event)
{
bool show = GetMenuBar()->IsChecked(event.GetId());
if (show)
{
if (!m_RegisterWindow)
{
m_RegisterWindow = new CRegisterWindow(this);
}
m_RegisterWindow->Show(true);
}
else // hide
{
// If m_dialog is NULL, then possibly the system
// didn't report the checked menu item status correctly.
// It should be true just after the menu item was selected,
// if there was no modeless dialog yet.
wxASSERT(m_RegisterWindow != NULL);
if (m_RegisterWindow)
{
m_RegisterWindow->Hide();
}
}
}
// =======================================================================================
// Toggle Sound Debugging Window
// ------------
void CCodeWindow::OnToggleSoundWindow(wxCommandEvent& event)
{
bool show = GetMenuBar()->IsChecked(event.GetId());
if (show)
{
// TODO: add some kind of if() check here to?
CPluginManager::GetInstance().OpenDebug(
GetHandle(),
SConfig::GetInstance().m_LocalCoreStartupParameter.m_strDSPPlugin.c_str(),
PLUGIN_TYPE_DSP, true // DSP, show
);
}
else // hide
{
// Close the sound dll that has an open debugger
CPluginManager::GetInstance().OpenDebug(
GetHandle(),
SConfig::GetInstance().m_LocalCoreStartupParameter.m_strDSPPlugin.c_str(),
PLUGIN_TYPE_DSP, false // DSP, hide
);
}
}
// ===========
// =======================================================================================
// Toggle Video Debugging Window
// ------------
void CCodeWindow::OnToggleVideoWindow(wxCommandEvent& event)
{
bool show = GetMenuBar()->IsChecked(event.GetId());
//GetMenuBar()->Check(event.GetId(), false); // Turn off
if (show)
{
// It works now, but I'll keep this message in case the problem reappears
/*if(Core::GetState() == Core::CORE_UNINITIALIZED)
{
wxMessageBox(_T("Warning, opening this window before a game is started \n\
may cause a crash when a game is later started. Todo: figure out why and fix it."), wxT("OpenGL Debugging Window"));
}*/
// TODO: add some kind of if() check here to?
CPluginManager::GetInstance().OpenDebug(
GetHandle(),
SConfig::GetInstance().m_LocalCoreStartupParameter.m_strVideoPlugin.c_str(),
PLUGIN_TYPE_VIDEO, true // Video, show
);
}
else // hide
{
// Close the video dll that has an open debugger
CPluginManager::GetInstance().OpenDebug(
GetHandle(),
SConfig::GetInstance().m_LocalCoreStartupParameter.m_strVideoPlugin.c_str(),
PLUGIN_TYPE_VIDEO, false // Video, hide
);
}
}
// ===========
void CCodeWindow::OnToggleJitWindow(wxCommandEvent& event)
{
bool show = GetMenuBar()->IsChecked(event.GetId());
if (show)
{
if (!m_JitWindow)
{
m_JitWindow = new CJitWindow(this);
}
m_JitWindow->Show(true);
}
else // hide
{
// If m_dialog is NULL, then possibly the system
// didn't report the checked menu item status correctly.
// It should be true just after the menu item was selected,
// if there was no modeless dialog yet.
wxASSERT(m_JitWindow != NULL);
if (m_JitWindow)
{
m_JitWindow->Hide();
}
}
}
void CCodeWindow::OnToggleBreakPointWindow(wxCommandEvent& event)
{
bool show = GetMenuBar()->IsChecked(event.GetId());
if (show)
{
if (!m_BreakpointWindow)
{
m_BreakpointWindow = new CBreakPointWindow(this, this);
}
m_BreakpointWindow->Show(true);
}
else // hide
{
// If m_dialog is NULL, then possibly the system
// didn't report the checked menu item status correctly.
// It should be true just after the menu item was selected,
// if there was no modeless dialog yet.
wxASSERT(m_BreakpointWindow != NULL);
if (m_BreakpointWindow)
{
m_BreakpointWindow->Hide();
}
}
}
void CCodeWindow::OnToggleMemoryWindow(wxCommandEvent& event)
{
bool show = GetMenuBar()->IsChecked(event.GetId());
if (show)
{
if (!m_MemoryWindow)
{
m_MemoryWindow = new CMemoryWindow(this);
}
m_MemoryWindow->Show(true);
}
else // hide
{
// If m_dialog is NULL, then possibly the system
// didn't report the checked menu item status correctly.
// It should be true just after the menu item was selected,
// if there was no modeless dialog yet.
wxASSERT(m_MemoryWindow != NULL);
if (m_MemoryWindow)
{
m_MemoryWindow->Hide();
}
}
}
//////////////////////////////////////////////////////////////////////////
// Change the global DebuggerFont
void CCodeWindow::OnChangeFont(wxCommandEvent& event)
{
wxFontData data;
data.SetInitialFont(GetFont());
wxFontDialog dialog(this, data);
if ( dialog.ShowModal() == wxID_OK )
DebuggerFont = dialog.GetFontData().GetChosenFont();
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
//////////////////////////////////////////////////////////////////////////////////////////
// Include
// ¯¯¯¯¯¯¯¯¯¯
#include "Common.h"
#include <wx/button.h>
#include <wx/textctrl.h>
#include <wx/textdlg.h>
#include <wx/listctrl.h>
#include <wx/thread.h>
#include <wx/mstream.h>
#include <wx/tipwin.h>
#include <wx/fontdlg.h>
// ugly that this lib included code from the main
#include "../../DolphinWX/Src/Globals.h"
#include "Host.h"
#include "Debugger.h"
#include "RegisterWindow.h"
#include "LogWindow.h"
#include "BreakpointWindow.h"
#include "MemoryWindow.h"
#include "JitWindow.h"
#include "CodeWindow.h"
#include "CodeView.h"
#include "FileUtil.h"
#include "Core.h"
#include "HLE/HLE.h"
#include "Boot/Boot.h"
#include "LogManager.h"
#include "HW/CPU.h"
#include "PowerPC/PowerPC.h"
#include "Debugger/PPCDebugInterface.h"
#include "Debugger/Debugger_SymbolMap.h"
#include "PowerPC/PPCAnalyst.h"
#include "PowerPC/Profiler.h"
#include "PowerPC/SymbolDB.h"
#include "PowerPC/SignatureDB.h"
#include "PowerPC/PPCTables.h"
#include "PowerPC/Jit64/Jit.h"
#include "PowerPC/Jit64/JitCache.h" // for ClearCache()
#include "PluginManager.h"
#include "ConfigManager.h"
extern "C" // Bitmaps
{
#include "../resources/toolbar_play.c"
#include "../resources/toolbar_pause.c"
#include "../resources/toolbar_add_memorycheck.c"
#include "../resources/toolbar_delete.c"
#include "../resources/toolbar_add_breakpoint.c"
}
///////////////////////////////////
void CCodeWindow::CreateSymbolsMenu()
{
wxMenu *pSymbolsMenu = new wxMenu;
pSymbolsMenu->Append(IDM_CLEARSYMBOLS, _T("&Clear symbols"));
// pSymbolsMenu->Append(IDM_CLEANSYMBOLS, _T("&Clean symbols (zz)"));
pSymbolsMenu->Append(IDM_SCANFUNCTIONS, _T("&Generate symbol map"));
pSymbolsMenu->AppendSeparator();
pSymbolsMenu->Append(IDM_LOADMAPFILE, _T("&Load symbol map"));
pSymbolsMenu->Append(IDM_SAVEMAPFILE, _T("&Save symbol map"));
pSymbolsMenu->AppendSeparator();
pSymbolsMenu->Append(IDM_SAVEMAPFILEWITHCODES, _T("Save code"),
wxString::FromAscii("Save the entire disassembled code. This may take a several seconds"
" and may require between 50 and 100 MB of hard drive space. It will only save code"
" that are in the first 4 MB of memory, if you are debugging a game that load .rel"
" files with code to memory you may want to increase that to perhaps 8 MB, you can do"
" that from SymbolDB::SaveMap().")
);
pSymbolsMenu->AppendSeparator();
pSymbolsMenu->Append(IDM_CREATESIGNATUREFILE, _T("&Create signature file..."));
pSymbolsMenu->Append(IDM_USESIGNATUREFILE, _T("&Use signature file..."));
pSymbolsMenu->AppendSeparator();
pSymbolsMenu->Append(IDM_PATCHHLEFUNCTIONS, _T("&Patch HLE functions"));
pMenuBar->Append(pSymbolsMenu, _T("&Symbols"));
wxMenu *pJitMenu = new wxMenu;
pJitMenu->Append(IDM_CLEARCODECACHE, _T("&Clear code cache"));
pJitMenu->Append(IDM_LOGINSTRUCTIONS, _T("&Log JIT instruction coverage"));
pMenuBar->Append(pJitMenu, _T("&JIT"));
wxMenu *pProfilerMenu = new wxMenu;
pProfilerMenu->Append(IDM_PROFILEBLOCKS, _T("&Profile blocks"), wxEmptyString, wxITEM_CHECK);
pProfilerMenu->AppendSeparator();
pProfilerMenu->Append(IDM_WRITEPROFILE, _T("&Write to profile.txt, show"));
pMenuBar->Append(pProfilerMenu, _T("&Profiler"));
}
void CCodeWindow::OnProfilerMenu(wxCommandEvent& event)
{
if (Core::GetState() == Core::CORE_RUN) {
event.Skip();
return;
}
switch (event.GetId())
{
case IDM_PROFILEBLOCKS:
jit.ClearCache();
Profiler::g_ProfileBlocks = GetMenuBar()->IsChecked(IDM_PROFILEBLOCKS);
break;
case IDM_WRITEPROFILE:
Profiler::WriteProfileResults("profiler.txt");
File::Launch("profiler.txt");
break;
}
}
void CCodeWindow::OnSymbolsMenu(wxCommandEvent& event)
{
if (Core::GetState() == Core::CORE_UNINITIALIZED)
{
// TODO: disable menu items instead :P
return;
}
std::string mapfile = CBoot::GenerateMapFilename();
switch (event.GetId())
{
case IDM_CLEARSYMBOLS:
g_symbolDB.Clear();
Host_NotifyMapLoaded();
break;
case IDM_CLEANSYMBOLS:
g_symbolDB.Clear("zz");
Host_NotifyMapLoaded();
break;
case IDM_SCANFUNCTIONS:
{
PPCAnalyst::FindFunctions(0x80000000, 0x80400000, &g_symbolDB);
SignatureDB db;
if (db.Load(TOTALDB_FILE))
db.Apply(&g_symbolDB);
// HLE::PatchFunctions();
NotifyMapLoaded();
break;
}
case IDM_LOADMAPFILE:
if (!File::Exists(mapfile.c_str()))
{
g_symbolDB.Clear();
PPCAnalyst::FindFunctions(0x80000000, 0x80400000, &g_symbolDB);
SignatureDB db;
if (db.Load(TOTALDB_FILE))
db.Apply(&g_symbolDB);
} else {
g_symbolDB.LoadMap(mapfile.c_str());
}
NotifyMapLoaded();
break;
case IDM_SAVEMAPFILE:
g_symbolDB.SaveMap(mapfile.c_str());
break;
case IDM_SAVEMAPFILEWITHCODES:
g_symbolDB.SaveMap(mapfile.c_str(), true);
break;
case IDM_CREATESIGNATUREFILE:
{
wxTextEntryDialog input_prefix(this, wxString::FromAscii("Only export symbols with prefix:"), wxGetTextFromUserPromptStr, _T("."));
if (input_prefix.ShowModal() == wxID_OK) {
std::string prefix(input_prefix.GetValue().mb_str());
wxString path = wxFileSelector(
_T("Save signature as"), wxEmptyString, wxEmptyString, wxEmptyString,
_T("Dolphin Signature File (*.dsy)|*.dsy;"), wxFD_SAVE,
this);
if (path) {
SignatureDB db;
db.Initialize(&g_symbolDB, prefix.c_str());
std::string filename(path.ToAscii()); // PPCAnalyst::SaveSignatureDB(
db.Save(path.ToAscii());
}
}
}
break;
case IDM_USESIGNATUREFILE:
{
wxString path = wxFileSelector(
_T("Apply signature file"), wxEmptyString, wxEmptyString, wxEmptyString,
_T("Dolphin Signature File (*.dsy)|*.dsy;"), wxFD_OPEN | wxFD_FILE_MUST_EXIST,
this);
if (path) {
SignatureDB db;
db.Load(path.ToAscii());
db.Apply(&g_symbolDB);
}
}
NotifyMapLoaded();
break;
case IDM_PATCHHLEFUNCTIONS:
HLE::PatchFunctions();
Update();
break;
}
}
void CCodeWindow::NotifyMapLoaded()
{
g_symbolDB.FillInCallers();
//symbols->Show(false); // hide it for faster filling
symbols->Freeze(); // HyperIris: wx style fast filling
symbols->Clear();
for (SymbolDB::XFuncMap::iterator iter = g_symbolDB.GetIterator(); iter != g_symbolDB.End(); iter++)
{
int idx = symbols->Append(wxString::FromAscii(iter->second.name.c_str()));
symbols->SetClientData(idx, (void*)&iter->second);
}
symbols->Thaw();
//symbols->Show(true);
Update();
}
void CCodeWindow::OnSymbolListChange(wxCommandEvent& event)
{
int index = symbols->GetSelection();
if (index >= 0) {
Symbol* pSymbol = static_cast<Symbol *>(symbols->GetClientData(index));
if (pSymbol != NULL)
{
if(pSymbol->type == Symbol::SYMBOL_DATA)
{
if(m_MemoryWindow && m_MemoryWindow->IsVisible())
m_MemoryWindow->JumpToAddress(pSymbol->address);
}
else
{
JumpToAddress(pSymbol->address);
}
}
}
}
void CCodeWindow::OnSymbolListContextMenu(wxContextMenuEvent& event)
{
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// Show and hide windows
/////////////////////////////////////////////////////////////////////////////////////////////////
void CCodeWindow::OnToggleLogWindow(wxCommandEvent& event)
{
if (LogManager::Enabled())
{
bool show = GetMenuBar()->IsChecked(event.GetId());
if (show)
{
if (!m_LogWindow)
{
m_LogWindow = new CLogWindow(this);
}
m_LogWindow->Show(true);
}
else // hide
{
// If m_dialog is NULL, then possibly the system
// didn't report the checked menu item status correctly.
// It should be true just after the menu item was selected,
// if there was no modeless dialog yet.
wxASSERT(m_LogWindow != NULL);
if (m_LogWindow)
{
m_LogWindow->Hide();
}
}
}
}
void CCodeWindow::OnToggleRegisterWindow(wxCommandEvent& event)
{
bool show = GetMenuBar()->IsChecked(event.GetId());
if (show)
{
if (!m_RegisterWindow)
{
m_RegisterWindow = new CRegisterWindow(this);
}
m_RegisterWindow->Show(true);
}
else // hide
{
// If m_dialog is NULL, then possibly the system
// didn't report the checked menu item status correctly.
// It should be true just after the menu item was selected,
// if there was no modeless dialog yet.
wxASSERT(m_RegisterWindow != NULL);
if (m_RegisterWindow)
{
m_RegisterWindow->Hide();
}
}
}
// =======================================================================================
// Toggle Sound Debugging Window
// ------------
void CCodeWindow::OnToggleSoundWindow(wxCommandEvent& event)
{
bool show = GetMenuBar()->IsChecked(event.GetId());
if (show)
{
// TODO: add some kind of if() check here to?
CPluginManager::GetInstance().OpenDebug(
GetHandle(),
SConfig::GetInstance().m_LocalCoreStartupParameter.m_strDSPPlugin.c_str(),
PLUGIN_TYPE_DSP, true // DSP, show
);
}
else // hide
{
// Close the sound dll that has an open debugger
CPluginManager::GetInstance().OpenDebug(
GetHandle(),
SConfig::GetInstance().m_LocalCoreStartupParameter.m_strDSPPlugin.c_str(),
PLUGIN_TYPE_DSP, false // DSP, hide
);
}
}
// ===========
// =======================================================================================
// Toggle Video Debugging Window
// ------------
void CCodeWindow::OnToggleVideoWindow(wxCommandEvent& event)
{
bool show = GetMenuBar()->IsChecked(event.GetId());
//GetMenuBar()->Check(event.GetId(), false); // Turn off
if (show)
{
// It works now, but I'll keep this message in case the problem reappears
/*if(Core::GetState() == Core::CORE_UNINITIALIZED)
{
wxMessageBox(_T("Warning, opening this window before a game is started \n\
may cause a crash when a game is later started. Todo: figure out why and fix it."), wxT("OpenGL Debugging Window"));
}*/
// TODO: add some kind of if() check here to?
CPluginManager::GetInstance().OpenDebug(
GetHandle(),
SConfig::GetInstance().m_LocalCoreStartupParameter.m_strVideoPlugin.c_str(),
PLUGIN_TYPE_VIDEO, true // Video, show
);
}
else // hide
{
// Close the video dll that has an open debugger
CPluginManager::GetInstance().OpenDebug(
GetHandle(),
SConfig::GetInstance().m_LocalCoreStartupParameter.m_strVideoPlugin.c_str(),
PLUGIN_TYPE_VIDEO, false // Video, hide
);
}
}
// ===========
void CCodeWindow::OnToggleJitWindow(wxCommandEvent& event)
{
bool show = GetMenuBar()->IsChecked(event.GetId());
if (show)
{
if (!m_JitWindow)
{
m_JitWindow = new CJitWindow(this);
}
m_JitWindow->Show(true);
}
else // hide
{
// If m_dialog is NULL, then possibly the system
// didn't report the checked menu item status correctly.
// It should be true just after the menu item was selected,
// if there was no modeless dialog yet.
wxASSERT(m_JitWindow != NULL);
if (m_JitWindow)
{
m_JitWindow->Hide();
}
}
}
void CCodeWindow::OnToggleBreakPointWindow(wxCommandEvent& event)
{
bool show = GetMenuBar()->IsChecked(event.GetId());
if (show)
{
if (!m_BreakpointWindow)
{
m_BreakpointWindow = new CBreakPointWindow(this, this);
}
m_BreakpointWindow->Show(true);
}
else // hide
{
// If m_dialog is NULL, then possibly the system
// didn't report the checked menu item status correctly.
// It should be true just after the menu item was selected,
// if there was no modeless dialog yet.
wxASSERT(m_BreakpointWindow != NULL);
if (m_BreakpointWindow)
{
m_BreakpointWindow->Hide();
}
}
}
void CCodeWindow::OnToggleMemoryWindow(wxCommandEvent& event)
{
bool show = GetMenuBar()->IsChecked(event.GetId());
if (show)
{
if (!m_MemoryWindow)
{
m_MemoryWindow = new CMemoryWindow(this);
}
m_MemoryWindow->Show(true);
}
else // hide
{
// If m_dialog is NULL, then possibly the system
// didn't report the checked menu item status correctly.
// It should be true just after the menu item was selected,
// if there was no modeless dialog yet.
wxASSERT(m_MemoryWindow != NULL);
if (m_MemoryWindow)
{
m_MemoryWindow->Hide();
}
}
}
//////////////////////////////////////////////////////////////////////////
// Change the global DebuggerFont
void CCodeWindow::OnChangeFont(wxCommandEvent& event)
{
wxFontData data;
data.SetInitialFont(GetFont());
wxFontDialog dialog(this, data);
if ( dialog.ShowModal() == wxID_OK )
DebuggerFont = dialog.GetFontData().GetChosenFont();
}

View File

@ -1,145 +1,145 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "ARCodeAddEdit.h"
extern std::vector<ActionReplay::ARCode> arCodes;
BEGIN_EVENT_TABLE(CARCodeAddEdit, wxDialog)
EVT_CLOSE(CARCodeAddEdit::OnClose)
EVT_BUTTON(wxID_OK, CARCodeAddEdit::SaveCheatData)
EVT_SPIN(ID_ENTRY_SELECT, CARCodeAddEdit::ChangeEntry)
END_EVENT_TABLE()
CARCodeAddEdit::CARCodeAddEdit(int _selection, wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& position, const wxSize& size, long style)
: wxDialog(parent, id, title, position, size, style)
{
selection = _selection;
CreateGUIControls(selection);
}
CARCodeAddEdit::~CARCodeAddEdit()
{
}
void CARCodeAddEdit::CreateGUIControls(int _selection)
{
wxString currentName = wxT("<Insert name here>");
if (_selection == -1)
{
tempEntries.name = "";
}
else
{
currentName = wxString::FromAscii(arCodes.at(_selection).name.c_str());
tempEntries = arCodes.at(_selection);
}
wxBoxSizer* sEditCheat = new wxBoxSizer(wxVERTICAL);
wxStaticBoxSizer* sbEntry = new wxStaticBoxSizer(wxVERTICAL, this, _("Code"));
wxStaticText* EditCheatNameText = new wxStaticText(this, ID_EDITCHEAT_NAME_TEXT, _("Name:"), wxDefaultPosition, wxDefaultSize);
EditCheatName = new wxTextCtrl(this, ID_EDITCHEAT_NAME, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0);
EditCheatName->SetValue(currentName);
EntrySelection = new wxSpinButton(this, ID_ENTRY_SELECT, wxDefaultPosition, wxDefaultSize, wxVERTICAL);
EntrySelection->SetRange(0, (int)arCodes.size()-1);
EntrySelection->SetValue((int)arCodes.size()-1 - _selection);
EditCheatCode = new wxTextCtrl(this, ID_EDITCHEAT_CODE, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE);
UpdateTextCtrl(tempEntries);
wxGridBagSizer* sgEntry = new wxGridBagSizer(0, 0);
sgEntry->AddGrowableCol(1);
sgEntry->AddGrowableRow(1);
sgEntry->Add(EditCheatNameText, wxGBPosition(0, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, 5);
sgEntry->Add(EditCheatName, wxGBPosition(0, 1), wxGBSpan(1, 1), wxEXPAND|wxALL, 5);
sgEntry->Add(EntrySelection, wxGBPosition(0, 2), wxGBSpan(2, 1), wxEXPAND|wxALL, 5);
sgEntry->Add(EditCheatCode, wxGBPosition(1, 0), wxGBSpan(1, 2), wxEXPAND|wxALL, 5);
sbEntry->Add(sgEntry, 1, wxEXPAND);
sEditCheat->Add(sbEntry, 1, wxEXPAND|wxALL, 5);
wxBoxSizer* sEditCheatButtons = new wxBoxSizer(wxHORIZONTAL);
wxButton* bOK = new wxButton(this, wxID_OK, _("OK"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
wxButton* bCancel = new wxButton(this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
sEditCheatButtons->Add(0, 0, 1, wxEXPAND, 5);
sEditCheatButtons->Add(bOK, 0, wxALL, 5);
sEditCheatButtons->Add(bCancel, 0, wxALL, 5);
sEditCheat->Add(sEditCheatButtons, 0, wxEXPAND, 5);
this->SetSizer(sEditCheat);
sEditCheat->Layout();
}
void CARCodeAddEdit::OnClose(wxCloseEvent& WXUNUSED (event))
{
Destroy();
}
void CARCodeAddEdit::ChangeEntry(wxSpinEvent& event)
{
ActionReplay::ARCode currentCode = arCodes.at((int)arCodes.size()-1 - event.GetPosition());
EditCheatName->SetValue(wxString::FromAscii(currentCode.name.c_str()));
UpdateTextCtrl(currentCode);
}
void CARCodeAddEdit::SaveCheatData(wxCommandEvent& WXUNUSED (event))
{
std::vector<ActionReplay::AREntry> tempEntries;
std::string cheatValues = std::string(EditCheatCode->GetValue().mb_str());
bool bWhile = true; size_t line = 0;
while (bWhile)
{
bWhile = false;
u32 addr, value;
addr = strtol(std::string(cheatValues.substr(line, line+8)).c_str(), NULL, 16); // cmd_addr of ArCode
value = strtol(std::string(cheatValues.substr(line+9, line+17)).c_str(), NULL, 16); // value of ArCode
tempEntries.push_back(ActionReplay::AREntry(addr, value));
line = cheatValues.find("\n", line);
if (line != std::string::npos && cheatValues.length() > (line+17))
bWhile = true; // newline found, if not empty, go on
line++;
}
if (selection == -1)
{
ActionReplay::ARCode newCheat;
newCheat.name = std::string(EditCheatName->GetValue().mb_str());
newCheat.ops = tempEntries;
newCheat.active = true;
arCodes.push_back(newCheat);
}
else
{
arCodes.at(selection).name = std::string(EditCheatName->GetValue().mb_str());
arCodes.at(selection).ops = tempEntries;
}
AcceptAndClose();
}
void CARCodeAddEdit::UpdateTextCtrl(ActionReplay::ARCode arCode)
{
EditCheatCode->Clear();
for (u32 i = 0; i < arCode.ops.size(); i++)
EditCheatCode->AppendText(wxString::Format(wxT("%08X %08X\n"), arCode.ops.at(i).cmd_addr, arCode.ops.at(i).value));
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "ARCodeAddEdit.h"
extern std::vector<ActionReplay::ARCode> arCodes;
BEGIN_EVENT_TABLE(CARCodeAddEdit, wxDialog)
EVT_CLOSE(CARCodeAddEdit::OnClose)
EVT_BUTTON(wxID_OK, CARCodeAddEdit::SaveCheatData)
EVT_SPIN(ID_ENTRY_SELECT, CARCodeAddEdit::ChangeEntry)
END_EVENT_TABLE()
CARCodeAddEdit::CARCodeAddEdit(int _selection, wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& position, const wxSize& size, long style)
: wxDialog(parent, id, title, position, size, style)
{
selection = _selection;
CreateGUIControls(selection);
}
CARCodeAddEdit::~CARCodeAddEdit()
{
}
void CARCodeAddEdit::CreateGUIControls(int _selection)
{
wxString currentName = wxT("<Insert name here>");
if (_selection == -1)
{
tempEntries.name = "";
}
else
{
currentName = wxString::FromAscii(arCodes.at(_selection).name.c_str());
tempEntries = arCodes.at(_selection);
}
wxBoxSizer* sEditCheat = new wxBoxSizer(wxVERTICAL);
wxStaticBoxSizer* sbEntry = new wxStaticBoxSizer(wxVERTICAL, this, _("Code"));
wxStaticText* EditCheatNameText = new wxStaticText(this, ID_EDITCHEAT_NAME_TEXT, _("Name:"), wxDefaultPosition, wxDefaultSize);
EditCheatName = new wxTextCtrl(this, ID_EDITCHEAT_NAME, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0);
EditCheatName->SetValue(currentName);
EntrySelection = new wxSpinButton(this, ID_ENTRY_SELECT, wxDefaultPosition, wxDefaultSize, wxVERTICAL);
EntrySelection->SetRange(0, (int)arCodes.size()-1);
EntrySelection->SetValue((int)arCodes.size()-1 - _selection);
EditCheatCode = new wxTextCtrl(this, ID_EDITCHEAT_CODE, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE);
UpdateTextCtrl(tempEntries);
wxGridBagSizer* sgEntry = new wxGridBagSizer(0, 0);
sgEntry->AddGrowableCol(1);
sgEntry->AddGrowableRow(1);
sgEntry->Add(EditCheatNameText, wxGBPosition(0, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, 5);
sgEntry->Add(EditCheatName, wxGBPosition(0, 1), wxGBSpan(1, 1), wxEXPAND|wxALL, 5);
sgEntry->Add(EntrySelection, wxGBPosition(0, 2), wxGBSpan(2, 1), wxEXPAND|wxALL, 5);
sgEntry->Add(EditCheatCode, wxGBPosition(1, 0), wxGBSpan(1, 2), wxEXPAND|wxALL, 5);
sbEntry->Add(sgEntry, 1, wxEXPAND);
sEditCheat->Add(sbEntry, 1, wxEXPAND|wxALL, 5);
wxBoxSizer* sEditCheatButtons = new wxBoxSizer(wxHORIZONTAL);
wxButton* bOK = new wxButton(this, wxID_OK, _("OK"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
wxButton* bCancel = new wxButton(this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
sEditCheatButtons->Add(0, 0, 1, wxEXPAND, 5);
sEditCheatButtons->Add(bOK, 0, wxALL, 5);
sEditCheatButtons->Add(bCancel, 0, wxALL, 5);
sEditCheat->Add(sEditCheatButtons, 0, wxEXPAND, 5);
this->SetSizer(sEditCheat);
sEditCheat->Layout();
}
void CARCodeAddEdit::OnClose(wxCloseEvent& WXUNUSED (event))
{
Destroy();
}
void CARCodeAddEdit::ChangeEntry(wxSpinEvent& event)
{
ActionReplay::ARCode currentCode = arCodes.at((int)arCodes.size()-1 - event.GetPosition());
EditCheatName->SetValue(wxString::FromAscii(currentCode.name.c_str()));
UpdateTextCtrl(currentCode);
}
void CARCodeAddEdit::SaveCheatData(wxCommandEvent& WXUNUSED (event))
{
std::vector<ActionReplay::AREntry> tempEntries;
std::string cheatValues = std::string(EditCheatCode->GetValue().mb_str());
bool bWhile = true; size_t line = 0;
while (bWhile)
{
bWhile = false;
u32 addr, value;
addr = strtol(std::string(cheatValues.substr(line, line+8)).c_str(), NULL, 16); // cmd_addr of ArCode
value = strtol(std::string(cheatValues.substr(line+9, line+17)).c_str(), NULL, 16); // value of ArCode
tempEntries.push_back(ActionReplay::AREntry(addr, value));
line = cheatValues.find("\n", line);
if (line != std::string::npos && cheatValues.length() > (line+17))
bWhile = true; // newline found, if not empty, go on
line++;
}
if (selection == -1)
{
ActionReplay::ARCode newCheat;
newCheat.name = std::string(EditCheatName->GetValue().mb_str());
newCheat.ops = tempEntries;
newCheat.active = true;
arCodes.push_back(newCheat);
}
else
{
arCodes.at(selection).name = std::string(EditCheatName->GetValue().mb_str());
arCodes.at(selection).ops = tempEntries;
}
AcceptAndClose();
}
void CARCodeAddEdit::UpdateTextCtrl(ActionReplay::ARCode arCode)
{
EditCheatCode->Clear();
for (u32 i = 0; i < arCode.ops.size(); i++)
EditCheatCode->AppendText(wxString::Format(wxT("%08X %08X\n"), arCode.ops.at(i).cmd_addr, arCode.ops.at(i).value));
}

File diff suppressed because it is too large Load Diff

View File

@ -1,484 +1,484 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
////////////////////////////////////////////////////////////////////////////////////////
// Include
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#include "Globals.h"
#include "Frame.h"
#include "FileUtil.h"
#include "StringUtil.h"
#include "ConsoleWindow.h"
#include "GameListCtrl.h"
#include "BootManager.h"
#include "Common.h"
#include "Setup.h"
#include "ConfigManager.h"
#include "Core.h"
#include "State.h"
#include "ConfigMain.h"
#include "PluginManager.h"
#include "MemcardManager.h"
#include "CheatsWindow.h"
#include "AboutDolphin.h"
#include <wx/statusbr.h>
/////////////////////////////////////////
namespace WiimoteLeds
{
int LED_SIZE_X = 8;
int LED_SIZE_Y = 8;
int SPEAKER_SIZE_X = 8;
int SPEAKER_SIZE_Y = 8;
int ConnectionStatusWidth = 103; // These widths need to be revised, for vista at least
int ConnectionStatusOnlyAdj = 7;
int RightmostMargin = 6;
int SpIconMargin = 11;
int LedIconMargin = 11;
// The necessary recording status width, allow Frame to be at last of the form 100,000
#ifdef RERECORDING
static const int RerecordingStatusWidth = 340;
#endif
// Leds only
static const int LdWidthsOn[] =
{
-1,
#ifdef RERECORDING
RerecordingStatusWidth,
#endif
ConnectionStatusWidth,
(LedIconMargin + LED_SIZE_X) * 4 + RightmostMargin
};
static const int StylesFieldOn[] = { wxSB_NORMAL, wxSB_NORMAL, wxSB_NORMAL };
// Speakers only
static const int SpWidthsOn[] =
{
-1,
#ifdef RERECORDING
RerecordingStatusWidth,
#endif
ConnectionStatusWidth,
( SpIconMargin + SPEAKER_SIZE_X ) * 3 + RightmostMargin
};
static const int SpStylesFieldOn[] = { wxSB_NORMAL,
#ifdef RERECORDING
wxSB_NORMAL,
#endif
wxSB_NORMAL, wxSB_NORMAL };
// Both
static const int LdSpWidthsOn[] =
{
-1,
#ifdef RERECORDING
RerecordingStatusWidth,
#endif
ConnectionStatusWidth,
(SpIconMargin + SPEAKER_SIZE_X) * 3,
(LedIconMargin + LED_SIZE_X) * 4 + RightmostMargin
};
static const int LdSpStylesFieldOn[] = { wxSB_NORMAL,
#ifdef RERECORDING
wxSB_NORMAL,
#endif
wxSB_NORMAL, wxSB_NORMAL };
// Only the Wiimote connection Status
static const int WidthsOff[] =
{
-1,
#ifdef RERECORDING
RerecordingStatusWidth,
#endif
ConnectionStatusWidth + ConnectionStatusOnlyAdj + RightmostMargin
};
static const int StylesFieldOff[] = { wxSB_NORMAL,
#ifdef RERECORDING
wxSB_NORMAL,
#endif
wxSB_NORMAL };
// GC mode
static const int WidthsOffGC[] = { -1
#ifdef RERECORDING
, RerecordingStatusWidth
#endif
};
static const int StylesFieldOffGC[] = { wxSB_NORMAL
#ifdef RERECORDING
, wxSB_NORMAL
#endif
};
};
// =======================================================
// Modify status bar
// -------------
void CFrame::ModifyStatusBar()
{
// Get settings
bool LedsOn = SConfig::GetInstance().m_LocalCoreStartupParameter.bWiiLeds;
bool SpeakersOn = SConfig::GetInstance().m_LocalCoreStartupParameter.bWiiSpeakers;
// Don't use this for GC games, or before a game is loaded
if(!SConfig::GetInstance().m_LocalCoreStartupParameter.bWii)
{ LedsOn = false; SpeakersOn = false; }
// Declarations
int Fields = 0;
int *Widths = 0;
int *StylesFields = 0;
// ---------------------------------------
// Leds only
// -------------
if(LedsOn && !SpeakersOn)
{
Fields = 3;
Widths = (int*)WiimoteLeds::LdWidthsOn;
StylesFields = (int*)WiimoteLeds::StylesFieldOn;
}
// ---------------------------------------
// Speaker only
// -------------
else if(!LedsOn && SpeakersOn)
{
Fields = 3;
Widths = (int*)WiimoteLeds::SpWidthsOn;
StylesFields = (int*)WiimoteLeds::SpStylesFieldOn;
}
// ---------------------------------------
// Both on
// -------------
else if(LedsOn && SpeakersOn)
{
Fields = 4;
Widths = (int*)WiimoteLeds::LdSpWidthsOn;
StylesFields = (int*)WiimoteLeds::LdSpStylesFieldOn;
}
// ---------------------------------------
// Both off
// -------------
else if(!LedsOn && !SpeakersOn)
{
Fields = 2;
Widths = (int*)WiimoteLeds::WidthsOff;
StylesFields = (int*)WiimoteLeds::StylesFieldOff;
// Maybe we should even go down to one field
if(!SConfig::GetInstance().m_LocalCoreStartupParameter.bWii)
{
Fields = 1;
Widths = (int*)WiimoteLeds::WidthsOffGC;
StylesFields = (int*)WiimoteLeds::StylesFieldOffGC;
}
}
// Add a filed for the rerecording status
#ifdef RERECORDING
Fields++;
#endif
// Update the settings
m_pStatusBar->SetFieldsCount(Fields);
m_pStatusBar->SetStatusWidths(Fields, Widths);
m_pStatusBar->SetStatusStyles(Fields, StylesFields);
/* Destroy and create all, and check for HaveLeds and HaveSpeakers in case we have
gotten a confirmed on or off setting, in which case we don't do anything */
if(!LedsOn && HaveLeds) CreateDestroy(DESTROYLEDS);
if(!SpeakersOn && HaveSpeakers) CreateDestroy(DESTROYSPEAKERS);
if(LedsOn && !HaveLeds) CreateDestroy(CREATELEDS);
if(SpeakersOn && !HaveSpeakers) CreateDestroy(CREATESPEAKERS);
DoMoveIcons();
m_pStatusBar->Refresh(); // avoid small glitches that can occur
}
// =======================================================
// Create and destroy leds and speakers icons
// -------------
void CFrame::CreateDestroy(int Case)
{
switch(Case)
{
case CREATELEDS:
{
CreateLeds();
UpdateLeds();
HaveLeds = true;
break;
}
case DESTROYLEDS:
{
for(int i = 0; i < 4; i++)
{
m_StatBmp[i]->Destroy();
}
HaveLeds = false;
break;
}
case CREATESPEAKERS:
{
CreateSpeakers();
HaveSpeakers = true;
break;
}
case DESTROYSPEAKERS:
{
for(int i = 4; i < 7; i++)
{
m_StatBmp[i]->Destroy();
}
HaveSpeakers = false;
break;
}
} // end of switch
DoMoveIcons();
}
// =============
// =======================================================
// Create and update leds
// -------------
void CFrame::CreateLeds()
{
// Begin with blank ones
memset(&g_Leds, 0, sizeof(g_Leds));
for(int i = 0; i < 4; i++)
{
m_StatBmp[i] = new wxStaticBitmap(m_pStatusBar, wxID_ANY,
CreateBitmapForLeds(g_Leds[i] == 1));
}
}
// Update leds
void CFrame::UpdateLeds()
{
for(int i = 0; i < 4; i++)
{
m_StatBmp[i]->SetBitmap(CreateBitmapForLeds(g_Leds[i] != 0));
}
}
// ==============
// =======================================================
// Create and speaker icons
// -------------
void CFrame::CreateSpeakers()
{
// Begin with blank ones
memset(&g_Speakers, 0, sizeof(g_Speakers));
memset(&g_Speakers_, 0, sizeof(g_Speakers_));
for(int i = 0; i < 3; i++)
{
m_StatBmp[i+4] = new wxStaticBitmap(m_pStatusBar, wxID_ANY,
CreateBitmapForSpeakers(i, g_Speakers[i] != 0));
}
}
// Update icons
void CFrame::UpdateSpeakers()
{
/*if(!SConfig::GetInstance().m_LocalCoreStartupParameter.bNTSC)
{ PanicAlert("Not NTSC");}
if(!SConfig::GetInstance().m_LocalCoreStartupParameter.bWii)
{ PanicAlert("Not Wii");}*/
for(int i = 0; i < 3; i++)
{
m_StatBmp[i+4]->SetBitmap(CreateBitmapForSpeakers(i, g_Speakers[i] != 0));
}
}
// ==============
// =======================================================
// Create the Leds bitmap
// -------------
wxBitmap CFrame::CreateBitmapForLeds(bool On)
{
wxBitmap bitmap(WiimoteLeds::LED_SIZE_X, WiimoteLeds::LED_SIZE_Y);
wxMemoryDC dc;
dc.SelectObject(bitmap);
// Set outline and fill colors
wxBrush LightBlueBrush(_T("#0383f0"));
wxPen LightBluePen(_T("#80c5fd"));
wxPen LightGrayPen(_T("#909090"));
dc.SetPen(On ? LightBluePen : LightGrayPen);
dc.SetBrush(On ? LightBlueBrush : *wxWHITE_BRUSH);
dc.Clear();
dc.DrawRectangle(0, 0, WiimoteLeds::LED_SIZE_X, WiimoteLeds::LED_SIZE_Y);
dc.SelectObject(wxNullBitmap);
return bitmap;
}
// =======================================================
// Create the Speaker bitmap
// -------------
wxBitmap CFrame::CreateBitmapForSpeakers(int BitmapType, bool On)
{
wxBitmap bitmap(WiimoteLeds::LED_SIZE_X, WiimoteLeds::LED_SIZE_Y);
wxMemoryDC dc;
dc.SelectObject(bitmap);
wxBrush BackgroundGrayBrush(_T("#ece9d8")); // the right color in windows
switch(BitmapType)
{
case 0: // Speaker on
{
// Set outline and fill colors
dc.SetPen(On ? *wxMEDIUM_GREY_PEN : *wxMEDIUM_GREY_PEN);
dc.SetBrush(On ? *wxGREEN_BRUSH : *wxWHITE_BRUSH);
dc.SetBackground(BackgroundGrayBrush);
dc.Clear();
dc.DrawEllipse(0, 0, WiimoteLeds::SPEAKER_SIZE_X, WiimoteLeds::SPEAKER_SIZE_Y);
dc.SelectObject(wxNullBitmap);
return bitmap;
}
case 1: // Speaker unmuted
{
// Set outline and fill colors
dc.SetPen(On ? *wxMEDIUM_GREY_PEN : *wxMEDIUM_GREY_PEN);
dc.SetBrush(On ? *wxBLUE_BRUSH : *wxWHITE_BRUSH);
dc.SetBackground(BackgroundGrayBrush);
dc.Clear();
dc.DrawEllipse(0, 0, WiimoteLeds::SPEAKER_SIZE_X, WiimoteLeds::SPEAKER_SIZE_Y);
dc.SelectObject(wxNullBitmap);
return bitmap;
}
case 2: // Speaker activity
{
// Set outline and fill colors
dc.SetPen(On ? *wxMEDIUM_GREY_PEN : *wxMEDIUM_GREY_PEN);
dc.SetBrush(On ? *wxGREEN_BRUSH : *wxWHITE_BRUSH);
dc.SetBackground(BackgroundGrayBrush);
dc.Clear();
dc.DrawEllipse(0, 0, WiimoteLeds::SPEAKER_SIZE_X, WiimoteLeds::SPEAKER_SIZE_Y);
dc.SelectObject(wxNullBitmap);
return bitmap;
}
}
return bitmap;
}
// =======================================================
// Move the bitmaps
// -------------
void CFrame::DoMoveIcons()
{
if(HaveLeds) MoveLeds();
if(HaveSpeakers) MoveSpeakers();
// If there is not room for the led icons hide them
if(m_pStatusBar->GetFieldsCount() >= 2 && HaveLeds)
{
wxRect Rect;
#ifdef RERECORDING
m_pStatusBar->GetFieldRect((HaveLeds && HaveSpeakers) ? 4 : 3, Rect);
#else
m_pStatusBar->GetFieldRect((HaveLeds && HaveSpeakers) ? 3 : 2, Rect);
#endif
if(Rect.GetWidth() < 20)
for (int i = 0; i < 4; i++) m_StatBmp[i]->Hide();
else // if(!m_StatBmp[0]->IsShown())
for (int i = 0; i < 4; i++) m_StatBmp[i]->Show();
//Console::Print("LED: %i ", Rect.GetWidth());
}
// If there is not room for the speaker icons hide them
if(m_pStatusBar->GetFieldsCount() >= 2 && HaveSpeakers)
{
wxRect Rect;
#ifdef RERECORDING
m_pStatusBar->GetFieldRect(3, Rect);
#else
m_pStatusBar->GetFieldRect(2, Rect);
#endif
if(Rect.GetWidth() < 20)
for(int i = 0; i < 3; i++) m_StatBmp[i + 4]->Hide();
else // if(!m_StatBmp[4]->IsShown())
for (int i = 0; i < 3; i++) m_StatBmp[i + 4]->Show();
//Console::Print("Speaker: %i\n", Rect.GetWidth());
}
}
void CFrame::MoveLeds()
{
wxRect Rect;
// Get the bitmap field coordinates
#ifdef RERECORDING
m_pStatusBar->GetFieldRect((HaveLeds && HaveSpeakers) ? 4 : 3, Rect);
#else
m_pStatusBar->GetFieldRect((HaveLeds && HaveSpeakers) ? 3 : 2, Rect);
#endif
wxSize Size = m_StatBmp[0]->GetSize(); // Get the bitmap size
//wxMessageBox(wxString::Format("%i", Rect.x));
int x = Rect.x + 10;
int Dist = WiimoteLeds::LED_SIZE_X + 7;
int y = Rect.y + (Rect.height - Size.y) / 2;
for(int i = 0; i < 4; i++)
{
if(i > 0) x = m_StatBmp[i-1]->GetPosition().x + Dist;
m_StatBmp[i]->Move(x, y);
}
}
void CFrame::MoveSpeakers()
{
wxRect Rect;
// Get the bitmap field coordinates
#ifdef RERECORDING
m_pStatusBar->GetFieldRect(3, Rect);
#else
m_pStatusBar->GetFieldRect(2, Rect);
#endif
// Get the actual bitmap size, currently it's the same as SPEAKER_SIZE_Y
wxSize Size = m_StatBmp[4]->GetSize();
//wxMessageBox(wxString::Format("%i", Rect.x));
int x = Rect.x + 9;
int Dist = WiimoteLeds::SPEAKER_SIZE_X + 7;
int y = Rect.y + (Rect.height - Size.y) / 2;
for(int i = 0; i < 3; i++)
{
if(i > 0) x = m_StatBmp[i-1+4]->GetPosition().x + Dist;
m_StatBmp[i + 4]->Move(x, y);
}
}
// ==============
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
////////////////////////////////////////////////////////////////////////////////////////
// Include
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#include "Globals.h"
#include "Frame.h"
#include "FileUtil.h"
#include "StringUtil.h"
#include "ConsoleWindow.h"
#include "GameListCtrl.h"
#include "BootManager.h"
#include "Common.h"
#include "Setup.h"
#include "ConfigManager.h"
#include "Core.h"
#include "State.h"
#include "ConfigMain.h"
#include "PluginManager.h"
#include "MemcardManager.h"
#include "CheatsWindow.h"
#include "AboutDolphin.h"
#include <wx/statusbr.h>
/////////////////////////////////////////
namespace WiimoteLeds
{
int LED_SIZE_X = 8;
int LED_SIZE_Y = 8;
int SPEAKER_SIZE_X = 8;
int SPEAKER_SIZE_Y = 8;
int ConnectionStatusWidth = 103; // These widths need to be revised, for vista at least
int ConnectionStatusOnlyAdj = 7;
int RightmostMargin = 6;
int SpIconMargin = 11;
int LedIconMargin = 11;
// The necessary recording status width, allow Frame to be at last of the form 100,000
#ifdef RERECORDING
static const int RerecordingStatusWidth = 340;
#endif
// Leds only
static const int LdWidthsOn[] =
{
-1,
#ifdef RERECORDING
RerecordingStatusWidth,
#endif
ConnectionStatusWidth,
(LedIconMargin + LED_SIZE_X) * 4 + RightmostMargin
};
static const int StylesFieldOn[] = { wxSB_NORMAL, wxSB_NORMAL, wxSB_NORMAL };
// Speakers only
static const int SpWidthsOn[] =
{
-1,
#ifdef RERECORDING
RerecordingStatusWidth,
#endif
ConnectionStatusWidth,
( SpIconMargin + SPEAKER_SIZE_X ) * 3 + RightmostMargin
};
static const int SpStylesFieldOn[] = { wxSB_NORMAL,
#ifdef RERECORDING
wxSB_NORMAL,
#endif
wxSB_NORMAL, wxSB_NORMAL };
// Both
static const int LdSpWidthsOn[] =
{
-1,
#ifdef RERECORDING
RerecordingStatusWidth,
#endif
ConnectionStatusWidth,
(SpIconMargin + SPEAKER_SIZE_X) * 3,
(LedIconMargin + LED_SIZE_X) * 4 + RightmostMargin
};
static const int LdSpStylesFieldOn[] = { wxSB_NORMAL,
#ifdef RERECORDING
wxSB_NORMAL,
#endif
wxSB_NORMAL, wxSB_NORMAL };
// Only the Wiimote connection Status
static const int WidthsOff[] =
{
-1,
#ifdef RERECORDING
RerecordingStatusWidth,
#endif
ConnectionStatusWidth + ConnectionStatusOnlyAdj + RightmostMargin
};
static const int StylesFieldOff[] = { wxSB_NORMAL,
#ifdef RERECORDING
wxSB_NORMAL,
#endif
wxSB_NORMAL };
// GC mode
static const int WidthsOffGC[] = { -1
#ifdef RERECORDING
, RerecordingStatusWidth
#endif
};
static const int StylesFieldOffGC[] = { wxSB_NORMAL
#ifdef RERECORDING
, wxSB_NORMAL
#endif
};
};
// =======================================================
// Modify status bar
// -------------
void CFrame::ModifyStatusBar()
{
// Get settings
bool LedsOn = SConfig::GetInstance().m_LocalCoreStartupParameter.bWiiLeds;
bool SpeakersOn = SConfig::GetInstance().m_LocalCoreStartupParameter.bWiiSpeakers;
// Don't use this for GC games, or before a game is loaded
if(!SConfig::GetInstance().m_LocalCoreStartupParameter.bWii)
{ LedsOn = false; SpeakersOn = false; }
// Declarations
int Fields = 0;
int *Widths = 0;
int *StylesFields = 0;
// ---------------------------------------
// Leds only
// -------------
if(LedsOn && !SpeakersOn)
{
Fields = 3;
Widths = (int*)WiimoteLeds::LdWidthsOn;
StylesFields = (int*)WiimoteLeds::StylesFieldOn;
}
// ---------------------------------------
// Speaker only
// -------------
else if(!LedsOn && SpeakersOn)
{
Fields = 3;
Widths = (int*)WiimoteLeds::SpWidthsOn;
StylesFields = (int*)WiimoteLeds::SpStylesFieldOn;
}
// ---------------------------------------
// Both on
// -------------
else if(LedsOn && SpeakersOn)
{
Fields = 4;
Widths = (int*)WiimoteLeds::LdSpWidthsOn;
StylesFields = (int*)WiimoteLeds::LdSpStylesFieldOn;
}
// ---------------------------------------
// Both off
// -------------
else if(!LedsOn && !SpeakersOn)
{
Fields = 2;
Widths = (int*)WiimoteLeds::WidthsOff;
StylesFields = (int*)WiimoteLeds::StylesFieldOff;
// Maybe we should even go down to one field
if(!SConfig::GetInstance().m_LocalCoreStartupParameter.bWii)
{
Fields = 1;
Widths = (int*)WiimoteLeds::WidthsOffGC;
StylesFields = (int*)WiimoteLeds::StylesFieldOffGC;
}
}
// Add a filed for the rerecording status
#ifdef RERECORDING
Fields++;
#endif
// Update the settings
m_pStatusBar->SetFieldsCount(Fields);
m_pStatusBar->SetStatusWidths(Fields, Widths);
m_pStatusBar->SetStatusStyles(Fields, StylesFields);
/* Destroy and create all, and check for HaveLeds and HaveSpeakers in case we have
gotten a confirmed on or off setting, in which case we don't do anything */
if(!LedsOn && HaveLeds) CreateDestroy(DESTROYLEDS);
if(!SpeakersOn && HaveSpeakers) CreateDestroy(DESTROYSPEAKERS);
if(LedsOn && !HaveLeds) CreateDestroy(CREATELEDS);
if(SpeakersOn && !HaveSpeakers) CreateDestroy(CREATESPEAKERS);
DoMoveIcons();
m_pStatusBar->Refresh(); // avoid small glitches that can occur
}
// =======================================================
// Create and destroy leds and speakers icons
// -------------
void CFrame::CreateDestroy(int Case)
{
switch(Case)
{
case CREATELEDS:
{
CreateLeds();
UpdateLeds();
HaveLeds = true;
break;
}
case DESTROYLEDS:
{
for(int i = 0; i < 4; i++)
{
m_StatBmp[i]->Destroy();
}
HaveLeds = false;
break;
}
case CREATESPEAKERS:
{
CreateSpeakers();
HaveSpeakers = true;
break;
}
case DESTROYSPEAKERS:
{
for(int i = 4; i < 7; i++)
{
m_StatBmp[i]->Destroy();
}
HaveSpeakers = false;
break;
}
} // end of switch
DoMoveIcons();
}
// =============
// =======================================================
// Create and update leds
// -------------
void CFrame::CreateLeds()
{
// Begin with blank ones
memset(&g_Leds, 0, sizeof(g_Leds));
for(int i = 0; i < 4; i++)
{
m_StatBmp[i] = new wxStaticBitmap(m_pStatusBar, wxID_ANY,
CreateBitmapForLeds(g_Leds[i] == 1));
}
}
// Update leds
void CFrame::UpdateLeds()
{
for(int i = 0; i < 4; i++)
{
m_StatBmp[i]->SetBitmap(CreateBitmapForLeds(g_Leds[i] != 0));
}
}
// ==============
// =======================================================
// Create and speaker icons
// -------------
void CFrame::CreateSpeakers()
{
// Begin with blank ones
memset(&g_Speakers, 0, sizeof(g_Speakers));
memset(&g_Speakers_, 0, sizeof(g_Speakers_));
for(int i = 0; i < 3; i++)
{
m_StatBmp[i+4] = new wxStaticBitmap(m_pStatusBar, wxID_ANY,
CreateBitmapForSpeakers(i, g_Speakers[i] != 0));
}
}
// Update icons
void CFrame::UpdateSpeakers()
{
/*if(!SConfig::GetInstance().m_LocalCoreStartupParameter.bNTSC)
{ PanicAlert("Not NTSC");}
if(!SConfig::GetInstance().m_LocalCoreStartupParameter.bWii)
{ PanicAlert("Not Wii");}*/
for(int i = 0; i < 3; i++)
{
m_StatBmp[i+4]->SetBitmap(CreateBitmapForSpeakers(i, g_Speakers[i] != 0));
}
}
// ==============
// =======================================================
// Create the Leds bitmap
// -------------
wxBitmap CFrame::CreateBitmapForLeds(bool On)
{
wxBitmap bitmap(WiimoteLeds::LED_SIZE_X, WiimoteLeds::LED_SIZE_Y);
wxMemoryDC dc;
dc.SelectObject(bitmap);
// Set outline and fill colors
wxBrush LightBlueBrush(_T("#0383f0"));
wxPen LightBluePen(_T("#80c5fd"));
wxPen LightGrayPen(_T("#909090"));
dc.SetPen(On ? LightBluePen : LightGrayPen);
dc.SetBrush(On ? LightBlueBrush : *wxWHITE_BRUSH);
dc.Clear();
dc.DrawRectangle(0, 0, WiimoteLeds::LED_SIZE_X, WiimoteLeds::LED_SIZE_Y);
dc.SelectObject(wxNullBitmap);
return bitmap;
}
// =======================================================
// Create the Speaker bitmap
// -------------
wxBitmap CFrame::CreateBitmapForSpeakers(int BitmapType, bool On)
{
wxBitmap bitmap(WiimoteLeds::LED_SIZE_X, WiimoteLeds::LED_SIZE_Y);
wxMemoryDC dc;
dc.SelectObject(bitmap);
wxBrush BackgroundGrayBrush(_T("#ece9d8")); // the right color in windows
switch(BitmapType)
{
case 0: // Speaker on
{
// Set outline and fill colors
dc.SetPen(On ? *wxMEDIUM_GREY_PEN : *wxMEDIUM_GREY_PEN);
dc.SetBrush(On ? *wxGREEN_BRUSH : *wxWHITE_BRUSH);
dc.SetBackground(BackgroundGrayBrush);
dc.Clear();
dc.DrawEllipse(0, 0, WiimoteLeds::SPEAKER_SIZE_X, WiimoteLeds::SPEAKER_SIZE_Y);
dc.SelectObject(wxNullBitmap);
return bitmap;
}
case 1: // Speaker unmuted
{
// Set outline and fill colors
dc.SetPen(On ? *wxMEDIUM_GREY_PEN : *wxMEDIUM_GREY_PEN);
dc.SetBrush(On ? *wxBLUE_BRUSH : *wxWHITE_BRUSH);
dc.SetBackground(BackgroundGrayBrush);
dc.Clear();
dc.DrawEllipse(0, 0, WiimoteLeds::SPEAKER_SIZE_X, WiimoteLeds::SPEAKER_SIZE_Y);
dc.SelectObject(wxNullBitmap);
return bitmap;
}
case 2: // Speaker activity
{
// Set outline and fill colors
dc.SetPen(On ? *wxMEDIUM_GREY_PEN : *wxMEDIUM_GREY_PEN);
dc.SetBrush(On ? *wxGREEN_BRUSH : *wxWHITE_BRUSH);
dc.SetBackground(BackgroundGrayBrush);
dc.Clear();
dc.DrawEllipse(0, 0, WiimoteLeds::SPEAKER_SIZE_X, WiimoteLeds::SPEAKER_SIZE_Y);
dc.SelectObject(wxNullBitmap);
return bitmap;
}
}
return bitmap;
}
// =======================================================
// Move the bitmaps
// -------------
void CFrame::DoMoveIcons()
{
if(HaveLeds) MoveLeds();
if(HaveSpeakers) MoveSpeakers();
// If there is not room for the led icons hide them
if(m_pStatusBar->GetFieldsCount() >= 2 && HaveLeds)
{
wxRect Rect;
#ifdef RERECORDING
m_pStatusBar->GetFieldRect((HaveLeds && HaveSpeakers) ? 4 : 3, Rect);
#else
m_pStatusBar->GetFieldRect((HaveLeds && HaveSpeakers) ? 3 : 2, Rect);
#endif
if(Rect.GetWidth() < 20)
for (int i = 0; i < 4; i++) m_StatBmp[i]->Hide();
else // if(!m_StatBmp[0]->IsShown())
for (int i = 0; i < 4; i++) m_StatBmp[i]->Show();
//Console::Print("LED: %i ", Rect.GetWidth());
}
// If there is not room for the speaker icons hide them
if(m_pStatusBar->GetFieldsCount() >= 2 && HaveSpeakers)
{
wxRect Rect;
#ifdef RERECORDING
m_pStatusBar->GetFieldRect(3, Rect);
#else
m_pStatusBar->GetFieldRect(2, Rect);
#endif
if(Rect.GetWidth() < 20)
for(int i = 0; i < 3; i++) m_StatBmp[i + 4]->Hide();
else // if(!m_StatBmp[4]->IsShown())
for (int i = 0; i < 3; i++) m_StatBmp[i + 4]->Show();
//Console::Print("Speaker: %i\n", Rect.GetWidth());
}
}
void CFrame::MoveLeds()
{
wxRect Rect;
// Get the bitmap field coordinates
#ifdef RERECORDING
m_pStatusBar->GetFieldRect((HaveLeds && HaveSpeakers) ? 4 : 3, Rect);
#else
m_pStatusBar->GetFieldRect((HaveLeds && HaveSpeakers) ? 3 : 2, Rect);
#endif
wxSize Size = m_StatBmp[0]->GetSize(); // Get the bitmap size
//wxMessageBox(wxString::Format("%i", Rect.x));
int x = Rect.x + 10;
int Dist = WiimoteLeds::LED_SIZE_X + 7;
int y = Rect.y + (Rect.height - Size.y) / 2;
for(int i = 0; i < 4; i++)
{
if(i > 0) x = m_StatBmp[i-1]->GetPosition().x + Dist;
m_StatBmp[i]->Move(x, y);
}
}
void CFrame::MoveSpeakers()
{
wxRect Rect;
// Get the bitmap field coordinates
#ifdef RERECORDING
m_pStatusBar->GetFieldRect(3, Rect);
#else
m_pStatusBar->GetFieldRect(2, Rect);
#endif
// Get the actual bitmap size, currently it's the same as SPEAKER_SIZE_Y
wxSize Size = m_StatBmp[4]->GetSize();
//wxMessageBox(wxString::Format("%i", Rect.x));
int x = Rect.x + 9;
int Dist = WiimoteLeds::SPEAKER_SIZE_X + 7;
int y = Rect.y + (Rect.height - Size.y) / 2;
for(int i = 0; i < 3; i++)
{
if(i > 0) x = m_StatBmp[i-1+4]->GetPosition().x + Dist;
m_StatBmp[i + 4]->Move(x, y);
}
}
// ==============

View File

@ -1,63 +1,63 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "SDCardWindow.h"
#include "Globals.h"
#include "IPC_HLE/HW/SDInterface.h"
BEGIN_EVENT_TABLE(wxSDCardWindow, wxWindow)
EVT_CLOSE( wxSDCardWindow::OnEvent_Window_Close)
EVT_BUTTON(ID_BUTTON_CLOSE, wxSDCardWindow::OnEvent_ButtonClose_Press)
END_EVENT_TABLE()
wxSDCardWindow::wxSDCardWindow(wxWindow* parent) :
wxDialog(parent, wxID_ANY, _T("SDCard Mounter"), wxDefaultPosition, wxSize(400, 400), wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE)
{
Init_ChildControls();
Layout();
Show();
}
wxSDCardWindow::~wxSDCardWindow()
{
// On Disposal
}
void wxSDCardWindow::Init_ChildControls()
{
// Button Strip
m_Button_Close = new wxButton(this, ID_BUTTON_CLOSE, _T("Close"), wxDefaultPosition, wxDefaultSize);
wxBoxSizer* sButtons = new wxBoxSizer(wxHORIZONTAL);
sButtons->Add(m_Button_Close, 0, wxALL, 5);
wxBoxSizer* sMain = new wxBoxSizer(wxVERTICAL);
sMain->Add(sButtons, 0, wxALL, 5);
SetSizer(sMain);
Layout();
Fit();
}
void wxSDCardWindow::OnEvent_Window_Close(wxCloseEvent& WXUNUSED(event))
{
EndModal(0);
}
void wxSDCardWindow::OnEvent_ButtonClose_Press(wxCommandEvent& WXUNUSED(event))
{
EndModal(0);
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "SDCardWindow.h"
#include "Globals.h"
#include "IPC_HLE/HW/SDInterface.h"
BEGIN_EVENT_TABLE(wxSDCardWindow, wxWindow)
EVT_CLOSE( wxSDCardWindow::OnEvent_Window_Close)
EVT_BUTTON(ID_BUTTON_CLOSE, wxSDCardWindow::OnEvent_ButtonClose_Press)
END_EVENT_TABLE()
wxSDCardWindow::wxSDCardWindow(wxWindow* parent) :
wxDialog(parent, wxID_ANY, _T("SDCard Mounter"), wxDefaultPosition, wxSize(400, 400), wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE)
{
Init_ChildControls();
Layout();
Show();
}
wxSDCardWindow::~wxSDCardWindow()
{
// On Disposal
}
void wxSDCardWindow::Init_ChildControls()
{
// Button Strip
m_Button_Close = new wxButton(this, ID_BUTTON_CLOSE, _T("Close"), wxDefaultPosition, wxDefaultSize);
wxBoxSizer* sButtons = new wxBoxSizer(wxHORIZONTAL);
sButtons->Add(m_Button_Close, 0, wxALL, 5);
wxBoxSizer* sMain = new wxBoxSizer(wxVERTICAL);
sMain->Add(sButtons, 0, wxALL, 5);
SetSizer(sMain);
Layout();
Fit();
}
void wxSDCardWindow::OnEvent_Window_Close(wxCloseEvent& WXUNUSED(event))
{
EndModal(0);
}
void wxSDCardWindow::OnEvent_ButtonClose_Press(wxCommandEvent& WXUNUSED(event))
{
EndModal(0);
}

View File

@ -1,252 +1,252 @@
//////////////////////////////////////////////////////////////////////////////////////////
// Project description
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Name: Input Configuration and Calibration
// Description: Common SDL Input Functions
//
// Author: Falcon4ever (nJoy@falcon4ever.com, www.multigesture.net), JPeterson etc
// Copyright (C) 2003-2008 Dolphin Project.
//
//////////////////////////////////////////////////////////////////////////////////////////
//
// Licensetype: GNU General Public License (GPL)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
//
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
//
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
//
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Include
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#if defined HAVE_WX && HAVE_WX
#include <wx/wx.h>
#endif
#include "SDL.h" // Local
////////////////////////////////////
namespace InputCommon
{
//////////////////////////////////////////////////////////////////////////////////////////
// Degree to radian and back
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
float Deg2Rad(float Deg)
{
return Deg * ((float)M_PI / 180.0f);
}
float Rad2Deg(float Rad)
{
return (Rad * 180.0f) / (float)M_PI;
}
/////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Check if the pad is within the dead zone, we assume the range is 0x8000
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
float CoordinatesToRadius(int x, int y)
{
return sqrt(pow((float)x, 2) + pow((float)y, 2));
}
bool IsDeadZone(float DeadZone, int x, int y)
{
// Get the distance from the center
float Distance = CoordinatesToRadius(x, y) / 32767.0f;
//Console::Print("%f\n", Distance);
// Check if it's within the dead zone
if (Distance <= DeadZone)
return true;
else
return false;
}
/////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Scale down stick values from 0x8000 to 0x80
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
The value returned by SDL_JoystickGetAxis is a signed integer s16
(-32768 to 32767). The value used for the gamecube controller is an unsigned
char u8 (0 to 255) with neutral at 0x80 (128), so that it's equivalent to a signed
-128 to 127.
*/
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int Pad_Convert(int _val)
{
/* If the limits on PadState[].axis[] actually is a u16 then we don't need this
but if it's not actually limited to that we need to apply these limits */
if(_val > 32767) _val = 32767; // upper limit
if(_val < -32768) _val = -32768; // lower limit
// Convert the range (-0x8000 to 0x7fff) to (0 to 0xffff)
_val = 0x8000 +_val;
// Convert the range (-32768 to 32767) to (-128 to 127)
_val = _val >> 8;
//Console::Print("0x%04x %06i\n\n", _val, _val);
return _val;
}
/////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
/* Convert the stick raidus from a square or rounded box to a circular radius. I don't know what
input values the actual GC controller produce for the GC, it may be a square, a circle or
something in between. But one thing that is certain is that PC pads differ in their output
(as shown in the list below), so it may be beneficiary to convert whatever radius they
produce to the radius the GC games expect. This is the first implementation of this
that convert a square radius to a circual radius. Use the advanced settings to enable
and calibrate it.
Observed diagonals:
Perfect circle: 71% = sin(45)
Logitech Dual Action: 100%
PS2 Dual Shock 2 (Original) with Super Dual Box Pro: 90%
XBox 360 Wireless: 85%
GameCube Controller (Third Party) with EMS Trio Linker Plus II: 60%
*/
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/* Calculate the distance from the outer edges of the box to the outer edges of the circle inside the box
at any angle from 0<> to 360<36>. The returned value is 1 + Distance, for example at most sqrt(2) in the
corners and at least 1.0 at the horizontal and vertical angles. */
float Square2CircleDistance(float deg)
{
// See if we have to adjust the angle
deg = abs(deg);
if( (deg > 45 && deg < 135) ) deg = deg - 90;
// Calculate distance from center
float val = abs(cos(Deg2Rad(deg)));
float Distance = 1 / val;
//m_frame->m_pStatusBar2->SetLabel(wxString::Format("Deg:%f Val:%f Dist:%f", deg, val, dist));
return Distance;
}
// Produce a perfect circle from an original square or rounded box
std::vector<int> Square2Circle(int _x, int _y, int _pad, std::string SDiagonal, bool Circle2Square)
{
// Do we need this?
if(_x > 32767) _x = 32767; if(_y > 32767) _y = 32767; // upper limit
if(_x < -32768) _x = -32768; if(_y < -32768) _y = -32768; // lower limit
// ====================================
// Convert to circle
// -----------
// Get the manually configured diagonal distance
int Tmp = atoi (SDiagonal.substr(0, SDiagonal.length() - 1).c_str());
float Diagonal = Tmp / 100.0f;
// First make a perfect square in case we don't have one already
float OrigDist = sqrt( pow((float)_y, 2) + pow((float)_x, 2) ); // Get current distance
float deg = Rad2Deg(atan2((float)_y, (float)_x)); // Get current angle
/* Calculate the actual distance between the maxium diagonal values, and the outer edges of the
square. A diagonal of 85% means a maximum distance of 0.85 * sqrt(2) ~1.2 in the diagonals. */
float corner_circle_dist = ( Diagonal / sin(Deg2Rad(45)) );
float SquareDist = Square2CircleDistance(deg);
// The original-to-square distance adjustment
float adj_ratio1;
// The circle-to-square distance adjustment
float adj_ratio2 = SquareDist;
// The resulting distance
float result_dist;
// Calculate the corner-to-square adjustment ratio
if(corner_circle_dist < SquareDist) adj_ratio1 = SquareDist / corner_circle_dist;
else adj_ratio1 = 1;
// Calculate the resulting distance
if(Circle2Square)
result_dist = OrigDist * adj_ratio1;
else
result_dist = OrigDist * adj_ratio1 / adj_ratio2;
// Calculate x and y and return it
float x = result_dist * cos(Deg2Rad(deg));
float y = result_dist * sin(Deg2Rad(deg));
// Make integers
int int_x = (int)floor(x);
int int_y = (int)floor(y);
// Boundaries
if (int_x < -32768) int_x = -32768; if (int_x > 32767) int_x = 32767;
if (int_y < -32768) int_y = -32768; if (int_y > 32767) int_y = 32767;
// Return it
std::vector<int> vec;
vec.push_back(int_x);
vec.push_back(int_y);
// Debugging
//Console::Print("%f %f %i", corner_circle_dist, Diagonal, Tmp));
return vec;
}
/////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Windows Virtual Key Codes Names
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#ifdef _WIN32
std::string VKToString(int keycode)
{
#ifdef _WIN32
// Default value
char KeyStr[64] = {0};
GetKeyNameText(MapVirtualKey(keycode, MAPVK_VK_TO_VSC) << 16, KeyStr, 64);
std::string KeyString = KeyStr;
switch(keycode)
{
// Give it some help with a few keys
case VK_END: return "END";
case VK_INSERT: return "INS";
case VK_DELETE: return "DEL";
case VK_PRIOR: return "PGUP";
case VK_NEXT: return "PGDN";
case VK_UP: return "UP";
case VK_DOWN: return "DOWN";
case VK_LEFT: return "LEFT";
case VK_RIGHT: return "RIGHT";
case VK_LSHIFT: return "LEFT SHIFT";
case VK_LCONTROL: return "LEFT CTRL";
case VK_RCONTROL: return "RIGHT CTRL";
case VK_LMENU: return "LEFT ALT";
default: return KeyString;
}
#else
// An equivalent name translation can probably be used on other systems to?
return "";
#endif
}
#endif
/////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Project description
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Name: Input Configuration and Calibration
// Description: Common SDL Input Functions
//
// Author: Falcon4ever (nJoy@falcon4ever.com, www.multigesture.net), JPeterson etc
// Copyright (C) 2003-2008 Dolphin Project.
//
//////////////////////////////////////////////////////////////////////////////////////////
//
// Licensetype: GNU General Public License (GPL)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
//
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
//
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
//
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Include
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#if defined HAVE_WX && HAVE_WX
#include <wx/wx.h>
#endif
#include "SDL.h" // Local
////////////////////////////////////
namespace InputCommon
{
//////////////////////////////////////////////////////////////////////////////////////////
// Degree to radian and back
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
float Deg2Rad(float Deg)
{
return Deg * ((float)M_PI / 180.0f);
}
float Rad2Deg(float Rad)
{
return (Rad * 180.0f) / (float)M_PI;
}
/////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Check if the pad is within the dead zone, we assume the range is 0x8000
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
float CoordinatesToRadius(int x, int y)
{
return sqrt(pow((float)x, 2) + pow((float)y, 2));
}
bool IsDeadZone(float DeadZone, int x, int y)
{
// Get the distance from the center
float Distance = CoordinatesToRadius(x, y) / 32767.0f;
//Console::Print("%f\n", Distance);
// Check if it's within the dead zone
if (Distance <= DeadZone)
return true;
else
return false;
}
/////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Scale down stick values from 0x8000 to 0x80
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
The value returned by SDL_JoystickGetAxis is a signed integer s16
(-32768 to 32767). The value used for the gamecube controller is an unsigned
char u8 (0 to 255) with neutral at 0x80 (128), so that it's equivalent to a signed
-128 to 127.
*/
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int Pad_Convert(int _val)
{
/* If the limits on PadState[].axis[] actually is a u16 then we don't need this
but if it's not actually limited to that we need to apply these limits */
if(_val > 32767) _val = 32767; // upper limit
if(_val < -32768) _val = -32768; // lower limit
// Convert the range (-0x8000 to 0x7fff) to (0 to 0xffff)
_val = 0x8000 +_val;
// Convert the range (-32768 to 32767) to (-128 to 127)
_val = _val >> 8;
//Console::Print("0x%04x %06i\n\n", _val, _val);
return _val;
}
/////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
/* Convert the stick raidus from a square or rounded box to a circular radius. I don't know what
input values the actual GC controller produce for the GC, it may be a square, a circle or
something in between. But one thing that is certain is that PC pads differ in their output
(as shown in the list below), so it may be beneficiary to convert whatever radius they
produce to the radius the GC games expect. This is the first implementation of this
that convert a square radius to a circual radius. Use the advanced settings to enable
and calibrate it.
Observed diagonals:
Perfect circle: 71% = sin(45)
Logitech Dual Action: 100%
PS2 Dual Shock 2 (Original) with Super Dual Box Pro: 90%
XBox 360 Wireless: 85%
GameCube Controller (Third Party) with EMS Trio Linker Plus II: 60%
*/
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/* Calculate the distance from the outer edges of the box to the outer edges of the circle inside the box
at any angle from 0<> to 360<36>. The returned value is 1 + Distance, for example at most sqrt(2) in the
corners and at least 1.0 at the horizontal and vertical angles. */
float Square2CircleDistance(float deg)
{
// See if we have to adjust the angle
deg = abs(deg);
if( (deg > 45 && deg < 135) ) deg = deg - 90;
// Calculate distance from center
float val = abs(cos(Deg2Rad(deg)));
float Distance = 1 / val;
//m_frame->m_pStatusBar2->SetLabel(wxString::Format("Deg:%f Val:%f Dist:%f", deg, val, dist));
return Distance;
}
// Produce a perfect circle from an original square or rounded box
std::vector<int> Square2Circle(int _x, int _y, int _pad, std::string SDiagonal, bool Circle2Square)
{
// Do we need this?
if(_x > 32767) _x = 32767; if(_y > 32767) _y = 32767; // upper limit
if(_x < -32768) _x = -32768; if(_y < -32768) _y = -32768; // lower limit
// ====================================
// Convert to circle
// -----------
// Get the manually configured diagonal distance
int Tmp = atoi (SDiagonal.substr(0, SDiagonal.length() - 1).c_str());
float Diagonal = Tmp / 100.0f;
// First make a perfect square in case we don't have one already
float OrigDist = sqrt( pow((float)_y, 2) + pow((float)_x, 2) ); // Get current distance
float deg = Rad2Deg(atan2((float)_y, (float)_x)); // Get current angle
/* Calculate the actual distance between the maxium diagonal values, and the outer edges of the
square. A diagonal of 85% means a maximum distance of 0.85 * sqrt(2) ~1.2 in the diagonals. */
float corner_circle_dist = ( Diagonal / sin(Deg2Rad(45)) );
float SquareDist = Square2CircleDistance(deg);
// The original-to-square distance adjustment
float adj_ratio1;
// The circle-to-square distance adjustment
float adj_ratio2 = SquareDist;
// The resulting distance
float result_dist;
// Calculate the corner-to-square adjustment ratio
if(corner_circle_dist < SquareDist) adj_ratio1 = SquareDist / corner_circle_dist;
else adj_ratio1 = 1;
// Calculate the resulting distance
if(Circle2Square)
result_dist = OrigDist * adj_ratio1;
else
result_dist = OrigDist * adj_ratio1 / adj_ratio2;
// Calculate x and y and return it
float x = result_dist * cos(Deg2Rad(deg));
float y = result_dist * sin(Deg2Rad(deg));
// Make integers
int int_x = (int)floor(x);
int int_y = (int)floor(y);
// Boundaries
if (int_x < -32768) int_x = -32768; if (int_x > 32767) int_x = 32767;
if (int_y < -32768) int_y = -32768; if (int_y > 32767) int_y = 32767;
// Return it
std::vector<int> vec;
vec.push_back(int_x);
vec.push_back(int_y);
// Debugging
//Console::Print("%f %f %i", corner_circle_dist, Diagonal, Tmp));
return vec;
}
/////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Windows Virtual Key Codes Names
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#ifdef _WIN32
std::string VKToString(int keycode)
{
#ifdef _WIN32
// Default value
char KeyStr[64] = {0};
GetKeyNameText(MapVirtualKey(keycode, MAPVK_VK_TO_VSC) << 16, KeyStr, 64);
std::string KeyString = KeyStr;
switch(keycode)
{
// Give it some help with a few keys
case VK_END: return "END";
case VK_INSERT: return "INS";
case VK_DELETE: return "DEL";
case VK_PRIOR: return "PGUP";
case VK_NEXT: return "PGDN";
case VK_UP: return "UP";
case VK_DOWN: return "DOWN";
case VK_LEFT: return "LEFT";
case VK_RIGHT: return "RIGHT";
case VK_LSHIFT: return "LEFT SHIFT";
case VK_LCONTROL: return "LEFT CTRL";
case VK_RCONTROL: return "RIGHT CTRL";
case VK_LMENU: return "LEFT ALT";
default: return KeyString;
}
#else
// An equivalent name translation can probably be used on other systems to?
return "";
#endif
}
#endif
/////////////////////////////////////////////////////////////////////
}

View File

@ -1,366 +1,366 @@
//////////////////////////////////////////////////////////////////////////////////////////
// Project description
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Name: SDL Input
// Description: Common SDL Input Functions
//
// Author: Falcon4ever (nJoy@falcon4ever.com, www.multigesture.net), JPeterson etc
// Copyright (C) 2003-2008 Dolphin Project.
//
//////////////////////////////////////////////////////////////////////////////////////////
//
// Licensetype: GNU General Public License (GPL)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
//
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
//
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
//
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Include
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#define _SDL_MAIN_ // Avoid certain declarations in SDL.h
#include "SDL.h" // Local
#include "XInput.h"
////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Definitions
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int g_LastPad = 0;
////////////////////////////////////
namespace InputCommon
{
//////////////////////////////////////////////////////////////////////////////////////////
// Definitions
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Search attached devices. Populate joyinfo for all attached physical devices.
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
bool SearchDevices(std::vector<CONTROLLER_INFO> &_joyinfo, int &_NumPads, int &_NumGoodPads)
{
/* SDL 1.3 use DirectInput instead of the old Microsoft Multimedia API, and with this we need
the SDL_INIT_VIDEO flag to */
if (!SDL_WasInit(0))
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0)
{
PanicAlert("Could not initialize SDL: %s", SDL_GetError());
return false;
}
// Get device status
int numjoy = SDL_NumJoysticks();
for (int i = 0; i < numjoy; i++ )
{
CONTROLLER_INFO Tmp;
Tmp.joy = SDL_JoystickOpen(i);
Tmp.ID = i;
Tmp.NumAxes = SDL_JoystickNumAxes(Tmp.joy);
Tmp.NumButtons = SDL_JoystickNumButtons(Tmp.joy);
Tmp.NumBalls = SDL_JoystickNumBalls(Tmp.joy);
Tmp.NumHats = SDL_JoystickNumHats(Tmp.joy);
Tmp.Name = SDL_JoystickName(i);
// Check if the device is okay
if ( Tmp.NumAxes == 0
&& Tmp.NumBalls == 0
&& Tmp.NumButtons == 0
&& Tmp.NumHats == 0
)
{
Tmp.Good = false;
}
else
{
_NumGoodPads++;
Tmp.Good = true;
}
_joyinfo.push_back(Tmp);
// We have now read the values we need so we close the device
if (SDL_JoystickOpened(i)) SDL_JoystickClose(_joyinfo[i].joy);
}
_NumPads = (int)_joyinfo.size();
return true;
}
////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Supporting functions
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Read current joystick status
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
The value PadMapping[].buttons[] is the number of the assigned joypad button,
PadState[].buttons[] is the status of the button, it becomes 0 (no pressed) or 1 (pressed) */
// Read buttons status. Called from GetJoyState().
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void ReadButton(CONTROLLER_STATE &_PadState, CONTROLLER_MAPPING _PadMapping, int button, int NumButtons)
{
int ctl_button = _PadMapping.buttons[button];
if (ctl_button < NumButtons)
{
_PadState.buttons[button] = SDL_JoystickGetButton(_PadState.joy, ctl_button);
}
}
// Request joystick state.
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/* Called from: PAD_GetStatus()
Input: The virtual device 0, 1, 2 or 3
Function: Updates the PadState struct with the current pad status. The input value "controller" is
for a virtual controller 0 to 3. */
void GetJoyState(CONTROLLER_STATE &_PadState, CONTROLLER_MAPPING _PadMapping, int Controller, int NumButtons)
{
// Update the gamepad status
SDL_JoystickUpdate();
// Update axis states. It doesn't hurt much if we happen to ask for nonexisting axises here.
_PadState.axis[CTL_MAIN_X] = SDL_JoystickGetAxis(_PadState.joy, _PadMapping.axis[CTL_MAIN_X]);
_PadState.axis[CTL_MAIN_Y] = SDL_JoystickGetAxis(_PadState.joy, _PadMapping.axis[CTL_MAIN_Y]);
_PadState.axis[CTL_SUB_X] = SDL_JoystickGetAxis(_PadState.joy, _PadMapping.axis[CTL_SUB_X]);
_PadState.axis[CTL_SUB_Y] = SDL_JoystickGetAxis(_PadState.joy, _PadMapping.axis[CTL_SUB_Y]);
// Update the analog trigger axis values
#ifdef _WIN32
if (_PadMapping.triggertype == CTL_TRIGGER_SDL)
{
#endif
// If we are using SDL analog triggers the buttons have to be mapped as 1000 or up, otherwise they are not used
if(_PadMapping.buttons[CTL_L_SHOULDER] >= 1000) _PadState.axis[CTL_L_SHOULDER] = SDL_JoystickGetAxis(_PadState.joy, _PadMapping.buttons[CTL_L_SHOULDER] - 1000); else _PadState.axis[CTL_L_SHOULDER] = 0;
if(_PadMapping.buttons[CTL_R_SHOULDER] >= 1000) _PadState.axis[CTL_R_SHOULDER] = SDL_JoystickGetAxis(_PadState.joy, _PadMapping.buttons[CTL_R_SHOULDER] - 1000); else _PadState.axis[CTL_R_SHOULDER] = 0;
#ifdef _WIN32
}
else
{
_PadState.axis[CTL_L_SHOULDER] = XInput::GetXI(0, _PadMapping.buttons[CTL_L_SHOULDER] - 1000);
_PadState.axis[CTL_R_SHOULDER] = XInput::GetXI(0, _PadMapping.buttons[CTL_R_SHOULDER] - 1000);
}
#endif
// Update button states to on or off
ReadButton(_PadState, _PadMapping, CTL_L_SHOULDER, NumButtons);
ReadButton(_PadState, _PadMapping, CTL_R_SHOULDER, NumButtons);
ReadButton(_PadState, _PadMapping, CTL_A_BUTTON, NumButtons);
ReadButton(_PadState, _PadMapping, CTL_B_BUTTON, NumButtons);
ReadButton(_PadState, _PadMapping, CTL_X_BUTTON, NumButtons);
ReadButton(_PadState, _PadMapping, CTL_Y_BUTTON, NumButtons);
ReadButton(_PadState, _PadMapping, CTL_Z_TRIGGER, NumButtons);
ReadButton(_PadState, _PadMapping, CTL_START, NumButtons);
//
if (_PadMapping.halfpress < NumButtons)
_PadState.halfpress = SDL_JoystickGetButton(_PadState.joy, _PadMapping.halfpress);
// Check if we have an analog or digital joypad
if (_PadMapping.controllertype == CTL_DPAD_HAT)
{
_PadState.dpad = SDL_JoystickGetHat(_PadState.joy, _PadMapping.dpad);
}
else
{
/* Only do this if the assigned button is in range (to allow for the current way of saving keyboard
keys in the same array) */
if(_PadMapping.dpad2[CTL_D_PAD_UP] <= NumButtons)
_PadState.dpad2[CTL_D_PAD_UP] = SDL_JoystickGetButton(_PadState.joy, _PadMapping.dpad2[CTL_D_PAD_UP]);
if(_PadMapping.dpad2[CTL_D_PAD_DOWN] <= NumButtons)
_PadState.dpad2[CTL_D_PAD_DOWN] = SDL_JoystickGetButton(_PadState.joy, _PadMapping.dpad2[CTL_D_PAD_DOWN]);
if(_PadMapping.dpad2[CTL_D_PAD_LEFT] <= NumButtons)
_PadState.dpad2[CTL_D_PAD_LEFT] = SDL_JoystickGetButton(_PadState.joy, _PadMapping.dpad2[CTL_D_PAD_LEFT]);
if(_PadMapping.dpad2[CTL_D_PAD_RIGHT] <= NumButtons)
_PadState.dpad2[CTL_D_PAD_RIGHT] = SDL_JoystickGetButton(_PadState.joy, _PadMapping.dpad2[CTL_D_PAD_RIGHT]);
}
#ifdef SHOW_PAD_STATUS
// Show the status of all connected pads
if ((g_LastPad == 0 && Controller == 0) || Controller < g_LastPad) Console::ClearScreen();
g_LastPad = Controller;
Console::Print(
"Pad | Number:%i Enabled:%i Handle:%i\n"
"Main Stick | X:%03i Y:%03i\n"
"C Stick | X:%03i Y:%03i\n"
"Trigger | Type:%s DigitalL:%i DigitalR:%i AnalogL:%03i AnalogR:%03i HalfPress:%i\n"
"Buttons | A:%i X:%i\n"
"D-Pad | Type:%s Hat:%i U:%i D:%i\n"
"======================================================\n",
Controller, _PadMapping.enabled, _PadState.joy,
_PadState.axis[InputCommon::CTL_MAIN_X], _PadState.axis[InputCommon::CTL_MAIN_Y],
_PadState.axis[InputCommon::CTL_SUB_X], _PadState.axis[InputCommon::CTL_SUB_Y],
(_PadMapping.triggertype ? "CTL_TRIGGER_XINPUT" : "CTL_TRIGGER_SDL"),
_PadState.buttons[InputCommon::CTL_L_SHOULDER], _PadState.buttons[InputCommon::CTL_R_SHOULDER],
_PadState.axis[InputCommon::CTL_L_SHOULDER], _PadState.axis[InputCommon::CTL_R_SHOULDER],
_PadState.halfpress,
_PadState.buttons[InputCommon::CTL_A_BUTTON], _PadState.buttons[InputCommon::CTL_X_BUTTON],
(_PadMapping.controllertype ? "CTL_DPAD_CUSTOM" : "CTL_DPAD_HAT"),
_PadState.dpad,
_PadState.dpad2[InputCommon::CTL_D_PAD_UP], _PadState.dpad2[InputCommon::CTL_D_PAD_DOWN]
);
#endif
}
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Configure button mapping
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Avoid extreme axis values
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/* Function: We have to avoid very big values to becuse some triggers are -0x8000 in the
unpressed state (and then go from -0x8000 to 0x8000 as they are fully pressed) */
bool AvoidValues(int value, bool NoTriggerFilter)
{
// Avoid detecting very small or very big (for triggers) values
if( (value > -0x2000 && value < 0x2000) // Small values
|| ((value < -0x6000 || value > 0x6000) && !NoTriggerFilter)) // Big values
return true; // Avoid
else
return false; // Keep
}
// Detect a pressed button
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void GetButton(SDL_Joystick *joy, int ControllerID, int buttons, int axes, int hats,
int &KeyboardKey, int &value, int &type, int &pressed, bool &Succeed, bool &Stop,
bool LeftRight, bool Axis, bool XInput, bool Button, bool Hat, bool NoTriggerFilter)
{
// It needs the wxWidgets excape keycode
static const int WXK_ESCAPE = 27;
// Update the internal status
SDL_JoystickUpdate();
// For the triggers we accept both a digital or an analog button
if(Axis)
{
for(int i = 0; i < axes; i++)
{
value = SDL_JoystickGetAxis(joy, i);
if(AvoidValues(value, NoTriggerFilter)) continue; // Avoid values
pressed = i + (LeftRight ? 1000 : 0); // Identify the analog triggers
type = InputCommon::CTL_AXIS;
Succeed = true;
}
}
// Check for a hat
if(Hat)
{
for(int i = 0; i < hats; i++)
{
if(SDL_JoystickGetHat(joy, i))
{
pressed = i;
type = InputCommon::CTL_HAT;
Succeed = true;
}
}
}
// Check for a button
if(Button)
{
for(int i = 0; i < buttons; i++)
{
// Some kind of bug in SDL 1.3 would give button 9 and 10 (nonexistent) the value 48 on the 360 pad
if (SDL_JoystickGetButton(joy, i) > 1) continue;
if(SDL_JoystickGetButton(joy, i))
{
pressed = i;
type = InputCommon::CTL_BUTTON;
Succeed = true;
}
}
}
// Check for a XInput trigger
#ifdef _WIN32
if(XInput)
{
for(int i = 0; i <= InputCommon::XI_TRIGGER_R; i++)
{
if(XInput::GetXI(0, i))
{
pressed = i + 1000;
type = InputCommon::CTL_AXIS;
Succeed = true;
}
}
}
#endif
// Check for keyboard action
if (KeyboardKey)
{
if(Button)
{
// Todo: Add a separate keyboard vector to remove this restriction
if(KeyboardKey >= buttons)
{
pressed = KeyboardKey;
type = InputCommon::CTL_BUTTON;
Succeed = true;
KeyboardKey = 0;
if(pressed == WXK_ESCAPE) pressed = -1; // Check for the escape key
}
// Else show the error message
else
{
pressed = KeyboardKey;
KeyboardKey = -1;
Stop = true;
}
}
// Only accept the escape key
else if (KeyboardKey == WXK_ESCAPE)
{
Succeed = true;
KeyboardKey = 0;
pressed = -1;
}
}
}
/////////////////////////////////////////////////////////// Configure button mapping
//////////////////////////////////////////////////////////////////////////////////////////
// Project description
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Name: SDL Input
// Description: Common SDL Input Functions
//
// Author: Falcon4ever (nJoy@falcon4ever.com, www.multigesture.net), JPeterson etc
// Copyright (C) 2003-2008 Dolphin Project.
//
//////////////////////////////////////////////////////////////////////////////////////////
//
// Licensetype: GNU General Public License (GPL)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
//
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
//
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
//
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Include
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#define _SDL_MAIN_ // Avoid certain declarations in SDL.h
#include "SDL.h" // Local
#include "XInput.h"
////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Definitions
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int g_LastPad = 0;
////////////////////////////////////
namespace InputCommon
{
//////////////////////////////////////////////////////////////////////////////////////////
// Definitions
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Search attached devices. Populate joyinfo for all attached physical devices.
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
bool SearchDevices(std::vector<CONTROLLER_INFO> &_joyinfo, int &_NumPads, int &_NumGoodPads)
{
/* SDL 1.3 use DirectInput instead of the old Microsoft Multimedia API, and with this we need
the SDL_INIT_VIDEO flag to */
if (!SDL_WasInit(0))
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0)
{
PanicAlert("Could not initialize SDL: %s", SDL_GetError());
return false;
}
// Get device status
int numjoy = SDL_NumJoysticks();
for (int i = 0; i < numjoy; i++ )
{
CONTROLLER_INFO Tmp;
Tmp.joy = SDL_JoystickOpen(i);
Tmp.ID = i;
Tmp.NumAxes = SDL_JoystickNumAxes(Tmp.joy);
Tmp.NumButtons = SDL_JoystickNumButtons(Tmp.joy);
Tmp.NumBalls = SDL_JoystickNumBalls(Tmp.joy);
Tmp.NumHats = SDL_JoystickNumHats(Tmp.joy);
Tmp.Name = SDL_JoystickName(i);
// Check if the device is okay
if ( Tmp.NumAxes == 0
&& Tmp.NumBalls == 0
&& Tmp.NumButtons == 0
&& Tmp.NumHats == 0
)
{
Tmp.Good = false;
}
else
{
_NumGoodPads++;
Tmp.Good = true;
}
_joyinfo.push_back(Tmp);
// We have now read the values we need so we close the device
if (SDL_JoystickOpened(i)) SDL_JoystickClose(_joyinfo[i].joy);
}
_NumPads = (int)_joyinfo.size();
return true;
}
////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Supporting functions
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Read current joystick status
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
The value PadMapping[].buttons[] is the number of the assigned joypad button,
PadState[].buttons[] is the status of the button, it becomes 0 (no pressed) or 1 (pressed) */
// Read buttons status. Called from GetJoyState().
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void ReadButton(CONTROLLER_STATE &_PadState, CONTROLLER_MAPPING _PadMapping, int button, int NumButtons)
{
int ctl_button = _PadMapping.buttons[button];
if (ctl_button < NumButtons)
{
_PadState.buttons[button] = SDL_JoystickGetButton(_PadState.joy, ctl_button);
}
}
// Request joystick state.
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/* Called from: PAD_GetStatus()
Input: The virtual device 0, 1, 2 or 3
Function: Updates the PadState struct with the current pad status. The input value "controller" is
for a virtual controller 0 to 3. */
void GetJoyState(CONTROLLER_STATE &_PadState, CONTROLLER_MAPPING _PadMapping, int Controller, int NumButtons)
{
// Update the gamepad status
SDL_JoystickUpdate();
// Update axis states. It doesn't hurt much if we happen to ask for nonexisting axises here.
_PadState.axis[CTL_MAIN_X] = SDL_JoystickGetAxis(_PadState.joy, _PadMapping.axis[CTL_MAIN_X]);
_PadState.axis[CTL_MAIN_Y] = SDL_JoystickGetAxis(_PadState.joy, _PadMapping.axis[CTL_MAIN_Y]);
_PadState.axis[CTL_SUB_X] = SDL_JoystickGetAxis(_PadState.joy, _PadMapping.axis[CTL_SUB_X]);
_PadState.axis[CTL_SUB_Y] = SDL_JoystickGetAxis(_PadState.joy, _PadMapping.axis[CTL_SUB_Y]);
// Update the analog trigger axis values
#ifdef _WIN32
if (_PadMapping.triggertype == CTL_TRIGGER_SDL)
{
#endif
// If we are using SDL analog triggers the buttons have to be mapped as 1000 or up, otherwise they are not used
if(_PadMapping.buttons[CTL_L_SHOULDER] >= 1000) _PadState.axis[CTL_L_SHOULDER] = SDL_JoystickGetAxis(_PadState.joy, _PadMapping.buttons[CTL_L_SHOULDER] - 1000); else _PadState.axis[CTL_L_SHOULDER] = 0;
if(_PadMapping.buttons[CTL_R_SHOULDER] >= 1000) _PadState.axis[CTL_R_SHOULDER] = SDL_JoystickGetAxis(_PadState.joy, _PadMapping.buttons[CTL_R_SHOULDER] - 1000); else _PadState.axis[CTL_R_SHOULDER] = 0;
#ifdef _WIN32
}
else
{
_PadState.axis[CTL_L_SHOULDER] = XInput::GetXI(0, _PadMapping.buttons[CTL_L_SHOULDER] - 1000);
_PadState.axis[CTL_R_SHOULDER] = XInput::GetXI(0, _PadMapping.buttons[CTL_R_SHOULDER] - 1000);
}
#endif
// Update button states to on or off
ReadButton(_PadState, _PadMapping, CTL_L_SHOULDER, NumButtons);
ReadButton(_PadState, _PadMapping, CTL_R_SHOULDER, NumButtons);
ReadButton(_PadState, _PadMapping, CTL_A_BUTTON, NumButtons);
ReadButton(_PadState, _PadMapping, CTL_B_BUTTON, NumButtons);
ReadButton(_PadState, _PadMapping, CTL_X_BUTTON, NumButtons);
ReadButton(_PadState, _PadMapping, CTL_Y_BUTTON, NumButtons);
ReadButton(_PadState, _PadMapping, CTL_Z_TRIGGER, NumButtons);
ReadButton(_PadState, _PadMapping, CTL_START, NumButtons);
//
if (_PadMapping.halfpress < NumButtons)
_PadState.halfpress = SDL_JoystickGetButton(_PadState.joy, _PadMapping.halfpress);
// Check if we have an analog or digital joypad
if (_PadMapping.controllertype == CTL_DPAD_HAT)
{
_PadState.dpad = SDL_JoystickGetHat(_PadState.joy, _PadMapping.dpad);
}
else
{
/* Only do this if the assigned button is in range (to allow for the current way of saving keyboard
keys in the same array) */
if(_PadMapping.dpad2[CTL_D_PAD_UP] <= NumButtons)
_PadState.dpad2[CTL_D_PAD_UP] = SDL_JoystickGetButton(_PadState.joy, _PadMapping.dpad2[CTL_D_PAD_UP]);
if(_PadMapping.dpad2[CTL_D_PAD_DOWN] <= NumButtons)
_PadState.dpad2[CTL_D_PAD_DOWN] = SDL_JoystickGetButton(_PadState.joy, _PadMapping.dpad2[CTL_D_PAD_DOWN]);
if(_PadMapping.dpad2[CTL_D_PAD_LEFT] <= NumButtons)
_PadState.dpad2[CTL_D_PAD_LEFT] = SDL_JoystickGetButton(_PadState.joy, _PadMapping.dpad2[CTL_D_PAD_LEFT]);
if(_PadMapping.dpad2[CTL_D_PAD_RIGHT] <= NumButtons)
_PadState.dpad2[CTL_D_PAD_RIGHT] = SDL_JoystickGetButton(_PadState.joy, _PadMapping.dpad2[CTL_D_PAD_RIGHT]);
}
#ifdef SHOW_PAD_STATUS
// Show the status of all connected pads
if ((g_LastPad == 0 && Controller == 0) || Controller < g_LastPad) Console::ClearScreen();
g_LastPad = Controller;
Console::Print(
"Pad | Number:%i Enabled:%i Handle:%i\n"
"Main Stick | X:%03i Y:%03i\n"
"C Stick | X:%03i Y:%03i\n"
"Trigger | Type:%s DigitalL:%i DigitalR:%i AnalogL:%03i AnalogR:%03i HalfPress:%i\n"
"Buttons | A:%i X:%i\n"
"D-Pad | Type:%s Hat:%i U:%i D:%i\n"
"======================================================\n",
Controller, _PadMapping.enabled, _PadState.joy,
_PadState.axis[InputCommon::CTL_MAIN_X], _PadState.axis[InputCommon::CTL_MAIN_Y],
_PadState.axis[InputCommon::CTL_SUB_X], _PadState.axis[InputCommon::CTL_SUB_Y],
(_PadMapping.triggertype ? "CTL_TRIGGER_XINPUT" : "CTL_TRIGGER_SDL"),
_PadState.buttons[InputCommon::CTL_L_SHOULDER], _PadState.buttons[InputCommon::CTL_R_SHOULDER],
_PadState.axis[InputCommon::CTL_L_SHOULDER], _PadState.axis[InputCommon::CTL_R_SHOULDER],
_PadState.halfpress,
_PadState.buttons[InputCommon::CTL_A_BUTTON], _PadState.buttons[InputCommon::CTL_X_BUTTON],
(_PadMapping.controllertype ? "CTL_DPAD_CUSTOM" : "CTL_DPAD_HAT"),
_PadState.dpad,
_PadState.dpad2[InputCommon::CTL_D_PAD_UP], _PadState.dpad2[InputCommon::CTL_D_PAD_DOWN]
);
#endif
}
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Configure button mapping
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// Avoid extreme axis values
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/* Function: We have to avoid very big values to becuse some triggers are -0x8000 in the
unpressed state (and then go from -0x8000 to 0x8000 as they are fully pressed) */
bool AvoidValues(int value, bool NoTriggerFilter)
{
// Avoid detecting very small or very big (for triggers) values
if( (value > -0x2000 && value < 0x2000) // Small values
|| ((value < -0x6000 || value > 0x6000) && !NoTriggerFilter)) // Big values
return true; // Avoid
else
return false; // Keep
}
// Detect a pressed button
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void GetButton(SDL_Joystick *joy, int ControllerID, int buttons, int axes, int hats,
int &KeyboardKey, int &value, int &type, int &pressed, bool &Succeed, bool &Stop,
bool LeftRight, bool Axis, bool XInput, bool Button, bool Hat, bool NoTriggerFilter)
{
// It needs the wxWidgets excape keycode
static const int WXK_ESCAPE = 27;
// Update the internal status
SDL_JoystickUpdate();
// For the triggers we accept both a digital or an analog button
if(Axis)
{
for(int i = 0; i < axes; i++)
{
value = SDL_JoystickGetAxis(joy, i);
if(AvoidValues(value, NoTriggerFilter)) continue; // Avoid values
pressed = i + (LeftRight ? 1000 : 0); // Identify the analog triggers
type = InputCommon::CTL_AXIS;
Succeed = true;
}
}
// Check for a hat
if(Hat)
{
for(int i = 0; i < hats; i++)
{
if(SDL_JoystickGetHat(joy, i))
{
pressed = i;
type = InputCommon::CTL_HAT;
Succeed = true;
}
}
}
// Check for a button
if(Button)
{
for(int i = 0; i < buttons; i++)
{
// Some kind of bug in SDL 1.3 would give button 9 and 10 (nonexistent) the value 48 on the 360 pad
if (SDL_JoystickGetButton(joy, i) > 1) continue;
if(SDL_JoystickGetButton(joy, i))
{
pressed = i;
type = InputCommon::CTL_BUTTON;
Succeed = true;
}
}
}
// Check for a XInput trigger
#ifdef _WIN32
if(XInput)
{
for(int i = 0; i <= InputCommon::XI_TRIGGER_R; i++)
{
if(XInput::GetXI(0, i))
{
pressed = i + 1000;
type = InputCommon::CTL_AXIS;
Succeed = true;
}
}
}
#endif
// Check for keyboard action
if (KeyboardKey)
{
if(Button)
{
// Todo: Add a separate keyboard vector to remove this restriction
if(KeyboardKey >= buttons)
{
pressed = KeyboardKey;
type = InputCommon::CTL_BUTTON;
Succeed = true;
KeyboardKey = 0;
if(pressed == WXK_ESCAPE) pressed = -1; // Check for the escape key
}
// Else show the error message
else
{
pressed = KeyboardKey;
KeyboardKey = -1;
Stop = true;
}
}
// Only accept the escape key
else if (KeyboardKey == WXK_ESCAPE)
{
Succeed = true;
KeyboardKey = 0;
pressed = -1;
}
}
}
/////////////////////////////////////////////////////////// Configure button mapping
} // InputCommon

View File

@ -1,136 +1,136 @@
//////////////////////////////////////////////////////////////////////////////////////////
//
// Licensetype: GNU General Public License (GPL)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
//
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
//
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
//
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// File description
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Function: This file will get the status of the analog triggers of any connected XInput device.
This code was made with the help of SimpleController.cpp in the June 2008 Microsoft DirectX SDK
Samples.
///////////////////////////////////////////////////// */
#ifdef _WIN32
//////////////////////////////////////////////////////////////////////////////////////////
// Includes
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#include <windows.h>
#include <XInput.h> // XInput API
#include "SDL.h" // Local
///////////////////////////////////////////////
namespace XInput
{
//////////////////////////////////////////////////////////////////////////////////////////
// Declarations
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#define MAX_CONTROLLERS 4 // XInput handles up to 4 controllers
struct CONTROLER_STATE
{
XINPUT_STATE state;
bool bConnected;
};
CONTROLER_STATE g_Controllers[MAX_CONTROLLERS];
///////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Init
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/* Function: Calculate the number of connected XInput devices
Todo: Implement this to figure out if there are multiple XInput controllers connected,
we currently only try to connect to XInput device 0 */
void Init()
{
// Init state
//ZeroMemory( g_Controllers, sizeof( CONTROLER_STATE ) * MAX_CONTROLLERS );
// Declaration
DWORD dwResult;
// Calculate the number of connected XInput devices
for( DWORD i = 0; i < MAX_CONTROLLERS; i++ )
{
// Simply get the state of the controller from XInput.
dwResult = XInputGetState( i, &g_Controllers[i].state );
if( dwResult == ERROR_SUCCESS )
g_Controllers[i].bConnected = true;
else
g_Controllers[i].bConnected = false;
}
}
///////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Get the trigger status
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int GetXI(int Controller, int Button)
{
// Update the internal status
DWORD dwResult;
dwResult = XInputGetState( Controller, &g_Controllers[Controller].state );
if( dwResult != ERROR_SUCCESS ) return -1;
switch(Button)
{
case InputCommon::XI_TRIGGER_L:
return g_Controllers[0].state.Gamepad.bLeftTrigger;
case InputCommon::XI_TRIGGER_R:
return g_Controllers[0].state.Gamepad.bRightTrigger;
default:
return 0;
}
}
///////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Check if a certain controller is connected
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
bool IsConnected(int Controller)
{
DWORD dwResult = XInputGetState( Controller, &g_Controllers[Controller].state );
// Update the connected status
if( dwResult == ERROR_SUCCESS )
return true;
else
return false;
}
///////////////////////////////////////////
} // XInput
//////////////////////////////////////////////////////////////////////////////////////////
//
// Licensetype: GNU General Public License (GPL)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
//
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
//
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
//
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// File description
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
Function: This file will get the status of the analog triggers of any connected XInput device.
This code was made with the help of SimpleController.cpp in the June 2008 Microsoft DirectX SDK
Samples.
///////////////////////////////////////////////////// */
#ifdef _WIN32
//////////////////////////////////////////////////////////////////////////////////////////
// Includes
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#include <windows.h>
#include <XInput.h> // XInput API
#include "SDL.h" // Local
///////////////////////////////////////////////
namespace XInput
{
//////////////////////////////////////////////////////////////////////////////////////////
// Declarations
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#define MAX_CONTROLLERS 4 // XInput handles up to 4 controllers
struct CONTROLER_STATE
{
XINPUT_STATE state;
bool bConnected;
};
CONTROLER_STATE g_Controllers[MAX_CONTROLLERS];
///////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Init
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/* Function: Calculate the number of connected XInput devices
Todo: Implement this to figure out if there are multiple XInput controllers connected,
we currently only try to connect to XInput device 0 */
void Init()
{
// Init state
//ZeroMemory( g_Controllers, sizeof( CONTROLER_STATE ) * MAX_CONTROLLERS );
// Declaration
DWORD dwResult;
// Calculate the number of connected XInput devices
for( DWORD i = 0; i < MAX_CONTROLLERS; i++ )
{
// Simply get the state of the controller from XInput.
dwResult = XInputGetState( i, &g_Controllers[i].state );
if( dwResult == ERROR_SUCCESS )
g_Controllers[i].bConnected = true;
else
g_Controllers[i].bConnected = false;
}
}
///////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Get the trigger status
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int GetXI(int Controller, int Button)
{
// Update the internal status
DWORD dwResult;
dwResult = XInputGetState( Controller, &g_Controllers[Controller].state );
if( dwResult != ERROR_SUCCESS ) return -1;
switch(Button)
{
case InputCommon::XI_TRIGGER_L:
return g_Controllers[0].state.Gamepad.bLeftTrigger;
case InputCommon::XI_TRIGGER_R:
return g_Controllers[0].state.Gamepad.bRightTrigger;
default:
return 0;
}
}
///////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Check if a certain controller is connected
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
bool IsConnected(int Controller)
{
DWORD dwResult = XInputGetState( Controller, &g_Controllers[Controller].state );
// Update the connected status
if( dwResult == ERROR_SUCCESS )
return true;
else
return false;
}
///////////////////////////////////////////
} // XInput
#endif

View File

@ -1,26 +1,26 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "NativeVertexWriter.h"
namespace VertexManager
{
u8* s_pCurBufferPointer = NULL;
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "NativeVertexWriter.h"
namespace VertexManager
{
u8* s_pCurBufferPointer = NULL;
}