wxgui: more of the slowly progressing.

* Implemented internationalization (i18n) framework.
 * Made a pretty configuration dialog box!
 * Many minor bugfixes.
 * Removed most of the old Win32 and Linux/GTK gui code because it was causing gettext cataloging to grab about 500 non-relevant strings (can always reference trunk for them anyway).

git-svn-id: http://pcsx2.googlecode.com/svn/branches/wxgui@1484 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2009-07-11 08:31:38 +00:00
commit 3c195e9f9a
139 changed files with 4226 additions and 11338 deletions

View File

@ -408,6 +408,10 @@
RelativePath="..\..\include\Utilities\win_memzero.h"
>
</File>
<File
RelativePath="..\..\include\Utilities\WinVersion.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"

View File

@ -1,5 +1,5 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2008 Pcsx2 Team
* Copyright (C) 2002-2009 Pcsx2 Team
*
* 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
@ -16,11 +16,28 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __MCDDLGS_H__
#define __MCDDLGS_H__
#pragma once
#include "Linux.h"
#include "RedtapeWindows.h"
#include <winnt.h>
GtkWidget *MemDlg;
namespace Win32
{
class RealVersionInfo
{
protected:
HMODULE m_kernel32;
wxString m_VersionString;
#endif
public:
~RealVersionInfo();
RealVersionInfo();
bool IsVista() const;
bool IsXP() const;
const wxString& GetVersionString() const;
protected:
void InitVersionString();
};
}

View File

@ -18,6 +18,10 @@
#include "../PrecompiledHeader.h"
#include "RedtapeWindows.h"
#include "WinVersion.h"
#include <shlwapi.h> // for IsOS()
static LARGE_INTEGER lfreq;
@ -37,3 +41,149 @@ u64 GetCPUTicks()
QueryPerformanceCounter( &count );
return count.QuadPart;
}
//////////////////////////////////////////////////////////////////////////////////////////
static const char* GetVersionName( DWORD minorVersion, DWORD majorVersion )
{
switch( majorVersion )
{
case 6:
return "Vista";
break;
case 5:
switch( minorVersion )
{
case 0:
return "2000";
break;
case 1:
return "XP";
break;
case 2:
return "Server 2003";
break;
default:
return "2000/XP";
}
break;
case 4:
switch( minorVersion )
{
case 0:
return "95";
break;
case 10:
return "98";
break;
case 90:
return "ME";
break;
default:
return "95/98/ME";
}
break;
case 3:
return "32S";
break;
default:
return "Unknown";
}
}
void Win32::RealVersionInfo::InitVersionString()
{
DWORD version = GetVersion();
int majorVersion = (DWORD)(LOBYTE(LOWORD(version)));
int minorVersion = (DWORD)(HIBYTE(LOWORD(version)));
RealVersionInfo really;
wxString verName( wxString::FromAscii( GetVersionName( minorVersion, majorVersion ) ) );
bool IsCompatMode = false;
if( really.IsVista() )
{
m_VersionString = L"Windows Vista";
if( verName != L"Vista" )
{
if( verName == L"Unknown" )
m_VersionString += L" or Newer";
else
IsCompatMode = true;
}
m_VersionString += wxsFormat( L" v%d.%d", majorVersion, minorVersion );
if( IsOS( OS_WOW6432 ) )
m_VersionString += L" (64-bit)";
else
m_VersionString += L" (32-bit)";
}
else if( really.IsXP() )
{
m_VersionString = wxsFormat( L"Windows XP v%d.%d", majorVersion, minorVersion );
if( IsOS( OS_WOW6432 ) )
m_VersionString += L" (64-bit)";
else
m_VersionString += L" (32-bit)";
if( verName != L"XP" )
IsCompatMode = true;
}
else
{
m_VersionString = L"Windows " + verName;
}
if( IsCompatMode )
m_VersionString += wxsFormat( L" [compatibility mode, running as Windows %s]", verName );
}
Win32::RealVersionInfo::~RealVersionInfo()
{
if( m_kernel32 != NULL )
FreeLibrary( m_kernel32 );
}
Win32::RealVersionInfo::RealVersionInfo() :
m_kernel32( LoadLibrary( L"kernel32" ) )
{
InitVersionString();
}
bool Win32::RealVersionInfo::IsVista() const
{
if( m_kernel32 == NULL ) return false;
// CreateThreadpoolWait is a good pick -- it's not likely to exist on older OS's
// GetLocaleInfoEx is also good -- two picks are better than one, just in case
// one of the APIs becomes available in a future XP service pack.
return
( GetProcAddress( m_kernel32, "CreateThreadpoolWait" ) != NULL ) &&
( GetProcAddress( m_kernel32, "GetLocaleInfoEx" ) != NULL );
}
bool Win32::RealVersionInfo::IsXP() const
{
return ( GetProcAddress( m_kernel32, "GetNativeSystemInfo" ) != NULL );
}
const wxString& Win32::RealVersionInfo::GetVersionString() const
{
return m_VersionString;
}

View File

@ -60,12 +60,12 @@ public:
struct FolderOptions
{
wxDirName Plugins;
wxDirName Settings;
wxDirName Bios;
wxDirName Snapshots;
wxDirName Savestates;
wxDirName MemoryCards;
wxDirName Logs;
wxDirName Dumps;
void LoadSave( IniInterface& conf );
};
@ -190,9 +190,13 @@ public:
FullpathHelpers Files;
bool UseAdminMode; // dictates if the program uses /home/user or /cwd for the program data
wxPoint MainGuiPosition;
bool CdvdVerboseReads; // enables cdvd read activity verbosely dumped to the console
// Current language in use (correlates to a wxWidgets wxLANGUAGE specifier)
int LanguageId;
// String value describing the desktop theme to use for pcsk2 (icons and background images)
// The theme name is used to look up files in the themes folder (relative to the executable).
wxString DeskTheme;
@ -220,6 +224,9 @@ public:
public:
void Load();
void Save();
void Apply();
void LoadSaveUserMode( IniInterface& ini );
protected:
void LoadSave( IniInterface& ini );

View File

@ -211,9 +211,9 @@ void iDumpBlock( int startpc, u8 * ptr )
Console::Status( "dump1 %x:%x, %x", params startpc, pc, cpuRegs.cycle );
g_Conf.Folders.Dumps.Mkdir();
g_Conf.Folders.Logs.Mkdir();
AsciiFile eff(
Path::Combine( g_Conf.Folders.Dumps, wxsFormat(L"R5900dump%.8X.txt", startpc) ),
Path::Combine( g_Conf.Folders.Logs, wxsFormat(L"R5900dump%.8X.txt", startpc) ),
wxFile::write
);

View File

@ -530,9 +530,10 @@ public:
/// hash keys. The <see cref="HashMap" /> class isn't suited to the task since it requires the key type to
/// include a set of unary methods. Obviously predicates cannot be added to fundamentals after the fact. :)
/// Note:
/// Do not use <c>char *</c> or <c>wchar_t *</c> as key types. Use <c>std::string</c> and <c>std::wstring</c> instead,
/// as performance of those types will generally be superior. For that matter, don't use this class at all!
/// Use the string-specialized classes <see cref="Dictionary" /> and <see cref="UnicodeDictionary" />.
/// Do not use <c>char *</c> or <c>wchar_t *</c> as key types. Use <c>std::string</c> and <c>std::wstring</c>
/// instead, as performance of those types will generally be superior due to string length caching. For that
/// matter, don't use this class at all! Use the string-specialized classes <see cref="Dictionary" /> and
/// <see cref="UnicodeDictionary" />.
/// </remarks>
template< class Key, class T >
class HashMap : public google::dense_hash_map<Key, T, CommonHashClass>
@ -547,7 +548,7 @@ public:
/// Both the <c>emptyKey</c>a nd c>deletedKey</c> parameters must be unique values that
/// are *not* used as actual values in the set.
/// </remarks>
HashMap( Key emptyKey, Key deletedKey, int initialCapacity=33 ) :
HashMap( const Key& emptyKey, const Key& deletedKey, int initialCapacity=33 ) :
google::dense_hash_map<Key, T, CommonHashClass>( initialCapacity )
{
set_empty_key( emptyKey );
@ -589,7 +590,7 @@ class Dictionary : public HashMap<std::string, T>
public:
virtual ~Dictionary() {}
Dictionary( int initialCapacity=33, std::string emptyKey = "@@-EMPTY-@@", std::string deletedKey = "@@-DELETED-@@" ) :
Dictionary( int initialCapacity=33, const std::string& emptyKey = "@@-EMPTY-@@", const std::string& deletedKey = "@@-DELETED-@@" ) :
HashMap( emptyKey, deletedKey, initialCapacity)
{
}

File diff suppressed because it is too large Load Diff

View File

@ -1,162 +0,0 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2008 Pcsx2 Team
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __LINUX_H__
#define __LINUX_H__
#include "PrecompiledHeader.h"
#include "Paths.h"
#include "Common.h"
#include "HostGui.h"
//For CpuDlg
#include "Counters.h"
// For AdvancedDialog
#include "x86/ix86/ix86.h"
#include <dirent.h>
#include <dlfcn.h>
#include <X11/keysym.h>
#include <gtk/gtk.h>
#include <glib/gthread.h>
#include <glib.h>
#ifdef __cplusplus
extern "C"
{
#endif
#include "support.h"
#include "callbacks.h"
#include "interface.h"
#ifdef __cplusplus
}
#endif
extern void SaveConfig();
extern int LoadConfig();
extern void SysRestorableReset();
extern int Pcsx2Configure();
extern GtkWidget *MainWindow;
char cfgfile[g_MaxPath];
#define is_checked(main_widget, widget_name) (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(main_widget, widget_name))))
#define set_checked(main_widget,widget_name, state) gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(lookup_widget(main_widget, widget_name)), state)
#define set_flag(v, flag, value) if (value == TRUE) v |= flag; else v &= flag;
#define get_flag(v,flag) ((v & (1 << flag)) != 0)
char ee_log_names[17][32] =
{
"Cpu Log",
"Mem Log",
"HW Log",
"Dma Log",
"Bios Log",
"Elf Log",
"Fpu Log",
"MMI Log",
"VU0 Log",
"Cop0 Log",
"Vif Log",
"SPR Log",
"GIF Log",
"Sif Log",
"IPU Log",
"VU Micro Log",
"RPC Log"
};
char iop_log_names[9][32] =
{
"IOP Log",
"Mem Log",
"HW Log",
"Bios Log",
"Dma Log",
"Pad Log",
"Gte Log",
"Cdr Log",
"GPU Log"
};
char vu_stealing_labels[5][256] =
{
"0: No speedup.",
"1: Slight speedup, should work with most games.",
"2: Moderate speedup, should work with most games with minor problems.",
"3: Large speedup, may break many games and make others skip frames.",
"4: Very large speedup, will break games in interesting ways."
};
char ee_cycle_labels[3][256] =
{
"Default Cycle Rate: Most compatible option - recommended for everyone with high-end machines.",
"x1.5 Cycle Rate: Moderate speedup, and works well with most games.",
"x2 Cycle Rate: Big speedup! Works well with many games."
};
//Tri-Ace - IDC_GAMEFIX2
#define FLAG_VU_ADD_SUB 0x1
// Persona3/4 - IDC_GAMEFIX4
#define FLAG_VU_CLIP 0x2
// Digimon Rumble Arena - IDC_GAMEFIX3
#define FLAG_FPU_Compare 0x4
//Tales of Destiny - IDC_GAMEFIX5
#define FLAG_FPU_MUL 0x8
//Fatal Frame
#define FLAG_DMAExec 0x10
//Erementar Gerad
#define FLAG_XGKick 0x20
#define FLAG_VU_NO_OVERFLOW 0x2
#define FLAG_VU_EXTRA_OVERFLOW 0x40
#define FLAG_FPU_NO_OVERFLOW 0x800
#define FLAG_FPU_EXTRA_OVERFLOW 0x1000
#define FLAG_EE_2_SYNC 0x1
#define FLAG_IOP_2_SYNC 0x10
#define FLAG_TRIPLE_SYNC 0x20
#define FLAG_ESC 0x400
#define FLAG_ROUND_NEAR 0x0000
#define FLAG_ROUND_NEGATIVE 0x2000
#define FLAG_ROUND_POSITIVE 0x4000
#define FLAG_ROUND_ZERO 0x6000
#define FLAG_FLUSH_ZERO 0x8000
#define FLAG_DENORMAL_ZERO 0x0040
#define FLAG_VU_CLAMP_NONE 0x0
#define FLAG_VU_CLAMP_NORMAL 0x1
#define FLAG_VU_CLAMP_EXTRA 0x3
#define FLAG_VU_CLAMP_EXTRA_PRESERVE 0x7
#define FLAG_EE_CLAMP_NONE 0x0
#define FLAG_EE_CLAMP_NORMAL 0x1
#define FLAG_EE_CLAMP_EXTRA_PRESERVE 0x3
#define FLAG_EE_CLAMP_FULL 0x7
#endif /* __LINUX_H__ */

View File

@ -1,147 +0,0 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 Pcsx2 Team
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "Linux.h"
#define COLOR_RESET "\033[0m"
// Linux Note : The Linux Console is pretty simple. It just dumps to the stdio!
// (no console open/close/title stuff tho, so those functions are dummies)
// Yeah, haven't really seen a need to add a console window, though I might
// at some point. --arcum42
namespace Console
{
static const char *tbl_color_codes[] =
{
"\033[30m" // black
, "\033[31m" // red
, "\033[32m" // green
, "\033[33m" // yellow
, "\033[34m" // blue
, "\033[35m" // magenta
, "\033[36m" // cyan
, "\033[37m" // white!
};
void SetTitle(const string& title)
{
}
void Open()
{
}
void Close()
{
}
__forceinline bool __fastcall Newline()
{
if (Config.PsxOut)
printf("\n");
if (emuLog != NULL)
{
fprintf(emuLog,"\n");
fflush(emuLog);
}
return false;
}
__forceinline bool __fastcall Write(const char* fmt)
{
// By using fputs, append a newline automatically.
if (Config.PsxOut) fputs(fmt, stdout);
// Color changing should not use this function, as we don't want the color codes logged, or new lines inserted.
if (emuLog != NULL) fputs(fmt, emuLog);
return false;
}
void __fastcall SetColor(Colors color)
{
// Don't log the color change, and don't insert a new line afterwards.
printf(tbl_color_codes[color]);
}
void ClearColor()
{
// Don't log the color change, and don't insert a new line afterwards.
printf(COLOR_RESET);
}
}
namespace Msgbox
{
bool Alert(const char* fmt)
{
GtkWidget *dialog;
if (g_Startup.NoGui)
{
Console::Error(fmt);
return false;
}
dialog = gtk_message_dialog_new(GTK_WINDOW(MainWindow),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_OK, fmt);
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
return false;
}
bool Alert(const char* fmt, VARG_PARAM dummy, ...)
{
GtkWidget *dialog;
string msg;
va_list list;
va_start(list, dummy);
vssprintf(msg, fmt, list);
va_end(list);
// fixme: using NULL terminators on std::string might work, but are technically "incorrect."
// This should use one of the std::string trimming functions instead.
if (msg[msg.length()-1] == '\n')
msg[msg.length()-1] = 0;
if (g_Startup.NoGui)
{
Console::Error(msg.c_str());
return false;
}
dialog = gtk_message_dialog_new(GTK_WINDOW(MainWindow),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_OK, msg.c_str());
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
return false;
}
}

View File

@ -1,534 +0,0 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 Pcsx2 Team
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "LnxMain.h"
using namespace R5900;
DIR *dir;
GtkWidget *FileSel;
GtkWidget *MsgDlg;
const char* g_pRunGSState = NULL;
int efile = 0;
char elfname[g_MaxPath];
char MAIN_DIR[g_MaxPath];
int main(int argc, char *argv[])
{
char *file = NULL;
char elfname[g_MaxPath];
efile = 0;
getcwd(MAIN_DIR, ArraySize(MAIN_DIR)); /* store main dir */
Console::Notice("MAIN_DIR is %s", params MAIN_DIR);
#ifdef ENABLE_NLS
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, "Langs");
textdomain(PACKAGE);
#endif
// Note: Config.InisDir won't do anything till we set up windows and the plugins to use it.
#ifndef LOCAL_PLUGIN_INIS
mkdir(DEFAULT_INIS_DIR, 0755);
sprintf(Config.InisDir, "%s/%s/", MAIN_DIR, DEFAULT_INIS_DIR);
sprintf(cfgfile, "%s/pcsx2.cfg", Config.InisDir);
#else
mkdir("~/.pcsx2");
chdir("~/.pcsx2");
mkdir(DEFAULT_INIS_DIR, 0755);
sprintf(Config.InisDir, "~/.pcsx2/%s/", DEFAULT_INIS_DIR);
sprintf(cfgfile, "%s/pcsx2.cfg", Config.InisDir);
chdir(MAIN_DIR);
#endif
#ifdef PCSX2_DEVBUILD
memset(&g_Startup, 0, sizeof(g_Startup));
#endif
if (!ParseCommandLine(argc, argv, file)) return 0;
// make gtk thread safe if using MTGS
if (CHECK_MULTIGS)
{
g_thread_init(NULL);
gdk_threads_init();
}
if (!g_Startup.NoGui)
{
gtk_init(NULL, NULL);
}
if (LoadConfig() == -1)
{
memset(&Config, 0, sizeof(Config));
sprintf(Config.BiosDir, "%s/%s/", MAIN_DIR, DEFAULT_BIOS_DIR);
sprintf(Config.PluginsDir, "%s/%s/", MAIN_DIR, DEFAULT_PLUGINS_DIR);
sprintf(Config.Mcd[0].Filename, "%s/%s/%s", MAIN_DIR, MEMCARDS_DIR, DEFAULT_MEMCARD1);
sprintf(Config.Mcd[1].Filename, "%s/%s/%s", MAIN_DIR, MEMCARDS_DIR, DEFAULT_MEMCARD2);
Config.Mcd[0].Enabled = 1;
Config.Mcd[1].Enabled = 1;
Config.McdEnableEject = 1;
Config.Patch = 0;
Config.PsxOut = 1;
Config.Options = PCSX2_EEREC | PCSX2_VU0REC | PCSX2_VU1REC | PCSX2_FRAMELIMIT_LIMIT;
Config.sseMXCSR = DEFAULT_sseMXCSR;
Config.sseVUMXCSR = DEFAULT_sseVUMXCSR;
Config.eeOptions = DEFAULT_eeOptions;
Config.vuOptions = DEFAULT_vuOptions;
Msgbox::Alert("Pcsx2 needs to be configured");
Pcsx2Configure();
LoadConfig();
}
InitLanguages();
if (Config.PsxOut)
{
// output the help commands
Console::WriteLn("\tF1 - save state");
Console::WriteLn("\t(Shift +) F2 - cycle states");
Console::WriteLn("\tF3 - load state");
#ifdef PCSX2_DEVBUILD
Console::WriteLn("\tF10 - dump performance counters");
Console::WriteLn("\tF11 - save GS state");
Console::WriteLn("\tF12 - dump hardware registers");
#endif
}
if (!SysInit()) return 1;
#ifdef PCSX2_DEVBUILD
if (g_pRunGSState)
{
LoadGSState(g_pRunGSState);
SysClose();
return 0;
}
#endif
if (!g_Startup.NoGui && (file == NULL))
{
StartGui();
return 0;
}
if (OpenPlugins(file) == -1) return -1;
SysReset();
cpuExecuteBios();
if (file) strcpy(elfname, file);
if (!efile) efile = GetPS2ElfName(elfname);
loadElfFile(elfname);
//ExecuteCpu();
return 0;
}
void InitLanguages()
{
char *lang;
int i = 1;
if (Config.Lang[0] == 0)
{
strcpy(Config.Lang, "en");
}
langs = (_langs*)malloc(sizeof(_langs));
strcpy(langs[0].lang, "en");
dir = opendir(LANGS_DIR);
while ((lang = GetLanguageNext()) != NULL)
{
langs = (_langs*)realloc(langs, sizeof(_langs) * (i + 1));
strcpy(langs[i].lang, lang);
i++;
}
CloseLanguages();
langsMax = i;
}
char *GetLanguageNext()
{
struct dirent *ent;
if (dir == NULL) return NULL;
for (;;)
{
ent = readdir(dir);
if (ent == NULL) return NULL;
if (!strcmp(ent->d_name, ".")) continue;
if (!strcmp(ent->d_name, "..")) continue;
break;
}
return ent->d_name;
}
void CloseLanguages()
{
if (dir) closedir(dir);
}
void ChangeLanguage(char *lang)
{
strcpy(Config.Lang, lang);
SaveConfig();
}
void OnMsg_Ok()
{
gtk_widget_destroy(MsgDlg);
gtk_main_quit();
}
void On_Dialog_Cancelled(GtkButton* button, gpointer user_data)
{
gtk_widget_destroy((GtkWidget*)gtk_widget_get_toplevel((GtkWidget*)button));
gtk_widget_set_sensitive(MainWindow, TRUE);
gtk_main_quit();
}
void On_Dialog_Close(GtkDialog* dialog, gpointer user_data)
{
gtk_widget_set_sensitive(MainWindow, TRUE);
}
void RefreshMenuSlots()
{
GtkWidget *Item;
char str[g_MaxPath], str2[g_MaxPath];
for (int i = 0; i < 5; i++)
{
sprintf(str, "load_slot_%d", i);
sprintf(str2, "save_slot_%d", i);
Item = lookup_widget(MainWindow, str);
if GTK_IS_WIDGET(Item)
gtk_widget_set_sensitive(Item, Slots[i]);
else
Console::Error("No such widget: %s", params str);
Item = lookup_widget(MainWindow, str2);
gtk_widget_set_sensitive(Item, (ElfCRC != 0));
}
}
void StartGui()
{
GtkWidget *Menu;
GtkWidget *Item;
u32 i;
add_pixmap_directory(".pixmaps");
MainWindow = create_MainWindow();
#ifdef PCSX2_DEVBUILD
gtk_window_set_title(GTK_WINDOW(MainWindow), "PCSX2 "PCSX2_VERSION" "SVN_REV);
#else
gtk_window_set_title(GTK_WINDOW(MainWindow), "PCSX2 "PCSX2_VERSION);
#endif
// status bar
pStatusBar = gtk_statusbar_new();
gtk_box_pack_start(GTK_BOX(lookup_widget(MainWindow, "status_box")), pStatusBar, TRUE, TRUE, 0);
gtk_widget_show(pStatusBar);
HostGui::SetStatusMsg( "F1 - save, F2 - next state, Shift+F2 - prev state, F3 - load, F8 - snapshot");
// add all the languages
Item = lookup_widget(MainWindow, "GtkMenuItem_Language");
Menu = gtk_menu_new();
gtk_menu_item_set_submenu(GTK_MENU_ITEM(Item), Menu);
for (i = 0; i < langsMax; i++)
{
Item = gtk_check_menu_item_new_with_label(ParseLang(langs[i].lang));
gtk_widget_show(Item);
gtk_container_add(GTK_CONTAINER(Menu), Item);
gtk_check_menu_item_set_show_toggle(GTK_CHECK_MENU_ITEM(Item), TRUE);
if (!strcmp(Config.Lang, langs[i].lang))
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(Item), TRUE);
gtk_signal_connect(GTK_OBJECT(Item), "activate",
GTK_SIGNAL_FUNC(OnLanguage),
(gpointer)(uptr)i);
}
// check the appropriate menu items
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(lookup_widget(MainWindow, "enable_console1")), Config.PsxOut);
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(lookup_widget(MainWindow, "enable_patches1")), Config.Patch);
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(lookup_widget(MainWindow, "print_cdvd_info1")), Config.cdvdPrint);
// disable anything not implemented or not working properly.
gtk_widget_set_sensitive(GTK_WIDGET(lookup_widget(MainWindow, "patch_browser1")), FALSE);
gtk_widget_set_sensitive(GTK_WIDGET(lookup_widget(MainWindow, "patch_finder2")), FALSE);
gtk_widget_set_sensitive(GTK_WIDGET(lookup_widget(MainWindow, "GtkMenuItem_EnterDebugger")), FALSE);
#ifndef PCSX2_DEVBUILD
/*gtk_widget_set_sensitive(GTK_WIDGET(lookup_widget(MainWindow, "GtkMenuItem_Logging")), FALSE);
gtk_widget_set_sensitive(GTK_WIDGET(lookup_widget(MainWindow, "GtkMenuItem_Arguments")), FALSE);*/
gtk_widget_destroy(lookup_widget(MainWindow, "GtkMenuItem_Debug"));
#endif
RefreshMenuSlots();
gtk_widget_show_all(MainWindow);
gtk_window_activate_focus(GTK_WINDOW(MainWindow));
gtk_main();
}
void OnDestroy(GtkObject *object, gpointer user_data) {}
gboolean OnDelete(GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
pcsx2_exit();
return (FALSE);
}
int Pcsx2Configure()
{
if (g_Startup.NoGui) return 0;
MainWindow = NULL;
OnConf_Conf(NULL, 0);
return applychanges;
}
void OnLanguage(GtkMenuItem *menuitem, gpointer user_data)
{
ChangeLanguage(langs[(int)(uptr)user_data].lang);
gtk_widget_destroy(MainWindow);
gtk_main_quit();
while (gtk_events_pending()) gtk_main_iteration();
StartGui();
}
void OnFile_RunCD(GtkMenuItem *menuitem, gpointer user_data)
{
SysReset();
SysPrepareExecution(NULL);
}
void OnRunElf_Ok(GtkButton* button, gpointer user_data)
{
gchar *File;
File = (gchar*)gtk_file_selection_get_filename(GTK_FILE_SELECTION(FileSel));
strcpy(elfname, File);
gtk_widget_destroy(FileSel);
SysPrepareExecution(elfname);
}
void OnRunElf_Cancel(GtkButton* button, gpointer user_data)
{
gtk_widget_destroy(FileSel);
}
void OnFile_LoadElf(GtkMenuItem *menuitem, gpointer user_data)
{
GtkWidget *Ok, *Cancel;
FileSel = gtk_file_selection_new("Select Psx Elf File");
Ok = GTK_FILE_SELECTION(FileSel)->ok_button;
gtk_signal_connect(GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnRunElf_Ok), NULL);
gtk_widget_show(Ok);
Cancel = GTK_FILE_SELECTION(FileSel)->cancel_button;
gtk_signal_connect(GTK_OBJECT(Cancel), "clicked", GTK_SIGNAL_FUNC(OnRunElf_Cancel), NULL);
gtk_widget_show(Cancel);
gtk_widget_show(FileSel);
gdk_window_raise(FileSel->window);
}
void pcsx2_exit()
{
DIR *dir;
struct dirent *ent;
void *Handle;
char plugin[g_MaxPath];
// with this the problem with plugins that are linked with the pthread
// library is solved
dir = opendir(Config.PluginsDir);
if (dir != NULL)
{
while ((ent = readdir(dir)) != NULL)
{
sprintf(plugin, "%s%s", Config.PluginsDir, ent->d_name);
if (strstr(plugin, ".so") == NULL) continue;
Handle = SysLoadLibrary(plugin);
if (Handle == NULL) continue;
}
}
printf("PCSX2 Quitting\n");
if (g_Startup.NoGui)
{
SysClose();
exit(0);
}
else
{
gtk_main_quit();
SysClose();
gtk_exit(0);
}
}
void SignalExit(int sig)
{
ClosePlugins(true);
pcsx2_exit();
}
void OnFile_Exit(GtkMenuItem *menuitem, gpointer user_data)
{
pcsx2_exit();
}
void OnEmu_Run(GtkMenuItem *menuitem, gpointer user_data)
{
SysPrepareExecution(NULL, true); // boots bios if no savestate is to be recovered
}
void OnEmu_Reset(GtkMenuItem *menuitem, gpointer user_data)
{
SysReset();
}
//2002-09-28 (Florin)
void OnArguments_Ok(GtkButton *button, gpointer user_data)
{
char *str;
str = (char*)gtk_entry_get_text(GTK_ENTRY(widgetCmdLine));
memcpy(args, str, g_MaxPath);
gtk_widget_destroy(CmdLine);
gtk_widget_set_sensitive(MainWindow, TRUE);
gtk_main_quit();
}
void OnEmu_Arguments(GtkMenuItem *menuitem, gpointer user_data)
{
GtkWidget *widgetCmdLine;
CmdLine = create_CmdLine();
gtk_window_set_title(GTK_WINDOW(CmdLine), _("Program arguments"));
widgetCmdLine = lookup_widget(CmdLine, "GtkEntry_dCMDLINE");
gtk_entry_set_text(GTK_ENTRY(widgetCmdLine), args);
gtk_widget_show_all(CmdLine);
gtk_widget_set_sensitive(MainWindow, FALSE);
gtk_main();
}
void OnLogging_Ok(GtkButton *button, gpointer user_data)
{
#ifdef PCSX2_DEVBUILD
GtkWidget *Btn;
char str[32];
int i, ret;
for (i = 0; i < 32; i++)
{
if (((i > 16) && (i < 20)) || (i == 29))
continue;
sprintf(str, "Log%d", i);
Btn = lookup_widget(LogDlg, str);
ret = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(Btn));
if (ret) varLog |= 1 << i;
else varLog &= ~(1 << i);
}
SaveConfig();
#endif
gtk_widget_destroy(LogDlg);
gtk_widget_set_sensitive(MainWindow, TRUE);
gtk_main_quit();
}
void OnDebug_Logging(GtkMenuItem *menuitem, gpointer user_data)
{
GtkWidget *Btn;
char str[32];
int i;
LogDlg = create_Logging();
for (i = 0; i < 32; i++)
{
if (((i > 16) && (i < 20)) || (i == 29))
continue;
sprintf(str, "Log%d", i);
Btn = lookup_widget(LogDlg, str);
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(Btn), varLog & (1 << i));
}
gtk_widget_show_all(LogDlg);
gtk_widget_set_sensitive(MainWindow, FALSE);
gtk_main();
}
void on_patch_browser1_activate(GtkMenuItem *menuitem, gpointer user_data) {}
void on_patch_finder2_activate(GtkMenuItem *menuitem, gpointer user_data) {}
void on_enable_console1_activate(GtkMenuItem *menuitem, gpointer user_data)
{
Config.PsxOut = (int)gtk_check_menu_item_get_active((GtkCheckMenuItem*)menuitem);
SaveConfig();
}
void on_enable_patches1_activate(GtkMenuItem *menuitem, gpointer user_data)
{
Config.Patch = (int)gtk_check_menu_item_get_active((GtkCheckMenuItem*)menuitem);
SaveConfig();
}
void OnPrintCdvdInfo(GtkMenuItem *menuitem, gpointer user_data)
{
Config.cdvdPrint = (int)gtk_check_menu_item_get_active((GtkCheckMenuItem*)menuitem);
SaveConfig();
}

View File

@ -1,82 +0,0 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 Pcsx2 Team
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __LNXMAIN_H__
#define __LNXMAIN_H__
#include "Linux.h"
#include "LnxMain.h"
#include "HostGui.h"
extern bool applychanges;
extern bool Slots[5];
extern bool ParseCommandLine(int argc, char *argv[], char *file);
extern void MemoryCard_Init();
void OnLanguage(GtkMenuItem *menuitem, gpointer user_data);
void InitLanguages();
char *GetLanguageNext();
void CloseLanguages();
void StartGui();
void pcsx2_exit();
extern bool SysInit();
extern void SysClose();
GtkWidget *MainWindow, *Status_Box;
GtkWidget *pStatusBar = NULL;
GtkWidget *CmdLine, *widgetCmdLine;
GtkWidget *LogDlg, *MemDlg;
GtkAccelGroup *AccelGroup;
typedef struct
{
char lang[g_MaxPath];
} _langs;
_langs *langs;
unsigned int langsMax;
const char* phelpmsg =
"\tpcsx2 [options] [file]\n\n"
"-cfg [file] {configuration file}\n"
"-efile [efile] {0 - reset, 1 - runcd (default), 2 - loadelf}\n"
"-help {display this help file}\n"
"-nogui {Don't use gui when launching}\n"
"-loadgs [file} {Loads a gsstate}\n"
"\n"
#ifdef PCSX2_DEVBUILD
"Testing Options: \n"
"\t-frame [frame] {game will run up to this frame before exiting}\n"
"\t-image [name] {path and base name of image (do not include the .ext)}\n"
"\t-jpg {save images to jpg format}\n"
"\t-log [name] {log path to save log file in}\n"
"\t-logopt [hex] {log options in hex (see debug.h) }\n"
"\t-numimages [num] {after hitting frame, this many images will be captures every 20 frames}\n"
"\t-test {Triggers testing mode (only for dev builds)}\n"
"\n"
#endif
"Load Plugins:\n"
"\t-cdvd [libpath] {specify the library load path of the CDVD plugin}\n"
"\t-gs [libpath] {specify the library load path of the GS plugin}\n"
"-pad [tsxcal] {specify to hold down on the triangle, square, circle, x, start, select buttons}\n"
"\t-spu [libpath] {specify the library load path of the SPU2 plugin}\n"
"\n";
#endif

View File

