mirror of https://github.com/PCSX2/pcsx2.git
reformat main common directory
Disable some reformat around emitter registers declaration and a massive cases.
This commit is contained in:
parent
1053234507
commit
1fba5cb580
File diff suppressed because it is too large
Load Diff
|
@ -55,8 +55,7 @@ static void __forceinline PluginNullConfigure(std::wstring desc, s32 &log);
|
||||||
static void __forceinline PluginNullAbout(const wchar_t *aboutText);
|
static void __forceinline PluginNullAbout(const wchar_t *aboutText);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum FileMode
|
enum FileMode {
|
||||||
{
|
|
||||||
READ_FILE = 0,
|
READ_FILE = 0,
|
||||||
WRITE_FILE
|
WRITE_FILE
|
||||||
};
|
};
|
||||||
|
@ -70,9 +69,8 @@ struct PluginLog
|
||||||
{
|
{
|
||||||
LogFile = fopen(logname.c_str(), "w");
|
LogFile = fopen(logname.c_str(), "w");
|
||||||
|
|
||||||
if (LogFile)
|
if (LogFile) {
|
||||||
{
|
setvbuf(LogFile, NULL, _IONBF, 0);
|
||||||
setvbuf(LogFile, NULL, _IONBF, 0);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -90,11 +88,14 @@ struct PluginLog
|
||||||
{
|
{
|
||||||
va_list list;
|
va_list list;
|
||||||
|
|
||||||
if (LogFile == NULL) return;
|
if (LogFile == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
va_start(list, fmt);
|
va_start(list, fmt);
|
||||||
if (WriteToFile) vfprintf(LogFile, fmt, list);
|
if (WriteToFile)
|
||||||
if (WriteToConsole) vfprintf(stdout, fmt, list);
|
vfprintf(LogFile, fmt, list);
|
||||||
|
if (WriteToConsole)
|
||||||
|
vfprintf(stdout, fmt, list);
|
||||||
va_end(list);
|
va_end(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,15 +103,20 @@ struct PluginLog
|
||||||
{
|
{
|
||||||
va_list list;
|
va_list list;
|
||||||
|
|
||||||
if (LogFile == NULL) return;
|
if (LogFile == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
va_start(list, fmt);
|
va_start(list, fmt);
|
||||||
if (WriteToFile) vfprintf(LogFile, fmt, list);
|
if (WriteToFile)
|
||||||
if (WriteToConsole) vfprintf(stdout, fmt, list);
|
vfprintf(LogFile, fmt, list);
|
||||||
|
if (WriteToConsole)
|
||||||
|
vfprintf(stdout, fmt, list);
|
||||||
va_end(list);
|
va_end(list);
|
||||||
|
|
||||||
if (WriteToFile) fprintf(LogFile, "\n");
|
if (WriteToFile)
|
||||||
if (WriteToConsole) fprintf(stdout, "\n");
|
fprintf(LogFile, "\n");
|
||||||
|
if (WriteToConsole)
|
||||||
|
fprintf(stdout, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(_MSC_VER) || !defined(UNICODE)
|
#if !defined(_MSC_VER) || !defined(UNICODE)
|
||||||
|
@ -119,7 +125,8 @@ struct PluginLog
|
||||||
va_list list;
|
va_list list;
|
||||||
char buf[256];
|
char buf[256];
|
||||||
|
|
||||||
if (LogFile == NULL) return;
|
if (LogFile == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
va_start(list, fmt);
|
va_start(list, fmt);
|
||||||
vsprintf(buf, fmt, list);
|
vsprintf(buf, fmt, list);
|
||||||
|
@ -128,19 +135,20 @@ struct PluginLog
|
||||||
SysMessage(buf);
|
SysMessage(buf);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
void Message(const wchar_t *fmt, ...)
|
void Message(const wchar_t *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list list;
|
va_list list;
|
||||||
wchar_t buf[256];
|
wchar_t buf[256];
|
||||||
|
|
||||||
if (LogFile == NULL) return;
|
if (LogFile == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
va_start(list, fmt);
|
va_start(list, fmt);
|
||||||
vswprintf(buf, 256, fmt, list);
|
vswprintf(buf, 256, fmt, list);
|
||||||
va_end(list);
|
va_end(list);
|
||||||
|
|
||||||
SysMessage(buf);
|
SysMessage(buf);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -151,16 +159,14 @@ struct PluginConf
|
||||||
|
|
||||||
bool Open(std::string name, FileMode mode = READ_FILE)
|
bool Open(std::string name, FileMode mode = READ_FILE)
|
||||||
{
|
{
|
||||||
if (mode == READ_FILE)
|
if (mode == READ_FILE) {
|
||||||
{
|
|
||||||
ConfFile = fopen(name.c_str(), "r");
|
ConfFile = fopen(name.c_str(), "r");
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
ConfFile = fopen(name.c_str(), "w");
|
ConfFile = fopen(name.c_str(), "w");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ConfFile == NULL) return false;
|
if (ConfFile == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -173,14 +179,14 @@ struct PluginConf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int ReadInt(const std::string& item, int defval)
|
int ReadInt(const std::string &item, int defval)
|
||||||
{
|
{
|
||||||
int value = defval;
|
int value = defval;
|
||||||
std::string buf = item + " = %d\n";
|
std::string buf = item + " = %d\n";
|
||||||
|
|
||||||
if (ConfFile)
|
if (ConfFile)
|
||||||
if (fscanf(ConfFile, buf.c_str(), &value) < 0)
|
if (fscanf(ConfFile, buf.c_str(), &value) < 0)
|
||||||
fprintf(stderr, "Error reading %s\n", item.c_str());
|
fprintf(stderr, "Error reading %s\n", item.c_str());
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -189,7 +195,8 @@ struct PluginConf
|
||||||
{
|
{
|
||||||
std::string buf = item + " = %d\n";
|
std::string buf = item + " = %d\n";
|
||||||
|
|
||||||
if (ConfFile) fprintf(ConfFile, buf.c_str(), value);
|
if (ConfFile)
|
||||||
|
fprintf(ConfFile, buf.c_str(), value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -204,19 +211,20 @@ static void SysMessage(const char *fmt, ...)
|
||||||
vsprintf(msg, fmt, list);
|
vsprintf(msg, fmt, list);
|
||||||
va_end(list);
|
va_end(list);
|
||||||
|
|
||||||
if (msg[strlen(msg)-1] == '\n') msg[strlen(msg)-1] = 0;
|
if (msg[strlen(msg) - 1] == '\n')
|
||||||
|
msg[strlen(msg) - 1] = 0;
|
||||||
|
|
||||||
GtkWidget *dialog;
|
GtkWidget *dialog;
|
||||||
dialog = gtk_message_dialog_new (NULL,
|
dialog = gtk_message_dialog_new(NULL,
|
||||||
GTK_DIALOG_DESTROY_WITH_PARENT,
|
GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||||
GTK_MESSAGE_INFO,
|
GTK_MESSAGE_INFO,
|
||||||
GTK_BUTTONS_OK,
|
GTK_BUTTONS_OK,
|
||||||
"%s", msg);
|
"%s", msg);
|
||||||
gtk_dialog_run (GTK_DIALOG (dialog));
|
gtk_dialog_run(GTK_DIALOG(dialog));
|
||||||
gtk_widget_destroy (dialog);
|
gtk_widget_destroy(dialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __forceinline set_logging(GtkToggleButton *check, int& log)
|
static void __forceinline set_logging(GtkToggleButton *check, int &log)
|
||||||
{
|
{
|
||||||
log = gtk_toggle_button_get_active(check);
|
log = gtk_toggle_button_get_active(check);
|
||||||
}
|
}
|
||||||
|
@ -227,7 +235,7 @@ static void __forceinline PluginNullConfigure(std::string desc, int &log)
|
||||||
|
|
||||||
/* Create the widgets */
|
/* Create the widgets */
|
||||||
dialog = gtk_dialog_new();
|
dialog = gtk_dialog_new();
|
||||||
label = gtk_label_new (desc.c_str());
|
label = gtk_label_new(desc.c_str());
|
||||||
check_box = gtk_check_button_new_with_label("Logging");
|
check_box = gtk_check_button_new_with_label("Logging");
|
||||||
|
|
||||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_box), (log != 0));
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_box), (log != 0));
|
||||||
|
@ -236,14 +244,14 @@ static void __forceinline PluginNullConfigure(std::string desc, int &log)
|
||||||
g_signal_connect(check_box, "toggled", G_CALLBACK(set_logging), &log);
|
g_signal_connect(check_box, "toggled", G_CALLBACK(set_logging), &log);
|
||||||
|
|
||||||
/* Add all our widgets, and show everything we've added to the dialog. */
|
/* Add all our widgets, and show everything we've added to the dialog. */
|
||||||
gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area(GTK_DIALOG(dialog))), label);
|
gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), label);
|
||||||
gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area(GTK_DIALOG(dialog))), check_box);
|
gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), check_box);
|
||||||
gtk_dialog_add_button(GTK_DIALOG(dialog), "Ok", 0);
|
gtk_dialog_add_button(GTK_DIALOG(dialog), "Ok", 0);
|
||||||
|
|
||||||
gtk_widget_show_all (dialog);
|
gtk_widget_show_all(dialog);
|
||||||
|
|
||||||
gtk_dialog_run (GTK_DIALOG (dialog));
|
gtk_dialog_run(GTK_DIALOG(dialog));
|
||||||
gtk_widget_destroy (dialog);
|
gtk_widget_destroy(dialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __forceinline PluginNullAbout(const char *aboutText)
|
static void __forceinline PluginNullAbout(const char *aboutText)
|
||||||
|
@ -265,7 +273,8 @@ static void SysMessage(const char *fmt, ...)
|
||||||
vsprintf(msg, fmt, list);
|
vsprintf(msg, fmt, list);
|
||||||
va_end(list);
|
va_end(list);
|
||||||
|
|
||||||
if (msg[strlen(msg)-1] == '\n') msg[strlen(msg)-1] = 0;
|
if (msg[strlen(msg) - 1] == '\n')
|
||||||
|
msg[strlen(msg) - 1] = 0;
|
||||||
|
|
||||||
// TODO OSX can we use WX MessageBox here or should Cocoa MessageBox used?
|
// TODO OSX can we use WX MessageBox here or should Cocoa MessageBox used?
|
||||||
}
|
}
|
||||||
|
@ -297,7 +306,7 @@ static void __forceinline PluginNullAbout(const char *aboutText)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define usleep(x) Sleep(x / 1000)
|
#define usleep(x) Sleep(x / 1000)
|
||||||
|
|
||||||
#ifndef UNICODE
|
#ifndef UNICODE
|
||||||
|
|
||||||
|
@ -305,15 +314,15 @@ static void __forceinline SysMessage(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list list;
|
va_list list;
|
||||||
char tmp[512];
|
char tmp[512];
|
||||||
va_start(list,fmt);
|
va_start(list, fmt);
|
||||||
vsprintf(tmp,fmt,list);
|
vsprintf(tmp, fmt, list);
|
||||||
va_end(list);
|
va_end(list);
|
||||||
MessageBox( GetActiveWindow(), tmp, "Message", MB_SETFOREGROUND | MB_OK );
|
MessageBox(GetActiveWindow(), tmp, "Message", MB_SETFOREGROUND | MB_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __forceinline PluginNullConfigure(std::string desc, s32 &log)
|
static void __forceinline PluginNullConfigure(std::string desc, s32 &log)
|
||||||
{
|
{
|
||||||
/* To do: Write a dialog box that displays a dialog box with the text in desc,
|
/* To do: Write a dialog box that displays a dialog box with the text in desc,
|
||||||
and a check box that says "Logging", checked if log !=0, and set log to
|
and a check box that says "Logging", checked if log !=0, and set log to
|
||||||
1 if it is checked on return, and 0 if it isn't. */
|
1 if it is checked on return, and 0 if it isn't. */
|
||||||
SysMessage("This space is intentionally left blank.");
|
SysMessage("This space is intentionally left blank.");
|
||||||
|
@ -327,39 +336,39 @@ static void __forceinline PluginNullAbout(const char *aboutText)
|
||||||
|
|
||||||
static void __forceinline SysMessage(const wchar_t *fmt, ...)
|
static void __forceinline SysMessage(const wchar_t *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list list;
|
va_list list;
|
||||||
wchar_t tmp[512];
|
wchar_t tmp[512];
|
||||||
va_start(list, fmt);
|
va_start(list, fmt);
|
||||||
vswprintf(tmp, 512, fmt, list);
|
vswprintf(tmp, 512, fmt, list);
|
||||||
va_end(list);
|
va_end(list);
|
||||||
MessageBox(GetActiveWindow(), tmp, L"Message", MB_SETFOREGROUND | MB_OK);
|
MessageBox(GetActiveWindow(), tmp, L"Message", MB_SETFOREGROUND | MB_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __forceinline PluginNullConfigure(std::string desc, s32 &log)
|
static void __forceinline PluginNullConfigure(std::string desc, s32 &log)
|
||||||
{
|
{
|
||||||
/* To do: Write a dialog box that displays a dialog box with the text in desc,
|
/* To do: Write a dialog box that displays a dialog box with the text in desc,
|
||||||
and a check box that says "Logging", checked if log !=0, and set log to
|
and a check box that says "Logging", checked if log !=0, and set log to
|
||||||
1 if it is checked on return, and 0 if it isn't. */
|
1 if it is checked on return, and 0 if it isn't. */
|
||||||
SysMessage(L"This space is intentionally left blank.");
|
SysMessage(L"This space is intentionally left blank.");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __forceinline PluginNullAbout(const wchar_t *aboutText)
|
static void __forceinline PluginNullAbout(const wchar_t *aboutText)
|
||||||
{
|
{
|
||||||
SysMessage(aboutText);
|
SysMessage(aboutText);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ENTRY_POINT \
|
#define ENTRY_POINT \
|
||||||
HINSTANCE hInst; \
|
HINSTANCE hInst; \
|
||||||
\
|
\
|
||||||
BOOL APIENTRY DllMain(HANDLE hModule, /* DLL INIT*/ \
|
BOOL APIENTRY DllMain(HANDLE hModule, /* DLL INIT*/ \
|
||||||
DWORD dwReason, \
|
DWORD dwReason, \
|
||||||
LPVOID lpReserved) \
|
LPVOID lpReserved) \
|
||||||
{ \
|
{ \
|
||||||
hInst = (HINSTANCE)hModule; \
|
hInst = (HINSTANCE)hModule; \
|
||||||
return TRUE; /* very quick :)*/ \
|
return TRUE; /* very quick :)*/ \
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#endif // PS2EEXT_H_INCLUDED
|
#endif // PS2EEXT_H_INCLUDED
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
* If not, see <http://www.gnu.org/licenses/>.
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// This file is just for backwards compatibility.
|
// This file is just for backwards compatibility.
|
||||||
|
|
||||||
#ifndef __PS2ETYPES_H__
|
#ifndef __PS2ETYPES_H__
|
||||||
#define __PS2ETYPES_H__
|
#define __PS2ETYPES_H__
|
||||||
|
|
|
@ -35,64 +35,71 @@
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#define EXPORT_C(type) extern "C" type CALLBACK
|
#define EXPORT_C(type) extern "C" type CALLBACK
|
||||||
#else
|
#else
|
||||||
#define EXPORT_C(type) extern "C" __attribute__((externally_visible,visibility("default"))) type
|
#define EXPORT_C(type) extern "C" __attribute__((externally_visible, visibility("default"))) type
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
EXPORT_C(u32) PS2EgetLibType(void);
|
EXPORT_C(u32)
|
||||||
EXPORT_C(u32) PS2EgetLibVersion2(u32 type);
|
PS2EgetLibType(void);
|
||||||
EXPORT_C(char*) PS2EgetLibName(void);
|
EXPORT_C(u32)
|
||||||
|
PS2EgetLibVersion2(u32 type);
|
||||||
|
EXPORT_C(char *)
|
||||||
|
PS2EgetLibName(void);
|
||||||
|
|
||||||
// Extended functions.
|
// Extended functions.
|
||||||
|
|
||||||
// allows the plugin to see the whole configuration when started up.
|
// allows the plugin to see the whole configuration when started up.
|
||||||
// Intended for them to get the ini and plugin paths, but could allow for other things as well.
|
// Intended for them to get the ini and plugin paths, but could allow for other things as well.
|
||||||
EXPORT_C_(void) PS2EpassConfig(PcsxConfig Config);
|
EXPORT_C_(void)
|
||||||
|
PS2EpassConfig(PcsxConfig Config);
|
||||||
|
|
||||||
// Alternately, this function serves the same purpose, but would work for emulators outside
|
// Alternately, this function serves the same purpose, but would work for emulators outside
|
||||||
// of pcsx2.
|
// of pcsx2.
|
||||||
EXPORT_C_(void) PS2EpassIniPath(const char *path);
|
EXPORT_C_(void)
|
||||||
|
PS2EpassIniPath(const char *path);
|
||||||
|
|
||||||
// PS2EgetLibType returns (may be OR'd)
|
// PS2EgetLibType returns (may be OR'd)
|
||||||
enum {
|
enum {
|
||||||
PS2E_LT_GS = 0x01,
|
PS2E_LT_GS = 0x01,
|
||||||
PS2E_LT_PAD = 0x02, // -=[ OBSOLETE ]=-
|
PS2E_LT_PAD = 0x02, // -=[ OBSOLETE ]=-
|
||||||
PS2E_LT_SPU2 = 0x04,
|
PS2E_LT_SPU2 = 0x04,
|
||||||
PS2E_LT_CDVD = 0x08,
|
PS2E_LT_CDVD = 0x08,
|
||||||
PS2E_LT_DEV9 = 0x10,
|
PS2E_LT_DEV9 = 0x10,
|
||||||
PS2E_LT_USB = 0x20,
|
PS2E_LT_USB = 0x20,
|
||||||
PS2E_LT_FW = 0x40,
|
PS2E_LT_FW = 0x40,
|
||||||
PS2E_LT_SIO = 0x80
|
PS2E_LT_SIO = 0x80
|
||||||
} PluginLibType;
|
} PluginLibType;
|
||||||
|
|
||||||
// PS2EgetLibVersion2 (high 16 bits)
|
// PS2EgetLibVersion2 (high 16 bits)
|
||||||
enum {
|
enum {
|
||||||
PS2E_GS_VERSION = 0x0006,
|
PS2E_GS_VERSION = 0x0006,
|
||||||
PS2E_PAD_VERSION = 0x0002, // -=[ OBSOLETE ]=-
|
PS2E_PAD_VERSION = 0x0002, // -=[ OBSOLETE ]=-
|
||||||
PS2E_SPU2_VERSION = 0x0005,
|
PS2E_SPU2_VERSION = 0x0005,
|
||||||
PS2E_CDVD_VERSION = 0x0005,
|
PS2E_CDVD_VERSION = 0x0005,
|
||||||
PS2E_DEV9_VERSION = 0x0003,
|
PS2E_DEV9_VERSION = 0x0003,
|
||||||
PS2E_USB_VERSION = 0x0003,
|
PS2E_USB_VERSION = 0x0003,
|
||||||
PS2E_FW_VERSION = 0x0002,
|
PS2E_FW_VERSION = 0x0002,
|
||||||
PS2E_SIO_VERSION = 0x0001
|
PS2E_SIO_VERSION = 0x0001
|
||||||
} PluginLibVersion;
|
} PluginLibVersion;
|
||||||
|
|
||||||
// freeze modes:
|
// freeze modes:
|
||||||
enum {
|
enum {
|
||||||
FREEZE_LOAD = 0,
|
FREEZE_LOAD = 0,
|
||||||
FREEZE_SAVE = 1,
|
FREEZE_SAVE = 1,
|
||||||
FREEZE_SIZE = 2
|
FREEZE_SIZE = 2
|
||||||
} FreezeModes;
|
} FreezeModes;
|
||||||
|
|
||||||
typedef struct _GSdriverInfo {
|
typedef struct _GSdriverInfo
|
||||||
char name[8];
|
{
|
||||||
void *common;
|
char name[8];
|
||||||
|
void *common;
|
||||||
} GSdriverInfo;
|
} GSdriverInfo;
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
typedef struct _winInfo { // unsupported values must be set to zero
|
typedef struct _winInfo
|
||||||
HWND hWnd;
|
{ // unsupported values must be set to zero
|
||||||
HMENU hMenu;
|
HWND hWnd;
|
||||||
HWND hStatusWnd;
|
HMENU hMenu;
|
||||||
|
HWND hStatusWnd;
|
||||||
} winInfo;
|
} winInfo;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -26,9 +26,9 @@
|
||||||
// make sure __POSIX__ is defined for all systems where we assume POSIX
|
// make sure __POSIX__ is defined for all systems where we assume POSIX
|
||||||
// compliance
|
// compliance
|
||||||
#if defined(__linux__) || defined(__APPLE__) || defined(__unix__) || defined(__CYGWIN__) || defined(__LINUX__)
|
#if defined(__linux__) || defined(__APPLE__) || defined(__unix__) || defined(__CYGWIN__) || defined(__LINUX__)
|
||||||
# if !defined(__POSIX__)
|
#if !defined(__POSIX__)
|
||||||
# define __POSIX__ 1
|
#define __POSIX__ 1
|
||||||
# endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "Pcsx2Types.h"
|
#include "Pcsx2Types.h"
|
||||||
|
@ -39,7 +39,7 @@
|
||||||
// Notes: I'd have used ARRAY_SIZE instead but ran into cross-platform lib conflicts with
|
// Notes: I'd have used ARRAY_SIZE instead but ran into cross-platform lib conflicts with
|
||||||
// that as well. >_<
|
// that as well. >_<
|
||||||
#ifndef ArraySize
|
#ifndef ArraySize
|
||||||
# define ArraySize(x) (sizeof(x)/sizeof((x)[0]))
|
#define ArraySize(x) (sizeof(x) / sizeof((x)[0]))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -51,51 +51,51 @@
|
||||||
// some tight loops it will likely make debug builds unusably slow.
|
// some tight loops it will likely make debug builds unusably slow.
|
||||||
//
|
//
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
# ifdef PCSX2_DEVBUILD
|
#ifdef PCSX2_DEVBUILD
|
||||||
static const bool IsDevBuild = true;
|
static const bool IsDevBuild = true;
|
||||||
# else
|
|
||||||
static const bool IsDevBuild = false;
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# ifdef PCSX2_DEBUG
|
|
||||||
static const bool IsDebugBuild = true;
|
|
||||||
# else
|
|
||||||
static const bool IsDebugBuild = false;
|
|
||||||
# endif
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
static const bool IsDevBuild = false;
|
||||||
# ifdef PCSX2_DEVBUILD
|
|
||||||
static const u8 IsDevBuild = 1;
|
|
||||||
# else
|
|
||||||
static const u8 IsDevBuild = 0;
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# ifdef PCSX2_DEBUG
|
|
||||||
static const u8 IsDebugBuild = 1;
|
|
||||||
# else
|
|
||||||
static const u8 IsDebugBuild = 0;
|
|
||||||
# endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef PCSX2_DEBUG
|
#ifdef PCSX2_DEBUG
|
||||||
# define pxDebugCode(code) code
|
static const bool IsDebugBuild = true;
|
||||||
#else
|
#else
|
||||||
# define pxDebugCode(code)
|
static const bool IsDebugBuild = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#ifdef PCSX2_DEVBUILD
|
||||||
|
static const u8 IsDevBuild = 1;
|
||||||
|
#else
|
||||||
|
static const u8 IsDevBuild = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef PCSX2_DEBUG
|
||||||
|
static const u8 IsDebugBuild = 1;
|
||||||
|
#else
|
||||||
|
static const u8 IsDebugBuild = 0;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef PCSX2_DEBUG
|
||||||
|
#define pxDebugCode(code) code
|
||||||
|
#else
|
||||||
|
#define pxDebugCode(code)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef PCSX2_DEVBUILD
|
#ifdef PCSX2_DEVBUILD
|
||||||
# define pxDevelCode(code) code
|
#define pxDevelCode(code) code
|
||||||
#else
|
#else
|
||||||
# define pxDevelCode(code)
|
#define pxDevelCode(code)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(PCSX2_DEBUG) || defined(PCSX2_DEVBUILD)
|
#if defined(PCSX2_DEBUG) || defined(PCSX2_DEVBUILD)
|
||||||
# define pxReleaseCode(code)
|
#define pxReleaseCode(code)
|
||||||
# define pxNonReleaseCode(code) code
|
#define pxNonReleaseCode(code) code
|
||||||
#else
|
#else
|
||||||
# define pxReleaseCode(code) code
|
#define pxReleaseCode(code) code
|
||||||
# define pxNonReleaseCode(code)
|
#define pxNonReleaseCode(code)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -116,8 +116,8 @@
|
||||||
|
|
||||||
// Defines the memory page size for the target platform at compilation. All supported platforms
|
// Defines the memory page size for the target platform at compilation. All supported platforms
|
||||||
// (which means Intel only right now) have a 4k granularity.
|
// (which means Intel only right now) have a 4k granularity.
|
||||||
#define PCSX2_PAGESIZE 0x1000
|
#define PCSX2_PAGESIZE 0x1000
|
||||||
static const int __pagesize = PCSX2_PAGESIZE;
|
static const int __pagesize = PCSX2_PAGESIZE;
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// Structure Packing (__packed)
|
// Structure Packing (__packed)
|
||||||
|
@ -154,27 +154,27 @@ static const int __pagesize = PCSX2_PAGESIZE;
|
||||||
|
|
||||||
// This is the 2005/earlier compatible packing define, which must be used in conjunction
|
// This is the 2005/earlier compatible packing define, which must be used in conjunction
|
||||||
// with #ifdef _MSC_VER/#pragma pack() directives (ugly).
|
// with #ifdef _MSC_VER/#pragma pack() directives (ugly).
|
||||||
# define __packed
|
#define __packed
|
||||||
|
|
||||||
# define __aligned(alig) __declspec(align(alig))
|
#define __aligned(alig) __declspec(align(alig))
|
||||||
# define __aligned16 __declspec(align(16))
|
#define __aligned16 __declspec(align(16))
|
||||||
# define __aligned32 __declspec(align(32))
|
#define __aligned32 __declspec(align(32))
|
||||||
# define __pagealigned __declspec(align(PCSX2_PAGESIZE))
|
#define __pagealigned __declspec(align(PCSX2_PAGESIZE))
|
||||||
|
|
||||||
// Deprecated; use __align instead.
|
// Deprecated; use __align instead.
|
||||||
# define PCSX2_ALIGNED(alig,x) __declspec(align(alig)) x
|
#define PCSX2_ALIGNED(alig, x) __declspec(align(alig)) x
|
||||||
# define PCSX2_ALIGNED_EXTERN(alig,x) extern __declspec(align(alig)) x
|
#define PCSX2_ALIGNED_EXTERN(alig, x) extern __declspec(align(alig)) x
|
||||||
# define PCSX2_ALIGNED16(x) __declspec(align(16)) x
|
#define PCSX2_ALIGNED16(x) __declspec(align(16)) x
|
||||||
# define PCSX2_ALIGNED16_EXTERN(x) extern __declspec(align(16)) x
|
#define PCSX2_ALIGNED16_EXTERN(x) extern __declspec(align(16)) x
|
||||||
|
|
||||||
# define __noinline __declspec(noinline)
|
#define __noinline __declspec(noinline)
|
||||||
# define __threadlocal __declspec(thread)
|
#define __threadlocal __declspec(thread)
|
||||||
|
|
||||||
// Don't know if there are Visual C++ equivalents of these.
|
// Don't know if there are Visual C++ equivalents of these.
|
||||||
# define likely(x) (!!(x))
|
#define likely(x) (!!(x))
|
||||||
# define unlikely(x) (!!(x))
|
#define unlikely(x) (!!(x))
|
||||||
|
|
||||||
# define CALLBACK __stdcall
|
#define CALLBACK __stdcall
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
@ -183,42 +183,42 @@ static const int __pagesize = PCSX2_PAGESIZE;
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
#ifndef __packed
|
#ifndef __packed
|
||||||
# define __packed __attribute__((packed))
|
#define __packed __attribute__((packed))
|
||||||
#endif
|
#endif
|
||||||
#ifndef __aligned
|
#ifndef __aligned
|
||||||
# define __aligned(alig) __attribute__((aligned(alig)))
|
#define __aligned(alig) __attribute__((aligned(alig)))
|
||||||
#endif
|
#endif
|
||||||
# define __aligned16 __attribute__((aligned(16)))
|
#define __aligned16 __attribute__((aligned(16)))
|
||||||
# define __aligned32 __attribute__((aligned(32)))
|
#define __aligned32 __attribute__((aligned(32)))
|
||||||
# define __pagealigned __attribute__((aligned(PCSX2_PAGESIZE)))
|
#define __pagealigned __attribute__((aligned(PCSX2_PAGESIZE)))
|
||||||
// Deprecated; use __align instead.
|
// Deprecated; use __align instead.
|
||||||
# define PCSX2_ALIGNED(alig,x) x __attribute((aligned(alig)))
|
#define PCSX2_ALIGNED(alig, x) x __attribute((aligned(alig)))
|
||||||
# define PCSX2_ALIGNED16(x) x __attribute((aligned(16)))
|
#define PCSX2_ALIGNED16(x) x __attribute((aligned(16)))
|
||||||
# define PCSX2_ALIGNED_EXTERN(alig,x) extern x __attribute((aligned(alig)))
|
#define PCSX2_ALIGNED_EXTERN(alig, x) extern x __attribute((aligned(alig)))
|
||||||
# define PCSX2_ALIGNED16_EXTERN(x) extern x __attribute((aligned(16)))
|
#define PCSX2_ALIGNED16_EXTERN(x) extern x __attribute((aligned(16)))
|
||||||
|
|
||||||
# define __assume(cond) ((void)0) // GCC has no equivalent for __assume
|
#define __assume(cond) ((void)0) // GCC has no equivalent for __assume
|
||||||
# define CALLBACK __attribute__((stdcall))
|
#define CALLBACK __attribute__((stdcall))
|
||||||
|
|
||||||
// Inlining note: GCC needs ((unused)) attributes defined on inlined functions to suppress
|
// Inlining note: GCC needs ((unused)) attributes defined on inlined functions to suppress
|
||||||
// warnings when a static inlined function isn't used in the scope of a single file (which
|
// warnings when a static inlined function isn't used in the scope of a single file (which
|
||||||
// happens *by design* like all the friggen time >_<)
|
// happens *by design* like all the friggen time >_<)
|
||||||
|
|
||||||
#ifndef __fastcall
|
#ifndef __fastcall
|
||||||
# define __fastcall __attribute__((fastcall))
|
#define __fastcall __attribute__((fastcall))
|
||||||
|
#endif
|
||||||
|
#define _inline __inline__ __attribute__((unused))
|
||||||
|
#ifdef NDEBUG
|
||||||
|
#define __forceinline __attribute__((always_inline, unused))
|
||||||
|
#else
|
||||||
|
#define __forceinline __attribute__((unused))
|
||||||
#endif
|
#endif
|
||||||
# define _inline __inline__ __attribute__((unused))
|
|
||||||
# ifdef NDEBUG
|
|
||||||
# define __forceinline __attribute__((always_inline,unused))
|
|
||||||
# else
|
|
||||||
# define __forceinline __attribute__((unused))
|
|
||||||
# endif
|
|
||||||
#ifndef __noinline
|
#ifndef __noinline
|
||||||
# define __noinline __attribute__((noinline))
|
#define __noinline __attribute__((noinline))
|
||||||
#endif
|
#endif
|
||||||
# define __threadlocal __thread
|
#define __threadlocal __thread
|
||||||
# define likely(x) __builtin_expect(!!(x), 1)
|
#define likely(x) __builtin_expect(!!(x), 1)
|
||||||
# define unlikely(x) __builtin_expect(!!(x), 0)
|
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -233,13 +233,13 @@ static const int __pagesize = PCSX2_PAGESIZE;
|
||||||
// environment.
|
// environment.
|
||||||
//
|
//
|
||||||
#ifdef PCSX2_DEVBUILD
|
#ifdef PCSX2_DEVBUILD
|
||||||
# define __releaseinline
|
#define __releaseinline
|
||||||
#else
|
#else
|
||||||
# define __releaseinline __forceinline
|
#define __releaseinline __forceinline
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define __ri __releaseinline
|
#define __ri __releaseinline
|
||||||
#define __fi __forceinline
|
#define __fi __forceinline
|
||||||
#define __fc __fastcall
|
#define __fc __fastcall
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -24,9 +24,9 @@
|
||||||
// depend on these types will not be usable (they will yield linker errors).
|
// depend on these types will not be usable (they will yield linker errors).
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
class wxString;
|
class wxString;
|
||||||
class FastFormatAscii;
|
class FastFormatAscii;
|
||||||
class FastFormatUnicode;
|
class FastFormatUnicode;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -65,116 +65,116 @@ typedef unsigned int uint;
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
union u128
|
union u128
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
u64 lo;
|
u64 lo;
|
||||||
u64 hi;
|
u64 hi;
|
||||||
};
|
};
|
||||||
|
|
||||||
u64 _u64[2];
|
u64 _u64[2];
|
||||||
u32 _u32[4];
|
u32 _u32[4];
|
||||||
u16 _u16[8];
|
u16 _u16[8];
|
||||||
u8 _u8[16];
|
u8 _u8[16];
|
||||||
|
|
||||||
// Explicit conversion from u64. Zero-extends the source through 128 bits.
|
// Explicit conversion from u64. Zero-extends the source through 128 bits.
|
||||||
static u128 From64( u64 src )
|
static u128 From64(u64 src)
|
||||||
{
|
{
|
||||||
u128 retval;
|
u128 retval;
|
||||||
retval.lo = src;
|
retval.lo = src;
|
||||||
retval.hi = 0;
|
retval.hi = 0;
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Explicit conversion from u32. Zero-extends the source through 128 bits.
|
// Explicit conversion from u32. Zero-extends the source through 128 bits.
|
||||||
static u128 From32( u32 src )
|
static u128 From32(u32 src)
|
||||||
{
|
{
|
||||||
u128 retval;
|
u128 retval;
|
||||||
retval._u32[0] = src;
|
retval._u32[0] = src;
|
||||||
retval._u32[1] = 0;
|
retval._u32[1] = 0;
|
||||||
retval.hi = 0;
|
retval.hi = 0;
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator u32() const { return _u32[0]; }
|
operator u32() const { return _u32[0]; }
|
||||||
operator u16() const { return _u16[0]; }
|
operator u16() const { return _u16[0]; }
|
||||||
operator u8() const { return _u8[0]; }
|
operator u8() const { return _u8[0]; }
|
||||||
|
|
||||||
bool operator==( const u128& right ) const
|
|
||||||
{
|
|
||||||
return (lo == right.lo) && (hi == right.hi);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!=( const u128& right ) const
|
bool operator==(const u128 &right) const
|
||||||
{
|
{
|
||||||
return (lo != right.lo) || (hi != right.hi);
|
return (lo == right.lo) && (hi == right.hi);
|
||||||
}
|
}
|
||||||
|
|
||||||
// In order for the following ToString() and WriteTo methods to be available, you must
|
bool operator!=(const u128 &right) const
|
||||||
// be linking to both wxWidgets and the pxWidgets extension library. If you are not
|
{
|
||||||
// using them, then you will need to provide your own implementations of these methods.
|
return (lo != right.lo) || (hi != right.hi);
|
||||||
wxString ToString() const;
|
}
|
||||||
wxString ToString64() const;
|
|
||||||
wxString ToString8() const;
|
// In order for the following ToString() and WriteTo methods to be available, you must
|
||||||
|
// be linking to both wxWidgets and the pxWidgets extension library. If you are not
|
||||||
void WriteTo( FastFormatAscii& dest ) const;
|
// using them, then you will need to provide your own implementations of these methods.
|
||||||
void WriteTo8( FastFormatAscii& dest ) const;
|
wxString ToString() const;
|
||||||
void WriteTo64( FastFormatAscii& dest ) const;
|
wxString ToString64() const;
|
||||||
|
wxString ToString8() const;
|
||||||
|
|
||||||
|
void WriteTo(FastFormatAscii &dest) const;
|
||||||
|
void WriteTo8(FastFormatAscii &dest) const;
|
||||||
|
void WriteTo64(FastFormatAscii &dest) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct s128
|
struct s128
|
||||||
{
|
{
|
||||||
s64 lo;
|
s64 lo;
|
||||||
s64 hi;
|
s64 hi;
|
||||||
|
|
||||||
// explicit conversion from s64, with sign extension.
|
// explicit conversion from s64, with sign extension.
|
||||||
static s128 From64( s64 src )
|
static s128 From64(s64 src)
|
||||||
{
|
{
|
||||||
s128 retval = { src, (src < 0) ? -1 : 0 };
|
s128 retval = {src, (src < 0) ? -1 : 0};
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
// explicit conversion from s32, with sign extension.
|
// explicit conversion from s32, with sign extension.
|
||||||
static s128 From64( s32 src )
|
static s128 From64(s32 src)
|
||||||
{
|
{
|
||||||
s128 retval = { src, (src < 0) ? -1 : 0 };
|
s128 retval = {src, (src < 0) ? -1 : 0};
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator u32() const { return (s32)lo; }
|
operator u32() const { return (s32)lo; }
|
||||||
operator u16() const { return (s16)lo; }
|
operator u16() const { return (s16)lo; }
|
||||||
operator u8() const { return (s8)lo; }
|
operator u8() const { return (s8)lo; }
|
||||||
|
|
||||||
bool operator==( const s128& right ) const
|
bool operator==(const s128 &right) const
|
||||||
{
|
{
|
||||||
return (lo == right.lo) && (hi == right.hi);
|
return (lo == right.lo) && (hi == right.hi);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=( const s128& right ) const
|
bool operator!=(const s128 &right) const
|
||||||
{
|
{
|
||||||
return (lo != right.lo) || (hi != right.hi);
|
return (lo != right.lo) || (hi != right.hi);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
typedef union _u128_t
|
typedef union _u128_t
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
u64 lo;
|
u64 lo;
|
||||||
u64 hi;
|
u64 hi;
|
||||||
};
|
};
|
||||||
|
|
||||||
u64 _u64[2];
|
u64 _u64[2];
|
||||||
u32 _u32[4];
|
u32 _u32[4];
|
||||||
u16 _u16[8];
|
u16 _u16[8];
|
||||||
u8 _u8[16];
|
u8 _u8[16];
|
||||||
} u128;
|
} u128;
|
||||||
|
|
||||||
typedef union _s128_t
|
typedef union _s128_t
|
||||||
{
|
{
|
||||||
u64 lo;
|
u64 lo;
|
||||||
s64 hi;
|
s64 hi;
|
||||||
} s128;
|
} s128;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -27,14 +27,13 @@
|
||||||
//
|
//
|
||||||
class Pcsx2AppTraits : public wxGUIAppTraits
|
class Pcsx2AppTraits : public wxGUIAppTraits
|
||||||
{
|
{
|
||||||
typedef wxGUIAppTraits _parent;
|
typedef wxGUIAppTraits _parent;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~Pcsx2AppTraits() {}
|
virtual ~Pcsx2AppTraits() {}
|
||||||
wxMessageOutput* CreateMessageOutput();
|
wxMessageOutput *CreateMessageOutput();
|
||||||
|
|
||||||
#ifdef wxUSE_STDPATHS
|
#ifdef wxUSE_STDPATHS
|
||||||
wxStandardPaths& GetStandardPaths();
|
wxStandardPaths &GetStandardPaths();
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -17,14 +17,14 @@
|
||||||
|
|
||||||
#ifndef __pxFUNCTION__
|
#ifndef __pxFUNCTION__
|
||||||
#if defined(__GNUG__)
|
#if defined(__GNUG__)
|
||||||
# define __pxFUNCTION__ __PRETTY_FUNCTION__
|
#define __pxFUNCTION__ __PRETTY_FUNCTION__
|
||||||
#else
|
#else
|
||||||
# define __pxFUNCTION__ __FUNCTION__
|
#define __pxFUNCTION__ __FUNCTION__
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef wxNullChar
|
#ifndef wxNullChar
|
||||||
# define wxNullChar ((wxChar*)NULL)
|
#define wxNullChar ((wxChar *)NULL)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// FnChar_t - function name char type; typedef'd in case it ever changes between compilers
|
// FnChar_t - function name char type; typedef'd in case it ever changes between compilers
|
||||||
|
@ -36,29 +36,29 @@ typedef char FnChar_t;
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
struct DiagnosticOrigin
|
struct DiagnosticOrigin
|
||||||
{
|
{
|
||||||
const wxChar* srcfile;
|
const wxChar *srcfile;
|
||||||
const FnChar_t* function;
|
const FnChar_t *function;
|
||||||
const wxChar* condition;
|
const wxChar *condition;
|
||||||
int line;
|
int line;
|
||||||
|
|
||||||
DiagnosticOrigin( const wxChar *_file, int _line, const FnChar_t *_func, const wxChar* _cond = NULL )
|
DiagnosticOrigin(const wxChar *_file, int _line, const FnChar_t *_func, const wxChar *_cond = NULL)
|
||||||
: srcfile( _file )
|
: srcfile(_file)
|
||||||
, function( _func )
|
, function(_func)
|
||||||
, condition( _cond )
|
, condition(_cond)
|
||||||
, line( _line )
|
, line(_line)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString ToString( const wxChar* msg=NULL ) const;
|
wxString ToString(const wxChar *msg = NULL) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Returns ture if the assertion is to trap into the debugger, or false if execution
|
// Returns ture if the assertion is to trap into the debugger, or false if execution
|
||||||
// of the program should continue unimpeded.
|
// of the program should continue unimpeded.
|
||||||
typedef bool pxDoAssertFnType(const DiagnosticOrigin& origin, const wxChar *msg);
|
typedef bool pxDoAssertFnType(const DiagnosticOrigin &origin, const wxChar *msg);
|
||||||
|
|
||||||
extern pxDoAssertFnType pxAssertImpl_LogIt;
|
extern pxDoAssertFnType pxAssertImpl_LogIt;
|
||||||
|
|
||||||
extern pxDoAssertFnType* pxDoAssert;
|
extern pxDoAssertFnType *pxDoAssert;
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------------
|
||||||
// pxAssert / pxAssertDev
|
// pxAssert / pxAssertDev
|
||||||
|
@ -97,95 +97,99 @@ extern pxDoAssertFnType* pxDoAssert;
|
||||||
// it can lead to the compiler optimizing out code and leading to crashes in dev/release
|
// it can lead to the compiler optimizing out code and leading to crashes in dev/release
|
||||||
// builds. To have code optimized, explicitly use pxAssume(false) or pxAssumeDev(false,msg);
|
// builds. To have code optimized, explicitly use pxAssume(false) or pxAssumeDev(false,msg);
|
||||||
|
|
||||||
#define pxDiagSpot DiagnosticOrigin( __TFILE__, __LINE__, __pxFUNCTION__ )
|
#define pxDiagSpot DiagnosticOrigin(__TFILE__, __LINE__, __pxFUNCTION__)
|
||||||
#define pxAssertSpot(cond) DiagnosticOrigin( __TFILE__, __LINE__, __pxFUNCTION__, _T(#cond) )
|
#define pxAssertSpot(cond) DiagnosticOrigin(__TFILE__, __LINE__, __pxFUNCTION__, _T(#cond))
|
||||||
|
|
||||||
// pxAssertRel ->
|
// pxAssertRel ->
|
||||||
// Special release-mode assertion. Limited use since stack traces in release mode builds
|
// Special release-mode assertion. Limited use since stack traces in release mode builds
|
||||||
// (especially with LTCG) are highly suspect. But when troubleshooting crashes that only
|
// (especially with LTCG) are highly suspect. But when troubleshooting crashes that only
|
||||||
// rear ugly heads in optimized builds, this is one of the few tools we have.
|
// rear ugly heads in optimized builds, this is one of the few tools we have.
|
||||||
|
|
||||||
#define pxAssertRel(cond, msg) ( (likely(cond)) || (pxOnAssert(pxAssertSpot(cond), msg), false) )
|
#define pxAssertRel(cond, msg) ((likely(cond)) || (pxOnAssert(pxAssertSpot(cond), msg), false))
|
||||||
#define pxAssumeRel(cond, msg) ((void) ( (!likely(cond)) && (pxOnAssert(pxAssertSpot(cond), msg), false) ))
|
#define pxAssumeRel(cond, msg) ((void)((!likely(cond)) && (pxOnAssert(pxAssertSpot(cond), msg), false)))
|
||||||
#define pxFailRel(msg) pxAssertRel(false, msg)
|
#define pxFailRel(msg) pxAssertRel(false, msg)
|
||||||
|
|
||||||
#if defined(PCSX2_DEBUG)
|
#if defined(PCSX2_DEBUG)
|
||||||
|
|
||||||
# define pxAssertMsg(cond, msg) pxAssertRel(cond, msg)
|
#define pxAssertMsg(cond, msg) pxAssertRel(cond, msg)
|
||||||
# define pxAssertDev(cond, msg) pxAssertMsg(cond, msg)
|
#define pxAssertDev(cond, msg) pxAssertMsg(cond, msg)
|
||||||
|
|
||||||
# define pxAssumeMsg(cond, msg) pxAssumeRel(cond, msg)
|
#define pxAssumeMsg(cond, msg) pxAssumeRel(cond, msg)
|
||||||
# define pxAssumeDev(cond, msg) pxAssumeRel(cond, msg)
|
#define pxAssumeDev(cond, msg) pxAssumeRel(cond, msg)
|
||||||
|
|
||||||
# define pxFail(msg) pxAssertMsg(false, msg)
|
#define pxFail(msg) pxAssertMsg(false, msg)
|
||||||
# define pxFailDev(msg) pxAssertDev(false, msg)
|
#define pxFailDev(msg) pxAssertDev(false, msg)
|
||||||
|
|
||||||
#elif defined(PCSX2_DEVBUILD)
|
#elif defined(PCSX2_DEVBUILD)
|
||||||
|
|
||||||
// Devel builds now will give you a release-mode assertion dialog window if any of the
|
// Devel builds now will give you a release-mode assertion dialog window if any of the
|
||||||
// following macro's 'cond' field is false.
|
// following macro's 'cond' field is false.
|
||||||
// Note: Only use pxAssume/Msg/Dev if you know what you're doing, __assume is supposed
|
// Note: Only use pxAssume/Msg/Dev if you know what you're doing, __assume is supposed
|
||||||
// to be used as an optimization hint, yet many devs have been using psAssume
|
// to be used as an optimization hint, yet many devs have been using psAssume
|
||||||
// thinking its the same as an assertion.
|
// thinking its the same as an assertion.
|
||||||
// __assume(0) is also very dangerous because it is a special case of __assume() which
|
// __assume(0) is also very dangerous because it is a special case of __assume() which
|
||||||
// tells the compiler that the code path is not reachable, and it can cause unpredictable
|
// tells the compiler that the code path is not reachable, and it can cause unpredictable
|
||||||
// results if the code path can be reached.
|
// results if the code path can be reached.
|
||||||
// i.e. if (1) { __assume(0); something(); }
|
// i.e. if (1) { __assume(0); something(); }
|
||||||
// In the above example, something() may never be called.
|
// In the above example, something() may never be called.
|
||||||
// __assume(0)'s real use is in optimizing stuff such as "default:" cases on a switch
|
// __assume(0)'s real use is in optimizing stuff such as "default:" cases on a switch
|
||||||
// statement. See jNO_DEFAULT
|
// statement. See jNO_DEFAULT
|
||||||
|
|
||||||
# define pxAssertMsg(cond, msg) pxAssertRel(cond, msg)
|
#define pxAssertMsg(cond, msg) pxAssertRel(cond, msg)
|
||||||
# define pxAssertDev(cond, msg) pxAssertRel(cond, msg)
|
#define pxAssertDev(cond, msg) pxAssertRel(cond, msg)
|
||||||
|
|
||||||
# define pxAssumeMsg(cond, msg) pxAssumeRel(cond, msg) //(__assume(cond))
|
#define pxAssumeMsg(cond, msg) pxAssumeRel(cond, msg) //(__assume(cond))
|
||||||
# define pxAssumeDev(cond, msg) pxAssumeRel(cond, msg)
|
#define pxAssumeDev(cond, msg) pxAssumeRel(cond, msg)
|
||||||
|
|
||||||
# define pxFail(msg) pxAssertDev(false, msg)
|
#define pxFail(msg) pxAssertDev(false, msg)
|
||||||
# define pxFailDev(msg) pxAssertDev(false, msg)
|
#define pxFailDev(msg) pxAssertDev(false, msg)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
// Release Builds just use __assume as an optimization, and return the conditional
|
// Release Builds just use __assume as an optimization, and return the conditional
|
||||||
// as a result (which is optimized to nil if unused).
|
// as a result (which is optimized to nil if unused).
|
||||||
|
|
||||||
# define pxAssertMsg(cond, msg) (likely(cond))
|
#define pxAssertMsg(cond, msg) (likely(cond))
|
||||||
# define pxAssertDev(cond, msg) (likely(cond))
|
#define pxAssertDev(cond, msg) (likely(cond))
|
||||||
|
|
||||||
# define pxAssumeMsg(cond, msg) (__assume(cond))
|
#define pxAssumeMsg(cond, msg) (__assume(cond))
|
||||||
# define pxAssumeDev(cond, msg) (__assume(cond))
|
#define pxAssumeDev(cond, msg) (__assume(cond))
|
||||||
|
|
||||||
# define pxFail(msg) do{} while(0)
|
#define pxFail(msg) \
|
||||||
# define pxFailDev(msg) do{} while(0)
|
do { \
|
||||||
|
} while (0)
|
||||||
|
#define pxFailDev(msg) \
|
||||||
|
do { \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define pxAssert(cond) pxAssertMsg(cond, wxNullChar)
|
#define pxAssert(cond) pxAssertMsg(cond, wxNullChar)
|
||||||
#define pxAssume(cond) pxAssumeMsg(cond, wxNullChar)
|
#define pxAssume(cond) pxAssumeMsg(cond, wxNullChar)
|
||||||
|
|
||||||
#define pxAssertRelease( cond, msg )
|
#define pxAssertRelease(cond, msg)
|
||||||
|
|
||||||
// Performs an unsigned index bounds check, and generates a debug assertion if the check fails.
|
// Performs an unsigned index bounds check, and generates a debug assertion if the check fails.
|
||||||
// For stricter checking in Devel builds as well as debug builds (but possibly slower), use
|
// For stricter checking in Devel builds as well as debug builds (but possibly slower), use
|
||||||
// IndexBoundsCheckDev.
|
// IndexBoundsCheckDev.
|
||||||
|
|
||||||
#define IndexBoundsCheck( objname, idx, sze ) pxAssertMsg( (uint)(idx) < (uint)(sze), \
|
#define IndexBoundsCheck(objname, idx, sze) pxAssertMsg((uint)(idx) < (uint)(sze), \
|
||||||
pxsFmt( L"Array index out of bounds accessing object '%s' (index=%d, size=%d)", objname, (idx), (sze) ) )
|
pxsFmt(L"Array index out of bounds accessing object '%s' (index=%d, size=%d)", objname, (idx), (sze)))
|
||||||
|
|
||||||
#define IndexBoundsCheckDev( objname, idx, sze ) pxAssertDev( (uint)(idx) < (uint)(sze), \
|
#define IndexBoundsCheckDev(objname, idx, sze) pxAssertDev((uint)(idx) < (uint)(sze), \
|
||||||
pxsFmt( L"Array index out of bounds accessing object '%s' (index=%d, size=%d)", objname, (idx), (sze) ) )
|
pxsFmt(L"Array index out of bounds accessing object '%s' (index=%d, size=%d)", objname, (idx), (sze)))
|
||||||
|
|
||||||
#define IndexBoundsAssume( objname, idx, sze ) pxAssumeMsg( (uint)(idx) < (uint)(sze), \
|
#define IndexBoundsAssume(objname, idx, sze) pxAssumeMsg((uint)(idx) < (uint)(sze), \
|
||||||
pxsFmt( L"Array index out of bounds accessing object '%s' (index=%d, size=%d)", objname, (idx), (sze) ) )
|
pxsFmt(L"Array index out of bounds accessing object '%s' (index=%d, size=%d)", objname, (idx), (sze)))
|
||||||
|
|
||||||
#define IndexBoundsAssumeDev( objname, idx, sze ) pxAssumeDev( (uint)(idx) < (uint)(sze), \
|
#define IndexBoundsAssumeDev(objname, idx, sze) pxAssumeDev((uint)(idx) < (uint)(sze), \
|
||||||
pxsFmt( L"Array index out of bounds accessing object '%s' (index=%d, size=%d)", objname, (idx), (sze) ) )
|
pxsFmt(L"Array index out of bounds accessing object '%s' (index=%d, size=%d)", objname, (idx), (sze)))
|
||||||
|
|
||||||
|
|
||||||
extern void pxOnAssert( const DiagnosticOrigin& origin, const wxChar* msg=NULL );
|
extern void pxOnAssert(const DiagnosticOrigin &origin, const wxChar *msg = NULL);
|
||||||
extern void pxOnAssert( const DiagnosticOrigin& origin, const char* msg );
|
extern void pxOnAssert(const DiagnosticOrigin &origin, const char *msg);
|
||||||
extern void pxOnAssert( const DiagnosticOrigin& origin, const wxString& msg);
|
extern void pxOnAssert(const DiagnosticOrigin &origin, const wxString &msg);
|
||||||
extern void pxOnAssert( const DiagnosticOrigin& origin, const FastFormatUnicode& msg);
|
extern void pxOnAssert(const DiagnosticOrigin &origin, const FastFormatUnicode &msg);
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// jNO_DEFAULT -- disables the default case in a switch, which improves switch optimization
|
// jNO_DEFAULT -- disables the default case in a switch, which improves switch optimization
|
||||||
|
@ -198,10 +202,9 @@ extern void pxOnAssert( const DiagnosticOrigin& origin, const FastFormatUnicode&
|
||||||
// * In debug/devel builds the default case will cause an assertion.
|
// * In debug/devel builds the default case will cause an assertion.
|
||||||
//
|
//
|
||||||
#ifndef jNO_DEFAULT
|
#ifndef jNO_DEFAULT
|
||||||
# define jNO_DEFAULT \
|
#define jNO_DEFAULT \
|
||||||
default: \
|
default: { \
|
||||||
{ \
|
pxAssumeDev(0, "Incorrect usage of jNO_DEFAULT detected (default case is not unreachable!)"); \
|
||||||
pxAssumeDev( 0, "Incorrect usage of jNO_DEFAULT detected (default case is not unreachable!)" ); \
|
break; \
|
||||||
break; \
|
}
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -19,19 +19,19 @@
|
||||||
|
|
||||||
class CheckedStaticBox : public wxPanelWithHelpers
|
class CheckedStaticBox : public wxPanelWithHelpers
|
||||||
{
|
{
|
||||||
typedef wxPanelWithHelpers _parent;
|
typedef wxPanelWithHelpers _parent;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
wxBoxSizer& ThisSizer; // Boxsizer which holds all child items.
|
wxBoxSizer &ThisSizer; // Boxsizer which holds all child items.
|
||||||
wxCheckBox& ThisToggle; // toggle which can enable/disable all child controls
|
wxCheckBox &ThisToggle; // toggle which can enable/disable all child controls
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CheckedStaticBox( wxWindow* parent, int orientation, const wxString& title=wxEmptyString );
|
CheckedStaticBox(wxWindow *parent, int orientation, const wxString &title = wxEmptyString);
|
||||||
|
|
||||||
|
void SetValue(bool val);
|
||||||
|
bool GetValue() const;
|
||||||
|
bool Enable(bool enable = true);
|
||||||
|
|
||||||
void SetValue( bool val );
|
|
||||||
bool GetValue() const;
|
|
||||||
bool Enable( bool enable = true );
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void MainToggle_Click( wxCommandEvent& evt );
|
virtual void MainToggle_Click(wxCommandEvent &evt);
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,46 +17,45 @@
|
||||||
|
|
||||||
#include "StringHelpers.h"
|
#include "StringHelpers.h"
|
||||||
|
|
||||||
enum ConsoleColors
|
enum ConsoleColors {
|
||||||
{
|
Color_Current = -1,
|
||||||
Color_Current = -1,
|
|
||||||
|
|
||||||
Color_Default = 0,
|
Color_Default = 0,
|
||||||
|
|
||||||
Color_Black,
|
Color_Black,
|
||||||
Color_Green,
|
Color_Green,
|
||||||
Color_Red,
|
Color_Red,
|
||||||
Color_Blue,
|
Color_Blue,
|
||||||
Color_Magenta,
|
Color_Magenta,
|
||||||
Color_Orange,
|
Color_Orange,
|
||||||
Color_Gray,
|
Color_Gray,
|
||||||
|
|
||||||
Color_Cyan, // faint visibility, intended for logging PS2/IOP output
|
Color_Cyan, // faint visibility, intended for logging PS2/IOP output
|
||||||
Color_Yellow, // faint visibility, intended for logging PS2/IOP output
|
Color_Yellow, // faint visibility, intended for logging PS2/IOP output
|
||||||
Color_White, // faint visibility, intended for logging PS2/IOP output
|
Color_White, // faint visibility, intended for logging PS2/IOP output
|
||||||
|
|
||||||
// Strong text *may* result in mis-aligned text in the console, depending on the
|
// Strong text *may* result in mis-aligned text in the console, depending on the
|
||||||
// font and the platform, so use these with caution.
|
// font and the platform, so use these with caution.
|
||||||
Color_StrongBlack,
|
Color_StrongBlack,
|
||||||
Color_StrongRed, // intended for errors
|
Color_StrongRed, // intended for errors
|
||||||
Color_StrongGreen, // intended for infrequent state information
|
Color_StrongGreen, // intended for infrequent state information
|
||||||
Color_StrongBlue, // intended for block headings
|
Color_StrongBlue, // intended for block headings
|
||||||
Color_StrongMagenta,
|
Color_StrongMagenta,
|
||||||
Color_StrongOrange, // intended for warnings
|
Color_StrongOrange, // intended for warnings
|
||||||
Color_StrongGray,
|
Color_StrongGray,
|
||||||
|
|
||||||
Color_StrongCyan,
|
Color_StrongCyan,
|
||||||
Color_StrongYellow,
|
Color_StrongYellow,
|
||||||
Color_StrongWhite,
|
Color_StrongWhite,
|
||||||
|
|
||||||
ConsoleColors_Count
|
ConsoleColors_Count
|
||||||
};
|
};
|
||||||
|
|
||||||
static const ConsoleColors DefaultConsoleColor = Color_Default;
|
static const ConsoleColors DefaultConsoleColor = Color_Default;
|
||||||
|
|
||||||
|
|
||||||
// Use fastcall for the console; should be helpful in most cases
|
// Use fastcall for the console; should be helpful in most cases
|
||||||
#define __concall __fastcall
|
#define __concall __fastcall
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------------
|
||||||
// IConsoleWriter -- For printing messages to the console.
|
// IConsoleWriter -- For printing messages to the console.
|
||||||
|
@ -71,60 +70,60 @@ static const ConsoleColors DefaultConsoleColor = Color_Default;
|
||||||
//
|
//
|
||||||
struct IConsoleWriter
|
struct IConsoleWriter
|
||||||
{
|
{
|
||||||
// A direct console write, without tabbing or newlines. Useful to devs who want to do quick
|
// A direct console write, without tabbing or newlines. Useful to devs who want to do quick
|
||||||
// logging of various junk; but should *not* be used in production code due.
|
// logging of various junk; but should *not* be used in production code due.
|
||||||
void (__concall *WriteRaw)( const wxString& fmt );
|
void(__concall *WriteRaw)(const wxString &fmt);
|
||||||
|
|
||||||
// WriteLn implementation for internal use only. Bypasses tabbing, prefixing, and other
|
// WriteLn implementation for internal use only. Bypasses tabbing, prefixing, and other
|
||||||
// formatting.
|
// formatting.
|
||||||
void (__concall *DoWriteLn)( const wxString& fmt );
|
void(__concall *DoWriteLn)(const wxString &fmt);
|
||||||
|
|
||||||
// SetColor implementation for internal use only.
|
// SetColor implementation for internal use only.
|
||||||
void (__concall *DoSetColor)( ConsoleColors color );
|
void(__concall *DoSetColor)(ConsoleColors color);
|
||||||
|
|
||||||
// Special implementation of DoWrite that's pretty much for MSVC use only.
|
// Special implementation of DoWrite that's pretty much for MSVC use only.
|
||||||
// All implementations should map to DoWrite, except Stdio which should map to Null.
|
// All implementations should map to DoWrite, except Stdio which should map to Null.
|
||||||
// (This avoids circular/recursive stdio output)
|
// (This avoids circular/recursive stdio output)
|
||||||
void (__concall *DoWriteFromStdout)( const wxString& fmt );
|
void(__concall *DoWriteFromStdout)(const wxString &fmt);
|
||||||
|
|
||||||
void (__concall *Newline)();
|
void(__concall *Newline)();
|
||||||
void (__concall *SetTitle)( const wxString& title );
|
void(__concall *SetTitle)(const wxString &title);
|
||||||
|
|
||||||
// internal value for indentation of individual lines. Use the Indent() member to invoke.
|
// internal value for indentation of individual lines. Use the Indent() member to invoke.
|
||||||
int _imm_indentation;
|
int _imm_indentation;
|
||||||
|
|
||||||
// For internal use only.
|
// For internal use only.
|
||||||
wxString _addIndentation( const wxString& src, int glob_indent ) const;
|
wxString _addIndentation(const wxString &src, int glob_indent) const;
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Public members; call these to print stuff to console!
|
// Public members; call these to print stuff to console!
|
||||||
//
|
//
|
||||||
// All functions always return false. Return value is provided only so that we can easily
|
// All functions always return false. Return value is provided only so that we can easily
|
||||||
// disable logs at compile time using the "0&&action" macro trick.
|
// disable logs at compile time using the "0&&action" macro trick.
|
||||||
|
|
||||||
ConsoleColors GetColor() const;
|
ConsoleColors GetColor() const;
|
||||||
const IConsoleWriter& SetColor( ConsoleColors color ) const;
|
const IConsoleWriter &SetColor(ConsoleColors color) const;
|
||||||
const IConsoleWriter& ClearColor() const;
|
const IConsoleWriter &ClearColor() const;
|
||||||
const IConsoleWriter& SetIndent( int tabcount=1 ) const;
|
const IConsoleWriter &SetIndent(int tabcount = 1) const;
|
||||||
|
|
||||||
IConsoleWriter Indent( int tabcount=1 ) const;
|
IConsoleWriter Indent(int tabcount = 1) const;
|
||||||
|
|
||||||
bool FormatV( const char* fmt, va_list args ) const;
|
bool FormatV(const char *fmt, va_list args) const;
|
||||||
bool WriteLn( ConsoleColors color, const char* fmt, ... ) const;
|
bool WriteLn(ConsoleColors color, const char *fmt, ...) const;
|
||||||
bool WriteLn( const char* fmt, ... ) const;
|
bool WriteLn(const char *fmt, ...) const;
|
||||||
bool Error( const char* fmt, ... ) const;
|
bool Error(const char *fmt, ...) const;
|
||||||
bool Warning( const char* fmt, ... ) const;
|
bool Warning(const char *fmt, ...) const;
|
||||||
|
|
||||||
bool FormatV( const wxChar* fmt, va_list args ) const;
|
bool FormatV(const wxChar *fmt, va_list args) const;
|
||||||
bool WriteLn( ConsoleColors color, const wxChar* fmt, ... ) const;
|
bool WriteLn(ConsoleColors color, const wxChar *fmt, ...) const;
|
||||||
bool WriteLn( const wxChar* fmt, ... ) const;
|
bool WriteLn(const wxChar *fmt, ...) const;
|
||||||
bool Error( const wxChar* fmt, ... ) const;
|
bool Error(const wxChar *fmt, ...) const;
|
||||||
bool Warning( const wxChar* fmt, ... ) const;
|
bool Warning(const wxChar *fmt, ...) const;
|
||||||
|
|
||||||
bool WriteLn( ConsoleColors color, const wxString fmt, ... ) const;
|
bool WriteLn(ConsoleColors color, const wxString fmt, ...) const;
|
||||||
bool WriteLn( const wxString fmt, ... ) const;
|
bool WriteLn(const wxString fmt, ...) const;
|
||||||
bool Error( const wxString fmt, ... ) const;
|
bool Error(const wxString fmt, ...) const;
|
||||||
bool Warning( const wxString fmt, ... ) const;
|
bool Warning(const wxString fmt, ...) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -134,37 +133,37 @@ struct IConsoleWriter
|
||||||
//
|
//
|
||||||
struct NullConsoleWriter
|
struct NullConsoleWriter
|
||||||
{
|
{
|
||||||
void WriteRaw( const wxString& fmt ) {}
|
void WriteRaw(const wxString &fmt) {}
|
||||||
void DoWriteLn( const wxString& fmt ) {}
|
void DoWriteLn(const wxString &fmt) {}
|
||||||
void DoSetColor( ConsoleColors color ) {}
|
void DoSetColor(ConsoleColors color) {}
|
||||||
void DoWriteFromStdout( const wxString& fmt ) {}
|
void DoWriteFromStdout(const wxString &fmt) {}
|
||||||
void Newline() {}
|
void Newline() {}
|
||||||
void SetTitle( const wxString& title ) {}
|
void SetTitle(const wxString &title) {}
|
||||||
|
|
||||||
|
|
||||||
ConsoleColors GetColor() const { return Color_Current; }
|
ConsoleColors GetColor() const { return Color_Current; }
|
||||||
const NullConsoleWriter& SetColor( ConsoleColors color ) const { return *this; }
|
const NullConsoleWriter &SetColor(ConsoleColors color) const { return *this; }
|
||||||
const NullConsoleWriter& ClearColor() const { return *this; }
|
const NullConsoleWriter &ClearColor() const { return *this; }
|
||||||
const NullConsoleWriter& SetIndent( int tabcount=1 ) const { return *this; }
|
const NullConsoleWriter &SetIndent(int tabcount = 1) const { return *this; }
|
||||||
|
|
||||||
NullConsoleWriter Indent( int tabcount=1 ) const { return NullConsoleWriter(); }
|
NullConsoleWriter Indent(int tabcount = 1) const { return NullConsoleWriter(); }
|
||||||
|
|
||||||
bool FormatV( const char* fmt, va_list args ) const { return false; }
|
bool FormatV(const char *fmt, va_list args) const { return false; }
|
||||||
bool WriteLn( ConsoleColors color, const char* fmt, ... ) const { return false; }
|
bool WriteLn(ConsoleColors color, const char *fmt, ...) const { return false; }
|
||||||
bool WriteLn( const char* fmt, ... ) const { return false; }
|
bool WriteLn(const char *fmt, ...) const { return false; }
|
||||||
bool Error( const char* fmt, ... ) const { return false; }
|
bool Error(const char *fmt, ...) const { return false; }
|
||||||
bool Warning( const char* fmt, ... ) const { return false; }
|
bool Warning(const char *fmt, ...) const { return false; }
|
||||||
|
|
||||||
bool FormatV( const wxChar* fmt, va_list args ) const { return false; }
|
bool FormatV(const wxChar *fmt, va_list args) const { return false; }
|
||||||
bool WriteLn( ConsoleColors color, const wxChar* fmt, ... ) const { return false; }
|
bool WriteLn(ConsoleColors color, const wxChar *fmt, ...) const { return false; }
|
||||||
bool WriteLn( const wxChar* fmt, ... ) const { return false; }
|
bool WriteLn(const wxChar *fmt, ...) const { return false; }
|
||||||
bool Error( const wxChar* fmt, ... ) const { return false; }
|
bool Error(const wxChar *fmt, ...) const { return false; }
|
||||||
bool Warning( const wxChar* fmt, ... ) const { return false; }
|
bool Warning(const wxChar *fmt, ...) const { return false; }
|
||||||
|
|
||||||
bool WriteLn( ConsoleColors color, const wxString fmt, ... ) const { return false; }
|
bool WriteLn(ConsoleColors color, const wxString fmt, ...) const { return false; }
|
||||||
bool WriteLn( const wxString fmt, ... ) const { return false; }
|
bool WriteLn(const wxString fmt, ...) const { return false; }
|
||||||
bool Error( const wxString fmt, ... ) const { return false; }
|
bool Error(const wxString fmt, ...) const { return false; }
|
||||||
bool Warning( const wxString fmt, ... ) const { return false; }
|
bool Warning(const wxString fmt, ...) const { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -180,19 +179,19 @@ struct NullConsoleWriter
|
||||||
//
|
//
|
||||||
class ConsoleIndentScope
|
class ConsoleIndentScope
|
||||||
{
|
{
|
||||||
DeclareNoncopyableObject( ConsoleIndentScope );
|
DeclareNoncopyableObject(ConsoleIndentScope);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int m_amount;
|
int m_amount;
|
||||||
bool m_IsScoped;
|
bool m_IsScoped;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Constructor: The specified number of tabs will be appended to the current indentation
|
// Constructor: The specified number of tabs will be appended to the current indentation
|
||||||
// setting. The tabs will be unrolled when the object leaves scope or is destroyed.
|
// setting. The tabs will be unrolled when the object leaves scope or is destroyed.
|
||||||
ConsoleIndentScope( int tabs=1 );
|
ConsoleIndentScope(int tabs = 1);
|
||||||
virtual ~ConsoleIndentScope() throw();
|
virtual ~ConsoleIndentScope() throw();
|
||||||
void EnterScope();
|
void EnterScope();
|
||||||
void LeaveScope();
|
void LeaveScope();
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -200,18 +199,18 @@ public:
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
class ConsoleColorScope
|
class ConsoleColorScope
|
||||||
{
|
{
|
||||||
DeclareNoncopyableObject( ConsoleColorScope );
|
DeclareNoncopyableObject(ConsoleColorScope);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ConsoleColors m_newcolor;
|
ConsoleColors m_newcolor;
|
||||||
ConsoleColors m_old_color;
|
ConsoleColors m_old_color;
|
||||||
bool m_IsScoped;
|
bool m_IsScoped;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ConsoleColorScope( ConsoleColors newcolor );
|
ConsoleColorScope(ConsoleColors newcolor);
|
||||||
virtual ~ConsoleColorScope() throw();
|
virtual ~ConsoleColorScope() throw();
|
||||||
void EnterScope();
|
void EnterScope();
|
||||||
void LeaveScope();
|
void LeaveScope();
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -221,42 +220,42 @@ public:
|
||||||
//
|
//
|
||||||
class ConsoleAttrScope
|
class ConsoleAttrScope
|
||||||
{
|
{
|
||||||
DeclareNoncopyableObject( ConsoleAttrScope );
|
DeclareNoncopyableObject(ConsoleAttrScope);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ConsoleColors m_old_color;
|
ConsoleColors m_old_color;
|
||||||
int m_tabsize;
|
int m_tabsize;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ConsoleAttrScope( ConsoleColors newcolor, int indent=0 );
|
ConsoleAttrScope(ConsoleColors newcolor, int indent = 0);
|
||||||
virtual ~ConsoleAttrScope() throw();
|
virtual ~ConsoleAttrScope() throw();
|
||||||
};
|
};
|
||||||
|
|
||||||
extern IConsoleWriter Console;
|
extern IConsoleWriter Console;
|
||||||
|
|
||||||
#if defined(__unix__)
|
#if defined(__unix__)
|
||||||
extern void Console_SetStdout(FILE *fp);
|
extern void Console_SetStdout(FILE *fp);
|
||||||
#endif
|
#endif
|
||||||
extern void Console_SetActiveHandler( const IConsoleWriter& writer, FILE* flushfp=NULL );
|
extern void Console_SetActiveHandler(const IConsoleWriter &writer, FILE *flushfp = NULL);
|
||||||
|
|
||||||
extern const IConsoleWriter ConsoleWriter_Null;
|
extern const IConsoleWriter ConsoleWriter_Null;
|
||||||
extern const IConsoleWriter ConsoleWriter_Stdout;
|
extern const IConsoleWriter ConsoleWriter_Stdout;
|
||||||
extern const IConsoleWriter ConsoleWriter_Assert;
|
extern const IConsoleWriter ConsoleWriter_Assert;
|
||||||
|
|
||||||
extern NullConsoleWriter NullCon;
|
extern NullConsoleWriter NullCon;
|
||||||
|
|
||||||
extern IConsoleWriter DevConWriter;
|
extern IConsoleWriter DevConWriter;
|
||||||
extern bool DevConWriterEnabled;
|
extern bool DevConWriterEnabled;
|
||||||
|
|
||||||
#ifdef PCSX2_DEVBUILD
|
#ifdef PCSX2_DEVBUILD
|
||||||
# define DevCon DevConWriter
|
#define DevCon DevConWriter
|
||||||
#else
|
#else
|
||||||
# define DevCon DevConWriterEnabled && DevConWriter
|
#define DevCon DevConWriterEnabled &&DevConWriter
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef PCSX2_DEBUG
|
#ifdef PCSX2_DEBUG
|
||||||
extern IConsoleWriter DbgConWriter;
|
extern IConsoleWriter DbgConWriter;
|
||||||
# define DbgCon DbgConWriter
|
#define DbgCon DbgConWriter
|
||||||
#else
|
#else
|
||||||
# define DbgCon 0&&NullCon
|
#define DbgCon 0 && NullCon
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -24,19 +24,19 @@
|
||||||
#define wxsFormat wxString::Format
|
#define wxsFormat wxString::Format
|
||||||
|
|
||||||
#ifdef PCSX2_DEBUG
|
#ifdef PCSX2_DEBUG
|
||||||
# define tryDEBUG try
|
#define tryDEBUG try
|
||||||
# define catchDEBUG(clause) catch(clause)
|
#define catchDEBUG(clause) catch (clause)
|
||||||
#else
|
#else
|
||||||
# define tryDEBUG if(true)
|
#define tryDEBUG if (true)
|
||||||
# define catchDEBUG(clause) if(false)
|
#define catchDEBUG(clause) if (false)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(PCSX2_DEVBUILD) || defined(PCSX2_DEBUG)
|
#if defined(PCSX2_DEVBUILD) || defined(PCSX2_DEBUG)
|
||||||
# define tryDEVEL try
|
#define tryDEVEL try
|
||||||
# define catchDEVEL catch(clause)
|
#define catchDEVEL catch (clause)
|
||||||
#else
|
#else
|
||||||
# define tryDEBUG if(true)
|
#define tryDEBUG if (true)
|
||||||
# define catchDEBUG(clause) if(false)
|
#define catchDEBUG(clause) if (false)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -61,24 +61,48 @@
|
||||||
// method is not implemented! You must implement it yourself if you want to use it:
|
// method is not implemented! You must implement it yourself if you want to use it:
|
||||||
// EnumToString(value);
|
// EnumToString(value);
|
||||||
//
|
//
|
||||||
#define ImplementEnumOperators( enumName ) \
|
#define ImplementEnumOperators(enumName) \
|
||||||
static __fi enumName& operator++ ( enumName& src ) { src = (enumName)((int)src+1); return src; } \
|
static __fi enumName &operator++(enumName &src) \
|
||||||
static __fi enumName& operator-- ( enumName& src ) { src = (enumName)((int)src-1); return src; } \
|
{ \
|
||||||
static __fi enumName operator++ ( enumName& src, int ) { enumName orig = src; src = (enumName)((int)src+1); return orig; } \
|
src = (enumName)((int)src + 1); \
|
||||||
static __fi enumName operator-- ( enumName& src, int ) { enumName orig = src; src = (enumName)((int)src-1); return orig; } \
|
return src; \
|
||||||
\
|
} \
|
||||||
static __fi bool operator< ( const enumName& left, const pxEnumEnd_t& ) { return (int)left < enumName##_COUNT; } \
|
static __fi enumName &operator--(enumName &src) \
|
||||||
static __fi bool operator!=( const enumName& left, const pxEnumEnd_t& ) { return (int)left != enumName##_COUNT; } \
|
{ \
|
||||||
static __fi bool operator==( const enumName& left, const pxEnumEnd_t& ) { return (int)left == enumName##_COUNT; } \
|
src = (enumName)((int)src - 1); \
|
||||||
\
|
return src; \
|
||||||
static __fi bool EnumIsValid( enumName id ) { \
|
} \
|
||||||
return ((int)id >= enumName##_FIRST) && ((int)id < enumName##_COUNT); } \
|
static __fi enumName operator++(enumName &src, int) \
|
||||||
static __fi void EnumAssert( enumName id ) { \
|
{ \
|
||||||
pxAssert( EnumIsValid(id) ); } \
|
enumName orig = src; \
|
||||||
\
|
src = (enumName)((int)src + 1); \
|
||||||
extern const wxChar* EnumToString( enumName id )
|
return orig; \
|
||||||
|
} \
|
||||||
|
static __fi enumName operator--(enumName &src, int) \
|
||||||
|
{ \
|
||||||
|
enumName orig = src; \
|
||||||
|
src = (enumName)((int)src - 1); \
|
||||||
|
return orig; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static __fi bool operator<(const enumName &left, const pxEnumEnd_t &) { return (int)left < enumName##_COUNT; } \
|
||||||
|
static __fi bool operator!=(const enumName &left, const pxEnumEnd_t &) { return (int)left != enumName##_COUNT; } \
|
||||||
|
static __fi bool operator==(const enumName &left, const pxEnumEnd_t &) { return (int)left == enumName##_COUNT; } \
|
||||||
|
\
|
||||||
|
static __fi bool EnumIsValid(enumName id) \
|
||||||
|
{ \
|
||||||
|
return ((int)id >= enumName##_FIRST) && ((int)id < enumName##_COUNT); \
|
||||||
|
} \
|
||||||
|
static __fi void EnumAssert(enumName id) \
|
||||||
|
{ \
|
||||||
|
pxAssert(EnumIsValid(id)); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
extern const wxChar *EnumToString(enumName id)
|
||||||
|
|
||||||
class pxEnumEnd_t { };
|
class pxEnumEnd_t
|
||||||
|
{
|
||||||
|
};
|
||||||
static const pxEnumEnd_t pxEnumEnd = {};
|
static const pxEnumEnd_t pxEnumEnd = {};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -105,10 +129,10 @@ static const pxEnumEnd_t pxEnumEnd = {};
|
||||||
// of wx dependencies though, and has a nicer typeset. :)
|
// of wx dependencies though, and has a nicer typeset. :)
|
||||||
//
|
//
|
||||||
#ifndef DeclareNoncopyableObject
|
#ifndef DeclareNoncopyableObject
|
||||||
# define DeclareNoncopyableObject(classname) \
|
#define DeclareNoncopyableObject(classname) \
|
||||||
private: \
|
private: \
|
||||||
explicit classname(const classname&); \
|
explicit classname(const classname &); \
|
||||||
classname& operator=(const classname&)
|
classname &operator=(const classname &)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -120,19 +144,19 @@ static const pxEnumEnd_t pxEnumEnd = {};
|
||||||
class ScopedBool
|
class ScopedBool
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
bool* m_boolme;
|
bool *m_boolme;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ScopedBool(bool& boolme)
|
ScopedBool(bool &boolme)
|
||||||
{
|
{
|
||||||
boolme = true;
|
boolme = true;
|
||||||
m_boolme = &boolme;
|
m_boolme = &boolme;
|
||||||
}
|
}
|
||||||
|
|
||||||
~ScopedBool() throw()
|
~ScopedBool() throw()
|
||||||
{
|
{
|
||||||
*m_boolme = false;
|
*m_boolme = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -149,15 +173,15 @@ public:
|
||||||
#define WXINTL_NO_GETTEXT_MACRO
|
#define WXINTL_NO_GETTEXT_MACRO
|
||||||
|
|
||||||
#ifndef _
|
#ifndef _
|
||||||
# define _(s) pxGetTranslation(_T(s))
|
#define _(s) pxGetTranslation(_T(s))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef _t
|
#ifndef _t
|
||||||
# define _t(s) pxGetTranslation(_T(s))
|
#define _t(s) pxGetTranslation(_T(s))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef _d
|
#ifndef _d
|
||||||
# define _d(s) pxGetTranslation(_T(s))
|
#define _d(s) pxGetTranslation(_T(s))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// pxL / pxLt / pxDt -- macros provided for tagging translation strings, without actually running
|
// pxL / pxLt / pxDt -- macros provided for tagging translation strings, without actually running
|
||||||
|
@ -167,15 +191,15 @@ public:
|
||||||
// debug/devel specific translations.
|
// debug/devel specific translations.
|
||||||
//
|
//
|
||||||
#ifndef pxL
|
#ifndef pxL
|
||||||
# define pxL(a) wxT(a)
|
#define pxL(a) wxT(a)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef pxLt
|
#ifndef pxLt
|
||||||
# define pxLt(a) wxT(a)
|
#define pxLt(a) wxT(a)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef pxDt
|
#ifndef pxDt
|
||||||
# define pxDt(a) wxT(a)
|
#define pxDt(a) wxT(a)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -193,8 +217,8 @@ public:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <cstring> // string.h under c++
|
#include <cstring> // string.h under c++
|
||||||
#include <cstdio> // stdio.h under c++
|
#include <cstdio> // stdio.h under c++
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
@ -207,42 +231,42 @@ public:
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// Handy Human-readable constants for common immediate values (_16kb -> _4gb)
|
// Handy Human-readable constants for common immediate values (_16kb -> _4gb)
|
||||||
|
|
||||||
static const sptr _1kb = 1024 * 1;
|
static const sptr _1kb = 1024 * 1;
|
||||||
static const sptr _4kb = _1kb * 4;
|
static const sptr _4kb = _1kb * 4;
|
||||||
static const sptr _16kb = _1kb * 16;
|
static const sptr _16kb = _1kb * 16;
|
||||||
static const sptr _32kb = _1kb * 32;
|
static const sptr _32kb = _1kb * 32;
|
||||||
static const sptr _64kb = _1kb * 64;
|
static const sptr _64kb = _1kb * 64;
|
||||||
static const sptr _128kb = _1kb * 128;
|
static const sptr _128kb = _1kb * 128;
|
||||||
static const sptr _256kb = _1kb * 256;
|
static const sptr _256kb = _1kb * 256;
|
||||||
|
|
||||||
static const s64 _1mb = 1024 * 1024;
|
static const s64 _1mb = 1024 * 1024;
|
||||||
static const s64 _8mb = _1mb * 8;
|
static const s64 _8mb = _1mb * 8;
|
||||||
static const s64 _16mb = _1mb * 16;
|
static const s64 _16mb = _1mb * 16;
|
||||||
static const s64 _32mb = _1mb * 32;
|
static const s64 _32mb = _1mb * 32;
|
||||||
static const s64 _64mb = _1mb * 64;
|
static const s64 _64mb = _1mb * 64;
|
||||||
static const s64 _256mb = _1mb * 256;
|
static const s64 _256mb = _1mb * 256;
|
||||||
static const s64 _1gb = _1mb * 1024;
|
static const s64 _1gb = _1mb * 1024;
|
||||||
static const s64 _4gb = _1gb * 4;
|
static const s64 _4gb = _1gb * 4;
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// pxE(msg) and pxEt(msg) [macros] => now same as _/_t/_d
|
// pxE(msg) and pxEt(msg) [macros] => now same as _/_t/_d
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
#define pxE(english) pxExpandMsg( (english) )
|
#define pxE(english) pxExpandMsg((english))
|
||||||
|
|
||||||
// For use with tertiary translations (low priority).
|
// For use with tertiary translations (low priority).
|
||||||
#define pxEt(english) pxExpandMsg( (english) )
|
#define pxEt(english) pxExpandMsg((english))
|
||||||
|
|
||||||
// For use with Dev/debug build translations (low priority).
|
// For use with Dev/debug build translations (low priority).
|
||||||
#define pxE_dev(english) pxExpandMsg( (english) )
|
#define pxE_dev(english) pxExpandMsg((english))
|
||||||
|
|
||||||
|
|
||||||
extern const wxChar* __fastcall pxExpandMsg( const wxChar* englishContent );
|
extern const wxChar *__fastcall pxExpandMsg(const wxChar *englishContent);
|
||||||
extern const wxChar* __fastcall pxGetTranslation( const wxChar* message );
|
extern const wxChar *__fastcall pxGetTranslation(const wxChar *message);
|
||||||
extern bool pxIsEnglish( int id );
|
extern bool pxIsEnglish(int id);
|
||||||
|
|
||||||
extern wxString fromUTF8( const char* src );
|
extern wxString fromUTF8(const char *src);
|
||||||
extern wxString fromAscii( const char* src );
|
extern wxString fromAscii(const char *src);
|
||||||
|
|
||||||
|
|
||||||
#include "Utilities/Assertions.h"
|
#include "Utilities/Assertions.h"
|
||||||
|
|
|
@ -25,8 +25,8 @@
|
||||||
class IEmbeddedImage
|
class IEmbeddedImage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual const wxImage& Get()=0;
|
virtual const wxImage &Get() = 0;
|
||||||
virtual wxImage Scale( int width, int height )=0;
|
virtual wxImage Scale(int width, int height) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -38,85 +38,83 @@ public:
|
||||||
// Note: Get() only loads the image once. All subsequent calls to Get will use the
|
// Note: Get() only loads the image once. All subsequent calls to Get will use the
|
||||||
// previously loaded image data.
|
// previously loaded image data.
|
||||||
//
|
//
|
||||||
template< typename ImageType >
|
template <typename ImageType>
|
||||||
class EmbeddedImage : public IEmbeddedImage
|
class EmbeddedImage : public IEmbeddedImage
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
wxImage m_Image;
|
wxImage m_Image;
|
||||||
const wxSize m_ResampleTo;
|
const wxSize m_ResampleTo;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// Internal function used to ensure the image is loaded before returning the image
|
// Internal function used to ensure the image is loaded before returning the image
|
||||||
// handle (called from all methods that return an image handle).
|
// handle (called from all methods that return an image handle).
|
||||||
//
|
//
|
||||||
void _loadImage()
|
void _loadImage()
|
||||||
{
|
{
|
||||||
if( !m_Image.Ok() )
|
if (!m_Image.Ok()) {
|
||||||
{
|
wxMemoryInputStream joe(ImageType::Data, ImageType::Length);
|
||||||
wxMemoryInputStream joe( ImageType::Data, ImageType::Length );
|
m_Image.LoadFile(joe, ImageType::GetFormat());
|
||||||
m_Image.LoadFile( joe, ImageType::GetFormat() );
|
|
||||||
|
|
||||||
if( m_ResampleTo.IsFullySpecified() && ( m_ResampleTo.GetWidth() != m_Image.GetWidth() || m_ResampleTo.GetHeight() != m_Image.GetHeight() ) )
|
if (m_ResampleTo.IsFullySpecified() && (m_ResampleTo.GetWidth() != m_Image.GetWidth() || m_ResampleTo.GetHeight() != m_Image.GetHeight()))
|
||||||
m_Image.Rescale( m_ResampleTo.GetWidth(), m_ResampleTo.GetHeight(), wxIMAGE_QUALITY_HIGH );
|
m_Image.Rescale(m_ResampleTo.GetWidth(), m_ResampleTo.GetHeight(), wxIMAGE_QUALITY_HIGH);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
EmbeddedImage() :
|
EmbeddedImage()
|
||||||
m_Image()
|
: m_Image()
|
||||||
, m_ResampleTo( wxDefaultSize )
|
, m_ResampleTo(wxDefaultSize)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// Constructor for creating an embedded image that gets resampled to the specified size when
|
// Constructor for creating an embedded image that gets resampled to the specified size when
|
||||||
// loaded.
|
// loaded.
|
||||||
//
|
//
|
||||||
// Implementation Note: This function uses wxWidgets ResamplBox method to resize the image.
|
// Implementation Note: This function uses wxWidgets ResamplBox method to resize the image.
|
||||||
// wxWidgets ResampleBicubic appears to be buggy and produces fairly poor results when down-
|
// wxWidgets ResampleBicubic appears to be buggy and produces fairly poor results when down-
|
||||||
// sampling images (basically resembles a pixel resize). ResampleBox produces much cleaner
|
// sampling images (basically resembles a pixel resize). ResampleBox produces much cleaner
|
||||||
// results.
|
// results.
|
||||||
//
|
//
|
||||||
EmbeddedImage( int newWidth, int newHeight ) :
|
EmbeddedImage(int newWidth, int newHeight)
|
||||||
m_Image()
|
: m_Image()
|
||||||
, m_ResampleTo( newWidth, newHeight )
|
, m_ResampleTo(newWidth, newHeight)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// Loads and retrieves the embedded image. The embedded image is only loaded from its em-
|
// Loads and retrieves the embedded image. The embedded image is only loaded from its em-
|
||||||
// bedded format once. Any subsequent calls to Get(), Rescale(), or Resample() will use
|
// bedded format once. Any subsequent calls to Get(), Rescale(), or Resample() will use
|
||||||
// the pre-loaded copy. Translation: the png/jpeg decoding overhead happens only once,
|
// the pre-loaded copy. Translation: the png/jpeg decoding overhead happens only once,
|
||||||
// and only happens when the image is actually fetched. Simply creating an instance
|
// and only happens when the image is actually fetched. Simply creating an instance
|
||||||
// of an EmbeddedImage object uses no excess memory nor cpu overhead. :)
|
// of an EmbeddedImage object uses no excess memory nor cpu overhead. :)
|
||||||
//
|
//
|
||||||
const wxImage& Get()
|
const wxImage &Get()
|
||||||
{
|
{
|
||||||
_loadImage();
|
_loadImage();
|
||||||
return m_Image;
|
return m_Image;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxIcon GetIcon()
|
wxIcon GetIcon()
|
||||||
{
|
{
|
||||||
wxIcon retval;
|
wxIcon retval;
|
||||||
retval.CopyFromBitmap( Get() );
|
retval.CopyFromBitmap(Get());
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// Performs a pixel resize of the loaded image and returns a new image handle (EmbeddedImage
|
// Performs a pixel resize of the loaded image and returns a new image handle (EmbeddedImage
|
||||||
// is left unmodified).
|
// is left unmodified).
|
||||||
//
|
//
|
||||||
|
|
||||||
wxImage Scale( int width, int height )
|
wxImage Scale(int width, int height)
|
||||||
{
|
{
|
||||||
_loadImage();
|
_loadImage();
|
||||||
// Not strictly necessary - wxWidgets does the dimensions check anyway.
|
// Not strictly necessary - wxWidgets does the dimensions check anyway.
|
||||||
if( width != m_Image.GetWidth() || height != m_Image.GetHeight() )
|
if (width != m_Image.GetWidth() || height != m_Image.GetHeight())
|
||||||
return m_Image.Scale( width, height, wxIMAGE_QUALITY_HIGH );
|
return m_Image.Scale(width, height, wxIMAGE_QUALITY_HIGH);
|
||||||
else
|
else
|
||||||
return m_Image;
|
return m_Image;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -22,56 +22,58 @@
|
||||||
// EventSource< template EvtType >
|
// EventSource< template EvtType >
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
template< typename ListenerType >
|
template <typename ListenerType>
|
||||||
class EventSource
|
class EventSource
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef typename ListenerType::EvtParams EvtParams;
|
typedef typename ListenerType::EvtParams EvtParams;
|
||||||
typedef typename std::list< ListenerType* > ListenerList;
|
typedef typename std::list<ListenerType *> ListenerList;
|
||||||
typedef typename ListenerList::iterator ListenerIterator;
|
typedef typename ListenerList::iterator ListenerIterator;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
typedef typename ListenerList::const_iterator ConstIterator;
|
typedef typename ListenerList::const_iterator ConstIterator;
|
||||||
|
|
||||||
ListenerList m_listeners;
|
ListenerList m_listeners;
|
||||||
|
|
||||||
// This is a cached copy of the listener list used to handle standard dispatching, which
|
// This is a cached copy of the listener list used to handle standard dispatching, which
|
||||||
// allows for self-modification of the EventSource's listener list by the listeners.
|
// allows for self-modification of the EventSource's listener list by the listeners.
|
||||||
// Translation: The dispatcher uses this copy instead, to avoid iterator invalidation.
|
// Translation: The dispatcher uses this copy instead, to avoid iterator invalidation.
|
||||||
ListenerList m_cache_copy;
|
ListenerList m_cache_copy;
|
||||||
bool m_cache_valid;
|
bool m_cache_valid;
|
||||||
|
|
||||||
Threading::Mutex m_listeners_lock;
|
Threading::Mutex m_listeners_lock;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
EventSource()
|
EventSource()
|
||||||
{
|
{
|
||||||
m_cache_valid = false;
|
m_cache_valid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~EventSource() throw() {}
|
virtual ~EventSource() throw() {}
|
||||||
|
|
||||||
virtual ListenerIterator Add( ListenerType& listener );
|
virtual ListenerIterator Add(ListenerType &listener);
|
||||||
virtual void Remove( ListenerType& listener );
|
virtual void Remove(ListenerType &listener);
|
||||||
virtual void Remove( const ListenerIterator& listenerHandle );
|
virtual void Remove(const ListenerIterator &listenerHandle);
|
||||||
|
|
||||||
void Add( ListenerType* listener )
|
void Add(ListenerType *listener)
|
||||||
{
|
{
|
||||||
if( listener == NULL ) return;
|
if (listener == NULL)
|
||||||
Add( *listener );
|
return;
|
||||||
}
|
Add(*listener);
|
||||||
|
}
|
||||||
|
|
||||||
void Remove( ListenerType* listener )
|
void Remove(ListenerType *listener)
|
||||||
{
|
{
|
||||||
if( listener == NULL ) return;
|
if (listener == NULL)
|
||||||
Remove( *listener );
|
return;
|
||||||
}
|
Remove(*listener);
|
||||||
|
}
|
||||||
|
|
||||||
void Dispatch( const EvtParams& params );
|
void Dispatch(const EvtParams ¶ms);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ListenerIterator _AddFast_without_lock( ListenerType& listener );
|
virtual ListenerIterator _AddFast_without_lock(ListenerType &listener);
|
||||||
virtual void _DispatchRaw( ListenerIterator iter, const ListenerIterator& iend, const EvtParams& params );
|
virtual void _DispatchRaw(ListenerIterator iter, const ListenerIterator &iend, const EvtParams ¶ms);
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -80,13 +82,13 @@ protected:
|
||||||
// This class is used as a base interface for EventListeners. It allows the listeners to do
|
// This class is used as a base interface for EventListeners. It allows the listeners to do
|
||||||
// customized dispatching of several event types into "user friendly" function overrides.
|
// customized dispatching of several event types into "user friendly" function overrides.
|
||||||
//
|
//
|
||||||
template< typename EvtParams >
|
template <typename EvtParams>
|
||||||
class IEventDispatcher
|
class IEventDispatcher
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
IEventDispatcher() {}
|
IEventDispatcher() {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~IEventDispatcher() throw() {}
|
virtual ~IEventDispatcher() throw() {}
|
||||||
virtual void DispatchEvent( const EvtParams& params )=0;
|
virtual void DispatchEvent(const EvtParams ¶ms) = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,88 +19,80 @@
|
||||||
|
|
||||||
using Threading::ScopedLock;
|
using Threading::ScopedLock;
|
||||||
|
|
||||||
template< typename ListenerType >
|
template <typename ListenerType>
|
||||||
typename EventSource<ListenerType>::ListenerIterator EventSource<ListenerType>::Add( ListenerType& listener )
|
typename EventSource<ListenerType>::ListenerIterator EventSource<ListenerType>::Add(ListenerType &listener)
|
||||||
{
|
{
|
||||||
ScopedLock locker( m_listeners_lock );
|
ScopedLock locker(m_listeners_lock);
|
||||||
|
|
||||||
// Check for duplicates before adding the event.
|
// Check for duplicates before adding the event.
|
||||||
if( IsDebugBuild )
|
if (IsDebugBuild) {
|
||||||
{
|
ListenerIterator iter = m_listeners.begin();
|
||||||
ListenerIterator iter = m_listeners.begin();
|
while (iter != m_listeners.end()) {
|
||||||
while( iter != m_listeners.end() )
|
if ((*iter) == &listener)
|
||||||
{
|
return iter;
|
||||||
if( (*iter) == &listener ) return iter;
|
++iter;
|
||||||
++iter;
|
}
|
||||||
}
|
}
|
||||||
}
|
return _AddFast_without_lock(listener);
|
||||||
return _AddFast_without_lock( listener );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename ListenerType >
|
template <typename ListenerType>
|
||||||
void EventSource<ListenerType>::Remove( ListenerType& listener )
|
void EventSource<ListenerType>::Remove(ListenerType &listener)
|
||||||
{
|
{
|
||||||
ScopedLock locker( m_listeners_lock );
|
ScopedLock locker(m_listeners_lock);
|
||||||
m_cache_valid = false;
|
m_cache_valid = false;
|
||||||
m_listeners.remove( &listener );
|
m_listeners.remove(&listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename ListenerType >
|
template <typename ListenerType>
|
||||||
void EventSource<ListenerType>::Remove( const ListenerIterator& listenerHandle )
|
void EventSource<ListenerType>::Remove(const ListenerIterator &listenerHandle)
|
||||||
{
|
{
|
||||||
ScopedLock locker( m_listeners_lock );
|
ScopedLock locker(m_listeners_lock);
|
||||||
m_cache_valid = false;
|
m_cache_valid = false;
|
||||||
m_listeners.erase( listenerHandle );
|
m_listeners.erase(listenerHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename ListenerType >
|
template <typename ListenerType>
|
||||||
typename EventSource<ListenerType>::ListenerIterator EventSource<ListenerType>::_AddFast_without_lock( ListenerType& listener )
|
typename EventSource<ListenerType>::ListenerIterator EventSource<ListenerType>::_AddFast_without_lock(ListenerType &listener)
|
||||||
{
|
{
|
||||||
m_cache_valid = false;
|
m_cache_valid = false;
|
||||||
m_listeners.push_front( &listener );
|
m_listeners.push_front(&listener);
|
||||||
return m_listeners.begin();
|
return m_listeners.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template< typename ListenerType >
|
template <typename ListenerType>
|
||||||
__fi void EventSource<ListenerType>::_DispatchRaw( ListenerIterator iter, const ListenerIterator& iend, const EvtParams& evtparams )
|
__fi void EventSource<ListenerType>::_DispatchRaw(ListenerIterator iter, const ListenerIterator &iend, const EvtParams &evtparams)
|
||||||
{
|
{
|
||||||
while( iter != iend )
|
while (iter != iend) {
|
||||||
{
|
try {
|
||||||
try {
|
(*iter)->DispatchEvent(evtparams);
|
||||||
(*iter)->DispatchEvent( evtparams );
|
} catch (Exception::RuntimeError &ex) {
|
||||||
}
|
if (IsDevBuild) {
|
||||||
catch( Exception::RuntimeError& ex )
|
pxFailDev(L"Ignoring runtime error thrown from event listener (event listeners should not throw exceptions!): " + ex.FormatDiagnosticMessage());
|
||||||
{
|
} else {
|
||||||
if( IsDevBuild ) {
|
Console.Error(L"Ignoring runtime error thrown from event listener: " + ex.FormatDiagnosticMessage());
|
||||||
pxFailDev( L"Ignoring runtime error thrown from event listener (event listeners should not throw exceptions!): " + ex.FormatDiagnosticMessage() );
|
}
|
||||||
}
|
} catch (BaseException &ex) {
|
||||||
else {
|
if (IsDevBuild) {
|
||||||
Console.Error( L"Ignoring runtime error thrown from event listener: " + ex.FormatDiagnosticMessage() );
|
ex.DiagMsg() = L"Non-runtime BaseException thrown from event listener .. " + ex.DiagMsg();
|
||||||
}
|
throw;
|
||||||
}
|
}
|
||||||
catch( BaseException& ex )
|
Console.Error(L"Ignoring non-runtime BaseException thrown from event listener: " + ex.FormatDiagnosticMessage());
|
||||||
{
|
}
|
||||||
if( IsDevBuild )
|
++iter;
|
||||||
{
|
}
|
||||||
ex.DiagMsg() = L"Non-runtime BaseException thrown from event listener .. " + ex.DiagMsg();
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
Console.Error( L"Ignoring non-runtime BaseException thrown from event listener: " + ex.FormatDiagnosticMessage() );
|
|
||||||
}
|
|
||||||
++iter;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename ListenerType >
|
template <typename ListenerType>
|
||||||
void EventSource<ListenerType>::Dispatch( const EvtParams& evtparams )
|
void EventSource<ListenerType>::Dispatch(const EvtParams &evtparams)
|
||||||
{
|
{
|
||||||
if( !m_cache_valid )
|
if (!m_cache_valid) {
|
||||||
{
|
m_cache_copy = m_listeners;
|
||||||
m_cache_copy = m_listeners;
|
m_cache_valid = true;
|
||||||
m_cache_valid = true;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if( m_cache_copy.empty() ) return;
|
if (m_cache_copy.empty())
|
||||||
_DispatchRaw( m_cache_copy.begin(), m_cache_copy.end(), evtparams );
|
return;
|
||||||
|
_DispatchRaw(m_cache_copy.begin(), m_cache_copy.end(), evtparams);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,112 +30,113 @@ void pxTrap();
|
||||||
// friendly error log in their wake.
|
// friendly error log in their wake.
|
||||||
//
|
//
|
||||||
// Note: Console can also fire an Exception::OutOfMemory
|
// Note: Console can also fire an Exception::OutOfMemory
|
||||||
#define __DESTRUCTOR_CATCHALL( funcname ) \
|
#define __DESTRUCTOR_CATCHALL(funcname) \
|
||||||
catch( BaseException& ex ) \
|
catch (BaseException & ex) \
|
||||||
{ \
|
{ \
|
||||||
try { \
|
try { \
|
||||||
Console.Error( "Unhandled BaseException in %s (ignored!):", funcname ); \
|
Console.Error("Unhandled BaseException in %s (ignored!):", funcname); \
|
||||||
Console.Error( ex.FormatDiagnosticMessage() ); \
|
Console.Error(ex.FormatDiagnosticMessage()); \
|
||||||
} catch (...) { \
|
} catch (...) { \
|
||||||
fprintf(stderr, "ERROR: (out of memory?)\n"); \
|
fprintf(stderr, "ERROR: (out of memory?)\n"); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
catch( std::exception& ex ) \
|
catch (std::exception & ex) \
|
||||||
{ \
|
{ \
|
||||||
try { \
|
try { \
|
||||||
Console.Error( "Unhandled std::exception in %s (ignored!):", funcname ); \
|
Console.Error("Unhandled std::exception in %s (ignored!):", funcname); \
|
||||||
Console.Error( ex.what() ); \
|
Console.Error(ex.what()); \
|
||||||
} catch (...) { \
|
} catch (...) { \
|
||||||
fprintf(stderr, "ERROR: (out of memory?)\n"); \
|
fprintf(stderr, "ERROR: (out of memory?)\n"); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
catch(...) { \
|
catch (...) \
|
||||||
/* Unreachable code */ \
|
{ \
|
||||||
}
|
/* Unreachable code */ \
|
||||||
|
}
|
||||||
|
|
||||||
#define DESTRUCTOR_CATCHALL __DESTRUCTOR_CATCHALL( __pxFUNCTION__ )
|
#define DESTRUCTOR_CATCHALL __DESTRUCTOR_CATCHALL(__pxFUNCTION__)
|
||||||
|
|
||||||
namespace Exception
|
namespace Exception
|
||||||
{
|
{
|
||||||
int MakeNewType();
|
int MakeNewType();
|
||||||
BaseException* FromErrno( const wxString& streamname, int errcode );
|
BaseException *FromErrno(const wxString &streamname, int errcode);
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// BaseException
|
// BaseException
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// std::exception sucks, and isn't entirely cross-platform reliable in its implementation,
|
// std::exception sucks, and isn't entirely cross-platform reliable in its implementation,
|
||||||
// so I made a replacement. The internal messages are non-const, which means that a
|
// so I made a replacement. The internal messages are non-const, which means that a
|
||||||
// catch clause can optionally modify them and then re-throw to a top-level handler.
|
// catch clause can optionally modify them and then re-throw to a top-level handler.
|
||||||
//
|
//
|
||||||
// Note, this class is "abstract" which means you shouldn't use it directly like, ever.
|
// Note, this class is "abstract" which means you shouldn't use it directly like, ever.
|
||||||
// Use Exception::RuntimeError instead for generic exceptions.
|
// Use Exception::RuntimeError instead for generic exceptions.
|
||||||
//
|
//
|
||||||
// Because exceptions are the (only!) really useful example of multiple inheritance,
|
// Because exceptions are the (only!) really useful example of multiple inheritance,
|
||||||
// this class has only a trivial constructor, and must be manually initialized using
|
// this class has only a trivial constructor, and must be manually initialized using
|
||||||
// InitBaseEx() or by individual member assignments. This is because C++ multiple inheritence
|
// InitBaseEx() or by individual member assignments. This is because C++ multiple inheritence
|
||||||
// is, by design, a lot of fail, especially when class initializers are mixed in.
|
// is, by design, a lot of fail, especially when class initializers are mixed in.
|
||||||
//
|
//
|
||||||
// [TODO] : Add an InnerException component, and Clone() facility.
|
// [TODO] : Add an InnerException component, and Clone() facility.
|
||||||
//
|
//
|
||||||
class BaseException
|
class BaseException
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
wxString m_message_diag; // (untranslated) a "detailed" message of what disastrous thing has occurred!
|
wxString m_message_diag; // (untranslated) a "detailed" message of what disastrous thing has occurred!
|
||||||
wxString m_message_user; // (translated) a "detailed" message of what disastrous thing has occurred!
|
wxString m_message_user; // (translated) a "detailed" message of what disastrous thing has occurred!
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~BaseException() throw()=0; // the =0; syntax forces this class into "abstract" mode.
|
virtual ~BaseException() throw() = 0; // the =0; syntax forces this class into "abstract" mode.
|
||||||
|
|
||||||
const wxString& DiagMsg() const { return m_message_diag; }
|
const wxString &DiagMsg() const { return m_message_diag; }
|
||||||
const wxString& UserMsg() const { return m_message_user; }
|
const wxString &UserMsg() const { return m_message_user; }
|
||||||
|
|
||||||
wxString& DiagMsg() { return m_message_diag; }
|
wxString &DiagMsg() { return m_message_diag; }
|
||||||
wxString& UserMsg() { return m_message_user; }
|
wxString &UserMsg() { return m_message_user; }
|
||||||
|
|
||||||
BaseException& SetBothMsgs( const wxChar* msg_diag );
|
BaseException &SetBothMsgs(const wxChar *msg_diag);
|
||||||
BaseException& SetDiagMsg( const wxString& msg_diag );
|
BaseException &SetDiagMsg(const wxString &msg_diag);
|
||||||
BaseException& SetUserMsg( const wxString& msg_user );
|
BaseException &SetUserMsg(const wxString &msg_user);
|
||||||
|
|
||||||
// Returns a message suitable for diagnostic / logging purposes.
|
// Returns a message suitable for diagnostic / logging purposes.
|
||||||
// This message is always in English, and includes a full stack trace.
|
// This message is always in English, and includes a full stack trace.
|
||||||
virtual wxString FormatDiagnosticMessage() const;
|
virtual wxString FormatDiagnosticMessage() const;
|
||||||
|
|
||||||
// Returns a message suitable for end-user display.
|
// Returns a message suitable for end-user display.
|
||||||
// This message is usually meant for display in a user popup or such.
|
// This message is usually meant for display in a user popup or such.
|
||||||
virtual wxString FormatDisplayMessage() const;
|
virtual wxString FormatDisplayMessage() const;
|
||||||
|
|
||||||
virtual void Rethrow() const=0;
|
virtual void Rethrow() const = 0;
|
||||||
virtual BaseException* Clone() const=0;
|
virtual BaseException *Clone() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::unique_ptr<BaseException> ScopedExcept;
|
typedef std::unique_ptr<BaseException> ScopedExcept;
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// Ps2Generic Exception
|
// Ps2Generic Exception
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// This class is used as a base exception for things tossed by PS2 cpus (EE, IOP, etc).
|
// This class is used as a base exception for things tossed by PS2 cpus (EE, IOP, etc).
|
||||||
//
|
//
|
||||||
// Implementation note: does not derive from BaseException, so that we can use different
|
// Implementation note: does not derive from BaseException, so that we can use different
|
||||||
// catch block hierarchies to handle them (if needed).
|
// catch block hierarchies to handle them (if needed).
|
||||||
//
|
//
|
||||||
// Translation Note: Currently these exceptions are never translated. English/diagnostic
|
// Translation Note: Currently these exceptions are never translated. English/diagnostic
|
||||||
// format only. :)
|
// format only. :)
|
||||||
//
|
//
|
||||||
class Ps2Generic
|
class Ps2Generic
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
wxString m_message; // a "detailed" message of what disastrous thing has occurred!
|
wxString m_message; // a "detailed" message of what disastrous thing has occurred!
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~Ps2Generic() throw() {}
|
virtual ~Ps2Generic() throw() {}
|
||||||
|
|
||||||
virtual u32 GetPc() const=0;
|
virtual u32 GetPc() const = 0;
|
||||||
virtual bool IsDelaySlot() const=0;
|
virtual bool IsDelaySlot() const = 0;
|
||||||
virtual wxString& Message() { return m_message; }
|
virtual wxString &Message() { return m_message; }
|
||||||
|
|
||||||
virtual void Rethrow() const=0;
|
virtual void Rethrow() const = 0;
|
||||||
virtual Ps2Generic* Clone() const=0;
|
virtual Ps2Generic *Clone() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Some helper macros for defining the standard constructors of internationalized constructors
|
// Some helper macros for defining the standard constructors of internationalized constructors
|
||||||
// Parameters:
|
// Parameters:
|
||||||
|
@ -151,217 +152,239 @@ namespace Exception
|
||||||
//
|
//
|
||||||
// (update: web searches indicate it's MSVC specific -- happens in 2008, not sure about 2010).
|
// (update: web searches indicate it's MSVC specific -- happens in 2008, not sure about 2010).
|
||||||
//
|
//
|
||||||
#define DEFINE_EXCEPTION_COPYTORS( classname, parent ) \
|
#define DEFINE_EXCEPTION_COPYTORS(classname, parent) \
|
||||||
private: \
|
private: \
|
||||||
typedef parent _parent; \
|
typedef parent _parent; \
|
||||||
public: \
|
\
|
||||||
virtual ~classname() throw() {} \
|
public: \
|
||||||
virtual void Rethrow() const { throw *this; } \
|
virtual ~classname() throw() {} \
|
||||||
virtual classname* Clone() const { return new classname( *this ); }
|
virtual void Rethrow() const { throw * this; } \
|
||||||
|
virtual classname *Clone() const { return new classname(*this); }
|
||||||
|
|
||||||
#define DEFINE_EXCEPTION_MESSAGES( classname ) \
|
#define DEFINE_EXCEPTION_MESSAGES(classname) \
|
||||||
public: \
|
public: \
|
||||||
classname& SetBothMsgs( const wxChar* msg_diag ) { BaseException::SetBothMsgs(msg_diag); return *this; } \
|
classname &SetBothMsgs(const wxChar *msg_diag) \
|
||||||
classname& SetDiagMsg( const wxString& msg_diag ) { m_message_diag = msg_diag; return *this; } \
|
{ \
|
||||||
classname& SetUserMsg( const wxString& msg_user ) { m_message_user = msg_user; return *this; }
|
BaseException::SetBothMsgs(msg_diag); \
|
||||||
|
return *this; \
|
||||||
|
} \
|
||||||
|
classname &SetDiagMsg(const wxString &msg_diag) \
|
||||||
|
{ \
|
||||||
|
m_message_diag = msg_diag; \
|
||||||
|
return *this; \
|
||||||
|
} \
|
||||||
|
classname &SetUserMsg(const wxString &msg_user) \
|
||||||
|
{ \
|
||||||
|
m_message_user = msg_user; \
|
||||||
|
return *this; \
|
||||||
|
}
|
||||||
|
|
||||||
#define DEFINE_RUNTIME_EXCEPTION( classname, parent, message ) \
|
#define DEFINE_RUNTIME_EXCEPTION(classname, parent, message) \
|
||||||
DEFINE_EXCEPTION_COPYTORS( classname, parent ) \
|
DEFINE_EXCEPTION_COPYTORS(classname, parent) \
|
||||||
classname() { SetDiagMsg(message); } \
|
classname() { SetDiagMsg(message); } \
|
||||||
DEFINE_EXCEPTION_MESSAGES( classname )
|
DEFINE_EXCEPTION_MESSAGES(classname)
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------------
|
|
||||||
// RuntimeError - Generalized Exceptions with Recoverable Traits!
|
|
||||||
// ---------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
class RuntimeError : public BaseException
|
|
||||||
{
|
|
||||||
DEFINE_EXCEPTION_COPYTORS( RuntimeError, BaseException )
|
|
||||||
DEFINE_EXCEPTION_MESSAGES( RuntimeError )
|
|
||||||
|
|
||||||
public:
|
// ---------------------------------------------------------------------------------------
|
||||||
bool IsSilent;
|
// RuntimeError - Generalized Exceptions with Recoverable Traits!
|
||||||
|
// ---------------------------------------------------------------------------------------
|
||||||
|
|
||||||
RuntimeError() { IsSilent = false; }
|
class RuntimeError : public BaseException
|
||||||
RuntimeError( const std::runtime_error& ex, const wxString& prefix=wxEmptyString );
|
{
|
||||||
RuntimeError( const std::exception& ex, const wxString& prefix=wxEmptyString );
|
DEFINE_EXCEPTION_COPYTORS(RuntimeError, BaseException)
|
||||||
};
|
DEFINE_EXCEPTION_MESSAGES(RuntimeError)
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
public:
|
||||||
// CancelAppEvent - Exception for canceling an event in a non-verbose fashion
|
bool IsSilent;
|
||||||
// --------------------------------------------------------------------------------------
|
|
||||||
// Typically the PCSX2 interface issues popup dialogs for runtime errors. This exception
|
|
||||||
// instead issues a "silent" cancelation that is handled by the app gracefully (generates
|
|
||||||
// log, and resumes messages queue processing).
|
|
||||||
//
|
|
||||||
// I chose to have this exception derive from RuntimeError, since if one is thrown from outside
|
|
||||||
// an App message loop we'll still want it to be handled in a reasonably graceful manner.
|
|
||||||
class CancelEvent : public RuntimeError
|
|
||||||
{
|
|
||||||
DEFINE_RUNTIME_EXCEPTION( CancelEvent, RuntimeError, pxLt("No reason given.") )
|
|
||||||
|
|
||||||
public:
|
RuntimeError() { IsSilent = false; }
|
||||||
explicit CancelEvent( const wxString& logmsg )
|
RuntimeError(const std::runtime_error &ex, const wxString &prefix = wxEmptyString);
|
||||||
{
|
RuntimeError(const std::exception &ex, const wxString &prefix = wxEmptyString);
|
||||||
m_message_diag = logmsg;
|
};
|
||||||
// overridden message formatters only use the diagnostic version...
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual wxString FormatDisplayMessage() const;
|
// --------------------------------------------------------------------------------------
|
||||||
virtual wxString FormatDiagnosticMessage() const;
|
// CancelAppEvent - Exception for canceling an event in a non-verbose fashion
|
||||||
};
|
// --------------------------------------------------------------------------------------
|
||||||
|
// Typically the PCSX2 interface issues popup dialogs for runtime errors. This exception
|
||||||
|
// instead issues a "silent" cancelation that is handled by the app gracefully (generates
|
||||||
|
// log, and resumes messages queue processing).
|
||||||
|
//
|
||||||
|
// I chose to have this exception derive from RuntimeError, since if one is thrown from outside
|
||||||
|
// an App message loop we'll still want it to be handled in a reasonably graceful manner.
|
||||||
|
class CancelEvent : public RuntimeError
|
||||||
|
{
|
||||||
|
DEFINE_RUNTIME_EXCEPTION(CancelEvent, RuntimeError, pxLt("No reason given."))
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------------
|
public:
|
||||||
// OutOfMemory
|
explicit CancelEvent(const wxString &logmsg)
|
||||||
// ---------------------------------------------------------------------------------------
|
{
|
||||||
// This exception has a custom-formatted Diagnostic string. The parameter give when constructing
|
m_message_diag = logmsg;
|
||||||
// the exception is a block/alloc name, which is used as a formatting parameter in the diagnostic
|
// overridden message formatters only use the diagnostic version...
|
||||||
// output. The default diagnostic message is "Out of memory exception, while allocating the %s."
|
}
|
||||||
// where %s is filled in with the block name.
|
|
||||||
//
|
|
||||||
// The user string is not custom-formatted, and should contain *NO* %s tags.
|
|
||||||
//
|
|
||||||
class OutOfMemory : public RuntimeError
|
|
||||||
{
|
|
||||||
DEFINE_RUNTIME_EXCEPTION( OutOfMemory, RuntimeError, wxEmptyString )
|
|
||||||
|
|
||||||
public:
|
virtual wxString FormatDisplayMessage() const;
|
||||||
wxString AllocDescription;
|
virtual wxString FormatDiagnosticMessage() const;
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
// ---------------------------------------------------------------------------------------
|
||||||
OutOfMemory( const wxString& allocdesc );
|
// OutOfMemory
|
||||||
|
// ---------------------------------------------------------------------------------------
|
||||||
|
// This exception has a custom-formatted Diagnostic string. The parameter give when constructing
|
||||||
|
// the exception is a block/alloc name, which is used as a formatting parameter in the diagnostic
|
||||||
|
// output. The default diagnostic message is "Out of memory exception, while allocating the %s."
|
||||||
|
// where %s is filled in with the block name.
|
||||||
|
//
|
||||||
|
// The user string is not custom-formatted, and should contain *NO* %s tags.
|
||||||
|
//
|
||||||
|
class OutOfMemory : public RuntimeError
|
||||||
|
{
|
||||||
|
DEFINE_RUNTIME_EXCEPTION(OutOfMemory, RuntimeError, wxEmptyString)
|
||||||
|
|
||||||
virtual wxString FormatDisplayMessage() const;
|
public:
|
||||||
virtual wxString FormatDiagnosticMessage() const;
|
wxString AllocDescription;
|
||||||
};
|
|
||||||
|
|
||||||
class ParseError : public RuntimeError
|
public:
|
||||||
{
|
OutOfMemory(const wxString &allocdesc);
|
||||||
DEFINE_RUNTIME_EXCEPTION( ParseError, RuntimeError, pxL("Parse error") );
|
|
||||||
};
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------------
|
virtual wxString FormatDisplayMessage() const;
|
||||||
// Hardware/OS Exceptions:
|
virtual wxString FormatDiagnosticMessage() const;
|
||||||
// HardwareDeficiency / VirtualMemoryMapConflict
|
};
|
||||||
// ---------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// This exception is a specific type of OutOfMemory error that isn't "really" an out of
|
class ParseError : public RuntimeError
|
||||||
// memory error. More likely it's caused by a plugin or driver reserving a range of memory
|
{
|
||||||
// we'd really like to have access to.
|
DEFINE_RUNTIME_EXCEPTION(ParseError, RuntimeError, pxL("Parse error"));
|
||||||
class VirtualMemoryMapConflict : public OutOfMemory
|
};
|
||||||
{
|
|
||||||
DEFINE_RUNTIME_EXCEPTION( VirtualMemoryMapConflict, OutOfMemory, wxEmptyString )
|
|
||||||
|
|
||||||
VirtualMemoryMapConflict( const wxString& allocdesc );
|
// ---------------------------------------------------------------------------------------
|
||||||
|
// Hardware/OS Exceptions:
|
||||||
|
// HardwareDeficiency / VirtualMemoryMapConflict
|
||||||
|
// ---------------------------------------------------------------------------------------
|
||||||
|
|
||||||
virtual wxString FormatDisplayMessage() const;
|
// This exception is a specific type of OutOfMemory error that isn't "really" an out of
|
||||||
virtual wxString FormatDiagnosticMessage() const;
|
// memory error. More likely it's caused by a plugin or driver reserving a range of memory
|
||||||
};
|
// we'd really like to have access to.
|
||||||
|
class VirtualMemoryMapConflict : public OutOfMemory
|
||||||
|
{
|
||||||
|
DEFINE_RUNTIME_EXCEPTION(VirtualMemoryMapConflict, OutOfMemory, wxEmptyString)
|
||||||
|
|
||||||
class HardwareDeficiency : public RuntimeError
|
VirtualMemoryMapConflict(const wxString &allocdesc);
|
||||||
{
|
|
||||||
public:
|
|
||||||
DEFINE_RUNTIME_EXCEPTION( HardwareDeficiency, RuntimeError, pxL("Your machine's hardware is incapable of running PCSX2. Sorry dood.") );
|
|
||||||
};
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------------
|
virtual wxString FormatDisplayMessage() const;
|
||||||
// Streaming (file) Exceptions:
|
virtual wxString FormatDiagnosticMessage() const;
|
||||||
// Stream / BadStream / CannotCreateStream / FileNotFound / AccessDenied / EndOfStream
|
};
|
||||||
// ---------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#define DEFINE_STREAM_EXCEPTION_ACCESSORS( classname ) \
|
class HardwareDeficiency : public RuntimeError
|
||||||
virtual classname& SetStreamName( const wxString& name ) { StreamName = name; return *this; } \
|
{
|
||||||
virtual classname& SetStreamName( const char* name ) { StreamName = fromUTF8(name); return *this; }
|
public:
|
||||||
|
DEFINE_RUNTIME_EXCEPTION(HardwareDeficiency, RuntimeError, pxL("Your machine's hardware is incapable of running PCSX2. Sorry dood."));
|
||||||
|
};
|
||||||
|
|
||||||
#define DEFINE_STREAM_EXCEPTION( classname, parent ) \
|
// ---------------------------------------------------------------------------------------
|
||||||
DEFINE_RUNTIME_EXCEPTION( classname, parent, wxEmptyString ) \
|
// Streaming (file) Exceptions:
|
||||||
classname( const wxString& filename ) { \
|
// Stream / BadStream / CannotCreateStream / FileNotFound / AccessDenied / EndOfStream
|
||||||
StreamName = filename; \
|
// ---------------------------------------------------------------------------------------
|
||||||
} \
|
|
||||||
DEFINE_STREAM_EXCEPTION_ACCESSORS( classname )
|
|
||||||
|
|
||||||
// A generic base error class for bad streams -- corrupted data, sudden closures, loss of
|
|
||||||
// connection, or anything else that would indicate a failure to open a stream or read the
|
|
||||||
// data after the stream was successfully opened.
|
|
||||||
//
|
|
||||||
class BadStream : public RuntimeError
|
|
||||||
{
|
|
||||||
DEFINE_STREAM_EXCEPTION( BadStream, RuntimeError )
|
|
||||||
|
|
||||||
public:
|
#define DEFINE_STREAM_EXCEPTION_ACCESSORS(classname) \
|
||||||
wxString StreamName; // name of the stream (if applicable)
|
virtual classname &SetStreamName(const wxString &name) \
|
||||||
|
{ \
|
||||||
|
StreamName = name; \
|
||||||
|
return *this; \
|
||||||
|
} \
|
||||||
|
virtual classname &SetStreamName(const char *name) \
|
||||||
|
{ \
|
||||||
|
StreamName = fromUTF8(name); \
|
||||||
|
return *this; \
|
||||||
|
}
|
||||||
|
|
||||||
virtual wxString FormatDiagnosticMessage() const;
|
#define DEFINE_STREAM_EXCEPTION(classname, parent) \
|
||||||
virtual wxString FormatDisplayMessage() const;
|
DEFINE_RUNTIME_EXCEPTION(classname, parent, wxEmptyString) \
|
||||||
|
classname(const wxString &filename) \
|
||||||
|
{ \
|
||||||
|
StreamName = filename; \
|
||||||
|
} \
|
||||||
|
DEFINE_STREAM_EXCEPTION_ACCESSORS(classname)
|
||||||
|
|
||||||
protected:
|
// A generic base error class for bad streams -- corrupted data, sudden closures, loss of
|
||||||
void _formatDiagMsg( FastFormatUnicode& dest ) const;
|
// connection, or anything else that would indicate a failure to open a stream or read the
|
||||||
void _formatUserMsg( FastFormatUnicode& dest ) const;
|
// data after the stream was successfully opened.
|
||||||
};
|
//
|
||||||
|
class BadStream : public RuntimeError
|
||||||
|
{
|
||||||
|
DEFINE_STREAM_EXCEPTION(BadStream, RuntimeError)
|
||||||
|
|
||||||
// A generic exception for odd-ball stream creation errors.
|
public:
|
||||||
//
|
wxString StreamName; // name of the stream (if applicable)
|
||||||
class CannotCreateStream : public BadStream
|
|
||||||
{
|
|
||||||
DEFINE_STREAM_EXCEPTION( CannotCreateStream, BadStream )
|
|
||||||
|
|
||||||
virtual wxString FormatDiagnosticMessage() const;
|
virtual wxString FormatDiagnosticMessage() const;
|
||||||
virtual wxString FormatDisplayMessage() const;
|
virtual wxString FormatDisplayMessage() const;
|
||||||
};
|
|
||||||
|
|
||||||
// Exception thrown when an attempt to open a non-existent file is made.
|
protected:
|
||||||
// (this exception can also mean file permissions are invalid)
|
void _formatDiagMsg(FastFormatUnicode &dest) const;
|
||||||
//
|
void _formatUserMsg(FastFormatUnicode &dest) const;
|
||||||
class FileNotFound : public CannotCreateStream
|
};
|
||||||
{
|
|
||||||
public:
|
|
||||||
DEFINE_STREAM_EXCEPTION( FileNotFound, CannotCreateStream )
|
|
||||||
|
|
||||||
virtual wxString FormatDiagnosticMessage() const;
|
// A generic exception for odd-ball stream creation errors.
|
||||||
virtual wxString FormatDisplayMessage() const;
|
//
|
||||||
};
|
class CannotCreateStream : public BadStream
|
||||||
|
{
|
||||||
|
DEFINE_STREAM_EXCEPTION(CannotCreateStream, BadStream)
|
||||||
|
|
||||||
class AccessDenied : public CannotCreateStream
|
virtual wxString FormatDiagnosticMessage() const;
|
||||||
{
|
virtual wxString FormatDisplayMessage() const;
|
||||||
public:
|
};
|
||||||
DEFINE_STREAM_EXCEPTION( AccessDenied, CannotCreateStream )
|
|
||||||
|
|
||||||
virtual wxString FormatDiagnosticMessage() const;
|
// Exception thrown when an attempt to open a non-existent file is made.
|
||||||
virtual wxString FormatDisplayMessage() const;
|
// (this exception can also mean file permissions are invalid)
|
||||||
};
|
//
|
||||||
|
class FileNotFound : public CannotCreateStream
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DEFINE_STREAM_EXCEPTION(FileNotFound, CannotCreateStream)
|
||||||
|
|
||||||
// EndOfStream can be used either as an error, or used just as a shortcut for manual
|
virtual wxString FormatDiagnosticMessage() const;
|
||||||
// feof checks.
|
virtual wxString FormatDisplayMessage() const;
|
||||||
//
|
};
|
||||||
class EndOfStream : public BadStream
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DEFINE_STREAM_EXCEPTION( EndOfStream, BadStream )
|
|
||||||
|
|
||||||
virtual wxString FormatDiagnosticMessage() const;
|
class AccessDenied : public CannotCreateStream
|
||||||
virtual wxString FormatDisplayMessage() const;
|
{
|
||||||
};
|
public:
|
||||||
|
DEFINE_STREAM_EXCEPTION(AccessDenied, CannotCreateStream)
|
||||||
|
|
||||||
|
virtual wxString FormatDiagnosticMessage() const;
|
||||||
|
virtual wxString FormatDisplayMessage() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
// EndOfStream can be used either as an error, or used just as a shortcut for manual
|
||||||
|
// feof checks.
|
||||||
|
//
|
||||||
|
class EndOfStream : public BadStream
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DEFINE_STREAM_EXCEPTION(EndOfStream, BadStream)
|
||||||
|
|
||||||
|
virtual wxString FormatDiagnosticMessage() const;
|
||||||
|
virtual wxString FormatDisplayMessage() const;
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef __WXMSW__
|
#ifdef __WXMSW__
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// Exception::WinApiError
|
// Exception::WinApiError
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
class WinApiError : public RuntimeError
|
class WinApiError : public RuntimeError
|
||||||
{
|
{
|
||||||
DEFINE_EXCEPTION_COPYTORS( WinApiError, RuntimeError )
|
DEFINE_EXCEPTION_COPYTORS(WinApiError, RuntimeError)
|
||||||
DEFINE_EXCEPTION_MESSAGES( WinApiError )
|
DEFINE_EXCEPTION_MESSAGES(WinApiError)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int ErrorId;
|
int ErrorId;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
WinApiError();
|
WinApiError();
|
||||||
|
|
||||||
wxString GetMsgFromWindows() const;
|
wxString GetMsgFromWindows() const;
|
||||||
virtual wxString FormatDisplayMessage() const;
|
virtual wxString FormatDisplayMessage() const;
|
||||||
virtual wxString FormatDiagnosticMessage() const;
|
virtual wxString FormatDiagnosticMessage() const;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,59 +17,59 @@
|
||||||
|
|
||||||
#include "Dependencies.h"
|
#include "Dependencies.h"
|
||||||
|
|
||||||
template< int Precision >
|
template <int Precision>
|
||||||
struct FixedInt
|
struct FixedInt
|
||||||
{
|
{
|
||||||
s32 Raw;
|
s32 Raw;
|
||||||
|
|
||||||
FixedInt();
|
FixedInt();
|
||||||
FixedInt( int signedval );
|
FixedInt(int signedval);
|
||||||
FixedInt( double doubval );
|
FixedInt(double doubval);
|
||||||
FixedInt( float floval );
|
FixedInt(float floval);
|
||||||
|
|
||||||
bool operator ==( const FixedInt<Precision>& right ) const { return Raw == right.Raw; }
|
bool operator==(const FixedInt<Precision> &right) const { return Raw == right.Raw; }
|
||||||
bool operator !=( const FixedInt<Precision>& right ) const { return Raw != right.Raw; }
|
bool operator!=(const FixedInt<Precision> &right) const { return Raw != right.Raw; }
|
||||||
|
|
||||||
bool operator>( const FixedInt<Precision>& right ) const { return Raw > right.Raw; };
|
bool operator>(const FixedInt<Precision> &right) const { return Raw > right.Raw; };
|
||||||
bool operator>=( const FixedInt<Precision>& right ) const { return Raw >= right.Raw; };
|
bool operator>=(const FixedInt<Precision> &right) const { return Raw >= right.Raw; };
|
||||||
bool operator<( const FixedInt<Precision>& right ) const { return Raw < right.Raw; };
|
bool operator<(const FixedInt<Precision> &right) const { return Raw < right.Raw; };
|
||||||
bool operator<=( const FixedInt<Precision>& right ) const { return Raw <= right.Raw; };
|
bool operator<=(const FixedInt<Precision> &right) const { return Raw <= right.Raw; };
|
||||||
|
|
||||||
FixedInt<Precision> operator+( const FixedInt<Precision>& right ) const;
|
FixedInt<Precision> operator+(const FixedInt<Precision> &right) const;
|
||||||
FixedInt<Precision> operator-( const FixedInt<Precision>& right ) const;
|
FixedInt<Precision> operator-(const FixedInt<Precision> &right) const;
|
||||||
FixedInt<Precision>& operator+=( const FixedInt<Precision>& right );
|
FixedInt<Precision> &operator+=(const FixedInt<Precision> &right);
|
||||||
FixedInt<Precision>& operator-=( const FixedInt<Precision>& right );
|
FixedInt<Precision> &operator-=(const FixedInt<Precision> &right);
|
||||||
|
|
||||||
FixedInt<Precision>& ConfineTo( const FixedInt<Precision>& low, const FixedInt<Precision>& high );
|
FixedInt<Precision> &ConfineTo(const FixedInt<Precision> &low, const FixedInt<Precision> &high);
|
||||||
|
|
||||||
FixedInt<Precision> operator*( const FixedInt<Precision>& right ) const;
|
FixedInt<Precision> operator*(const FixedInt<Precision> &right) const;
|
||||||
FixedInt<Precision> operator/( const FixedInt<Precision>& right ) const;
|
FixedInt<Precision> operator/(const FixedInt<Precision> &right) const;
|
||||||
FixedInt<Precision>& operator*=( const FixedInt<Precision>& right );
|
FixedInt<Precision> &operator*=(const FixedInt<Precision> &right);
|
||||||
FixedInt<Precision>& operator/=( const FixedInt<Precision>& right );
|
FixedInt<Precision> &operator/=(const FixedInt<Precision> &right);
|
||||||
|
|
||||||
static bool OverflowCheck( int signedval );
|
static bool OverflowCheck(int signedval);
|
||||||
static bool OverflowCheck( double signedval );
|
static bool OverflowCheck(double signedval);
|
||||||
|
|
||||||
int GetWhole() const;
|
int GetWhole() const;
|
||||||
int GetFraction() const;
|
int GetFraction() const;
|
||||||
|
|
||||||
FixedInt<Precision>& SetRaw( s32 rawsrc );
|
FixedInt<Precision> &SetRaw(s32 rawsrc);
|
||||||
FixedInt<Precision>& Round();
|
FixedInt<Precision> &Round();
|
||||||
FixedInt<Precision>& SetWhole( s32 wholepart );
|
FixedInt<Precision> &SetWhole(s32 wholepart);
|
||||||
FixedInt<Precision>& SetFraction( u32 fracpart );
|
FixedInt<Precision> &SetFraction(u32 fracpart);
|
||||||
|
|
||||||
wxString ToString() const;
|
wxString ToString() const;
|
||||||
wxString ToString( int fracDigits ) const;
|
wxString ToString(int fracDigits) const;
|
||||||
|
|
||||||
double ToDouble() const;
|
double ToDouble() const;
|
||||||
float ToFloat() const;
|
float ToFloat() const;
|
||||||
int ToIntTruncated() const;
|
int ToIntTruncated() const;
|
||||||
int ToIntRounded() const;
|
int ToIntRounded() const;
|
||||||
|
|
||||||
static bool TryFromString( FixedInt<Precision>& dest, const wxString& parseFrom );
|
static bool TryFromString(FixedInt<Precision> &dest, const wxString &parseFrom);
|
||||||
static FixedInt<Precision> FromString( const wxString& parseFrom, const FixedInt<Precision>& defval );
|
static FixedInt<Precision> FromString(const wxString &parseFrom, const FixedInt<Precision> &defval);
|
||||||
static FixedInt<Precision> FromString( const wxString parseFrom );
|
static FixedInt<Precision> FromString(const wxString parseFrom);
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef FixedInt<256> Fixed256;
|
typedef FixedInt<256> Fixed256;
|
||||||
typedef FixedInt<100> Fixed100;
|
typedef FixedInt<100> Fixed100;
|
||||||
|
|
|
@ -16,226 +16,237 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "FixedPointTypes.h"
|
#include "FixedPointTypes.h"
|
||||||
#include <cmath> // for pow!
|
#include <cmath> // for pow!
|
||||||
|
|
||||||
template< int Precision >
|
template <int Precision>
|
||||||
FixedInt<Precision>::FixedInt()
|
FixedInt<Precision>::FixedInt()
|
||||||
{
|
{
|
||||||
Raw = 0;
|
Raw = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template< int Precision >
|
template <int Precision>
|
||||||
FixedInt<Precision>::FixedInt( int signedval )
|
FixedInt<Precision>::FixedInt(int signedval)
|
||||||
{
|
{
|
||||||
Raw = signedval * Precision;
|
Raw = signedval * Precision;
|
||||||
}
|
}
|
||||||
|
|
||||||
template< int Precision >
|
template <int Precision>
|
||||||
FixedInt<Precision>::FixedInt( double doubval )
|
FixedInt<Precision>::FixedInt(double doubval)
|
||||||
{
|
{
|
||||||
Raw = lround(doubval * (double)Precision);
|
Raw = lround(doubval * (double)Precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
template< int Precision >
|
template <int Precision>
|
||||||
FixedInt<Precision>::FixedInt( float floval )
|
FixedInt<Precision>::FixedInt(float floval)
|
||||||
{
|
{
|
||||||
Raw = lroundf(floval * (float)Precision);
|
Raw = lroundf(floval * (float)Precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
template< int Precision >
|
template <int Precision>
|
||||||
FixedInt<Precision> FixedInt<Precision>::operator+( const FixedInt<Precision>& right ) const
|
FixedInt<Precision> FixedInt<Precision>::operator+(const FixedInt<Precision> &right) const
|
||||||
{
|
{
|
||||||
return FixedInt<Precision>().SetRaw( Raw + right.Raw );
|
return FixedInt<Precision>().SetRaw(Raw + right.Raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
template< int Precision >
|
template <int Precision>
|
||||||
FixedInt<Precision> FixedInt<Precision>::operator-( const FixedInt<Precision>& right ) const
|
FixedInt<Precision> FixedInt<Precision>::operator-(const FixedInt<Precision> &right) const
|
||||||
{
|
{
|
||||||
return FixedInt<Precision>().SetRaw( Raw + right.Raw );
|
return FixedInt<Precision>().SetRaw(Raw + right.Raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
template< int Precision >
|
template <int Precision>
|
||||||
FixedInt<Precision>& FixedInt<Precision>::operator+=( const FixedInt<Precision>& right )
|
FixedInt<Precision> &FixedInt<Precision>::operator+=(const FixedInt<Precision> &right)
|
||||||
{
|
{
|
||||||
return SetRaw( Raw + right.Raw );
|
return SetRaw(Raw + right.Raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
template< int Precision >
|
template <int Precision>
|
||||||
FixedInt<Precision>& FixedInt<Precision>::operator-=( const FixedInt<Precision>& right )
|
FixedInt<Precision> &FixedInt<Precision>::operator-=(const FixedInt<Precision> &right)
|
||||||
{
|
{
|
||||||
return SetRaw( Raw + right.Raw );
|
return SetRaw(Raw + right.Raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
template< int Precision >
|
template <int Precision>
|
||||||
FixedInt<Precision>& FixedInt<Precision>::ConfineTo( const FixedInt<Precision>& low, const FixedInt<Precision>& high )
|
FixedInt<Precision> &FixedInt<Precision>::ConfineTo(const FixedInt<Precision> &low, const FixedInt<Precision> &high)
|
||||||
{
|
{
|
||||||
return SetRaw( std::min( std::max( Raw, low.Raw ), high.Raw ) );
|
return SetRaw(std::min(std::max(Raw, low.Raw), high.Raw));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uses 64 bit internally to avoid overflows. For more precise/optimized 32 bit math
|
// Uses 64 bit internally to avoid overflows. For more precise/optimized 32 bit math
|
||||||
// you'll need to use the Raw values directly.
|
// you'll need to use the Raw values directly.
|
||||||
template< int Precision >
|
template <int Precision>
|
||||||
FixedInt<Precision> FixedInt<Precision>::operator*( const FixedInt<Precision>& right ) const
|
FixedInt<Precision> FixedInt<Precision>::operator*(const FixedInt<Precision> &right) const
|
||||||
{
|
{
|
||||||
s64 mulres = (s64)Raw * right.Raw;
|
s64 mulres = (s64)Raw * right.Raw;
|
||||||
return FixedInt<Precision>().SetRaw( (s32)(mulres / Precision) );
|
return FixedInt<Precision>().SetRaw((s32)(mulres / Precision));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uses 64 bit internally to avoid overflows. For more precise/optimized 32 bit math
|
// Uses 64 bit internally to avoid overflows. For more precise/optimized 32 bit math
|
||||||
// you'll need to use the Raw values directly.
|
// you'll need to use the Raw values directly.
|
||||||
template< int Precision >
|
template <int Precision>
|
||||||
FixedInt<Precision> FixedInt<Precision>::operator/( const FixedInt<Precision>& right ) const
|
FixedInt<Precision> FixedInt<Precision>::operator/(const FixedInt<Precision> &right) const
|
||||||
{
|
{
|
||||||
s64 divres = Raw * Precision;
|
s64 divres = Raw * Precision;
|
||||||
return FixedInt<Precision>().SetRaw( (s32)(divres / right.Raw) );
|
return FixedInt<Precision>().SetRaw((s32)(divres / right.Raw));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uses 64 bit internally to avoid overflows. For more precise/optimized 32 bit math
|
// Uses 64 bit internally to avoid overflows. For more precise/optimized 32 bit math
|
||||||
// you'll need to use the Raw values directly.
|
// you'll need to use the Raw values directly.
|
||||||
template< int Precision >
|
template <int Precision>
|
||||||
FixedInt<Precision>& FixedInt<Precision>::operator*=( const FixedInt<Precision>& right )
|
FixedInt<Precision> &FixedInt<Precision>::operator*=(const FixedInt<Precision> &right)
|
||||||
{
|
{
|
||||||
s64 mulres = (s64)Raw * right.Raw;
|
s64 mulres = (s64)Raw * right.Raw;
|
||||||
return SetRaw( (s32)(mulres / Precision) );
|
return SetRaw((s32)(mulres / Precision));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uses 64 bit internally to avoid overflows. For more precise/optimized 32 bit math
|
// Uses 64 bit internally to avoid overflows. For more precise/optimized 32 bit math
|
||||||
// you'll need to use the Raw values directly.
|
// you'll need to use the Raw values directly.
|
||||||
template< int Precision >
|
template <int Precision>
|
||||||
FixedInt<Precision>& FixedInt<Precision>::operator/=( const FixedInt<Precision>& right )
|
FixedInt<Precision> &FixedInt<Precision>::operator/=(const FixedInt<Precision> &right)
|
||||||
{
|
{
|
||||||
s64 divres = Raw * Precision;
|
s64 divres = Raw * Precision;
|
||||||
return SetRaw( (s32)(divres / right.Raw) );
|
return SetRaw((s32)(divres / right.Raw));
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns TRUE if the value overflows the legal integer range of this container.
|
// returns TRUE if the value overflows the legal integer range of this container.
|
||||||
template< int Precision >
|
template <int Precision>
|
||||||
bool FixedInt<Precision>::OverflowCheck( int signedval )
|
bool FixedInt<Precision>::OverflowCheck(int signedval)
|
||||||
{
|
{
|
||||||
return ( signedval >= (INT_MAX / Precision) );
|
return (signedval >= (INT_MAX / Precision));
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns TRUE if the value overflows the legal integer range of this container.
|
// returns TRUE if the value overflows the legal integer range of this container.
|
||||||
template< int Precision >
|
template <int Precision>
|
||||||
bool FixedInt<Precision>::OverflowCheck( double signedval )
|
bool FixedInt<Precision>::OverflowCheck(double signedval)
|
||||||
{
|
{
|
||||||
return ( signedval >= (INT_MAX / Precision) );
|
return (signedval >= (INT_MAX / Precision));
|
||||||
}
|
}
|
||||||
|
|
||||||
template< int Precision > int FixedInt<Precision>::GetWhole() const { return Raw / Precision; }
|
template <int Precision>
|
||||||
template< int Precision > int FixedInt<Precision>::GetFraction() const { return Raw % Precision; }
|
int FixedInt<Precision>::GetWhole() const
|
||||||
|
|
||||||
template< int Precision >
|
|
||||||
FixedInt<Precision>& FixedInt<Precision>::SetRaw( s32 rawsrc )
|
|
||||||
{
|
{
|
||||||
Raw = rawsrc;
|
return Raw / Precision;
|
||||||
return *this;
|
}
|
||||||
|
template <int Precision>
|
||||||
|
int FixedInt<Precision>::GetFraction() const
|
||||||
|
{
|
||||||
|
return Raw % Precision;
|
||||||
}
|
}
|
||||||
|
|
||||||
template< int Precision >
|
template <int Precision>
|
||||||
FixedInt<Precision>& FixedInt<Precision>::Round()
|
FixedInt<Precision> &FixedInt<Precision>::SetRaw(s32 rawsrc)
|
||||||
{
|
{
|
||||||
Raw = ToIntRounded();
|
Raw = rawsrc;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template< int Precision >
|
template <int Precision>
|
||||||
FixedInt<Precision>& FixedInt<Precision>::SetWhole( s32 wholepart )
|
FixedInt<Precision> &FixedInt<Precision>::Round()
|
||||||
{
|
{
|
||||||
pxAssert( wholepart < (INT_MAX / Precision) );
|
Raw = ToIntRounded();
|
||||||
Raw = GetFraction() + (wholepart * Precision);
|
return *this;
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template< int Precision >
|
template <int Precision>
|
||||||
FixedInt<Precision>& FixedInt<Precision>::SetFraction( u32 fracpart )
|
FixedInt<Precision> &FixedInt<Precision>::SetWhole(s32 wholepart)
|
||||||
{
|
{
|
||||||
Raw = (GetWhole() * Precision) + fracpart;
|
pxAssert(wholepart < (INT_MAX / Precision));
|
||||||
return *this;
|
Raw = GetFraction() + (wholepart * Precision);
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template< int Precision >
|
template <int Precision>
|
||||||
|
FixedInt<Precision> &FixedInt<Precision>::SetFraction(u32 fracpart)
|
||||||
|
{
|
||||||
|
Raw = (GetWhole() * Precision) + fracpart;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <int Precision>
|
||||||
wxString FixedInt<Precision>::ToString() const
|
wxString FixedInt<Precision>::ToString() const
|
||||||
{
|
{
|
||||||
return wxsFormat( L"%d.%02d", GetWhole(), (GetFraction() * 100) / Precision );
|
return wxsFormat(L"%d.%02d", GetWhole(), (GetFraction() * 100) / Precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
template< int Precision >
|
template <int Precision>
|
||||||
wxString FixedInt<Precision>::ToString( int fracDigits ) const
|
wxString FixedInt<Precision>::ToString(int fracDigits) const
|
||||||
{
|
{
|
||||||
if( fracDigits == 0 ) return wxsFormat( L"%d", GetWhole() );
|
if (fracDigits == 0)
|
||||||
|
return wxsFormat(L"%d", GetWhole());
|
||||||
|
|
||||||
pxAssert( fracDigits <= 7 ); // higher numbers would just cause overflows and bad mojo.
|
pxAssert(fracDigits <= 7); // higher numbers would just cause overflows and bad mojo.
|
||||||
int mulby = (int)pow( 10.0, fracDigits );
|
int mulby = (int)pow(10.0, fracDigits);
|
||||||
wxString fmt=wxsFormat(L"%%d.%%0%dd", fracDigits);
|
wxString fmt = wxsFormat(L"%%d.%%0%dd", fracDigits);
|
||||||
return wxsFormat( fmt, GetWhole(), (GetFraction() * mulby) / Precision );
|
return wxsFormat(fmt, GetWhole(), (GetFraction() * mulby) / Precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
template< int Precision >
|
template <int Precision>
|
||||||
double FixedInt<Precision>::ToDouble() const
|
double FixedInt<Precision>::ToDouble() const
|
||||||
{
|
{
|
||||||
return ((double)Raw / (double)Precision);
|
return ((double)Raw / (double)Precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
template< int Precision >
|
template <int Precision>
|
||||||
float FixedInt<Precision>::ToFloat() const
|
float FixedInt<Precision>::ToFloat() const
|
||||||
{
|
{
|
||||||
return ((float)Raw / (float)Precision);
|
return ((float)Raw / (float)Precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
template< int Precision >
|
template <int Precision>
|
||||||
int FixedInt<Precision>::ToIntTruncated() const
|
int FixedInt<Precision>::ToIntTruncated() const
|
||||||
{
|
{
|
||||||
return Raw / Precision;
|
return Raw / Precision;
|
||||||
}
|
}
|
||||||
|
|
||||||
template< int Precision >
|
template <int Precision>
|
||||||
int FixedInt<Precision>::ToIntRounded() const
|
int FixedInt<Precision>::ToIntRounded() const
|
||||||
{
|
{
|
||||||
return (Raw + (Precision/2)) / Precision;
|
return (Raw + (Precision / 2)) / Precision;
|
||||||
}
|
}
|
||||||
|
|
||||||
template< int Precision >
|
template <int Precision>
|
||||||
bool FixedInt<Precision>::TryFromString( FixedInt<Precision>& dest, const wxString& parseFrom )
|
bool FixedInt<Precision>::TryFromString(FixedInt<Precision> &dest, const wxString &parseFrom)
|
||||||
{
|
{
|
||||||
long whole=0, frac=0;
|
long whole = 0, frac = 0;
|
||||||
const wxString beforeFirst( parseFrom.BeforeFirst( L'.' ) );
|
const wxString beforeFirst(parseFrom.BeforeFirst(L'.'));
|
||||||
const wxString afterFirst( parseFrom.AfterFirst( L'.' ).Mid(0, 5) );
|
const wxString afterFirst(parseFrom.AfterFirst(L'.').Mid(0, 5));
|
||||||
bool success = true;
|
bool success = true;
|
||||||
|
|
||||||
if( !beforeFirst.IsEmpty() )
|
if (!beforeFirst.IsEmpty())
|
||||||
success = success && beforeFirst.ToLong( &whole );
|
success = success && beforeFirst.ToLong(&whole);
|
||||||
|
|
||||||
if( !afterFirst.IsEmpty() )
|
if (!afterFirst.IsEmpty())
|
||||||
success = success && afterFirst.ToLong( &frac );
|
success = success && afterFirst.ToLong(&frac);
|
||||||
|
|
||||||
if( !success ) return false;
|
if (!success)
|
||||||
|
return false;
|
||||||
|
|
||||||
dest.SetWhole( whole );
|
dest.SetWhole(whole);
|
||||||
|
|
||||||
if( afterFirst.Length() != 0 && frac != 0 )
|
if (afterFirst.Length() != 0 && frac != 0) {
|
||||||
{
|
int fracPower = (int)pow(10.0, (int)afterFirst.Length());
|
||||||
int fracPower = (int)pow( 10.0, (int)afterFirst.Length() );
|
dest.SetFraction((frac * Precision) / fracPower);
|
||||||
dest.SetFraction( (frac * Precision) / fracPower );
|
}
|
||||||
}
|
return true;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template< int Precision >
|
template <int Precision>
|
||||||
FixedInt<Precision> FixedInt<Precision>::FromString( const wxString& parseFrom, const FixedInt<Precision>& defval )
|
FixedInt<Precision> FixedInt<Precision>::FromString(const wxString &parseFrom, const FixedInt<Precision> &defval)
|
||||||
{
|
{
|
||||||
FixedInt<Precision> dest;
|
FixedInt<Precision> dest;
|
||||||
if( !TryFromString( dest, parseFrom ) ) return defval;
|
if (!TryFromString(dest, parseFrom))
|
||||||
return dest;
|
return defval;
|
||||||
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This version of FromString throws a ParseError exception if the conversion fails.
|
// This version of FromString throws a ParseError exception if the conversion fails.
|
||||||
template< int Precision >
|
template <int Precision>
|
||||||
FixedInt<Precision> FixedInt<Precision>::FromString( const wxString parseFrom )
|
FixedInt<Precision> FixedInt<Precision>::FromString(const wxString parseFrom)
|
||||||
{
|
{
|
||||||
FixedInt<Precision> dest;
|
FixedInt<Precision> dest;
|
||||||
if( !TryFromString( dest, parseFrom ) ) throw Exception::ParseError()
|
if (!TryFromString(dest, parseFrom))
|
||||||
.SetDiagMsg(wxsFormat(L"Parse error on FixedInt<%d>::FromString", Precision));
|
throw Exception::ParseError()
|
||||||
|
.SetDiagMsg(wxsFormat(L"Parse error on FixedInt<%d>::FromString", Precision));
|
||||||
|
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,16 +17,22 @@
|
||||||
|
|
||||||
// This macro is actually useful for about any and every possible application of C++
|
// This macro is actually useful for about any and every possible application of C++
|
||||||
// equality operators.
|
// equality operators.
|
||||||
#define OpEqu( field ) (field == right.field)
|
#define OpEqu(field) (field == right.field)
|
||||||
|
|
||||||
// Macro used for removing some of the redtape involved in defining bitfield/union helpers.
|
// Macro used for removing some of the redtape involved in defining bitfield/union helpers.
|
||||||
//
|
//
|
||||||
#define BITFIELD32() \
|
#define BITFIELD32() \
|
||||||
union { \
|
union \
|
||||||
u32 bitset; \
|
{ \
|
||||||
struct {
|
u32 bitset; \
|
||||||
|
struct \
|
||||||
|
{
|
||||||
|
|
||||||
#define BITFIELD_END }; };
|
#define BITFIELD_END \
|
||||||
|
} \
|
||||||
|
; \
|
||||||
|
} \
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------------
|
||||||
|
@ -42,15 +48,20 @@
|
||||||
class RecursionGuard
|
class RecursionGuard
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
int& Counter;
|
int &Counter;
|
||||||
|
|
||||||
RecursionGuard( int& counter ) : Counter( counter )
|
RecursionGuard(int &counter)
|
||||||
{ ++Counter; }
|
: Counter(counter)
|
||||||
|
{
|
||||||
|
++Counter;
|
||||||
|
}
|
||||||
|
|
||||||
virtual ~RecursionGuard() throw()
|
virtual ~RecursionGuard() throw()
|
||||||
{ --Counter; }
|
{
|
||||||
|
--Counter;
|
||||||
|
}
|
||||||
|
|
||||||
bool IsReentrant() const { return Counter > 1; }
|
bool IsReentrant() const { return Counter > 1; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -59,30 +70,30 @@ public:
|
||||||
class IActionInvocation
|
class IActionInvocation
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~IActionInvocation() throw() {}
|
virtual ~IActionInvocation() throw() {}
|
||||||
virtual void InvokeAction()=0;
|
virtual void InvokeAction() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ICloneable
|
class ICloneable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ICloneable* Clone() const=0;
|
virtual ICloneable *Clone() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class IDeletableObject
|
class IDeletableObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~IDeletableObject() throw() {}
|
virtual ~IDeletableObject() throw() {}
|
||||||
|
|
||||||
virtual void DeleteSelf()=0;
|
virtual void DeleteSelf() = 0;
|
||||||
virtual bool IsBeingDeleted()=0;
|
virtual bool IsBeingDeleted() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// This function is GUI implementation dependent! It's implemented by PCSX2's AppHost,
|
// This function is GUI implementation dependent! It's implemented by PCSX2's AppHost,
|
||||||
// but if the SysCore is being linked to another front end, you'll need to implement this
|
// but if the SysCore is being linked to another front end, you'll need to implement this
|
||||||
// yourself. Most GUIs have built in message pumps. If a platform lacks one then you'll
|
// yourself. Most GUIs have built in message pumps. If a platform lacks one then you'll
|
||||||
// need to implement one yourself (yay?).
|
// need to implement one yourself (yay?).
|
||||||
virtual void DoDeletion()=0;
|
virtual void DoDeletion() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -111,26 +122,26 @@ protected:
|
||||||
class BaseDeletableObject : public virtual IDeletableObject
|
class BaseDeletableObject : public virtual IDeletableObject
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
std::atomic<bool> m_IsBeingDeleted;
|
std::atomic<bool> m_IsBeingDeleted;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BaseDeletableObject();
|
BaseDeletableObject();
|
||||||
virtual ~BaseDeletableObject() throw();
|
virtual ~BaseDeletableObject() throw();
|
||||||
|
|
||||||
void DeleteSelf();
|
void DeleteSelf();
|
||||||
bool IsBeingDeleted() { return !!m_IsBeingDeleted; }
|
bool IsBeingDeleted() { return !!m_IsBeingDeleted; }
|
||||||
|
|
||||||
// Returns FALSE if the object is already marked for deletion, or TRUE if the app
|
// Returns FALSE if the object is already marked for deletion, or TRUE if the app
|
||||||
// should schedule the object for deletion. Only schedule if TRUE is returned, otherwise
|
// should schedule the object for deletion. Only schedule if TRUE is returned, otherwise
|
||||||
// the object could get deleted twice if two threads try to schedule it at the same time.
|
// the object could get deleted twice if two threads try to schedule it at the same time.
|
||||||
bool MarkForDeletion();
|
bool MarkForDeletion();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// This function is GUI implementation dependent! It's implemented by PCSX2's AppHost,
|
// This function is GUI implementation dependent! It's implemented by PCSX2's AppHost,
|
||||||
// but if the SysCore is being linked to another front end, you'll need to implement this
|
// but if the SysCore is being linked to another front end, you'll need to implement this
|
||||||
// yourself. Most GUIs have built in message pumps. If a platform lacks one then you'll
|
// yourself. Most GUIs have built in message pumps. If a platform lacks one then you'll
|
||||||
// need to implement one yourself (yay?).
|
// need to implement one yourself (yay?).
|
||||||
virtual void DoDeletion();
|
virtual void DoDeletion();
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -139,76 +150,76 @@ protected:
|
||||||
class PageProtectionMode
|
class PageProtectionMode
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
bool m_read;
|
bool m_read;
|
||||||
bool m_write;
|
bool m_write;
|
||||||
bool m_exec;
|
bool m_exec;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PageProtectionMode()
|
PageProtectionMode()
|
||||||
{
|
{
|
||||||
All( false );
|
All(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
PageProtectionMode& Read( bool allow=true )
|
PageProtectionMode &Read(bool allow = true)
|
||||||
{
|
{
|
||||||
m_read = allow;
|
m_read = allow;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
PageProtectionMode& Write( bool allow=true )
|
PageProtectionMode &Write(bool allow = true)
|
||||||
{
|
{
|
||||||
m_write = allow;
|
m_write = allow;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
PageProtectionMode& Execute( bool allow=true )
|
PageProtectionMode &Execute(bool allow = true)
|
||||||
{
|
{
|
||||||
m_exec = allow;
|
m_exec = allow;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
PageProtectionMode& All( bool allow=true )
|
|
||||||
{
|
|
||||||
m_read = m_write = m_exec = allow;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CanRead() const { return m_read; }
|
PageProtectionMode &All(bool allow = true)
|
||||||
bool CanWrite() const { return m_write; }
|
{
|
||||||
bool CanExecute() const { return m_exec && m_read; }
|
m_read = m_write = m_exec = allow;
|
||||||
bool IsNone() const { return !m_read && !m_write; }
|
return *this;
|
||||||
|
}
|
||||||
wxString ToString() const;
|
|
||||||
|
bool CanRead() const { return m_read; }
|
||||||
|
bool CanWrite() const { return m_write; }
|
||||||
|
bool CanExecute() const { return m_exec && m_read; }
|
||||||
|
bool IsNone() const { return !m_read && !m_write; }
|
||||||
|
|
||||||
|
wxString ToString() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
static __fi PageProtectionMode PageAccess_None()
|
static __fi PageProtectionMode PageAccess_None()
|
||||||
{
|
{
|
||||||
return PageProtectionMode();
|
return PageProtectionMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
static __fi PageProtectionMode PageAccess_ReadOnly()
|
static __fi PageProtectionMode PageAccess_ReadOnly()
|
||||||
{
|
{
|
||||||
return PageProtectionMode().Read();
|
return PageProtectionMode().Read();
|
||||||
}
|
}
|
||||||
|
|
||||||
static __fi PageProtectionMode PageAccess_WriteOnly()
|
static __fi PageProtectionMode PageAccess_WriteOnly()
|
||||||
{
|
{
|
||||||
return PageProtectionMode().Write();
|
return PageProtectionMode().Write();
|
||||||
}
|
}
|
||||||
|
|
||||||
static __fi PageProtectionMode PageAccess_ReadWrite()
|
static __fi PageProtectionMode PageAccess_ReadWrite()
|
||||||
{
|
{
|
||||||
return PageAccess_ReadOnly().Write();
|
return PageAccess_ReadOnly().Write();
|
||||||
}
|
}
|
||||||
|
|
||||||
static __fi PageProtectionMode PageAccess_ExecOnly()
|
static __fi PageProtectionMode PageAccess_ExecOnly()
|
||||||
{
|
{
|
||||||
return PageAccess_ReadOnly().Execute();
|
return PageAccess_ReadOnly().Execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
static __fi PageProtectionMode PageAccess_Any()
|
static __fi PageProtectionMode PageAccess_Any()
|
||||||
{
|
{
|
||||||
return PageProtectionMode().All();
|
return PageProtectionMode().All();
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -218,39 +229,39 @@ static __fi PageProtectionMode PageAccess_Any()
|
||||||
// platform prior to wxWidgets .. it should prolly be removed -- air)
|
// platform prior to wxWidgets .. it should prolly be removed -- air)
|
||||||
namespace HostSys
|
namespace HostSys
|
||||||
{
|
{
|
||||||
void* MmapReserve(uptr base, size_t size);
|
void *MmapReserve(uptr base, size_t size);
|
||||||
bool MmapCommit(uptr base, size_t size, const PageProtectionMode& mode);
|
bool MmapCommit(uptr base, size_t size, const PageProtectionMode &mode);
|
||||||
void MmapReset(uptr base, size_t size);
|
void MmapReset(uptr base, size_t size);
|
||||||
|
|
||||||
void* MmapReservePtr(void* base, size_t size);
|
void *MmapReservePtr(void *base, size_t size);
|
||||||
bool MmapCommitPtr(void* base, size_t size, const PageProtectionMode& mode);
|
bool MmapCommitPtr(void *base, size_t size, const PageProtectionMode &mode);
|
||||||
void MmapResetPtr(void* base, size_t size);
|
void MmapResetPtr(void *base, size_t size);
|
||||||
|
|
||||||
// Maps a block of memory for use as a recompiled code buffer.
|
// Maps a block of memory for use as a recompiled code buffer.
|
||||||
// Returns NULL on allocation failure.
|
// Returns NULL on allocation failure.
|
||||||
extern void* Mmap(uptr base, size_t size);
|
extern void *Mmap(uptr base, size_t size);
|
||||||
|
|
||||||
// Unmaps a block allocated by SysMmap
|
// Unmaps a block allocated by SysMmap
|
||||||
extern void Munmap(uptr base, size_t size);
|
extern void Munmap(uptr base, size_t size);
|
||||||
|
|
||||||
extern void MemProtect( void* baseaddr, size_t size, const PageProtectionMode& mode );
|
extern void MemProtect(void *baseaddr, size_t size, const PageProtectionMode &mode);
|
||||||
|
|
||||||
extern void Munmap( void* base, size_t size );
|
extern void Munmap(void *base, size_t size);
|
||||||
|
|
||||||
template< uint size >
|
template <uint size>
|
||||||
void MemProtectStatic( u8 (&arr)[size], const PageProtectionMode& mode )
|
void MemProtectStatic(u8 (&arr)[size], const PageProtectionMode &mode)
|
||||||
{
|
{
|
||||||
MemProtect( arr, size, mode );
|
MemProtect(arr, size, mode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Safe version of Munmap -- NULLs the pointer variable immediately after free'ing it.
|
// Safe version of Munmap -- NULLs the pointer variable immediately after free'ing it.
|
||||||
#define SafeSysMunmap( ptr, size ) \
|
#define SafeSysMunmap(ptr, size) \
|
||||||
((void) ( HostSys::Munmap( (uptr)(ptr), size ), (ptr) = NULL ))
|
((void)(HostSys::Munmap((uptr)(ptr), size), (ptr) = NULL))
|
||||||
|
|
||||||
extern void InitCPUTicks();
|
extern void InitCPUTicks();
|
||||||
extern u64 GetTickFrequency();
|
extern u64 GetTickFrequency();
|
||||||
extern u64 GetCPUTicks();
|
extern u64 GetCPUTicks();
|
||||||
extern u64 GetPhysicalMemory();
|
extern u64 GetPhysicalMemory();
|
||||||
|
|
||||||
extern wxString GetOSVersionString();
|
extern wxString GetOSVersionString();
|
||||||
|
|
|
@ -15,7 +15,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace HashTools {
|
namespace HashTools
|
||||||
|
{
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Type that represents a hashcode; returned by all hash functions.
|
/// Type that represents a hashcode; returned by all hash functions.
|
||||||
|
@ -26,7 +27,5 @@ namespace HashTools {
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
typedef u32 hash_key_t;
|
typedef u32 hash_key_t;
|
||||||
|
|
||||||
hash_key_t Hash(const char* data, int len);
|
hash_key_t Hash(const char *data, int len);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#include <wx/gdicmn.h>
|
#include <wx/gdicmn.h>
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// IniInterface (abstract base class)
|
// IniInterface (abstract base class)
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// This is used as an interchangable interface for both loading and saving options from an
|
// This is used as an interchangable interface for both loading and saving options from an
|
||||||
// ini/configuration file. The LoadSave code takes an IniInterface, and the interface
|
// ini/configuration file. The LoadSave code takes an IniInterface, and the interface
|
||||||
|
@ -32,53 +32,57 @@
|
||||||
class IniInterface
|
class IniInterface
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
wxConfigBase* m_Config;
|
wxConfigBase *m_Config;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~IniInterface();
|
virtual ~IniInterface();
|
||||||
explicit IniInterface();
|
explicit IniInterface();
|
||||||
explicit IniInterface( wxConfigBase& config );
|
explicit IniInterface(wxConfigBase &config);
|
||||||
explicit IniInterface( wxConfigBase* config );
|
explicit IniInterface(wxConfigBase *config);
|
||||||
|
|
||||||
void SetPath( const wxString& path );
|
void SetPath(const wxString &path);
|
||||||
void Flush();
|
void Flush();
|
||||||
|
|
||||||
wxConfigBase& GetConfig() { pxAssert( m_Config ); return *m_Config; }
|
wxConfigBase &GetConfig()
|
||||||
bool IsOk() const { return m_Config != NULL; }
|
{
|
||||||
|
pxAssert(m_Config);
|
||||||
|
return *m_Config;
|
||||||
|
}
|
||||||
|
bool IsOk() const { return m_Config != NULL; }
|
||||||
|
|
||||||
virtual bool IsLoading() const=0;
|
virtual bool IsLoading() const = 0;
|
||||||
bool IsSaving() const { return !IsLoading(); }
|
bool IsSaving() const { return !IsLoading(); }
|
||||||
|
|
||||||
virtual void Entry( const wxString& var, wxString& value, const wxString defvalue=wxString() )=0;
|
virtual void Entry(const wxString &var, wxString &value, const wxString defvalue = wxString()) = 0;
|
||||||
virtual void Entry( const wxString& var, wxDirName& value, const wxDirName defvalue=wxDirName(), bool isAllowRelative=false )=0;
|
virtual void Entry(const wxString &var, wxDirName &value, const wxDirName defvalue = wxDirName(), bool isAllowRelative = false) = 0;
|
||||||
virtual void Entry( const wxString& var, wxFileName& value, const wxFileName defvalue=wxFileName(), bool isAllowRelative=false )=0;
|
virtual void Entry(const wxString &var, wxFileName &value, const wxFileName defvalue = wxFileName(), bool isAllowRelative = false) = 0;
|
||||||
virtual void Entry( const wxString& var, int& value, const int defvalue=0 )=0;
|
virtual void Entry(const wxString &var, int &value, const int defvalue = 0) = 0;
|
||||||
virtual void Entry( const wxString& var, uint& value, const uint defvalue=0 )=0;
|
virtual void Entry(const wxString &var, uint &value, const uint defvalue = 0) = 0;
|
||||||
virtual void Entry( const wxString& var, bool& value, const bool defvalue=false )=0;
|
virtual void Entry(const wxString &var, bool &value, const bool defvalue = false) = 0;
|
||||||
|
|
||||||
// This special form of Entry is provided for bitfields, which cannot be passed by reference.
|
// This special form of Entry is provided for bitfields, which cannot be passed by reference.
|
||||||
virtual bool EntryBitBool( const wxString& var, bool value, const bool defvalue=false )=0;
|
virtual bool EntryBitBool(const wxString &var, bool value, const bool defvalue = false) = 0;
|
||||||
virtual int EntryBitfield( const wxString& var, int value, const int defvalue=0 )=0;
|
virtual int EntryBitfield(const wxString &var, int value, const int defvalue = 0) = 0;
|
||||||
|
|
||||||
virtual void Entry( const wxString& var, Fixed100& value, const Fixed100 defvalue=Fixed100() )=0;
|
virtual void Entry(const wxString &var, Fixed100 &value, const Fixed100 defvalue = Fixed100()) = 0;
|
||||||
|
|
||||||
virtual void Entry( const wxString& var, wxPoint& value, const wxPoint defvalue=wxDefaultPosition )=0;
|
virtual void Entry(const wxString &var, wxPoint &value, const wxPoint defvalue = wxDefaultPosition) = 0;
|
||||||
virtual void Entry( const wxString& var, wxSize& value, const wxSize defvalue=wxDefaultSize )=0;
|
virtual void Entry(const wxString &var, wxSize &value, const wxSize defvalue = wxDefaultSize) = 0;
|
||||||
virtual void Entry( const wxString& var, wxRect& value, const wxRect defvalue=wxDefaultRect )=0;
|
virtual void Entry(const wxString &var, wxRect &value, const wxRect defvalue = wxDefaultRect) = 0;
|
||||||
|
|
||||||
template< typename T >
|
template <typename T>
|
||||||
void EnumEntry( const wxString& var, T& value, const wxChar* const* enumArray=NULL, const T defvalue=(T)0 )
|
void EnumEntry(const wxString &var, T &value, const wxChar *const *enumArray = NULL, const T defvalue = (T)0)
|
||||||
{
|
{
|
||||||
int tstore = (int)value;
|
int tstore = (int)value;
|
||||||
if( enumArray == NULL )
|
if (enumArray == NULL)
|
||||||
Entry( var, tstore, defvalue );
|
Entry(var, tstore, defvalue);
|
||||||
else
|
else
|
||||||
_EnumEntry( var, tstore, enumArray, defvalue );
|
_EnumEntry(var, tstore, enumArray, defvalue);
|
||||||
value = (T)tstore;
|
value = (T)tstore;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void _EnumEntry( const wxString& var, int& value, const wxChar* const* enumArray, int defvalue )=0;
|
virtual void _EnumEntry(const wxString &var, int &value, const wxChar *const *enumArray, int defvalue) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -87,11 +91,11 @@ protected:
|
||||||
class ScopedIniGroup
|
class ScopedIniGroup
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
IniInterface& m_mom;
|
IniInterface &m_mom;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ScopedIniGroup( IniInterface& mommy, const wxString& group );
|
ScopedIniGroup(IniInterface &mommy, const wxString &group);
|
||||||
virtual ~ScopedIniGroup();
|
virtual ~ScopedIniGroup();
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -105,31 +109,31 @@ public:
|
||||||
class IniLoader : public IniInterface
|
class IniLoader : public IniInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~IniLoader() throw();
|
virtual ~IniLoader() throw();
|
||||||
explicit IniLoader();
|
explicit IniLoader();
|
||||||
explicit IniLoader( wxConfigBase& config );
|
explicit IniLoader(wxConfigBase &config);
|
||||||
explicit IniLoader( wxConfigBase* config );
|
explicit IniLoader(wxConfigBase *config);
|
||||||
|
|
||||||
bool IsLoading() const { return true; }
|
bool IsLoading() const { return true; }
|
||||||
|
|
||||||
void Entry( const wxString& var, wxString& value, const wxString defvalue=wxEmptyString );
|
void Entry(const wxString &var, wxString &value, const wxString defvalue = wxEmptyString);
|
||||||
void Entry( const wxString& var, wxDirName& value, const wxDirName defvalue=wxDirName(), bool isAllowRelative=false );
|
void Entry(const wxString &var, wxDirName &value, const wxDirName defvalue = wxDirName(), bool isAllowRelative = false);
|
||||||
void Entry( const wxString& var, wxFileName& value, const wxFileName defvalue=wxFileName(), bool isAllowRelative=false );
|
void Entry(const wxString &var, wxFileName &value, const wxFileName defvalue = wxFileName(), bool isAllowRelative = false);
|
||||||
void Entry( const wxString& var, int& value, const int defvalue=0 );
|
void Entry(const wxString &var, int &value, const int defvalue = 0);
|
||||||
void Entry( const wxString& var, uint& value, const uint defvalue=0 );
|
void Entry(const wxString &var, uint &value, const uint defvalue = 0);
|
||||||
void Entry( const wxString& var, bool& value, const bool defvalue=false );
|
void Entry(const wxString &var, bool &value, const bool defvalue = false);
|
||||||
|
|
||||||
bool EntryBitBool( const wxString& var, bool value, const bool defvalue=false );
|
bool EntryBitBool(const wxString &var, bool value, const bool defvalue = false);
|
||||||
int EntryBitfield( const wxString& var, int value, const int defvalue=0 );
|
int EntryBitfield(const wxString &var, int value, const int defvalue = 0);
|
||||||
|
|
||||||
void Entry( const wxString& var, Fixed100& value, const Fixed100 defvalue=Fixed100() );
|
void Entry(const wxString &var, Fixed100 &value, const Fixed100 defvalue = Fixed100());
|
||||||
|
|
||||||
void Entry( const wxString& var, wxPoint& value, const wxPoint defvalue=wxDefaultPosition );
|
void Entry(const wxString &var, wxPoint &value, const wxPoint defvalue = wxDefaultPosition);
|
||||||
void Entry( const wxString& var, wxSize& value, const wxSize defvalue=wxDefaultSize );
|
void Entry(const wxString &var, wxSize &value, const wxSize defvalue = wxDefaultSize);
|
||||||
void Entry( const wxString& var, wxRect& value, const wxRect defvalue=wxDefaultRect );
|
void Entry(const wxString &var, wxRect &value, const wxRect defvalue = wxDefaultRect);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _EnumEntry( const wxString& var, int& value, const wxChar* const* enumArray, int defvalue );
|
void _EnumEntry(const wxString &var, int &value, const wxChar *const *enumArray, int defvalue);
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -143,45 +147,45 @@ protected:
|
||||||
class IniSaver : public IniInterface
|
class IniSaver : public IniInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~IniSaver();
|
virtual ~IniSaver();
|
||||||
explicit IniSaver();
|
explicit IniSaver();
|
||||||
explicit IniSaver( wxConfigBase& config );
|
explicit IniSaver(wxConfigBase &config);
|
||||||
explicit IniSaver( wxConfigBase* config );
|
explicit IniSaver(wxConfigBase *config);
|
||||||
|
|
||||||
bool IsLoading() const { return false; }
|
bool IsLoading() const { return false; }
|
||||||
|
|
||||||
void Entry( const wxString& var, wxString& value, const wxString defvalue=wxString() );
|
void Entry(const wxString &var, wxString &value, const wxString defvalue = wxString());
|
||||||
void Entry( const wxString& var, wxDirName& value, const wxDirName defvalue=wxDirName(), bool isAllowRelative=false );
|
void Entry(const wxString &var, wxDirName &value, const wxDirName defvalue = wxDirName(), bool isAllowRelative = false);
|
||||||
void Entry( const wxString& var, wxFileName& value, const wxFileName defvalue=wxFileName(), bool isAllowRelative=false );
|
void Entry(const wxString &var, wxFileName &value, const wxFileName defvalue = wxFileName(), bool isAllowRelative = false);
|
||||||
void Entry( const wxString& var, int& value, const int defvalue=0 );
|
void Entry(const wxString &var, int &value, const int defvalue = 0);
|
||||||
void Entry( const wxString& var, uint& value, const uint defvalue=0 );
|
void Entry(const wxString &var, uint &value, const uint defvalue = 0);
|
||||||
void Entry( const wxString& var, bool& value, const bool defvalue=false );
|
void Entry(const wxString &var, bool &value, const bool defvalue = false);
|
||||||
|
|
||||||
bool EntryBitBool( const wxString& var, bool value, const bool defvalue=false );
|
bool EntryBitBool(const wxString &var, bool value, const bool defvalue = false);
|
||||||
int EntryBitfield( const wxString& var, int value, const int defvalue=0 );
|
int EntryBitfield(const wxString &var, int value, const int defvalue = 0);
|
||||||
|
|
||||||
void Entry( const wxString& var, Fixed100& value, const Fixed100 defvalue=Fixed100() );
|
void Entry(const wxString &var, Fixed100 &value, const Fixed100 defvalue = Fixed100());
|
||||||
|
|
||||||
void Entry( const wxString& var, wxPoint& value, const wxPoint defvalue=wxDefaultPosition );
|
void Entry(const wxString &var, wxPoint &value, const wxPoint defvalue = wxDefaultPosition);
|
||||||
void Entry( const wxString& var, wxSize& value, const wxSize defvalue=wxDefaultSize );
|
void Entry(const wxString &var, wxSize &value, const wxSize defvalue = wxDefaultSize);
|
||||||
void Entry( const wxString& var, wxRect& value, const wxRect defvalue=wxDefaultRect );
|
void Entry(const wxString &var, wxRect &value, const wxRect defvalue = wxDefaultRect);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _EnumEntry( const wxString& var, int& value, const wxChar* const* enumArray, int defvalue );
|
void _EnumEntry(const wxString &var, int &value, const wxChar *const *enumArray, int defvalue);
|
||||||
};
|
};
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// GCC Note: wxT() macro is required when using string token pasting. For some reason L generates
|
// GCC Note: wxT() macro is required when using string token pasting. For some reason L generates
|
||||||
// syntax errors. >_<
|
// syntax errors. >_<
|
||||||
//
|
//
|
||||||
#define IniEntry( varname ) ini.Entry( wxT(#varname), varname, varname )
|
#define IniEntry(varname) ini.Entry(wxT(#varname), varname, varname)
|
||||||
#define IniEntryDirFile( varname, isAllowRelative ) ini.Entry( wxT(#varname), varname, varname, isAllowRelative )
|
#define IniEntryDirFile(varname, isAllowRelative) ini.Entry(wxT(#varname), varname, varname, isAllowRelative)
|
||||||
#define IniBitfield( varname ) varname = ini.EntryBitfield( wxT(#varname), varname, varname )
|
#define IniBitfield(varname) varname = ini.EntryBitfield(wxT(#varname), varname, varname)
|
||||||
#define IniBitBool( varname ) varname = ini.EntryBitBool( wxT(#varname), !!varname, varname )
|
#define IniBitBool(varname) varname = ini.EntryBitBool(wxT(#varname), !!varname, varname)
|
||||||
|
|
||||||
#define IniBitfieldEx( varname, textname ) varname = ini.EntryBitfield( wxT(textname), varname, varname )
|
#define IniBitfieldEx(varname, textname) varname = ini.EntryBitfield(wxT(textname), varname, varname)
|
||||||
#define IniBitBoolEx( varname, textname ) varname = ini.EntryBitBool( wxT(textname), !!varname, varname )
|
#define IniBitBoolEx(varname, textname) varname = ini.EntryBitBool(wxT(textname), !!varname, varname)
|
||||||
|
|
||||||
//used for filenames and folder names as ini values.
|
//used for filenames and folder names as ini values.
|
||||||
//Set to app root folder, so all files and folders which are inside appRoot will be written as relative.
|
//Set to app root folder, so all files and folders which are inside appRoot will be written as relative.
|
||||||
void SetFullBaseDir( wxDirName appRoot );
|
void SetFullBaseDir(wxDirName appRoot);
|
||||||
|
|
|
@ -20,22 +20,22 @@
|
||||||
#include "Pcsx2Defs.h"
|
#include "Pcsx2Defs.h"
|
||||||
|
|
||||||
// On GCC >= 4.7, this is equivalent to __builtin_clrsb(n);
|
// On GCC >= 4.7, this is equivalent to __builtin_clrsb(n);
|
||||||
inline u32 count_leading_sign_bits(s32 n) {
|
inline u32 count_leading_sign_bits(s32 n)
|
||||||
// If the sign bit is 1, we invert the bits to 0 for count-leading-zero.
|
{
|
||||||
if (n < 0)
|
// If the sign bit is 1, we invert the bits to 0 for count-leading-zero.
|
||||||
n = ~n;
|
if (n < 0)
|
||||||
|
n = ~n;
|
||||||
|
|
||||||
// If BSR is used directly, it would have an undefined value for 0.
|
// If BSR is used directly, it would have an undefined value for 0.
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
return 32;
|
return 32;
|
||||||
|
|
||||||
// Perform our count leading zero.
|
// Perform our count leading zero.
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
unsigned long ret;
|
unsigned long ret;
|
||||||
_BitScanReverse(&ret, n);
|
_BitScanReverse(&ret, n);
|
||||||
return 31 - (u32)ret;
|
return 31 - (u32)ret;
|
||||||
#else
|
#else
|
||||||
return __builtin_clz(n);
|
return __builtin_clz(n);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,15 +16,15 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#if defined(__POSIX__)
|
#if defined(__POSIX__)
|
||||||
# include "lnx_memzero.h"
|
#include "lnx_memzero.h"
|
||||||
#else
|
#else
|
||||||
# include "win_memzero.h"
|
#include "win_memzero.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// For 32-bit MSVC compiles, memcmp performs much worse than memcmp_mmx and
|
// For 32-bit MSVC compiles, memcmp performs much worse than memcmp_mmx and
|
||||||
// other implementations. So for this combination only, prefer memcmp_mmx
|
// other implementations. So for this combination only, prefer memcmp_mmx
|
||||||
#if defined(_MSC_VER) && !defined(_M_X86_64)
|
#if defined(_MSC_VER) && !defined(_M_X86_64)
|
||||||
extern u8 memcmp_mmx(const void* src1, const void* src2, int cmpsize);
|
extern u8 memcmp_mmx(const void *src1, const void *src2, int cmpsize);
|
||||||
#else
|
#else
|
||||||
#define memcmp_mmx memcmp
|
#define memcmp_mmx memcmp
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -17,69 +17,67 @@
|
||||||
|
|
||||||
#include <xmmintrin.h>
|
#include <xmmintrin.h>
|
||||||
|
|
||||||
#define StoreDestIdx(idx) case idx: _mm_store_ps(&destxmm[idx-1][0], srcreg)
|
#define StoreDestIdx(idx) \
|
||||||
|
case idx: \
|
||||||
template< u8 data >
|
_mm_store_ps(&destxmm[idx - 1][0], srcreg)
|
||||||
__noinline void memset_sse_a( void* dest, const size_t size )
|
|
||||||
|
template <u8 data>
|
||||||
|
__noinline void memset_sse_a(void *dest, const size_t size)
|
||||||
{
|
{
|
||||||
const uint MZFqwc = size / 16;
|
const uint MZFqwc = size / 16;
|
||||||
|
|
||||||
pxAssert( (size & 0xf) == 0 );
|
pxAssert((size & 0xf) == 0);
|
||||||
|
|
||||||
__m128 srcreg;
|
__m128 srcreg;
|
||||||
|
|
||||||
if (data != 0)
|
if (data != 0) {
|
||||||
{
|
static __aligned16 const u8 loadval[8] = {data, data, data, data, data, data, data, data};
|
||||||
static __aligned16 const u8 loadval[8] = { data,data,data,data,data,data,data,data };
|
srcreg = _mm_loadh_pi(_mm_load_ps((float *)loadval), (__m64 *)loadval);
|
||||||
srcreg = _mm_loadh_pi( _mm_load_ps( (float*)loadval ), (__m64*)loadval );
|
} else
|
||||||
}
|
srcreg = _mm_setzero_ps();
|
||||||
else
|
|
||||||
srcreg = _mm_setzero_ps();
|
|
||||||
|
|
||||||
float (*destxmm)[4] = (float(*)[4])dest;
|
float(*destxmm)[4] = (float(*)[4])dest;
|
||||||
|
|
||||||
switch( MZFqwc & 0x07 )
|
switch (MZFqwc & 0x07) {
|
||||||
{
|
StoreDestIdx(0x07);
|
||||||
StoreDestIdx(0x07);
|
StoreDestIdx(0x06);
|
||||||
StoreDestIdx(0x06);
|
StoreDestIdx(0x05);
|
||||||
StoreDestIdx(0x05);
|
StoreDestIdx(0x04);
|
||||||
StoreDestIdx(0x04);
|
StoreDestIdx(0x03);
|
||||||
StoreDestIdx(0x03);
|
StoreDestIdx(0x02);
|
||||||
StoreDestIdx(0x02);
|
StoreDestIdx(0x01);
|
||||||
StoreDestIdx(0x01);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
destxmm += (MZFqwc & 0x07);
|
destxmm += (MZFqwc & 0x07);
|
||||||
for( uint i=0; i<MZFqwc / 8; ++i, destxmm+=8 )
|
for (uint i = 0; i < MZFqwc / 8; ++i, destxmm += 8) {
|
||||||
{
|
_mm_store_ps(&destxmm[0][0], srcreg);
|
||||||
_mm_store_ps(&destxmm[0][0], srcreg);
|
_mm_store_ps(&destxmm[1][0], srcreg);
|
||||||
_mm_store_ps(&destxmm[1][0], srcreg);
|
_mm_store_ps(&destxmm[2][0], srcreg);
|
||||||
_mm_store_ps(&destxmm[2][0], srcreg);
|
_mm_store_ps(&destxmm[3][0], srcreg);
|
||||||
_mm_store_ps(&destxmm[3][0], srcreg);
|
_mm_store_ps(&destxmm[4][0], srcreg);
|
||||||
_mm_store_ps(&destxmm[4][0], srcreg);
|
_mm_store_ps(&destxmm[5][0], srcreg);
|
||||||
_mm_store_ps(&destxmm[5][0], srcreg);
|
_mm_store_ps(&destxmm[6][0], srcreg);
|
||||||
_mm_store_ps(&destxmm[6][0], srcreg);
|
_mm_store_ps(&destxmm[7][0], srcreg);
|
||||||
_mm_store_ps(&destxmm[7][0], srcreg);
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static __fi void memzero_sse_a( void* dest, const size_t size )
|
static __fi void memzero_sse_a(void *dest, const size_t size)
|
||||||
{
|
{
|
||||||
memset_sse_a<0>( dest, size );
|
memset_sse_a<0>(dest, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef StoreDestIdx
|
#undef StoreDestIdx
|
||||||
|
|
||||||
template< u8 data, typename T >
|
template <u8 data, typename T>
|
||||||
__noinline void memset_sse_a( T& dest )
|
__noinline void memset_sse_a(T &dest)
|
||||||
{
|
{
|
||||||
static_assert( (sizeof(dest) & 0xf) == 0, "Bad size for SSE memset" );
|
static_assert((sizeof(dest) & 0xf) == 0, "Bad size for SSE memset");
|
||||||
memset_sse_a<data>( &dest, sizeof(dest) );
|
memset_sse_a<data>(&dest, sizeof(dest));
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template <typename T>
|
||||||
void memzero_sse_a( T& dest )
|
void memzero_sse_a(T &dest)
|
||||||
{
|
{
|
||||||
static_assert( (sizeof(dest) & 0xf) == 0, "Bad size for SSE memset" );
|
static_assert((sizeof(dest) & 0xf) == 0, "Bad size for SSE memset");
|
||||||
memset_sse_a<0>( &dest, sizeof(dest) );
|
memset_sse_a<0>(&dest, sizeof(dest));
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,12 +28,12 @@
|
||||||
|
|
||||||
struct PageFaultInfo
|
struct PageFaultInfo
|
||||||
{
|
{
|
||||||
uptr addr;
|
uptr addr;
|
||||||
|
|
||||||
PageFaultInfo( uptr address )
|
PageFaultInfo(uptr address)
|
||||||
{
|
{
|
||||||
addr = address;
|
addr = address;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -42,22 +42,22 @@ struct PageFaultInfo
|
||||||
class IEventListener_PageFault : public IEventDispatcher<PageFaultInfo>
|
class IEventListener_PageFault : public IEventDispatcher<PageFaultInfo>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef PageFaultInfo EvtParams;
|
typedef PageFaultInfo EvtParams;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~IEventListener_PageFault() throw() {}
|
virtual ~IEventListener_PageFault() throw() {}
|
||||||
|
|
||||||
virtual void DispatchEvent( const PageFaultInfo& evtinfo, bool& handled )
|
virtual void DispatchEvent(const PageFaultInfo &evtinfo, bool &handled)
|
||||||
{
|
{
|
||||||
OnPageFaultEvent( evtinfo, handled );
|
OnPageFaultEvent(evtinfo, handled);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void DispatchEvent( const PageFaultInfo& evtinfo )
|
virtual void DispatchEvent(const PageFaultInfo &evtinfo)
|
||||||
{
|
{
|
||||||
pxFailRel( "Don't call me, damnit. Use DispatchException instead." );
|
pxFailRel("Don't call me, damnit. Use DispatchException instead.");
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void OnPageFaultEvent( const PageFaultInfo& evtinfo, bool& handled ) {}
|
virtual void OnPageFaultEvent(const PageFaultInfo &evtinfo, bool &handled) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -66,35 +66,34 @@ public:
|
||||||
class EventListener_PageFault : public IEventListener_PageFault
|
class EventListener_PageFault : public IEventListener_PageFault
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
EventListener_PageFault();
|
EventListener_PageFault();
|
||||||
virtual ~EventListener_PageFault() throw();
|
virtual ~EventListener_PageFault() throw();
|
||||||
};
|
};
|
||||||
|
|
||||||
template< typename TypeToDispatchTo >
|
template <typename TypeToDispatchTo>
|
||||||
class EventListenerHelper_PageFault : public EventListener_PageFault
|
class EventListenerHelper_PageFault : public EventListener_PageFault
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TypeToDispatchTo* Owner;
|
TypeToDispatchTo *Owner;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
EventListenerHelper_PageFault( TypeToDispatchTo& dispatchTo )
|
EventListenerHelper_PageFault(TypeToDispatchTo &dispatchTo)
|
||||||
{
|
{
|
||||||
Owner = &dispatchTo;
|
Owner = &dispatchTo;
|
||||||
}
|
}
|
||||||
|
|
||||||
EventListenerHelper_PageFault( TypeToDispatchTo* dispatchTo )
|
EventListenerHelper_PageFault(TypeToDispatchTo *dispatchTo)
|
||||||
{
|
{
|
||||||
Owner = dispatchTo;
|
Owner = dispatchTo;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~EventListenerHelper_PageFault() throw() {}
|
virtual ~EventListenerHelper_PageFault() throw() {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void OnPageFaultEvent( const PageFaultInfo& info, bool& handled )
|
virtual void OnPageFaultEvent(const PageFaultInfo &info, bool &handled)
|
||||||
{
|
{
|
||||||
Owner->OnPageFaultEvent( info, handled );
|
Owner->OnPageFaultEvent(info, handled);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -103,20 +102,23 @@ protected:
|
||||||
class SrcType_PageFault : public EventSource<IEventListener_PageFault>
|
class SrcType_PageFault : public EventSource<IEventListener_PageFault>
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
typedef EventSource<IEventListener_PageFault> _parent;
|
typedef EventSource<IEventListener_PageFault> _parent;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool m_handled;
|
bool m_handled;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SrcType_PageFault() : m_handled(false) {}
|
SrcType_PageFault()
|
||||||
virtual ~SrcType_PageFault() throw() { }
|
: m_handled(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
virtual ~SrcType_PageFault() throw() {}
|
||||||
|
|
||||||
bool WasHandled() const { return m_handled; }
|
bool WasHandled() const { return m_handled; }
|
||||||
virtual void Dispatch( const PageFaultInfo& params );
|
virtual void Dispatch(const PageFaultInfo ¶ms);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void _DispatchRaw( ListenerIterator iter, const ListenerIterator& iend, const PageFaultInfo& evt );
|
virtual void _DispatchRaw(ListenerIterator iter, const ListenerIterator &iend, const PageFaultInfo &evt);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -125,92 +127,92 @@ protected:
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
class VirtualMemoryReserve
|
class VirtualMemoryReserve
|
||||||
{
|
{
|
||||||
DeclareNoncopyableObject( VirtualMemoryReserve );
|
DeclareNoncopyableObject(VirtualMemoryReserve);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
wxString m_name;
|
wxString m_name;
|
||||||
|
|
||||||
// Default size of the reserve, in bytes. Can be specified when the object is constructed.
|
// Default size of the reserve, in bytes. Can be specified when the object is constructed.
|
||||||
// Is used as the reserve size when Reserve() is called, unless an override is specified
|
// Is used as the reserve size when Reserve() is called, unless an override is specified
|
||||||
// in the Reserve parameters.
|
// in the Reserve parameters.
|
||||||
size_t m_defsize;
|
size_t m_defsize;
|
||||||
|
|
||||||
void* m_baseptr;
|
void *m_baseptr;
|
||||||
|
|
||||||
// reserved memory (in pages).
|
// reserved memory (in pages).
|
||||||
uptr m_pages_reserved;
|
uptr m_pages_reserved;
|
||||||
|
|
||||||
// Records the number of pages committed to memory.
|
// Records the number of pages committed to memory.
|
||||||
// (metric for analysis of buffer usage)
|
// (metric for analysis of buffer usage)
|
||||||
uptr m_pages_commited;
|
uptr m_pages_commited;
|
||||||
|
|
||||||
// Protection mode to be applied to committed blocks.
|
// Protection mode to be applied to committed blocks.
|
||||||
PageProtectionMode m_prot_mode;
|
PageProtectionMode m_prot_mode;
|
||||||
|
|
||||||
// Controls write access to the entire reserve. When true (the default), the reserve
|
// Controls write access to the entire reserve. When true (the default), the reserve
|
||||||
// operates normally. When set to false, all committed blocks are re-protected with
|
// operates normally. When set to false, all committed blocks are re-protected with
|
||||||
// write disabled, and accesses to uncommitted blocks (read or write) will cause a GPF
|
// write disabled, and accesses to uncommitted blocks (read or write) will cause a GPF
|
||||||
// as well.
|
// as well.
|
||||||
bool m_allow_writes;
|
bool m_allow_writes;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VirtualMemoryReserve( const wxString& name=wxEmptyString, size_t size = 0 );
|
VirtualMemoryReserve(const wxString &name = wxEmptyString, size_t size = 0);
|
||||||
virtual ~VirtualMemoryReserve() throw()
|
virtual ~VirtualMemoryReserve() throw()
|
||||||
{
|
{
|
||||||
Release();
|
Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void* Reserve( size_t size = 0, uptr base = 0, uptr upper_bounds = 0 );
|
virtual void *Reserve(size_t size = 0, uptr base = 0, uptr upper_bounds = 0);
|
||||||
virtual void* ReserveAt( uptr base = 0, uptr upper_bounds = 0 )
|
virtual void *ReserveAt(uptr base = 0, uptr upper_bounds = 0)
|
||||||
{
|
{
|
||||||
return Reserve(m_defsize, base, upper_bounds);
|
return Reserve(m_defsize, base, upper_bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void Reset();
|
virtual void Reset();
|
||||||
virtual void Release();
|
virtual void Release();
|
||||||
virtual bool TryResize( uint newsize );
|
virtual bool TryResize(uint newsize);
|
||||||
virtual bool Commit();
|
virtual bool Commit();
|
||||||
|
|
||||||
virtual void ForbidModification();
|
|
||||||
virtual void AllowModification();
|
|
||||||
|
|
||||||
bool IsOk() const { return m_baseptr != NULL; }
|
virtual void ForbidModification();
|
||||||
wxString GetName() const { return m_name; }
|
virtual void AllowModification();
|
||||||
|
|
||||||
uptr GetReserveSizeInBytes() const { return m_pages_reserved * __pagesize; }
|
bool IsOk() const { return m_baseptr != NULL; }
|
||||||
uptr GetReserveSizeInPages() const { return m_pages_reserved; }
|
wxString GetName() const { return m_name; }
|
||||||
uint GetCommittedPageCount() const { return m_pages_commited; }
|
|
||||||
uint GetCommittedBytes() const { return m_pages_commited * __pagesize; }
|
|
||||||
|
|
||||||
u8* GetPtr() { return (u8*)m_baseptr; }
|
uptr GetReserveSizeInBytes() const { return m_pages_reserved * __pagesize; }
|
||||||
const u8* GetPtr() const { return (u8*)m_baseptr; }
|
uptr GetReserveSizeInPages() const { return m_pages_reserved; }
|
||||||
u8* GetPtrEnd() { return (u8*)m_baseptr + (m_pages_reserved * __pagesize); }
|
uint GetCommittedPageCount() const { return m_pages_commited; }
|
||||||
const u8* GetPtrEnd() const { return (u8*)m_baseptr + (m_pages_reserved * __pagesize); }
|
uint GetCommittedBytes() const { return m_pages_commited * __pagesize; }
|
||||||
|
|
||||||
VirtualMemoryReserve& SetName( const wxString& newname );
|
u8 *GetPtr() { return (u8 *)m_baseptr; }
|
||||||
VirtualMemoryReserve& SetBaseAddr( uptr newaddr );
|
const u8 *GetPtr() const { return (u8 *)m_baseptr; }
|
||||||
VirtualMemoryReserve& SetPageAccessOnCommit( const PageProtectionMode& mode );
|
u8 *GetPtrEnd() { return (u8 *)m_baseptr + (m_pages_reserved * __pagesize); }
|
||||||
|
const u8 *GetPtrEnd() const { return (u8 *)m_baseptr + (m_pages_reserved * __pagesize); }
|
||||||
|
|
||||||
operator void*() { return m_baseptr; }
|
VirtualMemoryReserve &SetName(const wxString &newname);
|
||||||
operator const void*() const { return m_baseptr; }
|
VirtualMemoryReserve &SetBaseAddr(uptr newaddr);
|
||||||
|
VirtualMemoryReserve &SetPageAccessOnCommit(const PageProtectionMode &mode);
|
||||||
|
|
||||||
operator u8*() { return (u8*)m_baseptr; }
|
operator void *() { return m_baseptr; }
|
||||||
operator const u8*() const { return (u8*)m_baseptr; }
|
operator const void *() const { return m_baseptr; }
|
||||||
|
|
||||||
u8& operator[](uint idx)
|
operator u8 *() { return (u8 *)m_baseptr; }
|
||||||
{
|
operator const u8 *() const { return (u8 *)m_baseptr; }
|
||||||
pxAssert(idx < (m_pages_reserved * __pagesize));
|
|
||||||
return *((u8*)m_baseptr + idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
const u8& operator[](uint idx) const
|
u8 &operator[](uint idx)
|
||||||
{
|
{
|
||||||
pxAssert(idx < (m_pages_reserved * __pagesize));
|
pxAssert(idx < (m_pages_reserved * __pagesize));
|
||||||
return *((u8*)m_baseptr + idx);
|
return *((u8 *)m_baseptr + idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const u8 &operator[](uint idx) const
|
||||||
|
{
|
||||||
|
pxAssert(idx < (m_pages_reserved * __pagesize));
|
||||||
|
return *((u8 *)m_baseptr + idx);
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void ReprotectCommittedBlocks( const PageProtectionMode& newmode );
|
virtual void ReprotectCommittedBlocks(const PageProtectionMode &newmode);
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -218,80 +220,79 @@ protected:
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
class BaseVmReserveListener : public VirtualMemoryReserve
|
class BaseVmReserveListener : public VirtualMemoryReserve
|
||||||
{
|
{
|
||||||
DeclareNoncopyableObject( BaseVmReserveListener );
|
DeclareNoncopyableObject(BaseVmReserveListener);
|
||||||
|
|
||||||
typedef VirtualMemoryReserve _parent;
|
typedef VirtualMemoryReserve _parent;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
EventListenerHelper_PageFault<BaseVmReserveListener> m_pagefault_listener;
|
EventListenerHelper_PageFault<BaseVmReserveListener> m_pagefault_listener;
|
||||||
|
|
||||||
// Incremental size by which the buffer grows (in pages)
|
// Incremental size by which the buffer grows (in pages)
|
||||||
uptr m_blocksize;
|
uptr m_blocksize;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BaseVmReserveListener( const wxString& name, size_t size = 0 );
|
BaseVmReserveListener(const wxString &name, size_t size = 0);
|
||||||
virtual ~BaseVmReserveListener() throw() { }
|
virtual ~BaseVmReserveListener() throw() {}
|
||||||
|
|
||||||
operator void*() { return m_baseptr; }
|
operator void *() { return m_baseptr; }
|
||||||
operator const void*() const { return m_baseptr; }
|
operator const void *() const { return m_baseptr; }
|
||||||
|
|
||||||
operator u8*() { return (u8*)m_baseptr; }
|
operator u8 *() { return (u8 *)m_baseptr; }
|
||||||
operator const u8*() const { return (u8*)m_baseptr; }
|
operator const u8 *() const { return (u8 *)m_baseptr; }
|
||||||
|
|
||||||
using _parent::operator[];
|
using _parent::operator[];
|
||||||
|
|
||||||
void OnPageFaultEvent( const PageFaultInfo& info, bool& handled );
|
void OnPageFaultEvent(const PageFaultInfo &info, bool &handled);
|
||||||
|
|
||||||
virtual uptr SetBlockSize( uptr bytes )
|
virtual uptr SetBlockSize(uptr bytes)
|
||||||
{
|
{
|
||||||
m_blocksize = (bytes + __pagesize - 1) / __pagesize;
|
m_blocksize = (bytes + __pagesize - 1) / __pagesize;
|
||||||
return m_blocksize * __pagesize;
|
return m_blocksize * __pagesize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void Reset()
|
||||||
|
{
|
||||||
|
_parent::Reset();
|
||||||
|
}
|
||||||
|
|
||||||
virtual void Reset()
|
|
||||||
{
|
|
||||||
_parent::Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
// This function is called from OnPageFaultEvent after the address has been translated
|
||||||
|
// and confirmed to apply to this reserved area in question. OnPageFaultEvent contains
|
||||||
|
// a try/catch exception handler, which ensures "reasonable" error response behavior if
|
||||||
|
// this function throws exceptions.
|
||||||
|
//
|
||||||
|
// Important: This method is called from the context of an exception/signal handler. On
|
||||||
|
// Windows this isn't a big deal (most operations are ok). On Linux, however, logging
|
||||||
|
// and other facilities are probably not a good idea.
|
||||||
|
virtual void DoCommitAndProtect(uptr offset) = 0;
|
||||||
|
|
||||||
// This function is called from OnPageFaultEvent after the address has been translated
|
// This function is called for every committed block.
|
||||||
// and confirmed to apply to this reserved area in question. OnPageFaultEvent contains
|
virtual void OnCommittedBlock(void *block) = 0;
|
||||||
// a try/catch exception handler, which ensures "reasonable" error response behavior if
|
|
||||||
// this function throws exceptions.
|
|
||||||
//
|
|
||||||
// Important: This method is called from the context of an exception/signal handler. On
|
|
||||||
// Windows this isn't a big deal (most operations are ok). On Linux, however, logging
|
|
||||||
// and other facilities are probably not a good idea.
|
|
||||||
virtual void DoCommitAndProtect( uptr offset )=0;
|
|
||||||
|
|
||||||
// This function is called for every committed block.
|
virtual void CommitBlocks(uptr page, uint blocks);
|
||||||
virtual void OnCommittedBlock( void* block )=0;
|
|
||||||
|
|
||||||
virtual void CommitBlocks( uptr page, uint blocks );
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __POSIX__
|
#ifdef __POSIX__
|
||||||
|
|
||||||
# define PCSX2_PAGEFAULT_PROTECT
|
#define PCSX2_PAGEFAULT_PROTECT
|
||||||
# define PCSX2_PAGEFAULT_EXCEPT
|
#define PCSX2_PAGEFAULT_EXCEPT
|
||||||
|
|
||||||
#elif defined( _WIN32 )
|
#elif defined(_WIN32)
|
||||||
|
|
||||||
struct _EXCEPTION_POINTERS;
|
struct _EXCEPTION_POINTERS;
|
||||||
extern int SysPageFaultExceptionFilter(struct _EXCEPTION_POINTERS* eps);
|
extern int SysPageFaultExceptionFilter(struct _EXCEPTION_POINTERS *eps);
|
||||||
|
|
||||||
# define PCSX2_PAGEFAULT_PROTECT __try
|
#define PCSX2_PAGEFAULT_PROTECT __try
|
||||||
# define PCSX2_PAGEFAULT_EXCEPT __except(SysPageFaultExceptionFilter(GetExceptionInformation())) {}
|
#define PCSX2_PAGEFAULT_EXCEPT \
|
||||||
|
__except (SysPageFaultExceptionFilter(GetExceptionInformation())) {}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
# error PCSX2 - Unsupported operating system platform.
|
#error PCSX2 - Unsupported operating system platform.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern void pxInstallSignalHandler();
|
extern void pxInstallSignalHandler();
|
||||||
extern void _platform_InstallSignalHandler();
|
extern void _platform_InstallSignalHandler();
|
||||||
|
|
||||||
#include "Threading.h"
|
#include "Threading.h"
|
||||||
extern SrcType_PageFault* Source_PageFault;
|
extern SrcType_PageFault *Source_PageFault;
|
||||||
extern Threading::Mutex PageFault_Mutex;
|
extern Threading::Mutex PageFault_Mutex;
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
#include <wx/filename.h>
|
#include <wx/filename.h>
|
||||||
#include "StringHelpers.h"
|
#include "StringHelpers.h"
|
||||||
|
|
||||||
#define g_MaxPath 255 // 255 is safer with antiquated Win32 ASCII APIs.
|
#define g_MaxPath 255 // 255 is safer with antiquated Win32 ASCII APIs.
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// wxDirName
|
// wxDirName
|
||||||
|
@ -26,164 +26,180 @@
|
||||||
class wxDirName : protected wxFileName
|
class wxDirName : protected wxFileName
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit wxDirName( const wxFileName& src )
|
explicit wxDirName(const wxFileName &src)
|
||||||
{
|
{
|
||||||
Assign( src.GetPath(), wxEmptyString );
|
Assign(src.GetPath(), wxEmptyString);
|
||||||
}
|
}
|
||||||
|
|
||||||
wxDirName() : wxFileName() {}
|
wxDirName()
|
||||||
wxDirName( const wxDirName& src ) : wxFileName( src ) { }
|
: wxFileName()
|
||||||
explicit wxDirName( const char* src ) { Assign( fromUTF8(src) ); }
|
{
|
||||||
explicit wxDirName( const wxString& src ) { Assign( src ); }
|
}
|
||||||
|
wxDirName(const wxDirName &src)
|
||||||
|
: wxFileName(src)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
explicit wxDirName(const char *src) { Assign(fromUTF8(src)); }
|
||||||
|
explicit wxDirName(const wxString &src) { Assign(src); }
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
void Assign( const wxString& volume, const wxString& path )
|
void Assign(const wxString &volume, const wxString &path)
|
||||||
{
|
{
|
||||||
wxFileName::Assign( volume, path, wxEmptyString );
|
wxFileName::Assign(volume, path, wxEmptyString);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Assign( const wxString& path )
|
void Assign(const wxString &path)
|
||||||
{
|
{
|
||||||
wxFileName::Assign( path, wxEmptyString );
|
wxFileName::Assign(path, wxEmptyString);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Assign( const wxDirName& path )
|
void Assign(const wxDirName &path)
|
||||||
{
|
{
|
||||||
wxFileName::Assign( path );
|
wxFileName::Assign(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Clear() { wxFileName::Clear(); }
|
void Clear() { wxFileName::Clear(); }
|
||||||
|
|
||||||
wxCharBuffer ToUTF8() const { return GetPath().ToUTF8(); }
|
wxCharBuffer ToUTF8() const { return GetPath().ToUTF8(); }
|
||||||
wxCharBuffer ToAscii() const { return GetPath().ToAscii(); }
|
wxCharBuffer ToAscii() const { return GetPath().ToAscii(); }
|
||||||
wxString ToString() const { return GetPath(); }
|
wxString ToString() const { return GetPath(); }
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
bool IsWritable() const { return IsDirWritable(); }
|
bool IsWritable() const { return IsDirWritable(); }
|
||||||
bool IsReadable() const { return IsDirReadable(); }
|
bool IsReadable() const { return IsDirReadable(); }
|
||||||
bool Exists() const { return DirExists(); }
|
bool Exists() const { return DirExists(); }
|
||||||
bool FileExists() const { return wxFileName::FileExists(); }
|
bool FileExists() const { return wxFileName::FileExists(); }
|
||||||
bool IsOk() const { return wxFileName::IsOk(); }
|
bool IsOk() const { return wxFileName::IsOk(); }
|
||||||
bool IsRelative() const { return wxFileName::IsRelative(); }
|
bool IsRelative() const { return wxFileName::IsRelative(); }
|
||||||
bool IsAbsolute() const { return wxFileName::IsAbsolute(); }
|
bool IsAbsolute() const { return wxFileName::IsAbsolute(); }
|
||||||
|
|
||||||
bool SameAs( const wxDirName& filepath ) const
|
bool SameAs(const wxDirName &filepath) const
|
||||||
{
|
{
|
||||||
return wxFileName::SameAs( filepath );
|
return wxFileName::SameAs(filepath);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Returns true if the file is somewhere inside this directory (and both file and directory are not relative).
|
//Returns true if the file is somewhere inside this directory (and both file and directory are not relative).
|
||||||
bool IsContains( const wxFileName& file ) const
|
bool IsContains(const wxFileName &file) const
|
||||||
{
|
{
|
||||||
if( this->IsRelative() || file.IsRelative() )
|
if (this->IsRelative() || file.IsRelative())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
wxFileName f( file );
|
wxFileName f(file);
|
||||||
|
|
||||||
while( 1 )
|
while (1) {
|
||||||
{
|
if (this->SameAs(wxDirName(f.GetPath())))
|
||||||
if( this->SameAs( wxDirName(f.GetPath()) ) )
|
return true;
|
||||||
return true;
|
|
||||||
|
|
||||||
if( f.GetDirCount() == 0 )
|
if (f.GetDirCount() == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
f.RemoveLastDir();
|
f.RemoveLastDir();
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsContains( const wxDirName& dir ) const
|
bool IsContains(const wxDirName &dir) const
|
||||||
{
|
{
|
||||||
return IsContains( (wxFileName)dir );
|
return IsContains((wxFileName)dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//Auto relative works as follows:
|
//Auto relative works as follows:
|
||||||
// 1. if either base or subject are relative, return subject (should never be used with relative paths).
|
// 1. if either base or subject are relative, return subject (should never be used with relative paths).
|
||||||
// 2. else if subject is somewhere inside base folder, then result is subject relative to base.
|
// 2. else if subject is somewhere inside base folder, then result is subject relative to base.
|
||||||
// 3. (windows only, implicitly) else if subject is on the same driveletter as base, result is absolute path of subject without the driveletter.
|
// 3. (windows only, implicitly) else if subject is on the same driveletter as base, result is absolute path of subject without the driveletter.
|
||||||
// 4. else, result is absolute path of subject.
|
// 4. else, result is absolute path of subject.
|
||||||
//
|
//
|
||||||
// returns ok if both this and base are absolute paths.
|
// returns ok if both this and base are absolute paths.
|
||||||
static wxString MakeAutoRelativeTo(const wxFileName _subject, const wxString& pathbase)
|
static wxString MakeAutoRelativeTo(const wxFileName _subject, const wxString &pathbase)
|
||||||
{
|
{
|
||||||
wxFileName subject( _subject );
|
wxFileName subject(_subject);
|
||||||
wxDirName base ( pathbase );
|
wxDirName base(pathbase);
|
||||||
if( base.IsRelative() || subject.IsRelative() )
|
if (base.IsRelative() || subject.IsRelative())
|
||||||
return subject.GetFullPath();
|
return subject.GetFullPath();
|
||||||
|
|
||||||
wxString bv( base.GetVolume() ); bv.MakeUpper();
|
wxString bv(base.GetVolume());
|
||||||
wxString sv( subject.GetVolume() ); sv.MakeUpper();
|
bv.MakeUpper();
|
||||||
|
wxString sv(subject.GetVolume());
|
||||||
|
sv.MakeUpper();
|
||||||
|
|
||||||
if( base.IsContains( subject ) )
|
if (base.IsContains(subject)) {
|
||||||
{
|
subject.MakeRelativeTo(base.GetFullPath());
|
||||||
subject.MakeRelativeTo( base.GetFullPath() );
|
} else if (base.HasVolume() && subject.HasVolume() && bv == sv) {
|
||||||
}
|
wxString unusedVolume;
|
||||||
else if( base.HasVolume() && subject.HasVolume() && bv == sv )
|
wxString pathSansVolume;
|
||||||
{
|
subject.SplitVolume(subject.GetFullPath(), &unusedVolume, &pathSansVolume);
|
||||||
wxString unusedVolume;
|
subject = pathSansVolume;
|
||||||
wxString pathSansVolume;
|
}
|
||||||
subject.SplitVolume(subject.GetFullPath(), &unusedVolume, &pathSansVolume);
|
//implicit else: this stays fully absolute
|
||||||
subject = pathSansVolume;
|
|
||||||
}
|
|
||||||
//implicit else: this stays fully absolute
|
|
||||||
|
|
||||||
return subject.GetFullPath();
|
return subject.GetFullPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
static wxString MakeAutoRelativeTo(const wxDirName subject, const wxString& pathbase)
|
static wxString MakeAutoRelativeTo(const wxDirName subject, const wxString &pathbase)
|
||||||
{
|
{
|
||||||
return MakeAutoRelativeTo( wxFileName( subject ), pathbase );
|
return MakeAutoRelativeTo(wxFileName(subject), pathbase);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the number of sub folders in this directory path
|
// Returns the number of sub folders in this directory path
|
||||||
size_t GetCount() const { return GetDirCount(); }
|
size_t GetCount() const { return GetDirCount(); }
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
wxFileName Combine( const wxFileName& right ) const;
|
wxFileName Combine(const wxFileName &right) const;
|
||||||
wxDirName Combine( const wxDirName& right ) const;
|
wxDirName Combine(const wxDirName &right) const;
|
||||||
|
|
||||||
// removes the lastmost directory from the path
|
// removes the lastmost directory from the path
|
||||||
void RemoveLast() { wxFileName::RemoveDir(GetCount() - 1); }
|
void RemoveLast() { wxFileName::RemoveDir(GetCount() - 1); }
|
||||||
|
|
||||||
wxDirName& Normalize( int flags = wxPATH_NORM_ALL, const wxString& cwd = wxEmptyString );
|
wxDirName &Normalize(int flags = wxPATH_NORM_ALL, const wxString &cwd = wxEmptyString);
|
||||||
wxDirName& MakeRelativeTo( const wxString& pathBase = wxEmptyString );
|
wxDirName &MakeRelativeTo(const wxString &pathBase = wxEmptyString);
|
||||||
wxDirName& MakeAbsolute( const wxString& cwd = wxEmptyString );
|
wxDirName &MakeAbsolute(const wxString &cwd = wxEmptyString);
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
void AssignCwd( const wxString& volume = wxEmptyString ) { wxFileName::AssignCwd( volume ); }
|
void AssignCwd(const wxString &volume = wxEmptyString) { wxFileName::AssignCwd(volume); }
|
||||||
bool SetCwd() { return wxFileName::SetCwd(); }
|
bool SetCwd() { return wxFileName::SetCwd(); }
|
||||||
|
|
||||||
// wxWidgets is missing the const qualifier for this one! Shame!
|
// wxWidgets is missing the const qualifier for this one! Shame!
|
||||||
void Rmdir();
|
void Rmdir();
|
||||||
bool Mkdir();
|
bool Mkdir();
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
wxDirName& operator=(const wxDirName& dirname) { Assign( dirname ); return *this; }
|
wxDirName &operator=(const wxDirName &dirname)
|
||||||
wxDirName& operator=(const wxString& dirname) { Assign( dirname ); return *this; }
|
{
|
||||||
wxDirName& operator=(const char* dirname) { Assign( fromUTF8(dirname) ); return *this; }
|
Assign(dirname);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
wxDirName &operator=(const wxString &dirname)
|
||||||
|
{
|
||||||
|
Assign(dirname);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
wxDirName &operator=(const char *dirname)
|
||||||
|
{
|
||||||
|
Assign(fromUTF8(dirname));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
wxFileName operator+( const wxFileName& right ) const { return Combine( right ); }
|
wxFileName operator+(const wxFileName &right) const { return Combine(right); }
|
||||||
wxDirName operator+( const wxDirName& right ) const { return Combine( right ); }
|
wxDirName operator+(const wxDirName &right) const { return Combine(right); }
|
||||||
wxFileName operator+( const wxString& right ) const { return Combine( wxFileName(right) ); }
|
wxFileName operator+(const wxString &right) const { return Combine(wxFileName(right)); }
|
||||||
wxFileName operator+( const char* right ) const { return Combine( wxFileName(fromUTF8(right)) ); }
|
wxFileName operator+(const char *right) const { return Combine(wxFileName(fromUTF8(right))); }
|
||||||
|
|
||||||
bool operator==(const wxDirName& filename) const { return SameAs(filename); }
|
bool operator==(const wxDirName &filename) const { return SameAs(filename); }
|
||||||
bool operator!=(const wxDirName& filename) const { return !SameAs(filename); }
|
bool operator!=(const wxDirName &filename) const { return !SameAs(filename); }
|
||||||
|
|
||||||
bool operator==(const wxFileName& filename) const { return SameAs(wxDirName(filename)); }
|
bool operator==(const wxFileName &filename) const { return SameAs(wxDirName(filename)); }
|
||||||
bool operator!=(const wxFileName& filename) const { return !SameAs(wxDirName(filename)); }
|
bool operator!=(const wxFileName &filename) const { return !SameAs(wxDirName(filename)); }
|
||||||
|
|
||||||
// compare with a filename string interpreted as a native file name
|
// compare with a filename string interpreted as a native file name
|
||||||
bool operator==(const wxString& filename) const { return SameAs(wxDirName(filename)); }
|
bool operator==(const wxString &filename) const { return SameAs(wxDirName(filename)); }
|
||||||
bool operator!=(const wxString& filename) const { return !SameAs(wxDirName(filename)); }
|
bool operator!=(const wxString &filename) const { return !SameAs(wxDirName(filename)); }
|
||||||
|
|
||||||
const wxFileName& GetFilename() const { return *this; }
|
const wxFileName &GetFilename() const { return *this; }
|
||||||
wxFileName& GetFilename() { return *this; }
|
wxFileName &GetFilename() { return *this; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -195,20 +211,20 @@ public:
|
||||||
//
|
//
|
||||||
namespace Path
|
namespace Path
|
||||||
{
|
{
|
||||||
extern bool IsRelative( const wxString& path );
|
extern bool IsRelative(const wxString &path);
|
||||||
extern s64 GetFileSize( const wxString& path );
|
extern s64 GetFileSize(const wxString &path);
|
||||||
|
|
||||||
extern wxString Normalize( const wxString& srcpath );
|
extern wxString Normalize(const wxString &srcpath);
|
||||||
extern wxString Normalize( const wxDirName& srcpath );
|
extern wxString Normalize(const wxDirName &srcpath);
|
||||||
extern wxString MakeAbsolute( const wxString& srcpath );
|
extern wxString MakeAbsolute(const wxString &srcpath);
|
||||||
|
|
||||||
extern wxString Combine( const wxString& srcPath, const wxString& srcFile );
|
extern wxString Combine(const wxString &srcPath, const wxString &srcFile);
|
||||||
extern wxString Combine( const wxDirName& srcPath, const wxFileName& srcFile );
|
extern wxString Combine(const wxDirName &srcPath, const wxFileName &srcFile);
|
||||||
extern wxString Combine( const wxString& srcPath, const wxDirName& srcFile );
|
extern wxString Combine(const wxString &srcPath, const wxDirName &srcFile);
|
||||||
extern wxString ReplaceExtension( const wxString& src, const wxString& ext );
|
extern wxString ReplaceExtension(const wxString &src, const wxString &ext);
|
||||||
extern wxString ReplaceFilename( const wxString& src, const wxString& newfilename );
|
extern wxString ReplaceFilename(const wxString &src, const wxString &newfilename);
|
||||||
extern wxString GetFilename( const wxString& src );
|
extern wxString GetFilename(const wxString &src);
|
||||||
extern wxString GetDirectory( const wxString& src );
|
extern wxString GetDirectory(const wxString &src);
|
||||||
extern wxString GetFilenameWithoutExt( const wxString& src );
|
extern wxString GetFilenameWithoutExt(const wxString &src);
|
||||||
extern wxString GetRootDirectory( const wxString& src );
|
extern wxString GetRootDirectory(const wxString &src);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,43 +15,42 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace Perf {
|
namespace Perf
|
||||||
|
{
|
||||||
|
|
||||||
struct Info
|
struct Info
|
||||||
{
|
{
|
||||||
uptr m_x86;
|
uptr m_x86;
|
||||||
u32 m_size;
|
u32 m_size;
|
||||||
char m_symbol[20];
|
char m_symbol[20];
|
||||||
// The idea is to keep static zones that are set only
|
// The idea is to keep static zones that are set only
|
||||||
// once.
|
// once.
|
||||||
bool m_dynamic;
|
bool m_dynamic;
|
||||||
|
|
||||||
Info(uptr x86, u32 size, const char* symbol);
|
Info(uptr x86, u32 size, const char *symbol);
|
||||||
Info(uptr x86, u32 size, const char* symbol, u32 pc);
|
Info(uptr x86, u32 size, const char *symbol, u32 pc);
|
||||||
void Print(FILE* fp);
|
void Print(FILE *fp);
|
||||||
};
|
};
|
||||||
|
|
||||||
class InfoVector
|
class InfoVector
|
||||||
{
|
{
|
||||||
std::vector<Info> m_v;
|
std::vector<Info> m_v;
|
||||||
char m_prefix[20];
|
char m_prefix[20];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
InfoVector(const char *prefix);
|
||||||
|
|
||||||
InfoVector(const char* prefix);
|
void print(FILE *fp);
|
||||||
|
void map(uptr x86, u32 size, const char *symbol);
|
||||||
|
void map(uptr x86, u32 size, u32 pc);
|
||||||
|
void reset();
|
||||||
|
};
|
||||||
|
|
||||||
void print(FILE* fp);
|
void dump();
|
||||||
void map(uptr x86, u32 size, const char* symbol);
|
void dump_and_reset();
|
||||||
void map(uptr x86, u32 size, u32 pc);
|
|
||||||
void reset();
|
|
||||||
|
|
||||||
};
|
extern InfoVector any;
|
||||||
|
extern InfoVector ee;
|
||||||
void dump();
|
extern InfoVector iop;
|
||||||
void dump_and_reset();
|
extern InfoVector vu;
|
||||||
|
|
||||||
extern InfoVector any;
|
|
||||||
extern InfoVector ee;
|
|
||||||
extern InfoVector iop;
|
|
||||||
extern InfoVector vu;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,38 +25,38 @@ namespace Threading
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// ThreadDeleteEvent
|
// ThreadDeleteEvent
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
class EventListener_Thread : public IEventDispatcher<int>
|
class EventListener_Thread : public IEventDispatcher<int>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef int EvtParams;
|
typedef int EvtParams;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
pxThread* m_thread;
|
pxThread *m_thread;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
EventListener_Thread()
|
EventListener_Thread()
|
||||||
{
|
{
|
||||||
m_thread = NULL;
|
m_thread = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~EventListener_Thread() throw() {}
|
virtual ~EventListener_Thread() throw() {}
|
||||||
|
|
||||||
void SetThread( pxThread& thr ) { m_thread = &thr; }
|
void SetThread(pxThread &thr) { m_thread = &thr; }
|
||||||
void SetThread( pxThread* thr ) { m_thread = thr; }
|
void SetThread(pxThread *thr) { m_thread = thr; }
|
||||||
|
|
||||||
void DispatchEvent( const int& params )
|
void DispatchEvent(const int ¶ms)
|
||||||
{
|
{
|
||||||
OnThreadCleanup();
|
OnThreadCleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Invoked by the pxThread when the thread execution is ending. This is
|
// Invoked by the pxThread when the thread execution is ending. This is
|
||||||
// typically more useful than a delete listener since the extended thread information
|
// typically more useful than a delete listener since the extended thread information
|
||||||
// provided by virtualized functions/methods will be available.
|
// provided by virtualized functions/methods will be available.
|
||||||
// Important! This event is executed *by the thread*, so care must be taken to ensure
|
// Important! This event is executed *by the thread*, so care must be taken to ensure
|
||||||
// thread sync when necessary (posting messages to the main thread, etc).
|
// thread sync when necessary (posting messages to the main thread, etc).
|
||||||
virtual void OnThreadCleanup()=0;
|
virtual void OnThreadCleanup() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// pxThread - Helper class for the basics of starting/managing persistent threads.
|
// pxThread - Helper class for the basics of starting/managing persistent threads.
|
||||||
|
@ -85,122 +85,123 @@ namespace Threading
|
||||||
// no dependency options for ensuring correct static var initializations). Use heap
|
// no dependency options for ensuring correct static var initializations). Use heap
|
||||||
// allocation to create thread objects instead.
|
// allocation to create thread objects instead.
|
||||||
//
|
//
|
||||||
class pxThread
|
class pxThread
|
||||||
{
|
{
|
||||||
DeclareNoncopyableObject(pxThread);
|
DeclareNoncopyableObject(pxThread);
|
||||||
|
|
||||||
friend void pxYield( int ms );
|
friend void pxYield(int ms);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
wxString m_name; // diagnostic name for our thread.
|
wxString m_name; // diagnostic name for our thread.
|
||||||
pthread_t m_thread;
|
pthread_t m_thread;
|
||||||
uptr m_native_id; // typically an id, but implementing platforms can do whatever.
|
uptr m_native_id; // typically an id, but implementing platforms can do whatever.
|
||||||
uptr m_native_handle; // typically a pointer/handle, but implementing platforms can do whatever.
|
uptr m_native_handle; // typically a pointer/handle, but implementing platforms can do whatever.
|
||||||
|
|
||||||
Semaphore m_sem_event; // general wait event that's needed by most threads
|
Semaphore m_sem_event; // general wait event that's needed by most threads
|
||||||
Semaphore m_sem_startup; // startup sync tool
|
Semaphore m_sem_startup; // startup sync tool
|
||||||
Mutex m_mtx_InThread; // used for canceling and closing threads in a deadlock-safe manner
|
Mutex m_mtx_InThread; // used for canceling and closing threads in a deadlock-safe manner
|
||||||
MutexRecursive m_mtx_start; // used to lock the Start() code from starting simultaneous threads accidentally.
|
MutexRecursive m_mtx_start; // used to lock the Start() code from starting simultaneous threads accidentally.
|
||||||
Mutex m_mtx_ThreadName;
|
Mutex m_mtx_ThreadName;
|
||||||
|
|
||||||
std::atomic<bool> m_detached; // a boolean value which indicates if the m_thread handle is valid
|
std::atomic<bool> m_detached; // a boolean value which indicates if the m_thread handle is valid
|
||||||
std::atomic<bool> m_running; // set true by Start(), and set false by Cancel(), Block(), etc.
|
std::atomic<bool> m_running; // set true by Start(), and set false by Cancel(), Block(), etc.
|
||||||
|
|
||||||
// exception handle, set non-NULL if the thread terminated with an exception
|
// exception handle, set non-NULL if the thread terminated with an exception
|
||||||
// Use RethrowException() to re-throw the exception using its original exception type.
|
// Use RethrowException() to re-throw the exception using its original exception type.
|
||||||
ScopedPtrMT<BaseException> m_except;
|
ScopedPtrMT<BaseException> m_except;
|
||||||
|
|
||||||
EventSource<EventListener_Thread> m_evtsrc_OnDelete;
|
EventSource<EventListener_Thread> m_evtsrc_OnDelete;
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~pxThread() throw();
|
virtual ~pxThread() throw();
|
||||||
pxThread( const wxString& name=L"pxThread" );
|
pxThread(const wxString &name = L"pxThread");
|
||||||
|
|
||||||
pthread_t GetId() const { return m_thread; }
|
pthread_t GetId() const { return m_thread; }
|
||||||
u64 GetCpuTime() const;
|
u64 GetCpuTime() const;
|
||||||
|
|
||||||
virtual void Start();
|
virtual void Start();
|
||||||
virtual void Cancel( bool isBlocking = true );
|
virtual void Cancel(bool isBlocking = true);
|
||||||
virtual bool Cancel( const wxTimeSpan& timeout );
|
virtual bool Cancel(const wxTimeSpan &timeout);
|
||||||
virtual bool Detach();
|
virtual bool Detach();
|
||||||
virtual void Block();
|
virtual void Block();
|
||||||
virtual bool Block( const wxTimeSpan& timeout );
|
virtual bool Block(const wxTimeSpan &timeout);
|
||||||
virtual void RethrowException() const;
|
virtual void RethrowException() const;
|
||||||
|
|
||||||
void AddListener( EventListener_Thread& evt );
|
void AddListener(EventListener_Thread &evt);
|
||||||
void AddListener( EventListener_Thread* evt )
|
void AddListener(EventListener_Thread *evt)
|
||||||
{
|
{
|
||||||
if( evt == NULL ) return;
|
if (evt == NULL)
|
||||||
AddListener( *evt );
|
return;
|
||||||
}
|
AddListener(*evt);
|
||||||
|
}
|
||||||
|
|
||||||
void WaitOnSelf( Semaphore& mutex ) const;
|
void WaitOnSelf(Semaphore &mutex) const;
|
||||||
void WaitOnSelf( Mutex& mutex ) const;
|
void WaitOnSelf(Mutex &mutex) const;
|
||||||
bool WaitOnSelf( Semaphore& mutex, const wxTimeSpan& timeout ) const;
|
bool WaitOnSelf(Semaphore &mutex, const wxTimeSpan &timeout) const;
|
||||||
bool WaitOnSelf( Mutex& mutex, const wxTimeSpan& timeout ) const;
|
bool WaitOnSelf(Mutex &mutex, const wxTimeSpan &timeout) const;
|
||||||
|
|
||||||
bool IsRunning() const;
|
bool IsRunning() const;
|
||||||
bool IsSelf() const;
|
bool IsSelf() const;
|
||||||
bool HasPendingException() const { return !!m_except; }
|
bool HasPendingException() const { return !!m_except; }
|
||||||
|
|
||||||
wxString GetName() const;
|
wxString GetName() const;
|
||||||
void SetName( const wxString& newname );
|
void SetName(const wxString &newname);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Extending classes should always implement your own OnStart(), which is called by
|
// Extending classes should always implement your own OnStart(), which is called by
|
||||||
// Start() once necessary locks have been obtained. Do not override Start() directly
|
// Start() once necessary locks have been obtained. Do not override Start() directly
|
||||||
// unless you're really sure that's what you need to do. ;)
|
// unless you're really sure that's what you need to do. ;)
|
||||||
virtual void OnStart();
|
virtual void OnStart();
|
||||||
|
|
||||||
virtual void OnStartInThread();
|
virtual void OnStartInThread();
|
||||||
|
|
||||||
// This is called when the thread has been canceled or exits normally. The pxThread
|
// This is called when the thread has been canceled or exits normally. The pxThread
|
||||||
// automatically binds it to the pthread cleanup routines as soon as the thread starts.
|
// automatically binds it to the pthread cleanup routines as soon as the thread starts.
|
||||||
virtual void OnCleanupInThread();
|
virtual void OnCleanupInThread();
|
||||||
|
|
||||||
// Implemented by derived class to perform actual threaded task!
|
// Implemented by derived class to perform actual threaded task!
|
||||||
virtual void ExecuteTaskInThread()=0;
|
virtual void ExecuteTaskInThread() = 0;
|
||||||
|
|
||||||
void TestCancel() const;
|
void TestCancel() const;
|
||||||
|
|
||||||
// Yields this thread to other threads and checks for cancellation. A sleeping thread should
|
// Yields this thread to other threads and checks for cancellation. A sleeping thread should
|
||||||
// always test for cancellation, however if you really don't want to, you can use Threading::Sleep()
|
// always test for cancellation, however if you really don't want to, you can use Threading::Sleep()
|
||||||
// or better yet, disable cancellation of the thread completely with DisableCancellation().
|
// or better yet, disable cancellation of the thread completely with DisableCancellation().
|
||||||
//
|
//
|
||||||
// Parameters:
|
// Parameters:
|
||||||
// ms - 'minimum' yield time in milliseconds (rough -- typically yields are longer by 1-5ms
|
// ms - 'minimum' yield time in milliseconds (rough -- typically yields are longer by 1-5ms
|
||||||
// depending on operating system/platform). If ms is 0 or unspecified, then a single
|
// depending on operating system/platform). If ms is 0 or unspecified, then a single
|
||||||
// timeslice is yielded to other contending threads. If no threads are contending for
|
// timeslice is yielded to other contending threads. If no threads are contending for
|
||||||
// time when ms==0, then no yield is done, but cancellation is still tested.
|
// time when ms==0, then no yield is done, but cancellation is still tested.
|
||||||
void Yield( int ms = 0 )
|
void Yield(int ms = 0)
|
||||||
{
|
{
|
||||||
pxAssert( IsSelf() );
|
pxAssert(IsSelf());
|
||||||
Threading::Sleep( ms );
|
Threading::Sleep(ms);
|
||||||
TestCancel();
|
TestCancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrankenMutex( Mutex& mutex );
|
void FrankenMutex(Mutex &mutex);
|
||||||
|
|
||||||
bool AffinityAssert_AllowFromSelf( const DiagnosticOrigin& origin ) const;
|
bool AffinityAssert_AllowFromSelf(const DiagnosticOrigin &origin) const;
|
||||||
bool AffinityAssert_DisallowFromSelf( const DiagnosticOrigin& origin ) const;
|
bool AffinityAssert_DisallowFromSelf(const DiagnosticOrigin &origin) const;
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Section of methods for internal use only.
|
// Section of methods for internal use only.
|
||||||
|
|
||||||
void _platform_specific_OnStartInThread();
|
void _platform_specific_OnStartInThread();
|
||||||
void _platform_specific_OnCleanupInThread();
|
void _platform_specific_OnCleanupInThread();
|
||||||
bool _basecancel();
|
bool _basecancel();
|
||||||
void _selfRunningTest( const wxChar* name ) const;
|
void _selfRunningTest(const wxChar *name) const;
|
||||||
void _DoSetThreadName( const wxString& name );
|
void _DoSetThreadName(const wxString &name);
|
||||||
void _DoSetThreadName( const char* name );
|
void _DoSetThreadName(const char *name);
|
||||||
void _internal_execute();
|
void _internal_execute();
|
||||||
void _try_virtual_invoke( void (pxThread::*method)() );
|
void _try_virtual_invoke(void (pxThread::*method)());
|
||||||
void _ThreadCleanup();
|
void _ThreadCleanup();
|
||||||
|
|
||||||
static void* _internal_callback( void* func );
|
static void *_internal_callback(void *func);
|
||||||
static void _pt_callback_cleanup( void* handle );
|
static void _pt_callback_cleanup(void *handle);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -240,32 +241,32 @@ namespace Threading
|
||||||
// into smaller sections. For example, if you have 20,000 items to process, the task
|
// into smaller sections. For example, if you have 20,000 items to process, the task
|
||||||
// can be divided into two threads of 10,000 items each.
|
// can be divided into two threads of 10,000 items each.
|
||||||
//
|
//
|
||||||
class BaseTaskThread : public pxThread
|
class BaseTaskThread : public pxThread
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
std::atomic<bool> m_Done;
|
std::atomic<bool> m_Done;
|
||||||
std::atomic<bool> m_TaskPending;
|
std::atomic<bool> m_TaskPending;
|
||||||
Semaphore m_post_TaskComplete;
|
Semaphore m_post_TaskComplete;
|
||||||
Mutex m_lock_TaskComplete;
|
Mutex m_lock_TaskComplete;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~BaseTaskThread() throw() {}
|
virtual ~BaseTaskThread() throw() {}
|
||||||
BaseTaskThread() :
|
BaseTaskThread()
|
||||||
m_Done( false )
|
: m_Done(false)
|
||||||
, m_TaskPending( false )
|
, m_TaskPending(false)
|
||||||
, m_post_TaskComplete()
|
, m_post_TaskComplete()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Block();
|
void Block();
|
||||||
void PostTask();
|
void PostTask();
|
||||||
void WaitForResult();
|
void WaitForResult();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Abstract method run when a task has been posted. Implementing classes should do
|
// Abstract method run when a task has been posted. Implementing classes should do
|
||||||
// all your necessary processing work here.
|
// all your necessary processing work here.
|
||||||
virtual void Task()=0;
|
virtual void Task() = 0;
|
||||||
|
|
||||||
virtual void ExecuteTaskInThread();
|
virtual void ExecuteTaskInThread();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef __WXMSW__
|
#ifdef __WXMSW__
|
||||||
# include <wx/msw/wrapwin.h>
|
#include <wx/msw/wrapwin.h>
|
||||||
#else
|
#else
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -27,7 +27,7 @@
|
||||||
// check, so that we don't have to do it explicitly in every instance where it might
|
// check, so that we don't have to do it explicitly in every instance where it might
|
||||||
// be needed from non-Win32-specific files
|
// be needed from non-Win32-specific files
|
||||||
|
|
||||||
#define NOMINMAX // Disables other libs inclusion of their own min/max macros (we use std instead)
|
#define NOMINMAX // Disables other libs inclusion of their own min/max macros (we use std instead)
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
|
|
@ -22,69 +22,69 @@ namespace Threading
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// RwMutex
|
// RwMutex
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
class RwMutex
|
class RwMutex
|
||||||
{
|
{
|
||||||
DeclareNoncopyableObject(RwMutex);
|
DeclareNoncopyableObject(RwMutex);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
pthread_rwlock_t m_rwlock;
|
pthread_rwlock_t m_rwlock;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RwMutex();
|
RwMutex();
|
||||||
virtual ~RwMutex() throw();
|
virtual ~RwMutex() throw();
|
||||||
|
|
||||||
virtual void AcquireRead();
|
|
||||||
virtual void AcquireWrite();
|
|
||||||
virtual bool TryAcquireRead();
|
|
||||||
virtual bool TryAcquireWrite();
|
|
||||||
|
|
||||||
virtual void Release();
|
virtual void AcquireRead();
|
||||||
};
|
virtual void AcquireWrite();
|
||||||
|
virtual bool TryAcquireRead();
|
||||||
|
virtual bool TryAcquireWrite();
|
||||||
|
|
||||||
|
virtual void Release();
|
||||||
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// BaseScopedReadWriteLock
|
// BaseScopedReadWriteLock
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
class BaseScopedReadWriteLock
|
class BaseScopedReadWriteLock
|
||||||
{
|
{
|
||||||
DeclareNoncopyableObject(BaseScopedReadWriteLock);
|
DeclareNoncopyableObject(BaseScopedReadWriteLock);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
RwMutex& m_lock;
|
RwMutex &m_lock;
|
||||||
bool m_IsLocked;
|
bool m_IsLocked;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BaseScopedReadWriteLock( RwMutex& locker )
|
BaseScopedReadWriteLock(RwMutex &locker)
|
||||||
: m_lock( locker )
|
: m_lock(locker)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~BaseScopedReadWriteLock() throw();
|
virtual ~BaseScopedReadWriteLock() throw();
|
||||||
|
|
||||||
void Release();
|
void Release();
|
||||||
bool IsLocked() const { return m_IsLocked; }
|
bool IsLocked() const { return m_IsLocked; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// ScopedReadLock / ScopedWriteLock
|
// ScopedReadLock / ScopedWriteLock
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
class ScopedReadLock : public BaseScopedReadWriteLock
|
class ScopedReadLock : public BaseScopedReadWriteLock
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ScopedReadLock( RwMutex& locker );
|
ScopedReadLock(RwMutex &locker);
|
||||||
virtual ~ScopedReadLock() throw() {}
|
virtual ~ScopedReadLock() throw() {}
|
||||||
|
|
||||||
void Acquire();
|
void Acquire();
|
||||||
};
|
};
|
||||||
|
|
||||||
class ScopedWriteLock : public BaseScopedReadWriteLock
|
class ScopedWriteLock : public BaseScopedReadWriteLock
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ScopedWriteLock( RwMutex& locker );
|
ScopedWriteLock(RwMutex &locker);
|
||||||
virtual ~ScopedWriteLock() throw() {}
|
virtual ~ScopedWriteLock() throw() {}
|
||||||
|
|
||||||
void Acquire();
|
void Acquire();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ScopedWriteLock( RwMutex& locker, bool isTryLock );
|
ScopedWriteLock(RwMutex &locker, bool isTryLock);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,8 +23,8 @@
|
||||||
|
|
||||||
|
|
||||||
// Microsoft Windows only macro, useful for freeing out COM objects:
|
// Microsoft Windows only macro, useful for freeing out COM objects:
|
||||||
#define safe_release( ptr ) \
|
#define safe_release(ptr) \
|
||||||
((void) (( ( (ptr) != NULL ) && ((ptr)->Release(), !!0) ), (ptr) = NULL))
|
((void)((((ptr) != NULL) && ((ptr)->Release(), !!0)), (ptr) = NULL))
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// SafeArray
|
// SafeArray
|
||||||
|
@ -32,75 +32,75 @@
|
||||||
// Handy little class for allocating a resizable memory block, complete with exception
|
// Handy little class for allocating a resizable memory block, complete with exception
|
||||||
// error handling and automatic cleanup. A lightweight alternative to std::vector.
|
// error handling and automatic cleanup. A lightweight alternative to std::vector.
|
||||||
//
|
//
|
||||||
template< typename T >
|
template <typename T>
|
||||||
class SafeArray
|
class SafeArray
|
||||||
{
|
{
|
||||||
DeclareNoncopyableObject(SafeArray);
|
DeclareNoncopyableObject(SafeArray);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const int DefaultChunkSize = 0x1000 * sizeof(T);
|
static const int DefaultChunkSize = 0x1000 * sizeof(T);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
wxString Name; // user-assigned block name
|
wxString Name; // user-assigned block name
|
||||||
int ChunkSize;
|
int ChunkSize;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
T* m_ptr;
|
T *m_ptr;
|
||||||
int m_size; // size of the allocation of memory
|
int m_size; // size of the allocation of memory
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
SafeArray( const wxChar* name, T* allocated_mem, int initSize );
|
SafeArray(const wxChar *name, T *allocated_mem, int initSize);
|
||||||
virtual T* _virtual_realloc( int newsize );
|
virtual T *_virtual_realloc(int newsize);
|
||||||
|
|
||||||
// A safe array index fetcher. Asserts if the index is out of bounds (dev and debug
|
// A safe array index fetcher. Asserts if the index is out of bounds (dev and debug
|
||||||
// builds only -- no bounds checking is done in release builds).
|
// builds only -- no bounds checking is done in release builds).
|
||||||
T* _getPtr( uint i ) const;
|
T *_getPtr(uint i) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~SafeArray() throw();
|
virtual ~SafeArray() throw();
|
||||||
|
|
||||||
explicit SafeArray( const wxChar* name=L"Unnamed" );
|
explicit SafeArray(const wxChar *name = L"Unnamed");
|
||||||
explicit SafeArray( int initialSize, const wxChar* name=L"Unnamed" );
|
explicit SafeArray(int initialSize, const wxChar *name = L"Unnamed");
|
||||||
|
|
||||||
void Dispose();
|
|
||||||
void ExactAlloc( int newsize );
|
|
||||||
void MakeRoomFor( int newsize )
|
|
||||||
{
|
|
||||||
if( newsize > m_size )
|
|
||||||
ExactAlloc( newsize );
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsDisposed() const { return (m_ptr==NULL); }
|
void Dispose();
|
||||||
|
void ExactAlloc(int newsize);
|
||||||
|
void MakeRoomFor(int newsize)
|
||||||
|
{
|
||||||
|
if (newsize > m_size)
|
||||||
|
ExactAlloc(newsize);
|
||||||
|
}
|
||||||
|
|
||||||
// Returns the size of the memory allocation, as according to the array type.
|
bool IsDisposed() const { return (m_ptr == NULL); }
|
||||||
int GetLength() const { return m_size; }
|
|
||||||
// Returns the size of the memory allocation in bytes.
|
|
||||||
int GetSizeInBytes() const { return m_size * sizeof(T); }
|
|
||||||
|
|
||||||
// Extends the containment area of the array. Extensions are performed
|
// Returns the size of the memory allocation, as according to the array type.
|
||||||
// in chunks.
|
int GetLength() const { return m_size; }
|
||||||
void GrowBy( int items )
|
// Returns the size of the memory allocation in bytes.
|
||||||
{
|
int GetSizeInBytes() const { return m_size * sizeof(T); }
|
||||||
MakeRoomFor( m_size + ChunkSize + items + 1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gets a pointer to the requested allocation index.
|
// Extends the containment area of the array. Extensions are performed
|
||||||
// DevBuilds : Generates assertion if the index is invalid.
|
// in chunks.
|
||||||
T* GetPtr( uint idx=0 ) { return _getPtr( idx ); }
|
void GrowBy(int items)
|
||||||
const T* GetPtr( uint idx=0 ) const { return _getPtr( idx ); }
|
{
|
||||||
|
MakeRoomFor(m_size + ChunkSize + items + 1);
|
||||||
|
}
|
||||||
|
|
||||||
// Gets a pointer to the element directly after the last element in the array.
|
// Gets a pointer to the requested allocation index.
|
||||||
// This is equivalent to doing GetPtr(GetLength()), except that this call *avoids*
|
// DevBuilds : Generates assertion if the index is invalid.
|
||||||
// the out-of-bounds assertion check that typically occurs when you do that. :)
|
T *GetPtr(uint idx = 0) { return _getPtr(idx); }
|
||||||
T* GetPtrEnd() { return &m_ptr[m_size]; }
|
const T *GetPtr(uint idx = 0) const { return _getPtr(idx); }
|
||||||
const T* GetPtrEnd() const { return &m_ptr[m_size]; }
|
|
||||||
|
|
||||||
// Gets an element of this memory allocation much as if it were an array.
|
// Gets a pointer to the element directly after the last element in the array.
|
||||||
// DevBuilds : Generates assertion if the index is invalid.
|
// This is equivalent to doing GetPtr(GetLength()), except that this call *avoids*
|
||||||
T& operator[]( int idx ) { return *_getPtr( (uint)idx ); }
|
// the out-of-bounds assertion check that typically occurs when you do that. :)
|
||||||
const T& operator[]( int idx ) const { return *_getPtr( (uint)idx ); }
|
T *GetPtrEnd() { return &m_ptr[m_size]; }
|
||||||
|
const T *GetPtrEnd() const { return &m_ptr[m_size]; }
|
||||||
|
|
||||||
virtual SafeArray<T>* Clone() const;
|
// Gets an element of this memory allocation much as if it were an array.
|
||||||
|
// DevBuilds : Generates assertion if the index is invalid.
|
||||||
|
T &operator[](int idx) { return *_getPtr((uint)idx); }
|
||||||
|
const T &operator[](int idx) const { return *_getPtr((uint)idx); }
|
||||||
|
|
||||||
|
virtual SafeArray<T> *Clone() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -113,76 +113,76 @@ public:
|
||||||
// * Classes with copy constructors (copying is done using performance memcpy)
|
// * Classes with copy constructors (copying is done using performance memcpy)
|
||||||
// * Classes with destructors (they're not called, sorry!)
|
// * Classes with destructors (they're not called, sorry!)
|
||||||
//
|
//
|
||||||
template< typename T >
|
template <typename T>
|
||||||
class SafeList
|
class SafeList
|
||||||
{
|
{
|
||||||
DeclareNoncopyableObject(SafeList);
|
DeclareNoncopyableObject(SafeList);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const int DefaultChunkSize = 0x80 * sizeof(T);
|
static const int DefaultChunkSize = 0x80 * sizeof(T);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
wxString Name; // user-assigned block name
|
wxString Name; // user-assigned block name
|
||||||
int ChunkSize; // assigned DefaultChunkSize on init, reconfigurable at any time.
|
int ChunkSize; // assigned DefaultChunkSize on init, reconfigurable at any time.
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
T* m_ptr;
|
T *m_ptr;
|
||||||
int m_allocsize; // size of the allocation of memory
|
int m_allocsize; // size of the allocation of memory
|
||||||
uint m_length; // length of the array (active items, not buffer allocation)
|
uint m_length; // length of the array (active items, not buffer allocation)
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual T* _virtual_realloc( int newsize );
|
virtual T *_virtual_realloc(int newsize);
|
||||||
void _MakeRoomFor_threshold( int newsize );
|
void _MakeRoomFor_threshold(int newsize);
|
||||||
|
|
||||||
T* _getPtr( uint i ) const;
|
T *_getPtr(uint i) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~SafeList() throw();
|
virtual ~SafeList() throw();
|
||||||
explicit SafeList( const wxChar* name=L"Unnamed" );
|
explicit SafeList(const wxChar *name = L"Unnamed");
|
||||||
explicit SafeList( int initialSize, const wxChar* name=L"Unnamed" );
|
explicit SafeList(int initialSize, const wxChar *name = L"Unnamed");
|
||||||
virtual SafeList<T>* Clone() const;
|
virtual SafeList<T> *Clone() const;
|
||||||
|
|
||||||
void Remove( int index );
|
void Remove(int index);
|
||||||
void MakeRoomFor( int blockSize );
|
void MakeRoomFor(int blockSize);
|
||||||
|
|
||||||
T& New();
|
T &New();
|
||||||
int Add( const T& src );
|
int Add(const T &src);
|
||||||
T& AddNew( const T& src );
|
T &AddNew(const T &src);
|
||||||
|
|
||||||
// Returns the size of the list, as according to the array type. This includes
|
// Returns the size of the list, as according to the array type. This includes
|
||||||
// mapped items only. The actual size of the allocation may differ.
|
// mapped items only. The actual size of the allocation may differ.
|
||||||
int GetLength() const { return m_length; }
|
int GetLength() const { return m_length; }
|
||||||
|
|
||||||
// Returns the size of the list, in bytes. This includes mapped items only.
|
// Returns the size of the list, in bytes. This includes mapped items only.
|
||||||
// The actual size of the allocation may differ.
|
// The actual size of the allocation may differ.
|
||||||
int GetSizeInBytes() const { return m_length * sizeof(T); }
|
int GetSizeInBytes() const { return m_length * sizeof(T); }
|
||||||
|
|
||||||
void MatchLengthToAllocatedSize()
|
void MatchLengthToAllocatedSize()
|
||||||
{
|
{
|
||||||
m_length = m_allocsize;
|
m_length = m_allocsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrowBy( int items )
|
void GrowBy(int items)
|
||||||
{
|
{
|
||||||
MakeRoomFor( m_length + ChunkSize + items + 1 );
|
MakeRoomFor(m_length + ChunkSize + items + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the item length to zero. Does not free memory allocations.
|
// Sets the item length to zero. Does not free memory allocations.
|
||||||
void Clear()
|
void Clear()
|
||||||
{
|
{
|
||||||
m_length = 0;
|
m_length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets an element of this memory allocation much as if it were an array.
|
// Gets an element of this memory allocation much as if it were an array.
|
||||||
// DevBuilds : Generates assertion if the index is invalid.
|
// DevBuilds : Generates assertion if the index is invalid.
|
||||||
T& operator[]( int idx ) { return *_getPtr( (uint)idx ); }
|
T &operator[](int idx) { return *_getPtr((uint)idx); }
|
||||||
const T& operator[]( int idx ) const { return *_getPtr( (uint)idx ); }
|
const T &operator[](int idx) const { return *_getPtr((uint)idx); }
|
||||||
|
|
||||||
T* GetPtr() { return m_ptr; }
|
T *GetPtr() { return m_ptr; }
|
||||||
const T* GetPtr() const { return m_ptr; }
|
const T *GetPtr() const { return m_ptr; }
|
||||||
|
|
||||||
T& GetLast() { return m_ptr[m_length-1]; }
|
T &GetLast() { return m_ptr[m_length - 1]; }
|
||||||
const T& GetLast() const{ return m_ptr[m_length-1]; }
|
const T &GetLast() const { return m_ptr[m_length - 1]; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -192,25 +192,24 @@ public:
|
||||||
// exception-based error handling and automatic cleanup.
|
// exception-based error handling and automatic cleanup.
|
||||||
// This one supports aligned data allocations too!
|
// This one supports aligned data allocations too!
|
||||||
|
|
||||||
template< typename T, uint Alignment >
|
template <typename T, uint Alignment>
|
||||||
class SafeAlignedArray : public SafeArray<T>
|
class SafeAlignedArray : public SafeArray<T>
|
||||||
{
|
{
|
||||||
typedef SafeArray<T> _parent;
|
typedef SafeArray<T> _parent;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
T* _virtual_realloc( int newsize );
|
T *_virtual_realloc(int newsize);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using _parent::operator[];
|
using _parent::operator[];
|
||||||
|
|
||||||
virtual ~SafeAlignedArray() throw();
|
virtual ~SafeAlignedArray() throw();
|
||||||
|
|
||||||
explicit SafeAlignedArray( const wxChar* name=L"Unnamed" ) :
|
explicit SafeAlignedArray(const wxChar *name = L"Unnamed")
|
||||||
SafeArray<T>::SafeArray( name )
|
: SafeArray<T>::SafeArray(name)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit SafeAlignedArray( int initialSize, const wxChar* name=L"Unnamed" );
|
explicit SafeAlignedArray(int initialSize, const wxChar *name = L"Unnamed");
|
||||||
virtual SafeAlignedArray<T,Alignment>* Clone() const;
|
virtual SafeAlignedArray<T, Alignment> *Clone() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -21,104 +21,104 @@
|
||||||
// use its own memory allocation (with an aligned memory, for example).
|
// use its own memory allocation (with an aligned memory, for example).
|
||||||
// Throws:
|
// Throws:
|
||||||
// Exception::OutOfMemory if the allocated_mem pointer is NULL.
|
// Exception::OutOfMemory if the allocated_mem pointer is NULL.
|
||||||
template< typename T >
|
template <typename T>
|
||||||
SafeArray<T>::SafeArray( const wxChar* name, T* allocated_mem, int initSize )
|
SafeArray<T>::SafeArray(const wxChar *name, T *allocated_mem, int initSize)
|
||||||
: Name( name )
|
: Name(name)
|
||||||
{
|
{
|
||||||
ChunkSize = DefaultChunkSize;
|
ChunkSize = DefaultChunkSize;
|
||||||
m_ptr = allocated_mem;
|
m_ptr = allocated_mem;
|
||||||
m_size = initSize;
|
m_size = initSize;
|
||||||
|
|
||||||
if( m_ptr == NULL )
|
if (m_ptr == NULL)
|
||||||
throw Exception::OutOfMemory(name)
|
throw Exception::OutOfMemory(name)
|
||||||
.SetDiagMsg(wxsFormat(L"Called from 'SafeArray::ctor' [size=%d]", initSize));
|
.SetDiagMsg(wxsFormat(L"Called from 'SafeArray::ctor' [size=%d]", initSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template <typename T>
|
||||||
T* SafeArray<T>::_virtual_realloc( int newsize )
|
T *SafeArray<T>::_virtual_realloc(int newsize)
|
||||||
{
|
{
|
||||||
T* retval = (T*)((m_ptr == NULL) ?
|
T *retval = (T *)((m_ptr == NULL) ?
|
||||||
malloc( newsize * sizeof(T) ) :
|
malloc(newsize * sizeof(T)) :
|
||||||
realloc( m_ptr, newsize * sizeof(T) )
|
realloc(m_ptr, newsize * sizeof(T)));
|
||||||
);
|
|
||||||
|
|
||||||
if( IsDebugBuild && (retval != NULL))
|
|
||||||
{
|
|
||||||
// Zero everything out to 0xbaadf00d, so that its obviously uncleared
|
|
||||||
// to a debuggee
|
|
||||||
|
|
||||||
u32* fill = (u32*)&retval[m_size];
|
if (IsDebugBuild && (retval != NULL)) {
|
||||||
const u32* end = (u32*)((((uptr)&retval[newsize-1])-3) & ~0x3);
|
// Zero everything out to 0xbaadf00d, so that its obviously uncleared
|
||||||
for( ; fill<end; ++fill ) *fill = 0xbaadf00d;
|
// to a debuggee
|
||||||
}
|
|
||||||
|
u32 *fill = (u32 *)&retval[m_size];
|
||||||
return retval;
|
const u32 *end = (u32 *)((((uptr)&retval[newsize - 1]) - 3) & ~0x3);
|
||||||
|
for (; fill < end; ++fill)
|
||||||
|
*fill = 0xbaadf00d;
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template <typename T>
|
||||||
SafeArray<T>::~SafeArray() throw()
|
SafeArray<T>::~SafeArray() throw()
|
||||||
{
|
{
|
||||||
safe_free( m_ptr );
|
safe_free(m_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template <typename T>
|
||||||
SafeArray<T>::SafeArray( const wxChar* name )
|
SafeArray<T>::SafeArray(const wxChar *name)
|
||||||
: Name( name )
|
: Name(name)
|
||||||
{
|
{
|
||||||
ChunkSize = DefaultChunkSize;
|
ChunkSize = DefaultChunkSize;
|
||||||
m_ptr = NULL;
|
m_ptr = NULL;
|
||||||
m_size = 0;
|
m_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template <typename T>
|
||||||
SafeArray<T>::SafeArray( int initialSize, const wxChar* name )
|
SafeArray<T>::SafeArray(int initialSize, const wxChar *name)
|
||||||
: Name( name )
|
: Name(name)
|
||||||
{
|
{
|
||||||
ChunkSize = DefaultChunkSize;
|
ChunkSize = DefaultChunkSize;
|
||||||
m_ptr = (initialSize==0) ? NULL : (T*)malloc( initialSize * sizeof(T) );
|
m_ptr = (initialSize == 0) ? NULL : (T *)malloc(initialSize * sizeof(T));
|
||||||
m_size = initialSize;
|
m_size = initialSize;
|
||||||
|
|
||||||
if( (initialSize != 0) && (m_ptr == NULL) )
|
if ((initialSize != 0) && (m_ptr == NULL))
|
||||||
throw Exception::OutOfMemory(name)
|
throw Exception::OutOfMemory(name)
|
||||||
.SetDiagMsg(wxsFormat(L"Called from 'SafeArray::ctor' [size=%d]", initialSize));
|
.SetDiagMsg(wxsFormat(L"Called from 'SafeArray::ctor' [size=%d]", initialSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clears the contents of the array to zero, and frees all memory allocations.
|
// Clears the contents of the array to zero, and frees all memory allocations.
|
||||||
template< typename T >
|
template <typename T>
|
||||||
void SafeArray<T>::Dispose()
|
void SafeArray<T>::Dispose()
|
||||||
{
|
{
|
||||||
m_size = 0;
|
m_size = 0;
|
||||||
safe_free( m_ptr );
|
safe_free(m_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template <typename T>
|
||||||
T* SafeArray<T>::_getPtr( uint i ) const
|
T *SafeArray<T>::_getPtr(uint i) const
|
||||||
{
|
{
|
||||||
IndexBoundsAssumeDev( WX_STR(Name), i, m_size );
|
IndexBoundsAssumeDev(WX_STR(Name), i, m_size);
|
||||||
return &m_ptr[i];
|
return &m_ptr[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
// reallocates the array to the explicit size. Can be used to shrink or grow an
|
// reallocates the array to the explicit size. Can be used to shrink or grow an
|
||||||
// array, and bypasses the internal threshold growth indicators.
|
// array, and bypasses the internal threshold growth indicators.
|
||||||
template< typename T >
|
template <typename T>
|
||||||
void SafeArray<T>::ExactAlloc( int newsize )
|
void SafeArray<T>::ExactAlloc(int newsize)
|
||||||
{
|
{
|
||||||
if( newsize == m_size ) return;
|
if (newsize == m_size)
|
||||||
|
return;
|
||||||
|
|
||||||
m_ptr = _virtual_realloc( newsize );
|
m_ptr = _virtual_realloc(newsize);
|
||||||
if( m_ptr == NULL )
|
if (m_ptr == NULL)
|
||||||
throw Exception::OutOfMemory(Name)
|
throw Exception::OutOfMemory(Name)
|
||||||
.SetDiagMsg(wxsFormat(L"Called from 'SafeArray::ExactAlloc' [oldsize=%d] [newsize=%d]", m_size, newsize));
|
.SetDiagMsg(wxsFormat(L"Called from 'SafeArray::ExactAlloc' [oldsize=%d] [newsize=%d]", m_size, newsize));
|
||||||
|
|
||||||
m_size = newsize;
|
m_size = newsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template <typename T>
|
||||||
SafeArray<T>* SafeArray<T>::Clone() const
|
SafeArray<T> *SafeArray<T>::Clone() const
|
||||||
{
|
{
|
||||||
SafeArray<T>* retval = new SafeArray<T>( m_size );
|
SafeArray<T> *retval = new SafeArray<T>(m_size);
|
||||||
memcpy( retval->GetPtr(), m_ptr, sizeof(T) * m_size );
|
memcpy(retval->GetPtr(), m_ptr, sizeof(T) * m_size);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -126,164 +126,158 @@ SafeArray<T>* SafeArray<T>::Clone() const
|
||||||
// SafeAlignedArray<T> (implementations)
|
// SafeAlignedArray<T> (implementations)
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
template< typename T, uint Alignment >
|
template <typename T, uint Alignment>
|
||||||
T* SafeAlignedArray<T,Alignment>::_virtual_realloc( int newsize )
|
T *SafeAlignedArray<T, Alignment>::_virtual_realloc(int newsize)
|
||||||
{
|
{
|
||||||
return (T*)( ( this->m_ptr == NULL ) ?
|
return (T *)((this->m_ptr == NULL) ?
|
||||||
_aligned_malloc( newsize * sizeof(T), Alignment ) :
|
_aligned_malloc(newsize * sizeof(T), Alignment) :
|
||||||
pcsx2_aligned_realloc( this->m_ptr, newsize * sizeof(T), Alignment, this->m_size * sizeof(T) )
|
pcsx2_aligned_realloc(this->m_ptr, newsize * sizeof(T), Alignment, this->m_size * sizeof(T)));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Appends "(align: xx)" to the name of the allocation in devel builds.
|
// Appends "(align: xx)" to the name of the allocation in devel builds.
|
||||||
// Maybe useful,maybe not... no harm in attaching it. :D
|
// Maybe useful,maybe not... no harm in attaching it. :D
|
||||||
|
|
||||||
template< typename T, uint Alignment >
|
template <typename T, uint Alignment>
|
||||||
SafeAlignedArray<T,Alignment>::~SafeAlignedArray() throw()
|
SafeAlignedArray<T, Alignment>::~SafeAlignedArray() throw()
|
||||||
{
|
{
|
||||||
safe_aligned_free( this->m_ptr );
|
safe_aligned_free(this->m_ptr);
|
||||||
// mptr is set to null, so the parent class's destructor won't re-free it.
|
// mptr is set to null, so the parent class's destructor won't re-free it.
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T, uint Alignment >
|
template <typename T, uint Alignment>
|
||||||
SafeAlignedArray<T,Alignment>::SafeAlignedArray( int initialSize, const wxChar* name ) :
|
SafeAlignedArray<T, Alignment>::SafeAlignedArray(int initialSize, const wxChar *name)
|
||||||
SafeArray<T>::SafeArray(
|
: SafeArray<T>::SafeArray(
|
||||||
name,
|
name,
|
||||||
(T*)_aligned_malloc( initialSize * sizeof(T), Alignment ),
|
(T *)_aligned_malloc(initialSize * sizeof(T), Alignment),
|
||||||
initialSize
|
initialSize)
|
||||||
)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T, uint Alignment >
|
template <typename T, uint Alignment>
|
||||||
SafeAlignedArray<T,Alignment>* SafeAlignedArray<T,Alignment>::Clone() const
|
SafeAlignedArray<T, Alignment> *SafeAlignedArray<T, Alignment>::Clone() const
|
||||||
{
|
{
|
||||||
SafeAlignedArray<T,Alignment>* retval = new SafeAlignedArray<T,Alignment>( this->m_size );
|
SafeAlignedArray<T, Alignment> *retval = new SafeAlignedArray<T, Alignment>(this->m_size);
|
||||||
memcpy( retval->GetPtr(), this->m_ptr, sizeof(T) * this->m_size );
|
memcpy(retval->GetPtr(), this->m_ptr, sizeof(T) * this->m_size);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// SafeList<T> (implementations)
|
// SafeList<T> (implementations)
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
template< typename T >
|
template <typename T>
|
||||||
T* SafeList<T>::_virtual_realloc( int newsize )
|
T *SafeList<T>::_virtual_realloc(int newsize)
|
||||||
{
|
{
|
||||||
return (T*)realloc( m_ptr, newsize * sizeof(T) );
|
return (T *)realloc(m_ptr, newsize * sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template <typename T>
|
||||||
SafeList<T>::~SafeList() throw()
|
SafeList<T>::~SafeList() throw()
|
||||||
{
|
{
|
||||||
safe_free( m_ptr );
|
safe_free(m_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template <typename T>
|
||||||
SafeList<T>::SafeList( const wxChar* name )
|
SafeList<T>::SafeList(const wxChar *name)
|
||||||
: Name( name )
|
: Name(name)
|
||||||
{
|
{
|
||||||
ChunkSize = DefaultChunkSize;
|
ChunkSize = DefaultChunkSize;
|
||||||
m_ptr = NULL;
|
m_ptr = NULL;
|
||||||
m_allocsize = 0;
|
m_allocsize = 0;
|
||||||
m_length = 0;
|
m_length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template <typename T>
|
||||||
SafeList<T>::SafeList( int initialSize, const wxChar* name )
|
SafeList<T>::SafeList(int initialSize, const wxChar *name)
|
||||||
: Name( name )
|
: Name(name)
|
||||||
{
|
{
|
||||||
ChunkSize = DefaultChunkSize;
|
ChunkSize = DefaultChunkSize;
|
||||||
m_allocsize = initialSize;
|
m_allocsize = initialSize;
|
||||||
m_length = 0;
|
m_length = 0;
|
||||||
m_ptr = (T*)malloc( initialSize * sizeof(T) );
|
m_ptr = (T *)malloc(initialSize * sizeof(T));
|
||||||
|
|
||||||
if( m_ptr == NULL )
|
if (m_ptr == NULL)
|
||||||
throw Exception::OutOfMemory(Name)
|
throw Exception::OutOfMemory(Name)
|
||||||
.SetDiagMsg(wxsFormat(L"called from 'SafeList::ctor' [length=%d]", m_length));
|
.SetDiagMsg(wxsFormat(L"called from 'SafeList::ctor' [length=%d]", m_length));
|
||||||
|
|
||||||
for( int i=0; i<m_allocsize; ++i )
|
|
||||||
{
|
|
||||||
new (&m_ptr[i]) T();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
for (int i = 0; i < m_allocsize; ++i) {
|
||||||
|
new (&m_ptr[i]) T();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template <typename T>
|
||||||
T* SafeList<T>::_getPtr( uint i ) const
|
T *SafeList<T>::_getPtr(uint i) const
|
||||||
{
|
{
|
||||||
IndexBoundsAssumeDev( WX_STR(Name), i, m_length );
|
IndexBoundsAssumeDev(WX_STR(Name), i, m_length);
|
||||||
return &m_ptr[i];
|
return &m_ptr[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensures that the allocation is large enough to fit data of the
|
// Ensures that the allocation is large enough to fit data of the
|
||||||
// amount requested. The memory allocation is not resized smaller.
|
// amount requested. The memory allocation is not resized smaller.
|
||||||
template< typename T >
|
template <typename T>
|
||||||
void SafeList<T>::MakeRoomFor( int blockSize )
|
void SafeList<T>::MakeRoomFor(int blockSize)
|
||||||
{
|
{
|
||||||
if( blockSize > m_allocsize )
|
if (blockSize > m_allocsize) {
|
||||||
{
|
const int newalloc = blockSize + ChunkSize;
|
||||||
const int newalloc = blockSize + ChunkSize;
|
m_ptr = _virtual_realloc(newalloc);
|
||||||
m_ptr = _virtual_realloc( newalloc );
|
if (m_ptr == NULL)
|
||||||
if( m_ptr == NULL )
|
throw Exception::OutOfMemory(Name)
|
||||||
throw Exception::OutOfMemory(Name)
|
.SetDiagMsg(wxsFormat(L"Called from 'SafeList::MakeRoomFor' [oldlen=%d] [newlen=%d]", m_length, blockSize));
|
||||||
.SetDiagMsg(wxsFormat(L"Called from 'SafeList::MakeRoomFor' [oldlen=%d] [newlen=%d]", m_length, blockSize));
|
|
||||||
|
|
||||||
for( ; m_allocsize<newalloc; ++m_allocsize )
|
for (; m_allocsize < newalloc; ++m_allocsize) {
|
||||||
{
|
new (&m_ptr[m_allocsize]) T();
|
||||||
new (&m_ptr[m_allocsize]) T();
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Appends an item to the end of the list and returns a handle to it.
|
// Appends an item to the end of the list and returns a handle to it.
|
||||||
template< typename T >
|
template <typename T>
|
||||||
T& SafeList<T>::New()
|
T &SafeList<T>::New()
|
||||||
{
|
{
|
||||||
_MakeRoomFor_threshold( m_length + 1 );
|
_MakeRoomFor_threshold(m_length + 1);
|
||||||
return m_ptr[m_length++];
|
return m_ptr[m_length++];
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template <typename T>
|
||||||
int SafeList<T>::Add( const T& src )
|
int SafeList<T>::Add(const T &src)
|
||||||
{
|
{
|
||||||
_MakeRoomFor_threshold( m_length + 1 );
|
_MakeRoomFor_threshold(m_length + 1);
|
||||||
m_ptr[m_length] = src;
|
m_ptr[m_length] = src;
|
||||||
return m_length++;
|
return m_length++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Same as Add, but returns the handle of the new object instead of it's array index.
|
// Same as Add, but returns the handle of the new object instead of it's array index.
|
||||||
template< typename T >
|
template <typename T>
|
||||||
T& SafeList<T>::AddNew( const T& src )
|
T &SafeList<T>::AddNew(const T &src)
|
||||||
{
|
{
|
||||||
_MakeRoomFor_threshold( m_length + 1 );
|
_MakeRoomFor_threshold(m_length + 1);
|
||||||
m_ptr[m_length] = src;
|
m_ptr[m_length] = src;
|
||||||
return m_ptr[m_length];
|
return m_ptr[m_length];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Performs a standard array-copy removal of the given item. All items past the
|
// Performs a standard array-copy removal of the given item. All items past the
|
||||||
// given item are copied over.
|
// given item are copied over.
|
||||||
// DevBuilds : Generates assertion if the index is invalid.
|
// DevBuilds : Generates assertion if the index is invalid.
|
||||||
template< typename T >
|
template <typename T>
|
||||||
void SafeList<T>::Remove( int index )
|
void SafeList<T>::Remove(int index)
|
||||||
{
|
{
|
||||||
IndexBoundsAssumeDev( Name.c_str(), index, m_length );
|
IndexBoundsAssumeDev(Name.c_str(), index, m_length);
|
||||||
|
|
||||||
int copylen = m_length - index;
|
int copylen = m_length - index;
|
||||||
if( copylen > 0 )
|
if (copylen > 0)
|
||||||
memcpy( &m_ptr[index], &m_ptr[index+1], copylen );
|
memcpy(&m_ptr[index], &m_ptr[index + 1], copylen);
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template <typename T>
|
||||||
SafeList<T>* SafeList<T>::Clone() const
|
SafeList<T> *SafeList<T>::Clone() const
|
||||||
{
|
{
|
||||||
SafeList<T>* retval = new SafeList<T>( m_length );
|
SafeList<T> *retval = new SafeList<T>(m_length);
|
||||||
memcpy( retval->m_ptr, m_ptr, sizeof(T) * m_length );
|
memcpy(retval->m_ptr, m_ptr, sizeof(T) * m_length);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template <typename T>
|
||||||
void SafeList<T>::_MakeRoomFor_threshold( int newsize )
|
void SafeList<T>::_MakeRoomFor_threshold(int newsize)
|
||||||
{
|
{
|
||||||
MakeRoomFor( newsize + ChunkSize );
|
MakeRoomFor(newsize + ChunkSize);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,43 +27,43 @@
|
||||||
// Safe deallocation macros -- checks pointer validity (non-null) when needed, and sets
|
// Safe deallocation macros -- checks pointer validity (non-null) when needed, and sets
|
||||||
// pointer to null after deallocation.
|
// pointer to null after deallocation.
|
||||||
|
|
||||||
#define safe_delete( ptr ) \
|
#define safe_delete(ptr) \
|
||||||
((void) (delete (ptr)), (ptr) = NULL)
|
((void)(delete (ptr)), (ptr) = NULL)
|
||||||
|
|
||||||
#define safe_delete_array( ptr ) \
|
#define safe_delete_array(ptr) \
|
||||||
((void) (delete[] (ptr)), (ptr) = NULL)
|
((void)(delete[](ptr)), (ptr) = NULL)
|
||||||
|
|
||||||
// No checks for NULL -- wxWidgets says it's safe to skip NULL checks and it runs on
|
// No checks for NULL -- wxWidgets says it's safe to skip NULL checks and it runs on
|
||||||
// just about every compiler and libc implementation of any recentness.
|
// just about every compiler and libc implementation of any recentness.
|
||||||
#define safe_free( ptr ) \
|
#define safe_free(ptr) \
|
||||||
( (void) (free( ptr ), !!0), (ptr) = NULL )
|
((void)(free(ptr), !!0), (ptr) = NULL)
|
||||||
//((void) (( ( (ptr) != NULL ) && (free( ptr ), !!0) ), (ptr) = NULL))
|
//((void) (( ( (ptr) != NULL ) && (free( ptr ), !!0) ), (ptr) = NULL))
|
||||||
|
|
||||||
#define safe_fclose( ptr ) \
|
#define safe_fclose(ptr) \
|
||||||
((void) (( ( (ptr) != NULL ) && (fclose( ptr ), !!0) ), (ptr) = NULL))
|
((void)((((ptr) != NULL) && (fclose(ptr), !!0)), (ptr) = NULL))
|
||||||
|
|
||||||
// Implementation note: all known implementations of _aligned_free check the pointer for
|
// Implementation note: all known implementations of _aligned_free check the pointer for
|
||||||
// NULL status (our implementation under GCC, and microsoft's under MSVC), so no need to
|
// NULL status (our implementation under GCC, and microsoft's under MSVC), so no need to
|
||||||
// do it here.
|
// do it here.
|
||||||
#define safe_aligned_free( ptr ) \
|
#define safe_aligned_free(ptr) \
|
||||||
((void) ( _aligned_free( ptr ), (ptr) = NULL ))
|
((void)(_aligned_free(ptr), (ptr) = NULL))
|
||||||
|
|
||||||
// aligned_malloc: Implement/declare linux equivalents here!
|
// aligned_malloc: Implement/declare linux equivalents here!
|
||||||
#if !defined(_MSC_VER)
|
#if !defined(_MSC_VER)
|
||||||
extern void* __fastcall _aligned_malloc(size_t size, size_t align);
|
extern void *__fastcall _aligned_malloc(size_t size, size_t align);
|
||||||
extern void* __fastcall pcsx2_aligned_realloc(void* handle, size_t new_size, size_t align, size_t old_size);
|
extern void *__fastcall pcsx2_aligned_realloc(void *handle, size_t new_size, size_t align, size_t old_size);
|
||||||
extern void _aligned_free(void* pmem);
|
extern void _aligned_free(void *pmem);
|
||||||
#else
|
#else
|
||||||
#define pcsx2_aligned_realloc(handle, new_size, align, old_size) \
|
#define pcsx2_aligned_realloc(handle, new_size, align, old_size) \
|
||||||
_aligned_realloc(handle, new_size, align)
|
_aligned_realloc(handle, new_size, align)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// pxDoOutOfMemory
|
// pxDoOutOfMemory
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
typedef void FnType_OutOfMemory( uptr blocksize );
|
typedef void FnType_OutOfMemory(uptr blocksize);
|
||||||
typedef FnType_OutOfMemory* Fnptr_OutOfMemory;
|
typedef FnType_OutOfMemory *Fnptr_OutOfMemory;
|
||||||
|
|
||||||
// This method is meant to be assigned by applications that link against pxWex. It is called
|
// This method is meant to be assigned by applications that link against pxWex. It is called
|
||||||
// (invoked) prior to most pxWex built-in memory/array classes throwing exceptions, and can be
|
// (invoked) prior to most pxWex built-in memory/array classes throwing exceptions, and can be
|
||||||
|
@ -89,77 +89,78 @@ extern Fnptr_OutOfMemory pxDoOutOfMemory;
|
||||||
// destructing container for malloc. The entire class is almost completely dependency free,
|
// destructing container for malloc. The entire class is almost completely dependency free,
|
||||||
// and thus can be included everywhere and anywhere without dependency hassles.
|
// and thus can be included everywhere and anywhere without dependency hassles.
|
||||||
//
|
//
|
||||||
template< typename T >
|
template <typename T>
|
||||||
class BaseScopedAlloc
|
class BaseScopedAlloc
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
T* m_buffer;
|
T *m_buffer;
|
||||||
uint m_size;
|
uint m_size;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BaseScopedAlloc()
|
BaseScopedAlloc()
|
||||||
{
|
{
|
||||||
m_buffer = NULL;
|
m_buffer = NULL;
|
||||||
m_size = 0;
|
m_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~BaseScopedAlloc() throw()
|
virtual ~BaseScopedAlloc() throw()
|
||||||
{
|
{
|
||||||
//pxAssert(m_buffer==NULL);
|
//pxAssert(m_buffer==NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
size_t GetSize() const { return m_size; }
|
size_t GetSize() const { return m_size; }
|
||||||
size_t GetLength() const { return m_size; }
|
size_t GetLength() const { return m_size; }
|
||||||
|
|
||||||
// Allocates the object to the specified size. If an existing allocation is in
|
|
||||||
// place, it is freed and replaced with the new allocation, and all data is lost.
|
|
||||||
// Parameter:
|
|
||||||
// newSize - size of the new allocation, in elements (not bytes!). If the specified
|
|
||||||
// size is 0, the the allocation is freed, same as calling Free().
|
|
||||||
virtual void Alloc( size_t newsize )=0;
|
|
||||||
|
|
||||||
// Re-sizes the allocation to the requested size, without any data loss.
|
// Allocates the object to the specified size. If an existing allocation is in
|
||||||
// Parameter:
|
// place, it is freed and replaced with the new allocation, and all data is lost.
|
||||||
// newSize - size of the new allocation, in elements (not bytes!). If the specified
|
// Parameter:
|
||||||
// size is 0, the the allocation is freed, same as calling Free().
|
// newSize - size of the new allocation, in elements (not bytes!). If the specified
|
||||||
virtual void Resize( size_t newsize )=0;
|
// size is 0, the the allocation is freed, same as calling Free().
|
||||||
|
virtual void Alloc(size_t newsize) = 0;
|
||||||
|
|
||||||
void Free()
|
// Re-sizes the allocation to the requested size, without any data loss.
|
||||||
{
|
// Parameter:
|
||||||
Alloc( 0 );
|
// newSize - size of the new allocation, in elements (not bytes!). If the specified
|
||||||
}
|
// size is 0, the the allocation is freed, same as calling Free().
|
||||||
|
virtual void Resize(size_t newsize) = 0;
|
||||||
// Makes enough room for the requested size. Existing data in the array is retained.
|
|
||||||
void MakeRoomFor( uint size )
|
|
||||||
{
|
|
||||||
if (size <= m_size) return;
|
|
||||||
Resize( size );
|
|
||||||
}
|
|
||||||
|
|
||||||
T* GetPtr( uint idx=0 ) const
|
void Free()
|
||||||
{
|
{
|
||||||
#if pxUSE_SECURE_MALLOC
|
Alloc(0);
|
||||||
IndexBoundsAssumeDev( "ScopedAlloc", idx, m_size );
|
}
|
||||||
#endif
|
|
||||||
return &m_buffer[idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
T& operator[]( uint idx )
|
// Makes enough room for the requested size. Existing data in the array is retained.
|
||||||
{
|
void MakeRoomFor(uint size)
|
||||||
#if pxUSE_SECURE_MALLOC
|
{
|
||||||
IndexBoundsAssumeDev( "ScopedAlloc", idx, m_size );
|
if (size <= m_size)
|
||||||
#endif
|
return;
|
||||||
return m_buffer[idx];
|
Resize(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
const T& operator[]( uint idx ) const
|
T *GetPtr(uint idx = 0) const
|
||||||
{
|
{
|
||||||
#if pxUSE_SECURE_MALLOC
|
#if pxUSE_SECURE_MALLOC
|
||||||
IndexBoundsAssumeDev( "ScopedAlloc", idx, m_size );
|
IndexBoundsAssumeDev("ScopedAlloc", idx, m_size);
|
||||||
#endif
|
#endif
|
||||||
return m_buffer[idx];
|
return &m_buffer[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
T &operator[](uint idx)
|
||||||
|
{
|
||||||
|
#if pxUSE_SECURE_MALLOC
|
||||||
|
IndexBoundsAssumeDev("ScopedAlloc", idx, m_size);
|
||||||
|
#endif
|
||||||
|
return m_buffer[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
const T &operator[](uint idx) const
|
||||||
|
{
|
||||||
|
#if pxUSE_SECURE_MALLOC
|
||||||
|
IndexBoundsAssumeDev("ScopedAlloc", idx, m_size);
|
||||||
|
#endif
|
||||||
|
return m_buffer[idx];
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -171,43 +172,45 @@ public:
|
||||||
//
|
//
|
||||||
// See docs for BaseScopedAlloc for details and rationale.
|
// See docs for BaseScopedAlloc for details and rationale.
|
||||||
//
|
//
|
||||||
template< typename T >
|
template <typename T>
|
||||||
class ScopedAlloc : public BaseScopedAlloc<T>
|
class ScopedAlloc : public BaseScopedAlloc<T>
|
||||||
{
|
{
|
||||||
typedef BaseScopedAlloc<T> _parent;
|
typedef BaseScopedAlloc<T> _parent;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ScopedAlloc( size_t size=0 ) : _parent()
|
ScopedAlloc(size_t size = 0)
|
||||||
{
|
: _parent()
|
||||||
Alloc(size);
|
{
|
||||||
}
|
Alloc(size);
|
||||||
|
}
|
||||||
|
|
||||||
virtual ~ScopedAlloc() throw()
|
virtual ~ScopedAlloc() throw()
|
||||||
{
|
{
|
||||||
safe_free(this->m_buffer);
|
safe_free(this->m_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void Alloc( size_t newsize )
|
virtual void Alloc(size_t newsize)
|
||||||
{
|
{
|
||||||
safe_free(this->m_buffer);
|
safe_free(this->m_buffer);
|
||||||
this->m_size = newsize;
|
this->m_size = newsize;
|
||||||
if (!this->m_size) return;
|
if (!this->m_size)
|
||||||
|
return;
|
||||||
|
|
||||||
this->m_buffer = (T*)malloc( this->m_size * sizeof(T) );
|
this->m_buffer = (T *)malloc(this->m_size * sizeof(T));
|
||||||
if (!this->m_buffer)
|
if (!this->m_buffer)
|
||||||
throw Exception::OutOfMemory(L"ScopedAlloc");
|
throw Exception::OutOfMemory(L"ScopedAlloc");
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void Resize( size_t newsize )
|
virtual void Resize(size_t newsize)
|
||||||
{
|
{
|
||||||
this->m_size = newsize;
|
this->m_size = newsize;
|
||||||
this->m_buffer = (T*)realloc(this->m_buffer, this->m_size * sizeof(T));
|
this->m_buffer = (T *)realloc(this->m_buffer, this->m_size * sizeof(T));
|
||||||
|
|
||||||
if (!this->m_buffer)
|
if (!this->m_buffer)
|
||||||
throw Exception::OutOfMemory(L"ScopedAlloc::Resize");
|
throw Exception::OutOfMemory(L"ScopedAlloc::Resize");
|
||||||
}
|
}
|
||||||
|
|
||||||
using _parent::operator[];
|
using _parent::operator[];
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -219,41 +222,43 @@ public:
|
||||||
//
|
//
|
||||||
// See docs for BaseScopedAlloc for details and rationale.
|
// See docs for BaseScopedAlloc for details and rationale.
|
||||||
//
|
//
|
||||||
template< typename T, uint align >
|
template <typename T, uint align>
|
||||||
class ScopedAlignedAlloc : public BaseScopedAlloc<T>
|
class ScopedAlignedAlloc : public BaseScopedAlloc<T>
|
||||||
{
|
{
|
||||||
typedef BaseScopedAlloc<T> _parent;
|
typedef BaseScopedAlloc<T> _parent;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ScopedAlignedAlloc( size_t size=0 ) : _parent()
|
ScopedAlignedAlloc(size_t size = 0)
|
||||||
{
|
: _parent()
|
||||||
Alloc(size);
|
{
|
||||||
}
|
Alloc(size);
|
||||||
|
}
|
||||||
virtual ~ScopedAlignedAlloc() throw()
|
|
||||||
{
|
|
||||||
safe_aligned_free(this->m_buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void Alloc( size_t newsize )
|
virtual ~ScopedAlignedAlloc() throw()
|
||||||
{
|
{
|
||||||
safe_aligned_free(this->m_buffer);
|
safe_aligned_free(this->m_buffer);
|
||||||
this->m_size = newsize;
|
}
|
||||||
if (!this->m_size) return;
|
|
||||||
|
|
||||||
this->m_buffer = (T*)_aligned_malloc( this->m_size * sizeof(T), align );
|
virtual void Alloc(size_t newsize)
|
||||||
if (!this->m_buffer)
|
{
|
||||||
throw Exception::OutOfMemory(L"ScopedAlignedAlloc");
|
safe_aligned_free(this->m_buffer);
|
||||||
}
|
this->m_size = newsize;
|
||||||
|
if (!this->m_size)
|
||||||
|
return;
|
||||||
|
|
||||||
virtual void Resize( size_t newsize )
|
this->m_buffer = (T *)_aligned_malloc(this->m_size * sizeof(T), align);
|
||||||
{
|
if (!this->m_buffer)
|
||||||
this->m_buffer = (T*)pcsx2_aligned_realloc(this->m_buffer, newsize * sizeof(T), align, this->m_size * sizeof(T));
|
throw Exception::OutOfMemory(L"ScopedAlignedAlloc");
|
||||||
this->m_size = newsize;
|
}
|
||||||
|
|
||||||
if (!this->m_buffer)
|
virtual void Resize(size_t newsize)
|
||||||
throw Exception::OutOfMemory(L"ScopedAlignedAlloc::Resize");
|
{
|
||||||
}
|
this->m_buffer = (T *)pcsx2_aligned_realloc(this->m_buffer, newsize * sizeof(T), align, this->m_size * sizeof(T));
|
||||||
|
this->m_size = newsize;
|
||||||
using _parent::operator[];
|
|
||||||
|
if (!this->m_buffer)
|
||||||
|
throw Exception::OutOfMemory(L"ScopedAlignedAlloc::Resize");
|
||||||
|
}
|
||||||
|
|
||||||
|
using _parent::operator[];
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,95 +22,96 @@ using Threading::ScopedLock;
|
||||||
// ScopedPtrMT
|
// ScopedPtrMT
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
template< typename T >
|
template <typename T>
|
||||||
class ScopedPtrMT
|
class ScopedPtrMT
|
||||||
{
|
{
|
||||||
DeclareNoncopyableObject(ScopedPtrMT);
|
DeclareNoncopyableObject(ScopedPtrMT);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::atomic<T*> m_ptr;
|
std::atomic<T *> m_ptr;
|
||||||
Threading::Mutex m_mtx;
|
Threading::Mutex m_mtx;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef T element_type;
|
typedef T element_type;
|
||||||
|
|
||||||
wxEXPLICIT ScopedPtrMT(T * ptr = nullptr)
|
wxEXPLICIT ScopedPtrMT(T *ptr = nullptr)
|
||||||
{
|
{
|
||||||
m_ptr = ptr;
|
m_ptr = ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
~ScopedPtrMT() throw() { _Delete_unlocked(); }
|
~ScopedPtrMT() throw() { _Delete_unlocked(); }
|
||||||
|
|
||||||
ScopedPtrMT& Reassign(T * ptr = nullptr)
|
ScopedPtrMT &Reassign(T *ptr = nullptr)
|
||||||
{
|
{
|
||||||
T* doh = m_ptr.exchange(ptr);
|
T *doh = m_ptr.exchange(ptr);
|
||||||
if ( ptr != doh ) delete doh;
|
if (ptr != doh)
|
||||||
return *this;
|
delete doh;
|
||||||
}
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
ScopedPtrMT& Delete() throw()
|
ScopedPtrMT &Delete() throw()
|
||||||
{
|
{
|
||||||
ScopedLock lock( m_mtx );
|
ScopedLock lock(m_mtx);
|
||||||
_Delete_unlocked();
|
_Delete_unlocked();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Removes the pointer from scoped management, but does not delete!
|
// Removes the pointer from scoped management, but does not delete!
|
||||||
// (ScopedPtr will be nullptr after this method)
|
// (ScopedPtr will be nullptr after this method)
|
||||||
T *DetachPtr()
|
T *DetachPtr()
|
||||||
{
|
{
|
||||||
ScopedLock lock( m_mtx );
|
ScopedLock lock(m_mtx);
|
||||||
|
|
||||||
return m_ptr.exchange(nullptr);
|
return m_ptr.exchange(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the managed pointer. Can return nullptr as a valid result if the ScopedPtrMT
|
// Returns the managed pointer. Can return nullptr as a valid result if the ScopedPtrMT
|
||||||
// has no object in management.
|
// has no object in management.
|
||||||
T* GetPtr() const
|
T *GetPtr() const
|
||||||
{
|
{
|
||||||
return m_ptr;
|
return m_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwapPtr(ScopedPtrMT& other)
|
void SwapPtr(ScopedPtrMT &other)
|
||||||
{
|
{
|
||||||
ScopedLock lock( m_mtx );
|
ScopedLock lock(m_mtx);
|
||||||
m_ptr.exchange(other.m_ptr.exchange(m_ptr.load()));
|
m_ptr.exchange(other.m_ptr.exchange(m_ptr.load()));
|
||||||
T * const tmp = other.m_ptr;
|
T *const tmp = other.m_ptr;
|
||||||
other.m_ptr = m_ptr;
|
other.m_ptr = m_ptr;
|
||||||
m_ptr = tmp;
|
m_ptr = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// ScopedPtrMT Operators
|
// ScopedPtrMT Operators
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// I've decided to use the ATL's approach to pointer validity tests, opposed to
|
// I've decided to use the ATL's approach to pointer validity tests, opposed to
|
||||||
// the wx/boost approach (which uses some bizarre member method pointer crap, and can't
|
// the wx/boost approach (which uses some bizarre member method pointer crap, and can't
|
||||||
// allow the T* implicit casting.
|
// allow the T* implicit casting.
|
||||||
|
|
||||||
bool operator!() const throw()
|
bool operator!() const throw()
|
||||||
{
|
{
|
||||||
return m_ptr.load() == nullptr;
|
return m_ptr.load() == nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Equality
|
// Equality
|
||||||
bool operator==(T* pT) const throw()
|
bool operator==(T *pT) const throw()
|
||||||
{
|
{
|
||||||
return m_ptr == pT;
|
return m_ptr == pT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inequality
|
// Inequality
|
||||||
bool operator!=(T* pT) const throw()
|
bool operator!=(T *pT) const throw()
|
||||||
{
|
{
|
||||||
return !operator==(pT);
|
return !operator==(pT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convenient assignment operator. ScopedPtrMT = nullptr will issue an automatic deletion
|
// Convenient assignment operator. ScopedPtrMT = nullptr will issue an automatic deletion
|
||||||
// of the managed pointer.
|
// of the managed pointer.
|
||||||
ScopedPtrMT& operator=( T* src )
|
ScopedPtrMT &operator=(T *src)
|
||||||
{
|
{
|
||||||
return Reassign( src );
|
return Reassign(src);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
operator T*() const
|
operator T*() const
|
||||||
{
|
{
|
||||||
return m_ptr;
|
return m_ptr;
|
||||||
|
@ -129,11 +130,11 @@ public:
|
||||||
pxAssert(m_ptr != nullptr);
|
pxAssert(m_ptr != nullptr);
|
||||||
return m_ptr;
|
return m_ptr;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void _Delete_unlocked() throw()
|
void _Delete_unlocked() throw()
|
||||||
{
|
{
|
||||||
delete m_ptr.exchange(nullptr);
|
delete m_ptr.exchange(nullptr);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,10 +22,10 @@
|
||||||
#include <wx/tokenzr.h>
|
#include <wx/tokenzr.h>
|
||||||
|
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
#define WX_STR(str) (str.wc_str())
|
#define WX_STR(str) (str.wc_str())
|
||||||
#else
|
#else
|
||||||
// Stupid wx3.0 doesn't support c_str for vararg function
|
// Stupid wx3.0 doesn't support c_str for vararg function
|
||||||
#define WX_STR(str) (static_cast<const char*>(str.c_str()))
|
#define WX_STR(str) (static_cast<const char *>(str.c_str()))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -34,59 +34,59 @@
|
||||||
// Converts a string to UTF8 and provides an interface for getting its length.
|
// Converts a string to UTF8 and provides an interface for getting its length.
|
||||||
class pxToUTF8
|
class pxToUTF8
|
||||||
{
|
{
|
||||||
DeclareNoncopyableObject( pxToUTF8 );
|
DeclareNoncopyableObject(pxToUTF8);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
wxCharBuffer m_result;
|
wxCharBuffer m_result;
|
||||||
int m_length;
|
int m_length;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit pxToUTF8(const wxString& src)
|
explicit pxToUTF8(const wxString &src)
|
||||||
: m_result( src.ToUTF8() )
|
: m_result(src.ToUTF8())
|
||||||
{
|
{
|
||||||
m_length = -1;
|
m_length = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Length()
|
size_t Length()
|
||||||
{
|
{
|
||||||
if( -1 == m_length )
|
if (-1 == m_length)
|
||||||
m_length = strlen( m_result );
|
m_length = strlen(m_result);
|
||||||
return m_length;
|
return m_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Convert( const wxString& src )
|
void Convert(const wxString &src)
|
||||||
{
|
{
|
||||||
m_result = src.ToUTF8();
|
m_result = src.ToUTF8();
|
||||||
m_length = -1;
|
m_length = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* data() const { return m_result; }
|
const char *data() const { return m_result; }
|
||||||
|
|
||||||
operator const char*() const
|
operator const char *() const
|
||||||
{
|
{
|
||||||
return m_result.data();
|
return m_result.data();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void px_fputs( FILE* fp, const char* src );
|
extern void px_fputs(FILE *fp, const char *src);
|
||||||
|
|
||||||
// wxWidgets lacks one of its own...
|
// wxWidgets lacks one of its own...
|
||||||
extern const wxRect wxDefaultRect;
|
extern const wxRect wxDefaultRect;
|
||||||
|
|
||||||
extern void SplitString( wxArrayString& dest, const wxString& src, const wxString& delims, wxStringTokenizerMode mode = wxTOKEN_RET_EMPTY_ALL );
|
extern void SplitString(wxArrayString &dest, const wxString &src, const wxString &delims, wxStringTokenizerMode mode = wxTOKEN_RET_EMPTY_ALL);
|
||||||
extern wxString JoinString( const wxArrayString& src, const wxString& separator );
|
extern wxString JoinString(const wxArrayString &src, const wxString &separator);
|
||||||
extern wxString JoinString( const wxChar** src, const wxString& separator );
|
extern wxString JoinString(const wxChar **src, const wxString &separator);
|
||||||
|
|
||||||
extern wxString ToString( const wxPoint& src, const wxString& separator=L"," );
|
extern wxString ToString(const wxPoint &src, const wxString &separator = L",");
|
||||||
extern wxString ToString( const wxSize& src, const wxString& separator=L"," );
|
extern wxString ToString(const wxSize &src, const wxString &separator = L",");
|
||||||
extern wxString ToString( const wxRect& src, const wxString& separator=L"," );
|
extern wxString ToString(const wxRect &src, const wxString &separator = L",");
|
||||||
|
|
||||||
extern bool TryParse( wxPoint& dest, const wxStringTokenizer& parts );
|
extern bool TryParse(wxPoint &dest, const wxStringTokenizer &parts);
|
||||||
extern bool TryParse( wxSize& dest, const wxStringTokenizer& parts );
|
extern bool TryParse(wxSize &dest, const wxStringTokenizer &parts);
|
||||||
|
|
||||||
extern bool TryParse( wxPoint& dest, const wxString& src, const wxPoint& defval=wxDefaultPosition, const wxString& separators=L",");
|
extern bool TryParse(wxPoint &dest, const wxString &src, const wxPoint &defval = wxDefaultPosition, const wxString &separators = L",");
|
||||||
extern bool TryParse( wxSize& dest, const wxString& src, const wxSize& defval=wxDefaultSize, const wxString& separators=L",");
|
extern bool TryParse(wxSize &dest, const wxString &src, const wxSize &defval = wxDefaultSize, const wxString &separators = L",");
|
||||||
extern bool TryParse( wxRect& dest, const wxString& src, const wxRect& defval=wxDefaultRect, const wxString& separators=L",");
|
extern bool TryParse(wxRect &dest, const wxString &src, const wxRect &defval = wxDefaultRect, const wxString &separators = L",");
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// ParsedAssignmentString
|
// ParsedAssignmentString
|
||||||
|
@ -104,11 +104,11 @@ extern bool TryParse( wxRect& dest, const wxString& src, const wxRect& defval=wx
|
||||||
//
|
//
|
||||||
struct ParsedAssignmentString
|
struct ParsedAssignmentString
|
||||||
{
|
{
|
||||||
wxString lvalue;
|
wxString lvalue;
|
||||||
wxString rvalue;
|
wxString rvalue;
|
||||||
bool IsComment;
|
bool IsComment;
|
||||||
|
|
||||||
ParsedAssignmentString( const wxString& src );
|
ParsedAssignmentString(const wxString &src);
|
||||||
};
|
};
|
||||||
|
|
||||||
// ======================================================================================
|
// ======================================================================================
|
||||||
|
@ -134,46 +134,46 @@ struct ParsedAssignmentString
|
||||||
|
|
||||||
typedef ScopedAlignedAlloc<char, 16> CharBufferType;
|
typedef ScopedAlignedAlloc<char, 16> CharBufferType;
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// FastFormatAscii
|
// FastFormatAscii
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
class FastFormatAscii
|
class FastFormatAscii
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
CharBufferType m_dest;
|
CharBufferType m_dest;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FastFormatAscii();
|
FastFormatAscii();
|
||||||
~FastFormatAscii() throw();
|
~FastFormatAscii() throw();
|
||||||
FastFormatAscii& Write( const char* fmt, ... );
|
FastFormatAscii &Write(const char *fmt, ...);
|
||||||
FastFormatAscii& WriteV( const char* fmt, va_list argptr );
|
FastFormatAscii &WriteV(const char *fmt, va_list argptr);
|
||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
bool IsEmpty() const;
|
bool IsEmpty() const;
|
||||||
|
|
||||||
const char* c_str() const { return m_dest.GetPtr(); }
|
const char *c_str() const { return m_dest.GetPtr(); }
|
||||||
operator const char*() const { return m_dest.GetPtr(); }
|
operator const char *() const { return m_dest.GetPtr(); }
|
||||||
|
|
||||||
const wxString GetString() const;
|
const wxString GetString() const;
|
||||||
//operator wxString() const;
|
//operator wxString() const;
|
||||||
|
|
||||||
FastFormatAscii& operator+=(const wxString& s)
|
FastFormatAscii &operator+=(const wxString &s)
|
||||||
{
|
{
|
||||||
Write( "%s", WX_STR(s) );
|
Write("%s", WX_STR(s));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
FastFormatAscii& operator+=(const wxChar* psz )
|
FastFormatAscii &operator+=(const wxChar *psz)
|
||||||
{
|
{
|
||||||
Write( "%ls", psz );
|
Write("%ls", psz);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
FastFormatAscii& operator+=(const char* psz )
|
FastFormatAscii &operator+=(const char *psz)
|
||||||
{
|
{
|
||||||
Write( "%s", psz );
|
Write("%s", psz);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -182,57 +182,57 @@ public:
|
||||||
class FastFormatUnicode
|
class FastFormatUnicode
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
CharBufferType m_dest;
|
CharBufferType m_dest;
|
||||||
uint m_Length;
|
uint m_Length;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FastFormatUnicode();
|
FastFormatUnicode();
|
||||||
~FastFormatUnicode() throw();
|
~FastFormatUnicode() throw();
|
||||||
|
|
||||||
FastFormatUnicode& Write( const char* fmt, ... );
|
FastFormatUnicode &Write(const char *fmt, ...);
|
||||||
FastFormatUnicode& Write( const wxChar* fmt, ... );
|
FastFormatUnicode &Write(const wxChar *fmt, ...);
|
||||||
FastFormatUnicode& Write( const wxString fmt, ... );
|
FastFormatUnicode &Write(const wxString fmt, ...);
|
||||||
FastFormatUnicode& WriteV( const char* fmt, va_list argptr );
|
FastFormatUnicode &WriteV(const char *fmt, va_list argptr);
|
||||||
FastFormatUnicode& WriteV( const wxChar* fmt, va_list argptr );
|
FastFormatUnicode &WriteV(const wxChar *fmt, va_list argptr);
|
||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
bool IsEmpty() const;
|
bool IsEmpty() const;
|
||||||
uint Length() const { return m_Length; }
|
uint Length() const { return m_Length; }
|
||||||
|
|
||||||
FastFormatUnicode& ToUpper();
|
FastFormatUnicode &ToUpper();
|
||||||
FastFormatUnicode& ToLower();
|
FastFormatUnicode &ToLower();
|
||||||
|
|
||||||
const wxChar* c_str() const { return (const wxChar*)m_dest.GetPtr(); }
|
const wxChar *c_str() const { return (const wxChar *)m_dest.GetPtr(); }
|
||||||
operator const wxChar*() const { return (const wxChar*)m_dest.GetPtr(); }
|
operator const wxChar *() const { return (const wxChar *)m_dest.GetPtr(); }
|
||||||
operator wxString() const { return (const wxChar*)m_dest.GetPtr(); }
|
operator wxString() const { return (const wxChar *)m_dest.GetPtr(); }
|
||||||
|
|
||||||
FastFormatUnicode& operator+=(const wxString& s)
|
FastFormatUnicode &operator+=(const wxString &s)
|
||||||
{
|
{
|
||||||
Write( L"%s", WX_STR(s) );
|
Write(L"%s", WX_STR(s));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
FastFormatUnicode& operator+=(const wxChar* psz )
|
FastFormatUnicode &operator+=(const wxChar *psz)
|
||||||
{
|
{
|
||||||
Write( L"%s", psz );
|
Write(L"%s", psz);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
FastFormatUnicode& operator+=(const char* psz );
|
FastFormatUnicode &operator+=(const char *psz);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern bool pxParseAssignmentString( const wxString& src, wxString& ldest, wxString& rdest );
|
extern bool pxParseAssignmentString(const wxString &src, wxString &ldest, wxString &rdest);
|
||||||
|
|
||||||
#define pxsFmt FastFormatUnicode().Write
|
#define pxsFmt FastFormatUnicode().Write
|
||||||
#define pxsFmtV FastFormatUnicode().WriteV
|
#define pxsFmtV FastFormatUnicode().WriteV
|
||||||
|
|
||||||
#define pxsPtr(ptr) pxsFmt("0x%08X", (ptr)).c_str()
|
#define pxsPtr(ptr) pxsFmt("0x%08X", (ptr)).c_str()
|
||||||
|
|
||||||
extern wxString& operator+=(wxString& str1, const FastFormatUnicode& str2);
|
extern wxString &operator+=(wxString &str1, const FastFormatUnicode &str2);
|
||||||
extern wxString operator+(const wxString& str1, const FastFormatUnicode& str2);
|
extern wxString operator+(const wxString &str1, const FastFormatUnicode &str2);
|
||||||
extern wxString operator+(const wxChar* str1, const FastFormatUnicode& str2);
|
extern wxString operator+(const wxChar *str1, const FastFormatUnicode &str2);
|
||||||
extern wxString operator+(const FastFormatUnicode& str1, const wxString& str2);
|
extern wxString operator+(const FastFormatUnicode &str1, const wxString &str2);
|
||||||
extern wxString operator+(const FastFormatUnicode& str1, const wxChar* str2);
|
extern wxString operator+(const FastFormatUnicode &str1, const wxChar *str2);
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -241,4 +241,4 @@ extern wxString operator+(const FastFormatUnicode& str1, const wxChar* str2);
|
||||||
// These functions are useful since they are ASCII always, even under Unicode. Typically
|
// These functions are useful since they are ASCII always, even under Unicode. Typically
|
||||||
// even in a unicode app.
|
// even in a unicode app.
|
||||||
|
|
||||||
extern void ssappendf(std::string& dest, const char* format, ...);
|
extern void ssappendf(std::string &dest, const char *format, ...);
|
||||||
|
|
|
@ -26,10 +26,10 @@
|
||||||
#include "Pcsx2Defs.h"
|
#include "Pcsx2Defs.h"
|
||||||
#include "TraceLog.h"
|
#include "TraceLog.h"
|
||||||
|
|
||||||
#undef Yield // release the burden of windows.h global namespace spam.
|
#undef Yield // release the burden of windows.h global namespace spam.
|
||||||
|
|
||||||
#define AffinityAssert_AllowFrom_MainUI() \
|
#define AffinityAssert_AllowFrom_MainUI() \
|
||||||
pxAssertMsg( wxThread::IsMain(), "Thread affinity violation: Call allowed from main thread only." )
|
pxAssertMsg(wxThread::IsMain(), "Thread affinity violation: Call allowed from main thread only.")
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// pxThreadLog / ConsoleLogSource_Threading
|
// pxThreadLog / ConsoleLogSource_Threading
|
||||||
|
@ -37,22 +37,25 @@
|
||||||
|
|
||||||
class ConsoleLogSource_Threading : ConsoleLogSource
|
class ConsoleLogSource_Threading : ConsoleLogSource
|
||||||
{
|
{
|
||||||
typedef ConsoleLogSource _parent;
|
typedef ConsoleLogSource _parent;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using _parent::IsActive;
|
using _parent::IsActive;
|
||||||
|
|
||||||
ConsoleLogSource_Threading();
|
ConsoleLogSource_Threading();
|
||||||
|
|
||||||
bool Write( const wxString& thrname, const wxChar* msg ) {
|
bool Write(const wxString &thrname, const wxChar *msg)
|
||||||
return _parent::Write( wxsFormat(L"(thread:%s) ", WX_STR(thrname)) + msg );
|
{
|
||||||
}
|
return _parent::Write(wxsFormat(L"(thread:%s) ", WX_STR(thrname)) + msg);
|
||||||
bool Warn( const wxString& thrname, const wxChar* msg ) {
|
}
|
||||||
return _parent::Warn( wxsFormat(L"(thread:%s) ", WX_STR(thrname)) + msg );
|
bool Warn(const wxString &thrname, const wxChar *msg)
|
||||||
}
|
{
|
||||||
bool Error( const wxString& thrname, const wxChar* msg ) {
|
return _parent::Warn(wxsFormat(L"(thread:%s) ", WX_STR(thrname)) + msg);
|
||||||
return _parent::Error( wxsFormat(L"(thread:%s) ", WX_STR(thrname)) + msg );
|
}
|
||||||
}
|
bool Error(const wxString &thrname, const wxChar *msg)
|
||||||
|
{
|
||||||
|
return _parent::Error(wxsFormat(L"(thread:%s) ", WX_STR(thrname)) + msg);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
extern ConsoleLogSource_Threading pxConLog_Thread;
|
extern ConsoleLogSource_Threading pxConLog_Thread;
|
||||||
|
@ -69,79 +72,80 @@ extern ConsoleLogSource_Threading pxConLog_Thread;
|
||||||
//#define PCSX2_THREAD_LOCAL 0 // uncomment this line to force-disable native TLS (useful for testing TlsVariable on windows/linux)
|
//#define PCSX2_THREAD_LOCAL 0 // uncomment this line to force-disable native TLS (useful for testing TlsVariable on windows/linux)
|
||||||
|
|
||||||
#ifndef PCSX2_THREAD_LOCAL
|
#ifndef PCSX2_THREAD_LOCAL
|
||||||
# define PCSX2_THREAD_LOCAL 1
|
#define PCSX2_THREAD_LOCAL 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class wxTimeSpan;
|
class wxTimeSpan;
|
||||||
|
|
||||||
namespace Threading
|
namespace Threading
|
||||||
{
|
{
|
||||||
class pxThread;
|
class pxThread;
|
||||||
class RwMutex;
|
class RwMutex;
|
||||||
|
|
||||||
extern void pxTestCancel();
|
extern void pxTestCancel();
|
||||||
extern pxThread* pxGetCurrentThread();
|
extern pxThread *pxGetCurrentThread();
|
||||||
extern wxString pxGetCurrentThreadName();
|
extern wxString pxGetCurrentThreadName();
|
||||||
extern u64 GetThreadCpuTime();
|
extern u64 GetThreadCpuTime();
|
||||||
extern u64 GetThreadTicksPerSecond();
|
extern u64 GetThreadTicksPerSecond();
|
||||||
|
|
||||||
// Yields the current thread and provides cancellation points if the thread is managed by
|
// Yields the current thread and provides cancellation points if the thread is managed by
|
||||||
// pxThread. Unmanaged threads use standard Sleep.
|
// pxThread. Unmanaged threads use standard Sleep.
|
||||||
extern void pxYield( int ms );
|
extern void pxYield(int ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Exception
|
namespace Exception
|
||||||
{
|
{
|
||||||
class BaseThreadError : public RuntimeError
|
class BaseThreadError : public RuntimeError
|
||||||
{
|
{
|
||||||
DEFINE_EXCEPTION_COPYTORS( BaseThreadError, RuntimeError )
|
DEFINE_EXCEPTION_COPYTORS(BaseThreadError, RuntimeError)
|
||||||
DEFINE_EXCEPTION_MESSAGES( BaseThreadError )
|
DEFINE_EXCEPTION_MESSAGES(BaseThreadError)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Threading::pxThread* m_thread;
|
Threading::pxThread *m_thread;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
BaseThreadError() {
|
BaseThreadError()
|
||||||
m_thread = NULL;
|
{
|
||||||
}
|
m_thread = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit BaseThreadError( Threading::pxThread* _thread )
|
explicit BaseThreadError(Threading::pxThread *_thread)
|
||||||
{
|
{
|
||||||
m_thread = _thread;
|
m_thread = _thread;
|
||||||
m_message_diag = L"An unspecified thread-related error occurred (thread=%s)";
|
m_message_diag = L"An unspecified thread-related error occurred (thread=%s)";
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit BaseThreadError( Threading::pxThread& _thread )
|
explicit BaseThreadError(Threading::pxThread &_thread)
|
||||||
{
|
{
|
||||||
m_thread = &_thread;
|
m_thread = &_thread;
|
||||||
m_message_diag = L"An unspecified thread-related error occurred (thread=%s)";
|
m_message_diag = L"An unspecified thread-related error occurred (thread=%s)";
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual wxString FormatDiagnosticMessage() const;
|
virtual wxString FormatDiagnosticMessage() const;
|
||||||
virtual wxString FormatDisplayMessage() const;
|
virtual wxString FormatDisplayMessage() const;
|
||||||
|
|
||||||
Threading::pxThread& Thread();
|
Threading::pxThread &Thread();
|
||||||
const Threading::pxThread& Thread() const;
|
const Threading::pxThread &Thread() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ThreadCreationError : public BaseThreadError
|
class ThreadCreationError : public BaseThreadError
|
||||||
{
|
{
|
||||||
DEFINE_EXCEPTION_COPYTORS( ThreadCreationError, BaseThreadError )
|
DEFINE_EXCEPTION_COPYTORS(ThreadCreationError, BaseThreadError)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ThreadCreationError( Threading::pxThread* _thread )
|
explicit ThreadCreationError(Threading::pxThread *_thread)
|
||||||
{
|
{
|
||||||
m_thread = _thread;
|
m_thread = _thread;
|
||||||
SetBothMsgs( L"Thread creation failure. An unspecified error occurred while trying to create the %s thread." );
|
SetBothMsgs(L"Thread creation failure. An unspecified error occurred while trying to create the %s thread.");
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit ThreadCreationError( Threading::pxThread& _thread )
|
explicit ThreadCreationError(Threading::pxThread &_thread)
|
||||||
{
|
{
|
||||||
m_thread = &_thread;
|
m_thread = &_thread;
|
||||||
SetBothMsgs( L"Thread creation failure. An unspecified error occurred while trying to create the %s thread." );
|
SetBothMsgs(L"Thread creation failure. An unspecified error occurred while trying to create the %s thread.");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -153,22 +157,22 @@ namespace Threading
|
||||||
// The following set of documented functions have Linux/Win32 specific implementations,
|
// The following set of documented functions have Linux/Win32 specific implementations,
|
||||||
// which are found in WinThreads.cpp and LnxThreads.cpp
|
// which are found in WinThreads.cpp and LnxThreads.cpp
|
||||||
|
|
||||||
// Releases a timeslice to other threads.
|
// Releases a timeslice to other threads.
|
||||||
extern void Timeslice();
|
extern void Timeslice();
|
||||||
|
|
||||||
// For use in spin/wait loops.
|
// For use in spin/wait loops.
|
||||||
extern void SpinWait();
|
extern void SpinWait();
|
||||||
|
|
||||||
// Optional implementation to enable hires thread/process scheduler for the operating system.
|
// Optional implementation to enable hires thread/process scheduler for the operating system.
|
||||||
// Needed by Windows, but might not be relevant to other platforms.
|
// Needed by Windows, but might not be relevant to other platforms.
|
||||||
extern void EnableHiresScheduler();
|
extern void EnableHiresScheduler();
|
||||||
extern void DisableHiresScheduler();
|
extern void DisableHiresScheduler();
|
||||||
|
|
||||||
// sleeps the current thread for the given number of milliseconds.
|
// sleeps the current thread for the given number of milliseconds.
|
||||||
extern void Sleep( int ms );
|
extern void Sleep(int ms);
|
||||||
|
|
||||||
// pthread Cond is an evil api that is not suited for Pcsx2 needs.
|
// pthread Cond is an evil api that is not suited for Pcsx2 needs.
|
||||||
// Let's not use it. Use mutexes and semaphores instead to create waits. (Air)
|
// Let's not use it. Use mutexes and semaphores instead to create waits. (Air)
|
||||||
#if 0
|
#if 0
|
||||||
struct WaitEvent
|
struct WaitEvent
|
||||||
{
|
{
|
||||||
|
@ -194,181 +198,187 @@ namespace Threading
|
||||||
// If TryAcquire() returns true, you've locked the object and are *responsible* for unlocking
|
// If TryAcquire() returns true, you've locked the object and are *responsible* for unlocking
|
||||||
// it later.
|
// it later.
|
||||||
//
|
//
|
||||||
class NonblockingMutex
|
class NonblockingMutex
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
std::atomic_flag val;
|
std::atomic_flag val;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NonblockingMutex() { val.clear(); }
|
NonblockingMutex() { val.clear(); }
|
||||||
virtual ~NonblockingMutex() throw() {}
|
virtual ~NonblockingMutex() throw() {}
|
||||||
|
|
||||||
bool TryAcquire() throw()
|
bool TryAcquire() throw()
|
||||||
{
|
{
|
||||||
return !val.test_and_set();
|
return !val.test_and_set();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can be done with a TryAcquire/Release but it is likely better to do it outside of the object
|
// Can be done with a TryAcquire/Release but it is likely better to do it outside of the object
|
||||||
bool IsLocked()
|
bool IsLocked()
|
||||||
{ pxAssertMsg(0, "IsLocked isn't supported for NonblockingMutex"); return false; }
|
{
|
||||||
|
pxAssertMsg(0, "IsLocked isn't supported for NonblockingMutex");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void Release()
|
void Release()
|
||||||
{
|
{
|
||||||
val.clear();
|
val.clear();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Semaphore
|
class Semaphore
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
semaphore_t m_sema;
|
semaphore_t m_sema;
|
||||||
int m_counter;
|
int m_counter;
|
||||||
#else
|
#else
|
||||||
sem_t m_sema;
|
sem_t m_sema;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Semaphore();
|
Semaphore();
|
||||||
virtual ~Semaphore() throw();
|
virtual ~Semaphore() throw();
|
||||||
|
|
||||||
void Reset();
|
void Reset();
|
||||||
void Post();
|
void Post();
|
||||||
void Post( int multiple );
|
void Post(int multiple);
|
||||||
|
|
||||||
void WaitWithoutYield();
|
void WaitWithoutYield();
|
||||||
bool WaitWithoutYield( const wxTimeSpan& timeout );
|
bool WaitWithoutYield(const wxTimeSpan &timeout);
|
||||||
void WaitNoCancel();
|
void WaitNoCancel();
|
||||||
void WaitNoCancel( const wxTimeSpan& timeout );
|
void WaitNoCancel(const wxTimeSpan &timeout);
|
||||||
int Count();
|
int Count();
|
||||||
|
|
||||||
void Wait();
|
void Wait();
|
||||||
bool Wait( const wxTimeSpan& timeout );
|
bool Wait(const wxTimeSpan &timeout);
|
||||||
};
|
};
|
||||||
|
|
||||||
class Mutex
|
class Mutex
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
pthread_mutex_t m_mutex;
|
pthread_mutex_t m_mutex;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Mutex();
|
Mutex();
|
||||||
virtual ~Mutex() throw();
|
virtual ~Mutex() throw();
|
||||||
virtual bool IsRecursive() const { return false; }
|
virtual bool IsRecursive() const { return false; }
|
||||||
|
|
||||||
void Recreate();
|
void Recreate();
|
||||||
bool RecreateIfLocked();
|
bool RecreateIfLocked();
|
||||||
void Detach();
|
void Detach();
|
||||||
|
|
||||||
void Acquire();
|
void Acquire();
|
||||||
bool Acquire( const wxTimeSpan& timeout );
|
bool Acquire(const wxTimeSpan &timeout);
|
||||||
bool TryAcquire();
|
bool TryAcquire();
|
||||||
void Release();
|
void Release();
|
||||||
|
|
||||||
void AcquireWithoutYield();
|
void AcquireWithoutYield();
|
||||||
bool AcquireWithoutYield( const wxTimeSpan& timeout );
|
bool AcquireWithoutYield(const wxTimeSpan &timeout);
|
||||||
|
|
||||||
void Wait();
|
void Wait();
|
||||||
bool Wait( const wxTimeSpan& timeout );
|
bool Wait(const wxTimeSpan &timeout);
|
||||||
void WaitWithoutYield();
|
void WaitWithoutYield();
|
||||||
bool WaitWithoutYield( const wxTimeSpan& timeout );
|
bool WaitWithoutYield(const wxTimeSpan &timeout);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// empty constructor used by MutexLockRecursive
|
// empty constructor used by MutexLockRecursive
|
||||||
Mutex( bool ) {}
|
Mutex(bool) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class MutexRecursive : public Mutex
|
class MutexRecursive : public Mutex
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MutexRecursive();
|
MutexRecursive();
|
||||||
virtual ~MutexRecursive() throw();
|
virtual ~MutexRecursive() throw();
|
||||||
virtual bool IsRecursive() const { return true; }
|
virtual bool IsRecursive() const { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// ScopedLock
|
// ScopedLock
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// Helper class for using Mutexes. Using this class provides an exception-safe (and
|
// Helper class for using Mutexes. Using this class provides an exception-safe (and
|
||||||
// generally clean) method of locking code inside a function or conditional block. The lock
|
// generally clean) method of locking code inside a function or conditional block. The lock
|
||||||
// will be automatically released on any return or exit from the function.
|
// will be automatically released on any return or exit from the function.
|
||||||
//
|
//
|
||||||
// Const qualification note:
|
// Const qualification note:
|
||||||
// ScopedLock takes const instances of the mutex, even though the mutex is modified
|
// ScopedLock takes const instances of the mutex, even though the mutex is modified
|
||||||
// by locking and unlocking. Two rationales:
|
// by locking and unlocking. Two rationales:
|
||||||
//
|
//
|
||||||
// 1) when designing classes with accessors (GetString, GetValue, etc) that need mutexes,
|
// 1) when designing classes with accessors (GetString, GetValue, etc) that need mutexes,
|
||||||
// this class needs a const hack to allow those accessors to be const (which is typically
|
// this class needs a const hack to allow those accessors to be const (which is typically
|
||||||
// *very* important).
|
// *very* important).
|
||||||
//
|
//
|
||||||
// 2) The state of the Mutex is guaranteed to be unchanged when the calling function or
|
// 2) The state of the Mutex is guaranteed to be unchanged when the calling function or
|
||||||
// scope exits, by any means. Only via manual calls to Release or Acquire does that
|
// scope exits, by any means. Only via manual calls to Release or Acquire does that
|
||||||
// change, and typically those are only used in very special circumstances of their own.
|
// change, and typically those are only used in very special circumstances of their own.
|
||||||
//
|
//
|
||||||
class ScopedLock
|
class ScopedLock
|
||||||
{
|
{
|
||||||
DeclareNoncopyableObject(ScopedLock);
|
DeclareNoncopyableObject(ScopedLock);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Mutex* m_lock;
|
Mutex *m_lock;
|
||||||
bool m_IsLocked;
|
bool m_IsLocked;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~ScopedLock() throw();
|
virtual ~ScopedLock() throw();
|
||||||
explicit ScopedLock( const Mutex* locker=NULL );
|
explicit ScopedLock(const Mutex *locker = NULL);
|
||||||
explicit ScopedLock( const Mutex& locker );
|
explicit ScopedLock(const Mutex &locker);
|
||||||
void AssignAndLock( const Mutex& locker );
|
void AssignAndLock(const Mutex &locker);
|
||||||
void AssignAndLock( const Mutex* locker );
|
void AssignAndLock(const Mutex *locker);
|
||||||
|
|
||||||
void Assign( const Mutex& locker );
|
void Assign(const Mutex &locker);
|
||||||
void Assign( const Mutex* locker );
|
void Assign(const Mutex *locker);
|
||||||
|
|
||||||
void Release();
|
void Release();
|
||||||
void Acquire();
|
void Acquire();
|
||||||
|
|
||||||
bool IsLocked() const { return m_IsLocked; }
|
bool IsLocked() const { return m_IsLocked; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Special constructor used by ScopedTryLock
|
// Special constructor used by ScopedTryLock
|
||||||
ScopedLock( const Mutex& locker, bool isTryLock );
|
ScopedLock(const Mutex &locker, bool isTryLock);
|
||||||
};
|
};
|
||||||
|
|
||||||
class ScopedTryLock : public ScopedLock
|
class ScopedTryLock : public ScopedLock
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ScopedTryLock( const Mutex& locker ) : ScopedLock( locker, true ) { }
|
ScopedTryLock(const Mutex &locker)
|
||||||
virtual ~ScopedTryLock() throw() {}
|
: ScopedLock(locker, true)
|
||||||
bool Failed() const { return !m_IsLocked; }
|
{
|
||||||
};
|
}
|
||||||
|
virtual ~ScopedTryLock() throw() {}
|
||||||
|
bool Failed() const { return !m_IsLocked; }
|
||||||
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// ScopedNonblockingLock
|
// ScopedNonblockingLock
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// A ScopedTryLock branded for use with Nonblocking mutexes. See ScopedTryLock for details.
|
// A ScopedTryLock branded for use with Nonblocking mutexes. See ScopedTryLock for details.
|
||||||
//
|
//
|
||||||
class ScopedNonblockingLock
|
class ScopedNonblockingLock
|
||||||
{
|
{
|
||||||
DeclareNoncopyableObject(ScopedNonblockingLock);
|
DeclareNoncopyableObject(ScopedNonblockingLock);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
NonblockingMutex& m_lock;
|
NonblockingMutex &m_lock;
|
||||||
bool m_IsLocked;
|
bool m_IsLocked;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ScopedNonblockingLock( NonblockingMutex& locker ) :
|
ScopedNonblockingLock(NonblockingMutex &locker)
|
||||||
m_lock( locker )
|
: m_lock(locker)
|
||||||
, m_IsLocked( m_lock.TryAcquire() )
|
, m_IsLocked(m_lock.TryAcquire())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~ScopedNonblockingLock() throw()
|
virtual ~ScopedNonblockingLock() throw()
|
||||||
{
|
{
|
||||||
if( m_IsLocked )
|
if (m_IsLocked)
|
||||||
m_lock.Release();
|
m_lock.Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Failed() const { return !m_IsLocked; }
|
bool Failed() const { return !m_IsLocked; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// ScopedLockBool
|
// ScopedLockBool
|
||||||
|
@ -377,26 +387,30 @@ namespace Threading
|
||||||
// Note that the isLockedBool should only be used as an indicator for the locked status,
|
// Note that the isLockedBool should only be used as an indicator for the locked status,
|
||||||
// and not actually depended on for thread synchronization...
|
// and not actually depended on for thread synchronization...
|
||||||
|
|
||||||
struct ScopedLockBool {
|
struct ScopedLockBool
|
||||||
ScopedLock m_lock;
|
{
|
||||||
std::atomic<bool>& m_bool;
|
ScopedLock m_lock;
|
||||||
|
std::atomic<bool> &m_bool;
|
||||||
|
|
||||||
ScopedLockBool(Mutex& mutexToLock, std::atomic<bool>& isLockedBool)
|
ScopedLockBool(Mutex &mutexToLock, std::atomic<bool> &isLockedBool)
|
||||||
: m_lock(mutexToLock),
|
: m_lock(mutexToLock)
|
||||||
m_bool(isLockedBool) {
|
, m_bool(isLockedBool)
|
||||||
m_bool.store(m_lock.IsLocked(), std::memory_order_relaxed);
|
{
|
||||||
}
|
m_bool.store(m_lock.IsLocked(), std::memory_order_relaxed);
|
||||||
virtual ~ScopedLockBool() throw() {
|
}
|
||||||
m_bool.store(false, std::memory_order_relaxed);
|
virtual ~ScopedLockBool() throw()
|
||||||
}
|
{
|
||||||
void Acquire() {
|
m_bool.store(false, std::memory_order_relaxed);
|
||||||
m_lock.Acquire();
|
}
|
||||||
m_bool.store(m_lock.IsLocked(), std::memory_order_relaxed);
|
void Acquire()
|
||||||
}
|
{
|
||||||
void Release() {
|
m_lock.Acquire();
|
||||||
m_bool.store(false, std::memory_order_relaxed);
|
m_bool.store(m_lock.IsLocked(), std::memory_order_relaxed);
|
||||||
m_lock.Release();
|
}
|
||||||
}
|
void Release()
|
||||||
};
|
{
|
||||||
|
m_bool.store(false, std::memory_order_relaxed);
|
||||||
|
m_lock.Release();
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,32 +22,31 @@ wxDECLARE_EVENT(pxEvt_ThreadedTaskComplete, wxCommandEvent);
|
||||||
|
|
||||||
namespace Threading
|
namespace Threading
|
||||||
{
|
{
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// WaitForTaskDialog
|
// WaitForTaskDialog
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// This dialog is displayed whenever the main thread is recursively waiting on multiple
|
// This dialog is displayed whenever the main thread is recursively waiting on multiple
|
||||||
// mutexes or semaphores. wxwidgets does not support recursive yielding to pending events
|
// mutexes or semaphores. wxwidgets does not support recursive yielding to pending events
|
||||||
// but it *does* support opening a modal dialog, which disables the interface (preventing
|
// but it *does* support opening a modal dialog, which disables the interface (preventing
|
||||||
// the user from starting additional actions), and processes messages (allowing the system
|
// the user from starting additional actions), and processes messages (allowing the system
|
||||||
// to continue to manage threads and process logging).
|
// to continue to manage threads and process logging).
|
||||||
//
|
//
|
||||||
class WaitForTaskDialog : public wxDialogWithHelpers
|
class WaitForTaskDialog : public wxDialogWithHelpers
|
||||||
{
|
{
|
||||||
DECLARE_DYNAMIC_CLASS_NO_COPY(WaitForTaskDialog)
|
DECLARE_DYNAMIC_CLASS_NO_COPY(WaitForTaskDialog)
|
||||||
|
|
||||||
typedef wxDialogWithHelpers _parent;
|
typedef wxDialogWithHelpers _parent;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
SynchronousActionState m_sync;
|
SynchronousActionState m_sync;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
WaitForTaskDialog( const wxString& title=wxEmptyString, const wxString& heading=wxEmptyString );
|
WaitForTaskDialog(const wxString &title = wxEmptyString, const wxString &heading = wxEmptyString);
|
||||||
virtual ~WaitForTaskDialog() throw() {}
|
virtual ~WaitForTaskDialog() throw() {}
|
||||||
virtual int ShowModal();
|
virtual int ShowModal();
|
||||||
|
|
||||||
protected:
|
|
||||||
void OnTaskComplete( wxCommandEvent& evt );
|
|
||||||
//void OnTimer( wxTimerEvent& evt );
|
|
||||||
};
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void OnTaskComplete(wxCommandEvent &evt);
|
||||||
|
//void OnTimer( wxTimerEvent& evt );
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,9 +18,9 @@
|
||||||
#include "Threading.h"
|
#include "Threading.h"
|
||||||
|
|
||||||
#if PCSX2_THREAD_LOCAL
|
#if PCSX2_THREAD_LOCAL
|
||||||
# define DeclareTls(x) __threadlocal x
|
#define DeclareTls(x) __threadlocal x
|
||||||
#else
|
#else
|
||||||
# define DeclareTls(x) Threading::TlsVariable<x>
|
#define DeclareTls(x) Threading::TlsVariable<x>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace Threading
|
namespace Threading
|
||||||
|
@ -38,152 +38,153 @@ namespace Threading
|
||||||
// result in repeated calls to pthread_getspecific. (if the function inlines then it
|
// result in repeated calls to pthread_getspecific. (if the function inlines then it
|
||||||
// should actually optimize well enough, but I doubt it does).
|
// should actually optimize well enough, but I doubt it does).
|
||||||
//
|
//
|
||||||
template< typename T >
|
template <typename T>
|
||||||
class BaseTlsVariable
|
class BaseTlsVariable
|
||||||
{
|
{
|
||||||
DeclareNoncopyableObject(BaseTlsVariable<T>);
|
DeclareNoncopyableObject(BaseTlsVariable<T>);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
pthread_key_t m_thread_key;
|
pthread_key_t m_thread_key;
|
||||||
bool m_IsDisposed;
|
bool m_IsDisposed;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BaseTlsVariable();
|
BaseTlsVariable();
|
||||||
|
|
||||||
virtual ~BaseTlsVariable() throw()
|
virtual ~BaseTlsVariable() throw()
|
||||||
{
|
{
|
||||||
Dispose();
|
Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
T* GetPtr() const;
|
T *GetPtr() const;
|
||||||
T& GetRef() const { return *GetPtr(); }
|
T &GetRef() const { return *GetPtr(); }
|
||||||
|
|
||||||
operator T&() const { return GetRef(); }
|
operator T &() const { return GetRef(); }
|
||||||
T* operator->() const { return GetPtr(); }
|
T *operator->() const { return GetPtr(); }
|
||||||
|
|
||||||
void Dispose()
|
void Dispose()
|
||||||
{
|
{
|
||||||
if (!m_IsDisposed)
|
if (!m_IsDisposed) {
|
||||||
{
|
m_IsDisposed = true;
|
||||||
m_IsDisposed = true;
|
KillKey();
|
||||||
KillKey();
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void CreateKey();
|
void CreateKey();
|
||||||
void KillKey();
|
void KillKey();
|
||||||
|
|
||||||
virtual void CreateInstance( T* result ) const
|
virtual void CreateInstance(T *result) const
|
||||||
{
|
{
|
||||||
new (result) T();
|
new (result) T();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _aligned_delete_and_free( void* ptr )
|
static void _aligned_delete_and_free(void *ptr)
|
||||||
{
|
{
|
||||||
if (!ptr) return;
|
if (!ptr)
|
||||||
((T*)ptr)->~T();
|
return;
|
||||||
_aligned_free(ptr);
|
((T *)ptr)->~T();
|
||||||
}
|
_aligned_free(ptr);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template< typename T >
|
template <typename T>
|
||||||
class TlsVariable : public BaseTlsVariable<T>
|
class TlsVariable : public BaseTlsVariable<T>
|
||||||
{
|
{
|
||||||
DeclareNoncopyableObject(TlsVariable<T>);
|
DeclareNoncopyableObject(TlsVariable<T>);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
T m_initval;
|
T m_initval;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TlsVariable() {}
|
TlsVariable() {}
|
||||||
TlsVariable( const T& initval )
|
TlsVariable(const T &initval)
|
||||||
: m_initval(initval) { }
|
: m_initval(initval)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
// This is needed; The C++ standard likes making life suck for programmers.
|
// This is needed; The C++ standard likes making life suck for programmers.
|
||||||
using BaseTlsVariable<T>::GetRef;
|
using BaseTlsVariable<T>::GetRef;
|
||||||
|
|
||||||
virtual ~TlsVariable() throw()
|
virtual ~TlsVariable() throw()
|
||||||
{
|
{
|
||||||
// disable the parent cleanup. This leaks memory blocks, but its necessary because
|
// disable the parent cleanup. This leaks memory blocks, but its necessary because
|
||||||
// TLS is expected to be persistent until the very end of execution on the main thread.
|
// TLS is expected to be persistent until the very end of execution on the main thread.
|
||||||
// Killing the pthread_key at all will lead to the console logger death, etc.
|
// Killing the pthread_key at all will lead to the console logger death, etc.
|
||||||
|
|
||||||
// DON'T REMOVE this->, the "official"[ly stupid] C++ standard requires it because of its
|
|
||||||
// insistence that variables be looked up during initial template parsing and not during
|
|
||||||
// instantiation.
|
|
||||||
this->m_IsDisposed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
TlsVariable<T>& operator=( const T& src )
|
// DON'T REMOVE this->, the "official"[ly stupid] C++ standard requires it because of its
|
||||||
{
|
// insistence that variables be looked up during initial template parsing and not during
|
||||||
GetRef() = src;
|
// instantiation.
|
||||||
return *this;
|
this->m_IsDisposed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==( const T& src ) const { return GetRef() == src; }
|
TlsVariable<T> &operator=(const T &src)
|
||||||
bool operator!=( const T& src ) const { return GetRef() != src; }
|
{
|
||||||
bool operator>( const T& src ) const { return GetRef() > src; }
|
GetRef() = src;
|
||||||
bool operator<( const T& src ) const { return GetRef() < src; }
|
return *this;
|
||||||
bool operator>=( const T& src ) const { return GetRef() >= src; }
|
}
|
||||||
bool operator<=( const T& src ) const { return GetRef() <= src; }
|
|
||||||
|
|
||||||
T operator+( const T& src ) const { return GetRef() + src; }
|
bool operator==(const T &src) const { return GetRef() == src; }
|
||||||
T operator-( const T& src ) const { return GetRef() - src; }
|
bool operator!=(const T &src) const { return GetRef() != src; }
|
||||||
|
bool operator>(const T &src) const { return GetRef() > src; }
|
||||||
|
bool operator<(const T &src) const { return GetRef() < src; }
|
||||||
|
bool operator>=(const T &src) const { return GetRef() >= src; }
|
||||||
|
bool operator<=(const T &src) const { return GetRef() <= src; }
|
||||||
|
|
||||||
|
T operator+(const T &src) const { return GetRef() + src; }
|
||||||
|
T operator-(const T &src) const { return GetRef() - src; }
|
||||||
|
|
||||||
|
void operator+=(const T &src) { GetRef() += src; }
|
||||||
|
void operator-=(const T &src) { GetRef() -= src; }
|
||||||
|
|
||||||
void operator+=( const T& src ) { GetRef() += src; }
|
|
||||||
void operator-=( const T& src ) { GetRef() -= src; }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void CreateInstance( T* result ) const
|
virtual void CreateInstance(T *result) const
|
||||||
{
|
{
|
||||||
new (result) T(m_initval);
|
new (result) T(m_initval);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
template< typename T >
|
template <typename T>
|
||||||
Threading::BaseTlsVariable<T>::BaseTlsVariable()
|
Threading::BaseTlsVariable<T>::BaseTlsVariable()
|
||||||
{
|
{
|
||||||
m_IsDisposed = false;
|
m_IsDisposed = false;
|
||||||
CreateKey();
|
CreateKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template <typename T>
|
||||||
void Threading::BaseTlsVariable<T>::KillKey()
|
void Threading::BaseTlsVariable<T>::KillKey()
|
||||||
{
|
{
|
||||||
if (!m_thread_key) return;
|
if (!m_thread_key)
|
||||||
|
return;
|
||||||
|
|
||||||
// Delete the handle for the current thread (which should always be the main/UI thread!)
|
// Delete the handle for the current thread (which should always be the main/UI thread!)
|
||||||
// This is needed because pthreads does *not* clean up the dangling objects when you delete
|
// This is needed because pthreads does *not* clean up the dangling objects when you delete
|
||||||
// the key. The TLS for the process main thread will only be deleted when the process
|
// the key. The TLS for the process main thread will only be deleted when the process
|
||||||
// ends; which is too damn late (it shows up int he leaked memory blocks).
|
// ends; which is too damn late (it shows up int he leaked memory blocks).
|
||||||
|
|
||||||
BaseTlsVariable<T>::_aligned_delete_and_free( pthread_getspecific(m_thread_key) );
|
BaseTlsVariable<T>::_aligned_delete_and_free(pthread_getspecific(m_thread_key));
|
||||||
|
|
||||||
pthread_key_delete( m_thread_key );
|
pthread_key_delete(m_thread_key);
|
||||||
m_thread_key = 0;
|
m_thread_key = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template <typename T>
|
||||||
T* Threading::BaseTlsVariable<T>::GetPtr() const
|
T *Threading::BaseTlsVariable<T>::GetPtr() const
|
||||||
{
|
{
|
||||||
T* result = (T*)pthread_getspecific( m_thread_key );
|
T *result = (T *)pthread_getspecific(m_thread_key);
|
||||||
if( result == NULL )
|
if (result == NULL) {
|
||||||
{
|
pthread_setspecific(m_thread_key, result = (T *)_aligned_malloc(sizeof(T), 16));
|
||||||
pthread_setspecific( m_thread_key, result = (T*)_aligned_malloc(sizeof(T), 16) );
|
CreateInstance(result);
|
||||||
CreateInstance(result);
|
if (result == NULL)
|
||||||
if( result == NULL )
|
throw Exception::OutOfMemory(L"thread local storage variable instance");
|
||||||
throw Exception::OutOfMemory( L"thread local storage variable instance" );
|
}
|
||||||
}
|
return result;
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template <typename T>
|
||||||
void Threading::BaseTlsVariable<T>::CreateKey()
|
void Threading::BaseTlsVariable<T>::CreateKey()
|
||||||
{
|
{
|
||||||
if( 0 != pthread_key_create(&m_thread_key, BaseTlsVariable<T>::_aligned_delete_and_free) )
|
if (0 != pthread_key_create(&m_thread_key, BaseTlsVariable<T>::_aligned_delete_and_free)) {
|
||||||
{
|
pxFailRel("Thread Local Storage Error: key creation failed. This will most likely lead to a rapid application crash.");
|
||||||
pxFailRel( "Thread Local Storage Error: key creation failed. This will most likely lead to a rapid application crash." );
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,20 +29,20 @@
|
||||||
//
|
//
|
||||||
struct TraceLogDescriptor
|
struct TraceLogDescriptor
|
||||||
{
|
{
|
||||||
// short name, alphanumerics only: used for saving/loading options.
|
// short name, alphanumerics only: used for saving/loading options.
|
||||||
const wxChar* ShortName;
|
const wxChar *ShortName;
|
||||||
|
|
||||||
// Standard UI name for this log source. Used in menus, options dialogs.
|
// Standard UI name for this log source. Used in menus, options dialogs.
|
||||||
const wxChar* Name;
|
const wxChar *Name;
|
||||||
|
|
||||||
// Length description for use as a tooltip or menu item description.
|
// Length description for use as a tooltip or menu item description.
|
||||||
const wxChar* Description;
|
const wxChar *Description;
|
||||||
|
|
||||||
wxString GetShortName() const
|
wxString GetShortName() const
|
||||||
{
|
{
|
||||||
pxAssumeDev(Name, "Tracelog descriptors require a valid name!");
|
pxAssumeDev(Name, "Tracelog descriptors require a valid name!");
|
||||||
return ShortName ? ShortName : Name;
|
return ShortName ? ShortName : Name;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -62,52 +62,55 @@ struct TraceLogDescriptor
|
||||||
// check is done top-level, the parameters' calculations can be skipped. If the IsActive()
|
// check is done top-level, the parameters' calculations can be skipped. If the IsActive()
|
||||||
// check is done internally as part of the Write/Format calls, all parameters have to be
|
// check is done internally as part of the Write/Format calls, all parameters have to be
|
||||||
// resolved regardless of if the log is actually active.
|
// resolved regardless of if the log is actually active.
|
||||||
//
|
//
|
||||||
class BaseTraceLogSource
|
class BaseTraceLogSource
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
const TraceLogDescriptor* m_Descriptor;
|
const TraceLogDescriptor *m_Descriptor;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Indicates if the user has enabled this specific log. This boolean only represents
|
// Indicates if the user has enabled this specific log. This boolean only represents
|
||||||
// the configured status of this log, and does *NOT* actually mean the log is active
|
// the configured status of this log, and does *NOT* actually mean the log is active
|
||||||
// even when TRUE. Because many tracelogs have master enablers that act on a group
|
// even when TRUE. Because many tracelogs have master enablers that act on a group
|
||||||
// of logs, logging checks should always use IsActive() instead to determine if a log
|
// of logs, logging checks should always use IsActive() instead to determine if a log
|
||||||
// should be processed or not.
|
// should be processed or not.
|
||||||
bool Enabled;
|
bool Enabled;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
BaseTraceLogSource() : m_Descriptor(NULL), Enabled(false) {}
|
BaseTraceLogSource()
|
||||||
|
: m_Descriptor(NULL)
|
||||||
|
, Enabled(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TraceLog_ImplementBaseAPI(BaseTraceLogSource)
|
TraceLog_ImplementBaseAPI(BaseTraceLogSource)
|
||||||
|
|
||||||
BaseTraceLogSource( const TraceLogDescriptor* desc )
|
BaseTraceLogSource(const TraceLogDescriptor *desc)
|
||||||
{
|
{
|
||||||
pxAssumeDev( desc, "Trace logs must have a valid (non-NULL) descriptor." );
|
pxAssumeDev(desc, "Trace logs must have a valid (non-NULL) descriptor.");
|
||||||
Enabled = false;
|
Enabled = false;
|
||||||
m_Descriptor = desc;
|
m_Descriptor = desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provides a categorical identifier, typically in "group.subgroup.subgroup" form.
|
// Provides a categorical identifier, typically in "group.subgroup.subgroup" form.
|
||||||
// (use periods in favor of colons, since they do not require escape characters when
|
// (use periods in favor of colons, since they do not require escape characters when
|
||||||
// written to ini/config files).
|
// written to ini/config files).
|
||||||
virtual wxString GetCategory() const { return wxEmptyString; }
|
virtual wxString GetCategory() const { return wxEmptyString; }
|
||||||
|
|
||||||
// This method should be used to determine if a log should be generated or not.
|
// This method should be used to determine if a log should be generated or not.
|
||||||
// See the class overview comments for details on how and why this method should
|
// See the class overview comments for details on how and why this method should
|
||||||
// be used.
|
// be used.
|
||||||
virtual bool IsActive() const { return Enabled; }
|
virtual bool IsActive() const { return Enabled; }
|
||||||
|
|
||||||
virtual wxString GetShortName() const { return m_Descriptor->GetShortName(); }
|
virtual wxString GetShortName() const { return m_Descriptor->GetShortName(); }
|
||||||
virtual const wxChar* GetName() const { return m_Descriptor->Name; }
|
virtual const wxChar *GetName() const { return m_Descriptor->Name; }
|
||||||
virtual const wxChar* GetDescription() const
|
virtual const wxChar *GetDescription() const
|
||||||
{
|
{
|
||||||
return (m_Descriptor->Description!=NULL) ? pxGetTranslation(m_Descriptor->Description) : wxEmptyString;
|
return (m_Descriptor->Description != NULL) ? pxGetTranslation(m_Descriptor->Description) : wxEmptyString;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool HasDescription() const { return m_Descriptor->Description != NULL;}
|
|
||||||
|
|
||||||
|
virtual bool HasDescription() const { return m_Descriptor->Description != NULL; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -119,32 +122,32 @@ public:
|
||||||
class TextFileTraceLog : public BaseTraceLogSource
|
class TextFileTraceLog : public BaseTraceLogSource
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TextFileTraceLog( const TraceLogDescriptor* desc )
|
TextFileTraceLog(const TraceLogDescriptor *desc)
|
||||||
: BaseTraceLogSource( desc )
|
: BaseTraceLogSource(desc)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Write( const char* fmt, ... ) const
|
bool Write(const char *fmt, ...) const
|
||||||
{
|
{
|
||||||
va_list list;
|
va_list list;
|
||||||
va_start( list, fmt );
|
va_start(list, fmt);
|
||||||
WriteV( fmt, list );
|
WriteV(fmt, list);
|
||||||
va_end( list );
|
va_end(list);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteV( const char *fmt, va_list list ) const
|
bool WriteV(const char *fmt, va_list list) const
|
||||||
{
|
{
|
||||||
FastFormatAscii ascii;
|
FastFormatAscii ascii;
|
||||||
ApplyPrefix(ascii);
|
ApplyPrefix(ascii);
|
||||||
ascii.WriteV( fmt, list );
|
ascii.WriteV(fmt, list);
|
||||||
DoWrite( ascii );
|
DoWrite(ascii);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void ApplyPrefix( FastFormatAscii& ascii ) const {}
|
virtual void ApplyPrefix(FastFormatAscii &ascii) const {}
|
||||||
virtual void DoWrite( const char* fmt ) const=0;
|
virtual void DoWrite(const char *fmt) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -156,128 +159,130 @@ public:
|
||||||
class ConsoleLogSource : public BaseTraceLogSource
|
class ConsoleLogSource : public BaseTraceLogSource
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ConsoleColors DefaultColor;
|
ConsoleColors DefaultColor;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ConsoleLogSource() : DefaultColor(Color_Gray) {}
|
ConsoleLogSource()
|
||||||
|
: DefaultColor(Color_Gray)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ConsoleLog_ImplementBaseAPI(ConsoleLogSource)
|
ConsoleLog_ImplementBaseAPI(ConsoleLogSource)
|
||||||
|
|
||||||
ConsoleLogSource( const TraceLogDescriptor* desc, ConsoleColors defaultColor = Color_Gray )
|
ConsoleLogSource(const TraceLogDescriptor *desc, ConsoleColors defaultColor = Color_Gray)
|
||||||
: BaseTraceLogSource(desc)
|
: BaseTraceLogSource(desc)
|
||||||
{
|
{
|
||||||
DefaultColor = defaultColor;
|
DefaultColor = defaultColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Writes to the console using the source's default color. Note that the source's default
|
// Writes to the console using the source's default color. Note that the source's default
|
||||||
// color will always be used, thus ConsoleColorScope() will not be effectual unless the
|
// color will always be used, thus ConsoleColorScope() will not be effectual unless the
|
||||||
// console's default color is Color_Default.
|
// console's default color is Color_Default.
|
||||||
bool Write( const char* fmt, ... ) const
|
bool Write(const char *fmt, ...) const
|
||||||
{
|
{
|
||||||
va_list list;
|
va_list list;
|
||||||
va_start( list, fmt );
|
va_start(list, fmt);
|
||||||
WriteV( fmt, list );
|
WriteV(fmt, list);
|
||||||
va_end( list );
|
va_end(list);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Write( const wxChar* fmt, ... ) const
|
bool Write(const wxChar *fmt, ...) const
|
||||||
{
|
{
|
||||||
va_list list;
|
va_list list;
|
||||||
va_start( list, fmt );
|
va_start(list, fmt);
|
||||||
WriteV( fmt, list );
|
WriteV(fmt, list);
|
||||||
va_end( list );
|
va_end(list);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Write( const wxString fmt, ... ) const
|
bool Write(const wxString fmt, ...) const
|
||||||
{
|
{
|
||||||
va_list list;
|
va_list list;
|
||||||
va_start( list, fmt );
|
va_start(list, fmt);
|
||||||
WriteV( fmt.wx_str(), list );
|
WriteV(fmt.wx_str(), list);
|
||||||
va_end( list );
|
va_end(list);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Writes to the console using the specified color. This overrides the default color setting
|
// Writes to the console using the specified color. This overrides the default color setting
|
||||||
// for this log.
|
// for this log.
|
||||||
bool Write( ConsoleColors color, const char* fmt, ... ) const
|
bool Write(ConsoleColors color, const char *fmt, ...) const
|
||||||
{
|
{
|
||||||
va_list list;
|
va_list list;
|
||||||
va_start( list, fmt );
|
va_start(list, fmt);
|
||||||
WriteV( color, fmt, list );
|
WriteV(color, fmt, list);
|
||||||
va_end( list );
|
va_end(list);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Write( ConsoleColors color, const wxChar* fmt, ... ) const
|
bool Write(ConsoleColors color, const wxChar *fmt, ...) const
|
||||||
{
|
{
|
||||||
va_list list;
|
va_list list;
|
||||||
va_start( list, fmt );
|
va_start(list, fmt);
|
||||||
WriteV( color, fmt, list );
|
WriteV(color, fmt, list);
|
||||||
va_end( list );
|
va_end(list);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Writes to the console using bold yellow text -- overrides the log source's default
|
// Writes to the console using bold yellow text -- overrides the log source's default
|
||||||
// color settings.
|
// color settings.
|
||||||
bool Warn( const wxChar* fmt, ... ) const
|
bool Warn(const wxChar *fmt, ...) const
|
||||||
{
|
{
|
||||||
va_list list;
|
va_list list;
|
||||||
va_start( list, fmt );
|
va_start(list, fmt);
|
||||||
WriteV( Color_StrongYellow, fmt, list );
|
WriteV(Color_StrongYellow, fmt, list);
|
||||||
va_end( list );
|
va_end(list);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Warn( const wxString fmt, ... ) const
|
bool Warn(const wxString fmt, ...) const
|
||||||
{
|
{
|
||||||
va_list list;
|
va_list list;
|
||||||
va_start( list, fmt );
|
va_start(list, fmt);
|
||||||
WriteV( Color_StrongYellow, fmt.wx_str(), list );
|
WriteV(Color_StrongYellow, fmt.wx_str(), list);
|
||||||
va_end( list );
|
va_end(list);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Writes to the console using bold red text -- overrides the log source's default
|
// Writes to the console using bold red text -- overrides the log source's default
|
||||||
// color settings.
|
// color settings.
|
||||||
bool Error( const wxChar* fmt, ... ) const
|
bool Error(const wxChar *fmt, ...) const
|
||||||
{
|
{
|
||||||
va_list list;
|
va_list list;
|
||||||
va_start( list, fmt );
|
va_start(list, fmt);
|
||||||
WriteV( Color_StrongRed, fmt, list );
|
WriteV(Color_StrongRed, fmt, list);
|
||||||
va_end( list );
|
va_end(list);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Error( const wxString fmt, ... ) const
|
bool Error(const wxString fmt, ...) const
|
||||||
{
|
{
|
||||||
va_list list;
|
va_list list;
|
||||||
va_start( list, fmt );
|
va_start(list, fmt);
|
||||||
WriteV( Color_StrongRed, fmt.wx_str(), list );
|
WriteV(Color_StrongRed, fmt.wx_str(), list);
|
||||||
va_end( list );
|
va_end(list);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteV( const char *fmt, va_list list ) const;
|
bool WriteV(const char *fmt, va_list list) const;
|
||||||
bool WriteV( const wxChar *fmt, va_list list ) const;
|
bool WriteV(const wxChar *fmt, va_list list) const;
|
||||||
|
|
||||||
bool WriteV( ConsoleColors color, const char *fmt, va_list list ) const;
|
bool WriteV(ConsoleColors color, const char *fmt, va_list list) const;
|
||||||
bool WriteV( ConsoleColors color, const wxChar *fmt, va_list list ) const;
|
bool WriteV(ConsoleColors color, const wxChar *fmt, va_list list) const;
|
||||||
|
|
||||||
virtual void DoWrite( const wxChar* msg ) const
|
virtual void DoWrite(const wxChar *msg) const
|
||||||
{
|
{
|
||||||
Console.DoWriteLn( msg );
|
Console.DoWriteLn(msg);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,43 +18,43 @@
|
||||||
|
|
||||||
// This header contains non-optimized implementation of memzero_ptr and memset8, etc
|
// This header contains non-optimized implementation of memzero_ptr and memset8, etc
|
||||||
|
|
||||||
template< u32 data, typename T >
|
template <u32 data, typename T>
|
||||||
static __fi void memset32( T& obj )
|
static __fi void memset32(T &obj)
|
||||||
{
|
{
|
||||||
// this function works on 32-bit aligned lengths of data only.
|
// this function works on 32-bit aligned lengths of data only.
|
||||||
// If the data length is not a factor of 32 bits, the C++ optimizing compiler will
|
// If the data length is not a factor of 32 bits, the C++ optimizing compiler will
|
||||||
// probably just generate mysteriously broken code in Release builds. ;)
|
// probably just generate mysteriously broken code in Release builds. ;)
|
||||||
|
|
||||||
pxAssume((sizeof(T) & 0x3) == 0);
|
pxAssume((sizeof(T) & 0x3) == 0);
|
||||||
|
|
||||||
u32* dest = (u32*)&obj;
|
u32 *dest = (u32 *)&obj;
|
||||||
for( int i=sizeof(T)>>2; i; --i, ++dest )
|
for (int i = sizeof(T) >> 2; i; --i, ++dest)
|
||||||
*dest = data;
|
*dest = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T >
|
template <typename T>
|
||||||
static __fi void memzero( T& obj )
|
static __fi void memzero(T &obj)
|
||||||
{
|
{
|
||||||
memset( &obj, 0, sizeof( T ) );
|
memset(&obj, 0, sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
template< u8 data, typename T >
|
template <u8 data, typename T>
|
||||||
static __fi void memset8( T& obj )
|
static __fi void memset8(T &obj)
|
||||||
{
|
{
|
||||||
// Aligned sizes use the optimized 32 bit inline memset. Unaligned sizes use memset.
|
// Aligned sizes use the optimized 32 bit inline memset. Unaligned sizes use memset.
|
||||||
if( (sizeof(T) & 0x3) != 0 )
|
if ((sizeof(T) & 0x3) != 0)
|
||||||
memset( &obj, data, sizeof( T ) );
|
memset(&obj, data, sizeof(T));
|
||||||
else {
|
else {
|
||||||
const u32 data32 = data + (data<<8) + (data<<16) + (data<<24);
|
const u32 data32 = data + (data << 8) + (data << 16) + (data << 24);
|
||||||
memset32<data32>( obj );
|
memset32<data32>(obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Code is only called in the init so no need to bother with ASM
|
// Code is only called in the init so no need to bother with ASM
|
||||||
template< u8 data, size_t bytes >
|
template <u8 data, size_t bytes>
|
||||||
static __fi void memset_8( void *dest )
|
static __fi void memset_8(void *dest)
|
||||||
{
|
{
|
||||||
memset(dest, data, bytes);
|
memset(dest, data, bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -29,50 +29,74 @@
|
||||||
class pxCheckBox : public wxPanelWithHelpers
|
class pxCheckBox : public wxPanelWithHelpers
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
wxCheckBox* m_checkbox;
|
wxCheckBox *m_checkbox;
|
||||||
pxStaticText* m_subtext;
|
pxStaticText *m_subtext;
|
||||||
|
|
||||||
// padding below the subtext (if there's subtext). If there's no subtext, this value is unused.
|
// padding below the subtext (if there's subtext). If there's no subtext, this value is unused.
|
||||||
int m_subPadding;
|
int m_subPadding;
|
||||||
|
|
||||||
|
wxSizerItem *m_sizerItem_subtext;
|
||||||
|
|
||||||
wxSizerItem* m_sizerItem_subtext;
|
|
||||||
public:
|
public:
|
||||||
pxCheckBox( wxWindow* parent, const wxString& label, const wxString& subtext=wxEmptyString, int flags = wxCHK_2STATE );
|
pxCheckBox(wxWindow *parent, const wxString &label, const wxString &subtext = wxEmptyString, int flags = wxCHK_2STATE);
|
||||||
pxCheckBox( wxWindow* parent, const wxString& label, int flags );
|
pxCheckBox(wxWindow *parent, const wxString &label, int flags);
|
||||||
virtual ~pxCheckBox() throw() {}
|
virtual ~pxCheckBox() throw() {}
|
||||||
|
|
||||||
bool HasSubText() const { return m_subtext != NULL; }
|
bool HasSubText() const { return m_subtext != NULL; }
|
||||||
const pxStaticText* GetSubText() const { return m_subtext; }
|
const pxStaticText *GetSubText() const { return m_subtext; }
|
||||||
|
|
||||||
pxCheckBox& SetSubPadding( int pad );
|
pxCheckBox &SetSubPadding(int pad);
|
||||||
pxCheckBox& SetToolTip( const wxString& tip );
|
pxCheckBox &SetToolTip(const wxString &tip);
|
||||||
pxCheckBox& SetValue( bool val );
|
pxCheckBox &SetValue(bool val);
|
||||||
pxCheckBox& SetIndeterminate();
|
pxCheckBox &SetIndeterminate();
|
||||||
pxCheckBox& SetState( wxCheckBoxState state );
|
pxCheckBox &SetState(wxCheckBoxState state);
|
||||||
|
|
||||||
wxCheckBoxState GetState() const { pxAssert( m_checkbox != NULL ); return m_checkbox->Get3StateValue(); }
|
wxCheckBoxState GetState() const
|
||||||
bool GetValue() const { pxAssert( m_checkbox != NULL ); return m_checkbox->GetValue(); }
|
{
|
||||||
bool IsChecked() const { pxAssert( m_checkbox != NULL ); return m_checkbox->IsChecked(); }
|
pxAssert(m_checkbox != NULL);
|
||||||
bool IsIndeterminate() const { pxAssert( m_checkbox != NULL ); return m_checkbox->Get3StateValue() == wxCHK_UNDETERMINED; }
|
return m_checkbox->Get3StateValue();
|
||||||
operator wxCheckBox&() { pxAssert( m_checkbox != NULL ); return *m_checkbox; }
|
}
|
||||||
operator const wxCheckBox&() const { pxAssert( m_checkbox != NULL ); return *m_checkbox; }
|
bool GetValue() const
|
||||||
|
{
|
||||||
|
pxAssert(m_checkbox != NULL);
|
||||||
|
return m_checkbox->GetValue();
|
||||||
|
}
|
||||||
|
bool IsChecked() const
|
||||||
|
{
|
||||||
|
pxAssert(m_checkbox != NULL);
|
||||||
|
return m_checkbox->IsChecked();
|
||||||
|
}
|
||||||
|
bool IsIndeterminate() const
|
||||||
|
{
|
||||||
|
pxAssert(m_checkbox != NULL);
|
||||||
|
return m_checkbox->Get3StateValue() == wxCHK_UNDETERMINED;
|
||||||
|
}
|
||||||
|
operator wxCheckBox &()
|
||||||
|
{
|
||||||
|
pxAssert(m_checkbox != NULL);
|
||||||
|
return *m_checkbox;
|
||||||
|
}
|
||||||
|
operator const wxCheckBox &() const
|
||||||
|
{
|
||||||
|
pxAssert(m_checkbox != NULL);
|
||||||
|
return *m_checkbox;
|
||||||
|
}
|
||||||
|
|
||||||
wxCheckBox* GetWxPtr() { return m_checkbox; }
|
wxCheckBox *GetWxPtr() { return m_checkbox; }
|
||||||
const wxCheckBox* GetWxPtr() const { return m_checkbox; }
|
const wxCheckBox *GetWxPtr() const { return m_checkbox; }
|
||||||
|
|
||||||
//wxWindowID GetId() const { pxAssert( m_checkbox != NULL ); return m_checkbox->GetId(); }
|
//wxWindowID GetId() const { pxAssert( m_checkbox != NULL ); return m_checkbox->GetId(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void Init( const wxString& label, const wxString& subtext, int flags );
|
void Init(const wxString &label, const wxString &subtext, int flags);
|
||||||
void OnCheckpartCommand( wxCommandEvent& evt );
|
void OnCheckpartCommand(wxCommandEvent &evt);
|
||||||
void OnSubtextClicked( wxCommandEvent& evt );
|
void OnSubtextClicked(wxCommandEvent &evt);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void operator+=( wxSizer& target, pxCheckBox& src );
|
extern void operator+=(wxSizer &target, pxCheckBox &src);
|
||||||
|
|
||||||
template<>
|
template <>
|
||||||
inline void operator+=( wxSizer& target, const pxWindowAndFlags<pxCheckBox>& src )
|
inline void operator+=(wxSizer &target, const pxWindowAndFlags<pxCheckBox> &src)
|
||||||
{
|
{
|
||||||
target.Add( src.window, src.flags );
|
target.Add(src.window, src.flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,36 +26,36 @@ typedef void FnType_Void();
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
class SynchronousActionState
|
class SynchronousActionState
|
||||||
{
|
{
|
||||||
DeclareNoncopyableObject( SynchronousActionState );
|
DeclareNoncopyableObject(SynchronousActionState);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool m_posted;
|
bool m_posted;
|
||||||
Threading::Semaphore m_sema;
|
Threading::Semaphore m_sema;
|
||||||
ScopedExcept m_exception;
|
ScopedExcept m_exception;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
sptr return_value;
|
sptr return_value;
|
||||||
|
|
||||||
SynchronousActionState()
|
SynchronousActionState()
|
||||||
{
|
{
|
||||||
m_posted = false;
|
m_posted = false;
|
||||||
return_value = 0;
|
return_value = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~SynchronousActionState() throw() {}
|
virtual ~SynchronousActionState() throw() {}
|
||||||
|
|
||||||
void SetException( const BaseException& ex );
|
void SetException(const BaseException &ex);
|
||||||
void SetException( BaseException* ex );
|
void SetException(BaseException *ex);
|
||||||
|
|
||||||
Threading::Semaphore& GetSemaphore() { return m_sema; }
|
Threading::Semaphore &GetSemaphore() { return m_sema; }
|
||||||
const Threading::Semaphore& GetSemaphore() const { return m_sema; }
|
const Threading::Semaphore &GetSemaphore() const { return m_sema; }
|
||||||
|
|
||||||
void RethrowException() const;
|
void RethrowException() const;
|
||||||
int WaitForResult();
|
int WaitForResult();
|
||||||
int WaitForResult_NoExceptions();
|
int WaitForResult_NoExceptions();
|
||||||
void PostResult( int res );
|
void PostResult(int res);
|
||||||
void ClearResult();
|
void ClearResult();
|
||||||
void PostResult();
|
void PostResult();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -68,18 +68,20 @@ public:
|
||||||
//
|
//
|
||||||
class pxSimpleEvent : public wxEvent
|
class pxSimpleEvent : public wxEvent
|
||||||
{
|
{
|
||||||
DECLARE_DYNAMIC_CLASS_NO_ASSIGN(pxSimpleEvent)
|
DECLARE_DYNAMIC_CLASS_NO_ASSIGN(pxSimpleEvent)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit pxSimpleEvent( int evtid=0 )
|
explicit pxSimpleEvent(int evtid = 0)
|
||||||
: wxEvent(0, evtid)
|
: wxEvent(0, evtid)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
pxSimpleEvent( wxWindowID winId, int evtid )
|
pxSimpleEvent(wxWindowID winId, int evtid)
|
||||||
: wxEvent(winId, evtid)
|
: wxEvent(winId, evtid)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
virtual wxEvent *Clone() const { return new pxSimpleEvent(*this); }
|
virtual wxEvent *Clone() const { return new pxSimpleEvent(*this); }
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -91,41 +93,41 @@ wxDECLARE_EVENT(pxEvt_InvokeAction, pxActionEvent);
|
||||||
|
|
||||||
class pxActionEvent : public wxEvent
|
class pxActionEvent : public wxEvent
|
||||||
{
|
{
|
||||||
DECLARE_DYNAMIC_CLASS_NO_ASSIGN(pxActionEvent)
|
DECLARE_DYNAMIC_CLASS_NO_ASSIGN(pxActionEvent)
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
SynchronousActionState* m_state;
|
SynchronousActionState *m_state;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~pxActionEvent() throw() { }
|
virtual ~pxActionEvent() throw() {}
|
||||||
virtual pxActionEvent *Clone() const { return new pxActionEvent(*this); }
|
virtual pxActionEvent *Clone() const { return new pxActionEvent(*this); }
|
||||||
|
|
||||||
explicit pxActionEvent( SynchronousActionState* sema=NULL, int msgtype=pxEvt_InvokeAction );
|
explicit pxActionEvent(SynchronousActionState *sema = NULL, int msgtype = pxEvt_InvokeAction);
|
||||||
explicit pxActionEvent( SynchronousActionState& sema, int msgtype=pxEvt_InvokeAction );
|
explicit pxActionEvent(SynchronousActionState &sema, int msgtype = pxEvt_InvokeAction);
|
||||||
pxActionEvent( const pxActionEvent& src );
|
pxActionEvent(const pxActionEvent &src);
|
||||||
|
|
||||||
Threading::Semaphore* GetSemaphore() const { return m_state ? &m_state->GetSemaphore() : NULL; }
|
Threading::Semaphore *GetSemaphore() const { return m_state ? &m_state->GetSemaphore() : NULL; }
|
||||||
|
|
||||||
const SynchronousActionState* GetSyncState() const { return m_state; }
|
const SynchronousActionState *GetSyncState() const { return m_state; }
|
||||||
SynchronousActionState* GetSyncState() { return m_state; }
|
SynchronousActionState *GetSyncState() { return m_state; }
|
||||||
|
|
||||||
void SetSyncState( SynchronousActionState* obj ) { m_state = obj; }
|
void SetSyncState(SynchronousActionState *obj) { m_state = obj; }
|
||||||
void SetSyncState( SynchronousActionState& obj ) { m_state = &obj; }
|
void SetSyncState(SynchronousActionState &obj) { m_state = &obj; }
|
||||||
|
|
||||||
virtual void SetException( BaseException* ex );
|
virtual void SetException(BaseException *ex);
|
||||||
void SetException( const BaseException& ex );
|
void SetException(const BaseException &ex);
|
||||||
|
|
||||||
|
virtual void _DoInvokeEvent();
|
||||||
|
|
||||||
virtual void _DoInvokeEvent();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Extending classes should implement this method to perfoem whatever action it is
|
// Extending classes should implement this method to perfoem whatever action it is
|
||||||
// the event is supposed to do. :) Thread affinity is garaunteed to be the Main/UI
|
// the event is supposed to do. :) Thread affinity is garaunteed to be the Main/UI
|
||||||
// thread, and exceptions will be handled automatically.
|
// thread, and exceptions will be handled automatically.
|
||||||
//
|
//
|
||||||
// Exception note: exceptions are passed back to the thread that posted the event
|
// Exception note: exceptions are passed back to the thread that posted the event
|
||||||
// to the queue, when possible. If the calling thread is not blocking for a result
|
// to the queue, when possible. If the calling thread is not blocking for a result
|
||||||
// from this event, then the exception will be posted to the Main/UI thread instead.
|
// from this event, then the exception will be posted to the Main/UI thread instead.
|
||||||
virtual void InvokeEvent() {}
|
virtual void InvokeEvent() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -134,27 +136,27 @@ protected:
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
class pxExceptionEvent : public pxActionEvent
|
class pxExceptionEvent : public pxActionEvent
|
||||||
{
|
{
|
||||||
typedef pxActionEvent _parent;
|
typedef pxActionEvent _parent;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
BaseException* m_except;
|
BaseException *m_except;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
pxExceptionEvent( BaseException* ex=NULL )
|
pxExceptionEvent(BaseException *ex = NULL)
|
||||||
{
|
{
|
||||||
m_except = ex;
|
m_except = ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
pxExceptionEvent( const BaseException& ex );
|
pxExceptionEvent(const BaseException &ex);
|
||||||
|
|
||||||
virtual ~pxExceptionEvent() throw()
|
virtual ~pxExceptionEvent() throw()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual pxExceptionEvent *Clone() const { return new pxExceptionEvent(*this); }
|
virtual pxExceptionEvent *Clone() const { return new pxExceptionEvent(*this); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void InvokeEvent();
|
void InvokeEvent();
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -163,29 +165,29 @@ protected:
|
||||||
|
|
||||||
class pxSynchronousCommandEvent : public wxCommandEvent
|
class pxSynchronousCommandEvent : public wxCommandEvent
|
||||||
{
|
{
|
||||||
DECLARE_DYNAMIC_CLASS_NO_ASSIGN(pxSynchronousCommandEvent)
|
DECLARE_DYNAMIC_CLASS_NO_ASSIGN(pxSynchronousCommandEvent)
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
SynchronousActionState* m_sync;
|
SynchronousActionState *m_sync;
|
||||||
wxEventType m_realEvent;
|
wxEventType m_realEvent;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~pxSynchronousCommandEvent() throw() { }
|
virtual ~pxSynchronousCommandEvent() throw() {}
|
||||||
virtual pxSynchronousCommandEvent *Clone() const { return new pxSynchronousCommandEvent(*this); }
|
virtual pxSynchronousCommandEvent *Clone() const { return new pxSynchronousCommandEvent(*this); }
|
||||||
|
|
||||||
pxSynchronousCommandEvent(SynchronousActionState* sema=NULL, wxEventType commandType = wxEVT_NULL, int winid = 0);
|
pxSynchronousCommandEvent(SynchronousActionState *sema = NULL, wxEventType commandType = wxEVT_NULL, int winid = 0);
|
||||||
pxSynchronousCommandEvent(SynchronousActionState& sema, wxEventType commandType = wxEVT_NULL, int winid = 0);
|
pxSynchronousCommandEvent(SynchronousActionState &sema, wxEventType commandType = wxEVT_NULL, int winid = 0);
|
||||||
|
|
||||||
pxSynchronousCommandEvent(SynchronousActionState* sema, const wxCommandEvent& evt);
|
pxSynchronousCommandEvent(SynchronousActionState *sema, const wxCommandEvent &evt);
|
||||||
pxSynchronousCommandEvent(SynchronousActionState& sema, const wxCommandEvent& evt);
|
pxSynchronousCommandEvent(SynchronousActionState &sema, const wxCommandEvent &evt);
|
||||||
|
|
||||||
pxSynchronousCommandEvent(const pxSynchronousCommandEvent& src);
|
pxSynchronousCommandEvent(const pxSynchronousCommandEvent &src);
|
||||||
|
|
||||||
Threading::Semaphore* GetSemaphore() { return m_sync ? &m_sync->GetSemaphore() : NULL; }
|
Threading::Semaphore *GetSemaphore() { return m_sync ? &m_sync->GetSemaphore() : NULL; }
|
||||||
wxEventType GetRealEventType() const { return m_realEvent; }
|
wxEventType GetRealEventType() const { return m_realEvent; }
|
||||||
|
|
||||||
void SetException( BaseException* ex );
|
void SetException(BaseException *ex);
|
||||||
void SetException( const BaseException& ex );
|
void SetException(const BaseException &ex);
|
||||||
};
|
};
|
||||||
|
|
||||||
wxDECLARE_EVENT(pxEvt_SynchronousCommand, pxSynchronousCommandEvent);
|
wxDECLARE_EVENT(pxEvt_SynchronousCommand, pxSynchronousCommandEvent);
|
||||||
|
@ -195,23 +197,23 @@ wxDECLARE_EVENT(pxEvt_SynchronousCommand, pxSynchronousCommandEvent);
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
class BaseMessageBoxEvent : public pxActionEvent
|
class BaseMessageBoxEvent : public pxActionEvent
|
||||||
{
|
{
|
||||||
typedef pxActionEvent _parent;
|
typedef pxActionEvent _parent;
|
||||||
DECLARE_DYNAMIC_CLASS_NO_ASSIGN(BaseMessageBoxEvent)
|
DECLARE_DYNAMIC_CLASS_NO_ASSIGN(BaseMessageBoxEvent)
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
wxString m_Content;
|
wxString m_Content;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~BaseMessageBoxEvent() throw() { }
|
virtual ~BaseMessageBoxEvent() throw() {}
|
||||||
virtual BaseMessageBoxEvent *Clone() const { return new BaseMessageBoxEvent(*this); }
|
virtual BaseMessageBoxEvent *Clone() const { return new BaseMessageBoxEvent(*this); }
|
||||||
|
|
||||||
explicit BaseMessageBoxEvent( const wxString& content=wxEmptyString, SynchronousActionState* instdata=NULL );
|
explicit BaseMessageBoxEvent(const wxString &content = wxEmptyString, SynchronousActionState *instdata = NULL);
|
||||||
BaseMessageBoxEvent( const wxString& content, SynchronousActionState& instdata );
|
BaseMessageBoxEvent(const wxString &content, SynchronousActionState &instdata);
|
||||||
BaseMessageBoxEvent( const BaseMessageBoxEvent& event );
|
BaseMessageBoxEvent(const BaseMessageBoxEvent &event);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void InvokeEvent();
|
virtual void InvokeEvent();
|
||||||
virtual int _DoDialog() const;
|
virtual int _DoDialog() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -220,82 +222,134 @@ protected:
|
||||||
class MsgButtons
|
class MsgButtons
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
BITFIELD32()
|
BITFIELD32()
|
||||||
bool
|
bool
|
||||||
m_OK :1,
|
m_OK : 1,
|
||||||
m_Cancel :1,
|
m_Cancel : 1,
|
||||||
m_Yes :1,
|
m_Yes : 1,
|
||||||
m_No :1,
|
m_No : 1,
|
||||||
m_AllowToAll:1,
|
m_AllowToAll : 1,
|
||||||
m_Apply :1,
|
m_Apply : 1,
|
||||||
m_Abort :1,
|
m_Abort : 1,
|
||||||
m_Retry :1,
|
m_Retry : 1,
|
||||||
m_Ignore :1,
|
m_Ignore : 1,
|
||||||
m_Reset :1,
|
m_Reset : 1,
|
||||||
m_Close :1;
|
m_Close : 1;
|
||||||
BITFIELD_END
|
BITFIELD_END
|
||||||
|
|
||||||
wxString m_CustomLabel;
|
wxString m_CustomLabel;
|
||||||
wxString m_CustomLabelId;
|
wxString m_CustomLabelId;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MsgButtons() { bitset = 0; }
|
MsgButtons() { bitset = 0; }
|
||||||
|
|
||||||
MsgButtons& OK() { m_OK = true; return *this; }
|
MsgButtons &OK()
|
||||||
MsgButtons& Cancel() { m_Cancel = true; return *this; }
|
{
|
||||||
MsgButtons& Apply() { m_Apply = true; return *this; }
|
m_OK = true;
|
||||||
MsgButtons& Yes() { m_Yes = true; return *this; }
|
return *this;
|
||||||
MsgButtons& No() { m_No = true; return *this; }
|
}
|
||||||
MsgButtons& ToAll() { m_AllowToAll = true; return *this; }
|
MsgButtons &Cancel()
|
||||||
|
{
|
||||||
|
m_Cancel = true;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
MsgButtons &Apply()
|
||||||
|
{
|
||||||
|
m_Apply = true;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
MsgButtons &Yes()
|
||||||
|
{
|
||||||
|
m_Yes = true;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
MsgButtons &No()
|
||||||
|
{
|
||||||
|
m_No = true;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
MsgButtons &ToAll()
|
||||||
|
{
|
||||||
|
m_AllowToAll = true;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
MsgButtons& Abort() { m_Abort = true; return *this; }
|
MsgButtons &Abort()
|
||||||
MsgButtons& Retry() { m_Retry = true; return *this; }
|
{
|
||||||
MsgButtons& Ignore() { m_Ignore = true; return *this; }
|
m_Abort = true;
|
||||||
MsgButtons& Reset() { m_Reset = true; return *this; }
|
return *this;
|
||||||
MsgButtons& Close() { m_Close = true; return *this; }
|
}
|
||||||
|
MsgButtons &Retry()
|
||||||
|
{
|
||||||
|
m_Retry = true;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
MsgButtons &Ignore()
|
||||||
|
{
|
||||||
|
m_Ignore = true;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
MsgButtons &Reset()
|
||||||
|
{
|
||||||
|
m_Reset = true;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
MsgButtons &Close()
|
||||||
|
{
|
||||||
|
m_Close = true;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
// label - native language label displayed to user
|
// label - native language label displayed to user
|
||||||
// id - raw ASCII identifier used in the config file (do not translate, hence char*)
|
// id - raw ASCII identifier used in the config file (do not translate, hence char*)
|
||||||
MsgButtons& Custom( const wxString& label, const char* id )
|
MsgButtons &Custom(const wxString &label, const char *id)
|
||||||
{
|
{
|
||||||
m_CustomLabel = label;
|
m_CustomLabel = label;
|
||||||
m_CustomLabelId = fromUTF8(id);
|
m_CustomLabelId = fromUTF8(id);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
MsgButtons& OKCancel() { m_OK = m_Cancel = true; return *this; }
|
MsgButtons &OKCancel()
|
||||||
MsgButtons& YesNo() { m_Yes = m_No = true; return *this; }
|
{
|
||||||
|
m_OK = m_Cancel = true;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
MsgButtons &YesNo()
|
||||||
|
{
|
||||||
|
m_Yes = m_No = true;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
bool HasOK() const { return m_OK; }
|
bool HasOK() const { return m_OK; }
|
||||||
bool HasCancel() const { return m_Cancel; }
|
bool HasCancel() const { return m_Cancel; }
|
||||||
bool HasApply() const { return m_Apply; }
|
bool HasApply() const { return m_Apply; }
|
||||||
bool HasYes() const { return m_Yes; }
|
bool HasYes() const { return m_Yes; }
|
||||||
bool HasNo() const { return m_No; }
|
bool HasNo() const { return m_No; }
|
||||||
bool AllowsToAll() const{ return m_AllowToAll; }
|
bool AllowsToAll() const { return m_AllowToAll; }
|
||||||
|
|
||||||
bool HasAbort() const { return m_Abort; }
|
bool HasAbort() const { return m_Abort; }
|
||||||
bool HasRetry() const { return m_Retry; }
|
bool HasRetry() const { return m_Retry; }
|
||||||
bool HasIgnore() const { return m_Ignore; }
|
bool HasIgnore() const { return m_Ignore; }
|
||||||
bool HasReset() const { return m_Reset; }
|
bool HasReset() const { return m_Reset; }
|
||||||
bool HasClose() const { return m_Close; }
|
bool HasClose() const { return m_Close; }
|
||||||
|
|
||||||
bool HasCustom() const { return !m_CustomLabel.IsEmpty(); }
|
bool HasCustom() const { return !m_CustomLabel.IsEmpty(); }
|
||||||
const wxString& GetCustomLabel() const { return m_CustomLabel; }
|
const wxString &GetCustomLabel() const { return m_CustomLabel; }
|
||||||
const wxString& GetCustomLabelId() const { return m_CustomLabelId; }
|
const wxString &GetCustomLabelId() const { return m_CustomLabelId; }
|
||||||
|
|
||||||
bool Allows( wxWindowID id ) const;
|
bool Allows(wxWindowID id) const;
|
||||||
void SetBestFocus( wxWindow* dialog ) const;
|
void SetBestFocus(wxWindow *dialog) const;
|
||||||
void SetBestFocus( wxWindow& dialog ) const;
|
void SetBestFocus(wxWindow &dialog) const;
|
||||||
|
|
||||||
bool operator ==( const MsgButtons& right ) const
|
bool operator==(const MsgButtons &right) const
|
||||||
{
|
{
|
||||||
return OpEqu( bitset );
|
return OpEqu(bitset);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator !=( const MsgButtons& right ) const
|
bool operator!=(const MsgButtons &right) const
|
||||||
{
|
{
|
||||||
return !OpEqu( bitset );
|
return !OpEqu(bitset);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -318,24 +372,24 @@ public:
|
||||||
//
|
//
|
||||||
class pxMessageBoxEvent : public BaseMessageBoxEvent
|
class pxMessageBoxEvent : public BaseMessageBoxEvent
|
||||||
{
|
{
|
||||||
typedef BaseMessageBoxEvent _parent;
|
typedef BaseMessageBoxEvent _parent;
|
||||||
DECLARE_DYNAMIC_CLASS_NO_ASSIGN(pxMessageBoxEvent)
|
DECLARE_DYNAMIC_CLASS_NO_ASSIGN(pxMessageBoxEvent)
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
wxString m_Title;
|
wxString m_Title;
|
||||||
MsgButtons m_Buttons;
|
MsgButtons m_Buttons;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~pxMessageBoxEvent() throw() { }
|
virtual ~pxMessageBoxEvent() throw() {}
|
||||||
virtual pxMessageBoxEvent *Clone() const { return new pxMessageBoxEvent(*this); }
|
virtual pxMessageBoxEvent *Clone() const { return new pxMessageBoxEvent(*this); }
|
||||||
|
|
||||||
pxMessageBoxEvent() {}
|
pxMessageBoxEvent() {}
|
||||||
pxMessageBoxEvent( const wxString& title, const wxString& content, const MsgButtons& buttons, SynchronousActionState& instdata );
|
pxMessageBoxEvent(const wxString &title, const wxString &content, const MsgButtons &buttons, SynchronousActionState &instdata);
|
||||||
pxMessageBoxEvent( const wxString& title, const wxString& content, const MsgButtons& buttons, SynchronousActionState* instdata=NULL );
|
pxMessageBoxEvent(const wxString &title, const wxString &content, const MsgButtons &buttons, SynchronousActionState *instdata = NULL);
|
||||||
pxMessageBoxEvent( const pxMessageBoxEvent& event );
|
pxMessageBoxEvent(const pxMessageBoxEvent &event);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int _DoDialog() const;
|
int _DoDialog() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -343,22 +397,22 @@ protected:
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
class pxAssertionEvent : public BaseMessageBoxEvent
|
class pxAssertionEvent : public BaseMessageBoxEvent
|
||||||
{
|
{
|
||||||
typedef BaseMessageBoxEvent _parent;
|
typedef BaseMessageBoxEvent _parent;
|
||||||
DECLARE_DYNAMIC_CLASS_NO_ASSIGN( pxAssertionEvent )
|
DECLARE_DYNAMIC_CLASS_NO_ASSIGN(pxAssertionEvent)
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
wxString m_Stacktrace;
|
wxString m_Stacktrace;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~pxAssertionEvent() throw() { }
|
virtual ~pxAssertionEvent() throw() {}
|
||||||
virtual pxAssertionEvent *Clone() const { return new pxAssertionEvent(*this); }
|
virtual pxAssertionEvent *Clone() const { return new pxAssertionEvent(*this); }
|
||||||
|
|
||||||
pxAssertionEvent( const wxString& content=wxEmptyString, const wxString& trace=wxEmptyString, SynchronousActionState* instdata=NULL );
|
pxAssertionEvent(const wxString &content = wxEmptyString, const wxString &trace = wxEmptyString, SynchronousActionState *instdata = NULL);
|
||||||
pxAssertionEvent( const wxString& content, const wxString& trace, SynchronousActionState& instdata );
|
pxAssertionEvent(const wxString &content, const wxString &trace, SynchronousActionState &instdata);
|
||||||
pxAssertionEvent( const pxAssertionEvent& event );
|
pxAssertionEvent(const pxAssertionEvent &event);
|
||||||
|
|
||||||
pxAssertionEvent& SetStacktrace( const wxString& trace );
|
pxAssertionEvent &SetStacktrace(const wxString &trace);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int _DoDialog() const;
|
int _DoDialog() const;
|
||||||
};
|
};
|
||||||
|
|
|
@ -40,12 +40,12 @@ extern const wxPoint wxDefaultPosition;
|
||||||
|
|
||||||
namespace Threading
|
namespace Threading
|
||||||
{
|
{
|
||||||
class Mutex;
|
class Mutex;
|
||||||
class Semaphore;
|
class Semaphore;
|
||||||
class pxThread;
|
class pxThread;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Exception
|
namespace Exception
|
||||||
{
|
{
|
||||||
class BaseException;
|
class BaseException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,45 +25,45 @@
|
||||||
|
|
||||||
struct RadioPanelItem
|
struct RadioPanelItem
|
||||||
{
|
{
|
||||||
wxString Label;
|
wxString Label;
|
||||||
wxString SubText;
|
wxString SubText;
|
||||||
wxString ToolTip;
|
wxString ToolTip;
|
||||||
|
|
||||||
int SomeInt;
|
int SomeInt;
|
||||||
void* SomePtr;
|
void *SomePtr;
|
||||||
|
|
||||||
RadioPanelItem( const wxString& label, const wxString& subtext=wxEmptyString, const wxString& tooltip=wxEmptyString )
|
RadioPanelItem(const wxString &label, const wxString &subtext = wxEmptyString, const wxString &tooltip = wxEmptyString)
|
||||||
: Label( label )
|
: Label(label)
|
||||||
, SubText( subtext )
|
, SubText(subtext)
|
||||||
, ToolTip( tooltip )
|
, ToolTip(tooltip)
|
||||||
{
|
{
|
||||||
SomeInt = 0;
|
SomeInt = 0;
|
||||||
SomePtr = NULL;
|
SomePtr = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
RadioPanelItem& SetToolTip( const wxString& tip )
|
RadioPanelItem &SetToolTip(const wxString &tip)
|
||||||
{
|
{
|
||||||
ToolTip = tip;
|
ToolTip = tip;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
RadioPanelItem& SetSubText( const wxString& text )
|
RadioPanelItem &SetSubText(const wxString &text)
|
||||||
{
|
{
|
||||||
SubText = text;
|
SubText = text;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
RadioPanelItem& SetInt( int intval )
|
|
||||||
{
|
|
||||||
SomeInt = intval;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
RadioPanelItem& SetPtr( void* ptrval )
|
RadioPanelItem &SetInt(int intval)
|
||||||
{
|
{
|
||||||
SomePtr = ptrval;
|
SomeInt = intval;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RadioPanelItem &SetPtr(void *ptrval)
|
||||||
|
{
|
||||||
|
SomePtr = ptrval;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -71,8 +71,8 @@ struct RadioPanelItem
|
||||||
// wrapped and re-wrapped with multiple calls to OnResize().
|
// wrapped and re-wrapped with multiple calls to OnResize().
|
||||||
struct RadioPanelObjects
|
struct RadioPanelObjects
|
||||||
{
|
{
|
||||||
wxRadioButton* LabelObj;
|
wxRadioButton *LabelObj;
|
||||||
pxStaticText* SubTextObj;
|
pxStaticText *SubTextObj;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -91,86 +91,86 @@ struct RadioPanelObjects
|
||||||
class pxRadioPanel : public wxPanelWithHelpers
|
class pxRadioPanel : public wxPanelWithHelpers
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
typedef std::vector<RadioPanelItem> ButtonArray;
|
typedef std::vector<RadioPanelItem> ButtonArray;
|
||||||
typedef SafeArray<RadioPanelObjects> ButtonObjArray;
|
typedef SafeArray<RadioPanelObjects> ButtonObjArray;
|
||||||
|
|
||||||
ButtonArray m_buttonStrings;
|
ButtonArray m_buttonStrings;
|
||||||
ButtonObjArray m_objects;
|
ButtonObjArray m_objects;
|
||||||
|
|
||||||
bool m_IsRealized;
|
bool m_IsRealized;
|
||||||
|
|
||||||
wxSize m_padding;
|
wxSize m_padding;
|
||||||
int m_Indentation;
|
int m_Indentation;
|
||||||
int m_DefaultIdx; // index of the default option (gets specific color/font treatment)
|
int m_DefaultIdx; // index of the default option (gets specific color/font treatment)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template< int size >
|
template <int size>
|
||||||
pxRadioPanel( wxWindow* parent, const RadioPanelItem (&src)[size] )
|
pxRadioPanel(wxWindow *parent, const RadioPanelItem (&src)[size])
|
||||||
: wxPanelWithHelpers( parent, wxVERTICAL )
|
: wxPanelWithHelpers(parent, wxVERTICAL)
|
||||||
{
|
{
|
||||||
Init( src, size );
|
Init(src, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
pxRadioPanel( wxWindow* parent )
|
pxRadioPanel(wxWindow *parent)
|
||||||
: wxPanelWithHelpers( parent, wxVERTICAL )
|
: wxPanelWithHelpers(parent, wxVERTICAL)
|
||||||
{
|
{
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~pxRadioPanel() throw() {}
|
virtual ~pxRadioPanel() throw() {}
|
||||||
|
|
||||||
void Reset();
|
void Reset();
|
||||||
void Realize();
|
void Realize();
|
||||||
|
|
||||||
pxStaticText* GetSubText( int idx );
|
pxStaticText *GetSubText(int idx);
|
||||||
const pxStaticText* GetSubText( int idx ) const;
|
const pxStaticText *GetSubText(int idx) const;
|
||||||
pxRadioPanel& Append( const RadioPanelItem& entry );
|
pxRadioPanel &Append(const RadioPanelItem &entry);
|
||||||
|
|
||||||
pxRadioPanel& SetToolTip( int idx, const wxString& tip );
|
pxRadioPanel &SetToolTip(int idx, const wxString &tip);
|
||||||
pxRadioPanel& SetSelection( int idx );
|
pxRadioPanel &SetSelection(int idx);
|
||||||
pxRadioPanel& SetDefaultItem( int idx );
|
pxRadioPanel &SetDefaultItem(int idx);
|
||||||
pxRadioPanel& EnableItem( int idx, bool enable=true );
|
pxRadioPanel &EnableItem(int idx, bool enable = true);
|
||||||
|
|
||||||
const RadioPanelItem& Item(int idx) const;
|
const RadioPanelItem &Item(int idx) const;
|
||||||
RadioPanelItem& Item(int idx);
|
RadioPanelItem &Item(int idx);
|
||||||
|
|
||||||
int GetSelection() const;
|
int GetSelection() const;
|
||||||
wxWindowID GetSelectionId() const;
|
wxWindowID GetSelectionId() const;
|
||||||
bool IsSelected( int idx ) const;
|
bool IsSelected(int idx) const;
|
||||||
|
|
||||||
const RadioPanelItem& SelectedItem() const { return Item(GetSelection()); }
|
const RadioPanelItem &SelectedItem() const { return Item(GetSelection()); }
|
||||||
RadioPanelItem& SelectedItem() { return Item(GetSelection()); }
|
RadioPanelItem &SelectedItem() { return Item(GetSelection()); }
|
||||||
|
|
||||||
wxRadioButton* GetButton( int idx );
|
wxRadioButton *GetButton(int idx);
|
||||||
const wxRadioButton* GetButton( int idx ) const;
|
const wxRadioButton *GetButton(int idx) const;
|
||||||
|
|
||||||
int GetPaddingVert() const { return m_padding.GetHeight(); }
|
int GetPaddingVert() const { return m_padding.GetHeight(); }
|
||||||
int GetIndentation() const { return m_Indentation; }
|
int GetIndentation() const { return m_Indentation; }
|
||||||
|
|
||||||
pxRadioPanel& SetPaddingHoriz( int newpad )
|
pxRadioPanel &SetPaddingHoriz(int newpad)
|
||||||
{
|
{
|
||||||
m_padding.SetHeight( newpad );
|
m_padding.SetHeight(newpad);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
pxRadioPanel& SetIndentation( int newdent )
|
pxRadioPanel &SetIndentation(int newdent)
|
||||||
{
|
{
|
||||||
m_Indentation = newdent;
|
m_Indentation = newdent;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HasSubText( int idx ) const
|
bool HasSubText(int idx) const
|
||||||
{
|
{
|
||||||
return !m_buttonStrings[idx].SubText.IsEmpty();
|
return !m_buttonStrings[idx].SubText.IsEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
pxRadioPanel& Append( const wxString& label, const wxString& subtext=wxEmptyString, const wxString& tooltip=wxEmptyString )
|
pxRadioPanel &Append(const wxString &label, const wxString &subtext = wxEmptyString, const wxString &tooltip = wxEmptyString)
|
||||||
{
|
{
|
||||||
return Append( RadioPanelItem(label, subtext, tooltip) );
|
return Append(RadioPanelItem(label, subtext, tooltip));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void Init( const RadioPanelItem* srcArray=NULL, int arrsize=0 );
|
void Init(const RadioPanelItem *srcArray = NULL, int arrsize = 0);
|
||||||
void _setToolTipImmediate( int idx, const wxString &tip );
|
void _setToolTipImmediate(int idx, const wxString &tip);
|
||||||
void _RealizeDefaultOption();
|
void _RealizeDefaultOption();
|
||||||
};
|
};
|
||||||
|
|
|
@ -33,93 +33,92 @@
|
||||||
//
|
//
|
||||||
class pxStaticText : public wxControl
|
class pxStaticText : public wxControl
|
||||||
{
|
{
|
||||||
typedef wxControl _parent;
|
typedef wxControl _parent;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
wxString m_label;
|
wxString m_label;
|
||||||
wxString m_wrappedLabel;
|
wxString m_wrappedLabel;
|
||||||
|
|
||||||
wxAlignment m_align;
|
wxAlignment m_align;
|
||||||
bool m_autowrap;
|
bool m_autowrap;
|
||||||
int m_wrappedWidth;
|
int m_wrappedWidth;
|
||||||
int m_heightInLines;
|
int m_heightInLines;
|
||||||
|
|
||||||
int m_paddingPix_horiz;
|
int m_paddingPix_horiz;
|
||||||
int m_paddingPix_vert;
|
int m_paddingPix_vert;
|
||||||
float m_paddingPct_horiz;
|
float m_paddingPct_horiz;
|
||||||
float m_paddingPct_vert;
|
float m_paddingPct_vert;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
explicit pxStaticText( wxWindow* parent=NULL );
|
explicit pxStaticText(wxWindow *parent = NULL);
|
||||||
|
|
||||||
// wxWindow overloads!
|
// wxWindow overloads!
|
||||||
bool AcceptsFocus() const { return false; }
|
bool AcceptsFocus() const { return false; }
|
||||||
bool HasTransparentBackground() { return true; }
|
bool HasTransparentBackground() { return true; }
|
||||||
void DoSetSize(int x, int y, int w, int h, int sizeFlags = wxSIZE_AUTO);
|
void DoSetSize(int x, int y, int w, int h, int sizeFlags = wxSIZE_AUTO);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
pxStaticText( wxWindow* parent, const wxString& label, wxAlignment align=wxALIGN_CENTRE_HORIZONTAL );
|
pxStaticText(wxWindow *parent, const wxString &label, wxAlignment align = wxALIGN_CENTRE_HORIZONTAL);
|
||||||
pxStaticText( wxWindow* parent, int heightInLines, const wxString& label, wxAlignment align=wxALIGN_CENTRE_HORIZONTAL );
|
pxStaticText(wxWindow *parent, int heightInLines, const wxString &label, wxAlignment align = wxALIGN_CENTRE_HORIZONTAL);
|
||||||
virtual ~pxStaticText() throw() {}
|
virtual ~pxStaticText() throw() {}
|
||||||
|
|
||||||
wxFont GetFontOk() const;
|
wxFont GetFontOk() const;
|
||||||
bool Enable( bool enabled=true );
|
bool Enable(bool enabled = true);
|
||||||
|
|
||||||
virtual void SetLabel(const wxString& label);
|
virtual void SetLabel(const wxString &label);
|
||||||
virtual wxString GetLabel() const { return m_label; }
|
virtual wxString GetLabel() const { return m_label; }
|
||||||
|
|
||||||
pxStaticText& SetMinWidth( int width );
|
pxStaticText &SetMinWidth(int width);
|
||||||
pxStaticText& SetMinHeight( int height );
|
pxStaticText &SetMinHeight(int height);
|
||||||
|
|
||||||
pxStaticText& SetHeight( int lines );
|
pxStaticText &SetHeight(int lines);
|
||||||
pxStaticText& Align( wxAlignment align );
|
pxStaticText &Align(wxAlignment align);
|
||||||
pxStaticText& Bold();
|
pxStaticText &Bold();
|
||||||
pxStaticText& WrapAt( int width );
|
pxStaticText &WrapAt(int width);
|
||||||
|
|
||||||
pxStaticText& Unwrapped();
|
pxStaticText &Unwrapped();
|
||||||
|
|
||||||
pxStaticText& PaddingPixH( int pixels );
|
pxStaticText &PaddingPixH(int pixels);
|
||||||
pxStaticText& PaddingPixV( int pixels );
|
pxStaticText &PaddingPixV(int pixels);
|
||||||
|
|
||||||
pxStaticText& PaddingPctH( float pct );
|
pxStaticText &PaddingPctH(float pct);
|
||||||
pxStaticText& PaddingPctV( float pct );
|
pxStaticText &PaddingPctV(float pct);
|
||||||
//pxStaticText& DoBestGuessHeight();
|
//pxStaticText& DoBestGuessHeight();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void SetPaddingDefaults();
|
void SetPaddingDefaults();
|
||||||
void Init( const wxString& label );
|
void Init(const wxString &label);
|
||||||
|
|
||||||
wxSize GetBestWrappedSize( const wxClientDC& dc ) const;
|
wxSize GetBestWrappedSize(const wxClientDC &dc) const;
|
||||||
wxSize DoGetBestSize() const;
|
wxSize DoGetBestSize() const;
|
||||||
|
|
||||||
int calcPaddingWidth( int newWidth ) const;
|
int calcPaddingWidth(int newWidth) const;
|
||||||
int calcPaddingHeight( int newHeight ) const;
|
int calcPaddingHeight(int newHeight) const;
|
||||||
|
|
||||||
void paintEvent(wxPaintEvent& evt);
|
void paintEvent(wxPaintEvent &evt);
|
||||||
|
|
||||||
void UpdateWrapping( bool textChanged );
|
void UpdateWrapping(bool textChanged);
|
||||||
bool _updateWrapping( bool textChanged );
|
bool _updateWrapping(bool textChanged);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class pxStaticHeading : public pxStaticText
|
class pxStaticHeading : public pxStaticText
|
||||||
{
|
{
|
||||||
typedef pxStaticText _parent;
|
typedef pxStaticText _parent;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
pxStaticHeading( wxWindow* parent=NULL, const wxString& label=wxEmptyString );
|
pxStaticHeading(wxWindow *parent = NULL, const wxString &label = wxEmptyString);
|
||||||
pxStaticHeading( wxWindow* parent, int heightInLines, const wxString& label=wxEmptyString );
|
pxStaticHeading(wxWindow *parent, int heightInLines, const wxString &label = wxEmptyString);
|
||||||
virtual ~pxStaticHeading() throw() {}
|
virtual ~pxStaticHeading() throw() {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void SetPaddingDefaults();
|
void SetPaddingDefaults();
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void operator+=( wxSizer& target, pxStaticText& src );
|
extern void operator+=(wxSizer &target, pxStaticText &src);
|
||||||
|
|
||||||
template<>
|
template <>
|
||||||
inline void operator+=( wxSizer& target, const pxWindowAndFlags<pxStaticText>& src )
|
inline void operator+=(wxSizer &target, const pxWindowAndFlags<pxStaticText> &src)
|
||||||
{
|
{
|
||||||
target.Add( src.window, src.flags );
|
target.Add(src.window, src.flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,28 +23,28 @@
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
class pxStreamBase
|
class pxStreamBase
|
||||||
{
|
{
|
||||||
DeclareNoncopyableObject(pxStreamBase);
|
DeclareNoncopyableObject(pxStreamBase);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Filename of the stream, provided by the creator/caller. This is typically used *only*
|
// Filename of the stream, provided by the creator/caller. This is typically used *only*
|
||||||
// for generating comprehensive error messages when an error occurs (the stream name is
|
// for generating comprehensive error messages when an error occurs (the stream name is
|
||||||
// passed to the exception handlers).
|
// passed to the exception handlers).
|
||||||
wxString m_filename;
|
wxString m_filename;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
pxStreamBase(const wxString& filename);
|
pxStreamBase(const wxString &filename);
|
||||||
virtual ~pxStreamBase() throw() {}
|
virtual ~pxStreamBase() throw() {}
|
||||||
|
|
||||||
// Implementing classes should return the base wxStream object (usually either a wxInputStream
|
// Implementing classes should return the base wxStream object (usually either a wxInputStream
|
||||||
// or wxOputStream derivative).
|
// or wxOputStream derivative).
|
||||||
virtual wxStreamBase* GetWxStreamBase() const=0;
|
virtual wxStreamBase *GetWxStreamBase() const = 0;
|
||||||
virtual void Close()=0;
|
virtual void Close() = 0;
|
||||||
virtual wxFileOffset Tell() const=0;
|
virtual wxFileOffset Tell() const = 0;
|
||||||
virtual wxFileOffset Seek( wxFileOffset ofs, wxSeekMode mode = wxFromStart )=0;
|
virtual wxFileOffset Seek(wxFileOffset ofs, wxSeekMode mode = wxFromStart) = 0;
|
||||||
|
|
||||||
virtual wxFileOffset Length() const;
|
virtual wxFileOffset Length() const;
|
||||||
bool IsOk() const;
|
bool IsOk() const;
|
||||||
wxString GetStreamName() const { return m_filename; }
|
wxString GetStreamName() const { return m_filename; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -53,33 +53,33 @@ public:
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
class pxOutputStream : public pxStreamBase
|
class pxOutputStream : public pxStreamBase
|
||||||
{
|
{
|
||||||
DeclareNoncopyableObject(pxOutputStream);
|
DeclareNoncopyableObject(pxOutputStream);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::unique_ptr<wxOutputStream> m_stream_out;
|
std::unique_ptr<wxOutputStream> m_stream_out;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
pxOutputStream(const wxString& filename, std::unique_ptr<wxOutputStream>& output);
|
pxOutputStream(const wxString &filename, std::unique_ptr<wxOutputStream> &output);
|
||||||
pxOutputStream(const wxString& filename, wxOutputStream* output);
|
pxOutputStream(const wxString &filename, wxOutputStream *output);
|
||||||
|
|
||||||
virtual ~pxOutputStream() throw() {}
|
virtual ~pxOutputStream() throw() {}
|
||||||
virtual void Write( const void* data, size_t size );
|
virtual void Write(const void *data, size_t size);
|
||||||
|
|
||||||
void SetStream( const wxString& filename, std::unique_ptr<wxOutputStream>& stream );
|
|
||||||
void SetStream( const wxString& filename, wxOutputStream* stream );
|
|
||||||
|
|
||||||
void Close() { m_stream_out = nullptr; }
|
void SetStream(const wxString &filename, std::unique_ptr<wxOutputStream> &stream);
|
||||||
|
void SetStream(const wxString &filename, wxOutputStream *stream);
|
||||||
|
|
||||||
virtual wxStreamBase* GetWxStreamBase() const;
|
void Close() { m_stream_out = nullptr; }
|
||||||
|
|
||||||
template< typename T >
|
virtual wxStreamBase *GetWxStreamBase() const;
|
||||||
void Write( const T& data )
|
|
||||||
{
|
|
||||||
Write( &data, sizeof(data) );
|
|
||||||
}
|
|
||||||
|
|
||||||
wxFileOffset Tell() const;
|
template <typename T>
|
||||||
wxFileOffset Seek( wxFileOffset ofs, wxSeekMode mode = wxFromStart );
|
void Write(const T &data)
|
||||||
|
{
|
||||||
|
Write(&data, sizeof(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
wxFileOffset Tell() const;
|
||||||
|
wxFileOffset Seek(wxFileOffset ofs, wxSeekMode mode = wxFromStart);
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -87,31 +87,31 @@ public:
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
class pxInputStream : public pxStreamBase
|
class pxInputStream : public pxStreamBase
|
||||||
{
|
{
|
||||||
DeclareNoncopyableObject(pxInputStream);
|
DeclareNoncopyableObject(pxInputStream);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::unique_ptr<wxInputStream> m_stream_in;
|
std::unique_ptr<wxInputStream> m_stream_in;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
pxInputStream(const wxString& filename, std::unique_ptr<wxInputStream>& input);
|
pxInputStream(const wxString &filename, std::unique_ptr<wxInputStream> &input);
|
||||||
pxInputStream(const wxString& filename, wxInputStream* input);
|
pxInputStream(const wxString &filename, wxInputStream *input);
|
||||||
|
|
||||||
virtual ~pxInputStream() throw() {}
|
virtual ~pxInputStream() throw() {}
|
||||||
virtual void Read( void* dest, size_t size );
|
virtual void Read(void *dest, size_t size);
|
||||||
|
|
||||||
void SetStream( const wxString& filename, std::unique_ptr<wxInputStream>& stream );
|
|
||||||
void SetStream( const wxString& filename, wxInputStream* stream );
|
|
||||||
|
|
||||||
void Close() { m_stream_in = nullptr; }
|
void SetStream(const wxString &filename, std::unique_ptr<wxInputStream> &stream);
|
||||||
|
void SetStream(const wxString &filename, wxInputStream *stream);
|
||||||
|
|
||||||
virtual wxStreamBase* GetWxStreamBase() const;
|
void Close() { m_stream_in = nullptr; }
|
||||||
|
|
||||||
template< typename T >
|
virtual wxStreamBase *GetWxStreamBase() const;
|
||||||
void Read( T& dest )
|
|
||||||
{
|
|
||||||
Read( &dest, sizeof(dest) );
|
|
||||||
}
|
|
||||||
|
|
||||||
wxFileOffset Tell() const;
|
template <typename T>
|
||||||
wxFileOffset Seek( wxFileOffset ofs, wxSeekMode mode = wxFromStart );
|
void Read(T &dest)
|
||||||
|
{
|
||||||
|
Read(&dest, sizeof(dest));
|
||||||
|
}
|
||||||
|
|
||||||
|
wxFileOffset Tell() const;
|
||||||
|
wxFileOffset Seek(wxFileOffset ofs, wxSeekMode mode = wxFromStart);
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,30 +16,30 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
# pragma warning(disable:4063) // case '1' is not a valid value for switch()
|
#pragma warning(disable : 4063) // case '1' is not a valid value for switch()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// These functions are meant for memset operations of constant length only.
|
// These functions are meant for memset operations of constant length only.
|
||||||
// For dynamic length clears, use the C-compiler provided memset instead.
|
// For dynamic length clears, use the C-compiler provided memset instead.
|
||||||
|
|
||||||
template< u8 data, size_t bytes >
|
template <u8 data, size_t bytes>
|
||||||
static __fi void memset_8( void *dest )
|
static __fi void memset_8(void *dest)
|
||||||
{
|
{
|
||||||
memset(dest, data, bytes);
|
memset(dest, data, bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method can clear any object-like entity -- which is anything that is not a pointer.
|
// This method can clear any object-like entity -- which is anything that is not a pointer.
|
||||||
// Structures, static arrays, etc. No need to include sizeof() crap, this does it automatically
|
// Structures, static arrays, etc. No need to include sizeof() crap, this does it automatically
|
||||||
// for you!
|
// for you!
|
||||||
template< typename T >
|
template <typename T>
|
||||||
static __fi void memzero( T& object )
|
static __fi void memzero(T &object)
|
||||||
{
|
{
|
||||||
memset(&object, 0, sizeof(T));
|
memset(&object, 0, sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method clears an object with the given 8 bit value.
|
// This method clears an object with the given 8 bit value.
|
||||||
template< u8 data, typename T >
|
template <u8 data, typename T>
|
||||||
static __fi void memset8( T& object )
|
static __fi void memset8(T &object)
|
||||||
{
|
{
|
||||||
memset_8<data, sizeof(T)>( &object );
|
memset_8<data, sizeof(T)>(&object);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,10 +32,10 @@ class pxSynchronousCommandEvent;
|
||||||
|
|
||||||
class ConsoleLogSource_App : public ConsoleLogSource
|
class ConsoleLogSource_App : public ConsoleLogSource
|
||||||
{
|
{
|
||||||
typedef ConsoleLogSource _parent;
|
typedef ConsoleLogSource _parent;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ConsoleLogSource_App();
|
ConsoleLogSource_App();
|
||||||
};
|
};
|
||||||
|
|
||||||
extern ConsoleLogSource_App pxConLog_App;
|
extern ConsoleLogSource_App pxConLog_App;
|
||||||
|
@ -49,96 +49,97 @@ extern ConsoleLogSource_App pxConLog_App;
|
||||||
class ModalButtonPanel : public wxPanelWithHelpers
|
class ModalButtonPanel : public wxPanelWithHelpers
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ModalButtonPanel( wxWindow* window, const MsgButtons& buttons );
|
ModalButtonPanel(wxWindow *window, const MsgButtons &buttons);
|
||||||
virtual ~ModalButtonPanel() throw() { }
|
virtual ~ModalButtonPanel() throw() {}
|
||||||
|
|
||||||
virtual void AddActionButton( wxWindowID id );
|
virtual void AddActionButton(wxWindowID id);
|
||||||
virtual void AddCustomButton( wxWindowID id, const wxString& label );
|
virtual void AddCustomButton(wxWindowID id, const wxString &label);
|
||||||
|
|
||||||
virtual void OnActionButtonClicked( wxCommandEvent& evt );
|
virtual void OnActionButtonClicked(wxCommandEvent &evt);
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::list< wxEvent* > wxEventList;
|
typedef std::list<wxEvent *> wxEventList;
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// wxAppWithHelpers
|
// wxAppWithHelpers
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
class wxAppWithHelpers : public wxApp
|
class wxAppWithHelpers : public wxApp
|
||||||
{
|
{
|
||||||
typedef wxApp _parent;
|
typedef wxApp _parent;
|
||||||
|
|
||||||
DECLARE_DYNAMIC_CLASS(wxAppWithHelpers)
|
DECLARE_DYNAMIC_CLASS(wxAppWithHelpers)
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
wxEventList m_IdleEventQueue;
|
wxEventList m_IdleEventQueue;
|
||||||
Threading::MutexRecursive m_IdleEventMutex;
|
Threading::MutexRecursive m_IdleEventMutex;
|
||||||
wxTimer m_IdleEventTimer;
|
wxTimer m_IdleEventTimer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
wxAppWithHelpers();
|
wxAppWithHelpers();
|
||||||
virtual ~wxAppWithHelpers() {}
|
virtual ~wxAppWithHelpers() {}
|
||||||
|
|
||||||
wxAppTraits* CreateTraits();
|
wxAppTraits *CreateTraits();
|
||||||
|
|
||||||
void CleanUp();
|
void CleanUp();
|
||||||
|
|
||||||
void DeleteObject( BaseDeletableObject& obj );
|
|
||||||
void DeleteObject( BaseDeletableObject* obj )
|
|
||||||
{
|
|
||||||
if( obj == NULL ) return;
|
|
||||||
DeleteObject( *obj );
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeleteThread( Threading::pxThread& obj );
|
void DeleteObject(BaseDeletableObject &obj);
|
||||||
void DeleteThread( Threading::pxThread* obj )
|
void DeleteObject(BaseDeletableObject *obj)
|
||||||
{
|
{
|
||||||
if( obj == NULL ) return;
|
if (obj == NULL)
|
||||||
DeleteThread( *obj );
|
return;
|
||||||
}
|
DeleteObject(*obj);
|
||||||
|
}
|
||||||
|
|
||||||
void PostCommand( void* clientData, int evtType, int intParam=0, long longParam=0, const wxString& stringParam=wxEmptyString );
|
void DeleteThread(Threading::pxThread &obj);
|
||||||
void PostCommand( int evtType, int intParam=0, long longParam=0, const wxString& stringParam=wxEmptyString );
|
void DeleteThread(Threading::pxThread *obj)
|
||||||
void PostMethod( FnType_Void* method );
|
{
|
||||||
void PostIdleMethod( FnType_Void* method );
|
if (obj == NULL)
|
||||||
void ProcessMethod( FnType_Void* method );
|
return;
|
||||||
|
DeleteThread(*obj);
|
||||||
|
}
|
||||||
|
|
||||||
bool Rpc_TryInvoke( FnType_Void* method );
|
void PostCommand(void *clientData, int evtType, int intParam = 0, long longParam = 0, const wxString &stringParam = wxEmptyString);
|
||||||
bool Rpc_TryInvokeAsync( FnType_Void* method );
|
void PostCommand(int evtType, int intParam = 0, long longParam = 0, const wxString &stringParam = wxEmptyString);
|
||||||
|
void PostMethod(FnType_Void *method);
|
||||||
|
void PostIdleMethod(FnType_Void *method);
|
||||||
|
void ProcessMethod(FnType_Void *method);
|
||||||
|
|
||||||
sptr ProcessCommand( void* clientData, int evtType, int intParam=0, long longParam=0, const wxString& stringParam=wxEmptyString );
|
bool Rpc_TryInvoke(FnType_Void *method);
|
||||||
sptr ProcessCommand( int evtType, int intParam=0, long longParam=0, const wxString& stringParam=wxEmptyString );
|
bool Rpc_TryInvokeAsync(FnType_Void *method);
|
||||||
|
|
||||||
void ProcessAction( pxActionEvent& evt );
|
sptr ProcessCommand(void *clientData, int evtType, int intParam = 0, long longParam = 0, const wxString &stringParam = wxEmptyString);
|
||||||
void PostAction( const pxActionEvent& evt );
|
sptr ProcessCommand(int evtType, int intParam = 0, long longParam = 0, const wxString &stringParam = wxEmptyString);
|
||||||
|
|
||||||
void Ping();
|
void ProcessAction(pxActionEvent &evt);
|
||||||
bool OnInit();
|
void PostAction(const pxActionEvent &evt);
|
||||||
//int OnExit();
|
|
||||||
|
|
||||||
void AddIdleEvent( const wxEvent& evt );
|
void Ping();
|
||||||
|
bool OnInit();
|
||||||
|
//int OnExit();
|
||||||
|
|
||||||
void PostEvent( const wxEvent& evt );
|
void AddIdleEvent(const wxEvent &evt);
|
||||||
bool ProcessEvent( wxEvent& evt );
|
|
||||||
bool ProcessEvent( wxEvent* evt );
|
void PostEvent(const wxEvent &evt);
|
||||||
|
bool ProcessEvent(wxEvent &evt);
|
||||||
bool ProcessEvent( pxActionEvent& evt );
|
bool ProcessEvent(wxEvent *evt);
|
||||||
bool ProcessEvent( pxActionEvent* evt );
|
|
||||||
|
bool ProcessEvent(pxActionEvent &evt);
|
||||||
|
bool ProcessEvent(pxActionEvent *evt);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void IdleEventDispatcher( const wxChar* action=wxEmptyString );
|
void IdleEventDispatcher(const wxChar *action = wxEmptyString);
|
||||||
|
|
||||||
void OnIdleEvent( wxIdleEvent& evt );
|
|
||||||
void OnStartIdleEventTimer( wxCommandEvent& evt );
|
|
||||||
void OnIdleEventTimeout( wxTimerEvent& evt );
|
|
||||||
void OnDeleteObject( wxCommandEvent& evt );
|
|
||||||
void OnDeleteThread( wxCommandEvent& evt );
|
|
||||||
void OnSynchronousCommand( pxSynchronousCommandEvent& evt );
|
|
||||||
void OnInvokeAction( pxActionEvent& evt );
|
|
||||||
|
|
||||||
|
void OnIdleEvent(wxIdleEvent &evt);
|
||||||
|
void OnStartIdleEventTimer(wxCommandEvent &evt);
|
||||||
|
void OnIdleEventTimeout(wxTimerEvent &evt);
|
||||||
|
void OnDeleteObject(wxCommandEvent &evt);
|
||||||
|
void OnDeleteThread(wxCommandEvent &evt);
|
||||||
|
void OnSynchronousCommand(pxSynchronousCommandEvent &evt);
|
||||||
|
void OnInvokeAction(pxActionEvent &evt);
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace Msgbox
|
namespace Msgbox
|
||||||
{
|
{
|
||||||
extern int ShowModal( BaseMessageBoxEvent& evt );
|
extern int ShowModal(BaseMessageBoxEvent &evt);
|
||||||
extern int ShowModal( const wxString& title, const wxString& content, const MsgButtons& buttons );
|
extern int ShowModal(const wxString &title, const wxString &content, const MsgButtons &buttons);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,11 +26,11 @@
|
||||||
// which require wxCore, see wxGuiTools.h
|
// which require wxCore, see wxGuiTools.h
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
extern void pxExplore( const wxString& path );
|
extern void pxExplore(const wxString &path);
|
||||||
extern void pxExplore( const char *path );
|
extern void pxExplore(const char *path);
|
||||||
|
|
||||||
extern void pxLaunch( const wxString& path );
|
extern void pxLaunch(const wxString &path);
|
||||||
extern void pxLaunch( const char *path );
|
extern void pxLaunch(const char *path);
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// wxDoNotLogInThisScope
|
// wxDoNotLogInThisScope
|
||||||
|
@ -44,29 +44,28 @@ extern void pxLaunch( const char *path );
|
||||||
//
|
//
|
||||||
class wxDoNotLogInThisScope
|
class wxDoNotLogInThisScope
|
||||||
{
|
{
|
||||||
DeclareNoncopyableObject(wxDoNotLogInThisScope);
|
DeclareNoncopyableObject(wxDoNotLogInThisScope);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool m_prev;
|
bool m_prev;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
wxDoNotLogInThisScope()
|
wxDoNotLogInThisScope()
|
||||||
{
|
{
|
||||||
m_prev = wxLog::EnableLogging( false );
|
m_prev = wxLog::EnableLogging(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~wxDoNotLogInThisScope() throw()
|
virtual ~wxDoNotLogInThisScope() throw()
|
||||||
{
|
{
|
||||||
wxLog::EnableLogging( m_prev );
|
wxLog::EnableLogging(m_prev);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
extern wxString pxReadLine( wxInputStream& input );
|
extern wxString pxReadLine(wxInputStream &input);
|
||||||
extern void pxReadLine( wxInputStream& input, wxString& dest );
|
extern void pxReadLine(wxInputStream &input, wxString &dest);
|
||||||
extern void pxReadLine( wxInputStream& input, wxString& dest, std::string& intermed );
|
extern void pxReadLine(wxInputStream &input, wxString &dest, std::string &intermed);
|
||||||
extern bool pxReadLine( wxInputStream& input, std::string& dest );
|
extern bool pxReadLine(wxInputStream &input, std::string &dest);
|
||||||
extern void pxWriteLine( wxOutputStream& output );
|
extern void pxWriteLine(wxOutputStream &output);
|
||||||
extern void pxWriteLine( wxOutputStream& output, const wxString& text );
|
extern void pxWriteLine(wxOutputStream &output, const wxString &text);
|
||||||
extern void pxWriteMultiline( wxOutputStream& output, const wxString& src );
|
extern void pxWriteMultiline(wxOutputStream &output, const wxString &src);
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -35,101 +35,124 @@
|
||||||
|
|
||||||
// Basic functions.
|
// Basic functions.
|
||||||
|
|
||||||
EXPORT_C_(s32) CDVDinit();
|
EXPORT_C_(s32)
|
||||||
EXPORT_C_(s32) CDVDopen(void *pDisplay, const char* pTitleFilename);
|
CDVDinit();
|
||||||
EXPORT_C_(void) CDVDclose();
|
EXPORT_C_(s32)
|
||||||
EXPORT_C_(void) CDVDshutdown();
|
CDVDopen(void *pDisplay, const char *pTitleFilename);
|
||||||
EXPORT_C_(s32) CDVDreadTrack(u32 lsn, int mode);
|
EXPORT_C_(void)
|
||||||
|
CDVDclose();
|
||||||
|
EXPORT_C_(void)
|
||||||
|
CDVDshutdown();
|
||||||
|
EXPORT_C_(s32)
|
||||||
|
CDVDreadTrack(u32 lsn, int mode);
|
||||||
|
|
||||||
// return can be NULL (for async modes)
|
// return can be NULL (for async modes)
|
||||||
EXPORT_C_(u8*) CDVDgetBuffer();
|
EXPORT_C_(u8 *)
|
||||||
|
CDVDgetBuffer();
|
||||||
|
|
||||||
EXPORT_C_(s32) CDVDreadSubQ(u32 lsn, cdvdSubQ* subq);//read subq from disc (only cds have subq data)
|
EXPORT_C_(s32)
|
||||||
EXPORT_C_(s32) CDVDgetTN(cdvdTN *Buffer); //disk information
|
CDVDreadSubQ(u32 lsn, cdvdSubQ *subq); //read subq from disc (only cds have subq data)
|
||||||
EXPORT_C_(s32) CDVDgetTD(u8 Track, cdvdTD *Buffer); //track info: min,sec,frame,type
|
EXPORT_C_(s32)
|
||||||
EXPORT_C_(s32) CDVDgetTOC(void* toc); //gets ps2 style toc from disc
|
CDVDgetTN(cdvdTN *Buffer); //disk information
|
||||||
EXPORT_C_(s32) CDVDgetDiskType(); //CDVD_TYPE_xxxx
|
EXPORT_C_(s32)
|
||||||
EXPORT_C_(s32) CDVDgetTrayStatus(); //CDVD_TRAY_xxxx
|
CDVDgetTD(u8 Track, cdvdTD *Buffer); //track info: min,sec,frame,type
|
||||||
EXPORT_C_(s32) CDVDctrlTrayOpen(); //open disc tray
|
EXPORT_C_(s32)
|
||||||
EXPORT_C_(s32) CDVDctrlTrayClose(); //close disc tray
|
CDVDgetTOC(void *toc); //gets ps2 style toc from disc
|
||||||
|
EXPORT_C_(s32)
|
||||||
|
CDVDgetDiskType(); //CDVD_TYPE_xxxx
|
||||||
|
EXPORT_C_(s32)
|
||||||
|
CDVDgetTrayStatus(); //CDVD_TRAY_xxxx
|
||||||
|
EXPORT_C_(s32)
|
||||||
|
CDVDctrlTrayOpen(); //open disc tray
|
||||||
|
EXPORT_C_(s32)
|
||||||
|
CDVDctrlTrayClose(); //close disc tray
|
||||||
|
|
||||||
// Extended functions
|
// Extended functions
|
||||||
|
|
||||||
EXPORT_C_(void) CDVDkeyEvent(keyEvent *ev);
|
EXPORT_C_(void)
|
||||||
EXPORT_C_(void) CDVDconfigure();
|
CDVDkeyEvent(keyEvent *ev);
|
||||||
EXPORT_C_(s32) CDVDfreeze(u8 mode, freezeData *data);
|
EXPORT_C_(void)
|
||||||
EXPORT_C_(void) CDVDabout();
|
CDVDconfigure();
|
||||||
EXPORT_C_(s32) CDVDtest();
|
EXPORT_C_(s32)
|
||||||
EXPORT_C_(void) CDVDnewDiskCB(void (*callback)());
|
CDVDfreeze(u8 mode, freezeData *data);
|
||||||
|
EXPORT_C_(void)
|
||||||
|
CDVDabout();
|
||||||
|
EXPORT_C_(s32)
|
||||||
|
CDVDtest();
|
||||||
|
EXPORT_C_(void)
|
||||||
|
CDVDnewDiskCB(void (*callback)());
|
||||||
|
|
||||||
typedef struct _cdvdSubQ {
|
typedef struct _cdvdSubQ
|
||||||
u8 ctrl:4; // control and mode bits
|
{
|
||||||
u8 mode:4; // control and mode bits
|
u8 ctrl : 4; // control and mode bits
|
||||||
u8 trackNum; // current track number (1 to 99)
|
u8 mode : 4; // control and mode bits
|
||||||
u8 trackIndex; // current index within track (0 to 99)
|
u8 trackNum; // current track number (1 to 99)
|
||||||
u8 trackM; // current minute location on the disc (BCD encoded)
|
u8 trackIndex; // current index within track (0 to 99)
|
||||||
u8 trackS; // current sector location on the disc (BCD encoded)
|
u8 trackM; // current minute location on the disc (BCD encoded)
|
||||||
u8 trackF; // current frame location on the disc (BCD encoded)
|
u8 trackS; // current sector location on the disc (BCD encoded)
|
||||||
u8 pad; // unused
|
u8 trackF; // current frame location on the disc (BCD encoded)
|
||||||
u8 discM; // current minute offset from first track (BCD encoded)
|
u8 pad; // unused
|
||||||
u8 discS; // current sector offset from first track (BCD encoded)
|
u8 discM; // current minute offset from first track (BCD encoded)
|
||||||
u8 discF; // current frame offset from first track (BCD encoded)
|
u8 discS; // current sector offset from first track (BCD encoded)
|
||||||
|
u8 discF; // current frame offset from first track (BCD encoded)
|
||||||
} cdvdSubQ;
|
} cdvdSubQ;
|
||||||
|
|
||||||
typedef struct _cdvdTD { // NOT bcd coded
|
typedef struct _cdvdTD
|
||||||
u32 lsn;
|
{ // NOT bcd coded
|
||||||
u8 type;
|
u32 lsn;
|
||||||
|
u8 type;
|
||||||
} cdvdTD;
|
} cdvdTD;
|
||||||
|
|
||||||
typedef struct _cdvdTN {
|
typedef struct _cdvdTN
|
||||||
u8 strack; //number of the first track (usually 1)
|
{
|
||||||
u8 etrack; //number of the last track
|
u8 strack; //number of the first track (usually 1)
|
||||||
|
u8 etrack; //number of the last track
|
||||||
} cdvdTN;
|
} cdvdTN;
|
||||||
|
|
||||||
// CDVDreadTrack mode values:
|
// CDVDreadTrack mode values:
|
||||||
enum {
|
enum {
|
||||||
CDVD_MODE_2352 0, // full 2352 bytes
|
CDVD_MODE_2352 0, // full 2352 bytes
|
||||||
CDVD_MODE_2340 1, // skip sync (12) bytes
|
CDVD_MODE_2340 1, // skip sync (12) bytes
|
||||||
CDVD_MODE_2328 2, // skip sync+head+sub (24) bytes
|
CDVD_MODE_2328 2, // skip sync+head+sub (24) bytes
|
||||||
CDVD_MODE_2048 3, // skip sync+head+sub (24) bytes
|
CDVD_MODE_2048 3, // skip sync+head+sub (24) bytes
|
||||||
CDVD_MODE_2368 4 // full 2352 bytes + 16 subq
|
CDVD_MODE_2368 4 // full 2352 bytes + 16 subq
|
||||||
} TrackModes
|
} TrackModes
|
||||||
|
|
||||||
// CDVDgetDiskType returns:
|
// CDVDgetDiskType returns:
|
||||||
enum {
|
enum {
|
||||||
CDVD_TYPE_ILLEGAL = 0xff, // Illegal Disc
|
CDVD_TYPE_ILLEGAL = 0xff, // Illegal Disc
|
||||||
CDVD_TYPE_DVDV = 0xfe, // DVD Video
|
CDVD_TYPE_DVDV = 0xfe, // DVD Video
|
||||||
CDVD_TYPE_CDDA = 0xfd, // Audio CD
|
CDVD_TYPE_CDDA = 0xfd, // Audio CD
|
||||||
CDVD_TYPE_PS2DVD = 0x14, // PS2 DVD
|
CDVD_TYPE_PS2DVD = 0x14, // PS2 DVD
|
||||||
CDVD_TYPE_PS2CDDA = 0x13, // PS2 CD (with audio)
|
CDVD_TYPE_PS2CDDA = 0x13, // PS2 CD (with audio)
|
||||||
CDVD_TYPE_PS2CD = 0x12, // PS2 CD
|
CDVD_TYPE_PS2CD = 0x12, // PS2 CD
|
||||||
CDVD_TYPE_PSCDDA = 0x11, // PS CD (with audio)
|
CDVD_TYPE_PSCDDA = 0x11, // PS CD (with audio)
|
||||||
CDVD_TYPE_PSCD = 0x10, // PS CD
|
CDVD_TYPE_PSCD = 0x10, // PS CD
|
||||||
CDVD_TYPE_UNKNOWN = 0x05, // Unknown
|
CDVD_TYPE_UNKNOWN = 0x05, // Unknown
|
||||||
CDVD_TYPE_DETCTDVDD = 0x04, // Detecting Dvd Dual Sided
|
CDVD_TYPE_DETCTDVDD = 0x04, // Detecting Dvd Dual Sided
|
||||||
CDVD_TYPE_DETCTDVDS = 0x03, // Detecting Dvd Single Sided
|
CDVD_TYPE_DETCTDVDS = 0x03, // Detecting Dvd Single Sided
|
||||||
CDVD_TYPE_DETCTCD = 0x02, // Detecting Cd
|
CDVD_TYPE_DETCTCD = 0x02, // Detecting Cd
|
||||||
CDVD_TYPE_DETCT = 0x01, // Detecting
|
CDVD_TYPE_DETCT = 0x01, // Detecting
|
||||||
CDVD_TYPE_NODISC = 0x00 // No Disc
|
CDVD_TYPE_NODISC = 0x00 // No Disc
|
||||||
} DiskType;
|
} DiskType;
|
||||||
|
|
||||||
// CDVDgetTrayStatus returns:
|
// CDVDgetTrayStatus returns:
|
||||||
enum {
|
enum {
|
||||||
CDVD_TRAY_CLOSE = 0x00,
|
CDVD_TRAY_CLOSE = 0x00,
|
||||||
CDVD_TRAY_OPEN = 0x01
|
CDVD_TRAY_OPEN = 0x01
|
||||||
} TrayStatus;
|
} TrayStatus;
|
||||||
|
|
||||||
// cdvdTD.type (track types for cds)
|
// cdvdTD.type (track types for cds)
|
||||||
enum {
|
enum {
|
||||||
CDVD_AUDIO_TRACK = 0x01,
|
CDVD_AUDIO_TRACK = 0x01,
|
||||||
CDVD_MODE1_TRACK = 0x41,
|
CDVD_MODE1_TRACK = 0x41,
|
||||||
CDVD_MODE2_TRACK = 0x61
|
CDVD_MODE2_TRACK = 0x61
|
||||||
} CDVDTDType;
|
} CDVDTDType;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
CDVD_AUDIO_MASK = 0x00,
|
CDVD_AUDIO_MASK = 0x00,
|
||||||
CDVD_DATA_MASK = 0x40
|
CDVD_DATA_MASK = 0x40
|
||||||
// CDROM_DATA_TRACK 0x04 //do not enable this! (from linux kernel)
|
// CDROM_DATA_TRACK 0x04 //do not enable this! (from linux kernel)
|
||||||
} CDVD_Masks;
|
} CDVD_Masks;
|
||||||
|
|
||||||
#endif // __CDVDAPI_H__
|
#endif // __CDVDAPI_H__
|
|
@ -32,37 +32,56 @@
|
||||||
#include "Pcsx2Api.h"
|
#include "Pcsx2Api.h"
|
||||||
|
|
||||||
typedef void (*DEV9callback)(int cycles);
|
typedef void (*DEV9callback)(int cycles);
|
||||||
typedef int (*DEV9handler)(void);
|
typedef int (*DEV9handler)(void);
|
||||||
|
|
||||||
// Basic functions.
|
// Basic functions.
|
||||||
// NOTE: The read/write functions CANNOT use XMM/MMX regs
|
// NOTE: The read/write functions CANNOT use XMM/MMX regs
|
||||||
// If you want to use them, need to save and restore current ones
|
// If you want to use them, need to save and restore current ones
|
||||||
EXPORT_C_(s32) DEV9init();
|
EXPORT_C_(s32)
|
||||||
|
DEV9init();
|
||||||
|
|
||||||
// pDisplay normally is passed a handle to the GS plugins window.
|
// pDisplay normally is passed a handle to the GS plugins window.
|
||||||
EXPORT_C_(s32) DEV9open(void *pDisplay);
|
EXPORT_C_(s32)
|
||||||
EXPORT_C_(void) DEV9close();
|
DEV9open(void *pDisplay);
|
||||||
EXPORT_C_(void) DEV9shutdown();
|
EXPORT_C_(void)
|
||||||
EXPORT_C_(u8) DEV9read8(u32 addr);
|
DEV9close();
|
||||||
EXPORT_C_(u16) DEV9read16(u32 addr);
|
EXPORT_C_(void)
|
||||||
EXPORT_C_(u32) DEV9read32(u32 addr);
|
DEV9shutdown();
|
||||||
EXPORT_C_(void) DEV9write8(u32 addr, u8 value);
|
EXPORT_C_(u8)
|
||||||
EXPORT_C_(void) DEV9write16(u32 addr, u16 value);
|
DEV9read8(u32 addr);
|
||||||
EXPORT_C_(void) DEV9write32(u32 addr, u32 value);
|
EXPORT_C_(u16)
|
||||||
EXPORT_C_(void) DEV9readDMA8Mem(u32 *pMem, int size);
|
DEV9read16(u32 addr);
|
||||||
EXPORT_C_(void) DEV9writeDMA8Mem(u32 *pMem, int size);
|
EXPORT_C_(u32)
|
||||||
|
DEV9read32(u32 addr);
|
||||||
|
EXPORT_C_(void)
|
||||||
|
DEV9write8(u32 addr, u8 value);
|
||||||
|
EXPORT_C_(void)
|
||||||
|
DEV9write16(u32 addr, u16 value);
|
||||||
|
EXPORT_C_(void)
|
||||||
|
DEV9write32(u32 addr, u32 value);
|
||||||
|
EXPORT_C_(void)
|
||||||
|
DEV9readDMA8Mem(u32 *pMem, int size);
|
||||||
|
EXPORT_C_(void)
|
||||||
|
DEV9writeDMA8Mem(u32 *pMem, int size);
|
||||||
|
|
||||||
// cycles = IOP cycles before calling callback,
|
// cycles = IOP cycles before calling callback,
|
||||||
// if callback returns 1 the irq is triggered, else not
|
// if callback returns 1 the irq is triggered, else not
|
||||||
EXPORT_C_(void) DEV9irqCallback(DEV9callback callback);
|
EXPORT_C_(void)
|
||||||
EXPORT_C_(DEV9handler) DEV9irqHandler(void);
|
DEV9irqCallback(DEV9callback callback);
|
||||||
|
EXPORT_C_(DEV9handler)
|
||||||
|
DEV9irqHandler(void);
|
||||||
|
|
||||||
// Extended functions
|
// Extended functions
|
||||||
|
|
||||||
EXPORT_C_(void) DEV9keyEvent(keyEvent *ev);
|
EXPORT_C_(void)
|
||||||
EXPORT_C_(s32) DEV9freeze(u8 mode, freezeData *data);
|
DEV9keyEvent(keyEvent *ev);
|
||||||
EXPORT_C_(void) DEV9configure();
|
EXPORT_C_(s32)
|
||||||
EXPORT_C_(void) DEV9about();
|
DEV9freeze(u8 mode, freezeData *data);
|
||||||
EXPORT_C_(s32) DEV9test();
|
EXPORT_C_(void)
|
||||||
|
DEV9configure();
|
||||||
|
EXPORT_C_(void)
|
||||||
|
DEV9about();
|
||||||
|
EXPORT_C_(s32)
|
||||||
|
DEV9test();
|
||||||
|
|
||||||
#endif // __DEV9API_H__
|
#endif // __DEV9API_H__
|
||||||
|
|
|
@ -37,22 +37,34 @@
|
||||||
|
|
||||||
// NOTE: The read/write functions CANNOT use XMM/MMX regs
|
// NOTE: The read/write functions CANNOT use XMM/MMX regs
|
||||||
// If you want to use them, need to save and restore current ones
|
// If you want to use them, need to save and restore current ones
|
||||||
EXPORT_C_(s32) FWinit();
|
EXPORT_C_(s32)
|
||||||
|
FWinit();
|
||||||
// pDisplay normally is passed a handle to the GS plugins window.
|
// pDisplay normally is passed a handle to the GS plugins window.
|
||||||
EXPORT_C_(s32) FWopen(void *pDisplay);
|
EXPORT_C_(s32)
|
||||||
EXPORT_C_(void) FWclose();
|
FWopen(void *pDisplay);
|
||||||
EXPORT_C_(void) FWshutdown();
|
EXPORT_C_(void)
|
||||||
EXPORT_C_(u32) FWread32(u32 addr);
|
FWclose();
|
||||||
EXPORT_C_(void) FWwrite32(u32 addr, u32 value);
|
EXPORT_C_(void)
|
||||||
EXPORT_C_(void) FWirqCallback(void (*callback)());
|
FWshutdown();
|
||||||
|
EXPORT_C_(u32)
|
||||||
|
FWread32(u32 addr);
|
||||||
|
EXPORT_C_(void)
|
||||||
|
FWwrite32(u32 addr, u32 value);
|
||||||
|
EXPORT_C_(void)
|
||||||
|
FWirqCallback(void (*callback)());
|
||||||
|
|
||||||
// Extended functions
|
// Extended functions
|
||||||
|
|
||||||
EXPORT_C_(void) FWkeyEvent(keyEvent *ev);
|
EXPORT_C_(void)
|
||||||
EXPORT_C_(s32) FWfreeze(u8 mode, freezeData *data);
|
FWkeyEvent(keyEvent *ev);
|
||||||
EXPORT_C_(void) FWconfigure();
|
EXPORT_C_(s32)
|
||||||
EXPORT_C_(void) FWabout();
|
FWfreeze(u8 mode, freezeData *data);
|
||||||
EXPORT_C_(s32) FWtest();
|
EXPORT_C_(void)
|
||||||
|
FWconfigure();
|
||||||
|
EXPORT_C_(void)
|
||||||
|
FWabout();
|
||||||
|
EXPORT_C_(s32)
|
||||||
|
FWtest();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // __USBAPI_H__
|
#endif // __USBAPI_H__
|
||||||
|
|
|
@ -31,55 +31,86 @@
|
||||||
|
|
||||||
#include "Pcsx2Api.h"
|
#include "Pcsx2Api.h"
|
||||||
|
|
||||||
typedef struct _GSdriverInfo {
|
typedef struct _GSdriverInfo
|
||||||
char name[8];
|
{
|
||||||
void *common;
|
char name[8];
|
||||||
|
void *common;
|
||||||
} GSdriverInfo;
|
} GSdriverInfo;
|
||||||
|
|
||||||
// Basic functions.
|
// Basic functions.
|
||||||
EXPORT_C_(s32) GSinit();
|
EXPORT_C_(s32)
|
||||||
|
GSinit();
|
||||||
// pDisplay normally is passed a handle to the GS plugins window.
|
// pDisplay normally is passed a handle to the GS plugins window.
|
||||||
EXPORT_C_(s32) GSopen(void *pDisplay, char *Title, bool multithread);
|
EXPORT_C_(s32)
|
||||||
EXPORT_C_(void) GSclose();
|
GSopen(void *pDisplay, char *Title, bool multithread);
|
||||||
EXPORT_C_(void) GSshutdown();
|
EXPORT_C_(void)
|
||||||
EXPORT_C_(void) GSvsync(int field);
|
GSclose();
|
||||||
EXPORT_C_(void) GSgifTransfer1(u32 *pMem, u32 addr);
|
EXPORT_C_(void)
|
||||||
EXPORT_C_(void) GSgifTransfer2(u32 *pMem, u32 size);
|
GSshutdown();
|
||||||
EXPORT_C_(void) GSgifTransfer3(u32 *pMem, u32 size);
|
EXPORT_C_(void)
|
||||||
EXPORT_C_(void) GSgetLastTag(u64* ptag); // returns the last tag processed (64 bits)
|
GSvsync(int field);
|
||||||
EXPORT_C_(void) GSgifSoftReset(u32 mask);
|
EXPORT_C_(void)
|
||||||
EXPORT_C_(void) GSreadFIFO(u64 *mem);
|
GSgifTransfer1(u32 *pMem, u32 addr);
|
||||||
EXPORT_C_(void) GSreadFIFO2(u64 *mem, int qwc);
|
EXPORT_C_(void)
|
||||||
|
GSgifTransfer2(u32 *pMem, u32 size);
|
||||||
|
EXPORT_C_(void)
|
||||||
|
GSgifTransfer3(u32 *pMem, u32 size);
|
||||||
|
EXPORT_C_(void)
|
||||||
|
GSgetLastTag(u64 *ptag); // returns the last tag processed (64 bits)
|
||||||
|
EXPORT_C_(void)
|
||||||
|
GSgifSoftReset(u32 mask);
|
||||||
|
EXPORT_C_(void)
|
||||||
|
GSreadFIFO(u64 *mem);
|
||||||
|
EXPORT_C_(void)
|
||||||
|
GSreadFIFO2(u64 *mem, int qwc);
|
||||||
|
|
||||||
// Extended functions
|
// Extended functions
|
||||||
|
|
||||||
// GSkeyEvent gets called when there is a keyEvent from the PAD plugin
|
// GSkeyEvent gets called when there is a keyEvent from the PAD plugin
|
||||||
EXPORT_C_(void) GSkeyEvent(keyEvent *ev);
|
EXPORT_C_(void)
|
||||||
EXPORT_C_(void) GSchangeSaveState(s32 state, const char* filename);
|
GSkeyEvent(keyEvent *ev);
|
||||||
EXPORT_C_(void) GSmakeSnapshot(char *path);
|
EXPORT_C_(void)
|
||||||
EXPORT_C_(void) GSmakeSnapshot2(char *pathname, int* snapdone, int savejpg);
|
GSchangeSaveState(s32 state, const char *filename);
|
||||||
EXPORT_C_(void) GSirqCallback(void (*callback)());
|
EXPORT_C_(void)
|
||||||
EXPORT_C_(void) CALLBACK GSprintf(s32 timeout, char *fmt, ...);
|
GSmakeSnapshot(char *path);
|
||||||
EXPORT_C_(void) GSsetBaseMem(void*);
|
EXPORT_C_(void)
|
||||||
EXPORT_C_(void) GSsetGameCRC(s32 crc, s32 gameoptions);
|
GSmakeSnapshot2(char *pathname, int *snapdone, int savejpg);
|
||||||
|
EXPORT_C_(void)
|
||||||
|
GSirqCallback(void (*callback)());
|
||||||
|
EXPORT_C_(void)
|
||||||
|
CALLBACK GSprintf(s32 timeout, char *fmt, ...);
|
||||||
|
EXPORT_C_(void)
|
||||||
|
GSsetBaseMem(void *);
|
||||||
|
EXPORT_C_(void)
|
||||||
|
GSsetGameCRC(s32 crc, s32 gameoptions);
|
||||||
|
|
||||||
// controls frame skipping in the GS, if this routine isn't present, frame skipping won't be done
|
// controls frame skipping in the GS, if this routine isn't present, frame skipping won't be done
|
||||||
EXPORT_C_(void) GSsetFrameSkip(int frameskip);
|
EXPORT_C_(void)
|
||||||
|
GSsetFrameSkip(int frameskip);
|
||||||
|
|
||||||
// if start is true, starts recording spu2 data, else stops
|
// if start is true, starts recording spu2 data, else stops
|
||||||
// returns true if successful
|
// returns true if successful
|
||||||
// for now, pData is not used
|
// for now, pData is not used
|
||||||
EXPORT_C_(bool) GSsetupRecording(bool start);
|
EXPORT_C_(bool)
|
||||||
|
GSsetupRecording(bool start);
|
||||||
|
|
||||||
EXPORT_C_(void) GSreset();
|
EXPORT_C_(void)
|
||||||
EXPORT_C_(void) GSwriteCSR(u32 value);
|
GSreset();
|
||||||
EXPORT_C_(void ) GSgetDriverInfo(GSdriverInfo *info);
|
EXPORT_C_(void)
|
||||||
|
GSwriteCSR(u32 value);
|
||||||
|
EXPORT_C_(void)
|
||||||
|
GSgetDriverInfo(GSdriverInfo *info);
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
EXPORT_C_(s32) CALLBACK GSsetWindowInfo(winInfo *info);
|
EXPORT_C_(s32)
|
||||||
|
CALLBACK GSsetWindowInfo(winInfo *info);
|
||||||
#endif
|
#endif
|
||||||
EXPORT_C_(s32) GSfreeze(u8 mode, freezeData *data);
|
EXPORT_C_(s32)
|
||||||
EXPORT_C_(void) GSconfigure();
|
GSfreeze(u8 mode, freezeData *data);
|
||||||
EXPORT_C_(void) GSabout();
|
EXPORT_C_(void)
|
||||||
EXPORT_C_(s32) GStest();
|
GSconfigure();
|
||||||
|
EXPORT_C_(void)
|
||||||
|
GSabout();
|
||||||
|
EXPORT_C_(s32)
|
||||||
|
GStest();
|
||||||
|
|
||||||
#endif // __GSAPI_H__
|
#endif // __GSAPI_H__
|
|
@ -35,19 +35,27 @@
|
||||||
/* So obsolete that everyone uses it. */
|
/* So obsolete that everyone uses it. */
|
||||||
|
|
||||||
// Basic functions.
|
// Basic functions.
|
||||||
EXPORT_C_(s32) PADinit(u32 flags);
|
EXPORT_C_(s32)
|
||||||
|
PADinit(u32 flags);
|
||||||
// pDisplay normally is passed a handle to the GS plugins window.
|
// pDisplay normally is passed a handle to the GS plugins window.
|
||||||
EXPORT_C_(s32) PADopen(void *pDisplay);
|
EXPORT_C_(s32)
|
||||||
EXPORT_C_(void) PADclose();
|
PADopen(void *pDisplay);
|
||||||
EXPORT_C_(void) PADshutdown();
|
EXPORT_C_(void)
|
||||||
|
PADclose();
|
||||||
|
EXPORT_C_(void)
|
||||||
|
PADshutdown();
|
||||||
// PADkeyEvent is called every vsync (return NULL if no event)
|
// PADkeyEvent is called every vsync (return NULL if no event)
|
||||||
EXPORT_C_(keyEvent*) PADkeyEvent();
|
EXPORT_C_(keyEvent *)
|
||||||
EXPORT_C_(u8) PADstartPoll(u8 pad);
|
PADkeyEvent();
|
||||||
EXPORT_C_(u8) PADpoll(u8 value);
|
EXPORT_C_(u8)
|
||||||
|
PADstartPoll(u8 pad);
|
||||||
|
EXPORT_C_(u8)
|
||||||
|
PADpoll(u8 value);
|
||||||
// returns: 1 if supported pad1
|
// returns: 1 if supported pad1
|
||||||
// 2 if supported pad2
|
// 2 if supported pad2
|
||||||
// 3 if both are supported
|
// 3 if both are supported
|
||||||
EXPORT_C_(u8) PADquery();
|
EXPORT_C_(u8)
|
||||||
|
PADquery();
|
||||||
|
|
||||||
// call to give a hint to the PAD plugin to query for the keyboard state. A
|
// call to give a hint to the PAD plugin to query for the keyboard state. A
|
||||||
// good plugin will query the OS for keyboard state ONLY in this function.
|
// good plugin will query the OS for keyboard state ONLY in this function.
|
||||||
|
@ -56,25 +64,33 @@ EXPORT_C_(u8) PADquery();
|
||||||
// the window (and input). Note that PADupdate can be called from a different
|
// the window (and input). Note that PADupdate can be called from a different
|
||||||
// thread than the other functions, so mutex or other multithreading primitives
|
// thread than the other functions, so mutex or other multithreading primitives
|
||||||
// have to be added to maintain data integrity.
|
// have to be added to maintain data integrity.
|
||||||
EXPORT_C_(void) PADupdate(u8 pad);
|
EXPORT_C_(void)
|
||||||
|
PADupdate(u8 pad);
|
||||||
|
|
||||||
// Extended functions
|
// Extended functions
|
||||||
EXPORT_C_(void) PADgsDriverInfo(GSdriverInfo *info);
|
EXPORT_C_(void)
|
||||||
EXPORT_C_(s32) PADfreeze(u8 mode, freezeData *data);
|
PADgsDriverInfo(GSdriverInfo *info);
|
||||||
|
EXPORT_C_(s32)
|
||||||
|
PADfreeze(u8 mode, freezeData *data);
|
||||||
|
|
||||||
// Returns 1 if the pad plugin wants a multitap on the specified port.
|
// Returns 1 if the pad plugin wants a multitap on the specified port.
|
||||||
// 0 otherwise.
|
// 0 otherwise.
|
||||||
EXPORT_C_(s32) PADqueryMtap(u8 port);
|
EXPORT_C_(s32)
|
||||||
|
PADqueryMtap(u8 port);
|
||||||
|
|
||||||
// Sets the active pad slot for the specified port.
|
// Sets the active pad slot for the specified port.
|
||||||
// Both numbers are 1-based indices. Should return 0 if there's no
|
// Both numbers are 1-based indices. Should return 0 if there's no
|
||||||
// pad on the specified slot. Even if PADqueryMtap(port) returns 0,
|
// pad on the specified slot. Even if PADqueryMtap(port) returns 0,
|
||||||
// should handle this properly for slot != 1, so emulator can allow
|
// should handle this properly for slot != 1, so emulator can allow
|
||||||
// Multitap to be enabled/disabled elsewhere.
|
// Multitap to be enabled/disabled elsewhere.
|
||||||
EXPORT_C_(s32) PADsetSlot(u8 port, u8 slot);
|
EXPORT_C_(s32)
|
||||||
|
PADsetSlot(u8 port, u8 slot);
|
||||||
|
|
||||||
EXPORT_C_(void) PADconfigure();
|
EXPORT_C_(void)
|
||||||
EXPORT_C_(void) PADabout();
|
PADconfigure();
|
||||||
EXPORT_C_(s32) PADtest();
|
EXPORT_C_(void)
|
||||||
|
PADabout();
|
||||||
|
EXPORT_C_(s32)
|
||||||
|
PADtest();
|
||||||
|
|
||||||
#endif // __PADAPI_H__
|
#endif // __PADAPI_H__
|
|
@ -38,49 +38,61 @@
|
||||||
// MTAP SIO plugins should ignore slot values on startPoll, as should RMs (probably).
|
// MTAP SIO plugins should ignore slot values on startPoll, as should RMs (probably).
|
||||||
|
|
||||||
// Port isn't strictly necessary, but doesn't hurt.
|
// Port isn't strictly necessary, but doesn't hurt.
|
||||||
typedef int (CALLBACK * SIOchangeSlotCB)(int port, int slot);
|
typedef int(CALLBACK *SIOchangeSlotCB)(int port, int slot);
|
||||||
|
|
||||||
// Basic functions.
|
// Basic functions.
|
||||||
|
|
||||||
// Types is an or-ed combination of SioTypes to initialize. It'd probably be simplest
|
// Types is an or-ed combination of SioTypes to initialize. It'd probably be simplest
|
||||||
// just to make each SIO plugin support only one type, for simplicity.
|
// just to make each SIO plugin support only one type, for simplicity.
|
||||||
// SIOchangeSlotCB should *only* be called by MTAP plugins.
|
// SIOchangeSlotCB should *only* be called by MTAP plugins.
|
||||||
EXPORT_C_(s32) SIOinit(int types, SIOchangeSlotCB f);
|
EXPORT_C_(s32)
|
||||||
|
SIOinit(int types, SIOchangeSlotCB f);
|
||||||
|
|
||||||
// Single plugin can only be PAD, MTAP, RM, or MC. Only load one plugin of each type,
|
// Single plugin can only be PAD, MTAP, RM, or MC. Only load one plugin of each type,
|
||||||
// but not both a PAD and MTAP. Simplifies plugin selection and interface, as well
|
// but not both a PAD and MTAP. Simplifies plugin selection and interface, as well
|
||||||
// as API.
|
// as API.
|
||||||
// pDisplay normally is passed a handle to the GS plugins window.
|
// pDisplay normally is passed a handle to the GS plugins window.
|
||||||
EXPORT_C_(s32) SIOopen(void *pDisplay);
|
EXPORT_C_(s32)
|
||||||
EXPORT_C_(void) SIOclose();
|
SIOopen(void *pDisplay);
|
||||||
EXPORT_C_(void) SIOshutdown();
|
EXPORT_C_(void)
|
||||||
|
SIOclose();
|
||||||
|
EXPORT_C_(void)
|
||||||
|
SIOshutdown();
|
||||||
|
|
||||||
// Returns 0 if device doesn't exist. Means old pad plugins can just say nothing
|
// Returns 0 if device doesn't exist. Means old pad plugins can just say nothing
|
||||||
// connected to other slots, and SIOpoll won't be called on those slots, ideally.
|
// connected to other slots, and SIOpoll won't be called on those slots, ideally.
|
||||||
EXPORT_C_(s32) SIOstartPoll(u8 deviceType, u32 port, u32 slot, u8 *returnValue);
|
EXPORT_C_(s32)
|
||||||
|
SIOstartPoll(u8 deviceType, u32 port, u32 slot, u8 *returnValue);
|
||||||
|
|
||||||
// Returns 0 on the last output byte.
|
// Returns 0 on the last output byte.
|
||||||
EXPORT_C_(s32) SIOpoll(u8 value, u8 *returnValue);
|
EXPORT_C_(s32)
|
||||||
|
SIOpoll(u8 value, u8 *returnValue);
|
||||||
|
|
||||||
// returns: SIO_TYPE_{PAD,MTAP,RM,MC}
|
// returns: SIO_TYPE_{PAD,MTAP,RM,MC}
|
||||||
EXPORT_C_(u32) SIOquery();
|
EXPORT_C_(u32)
|
||||||
|
SIOquery();
|
||||||
|
|
||||||
// extended funcs
|
// extended funcs
|
||||||
|
|
||||||
EXPORT_C_(void) SIOconfigure();
|
EXPORT_C_(void)
|
||||||
EXPORT_C_(keyEvent*) CALLBACK SIOkeyEvent();
|
SIOconfigure();
|
||||||
|
EXPORT_C_(keyEvent *)
|
||||||
|
CALLBACK SIOkeyEvent();
|
||||||
|
|
||||||
// Save one type at a time. If a plugin supports all 4 types,
|
// Save one type at a time. If a plugin supports all 4 types,
|
||||||
// should expect 4 calls. Increases savestate compatibility.
|
// should expect 4 calls. Increases savestate compatibility.
|
||||||
EXPORT_C_(s32) SIOfreeze(u8 mode, freezeData *data, int type);
|
EXPORT_C_(s32)
|
||||||
EXPORT_C_(void) SIOabout();
|
SIOfreeze(u8 mode, freezeData *data, int type);
|
||||||
EXPORT_C_(s32) SIOtest();
|
EXPORT_C_(void)
|
||||||
|
SIOabout();
|
||||||
|
EXPORT_C_(s32)
|
||||||
|
SIOtest();
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
SIO_TYPE_PAD = 0x00000001,
|
SIO_TYPE_PAD = 0x00000001,
|
||||||
SIO_TYPE_MTAP = 0x00000004,
|
SIO_TYPE_MTAP = 0x00000004,
|
||||||
SIO_TYPE_RM = 0x00000040,
|
SIO_TYPE_RM = 0x00000040,
|
||||||
SIO_TYPE_MC = 0x00000100
|
SIO_TYPE_MC = 0x00000100
|
||||||
} SioTypes;
|
} SioTypes;
|
||||||
|
|
||||||
#endif // __SIOAPI_H__
|
#endif // __SIOAPI_H__
|
|
@ -31,47 +31,74 @@
|
||||||
|
|
||||||
#include "Pcsx2Api.h"
|
#include "Pcsx2Api.h"
|
||||||
|
|
||||||
EXPORT_C_(s32) SPU2init();
|
EXPORT_C_(s32)
|
||||||
|
SPU2init();
|
||||||
// pDisplay normally is passed a handle to the GS plugins window.
|
// pDisplay normally is passed a handle to the GS plugins window.
|
||||||
EXPORT_C_(s32) SPU2open(void *pDisplay);
|
EXPORT_C_(s32)
|
||||||
EXPORT_C_(void) SPU2close();
|
SPU2open(void *pDisplay);
|
||||||
EXPORT_C_(void) SPU2shutdown();
|
EXPORT_C_(void)
|
||||||
EXPORT_C_(void) SPU2write(u32 mem, u16 value);
|
SPU2close();
|
||||||
EXPORT_C_(u16) SPU2read(u32 mem);
|
EXPORT_C_(void)
|
||||||
|
SPU2shutdown();
|
||||||
|
EXPORT_C_(void)
|
||||||
|
SPU2write(u32 mem, u16 value);
|
||||||
|
EXPORT_C_(u16)
|
||||||
|
SPU2read(u32 mem);
|
||||||
|
|
||||||
// The following calls are depreciated.
|
// The following calls are depreciated.
|
||||||
EXPORT_C_(void) SPU2readDMA4Mem(u16 *pMem, u32 size);
|
EXPORT_C_(void)
|
||||||
EXPORT_C_(void) SPU2readDMA7Mem(u16 *pMem, u32 size);
|
SPU2readDMA4Mem(u16 *pMem, u32 size);
|
||||||
EXPORT_C_(void) SPU2writeDMA4Mem(u16 *pMem, u32 size);
|
EXPORT_C_(void)
|
||||||
EXPORT_C_(void) SPU2writeDMA7Mem(u16 *pMem, u32 size);
|
SPU2readDMA7Mem(u16 *pMem, u32 size);
|
||||||
EXPORT_C_(void) SPU2interruptDMA4();
|
EXPORT_C_(void)
|
||||||
EXPORT_C_(void) SPU2interruptDMA7();
|
SPU2writeDMA4Mem(u16 *pMem, u32 size);
|
||||||
|
EXPORT_C_(void)
|
||||||
|
SPU2writeDMA7Mem(u16 *pMem, u32 size);
|
||||||
|
EXPORT_C_(void)
|
||||||
|
SPU2interruptDMA4();
|
||||||
|
EXPORT_C_(void)
|
||||||
|
SPU2interruptDMA7();
|
||||||
|
|
||||||
// These calls replace the calls above.
|
// These calls replace the calls above.
|
||||||
EXPORT_C_(void) SPU2readDMAMem(u16 *pMem, u32 size, u8 core);
|
EXPORT_C_(void)
|
||||||
EXPORT_C_(void) SPU2writeDMAMem(u16 *pMem, u32 size, u8 core);
|
SPU2readDMAMem(u16 *pMem, u32 size, u8 core);
|
||||||
EXPORT_C_(void) SPU2interruptDMA(u8 core);
|
EXPORT_C_(void)
|
||||||
|
SPU2writeDMAMem(u16 *pMem, u32 size, u8 core);
|
||||||
|
EXPORT_C_(void)
|
||||||
|
SPU2interruptDMA(u8 core);
|
||||||
|
|
||||||
// all addresses passed by dma will be pointers to the array starting at baseaddr
|
// all addresses passed by dma will be pointers to the array starting at baseaddr
|
||||||
// This function is necessary to successfully save and reload the spu2 state
|
// This function is necessary to successfully save and reload the spu2 state
|
||||||
EXPORT_C_(void) SPU2setDMABaseAddr(uptr baseaddr);
|
EXPORT_C_(void)
|
||||||
|
SPU2setDMABaseAddr(uptr baseaddr);
|
||||||
|
|
||||||
EXPORT_C_(u32) SPU2ReadMemAddr(u8 core);
|
EXPORT_C_(u32)
|
||||||
EXPORT_C_(void) SPU2WriteMemAddr(u8 core,u32 value);
|
SPU2ReadMemAddr(u8 core);
|
||||||
EXPORT_C_(void) SPU2irqCallback(void (*SPU2callback)(),void (*DMA4callback)(),void (*DMA7callback)());
|
EXPORT_C_(void)
|
||||||
|
SPU2WriteMemAddr(u8 core, u32 value);
|
||||||
|
EXPORT_C_(void)
|
||||||
|
SPU2irqCallback(void (*SPU2callback)(), void (*DMA4callback)(), void (*DMA7callback)());
|
||||||
|
|
||||||
// extended funcs
|
// extended funcs
|
||||||
|
|
||||||
// if start is true, starts recording spu2 data, else stops
|
// if start is true, starts recording spu2 data, else stops
|
||||||
// returns true if successful
|
// returns true if successful
|
||||||
EXPORT_C_(bool) SPU2setupRecording(bool start);
|
EXPORT_C_(bool)
|
||||||
|
SPU2setupRecording(bool start);
|
||||||
|
|
||||||
EXPORT_C_(void) SPU2keyEvent(keyEvent *ev);
|
EXPORT_C_(void)
|
||||||
EXPORT_C_(void) SPU2setClockPtr(u32* ptr);
|
SPU2keyEvent(keyEvent *ev);
|
||||||
EXPORT_C_(void) SPU2async(u32 cycles);
|
EXPORT_C_(void)
|
||||||
EXPORT_C_(s32) SPU2freeze(u8 mode, freezeData *data);
|
SPU2setClockPtr(u32 *ptr);
|
||||||
EXPORT_C_(void) SPU2configure();
|
EXPORT_C_(void)
|
||||||
EXPORT_C_(void) SPU2about();
|
SPU2async(u32 cycles);
|
||||||
EXPORT_C_(s32) SPU2test();
|
EXPORT_C_(s32)
|
||||||
|
SPU2freeze(u8 mode, freezeData *data);
|
||||||
|
EXPORT_C_(void)
|
||||||
|
SPU2configure();
|
||||||
|
EXPORT_C_(void)
|
||||||
|
SPU2about();
|
||||||
|
EXPORT_C_(s32)
|
||||||
|
SPU2test();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -32,34 +32,53 @@
|
||||||
#include "Pcsx2Api.h"
|
#include "Pcsx2Api.h"
|
||||||
|
|
||||||
typedef void (*USBcallback)(int cycles);
|
typedef void (*USBcallback)(int cycles);
|
||||||
typedef int (*USBhandler)(void);
|
typedef int (*USBhandler)(void);
|
||||||
|
|
||||||
// Basic functions.
|
// Basic functions.
|
||||||
EXPORT_C_(s32) USBinit();
|
EXPORT_C_(s32)
|
||||||
|
USBinit();
|
||||||
// pDisplay normally is passed a handle to the GS plugins window.
|
// pDisplay normally is passed a handle to the GS plugins window.
|
||||||
EXPORT_C_(s32) USBopen(void *pDisplay);
|
EXPORT_C_(s32)
|
||||||
EXPORT_C_(void) USBclose();
|
USBopen(void *pDisplay);
|
||||||
EXPORT_C_(void) USBshutdown();
|
EXPORT_C_(void)
|
||||||
EXPORT_C_(u8) USBread8(u32 addr);
|
USBclose();
|
||||||
EXPORT_C_(u16) USBread16(u32 addr);
|
EXPORT_C_(void)
|
||||||
EXPORT_C_(u32) USBread32(u32 addr);
|
USBshutdown();
|
||||||
EXPORT_C_(void) USBwrite8(u32 addr, u8 value);
|
EXPORT_C_(u8)
|
||||||
EXPORT_C_(void) USBwrite16(u32 addr, u16 value);
|
USBread8(u32 addr);
|
||||||
EXPORT_C_(void) USBwrite32(u32 addr, u32 value);
|
EXPORT_C_(u16)
|
||||||
EXPORT_C_(void) USBasync(u32 cycles);
|
USBread16(u32 addr);
|
||||||
|
EXPORT_C_(u32)
|
||||||
|
USBread32(u32 addr);
|
||||||
|
EXPORT_C_(void)
|
||||||
|
USBwrite8(u32 addr, u8 value);
|
||||||
|
EXPORT_C_(void)
|
||||||
|
USBwrite16(u32 addr, u16 value);
|
||||||
|
EXPORT_C_(void)
|
||||||
|
USBwrite32(u32 addr, u32 value);
|
||||||
|
EXPORT_C_(void)
|
||||||
|
USBasync(u32 cycles);
|
||||||
|
|
||||||
// cycles = IOP cycles before calling callback,
|
// cycles = IOP cycles before calling callback,
|
||||||
// if callback returns 1 the irq is triggered, else not
|
// if callback returns 1 the irq is triggered, else not
|
||||||
EXPORT_C_(void) USBirqCallback(USBcallback callback);
|
EXPORT_C_(void)
|
||||||
EXPORT_C_(USBhandler) USBirqHandler(void);
|
USBirqCallback(USBcallback callback);
|
||||||
EXPORT_C_(void) USBsetRAM(void *mem);
|
EXPORT_C_(USBhandler)
|
||||||
|
USBirqHandler(void);
|
||||||
|
EXPORT_C_(void)
|
||||||
|
USBsetRAM(void *mem);
|
||||||
|
|
||||||
// Extended functions
|
// Extended functions
|
||||||
|
|
||||||
EXPORT_C_(void) USBkeyEvent(keyEvent *ev);
|
EXPORT_C_(void)
|
||||||
EXPORT_C_(s32) USBfreeze(u8 mode, freezeData *data);
|
USBkeyEvent(keyEvent *ev);
|
||||||
EXPORT_C_(void) USBconfigure();
|
EXPORT_C_(s32)
|
||||||
EXPORT_C_(void) USBabout();
|
USBfreeze(u8 mode, freezeData *data);
|
||||||
EXPORT_C_(s32) USBtest();
|
EXPORT_C_(void)
|
||||||
|
USBconfigure();
|
||||||
|
EXPORT_C_(void)
|
||||||
|
USBabout();
|
||||||
|
EXPORT_C_(s32)
|
||||||
|
USBtest();
|
||||||
|
|
||||||
#endif // __USBAPI_H__
|
#endif // __USBAPI_H__
|
||||||
|
|
|
@ -17,21 +17,22 @@
|
||||||
|
|
||||||
// Implement BMI1/BMI2 instruction set
|
// Implement BMI1/BMI2 instruction set
|
||||||
|
|
||||||
namespace x86Emitter {
|
namespace x86Emitter
|
||||||
|
{
|
||||||
|
|
||||||
struct xImplBMI_RVM
|
struct xImplBMI_RVM
|
||||||
{
|
{
|
||||||
u8 Prefix;
|
u8 Prefix;
|
||||||
u8 MbPrefix;
|
u8 MbPrefix;
|
||||||
u8 Opcode;
|
u8 Opcode;
|
||||||
|
|
||||||
// RVM
|
// RVM
|
||||||
// MULX Unsigned multiply without affecting flags, and arbitrary destination registers
|
// MULX Unsigned multiply without affecting flags, and arbitrary destination registers
|
||||||
// PDEP Parallel bits deposit
|
// PDEP Parallel bits deposit
|
||||||
// PEXT Parallel bits extract
|
// PEXT Parallel bits extract
|
||||||
// ANDN Logical and not ~x & y
|
// ANDN Logical and not ~x & y
|
||||||
void operator()( const xRegisterInt& to, const xRegisterInt& from1, const xRegisterInt& from2) const;
|
void operator()(const xRegisterInt &to, const xRegisterInt &from1, const xRegisterInt &from2) const;
|
||||||
void operator()( const xRegisterInt& to, const xRegisterInt& from1, const xIndirectVoid& from2) const;
|
void operator()(const xRegisterInt &to, const xRegisterInt &from1, const xIndirectVoid &from2) const;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// RMV
|
// RMV
|
||||||
|
@ -56,6 +57,5 @@ namespace x86Emitter {
|
||||||
void operator()( const xRegisterInt& to, const xRegisterInt& from, u8 imm) const;
|
void operator()( const xRegisterInt& to, const xRegisterInt& from, u8 imm) const;
|
||||||
void operator()( const xRegisterInt& to, const xIndirectVoid& from, u8 imm) const;
|
void operator()( const xRegisterInt& to, const xIndirectVoid& from, u8 imm) const;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace x86Emitter {
|
namespace x86Emitter
|
||||||
|
{
|
||||||
|
|
||||||
// Implementations here cover SHLD and SHRD.
|
// Implementations here cover SHLD and SHRD.
|
||||||
|
|
||||||
|
@ -30,14 +31,14 @@ namespace x86Emitter {
|
||||||
//
|
//
|
||||||
struct xImpl_DwordShift
|
struct xImpl_DwordShift
|
||||||
{
|
{
|
||||||
u16 OpcodeBase;
|
u16 OpcodeBase;
|
||||||
|
|
||||||
void operator()( const xRegister16or32or64& to, const xRegister16or32or64& from, const xRegisterCL& clreg ) const;
|
void operator()(const xRegister16or32or64 &to, const xRegister16or32or64 &from, const xRegisterCL &clreg) const;
|
||||||
|
|
||||||
void operator()( const xRegister16or32or64& to, const xRegister16or32or64& from, u8 shiftcnt ) const;
|
void operator()(const xRegister16or32or64 &to, const xRegister16or32or64 &from, u8 shiftcnt) const;
|
||||||
|
|
||||||
void operator()( const xIndirectVoid& dest,const xRegister16or32or64& from, const xRegisterCL& clreg ) const;
|
void operator()(const xIndirectVoid &dest, const xRegister16or32or64 &from, const xRegisterCL &clreg) const;
|
||||||
void operator()( const xIndirectVoid& dest,const xRegister16or32or64& from, u8 shiftcnt ) const;
|
void operator()(const xIndirectVoid &dest, const xRegister16or32or64 &from, u8 shiftcnt) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End namespace x86Emitter
|
} // End namespace x86Emitter
|
||||||
|
|
|
@ -15,35 +15,35 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace x86Emitter {
|
namespace x86Emitter
|
||||||
|
|
||||||
enum G1Type
|
|
||||||
{
|
{
|
||||||
G1Type_ADD=0,
|
|
||||||
G1Type_OR,
|
enum G1Type {
|
||||||
G1Type_ADC,
|
G1Type_ADD = 0,
|
||||||
G1Type_SBB,
|
G1Type_OR,
|
||||||
G1Type_AND,
|
G1Type_ADC,
|
||||||
G1Type_SUB,
|
G1Type_SBB,
|
||||||
G1Type_XOR,
|
G1Type_AND,
|
||||||
G1Type_CMP
|
G1Type_SUB,
|
||||||
|
G1Type_XOR,
|
||||||
|
G1Type_CMP
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void _g1_EmitOp( G1Type InstType, const xRegisterInt& to, const xRegisterInt& from );
|
extern void _g1_EmitOp(G1Type InstType, const xRegisterInt &to, const xRegisterInt &from);
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// xImpl_Group1
|
// xImpl_Group1
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
struct xImpl_Group1
|
struct xImpl_Group1
|
||||||
{
|
{
|
||||||
G1Type InstType;
|
G1Type InstType;
|
||||||
|
|
||||||
void operator()( const xRegisterInt& to, const xRegisterInt& from ) const;
|
void operator()(const xRegisterInt &to, const xRegisterInt &from) const;
|
||||||
|
|
||||||
void operator()( const xIndirectVoid& to, const xRegisterInt& from ) const;
|
void operator()(const xIndirectVoid &to, const xRegisterInt &from) const;
|
||||||
void operator()( const xRegisterInt& to, const xIndirectVoid& from ) const;
|
void operator()(const xRegisterInt &to, const xIndirectVoid &from) const;
|
||||||
void operator()( const xRegisterInt& to, int imm ) const;
|
void operator()(const xRegisterInt &to, int imm) const;
|
||||||
void operator()( const xIndirect64orLess& to, int imm ) const;
|
void operator()(const xIndirect64orLess &to, int imm) const;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
@ -87,18 +87,18 @@ struct xImpl_Group1
|
||||||
//
|
//
|
||||||
struct xImpl_G1Logic
|
struct xImpl_G1Logic
|
||||||
{
|
{
|
||||||
G1Type InstType;
|
G1Type InstType;
|
||||||
|
|
||||||
void operator()( const xRegisterInt& to, const xRegisterInt& from ) const;
|
void operator()(const xRegisterInt &to, const xRegisterInt &from) const;
|
||||||
|
|
||||||
void operator()( const xIndirectVoid& to, const xRegisterInt& from ) const;
|
void operator()(const xIndirectVoid &to, const xRegisterInt &from) const;
|
||||||
void operator()( const xRegisterInt& to, const xIndirectVoid& from ) const;
|
void operator()(const xRegisterInt &to, const xIndirectVoid &from) const;
|
||||||
void operator()( const xRegisterInt& to, int imm ) const;
|
void operator()(const xRegisterInt &to, int imm) const;
|
||||||
|
|
||||||
void operator()( const xIndirect64orLess& to, int imm ) const;
|
void operator()(const xIndirect64orLess &to, int imm) const;
|
||||||
|
|
||||||
xImplSimd_DestRegSSE PS; // packed single precision
|
xImplSimd_DestRegSSE PS; // packed single precision
|
||||||
xImplSimd_DestRegSSE PD; // packed double precision
|
xImplSimd_DestRegSSE PD; // packed double precision
|
||||||
};
|
};
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
@ -106,38 +106,37 @@ struct xImpl_G1Logic
|
||||||
//
|
//
|
||||||
struct xImpl_G1Arith
|
struct xImpl_G1Arith
|
||||||
{
|
{
|
||||||
G1Type InstType;
|
G1Type InstType;
|
||||||
|
|
||||||
void operator()( const xRegisterInt& to, const xRegisterInt& from ) const;
|
void operator()(const xRegisterInt &to, const xRegisterInt &from) const;
|
||||||
|
|
||||||
void operator()( const xIndirectVoid& to, const xRegisterInt& from ) const;
|
void operator()(const xIndirectVoid &to, const xRegisterInt &from) const;
|
||||||
void operator()( const xRegisterInt& to, const xIndirectVoid& from ) const;
|
void operator()(const xRegisterInt &to, const xIndirectVoid &from) const;
|
||||||
void operator()( const xRegisterInt& to, int imm ) const;
|
void operator()(const xRegisterInt &to, int imm) const;
|
||||||
|
|
||||||
void operator()( const xIndirect64orLess& to, int imm ) const;
|
void operator()(const xIndirect64orLess &to, int imm) const;
|
||||||
|
|
||||||
xImplSimd_DestRegSSE PS; // packed single precision
|
xImplSimd_DestRegSSE PS; // packed single precision
|
||||||
xImplSimd_DestRegSSE PD; // packed double precision
|
xImplSimd_DestRegSSE PD; // packed double precision
|
||||||
xImplSimd_DestRegSSE SS; // scalar single precision
|
xImplSimd_DestRegSSE SS; // scalar single precision
|
||||||
xImplSimd_DestRegSSE SD; // scalar double precision
|
xImplSimd_DestRegSSE SD; // scalar double precision
|
||||||
};
|
};
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
struct xImpl_G1Compare
|
struct xImpl_G1Compare
|
||||||
{
|
{
|
||||||
void operator()( const xRegisterInt& to, const xRegisterInt& from ) const;
|
void operator()(const xRegisterInt &to, const xRegisterInt &from) const;
|
||||||
|
|
||||||
void operator()( const xIndirectVoid& to, const xRegisterInt& from ) const;
|
void operator()(const xIndirectVoid &to, const xRegisterInt &from) const;
|
||||||
void operator()( const xRegisterInt& to, const xIndirectVoid& from ) const;
|
void operator()(const xRegisterInt &to, const xIndirectVoid &from) const;
|
||||||
void operator()( const xRegisterInt& to, int imm ) const;
|
void operator()(const xRegisterInt &to, int imm) const;
|
||||||
|
|
||||||
void operator()( const xIndirect64orLess& to, int imm ) const;
|
void operator()(const xIndirect64orLess &to, int imm) const;
|
||||||
|
|
||||||
xImplSimd_DestSSE_CmpImm PS;
|
xImplSimd_DestSSE_CmpImm PS;
|
||||||
xImplSimd_DestSSE_CmpImm PD;
|
xImplSimd_DestSSE_CmpImm PD;
|
||||||
xImplSimd_DestSSE_CmpImm SS;
|
xImplSimd_DestSSE_CmpImm SS;
|
||||||
xImplSimd_DestSSE_CmpImm SD;
|
xImplSimd_DestSSE_CmpImm SD;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End namespace x86Emitter
|
} // End namespace x86Emitter
|
||||||
|
|
||||||
|
|
|
@ -15,18 +15,18 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace x86Emitter {
|
namespace x86Emitter
|
||||||
|
|
||||||
enum G2Type
|
|
||||||
{
|
{
|
||||||
G2Type_ROL=0,
|
|
||||||
G2Type_ROR,
|
enum G2Type {
|
||||||
G2Type_RCL,
|
G2Type_ROL = 0,
|
||||||
G2Type_RCR,
|
G2Type_ROR,
|
||||||
G2Type_SHL,
|
G2Type_RCL,
|
||||||
G2Type_SHR,
|
G2Type_RCR,
|
||||||
G2Type_Unused,
|
G2Type_SHL,
|
||||||
G2Type_SAR
|
G2Type_SHR,
|
||||||
|
G2Type_Unused,
|
||||||
|
G2Type_SAR
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -38,12 +38,12 @@ enum G2Type
|
||||||
//
|
//
|
||||||
struct xImpl_Group2
|
struct xImpl_Group2
|
||||||
{
|
{
|
||||||
G2Type InstType;
|
G2Type InstType;
|
||||||
|
|
||||||
void operator()( const xRegisterInt& to, const xRegisterCL& from ) const;
|
void operator()(const xRegisterInt &to, const xRegisterCL &from) const;
|
||||||
void operator()( const xIndirect64orLess& to, const xRegisterCL& from ) const;
|
void operator()(const xIndirect64orLess &to, const xRegisterCL &from) const;
|
||||||
void operator()( const xRegisterInt& to, u8 imm ) const;
|
void operator()(const xRegisterInt &to, u8 imm) const;
|
||||||
void operator()( const xIndirect64orLess& to, u8 imm ) const;
|
void operator()(const xIndirect64orLess &to, u8 imm) const;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
|
@ -15,16 +15,16 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace x86Emitter {
|
namespace x86Emitter
|
||||||
|
|
||||||
enum G3Type
|
|
||||||
{
|
{
|
||||||
G3Type_NOT = 2,
|
|
||||||
G3Type_NEG = 3,
|
enum G3Type {
|
||||||
G3Type_MUL = 4,
|
G3Type_NOT = 2,
|
||||||
G3Type_iMUL = 5, // partial implementation, iMul has additional forms in ix86.cpp
|
G3Type_NEG = 3,
|
||||||
G3Type_DIV = 6,
|
G3Type_MUL = 4,
|
||||||
G3Type_iDIV = 7
|
G3Type_iMUL = 5, // partial implementation, iMul has additional forms in ix86.cpp
|
||||||
|
G3Type_DIV = 6,
|
||||||
|
G3Type_iDIV = 7
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -32,10 +32,10 @@ enum G3Type
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
struct xImpl_Group3
|
struct xImpl_Group3
|
||||||
{
|
{
|
||||||
G3Type InstType;
|
G3Type InstType;
|
||||||
|
|
||||||
void operator()( const xRegisterInt& from ) const;
|
void operator()(const xRegisterInt &from) const;
|
||||||
void operator()( const xIndirect64orLess& from ) const;
|
void operator()(const xIndirect64orLess &from) const;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
template< typename T >
|
template< typename T >
|
||||||
|
@ -53,16 +53,16 @@ struct xImpl_Group3
|
||||||
//
|
//
|
||||||
struct xImpl_MulDivBase
|
struct xImpl_MulDivBase
|
||||||
{
|
{
|
||||||
G3Type InstType;
|
G3Type InstType;
|
||||||
u16 OpcodeSSE;
|
u16 OpcodeSSE;
|
||||||
|
|
||||||
void operator()( const xRegisterInt& from ) const;
|
void operator()(const xRegisterInt &from) const;
|
||||||
void operator()( const xIndirect64orLess& from ) const;
|
void operator()(const xIndirect64orLess &from) const;
|
||||||
|
|
||||||
const xImplSimd_DestRegSSE PS;
|
const xImplSimd_DestRegSSE PS;
|
||||||
const xImplSimd_DestRegSSE PD;
|
const xImplSimd_DestRegSSE PD;
|
||||||
const xImplSimd_DestRegSSE SS;
|
const xImplSimd_DestRegSSE SS;
|
||||||
const xImplSimd_DestRegSSE SD;
|
const xImplSimd_DestRegSSE SD;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -70,13 +70,13 @@ struct xImpl_MulDivBase
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
struct xImpl_iDiv
|
struct xImpl_iDiv
|
||||||
{
|
{
|
||||||
void operator()( const xRegisterInt& from ) const;
|
void operator()(const xRegisterInt &from) const;
|
||||||
void operator()( const xIndirect64orLess& from ) const;
|
void operator()(const xIndirect64orLess &from) const;
|
||||||
|
|
||||||
const xImplSimd_DestRegSSE PS;
|
const xImplSimd_DestRegSSE PS;
|
||||||
const xImplSimd_DestRegSSE PD;
|
const xImplSimd_DestRegSSE PD;
|
||||||
const xImplSimd_DestRegSSE SS;
|
const xImplSimd_DestRegSSE SS;
|
||||||
const xImplSimd_DestRegSSE SD;
|
const xImplSimd_DestRegSSE SD;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -85,25 +85,24 @@ struct xImpl_iDiv
|
||||||
//
|
//
|
||||||
struct xImpl_iMul
|
struct xImpl_iMul
|
||||||
{
|
{
|
||||||
void operator()( const xRegisterInt& from ) const;
|
void operator()(const xRegisterInt &from) const;
|
||||||
void operator()( const xIndirect64orLess& from ) const;
|
void operator()(const xIndirect64orLess &from) const;
|
||||||
|
|
||||||
// The following iMul-specific forms are valid for 16 and 32 bit register operands only!
|
// The following iMul-specific forms are valid for 16 and 32 bit register operands only!
|
||||||
|
|
||||||
void operator()( const xRegister32& to, const xRegister32& from ) const;
|
void operator()(const xRegister32 &to, const xRegister32 &from) const;
|
||||||
void operator()( const xRegister32& to, const xIndirectVoid& src ) const;
|
void operator()(const xRegister32 &to, const xIndirectVoid &src) const;
|
||||||
void operator()( const xRegister16& to, const xRegister16& from ) const;
|
void operator()(const xRegister16 &to, const xRegister16 &from) const;
|
||||||
void operator()( const xRegister16& to, const xIndirectVoid& src ) const;
|
void operator()(const xRegister16 &to, const xIndirectVoid &src) const;
|
||||||
|
|
||||||
void operator()( const xRegister32& to, const xRegister32& from, s32 imm ) const;
|
void operator()(const xRegister32 &to, const xRegister32 &from, s32 imm) const;
|
||||||
void operator()( const xRegister32& to, const xIndirectVoid& from, s32 imm ) const;
|
void operator()(const xRegister32 &to, const xIndirectVoid &from, s32 imm) const;
|
||||||
void operator()( const xRegister16& to, const xRegister16& from, s16 imm ) const;
|
void operator()(const xRegister16 &to, const xRegister16 &from, s16 imm) const;
|
||||||
void operator()( const xRegister16& to, const xIndirectVoid& from, s16 imm ) const;
|
void operator()(const xRegister16 &to, const xIndirectVoid &from, s16 imm) const;
|
||||||
|
|
||||||
const xImplSimd_DestRegSSE PS;
|
const xImplSimd_DestRegSSE PS;
|
||||||
const xImplSimd_DestRegSSE PD;
|
const xImplSimd_DestRegSSE PD;
|
||||||
const xImplSimd_DestRegSSE SS;
|
const xImplSimd_DestRegSSE SS;
|
||||||
const xImplSimd_DestRegSSE SD;
|
const xImplSimd_DestRegSSE SD;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace x86Emitter {
|
namespace x86Emitter
|
||||||
|
{
|
||||||
|
|
||||||
// helpermess is currently broken >_<
|
// helpermess is currently broken >_<
|
||||||
|
|
||||||
|
@ -88,4 +89,4 @@ void _DoI_helpermess( const xImpl& helpme, const xDirectOrIndirect<T>& to, const
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} // End namespace x86Emitter
|
} // End namespace x86Emitter
|
||||||
|
|
|
@ -18,17 +18,18 @@
|
||||||
// Implementations found here: Increment and Decrement Instructions!
|
// Implementations found here: Increment and Decrement Instructions!
|
||||||
// (They're soooo lonely... but I dunno where else to stick this class!)
|
// (They're soooo lonely... but I dunno where else to stick this class!)
|
||||||
|
|
||||||
namespace x86Emitter {
|
namespace x86Emitter
|
||||||
|
{
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// xImpl_IncDec
|
// xImpl_IncDec
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
struct xImpl_IncDec
|
struct xImpl_IncDec
|
||||||
{
|
{
|
||||||
bool isDec;
|
bool isDec;
|
||||||
|
|
||||||
void operator()( const xRegisterInt& to ) const;
|
void operator()(const xRegisterInt &to) const;
|
||||||
void operator()( const xIndirect64orLess& to ) const;
|
void operator()(const xIndirect64orLess &to) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End namespace x86Emitter
|
} // End namespace x86Emitter
|
||||||
|
|
|
@ -17,171 +17,170 @@
|
||||||
|
|
||||||
// Implementations found here: CALL and JMP! (unconditional only)
|
// Implementations found here: CALL and JMP! (unconditional only)
|
||||||
|
|
||||||
namespace x86Emitter {
|
namespace x86Emitter
|
||||||
|
{
|
||||||
|
|
||||||
extern void xJccKnownTarget( JccComparisonType comparison, const void* target, bool slideForward );
|
extern void xJccKnownTarget(JccComparisonType comparison, const void *target, bool slideForward);
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
struct xImpl_JmpCall
|
struct xImpl_JmpCall
|
||||||
{
|
{
|
||||||
bool isJmp;
|
bool isJmp;
|
||||||
|
|
||||||
void operator()( const xRegisterInt& absreg ) const;
|
void operator()(const xRegisterInt &absreg) const;
|
||||||
void operator()( const xIndirect64orLess& src ) const;
|
void operator()(const xIndirect64orLess &src) const;
|
||||||
|
|
||||||
// Special form for calling functions. This form automatically resolves the
|
// Special form for calling functions. This form automatically resolves the
|
||||||
// correct displacement based on the size of the instruction being generated.
|
// correct displacement based on the size of the instruction being generated.
|
||||||
void operator()( void* func ) const
|
void operator()(void *func) const
|
||||||
{
|
{
|
||||||
if( isJmp )
|
if (isJmp)
|
||||||
xJccKnownTarget( Jcc_Unconditional, (void*)(uptr)func, false ); // double cast to/from (uptr) needed to appease GCC
|
xJccKnownTarget(Jcc_Unconditional, (void *)(uptr)func, false); // double cast to/from (uptr) needed to appease GCC
|
||||||
else
|
else {
|
||||||
{
|
// calls are relative to the instruction after this one, and length is
|
||||||
// calls are relative to the instruction after this one, and length is
|
// always 5 bytes (16 bit calls are bad mojo, so no bother to do special logic).
|
||||||
// always 5 bytes (16 bit calls are bad mojo, so no bother to do special logic).
|
|
||||||
|
|
||||||
sptr dest = (sptr)func - ((sptr)xGetPtr() + 5);
|
sptr dest = (sptr)func - ((sptr)xGetPtr() + 5);
|
||||||
xWrite8( 0xe8 );
|
xWrite8(0xe8);
|
||||||
xWrite32( dest );
|
xWrite32(dest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// yes it is awful. Due to template code is in a header with a nice circular dep.
|
// yes it is awful. Due to template code is in a header with a nice circular dep.
|
||||||
extern const xImpl_Mov xMOV;
|
extern const xImpl_Mov xMOV;
|
||||||
extern const xImpl_JmpCall xCALL;
|
extern const xImpl_JmpCall xCALL;
|
||||||
|
|
||||||
struct xImpl_FastCall
|
struct xImpl_FastCall
|
||||||
{
|
{
|
||||||
// FIXME: current 64 bits is mostly a copy/past potentially it would require to push/pop
|
// FIXME: current 64 bits is mostly a copy/past potentially it would require to push/pop
|
||||||
// some registers. But I think it is enough to handle the first call.
|
// some registers. But I think it is enough to handle the first call.
|
||||||
|
|
||||||
|
|
||||||
// Type unsafety is nice
|
// Type unsafety is nice
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
|
|
||||||
#define XFASTCALL \
|
#define XFASTCALL \
|
||||||
xCALL(f);
|
xCALL(f);
|
||||||
|
|
||||||
#define XFASTCALL1 \
|
#define XFASTCALL1 \
|
||||||
xMOV(rdi, a1); \
|
xMOV(rdi, a1); \
|
||||||
xCALL(f);
|
xCALL(f);
|
||||||
|
|
||||||
#define XFASTCALL2 \
|
#define XFASTCALL2 \
|
||||||
xMOV(rdi, a1); \
|
xMOV(rdi, a1); \
|
||||||
xMOV(rsi, a2); \
|
xMOV(rsi, a2); \
|
||||||
xCALL(f);
|
xCALL(f);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define XFASTCALL \
|
#define XFASTCALL \
|
||||||
xCALL(f);
|
xCALL(f);
|
||||||
|
|
||||||
#define XFASTCALL1 \
|
#define XFASTCALL1 \
|
||||||
xMOV(ecx, a1); \
|
xMOV(ecx, a1); \
|
||||||
xCALL(f);
|
xCALL(f);
|
||||||
|
|
||||||
#define XFASTCALL2 \
|
#define XFASTCALL2 \
|
||||||
xMOV(ecx, a1); \
|
xMOV(ecx, a1); \
|
||||||
xMOV(edx, a2); \
|
xMOV(edx, a2); \
|
||||||
xCALL(f);
|
xCALL(f);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void operator()( void* f, const xRegisterLong& a1 = xEmptyReg, const xRegisterLong& a2 = xEmptyReg) const
|
void operator()(void *f, const xRegisterLong &a1 = xEmptyReg, const xRegisterLong &a2 = xEmptyReg) const
|
||||||
{
|
{
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
if (a1.IsEmpty()) {
|
if (a1.IsEmpty()) {
|
||||||
XFASTCALL;
|
XFASTCALL;
|
||||||
} else if (a2.IsEmpty()) {
|
} else if (a2.IsEmpty()) {
|
||||||
XFASTCALL1;
|
XFASTCALL1;
|
||||||
} else {
|
} else {
|
||||||
XFASTCALL2;
|
XFASTCALL2;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (a1.IsEmpty()) {
|
if (a1.IsEmpty()) {
|
||||||
XFASTCALL;
|
XFASTCALL;
|
||||||
} else if (a2.IsEmpty()) {
|
} else if (a2.IsEmpty()) {
|
||||||
XFASTCALL1;
|
XFASTCALL1;
|
||||||
} else {
|
} else {
|
||||||
XFASTCALL2;
|
XFASTCALL2;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T > __fi
|
template <typename T>
|
||||||
void operator()( T* func, u32 a1, const xRegisterLong& a2) const
|
__fi void operator()(T *func, u32 a1, const xRegisterLong &a2) const
|
||||||
{
|
{
|
||||||
void* f = (void*)func;
|
void *f = (void *)func;
|
||||||
|
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
XFASTCALL2;
|
XFASTCALL2;
|
||||||
#else
|
#else
|
||||||
XFASTCALL2;
|
XFASTCALL2;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T > __fi
|
template <typename T>
|
||||||
void operator()( T* func, const xIndirectVoid& a1) const
|
__fi void operator()(T *func, const xIndirectVoid &a1) const
|
||||||
{
|
{
|
||||||
void* f = (void*)func;
|
void *f = (void *)func;
|
||||||
|
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
XFASTCALL1;
|
XFASTCALL1;
|
||||||
#else
|
#else
|
||||||
XFASTCALL1;
|
XFASTCALL1;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T > __fi
|
template <typename T>
|
||||||
void operator()( T* func, u32 a1, u32 a2) const
|
__fi void operator()(T *func, u32 a1, u32 a2) const
|
||||||
{
|
{
|
||||||
void* f = (void*)func;
|
void *f = (void *)func;
|
||||||
|
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
XFASTCALL2;
|
XFASTCALL2;
|
||||||
#else
|
#else
|
||||||
XFASTCALL2;
|
XFASTCALL2;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
template< typename T > __fi
|
template <typename T>
|
||||||
void operator()( T* func, u32 a1) const
|
__fi void operator()(T *func, u32 a1) const
|
||||||
{
|
{
|
||||||
void* f = (void*)func;
|
void *f = (void *)func;
|
||||||
|
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
XFASTCALL1;
|
XFASTCALL1;
|
||||||
#else
|
#else
|
||||||
XFASTCALL1;
|
XFASTCALL1;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()(const xIndirect32& f, const xRegisterLong& a1 = xEmptyReg, const xRegisterLong& a2 = xEmptyReg) const
|
void operator()(const xIndirect32 &f, const xRegisterLong &a1 = xEmptyReg, const xRegisterLong &a2 = xEmptyReg) const
|
||||||
{
|
{
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
if (a1.IsEmpty()) {
|
if (a1.IsEmpty()) {
|
||||||
XFASTCALL;
|
XFASTCALL;
|
||||||
} else if (a2.IsEmpty()) {
|
} else if (a2.IsEmpty()) {
|
||||||
XFASTCALL1;
|
XFASTCALL1;
|
||||||
} else {
|
} else {
|
||||||
XFASTCALL2;
|
XFASTCALL2;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (a1.IsEmpty()) {
|
if (a1.IsEmpty()) {
|
||||||
XFASTCALL;
|
XFASTCALL;
|
||||||
} else if (a2.IsEmpty()) {
|
} else if (a2.IsEmpty()) {
|
||||||
XFASTCALL1;
|
XFASTCALL1;
|
||||||
} else {
|
} else {
|
||||||
XFASTCALL2;
|
XFASTCALL2;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef XFASTCALL
|
#undef XFASTCALL
|
||||||
#undef XFASTCALL1
|
#undef XFASTCALL1
|
||||||
#undef XFASTCALL2
|
#undef XFASTCALL2
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End namespace x86Emitter
|
} // End namespace x86Emitter
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,8 @@
|
||||||
// Header: ix86_impl_movs.h -- covers mov, cmov, movsx/movzx, and SETcc (which shares
|
// Header: ix86_impl_movs.h -- covers mov, cmov, movsx/movzx, and SETcc (which shares
|
||||||
// with cmov many similarities).
|
// with cmov many similarities).
|
||||||
|
|
||||||
namespace x86Emitter {
|
namespace x86Emitter
|
||||||
|
{
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// MovImplAll
|
// MovImplAll
|
||||||
|
@ -27,13 +28,13 @@ namespace x86Emitter {
|
||||||
//
|
//
|
||||||
struct xImpl_Mov
|
struct xImpl_Mov
|
||||||
{
|
{
|
||||||
xImpl_Mov() {} // Satisfy GCC's whims.
|
xImpl_Mov() {} // Satisfy GCC's whims.
|
||||||
|
|
||||||
void operator()( const xRegisterInt& to, const xRegisterInt& from ) const;
|
void operator()(const xRegisterInt &to, const xRegisterInt &from) const;
|
||||||
void operator()( const xIndirectVoid& dest, const xRegisterInt& from ) const;
|
void operator()(const xIndirectVoid &dest, const xRegisterInt &from) const;
|
||||||
void operator()( const xRegisterInt& to, const xIndirectVoid& src ) const;
|
void operator()(const xRegisterInt &to, const xIndirectVoid &src) const;
|
||||||
void operator()( const xIndirect64orLess& dest, int imm ) const;
|
void operator()(const xIndirect64orLess &dest, int imm) const;
|
||||||
void operator()( const xRegisterInt& to, int imm, bool preserve_flags=false ) const;
|
void operator()(const xRegisterInt &to, int imm, bool preserve_flags = false) const;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
template< typename T > __noinline void operator()( const ModSibBase& to, const xImmReg<T>& immOrReg ) const
|
template< typename T > __noinline void operator()( const ModSibBase& to, const xImmReg<T>& immOrReg ) const
|
||||||
|
@ -84,22 +85,22 @@ struct xImpl_Mov
|
||||||
|
|
||||||
struct xImpl_CMov
|
struct xImpl_CMov
|
||||||
{
|
{
|
||||||
JccComparisonType ccType;
|
JccComparisonType ccType;
|
||||||
void operator()( const xRegister16or32or64& to, const xRegister16or32or64& from ) const;
|
void operator()(const xRegister16or32or64 &to, const xRegister16or32or64 &from) const;
|
||||||
void operator()( const xRegister16or32or64& to, const xIndirectVoid& sibsrc ) const;
|
void operator()(const xRegister16or32or64 &to, const xIndirectVoid &sibsrc) const;
|
||||||
|
|
||||||
//void operator()( const xDirectOrIndirect32& to, const xDirectOrIndirect32& from );
|
//void operator()( const xDirectOrIndirect32& to, const xDirectOrIndirect32& from );
|
||||||
//void operator()( const xDirectOrIndirect16& to, const xDirectOrIndirect16& from ) const;
|
//void operator()( const xDirectOrIndirect16& to, const xDirectOrIndirect16& from ) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct xImpl_Set
|
struct xImpl_Set
|
||||||
{
|
{
|
||||||
JccComparisonType ccType;
|
JccComparisonType ccType;
|
||||||
|
|
||||||
void operator()( const xRegister8& to ) const;
|
void operator()(const xRegister8 &to) const;
|
||||||
void operator()( const xIndirect8& dest ) const;
|
void operator()(const xIndirect8 &dest) const;
|
||||||
|
|
||||||
//void operator()( const xDirectOrIndirect8& dest ) const;
|
//void operator()( const xDirectOrIndirect8& dest ) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -110,16 +111,16 @@ struct xImpl_Set
|
||||||
//
|
//
|
||||||
struct xImpl_MovExtend
|
struct xImpl_MovExtend
|
||||||
{
|
{
|
||||||
bool SignExtend;
|
bool SignExtend;
|
||||||
|
|
||||||
void operator()( const xRegister16or32or64& to, const xRegister8& from ) const;
|
void operator()(const xRegister16or32or64 &to, const xRegister8 &from) const;
|
||||||
void operator()( const xRegister16or32or64& to, const xIndirect8& sibsrc ) const;
|
void operator()(const xRegister16or32or64 &to, const xIndirect8 &sibsrc) const;
|
||||||
void operator()( const xRegister32or64& to, const xRegister16& from ) const;
|
void operator()(const xRegister32or64 &to, const xRegister16 &from) const;
|
||||||
void operator()( const xRegister32or64& to, const xIndirect16& sibsrc ) const;
|
void operator()(const xRegister32or64 &to, const xIndirect16 &sibsrc) const;
|
||||||
|
|
||||||
//void operator()( const xRegister32& to, const xDirectOrIndirect16& src ) const;
|
//void operator()( const xRegister32& to, const xDirectOrIndirect16& src ) const;
|
||||||
//void operator()( const xRegister16or32& to, const xDirectOrIndirect8& src ) const;
|
//void operator()( const xRegister16or32& to, const xDirectOrIndirect8& src ) const;
|
||||||
//void operator()( const xRegister16& to, const xDirectOrIndirect8& src ) const;
|
//void operator()( const xRegister16& to, const xDirectOrIndirect8& src ) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End namespace x86Emitter
|
} // End namespace x86Emitter
|
||||||
|
|
|
@ -15,22 +15,23 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace x86Emitter {
|
namespace x86Emitter
|
||||||
|
{
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// _SimdShiftHelper
|
// _SimdShiftHelper
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
struct _SimdShiftHelper
|
struct _SimdShiftHelper
|
||||||
{
|
{
|
||||||
u8 Prefix;
|
u8 Prefix;
|
||||||
u16 Opcode;
|
u16 Opcode;
|
||||||
u16 OpcodeImm;
|
u16 OpcodeImm;
|
||||||
u8 Modcode;
|
u8 Modcode;
|
||||||
|
|
||||||
void operator()( const xRegisterSSE& to, const xRegisterSSE& from ) const;
|
void operator()(const xRegisterSSE &to, const xRegisterSSE &from) const;
|
||||||
void operator()( const xRegisterSSE& to, const xIndirectVoid& from ) const;
|
void operator()(const xRegisterSSE &to, const xIndirectVoid &from) const;
|
||||||
|
|
||||||
void operator()( const xRegisterSSE& to, u8 imm8 ) const;
|
void operator()(const xRegisterSSE &to, u8 imm8) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -41,70 +42,70 @@ struct _SimdShiftHelper
|
||||||
//
|
//
|
||||||
struct xImplSimd_ShiftWithoutQ
|
struct xImplSimd_ShiftWithoutQ
|
||||||
{
|
{
|
||||||
const _SimdShiftHelper W;
|
const _SimdShiftHelper W;
|
||||||
const _SimdShiftHelper D;
|
const _SimdShiftHelper D;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Implements PSRL and PSLL
|
// Implements PSRL and PSLL
|
||||||
//
|
//
|
||||||
struct xImplSimd_Shift
|
struct xImplSimd_Shift
|
||||||
{
|
{
|
||||||
const _SimdShiftHelper W;
|
const _SimdShiftHelper W;
|
||||||
const _SimdShiftHelper D;
|
const _SimdShiftHelper D;
|
||||||
const _SimdShiftHelper Q;
|
const _SimdShiftHelper Q;
|
||||||
|
|
||||||
void DQ( const xRegisterSSE& to, u8 imm8 ) const;
|
void DQ(const xRegisterSSE &to, u8 imm8) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
struct xImplSimd_AddSub
|
struct xImplSimd_AddSub
|
||||||
{
|
{
|
||||||
const xImplSimd_DestRegEither B;
|
const xImplSimd_DestRegEither B;
|
||||||
const xImplSimd_DestRegEither W;
|
const xImplSimd_DestRegEither W;
|
||||||
const xImplSimd_DestRegEither D;
|
const xImplSimd_DestRegEither D;
|
||||||
const xImplSimd_DestRegEither Q;
|
const xImplSimd_DestRegEither Q;
|
||||||
|
|
||||||
// Add/Sub packed signed byte [8bit] integers from src into dest, and saturate the results.
|
// Add/Sub packed signed byte [8bit] integers from src into dest, and saturate the results.
|
||||||
const xImplSimd_DestRegEither SB;
|
const xImplSimd_DestRegEither SB;
|
||||||
|
|
||||||
// Add/Sub packed signed word [16bit] integers from src into dest, and saturate the results.
|
// Add/Sub packed signed word [16bit] integers from src into dest, and saturate the results.
|
||||||
const xImplSimd_DestRegEither SW;
|
const xImplSimd_DestRegEither SW;
|
||||||
|
|
||||||
// Add/Sub packed unsigned byte [8bit] integers from src into dest, and saturate the results.
|
// Add/Sub packed unsigned byte [8bit] integers from src into dest, and saturate the results.
|
||||||
const xImplSimd_DestRegEither USB;
|
const xImplSimd_DestRegEither USB;
|
||||||
|
|
||||||
// Add/Sub packed unsigned word [16bit] integers from src into dest, and saturate the results.
|
// Add/Sub packed unsigned word [16bit] integers from src into dest, and saturate the results.
|
||||||
const xImplSimd_DestRegEither USW;
|
const xImplSimd_DestRegEither USW;
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
struct xImplSimd_PMul
|
struct xImplSimd_PMul
|
||||||
{
|
{
|
||||||
const xImplSimd_DestRegEither LW;
|
const xImplSimd_DestRegEither LW;
|
||||||
const xImplSimd_DestRegEither HW;
|
const xImplSimd_DestRegEither HW;
|
||||||
const xImplSimd_DestRegEither HUW;
|
const xImplSimd_DestRegEither HUW;
|
||||||
const xImplSimd_DestRegEither UDQ;
|
const xImplSimd_DestRegEither UDQ;
|
||||||
|
|
||||||
// [SSE-3] PMULHRSW multiplies vertically each signed 16-bit integer from dest with the
|
// [SSE-3] PMULHRSW multiplies vertically each signed 16-bit integer from dest with the
|
||||||
// corresponding signed 16-bit integer of source, producing intermediate signed 32-bit
|
// corresponding signed 16-bit integer of source, producing intermediate signed 32-bit
|
||||||
// integers. Each intermediate 32-bit integer is truncated to the 18 most significant
|
// integers. Each intermediate 32-bit integer is truncated to the 18 most significant
|
||||||
// bits. Rounding is always performed by adding 1 to the least significant bit of the
|
// bits. Rounding is always performed by adding 1 to the least significant bit of the
|
||||||
// 18-bit intermediate result. The final result is obtained by selecting the 16 bits
|
// 18-bit intermediate result. The final result is obtained by selecting the 16 bits
|
||||||
// immediately to the right of the most significant bit of each 18-bit intermediate
|
// immediately to the right of the most significant bit of each 18-bit intermediate
|
||||||
// result and packed to the destination operand.
|
// result and packed to the destination operand.
|
||||||
//
|
//
|
||||||
// Both operands can be MMX or XMM registers. Source can be register or memory.
|
// Both operands can be MMX or XMM registers. Source can be register or memory.
|
||||||
//
|
//
|
||||||
const xImplSimd_DestRegEither HRSW;
|
const xImplSimd_DestRegEither HRSW;
|
||||||
|
|
||||||
// [SSE-4.1] Multiply the packed dword signed integers in dest with src, and store
|
// [SSE-4.1] Multiply the packed dword signed integers in dest with src, and store
|
||||||
// the low 32 bits of each product in xmm1.
|
// the low 32 bits of each product in xmm1.
|
||||||
const xImplSimd_DestRegSSE LD;
|
const xImplSimd_DestRegSSE LD;
|
||||||
|
|
||||||
// [SSE-4.1] Multiply the packed signed dword integers in dest with src.
|
// [SSE-4.1] Multiply the packed signed dword integers in dest with src.
|
||||||
const xImplSimd_DestRegSSE DQ;
|
const xImplSimd_DestRegSSE DQ;
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -112,8 +113,8 @@ struct xImplSimd_PMul
|
||||||
//
|
//
|
||||||
struct xImplSimd_rSqrt
|
struct xImplSimd_rSqrt
|
||||||
{
|
{
|
||||||
const xImplSimd_DestRegSSE PS;
|
const xImplSimd_DestRegSSE PS;
|
||||||
const xImplSimd_DestRegSSE SS;
|
const xImplSimd_DestRegSSE SS;
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -121,17 +122,17 @@ struct xImplSimd_rSqrt
|
||||||
//
|
//
|
||||||
struct xImplSimd_Sqrt
|
struct xImplSimd_Sqrt
|
||||||
{
|
{
|
||||||
const xImplSimd_DestRegSSE PS;
|
const xImplSimd_DestRegSSE PS;
|
||||||
const xImplSimd_DestRegSSE SS;
|
const xImplSimd_DestRegSSE SS;
|
||||||
const xImplSimd_DestRegSSE SD;
|
const xImplSimd_DestRegSSE SD;
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
struct xImplSimd_AndNot
|
struct xImplSimd_AndNot
|
||||||
{
|
{
|
||||||
const xImplSimd_DestRegSSE PS;
|
const xImplSimd_DestRegSSE PS;
|
||||||
const xImplSimd_DestRegSSE PD;
|
const xImplSimd_DestRegSSE PD;
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -139,17 +140,17 @@ struct xImplSimd_AndNot
|
||||||
//
|
//
|
||||||
struct xImplSimd_PAbsolute
|
struct xImplSimd_PAbsolute
|
||||||
{
|
{
|
||||||
// [sSSE-3] Computes the absolute value of bytes in the src, and stores the result
|
// [sSSE-3] Computes the absolute value of bytes in the src, and stores the result
|
||||||
// in dest, as UNSIGNED.
|
// in dest, as UNSIGNED.
|
||||||
const xImplSimd_DestRegEither B;
|
const xImplSimd_DestRegEither B;
|
||||||
|
|
||||||
// [sSSE-3] Computes the absolute value of word in the src, and stores the result
|
// [sSSE-3] Computes the absolute value of word in the src, and stores the result
|
||||||
// in dest, as UNSIGNED.
|
// in dest, as UNSIGNED.
|
||||||
const xImplSimd_DestRegEither W;
|
const xImplSimd_DestRegEither W;
|
||||||
|
|
||||||
// [sSSE-3] Computes the absolute value of doublewords in the src, and stores the
|
// [sSSE-3] Computes the absolute value of doublewords in the src, and stores the
|
||||||
// result in dest, as UNSIGNED.
|
// result in dest, as UNSIGNED.
|
||||||
const xImplSimd_DestRegEither D;
|
const xImplSimd_DestRegEither D;
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -158,27 +159,26 @@ struct xImplSimd_PAbsolute
|
||||||
//
|
//
|
||||||
struct xImplSimd_PSign
|
struct xImplSimd_PSign
|
||||||
{
|
{
|
||||||
// [sSSE-3] negates each byte element of dest if the signed integer value of the
|
// [sSSE-3] negates each byte element of dest if the signed integer value of the
|
||||||
// corresponding data element in src is less than zero. If the signed integer value
|
// corresponding data element in src is less than zero. If the signed integer value
|
||||||
// of a data element in src is positive, the corresponding data element in dest is
|
// of a data element in src is positive, the corresponding data element in dest is
|
||||||
// unchanged. If a data element in src is zero, the corresponding data element in
|
// unchanged. If a data element in src is zero, the corresponding data element in
|
||||||
// dest is set to zero.
|
// dest is set to zero.
|
||||||
const xImplSimd_DestRegEither B;
|
const xImplSimd_DestRegEither B;
|
||||||
|
|
||||||
// [sSSE-3] negates each word element of dest if the signed integer value of the
|
// [sSSE-3] negates each word element of dest if the signed integer value of the
|
||||||
// corresponding data element in src is less than zero. If the signed integer value
|
// corresponding data element in src is less than zero. If the signed integer value
|
||||||
// of a data element in src is positive, the corresponding data element in dest is
|
// of a data element in src is positive, the corresponding data element in dest is
|
||||||
// unchanged. If a data element in src is zero, the corresponding data element in
|
// unchanged. If a data element in src is zero, the corresponding data element in
|
||||||
// dest is set to zero.
|
// dest is set to zero.
|
||||||
const xImplSimd_DestRegEither W;
|
const xImplSimd_DestRegEither W;
|
||||||
|
|
||||||
// [sSSE-3] negates each doubleword element of dest if the signed integer value
|
|
||||||
// of the corresponding data element in src is less than zero. If the signed integer
|
|
||||||
// value of a data element in src is positive, the corresponding data element in dest
|
|
||||||
// is unchanged. If a data element in src is zero, the corresponding data element in
|
|
||||||
// dest is set to zero.
|
|
||||||
const xImplSimd_DestRegEither D;
|
|
||||||
|
|
||||||
|
// [sSSE-3] negates each doubleword element of dest if the signed integer value
|
||||||
|
// of the corresponding data element in src is less than zero. If the signed integer
|
||||||
|
// value of a data element in src is positive, the corresponding data element in dest
|
||||||
|
// is unchanged. If a data element in src is zero, the corresponding data element in
|
||||||
|
// dest is set to zero.
|
||||||
|
const xImplSimd_DestRegEither D;
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -186,31 +186,31 @@ struct xImplSimd_PSign
|
||||||
//
|
//
|
||||||
struct xImplSimd_PMultAdd
|
struct xImplSimd_PMultAdd
|
||||||
{
|
{
|
||||||
// Multiplies the individual signed words of dest by the corresponding signed words
|
// Multiplies the individual signed words of dest by the corresponding signed words
|
||||||
// of src, producing temporary signed, doubleword results. The adjacent doubleword
|
// of src, producing temporary signed, doubleword results. The adjacent doubleword
|
||||||
// results are then summed and stored in the destination operand.
|
// results are then summed and stored in the destination operand.
|
||||||
//
|
//
|
||||||
// DEST[31:0] = ( DEST[15:0] * SRC[15:0]) + (DEST[31:16] * SRC[31:16] );
|
// DEST[31:0] = ( DEST[15:0] * SRC[15:0]) + (DEST[31:16] * SRC[31:16] );
|
||||||
// DEST[63:32] = ( DEST[47:32] * SRC[47:32]) + (DEST[63:48] * SRC[63:48] );
|
// DEST[63:32] = ( DEST[47:32] * SRC[47:32]) + (DEST[63:48] * SRC[63:48] );
|
||||||
// [.. repeat in the case of XMM src/dest operands ..]
|
// [.. repeat in the case of XMM src/dest operands ..]
|
||||||
//
|
//
|
||||||
const xImplSimd_DestRegEither WD;
|
const xImplSimd_DestRegEither WD;
|
||||||
|
|
||||||
// [sSSE-3] multiplies vertically each unsigned byte of dest with the corresponding
|
// [sSSE-3] multiplies vertically each unsigned byte of dest with the corresponding
|
||||||
// signed byte of src, producing intermediate signed 16-bit integers. Each adjacent
|
// signed byte of src, producing intermediate signed 16-bit integers. Each adjacent
|
||||||
// pair of signed words is added and the saturated result is packed to dest.
|
// pair of signed words is added and the saturated result is packed to dest.
|
||||||
// For example, the lowest-order bytes (bits 7-0) in src and dest are multiplied
|
// For example, the lowest-order bytes (bits 7-0) in src and dest are multiplied
|
||||||
// and the intermediate signed word result is added with the corresponding
|
// and the intermediate signed word result is added with the corresponding
|
||||||
// intermediate result from the 2nd lowest-order bytes (bits 15-8) of the operands;
|
// intermediate result from the 2nd lowest-order bytes (bits 15-8) of the operands;
|
||||||
// the sign-saturated result is stored in the lowest word of dest (bits 15-0).
|
// the sign-saturated result is stored in the lowest word of dest (bits 15-0).
|
||||||
// The same operation is performed on the other pairs of adjacent bytes.
|
// The same operation is performed on the other pairs of adjacent bytes.
|
||||||
//
|
//
|
||||||
// In Coder Speak:
|
// In Coder Speak:
|
||||||
// DEST[15-0] = SaturateToSignedWord( SRC[15-8] * DEST[15-8] + SRC[7-0] * DEST[7-0] );
|
// DEST[15-0] = SaturateToSignedWord( SRC[15-8] * DEST[15-8] + SRC[7-0] * DEST[7-0] );
|
||||||
// DEST[31-16] = SaturateToSignedWord( SRC[31-24] * DEST[31-24] + SRC[23-16] * DEST[23-16] );
|
// DEST[31-16] = SaturateToSignedWord( SRC[31-24] * DEST[31-24] + SRC[23-16] * DEST[23-16] );
|
||||||
// [.. repeat for each 16 bits up to 64 (mmx) or 128 (xmm) ..]
|
// [.. repeat for each 16 bits up to 64 (mmx) or 128 (xmm) ..]
|
||||||
//
|
//
|
||||||
const xImplSimd_DestRegEither UBSW;
|
const xImplSimd_DestRegEither UBSW;
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -218,21 +218,21 @@ struct xImplSimd_PMultAdd
|
||||||
//
|
//
|
||||||
struct xImplSimd_HorizAdd
|
struct xImplSimd_HorizAdd
|
||||||
{
|
{
|
||||||
// [SSE-3] Horizontal Add of Packed Data. A three step process:
|
// [SSE-3] Horizontal Add of Packed Data. A three step process:
|
||||||
// * Adds the single-precision floating-point values in the first and second dwords of
|
// * Adds the single-precision floating-point values in the first and second dwords of
|
||||||
// dest and stores the result in the first dword of dest.
|
// dest and stores the result in the first dword of dest.
|
||||||
// * Adds single-precision floating-point values in the third and fourth dword of dest
|
// * Adds single-precision floating-point values in the third and fourth dword of dest
|
||||||
// stores the result in the second dword of dest.
|
// stores the result in the second dword of dest.
|
||||||
// * Adds single-precision floating-point values in the first and second dword of *src*
|
// * Adds single-precision floating-point values in the first and second dword of *src*
|
||||||
// and stores the result in the third dword of dest.
|
// and stores the result in the third dword of dest.
|
||||||
const xImplSimd_DestRegSSE PS;
|
const xImplSimd_DestRegSSE PS;
|
||||||
|
|
||||||
// [SSE-3] Horizontal Add of Packed Data. A two step process:
|
// [SSE-3] Horizontal Add of Packed Data. A two step process:
|
||||||
// * Adds the double-precision floating-point values in the high and low quadwords of
|
// * Adds the double-precision floating-point values in the high and low quadwords of
|
||||||
// dest and stores the result in the low quadword of dest.
|
// dest and stores the result in the low quadword of dest.
|
||||||
// * Adds the double-precision floating-point values in the high and low quadwords of
|
// * Adds the double-precision floating-point values in the high and low quadwords of
|
||||||
// *src* stores the result in the high quadword of dest.
|
// *src* stores the result in the high quadword of dest.
|
||||||
const xImplSimd_DestRegSSE PD;
|
const xImplSimd_DestRegSSE PD;
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -240,23 +240,23 @@ struct xImplSimd_HorizAdd
|
||||||
//
|
//
|
||||||
struct xImplSimd_DotProduct
|
struct xImplSimd_DotProduct
|
||||||
{
|
{
|
||||||
// [SSE-4.1] Conditionally multiplies the packed single precision floating-point
|
// [SSE-4.1] Conditionally multiplies the packed single precision floating-point
|
||||||
// values in dest with the packed single-precision floats in src depending on a
|
// values in dest with the packed single-precision floats in src depending on a
|
||||||
// mask extracted from the high 4 bits of the immediate byte. If a condition mask
|
// mask extracted from the high 4 bits of the immediate byte. If a condition mask
|
||||||
// bit in Imm8[7:4] is zero, the corresponding multiplication is replaced by a value
|
// bit in Imm8[7:4] is zero, the corresponding multiplication is replaced by a value
|
||||||
// of 0.0. The four resulting single-precision values are summed into an inter-
|
// of 0.0. The four resulting single-precision values are summed into an inter-
|
||||||
// mediate result.
|
// mediate result.
|
||||||
//
|
//
|
||||||
// The intermediate result is conditionally broadcasted to the destination using a
|
// The intermediate result is conditionally broadcasted to the destination using a
|
||||||
// broadcast mask specified by bits [3:0] of the immediate byte. If a broadcast
|
// broadcast mask specified by bits [3:0] of the immediate byte. If a broadcast
|
||||||
// mask bit is 1, the intermediate result is copied to the corresponding dword
|
// mask bit is 1, the intermediate result is copied to the corresponding dword
|
||||||
// element in dest. If a broadcast mask bit is zero, the corresponding element in
|
// element in dest. If a broadcast mask bit is zero, the corresponding element in
|
||||||
// the destination is set to zero.
|
// the destination is set to zero.
|
||||||
//
|
//
|
||||||
xImplSimd_DestRegImmSSE PS;
|
xImplSimd_DestRegImmSSE PS;
|
||||||
|
|
||||||
// [SSE-4.1]
|
// [SSE-4.1]
|
||||||
xImplSimd_DestRegImmSSE PD;
|
xImplSimd_DestRegImmSSE PD;
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -264,54 +264,53 @@ struct xImplSimd_DotProduct
|
||||||
// (SSE4.1 only!)
|
// (SSE4.1 only!)
|
||||||
struct xImplSimd_Round
|
struct xImplSimd_Round
|
||||||
{
|
{
|
||||||
// [SSE-4.1] Rounds the 4 packed single-precision src values and stores them in dest.
|
// [SSE-4.1] Rounds the 4 packed single-precision src values and stores them in dest.
|
||||||
//
|
//
|
||||||
// Imm8 specifies control fields for the rounding operation:
|
// Imm8 specifies control fields for the rounding operation:
|
||||||
// Bit 3 - processor behavior for a precision exception (0: normal, 1: inexact)
|
// Bit 3 - processor behavior for a precision exception (0: normal, 1: inexact)
|
||||||
// Bit 2 - If enabled, use MXCSR.RC, else use RC specified in bits 1:0 of this Imm8.
|
// Bit 2 - If enabled, use MXCSR.RC, else use RC specified in bits 1:0 of this Imm8.
|
||||||
// Bits 1:0 - Specifies a rounding mode for this instruction only.
|
// Bits 1:0 - Specifies a rounding mode for this instruction only.
|
||||||
//
|
//
|
||||||
// Rounding Mode Reference:
|
// Rounding Mode Reference:
|
||||||
// 0 - Nearest, 1 - Negative Infinity, 2 - Positive infinity, 3 - Truncate.
|
// 0 - Nearest, 1 - Negative Infinity, 2 - Positive infinity, 3 - Truncate.
|
||||||
//
|
//
|
||||||
const xImplSimd_DestRegImmSSE PS;
|
const xImplSimd_DestRegImmSSE PS;
|
||||||
|
|
||||||
// [SSE-4.1] Rounds the 2 packed double-precision src values and stores them in dest.
|
// [SSE-4.1] Rounds the 2 packed double-precision src values and stores them in dest.
|
||||||
//
|
//
|
||||||
// Imm8 specifies control fields for the rounding operation:
|
// Imm8 specifies control fields for the rounding operation:
|
||||||
// Bit 3 - processor behavior for a precision exception (0: normal, 1: inexact)
|
// Bit 3 - processor behavior for a precision exception (0: normal, 1: inexact)
|
||||||
// Bit 2 - If enabled, use MXCSR.RC, else use RC specified in bits 1:0 of this Imm8.
|
// Bit 2 - If enabled, use MXCSR.RC, else use RC specified in bits 1:0 of this Imm8.
|
||||||
// Bits 1:0 - Specifies a rounding mode for this instruction only.
|
// Bits 1:0 - Specifies a rounding mode for this instruction only.
|
||||||
//
|
//
|
||||||
// Rounding Mode Reference:
|
// Rounding Mode Reference:
|
||||||
// 0 - Nearest, 1 - Negative Infinity, 2 - Positive infinity, 3 - Truncate.
|
// 0 - Nearest, 1 - Negative Infinity, 2 - Positive infinity, 3 - Truncate.
|
||||||
//
|
//
|
||||||
const xImplSimd_DestRegImmSSE PD;
|
const xImplSimd_DestRegImmSSE PD;
|
||||||
|
|
||||||
// [SSE-4.1] Rounds the single-precision src value and stores in dest.
|
// [SSE-4.1] Rounds the single-precision src value and stores in dest.
|
||||||
//
|
//
|
||||||
// Imm8 specifies control fields for the rounding operation:
|
// Imm8 specifies control fields for the rounding operation:
|
||||||
// Bit 3 - processor behavior for a precision exception (0: normal, 1: inexact)
|
// Bit 3 - processor behavior for a precision exception (0: normal, 1: inexact)
|
||||||
// Bit 2 - If enabled, use MXCSR.RC, else use RC specified in bits 1:0 of this Imm8.
|
// Bit 2 - If enabled, use MXCSR.RC, else use RC specified in bits 1:0 of this Imm8.
|
||||||
// Bits 1:0 - Specifies a rounding mode for this instruction only.
|
// Bits 1:0 - Specifies a rounding mode for this instruction only.
|
||||||
//
|
//
|
||||||
// Rounding Mode Reference:
|
// Rounding Mode Reference:
|
||||||
// 0 - Nearest, 1 - Negative Infinity, 2 - Positive infinity, 3 - Truncate.
|
// 0 - Nearest, 1 - Negative Infinity, 2 - Positive infinity, 3 - Truncate.
|
||||||
//
|
//
|
||||||
const xImplSimd_DestRegImmSSE SS;
|
const xImplSimd_DestRegImmSSE SS;
|
||||||
|
|
||||||
// [SSE-4.1] Rounds the double-precision src value and stores in dest.
|
// [SSE-4.1] Rounds the double-precision src value and stores in dest.
|
||||||
//
|
//
|
||||||
// Imm8 specifies control fields for the rounding operation:
|
// Imm8 specifies control fields for the rounding operation:
|
||||||
// Bit 3 - processor behavior for a precision exception (0: normal, 1: inexact)
|
// Bit 3 - processor behavior for a precision exception (0: normal, 1: inexact)
|
||||||
// Bit 2 - If enabled, use MXCSR.RC, else use RC specified in bits 1:0 of this Imm8.
|
// Bit 2 - If enabled, use MXCSR.RC, else use RC specified in bits 1:0 of this Imm8.
|
||||||
// Bits 1:0 - Specifies a rounding mode for this instruction only.
|
// Bits 1:0 - Specifies a rounding mode for this instruction only.
|
||||||
//
|
//
|
||||||
// Rounding Mode Reference:
|
// Rounding Mode Reference:
|
||||||
// 0 - Nearest, 1 - Negative Infinity, 2 - Positive infinity, 3 - Truncate.
|
// 0 - Nearest, 1 - Negative Infinity, 2 - Positive infinity, 3 - Truncate.
|
||||||
//
|
//
|
||||||
const xImplSimd_DestRegImmSSE SD;
|
const xImplSimd_DestRegImmSSE SD;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End namespace x86Emitter
|
} // End namespace x86Emitter
|
||||||
|
|
||||||
|
|
|
@ -15,33 +15,34 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace x86Emitter {
|
namespace x86Emitter
|
||||||
|
{
|
||||||
|
|
||||||
struct xImplSimd_MinMax
|
struct xImplSimd_MinMax
|
||||||
{
|
{
|
||||||
const xImplSimd_DestRegSSE PS; // packed single precision
|
const xImplSimd_DestRegSSE PS; // packed single precision
|
||||||
const xImplSimd_DestRegSSE PD; // packed double precision
|
const xImplSimd_DestRegSSE PD; // packed double precision
|
||||||
const xImplSimd_DestRegSSE SS; // scalar single precision
|
const xImplSimd_DestRegSSE SS; // scalar single precision
|
||||||
const xImplSimd_DestRegSSE SD; // scalar double precision
|
const xImplSimd_DestRegSSE SD; // scalar double precision
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
struct xImplSimd_Compare
|
struct xImplSimd_Compare
|
||||||
{
|
{
|
||||||
SSE2_ComparisonType CType;
|
SSE2_ComparisonType CType;
|
||||||
|
|
||||||
void PS( const xRegisterSSE& to, const xRegisterSSE& from ) const;
|
void PS(const xRegisterSSE &to, const xRegisterSSE &from) const;
|
||||||
void PS( const xRegisterSSE& to, const xIndirectVoid& from ) const;
|
void PS(const xRegisterSSE &to, const xIndirectVoid &from) const;
|
||||||
|
|
||||||
void PD( const xRegisterSSE& to, const xRegisterSSE& from ) const;
|
void PD(const xRegisterSSE &to, const xRegisterSSE &from) const;
|
||||||
void PD( const xRegisterSSE& to, const xIndirectVoid& from ) const;
|
void PD(const xRegisterSSE &to, const xIndirectVoid &from) const;
|
||||||
|
|
||||||
void SS( const xRegisterSSE& to, const xRegisterSSE& from ) const;
|
void SS(const xRegisterSSE &to, const xRegisterSSE &from) const;
|
||||||
void SS( const xRegisterSSE& to, const xIndirectVoid& from ) const;
|
void SS(const xRegisterSSE &to, const xIndirectVoid &from) const;
|
||||||
|
|
||||||
void SD( const xRegisterSSE& to, const xRegisterSSE& from ) const;
|
void SD(const xRegisterSSE &to, const xRegisterSSE &from) const;
|
||||||
void SD( const xRegisterSSE& to, const xIndirectVoid& from ) const;
|
void SD(const xRegisterSSE &to, const xIndirectVoid &from) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -49,8 +50,8 @@ struct xImplSimd_Compare
|
||||||
//
|
//
|
||||||
struct xImplSimd_COMI
|
struct xImplSimd_COMI
|
||||||
{
|
{
|
||||||
const xImplSimd_DestRegSSE SS;
|
const xImplSimd_DestRegSSE SS;
|
||||||
const xImplSimd_DestRegSSE SD;
|
const xImplSimd_DestRegSSE SD;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,65 +60,64 @@ struct xImplSimd_COMI
|
||||||
struct xImplSimd_PCompare
|
struct xImplSimd_PCompare
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// Compare packed bytes for equality.
|
// Compare packed bytes for equality.
|
||||||
// If a data element in dest is equal to the corresponding date element src, the
|
// If a data element in dest is equal to the corresponding date element src, the
|
||||||
// corresponding data element in dest is set to all 1s; otherwise, it is set to all 0s.
|
// corresponding data element in dest is set to all 1s; otherwise, it is set to all 0s.
|
||||||
const xImplSimd_DestRegEither EQB;
|
const xImplSimd_DestRegEither EQB;
|
||||||
|
|
||||||
// Compare packed words for equality.
|
// Compare packed words for equality.
|
||||||
// If a data element in dest is equal to the corresponding date element src, the
|
// If a data element in dest is equal to the corresponding date element src, the
|
||||||
// corresponding data element in dest is set to all 1s; otherwise, it is set to all 0s.
|
// corresponding data element in dest is set to all 1s; otherwise, it is set to all 0s.
|
||||||
const xImplSimd_DestRegEither EQW;
|
const xImplSimd_DestRegEither EQW;
|
||||||
|
|
||||||
// Compare packed doublewords [32-bits] for equality.
|
// Compare packed doublewords [32-bits] for equality.
|
||||||
// If a data element in dest is equal to the corresponding date element src, the
|
// If a data element in dest is equal to the corresponding date element src, the
|
||||||
// corresponding data element in dest is set to all 1s; otherwise, it is set to all 0s.
|
// corresponding data element in dest is set to all 1s; otherwise, it is set to all 0s.
|
||||||
const xImplSimd_DestRegEither EQD;
|
const xImplSimd_DestRegEither EQD;
|
||||||
|
|
||||||
// Compare packed signed bytes for greater than.
|
// Compare packed signed bytes for greater than.
|
||||||
// If a data element in dest is greater than the corresponding date element src, the
|
// If a data element in dest is greater than the corresponding date element src, the
|
||||||
// corresponding data element in dest is set to all 1s; otherwise, it is set to all 0s.
|
// corresponding data element in dest is set to all 1s; otherwise, it is set to all 0s.
|
||||||
const xImplSimd_DestRegEither GTB;
|
const xImplSimd_DestRegEither GTB;
|
||||||
|
|
||||||
// Compare packed signed words for greater than.
|
// Compare packed signed words for greater than.
|
||||||
// If a data element in dest is greater than the corresponding date element src, the
|
// If a data element in dest is greater than the corresponding date element src, the
|
||||||
// corresponding data element in dest is set to all 1s; otherwise, it is set to all 0s.
|
// corresponding data element in dest is set to all 1s; otherwise, it is set to all 0s.
|
||||||
const xImplSimd_DestRegEither GTW;
|
const xImplSimd_DestRegEither GTW;
|
||||||
|
|
||||||
// Compare packed signed doublewords [32-bits] for greater than.
|
// Compare packed signed doublewords [32-bits] for greater than.
|
||||||
// If a data element in dest is greater than the corresponding date element src, the
|
// If a data element in dest is greater than the corresponding date element src, the
|
||||||
// corresponding data element in dest is set to all 1s; otherwise, it is set to all 0s.
|
// corresponding data element in dest is set to all 1s; otherwise, it is set to all 0s.
|
||||||
const xImplSimd_DestRegEither GTD;
|
const xImplSimd_DestRegEither GTD;
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
struct xImplSimd_PMinMax
|
struct xImplSimd_PMinMax
|
||||||
{
|
{
|
||||||
// Compare packed unsigned byte integers in dest to src and store packed min/max
|
// Compare packed unsigned byte integers in dest to src and store packed min/max
|
||||||
// values in dest.
|
// values in dest.
|
||||||
const xImplSimd_DestRegEither UB;
|
const xImplSimd_DestRegEither UB;
|
||||||
|
|
||||||
// Compare packed signed word integers in dest to src and store packed min/max
|
// Compare packed signed word integers in dest to src and store packed min/max
|
||||||
// values in dest.
|
// values in dest.
|
||||||
const xImplSimd_DestRegEither SW;
|
const xImplSimd_DestRegEither SW;
|
||||||
|
|
||||||
// [SSE-4.1] Compare packed signed byte integers in dest to src and store
|
// [SSE-4.1] Compare packed signed byte integers in dest to src and store
|
||||||
// packed min/max values in dest. (SSE operands only)
|
// packed min/max values in dest. (SSE operands only)
|
||||||
const xImplSimd_DestRegSSE SB;
|
const xImplSimd_DestRegSSE SB;
|
||||||
|
|
||||||
// [SSE-4.1] Compare packed signed doubleword integers in dest to src and store
|
// [SSE-4.1] Compare packed signed doubleword integers in dest to src and store
|
||||||
// packed min/max values in dest. (SSE operands only)
|
// packed min/max values in dest. (SSE operands only)
|
||||||
const xImplSimd_DestRegSSE SD;
|
const xImplSimd_DestRegSSE SD;
|
||||||
|
|
||||||
// [SSE-4.1] Compare packed unsigned word integers in dest to src and store
|
// [SSE-4.1] Compare packed unsigned word integers in dest to src and store
|
||||||
// packed min/max values in dest. (SSE operands only)
|
// packed min/max values in dest. (SSE operands only)
|
||||||
const xImplSimd_DestRegSSE UW;
|
const xImplSimd_DestRegSSE UW;
|
||||||
|
|
||||||
// [SSE-4.1] Compare packed unsigned doubleword integers in dest to src and store
|
// [SSE-4.1] Compare packed unsigned doubleword integers in dest to src and store
|
||||||
// packed min/max values in dest. (SSE operands only)
|
// packed min/max values in dest. (SSE operands only)
|
||||||
const xImplSimd_DestRegSSE UD;
|
const xImplSimd_DestRegSSE UD;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace x86Emitter
|
} // end namespace x86Emitter
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace x86Emitter {
|
namespace x86Emitter
|
||||||
|
{
|
||||||
|
|
||||||
// =====================================================================================================
|
// =====================================================================================================
|
||||||
// xImpl_SIMD Types (template free!)
|
// xImpl_SIMD Types (template free!)
|
||||||
|
@ -27,11 +28,11 @@ namespace x86Emitter {
|
||||||
//
|
//
|
||||||
struct xImplSimd_DestRegSSE
|
struct xImplSimd_DestRegSSE
|
||||||
{
|
{
|
||||||
u8 Prefix;
|
u8 Prefix;
|
||||||
u16 Opcode;
|
u16 Opcode;
|
||||||
|
|
||||||
void operator()( const xRegisterSSE& to, const xRegisterSSE& from ) const;
|
void operator()(const xRegisterSSE &to, const xRegisterSSE &from) const;
|
||||||
void operator()( const xRegisterSSE& to, const xIndirectVoid& from ) const;
|
void operator()(const xRegisterSSE &to, const xIndirectVoid &from) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
@ -40,20 +41,20 @@ struct xImplSimd_DestRegSSE
|
||||||
//
|
//
|
||||||
struct xImplSimd_DestRegImmSSE
|
struct xImplSimd_DestRegImmSSE
|
||||||
{
|
{
|
||||||
u8 Prefix;
|
u8 Prefix;
|
||||||
u16 Opcode;
|
u16 Opcode;
|
||||||
|
|
||||||
void operator()( const xRegisterSSE& to, const xRegisterSSE& from, u8 imm ) const;
|
void operator()(const xRegisterSSE &to, const xRegisterSSE &from, u8 imm) const;
|
||||||
void operator()( const xRegisterSSE& to, const xIndirectVoid& from, u8 imm ) const;
|
void operator()(const xRegisterSSE &to, const xIndirectVoid &from, u8 imm) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct xImplSimd_DestSSE_CmpImm
|
struct xImplSimd_DestSSE_CmpImm
|
||||||
{
|
{
|
||||||
u8 Prefix;
|
u8 Prefix;
|
||||||
u16 Opcode;
|
u16 Opcode;
|
||||||
|
|
||||||
void operator()( const xRegisterSSE& to, const xRegisterSSE& from, SSE2_ComparisonType imm ) const;
|
void operator()(const xRegisterSSE &to, const xRegisterSSE &from, SSE2_ComparisonType imm) const;
|
||||||
void operator()( const xRegisterSSE& to, const xIndirectVoid& from, SSE2_ComparisonType imm ) const;
|
void operator()(const xRegisterSSE &to, const xIndirectVoid &from, SSE2_ComparisonType imm) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
@ -62,12 +63,11 @@ struct xImplSimd_DestSSE_CmpImm
|
||||||
//
|
//
|
||||||
struct xImplSimd_DestRegEither
|
struct xImplSimd_DestRegEither
|
||||||
{
|
{
|
||||||
u8 Prefix;
|
u8 Prefix;
|
||||||
u16 Opcode;
|
u16 Opcode;
|
||||||
|
|
||||||
void operator()( const xRegisterSSE& to, const xRegisterSSE& from ) const;
|
void operator()(const xRegisterSSE &to, const xRegisterSSE &from) const;
|
||||||
void operator()( const xRegisterSSE& to, const xIndirectVoid& from ) const;
|
void operator()(const xRegisterSSE &to, const xIndirectVoid &from) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace x86Emitter
|
} // end namespace x86Emitter
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace x86Emitter {
|
namespace x86Emitter
|
||||||
|
{
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// xImplSimd_MovHL
|
// xImplSimd_MovHL
|
||||||
|
@ -25,13 +26,13 @@ namespace x86Emitter {
|
||||||
//
|
//
|
||||||
struct xImplSimd_MovHL
|
struct xImplSimd_MovHL
|
||||||
{
|
{
|
||||||
u16 Opcode;
|
u16 Opcode;
|
||||||
|
|
||||||
void PS( const xRegisterSSE& to, const xIndirectVoid& from ) const;
|
void PS(const xRegisterSSE &to, const xIndirectVoid &from) const;
|
||||||
void PS( const xIndirectVoid& to, const xRegisterSSE& from ) const;
|
void PS(const xIndirectVoid &to, const xRegisterSSE &from) const;
|
||||||
|
|
||||||
void PD( const xRegisterSSE& to, const xIndirectVoid& from ) const;
|
void PD(const xRegisterSSE &to, const xIndirectVoid &from) const;
|
||||||
void PD( const xIndirectVoid& to, const xRegisterSSE& from ) const;
|
void PD(const xIndirectVoid &to, const xRegisterSSE &from) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -42,10 +43,10 @@ struct xImplSimd_MovHL
|
||||||
//
|
//
|
||||||
struct xImplSimd_MovHL_RtoR
|
struct xImplSimd_MovHL_RtoR
|
||||||
{
|
{
|
||||||
u16 Opcode;
|
u16 Opcode;
|
||||||
|
|
||||||
void PS( const xRegisterSSE& to, const xRegisterSSE& from ) const;
|
void PS(const xRegisterSSE &to, const xRegisterSSE &from) const;
|
||||||
void PD( const xRegisterSSE& to, const xRegisterSSE& from ) const;
|
void PD(const xRegisterSSE &to, const xRegisterSSE &from) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -59,12 +60,12 @@ struct xImplSimd_MovHL_RtoR
|
||||||
//
|
//
|
||||||
struct xImplSimd_MoveSSE
|
struct xImplSimd_MoveSSE
|
||||||
{
|
{
|
||||||
u8 Prefix;
|
u8 Prefix;
|
||||||
bool isAligned;
|
bool isAligned;
|
||||||
|
|
||||||
void operator()( const xRegisterSSE& to, const xRegisterSSE& from ) const;
|
void operator()(const xRegisterSSE &to, const xRegisterSSE &from) const;
|
||||||
void operator()( const xRegisterSSE& to, const xIndirectVoid& from ) const;
|
void operator()(const xRegisterSSE &to, const xIndirectVoid &from) const;
|
||||||
void operator()( const xIndirectVoid& to, const xRegisterSSE& from ) const;
|
void operator()(const xIndirectVoid &to, const xRegisterSSE &from) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -78,12 +79,12 @@ struct xImplSimd_MoveSSE
|
||||||
|
|
||||||
struct xImplSimd_MoveDQ
|
struct xImplSimd_MoveDQ
|
||||||
{
|
{
|
||||||
u8 Prefix;
|
u8 Prefix;
|
||||||
bool isAligned;
|
bool isAligned;
|
||||||
|
|
||||||
void operator()( const xRegisterSSE& to, const xRegisterSSE& from ) const;
|
void operator()(const xRegisterSSE &to, const xRegisterSSE &from) const;
|
||||||
void operator()( const xRegisterSSE& to, const xIndirectVoid& from ) const;
|
void operator()(const xRegisterSSE &to, const xIndirectVoid &from) const;
|
||||||
void operator()( const xIndirectVoid& to, const xRegisterSSE& from ) const;
|
void operator()(const xIndirectVoid &to, const xRegisterSSE &from) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -93,41 +94,41 @@ struct xImplSimd_MoveDQ
|
||||||
//
|
//
|
||||||
struct xImplSimd_Blend
|
struct xImplSimd_Blend
|
||||||
{
|
{
|
||||||
// [SSE-4.1] Conditionally copies dword values from src to dest, depending on the
|
// [SSE-4.1] Conditionally copies dword values from src to dest, depending on the
|
||||||
// mask bits in the immediate operand (bits [3:0]). Each mask bit corresponds to a
|
// mask bits in the immediate operand (bits [3:0]). Each mask bit corresponds to a
|
||||||
// dword element in a 128-bit operand.
|
// dword element in a 128-bit operand.
|
||||||
//
|
//
|
||||||
// If a mask bit is 1, then the corresponding dword in the source operand is copied
|
// If a mask bit is 1, then the corresponding dword in the source operand is copied
|
||||||
// to dest, else the dword element in dest is left unchanged.
|
// to dest, else the dword element in dest is left unchanged.
|
||||||
//
|
//
|
||||||
xImplSimd_DestRegImmSSE PS;
|
xImplSimd_DestRegImmSSE PS;
|
||||||
|
|
||||||
// [SSE-4.1] Conditionally copies quadword values from src to dest, depending on the
|
// [SSE-4.1] Conditionally copies quadword values from src to dest, depending on the
|
||||||
// mask bits in the immediate operand (bits [1:0]). Each mask bit corresponds to a
|
// mask bits in the immediate operand (bits [1:0]). Each mask bit corresponds to a
|
||||||
// quadword element in a 128-bit operand.
|
// quadword element in a 128-bit operand.
|
||||||
//
|
//
|
||||||
// If a mask bit is 1, then the corresponding dword in the source operand is copied
|
// If a mask bit is 1, then the corresponding dword in the source operand is copied
|
||||||
// to dest, else the dword element in dest is left unchanged.
|
// to dest, else the dword element in dest is left unchanged.
|
||||||
//
|
//
|
||||||
xImplSimd_DestRegImmSSE PD;
|
xImplSimd_DestRegImmSSE PD;
|
||||||
|
|
||||||
// [SSE-4.1] Conditionally copies dword values from src to dest, depending on the
|
// [SSE-4.1] Conditionally copies dword values from src to dest, depending on the
|
||||||
// mask (bits [3:0]) in XMM0 (yes, the fixed register). Each mask bit corresponds
|
// mask (bits [3:0]) in XMM0 (yes, the fixed register). Each mask bit corresponds
|
||||||
// to a dword element in the 128-bit operand.
|
// to a dword element in the 128-bit operand.
|
||||||
//
|
//
|
||||||
// If a mask bit is 1, then the corresponding dword in the source operand is copied
|
// If a mask bit is 1, then the corresponding dword in the source operand is copied
|
||||||
// to dest, else the dword element in dest is left unchanged.
|
// to dest, else the dword element in dest is left unchanged.
|
||||||
//
|
//
|
||||||
xImplSimd_DestRegSSE VPS;
|
xImplSimd_DestRegSSE VPS;
|
||||||
|
|
||||||
// [SSE-4.1] Conditionally copies quadword values from src to dest, depending on the
|
// [SSE-4.1] Conditionally copies quadword values from src to dest, depending on the
|
||||||
// mask (bits [1:0]) in XMM0 (yes, the fixed register). Each mask bit corresponds
|
// mask (bits [1:0]) in XMM0 (yes, the fixed register). Each mask bit corresponds
|
||||||
// to a quadword element in the 128-bit operand.
|
// to a quadword element in the 128-bit operand.
|
||||||
//
|
//
|
||||||
// If a mask bit is 1, then the corresponding dword in the source operand is copied
|
// If a mask bit is 1, then the corresponding dword in the source operand is copied
|
||||||
// to dest, else the dword element in dest is left unchanged.
|
// to dest, else the dword element in dest is left unchanged.
|
||||||
//
|
//
|
||||||
xImplSimd_DestRegSSE VPD;
|
xImplSimd_DestRegSSE VPD;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -137,38 +138,36 @@ struct xImplSimd_Blend
|
||||||
//
|
//
|
||||||
struct xImplSimd_PMove
|
struct xImplSimd_PMove
|
||||||
{
|
{
|
||||||
u16 OpcodeBase;
|
u16 OpcodeBase;
|
||||||
|
|
||||||
// [SSE-4.1] Zero/Sign-extend the low byte values in src into word integers
|
// [SSE-4.1] Zero/Sign-extend the low byte values in src into word integers
|
||||||
// and store them in dest.
|
// and store them in dest.
|
||||||
void BW( const xRegisterSSE& to, const xRegisterSSE& from ) const;
|
void BW(const xRegisterSSE &to, const xRegisterSSE &from) const;
|
||||||
void BW( const xRegisterSSE& to, const xIndirect64& from ) const;
|
void BW(const xRegisterSSE &to, const xIndirect64 &from) const;
|
||||||
|
|
||||||
// [SSE-4.1] Zero/Sign-extend the low byte values in src into dword integers
|
// [SSE-4.1] Zero/Sign-extend the low byte values in src into dword integers
|
||||||
// and store them in dest.
|
// and store them in dest.
|
||||||
void BD( const xRegisterSSE& to, const xRegisterSSE& from ) const;
|
void BD(const xRegisterSSE &to, const xRegisterSSE &from) const;
|
||||||
void BD( const xRegisterSSE& to, const xIndirect32& from ) const;
|
void BD(const xRegisterSSE &to, const xIndirect32 &from) const;
|
||||||
|
|
||||||
// [SSE-4.1] Zero/Sign-extend the low byte values in src into qword integers
|
// [SSE-4.1] Zero/Sign-extend the low byte values in src into qword integers
|
||||||
// and store them in dest.
|
// and store them in dest.
|
||||||
void BQ( const xRegisterSSE& to, const xRegisterSSE& from ) const;
|
void BQ(const xRegisterSSE &to, const xRegisterSSE &from) const;
|
||||||
void BQ( const xRegisterSSE& to, const xIndirect16& from ) const;
|
void BQ(const xRegisterSSE &to, const xIndirect16 &from) const;
|
||||||
|
|
||||||
// [SSE-4.1] Zero/Sign-extend the low word values in src into dword integers
|
// [SSE-4.1] Zero/Sign-extend the low word values in src into dword integers
|
||||||
// and store them in dest.
|
// and store them in dest.
|
||||||
void WD( const xRegisterSSE& to, const xRegisterSSE& from ) const;
|
void WD(const xRegisterSSE &to, const xRegisterSSE &from) const;
|
||||||
void WD( const xRegisterSSE& to, const xIndirect64& from ) const;
|
void WD(const xRegisterSSE &to, const xIndirect64 &from) const;
|
||||||
|
|
||||||
// [SSE-4.1] Zero/Sign-extend the low word values in src into qword integers
|
// [SSE-4.1] Zero/Sign-extend the low word values in src into qword integers
|
||||||
// and store them in dest.
|
// and store them in dest.
|
||||||
void WQ( const xRegisterSSE& to, const xRegisterSSE& from ) const;
|
void WQ(const xRegisterSSE &to, const xRegisterSSE &from) const;
|
||||||
void WQ( const xRegisterSSE& to, const xIndirect32& from ) const;
|
void WQ(const xRegisterSSE &to, const xIndirect32 &from) const;
|
||||||
|
|
||||||
// [SSE-4.1] Zero/Sign-extend the low dword values in src into qword integers
|
// [SSE-4.1] Zero/Sign-extend the low dword values in src into qword integers
|
||||||
// and store them in dest.
|
// and store them in dest.
|
||||||
void DQ( const xRegisterSSE& to, const xRegisterSSE& from ) const;
|
void DQ(const xRegisterSSE &to, const xRegisterSSE &from) const;
|
||||||
void DQ( const xRegisterSSE& to, const xIndirect64& from ) const;
|
void DQ(const xRegisterSSE &to, const xIndirect64 &from) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,20 +15,21 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace x86Emitter {
|
namespace x86Emitter
|
||||||
|
{
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// xImplSimd_Shuffle
|
// xImplSimd_Shuffle
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
struct xImplSimd_Shuffle
|
struct xImplSimd_Shuffle
|
||||||
{
|
{
|
||||||
inline void _selector_assertion_check( u8 selector ) const;
|
inline void _selector_assertion_check(u8 selector) const;
|
||||||
|
|
||||||
void PS( const xRegisterSSE& to, const xRegisterSSE& from, u8 selector ) const;
|
void PS(const xRegisterSSE &to, const xRegisterSSE &from, u8 selector) const;
|
||||||
void PS( const xRegisterSSE& to, const xIndirectVoid& from, u8 selector ) const;
|
void PS(const xRegisterSSE &to, const xIndirectVoid &from, u8 selector) const;
|
||||||
|
|
||||||
void PD( const xRegisterSSE& to, const xRegisterSSE& from, u8 selector ) const;
|
void PD(const xRegisterSSE &to, const xRegisterSSE &from, u8 selector) const;
|
||||||
void PD( const xRegisterSSE& to, const xIndirectVoid& from, u8 selector ) const;
|
void PD(const xRegisterSSE &to, const xIndirectVoid &from, u8 selector) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -36,33 +37,33 @@ struct xImplSimd_Shuffle
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
struct xImplSimd_PShuffle
|
struct xImplSimd_PShuffle
|
||||||
{
|
{
|
||||||
// Copies doublewords from src and inserts them into dest at dword locations selected
|
// Copies doublewords from src and inserts them into dest at dword locations selected
|
||||||
// with the order operand (8 bit immediate).
|
// with the order operand (8 bit immediate).
|
||||||
const xImplSimd_DestRegImmSSE D;
|
const xImplSimd_DestRegImmSSE D;
|
||||||
|
|
||||||
// Copies words from the low quadword of src and inserts them into the low quadword
|
// Copies words from the low quadword of src and inserts them into the low quadword
|
||||||
// of dest at word locations selected with the order operand (8 bit immediate).
|
// of dest at word locations selected with the order operand (8 bit immediate).
|
||||||
// The high quadword of src is copied to the high quadword of dest.
|
// The high quadword of src is copied to the high quadword of dest.
|
||||||
const xImplSimd_DestRegImmSSE LW;
|
const xImplSimd_DestRegImmSSE LW;
|
||||||
|
|
||||||
// Copies words from the high quadword of src and inserts them into the high quadword
|
// Copies words from the high quadword of src and inserts them into the high quadword
|
||||||
// of dest at word locations selected with the order operand (8 bit immediate).
|
// of dest at word locations selected with the order operand (8 bit immediate).
|
||||||
// The low quadword of src is copied to the low quadword of dest.
|
// The low quadword of src is copied to the low quadword of dest.
|
||||||
const xImplSimd_DestRegImmSSE HW;
|
const xImplSimd_DestRegImmSSE HW;
|
||||||
|
|
||||||
// [sSSE-3] Performs in-place shuffles of bytes in dest according to the shuffle
|
// [sSSE-3] Performs in-place shuffles of bytes in dest according to the shuffle
|
||||||
// control mask in src. If the most significant bit (bit[7]) of each byte of the
|
// control mask in src. If the most significant bit (bit[7]) of each byte of the
|
||||||
// shuffle control mask is set, then constant zero is written in the result byte.
|
// shuffle control mask is set, then constant zero is written in the result byte.
|
||||||
// Each byte in the shuffle control mask forms an index to permute the corresponding
|
// Each byte in the shuffle control mask forms an index to permute the corresponding
|
||||||
// byte in dest. The value of each index is the least significant 4 bits (128-bit
|
// byte in dest. The value of each index is the least significant 4 bits (128-bit
|
||||||
// operation) or 3 bits (64-bit operation) of the shuffle control byte.
|
// operation) or 3 bits (64-bit operation) of the shuffle control byte.
|
||||||
//
|
//
|
||||||
const xImplSimd_DestRegEither B;
|
const xImplSimd_DestRegEither B;
|
||||||
|
|
||||||
// below is my test bed for a new system, free of subclasses. Was supposed to improve intellisense
|
// below is my test bed for a new system, free of subclasses. Was supposed to improve intellisense
|
||||||
// but it doesn't (makes it worse). Will try again in MSVC 2010. --air
|
// but it doesn't (makes it worse). Will try again in MSVC 2010. --air
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// Copies words from src and inserts them into dest at word locations selected with
|
// Copies words from src and inserts them into dest at word locations selected with
|
||||||
// the order operand (8 bit immediate).
|
// the order operand (8 bit immediate).
|
||||||
|
|
||||||
|
@ -92,7 +93,7 @@ struct xImplSimd_PShuffle
|
||||||
//
|
//
|
||||||
void B( const xRegisterSSE& to, const xRegisterSSE& from ) const { OpWriteSSE( 0x66, 0x0038 ); }
|
void B( const xRegisterSSE& to, const xRegisterSSE& from ) const { OpWriteSSE( 0x66, 0x0038 ); }
|
||||||
void B( const xRegisterSSE& to, const xIndirectVoid& from ) const { OpWriteSSE( 0x66, 0x0038 ); }
|
void B( const xRegisterSSE& to, const xIndirectVoid& from ) const { OpWriteSSE( 0x66, 0x0038 ); }
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -100,23 +101,23 @@ struct xImplSimd_PShuffle
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
struct SimdImpl_PUnpack
|
struct SimdImpl_PUnpack
|
||||||
{
|
{
|
||||||
// Unpack and interleave low-order bytes from src and dest into dest.
|
// Unpack and interleave low-order bytes from src and dest into dest.
|
||||||
const xImplSimd_DestRegEither LBW;
|
const xImplSimd_DestRegEither LBW;
|
||||||
// Unpack and interleave low-order words from src and dest into dest.
|
// Unpack and interleave low-order words from src and dest into dest.
|
||||||
const xImplSimd_DestRegEither LWD;
|
const xImplSimd_DestRegEither LWD;
|
||||||
// Unpack and interleave low-order doublewords from src and dest into dest.
|
// Unpack and interleave low-order doublewords from src and dest into dest.
|
||||||
const xImplSimd_DestRegEither LDQ;
|
const xImplSimd_DestRegEither LDQ;
|
||||||
// Unpack and interleave low-order quadwords from src and dest into dest.
|
// Unpack and interleave low-order quadwords from src and dest into dest.
|
||||||
const xImplSimd_DestRegSSE LQDQ;
|
const xImplSimd_DestRegSSE LQDQ;
|
||||||
|
|
||||||
// Unpack and interleave high-order bytes from src and dest into dest.
|
// Unpack and interleave high-order bytes from src and dest into dest.
|
||||||
const xImplSimd_DestRegEither HBW;
|
const xImplSimd_DestRegEither HBW;
|
||||||
// Unpack and interleave high-order words from src and dest into dest.
|
// Unpack and interleave high-order words from src and dest into dest.
|
||||||
const xImplSimd_DestRegEither HWD;
|
const xImplSimd_DestRegEither HWD;
|
||||||
// Unpack and interleave high-order doublewords from src and dest into dest.
|
// Unpack and interleave high-order doublewords from src and dest into dest.
|
||||||
const xImplSimd_DestRegEither HDQ;
|
const xImplSimd_DestRegEither HDQ;
|
||||||
// Unpack and interleave high-order quadwords from src and dest into dest.
|
// Unpack and interleave high-order quadwords from src and dest into dest.
|
||||||
const xImplSimd_DestRegSSE HQDQ;
|
const xImplSimd_DestRegSSE HQDQ;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -126,21 +127,21 @@ struct SimdImpl_PUnpack
|
||||||
//
|
//
|
||||||
struct SimdImpl_Pack
|
struct SimdImpl_Pack
|
||||||
{
|
{
|
||||||
// Converts packed signed word integers from src and dest into packed signed
|
// Converts packed signed word integers from src and dest into packed signed
|
||||||
// byte integers in dest, using signed saturation.
|
// byte integers in dest, using signed saturation.
|
||||||
const xImplSimd_DestRegEither SSWB;
|
const xImplSimd_DestRegEither SSWB;
|
||||||
|
|
||||||
// Converts packed signed dword integers from src and dest into packed signed
|
// Converts packed signed dword integers from src and dest into packed signed
|
||||||
// word integers in dest, using signed saturation.
|
// word integers in dest, using signed saturation.
|
||||||
const xImplSimd_DestRegEither SSDW;
|
const xImplSimd_DestRegEither SSDW;
|
||||||
|
|
||||||
// Converts packed unsigned word integers from src and dest into packed unsigned
|
// Converts packed unsigned word integers from src and dest into packed unsigned
|
||||||
// byte integers in dest, using unsigned saturation.
|
// byte integers in dest, using unsigned saturation.
|
||||||
const xImplSimd_DestRegEither USWB;
|
const xImplSimd_DestRegEither USWB;
|
||||||
|
|
||||||
// [SSE-4.1] Converts packed unsigned dword integers from src and dest into packed
|
// [SSE-4.1] Converts packed unsigned dword integers from src and dest into packed
|
||||||
// unsigned word integers in dest, using signed saturation.
|
// unsigned word integers in dest, using signed saturation.
|
||||||
const xImplSimd_DestRegSSE USDW;
|
const xImplSimd_DestRegSSE USDW;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -148,50 +149,50 @@ struct SimdImpl_Pack
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
struct xImplSimd_Unpack
|
struct xImplSimd_Unpack
|
||||||
{
|
{
|
||||||
// Unpacks the high doubleword [single-precision] values from src and dest into
|
// Unpacks the high doubleword [single-precision] values from src and dest into
|
||||||
// dest, such that the result of dest looks like this:
|
// dest, such that the result of dest looks like this:
|
||||||
// dest[0] <- dest[2]
|
// dest[0] <- dest[2]
|
||||||
// dest[1] <- src[2]
|
// dest[1] <- src[2]
|
||||||
// dest[2] <- dest[3]
|
// dest[2] <- dest[3]
|
||||||
// dest[3] <- src[3]
|
// dest[3] <- src[3]
|
||||||
//
|
//
|
||||||
const xImplSimd_DestRegSSE HPS;
|
const xImplSimd_DestRegSSE HPS;
|
||||||
|
|
||||||
// Unpacks the high quadword [double-precision] values from src and dest into
|
// Unpacks the high quadword [double-precision] values from src and dest into
|
||||||
// dest, such that the result of dest looks like this:
|
// dest, such that the result of dest looks like this:
|
||||||
// dest.lo <- dest.hi
|
// dest.lo <- dest.hi
|
||||||
// dest.hi <- src.hi
|
// dest.hi <- src.hi
|
||||||
//
|
//
|
||||||
const xImplSimd_DestRegSSE HPD;
|
const xImplSimd_DestRegSSE HPD;
|
||||||
|
|
||||||
// Unpacks the low doubleword [single-precision] values from src and dest into
|
// Unpacks the low doubleword [single-precision] values from src and dest into
|
||||||
// dest, such that the result of dest looks like this:
|
// dest, such that the result of dest looks like this:
|
||||||
// dest[3] <- src[1]
|
// dest[3] <- src[1]
|
||||||
// dest[2] <- dest[1]
|
// dest[2] <- dest[1]
|
||||||
// dest[1] <- src[0]
|
// dest[1] <- src[0]
|
||||||
// dest[0] <- dest[0]
|
// dest[0] <- dest[0]
|
||||||
//
|
//
|
||||||
const xImplSimd_DestRegSSE LPS;
|
const xImplSimd_DestRegSSE LPS;
|
||||||
|
|
||||||
// Unpacks the low quadword [double-precision] values from src and dest into
|
// Unpacks the low quadword [double-precision] values from src and dest into
|
||||||
// dest, effectively moving the low portion of src into the upper portion of dest.
|
// dest, effectively moving the low portion of src into the upper portion of dest.
|
||||||
// The result of dest is loaded as such:
|
// The result of dest is loaded as such:
|
||||||
// dest.hi <- src.lo
|
// dest.hi <- src.lo
|
||||||
// dest.lo <- dest.lo [remains unchanged!]
|
// dest.lo <- dest.lo [remains unchanged!]
|
||||||
//
|
//
|
||||||
const xImplSimd_DestRegSSE LPD;
|
const xImplSimd_DestRegSSE LPD;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct xImplSimd_InsertExtractHelper
|
struct xImplSimd_InsertExtractHelper
|
||||||
{
|
{
|
||||||
u16 Opcode;
|
u16 Opcode;
|
||||||
|
|
||||||
// [SSE-4.1] Allowed with SSE registers only (MMX regs are invalid)
|
// [SSE-4.1] Allowed with SSE registers only (MMX regs are invalid)
|
||||||
void operator()( const xRegisterSSE& to, const xRegister32& from, u8 imm8 ) const;
|
void operator()(const xRegisterSSE &to, const xRegister32 &from, u8 imm8) const;
|
||||||
|
|
||||||
// [SSE-4.1] Allowed with SSE registers only (MMX regs are invalid)
|
// [SSE-4.1] Allowed with SSE registers only (MMX regs are invalid)
|
||||||
void operator()( const xRegisterSSE& to, const xIndirectVoid& from, u8 imm8 ) const;
|
void operator()(const xRegisterSSE &to, const xIndirectVoid &from, u8 imm8) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -201,14 +202,14 @@ struct xImplSimd_InsertExtractHelper
|
||||||
//
|
//
|
||||||
struct xImplSimd_PInsert
|
struct xImplSimd_PInsert
|
||||||
{
|
{
|
||||||
void W( const xRegisterSSE& to, const xRegister32& from, u8 imm8 ) const;
|
void W(const xRegisterSSE &to, const xRegister32 &from, u8 imm8) const;
|
||||||
void W( const xRegisterSSE& to, const xIndirectVoid& from, u8 imm8 ) const;
|
void W(const xRegisterSSE &to, const xIndirectVoid &from, u8 imm8) const;
|
||||||
|
|
||||||
// [SSE-4.1] Allowed with SSE registers only (MMX regs are invalid)
|
// [SSE-4.1] Allowed with SSE registers only (MMX regs are invalid)
|
||||||
xImplSimd_InsertExtractHelper B;
|
xImplSimd_InsertExtractHelper B;
|
||||||
|
|
||||||
// [SSE-4.1] Allowed with SSE registers only (MMX regs are invalid)
|
// [SSE-4.1] Allowed with SSE registers only (MMX regs are invalid)
|
||||||
xImplSimd_InsertExtractHelper D;
|
xImplSimd_InsertExtractHelper D;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -219,23 +220,22 @@ struct xImplSimd_PInsert
|
||||||
//
|
//
|
||||||
struct SimdImpl_PExtract
|
struct SimdImpl_PExtract
|
||||||
{
|
{
|
||||||
// Copies the word element specified by imm8 from src to dest. The upper bits
|
// Copies the word element specified by imm8 from src to dest. The upper bits
|
||||||
// of dest are zero-extended (cleared). This can be used to extract any single packed
|
// of dest are zero-extended (cleared). This can be used to extract any single packed
|
||||||
// word value from src into an x86 32 bit register.
|
// word value from src into an x86 32 bit register.
|
||||||
//
|
//
|
||||||
// [SSE-4.1] Note: Indirect memory forms of this instruction are an SSE-4.1 extension!
|
// [SSE-4.1] Note: Indirect memory forms of this instruction are an SSE-4.1 extension!
|
||||||
//
|
//
|
||||||
void W( const xRegister32& to, const xRegisterSSE& from, u8 imm8 ) const;
|
void W(const xRegister32 &to, const xRegisterSSE &from, u8 imm8) const;
|
||||||
void W( const xIndirectVoid& dest, const xRegisterSSE& from, u8 imm8 ) const;
|
void W(const xIndirectVoid &dest, const xRegisterSSE &from, u8 imm8) const;
|
||||||
|
|
||||||
// [SSE-4.1] Copies the byte element specified by imm8 from src to dest. The upper bits
|
// [SSE-4.1] Copies the byte element specified by imm8 from src to dest. The upper bits
|
||||||
// of dest are zero-extended (cleared). This can be used to extract any single packed
|
// of dest are zero-extended (cleared). This can be used to extract any single packed
|
||||||
// byte value from src into an x86 32 bit register.
|
// byte value from src into an x86 32 bit register.
|
||||||
const xImplSimd_InsertExtractHelper B;
|
const xImplSimd_InsertExtractHelper B;
|
||||||
|
|
||||||
// [SSE-4.1] Copies the dword element specified by imm8 from src to dest. This can be
|
// [SSE-4.1] Copies the dword element specified by imm8 from src to dest. This can be
|
||||||
// used to extract any single packed dword value from src into an x86 32 bit register.
|
// used to extract any single packed dword value from src into an x86 32 bit register.
|
||||||
const xImplSimd_InsertExtractHelper D;
|
const xImplSimd_InsertExtractHelper D;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,17 +22,17 @@
|
||||||
// For implementing SSE-only logic operations that have xmmreg,xmmreg/rm forms only,
|
// For implementing SSE-only logic operations that have xmmreg,xmmreg/rm forms only,
|
||||||
// like ANDPS/ANDPD
|
// like ANDPS/ANDPD
|
||||||
//
|
//
|
||||||
template< u8 Prefix, u16 Opcode >
|
template <u8 Prefix, u16 Opcode>
|
||||||
class SimdImpl_DestRegSSE
|
class SimdImpl_DestRegSSE
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
__forceinline void operator()( const xRegisterSSE& to, const xRegisterSSE& from ) const { xOpWrite0F( Prefix, Opcode, to, from ); }
|
__forceinline void operator()(const xRegisterSSE &to, const xRegisterSSE &from) const { xOpWrite0F(Prefix, Opcode, to, from); }
|
||||||
__forceinline void operator()( const xRegisterSSE& to, const ModSibBase& from ) const
|
__forceinline void operator()(const xRegisterSSE &to, const ModSibBase &from) const
|
||||||
{
|
{
|
||||||
bool isReallyAligned = ((from.Displacement & 0x0f) == 0) && from.Index.IsEmpty() && from.Base.IsEmpty();
|
bool isReallyAligned = ((from.Displacement & 0x0f) == 0) && from.Index.IsEmpty() && from.Base.IsEmpty();
|
||||||
pxAssertDev( isReallyAligned, "Alignment check failed on SSE indirect load." );
|
pxAssertDev(isReallyAligned, "Alignment check failed on SSE indirect load.");
|
||||||
xOpWrite0F( Prefix, Opcode, to, from );
|
xOpWrite0F(Prefix, Opcode, to, from);
|
||||||
}
|
}
|
||||||
|
|
||||||
SimdImpl_DestRegSSE() {} //GCWho?
|
SimdImpl_DestRegSSE() {} //GCWho?
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,7 +17,8 @@
|
||||||
|
|
||||||
// Implementations found here: TEST + BTS/BT/BTC/BTR + BSF/BSR! (for lack of better location)
|
// Implementations found here: TEST + BTS/BT/BTC/BTR + BSF/BSR! (for lack of better location)
|
||||||
|
|
||||||
namespace x86Emitter {
|
namespace x86Emitter
|
||||||
|
{
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// xImpl_Test
|
// xImpl_Test
|
||||||
|
@ -25,17 +26,16 @@ namespace x86Emitter {
|
||||||
//
|
//
|
||||||
struct xImpl_Test
|
struct xImpl_Test
|
||||||
{
|
{
|
||||||
void operator()( const xRegisterInt& to, const xRegisterInt& from ) const;
|
void operator()(const xRegisterInt &to, const xRegisterInt &from) const;
|
||||||
void operator()( const xIndirect64orLess& dest, int imm ) const;
|
void operator()(const xIndirect64orLess &dest, int imm) const;
|
||||||
void operator()( const xRegisterInt& to, int imm ) const;
|
void operator()(const xRegisterInt &to, int imm) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum G8Type
|
enum G8Type {
|
||||||
{
|
G8Type_BT = 4,
|
||||||
G8Type_BT = 4,
|
G8Type_BTS,
|
||||||
G8Type_BTS,
|
G8Type_BTR,
|
||||||
G8Type_BTR,
|
G8Type_BTC,
|
||||||
G8Type_BTC,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -45,11 +45,11 @@ enum G8Type
|
||||||
//
|
//
|
||||||
struct xImpl_BitScan
|
struct xImpl_BitScan
|
||||||
{
|
{
|
||||||
// 0xbc [fwd] / 0xbd [rev]
|
// 0xbc [fwd] / 0xbd [rev]
|
||||||
u16 Opcode;
|
u16 Opcode;
|
||||||
|
|
||||||
void operator()( const xRegister16or32or64& to, const xRegister16or32or64& from ) const;
|
void operator()(const xRegister16or32or64 &to, const xRegister16or32or64 &from) const;
|
||||||
void operator()( const xRegister16or32or64& to, const xIndirectVoid& sibsrc ) const;
|
void operator()(const xRegister16or32or64 &to, const xIndirectVoid &sibsrc) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -59,17 +59,16 @@ struct xImpl_BitScan
|
||||||
//
|
//
|
||||||
struct xImpl_Group8
|
struct xImpl_Group8
|
||||||
{
|
{
|
||||||
G8Type InstType;
|
G8Type InstType;
|
||||||
|
|
||||||
void operator()( const xRegister16or32or64& bitbase, const xRegister16or32or64& bitoffset ) const;
|
void operator()(const xRegister16or32or64 &bitbase, const xRegister16or32or64 &bitoffset) const;
|
||||||
void operator()( const xRegister16or32or64& bitbase, u8 bitoffset ) const;
|
void operator()(const xRegister16or32or64 &bitbase, u8 bitoffset) const;
|
||||||
|
|
||||||
void operator()( const xIndirectVoid& bitbase, const xRegister16or32or64& bitoffset ) const;
|
void operator()(const xIndirectVoid &bitbase, const xRegister16or32or64 &bitoffset) const;
|
||||||
|
|
||||||
void operator()( const xIndirect64& bitbase, u8 bitoffset ) const;
|
void operator()(const xIndirect64 &bitbase, u8 bitoffset) const;
|
||||||
void operator()( const xIndirect32& bitbase, u8 bitoffset ) const;
|
void operator()(const xIndirect32 &bitbase, u8 bitoffset) const;
|
||||||
void operator()( const xIndirect16& bitbase, u8 bitoffset ) const;
|
void operator()(const xIndirect16 &bitbase, u8 bitoffset) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End namespace x86Emitter
|
} // End namespace x86Emitter
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,8 @@
|
||||||
// This header file is intended to be the future home of xchg, cmpxchg, xadd, and
|
// This header file is intended to be the future home of xchg, cmpxchg, xadd, and
|
||||||
// other threading-related exchange instructions.
|
// other threading-related exchange instructions.
|
||||||
|
|
||||||
namespace x86Emitter {
|
namespace x86Emitter
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
} // End namespace x86Emitter
|
} // End namespace x86Emitter
|
||||||
|
|
|
@ -32,472 +32,551 @@
|
||||||
|
|
||||||
namespace x86Emitter
|
namespace x86Emitter
|
||||||
{
|
{
|
||||||
extern void xStoreReg( const xRegisterSSE& src );
|
extern void xStoreReg(const xRegisterSSE &src);
|
||||||
extern void xRestoreReg( const xRegisterSSE& dest );
|
extern void xRestoreReg(const xRegisterSSE &dest);
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// Group 1 Instruction Class
|
// Group 1 Instruction Class
|
||||||
|
|
||||||
extern const xImpl_Group1 xADC;
|
extern const xImpl_Group1 xADC;
|
||||||
extern const xImpl_Group1 xSBB;
|
extern const xImpl_Group1 xSBB;
|
||||||
|
|
||||||
extern const xImpl_G1Logic xAND;
|
extern const xImpl_G1Logic xAND;
|
||||||
extern const xImpl_G1Logic xOR;
|
extern const xImpl_G1Logic xOR;
|
||||||
extern const xImpl_G1Logic xXOR;
|
extern const xImpl_G1Logic xXOR;
|
||||||
|
|
||||||
extern const xImpl_G1Arith xADD;
|
extern const xImpl_G1Arith xADD;
|
||||||
extern const xImpl_G1Arith xSUB;
|
extern const xImpl_G1Arith xSUB;
|
||||||
extern const xImpl_G1Compare xCMP;
|
extern const xImpl_G1Compare xCMP;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// Group 2 Instruction Class
|
// Group 2 Instruction Class
|
||||||
//
|
//
|
||||||
// Optimization Note: For Imm forms, we ignore the instruction if the shift count is
|
// Optimization Note: For Imm forms, we ignore the instruction if the shift count is
|
||||||
// zero. This is a safe optimization since any zero-value shift does not affect any
|
// zero. This is a safe optimization since any zero-value shift does not affect any
|
||||||
// flags.
|
// flags.
|
||||||
|
|
||||||
extern const xImpl_Mov xMOV;
|
extern const xImpl_Mov xMOV;
|
||||||
extern const xImpl_Test xTEST;
|
extern const xImpl_Test xTEST;
|
||||||
|
|
||||||
extern const xImpl_Group2 xROL, xROR,
|
extern const xImpl_Group2 xROL, xROR,
|
||||||
xRCL, xRCR,
|
xRCL, xRCR,
|
||||||
xSHL, xSHR,
|
xSHL, xSHR,
|
||||||
xSAR;
|
xSAR;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// Group 3 Instruction Class
|
// Group 3 Instruction Class
|
||||||
|
|
||||||
extern const xImpl_Group3 xNOT, xNEG;
|
extern const xImpl_Group3 xNOT, xNEG;
|
||||||
extern const xImpl_Group3 xUMUL, xUDIV;
|
extern const xImpl_Group3 xUMUL, xUDIV;
|
||||||
extern const xImpl_iDiv xDIV;
|
extern const xImpl_iDiv xDIV;
|
||||||
extern const xImpl_iMul xMUL;
|
extern const xImpl_iMul xMUL;
|
||||||
|
|
||||||
extern const xImpl_IncDec xINC, xDEC;
|
extern const xImpl_IncDec xINC, xDEC;
|
||||||
|
|
||||||
extern const xImpl_MovExtend xMOVZX, xMOVSX;
|
extern const xImpl_MovExtend xMOVZX, xMOVSX;
|
||||||
|
|
||||||
extern const xImpl_DwordShift xSHLD, xSHRD;
|
extern const xImpl_DwordShift xSHLD, xSHRD;
|
||||||
|
|
||||||
extern const xImpl_Group8 xBT;
|
extern const xImpl_Group8 xBT;
|
||||||
extern const xImpl_Group8 xBTR;
|
extern const xImpl_Group8 xBTR;
|
||||||
extern const xImpl_Group8 xBTS;
|
extern const xImpl_Group8 xBTS;
|
||||||
extern const xImpl_Group8 xBTC;
|
extern const xImpl_Group8 xBTC;
|
||||||
|
|
||||||
extern const xImpl_BitScan xBSF, xBSR;
|
extern const xImpl_BitScan xBSF, xBSR;
|
||||||
|
|
||||||
extern const xImpl_JmpCall xJMP;
|
extern const xImpl_JmpCall xJMP;
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
// 32 bits Call won't be compatible in 64 bits (different ABI)
|
// 32 bits Call won't be compatible in 64 bits (different ABI)
|
||||||
// Just a reminder to port the code
|
// Just a reminder to port the code
|
||||||
[[deprecated]] extern const xImpl_JmpCall xCALL;
|
[[deprecated]] extern const xImpl_JmpCall xCALL;
|
||||||
#else
|
#else
|
||||||
extern const xImpl_JmpCall xCALL;
|
extern const xImpl_JmpCall xCALL;
|
||||||
#endif
|
#endif
|
||||||
extern const xImpl_FastCall xFastCall;
|
extern const xImpl_FastCall xFastCall;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
extern const xImpl_CMov
|
|
||||||
xCMOVA, xCMOVAE,
|
|
||||||
xCMOVB, xCMOVBE,
|
|
||||||
xCMOVG, xCMOVGE,
|
|
||||||
xCMOVL, xCMOVLE,
|
|
||||||
|
|
||||||
xCMOVZ, xCMOVE,
|
|
||||||
xCMOVNZ, xCMOVNE,
|
|
||||||
xCMOVO, xCMOVNO,
|
|
||||||
xCMOVC, xCMOVNC,
|
|
||||||
|
|
||||||
xCMOVS, xCMOVNS,
|
|
||||||
xCMOVPE, xCMOVPO;
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
extern const xImpl_Set
|
|
||||||
xSETA, xSETAE,
|
|
||||||
xSETB, xSETBE,
|
|
||||||
xSETG, xSETGE,
|
|
||||||
xSETL, xSETLE,
|
|
||||||
|
|
||||||
xSETZ, xSETE,
|
|
||||||
xSETNZ, xSETNE,
|
|
||||||
xSETO, xSETNO,
|
|
||||||
xSETC, xSETNC,
|
|
||||||
|
|
||||||
xSETS, xSETNS,
|
|
||||||
xSETPE, xSETPO;
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// BMI extra instruction requires BMI1/BMI2
|
|
||||||
extern const xImplBMI_RVM xMULX, xPDEP, xPEXT, xANDN_S; // Warning xANDN is already used by SSE
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Miscellaneous Instructions
|
|
||||||
// These are all defined inline or in ix86.cpp.
|
|
||||||
//
|
|
||||||
|
|
||||||
extern void xBSWAP( const xRegister32or64& to );
|
|
||||||
|
|
||||||
// ----- Lea Instructions (Load Effective Address) -----
|
|
||||||
// Note: alternate (void*) forms of these instructions are not provided since those
|
|
||||||
// forms are functionally equivalent to Mov reg,imm, and thus better written as MOVs
|
|
||||||
// instead.
|
|
||||||
|
|
||||||
extern void xLEA( xRegister64 to, const xIndirectVoid& src, bool preserve_flags=false );
|
|
||||||
extern void xLEA( xRegister32 to, const xIndirectVoid& src, bool preserve_flags=false );
|
|
||||||
extern void xLEA( xRegister16 to, const xIndirectVoid& src, bool preserve_flags=false );
|
|
||||||
|
|
||||||
// ----- Push / Pop Instructions -----
|
|
||||||
// Note: pushad/popad implementations are intentionally left out. The instructions are
|
|
||||||
// invalid in x64, and are super slow on x32. Use multiple Push/Pop instructions instead.
|
|
||||||
|
|
||||||
extern void xPOP( const xIndirectVoid& from );
|
|
||||||
extern void xPUSH( const xIndirectVoid& from );
|
|
||||||
|
|
||||||
extern void xPOP( xRegister32or64 from );
|
|
||||||
|
|
||||||
extern void xPUSH( u32 imm );
|
|
||||||
extern void xPUSH( xRegister32or64 from );
|
|
||||||
|
|
||||||
// pushes the EFLAGS register onto the stack
|
|
||||||
extern void xPUSHFD();
|
|
||||||
// pops the EFLAGS register from the stack
|
|
||||||
extern void xPOPFD();
|
|
||||||
|
|
||||||
// ----- Miscellaneous Instructions -----
|
|
||||||
// Various Instructions with no parameter and no special encoding logic.
|
|
||||||
|
|
||||||
extern void xLEAVE();
|
|
||||||
extern void xRET();
|
|
||||||
extern void xCBW();
|
|
||||||
extern void xCWD();
|
|
||||||
extern void xCDQ();
|
|
||||||
extern void xCWDE();
|
|
||||||
|
|
||||||
extern void xLAHF();
|
|
||||||
extern void xSAHF();
|
|
||||||
|
|
||||||
extern void xSTC();
|
|
||||||
extern void xCLC();
|
|
||||||
|
|
||||||
// NOP 1-byte
|
|
||||||
extern void xNOP();
|
|
||||||
|
|
||||||
extern void xINT( u8 imm );
|
|
||||||
extern void xINTO();
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Helper object to handle the various functions ABI
|
|
||||||
class xScopedStackFrame
|
|
||||||
{
|
|
||||||
bool m_base_frame;
|
|
||||||
bool m_save_base_pointer;
|
|
||||||
int m_offset;
|
|
||||||
|
|
||||||
public:
|
|
||||||
xScopedStackFrame(bool base_frame, bool save_base_pointer = false, int offset = 0);
|
|
||||||
~xScopedStackFrame();
|
|
||||||
};
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// JMP / Jcc Instructions!
|
|
||||||
|
|
||||||
extern void xJcc( JccComparisonType comparison, const void* target );
|
|
||||||
extern s8* xJcc8( JccComparisonType comparison=Jcc_Unconditional, s8 displacement=0 );
|
|
||||||
extern s32* xJcc32( JccComparisonType comparison=Jcc_Unconditional, s32 displacement=0 );
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// Conditional jumps to fixed targets.
|
|
||||||
// Jumps accept any pointer as a valid target (function or data), and will generate either
|
|
||||||
// 8 or 32 bit displacement versions of the jump, depending on relative displacement of
|
|
||||||
// the target (efficient!)
|
|
||||||
//
|
|
||||||
|
|
||||||
template< typename T > __fi void xJE( T* func ) { xJcc( Jcc_Equal, (void*)(uptr)func ); }
|
|
||||||
template< typename T > __fi void xJZ( T* func ) { xJcc( Jcc_Zero, (void*)(uptr)func ); }
|
|
||||||
template< typename T > __fi void xJNE( T* func ) { xJcc( Jcc_NotEqual, (void*)(uptr)func ); }
|
|
||||||
template< typename T > __fi void xJNZ( T* func ) { xJcc( Jcc_NotZero, (void*)(uptr)func ); }
|
|
||||||
|
|
||||||
template< typename T > __fi void xJO( T* func ) { xJcc( Jcc_Overflow, (void*)(uptr)func ); }
|
|
||||||
template< typename T > __fi void xJNO( T* func ) { xJcc( Jcc_NotOverflow, (void*)(uptr)func ); }
|
|
||||||
template< typename T > __fi void xJC( T* func ) { xJcc( Jcc_Carry, (void*)(uptr)func ); }
|
|
||||||
template< typename T > __fi void xJNC( T* func ) { xJcc( Jcc_NotCarry, (void*)(uptr)func ); }
|
|
||||||
template< typename T > __fi void xJS( T* func ) { xJcc( Jcc_Signed, (void*)(uptr)func ); }
|
|
||||||
template< typename T > __fi void xJNS( T* func ) { xJcc( Jcc_Unsigned, (void*)(uptr)func ); }
|
|
||||||
|
|
||||||
template< typename T > __fi void xJPE( T* func ) { xJcc( Jcc_ParityEven, (void*)(uptr)func ); }
|
|
||||||
template< typename T > __fi void xJPO( T* func ) { xJcc( Jcc_ParityOdd, (void*)(uptr)func ); }
|
|
||||||
|
|
||||||
template< typename T > __fi void xJL( T* func ) { xJcc( Jcc_Less, (void*)(uptr)func ); }
|
|
||||||
template< typename T > __fi void xJLE( T* func ) { xJcc( Jcc_LessOrEqual, (void*)(uptr)func ); }
|
|
||||||
template< typename T > __fi void xJG( T* func ) { xJcc( Jcc_Greater, (void*)(uptr)func ); }
|
|
||||||
template< typename T > __fi void xJGE( T* func ) { xJcc( Jcc_GreaterOrEqual, (void*)(uptr)func ); }
|
|
||||||
|
|
||||||
template< typename T > __fi void xJB( T* func ) { xJcc( Jcc_Below, (void*)(uptr)func ); }
|
|
||||||
template< typename T > __fi void xJBE( T* func ) { xJcc( Jcc_BelowOrEqual, (void*)(uptr)func ); }
|
|
||||||
template< typename T > __fi void xJA( T* func ) { xJcc( Jcc_Above, (void*)(uptr)func ); }
|
|
||||||
template< typename T > __fi void xJAE( T* func ) { xJcc( Jcc_AboveOrEqual, (void*)(uptr)func ); }
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// Forward Jump Helpers (act as labels!)
|
|
||||||
|
|
||||||
#define DEFINE_FORWARD_JUMP( label, cond ) \
|
|
||||||
template< typename OperandType > \
|
|
||||||
class xForward##label : public xForwardJump<OperandType> \
|
|
||||||
{ \
|
|
||||||
public: \
|
|
||||||
xForward##label() : xForwardJump<OperandType>( cond ) {} \
|
|
||||||
};
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// Note: typedefs below are defined individually in order to appease Intellisense
|
|
||||||
// resolution. Including them into the class definition macro above breaks it.
|
|
||||||
|
|
||||||
typedef xForwardJump<s8> xForwardJump8;
|
|
||||||
typedef xForwardJump<s32> xForwardJump32;
|
|
||||||
|
|
||||||
DEFINE_FORWARD_JUMP( JA, Jcc_Above );
|
|
||||||
DEFINE_FORWARD_JUMP( JB, Jcc_Below );
|
|
||||||
DEFINE_FORWARD_JUMP( JAE, Jcc_AboveOrEqual );
|
|
||||||
DEFINE_FORWARD_JUMP( JBE, Jcc_BelowOrEqual );
|
|
||||||
|
|
||||||
typedef xForwardJA<s8> xForwardJA8;
|
|
||||||
typedef xForwardJA<s32> xForwardJA32;
|
|
||||||
typedef xForwardJB<s8> xForwardJB8;
|
|
||||||
typedef xForwardJB<s32> xForwardJB32;
|
|
||||||
typedef xForwardJAE<s8> xForwardJAE8;
|
|
||||||
typedef xForwardJAE<s32> xForwardJAE32;
|
|
||||||
typedef xForwardJBE<s8> xForwardJBE8;
|
|
||||||
typedef xForwardJBE<s32> xForwardJBE32;
|
|
||||||
|
|
||||||
DEFINE_FORWARD_JUMP( JG, Jcc_Greater );
|
|
||||||
DEFINE_FORWARD_JUMP( JL, Jcc_Less );
|
|
||||||
DEFINE_FORWARD_JUMP( JGE, Jcc_GreaterOrEqual );
|
|
||||||
DEFINE_FORWARD_JUMP( JLE, Jcc_LessOrEqual );
|
|
||||||
|
|
||||||
typedef xForwardJG<s8> xForwardJG8;
|
|
||||||
typedef xForwardJG<s32> xForwardJG32;
|
|
||||||
typedef xForwardJL<s8> xForwardJL8;
|
|
||||||
typedef xForwardJL<s32> xForwardJL32;
|
|
||||||
typedef xForwardJGE<s8> xForwardJGE8;
|
|
||||||
typedef xForwardJGE<s32> xForwardJGE32;
|
|
||||||
typedef xForwardJLE<s8> xForwardJLE8;
|
|
||||||
typedef xForwardJLE<s32> xForwardJLE32;
|
|
||||||
|
|
||||||
DEFINE_FORWARD_JUMP( JZ, Jcc_Zero );
|
|
||||||
DEFINE_FORWARD_JUMP( JE, Jcc_Equal );
|
|
||||||
DEFINE_FORWARD_JUMP( JNZ, Jcc_NotZero );
|
|
||||||
DEFINE_FORWARD_JUMP( JNE, Jcc_NotEqual );
|
|
||||||
|
|
||||||
typedef xForwardJZ<s8> xForwardJZ8;
|
|
||||||
typedef xForwardJZ<s32> xForwardJZ32;
|
|
||||||
typedef xForwardJE<s8> xForwardJE8;
|
|
||||||
typedef xForwardJE<s32> xForwardJE32;
|
|
||||||
typedef xForwardJNZ<s8> xForwardJNZ8;
|
|
||||||
typedef xForwardJNZ<s32> xForwardJNZ32;
|
|
||||||
typedef xForwardJNE<s8> xForwardJNE8;
|
|
||||||
typedef xForwardJNE<s32> xForwardJNE32;
|
|
||||||
|
|
||||||
DEFINE_FORWARD_JUMP( JS, Jcc_Signed );
|
|
||||||
DEFINE_FORWARD_JUMP( JNS, Jcc_Unsigned );
|
|
||||||
|
|
||||||
typedef xForwardJS<s8> xForwardJS8;
|
|
||||||
typedef xForwardJS<s32> xForwardJS32;
|
|
||||||
typedef xForwardJNS<s8> xForwardJNS8;
|
|
||||||
typedef xForwardJNS<s32> xForwardJNS32;
|
|
||||||
|
|
||||||
DEFINE_FORWARD_JUMP( JO, Jcc_Overflow );
|
|
||||||
DEFINE_FORWARD_JUMP( JNO, Jcc_NotOverflow );
|
|
||||||
|
|
||||||
typedef xForwardJO<s8> xForwardJO8;
|
|
||||||
typedef xForwardJO<s32> xForwardJO32;
|
|
||||||
typedef xForwardJNO<s8> xForwardJNO8;
|
|
||||||
typedef xForwardJNO<s32> xForwardJNO32;
|
|
||||||
|
|
||||||
DEFINE_FORWARD_JUMP( JC, Jcc_Carry );
|
|
||||||
DEFINE_FORWARD_JUMP( JNC, Jcc_NotCarry );
|
|
||||||
|
|
||||||
typedef xForwardJC<s8> xForwardJC8;
|
|
||||||
typedef xForwardJC<s32> xForwardJC32;
|
|
||||||
typedef xForwardJNC<s8> xForwardJNC8;
|
|
||||||
typedef xForwardJNC<s32> xForwardJNC32;
|
|
||||||
|
|
||||||
DEFINE_FORWARD_JUMP( JPE, Jcc_ParityEven );
|
|
||||||
DEFINE_FORWARD_JUMP( JPO, Jcc_ParityOdd );
|
|
||||||
|
|
||||||
typedef xForwardJPE<s8> xForwardJPE8;
|
|
||||||
typedef xForwardJPE<s32> xForwardJPE32;
|
|
||||||
typedef xForwardJPO<s8> xForwardJPO8;
|
|
||||||
typedef xForwardJPO<s32> xForwardJPO32;
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
|
|
||||||
extern void xEMMS();
|
|
||||||
extern void xSTMXCSR( const xIndirect32& dest );
|
|
||||||
extern void xLDMXCSR( const xIndirect32& src );
|
|
||||||
extern void xFXSAVE( const xIndirectVoid& dest );
|
|
||||||
extern void xFXRSTOR( const xIndirectVoid& src );
|
|
||||||
|
|
||||||
extern void xMOVDZX( const xRegisterSSE& to, const xRegister32or64& from );
|
|
||||||
extern void xMOVDZX( const xRegisterSSE& to, const xIndirectVoid& src );
|
|
||||||
|
|
||||||
extern void xMOVD( const xRegister32or64& to, const xRegisterSSE& from );
|
|
||||||
extern void xMOVD( const xIndirectVoid& dest, const xRegisterSSE& from );
|
|
||||||
|
|
||||||
extern void xMOVQ( const xIndirectVoid& dest, const xRegisterSSE& from );
|
|
||||||
|
|
||||||
extern void xMOVQZX( const xRegisterSSE& to, const xIndirectVoid& src );
|
|
||||||
extern void xMOVQZX( const xRegisterSSE& to, const xRegisterSSE& from );
|
|
||||||
|
|
||||||
extern void xMOVSS( const xRegisterSSE& to, const xRegisterSSE& from );
|
|
||||||
extern void xMOVSS( const xIndirectVoid& to, const xRegisterSSE& from );
|
|
||||||
extern void xMOVSD( const xRegisterSSE& to, const xRegisterSSE& from );
|
|
||||||
extern void xMOVSD( const xIndirectVoid& to, const xRegisterSSE& from );
|
|
||||||
|
|
||||||
extern void xMOVSSZX( const xRegisterSSE& to, const xIndirectVoid& from );
|
|
||||||
extern void xMOVSDZX( const xRegisterSSE& to, const xIndirectVoid& from );
|
|
||||||
|
|
||||||
extern void xMOVNTDQA( const xRegisterSSE& to, const xIndirectVoid& from );
|
|
||||||
extern void xMOVNTDQA( const xIndirectVoid& to, const xRegisterSSE& from );
|
|
||||||
|
|
||||||
extern void xMOVNTPD( const xIndirectVoid& to, const xRegisterSSE& from );
|
|
||||||
extern void xMOVNTPS( const xIndirectVoid& to, const xRegisterSSE& from );
|
|
||||||
|
|
||||||
extern void xMOVMSKPS( const xRegister32or64& to, const xRegisterSSE& from );
|
|
||||||
extern void xMOVMSKPD( const xRegister32or64& to, const xRegisterSSE& from );
|
|
||||||
|
|
||||||
extern void xMASKMOV( const xRegisterSSE& to, const xRegisterSSE& from );
|
|
||||||
extern void xPMOVMSKB( const xRegister32or64& to, const xRegisterSSE& from );
|
|
||||||
extern void xPALIGNR( const xRegisterSSE& to, const xRegisterSSE& from, u8 imm8 );
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
|
|
||||||
extern const xImplSimd_MoveSSE xMOVAPS;
|
|
||||||
extern const xImplSimd_MoveSSE xMOVUPS;
|
|
||||||
extern const xImplSimd_MoveSSE xMOVAPD;
|
|
||||||
extern const xImplSimd_MoveSSE xMOVUPD;
|
|
||||||
|
|
||||||
#ifdef ALWAYS_USE_MOVAPS
|
|
||||||
extern const xImplSimd_MoveSSE xMOVDQA;
|
|
||||||
extern const xImplSimd_MoveSSE xMOVDQU;
|
|
||||||
#else
|
|
||||||
extern const xImplSimd_MoveDQ xMOVDQA;
|
|
||||||
extern const xImplSimd_MoveDQ xMOVDQU;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern const xImplSimd_MovHL xMOVH;
|
|
||||||
extern const xImplSimd_MovHL xMOVL;
|
|
||||||
extern const xImplSimd_MovHL_RtoR xMOVLH;
|
|
||||||
extern const xImplSimd_MovHL_RtoR xMOVHL;
|
|
||||||
|
|
||||||
extern const xImplSimd_Blend xBLEND;
|
|
||||||
extern const xImplSimd_PMove xPMOVSX;
|
|
||||||
extern const xImplSimd_PMove xPMOVZX;
|
|
||||||
|
|
||||||
extern const xImplSimd_DestRegSSE xMOVSLDUP;
|
|
||||||
extern const xImplSimd_DestRegSSE xMOVSHDUP;
|
|
||||||
|
|
||||||
extern void xINSERTPS( const xRegisterSSE& to, const xRegisterSSE& from, u8 imm8 );
|
|
||||||
extern void xINSERTPS( const xRegisterSSE& to, const xIndirect32& from, u8 imm8 );
|
|
||||||
|
|
||||||
extern void xEXTRACTPS( const xRegister32or64& to, const xRegisterSSE& from, u8 imm8 );
|
|
||||||
extern void xEXTRACTPS( const xIndirect32& dest, const xRegisterSSE& from, u8 imm8 );
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
|
|
||||||
extern const xImplSimd_DestRegEither xPAND;
|
|
||||||
extern const xImplSimd_DestRegEither xPANDN;
|
|
||||||
extern const xImplSimd_DestRegEither xPOR;
|
|
||||||
extern const xImplSimd_DestRegEither xPXOR;
|
|
||||||
|
|
||||||
extern const xImplSimd_Shuffle xSHUF;
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
|
|
||||||
extern const xImplSimd_DestRegSSE xPTEST;
|
|
||||||
|
|
||||||
extern const xImplSimd_MinMax xMIN;
|
|
||||||
extern const xImplSimd_MinMax xMAX;
|
|
||||||
|
|
||||||
extern const xImplSimd_Compare xCMPEQ, xCMPLT,
|
|
||||||
xCMPLE, xCMPUNORD,
|
|
||||||
xCMPNE, xCMPNLT,
|
|
||||||
xCMPNLE,xCMPORD;
|
|
||||||
|
|
||||||
extern const xImplSimd_COMI xCOMI;
|
|
||||||
extern const xImplSimd_COMI xUCOMI;
|
|
||||||
|
|
||||||
extern const xImplSimd_PCompare xPCMP;
|
|
||||||
extern const xImplSimd_PMinMax xPMIN;
|
|
||||||
extern const xImplSimd_PMinMax xPMAX;
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
//
|
|
||||||
//
|
|
||||||
extern void xCVTDQ2PD( const xRegisterSSE& to, const xRegisterSSE& from );
|
|
||||||
extern void xCVTDQ2PD( const xRegisterSSE& to, const xIndirect64& from );
|
|
||||||
extern void xCVTDQ2PS( const xRegisterSSE& to, const xRegisterSSE& from );
|
|
||||||
extern void xCVTDQ2PS( const xRegisterSSE& to, const xIndirect128& from );
|
|
||||||
|
|
||||||
extern void xCVTPD2DQ( const xRegisterSSE& to, const xRegisterSSE& from );
|
|
||||||
extern void xCVTPD2DQ( const xRegisterSSE& to, const xIndirect128& from );
|
|
||||||
extern void xCVTPD2PS( const xRegisterSSE& to, const xRegisterSSE& from );
|
|
||||||
extern void xCVTPD2PS( const xRegisterSSE& to, const xIndirect128& from );
|
|
||||||
|
|
||||||
extern void xCVTPI2PD( const xRegisterSSE& to, const xIndirect64& from );
|
|
||||||
extern void xCVTPI2PS( const xRegisterSSE& to, const xIndirect64& from );
|
|
||||||
|
|
||||||
extern void xCVTPS2DQ( const xRegisterSSE& to, const xRegisterSSE& from );
|
|
||||||
extern void xCVTPS2DQ( const xRegisterSSE& to, const xIndirect128& from );
|
|
||||||
extern void xCVTPS2PD( const xRegisterSSE& to, const xRegisterSSE& from );
|
|
||||||
extern void xCVTPS2PD( const xRegisterSSE& to, const xIndirect64& from );
|
|
||||||
|
|
||||||
extern void xCVTSD2SI( const xRegister32or64& to, const xRegisterSSE& from );
|
|
||||||
extern void xCVTSD2SI( const xRegister32or64& to, const xIndirect64& from );
|
|
||||||
extern void xCVTSD2SS( const xRegisterSSE& to, const xRegisterSSE& from );
|
|
||||||
extern void xCVTSD2SS( const xRegisterSSE& to, const xIndirect64& from );
|
|
||||||
extern void xCVTSI2SS( const xRegisterSSE& to, const xRegister32or64& from );
|
|
||||||
extern void xCVTSI2SS( const xRegisterSSE& to, const xIndirect32& from );
|
|
||||||
|
|
||||||
extern void xCVTSS2SD( const xRegisterSSE& to, const xRegisterSSE& from );
|
|
||||||
extern void xCVTSS2SD( const xRegisterSSE& to, const xIndirect32& from );
|
|
||||||
extern void xCVTSS2SI( const xRegister32or64& to, const xRegisterSSE& from );
|
|
||||||
extern void xCVTSS2SI( const xRegister32or64& to, const xIndirect32& from );
|
|
||||||
|
|
||||||
extern void xCVTTPD2DQ( const xRegisterSSE& to, const xRegisterSSE& from );
|
|
||||||
extern void xCVTTPD2DQ( const xRegisterSSE& to, const xIndirect128& from );
|
|
||||||
extern void xCVTTPS2DQ( const xRegisterSSE& to, const xRegisterSSE& from );
|
|
||||||
extern void xCVTTPS2DQ( const xRegisterSSE& to, const xIndirect128& from );
|
|
||||||
|
|
||||||
extern void xCVTTSD2SI( const xRegister32or64& to, const xRegisterSSE& from );
|
|
||||||
extern void xCVTTSD2SI( const xRegister32or64& to, const xIndirect64& from );
|
|
||||||
extern void xCVTTSS2SI( const xRegister32or64& to, const xRegisterSSE& from );
|
|
||||||
extern void xCVTTSS2SI( const xRegister32or64& to, const xIndirect32& from );
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
|
|
||||||
extern const xImplSimd_AndNot xANDN;
|
|
||||||
extern const xImplSimd_rSqrt xRCP;
|
|
||||||
extern const xImplSimd_rSqrt xRSQRT;
|
|
||||||
extern const xImplSimd_Sqrt xSQRT;
|
|
||||||
|
|
||||||
extern const xImplSimd_Shift xPSLL;
|
|
||||||
extern const xImplSimd_Shift xPSRL;
|
|
||||||
extern const xImplSimd_ShiftWithoutQ xPSRA;
|
|
||||||
extern const xImplSimd_AddSub xPADD;
|
|
||||||
extern const xImplSimd_AddSub xPSUB;
|
|
||||||
extern const xImplSimd_PMul xPMUL;
|
|
||||||
extern const xImplSimd_PAbsolute xPABS;
|
|
||||||
extern const xImplSimd_PSign xPSIGN;
|
|
||||||
extern const xImplSimd_PMultAdd xPMADD;
|
|
||||||
extern const xImplSimd_HorizAdd xHADD;
|
|
||||||
extern const xImplSimd_DotProduct xDP;
|
|
||||||
extern const xImplSimd_Round xROUND;
|
|
||||||
|
|
||||||
extern const xImplSimd_PShuffle xPSHUF;
|
|
||||||
extern const SimdImpl_PUnpack xPUNPCK;
|
|
||||||
extern const xImplSimd_Unpack xUNPCK;
|
|
||||||
extern const SimdImpl_Pack xPACK;
|
|
||||||
extern const xImplSimd_PInsert xPINSR;
|
|
||||||
extern const SimdImpl_PExtract xPEXTR;
|
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
extern const xImpl_CMov xCMOVA, xCMOVAE,
|
||||||
|
xCMOVB, xCMOVBE,
|
||||||
|
xCMOVG, xCMOVGE,
|
||||||
|
xCMOVL, xCMOVLE,
|
||||||
|
|
||||||
|
xCMOVZ, xCMOVE,
|
||||||
|
xCMOVNZ, xCMOVNE,
|
||||||
|
xCMOVO, xCMOVNO,
|
||||||
|
xCMOVC, xCMOVNC,
|
||||||
|
|
||||||
|
xCMOVS, xCMOVNS,
|
||||||
|
xCMOVPE, xCMOVPO;
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
extern const xImpl_Set xSETA, xSETAE,
|
||||||
|
xSETB, xSETBE,
|
||||||
|
xSETG, xSETGE,
|
||||||
|
xSETL, xSETLE,
|
||||||
|
|
||||||
|
xSETZ, xSETE,
|
||||||
|
xSETNZ, xSETNE,
|
||||||
|
xSETO, xSETNO,
|
||||||
|
xSETC, xSETNC,
|
||||||
|
|
||||||
|
xSETS, xSETNS,
|
||||||
|
xSETPE, xSETPO;
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// BMI extra instruction requires BMI1/BMI2
|
||||||
|
extern const xImplBMI_RVM xMULX, xPDEP, xPEXT, xANDN_S; // Warning xANDN is already used by SSE
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Miscellaneous Instructions
|
||||||
|
// These are all defined inline or in ix86.cpp.
|
||||||
|
//
|
||||||
|
|
||||||
|
extern void xBSWAP(const xRegister32or64 &to);
|
||||||
|
|
||||||
|
// ----- Lea Instructions (Load Effective Address) -----
|
||||||
|
// Note: alternate (void*) forms of these instructions are not provided since those
|
||||||
|
// forms are functionally equivalent to Mov reg,imm, and thus better written as MOVs
|
||||||
|
// instead.
|
||||||
|
|
||||||
|
extern void xLEA(xRegister64 to, const xIndirectVoid &src, bool preserve_flags = false);
|
||||||
|
extern void xLEA(xRegister32 to, const xIndirectVoid &src, bool preserve_flags = false);
|
||||||
|
extern void xLEA(xRegister16 to, const xIndirectVoid &src, bool preserve_flags = false);
|
||||||
|
|
||||||
|
// ----- Push / Pop Instructions -----
|
||||||
|
// Note: pushad/popad implementations are intentionally left out. The instructions are
|
||||||
|
// invalid in x64, and are super slow on x32. Use multiple Push/Pop instructions instead.
|
||||||
|
|
||||||
|
extern void xPOP(const xIndirectVoid &from);
|
||||||
|
extern void xPUSH(const xIndirectVoid &from);
|
||||||
|
|
||||||
|
extern void xPOP(xRegister32or64 from);
|
||||||
|
|
||||||
|
extern void xPUSH(u32 imm);
|
||||||
|
extern void xPUSH(xRegister32or64 from);
|
||||||
|
|
||||||
|
// pushes the EFLAGS register onto the stack
|
||||||
|
extern void xPUSHFD();
|
||||||
|
// pops the EFLAGS register from the stack
|
||||||
|
extern void xPOPFD();
|
||||||
|
|
||||||
|
// ----- Miscellaneous Instructions -----
|
||||||
|
// Various Instructions with no parameter and no special encoding logic.
|
||||||
|
|
||||||
|
extern void xLEAVE();
|
||||||
|
extern void xRET();
|
||||||
|
extern void xCBW();
|
||||||
|
extern void xCWD();
|
||||||
|
extern void xCDQ();
|
||||||
|
extern void xCWDE();
|
||||||
|
|
||||||
|
extern void xLAHF();
|
||||||
|
extern void xSAHF();
|
||||||
|
|
||||||
|
extern void xSTC();
|
||||||
|
extern void xCLC();
|
||||||
|
|
||||||
|
// NOP 1-byte
|
||||||
|
extern void xNOP();
|
||||||
|
|
||||||
|
extern void xINT(u8 imm);
|
||||||
|
extern void xINTO();
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Helper object to handle the various functions ABI
|
||||||
|
class xScopedStackFrame
|
||||||
|
{
|
||||||
|
bool m_base_frame;
|
||||||
|
bool m_save_base_pointer;
|
||||||
|
int m_offset;
|
||||||
|
|
||||||
|
public:
|
||||||
|
xScopedStackFrame(bool base_frame, bool save_base_pointer = false, int offset = 0);
|
||||||
|
~xScopedStackFrame();
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// JMP / Jcc Instructions!
|
||||||
|
|
||||||
|
extern void xJcc(JccComparisonType comparison, const void *target);
|
||||||
|
extern s8 *xJcc8(JccComparisonType comparison = Jcc_Unconditional, s8 displacement = 0);
|
||||||
|
extern s32 *xJcc32(JccComparisonType comparison = Jcc_Unconditional, s32 displacement = 0);
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// Conditional jumps to fixed targets.
|
||||||
|
// Jumps accept any pointer as a valid target (function or data), and will generate either
|
||||||
|
// 8 or 32 bit displacement versions of the jump, depending on relative displacement of
|
||||||
|
// the target (efficient!)
|
||||||
|
//
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
__fi void xJE(T *func)
|
||||||
|
{
|
||||||
|
xJcc(Jcc_Equal, (void *)(uptr)func);
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
__fi void xJZ(T *func)
|
||||||
|
{
|
||||||
|
xJcc(Jcc_Zero, (void *)(uptr)func);
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
__fi void xJNE(T *func)
|
||||||
|
{
|
||||||
|
xJcc(Jcc_NotEqual, (void *)(uptr)func);
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
__fi void xJNZ(T *func)
|
||||||
|
{
|
||||||
|
xJcc(Jcc_NotZero, (void *)(uptr)func);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
__fi void xJO(T *func)
|
||||||
|
{
|
||||||
|
xJcc(Jcc_Overflow, (void *)(uptr)func);
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
__fi void xJNO(T *func)
|
||||||
|
{
|
||||||
|
xJcc(Jcc_NotOverflow, (void *)(uptr)func);
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
__fi void xJC(T *func)
|
||||||
|
{
|
||||||
|
xJcc(Jcc_Carry, (void *)(uptr)func);
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
__fi void xJNC(T *func)
|
||||||
|
{
|
||||||
|
xJcc(Jcc_NotCarry, (void *)(uptr)func);
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
__fi void xJS(T *func)
|
||||||
|
{
|
||||||
|
xJcc(Jcc_Signed, (void *)(uptr)func);
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
__fi void xJNS(T *func)
|
||||||
|
{
|
||||||
|
xJcc(Jcc_Unsigned, (void *)(uptr)func);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
__fi void xJPE(T *func)
|
||||||
|
{
|
||||||
|
xJcc(Jcc_ParityEven, (void *)(uptr)func);
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
__fi void xJPO(T *func)
|
||||||
|
{
|
||||||
|
xJcc(Jcc_ParityOdd, (void *)(uptr)func);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
__fi void xJL(T *func)
|
||||||
|
{
|
||||||
|
xJcc(Jcc_Less, (void *)(uptr)func);
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
__fi void xJLE(T *func)
|
||||||
|
{
|
||||||
|
xJcc(Jcc_LessOrEqual, (void *)(uptr)func);
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
__fi void xJG(T *func)
|
||||||
|
{
|
||||||
|
xJcc(Jcc_Greater, (void *)(uptr)func);
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
__fi void xJGE(T *func)
|
||||||
|
{
|
||||||
|
xJcc(Jcc_GreaterOrEqual, (void *)(uptr)func);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
__fi void xJB(T *func)
|
||||||
|
{
|
||||||
|
xJcc(Jcc_Below, (void *)(uptr)func);
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
__fi void xJBE(T *func)
|
||||||
|
{
|
||||||
|
xJcc(Jcc_BelowOrEqual, (void *)(uptr)func);
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
__fi void xJA(T *func)
|
||||||
|
{
|
||||||
|
xJcc(Jcc_Above, (void *)(uptr)func);
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
__fi void xJAE(T *func)
|
||||||
|
{
|
||||||
|
xJcc(Jcc_AboveOrEqual, (void *)(uptr)func);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// Forward Jump Helpers (act as labels!)
|
||||||
|
|
||||||
|
#define DEFINE_FORWARD_JUMP(label, cond) \
|
||||||
|
template <typename OperandType> \
|
||||||
|
class xForward##label : public xForwardJump<OperandType> \
|
||||||
|
{ \
|
||||||
|
public: \
|
||||||
|
xForward##label() \
|
||||||
|
: xForwardJump<OperandType>(cond) \
|
||||||
|
{ \
|
||||||
|
} \
|
||||||
|
};
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// Note: typedefs below are defined individually in order to appease Intellisense
|
||||||
|
// resolution. Including them into the class definition macro above breaks it.
|
||||||
|
|
||||||
|
typedef xForwardJump<s8> xForwardJump8;
|
||||||
|
typedef xForwardJump<s32> xForwardJump32;
|
||||||
|
|
||||||
|
DEFINE_FORWARD_JUMP(JA, Jcc_Above);
|
||||||
|
DEFINE_FORWARD_JUMP(JB, Jcc_Below);
|
||||||
|
DEFINE_FORWARD_JUMP(JAE, Jcc_AboveOrEqual);
|
||||||
|
DEFINE_FORWARD_JUMP(JBE, Jcc_BelowOrEqual);
|
||||||
|
|
||||||
|
typedef xForwardJA<s8> xForwardJA8;
|
||||||
|
typedef xForwardJA<s32> xForwardJA32;
|
||||||
|
typedef xForwardJB<s8> xForwardJB8;
|
||||||
|
typedef xForwardJB<s32> xForwardJB32;
|
||||||
|
typedef xForwardJAE<s8> xForwardJAE8;
|
||||||
|
typedef xForwardJAE<s32> xForwardJAE32;
|
||||||
|
typedef xForwardJBE<s8> xForwardJBE8;
|
||||||
|
typedef xForwardJBE<s32> xForwardJBE32;
|
||||||
|
|
||||||
|
DEFINE_FORWARD_JUMP(JG, Jcc_Greater);
|
||||||
|
DEFINE_FORWARD_JUMP(JL, Jcc_Less);
|
||||||
|
DEFINE_FORWARD_JUMP(JGE, Jcc_GreaterOrEqual);
|
||||||
|
DEFINE_FORWARD_JUMP(JLE, Jcc_LessOrEqual);
|
||||||
|
|
||||||
|
typedef xForwardJG<s8> xForwardJG8;
|
||||||
|
typedef xForwardJG<s32> xForwardJG32;
|
||||||
|
typedef xForwardJL<s8> xForwardJL8;
|
||||||
|
typedef xForwardJL<s32> xForwardJL32;
|
||||||
|
typedef xForwardJGE<s8> xForwardJGE8;
|
||||||
|
typedef xForwardJGE<s32> xForwardJGE32;
|
||||||
|
typedef xForwardJLE<s8> xForwardJLE8;
|
||||||
|
typedef xForwardJLE<s32> xForwardJLE32;
|
||||||
|
|
||||||
|
DEFINE_FORWARD_JUMP(JZ, Jcc_Zero);
|
||||||
|
DEFINE_FORWARD_JUMP(JE, Jcc_Equal);
|
||||||
|
DEFINE_FORWARD_JUMP(JNZ, Jcc_NotZero);
|
||||||
|
DEFINE_FORWARD_JUMP(JNE, Jcc_NotEqual);
|
||||||
|
|
||||||
|
typedef xForwardJZ<s8> xForwardJZ8;
|
||||||
|
typedef xForwardJZ<s32> xForwardJZ32;
|
||||||
|
typedef xForwardJE<s8> xForwardJE8;
|
||||||
|
typedef xForwardJE<s32> xForwardJE32;
|
||||||
|
typedef xForwardJNZ<s8> xForwardJNZ8;
|
||||||
|
typedef xForwardJNZ<s32> xForwardJNZ32;
|
||||||
|
typedef xForwardJNE<s8> xForwardJNE8;
|
||||||
|
typedef xForwardJNE<s32> xForwardJNE32;
|
||||||
|
|
||||||
|
DEFINE_FORWARD_JUMP(JS, Jcc_Signed);
|
||||||
|
DEFINE_FORWARD_JUMP(JNS, Jcc_Unsigned);
|
||||||
|
|
||||||
|
typedef xForwardJS<s8> xForwardJS8;
|
||||||
|
typedef xForwardJS<s32> xForwardJS32;
|
||||||
|
typedef xForwardJNS<s8> xForwardJNS8;
|
||||||
|
typedef xForwardJNS<s32> xForwardJNS32;
|
||||||
|
|
||||||
|
DEFINE_FORWARD_JUMP(JO, Jcc_Overflow);
|
||||||
|
DEFINE_FORWARD_JUMP(JNO, Jcc_NotOverflow);
|
||||||
|
|
||||||
|
typedef xForwardJO<s8> xForwardJO8;
|
||||||
|
typedef xForwardJO<s32> xForwardJO32;
|
||||||
|
typedef xForwardJNO<s8> xForwardJNO8;
|
||||||
|
typedef xForwardJNO<s32> xForwardJNO32;
|
||||||
|
|
||||||
|
DEFINE_FORWARD_JUMP(JC, Jcc_Carry);
|
||||||
|
DEFINE_FORWARD_JUMP(JNC, Jcc_NotCarry);
|
||||||
|
|
||||||
|
typedef xForwardJC<s8> xForwardJC8;
|
||||||
|
typedef xForwardJC<s32> xForwardJC32;
|
||||||
|
typedef xForwardJNC<s8> xForwardJNC8;
|
||||||
|
typedef xForwardJNC<s32> xForwardJNC32;
|
||||||
|
|
||||||
|
DEFINE_FORWARD_JUMP(JPE, Jcc_ParityEven);
|
||||||
|
DEFINE_FORWARD_JUMP(JPO, Jcc_ParityOdd);
|
||||||
|
|
||||||
|
typedef xForwardJPE<s8> xForwardJPE8;
|
||||||
|
typedef xForwardJPE<s32> xForwardJPE32;
|
||||||
|
typedef xForwardJPO<s8> xForwardJPO8;
|
||||||
|
typedef xForwardJPO<s32> xForwardJPO32;
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
|
extern void xEMMS();
|
||||||
|
extern void xSTMXCSR(const xIndirect32 &dest);
|
||||||
|
extern void xLDMXCSR(const xIndirect32 &src);
|
||||||
|
extern void xFXSAVE(const xIndirectVoid &dest);
|
||||||
|
extern void xFXRSTOR(const xIndirectVoid &src);
|
||||||
|
|
||||||
|
extern void xMOVDZX(const xRegisterSSE &to, const xRegister32or64 &from);
|
||||||
|
extern void xMOVDZX(const xRegisterSSE &to, const xIndirectVoid &src);
|
||||||
|
|
||||||
|
extern void xMOVD(const xRegister32or64 &to, const xRegisterSSE &from);
|
||||||
|
extern void xMOVD(const xIndirectVoid &dest, const xRegisterSSE &from);
|
||||||
|
|
||||||
|
extern void xMOVQ(const xIndirectVoid &dest, const xRegisterSSE &from);
|
||||||
|
|
||||||
|
extern void xMOVQZX(const xRegisterSSE &to, const xIndirectVoid &src);
|
||||||
|
extern void xMOVQZX(const xRegisterSSE &to, const xRegisterSSE &from);
|
||||||
|
|
||||||
|
extern void xMOVSS(const xRegisterSSE &to, const xRegisterSSE &from);
|
||||||
|
extern void xMOVSS(const xIndirectVoid &to, const xRegisterSSE &from);
|
||||||
|
extern void xMOVSD(const xRegisterSSE &to, const xRegisterSSE &from);
|
||||||
|
extern void xMOVSD(const xIndirectVoid &to, const xRegisterSSE &from);
|
||||||
|
|
||||||
|
extern void xMOVSSZX(const xRegisterSSE &to, const xIndirectVoid &from);
|
||||||
|
extern void xMOVSDZX(const xRegisterSSE &to, const xIndirectVoid &from);
|
||||||
|
|
||||||
|
extern void xMOVNTDQA(const xRegisterSSE &to, const xIndirectVoid &from);
|
||||||
|
extern void xMOVNTDQA(const xIndirectVoid &to, const xRegisterSSE &from);
|
||||||
|
|
||||||
|
extern void xMOVNTPD(const xIndirectVoid &to, const xRegisterSSE &from);
|
||||||
|
extern void xMOVNTPS(const xIndirectVoid &to, const xRegisterSSE &from);
|
||||||
|
|
||||||
|
extern void xMOVMSKPS(const xRegister32or64 &to, const xRegisterSSE &from);
|
||||||
|
extern void xMOVMSKPD(const xRegister32or64 &to, const xRegisterSSE &from);
|
||||||
|
|
||||||
|
extern void xMASKMOV(const xRegisterSSE &to, const xRegisterSSE &from);
|
||||||
|
extern void xPMOVMSKB(const xRegister32or64 &to, const xRegisterSSE &from);
|
||||||
|
extern void xPALIGNR(const xRegisterSSE &to, const xRegisterSSE &from, u8 imm8);
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
|
extern const xImplSimd_MoveSSE xMOVAPS;
|
||||||
|
extern const xImplSimd_MoveSSE xMOVUPS;
|
||||||
|
extern const xImplSimd_MoveSSE xMOVAPD;
|
||||||
|
extern const xImplSimd_MoveSSE xMOVUPD;
|
||||||
|
|
||||||
|
#ifdef ALWAYS_USE_MOVAPS
|
||||||
|
extern const xImplSimd_MoveSSE xMOVDQA;
|
||||||
|
extern const xImplSimd_MoveSSE xMOVDQU;
|
||||||
|
#else
|
||||||
|
extern const xImplSimd_MoveDQ xMOVDQA;
|
||||||
|
extern const xImplSimd_MoveDQ xMOVDQU;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern const xImplSimd_MovHL xMOVH;
|
||||||
|
extern const xImplSimd_MovHL xMOVL;
|
||||||
|
extern const xImplSimd_MovHL_RtoR xMOVLH;
|
||||||
|
extern const xImplSimd_MovHL_RtoR xMOVHL;
|
||||||
|
|
||||||
|
extern const xImplSimd_Blend xBLEND;
|
||||||
|
extern const xImplSimd_PMove xPMOVSX;
|
||||||
|
extern const xImplSimd_PMove xPMOVZX;
|
||||||
|
|
||||||
|
extern const xImplSimd_DestRegSSE xMOVSLDUP;
|
||||||
|
extern const xImplSimd_DestRegSSE xMOVSHDUP;
|
||||||
|
|
||||||
|
extern void xINSERTPS(const xRegisterSSE &to, const xRegisterSSE &from, u8 imm8);
|
||||||
|
extern void xINSERTPS(const xRegisterSSE &to, const xIndirect32 &from, u8 imm8);
|
||||||
|
|
||||||
|
extern void xEXTRACTPS(const xRegister32or64 &to, const xRegisterSSE &from, u8 imm8);
|
||||||
|
extern void xEXTRACTPS(const xIndirect32 &dest, const xRegisterSSE &from, u8 imm8);
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
|
extern const xImplSimd_DestRegEither xPAND;
|
||||||
|
extern const xImplSimd_DestRegEither xPANDN;
|
||||||
|
extern const xImplSimd_DestRegEither xPOR;
|
||||||
|
extern const xImplSimd_DestRegEither xPXOR;
|
||||||
|
|
||||||
|
extern const xImplSimd_Shuffle xSHUF;
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
|
extern const xImplSimd_DestRegSSE xPTEST;
|
||||||
|
|
||||||
|
extern const xImplSimd_MinMax xMIN;
|
||||||
|
extern const xImplSimd_MinMax xMAX;
|
||||||
|
|
||||||
|
extern const xImplSimd_Compare xCMPEQ, xCMPLT,
|
||||||
|
xCMPLE, xCMPUNORD,
|
||||||
|
xCMPNE, xCMPNLT,
|
||||||
|
xCMPNLE, xCMPORD;
|
||||||
|
|
||||||
|
extern const xImplSimd_COMI xCOMI;
|
||||||
|
extern const xImplSimd_COMI xUCOMI;
|
||||||
|
|
||||||
|
extern const xImplSimd_PCompare xPCMP;
|
||||||
|
extern const xImplSimd_PMinMax xPMIN;
|
||||||
|
extern const xImplSimd_PMinMax xPMAX;
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
//
|
||||||
|
extern void xCVTDQ2PD(const xRegisterSSE &to, const xRegisterSSE &from);
|
||||||
|
extern void xCVTDQ2PD(const xRegisterSSE &to, const xIndirect64 &from);
|
||||||
|
extern void xCVTDQ2PS(const xRegisterSSE &to, const xRegisterSSE &from);
|
||||||
|
extern void xCVTDQ2PS(const xRegisterSSE &to, const xIndirect128 &from);
|
||||||
|
|
||||||
|
extern void xCVTPD2DQ(const xRegisterSSE &to, const xRegisterSSE &from);
|
||||||
|
extern void xCVTPD2DQ(const xRegisterSSE &to, const xIndirect128 &from);
|
||||||
|
extern void xCVTPD2PS(const xRegisterSSE &to, const xRegisterSSE &from);
|
||||||
|
extern void xCVTPD2PS(const xRegisterSSE &to, const xIndirect128 &from);
|
||||||
|
|
||||||
|
extern void xCVTPI2PD(const xRegisterSSE &to, const xIndirect64 &from);
|
||||||
|
extern void xCVTPI2PS(const xRegisterSSE &to, const xIndirect64 &from);
|
||||||
|
|
||||||
|
extern void xCVTPS2DQ(const xRegisterSSE &to, const xRegisterSSE &from);
|
||||||
|
extern void xCVTPS2DQ(const xRegisterSSE &to, const xIndirect128 &from);
|
||||||
|
extern void xCVTPS2PD(const xRegisterSSE &to, const xRegisterSSE &from);
|
||||||
|
extern void xCVTPS2PD(const xRegisterSSE &to, const xIndirect64 &from);
|
||||||
|
|
||||||
|
extern void xCVTSD2SI(const xRegister32or64 &to, const xRegisterSSE &from);
|
||||||
|
extern void xCVTSD2SI(const xRegister32or64 &to, const xIndirect64 &from);
|
||||||
|
extern void xCVTSD2SS(const xRegisterSSE &to, const xRegisterSSE &from);
|
||||||
|
extern void xCVTSD2SS(const xRegisterSSE &to, const xIndirect64 &from);
|
||||||
|
extern void xCVTSI2SS(const xRegisterSSE &to, const xRegister32or64 &from);
|
||||||
|
extern void xCVTSI2SS(const xRegisterSSE &to, const xIndirect32 &from);
|
||||||
|
|
||||||
|
extern void xCVTSS2SD(const xRegisterSSE &to, const xRegisterSSE &from);
|
||||||
|
extern void xCVTSS2SD(const xRegisterSSE &to, const xIndirect32 &from);
|
||||||
|
extern void xCVTSS2SI(const xRegister32or64 &to, const xRegisterSSE &from);
|
||||||
|
extern void xCVTSS2SI(const xRegister32or64 &to, const xIndirect32 &from);
|
||||||
|
|
||||||
|
extern void xCVTTPD2DQ(const xRegisterSSE &to, const xRegisterSSE &from);
|
||||||
|
extern void xCVTTPD2DQ(const xRegisterSSE &to, const xIndirect128 &from);
|
||||||
|
extern void xCVTTPS2DQ(const xRegisterSSE &to, const xRegisterSSE &from);
|
||||||
|
extern void xCVTTPS2DQ(const xRegisterSSE &to, const xIndirect128 &from);
|
||||||
|
|
||||||
|
extern void xCVTTSD2SI(const xRegister32or64 &to, const xRegisterSSE &from);
|
||||||
|
extern void xCVTTSD2SI(const xRegister32or64 &to, const xIndirect64 &from);
|
||||||
|
extern void xCVTTSS2SI(const xRegister32or64 &to, const xRegisterSSE &from);
|
||||||
|
extern void xCVTTSS2SI(const xRegister32or64 &to, const xIndirect32 &from);
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
|
extern const xImplSimd_AndNot xANDN;
|
||||||
|
extern const xImplSimd_rSqrt xRCP;
|
||||||
|
extern const xImplSimd_rSqrt xRSQRT;
|
||||||
|
extern const xImplSimd_Sqrt xSQRT;
|
||||||
|
|
||||||
|
extern const xImplSimd_Shift xPSLL;
|
||||||
|
extern const xImplSimd_Shift xPSRL;
|
||||||
|
extern const xImplSimd_ShiftWithoutQ xPSRA;
|
||||||
|
extern const xImplSimd_AddSub xPADD;
|
||||||
|
extern const xImplSimd_AddSub xPSUB;
|
||||||
|
extern const xImplSimd_PMul xPMUL;
|
||||||
|
extern const xImplSimd_PAbsolute xPABS;
|
||||||
|
extern const xImplSimd_PSign xPSIGN;
|
||||||
|
extern const xImplSimd_PMultAdd xPMADD;
|
||||||
|
extern const xImplSimd_HorizAdd xHADD;
|
||||||
|
extern const xImplSimd_DotProduct xDP;
|
||||||
|
extern const xImplSimd_Round xROUND;
|
||||||
|
|
||||||
|
extern const xImplSimd_PShuffle xPSHUF;
|
||||||
|
extern const SimdImpl_PUnpack xPUNPCK;
|
||||||
|
extern const xImplSimd_Unpack xUNPCK;
|
||||||
|
extern const SimdImpl_Pack xPACK;
|
||||||
|
extern const xImplSimd_PInsert xPINSR;
|
||||||
|
extern const SimdImpl_PExtract xPEXTR;
|
||||||
|
}
|
||||||
|
|
|
@ -19,156 +19,164 @@
|
||||||
#include "instructions.h"
|
#include "instructions.h"
|
||||||
|
|
||||||
|
|
||||||
namespace x86Emitter {
|
namespace x86Emitter
|
||||||
|
{
|
||||||
|
|
||||||
#define OpWriteSSE( pre, op ) xOpWrite0F( pre, op, to, from )
|
#define OpWriteSSE(pre, op) xOpWrite0F(pre, op, to, from)
|
||||||
|
|
||||||
extern void SimdPrefix( u8 prefix, u16 opcode );
|
extern void SimdPrefix(u8 prefix, u16 opcode);
|
||||||
extern void EmitSibMagic( uint regfield, const void* address );
|
extern void EmitSibMagic(uint regfield, const void *address);
|
||||||
extern void EmitSibMagic( uint regfield, const xIndirectVoid& info );
|
extern void EmitSibMagic(uint regfield, const xIndirectVoid &info);
|
||||||
extern void EmitSibMagic( uint reg1, const xRegisterBase& reg2 );
|
extern void EmitSibMagic(uint reg1, const xRegisterBase ®2);
|
||||||
extern void EmitSibMagic( const xRegisterBase& reg1, const xRegisterBase& reg2 );
|
extern void EmitSibMagic(const xRegisterBase ®1, const xRegisterBase ®2);
|
||||||
extern void EmitSibMagic( const xRegisterBase& reg1, const void* src );
|
extern void EmitSibMagic(const xRegisterBase ®1, const void *src);
|
||||||
extern void EmitSibMagic( const xRegisterBase& reg1, const xIndirectVoid& sib );
|
extern void EmitSibMagic(const xRegisterBase ®1, const xIndirectVoid &sib);
|
||||||
|
|
||||||
extern void EmitRex( uint regfield, const void* address );
|
extern void EmitRex(uint regfield, const void *address);
|
||||||
extern void EmitRex( uint regfield, const xIndirectVoid& info );
|
extern void EmitRex(uint regfield, const xIndirectVoid &info);
|
||||||
extern void EmitRex( uint reg1, const xRegisterBase& reg2 );
|
extern void EmitRex(uint reg1, const xRegisterBase ®2);
|
||||||
extern void EmitRex( const xRegisterBase& reg1, const xRegisterBase& reg2 );
|
extern void EmitRex(const xRegisterBase ®1, const xRegisterBase ®2);
|
||||||
extern void EmitRex( const xRegisterBase& reg1, const void* src );
|
extern void EmitRex(const xRegisterBase ®1, const void *src);
|
||||||
extern void EmitRex( const xRegisterBase& reg1, const xIndirectVoid& sib );
|
extern void EmitRex(const xRegisterBase ®1, const xIndirectVoid &sib);
|
||||||
|
|
||||||
extern void _xMovRtoR( const xRegisterInt& to, const xRegisterInt& from );
|
extern void _xMovRtoR(const xRegisterInt &to, const xRegisterInt &from);
|
||||||
|
|
||||||
template< typename T > inline
|
|
||||||
void xWrite( T val )
|
|
||||||
{
|
|
||||||
*(T*)x86Ptr = val;
|
|
||||||
x86Ptr += sizeof(T);
|
|
||||||
}
|
|
||||||
|
|
||||||
template< typename T1, typename T2 > __emitinline
|
|
||||||
void xOpWrite( u8 prefix, u8 opcode, const T1& param1, const T2& param2 )
|
|
||||||
{
|
|
||||||
if( prefix != 0 ) xWrite8( prefix );
|
|
||||||
EmitRex( param1, param2 );
|
|
||||||
|
|
||||||
xWrite8( opcode );
|
|
||||||
|
|
||||||
EmitSibMagic( param1, param2 );
|
|
||||||
}
|
|
||||||
|
|
||||||
template< typename T1, typename T2 > __emitinline
|
|
||||||
void xOpAccWrite( u8 prefix, u8 opcode, const T1& param1, const T2& param2 )
|
|
||||||
{
|
|
||||||
if( prefix != 0 ) xWrite8( prefix );
|
|
||||||
EmitRex( param1, param2 );
|
|
||||||
|
|
||||||
xWrite8( opcode );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// emitter helpers for xmm instruction with prefixes, most of which are using
|
|
||||||
// the basic opcode format (items inside braces denote optional or conditional
|
|
||||||
// emission):
|
|
||||||
//
|
|
||||||
// [Prefix] / 0x0f / [OpcodePrefix] / Opcode / ModRM+[SibSB]
|
|
||||||
//
|
|
||||||
// Prefixes are typically 0x66, 0xf2, or 0xf3. OpcodePrefixes are either 0x38 or
|
|
||||||
// 0x3a [and other value will result in assertion failue].
|
|
||||||
//
|
|
||||||
template< typename T1, typename T2 > __emitinline
|
|
||||||
void xOpWrite0F( u8 prefix, u16 opcode, const T1& param1, const T2& param2 )
|
|
||||||
{
|
|
||||||
if( prefix != 0 ) xWrite8( prefix );
|
|
||||||
EmitRex( param1, param2 );
|
|
||||||
|
|
||||||
SimdPrefix( 0, opcode );
|
|
||||||
|
|
||||||
EmitSibMagic( param1, param2 );
|
|
||||||
}
|
|
||||||
|
|
||||||
template< typename T1, typename T2 > __emitinline
|
|
||||||
void xOpWrite0F( u8 prefix, u16 opcode, const T1& param1, const T2& param2, u8 imm8 )
|
|
||||||
{
|
|
||||||
xOpWrite0F( prefix, opcode, param1, param2 );
|
|
||||||
xWrite8( imm8 );
|
|
||||||
}
|
|
||||||
|
|
||||||
template< typename T1, typename T2 > __emitinline
|
|
||||||
void xOpWrite0F( u16 opcode, const T1& param1, const T2& param2 ) { xOpWrite0F( 0, opcode, param1, param2 ); }
|
|
||||||
|
|
||||||
template< typename T1, typename T2 > __emitinline
|
|
||||||
void xOpWrite0F( u16 opcode, const T1& param1, const T2& param2, u8 imm8 ) { xOpWrite0F( 0, opcode, param1, param2, imm8 ); }
|
|
||||||
|
|
||||||
// VEX 2 Bytes Prefix
|
|
||||||
template< typename T1, typename T2, typename T3 > __emitinline
|
|
||||||
void xOpWriteC5( u8 prefix, u8 opcode, const T1& param1, const T2& param2, const T3& param3 )
|
|
||||||
{
|
|
||||||
pxAssert( prefix == 0 || prefix == 0x66 || prefix == 0xF3 || prefix == 0xF2 );
|
|
||||||
|
|
||||||
const xRegisterInt& reg = param1.IsReg() ? param1 : param2;
|
|
||||||
|
|
||||||
#ifdef __x86_64__
|
|
||||||
u8 nR = reg.IsExtended() ? 0x00 : 0x80;
|
|
||||||
#else
|
|
||||||
u8 nR = 0x80;
|
|
||||||
#endif
|
|
||||||
u8 L = reg.IsWideSIMD() ? 4 : 0;
|
|
||||||
|
|
||||||
u8 nv = (~param2.GetId() & 0xF) << 3;
|
|
||||||
|
|
||||||
u8 p =
|
|
||||||
prefix == 0xF2 ? 3 :
|
|
||||||
prefix == 0xF3 ? 2 :
|
|
||||||
prefix == 0x66 ? 1 : 0;
|
|
||||||
|
|
||||||
xWrite8( 0xC5 );
|
|
||||||
xWrite8( nR | nv | L | p );
|
|
||||||
xWrite8( opcode );
|
|
||||||
EmitSibMagic( param1, param3 );
|
|
||||||
}
|
|
||||||
|
|
||||||
// VEX 3 Bytes Prefix
|
|
||||||
template< typename T1, typename T2, typename T3 > __emitinline
|
|
||||||
void xOpWriteC4( u8 prefix, u8 mb_prefix, u8 opcode, const T1& param1, const T2& param2, const T3& param3, int w = -1 )
|
|
||||||
{
|
|
||||||
pxAssert( prefix == 0 || prefix == 0x66 || prefix == 0xF3 || prefix == 0xF2 );
|
|
||||||
pxAssert( mb_prefix == 0x0F || mb_prefix == 0x38 || mb_prefix == 0x3A );
|
|
||||||
|
|
||||||
const xRegisterInt& reg = param1.IsReg() ? param1 : param2;
|
|
||||||
|
|
||||||
#ifdef __x86_64__
|
|
||||||
u8 nR = reg.IsExtended() ? 0x00 : 0x80;
|
|
||||||
u8 nB = param3.IsExtended() ? 0x00 : 0x20;
|
|
||||||
u8 nX = 0x40; // likely unused so hardwired to disabled
|
|
||||||
#else
|
|
||||||
u8 nR = 0x80;
|
|
||||||
u8 nB = 0x20;
|
|
||||||
u8 nX = 0x40;
|
|
||||||
#endif
|
|
||||||
u8 L = reg.IsWideSIMD() ? 4 : 0;
|
|
||||||
u8 W = (w == -1) ? (reg.GetOperandSize() == 8 ? 0x80 : 0) : // autodetect the size
|
|
||||||
0x80 * w; // take directly the W value
|
|
||||||
|
|
||||||
u8 nv = (~param2.GetId() & 0xF) << 3;
|
|
||||||
|
|
||||||
u8 p =
|
|
||||||
prefix == 0xF2 ? 3 :
|
|
||||||
prefix == 0xF3 ? 2 :
|
|
||||||
prefix == 0x66 ? 1 : 0;
|
|
||||||
|
|
||||||
u8 m =
|
|
||||||
mb_prefix == 0x3A ? 3 :
|
|
||||||
mb_prefix == 0x38 ? 2 : 1;
|
|
||||||
|
|
||||||
xWrite8( 0xC4 );
|
|
||||||
xWrite8( nR | nX | nB | m );
|
|
||||||
xWrite8( W | nv | L | p );
|
|
||||||
xWrite8( opcode );
|
|
||||||
EmitSibMagic( param1, param3 );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline void xWrite(T val)
|
||||||
|
{
|
||||||
|
*(T *)x86Ptr = val;
|
||||||
|
x86Ptr += sizeof(T);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T1, typename T2>
|
||||||
|
__emitinline void xOpWrite(u8 prefix, u8 opcode, const T1 ¶m1, const T2 ¶m2)
|
||||||
|
{
|
||||||
|
if (prefix != 0)
|
||||||
|
xWrite8(prefix);
|
||||||
|
EmitRex(param1, param2);
|
||||||
|
|
||||||
|
xWrite8(opcode);
|
||||||
|
|
||||||
|
EmitSibMagic(param1, param2);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T1, typename T2>
|
||||||
|
__emitinline void xOpAccWrite(u8 prefix, u8 opcode, const T1 ¶m1, const T2 ¶m2)
|
||||||
|
{
|
||||||
|
if (prefix != 0)
|
||||||
|
xWrite8(prefix);
|
||||||
|
EmitRex(param1, param2);
|
||||||
|
|
||||||
|
xWrite8(opcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// emitter helpers for xmm instruction with prefixes, most of which are using
|
||||||
|
// the basic opcode format (items inside braces denote optional or conditional
|
||||||
|
// emission):
|
||||||
|
//
|
||||||
|
// [Prefix] / 0x0f / [OpcodePrefix] / Opcode / ModRM+[SibSB]
|
||||||
|
//
|
||||||
|
// Prefixes are typically 0x66, 0xf2, or 0xf3. OpcodePrefixes are either 0x38 or
|
||||||
|
// 0x3a [and other value will result in assertion failue].
|
||||||
|
//
|
||||||
|
template <typename T1, typename T2>
|
||||||
|
__emitinline void xOpWrite0F(u8 prefix, u16 opcode, const T1 ¶m1, const T2 ¶m2)
|
||||||
|
{
|
||||||
|
if (prefix != 0)
|
||||||
|
xWrite8(prefix);
|
||||||
|
EmitRex(param1, param2);
|
||||||
|
|
||||||
|
SimdPrefix(0, opcode);
|
||||||
|
|
||||||
|
EmitSibMagic(param1, param2);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T1, typename T2>
|
||||||
|
__emitinline void xOpWrite0F(u8 prefix, u16 opcode, const T1 ¶m1, const T2 ¶m2, u8 imm8)
|
||||||
|
{
|
||||||
|
xOpWrite0F(prefix, opcode, param1, param2);
|
||||||
|
xWrite8(imm8);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T1, typename T2>
|
||||||
|
__emitinline void xOpWrite0F(u16 opcode, const T1 ¶m1, const T2 ¶m2)
|
||||||
|
{
|
||||||
|
xOpWrite0F(0, opcode, param1, param2);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T1, typename T2>
|
||||||
|
__emitinline void xOpWrite0F(u16 opcode, const T1 ¶m1, const T2 ¶m2, u8 imm8)
|
||||||
|
{
|
||||||
|
xOpWrite0F(0, opcode, param1, param2, imm8);
|
||||||
|
}
|
||||||
|
|
||||||
|
// VEX 2 Bytes Prefix
|
||||||
|
template <typename T1, typename T2, typename T3>
|
||||||
|
__emitinline void xOpWriteC5(u8 prefix, u8 opcode, const T1 ¶m1, const T2 ¶m2, const T3 ¶m3)
|
||||||
|
{
|
||||||
|
pxAssert(prefix == 0 || prefix == 0x66 || prefix == 0xF3 || prefix == 0xF2);
|
||||||
|
|
||||||
|
const xRegisterInt ® = param1.IsReg() ? param1 : param2;
|
||||||
|
|
||||||
|
#ifdef __x86_64__
|
||||||
|
u8 nR = reg.IsExtended() ? 0x00 : 0x80;
|
||||||
|
#else
|
||||||
|
u8 nR = 0x80;
|
||||||
|
#endif
|
||||||
|
u8 L = reg.IsWideSIMD() ? 4 : 0;
|
||||||
|
|
||||||
|
u8 nv = (~param2.GetId() & 0xF) << 3;
|
||||||
|
|
||||||
|
u8 p =
|
||||||
|
prefix == 0xF2 ? 3 :
|
||||||
|
prefix == 0xF3 ? 2 :
|
||||||
|
prefix == 0x66 ? 1 : 0;
|
||||||
|
|
||||||
|
xWrite8(0xC5);
|
||||||
|
xWrite8(nR | nv | L | p);
|
||||||
|
xWrite8(opcode);
|
||||||
|
EmitSibMagic(param1, param3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// VEX 3 Bytes Prefix
|
||||||
|
template <typename T1, typename T2, typename T3>
|
||||||
|
__emitinline void xOpWriteC4(u8 prefix, u8 mb_prefix, u8 opcode, const T1 ¶m1, const T2 ¶m2, const T3 ¶m3, int w = -1)
|
||||||
|
{
|
||||||
|
pxAssert(prefix == 0 || prefix == 0x66 || prefix == 0xF3 || prefix == 0xF2);
|
||||||
|
pxAssert(mb_prefix == 0x0F || mb_prefix == 0x38 || mb_prefix == 0x3A);
|
||||||
|
|
||||||
|
const xRegisterInt ® = param1.IsReg() ? param1 : param2;
|
||||||
|
|
||||||
|
#ifdef __x86_64__
|
||||||
|
u8 nR = reg.IsExtended() ? 0x00 : 0x80;
|
||||||
|
u8 nB = param3.IsExtended() ? 0x00 : 0x20;
|
||||||
|
u8 nX = 0x40; // likely unused so hardwired to disabled
|
||||||
|
#else
|
||||||
|
u8 nR = 0x80;
|
||||||
|
u8 nB = 0x20;
|
||||||
|
u8 nX = 0x40;
|
||||||
|
#endif
|
||||||
|
u8 L = reg.IsWideSIMD() ? 4 : 0;
|
||||||
|
u8 W = (w == -1) ? (reg.GetOperandSize() == 8 ? 0x80 : 0) : // autodetect the size
|
||||||
|
0x80 * w; // take directly the W value
|
||||||
|
|
||||||
|
u8 nv = (~param2.GetId() & 0xF) << 3;
|
||||||
|
|
||||||
|
u8 p =
|
||||||
|
prefix == 0xF2 ? 3 :
|
||||||
|
prefix == 0xF3 ? 2 :
|
||||||
|
prefix == 0x66 ? 1 : 0;
|
||||||
|
|
||||||
|
u8 m =
|
||||||
|
mb_prefix == 0x3A ? 3 :
|
||||||
|
mb_prefix == 0x38 ? 2 : 1;
|
||||||
|
|
||||||
|
xWrite8(0xC4);
|
||||||
|
xWrite8(nR | nX | nB | m);
|
||||||
|
xWrite8(W | nv | L | p);
|
||||||
|
xWrite8(opcode);
|
||||||
|
EmitSibMagic(param1, param3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -25,15 +25,15 @@
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
// legacy jump/align functions
|
// legacy jump/align functions
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
ATTR_DEP extern void x86SetPtr( u8 *ptr );
|
ATTR_DEP extern void x86SetPtr(u8 *ptr);
|
||||||
ATTR_DEP extern void x86SetJ8( u8 *j8 );
|
ATTR_DEP extern void x86SetJ8(u8 *j8);
|
||||||
ATTR_DEP extern void x86SetJ8A( u8 *j8 );
|
ATTR_DEP extern void x86SetJ8A(u8 *j8);
|
||||||
ATTR_DEP extern void x86SetJ16( u16 *j16 );
|
ATTR_DEP extern void x86SetJ16(u16 *j16);
|
||||||
ATTR_DEP extern void x86SetJ16A( u16 *j16 );
|
ATTR_DEP extern void x86SetJ16A(u16 *j16);
|
||||||
ATTR_DEP extern void x86SetJ32( u32 *j32 );
|
ATTR_DEP extern void x86SetJ32(u32 *j32);
|
||||||
ATTR_DEP extern void x86SetJ32A( u32 *j32 );
|
ATTR_DEP extern void x86SetJ32A(u32 *j32);
|
||||||
ATTR_DEP extern void x86Align( int bytes );
|
ATTR_DEP extern void x86Align(int bytes);
|
||||||
ATTR_DEP extern void x86AlignExecutable( int align );
|
ATTR_DEP extern void x86AlignExecutable(int align);
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
|
||||||
////////////////////////////////////
|
////////////////////////////////////
|
||||||
|
@ -41,55 +41,55 @@ ATTR_DEP extern void x86AlignExecutable( int align );
|
||||||
////////////////////////////////////
|
////////////////////////////////////
|
||||||
|
|
||||||
// jmp rel8
|
// jmp rel8
|
||||||
ATTR_DEP extern u8* JMP8( u8 to );
|
ATTR_DEP extern u8 *JMP8(u8 to);
|
||||||
|
|
||||||
// jmp rel32
|
// jmp rel32
|
||||||
ATTR_DEP extern u32* JMP32( uptr to );
|
ATTR_DEP extern u32 *JMP32(uptr to);
|
||||||
|
|
||||||
// jp rel8
|
// jp rel8
|
||||||
ATTR_DEP extern u8* JP8( u8 to );
|
ATTR_DEP extern u8 *JP8(u8 to);
|
||||||
// jnp rel8
|
// jnp rel8
|
||||||
ATTR_DEP extern u8* JNP8( u8 to );
|
ATTR_DEP extern u8 *JNP8(u8 to);
|
||||||
// je rel8
|
// je rel8
|
||||||
ATTR_DEP extern u8* JE8( u8 to );
|
ATTR_DEP extern u8 *JE8(u8 to);
|
||||||
// jz rel8
|
// jz rel8
|
||||||
ATTR_DEP extern u8* JZ8( u8 to );
|
ATTR_DEP extern u8 *JZ8(u8 to);
|
||||||
// jg rel8
|
// jg rel8
|
||||||
ATTR_DEP extern u8* JG8( u8 to );
|
ATTR_DEP extern u8 *JG8(u8 to);
|
||||||
// jge rel8
|
// jge rel8
|
||||||
ATTR_DEP extern u8* JGE8( u8 to );
|
ATTR_DEP extern u8 *JGE8(u8 to);
|
||||||
// js rel8
|
// js rel8
|
||||||
ATTR_DEP extern u8* JS8( u8 to );
|
ATTR_DEP extern u8 *JS8(u8 to);
|
||||||
// jns rel8
|
// jns rel8
|
||||||
ATTR_DEP extern u8* JNS8( u8 to );
|
ATTR_DEP extern u8 *JNS8(u8 to);
|
||||||
// jl rel8
|
// jl rel8
|
||||||
ATTR_DEP extern u8* JL8( u8 to );
|
ATTR_DEP extern u8 *JL8(u8 to);
|
||||||
// ja rel8
|
// ja rel8
|
||||||
ATTR_DEP extern u8* JA8( u8 to );
|
ATTR_DEP extern u8 *JA8(u8 to);
|
||||||
// jae rel8
|
// jae rel8
|
||||||
ATTR_DEP extern u8* JAE8( u8 to );
|
ATTR_DEP extern u8 *JAE8(u8 to);
|
||||||
// jb rel8
|
// jb rel8
|
||||||
ATTR_DEP extern u8* JB8( u8 to );
|
ATTR_DEP extern u8 *JB8(u8 to);
|
||||||
// jbe rel8
|
// jbe rel8
|
||||||
ATTR_DEP extern u8* JBE8( u8 to );
|
ATTR_DEP extern u8 *JBE8(u8 to);
|
||||||
// jle rel8
|
// jle rel8
|
||||||
ATTR_DEP extern u8* JLE8( u8 to );
|
ATTR_DEP extern u8 *JLE8(u8 to);
|
||||||
// jne rel8
|
// jne rel8
|
||||||
ATTR_DEP extern u8* JNE8( u8 to );
|
ATTR_DEP extern u8 *JNE8(u8 to);
|
||||||
// jnz rel8
|
// jnz rel8
|
||||||
ATTR_DEP extern u8* JNZ8( u8 to );
|
ATTR_DEP extern u8 *JNZ8(u8 to);
|
||||||
// jng rel8
|
// jng rel8
|
||||||
ATTR_DEP extern u8* JNG8( u8 to );
|
ATTR_DEP extern u8 *JNG8(u8 to);
|
||||||
// jnge rel8
|
// jnge rel8
|
||||||
ATTR_DEP extern u8* JNGE8( u8 to );
|
ATTR_DEP extern u8 *JNGE8(u8 to);
|
||||||
// jnl rel8
|
// jnl rel8
|
||||||
ATTR_DEP extern u8* JNL8( u8 to );
|
ATTR_DEP extern u8 *JNL8(u8 to);
|
||||||
// jnle rel8
|
// jnle rel8
|
||||||
ATTR_DEP extern u8* JNLE8( u8 to );
|
ATTR_DEP extern u8 *JNLE8(u8 to);
|
||||||
// jo rel8
|
// jo rel8
|
||||||
ATTR_DEP extern u8* JO8( u8 to );
|
ATTR_DEP extern u8 *JO8(u8 to);
|
||||||
// jno rel8
|
// jno rel8
|
||||||
ATTR_DEP extern u8* JNO8( u8 to );
|
ATTR_DEP extern u8 *JNO8(u8 to);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// jb rel16
|
// jb rel16
|
||||||
|
@ -103,51 +103,51 @@ ATTR_DEP extern u16* JZ16( u16 to );
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// jns rel32
|
// jns rel32
|
||||||
ATTR_DEP extern u32* JNS32( u32 to );
|
ATTR_DEP extern u32 *JNS32(u32 to);
|
||||||
// js rel32
|
// js rel32
|
||||||
ATTR_DEP extern u32* JS32( u32 to );
|
ATTR_DEP extern u32 *JS32(u32 to);
|
||||||
|
|
||||||
// jb rel32
|
// jb rel32
|
||||||
ATTR_DEP extern u32* JB32( u32 to );
|
ATTR_DEP extern u32 *JB32(u32 to);
|
||||||
// je rel32
|
// je rel32
|
||||||
ATTR_DEP extern u32* JE32( u32 to );
|
ATTR_DEP extern u32 *JE32(u32 to);
|
||||||
// jz rel32
|
// jz rel32
|
||||||
ATTR_DEP extern u32* JZ32( u32 to );
|
ATTR_DEP extern u32 *JZ32(u32 to);
|
||||||
// jg rel32
|
// jg rel32
|
||||||
ATTR_DEP extern u32* JG32( u32 to );
|
ATTR_DEP extern u32 *JG32(u32 to);
|
||||||
// jge rel32
|
// jge rel32
|
||||||
ATTR_DEP extern u32* JGE32( u32 to );
|
ATTR_DEP extern u32 *JGE32(u32 to);
|
||||||
// jl rel32
|
// jl rel32
|
||||||
ATTR_DEP extern u32* JL32( u32 to );
|
ATTR_DEP extern u32 *JL32(u32 to);
|
||||||
// jle rel32
|
// jle rel32
|
||||||
ATTR_DEP extern u32* JLE32( u32 to );
|
ATTR_DEP extern u32 *JLE32(u32 to);
|
||||||
// jae rel32
|
// jae rel32
|
||||||
ATTR_DEP extern u32* JAE32( u32 to );
|
ATTR_DEP extern u32 *JAE32(u32 to);
|
||||||
// jne rel32
|
// jne rel32
|
||||||
ATTR_DEP extern u32* JNE32( u32 to );
|
ATTR_DEP extern u32 *JNE32(u32 to);
|
||||||
// jnz rel32
|
// jnz rel32
|
||||||
ATTR_DEP extern u32* JNZ32( u32 to );
|
ATTR_DEP extern u32 *JNZ32(u32 to);
|
||||||
// jng rel32
|
// jng rel32
|
||||||
ATTR_DEP extern u32* JNG32( u32 to );
|
ATTR_DEP extern u32 *JNG32(u32 to);
|
||||||
// jnge rel32
|
// jnge rel32
|
||||||
ATTR_DEP extern u32* JNGE32( u32 to );
|
ATTR_DEP extern u32 *JNGE32(u32 to);
|
||||||
// jnl rel32
|
// jnl rel32
|
||||||
ATTR_DEP extern u32* JNL32( u32 to );
|
ATTR_DEP extern u32 *JNL32(u32 to);
|
||||||
// jnle rel32
|
// jnle rel32
|
||||||
ATTR_DEP extern u32* JNLE32( u32 to );
|
ATTR_DEP extern u32 *JNLE32(u32 to);
|
||||||
// jo rel32
|
// jo rel32
|
||||||
ATTR_DEP extern u32* JO32( u32 to );
|
ATTR_DEP extern u32 *JO32(u32 to);
|
||||||
// jno rel32
|
// jno rel32
|
||||||
ATTR_DEP extern u32* JNO32( u32 to );
|
ATTR_DEP extern u32 *JNO32(u32 to);
|
||||||
// js rel32
|
// js rel32
|
||||||
ATTR_DEP extern u32* JS32( u32 to );
|
ATTR_DEP extern u32 *JS32(u32 to);
|
||||||
|
|
||||||
//******************
|
//******************
|
||||||
// FPU instructions
|
// FPU instructions
|
||||||
//******************
|
//******************
|
||||||
|
|
||||||
// fld m32 to fpu reg stack
|
// fld m32 to fpu reg stack
|
||||||
ATTR_DEP extern void FLD32( u32 from );
|
ATTR_DEP extern void FLD32(u32 from);
|
||||||
// fld st(i)
|
// fld st(i)
|
||||||
ATTR_DEP extern void FLD(int st);
|
ATTR_DEP extern void FLD(int st);
|
||||||
// fld1 (push +1.0f on the stack)
|
// fld1 (push +1.0f on the stack)
|
||||||
|
@ -155,7 +155,7 @@ ATTR_DEP extern void FLD1();
|
||||||
// fld1 (push log_2 e on the stack)
|
// fld1 (push log_2 e on the stack)
|
||||||
ATTR_DEP extern void FLDL2E();
|
ATTR_DEP extern void FLDL2E();
|
||||||
// fstp m32 from fpu reg stack
|
// fstp m32 from fpu reg stack
|
||||||
ATTR_DEP extern void FSTP32( u32 to );
|
ATTR_DEP extern void FSTP32(u32 to);
|
||||||
// fstp st(i)
|
// fstp st(i)
|
||||||
ATTR_DEP extern void FSTP(int st);
|
ATTR_DEP extern void FSTP(int st);
|
||||||
|
|
||||||
|
@ -166,32 +166,32 @@ ATTR_DEP extern void F2XM1();
|
||||||
ATTR_DEP extern void FSCALE();
|
ATTR_DEP extern void FSCALE();
|
||||||
|
|
||||||
// fadd ST(0) to fpu reg stack ST(src)
|
// fadd ST(0) to fpu reg stack ST(src)
|
||||||
ATTR_DEP extern void FADD320toR( x86IntRegType src );
|
ATTR_DEP extern void FADD320toR(x86IntRegType src);
|
||||||
// fsub ST(src) to fpu reg stack ST(0)
|
// fsub ST(src) to fpu reg stack ST(0)
|
||||||
ATTR_DEP extern void FSUB32Rto0( x86IntRegType src );
|
ATTR_DEP extern void FSUB32Rto0(x86IntRegType src);
|
||||||
|
|
||||||
// fmul m32 to fpu reg stack
|
// fmul m32 to fpu reg stack
|
||||||
ATTR_DEP extern void FMUL32( u32 from );
|
ATTR_DEP extern void FMUL32(u32 from);
|
||||||
// fdiv m32 to fpu reg stack
|
// fdiv m32 to fpu reg stack
|
||||||
ATTR_DEP extern void FDIV32( u32 from );
|
ATTR_DEP extern void FDIV32(u32 from);
|
||||||
// ftan fpu reg stack
|
// ftan fpu reg stack
|
||||||
ATTR_DEP extern void FPATAN( void );
|
ATTR_DEP extern void FPATAN(void);
|
||||||
// fsin fpu reg stack
|
// fsin fpu reg stack
|
||||||
ATTR_DEP extern void FSIN( void );
|
ATTR_DEP extern void FSIN(void);
|
||||||
|
|
||||||
//*********************
|
//*********************
|
||||||
// SSE instructions *
|
// SSE instructions *
|
||||||
//*********************
|
//*********************
|
||||||
ATTR_DEP extern void SSE_MAXSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
|
ATTR_DEP extern void SSE_MAXSS_XMM_to_XMM(x86SSERegType to, x86SSERegType from);
|
||||||
ATTR_DEP extern void SSE_MINSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
|
ATTR_DEP extern void SSE_MINSS_XMM_to_XMM(x86SSERegType to, x86SSERegType from);
|
||||||
ATTR_DEP extern void SSE_ADDSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
|
ATTR_DEP extern void SSE_ADDSS_XMM_to_XMM(x86SSERegType to, x86SSERegType from);
|
||||||
ATTR_DEP extern void SSE_SUBSS_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
|
ATTR_DEP extern void SSE_SUBSS_XMM_to_XMM(x86SSERegType to, x86SSERegType from);
|
||||||
|
|
||||||
//*********************
|
//*********************
|
||||||
// SSE 2 Instructions*
|
// SSE 2 Instructions*
|
||||||
//*********************
|
//*********************
|
||||||
|
|
||||||
ATTR_DEP extern void SSE2_MAXSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
|
ATTR_DEP extern void SSE2_MAXSD_XMM_to_XMM(x86SSERegType to, x86SSERegType from);
|
||||||
ATTR_DEP extern void SSE2_MINSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
|
ATTR_DEP extern void SSE2_MINSD_XMM_to_XMM(x86SSERegType to, x86SSERegType from);
|
||||||
ATTR_DEP extern void SSE2_ADDSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
|
ATTR_DEP extern void SSE2_ADDSD_XMM_to_XMM(x86SSERegType to, x86SSERegType from);
|
||||||
ATTR_DEP extern void SSE2_SUBSD_XMM_to_XMM( x86SSERegType to, x86SSERegType from );
|
ATTR_DEP extern void SSE2_SUBSD_XMM_to_XMM(x86SSERegType to, x86SSERegType from);
|
||||||
|
|
|
@ -31,11 +31,10 @@ using x86Emitter::xWrite64;
|
||||||
#include "legacy_types.h"
|
#include "legacy_types.h"
|
||||||
#include "legacy_instructions.h"
|
#include "legacy_instructions.h"
|
||||||
|
|
||||||
#define MEMADDR(addr, oplen) (addr)
|
#define MEMADDR(addr, oplen) (addr)
|
||||||
|
|
||||||
extern void ModRM( uint mod, uint reg, uint rm );
|
|
||||||
extern void SibSB( uint ss, uint index, uint base );
|
|
||||||
extern void SET8R( int cc, int to );
|
|
||||||
extern u8* J8Rel( int cc, int to );
|
|
||||||
extern u32* J32Rel( int cc, u32 to );
|
|
||||||
|
|
||||||
|
extern void ModRM(uint mod, uint reg, uint rm);
|
||||||
|
extern void SibSB(uint ss, uint index, uint base);
|
||||||
|
extern void SET8R(int cc, int to);
|
||||||
|
extern u8 *J8Rel(int cc, int to);
|
||||||
|
extern u32 *J32Rel(int cc, u32 to);
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
//#define SIB 4 // maps to ESP
|
//#define SIB 4 // maps to ESP
|
||||||
//#define SIBDISP 5 // maps to EBP
|
//#define SIBDISP 5 // maps to EBP
|
||||||
#define DISP32 5 // maps to EBP
|
#define DISP32 5 // maps to EBP
|
||||||
|
|
||||||
// general types
|
// general types
|
||||||
typedef int x86IntRegType;
|
typedef int x86IntRegType;
|
||||||
|
|
|
@ -17,11 +17,10 @@
|
||||||
|
|
||||||
#include "x86emitter.h"
|
#include "x86emitter.h"
|
||||||
|
|
||||||
enum x86VendorType
|
enum x86VendorType {
|
||||||
{
|
x86Vendor_Intel = 0,
|
||||||
x86Vendor_Intel = 0,
|
x86Vendor_AMD = 1,
|
||||||
x86Vendor_AMD = 1,
|
x86Vendor_Unknown = 2
|
||||||
x86Vendor_Unknown = 2
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -30,110 +29,111 @@ enum x86VendorType
|
||||||
class x86capabilities
|
class x86capabilities
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool isIdentified;
|
bool isIdentified;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
x86VendorType VendorID;
|
x86VendorType VendorID;
|
||||||
|
|
||||||
uint FamilyID; // Processor Family
|
uint FamilyID; // Processor Family
|
||||||
uint Model; // Processor Model
|
uint Model; // Processor Model
|
||||||
uint TypeID; // Processor Type
|
uint TypeID; // Processor Type
|
||||||
uint StepID; // Stepping ID
|
uint StepID; // Stepping ID
|
||||||
|
|
||||||
u32 Flags; // Feature Flags
|
u32 Flags; // Feature Flags
|
||||||
u32 Flags2; // More Feature Flags
|
u32 Flags2; // More Feature Flags
|
||||||
u32 EFlags; // Extended Feature Flags
|
u32 EFlags; // Extended Feature Flags
|
||||||
u32 EFlags2; // Extended Feature Flags pg2
|
u32 EFlags2; // Extended Feature Flags pg2
|
||||||
u32 SEFlag; // Structured Extended Feature Flags Enumeration
|
u32 SEFlag; // Structured Extended Feature Flags Enumeration
|
||||||
|
|
||||||
char VendorName[16]; // Vendor/Creator ID
|
char VendorName[16]; // Vendor/Creator ID
|
||||||
char FamilyName[50]; // the original cpu name
|
char FamilyName[50]; // the original cpu name
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// x86 CPU Capabilities Section (all boolean flags!)
|
// x86 CPU Capabilities Section (all boolean flags!)
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
union {
|
union
|
||||||
struct {
|
{
|
||||||
u32 hasFloatingPointUnit :1;
|
struct
|
||||||
u32 hasVirtual8086ModeEnhancements :1;
|
{
|
||||||
u32 hasDebuggingExtensions :1;
|
u32 hasFloatingPointUnit : 1;
|
||||||
u32 hasPageSizeExtensions :1;
|
u32 hasVirtual8086ModeEnhancements : 1;
|
||||||
u32 hasTimeStampCounter :1;
|
u32 hasDebuggingExtensions : 1;
|
||||||
u32 hasModelSpecificRegisters :1;
|
u32 hasPageSizeExtensions : 1;
|
||||||
u32 hasPhysicalAddressExtension :1;
|
u32 hasTimeStampCounter : 1;
|
||||||
u32 hasCOMPXCHG8BInstruction :1;
|
u32 hasModelSpecificRegisters : 1;
|
||||||
u32 hasAdvancedProgrammableInterruptController :1;
|
u32 hasPhysicalAddressExtension : 1;
|
||||||
u32 hasSEPFastSystemCall :1;
|
u32 hasCOMPXCHG8BInstruction : 1;
|
||||||
u32 hasMemoryTypeRangeRegisters :1;
|
u32 hasAdvancedProgrammableInterruptController : 1;
|
||||||
u32 hasPTEGlobalFlag :1;
|
u32 hasSEPFastSystemCall : 1;
|
||||||
u32 hasMachineCheckArchitecture :1;
|
u32 hasMemoryTypeRangeRegisters : 1;
|
||||||
u32 hasConditionalMoveAndCompareInstructions :1;
|
u32 hasPTEGlobalFlag : 1;
|
||||||
u32 hasFGPageAttributeTable :1;
|
u32 hasMachineCheckArchitecture : 1;
|
||||||
u32 has36bitPageSizeExtension :1;
|
u32 hasConditionalMoveAndCompareInstructions : 1;
|
||||||
u32 hasProcessorSerialNumber :1;
|
u32 hasFGPageAttributeTable : 1;
|
||||||
u32 hasCFLUSHInstruction :1;
|
u32 has36bitPageSizeExtension : 1;
|
||||||
u32 hasDebugStore :1;
|
u32 hasProcessorSerialNumber : 1;
|
||||||
u32 hasACPIThermalMonitorAndClockControl :1;
|
u32 hasCFLUSHInstruction : 1;
|
||||||
u32 hasFastStreamingSIMDExtensionsSaveRestore :1;
|
u32 hasDebugStore : 1;
|
||||||
u32 hasStreamingSIMDExtensions :1;
|
u32 hasACPIThermalMonitorAndClockControl : 1;
|
||||||
u32 hasStreamingSIMD2Extensions :1;
|
u32 hasFastStreamingSIMDExtensionsSaveRestore : 1;
|
||||||
u32 hasSelfSnoop :1;
|
u32 hasStreamingSIMDExtensions : 1;
|
||||||
|
u32 hasStreamingSIMD2Extensions : 1;
|
||||||
|
u32 hasSelfSnoop : 1;
|
||||||
|
|
||||||
// is TRUE for both multi-core and Hyperthreaded CPUs.
|
// is TRUE for both multi-core and Hyperthreaded CPUs.
|
||||||
u32 hasMultiThreading :1;
|
u32 hasMultiThreading : 1;
|
||||||
|
|
||||||
u32 hasThermalMonitor :1;
|
u32 hasThermalMonitor : 1;
|
||||||
u32 hasIntel64BitArchitecture :1;
|
u32 hasIntel64BitArchitecture : 1;
|
||||||
u32 hasStreamingSIMD3Extensions :1;
|
u32 hasStreamingSIMD3Extensions : 1;
|
||||||
u32 hasSupplementalStreamingSIMD3Extensions :1;
|
u32 hasSupplementalStreamingSIMD3Extensions : 1;
|
||||||
u32 hasStreamingSIMD4Extensions :1;
|
u32 hasStreamingSIMD4Extensions : 1;
|
||||||
u32 hasStreamingSIMD4Extensions2 :1;
|
u32 hasStreamingSIMD4Extensions2 : 1;
|
||||||
u32 hasAVX :1;
|
u32 hasAVX : 1;
|
||||||
u32 hasAVX2 :1;
|
u32 hasAVX2 : 1;
|
||||||
u32 hasBMI1 :1;
|
u32 hasBMI1 : 1;
|
||||||
u32 hasBMI2 :1;
|
u32 hasBMI2 : 1;
|
||||||
u32 hasFMA :1;
|
u32 hasFMA : 1;
|
||||||
|
|
||||||
// AMD-specific CPU Features
|
// AMD-specific CPU Features
|
||||||
u32 hasAMD64BitArchitecture :1;
|
u32 hasAMD64BitArchitecture : 1;
|
||||||
u32 hasStreamingSIMD4ExtensionsA :1;
|
u32 hasStreamingSIMD4ExtensionsA : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
u64 AllCapabilities;
|
u64 AllCapabilities;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Core Counts!
|
// Core Counts!
|
||||||
u32 PhysicalCores;
|
u32 PhysicalCores;
|
||||||
u32 LogicalCores;
|
u32 LogicalCores;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
x86capabilities();
|
x86capabilities();
|
||||||
|
|
||||||
void Identify();
|
void Identify();
|
||||||
void CountCores();
|
void CountCores();
|
||||||
wxString GetTypeName() const;
|
wxString GetTypeName() const;
|
||||||
|
|
||||||
u32 CalculateMHz() const;
|
u32 CalculateMHz() const;
|
||||||
|
|
||||||
void SIMD_EstablishMXCSRmask();
|
void SIMD_EstablishMXCSRmask();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
s64 _CPUSpeedHz( u64 time ) const;
|
s64 _CPUSpeedHz(u64 time) const;
|
||||||
void CountLogicalCores();
|
void CountLogicalCores();
|
||||||
};
|
};
|
||||||
|
|
||||||
enum SSE_RoundMode
|
enum SSE_RoundMode {
|
||||||
{
|
SSE_RoundMode_FIRST = 0,
|
||||||
SSE_RoundMode_FIRST = 0,
|
SSEround_Nearest = 0,
|
||||||
SSEround_Nearest = 0,
|
SSEround_NegInf,
|
||||||
SSEround_NegInf,
|
SSEround_PosInf,
|
||||||
SSEround_PosInf,
|
SSEround_Chop,
|
||||||
SSEround_Chop,
|
SSE_RoundMode_COUNT
|
||||||
SSE_RoundMode_COUNT
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ImplementEnumOperators( SSE_RoundMode );
|
ImplementEnumOperators(SSE_RoundMode);
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// SSE_MXCSR - Control/Status Register (bitfield)
|
// SSE_MXCSR - Control/Status Register (bitfield)
|
||||||
|
@ -147,56 +147,55 @@ ImplementEnumOperators( SSE_RoundMode );
|
||||||
//
|
//
|
||||||
union SSE_MXCSR
|
union SSE_MXCSR
|
||||||
{
|
{
|
||||||
u32 bitmask;
|
u32 bitmask;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
u32
|
u32
|
||||||
InvalidOpFlag :1,
|
InvalidOpFlag : 1,
|
||||||
DenormalFlag :1,
|
DenormalFlag : 1,
|
||||||
DivideByZeroFlag :1,
|
DivideByZeroFlag : 1,
|
||||||
OverflowFlag :1,
|
OverflowFlag : 1,
|
||||||
UnderflowFlag :1,
|
UnderflowFlag : 1,
|
||||||
PrecisionFlag :1,
|
PrecisionFlag : 1,
|
||||||
|
|
||||||
// This bit is supported only on SSE2 or better CPUs. Setting it to 1 on
|
// This bit is supported only on SSE2 or better CPUs. Setting it to 1 on
|
||||||
// SSE1 cpus will result in an invalid instruction exception when executing
|
// SSE1 cpus will result in an invalid instruction exception when executing
|
||||||
// LDMXSCR.
|
// LDMXSCR.
|
||||||
DenormalsAreZero :1,
|
DenormalsAreZero : 1,
|
||||||
|
|
||||||
InvalidOpMask :1,
|
InvalidOpMask : 1,
|
||||||
DenormalMask :1,
|
DenormalMask : 1,
|
||||||
DivideByZeroMask :1,
|
DivideByZeroMask : 1,
|
||||||
OverflowMask :1,
|
OverflowMask : 1,
|
||||||
UnderflowMask :1,
|
UnderflowMask : 1,
|
||||||
PrecisionMask :1,
|
PrecisionMask : 1,
|
||||||
|
|
||||||
RoundingControl :2,
|
RoundingControl : 2,
|
||||||
FlushToZero :1;
|
FlushToZero : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
SSE_RoundMode GetRoundMode() const;
|
SSE_RoundMode GetRoundMode() const;
|
||||||
SSE_MXCSR& SetRoundMode( SSE_RoundMode mode );
|
SSE_MXCSR &SetRoundMode(SSE_RoundMode mode);
|
||||||
SSE_MXCSR& ClearExceptionFlags();
|
SSE_MXCSR &ClearExceptionFlags();
|
||||||
SSE_MXCSR& EnableExceptions();
|
SSE_MXCSR &EnableExceptions();
|
||||||
SSE_MXCSR& DisableExceptions();
|
SSE_MXCSR &DisableExceptions();
|
||||||
|
|
||||||
SSE_MXCSR& ApplyReserveMask();
|
SSE_MXCSR &ApplyReserveMask();
|
||||||
|
|
||||||
bool operator ==( const SSE_MXCSR& right ) const
|
bool operator==(const SSE_MXCSR &right) const
|
||||||
{
|
{
|
||||||
return bitmask == right.bitmask;
|
return bitmask == right.bitmask;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator !=( const SSE_MXCSR& right ) const
|
bool operator!=(const SSE_MXCSR &right) const
|
||||||
{
|
{
|
||||||
return bitmask != right.bitmask;
|
return bitmask != right.bitmask;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator x86Emitter::xIndirect32() const;
|
operator x86Emitter::xIndirect32() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern SSE_MXCSR MXCSR_Mask;
|
extern SSE_MXCSR MXCSR_Mask;
|
||||||
|
|
||||||
|
|
||||||
extern __aligned16 x86capabilities x86caps;
|
extern __aligned16 x86capabilities x86caps;
|
||||||
|
|
||||||
|
|
|
@ -32,26 +32,30 @@
|
||||||
// CPU information support
|
// CPU information support
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
|
|
||||||
#define cpuid __cpuid
|
#define cpuid __cpuid
|
||||||
#define cpuidex __cpuidex
|
#define cpuidex __cpuidex
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#include <cpuid.h>
|
#include <cpuid.h>
|
||||||
|
|
||||||
static __inline__ __attribute__((always_inline)) void cpuidex(int CPUInfo[], const int InfoType, const int count) {
|
static __inline__ __attribute__((always_inline)) void cpuidex(int CPUInfo[], const int InfoType, const int count)
|
||||||
__cpuid_count(InfoType, count, CPUInfo[0], CPUInfo[1], CPUInfo[2], CPUInfo[3]);
|
{
|
||||||
|
__cpuid_count(InfoType, count, CPUInfo[0], CPUInfo[1], CPUInfo[2], CPUInfo[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static __inline__ __attribute__((always_inline)) void cpuid(int CPUInfo[], const int InfoType) {
|
static __inline__ __attribute__((always_inline)) void cpuid(int CPUInfo[], const int InfoType)
|
||||||
__cpuid(InfoType, CPUInfo[0], CPUInfo[1], CPUInfo[2], CPUInfo[3]);
|
{
|
||||||
|
__cpuid(InfoType, CPUInfo[0], CPUInfo[1], CPUInfo[2], CPUInfo[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static __inline__ __attribute__((always_inline)) unsigned long long _xgetbv(unsigned int index)
|
static __inline__ __attribute__((always_inline)) unsigned long long _xgetbv(unsigned int index)
|
||||||
{
|
{
|
||||||
unsigned int eax, edx;
|
unsigned int eax, edx;
|
||||||
__asm__ __volatile__("xgetbv" : "=a"(eax), "=d"(edx) : "c"(index));
|
__asm__ __volatile__("xgetbv"
|
||||||
return ((unsigned long long)edx << 32) | eax;
|
: "=a"(eax), "=d"(edx)
|
||||||
|
: "c"(index));
|
||||||
|
return ((unsigned long long)edx << 32) | eax;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -61,16 +65,16 @@ static __inline__ __attribute__((always_inline)) unsigned long long _xgetbv(unsi
|
||||||
// Seriously what is so complicated to provided this bunch of intrinsics in clangs.
|
// Seriously what is so complicated to provided this bunch of intrinsics in clangs.
|
||||||
static unsigned int _rotr(unsigned int x, int s)
|
static unsigned int _rotr(unsigned int x, int s)
|
||||||
{
|
{
|
||||||
return (x >> s) | (x << (32 - s));
|
return (x >> s) | (x << (32 - s));
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int _rotl(unsigned int x, int s)
|
static unsigned int _rotl(unsigned int x, int s)
|
||||||
{
|
{
|
||||||
return (x << s) | (x >> (32 - s));
|
return (x << s) | (x >> (32 - s));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Not correctly defined in GCC4.8 and below ! (dunno for VS)
|
// Not correctly defined in GCC4.8 and below ! (dunno for VS)
|
||||||
#ifndef _MM_MK_INSERTPS_NDX
|
#ifndef _MM_MK_INSERTPS_NDX
|
||||||
#define _MM_MK_INSERTPS_NDX(srcField, dstField, zeroMask) (((srcField)<<6) | ((dstField)<<4) | (zeroMask))
|
#define _MM_MK_INSERTPS_NDX(srcField, dstField, zeroMask) (((srcField) << 6) | ((dstField) << 4) | (zeroMask))
|
||||||
#endif
|
#endif
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -18,32 +18,32 @@
|
||||||
|
|
||||||
#include "PrecompiledHeader.h"
|
#include "PrecompiledHeader.h"
|
||||||
|
|
||||||
void* __fastcall _aligned_malloc(size_t size, size_t align)
|
void *__fastcall _aligned_malloc(size_t size, size_t align)
|
||||||
{
|
{
|
||||||
pxAssert( align < 0x10000 );
|
pxAssert(align < 0x10000);
|
||||||
#if defined(__USE_ISOC11) && !defined(ASAN_WORKAROUND) // not supported yet on gcc 4.9
|
#if defined(__USE_ISOC11) && !defined(ASAN_WORKAROUND) // not supported yet on gcc 4.9
|
||||||
return aligned_alloc(align, size);
|
return aligned_alloc(align, size);
|
||||||
#else
|
#else
|
||||||
void *result = 0;
|
void *result = 0;
|
||||||
posix_memalign(&result, align, size);
|
posix_memalign(&result, align, size);
|
||||||
return result;
|
return result;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void* __fastcall pcsx2_aligned_realloc(void* handle, size_t new_size, size_t align, size_t old_size)
|
void *__fastcall pcsx2_aligned_realloc(void *handle, size_t new_size, size_t align, size_t old_size)
|
||||||
{
|
{
|
||||||
pxAssert( align < 0x10000 );
|
pxAssert(align < 0x10000);
|
||||||
|
|
||||||
void* newbuf = _aligned_malloc(new_size, align);
|
void *newbuf = _aligned_malloc(new_size, align);
|
||||||
|
|
||||||
if (newbuf != NULL && handle != NULL) {
|
if (newbuf != NULL && handle != NULL) {
|
||||||
memcpy(newbuf, handle, std::min(old_size, new_size));
|
memcpy(newbuf, handle, std::min(old_size, new_size));
|
||||||
_aligned_free(handle);
|
_aligned_free(handle);
|
||||||
}
|
}
|
||||||
return newbuf;
|
return newbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
__fi void _aligned_free(void* pmem)
|
__fi void _aligned_free(void *pmem)
|
||||||
{
|
{
|
||||||
free(pmem);
|
free(pmem);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,62 +16,61 @@
|
||||||
#include "PrecompiledHeader.h"
|
#include "PrecompiledHeader.h"
|
||||||
#include "CheckedStaticBox.h"
|
#include "CheckedStaticBox.h"
|
||||||
|
|
||||||
CheckedStaticBox::CheckedStaticBox( wxWindow* parent, int orientation, const wxString& title )
|
CheckedStaticBox::CheckedStaticBox(wxWindow *parent, int orientation, const wxString &title)
|
||||||
: wxPanelWithHelpers( parent, wxVERTICAL )
|
: wxPanelWithHelpers(parent, wxVERTICAL)
|
||||||
, ThisSizer( *new wxStaticBoxSizer( orientation, this ) )
|
, ThisSizer(*new wxStaticBoxSizer(orientation, this))
|
||||||
, ThisToggle( *new wxCheckBox( this, wxID_ANY, title, wxPoint( 8, 0 ) ) )
|
, ThisToggle(*new wxCheckBox(this, wxID_ANY, title, wxPoint(8, 0)))
|
||||||
{
|
{
|
||||||
*this += ThisToggle;
|
*this += ThisToggle;
|
||||||
*this += ThisSizer | pxExpand;
|
*this += ThisSizer | pxExpand;
|
||||||
|
|
||||||
// Ensure that the right-side of the static group box isn't too cozy:
|
// Ensure that the right-side of the static group box isn't too cozy:
|
||||||
SetMinWidth( ThisToggle.GetSize().GetWidth() + 32 );
|
SetMinWidth(ThisToggle.GetSize().GetWidth() + 32);
|
||||||
|
|
||||||
Bind(wxEVT_CHECKBOX, &CheckedStaticBox::MainToggle_Click, this, ThisToggle.GetId());
|
Bind(wxEVT_CHECKBOX, &CheckedStaticBox::MainToggle_Click, this, ThisToggle.GetId());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Event handler for click events for the main checkbox (default behavior: enables/disables all child controls)
|
// Event handler for click events for the main checkbox (default behavior: enables/disables all child controls)
|
||||||
// This function can be overridden to implement custom handling of check enable/disable behavior.
|
// This function can be overridden to implement custom handling of check enable/disable behavior.
|
||||||
void CheckedStaticBox::MainToggle_Click( wxCommandEvent& evt )
|
void CheckedStaticBox::MainToggle_Click(wxCommandEvent &evt)
|
||||||
{
|
{
|
||||||
SetValue( evt.IsChecked() );
|
SetValue(evt.IsChecked());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the main checkbox status, and enables/disables all child controls
|
// Sets the main checkbox status, and enables/disables all child controls
|
||||||
// bound to the StaticBox accordingly.
|
// bound to the StaticBox accordingly.
|
||||||
void CheckedStaticBox::SetValue( bool val )
|
void CheckedStaticBox::SetValue(bool val)
|
||||||
{
|
{
|
||||||
wxWindowList& list = GetChildren();
|
wxWindowList &list = GetChildren();
|
||||||
|
|
||||||
for( wxWindowList::iterator iter = list.begin(); iter != list.end(); ++iter)
|
for (wxWindowList::iterator iter = list.begin(); iter != list.end(); ++iter) {
|
||||||
{
|
wxWindow *current = *iter;
|
||||||
wxWindow *current = *iter;
|
if (current != &ThisToggle)
|
||||||
if( current != &ThisToggle )
|
current->Enable(val);
|
||||||
current->Enable( val );
|
}
|
||||||
}
|
ThisToggle.SetValue(val);
|
||||||
ThisToggle.SetValue( val );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckedStaticBox::GetValue() const
|
bool CheckedStaticBox::GetValue() const
|
||||||
{
|
{
|
||||||
return ThisToggle.GetValue();
|
return ThisToggle.GetValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
// This override is here so to only enable the children if both the main toggle and
|
// This override is here so to only enable the children if both the main toggle and
|
||||||
// the enable request are true. If not, disable them!
|
// the enable request are true. If not, disable them!
|
||||||
bool CheckedStaticBox::Enable( bool enable )
|
bool CheckedStaticBox::Enable(bool enable)
|
||||||
{
|
{
|
||||||
if (!_parent::Enable(enable)) return false;
|
if (!_parent::Enable(enable))
|
||||||
|
return false;
|
||||||
|
|
||||||
bool val = enable && ThisToggle.GetValue();
|
bool val = enable && ThisToggle.GetValue();
|
||||||
wxWindowList& list = GetChildren();
|
wxWindowList &list = GetChildren();
|
||||||
|
|
||||||
for( wxWindowList::iterator iter = list.begin(); iter != list.end(); ++iter)
|
for (wxWindowList::iterator iter = list.begin(); iter != list.end(); ++iter) {
|
||||||
{
|
wxWindow *current = *iter;
|
||||||
wxWindow *current = *iter;
|
if (current != &ThisToggle)
|
||||||
if( current != &ThisToggle )
|
current->Enable(val);
|
||||||
current->Enable( val );
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,22 +18,22 @@
|
||||||
#include "TraceLog.h"
|
#include "TraceLog.h"
|
||||||
#include "TlsVariable.inl"
|
#include "TlsVariable.inl"
|
||||||
|
|
||||||
#include "RedtapeWindows.h" // nneded for OutputDebugString
|
#include "RedtapeWindows.h" // nneded for OutputDebugString
|
||||||
|
|
||||||
using namespace Threading;
|
using namespace Threading;
|
||||||
|
|
||||||
// thread-local console indentation setting.
|
// thread-local console indentation setting.
|
||||||
static DeclareTls(int) conlog_Indent( 0 );
|
static DeclareTls(int) conlog_Indent(0);
|
||||||
|
|
||||||
// thread-local console color storage.
|
// thread-local console color storage.
|
||||||
static DeclareTls(ConsoleColors) conlog_Color( DefaultConsoleColor );
|
static DeclareTls(ConsoleColors) conlog_Color(DefaultConsoleColor);
|
||||||
|
|
||||||
#ifdef __POSIX__
|
#ifdef __POSIX__
|
||||||
static FILE *stdout_fp = stdout;
|
static FILE *stdout_fp = stdout;
|
||||||
|
|
||||||
void Console_SetStdout(FILE *fp)
|
void Console_SetStdout(FILE *fp)
|
||||||
{
|
{
|
||||||
stdout_fp = fp;
|
stdout_fp = fp;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -44,33 +44,33 @@ void Console_SetStdout(FILE *fp)
|
||||||
// Important! Only Assert and Null console loggers are allowed during C++ startup init (when
|
// Important! Only Assert and Null console loggers are allowed during C++ startup init (when
|
||||||
// the program or DLL first loads). Other log targets rely on the static buffer and a
|
// the program or DLL first loads). Other log targets rely on the static buffer and a
|
||||||
// threaded mutex lock, which are only valid after C++ initialization has finished.
|
// threaded mutex lock, which are only valid after C++ initialization has finished.
|
||||||
void Console_SetActiveHandler( const IConsoleWriter& writer, FILE* flushfp )
|
void Console_SetActiveHandler(const IConsoleWriter &writer, FILE *flushfp)
|
||||||
{
|
{
|
||||||
pxAssertDev(
|
pxAssertDev(
|
||||||
(writer.WriteRaw != NULL) && (writer.DoWriteLn != NULL) &&
|
(writer.WriteRaw != NULL) && (writer.DoWriteLn != NULL) &&
|
||||||
(writer.Newline != NULL) && (writer.SetTitle != NULL) &&
|
(writer.Newline != NULL) && (writer.SetTitle != NULL) &&
|
||||||
(writer.DoSetColor != NULL),
|
(writer.DoSetColor != NULL),
|
||||||
"Invalid IConsoleWriter object! All function pointer interfaces must be implemented."
|
"Invalid IConsoleWriter object! All function pointer interfaces must be implemented.");
|
||||||
);
|
|
||||||
|
|
||||||
Console = writer;
|
Console = writer;
|
||||||
DevConWriter = writer;
|
DevConWriter = writer;
|
||||||
|
|
||||||
#ifdef PCSX2_DEBUG
|
#ifdef PCSX2_DEBUG
|
||||||
DbgCon = writer;
|
DbgCon = writer;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Writes text to the Visual Studio Output window (Microsoft Windows only).
|
// Writes text to the Visual Studio Output window (Microsoft Windows only).
|
||||||
// On all other platforms this pipes to Stdout instead.
|
// On all other platforms this pipes to Stdout instead.
|
||||||
void MSW_OutputDebugString( const wxString& text )
|
void MSW_OutputDebugString(const wxString &text)
|
||||||
{
|
{
|
||||||
#if defined(__WXMSW__) && !defined(__WXMICROWIN__)
|
#if defined(__WXMSW__) && !defined(__WXMICROWIN__)
|
||||||
static bool hasDebugger = wxIsDebuggerRunning();
|
static bool hasDebugger = wxIsDebuggerRunning();
|
||||||
if( hasDebugger ) OutputDebugString( text );
|
if (hasDebugger)
|
||||||
|
OutputDebugString(text);
|
||||||
#else
|
#else
|
||||||
fputs(text.utf8_str(), stdout_fp);
|
fputs(text.utf8_str(), stdout_fp);
|
||||||
fflush(stdout_fp);
|
fflush(stdout_fp);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,23 +79,23 @@ void MSW_OutputDebugString( const wxString& text )
|
||||||
// ConsoleNull
|
// ConsoleNull
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
static void __concall ConsoleNull_SetTitle( const wxString& title ) {}
|
static void __concall ConsoleNull_SetTitle(const wxString &title) {}
|
||||||
static void __concall ConsoleNull_DoSetColor( ConsoleColors color ) {}
|
static void __concall ConsoleNull_DoSetColor(ConsoleColors color) {}
|
||||||
static void __concall ConsoleNull_Newline() {}
|
static void __concall ConsoleNull_Newline() {}
|
||||||
static void __concall ConsoleNull_DoWrite( const wxString& fmt ) {}
|
static void __concall ConsoleNull_DoWrite(const wxString &fmt) {}
|
||||||
static void __concall ConsoleNull_DoWriteLn( const wxString& fmt ) {}
|
static void __concall ConsoleNull_DoWriteLn(const wxString &fmt) {}
|
||||||
|
|
||||||
const IConsoleWriter ConsoleWriter_Null =
|
const IConsoleWriter ConsoleWriter_Null =
|
||||||
{
|
{
|
||||||
ConsoleNull_DoWrite,
|
ConsoleNull_DoWrite,
|
||||||
ConsoleNull_DoWriteLn,
|
ConsoleNull_DoWriteLn,
|
||||||
ConsoleNull_DoSetColor,
|
ConsoleNull_DoSetColor,
|
||||||
|
|
||||||
ConsoleNull_DoWrite,
|
ConsoleNull_DoWrite,
|
||||||
ConsoleNull_Newline,
|
ConsoleNull_Newline,
|
||||||
ConsoleNull_SetTitle,
|
ConsoleNull_SetTitle,
|
||||||
|
|
||||||
0, // instance-level indentation (should always be 0)
|
0, // instance-level indentation (should always be 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -103,118 +103,133 @@ const IConsoleWriter ConsoleWriter_Null =
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
#if defined(__unix__)
|
#if defined(__unix__)
|
||||||
static __fi const char* GetLinuxConsoleColor(ConsoleColors color)
|
static __fi const char *GetLinuxConsoleColor(ConsoleColors color)
|
||||||
{
|
{
|
||||||
switch(color)
|
switch (color) {
|
||||||
{
|
|
||||||
case Color_Black:
|
case Color_Black:
|
||||||
case Color_StrongBlack: return "\033[30m\033[1m";
|
case Color_StrongBlack:
|
||||||
|
return "\033[30m\033[1m";
|
||||||
|
|
||||||
case Color_Red: return "\033[31m";
|
case Color_Red:
|
||||||
case Color_StrongRed: return "\033[31m\033[1m";
|
return "\033[31m";
|
||||||
|
case Color_StrongRed:
|
||||||
|
return "\033[31m\033[1m";
|
||||||
|
|
||||||
case Color_Green: return "\033[32m";
|
case Color_Green:
|
||||||
case Color_StrongGreen: return "\033[32m\033[1m";
|
return "\033[32m";
|
||||||
|
case Color_StrongGreen:
|
||||||
|
return "\033[32m\033[1m";
|
||||||
|
|
||||||
case Color_Yellow: return "\033[33m";
|
case Color_Yellow:
|
||||||
case Color_StrongYellow: return "\033[33m\033[1m";
|
return "\033[33m";
|
||||||
|
case Color_StrongYellow:
|
||||||
|
return "\033[33m\033[1m";
|
||||||
|
|
||||||
case Color_Blue: return "\033[34m";
|
case Color_Blue:
|
||||||
case Color_StrongBlue: return "\033[34m\033[1m";
|
return "\033[34m";
|
||||||
|
case Color_StrongBlue:
|
||||||
|
return "\033[34m\033[1m";
|
||||||
|
|
||||||
// No orange, so use magenta.
|
// No orange, so use magenta.
|
||||||
case Color_Orange:
|
case Color_Orange:
|
||||||
case Color_Magenta: return "\033[35m";
|
case Color_Magenta:
|
||||||
|
return "\033[35m";
|
||||||
case Color_StrongOrange:
|
case Color_StrongOrange:
|
||||||
case Color_StrongMagenta: return "\033[35m\033[1m";
|
case Color_StrongMagenta:
|
||||||
|
return "\033[35m\033[1m";
|
||||||
|
|
||||||
case Color_Cyan: return "\033[36m";
|
case Color_Cyan:
|
||||||
case Color_StrongCyan: return "\033[36m\033[1m";
|
return "\033[36m";
|
||||||
|
case Color_StrongCyan:
|
||||||
|
return "\033[36m\033[1m";
|
||||||
|
|
||||||
// Use 'white' instead of grey.
|
// Use 'white' instead of grey.
|
||||||
case Color_Gray:
|
case Color_Gray:
|
||||||
case Color_White: return "\033[37m";
|
case Color_White:
|
||||||
|
return "\033[37m";
|
||||||
case Color_StrongGray:
|
case Color_StrongGray:
|
||||||
case Color_StrongWhite: return "\033[37m\033[1m";
|
case Color_StrongWhite:
|
||||||
|
return "\033[37m\033[1m";
|
||||||
|
|
||||||
// On some other value being passed, clear any formatting.
|
// On some other value being passed, clear any formatting.
|
||||||
case Color_Default:
|
case Color_Default:
|
||||||
default: return "\033[0m";
|
default:
|
||||||
|
return "\033[0m";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// One possible default write action at startup and shutdown is to use the stdout.
|
// One possible default write action at startup and shutdown is to use the stdout.
|
||||||
static void __concall ConsoleStdout_DoWrite( const wxString& fmt )
|
static void __concall ConsoleStdout_DoWrite(const wxString &fmt)
|
||||||
{
|
{
|
||||||
MSW_OutputDebugString( fmt );
|
MSW_OutputDebugString(fmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default write action at startup and shutdown is to use the stdout.
|
// Default write action at startup and shutdown is to use the stdout.
|
||||||
static void __concall ConsoleStdout_DoWriteLn( const wxString& fmt )
|
static void __concall ConsoleStdout_DoWriteLn(const wxString &fmt)
|
||||||
{
|
{
|
||||||
MSW_OutputDebugString( fmt + L"\n" );
|
MSW_OutputDebugString(fmt + L"\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __concall ConsoleStdout_Newline()
|
static void __concall ConsoleStdout_Newline()
|
||||||
{
|
{
|
||||||
MSW_OutputDebugString( L"\n" );
|
MSW_OutputDebugString(L"\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __concall ConsoleStdout_DoSetColor( ConsoleColors color )
|
static void __concall ConsoleStdout_DoSetColor(ConsoleColors color)
|
||||||
{
|
{
|
||||||
#if defined(__unix__)
|
#if defined(__unix__)
|
||||||
fprintf(stdout_fp, "\033[0m%s", GetLinuxConsoleColor(color));
|
fprintf(stdout_fp, "\033[0m%s", GetLinuxConsoleColor(color));
|
||||||
fflush(stdout_fp);
|
fflush(stdout_fp);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __concall ConsoleStdout_SetTitle( const wxString& title )
|
static void __concall ConsoleStdout_SetTitle(const wxString &title)
|
||||||
{
|
{
|
||||||
#if defined(__unix__)
|
#if defined(__unix__)
|
||||||
fputs("\033]0;", stdout_fp);
|
fputs("\033]0;", stdout_fp);
|
||||||
fputs(title.utf8_str(), stdout_fp);
|
fputs(title.utf8_str(), stdout_fp);
|
||||||
fputs("\007", stdout_fp);
|
fputs("\007", stdout_fp);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
const IConsoleWriter ConsoleWriter_Stdout =
|
const IConsoleWriter ConsoleWriter_Stdout =
|
||||||
{
|
{
|
||||||
ConsoleStdout_DoWrite, // Writes without newlines go to buffer to avoid error log spam.
|
ConsoleStdout_DoWrite, // Writes without newlines go to buffer to avoid error log spam.
|
||||||
ConsoleStdout_DoWriteLn,
|
ConsoleStdout_DoWriteLn,
|
||||||
ConsoleStdout_DoSetColor,
|
ConsoleStdout_DoSetColor,
|
||||||
|
|
||||||
ConsoleNull_DoWrite, // writes from re-piped stdout are ignored here, lest we create infinite loop hell >_<
|
ConsoleNull_DoWrite, // writes from re-piped stdout are ignored here, lest we create infinite loop hell >_<
|
||||||
ConsoleStdout_Newline,
|
ConsoleStdout_Newline,
|
||||||
ConsoleStdout_SetTitle,
|
ConsoleStdout_SetTitle,
|
||||||
0, // instance-level indentation (should always be 0)
|
0, // instance-level indentation (should always be 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// ConsoleAssert
|
// ConsoleAssert
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
static void __concall ConsoleAssert_DoWrite( const wxString& fmt )
|
static void __concall ConsoleAssert_DoWrite(const wxString &fmt)
|
||||||
{
|
{
|
||||||
pxFail( L"Console class has not been initialized; Message written:\n\t" + fmt );
|
pxFail(L"Console class has not been initialized; Message written:\n\t" + fmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __concall ConsoleAssert_DoWriteLn( const wxString& fmt )
|
static void __concall ConsoleAssert_DoWriteLn(const wxString &fmt)
|
||||||
{
|
{
|
||||||
pxFail( L"Console class has not been initialized; Message written:\n\t" + fmt );
|
pxFail(L"Console class has not been initialized; Message written:\n\t" + fmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
const IConsoleWriter ConsoleWriter_Assert =
|
const IConsoleWriter ConsoleWriter_Assert =
|
||||||
{
|
{
|
||||||
ConsoleAssert_DoWrite,
|
ConsoleAssert_DoWrite,
|
||||||
ConsoleAssert_DoWriteLn,
|
ConsoleAssert_DoWriteLn,
|
||||||
ConsoleNull_DoSetColor,
|
ConsoleNull_DoSetColor,
|
||||||
|
|
||||||
ConsoleNull_DoWrite,
|
ConsoleNull_DoWrite,
|
||||||
ConsoleNull_Newline,
|
ConsoleNull_Newline,
|
||||||
ConsoleNull_SetTitle,
|
ConsoleNull_SetTitle,
|
||||||
|
|
||||||
0, // instance-level indentation (should always be 0)
|
0, // instance-level indentation (should always be 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
// =====================================================================================================
|
// =====================================================================================================
|
||||||
|
@ -227,214 +242,216 @@ const IConsoleWriter ConsoleWriter_Assert =
|
||||||
// glob_indent - this parameter is used to specify a global indentation setting. It is used by
|
// glob_indent - this parameter is used to specify a global indentation setting. It is used by
|
||||||
// WriteLn function, but defaults to 0 for Warning and Error calls. Local indentation always
|
// WriteLn function, but defaults to 0 for Warning and Error calls. Local indentation always
|
||||||
// applies to all writes.
|
// applies to all writes.
|
||||||
wxString IConsoleWriter::_addIndentation( const wxString& src, int glob_indent=0 ) const
|
wxString IConsoleWriter::_addIndentation(const wxString &src, int glob_indent = 0) const
|
||||||
{
|
{
|
||||||
const int indent = glob_indent + _imm_indentation;
|
const int indent = glob_indent + _imm_indentation;
|
||||||
if( indent == 0 ) return src;
|
if (indent == 0)
|
||||||
|
return src;
|
||||||
|
|
||||||
wxString result( src );
|
wxString result(src);
|
||||||
const wxString indentStr( L'\t', indent );
|
const wxString indentStr(L'\t', indent);
|
||||||
result.Replace( L"\n", L"\n" + indentStr );
|
result.Replace(L"\n", L"\n" + indentStr);
|
||||||
return indentStr + result;
|
return indentStr + result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the indentation to be applied to all WriteLn's. The indentation is added to the
|
// Sets the indentation to be applied to all WriteLn's. The indentation is added to the
|
||||||
// primary write, and to any newlines specified within the write. Note that this applies
|
// primary write, and to any newlines specified within the write. Note that this applies
|
||||||
// to calls to WriteLn *only* -- calls to Write bypass the indentation parser.
|
// to calls to WriteLn *only* -- calls to Write bypass the indentation parser.
|
||||||
const IConsoleWriter& IConsoleWriter::SetIndent( int tabcount ) const
|
const IConsoleWriter &IConsoleWriter::SetIndent(int tabcount) const
|
||||||
{
|
{
|
||||||
conlog_Indent += tabcount;
|
conlog_Indent += tabcount;
|
||||||
pxAssert( conlog_Indent >= 0 );
|
pxAssert(conlog_Indent >= 0);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
IConsoleWriter IConsoleWriter::Indent( int tabcount ) const
|
IConsoleWriter IConsoleWriter::Indent(int tabcount) const
|
||||||
{
|
{
|
||||||
IConsoleWriter retval = *this;
|
IConsoleWriter retval = *this;
|
||||||
retval._imm_indentation = tabcount;
|
retval._imm_indentation = tabcount;
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Changes the active console color.
|
// Changes the active console color.
|
||||||
// This color will be unset by calls to colored text methods
|
// This color will be unset by calls to colored text methods
|
||||||
// such as ErrorMsg and Notice.
|
// such as ErrorMsg and Notice.
|
||||||
const IConsoleWriter& IConsoleWriter::SetColor( ConsoleColors color ) const
|
const IConsoleWriter &IConsoleWriter::SetColor(ConsoleColors color) const
|
||||||
{
|
{
|
||||||
// Ignore current color requests since, well, the current color is already set. ;)
|
// Ignore current color requests since, well, the current color is already set. ;)
|
||||||
if( color == Color_Current ) return *this;
|
if (color == Color_Current)
|
||||||
|
return *this;
|
||||||
|
|
||||||
pxAssertMsg( (color > Color_Current) && (color < ConsoleColors_Count), "Invalid ConsoleColor specified." );
|
pxAssertMsg((color > Color_Current) && (color < ConsoleColors_Count), "Invalid ConsoleColor specified.");
|
||||||
|
|
||||||
if( conlog_Color != color )
|
if (conlog_Color != color)
|
||||||
DoSetColor( conlog_Color = color );
|
DoSetColor(conlog_Color = color);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConsoleColors IConsoleWriter::GetColor() const
|
ConsoleColors IConsoleWriter::GetColor() const
|
||||||
{
|
{
|
||||||
return conlog_Color;
|
return conlog_Color;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restores the console color to default (usually black, or low-intensity white if the console uses a black background)
|
// Restores the console color to default (usually black, or low-intensity white if the console uses a black background)
|
||||||
const IConsoleWriter& IConsoleWriter::ClearColor() const
|
const IConsoleWriter &IConsoleWriter::ClearColor() const
|
||||||
{
|
{
|
||||||
if( conlog_Color != DefaultConsoleColor )
|
if (conlog_Color != DefaultConsoleColor)
|
||||||
DoSetColor( conlog_Color = DefaultConsoleColor );
|
DoSetColor(conlog_Color = DefaultConsoleColor);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// ASCII/UTF8 (char*)
|
// ASCII/UTF8 (char*)
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
bool IConsoleWriter::FormatV( const char* fmt, va_list args ) const
|
bool IConsoleWriter::FormatV(const char *fmt, va_list args) const
|
||||||
{
|
{
|
||||||
DoWriteLn( _addIndentation( pxsFmtV(fmt,args), conlog_Indent ) );
|
DoWriteLn(_addIndentation(pxsFmtV(fmt, args), conlog_Indent));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IConsoleWriter::WriteLn( const char* fmt, ... ) const
|
bool IConsoleWriter::WriteLn(const char *fmt, ...) const
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args,fmt);
|
va_start(args, fmt);
|
||||||
FormatV(fmt, args);
|
FormatV(fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IConsoleWriter::WriteLn( ConsoleColors color, const char* fmt, ... ) const
|
bool IConsoleWriter::WriteLn(ConsoleColors color, const char *fmt, ...) const
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args,fmt);
|
va_start(args, fmt);
|
||||||
ConsoleColorScope cs( color );
|
ConsoleColorScope cs(color);
|
||||||
FormatV(fmt, args);
|
FormatV(fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IConsoleWriter::Error( const char* fmt, ... ) const
|
bool IConsoleWriter::Error(const char *fmt, ...) const
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args,fmt);
|
va_start(args, fmt);
|
||||||
ConsoleColorScope cs( Color_StrongRed );
|
ConsoleColorScope cs(Color_StrongRed);
|
||||||
FormatV(fmt, args);
|
FormatV(fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IConsoleWriter::Warning( const char* fmt, ... ) const
|
bool IConsoleWriter::Warning(const char *fmt, ...) const
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args,fmt);
|
va_start(args, fmt);
|
||||||
ConsoleColorScope cs( Color_StrongOrange );
|
ConsoleColorScope cs(Color_StrongOrange);
|
||||||
FormatV(fmt, args);
|
FormatV(fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// Write Variants - Unicode/UTF16 style
|
// Write Variants - Unicode/UTF16 style
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
bool IConsoleWriter::FormatV( const wxChar* fmt, va_list args ) const
|
bool IConsoleWriter::FormatV(const wxChar *fmt, va_list args) const
|
||||||
{
|
{
|
||||||
DoWriteLn( _addIndentation( pxsFmtV( fmt, args ), conlog_Indent ) );
|
DoWriteLn(_addIndentation(pxsFmtV(fmt, args), conlog_Indent));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IConsoleWriter::WriteLn( const wxChar* fmt, ... ) const
|
bool IConsoleWriter::WriteLn(const wxChar *fmt, ...) const
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args,fmt);
|
va_start(args, fmt);
|
||||||
FormatV(fmt,args);
|
FormatV(fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IConsoleWriter::WriteLn( ConsoleColors color, const wxChar* fmt, ... ) const
|
bool IConsoleWriter::WriteLn(ConsoleColors color, const wxChar *fmt, ...) const
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args,fmt);
|
va_start(args, fmt);
|
||||||
ConsoleColorScope cs( color );
|
ConsoleColorScope cs(color);
|
||||||
FormatV(fmt,args);
|
FormatV(fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IConsoleWriter::Error( const wxChar* fmt, ... ) const
|
bool IConsoleWriter::Error(const wxChar *fmt, ...) const
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args,fmt);
|
va_start(args, fmt);
|
||||||
ConsoleColorScope cs( Color_StrongRed );
|
ConsoleColorScope cs(Color_StrongRed);
|
||||||
FormatV(fmt,args);
|
FormatV(fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IConsoleWriter::Warning( const wxChar* fmt, ... ) const
|
bool IConsoleWriter::Warning(const wxChar *fmt, ...) const
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args,fmt);
|
va_start(args, fmt);
|
||||||
ConsoleColorScope cs( Color_StrongOrange );
|
ConsoleColorScope cs(Color_StrongOrange);
|
||||||
FormatV(fmt,args);
|
FormatV(fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// Write Variants - Unknown style
|
// Write Variants - Unknown style
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
bool IConsoleWriter::WriteLn( const wxString fmt, ... ) const
|
bool IConsoleWriter::WriteLn(const wxString fmt, ...) const
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args,fmt);
|
va_start(args, fmt);
|
||||||
FormatV(fmt.wx_str(),args);
|
FormatV(fmt.wx_str(), args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IConsoleWriter::WriteLn( ConsoleColors color, const wxString fmt, ... ) const
|
bool IConsoleWriter::WriteLn(ConsoleColors color, const wxString fmt, ...) const
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args,fmt);
|
va_start(args, fmt);
|
||||||
ConsoleColorScope cs( color );
|
ConsoleColorScope cs(color);
|
||||||
FormatV(fmt.wx_str(),args);
|
FormatV(fmt.wx_str(), args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IConsoleWriter::Error( const wxString fmt, ... ) const
|
bool IConsoleWriter::Error(const wxString fmt, ...) const
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args,fmt);
|
va_start(args, fmt);
|
||||||
ConsoleColorScope cs( Color_StrongRed );
|
ConsoleColorScope cs(Color_StrongRed);
|
||||||
FormatV(fmt.wx_str(),args);
|
FormatV(fmt.wx_str(), args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IConsoleWriter::Warning( const wxString fmt, ... ) const
|
bool IConsoleWriter::Warning(const wxString fmt, ...) const
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args,fmt);
|
va_start(args, fmt);
|
||||||
ConsoleColorScope cs( Color_StrongOrange );
|
ConsoleColorScope cs(Color_StrongOrange);
|
||||||
FormatV(fmt.wx_str(),args);
|
FormatV(fmt.wx_str(), args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -442,73 +459,72 @@ bool IConsoleWriter::Warning( const wxString fmt, ... ) const
|
||||||
// ConsoleColorScope / ConsoleIndentScope
|
// ConsoleColorScope / ConsoleIndentScope
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
ConsoleColorScope::ConsoleColorScope( ConsoleColors newcolor )
|
ConsoleColorScope::ConsoleColorScope(ConsoleColors newcolor)
|
||||||
{
|
{
|
||||||
m_IsScoped = false;
|
m_IsScoped = false;
|
||||||
m_newcolor = newcolor;
|
m_newcolor = newcolor;
|
||||||
EnterScope();
|
EnterScope();
|
||||||
}
|
}
|
||||||
|
|
||||||
ConsoleColorScope::~ConsoleColorScope() throw()
|
ConsoleColorScope::~ConsoleColorScope() throw()
|
||||||
{
|
{
|
||||||
LeaveScope();
|
LeaveScope();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleColorScope::EnterScope()
|
void ConsoleColorScope::EnterScope()
|
||||||
{
|
{
|
||||||
if (!m_IsScoped)
|
if (!m_IsScoped) {
|
||||||
{
|
m_old_color = Console.GetColor();
|
||||||
m_old_color = Console.GetColor();
|
Console.SetColor(m_newcolor);
|
||||||
Console.SetColor( m_newcolor );
|
m_IsScoped = true;
|
||||||
m_IsScoped = true;
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleColorScope::LeaveScope()
|
void ConsoleColorScope::LeaveScope()
|
||||||
{
|
{
|
||||||
m_IsScoped = m_IsScoped && (Console.SetColor( m_old_color ), false);
|
m_IsScoped = m_IsScoped && (Console.SetColor(m_old_color), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConsoleIndentScope::ConsoleIndentScope( int tabs )
|
ConsoleIndentScope::ConsoleIndentScope(int tabs)
|
||||||
{
|
{
|
||||||
m_IsScoped = false;
|
m_IsScoped = false;
|
||||||
m_amount = tabs;
|
m_amount = tabs;
|
||||||
EnterScope();
|
EnterScope();
|
||||||
}
|
}
|
||||||
|
|
||||||
ConsoleIndentScope::~ConsoleIndentScope() throw()
|
ConsoleIndentScope::~ConsoleIndentScope() throw()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
LeaveScope();
|
LeaveScope();
|
||||||
}
|
}
|
||||||
DESTRUCTOR_CATCHALL
|
DESTRUCTOR_CATCHALL
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleIndentScope::EnterScope()
|
void ConsoleIndentScope::EnterScope()
|
||||||
{
|
{
|
||||||
m_IsScoped = m_IsScoped || (Console.SetIndent( m_amount ),true);
|
m_IsScoped = m_IsScoped || (Console.SetIndent(m_amount), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConsoleIndentScope::LeaveScope()
|
void ConsoleIndentScope::LeaveScope()
|
||||||
{
|
{
|
||||||
m_IsScoped = m_IsScoped && (Console.SetIndent( -m_amount ),false);
|
m_IsScoped = m_IsScoped && (Console.SetIndent(-m_amount), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ConsoleAttrScope::ConsoleAttrScope( ConsoleColors newcolor, int indent )
|
ConsoleAttrScope::ConsoleAttrScope(ConsoleColors newcolor, int indent)
|
||||||
{
|
{
|
||||||
m_old_color = Console.GetColor();
|
m_old_color = Console.GetColor();
|
||||||
Console.SetIndent( m_tabsize = indent );
|
Console.SetIndent(m_tabsize = indent);
|
||||||
Console.SetColor( newcolor );
|
Console.SetColor(newcolor);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConsoleAttrScope::~ConsoleAttrScope() throw()
|
ConsoleAttrScope::~ConsoleAttrScope() throw()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
Console.SetColor( m_old_color );
|
Console.SetColor(m_old_color);
|
||||||
Console.SetIndent( -m_tabsize );
|
Console.SetIndent(-m_tabsize);
|
||||||
}
|
}
|
||||||
DESTRUCTOR_CATCHALL
|
DESTRUCTOR_CATCHALL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -520,18 +536,18 @@ ConsoleAttrScope::~ConsoleAttrScope() throw()
|
||||||
// platform specific code). Under windows Stdout will attempt to write to the IDE Debug
|
// platform specific code). Under windows Stdout will attempt to write to the IDE Debug
|
||||||
// console, if one is available (such as running pcsx2 via MSVC). If not available, then
|
// console, if one is available (such as running pcsx2 via MSVC). If not available, then
|
||||||
// the log message will pretty much be lost into the ether.
|
// the log message will pretty much be lost into the ether.
|
||||||
//
|
//
|
||||||
#define _DefaultWriter_ ConsoleWriter_Stdout
|
#define _DefaultWriter_ ConsoleWriter_Stdout
|
||||||
|
|
||||||
IConsoleWriter Console = _DefaultWriter_;
|
IConsoleWriter Console = _DefaultWriter_;
|
||||||
IConsoleWriter DevConWriter = _DefaultWriter_;
|
IConsoleWriter DevConWriter = _DefaultWriter_;
|
||||||
bool DevConWriterEnabled = false;
|
bool DevConWriterEnabled = false;
|
||||||
|
|
||||||
#ifdef PCSX2_DEBUG
|
#ifdef PCSX2_DEBUG
|
||||||
IConsoleWriter DbgConWriter = _DefaultWriter_;
|
IConsoleWriter DbgConWriter = _DefaultWriter_;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NullConsoleWriter NullCon = {};
|
NullConsoleWriter NullCon = {};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// ConsoleLogSource (implementations)
|
// ConsoleLogSource (implementations)
|
||||||
|
@ -539,31 +555,31 @@ NullConsoleWriter NullCon = {};
|
||||||
|
|
||||||
// Writes to the console using the specified color. This overrides the default color setting
|
// Writes to the console using the specified color. This overrides the default color setting
|
||||||
// for this log.
|
// for this log.
|
||||||
bool ConsoleLogSource::WriteV( ConsoleColors color, const char *fmt, va_list list ) const
|
bool ConsoleLogSource::WriteV(ConsoleColors color, const char *fmt, va_list list) const
|
||||||
{
|
{
|
||||||
ConsoleColorScope cs(color);
|
ConsoleColorScope cs(color);
|
||||||
DoWrite( pxsFmtV(fmt,list).c_str() );
|
DoWrite(pxsFmtV(fmt, list).c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ConsoleLogSource::WriteV( ConsoleColors color, const wxChar *fmt, va_list list ) const
|
bool ConsoleLogSource::WriteV(ConsoleColors color, const wxChar *fmt, va_list list) const
|
||||||
{
|
{
|
||||||
ConsoleColorScope cs(color);
|
ConsoleColorScope cs(color);
|
||||||
DoWrite( pxsFmtV(fmt,list).c_str() );
|
DoWrite(pxsFmtV(fmt, list).c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Writes to the console using the source's default color. Note that the source's default
|
// Writes to the console using the source's default color. Note that the source's default
|
||||||
// color will always be used, thus ConsoleColorScope() will not be effectual unless the
|
// color will always be used, thus ConsoleColorScope() will not be effectual unless the
|
||||||
// console's default color is Color_Default.
|
// console's default color is Color_Default.
|
||||||
bool ConsoleLogSource::WriteV( const char *fmt, va_list list ) const
|
bool ConsoleLogSource::WriteV(const char *fmt, va_list list) const
|
||||||
{
|
{
|
||||||
WriteV( DefaultColor, fmt, list );
|
WriteV(DefaultColor, fmt, list);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ConsoleLogSource::WriteV( const wxChar *fmt, va_list list ) const
|
bool ConsoleLogSource::WriteV(const wxChar *fmt, va_list list) const
|
||||||
{
|
{
|
||||||
WriteV( DefaultColor, fmt, list );
|
WriteV(DefaultColor, fmt, list);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
#include <mach/mach_time.h>
|
#include <mach/mach_time.h>
|
||||||
|
|
||||||
#define NELEM(x) \
|
#define NELEM(x) \
|
||||||
((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
|
((sizeof(x) / sizeof(0 [x])) / ((size_t)(!(sizeof(x) % sizeof(0 [x])))))
|
||||||
|
|
||||||
// Darwin (OSX) is a bit different from Linux when requesting properties of
|
// Darwin (OSX) is a bit different from Linux when requesting properties of
|
||||||
// the OS because of its BSD/Mach heritage. Helpfully, most of this code
|
// the OS because of its BSD/Mach heritage. Helpfully, most of this code
|
||||||
|
@ -38,23 +38,23 @@
|
||||||
// failure (not supported by the operating system).
|
// failure (not supported by the operating system).
|
||||||
u64 GetPhysicalMemory()
|
u64 GetPhysicalMemory()
|
||||||
{
|
{
|
||||||
static u64 mem = 0;
|
static u64 mem = 0;
|
||||||
|
|
||||||
// fetch the total memory only once, as its an expensive system call and
|
// fetch the total memory only once, as its an expensive system call and
|
||||||
// doesn't change during the course of the program. Thread-safety is
|
// doesn't change during the course of the program. Thread-safety is
|
||||||
// ensured by atomic operations with full-barriers (usually compiled
|
// ensured by atomic operations with full-barriers (usually compiled
|
||||||
// down to XCHG on x86).
|
// down to XCHG on x86).
|
||||||
if (__atomic_load_n(&mem, __ATOMIC_SEQ_CST) == 0) {
|
if (__atomic_load_n(&mem, __ATOMIC_SEQ_CST) == 0) {
|
||||||
u64 getmem = 0;
|
u64 getmem = 0;
|
||||||
size_t len = sizeof(getmem);
|
size_t len = sizeof(getmem);
|
||||||
int mib[] = { CTL_HW, HW_MEMSIZE };
|
int mib[] = {CTL_HW, HW_MEMSIZE};
|
||||||
if (sysctl(mib, NELEM(mib), &getmem, &len, NULL, 0) < 0) {
|
if (sysctl(mib, NELEM(mib), &getmem, &len, NULL, 0) < 0) {
|
||||||
perror("sysctl:");
|
perror("sysctl:");
|
||||||
}
|
}
|
||||||
__atomic_store_n(&mem, getmem, __ATOMIC_SEQ_CST);
|
__atomic_store_n(&mem, getmem, __ATOMIC_SEQ_CST);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mem;
|
return mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitCPUTicks()
|
void InitCPUTicks()
|
||||||
|
@ -71,26 +71,26 @@ void InitCPUTicks()
|
||||||
// GetTickFrequency() to maintain good precision.
|
// GetTickFrequency() to maintain good precision.
|
||||||
u64 GetTickFrequency()
|
u64 GetTickFrequency()
|
||||||
{
|
{
|
||||||
static u64 freq = 0;
|
static u64 freq = 0;
|
||||||
|
|
||||||
// by the time denom is not 0, the structure will have been fully
|
// by the time denom is not 0, the structure will have been fully
|
||||||
// updated and no more atomic accesses are necessary.
|
// updated and no more atomic accesses are necessary.
|
||||||
if (__atomic_load_n(&freq, __ATOMIC_SEQ_CST) == 0) {
|
if (__atomic_load_n(&freq, __ATOMIC_SEQ_CST) == 0) {
|
||||||
mach_timebase_info_data_t info;
|
mach_timebase_info_data_t info;
|
||||||
|
|
||||||
// mach_timebase_info() is a syscall, very slow, that's why we take
|
// mach_timebase_info() is a syscall, very slow, that's why we take
|
||||||
// pains to only do it once. On x86(-64), the result is guaranteed
|
// pains to only do it once. On x86(-64), the result is guaranteed
|
||||||
// to be info.denom == info.numer == 1 (i.e.: the frequency is 1e9,
|
// to be info.denom == info.numer == 1 (i.e.: the frequency is 1e9,
|
||||||
// which means GetCPUTicks is just nanoseconds).
|
// which means GetCPUTicks is just nanoseconds).
|
||||||
if (mach_timebase_info(&info) != KERN_SUCCESS) {
|
if (mach_timebase_info(&info) != KERN_SUCCESS) {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
// store the calculated value atomically
|
// store the calculated value atomically
|
||||||
__atomic_store_n(&freq, (u64) 1e9 * (u64) info.denom / (u64) info.numer, __ATOMIC_SEQ_CST);
|
__atomic_store_n(&freq, (u64)1e9 * (u64)info.denom / (u64)info.numer, __ATOMIC_SEQ_CST);
|
||||||
}
|
}
|
||||||
|
|
||||||
return freq;
|
return freq;
|
||||||
}
|
}
|
||||||
|
|
||||||
// return the number of "ticks" since some arbitrary, fixed time in the
|
// return the number of "ticks" since some arbitrary, fixed time in the
|
||||||
|
@ -99,52 +99,52 @@ u64 GetTickFrequency()
|
||||||
// nanoseconds.
|
// nanoseconds.
|
||||||
u64 GetCPUTicks()
|
u64 GetCPUTicks()
|
||||||
{
|
{
|
||||||
return mach_absolute_time();
|
return mach_absolute_time();
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString GetOSVersionString()
|
wxString GetOSVersionString()
|
||||||
{
|
{
|
||||||
wxString version;
|
wxString version;
|
||||||
static int initialized = 0;
|
static int initialized = 0;
|
||||||
|
|
||||||
// fetch the OS description only once (thread-safely)
|
// fetch the OS description only once (thread-safely)
|
||||||
if (__atomic_load_n(&initialized, __ATOMIC_SEQ_CST) == 0) {
|
if (__atomic_load_n(&initialized, __ATOMIC_SEQ_CST) == 0) {
|
||||||
char type[32] = {0};
|
char type[32] = {0};
|
||||||
char release[32] = {0};
|
char release[32] = {0};
|
||||||
char arch[32] = {0};
|
char arch[32] = {0};
|
||||||
|
|
||||||
#define SYSCTL_GET(var, base, name) \
|
#define SYSCTL_GET(var, base, name) \
|
||||||
do { \
|
do { \
|
||||||
int mib[] = { base, name }; \
|
int mib[] = {base, name}; \
|
||||||
size_t len = sizeof(var); \
|
size_t len = sizeof(var); \
|
||||||
sysctl(mib, NELEM(mib), NULL, &len, NULL, 0); \
|
sysctl(mib, NELEM(mib), NULL, &len, NULL, 0); \
|
||||||
sysctl(mib, NELEM(mib), var, &len, NULL, 0); \
|
sysctl(mib, NELEM(mib), var, &len, NULL, 0); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
SYSCTL_GET(release, CTL_KERN, KERN_OSRELEASE);
|
SYSCTL_GET(release, CTL_KERN, KERN_OSRELEASE);
|
||||||
SYSCTL_GET(type, CTL_KERN, KERN_OSTYPE);
|
SYSCTL_GET(type, CTL_KERN, KERN_OSTYPE);
|
||||||
SYSCTL_GET(arch, CTL_HW, HW_MACHINE);
|
SYSCTL_GET(arch, CTL_HW, HW_MACHINE);
|
||||||
|
|
||||||
#undef SYSCTL_KERN
|
#undef SYSCTL_KERN
|
||||||
|
|
||||||
// I know strcat is not good, but stpcpy is not universally
|
// I know strcat is not good, but stpcpy is not universally
|
||||||
// available yet.
|
// available yet.
|
||||||
char buf[128] = {0};
|
char buf[128] = {0};
|
||||||
strcat(buf, type);
|
strcat(buf, type);
|
||||||
strcat(buf, " ");
|
strcat(buf, " ");
|
||||||
strcat(buf, release);
|
strcat(buf, release);
|
||||||
strcat(buf, " ");
|
strcat(buf, " ");
|
||||||
strcat(buf, arch);
|
strcat(buf, arch);
|
||||||
|
|
||||||
version = buf;
|
version = buf;
|
||||||
|
|
||||||
__atomic_store_n(&initialized, 1, __ATOMIC_SEQ_CST);
|
__atomic_store_n(&initialized, 1, __ATOMIC_SEQ_CST);
|
||||||
}
|
}
|
||||||
|
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScreensaverAllow(bool allow)
|
void ScreensaverAllow(bool allow)
|
||||||
{
|
{
|
||||||
// no-op
|
// no-op
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,17 +14,17 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cassert> // assert
|
#include <cassert> // assert
|
||||||
|
|
||||||
#include <pthread.h> // pthread_setcancelstate()
|
#include <pthread.h> // pthread_setcancelstate()
|
||||||
|
|
||||||
#include <sys/time.h> // gettimeofday()
|
#include <sys/time.h> // gettimeofday()
|
||||||
|
|
||||||
#include <mach/mach.h>
|
#include <mach/mach.h>
|
||||||
#include <mach/task.h> // semaphore_create() and semaphore_destroy()
|
#include <mach/task.h> // semaphore_create() and semaphore_destroy()
|
||||||
#include <mach/semaphore.h> // semaphore_*()
|
#include <mach/semaphore.h> // semaphore_*()
|
||||||
#include <mach/mach_error.h> // mach_error_string()
|
#include <mach/mach_error.h> // mach_error_string()
|
||||||
#include <mach/mach_time.h> // mach_absolute_time()
|
#include <mach/mach_time.h> // mach_absolute_time()
|
||||||
|
|
||||||
#include "PrecompiledHeader.h"
|
#include "PrecompiledHeader.h"
|
||||||
|
|
||||||
|
@ -47,105 +47,105 @@
|
||||||
//
|
//
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
#define MACH_CHECK(mach_retval) \
|
#define MACH_CHECK(mach_retval) \
|
||||||
do { \
|
do { \
|
||||||
kern_return_t _kr = (mach_retval); \
|
kern_return_t _kr = (mach_retval); \
|
||||||
if (_kr != KERN_SUCCESS) { \
|
if (_kr != KERN_SUCCESS) { \
|
||||||
fprintf(stderr, "mach error: %s", mach_error_string(_kr)); \
|
fprintf(stderr, "mach error: %s", mach_error_string(_kr)); \
|
||||||
assert(_kr == KERN_SUCCESS); \
|
assert(_kr == KERN_SUCCESS); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
Threading::Semaphore::Semaphore()
|
Threading::Semaphore::Semaphore()
|
||||||
{
|
{
|
||||||
// other platforms explicitly make a thread-private (unshared) semaphore
|
// other platforms explicitly make a thread-private (unshared) semaphore
|
||||||
// here. But it seems Mach doesn't support that.
|
// here. But it seems Mach doesn't support that.
|
||||||
MACH_CHECK(semaphore_create(mach_task_self(), (semaphore_t *)&m_sema, SYNC_POLICY_FIFO, 0));
|
MACH_CHECK(semaphore_create(mach_task_self(), (semaphore_t *)&m_sema, SYNC_POLICY_FIFO, 0));
|
||||||
__atomic_store_n(&m_counter, 0, __ATOMIC_SEQ_CST);
|
__atomic_store_n(&m_counter, 0, __ATOMIC_SEQ_CST);
|
||||||
}
|
}
|
||||||
|
|
||||||
Threading::Semaphore::~Semaphore() throw()
|
Threading::Semaphore::~Semaphore() throw()
|
||||||
{
|
{
|
||||||
MACH_CHECK(semaphore_destroy(mach_task_self(), (semaphore_t) m_sema));
|
MACH_CHECK(semaphore_destroy(mach_task_self(), (semaphore_t)m_sema));
|
||||||
__atomic_store_n(&m_counter, 0, __ATOMIC_SEQ_CST);
|
__atomic_store_n(&m_counter, 0, __ATOMIC_SEQ_CST);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Threading::Semaphore::Reset()
|
void Threading::Semaphore::Reset()
|
||||||
{
|
{
|
||||||
MACH_CHECK(semaphore_destroy(mach_task_self(), (semaphore_t) m_sema));
|
MACH_CHECK(semaphore_destroy(mach_task_self(), (semaphore_t)m_sema));
|
||||||
MACH_CHECK(semaphore_create(mach_task_self(), (semaphore_t *) &m_sema, SYNC_POLICY_FIFO, 0));
|
MACH_CHECK(semaphore_create(mach_task_self(), (semaphore_t *)&m_sema, SYNC_POLICY_FIFO, 0));
|
||||||
__atomic_store_n(&m_counter, 0, __ATOMIC_SEQ_CST);
|
__atomic_store_n(&m_counter, 0, __ATOMIC_SEQ_CST);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Threading::Semaphore::Post()
|
void Threading::Semaphore::Post()
|
||||||
{
|
{
|
||||||
MACH_CHECK(semaphore_signal(m_sema));
|
MACH_CHECK(semaphore_signal(m_sema));
|
||||||
__atomic_add_fetch(&m_counter, 1, __ATOMIC_SEQ_CST);
|
__atomic_add_fetch(&m_counter, 1, __ATOMIC_SEQ_CST);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Threading::Semaphore::Post(int multiple)
|
void Threading::Semaphore::Post(int multiple)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < multiple; ++i) {
|
for (int i = 0; i < multiple; ++i) {
|
||||||
MACH_CHECK(semaphore_signal(m_sema));
|
MACH_CHECK(semaphore_signal(m_sema));
|
||||||
}
|
}
|
||||||
__atomic_add_fetch(&m_counter, multiple, __ATOMIC_SEQ_CST);
|
__atomic_add_fetch(&m_counter, multiple, __ATOMIC_SEQ_CST);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Threading::Semaphore::WaitWithoutYield()
|
void Threading::Semaphore::WaitWithoutYield()
|
||||||
{
|
{
|
||||||
pxAssertMsg(!wxThread::IsMain(), "Unyielding semaphore wait issued from the main/gui thread. Please use Wait() instead.");
|
pxAssertMsg(!wxThread::IsMain(), "Unyielding semaphore wait issued from the main/gui thread. Please use Wait() instead.");
|
||||||
MACH_CHECK(semaphore_wait(m_sema));
|
MACH_CHECK(semaphore_wait(m_sema));
|
||||||
__atomic_sub_fetch(&m_counter, 1, __ATOMIC_SEQ_CST);
|
__atomic_sub_fetch(&m_counter, 1, __ATOMIC_SEQ_CST);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Threading::Semaphore::WaitWithoutYield(const wxTimeSpan& timeout)
|
bool Threading::Semaphore::WaitWithoutYield(const wxTimeSpan &timeout)
|
||||||
{
|
{
|
||||||
// This method is the reason why there has to be a special Darwin
|
// This method is the reason why there has to be a special Darwin
|
||||||
// implementation of Semaphore. Note that semaphore_timedwait() is prone
|
// implementation of Semaphore. Note that semaphore_timedwait() is prone
|
||||||
// to returning with KERN_ABORTED, which basically signifies that some
|
// to returning with KERN_ABORTED, which basically signifies that some
|
||||||
// signal has worken it up. The best official "documentation" for
|
// signal has worken it up. The best official "documentation" for
|
||||||
// semaphore_timedwait() is the way it's used in Grand Central Dispatch,
|
// semaphore_timedwait() is the way it's used in Grand Central Dispatch,
|
||||||
// which is open-source.
|
// which is open-source.
|
||||||
|
|
||||||
// on x86 platforms, mach_absolute_time() returns nanoseconds
|
// on x86 platforms, mach_absolute_time() returns nanoseconds
|
||||||
// TODO(aktau): on iOS a scale value from mach_timebase_info will be necessary
|
// TODO(aktau): on iOS a scale value from mach_timebase_info will be necessary
|
||||||
u64 const kOneThousand = 1000;
|
u64 const kOneThousand = 1000;
|
||||||
u64 const kOneBillion = kOneThousand * kOneThousand * kOneThousand;
|
u64 const kOneBillion = kOneThousand * kOneThousand * kOneThousand;
|
||||||
u64 const delta = timeout.GetMilliseconds().GetValue() * (kOneThousand * kOneThousand);
|
u64 const delta = timeout.GetMilliseconds().GetValue() * (kOneThousand * kOneThousand);
|
||||||
mach_timespec_t ts;
|
mach_timespec_t ts;
|
||||||
kern_return_t kr = KERN_ABORTED;
|
kern_return_t kr = KERN_ABORTED;
|
||||||
for (u64 now = mach_absolute_time(), deadline = now + delta;
|
for (u64 now = mach_absolute_time(), deadline = now + delta;
|
||||||
kr == KERN_ABORTED; now = mach_absolute_time()) {
|
kr == KERN_ABORTED; now = mach_absolute_time()) {
|
||||||
if (now > deadline) {
|
if (now > deadline) {
|
||||||
// timed out by definition
|
// timed out by definition
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 timeleft = deadline - now;
|
u64 timeleft = deadline - now;
|
||||||
ts.tv_sec = timeleft / kOneBillion;
|
ts.tv_sec = timeleft / kOneBillion;
|
||||||
ts.tv_nsec = timeleft % kOneBillion;
|
ts.tv_nsec = timeleft % kOneBillion;
|
||||||
|
|
||||||
// possible return values of semaphore_timedwait() (from XNU sources):
|
// possible return values of semaphore_timedwait() (from XNU sources):
|
||||||
// internal kernel val -> return value
|
// internal kernel val -> return value
|
||||||
// THREAD_INTERRUPTED -> KERN_ABORTED
|
// THREAD_INTERRUPTED -> KERN_ABORTED
|
||||||
// THREAD_TIMED_OUT -> KERN_OPERATION_TIMED_OUT
|
// THREAD_TIMED_OUT -> KERN_OPERATION_TIMED_OUT
|
||||||
// THREAD_AWAKENED -> KERN_SUCCESS
|
// THREAD_AWAKENED -> KERN_SUCCESS
|
||||||
// THREAD_RESTART -> KERN_TERMINATED
|
// THREAD_RESTART -> KERN_TERMINATED
|
||||||
// default -> KERN_FAILURE
|
// default -> KERN_FAILURE
|
||||||
kr = semaphore_timedwait(m_sema, ts);
|
kr = semaphore_timedwait(m_sema, ts);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kr == KERN_OPERATION_TIMED_OUT) {
|
if (kr == KERN_OPERATION_TIMED_OUT) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// while it's entirely possible to have KERN_FAILURE here, we should
|
// while it's entirely possible to have KERN_FAILURE here, we should
|
||||||
// probably assert so we can study and correct the actual error here
|
// probably assert so we can study and correct the actual error here
|
||||||
// (the thread dying while someone is wainting for it).
|
// (the thread dying while someone is wainting for it).
|
||||||
MACH_CHECK(kr);
|
MACH_CHECK(kr);
|
||||||
|
|
||||||
__atomic_sub_fetch(&m_counter, 1, __ATOMIC_SEQ_CST);
|
__atomic_sub_fetch(&m_counter, 1, __ATOMIC_SEQ_CST);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a wxApp-safe implementation of Wait, which makes sure and executes the App's
|
// This is a wxApp-safe implementation of Wait, which makes sure and executes the App's
|
||||||
|
@ -155,20 +155,18 @@ bool Threading::Semaphore::WaitWithoutYield(const wxTimeSpan& timeout)
|
||||||
void Threading::Semaphore::Wait()
|
void Threading::Semaphore::Wait()
|
||||||
{
|
{
|
||||||
#if wxUSE_GUI
|
#if wxUSE_GUI
|
||||||
if(!wxThread::IsMain() || (wxTheApp == NULL)) {
|
if (!wxThread::IsMain() || (wxTheApp == NULL)) {
|
||||||
WaitWithoutYield();
|
WaitWithoutYield();
|
||||||
}
|
} else if (_WaitGui_RecursionGuard(L"Semaphore::Wait")) {
|
||||||
else if(_WaitGui_RecursionGuard( L"Semaphore::Wait" )) {
|
ScopedBusyCursor hourglass(Cursor_ReallyBusy);
|
||||||
ScopedBusyCursor hourglass( Cursor_ReallyBusy );
|
WaitWithoutYield();
|
||||||
WaitWithoutYield();
|
} else {
|
||||||
}
|
while (!WaitWithoutYield(def_yieldgui_interval)) {
|
||||||
else {
|
YieldToMain();
|
||||||
while (!WaitWithoutYield(def_yieldgui_interval)) {
|
}
|
||||||
YieldToMain();
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
WaitWithoutYield();
|
WaitWithoutYield();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,30 +179,29 @@ void Threading::Semaphore::Wait()
|
||||||
// false if the wait timed out before the semaphore was signaled, or true if the signal was
|
// false if the wait timed out before the semaphore was signaled, or true if the signal was
|
||||||
// reached prior to timeout.
|
// reached prior to timeout.
|
||||||
//
|
//
|
||||||
bool Threading::Semaphore::Wait(const wxTimeSpan& timeout)
|
bool Threading::Semaphore::Wait(const wxTimeSpan &timeout)
|
||||||
{
|
{
|
||||||
#if wxUSE_GUI
|
#if wxUSE_GUI
|
||||||
if(!wxThread::IsMain() || (wxTheApp == NULL)) {
|
if (!wxThread::IsMain() || (wxTheApp == NULL)) {
|
||||||
return WaitWithoutYield(timeout);
|
return WaitWithoutYield(timeout);
|
||||||
}
|
} else if (_WaitGui_RecursionGuard(L"Semaphore::TimedWait")) {
|
||||||
else if (_WaitGui_RecursionGuard( L"Semaphore::TimedWait")) {
|
ScopedBusyCursor hourglass(Cursor_ReallyBusy);
|
||||||
ScopedBusyCursor hourglass(Cursor_ReallyBusy);
|
return WaitWithoutYield(timeout);
|
||||||
return WaitWithoutYield(timeout);
|
} else {
|
||||||
}
|
//ScopedBusyCursor hourglass( Cursor_KindaBusy );
|
||||||
else {
|
wxTimeSpan countdown((timeout));
|
||||||
//ScopedBusyCursor hourglass( Cursor_KindaBusy );
|
|
||||||
wxTimeSpan countdown((timeout));
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (WaitWithoutYield(def_yieldgui_interval)) break;
|
if (WaitWithoutYield(def_yieldgui_interval))
|
||||||
YieldToMain();
|
break;
|
||||||
countdown -= def_yieldgui_interval;
|
YieldToMain();
|
||||||
} while (countdown.GetMilliseconds() > 0);
|
countdown -= def_yieldgui_interval;
|
||||||
|
} while (countdown.GetMilliseconds() > 0);
|
||||||
|
|
||||||
return countdown.GetMilliseconds() > 0;
|
return countdown.GetMilliseconds() > 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
return WaitWithoutYield(timeout);
|
return WaitWithoutYield(timeout);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,21 +220,21 @@ bool Threading::Semaphore::Wait(const wxTimeSpan& timeout)
|
||||||
// POSIX threads), this should work. -- aktau
|
// POSIX threads), this should work. -- aktau
|
||||||
void Threading::Semaphore::WaitNoCancel()
|
void Threading::Semaphore::WaitNoCancel()
|
||||||
{
|
{
|
||||||
int oldstate;
|
int oldstate;
|
||||||
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
|
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
|
||||||
Wait();
|
Wait();
|
||||||
pthread_setcancelstate(oldstate, NULL);
|
pthread_setcancelstate(oldstate, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Threading::Semaphore::WaitNoCancel(const wxTimeSpan& timeout)
|
void Threading::Semaphore::WaitNoCancel(const wxTimeSpan &timeout)
|
||||||
{
|
{
|
||||||
int oldstate;
|
int oldstate;
|
||||||
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
|
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
|
||||||
Wait(timeout);
|
Wait(timeout);
|
||||||
pthread_setcancelstate(oldstate, NULL);
|
pthread_setcancelstate(oldstate, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Threading::Semaphore::Count()
|
int Threading::Semaphore::Count()
|
||||||
{
|
{
|
||||||
return __atomic_load_n(&m_counter, __ATOMIC_SEQ_CST);
|
return __atomic_load_n(&m_counter, __ATOMIC_SEQ_CST);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#if !defined(__APPLE__)
|
#if !defined(__APPLE__)
|
||||||
# error "DarwinThreads.cpp should only be compiled by projects or makefiles targeted at OSX."
|
#error "DarwinThreads.cpp should only be compiled by projects or makefiles targeted at OSX."
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#include <mach/mach_init.h>
|
#include <mach/mach_init.h>
|
||||||
|
@ -30,7 +30,7 @@
|
||||||
// the LOCK prefix. The prefix works on single core CPUs fine (but is slow), but not
|
// the LOCK prefix. The prefix works on single core CPUs fine (but is slow), but not
|
||||||
// having the LOCK prefix is very bad indeed.
|
// having the LOCK prefix is very bad indeed.
|
||||||
|
|
||||||
__forceinline void Threading::Sleep( int ms )
|
__forceinline void Threading::Sleep(int ms)
|
||||||
{
|
{
|
||||||
usleep(1000 * ms);
|
usleep(1000 * ms);
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ __forceinline void Threading::SpinWait()
|
||||||
{
|
{
|
||||||
// If this doesn't compile you can just comment it out (it only serves as a
|
// If this doesn't compile you can just comment it out (it only serves as a
|
||||||
// performance hint and isn't required).
|
// performance hint and isn't required).
|
||||||
__asm__ ( "pause" );
|
__asm__("pause");
|
||||||
}
|
}
|
||||||
|
|
||||||
__forceinline void Threading::EnableHiresScheduler()
|
__forceinline void Threading::EnableHiresScheduler()
|
||||||
|
@ -66,21 +66,22 @@ u64 Threading::GetThreadTicksPerSecond()
|
||||||
|
|
||||||
// gets the CPU time used by the current thread (both system and user), in
|
// gets the CPU time used by the current thread (both system and user), in
|
||||||
// microseconds, returns 0 on failure
|
// microseconds, returns 0 on failure
|
||||||
static u64 getthreadtime(thread_port_t thread) {
|
static u64 getthreadtime(thread_port_t thread)
|
||||||
|
{
|
||||||
mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
|
mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
|
||||||
thread_basic_info_data_t info;
|
thread_basic_info_data_t info;
|
||||||
|
|
||||||
kern_return_t kr = thread_info(thread, THREAD_BASIC_INFO,
|
kern_return_t kr = thread_info(thread, THREAD_BASIC_INFO,
|
||||||
(thread_info_t) &info, &count);
|
(thread_info_t)&info, &count);
|
||||||
if (kr != KERN_SUCCESS) {
|
if (kr != KERN_SUCCESS) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add system and user time
|
// add system and user time
|
||||||
return (u64) info.user_time.seconds * (u64) 1e6 +
|
return (u64)info.user_time.seconds * (u64)1e6 +
|
||||||
(u64) info.user_time.microseconds +
|
(u64)info.user_time.microseconds +
|
||||||
(u64) info.system_time.seconds * (u64) 1e6 +
|
(u64)info.system_time.seconds * (u64)1e6 +
|
||||||
(u64) info.system_time.microseconds;
|
(u64)info.system_time.microseconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the current timestamp (not relative to a real world clock) in
|
// Returns the current timestamp (not relative to a real world clock) in
|
||||||
|
@ -109,19 +110,19 @@ u64 Threading::pxThread::GetCpuTime() const
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return getthreadtime((thread_port_t) m_native_id) * 10ULL;
|
return getthreadtime((thread_port_t)m_native_id) * 10ULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Threading::pxThread::_platform_specific_OnStartInThread()
|
void Threading::pxThread::_platform_specific_OnStartInThread()
|
||||||
{
|
{
|
||||||
m_native_id = (uptr) mach_thread_self();
|
m_native_id = (uptr)mach_thread_self();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Threading::pxThread::_platform_specific_OnCleanupInThread()
|
void Threading::pxThread::_platform_specific_OnCleanupInThread()
|
||||||
{
|
{
|
||||||
// cleanup of handles that were upened in
|
// cleanup of handles that were upened in
|
||||||
// _platform_specific_OnStartInThread
|
// _platform_specific_OnStartInThread
|
||||||
mach_port_deallocate(mach_task_self(), (thread_port_t) m_native_id);
|
mach_port_deallocate(mach_task_self(), (thread_port_t)m_native_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// name can be up to 16 bytes
|
// name can be up to 16 bytes
|
||||||
|
|
|
@ -43,37 +43,37 @@ Fnptr_OutOfMemory pxDoOutOfMemory = NULL;
|
||||||
// const false).
|
// const false).
|
||||||
//
|
//
|
||||||
#ifdef PCSX2_DEVBUILD
|
#ifdef PCSX2_DEVBUILD
|
||||||
# define DEVASSERT_INLINE __noinline
|
#define DEVASSERT_INLINE __noinline
|
||||||
#else
|
#else
|
||||||
# define DEVASSERT_INLINE __fi
|
#define DEVASSERT_INLINE __fi
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Using a threadlocal assertion guard. Separate threads can assert at the same time.
|
// Using a threadlocal assertion guard. Separate threads can assert at the same time.
|
||||||
// That's ok. What we don't want is the *same* thread recurse-asserting.
|
// That's ok. What we don't want is the *same* thread recurse-asserting.
|
||||||
static DeclareTls(int) s_assert_guard( 0 );
|
static DeclareTls(int) s_assert_guard(0);
|
||||||
|
|
||||||
pxDoAssertFnType* pxDoAssert = pxAssertImpl_LogIt;
|
pxDoAssertFnType *pxDoAssert = pxAssertImpl_LogIt;
|
||||||
|
|
||||||
// make life easier for people using VC++ IDE by using this format, which allows double-click
|
// make life easier for people using VC++ IDE by using this format, which allows double-click
|
||||||
// response times from the Output window...
|
// response times from the Output window...
|
||||||
wxString DiagnosticOrigin::ToString( const wxChar* msg ) const
|
wxString DiagnosticOrigin::ToString(const wxChar *msg) const
|
||||||
{
|
{
|
||||||
FastFormatUnicode message;
|
FastFormatUnicode message;
|
||||||
|
|
||||||
message.Write( L"%ls(%d) : assertion failed:\n", srcfile, line );
|
message.Write(L"%ls(%d) : assertion failed:\n", srcfile, line);
|
||||||
|
|
||||||
if( function != NULL )
|
if (function != NULL)
|
||||||
message.Write( " Function: %s\n", function );
|
message.Write(" Function: %s\n", function);
|
||||||
|
|
||||||
message.Write(L" Thread: %s\n", WX_STR(Threading::pxGetCurrentThreadName()) );
|
message.Write(L" Thread: %s\n", WX_STR(Threading::pxGetCurrentThreadName()));
|
||||||
|
|
||||||
if( condition != NULL )
|
if (condition != NULL)
|
||||||
message.Write(L" Condition: %ls\n", condition);
|
message.Write(L" Condition: %ls\n", condition);
|
||||||
|
|
||||||
if( msg != NULL )
|
if (msg != NULL)
|
||||||
message.Write(L" Message: %ls\n", msg);
|
message.Write(L" Message: %ls\n", msg);
|
||||||
|
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -83,71 +83,72 @@ void pxTrap()
|
||||||
#if defined(__WXMSW__) && !defined(__WXMICROWIN__)
|
#if defined(__WXMSW__) && !defined(__WXMICROWIN__)
|
||||||
__debugbreak();
|
__debugbreak();
|
||||||
#elif defined(__WXMAC__) && !defined(__DARWIN__)
|
#elif defined(__WXMAC__) && !defined(__DARWIN__)
|
||||||
#if __powerc
|
#if __powerc
|
||||||
Debugger();
|
Debugger();
|
||||||
#else
|
#else
|
||||||
SysBreak();
|
SysBreak();
|
||||||
#endif
|
#endif
|
||||||
#elif defined(_MSL_USING_MW_C_HEADERS) && _MSL_USING_MW_C_HEADERS
|
#elif defined(_MSL_USING_MW_C_HEADERS) && _MSL_USING_MW_C_HEADERS
|
||||||
Debugger();
|
Debugger();
|
||||||
#elif defined(__UNIX__)
|
#elif defined(__UNIX__)
|
||||||
raise(SIGTRAP);
|
raise(SIGTRAP);
|
||||||
#else
|
#else
|
||||||
// TODO
|
// TODO
|
||||||
#endif // Win/Unix
|
#endif // Win/Unix
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool pxAssertImpl_LogIt( const DiagnosticOrigin& origin, const wxChar *msg )
|
bool pxAssertImpl_LogIt(const DiagnosticOrigin &origin, const wxChar *msg)
|
||||||
{
|
{
|
||||||
//wxLogError( L"%s", origin.ToString( msg ).c_str() );
|
//wxLogError( L"%s", origin.ToString( msg ).c_str() );
|
||||||
wxMessageOutputDebug().Printf( L"%s", origin.ToString( msg ).c_str() );
|
wxMessageOutputDebug().Printf(L"%s", origin.ToString(msg).c_str());
|
||||||
pxTrap();
|
pxTrap();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DEVASSERT_INLINE void pxOnAssert( const DiagnosticOrigin& origin, const wxChar* msg )
|
DEVASSERT_INLINE void pxOnAssert(const DiagnosticOrigin &origin, const wxChar *msg)
|
||||||
{
|
{
|
||||||
// Recursion guard: Allow at least one recursive call. This is useful because sometimes
|
// Recursion guard: Allow at least one recursive call. This is useful because sometimes
|
||||||
// we get meaningless assertions while unwinding stack traces after exceptions have occurred.
|
// we get meaningless assertions while unwinding stack traces after exceptions have occurred.
|
||||||
|
|
||||||
RecursionGuard guard( s_assert_guard );
|
RecursionGuard guard(s_assert_guard);
|
||||||
if (guard.Counter > 2) { return pxTrap(); }
|
if (guard.Counter > 2) {
|
||||||
|
return pxTrap();
|
||||||
|
}
|
||||||
|
|
||||||
// wxWidgets doesn't come with debug builds on some Linux distros, and other distros make
|
// wxWidgets doesn't come with debug builds on some Linux distros, and other distros make
|
||||||
// it difficult to use the debug build (compilation failures). To handle these I've had to
|
// it difficult to use the debug build (compilation failures). To handle these I've had to
|
||||||
// bypass the internal wxWidgets assertion handler entirely, since it may not exist even if
|
// bypass the internal wxWidgets assertion handler entirely, since it may not exist even if
|
||||||
// PCSX2 itself is compiled in debug mode (assertions enabled).
|
// PCSX2 itself is compiled in debug mode (assertions enabled).
|
||||||
|
|
||||||
bool trapit;
|
bool trapit;
|
||||||
|
|
||||||
if( pxDoAssert == NULL )
|
if (pxDoAssert == NULL) {
|
||||||
{
|
// Note: Format uses MSVC's syntax for output window hotlinking.
|
||||||
// Note: Format uses MSVC's syntax for output window hotlinking.
|
trapit = pxAssertImpl_LogIt(origin, msg);
|
||||||
trapit = pxAssertImpl_LogIt( origin, msg );
|
} else {
|
||||||
}
|
trapit = pxDoAssert(origin, msg);
|
||||||
else
|
}
|
||||||
{
|
|
||||||
trapit = pxDoAssert( origin, msg );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( trapit ) { pxTrap(); }
|
if (trapit) {
|
||||||
|
pxTrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__fi void pxOnAssert( const DiagnosticOrigin& origin, const char* msg)
|
__fi void pxOnAssert(const DiagnosticOrigin &origin, const char *msg)
|
||||||
{
|
{
|
||||||
pxOnAssert( origin, fromUTF8(msg) );
|
pxOnAssert(origin, fromUTF8(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
__fi void pxOnAssert( const DiagnosticOrigin& origin, const wxString& msg)
|
__fi void pxOnAssert(const DiagnosticOrigin &origin, const wxString &msg)
|
||||||
{
|
{
|
||||||
pxOnAssert( origin, msg.wc_str() );
|
pxOnAssert(origin, msg.wc_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
__fi void pxOnAssert( const DiagnosticOrigin& origin, const FastFormatUnicode& msg)
|
__fi void pxOnAssert(const DiagnosticOrigin &origin, const FastFormatUnicode &msg)
|
||||||
{
|
{
|
||||||
pxOnAssert( origin, msg.c_str());
|
pxOnAssert(origin, msg.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -156,136 +157,132 @@ __fi void pxOnAssert( const DiagnosticOrigin& origin, const FastFormatUnicode& m
|
||||||
|
|
||||||
BaseException::~BaseException() throw() {}
|
BaseException::~BaseException() throw() {}
|
||||||
|
|
||||||
BaseException& BaseException::SetBothMsgs( const wxChar* msg_diag )
|
BaseException &BaseException::SetBothMsgs(const wxChar *msg_diag)
|
||||||
{
|
{
|
||||||
m_message_user = msg_diag ? wxString(wxGetTranslation( msg_diag )) : wxString("");
|
m_message_user = msg_diag ? wxString(wxGetTranslation(msg_diag)) : wxString("");
|
||||||
return SetDiagMsg( msg_diag );
|
return SetDiagMsg(msg_diag);
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseException& BaseException::SetDiagMsg( const wxString& msg_diag )
|
BaseException &BaseException::SetDiagMsg(const wxString &msg_diag)
|
||||||
{
|
{
|
||||||
m_message_diag = msg_diag;
|
m_message_diag = msg_diag;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
BaseException& BaseException::SetUserMsg( const wxString& msg_user )
|
BaseException &BaseException::SetUserMsg(const wxString &msg_user)
|
||||||
{
|
{
|
||||||
m_message_user = msg_user;
|
m_message_user = msg_user;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString BaseException::FormatDiagnosticMessage() const
|
wxString BaseException::FormatDiagnosticMessage() const
|
||||||
{
|
{
|
||||||
return m_message_diag;
|
return m_message_diag;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString BaseException::FormatDisplayMessage() const
|
wxString BaseException::FormatDisplayMessage() const
|
||||||
{
|
{
|
||||||
return m_message_user.IsEmpty() ? m_message_diag : m_message_user;
|
return m_message_user.IsEmpty() ? m_message_diag : m_message_user;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// Exception::RuntimeError (implementations)
|
// Exception::RuntimeError (implementations)
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
Exception::RuntimeError::RuntimeError( const std::runtime_error& ex, const wxString& prefix )
|
Exception::RuntimeError::RuntimeError(const std::runtime_error &ex, const wxString &prefix)
|
||||||
{
|
{
|
||||||
IsSilent = false;
|
IsSilent = false;
|
||||||
|
|
||||||
SetDiagMsg( pxsFmt( L"STL Runtime Error%s: %s",
|
SetDiagMsg(pxsFmt(L"STL Runtime Error%s: %s",
|
||||||
(prefix.IsEmpty() ? L"" : pxsFmt(L" (%s)", WX_STR(prefix)).c_str()),
|
(prefix.IsEmpty() ? L"" : pxsFmt(L" (%s)", WX_STR(prefix)).c_str()),
|
||||||
WX_STR(fromUTF8( ex.what() ))
|
WX_STR(fromUTF8(ex.what()))));
|
||||||
) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Exception::RuntimeError::RuntimeError( const std::exception& ex, const wxString& prefix )
|
Exception::RuntimeError::RuntimeError(const std::exception &ex, const wxString &prefix)
|
||||||
{
|
{
|
||||||
IsSilent = false;
|
IsSilent = false;
|
||||||
|
|
||||||
SetDiagMsg( pxsFmt( L"STL Exception%s: %s",
|
SetDiagMsg(pxsFmt(L"STL Exception%s: %s",
|
||||||
(prefix.IsEmpty() ? L"" : pxsFmt(L" (%s)", WX_STR(prefix)).c_str()),
|
(prefix.IsEmpty() ? L"" : pxsFmt(L" (%s)", WX_STR(prefix)).c_str()),
|
||||||
WX_STR(fromUTF8( ex.what() ))
|
WX_STR(fromUTF8(ex.what()))));
|
||||||
) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// Exception::OutOfMemory (implementations)
|
// Exception::OutOfMemory (implementations)
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
Exception::OutOfMemory::OutOfMemory( const wxString& allocdesc )
|
Exception::OutOfMemory::OutOfMemory(const wxString &allocdesc)
|
||||||
{
|
{
|
||||||
AllocDescription = allocdesc;
|
AllocDescription = allocdesc;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString Exception::OutOfMemory::FormatDiagnosticMessage() const
|
wxString Exception::OutOfMemory::FormatDiagnosticMessage() const
|
||||||
{
|
{
|
||||||
FastFormatUnicode retmsg;
|
FastFormatUnicode retmsg;
|
||||||
retmsg.Write(L"Out of memory");
|
retmsg.Write(L"Out of memory");
|
||||||
if (!AllocDescription.IsEmpty())
|
if (!AllocDescription.IsEmpty())
|
||||||
retmsg.Write(L" while allocating '%s'", WX_STR(AllocDescription));
|
retmsg.Write(L" while allocating '%s'", WX_STR(AllocDescription));
|
||||||
|
|
||||||
if (!m_message_diag.IsEmpty())
|
if (!m_message_diag.IsEmpty())
|
||||||
retmsg.Write(L":\n%s", WX_STR(m_message_diag));
|
retmsg.Write(L":\n%s", WX_STR(m_message_diag));
|
||||||
|
|
||||||
return retmsg;
|
return retmsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString Exception::OutOfMemory::FormatDisplayMessage() const
|
wxString Exception::OutOfMemory::FormatDisplayMessage() const
|
||||||
{
|
{
|
||||||
FastFormatUnicode retmsg;
|
FastFormatUnicode retmsg;
|
||||||
retmsg.Write( L"%s", _("Oh noes! Out of memory!") );
|
retmsg.Write(L"%s", _("Oh noes! Out of memory!"));
|
||||||
|
|
||||||
if (!m_message_user.IsEmpty())
|
if (!m_message_user.IsEmpty())
|
||||||
retmsg.Write(L"\n\n%s", WX_STR(m_message_user));
|
retmsg.Write(L"\n\n%s", WX_STR(m_message_user));
|
||||||
|
|
||||||
return retmsg;
|
return retmsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// Exception::VirtualMemoryMapConflict (implementations)
|
// Exception::VirtualMemoryMapConflict (implementations)
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
Exception::VirtualMemoryMapConflict::VirtualMemoryMapConflict( const wxString& allocdesc )
|
Exception::VirtualMemoryMapConflict::VirtualMemoryMapConflict(const wxString &allocdesc)
|
||||||
{
|
{
|
||||||
AllocDescription = allocdesc;
|
AllocDescription = allocdesc;
|
||||||
m_message_user = _("Virtual memory mapping failure! Your system may have conflicting device drivers, services, or may simply have insufficient memory or resources to meet PCSX2's lofty needs.");
|
m_message_user = _("Virtual memory mapping failure! Your system may have conflicting device drivers, services, or may simply have insufficient memory or resources to meet PCSX2's lofty needs.");
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString Exception::VirtualMemoryMapConflict::FormatDiagnosticMessage() const
|
wxString Exception::VirtualMemoryMapConflict::FormatDiagnosticMessage() const
|
||||||
{
|
{
|
||||||
FastFormatUnicode retmsg;
|
FastFormatUnicode retmsg;
|
||||||
retmsg.Write(L"Virtual memory map failed");
|
retmsg.Write(L"Virtual memory map failed");
|
||||||
if (!AllocDescription.IsEmpty())
|
if (!AllocDescription.IsEmpty())
|
||||||
retmsg.Write(L" while reserving '%s'", WX_STR(AllocDescription));
|
retmsg.Write(L" while reserving '%s'", WX_STR(AllocDescription));
|
||||||
|
|
||||||
if (!m_message_diag.IsEmpty())
|
if (!m_message_diag.IsEmpty())
|
||||||
retmsg.Write(L":\n%s", WX_STR(m_message_diag));
|
retmsg.Write(L":\n%s", WX_STR(m_message_diag));
|
||||||
|
|
||||||
return retmsg;
|
return retmsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString Exception::VirtualMemoryMapConflict::FormatDisplayMessage() const
|
wxString Exception::VirtualMemoryMapConflict::FormatDisplayMessage() const
|
||||||
{
|
{
|
||||||
FastFormatUnicode retmsg;
|
FastFormatUnicode retmsg;
|
||||||
retmsg.Write( L"%s",
|
retmsg.Write(L"%s",
|
||||||
pxE( L"There is not enough virtual memory available, or necessary virtual memory mappings have already been reserved by other processes, services, or DLLs."
|
pxE(L"There is not enough virtual memory available, or necessary virtual memory mappings have already been reserved by other processes, services, or DLLs."));
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!m_message_diag.IsEmpty())
|
if (!m_message_diag.IsEmpty())
|
||||||
retmsg.Write(L"\n\n%s", WX_STR(m_message_diag));
|
retmsg.Write(L"\n\n%s", WX_STR(m_message_diag));
|
||||||
|
|
||||||
return retmsg;
|
return retmsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
wxString Exception::CancelEvent::FormatDiagnosticMessage() const
|
wxString Exception::CancelEvent::FormatDiagnosticMessage() const
|
||||||
{
|
{
|
||||||
return L"Action canceled: " + m_message_diag;
|
return L"Action canceled: " + m_message_diag;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString Exception::CancelEvent::FormatDisplayMessage() const
|
wxString Exception::CancelEvent::FormatDisplayMessage() const
|
||||||
{
|
{
|
||||||
return L"Action canceled: " + m_message_diag;
|
return L"Action canceled: " + m_message_diag;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -293,40 +290,40 @@ wxString Exception::CancelEvent::FormatDisplayMessage() const
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
wxString Exception::BadStream::FormatDiagnosticMessage() const
|
wxString Exception::BadStream::FormatDiagnosticMessage() const
|
||||||
{
|
{
|
||||||
FastFormatUnicode retval;
|
FastFormatUnicode retval;
|
||||||
_formatDiagMsg(retval);
|
_formatDiagMsg(retval);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString Exception::BadStream::FormatDisplayMessage() const
|
wxString Exception::BadStream::FormatDisplayMessage() const
|
||||||
{
|
{
|
||||||
FastFormatUnicode retval;
|
FastFormatUnicode retval;
|
||||||
_formatUserMsg(retval);
|
_formatUserMsg(retval);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Exception::BadStream::_formatDiagMsg( FastFormatUnicode& dest ) const
|
void Exception::BadStream::_formatDiagMsg(FastFormatUnicode &dest) const
|
||||||
{
|
{
|
||||||
dest.Write( L"Path: " );
|
dest.Write(L"Path: ");
|
||||||
if (!StreamName.IsEmpty())
|
if (!StreamName.IsEmpty())
|
||||||
dest.Write( L"%s", WX_STR(StreamName) );
|
dest.Write(L"%s", WX_STR(StreamName));
|
||||||
else
|
else
|
||||||
dest.Write( L"[Unnamed or unknown]" );
|
dest.Write(L"[Unnamed or unknown]");
|
||||||
|
|
||||||
if (!m_message_diag.IsEmpty())
|
if (!m_message_diag.IsEmpty())
|
||||||
dest.Write(L"\n%s", WX_STR(m_message_diag));
|
dest.Write(L"\n%s", WX_STR(m_message_diag));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Exception::BadStream::_formatUserMsg( FastFormatUnicode& dest ) const
|
void Exception::BadStream::_formatUserMsg(FastFormatUnicode &dest) const
|
||||||
{
|
{
|
||||||
dest.Write( _("Path: ") );
|
dest.Write(_("Path: "));
|
||||||
if (!StreamName.IsEmpty())
|
if (!StreamName.IsEmpty())
|
||||||
dest.Write( L"%s", WX_STR(StreamName) );
|
dest.Write(L"%s", WX_STR(StreamName));
|
||||||
else
|
else
|
||||||
dest.Write( _("[Unnamed or unknown]") );
|
dest.Write(_("[Unnamed or unknown]"));
|
||||||
|
|
||||||
if (!m_message_user.IsEmpty())
|
if (!m_message_user.IsEmpty())
|
||||||
dest.Write(L"\n%s", WX_STR(m_message_user));
|
dest.Write(L"\n%s", WX_STR(m_message_user));
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -334,19 +331,19 @@ void Exception::BadStream::_formatUserMsg( FastFormatUnicode& dest ) const
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
wxString Exception::CannotCreateStream::FormatDiagnosticMessage() const
|
wxString Exception::CannotCreateStream::FormatDiagnosticMessage() const
|
||||||
{
|
{
|
||||||
FastFormatUnicode retval;
|
FastFormatUnicode retval;
|
||||||
retval.Write("File could not be created.");
|
retval.Write("File could not be created.");
|
||||||
_formatDiagMsg(retval);
|
_formatDiagMsg(retval);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString Exception::CannotCreateStream::FormatDisplayMessage() const
|
wxString Exception::CannotCreateStream::FormatDisplayMessage() const
|
||||||
{
|
{
|
||||||
FastFormatUnicode retval;
|
FastFormatUnicode retval;
|
||||||
retval.Write(_("A file could not be created."));
|
retval.Write(_("A file could not be created."));
|
||||||
retval.Write("\n");
|
retval.Write("\n");
|
||||||
_formatUserMsg(retval);
|
_formatUserMsg(retval);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -354,19 +351,19 @@ wxString Exception::CannotCreateStream::FormatDisplayMessage() const
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
wxString Exception::FileNotFound::FormatDiagnosticMessage() const
|
wxString Exception::FileNotFound::FormatDiagnosticMessage() const
|
||||||
{
|
{
|
||||||
FastFormatUnicode retval;
|
FastFormatUnicode retval;
|
||||||
retval.Write("File not found.\n");
|
retval.Write("File not found.\n");
|
||||||
_formatDiagMsg(retval);
|
_formatDiagMsg(retval);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString Exception::FileNotFound::FormatDisplayMessage() const
|
wxString Exception::FileNotFound::FormatDisplayMessage() const
|
||||||
{
|
{
|
||||||
FastFormatUnicode retval;
|
FastFormatUnicode retval;
|
||||||
retval.Write(_("File not found."));
|
retval.Write(_("File not found."));
|
||||||
retval.Write("\n");
|
retval.Write("\n");
|
||||||
_formatUserMsg(retval);
|
_formatUserMsg(retval);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -374,19 +371,19 @@ wxString Exception::FileNotFound::FormatDisplayMessage() const
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
wxString Exception::AccessDenied::FormatDiagnosticMessage() const
|
wxString Exception::AccessDenied::FormatDiagnosticMessage() const
|
||||||
{
|
{
|
||||||
FastFormatUnicode retval;
|
FastFormatUnicode retval;
|
||||||
retval.Write("Permission denied to file.\n");
|
retval.Write("Permission denied to file.\n");
|
||||||
_formatDiagMsg(retval);
|
_formatDiagMsg(retval);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString Exception::AccessDenied::FormatDisplayMessage() const
|
wxString Exception::AccessDenied::FormatDisplayMessage() const
|
||||||
{
|
{
|
||||||
FastFormatUnicode retval;
|
FastFormatUnicode retval;
|
||||||
retval.Write(_("Permission denied while trying to open file, likely due to insufficient user account rights."));
|
retval.Write(_("Permission denied while trying to open file, likely due to insufficient user account rights."));
|
||||||
retval.Write("\n");
|
retval.Write("\n");
|
||||||
_formatUserMsg(retval);
|
_formatUserMsg(retval);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -394,19 +391,19 @@ wxString Exception::AccessDenied::FormatDisplayMessage() const
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
wxString Exception::EndOfStream::FormatDiagnosticMessage() const
|
wxString Exception::EndOfStream::FormatDiagnosticMessage() const
|
||||||
{
|
{
|
||||||
FastFormatUnicode retval;
|
FastFormatUnicode retval;
|
||||||
retval.Write("Unexpected end of file or stream.\n");
|
retval.Write("Unexpected end of file or stream.\n");
|
||||||
_formatDiagMsg(retval);
|
_formatDiagMsg(retval);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString Exception::EndOfStream::FormatDisplayMessage() const
|
wxString Exception::EndOfStream::FormatDisplayMessage() const
|
||||||
{
|
{
|
||||||
FastFormatUnicode retval;
|
FastFormatUnicode retval;
|
||||||
retval.Write(_("Unexpected end of file or stream encountered. File is probably truncated or corrupted."));
|
retval.Write(_("Unexpected end of file or stream encountered. File is probably truncated or corrupted."));
|
||||||
retval.Write("\n");
|
retval.Write("\n");
|
||||||
_formatUserMsg(retval);
|
_formatUserMsg(retval);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -415,35 +412,34 @@ wxString Exception::EndOfStream::FormatDisplayMessage() const
|
||||||
|
|
||||||
// Translates an Errno code into an exception.
|
// Translates an Errno code into an exception.
|
||||||
// Throws an exception based on the given error code (usually taken from ANSI C's errno)
|
// Throws an exception based on the given error code (usually taken from ANSI C's errno)
|
||||||
BaseException* Exception::FromErrno( const wxString& streamname, int errcode )
|
BaseException *Exception::FromErrno(const wxString &streamname, int errcode)
|
||||||
{
|
{
|
||||||
pxAssumeDev( errcode != 0, "Invalid NULL error code? (errno)" );
|
pxAssumeDev(errcode != 0, "Invalid NULL error code? (errno)");
|
||||||
|
|
||||||
switch( errcode )
|
switch (errcode) {
|
||||||
{
|
case EINVAL:
|
||||||
case EINVAL:
|
pxFailDev(L"Invalid argument");
|
||||||
pxFailDev( L"Invalid argument" );
|
return &(new Exception::BadStream(streamname))->SetDiagMsg(L"Invalid argument? (likely caused by an unforgivable programmer error!)");
|
||||||
return &(new Exception::BadStream( streamname ))->SetDiagMsg(L"Invalid argument? (likely caused by an unforgivable programmer error!)" );
|
|
||||||
|
|
||||||
case EACCES: // Access denied!
|
case EACCES: // Access denied!
|
||||||
return new Exception::AccessDenied( streamname );
|
return new Exception::AccessDenied(streamname);
|
||||||
|
|
||||||
case EMFILE: // Too many open files!
|
case EMFILE: // Too many open files!
|
||||||
return &(new Exception::CannotCreateStream( streamname ))->SetDiagMsg(L"Too many open files"); // File handle allocation failure
|
return &(new Exception::CannotCreateStream(streamname))->SetDiagMsg(L"Too many open files"); // File handle allocation failure
|
||||||
|
|
||||||
case EEXIST:
|
case EEXIST:
|
||||||
return &(new Exception::CannotCreateStream( streamname ))->SetDiagMsg(L"File already exists");
|
return &(new Exception::CannotCreateStream(streamname))->SetDiagMsg(L"File already exists");
|
||||||
|
|
||||||
case ENOENT: // File not found!
|
case ENOENT: // File not found!
|
||||||
return new Exception::FileNotFound( streamname );
|
return new Exception::FileNotFound(streamname);
|
||||||
|
|
||||||
case EPIPE:
|
case EPIPE:
|
||||||
return &(new Exception::BadStream( streamname ))->SetDiagMsg(L"Broken pipe");
|
return &(new Exception::BadStream(streamname))->SetDiagMsg(L"Broken pipe");
|
||||||
|
|
||||||
case EBADF:
|
case EBADF:
|
||||||
return &(new Exception::BadStream( streamname ))->SetDiagMsg(L"Bad file number");
|
return &(new Exception::BadStream(streamname))->SetDiagMsg(L"Bad file number");
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return &(new Exception::BadStream( streamname ))->SetDiagMsg(pxsFmt( L"General file/stream error [errno: %d]", errcode ));
|
return &(new Exception::BadStream(streamname))->SetDiagMsg(pxsFmt(L"General file/stream error [errno: %d]", errcode));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,9 +24,9 @@ template class SafeArray<char>;
|
||||||
template class SafeArray<wchar_t>;
|
template class SafeArray<wchar_t>;
|
||||||
template class SafeArray<u8>;
|
template class SafeArray<u8>;
|
||||||
|
|
||||||
template class SafeAlignedArray<char,16>;
|
template class SafeAlignedArray<char, 16>;
|
||||||
template class SafeAlignedArray<wchar_t,16>;
|
template class SafeAlignedArray<wchar_t, 16>;
|
||||||
template class SafeAlignedArray<u8,16>;
|
template class SafeAlignedArray<u8, 16>;
|
||||||
|
|
||||||
// Sanity check: truncate strings if they exceed 512k in length. Anything like that
|
// Sanity check: truncate strings if they exceed 512k in length. Anything like that
|
||||||
// is either a bug or really horrible code that needs to be stopped before it causes
|
// is either a bug or really horrible code that needs to be stopped before it causes
|
||||||
|
@ -35,82 +35,86 @@ static const int MaxFormattedStringLength = 0x80000;
|
||||||
|
|
||||||
static
|
static
|
||||||
#ifndef __linux__
|
#ifndef __linux__
|
||||||
__ri
|
__ri
|
||||||
#endif
|
#endif
|
||||||
void format_that_ascii_mess( CharBufferType& buffer, uint writepos, const char* fmt, va_list argptr )
|
void
|
||||||
|
format_that_ascii_mess(CharBufferType &buffer, uint writepos, const char *fmt, va_list argptr)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
while( true )
|
while (true) {
|
||||||
{
|
int size = buffer.GetLength();
|
||||||
int size = buffer.GetLength();
|
|
||||||
|
|
||||||
va_copy(args, argptr);
|
va_copy(args, argptr);
|
||||||
int len = vsnprintf(buffer.GetPtr(writepos), size-writepos, fmt, args);
|
int len = vsnprintf(buffer.GetPtr(writepos), size - writepos, fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
// some implementations of vsnprintf() don't NUL terminate
|
// some implementations of vsnprintf() don't NUL terminate
|
||||||
// the string if there is not enough space for it so
|
// the string if there is not enough space for it so
|
||||||
// always do it manually
|
// always do it manually
|
||||||
buffer[size-1] = '\0';
|
buffer[size - 1] = '\0';
|
||||||
|
|
||||||
if (size >= MaxFormattedStringLength) break;
|
if (size >= MaxFormattedStringLength)
|
||||||
|
break;
|
||||||
|
|
||||||
// vsnprintf() may return either -1 (traditional Unix behavior) or the
|
// vsnprintf() may return either -1 (traditional Unix behavior) or the
|
||||||
// total number of characters which would have been written if the
|
// total number of characters which would have been written if the
|
||||||
// buffer were large enough (newer standards such as Unix98)
|
// buffer were large enough (newer standards such as Unix98)
|
||||||
|
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
len = size + (size/4);
|
len = size + (size / 4);
|
||||||
|
|
||||||
len += writepos;
|
len += writepos;
|
||||||
if (len < size) break;
|
if (len < size)
|
||||||
buffer.Resize( len + 128 );
|
break;
|
||||||
};
|
buffer.Resize(len + 128);
|
||||||
|
};
|
||||||
|
|
||||||
// performing an assertion or log of a truncated string is unsafe, so let's not; even
|
// performing an assertion or log of a truncated string is unsafe, so let's not; even
|
||||||
// though it'd be kinda nice if we did.
|
// though it'd be kinda nice if we did.
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns the length of the formatted string, in characters (wxChars).
|
// returns the length of the formatted string, in characters (wxChars).
|
||||||
static
|
static
|
||||||
#ifndef __linux__
|
#ifndef __linux__
|
||||||
__ri
|
__ri
|
||||||
#endif
|
#endif
|
||||||
uint format_that_unicode_mess( CharBufferType& buffer, uint writepos, const wxChar* fmt, va_list argptr)
|
uint
|
||||||
|
format_that_unicode_mess(CharBufferType &buffer, uint writepos, const wxChar *fmt, va_list argptr)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
while( true )
|
while (true) {
|
||||||
{
|
int size = buffer.GetLength() / sizeof(wxChar);
|
||||||
int size = buffer.GetLength() / sizeof(wxChar);
|
|
||||||
|
|
||||||
va_copy(args, argptr);
|
va_copy(args, argptr);
|
||||||
int len = wxVsnprintf((wxChar*)buffer.GetPtr(writepos*sizeof(wxChar)), size-writepos, fmt, args);
|
int len = wxVsnprintf((wxChar *)buffer.GetPtr(writepos * sizeof(wxChar)), size - writepos, fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
// some implementations of vsnprintf() don't NUL terminate
|
// some implementations of vsnprintf() don't NUL terminate
|
||||||
// the string if there is not enough space for it so
|
// the string if there is not enough space for it so
|
||||||
// always do it manually
|
// always do it manually
|
||||||
((wxChar*)buffer.GetPtr())[size-1] = L'\0';
|
((wxChar *)buffer.GetPtr())[size - 1] = L'\0';
|
||||||
|
|
||||||
if( size >= MaxFormattedStringLength ) return size-1;
|
if (size >= MaxFormattedStringLength)
|
||||||
|
return size - 1;
|
||||||
|
|
||||||
// vsnprintf() may return either -1 (traditional Unix behavior) or the
|
// vsnprintf() may return either -1 (traditional Unix behavior) or the
|
||||||
// total number of characters which would have been written if the
|
// total number of characters which would have been written if the
|
||||||
// buffer were large enough (newer standards such as Unix98)
|
// buffer were large enough (newer standards such as Unix98)
|
||||||
|
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
len = size + (size/4);
|
len = size + (size / 4);
|
||||||
|
|
||||||
len += writepos;
|
len += writepos;
|
||||||
if (len < size) return len;
|
if (len < size)
|
||||||
buffer.Resize( (len + 128) * sizeof(wxChar) );
|
return len;
|
||||||
};
|
buffer.Resize((len + 128) * sizeof(wxChar));
|
||||||
|
};
|
||||||
|
|
||||||
// performing an assertion or log of a truncated string is unsafe, so let's not; even
|
// performing an assertion or log of a truncated string is unsafe, so let's not; even
|
||||||
// though it'd be kinda nice if we did.
|
// though it'd be kinda nice if we did.
|
||||||
|
|
||||||
pxAssume( false );
|
pxAssume(false);
|
||||||
return 0; // unreachable.
|
return 0; // unreachable.
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -123,9 +127,9 @@ uint format_that_unicode_mess( CharBufferType& buffer, uint writepos, const wxCh
|
||||||
// this class nicely in its current state. --air
|
// this class nicely in its current state. --air
|
||||||
|
|
||||||
FastFormatUnicode::FastFormatUnicode()
|
FastFormatUnicode::FastFormatUnicode()
|
||||||
: m_dest(2048)
|
: m_dest(2048)
|
||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
FastFormatUnicode::~FastFormatUnicode() throw()
|
FastFormatUnicode::~FastFormatUnicode() throw()
|
||||||
|
@ -134,117 +138,117 @@ FastFormatUnicode::~FastFormatUnicode() throw()
|
||||||
|
|
||||||
void FastFormatUnicode::Clear()
|
void FastFormatUnicode::Clear()
|
||||||
{
|
{
|
||||||
m_Length = 0;
|
m_Length = 0;
|
||||||
((wxChar*)m_dest.GetPtr())[0] = 0;
|
((wxChar *)m_dest.GetPtr())[0] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
FastFormatUnicode& FastFormatUnicode::WriteV( const char* fmt, va_list argptr )
|
FastFormatUnicode &FastFormatUnicode::WriteV(const char *fmt, va_list argptr)
|
||||||
{
|
{
|
||||||
wxString converted( fromUTF8(FastFormatAscii().WriteV( fmt, argptr )) );
|
wxString converted(fromUTF8(FastFormatAscii().WriteV(fmt, argptr)));
|
||||||
|
|
||||||
const uint inspos = m_Length;
|
const uint inspos = m_Length;
|
||||||
const uint convLen = converted.Length();
|
const uint convLen = converted.Length();
|
||||||
m_dest.MakeRoomFor((inspos + convLen + 64) * sizeof(wxChar));
|
m_dest.MakeRoomFor((inspos + convLen + 64) * sizeof(wxChar));
|
||||||
memcpy( &((wxChar*)m_dest.GetPtr())[inspos], converted.wc_str(), (convLen+1)*sizeof(wxChar) );
|
memcpy(&((wxChar *)m_dest.GetPtr())[inspos], converted.wc_str(), (convLen + 1) * sizeof(wxChar));
|
||||||
m_Length += convLen;
|
m_Length += convLen;
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
FastFormatUnicode& FastFormatUnicode::WriteV( const wxChar* fmt, va_list argptr )
|
FastFormatUnicode &FastFormatUnicode::WriteV(const wxChar *fmt, va_list argptr)
|
||||||
{
|
{
|
||||||
m_Length = format_that_unicode_mess( m_dest, m_Length, fmt, argptr );
|
m_Length = format_that_unicode_mess(m_dest, m_Length, fmt, argptr);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
FastFormatUnicode& FastFormatUnicode::Write( const char* fmt, ... )
|
FastFormatUnicode &FastFormatUnicode::Write(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list list;
|
va_list list;
|
||||||
va_start(list, fmt);
|
va_start(list, fmt);
|
||||||
WriteV(fmt,list);
|
WriteV(fmt, list);
|
||||||
va_end(list);
|
va_end(list);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
FastFormatUnicode& FastFormatUnicode::Write( const wxChar* fmt, ... )
|
FastFormatUnicode &FastFormatUnicode::Write(const wxChar *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list list;
|
va_list list;
|
||||||
va_start(list, fmt);
|
va_start(list, fmt);
|
||||||
WriteV(fmt,list);
|
WriteV(fmt, list);
|
||||||
va_end(list);
|
va_end(list);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
FastFormatUnicode& FastFormatUnicode::Write( const wxString fmt, ... )
|
FastFormatUnicode &FastFormatUnicode::Write(const wxString fmt, ...)
|
||||||
{
|
{
|
||||||
va_list list;
|
va_list list;
|
||||||
va_start(list, fmt);
|
va_start(list, fmt);
|
||||||
WriteV(fmt.wx_str(),list);
|
WriteV(fmt.wx_str(), list);
|
||||||
va_end(list);
|
va_end(list);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FastFormatUnicode::IsEmpty() const
|
bool FastFormatUnicode::IsEmpty() const
|
||||||
{
|
{
|
||||||
return ((wxChar&)m_dest[0]) == 0;
|
return ((wxChar &)m_dest[0]) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
FastFormatUnicode& FastFormatUnicode::ToUpper()
|
FastFormatUnicode &FastFormatUnicode::ToUpper()
|
||||||
{
|
{
|
||||||
wxChar* ch = (wxChar*)m_dest.GetPtr();
|
wxChar *ch = (wxChar *)m_dest.GetPtr();
|
||||||
for ( uint i=0; i<m_Length; ++i, ++ch )
|
for (uint i = 0; i < m_Length; ++i, ++ch)
|
||||||
*ch = (wxChar)wxToupper(*ch);
|
*ch = (wxChar)wxToupper(*ch);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
FastFormatUnicode& FastFormatUnicode::ToLower()
|
FastFormatUnicode &FastFormatUnicode::ToLower()
|
||||||
{
|
{
|
||||||
wxChar* ch = (wxChar*)m_dest.GetPtr();
|
wxChar *ch = (wxChar *)m_dest.GetPtr();
|
||||||
for ( uint i=0; i<m_Length; ++i, ++ch )
|
for (uint i = 0; i < m_Length; ++i, ++ch)
|
||||||
*ch = (wxChar)wxTolower(*ch);
|
*ch = (wxChar)wxTolower(*ch);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
FastFormatUnicode& FastFormatUnicode::operator+=(const char* psz )
|
FastFormatUnicode &FastFormatUnicode::operator+=(const char *psz)
|
||||||
{
|
{
|
||||||
Write( L"%s", WX_STR(fromUTF8(psz)) );
|
Write(L"%s", WX_STR(fromUTF8(psz)));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString& operator+=(wxString& str1, const FastFormatUnicode& str2)
|
wxString &operator+=(wxString &str1, const FastFormatUnicode &str2)
|
||||||
{
|
{
|
||||||
str1.Append(str2.c_str(), str2.Length());
|
str1.Append(str2.c_str(), str2.Length());
|
||||||
return str1;
|
return str1;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString operator+(const wxString& str1, const FastFormatUnicode& str2)
|
wxString operator+(const wxString &str1, const FastFormatUnicode &str2)
|
||||||
{
|
{
|
||||||
wxString s = str1;
|
wxString s = str1;
|
||||||
s += str2;
|
s += str2;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString operator+(const wxChar* str1, const FastFormatUnicode& str2)
|
wxString operator+(const wxChar *str1, const FastFormatUnicode &str2)
|
||||||
{
|
{
|
||||||
wxString s = str1;
|
wxString s = str1;
|
||||||
s += str2;
|
s += str2;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString operator+(const FastFormatUnicode& str1, const wxString& str2)
|
wxString operator+(const FastFormatUnicode &str1, const wxString &str2)
|
||||||
{
|
{
|
||||||
wxString s = str1;
|
wxString s = str1;
|
||||||
s += str2;
|
s += str2;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString operator+(const FastFormatUnicode& str1, const wxChar* str2)
|
wxString operator+(const FastFormatUnicode &str1, const wxChar *str2)
|
||||||
{
|
{
|
||||||
wxString s = str1;
|
wxString s = str1;
|
||||||
s += str2;
|
s += str2;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -252,9 +256,9 @@ wxString operator+(const FastFormatUnicode& str1, const wxChar* str2)
|
||||||
// FastFormatAscii (implementations)
|
// FastFormatAscii (implementations)
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
FastFormatAscii::FastFormatAscii()
|
FastFormatAscii::FastFormatAscii()
|
||||||
: m_dest(2048)
|
: m_dest(2048)
|
||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
FastFormatAscii::~FastFormatAscii() throw()
|
FastFormatAscii::~FastFormatAscii() throw()
|
||||||
|
@ -263,31 +267,31 @@ FastFormatAscii::~FastFormatAscii() throw()
|
||||||
|
|
||||||
void FastFormatAscii::Clear()
|
void FastFormatAscii::Clear()
|
||||||
{
|
{
|
||||||
m_dest.GetPtr()[0] = 0;
|
m_dest.GetPtr()[0] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const wxString FastFormatAscii::GetString() const
|
const wxString FastFormatAscii::GetString() const
|
||||||
{
|
{
|
||||||
return fromAscii(m_dest.GetPtr());
|
return fromAscii(m_dest.GetPtr());
|
||||||
}
|
}
|
||||||
|
|
||||||
FastFormatAscii& FastFormatAscii::WriteV( const char* fmt, va_list argptr )
|
FastFormatAscii &FastFormatAscii::WriteV(const char *fmt, va_list argptr)
|
||||||
{
|
{
|
||||||
format_that_ascii_mess( m_dest, strlen(m_dest.GetPtr()), fmt, argptr );
|
format_that_ascii_mess(m_dest, strlen(m_dest.GetPtr()), fmt, argptr);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
FastFormatAscii& FastFormatAscii::Write( const char* fmt, ... )
|
FastFormatAscii &FastFormatAscii::Write(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list list;
|
va_list list;
|
||||||
va_start(list, fmt);
|
va_start(list, fmt);
|
||||||
WriteV(fmt,list);
|
WriteV(fmt, list);
|
||||||
va_end(list);
|
va_end(list);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool FastFormatAscii::IsEmpty() const
|
bool FastFormatAscii::IsEmpty() const
|
||||||
{
|
{
|
||||||
return m_dest[0] == 0;
|
return m_dest[0] == 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,9 +16,10 @@
|
||||||
#include "PrecompiledHeader.h"
|
#include "PrecompiledHeader.h"
|
||||||
#include "HashMap.h"
|
#include "HashMap.h"
|
||||||
|
|
||||||
namespace HashTools {
|
namespace HashTools
|
||||||
|
{
|
||||||
|
|
||||||
#define get16bits(d) (*((const u16 *) (d)))
|
#define get16bits(d) (*((const u16 *)(d)))
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculates a hash value for an arbitrary set of binary data.
|
/// Calculates a hash value for an arbitrary set of binary data.
|
||||||
|
@ -52,51 +53,53 @@ namespace HashTools {
|
||||||
/// uint32 hashval = Hash( (const char*)&data, sizeof( data ) );
|
/// uint32 hashval = Hash( (const char*)&data, sizeof( data ) );
|
||||||
/// </code>
|
/// </code>
|
||||||
/// </example>
|
/// </example>
|
||||||
u32 Hash(const s8 * data, int len)
|
u32 Hash(const s8 *data, int len)
|
||||||
{
|
{
|
||||||
u32 hash = len;
|
u32 hash = len;
|
||||||
int rem;
|
int rem;
|
||||||
|
|
||||||
if (len <= 0 || data == NULL) return 0;
|
if (len <= 0 || data == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
rem = len & 3;
|
rem = len & 3;
|
||||||
len >>= 2;
|
len >>= 2;
|
||||||
|
|
||||||
/* Main loop */
|
/* Main loop */
|
||||||
for (;len > 0; --len)
|
for (; len > 0; --len) {
|
||||||
{
|
hash += get16bits(data);
|
||||||
hash += get16bits (data);
|
u32 tmp = (get16bits(data + 2) << 11) ^ hash;
|
||||||
u32 tmp = (get16bits (data+2) << 11) ^ hash;
|
hash = (hash << 16) ^ tmp;
|
||||||
hash = (hash << 16) ^ tmp;
|
data += 2 * sizeof(u16);
|
||||||
data += 2*sizeof (u16);
|
hash += hash >> 11;
|
||||||
hash += hash >> 11;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle end cases */
|
/* Handle end cases */
|
||||||
switch (rem)
|
switch (rem) {
|
||||||
{
|
case 3:
|
||||||
case 3: hash += get16bits (data);
|
hash += get16bits(data);
|
||||||
hash ^= hash << 16;
|
hash ^= hash << 16;
|
||||||
hash ^= data[sizeof (u16)] << 18;
|
hash ^= data[sizeof(u16)] << 18;
|
||||||
hash += hash >> 11;
|
hash += hash >> 11;
|
||||||
break;
|
break;
|
||||||
case 2: hash += get16bits (data);
|
case 2:
|
||||||
hash ^= hash << 11;
|
hash += get16bits(data);
|
||||||
hash += hash >> 17;
|
hash ^= hash << 11;
|
||||||
break;
|
hash += hash >> 17;
|
||||||
case 1: hash += *data;
|
break;
|
||||||
hash ^= hash << 10;
|
case 1:
|
||||||
hash += hash >> 1;
|
hash += *data;
|
||||||
}
|
hash ^= hash << 10;
|
||||||
|
hash += hash >> 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Force "avalanching" of final 127 bits */
|
/* Force "avalanching" of final 127 bits */
|
||||||
hash ^= hash << 3;
|
hash ^= hash << 3;
|
||||||
hash += hash >> 5;
|
hash += hash >> 5;
|
||||||
hash ^= hash << 4;
|
hash ^= hash << 4;
|
||||||
hash += hash >> 17;
|
hash += hash >> 17;
|
||||||
hash ^= hash << 25;
|
hash ^= hash << 25;
|
||||||
hash += hash >> 6;
|
hash += hash >> 6;
|
||||||
|
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
#include <wx/gdicmn.h>
|
#include <wx/gdicmn.h>
|
||||||
|
|
||||||
const wxRect wxDefaultRect( wxDefaultCoord, wxDefaultCoord, wxDefaultCoord, wxDefaultCoord );
|
const wxRect wxDefaultRect(wxDefaultCoord, wxDefaultCoord, wxDefaultCoord, wxDefaultCoord);
|
||||||
|
|
||||||
// Implement FixedPointTypes (for lack of a better location, for now)
|
// Implement FixedPointTypes (for lack of a better location, for now)
|
||||||
|
|
||||||
|
@ -27,369 +27,396 @@ template struct FixedInt<100>;
|
||||||
template struct FixedInt<256>;
|
template struct FixedInt<256>;
|
||||||
|
|
||||||
wxDirName g_fullBaseDirName = wxDirName(L"");
|
wxDirName g_fullBaseDirName = wxDirName(L"");
|
||||||
void SetFullBaseDir( wxDirName appRoot )
|
void SetFullBaseDir(wxDirName appRoot)
|
||||||
{
|
{
|
||||||
g_fullBaseDirName = appRoot;
|
g_fullBaseDirName = appRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _calcEnumLength( const wxChar* const* enumArray )
|
static int _calcEnumLength(const wxChar *const *enumArray)
|
||||||
{
|
{
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
while( *enumArray != NULL )
|
while (*enumArray != NULL) {
|
||||||
{
|
enumArray++;
|
||||||
enumArray++;
|
cnt++;
|
||||||
cnt++;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return cnt;
|
return cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScopedIniGroup::ScopedIniGroup( IniInterface& mommy, const wxString& group )
|
ScopedIniGroup::ScopedIniGroup(IniInterface &mommy, const wxString &group)
|
||||||
: m_mom( mommy )
|
: m_mom(mommy)
|
||||||
{
|
{
|
||||||
pxAssertDev( wxStringTokenize( group, L"/" ).Count() <= 1, L"Cannot nest more than one group deep per instance of ScopedIniGroup." );
|
pxAssertDev(wxStringTokenize(group, L"/").Count() <= 1, L"Cannot nest more than one group deep per instance of ScopedIniGroup.");
|
||||||
m_mom.SetPath( group );
|
m_mom.SetPath(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScopedIniGroup::~ScopedIniGroup()
|
ScopedIniGroup::~ScopedIniGroup()
|
||||||
{
|
{
|
||||||
m_mom.SetPath( L".." );
|
m_mom.SetPath(L"..");
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// IniInterface (implementations)
|
// IniInterface (implementations)
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
IniInterface::IniInterface( wxConfigBase& config )
|
IniInterface::IniInterface(wxConfigBase &config)
|
||||||
{
|
{
|
||||||
m_Config = &config;
|
m_Config = &config;
|
||||||
}
|
}
|
||||||
|
|
||||||
IniInterface::IniInterface( wxConfigBase* config )
|
IniInterface::IniInterface(wxConfigBase *config)
|
||||||
{
|
{
|
||||||
m_Config = config;
|
m_Config = config;
|
||||||
}
|
}
|
||||||
|
|
||||||
IniInterface::IniInterface()
|
IniInterface::IniInterface()
|
||||||
{
|
{
|
||||||
m_Config = wxConfigBase::Get( false );
|
m_Config = wxConfigBase::Get(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
IniInterface::~IniInterface()
|
IniInterface::~IniInterface()
|
||||||
{
|
{
|
||||||
Flush();
|
Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void IniInterface::SetPath( const wxString& path )
|
void IniInterface::SetPath(const wxString &path)
|
||||||
{
|
{
|
||||||
if( m_Config ) m_Config->SetPath( path );
|
if (m_Config)
|
||||||
|
m_Config->SetPath(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IniInterface::Flush()
|
void IniInterface::Flush()
|
||||||
{
|
{
|
||||||
if( m_Config ) m_Config->Flush();
|
if (m_Config)
|
||||||
|
m_Config->Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// IniLoader (implementations)
|
// IniLoader (implementations)
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
IniLoader::IniLoader( wxConfigBase& config ) : IniInterface( config ) { }
|
IniLoader::IniLoader(wxConfigBase &config)
|
||||||
IniLoader::IniLoader( wxConfigBase* config ) : IniInterface( config ) { }
|
: IniInterface(config)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
IniLoader::IniLoader(wxConfigBase *config)
|
||||||
|
: IniInterface(config)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
IniLoader::IniLoader() : IniInterface() {}
|
IniLoader::IniLoader()
|
||||||
|
: IniInterface()
|
||||||
|
{
|
||||||
|
}
|
||||||
IniLoader::~IniLoader() throw() {}
|
IniLoader::~IniLoader() throw() {}
|
||||||
|
|
||||||
|
|
||||||
void IniLoader::Entry( const wxString& var, wxString& value, const wxString defvalue )
|
void IniLoader::Entry(const wxString &var, wxString &value, const wxString defvalue)
|
||||||
{
|
{
|
||||||
if( m_Config )
|
if (m_Config)
|
||||||
m_Config->Read( var, &value, defvalue );
|
m_Config->Read(var, &value, defvalue);
|
||||||
else
|
else
|
||||||
value = defvalue;
|
value = defvalue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void IniLoader::Entry( const wxString& var, wxDirName& value, const wxDirName defvalue, bool isAllowRelative )
|
void IniLoader::Entry(const wxString &var, wxDirName &value, const wxDirName defvalue, bool isAllowRelative)
|
||||||
{
|
{
|
||||||
wxString dest;
|
wxString dest;
|
||||||
if( m_Config ) m_Config->Read( var, &dest, wxEmptyString );
|
if (m_Config)
|
||||||
|
m_Config->Read(var, &dest, wxEmptyString);
|
||||||
|
|
||||||
if( dest.IsEmpty() )
|
if (dest.IsEmpty())
|
||||||
value = defvalue;
|
value = defvalue;
|
||||||
else
|
else {
|
||||||
{
|
value = dest;
|
||||||
value = dest;
|
if (isAllowRelative)
|
||||||
if( isAllowRelative )
|
value = g_fullBaseDirName + value;
|
||||||
value = g_fullBaseDirName + value;
|
|
||||||
|
|
||||||
if( value.IsAbsolute() )
|
if (value.IsAbsolute())
|
||||||
value.Normalize();
|
value.Normalize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IniLoader::Entry( const wxString& var, wxFileName& value, const wxFileName defvalue, bool isAllowRelative )
|
void IniLoader::Entry(const wxString &var, wxFileName &value, const wxFileName defvalue, bool isAllowRelative)
|
||||||
{
|
{
|
||||||
wxString dest( defvalue.GetFullPath() );
|
wxString dest(defvalue.GetFullPath());
|
||||||
if( m_Config ) m_Config->Read( var, &dest, defvalue.GetFullPath() );
|
if (m_Config)
|
||||||
value = dest;
|
m_Config->Read(var, &dest, defvalue.GetFullPath());
|
||||||
if( isAllowRelative )
|
value = dest;
|
||||||
value = g_fullBaseDirName + value;
|
if (isAllowRelative)
|
||||||
|
value = g_fullBaseDirName + value;
|
||||||
|
|
||||||
if( value.IsAbsolute() )
|
if (value.IsAbsolute())
|
||||||
value.Normalize();
|
value.Normalize();
|
||||||
|
|
||||||
if (value.HasVolume())
|
if (value.HasVolume())
|
||||||
value.SetVolume(value.GetVolume().Upper());
|
value.SetVolume(value.GetVolume().Upper());
|
||||||
}
|
}
|
||||||
|
|
||||||
void IniLoader::Entry( const wxString& var, int& value, const int defvalue )
|
void IniLoader::Entry(const wxString &var, int &value, const int defvalue)
|
||||||
{
|
{
|
||||||
if( m_Config )
|
if (m_Config)
|
||||||
m_Config->Read( var, &value, defvalue );
|
m_Config->Read(var, &value, defvalue);
|
||||||
else
|
else
|
||||||
value = defvalue;
|
value = defvalue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IniLoader::Entry( const wxString& var, uint& value, const uint defvalue )
|
void IniLoader::Entry(const wxString &var, uint &value, const uint defvalue)
|
||||||
{
|
{
|
||||||
if( m_Config )
|
if (m_Config)
|
||||||
m_Config->Read( var, (int*)&value, (int)defvalue );
|
m_Config->Read(var, (int *)&value, (int)defvalue);
|
||||||
else
|
else
|
||||||
value = defvalue;
|
value = defvalue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IniLoader::Entry( const wxString& var, bool& value, const bool defvalue )
|
void IniLoader::Entry(const wxString &var, bool &value, const bool defvalue)
|
||||||
{
|
{
|
||||||
// TODO : Stricter value checking on enabled/disabled?
|
// TODO : Stricter value checking on enabled/disabled?
|
||||||
wxString dest(defvalue ? L"enabled" : L"disabled");
|
wxString dest(defvalue ? L"enabled" : L"disabled");
|
||||||
if( m_Config ) m_Config->Read( var, &dest, dest );
|
if (m_Config)
|
||||||
value = (dest == L"enabled") || (dest == L"1");
|
m_Config->Read(var, &dest, dest);
|
||||||
|
value = (dest == L"enabled") || (dest == L"1");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IniLoader::EntryBitBool( const wxString& var, bool value, const bool defvalue )
|
bool IniLoader::EntryBitBool(const wxString &var, bool value, const bool defvalue)
|
||||||
{
|
{
|
||||||
// Note: 'value' param is used by inisaver only.
|
// Note: 'value' param is used by inisaver only.
|
||||||
bool result;
|
bool result;
|
||||||
Entry( var, result, defvalue );
|
Entry(var, result, defvalue);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int IniLoader::EntryBitfield( const wxString& var, int value, const int defvalue )
|
int IniLoader::EntryBitfield(const wxString &var, int value, const int defvalue)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
Entry( var, result, defvalue );
|
Entry(var, result, defvalue);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IniLoader::Entry( const wxString& var, Fixed100& value, const Fixed100 defvalue )
|
void IniLoader::Entry(const wxString &var, Fixed100 &value, const Fixed100 defvalue)
|
||||||
{
|
{
|
||||||
// Note: the "easy" way would be to convert to double and load/save that, but floating point
|
// Note: the "easy" way would be to convert to double and load/save that, but floating point
|
||||||
// has way too much rounding error so we really need to do things out manually.. >_<
|
// has way too much rounding error so we really need to do things out manually.. >_<
|
||||||
|
|
||||||
wxString readval( value.ToString() );
|
wxString readval(value.ToString());
|
||||||
if( m_Config ) m_Config->Read( var, &readval );
|
if (m_Config)
|
||||||
value = Fixed100::FromString( readval, value );
|
m_Config->Read(var, &readval);
|
||||||
|
value = Fixed100::FromString(readval, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IniLoader::Entry( const wxString& var, wxPoint& value, const wxPoint defvalue )
|
void IniLoader::Entry(const wxString &var, wxPoint &value, const wxPoint defvalue)
|
||||||
{
|
{
|
||||||
if( !m_Config )
|
if (!m_Config) {
|
||||||
{
|
value = defvalue;
|
||||||
value = defvalue; return;
|
return;
|
||||||
}
|
}
|
||||||
TryParse( value, m_Config->Read( var, ToString( defvalue ) ), defvalue );
|
TryParse(value, m_Config->Read(var, ToString(defvalue)), defvalue);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IniLoader::Entry( const wxString& var, wxSize& value, const wxSize defvalue )
|
void IniLoader::Entry(const wxString &var, wxSize &value, const wxSize defvalue)
|
||||||
{
|
{
|
||||||
if( !m_Config )
|
if (!m_Config) {
|
||||||
{
|
value = defvalue;
|
||||||
value = defvalue; return;
|
return;
|
||||||
}
|
}
|
||||||
TryParse( value, m_Config->Read( var, ToString( defvalue ) ), defvalue );
|
TryParse(value, m_Config->Read(var, ToString(defvalue)), defvalue);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IniLoader::Entry( const wxString& var, wxRect& value, const wxRect defvalue )
|
void IniLoader::Entry(const wxString &var, wxRect &value, const wxRect defvalue)
|
||||||
{
|
{
|
||||||
if( !m_Config )
|
if (!m_Config) {
|
||||||
{
|
value = defvalue;
|
||||||
value = defvalue; return;
|
return;
|
||||||
}
|
}
|
||||||
TryParse( value, m_Config->Read( var, ToString( defvalue ) ), defvalue );
|
TryParse(value, m_Config->Read(var, ToString(defvalue)), defvalue);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IniLoader::_EnumEntry( const wxString& var, int& value, const wxChar* const* enumArray, int defvalue )
|
void IniLoader::_EnumEntry(const wxString &var, int &value, const wxChar *const *enumArray, int defvalue)
|
||||||
{
|
{
|
||||||
// Confirm default value sanity...
|
// Confirm default value sanity...
|
||||||
|
|
||||||
const int cnt = _calcEnumLength( enumArray );
|
const int cnt = _calcEnumLength(enumArray);
|
||||||
if( !IndexBoundsCheck( L"IniLoader EnumDefaultValue", defvalue, cnt ) )
|
if (!IndexBoundsCheck(L"IniLoader EnumDefaultValue", defvalue, cnt)) {
|
||||||
{
|
Console.Error("(LoadSettings) Default enumeration index is out of bounds. Truncating.");
|
||||||
Console.Error( "(LoadSettings) Default enumeration index is out of bounds. Truncating." );
|
defvalue = cnt - 1;
|
||||||
defvalue = cnt-1;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Sanity confirmed, proceed with craziness!
|
// Sanity confirmed, proceed with craziness!
|
||||||
|
|
||||||
if( !m_Config )
|
if (!m_Config) {
|
||||||
{
|
value = defvalue;
|
||||||
value = defvalue;
|
return;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
wxString retval;
|
wxString retval;
|
||||||
m_Config->Read( var, &retval, enumArray[defvalue] );
|
m_Config->Read(var, &retval, enumArray[defvalue]);
|
||||||
|
|
||||||
int i=0;
|
int i = 0;
|
||||||
while( enumArray[i] != NULL && ( retval != enumArray[i] ) ) i++;
|
while (enumArray[i] != NULL && (retval != enumArray[i]))
|
||||||
|
i++;
|
||||||
|
|
||||||
if( enumArray[i] == NULL )
|
if (enumArray[i] == NULL) {
|
||||||
{
|
Console.Warning(L"(LoadSettings) Warning: Unrecognized value '%s' on key '%s'\n\tUsing the default setting of '%s'.",
|
||||||
Console.Warning( L"(LoadSettings) Warning: Unrecognized value '%s' on key '%s'\n\tUsing the default setting of '%s'.",
|
WX_STR(retval), WX_STR(var), enumArray[defvalue]);
|
||||||
WX_STR(retval), WX_STR(var), enumArray[defvalue]
|
value = defvalue;
|
||||||
);
|
} else
|
||||||
value = defvalue;
|
value = i;
|
||||||
}
|
|
||||||
else
|
|
||||||
value = i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
// IniSaver (implementations)
|
// IniSaver (implementations)
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
IniSaver::IniSaver( wxConfigBase& config ) : IniInterface( config ) { }
|
IniSaver::IniSaver(wxConfigBase &config)
|
||||||
IniSaver::IniSaver( wxConfigBase* config ) : IniInterface( config ) { }
|
: IniInterface(config)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
IniSaver::IniSaver(wxConfigBase *config)
|
||||||
|
: IniInterface(config)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
IniSaver::IniSaver() : IniInterface() {}
|
IniSaver::IniSaver()
|
||||||
|
: IniInterface()
|
||||||
|
{
|
||||||
|
}
|
||||||
IniSaver::~IniSaver() {}
|
IniSaver::~IniSaver() {}
|
||||||
|
|
||||||
void IniSaver::Entry( const wxString& var, wxString& value, const wxString defvalue )
|
void IniSaver::Entry(const wxString &var, wxString &value, const wxString defvalue)
|
||||||
{
|
{
|
||||||
if( !m_Config ) return;
|
if (!m_Config)
|
||||||
m_Config->Write( var, value );
|
return;
|
||||||
|
m_Config->Write(var, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IniSaver::Entry( const wxString& var, wxDirName& value, const wxDirName defvalue, bool isAllowRelative )
|
void IniSaver::Entry(const wxString &var, wxDirName &value, const wxDirName defvalue, bool isAllowRelative)
|
||||||
{
|
{
|
||||||
if( !m_Config ) return;
|
if (!m_Config)
|
||||||
wxDirName res(value);
|
return;
|
||||||
|
wxDirName res(value);
|
||||||
|
|
||||||
if ( res.IsAbsolute() )
|
if (res.IsAbsolute())
|
||||||
res.Normalize();
|
res.Normalize();
|
||||||
|
|
||||||
if (isAllowRelative)
|
if (isAllowRelative)
|
||||||
res = wxDirName::MakeAutoRelativeTo( res, g_fullBaseDirName.ToString() );
|
res = wxDirName::MakeAutoRelativeTo(res, g_fullBaseDirName.ToString());
|
||||||
|
|
||||||
|
|
||||||
/*if( value == defvalue )
|
/*if( value == defvalue )
|
||||||
m_Config->Write( var, wxString() );
|
m_Config->Write( var, wxString() );
|
||||||
else*/
|
else*/
|
||||||
m_Config->Write( var, res.ToString() );
|
m_Config->Write(var, res.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
void IniSaver::Entry( const wxString& var, wxFileName& value, const wxFileName defvalue, bool isAllowRelative )
|
void IniSaver::Entry(const wxString &var, wxFileName &value, const wxFileName defvalue, bool isAllowRelative)
|
||||||
{
|
{
|
||||||
if( !m_Config ) return;
|
if (!m_Config)
|
||||||
wxFileName res(value);
|
return;
|
||||||
|
wxFileName res(value);
|
||||||
|
|
||||||
if ( res.IsAbsolute() )
|
if (res.IsAbsolute())
|
||||||
res.Normalize();
|
res.Normalize();
|
||||||
|
|
||||||
if (isAllowRelative)
|
if (isAllowRelative)
|
||||||
res = wxDirName::MakeAutoRelativeTo( res, g_fullBaseDirName.ToString() );
|
res = wxDirName::MakeAutoRelativeTo(res, g_fullBaseDirName.ToString());
|
||||||
|
|
||||||
m_Config->Write( var, res.GetFullPath() );
|
m_Config->Write(var, res.GetFullPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
void IniSaver::Entry( const wxString& var, int& value, const int defvalue )
|
void IniSaver::Entry(const wxString &var, int &value, const int defvalue)
|
||||||
{
|
{
|
||||||
if( !m_Config ) return;
|
if (!m_Config)
|
||||||
m_Config->Write( var, value );
|
return;
|
||||||
|
m_Config->Write(var, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IniSaver::Entry( const wxString& var, uint& value, const uint defvalue )
|
void IniSaver::Entry(const wxString &var, uint &value, const uint defvalue)
|
||||||
{
|
{
|
||||||
if( !m_Config ) return;
|
if (!m_Config)
|
||||||
m_Config->Write( var, (int)value );
|
return;
|
||||||
|
m_Config->Write(var, (int)value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IniSaver::Entry( const wxString& var, bool& value, const bool defvalue )
|
void IniSaver::Entry(const wxString &var, bool &value, const bool defvalue)
|
||||||
{
|
{
|
||||||
if( !m_Config ) return;
|
if (!m_Config)
|
||||||
m_Config->Write( var, value ? L"enabled" : L"disabled" );
|
return;
|
||||||
|
m_Config->Write(var, value ? L"enabled" : L"disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IniSaver::EntryBitBool( const wxString& var, bool value, const bool defvalue )
|
bool IniSaver::EntryBitBool(const wxString &var, bool value, const bool defvalue)
|
||||||
{
|
{
|
||||||
if( m_Config ) m_Config->Write( var, value ? L"enabled" : L"disabled" );
|
if (m_Config)
|
||||||
return value;
|
m_Config->Write(var, value ? L"enabled" : L"disabled");
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
int IniSaver::EntryBitfield( const wxString& var, int value, const int defvalue )
|
int IniSaver::EntryBitfield(const wxString &var, int value, const int defvalue)
|
||||||
{
|
{
|
||||||
if( m_Config ) m_Config->Write( var, value );
|
if (m_Config)
|
||||||
return value;
|
m_Config->Write(var, value);
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IniSaver::Entry( const wxString& var, Fixed100& value, const Fixed100 defvalue )
|
void IniSaver::Entry(const wxString &var, Fixed100 &value, const Fixed100 defvalue)
|
||||||
{
|
{
|
||||||
if( !m_Config ) return;
|
if (!m_Config)
|
||||||
|
return;
|
||||||
|
|
||||||
// Note: the "easy" way would be to convert to double and load/save that, but floating point
|
// Note: the "easy" way would be to convert to double and load/save that, but floating point
|
||||||
// has way too much rounding error so we really need to do things out manually, using strings.
|
// has way too much rounding error so we really need to do things out manually, using strings.
|
||||||
|
|
||||||
m_Config->Write( var, value.ToString() );
|
m_Config->Write(var, value.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
void IniSaver::Entry( const wxString& var, wxPoint& value, const wxPoint defvalue )
|
void IniSaver::Entry(const wxString &var, wxPoint &value, const wxPoint defvalue)
|
||||||
{
|
{
|
||||||
if( !m_Config ) return;
|
if (!m_Config)
|
||||||
m_Config->Write( var, ToString( value ) );
|
return;
|
||||||
|
m_Config->Write(var, ToString(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
void IniSaver::Entry( const wxString& var, wxSize& value, const wxSize defvalue )
|
void IniSaver::Entry(const wxString &var, wxSize &value, const wxSize defvalue)
|
||||||
{
|
{
|
||||||
if( !m_Config ) return;
|
if (!m_Config)
|
||||||
m_Config->Write( var, ToString( value ) );
|
return;
|
||||||
|
m_Config->Write(var, ToString(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
void IniSaver::Entry( const wxString& var, wxRect& value, const wxRect defvalue )
|
void IniSaver::Entry(const wxString &var, wxRect &value, const wxRect defvalue)
|
||||||
{
|
{
|
||||||
if( !m_Config ) return;
|
if (!m_Config)
|
||||||
m_Config->Write( var, ToString( value ) );
|
return;
|
||||||
|
m_Config->Write(var, ToString(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
void IniSaver::_EnumEntry( const wxString& var, int& value, const wxChar* const* enumArray, int defvalue )
|
void IniSaver::_EnumEntry(const wxString &var, int &value, const wxChar *const *enumArray, int defvalue)
|
||||||
{
|
{
|
||||||
const int cnt = _calcEnumLength( enumArray );
|
const int cnt = _calcEnumLength(enumArray);
|
||||||
|
|
||||||
// Confirm default value sanity...
|
// Confirm default value sanity...
|
||||||
|
|
||||||
if( !IndexBoundsCheck( L"IniSaver EnumDefaultValue", defvalue, cnt ) )
|
if (!IndexBoundsCheck(L"IniSaver EnumDefaultValue", defvalue, cnt)) {
|
||||||
{
|
Console.Error("(SaveSettings) Default enumeration index is out of bounds. Truncating.");
|
||||||
Console.Error( "(SaveSettings) Default enumeration index is out of bounds. Truncating." );
|
defvalue = cnt - 1;
|
||||||
defvalue = cnt-1;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if( !m_Config ) return;
|
if (!m_Config)
|
||||||
|
return;
|
||||||
|
|
||||||
if( value >= cnt )
|
if (value >= cnt) {
|
||||||
{
|
Console.Warning(L"(SaveSettings) An illegal enumerated index was detected when saving '%s'", WX_STR(var));
|
||||||
Console.Warning( L"(SaveSettings) An illegal enumerated index was detected when saving '%s'", WX_STR(var) );
|
Console.Indent().Warning(
|
||||||
Console.Indent().Warning(
|
L"Illegal Value: %d\n"
|
||||||
L"Illegal Value: %d\n"
|
L"Using Default: %d (%s)\n",
|
||||||
L"Using Default: %d (%s)\n",
|
value, defvalue, enumArray[defvalue]);
|
||||||
value, defvalue, enumArray[defvalue]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Cause a debug assertion, since this is a fully recoverable error.
|
// Cause a debug assertion, since this is a fully recoverable error.
|
||||||
pxAssert( value < cnt );
|
pxAssert(value < cnt);
|
||||||
|
|
||||||
value = defvalue;
|
value = defvalue;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Config->Write( var, enumArray[value] );
|
m_Config->Write(var, enumArray[value]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,205 +27,206 @@
|
||||||
// Apple uses the MAP_ANON define instead of MAP_ANONYMOUS, but they mean
|
// Apple uses the MAP_ANON define instead of MAP_ANONYMOUS, but they mean
|
||||||
// the same thing.
|
// the same thing.
|
||||||
#if defined(__APPLE__) && !defined(MAP_ANONYMOUS)
|
#if defined(__APPLE__) && !defined(MAP_ANONYMOUS)
|
||||||
# define MAP_ANONYMOUS MAP_ANON
|
#define MAP_ANONYMOUS MAP_ANON
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern void SignalExit(int sig);
|
extern void SignalExit(int sig);
|
||||||
|
|
||||||
static const uptr m_pagemask = getpagesize()-1;
|
static const uptr m_pagemask = getpagesize() - 1;
|
||||||
|
|
||||||
// Linux implementation of SIGSEGV handler. Bind it using sigaction().
|
// Linux implementation of SIGSEGV handler. Bind it using sigaction().
|
||||||
static void SysPageFaultSignalFilter( int signal, siginfo_t *siginfo, void * )
|
static void SysPageFaultSignalFilter(int signal, siginfo_t *siginfo, void *)
|
||||||
{
|
{
|
||||||
// [TODO] : Add a thread ID filter to the Linux Signal handler here.
|
// [TODO] : Add a thread ID filter to the Linux Signal handler here.
|
||||||
// Rationale: On windows, the __try/__except model allows per-thread specific behavior
|
// Rationale: On windows, the __try/__except model allows per-thread specific behavior
|
||||||
// for page fault handling. On linux, there is a single signal handler for the whole
|
// for page fault handling. On linux, there is a single signal handler for the whole
|
||||||
// process, but the handler is executed by the thread that caused the exception.
|
// process, but the handler is executed by the thread that caused the exception.
|
||||||
|
|
||||||
|
|
||||||
// Stdio Usage note: SIGSEGV handling is a synchronous in-thread signal. It is done
|
// Stdio Usage note: SIGSEGV handling is a synchronous in-thread signal. It is done
|
||||||
// from the context of the current thread and stackframe. So long as the thread is not
|
// from the context of the current thread and stackframe. So long as the thread is not
|
||||||
// the main/ui thread, use of the px assertion system should be safe. Use of stdio should
|
// the main/ui thread, use of the px assertion system should be safe. Use of stdio should
|
||||||
// be safe even on the main thread.
|
// be safe even on the main thread.
|
||||||
// (in other words, stdio limitations only really apply to process-level asynchronous
|
// (in other words, stdio limitations only really apply to process-level asynchronous
|
||||||
// signals)
|
// signals)
|
||||||
|
|
||||||
// Note: Use of stdio functions isn't safe here. Avoid console logs,
|
// Note: Use of stdio functions isn't safe here. Avoid console logs,
|
||||||
// assertions, file logs, or just about anything else useful.
|
// assertions, file logs, or just about anything else useful.
|
||||||
|
|
||||||
|
|
||||||
// Note: This signal can be accessed by the EE or MTVU thread
|
// Note: This signal can be accessed by the EE or MTVU thread
|
||||||
// Source_PageFault is a global variable with its own state information
|
// Source_PageFault is a global variable with its own state information
|
||||||
// so for now we lock this exception code unless someone can fix this better...
|
// so for now we lock this exception code unless someone can fix this better...
|
||||||
Threading::ScopedLock lock(PageFault_Mutex);
|
Threading::ScopedLock lock(PageFault_Mutex);
|
||||||
|
|
||||||
Source_PageFault->Dispatch( PageFaultInfo( (uptr)siginfo->si_addr & ~m_pagemask ) );
|
Source_PageFault->Dispatch(PageFaultInfo((uptr)siginfo->si_addr & ~m_pagemask));
|
||||||
|
|
||||||
// resumes execution right where we left off (re-executes instruction that
|
// resumes execution right where we left off (re-executes instruction that
|
||||||
// caused the SIGSEGV).
|
// caused the SIGSEGV).
|
||||||
if (Source_PageFault->WasHandled()) return;
|
if (Source_PageFault->WasHandled())
|
||||||
|
return;
|
||||||
|
|
||||||
if (!wxThread::IsMain())
|
if (!wxThread::IsMain()) {
|
||||||
{
|
pxFailRel(pxsFmt("Unhandled page fault @ 0x%08x", siginfo->si_addr));
|
||||||
pxFailRel(pxsFmt("Unhandled page fault @ 0x%08x", siginfo->si_addr));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Bad mojo! Completely invalid address.
|
// Bad mojo! Completely invalid address.
|
||||||
// Instigate a trap if we're in a debugger, and if not then do a SIGKILL.
|
// Instigate a trap if we're in a debugger, and if not then do a SIGKILL.
|
||||||
|
|
||||||
pxTrap();
|
pxTrap();
|
||||||
if (!IsDebugBuild) raise( SIGKILL );
|
if (!IsDebugBuild)
|
||||||
|
raise(SIGKILL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _platform_InstallSignalHandler()
|
void _platform_InstallSignalHandler()
|
||||||
{
|
{
|
||||||
Console.WriteLn("Installing POSIX SIGSEGV handler...");
|
Console.WriteLn("Installing POSIX SIGSEGV handler...");
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
|
|
||||||
sigemptyset(&sa.sa_mask);
|
sigemptyset(&sa.sa_mask);
|
||||||
sa.sa_flags = SA_SIGINFO;
|
sa.sa_flags = SA_SIGINFO;
|
||||||
sa.sa_sigaction = SysPageFaultSignalFilter;
|
sa.sa_sigaction = SysPageFaultSignalFilter;
|
||||||
sigaction(SIGSEGV, &sa, NULL);
|
sigaction(SIGSEGV, &sa, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static __ri void PageSizeAssertionTest( size_t size )
|
static __ri void PageSizeAssertionTest(size_t size)
|
||||||
{
|
{
|
||||||
pxAssertMsg( (__pagesize == getpagesize()), pxsFmt(
|
pxAssertMsg((__pagesize == getpagesize()), pxsFmt(
|
||||||
"Internal system error: Operating system pagesize does not match compiled pagesize.\n\t"
|
"Internal system error: Operating system pagesize does not match compiled pagesize.\n\t"
|
||||||
L"\tOS Page Size: 0x%x (%d), Compiled Page Size: 0x%x (%u)",
|
L"\tOS Page Size: 0x%x (%d), Compiled Page Size: 0x%x (%u)",
|
||||||
getpagesize(), getpagesize(), __pagesize, __pagesize )
|
getpagesize(), getpagesize(), __pagesize, __pagesize));
|
||||||
);
|
|
||||||
|
|
||||||
pxAssertDev( (size & (__pagesize-1)) == 0, pxsFmt(
|
pxAssertDev((size & (__pagesize - 1)) == 0, pxsFmt(
|
||||||
L"Memory block size must be a multiple of the target platform's page size.\n"
|
L"Memory block size must be a multiple of the target platform's page size.\n"
|
||||||
L"\tPage Size: 0x%x (%u), Block Size: 0x%x (%u)",
|
L"\tPage Size: 0x%x (%u), Block Size: 0x%x (%u)",
|
||||||
__pagesize, __pagesize, size, size )
|
__pagesize, __pagesize, size, size));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns FALSE if the mprotect call fails with an ENOMEM.
|
// returns FALSE if the mprotect call fails with an ENOMEM.
|
||||||
// Raises assertions on other types of POSIX errors (since those typically reflect invalid object
|
// Raises assertions on other types of POSIX errors (since those typically reflect invalid object
|
||||||
// or memory states).
|
// or memory states).
|
||||||
static bool _memprotect( void* baseaddr, size_t size, const PageProtectionMode& mode )
|
static bool _memprotect(void *baseaddr, size_t size, const PageProtectionMode &mode)
|
||||||
{
|
{
|
||||||
PageSizeAssertionTest(size);
|
PageSizeAssertionTest(size);
|
||||||
|
|
||||||
uint lnxmode = 0;
|
uint lnxmode = 0;
|
||||||
|
|
||||||
if (mode.CanWrite()) lnxmode |= PROT_WRITE;
|
if (mode.CanWrite())
|
||||||
if (mode.CanRead()) lnxmode |= PROT_READ;
|
lnxmode |= PROT_WRITE;
|
||||||
if (mode.CanExecute()) lnxmode |= PROT_EXEC | PROT_READ;
|
if (mode.CanRead())
|
||||||
|
lnxmode |= PROT_READ;
|
||||||
|
if (mode.CanExecute())
|
||||||
|
lnxmode |= PROT_EXEC | PROT_READ;
|
||||||
|
|
||||||
const int result = mprotect( baseaddr, size, lnxmode );
|
const int result = mprotect(baseaddr, size, lnxmode);
|
||||||
|
|
||||||
if (result == 0) return true;
|
if (result == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
switch(errno)
|
switch (errno) {
|
||||||
{
|
case EINVAL:
|
||||||
case EINVAL:
|
pxFailDev(pxsFmt(L"mprotect returned EINVAL @ 0x%08X -> 0x%08X (mode=%s)",
|
||||||
pxFailDev(pxsFmt(L"mprotect returned EINVAL @ 0x%08X -> 0x%08X (mode=%s)",
|
baseaddr, (uptr)baseaddr + size, WX_STR(mode.ToString())));
|
||||||
baseaddr, (uptr)baseaddr+size, WX_STR(mode.ToString()))
|
break;
|
||||||
);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case EACCES:
|
case EACCES:
|
||||||
pxFailDev(pxsFmt(L"mprotect returned EACCES @ 0x%08X -> 0x%08X (mode=%s)",
|
pxFailDev(pxsFmt(L"mprotect returned EACCES @ 0x%08X -> 0x%08X (mode=%s)",
|
||||||
baseaddr, (uptr)baseaddr+size, WX_STR(mode.ToString()))
|
baseaddr, (uptr)baseaddr + size, WX_STR(mode.ToString())));
|
||||||
);
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
case ENOMEM:
|
case ENOMEM:
|
||||||
// caller handles assertion or exception, or whatever.
|
// caller handles assertion or exception, or whatever.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* HostSys::MmapReservePtr(void* base, size_t size)
|
void *HostSys::MmapReservePtr(void *base, size_t size)
|
||||||
{
|
{
|
||||||
PageSizeAssertionTest(size);
|
PageSizeAssertionTest(size);
|
||||||
|
|
||||||
// On linux a reserve-without-commit is performed by using mmap on a read-only
|
// On linux a reserve-without-commit is performed by using mmap on a read-only
|
||||||
// or anonymous source, with PROT_NONE (no-access) permission. Since the mapping
|
// or anonymous source, with PROT_NONE (no-access) permission. Since the mapping
|
||||||
// is completely inaccessible, the OS will simply reserve it and will not put it
|
// is completely inaccessible, the OS will simply reserve it and will not put it
|
||||||
// against the commit table.
|
// against the commit table.
|
||||||
return mmap(base, size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
return mmap(base, size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HostSys::MmapCommitPtr(void* base, size_t size, const PageProtectionMode& mode)
|
bool HostSys::MmapCommitPtr(void *base, size_t size, const PageProtectionMode &mode)
|
||||||
{
|
{
|
||||||
// In linux, reserved memory is automatically committed when its permissions are
|
// In linux, reserved memory is automatically committed when its permissions are
|
||||||
// changed to something other than PROT_NONE. If the user is committing memory
|
// changed to something other than PROT_NONE. If the user is committing memory
|
||||||
// as PROT_NONE, then just ignore this call (memory will be committed automatically
|
// as PROT_NONE, then just ignore this call (memory will be committed automatically
|
||||||
// later when the user changes permissions to something useful via calls to MemProtect).
|
// later when the user changes permissions to something useful via calls to MemProtect).
|
||||||
|
|
||||||
if (mode.IsNone()) return false;
|
if (mode.IsNone())
|
||||||
|
return false;
|
||||||
|
|
||||||
if (_memprotect( base, size, mode )) return true;
|
if (_memprotect(base, size, mode))
|
||||||
|
return true;
|
||||||
|
|
||||||
if (!pxDoOutOfMemory) return false;
|
if (!pxDoOutOfMemory)
|
||||||
pxDoOutOfMemory(size);
|
return false;
|
||||||
return _memprotect( base, size, mode );
|
pxDoOutOfMemory(size);
|
||||||
|
return _memprotect(base, size, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HostSys::MmapResetPtr(void* base, size_t size)
|
void HostSys::MmapResetPtr(void *base, size_t size)
|
||||||
{
|
{
|
||||||
// On linux the only way to reset the memory is to unmap and remap it as PROT_NONE.
|
// On linux the only way to reset the memory is to unmap and remap it as PROT_NONE.
|
||||||
// That forces linux to unload all committed pages and start from scratch.
|
// That forces linux to unload all committed pages and start from scratch.
|
||||||
|
|
||||||
// FIXME: Ideally this code would have some threading lock on it to prevent any other
|
// FIXME: Ideally this code would have some threading lock on it to prevent any other
|
||||||
// malloc/free code in the current process from interfering with the operation, but I
|
// malloc/free code in the current process from interfering with the operation, but I
|
||||||
// can't think of any good way to do that. (generally it shouldn't be a problem in
|
// can't think of any good way to do that. (generally it shouldn't be a problem in
|
||||||
// PCSX2 anyway, since MmapReset is only called when the ps2vm is suspended; so that
|
// PCSX2 anyway, since MmapReset is only called when the ps2vm is suspended; so that
|
||||||
// pretty well stops all PCSX2 threads anyway).
|
// pretty well stops all PCSX2 threads anyway).
|
||||||
|
|
||||||
Munmap(base, size);
|
Munmap(base, size);
|
||||||
void* result = MmapReservePtr(base, size);
|
void *result = MmapReservePtr(base, size);
|
||||||
|
|
||||||
pxAssertRel ((uptr)result == (uptr)base, pxsFmt(
|
pxAssertRel((uptr)result == (uptr)base, pxsFmt(
|
||||||
"Virtual memory decommit failed: memory at 0x%08X -> 0x%08X could not be remapped. "
|
"Virtual memory decommit failed: memory at 0x%08X -> 0x%08X could not be remapped. "
|
||||||
"This is likely caused by multi-thread memory contention.", base, (uptr)base+size
|
"This is likely caused by multi-thread memory contention.",
|
||||||
));
|
base, (uptr)base + size));
|
||||||
}
|
}
|
||||||
|
|
||||||
void* HostSys::MmapReserve(uptr base, size_t size)
|
void *HostSys::MmapReserve(uptr base, size_t size)
|
||||||
{
|
{
|
||||||
return MmapReservePtr((void*)base, size);
|
return MmapReservePtr((void *)base, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HostSys::MmapCommit(uptr base, size_t size, const PageProtectionMode& mode)
|
bool HostSys::MmapCommit(uptr base, size_t size, const PageProtectionMode &mode)
|
||||||
{
|
{
|
||||||
return MmapCommitPtr( (void*)base, size, mode );
|
return MmapCommitPtr((void *)base, size, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HostSys::MmapReset(uptr base, size_t size)
|
void HostSys::MmapReset(uptr base, size_t size)
|
||||||
{
|
{
|
||||||
MmapResetPtr((void*)base, size);
|
MmapResetPtr((void *)base, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* HostSys::Mmap(uptr base, size_t size)
|
void *HostSys::Mmap(uptr base, size_t size)
|
||||||
{
|
{
|
||||||
PageSizeAssertionTest(size);
|
PageSizeAssertionTest(size);
|
||||||
|
|
||||||
// MAP_ANONYMOUS - means we have no associated file handle (or device).
|
// MAP_ANONYMOUS - means we have no associated file handle (or device).
|
||||||
|
|
||||||
return mmap((void*)base, size, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
return mmap((void *)base, size, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HostSys::Munmap(uptr base, size_t size)
|
void HostSys::Munmap(uptr base, size_t size)
|
||||||
{
|
{
|
||||||
if (!base) return;
|
if (!base)
|
||||||
munmap((void*)base, size);
|
return;
|
||||||
|
munmap((void *)base, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HostSys::MemProtect( void* baseaddr, size_t size, const PageProtectionMode& mode )
|
void HostSys::MemProtect(void *baseaddr, size_t size, const PageProtectionMode &mode)
|
||||||
{
|
{
|
||||||
if (!_memprotect(baseaddr, size, mode))
|
if (!_memprotect(baseaddr, size, mode)) {
|
||||||
{
|
throw Exception::OutOfMemory(L"MemProtect")
|
||||||
throw Exception::OutOfMemory( L"MemProtect" )
|
.SetDiagMsg(pxsFmt(L"mprotect failed @ 0x%08X -> 0x%08X (mode=%s)",
|
||||||
.SetDiagMsg(pxsFmt( L"mprotect failed @ 0x%08X -> 0x%08X (mode=%s)",
|
baseaddr, (uptr)baseaddr + size, WX_STR(mode.ToString())));
|
||||||
baseaddr, (uptr)baseaddr+size, WX_STR(mode.ToString())
|
}
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,13 +24,13 @@
|
||||||
// Returns 0 on failure (not supported by the operating system).
|
// Returns 0 on failure (not supported by the operating system).
|
||||||
u64 GetPhysicalMemory()
|
u64 GetPhysicalMemory()
|
||||||
{
|
{
|
||||||
u64 pages = 0;
|
u64 pages = 0;
|
||||||
|
|
||||||
#ifdef _SC_PHYS_PAGES
|
#ifdef _SC_PHYS_PAGES
|
||||||
pages = sysconf(_SC_PHYS_PAGES);
|
pages = sysconf(_SC_PHYS_PAGES);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return pages * getpagesize();
|
return pages * getpagesize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,22 +40,22 @@ void InitCPUTicks()
|
||||||
|
|
||||||
u64 GetTickFrequency()
|
u64 GetTickFrequency()
|
||||||
{
|
{
|
||||||
return 1000000; // unix measures in microseconds
|
return 1000000; // unix measures in microseconds
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 GetCPUTicks()
|
u64 GetCPUTicks()
|
||||||
{
|
{
|
||||||
struct timeval t;
|
struct timeval t;
|
||||||
gettimeofday(&t, NULL);
|
gettimeofday(&t, NULL);
|
||||||
return ((u64)t.tv_sec*GetTickFrequency())+t.tv_usec;
|
return ((u64)t.tv_sec * GetTickFrequency()) + t.tv_usec;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString GetOSVersionString()
|
wxString GetOSVersionString()
|
||||||
{
|
{
|
||||||
return wxGetOsDescription();
|
return wxGetOsDescription();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScreensaverAllow(bool allow)
|
void ScreensaverAllow(bool allow)
|
||||||
{
|
{
|
||||||
// no-op
|
// no-op
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
#if !defined(__unix__)
|
#if !defined(__unix__)
|
||||||
|
|
||||||
# pragma message( "LnxThreads.cpp should only be compiled by projects or makefiles targeted at Linux/BSD distros.")
|
#pragma message("LnxThreads.cpp should only be compiled by projects or makefiles targeted at Linux/BSD distros.")
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
@ -37,23 +37,23 @@
|
||||||
// the LOCK prefix. The prefix works on single core CPUs fine (but is slow), but not
|
// the LOCK prefix. The prefix works on single core CPUs fine (but is slow), but not
|
||||||
// having the LOCK prefix is very bad indeed.
|
// having the LOCK prefix is very bad indeed.
|
||||||
|
|
||||||
__forceinline void Threading::Sleep( int ms )
|
__forceinline void Threading::Sleep(int ms)
|
||||||
{
|
{
|
||||||
usleep( 1000*ms );
|
usleep(1000 * ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For use in spin/wait loops, Acts as a hint to Intel CPUs and should, in theory
|
// For use in spin/wait loops, Acts as a hint to Intel CPUs and should, in theory
|
||||||
// improve performance and reduce cpu power consumption.
|
// improve performance and reduce cpu power consumption.
|
||||||
__forceinline void Threading::SpinWait()
|
__forceinline void Threading::SpinWait()
|
||||||
{
|
{
|
||||||
// If this doesn't compile you can just comment it out (it only serves as a
|
// If this doesn't compile you can just comment it out (it only serves as a
|
||||||
// performance hint and isn't required).
|
// performance hint and isn't required).
|
||||||
__asm__ ( "pause" );
|
__asm__("pause");
|
||||||
}
|
}
|
||||||
|
|
||||||
__forceinline void Threading::EnableHiresScheduler()
|
__forceinline void Threading::EnableHiresScheduler()
|
||||||
{
|
{
|
||||||
// Don't know if linux has a customizable scheduler resolution like Windows (doubtful)
|
// Don't know if linux has a customizable scheduler resolution like Windows (doubtful)
|
||||||
}
|
}
|
||||||
|
|
||||||
__forceinline void Threading::DisableHiresScheduler()
|
__forceinline void Threading::DisableHiresScheduler()
|
||||||
|
@ -63,66 +63,69 @@ __forceinline void Threading::DisableHiresScheduler()
|
||||||
// Unit of time of GetThreadCpuTime/GetCpuTime
|
// Unit of time of GetThreadCpuTime/GetCpuTime
|
||||||
u64 Threading::GetThreadTicksPerSecond()
|
u64 Threading::GetThreadTicksPerSecond()
|
||||||
{
|
{
|
||||||
return 1000000;
|
return 1000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to get either either the current cpu usage
|
// Helper function to get either either the current cpu usage
|
||||||
// in called thread or in id thread
|
// in called thread or in id thread
|
||||||
static u64 get_thread_time(uptr id = 0)
|
static u64 get_thread_time(uptr id = 0)
|
||||||
{
|
{
|
||||||
clockid_t cid;
|
clockid_t cid;
|
||||||
if (id) {
|
if (id) {
|
||||||
int err = pthread_getcpuclockid((pthread_t)id, &cid);
|
int err = pthread_getcpuclockid((pthread_t)id, &cid);
|
||||||
if (err) return 0;
|
if (err)
|
||||||
} else {
|
return 0;
|
||||||
cid = CLOCK_THREAD_CPUTIME_ID;
|
} else {
|
||||||
}
|
cid = CLOCK_THREAD_CPUTIME_ID;
|
||||||
|
}
|
||||||
|
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
int err = clock_gettime(cid, &ts);
|
int err = clock_gettime(cid, &ts);
|
||||||
if (err) return 0;
|
if (err)
|
||||||
|
return 0;
|
||||||
|
|
||||||
return (u64) ts.tv_sec * (u64) 1e6 + (u64) ts.tv_nsec / (u64) 1e3;
|
return (u64)ts.tv_sec * (u64)1e6 + (u64)ts.tv_nsec / (u64)1e3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the current timestamp (not relative to a real world clock)
|
// Returns the current timestamp (not relative to a real world clock)
|
||||||
u64 Threading::GetThreadCpuTime()
|
u64 Threading::GetThreadCpuTime()
|
||||||
{
|
{
|
||||||
return get_thread_time();
|
return get_thread_time();
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 Threading::pxThread::GetCpuTime() const
|
u64 Threading::pxThread::GetCpuTime() const
|
||||||
{
|
{
|
||||||
// Get the cpu time for the thread belonging to this object. Use m_native_id and/or
|
// Get the cpu time for the thread belonging to this object. Use m_native_id and/or
|
||||||
// m_native_handle to implement it. Return value should be a measure of total time the
|
// m_native_handle to implement it. Return value should be a measure of total time the
|
||||||
// thread has used on the CPU (scaled by the value returned by GetThreadTicksPerSecond(),
|
// thread has used on the CPU (scaled by the value returned by GetThreadTicksPerSecond(),
|
||||||
// which typically would be an OS-provided scalar or some sort).
|
// which typically would be an OS-provided scalar or some sort).
|
||||||
|
|
||||||
if (!m_native_id) return 0;
|
if (!m_native_id)
|
||||||
|
return 0;
|
||||||
|
|
||||||
return get_thread_time(m_native_id);
|
return get_thread_time(m_native_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Threading::pxThread::_platform_specific_OnStartInThread()
|
void Threading::pxThread::_platform_specific_OnStartInThread()
|
||||||
{
|
{
|
||||||
// Obtain linux-specific thread IDs or Handles here, which can be used to query
|
// Obtain linux-specific thread IDs or Handles here, which can be used to query
|
||||||
// kernel scheduler performance information.
|
// kernel scheduler performance information.
|
||||||
m_native_id = (uptr) pthread_self();
|
m_native_id = (uptr)pthread_self();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Threading::pxThread::_platform_specific_OnCleanupInThread()
|
void Threading::pxThread::_platform_specific_OnCleanupInThread()
|
||||||
{
|
{
|
||||||
// Cleanup handles here, which were opened above.
|
// Cleanup handles here, which were opened above.
|
||||||
}
|
}
|
||||||
|
|
||||||
void Threading::pxThread::_DoSetThreadName( const char* name )
|
void Threading::pxThread::_DoSetThreadName(const char *name)
|
||||||
{
|
{
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
// Extract of manpage: "The name can be up to 16 bytes long, and should be
|
// Extract of manpage: "The name can be up to 16 bytes long, and should be
|
||||||
// null-terminated if it contains fewer bytes."
|
// null-terminated if it contains fewer bytes."
|
||||||
prctl(PR_SET_NAME, name, 0, 0, 0);
|
prctl(PR_SET_NAME, name, 0, 0, 0);
|
||||||
#elif defined(__unix__)
|
#elif defined(__unix__)
|
||||||
pthread_set_name_np(pthread_self(), name);
|
pthread_set_name_np(pthread_self(), name);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,8 @@
|
||||||
|
|
||||||
namespace Threading
|
namespace Threading
|
||||||
{
|
{
|
||||||
static std::atomic<int> _attr_refcount(0);
|
static std::atomic<int> _attr_refcount(0);
|
||||||
static pthread_mutexattr_t _attr_recursive;
|
static pthread_mutexattr_t _attr_recursive;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -38,7 +38,7 @@ namespace Threading
|
||||||
// We have to emulate pthread_mutex_timedlock(). This could be a serious
|
// We have to emulate pthread_mutex_timedlock(). This could be a serious
|
||||||
// performance drain if its used a lot.
|
// performance drain if its used a lot.
|
||||||
|
|
||||||
#include <sys/time.h> // gettimeofday()
|
#include <sys/time.h> // gettimeofday()
|
||||||
|
|
||||||
// sleep for 10ms at a time
|
// sleep for 10ms at a time
|
||||||
#define TIMEDLOCK_EMU_SLEEP_NS 10000000ULL
|
#define TIMEDLOCK_EMU_SLEEP_NS 10000000ULL
|
||||||
|
@ -55,87 +55,91 @@ namespace Threading
|
||||||
// This is an implementation that emulates pthread_mutex_timedlock() via
|
// This is an implementation that emulates pthread_mutex_timedlock() via
|
||||||
// pthread_mutex_trylock().
|
// pthread_mutex_trylock().
|
||||||
static int xpthread_mutex_timedlock(
|
static int xpthread_mutex_timedlock(
|
||||||
pthread_mutex_t *mutex,
|
pthread_mutex_t *mutex,
|
||||||
const struct timespec *abs_timeout)
|
const struct timespec *abs_timeout)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
while ((err = pthread_mutex_trylock(mutex)) == EBUSY) {
|
while ((err = pthread_mutex_trylock(mutex)) == EBUSY) {
|
||||||
// acquiring lock failed, sleep some
|
// acquiring lock failed, sleep some
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
ts.tv_sec = 0;
|
ts.tv_sec = 0;
|
||||||
ts.tv_nsec = TIMEDLOCK_EMU_SLEEP_NS;
|
ts.tv_nsec = TIMEDLOCK_EMU_SLEEP_NS;
|
||||||
int status;
|
int status;
|
||||||
while ((status = nanosleep(&ts, &ts)) == -1);
|
while ((status = nanosleep(&ts, &ts)) == -1)
|
||||||
|
;
|
||||||
|
|
||||||
// check if the timeout has expired, gettimeofday() is implemented
|
// check if the timeout has expired, gettimeofday() is implemented
|
||||||
// efficiently (in userspace) on OSX
|
// efficiently (in userspace) on OSX
|
||||||
struct timeval now;
|
struct timeval now;
|
||||||
int res = gettimeofday(&now, NULL);
|
int res = gettimeofday(&now, NULL);
|
||||||
if (abs_timeout->tv_sec == 0 || now.tv_sec > abs_timeout->tv_sec ||
|
if (abs_timeout->tv_sec == 0 || now.tv_sec > abs_timeout->tv_sec ||
|
||||||
(u64) now.tv_usec * 1000ULL > (u64) abs_timeout->tv_nsec) {
|
(u64)now.tv_usec * 1000ULL > (u64)abs_timeout->tv_nsec) {
|
||||||
return ETIMEDOUT;
|
return ETIMEDOUT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Threading::Mutex::Mutex()
|
Threading::Mutex::Mutex()
|
||||||
{
|
{
|
||||||
pthread_mutex_init( &m_mutex, NULL );
|
pthread_mutex_init(&m_mutex, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static wxTimeSpan def_detach_timeout( 0, 0, 6, 0 );
|
static wxTimeSpan def_detach_timeout(0, 0, 6, 0);
|
||||||
|
|
||||||
void Threading::Mutex::Detach()
|
void Threading::Mutex::Detach()
|
||||||
{
|
{
|
||||||
if( EBUSY != pthread_mutex_destroy(&m_mutex) ) return;
|
if (EBUSY != pthread_mutex_destroy(&m_mutex))
|
||||||
|
return;
|
||||||
|
|
||||||
if( IsRecursive() )
|
if (IsRecursive()) {
|
||||||
{
|
// Sanity check: Recursive locks could be held by our own thread, which would
|
||||||
// Sanity check: Recursive locks could be held by our own thread, which would
|
// be considered an assertion failure, but can also be handled gracefully.
|
||||||
// be considered an assertion failure, but can also be handled gracefully.
|
// (note: if the mutex is locked recursively more than twice then this assert won't
|
||||||
// (note: if the mutex is locked recursively more than twice then this assert won't
|
// detect it)
|
||||||
// detect it)
|
|
||||||
|
|
||||||
Release(); Release(); // in case of double recursion.
|
Release();
|
||||||
int result = pthread_mutex_destroy( &m_mutex );
|
Release(); // in case of double recursion.
|
||||||
if( pxAssertDev( result != EBUSY, "Detachment of a recursively-locked mutex (self-locked!)." ) ) return;
|
int result = pthread_mutex_destroy(&m_mutex);
|
||||||
}
|
if (pxAssertDev(result != EBUSY, "Detachment of a recursively-locked mutex (self-locked!)."))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if( Wait(def_detach_timeout) )
|
if (Wait(def_detach_timeout))
|
||||||
pthread_mutex_destroy( &m_mutex );
|
pthread_mutex_destroy(&m_mutex);
|
||||||
else
|
else
|
||||||
Console.Error( "(Thread Log) Mutex cleanup failed due to possible deadlock.");
|
Console.Error("(Thread Log) Mutex cleanup failed due to possible deadlock.");
|
||||||
}
|
}
|
||||||
|
|
||||||
Threading::Mutex::~Mutex() throw()
|
Threading::Mutex::~Mutex() throw()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
Mutex::Detach();
|
Mutex::Detach();
|
||||||
} DESTRUCTOR_CATCHALL;
|
}
|
||||||
|
DESTRUCTOR_CATCHALL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Threading::MutexRecursive::MutexRecursive() : Mutex( false )
|
Threading::MutexRecursive::MutexRecursive()
|
||||||
|
: Mutex(false)
|
||||||
{
|
{
|
||||||
if( ++_attr_refcount == 1 )
|
if (++_attr_refcount == 1) {
|
||||||
{
|
if (0 != pthread_mutexattr_init(&_attr_recursive))
|
||||||
if( 0 != pthread_mutexattr_init( &_attr_recursive ) )
|
throw Exception::OutOfMemory(L"Recursive mutexing attributes");
|
||||||
throw Exception::OutOfMemory(L"Recursive mutexing attributes");
|
|
||||||
|
|
||||||
pthread_mutexattr_settype( &_attr_recursive, PTHREAD_MUTEX_RECURSIVE );
|
pthread_mutexattr_settype(&_attr_recursive, PTHREAD_MUTEX_RECURSIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pthread_mutex_init( &m_mutex, &_attr_recursive ))
|
if (pthread_mutex_init(&m_mutex, &_attr_recursive))
|
||||||
Console.Error( "(Thread Log) Failed to initialize mutex.");
|
Console.Error("(Thread Log) Failed to initialize mutex.");
|
||||||
}
|
}
|
||||||
|
|
||||||
Threading::MutexRecursive::~MutexRecursive() throw()
|
Threading::MutexRecursive::~MutexRecursive() throw()
|
||||||
{
|
{
|
||||||
if( --_attr_refcount == 0 )
|
if (--_attr_refcount == 0)
|
||||||
pthread_mutexattr_destroy( &_attr_recursive );
|
pthread_mutexattr_destroy(&_attr_recursive);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a bit of a hackish function, which is technically unsafe, but can be useful for allowing
|
// This is a bit of a hackish function, which is technically unsafe, but can be useful for allowing
|
||||||
|
@ -144,8 +148,8 @@ Threading::MutexRecursive::~MutexRecursive() throw()
|
||||||
// the deeper meanings of the universe for eternity.
|
// the deeper meanings of the universe for eternity.
|
||||||
void Threading::Mutex::Recreate()
|
void Threading::Mutex::Recreate()
|
||||||
{
|
{
|
||||||
Detach();
|
Detach();
|
||||||
pthread_mutex_init( &m_mutex, NULL );
|
pthread_mutex_init(&m_mutex, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns:
|
// Returns:
|
||||||
|
@ -153,12 +157,11 @@ void Threading::Mutex::Recreate()
|
||||||
// unlocked.
|
// unlocked.
|
||||||
bool Threading::Mutex::RecreateIfLocked()
|
bool Threading::Mutex::RecreateIfLocked()
|
||||||
{
|
{
|
||||||
if( !Wait(def_detach_timeout) )
|
if (!Wait(def_detach_timeout)) {
|
||||||
{
|
Recreate();
|
||||||
Recreate();
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
return false;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -168,25 +171,25 @@ bool Threading::Mutex::RecreateIfLocked()
|
||||||
// other than the main thread.
|
// other than the main thread.
|
||||||
void Threading::Mutex::AcquireWithoutYield()
|
void Threading::Mutex::AcquireWithoutYield()
|
||||||
{
|
{
|
||||||
pxAssertMsg( !wxThread::IsMain(), "Unyielding mutex acquire issued from the main/gui thread. Please use Acquire() instead." );
|
pxAssertMsg(!wxThread::IsMain(), "Unyielding mutex acquire issued from the main/gui thread. Please use Acquire() instead.");
|
||||||
pthread_mutex_lock( &m_mutex );
|
pthread_mutex_lock(&m_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Threading::Mutex::AcquireWithoutYield( const wxTimeSpan& timeout )
|
bool Threading::Mutex::AcquireWithoutYield(const wxTimeSpan &timeout)
|
||||||
{
|
{
|
||||||
wxDateTime megafail( wxDateTime::UNow() + timeout );
|
wxDateTime megafail(wxDateTime::UNow() + timeout);
|
||||||
const timespec fail = { megafail.GetTicks(), megafail.GetMillisecond() * 1000000 };
|
const timespec fail = {megafail.GetTicks(), megafail.GetMillisecond() * 1000000};
|
||||||
return xpthread_mutex_timedlock( &m_mutex, &fail ) == 0;
|
return xpthread_mutex_timedlock(&m_mutex, &fail) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Threading::Mutex::Release()
|
void Threading::Mutex::Release()
|
||||||
{
|
{
|
||||||
pthread_mutex_unlock( &m_mutex );
|
pthread_mutex_unlock(&m_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Threading::Mutex::TryAcquire()
|
bool Threading::Mutex::TryAcquire()
|
||||||
{
|
{
|
||||||
return EBUSY != pthread_mutex_trylock( &m_mutex );
|
return EBUSY != pthread_mutex_trylock(&m_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a wxApp-safe rendition of AcquireWithoutYield, which makes sure to execute pending app events
|
// This is a wxApp-safe rendition of AcquireWithoutYield, which makes sure to execute pending app events
|
||||||
|
@ -195,54 +198,45 @@ bool Threading::Mutex::TryAcquire()
|
||||||
void Threading::Mutex::Acquire()
|
void Threading::Mutex::Acquire()
|
||||||
{
|
{
|
||||||
#if wxUSE_GUI
|
#if wxUSE_GUI
|
||||||
if( !wxThread::IsMain() || (wxTheApp == NULL) )
|
if (!wxThread::IsMain() || (wxTheApp == NULL)) {
|
||||||
{
|
pthread_mutex_lock(&m_mutex);
|
||||||
pthread_mutex_lock( &m_mutex );
|
} else if (_WaitGui_RecursionGuard(L"Mutex::Acquire")) {
|
||||||
}
|
ScopedBusyCursor hourglass(Cursor_ReallyBusy);
|
||||||
else if( _WaitGui_RecursionGuard( L"Mutex::Acquire" ) )
|
pthread_mutex_lock(&m_mutex);
|
||||||
{
|
} else {
|
||||||
ScopedBusyCursor hourglass( Cursor_ReallyBusy );
|
//ScopedBusyCursor hourglass( Cursor_KindaBusy );
|
||||||
pthread_mutex_lock( &m_mutex );
|
while (!AcquireWithoutYield(def_yieldgui_interval))
|
||||||
}
|
YieldToMain();
|
||||||
else
|
}
|
||||||
{
|
|
||||||
//ScopedBusyCursor hourglass( Cursor_KindaBusy );
|
|
||||||
while( !AcquireWithoutYield(def_yieldgui_interval) )
|
|
||||||
YieldToMain();
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
pthread_mutex_lock( &m_mutex );
|
pthread_mutex_lock(&m_mutex);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Threading::Mutex::Acquire( const wxTimeSpan& timeout )
|
bool Threading::Mutex::Acquire(const wxTimeSpan &timeout)
|
||||||
{
|
{
|
||||||
#if wxUSE_GUI
|
#if wxUSE_GUI
|
||||||
if( !wxThread::IsMain() || (wxTheApp == NULL) )
|
if (!wxThread::IsMain() || (wxTheApp == NULL)) {
|
||||||
{
|
return AcquireWithoutYield(timeout);
|
||||||
return AcquireWithoutYield(timeout);
|
} else if (_WaitGui_RecursionGuard(L"Mutex::TimedAcquire")) {
|
||||||
}
|
ScopedBusyCursor hourglass(Cursor_ReallyBusy);
|
||||||
else if( _WaitGui_RecursionGuard( L"Mutex::TimedAcquire" ) )
|
return AcquireWithoutYield(timeout);
|
||||||
{
|
} else {
|
||||||
ScopedBusyCursor hourglass( Cursor_ReallyBusy );
|
//ScopedBusyCursor hourglass( Cursor_KindaBusy );
|
||||||
return AcquireWithoutYield( timeout );
|
wxTimeSpan countdown((timeout));
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//ScopedBusyCursor hourglass( Cursor_KindaBusy );
|
|
||||||
wxTimeSpan countdown( (timeout) );
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if( AcquireWithoutYield( def_yieldgui_interval ) ) break;
|
if (AcquireWithoutYield(def_yieldgui_interval))
|
||||||
YieldToMain();
|
break;
|
||||||
countdown -= def_yieldgui_interval;
|
YieldToMain();
|
||||||
} while( countdown.GetMilliseconds() > 0 );
|
countdown -= def_yieldgui_interval;
|
||||||
|
} while (countdown.GetMilliseconds() > 0);
|
||||||
|
|
||||||
return countdown.GetMilliseconds() > 0;
|
return countdown.GetMilliseconds() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
return AcquireWithoutYield();
|
return AcquireWithoutYield();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,14 +249,14 @@ bool Threading::Mutex::Acquire( const wxTimeSpan& timeout )
|
||||||
//
|
//
|
||||||
void Threading::Mutex::Wait()
|
void Threading::Mutex::Wait()
|
||||||
{
|
{
|
||||||
Acquire();
|
Acquire();
|
||||||
Release();
|
Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Threading::Mutex::WaitWithoutYield()
|
void Threading::Mutex::WaitWithoutYield()
|
||||||
{
|
{
|
||||||
AcquireWithoutYield();
|
AcquireWithoutYield();
|
||||||
Release();
|
Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Performs a wait on a locked mutex, or returns instantly if the mutex is unlocked.
|
// Performs a wait on a locked mutex, or returns instantly if the mutex is unlocked.
|
||||||
|
@ -272,24 +266,22 @@ void Threading::Mutex::WaitWithoutYield()
|
||||||
// true if the mutex was freed and is in an unlocked state; or false if the wait timed out
|
// true if the mutex was freed and is in an unlocked state; or false if the wait timed out
|
||||||
// and the mutex is still locked by another thread.
|
// and the mutex is still locked by another thread.
|
||||||
//
|
//
|
||||||
bool Threading::Mutex::Wait( const wxTimeSpan& timeout )
|
bool Threading::Mutex::Wait(const wxTimeSpan &timeout)
|
||||||
{
|
{
|
||||||
if( Acquire(timeout) )
|
if (Acquire(timeout)) {
|
||||||
{
|
Release();
|
||||||
Release();
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
return false;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Threading::Mutex::WaitWithoutYield( const wxTimeSpan& timeout )
|
bool Threading::Mutex::WaitWithoutYield(const wxTimeSpan &timeout)
|
||||||
{
|
{
|
||||||
if( AcquireWithoutYield(timeout) )
|
if (AcquireWithoutYield(timeout)) {
|
||||||
{
|
Release();
|
||||||
Release();
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
return false;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------
|
||||||
|
@ -298,67 +290,72 @@ bool Threading::Mutex::WaitWithoutYield( const wxTimeSpan& timeout )
|
||||||
|
|
||||||
Threading::ScopedLock::~ScopedLock() throw()
|
Threading::ScopedLock::~ScopedLock() throw()
|
||||||
{
|
{
|
||||||
if( m_IsLocked && m_lock )
|
if (m_IsLocked && m_lock)
|
||||||
m_lock->Release();
|
m_lock->Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
Threading::ScopedLock::ScopedLock( const Mutex* locker )
|
Threading::ScopedLock::ScopedLock(const Mutex *locker)
|
||||||
{
|
{
|
||||||
m_IsLocked = false;
|
m_IsLocked = false;
|
||||||
AssignAndLock( locker );
|
AssignAndLock(locker);
|
||||||
}
|
}
|
||||||
|
|
||||||
Threading::ScopedLock::ScopedLock( const Mutex& locker )
|
Threading::ScopedLock::ScopedLock(const Mutex &locker)
|
||||||
{
|
{
|
||||||
m_IsLocked = false;
|
m_IsLocked = false;
|
||||||
AssignAndLock( locker );
|
AssignAndLock(locker);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Threading::ScopedLock::AssignAndLock( const Mutex& locker )
|
void Threading::ScopedLock::AssignAndLock(const Mutex &locker)
|
||||||
{
|
{
|
||||||
AssignAndLock( &locker );
|
AssignAndLock(&locker);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Threading::ScopedLock::AssignAndLock( const Mutex* locker )
|
void Threading::ScopedLock::AssignAndLock(const Mutex *locker)
|
||||||
{
|
{
|
||||||
pxAssert(!m_IsLocked); // if we're already locked, changing the lock is bad mojo.
|
pxAssert(!m_IsLocked); // if we're already locked, changing the lock is bad mojo.
|
||||||
|
|
||||||
m_lock = const_cast<Mutex*>(locker);
|
m_lock = const_cast<Mutex *>(locker);
|
||||||
if( !m_lock ) return;
|
if (!m_lock)
|
||||||
|
return;
|
||||||
|
|
||||||
m_IsLocked = true;
|
m_IsLocked = true;
|
||||||
m_lock->Acquire();
|
m_lock->Acquire();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Threading::ScopedLock::Assign( const Mutex& locker )
|
void Threading::ScopedLock::Assign(const Mutex &locker)
|
||||||
{
|
{
|
||||||
m_lock = const_cast<Mutex*>(&locker);
|
m_lock = const_cast<Mutex *>(&locker);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Threading::ScopedLock::Assign( const Mutex* locker )
|
void Threading::ScopedLock::Assign(const Mutex *locker)
|
||||||
{
|
{
|
||||||
m_lock = const_cast<Mutex*>(locker);
|
m_lock = const_cast<Mutex *>(locker);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provides manual unlocking of a scoped lock prior to object destruction.
|
// Provides manual unlocking of a scoped lock prior to object destruction.
|
||||||
void Threading::ScopedLock::Release()
|
void Threading::ScopedLock::Release()
|
||||||
{
|
{
|
||||||
if( !m_IsLocked ) return;
|
if (!m_IsLocked)
|
||||||
m_IsLocked = false;
|
return;
|
||||||
if( m_lock ) m_lock->Release();
|
m_IsLocked = false;
|
||||||
|
if (m_lock)
|
||||||
|
m_lock->Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
// provides manual locking of a scoped lock, to re-lock after a manual unlocking.
|
// provides manual locking of a scoped lock, to re-lock after a manual unlocking.
|
||||||
void Threading::ScopedLock::Acquire()
|
void Threading::ScopedLock::Acquire()
|
||||||
{
|
{
|
||||||
if( m_IsLocked || !m_lock ) return;
|
if (m_IsLocked || !m_lock)
|
||||||
m_lock->Acquire();
|
return;
|
||||||
m_IsLocked = true;
|
m_lock->Acquire();
|
||||||
|
m_IsLocked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Threading::ScopedLock::ScopedLock( const Mutex& locker, bool isTryLock )
|
Threading::ScopedLock::ScopedLock(const Mutex &locker, bool isTryLock)
|
||||||
{
|
{
|
||||||
m_lock = const_cast<Mutex*>(&locker);
|
m_lock = const_cast<Mutex *>(&locker);
|
||||||
if( !m_lock ) return;
|
if (!m_lock)
|
||||||
m_IsLocked = isTryLock ? m_lock->TryAcquire() : false;
|
return;
|
||||||
|
m_IsLocked = isTryLock ? m_lock->TryAcquire() : false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,72 +23,74 @@
|
||||||
// wxDirName (implementations)
|
// wxDirName (implementations)
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
wxFileName wxDirName::Combine( const wxFileName& right ) const
|
wxFileName wxDirName::Combine(const wxFileName &right) const
|
||||||
{
|
{
|
||||||
pxAssertMsg( IsDir(), L"Warning: Malformed directory name detected during wxDirName concatenation." );
|
pxAssertMsg(IsDir(), L"Warning: Malformed directory name detected during wxDirName concatenation.");
|
||||||
if( right.IsAbsolute() )
|
if (right.IsAbsolute())
|
||||||
return right;
|
return right;
|
||||||
|
|
||||||
// Append any directory parts from right, and then set the filename.
|
// Append any directory parts from right, and then set the filename.
|
||||||
// Except we can't do that because our m_members are private (argh!) and there is no API
|
// Except we can't do that because our m_members are private (argh!) and there is no API
|
||||||
// for getting each component of the path. So instead let's use Normalize:
|
// for getting each component of the path. So instead let's use Normalize:
|
||||||
|
|
||||||
wxFileName result( right );
|
wxFileName result(right);
|
||||||
result.Normalize( wxPATH_NORM_ENV_VARS | wxPATH_NORM_DOTS | wxPATH_NORM_ABSOLUTE, GetPath() );
|
result.Normalize(wxPATH_NORM_ENV_VARS | wxPATH_NORM_DOTS | wxPATH_NORM_ABSOLUTE, GetPath());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxDirName wxDirName::Combine( const wxDirName& right ) const
|
wxDirName wxDirName::Combine(const wxDirName &right) const
|
||||||
{
|
{
|
||||||
pxAssertMsg( IsDir() && right.IsDir(), L"Warning: Malformed directory name detected during wDirName concatenation." );
|
pxAssertMsg(IsDir() && right.IsDir(), L"Warning: Malformed directory name detected during wDirName concatenation.");
|
||||||
|
|
||||||
wxDirName result( right );
|
wxDirName result(right);
|
||||||
result.Normalize( wxPATH_NORM_ENV_VARS | wxPATH_NORM_DOTS | wxPATH_NORM_ABSOLUTE, GetPath() );
|
result.Normalize(wxPATH_NORM_ENV_VARS | wxPATH_NORM_DOTS | wxPATH_NORM_ABSOLUTE, GetPath());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxDirName& wxDirName::Normalize( int flags, const wxString& cwd )
|
wxDirName &wxDirName::Normalize(int flags, const wxString &cwd)
|
||||||
{
|
{
|
||||||
pxAssertMsg( IsDir(), L"Warning: Malformed directory name detected during wDirName normalization." );
|
pxAssertMsg(IsDir(), L"Warning: Malformed directory name detected during wDirName normalization.");
|
||||||
if( !wxFileName::Normalize( flags, cwd ) )
|
if (!wxFileName::Normalize(flags, cwd))
|
||||||
throw Exception::ParseError().SetDiagMsg( L"wxDirName::Normalize operation failed." );
|
throw Exception::ParseError().SetDiagMsg(L"wxDirName::Normalize operation failed.");
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxDirName& wxDirName::MakeRelativeTo( const wxString& pathBase )
|
wxDirName &wxDirName::MakeRelativeTo(const wxString &pathBase)
|
||||||
{
|
{
|
||||||
pxAssertMsg( IsDir(), L"Warning: Malformed directory name detected during wDirName normalization." );
|
pxAssertMsg(IsDir(), L"Warning: Malformed directory name detected during wDirName normalization.");
|
||||||
if( !wxFileName::MakeRelativeTo( pathBase ) )
|
if (!wxFileName::MakeRelativeTo(pathBase))
|
||||||
throw Exception::ParseError().SetDiagMsg( L"wxDirName::MakeRelativeTo operation failed." );
|
throw Exception::ParseError().SetDiagMsg(L"wxDirName::MakeRelativeTo operation failed.");
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxDirName& wxDirName::MakeAbsolute( const wxString& cwd )
|
wxDirName &wxDirName::MakeAbsolute(const wxString &cwd)
|
||||||
{
|
{
|
||||||
pxAssertMsg( IsDir(), L"Warning: Malformed directory name detected during wDirName normalization." );
|
pxAssertMsg(IsDir(), L"Warning: Malformed directory name detected during wDirName normalization.");
|
||||||
if( !wxFileName::MakeAbsolute( cwd ) )
|
if (!wxFileName::MakeAbsolute(cwd))
|
||||||
throw Exception::ParseError().SetDiagMsg( L"wxDirName::MakeAbsolute operation failed." );
|
throw Exception::ParseError().SetDiagMsg(L"wxDirName::MakeAbsolute operation failed.");
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxDirName::Rmdir()
|
void wxDirName::Rmdir()
|
||||||
{
|
{
|
||||||
if( !Exists() ) return;
|
if (!Exists())
|
||||||
wxFileName::Rmdir();
|
return;
|
||||||
// TODO : Throw exception if operation failed? Do we care?
|
wxFileName::Rmdir();
|
||||||
|
// TODO : Throw exception if operation failed? Do we care?
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxDirName::Mkdir()
|
bool wxDirName::Mkdir()
|
||||||
{
|
{
|
||||||
// wxWidgets recurses directory creation for us.
|
// wxWidgets recurses directory creation for us.
|
||||||
|
|
||||||
// only exist in wx2.9 and above
|
// only exist in wx2.9 and above
|
||||||
#ifndef wxS_DIR_DEFAULT
|
#ifndef wxS_DIR_DEFAULT
|
||||||
#define wxS_DIR_DEFAULT 0777
|
#define wxS_DIR_DEFAULT 0777
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if( Exists() ) return true;
|
if (Exists())
|
||||||
return wxFileName::Mkdir(wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL);
|
return true;
|
||||||
|
return wxFileName::Mkdir(wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -97,110 +99,111 @@ bool wxDirName::Mkdir()
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
bool Path::IsRelative( const wxString& path )
|
bool Path::IsRelative(const wxString &path)
|
||||||
{
|
{
|
||||||
return wxDirName( path ).IsRelative();
|
return wxDirName(path).IsRelative();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns -1 if the file does not exist.
|
// Returns -1 if the file does not exist.
|
||||||
s64 Path::GetFileSize( const wxString& path )
|
s64 Path::GetFileSize(const wxString &path)
|
||||||
{
|
{
|
||||||
if( !wxFile::Exists( path.c_str() ) ) return -1;
|
if (!wxFile::Exists(path.c_str()))
|
||||||
return (s64)wxFileName::GetSize( path ).GetValue();
|
return -1;
|
||||||
|
return (s64)wxFileName::GetSize(path).GetValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
wxString Path::Normalize( const wxString& src )
|
wxString Path::Normalize(const wxString &src)
|
||||||
{
|
{
|
||||||
wxFileName normalize( src );
|
wxFileName normalize(src);
|
||||||
normalize.Normalize();
|
normalize.Normalize();
|
||||||
return normalize.GetFullPath();
|
return normalize.GetFullPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString Path::Normalize( const wxDirName& src )
|
wxString Path::Normalize(const wxDirName &src)
|
||||||
{
|
{
|
||||||
return wxDirName(src).Normalize().ToString();
|
return wxDirName(src).Normalize().ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString Path::MakeAbsolute( const wxString& src )
|
wxString Path::MakeAbsolute(const wxString &src)
|
||||||
{
|
{
|
||||||
wxFileName absolute( src );
|
wxFileName absolute(src);
|
||||||
absolute.MakeAbsolute();
|
absolute.MakeAbsolute();
|
||||||
return absolute.GetFullPath();
|
return absolute.GetFullPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Concatenates two pathnames together, inserting delimiters (backslash on win32)
|
// Concatenates two pathnames together, inserting delimiters (backslash on win32)
|
||||||
// as needed! Assumes the 'dest' is allocated to at least g_MaxPath length.
|
// as needed! Assumes the 'dest' is allocated to at least g_MaxPath length.
|
||||||
//
|
//
|
||||||
wxString Path::Combine( const wxString& srcPath, const wxString& srcFile )
|
wxString Path::Combine(const wxString &srcPath, const wxString &srcFile)
|
||||||
{
|
{
|
||||||
return (wxDirName( srcPath ) + srcFile).GetFullPath();
|
return (wxDirName(srcPath) + srcFile).GetFullPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString Path::Combine( const wxDirName& srcPath, const wxFileName& srcFile )
|
wxString Path::Combine(const wxDirName &srcPath, const wxFileName &srcFile)
|
||||||
{
|
{
|
||||||
return (srcPath + srcFile).GetFullPath();
|
return (srcPath + srcFile).GetFullPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString Path::Combine( const wxString& srcPath, const wxDirName& srcFile )
|
wxString Path::Combine(const wxString &srcPath, const wxDirName &srcFile)
|
||||||
{
|
{
|
||||||
return (wxDirName( srcPath ) + srcFile).ToString();
|
return (wxDirName(srcPath) + srcFile).ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replaces the extension of the file with the one given.
|
// Replaces the extension of the file with the one given.
|
||||||
// This function works for path names as well as file names.
|
// This function works for path names as well as file names.
|
||||||
wxString Path::ReplaceExtension( const wxString& src, const wxString& ext )
|
wxString Path::ReplaceExtension(const wxString &src, const wxString &ext)
|
||||||
{
|
{
|
||||||
wxFileName jojo( src );
|
wxFileName jojo(src);
|
||||||
jojo.SetExt( ext );
|
jojo.SetExt(ext);
|
||||||
return jojo.GetFullPath();
|
return jojo.GetFullPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString Path::ReplaceFilename( const wxString& src, const wxString& newfilename )
|
wxString Path::ReplaceFilename(const wxString &src, const wxString &newfilename)
|
||||||
{
|
{
|
||||||
wxFileName jojo( src );
|
wxFileName jojo(src);
|
||||||
jojo.SetFullName( newfilename );
|
jojo.SetFullName(newfilename);
|
||||||
return jojo.GetFullPath();
|
return jojo.GetFullPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString Path::GetFilename( const wxString& src )
|
wxString Path::GetFilename(const wxString &src)
|
||||||
{
|
{
|
||||||
return wxFileName(src).GetFullName();
|
return wxFileName(src).GetFullName();
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString Path::GetFilenameWithoutExt( const wxString& src )
|
wxString Path::GetFilenameWithoutExt(const wxString &src)
|
||||||
{
|
{
|
||||||
return wxFileName(src).GetName();
|
return wxFileName(src).GetName();
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString Path::GetDirectory( const wxString& src )
|
wxString Path::GetDirectory(const wxString &src)
|
||||||
{
|
{
|
||||||
return wxFileName(src).GetPath();
|
return wxFileName(src).GetPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// returns the base/root directory of the given path.
|
// returns the base/root directory of the given path.
|
||||||
// Example /this/that/something.txt -> dest == "/"
|
// Example /this/that/something.txt -> dest == "/"
|
||||||
wxString Path::GetRootDirectory( const wxString& src )
|
wxString Path::GetRootDirectory(const wxString &src)
|
||||||
{
|
{
|
||||||
size_t pos = src.find_first_of( wxFileName::GetPathSeparators() );
|
size_t pos = src.find_first_of(wxFileName::GetPathSeparators());
|
||||||
if( pos == wxString::npos )
|
if (pos == wxString::npos)
|
||||||
return wxString();
|
return wxString();
|
||||||
else
|
else
|
||||||
return wxString( src.begin(), src.begin()+pos );
|
return wxString(src.begin(), src.begin() + pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// Launches the specified file according to its mime type
|
// Launches the specified file according to its mime type
|
||||||
//
|
//
|
||||||
void pxLaunch( const wxString& filename )
|
void pxLaunch(const wxString &filename)
|
||||||
{
|
{
|
||||||
wxLaunchDefaultBrowser( filename );
|
wxLaunchDefaultBrowser(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pxLaunch(const char *filename)
|
void pxLaunch(const char *filename)
|
||||||
{
|
{
|
||||||
pxLaunch( fromUTF8(filename) );
|
pxLaunch(fromUTF8(filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
@ -209,12 +212,12 @@ void pxLaunch(const char *filename)
|
||||||
// bypasses wxWidgets internal filename checking, which can end up launching things
|
// bypasses wxWidgets internal filename checking, which can end up launching things
|
||||||
// through browser more often than desired.
|
// through browser more often than desired.
|
||||||
//
|
//
|
||||||
void pxExplore( const wxString& path )
|
void pxExplore(const wxString &path)
|
||||||
{
|
{
|
||||||
wxLaunchDefaultBrowser( !path.Contains( L"://") ? L"file://" + path : path );
|
wxLaunchDefaultBrowser(!path.Contains(L"://") ? L"file://" + path : path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pxExplore(const char *path)
|
void pxExplore(const char *path)
|
||||||
{
|
{
|
||||||
pxExplore( fromUTF8(path) );
|
pxExplore(fromUTF8(path));
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,118 +23,125 @@
|
||||||
|
|
||||||
namespace Perf
|
namespace Perf
|
||||||
{
|
{
|
||||||
// Warning object aren't thread safe
|
// Warning object aren't thread safe
|
||||||
InfoVector any("");
|
InfoVector any("");
|
||||||
InfoVector ee("EE");
|
InfoVector ee("EE");
|
||||||
InfoVector iop("IOP");
|
InfoVector iop("IOP");
|
||||||
InfoVector vu("VU");
|
InfoVector vu("VU");
|
||||||
|
|
||||||
// Perf is only supported on linux
|
// Perf is only supported on linux
|
||||||
#if defined(__linux__) && defined(ProfileWithPerf)
|
#if defined(__linux__) && defined(ProfileWithPerf)
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Implementation of the Info object
|
// Implementation of the Info object
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
Info::Info(uptr x86, u32 size, const char* symbol) : m_x86(x86), m_size(size), m_dynamic(false)
|
Info::Info(uptr x86, u32 size, const char *symbol)
|
||||||
{
|
: m_x86(x86)
|
||||||
strncpy(m_symbol, symbol, sizeof(m_symbol));
|
, m_size(size)
|
||||||
}
|
, m_dynamic(false)
|
||||||
|
{
|
||||||
|
strncpy(m_symbol, symbol, sizeof(m_symbol));
|
||||||
|
}
|
||||||
|
|
||||||
Info::Info(uptr x86, u32 size, const char* symbol, u32 pc) : m_x86(x86), m_size(size), m_dynamic(true)
|
Info::Info(uptr x86, u32 size, const char *symbol, u32 pc)
|
||||||
{
|
: m_x86(x86)
|
||||||
snprintf(m_symbol, sizeof(m_symbol), "%s_0x%08x", symbol, pc);
|
, m_size(size)
|
||||||
}
|
, m_dynamic(true)
|
||||||
|
{
|
||||||
|
snprintf(m_symbol, sizeof(m_symbol), "%s_0x%08x", symbol, pc);
|
||||||
|
}
|
||||||
|
|
||||||
void Info::Print(FILE* fp)
|
void Info::Print(FILE *fp)
|
||||||
{
|
{
|
||||||
fprintf(fp, "%x %x %s\n", m_x86, m_size, m_symbol);
|
fprintf(fp, "%x %x %s\n", m_x86, m_size, m_symbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Implementation of the InfoVector object
|
// Implementation of the InfoVector object
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
InfoVector::InfoVector(const char* prefix)
|
InfoVector::InfoVector(const char *prefix)
|
||||||
{
|
{
|
||||||
strncpy(m_prefix, prefix, sizeof(m_prefix));
|
strncpy(m_prefix, prefix, sizeof(m_prefix));
|
||||||
}
|
}
|
||||||
|
|
||||||
void InfoVector::print(FILE* fp)
|
void InfoVector::print(FILE *fp)
|
||||||
{
|
{
|
||||||
for(auto&& it : m_v) it.Print(fp);
|
for (auto &&it : m_v)
|
||||||
}
|
it.Print(fp);
|
||||||
|
}
|
||||||
|
|
||||||
void InfoVector::map(uptr x86, u32 size, const char* symbol)
|
void InfoVector::map(uptr x86, u32 size, const char *symbol)
|
||||||
{
|
{
|
||||||
// This function is typically used for dispatcher and recompiler.
|
// This function is typically used for dispatcher and recompiler.
|
||||||
// Dispatchers are on a page and must always be kept.
|
// Dispatchers are on a page and must always be kept.
|
||||||
// Recompilers are much bigger (TODO check VIF) and are only
|
// Recompilers are much bigger (TODO check VIF) and are only
|
||||||
// useful when MERGE_BLOCK_RESULT is defined
|
// useful when MERGE_BLOCK_RESULT is defined
|
||||||
|
|
||||||
#ifdef MERGE_BLOCK_RESULT
|
#ifdef MERGE_BLOCK_RESULT
|
||||||
m_v.emplace_back(x86, size, symbol);
|
m_v.emplace_back(x86, size, symbol);
|
||||||
#else
|
#else
|
||||||
if (size < 8 * _1kb) m_v.emplace_back(x86, size, symbol);
|
if (size < 8 * _1kb)
|
||||||
|
m_v.emplace_back(x86, size, symbol);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void InfoVector::map(uptr x86, u32 size, u32 pc)
|
||||||
|
{
|
||||||
|
#ifndef MERGE_BLOCK_RESULT
|
||||||
|
m_v.emplace_back(x86, size, m_prefix, pc);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void InfoVector::reset()
|
||||||
|
{
|
||||||
|
auto dynamic = std::remove_if(m_v.begin(), m_v.end(), [](Info i) { return i.m_dynamic; });
|
||||||
|
m_v.erase(dynamic, m_v.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Global function
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void dump()
|
||||||
|
{
|
||||||
|
char file[256];
|
||||||
|
snprintf(file, 250, "/tmp/perf-%d.map", getpid());
|
||||||
|
FILE *fp = fopen(file, "w");
|
||||||
|
|
||||||
|
any.print(fp);
|
||||||
|
ee.print(fp);
|
||||||
|
iop.print(fp);
|
||||||
|
vu.print(fp);
|
||||||
|
|
||||||
|
if (fp)
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_and_reset()
|
||||||
|
{
|
||||||
|
dump();
|
||||||
|
|
||||||
|
any.reset();
|
||||||
|
ee.reset();
|
||||||
|
iop.reset();
|
||||||
|
vu.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Dummy implementation
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
InfoVector::InfoVector(const char *prefix) {}
|
||||||
|
void InfoVector::map(uptr x86, u32 size, const char *symbol) {}
|
||||||
|
void InfoVector::map(uptr x86, u32 size, u32 pc) {}
|
||||||
|
void InfoVector::reset() {}
|
||||||
|
|
||||||
|
void dump() {}
|
||||||
|
void dump_and_reset() {}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
void InfoVector::map(uptr x86, u32 size, u32 pc)
|
|
||||||
{
|
|
||||||
#ifndef MERGE_BLOCK_RESULT
|
|
||||||
m_v.emplace_back(x86, size, m_prefix, pc);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void InfoVector::reset()
|
|
||||||
{
|
|
||||||
auto dynamic = std::remove_if(m_v.begin(), m_v.end(), [](Info i) { return i.m_dynamic; });
|
|
||||||
m_v.erase(dynamic, m_v.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Global function
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
void dump()
|
|
||||||
{
|
|
||||||
char file[256];
|
|
||||||
snprintf(file, 250, "/tmp/perf-%d.map", getpid());
|
|
||||||
FILE* fp = fopen(file, "w");
|
|
||||||
|
|
||||||
any.print(fp);
|
|
||||||
ee.print(fp);
|
|
||||||
iop.print(fp);
|
|
||||||
vu.print(fp);
|
|
||||||
|
|
||||||
if (fp)
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void dump_and_reset()
|
|
||||||
{
|
|
||||||
dump();
|
|
||||||
|
|
||||||
any.reset();
|
|
||||||
ee.reset();
|
|
||||||
iop.reset();
|
|
||||||
vu.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Dummy implementation
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
InfoVector::InfoVector(const char* prefix) {}
|
|
||||||
void InfoVector::map(uptr x86, u32 size, const char* symbol) {}
|
|
||||||
void InfoVector::map(uptr x86, u32 size, u32 pc) {}
|
|
||||||
void InfoVector::reset() {}
|
|
||||||
|
|
||||||
void dump() {}
|
|
||||||
void dump_and_reset() {}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,4 +28,3 @@
|
||||||
#include "General.h"
|
#include "General.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue