diff --git a/Source/Core/Common/Src/CommonFuncs.h b/Source/Core/Common/Src/CommonFuncs.h index fe369cd292..1d4bf5ee28 100644 --- a/Source/Core/Common/Src/CommonFuncs.h +++ b/Source/Core/Common/Src/CommonFuncs.h @@ -1,116 +1,116 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#ifndef COMMONFUNCS_H -#define COMMONFUNCS_H - -#ifdef _WIN32 -#define SLEEP(x) Sleep(x) -#else -#define SLEEP(x) usleep(x*1000) -#endif - -#ifndef _WIN32 - -#if defined __APPLE__ -char* strndup (char const *s, size_t n); -size_t strnlen(const char *s, size_t n); -#else -#include -#endif // APPLE - #include -// go to debugger mode - #define Crash() {asm ("int $3");} - #define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) -inline u32 _rotl(u32 x, int shift) { - shift &= 31; - if (!shift) return x; - return (x << shift) | (x >> (32 - shift)); -} - -inline u32 _rotr(u32 x, int shift) { - shift &= 31; - if (!shift) return x; - return (x >> shift) | (x << (32 - shift)); -} - #define SLEEP(x) usleep(x*1000) -#else // WIN32 -// Function Cross-Compatibility - #define strcasecmp _stricmp - #define strncasecmp _strnicmp - #define unlink _unlink - #define snprintf _snprintf -char* strndup (char const *s, size_t n); - -// 64 bit offsets for windows - #define fseek _fseeki64 - #define ftell _ftelli64 - #define atoll _atoi64 - #define stat64 _stat64 - #define SLEEP(x) Sleep(x) - - #if _M_IX86 - #define Crash() {__asm int 3} - #else -extern "C" { - __declspec(dllimport) void __stdcall DebugBreak(void); -} - #define Crash() {DebugBreak();} - #endif // M_IX86 -#endif // WIN32 ndef - -// Dolphin's min and max functions -#undef min -#undef max - -template -inline T min(const T& a, const T& b) {return a > b ? b : a;} -template -inline T max(const T& a, const T& b) {return a > b ? a : b;} - -// Generic function to get last error message. -// Call directly after the command or use the error num. -// This function might change the error code. -// Defined in Misc.cpp. -const char* GetLastErrorMsg(); - -namespace Common -{ -inline u8 swap8(u8 _data) {return _data;} - -#ifdef _WIN32 -inline u16 swap16(u16 _data) {return _byteswap_ushort(_data);} -inline u32 swap32(u32 _data) {return _byteswap_ulong (_data);} -inline u64 swap64(u64 _data) {return _byteswap_uint64(_data);} -#elif __linux__ -inline u16 swap16(u16 _data) {return bswap_16(_data);} -inline u32 swap32(u32 _data) {return bswap_32(_data);} -inline u64 swap64(u64 _data) {return bswap_64(_data);} -#else -// Slow generic implementation. -inline u16 swap16(u16 data) {return (data >> 8) | (data << 8);} -inline u32 swap32(u32 data) {return (swap16(data) << 16) | swap16(data >> 16);} -inline u64 swap64(u64 data) {return ((u64)swap32(data) << 32) | swap32(data >> 32);} -#endif - -inline u16 swap16(const u8* _pData) {return swap16(*(const u16*)_pData);} -inline u32 swap32(const u8* _pData) {return swap32(*(const u32*)_pData);} -inline u64 swap64(const u8* _pData) {return swap64(*(const u64*)_pData);} - -} // namespace Common - -#endif // COMMONFUNCS +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifndef COMMONFUNCS_H +#define COMMONFUNCS_H + +#ifdef _WIN32 +#define SLEEP(x) Sleep(x) +#else +#define SLEEP(x) usleep(x*1000) +#endif + +#ifndef _WIN32 + +#if defined __APPLE__ +char* strndup (char const *s, size_t n); +size_t strnlen(const char *s, size_t n); +#else +#include +#endif // APPLE + #include +// go to debugger mode + #define Crash() {asm ("int $3");} + #define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) +inline u32 _rotl(u32 x, int shift) { + shift &= 31; + if (!shift) return x; + return (x << shift) | (x >> (32 - shift)); +} + +inline u32 _rotr(u32 x, int shift) { + shift &= 31; + if (!shift) return x; + return (x >> shift) | (x << (32 - shift)); +} + #define SLEEP(x) usleep(x*1000) +#else // WIN32 +// Function Cross-Compatibility + #define strcasecmp _stricmp + #define strncasecmp _strnicmp + #define unlink _unlink + #define snprintf _snprintf +char* strndup (char const *s, size_t n); + +// 64 bit offsets for windows + #define fseek _fseeki64 + #define ftell _ftelli64 + #define atoll _atoi64 + #define stat64 _stat64 + #define SLEEP(x) Sleep(x) + + #if _M_IX86 + #define Crash() {__asm int 3} + #else +extern "C" { + __declspec(dllimport) void __stdcall DebugBreak(void); +} + #define Crash() {DebugBreak();} + #endif // M_IX86 +#endif // WIN32 ndef + +// Dolphin's min and max functions +#undef min +#undef max + +template +inline T min(const T& a, const T& b) {return a > b ? b : a;} +template +inline T max(const T& a, const T& b) {return a > b ? a : b;} + +// Generic function to get last error message. +// Call directly after the command or use the error num. +// This function might change the error code. +// Defined in Misc.cpp. +const char* GetLastErrorMsg(); + +namespace Common +{ +inline u8 swap8(u8 _data) {return _data;} + +#ifdef _WIN32 +inline u16 swap16(u16 _data) {return _byteswap_ushort(_data);} +inline u32 swap32(u32 _data) {return _byteswap_ulong (_data);} +inline u64 swap64(u64 _data) {return _byteswap_uint64(_data);} +#elif __linux__ +inline u16 swap16(u16 _data) {return bswap_16(_data);} +inline u32 swap32(u32 _data) {return bswap_32(_data);} +inline u64 swap64(u64 _data) {return bswap_64(_data);} +#else +// Slow generic implementation. +inline u16 swap16(u16 data) {return (data >> 8) | (data << 8);} +inline u32 swap32(u32 data) {return (swap16(data) << 16) | swap16(data >> 16);} +inline u64 swap64(u64 data) {return ((u64)swap32(data) << 32) | swap32(data >> 32);} +#endif + +inline u16 swap16(const u8* _pData) {return swap16(*(const u16*)_pData);} +inline u32 swap32(const u8* _pData) {return swap32(*(const u32*)_pData);} +inline u64 swap64(const u8* _pData) {return swap64(*(const u64*)_pData);} + +} // namespace Common + +#endif // COMMONFUNCS diff --git a/Source/Core/Common/Src/CommonPaths.h b/Source/Core/Common/Src/CommonPaths.h index 54e2b366dc..6f515383af 100644 --- a/Source/Core/Common/Src/CommonPaths.h +++ b/Source/Core/Common/Src/CommonPaths.h @@ -1,163 +1,163 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#ifndef COMMON_PATHS_H -#define COMMON_PATHS_H - -// Library suffix/prefix -#ifdef _WIN32 -#define PLUGIN_PREFIX "" -#define PLUGIN_SUFFIX ".dll" -#elif defined __APPLE__ -#define PLUGIN_PREFIX "lib" -#define PLUGIN_SUFFIX ".dylib" -#else -#define PLUGIN_PREFIX "lib" -#define PLUGIN_SUFFIX ".so" -#endif - -// Directory seperators, do we need this? -#define DIR_SEP "/" -#define DIR_SEP_CHR '/' - -#if defined __APPLE__ -#define PLUGINS_DIR "Contents/PlugIns" -#else -#define PLUGINS_DIR "Plugins" -#endif -#define ROOT_DIR "." -#define USERDATA_DIR "User" -#define SYSDATA_DIR "Sys" - -// Where data directory is -#ifdef _WIN32 -#define DOLPHIN_DATA_DIR "Dolphin" -#elif defined __APPLE__ -#define DOLPHIN_DATA_DIR "Library/Application Support/Dolphin" -#else -#define DOLPHIN_DATA_DIR ".dolphin" -#endif - -// Dirs in both User and Sys -#define EUR_DIR "EUR" -#define USA_DIR "USA" -#define JAP_DIR "JAP" - -// Dirs in User -#define GC_USER_DIR "GC" -#define WII_USER_DIR "Wii" -#define WII_SYSCONF_DIR "shared2/sys" -#define CONFIG_DIR "Config" -#define GAMECONFIG_DIR "GameConfig" -#define MAPS_DIR "Maps" -#define CACHE_DIR "Cache" -#define STATESAVES_DIR "StateSaves" -#define SCREENSHOTS_DIR "ScreenShots" -#define DUMP_DIR "Dump" -#define LOGS_DIR "Logs" -#define MAIL_LOGS_DIR "Mail" - -// Dirs in Sys -#define GC_SYS_DIR "GC" -#define WII_SYS_DIR "Wii" - -// Filenames -#define DOLPHIN_CONFIG "Dolphin.ini" -#define DEBUGGER_CONFIG "Debugger.ini" -#define LOGGER_CONFIG "Logger.ini" -#define TOTALDB "totaldb.dsy" - -#define DEFAULT_GFX_PLUGIN PLUGIN_PREFIX "Plugin_VideoOGL" PLUGIN_SUFFIX -#define DEFAULT_DSP_PLUGIN PLUGIN_PREFIX "Plugin_DSP_HLE" PLUGIN_SUFFIX -#define DEFAULT_PAD_PLUGIN PLUGIN_PREFIX "Plugin_PadSimple" PLUGIN_SUFFIX -#define DEFAULT_WIIMOTE_PLUGIN PLUGIN_PREFIX "Plugin_Wiimote" PLUGIN_SUFFIX - -#define FONT_ANSI "font_ansi.bin" -#define FONT_SJIS "font_sjis.bin" - -#define DSP_ROM "dsp_rom.bin" -#define DSP_COEF "dsp_coef.bin" - -#define GC_IPL "IPL.bin" -#define GC_SRAM "SRAM.raw" -#define GC_MEMCARDA "MemoryCardA" -#define GC_MEMCARDB "MemoryCardB" - -#define WII_EUR_SETTING "setting-eur.txt" -#define WII_USA_SETTING "setting-usa.txt" -#define WII_JAP_SETTING "setting-jpn.txt" -#define WII_SYSCONF "SYSCONF" - -#define MEMORY_DUMP_FILE "mainram.dump" - -// Shorts - dirs -// User dirs -#define FULL_USERDATA_DIR ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP - -#define FULL_GC_USER_DIR FULL_USERDATA_DIR GC_USER_DIR DIR_SEP -//#define GC_USER_EUR_DIR FULL_GC_USER_DIR EUR_DIR -//#define GC_USER_USA_DIR FULL_GC_USER_DIR USA_DIR -//#define GC_USER_JAP_DIR FULL_GC_USER_DIR JAP_DIR - -#define FULL_WII_USER_DIR FULL_USERDATA_DIR WII_USER_DIR DIR_SEP -#define FULL_WII_ROOT_DIR FULL_USERDATA_DIR WII_USER_DIR // This is the "root" for Wii fs, so that it may be used with created devices - -#define FULL_GAMECONFIG_DIR FULL_USERDATA_DIR GAMECONFIG_DIR DIR_SEP -#define FULL_CONFIG_DIR FULL_USERDATA_DIR CONFIG_DIR DIR_SEP -#define FULL_CACHE_DIR FULL_USERDATA_DIR CACHE_DIR DIR_SEP -#define FULL_STATESAVES_DIR FULL_USERDATA_DIR STATESAVES_DIR DIR_SEP -#define FULL_SCREENSHOTS_DIR FULL_USERDATA_DIR SCREENSHOTS_DIR DIR_SEP -#define FULL_DUMP_DIR FULL_USERDATA_DIR DUMP_DIR DIR_SEP -#define FULL_LOGS_DIR FULL_USERDATA_DIR LOGS_DIR DIR_SEP -#define FULL_MAIL_LOGS_DIR FULL_LOGS_DIR MAIL_LOGS_DIR DIR_SEP -#define FULL_MAPS_DIR FULL_USERDATA_DIR MAPS_DIR DIR_SEP - -// Sys dirs -#define FULL_SYSDATA_DIR ROOT_DIR DIR_SEP SYSDATA_DIR DIR_SEP - -#define FULL_GC_SYS_DIR FULL_SYSDATA_DIR GC_SYS_DIR DIR_SEP -//#define GC_SYS_EUR_DIR FULL_GC_SYS_DIR EUR_DIR -//#define GC_SYS_USA_DIR FULL_GC_SYS_DIR USA_DIR -//#define GC_SYS_JAP_DIR FULL_GC_SYS_DIR JAP_DIR - -#define FULL_WII_SYS_DIR FULL_SYSDATA_DIR WII_SYS_DIR DIR_SEP - -// Shorts - files -// User files -#define CONFIG_FILE FULL_CONFIG_DIR DOLPHIN_CONFIG -#define DEBUGGER_CONFIG_FILE FULL_CONFIG_DIR DEBUGGER_CONFIG -#define LOGGER_CONFIG_FILE FULL_CONFIG_DIR LOGGER_CONFIG - -#define TOTALDB_FILE FULL_SYSDATA_DIR TOTALDB -#define MAINRAM_DUMP_FILE FULL_DUMP_DIR MEMORY_DUMP_FILE -#define GC_SRAM_FILE FULL_USERDATA_DIR GC_USER_DIR DIR_SEP GC_SRAM - -// Sys files -#define FONT_ANSI_FILE FULL_GC_SYS_DIR FONT_ANSI -#define FONT_SJIS_FILE FULL_GC_SYS_DIR FONT_SJIS - -#define DSP_ROM_FILE FULL_GC_SYS_DIR DSP_ROM -#define DSP_COEF_FILE FULL_GC_SYS_DIR DSP_COEF - -#define WII_EUR_SETTING_FILE FULL_WII_SYS_DIR WII_EUR_SETTING -#define WII_USA_SETTING_FILE FULL_WII_SYS_DIR WII_USA_SETTING -#define WII_JAP_SETTING_FILE FULL_WII_SYS_DIR WII_JAP_SETTING -#define WII_SYSCONF_FILE FULL_WII_USER_DIR WII_SYSCONF_DIR DIR_SEP WII_SYSCONF - -#define FULL_WII_MENU_DIR FULL_WII_USER_DIR "title" DIR_SEP "00000001" DIR_SEP "00000002" DIR_SEP "content" - -#endif // COMMON_PATHS_H +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifndef COMMON_PATHS_H +#define COMMON_PATHS_H + +// Library suffix/prefix +#ifdef _WIN32 +#define PLUGIN_PREFIX "" +#define PLUGIN_SUFFIX ".dll" +#elif defined __APPLE__ +#define PLUGIN_PREFIX "lib" +#define PLUGIN_SUFFIX ".dylib" +#else +#define PLUGIN_PREFIX "lib" +#define PLUGIN_SUFFIX ".so" +#endif + +// Directory seperators, do we need this? +#define DIR_SEP "/" +#define DIR_SEP_CHR '/' + +#if defined __APPLE__ +#define PLUGINS_DIR "Contents/PlugIns" +#else +#define PLUGINS_DIR "Plugins" +#endif +#define ROOT_DIR "." +#define USERDATA_DIR "User" +#define SYSDATA_DIR "Sys" + +// Where data directory is +#ifdef _WIN32 +#define DOLPHIN_DATA_DIR "Dolphin" +#elif defined __APPLE__ +#define DOLPHIN_DATA_DIR "Library/Application Support/Dolphin" +#else +#define DOLPHIN_DATA_DIR ".dolphin" +#endif + +// Dirs in both User and Sys +#define EUR_DIR "EUR" +#define USA_DIR "USA" +#define JAP_DIR "JAP" + +// Dirs in User +#define GC_USER_DIR "GC" +#define WII_USER_DIR "Wii" +#define WII_SYSCONF_DIR "shared2/sys" +#define CONFIG_DIR "Config" +#define GAMECONFIG_DIR "GameConfig" +#define MAPS_DIR "Maps" +#define CACHE_DIR "Cache" +#define STATESAVES_DIR "StateSaves" +#define SCREENSHOTS_DIR "ScreenShots" +#define DUMP_DIR "Dump" +#define LOGS_DIR "Logs" +#define MAIL_LOGS_DIR "Mail" + +// Dirs in Sys +#define GC_SYS_DIR "GC" +#define WII_SYS_DIR "Wii" + +// Filenames +#define DOLPHIN_CONFIG "Dolphin.ini" +#define DEBUGGER_CONFIG "Debugger.ini" +#define LOGGER_CONFIG "Logger.ini" +#define TOTALDB "totaldb.dsy" + +#define DEFAULT_GFX_PLUGIN PLUGIN_PREFIX "Plugin_VideoOGL" PLUGIN_SUFFIX +#define DEFAULT_DSP_PLUGIN PLUGIN_PREFIX "Plugin_DSP_HLE" PLUGIN_SUFFIX +#define DEFAULT_PAD_PLUGIN PLUGIN_PREFIX "Plugin_PadSimple" PLUGIN_SUFFIX +#define DEFAULT_WIIMOTE_PLUGIN PLUGIN_PREFIX "Plugin_Wiimote" PLUGIN_SUFFIX + +#define FONT_ANSI "font_ansi.bin" +#define FONT_SJIS "font_sjis.bin" + +#define DSP_ROM "dsp_rom.bin" +#define DSP_COEF "dsp_coef.bin" + +#define GC_IPL "IPL.bin" +#define GC_SRAM "SRAM.raw" +#define GC_MEMCARDA "MemoryCardA" +#define GC_MEMCARDB "MemoryCardB" + +#define WII_EUR_SETTING "setting-eur.txt" +#define WII_USA_SETTING "setting-usa.txt" +#define WII_JAP_SETTING "setting-jpn.txt" +#define WII_SYSCONF "SYSCONF" + +#define MEMORY_DUMP_FILE "mainram.dump" + +// Shorts - dirs +// User dirs +#define FULL_USERDATA_DIR ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP + +#define FULL_GC_USER_DIR FULL_USERDATA_DIR GC_USER_DIR DIR_SEP +//#define GC_USER_EUR_DIR FULL_GC_USER_DIR EUR_DIR +//#define GC_USER_USA_DIR FULL_GC_USER_DIR USA_DIR +//#define GC_USER_JAP_DIR FULL_GC_USER_DIR JAP_DIR + +#define FULL_WII_USER_DIR FULL_USERDATA_DIR WII_USER_DIR DIR_SEP +#define FULL_WII_ROOT_DIR FULL_USERDATA_DIR WII_USER_DIR // This is the "root" for Wii fs, so that it may be used with created devices + +#define FULL_GAMECONFIG_DIR FULL_USERDATA_DIR GAMECONFIG_DIR DIR_SEP +#define FULL_CONFIG_DIR FULL_USERDATA_DIR CONFIG_DIR DIR_SEP +#define FULL_CACHE_DIR FULL_USERDATA_DIR CACHE_DIR DIR_SEP +#define FULL_STATESAVES_DIR FULL_USERDATA_DIR STATESAVES_DIR DIR_SEP +#define FULL_SCREENSHOTS_DIR FULL_USERDATA_DIR SCREENSHOTS_DIR DIR_SEP +#define FULL_DUMP_DIR FULL_USERDATA_DIR DUMP_DIR DIR_SEP +#define FULL_LOGS_DIR FULL_USERDATA_DIR LOGS_DIR DIR_SEP +#define FULL_MAIL_LOGS_DIR FULL_LOGS_DIR MAIL_LOGS_DIR DIR_SEP +#define FULL_MAPS_DIR FULL_USERDATA_DIR MAPS_DIR DIR_SEP + +// Sys dirs +#define FULL_SYSDATA_DIR ROOT_DIR DIR_SEP SYSDATA_DIR DIR_SEP + +#define FULL_GC_SYS_DIR FULL_SYSDATA_DIR GC_SYS_DIR DIR_SEP +//#define GC_SYS_EUR_DIR FULL_GC_SYS_DIR EUR_DIR +//#define GC_SYS_USA_DIR FULL_GC_SYS_DIR USA_DIR +//#define GC_SYS_JAP_DIR FULL_GC_SYS_DIR JAP_DIR + +#define FULL_WII_SYS_DIR FULL_SYSDATA_DIR WII_SYS_DIR DIR_SEP + +// Shorts - files +// User files +#define CONFIG_FILE FULL_CONFIG_DIR DOLPHIN_CONFIG +#define DEBUGGER_CONFIG_FILE FULL_CONFIG_DIR DEBUGGER_CONFIG +#define LOGGER_CONFIG_FILE FULL_CONFIG_DIR LOGGER_CONFIG + +#define TOTALDB_FILE FULL_SYSDATA_DIR TOTALDB +#define MAINRAM_DUMP_FILE FULL_DUMP_DIR MEMORY_DUMP_FILE +#define GC_SRAM_FILE FULL_USERDATA_DIR GC_USER_DIR DIR_SEP GC_SRAM + +// Sys files +#define FONT_ANSI_FILE FULL_GC_SYS_DIR FONT_ANSI +#define FONT_SJIS_FILE FULL_GC_SYS_DIR FONT_SJIS + +#define DSP_ROM_FILE FULL_GC_SYS_DIR DSP_ROM +#define DSP_COEF_FILE FULL_GC_SYS_DIR DSP_COEF + +#define WII_EUR_SETTING_FILE FULL_WII_SYS_DIR WII_EUR_SETTING +#define WII_USA_SETTING_FILE FULL_WII_SYS_DIR WII_USA_SETTING +#define WII_JAP_SETTING_FILE FULL_WII_SYS_DIR WII_JAP_SETTING +#define WII_SYSCONF_FILE FULL_WII_USER_DIR WII_SYSCONF_DIR DIR_SEP WII_SYSCONF + +#define FULL_WII_MENU_DIR FULL_WII_USER_DIR "title" DIR_SEP "00000001" DIR_SEP "00000002" DIR_SEP "content" + +#endif // COMMON_PATHS_H diff --git a/Source/Core/Common/Src/CommonTypes.h b/Source/Core/Common/Src/CommonTypes.h index 134db4afeb..769640c832 100644 --- a/Source/Core/Common/Src/CommonTypes.h +++ b/Source/Core/Common/Src/CommonTypes.h @@ -1,58 +1,58 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - - -// This header contains type definitions that are shared between the Dolphin -// core and the plugin specs. Any definitions that are only used by the core -// should be placed in "Common.h" instead. - -#ifndef _COMMONTYPES_H -#define _COMMONTYPES_H - -#ifdef _WIN32 - -#include - -typedef unsigned __int8 u8; -typedef unsigned __int16 u16; -typedef unsigned __int32 u32; -typedef unsigned __int64 u64; - -typedef signed __int8 s8; -typedef signed __int16 s16; -typedef signed __int32 s32; -typedef signed __int64 s64; - -#else - -typedef unsigned char u8; -typedef unsigned short u16; -typedef unsigned int u32; -typedef unsigned long long u64; - -typedef char s8; -typedef short s16; -typedef int s32; -typedef long long s64; - -// For using windows lock code -#define TCHAR char -#define LONG int - -#endif // _WIN32 - -#endif // _COMMONTYPES_H +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + + +// This header contains type definitions that are shared between the Dolphin +// core and the plugin specs. Any definitions that are only used by the core +// should be placed in "Common.h" instead. + +#ifndef _COMMONTYPES_H +#define _COMMONTYPES_H + +#ifdef _WIN32 + +#include + +typedef unsigned __int8 u8; +typedef unsigned __int16 u16; +typedef unsigned __int32 u32; +typedef unsigned __int64 u64; + +typedef signed __int8 s8; +typedef signed __int16 s16; +typedef signed __int32 s32; +typedef signed __int64 s64; + +#else + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long long u64; + +typedef char s8; +typedef short s16; +typedef int s32; +typedef long long s64; + +// For using windows lock code +#define TCHAR char +#define LONG int + +#endif // _WIN32 + +#endif // _COMMONTYPES_H diff --git a/Source/Core/Common/Src/Log.h b/Source/Core/Common/Src/Log.h index b4790a5ba3..5de365a133 100644 --- a/Source/Core/Common/Src/Log.h +++ b/Source/Core/Common/Src/Log.h @@ -1,153 +1,153 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#ifndef _LOG_H -#define _LOG_H - -namespace LogTypes -{ - -enum LOG_TYPE { - ACTIONREPLAY, - AUDIO, - AUDIO_INTERFACE, - BOOT, - COMMANDPROCESSOR, - COMMON, - CONSOLE, - DISCIO, - DSPHLE, - DSPINTERFACE, - DVDINTERFACE, - DYNA_REC, - EXPANSIONINTERFACE, - GEKKO, - GPFIFO, - HLE, - MASTER_LOG, - MEMMAP, - OSREPORT, - PERIPHERALINTERFACE, - PIXELENGINE, - SERIALINTERFACE, - STREAMINGINTERFACE, - VIDEO, - VIDEOINTERFACE, - WII_IOB, - WII_IPC, - WII_IPC_DVD, - WII_IPC_ES, - WII_IPC_FILEIO, - WII_IPC_HLE, - WII_IPC_NET, - WII_IPC_SD, - WII_IPC_WIIMOTE, - - NUMBER_OF_LOGS // Must be last -}; - -enum LOG_LEVELS { - LERROR = 1, // Bad errors - that still don't deserve a PanicAlert. - LWARNING, // Something is suspicious. - LINFO, // General information. - LDEBUG, // Strictly for detailed debugging - might make things slow. -}; - -} // namespace - - -/* - FIXME: - - Debug_run() - run only in debug time - - Compile the log functions according to LOGLEVEL -*/ -#ifdef LOGGING -#define LOGLEVEL 4 //LogTypes::LDEBUG -#else -#ifndef LOGLEVEL -#define LOGLEVEL 2 //LogTypes::LWARNING -#endif // loglevel -#endif // logging - -#define ERROR_LOG(...) {} -#define WARN_LOG(...) {} -#define INFO_LOG(...) {} -#define DEBUG_LOG(...) {} - -extern void __Log(int logNumber, const char* text, ...); - -// Let the compiler optimize this out -#define GENERIC_LOG(t,v, ...) {if (v <= LOGLEVEL) __Log(t + (v)*100, __VA_ARGS__);} - -#if LOGLEVEL >= 1 //LogTypes::LERROR -#undef ERROR_LOG -#define ERROR_LOG(t,...) {GENERIC_LOG(LogTypes::t, LogTypes::LERROR, __VA_ARGS__)} -#endif // loglevel LERROR+ - -#if LOGLEVEL >= 2 //LogTypes::LWARNING -#undef WARN_LOG -#define WARN_LOG(t,...) {GENERIC_LOG(LogTypes::t, LogTypes::LWARNING, __VA_ARGS__)} -#endif // loglevel LWARNING+ - -#if LOGLEVEL >= 3 //LogTypes::LINFO -#undef INFO_LOG -#define INFO_LOG(t,...) {GENERIC_LOG(LogTypes::t, LogTypes::LINFO, __VA_ARGS__)} -#endif // loglevel LINFO+ - -#if LOGLEVEL >= 4 //LogTypes::LDEBUG -#undef DEBUG_LOG -#define DEBUG_LOG(t,...) {GENERIC_LOG(LogTypes::t, LogTypes::LDEBUG, __VA_ARGS__)} -#endif // loglevel LDEBUG+ - -#if LOGLEVEL >= 4 //LogTypes::LDEBUG -#define _dbg_assert_(_t_, _a_) \ - if (!(_a_)) {\ - ERROR_LOG(_t_, "Error...\n\n Line: %d\n File: %s\n Time: %s\n\nIgnore and continue?", \ - __LINE__, __FILE__, __TIME__); \ - if (!PanicYesNo("*** Assertion (see log)***\n")) {Crash();} \ - } -#define _dbg_assert_msg_(_t_, _a_, ...)\ - if (!(_a_)) {\ - ERROR_LOG(_t_, __VA_ARGS__); \ - if (!PanicYesNo(__VA_ARGS__)) {Crash();} \ - } -#define _dbg_update_() Host_UpdateLogDisplay(); - -#else // not debug -#define _dbg_clear_() -#define _dbg_update_() ; - -#ifndef _dbg_assert_ -#define _dbg_assert_(_t_, _a_) ; -#define _dbg_assert_msg_(_t_, _a_, _desc_, ...) ; -#endif // dbg_assert -#endif // LOGLEVEL LDEBUG - -#define _assert_(_a_) _dbg_assert_(MASTER_LOG, _a_) -#ifdef _WIN32 -#define _assert_msg_(_t_, _a_, _fmt_, ...) \ - if (!(_a_)) {\ - if (!PanicYesNo(_fmt_, __VA_ARGS__)) {Crash();} \ - } -#else // not win32 -#define _assert_msg_(_t_, _a_, _fmt_, ...) \ - if (!(_a_)) {\ - if (!PanicYesNo(_fmt_, ##__VA_ARGS__)) {Crash();} \ - } -#endif // WIN32 - -#endif // LOG_H +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifndef _LOG_H +#define _LOG_H + +namespace LogTypes +{ + +enum LOG_TYPE { + ACTIONREPLAY, + AUDIO, + AUDIO_INTERFACE, + BOOT, + COMMANDPROCESSOR, + COMMON, + CONSOLE, + DISCIO, + DSPHLE, + DSPINTERFACE, + DVDINTERFACE, + DYNA_REC, + EXPANSIONINTERFACE, + GEKKO, + GPFIFO, + HLE, + MASTER_LOG, + MEMMAP, + OSREPORT, + PERIPHERALINTERFACE, + PIXELENGINE, + SERIALINTERFACE, + STREAMINGINTERFACE, + VIDEO, + VIDEOINTERFACE, + WII_IOB, + WII_IPC, + WII_IPC_DVD, + WII_IPC_ES, + WII_IPC_FILEIO, + WII_IPC_HLE, + WII_IPC_NET, + WII_IPC_SD, + WII_IPC_WIIMOTE, + + NUMBER_OF_LOGS // Must be last +}; + +enum LOG_LEVELS { + LERROR = 1, // Bad errors - that still don't deserve a PanicAlert. + LWARNING, // Something is suspicious. + LINFO, // General information. + LDEBUG, // Strictly for detailed debugging - might make things slow. +}; + +} // namespace + + +/* + FIXME: + - Debug_run() - run only in debug time + - Compile the log functions according to LOGLEVEL +*/ +#ifdef LOGGING +#define LOGLEVEL 4 //LogTypes::LDEBUG +#else +#ifndef LOGLEVEL +#define LOGLEVEL 2 //LogTypes::LWARNING +#endif // loglevel +#endif // logging + +#define ERROR_LOG(...) {} +#define WARN_LOG(...) {} +#define INFO_LOG(...) {} +#define DEBUG_LOG(...) {} + +extern void __Log(int logNumber, const char* text, ...); + +// Let the compiler optimize this out +#define GENERIC_LOG(t,v, ...) {if (v <= LOGLEVEL) __Log(t + (v)*100, __VA_ARGS__);} + +#if LOGLEVEL >= 1 //LogTypes::LERROR +#undef ERROR_LOG +#define ERROR_LOG(t,...) {GENERIC_LOG(LogTypes::t, LogTypes::LERROR, __VA_ARGS__)} +#endif // loglevel LERROR+ + +#if LOGLEVEL >= 2 //LogTypes::LWARNING +#undef WARN_LOG +#define WARN_LOG(t,...) {GENERIC_LOG(LogTypes::t, LogTypes::LWARNING, __VA_ARGS__)} +#endif // loglevel LWARNING+ + +#if LOGLEVEL >= 3 //LogTypes::LINFO +#undef INFO_LOG +#define INFO_LOG(t,...) {GENERIC_LOG(LogTypes::t, LogTypes::LINFO, __VA_ARGS__)} +#endif // loglevel LINFO+ + +#if LOGLEVEL >= 4 //LogTypes::LDEBUG +#undef DEBUG_LOG +#define DEBUG_LOG(t,...) {GENERIC_LOG(LogTypes::t, LogTypes::LDEBUG, __VA_ARGS__)} +#endif // loglevel LDEBUG+ + +#if LOGLEVEL >= 4 //LogTypes::LDEBUG +#define _dbg_assert_(_t_, _a_) \ + if (!(_a_)) {\ + ERROR_LOG(_t_, "Error...\n\n Line: %d\n File: %s\n Time: %s\n\nIgnore and continue?", \ + __LINE__, __FILE__, __TIME__); \ + if (!PanicYesNo("*** Assertion (see log)***\n")) {Crash();} \ + } +#define _dbg_assert_msg_(_t_, _a_, ...)\ + if (!(_a_)) {\ + ERROR_LOG(_t_, __VA_ARGS__); \ + if (!PanicYesNo(__VA_ARGS__)) {Crash();} \ + } +#define _dbg_update_() Host_UpdateLogDisplay(); + +#else // not debug +#define _dbg_clear_() +#define _dbg_update_() ; + +#ifndef _dbg_assert_ +#define _dbg_assert_(_t_, _a_) ; +#define _dbg_assert_msg_(_t_, _a_, _desc_, ...) ; +#endif // dbg_assert +#endif // LOGLEVEL LDEBUG + +#define _assert_(_a_) _dbg_assert_(MASTER_LOG, _a_) +#ifdef _WIN32 +#define _assert_msg_(_t_, _a_, _fmt_, ...) \ + if (!(_a_)) {\ + if (!PanicYesNo(_fmt_, __VA_ARGS__)) {Crash();} \ + } +#else // not win32 +#define _assert_msg_(_t_, _a_, _fmt_, ...) \ + if (!(_a_)) {\ + if (!PanicYesNo(_fmt_, ##__VA_ARGS__)) {Crash();} \ + } +#endif // WIN32 + +#endif // LOG_H diff --git a/Source/Core/Common/Src/Misc.cpp b/Source/Core/Common/Src/Misc.cpp index 40b7623ba5..15f79fe700 100644 --- a/Source/Core/Common/Src/Misc.cpp +++ b/Source/Core/Common/Src/Misc.cpp @@ -1,60 +1,60 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "Common.h" - -// Generic function to get last error message. -// Call directly after the command or use the error num. -// This function might change the error code. -const char *GetLastErrorMsg() -{ - // FIXME : not thread safe. - // Caused by sloppy use in logging in FileUtil.cpp, primarily. What to do, what to do ... - static char errStr[255] = {0}; -#ifdef _WIN32 - DWORD dw = GetLastError(); - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dw, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) errStr, 254, NULL ); -#else - // Thread safe (XSI-compliant) - strerror_r(errno, errStr, 255); -#endif - return errStr; -} - -#ifdef __APPLE__ -// strlen with cropping after size n -size_t strnlen(const char *s, size_t n) -{ - const char *p = (const char *)memchr(s, 0, n); - return(p ? p-s : n); -} -#endif - -// strdup with cropping after size n -char* strndup(char const *s, size_t n) -{ - size_t len = strnlen(s, n); - char *dup = (char *)malloc(len + 1); - - if (dup == NULL) - return NULL; - - dup[len] = '\0'; - return (char *)memcpy(dup, s, len); -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Common.h" + +// Generic function to get last error message. +// Call directly after the command or use the error num. +// This function might change the error code. +const char *GetLastErrorMsg() +{ + // FIXME : not thread safe. + // Caused by sloppy use in logging in FileUtil.cpp, primarily. What to do, what to do ... + static char errStr[255] = {0}; +#ifdef _WIN32 + DWORD dw = GetLastError(); + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dw, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) errStr, 254, NULL ); +#else + // Thread safe (XSI-compliant) + strerror_r(errno, errStr, 255); +#endif + return errStr; +} + +#ifdef __APPLE__ +// strlen with cropping after size n +size_t strnlen(const char *s, size_t n) +{ + const char *p = (const char *)memchr(s, 0, n); + return(p ? p-s : n); +} +#endif + +// strdup with cropping after size n +char* strndup(char const *s, size_t n) +{ + size_t len = strnlen(s, n); + char *dup = (char *)malloc(len + 1); + + if (dup == NULL) + return NULL; + + dup[len] = '\0'; + return (char *)memcpy(dup, s, len); +} diff --git a/Source/Core/Common/Src/MsgHandler.h b/Source/Core/Common/Src/MsgHandler.h index 9ab9058bf9..579ba05c16 100644 --- a/Source/Core/Common/Src/MsgHandler.h +++ b/Source/Core/Common/Src/MsgHandler.h @@ -1,45 +1,45 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#ifndef MSGHANDLER_H -#define MSGHANDLER_H -// Message alerts -enum MSG_TYPE -{ - INFORMATION, - QUESTION, - WARNING, -}; - -typedef bool (*MsgAlertHandler)(const char* caption, const char* text, - bool yes_no, int Style); -void RegisterMsgAlertHandler(MsgAlertHandler handler); -extern bool MsgAlert(const char* caption, bool yes_no, int Style, const char* format, ...); - -#ifdef _WIN32 - #define SuccessAlert(format, ...) MsgAlert("Information", false, INFORMATION, format, __VA_ARGS__) - #define PanicAlert(format, ...) MsgAlert("Warning", false, WARNING, format, __VA_ARGS__) - #define PanicYesNo(format, ...) MsgAlert("Warning", true, WARNING, format, __VA_ARGS__) - #define AskYesNo(format, ...) MsgAlert("Question", true, QUESTION, format, __VA_ARGS__) -#else - #define SuccessAlert(format, ...) MsgAlert("SUCCESS", false, INFORMATION, format, ##__VA_ARGS__) - #define PanicAlert(format, ...) MsgAlert("PANIC", false, WARNING, format, ##__VA_ARGS__) - #define PanicYesNo(format, ...) MsgAlert("PANIC", true, WARNING, format, ##__VA_ARGS__) - #define AskYesNo(format, ...) MsgAlert("ASK", true, QUESTION, format, ##__VA_ARGS__) -#endif - -#endif //MSGHANDLER +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#ifndef MSGHANDLER_H +#define MSGHANDLER_H +// Message alerts +enum MSG_TYPE +{ + INFORMATION, + QUESTION, + WARNING, +}; + +typedef bool (*MsgAlertHandler)(const char* caption, const char* text, + bool yes_no, int Style); +void RegisterMsgAlertHandler(MsgAlertHandler handler); +extern bool MsgAlert(const char* caption, bool yes_no, int Style, const char* format, ...); + +#ifdef _WIN32 + #define SuccessAlert(format, ...) MsgAlert("Information", false, INFORMATION, format, __VA_ARGS__) + #define PanicAlert(format, ...) MsgAlert("Warning", false, WARNING, format, __VA_ARGS__) + #define PanicYesNo(format, ...) MsgAlert("Warning", true, WARNING, format, __VA_ARGS__) + #define AskYesNo(format, ...) MsgAlert("Question", true, QUESTION, format, __VA_ARGS__) +#else + #define SuccessAlert(format, ...) MsgAlert("SUCCESS", false, INFORMATION, format, ##__VA_ARGS__) + #define PanicAlert(format, ...) MsgAlert("PANIC", false, WARNING, format, ##__VA_ARGS__) + #define PanicYesNo(format, ...) MsgAlert("PANIC", true, WARNING, format, ##__VA_ARGS__) + #define AskYesNo(format, ...) MsgAlert("ASK", true, QUESTION, format, ##__VA_ARGS__) +#endif + +#endif //MSGHANDLER diff --git a/Source/Core/Core/Src/HW/EXI_Channel.h b/Source/Core/Core/Src/HW/EXI_Channel.h index e28f59d82c..65792ea5b8 100644 --- a/Source/Core/Core/Src/HW/EXI_Channel.h +++ b/Source/Core/Core/Src/HW/EXI_Channel.h @@ -38,7 +38,7 @@ private: union UEXI_STATUS { u32 hex; - struct + struct _EXISTATUS { unsigned EXIINTMASK : 1; //31 unsigned EXIINT : 1; //30 @@ -60,7 +60,7 @@ private: union UEXI_CONTROL { u32 hex; - struct + struct _EXICONTROL { unsigned TSTART : 1; unsigned DMA : 1; diff --git a/Source/Core/Core/Src/HW/SI.cpp b/Source/Core/Core/Src/HW/SI.cpp index f36e3c84dc..1cd951383f 100644 --- a/Source/Core/Core/Src/HW/SI.cpp +++ b/Source/Core/Core/Src/HW/SI.cpp @@ -1,608 +1,608 @@ -// Copyright (C) 2003-2009 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "Common.h" -#include "ChunkFile.h" -#include "../ConfigManager.h" -#include "../CoreTiming.h" - -#include "PeripheralInterface.h" - -#include "SI.h" - -namespace SerialInterface -{ - -static int changeDevice; - -void RunSIBuffer(); -void UpdateInterrupts(); - -// SI Interrupt Types -enum SIInterruptType -{ - INT_RDSTINT = 0, - INT_TCINT = 1, -}; -static void GenerateSIInterrupt(SIInterruptType _SIInterrupt); - -// SI number of channels -enum -{ - NUMBER_OF_CHANNELS = 0x04 -}; - -// SI Internal Hardware Addresses -enum -{ - SI_CHANNEL_0_OUT = 0x00, - SI_CHANNEL_0_IN_HI = 0x04, - SI_CHANNEL_0_IN_LO = 0x08, - SI_CHANNEL_1_OUT = 0x0C, - SI_CHANNEL_1_IN_HI = 0x10, - SI_CHANNEL_1_IN_LO = 0x14, - SI_CHANNEL_2_OUT = 0x18, - SI_CHANNEL_2_IN_HI = 0x1C, - SI_CHANNEL_2_IN_LO = 0x20, - SI_CHANNEL_3_OUT = 0x24, - SI_CHANNEL_3_IN_HI = 0x28, - SI_CHANNEL_3_IN_LO = 0x2C, - SI_POLL = 0x30, - SI_COM_CSR = 0x34, - SI_STATUS_REG = 0x38, - SI_EXI_CLOCK_COUNT = 0x3C, -}; - -// SI Channel Output -union USIChannelOut -{ - u32 Hex; - struct - { - unsigned OUTPUT1 : 8; - unsigned OUTPUT0 : 8; - unsigned CMD : 8; - unsigned : 8; - }; -}; - -// SI Channel Input High u32 -union USIChannelIn_Hi -{ - u32 Hex; - struct - { - unsigned INPUT3 : 8; - unsigned INPUT2 : 8; - unsigned INPUT1 : 8; - unsigned INPUT0 : 6; - unsigned ERRLATCH : 1; // 0: no error 1: Error latched. Check SISR. - unsigned ERRSTAT : 1; // 0: no error 1: error on last transfer - }; -}; - -// SI Channel Input Low u32 -union USIChannelIn_Lo -{ - u32 Hex; - struct - { - unsigned INPUT7 : 8; - unsigned INPUT6 : 8; - unsigned INPUT5 : 8; - unsigned INPUT4 : 8; - }; -}; - -// SI Channel -struct SSIChannel -{ - USIChannelOut m_Out; - USIChannelIn_Hi m_InHi; - USIChannelIn_Lo m_InLo; - ISIDevice* m_pDevice; -}; - -// SI Poll: Controls how often a device is polled -union USIPoll -{ - u32 Hex; - struct - { - unsigned VBCPY3 : 1; // 1: write to output buffer only on vblank - unsigned VBCPY2 : 1; - unsigned VBCPY1 : 1; - unsigned VBCPY0 : 1; - unsigned EN3 : 1; // Enable polling of channel - unsigned EN2 : 1; // does not affect communication RAM transfers - unsigned EN1 : 1; - unsigned EN0 : 1; - unsigned Y : 10; // Polls per frame - unsigned X : 10; // Polls per X lines. begins at vsync, min 7, max depends on video mode - unsigned : 6; - }; -}; - -// SI Communication Control Status Register -union USIComCSR -{ - u32 Hex; - struct - { - unsigned TSTART : 1; // write: start transfer read: transfer status - unsigned CHANNEL : 2; // determines which SI channel will be used on the communication interface. - unsigned : 3; - unsigned CALLBEN : 1; // Callback enable - unsigned CMDEN : 1; // Command enable? - unsigned INLNGTH : 7; - unsigned : 1; - unsigned OUTLNGTH : 7; // Communication Channel Output Length in bytes - unsigned : 1; - unsigned CHANEN : 1; // Channel enable? - unsigned CHANNUM : 2; // Channel number? - unsigned RDSTINTMSK : 1; // Read Status Interrupt Status Mask - unsigned RDSTINT : 1; // Read Status Interrupt Status - unsigned COMERR : 1; // Communication Error (set 0) - unsigned TCINTMSK : 1; // Transfer Complete Interrupt Mask - unsigned TCINT : 1; // Transfer Complete Interrupt - }; - USIComCSR() {Hex = 0;} - USIComCSR(u32 _hex) {Hex = _hex;} -}; - -// SI Status Register -union USIStatusReg -{ - u32 Hex; +// Copyright (C) 2003-2009 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Common.h" +#include "ChunkFile.h" +#include "../ConfigManager.h" +#include "../CoreTiming.h" + +#include "PeripheralInterface.h" + +#include "SI.h" + +namespace SerialInterface +{ + +static int changeDevice; + +void RunSIBuffer(); +void UpdateInterrupts(); + +// SI Interrupt Types +enum SIInterruptType +{ + INT_RDSTINT = 0, + INT_TCINT = 1, +}; +static void GenerateSIInterrupt(SIInterruptType _SIInterrupt); + +// SI number of channels +enum +{ + NUMBER_OF_CHANNELS = 0x04 +}; + +// SI Internal Hardware Addresses +enum +{ + SI_CHANNEL_0_OUT = 0x00, + SI_CHANNEL_0_IN_HI = 0x04, + SI_CHANNEL_0_IN_LO = 0x08, + SI_CHANNEL_1_OUT = 0x0C, + SI_CHANNEL_1_IN_HI = 0x10, + SI_CHANNEL_1_IN_LO = 0x14, + SI_CHANNEL_2_OUT = 0x18, + SI_CHANNEL_2_IN_HI = 0x1C, + SI_CHANNEL_2_IN_LO = 0x20, + SI_CHANNEL_3_OUT = 0x24, + SI_CHANNEL_3_IN_HI = 0x28, + SI_CHANNEL_3_IN_LO = 0x2C, + SI_POLL = 0x30, + SI_COM_CSR = 0x34, + SI_STATUS_REG = 0x38, + SI_EXI_CLOCK_COUNT = 0x3C, +}; + +// SI Channel Output +union USIChannelOut +{ + u32 Hex; + struct + { + unsigned OUTPUT1 : 8; + unsigned OUTPUT0 : 8; + unsigned CMD : 8; + unsigned : 8; + }; +}; + +// SI Channel Input High u32 +union USIChannelIn_Hi +{ + u32 Hex; + struct + { + unsigned INPUT3 : 8; + unsigned INPUT2 : 8; + unsigned INPUT1 : 8; + unsigned INPUT0 : 6; + unsigned ERRLATCH : 1; // 0: no error 1: Error latched. Check SISR. + unsigned ERRSTAT : 1; // 0: no error 1: error on last transfer + }; +}; + +// SI Channel Input Low u32 +union USIChannelIn_Lo +{ + u32 Hex; + struct + { + unsigned INPUT7 : 8; + unsigned INPUT6 : 8; + unsigned INPUT5 : 8; + unsigned INPUT4 : 8; + }; +}; + +// SI Channel +struct SSIChannel +{ + USIChannelOut m_Out; + USIChannelIn_Hi m_InHi; + USIChannelIn_Lo m_InLo; + ISIDevice* m_pDevice; +}; + +// SI Poll: Controls how often a device is polled +union USIPoll +{ + u32 Hex; struct - { - unsigned UNRUN3 : 1; // (RWC) write 1: bit cleared read 1: main proc underrun error - unsigned OVRUN3 : 1; // (RWC) write 1: bit cleared read 1: overrun error - unsigned COLL3 : 1; // (RWC) write 1: bit cleared read 1: collision error - unsigned NOREP3 : 1; // (RWC) write 1: bit cleared read 1: response error - unsigned WRST3 : 1; // (R) 1: buffer channel0 not copied - unsigned RDST3 : 1; // (R) 1: new Data available - unsigned : 2; // 7:6 - unsigned UNRUN2 : 1; // (RWC) write 1: bit cleared read 1: main proc underrun error - unsigned OVRUN2 : 1; // (RWC) write 1: bit cleared read 1: overrun error - unsigned COLL2 : 1; // (RWC) write 1: bit cleared read 1: collision error - unsigned NOREP2 : 1; // (RWC) write 1: bit cleared read 1: response error - unsigned WRST2 : 1; // (R) 1: buffer channel0 not copied - unsigned RDST2 : 1; // (R) 1: new Data available - unsigned : 2; // 15:14 - unsigned UNRUN1 : 1; // (RWC) write 1: bit cleared read 1: main proc underrun error - unsigned OVRUN1 : 1; // (RWC) write 1: bit cleared read 1: overrun error - unsigned COLL1 : 1; // (RWC) write 1: bit cleared read 1: collision error - unsigned NOREP1 : 1; // (RWC) write 1: bit cleared read 1: response error - unsigned WRST1 : 1; // (R) 1: buffer channel0 not copied - unsigned RDST1 : 1; // (R) 1: new Data available - unsigned : 2; // 23:22 - unsigned UNRUN0 : 1; // (RWC) write 1: bit cleared read 1: main proc underrun error - unsigned OVRUN0 : 1; // (RWC) write 1: bit cleared read 1: overrun error - unsigned COLL0 : 1; // (RWC) write 1: bit cleared read 1: collision error - unsigned NOREP0 : 1; // (RWC) write 1: bit cleared read 1: response error - unsigned WRST0 : 1; // (R) 1: buffer channel0 not copied - unsigned RDST0 : 1; // (R) 1: new Data available - unsigned : 1; - unsigned WR : 1; // (RW) write 1 start copy, read 0 copy done - }; - USIStatusReg() {Hex = 0;} - USIStatusReg(u32 _hex) {Hex = _hex;} -}; - -// SI EXI Clock Count -union USIEXIClockCount -{ - u32 Hex; - struct - { - unsigned LOCK : 1; // 1: prevents CPU from setting EXI clock to 32MHz - unsigned : 30; - }; -}; - -// STATE_TO_SAVE -static SSIChannel g_Channel[NUMBER_OF_CHANNELS]; -static USIPoll g_Poll; -static USIComCSR g_ComCSR; -static USIStatusReg g_StatusReg; -static USIEXIClockCount g_EXIClockCount; -static u8 g_SIBuffer[128]; - -void DoState(PointerWrap &p) -{ - // p.DoArray(g_Channel); - p.Do(g_Poll); - p.Do(g_ComCSR); - p.Do(g_StatusReg); - p.Do(g_EXIClockCount); - p.Do(g_SIBuffer); -} - - -void Init() -{ - for (int i = 0; i < NUMBER_OF_CHANNELS; i++) - { - g_Channel[i].m_Out.Hex = 0; - g_Channel[i].m_InHi.Hex = 0; - g_Channel[i].m_InLo.Hex = 0; - - AddDevice(SConfig::GetInstance().m_SIDevice[i], i); - } - - g_Poll.Hex = 0; - g_ComCSR.Hex = 0; - g_StatusReg.Hex = 0; - g_EXIClockCount.Hex = 0; - memset(g_SIBuffer, 0xce, 128); // This could be the cause of "WII something" in GCController - - changeDevice = CoreTiming::RegisterEvent("ChangeSIDevice", ChangeDeviceCallback); -} - -void Shutdown() -{ - for (int i = 0; i < NUMBER_OF_CHANNELS; i++) - RemoveDevice(i); -} - -void Read32(u32& _uReturnValue, const u32 _iAddress) -{ - DEBUG_LOG(SERIALINTERFACE, "(r32): 0x%08x", _iAddress); - - // SIBuffer - if ((_iAddress >= 0xCC006480 && _iAddress < 0xCC006500) || - (_iAddress >= 0xCD006480 && _iAddress < 0xCD006500)) - { - _uReturnValue = *(u32*)&g_SIBuffer[_iAddress & 0x7F]; - return; - } - - // registers - switch (_iAddress & 0x3FF) - { - ////////////////////////////////////////////////////////////////////////// - // Channel 0 - ////////////////////////////////////////////////////////////////////////// - case SI_CHANNEL_0_OUT: - _uReturnValue = g_Channel[0].m_Out.Hex; - return; - - case SI_CHANNEL_0_IN_HI: - g_StatusReg.RDST0 = 0; - UpdateInterrupts(); - _uReturnValue = g_Channel[0].m_InHi.Hex; - return; - - case SI_CHANNEL_0_IN_LO: - g_StatusReg.RDST0 = 0; - UpdateInterrupts(); - _uReturnValue = g_Channel[0].m_InLo.Hex; - return; - - ////////////////////////////////////////////////////////////////////////// - // Channel 1 - ////////////////////////////////////////////////////////////////////////// - case SI_CHANNEL_1_OUT: - _uReturnValue = g_Channel[1].m_Out.Hex; - return; - - case SI_CHANNEL_1_IN_HI: - g_StatusReg.RDST1 = 0; - UpdateInterrupts(); - _uReturnValue = g_Channel[1].m_InHi.Hex; - return; - - case SI_CHANNEL_1_IN_LO: - g_StatusReg.RDST1 = 0; - UpdateInterrupts(); - _uReturnValue = g_Channel[1].m_InLo.Hex; - return; - - ////////////////////////////////////////////////////////////////////////// - // Channel 2 - ////////////////////////////////////////////////////////////////////////// - case SI_CHANNEL_2_OUT: - _uReturnValue = g_Channel[2].m_Out.Hex; - return; - - case SI_CHANNEL_2_IN_HI: - g_StatusReg.RDST2 = 0; - UpdateInterrupts(); - _uReturnValue = g_Channel[2].m_InHi.Hex; - return; - - case SI_CHANNEL_2_IN_LO: - g_StatusReg.RDST2 = 0; - UpdateInterrupts(); - _uReturnValue = g_Channel[2].m_InLo.Hex; - return; - - ////////////////////////////////////////////////////////////////////////// - // Channel 3 - ////////////////////////////////////////////////////////////////////////// - case SI_CHANNEL_3_OUT: - _uReturnValue = g_Channel[3].m_Out.Hex; - return; - - case SI_CHANNEL_3_IN_HI: - g_StatusReg.RDST3 = 0; - UpdateInterrupts(); - _uReturnValue = g_Channel[3].m_InHi.Hex; - return; - - case SI_CHANNEL_3_IN_LO: - g_StatusReg.RDST3 = 0; - UpdateInterrupts(); - _uReturnValue = g_Channel[3].m_InLo.Hex; - return; - - case SI_POLL: _uReturnValue = g_Poll.Hex; return; - case SI_COM_CSR: _uReturnValue = g_ComCSR.Hex; return; - case SI_STATUS_REG: _uReturnValue = g_StatusReg.Hex; return; - - case SI_EXI_CLOCK_COUNT: _uReturnValue = g_EXIClockCount.Hex; return; - - default: - INFO_LOG(SERIALINTERFACE, "(r32-unk): 0x%08x", _iAddress); - _dbg_assert_(SERIALINTERFACE,0); - break; - } - - // error - _uReturnValue = 0xdeadbeef; -} - -void Write32(const u32 _iValue, const u32 _iAddress) -{ - DEBUG_LOG(SERIALINTERFACE, "(w32): 0x%08x 0x%08x", _iValue,_iAddress); - - // SIBuffer - if ((_iAddress >= 0xCC006480 && _iAddress < 0xCC006500) || - (_iAddress >= 0xCD006480 && _iAddress < 0xCD006500)) - { - *(u32*)&g_SIBuffer[_iAddress & 0x7F] = _iValue; - return; - } - - // registers - switch (_iAddress & 0x3FF) - { - case SI_CHANNEL_0_OUT: g_Channel[0].m_Out.Hex = _iValue; break; - case SI_CHANNEL_0_IN_HI: g_Channel[0].m_InHi.Hex = _iValue; break; - case SI_CHANNEL_0_IN_LO: g_Channel[0].m_InLo.Hex = _iValue; break; - case SI_CHANNEL_1_OUT: g_Channel[1].m_Out.Hex = _iValue; break; - case SI_CHANNEL_1_IN_HI: g_Channel[1].m_InHi.Hex = _iValue; break; - case SI_CHANNEL_1_IN_LO: g_Channel[1].m_InLo.Hex = _iValue; break; - case SI_CHANNEL_2_OUT: g_Channel[2].m_Out.Hex = _iValue; break; - case SI_CHANNEL_2_IN_HI: g_Channel[2].m_InHi.Hex = _iValue; break; - case SI_CHANNEL_2_IN_LO: g_Channel[2].m_InLo.Hex = _iValue; break; - case SI_CHANNEL_3_OUT: g_Channel[3].m_Out.Hex = _iValue; break; - case SI_CHANNEL_3_IN_HI: g_Channel[3].m_InHi.Hex = _iValue; break; - case SI_CHANNEL_3_IN_LO: g_Channel[3].m_InLo.Hex = _iValue; break; - - case SI_POLL: - g_Poll.Hex = _iValue; - break; - - case SI_COM_CSR: - { - USIComCSR tmpComCSR(_iValue); - - g_ComCSR.CHANNEL = tmpComCSR.CHANNEL; - g_ComCSR.INLNGTH = tmpComCSR.INLNGTH; - g_ComCSR.OUTLNGTH = tmpComCSR.OUTLNGTH; - g_ComCSR.RDSTINTMSK = tmpComCSR.RDSTINTMSK; - g_ComCSR.TCINTMSK = tmpComCSR.TCINTMSK; - - g_ComCSR.COMERR = 0; - - if (tmpComCSR.RDSTINT) g_ComCSR.RDSTINT = 0; - if (tmpComCSR.TCINT) g_ComCSR.TCINT = 0; - - // be careful: run si-buffer after updating the INT flags - if (tmpComCSR.TSTART) RunSIBuffer(); - UpdateInterrupts(); - } - break; - - case SI_STATUS_REG: - { - USIStatusReg tmpStatus(_iValue); - - // clear bits ( if(tmp.bit) SISR.bit=0 ) - if (tmpStatus.NOREP0) g_StatusReg.NOREP0 = 0; - if (tmpStatus.COLL0) g_StatusReg.COLL0 = 0; - if (tmpStatus.OVRUN0) g_StatusReg.OVRUN0 = 0; - if (tmpStatus.UNRUN0) g_StatusReg.UNRUN0 = 0; - - if (tmpStatus.NOREP1) g_StatusReg.NOREP1 = 0; - if (tmpStatus.COLL1) g_StatusReg.COLL1 = 0; - if (tmpStatus.OVRUN1) g_StatusReg.OVRUN1 = 0; - if (tmpStatus.UNRUN1) g_StatusReg.UNRUN1 = 0; - - if (tmpStatus.NOREP2) g_StatusReg.NOREP2 = 0; - if (tmpStatus.COLL2) g_StatusReg.COLL2 = 0; - if (tmpStatus.OVRUN2) g_StatusReg.OVRUN2 = 0; - if (tmpStatus.UNRUN2) g_StatusReg.UNRUN2 = 0; - - if (tmpStatus.NOREP3) g_StatusReg.NOREP3 = 0; - if (tmpStatus.COLL3) g_StatusReg.COLL3 = 0; - if (tmpStatus.OVRUN3) g_StatusReg.OVRUN3 = 0; - if (tmpStatus.UNRUN3) g_StatusReg.UNRUN3 = 0; - - // send command to devices - if (tmpStatus.WR) - { - g_Channel[0].m_pDevice->SendCommand(g_Channel[0].m_Out.Hex); - g_Channel[1].m_pDevice->SendCommand(g_Channel[1].m_Out.Hex); - g_Channel[2].m_pDevice->SendCommand(g_Channel[2].m_Out.Hex); - g_Channel[3].m_pDevice->SendCommand(g_Channel[3].m_Out.Hex); - - g_StatusReg.WR = 0; - g_StatusReg.WRST0 = 0; - g_StatusReg.WRST1 = 0; - g_StatusReg.WRST2 = 0; - g_StatusReg.WRST3 = 0; - } - } - break; - - case SI_EXI_CLOCK_COUNT: - g_EXIClockCount.Hex = _iValue; - break; - - case 0x80: - INFO_LOG(SERIALINTERFACE, "WII something at 0xCD006480"); - break; - - default: - _dbg_assert_(SERIALINTERFACE,0); - break; - } -} - -void UpdateInterrupts() -{ - // check if we have to update the RDSTINT flag - if (g_StatusReg.RDST0 || g_StatusReg.RDST1 || - g_StatusReg.RDST2 || g_StatusReg.RDST3) - g_ComCSR.RDSTINT = 1; - else - g_ComCSR.RDSTINT = 0; - - // check if we have to generate an interrupt - if ((g_ComCSR.RDSTINT & g_ComCSR.RDSTINTMSK) || - (g_ComCSR.TCINT & g_ComCSR.TCINTMSK)) - { - CPeripheralInterface::SetInterrupt(CPeripheralInterface::INT_CAUSE_SI, true); - } - else - { - CPeripheralInterface::SetInterrupt(CPeripheralInterface::INT_CAUSE_SI, false); - } -} - -void GenerateSIInterrupt(SIInterruptType _SIInterrupt) -{ - switch(_SIInterrupt) - { - case INT_RDSTINT: g_ComCSR.RDSTINT = 1; break; - case INT_TCINT: g_ComCSR.TCINT = 1; break; - } - - UpdateInterrupts(); -} - -void RemoveDevice(int _iDeviceNumber) -{ - if (g_Channel[_iDeviceNumber].m_pDevice != NULL) - { - delete g_Channel[_iDeviceNumber].m_pDevice; - g_Channel[_iDeviceNumber].m_pDevice = NULL; - } -} - -void AddDevice(const TSIDevices _device, int _iDeviceNumber) -{ - //_dbg_assert_(SERIALINTERFACE, _iDeviceNumber < NUMBER_OF_CHANNELS); - - // delete the old device - RemoveDevice(_iDeviceNumber); - - // create the new one - g_Channel[_iDeviceNumber].m_pDevice = SIDevice_Create(_device, _iDeviceNumber); - _dbg_assert_(SERIALINTERFACE, g_Channel[_iDeviceNumber].m_pDevice != NULL); -} - -void ChangeDeviceCallback(u64 userdata, int cyclesLate) -{ - u8 channel = (u8)(userdata >> 32); - // doubt this matters... - g_Channel[channel].m_Out.Hex = 0; - g_Channel[channel].m_InHi.Hex = 0; - g_Channel[channel].m_InLo.Hex = 0; - - // raise the NO RESPONSE error - switch (channel) - { - case 0: - g_StatusReg.NOREP0 = 1; - break; - case 1: - g_StatusReg.NOREP1 = 1; - break; - case 2: - g_StatusReg.NOREP2 = 1; - break; - case 3: - g_StatusReg.NOREP3 = 1; - break; - } - - AddDevice((TSIDevices)(u32)userdata, channel); -} - -void ChangeDevice(TSIDevices device, int deviceNumber) -{ - // Called from GUI, so we need to make it thread safe. - // Let the hardware see no device for .5b cycles - CoreTiming::ScheduleEvent_Threadsafe(0, changeDevice, (SI_DUMMY | (u64)deviceNumber << 32)); - CoreTiming::ScheduleEvent_Threadsafe(500000000, changeDevice, (device | (u64)deviceNumber << 32)); -} - -void UpdateDevices() -{ - // Update channels - g_StatusReg.RDST0 = g_Channel[0].m_pDevice->GetData(g_Channel[0].m_InHi.Hex, g_Channel[0].m_InLo.Hex) ? 1 : 0; - g_StatusReg.RDST1 = g_Channel[1].m_pDevice->GetData(g_Channel[1].m_InHi.Hex, g_Channel[1].m_InLo.Hex) ? 1 : 0; - g_StatusReg.RDST2 = g_Channel[2].m_pDevice->GetData(g_Channel[2].m_InHi.Hex, g_Channel[2].m_InLo.Hex) ? 1 : 0; - g_StatusReg.RDST3 = g_Channel[3].m_pDevice->GetData(g_Channel[3].m_InHi.Hex, g_Channel[3].m_InLo.Hex) ? 1 : 0; - - // Update interrupts - UpdateInterrupts(); -} - -void RunSIBuffer() -{ - // Math inLength - int inLength = g_ComCSR.INLNGTH; - if (inLength == 0) - inLength = 128; - else - inLength++; - - // Math outLength - int outLength = g_ComCSR.OUTLNGTH; - if (outLength == 0) - outLength = 128; - else - outLength++; - -#if LOGLEVEL >= 3 - int numOutput = -#endif - g_Channel[g_ComCSR.CHANNEL].m_pDevice->RunBuffer(g_SIBuffer, inLength); - - INFO_LOG(SERIALINTERFACE, "RunSIBuffer (intLen: %i outLen: %i) (processed: %i)", inLength, outLength, numOutput); - - // Transfer completed - GenerateSIInterrupt(INT_TCINT); - g_ComCSR.TSTART = 0; -} - -} // end of namespace SerialInterface + { + unsigned VBCPY3 : 1; // 1: write to output buffer only on vblank + unsigned VBCPY2 : 1; + unsigned VBCPY1 : 1; + unsigned VBCPY0 : 1; + unsigned EN3 : 1; // Enable polling of channel + unsigned EN2 : 1; // does not affect communication RAM transfers + unsigned EN1 : 1; + unsigned EN0 : 1; + unsigned Y : 10; // Polls per frame + unsigned X : 10; // Polls per X lines. begins at vsync, min 7, max depends on video mode + unsigned : 6; + }; +}; + +// SI Communication Control Status Register +union USIComCSR +{ + u32 Hex; + struct + { + unsigned TSTART : 1; // write: start transfer read: transfer status + unsigned CHANNEL : 2; // determines which SI channel will be used on the communication interface. + unsigned : 3; + unsigned CALLBEN : 1; // Callback enable + unsigned CMDEN : 1; // Command enable? + unsigned INLNGTH : 7; + unsigned : 1; + unsigned OUTLNGTH : 7; // Communication Channel Output Length in bytes + unsigned : 1; + unsigned CHANEN : 1; // Channel enable? + unsigned CHANNUM : 2; // Channel number? + unsigned RDSTINTMSK : 1; // Read Status Interrupt Status Mask + unsigned RDSTINT : 1; // Read Status Interrupt Status + unsigned COMERR : 1; // Communication Error (set 0) + unsigned TCINTMSK : 1; // Transfer Complete Interrupt Mask + unsigned TCINT : 1; // Transfer Complete Interrupt + }; + USIComCSR() {Hex = 0;} + USIComCSR(u32 _hex) {Hex = _hex;} +}; + +// SI Status Register +union USIStatusReg +{ + u32 Hex; + struct + { + unsigned UNRUN3 : 1; // (RWC) write 1: bit cleared read 1: main proc underrun error + unsigned OVRUN3 : 1; // (RWC) write 1: bit cleared read 1: overrun error + unsigned COLL3 : 1; // (RWC) write 1: bit cleared read 1: collision error + unsigned NOREP3 : 1; // (RWC) write 1: bit cleared read 1: response error + unsigned WRST3 : 1; // (R) 1: buffer channel0 not copied + unsigned RDST3 : 1; // (R) 1: new Data available + unsigned : 2; // 7:6 + unsigned UNRUN2 : 1; // (RWC) write 1: bit cleared read 1: main proc underrun error + unsigned OVRUN2 : 1; // (RWC) write 1: bit cleared read 1: overrun error + unsigned COLL2 : 1; // (RWC) write 1: bit cleared read 1: collision error + unsigned NOREP2 : 1; // (RWC) write 1: bit cleared read 1: response error + unsigned WRST2 : 1; // (R) 1: buffer channel0 not copied + unsigned RDST2 : 1; // (R) 1: new Data available + unsigned : 2; // 15:14 + unsigned UNRUN1 : 1; // (RWC) write 1: bit cleared read 1: main proc underrun error + unsigned OVRUN1 : 1; // (RWC) write 1: bit cleared read 1: overrun error + unsigned COLL1 : 1; // (RWC) write 1: bit cleared read 1: collision error + unsigned NOREP1 : 1; // (RWC) write 1: bit cleared read 1: response error + unsigned WRST1 : 1; // (R) 1: buffer channel0 not copied + unsigned RDST1 : 1; // (R) 1: new Data available + unsigned : 2; // 23:22 + unsigned UNRUN0 : 1; // (RWC) write 1: bit cleared read 1: main proc underrun error + unsigned OVRUN0 : 1; // (RWC) write 1: bit cleared read 1: overrun error + unsigned COLL0 : 1; // (RWC) write 1: bit cleared read 1: collision error + unsigned NOREP0 : 1; // (RWC) write 1: bit cleared read 1: response error + unsigned WRST0 : 1; // (R) 1: buffer channel0 not copied + unsigned RDST0 : 1; // (R) 1: new Data available + unsigned : 1; + unsigned WR : 1; // (RW) write 1 start copy, read 0 copy done + }; + USIStatusReg() {Hex = 0;} + USIStatusReg(u32 _hex) {Hex = _hex;} +}; + +// SI EXI Clock Count +union USIEXIClockCount +{ + u32 Hex; + struct + { + unsigned LOCK : 1; // 1: prevents CPU from setting EXI clock to 32MHz + unsigned : 30; + }; +}; + +// STATE_TO_SAVE +static SSIChannel g_Channel[NUMBER_OF_CHANNELS]; +static USIPoll g_Poll; +static USIComCSR g_ComCSR; +static USIStatusReg g_StatusReg; +static USIEXIClockCount g_EXIClockCount; +static u8 g_SIBuffer[128]; + +void DoState(PointerWrap &p) +{ + // p.DoArray(g_Channel); + p.Do(g_Poll); + p.Do(g_ComCSR); + p.Do(g_StatusReg); + p.Do(g_EXIClockCount); + p.Do(g_SIBuffer); +} + + +void Init() +{ + for (int i = 0; i < NUMBER_OF_CHANNELS; i++) + { + g_Channel[i].m_Out.Hex = 0; + g_Channel[i].m_InHi.Hex = 0; + g_Channel[i].m_InLo.Hex = 0; + + AddDevice(SConfig::GetInstance().m_SIDevice[i], i); + } + + g_Poll.Hex = 0; + g_ComCSR.Hex = 0; + g_StatusReg.Hex = 0; + g_EXIClockCount.Hex = 0; + memset(g_SIBuffer, 0xce, 128); // This could be the cause of "WII something" in GCController + + changeDevice = CoreTiming::RegisterEvent("ChangeSIDevice", ChangeDeviceCallback); +} + +void Shutdown() +{ + for (int i = 0; i < NUMBER_OF_CHANNELS; i++) + RemoveDevice(i); +} + +void Read32(u32& _uReturnValue, const u32 _iAddress) +{ + DEBUG_LOG(SERIALINTERFACE, "(r32): 0x%08x", _iAddress); + + // SIBuffer + if ((_iAddress >= 0xCC006480 && _iAddress < 0xCC006500) || + (_iAddress >= 0xCD006480 && _iAddress < 0xCD006500)) + { + _uReturnValue = *(u32*)&g_SIBuffer[_iAddress & 0x7F]; + return; + } + + // registers + switch (_iAddress & 0x3FF) + { + ////////////////////////////////////////////////////////////////////////// + // Channel 0 + ////////////////////////////////////////////////////////////////////////// + case SI_CHANNEL_0_OUT: + _uReturnValue = g_Channel[0].m_Out.Hex; + return; + + case SI_CHANNEL_0_IN_HI: + g_StatusReg.RDST0 = 0; + UpdateInterrupts(); + _uReturnValue = g_Channel[0].m_InHi.Hex; + return; + + case SI_CHANNEL_0_IN_LO: + g_StatusReg.RDST0 = 0; + UpdateInterrupts(); + _uReturnValue = g_Channel[0].m_InLo.Hex; + return; + + ////////////////////////////////////////////////////////////////////////// + // Channel 1 + ////////////////////////////////////////////////////////////////////////// + case SI_CHANNEL_1_OUT: + _uReturnValue = g_Channel[1].m_Out.Hex; + return; + + case SI_CHANNEL_1_IN_HI: + g_StatusReg.RDST1 = 0; + UpdateInterrupts(); + _uReturnValue = g_Channel[1].m_InHi.Hex; + return; + + case SI_CHANNEL_1_IN_LO: + g_StatusReg.RDST1 = 0; + UpdateInterrupts(); + _uReturnValue = g_Channel[1].m_InLo.Hex; + return; + + ////////////////////////////////////////////////////////////////////////// + // Channel 2 + ////////////////////////////////////////////////////////////////////////// + case SI_CHANNEL_2_OUT: + _uReturnValue = g_Channel[2].m_Out.Hex; + return; + + case SI_CHANNEL_2_IN_HI: + g_StatusReg.RDST2 = 0; + UpdateInterrupts(); + _uReturnValue = g_Channel[2].m_InHi.Hex; + return; + + case SI_CHANNEL_2_IN_LO: + g_StatusReg.RDST2 = 0; + UpdateInterrupts(); + _uReturnValue = g_Channel[2].m_InLo.Hex; + return; + + ////////////////////////////////////////////////////////////////////////// + // Channel 3 + ////////////////////////////////////////////////////////////////////////// + case SI_CHANNEL_3_OUT: + _uReturnValue = g_Channel[3].m_Out.Hex; + return; + + case SI_CHANNEL_3_IN_HI: + g_StatusReg.RDST3 = 0; + UpdateInterrupts(); + _uReturnValue = g_Channel[3].m_InHi.Hex; + return; + + case SI_CHANNEL_3_IN_LO: + g_StatusReg.RDST3 = 0; + UpdateInterrupts(); + _uReturnValue = g_Channel[3].m_InLo.Hex; + return; + + case SI_POLL: _uReturnValue = g_Poll.Hex; return; + case SI_COM_CSR: _uReturnValue = g_ComCSR.Hex; return; + case SI_STATUS_REG: _uReturnValue = g_StatusReg.Hex; return; + + case SI_EXI_CLOCK_COUNT: _uReturnValue = g_EXIClockCount.Hex; return; + + default: + INFO_LOG(SERIALINTERFACE, "(r32-unk): 0x%08x", _iAddress); + _dbg_assert_(SERIALINTERFACE,0); + break; + } + + // error + _uReturnValue = 0xdeadbeef; +} + +void Write32(const u32 _iValue, const u32 _iAddress) +{ + DEBUG_LOG(SERIALINTERFACE, "(w32): 0x%08x 0x%08x", _iValue,_iAddress); + + // SIBuffer + if ((_iAddress >= 0xCC006480 && _iAddress < 0xCC006500) || + (_iAddress >= 0xCD006480 && _iAddress < 0xCD006500)) + { + *(u32*)&g_SIBuffer[_iAddress & 0x7F] = _iValue; + return; + } + + // registers + switch (_iAddress & 0x3FF) + { + case SI_CHANNEL_0_OUT: g_Channel[0].m_Out.Hex = _iValue; break; + case SI_CHANNEL_0_IN_HI: g_Channel[0].m_InHi.Hex = _iValue; break; + case SI_CHANNEL_0_IN_LO: g_Channel[0].m_InLo.Hex = _iValue; break; + case SI_CHANNEL_1_OUT: g_Channel[1].m_Out.Hex = _iValue; break; + case SI_CHANNEL_1_IN_HI: g_Channel[1].m_InHi.Hex = _iValue; break; + case SI_CHANNEL_1_IN_LO: g_Channel[1].m_InLo.Hex = _iValue; break; + case SI_CHANNEL_2_OUT: g_Channel[2].m_Out.Hex = _iValue; break; + case SI_CHANNEL_2_IN_HI: g_Channel[2].m_InHi.Hex = _iValue; break; + case SI_CHANNEL_2_IN_LO: g_Channel[2].m_InLo.Hex = _iValue; break; + case SI_CHANNEL_3_OUT: g_Channel[3].m_Out.Hex = _iValue; break; + case SI_CHANNEL_3_IN_HI: g_Channel[3].m_InHi.Hex = _iValue; break; + case SI_CHANNEL_3_IN_LO: g_Channel[3].m_InLo.Hex = _iValue; break; + + case SI_POLL: + g_Poll.Hex = _iValue; + break; + + case SI_COM_CSR: + { + USIComCSR tmpComCSR(_iValue); + + g_ComCSR.CHANNEL = tmpComCSR.CHANNEL; + g_ComCSR.INLNGTH = tmpComCSR.INLNGTH; + g_ComCSR.OUTLNGTH = tmpComCSR.OUTLNGTH; + g_ComCSR.RDSTINTMSK = tmpComCSR.RDSTINTMSK; + g_ComCSR.TCINTMSK = tmpComCSR.TCINTMSK; + + g_ComCSR.COMERR = 0; + + if (tmpComCSR.RDSTINT) g_ComCSR.RDSTINT = 0; + if (tmpComCSR.TCINT) g_ComCSR.TCINT = 0; + + // be careful: run si-buffer after updating the INT flags + if (tmpComCSR.TSTART) RunSIBuffer(); + UpdateInterrupts(); + } + break; + + case SI_STATUS_REG: + { + USIStatusReg tmpStatus(_iValue); + + // clear bits ( if(tmp.bit) SISR.bit=0 ) + if (tmpStatus.NOREP0) g_StatusReg.NOREP0 = 0; + if (tmpStatus.COLL0) g_StatusReg.COLL0 = 0; + if (tmpStatus.OVRUN0) g_StatusReg.OVRUN0 = 0; + if (tmpStatus.UNRUN0) g_StatusReg.UNRUN0 = 0; + + if (tmpStatus.NOREP1) g_StatusReg.NOREP1 = 0; + if (tmpStatus.COLL1) g_StatusReg.COLL1 = 0; + if (tmpStatus.OVRUN1) g_StatusReg.OVRUN1 = 0; + if (tmpStatus.UNRUN1) g_StatusReg.UNRUN1 = 0; + + if (tmpStatus.NOREP2) g_StatusReg.NOREP2 = 0; + if (tmpStatus.COLL2) g_StatusReg.COLL2 = 0; + if (tmpStatus.OVRUN2) g_StatusReg.OVRUN2 = 0; + if (tmpStatus.UNRUN2) g_StatusReg.UNRUN2 = 0; + + if (tmpStatus.NOREP3) g_StatusReg.NOREP3 = 0; + if (tmpStatus.COLL3) g_StatusReg.COLL3 = 0; + if (tmpStatus.OVRUN3) g_StatusReg.OVRUN3 = 0; + if (tmpStatus.UNRUN3) g_StatusReg.UNRUN3 = 0; + + // send command to devices + if (tmpStatus.WR) + { + g_Channel[0].m_pDevice->SendCommand(g_Channel[0].m_Out.Hex); + g_Channel[1].m_pDevice->SendCommand(g_Channel[1].m_Out.Hex); + g_Channel[2].m_pDevice->SendCommand(g_Channel[2].m_Out.Hex); + g_Channel[3].m_pDevice->SendCommand(g_Channel[3].m_Out.Hex); + + g_StatusReg.WR = 0; + g_StatusReg.WRST0 = 0; + g_StatusReg.WRST1 = 0; + g_StatusReg.WRST2 = 0; + g_StatusReg.WRST3 = 0; + } + } + break; + + case SI_EXI_CLOCK_COUNT: + g_EXIClockCount.Hex = _iValue; + break; + + case 0x80: + INFO_LOG(SERIALINTERFACE, "WII something at 0xCD006480"); + break; + + default: + _dbg_assert_(SERIALINTERFACE,0); + break; + } +} + +void UpdateInterrupts() +{ + // check if we have to update the RDSTINT flag + if (g_StatusReg.RDST0 || g_StatusReg.RDST1 || + g_StatusReg.RDST2 || g_StatusReg.RDST3) + g_ComCSR.RDSTINT = 1; + else + g_ComCSR.RDSTINT = 0; + + // check if we have to generate an interrupt + if ((g_ComCSR.RDSTINT & g_ComCSR.RDSTINTMSK) || + (g_ComCSR.TCINT & g_ComCSR.TCINTMSK)) + { + CPeripheralInterface::SetInterrupt(CPeripheralInterface::INT_CAUSE_SI, true); + } + else + { + CPeripheralInterface::SetInterrupt(CPeripheralInterface::INT_CAUSE_SI, false); + } +} + +void GenerateSIInterrupt(SIInterruptType _SIInterrupt) +{ + switch(_SIInterrupt) + { + case INT_RDSTINT: g_ComCSR.RDSTINT = 1; break; + case INT_TCINT: g_ComCSR.TCINT = 1; break; + } + + UpdateInterrupts(); +} + +void RemoveDevice(int _iDeviceNumber) +{ + if (g_Channel[_iDeviceNumber].m_pDevice != NULL) + { + delete g_Channel[_iDeviceNumber].m_pDevice; + g_Channel[_iDeviceNumber].m_pDevice = NULL; + } +} + +void AddDevice(const TSIDevices _device, int _iDeviceNumber) +{ + //_dbg_assert_(SERIALINTERFACE, _iDeviceNumber < NUMBER_OF_CHANNELS); + + // delete the old device + RemoveDevice(_iDeviceNumber); + + // create the new one + g_Channel[_iDeviceNumber].m_pDevice = SIDevice_Create(_device, _iDeviceNumber); + _dbg_assert_(SERIALINTERFACE, g_Channel[_iDeviceNumber].m_pDevice != NULL); +} + +void ChangeDeviceCallback(u64 userdata, int cyclesLate) +{ + u8 channel = (u8)(userdata >> 32); + // doubt this matters... + g_Channel[channel].m_Out.Hex = 0; + g_Channel[channel].m_InHi.Hex = 0; + g_Channel[channel].m_InLo.Hex = 0; + + // raise the NO RESPONSE error + switch (channel) + { + case 0: + g_StatusReg.NOREP0 = 1; + break; + case 1: + g_StatusReg.NOREP1 = 1; + break; + case 2: + g_StatusReg.NOREP2 = 1; + break; + case 3: + g_StatusReg.NOREP3 = 1; + break; + } + + AddDevice((TSIDevices)(u32)userdata, channel); +} + +void ChangeDevice(TSIDevices device, int deviceNumber) +{ + // Called from GUI, so we need to make it thread safe. + // Let the hardware see no device for .5b cycles + CoreTiming::ScheduleEvent_Threadsafe(0, changeDevice, (SI_DUMMY | (u64)deviceNumber << 32)); + CoreTiming::ScheduleEvent_Threadsafe(500000000, changeDevice, (device | (u64)deviceNumber << 32)); +} + +void UpdateDevices() +{ + // Update channels + g_StatusReg.RDST0 = g_Channel[0].m_pDevice->GetData(g_Channel[0].m_InHi.Hex, g_Channel[0].m_InLo.Hex) ? 1 : 0; + g_StatusReg.RDST1 = g_Channel[1].m_pDevice->GetData(g_Channel[1].m_InHi.Hex, g_Channel[1].m_InLo.Hex) ? 1 : 0; + g_StatusReg.RDST2 = g_Channel[2].m_pDevice->GetData(g_Channel[2].m_InHi.Hex, g_Channel[2].m_InLo.Hex) ? 1 : 0; + g_StatusReg.RDST3 = g_Channel[3].m_pDevice->GetData(g_Channel[3].m_InHi.Hex, g_Channel[3].m_InLo.Hex) ? 1 : 0; + + // Update interrupts + UpdateInterrupts(); +} + +void RunSIBuffer() +{ + // Math inLength + int inLength = g_ComCSR.INLNGTH; + if (inLength == 0) + inLength = 128; + else + inLength++; + + // Math outLength + int outLength = g_ComCSR.OUTLNGTH; + if (outLength == 0) + outLength = 128; + else + outLength++; + +#if LOGLEVEL >= 3 + int numOutput = +#endif + g_Channel[g_ComCSR.CHANNEL].m_pDevice->RunBuffer(g_SIBuffer, inLength); + + INFO_LOG(SERIALINTERFACE, "RunSIBuffer (intLen: %i outLen: %i) (processed: %i)", inLength, outLength, numOutput); + + // Transfer completed + GenerateSIInterrupt(INT_TCINT); + g_ComCSR.TSTART = 0; +} + +} // end of namespace SerialInterface diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp index fcddd8fb36..7f3a34bed1 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp @@ -1,444 +1,444 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - - - -// ======================================================= -// File description -// ------------- -/* Here we handle /dev/es requests. We have cases for these functions, the exact - DevKitPro/libogc name is in parenthesis: - - 0x20 GetTitleID (ES_GetTitleID) (Input: none, Output: 8 bytes) - 0x1d GetDataDir (ES_GetDataDir) (Input: 8 bytes, Output: 30 bytes) - - 0x1b DiGetTicketView (Input: none, Output: 216 bytes) - 0x16 GetConsumption (Input: 8 bytes, Output: 0 bytes, 4 bytes) // there are two output buffers - - 0x12 GetNumTicketViews (ES_GetNumTicketViews) (Input: 8 bytes, Output: 4 bytes) - 0x14 GetTMDViewSize (ES_GetTMDViewSize) (Input: ?, Output: ?) // I don't get this anymore, - it used to come after 0x12 - - but only the first two are correctly supported. For the other four we ignore any potential - input and only write zero to the out buffer. However, most games only use first two, - but some Nintendo developed games use the other ones to: - - 0x1b: Mario Galaxy, Mario Kart, SSBB - 0x16: Mario Galaxy, Mario Kart, SSBB - 0x12: Mario Kart - 0x14: Mario Kart: But only if we don't return a zeroed out buffer for the 0x12 question, - and instead answer for example 1 will this question appear. - -*/ -// ============= - -#include "WII_IPC_HLE_Device_es.h" - -#include "../PowerPC/PowerPC.h" -#include "../VolumeHandler.h" - - -CWII_IPC_HLE_Device_es::CWII_IPC_HLE_Device_es(u32 _DeviceID, const std::string& _rDeviceName, const std::string& _rDefaultContentFile) - : IWII_IPC_HLE_Device(_DeviceID, _rDeviceName) - , m_pContentLoader(NULL) - , m_TitleID(-1) - , AccessIdentID(0x6000000) -{ - m_pContentLoader = new DiscIO::CNANDContentLoader(_rDefaultContentFile); - - // check for cd ... - if (m_pContentLoader->IsValid()) - { - m_TitleID = m_pContentLoader->GetTitleID(); - } - else if (VolumeHandler::IsValid()) - { - m_TitleID = ((u64)0x00010000 << 32) | VolumeHandler::Read32(0); - } - else - { - m_TitleID = ((u64)0x00010000 << 32) | 0xF00DBEEF; - } - - INFO_LOG(WII_IPC_ES, "Set default title to %08x/%08x", m_TitleID>>32, m_TitleID); -} - -CWII_IPC_HLE_Device_es::~CWII_IPC_HLE_Device_es() -{ - delete m_pContentLoader; -} - -bool CWII_IPC_HLE_Device_es::Open(u32 _CommandAddress, u32 _Mode) -{ - Memory::Write_U32(GetDeviceID(), _CommandAddress+4); - return true; -} - -bool CWII_IPC_HLE_Device_es::Close(u32 _CommandAddress) -{ - INFO_LOG(WII_IPC_ES, "ES: Close"); - Memory::Write_U32(0, _CommandAddress + 4); - return true; -} - -bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) -{ - SIOCtlVBuffer Buffer(_CommandAddress); - - INFO_LOG(WII_IPC_ES, "%s (0x%x)", GetDeviceName().c_str(), Buffer.Parameter); - - // Prepare the out buffer(s) with zeroes as a safety precaution - // to avoid returning bad values - for (u32 i = 0; i < Buffer.NumberPayloadBuffer; i++) - { - Memory::Memset(Buffer.PayloadBuffer[i].m_Address, 0, - Buffer.PayloadBuffer[i].m_Size); - } - - switch (Buffer.Parameter) - { - case IOCTL_ES_OPENTITLECONTENT: - { - u32 CFD = AccessIdentID++; - u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); - u32 Index = Memory::Read_U32(Buffer.InBuffer[0].m_Address+8); - - m_ContentAccessMap[CFD].m_Position = 0; - m_ContentAccessMap[CFD].m_pContent = AccessContentDevice(TitleID).GetContentByIndex(Index); - _dbg_assert_(WII_IPC_ES, m_ContentAccessMap[CFD].m_pContent != NULL); - - Memory::Write_U32(CFD, _CommandAddress + 0x4); - - INFO_LOG(WII_IPC_ES, "ES: IOCTL_ES_OPENTITLECONTENT: TitleID: %08x/%08x Index %i -> got CFD %x", TitleID>>32, TitleID, Index, CFD); - return true; - } - break; - - case IOCTL_ES_OPENCONTENT: - { - u32 CFD = AccessIdentID++; - u32 Index = Memory::Read_U32(Buffer.InBuffer[0].m_Address); - - m_ContentAccessMap[CFD].m_Position = 0; - m_ContentAccessMap[CFD].m_pContent = AccessContentDevice(m_TitleID).GetContentByIndex(Index); - _dbg_assert_(WII_IPC_ES, m_ContentAccessMap[CFD].m_pContent != NULL); - - Memory::Write_U32(CFD, _CommandAddress + 0x4); - - INFO_LOG(WII_IPC_ES, "ES: IOCTL_ES_OPENCONTENT: Index %i -> got CFD %x", Index, CFD); - return true; - } - break; - - case IOCTL_ES_READCONTENT: - { - _dbg_assert_(WII_IPC_ES, Buffer.NumberInBuffer == 1); - - u32 CFD = Memory::Read_U32(Buffer.InBuffer[0].m_Address); - u32 Size = Buffer.PayloadBuffer[0].m_Size; - u32 Addr = Buffer.PayloadBuffer[0].m_Address; - - _dbg_assert_(WII_IPC_ES, m_ContentAccessMap.find(CFD) != m_ContentAccessMap.end()); - SContentAccess& rContent = m_ContentAccessMap[CFD]; - - u8* pSrc = &rContent.m_pContent->m_pData[rContent.m_Position]; - u8* pDest = Memory::GetPointer(Addr); - - if (rContent.m_Position + Size > rContent.m_pContent->m_Size) - { - Size = rContent.m_pContent->m_Size-rContent.m_Position; - } - - if (Size > 0) - { - memcpy(pDest,pSrc, Size); - rContent.m_Position += Size; - } - - INFO_LOG(WII_IPC_ES, "ES: IOCTL_ES_READCONTENT: CFD %x, Addr 0x%x, Size %i -> stream pos %i", CFD, Addr, Size, rContent.m_Position); - - Memory::Write_U32(Size, _CommandAddress + 0x4); - return true; - } - break; - - case IOCTL_ES_CLOSECONTENT: - { - _dbg_assert_(WII_IPC_ES, Buffer.NumberInBuffer == 1); - u32 CFD = Memory::Read_U32(Buffer.InBuffer[0].m_Address); - - CContentAccessMap::iterator itr = m_ContentAccessMap.find(CFD); - m_ContentAccessMap.erase(itr); - - INFO_LOG(WII_IPC_ES, "ES: IOCTL_ES_CLOSECONTENT: CFD %x", CFD); - - Memory::Write_U32(0, _CommandAddress + 0x4); - return true; - } - break; - - case IOCTL_ES_SEEKCONTENT: - { - u32 CFD = Memory::Read_U32(Buffer.InBuffer[0].m_Address); - u32 Addr = Memory::Read_U32(Buffer.InBuffer[1].m_Address); - u32 Mode = Memory::Read_U32(Buffer.InBuffer[2].m_Address); - - _dbg_assert_(WII_IPC_ES, m_ContentAccessMap.find(CFD) != m_ContentAccessMap.end()); - SContentAccess& rContent = m_ContentAccessMap[CFD]; - - switch (Mode) - { - case 0: // SET - rContent.m_Position = Addr; - break; - - case 1: // CUR - rContent.m_Position += Addr; - break; - - case 2: // END - rContent.m_Position = rContent.m_pContent->m_Size + Addr; - break; - } - - INFO_LOG(WII_IPC_ES, "ES: IOCTL_ES_SEEKCONTENT: CFD %x, Addr 0x%x, Mode %i -> Pos %i", CFD, Addr, Mode, rContent.m_Position); - - Memory::Write_U32(rContent.m_Position, _CommandAddress + 0x4); - return true; - } - break; - - case IOCTL_ES_GETTITLEDIR: - { - u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); - - char* pTitleID = (char*)&TitleID; - char* Path = (char*)Memory::GetPointer(Buffer.PayloadBuffer[0].m_Address); - sprintf(Path, "/%08x/%08x/data", (u32)(TitleID >> 32) & 0xFFFFFFFF, (u32)TitleID & 0xFFFFFFFF); - - INFO_LOG(WII_IPC_ES, "ES: IOCTL_ES_GETTITLEDIR: %s)", Path); - } - break; - - case IOCTL_ES_GETTITLEID: - { - _dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1, "CWII_IPC_HLE_Device_es: IOCTL_ES_GETTITLEID no out buffer"); - - Memory::Write_U64(m_TitleID, Buffer.PayloadBuffer[0].m_Address); - INFO_LOG(WII_IPC_ES, "ES: IOCTL_ES_GETTITLEID: %08x/%08x", m_TitleID>>32, m_TitleID); - } - break; - - case IOCTL_ES_SETUID: - { - _dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 1, "CWII_IPC_HLE_Device_es: IOCTL_ES_GETTITLEID no in buffer"); - - u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); - INFO_LOG(WII_IPC_ES, "ES: IOCTL_ES_SETUID titleID: %08x/%08x", TitleID>>32, TitleID ); - } - break; - - case IOCTL_ES_GETVIEWCNT: - { - _dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 1, "CWII_IPC_HLE_Device_es: IOCTL_ES_GETVIEWCNT no in buffer"); - _dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1, "CWII_IPC_HLE_Device_es: IOCTL_ES_GETVIEWCNT no out buffer"); - - u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); - - // [TODO] here we should have a map from title id to tickets or something like that... - if (IsValid(TitleID)) - { - Memory::Write_U32(1, Buffer.PayloadBuffer[0].m_Address); - } - else - { - Memory::Write_U32(0, Buffer.PayloadBuffer[0].m_Address); - } - - INFO_LOG(WII_IPC_ES, "ES: IOCTL_ES_GETVIEWCNT for titleID: %08x/%08x", TitleID>>32, TitleID ); - - Memory::Write_U32(0, _CommandAddress + 0x4); - return true; - } - break; - - case IOCTL_ES_GETTITLECNT: - { - _dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 0, "IOCTL_ES_GETTITLECNT has an in buffer"); - _dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1, "IOCTL_ES_GETTITLECNT has no out buffer"); - _dbg_assert_msg_(WII_IPC_ES, Buffer.PayloadBuffer[0].m_Size == 4, "IOCTL_ES_GETTITLECNT payload[0].size != 4"); - - - // TODO - Memory::Write_U32(1, Buffer.PayloadBuffer[0].m_Address); - - ERROR_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLECNT: TODO... 1"); - } - break; - - - case IOCTL_ES_GETTITLES: - { - _dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 1, "IOCTL_ES_GETTITLES has an in buffer"); - _dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1, "IOCTL_ES_GETTITLES has no out buffer"); - - u32 Count = Memory::Read_U32(Buffer.InBuffer[0].m_Address); - - std::vector TitleIDs; - TitleIDs.push_back(0x0000000100000002ULL); - // TitleIDs.push_back(0x0001000248414341); - // TitleIDs.push_back(0x0001000146414b45); - - for (int i = 0; i < (int)TitleIDs.size(); i++) - { - Memory::Write_U64(TitleIDs[i], Buffer.PayloadBuffer[0].m_Address + i*8); - ERROR_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLES: %08x/%08x", TitleIDs[i] >> 32, TitleIDs[i]); - } - } - break; - - - - // =============================================================================================== - // unsupported functions - // =============================================================================================== - - case IOCTL_ES_LAUNCH: - { - _dbg_assert_(WII_IPC_ES, Buffer.NumberInBuffer == 2); - - u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); - - u32 view = Memory::Read_U32(Buffer.InBuffer[1].m_Address); - u64 ticketid = Memory::Read_U64(Buffer.InBuffer[1].m_Address+4); - u32 devicetype =Memory::Read_U32(Buffer.InBuffer[1].m_Address+12); - u64 titleid = Memory::Read_U64(Buffer.InBuffer[1].m_Address+16); - u16 access = Memory::Read_U16(Buffer.InBuffer[1].m_Address+24); - - PanicAlert("IOCTL_ES_LAUNCH: src titleID %08x/%08x -> start %08x/%08x \n" - "This means that dolphin tries to relaunch the WiiMenu or" - "launches code from the an URL. Both wont work and dolphin will prolly hang...", - TitleID>>32, TitleID, titleid>>32, titleid ); - - Memory::Write_U32(0, _CommandAddress + 0x4); - - ERROR_LOG(WII_IPC_ES, "IOCTL_ES_LAUNCH"); - - return true; - } - break; - - case IOCTL_ES_GETVIEWS: - { - _dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 2, "IOCTL_ES_GETVIEWS no in buffer"); - _dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1, "IOCTL_ES_GETVIEWS no out buffer"); - - u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); - u32 Count = Memory::Read_U32(Buffer.InBuffer[1].m_Address); - - _dbg_assert_msg_(WII_IPC_ES, TitleID==0x0000000100000002ull, "IOCTL_ES_GETVIEWS: TitleID != 00000001/00000002"); - - /* write ticket data... hmmm - typedef struct _tikview { - u32 view; - u64 ticketid; - u32 devicetype; - u64 titleid; - u16 access_mask; - u8 reserved[0x3c]; - u8 cidx_mask[0x40]; - u16 padding; - tiklimit limits[8]; - } __attribute__((packed)) tikview; - */ - - Memory::Write_U32(1, Buffer.PayloadBuffer[0].m_Address); - Memory::Write_U64(m_TitleID, Buffer.PayloadBuffer[0].m_Address+4); - Memory::Write_U32(0x00010001, Buffer.PayloadBuffer[0].m_Address+12); - Memory::Write_U64(m_TitleID, Buffer.PayloadBuffer[0].m_Address+16); - Memory::Write_U16(0x777, Buffer.PayloadBuffer[0].m_Address+24); - - Memory::Write_U32(0, _CommandAddress + 0x4); - - _dbg_assert_msg_(WII_IPC_ES, 0, "IOCTL_ES_GETVIEWS: this looks really wrong..."); - - ERROR_LOG(WII_IPC_ES, "IOCTL_ES_LAUNCH"); - return true; - } - break; - - case IOCTL_ES_GETSTOREDTMDSIZE: - { - _dbg_assert_msg_(WII_IPC_ES, 0, "IOCTL_ES_GETSTOREDTMDSIZE: this looks really wrong..."); - - /* u64 TitleId = Memory::Read_U64(Buffer.InBuffer[0].m_Address); - u32 OutBuffer = Memory::Read_U32(Buffer.PayloadBuffer[0].m_Address); - - Memory::Write_U32(0, OutBuffer); - printf("ES_GetStoredTmdSize(%llx)\n", TitleId); - LOG(WII_IPC_ES, "CWII_IPC_HLE_Device_es command:" - " IOCTL_ES_GETSTOREDTMDSIZE: 0x%x", OutBuffer);*/ - } - break; - - case IOCTL_ES_GETTMDVIEWCNT: - _dbg_assert_msg_(WII_IPC_ES, 0, "IOCTL_ES_GETTMDVIEWCNT: this looks really wrong..."); - break; - - case IOCTL_ES_GETCONSUMPTION: // (Input: 8 bytes, Output: 0 bytes, 4 bytes) - _dbg_assert_msg_(WII_IPC_ES, 0, "IOCTL_ES_GETCONSUMPTION: this looks really wrong..."); - break; - - case IOCTL_ES_DIGETTICKETVIEW: // (Input: none, Output: 216 bytes) - _dbg_assert_msg_(WII_IPC_ES, 0, "IOCTL_ES_DIGETTICKETVIEW: this looks really wrong..."); - break; - - - default: - - _dbg_assert_msg_(WII_IPC_ES, 0, "CWII_IPC_HLE_Device_es: 0x%x", Buffer.Parameter); - - DumpCommands(_CommandAddress, 8); - INFO_LOG(WII_IPC_ES, "CWII_IPC_HLE_Device_es command:" - "Parameter: 0x%08x", Buffer.Parameter); - - break; - } - - // Write return value (0 means OK) - Memory::Write_U32(0, _CommandAddress + 0x4); - - return true; -} - -DiscIO::CNANDContentLoader& CWII_IPC_HLE_Device_es::AccessContentDevice(u64 _TitleID) const -{ - if (m_pContentLoader->IsValid() && m_pContentLoader->GetTitleID() == _TitleID) - return* m_pContentLoader; - - PanicAlert("Try to access unknown title content (%08x/%08x). Dolphin will prolly crash now.", _TitleID>>32, _TitleID); - return* m_pContentLoader; -} - -bool CWII_IPC_HLE_Device_es::IsValid(u64 _TitleID) const -{ - if (m_pContentLoader->IsValid() && m_pContentLoader->GetTitleID() == _TitleID) - return true; - - return false; -} - +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + + + +// ======================================================= +// File description +// ------------- +/* Here we handle /dev/es requests. We have cases for these functions, the exact + DevKitPro/libogc name is in parenthesis: + + 0x20 GetTitleID (ES_GetTitleID) (Input: none, Output: 8 bytes) + 0x1d GetDataDir (ES_GetDataDir) (Input: 8 bytes, Output: 30 bytes) + + 0x1b DiGetTicketView (Input: none, Output: 216 bytes) + 0x16 GetConsumption (Input: 8 bytes, Output: 0 bytes, 4 bytes) // there are two output buffers + + 0x12 GetNumTicketViews (ES_GetNumTicketViews) (Input: 8 bytes, Output: 4 bytes) + 0x14 GetTMDViewSize (ES_GetTMDViewSize) (Input: ?, Output: ?) // I don't get this anymore, + it used to come after 0x12 + + but only the first two are correctly supported. For the other four we ignore any potential + input and only write zero to the out buffer. However, most games only use first two, + but some Nintendo developed games use the other ones to: + + 0x1b: Mario Galaxy, Mario Kart, SSBB + 0x16: Mario Galaxy, Mario Kart, SSBB + 0x12: Mario Kart + 0x14: Mario Kart: But only if we don't return a zeroed out buffer for the 0x12 question, + and instead answer for example 1 will this question appear. + +*/ +// ============= + +#include "WII_IPC_HLE_Device_es.h" + +#include "../PowerPC/PowerPC.h" +#include "../VolumeHandler.h" + + +CWII_IPC_HLE_Device_es::CWII_IPC_HLE_Device_es(u32 _DeviceID, const std::string& _rDeviceName, const std::string& _rDefaultContentFile) + : IWII_IPC_HLE_Device(_DeviceID, _rDeviceName) + , m_pContentLoader(NULL) + , m_TitleID(-1) + , AccessIdentID(0x6000000) +{ + m_pContentLoader = new DiscIO::CNANDContentLoader(_rDefaultContentFile); + + // check for cd ... + if (m_pContentLoader->IsValid()) + { + m_TitleID = m_pContentLoader->GetTitleID(); + } + else if (VolumeHandler::IsValid()) + { + m_TitleID = ((u64)0x00010000 << 32) | VolumeHandler::Read32(0); + } + else + { + m_TitleID = ((u64)0x00010000 << 32) | 0xF00DBEEF; + } + + INFO_LOG(WII_IPC_ES, "Set default title to %08x/%08x", m_TitleID>>32, m_TitleID); +} + +CWII_IPC_HLE_Device_es::~CWII_IPC_HLE_Device_es() +{ + delete m_pContentLoader; +} + +bool CWII_IPC_HLE_Device_es::Open(u32 _CommandAddress, u32 _Mode) +{ + Memory::Write_U32(GetDeviceID(), _CommandAddress+4); + return true; +} + +bool CWII_IPC_HLE_Device_es::Close(u32 _CommandAddress) +{ + INFO_LOG(WII_IPC_ES, "ES: Close"); + Memory::Write_U32(0, _CommandAddress + 4); + return true; +} + +bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) +{ + SIOCtlVBuffer Buffer(_CommandAddress); + + INFO_LOG(WII_IPC_ES, "%s (0x%x)", GetDeviceName().c_str(), Buffer.Parameter); + + // Prepare the out buffer(s) with zeroes as a safety precaution + // to avoid returning bad values + for (u32 i = 0; i < Buffer.NumberPayloadBuffer; i++) + { + Memory::Memset(Buffer.PayloadBuffer[i].m_Address, 0, + Buffer.PayloadBuffer[i].m_Size); + } + + switch (Buffer.Parameter) + { + case IOCTL_ES_OPENTITLECONTENT: + { + u32 CFD = AccessIdentID++; + u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); + u32 Index = Memory::Read_U32(Buffer.InBuffer[0].m_Address+8); + + m_ContentAccessMap[CFD].m_Position = 0; + m_ContentAccessMap[CFD].m_pContent = AccessContentDevice(TitleID).GetContentByIndex(Index); + _dbg_assert_(WII_IPC_ES, m_ContentAccessMap[CFD].m_pContent != NULL); + + Memory::Write_U32(CFD, _CommandAddress + 0x4); + + INFO_LOG(WII_IPC_ES, "ES: IOCTL_ES_OPENTITLECONTENT: TitleID: %08x/%08x Index %i -> got CFD %x", TitleID>>32, TitleID, Index, CFD); + return true; + } + break; + + case IOCTL_ES_OPENCONTENT: + { + u32 CFD = AccessIdentID++; + u32 Index = Memory::Read_U32(Buffer.InBuffer[0].m_Address); + + m_ContentAccessMap[CFD].m_Position = 0; + m_ContentAccessMap[CFD].m_pContent = AccessContentDevice(m_TitleID).GetContentByIndex(Index); + _dbg_assert_(WII_IPC_ES, m_ContentAccessMap[CFD].m_pContent != NULL); + + Memory::Write_U32(CFD, _CommandAddress + 0x4); + + INFO_LOG(WII_IPC_ES, "ES: IOCTL_ES_OPENCONTENT: Index %i -> got CFD %x", Index, CFD); + return true; + } + break; + + case IOCTL_ES_READCONTENT: + { + _dbg_assert_(WII_IPC_ES, Buffer.NumberInBuffer == 1); + + u32 CFD = Memory::Read_U32(Buffer.InBuffer[0].m_Address); + u32 Size = Buffer.PayloadBuffer[0].m_Size; + u32 Addr = Buffer.PayloadBuffer[0].m_Address; + + _dbg_assert_(WII_IPC_ES, m_ContentAccessMap.find(CFD) != m_ContentAccessMap.end()); + SContentAccess& rContent = m_ContentAccessMap[CFD]; + + u8* pSrc = &rContent.m_pContent->m_pData[rContent.m_Position]; + u8* pDest = Memory::GetPointer(Addr); + + if (rContent.m_Position + Size > rContent.m_pContent->m_Size) + { + Size = rContent.m_pContent->m_Size-rContent.m_Position; + } + + if (Size > 0) + { + memcpy(pDest,pSrc, Size); + rContent.m_Position += Size; + } + + INFO_LOG(WII_IPC_ES, "ES: IOCTL_ES_READCONTENT: CFD %x, Addr 0x%x, Size %i -> stream pos %i", CFD, Addr, Size, rContent.m_Position); + + Memory::Write_U32(Size, _CommandAddress + 0x4); + return true; + } + break; + + case IOCTL_ES_CLOSECONTENT: + { + _dbg_assert_(WII_IPC_ES, Buffer.NumberInBuffer == 1); + u32 CFD = Memory::Read_U32(Buffer.InBuffer[0].m_Address); + + CContentAccessMap::iterator itr = m_ContentAccessMap.find(CFD); + m_ContentAccessMap.erase(itr); + + INFO_LOG(WII_IPC_ES, "ES: IOCTL_ES_CLOSECONTENT: CFD %x", CFD); + + Memory::Write_U32(0, _CommandAddress + 0x4); + return true; + } + break; + + case IOCTL_ES_SEEKCONTENT: + { + u32 CFD = Memory::Read_U32(Buffer.InBuffer[0].m_Address); + u32 Addr = Memory::Read_U32(Buffer.InBuffer[1].m_Address); + u32 Mode = Memory::Read_U32(Buffer.InBuffer[2].m_Address); + + _dbg_assert_(WII_IPC_ES, m_ContentAccessMap.find(CFD) != m_ContentAccessMap.end()); + SContentAccess& rContent = m_ContentAccessMap[CFD]; + + switch (Mode) + { + case 0: // SET + rContent.m_Position = Addr; + break; + + case 1: // CUR + rContent.m_Position += Addr; + break; + + case 2: // END + rContent.m_Position = rContent.m_pContent->m_Size + Addr; + break; + } + + INFO_LOG(WII_IPC_ES, "ES: IOCTL_ES_SEEKCONTENT: CFD %x, Addr 0x%x, Mode %i -> Pos %i", CFD, Addr, Mode, rContent.m_Position); + + Memory::Write_U32(rContent.m_Position, _CommandAddress + 0x4); + return true; + } + break; + + case IOCTL_ES_GETTITLEDIR: + { + u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); + + char* pTitleID = (char*)&TitleID; + char* Path = (char*)Memory::GetPointer(Buffer.PayloadBuffer[0].m_Address); + sprintf(Path, "/%08x/%08x/data", (u32)(TitleID >> 32) & 0xFFFFFFFF, (u32)TitleID & 0xFFFFFFFF); + + INFO_LOG(WII_IPC_ES, "ES: IOCTL_ES_GETTITLEDIR: %s)", Path); + } + break; + + case IOCTL_ES_GETTITLEID: + { + _dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1, "CWII_IPC_HLE_Device_es: IOCTL_ES_GETTITLEID no out buffer"); + + Memory::Write_U64(m_TitleID, Buffer.PayloadBuffer[0].m_Address); + INFO_LOG(WII_IPC_ES, "ES: IOCTL_ES_GETTITLEID: %08x/%08x", m_TitleID>>32, m_TitleID); + } + break; + + case IOCTL_ES_SETUID: + { + _dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 1, "CWII_IPC_HLE_Device_es: IOCTL_ES_GETTITLEID no in buffer"); + + u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); + INFO_LOG(WII_IPC_ES, "ES: IOCTL_ES_SETUID titleID: %08x/%08x", TitleID>>32, TitleID ); + } + break; + + case IOCTL_ES_GETVIEWCNT: + { + _dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 1, "CWII_IPC_HLE_Device_es: IOCTL_ES_GETVIEWCNT no in buffer"); + _dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1, "CWII_IPC_HLE_Device_es: IOCTL_ES_GETVIEWCNT no out buffer"); + + u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); + + // [TODO] here we should have a map from title id to tickets or something like that... + if (IsValid(TitleID)) + { + Memory::Write_U32(1, Buffer.PayloadBuffer[0].m_Address); + } + else + { + Memory::Write_U32(0, Buffer.PayloadBuffer[0].m_Address); + } + + INFO_LOG(WII_IPC_ES, "ES: IOCTL_ES_GETVIEWCNT for titleID: %08x/%08x", TitleID>>32, TitleID ); + + Memory::Write_U32(0, _CommandAddress + 0x4); + return true; + } + break; + + case IOCTL_ES_GETTITLECNT: + { + _dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 0, "IOCTL_ES_GETTITLECNT has an in buffer"); + _dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1, "IOCTL_ES_GETTITLECNT has no out buffer"); + _dbg_assert_msg_(WII_IPC_ES, Buffer.PayloadBuffer[0].m_Size == 4, "IOCTL_ES_GETTITLECNT payload[0].size != 4"); + + + // TODO + Memory::Write_U32(1, Buffer.PayloadBuffer[0].m_Address); + + ERROR_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLECNT: TODO... 1"); + } + break; + + + case IOCTL_ES_GETTITLES: + { + _dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 1, "IOCTL_ES_GETTITLES has an in buffer"); + _dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1, "IOCTL_ES_GETTITLES has no out buffer"); + + u32 Count = Memory::Read_U32(Buffer.InBuffer[0].m_Address); + + std::vector TitleIDs; + TitleIDs.push_back(0x0000000100000002ULL); + // TitleIDs.push_back(0x0001000248414341); + // TitleIDs.push_back(0x0001000146414b45); + + for (int i = 0; i < (int)TitleIDs.size(); i++) + { + Memory::Write_U64(TitleIDs[i], Buffer.PayloadBuffer[0].m_Address + i*8); + ERROR_LOG(WII_IPC_ES, "IOCTL_ES_GETTITLES: %08x/%08x", TitleIDs[i] >> 32, TitleIDs[i]); + } + } + break; + + + + // =============================================================================================== + // unsupported functions + // =============================================================================================== + + case IOCTL_ES_LAUNCH: + { + _dbg_assert_(WII_IPC_ES, Buffer.NumberInBuffer == 2); + + u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); + + u32 view = Memory::Read_U32(Buffer.InBuffer[1].m_Address); + u64 ticketid = Memory::Read_U64(Buffer.InBuffer[1].m_Address+4); + u32 devicetype =Memory::Read_U32(Buffer.InBuffer[1].m_Address+12); + u64 titleid = Memory::Read_U64(Buffer.InBuffer[1].m_Address+16); + u16 access = Memory::Read_U16(Buffer.InBuffer[1].m_Address+24); + + PanicAlert("IOCTL_ES_LAUNCH: src titleID %08x/%08x -> start %08x/%08x \n" + "This means that dolphin tries to relaunch the WiiMenu or" + "launches code from the an URL. Both wont work and dolphin will prolly hang...", + TitleID>>32, TitleID, titleid>>32, titleid ); + + Memory::Write_U32(0, _CommandAddress + 0x4); + + ERROR_LOG(WII_IPC_ES, "IOCTL_ES_LAUNCH"); + + return true; + } + break; + + case IOCTL_ES_GETVIEWS: + { + _dbg_assert_msg_(WII_IPC_ES, Buffer.NumberInBuffer == 2, "IOCTL_ES_GETVIEWS no in buffer"); + _dbg_assert_msg_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 1, "IOCTL_ES_GETVIEWS no out buffer"); + + u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address); + u32 Count = Memory::Read_U32(Buffer.InBuffer[1].m_Address); + + _dbg_assert_msg_(WII_IPC_ES, TitleID==0x0000000100000002ull, "IOCTL_ES_GETVIEWS: TitleID != 00000001/00000002"); + + /* write ticket data... hmmm + typedef struct _tikview { + u32 view; + u64 ticketid; + u32 devicetype; + u64 titleid; + u16 access_mask; + u8 reserved[0x3c]; + u8 cidx_mask[0x40]; + u16 padding; + tiklimit limits[8]; + } __attribute__((packed)) tikview; + */ + + Memory::Write_U32(1, Buffer.PayloadBuffer[0].m_Address); + Memory::Write_U64(m_TitleID, Buffer.PayloadBuffer[0].m_Address+4); + Memory::Write_U32(0x00010001, Buffer.PayloadBuffer[0].m_Address+12); + Memory::Write_U64(m_TitleID, Buffer.PayloadBuffer[0].m_Address+16); + Memory::Write_U16(0x777, Buffer.PayloadBuffer[0].m_Address+24); + + Memory::Write_U32(0, _CommandAddress + 0x4); + + _dbg_assert_msg_(WII_IPC_ES, 0, "IOCTL_ES_GETVIEWS: this looks really wrong..."); + + ERROR_LOG(WII_IPC_ES, "IOCTL_ES_LAUNCH"); + return true; + } + break; + + case IOCTL_ES_GETSTOREDTMDSIZE: + { + _dbg_assert_msg_(WII_IPC_ES, 0, "IOCTL_ES_GETSTOREDTMDSIZE: this looks really wrong..."); + + /* u64 TitleId = Memory::Read_U64(Buffer.InBuffer[0].m_Address); + u32 OutBuffer = Memory::Read_U32(Buffer.PayloadBuffer[0].m_Address); + + Memory::Write_U32(0, OutBuffer); + printf("ES_GetStoredTmdSize(%llx)\n", TitleId); + LOG(WII_IPC_ES, "CWII_IPC_HLE_Device_es command:" + " IOCTL_ES_GETSTOREDTMDSIZE: 0x%x", OutBuffer);*/ + } + break; + + case IOCTL_ES_GETTMDVIEWCNT: + _dbg_assert_msg_(WII_IPC_ES, 0, "IOCTL_ES_GETTMDVIEWCNT: this looks really wrong..."); + break; + + case IOCTL_ES_GETCONSUMPTION: // (Input: 8 bytes, Output: 0 bytes, 4 bytes) + _dbg_assert_msg_(WII_IPC_ES, 0, "IOCTL_ES_GETCONSUMPTION: this looks really wrong..."); + break; + + case IOCTL_ES_DIGETTICKETVIEW: // (Input: none, Output: 216 bytes) + _dbg_assert_msg_(WII_IPC_ES, 0, "IOCTL_ES_DIGETTICKETVIEW: this looks really wrong..."); + break; + + + default: + + _dbg_assert_msg_(WII_IPC_ES, 0, "CWII_IPC_HLE_Device_es: 0x%x", Buffer.Parameter); + + DumpCommands(_CommandAddress, 8); + INFO_LOG(WII_IPC_ES, "CWII_IPC_HLE_Device_es command:" + "Parameter: 0x%08x", Buffer.Parameter); + + break; + } + + // Write return value (0 means OK) + Memory::Write_U32(0, _CommandAddress + 0x4); + + return true; +} + +DiscIO::CNANDContentLoader& CWII_IPC_HLE_Device_es::AccessContentDevice(u64 _TitleID) const +{ + if (m_pContentLoader->IsValid() && m_pContentLoader->GetTitleID() == _TitleID) + return* m_pContentLoader; + + PanicAlert("Try to access unknown title content (%08x/%08x). Dolphin will prolly crash now.", _TitleID>>32, _TitleID); + return* m_pContentLoader; +} + +bool CWII_IPC_HLE_Device_es::IsValid(u64 _TitleID) const +{ + if (m_pContentLoader->IsValid() && m_pContentLoader->GetTitleID() == _TitleID) + return true; + + return false; +} + diff --git a/Source/Core/DiscIO/Src/NANDContentLoader.cpp b/Source/Core/DiscIO/Src/NANDContentLoader.cpp index 668d28488f..16b8d3d70c 100644 --- a/Source/Core/DiscIO/Src/NANDContentLoader.cpp +++ b/Source/Core/DiscIO/Src/NANDContentLoader.cpp @@ -1,295 +1,295 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "stdafx.h" -#include "NANDContentLoader.h" - -#include "AES/aes.h" -#include "MathUtil.h" -#include "FileUtil.h" -#include "Log.h" - -namespace DiscIO -{ - -class CBlobBigEndianReader -{ -public: - CBlobBigEndianReader(DiscIO::IBlobReader& _rReader) : m_rReader(_rReader) {} - - u32 Read32(u64 _Offset) - { - u32 Temp; - m_rReader.Read(_Offset, 4, (u8*)&Temp); - return(Common::swap32(Temp)); - } - -private: - DiscIO::IBlobReader& m_rReader; -}; - - - - -CNANDContentLoader::CNANDContentLoader(const std::string& _rName) - : m_TitleID(-1) - , m_BootIndex(-1) - , m_Valid(false) -{ - if (File::IsDirectory(_rName.c_str())) - { - m_Valid = CreateFromDirectory(_rName); - } - else if (File::Exists(_rName.c_str())) - { - m_Valid = CreateFromWAD(_rName); - } - else - { -// _dbg_assert_msg_(BOOT, 0, "CNANDContentLoader loads neither folder nor file"); - } -} - -CNANDContentLoader::~CNANDContentLoader() -{ - for (size_t i=0; i 0) - { - u8* pTmpBuffer = new u8[_Size]; - _dbg_assert_msg_(BOOT, pTmpBuffer!=0, "WiiWAD: Cant allocate memory for WAD entry"); - - if (!_rReader.Read(_Offset, _Size, pTmpBuffer)) - { - ERROR_LOG(DISCIO, "WiiWAD: Could not read from file"); - PanicAlert("WiiWAD: Could not read from file"); - } - return pTmpBuffer; - } - return NULL; -} - -void CNANDContentLoader::GetKeyFromTicket(u8* pTicket, u8* pTicketKey) -{ - u8 CommonKey[16] = {0xeb,0xe4,0x2a,0x22,0x5e,0x85,0x93,0xe4,0x48,0xd9,0xc5,0x45,0x73,0x81,0xaa,0xf7}; - u8 IV[16]; - memset(IV, 0, sizeof IV); - memcpy(IV, pTicket + 0x01dc, 8); - AESDecode(CommonKey, IV, pTicket + 0x01bf, 16, pTicketKey); -} - -bool CNANDContentLoader::ParseTMD(u8* pDataApp, u32 pDataAppSize, u8* pTicket, u8* pTMD) -{ - u8 DecryptTitleKey[16]; - u8 IV[16]; - - GetKeyFromTicket(pTicket, DecryptTitleKey); - - u32 numEntries = Common::swap16(pTMD + 0x01de); - m_BootIndex = Common::swap16(pTMD + 0x01e0); - m_TitleID = Common::swap64(pTMD + 0x018C); - - u8* p = pDataApp; - - m_Content.resize(numEntries); - - for (u32 i=0; i 0) + { + u8* pTmpBuffer = new u8[_Size]; + _dbg_assert_msg_(BOOT, pTmpBuffer!=0, "WiiWAD: Cant allocate memory for WAD entry"); + + if (!_rReader.Read(_Offset, _Size, pTmpBuffer)) + { + ERROR_LOG(DISCIO, "WiiWAD: Could not read from file"); + PanicAlert("WiiWAD: Could not read from file"); + } + return pTmpBuffer; + } + return NULL; +} + +void CNANDContentLoader::GetKeyFromTicket(u8* pTicket, u8* pTicketKey) +{ + u8 CommonKey[16] = {0xeb,0xe4,0x2a,0x22,0x5e,0x85,0x93,0xe4,0x48,0xd9,0xc5,0x45,0x73,0x81,0xaa,0xf7}; + u8 IV[16]; + memset(IV, 0, sizeof IV); + memcpy(IV, pTicket + 0x01dc, 8); + AESDecode(CommonKey, IV, pTicket + 0x01bf, 16, pTicketKey); +} + +bool CNANDContentLoader::ParseTMD(u8* pDataApp, u32 pDataAppSize, u8* pTicket, u8* pTMD) +{ + u8 DecryptTitleKey[16]; + u8 IV[16]; + + GetKeyFromTicket(pTicket, DecryptTitleKey); + + u32 numEntries = Common::swap16(pTMD + 0x01de); + m_BootIndex = Common::swap16(pTMD + 0x01e0); + m_TitleID = Common::swap64(pTMD + 0x018C); + + u8* p = pDataApp; + + m_Content.resize(numEntries); + + for (u32 i=0; i -#include -#include - -#include "VideoCommon.h" -#include "Statistics.h" - -#include "VertexShaderManager.h" -#include "VertexLoader.h" -#include "VertexLoaderManager.h" - -static int s_attr_dirty; // bitfield - -static VertexLoader *g_VertexLoaders[8]; - -namespace VertexLoaderManager -{ - -typedef std::map VertexLoaderMap; -static VertexLoaderMap g_VertexLoaderMap; -// TODO - change into array of pointers. Keep a map of all seen so far. - -void Init() -{ - MarkAllDirty(); - for (int i = 0; i < 8; i++) - g_VertexLoaders[i] = NULL; -} - -void Shutdown() -{ - for (VertexLoaderMap::iterator iter = g_VertexLoaderMap.begin(); iter != g_VertexLoaderMap.end(); ++iter) - { - delete iter->second; - } - g_VertexLoaderMap.clear(); -} - -namespace { -struct entry { - std::string text; - u64 num_verts; - bool operator < (const entry &other) const { - return num_verts > other.num_verts; - } -}; -} - -void AppendListToString(std::string *dest) -{ - std::vector entries; - - size_t total_size = 0; - for (VertexLoaderMap::const_iterator iter = g_VertexLoaderMap.begin(); iter != g_VertexLoaderMap.end(); ++iter) - { - entry e; - iter->second->AppendToString(&e.text); - e.num_verts = iter->second->GetNumLoadedVerts(); - entries.push_back(e); - total_size += e.text.size() + 1; - } - sort(entries.begin(), entries.end()); - dest->reserve(dest->size() + total_size); - for (std::vector::const_iterator iter = entries.begin(); iter != entries.end(); ++iter) { - dest->append(iter->text); - } -} - -void MarkAllDirty() -{ - s_attr_dirty = 0xff; -} - -static void RefreshLoader(int vtx_attr_group) -{ - if ((s_attr_dirty >> vtx_attr_group) & 1) - { - VertexLoaderUID uid; - uid.InitFromCurrentState(vtx_attr_group); - VertexLoaderMap::iterator iter = g_VertexLoaderMap.find(uid); - if (iter != g_VertexLoaderMap.end()) - { - g_VertexLoaders[vtx_attr_group] = iter->second; - } - else - { - VertexLoader *loader = new VertexLoader(g_VtxDesc, g_VtxAttr[vtx_attr_group]); - g_VertexLoaderMap[uid] = loader; - g_VertexLoaders[vtx_attr_group] = loader; - INCSTAT(stats.numVertexLoaders); - } - } - s_attr_dirty &= ~(1 << vtx_attr_group); -} - -void RunVertices(int vtx_attr_group, int primitive, int count) -{ - if (!count) - return; - RefreshLoader(vtx_attr_group); - g_VertexLoaders[vtx_attr_group]->RunVertices(vtx_attr_group, primitive, count); -} - -int GetVertexSize(int vtx_attr_group) -{ - RefreshLoader(vtx_attr_group); - return g_VertexLoaders[vtx_attr_group]->GetVertexSize(); -} - -} // namespace - -void LoadCPReg(u32 sub_cmd, u32 value) -{ - switch (sub_cmd & 0xF0) - { - case 0x30: - VertexShaderManager::SetTexMatrixChangedA(value); - break; - - case 0x40: - VertexShaderManager::SetTexMatrixChangedB(value); - break; - - case 0x50: - g_VtxDesc.Hex &= ~0x1FFFF; // keep the Upper bits - g_VtxDesc.Hex |= value; - s_attr_dirty = 0xFF; - break; - - case 0x60: - g_VtxDesc.Hex &= 0x1FFFF; // keep the lower 17Bits - g_VtxDesc.Hex |= (u64)value << 17; - s_attr_dirty = 0xFF; - break; - - case 0x70: - _assert_((sub_cmd & 0x0F) < 8); - g_VtxAttr[sub_cmd & 7].g0.Hex = value; - s_attr_dirty |= 1 << (sub_cmd & 7); - break; - - case 0x80: - _assert_((sub_cmd & 0x0F) < 8); - g_VtxAttr[sub_cmd & 7].g1.Hex = value; - s_attr_dirty |= 1 << (sub_cmd & 7); - break; - - case 0x90: - _assert_((sub_cmd & 0x0F) < 8); - g_VtxAttr[sub_cmd & 7].g2.Hex = value; - s_attr_dirty |= 1 << (sub_cmd & 7); - break; - - // Pointers to vertex arrays in GC RAM - case 0xA0: - arraybases[sub_cmd & 0xF] = value; - cached_arraybases[sub_cmd & 0xF] = Memory_GetPtr(value); - break; - - case 0xB0: - arraystrides[sub_cmd & 0xF] = value & 0xFF; - break; - } -} - -void RecomputeCachedArraybases() -{ - for (int i = 0; i < 16; i++) - { - cached_arraybases[i] = Memory_GetPtr(arraybases[i]); - } -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include +#include +#include + +#include "VideoCommon.h" +#include "Statistics.h" + +#include "VertexShaderManager.h" +#include "VertexLoader.h" +#include "VertexLoaderManager.h" + +static int s_attr_dirty; // bitfield + +static VertexLoader *g_VertexLoaders[8]; + +namespace VertexLoaderManager +{ + +typedef std::map VertexLoaderMap; +static VertexLoaderMap g_VertexLoaderMap; +// TODO - change into array of pointers. Keep a map of all seen so far. + +void Init() +{ + MarkAllDirty(); + for (int i = 0; i < 8; i++) + g_VertexLoaders[i] = NULL; +} + +void Shutdown() +{ + for (VertexLoaderMap::iterator iter = g_VertexLoaderMap.begin(); iter != g_VertexLoaderMap.end(); ++iter) + { + delete iter->second; + } + g_VertexLoaderMap.clear(); +} + +namespace { +struct entry { + std::string text; + u64 num_verts; + bool operator < (const entry &other) const { + return num_verts > other.num_verts; + } +}; +} + +void AppendListToString(std::string *dest) +{ + std::vector entries; + + size_t total_size = 0; + for (VertexLoaderMap::const_iterator iter = g_VertexLoaderMap.begin(); iter != g_VertexLoaderMap.end(); ++iter) + { + entry e; + iter->second->AppendToString(&e.text); + e.num_verts = iter->second->GetNumLoadedVerts(); + entries.push_back(e); + total_size += e.text.size() + 1; + } + sort(entries.begin(), entries.end()); + dest->reserve(dest->size() + total_size); + for (std::vector::const_iterator iter = entries.begin(); iter != entries.end(); ++iter) { + dest->append(iter->text); + } +} + +void MarkAllDirty() +{ + s_attr_dirty = 0xff; +} + +static void RefreshLoader(int vtx_attr_group) +{ + if ((s_attr_dirty >> vtx_attr_group) & 1) + { + VertexLoaderUID uid; + uid.InitFromCurrentState(vtx_attr_group); + VertexLoaderMap::iterator iter = g_VertexLoaderMap.find(uid); + if (iter != g_VertexLoaderMap.end()) + { + g_VertexLoaders[vtx_attr_group] = iter->second; + } + else + { + VertexLoader *loader = new VertexLoader(g_VtxDesc, g_VtxAttr[vtx_attr_group]); + g_VertexLoaderMap[uid] = loader; + g_VertexLoaders[vtx_attr_group] = loader; + INCSTAT(stats.numVertexLoaders); + } + } + s_attr_dirty &= ~(1 << vtx_attr_group); +} + +void RunVertices(int vtx_attr_group, int primitive, int count) +{ + if (!count) + return; + RefreshLoader(vtx_attr_group); + g_VertexLoaders[vtx_attr_group]->RunVertices(vtx_attr_group, primitive, count); +} + +int GetVertexSize(int vtx_attr_group) +{ + RefreshLoader(vtx_attr_group); + return g_VertexLoaders[vtx_attr_group]->GetVertexSize(); +} + +} // namespace + +void LoadCPReg(u32 sub_cmd, u32 value) +{ + switch (sub_cmd & 0xF0) + { + case 0x30: + VertexShaderManager::SetTexMatrixChangedA(value); + break; + + case 0x40: + VertexShaderManager::SetTexMatrixChangedB(value); + break; + + case 0x50: + g_VtxDesc.Hex &= ~0x1FFFF; // keep the Upper bits + g_VtxDesc.Hex |= value; + s_attr_dirty = 0xFF; + break; + + case 0x60: + g_VtxDesc.Hex &= 0x1FFFF; // keep the lower 17Bits + g_VtxDesc.Hex |= (u64)value << 17; + s_attr_dirty = 0xFF; + break; + + case 0x70: + _assert_((sub_cmd & 0x0F) < 8); + g_VtxAttr[sub_cmd & 7].g0.Hex = value; + s_attr_dirty |= 1 << (sub_cmd & 7); + break; + + case 0x80: + _assert_((sub_cmd & 0x0F) < 8); + g_VtxAttr[sub_cmd & 7].g1.Hex = value; + s_attr_dirty |= 1 << (sub_cmd & 7); + break; + + case 0x90: + _assert_((sub_cmd & 0x0F) < 8); + g_VtxAttr[sub_cmd & 7].g2.Hex = value; + s_attr_dirty |= 1 << (sub_cmd & 7); + break; + + // Pointers to vertex arrays in GC RAM + case 0xA0: + arraybases[sub_cmd & 0xF] = value; + cached_arraybases[sub_cmd & 0xF] = Memory_GetPtr(value); + break; + + case 0xB0: + arraystrides[sub_cmd & 0xF] = value & 0xFF; + break; + } +} + +void RecomputeCachedArraybases() +{ + for (int i = 0; i < 16; i++) + { + cached_arraybases[i] = Memory_GetPtr(arraybases[i]); + } +} diff --git a/Source/Core/VideoCommon/Src/VideoLog.cpp b/Source/Core/VideoCommon/Src/VideoLog.cpp index 816d57be75..2a65ec135a 100644 --- a/Source/Core/VideoCommon/Src/VideoLog.cpp +++ b/Source/Core/VideoCommon/Src/VideoLog.cpp @@ -1,62 +1,62 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "VideoCommon.h" -#include -#include - -static FILE* pfLog = NULL; -void __Log(const char *fmt, ...) -{ - char* Msg = (char*)alloca(strlen(fmt)+512); - va_list ap; - - va_start( ap, fmt ); - vsnprintf( Msg, strlen(fmt)+512, fmt, ap ); - va_end( ap ); - - g_VideoInitialize.pLog(Msg, FALSE); - - if (pfLog == NULL) - pfLog = fopen(FULL_LOGS_DIR "oglgfx.txt", "w"); - - if (pfLog != NULL) - fwrite(Msg, strlen(Msg), 1, pfLog); -#ifdef _WIN32 -// DWORD tmp; -// WriteConsole(hConsole, Msg, (DWORD)strlen(Msg), &tmp, 0); -#else - //printf("%s", Msg); -#endif -} - -void __Log(int type, const char *fmt, ...) -{ - char* Msg = (char*)alloca(strlen(fmt)+512); - va_list ap; - - va_start( ap, fmt ); - vsnprintf( Msg, strlen(fmt)+512, fmt, ap ); - va_end( ap ); - - g_VideoInitialize.pLog(Msg, FALSE); - -#ifdef _WIN32 -// DWORD tmp; - // WriteConsole(hConsole, Msg, (DWORD)strlen(Msg), &tmp, 0); -#endif -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "VideoCommon.h" +#include +#include + +static FILE* pfLog = NULL; +void __Log(const char *fmt, ...) +{ + char* Msg = (char*)alloca(strlen(fmt)+512); + va_list ap; + + va_start( ap, fmt ); + vsnprintf( Msg, strlen(fmt)+512, fmt, ap ); + va_end( ap ); + + g_VideoInitialize.pLog(Msg, FALSE); + + if (pfLog == NULL) + pfLog = fopen(FULL_LOGS_DIR "oglgfx.txt", "w"); + + if (pfLog != NULL) + fwrite(Msg, strlen(Msg), 1, pfLog); +#ifdef _WIN32 +// DWORD tmp; +// WriteConsole(hConsole, Msg, (DWORD)strlen(Msg), &tmp, 0); +#else + //printf("%s", Msg); +#endif +} + +void __Log(int type, const char *fmt, ...) +{ + char* Msg = (char*)alloca(strlen(fmt)+512); + va_list ap; + + va_start( ap, fmt ); + vsnprintf( Msg, strlen(fmt)+512, fmt, ap ); + va_end( ap ); + + g_VideoInitialize.pLog(Msg, FALSE); + +#ifdef _WIN32 +// DWORD tmp; + // WriteConsole(hConsole, Msg, (DWORD)strlen(Msg), &tmp, 0); +#endif +} diff --git a/Source/Core/VideoCommon/Src/XFStructs.cpp b/Source/Core/VideoCommon/Src/XFStructs.cpp index 9f1bffdf74..b9d8770263 100644 --- a/Source/Core/VideoCommon/Src/XFStructs.cpp +++ b/Source/Core/VideoCommon/Src/XFStructs.cpp @@ -1,235 +1,235 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "Common.h" -#include "VideoCommon.h" -#include "XFMemory.h" -#include "CPMemory.h" -#include "NativeVertexWriter.h" -#include "VertexShaderManager.h" -#include "PixelShaderManager.h" - -// LoadXFReg 0x10 -void LoadXFReg(u32 transferSize, u32 baseAddress, u32 *pData) -{ - u32 address = baseAddress; - for (int i = 0; i < (int)transferSize; i++) - { - address = baseAddress + i; - - // Setup a Matrix - if (address < 0x1000) - { - VertexManager::Flush(); - VertexShaderManager::InvalidateXFRange(address, address + transferSize); - //PRIM_LOG("xfmem write: 0x%x-0x%x\n", address, address+transferSize); - - u32* p1 = &xfmem[address]; - memcpy_gc(p1, &pData[i], transferSize*4); - i += transferSize; - } - else if (address < 0x2000) - { - u32 data = pData[i]; - switch (address) - { - case 0x1000: // error - break; - case 0x1001: // diagnostics - break; - case 0x1002: // internal state 0 - break; - case 0x1003: // internal state 1 - break; - case 0x1004: // xf_clock - break; - case 0x1005: // clipdisable - if (data & 1) { // disable clipping detection - } - if (data & 2) { // disable trivial rejection - } - if (data & 4) { // disable cpoly clipping acceleration - } - break; - case 0x1006: //SetGPMetric - break; - case 0x1008: //__GXXfVtxSpecs, wrote 0004 - xfregs.hostinfo = *(INVTXSPEC*)&data; - break; - case 0x1009: //GXSetNumChans (no) - if ((u32)xfregs.nNumChans != (data & 3)) { - VertexManager::Flush(); - xfregs.nNumChans = data & 3; - } - break; - case 0x100a: //GXSetChanAmbientcolor - if (xfregs.colChans[0].ambColor != data) { - VertexManager::Flush(); - xfregs.colChans[0].ambColor = data; - VertexShaderManager::SetMaterialColor(0, data); - } - break; - case 0x100b: //GXSetChanAmbientcolor - if (xfregs.colChans[1].ambColor != data) { - VertexManager::Flush(); - xfregs.colChans[1].ambColor = data; - VertexShaderManager::SetMaterialColor(1, data); - } - break; - case 0x100c: //GXSetChanMatcolor (rgba) - if (xfregs.colChans[0].matColor != data) { - VertexManager::Flush(); - xfregs.colChans[0].matColor = data; - VertexShaderManager::SetMaterialColor(2, data); - } - break; - case 0x100d: //GXSetChanMatcolor (rgba) - if (xfregs.colChans[1].matColor != data) { - VertexManager::Flush(); - xfregs.colChans[1].matColor = data; - VertexShaderManager::SetMaterialColor(3, data); - } - break; - - case 0x100e: // color0 - if (xfregs.colChans[0].color.hex != (data & 0x7fff) ) { - VertexManager::Flush(); - xfregs.colChans[0].color.hex = data; - } - break; - case 0x100f: // color1 - if (xfregs.colChans[1].color.hex != (data & 0x7fff) ) { - VertexManager::Flush(); - xfregs.colChans[1].color.hex = data; - } - break; - case 0x1010: // alpha0 - if (xfregs.colChans[0].alpha.hex != (data & 0x7fff) ) { - VertexManager::Flush(); - xfregs.colChans[0].alpha.hex = data; - } - break; - case 0x1011: // alpha1 - if (xfregs.colChans[1].alpha.hex != (data & 0x7fff) ) { - VertexManager::Flush(); - xfregs.colChans[1].alpha.hex = data; - } - break; - case 0x1012: // dual tex transform - if (xfregs.bEnableDualTexTransform != (data & 1)) { - VertexManager::Flush(); - xfregs.bEnableDualTexTransform = data & 1; - } - break; - - case 0x1013: - case 0x1014: - case 0x1015: - case 0x1016: - case 0x1017: - DEBUG_LOG(VIDEO, "xf addr: %x=%x\n", address, data); - break; - case 0x1018: - //_assert_msg_(GX_XF, 0, "XF matrixindex0"); - VertexShaderManager::SetTexMatrixChangedA(data); //? - break; - case 0x1019: - //_assert_msg_(GX_XF, 0, "XF matrixindex1"); - VertexShaderManager::SetTexMatrixChangedB(data); //? - break; - - case 0x101a: - VertexManager::Flush(); - VertexShaderManager::SetViewport((float*)&pData[i]); - PixelShaderManager::SetViewport((float*)&pData[i]); - i += 6; - break; - - case 0x101c: // paper mario writes 16777216.0f, 1677721.75 - break; - case 0x101f: // paper mario writes 16777216.0f, 5033165.0f - break; - - case 0x1020: - VertexManager::Flush(); - VertexShaderManager::SetProjection((float*)&pData[i]); - i += 7; - return; - - case 0x103f: // GXSetNumTexGens - if ((u32)xfregs.numTexGens != data) { - VertexManager::Flush(); - xfregs.numTexGens = data; - } - break; - - case 0x1040: xfregs.texcoords[0].texmtxinfo.hex = data; break; - case 0x1041: xfregs.texcoords[1].texmtxinfo.hex = data; break; - case 0x1042: xfregs.texcoords[2].texmtxinfo.hex = data; break; - case 0x1043: xfregs.texcoords[3].texmtxinfo.hex = data; break; - case 0x1044: xfregs.texcoords[4].texmtxinfo.hex = data; break; - case 0x1045: xfregs.texcoords[5].texmtxinfo.hex = data; break; - case 0x1046: xfregs.texcoords[6].texmtxinfo.hex = data; break; - case 0x1047: xfregs.texcoords[7].texmtxinfo.hex = data; break; - - case 0x1048: - case 0x1049: - case 0x104a: - case 0x104b: - case 0x104c: - case 0x104d: - case 0x104e: - case 0x104f: - DEBUG_LOG(VIDEO, "xf addr: %x=%x\n", address, data); - break; - case 0x1050: xfregs.texcoords[0].postmtxinfo.hex = data; break; - case 0x1051: xfregs.texcoords[1].postmtxinfo.hex = data; break; - case 0x1052: xfregs.texcoords[2].postmtxinfo.hex = data; break; - case 0x1053: xfregs.texcoords[3].postmtxinfo.hex = data; break; - case 0x1054: xfregs.texcoords[4].postmtxinfo.hex = data; break; - case 0x1055: xfregs.texcoords[5].postmtxinfo.hex = data; break; - case 0x1056: xfregs.texcoords[6].postmtxinfo.hex = data; break; - case 0x1057: xfregs.texcoords[7].postmtxinfo.hex = data; break; - - default: - DEBUG_LOG(VIDEO, "xf addr: %x=%x\n", address, data); - break; - } - } - else if (address >= 0x4000) - { - // MessageBox(NULL, "1", "1", MB_OK); - //4010 __GXSetGenMode - } - } -} - -// TODO - verify that it is correct. Seems to work, though. -void LoadIndexedXF(u32 val, int array) -{ - int index = val >> 16; - int address = val & 0xFFF; //check mask - int size = ((val >> 12) & 0xF) + 1; - //load stuff from array to address in xf mem - - VertexManager::Flush(); - VertexShaderManager::InvalidateXFRange(address, address+size); - //PRIM_LOG("xfmem iwrite: 0x%x-0x%x\n", address, address+size); - - for (int i = 0; i < size; i++) - xfmem[address + i] = Memory_Read_U32(arraybases[array] + arraystrides[array]*index + i*4); -} +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Common.h" +#include "VideoCommon.h" +#include "XFMemory.h" +#include "CPMemory.h" +#include "NativeVertexWriter.h" +#include "VertexShaderManager.h" +#include "PixelShaderManager.h" + +// LoadXFReg 0x10 +void LoadXFReg(u32 transferSize, u32 baseAddress, u32 *pData) +{ + u32 address = baseAddress; + for (int i = 0; i < (int)transferSize; i++) + { + address = baseAddress + i; + + // Setup a Matrix + if (address < 0x1000) + { + VertexManager::Flush(); + VertexShaderManager::InvalidateXFRange(address, address + transferSize); + //PRIM_LOG("xfmem write: 0x%x-0x%x\n", address, address+transferSize); + + u32* p1 = &xfmem[address]; + memcpy_gc(p1, &pData[i], transferSize*4); + i += transferSize; + } + else if (address < 0x2000) + { + u32 data = pData[i]; + switch (address) + { + case 0x1000: // error + break; + case 0x1001: // diagnostics + break; + case 0x1002: // internal state 0 + break; + case 0x1003: // internal state 1 + break; + case 0x1004: // xf_clock + break; + case 0x1005: // clipdisable + if (data & 1) { // disable clipping detection + } + if (data & 2) { // disable trivial rejection + } + if (data & 4) { // disable cpoly clipping acceleration + } + break; + case 0x1006: //SetGPMetric + break; + case 0x1008: //__GXXfVtxSpecs, wrote 0004 + xfregs.hostinfo = *(INVTXSPEC*)&data; + break; + case 0x1009: //GXSetNumChans (no) + if ((u32)xfregs.nNumChans != (data & 3)) { + VertexManager::Flush(); + xfregs.nNumChans = data & 3; + } + break; + case 0x100a: //GXSetChanAmbientcolor + if (xfregs.colChans[0].ambColor != data) { + VertexManager::Flush(); + xfregs.colChans[0].ambColor = data; + VertexShaderManager::SetMaterialColor(0, data); + } + break; + case 0x100b: //GXSetChanAmbientcolor + if (xfregs.colChans[1].ambColor != data) { + VertexManager::Flush(); + xfregs.colChans[1].ambColor = data; + VertexShaderManager::SetMaterialColor(1, data); + } + break; + case 0x100c: //GXSetChanMatcolor (rgba) + if (xfregs.colChans[0].matColor != data) { + VertexManager::Flush(); + xfregs.colChans[0].matColor = data; + VertexShaderManager::SetMaterialColor(2, data); + } + break; + case 0x100d: //GXSetChanMatcolor (rgba) + if (xfregs.colChans[1].matColor != data) { + VertexManager::Flush(); + xfregs.colChans[1].matColor = data; + VertexShaderManager::SetMaterialColor(3, data); + } + break; + + case 0x100e: // color0 + if (xfregs.colChans[0].color.hex != (data & 0x7fff) ) { + VertexManager::Flush(); + xfregs.colChans[0].color.hex = data; + } + break; + case 0x100f: // color1 + if (xfregs.colChans[1].color.hex != (data & 0x7fff) ) { + VertexManager::Flush(); + xfregs.colChans[1].color.hex = data; + } + break; + case 0x1010: // alpha0 + if (xfregs.colChans[0].alpha.hex != (data & 0x7fff) ) { + VertexManager::Flush(); + xfregs.colChans[0].alpha.hex = data; + } + break; + case 0x1011: // alpha1 + if (xfregs.colChans[1].alpha.hex != (data & 0x7fff) ) { + VertexManager::Flush(); + xfregs.colChans[1].alpha.hex = data; + } + break; + case 0x1012: // dual tex transform + if (xfregs.bEnableDualTexTransform != (data & 1)) { + VertexManager::Flush(); + xfregs.bEnableDualTexTransform = data & 1; + } + break; + + case 0x1013: + case 0x1014: + case 0x1015: + case 0x1016: + case 0x1017: + DEBUG_LOG(VIDEO, "xf addr: %x=%x\n", address, data); + break; + case 0x1018: + //_assert_msg_(GX_XF, 0, "XF matrixindex0"); + VertexShaderManager::SetTexMatrixChangedA(data); //? + break; + case 0x1019: + //_assert_msg_(GX_XF, 0, "XF matrixindex1"); + VertexShaderManager::SetTexMatrixChangedB(data); //? + break; + + case 0x101a: + VertexManager::Flush(); + VertexShaderManager::SetViewport((float*)&pData[i]); + PixelShaderManager::SetViewport((float*)&pData[i]); + i += 6; + break; + + case 0x101c: // paper mario writes 16777216.0f, 1677721.75 + break; + case 0x101f: // paper mario writes 16777216.0f, 5033165.0f + break; + + case 0x1020: + VertexManager::Flush(); + VertexShaderManager::SetProjection((float*)&pData[i]); + i += 7; + return; + + case 0x103f: // GXSetNumTexGens + if ((u32)xfregs.numTexGens != data) { + VertexManager::Flush(); + xfregs.numTexGens = data; + } + break; + + case 0x1040: xfregs.texcoords[0].texmtxinfo.hex = data; break; + case 0x1041: xfregs.texcoords[1].texmtxinfo.hex = data; break; + case 0x1042: xfregs.texcoords[2].texmtxinfo.hex = data; break; + case 0x1043: xfregs.texcoords[3].texmtxinfo.hex = data; break; + case 0x1044: xfregs.texcoords[4].texmtxinfo.hex = data; break; + case 0x1045: xfregs.texcoords[5].texmtxinfo.hex = data; break; + case 0x1046: xfregs.texcoords[6].texmtxinfo.hex = data; break; + case 0x1047: xfregs.texcoords[7].texmtxinfo.hex = data; break; + + case 0x1048: + case 0x1049: + case 0x104a: + case 0x104b: + case 0x104c: + case 0x104d: + case 0x104e: + case 0x104f: + DEBUG_LOG(VIDEO, "xf addr: %x=%x\n", address, data); + break; + case 0x1050: xfregs.texcoords[0].postmtxinfo.hex = data; break; + case 0x1051: xfregs.texcoords[1].postmtxinfo.hex = data; break; + case 0x1052: xfregs.texcoords[2].postmtxinfo.hex = data; break; + case 0x1053: xfregs.texcoords[3].postmtxinfo.hex = data; break; + case 0x1054: xfregs.texcoords[4].postmtxinfo.hex = data; break; + case 0x1055: xfregs.texcoords[5].postmtxinfo.hex = data; break; + case 0x1056: xfregs.texcoords[6].postmtxinfo.hex = data; break; + case 0x1057: xfregs.texcoords[7].postmtxinfo.hex = data; break; + + default: + DEBUG_LOG(VIDEO, "xf addr: %x=%x\n", address, data); + break; + } + } + else if (address >= 0x4000) + { + // MessageBox(NULL, "1", "1", MB_OK); + //4010 __GXSetGenMode + } + } +} + +// TODO - verify that it is correct. Seems to work, though. +void LoadIndexedXF(u32 val, int array) +{ + int index = val >> 16; + int address = val & 0xFFF; //check mask + int size = ((val >> 12) & 0xF) + 1; + //load stuff from array to address in xf mem + + VertexManager::Flush(); + VertexShaderManager::InvalidateXFRange(address, address+size); + //PRIM_LOG("xfmem iwrite: 0x%x-0x%x\n", address, address+size); + + for (int i = 0; i < size; i++) + xfmem[address + i] = Memory_Read_U32(arraybases[array] + arraystrides[array]*index + i*4); +} diff --git a/Source/Core/VideoCommon/Src/XFStructs.h b/Source/Core/VideoCommon/Src/XFStructs.h index 6e06efa010..005c20c1d5 100644 --- a/Source/Core/VideoCommon/Src/XFStructs.h +++ b/Source/Core/VideoCommon/Src/XFStructs.h @@ -1,18 +1,18 @@ -// Copyright (C) 2003-2008 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include "XFMemory.h" +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "XFMemory.h" diff --git a/Source/TestSuite/EXI/source/dolphintest_exi.cpp b/Source/TestSuite/EXI/source/dolphintest_exi.cpp index e559e86bbd..3b7fb1c3bc 100644 --- a/Source/TestSuite/EXI/source/dolphintest_exi.cpp +++ b/Source/TestSuite/EXI/source/dolphintest_exi.cpp @@ -1,103 +1,103 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -static void *xfb = NULL; -u32 first_frame = 1; -GXRModeObj *rmode; - -void Initialise(); - -int main() -{ - Initialise(); - - while(1) - { - s32 Size; - s32 SSize; - u32 ID; - s32 getIDerr; - s32 CARDerr; - s32 EXIerr; - VIDEO_ClearFrameBuffer(rmode, xfb, 0); - - // Can't use printf since Dolphin overrides it - std::cout<<"\x1b[0;0H"; // Position the cursor (at 0, 0) - for (int channel = 0; channel < EXI_CHANNEL_MAX; ++channel) - for (int device = 0; device < EXI_DEVICE_MAX; ++device) - { - if (getIDerr = EXI_GetID(channel, device, &ID) == 1) - { - std::cout<<"Channel "<= 0) - { - std::cout<<"\tMemcard has a size of "<fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ); - - // Set up the video registers with the chosen mode - VIDEO_Configure(rmode); - - // Tell the video hardware where our display memory is - VIDEO_SetNextFramebuffer(xfb); - - // Make the display visible - VIDEO_SetBlack(FALSE); - - // Flush the video register changes to the hardware - VIDEO_Flush(); - - // Wait for Video setup to complete - VIDEO_WaitVSync(); - if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync(); -} +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static void *xfb = NULL; +u32 first_frame = 1; +GXRModeObj *rmode; + +void Initialise(); + +int main() +{ + Initialise(); + + while(1) + { + s32 Size; + s32 SSize; + u32 ID; + s32 getIDerr; + s32 CARDerr; + s32 EXIerr; + VIDEO_ClearFrameBuffer(rmode, xfb, 0); + + // Can't use printf since Dolphin overrides it + std::cout<<"\x1b[0;0H"; // Position the cursor (at 0, 0) + for (int channel = 0; channel < EXI_CHANNEL_MAX; ++channel) + for (int device = 0; device < EXI_DEVICE_MAX; ++device) + { + if (getIDerr = EXI_GetID(channel, device, &ID) == 1) + { + std::cout<<"Channel "<= 0) + { + std::cout<<"\tMemcard has a size of "<fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ); + + // Set up the video registers with the chosen mode + VIDEO_Configure(rmode); + + // Tell the video hardware where our display memory is + VIDEO_SetNextFramebuffer(xfb); + + // Make the display visible + VIDEO_SetBlack(FALSE); + + // Flush the video register changes to the hardware + VIDEO_Flush(); + + // Wait for Video setup to complete + VIDEO_WaitVSync(); + if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync(); +}