@ -1,572 +0,0 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 Pcsx2 Team
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "Linux.h"
#include "LnxSysExec.h"
#include "HostGui.h"
static bool sinit = false;
GtkWidget *FileSel;
static uptr current_offset = 0;
static uptr offset_counter = 0;
bool Slots[5] = { false, false, false, false, false };
__noinline void InstallLinuxExceptionHandler()
{
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = &SysPageFaultExceptionFilter;
sigaction(SIGSEGV, &sa, NULL);
}
__noinline void ReleaseLinuxExceptionHandler()
{
// This may be called too early or something, since implementing it causes all games to segfault.
// I'll look in to it. --arcum42
}
__noinline void KillLinuxExceptionHandler()
{
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESETHAND;
//sa.sa_sigaction = &SysPageFaultExceptionFilter;
sigaction(SIGSEGV, &sa, NULL);
}
static const uptr m_pagemask = getpagesize()-1;
// Linux implementation of SIGSEGV handler. Bind it using sigaction().
__noinline void SysPageFaultExceptionFilter( int signal, siginfo_t *info, void * )
{
// get bad virtual address
uptr offset = (u8*)info->si_addr - psM;
if (offset != current_offset)
{
current_offset = offset;
offset_counter = 0;
}
else
{
offset_counter++;
if (offset_counter > 500)
{
DevCon::Status( "Offset 0x%x endlessly repeating. Aborting.", params offset );
KillLinuxExceptionHandler();
assert( false );
}
}
if (offset>=Ps2MemSize::Base)
{
// Bad mojo! Completely invalid address.
// Instigate a crash or abort emulation or something.
DevCon::Status( "Offset 0x%x invalid. Legit SIGSEGV. Aborting.", params offset );
KillLinuxExceptionHandler();
assert( false );
}
mmap_ClearCpuBlock( offset & ~m_pagemask );
}
bool ParseCommandLine(int argc, char *argv[], char *file)
{
int i = 1;
g_Startup.BootMode = BootMode_Bios;
while (i < argc)
{
char* token = argv[i++];
if (stricmp(token, "-help") == 0 || stricmp(token, "--help") == 0 || stricmp(token, "-h") == 0)
{
//Msgbox::Alert( phelpmsg );
return false;
}
else if (stricmp(token, "-nogui") == 0)
{
g_Startup.NoGui = FALSE;
}
else if (stricmp(token, "-loadgs") == 0)
{
g_pRunGSState = argv[i++];
}
else if( strcmp(token, "-bootmode" ) == 0)
{
token = argv[i++];
g_Startup.BootMode = (StartupMode)atoi( token);
g_Startup.Enabled = true;
}
else if (stricmp(token, "-gs") == 0)
{
token = argv[i++];
g_Startup.gsdll = token;
}
else if (stricmp(token, "-cdvd") == 0)
{
token = argv[i++];
g_Startup.cdvddll = token;
}
else if (stricmp(token, "-spu") == 0)
{
token = argv[i++];
g_Startup.spudll = token;
}
else if (stricmp(token, "-pad") == 0)
{
token = argv[i++];
g_Startup.pad1dll = token;
g_Startup.pad2dll = token;
}
else if (stricmp(token, "-pad1") == 0)
{
token = argv[i++];
g_Startup.pad1dll = token;
}
else if (stricmp(token, "-pad2") == 0)
{
token = argv[i++];
g_Startup.pad2dll = token;
}
else if (stricmp(token, "-loadgs") == 0)
{
token = argv[i++];
g_pRunGSState = token;
}
else
{
file = token;
printf("opening file %s\n", file);
}
}
return true;
}
void SysPrintf(const char *fmt, ...)
{
va_list list;
char msg[512];
va_start(list, fmt);
vsnprintf(msg, 511, fmt, list);
msg[511] = '\0';
va_end(list);
Console::Write(msg);
}
static std::string str_Default( "default" );
void RunGui()
{
PCSX2_MEM_PROTECT_BEGIN();
LoadPatch( str_Default );
if( g_Startup.NoGui || g_Startup.Enabled )
{
// Initially bypass GUI and start PCSX2 directly.
// Manually load plugins using the user's configured image (if non-elf).
if( g_Startup.Enabled && (g_Startup.BootMode != BootMode_Elf) )
{
if (OpenPlugins(g_Startup.ImageName) == -1)
return;
}
SysPrepareExecution(
(g_Startup.BootMode == BootMode_Elf) ? g_Startup.ImageName : NULL,
(g_Startup.BootMode == BootMode_Bios)
);
}
StartGui();
PCSX2_MEM_PROTECT_END();
}
void OnStates_Load(GtkMenuItem *menuitem, gpointer user_data)
{
char *name;
int i;
if (GTK_BIN (menuitem)->child)
{
GtkWidget *child = GTK_BIN (menuitem)->child;
if (GTK_IS_LABEL (child))
gtk_label_get (GTK_LABEL (child), &name);
else
return;
}
sscanf(name, "Slot %d", &i);
States_Load(i);
RefreshMenuSlots();
}
void OnLoadOther_Ok(GtkButton* button, gpointer user_data)
{
gchar *File;
char str[g_MaxPath];
File = (gchar*)gtk_file_selection_get_filename(GTK_FILE_SELECTION(FileSel));
strcpy(str, File);
gtk_widget_destroy(FileSel);
States_Load(str);
RefreshMenuSlots();
}
void OnLoadOther_Cancel(GtkButton* button, gpointer user_data)
{
gtk_widget_destroy(FileSel);
}
void OnStates_LoadOther(GtkMenuItem *menuitem, gpointer user_data)
{
GtkWidget *Ok, *Cancel;
FileSel = gtk_file_selection_new(_("Select State File"));
gtk_file_selection_set_filename(GTK_FILE_SELECTION(FileSel), SSTATES_DIR "/");
Ok = GTK_FILE_SELECTION(FileSel)->ok_button;
gtk_signal_connect(GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnLoadOther_Ok), NULL);
gtk_widget_show(Ok);
Cancel = GTK_FILE_SELECTION(FileSel)->cancel_button;
gtk_signal_connect(GTK_OBJECT(Cancel), "clicked", GTK_SIGNAL_FUNC(OnLoadOther_Cancel), NULL);
gtk_widget_show(Cancel);
gtk_widget_show(FileSel);
gdk_window_raise(FileSel->window);
}
void OnStates_Save(GtkMenuItem *menuitem, gpointer user_data)
{
char *name;
int i;
if (GTK_BIN (menuitem)->child)
{
GtkWidget *child = GTK_BIN (menuitem)->child;
if (GTK_IS_LABEL (child))
gtk_label_get (GTK_LABEL (child), &name);
else
return;
}
sscanf(name, "Slot %d", &i);
States_Save(i);
}
void OnSaveOther_Ok(GtkButton* button, gpointer user_data)
{
gchar *File;
char str[g_MaxPath];
File = (gchar*)gtk_file_selection_get_filename(GTK_FILE_SELECTION(FileSel));
strcpy(str, File);
gtk_widget_destroy(FileSel);
States_Save(str);
}
void OnSaveOther_Cancel(GtkButton* button, gpointer user_data)
{
gtk_widget_destroy(FileSel);
}
void OnStates_SaveOther(GtkMenuItem *menuitem, gpointer user_data)
{
GtkWidget *Ok, *Cancel;
FileSel = gtk_file_selection_new(_("Select State File"));
gtk_file_selection_set_filename(GTK_FILE_SELECTION(FileSel), SSTATES_DIR "/");
Ok = GTK_FILE_SELECTION(FileSel)->ok_button;
gtk_signal_connect(GTK_OBJECT(Ok), "clicked", GTK_SIGNAL_FUNC(OnSaveOther_Ok), NULL);
gtk_widget_show(Ok);
Cancel = GTK_FILE_SELECTION(FileSel)->cancel_button;
gtk_signal_connect(GTK_OBJECT(Cancel), "clicked", GTK_SIGNAL_FUNC(OnSaveOther_Cancel), NULL);
gtk_widget_show(Cancel);
gtk_widget_show(FileSel);
gdk_window_raise(FileSel->window);
}
bool SysInit()
{
if (sinit) return true;
sinit = true;
mkdir(SSTATES_DIR, 0755);
mkdir(MEMCARDS_DIR, 0755);
mkdir(LOGS_DIR, 0755);
#ifdef PCSX2_DEVBUILD
if (emuLog == NULL)
emuLog = fopen(LOGS_DIR "/emuLog.txt", "wb");
#endif
if (emuLog != NULL)
setvbuf(emuLog, NULL, _IONBF, 0);
PCSX2_MEM_PROTECT_BEGIN();
SysDetect();
if (!SysAllocateMem()) return false; // critical memory allocation failure;
SysAllocateDynarecs();
PCSX2_MEM_PROTECT_END();
while (LoadPlugins() == -1)
{
if (Pcsx2Configure() == FALSE)
{
Msgbox::Alert("Configuration failed. Exiting.");
exit(1);
}
}
return true;
}
void SysClose()
{
if (sinit == false) return;
cpuShutdown();
ClosePlugins( true );
ReleasePlugins();
if (emuLog != NULL)
{
fclose(emuLog);
emuLog = NULL;
}
sinit = false;
// Precautionary extra shutdown stuff.
SysEndExecution();
g_EmulationInProgress = false;
}
namespace HostSys
{
void *LoadLibrary(const char *lib)
{
return dlopen(lib, RTLD_NOW);
}
void *LoadSym(void *lib, const char *sym)
{
return dlsym(lib, sym);
}
const char *LibError()
{
return dlerror();
}
void CloseLibrary(void *lib)
{
dlclose(lib);
}
void *Mmap(uptr base, u32 size)
{
u8 *Mem;
Mem = (u8*)mmap((uptr*)base, size, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
if (Mem == MAP_FAILED) Console::Notice("Mmap Failed!");
return Mem;
}
void Munmap(uptr base, u32 size)
{
munmap((uptr*)base, size);
}
void MemProtect( void* baseaddr, size_t size, PageProtectionMode mode, bool allowExecution )
{
// Breakpoint this to trap potentially inappropriate use of page protection, which would
// be caused by failed aligned directives on global vars.
if( ((uptr)baseaddr & m_pagemask) != 0 )
{
Console::Error(
"*PCSX2/Linux Warning* Inappropriate use of page protection detected.\n"
"\tbaseaddr not page aligned: 0x%08X", params (uptr)baseaddr
);
}
int lnxmode = 0;
// make sure base and size are aligned to the system page size:
size = (size + m_pagemask) & ~m_pagemask;
baseaddr = (void*)( ((uptr)baseaddr) & ~m_pagemask );
switch( mode )
{
case Protect_NoAccess: break;
case Protect_ReadOnly: lnxmode = PROT_READ; break;
case Protect_ReadWrite: lnxmode = PROT_READ | PROT_WRITE; break;
}
if( allowExecution ) lnxmode |= PROT_EXEC;
mprotect( baseaddr, size, lnxmode );
}
}
namespace HostGui
{
// Sets the status bar message without mirroring the output to the console.
void SetStatusMsg( const string& text )
{
// don't try this in Visual C++ folks!
gtk_statusbar_push(GTK_STATUSBAR(pStatusBar), 0, text.c_str());
}
void Notice( const string& text )
{
// mirror output to the console!
Console::Status( text.c_str() );
SetStatusMsg( text );
}
void ResetMenuSlots()
{
for (int i = 0; i < 5; i++)
{
Slots[i] = States_isSlotUsed(i);
}
}
void BeginExecution()
{
// Destroy the window. Ugly thing.
gtk_widget_destroy(MainWindow);
gtk_main_quit();
while (gtk_events_pending()) gtk_main_iteration();
signal(SIGINT, SignalExit);
signal(SIGPIPE, SignalExit);
// no try/catch needed since no cleanup needed.. ?
SysExecute();
}
/* Quick macros for checking shift, control, alt, and caps lock. */
#define SHIFT_EVT(evt) ((evt == XK_Shift_L) || (evt == XK_Shift_R))
#define CTRL_EVT(evt) ((evt == XK_Control_L) || (evt == XK_Control_R))
#define ALT_EVT(evt) ((evt == XK_Alt_L) || (evt == XK_Alt_R))
#define CAPS_LOCK_EVT(evt) (evt == XK_Caps_Lock)
void __fastcall KeyEvent(keyEvent* ev)
{
struct KeyModifiers *keymod = &keymodifiers;
if (ev == NULL) return;
if (GSkeyEvent != NULL) GSkeyEvent(ev);
if (ev->evt == KEYPRESS)
{
if (SHIFT_EVT(ev->key)) keymod->shift = TRUE;
if (CTRL_EVT(ev->key)) keymod->control = TRUE;
if (ALT_EVT(ev->key)) keymod->alt = TRUE;
if (CAPS_LOCK_EVT(ev->key)) keymod->capslock = TRUE;
switch (ev->key)
{
case XK_F1:
case XK_F2:
case XK_F3:
case XK_F4:
case XK_F5:
case XK_F6:
case XK_F7:
case XK_F8:
case XK_F9:
case XK_F10:
case XK_F11:
case XK_F12:
try
{
ProcessFKeys(ev->key - XK_F1 + 1, keymod);
}
catch (Exception::CpuStateShutdown&)
{
// Woops! Something was unrecoverable. Bummer.
// Let's give the user a RunGui!
g_EmulationInProgress = false;
SysEndExecution();
}
break;
case XK_Tab:
CycleFrameLimit(0);
break;
case XK_Escape:
signal(SIGINT, SIG_DFL);
signal(SIGPIPE, SIG_DFL);
#ifdef PCSX2_DEVBUILD
if (g_SaveGSStream >= 3)
{
g_SaveGSStream = 4;// gs state
break;
}
#endif
SysEndExecution();
if (g_Startup.NoGui) exit(0);
// fixme: The GUI is now capable of receiving control back from the
// emulator. Which means that when we call SysEscapeExecute() here, the
// emulation loop in ExecuteCpu() will exit. You should be able to set it
// up so that it returns control to the existing GTK event loop, instead of
// always starting a new one via RunGui(). (but could take some trial and
// error) -- (air)
// Easier said then done; running gtk in two threads at the same time can't be
// done, and working around that is pretty fiddly.
RunGui();
break;
default:
GSkeyEvent(ev);
break;
}
}
else if (ev->evt == KEYRELEASE)
{
if (SHIFT_EVT(ev->key)) keymod->shift = FALSE;
if (CTRL_EVT(ev->key)) keymod->control = FALSE;
if (ALT_EVT(ev->key)) keymod->alt = FALSE;
if (CAPS_LOCK_EVT(ev->key)) keymod->capslock = FALSE;
}
return;
}
}

View File

@ -1,42 +0,0 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 Pcsx2 Team
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __LNXSYSEXEC_H__
#define __LNXSYSEXEC_H__
#include "Linux.h"
#include "GS.h"
#include <sys/mman.h>
#include "x86/iR5900.h"
void SysPageFaultExceptionFilter( int signal, siginfo_t *info, void * );
void __fastcall InstallLinuxExceptionHandler();
void __fastcall ReleaseLinuxExceptionHandler();
#define PCSX2_MEM_PROTECT_BEGIN() InstallLinuxExceptionHandler()
#define PCSX2_MEM_PROTECT_END() ReleaseLinuxExceptionHandler()
extern void StartGui();
extern void RefreshMenuSlots();
extern void SignalExit(int sig);
extern const char* g_pRunGSState;
extern int efile;
extern GtkWidget *pStatusBar;
#endif

View File

@ -1,107 +0,0 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2008 Pcsx2 Team
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "McdDlgs.h"
void OnConf_Memcards(GtkMenuItem *menuitem, gpointer user_data)
{
char file[g_MaxPath], card[g_MaxPath];
DIR *dir;
struct dirent *entry;
struct stat statinfo;
GtkWidget *memcombo[2];
int i = 0, j = 0;
bool active[2] ={false, false};
MemDlg = create_MemDlg();
memcombo[0] = lookup_widget(MemDlg, "memcard1combo");
memcombo[1] = lookup_widget(MemDlg, "memcard2combo");
set_checked(MemDlg, "check_enable_mcd1", Config.Mcd[0].Enabled);
set_checked(MemDlg, "check_enable_mcd2", Config.Mcd[1].Enabled);
set_checked(MemDlg, "check_eject_mcds", Config.McdEnableEject);
getcwd(file, ArraySize(file)); /* store current dir */
sprintf(card, "%s/%s", file, MEMCARDS_DIR );
chdir(card); /* change dirs so that plugins can find their config file*/
if ((dir = opendir(card)) == NULL)
{
Console::Error("ERROR: Could not open directory %s\n", params card);
return;
}
while ((entry = readdir(dir)) != NULL)
{
stat(entry->d_name, &statinfo);
if (S_ISREG(statinfo.st_mode))
{
char path[g_MaxPath];
sprintf(path, "%s/%s/%s", MAIN_DIR, MEMCARDS_DIR, entry->d_name);
for (j = 0; j < 2; j++)
{
gtk_combo_box_append_text(GTK_COMBO_BOX(memcombo[j]), entry->d_name);
if (strcmp(Config.Mcd[j].Filename, path) == 0)
{
gtk_combo_box_set_active(GTK_COMBO_BOX(memcombo[j]), i);
active[j] = true;
}
}
i++;
}
}
closedir(dir);
chdir(file);
gtk_widget_show_all(MemDlg);
gtk_widget_set_sensitive(MainWindow, FALSE);
gtk_main();
}
void OnMemcards_Ok(GtkButton *button, gpointer user_data)
{
if (gtk_combo_box_get_active(GTK_COMBO_BOX(lookup_widget(MemDlg, "memcard1combo"))) != -1)
sprintf(Config.Mcd[0].Filename, "%s/%s/%s", MAIN_DIR, MEMCARDS_DIR,
gtk_combo_box_get_active_text(GTK_COMBO_BOX(lookup_widget(MemDlg, "memcard1combo"))));
else
sprintf(Config.Mcd[0].Filename, "%s/%s/%s", MAIN_DIR, MEMCARDS_DIR, DEFAULT_MEMCARD1);
if (gtk_combo_box_get_active(GTK_COMBO_BOX(lookup_widget(MemDlg, "memcard2combo"))) != -1)
sprintf(Config.Mcd[1].Filename, "%s/%s/%s", MAIN_DIR, MEMCARDS_DIR,
gtk_combo_box_get_active_text(GTK_COMBO_BOX(lookup_widget(MemDlg, "memcard2combo"))));
else
sprintf(Config.Mcd[1].Filename, "%s/%s/%s", MAIN_DIR, MEMCARDS_DIR, DEFAULT_MEMCARD2);
Config.Mcd[0].Enabled = is_checked(MemDlg, "check_enable_mcd1");
Config.Mcd[1].Enabled = is_checked(MemDlg, "check_enable_mcd2");
Config.McdEnableEject = is_checked(MemDlg, "check_eject_mcds");
SaveConfig();
gtk_widget_destroy(MemDlg);
gtk_widget_set_sensitive(MainWindow, TRUE);
gtk_main_quit();
}

View File

@ -1,208 +0,0 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 Pcsx2 Team
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "Linux.h"
FILE *pref_file;
char *data;
static void SetValue(const char *name, char *var)
{
fprintf(pref_file, "%s = %s\n", name, var);
}
static void SetValuel(const char *name, s32 var)
{
fprintf(pref_file, "%s = %x\n", name, var);
}
#define GetValue(name, var) {\
char * tmp; \
tmp = strstr(data, name); \
if (tmp != NULL) { \
tmp+=strlen(name); \
while ((*tmp == ' ') || (*tmp == '=')) tmp++; \
if (*tmp != '\n') sscanf(tmp, "%s", var); \
} \
}
#define GetValuel(name, var) {\
char * tmp; \
tmp = strstr(data, name); \
if (tmp != NULL) { \
tmp+=strlen(name); \
while ((*tmp == ' ') || (*tmp == '=')) tmp++; \
if (*tmp != '\n') sscanf(tmp, "%x", &var); \
} \
}
int LoadConfig()
{
struct stat buf;
int size;
if (stat(cfgfile, &buf) == -1) return -1;
size = buf.st_size;
pref_file = fopen(cfgfile, "r");
if (pref_file == NULL) return -1;
data = (char*)malloc(size);
if (data == NULL) return -1;
fread(data, 1, size, pref_file);
fclose(pref_file);
GetValue("Bios", Config.Bios);
Config.Lang[0] = 0;
GetValue("Lang", Config.Lang);
GetValuel("Ps2Out", Config.PsxOut);
GetValuel("cdvdPrint", Config.cdvdPrint);
GetValue("PluginsDir", Config.PluginsDir);
GetValue("BiosDir", Config.BiosDir);
GetValuel("EnabledCard1", Config.Mcd[0].Enabled);
GetValue("Mcd1", Config.Mcd[0].Filename);
if (strcmp(Config.Mcd[0].Filename,"") == 0) strcpy(Config.Mcd[0].Filename, MEMCARDS_DIR "/" DEFAULT_MEMCARD1);
GetValuel("EnabledCard2", Config.Mcd[1].Enabled);
GetValue("Mcd2", Config.Mcd[1].Filename);
if (strcmp(Config.Mcd[1].Filename,"") == 0) strcpy(Config.Mcd[1].Filename, MEMCARDS_DIR "/" DEFAULT_MEMCARD2);
GetValuel("McdEnableEject", Config.McdEnableEject);
GetValue("GS", Config.GS);
GetValue("SPU2", Config.SPU2);
GetValue("CDVD", Config.CDVD);
GetValue("PAD1", Config.PAD1);
GetValue("PAD2", Config.PAD2);
GetValue("DEV9", Config.DEV9);
GetValue("USB", Config.USB);
GetValue("FW", Config.FW);
GetValuel("Patch", Config.Patch);
#ifdef PCSX2_DEVBUILD
GetValuel("varLog", varLog);
#endif
GetValuel("Options", Config.Options);
GetValuel("EECycleRate", Config.Hacks.EECycleRate);
if (Config.Hacks.EECycleRate > 2)
Config.Hacks.EECycleRate = 2;
GetValuel("IOPCycleDouble", Config.Hacks.IOPCycleDouble);
GetValuel("WaitCycleExt", Config.Hacks.WaitCycleExt);
GetValuel("INTCSTATSlow", Config.Hacks.INTCSTATSlow);
GetValuel("VUCycleSteal", Config.Hacks.VUCycleSteal);
GetValuel("vuFlagHack", Config.Hacks.vuFlagHack);
GetValuel("vuMinMax", Config.Hacks.vuMinMax);
GetValuel("IdleLoopFF", Config.Hacks.IdleLoopFF);
GetValuel("ESCExits", Config.Hacks.ESCExits);
if (Config.Hacks.VUCycleSteal < 0 || Config.Hacks.VUCycleSteal > 4)
Config.Hacks.VUCycleSteal = 0;
GetValuel("Fixes", Config.GameFixes);
GetValuel("CustomFps", Config.CustomFps);
GetValuel("CustomFrameskip", Config.CustomFrameSkip);
GetValuel("CustomConsecutiveFrames", Config.CustomConsecutiveFrames);
GetValuel("CustomConsecutiveSkip", Config.CustomConsecutiveSkip);
// Note - order is currently important.
GetValuel("sseMXCSR", Config.sseMXCSR);
GetValuel("sseVUMXCSR", Config.sseVUMXCSR);
GetValuel("eeOptions", Config.eeOptions);
GetValuel("vuOptions", Config.vuOptions);
free(data);
#ifdef ENABLE_NLS
if (Config.Lang[0])
{
extern int _nl_msg_cat_cntr;
setenv("LANGUAGE", Config.Lang, 1);
++_nl_msg_cat_cntr;
}
#endif
return 0;
}
/////////////////////////////////////////////////////////
void SaveConfig()
{
pref_file = fopen(cfgfile, "w");
if (pref_file == NULL) return;
SetValue("Bios", Config.Bios);
SetValue("Lang", Config.Lang);
SetValue("PluginsDir", Config.PluginsDir);
SetValue("BiosDir", Config.BiosDir);
SetValuel("Ps2Out", Config.PsxOut);
SetValuel("cdvdPrint", Config.cdvdPrint);
SetValuel("EnabledCard1", Config.Mcd[0].Enabled);
SetValue("Mcd1", Config.Mcd[0].Filename);
SetValuel("EnabledCard2", Config.Mcd[1].Enabled);
SetValue("Mcd2", Config.Mcd[1].Filename);
SetValuel("McdEnableEject", Config.McdEnableEject);
SetValue("GS", Config.GS);
SetValue("SPU2", Config.SPU2);
SetValue("CDVD", Config.CDVD);
SetValue("PAD1", Config.PAD1);
SetValue("PAD2", Config.PAD2);
SetValue("DEV9", Config.DEV9);
SetValue("USB", Config.USB);
SetValue("FW", Config.FW);
SetValuel("Options", Config.Options);
SetValuel("EECycleRate", Config.Hacks.EECycleRate);
SetValuel("IOPCycleDouble", Config.Hacks.IOPCycleDouble);
SetValuel("WaitCycleExt", Config.Hacks.WaitCycleExt);
SetValuel("INTCSTATSlow", Config.Hacks.INTCSTATSlow);
SetValuel("VUCycleSteal", Config.Hacks.VUCycleSteal);
SetValuel("IdleLoopFF", Config.Hacks.IdleLoopFF);
SetValuel("ESCExits", Config.Hacks.ESCExits);
SetValuel("Fixes", Config.GameFixes);
SetValuel("Patch", Config.Patch);
SetValuel("CustomFps", Config.CustomFps);
SetValuel("CustomFrameskip", Config.CustomFrameSkip);
SetValuel("CustomConsecutiveFrames", Config.CustomConsecutiveFrames);
SetValuel("CustomConsecutiveSkip", Config.CustomConsecutiveSkip);
SetValuel("sseMXCSR", Config.sseMXCSR);
SetValuel("sseVUMXCSR", Config.sseVUMXCSR);
SetValuel("eeOptions", Config.eeOptions);
SetValuel("vuOptions", Config.vuOptions);
#ifdef PCSX2_DEVBUILD
SetValuel("varLog", varLog);
#endif
fclose(pref_file);
return;
}

View File

@ -1,267 +0,0 @@
#include <gtk/gtk.h>
void
On_Dialog_Close (GtkDialog *dialog,
gpointer user_data);
void
on_Advanced_Defaults (GtkButton *button,
gpointer user_data);
void
on_Advanced_OK (GtkButton *button,
gpointer user_data);
void
On_Dialog_Cancelled (GtkButton *button,
gpointer user_data);
void
on_ee_slider_changed (GtkRange *range,
gpointer user_data);
void
on_vu_slider_changed (GtkRange *range,
gpointer user_data);
void
on_Speed_Hack_OK (GtkButton *button,
gpointer user_data);
void
on_Game_Fix_OK (GtkButton *button,
gpointer user_data);
void
OnMemWrite32_Ok (GtkButton *button,
gpointer user_data);
void
OnArguments_Ok (GtkButton *button,
gpointer user_data);
void
OnDumpR_Ok (GtkButton *button,
gpointer user_data);
void
OnDumpC_Ok (GtkButton *button,
gpointer user_data);
void
OnSetBPC_Ok (GtkButton *button,
gpointer user_data);
void
OnSetBPA_Ok (GtkButton *button,
gpointer user_data);
void
OnSetBPA_Cancel (GtkButton *button,
gpointer user_data);
void
OnSetPC_Ok (GtkButton *button,
gpointer user_data);
void
OnDebug_EEMode (GtkToggleButton *togglebutton,
gpointer user_data);
void
OnDebug_IOPMode (GtkToggleButton *togglebutton,
gpointer user_data);
void
OnDebug_Step (GtkButton *button,
gpointer user_data);
void
OnDebug_Skip (GtkButton *button,
gpointer user_data);
void
OnDebug_Go (GtkButton *button,
gpointer user_data);
void
OnDebug_Log (GtkButton *button,
gpointer user_data);
void
OnDebug_SetPC (GtkButton *button,
gpointer user_data);
void
OnDebug_SetBPA (GtkButton *button,
gpointer user_data);
void
OnDebug_SetBPC (GtkButton *button,
gpointer user_data);
void
OnDebug_ClearBPs (GtkButton *button,
gpointer user_data);
void
OnDebug_DumpCode (GtkButton *button,
gpointer user_data);
void
OnDebug_RawDump (GtkButton *button,
gpointer user_data);
void
OnDebug_Close (GtkButton *button,
gpointer user_data);
void
OnDebug_memWrite32 (GtkButton *button,
gpointer user_data);
void
OnConfButton (GtkButton *button,
gpointer user_data);
void
OnConfConf_PluginsPath (GtkButton *button,
gpointer user_data);
void
OnConfConf_BiosPath (GtkButton *button,
gpointer user_data);
void
OnConfConf_Ok (GtkButton *button,
gpointer user_data);
void
OnHelpAbout_Ok (GtkButton *button,
gpointer user_data);
void
OnDestroy (GtkObject *object,
gpointer user_data);
gboolean
OnDelete (GtkWidget *widget,
GdkEvent *event,
gpointer user_data);
void
OnFile_RunCD (GtkMenuItem *menuitem,
gpointer user_data);
void
OnFile_LoadElf (GtkMenuItem *menuitem,
gpointer user_data);
void
OnStates_Load (GtkMenuItem *menuitem,
gpointer user_data);
void
OnStates_LoadOther (GtkMenuItem *menuitem,
gpointer user_data);
void
OnStates_Save (GtkMenuItem *menuitem,
gpointer user_data);
void
OnStates_SaveOther (GtkMenuItem *menuitem,
gpointer user_data);
void
OnFile_Exit (GtkMenuItem *menuitem,
gpointer user_data);
void
OnEmu_Run (GtkMenuItem *menuitem,
gpointer user_data);
void
OnEmu_Reset (GtkMenuItem *menuitem,
gpointer user_data);
void
OnConf_Conf (GtkMenuItem *menuitem,
gpointer user_data);
void
OnConf_Menu (GtkMenuItem *menuitem,
gpointer user_data);
void
OnConf_Memcards (GtkMenuItem *menuitem,
gpointer user_data);
void
OnConf_Cpu (GtkMenuItem *menuitem,
gpointer user_data);
void
on_Game_Fixes (GtkMenuItem *menuitem,
gpointer user_data);
void
on_Speed_Hacks (GtkMenuItem *menuitem,
gpointer user_data);
void
on_Advanced (GtkMenuItem *menuitem,
gpointer user_data);
void
on_patch_browser1_activate (GtkMenuItem *menuitem,
gpointer user_data);
void
on_patch_finder2_activate (GtkMenuItem *menuitem,
gpointer user_data);
void
on_enable_console1_activate (GtkMenuItem *menuitem,
gpointer user_data);
void
on_enable_patches1_activate (GtkMenuItem *menuitem,
gpointer user_data);
void
OnPrintCdvdInfo (GtkMenuItem *menuitem,
gpointer user_data);
void
OnDebug_Debugger (GtkMenuItem *menuitem,
gpointer user_data);
void
OnDebug_Logging (GtkMenuItem *menuitem,
gpointer user_data);
void
OnEmu_Arguments (GtkMenuItem *menuitem,
gpointer user_data);
void
OnHelp_About (GtkMenuItem *menuitem,
gpointer user_data);
void
OnCpuCheckToggled (GtkToggleButton *togglebutton,
gpointer user_data);
void
OnCpu_Ok (GtkButton *button,
gpointer user_data);
void
OnLogging_Ok (GtkButton *button,
gpointer user_data);
void
OnMemcards_Ok (GtkButton *button,
gpointer user_data);

File diff suppressed because it is too large Load Diff

View File

@ -1,23 +0,0 @@
/*
* DO NOT EDIT THIS FILE - it is generated by Glade.
*/
GtkWidget* create_AdvDlg (void);
GtkWidget* create_SpeedHacksDlg (void);
GtkWidget* create_GameFixDlg (void);
GtkWidget* create_MemWrite32 (void);
GtkWidget* create_CmdLine (void);
GtkWidget* create_DumpRDlg (void);
GtkWidget* create_DumpCDlg (void);
GtkWidget* create_SetBPCDlg (void);
GtkWidget* create_SetBPADlg (void);
GtkWidget* create_SetPCDlg (void);
GtkWidget* create_DebugWnd (void);
GtkWidget* create_ConfDlg (void);
GtkWidget* create_AboutDlg (void);
GtkWidget* create_MainWindow (void);
GtkWidget* create_PatchBrowserWindow (void);
GtkWidget* create_PatchFinderWindow (void);
GtkWidget* create_CpuDlg (void);
GtkWidget* create_Logging (void);
GtkWidget* create_MemDlg (void);

View File

@ -1,144 +0,0 @@
/*
* DO NOT EDIT THIS FILE - it is generated by Glade.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <gtk/gtk.h>
#include "support.h"
GtkWidget*
lookup_widget (GtkWidget *widget,
const gchar *widget_name)
{
GtkWidget *parent, *found_widget;
for (;;)
{
if (GTK_IS_MENU (widget))
parent = gtk_menu_get_attach_widget (GTK_MENU (widget));
else
parent = widget->parent;
if (!parent)
parent = (GtkWidget*) g_object_get_data (G_OBJECT (widget), "GladeParentKey");
if (parent == NULL)
break;
widget = parent;
}
found_widget = (GtkWidget*) g_object_get_data (G_OBJECT (widget),
widget_name);
if (!found_widget)
g_warning ("Widget not found: %s", widget_name);
return found_widget;
}
static GList *pixmaps_directories = NULL;
/* Use this function to set the directory containing installed pixmaps. */
void
add_pixmap_directory (const gchar *directory)
{
pixmaps_directories = g_list_prepend (pixmaps_directories,
g_strdup (directory));
}
/* This is an internally used function to find pixmap files. */
static gchar*
find_pixmap_file (const gchar *filename)
{
GList *elem;
/* We step through each of the pixmaps directory to find it. */
elem = pixmaps_directories;
while (elem)
{
gchar *pathname = g_strdup_printf ("%s%s%s", (gchar*)elem->data,
G_DIR_SEPARATOR_S, filename);
if (g_file_test (pathname, G_FILE_TEST_EXISTS))
return pathname;
g_free (pathname);
elem = elem->next;
}
return NULL;
}
/* This is an internally used function to create pixmaps. */
GtkWidget*
create_pixmap (GtkWidget *widget,
const gchar *filename)
{
gchar *pathname = NULL;
GtkWidget *pixmap;
if (!filename || !filename[0])
return gtk_image_new ();
pathname = find_pixmap_file (filename);
if (!pathname)
{
g_warning (_("Couldn't find pixmap file: %s"), filename);
return gtk_image_new ();
}
pixmap = gtk_image_new_from_file (pathname);
g_free (pathname);
return pixmap;
}
/* This is an internally used function to create pixmaps. */
GdkPixbuf*
create_pixbuf (const gchar *filename)
{
gchar *pathname = NULL;
GdkPixbuf *pixbuf;
GError *error = NULL;
if (!filename || !filename[0])
return NULL;
pathname = find_pixmap_file (filename);
if (!pathname)
{
g_warning (_("Couldn't find pixmap file: %s"), filename);
return NULL;
}
pixbuf = gdk_pixbuf_new_from_file (pathname, &error);
if (!pixbuf)
{
fprintf (stderr, "Failed to load pixbuf file: %s: %s\n",
pathname, error->message);
g_error_free (error);
}
g_free (pathname);
return pixbuf;
}
/* This is used to set ATK action descriptions. */
void
glade_set_atk_action_description (AtkAction *action,
const gchar *action_name,
const gchar *description)
{
gint n_actions, i;
n_actions = atk_action_get_n_actions (action);
for (i = 0; i < n_actions; i++)
{
if (!strcmp (atk_action_get_name (action, i), action_name))
atk_action_set_description (action, i, description);
}
}

View File

@ -1,69 +0,0 @@
/*
* DO NOT EDIT THIS FILE - it is generated by Glade.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <gtk/gtk.h>
/*
* Standard gettext macros.
*/
#ifdef ENABLE_NLS
# include <libintl.h>
# undef _
# define _(String) dgettext (PACKAGE, String)
# define Q_(String) g_strip_context ((String), gettext (String))
# ifdef gettext_noop
# define N_(String) gettext_noop (String)
# else
# define N_(String) (String)
# endif
#else
# define textdomain(String) (String)
# define gettext(String) (String)
# define dgettext(Domain,Message) (Message)
# define dcgettext(Domain,Message,Type) (Message)
# define bindtextdomain(Domain,Directory) (Domain)
# define _(String) (String)
# define Q_(String) g_strip_context ((String), (String))
# define N_(String) (String)
#endif
/*
* Public Functions.
*/
/*
* This function returns a widget in a component created by Glade.
* Call it with the toplevel widget in the component (i.e. a window/dialog),
* or alternatively any widget in the component, and the name of the widget
* you want returned.
*/
GtkWidget* lookup_widget (GtkWidget *widget,
const gchar *widget_name);
/* Use this function to set the directory containing installed pixmaps. */
void add_pixmap_directory (const gchar *directory);
/*
* Private Functions.
*/
/* This is used to create the pixmaps used in the interface. */
GtkWidget* create_pixmap (GtkWidget *widget,
const gchar *filename);
/* This is used to create the pixbufs used in the interface. */
GdkPixbuf* create_pixbuf (const gchar *filename);
/* This is used to set ATK action descriptions. */
void glade_set_atk_action_description (AtkAction *action,
const gchar *action_name,
const gchar *description);

View File

@ -106,6 +106,7 @@ bool IsRooted( const wxString& path )
// ------------------------------------------------------------------------
// Concatenates two pathnames together, inserting delimiters (backslash on win32)
// as needed! Assumes the 'dest' is allocated to at least g_MaxPath length.
//
wxString Combine( const wxString& srcPath, const wxString& srcFile )
{
#if 0

View File

@ -88,24 +88,9 @@ public:
// removes the lastmost directory from the path
void RemoveLast() { wxFileName::RemoveDir(GetCount() - 1); }
// ------------------------------------------------------------------------
bool Normalize( int flags = wxPATH_NORM_ALL, const wxString& cwd = wxEmptyString )
{
wxASSERT_MSG( IsDir(), L"Warning: Malformed directory name detected during wDirName normalization." );
return wxFileName::Normalize( flags, cwd );
}
bool MakeRelativeTo( const wxString& pathBase = wxEmptyString )
{
wxASSERT_MSG( IsDir(), L"Warning: Malformed directory name detected during wDirName normalization." );
return wxFileName::MakeRelativeTo( pathBase );
}
bool MakeAbsolute( const wxString& cwd = wxEmptyString )
{
wxASSERT_MSG( IsDir(), L"Warning: Malformed directory name detected during wDirName normalization." );
return wxFileName::MakeAbsolute( cwd );
}
wxDirName& Normalize( int flags = wxPATH_NORM_ALL, const wxString& cwd = wxEmptyString );
wxDirName& MakeRelativeTo( const wxString& pathBase = wxEmptyString );
wxDirName& MakeAbsolute( const wxString& cwd = wxEmptyString );
// ------------------------------------------------------------------------
@ -181,7 +166,7 @@ namespace PathDefs
extern const wxDirName Snapshots;
extern const wxDirName Savestates;
extern const wxDirName MemoryCards;
extern const wxDirName Configs;
extern const wxDirName Settings;
extern const wxDirName Plugins;
extern const wxDirName Themes;
@ -192,7 +177,7 @@ namespace PathDefs
extern wxDirName GetPlugins();
extern wxDirName GetSavestates();
extern wxDirName GetMemoryCards();
extern wxDirName GetConfigs();
extern wxDirName GetSettings();
}
namespace FilenameDefs

View File

@ -1,7 +1,20 @@
#ifndef PCSX2_PRECOMPILED_HEADER
#define PCSX2_PRECOMPILED_HEADER
//#pragma once
//#pragma once // no dice, causes problems in GCC PCH (which doesn't really work very well
//////////////////////////////////////////////////////////////////////////////////////////
// Define PCSX2's own i18n helpers. These override the wxWidgets helpers and provide
// additional functionality.
//
#define WXINTL_NO_GETTEXT_MACRO
#undef _
#define _(s) pxGetTranslation(_T(s))
// macro provided for tagging translation strings, without actually running them through the
// translator (which the _() does automatically, and sometimes we don't want that). This is
// a shorthand replacement for wxTRANSLATE.
#define wxLt(a) (a)
#define NOMINMAX // Disables other libs inclusion of their own min/max macros (we use std instead)
@ -38,6 +51,7 @@
#include <sys/stat.h>
#include <pthread.h>
using std::string; // we use it enough, so bring it into the global namespace.
using std::min;
using std::max;
@ -49,10 +63,6 @@ typedef int BOOL;
#define TRUE 1
#define FALSE 0
// macro provided for tagging translation strings, without actually running them through the
// translator (which the _() does automatically, and sometimes we don't want that)
#define wxLt(a) a
#define wxASSERT_MSG_A( cond, msg ) wxASSERT_MSG( cond, wxString::FromAscii(msg).c_str() );
//////////////////////////////////////////////////////////////////////////////////////////
@ -61,6 +71,7 @@ typedef int BOOL;
// need a full recompile anyway, when modified (etc)
#include "zlib/zlib.h"
#include "i18n.h"
#include "Pcsx2Defs.h"
#include "Paths.h"
#include "Config.h"

