mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-24 14:49:42 -06:00
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:
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
@ -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();
|
||||
}
|
||||
|
@ -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
@ -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);
|
||||
}
|
||||
}
|
||||
// ==============
|
||||
|
@ -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);
|
||||
}
|
@ -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
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
@ -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
|
@ -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
|
@ -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;
|
||||
|
||||
}
|
Reference in New Issue
Block a user