View File

@ -2048,7 +2048,7 @@ void _vuXITOP(VURegs * VU) {
void _vuXGKICK(VURegs * VU)
{
u32* ptr = (u32*)GET_VU_MEM(VU, (VU->VI[_Is_].US[0]*16) & (VU == &VU1 ? 0x3fff : 0xfff));
// u32* ptr = (u32*)GET_VU_MEM(VU, (VU->VI[_Is_].US[0]*16) & (VU == &VU1 ? 0x3fff : 0xfff));
// int temp = 0x4000 - ((VU->VI[_Is_].US[0]*16) & 0x3fff);
// u32 tempmem[0x8000];

View File

@ -464,11 +464,6 @@ static int VIFalign(u32 *data, vifCode *v, unsigned int size, const unsigned int
if (vif->cl != 0 || (size & 0xf)) //Check alignment for SSE unpacks
{
#ifdef PCSX2_DEBUG
static int s_count = 0;
#endif
int incdest;
if (vifRegs->cycle.cl >= vifRegs->cycle.wl) // skipping write
@ -611,10 +606,6 @@ static void VIFunpack(u32 *data, vifCode *v, unsigned int size, const unsigned i
if (vifRegs->cycle.cl >= vifRegs->cycle.wl) // skipping write
{
#ifdef PCSX2_DEBUG
static int s_count = 0;
#endif
if (v->addr >= memlimit)
{
//DevCon::Notice("Overflown at the start");

View File

@ -19,7 +19,7 @@
#include "PrecompiledHeader.h"
#include "Misc.h"
#include "App.h"
#include "AboutBoxDialog.h"
#include "Dialogs/ModalPopups.h"
#include "wxHelpers.h"
#include "Resources/EmbeddedImage.h"
@ -27,6 +27,7 @@
#include <wx/mstream.h>
#include <wx/hyperlink.h>
using namespace wxHelpers;
namespace Dialogs {
@ -97,19 +98,19 @@ AboutBoxDialog::AboutBoxDialog( wxWindow* parent, int id ):
label_auth->Wrap( m_bitmap_logo.GetSize().GetWidth() / 2 );
label_greets->Wrap( (m_bitmap_logo.GetSize().GetWidth() * 4) / 3 );
aboutUs.Add( label_auth, stdSpacingFlags );
contribs.Add( label_greets, stdSpacingFlags.Expand() );
aboutUs.Add( label_auth, SizerFlags::StdSpace() );
contribs.Add( label_greets, SizerFlags::StdExpand() );
AuthLogoSizer.Add( &aboutUs );
AuthLogoSizer.AddSpacer( 7 );
AuthLogoSizer.Add( &m_bitmap_logo, wxSizerFlags().Border( wxALL, 4 ) );
ContribSizer.AddStretchSpacer( 1 );
ContribSizer.Add( &m_bitmap_ps2system, stdSpacingFlags );
ContribSizer.Add( &m_bitmap_ps2system, SizerFlags::StdSpace() );
ContribSizer.AddStretchSpacer( 1 );
ContribSizer.Add( &contribs, wxSizerFlags(7).HorzBorder().Expand() );
mainSizer.Add( &AuthLogoSizer, stdSpacingFlags );
mainSizer.Add( &AuthLogoSizer, SizerFlags::StdSpace() );
mainSizer.Add( new wxHyperlinkCtrl(
this, wxID_ANY, L"Pcsx2 Official Website and Forums" , L"http://www.pcsx2.net" ),
@ -118,9 +119,9 @@ AboutBoxDialog::AboutBoxDialog( wxWindow* parent, int id ):
this, wxID_ANY, L"Pcsx2 Official Svn Repository at Googlecode" , L"http://code.google.com/p/pcsx2" ),
wxSizerFlags(1).Center().Border( wxALL, 3 ) );
mainSizer.Add( &ContribSizer, stdSpacingFlags.Expand() );
mainSizer.Add( &ContribSizer, SizerFlags::StdExpand() );
mainSizer.Add( new wxButton( this, wxID_OK, L"I've seen enough"), stdCenteredFlags );
mainSizer.Add( new wxButton( this, wxID_OK, L"I've seen enough"), SizerFlags::StdCenter() );
SetSizerAndFit( &mainSizer );
}

View File

@ -70,17 +70,22 @@ protected:
void OnResize( wxSizeEvent& evt );
};
//////////////////////////////////////////////////////////////////////////////////////////
//
struct AppImageIds
{
struct ConfigIds
{
int Paths,
Plugins,
Speedhacks,
Gamefixes,
Video;
ConfigIds() :
Paths( -1 )
, Plugins( -1 )
, Speedhacks( -1 )
, Gamefixes( -1 )
, Video( -1 )
@ -148,6 +153,8 @@ public:
ConsoleLogFrame* GetConsoleFrame() const { return m_ConsoleFrame; }
void SetConsoleFrame( ConsoleLogFrame& frame ) { m_ConsoleFrame = &frame; }
protected:
void ReadUserModeSettings();
bool TryOpenConfigCwd();
};

View File

@ -31,14 +31,14 @@
//
namespace PathDefs
{
const wxDirName Snapshots( L"snaps" );
const wxDirName Savestates( L"sstates" );
const wxDirName MemoryCards( L"memcards" );
const wxDirName Configs( L"inis" );
const wxDirName Plugins( L"plugins" );
const wxDirName Logs( L"logs" );
const wxDirName Dumps( L"dumps" );
const wxDirName Themes( L"themes" );
const wxDirName Snapshots ( L"snaps" );
const wxDirName Savestates ( L"sstates" );
const wxDirName MemoryCards ( L"memcards" );
const wxDirName Settings ( L"inis" );
const wxDirName Plugins ( L"plugins" );
const wxDirName Logs ( L"logs" );
const wxDirName Dumps ( L"dumps" );
const wxDirName Themes ( L"themes" );
// Specifies the root folder for the application install.
// (currently it's the CWD, but in the future I intend to move all binaries to a "bin"
@ -49,18 +49,20 @@ namespace PathDefs
// share with other programs: screenshots, memory cards, and savestates.
wxDirName GetDocuments()
{
wxString wtf( wxStandardPaths::Get().GetDocumentsDir() );
return (wxDirName)wxStandardPaths::Get().GetDocumentsDir() + (wxDirName)wxGetApp().GetAppName();
if( g_Conf.UseAdminMode )
return (wxDirName)wxGetCwd();
else
return (wxDirName)wxStandardPaths::Get().GetDocumentsDir() + (wxDirName)wxGetApp().GetAppName();
}
wxDirName GetSnapshots()
{
return (wxDirName)GetDocuments() + Snapshots;
return GetDocuments() + Snapshots;
}
wxDirName GetBios()
{
return AppRoot + wxDirName( L"bios" );
return GetDocuments() + wxDirName( L"bios" );
}
wxDirName GetSavestates()
@ -73,16 +75,16 @@ namespace PathDefs
return GetDocuments() + MemoryCards;
}
wxDirName GetConfigs()
{
return GetDocuments() + Configs;
}
wxDirName GetPlugins()
{
return AppRoot + Plugins;
}
wxDirName GetSettings()
{
return GetDocuments() + Settings;
}
wxDirName GetThemes()
{
return AppRoot + Themes;
@ -134,6 +136,7 @@ wxFileName wxDirName::Combine( const wxFileName& right ) const
return result;
}
// ------------------------------------------------------------------------
wxDirName wxDirName::Combine( const wxDirName& right ) const
{
wxASSERT_MSG( IsDir() && right.IsDir(), L"Warning: Malformed directory name detected during wDirName concatenation." );
@ -143,6 +146,34 @@ wxDirName wxDirName::Combine( const wxDirName& right ) const
return result;
}
// ------------------------------------------------------------------------
wxDirName& wxDirName::Normalize( int flags, const wxString& cwd )
{
wxASSERT_MSG( IsDir(), L"Warning: Malformed directory name detected during wDirName normalization." );
if( !wxFileName::Normalize( flags, cwd ) )
throw Exception::RuntimeError( "wxDirName::Normalize operation failed." );
return *this;
}
// ------------------------------------------------------------------------
wxDirName& wxDirName::MakeRelativeTo( const wxString& pathBase )
{
wxASSERT_MSG( IsDir(), L"Warning: Malformed directory name detected during wDirName normalization." );
if( !wxFileName::MakeRelativeTo( pathBase ) )
throw Exception::RuntimeError( "wxDirName::MakeRelativeTo operation failed." );
return *this;
}
// ------------------------------------------------------------------------
wxDirName& wxDirName::MakeAbsolute( const wxString& cwd )
{
wxASSERT_MSG( IsDir(), L"Warning: Malformed directory name detected during wDirName normalization." );
if( !wxFileName::MakeAbsolute( cwd ) )
throw Exception::RuntimeError( "wxDirName::MakeAbsolute operation failed." );
return *this;
}
// ------------------------------------------------------------------------
void wxDirName::Rmdir()
{
if( !Exists() ) return;
@ -171,6 +202,66 @@ wxString AppConfig::FullpathHelpers::Mcd( uint mcdidx ) const { return Path::Com
//
#define IniEntry( varname, defval ) ini.Entry( wxT(#varname), varname, defval )
// ------------------------------------------------------------------------
void AppConfig::LoadSaveUserMode( IniInterface& ini )
{
IniEntry( UseAdminMode, false );
ini.Entry( L"SettingsPath", Folders.Settings, PathDefs::GetSettings() );
ini.Flush();
}
// ------------------------------------------------------------------------
//
void i18n_DoPackageCheck( int wxLangId, wxArrayString& destEng, wxArrayString& destTrans )
{
// Note: wx auto-preserves the current locale for us
if( !wxLocale::IsAvailable( wxLangId ) ) return;
wxLocale* locale = new wxLocale( wxLangId, wxLOCALE_CONV_ENCODING );
if( locale->IsOk() && locale->AddCatalog( L"pcsx2ident" ) )
{
// Should be a valid language, so add it to the list.
destEng.Add( wxLocale::GetLanguageName( wxLangId ) );
destTrans.Add( wxGetTranslation( L"NativeName" ) );
}
delete locale;
}
// ------------------------------------------------------------------------
// Finds all valid PCSX2 language packs, and enumerates them for configuration selection.
// Note: On linux there's no easy way to reliably enumerate language packs, since every distro
// could use its own location for installing pcsx2.mo files (wtcrap?). Furthermore wxWidgets
// doesn't give us a public API for checking what the language search paths are. So the only
// safe way to enumerate the languages is by forcibly loading every possible locale in the wx
// database. Anything which hasn't been installed will fail to load.
//
// Because loading and hashing the entire pcsx2 translation for every possible language would
// assinine and slow, I've decided to use a two-file translation system. One file is very
// small and simply contains the name of the language in the language native. The second file
// is loaded only if the user picks it (or if it's the default language of the OS).
//
void i18n_EnumeratePackages( wxArrayString& englishNames, wxArrayString& xlatedNames)
{
for( int li=wxLANGUAGE_ABKHAZIAN; li<wxLANGUAGE_ZULU; ++li )
{
i18n_DoPackageCheck( li, englishNames, xlatedNames );
}
// Brilliant. Because someone in the wx world didn't think to move wxLANGUAGE_USER_DEFINED
// to a place where it wasn't butt right up against the main languages (like, say, start user
// defined values at 4000 or something?), they had to add new languages in at some arbitrary
// value instead. Let's handle them here:
// fixme: these won't show up in alphabetical order if they're actually present (however
// horribly unlikely that is)... do we care? Probably not.
i18n_DoPackageCheck( wxLANGUAGE_VALENCIAN, englishNames, xlatedNames );
i18n_DoPackageCheck( wxLANGUAGE_SAMI, englishNames, xlatedNames );
}
// ------------------------------------------------------------------------
void AppConfig::LoadSave( IniInterface& ini )
{
IniEntry( MainGuiPosition, wxDefaultPosition );
@ -185,9 +276,31 @@ void AppConfig::LoadSave( IniInterface& ini )
ini.Flush();
}
// ------------------------------------------------------------------------
//
void AppConfig::Apply()
{
// Language Application:
// Three stages. First we try and configure the requested language. If that fails,
// we fall back on the default language for the user's operating system. If that
// fails we fall back on good old english.
//wxLocale* locale;
if( !i18n_SetLanguage( LanguageId ) )
{
if( !i18n_SetLanguage( wxLANGUAGE_DEFAULT ) )
{
//wxGetTranslation();
}
}
}
// ------------------------------------------------------------------------
void AppConfig::Load()
{
// Note: Extra parenthisis resolves "I think this is a function" issues with C++.
// Note: Extra parenthesis resolves "I think this is a function" issues with C++.
IniLoader loader( (IniLoader()) );
LoadSave( loader );
}
@ -227,12 +340,12 @@ void AppConfig::FolderOptions::LoadSave( IniInterface& ini )
const wxDirName def( L"default" );
IniEntry( Plugins, PathDefs::GetPlugins() );
IniEntry( Settings, PathDefs::GetSettings() );
IniEntry( Bios, PathDefs::GetBios() );
IniEntry( Snapshots, PathDefs::GetSnapshots() );
IniEntry( Savestates, PathDefs::GetSavestates() );
IniEntry( MemoryCards, PathDefs::GetMemoryCards() );
IniEntry( Logs, PathDefs::GetLogs() );
IniEntry( Dumps, PathDefs::GetDumps() );
ini.SetPath( L".." );
}

View File

@ -253,7 +253,8 @@ namespace Console
if( ConsoleLogFrame* FrameHandle = wxGetApp().GetConsoleFrame() )
FrameHandle->Newline();
fputs( "\n", emuLog );
if( emuLog != NULL )
fputs( "\n", emuLog );
return false;
}
@ -263,7 +264,8 @@ namespace Console
if( ConsoleLogFrame* FrameHandle = wxGetApp().GetConsoleFrame() )
FrameHandle->Write( fmt );
fputs( fmt, emuLog );
if( emuLog != NULL )
fputs( fmt, emuLog );
return false;
}
@ -273,7 +275,8 @@ namespace Console
if( ConsoleLogFrame* FrameHandle = wxGetApp().GetConsoleFrame() )
FrameHandle->Write( fmt );
fputs( fmt.ToAscii().data(), emuLog );
if( emuLog != NULL )
fputs( fmt.ToAscii().data(), emuLog );
return false;
}
}

View File

@ -41,22 +41,22 @@ Dialogs::ConfigurationDialog::ConfigurationDialog( wxWindow* parent, int id ) :
#endif
wxBoxSizer& mainSizer = *new wxBoxSizer( wxVERTICAL );
wxListbook& Notebook = *new wxListbook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, orient );
wxListbook& listbook = *new wxListbook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, orient );
Notebook.SetImageList( &wxGetApp().GetImgList_Config() );
listbook.SetImageList( &wxGetApp().GetImgList_Config() );
const AppImageIds::ConfigIds& cfgid( wxGetApp().GetImgId().Config );
Notebook.AddPage( new PathsPanel( Notebook ), L"Paths", false, cfgid.Paths );
//Notebook->AddPage( new PluginSelectionPanel( Notebook ), L"Plugins" );
Notebook.AddPage( new SpeedHacksPanel( Notebook ), L"Speedhacks", true, cfgid.Speedhacks );
Notebook.AddPage( new GameFixesPanel( Notebook ), L"Game Fixes", false, cfgid.Gamefixes );
listbook.AddPage( new PathsPanel( listbook ), L"Paths", false, cfgid.Paths );
listbook.AddPage( new PluginSelectorPanel( listbook ), L"Plugins", false, cfgid.Plugins );
listbook.AddPage( new SpeedHacksPanel( listbook ), L"Speedhacks", true, cfgid.Speedhacks );
listbook.AddPage( new GameFixesPanel( listbook ), L"Game Fixes", false, cfgid.Gamefixes );
mainSizer.Add( &Notebook );
AddOkCancel( mainSizer );
mainSizer.Add( &listbook );
AddOkCancel( mainSizer, true );
SetSizerAndFit( &mainSizer );
Center();
Center( wxCENTER_ON_SCREEN );
}

View File

@ -21,6 +21,8 @@
#include <wx/wx.h>
#include <wx/image.h>
#include "wxHelpers.h"
namespace Dialogs
{
class AboutBoxDialog: public wxDialog
@ -33,5 +35,11 @@ namespace Dialogs
wxStaticBitmap m_bitmap_ps2system;
};
class PickUserModeDialog : public wxDialogWithHelpers
{
public:
PickUserModeDialog( wxWindow* parent, int id=wxID_ANY );
};
}

View File

@ -16,22 +16,21 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __MCDSDLG_H__
#define __MCDSDLG_H__
#include "PrecompiledHeader.h"
// Old school memcard manager that never got finished/working :(
//BOOL CALLBACK ConfigureMcdsDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam);
#include "ModalPopups.h"
class MemcardConfig
using namespace wxHelpers;
Dialogs::PickUserModeDialog::PickUserModeDialog( wxWindow* parent, int id ) :
wxDialogWithHelpers( parent, id, _("PCSX2 Select User Mode"), false )
{
protected:
static void Open_Mcd_Proc(HWND hW, int mcd);
static BOOL CALLBACK DialogProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam);
wxBoxSizer& s_main = *new wxBoxSizer( wxVERTICAL );
public:
static void OpenDialog();
static void LoadSettings();
};
AddStaticText( s_main, _("PCSX2 is starting from a new or unknown working directory and needs to be configured."), 400 );
AddStaticText( s_main, _("Current Working Directory: ") + wxGetCwd(), 480 );
AddOkCancel( s_main );
}
#endif

View File

@ -46,13 +46,13 @@ LogOptionsDialog::eeLogOptionsPanel::eeLogOptionsPanel( wxWindow* parent ) :
AddCheckBoxTo( this, eeMisc, L"Memory", LogID_Memory );
AddCheckBoxTo( this, eeMisc, L"Bios", LogID_Bios );
AddCheckBoxTo( this, eeMisc, L"Elf", LogID_ELF );
AddCheckBoxTo( this, eeMisc, L"Elf", LogID_ELF );
wxBoxSizer& eeStack = *new wxBoxSizer( wxVERTICAL );
eeStack.Add( new DisasmPanel( this ), stdSpacingFlags );
eeStack.Add( new DisasmPanel( this ), SizerFlags::StdSpace() );
eeStack.Add( &eeMisc );
ThisSizer.Add( new HwPanel( this ), stdSpacingFlags );
ThisSizer.Add( new HwPanel( this ), SizerFlags::StdSpace() );
ThisSizer.Add( &eeStack );
SetValue( true );
@ -62,11 +62,11 @@ LogOptionsDialog::eeLogOptionsPanel::eeLogOptionsPanel( wxWindow* parent ) :
LogOptionsDialog::eeLogOptionsPanel::DisasmPanel::DisasmPanel( wxWindow* parent ) :
CheckedStaticBox( parent, wxVERTICAL, L"Disasm" , LogID_Disasm )
{
AddCheckBox( L"Core", LogID_CPU );
AddCheckBox( L"Core", LogID_CPU );
AddCheckBox( L"Fpu", LogID_FPU );
AddCheckBox( L"VU0", LogID_VU0 );
AddCheckBox( L"Cop0", LogID_COP0 );
AddCheckBox( L"VU Macro",LogID_VU_Macro );
AddCheckBox( L"Cop0", LogID_COP0 );
AddCheckBox( L"VU Macro", LogID_VU_Macro );
SetValue( false );
Fit();
@ -75,7 +75,7 @@ LogOptionsDialog::eeLogOptionsPanel::DisasmPanel::DisasmPanel( wxWindow* parent
LogOptionsDialog::eeLogOptionsPanel::HwPanel::HwPanel( wxWindow* parent ) :
CheckedStaticBox( parent, wxVERTICAL, L"Hardware", LogID_Hardware )
{
AddCheckBox( L"Registers", LogID_Registers );
AddCheckBox( L"Registers", LogID_Registers );
AddCheckBox( L"Dma", LogID_DMA );
AddCheckBox( L"Vif", LogID_VIF );
AddCheckBox( L"SPR", LogID_SPR );
@ -132,11 +132,11 @@ LogOptionsDialog::LogOptionsDialog(wxWindow* parent, int id, const wxPoint& pos,
// only wanted to work right for the miscSizer and I couldn't figure out why the CheckStaticBox
// panel wouldn't also resize to fit the window.. :( -- air
topSizer.Add( &eeBox, stdSpacingFlags ); //.Expand() );
topSizer.Add( &iopSizer, stdSpacingFlags ); //.Expand() );
topSizer.Add( &eeBox, SizerFlags::StdSpace() ); //.Expand() );
topSizer.Add( &iopSizer, SizerFlags::StdSpace() ); //.Expand() );
mainsizer.Add( &topSizer ); //, wxSizerFlags().Expand() ); // topsizer has it's own padding.
mainsizer.Add( &miscSizer, stdSpacingFlags ); //.Expand() );
mainsizer.Add( &miscSizer, SizerFlags::StdSpace() ); //.Expand() );
AddOkCancel( mainsizer );

View File

@ -19,7 +19,7 @@
#include "PrecompiledHeader.h"
#include "MainFrame.h"
#include "LogOptionsDialog.h"
#include "AboutBoxDialog.h"
#include "Dialogs/ModalPopups.h"
#include "Resources/EmbeddedImage.h"
#include "Resources/AppIcon.h"

View File

@ -25,6 +25,7 @@
#pragma once
#include <wx/image.h>
#include <wx/statline.h>
#include "wxHelpers.h"
@ -68,8 +69,38 @@ namespace Panels
//
class PathsPanel: public wxPanelWithHelpers
{
protected:
class MyBasePanel : public wxPanelWithHelpers
{
public:
MyBasePanel(wxWindow& parent, int id=wxID_ANY);
protected:
wxDirPickerCtrl& AddDirPicker( wxBoxSizer& sizer, int id, const wxDirName& defaultPath, const wxString& label, const wxString& dialogLabel, bool pathMustExist=true );
};
class StandardPanel : public MyBasePanel
{
public:
StandardPanel(wxWindow& parent, int id=wxID_ANY);
};
class AdvancedPanel : public MyBasePanel
{
public:
AdvancedPanel(wxWindow& parent, int id=wxID_ANY);
};
public:
PathsPanel(wxWindow& parent, int id=wxID_ANY);
};
//////////////////////////////////////////////////////////////////////////////////////////
//
class PluginSelectorPanel: public wxPanelWithHelpers
{
public:
PluginSelectorPanel(wxWindow& parent, int id=wxID_ANY);
protected:

View File

@ -41,8 +41,8 @@ Panels::GameFixesPanel::GameFixesPanel( wxWindow& parent, int id ) :
AddCheckBox( groupSizer, _T("VU Add / Sub Hack - Special fix for Tri-Ace games!") );
AddCheckBox( groupSizer, _T("VU Clip Hack - Special fix for God of War") );
mainSizer.Add( label_Title, stdCenteredFlags );
mainSizer.Add( &groupSizer, stdSpacingFlags );
mainSizer.Add( label_Title, SizerFlags::StdCenter() );
mainSizer.Add( &groupSizer, SizerFlags::StdSpace() );
SetSizerAndFit( &mainSizer );

View File

@ -17,11 +17,118 @@
*/
#include "PrecompiledHeader.h"
#include "ConfigurationPanels.h"
#include <wx/notebook.h>
#include <wx/stdpaths.h>
using namespace wxHelpers;
static const int BetweenFolderSpace = 5;
// ------------------------------------------------------------------------
wxDirPickerCtrl& Panels::PathsPanel::MyBasePanel::AddDirPicker( wxBoxSizer& sizer, int id, const wxDirName& defaultPath, const wxString& label, const wxString& dialogLabel, bool pathMustExist )
{
// fixme: Should wxGTK (linux) force-enable the wxDIRP_USE_TEXTCTRL? It's not "standard" on that platform
// but it might still be preferred. - air
wxDirName normalized( defaultPath );
normalized.Normalize();
wxDirPickerCtrl* jobe = new wxDirPickerCtrl( this, id, normalized.ToString(), dialogLabel );
wxStaticBoxSizer& s_box = *new wxStaticBoxSizer( wxVERTICAL, this, label );
s_box.Add( jobe, wxSizerFlags().Border(wxLEFT | wxRIGHT | wxTOP, 5).Expand() );
AddCheckBox( s_box, _("Use operating system default settings") );
sizer.Add( &s_box, SizerFlags::StdGroupie() );
return *jobe;
}
// ------------------------------------------------------------------------
Panels::PathsPanel::MyBasePanel::MyBasePanel( wxWindow& parent, int id ) :
wxPanelWithHelpers( &parent, id )
{
}
// ------------------------------------------------------------------------
Panels::PathsPanel::StandardPanel::StandardPanel( wxWindow& parent, int id ) :
MyBasePanel( parent, id )
{
wxBoxSizer& s_main = *new wxBoxSizer( wxVERTICAL );
AddDirPicker( s_main, wxID_ANY, g_Conf.Folders.Bios, _("Bios:"), _("Select folder with PS2 Bios") )
.SetToolTip( pxE(Msg_Tooltips_Bios) );
s_main.AddSpacer( BetweenFolderSpace );
AddDirPicker( s_main, wxID_ANY, g_Conf.Folders.Savestates, _("Savestates:"), _("Select folder for Savestates") )
.SetToolTip( pxE(Msg_Tooltips_Savestates) );
s_main.AddSpacer( BetweenFolderSpace );
AddDirPicker( s_main, wxID_ANY, g_Conf.Folders.Snapshots, _("Snapshots:"), _("Select a folder for Snapshots") )
.SetToolTip( pxE(Msg_Tooltips_Snapshots) );
s_main.AddSpacer( BetweenFolderSpace );
AddDirPicker( s_main, wxID_ANY, g_Conf.Folders.Logs, _("Log/Dumps:" ), _("Select a folder for logs/dumps") )
.SetToolTip( pxE(Msg_Tooltips_Logs) );
s_main.AddSpacer( BetweenFolderSpace );
AddDirPicker( s_main, wxID_ANY, g_Conf.Folders.MemoryCards, _("Memorycards:"), _("Select a default Memorycards folder") )
.SetToolTip( pxE(Msg_Tooltips_Memorycards) );
s_main.AddSpacer( 5 );
SetSizerAndFit( &s_main );
}
// ------------------------------------------------------------------------
Panels::PathsPanel::AdvancedPanel::AdvancedPanel( wxWindow& parent, int id ) :
MyBasePanel( parent, id )
{
wxBoxSizer& s_main = *new wxBoxSizer( wxVERTICAL );
wxStaticBoxSizer& advanced = *new wxStaticBoxSizer( wxVERTICAL, this, _("Advanced") );
AddStaticText( advanced, pxE(Msg_Dialog_AdvancedPaths), 420, wxALIGN_CENTRE );
AddDirPicker( advanced, wxID_ANY, g_Conf.Folders.Plugins, _("Plugins:"), _("Select folder for PCSX2 plugins") )
.SetToolTip( pxE(Msg_Tooltips_PluginsPath) );
advanced.AddSpacer( BetweenFolderSpace );
AddDirPicker( advanced, wxID_ANY, g_Conf.Folders.Settings, _("Settings:"), _("Select a folder for PCSX2 settings/inis") )
.SetToolTip( pxE(Msg_Tooltips_SettingsPath) );
wxStaticBoxSizer& s_diag = *new wxStaticBoxSizer( wxVERTICAL, this, _("Default folder mode") );
AddStaticText( s_diag,
L"This setting only affects folders which are set to use the default folder configurations for your "
L"operating system. Any folders which are configured manually will override this option. ",
400, wxALIGN_CENTRE );
AddRadioButton( s_diag, _("Use to your Documents folder"), _("Location: ") + wxStandardPaths::Get().GetDocumentsDir() );
AddRadioButton( s_diag, _("Use the current working folder"), _("Location: ") + wxGetCwd() );
s_diag.AddSpacer( 4 );
advanced.AddSpacer( 4 );
advanced.Add( &s_diag, SizerFlags::StdGroupie() );
s_main.Add( &advanced, SizerFlags::StdGroupie() );
s_main.AddSpacer( 5 );
SetSizerAndFit( &s_main );
}
// ------------------------------------------------------------------------
Panels::PathsPanel::PathsPanel( wxWindow& parent, int id ) :
wxPanelWithHelpers( &parent, id )
{
wxBoxSizer& s_main = *new wxBoxSizer( wxVERTICAL );
wxNotebook& notebook = *new wxNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_BOTTOM | wxNB_FIXEDWIDTH );
notebook.AddPage( new StandardPanel( notebook ), _("Standard") );
notebook.AddPage( new AdvancedPanel( notebook ), _("Advanced") );
s_main.Add( &notebook, SizerFlags::StdSpace() );
SetSizerAndFit( &s_main );
}

View File

@ -17,3 +17,11 @@
*/
#include "PrecompiledHeader.h"
#include "ConfigurationPanels.h"
Panels::PluginSelectorPanel::PluginSelectorPanel( wxWindow& parent, int id ) :
wxPanelWithHelpers( &parent, id )
{
}

View File

@ -40,7 +40,7 @@ Panels::SpeedHacksPanel::SpeedHacksPanel( wxWindow& parent, int id ) :
wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE
);
mainSizer.Add( label_Title, stdCenteredFlags );
mainSizer.Add( label_Title, SizerFlags::StdCenter() );
wxSlider* vuScale = new wxSlider(this, wxID_ANY, Config.Hacks.VUCycleSteal, 0, 4 );
wxSlider* eeScale = new wxSlider(this, wxID_ANY, Config.Hacks.EECycleRate, 0, 2);

178
pcsx2/gui/i18n.cpp Normal file
View File

@ -0,0 +1,178 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 Pcsx2 Team
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "PrecompiledHeader.h"
#include "i18n.h"
#include "HashMap.h"
#include "Utilities/SafeArray.h"
using namespace HashTools;
//////////////////////////////////////////////////////////////////////////////////////////
// Notes to Translators:
// * The first line of each entry consists of an enumerated index (used internally), and
// the gettext lookup string (which you'll find in the PO data). The resulting translation
// should match the text underneath.
//
// * Text marked as Tooltips are usually tertiary information that is not critical to PCSX2
// use, and translations are not required.
//
const EnglishExpansionEntry m_tbl_English[] =
{
{ Msg_Dialog_AdvancedPaths, wxLt(L"Settings Dialog:Advanced Paths"),
L"Warning!! These advanced options are provided for developers and advanced testers only. "
L"Changing these settings can cause program errors, so please be weary."
},
{ Msg_Tooltips_SettingsPath, wxLt(L"Setting Tooltip:Settings Path"),
L"This is the folder where PCSX2 saves all settings, including settings generated "
L"by most plugins.\n\nWarning: Some older versions of plugins may not respect this value."
},
// ------------------------------------------------------------------------
// Begin Tooltips Section
// (All following texts are non-critical for a functional PCSX2 translation).
{ Msg_Tooltips_PluginsPath, wxLt(L"Setting Tooltip:Plugins Path"),
L"This is the location where PCSX2 will expect to find its plugins. Plugins found in this folder "
L"will be enumerated and are selectable from the Plugins panel."
},
{ Msg_Tooltips_Savestates, wxLt(L"Setting Tooltip:Savestates Folder"),
L"This folder is where PCSX2 records savestates; which are recorded either by using "
L"menus/toolbars, or by pressing F1/F3 (load/save)."
},
{ Msg_Tooltips_Snapshots, wxLt(L"Setting Tooltip:Snapshots Folder"),
L"This folder is where PCSX2 saves screenshots. Actual screenshot image format and style "
L"may vary depending on the GS plugin being used."
},
{ Msg_Tooltips_Bios, wxLt(L"Setting Tooltip:Bios Folder"),
L"This folder is where PCSX2 looks to find PS2 bios files. The actual bios used can be "
L"selected from the CPU dialog."
},
{ Msg_Tooltips_Logs, wxLt(L"Setting Tooltip:Logs Folder"),
L"This folder is where PCSX2 saves its logfiles and diagnostic dumps. Most plugins will "
L"also adhere to this folder, however some older plugins may ignore it."
},
{ Msg_Tooltips_Memorycards, wxLt(L"Setting Tooltip:Memorycards Folder"),
L"This is the default path where PCSX2 loads or creates its memory cards, and can be "
L"overridden in the MemoryCard Configuration by using absolute filenames."
},
};
C_ASSERT( ArraySize( m_tbl_English ) == ExpandedMsg_Count );
static HashMap<int,HashedExpansionPair> m_EnglishExpansions( -1, 0xcdcdcd, ArraySize( m_tbl_English ) );
// ------------------------------------------------------------------------
// Builds an internal hashtable for English iconized description lookups.
//
void i18n_InitPlainEnglish()
{
static bool IsInitialized = false;
IsInitialized = true;
for( int i=0; i<ExpandedMsg_Count; ++i )
{
HashedExpansionPair silly = { m_tbl_English[i].gettextKey, m_tbl_English[i].Expanded };
m_EnglishExpansions[m_tbl_English[i].Key] = silly;
}
}
// ------------------------------------------------------------------------
// PCSX2's Iconized Text Translator.
// This i18n version provides two layers of translated lookups. It puts the key through the
// current language first and, if the key is not resolved (meaning the language pack doesn't
// have a translation for it), it's put through our own built-in english translation. This
// second step is needed to resolve some of our lengthy UI tooltips and descriptors, which
// use iconized GetText identifiers.
//
// (without this second pass many tooltips would just show up as "Savestate Tooltip" instead
// of something meaningful).
//
const wxChar* __fastcall pxExpandMsg( ExpandedMsgEnum key )
{
const HashedExpansionPair& data( m_EnglishExpansions[key] );
int curlangid = wxLocale::GetLanguageInfo( g_Conf.LanguageId )->Language;
if( curlangid == wxLANGUAGE_ENGLISH || curlangid == wxLANGUAGE_ENGLISH_US )
return data.Expanded;
const wxChar* retval = wxGetTranslation( data.gettextKey );
// Check if the translation failed, and fall back on an english lookup.
return ( wxStrcmp( retval, data.gettextKey ) == 0 ) ? data.Expanded : retval;
}
// ------------------------------------------------------------------------
// Alternative implementation for wxGetTranslation.
// This version performs a string length check in devel builds, which issues a warning
// if the string seems too long for gettext lookups. Longer complicated strings should
// usually be implemented used the pxMsgExpand system instead.
//
const wxChar* __fastcall pxGetTranslation( const wxChar* message )
{
if( IsDevBuild )
{
if( wxStrlen( message ) > 96 )
{
Console::Notice( "pxGetTranslation: Long message detected, maybe use pxExpandMsg instead?" );
Console::Status( wxsFormat( L"\tMessage: %s", message ) );
}
}
return wxGetTranslation( message );
}
// ------------------------------------------------------------------------
bool i18n_SetLanguage( int wxLangId )
{
if( !wxLocale::IsAvailable( wxLangId ) )
{
Console::Notice( "Invalid Language Identifier (wxID=%d).", params wxLangId );
return false;
}
wxLocale* locale = new wxLocale( wxLangId, wxLOCALE_CONV_ENCODING );
if( !locale->IsOk() )
{
Console::Notice( wxsFormat( L"SetLanguage: '%s' [%s] is not supported by the operating system",
wxLocale::GetLanguageName( locale->GetLanguage() ), locale->GetCanonicalName() )
);
safe_delete( locale );
return false;
}
if( !locale->AddCatalog( L"pcsx2main" ) ) //, wxLANGUAGE_UNKNOWN, NULL ) )
{
Console::Notice( wxsFormat( L"SetLanguage: Cannot find pcsx2main.mo file for language '%s' [%s]",
wxLocale::GetLanguageName( locale->GetLanguage() ), locale->GetCanonicalName() )
);
safe_delete( locale );
}
//return locale;
return true;
}

63
pcsx2/gui/i18n.h Normal file
View File

@ -0,0 +1,63 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 Pcsx2 Team
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#pragma once
#include <wx/wx.h>
//////////////////////////////////////////////////////////////////////////////////////////
//
enum ExpandedMsgEnum
{
Msg_Dialog_AdvancedPaths,
Msg_Tooltips_Savestates,
Msg_Tooltips_Snapshots,
Msg_Tooltips_Bios,
Msg_Tooltips_Logs,
Msg_Tooltips_Memorycards,
Msg_Tooltips_SettingsPath,
Msg_Tooltips_PluginsPath,
ExpandedMsg_Count
};
//////////////////////////////////////////////////////////////////////////////////////////
// English Tables for "Translating" iconized UI descriptions.
//
struct HashedExpansionPair
{
const wxChar* gettextKey; // send this to wxGetTranslation()
const wxChar* Expanded;
};
struct EnglishExpansionEntry
{
ExpandedMsgEnum Key;
const wxChar* gettextKey; // send this to wxGetTranslation()
const wxChar* Expanded;
};
extern void i18n_InitPlainEnglish();
extern bool i18n_SetLanguage( int wxLangId );
extern const wxChar* __fastcall pxExpandMsg( ExpandedMsgEnum key );
extern const wxChar* __fastcall pxGetTranslation( const wxChar* message );
#define pxE(n) pxExpandMsg( n )

View File

@ -19,6 +19,7 @@
#include "PrecompiledHeader.h"
#include "IniInterface.h"
#include "MainFrame.h"
#include "Dialogs/ModalPopups.h"
#include "Resources/EmbeddedImage.h"
#include "Resources/BackgroundLogo.h"
@ -46,11 +47,33 @@ wxFileConfig* OpenConfig( const wxString& filename )
return new wxFileConfig( wxEmptyString, wxEmptyString, filename, wxEmptyString, wxCONFIG_USE_RELATIVE_PATH );
}
void Pcsx2App::ReadUserModeSettings()
{
wxString configfile( Path::Combine( wxGetCwd(), L"usermode.ini" ) );
if( !wxFile::Exists( configfile ) )
{
Dialogs::PickUserModeDialog( m_MainFrame ).ShowModal();
}
wxFileConfig* conf_usermode = OpenConfig( Path::Combine( wxGetCwd(), L"usermode.ini" ) );
// Ensure proper scoping (IniLoader gets closed prior to delete)
{
IniLoader loader( *conf_usermode );
g_Conf.LoadSaveUserMode( loader );
}
delete conf_usermode;
}
// ------------------------------------------------------------------------
// returns true if a configuration file is present in the current working dir (cwd).
// returns false if not (in which case the calling code should fall back on using OpenConfigUserLocal())
//
bool Pcsx2App::TryOpenConfigCwd()
{
wxDirName inipath_cwd( (wxDirName)wxGetCwd() + PathDefs::Configs );
wxDirName inipath_cwd( (wxDirName)wxGetCwd() + PathDefs::Settings );
if( !inipath_cwd.IsReadable() ) return false;
wxString inifile_cwd( Path::Combine( inipath_cwd, FilenameDefs::GetConfig() ) );
@ -107,23 +130,33 @@ bool Pcsx2App::OnInit()
wxApp::OnInit();
// Ini Startup: The ini file could be in one of two locations, depending on how Pcsx2 has
// been installed or configured. The first place we look is in our program's working
// directory. If the ini there exist, and is *not* empty, then we'll use it. Otherwise
// we fall back on the ini file in the user's Documents folder.
i18n_InitPlainEnglish();
wxLocale::AddCatalogLookupPathPrefix( wxGetCwd() );
// User/Admin Mode Dual Setup:
// Pcsx2 now supports two fundamental modes of operation. The default is Classic mode,
// which uses the Current Working Directory (CWD) for all user data files, and requires
// Admin access on Vista (and some Linux as well). The second mode is the Vista-
// compatible \documents folder usage. The mode is determined by the presence and
// contents of a usermode.ini file in the CWD. If the ini file is missing, we assume
// the user is setting up a classic install. If the ini is present, we read the value of
// the UserMode and SettingsPath vars.
//
// Conveniently this dual mode setup applies equally well to most modern Linux distros.
if( !TryOpenConfigCwd() )
{
PathDefs::GetDocuments().Mkdir();
PathDefs::GetConfigs().Mkdir();
PathDefs::GetSettings().Mkdir();
// Allow wx to use our config, and enforces auto-cleanup as well
wxString confile( Path::Combine( PathDefs::GetConfigs(), FilenameDefs::GetConfig() ) );
wxString confile( Path::Combine( PathDefs::GetSettings(), FilenameDefs::GetConfig() ) );
wxConfigBase::Set( OpenConfig( confile ) );
wxConfigBase::Get()->SetRecordDefaults();
}
g_Conf.Load();
g_Conf.Apply();
m_MainFrame = new MainEmuFrame( NULL, wxID_ANY, wxEmptyString );
SetTopWindow( m_MainFrame );
@ -230,6 +263,7 @@ const wxBitmap& Pcsx2App::GetLogoBitmap()
#include "Resources/ConfigIcon_Speedhacks.h"
#include "Resources/ConfigIcon_Gamefixes.h"
#include "Resources/ConfigIcon_Paths.h"
#include "Resources/ConfigIcon_Plugins.h"
// ------------------------------------------------------------------------
wxImageList& Pcsx2App::GetImgList_Config()
@ -260,6 +294,7 @@ wxImageList& Pcsx2App::GetImgList_Config()
}
FancyLoadMacro( Paths );
FancyLoadMacro( Plugins );
FancyLoadMacro( Gamefixes );
FancyLoadMacro( Speedhacks );
FancyLoadMacro( Video );

View File

@ -27,23 +27,96 @@
namespace wxHelpers
{
wxSizerFlags stdCenteredFlags( wxSizerFlags().Align( wxALIGN_CENTER ).DoubleBorder() );
wxSizerFlags stdSpacingFlags( wxSizerFlags().Border( wxALL, 6 ) );
wxSizerFlags stdButtonSizerFlags( wxSizerFlags().Align( wxALIGN_RIGHT ).Border() );
wxSizerFlags CheckboxFlags( wxSizerFlags().Border( wxALL, 6 ).Expand() );
// ------------------------------------------------------------------------
// FlagsAccessors - Provides read-write copies of standard sizer flags for our interface.
// These standard definitions provide a consistent and pretty interface for our GUI.
// Without them things look compacted, misaligned, and yucky!
//
// Implementation Note: Accessors are all provisioned as dynamic (realtime) sizer calculations.
// I've preferred this over cstatic const variables on the premise that spacing logic could
// in the future become a dynamic value (currently it is affixed to 6 for most items).
//
namespace SizerFlags
{
wxSizerFlags StdSpace()
{
return wxSizerFlags().Border( wxALL, 6 );
}
wxSizerFlags StdCenter()
{
return wxSizerFlags().Align( wxALIGN_CENTER ).DoubleBorder();
}
wxSizerFlags StdExpand()
{
return StdSpace().Expand();
}
wxSizerFlags StdGroupie()
{
// Groups look better with a slightly smaller margin than standard.
// (basically this accounts for the group's frame)
return wxSizerFlags().Border( wxLEFT | wxBOTTOM | wxRIGHT, 4 ).Expand();
}
// This force-aligns the std button sizer to the right, where (at least) us win32 platform
// users always expect it to be. Most likely Mac platforms expect it on the left side
// just because it's *not* where win32 sticks it. Too bad!
wxSizerFlags StdButton()
{
return wxSizerFlags().Align( wxALIGN_RIGHT ).Border();
}
wxSizerFlags Checkbox()
{
return StdExpand();
}
};
// ------------------------------------------------------------------------
// Creates a new checkbox and adds it to the specified sizer/parent combo.
// Uses the default spacer setting for adding checkboxes.
//
wxCheckBox& AddCheckBoxTo( wxWindow* parent, wxBoxSizer& sizer, const wxString& label, wxWindowID id )
{
wxCheckBox* retval = new wxCheckBox( parent, id, label );
sizer.Add( retval, CheckboxFlags );
sizer.Add( retval, SizerFlags::Checkbox() );
return *retval;
}
wxStaticText& AddStaticTextTo(wxWindow* parent, wxBoxSizer& sizer, const wxString& label, int size )
// ------------------------------------------------------------------------
// Creates a new Radio Button and adds it to the specified sizer/parent combo.
// The first item in a group should pass True for the isFisrt parameter.
// Uses the default spacer setting for checkboxes.
//
wxRadioButton& AddRadioButtonTo( wxWindow* parent, wxBoxSizer& sizer, const wxString& label, wxWindowID id, bool isFirst )
{
wxStaticText *temp = new wxStaticText(parent, wxID_ANY, label);
wxRadioButton* retval = new wxRadioButton( parent, id, label, wxDefaultPosition, wxDefaultSize, isFirst ? wxRB_GROUP : 0 );
sizer.Add( retval, SizerFlags::Checkbox() );
return *retval;
}
// ------------------------------------------------------------------------
// Creates a static text box that generally "makes sense" in a free-flowing layout. Specifically, this
// ensures that that auto resizing is disabled, and that the sizer flags match the alignment specified
// for the textbox.
//
// Parameters:
// Size - allows forcing the control to wrap text at a specific pre-defined pixel width;
// or specify zero to let wxWidgets layout the text as it deems appropriate (recommended)
//
// alignFlags - Either wxALIGN_LEFT, RIGHT, or CENTRE. All other wxStaticText flags are ignored
// or overridden. [default is left alignment]
//
wxStaticText& AddStaticTextTo(wxWindow* parent, wxBoxSizer& sizer, const wxString& label, int size, int alignFlags )
{
// No reason to ever have AutoResize enabled, quite frankly. It just causes layout and centering problems.
alignFlags |= wxST_NO_AUTORESIZE;
wxStaticText *temp = new wxStaticText(parent, wxID_ANY, label, wxDefaultPosition, wxDefaultSize, alignFlags );
if (size > 0) temp->Wrap(size);
sizer.Add(temp);
sizer.Add(temp, SizerFlags::StdSpace().Align( alignFlags & wxALIGN_MASK ) );
return *temp;
}
@ -107,7 +180,7 @@ wxStaticText& wxDialogWithHelpers::AddStaticText(wxBoxSizer& sizer, const wxStri
return wxHelpers::AddStaticTextTo( this, sizer, label, size );
}
void wxDialogWithHelpers::AddOkCancel( wxBoxSizer &sizer )
void wxDialogWithHelpers::AddOkCancel( wxBoxSizer &sizer, bool hasApply )
{
wxBoxSizer* buttonSizer = &sizer;
if( m_hasContextHelp )
@ -124,13 +197,26 @@ void wxDialogWithHelpers::AddOkCancel( wxBoxSizer &sizer )
sizer.Add( buttonSizer, wxSizerFlags().Center() );
#endif
}
buttonSizer->Add( CreateStdDialogButtonSizer( wxOK | wxCANCEL ), wxHelpers::stdButtonSizerFlags );
wxStdDialogButtonSizer& s_buttons = *new wxStdDialogButtonSizer();
s_buttons.AddButton( new wxButton( this, wxID_OK ) );
s_buttons.AddButton( new wxButton( this, wxID_CANCEL ) );
if( hasApply )
{
s_buttons.AddButton( new wxButton( this, wxID_APPLY ) );
}
s_buttons.Realize();
buttonSizer->Add( &s_buttons, wxHelpers::SizerFlags::StdButton() );
}
//////////////////////////////////////////////////////////////////////////////////////////
//
wxPanelWithHelpers::wxPanelWithHelpers( wxWindow* parent, int id, const wxPoint& pos, const wxSize& size ) :
wxPanel( parent, id, pos, size )
, m_StartNewRadioGroup( true )
{
}
@ -139,7 +225,21 @@ wxCheckBox& wxPanelWithHelpers::AddCheckBox( wxBoxSizer& sizer, const wxString&
return wxHelpers::AddCheckBoxTo( this, sizer, label, id );
}
wxStaticText& wxPanelWithHelpers::AddStaticText(wxBoxSizer& sizer, const wxString& label, int size )
wxStaticText& wxPanelWithHelpers::AddStaticText(wxBoxSizer& sizer, const wxString& label, int size, int alignFlags )
{
return wxHelpers::AddStaticTextTo( this, sizer, label, size );
return wxHelpers::AddStaticTextTo( this, sizer, label, size, alignFlags );
}
wxRadioButton& wxPanelWithHelpers::AddRadioButton( wxBoxSizer& sizer, const wxString& label, const wxString& subtext, wxWindowID id )
{
wxRadioButton& retval = wxHelpers::AddRadioButtonTo( this, sizer, label, id, m_StartNewRadioGroup );
m_StartNewRadioGroup = false;
if( !subtext.IsEmpty() )
{
sizer.Add( new wxStaticText( this, wxID_ANY, subtext ), wxSizerFlags().Border( wxLEFT, 25 ) );
sizer.AddSpacer( 4 );
}
return retval;
}

View File

@ -1,23 +1,24 @@
#pragma once
#include <wx/wx.h>
#include <wx/filepicker.h>
namespace wxHelpers
{
// Creates a new checkbox and adds it to the specified sizer/parent combo.
// Uses the default spacer setting for adding checkboxes.
extern wxCheckBox& AddCheckBoxTo( wxWindow* parent, wxBoxSizer& sizer, const wxString& label, wxWindowID id=wxID_ANY );
extern wxStaticText& AddWrappedStaticTextTo(wxWindow* parent, wxBoxSizer& sizer, const wxString& label, int size );
extern wxRadioButton& AddRadioButtonTo( wxWindow* parent, wxBoxSizer& sizer, const wxString& label, wxWindowID id=wxID_ANY, bool isFirst = false );
extern wxStaticText& AddStaticTextTo(wxWindow* parent, wxBoxSizer& sizer, const wxString& label, int size=0, int alignFlags=wxALIGN_LEFT );
extern wxSizerFlags stdCenteredFlags;
extern wxSizerFlags stdSpacingFlags;
// This force-aligns the std button sizer to the right, where (at least) us win32 platform
// users always expect it to be. Most likely Mac platforms expect it on the left side
// just because it's *not* where win32 sticks it. Too bad!
extern wxSizerFlags stdButtonSizerFlags;
extern wxSizerFlags CheckboxFlags;
namespace SizerFlags
{
extern wxSizerFlags StdSpace();
extern wxSizerFlags StdCenter();
extern wxSizerFlags StdExpand();
extern wxSizerFlags StdGroupie();
extern wxSizerFlags StdButton();
extern wxSizerFlags Checkbox();
};
}
//////////////////////////////////////////////////////////////////////////////////////////
@ -33,17 +34,26 @@ public:
protected:
wxCheckBox& AddCheckBox( wxBoxSizer& sizer, const wxString& label, wxWindowID id=wxID_ANY );
wxStaticText& AddStaticText(wxBoxSizer& sizer, const wxString& label, int size=0 );
void AddOkCancel( wxBoxSizer& sizer );
void AddOkCancel( wxBoxSizer& sizer, bool hasApply=false );
};
//////////////////////////////////////////////////////////////////////////////////////////
//
class wxPanelWithHelpers : public wxPanel
{
protected:
bool m_StartNewRadioGroup;
public:
wxPanelWithHelpers( wxWindow* parent, int id, const wxPoint& pos=wxDefaultPosition, const wxSize& size=wxDefaultSize );
protected:
wxCheckBox& AddCheckBox( wxBoxSizer& sizer, const wxString& label, wxWindowID id=wxID_ANY );
wxStaticText& AddStaticText(wxBoxSizer& sizer, const wxString& label, int size=0 );
wxRadioButton& AddRadioButton( wxBoxSizer& sizer, const wxString& label, const wxString& subtext=wxEmptyString, wxWindowID id=wxID_ANY );
wxStaticText& AddStaticText(wxBoxSizer& sizer, const wxString& label, int size=0, int alignFlags=wxALIGN_LEFT );
void StartRadioGroup()
{
m_StartNewRadioGroup = true;
}
};

View File

@ -1,566 +0,0 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 Pcsx2 Team
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "Win32.h"
#include <shlobj.h>
#include "common.h"
#include "plugins.h"
struct ComboInitializer
{
HWND hwnd;
HANDLE Find;
HANDLE Lib;
WIN32_FIND_DATA FindData;
_PS2EgetLibType PS2E_GetLibType;
_PS2EgetLibName PS2E_GetLibName;
_PS2EgetLibVersion2 PS2E_GetLibVersion2;
long version;
u32 type;
ComboInitializer( HWND hwndDlg ) :
hwnd( hwndDlg )
, Find( INVALID_HANDLE_VALUE )
, Lib( NULL )
, PS2E_GetLibType( NULL )
, PS2E_GetLibName( NULL )
, PS2E_GetLibVersion2( NULL )
{
Find = FindFirstFile( Path::Combine( Config.PluginsDir, "*.dll" ).c_str(), &FindData);
}
~ComboInitializer()
{
if (Find!=INVALID_HANDLE_VALUE)
FindClose(Find);
}
bool FindNext()
{
return !!FindNextFile( Find, &FindData );
}
bool LoadNextLibrary()
{
string tmpStr( Path::Combine( Config.PluginsDir, FindData.cFileName ) );
Lib = HostSys::LoadLibrary( tmpStr.c_str() );
if (Lib == NULL)
{
Console::Error( "Plugin load failure: %hs\n\tSysLibError Message: %s", params &tmpStr, SysLibError() );
return false;
}
PS2E_GetLibType = (_PS2EgetLibType) GetProcAddress((HMODULE)Lib,"PS2EgetLibType");
PS2E_GetLibName = (_PS2EgetLibName) GetProcAddress((HMODULE)Lib,"PS2EgetLibName");
PS2E_GetLibVersion2 = (_PS2EgetLibVersion2) GetProcAddress((HMODULE)Lib,"PS2EgetLibVersion2");
if( PS2E_GetLibType == NULL || PS2E_GetLibName == NULL || PS2E_GetLibVersion2 == NULL )
return false;
type = PS2E_GetLibType();
return true;
}
void AddPlugin(HWND hwndCombo, const char* str)
{
string tmpStr;
int i;
ssprintf(tmpStr, "%s %d.%d.%d", PS2E_GetLibName(), (version>>8)&0xff, version&0xff, (version>>24)&0xff);
char* lp = (char *)malloc(strlen(FindData.cFileName)+8);
sprintf(lp, "%s", FindData.cFileName);
i = ComboBox_AddString(hwndCombo, tmpStr.c_str());
ComboBox_SetItemData(hwndCombo, i, lp);
if (_stricmp(str, lp)==0)
ComboBox_SetCurSel(hwndCombo, i);
}
bool CheckVersion( const char* typeStr, u32 pluginType, long checkver )
{
if( type & pluginType )
{
version = PS2E_GetLibVersion2( pluginType );
if ( ((version >> 16)&0xff) == checkver )
return true;
Console::Notice("%s Plugin %s: Version %x != %x", params typeStr, FindData.cFileName, 0xff&(version >> 16), checkver);
}
return false;
}
};
BOOL OnConfigureDialog(HWND hW) {
HWND const hWC_GS=GetDlgItem(hW,IDC_LISTGS);
HWND const hWC_PAD1=GetDlgItem(hW,IDC_LISTPAD1);
HWND const hWC_PAD2=GetDlgItem(hW,IDC_LISTPAD2);
HWND const hWC_SPU2=GetDlgItem(hW,IDC_LISTSPU2);
HWND const hWC_CDVD=GetDlgItem(hW,IDC_LISTCDVD);
HWND const hWC_DEV9=GetDlgItem(hW,IDC_LISTDEV9);
HWND const hWC_USB=GetDlgItem(hW,IDC_LISTUSB);
HWND const hWC_FW=GetDlgItem(hW,IDC_LISTFW);
HWND const hWC_BIOS=GetDlgItem(hW,IDC_LISTBIOS);
ComboInitializer tool(hW);
if( tool.Find == INVALID_HANDLE_VALUE ) // epic fail?
return FALSE;
do
{
if( !tool.LoadNextLibrary() ) continue;
if( tool.CheckVersion( "GS", PS2E_LT_GS, PS2E_GS_VERSION ) )
tool.AddPlugin(hWC_GS, winConfig.GS);
if (tool.type & PS2E_LT_PAD)
{
_PADquery query;
query = (_PADquery)GetProcAddress((HMODULE)tool.Lib, "PADquery");
if( query != NULL )
{
if( tool.CheckVersion( "PAD", PS2E_LT_PAD, PS2E_PAD_VERSION ) )
{
if (query() & 0x1)
tool.AddPlugin(hWC_PAD1, winConfig.PAD1);
if (query() & 0x2)
tool.AddPlugin(hWC_PAD2, winConfig.PAD2);
}
}
}
if( tool.CheckVersion( "SPU2", PS2E_LT_SPU2, PS2E_SPU2_VERSION ) )
tool.AddPlugin(hWC_SPU2, winConfig.SPU2);
if( tool.CheckVersion( "CDVD", PS2E_LT_CDVD, PS2E_CDVD_VERSION ) )
tool.AddPlugin(hWC_CDVD, winConfig.CDVD);
if( tool.CheckVersion( "DEV9", PS2E_LT_DEV9, PS2E_DEV9_VERSION ) )
tool.AddPlugin(hWC_DEV9, winConfig.DEV9);
if( tool.CheckVersion( "USB", PS2E_LT_USB, PS2E_USB_VERSION ) )
tool.AddPlugin(hWC_USB, winConfig.USB);
if( tool.CheckVersion( "FW", PS2E_LT_FW, PS2E_FW_VERSION ) )
tool.AddPlugin(hWC_FW, winConfig.FW);
} while( tool.FindNext() );
// BIOS
/*lp=(char *)malloc(strlen("HLE") + 1);
sprintf(lp, "HLE");
i=ComboBox_AddString(hWC_BIOS, "Internal HLE Bios");
ComboBox_SetItemData(hWC_BIOS, i, lp);
if (_stricmp(Config.Bios, lp)==0)
ComboBox_SetCurSel(hWC_BIOS, i);*/
HANDLE Find;
WIN32_FIND_DATA FindData;
Find = FindFirstFile( Path::Combine( Config.BiosDir, "*" ).c_str(), &FindData);
do
{
char* lp;
int i;
char description[50]; //2002-09-22 (Florin)
if (Find==INVALID_HANDLE_VALUE) break;
if (!strcmp(FindData.cFileName, ".")) continue;
if (!strcmp(FindData.cFileName, "..")) continue;
if (FindData.nFileSizeLow > 1024 * 4096) continue; //2002-09-22 (Florin)
if (!IsBIOS(FindData.cFileName, description)) continue;//2002-09-22 (Florin)
lp = (char *)malloc(strlen(FindData.cFileName)+8);
sprintf(lp, "%s", (char *)FindData.cFileName);
i = ComboBox_AddString(hWC_BIOS, description); //2002-09-22 (Florin) modified
ComboBox_SetItemData(hWC_BIOS, i, lp);
if (_stricmp(Config.Bios, FindData.cFileName)==0)
ComboBox_SetCurSel(hWC_BIOS, i);
} while (FindNextFile(Find,&FindData));
if (Find!=INVALID_HANDLE_VALUE) FindClose(Find);
if (ComboBox_GetCurSel(hWC_GS) == -1)
ComboBox_SetCurSel(hWC_GS, 0);
if (ComboBox_GetCurSel(hWC_PAD1) == -1)
ComboBox_SetCurSel(hWC_PAD1, 0);
if (ComboBox_GetCurSel(hWC_PAD2) == -1)
ComboBox_SetCurSel(hWC_PAD2, 0);
if (ComboBox_GetCurSel(hWC_SPU2) == -1)
ComboBox_SetCurSel(hWC_SPU2, 0);
if (ComboBox_GetCurSel(hWC_CDVD) == -1)
ComboBox_SetCurSel(hWC_CDVD, 0);
if (ComboBox_GetCurSel(hWC_DEV9) == -1)
ComboBox_SetCurSel(hWC_DEV9, 0);
if (ComboBox_GetCurSel(hWC_USB) == -1)
ComboBox_SetCurSel(hWC_USB, 0);
if (ComboBox_GetCurSel(hWC_FW) == -1)
ComboBox_SetCurSel(hWC_FW, 0);
if (ComboBox_GetCurSel(hWC_BIOS) == -1)
ComboBox_SetCurSel(hWC_BIOS, 0);
return TRUE;
}
#define CleanCombo(item) \
hWC = GetDlgItem(hW, item); \
iCnt = ComboBox_GetCount(hWC); \
for (i=0; i<iCnt; i++) { \
lp = (char *)ComboBox_GetItemData(hWC, i); \
if (lp) free(lp); \
} \
ComboBox_ResetContent(hWC);
void CleanUpCombos(HWND hW) {
int i,iCnt;HWND hWC;char * lp;
CleanCombo(IDC_LISTGS);
CleanCombo(IDC_LISTPAD1);
CleanCombo(IDC_LISTPAD2);
CleanCombo(IDC_LISTSPU2);
CleanCombo(IDC_LISTCDVD);
CleanCombo(IDC_LISTDEV9);
CleanCombo(IDC_LISTUSB);
CleanCombo(IDC_LISTFW);
CleanCombo(IDC_LISTBIOS);
}
void OnCancel(HWND hW) {
CleanUpCombos(hW);
EndDialog(hW,FALSE);
}
char *GetComboSel(HWND hW, int id) {
HWND hWC = GetDlgItem(hW,id);
int iSel;
iSel = ComboBox_GetCurSel(hWC);
if (iSel<0) return NULL;
return (char *)ComboBox_GetItemData(hWC, iSel);
}
#define CheckComboSel(cfg, idc) { \
char *str = GetComboSel(hW, idc); \
\
if (str != NULL) strcpy(cfg, str); \
}
void OnOK(HWND hW) {
CheckComboSel(winConfig.Bios, IDC_LISTBIOS);
CheckComboSel(winConfig.GS, IDC_LISTGS);
CheckComboSel(winConfig.PAD1, IDC_LISTPAD1);
CheckComboSel(winConfig.PAD2, IDC_LISTPAD2);
CheckComboSel(winConfig.SPU2, IDC_LISTSPU2);
CheckComboSel(winConfig.CDVD, IDC_LISTCDVD);
CheckComboSel(winConfig.DEV9, IDC_LISTDEV9);
CheckComboSel(winConfig.USB, IDC_LISTUSB);
CheckComboSel(winConfig.FW, IDC_LISTFW);
CleanUpCombos(hW);
EndDialog(hW, TRUE);
// Apply winConfig settings:
#define ApplyPluginPath( name ) strcpy( Config.name, winConfig.name )
ApplyPluginPath( Bios );
ApplyPluginPath( GS );
ApplyPluginPath( PAD1 );
ApplyPluginPath( PAD2 );
ApplyPluginPath( SPU2 );
ApplyPluginPath( CDVD );
ApplyPluginPath( DEV9 );
ApplyPluginPath( USB );
ApplyPluginPath( FW );
SaveConfig();
SysRestorableReset();
ReleasePlugins();
}
static void ConfPlugin( HWND hW, int confs, const char* name )
{
void *drv;
void (*conf)();
char * pDLL = GetComboSel(hW, confs);
if(pDLL==NULL) return;
drv = SysLoadLibrary( Path::Combine( Config.PluginsDir, pDLL ).c_str() );
if (drv == NULL) return;
conf = (void (*)()) SysLoadSym(drv, name);
if (SysLibError() == NULL) conf();
SysCloseLibrary(drv);
}
void ConfigureGS(HWND hW) {
ConfPlugin(hW, IDC_LISTGS, "GSconfigure");
}
void ConfigurePAD1(HWND hW) {
ConfPlugin(hW, IDC_LISTPAD1, "PADconfigure");
}
void ConfigurePAD2(HWND hW) {
ConfPlugin(hW, IDC_LISTPAD2, "PADconfigure");
}
void ConfigureSPU2(HWND hW) {
ConfPlugin(hW, IDC_LISTSPU2, "SPU2configure");
}
void ConfigureCDVD(HWND hW) {
ConfPlugin(hW, IDC_LISTCDVD, "CDVDconfigure");
}
void ConfigureDEV9(HWND hW) {
ConfPlugin(hW, IDC_LISTDEV9, "DEV9configure");
}
void ConfigureUSB(HWND hW) {
ConfPlugin(hW, IDC_LISTUSB, "USBconfigure");
}
void ConfigureFW(HWND hW) {
ConfPlugin(hW, IDC_LISTFW, "FWconfigure");
}
void AboutGS(HWND hW) {
ConfPlugin(hW, IDC_LISTGS, "GSabout");
}
void AboutPAD1(HWND hW) {
ConfPlugin(hW, IDC_LISTPAD1, "PADabout");
}
void AboutPAD2(HWND hW) {
ConfPlugin(hW, IDC_LISTPAD2, "PADabout");
}
void AboutSPU2(HWND hW) {
ConfPlugin(hW, IDC_LISTSPU2, "SPU2about");
}
void AboutCDVD(HWND hW) {
ConfPlugin(hW, IDC_LISTCDVD, "CDVDabout");
}
void AboutDEV9(HWND hW) {
ConfPlugin(hW, IDC_LISTDEV9, "DEV9about");
}
void AboutUSB(HWND hW) {
ConfPlugin(hW, IDC_LISTUSB, "USBabout");
}
void AboutFW(HWND hW) {
ConfPlugin(hW, IDC_LISTFW, "FWabout");
}
static void TestPlugin( HWND hW, int confs, const char* name )
{
void *drv;
int (*conf)();
int ret = 0;
char * pDLL = GetComboSel(hW, confs);
if (pDLL== NULL) return;
drv = SysLoadLibrary( Path::Combine( Config.PluginsDir, pDLL ).c_str() );
if (drv == NULL) return;
conf = (int (*)()) SysLoadSym(drv, name);
if (SysLibError() == NULL) ret = conf();
SysCloseLibrary(drv);
if (ret == 0)
Msgbox::Alert("Success!\nThis plugin reports that should work correctly.");
else
Msgbox::Alert("Test Failed.\nThis plugin may not work correctly.");
}
void TestGS(HWND hW) {
TestPlugin(hW, IDC_LISTGS, "GStest");
}
void TestPAD1(HWND hW) {
TestPlugin(hW, IDC_LISTPAD1, "PADtest");
}
void TestPAD2(HWND hW) {
TestPlugin(hW, IDC_LISTPAD2, "PADtest");
}
void TestSPU2(HWND hW) {
TestPlugin(hW, IDC_LISTSPU2, "SPU2test");
}
void TestCDVD(HWND hW) {
TestPlugin(hW, IDC_LISTCDVD, "CDVDtest");
}
void TestDEV9(HWND hW) {
TestPlugin(hW, IDC_LISTDEV9, "DEV9test");
}
void TestUSB(HWND hW) {
TestPlugin(hW, IDC_LISTUSB, "USBtest");
}
void TestFW(HWND hW) {
TestPlugin(hW, IDC_LISTFW, "FWtest");
}
int SelectPath(HWND hW, char *Title, char *Path) {
LPITEMIDLIST pidl;
BROWSEINFO bi;
char Buffer[g_MaxPath];
bi.hwndOwner = hW;
bi.pidlRoot = NULL;
bi.pszDisplayName = Buffer;
bi.lpszTitle = Title;
bi.ulFlags = BIF_RETURNFSANCESTORS | BIF_RETURNONLYFSDIRS;
bi.lpfn = NULL;
bi.lParam = 0;
if ((pidl = SHBrowseForFolder(&bi)) != NULL) {
if (SHGetPathFromIDList(pidl, Path)) {
int len = strlen(Path);
if (Path[len - 1] != '\\') { strcat(Path,"\\"); }
return 0;
}
}
return -1;
}
void SetPluginsDir(HWND hW) {
char Path[g_MaxPath];
if (SelectPath(hW, "Select Plugins Directory", Path) == -1) return;
strcpy(Config.PluginsDir, Path);
CleanUpCombos(hW);
OnConfigureDialog(hW);
}
void SetBiosDir(HWND hW) {
char Path[g_MaxPath];
if (SelectPath(hW, "Select Bios Directory", Path) == -1) return;
strcpy(Config.BiosDir, Path);
CleanUpCombos(hW);
OnConfigureDialog(hW);
}
BOOL CALLBACK ConfigureDlgProc(HWND hW, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch(uMsg) {
case WM_INITDIALOG:
SetWindowText(hW, "Configuration");
Button_SetText(GetDlgItem(hW, IDOK), "OK");
Button_SetText(GetDlgItem(hW, IDCANCEL), "Cancel");
Static_SetText(GetDlgItem(hW, IDC_GRAPHICS), "Graphics");
Static_SetText(GetDlgItem(hW, IDC_FIRSTCONTROLLER), "First Controller");
Static_SetText(GetDlgItem(hW, IDC_SECONDCONTROLLER), "Second Controller");
Static_SetText(GetDlgItem(hW, IDC_SOUND), "Sound");
Static_SetText(GetDlgItem(hW, IDC_CDVDROM), "Cdvdrom");
Static_SetText(GetDlgItem(hW, IDC_BIOS), "Bios");
Static_SetText(GetDlgItem(hW, IDC_USB), "Usb");
Static_SetText(GetDlgItem(hW, IDC_FW), "FireWire");
Static_SetText(GetDlgItem(hW, IDC_DEV9), "Dev9");
Button_SetText(GetDlgItem(hW, IDC_BIOSDIR), "Set Bios Directory");
Button_SetText(GetDlgItem(hW, IDC_PLUGINSDIR), "Set Plugins Directory");
Button_SetText(GetDlgItem(hW, IDC_CONFIGGS), "Configure...");
Button_SetText(GetDlgItem(hW, IDC_TESTGS), "Test...");
Button_SetText(GetDlgItem(hW, IDC_ABOUTGS), "About...");
Button_SetText(GetDlgItem(hW, IDC_CONFIGSPU2), "Configure...");
Button_SetText(GetDlgItem(hW, IDC_TESTSPU2), "Test...");
Button_SetText(GetDlgItem(hW, IDC_ABOUTSPU2), "About...");
Button_SetText(GetDlgItem(hW, IDC_CONFIGCDVD), "Configure...");
Button_SetText(GetDlgItem(hW, IDC_TESTCDVD), "Test...");
Button_SetText(GetDlgItem(hW, IDC_ABOUTCDVD), "About...");
Button_SetText(GetDlgItem(hW, IDC_CONFIGPAD1), "Configure...");
Button_SetText(GetDlgItem(hW, IDC_TESTPAD1), "Test...");
Button_SetText(GetDlgItem(hW, IDC_ABOUTPAD1), "About...");
Button_SetText(GetDlgItem(hW, IDC_CONFIGPAD2), "Configure...");
Button_SetText(GetDlgItem(hW, IDC_TESTPAD2), "Test...");
Button_SetText(GetDlgItem(hW, IDC_ABOUTPAD2), "About...");
Button_SetText(GetDlgItem(hW, IDC_CONFIGDEV9), "Configure...");
Button_SetText(GetDlgItem(hW, IDC_TESTDEV9), "Test...");
Button_SetText(GetDlgItem(hW, IDC_ABOUTDEV9), "About...");
Button_SetText(GetDlgItem(hW, IDC_CONFIGUSB), "Configure...");
Button_SetText(GetDlgItem(hW, IDC_TESTUSB), "Test...");
Button_SetText(GetDlgItem(hW, IDC_ABOUTUSB), "About...");
Button_SetText(GetDlgItem(hW, IDC_CONFIGFW), "Configure...");
Button_SetText(GetDlgItem(hW, IDC_TESTFW), "Test...");
Button_SetText(GetDlgItem(hW, IDC_ABOUTFW), "About...");
return OnConfigureDialog(hW);
case WM_COMMAND:
switch(LOWORD(wParam)) {
case IDC_CONFIGGS: ConfigureGS(hW); return TRUE;
case IDC_CONFIGPAD1: ConfigurePAD1(hW); return TRUE;
case IDC_CONFIGPAD2: ConfigurePAD2(hW); return TRUE;
case IDC_CONFIGSPU2: ConfigureSPU2(hW); return TRUE;
case IDC_CONFIGCDVD: ConfigureCDVD(hW); return TRUE;
case IDC_CONFIGDEV9: ConfigureDEV9(hW); return TRUE;
case IDC_CONFIGUSB: ConfigureUSB(hW); return TRUE;
case IDC_CONFIGFW: ConfigureFW(hW); return TRUE;
case IDC_TESTGS: TestGS(hW); return TRUE;
case IDC_TESTPAD1: TestPAD1(hW); return TRUE;
case IDC_TESTPAD2: TestPAD2(hW); return TRUE;
case IDC_TESTSPU2: TestSPU2(hW); return TRUE;
case IDC_TESTCDVD: TestCDVD(hW); return TRUE;
case IDC_TESTDEV9: TestDEV9(hW); return TRUE;
case IDC_TESTUSB: TestUSB(hW); return TRUE;
case IDC_TESTFW: TestFW(hW); return TRUE;
case IDC_ABOUTGS: AboutGS(hW); return TRUE;
case IDC_ABOUTPAD1: AboutPAD1(hW); return TRUE;
case IDC_ABOUTPAD2: AboutPAD2(hW); return TRUE;
case IDC_ABOUTSPU2: AboutSPU2(hW); return TRUE;
case IDC_ABOUTCDVD: AboutCDVD(hW); return TRUE;
case IDC_ABOUTDEV9: AboutDEV9(hW); return TRUE;
case IDC_ABOUTUSB: AboutUSB(hW); return TRUE;
case IDC_ABOUTFW: AboutFW(hW); return TRUE;
case IDC_PLUGINSDIR: SetPluginsDir(hW); return TRUE;
case IDC_BIOSDIR: SetBiosDir(hW); return TRUE;
case IDCANCEL: OnCancel(hW); return TRUE;
case IDOK: OnOK(hW); return TRUE;
}
}
return FALSE;
}
BOOL Pcsx2Configure(HWND hWnd)
{
return DialogBox(
gApp.hInstance,
MAKEINTRESOURCE(IDD_CONFIG),
hWnd,
(DLGPROC)ConfigureDlgProc
);
}

View File

@ -1,268 +0,0 @@
/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 Pcsx2 Team
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "Win32.h"
#include <math.h>
#include "System.h"
#include "McdsDlg.h"
#include "Sio.h"
HWND mcdDlg;
#define SET_CHECK(idc,value) SendMessage(GetDlgItem(hWnd,idc),BM_SETCHECK,((value)==0)?BST_UNCHECKED:BST_CHECKED,0)
#define ENABLE_CONTROL(idc,value) EnableWindow(GetDlgItem(hWnd,idc),value)
#define HANDLE_CHECK(idc,hvar) case idc: (hvar) = !(hvar); SendMessage(GetDlgItem(hWnd,idc),BM_SETCHECK,(hvar)?BST_CHECKED:BST_UNCHECKED,0); break
#define HANDLE_CHECKNB(idc,hvar) case idc: (hvar) = !(hvar); SendMessage(GetDlgItem(hWnd,idc),BM_SETCHECK,(hvar)?BST_CHECKED:BST_UNCHECKED,0)
void DlgItem_GetText( HWND hwnd, int dlgId, wxString& dest )
{
HWND dlg = GetDlgItem( hwnd, dlgId );
int length = GetWindowTextLength( dlg );
if( length <= 0 )
{
dest.clear();
return;
}
char* outstr = new char[length+2];
if( outstr != NULL )
{
GetWindowText( dlg, outstr, length+1 );
dest = outstr;
safe_delete_array( outstr );
}
}
// strips path information so that absolute paths are reduced to relative paths
// where appropriate.
static const char* _stripPathInfo( const char* src )
{
const char* retval = src;
const char* workingfold = g_WorkingFolder;
while( (*retval != 0) && (*workingfold != 0) && (tolower(*retval) == tolower(*workingfold)) )
{
retval++;
workingfold++;
}
// If a difference is found before we reach the end of our pcsx2 working folder, it
// means we need to use the fully absolute path form the user.
if( *workingfold != 0 ) return src;
while( (*retval != 0) && (*retval == '\\') ) retval++;
return retval;
}
void MemcardConfig::Open_Mcd_Proc(HWND hW, int mcd)
{
OPENFILENAME ofn;
char szFileName[256];
char szFileTitle[256];
char szFilter[1024];
char *str;
memzero_obj( szFileName );
memzero_obj( szFileTitle );
memzero_obj( szFilter );
strcpy(szFilter, "Ps2 Memory Card (*.ps2)");
str = szFilter + strlen(szFilter) + 1;
strcpy(str, "*.ps2");
str += strlen(str) + 1;
strcpy(str, "All Files");
str += strlen(str) + 1;
strcpy(str, "*.*");
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hW;
ofn.lpstrFilter = szFilter;
ofn.lpstrCustomFilter = NULL;
ofn.nMaxCustFilter = 0;
ofn.nFilterIndex = 1;
ofn.lpstrFile = szFileName;
ofn.nMaxFile = 256;
ofn.lpstrInitialDir = MEMCARDS_DIR;
ofn.lpstrFileTitle = szFileTitle;
ofn.nMaxFileTitle = 256;
ofn.lpstrTitle = NULL;
ofn.lpstrDefExt = "PS2";
ofn.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR | OFN_EXPLORER;
if (GetOpenFileName ((LPOPENFILENAME)&ofn))
{
Edit_SetText(GetDlgItem(hW,mcd == 1 ? IDC_MCD_FILE1 : IDC_MCD_FILE2),
_stripPathInfo( Path::Combine( g_WorkingFolder, szFileName ).c_str() ) );
}
}
static wxString m_Default_MemcardsDir[2] =
{
Path::Combine( MEMCARDS_DIR, DEFAULT_MEMCARD1 ),
Path::Combine( MEMCARDS_DIR, DEFAULT_MEMCARD2 )
};
BOOL CALLBACK MemcardConfig::DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_INITDIALOG:
{
mcdDlg = hWnd;
SetWindowText(hWnd, "MemoryCard Config - Pcsx2");
Button_SetText(GetDlgItem(hWnd, IDOK), "OK");
Button_SetText(GetDlgItem(hWnd, IDCANCEL), "Cancel");
Button_SetText(GetDlgItem(hWnd, IDC_MCDSEL1), "Browse...");
Button_SetText(GetDlgItem(hWnd, IDC_MCDSEL2), "Browse...");
Static_SetText(GetDlgItem(hWnd, IDC_MCD_ENABLE1), "Memory Card Slot 1");
Static_SetText(GetDlgItem(hWnd, IDC_MCD_ENABLE2), "Memory Card Slot 2");
if( Config.Mcd[0].Filename[0] == 0 )
{
strcpy_s( Config.Mcd[0].Filename,
Path::Combine( g_WorkingFolder, m_Default_MemcardsDir[0] ).c_str() );
}
if( Config.Mcd[1].Filename[1] == 0 )
{
strcpy_s( Config.Mcd[1].Filename,
Path::Combine( g_WorkingFolder, m_Default_MemcardsDir[1] ).c_str() );
}
Edit_SetText( GetDlgItem(hWnd,IDC_MCD_FILE1), _stripPathInfo( Config.Mcd[0].Filename ) );
Edit_SetText( GetDlgItem(hWnd,IDC_MCD_FILE2), _stripPathInfo( Config.Mcd[1].Filename ) );
SET_CHECK( IDC_MCD_ENABLE1, Config.Mcd[0].Enabled );
SET_CHECK( IDC_MCD_ENABLE2, Config.Mcd[1].Enabled );
SET_CHECK( IDC_NTFS_ENABLE, Config.McdEnableNTFS );
SET_CHECK( IDC_MCD_EJECT_ENABLE, Config.McdEnableEject );
}
break;
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
int wmEvent = HIWORD(wParam);
switch (LOWORD(wmId))
{
case IDC_MCD_BROWSE1:
Open_Mcd_Proc(hWnd, 1);
return TRUE;
case IDC_MCD_BROWSE2:
Open_Mcd_Proc(hWnd, 2);
return TRUE;
case IDCANCEL:
EndDialog(hWnd,FALSE);
return TRUE;
case IDOK:
{
//DlgItem_GetText( hWnd, IDC_MCD_FILE1, Config.Mcd[0].Filename );
//DlgItem_GetText( hWnd, IDC_MCD_FILE2, Config.Mcd[1].Filename );
wxString oldone( Config.Mcd[0].Filename ), oldtwo( Config.Mcd[1].Filename );
GetWindowText( GetDlgItem( hWnd, IDC_MCD_FILE1 ), Config.Mcd[0].Filename, g_MaxPath );
GetWindowText( GetDlgItem( hWnd, IDC_MCD_FILE2 ), Config.Mcd[1].Filename, g_MaxPath );
// reassign text with the extra unnecessary path info stripped out.
_tcscpy( Config.Mcd[0].Filename, _stripPathInfo( Path::Combine( g_WorkingFolder, Config.Mcd[0].Filename ).c_str() ) );
_tcscpy( Config.Mcd[1].Filename, _stripPathInfo( Path::Combine( g_WorkingFolder, Config.Mcd[1].Filename ).c_str() ) );
if( g_EmulationInProgress )
{
if( !Config.Mcd[0].Enabled || oldone != Config.Mcd[0].Filename )
sioEjectCard( 0 );
if( !Config.Mcd[1].Enabled || oldtwo != Config.Mcd[1].Filename )
sioEjectCard( 1 );
}
IniFileSaver().MemcardSettings( Config );
EndDialog( hWnd, TRUE );
}
return TRUE;
HANDLE_CHECKNB( IDC_MCD_ENABLE1, Config.Mcd[0].Enabled );
ENABLE_CONTROL( IDC_MCD_BROWSE1, Config.Mcd[0].Enabled );
ENABLE_CONTROL( IDC_MCD_FILE1, Config.Mcd[0].Enabled );
ENABLE_CONTROL( IDC_MCD_LABEL1, Config.Mcd[0].Enabled );
break;
HANDLE_CHECKNB( IDC_MCD_ENABLE2, Config.Mcd[1].Enabled );
ENABLE_CONTROL( IDC_MCD_BROWSE2, Config.Mcd[1].Enabled );
ENABLE_CONTROL( IDC_MCD_FILE2, Config.Mcd[1].Enabled );
ENABLE_CONTROL( IDC_MCD_LABEL2, Config.Mcd[1].Enabled );
break;
HANDLE_CHECK( IDC_NTFS_ENABLE, Config.McdEnableNTFS );
HANDLE_CHECK( IDC_MCD_EJECT_ENABLE, Config.McdEnableEject );
default:
return FALSE;
}
}
break;
default:
return FALSE;
}
return TRUE;
}
// Both loads and saves as a single unified settings function! :D
void IniFile::MemcardSettings( PcsxConfig& conf )
{
SetCurrentSection( "Memorycards" );
Entry( "Slot1_Path", conf.Mcd[0].Filename,
Path::Combine( g_WorkingFolder, m_Default_MemcardsDir[0] ) );
Entry( "Slot2_Path", conf.Mcd[1].Filename,
Path::Combine( g_WorkingFolder, m_Default_MemcardsDir[1] ) );
Entry( "Slot1_Enabled", conf.Mcd[0].Enabled, true );
Entry( "Slot2_Enabled", conf.Mcd[1].Enabled, true );
Entry( "EnableNTFS", conf.McdEnableNTFS, true );
Entry( "EnableEjection", conf.McdEnableEject, true );
}
// Creates the MemoryCard configuration dialog box
void MemcardConfig::OpenDialog()
{
DialogBox( gApp.hInstance, MAKEINTRESOURCE(IDD_CONF_MEMCARD), gApp.hWnd, (DLGPROC)DialogProc );
// Re-loads old config if the user canceled.
IniFileLoader().MemcardSettings( Config );
}

View File

@ -1941,6 +1941,14 @@
RelativePath="..\..\HostGui.h"
>
</File>
<File
RelativePath="..\..\gui\i18n.cpp"
>
</File>
<File
RelativePath="..\..\gui\i18n.h"
>
</File>
<File
RelativePath="..\..\gui\IniInterface.cpp"
>
@ -1976,10 +1984,6 @@
RelativePath="..\..\gui\AboutBoxDialog.cpp"
>
</File>
<File
RelativePath="..\..\gui\AboutBoxDialog.h"
>
</File>
<File
RelativePath="..\..\gui\AdvancedDialog.cpp"
>
@ -2004,6 +2008,14 @@
RelativePath="..\..\gui\LogOptionsDialog.h"
>
</File>
<File
RelativePath="..\..\gui\Dialogs\ModalPopups.h"
>
</File>
<File
RelativePath="..\..\gui\Dialogs\PickUserModeDialog.cpp"
>
</File>
</Filter>
<Filter
Name="Resources"
@ -2185,6 +2197,38 @@
>
</File>
</Filter>
<Filter
Name="Linux"
>
<File
RelativePath="..\..\Linux\LnxHostSys.cpp"
>
<FileConfiguration
Name="Debug|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Devel|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
</File>
</Filter>
</Filter>
<File
RelativePath="..\..\Common.h"
@ -2194,10 +2238,6 @@
RelativePath="..\..\Config.h"
>
</File>
<File
RelativePath=".\icon1.ico"
>
</File>
<File
RelativePath="..\..\IopCommon.h"
>

View File

@ -7,14 +7,14 @@
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="./;../../;../../x86;&quot;../../x86/ix86-32&quot;;../libs;../../IPU"
PreprocessorDefinitions="__i386__;ENABLE_NLS;PACKAGE=\&quot;pcsx2\&quot;;TIXML_USE_STL"
PreprocessorDefinitions="__i386__;TIXML_USE_STL;_SCL_SECURE_NO_WARNINGS"
RuntimeTypeInfo="false"
PrecompiledHeaderFile="$(IntDir)/pcsx2.pch"
CompileAs="0"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib ws2_32.lib winmm.lib"
AdditionalDependencies="odbc32.lib odbccp32.lib comctl32.lib ws2_32.lib shlwapi.lib winmm.lib"
LinkIncremental="1"
AdditionalLibraryDirectories="..\;..\libs"
GenerateDebugInformation="true"

View File

@ -27,7 +27,6 @@
#include "System.h"
#include "HostGui.h"
#include "resource.h"
#include "WinDebugResource.h"
#define COMPILEDATE __DATE__

View File

@ -153,9 +153,9 @@ static void iIopDumpBlock( int startpc, u8 * ptr )
int numused, count;
Console::WriteLn( "dump1 %x:%x, %x", params startpc, psxpc, psxRegs.cycle );
Path::CreateDirectory( L"dumps" );
g_Conf.Folders.Logs.Mkdir();
wxString filename( Path::Combine( g_Conf.Folders.Dumps, wxsFormat( L"psxdump%.8X.txt", startpc ) ) );
wxString filename( Path::Combine( g_Conf.Folders.Logs, wxsFormat( L"psxdump%.8X.txt", startpc ) ) );
AsciiFile f( filename, wxFile::write );
/*for ( i = startpc; i < s_nEndBlock; i += 4 ) {
@ -697,6 +697,7 @@ static __forceinline u32 psxRecClearMem(u32 pc)
jASSUME(blockidx != -1);
// Variable assignment in the middle of the while statements condition?
while (pexblock = recBlocks[blockidx - 1]) {
if (pexblock->startpc + pexblock->size * 4 <= lowerextent)
break;
@ -705,6 +706,7 @@ static __forceinline u32 psxRecClearMem(u32 pc)
blockidx--;
}
// Same here.
while (pexblock = recBlocks[blockidx]) {
if (pexblock->startpc >= upperextent)
break;
@ -813,6 +815,7 @@ static void iPsxBranchTest(u32 newpc, u32 cpuBranch)
x86SetJ8( j8Ptr[0] );
}
#if 0
//static const int *s_pCode;
#if !defined(_MSC_VER)
@ -828,6 +831,7 @@ static void checkcodefn()
Console::WriteLn("iop code changed! %x", params pctemp);
}
#endif
#endif
void rpsxSYSCALL()
{
@ -873,7 +877,7 @@ void psxRecompileNextInstruction(int delayslot)
static u8 s_bFlushReg = 1;
// pblock isn't used elsewhere in this function.
BASEBLOCK* pblock = PSX_GETBLOCK(psxpc);
//BASEBLOCK* pblock = PSX_GETBLOCK(psxpc);
if( IsDebugBuild )
MOV32ItoR(EAX, psxpc);

View File

@ -783,7 +783,6 @@ void recDIVU1_constt(int info)
EERECOMPILE_CODE0(DIVU1, XMMINFO_READS|XMMINFO_READT);
void recMADD()
{
EEINST_SETSIGNEXT(_Rs_);
@ -826,15 +825,15 @@ void recMADD()
if( GPR_IS_CONST1(_Rs_) ) {
MOV32ItoR( EAX, g_cpuConstRegs[_Rs_].UL[0] );
MUL32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
IMUL32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
}
else if ( GPR_IS_CONST1(_Rt_) ) {
MOV32ItoR( EAX, g_cpuConstRegs[_Rt_].UL[0] );
MUL32M( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] );
IMUL32M( (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] );
}
else {
MOV32MtoR( EAX, (int)&cpuRegs.GPR.r[ _Rs_ ].UL[ 0 ] );
MUL32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
IMUL32M( (int)&cpuRegs.GPR.r[ _Rt_ ].UL[ 0 ] );
}
MOV32RtoR( ECX, EDX );

View File

@ -40,15 +40,16 @@ microVUt(void) mVUinit(VURegs* vuRegsPtr, int vuIndex) {
microVU* mVU = mVUx;
memset(&mVU->prog, 0, sizeof(mVU->prog));
mVU->regs = vuRegsPtr;
mVU->index = vuIndex;
mVU->vuMemSize = (vuIndex ? 0x4000 : 0x1000);
mVU->microMemSize = (vuIndex ? 0x4000 : 0x1000);
mVU->progSize = (vuIndex ? 0x4000 : 0x1000) / 4;
mVU->cache = NULL;
mVU->cacheSize = mVUcacheSize;
mVU->prog.max = mMaxProg - 1;
mVU->prog.prog = (microProgram*)_aligned_malloc(sizeof(microProgram)*(mVU->prog.max+1), 64);
mVU->regs = vuRegsPtr;
mVU->index = vuIndex;
mVU->vuMemSize = (vuIndex ? 0x4000 : 0x1000);
mVU->microMemSize = (vuIndex ? 0x4000 : 0x1000);
mVU->progSize = (vuIndex ? 0x4000 : 0x1000) / 4;
mVU->cache = NULL;
mVU->cacheSize = mVUcacheSize;
mVU->prog.max = mMaxProg - 1;
mVU->prog.prog = (microProgram*)_aligned_malloc(sizeof(microProgram)*(mVU->prog.max+1), 64);
mVU->prog.progList = new int[mMaxProg];
mVUprint((vuIndex) ? "microVU1: init" : "microVU0: init");
mVU->cache = SysMmapEx((vuIndex ? 0x5f240000 : 0x5e240000), mVU->cacheSize + 0x1000, 0, (vuIndex ? "Micro VU1" : "Micro VU0"));
@ -69,18 +70,18 @@ microVUt(void) mVUinit(VURegs* vuRegsPtr, int vuIndex) {
microVUt(void) mVUreset(mV) {
mVUprint((mVU->index) ? "microVU1: reset" : "microVU0: reset");
mVUclose(mVU, 1);
// Clear All Program Data
//memset(&mVU->prog, 0, sizeof(mVU->prog));
memset(&mVU->prog.lpState, 0, sizeof(mVU->prog.lpState));
// Program Variables
mVU->prog.cleared = 1;
mVU->prog.isSame = -1;
mVU->prog.cur = -1;
mVU->prog.total = -1;
mVU->prog.max = mMaxProg - 1;
mVU->prog.cleared = 1;
mVU->prog.isSame = -1;
mVU->prog.cur = -1;
mVU->prog.total = -1;
mVU->prog.curFrame = 0;
mVU->prog.max = mMaxProg - 1;
// Setup Dynarec Cache Limits for Each Program
u8* z = (mVU->cache + 0x1000); // Dispatcher Code is in first page of cache
@ -89,20 +90,18 @@ microVUt(void) mVUreset(mV) {
mVU->prog.x86end = (u8*)((uptr)z + (uptr)(mVU->cacheSize - (mVU->cacheSize*.05)));
for (int i = 0; i <= mVU->prog.max; i++) {
for (int j = 0; j <= mVU->prog.prog[i].ranges.max; j++) {
mVU->prog.prog[i].ranges.range[j][0] = -1; // Set range to
mVU->prog.prog[i].ranges.range[j][1] = -1; // indeterminable status
mVU->prog.prog[i].ranges.total = -1;
}
if (!mVU->index) mVUclearProg<0>(i);
else mVUclearProg<1>(i);
mVU->prog.progList[i] = i;
}
}
// Free Allocated Resources
microVUt(void) mVUclose(mV, bool isReset) {
microVUt(void) mVUclose(mV) {
mVUprint((mVU->index) ? "microVU1: close" : "microVU0: close");
if (!isReset && mVU->cache) { HostSys::Munmap(mVU->cache, mVU->cacheSize); mVU->cache = NULL; }
if (mVU->cache) { HostSys::Munmap(mVU->cache, mVU->cacheSize); mVU->cache = NULL; }
// Delete Programs and Block Managers
if (mVU->prog.prog) {
@ -111,8 +110,9 @@ microVUt(void) mVUclose(mV, bool isReset) {
microBlockManager::Delete(mVU->prog.prog[i].block[j]);
}
}
if (!isReset) safe_aligned_free(mVU->prog.prog);
safe_aligned_free(mVU->prog.prog);
}
safe_delete_array(mVU->prog.progList);
}
// Clears Block Data in specified range
@ -127,18 +127,18 @@ microVUt(void) mVUclear(mV, u32 addr, u32 size) {
// Micro VU - Private Functions
//------------------------------------------------------------------
// Clears program data (Sets used to 1 because calling this function implies the program will be used at least once)
// Clears program data
microVUf(void) mVUclearProg(int progIndex) {
microVU* mVU = mVUx;
mVUprogI.used = 1;
mVUprogI.last_used = 3;
mVUprogI.used = 0;
mVUprogI.isDead = 1;
mVUprogI.frame = mVU->prog.curFrame;
for (int j = 0; j <= mVUprogI.ranges.max; j++) {
mVUprogI.ranges.range[j][0] = -1; // Set range to
mVUprogI.ranges.range[j][1] = -1; // indeterminable status
mVUprogI.ranges.total = -1;
}
for (u32 i = 0; i < (mVU->progSize / 2); i++) {
//if (mVUprogI.block[i]) { mVUprogI.block[i]->reset(); }
microBlockManager::Delete(mVUprogI.block[i]);
}
}
@ -150,85 +150,66 @@ microVUf(void) mVUcacheProg(int progIndex) {
mVUdumpProg(progIndex);
}
#define aWrap(x, nMax) ((x > nMax) ? 0 : x)
// Sorts the program list (Moves progIndex to Beginning of ProgList)
microVUt(void) mVUsortProg(mV, int progIndex) {
int* temp = new int[mVU->prog.max+1];
int offset = 0;
for (int i = 0; i <= (mVU->prog.max-1); i++) {
if (progIndex == mVU->prog.progList[i]) offset = 1;
temp[i+1] = mVU->prog.progList[i+offset];
}
temp[0] = progIndex;
delete[] mVU->prog.progList;
mVU->prog.progList = temp;
}
// Finds the least used program, (if program list full clears and returns an old program; if not-full, returns free program)
microVUf(int) mVUfindLeastUsedProg() {
microVU* mVU = mVUx;
if (mVU->prog.total < mVU->prog.max) {
mVU->prog.total++;
mVUcacheProg<vuIndex>(mVU->prog.total); // Cache Micro Program
mVU->prog.prog[mVU->prog.total].used = 1;
mVU->prog.prog[mVU->prog.total].last_used = 3;
Console::Notice("microVU%d: Cached MicroPrograms = %d", params vuIndex, mVU->prog.total+1);
return mVU->prog.total;
}
else {
/*
const int pMax = mVU->prog.max;
int smallidx = aWrap((mVU->prog.cur+1), pMax);
u64 smallval = mVU->prog.prog[smallidx].used;
for (int i = 1, j = aWrap((smallidx+1), pMax); i <= pMax; i++, aWrap((j+1), pMax)) {
if (smallval > mVU->prog.prog[j].used) {
smallval = mVU->prog.prog[j].used;
smallidx = j;
}
}
//smallidx = rand() % 200;
mVUclearProg<vuIndex>(smallidx); // Clear old data if overwriting old program
mVUcacheProg<vuIndex>(smallidx); // Cache Micro Program
//Console::Notice("microVU%d: Overwriting existing program in slot %d [%d times used]", params vuIndex, smallidx, smallval);
return smallidx;
*/
/*
static int smallidx = 0;
const int pMax = mVU->prog.max;
smallidx = aWrap((smallidx+1), pMax);
mVUclearProg<vuIndex>(smallidx); // Clear old data if overwriting old program
mVUcacheProg<vuIndex>(smallidx); // Cache Micro Program
//Console::Notice("microVU%d: Overwriting existing program in slot %d [%d times used]", params vuIndex, smallidx, smallval);
return smallidx;
*/
//mVUreset(mVU);
mVU->prog.x86ptr = mVU->prog.x86start;
for (int z = 0; z <= mVU->prog.max; z++) {
mVUclearProg<vuIndex>(z);
mVU->prog.prog[z].used = 0;
mVU->prog.prog[z].last_used = 0;
}
mVU->prog.total = 0;
mVUcacheProg<vuIndex>(mVU->prog.total); // Cache Micro Program
mVU->prog.prog[mVU->prog.total].used = 1;
mVU->prog.prog[mVU->prog.total].last_used = 3;
Console::Notice("microVU%d: Cached MicroPrograms = %d", params vuIndex, mVU->prog.total+1);
return mVU->prog.total;
}
}
// mVUvsyncUpdate -->
// This should be run at 30fps intervals from Counters.cpp (or 60fps works too, but 30fps is
// probably all we need for accurate results)
//
// To fix the program cache to more efficiently dispose of "obsolete" programs, we need to use a
// frame-based decrementing system in combination with a program-execution-based incrementing
// system. In English: if last_used >= 2 it means the program has been used for the current
// or prev frame. if it's 0, the program hasn't been used for a while.
microVUt(void) mVUvsyncUpdate(mV) {
if (mVU->prog.total < mVU->prog.max) return;
for (int i = 0; i <= mVU->prog.max; i++) {
if (mVU->prog.prog[i].last_used != 0) {
if (mVU->prog.prog[i].last_used >= 3) {
mVU->prog.prog[i].used += 0x200; // give 'weighted' bonus
}
mVU->prog.prog[i].last_used--;
if (mVU->prog.prog[i].isDead) {
mVU->prog.total++;
mVUcacheProg<vuIndex>(i); // Cache Micro Program
mVU->prog.prog[i].isDead = 0;
mVU->prog.prog[i].used = 1;
mVUsortProg(mVU, i);
Console::Notice("microVU%d: Cached MicroPrograms = [%03d] [%03d]", params vuIndex, i+1, mVU->prog.total+1);
return i;
}
else mVU->prog.prog[i].used /= 2; // penalize unused programs.
}
static int clearIdx = 0;
int pIdx = clearIdx;
for (int i = 0; i < ((mVU->prog.max+1)/4); i++) {
mVUclearProg<vuIndex>(clearIdx);
clearIdx = aWrap(clearIdx+1, mVU->prog.max);
}
mVU->prog.total -= ((mVU->prog.max+1)/4)-1;
mVUcacheProg<vuIndex>(pIdx); // Cache Micro Program
mVU->prog.prog[pIdx].isDead = 0;
mVU->prog.prog[pIdx].used = 1;
mVUsortProg(mVU, pIdx);
Console::Notice("microVU%d: Cached MicroPrograms = [%03d] [%03d]", params vuIndex, pIdx+1, mVU->prog.total+1);
return pIdx;
}
// Finds and Kills Programs if they haven't been used in a while.
microVUt(void) mVUvsyncUpdate(mV) {
for (int i = 0; i <= mVU->prog.max; i++) {
if (mVU->prog.prog[i].isDead) continue;
if (mVU->prog.prog[i].used) {
mVU->prog.prog[i].used = 0;
mVU->prog.prog[i].frame = mVU->prog.curFrame;
}
if((mVU->prog.curFrame - mVU->prog.prog[i].frame) >= (60 * 7)) {
mVU->prog.total--;
if (!mVU->index) mVUclearProg<0>(i);
else mVUclearProg<1>(i);
DevCon::Status("microVU%d: Killing Dead Program [%03d]", params mVU->index, i+1);
}
}
mVU->prog.curFrame++;
}
microVUf(bool) mVUcmpPartial(int progIndex) {
@ -244,16 +225,15 @@ microVUf(bool) mVUcmpPartial(int progIndex) {
}
// Compare Cached microProgram to mVU->regs->Micro
microVUf(bool) mVUcmpProg(int progIndex, bool progUsed, const bool cmpWholeProg) {
microVUf(bool) mVUcmpProg(int progIndex, const bool cmpWholeProg) {
microVU* mVU = mVUx;
if (progUsed) {
if (!mVUprogI.isDead) {
if ((cmpWholeProg && !memcmp_mmx((u8*)mVUprogI.data, mVU->regs->Micro, mVU->microMemSize))
|| (!cmpWholeProg && mVUcmpPartial<vuIndex>(progIndex))) {
mVU->prog.cur = progIndex;
mVU->prog.cleared = 0;
mVU->prog.isSame = cmpWholeProg ? 1 : -1;
mVU->prog.prog[progIndex].last_used = 3;
mVU->prog.prog[progIndex].used++; // increment 'used'
mVU->prog.prog[progIndex].used = 1;
return 1;
}
}
@ -263,23 +243,17 @@ microVUf(bool) mVUcmpProg(int progIndex, bool progUsed, const bool cmpWholeProg)
// Searches for Cached Micro Program and sets prog.cur to it (returns 1 if program found, else returns 0)
microVUf(int) mVUsearchProg() {
microVU* mVU = mVUx;
if (mVU->prog.cleared) { // If cleared, we need to search for new program
for (int i = 0; i <= mVU->prog.total; i++) {
if (mVUcmpProg<vuIndex>(i, !!mVU->prog.prog[i].used, 0))
return 1; // Check Recently Used Programs
}
for (int i = 0; i <= mVU->prog.total; i++) {
if (mVUcmpProg<vuIndex>(i, !mVU->prog.prog[i].used, 0))
return 1; // Check Older Programs
for (int i = mVU->prog.max; i >= 0; i--) {
if (mVUcmpProg<vuIndex>(mVU->prog.progList[i], 0))
return 1;
}
mVU->prog.cur = mVUfindLeastUsedProg<vuIndex>(); // If cleared and program not found, make a new program instance
mVU->prog.cleared = 0;
mVU->prog.isSame = 1;
return 0;
}
mVU->prog.prog[mVU->prog.cur].used++;
mVU->prog.prog[mVU->prog.cur].last_used = 3;
mVU->prog.prog[mVU->prog.cur].used = 1;
return 1; // If !cleared, then we're still on the same program as last-time ;)
}
@ -288,7 +262,7 @@ microVUf(int) mVUsearchProg() {
//------------------------------------------------------------------
void initVUrec (VURegs* vuRegs, const int vuIndex) { mVUinit(vuRegs, vuIndex); }
void closeVUrec(const int vuIndex) { mVUclose(mVUx, 0); }
void closeVUrec(const int vuIndex) { mVUclose(mVUx); }
void resetVUrec(const int vuIndex) { mVUreset(mVUx); }
void vsyncVUrec(const int vuIndex) { mVUvsyncUpdate(mVUx); }

View File

@ -114,23 +114,26 @@ struct microProgram {
u32 data [mProgSize]; // Holds a copy of the VU microProgram
microBlockManager* block[mProgSize/2]; // Array of Block Managers
microRange ranges; // The ranges of the microProgram that have already been recompiled
u64 used; // Number of times its been used
u32 last_used; // Counters # of frames since last use (starts at 3 and counts backwards to 0 for each 30fps vSync)
u32 frame; // Frame # the program was last used on
u32 used; // Program was used this frame?
bool isDead; // Program is dead?
};
#define mMaxProg ((mVU->index)?400:8) // The amount of Micro Programs Recs will 'remember' (For n = 1, 2, 4, 8, 16, etc...)
struct microProgManager {
microIR<mProgSize> allocInfo; // IR information
microProgram* prog; // Store MicroPrograms in memory
int max; // Max Number of MicroPrograms minus 1
int total; // Total Number of valid MicroPrograms minus 1
int cur; // Index to Current MicroProgram thats running (-1 = uncached)
int isSame; // Current cached microProgram is Exact Same program as mVU->regs->Micro (-1 = unknown, 0 = No, 1 = Yes)
int cleared; // Micro Program is Indeterminate so must be searched for (and if no matches are found then recompile a new one)
u8* x86ptr; // Pointer to program's recompilation code
u8* x86start; // Start of program's rec-cache
u8* x86end; // Limit of program's rec-cache
microRegInfo lpState; // Pipeline state from where program left off (useful for continuing execution)
microIR<mProgSize> allocInfo; // IR information
microProgram* prog; // Store MicroPrograms in memory
int* progList; // List of program indexes ordered by age (ordered from newest to oldest)
int max; // Max Number of MicroPrograms minus 1
int total; // Total Number of valid MicroPrograms minus 1
int cur; // Index to Current MicroProgram thats running (-1 = uncached)
int isSame; // Current cached microProgram is Exact Same program as mVU->regs->Micro (-1 = unknown, 0 = No, 1 = Yes)
int cleared; // Micro Program is Indeterminate so must be searched for (and if no matches are found then recompile a new one)
u32 curFrame; // Frame Counter
u8* x86ptr; // Pointer to program's recompilation code
u8* x86start; // Start of program's rec-cache
u8* x86end; // Limit of program's rec-cache
microRegInfo lpState; // Pipeline state from where program left off (useful for continuing execution)
};
#define mVUcacheSize (mMaxProg * (0x100000 * 0.5)) // 0.5mb per program
@ -175,7 +178,7 @@ extern int mVUdebugNow;
// Main Functions
microVUt(void) mVUinit(VURegs*, int);
microVUt(void) mVUreset(mV);
microVUt(void) mVUclose(mV, bool isReset);
microVUt(void) mVUclose(mV);
microVUt(void) mVUclear(mV, u32, u32);
microVUt(void*) mVUblockFetch(microVU* mVU, u32 startPC, uptr pState);
microVUx(void*) __fastcall mVUcompileJIT(u32 startPC, uptr pState);
@ -187,6 +190,8 @@ mVUop(mVUopU);
mVUop(mVUopL);
// Private Functions
microVUt(void) mVUsortProg(mV, int progIndex);
microVUf(void) mVUclearProg(int progIndex);
microVUf(int) mVUfindLeastUsedProg(microVU* mVU);
microVUf(int) mVUsearchProg();
microVUf(void) mVUcacheProg(int progIndex);

View File

@ -70,7 +70,7 @@
#define doLowerOp() { incPC(-1); mVUopL(mVU, 1); incPC(1); }
#define doSwapOp() { doBackupVF1(); mVUopL(mVU, 1); doBackupVF2(); incPC(1); doUpperOp(); doBackupVF3(); }
#define doIbit() { if (mVUup.iBit) { incPC(-1); MOV32ItoM((uptr)&mVU->regs->VI[REG_I].UL, curI); incPC(1); } }
#define blockCreate(addr) { if (!mVUblocks[addr]) mVUblocks[addr] = new microBlockManager();/*microBlockManager::AlignedNew();*/ }
#define blockCreate(addr) { if (!mVUblocks[addr]) mVUblocks[addr] = new microBlockManager(); }
//------------------------------------------------------------------
// Helper Functions

View File

@ -143,9 +143,9 @@ microVUt(int) mVUsetFlags(mV, int* xStatus, int* xMac, int* xClip) {
mFLAG.lastWrite = (xM-1) & 3;
cFLAG.lastWrite = (xC-1) & 3;
if (sFlagCond) { xStatus[xS] = cycles + 4; xS = (xS+1) & 3; }
if (mFLAG.doFlag) { xMac [xM] = cycles + 4; xM = (xM+1) & 3; }
if (cFLAG.doFlag) { xClip [xC] = cycles + 4; xC = (xC+1) & 3; }
if (sFlagCond) { xStatus[xS] = cycles + 4; xS = (xS+1) & 3; }
if (mFLAG.doFlag) { xMac [xM] = cycles + 4; xM = (xM+1) & 3; }
if (cFLAG.doFlag) { xClip [xC] = cycles + 4; xC = (xC+1) & 3; }
cycles++;
incPC2(2);
@ -170,9 +170,6 @@ microVUt(void) mVUsetupFlags(mV, int* xStatus, int* xMac, int* xClip, int cycles
int sortRegs = sortFlag(xStatus, bStatus, cycles);
// DevCon::Status("sortRegs = %d", params sortRegs);
// Note: Emitter will optimize out mov(reg1, reg1) cases...
// There 'is' still room for small optimizations but the
// sorting algorithm would be really complex and not really
// a noticeable improvement... (Most common cases are 1 & 2)
if (sortRegs == 1) {
MOV32RtoR(gprF0, getFlagReg1(bStatus[0]));
MOV32RtoR(gprF1, getFlagReg1(bStatus[1]));
@ -224,12 +221,12 @@ microVUt(void) mVUsetupFlags(mV, int* xStatus, int* xMac, int* xClip, int cycles
}
}
#define shortBranch() { \
if (branch == 3) { \
#define shortBranch() \
if ((branch == 3) || (branch == 4)) { \
mVUflagPass(mVU, aBranchAddr, (xCount - (mVUcount+1))); \
mVUcount = 4; \
if (branch == 3) { mVUcount = 4; break; } \
} \
}
else break
// Scan through instructions and check if flags are read (FSxxx, FMxxx, FCxxx opcodes)
void mVUflagPass(mV, u32 startPC, u32 xCount) {
@ -243,12 +240,12 @@ void mVUflagPass(mV, u32 startPC, u32 xCount) {
mVUbranch = 0;
for (int branch = 0; mVUcount < xCount; mVUcount++) {
incPC(1);
if ( curI & _Ebit_ ) { branch = 1; }
if ( curI & _DTbit_ ) { branch = 4; }
if (!(curI & _Ibit_) ) { incPC(-1); mVUopL(mVU, 3); incPC(1); }
if (branch >= 2) { shortBranch(); break; }
if ( curI & _Ebit_ ) { branch = 1; }
if ( curI & _DTbit_ ) { branch = 6; }
if (!(curI & _Ibit_) ) { incPC(-1); mVUopL(mVU, 3); incPC(1); }
if (branch >= 2) { shortBranch(); }
else if (branch == 1) { branch = 2; }
if (mVUbranch) { branch = (mVUbranch >= 9) ? 5 : 3; aBranchAddr = branchAddr; mVUbranch = 0; }
if (mVUbranch) { branch = ((mVUbranch>8)?(5):((mVUbranch<3)?3:4)); aBranchAddr = branchAddr; mVUbranch = 0; }
incPC(1);
}
if (mVUcount < 4) { mVUflagInfo |= 0xfff; }
@ -267,7 +264,7 @@ microVUt(void) mVUsetFlagInfo(mV) {
branchType1 { incPC(-1); mVUflagPass(mVU, branchAddr, 4); incPC(1); }
branchType2 {
if (!mVUlow.constJump.isValid) { mVUflagInfo |= 0xfff; }
else { mVUflagPass(mVU, mVUlow.constJump.regValue, 4); }
else { mVUflagPass(mVU, (mVUlow.constJump.regValue*8)&(mVU->microMemSize-8), 4); }
}
branchType3 {
incPC(-1);

View File

@ -18,7 +18,7 @@
#pragma once
// writes text directly to the microVU.txt, no newlines appended.
// writes text directly to mVU->logFile, no newlines appended.
microVUx(void) __mVULog(const char* fmt, ...) {
microVU* mVU = mVUx;
char tmp[2024];

View File

@ -219,6 +219,7 @@ typedef u32 (__fastcall *mVUCall)(void*, void*);
#define cmpOffset(x) ((u8*)&(((u8*)x)[mVUprogI.ranges.range[i][0]]))
#define Rmem (uptr)&mVU->regs->VI[REG_R].UL
#define Roffset (uptr)&mVU->regs->VI[9].UL
#define aWrap(x, m) ((x > m) ? 0 : x)
// Flag Info
#define __Status (mVUflagInfo & (0xf<<0))

View File

@ -568,9 +568,9 @@ void SuperVUDumpBlock(list<VuBaseBlock*>& blocks, int vuindex)
u32 *mem;
u32 i;
g_Conf.Folders.Dumps.Mkdir();
g_Conf.Folders.Logs.Mkdir();
AsciiFile eff(
Path::Combine( g_Conf.Folders.Dumps, wxsFormat(L"svu%cdump%.4X.txt", s_vu?L'0':L'1', s_pFnHeader->startpc) ),
Path::Combine( g_Conf.Folders.Logs, wxsFormat(L"svu%cdump%.4X.txt", s_vu?L'0':L'1', s_pFnHeader->startpc) ),
wxFile::write
);

View File

@ -26,9 +26,8 @@
#include "GPUScanlineEnvironment.h"
#include "GPUSetupPrimCodeGenerator.h"
#include "GPUDrawScanlineCodeGenerator.h"
#include "GSAlignedClass.h"
class GPUDrawScanline : public GSAlignedClass<16>, public IDrawScanline
class GPUDrawScanline : public IDrawScanline
{
GPUScanlineEnvironment m_env;

View File

@ -113,7 +113,17 @@ void GPURenderer::VSync()
Flush();
if(!Merge()) return;
if(!m_dev->IsLost(true))
{
if(!Merge())
{
return;
}
}
else
{
ResetDevice();
}
// osd
@ -148,11 +158,6 @@ void GPURenderer::VSync()
SetWindowText(m_hWnd, s.c_str());
}
if(m_dev->IsLost())
{
ResetDevice();
}
GSVector4i r;
GetClientRect(m_hWnd, r);

View File

@ -32,6 +32,7 @@ GPURendererSW::GPURendererSW(GSDevice* dev)
GPURendererSW::~GPURendererSW()
{
delete m_texture;
}
void GPURendererSW::ResetDevice()
@ -50,36 +51,16 @@ GSTexture* GPURendererSW::GetOutput()
r.right <<= m_scale.x;
r.bottom <<= m_scale.y;
// TODO
static uint32* buff = (uint32*)_aligned_malloc(m_mem.GetWidth() * m_mem.GetHeight() * sizeof(uint32), 16);
m_mem.ReadFrame32(r, buff, !!m_env.STATUS.ISRGB24);
int w = r.width();
int h = r.height();
if(m_texture)
if(m_dev->ResizeTexture(&m_texture, r.width(), r.height()))
{
if(m_texture->GetWidth() != w || m_texture->GetHeight() != h)
{
delete m_texture;
// TODO
static uint32* buff = (uint32*)_aligned_malloc(m_mem.GetWidth() * m_mem.GetHeight() * sizeof(uint32), 16);
m_texture = NULL;
}
m_mem.ReadFrame32(r, buff, !!m_env.STATUS.ISRGB24);
m_texture->Update(r.rsize(), buff, m_mem.GetWidth() * sizeof(uint32));
}
if(!m_texture)
{
m_texture = m_dev->CreateTexture(w, h);
if(!m_texture)
{
return NULL;
}
}
m_texture->Update(r.rsize(), buff, m_mem.GetWidth() * sizeof(uint32));
return m_texture;
}
@ -164,8 +145,8 @@ void GPURendererSW::Draw()
{
GSVector4 p = m_vertices[i].p;
tl = tl.minv(p);
br = br.maxv(p);
tl = tl.min(p);
br = br.max(p);
}
GSVector4i r = GSVector4i(tl.xyxy(br)).rintersect(data.scissor);

View File

@ -801,7 +801,9 @@ union
uint64 _PAD4:30;
};
};
REG_END
REG_END2
__forceinline bool IsRepeating() {return ((uint32)1 << TW) > (TBW << 6);}
REG_END2
REG64_(GIFReg, TEX1)
uint32 LCM:1;

View File

@ -25,6 +25,7 @@ template<int i> class GSAlignedClass
{
public:
GSAlignedClass() {}
virtual ~GSAlignedClass() {}
void* operator new (size_t size)
{

View File

@ -23,7 +23,7 @@
#include "GSClut.h"
#include "GSLocalMemory.h"
GSClut::GSClut(const GSLocalMemory* mem)
GSClut::GSClut(GSLocalMemory* mem)
: m_mem(mem)
{
uint8* p = (uint8*)VirtualAlloc(NULL, 2 * 4096, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
@ -168,14 +168,16 @@ void GSClut::WriteCLUT16S_I4_CSM1(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& T
template<int n> void GSClut::WriteCLUT32_CSM2(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& TEXCLUT)
{
uint16* RESTRICT clut = m_clut + (TEX0.CSA << 4);
GSLocalMemory::PixelOffset* po = m_mem->GetPixelOffset(TEX0.CBP, TEXCLUT.CBW, PSM_PSMCT32);
uint32 base = m_mem->PixelAddress32(0, TEXCLUT.COV, TEX0.CBP, TEXCLUT.CBW);
int* offset = &m_mem->rowOffset32[TEXCLUT.COU << 4];
uint32* RESTRICT s = &m_mem->m_vm32[po->row[TEXCLUT.COV]];
int* RESTRICT o = &po->col[0][TEXCLUT.COU << 4];
uint16* RESTRICT clut = m_clut + (TEX0.CSA << 4);
for(int i = 0; i < n; i++)
{
uint32 c = m_mem->ReadPixel32(base + offset[i]);
uint32 c = s[o[i]];
clut[i] = (uint16)(c & 0xffff);
clut[i + 256] = (uint16)(c >> 16);
@ -184,27 +186,31 @@ template<int n> void GSClut::WriteCLUT32_CSM2(const GIFRegTEX0& TEX0, const GIFR
template<int n> void GSClut::WriteCLUT16_CSM2(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& TEXCLUT)
{
uint16* RESTRICT clut = m_clut + (TEX0.CSA << 4);
GSLocalMemory::PixelOffset* po = m_mem->GetPixelOffset(TEX0.CBP, TEXCLUT.CBW, PSM_PSMCT16);
uint32 base = m_mem->PixelAddress16(0, TEXCLUT.COV, TEX0.CBP, TEXCLUT.CBW);
int* offset = &m_mem->rowOffset16[TEXCLUT.COU << 4];
uint16* RESTRICT s = &m_mem->m_vm16[po->row[TEXCLUT.COV]];
int* RESTRICT o = &po->col[0][TEXCLUT.COU << 4];
uint16* RESTRICT clut = m_clut + (TEX0.CSA << 4);
for(int i = 0; i < n; i++)
{
clut[i] = (uint16)m_mem->ReadPixel16(base + offset[i]);
clut[i] = s[o[i]];
}
}
template<int n> void GSClut::WriteCLUT16S_CSM2(const GIFRegTEX0& TEX0, const GIFRegTEXCLUT& TEXCLUT)
{
uint16* RESTRICT clut = m_clut + (TEX0.CSA << 4);
GSLocalMemory::PixelOffset* po = m_mem->GetPixelOffset(TEX0.CBP, TEXCLUT.CBW, PSM_PSMCT16S);
uint32 base = m_mem->PixelAddress16S(0, TEXCLUT.COV, TEX0.CBP, TEXCLUT.CBW);
int* offset = &m_mem->rowOffset16S[TEXCLUT.COU << 4];
uint16* RESTRICT s = &m_mem->m_vm16[po->row[TEXCLUT.COV]];
int* RESTRICT o = &po->col[0][TEXCLUT.COU << 4];
uint16* RESTRICT clut = m_clut + (TEX0.CSA << 4);
for(int i = 0; i < n; i++)
{
clut[i] = (uint16)m_mem->ReadPixel16(base + offset[i]);
clut[i] = s[o[i]];
}
}

View File

@ -30,7 +30,7 @@ class GSLocalMemory;
__declspec(align(16)) class GSClut : public GSAlignedClass<16>
{
const GSLocalMemory* m_mem;
GSLocalMemory* m_mem;
uint32 m_CBP[2];
uint16* m_clut;
@ -93,7 +93,7 @@ __declspec(align(16)) class GSClut : public GSAlignedClass<16>
static void Expand16(const uint16* RESTRICT src, uint32* RESTRICT dst, int w, const GIFRegTEXA& TEXA);
public:
GSClut(const GSLocalMemory* mem);
GSClut(GSLocalMemory* mem);
virtual ~GSClut();
void Invalidate();

View File

@ -89,6 +89,7 @@ CRC::Game CRC::m_games[] =
{0x7D8F539A, SoTC, EU, 0},
{0x3122B508, OnePieceGrandAdventure, US, 0},
{0x8DF14A24, OnePieceGrandAdventure, Unknown, 0},
{0x5D02CC5B, OnePieceGrandBattle, Unknown, 0},
{0x6F8545DB, ICO, US, 0},
{0xB01A4C95, ICO, JP, 0},
{0x5C991F4E, ICO, Unknown, 0},
@ -143,7 +144,9 @@ CRC::Game CRC::m_games[] =
{0x23A97857, StarOcean3, JPUNDUB, 0},
{0xCC96CE93, ValkyrieProfile2, US, 0},
{0x774DE8E2, ValkyrieProfile2, JP, 0},
{0x04CCB600, ValkyrieProfile2, EU, 0},
{0x47B9B2FD, RadiataStories, US, 0},
{0xE8FCF8EC, SMTNocturne, US, ZWriteMustNotClear}, // saves/reloads z buffer around shadow drawing
};
hash_map<uint32, CRC::Game*> CRC::m_map;

View File

@ -48,6 +48,7 @@ public:
BullyCC,
SoTC,
OnePieceGrandAdventure,
OnePieceGrandBattle,
ICO,
GT4,
WildArms5,
@ -74,6 +75,7 @@ public:
StarOcean3,
ValkyrieProfile2,
RadiataStories,
SMTNocturne,
TitleCount,
};
@ -95,6 +97,7 @@ public:
enum Flags
{
PointListPalette = 1,
ZWriteMustNotClear = 2,
};
struct Game

View File

@ -24,6 +24,7 @@
GSDevice::GSDevice()
: m_wnd(NULL)
, m_rbswapped(false)
, m_backbuffer(NULL)
, m_merge(NULL)
, m_weavebob(NULL)
@ -34,6 +35,13 @@ GSDevice::GSDevice()
GSDevice::~GSDevice()
{
for_each(m_pool.begin(), m_pool.end(), delete_object());
delete m_backbuffer;
delete m_merge;
delete m_weavebob;
delete m_blend;
delete m_1x1;
}
bool GSDevice::Create(GSWnd* wnd, bool vsync)
@ -44,12 +52,9 @@ bool GSDevice::Create(GSWnd* wnd, bool vsync)
return true;
}
bool GSDevice::Reset(int w, int h, bool fs)
bool GSDevice::Reset(int w, int h, int mode)
{
for(list<GSTexture*>::iterator i = m_pool.begin(); i != m_pool.end(); i++)
{
delete *i;
}
for_each(m_pool.begin(), m_pool.end(), delete_object());
m_pool.clear();
@ -74,9 +79,15 @@ void GSDevice::Present(const GSVector4i& r, int shader)
{
GSVector4i cr = m_wnd->GetClientRect();
if(m_backbuffer->GetWidth() != cr.width() || m_backbuffer->GetHeight() != cr.height())
int w = std::max(cr.width(), 1);
int h = std::max(cr.height(), 1);
if(!m_backbuffer || m_backbuffer->GetWidth() != w || m_backbuffer->GetHeight() != h)
{
Reset(cr.width(), cr.height(), false);
if(!Reset(w, h, DontCare))
{
return;
}
}
ClearRenderTarget(m_backbuffer, 0);
@ -222,3 +233,21 @@ void GSDevice::Interlace(const GSVector2i& ds, int field, int mode, float yoffse
m_current = m_merge;
}
}
bool GSDevice::ResizeTexture(GSTexture** t, int w, int h)
{
if(t == NULL) {ASSERT(0); return false;}
GSTexture* t2 = *t;
if(t2 == NULL || t2->GetWidth() != w || t2->GetHeight() != h)
{
delete t2;
t2 = CreateTexture(w, h);
*t = t2;
}
return t2 != NULL;
}

View File

@ -55,6 +55,7 @@ class GSDevice : public GSAlignedClass<16>
protected:
GSWnd* m_wnd;
bool m_vsync;
bool m_rbswapped;
GSTexture* m_backbuffer;
GSTexture* m_merge;
GSTexture* m_weavebob;
@ -73,10 +74,11 @@ public:
void Recycle(GSTexture* t);
virtual bool Create(GSWnd* wnd, bool vsync);
virtual bool Reset(int w, int h, bool fs);
enum {Windowed, Fullscreen, DontCare};
virtual bool IsLost() {return false;}
virtual bool Create(GSWnd* wnd, bool vsync);
virtual bool Reset(int w, int h, int mode);
virtual bool IsLost(bool update = false) {return false;}
virtual void Present(const GSVector4i& r, int shader);
virtual void Flip() {}
@ -96,15 +98,20 @@ public:
virtual GSTexture* CopyOffscreen(GSTexture* src, const GSVector4& sr, int w, int h, int format = 0) {return NULL;}
virtual void CopyRect(GSTexture* st, GSTexture* dt, const GSVector4i& r) {}
virtual void StretchRect(GSTexture* st, GSTexture* dt, const GSVector4& dr, int shader = 0, bool linear = true);
virtual void StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, int shader = 0, bool linear = true) {}
GSTexture* GetCurrent();
virtual bool IsCurrentRGBA() {return true;}
void Merge(GSTexture* st[2], GSVector4* sr, GSVector4* dr, const GSVector2i& fs, bool slbg, bool mmod, const GSVector4& c);
void Interlace(const GSVector2i& ds, int field, int mode, float yoffset);
bool ResizeTexture(GSTexture** t, int w, int h);
bool IsRBSwapped() {return m_rbswapped;}
template<class T> void PrepareShaderMacro(vector<T>& dst, const T* src, const char* model)
{
dst.clear();

View File

@ -207,16 +207,16 @@ bool GSDevice10::Create(GSWnd* wnd, bool vsync)
//
Reset(1, 1, false);
Reset(1, 1, Windowed);
//
return true;
}
bool GSDevice10::Reset(int w, int h, bool fs)
bool GSDevice10::Reset(int w, int h, int mode)
{
if(!__super::Reset(w, h, fs))
if(!__super::Reset(w, h, mode))
return false;
DXGI_SWAP_CHAIN_DESC scd;
@ -392,6 +392,13 @@ GSTexture* GSDevice10::CopyOffscreen(GSTexture* src, const GSVector4& sr, int w,
return dst;
}
void GSDevice10::CopyRect(GSTexture* st, GSTexture* dt, const GSVector4i& r)
{
D3D10_BOX box = {r.left, r.top, 0, r.right, r.bottom, 1};
m_dev->CopySubresourceRegion(*(GSTexture10*)dt, 0, 0, 0, 0, *(GSTexture10*)st, 0, &box);
}
void GSDevice10::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, int shader, bool linear)
{
StretchRect(st, sr, dt, dr, m_convert.ps[shader], NULL, linear);
@ -504,7 +511,7 @@ void GSDevice10::IASetVertexBuffer(const void* vertices, size_t stride, size_t c
m_vertices.vb = NULL;
m_vertices.start = 0;
m_vertices.count = 0;
m_vertices.limit = max(count * 3 / 2, 10000);
m_vertices.limit = std::max<int>(count * 3 / 2, 10000);
}
if(m_vertices.vb == NULL)

View File

@ -96,8 +96,7 @@ public:
virtual ~GSDevice10();
bool Create(GSWnd* wnd, bool vsync);
bool Reset(int w, int h, bool fs);
bool Reset(int w, int h, int mode);
void Flip();
void BeginScene();
@ -116,6 +115,8 @@ public:
GSTexture* CopyOffscreen(GSTexture* src, const GSVector4& sr, int w, int h, int format = 0);
void CopyRect(GSTexture* st, GSTexture* dt, const GSVector4i& r);
void StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, int shader = 0, bool linear = true);
void StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, ID3D10PixelShader* ps, ID3D10Buffer* ps_cb, bool linear = true);
void StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, ID3D10PixelShader* ps, ID3D10Buffer* ps_cb, ID3D10BlendState* bs, bool linear = true);

View File

@ -92,8 +92,8 @@ bool GSDevice11::Create(GSWnd* wnd, bool vsync)
flags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &scd, &m_swapchain, &m_dev, &m_level, &m_ctx);
// hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_REFERENCE, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &scd, &m_swapchain, &m_dev, &m_level, &m_ctx);
hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, flags, NULL, 0, D3D11_SDK_VERSION, &scd, &m_swapchain, &m_dev, &m_level, &m_ctx);
// hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_REFERENCE, NULL, flags, NULL, 0, D3D11_SDK_VERSION, &scd, &m_swapchain, &m_dev, &m_level, &m_ctx);
if(FAILED(hr)) return false;
@ -244,16 +244,16 @@ bool GSDevice11::Create(GSWnd* wnd, bool vsync)
//
Reset(1, 1, false);
Reset(1, 1, Windowed);
//
return true;
}
bool GSDevice11::Reset(int w, int h, bool fs)
bool GSDevice11::Reset(int w, int h, int mode)
{
if(!__super::Reset(w, h, fs))
if(!__super::Reset(w, h, mode))
return false;
DXGI_SWAP_CHAIN_DESC scd;
@ -429,6 +429,13 @@ GSTexture* GSDevice11::CopyOffscreen(GSTexture* src, const GSVector4& sr, int w,
return dst;
}
void GSDevice11::CopyRect(GSTexture* st, GSTexture* dt, const GSVector4i& r)
{
D3D11_BOX box = {r.left, r.top, 0, r.right, r.bottom, 1};
m_ctx->CopySubresourceRegion(*(GSTexture11*)dt, 0, 0, 0, 0, *(GSTexture11*)st, 0, &box);
}
void GSDevice11::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, int shader, bool linear)
{
StretchRect(st, sr, dt, dr, m_convert.ps[shader], NULL, linear);
@ -541,7 +548,7 @@ void GSDevice11::IASetVertexBuffer(const void* vertices, size_t stride, size_t c
m_vertices.vb = NULL;
m_vertices.start = 0;
m_vertices.count = 0;
m_vertices.limit = max(count * 3 / 2, 10000);
m_vertices.limit = std::max<int>(count * 3 / 2, 10000);
}
if(m_vertices.vb == NULL)

View File

@ -99,8 +99,7 @@ public:
virtual ~GSDevice11();
bool Create(GSWnd* wnd, bool vsync);
bool Reset(int w, int h, bool fs);
bool Reset(int w, int h, int mode);
void Flip();
void BeginScene();
@ -119,6 +118,8 @@ public:
GSTexture* CopyOffscreen(GSTexture* src, const GSVector4& sr, int w, int h, int format = 0);
void CopyRect(GSTexture* st, GSTexture* dt, const GSVector4i& r);
void StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, int shader = 0, bool linear = true);
void StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, ID3D11PixelShader* ps, ID3D11Buffer* ps_cb, bool linear = true);
void StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, ID3D11PixelShader* ps, ID3D11Buffer* ps_cb, ID3D11BlendState* bs, bool linear = true);

View File

@ -25,6 +25,7 @@
#include "GSDevice7.h"
GSDevice7::GSDevice7()
: m_lost(false)
{
}
@ -75,14 +76,14 @@ bool GSDevice7::Create(GSWnd* wnd, bool vsync)
return false;
}
Reset(1, 1, false);
Reset(1, 1, Windowed);
return true;
}
bool GSDevice7::Reset(int w, int h, bool fs)
bool GSDevice7::Reset(int w, int h, int mode)
{
if(!__super::Reset(w, h, fs))
if(!__super::Reset(w, h, mode))
return false;
DDSURFACEDESC2 desc;
@ -130,6 +131,8 @@ bool GSDevice7::Reset(int w, int h, bool fs)
}
}
m_lost = false;
return true;
}
@ -139,9 +142,15 @@ void GSDevice7::Present(const GSVector4i& r, int shader)
GSVector4i cr = m_wnd->GetClientRect();
if(m_backbuffer->GetWidth() != cr.width() || m_backbuffer->GetHeight() != cr.height())
int w = std::max(cr.width(), 1);
int h = std::max(cr.height(), 1);
if(!m_backbuffer || m_backbuffer->GetWidth() != w || m_backbuffer->GetHeight() != h)
{
Reset(cr.width(), cr.height(), false);
if(!Reset(w, h, DontCare))
{
return;
}
}
CComPtr<IDirectDrawSurface7> backbuffer = *(GSTexture7*)m_backbuffer;
@ -157,7 +166,10 @@ void GSDevice7::Present(const GSVector4i& r, int shader)
GSVector4i r2 = r;
hr = backbuffer->Blt(r2, *(GSTexture7*)m_merge, NULL, DDBLT_WAIT, NULL);
if(m_current)
{
hr = backbuffer->Blt(r2, *(GSTexture7*)m_current, NULL, DDBLT_WAIT, NULL);
}
// if ClearRenderTarget was implemented the parent class could handle these tasks until this point
@ -174,6 +186,8 @@ void GSDevice7::Present(const GSVector4i& r, int shader)
if(hr == DDERR_SURFACELOST)
{
m_lost = true;
// TODO
HRESULT hr = m_dd->TestCooperativeLevel();

View File

@ -29,6 +29,7 @@ class GSDevice7 : public GSDevice
private:
CComPtr<IDirectDraw7> m_dd;
CComPtr<IDirectDrawSurface7> m_primary;
bool m_lost;
GSTexture* Create(int type, int w, int h, int format);
@ -40,7 +41,7 @@ public:
virtual ~GSDevice7();
bool Create(GSWnd* wnd, bool vsync);
bool Reset(int w, int h, bool fs);
bool Reset(int w, int h, int mode);
bool IsLost(bool update) {return m_lost;}
void Present(const GSVector4i& r, int shader);
};

View File

@ -42,7 +42,10 @@ GSDevice9::GSDevice9()
, m_bf(0xffffffff)
, m_rtv(NULL)
, m_dsv(NULL)
, m_lost(false)
{
m_rbswapped = true;
memset(&m_pp, 0, sizeof(m_pp));
memset(&m_ddcaps, 0, sizeof(m_ddcaps));
memset(&m_d3dcaps, 0, sizeof(m_d3dcaps));
@ -89,7 +92,7 @@ bool GSDevice9::Create(GSWnd* wnd, bool vsync)
// d3d
m_d3d = Direct3DCreate9(D3D_SDK_VERSION);
m_d3d.Attach(Direct3DCreate9(D3D_SDK_VERSION));
if(!m_d3d) return false;
@ -105,9 +108,7 @@ bool GSDevice9::Create(GSWnd* wnd, bool vsync)
m_d3d->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &m_d3dcaps);
bool fs = theApp.GetConfig("ModeWidth", 0) > 0;
if(!Reset(1, 1, fs)) return false;
if(!Reset(1, 1, theApp.GetConfig("ModeWidth", 0) > 0 ? Fullscreen : Windowed)) return false;
m_dev->Clear(0, NULL, D3DCLEAR_TARGET, 0, 1.0f, 0);
@ -188,35 +189,46 @@ bool GSDevice9::Create(GSWnd* wnd, bool vsync)
return true;
}
bool GSDevice9::Reset(int w, int h, bool fs)
bool GSDevice9::Reset(int w, int h, int mode)
{
if(!__super::Reset(w, h, fs))
if(!__super::Reset(w, h, mode))
return false;
HRESULT hr;
if(!m_d3d) return false;
if(m_swapchain && !fs && m_pp.Windowed)
if(mode == DontCare)
{
m_swapchain = NULL;
mode = m_pp.Windowed ? Windowed : Fullscreen;
}
m_pp.BackBufferWidth = w;
m_pp.BackBufferHeight = h;
if(!m_lost)
{
if(m_swapchain && mode != Fullscreen && m_pp.Windowed)
{
m_swapchain = NULL;
hr = m_dev->CreateAdditionalSwapChain(&m_pp, &m_swapchain);
m_pp.BackBufferWidth = w;
m_pp.BackBufferHeight = h;
if(FAILED(hr)) return false;
hr = m_dev->CreateAdditionalSwapChain(&m_pp, &m_swapchain);
CComPtr<IDirect3DSurface9> backbuffer;
hr = m_swapchain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
m_backbuffer = new GSTexture9(backbuffer);
if(FAILED(hr)) return false;
return true;
CComPtr<IDirect3DSurface9> backbuffer;
hr = m_swapchain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
m_backbuffer = new GSTexture9(backbuffer);
return true;
}
}
m_swapchain = NULL;
m_vertices.vb = NULL;
m_vertices.vb_old = NULL;
m_vertices.start = 0;
m_vertices.count = 0;
if(m_vs_cb) _aligned_free(m_vs_cb);
if(m_ps_cb) _aligned_free(m_ps_cb);
@ -258,7 +270,7 @@ bool GSDevice9::Reset(int w, int h, bool fs)
int mh = theApp.GetConfig("ModeHeight", 0);
int mrr = theApp.GetConfig("ModeRefreshRate", 0);
if(fs && mw > 0 && mh > 0 && mrr >= 0)
if(mode == Fullscreen && mw > 0 && mh > 0 && mrr >= 0)
{
m_pp.Windowed = FALSE;
m_pp.BackBufferWidth = mw;
@ -324,27 +336,39 @@ bool GSDevice9::Reset(int w, int h, bool fs)
return true;
}
bool GSDevice9::IsLost()
bool GSDevice9::IsLost(bool update)
{
HRESULT hr = m_dev->TestCooperativeLevel();
if(!m_lost || update)
{
HRESULT hr = m_dev->TestCooperativeLevel();
return hr == D3DERR_DEVICELOST || hr == D3DERR_DEVICENOTRESET;
m_lost = hr == D3DERR_DEVICELOST || hr == D3DERR_DEVICENOTRESET;
}
return m_lost;
}
void GSDevice9::Flip()
{
m_dev->EndScene();
HRESULT hr;
if(m_swapchain)
{
m_swapchain->Present(NULL, NULL, NULL, NULL, 0);
hr = m_swapchain->Present(NULL, NULL, NULL, NULL, 0);
}
else
{
m_dev->Present(NULL, NULL, NULL, NULL);
hr = m_dev->Present(NULL, NULL, NULL, NULL);
}
m_dev->BeginScene();
if(FAILED(hr))
{
m_lost = true;
}
}
void GSDevice9::BeginScene()
@ -549,6 +573,11 @@ GSTexture* GSDevice9::CopyOffscreen(GSTexture* src, const GSVector4& sr, int w,
return dst;
}
void GSDevice9::CopyRect(GSTexture* st, GSTexture* dt, const GSVector4i& r)
{
m_dev->StretchRect(*(GSTexture9*)st, r, *(GSTexture9*)dt, r, D3DTEXF_POINT);
}
void GSDevice9::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, int shader, bool linear)
{
StretchRect(st, sr, dt, dr, m_convert.ps[shader], NULL, 0, linear);
@ -663,7 +692,7 @@ void GSDevice9::IASetVertexBuffer(const void* vertices, size_t stride, size_t co
m_vertices.vb = NULL;
m_vertices.start = 0;
m_vertices.count = 0;
m_vertices.limit = max(count * 3 / 2, 10000);
m_vertices.limit = std::max<int>(count * 3 / 2, 10000);
}
if(m_vertices.vb == NULL)
@ -817,16 +846,16 @@ void GSDevice9::PSSetSamplerState(Direct3DSamplerState9* ss)
m_dev->SetSamplerState(0, D3DSAMP_ADDRESSU, ss->AddressU);
m_dev->SetSamplerState(0, D3DSAMP_ADDRESSV, ss->AddressV);
m_dev->SetSamplerState(1, D3DSAMP_ADDRESSU, ss->AddressU);
m_dev->SetSamplerState(1, D3DSAMP_ADDRESSV, ss->AddressV);
m_dev->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
m_dev->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
m_dev->SetSamplerState(2, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
m_dev->SetSamplerState(2, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
m_dev->SetSamplerState(3, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
m_dev->SetSamplerState(3, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
m_dev->SetSamplerState(0, D3DSAMP_MINFILTER, ss->FilterMin[0]);
m_dev->SetSamplerState(0, D3DSAMP_MAGFILTER, ss->FilterMag[0]);
m_dev->SetSamplerState(1, D3DSAMP_MINFILTER, ss->FilterMin[1]);
m_dev->SetSamplerState(1, D3DSAMP_MAGFILTER, ss->FilterMag[1]);
m_dev->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_POINT);
m_dev->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
m_dev->SetSamplerState(2, D3DSAMP_MINFILTER, D3DTEXF_POINT);
m_dev->SetSamplerState(2, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
m_dev->SetSamplerState(3, D3DSAMP_MINFILTER, D3DTEXF_POINT);

View File

@ -92,9 +92,11 @@ private:
DDCAPS m_ddcaps;
D3DCAPS9 m_d3dcaps;
D3DPRESENT_PARAMETERS m_pp;
CComPtr<IDirect3D9> m_d3d;
CComPtr<IDirect3DDevice9> m_dev;
CComPtr<IDirect3DSwapChain9> m_swapchain;
bool m_lost;
struct
{
@ -103,7 +105,6 @@ private:
} m_vertices;
public: // TODO
D3DPRESENT_PARAMETERS m_pp;
struct
{
@ -132,9 +133,8 @@ public:
virtual ~GSDevice9();
bool Create(GSWnd* wnd, bool vsync);
bool Reset(int w, int h, bool fs);
bool IsLost();
bool Reset(int w, int h, int mode);
bool IsLost(bool update);
void Flip();
void BeginScene();
@ -153,7 +153,7 @@ public:
GSTexture* CopyOffscreen(GSTexture* src, const GSVector4& sr, int w, int h, int format = 0);
virtual bool IsCurrentRGBA() {return false;}
void CopyRect(GSTexture* st, GSTexture* dt, const GSVector4i& r);
void StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, int shader = 0, bool linear = true);
void StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, IDirect3DPixelShader9* ps, const float* ps_cb, int ps_cb_len, bool linear = true);

View File

@ -29,14 +29,14 @@ bool GSDeviceNull::Create(GSWnd* wnd, bool vsync)
return false;
}
Reset(1, 1, false);
Reset(1, 1, Windowed);
return true;
}
bool GSDeviceNull::Reset(int w, int h, bool fs)
bool GSDeviceNull::Reset(int w, int h, int mode)
{
if(!__super::Reset(w, h, fs))
if(!__super::Reset(w, h, mode))
return false;
return true;

View File

@ -36,5 +36,5 @@ public:
GSDeviceNull() {}
bool Create(GSWnd* wnd, bool vsync);
bool Reset(int w, int h, bool fs);
bool Reset(int w, int h, int mode);
};

View File

@ -150,14 +150,14 @@ bool GSDeviceOGL::Create(GSWnd* wnd, bool vsync)
*/
GSVector4i r = wnd->GetClientRect();
Reset(r.width(), r.height(), false);
Reset(r.width(), r.height(), Windowed);
return true;
}
bool GSDeviceOGL::Reset(int w, int h, bool fs)
bool GSDeviceOGL::Reset(int w, int h, int mode)
{
if(!__super::Reset(w, h, fs))
if(!__super::Reset(w, h, mode))
return false;
glCullFace(GL_FRONT_AND_BACK); CheckError();
@ -333,6 +333,11 @@ GSTexture* GSDeviceOGL::CopyOffscreen(GSTexture* src, const GSVector4& sr, int w
return NULL;
}
void GSDeviceOGL::CopyRect(GSTexture* st, GSTexture* dt, const GSVector4i& r)
{
// TODO
}
void GSDeviceOGL::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, int shader, bool linear)
{
// TODO
@ -361,7 +366,7 @@ void GSDeviceOGL::IASetVertexBuffer(const void* vertices, size_t stride, size_t
{
m_vertices.start = 0;
m_vertices.count = 0;
m_vertices.limit = max(count * 3 / 2, 10000);
m_vertices.limit = std::max<int>(count * 3 / 2, 10000);
growbuffer = true;
}

View File

@ -110,8 +110,7 @@ public:
virtual ~GSDeviceOGL();
bool Create(GSWnd* wnd, bool vsync);
bool Reset(int w, int h, bool fs);
bool Reset(int w, int h, int mode);
void Present(const GSVector4i& r, int shader);
void Flip();
@ -131,6 +130,8 @@ public:
GSTexture* CopyOffscreen(GSTexture* src, const GSVector4& sr, int w, int h, int format = 0);
void CopyRect(GSTexture* st, GSTexture* dt, const GSVector4i& r);
void StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, int shader = 0, bool linear = true);
void IASetVertexBuffer(const void* vertices, size_t stride, size_t count);

View File

@ -48,8 +48,8 @@ void GSDrawScanline::BeginDraw(const GSRasterizerData* data, Functions* f)
m_env.vm = p->vm;
m_env.fbr = p->fbo->row;
m_env.zbr = p->zbo->row;
m_env.fbc = p->fbo->col;
m_env.zbc = p->zbo->col;
m_env.fbc = p->fbo->col[0];
m_env.zbc = p->zbo->col[0];
m_env.fzbr = p->fzbo->row;
m_env.fzbc = p->fzbo->col;
m_env.fm = GSVector4i(p->fm);
@ -116,8 +116,8 @@ void GSDrawScanline::BeginDraw(const GSRasterizerData* data, Functions* f)
m_env.t.mask.u32[0] = 0;
break;
case CLAMP_REGION_CLAMP:
m_env.t.min.u16[0] = min(context->CLAMP.MINU, tw - 1);
m_env.t.max.u16[0] = min(context->CLAMP.MAXU, tw - 1);
m_env.t.min.u16[0] = std::min<int>(context->CLAMP.MINU, tw - 1);
m_env.t.max.u16[0] = std::min<int>(context->CLAMP.MAXU, tw - 1);
m_env.t.mask.u32[0] = 0;
break;
case CLAMP_REGION_REPEAT:
@ -142,8 +142,8 @@ void GSDrawScanline::BeginDraw(const GSRasterizerData* data, Functions* f)
m_env.t.mask.u32[2] = 0;
break;
case CLAMP_REGION_CLAMP:
m_env.t.min.u16[4] = min(context->CLAMP.MINV, th - 1);
m_env.t.max.u16[4] = min(context->CLAMP.MAXV, th - 1); // ffx anima summon scene, when the anchor appears (th = 256, maxv > 256)
m_env.t.min.u16[4] = std::min<int>(context->CLAMP.MINV, th - 1);
m_env.t.max.u16[4] = std::min<int>(context->CLAMP.MAXV, th - 1); // ffx anima summon scene, when the anchor appears (th = 256, maxv > 256)
m_env.t.mask.u32[2] = 0;
break;
case CLAMP_REGION_REPEAT:
@ -224,22 +224,22 @@ void GSDrawScanline::DrawSolidRect(const GSVector4i& r, const GSVertexSW& v)
{
if(m == 0)
{
DrawSolidRectT<uint32, false>(m_env.zbr, m_env.zbc[0], r, z, m);
DrawSolidRectT<uint32, false>(m_env.zbr, m_env.zbc, r, z, m);
}
else
{
DrawSolidRectT<uint32, true>(m_env.zbr, m_env.zbc[0], r, z, m);
DrawSolidRectT<uint32, true>(m_env.zbr, m_env.zbc, r, z, m);
}
}
else
{
if(m == 0)
{
DrawSolidRectT<uint16, false>(m_env.zbr, m_env.zbc[0], r, z, m);
DrawSolidRectT<uint16, false>(m_env.zbr, m_env.zbc, r, z, m);
}
else
{
DrawSolidRectT<uint16, true>(m_env.zbr, m_env.zbc[0], r, z, m);
DrawSolidRectT<uint16, true>(m_env.zbr, m_env.zbc, r, z, m);
}
}
}
@ -259,11 +259,11 @@ void GSDrawScanline::DrawSolidRect(const GSVector4i& r, const GSVertexSW& v)
{
if(m == 0)
{
DrawSolidRectT<uint32, false>(m_env.fbr, m_env.fbc[0], r, c, m);
DrawSolidRectT<uint32, false>(m_env.fbr, m_env.fbc, r, c, m);
}
else
{
DrawSolidRectT<uint32, true>(m_env.fbr, m_env.fbc[0], r, c, m);
DrawSolidRectT<uint32, true>(m_env.fbr, m_env.fbc, r, c, m);
}
}
else
@ -272,18 +272,18 @@ void GSDrawScanline::DrawSolidRect(const GSVector4i& r, const GSVertexSW& v)
if(m == 0)
{
DrawSolidRectT<uint16, false>(m_env.fbr, m_env.fbc[0], r, c, m);
DrawSolidRectT<uint16, false>(m_env.fbr, m_env.fbc, r, c, m);
}
else
{
DrawSolidRectT<uint16, true>(m_env.fbr, m_env.fbc[0], r, c, m);
DrawSolidRectT<uint16, true>(m_env.fbr, m_env.fbc, r, c, m);
}
}
}
}
template<class T, bool masked>
void GSDrawScanline::DrawSolidRectT(const GSVector4i* row, int* col, const GSVector4i& r, uint32 c, uint32 m)
void GSDrawScanline::DrawSolidRectT(const int* RESTRICT row, const int* RESTRICT col, const GSVector4i& r, uint32 c, uint32 m)
{
if(m == 0xffffffff) return;
@ -320,35 +320,33 @@ void GSDrawScanline::DrawSolidRectT(const GSVector4i* row, int* col, const GSVec
}
template<class T, bool masked>
void GSDrawScanline::FillRect(const GSVector4i* row, int* col, const GSVector4i& r, uint32 c, uint32 m)
void GSDrawScanline::FillRect(const int* RESTRICT row, const int* RESTRICT col, const GSVector4i& r, uint32 c, uint32 m)
{
if(r.x >= r.z) return;
for(int y = r.y; y < r.w; y++)
{
uint32 base = row[y].x;
T* RESTRICT d = &((T*)m_env.vm)[row[y]];
for(int x = r.x; x < r.z; x++)
{
T* p = &((T*)m_env.vm)[base + col[x]];
*p = (T)(!masked ? c : (c | (*p & m)));
d[col[x]] = (T)(!masked ? c : (c | (d[col[x]] & m)));
}
}
}
template<class T, bool masked>
void GSDrawScanline::FillBlock(const GSVector4i* row, int* col, const GSVector4i& r, const GSVector4i& c, const GSVector4i& m)
void GSDrawScanline::FillBlock(const int* RESTRICT row, const int* RESTRICT col, const GSVector4i& r, const GSVector4i& c, const GSVector4i& m)
{
if(r.x >= r.z) return;
for(int y = r.y; y < r.w; y += 8)
{
uint32 base = row[y].x;
T* RESTRICT d = &((T*)m_env.vm)[row[y]];
for(int x = r.x; x < r.z; x += 8 * 4 / sizeof(T))
{
GSVector4i* p = (GSVector4i*)&((T*)m_env.vm)[base + col[x]];
GSVector4i* RESTRICT p = (GSVector4i*)&d[col[x]];
for(int i = 0; i < 16; i += 4)
{

View File

@ -26,9 +26,8 @@
#include "GSScanlineEnvironment.h"
#include "GSSetupPrimCodeGenerator.h"
#include "GSDrawScanlineCodeGenerator.h"
#include "GSAlignedClass.h"
class GSDrawScanline : public GSAlignedClass<16>, public IDrawScanline
class GSDrawScanline : public IDrawScanline
{
GSScanlineEnvironment m_env;
GSScanlineSelector m_sel;
@ -60,13 +59,13 @@ class GSDrawScanline : public GSAlignedClass<16>, public IDrawScanline
void DrawSolidRect(const GSVector4i& r, const GSVertexSW& v);
template<class T, bool masked>
void DrawSolidRectT(const GSVector4i* row, int* col, const GSVector4i& r, uint32 c, uint32 m);
void DrawSolidRectT(const int* RESTRICT row, const int* RESTRICT col, const GSVector4i& r, uint32 c, uint32 m);
template<class T, bool masked>
__forceinline void FillRect(const GSVector4i* row, int* col, const GSVector4i& r, uint32 c, uint32 m);
__forceinline void FillRect(const int* RESTRICT row, const int* RESTRICT col, const GSVector4i& r, uint32 c, uint32 m);
template<class T, bool masked>
__forceinline void FillBlock(const GSVector4i* row, int* col, const GSVector4i& r, const GSVector4i& c, const GSVector4i& m);
__forceinline void FillBlock(const int* RESTRICT row, const int* RESTRICT col, const GSVector4i& r, const GSVector4i& c, const GSVector4i& m);
protected:
GSState* m_state;

View File

@ -66,10 +66,7 @@ public:
virtual ~GSFunctionMap()
{
for(hash_map<KEY, ActivePtr*>::iterator i = m_map_active.begin(); i != m_map_active.end(); i++)
{
delete i->second;
}
for_each(m_map_active.begin(), m_map_active.end(), delete_second());
}
VALUE operator [] (KEY key)
@ -177,10 +174,7 @@ public:
virtual ~GSCodeGeneratorFunctionMap()
{
for(hash_map<uint64, CG*>::iterator i = m_cgmap.begin(); i != m_cgmap.end(); i++)
{
delete i->second;
}
for_each(m_cgmap.begin(), m_cgmap.end(), delete_second());
}
VALUE GetDefaultFunction(KEY key)

View File

@ -28,19 +28,21 @@
#include "GSLocalMemory.h"
#define ASSERT_BLOCK(r, w, h) \
ASSERT((r).width() >= w && (r).height() >= h && !((r).left&(w-1)) && !((r).top&(h-1)) && !((r).right&(w-1)) && !((r).bottom&(h-1))); \
ASSERT((r).width() >= w && (r).height() >= h && !((r).left & (w - 1)) && !((r).top & (h - 1)) && !((r).right & (w - 1)) && !((r).bottom & (h - 1))); \
#define FOREACH_BLOCK_START(w, h, bpp, format) \
const GSLocalMemory::psm_t& psm = GSLocalMemory::m_psm[format]; \
uint32 bp = TEX0.TBP0; \
uint32 bw = TEX0.TBW; \
int offset = dstpitch * h - r.width() * bpp / 8; \
for(int y = r.top, ye = r.bottom; y < ye; y += h, dst += offset) \
{ ASSERT_BLOCK(r, w, h); \
uint32 base = psm.bn(0, y, bp, bw); \
for(int x = r.left, xe = r.right; x < xe; x += w, dst += w * bpp / 8) \
#define FOREACH_BLOCK_START(r, w, h, bpp, psm) \
ASSERT_BLOCK(r, w, h); \
const GSLocalMemory::BlockOffset* RESTRICT _bo = GetBlockOffset(TEX0.TBP0, TEX0.TBW, psm); \
GSVector4i _r = r >> 3; \
uint8* _dst = dst - _r.left * bpp; \
int _offset = dstpitch * h; \
for(int y = _r.top; y < _r.bottom; y += h >> 3, _dst += _offset) \
{ \
uint32 _base = _bo->row[y]; \
for(int x = _r.left; x < _r.right; x += w >> 3) \
{ \
const uint8* src = BlockPtr(base + psm.blockOffset[x >> 3]); \
const uint8* src = BlockPtr(_base + _bo->col[x]); \
uint8* dst = &_dst[x * bpp]; \
#define FOREACH_BLOCK_END }}
@ -463,37 +465,52 @@ GSLocalMemory::~GSLocalMemory()
{
VirtualFree(m_vm8, 0, MEM_RELEASE);
for(hash_map<uint32, Offset*>::iterator i = m_omap.begin(); i != m_omap.end(); i++)
{
Offset* o = i->second;
_aligned_free(o->col[0]);
_aligned_free(o);
}
for(hash_map<uint32, Offset4*>::iterator i = m_o4map.begin(); i != m_o4map.end(); i++)
{
_aligned_free(i->second);
}
for_each(m_bomap.begin(), m_bomap.end(), aligned_free_second());
for_each(m_pomap.begin(), m_pomap.end(), aligned_free_second());
for_each(m_po4map.begin(), m_po4map.end(), aligned_free_second());
}
GSLocalMemory::Offset* GSLocalMemory::GetOffset(uint32 bp, uint32 bw, uint32 psm)
GSLocalMemory::BlockOffset* GSLocalMemory::GetBlockOffset(uint32 bp, uint32 bw, uint32 psm)
{
if(bw == 0) {ASSERT(0); return NULL;}
ASSERT(m_psm[psm].bpp > 8); // only for 16/24/32/8h/4hh/4hl formats where all columns are the same
uint32 hash = bp | (bw << 14) | (psm << 20);
hash_map<uint32, Offset*>::iterator i = m_omap.find(hash);
hash_map<uint32, BlockOffset*>::iterator i = m_bomap.find(hash);
if(i != m_omap.end())
if(i != m_bomap.end())
{
return i->second;
}
Offset* o = (Offset*)_aligned_malloc(sizeof(Offset), 16);
BlockOffset* o = (BlockOffset*)_aligned_malloc(sizeof(BlockOffset), 16);
o->hash = hash;
pixelAddress bn = m_psm[psm].bn;
for(int i = 0; i < 256; i++)
{
o->row[i] = (int)bn(0, i << 3, bp, bw);
}
o->col = m_psm[psm].blockOffset;
m_bomap[hash] = o;
return o;
}
GSLocalMemory::PixelOffset* GSLocalMemory::GetPixelOffset(uint32 bp, uint32 bw, uint32 psm)
{
uint32 hash = bp | (bw << 14) | (psm << 20);
hash_map<uint32, PixelOffset*>::iterator i = m_pomap.find(hash);
if(i != m_pomap.end())
{
return i->second;
}
PixelOffset* o = (PixelOffset*)_aligned_malloc(sizeof(PixelOffset), 16);
o->hash = hash;
@ -501,24 +518,20 @@ GSLocalMemory::Offset* GSLocalMemory::GetOffset(uint32 bp, uint32 bw, uint32 psm
for(int i = 0; i < 2048; i++)
{
o->row[i] = GSVector4i((int)pa(0, i, bp, bw));
o->row[i] = (int)pa(0, i, bp, bw);
}
int* p = (int*)_aligned_malloc(sizeof(int) * (2048 + 3) * 4, 16);
for(int i = 0; i < 4; i++)
for(int i = 0; i < 8; i++)
{
o->col[i] = &p[2048 * i + ((4 - (i & 3)) & 3)];
memcpy(o->col[i], m_psm[psm].rowOffset[0], sizeof(int) * 2048);
o->col[i] = m_psm[psm].rowOffset[i];
}
m_omap[hash] = o;
m_pomap[hash] = o;
return o;
}
GSLocalMemory::Offset4* GSLocalMemory::GetOffset4(const GIFRegFRAME& FRAME, const GIFRegZBUF& ZBUF)
GSLocalMemory::PixelOffset4* GSLocalMemory::GetPixelOffset4(const GIFRegFRAME& FRAME, const GIFRegZBUF& ZBUF)
{
uint32 fbp = FRAME.Block();
uint32 zbp = ZBUF.Block();
@ -535,14 +548,14 @@ GSLocalMemory::Offset4* GSLocalMemory::GetOffset4(const GIFRegFRAME& FRAME, cons
uint32 hash = (FRAME.FBP << 0) | (ZBUF.ZBP << 9) | (bw << 18) | (fpsm_hash << 24) | (zpsm_hash << 28);
hash_map<uint32, Offset4*>::iterator i = m_o4map.find(hash);
hash_map<uint32, PixelOffset4*>::iterator i = m_po4map.find(hash);
if(i != m_o4map.end())
if(i != m_po4map.end())
{
return i->second;
}
Offset4* o = (Offset4*)_aligned_malloc(sizeof(Offset4), 16);
PixelOffset4* o = (PixelOffset4*)_aligned_malloc(sizeof(PixelOffset4), 16);
o->hash = hash;
@ -564,7 +577,7 @@ GSLocalMemory::Offset4* GSLocalMemory::GetOffset4(const GIFRegFRAME& FRAME, cons
o->col[i].y = m_psm[zpsm].rowOffset[0][i * 4] << zs;
}
m_o4map[hash] = o;
m_po4map[hash] = o;
return o;
}
@ -1436,20 +1449,20 @@ void GSLocalMemory::ReadImageX(int& tx, int& ty, uint8* dst, int len, GIFRegBITB
///////////////////
void GSLocalMemory::ReadTexture32(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
void GSLocalMemory::ReadTexture32(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
{
FOREACH_BLOCK_START(8, 8, 32, PSM_PSMCT32)
FOREACH_BLOCK_START(r, 8, 8, 32, PSM_PSMCT32)
{
ReadBlock32<true>(src, dst, dstpitch);
}
FOREACH_BLOCK_END
}
void GSLocalMemory::ReadTexture24(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
void GSLocalMemory::ReadTexture24(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
{
if(TEXA.AEM)
{
FOREACH_BLOCK_START(8, 8, 32, PSM_PSMCT24)
FOREACH_BLOCK_START(r, 8, 8, 32, PSM_PSMCT24)
{
ReadAndExpandBlock24<true>(src, dst, dstpitch, TEXA);
}
@ -1457,7 +1470,7 @@ void GSLocalMemory::ReadTexture24(const GSVector4i& r, uint8* dst, int dstpitch,
}
else
{
FOREACH_BLOCK_START(8, 8, 32, PSM_PSMCT24)
FOREACH_BLOCK_START(r, 8, 8, 32, PSM_PSMCT24)
{
ReadAndExpandBlock24<false>(src, dst, dstpitch, TEXA);
}
@ -1465,11 +1478,11 @@ void GSLocalMemory::ReadTexture24(const GSVector4i& r, uint8* dst, int dstpitch,
}
}
void GSLocalMemory::ReadTexture16(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
void GSLocalMemory::ReadTexture16(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
{
__declspec(align(16)) uint16 block[16 * 8];
FOREACH_BLOCK_START(16, 8, 32, PSM_PSMCT16)
FOREACH_BLOCK_START(r, 16, 8, 32, PSM_PSMCT16)
{
ReadBlock16<true>(src, (uint8*)block, sizeof(block) / 8);
@ -1478,11 +1491,11 @@ void GSLocalMemory::ReadTexture16(const GSVector4i& r, uint8* dst, int dstpitch,
FOREACH_BLOCK_END
}
void GSLocalMemory::ReadTexture16S(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
void GSLocalMemory::ReadTexture16S(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
{
__declspec(align(16)) uint16 block[16 * 8];
FOREACH_BLOCK_START(16, 8, 32, PSM_PSMCT16S)
FOREACH_BLOCK_START(r, 16, 8, 32, PSM_PSMCT16S)
{
ReadBlock16<true>(src, (uint8*)block, sizeof(block) / 8);
@ -1491,75 +1504,75 @@ void GSLocalMemory::ReadTexture16S(const GSVector4i& r, uint8* dst, int dstpitch
FOREACH_BLOCK_END
}
void GSLocalMemory::ReadTexture8(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
void GSLocalMemory::ReadTexture8(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
{
const uint32* pal = m_clut;
FOREACH_BLOCK_START(16, 16, 32, PSM_PSMT8)
FOREACH_BLOCK_START(r, 16, 16, 32, PSM_PSMT8)
{
ReadAndExpandBlock8_32(src, dst, dstpitch, pal);
}
FOREACH_BLOCK_END
}
void GSLocalMemory::ReadTexture4(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
void GSLocalMemory::ReadTexture4(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
{
const uint64* pal = m_clut;
FOREACH_BLOCK_START(32, 16, 32, PSM_PSMT4)
FOREACH_BLOCK_START(r, 32, 16, 32, PSM_PSMT4)
{
ReadAndExpandBlock4_32(src, dst, dstpitch, pal);
}
FOREACH_BLOCK_END
}
void GSLocalMemory::ReadTexture8H(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
void GSLocalMemory::ReadTexture8H(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
{
const uint32* pal = m_clut;
FOREACH_BLOCK_START(8, 8, 32, PSM_PSMT8H)
FOREACH_BLOCK_START(r, 8, 8, 32, PSM_PSMT8H)
{
ReadAndExpandBlock8H_32(src, dst, dstpitch, pal);
}
FOREACH_BLOCK_END
}
void GSLocalMemory::ReadTexture4HL(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
void GSLocalMemory::ReadTexture4HL(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
{
const uint32* pal = m_clut;
FOREACH_BLOCK_START(8, 8, 32, PSM_PSMT4HL)
FOREACH_BLOCK_START(r, 8, 8, 32, PSM_PSMT4HL)
{
ReadAndExpandBlock4HL_32(src, dst, dstpitch, pal);
}
FOREACH_BLOCK_END
}
void GSLocalMemory::ReadTexture4HH(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
void GSLocalMemory::ReadTexture4HH(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
{
const uint32* pal = m_clut;
FOREACH_BLOCK_START(8, 8, 32, PSM_PSMT4HH)
FOREACH_BLOCK_START(r, 8, 8, 32, PSM_PSMT4HH)
{
ReadAndExpandBlock4HH_32(src, dst, dstpitch, pal);
}
FOREACH_BLOCK_END
}
void GSLocalMemory::ReadTexture32Z(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
void GSLocalMemory::ReadTexture32Z(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
{
FOREACH_BLOCK_START(8, 8, 32, PSM_PSMZ32)
FOREACH_BLOCK_START(r, 8, 8, 32, PSM_PSMZ32)
{
ReadBlock32<true>(src, dst, dstpitch);
}
FOREACH_BLOCK_END
}
void GSLocalMemory::ReadTexture24Z(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
void GSLocalMemory::ReadTexture24Z(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
{
if(TEXA.AEM)
{
FOREACH_BLOCK_START(8, 8, 32, PSM_PSMZ24)
FOREACH_BLOCK_START(r, 8, 8, 32, PSM_PSMZ24)
{
ReadAndExpandBlock24<true>(src, dst, dstpitch, TEXA);
}
@ -1567,7 +1580,7 @@ void GSLocalMemory::ReadTexture24Z(const GSVector4i& r, uint8* dst, int dstpitch
}
else
{
FOREACH_BLOCK_START(8, 8, 32, PSM_PSMZ24)
FOREACH_BLOCK_START(r, 8, 8, 32, PSM_PSMZ24)
{
ReadAndExpandBlock24<false>(src, dst, dstpitch, TEXA);
}
@ -1575,11 +1588,11 @@ void GSLocalMemory::ReadTexture24Z(const GSVector4i& r, uint8* dst, int dstpitch
}
}
void GSLocalMemory::ReadTexture16Z(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
void GSLocalMemory::ReadTexture16Z(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
{
__declspec(align(16)) uint16 block[16 * 8];
FOREACH_BLOCK_START(16, 8, 32, PSM_PSMZ16)
FOREACH_BLOCK_START(r, 16, 8, 32, PSM_PSMZ16)
{
ReadBlock16<true>(src, (uint8*)block, sizeof(block) / 8);
@ -1588,11 +1601,11 @@ void GSLocalMemory::ReadTexture16Z(const GSVector4i& r, uint8* dst, int dstpitch
FOREACH_BLOCK_END
}
void GSLocalMemory::ReadTexture16SZ(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
void GSLocalMemory::ReadTexture16SZ(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
{
__declspec(align(16)) uint16 block[16 * 8];
FOREACH_BLOCK_START(16, 8, 32, PSM_PSMZ16S)
FOREACH_BLOCK_START(r, 16, 8, 32, PSM_PSMZ16S)
{
ReadBlock16<true>(src, (uint8*)block, sizeof(block) / 8);
@ -1737,31 +1750,31 @@ void GSLocalMemory::ReadTexture(const GSVector4i& r, uint8* dst, int dstpitch, c
}
///////////////////
void GSLocalMemory::ReadTexture16NP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
void GSLocalMemory::ReadTexture16NP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
{
FOREACH_BLOCK_START(16, 8, 16, PSM_PSMCT16)
FOREACH_BLOCK_START(r, 16, 8, 16, PSM_PSMCT16)
{
ReadBlock16<true>(src, dst, dstpitch);
}
FOREACH_BLOCK_END
}
void GSLocalMemory::ReadTexture16SNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
void GSLocalMemory::ReadTexture16SNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
{
FOREACH_BLOCK_START(16, 8, 16, PSM_PSMCT16S)
FOREACH_BLOCK_START(r, 16, 8, 16, PSM_PSMCT16S)
{
ReadBlock16<true>(src, dst, dstpitch);
}
FOREACH_BLOCK_END
}
void GSLocalMemory::ReadTexture8NP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
void GSLocalMemory::ReadTexture8NP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
{
const uint32* pal = m_clut;
if(TEX0.CPSM == PSM_PSMCT32 || TEX0.CPSM == PSM_PSMCT24)
{
FOREACH_BLOCK_START(16, 16, 32, PSM_PSMT8)
FOREACH_BLOCK_START(r, 16, 16, 32, PSM_PSMT8)
{
ReadAndExpandBlock8_32(src, dst, dstpitch, pal);
}
@ -1773,7 +1786,7 @@ void GSLocalMemory::ReadTexture8NP(const GSVector4i& r, uint8* dst, int dstpitch
__declspec(align(16)) uint8 block[16 * 16];
FOREACH_BLOCK_START(16, 16, 16, PSM_PSMT8)
FOREACH_BLOCK_START(r, 16, 16, 16, PSM_PSMT8)
{
ReadBlock8<true>(src, (uint8*)block, sizeof(block) / 16);
@ -1783,13 +1796,13 @@ void GSLocalMemory::ReadTexture8NP(const GSVector4i& r, uint8* dst, int dstpitch
}
}
void GSLocalMemory::ReadTexture4NP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
void GSLocalMemory::ReadTexture4NP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
{
const uint64* pal = m_clut;
if(TEX0.CPSM == PSM_PSMCT32 || TEX0.CPSM == PSM_PSMCT24)
{
FOREACH_BLOCK_START(32, 16, 32, PSM_PSMT4)
FOREACH_BLOCK_START(r, 32, 16, 32, PSM_PSMT4)
{
ReadAndExpandBlock4_32(src, dst, dstpitch, pal);
}
@ -1801,7 +1814,7 @@ void GSLocalMemory::ReadTexture4NP(const GSVector4i& r, uint8* dst, int dstpitch
__declspec(align(16)) uint8 block[(32 / 2) * 16];
FOREACH_BLOCK_START(32, 16, 16, PSM_PSMT4)
FOREACH_BLOCK_START(r, 32, 16, 16, PSM_PSMT4)
{
ReadBlock4<true>(src, (uint8*)block, sizeof(block) / 16);
@ -1811,13 +1824,13 @@ void GSLocalMemory::ReadTexture4NP(const GSVector4i& r, uint8* dst, int dstpitch
}
}
void GSLocalMemory::ReadTexture8HNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
void GSLocalMemory::ReadTexture8HNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
{
const uint32* pal = m_clut;
if(TEX0.CPSM == PSM_PSMCT32 || TEX0.CPSM == PSM_PSMCT24)
{
FOREACH_BLOCK_START(8, 8, 32, PSM_PSMT8H)
FOREACH_BLOCK_START(r, 8, 8, 32, PSM_PSMT8H)
{
ReadAndExpandBlock8H_32(src, dst, dstpitch, pal);
}
@ -1829,7 +1842,7 @@ void GSLocalMemory::ReadTexture8HNP(const GSVector4i& r, uint8* dst, int dstpitc
__declspec(align(16)) uint32 block[8 * 8];
FOREACH_BLOCK_START(8, 8, 16, PSM_PSMT8H)
FOREACH_BLOCK_START(r, 8, 8, 16, PSM_PSMT8H)
{
ReadBlock32<true>(src, (uint8*)block, sizeof(block) / 8);
@ -1839,13 +1852,13 @@ void GSLocalMemory::ReadTexture8HNP(const GSVector4i& r, uint8* dst, int dstpitc
}
}
void GSLocalMemory::ReadTexture4HLNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
void GSLocalMemory::ReadTexture4HLNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
{
const uint32* pal = m_clut;
if(TEX0.CPSM == PSM_PSMCT32 || TEX0.CPSM == PSM_PSMCT24)
{
FOREACH_BLOCK_START(8, 8, 32, PSM_PSMT4HL)
FOREACH_BLOCK_START(r, 8, 8, 32, PSM_PSMT4HL)
{
ReadAndExpandBlock4HL_32(src, dst, dstpitch, pal);
}
@ -1857,7 +1870,7 @@ void GSLocalMemory::ReadTexture4HLNP(const GSVector4i& r, uint8* dst, int dstpit
__declspec(align(16)) uint32 block[8 * 8];
FOREACH_BLOCK_START(8, 8, 16, PSM_PSMT4HL)
FOREACH_BLOCK_START(r, 8, 8, 16, PSM_PSMT4HL)
{
ReadBlock32<true>(src, (uint8*)block, sizeof(block) / 8);
@ -1867,13 +1880,13 @@ void GSLocalMemory::ReadTexture4HLNP(const GSVector4i& r, uint8* dst, int dstpit
}
}
void GSLocalMemory::ReadTexture4HHNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
void GSLocalMemory::ReadTexture4HHNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
{
const uint32* pal = m_clut;
if(TEX0.CPSM == PSM_PSMCT32 || TEX0.CPSM == PSM_PSMCT24)
{
FOREACH_BLOCK_START(8, 8, 32, PSM_PSMT4HH)
FOREACH_BLOCK_START(r, 8, 8, 32, PSM_PSMT4HH)
{
ReadAndExpandBlock4HH_32(src, dst, dstpitch, pal);
}
@ -1885,7 +1898,7 @@ void GSLocalMemory::ReadTexture4HHNP(const GSVector4i& r, uint8* dst, int dstpit
__declspec(align(16)) uint32 block[8 * 8];
FOREACH_BLOCK_START(8, 8, 16, PSM_PSMT4HH)
FOREACH_BLOCK_START(r, 8, 8, 16, PSM_PSMT4HH)
{
ReadBlock32<true>(src, (uint8*)block, sizeof(block) / 8);
@ -1895,18 +1908,18 @@ void GSLocalMemory::ReadTexture4HHNP(const GSVector4i& r, uint8* dst, int dstpit
}
}
void GSLocalMemory::ReadTexture16ZNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
void GSLocalMemory::ReadTexture16ZNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
{
FOREACH_BLOCK_START(16, 8, 16, PSM_PSMZ16)
FOREACH_BLOCK_START(r, 16, 8, 16, PSM_PSMZ16)
{
ReadBlock16<true>(src, dst, dstpitch);
}
FOREACH_BLOCK_END
}
void GSLocalMemory::ReadTexture16SZNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
void GSLocalMemory::ReadTexture16SZNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
{
FOREACH_BLOCK_START(16, 8, 16, PSM_PSMZ16S)
FOREACH_BLOCK_START(r, 16, 8, 16, PSM_PSMZ16S)
{
ReadBlock16<true>(src, dst, dstpitch);
}
@ -1959,45 +1972,45 @@ void GSLocalMemory::ReadTextureNP(const GSVector4i& r, uint8* dst, int dstpitch,
// 32/8
void GSLocalMemory::ReadTexture8P(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
void GSLocalMemory::ReadTexture8P(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
{
FOREACH_BLOCK_START(16, 16, 8, PSM_PSMT8)
FOREACH_BLOCK_START(r, 16, 16, 8, PSM_PSMT8)
{
ReadBlock8<true>(src, dst, dstpitch);
}
FOREACH_BLOCK_END
}
void GSLocalMemory::ReadTexture4P(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
void GSLocalMemory::ReadTexture4P(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
{
FOREACH_BLOCK_START(32, 16, 8, PSM_PSMT4)
FOREACH_BLOCK_START(r, 32, 16, 8, PSM_PSMT4)
{
ReadBlock4P(src, dst, dstpitch);
}
FOREACH_BLOCK_END
}
void GSLocalMemory::ReadTexture8HP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
void GSLocalMemory::ReadTexture8HP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
{
FOREACH_BLOCK_START(8, 8, 8, PSM_PSMT8H)
FOREACH_BLOCK_START(r, 8, 8, 8, PSM_PSMT8H)
{
ReadBlock8HP(src, dst, dstpitch);
}
FOREACH_BLOCK_END
}
void GSLocalMemory::ReadTexture4HLP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
void GSLocalMemory::ReadTexture4HLP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
{
FOREACH_BLOCK_START(8, 8, 8, PSM_PSMT4HL)
FOREACH_BLOCK_START(r, 8, 8, 8, PSM_PSMT4HL)
{
ReadBlock4HLP(src, dst, dstpitch);
}
FOREACH_BLOCK_END
}
void GSLocalMemory::ReadTexture4HHP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const
void GSLocalMemory::ReadTexture4HHP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
{
FOREACH_BLOCK_START(8, 8, 8, PSM_PSMT4HH)
FOREACH_BLOCK_START(r, 8, 8, 8, PSM_PSMT4HH)
{
ReadBlock4HHP(src, dst, dstpitch);
}

View File

@ -43,7 +43,7 @@ public:
typedef uint32 (GSLocalMemory::*readTexelAddr)(uint32 addr, const GIFRegTEXA& TEXA) const;
typedef void (GSLocalMemory::*writeImage)(int& tx, int& ty, uint8* src, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG);
typedef void (GSLocalMemory::*readImage)(int& tx, int& ty, uint8* dst, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG) const;
typedef void (GSLocalMemory::*readTexture)(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const;
typedef void (GSLocalMemory::*readTexture)(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
typedef void (GSLocalMemory::*readTextureBlock)(uint32 bp, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA) const;
typedef union
@ -81,14 +81,21 @@ public:
GSClut m_clut;
struct Offset
struct BlockOffset
{
GSVector4i row[2048]; // 0 | 0 | 0 | 0
int* col[4]; // x | x+1 | x+2 | x+3
int row[256]; // yn (n = 0 8 16 ...)
int* col; // blockOffset*
uint32 hash;
};
struct Offset4
struct PixelOffset
{
int row[2048]; // yn (n = 0 1 2 ...)
int* col[8]; // rowOffset*
uint32 hash;
};
struct PixelOffset4
{
// 16 bit offsets (m_vm16[...])
@ -141,15 +148,17 @@ protected:
//
hash_map<uint32, Offset*> m_omap;
hash_map<uint32, Offset4*> m_o4map;
hash_map<uint32, BlockOffset*> m_bomap;
hash_map<uint32, PixelOffset*> m_pomap;
hash_map<uint32, PixelOffset4*> m_po4map;
public:
GSLocalMemory();
virtual ~GSLocalMemory();
Offset* GetOffset(uint32 bp, uint32 bw, uint32 psm);
Offset4* GetOffset4(const GIFRegFRAME& FRAME, const GIFRegZBUF& ZBUF);
BlockOffset* GetBlockOffset(uint32 bp, uint32 bw, uint32 psm);
PixelOffset* GetPixelOffset(uint32 bp, uint32 bw, uint32 psm);
PixelOffset4* GetPixelOffset4(const GIFRegFRAME& FRAME, const GIFRegZBUF& ZBUF);
// address
@ -626,6 +635,77 @@ public:
WriteFrame16(PixelAddress16SZ(x, y, bp, bw), c);
}
__forceinline void WritePixel32(uint8* RESTRICT src, uint32 pitch, PixelOffset* po, const GSVector4i& r)
{
src -= r.left * sizeof(uint32);
for(int y = r.top; y < r.bottom; y++, src += pitch)
{
uint32* RESTRICT s = (uint32*)src;
uint32* RESTRICT d = &m_vm32[po->row[y]];
int* RESTRICT o = po->col[0];
for(int x = r.left; x < r.right; x++)
{
d[o[x]] = s[x];
}
}
}
__forceinline void WritePixel24(uint8* RESTRICT src, uint32 pitch, PixelOffset* po, const GSVector4i& r)
{
src -= r.left * sizeof(uint32);
for(int y = r.top; y < r.bottom; y++, src += pitch)
{
uint32* RESTRICT s = (uint32*)src;
uint32* RESTRICT d = &m_vm32[po->row[y]];
int* RESTRICT o = po->col[0];
for(int x = r.left; x < r.right; x++)
{
d[o[x]] = (d[o[x]] & 0xff000000) | (s[x] & 0x00ffffff);
}
}
}
__forceinline void WritePixel16(uint8* RESTRICT src, uint32 pitch, PixelOffset* po, const GSVector4i& r)
{
src -= r.left * sizeof(uint16);
for(int y = r.top; y < r.bottom; y++, src += pitch)
{
uint16* RESTRICT s = (uint16*)src;
uint16* RESTRICT d = &m_vm16[po->row[y]];
int* RESTRICT o = po->col[0];
for(int x = r.left; x < r.right; x++)
{
d[o[x]] = s[x];
}
}
}
__forceinline void WriteFrame16(uint8* RESTRICT src, uint32 pitch, PixelOffset* po, const GSVector4i& r)
{
src -= r.left * sizeof(uint32);
for(int y = r.top; y < r.bottom; y++, src += pitch)
{
uint32* RESTRICT s = (uint32*)src;
uint16* RESTRICT d = &m_vm16[po->row[y]];
int* RESTRICT o = po->col[0];
for(int x = r.left; x < r.right; x++)
{
uint32 rb = s[x] & 0x00f800f8;
uint32 ga = s[x] & 0x8000f800;
d[o[x]] = (ga >> 16) | (rb >> 9) | (ga >> 6) | (rb >> 3);
}
}
}
__forceinline uint32 ReadTexel32(uint32 addr, const GIFRegTEXA& TEXA) const
{
return m_vm32[addr];
@ -781,19 +861,19 @@ public:
// * => 32
void ReadTexture32(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const;
void ReadTexture24(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const;
void ReadTexture16(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const;
void ReadTexture16S(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const;
void ReadTexture8(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const;
void ReadTexture4(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const;
void ReadTexture8H(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const;
void ReadTexture4HL(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const;
void ReadTexture4HH(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const;
void ReadTexture32Z(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const;
void ReadTexture24Z(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const;
void ReadTexture16Z(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const;
void ReadTexture16SZ(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const;
void ReadTexture32(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
void ReadTexture24(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
void ReadTexture16(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
void ReadTexture16S(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
void ReadTexture8(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
void ReadTexture4(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
void ReadTexture8H(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
void ReadTexture4HL(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
void ReadTexture4HH(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
void ReadTexture32Z(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
void ReadTexture24Z(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
void ReadTexture16Z(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
void ReadTexture16SZ(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
void ReadTexture(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
@ -813,25 +893,25 @@ public:
// * => 32/16
void ReadTexture16NP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const;
void ReadTexture16SNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const;
void ReadTexture8NP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const;
void ReadTexture4NP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const;
void ReadTexture8HNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const;
void ReadTexture4HLNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const;
void ReadTexture4HHNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const;
void ReadTexture16ZNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const;
void ReadTexture16SZNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const;
void ReadTexture16NP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
void ReadTexture16SNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
void ReadTexture8NP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
void ReadTexture4NP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
void ReadTexture8HNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
void ReadTexture4HLNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
void ReadTexture4HHNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
void ReadTexture16ZNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
void ReadTexture16SZNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
void ReadTextureNP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
// pal ? 8 : 32
void ReadTexture8P(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const;
void ReadTexture4P(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const;
void ReadTexture8HP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const;
void ReadTexture4HLP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const;
void ReadTexture4HHP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA) const;
void ReadTexture8P(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
void ReadTexture4P(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
void ReadTexture8HP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
void ReadTexture4HLP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
void ReadTexture4HHP(const GSVector4i& r, uint8* dst, int dstpitch, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA);
void ReadTextureBlock8P(uint32 bp, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA) const;
void ReadTextureBlock4P(uint32 bp, uint8* dst, int dstpitch, const GIFRegTEXA& TEXA) const;

View File

@ -290,8 +290,8 @@ void GSRasterizer::DrawTriangleTop(GSVertexSW* v, const GSVector4i& scissor)
GSVector4 tb = l.p.upl(v[2].p).ceil();
GSVector4 tbmax = tb.maxv(fscissor.yyyy());
GSVector4 tbmin = tb.minv(fscissor.wwww());
GSVector4 tbmax = tb.max(fscissor.yyyy());
GSVector4 tbmin = tb.min(fscissor.wwww());
GSVector4i tbi = GSVector4i(tbmax.zzww(tbmin));
@ -342,8 +342,8 @@ void GSRasterizer::DrawTriangleBottom(GSVertexSW* v, const GSVector4i& scissor)
GSVector4 tb = l.p.upl(v[2].p).ceil();
GSVector4 tbmax = tb.maxv(fscissor.yyyy());
GSVector4 tbmin = tb.minv(fscissor.wwww());
GSVector4 tbmax = tb.max(fscissor.yyyy());
GSVector4 tbmin = tb.min(fscissor.wwww());
GSVector4i tbi = GSVector4i(tbmax.zzww(tbmin));
@ -398,8 +398,8 @@ void GSRasterizer::DrawTriangleTopBottom(GSVertexSW* v, const GSVector4i& scisso
GSVector4 tb = v[0].p.upl(v[1].p).zwzw(v[1].p.upl(v[2].p)).ceil();
GSVector4 tbmax = tb.maxv(fscissor.yyyy());
GSVector4 tbmin = tb.minv(fscissor.wwww());
GSVector4 tbmax = tb.max(fscissor.yyyy());
GSVector4 tbmin = tb.min(fscissor.wwww());
GSVector4i tbi = GSVector4i(tbmax.xzyw(tbmin));
@ -462,8 +462,8 @@ void GSRasterizer::DrawTriangleSection(int top, int bottom, GSVertexSW& l, const
{
GSVector4 lr = l.p.xyxy(r).ceil();
GSVector4 lrmax = lr.maxv(fscissor.xxxx());
GSVector4 lrmin = lr.minv(fscissor.zzzz());
GSVector4 lrmax = lr.max(fscissor.xxxx());
GSVector4 lrmin = lr.min(fscissor.zzzz());
GSVector4i lri = GSVector4i(lrmax.xxzz(lrmin));
@ -503,8 +503,8 @@ void GSRasterizer::DrawTriangleSection(int top, int bottom, GSVertexSW& l, const
{
GSVector4 lr = l.p.ceil();
GSVector4 lrmax = lr.maxv(fscissor.xxxx());
GSVector4 lrmin = lr.minv(fscissor.zzzz());
GSVector4 lrmax = lr.max(fscissor.xxxx());
GSVector4 lrmin = lr.min(fscissor.zzzz());
GSVector4i lri = GSVector4i(lrmax.xxyy(lrmin));
@ -613,8 +613,8 @@ void GSRasterizer::DrawEdge(const GSVertexSW& v0, const GSVertexSW& v1, const GS
if(orientation)
{
GSVector4 tbmax = lrtb.maxv(fscissor.yyyy());
GSVector4 tbmin = lrtb.minv(fscissor.wwww());
GSVector4 tbmax = lrtb.max(fscissor.yyyy());
GSVector4 tbmin = lrtb.min(fscissor.wwww());
GSVector4i tbi = GSVector4i(tbmax.zwzw(tbmin));
@ -711,8 +711,8 @@ void GSRasterizer::DrawEdge(const GSVertexSW& v0, const GSVertexSW& v1, const GS
}
else
{
GSVector4 lrmax = lrtb.maxv(fscissor.xxxx());
GSVector4 lrmin = lrtb.minv(fscissor.zzzz());
GSVector4 lrmax = lrtb.max(fscissor.xxxx());
GSVector4 lrmin = lrtb.min(fscissor.zzzz());
GSVector4i lri = GSVector4i(lrmax.xyxy(lrmin));
@ -883,10 +883,7 @@ GSRasterizerList::~GSRasterizerList()
void GSRasterizerList::FreeRasterizers()
{
for(list<IRasterizer*>::iterator i = begin(); i != end(); i++)
{
delete *i;
}
for_each(begin(), end(), delete_object());
clear();
}

View File

@ -25,6 +25,7 @@
#include "GSVertexSW.h"
#include "GSFunctionMap.h"
#include "GSThread.h"
#include "GSAlignedClass.h"
__declspec(align(16)) class GSRasterizerData
{
@ -46,7 +47,7 @@ public:
virtual void PrintStats() = 0;
};
class IDrawScanline
class IDrawScanline : public GSAlignedClass<16>
{
public:
typedef void (__fastcall *DrawScanlineStaticPtr)(int right, int left, int top, const GSVertexSW& v);

View File

@ -41,10 +41,16 @@ GSRenderer::GSRenderer(uint8* base, bool mt, void (*irq)(), GSDevice* dev)
s_dump = !!theApp.GetConfig("dump", 0);
s_save = !!theApp.GetConfig("save", 0);
s_savez = !!theApp.GetConfig("savez", 0);
s_saven = theApp.GetConfig("saven", 0);
}
GSRenderer::~GSRenderer()
{
if(m_dev)
{
m_dev->Reset(1, 1, GSDevice::Windowed);
}
delete m_dev;
}
@ -259,9 +265,17 @@ void GSRenderer::VSync(int field)
Flush();
field = field ? 1 : 0;
if(!Merge(field)) return;
if(!m_dev->IsLost(true))
{
if(!Merge(field ? 1 : 0))
{
return;
}
}
else
{
ResetDevice();
}
// osd
@ -311,11 +325,6 @@ void GSRenderer::VSync(int field)
// present
if(m_dev->IsLost())
{
ResetDevice();
}
m_dev->Present(m_wnd.GetClientRect().fit(m_aspectratio), m_shader);
// snapshot
@ -365,7 +374,7 @@ void GSRenderer::VSync(int field)
if(offscreen->Map(m))
{
m_capture.DeliverFrame(m.bits, m.pitch, m_dev->IsCurrentRGBA());
m_capture.DeliverFrame(m.bits, m.pitch, m_dev->IsRBSwapped());
offscreen->Unmap();
}

View File

@ -67,6 +67,7 @@ public:
bool s_dump;
bool s_save;
bool s_savez;
int s_saven;
public:
GSRenderer(uint8* base, bool mt, void (*irq)(), GSDevice* dev);
@ -127,7 +128,10 @@ protected:
{
// FIXME: berserk fpsm = 27 (8H)
Draw();
if(!m_dev->IsLost())
{
Draw();
}
m_perfmon.Put(GSPerfMon::Draw, 1);
}

View File

@ -91,10 +91,30 @@ public:
GSTextureFX::OMBlendSelector om_bsel;
om_bsel.abe = !IsOpaque();
om_bsel.a = context->ALPHA.A;
om_bsel.b = context->ALPHA.B;
om_bsel.c = context->ALPHA.C;
om_bsel.d = context->ALPHA.D;
if(om_bsel.abe)
{
om_bsel.a = context->ALPHA.A;
om_bsel.b = context->ALPHA.B;
om_bsel.c = context->ALPHA.C;
om_bsel.d = context->ALPHA.D;
if(env.PABE.PABE)
{
if(om_bsel.a == 0 && om_bsel.b == 1 && om_bsel.c == 0 && om_bsel.d == 1)
{
// this works because with PABE alpha blending is on when alpha >= 0x80, but since the pixel shader
// cannot output anything over 0x80 (== 1.0) blending with 0x80 or turning it off gives the same result
om_bsel.abe = 0;
}
else
{
ASSERT(0);
}
}
}
om_bsel.wr = (context->FRAME.FBMSK & 0x000000ff) != 0x000000ff;
om_bsel.wg = (context->FRAME.FBMSK & 0x0000ff00) != 0x0000ff00;
om_bsel.wb = (context->FRAME.FBMSK & 0x00ff0000) != 0x00ff0000;
@ -173,7 +193,6 @@ public:
ps_sel.fst = PRIM->FST;
ps_sel.wms = context->CLAMP.WMS;
ps_sel.wmt = context->CLAMP.WMT;
ps_sel.bpp = 0;
ps_sel.aem = env.TEXA.AEM;
ps_sel.tfx = context->TEX0.TFX;
ps_sel.tcc = context->TEX0.TCC;
@ -193,24 +212,30 @@ public:
GSTextureFX::PSConstantBuffer ps_cb;
ps_cb.FogColor_AREF = GSVector4((int)env.FOGCOL.FCR, (int)env.FOGCOL.FCG, (int)env.FOGCOL.FCB, 0) / 255;
switch(ps_sel.atst)
if(ps_sel.fog)
{
case ATST_LESS:
ps_cb.FogColor_AREF.a = (float)((int)context->TEST.AREF - 1);
break;
case ATST_GREATER:
ps_cb.FogColor_AREF.a = (float)((int)context->TEST.AREF + 1);
break;
default:
ps_cb.FogColor_AREF.a = (float)(int)context->TEST.AREF;
break;
ps_cb.FogColor_AREF = GSVector4((int)env.FOGCOL.FCR, (int)env.FOGCOL.FCG, (int)env.FOGCOL.FCB, 0) / 255;
}
if(ps_sel.ate)
{
switch(ps_sel.atst)
{
case ATST_LESS:
ps_cb.FogColor_AREF.a = (float)((int)context->TEST.AREF - 1);
break;
case ATST_GREATER:
ps_cb.FogColor_AREF.a = (float)((int)context->TEST.AREF + 1);
break;
default:
ps_cb.FogColor_AREF.a = (float)(int)context->TEST.AREF;
break;
}
}
if(tex)
{
ps_sel.bpp = tex->m_bpp;
ps_sel.fmt = tex->m_fmt;
ps_sel.rt = tex->m_target;
int w = tex->m_texture->GetWidth();
@ -223,19 +248,19 @@ public:
switch(context->CLAMP.WMS)
{
case 0:
case CLAMP_REPEAT:
ps_ssel.tau = 1;
break;
case 1:
case CLAMP_CLAMP:
ps_ssel.tau = 0;
break;
case 2:
case CLAMP_REGION_CLAMP:
ps_cb.MinMax.x = ((float)(int)context->CLAMP.MINU) / (1 << context->TEX0.TW);
ps_cb.MinMax.z = ((float)(int)context->CLAMP.MAXU) / (1 << context->TEX0.TW);
ps_cb.MinF_TA.x = ((float)(int)context->CLAMP.MINU + 0.5f) / (1 << context->TEX0.TW);
ps_ssel.tau = 0;
break;
case 3:
case CLAMP_REGION_REPEAT:
ps_cb.MskFix.x = context->CLAMP.MINU;
ps_cb.MskFix.z = context->CLAMP.MAXU;
ps_ssel.tau = 1;
@ -246,19 +271,19 @@ public:
switch(context->CLAMP.WMT)
{
case 0:
case CLAMP_REPEAT:
ps_ssel.tav = 1;
break;
case 1:
case CLAMP_CLAMP:
ps_ssel.tav = 0;
break;
case 2:
case CLAMP_REGION_CLAMP:
ps_cb.MinMax.y = ((float)(int)context->CLAMP.MINV) / (1 << context->TEX0.TH);
ps_cb.MinMax.w = ((float)(int)context->CLAMP.MAXV) / (1 << context->TEX0.TH);
ps_cb.MinF_TA.y = ((float)(int)context->CLAMP.MINV + 0.5f) / (1 << context->TEX0.TH);
ps_ssel.tav = 0;
break;
case 3:
case CLAMP_REGION_REPEAT:
ps_cb.MskFix.y = context->CLAMP.MINV;
ps_cb.MskFix.w = context->CLAMP.MAXV;
ps_ssel.tav = 1;

View File

@ -122,14 +122,14 @@ void GSRendererDX9::VertexKick(bool skip)
case GS_LINELIST:
case GS_LINESTRIP:
case GS_SPRITE:
pmin = v[0].p.minv(v[1].p);
pmax = v[0].p.maxv(v[1].p);
pmin = v[0].p.min(v[1].p);
pmax = v[0].p.max(v[1].p);
break;
case GS_TRIANGLELIST:
case GS_TRIANGLESTRIP:
case GS_TRIANGLEFAN:
pmin = v[0].p.minv(v[1].p).minv(v[2].p);
pmax = v[0].p.maxv(v[1].p).maxv(v[2].p);
pmin = v[0].p.min(v[1].p).min(v[2].p);
pmax = v[0].p.max(v[1].p).max(v[2].p);
break;
}

View File

@ -87,7 +87,7 @@ protected:
if(s_dump)
{
if(s_save)
if(s_save && s_n >= s_saven)
{
t->Save(format("c:\\temp2\\_%05d_f%I64d_fr%d_%05x_%d.bmp", s_n, m_perfmon.GetFrame(), i, (int)TEX0.TBP0, (int)TEX0.PSM));
}
@ -157,7 +157,7 @@ protected:
string s;
if(s_save && tex)
if(s_save && s_n >= s_saven && tex)
{
s = format("c:\\temp2\\_%05d_f%I64d_tex_%05x_%d_%d%d_%02x_%02x_%02x_%02x.dds",
s_n, frame, (int)context->TEX0.TBP0, (int)context->TEX0.PSM,
@ -177,14 +177,14 @@ protected:
s_n++;
if(s_save)
if(s_save && s_n >= s_saven)
{
s = format("c:\\temp2\\_%05d_f%I64d_rt0_%05x_%d.bmp", s_n, frame, context->FRAME.Block(), context->FRAME.PSM);
rt->m_texture->Save(s);
}
if(s_savez)
if(s_savez && s_n >= s_saven)
{
s = format("c:\\temp2\\_%05d_f%I64d_rz0_%05x_%d.bmp", s_n, frame, context->ZBUF.Block(), context->ZBUF.PSM);
@ -265,14 +265,14 @@ protected:
string s;
if(s_save)
if(s_save && s_n >= s_saven)
{
s = format("c:\\temp2\\_%05d_f%I64d_rt1_%05x_%d.bmp", s_n, frame, context->FRAME.Block(), context->FRAME.PSM);
rt->m_texture->Save(s);
}
if(s_savez)
if(s_savez && s_n >= s_saven)
{
s = format("c:\\temp2\\_%05d_f%I64d_rz1_%05x_%d.bmp", s_n, frame, context->ZBUF.Block(), context->ZBUF.PSM);

View File

@ -39,6 +39,11 @@ GSRendererSW::GSRendererSW(uint8* base, bool mt, void (*irq)(), GSDevice* dev)
GSRendererSW::~GSRendererSW()
{
delete m_tc;
for(int i = 0; i < countof(m_texture); i++)
{
delete m_texture[i];
}
}
void GSRendererSW::Reset()
@ -87,51 +92,34 @@ GSTexture* GSRendererSW::GetOutput(int i)
TEX0.TBW = DISPFB.FBW;
TEX0.PSM = DISPFB.PSM;
GSVector4i r(0, 0, TEX0.TBW * 64, GetFrameRect(i).bottom);
int w = TEX0.TBW * 64;
int h = GetFrameRect(i).bottom;
// TODO: round up bottom
int w = r.width();
int h = r.height();
if(m_texture[i])
if(m_dev->ResizeTexture(&m_texture[i], w, h))
{
if(m_texture[i]->GetWidth() != w || m_texture[i]->GetHeight() != h)
// TODO
static uint8* buff = (uint8*)_aligned_malloc(1024 * 1024 * 4, 16);
static int pitch = 1024 * 4;
GSVector4i r(0, 0, w, h);
m_mem.ReadTexture(r, buff, pitch, TEX0, m_env.TEXA);
m_texture[i]->Update(r, buff, pitch);
if(s_dump)
{
delete m_texture[i];
if(s_save && s_n >= s_saven)
{
m_texture[i]->Save(format("c:\\temp1\\_%05d_f%I64d_fr%d_%05x_%d.bmp", s_n, m_perfmon.GetFrame(), i, (int)TEX0.TBP0, (int)TEX0.PSM));
}
m_texture[i] = NULL;
s_n++;
}
}
if(!m_texture[i])
{
m_texture[i] = m_dev->CreateTexture(w, h);
if(!m_texture[i])
{
return NULL;
}
}
// TODO
static uint8* buff = (uint8*)_aligned_malloc(1024 * 1024 * 4, 16);
static int pitch = 1024 * 4;
m_mem.ReadTexture(r, buff, pitch, TEX0, m_env.TEXA);
m_texture[i]->Update(r, buff, pitch);
if(s_dump)
{
if(s_save)
{
m_texture[i]->Save(format("c:\\temp1\\_%05d_f%I64d_fr%d_%05x_%d.bmp", s_n, m_perfmon.GetFrame(), i, (int)TEX0.TBP0, (int)TEX0.PSM));
}
s_n++;
}
return m_texture[i];
}
@ -161,7 +149,7 @@ void GSRendererSW::Draw()
string s;
if(s_save && PRIM->TME)
if(s_save && s_n >= s_saven && PRIM->TME)
{
s = format("c:\\temp1\\_%05d_f%I64d_tex_%05x_%d.bmp", s_n, frame, (int)m_context->TEX0.TBP0, (int)m_context->TEX0.PSM);
@ -170,14 +158,14 @@ void GSRendererSW::Draw()
s_n++;
if(s_save)
if(s_save && s_n >= s_saven)
{
s = format("c:\\temp1\\_%05d_f%I64d_rt0_%05x_%d.bmp", s_n, frame, m_context->FRAME.Block(), m_context->FRAME.PSM);
m_mem.SaveBMP(s, m_context->FRAME.Block(), m_context->FRAME.FBW, m_context->FRAME.PSM, GetFrameRect().width(), 512);//GetFrameSize(1).cy);
}
if(s_savez)
if(s_savez && s_n >= s_saven)
{
s = format("c:\\temp1\\_%05d_f%I64d_rz0_%05x_%d.bmp", s_n, frame, m_context->ZBUF.Block(), m_context->ZBUF.PSM);
@ -234,14 +222,14 @@ void GSRendererSW::Draw()
string s;
if(s_save)
if(s_save && s_n >= s_saven)
{
s = format("c:\\temp1\\_%05d_f%I64d_rt1_%05x_%d.bmp", s_n, frame, m_context->FRAME.Block(), m_context->FRAME.PSM);
m_mem.SaveBMP(s, m_context->FRAME.Block(), m_context->FRAME.FBW, m_context->FRAME.PSM, GetFrameRect().width(), 512);//GetFrameSize(1).cy);
}
if(s_savez)
if(s_savez && s_n >= s_saven)
{
s = format("c:\\temp1\\_%05d_f%I64d_rz1_%05x_%d.bmp", s_n, frame, m_context->ZBUF.Block(), m_context->ZBUF.PSM);
@ -273,9 +261,9 @@ void GSRendererSW::GetScanlineParam(GSScanlineParam& p, GS_PRIM_CLASS primclass)
p.vm = m_mem.m_vm8;
p.fbo = m_mem.GetOffset(context->FRAME.Block(), context->FRAME.FBW, context->FRAME.PSM);
p.zbo = m_mem.GetOffset(context->ZBUF.Block(), context->FRAME.FBW, context->ZBUF.PSM);
p.fzbo = m_mem.GetOffset4(context->FRAME, context->ZBUF);
p.fbo = m_mem.GetPixelOffset(context->FRAME.Block(), context->FRAME.FBW, context->FRAME.PSM);
p.zbo = m_mem.GetPixelOffset(context->ZBUF.Block(), context->FRAME.FBW, context->ZBUF.PSM);
p.fzbo = m_mem.GetPixelOffset4(context->FRAME, context->ZBUF);
p.sel.key = 0;
@ -517,14 +505,14 @@ if(!m_dump)
case GS_LINELIST:
case GS_LINESTRIP:
case GS_SPRITE:
pmin = v[0].p.minv(v[1].p);
pmax = v[0].p.maxv(v[1].p);
pmin = v[0].p.min(v[1].p);
pmax = v[0].p.max(v[1].p);
break;
case GS_TRIANGLELIST:
case GS_TRIANGLESTRIP:
case GS_TRIANGLEFAN:
pmin = v[0].p.minv(v[1].p).minv(v[2].p);
pmax = v[0].p.maxv(v[1].p).maxv(v[2].p);
pmin = v[0].p.min(v[1].p).min(v[2].p);
pmax = v[0].p.max(v[1].p).max(v[2].p);
break;
}

View File

@ -108,9 +108,9 @@ __declspec(align(16)) struct GSScanlineParam
const uint32* clut;
uint32 tw;
GSLocalMemory::Offset* fbo;
GSLocalMemory::Offset* zbo;
GSLocalMemory::Offset4* fzbo;
GSLocalMemory::PixelOffset* fbo;
GSLocalMemory::PixelOffset* zbo;
GSLocalMemory::PixelOffset4* fzbo;
uint32 fm, zm;
};
@ -122,10 +122,10 @@ __declspec(align(16)) struct GSScanlineEnvironment
const uint32* clut;
uint32 tw;
GSVector4i* fbr;
GSVector4i* zbr;
int** fbc;
int** zbc;
int* fbr;
int* zbr;
int* fbc;
int* zbc;
GSVector2i* fzbr;
GSVector2i* fzbc;

View File

@ -120,9 +120,10 @@ void GSSettingsDlg::OnInit()
ComboBoxInit(IDC_INTERLACE, g_interlace, countof(g_interlace), theApp.GetConfig("Interlace", 0));
ComboBoxInit(IDC_ASPECTRATIO, g_aspectratio, countof(g_aspectratio), theApp.GetConfig("AspectRatio", 1));
CheckDlgButton(m_hWnd, IDC_FILTER, theApp.GetConfig("filter", 1));
CheckDlgButton(m_hWnd, IDC_FILTER, theApp.GetConfig("filter", 2));
CheckDlgButton(m_hWnd, IDC_PALTEX, theApp.GetConfig("paltex", 1));
CheckDlgButton(m_hWnd, IDC_VSYNC, theApp.GetConfig("vsync", 0));
CheckDlgButton(m_hWnd, IDC_LOGZ, theApp.GetConfig("logz", 0));
CheckDlgButton(m_hWnd, IDC_LOGZ, theApp.GetConfig("logz", 1));
CheckDlgButton(m_hWnd, IDC_FBA, theApp.GetConfig("fba", 1));
CheckDlgButton(m_hWnd, IDC_AA1, theApp.GetConfig("aa1", 0));
CheckDlgButton(m_hWnd, IDC_BLUR, theApp.GetConfig("blur", 0));
@ -179,6 +180,7 @@ bool GSSettingsDlg::OnCommand(HWND hWnd, UINT id, UINT code)
}
theApp.SetConfig("filter", (int)IsDlgButtonChecked(m_hWnd, IDC_FILTER));
theApp.SetConfig("paltex", (int)IsDlgButtonChecked(m_hWnd, IDC_PALTEX));
theApp.SetConfig("vsync", (int)IsDlgButtonChecked(m_hWnd, IDC_VSYNC));
theApp.SetConfig("logz", (int)IsDlgButtonChecked(m_hWnd, IDC_LOGZ));
theApp.SetConfig("fba", (int)IsDlgButtonChecked(m_hWnd, IDC_FBA));
@ -220,6 +222,7 @@ void GSSettingsDlg::UpdateControls()
EnableWindow(GetDlgItem(m_hWnd, IDC_RESY_EDIT), hw && !native);
EnableWindow(GetDlgItem(m_hWnd, IDC_NATIVERES), hw);
EnableWindow(GetDlgItem(m_hWnd, IDC_FILTER), hw && !native);
EnableWindow(GetDlgItem(m_hWnd, IDC_PALTEX), hw);
EnableWindow(GetDlgItem(m_hWnd, IDC_LOGZ), dx9 && hw);
EnableWindow(GetDlgItem(m_hWnd, IDC_FBA), dx9 && hw);
EnableWindow(GetDlgItem(m_hWnd, IDC_AA1), sw);

View File

@ -87,8 +87,6 @@ GSState::GSState(uint8* base, bool mt, void (*irq)())
m_regs = (GSPrivRegSet*)(base + 0x12000000);
memset(m_regs, 0, sizeof(GSPrivRegSet));
PRIM = &m_env.PRIM;
// CSR->rREV = 0x20;
m_env.PRMODECONT.AC = 1;
@ -948,7 +946,7 @@ void GSState::FlushWrite()
r.left = m_env.TRXPOS.DSAX;
r.top = y;
r.right = r.left + m_env.TRXREG.RRW;
r.bottom = min(r.top + m_env.TRXREG.RRH, m_tr.x == r.left ? m_tr.y : m_tr.y + 1);
r.bottom = std::min<int>(r.top + m_env.TRXREG.RRH, m_tr.x == r.left ? m_tr.y : m_tr.y + 1);
InvalidateVideoMem(m_env.BITBLTBUF, r);
/*
@ -1085,96 +1083,168 @@ void GSState::Move()
// TODO: unroll inner loops (width has special size requirement, must be multiples of 1 << n, depending on the format)
GSLocalMemory::PixelOffset* RESTRICT spo = m_mem.GetPixelOffset(m_env.BITBLTBUF.SBP, m_env.BITBLTBUF.SBW, m_env.BITBLTBUF.SPSM);
GSLocalMemory::PixelOffset* RESTRICT dpo = m_mem.GetPixelOffset(m_env.BITBLTBUF.DBP, m_env.BITBLTBUF.DBW, m_env.BITBLTBUF.DPSM);
if(spsm.trbpp == dpsm.trbpp && spsm.trbpp >= 16)
{
int* soffset = spsm.rowOffset[0];
int* doffset = dpsm.rowOffset[0];
int* RESTRICT scol = &spo->col[0][sx];
int* RESTRICT dcol = &dpo->col[0][dx];
if(spsm.trbpp == 32)
{
for(int y = 0; y < h; y++, sy += yinc, dy += yinc, sx -= xinc * w, dx -= xinc * w)
if(xinc > 0)
{
uint32 sbase = spsm.pa(0, sy, m_env.BITBLTBUF.SBP, m_env.BITBLTBUF.SBW);
uint32 dbase = dpsm.pa(0, dy, m_env.BITBLTBUF.DBP, m_env.BITBLTBUF.DBW);
for(int x = 0; x < w; x++, sx += xinc, dx += xinc)
for(int y = 0; y < h; y++, sy += yinc, dy += yinc)
{
m_mem.WritePixel32(dbase + doffset[dx], m_mem.ReadPixel32(sbase + soffset[sx]));
uint32* RESTRICT s = &m_mem.m_vm32[spo->row[sy]];
uint32* RESTRICT d = &m_mem.m_vm32[dpo->row[dy]];
for(int x = 0; x < w; x++) d[dcol[x]] = s[scol[x]];
}
}
else
{
for(int y = 0; y < h; y++, sy += yinc, dy += yinc)
{
uint32* RESTRICT s = &m_mem.m_vm32[spo->row[sy]];
uint32* RESTRICT d = &m_mem.m_vm32[dpo->row[dy]];
for(int x = 0; x > -w; x--) d[dcol[x]] = s[scol[x]];
}
}
}
else if(spsm.trbpp == 24)
{
for(int y = 0; y < h; y++, sy += yinc, dy += yinc, sx -= xinc * w, dx -= xinc * w)
if(xinc > 0)
{
uint32 sbase = spsm.pa(0, sy, m_env.BITBLTBUF.SBP, m_env.BITBLTBUF.SBW);
uint32 dbase = dpsm.pa(0, dy, m_env.BITBLTBUF.DBP, m_env.BITBLTBUF.DBW);
for(int x = 0; x < w; x++, sx += xinc, dx += xinc)
for(int y = 0; y < h; y++, sy += yinc, dy += yinc)
{
m_mem.WritePixel24(dbase + doffset[dx], m_mem.ReadPixel24(sbase + soffset[sx]));
uint32* RESTRICT s = &m_mem.m_vm32[spo->row[sy]];
uint32* RESTRICT d = &m_mem.m_vm32[dpo->row[dy]];
for(int x = 0; x < w; x++) d[dcol[x]] = (d[dcol[x]] & 0xff000000) | (s[scol[x]] & 0x00ffffff);
}
}
else
{
for(int y = 0; y < h; y++, sy += yinc, dy += yinc)
{
uint32* RESTRICT s = &m_mem.m_vm32[spo->row[sy]];
uint32* RESTRICT d = &m_mem.m_vm32[dpo->row[dy]];
for(int x = 0; x > -w; x--) d[dcol[x]] = (d[dcol[x]] & 0xff000000) | (s[scol[x]] & 0x00ffffff);
}
}
}
else // if(spsm.trbpp == 16)
{
for(int y = 0; y < h; y++, sy += yinc, dy += yinc, sx -= xinc * w, dx -= xinc * w)
if(xinc > 0)
{
uint32 sbase = spsm.pa(0, sy, m_env.BITBLTBUF.SBP, m_env.BITBLTBUF.SBW);
uint32 dbase = dpsm.pa(0, dy, m_env.BITBLTBUF.DBP, m_env.BITBLTBUF.DBW);
for(int x = 0; x < w; x++, sx += xinc, dx += xinc)
for(int y = 0; y < h; y++, sy += yinc, dy += yinc)
{
m_mem.WritePixel16(dbase + doffset[dx], m_mem.ReadPixel16(sbase + soffset[sx]));
uint16* RESTRICT s = &m_mem.m_vm16[spo->row[sy]];
uint16* RESTRICT d = &m_mem.m_vm16[dpo->row[dy]];
for(int x = 0; x < w; x++) d[dcol[x]] = s[scol[x]];
}
}
else
{
for(int y = 0; y < h; y++, sy += yinc, dy += yinc)
{
uint16* RESTRICT s = &m_mem.m_vm16[spo->row[sy]];
uint16* RESTRICT d = &m_mem.m_vm16[dpo->row[dy]];
for(int x = 0; x > -w; x--) d[dcol[x]] = s[scol[x]];
}
}
}
}
else if(m_env.BITBLTBUF.SPSM == PSM_PSMT8 && m_env.BITBLTBUF.DPSM == PSM_PSMT8)
{
for(int y = 0; y < h; y++, sy += yinc, dy += yinc, sx -= xinc * w, dx -= xinc * w)
if(xinc > 0)
{
uint32 sbase = GSLocalMemory::PixelAddress8(0, sy, m_env.BITBLTBUF.SBP, m_env.BITBLTBUF.SBW);
int* soffset = spsm.rowOffset[sy & 7];
uint32 dbase = GSLocalMemory::PixelAddress8(0, dy, m_env.BITBLTBUF.DBP, m_env.BITBLTBUF.DBW);
int* doffset = dpsm.rowOffset[dy & 7];
for(int x = 0; x < w; x++, sx += xinc, dx += xinc)
for(int y = 0; y < h; y++, sy += yinc, dy += yinc)
{
m_mem.WritePixel8(dbase + doffset[dx], m_mem.ReadPixel8(sbase + soffset[sx]));
uint8* RESTRICT s = &m_mem.m_vm8[spo->row[sy]];
uint8* RESTRICT d = &m_mem.m_vm8[dpo->row[dy]];
int* RESTRICT scol = &spo->col[sy & 7][sx];
int* RESTRICT dcol = &dpo->col[dy & 7][dx];
for(int x = 0; x < w; x++) d[dcol[x]] = s[scol[x]];
}
}
else
{
for(int y = 0; y < h; y++, sy += yinc, dy += yinc)
{
uint8* RESTRICT s = &m_mem.m_vm8[spo->row[sy]];
uint8* RESTRICT d = &m_mem.m_vm8[dpo->row[dy]];
int* RESTRICT scol = &spo->col[sy & 7][sx];
int* RESTRICT dcol = &dpo->col[dy & 7][dx];
for(int x = 0; x > -w; x--) d[dcol[x]] = s[scol[x]];
}
}
}
else if(m_env.BITBLTBUF.SPSM == PSM_PSMT4 && m_env.BITBLTBUF.DPSM == PSM_PSMT4)
{
for(int y = 0; y < h; y++, sy += yinc, dy += yinc, sx -= xinc * w, dx -= xinc * w)
if(xinc > 0)
{
uint32 sbase = GSLocalMemory::PixelAddress4(0, sy, m_env.BITBLTBUF.SBP, m_env.BITBLTBUF.SBW);
int* soffset = spsm.rowOffset[sy & 7];
uint32 dbase = GSLocalMemory::PixelAddress4(0, dy, m_env.BITBLTBUF.DBP, m_env.BITBLTBUF.DBW);
int* doffset = dpsm.rowOffset[dy & 7];
for(int x = 0; x < w; x++, sx += xinc, dx += xinc)
for(int y = 0; y < h; y++, sy += yinc, dy += yinc)
{
m_mem.WritePixel4(dbase + doffset[dx], m_mem.ReadPixel4(sbase + soffset[sx]));
uint32 sbase = spo->row[sy];
uint32 dbase = dpo->row[dy];
int* RESTRICT scol = &spo->col[sy & 7][sx];
int* RESTRICT dcol = &dpo->col[dy & 7][dx];
for(int x = 0; x < w; x++) m_mem.WritePixel4(dbase + dcol[x], m_mem.ReadPixel4(sbase + scol[x]));
}
}
else
{
for(int y = 0; y < h; y++, sy += yinc, dy += yinc)
{
uint32 sbase = spo->row[sy];
uint32 dbase = dpo->row[dy];
int* RESTRICT scol = &spo->col[sy & 7][sx];
int* RESTRICT dcol = &dpo->col[dy & 7][dx];
for(int x = 0; x > -w; x--) m_mem.WritePixel4(dbase + dcol[x], m_mem.ReadPixel4(sbase + scol[x]));
}
}
}
else
{
for(int y = 0; y < h; y++, sy += yinc, dy += yinc, sx -= xinc * w, dx -= xinc * w)
if(xinc > 0)
{
uint32 sbase = spsm.pa(0, sy, m_env.BITBLTBUF.SBP, m_env.BITBLTBUF.SBW);
int* soffset = spsm.rowOffset[sy & 7];
uint32 dbase = dpsm.pa(0, dy, m_env.BITBLTBUF.DBP, m_env.BITBLTBUF.DBW);
int* doffset = dpsm.rowOffset[dy & 7];
for(int x = 0; x < w; x++, sx += xinc, dx += xinc)
for(int y = 0; y < h; y++, sy += yinc, dy += yinc)
{
(m_mem.*dpsm.wpa)(dbase + doffset[dx], (m_mem.*spsm.rpa)(sbase + soffset[sx]));
uint32 sbase = spo->row[sy];
uint32 dbase = dpo->row[dy];
int* RESTRICT scol = &spo->col[sy & 7][sx];
int* RESTRICT dcol = &dpo->col[dy & 7][dx];
for(int x = 0; x < w; x++) (m_mem.*dpsm.wpa)(dbase + dcol[x], (m_mem.*spsm.rpa)(sbase + scol[x]));
}
}
else
{
for(int y = 0; y < h; y++, sy += yinc, dy += yinc)
{
uint32 sbase = spo->row[sy];
uint32 dbase = dpo->row[dy];
int* RESTRICT scol = &spo->col[sy & 7][sx];
int* RESTRICT dcol = &dpo->col[dy & 7][dx];
for(int x = 0; x > -w; x--) (m_mem.*dpsm.wpa)(dbase + dcol[x], (m_mem.*spsm.rpa)(sbase + scol[x]));
}
}
}
@ -1880,6 +1950,19 @@ bool GSC_OnePieceGrandAdventure(const GSFrameInfo& fi, int& skip)
return true;
}
bool GSC_OnePieceGrandBattle(const GSFrameInfo& fi, int& skip)
{
if(skip == 0)
{
if(fi.TME && fi.FBP == 0x02d00 && fi.FPSM == PSM_PSMCT16 && (fi.TBP0 == 0x00000 || fi.TBP0 == 0x00f00) && fi.TPSM == PSM_PSMCT16)
{
skip = 4;
}
}
return true;
}
bool GSC_ICO(const GSFrameInfo& fi, int& skip)
{
if(skip == 0)
@ -2300,6 +2383,7 @@ bool GSState::IsBadFrame(int& skip)
map[CRC::BullyCC] = GSC_BullyCC;
map[CRC::SoTC] = GSC_SoTC;
map[CRC::OnePieceGrandAdventure] = GSC_OnePieceGrandAdventure;
map[CRC::OnePieceGrandBattle] = GSC_OnePieceGrandBattle;
map[CRC::ICO] = GSC_ICO;
map[CRC::GT4] = GSC_GT4;
map[CRC::WildArms5] = GSC_WildArms5;

View File

@ -82,7 +82,7 @@ bool GSTexture7::Update(const GSVector4i& r, const void* data, int pitch)
uint8* src = (uint8*)data;
uint8* dst = (uint8*)desc.lpSurface;
int bytes = min(pitch, desc.lPitch);
int bytes = std::min<int>(pitch, desc.lPitch);
for(int i = 0, j = r.height(); i < j; i++, src += pitch, dst += desc.lPitch)
{

View File

@ -87,7 +87,14 @@ bool GSTexture9::Update(const GSVector4i& r, const void* data, int pitch)
uint8* src = (uint8*)data;
uint8* dst = (uint8*)lr.pBits;
int bytes = r.width() << (m_desc.Format == D3DFMT_A1R5G5B5 ? 1 : 2);
int bytes = r.width() * sizeof(uint32);
switch(m_desc.Format)
{
case D3DFMT_A8: bytes >>= 2; break;
case D3DFMT_A1R5G5B5: bytes >>= 1; break;
default: ASSERT(m_desc.Format == D3DFMT_A8R8G8B8); break;
}
bytes = min(bytes, pitch);
bytes = min(bytes, lr.Pitch);

Some files were not shown because too many files have changed in this diff Show More