wxSavestates branch: (partially sync'd with trunk**)

* Finished up zipfile-style savestate implementation
 * Simplified BaseSaveState class, and removed lots of now-unneeded code.
 * Prepared the i18n stuff for a pcsx2_Dev.pot file (WIP), and sorted more stuff to pcsx2_Tertiary.pot.

git-svn-id: http://pcsx2.googlecode.com/svn/branches/wxSavestates@4091 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2010-12-14 07:28:05 +00:00
commit daf47b50a0
201 changed files with 9252 additions and 7551 deletions

View File

@ -39,7 +39,7 @@ set(SoundTouchSources
RateTransposer.cpp RateTransposer.cpp
SoundTouch.cpp SoundTouch.cpp
TDStretch.cpp TDStretch.cpp
WavFile.cpp # WavFile.cpp # directly include in spu2x
cpu_detect_x86_gcc.cpp cpu_detect_x86_gcc.cpp
mmx_optimized.cpp mmx_optimized.cpp
sse_optimized.cpp) sse_optimized.cpp)
@ -55,7 +55,7 @@ set(SoundTouchHeaders
STTypes.h STTypes.h
SoundTouch.h SoundTouch.h
TDStretch.h TDStretch.h
WavFile.h # WavFile.h # directly include in spu2x
cpu_detect.h) cpu_detect.h)
# add library # add library

View File

@ -23,9 +23,6 @@ if(Linux)
endif(GTK2_FOUND) endif(GTK2_FOUND)
find_package(X11) find_package(X11)
# Manually find Xxf86vm because it is not done in the module...
FIND_LIBRARY(X11_Xxf86vm_LIB Xxf86vm ${X11_LIB_SEARCH_PATH})
MARK_AS_ADVANCED(X11_Xxf86vm_LIB)
endif(Linux) endif(Linux)
## Use cmake package to find module ## Use cmake package to find module

View File

@ -445,6 +445,10 @@
RelativePath="..\..\include\Utilities\pxEvents.h" RelativePath="..\..\include\Utilities\pxEvents.h"
> >
</File> </File>
<File
RelativePath="..\..\include\Utilities\pxForwardDefs.h"
>
</File>
<File <File
RelativePath="..\..\include\Utilities\pxRadioPanel.h" RelativePath="..\..\include\Utilities\pxRadioPanel.h"
> >

View File

@ -278,7 +278,9 @@ void CALLBACK GSsetFrameSkip(int frameskip);
int CALLBACK GSsetupRecording(int start, void* pData); int CALLBACK GSsetupRecording(int start, void* pData);
void CALLBACK GSreset(); void CALLBACK GSreset();
void CALLBACK GSgetTitleInfo( char dest[128] ); //deprecated: GSgetTitleInfo was used in PCSX2 but no plugin supported it prior to r4070:
//void CALLBACK GSgetTitleInfo( char dest[128] );
void CALLBACK GSgetTitleInfo2( char* dest, size_t length );
void CALLBACK GSwriteCSR(u32 value); void CALLBACK GSwriteCSR(u32 value);
s32 CALLBACK GSfreeze(int mode, freezeData *data); s32 CALLBACK GSfreeze(int mode, freezeData *data);
void CALLBACK GSconfigure(); void CALLBACK GSconfigure();
@ -575,7 +577,7 @@ typedef void (CALLBACK* _GSreadFIFO)(u64 *pMem);
typedef void (CALLBACK* _GSreadFIFO2)(u64 *pMem, int qwc); typedef void (CALLBACK* _GSreadFIFO2)(u64 *pMem, int qwc);
typedef void (CALLBACK* _GSchangeSaveState)(int, const char* filename); typedef void (CALLBACK* _GSchangeSaveState)(int, const char* filename);
typedef void (CALLBACK* _GSgetTitleInfo)(char dest[128]); typedef void (CALLBACK* _GSgetTitleInfo2)(char* dest, size_t length);
typedef void (CALLBACK* _GSirqCallback)(void (*callback)()); typedef void (CALLBACK* _GSirqCallback)(void (*callback)());
typedef void (CALLBACK* _GSprintf)(int timeout, char *fmt, ...); typedef void (CALLBACK* _GSprintf)(int timeout, char *fmt, ...);
typedef void (CALLBACK* _GSsetBaseMem)(void*); typedef void (CALLBACK* _GSsetBaseMem)(void*);
@ -729,7 +731,7 @@ extern _GSreadFIFO GSreadFIFO;
extern _GSreadFIFO2 GSreadFIFO2; extern _GSreadFIFO2 GSreadFIFO2;
extern _GSchangeSaveState GSchangeSaveState; extern _GSchangeSaveState GSchangeSaveState;
extern _GSgetTitleInfo GSgetTitleInfo; extern _GSgetTitleInfo2 GSgetTitleInfo2;
extern _GSmakeSnapshot GSmakeSnapshot; extern _GSmakeSnapshot GSmakeSnapshot;
extern _GSmakeSnapshot2 GSmakeSnapshot2; extern _GSmakeSnapshot2 GSmakeSnapshot2;
extern _GSirqCallback GSirqCallback; extern _GSirqCallback GSirqCallback;

View File

@ -18,37 +18,7 @@
// Dependencies.h : Contains classes required by all Utilities headers. // Dependencies.h : Contains classes required by all Utilities headers.
// This file is included by most .h files provided by the Utilities class. // This file is included by most .h files provided by the Utilities class.
// -------------------------------------------------------------------------------------- #include "pxForwardDefs.h"
// Forward Declarations Section
// --------------------------------------------------------------------------------------
class wxOutputStream;
class wxFileOutputStream;
class wxFFileOutputStream;
class wxStreamBase;
class wxInputStream;
class wxFileInputStream;
class wxFFileInputStream;
class wxPoint;
class wxRect;
class wxSize;
extern const wxSize wxDefaultSize;
extern const wxPoint wxDefaultPosition;
namespace Threading
{
class Mutex;
class Semaphore;
class pxThread;
}
namespace Exception
{
class BaseException;
}
// This should prove useful.... // This should prove useful....
#define wxsFormat wxString::Format #define wxsFormat wxString::Format
@ -165,6 +135,50 @@ public:
} }
}; };
// --------------------------------------------------------------------------------------
// _(x) / _t(x) / _d(x) / pxL(x) / pxLt(x) [macros]
// --------------------------------------------------------------------------------------
// Define pxWex's own i18n helpers. These override the wxWidgets helpers and provide
// additional functionality. Define them FIRST THING, to make sure that wx's own gettext
// macros aren't in place.
//
// _ is for standard translations
// _t is for tertiary low priority translations
// _d is for debug/devel build translations
#define WXINTL_NO_GETTEXT_MACRO
#ifndef _
# define _(s) pxGetTranslation(_T(s))
#endif
#ifndef _t
# define _t(s) pxGetTranslation(_T(s))
#endif
#ifndef _d
# define _d(s) pxGetTranslation(_T(s))
#endif
// pxL / pxLt / pxDt -- macros 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. pxL is a standard translation
// moniker. pxLt is for tertiary strings that have a very low translation priority. pxDt is for
// debug/devel specific translations.
//
#ifndef pxL
# define pxL(a) wxT(a)
#endif
#ifndef pxLt
# define pxLt(a) wxT(a)
#endif
#ifndef pxDt
# define pxDt(a) wxT(a)
#endif
#include <wx/string.h> #include <wx/string.h>
#include <wx/intl.h> #include <wx/intl.h>
#include <wx/log.h> #include <wx/log.h>
@ -178,6 +192,9 @@ public:
#include "Pcsx2Defs.h" #include "Pcsx2Defs.h"
// --------------------------------------------------------------------------------------
// Handy Human-readable constants for common immediate values (_16kb -> _4gb)
static const sptr _64kb = 0x10000; static const sptr _64kb = 0x10000;
static const sptr _16kb = _64kb / 4; static const sptr _16kb = _64kb / 4;
static const sptr _128kb = _64kb * 2; static const sptr _128kb = _64kb * 2;
@ -193,30 +210,8 @@ static const s64 _1gb = _256mb * 4;
static const s64 _4gb = _1gb * 4; static const s64 _4gb = _1gb * 4;
// ===========================================================================================
// i18n/Translation Feature Set!
// ===========================================================================================
extern const wxChar* __fastcall pxExpandMsg( const wxChar* key, const wxChar* englishContent );
extern const wxChar* __fastcall pxGetTranslation( const wxChar* message );
extern bool pxIsEnglish( int id );
extern wxString fromUTF8( const char* src );
extern wxString fromAscii( const char* src );
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
// wxLt(x) [macro] // pxE(key, msg) and pxEt(key, msg) [macros]
// --------------------------------------------------------------------------------------
// 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.
//
#ifndef wxLt
# define wxLt(a) wxT(a)
#endif
// --------------------------------------------------------------------------------------
// pxE(x) [macro]
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
// Translation Feature: pxE is used as a method of dereferencing very long english text // Translation Feature: pxE is used as a method of dereferencing very long english text
// descriptions via a "key" identifier. In this way, the english text can be revised without // descriptions via a "key" identifier. In this way, the english text can be revised without
@ -226,28 +221,42 @@ extern wxString fromAscii( const char* src );
// //
// Valid prefix types: // Valid prefix types:
// //
// .Panel: Key-based translation of a panel or dialog text; usually either a header or // !Panel: Key-based translation of a panel or dialog text; usually either a header or
// checkbox description, by may also include some controls with long labels. // checkbox description, by may also include some controls with long labels.
// These have the highest translation priority. // These have the highest translation priority.
// //
// .Popup: Key-based translation of a popup dialog box; either a notice, confirmation, // !Notice: Key-based translation of a popup dialog box; either a notice, confirmation,
// or error. These typically have very high translation priority (roughly equal // or error. These typically have very high translation priority (roughly equal
// or slightly less than pxE_Panel). // or slightly less than pxE_Panel).
// //
// .Error Key-based translation of error messages, typically used when throwing exceptions // !Tooltip: Key-based translation of a tooltip for a button on a tool bar. Since buttons are
// that have end-user errors. These are normally (but not always) displayed as popups // rarely self-explanatory, these translations are considered medium to high priority.
// to the user. Translation priority is medium.
// //
// .Wizard Key-based translation of a heading, checkbox item, description, or other text // !Wizard Key-based translation of a heading, checkbox item, description, or other text
// associated with the First-time wizard. Translation of these items is considered // associated with the First-time wizard. Translation of these items is considered
// lower-priority to most other messages; but equal or higher priority to tooltips. // lower-priority to most other messages; but equal or higher priority to ContextTips.
// //
// .Tooltip: Key-based translation of a tooltip for a control on a dialog/panel. Translation // !ContextTip: Key-based translation of a tooltip for a control on a dialog/panel. Translation
// of these items is typically considered "lowest priority" as they usually provide // of these items is typically considered "lowest priority" as they usually provide
// the most tertiary of info to the user. // only tertiary (extra) info to the user.
// //
#define pxE(key, english) pxExpandMsg( wxT(key), english ) #define pxE(key, english) pxExpandMsg( wxT(key), english )
// For use with tertiary translations (low priority).
#define pxEt(key, english) pxExpandMsg( wxT(key), english )
// For use with Dev/debug build translations (low priority).
#define pxE_dev(key, english) pxExpandMsg( wxT(key), english )
extern const wxChar* __fastcall pxExpandMsg( const wxChar* key, const wxChar* englishContent );
extern const wxChar* __fastcall pxGetTranslation( const wxChar* message );
extern bool pxIsEnglish( int id );
extern wxString fromUTF8( const char* src );
extern wxString fromAscii( const char* src );
#include "Utilities/Assertions.h" #include "Utilities/Assertions.h"
#include "Utilities/Exceptions.h" #include "Utilities/Exceptions.h"

View File

@ -184,7 +184,7 @@ public: \
// an App message loop we'll still want it to be handled in a reasonably graceful manner. // an App message loop we'll still want it to be handled in a reasonably graceful manner.
class CancelEvent : public RuntimeError class CancelEvent : public RuntimeError
{ {
DEFINE_RUNTIME_EXCEPTION( CancelEvent, RuntimeError, wxLt("No reason given.") ) DEFINE_RUNTIME_EXCEPTION( CancelEvent, RuntimeError, pxLt("No reason given.") )
public: public:
explicit CancelEvent( const wxString& logmsg ) explicit CancelEvent( const wxString& logmsg )
@ -223,7 +223,7 @@ public: \
class ParseError : public RuntimeError class ParseError : public RuntimeError
{ {
DEFINE_RUNTIME_EXCEPTION( ParseError, RuntimeError, wxLt("Parse error") ); DEFINE_RUNTIME_EXCEPTION( ParseError, RuntimeError, pxL("Parse error") );
}; };
// --------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------
@ -247,7 +247,7 @@ public: \
class HardwareDeficiency : public RuntimeError class HardwareDeficiency : public RuntimeError
{ {
public: public:
DEFINE_RUNTIME_EXCEPTION( HardwareDeficiency, RuntimeError, wxLt("Your machine's hardware is incapable of running PCSX2. Sorry dood.") ); DEFINE_RUNTIME_EXCEPTION( HardwareDeficiency, RuntimeError, pxL("Your machine's hardware is incapable of running PCSX2. Sorry dood.") );
}; };
// --------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------

View File

@ -251,5 +251,6 @@ namespace HostSys
extern void InitCPUTicks(); extern void InitCPUTicks();
extern u64 GetTickFrequency(); extern u64 GetTickFrequency();
extern u64 GetCPUTicks(); extern u64 GetCPUTicks();
extern u64 GetPhysicalMemory();
extern wxString GetOSVersionString(); extern wxString GetOSVersionString();

View File

@ -195,16 +195,16 @@ public:
this->m_buffer = (T*)malloc( this->m_size * sizeof(T) ); this->m_buffer = (T*)malloc( this->m_size * sizeof(T) );
if (!this->m_buffer) if (!this->m_buffer)
throw Exception::OutOfMemory("ScopedAlloc"); throw Exception::OutOfMemory(L"ScopedAlloc");
} }
virtual void Resize( size_t newsize ) virtual void Resize( size_t newsize )
{ {
this->m_size = newsize; this->m_size = newsize;
this->m_buffer = (T*)realloc(this->m_buffer * sizeof(T), newsize); this->m_buffer = (T*)realloc(this->m_buffer, this->m_size * sizeof(T));
if (!this->m_buffer) if (!this->m_buffer)
throw Exception::OutOfMemory("ScopedAlloc::Resize"); throw Exception::OutOfMemory(L"ScopedAlloc::Resize");
} }
}; };

View File

@ -233,7 +233,8 @@ protected:
m_Close :1; m_Close :1;
BITFIELD_END BITFIELD_END
wxString m_CustomLabel; wxString m_CustomLabel;
wxString m_CustomLabelId;
public: public:
MsgButtons() { bitset = 0; } MsgButtons() { bitset = 0; }
@ -251,9 +252,12 @@ public:
MsgButtons& Reset() { m_Reset = true; return *this; } MsgButtons& Reset() { m_Reset = true; return *this; }
MsgButtons& Close() { m_Close = true; return *this; } MsgButtons& Close() { m_Close = true; return *this; }
MsgButtons& Custom( const wxString& label) // label - native language label displayed to user
// id - raw ASCII identifier used in the config file (do not translate, hence char*)
MsgButtons& Custom( const wxString& label, const char* id )
{ {
m_CustomLabel = label; m_CustomLabel = label;
m_CustomLabelId = fromUTF8(id);
return *this; return *this;
} }
@ -274,7 +278,8 @@ public:
bool HasClose() const { return m_Close; } bool HasClose() const { return m_Close; }
bool HasCustom() const { return !m_CustomLabel.IsEmpty(); } bool HasCustom() const { return !m_CustomLabel.IsEmpty(); }
const wxString& GetCustomLabel() const { return m_CustomLabel; } const wxString& GetCustomLabel() const { return m_CustomLabel; }
const wxString& GetCustomLabelId() const { return m_CustomLabelId; }
bool Allows( wxWindowID id ) const; bool Allows( wxWindowID id ) const;
void SetBestFocus( wxWindow* dialog ) const; void SetBestFocus( wxWindow* dialog ) const;

View File

@ -15,6 +15,8 @@
#pragma once #pragma once
#include "wx/filefn.h"
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
// pxStreamBase // pxStreamBase
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
@ -36,7 +38,10 @@ public:
// or wxOputStream derivative). // or wxOputStream derivative).
virtual wxStreamBase* GetWxStreamBase() const=0; virtual wxStreamBase* GetWxStreamBase() const=0;
virtual void Close()=0; virtual void Close()=0;
virtual wxFileOffset Tell() const=0;
virtual wxFileOffset Seek( wxFileOffset ofs, wxSeekMode mode = wxFromStart )=0;
virtual wxFileOffset Length() const;
bool IsOk() const; bool IsOk() const;
wxString GetStreamName() const { return m_filename; } wxString GetStreamName() const { return m_filename; }
}; };
@ -71,6 +76,9 @@ public:
{ {
Write( &data, sizeof(data) ); Write( &data, sizeof(data) );
} }
wxFileOffset Tell() const;
wxFileOffset Seek( wxFileOffset ofs, wxSeekMode mode = wxFromStart );
}; };
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
@ -102,4 +110,7 @@ public:
{ {
Read( &dest, sizeof(dest) ); Read( &dest, sizeof(dest) );
} }
wxFileOffset Tell() const;
wxFileOffset Seek( wxFileOffset ofs, wxSeekMode mode = wxFromStart );
}; };

View File

@ -522,6 +522,7 @@ public:
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
class wxDialogWithHelpers : public wxDialog class wxDialogWithHelpers : public wxDialog
{ {
typedef wxDialog _parent;
DECLARE_DYNAMIC_CLASS_NO_COPY(wxDialogWithHelpers) DECLARE_DYNAMIC_CLASS_NO_COPY(wxDialogWithHelpers)
protected: protected:
@ -541,6 +542,7 @@ public:
virtual void SmartCenterFit(); virtual void SmartCenterFit();
virtual int ShowModal(); virtual int ShowModal();
virtual bool Show( bool show=true ); virtual bool Show( bool show=true );
virtual bool Destroy();
// Must return the same thing as GetNameStatic; a name ideal for use in uniquely // Must return the same thing as GetNameStatic; a name ideal for use in uniquely
// identifying dialogs. (this version is the 'instance' version, which is called // identifying dialogs. (this version is the 'instance' version, which is called

View File

@ -31,8 +31,6 @@ class x86capabilities
{ {
public: public:
bool isIdentified; bool isIdentified;
u32 LogicalCoresPerPhysicalCPU;
u32 PhysicalCoresPerPhysicalCPU;
public: public:
x86VendorType VendorID; x86VendorType VendorID;
@ -106,8 +104,6 @@ public:
{ {
isIdentified = false; isIdentified = false;
VendorID = x86Vendor_Unknown; VendorID = x86Vendor_Unknown;
LogicalCoresPerPhysicalCPU = 1;
PhysicalCoresPerPhysicalCPU = 1;
} }
void Identify(); void Identify();

View File

@ -251,7 +251,7 @@ wxString Exception::VirtualMemoryMapConflict::FormatDisplayMessage() const
{ {
FastFormatUnicode retmsg; FastFormatUnicode retmsg;
retmsg.Write( L"%s", retmsg.Write( L"%s",
pxE( ".Error:VirtualMemoryMap", pxE( "!Notice:VirtualMemoryMap",
L"There is not enough virtual memory available, or necessary virtual memory " L"There is not enough virtual memory available, or necessary virtual memory "
L"mappings have already been reserved by other processes, services, or DLLs." L"mappings have already been reserved by other processes, services, or DLLs."
) )

View File

@ -167,9 +167,9 @@ void HostSys::MmapResetPtr(void* base, size_t size)
// pretty well stops all PCSX2 threads anyway). // pretty well stops all PCSX2 threads anyway).
Munmap(base, size); Munmap(base, size);
void* result = Mmap((uptr)base, size); void* result = MmapReservePtr(base, size);
pxAssertRel ((uptr)result != (uptr)base, pxsFmt( pxAssertRel ((uptr)result == (uptr)base, pxsFmt(
"Virtual memory decommit failed: memory at 0x%08X -> 0x%08X could not be remapped. " "Virtual memory decommit failed: memory at 0x%08X -> 0x%08X could not be remapped. "
"This is likely caused by multi-thread memory contention.", base, (uptr)base+size "This is likely caused by multi-thread memory contention.", base, (uptr)base+size
)); ));

View File

@ -20,11 +20,18 @@
#include <sys/time.h> #include <sys/time.h>
#include <wx/utils.h> #include <wx/utils.h>
extern "C" __aligned16 u8 _xmm_backup[16*2]; // Returns 0 on failure (not supported by the operating system).
extern "C" __aligned16 u8 _mmx_backup[8*4]; u64 GetPhysicalMemory()
{
u64 pages = 0;
#ifdef _SC_PHYS_PAGES
pages = sysconf(_SC_PHYS_PAGES);
#endif
return pages * getpagesize();
}
u8 _xmm_backup[16*2];
u8 _mmx_backup[8*4];
void InitCPUTicks() void InitCPUTicks()
{ {

View File

@ -38,7 +38,7 @@ ConsoleLogSource_Threading::ConsoleLogSource_Threading()
static const TraceLogDescriptor myDesc = static const TraceLogDescriptor myDesc =
{ {
L"pxThread", L"pxThread", L"pxThread", L"pxThread",
wxLt("Threading activity: start, detach, sync, deletion, etc.") pxLt("Threading activity: start, detach, sync, deletion, etc.")
}; };
m_Descriptor = &myDesc; m_Descriptor = &myDesc;

View File

@ -19,6 +19,7 @@
#include <winnt.h> #include <winnt.h>
int SysPageFaultExceptionFilter( EXCEPTION_POINTERS* eps ) int SysPageFaultExceptionFilter( EXCEPTION_POINTERS* eps )
{ {
if( eps->ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION ) if( eps->ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION )

View File

@ -39,6 +39,14 @@ u64 GetCPUTicks()
return count.QuadPart; return count.QuadPart;
} }
u64 GetPhysicalMemory()
{
MEMORYSTATUSEX status;
status.dwLength = sizeof(status);
GlobalMemoryStatusEx(&status);
return status.ullTotalPhys;
}
// Windows SDK 7 provides this but previous ones do not, so roll our own in those cases: // Windows SDK 7 provides this but previous ones do not, so roll our own in those cases:
#ifndef VER_SUITE_WH_SERVER #ifndef VER_SUITE_WH_SERVER
# define VER_SUITE_WH_SERVER 0x00008000 # define VER_SUITE_WH_SERVER 0x00008000

View File

@ -35,6 +35,12 @@ bool pxStreamBase::IsOk() const
return woot && woot->IsOk(); return woot && woot->IsOk();
} }
wxFileOffset pxStreamBase::Length() const
{
if (!GetWxStreamBase()) return 0;
return GetWxStreamBase()->GetLength();
}
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
// pxInputStream (implementations) // pxInputStream (implementations)
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
@ -55,6 +61,16 @@ pxInputStream::pxInputStream(const wxString& filename, wxInputStream* input)
wxStreamBase* pxInputStream::GetWxStreamBase() const { return m_stream_in.GetPtr(); } wxStreamBase* pxInputStream::GetWxStreamBase() const { return m_stream_in.GetPtr(); }
wxFileOffset pxInputStream::Tell() const
{
return m_stream_in->TellI();
}
wxFileOffset pxInputStream::Seek( wxFileOffset ofs, wxSeekMode mode )
{
return m_stream_in->SeekI(ofs, mode);
}
void pxInputStream::SetStream( const wxString& filename, ScopedPtr<wxInputStream>& stream ) void pxInputStream::SetStream( const wxString& filename, ScopedPtr<wxInputStream>& stream )
{ {
m_filename = filename; m_filename = filename;
@ -107,6 +123,15 @@ pxOutputStream::pxOutputStream(const wxString& filename, wxOutputStream* output)
wxStreamBase* pxOutputStream::GetWxStreamBase() const { return m_stream_out.GetPtr(); } wxStreamBase* pxOutputStream::GetWxStreamBase() const { return m_stream_out.GetPtr(); }
wxFileOffset pxOutputStream::Tell() const
{
return m_stream_out->TellO();
}
wxFileOffset pxOutputStream::Seek( wxFileOffset ofs, wxSeekMode mode )
{
return m_stream_out->SeekO( ofs, mode );
}
void pxOutputStream::SetStream( const wxString& filename, ScopedPtr<wxOutputStream>& stream ) void pxOutputStream::SetStream( const wxString& filename, ScopedPtr<wxOutputStream>& stream )
{ {

View File

@ -32,20 +32,25 @@ bool pxIsEnglish( int id )
// (without this second pass many tooltips would just show up as "Savestate Tooltip" instead // (without this second pass many tooltips would just show up as "Savestate Tooltip" instead
// of something meaningful). // of something meaningful).
// //
// Rationale: Traditional gnu-style gnu_gettext stuff tends to stop translating strings when // Rationale: Traditional gnu-style gettext stuff tends to stop translating strings when
// the slightest change to a string is made (including punctuation and possibly even case). // the slightest change to a string is made (including punctuation and possibly even case).
// On long strings especially, this can be unwanted since future revisions of the app may have // On long strings especially, this can be unwanted since future revisions of the app may have
// simple tyop fixes that *should not* break existing translations. Furthermore // simple typo or newline fixes that *should not* break existing translations. Furthermore,
// icons can be used in places where otherwise identical english verbage for two separate
// terms can be differentiated. GNU gettext has some new tools for using fuzzy logic heuristics
// matching, but it is also imperfect and complicated, so we have opted to continue using this
// system instead.
//
const wxChar* __fastcall pxExpandMsg( const wxChar* key, const wxChar* englishContent ) const wxChar* __fastcall pxExpandMsg( const wxChar* key, const wxChar* englishContent )
{ {
#ifdef PCSX2_DEVBUILD #ifdef PCSX2_DEVBUILD
static const wxChar* tbl_pxE_Prefixes[] = static const wxChar* tbl_pxE_Prefixes[] =
{ {
L".Panel:", L"!Panel:",
L".Popup:", L"!Notice:",
L".Error:", L"!Wizard:",
L".Wizard:", L"!Tooltip:",
L".Tooltip:", L"!ContextTip:",
NULL NULL
}; };
@ -57,7 +62,7 @@ const wxChar* __fastcall pxExpandMsg( const wxChar* key, const wxChar* englishCo
++prefix; ++prefix;
} }
pxAssertDev( *prefix != NULL, pxAssertDev( *prefix != NULL,
wxsFormat( L"Invalid pxE key prefix in key '%s'. Prefix must be one of the valid prefixes listed in pxExpandMsg.", key ) pxsFmt( L"Invalid pxE key prefix in key '%s'. Prefix must be one of the valid prefixes listed in pxExpandMsg.", key )
); );
#endif #endif

View File

@ -33,7 +33,7 @@ ConsoleLogSource_App::ConsoleLogSource_App()
static const TraceLogDescriptor myDesc = static const TraceLogDescriptor myDesc =
{ {
L"AppEvents", L"App Events", L"AppEvents", L"App Events",
wxLt("Includes idle event processing and some other uncommon event usages.") pxLt("Includes idle event processing and some other uncommon event usages.")
}; };
m_Descriptor = &myDesc; m_Descriptor = &myDesc;

View File

@ -274,13 +274,13 @@ pxStaticText& wxDialogWithHelpers::Heading( const wxString& label )
return *new pxStaticHeading( this, label ); return *new pxStaticHeading( this, label );
} }
void wxDialogWithHelpers::OnCloseWindow( wxCloseEvent& evt ) bool wxDialogWithHelpers::Destroy()
{ {
// Save the dialog position if the dialog is named... // Save the dialog position if the dialog is named...
// FIXME : This doesn't get called if the app is exited by alt-f4'ing the main app window. // FIXME : This doesn't get called if the app is exited by alt-f4'ing the main app window.
// ... not sure how to fix that yet. I could register a list of open windows into wxAppWithHelpers // ... not sure how to fix that yet. I could register a list of open windows into wxAppWithHelpers
// that systematically get closed. Seems like work, maybe later. --air // that systematically get closed. Seems like work, maybe later. --air
if( wxConfigBase* cfg = IsIconized() ? NULL : wxConfigBase::Get( false ) ) if( wxConfigBase* cfg = IsIconized() ? NULL : wxConfigBase::Get( false ) )
{ {
const wxString dlgName( GetDialogName() ); const wxString dlgName( GetDialogName() );
@ -300,6 +300,11 @@ void wxDialogWithHelpers::OnCloseWindow( wxCloseEvent& evt )
} }
} }
return _parent::Destroy();
}
void wxDialogWithHelpers::OnCloseWindow( wxCloseEvent& evt )
{
if( !IsModal() ) Destroy(); if( !IsModal() ) Destroy();
evt.Skip(); evt.Skip();
} }

View File

@ -183,11 +183,11 @@ __fi void memcpy_vibes(void * dest, const void * src, int size) {
__asm__ __volatile__ __asm__ __volatile__
( (
".intel_syntax noprefix\n" ".intel_syntax noprefix\n"
"mov eax, %[qwc]\n" // keep a copy of count for looping "sub %[qwc], 1\n" // dec the counter to ease the count of 16bytes block later (optimization)
"shr eax, 1\n" // Note after this line, real value of the counter is %[qwc] + 1
"jz memcpy_qwc_1_%=\n" // only one 16 byte block to copy? "jle memcpy_qwc_1_%=\n" // only one 16 byte block to copy? Or nothing.
"cmp eax, 64\n" // "IN_CACHE_COPY/32" "cmp %[qwc], 127\n" // "IN_CACHE_COPY/16"
"jb memcpy_qwc_loop1_%=\n" // small copies should be cached (definite speedup --air) "jb memcpy_qwc_loop1_%=\n" // small copies should be cached (definite speedup --air)
"memcpy_qwc_loop2_%=:\n" // 32-byte blocks, uncached copy "memcpy_qwc_loop2_%=:\n" // 32-byte blocks, uncached copy
@ -204,8 +204,8 @@ __fi void memcpy_vibes(void * dest, const void * src, int size) {
"add %[src],32\n" // update source pointer "add %[src],32\n" // update source pointer
"add %[dest],32\n" // update destination pointer "add %[dest],32\n" // update destination pointer
"sub eax,1\n" "sub %[qwc],2\n"
"jnz memcpy_qwc_loop2_%=\n" // last 64-byte block? "jg memcpy_qwc_loop2_%=\n" // last 64-byte block?
"sfence\n" // flush the write buffer "sfence\n" // flush the write buffer
"jmp memcpy_qwc_1_%=\n" "jmp memcpy_qwc_1_%=\n"
@ -227,12 +227,12 @@ __fi void memcpy_vibes(void * dest, const void * src, int size) {
"add %[src],32\n" // update source pointer "add %[src],32\n" // update source pointer
"add %[dest],32\n" // update destination pointer "add %[dest],32\n" // update destination pointer
"sub eax,1\n" "sub %[qwc],2\n"
"jnz memcpy_qwc_loop1_%=\n" // last 64-byte block? "jg memcpy_qwc_loop2_%=\n" // last 64-byte block?
"memcpy_qwc_1_%=:\n" "memcpy_qwc_1_%=:\n"
"test %[qwc],1\n" "cmp %[qwc],0\n"
"jz memcpy_qwc_final_%=\n" "jne memcpy_qwc_final_%=\n"
"movq mm0,[%[src]]\n" "movq mm0,[%[src]]\n"
"movq mm1,[%[src]+8]\n" "movq mm1,[%[src]+8]\n"
"movq [%[dest]], mm0\n" "movq [%[dest]], mm0\n"
@ -243,7 +243,7 @@ __fi void memcpy_vibes(void * dest, const void * src, int size) {
".att_syntax\n" ".att_syntax\n"
: "=&r"(dest), "=&r"(src), "=&r"(qwc) : "=&r"(dest), "=&r"(src), "=&r"(qwc)
: [dest]"0"(dest), [src]"1"(src), [qwc]"2"(qwc) : [dest]"0"(dest), [src]"1"(src), [qwc]"2"(qwc)
: "memory", "eax", "mm0", "mm1", "mm2", "mm3" : "memory", "mm0", "mm1", "mm2", "mm3"
); );
} }
#endif #endif

View File

@ -16,24 +16,16 @@
#include "PrecompiledHeader.h" #include "PrecompiledHeader.h"
#include "cpudetect_internal.h" #include "cpudetect_internal.h"
#include <wx/thread.h>
// Note: Apparently this solution is Linux/Solaris only. // Note: Apparently this solution is Linux/Solaris only.
// FreeBSD/OsX need something far more complicated (apparently) // FreeBSD/OsX need something far more complicated (apparently)
void x86capabilities::CountLogicalCores() void x86capabilities::CountLogicalCores()
{ {
const uint numCPU = sysconf( _SC_NPROCESSORS_ONLN ); // Note : GetCPUCount uses sysconf( _SC_NPROCESSORS_ONLN ) internally, which can return 1
if( numCPU > 0 ) // if sysconf info isn't available (a long standing linux bug). There are no fallbacks or
{ // alternatives, apparently.
//isMultiCore = numCPU > 1; LogicalCores = wxThread::GetCPUCount();
LogicalCores = numCPU;
PhysicalCores = ( numCPU / LogicalCoresPerPhysicalCPU ) * PhysicalCoresPerPhysicalCPU;
}
else
{
// Indeterminate?
LogicalCores = 1;
PhysicalCores = 1;
}
} }
bool CanEmitShit() bool CanEmitShit()

View File

@ -37,10 +37,6 @@ void x86capabilities::CountLogicalCores()
} }
LogicalCores = CPUs; LogicalCores = CPUs;
if( LogicalCoresPerPhysicalCPU > CPUs) // for 1-socket HTT-disabled machines
LogicalCoresPerPhysicalCPU = CPUs;
PhysicalCores = ( CPUs / LogicalCoresPerPhysicalCPU ) * PhysicalCoresPerPhysicalCPU;
} }
bool _test_instruction( void* pfnCall ) bool _test_instruction( void* pfnCall )

View File

@ -133,23 +133,6 @@ void x86capabilities::CountCores()
s32 regs[ 4 ]; s32 regs[ 4 ];
u32 cmds; u32 cmds;
LogicalCoresPerPhysicalCPU = 0;
PhysicalCoresPerPhysicalCPU = 1;
// detect multicore for Intel cpu
__cpuid( regs, 0 );
cmds = regs[ 0 ];
if( cmds >= 0x00000001 )
LogicalCoresPerPhysicalCPU = ( regs[1] >> 16 ) & 0xff;
if ((cmds >= 0x00000004) && (VendorID == x86Vendor_Intel))
{
__cpuid( regs, 0x00000004 );
PhysicalCoresPerPhysicalCPU += ( regs[0] >> 26) & 0x3f;
}
__cpuid( regs, 0x80000000 ); __cpuid( regs, 0x80000000 );
cmds = regs[ 0 ]; cmds = regs[ 0 ];
@ -157,9 +140,6 @@ void x86capabilities::CountCores()
if ((cmds >= 0x80000008) && (VendorID == x86Vendor_AMD) ) if ((cmds >= 0x80000008) && (VendorID == x86Vendor_AMD) )
{ {
__cpuid( regs, 0x80000008 );
PhysicalCoresPerPhysicalCPU += ( regs[2] ) & 0xff;
// AMD note: they don't support hyperthreading, but they like to flag this true // AMD note: they don't support hyperthreading, but they like to flag this true
// anyway. Let's force-unflag it until we come up with a better solution. // anyway. Let's force-unflag it until we come up with a better solution.
// (note: seems to affect some Phenom II's only? -- Athlon X2's and PhenomI's do // (note: seems to affect some Phenom II's only? -- Athlon X2's and PhenomI's do
@ -167,9 +147,6 @@ void x86capabilities::CountCores()
hasMultiThreading = 0; hasMultiThreading = 0;
} }
if( !hasMultiThreading || LogicalCoresPerPhysicalCPU == 0 )
LogicalCoresPerPhysicalCPU = 1;
// This will assign values into LogicalCores and PhysicalCores // This will assign values into LogicalCores and PhysicalCores
CountLogicalCores(); CountLogicalCores();
} }

View File

@ -122,9 +122,6 @@ find $NEW_DIR -name "configure.ac" -exec rm -f {} \;
find $NEW_DIR -name "Makefile.am" -exec rm -f {} \; find $NEW_DIR -name "Makefile.am" -exec rm -f {} \;
echo "Remove 3rd party directories" echo "Remove 3rd party directories"
find $NEW_DIR -name "3rdparty" -exec rm -fr {} \; 2> /dev/null find $NEW_DIR -name "3rdparty" -exec rm -fr {} \; 2> /dev/null
# I really need to clean this mess one day
# echo "Remove plugins/zzogl-pg/opengl/ZeroGSShaders (some zlib source in the middle)"
# rm -fr $NEW_DIR/plugins/zzogl-pg/opengl/ZeroGSShaders
echo "Remove windows file (useless & copyright issue)" echo "Remove windows file (useless & copyright issue)"
find $NEW_DIR -iname "windows" -type d -exec rm -fr {} \; 2> /dev/null find $NEW_DIR -iname "windows" -type d -exec rm -fr {} \; 2> /dev/null
find $NEW_DIR -name "Win32" -type d -exec rm -fr {} \; 2> /dev/null find $NEW_DIR -name "Win32" -type d -exec rm -fr {} \; 2> /dev/null
@ -134,7 +131,6 @@ rm -fr "${NEW_DIR}/common/vsprops"
echo "Remove useless files (copyright issues)" echo "Remove useless files (copyright issues)"
rm -fr "${NEW_DIR}/plugins/zzogl-pg/opengl/ZeroGSShaders" rm -fr "${NEW_DIR}/plugins/zzogl-pg/opengl/ZeroGSShaders"
rm -fr "${NEW_DIR}/common/src/Utilities/x86/MemcpyFast.cpp" rm -fr "${NEW_DIR}/common/src/Utilities/x86/MemcpyFast.cpp"
rm -fr "${NEW_DIR}/plugins/zzogl-pg/opengl/memcpy_amd.cpp"
## BUILD ## BUILD
echo "Build the tar.gz file" echo "Build the tar.gz file"

View File

@ -1,176 +0,0 @@
This patch removes recording feature beacause it needs libsoundtouch > 1.4.
Howerever only the version 1.3 is in debian. Unfortunately the package seems
to be not actively maintained.
Note it also correct the inlude path.
Index: pcsx2.snapshot-3369/plugins/spu2-x/src/Wavedump_wav.cpp
===================================================================
--- pcsx2.snapshot-3369.orig/plugins/spu2-x/src/Wavedump_wav.cpp
+++ pcsx2.snapshot-3369/plugins/spu2-x/src/Wavedump_wav.cpp
@@ -16,16 +16,22 @@
*/
#include "Global.h"
+#if defined(SOUNDTOUCH_VERSION_ID) & (SOUNDTOUCH_VERSION_ID >= 10400)
#include "soundtouch/WavFile.h"
+#endif
+#if defined(SOUNDTOUCH_VERSION_ID) & (SOUNDTOUCH_VERSION_ID >= 10400)
static WavOutFile* _new_WavOutFile( const char* destfile )
{
return new WavOutFile( destfile, 48000, 16, 2 );
}
+#endif
namespace WaveDump
{
+#if defined(SOUNDTOUCH_VERSION_ID) & (SOUNDTOUCH_VERSION_ID >= 10400)
static WavOutFile* m_CoreWav[2][CoreSrc_Count] = { NULL };
+#endif
static const char* m_tbl_CoreOutputTypeNames[CoreSrc_Count] =
{
@@ -42,6 +48,7 @@
if( !IsDevBuild ) return;
if( !WaveLog() ) return;
+#if defined(SOUNDTOUCH_VERSION_ID) & (SOUNDTOUCH_VERSION_ID >= 10400)
char wavfilename[256];
for( uint cidx=0; cidx<2; cidx++ )
@@ -68,11 +75,13 @@
}
}
}
+#endif
}
void Close()
{
if( !IsDevBuild ) return;
+#if defined(SOUNDTOUCH_VERSION_ID) & (SOUNDTOUCH_VERSION_ID >= 10400)
for( uint cidx=0; cidx<2; cidx++ )
{
for( int srcidx=0; srcidx<CoreSrc_Count; srcidx++ )
@@ -80,13 +89,16 @@
safe_delete( m_CoreWav[cidx][srcidx] );
}
}
+#endif
}
void WriteCore( uint coreidx, CoreSourceType src, const StereoOut16& sample )
{
if( !IsDevBuild ) return;
+#if defined(SOUNDTOUCH_VERSION_ID) & (SOUNDTOUCH_VERSION_ID >= 10400)
if( m_CoreWav[coreidx][src] != NULL )
m_CoreWav[coreidx][src]->write( (s16*)&sample, 2 );
+#endif
}
void WriteCore( uint coreidx, CoreSourceType src, s16 left, s16 right )
@@ -101,11 +113,14 @@
bool WavRecordEnabled = false;
+#if defined(SOUNDTOUCH_VERSION_ID) & (SOUNDTOUCH_VERSION_ID >= 10400)
static WavOutFile* m_wavrecord = NULL;
+#endif
static Mutex WavRecordMutex;
void RecordStart()
{
+#if defined(SOUNDTOUCH_VERSION_ID) & (SOUNDTOUCH_VERSION_ID >= 10400)
WavRecordEnabled = false;
try
@@ -120,18 +135,23 @@
m_wavrecord = NULL; // not needed, but what the heck. :)
SysMessage("SPU2-X couldn't open file for recording: %s.\nRecording to wavfile disabled.", "recording.wav");
}
+#endif
}
void RecordStop()
{
+#if defined(SOUNDTOUCH_VERSION_ID) & (SOUNDTOUCH_VERSION_ID >= 10400)
WavRecordEnabled = false;
ScopedLock lock( WavRecordMutex );
safe_delete( m_wavrecord );
+#endif
}
void RecordWrite( const StereoOut16& sample )
{
+#if defined(SOUNDTOUCH_VERSION_ID) & (SOUNDTOUCH_VERSION_ID >= 10400)
ScopedLock lock( WavRecordMutex );
if( m_wavrecord == NULL ) return;
m_wavrecord->write( (s16*)&sample, 2 );
+#endif
}
Index: pcsx2.snapshot-3369/plugins/zerospu2/zerospu2.cpp
===================================================================
--- pcsx2.snapshot-3369.orig/plugins/zerospu2/zerospu2.cpp
+++ pcsx2.snapshot-3369/plugins/zerospu2/zerospu2.cpp
@@ -28,7 +28,9 @@
#include <stdlib.h>
#include "soundtouch/SoundTouch.h"
+#if defined(SOUNDTOUCH_VERSION_ID) & (SOUNDTOUCH_VERSION_ID >= 10400)
#include "soundtouch/WavFile.h"
+#endif
char libraryName[256];
@@ -74,7 +76,9 @@
// time stretch variables
soundtouch::SoundTouch* pSoundTouch=NULL;
+#if defined(SOUNDTOUCH_VERSION_ID) & (SOUNDTOUCH_VERSION_ID >= 10400)
extern WavOutFile* g_pWavRecord; // used for recording
+#endif
u64 s_GlobalTimeStamp = 0;
s32 s_nDurations[64]={0};
@@ -361,7 +365,9 @@
RemoveSound();
+#if defined(SOUNDTOUCH_VERSION_ID) & (SOUNDTOUCH_VERSION_ID >= 10400)
delete g_pWavRecord; g_pWavRecord = NULL;
+#endif
delete pSoundTouch; pSoundTouch = NULL;
for (u32 i = 0; i < ArraySize(s_pAudioBuffers); ++i)
Index: pcsx2.snapshot-3369/plugins/zerospu2/zeroworker.cpp
===================================================================
--- pcsx2.snapshot-3369.orig/plugins/zerospu2/zeroworker.cpp
+++ pcsx2.snapshot-3369/plugins/zerospu2/zeroworker.cpp
@@ -19,10 +19,14 @@
#include "zerospu2.h"
#include "zeroworker.h"
#include "soundtouch/SoundTouch.h"
+#if defined(SOUNDTOUCH_VERSION_ID) & (SOUNDTOUCH_VERSION_ID >= 10400)
#include "soundtouch/WavFile.h"
+#endif
s32 g_logsound = 0;
+#if defined(SOUNDTOUCH_VERSION_ID) & (SOUNDTOUCH_VERSION_ID >= 10400)
WavOutFile* g_pWavRecord=NULL; // used for recording
+#endif
const s32 f[5][2] = {
{ 0, 0 },
@@ -302,6 +306,7 @@
void LogRawSound(void* pleft, s32 leftstride, void* pright, s32 rightstride, s32 numsamples)
{
+#if defined(SOUNDTOUCH_VERSION_ID) & (SOUNDTOUCH_VERSION_ID >= 10400)
if (g_pWavRecord == NULL )
g_pWavRecord = new WavOutFile(RECORD_FILENAME, SAMPLE_RATE, 16, 2);
@@ -320,4 +325,5 @@
}
g_pWavRecord->write(&tempbuf[0], numsamples*2);
+#endif
}

View File

@ -1,4 +1,3 @@
01_rename_binary_generated.patch 01_rename_binary_generated.patch
02_update_default_path.patch 02_update_default_path.patch
05_move_data_to_config.patch 05_move_data_to_config.patch
21_use_legacy_soundtouch_13.patch

View File

@ -382,7 +382,7 @@ void cdvdReloadElfInfo(wxString elfoverride)
if (!ENABLE_LOADING_PS1_GAMES) if (!ENABLE_LOADING_PS1_GAMES)
Cpu->ThrowException( Exception::RuntimeError() Cpu->ThrowException( Exception::RuntimeError()
.SetDiagMsg(L"PSX game discs are not supported by PCSX2.") .SetDiagMsg(L"PSX game discs are not supported by PCSX2.")
.SetUserMsg(pxE( "Error:PsxDisc", .SetUserMsg(pxE( "!Notice:PsxDisc",
L"Playstation game discs are not supported by PCSX2. If you want to emulate PSX games " L"Playstation game discs are not supported by PCSX2. If you want to emulate PSX games "
L"then you'll have to download a PSX-specific emulator, such as ePSXe or PCSX.") L"then you'll have to download a PSX-specific emulator, such as ePSXe or PCSX.")
) )

View File

@ -411,7 +411,9 @@ void isoFile::Open( const wxString& srcfile )
// (and if numparts is incremented, elsn will get assigned accordingly) // (and if numparts is incremented, elsn will get assigned accordingly)
if (!Detect()) if (!Detect())
throw Exception::BadStream().SetUserMsg(wxLt("Unrecognized ISO file format.")); throw Exception::BadStream()
.SetUserMsg(L"Unrecognized ISO image file format")
.SetDiagMsg(_("ISO mounting failed: PCSX2 is unable to identify the ISO image type."));
if (!(m_flags & ISOFLAGS_BLOCKDUMP_V2)) if (!(m_flags & ISOFLAGS_BLOCKDUMP_V2))
{ {

View File

@ -274,7 +274,6 @@ set(pcsx2DebugToolsHeaders
# gui sources # gui sources
set(pcsx2GuiSources set(pcsx2GuiSources
gui/AdvancedDialog.cpp
gui/AppAssert.cpp gui/AppAssert.cpp
gui/AppConfig.cpp gui/AppConfig.cpp
gui/AppCorePlugins.cpp gui/AppCorePlugins.cpp
@ -338,7 +337,6 @@ set(pcsx2GuiSources
# gui headers # gui headers
set(pcsx2GuiHeaders set(pcsx2GuiHeaders
gui/AdvancedDialog.h
gui/App.h gui/App.h
gui/ApplyState.h gui/ApplyState.h
gui/AppAccelerators.h gui/AppAccelerators.h

View File

@ -400,7 +400,7 @@ struct Pcsx2Config
// when enabled uses BOOT2 injection, skipping sony bios splashes // when enabled uses BOOT2 injection, skipping sony bios splashes
UseBOOT2Injection :1, UseBOOT2Injection :1,
BackupSavestate :1,
// enables simulated ejection of memory cards when loading savestates // enables simulated ejection of memory cards when loading savestates
McdEnableEjection :1, McdEnableEjection :1,

View File

@ -556,7 +556,9 @@ extern tDMA_TAG *dmaGetAddr(u32 addr, bool write);
extern void hwIntcIrq(int n); extern void hwIntcIrq(int n);
extern void hwDmacIrq(int n); extern void hwDmacIrq(int n);
extern void FireMFIFOEmpty();
extern bool hwMFIFOWrite(u32 addr, const u128* data, uint size_qwc); extern bool hwMFIFOWrite(u32 addr, const u128* data, uint size_qwc);
extern void hwDmacSrcTadrInc(DMACh& dma);
extern bool hwDmacSrcChainWithStack(DMACh& dma, int id); extern bool hwDmacSrcChainWithStack(DMACh& dma, int id);
extern bool hwDmacSrcChain(DMACh& dma, int id); extern bool hwDmacSrcChain(DMACh& dma, int id);

View File

@ -260,16 +260,26 @@ void ElfObject::readFile()
if (rsize < data.GetSizeInBytes()) throw Exception::EndOfStream(filename); if (rsize < data.GetSizeInBytes()) throw Exception::EndOfStream(filename);
} }
static wxString GetMsg_InvalidELF()
{
return
_("Cannot load ELF binary image. The file may be corrupt or incomplete.") +
wxString(L"\n\n") +
_("If loading from an ISO image, this error may be caused by an unsupported ISO image type or bug in PCSX2 ISO image support.");
}
void ElfObject::checkElfSize(s64 elfsize) void ElfObject::checkElfSize(s64 elfsize)
{ {
if (elfsize > 0xfffffff) const wxChar* diagMsg = NULL;
throw Exception::BadStream(filename).SetBothMsgs(wxLt("Illegal ELF file size over 2GB!")); if (elfsize > 0xfffffff) diagMsg = L"Illegal ELF file size over 2GB!";
else if (elfsize == -1) diagMsg = L"ELF file does not exist!";
else if (elfsize == 0) diagMsg = L"Unexpected end of ELF file.";
if (elfsize == -1) if (diagMsg)
throw Exception::BadStream(filename).SetBothMsgs(wxLt("ELF file does not exist!")); throw Exception::BadStream(filename)
.SetDiagMsg(diagMsg)
if (elfsize == 0) .SetUserMsg(GetMsg_InvalidELF());
throw Exception::BadStream(filename).SetBothMsgs(wxLt("Unexpected end of ELF file."));
} }
u32 ElfObject::getCRC() u32 ElfObject::getCRC()

View File

@ -27,7 +27,6 @@ using std::min;
// A three-way toggle used to determine if the GIF is stalling (transferring) or done (finished). // A three-way toggle used to determine if the GIF is stalling (transferring) or done (finished).
// Should be a gifstate_t rather then int, but I don't feel like possibly interfering with savestates right now. // Should be a gifstate_t rather then int, but I don't feel like possibly interfering with savestates right now.
static int gifstate = GIF_STATE_READY; static int gifstate = GIF_STATE_READY;
static bool gifempty = false;
static bool gspath3done = false; static bool gspath3done = false;
@ -47,14 +46,14 @@ static __fi void clearFIFOstuff(bool full)
else else
CSRreg.FIFO = CSR_FIFO_EMPTY; CSRreg.FIFO = CSR_FIFO_EMPTY;
} }
extern bool SIGNAL_IMR_Pending;
void gsPath1Interrupt() void gsPath1Interrupt()
{ {
//DevCon.Warning("Path1 flush W %x, R %x", Path1WritePos, Path1ReadPos); //DevCon.Warning("Path1 flush W %x, R %x", Path1WritePos, Path1ReadPos);
if((gifRegs.stat.APATH <= GIF_APATH1 || (gifRegs.stat.IP3 == true && gifRegs.stat.APATH == GIF_APATH3)) && Path1WritePos > 0 && !gifRegs.stat.PSE) if((gifRegs.stat.APATH <= GIF_APATH1 || (gifRegs.stat.IP3 == true && gifRegs.stat.APATH == GIF_APATH3)) && Path1WritePos > 0 && !gifRegs.stat.PSE && SIGNAL_IMR_Pending == false)
{ {
gifRegs.stat.P1Q = false; gifRegs.stat.P1Q = false;
@ -62,7 +61,7 @@ void gsPath1Interrupt()
{ {
GetMTGS().PrepDataPacket(GIF_PATH_1, size); GetMTGS().PrepDataPacket(GIF_PATH_1, size);
//DevCon.Warning("Flush Size = %x", size); //DevCon.Warning("Flush Size = %x", size);
while(size > 0) while(size > 0 && SIGNAL_IMR_Pending == false)
{ {
uint count = GIFPath_CopyTag(GIF_PATH_1, ((u128*)Path1Buffer) + Path1ReadPos, size); uint count = GIFPath_CopyTag(GIF_PATH_1, ((u128*)Path1Buffer) + Path1ReadPos, size);
Path1ReadPos += count; Path1ReadPos += count;
@ -79,13 +78,18 @@ void gsPath1Interrupt()
if(Path1ReadPos == Path1WritePos) if(Path1ReadPos == Path1WritePos)
{ {
Path1WritePos = Path1ReadPos = 0; Path1WritePos = Path1ReadPos = 0;
}
else
{
//DevCon.Warning("Queue quitting early due to signal or EOP %x", size);
gifRegs.stat.P1Q = true;
} }
} }
} }
else else
{ {
if(gifRegs.stat.PSE) DevCon.Warning("Path1 paused by GIF_CTRL"); if(gifRegs.stat.PSE) DevCon.Warning("Path1 paused by GIF_CTRL");
DevCon.Warning("Looping??? IP3 %x APATH %x OPH %x", gifRegs.stat.IP3, gifRegs.stat.APATH, gifRegs.stat.OPH); //DevCon.Warning("Looping??? IP3 %x APATH %x OPH %x", gifRegs.stat.IP3, gifRegs.stat.APATH, gifRegs.stat.OPH);
//if(!(cpuRegs.interrupt & (1<<28)) && Path1WritePos > 0)CPU_INT(28, 128); //if(!(cpuRegs.interrupt & (1<<28)) && Path1WritePos > 0)CPU_INT(28, 128);
} }
@ -97,6 +101,13 @@ __fi void gsInterrupt()
{ {
GIF_LOG("gsInterrupt caught!"); GIF_LOG("gsInterrupt caught!");
if (dmacRegs.ctrl.MFD == MFD_GIF) // GIF MFIFO
{
//Console.WriteLn("GIF MFIFO");
gifMFIFOInterrupt();
return;
}
if(SIGNAL_IMR_Pending == true) if(SIGNAL_IMR_Pending == true)
{ {
//DevCon.Warning("Path 3 Paused"); //DevCon.Warning("Path 3 Paused");
@ -234,6 +245,7 @@ bool CheckPaths(int Channel)
{ {
if((vif1.cmd & 0x7f) != 0x51 || gifRegs.stat.P1Q == true) if((vif1.cmd & 0x7f) != 0x51 || gifRegs.stat.P1Q == true)
{ {
//DevCon.Warning("GIF Stall 1 P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs.stat.P1Q, gifRegs.stat.P2Q, gifRegs.stat.APATH, GSTransferStatus.PTH3, vif1.cmd);
gifRegs.stat.IP3 = true; gifRegs.stat.IP3 = true;
if(gifRegs.stat.P1Q) gsPath1Interrupt(); if(gifRegs.stat.P1Q) gsPath1Interrupt();
CPU_INT(DMAC_GIF, 16); CPU_INT(DMAC_GIF, 16);
@ -246,6 +258,7 @@ bool CheckPaths(int Channel)
//This should cover both scenarios, as DIRECTHL doesn't gain priority when image mode is running (PENDINGIMAGE_MODE == fininshed). //This should cover both scenarios, as DIRECTHL doesn't gain priority when image mode is running (PENDINGIMAGE_MODE == fininshed).
if((gifRegs.stat.P1Q == true || gifRegs.stat.P2Q == true) || (gifRegs.stat.APATH > GIF_APATH_IDLE && gifRegs.stat.APATH < GIF_APATH3)) if((gifRegs.stat.P1Q == true || gifRegs.stat.P2Q == true) || (gifRegs.stat.APATH > GIF_APATH_IDLE && gifRegs.stat.APATH < GIF_APATH3))
{ {
//DevCon.Warning("GIF Stall 2 P1Q %x P2Q %x APATH %x PTH3 %x vif1cmd %x", gifRegs.stat.P1Q, gifRegs.stat.P2Q, gifRegs.stat.APATH, GSTransferStatus.PTH3, vif1.cmd);
gifRegs.stat.IP3 = true; gifRegs.stat.IP3 = true;
CPU_INT(DMAC_GIF, 16); CPU_INT(DMAC_GIF, 16);
return false; return false;
@ -430,61 +443,90 @@ void dmaGIF()
} }
} }
if (dmacRegs.ctrl.MFD == MFD_GIF) // GIF MFIFO
{
//Console.WriteLn("GIF MFIFO");
gifMFIFOInterrupt();
return;
}
GIFdma(); gsInterrupt();
}
static u16 QWCinGIFMFIFO(u32 DrainADDR)
{
u32 ret;
GIF_LOG("GIF MFIFO Requesting %x QWC from the MFIFO Base %x, SPR MADR %x Drain %x", gifch.qwc, dmacRegs.rbor.ADDR, spr0ch.madr, DrainADDR);
//Calculate what we have in the fifo.
if(DrainADDR <= spr0ch.madr)
{
//Drain is below the tadr, calculate the difference between them
ret = (spr0ch.madr - DrainADDR) >> 4;
}
else
{
u32 limit = dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16;
//Drain is higher than SPR so it has looped round,
//calculate from base to the SPR tag addr and what is left in the top of the ring
ret = ((spr0ch.madr - dmacRegs.rbor.ADDR) + (limit - DrainADDR)) >> 4;
}
GIF_LOG("%x Available of the %x requested", ret, gifch.qwc);
if((s32)ret < 0) DevCon.Warning("GIF Returning %x!", ret);
return ret;
} }
// called from only one location, so forceinline it: // called from only one location, so forceinline it:
static __fi bool mfifoGIFrbTransfer() static __fi bool mfifoGIFrbTransfer()
{ {
u32 mfifoqwc = min(gifqwc, (u32)gifch.qwc); u16 mfifoqwc = min(QWCinGIFMFIFO(gifch.madr), gifch.qwc);
u32 *src; u32 *src;
if(mfifoqwc == 0) return true; //Lets skip all this, we don't have the data
GetMTGS().PrepDataPacket(GIF_PATH_3, mfifoqwc); GetMTGS().PrepDataPacket(GIF_PATH_3, mfifoqwc);
// TODO (minor optimization): The new GIFpath parser can do rather efficient wrapping of // TODO (minor optimization): The new GIFpath parser can do rather efficient wrapping of
// its own internally now. We just need to groom a version of it that can wrap around MFIFO // its own internally now. We just need to groom a version of it that can wrap around MFIFO
// memory similarly to how it wraps VU1 memory on PATH1. // memory similarly to how it wraps VU1 memory on PATH1.
GIF_LOG("MFIFO QWC to Transfer %x", mfifoqwc);
/* Check if the transfer should wrap around the ring buffer */ /* Check if the transfer should wrap around the ring buffer */
if ((gifch.madr + mfifoqwc * 16) > (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16)) if ( (gifch.madr + (mfifoqwc * 16)) > (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16))
{ {
uint s1 = ((dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16) - gifch.madr) >> 4; uint s1 = ((dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16) - gifch.madr) >> 4;
uint s2 = (mfifoqwc - s1); uint s2 = (mfifoqwc - s1);
GIF_LOG("Split transfer doing %x QWC of %x Total QWC", s1, mfifoqwc);
/* it does (wrap around), so first copy 's1' bytes from 'addr' to 'data' */ /* it does (wrap around), so first copy 's1' bytes from 'addr' to 'data' */
/* and second copy 's2' bytes from 'maddr' to '&data[s1]' */ /* and second copy 's2' bytes from 'maddr' to '&data[s1]' */
gifch.madr = dmacRegs.rbor.ADDR + (gifch.madr & dmacRegs.rbsr.RMSK);
src = (u32*)PSM(gifch.madr); src = (u32*)PSM(gifch.madr);
if (src == NULL) return false; if (src == NULL) return false;
uint copied = GIFPath_CopyTag(GIF_PATH_3, (u128*)src, s1); uint copied = GIFPath_CopyTag(GIF_PATH_3, (u128*)src, s1);
if (copied == s1) // but only copy second if first didn't abort prematurely for some reason. if (copied == s1) // but only copy second if first didn't abort prematurely for some reason.
{ {
GIF_LOG("Transferring last %x QWC", s2);
src = (u32*)PSM(dmacRegs.rbor.ADDR); src = (u32*)PSM(dmacRegs.rbor.ADDR);
gifch.madr = dmacRegs.rbor.ADDR;
if (src == NULL) return false; if (src == NULL) return false;
copied += GIFPath_CopyTag(GIF_PATH_3, (u128*)src, s2); copied += GIFPath_CopyTag(GIF_PATH_3, (u128*)src, s2);
} }
mfifoqwc = copied; mfifoqwc = copied;
GIF_LOG("Copied %x QWC, %x QWC Left", mfifoqwc, gifch.qwc);
} }
else else
{ {
GIF_LOG("Direct MFIFO transfer doing %x Total QWC", mfifoqwc);
/* it doesn't, so just transfer 'qwc*16' words from 'gifch.madr' to GS */ /* it doesn't, so just transfer 'qwc*16' words from 'gifch.madr' to GS */
gifch.madr = dmacRegs.rbor.ADDR + (gifch.madr & dmacRegs.rbsr.RMSK);
src = (u32*)PSM(gifch.madr); src = (u32*)PSM(gifch.madr);
if (src == NULL) return false; if (src == NULL) return false;
mfifoqwc = GIFPath_CopyTag(GIF_PATH_3, (u128*)src, mfifoqwc); mfifoqwc = GIFPath_CopyTag(GIF_PATH_3, (u128*)src, mfifoqwc);
gifch.madr = dmacRegs.rbor.ADDR + (gifch.madr & dmacRegs.rbsr.RMSK); GIF_LOG("%X QWC Copied direct %x QWC Left", mfifoqwc, gifch.qwc);
} }
GetMTGS().SendDataPacket(); GetMTGS().SendDataPacket();
gifqwc -= mfifoqwc; //gifqwc -= mfifoqwc;
mfifocycles += (mfifoqwc) * 2; /* guessing */
return true; return true;
} }
@ -496,14 +538,19 @@ static __fi bool mfifoGIFchain()
if (gifch.qwc == 0) return true; if (gifch.qwc == 0) return true;
if (gifch.madr >= dmacRegs.rbor.ADDR && if (gifch.madr >= dmacRegs.rbor.ADDR &&
gifch.madr <= (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK)) gifch.madr <= (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16))
{ {
if (!mfifoGIFrbTransfer()) return false; bool ret = true;
// if(gifch.madr == (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16)) DevCon.Warning("Edge GIF");
if (!mfifoGIFrbTransfer()) ret = false;
if(QWCinGIFMFIFO(gifch.madr) == 0) gifstate |= GIF_STATE_EMPTY;
return ret;
} }
else else
{ {
int mfifoqwc; int mfifoqwc;
GIF_LOG("Non-MFIFO Location transfer doing %x Total QWC", gifch.qwc);
tDMA_TAG *pMem = dmaGetAddr(gifch.madr, false); tDMA_TAG *pMem = dmaGetAddr(gifch.madr, false);
if (pMem == NULL) return false; if (pMem == NULL) return false;
@ -528,12 +575,13 @@ void mfifoGIFtransfer(int qwc)
if(qwc > 0 ) if(qwc > 0 )
{ {
gifqwc += qwc; if ((gifstate & GIF_STATE_EMPTY) && !(cpuRegs.interrupt & (1<<DMAC_MFIFO_GIF)))
{
if (!(gifstate & GIF_STATE_EMPTY)) return; if(gifch.chcr.STR == true)CPU_INT(DMAC_MFIFO_GIF, 4);
// if (gifempty == false) return; gifstate &= ~GIF_STATE_EMPTY;
gifstate &= ~GIF_STATE_EMPTY; }
gifempty = false; gifRegs.stat.FQC = 16;
return;
} }
if (gifRegs.ctrl.PSE) // temporarily stop if (gifRegs.ctrl.PSE) // temporarily stop
@ -545,15 +593,6 @@ void mfifoGIFtransfer(int qwc)
if (gifch.qwc == 0) if (gifch.qwc == 0)
{ {
if (gifch.tadr == spr0ch.madr)
{
//if( gifqwc > 1 ) DevCon.WriteLn("gif mfifo tadr==madr but qwc = %d", gifqwc);
hwDmacIrq(DMAC_MFIFO_EMPTY);
gifstate |= GIF_STATE_EMPTY;
gifempty = true;
return;
}
gifch.tadr = qwctag(gifch.tadr); gifch.tadr = qwctag(gifch.tadr);
ptag = dmaGetAddr(gifch.tadr, false); ptag = dmaGetAddr(gifch.tadr, false);
@ -565,42 +604,10 @@ void mfifoGIFtransfer(int qwc)
GIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx mfifo qwc = %x spr0 madr = %x", GIF_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx mfifo qwc = %x spr0 madr = %x",
ptag[1]._u32, ptag[0]._u32, gifch.qwc, ptag->ID, gifch.madr, gifch.tadr, gifqwc, spr0ch.madr); ptag[1]._u32, ptag[0]._u32, gifch.qwc, ptag->ID, gifch.madr, gifch.tadr, gifqwc, spr0ch.madr);
gifqwc--; gspath3done = hwDmacSrcChainWithStack(gifch, ptag->ID);
switch (ptag->ID) if(gspath3done == true) gifstate = GIF_STATE_DONE;
{ else gifstate = GIF_STATE_READY;
case TAG_REFE: // Refe - Transfer Packet According to ADDR field
gifch.tadr = qwctag(gifch.tadr + 16);
gifstate = GIF_STATE_DONE; //End Transfer
break;
case TAG_CNT: // CNT - Transfer QWC following the tag.
gifch.madr = qwctag(gifch.tadr + 16); //Set MADR to QW after Tag
gifch.tadr = qwctag(gifch.madr + (gifch.qwc << 4)); //Set TADR to QW following the data
gifstate = GIF_STATE_READY;
break;
case TAG_NEXT: // Next - Transfer QWC following tag. TADR = ADDR
{
u32 temp = gifch.madr; //Temporarily Store ADDR
gifch.madr = qwctag(gifch.tadr + 16); //Set MADR to QW following the tag
gifch.tadr = temp; //Copy temporarily stored ADDR to Tag
gifstate = GIF_STATE_READY;
break;
}
case TAG_REF: // Ref - Transfer QWC from ADDR field
case TAG_REFS: // Refs - Transfer QWC from ADDR field (Stall Control)
gifch.tadr = qwctag(gifch.tadr + 16); //Set TADR to next tag
gifstate = GIF_STATE_READY;
break;
case TAG_END: // End - Transfer QWC following the tag
gifch.madr = qwctag(gifch.tadr + 16); //Set MADR to data following the tag
gifch.tadr = qwctag(gifch.madr + (gifch.qwc << 4)); //Set TADR to QW following the data
gifstate = GIF_STATE_DONE; //End Transfer
break;
}
if ((gifch.chcr.TIE) && (ptag->IRQ)) if ((gifch.chcr.TIE) && (ptag->IRQ))
{ {
@ -608,7 +615,8 @@ void mfifoGIFtransfer(int qwc)
gifstate = GIF_STATE_DONE; gifstate = GIF_STATE_DONE;
gifmfifoirq = true; gifmfifoirq = true;
} }
} if (QWCinGIFMFIFO(gifch.tadr) == 0) gifstate |= GIF_STATE_EMPTY;
}
if (!mfifoGIFchain()) if (!mfifoGIFchain())
{ {
@ -616,7 +624,7 @@ void mfifoGIFtransfer(int qwc)
gifstate = GIF_STATE_STALL; gifstate = GIF_STATE_STALL;
} }
if ((gifch.qwc == 0) && (gifstate & GIF_STATE_DONE)) gifstate = GIF_STATE_STALL; if ((gifch.qwc == 0) && (gifstate & GIF_STATE_DONE)) gifstate |= GIF_STATE_STALL;
CPU_INT(DMAC_MFIFO_GIF,mfifocycles); CPU_INT(DMAC_MFIFO_GIF,mfifocycles);
SPR_LOG("mfifoGIFtransfer end %x madr %x, tadr %x", gifch.chcr._u32, gifch.madr, gifch.tadr); SPR_LOG("mfifoGIFtransfer end %x madr %x, tadr %x", gifch.chcr._u32, gifch.madr, gifch.tadr);
@ -624,9 +632,15 @@ void mfifoGIFtransfer(int qwc)
void gifMFIFOInterrupt() void gifMFIFOInterrupt()
{ {
//Console.WriteLn("gifMFIFOInterrupt"); GIF_LOG("gifMFIFOInterrupt");
mfifocycles = 0; mfifocycles = 0;
if (dmacRegs.ctrl.MFD != MFD_GIF)
{
DevCon.Warning("Not in GIF MFIFO mode! Stopping GIF MFIFO");
return;
}
if(SIGNAL_IMR_Pending == true) if(SIGNAL_IMR_Pending == true)
{ {
//DevCon.Warning("Path 3 Paused"); //DevCon.Warning("Path 3 Paused");
@ -634,13 +648,20 @@ void gifMFIFOInterrupt()
return; return;
} }
if(GSTransferStatus.PTH3 == STOPPED_MODE && gifRegs.stat.APATH == GIF_APATH3 ) if(GSTransferStatus.PTH3 >= PENDINGSTOP_MODE && gifRegs.stat.APATH == GIF_APATH3 )
{ {
gifRegs.stat.OPH = false; gifRegs.stat.OPH = false;
GSTransferStatus.PTH3 = STOPPED_MODE;
gifRegs.stat.APATH = GIF_APATH_IDLE; gifRegs.stat.APATH = GIF_APATH_IDLE;
if(gifRegs.stat.P1Q) gsPath1Interrupt(); if(gifRegs.stat.P1Q) gsPath1Interrupt();
} }
if((gifstate & GIF_STATE_EMPTY))
{
FireMFIFOEmpty();
if(!(gifstate & GIF_STATE_STALL)) return;
}
if(CheckPaths(11) == false) return; if(CheckPaths(11) == false) return;
if (!(gifch.chcr.STR)) if (!(gifch.chcr.STR))
@ -652,16 +673,13 @@ void gifMFIFOInterrupt()
if (!(gifstate & GIF_STATE_STALL)) if (!(gifstate & GIF_STATE_STALL))
{ {
if (gifqwc <= 0) if (QWCinGIFMFIFO(gifch.tadr) == 0)
{ {
//Console.WriteLn("Empty");
hwDmacIrq(DMAC_MFIFO_EMPTY);
gifstate |= GIF_STATE_EMPTY; gifstate |= GIF_STATE_EMPTY;
gifempty = true; CPU_INT(DMAC_MFIFO_GIF, 4);
gifRegs.stat.IMT = false;
return; return;
} }
mfifoGIFtransfer(0); mfifoGIFtransfer(0);
return; return;
} }
@ -685,6 +703,7 @@ void gifMFIFOInterrupt()
gifch.chcr.STR = false; gifch.chcr.STR = false;
gifstate = GIF_STATE_READY; gifstate = GIF_STATE_READY;
hwDmacIrq(DMAC_GIF); hwDmacIrq(DMAC_GIF);
GIF_LOG("gifMFIFO End");
clearFIFOstuff(false); clearFIFOstuff(false);
} }
@ -696,7 +715,6 @@ void SaveStateBase::gifFreeze()
Freeze( gifqwc ); Freeze( gifqwc );
Freeze( gspath3done ); Freeze( gspath3done );
Freeze( gscycles ); Freeze( gscycles );
//Freeze(gifempty);
// Note: mfifocycles is not a persistent var, so no need to save it here. // Note: mfifocycles is not a persistent var, so no need to save it here.
int bufsize = Path1WritePos - Path1ReadPos; int bufsize = Path1WritePos - Path1ReadPos;

View File

@ -26,7 +26,7 @@ enum gifstate_t
enum GSTransferModes //0 = Image Mode (DirectHL), 1 = transferring, 2 = Stopped at End of Packet enum GSTransferModes //0 = Image Mode (DirectHL), 1 = transferring, 2 = Stopped at End of Packet
{ {
PENDINGIMAGE_MODE = 0, WAITING_MODE = 0,
IMAGE_MODE = 1, IMAGE_MODE = 1,
TRANSFER_MODE = 2, TRANSFER_MODE = 2,
PENDINGSTOP_MODE = 3, PENDINGSTOP_MODE = 3,

View File

@ -130,6 +130,14 @@ void hwDmacIrq(int n)
if(psHu16(DMAC_STAT+2) & (1<<n))cpuTestDMACInts(); if(psHu16(DMAC_STAT+2) & (1<<n))cpuTestDMACInts();
} }
void FireMFIFOEmpty()
{
SPR_LOG("VIF MFIFO Data Empty");
hwDmacIrq(DMAC_MFIFO_EMPTY);
if (dmacRegs.ctrl.MFD == MFD_VIF1) vif1Regs.stat.FQC = 0;
else if (dmacRegs.ctrl.MFD == MFD_GIF) gifRegs.stat.FQC = 0;
}
// Write 'size' bytes to memory address 'addr' from 'data'. // Write 'size' bytes to memory address 'addr' from 'data'.
__ri bool hwMFIFOWrite(u32 addr, const u128* data, uint qwc) __ri bool hwMFIFOWrite(u32 addr, const u128* data, uint qwc)
{ {
@ -137,6 +145,7 @@ __ri bool hwMFIFOWrite(u32 addr, const u128* data, uint qwc)
pxAssume((dmacRegs.rbor.ADDR & 15) == 0); pxAssume((dmacRegs.rbor.ADDR & 15) == 0);
pxAssume((addr & 15) == 0); pxAssume((addr & 15) == 0);
if(qwc > ((dmacRegs.rbsr.RMSK + 16) >> 4)) DevCon.Warning("MFIFO Write bigger than MFIFO! QWC=%x FifoSize=%x", qwc, ((dmacRegs.rbsr.RMSK + 16) >> 4));
// DMAC Address resolution: FIFO can be placed anywhere in the *physical* memory map // DMAC Address resolution: FIFO can be placed anywhere in the *physical* memory map
// for the PS2. Its probably a serious error for a PS2 app to have the buffer cross // for the PS2. Its probably a serious error for a PS2 app to have the buffer cross
// valid/invalid page areas of ram, so realistically we only need to test the base address // valid/invalid page areas of ram, so realistically we only need to test the base address
@ -162,13 +171,15 @@ __ri bool hwMFIFOWrite(u32 addr, const u128* data, uint qwc)
__ri bool hwDmacSrcChainWithStack(DMACh& dma, int id) { __ri bool hwDmacSrcChainWithStack(DMACh& dma, int id) {
switch (id) { switch (id) {
case TAG_REFE: // Refe - Transfer Packet According to ADDR field case TAG_REFE: // Refe - Transfer Packet According to ADDR field
dma.tadr += 16;
//End Transfer //End Transfer
return true; return true;
case TAG_CNT: // CNT - Transfer QWC following the tag. case TAG_CNT: // CNT - Transfer QWC following the tag.
// Set MADR to QW afer tag, and set TADR to QW following the data. // Set MADR to QW afer tag, and set TADR to QW following the data.
dma.madr = dma.tadr + 16; dma.tadr += 16;
dma.tadr = dma.madr + (dma.qwc << 4); dma.madr = dma.tadr;
//dma.tadr = dma.madr + (dma.qwc << 4);
return false; return false;
case TAG_NEXT: // Next - Transfer QWC following tag. TADR = ADDR case TAG_NEXT: // Next - Transfer QWC following tag. TADR = ADDR
@ -267,6 +278,33 @@ __ri bool hwDmacSrcChainWithStack(DMACh& dma, int id) {
return false; return false;
} }
/********TADR NOTES***********
From what i've gathered from testing tadr increment stuff (with CNT) is that we might not be 100% accurate in what
increments it and what doesnt. Previously we presumed REFE and END didn't increment the tag, but SIF and IPU never
liked this.
From what i've deduced, REFE does in fact increment, but END doesn't, after much testing, i've concluded this is how
we can standardize DMA chains, so i've modified the code to work like this. The below function controls the increment
of the TADR along with the MADR on VIF, GIF and SPR1 when using the CNT tag, the others don't use it yet, but they
can probably be modified to do so now.
Reason for this:- Many games (such as clock tower 3 and FFX Videos) watched the TADR to see when a transfer has finished,
so we need to simulate this wherever we can! Even the FFX video gets corruption and tries to fire multiple DMA Kicks
if this doesnt happen, which was the reasoning for the hacked up SPR timing we had, that is no longer required.
-Refraction
******************************/
void hwDmacSrcTadrInc(DMACh& dma)
{
u16 tagid = (dma.chcr.TAG >> 12) & 0x7;
if(tagid == TAG_CNT)
{
dma.tadr = dma.madr;
}
}
bool hwDmacSrcChain(DMACh& dma, int id) bool hwDmacSrcChain(DMACh& dma, int id)
{ {
u32 temp; u32 temp;
@ -274,13 +312,14 @@ bool hwDmacSrcChain(DMACh& dma, int id)
switch (id) switch (id)
{ {
case TAG_REFE: // Refe - Transfer Packet According to ADDR field case TAG_REFE: // Refe - Transfer Packet According to ADDR field
dma.tadr += 16;
// End the transfer. // End the transfer.
return true; return true;
case TAG_CNT: // CNT - Transfer QWC following the tag. case TAG_CNT: // CNT - Transfer QWC following the tag.
// Set MADR to QW after the tag, and TADR to QW following the data. // Set MADR to QW after the tag, and TADR to QW following the data.
dma.madr = dma.tadr + 16; dma.madr = dma.tadr + 16;
dma.tadr = dma.madr + (dma.qwc << 4); dma.tadr = dma.madr;
return false; return false;
case TAG_NEXT: // Next - Transfer QWC following tag. TADR = ADDR case TAG_NEXT: // Next - Transfer QWC following tag. TADR = ADDR
@ -305,3 +344,4 @@ bool hwDmacSrcChain(DMACh& dma, int id)
return false; return false;
} }

View File

@ -308,6 +308,7 @@ enum EERegisterAddresses
DMAC_RBSR = 0x1000E040, DMAC_RBSR = 0x1000E040,
DMAC_RBOR = 0x1000E050, DMAC_RBOR = 0x1000E050,
DMAC_STADR = 0x1000E060, DMAC_STADR = 0x1000E060,
DMAC_FAKESTAT = 0x1000E100, //Midway, you're idiots (checked this in the MK Deception ELF!) (Refraction)
INTC_STAT = 0x1000F000, INTC_STAT = 0x1000F000,
INTC_MASK = 0x1000F010, INTC_MASK = 0x1000F010,

View File

@ -440,10 +440,9 @@ static __fi bool ipuVDEC(u32 val)
// very choppy (basically only decoding/updating every 30th frame or so). So yeah, // very choppy (basically only decoding/updating every 30th frame or so). So yeah,
// someone with knowledge on the subject please feel free to explain this one. :) --air // someone with knowledge on the subject please feel free to explain this one. :) --air
ipuRegs.cmd.DATA &= 0xFFFF; // The upper bits are the "length" of the decoded command, where the lower is the address.
ipuRegs.cmd.DATA |= 0x10000; // This is due to differences with IPU and the MPEG standard. See get_macroblock_address_increment().
//ipuRegs.cmd.DATA = (ipuRegs.cmd.DATA & 0xFFFF) | ((decoder.bitstream_bits + 16) << 16);
ipuRegs.ctrl.ECD = (ipuRegs.cmd.DATA == 0); ipuRegs.ctrl.ECD = (ipuRegs.cmd.DATA == 0);
case 1: case 1:
@ -909,7 +908,7 @@ __noinline void IPUWorker()
// CHECK!: IPU0dma remains when IDEC is done, so we need to clear it // CHECK!: IPU0dma remains when IDEC is done, so we need to clear it
// Check Mana Khemia 1 "off campus" to trigger a GUST IDEC messup. // Check Mana Khemia 1 "off campus" to trigger a GUST IDEC messup.
// This hackfixes it :/ // This hackfixes it :/
if (ipu0dma.qwc > 0 && ipu0dma.chcr.STR) ipu0Interrupt(); //if (ipu0dma.qwc > 0 && ipu0dma.chcr.STR) ipu0Interrupt();
break; break;
case SCE_IPU_BDEC: case SCE_IPU_BDEC:

View File

@ -109,11 +109,11 @@ int IPU_Fifo_Output::write(const u32 *value, uint size)
pxAssumeMsg(size>0, "Invalid size==0 when calling IPU_Fifo_Output::write"); pxAssumeMsg(size>0, "Invalid size==0 when calling IPU_Fifo_Output::write");
uint origsize = size; uint origsize = size;
do { /*do {*/
IPU0dma(); //IPU0dma();
uint transsize = min(size, 8 - (uint)ipuRegs.ctrl.OFC); uint transsize = min(size, 8 - (uint)ipuRegs.ctrl.OFC);
if(!transsize) break; if(!transsize) return 0;
ipuRegs.ctrl.OFC = transsize; ipuRegs.ctrl.OFC = transsize;
size -= transsize; size -= transsize;
@ -124,7 +124,7 @@ int IPU_Fifo_Output::write(const u32 *value, uint size)
value += 4; value += 4;
--transsize; --transsize;
} }
} while(true); /*} while(true);*/
return origsize - size; return origsize - size;
} }

View File

@ -42,21 +42,6 @@ void SaveStateBase::ipuDmaFreeze()
Freeze(IPU1Status); Freeze(IPU1Status);
} }
static __fi bool ipuDmacPartialChain(tDMA_TAG tag)
{
switch (tag.ID)
{
case TAG_REFE: // refe
ipu1dma.tadr += 16;
return true;
case TAG_END: // end
ipu1dma.tadr = ipu1dma.madr;
return true;
}
return false;
}
static __fi void ipuDmacSrcChain() static __fi void ipuDmacSrcChain()
{ {
switch (IPU1Status.ChainMode) switch (IPU1Status.ChainMode)
@ -82,7 +67,7 @@ static __fi void ipuDmacSrcChain()
break; break;
case TAG_END: // end case TAG_END: // end
ipu1dma.tadr = ipu1dma.madr; //ipu1dma.tadr = ipu1dma.madr;
IPU1Status.DMAFinished = true; IPU1Status.DMAFinished = true;
break; break;
} }
@ -136,15 +121,12 @@ static __fi int IPU1chain() {
ipu1dma.qwc -= qwc; ipu1dma.qwc -= qwc;
totalqwc += qwc; totalqwc += qwc;
} }
//Update TADR etc
if(IPU1Status.DMAMode == DMA_MODE_CHAIN) ipuDmacSrcChain();
if( ipu1dma.qwc == 0) if( ipu1dma.qwc == 0)
{
//Update TADR etc
if(IPU1Status.DMAMode == DMA_MODE_CHAIN) ipuDmacSrcChain();
//If the transfer has finished or we have room in the FIFO, schedule to the interrupt code.
//No data left
IPU1Status.InProgress = false; IPU1Status.InProgress = false;
} //If we still have data the commands should pull this across when need be.
return totalqwc; return totalqwc;
} }
@ -238,7 +220,8 @@ int IPU1dma()
break; break;
case TAG_CNT: // cnt case TAG_CNT: // cnt
ipu1dma.madr = ipu1dma.tadr + 16; ipu1dma.tadr += 16;
ipu1dma.madr = ipu1dma.tadr;
IPU_LOG("Tag should end on %x", ipu1dma.madr + ipu1dma.qwc * 16); IPU_LOG("Tag should end on %x", ipu1dma.madr + ipu1dma.qwc * 16);
//ipu1dma.tadr = ipu1dma.madr + (ipu1dma.qwc * 16); //ipu1dma.tadr = ipu1dma.madr + (ipu1dma.qwc * 16);
// Set the taddr to the next tag // Set the taddr to the next tag
@ -262,7 +245,7 @@ int IPU1dma()
case TAG_END: // end case TAG_END: // end
// do not change tadr // do not change tadr
ipu1dma.madr = ipu1dma.tadr + 16; ipu1dma.madr = ipu1dma.tadr + 16;
ipu1dma.tadr += 16; //ipu1dma.tadr += 16;
IPU_LOG("Tag should end on %x", ipu1dma.madr + ipu1dma.qwc * 16); IPU_LOG("Tag should end on %x", ipu1dma.madr + ipu1dma.qwc * 16);
break; break;
@ -310,15 +293,23 @@ int IPU1dma()
return totalqwc; return totalqwc;
} }
int IPU0dma() void IPU0dma()
{ {
if(!ipuRegs.ctrl.OFC) return 0; if(!ipuRegs.ctrl.OFC)
{
IPU_INT_FROM( 64 );
IPUProcessInterrupt();
return;
}
int readsize; int readsize;
tDMA_TAG* pMem; tDMA_TAG* pMem;
if ((!(ipu0dma.chcr.STR) || (cpuRegs.interrupt & (1 << DMAC_FROM_IPU))) || (ipu0dma.qwc == 0)) if ((!(ipu0dma.chcr.STR) || (cpuRegs.interrupt & (1 << DMAC_FROM_IPU))) || (ipu0dma.qwc == 0))
return 0; {
DevCon.Warning("How??");
return;
}
pxAssert(!(ipu0dma.chcr.TTE)); pxAssert(!(ipu0dma.chcr.TTE));
@ -362,10 +353,11 @@ int IPU0dma()
//This was IPU_INT_FROM(readsize*BIAS ); //This was IPU_INT_FROM(readsize*BIAS );
//This broke vids in Digital Devil Saga //This broke vids in Digital Devil Saga
//Note that interrupting based on totalsize is just guessing.. //Note that interrupting based on totalsize is just guessing..
IPU_INT_FROM( readsize * BIAS );
} }
IPU_INT_FROM( readsize * BIAS );
if(ipuRegs.ctrl.IFC > 0) IPUProcessInterrupt();
return readsize; //return readsize;
} }
__fi void dmaIPU0() // fromIPU __fi void dmaIPU0() // fromIPU
@ -381,7 +373,10 @@ __fi void dmaIPU0() // fromIPU
hwDmacIrq(DMAC_FROM_IPU); hwDmacIrq(DMAC_FROM_IPU);
} }
IPUProcessInterrupt(); IPU_INT_FROM( 64 );
} }
__fi void dmaIPU1() // toIPU __fi void dmaIPU1() // toIPU
@ -450,6 +445,11 @@ void ipu0Interrupt()
{ {
IPU_LOG("ipu0Interrupt: %x", cpuRegs.cycle); IPU_LOG("ipu0Interrupt: %x", cpuRegs.cycle);
if(ipu0dma.qwc > 0)
{
IPU0dma();
return;
}
if (g_nDMATransfer.FIREINT0) if (g_nDMATransfer.FIREINT0)
{ {
g_nDMATransfer.FIREINT0 = false; g_nDMATransfer.FIREINT0 = false;

View File

@ -87,7 +87,7 @@ extern void ipu1Interrupt();
extern void dmaIPU0(); extern void dmaIPU0();
extern void dmaIPU1(); extern void dmaIPU1();
extern int IPU0dma(); extern void IPU0dma();
extern int IPU1dma(); extern int IPU1dma();
extern void ipuDmaReset(); extern void ipuDmaReset();

View File

@ -135,14 +135,13 @@ int get_macroblock_modes()
{ {
macroblock_modes |= GETBITS(2) * MOTION_TYPE_BASE; macroblock_modes |= GETBITS(2) * MOTION_TYPE_BASE;
} }
return (macroblock_modes | (tab->len << 16));
return macroblock_modes;
} }
else if (decoder.frame_pred_frame_dct) else if (decoder.frame_pred_frame_dct)
{ {
/* if (! (macroblock_modes & MACROBLOCK_INTRA)) */ /* if (! (macroblock_modes & MACROBLOCK_INTRA)) */
macroblock_modes |= MC_FRAME; macroblock_modes |= MC_FRAME;
return macroblock_modes; return (macroblock_modes | (tab->len << 16));
} }
else else
{ {
@ -155,15 +154,15 @@ int get_macroblock_modes()
intra: intra:
macroblock_modes |= GETBITS(1) * DCT_TYPE_INTERLACED; macroblock_modes |= GETBITS(1) * DCT_TYPE_INTERLACED;
} }
return (macroblock_modes | (tab->len << 16));
return macroblock_modes;
} }
case D_TYPE: case D_TYPE:
macroblock_modes = GETBITS(1); macroblock_modes = GETBITS(1);
//I suspect (as this is actually a 2 bit command) that this should be getbits(2)
//additionally, we arent dumping any bits here when i think we should be, need a game to test. (Refraction)
if (macroblock_modes == 0) return 0; // error if (macroblock_modes == 0) return 0; // error
return MACROBLOCK_INTRA; return (MACROBLOCK_INTRA | (1 << 16));
default: default:
return 0; return 0;
@ -222,14 +221,15 @@ int __fi get_motion_delta(const int f_code)
sign = SBITS(1); sign = SBITS(1);
DUMPBITS(1); DUMPBITS(1);
return (delta ^ sign) - sign;
return (((delta ^ sign) - sign) | (tab->len << 16));
} }
int __fi get_dmv() int __fi get_dmv()
{ {
const DMVtab* tab = DMV_2 + UBITS(2); const DMVtab* tab = DMV_2 + UBITS(2);
DUMPBITS(tab->len); DUMPBITS(tab->len);
return tab->dmv; return (tab->dmv | (tab->len << 16));
} }
int get_macroblock_address_increment() int get_macroblock_address_increment()
@ -246,13 +246,13 @@ int get_macroblock_address_increment()
{ {
case 8: /* macroblock_escape */ case 8: /* macroblock_escape */
DUMPBITS(11); DUMPBITS(11);
return 0x23; return 0xb0023;
case 15: /* macroblock_stuffing (MPEG1 only) */ case 15: /* macroblock_stuffing (MPEG1 only) */
if (decoder.mpeg1) if (decoder.mpeg1)
{ {
DUMPBITS(11); DUMPBITS(11);
return 0x22; return 0xb0022;
} }
default: default:
@ -261,7 +261,7 @@ int get_macroblock_address_increment()
DUMPBITS(mba->len); DUMPBITS(mba->len);
return mba->mba + 1; return ((mba->mba + 1) | (mba->len << 16));
} }
static __fi int get_luma_dc_dct_diff() static __fi int get_luma_dc_dct_diff()

View File

@ -395,8 +395,6 @@
<Unit filename="../ZipTools/ThreadedZipTools.h" /> <Unit filename="../ZipTools/ThreadedZipTools.h" />
<Unit filename="../ZipTools/thread_gzip.cpp" /> <Unit filename="../ZipTools/thread_gzip.cpp" />
<Unit filename="../ZipTools/thread_lzma.cpp" /> <Unit filename="../ZipTools/thread_lzma.cpp" />
<Unit filename="../gui/AdvancedDialog.cpp" />
<Unit filename="../gui/AdvancedDialog.h" />
<Unit filename="../gui/App.h" /> <Unit filename="../gui/App.h" />
<Unit filename="../gui/AppAccelerators.h" /> <Unit filename="../gui/AppAccelerators.h" />
<Unit filename="../gui/AppAssert.cpp" /> <Unit filename="../gui/AppAssert.cpp" />

View File

@ -806,7 +806,7 @@ void SysMtgsThread::WaitForOpen()
// emulator forcefully, or to continue waiting on the GS. // emulator forcefully, or to continue waiting on the GS.
throw Exception::PluginOpenError( PluginId_GS ) throw Exception::PluginOpenError( PluginId_GS )
.SetBothMsgs(wxLt("The MTGS thread has become unresponsive while waiting for the GS plugin to open.")); .SetBothMsgs(pxLt("The MTGS thread has become unresponsive while waiting for the GS plugin to open."));
} }
} }

View File

@ -374,6 +374,7 @@ void Pcsx2Config::LoadSave( IniInterface& ini )
IniBitBool( ConsoleToStdio ); IniBitBool( ConsoleToStdio );
IniBitBool( HostFs ); IniBitBool( HostFs );
IniBitBool( BackupSavestate );
IniBitBool( McdEnableEjection ); IniBitBool( McdEnableEjection );
IniBitBool( MultitapPort0_Enabled ); IniBitBool( MultitapPort0_Enabled );
IniBitBool( MultitapPort1_Enabled ); IniBitBool( MultitapPort1_Enabled );

View File

@ -23,6 +23,7 @@
#include "CDVD/CDVDisoReader.h" #include "CDVD/CDVDisoReader.h"
#include "Utilities/ScopedPtr.h" #include "Utilities/ScopedPtr.h"
#include "Utilities/pxStreams.h"
#if _MSC_VER #if _MSC_VER
# include "svnrev.h" # include "svnrev.h"
@ -152,7 +153,7 @@ _GSgifSoftReset GSgifSoftReset;
_GSreadFIFO GSreadFIFO; _GSreadFIFO GSreadFIFO;
_GSreadFIFO2 GSreadFIFO2; _GSreadFIFO2 GSreadFIFO2;
_GSchangeSaveState GSchangeSaveState; _GSchangeSaveState GSchangeSaveState;
_GSgetTitleInfo GSgetTitleInfo; _GSgetTitleInfo2 GSgetTitleInfo2;
_GSmakeSnapshot GSmakeSnapshot; _GSmakeSnapshot GSmakeSnapshot;
_GSmakeSnapshot2 GSmakeSnapshot2; _GSmakeSnapshot2 GSmakeSnapshot2;
_GSirqCallback GSirqCallback; _GSirqCallback GSirqCallback;
@ -185,8 +186,11 @@ static void CALLBACK GS_printf(int timeout, char *fmt, ...)
Console.WriteLn(msg); Console.WriteLn(msg);
} }
void CALLBACK GS_getTitleInfo( char dest[128] ) void CALLBACK GS_getTitleInfo2( char* dest, size_t length )
{ {
// Just return a generic "GS" title -- a plugin actually implementing this feature
// should return a title such as "GSdx" or "ZZogl" instead. --air
dest[0] = 'G'; dest[0] = 'G';
dest[1] = 'S'; dest[1] = 'S';
dest[2] = 0; dest[2] = 0;
@ -372,7 +376,7 @@ static const LegacyApi_ReqMethod s_MethMessReq_GS[] =
{ "GSsetVsync", (vMeth**)&GSsetVsync, (vMeth*)GS_setVsync }, { "GSsetVsync", (vMeth**)&GSsetVsync, (vMeth*)GS_setVsync },
{ "GSsetExclusive", (vMeth**)&GSsetExclusive, (vMeth*)GS_setExclusive }, { "GSsetExclusive", (vMeth**)&GSsetExclusive, (vMeth*)GS_setExclusive },
{ "GSchangeSaveState",(vMeth**)&GSchangeSaveState,(vMeth*)GS_changeSaveState }, { "GSchangeSaveState",(vMeth**)&GSchangeSaveState,(vMeth*)GS_changeSaveState },
{ "GSgetTitleInfo", (vMeth**)&GSgetTitleInfo, (vMeth*)GS_getTitleInfo }, { "GSgetTitleInfo2", (vMeth**)&GSgetTitleInfo2, (vMeth*)GS_getTitleInfo2 },
{ NULL } { NULL }
}; };
@ -807,11 +811,11 @@ SysCorePlugins::PluginStatus_t::PluginStatus_t( PluginsEnum_t _pid, const wxStri
if( !wxFile::Exists( Filename ) ) if( !wxFile::Exists( Filename ) )
throw Exception::PluginLoadError( pid ).SetStreamName(srcfile) throw Exception::PluginLoadError( pid ).SetStreamName(srcfile)
.SetBothMsgs(wxLt("The configured %s plugin file was not found")); .SetBothMsgs(pxL("The configured %s plugin file was not found"));
if( !Lib.Load( Filename ) ) if( !Lib.Load( Filename ) )
throw Exception::PluginLoadError( pid ).SetStreamName(Filename) throw Exception::PluginLoadError( pid ).SetStreamName(Filename)
.SetBothMsgs(wxLt("The configured %s plugin file is not a valid dynamic library")); .SetBothMsgs(pxL("The configured %s plugin file is not a valid dynamic library"));
// Try to enumerate the new v2.0 plugin interface first. // Try to enumerate the new v2.0 plugin interface first.
@ -1321,7 +1325,7 @@ bool SysCorePlugins::Init()
{ {
// fixme: use plugin's GetLastError (not implemented yet!) // fixme: use plugin's GetLastError (not implemented yet!)
throw Exception::PluginInitError( PluginId_Mcd ) throw Exception::PluginInitError( PluginId_Mcd )
.SetBothMsgs(wxLt("Internal Memorycard Plugin failed to initialize.")); .SetBothMsgs(pxLt("Internal Memorycard Plugin failed to initialize."));
} }
} }
@ -1399,9 +1403,6 @@ void SysCorePlugins::Freeze( PluginsEnum_t pid, SaveStateBase& state )
// No locking leeded -- DoFreeze locks as needed, and this avoids MTGS deadlock. // No locking leeded -- DoFreeze locks as needed, and this avoids MTGS deadlock.
//ScopedLock lock( m_mtx_PluginStatus ); //ScopedLock lock( m_mtx_PluginStatus );
Console.Indent().WriteLn( "%s %s", state.IsSaving() ? "Saving" : "Loading",
tbl_PluginInfo[pid].shortname );
freezeData fP = { 0, NULL }; freezeData fP = { 0, NULL };
if( !DoFreeze( pid, FREEZE_SIZE, &fP ) ) if( !DoFreeze( pid, FREEZE_SIZE, &fP ) )
fP.size = 0; fP.size = 0;
@ -1409,6 +1410,9 @@ void SysCorePlugins::Freeze( PluginsEnum_t pid, SaveStateBase& state )
int fsize = fP.size; int fsize = fP.size;
state.Freeze( fsize ); state.Freeze( fsize );
Console.Indent().WriteLn( "%s %s", state.IsSaving() ? "Saving" : "Loading",
tbl_PluginInfo[pid].shortname );
if( state.IsLoading() && (fsize == 0) ) if( state.IsLoading() && (fsize == 0) )
{ {
// no state data to read, but the plugin expects some state data. // no state data to read, but the plugin expects some state data.
@ -1443,6 +1447,82 @@ void SysCorePlugins::Freeze( PluginsEnum_t pid, SaveStateBase& state )
state.CommitBlock( fP.size ); state.CommitBlock( fP.size );
} }
size_t SysCorePlugins::GetFreezeSize( PluginsEnum_t pid )
{
freezeData fP = { 0, NULL };
if (!DoFreeze( pid, FREEZE_SIZE, &fP)) return 0;
return fP.size;
}
void SysCorePlugins::FreezeOut( PluginsEnum_t pid, void* dest )
{
// No locking needed -- DoFreeze locks as needed, and this avoids MTGS deadlock.
//ScopedLock lock( m_mtx_PluginStatus );
freezeData fP = { 0, (s8*)dest };
if (!DoFreeze( pid, FREEZE_SIZE, &fP)) return;
if (!fP.size) return;
Console.Indent().WriteLn( "Saving %s", tbl_PluginInfo[pid].shortname );
if (!DoFreeze(pid, FREEZE_SAVE, &fP))
throw Exception::FreezePluginFailure( pid );
}
void SysCorePlugins::FreezeOut( PluginsEnum_t pid, pxOutputStream& outfp )
{
// No locking needed -- DoFreeze locks as needed, and this avoids MTGS deadlock.
//ScopedLock lock( m_mtx_PluginStatus );
freezeData fP = { 0, NULL };
if (!DoFreeze( pid, FREEZE_SIZE, &fP)) return;
if (!fP.size) return;
Console.Indent().WriteLn( "Saving %s", tbl_PluginInfo[pid].shortname );
ScopedAlloc<s8> data( fP.size );
fP.data = data.GetPtr();
if (!DoFreeze(pid, FREEZE_SAVE, &fP))
throw Exception::FreezePluginFailure( pid );
outfp.Write( fP.data, fP.size );
}
void SysCorePlugins::FreezeIn( PluginsEnum_t pid, pxInputStream& infp )
{
// No locking needed -- DoFreeze locks as needed, and this avoids MTGS deadlock.
//ScopedLock lock( m_mtx_PluginStatus );
freezeData fP = { 0, NULL };
if (!DoFreeze( pid, FREEZE_SIZE, &fP ))
fP.size = 0;
Console.Indent().WriteLn( "Loading %s", tbl_PluginInfo[pid].shortname );
if (!infp.IsOk() || !infp.Length())
{
// no state data to read, but the plugin expects some state data?
// Issue a warning to console...
if( fP.size != 0 )
Console.Indent().Warning( "Warning: No data for this plugin was found. Plugin status may be unpredictable." );
return;
// Note: Size mismatch check could also be done here on loading, but
// some plugins may have built-in version support for non-native formats or
// older versions of a different size... or could give different sizes depending
// on the status of the plugin when loading, so let's ignore it.
}
ScopedAlloc<s8> data( fP.size );
fP.data = data.GetPtr();
infp.Read( fP.data, fP.size );
if (!DoFreeze(pid, FREEZE_LOAD, &fP))
throw Exception::ThawPluginFailure( pid );
}
bool SysCorePlugins::KeyEvent( const keyEvent& evt ) bool SysCorePlugins::KeyEvent( const keyEvent& evt )
{ {
ScopedLock lock( m_mtx_PluginStatus ); ScopedLock lock( m_mtx_PluginStatus );

View File

@ -326,6 +326,10 @@ public:
virtual bool IsInitialized( PluginsEnum_t pid ) const; virtual bool IsInitialized( PluginsEnum_t pid ) const;
virtual bool IsLoaded( PluginsEnum_t pid ) const; virtual bool IsLoaded( PluginsEnum_t pid ) const;
virtual size_t GetFreezeSize( PluginsEnum_t pid );
virtual void FreezeOut( PluginsEnum_t pid, void* dest );
virtual void FreezeOut( PluginsEnum_t pid, pxOutputStream& outfp );
virtual void FreezeIn( PluginsEnum_t pid, pxInputStream& infp );
virtual void Freeze( PluginsEnum_t pid, SaveStateBase& state ); virtual void Freeze( PluginsEnum_t pid, SaveStateBase& state );
virtual bool DoFreeze( PluginsEnum_t pid, int mode, freezeData* data ); virtual bool DoFreeze( PluginsEnum_t pid, int mode, freezeData* data );

View File

@ -16,7 +16,7 @@
#ifndef PCSX2_PRECOMPILED_HEADER #ifndef PCSX2_PRECOMPILED_HEADER
#define PCSX2_PRECOMPILED_HEADER #define PCSX2_PRECOMPILED_HEADER
//#pragma once // no dice, causes problems in GCC PCH (which doesn't really work very well //#pragma once // no dice, causes problems in GCC PCH (which doesn't really work very well anyway)
// Disable some pointless warnings... // Disable some pointless warnings...
#ifdef _MSC_VER #ifdef _MSC_VER
@ -24,20 +24,7 @@
# pragma warning(disable:4996) //ignore the stricmp deprecated warning # pragma warning(disable:4996) //ignore the stricmp deprecated warning
#endif #endif
////////////////////////////////////////////////////////////////////////////////////////// #include "Utilities/Dependencies.h"
// 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.
#ifndef wxLt
# define wxLt(a) wxT(a)
#endif
#define NOMINMAX // Disables other libs inclusion of their own min/max macros (we use std instead) #define NOMINMAX // Disables other libs inclusion of their own min/max macros (we use std instead)

View File

@ -86,7 +86,7 @@ int _SPR0chain()
__fi void SPR0chain() __fi void SPR0chain()
{ {
CPU_INT(DMAC_FROM_SPR, _SPR0chain() / BIAS); CPU_INT(DMAC_FROM_SPR, _SPR0chain() * BIAS);
spr0ch.qwc = 0; spr0ch.qwc = 0;
} }
@ -102,7 +102,7 @@ void _SPR0interleave()
SPR_LOG("SPR0 interleave size=%d, tqwc=%d, sqwc=%d, addr=%lx sadr=%lx", SPR_LOG("SPR0 interleave size=%d, tqwc=%d, sqwc=%d, addr=%lx sadr=%lx",
spr0ch.qwc, tqwc, sqwc, spr0ch.madr, spr0ch.sadr); spr0ch.qwc, tqwc, sqwc, spr0ch.madr, spr0ch.sadr);
CPU_INT(DMAC_FROM_SPR, qwc / BIAS); CPU_INT(DMAC_FROM_SPR, qwc * BIAS);
while (qwc > 0) while (qwc > 0)
{ {
@ -290,13 +290,14 @@ int _SPR1chain()
SPR1transfer(pMem, spr1ch.qwc); SPR1transfer(pMem, spr1ch.qwc);
spr1ch.madr += spr1ch.qwc * 16; spr1ch.madr += spr1ch.qwc * 16;
hwDmacSrcTadrInc(spr1ch);
return (spr1ch.qwc); return (spr1ch.qwc);
} }
__fi void SPR1chain() __fi void SPR1chain()
{ {
CPU_INT(DMAC_TO_SPR, _SPR1chain() / BIAS); CPU_INT(DMAC_TO_SPR, _SPR1chain() * BIAS);
spr1ch.qwc = 0; spr1ch.qwc = 0;
} }
@ -310,7 +311,7 @@ void _SPR1interleave()
if (tqwc == 0) tqwc = qwc; if (tqwc == 0) tqwc = qwc;
SPR_LOG("SPR1 interleave size=%d, tqwc=%d, sqwc=%d, addr=%lx sadr=%lx", SPR_LOG("SPR1 interleave size=%d, tqwc=%d, sqwc=%d, addr=%lx sadr=%lx",
spr1ch.qwc, tqwc, sqwc, spr1ch.madr, spr1ch.sadr); spr1ch.qwc, tqwc, sqwc, spr1ch.madr, spr1ch.sadr);
CPU_INT(DMAC_TO_SPR, qwc / BIAS); CPU_INT(DMAC_TO_SPR, qwc * BIAS);
while (qwc > 0) while (qwc > 0)
{ {
spr1ch.qwc = std::min(tqwc, qwc); spr1ch.qwc = std::min(tqwc, qwc);

View File

@ -70,8 +70,6 @@ void SaveStateBase::Init( SafeArray<u8>* memblock )
m_memory = memblock; m_memory = memblock;
m_version = g_SaveVersion; m_version = g_SaveVersion;
m_idx = 0; m_idx = 0;
m_sectid = FreezeId_Unknown;
m_pid = PluginId_GS;
m_DidBios = false; m_DidBios = false;
} }
@ -106,50 +104,45 @@ void SaveStateBase::FreezeTag( const char* src )
} }
} }
void SaveStateBase::FreezeBios() SaveStateBase& SaveStateBase::FreezeBios()
{ {
FreezeTag( "BIOS" );
// Check the BIOS, and issue a warning if the bios for this state // Check the BIOS, and issue a warning if the bios for this state
// doesn't match the bios currently being used (chances are it'll still // doesn't match the bios currently being used (chances are it'll still
// work fine, but some games are very picky). // work fine, but some games are very picky).
u32 bioscheck = BiosChecksum;
char biosdesc[256];
char descin[128], desccmp[128]; pxToUTF8 utf8(BiosDescription);
wxString descout;
IsBIOS( g_Conf->FullpathToBios(), descout );
memzero( descin );
memzero( desccmp );
pxToUTF8 utf8(descout); memzero( biosdesc );
memcpy_fast( descin, utf8, utf8.Length() ); memcpy_fast( biosdesc, utf8, std::min( sizeof(biosdesc), utf8.Length() ) );
memcpy_fast( desccmp, utf8, utf8.Length() );
Freeze( bioscheck );
Freeze( biosdesc );
// ... and only freeze bios info once per state, since the user msg could if (bioscheck != BiosChecksum)
// become really annoying on a corrupted state or something. (have to always
// load though, so that we advance past the duplicated info, if present)
if( IsLoading() || !m_DidBios )
Freeze( descin );
if( !m_DidBios )
{ {
if( memcmp( descin, desccmp, 128 ) != 0 ) Console.Newline();
{ Console.Indent(1).Error( "Warning: BIOS Version Mismatch, savestate may be unstable!" );
Console.Newline(); Console.Indent(2).Error(
Console.Indent(1).Error( "Warning: BIOS Version Mismatch, savestate may be unstable!" ); "Current BIOS: %ls (crc=0x%08x)\n"
Console.Indent(2).Error( "Savestate BIOS: %s (crc=0x%08x)\n",
"Current Version: %s\n" BiosDescription.c_str(), BiosChecksum,
"Savestate Version: %s\n", biosdesc, bioscheck
utf8.data(), descin );
);
}
} }
m_DidBios = true;
return *this;
} }
static const uint MainMemorySizeInBytes = static const uint MainMemorySizeInBytes =
Ps2MemSize::MainRam + Ps2MemSize::Scratch + Ps2MemSize::Hardware + Ps2MemSize::MainRam + Ps2MemSize::Scratch + Ps2MemSize::Hardware +
Ps2MemSize::IopRam + Ps2MemSize::IopHardware; Ps2MemSize::IopRam + Ps2MemSize::IopHardware;
void SaveStateBase::FreezeMainMemory() SaveStateBase& SaveStateBase::FreezeMainMemory()
{ {
if (IsLoading()) if (IsLoading())
PreLoadPrep(); PreLoadPrep();
@ -170,9 +163,11 @@ void SaveStateBase::FreezeMainMemory()
FreezeMem(vuRegs[1].Micro, VU1_PROGSIZE); FreezeMem(vuRegs[1].Micro, VU1_PROGSIZE);
FreezeMem(vuRegs[1].Mem, VU1_MEMSIZE); FreezeMem(vuRegs[1].Mem, VU1_MEMSIZE);
return *this;
} }
void SaveStateBase::FreezeRegisters() SaveStateBase& SaveStateBase::FreezeInternals()
{ {
if( IsLoading() ) if( IsLoading() )
PreLoadPrep(); PreLoadPrep();
@ -229,138 +224,31 @@ void SaveStateBase::FreezeRegisters()
if( IsLoading() ) if( IsLoading() )
PostLoadPrep(); PostLoadPrep();
return *this;
} }
void SaveStateBase::WritebackSectionLength( int seekpos, int sectlen, const wxChar* sectname ) SaveStateBase& SaveStateBase::FreezePlugins()
{ {
int realsectsize = m_idx - seekpos; for (uint i=0; i<PluginId_Count; ++i)
if( IsSaving() )
{ {
// write back the section length... FreezeTag( FastFormatAscii().Write("Plugin:%s", tbl_PluginInfo[i].shortname) );
*((u32*)m_memory->GetPtr(seekpos-4)) = realsectsize; GetCorePlugins().Freeze( (PluginsEnum_t)i, *this );
}
else // IsLoading!!
{
if( sectlen != realsectsize ) // if they don't match then we have a problem, jim.
{
throw Exception::SaveStateLoadError()
.SetDiagMsg(pxsFmt(L"Invalid size encountered on section '%s'.", sectname ))
.SetUserMsg(_("The savestate data is invalid or corrupted."));
}
} }
return *this;
} }
bool SaveStateBase::FreezeSection( int seek_section ) SaveStateBase& SaveStateBase::FreezeAll()
{ {
const bool isSeeking = (seek_section != FreezeId_NotSeeking ); FreezeMainMemory();
if( IsSaving() ) pxAssertDev( !isSeeking, "Cannot seek on a saving-mode savestate stream." ); FreezeBios();
FreezeInternals();
Freeze( m_sectid ); FreezePlugins();
if( seek_section == m_sectid ) return false;
return *this;
switch( m_sectid )
{
case FreezeId_End:
return false;
case FreezeId_Bios:
{
int sectlen = 128;
FreezeTag( "BiosVersion" );
Freeze( sectlen );
if( sectlen != 128 )
{
throw Exception::SaveStateLoadError()
.SetDiagMsg(L"Invalid size encountered on BiosVersion section.")
.SetUserMsg(_("The savestate data is invalid or corrupted."));
}
if( isSeeking )
m_idx += sectlen;
else
FreezeBios();
m_sectid++;
}
break;
case FreezeId_Registers:
{
FreezeTag( "HardwareRegisters" );
int seekpos = m_idx+4;
int sectlen = 0xdead; // gets written back over with "real" data in IsSaving() mode
Freeze( sectlen );
FreezeRegisters();
WritebackSectionLength( seekpos, sectlen, L"HardwareRegisters" );
m_sectid++;
}
break;
case FreezeId_Plugin:
{
FreezeTag( "Plugin" );
int seekpos = m_idx+4;
int sectlen = 0xdead; // gets written back over with "real" data in IsSaving() mode
Freeze( sectlen );
Freeze( m_pid );
if( isSeeking )
m_idx += sectlen;
else
GetCorePlugins().Freeze( (PluginsEnum_t)m_pid, *this );
WritebackSectionLength( seekpos, sectlen, L"Plugins" );
// following increments only affect Saving mode, which needs to be sure to save all
// plugins (order doesn't matter but sequential is easy enough. (ignored by Loading mode)
m_pid++;
if( m_pid >= PluginId_Count )
m_sectid = FreezeId_End;
}
break;
case FreezeId_Unknown:
default:
pxAssert( IsSaving() );
// Skip unknown sections with a warning log.
// Maybe it'll work! (haha?)
int size;
Freeze( m_tagspace );
Freeze( size );
m_tagspace[sizeof(m_tagspace)-1] = 0;
Console.Warning(
"Warning: Unknown tag encountered while loading savestate; going to ignore it!\n"
"\tTagname: %s, Size: %d", m_tagspace, size
);
m_idx += size;
break;
}
if( wxThread::IsMain() )
wxSafeYield( NULL, true );
return true;
} }
void SaveStateBase::FreezeAll()
{
if( IsSaving() )
{
// Loading mode streams will assign these, but saving mode reads them so better
// do some setup first.
m_sectid = (int)FreezeId_End+1;
m_pid = PluginId_GS;
}
while( FreezeSection() );
}
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
// memSavingState (implementations) // memSavingState (implementations)
@ -380,7 +268,9 @@ memSavingState::memSavingState( SafeArray<u8>* save_to )
// Saving of state data // Saving of state data
void memSavingState::FreezeMem( void* data, int size ) void memSavingState::FreezeMem( void* data, int size )
{ {
m_memory->MakeRoomFor( m_idx+size ); if (!size) return;
m_memory->MakeRoomFor( m_idx + size );
memcpy_fast( m_memory->GetPtr(m_idx), data, size ); memcpy_fast( m_memory->GetPtr(m_idx), data, size );
m_idx += size; m_idx += size;
} }
@ -394,10 +284,11 @@ void memSavingState::MakeRoomForData()
} }
// Saving of state data to a memory buffer // Saving of state data to a memory buffer
void memSavingState::FreezeAll() memSavingState& memSavingState::FreezeAll()
{ {
MakeRoomForData(); MakeRoomForData();
_parent::FreezeAll(); _parent::FreezeAll();
return *this;
} }
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
@ -423,25 +314,6 @@ void memLoadingState::FreezeMem( void* data, int size )
memcpy_fast( data, src, size ); memcpy_fast( data, src, size );
} }
bool memLoadingState::SeekToSection( PluginsEnum_t pid )
{
m_idx = 0; // start from the beginning
do
{
while( FreezeSection( FreezeId_Plugin ) );
if( m_sectid == FreezeId_End ) return false;
FreezeTag( "Plugin" );
int sectlen = 0xdead;
Freeze( sectlen );
Freeze( m_pid );
} while( m_pid != pid );
return true;
}
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
// SaveState Exception Messages // SaveState Exception Messages
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------

View File

@ -31,21 +31,6 @@ static const u32 g_SaveVersion = (0x9A01 << 16) | 0x0000;
extern s32 CALLBACK gsSafeFreeze( int mode, freezeData *data ); extern s32 CALLBACK gsSafeFreeze( int mode, freezeData *data );
enum FreezeSectionId
{
FreezeId_NotSeeking = -2,
FreezeId_End,
// A BIOS tag should always be saved in conjunction with Memory or Registers tags,
// but can be skipped if the savestate has only plugins.
FreezeId_Bios,
FreezeId_Registers,
FreezeId_Plugin,
// anything here and beyond we can skip, with a warning
FreezeId_Unknown,
};
namespace Exception namespace Exception
{ {
// --------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------
@ -119,8 +104,6 @@ protected:
u32 m_version; // version of the savestate being loaded. u32 m_version; // version of the savestate being loaded.
int m_idx; // current read/write index of the allocation int m_idx; // current read/write index of the allocation
int m_sectid;
int m_pid;
bool m_DidBios; bool m_DidBios;
@ -141,9 +124,12 @@ public:
// Loads or saves the entire emulation state. // Loads or saves the entire emulation state.
// Note: The Cpu state must be reset, and plugins *open*, prior to Defrosting // Note: The Cpu state must be reset, and plugins *open*, prior to Defrosting
// (loading) a state! // (loading) a state!
virtual void FreezeAll(); virtual SaveStateBase& FreezeAll();
void FreezeMainMemory(); virtual SaveStateBase& FreezeMainMemory();
virtual SaveStateBase& FreezeBios();
virtual SaveStateBase& FreezeInternals();
virtual SaveStateBase& FreezePlugins();
// Loads or saves an arbitrary data type. Usable on atomic types, structs, and arrays. // Loads or saves an arbitrary data type. Usable on atomic types, structs, and arrays.
// For dynamically allocated pointers use FreezeMem instead. // For dynamically allocated pointers use FreezeMem instead.
@ -183,9 +169,6 @@ public:
m_idx += size; m_idx += size;
} }
void WritebackSectionLength( int seekpos, int sectlen, const wxChar* sectname );
bool FreezeSection( int seek_section = FreezeId_NotSeeking );
// Freezes an identifier value into the savestate for troubleshooting purposes. // Freezes an identifier value into the savestate for troubleshooting purposes.
// Identifiers can be used to determine where in a savestate that data has become // Identifiers can be used to determine where in a savestate that data has become
// skewed (if the value does not match then the error occurs somewhere prior to that // skewed (if the value does not match then the error occurs somewhere prior to that
@ -210,9 +193,6 @@ protected:
// Load/Save functions for the various components of our glorious emulator! // Load/Save functions for the various components of our glorious emulator!
void FreezeBios();
void FreezeRegisters();
void rcntFreeze(); void rcntFreeze();
void vuMicroFreeze(); void vuMicroFreeze();
void vif0Freeze(); void vif0Freeze();
@ -257,7 +237,7 @@ public:
void MakeRoomForData(); void MakeRoomForData();
void FreezeMem( void* data, int size ); void FreezeMem( void* data, int size );
void FreezeAll(); memSavingState& FreezeAll();
bool IsSaving() const { return true; } bool IsSaving() const { return true; }
}; };
@ -271,7 +251,6 @@ public:
memLoadingState( const VmStateBuffer* load_from ); memLoadingState( const VmStateBuffer* load_from );
void FreezeMem( void* data, int size ); void FreezeMem( void* data, int size );
bool SeekToSection( PluginsEnum_t pid );
bool IsSaving() const { return false; } bool IsSaving() const { return false; }
bool IsFinished() const { return m_idx >= m_memory->GetSizeInBytes(); } bool IsFinished() const { return m_idx >= m_memory->GetSizeInBytes(); }

View File

@ -52,6 +52,7 @@ static __fi bool WriteEEtoFifo()
sif1.fifo.write((u32*)ptag, writeSize << 2); sif1.fifo.write((u32*)ptag, writeSize << 2);
sif1dma.madr += writeSize << 4; sif1dma.madr += writeSize << 4;
hwDmacSrcTadrInc(sif1dma);
sif1.ee.cycles += writeSize; // fixme : BIAS is factored in above sif1.ee.cycles += writeSize; // fixme : BIAS is factored in above
sif1dma.qwc -= writeSize; sif1dma.qwc -= writeSize;
@ -114,8 +115,8 @@ static __fi bool ProcessEETag()
break; break;
case TAG_CNT: case TAG_CNT:
sif1dma.madr = sif1dma.tadr + 16; sif1dma.tadr += 16;
sif1dma.tadr = sif1dma.madr + (sif1dma.qwc << 4); sif1dma.madr = sif1dma.tadr;
break; break;
case TAG_NEXT: case TAG_NEXT:
@ -132,7 +133,7 @@ static __fi bool ProcessEETag()
case TAG_END: case TAG_END:
sif1.ee.end = true; sif1.ee.end = true;
sif1dma.madr = sif1dma.tadr + 16; sif1dma.madr = sif1dma.tadr + 16;
sif1dma.tadr = sif1dma.madr + (sif1dma.qwc << 4); //sif1dma.tadr = sif1dma.madr + (sif1dma.qwc << 4);
break; break;
default: default:

View File

@ -93,27 +93,27 @@ static const TraceLogDescriptor
TLD_ELF = { TLD_ELF = {
L"ELF", L"ELF", L"ELF", L"ELF",
wxLt("Dumps detailed information for PS2 executables (ELFs).") pxDt("Dumps detailed information for PS2 executables (ELFs).")
}, },
TLD_eeRecPerf = { TLD_eeRecPerf = {
L"EErecPerf", L"EErec Performance", L"EErecPerf", L"EErec Performance",
wxLt("Logs manual protection, split blocks, and other things that might impact performance.") pxDt("Logs manual protection, split blocks, and other things that might impact performance.")
}, },
TLD_eeConsole = { TLD_eeConsole = {
L"EEout", L"EE Console", L"EEout", L"EE Console",
wxLt("Shows the game developer's logging text (EE processor)") pxDt("Shows the game developer's logging text (EE processor)")
}, },
TLD_iopConsole = { TLD_iopConsole = {
L"IOPout", L"IOP Console", L"IOPout", L"IOP Console",
wxLt("Shows the game developer's logging text (IOP processor)") pxDt("Shows the game developer's logging text (IOP processor)")
}, },
TLD_deci2 = { TLD_deci2 = {
L"DECI2", L"DECI2 Console", L"DECI2", L"DECI2 Console",
wxLt("Shows DECI2 debugging logs (EE processor)") pxDt("Shows DECI2 debugging logs (EE processor)")
}; };
SysConsoleLogPack::SysConsoleLogPack() SysConsoleLogPack::SysConsoleLogPack()
@ -131,7 +131,7 @@ SysConsoleLogPack::SysConsoleLogPack()
static const SysTraceLogDescriptor static const SysTraceLogDescriptor
TLD_SIF = { TLD_SIF = {
L"SIF", L"SIF (EE <-> IOP)", L"SIF", L"SIF (EE <-> IOP)",
wxLt(""), pxDt(""),
"SIF" "SIF"
}; };
@ -142,109 +142,109 @@ TLD_SIF = {
static const SysTraceLogDescriptor static const SysTraceLogDescriptor
TLD_EE_Bios = { TLD_EE_Bios = {
L"Bios", L"Bios", L"Bios", L"Bios",
wxLt("SYSCALL and DECI2 activity."), pxDt("SYSCALL and DECI2 activity."),
"EE" "EE"
}, },
TLD_EE_Memory = { TLD_EE_Memory = {
L"Memory", L"Memory", L"Memory", L"Memory",
wxLt("Direct memory accesses to unknown or unmapped EE memory space."), pxDt("Direct memory accesses to unknown or unmapped EE memory space."),
"eMem" "eMem"
}, },
TLD_EE_R5900 = { TLD_EE_R5900 = {
L"R5900", L"R5900 Core", L"R5900", L"R5900 Core",
wxLt("Disasm of executing core instructions (excluding COPs and CACHE)."), pxDt("Disasm of executing core instructions (excluding COPs and CACHE)."),
"eDis" "eDis"
}, },
TLD_EE_COP0 = { TLD_EE_COP0 = {
L"COP0", L"COP0", L"COP0", L"COP0",
wxLt("Disasm of COP0 instructions (MMU, cpu and dma status, etc)."), pxDt("Disasm of COP0 instructions (MMU, cpu and dma status, etc)."),
"eDis" "eDis"
}, },
TLD_EE_COP1 = { TLD_EE_COP1 = {
L"FPU", L"COP1/FPU", L"FPU", L"COP1/FPU",
wxLt("Disasm of the EE's floating point unit (FPU) only."), pxDt("Disasm of the EE's floating point unit (FPU) only."),
"eDis" "eDis"
}, },
TLD_EE_COP2 = { TLD_EE_COP2 = {
L"VUmacro", L"COP2/VUmacro", L"VUmacro", L"COP2/VUmacro",
wxLt("Disasm of the EE's VU0macro co-processor instructions."), pxDt("Disasm of the EE's VU0macro co-processor instructions."),
"eDis" "eDis"
}, },
TLD_EE_Cache = { TLD_EE_Cache = {
L"Cache", L"Cache", L"Cache", L"Cache",
wxLt("Execution of EE cache instructions."), pxDt("Execution of EE cache instructions."),
"eDis" "eDis"
}, },
TLD_EE_KnownHw = { TLD_EE_KnownHw = {
L"HwRegs", L"Hardware Regs", L"HwRegs", L"Hardware Regs",
wxLt("All known hardware register accesses (very slow!); not including sub filter options below."), pxDt("All known hardware register accesses (very slow!); not including sub filter options below."),
"eReg" "eReg"
}, },
TLD_EE_UnknownHw = { TLD_EE_UnknownHw = {
L"UnknownRegs", L"Unknown Regs", L"UnknownRegs", L"Unknown Regs",
wxLt("Logs only unknown, unmapped, or unimplemented register accesses."), pxDt("Logs only unknown, unmapped, or unimplemented register accesses."),
"eReg" "eReg"
}, },
TLD_EE_DMAhw = { TLD_EE_DMAhw = {
L"DmaRegs", L"DMA Regs", L"DmaRegs", L"DMA Regs",
wxLt("Logs only DMA-related registers."), pxDt("Logs only DMA-related registers."),
"eReg" "eReg"
}, },
TLD_EE_IPU = { TLD_EE_IPU = {
L"IPU", L"IPU", L"IPU", L"IPU",
wxLt("IPU activity: hardware registers, decoding operations, DMA status, etc."), pxDt("IPU activity: hardware registers, decoding operations, DMA status, etc."),
"IPU" "IPU"
}, },
TLD_EE_GIFtag = { TLD_EE_GIFtag = {
L"GIFtags", L"GIFtags", L"GIFtags", L"GIFtags",
wxLt("All GIFtag parse activity; path index, tag type, etc."), pxDt("All GIFtag parse activity; path index, tag type, etc."),
"GIF" "GIF"
}, },
TLD_EE_VIFcode = { TLD_EE_VIFcode = {
L"VIFcodes", L"VIFcodes", L"VIFcodes", L"VIFcodes",
wxLt("All VIFcode processing; command, tag style, interrupts."), pxDt("All VIFcode processing; command, tag style, interrupts."),
"VIF" "VIF"
}, },
TLD_EE_SPR = { TLD_EE_SPR = {
L"MFIFO", L"Scratchpad MFIFO", L"MFIFO", L"Scratchpad MFIFO",
wxLt("Scratchpad's MFIFO activity."), pxDt("Scratchpad's MFIFO activity."),
"SPR" "SPR"
}, },
TLD_EE_DMAC = { TLD_EE_DMAC = {
L"DmaCtrl", L"DMA Controller", L"DmaCtrl", L"DMA Controller",
wxLt("Actual data transfer logs, bus right arbitration, stalls, etc."), pxDt("Actual data transfer logs, bus right arbitration, stalls, etc."),
"eDmaC" "eDmaC"
}, },
TLD_EE_Counters = { TLD_EE_Counters = {
L"Counters", L"Counters", L"Counters", L"Counters",
wxLt("Tracks all EE counters events and some counter register activity."), pxDt("Tracks all EE counters events and some counter register activity."),
"eCnt" "eCnt"
}, },
TLD_EE_VIF = { TLD_EE_VIF = {
L"VIF", L"VIF", L"VIF", L"VIF",
wxLt("Dumps various VIF and VIFcode processing data."), pxDt("Dumps various VIF and VIFcode processing data."),
"VIF" "VIF"
}, },
TLD_EE_GIF = { TLD_EE_GIF = {
L"GIF", L"GIF", L"GIF", L"GIF",
wxLt("Dumps various GIF and GIFtag parsing data."), pxDt("Dumps various GIF and GIFtag parsing data."),
"GIF" "GIF"
}; };
@ -255,73 +255,73 @@ TLD_EE_GIF = {
static const SysTraceLogDescriptor static const SysTraceLogDescriptor
TLD_IOP_Bios = { TLD_IOP_Bios = {
L"Bios", L"Bios", L"Bios", L"Bios",
wxLt("SYSCALL and IRX activity."), pxDt("SYSCALL and IRX activity."),
"IOP" "IOP"
}, },
TLD_IOP_Memory = { TLD_IOP_Memory = {
L"Memory", L"Memory", L"Memory", L"Memory",
wxLt("Direct memory accesses to unknown or unmapped IOP memory space."), pxDt("Direct memory accesses to unknown or unmapped IOP memory space."),
"iMem" "iMem"
}, },
TLD_IOP_R3000A = { TLD_IOP_R3000A = {
L"R3000A", L"R3000A Core", L"R3000A", L"R3000A Core",
wxLt("Disasm of executing core instructions (excluding COPs and CACHE)."), pxDt("Disasm of executing core instructions (excluding COPs and CACHE)."),
"iDis" "iDis"
}, },
TLD_IOP_COP2 = { TLD_IOP_COP2 = {
L"COP2/GPU", L"COP2", L"COP2/GPU", L"COP2",
wxLt("Disasm of the IOP's GPU co-processor instructions."), pxDt("Disasm of the IOP's GPU co-processor instructions."),
"iDis" "iDis"
}, },
TLD_IOP_KnownHw = { TLD_IOP_KnownHw = {
L"HwRegs", L"Hardware Regs", L"HwRegs", L"Hardware Regs",
wxLt("All known hardware register accesses, not including the sub-filters below."), pxDt("All known hardware register accesses, not including the sub-filters below."),
"iReg" "iReg"
}, },
TLD_IOP_UnknownHw = { TLD_IOP_UnknownHw = {
L"UnknownRegs", L"Unknown Regs", L"UnknownRegs", L"Unknown Regs",
wxLt("Logs only unknown, unmapped, or unimplemented register accesses."), pxDt("Logs only unknown, unmapped, or unimplemented register accesses."),
"iReg" "iReg"
}, },
TLD_IOP_DMAhw = { TLD_IOP_DMAhw = {
L"DmaRegs", L"DMA Regs", L"DmaRegs", L"DMA Regs",
wxLt("Logs only DMA-related registers."), pxDt("Logs only DMA-related registers."),
"iReg" "iReg"
}, },
TLD_IOP_Memcards = { TLD_IOP_Memcards = {
L"Memorycards", L"Memorycards", L"Memorycards", L"Memorycards",
wxLt("Memorycard reads, writes, erases, terminators, and other processing."), pxDt("Memorycard reads, writes, erases, terminators, and other processing."),
"Mcd" "Mcd"
}, },
TLD_IOP_PAD = { TLD_IOP_PAD = {
L"Pad", L"Pad", L"Pad", L"Pad",
wxLt("Gamepad activity on the SIO."), pxDt("Gamepad activity on the SIO."),
"Pad" "Pad"
}, },
TLD_IOP_DMAC = { TLD_IOP_DMAC = {
L"DmaCrl", L"DMA Controller", L"DmaCrl", L"DMA Controller",
wxLt("Actual DMA event processing and data transfer logs."), pxDt("Actual DMA event processing and data transfer logs."),
"iDmaC" "iDmaC"
}, },
TLD_IOP_Counters = { TLD_IOP_Counters = {
L"Counters", L"Counters", L"Counters", L"Counters",
wxLt("Tracks all IOP counters events and some counter register activity."), pxDt("Tracks all IOP counters events and some counter register activity."),
"iCnt" "iCnt"
}, },
TLD_IOP_CDVD = { TLD_IOP_CDVD = {
L"CDVD", L"CDVD", L"CDVD", L"CDVD",
wxLt("Detailed logging of CDVD hardware."), pxDt("Detailed logging of CDVD hardware."),
"CDVD" "CDVD"
}; };

View File

@ -21,9 +21,6 @@
#include "SamplProf.h" #include "SamplProf.h"
// Includes needed for cleanup, since we don't have a good system (yet) for
// cleaning up these things.
#include "GameDatabase.h"
#include "Elfheader.h" #include "Elfheader.h"
#include "System/RecTypes.h" #include "System/RecTypes.h"
@ -114,7 +111,7 @@ void RecompiledCodeReserve::ThrowIfNotOk() const
throw Exception::OutOfMemory(m_name) throw Exception::OutOfMemory(m_name)
.SetDiagMsg(pxsFmt( L"Recompiled code cache could not be mapped." )) .SetDiagMsg(pxsFmt( L"Recompiled code cache could not be mapped." ))
.SetUserMsg( pxE( ".Error:Recompiler:VirtualMemoryAlloc", .SetUserMsg( pxE( "!Notice:Recompiler:VirtualMemoryAlloc",
L"This recompiler was unable to reserve contiguous memory required for internal caches. " L"This recompiler was unable to reserve contiguous memory required for internal caches. "
L"This error can be caused by low virtual memory resources, such as a small or disabled swapfile, " L"This error can be caused by low virtual memory resources, such as a small or disabled swapfile, "
L"or by another program that is hogging a lot of memory. You can also try reducing the default " L"or by another program that is hogging a lot of memory. You can also try reducing the default "
@ -133,25 +130,25 @@ void SysOutOfMemory_EmergencyResponse(uptr blocksize)
if (Cpu) if (Cpu)
{ {
Cpu->SetCacheReserve( (Cpu->GetCacheReserve() * 3) / 2 ); Cpu->SetCacheReserve( (Cpu->GetCacheReserve() * 2) / 3 );
Cpu->Reset(); Cpu->Reset();
} }
if (CpuVU0) if (CpuVU0)
{ {
CpuVU0->SetCacheReserve( (CpuVU0->GetCacheReserve() * 3) / 2 ); CpuVU0->SetCacheReserve( (CpuVU0->GetCacheReserve() * 2) / 3 );
CpuVU0->Reset(); CpuVU0->Reset();
} }
if (CpuVU1) if (CpuVU1)
{ {
CpuVU1->SetCacheReserve( (CpuVU1->GetCacheReserve() * 3) / 2 ); CpuVU1->SetCacheReserve( (CpuVU1->GetCacheReserve() * 2) / 3 );
CpuVU1->Reset(); CpuVU1->Reset();
} }
if (psxCpu) if (psxCpu)
{ {
psxCpu->SetCacheReserve( (psxCpu->GetCacheReserve() * 3) / 2 ); psxCpu->SetCacheReserve( (psxCpu->GetCacheReserve() * 2) / 3 );
psxCpu->Reset(); psxCpu->Reset();
} }
} }
@ -201,30 +198,37 @@ TraceLogFilters& SetTraceConfig()
// This function should be called once during program execution. // This function should be called once during program execution.
void SysLogMachineCaps() void SysLogMachineCaps()
{ {
Console.WriteLn( Color_StrongGreen, "PCSX2 %u.%u.%u.r%d %s - compiled on " __DATE__, PCSX2_VersionHi, PCSX2_VersionMid, PCSX2_VersionLo, Console.WriteLn( Color_StrongGreen, "PCSX2 %u.%u.%u.r%d %s - compiled on " __DATE__,
PCSX2_VersionHi, PCSX2_VersionMid, PCSX2_VersionLo,
SVN_REV, SVN_MODS ? "(modded)" : "" SVN_REV, SVN_MODS ? "(modded)" : ""
); );
Console.WriteLn( "Savestate version: 0x%x", g_SaveVersion); Console.WriteLn( "Savestate version: 0x%x", g_SaveVersion);
Console.Newline(); Console.Newline();
Console.WriteLn( Color_StrongBlack, "x86-32 Init:" ); Console.WriteLn( Color_StrongBlack, "Host Machine Init:" );
Console.Indent().WriteLn(
L"Operating System = %s\n"
L"Physical RAM = %u MB",
GetOSVersionString().c_str(),
(u32)(GetPhysicalMemory() / _1mb)
);
u32 speed = x86caps.CalculateMHz(); u32 speed = x86caps.CalculateMHz();
Console.Indent().WriteLn( Console.Indent().WriteLn(
L"CPU vendor name = %s\n" L"CPU name = %s\n"
L"FamilyID = %x\n" L"Vendor/Model = %s (stepping %02X)\n"
L"x86Family = %s\n" L"CPU speed = %u.%03u ghz (%u logical thread%s)\n"
L"CPU speed = %d.%03d ghz\n"
L"Cores = %d physical [%d logical]\n"
L"x86PType = %s\n" L"x86PType = %s\n"
L"x86Flags = %8.8x %8.8x\n" L"x86Flags = %08x %08x\n"
L"x86EFlags = %8.8x", L"x86EFlags = %08x",
fromUTF8( x86caps.VendorName ).c_str(), x86caps.StepID,
fromUTF8( x86caps.FamilyName ).Trim().Trim(false).c_str(), fromUTF8( x86caps.FamilyName ).Trim().Trim(false).c_str(),
fromUTF8( x86caps.VendorName ).c_str(), x86caps.StepID,
speed / 1000, speed % 1000, speed / 1000, speed % 1000,
x86caps.PhysicalCores, x86caps.LogicalCores, x86caps.LogicalCores, (x86caps.LogicalCores==1) ? L"" : L"s",
x86caps.GetTypeName().c_str(), x86caps.GetTypeName().c_str(),
x86caps.Flags, x86caps.Flags2, x86caps.Flags, x86caps.Flags2,
x86caps.EFlags x86caps.EFlags
@ -339,7 +343,7 @@ public:
// returns the translated error message for the Virtual Machine failing to allocate! // returns the translated error message for the Virtual Machine failing to allocate!
static wxString GetMemoryErrorVM() static wxString GetMemoryErrorVM()
{ {
return pxE( ".Error:EmuCore::MemoryForVM", return pxE( "!Notice:EmuCore::MemoryForVM",
L"PCSX2 is unable to allocate memory needed for the PS2 virtual machine. " L"PCSX2 is unable to allocate memory needed for the PS2 virtual machine. "
L"Close out some memory hogging background tasks and try again." L"Close out some memory hogging background tasks and try again."
); );
@ -598,7 +602,7 @@ wxString SysGetDiscID()
if( !ElfCRC ) if( !ElfCRC )
{ {
// FIXME: If the system is currently running the BIOS, it should return a serial based on // FIXME: system is currently running the BIOS, so it should return a serial based on
// the BIOS being run (either a checksum of the BIOS roms, and/or a string based on BIOS // the BIOS being run (either a checksum of the BIOS roms, and/or a string based on BIOS
// region and revision). // region and revision).
} }

View File

@ -151,7 +151,6 @@ void SysCoreThread::UploadStateCopy( const VmStateBuffer& copy )
if( !pxAssertDev( IsPaused(), "CoreThread is not paused; new VM state cannot be uploaded." ) ) return; if( !pxAssertDev( IsPaused(), "CoreThread is not paused; new VM state cannot be uploaded." ) ) return;
memLoadingState loadme( copy ); memLoadingState loadme( copy );
loadme.FreezeMainMemory();
loadme.FreezeAll(); loadme.FreezeAll();
m_resetVirtualMachine = false; m_resetVirtualMachine = false;
} }

View File

@ -77,12 +77,16 @@ __fi void vif0FBRST(u32 value) {
memzero(vif0); memzero(vif0);
vif0ch.qwc = 0; //? vif0ch.qwc = 0; //?
cpuRegs.interrupt &= ~1; //Stop all vif0 DMA's //cpuRegs.interrupt &= ~1; //Stop all vif0 DMA's
psHu64(VIF0_FIFO) = 0; psHu64(VIF0_FIFO) = 0;
psHu64(VIF0_FIFO + 8) = 0; psHu64(VIF0_FIFO + 8) = 0;
vif0.done = false; vif0.vifstalled = false;
vif0.inprogress = 0;
vif0.cmd = 0;
//vif0.done = false;
vif0Regs.err.reset(); vif0Regs.err.reset();
vif0Regs.stat.clear_flags(VIF0_STAT_FQC | VIF0_STAT_INT | VIF0_STAT_VSS | VIF0_STAT_VIS | VIF0_STAT_VFS | VIF0_STAT_VPS); // FQC=0 vif0Regs.stat.clear_flags(VIF0_STAT_FQC | VIF0_STAT_INT | VIF0_STAT_VSS | VIF0_STAT_VIS | VIF0_STAT_VFS | VIF0_STAT_VPS); // FQC=0
if(vif0ch.chcr.STR == true) CPU_INT(DMAC_VIF0, 4);
} }
/* Fixme: Forcebreaks are pretty unknown for operation, presumption is it just stops it what its doing /* Fixme: Forcebreaks are pretty unknown for operation, presumption is it just stops it what its doing
@ -137,7 +141,8 @@ __fi void vif1FBRST(u32 value) {
memzero(vif1); memzero(vif1);
//cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's //cpuRegs.interrupt &= ~((1 << 1) | (1 << 10)); //Stop all vif1 DMA's
vif1ch.qwc -= min((int)vif1ch.qwc, 16); //? //vif1ch.qwc -= min((int)vif1ch.qwc, 16); //not sure if the dma should stop, FFWDing could be tricky
vif1ch.qwc = 0;
psHu64(VIF1_FIFO) = 0; psHu64(VIF1_FIFO) = 0;
psHu64(VIF1_FIFO + 8) = 0; psHu64(VIF1_FIFO + 8) = 0;
//vif1.done = false; //vif1.done = false;
@ -160,6 +165,7 @@ __fi void vif1FBRST(u32 value) {
vif1.vifstalled = false; vif1.vifstalled = false;
vif1Regs.stat.FQC = 0; vif1Regs.stat.FQC = 0;
vif1Regs.stat.clear_flags(VIF1_STAT_FDR | VIF1_STAT_INT | VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS | VIF1_STAT_VPS); vif1Regs.stat.clear_flags(VIF1_STAT_FDR | VIF1_STAT_INT | VIF1_STAT_VSS | VIF1_STAT_VIS | VIF1_STAT_VFS | VIF1_STAT_VPS);
if(vif1ch.chcr.STR == true) CPU_INT(DMAC_VIF1, 4);
} }
/* Fixme: Forcebreaks are pretty unknown for operation, presumption is it just stops it what its doing /* Fixme: Forcebreaks are pretty unknown for operation, presumption is it just stops it what its doing

View File

@ -155,9 +155,9 @@ bool _VIF1chain()
vif1ch.qwc, vif1ch.madr, vif1ch.tadr); vif1ch.qwc, vif1ch.madr, vif1ch.tadr);
if (vif1.vifstalled) if (vif1.vifstalled)
return VIF1transfer(pMem + vif1.irqoffset, vif1ch.qwc * 4 - vif1.irqoffset); return VIF1transfer(pMem + vif1.irqoffset, vif1ch.qwc * 4 - vif1.irqoffset, false);
else else
return VIF1transfer(pMem, vif1ch.qwc * 4); return VIF1transfer(pMem, vif1ch.qwc * 4, false);
} }
__fi void vif1SetupTransfer() __fi void vif1SetupTransfer()
@ -490,7 +490,7 @@ void dmaVIF1()
if(vif1ch.chcr.MOD == CHAIN_MODE && vif1.dmamode != VIF_NORMAL_TO_MEM_MODE) if(vif1ch.chcr.MOD == CHAIN_MODE && vif1.dmamode != VIF_NORMAL_TO_MEM_MODE)
{ {
vif1.dmamode = VIF_CHAIN_MODE; vif1.dmamode = VIF_CHAIN_MODE;
DevCon.Warning(L"VIF1 QWC on Chain CHCR " + vif1ch.chcr.desc()); //DevCon.Warning(L"VIF1 QWC on Chain CHCR " + vif1ch.chcr.desc());
if ((vif1ch.chcr.tag().ID == TAG_REFE) || (vif1ch.chcr.tag().ID == TAG_END)) if ((vif1ch.chcr.tag().ID == TAG_REFE) || (vif1ch.chcr.tag().ID == TAG_END))
{ {
@ -502,6 +502,7 @@ void dmaVIF1()
{ {
vif1.dmamode = VIF_CHAIN_MODE; vif1.dmamode = VIF_CHAIN_MODE;
vif1.done = false; vif1.done = false;
vif1.inprogress = 0;
} }
if (vif1ch.chcr.DIR) vif1Regs.stat.FQC = min((u16)0x10, vif1ch.qwc); if (vif1ch.chcr.DIR) vif1Regs.stat.FQC = min((u16)0x10, vif1ch.qwc);

View File

@ -32,14 +32,39 @@ static u32 qwctag(u32 mask)
return (dmacRegs.rbor.ADDR + (mask & dmacRegs.rbsr.RMSK)); return (dmacRegs.rbor.ADDR + (mask & dmacRegs.rbsr.RMSK));
} }
static u16 QWCinVIFMFIFO(u32 DrainADDR)
{
u32 ret;
SPR_LOG("VIF MFIFO Requesting %x QWC from the MFIFO Base %x, SPR MADR %x Drain %x", vif1ch.qwc, dmacRegs.rbor.ADDR, spr0ch.madr, DrainADDR);
//Calculate what we have in the fifo.
if(DrainADDR <= spr0ch.madr)
{
//Drain is below the tadr, calculate the difference between them
ret = (spr0ch.madr - DrainADDR) >> 4;
}
else
{
u32 limit = dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16;
//Drain is higher than SPR so it has looped round,
//calculate from base to the SPR tag addr and what is left in the top of the ring
ret = ((spr0ch.madr - dmacRegs.rbor.ADDR) + (limit - DrainADDR)) >> 4;
}
SPR_LOG("%x Available of the %x requested", ret, vif1ch.qwc);
return ret;
}
static __fi bool mfifoVIF1rbTransfer() static __fi bool mfifoVIF1rbTransfer()
{ {
u32 maddr = dmacRegs.rbor.ADDR; u32 maddr = dmacRegs.rbor.ADDR;
u32 msize = dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16; u32 msize = dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16;
u16 mfifoqwc = std::min(vif1ch.qwc, vifqwc); u16 mfifoqwc = min(QWCinVIFMFIFO(vif1ch.madr), vif1ch.qwc);
u32 *src; u32 *src;
bool ret; bool ret;
if(mfifoqwc == 0) return true; //Cant do anything, lets forget it
/* Check if the transfer should wrap around the ring buffer */ /* Check if the transfer should wrap around the ring buffer */
if ((vif1ch.madr + (mfifoqwc << 4)) > (msize)) if ((vif1ch.madr + (mfifoqwc << 4)) > (msize))
{ {
@ -48,6 +73,8 @@ static __fi bool mfifoVIF1rbTransfer()
SPR_LOG("Split MFIFO"); SPR_LOG("Split MFIFO");
/* it does, so first copy 's1' bytes from 'addr' to 'data' */ /* it does, so first copy 's1' bytes from 'addr' to 'data' */
vif1ch.madr = qwctag(vif1ch.madr);
src = (u32*)PSM(vif1ch.madr); src = (u32*)PSM(vif1ch.madr);
if (src == NULL) return false; if (src == NULL) return false;
@ -56,10 +83,9 @@ static __fi bool mfifoVIF1rbTransfer()
else else
ret = VIF1transfer(src, s1); ret = VIF1transfer(src, s1);
vif1ch.madr = qwctag(vif1ch.madr);
if (ret) if (ret)
{ {
if(vif1.irqoffset != 0) DevCon.Warning("VIF1 MFIFO Offest != 0! vifoffset=%x", vif1.irqoffset);
/* and second copy 's2' bytes from 'maddr' to '&data[s1]' */ /* and second copy 's2' bytes from 'maddr' to '&data[s1]' */
vif1ch.madr = maddr; vif1ch.madr = maddr;
@ -67,13 +93,12 @@ static __fi bool mfifoVIF1rbTransfer()
if (src == NULL) return false; if (src == NULL) return false;
VIF1transfer(src, ((mfifoqwc << 2) - s1)); VIF1transfer(src, ((mfifoqwc << 2) - s1));
} }
vif1ch.madr = qwctag(vif1ch.madr);
} }
else else
{ {
SPR_LOG("Direct MFIFO"); SPR_LOG("Direct MFIFO");
/* it doesn't, so just transfer 'qwc*4' words */ /* it doesn't, so just transfer 'qwc*4' words */
src = (u32*)PSM(vif1ch.madr); src = (u32*)PSM(vif1ch.madr);
if (src == NULL) return false; if (src == NULL) return false;
@ -83,8 +108,6 @@ static __fi bool mfifoVIF1rbTransfer()
else else
ret = VIF1transfer(src, mfifoqwc << 2); ret = VIF1transfer(src, mfifoqwc << 2);
vif1ch.madr = qwctag(vif1ch.madr);
} }
return ret; return ret;
} }
@ -99,13 +122,17 @@ static __fi void mfifo_VIF1chain()
} }
if (vif1ch.madr >= dmacRegs.rbor.ADDR && if (vif1ch.madr >= dmacRegs.rbor.ADDR &&
vif1ch.madr <= (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK)) vif1ch.madr <= (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16))
{ {
//Need to exit on mfifo locations, if the madr is matching the madr of spr, we dont have any data left :( if(vif1ch.madr == (dmacRegs.rbor.ADDR + dmacRegs.rbsr.RMSK + 16)) DevCon.Warning("Edge VIF1");
u16 startqwc = vif1ch.qwc; vif1ch.madr = qwctag(vif1ch.madr);
mfifoVIF1rbTransfer(); mfifoVIF1rbTransfer();
vifqwc -= startqwc - vif1ch.qwc; vif1ch.tadr = qwctag(vif1ch.tadr);
vif1ch.madr = qwctag(vif1ch.madr);
if(QWCinVIFMFIFO(vif1ch.madr) == 0) vif1.inprogress |= 0x10;
//vifqwc -= startqwc - vif1ch.qwc;
} }
else else
@ -124,8 +151,6 @@ static __fi void mfifo_VIF1chain()
} }
} }
int NextTADR = 0; //Bodge for Clock Tower 3 (see below)
void mfifoVIF1transfer(int qwc) void mfifoVIF1transfer(int qwc)
{ {
tDMA_TAG *ptag; tDMA_TAG *ptag;
@ -134,11 +159,15 @@ void mfifoVIF1transfer(int qwc)
if (qwc > 0) if (qwc > 0)
{ {
vifqwc += qwc; //vifqwc += qwc;
SPR_LOG("Added %x qw to mfifo, total now %x - Vif CHCR %x Stalled %x done %x", qwc, vifqwc, vif1ch.chcr._u32, vif1.vifstalled, vif1.done); SPR_LOG("Added %x qw to mfifo, total now %x - Vif CHCR %x Stalled %x done %x", qwc, vif1ch.chcr._u32, vif1.vifstalled, vif1.done);
if (vif1.inprogress & 0x10) if (vif1.inprogress & 0x10)
{ {
if(vif1ch.chcr.STR == true)CPU_INT(DMAC_MFIFO_VIF, 4); if(vif1ch.chcr.STR == true && !(cpuRegs.interrupt & (1<<DMAC_MFIFO_VIF)))
{
SPR_LOG("Data Added, Resuming");
CPU_INT(DMAC_MFIFO_VIF, 4);
}
vif1Regs.stat.FQC = 0x10; // FQC=16 vif1Regs.stat.FQC = 0x10; // FQC=16
} }
@ -147,8 +176,9 @@ void mfifoVIF1transfer(int qwc)
return; return;
} }
if (vif1ch.qwc == 0 && vifqwc > 0) if (vif1ch.qwc == 0)
{ {
vif1ch.tadr = qwctag(vif1ch.tadr);
ptag = dmaGetAddr(vif1ch.tadr, false); ptag = dmaGetAddr(vif1ch.tadr, false);
if (vif1ch.chcr.TTE) if (vif1ch.chcr.TTE)
@ -169,63 +199,32 @@ void mfifoVIF1transfer(int qwc)
} }
else else
{ {
ret = VIF1transfer((u32*)&masked_tag, 4, true); //Transfer Tag vif1.irqoffset = 2;
ret = VIF1transfer((u32*)&masked_tag + 2, 2, true); //Transfer Tag
//ret = VIF1transfer((u32*)ptag + 2, 2); //Transfer Tag //ret = VIF1transfer((u32*)ptag + 2, 2); //Transfer Tag
} }
if (!ret && vif1.irqoffset) if (!ret && vif1.irqoffset)
{ {
vif1.inprogress &= ~1;
return; //IRQ set by VIFTransfer return; //IRQ set by VIFTransfer
} //else vif1.vifstalled = false; } //else vif1.vifstalled = false;
g_vifCycles += 2; g_vifCycles += 2;
} }
vif1.irqoffset = 0; vif1.irqoffset = 0;
vif1ch.unsafeTransfer(ptag); vif1ch.unsafeTransfer(ptag);
vif1ch.madr = ptag[1]._u32; vif1ch.madr = ptag[1]._u32;
vifqwc--;
//vifqwc--;
SPR_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx mfifo qwc = %x spr0 madr = %x", SPR_LOG("dmaChain %8.8x_%8.8x size=%d, id=%d, madr=%lx, tadr=%lx mfifo qwc = %x spr0 madr = %x",
ptag[1]._u32, ptag[0]._u32, vif1ch.qwc, ptag->ID, vif1ch.madr, vif1ch.tadr, vifqwc, spr0ch.madr); ptag[1]._u32, ptag[0]._u32, vif1ch.qwc, ptag->ID, vif1ch.madr, vif1ch.tadr, vifqwc, spr0ch.madr);
switch (ptag->ID) vif1.done |= hwDmacSrcChainWithStack(vif1ch, ptag->ID);
{
case TAG_REFE: // Refe - Transfer Packet According to ADDR field
NextTADR = qwctag(vif1ch.tadr + 16);
vif1.done = true; //End Transfer
break;
case TAG_CNT: // CNT - Transfer QWC following the tag.
vif1ch.madr = qwctag(vif1ch.tadr + 16); //Set MADR to QW after Tag
NextTADR = qwctag(vif1ch.madr + (vif1ch.qwc << 4)); //Set TADR to QW following the data
vif1.done = false;
break;
case TAG_NEXT: // Next - Transfer QWC following tag. TADR = ADDR
{
int temp = vif1ch.madr; //Temporarily Store ADDR
vif1ch.madr = qwctag(vif1ch.tadr + 16); //Set MADR to QW following the tag
NextTADR = temp; //Copy temporarily stored ADDR to Tag
if ((temp & dmacRegs.rbsr.RMSK) != dmacRegs.rbor.ADDR) Console.WriteLn("Next tag = %x outside ring %x size %x", temp, psHu32(DMAC_RBOR), psHu32(DMAC_RBSR));
vif1.done = false;
break;
}
case TAG_REF: // Ref - Transfer QWC from ADDR field
case TAG_REFS: // Refs - Transfer QWC from ADDR field (Stall Control)
NextTADR = qwctag(vif1ch.tadr + 16); //Set TADR to next tag
vif1.done = false;
break;
case TAG_END: // End - Transfer QWC following the tag
vif1ch.madr = qwctag(vif1ch.tadr + 16); //Set MADR to data following the tag
NextTADR = qwctag(vif1ch.madr + (vif1ch.qwc << 4)); //Set TADR to QW following the data
vif1.done = true; //End Transfer
break;
}
if (vif1ch.chcr.TIE && ptag->IRQ) if (vif1ch.chcr.TIE && ptag->IRQ)
{ {
@ -233,8 +232,16 @@ void mfifoVIF1transfer(int qwc)
vif1.done = true; vif1.done = true;
} }
vif1Regs.stat.FQC = min(vif1ch.qwc, (u16)16);
vif1.inprogress |= 1; if(vif1ch.qwc > 0) vif1.inprogress |= 1;
vif1ch.tadr = qwctag(vif1ch.tadr);
if(QWCinVIFMFIFO(vif1ch.tadr) == 0) vif1.inprogress |= 0x10;
}
else
{
DevCon.Warning("Vif MFIFO QWC not 0 on tag");
} }
@ -247,14 +254,10 @@ void vifMFIFOInterrupt()
VIF_LOG("vif mfifo interrupt"); VIF_LOG("vif mfifo interrupt");
if(NextTADR != 0 && vif1ch.qwc == 0) if (dmacRegs.ctrl.MFD != MFD_VIF1)
{ {
// Clock Tower 3 Note! DevCon.Warning("Not in VIF MFIFO mode! Stopping VIF MFIFO");
/* If the DMA starts the transfer then hammers the TADR to see when the transfer has finished(as clock tower does) return;
and we have preincremented before all data has arrived, it breaks. Idealy we increment this as we transfer the data.
"NextTADR" bodge in for the moment! - Refraction */
vif1ch.tadr = NextTADR;
NextTADR = 0;
} }
if(GSTransferStatus.PTH2 == STOPPED_MODE && gifRegs.stat.APATH == GIF_APATH2) if(GSTransferStatus.PTH2 == STOPPED_MODE && gifRegs.stat.APATH == GIF_APATH2)
@ -269,7 +272,11 @@ void vifMFIFOInterrupt()
if (schedulepath3msk & 0x10) Vif1MskPath3(); if (schedulepath3msk & 0x10) Vif1MskPath3();
if(vif1ch.chcr.DIR && CheckPath2GIF(DMAC_MFIFO_VIF) == false) return; if(vif1ch.chcr.DIR && CheckPath2GIF(DMAC_MFIFO_VIF) == false)
{
SPR_LOG("Waiting for PATH to be ready");
return;
}
//We need to check the direction, if it is downloading from the GS, we handle that seperately (KH2 for testing) //We need to check the direction, if it is downloading from the GS, we handle that seperately (KH2 for testing)
//Simulated GS transfer time done, clear the flags //Simulated GS transfer time done, clear the flags
@ -283,8 +290,10 @@ void vifMFIFOInterrupt()
vif1Regs.stat.VPS = VPS_IDLE; vif1Regs.stat.VPS = VPS_IDLE;
} }
if (vif1.irq && vif1.tag.size == 0) if (vif1.irq && vif1.tag.size == 0)
{ {
SPR_LOG("VIF MFIFO Code Interrupt detected");
vif1Regs.stat.INT = true; vif1Regs.stat.INT = true;
hwIntcIrq(INTC_VIF1); hwIntcIrq(INTC_VIF1);
--vif1.irq; --vif1.irq;
@ -293,55 +302,40 @@ void vifMFIFOInterrupt()
{ {
/*vif1Regs.stat.FQC = 0; // FQC=0 /*vif1Regs.stat.FQC = 0; // FQC=0
vif1ch.chcr.STR = false;*/ vif1ch.chcr.STR = false;*/
if(vif1ch.qwc > 0 || !vif1.done) return; if((vif1ch.qwc > 0 || !vif1.done) && !(vif1.inprogress & 0x10)) return;
} }
} }
if(vif1.inprogress & 0x10)
{
FireMFIFOEmpty();
if(!(vif1.done && vif1ch.qwc == 0))return;
}
if (vif1.done == false || vif1ch.qwc) if (vif1.done == false || vif1ch.qwc)
{ {
switch(vif1.inprogress & 1) switch(vif1.inprogress & 1)
{ {
case 0: //Set up transfer case 0: //Set up transfer
if (vif1ch.tadr == spr0ch.madr) if (QWCinVIFMFIFO(vif1ch.tadr) == 0)
{ {
// Console.WriteLn("Empty 1"); vif1.inprogress |= 0x10;
vifqwc = 0; CPU_INT(DMAC_MFIFO_VIF, 4 );
if((vif1.inprogress & 0x10) == 0)
{
hwDmacIrq(DMAC_MFIFO_EMPTY);
vif1.inprogress |= 0x10;
}
vif1Regs.stat.FQC = 0;
return; return;
} }
mfifoVIF1transfer(0); mfifoVIF1transfer(0);
CPU_INT(DMAC_MFIFO_VIF, 4);
return;
case 1: //Transfer data case 1: //Transfer data
mfifo_VIF1chain(); mfifo_VIF1chain();
//Sanity check! making sure we always have non-zero values //Sanity check! making sure we always have non-zero values
CPU_INT(DMAC_MFIFO_VIF, (g_vifCycles == 0 ? 4 : g_vifCycles) ); CPU_INT(DMAC_MFIFO_VIF, (g_vifCycles == 0 ? 4 : g_vifCycles) );
return; return;
} }
return; return;
} }
//FF7 Dirge of Cerberus seems to like the mfifo to tell it when it's empty, even if it's ending.
//Doesn't seem to care about the vif1 dma interrupting (possibly disabled the interrupt?)
if (vif1ch.tadr == spr0ch.madr)
{
vifqwc = 0;
if((vif1.inprogress & 0x10) == 0)
{
hwDmacIrq(DMAC_MFIFO_EMPTY);
vif1.inprogress |= 0x10;
}
}
vif1.vifstalled = false; vif1.vifstalled = false;
vif1.done = 1; vif1.done = 1;
g_vifCycles = 0; g_vifCycles = 0;

View File

@ -115,6 +115,8 @@ vifOp(vifCode_Base) {
} }
extern bool SIGNAL_IMR_Pending; extern bool SIGNAL_IMR_Pending;
static __aligned16 u32 partial_write[4];
static uint partial_count = 0;
template<int idx> __fi int _vifCode_Direct(int pass, const u8* data, bool isDirectHL) { template<int idx> __fi int _vifCode_Direct(int pass, const u8* data, bool isDirectHL) {
pass1 { pass1 {
@ -154,7 +156,7 @@ template<int idx> __fi int _vifCode_Direct(int pass, const u8* data, bool isDire
} }
if(SIGNAL_IMR_Pending == true) if(SIGNAL_IMR_Pending == true)
{ {
DevCon.Warning("Path 2 Paused (At start)"); //DevCon.Warning("Path 2 Paused (At start)");
vif1.vifstalled = true; vif1.vifstalled = true;
return 0; return 0;
} }
@ -175,7 +177,7 @@ template<int idx> __fi int _vifCode_Direct(int pass, const u8* data, bool isDire
uint minSize = aMin(vif1.vifpacketsize, vif1.tag.size); uint minSize = aMin(vif1.vifpacketsize, vif1.tag.size);
uint ret; uint ret;
if(minSize < 4) if(minSize < 4 || partial_count > 0)
{ {
// When TTE==1, the VIF might end up sending us 8-byte packets instead of the usual 16-byte // When TTE==1, the VIF might end up sending us 8-byte packets instead of the usual 16-byte
// variety, if DIRECT tags cross chain dma boundaries. The actual behavior of real hardware // variety, if DIRECT tags cross chain dma boundaries. The actual behavior of real hardware
@ -189,21 +191,24 @@ template<int idx> __fi int _vifCode_Direct(int pass, const u8* data, bool isDire
// be any need to worry about queuing more than 16 bytes of data, // be any need to worry about queuing more than 16 bytes of data,
// //
static __aligned16 u32 partial_write[4];
static uint partial_count = 0;
ret = 0;
minSize = aMin(minSize, 4-partial_count);
for( uint i=0; i<(minSize & 3); ++i) for( uint i=0; i<(minSize & 3); ++i)
{
partial_write[partial_count++] = ((u32*)data)[i]; partial_write[partial_count++] = ((u32*)data)[i];
ret++;
}
pxAssume( partial_count <= 4 ); pxAssume( partial_count <= 4 );
ret = 0;
if (partial_count == 4) if (partial_count == 4)
{ {
GetMTGS().PrepDataPacket(GIF_PATH_2, 1); GetMTGS().PrepDataPacket(GIF_PATH_2, 1);
GIFPath_CopyTag(GIF_PATH_2, (u128*)partial_write, 1); GIFPath_CopyTag(GIF_PATH_2, (u128*)partial_write, 1);
GetMTGS().SendDataPacket(); GetMTGS().SendDataPacket();
partial_count = 0; partial_count = 0;
ret = 4;
} }
} }
else else
@ -372,14 +377,16 @@ vifOp(vifCode_MSCNT) {
vifOp(vifCode_MskPath3) { vifOp(vifCode_MskPath3) {
vif1Only(); vif1Only();
pass1 { pass1 {
//I Hate the timing sensitivity of this stuff
if (vif1ch.chcr.STR && vif1.lastcmd != 0x13) { if (vif1ch.chcr.STR && vif1.lastcmd != 0x13) {
schedulepath3msk = 0x10 | ((vif1Regs.code >> 15) & 0x1); schedulepath3msk = 0x10 | ((vif1Regs.code >> 15) & 0x1);
vif1.vifstalled = true;
} }
else { else
{
schedulepath3msk = (vif1Regs.code >> 15) & 0x1; schedulepath3msk = (vif1Regs.code >> 15) & 0x1;
Vif1MskPath3(); Vif1MskPath3();
} }
if(vif1ch.chcr.STR)vif1.vifstalled = true;
vif1.cmd = 0; vif1.cmd = 0;
} }
pass3 { VifCodeLog("MskPath3"); } pass3 { VifCodeLog("MskPath3"); }

View File

@ -25,7 +25,7 @@
// Doesn't stall if the next vifCode is the Mark command // Doesn't stall if the next vifCode is the Mark command
_vifT bool runMark(u32* &data) { _vifT bool runMark(u32* &data) {
if (((vifXRegs.code >> 24) & 0x7f) == 0x7) { if (((vifXRegs.code >> 24) & 0x7f) == 0x7) {
DevCon.WriteLn("Vif%d: Running Mark with I-bit", idx); //DevCon.WriteLn("Vif%d: Running Mark with I-bit", idx);
return 1; // No Stall? return 1; // No Stall?
} }
return 1; // Stall return 1; // Stall
@ -145,12 +145,21 @@ _vifT static __fi bool vifTransfer(u32 *data, int size, bool TTE) {
vifXch.madr +=(transferred << 4); vifXch.madr +=(transferred << 4);
vifXch.qwc -= transferred; vifXch.qwc -= transferred;
} if(vifXch.chcr.STR)hwDmacSrcTadrInc(vifXch);
if (!vifXch.qwc && !vifX.irqoffset) if (!vifXch.qwc)
{
vifX.inprogress &= ~0x1;
vifX.vifstalled = false;
}
}
else
{ {
vifX.inprogress &= ~0x1;
vifX.vifstalled = false; if(!vifX.irqoffset)
{
vifX.vifstalled = false;
}
} }
if (vifX.irq && vifX.cmd == 0) { if (vifX.irq && vifX.cmd == 0) {

View File

@ -21,22 +21,6 @@
using namespace Threading; using namespace Threading;
// --------------------------------------------------------------------------------------
// BaseArchiveEntry
// --------------------------------------------------------------------------------------
class BaseArchiveEntry
{
protected:
BaseArchiveEntry() {}
virtual ~BaseArchiveEntry() throw() {}
public:
virtual wxString GetFilename() const=0;
virtual u8* GetDataPtr() const=0;
virtual uint GetDataSize() const=0;
};
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
// ArchiveEntry // ArchiveEntry
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------

View File

@ -1,16 +0,0 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 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 PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"

View File

@ -1,21 +0,0 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 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 PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ADVANCEDDIALOG_H_INCLUDED
#define ADVANCEDDIALOG_H_INCLUDED
#endif // ADVANCEDDIALOG_H_INCLUDED

View File

@ -47,6 +47,14 @@ static const int pxID_PadHandler_Keydown = 8030;
// single for-loop to create them. // single for-loop to create them.
static const int PluginMenuId_Interval = 0x10; static const int PluginMenuId_Interval = 0x10;
// ID and return code used for modal popups that have a custom button.
static const wxWindowID pxID_CUSTOM = wxID_LOWEST - 1;
// Return code used by first time wizard if the dialog needs to be automatically recreated
// (assigned an arbitrary value)
static const wxWindowID pxID_RestartWizard = wxID_LOWEST - 100;
// Forces the Interface to destroy the GS viewport window when the GS plugin is // Forces the Interface to destroy the GS viewport window when the GS plugin is
// destroyed. This has the side effect of forcing all plugins to close and re-open // destroyed. This has the side effect of forcing all plugins to close and re-open
// along with the GS, since the GS viewport window handle will have changed. // along with the GS, since the GS viewport window handle will have changed.
@ -109,6 +117,7 @@ enum MenuIdentifiers
MenuId_Config_AppSettings, MenuId_Config_AppSettings,
MenuId_Config_GameDatabase, MenuId_Config_GameDatabase,
MenuId_Config_BIOS, MenuId_Config_BIOS,
MenuId_Config_Language,
// Plugin ID order is important. Must match the order in tbl_PluginInfo. // Plugin ID order is important. Must match the order in tbl_PluginInfo.
MenuId_Config_GS, MenuId_Config_GS,
@ -359,6 +368,10 @@ class Pcsx2AppTraits : public wxGUIAppTraits
public: public:
virtual ~Pcsx2AppTraits() {} virtual ~Pcsx2AppTraits() {}
wxMessageOutput* CreateMessageOutput(); wxMessageOutput* CreateMessageOutput();
#ifdef wxUSE_STDPATHS
wxStandardPathsBase& GetStandardPaths();
#endif
}; };
// ===================================================================================================== // =====================================================================================================

View File

@ -97,26 +97,7 @@ namespace PathDefs
// Specifies the main configuration folder. // Specifies the main configuration folder.
wxDirName GetUserLocalDataDir() wxDirName GetUserLocalDataDir()
{ {
#ifdef __LINUX__
// Note: GetUserLocalDataDir() on linux return $HOME/.pcsx2 unfortunately it does not follow the XDG standard
// So we re-implement it, to follow the standard.
wxDirName user_local_dir;
wxString xdg_home_value;
if( wxGetEnv(L"XDG_CONFIG_HOME", &xdg_home_value) ) {
if ( xdg_home_value.IsEmpty() ) {
// variable exist but it is empty. So use the default value
user_local_dir = (wxDirName)Path::Combine( wxStandardPaths::Get().GetUserConfigDir() , wxDirName( L".config/pcsx2" ));
} else {
user_local_dir = (wxDirName)Path::Combine( xdg_home_value, pxGetAppName());
}
} else {
// variable do not exist
user_local_dir = (wxDirName)Path::Combine( wxStandardPaths::Get().GetUserConfigDir() , wxDirName( L".config/pcsx2" ));
}
return user_local_dir;
#else
return wxDirName(wxStandardPaths::Get().GetUserLocalDataDir()); return wxDirName(wxStandardPaths::Get().GetUserLocalDataDir());
#endif
} }
// Fetches the path location for user-consumable documents -- stuff users are likely to want to // Fetches the path location for user-consumable documents -- stuff users are likely to want to
@ -384,6 +365,7 @@ AppConfig::AppConfig()
, DeskTheme( L"default" ) , DeskTheme( L"default" )
{ {
LanguageId = wxLANGUAGE_DEFAULT; LanguageId = wxLANGUAGE_DEFAULT;
LanguageCode = L"default";
RecentIsoCount = 12; RecentIsoCount = 12;
Listbook_ImageSize = 32; Listbook_ImageSize = 32;
Toolbar_ImageSize = 24; Toolbar_ImageSize = 24;
@ -487,6 +469,7 @@ void AppConfig::LoadSaveRootItems( IniInterface& ini )
IniEntry( AppSettingsTabName ); IniEntry( AppSettingsTabName );
IniEntry( GameDatabaseTabName ); IniEntry( GameDatabaseTabName );
ini.EnumEntry( L"LanguageId", LanguageId, NULL, defaults.LanguageId ); ini.EnumEntry( L"LanguageId", LanguageId, NULL, defaults.LanguageId );
IniEntry( LanguageCode );
IniEntry( RecentIsoCount ); IniEntry( RecentIsoCount );
IniEntry( DeskTheme ); IniEntry( DeskTheme );
IniEntry( Listbook_ImageSize ); IniEntry( Listbook_ImageSize );
@ -780,7 +763,8 @@ void AppConfig_OnChangedSettingsFolder( bool overwrite )
if( overwrite ) if( overwrite )
{ {
if( wxFileExists( iniFilename ) && !wxRemoveFile( iniFilename ) ) if( wxFileExists( iniFilename ) && !wxRemoveFile( iniFilename ) )
throw Exception::AccessDenied(iniFilename).SetBothMsgs(wxLt("Failed to overwrite existing settings file; permission was denied.")); throw Exception::AccessDenied(iniFilename)
.SetBothMsgs(pxL("Failed to overwrite existing settings file; permission was denied."));
} }
// Bind into wxConfigBase to allow wx to use our config internally, and delete whatever // Bind into wxConfigBase to allow wx to use our config internally, and delete whatever

View File

@ -195,9 +195,14 @@ public:
wxString AppSettingsTabName; wxString AppSettingsTabName;
wxString GameDatabaseTabName; wxString GameDatabaseTabName;
// Current language in use (correlates to a wxWidgets wxLANGUAGE specifier) // Currently selected language ID -- wxWidgets version-specific identifier. This is one side of
// a two-part configuration that also includes LanguageCode.
wxLanguage LanguageId; wxLanguage LanguageId;
// Current language in use (correlates to the universal language codes, such as "en_US", "de_DE", etc).
// This code is not always unique, which is why we use the language ID also.
wxString LanguageCode;
int RecentIsoCount; // number of files displayed in the Recent Isos list. int RecentIsoCount; // number of files displayed in the Recent Isos list.
// String value describing the desktop theme to use for pcsk2 (icons and background images) // String value describing the desktop theme to use for pcsk2 (icons and background images)

View File

@ -41,7 +41,7 @@ static void CpuCheckSSE2()
wxDialogWithHelpers exconf( NULL, _("PCSX2 - SSE2 Recommended") ); wxDialogWithHelpers exconf( NULL, _("PCSX2 - SSE2 Recommended") );
exconf += exconf.Heading( pxE( ".Popup:Startup:NoSSE2", exconf += exconf.Heading( pxE( "!Notice:Startup:NoSSE2",
L"Warning: Your computer does not support SSE2, which is required by many PCSX2 recompilers and plugins. " L"Warning: Your computer does not support SSE2, which is required by many PCSX2 recompilers and plugins. "
L"Your options will be limited and emulation will be *very* slow." ) L"Your options will be limited and emulation will be *very* slow." )
); );
@ -70,12 +70,30 @@ void Pcsx2App::WipeUserModeSettings()
usermodefile.SetPath( usrlocaldir.ToString() ); usermodefile.SetPath( usrlocaldir.ToString() );
ScopedPtr<wxFileConfig> conf_usermode( OpenFileConfig( usermodefile.GetFullPath() ) ); ScopedPtr<wxFileConfig> conf_usermode( OpenFileConfig( usermodefile.GetFullPath() ) );
wxString groupname( wxsFormat( L"CWD.%08x", hashres ) ); FastFormatUnicode groupname;
groupname.Write( L"CWD.%08x", hashres );
Console.WriteLn( "(UserModeSettings) Removing entry:" ); Console.WriteLn( "(UserModeSettings) Removing entry:" );
Console.Indent().WriteLn( L"Path: %s\nHash:%s", cwd.c_str(), groupname.c_str() ); Console.Indent().WriteLn( L"Path: %s\nHash:%s", cwd.c_str(), groupname.c_str() );
conf_usermode->DeleteGroup( groupname ); conf_usermode->DeleteGroup( groupname );
} }
static void DoFirstTimeWizard()
{
// first time startup, so give the user the choice of user mode:
while(true)
{
// PCSX2's FTWizard allows improptu restarting of the wizard without cancellation. This is
// typically used to change the user's language selection.
FirstTimeWizard wiz( NULL );
if( wiz.RunWizard( wiz.GetUsermodePage() ) ) break;
if (wiz.GetReturnCode() != pxID_RestartWizard)
throw Exception::StartupAborted( L"User canceled FirstTime Wizard." );
Console.WriteLn( Color_StrongBlack, "Restarting First Time Wizard!" );
}
}
// User mode settings can't be stored in the CWD for two reasons: // User mode settings can't be stored in the CWD for two reasons:
// (a) the user may not have permission to do so (most obvious) // (a) the user may not have permission to do so (most obvious)
// (b) it would result in sloppy usermode.ini found all over a hard drive if people runs the // (b) it would result in sloppy usermode.ini found all over a hard drive if people runs the
@ -104,7 +122,8 @@ void Pcsx2App::ReadUserModeSettings()
usermodefile.SetPath( usrlocaldir.ToString() ); usermodefile.SetPath( usrlocaldir.ToString() );
ScopedPtr<wxFileConfig> conf_usermode( OpenFileConfig( usermodefile.GetFullPath() ) ); ScopedPtr<wxFileConfig> conf_usermode( OpenFileConfig( usermodefile.GetFullPath() ) );
wxString groupname( wxsFormat( L"CWD.%08x", hashres ) ); FastFormatUnicode groupname;
groupname.Write( L"CWD.%08x", hashres );
bool hasGroup = conf_usermode->HasGroup( groupname ); bool hasGroup = conf_usermode->HasGroup( groupname );
bool forceWiz = Startup.ForceWizard || !hasGroup; bool forceWiz = Startup.ForceWizard || !hasGroup;
@ -135,10 +154,7 @@ void Pcsx2App::ReadUserModeSettings()
} }
#endif #endif
// first time startup, so give the user the choice of user mode: DoFirstTimeWizard();
FirstTimeWizard wiz( NULL );
if( !wiz.RunWizard( wiz.GetUsermodePage() ) )
throw Exception::StartupAborted( L"User canceled FirstTime Wizard." );
// Save user's new settings // Save user's new settings
IniSaver saver( *conf_usermode ); IniSaver saver( *conf_usermode );
@ -159,14 +175,8 @@ void Pcsx2App::ReadUserModeSettings()
if( !wxFile::Exists( GetSettingsFilename() ) ) if( !wxFile::Exists( GetSettingsFilename() ) )
{ {
// user wiped their pcsx2.ini -- needs a reconfiguration via wizard! // user wiped their pcsx2.ini -- needs a reconfiguration via wizard!
// (we skip the first page since it's a usermode.ini thing)
DoFirstTimeWizard();
// Fixme : Skipping the first page is a bad idea, as it does a lot of file / directory checks on hitting Apply.
// If anything is missing, the first page prompts to fix it.
// If we skip this check, it's very likely that actions like creating Memory Cards will fail.
FirstTimeWizard wiz( NULL );
if( !wiz.RunWizard( /*wiz.GetPostUsermodePage()*/ wiz.GetUsermodePage() ) )
throw Exception::StartupAborted( L"User canceled Configuration Wizard." );
// Save user's new settings // Save user's new settings
IniSaver saver( *conf_usermode ); IniSaver saver( *conf_usermode );
@ -236,6 +246,19 @@ void Pcsx2App::OpenProgramLog()
EnableAllLogging(); EnableAllLogging();
if( m_current_focus ) m_current_focus->SetFocus(); if( m_current_focus ) m_current_focus->SetFocus();
// This is test code for printing out all supported languages and their canonical names in wiki-fied
// format. I might use it again soon, so I'm leaving it in for now... --air
/*
for( int li=wxLANGUAGE_UNKNOWN+1; li<wxLANGUAGE_USER_DEFINED; ++li )
{
if (const wxLanguageInfo* info = wxLocale::GetLanguageInfo( li ))
{
if (i18n_IsLegacyLanguageId((wxLanguage)info->Language)) continue;
Console.WriteLn( L"|| %-30s || %-8s ||", info->Description.c_str(), info->CanonicalName.c_str() );
}
}
*/
} }
void Pcsx2App::AllocateCoreStuffs() void Pcsx2App::AllocateCoreStuffs()
@ -264,7 +287,7 @@ void Pcsx2App::AllocateCoreStuffs()
wxDialogWithHelpers exconf( NULL, _("PCSX2 Recompiler Error(s)") ); wxDialogWithHelpers exconf( NULL, _("PCSX2 Recompiler Error(s)") );
exconf += 12; exconf += 12;
exconf += exconf.Heading( pxE( ".Popup:RecompilerInit:Header", exconf += exconf.Heading( pxE( "!Notice:RecompilerInit:Header",
L"Warning: Some of the configured PS2 recompilers failed to initialize and have been disabled:" ) L"Warning: Some of the configured PS2 recompilers failed to initialize and have been disabled:" )
); );
@ -318,7 +341,7 @@ void Pcsx2App::AllocateCoreStuffs()
recOps.EnableVU1 = recOps.EnableVU1 && recOps.UseMicroVU1; recOps.EnableVU1 = recOps.EnableVU1 && recOps.UseMicroVU1;
} }
exconf += exconf.Heading( pxE(".Popup:RecompilerInit:Footer", exconf += exconf.Heading( pxE("!Notice:RecompilerInit:Footer",
L"Note: Recompilers are not necessary for PCSX2 to run, however they typically improve emulation speed substantially. " L"Note: Recompilers are not necessary for PCSX2 to run, however they typically improve emulation speed substantially. "
L"You may have to manually re-enable the recompilers listed above, if you resolve the errors." ) L"You may have to manually re-enable the recompilers listed above, if you resolve the errors." )
); );
@ -365,7 +388,7 @@ void Pcsx2App::OnInitCmdLine( wxCmdLineParser& parser )
const PluginInfo* pi = tbl_PluginInfo; do { const PluginInfo* pi = tbl_PluginInfo; do {
parser.AddOption( wxEmptyString, pi->GetShortname().Lower(), parser.AddOption( wxEmptyString, pi->GetShortname().Lower(),
wxsFormat( _("specify the file to use as the %s plugin"), pi->GetShortname().c_str() ) pxsFmt( _("specify the file to use as the %s plugin"), pi->GetShortname().c_str() )
); );
} while( ++pi, pi->shortname != NULL ); } while( ++pi, pi->shortname != NULL );
@ -524,6 +547,9 @@ bool Pcsx2App::OnInit()
g_Conf = new AppConfig(); g_Conf = new AppConfig();
wxInitAllImageHandlers(); wxInitAllImageHandlers();
Console.WriteLn("Applying operating system default language...");
i18n_SetLanguage( wxLANGUAGE_DEFAULT );
Console.WriteLn("Command line parsing..."); Console.WriteLn("Command line parsing...");
if( !_parent::OnInit() ) return false; if( !_parent::OnInit() ) return false;
Console.WriteLn("Command line parsed!"); Console.WriteLn("Command line parsed!");
@ -552,8 +578,6 @@ bool Pcsx2App::OnInit()
InitDefaultGlobalAccelerators(); InitDefaultGlobalAccelerators();
delete wxLog::SetActiveTarget( new pxLogConsole() ); delete wxLog::SetActiveTarget( new pxLogConsole() );
m_RecentIsoList = new RecentIsoList();
#ifdef __WXMSW__ #ifdef __WXMSW__
pxDwm_Load(); pxDwm_Load();
#endif #endif
@ -775,6 +799,28 @@ protected:
Pcsx2App::Pcsx2App() Pcsx2App::Pcsx2App()
: SysExecutorThread( new SysEvtHandler() ) : SysExecutorThread( new SysEvtHandler() )
{ {
#if 0
{
// Some common labels provided by wxWidgets. wxWidgets translation files are chucked full
// of worthless crap, and tally more than 200k each. We only need these couple.
_("OK");
_("&OK");
_("Cancel");
_("&Cancel");
_("&Apply");
_("&Next >");
_("&Back >");
_("&Back");
_("&Finish");
_("&Save");
_("Save &As...");
_("&Help");
_("&Home");
}
#endif
m_PendingSaves = 0; m_PendingSaves = 0;
m_ScheduledTermination = false; m_ScheduledTermination = false;

View File

@ -29,6 +29,8 @@
#include "Utilities/IniInterface.h" #include "Utilities/IniInterface.h"
#include <wx/stdpaths.h>
#ifdef __WXMSW__ #ifdef __WXMSW__
# include <wx/msw/wrapwin.h> // needed to implement the app! # include <wx/msw/wrapwin.h> // needed to implement the app!
#endif #endif
@ -275,6 +277,12 @@ public:
virtual void Printf(const wxChar* format, ...); virtual void Printf(const wxChar* format, ...);
}; };
// EXTRAORDINARY HACK! wxWidgets does not provide a clean way of overriding the commandline options
// display dialog. The default one uses operating system built-in message/notice windows, which are
// appaling, ugly, and not at all suited to a large number of command line options. Fortunately,
// wxMessageOutputMessageBox::PrintF is only used in like two places, so we can just check for the
// commandline window using an identifier we know is contained in it, and then format our own window
// display. :D --air
void pxMessageOutputMessageBox::Printf(const wxChar* format, ...) void pxMessageOutputMessageBox::Printf(const wxChar* format, ...)
{ {
using namespace pxSizerFlags; using namespace pxSizerFlags;
@ -285,14 +293,16 @@ void pxMessageOutputMessageBox::Printf(const wxChar* format, ...)
out.PrintfV(format, args); out.PrintfV(format, args);
va_end(args); va_end(args);
int pos = out.Find( L"[IsoFile]" ); FastFormatUnicode isoFormatted;
isoFormatted.Write( L"[%s]", _("IsoFile") );
int pos = out.Find( isoFormatted );
if(pos == wxNOT_FOUND) if(pos == wxNOT_FOUND)
{ {
Msgbox::Alert( out ); return; Msgbox::Alert( out ); return;
} }
pos += 9; // strlen of [IsoFile] pos += isoFormatted.Length();
wxDialogWithHelpers popup( NULL, AddAppName(_("%s Commandline Options")) ); wxDialogWithHelpers popup( NULL, AddAppName(_("%s Commandline Options")) );
popup.SetMinWidth( 640 ); popup.SetMinWidth( 640 );
@ -305,8 +315,8 @@ void pxMessageOutputMessageBox::Printf(const wxChar* format, ...)
wxTE_READONLY | wxTE_MULTILINE | wxTE_RICH2 | wxHSCROLL wxTE_READONLY | wxTE_MULTILINE | wxTE_RICH2 | wxHSCROLL
); );
traceArea->SetDefaultStyle( wxTextAttr( wxNullColour, wxNullColour, pxGetFixedFont() ) ); traceArea->SetDefaultStyle( wxTextAttr( wxNullColour, wxNullColour, pxGetFixedFont(9) ) );
traceArea->SetFont( pxGetFixedFont() ); traceArea->SetFont( pxGetFixedFont(9) );
int fonty = traceArea->GetCharHeight(); int fonty = traceArea->GetCharHeight();
@ -328,7 +338,54 @@ wxMessageOutput* Pcsx2AppTraits::CreateMessageOutput()
return new pxMessageOutputMessageBox; return new pxMessageOutputMessageBox;
#endif #endif
} }
// --------------------------------------------------------------------------------------
// Pcsx2StandardPaths
// --------------------------------------------------------------------------------------
#ifdef wxUSE_STDPATHS
class Pcsx2StandardPaths : public wxStandardPaths
{
public:
wxString GetResourcesDir() const
{
return Path::Combine( GetDataDir(), L"Langs" );
}
#ifdef __LINUX__
wxString GetUserLocalDataDir() const
{
// Note: GetUserLocalDataDir() on linux return $HOME/.pcsx2 unfortunately it does not follow the XDG standard
// So we re-implement it, to follow the standard.
wxDirName user_local_dir;
wxString xdg_home_value;
if( wxGetEnv(L"XDG_CONFIG_HOME", &xdg_home_value) ) {
if ( xdg_home_value.IsEmpty() ) {
// variable exist but it is empty. So use the default value
user_local_dir = (wxDirName)Path::Combine( GetUserConfigDir() , wxDirName( L".config/pcsx2" ));
} else {
user_local_dir = (wxDirName)Path::Combine( xdg_home_value, pxGetAppName());
}
} else {
// variable do not exist
user_local_dir = (wxDirName)Path::Combine( GetUserConfigDir() , wxDirName( L".config/pcsx2" ));
}
return user_local_dir.ToString();
}
#endif
};
wxStandardPathsBase& Pcsx2AppTraits::GetStandardPaths()
{
static Pcsx2StandardPaths stdPaths;
return stdPaths;
}
#endif
wxAppTraits* Pcsx2App::CreateTraits()
{
return new Pcsx2AppTraits;
}
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
// FramerateManager (implementations) // FramerateManager (implementations)
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
@ -423,7 +480,7 @@ void Pcsx2App::OnEmuKeyDown( wxKeyEvent& evt )
// are multiple variations on the BIOS and BIOS folder checks). // are multiple variations on the BIOS and BIOS folder checks).
wxString BIOS_GetMsg_Required() wxString BIOS_GetMsg_Required()
{ {
return pxE( ".Popup:BiosDumpRequired", return pxE( "!Notice:BiosDumpRequired",
L"\n\n" L"\n\n"
L"PCSX2 requires a PS2 BIOS in order to run. For legal reasons, you *must* obtain \n" L"PCSX2 requires a PS2 BIOS in order to run. For legal reasons, you *must* obtain \n"
L"a BIOS from an actual PS2 unit that you own (borrowing doesn't count).\n" L"a BIOS from an actual PS2 unit that you own (borrowing doesn't count).\n"
@ -507,7 +564,7 @@ void Pcsx2App::HandleEvent(wxEvtHandler* handler, wxEventFunction func, wxEvent&
wxDialogWithHelpers dialog( NULL, _("PCSX2 Unresponsive Thread"), wxVERTICAL ); wxDialogWithHelpers dialog( NULL, _("PCSX2 Unresponsive Thread"), wxVERTICAL );
dialog += dialog.Heading( ex.FormatDisplayMessage() + L"\n\n" + dialog += dialog.Heading( ex.FormatDisplayMessage() + L"\n\n" +
pxE( ".Popup Error:Thread Deadlock Actions", pxE( "!Notice Error:Thread Deadlock Actions",
L"'Ignore' to continue waiting for the thread to respond.\n" L"'Ignore' to continue waiting for the thread to respond.\n"
L"'Cancel' to attempt to cancel the thread.\n" L"'Cancel' to attempt to cancel the thread.\n"
L"'Terminate' to quit PCSX2 immediately.\n" L"'Terminate' to quit PCSX2 immediately.\n"
@ -574,11 +631,6 @@ void Pcsx2App::ClearPendingSave()
} }
} }
wxAppTraits* Pcsx2App::CreateTraits()
{
return new Pcsx2AppTraits;
}
// This method generates debug assertions if the MainFrame handle is NULL (typically // This method generates debug assertions if the MainFrame handle is NULL (typically
// indicating that PCSX2 is running in NoGUI mode, or that the main frame has been // indicating that PCSX2 is running in NoGUI mode, or that the main frame has been
// closed). In most cases you'll want to use HasMainFrame() to test for thread // closed). In most cases you'll want to use HasMainFrame() to test for thread
@ -622,16 +674,10 @@ void AppApplySettings( const AppConfig* oldconf )
RelocateLogfile(); RelocateLogfile();
if( (oldconf == NULL) || (oldconf->LanguageId != g_Conf->LanguageId) ) if( (oldconf == NULL) || (oldconf->LanguageCode.CmpNoCase(g_Conf->LanguageCode)) )
{ {
wxDoNotLogInThisScope please; wxDoNotLogInThisScope please;
if( !i18n_SetLanguage( g_Conf->LanguageId ) ) i18n_SetLanguage( g_Conf->LanguageId, g_Conf->LanguageCode );
{
if( !i18n_SetLanguage( wxLANGUAGE_DEFAULT ) )
{
i18n_SetLanguage( wxLANGUAGE_ENGLISH );
}
}
} }
CorePlugins.SetSettingsFolder( GetSettingsFolder().ToString() ); CorePlugins.SetSettingsFolder( GetSettingsFolder().ToString() );

View File

@ -80,13 +80,13 @@ pxAppResources::~pxAppResources() throw() {}
wxMenu& Pcsx2App::GetRecentIsoMenu() wxMenu& Pcsx2App::GetRecentIsoMenu()
{ {
pxAssert( !!m_RecentIsoList->Menu ); if (!m_RecentIsoList) m_RecentIsoList = new RecentIsoList();
return *m_RecentIsoList->Menu; return *m_RecentIsoList->Menu;
} }
RecentIsoManager& Pcsx2App::GetRecentIsoManager() RecentIsoManager& Pcsx2App::GetRecentIsoManager()
{ {
pxAssert( !!m_RecentIsoList->Manager ); if (!m_RecentIsoList) m_RecentIsoList = new RecentIsoList();
return *m_RecentIsoList->Manager; return *m_RecentIsoList->Manager;
} }

View File

@ -52,7 +52,7 @@ namespace Exception
public: public:
explicit CannotApplySettings( BaseApplicableConfigPanel* thispanel ) explicit CannotApplySettings( BaseApplicableConfigPanel* thispanel )
{ {
SetBothMsgs(wxLt("Cannot apply new settings, one of the settings is invalid.")); SetBothMsgs(pxL("Cannot apply new settings, one of the settings is invalid."));
m_Panel = thispanel; m_Panel = thispanel;
IsVerbose = true; IsVerbose = true;
} }

View File

@ -409,22 +409,22 @@ ConsoleLogFrame::ConsoleLogFrame( MainEmuFrame *parent, const wxString& title, A
// create Appearance menu and submenus // create Appearance menu and submenus
menuFontSizes.Append( MenuId_FontSize_Small, _("Small"), _("Fits a lot of log in a microcosmically small area."), menuFontSizes.Append( MenuId_FontSize_Small, _("Small"), _t("Fits a lot of log in a microcosmically small area."),
wxITEM_RADIO )->Check( options.FontSize == 7 ); wxITEM_RADIO )->Check( options.FontSize == 7 );
menuFontSizes.Append( MenuId_FontSize_Normal, _("Normal"),_("It's what I use (the programmer guy)."), menuFontSizes.Append( MenuId_FontSize_Normal, _("Normal"),_t("It's what I use (the programmer guy)."),
wxITEM_RADIO )->Check( options.FontSize == 8 ); wxITEM_RADIO )->Check( options.FontSize == 8 );
menuFontSizes.Append( MenuId_FontSize_Large, _("Large"), _("Its nice and readable."), menuFontSizes.Append( MenuId_FontSize_Large, _("Large"), _t("Its nice and readable."),
wxITEM_RADIO )->Check( options.FontSize == 10 ); wxITEM_RADIO )->Check( options.FontSize == 10 );
menuFontSizes.Append( MenuId_FontSize_Huge, _("Huge"), _("In case you have a really high res display."), menuFontSizes.Append( MenuId_FontSize_Huge, _("Huge"), _t("In case you have a really high res display."),
wxITEM_RADIO )->Check( options.FontSize == 12 ); wxITEM_RADIO )->Check( options.FontSize == 12 );
menuFontSizes.AppendSeparator(); menuFontSizes.AppendSeparator();
menuFontSizes.Append( MenuId_ColorScheme_Light, _("Light theme"), _("Default soft-tone color scheme."), wxITEM_RADIO ); menuFontSizes.Append( MenuId_ColorScheme_Light, _("Light theme"), _t("Default soft-tone color scheme."), wxITEM_RADIO );
menuFontSizes.Append( MenuId_ColorScheme_Dark, _("Dark theme"), _("Classic black color scheme for people who enjoy having text seared into their optic nerves."), wxITEM_RADIO ); menuFontSizes.Append( MenuId_ColorScheme_Dark, _("Dark theme"), _t("Classic black color scheme for people who enjoy having text seared into their optic nerves."), wxITEM_RADIO );
menuAppear.AppendSeparator(); menuAppear.AppendSeparator();
menuAppear.Append( wxID_ANY, _("Always on Top"), menuAppear.Append( wxID_ANY, _("Always on Top"),
_("When checked the log window will be visible over other foreground windows."), wxITEM_CHECK ); _t("When checked the log window will be visible over other foreground windows."), wxITEM_CHECK );
menuLog.Append(wxID_SAVE, _("&Save..."), _("Save log contents to file")); menuLog.Append(wxID_SAVE, _("&Save..."), _("Save log contents to file"));
menuLog.Append(wxID_CLEAR, _("C&lear"), _("Clear the log window contents")); menuLog.Append(wxID_CLEAR, _("C&lear"), _("Clear the log window contents"));

View File

@ -89,6 +89,26 @@ namespace Dialogs
virtual wxString& GetConfSettingsTabName() const { return g_Conf->SysSettingsTabName; } virtual wxString& GetConfSettingsTabName() const { return g_Conf->SysSettingsTabName; }
}; };
// --------------------------------------------------------------------------------------
// LanguageSelectionDialog
// --------------------------------------------------------------------------------------
class LanguageSelectionDialog : public BaseConfigurationDialog
{
public:
virtual ~LanguageSelectionDialog() throw() {}
LanguageSelectionDialog(wxWindow* parent=NULL);
static wxString GetNameStatic() { return L"LanguageSelector"; }
wxString GetDialogName() const { return GetNameStatic(); }
protected:
virtual wxString& GetConfSettingsTabName() const
{
pxFailDev("Language selector does not have a listbook or settings tab.");
static wxString fail;
return fail;
}
};
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
// McdConfigDialog // McdConfigDialog
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------

View File

@ -65,7 +65,7 @@ static wxString ResultToString( int result, const MsgButtons& buttons )
case wxID_ABORT: return L"abort"; case wxID_ABORT: return L"abort";
case wxID_RETRY: return L"retry"; case wxID_RETRY: return L"retry";
// [TODO] : maybe add in an Ignore All? // [TODO] : maybe add in an Ignore All?
case wxID_IGNORE: return L"ignore"; case wxID_IGNORE: return L"ignore";
case wxID_RESET: return L"reset"; case wxID_RESET: return L"reset";
@ -73,7 +73,7 @@ static wxString ResultToString( int result, const MsgButtons& buttons )
} }
if (result <= wxID_LOWEST) if (result <= wxID_LOWEST)
return buttons.GetCustomLabel(); return buttons.GetCustomLabelId();
return wxEmptyString; return wxEmptyString;
} }

View File

@ -148,7 +148,7 @@ void Dialogs::CreateMemoryCardDialog::CreateControls()
GetMsg_McdNtfsCompress() GetMsg_McdNtfsCompress()
); );
m_check_CompressNTFS->SetToolTip( pxE( ".Tooltip:ChangingNTFS", m_check_CompressNTFS->SetToolTip( pxEt( "!ContextTip:ChangingNTFS",
L"NTFS compression can be changed manually at any time by using file properties from Windows Explorer." L"NTFS compression can be changed manually at any time by using file properties from Windows Explorer."
) )
); );
@ -161,19 +161,19 @@ void Dialogs::CreateMemoryCardDialog::CreateControls()
const RadioPanelItem tbl_CardSizes[] = const RadioPanelItem tbl_CardSizes[] =
{ {
RadioPanelItem(_("8 MB [most compatible]"), _("This is the standard Sony-provisioned size, and is supported by all games and BIOS versions.")) RadioPanelItem(_("8 MB [most compatible]"), _("This is the standard Sony-provisioned size, and is supported by all games and BIOS versions."))
. SetToolTip(_("Always use this option if you want the safest and surest memory card behavior.")) . SetToolTip(_t("Always use this option if you want the safest and surest memory card behavior."))
. SetInt(8), . SetInt(8),
RadioPanelItem(_("16 MB"), _("A typical size for 3rd-party memory cards which should work with most games.")) RadioPanelItem(_("16 MB"), _("A typical size for 3rd-party memory cards which should work with most games."))
. SetToolTip(_("16 and 32 MB cards have roughly the same compatibility factor.")) . SetToolTip(_t("16 and 32 MB cards have roughly the same compatibility factor."))
. SetInt(16), . SetInt(16),
RadioPanelItem(_("32 MB"), _("A typical size for 3rd-party memory cards which should work with most games.")) RadioPanelItem(_("32 MB"), _("A typical size for 3rd-party memory cards which should work with most games."))
. SetToolTip(_("16 and 32 MB cards have roughly the same compatibility factor.")) . SetToolTip(_t("16 and 32 MB cards have roughly the same compatibility factor."))
. SetInt(32), . SetInt(32),
RadioPanelItem(_("64 MB"), _("Low compatibility warning: Yes it's very big, but may not work with many games.")) RadioPanelItem(_("64 MB"), _("Low compatibility warning: Yes it's very big, but may not work with many games."))
. SetToolTip(_("Use at your own risk. Erratic memory card behavior is possible (though unlikely).")) . SetToolTip(_t("Use at your own risk. Erratic memory card behavior is possible (though unlikely)."))
. SetInt(64) . SetInt(64)
}; };

View File

@ -45,12 +45,12 @@ bool ApplicableWizardPage::PrepForApply()
Panels::SettingsDirPickerPanel::SettingsDirPickerPanel( wxWindow* parent ) Panels::SettingsDirPickerPanel::SettingsDirPickerPanel( wxWindow* parent )
: DirPickerPanel( parent, FolderId_Settings, _("Settings"), AddAppName(_("Select a folder for %s settings")) ) : DirPickerPanel( parent, FolderId_Settings, _("Settings"), AddAppName(_("Select a folder for %s settings")) )
{ {
pxSetToolTip( this, pxE( ".Tooltip:Folders:Settings", pxSetToolTip( this, pxEt( "!ContextTip:Folders:Settings",
L"This is the folder where PCSX2 saves your settings, including settings generated " L"This is the folder where PCSX2 saves your settings, including settings generated "
L"by most plugins (some older plugins may not respect this value)." L"by most plugins (some older plugins may not respect this value)."
) ); ) );
SetStaticDesc( pxE( ".Panel:Folders:Settings", SetStaticDesc( pxE( "!Panel:Folders:Settings",
L"You may optionally specify a location for your PCSX2 settings here. If the location " L"You may optionally specify a location for your PCSX2 settings here. If the location "
L"contains existing PCSX2 settings, you will be given the option to import or overwrite them." L"contains existing PCSX2 settings, you will be given the option to import or overwrite them."
) ); ) );
@ -106,7 +106,7 @@ bool FirstTimeWizard::UsermodePage::PrepForApply()
// FIXME: There's already a file by the same name.. not sure what we should do here. // FIXME: There's already a file by the same name.. not sure what we should do here.
throw Exception::BadStream( path.ToString() ) throw Exception::BadStream( path.ToString() )
.SetDiagMsg(L"Targeted documents folder is already occupied by a file.") .SetDiagMsg(L"Targeted documents folder is already occupied by a file.")
.SetUserMsg(pxE( ".Error:DocsFolderFileConflict", .SetUserMsg(pxE( "!Notice:DocsFolderFileConflict",
L"PCSX2 cannot create a documents folder in the requested location. " L"PCSX2 cannot create a documents folder in the requested location. "
L"The path name matches an existing file. Delete the file or change the documents location, " L"The path name matches an existing file. Delete the file or change the documents location, "
L"and then try again." L"and then try again."
@ -120,7 +120,7 @@ bool FirstTimeWizard::UsermodePage::PrepForApply()
dialog += 12; dialog += 12;
dialog += dialog.Heading( path.ToString() ); dialog += dialog.Heading( path.ToString() );
if( wxID_CANCEL == pxIssueConfirmation( dialog, MsgButtons().Custom(_("Create")).Cancel(), L"CreateNewFolder" ) ) if( wxID_CANCEL == pxIssueConfirmation( dialog, MsgButtons().Custom(_("Create"), "create").Cancel(), L"CreateNewFolder" ) )
return false; return false;
} }
path.Mkdir(); path.Mkdir();
@ -149,7 +149,7 @@ FirstTimeWizard::FirstTimeWizard( wxWindow* parent )
// Temporary tutorial message for the BIOS, needs proof-reading!! // Temporary tutorial message for the BIOS, needs proof-reading!!
m_page_bios += 12; m_page_bios += 12;
m_page_bios += new pxStaticHeading( &m_page_bios, m_page_bios += new pxStaticHeading( &m_page_bios,
pxE( ".Wizard:Bios:Tutorial", pxE( "!Wizard:Bios:Tutorial",
L"PCSX2 requires a *legal* copy of the PS2 BIOS in order to run games.\n" L"PCSX2 requires a *legal* copy of the PS2 BIOS in order to run games.\n"
L"You cannot use a copy obtained from a friend or the Internet.\n" L"You cannot use a copy obtained from a friend or the Internet.\n"
L"You must dump the BIOS from your *own* Playstation 2 console." L"You must dump the BIOS from your *own* Playstation 2 console."
@ -175,6 +175,8 @@ FirstTimeWizard::FirstTimeWizard( wxWindow* parent )
Connect( wxEVT_WIZARD_PAGE_CHANGED, wxWizardEventHandler (FirstTimeWizard::OnPageChanged) ); Connect( wxEVT_WIZARD_PAGE_CHANGED, wxWizardEventHandler (FirstTimeWizard::OnPageChanged) );
Connect( wxEVT_WIZARD_PAGE_CHANGING, wxWizardEventHandler (FirstTimeWizard::OnPageChanging) ); Connect( wxEVT_WIZARD_PAGE_CHANGING, wxWizardEventHandler (FirstTimeWizard::OnPageChanging) );
Connect( wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, wxCommandEventHandler (FirstTimeWizard::OnDoubleClicked) ); Connect( wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, wxCommandEventHandler (FirstTimeWizard::OnDoubleClicked) );
Connect( pxID_RestartWizard, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( FirstTimeWizard::OnRestartWizard ) );
} }
FirstTimeWizard::~FirstTimeWizard() throw() FirstTimeWizard::~FirstTimeWizard() throw()
@ -182,6 +184,12 @@ FirstTimeWizard::~FirstTimeWizard() throw()
} }
void FirstTimeWizard::OnRestartWizard( wxCommandEvent& evt )
{
EndModal( pxID_RestartWizard );
evt.Skip();
}
static void _OpenConsole() static void _OpenConsole()
{ {
g_Conf->ProgLogBox.Visible = true; g_Conf->ProgLogBox.Visible = true;

View File

@ -17,10 +17,13 @@
#include "ConfigurationDialog.h" #include "ConfigurationDialog.h"
#include "Panels/ConfigurationPanels.h" #include "Panels/ConfigurationPanels.h"
using namespace Panels;
using namespace pxSizerFlags;
Dialogs::GameDatabaseDialog::GameDatabaseDialog(wxWindow* parent) Dialogs::GameDatabaseDialog::GameDatabaseDialog(wxWindow* parent)
: BaseConfigurationDialog( parent, AddAppName(_("Game Database - %s")), 580 ) : BaseConfigurationDialog( parent, AddAppName(_("Game database - %s")), 580 )
{ {
ScopedBusyCursor busy( Cursor_ReallyBusy ); ScopedBusyCursor busy( Cursor_ReallyBusy );
*this += new Panels::GameDatabasePanel(this); *this += new GameDatabasePanel(this) | StdExpand();
AddOkCancel(); AddOkCancel();
} }

View File

@ -25,8 +25,10 @@ Dialogs::ImportSettingsDialog::ImportSettingsDialog( wxWindow* parent )
{ {
SetMinWidth( 440 ); SetMinWidth( 440 );
pxStaticText& heading( Text( wxsFormat( pxStaticText& heading( Text( pxsFmt(
pxE( ".Popup:ImportExistingSettings",
/// (%s is the app name, normally PCSX2 -- omitting one or both %s is allowed)
pxE( "!Notice:ImportExistingSettings",
L"Existing %s settings have been found in the configured settings folder. " L"Existing %s settings have been found in the configured settings folder. "
L"Would you like to import these settings or overwrite them with %s default values?" L"Would you like to import these settings or overwrite them with %s default values?"
L"\n\n(or press Cancel to select a different settings folder)" L"\n\n(or press Cancel to select a different settings folder)"

View File

@ -27,7 +27,7 @@ using namespace pxSizerFlags;
wxString GetMsg_McdNtfsCompress() wxString GetMsg_McdNtfsCompress()
{ {
return pxE( ".Panel:Mcd:NtfsCompress", return pxE( "!Panel:Mcd:NtfsCompress",
L"NTFS compression is built-in, fast, and completely reliable; and typically compresses memory cards " L"NTFS compression is built-in, fast, and completely reliable; and typically compresses memory cards "
L"very well (this option is highly recommended)." L"very well (this option is highly recommended)."
); );
@ -38,12 +38,14 @@ Panels::McdConfigPanel_Toggles::McdConfigPanel_Toggles(wxWindow *parent)
{ {
m_check_Ejection = new pxCheckBox( this, m_check_Ejection = new pxCheckBox( this,
_("Auto-eject memory cards when loading savestates"), _("Auto-eject memory cards when loading savestates"),
pxE( ".Panel:Mcd:EnableEjection", pxE( "!Panel:Mcd:EnableEjection",
L"Avoids memory card corruption by forcing games to re-index card contents after " L"Avoids memory card corruption by forcing games to re-index card contents after "
L"loading from savestates. May not be compatible with all games (Guitar Hero)." L"loading from savestates. May not be compatible with all games (Guitar Hero)."
) )
); );
m_check_SavestateBackup = new pxCheckBox( this, pxsFmt(_("Backup existing Savestate when creating a new one")) );
for( uint i=0; i<2; ++i ) for( uint i=0; i<2; ++i )
{ {
m_check_Multitap[i] = new pxCheckBox( this, pxsFmt(_("Enable Multitap on Port %u"), i+1) ); m_check_Multitap[i] = new pxCheckBox( this, pxsFmt(_("Enable Multitap on Port %u"), i+1) );
@ -60,23 +62,29 @@ Panels::McdConfigPanel_Toggles::McdConfigPanel_Toggles(wxWindow *parent)
*this += 4; *this += 4;
*this += m_check_SavestateBackup;
*this += 4;
*this += m_check_Ejection; *this += m_check_Ejection;
} }
void Panels::McdConfigPanel_Toggles::Apply() void Panels::McdConfigPanel_Toggles::Apply()
{ {
g_Conf->EmuOptions.MultitapPort0_Enabled = m_check_Multitap[0]->GetValue(); g_Conf->EmuOptions.MultitapPort0_Enabled = m_check_Multitap[0]->GetValue();
g_Conf->EmuOptions.MultitapPort1_Enabled = m_check_Multitap[1]->GetValue(); g_Conf->EmuOptions.MultitapPort1_Enabled = m_check_Multitap[1]->GetValue();
g_Conf->EmuOptions.McdEnableEjection = m_check_Ejection->GetValue(); g_Conf->EmuOptions.BackupSavestate = m_check_SavestateBackup->GetValue();
g_Conf->EmuOptions.McdEnableEjection = m_check_Ejection->GetValue();
} }
void Panels::McdConfigPanel_Toggles::AppStatusEvent_OnSettingsApplied() void Panels::McdConfigPanel_Toggles::AppStatusEvent_OnSettingsApplied()
{ {
m_check_Multitap[0] ->SetValue( g_Conf->EmuOptions.MultitapPort0_Enabled ); m_check_Multitap[0] ->SetValue( g_Conf->EmuOptions.MultitapPort0_Enabled );
m_check_Multitap[1] ->SetValue( g_Conf->EmuOptions.MultitapPort1_Enabled ); m_check_Multitap[1] ->SetValue( g_Conf->EmuOptions.MultitapPort1_Enabled );
m_check_Ejection ->SetValue( g_Conf->EmuOptions.McdEnableEjection ); m_check_SavestateBackup ->SetValue( g_Conf->EmuOptions.BackupSavestate );
m_check_Ejection ->SetValue( g_Conf->EmuOptions.McdEnableEjection );
} }
@ -91,9 +99,6 @@ Dialogs::McdConfigDialog::McdConfigDialog( wxWindow* parent )
// [TODO] : Plan here is to add an advanced tab which gives the user the ability // [TODO] : Plan here is to add an advanced tab which gives the user the ability
// to configure the names of each memory card slot. // to configure the names of each memory card slot.
//AddPage<McdConfigPanel_Toggles> ( wxLt("Settings"), cfgid.MemoryCard );
//AddPage<McdConfigPanel_Standard> ( wxLt("Slots 1/2"), cfgid.MemoryCard );
*this += Heading(_("Drag items over other items in the list to swap or copy memory cards.")) | StdExpand(); *this += Heading(_("Drag items over other items in the list to swap or copy memory cards.")) | StdExpand();
*this += StdPadding; *this += StdPadding;

View File

@ -21,8 +21,6 @@
#include <wx/wizard.h> #include <wx/wizard.h>
static const wxWindowID pxID_CUSTOM = wxID_LOWEST - 1;
class FirstTimeWizard : public wxWizard class FirstTimeWizard : public wxWizard
{ {
typedef wxWizard _parent; typedef wxWizard _parent;
@ -71,6 +69,8 @@ protected:
virtual void OnPageChanging( wxWizardEvent& evt ); virtual void OnPageChanging( wxWizardEvent& evt );
virtual void OnPageChanged( wxWizardEvent& evt ); virtual void OnPageChanged( wxWizardEvent& evt );
virtual void OnDoubleClicked( wxCommandEvent& evt ); virtual void OnDoubleClicked( wxCommandEvent& evt );
void OnRestartWizard( wxCommandEvent& evt );
}; };

View File

@ -30,7 +30,7 @@ Dialogs::StuckThreadDialog::StuckThreadDialog( wxWindow* parent, StuckThreadActi
stuck_thread.AddListener( this ); stuck_thread.AddListener( this );
*this += Heading( wxsFormat( *this += Heading( wxsFormat(
pxE( ".Panel:StuckThread:Heading", pxE( "!Panel:StuckThread:Heading",
L"The thread '%s' is not responding. It could be deadlocked, or it might " L"The thread '%s' is not responding. It could be deadlocked, or it might "
L"just be running *really* slowly." L"just be running *really* slowly."
), ),
@ -43,7 +43,7 @@ Dialogs::StuckThreadDialog::StuckThreadDialog( wxWindow* parent, StuckThreadActi
L"\nOr press [Ignore] to suppress further assertions." L"\nOr press [Ignore] to suppress further assertions."
); );
*this += new ModalButtonPanel( this, MsgButtons().Cancel().Custom(L"Wait") ) | StdCenter(); *this += new ModalButtonPanel( this, MsgButtons().Cancel().Custom(L"Wait", "wait") ) | StdCenter();
if( wxWindow* idyes = FindWindowById( wxID_YES ) ) if( wxWindow* idyes = FindWindowById( wxID_YES ) )
idyes->SetFocus(); idyes->SetFocus();

View File

@ -23,6 +23,7 @@
#include "Panels/ConfigurationPanels.h" #include "Panels/ConfigurationPanels.h"
using namespace Panels; using namespace Panels;
using namespace pxSizerFlags;
static void CheckHacksOverrides() static void CheckHacksOverrides()
{ {
@ -33,7 +34,7 @@ static void CheckHacksOverrides()
wxDialogWithHelpers dialog( wxFindWindowByName( L"Dialog:" + Dialogs::SysConfigDialog::GetNameStatic() ), _("Config Overrides Warning") ); wxDialogWithHelpers dialog( wxFindWindowByName( L"Dialog:" + Dialogs::SysConfigDialog::GetNameStatic() ), _("Config Overrides Warning") );
dialog += dialog.Text( pxE(".Panel:HasHacksOverrides", dialog += dialog.Text( pxE("!Panel:HasHacksOverrides",
L"Warning! You are running PCSX2 with command line options that override your configured settings. " L"Warning! You are running PCSX2 with command line options that override your configured settings. "
L"These command line options will not be reflected in the Settings dialog, and will be disabled " L"These command line options will not be reflected in the Settings dialog, and will be disabled "
L"if you apply any changes here." L"if you apply any changes here."
@ -53,7 +54,7 @@ static void CheckPluginsOverrides()
wxDialogWithHelpers dialog( NULL, _("Components Overrides Warning") ); wxDialogWithHelpers dialog( NULL, _("Components Overrides Warning") );
dialog += dialog.Text( pxE(".Panel:HasPluginsOverrides", dialog += dialog.Text( pxE("!Panel:HasPluginsOverrides",
L"Warning! You are running PCSX2 with command line options that override your configured plugin and/or folder settings. " L"Warning! You are running PCSX2 with command line options that override your configured plugin and/or folder settings. "
L"These command line options will not be reflected in the settings dialog, and will be disabled " L"These command line options will not be reflected in the settings dialog, and will be disabled "
L"when you apply settings changes here." L"when you apply settings changes here."
@ -72,13 +73,12 @@ Dialogs::SysConfigDialog::SysConfigDialog(wxWindow* parent)
CreateListbook( wxGetApp().GetImgList_Config() ); CreateListbook( wxGetApp().GetImgList_Config() );
const AppImageIds::ConfigIds& cfgid( wxGetApp().GetImgId().Config ); const AppImageIds::ConfigIds& cfgid( wxGetApp().GetImgId().Config );
AddPage<CpuPanelEE> ( wxLt("EE/IOP"), cfgid.Cpu ); AddPage<CpuPanelEE> ( pxL("EE/IOP"), cfgid.Cpu );
AddPage<CpuPanelVU> ( wxLt("VUs"), cfgid.Cpu ); AddPage<CpuPanelVU> ( pxL("VUs"), cfgid.Cpu );
AddPage<VideoPanel> ( wxLt("GS"), cfgid.Cpu ); AddPage<VideoPanel> ( pxL("GS"), cfgid.Cpu );
AddPage<GSWindowSettingsPanel> ( wxLt("GS Window"), cfgid.Video ); AddPage<GSWindowSettingsPanel> ( pxL("GS Window"), cfgid.Video );
AddPage<SpeedHacksPanel> ( wxLt("Speedhacks"), cfgid.Speedhacks ); AddPage<SpeedHacksPanel> ( pxL("Speedhacks"), cfgid.Speedhacks );
AddPage<GameFixesPanel> ( wxLt("Game Fixes"), cfgid.Gamefixes ); AddPage<GameFixesPanel> ( pxL("Game Fixes"), cfgid.Gamefixes );
//AddPage<GameDatabasePanel> ( wxLt("Game Database"),cfgid.Plugins );
AddListbook(); AddListbook();
AddOkCancel(); AddOkCancel();
@ -95,9 +95,9 @@ Dialogs::ComponentsConfigDialog::ComponentsConfigDialog(wxWindow* parent)
CreateListbook( wxGetApp().GetImgList_Config() ); CreateListbook( wxGetApp().GetImgList_Config() );
const AppImageIds::ConfigIds& cfgid( wxGetApp().GetImgId().Config ); const AppImageIds::ConfigIds& cfgid( wxGetApp().GetImgId().Config );
AddPage<PluginSelectorPanel> ( wxLt("Plugins"), cfgid.Plugins ); AddPage<PluginSelectorPanel> ( pxL("Plugins"), cfgid.Plugins );
AddPage<BiosSelectorPanel> ( wxLt("BIOS"), cfgid.Cpu ); AddPage<BiosSelectorPanel> ( pxL("BIOS"), cfgid.Cpu );
AddPage<StandardPathsPanel> ( wxLt("Folders"), cfgid.Paths ); AddPage<StandardPathsPanel> ( pxL("Folders"), cfgid.Paths );
AddListbook(); AddListbook();
AddOkCancel(); AddOkCancel();
@ -105,3 +105,13 @@ Dialogs::ComponentsConfigDialog::ComponentsConfigDialog(wxWindow* parent)
if( wxGetApp().Overrides.HasPluginsOverride() ) if( wxGetApp().Overrides.HasPluginsOverride() )
wxGetApp().PostMethod( CheckPluginsOverrides ); wxGetApp().PostMethod( CheckPluginsOverrides );
} }
Dialogs::LanguageSelectionDialog::LanguageSelectionDialog(wxWindow *parent)
: BaseConfigurationDialog( parent, AddAppName(_("Language Selector - %s")), 400 )
{
ScopedBusyCursor busy( Cursor_ReallyBusy );
*this += new Panels::LanguageSelectionPanel( this ) | pxCenter;
wxDialogWithHelpers::AddOkCancel( NULL, false );
}

View File

@ -23,13 +23,13 @@ using namespace pxSizerFlags;
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
bool ConsoleLogSource_Event::Write( const pxEvtHandler* evtHandler, const SysExecEvent* evt, const wxChar* msg ) { bool ConsoleLogSource_Event::Write( const pxEvtHandler* evtHandler, const SysExecEvent* evt, const wxChar* msg ) {
return _parent::Write( wxsFormat(L"(%s%s) ", evtHandler->GetEventHandlerName().c_str(), evt->GetEventName().c_str()) + msg ); return _parent::Write( pxsFmt(L"(%s:%s) ", evtHandler->GetEventHandlerName().c_str(), evt->GetEventName().c_str()) + msg );
} }
bool ConsoleLogSource_Event::Warn( const pxEvtHandler* evtHandler, const SysExecEvent* evt, const wxChar* msg ) { bool ConsoleLogSource_Event::Warn( const pxEvtHandler* evtHandler, const SysExecEvent* evt, const wxChar* msg ) {
return _parent::Write( wxsFormat(L"(%s%s) ", evtHandler->GetEventHandlerName().c_str(), evt->GetEventName().c_str()) + msg ); return _parent::Write( pxsFmt(L"(%s:%s) ", evtHandler->GetEventHandlerName().c_str(), evt->GetEventName().c_str()) + msg );
} }
bool ConsoleLogSource_Event::Error( const pxEvtHandler* evtHandler, const SysExecEvent* evt, const wxChar* msg ) { bool ConsoleLogSource_Event::Error( const pxEvtHandler* evtHandler, const SysExecEvent* evt, const wxChar* msg ) {
return _parent::Write( wxsFormat(L"(%s%s) ", evtHandler->GetEventHandlerName().c_str(), evt->GetEventName().c_str()) + msg ); return _parent::Write( pxsFmt(L"(%s:%s) ", evtHandler->GetEventHandlerName().c_str(), evt->GetEventName().c_str()) + msg );
} }
ConsoleLogSource_Event::ConsoleLogSource_Event() ConsoleLogSource_Event::ConsoleLogSource_Event()
@ -37,7 +37,7 @@ ConsoleLogSource_Event::ConsoleLogSource_Event()
static const TraceLogDescriptor myDesc = static const TraceLogDescriptor myDesc =
{ {
L"SysEvents", L"SysVM Control Events", L"SysEvents", L"SysVM Control Events",
wxLt("Logs events as they are passed to the PS2 virtual machine."), pxLt("Logs events as they are passed to the PS2 virtual machine."),
}; };
m_Descriptor = &myDesc; m_Descriptor = &myDesc;

View File

@ -386,8 +386,7 @@ void GSFrame::OnUpdateTitle( wxTimerEvent& evt )
double fps = wxGetApp().FpsManager.GetFramerate(); double fps = wxGetApp().FpsManager.GetFramerate();
char gsDest[128]; char gsDest[128];
GSgetTitleInfo( gsDest ); GSgetTitleInfo2( gsDest, sizeof(gsDest) );
const wxChar* limiterStr = L"None"; const wxChar* limiterStr = L"None";
@ -401,16 +400,16 @@ void GSFrame::OnUpdateTitle( wxTimerEvent& evt )
} }
} }
wxString cpuUsage; FastFormatUnicode cpuUsage;
if( m_CpuUsage.IsImplemented() ) if( m_CpuUsage.IsImplemented() )
{ {
m_CpuUsage.UpdateStats(); m_CpuUsage.UpdateStats();
cpuUsage = wxsFormat( L" | EE: %3d%% | GS: %3d%% | UI: %3d%%", m_CpuUsage.GetEEcorePct(), m_CpuUsage.GetGsPct(), m_CpuUsage.GetGuiPct() ); cpuUsage.Write( L" | EE: %3d%% | GS: %3d%% | UI: %3d%%", m_CpuUsage.GetEEcorePct(), m_CpuUsage.GetGsPct(), m_CpuUsage.GetGuiPct() );
} }
const u64& smode2 = *(u64*)PS2GS_BASE(GS_SMODE2); const u64& smode2 = *(u64*)PS2GS_BASE(GS_SMODE2);
SetTitle( wxsFormat( L"%s | %s (%s) | Limiter: %s | fps: %6.02f%s", SetTitle( pxsFmt( L"%s | %s (%s) | Limiter: %s | fps: %6.02f%s",
fromUTF8(gsDest).c_str(), fromUTF8(gsDest).c_str(),
(smode2 & 1) ? L"Interlaced" : L"Progressive", (smode2 & 1) ? L"Interlaced" : L"Progressive",
(smode2 & 2) ? L"frame" : L"field", (smode2 & 2) ? L"frame" : L"field",

View File

@ -240,26 +240,26 @@ static const GlobalCommandDescriptor CommandDeclarations[] =
{ {
{ "States_FreezeCurrentSlot", { "States_FreezeCurrentSlot",
States_FreezeCurrentSlot, States_FreezeCurrentSlot,
wxLt( "Save state" ), pxL( "Save state" ),
wxLt( "Saves the virtual machine state to the current slot." ), pxL( "Saves the virtual machine state to the current slot." ),
}, },
{ "States_DefrostCurrentSlot", { "States_DefrostCurrentSlot",
States_DefrostCurrentSlot, States_DefrostCurrentSlot,
wxLt( "Load state" ), pxL( "Load state" ),
wxLt( "Loads a virtual machine state from the current slot." ), pxL( "Loads a virtual machine state from the current slot." ),
}, },
{ "States_CycleSlotForward", { "States_CycleSlotForward",
States_CycleSlotForward, States_CycleSlotForward,
wxLt( "Cycle to next slot" ), pxL( "Cycle to next slot" ),
wxLt( "Cycles the current save slot in +1 fashion!" ), pxL( "Cycles the current save slot in +1 fashion!" ),
}, },
{ "States_CycleSlotBackward", { "States_CycleSlotBackward",
States_CycleSlotBackward, States_CycleSlotBackward,
wxLt( "Cycle to prev slot" ), pxL( "Cycle to prev slot" ),
wxLt( "Cycles the current save slot in -1 fashion!" ), pxL( "Cycles the current save slot in -1 fashion!" ),
}, },
{ "Frameskip_Toggle", { "Frameskip_Toggle",

View File

@ -25,7 +25,7 @@
wxString GetMsg_ConfirmSysReset() wxString GetMsg_ConfirmSysReset()
{ {
return pxE( ".Popup:ConfirmSysReset", return pxE( "!Notice:ConfirmSysReset",
L"This action will reset the existing PS2 virtual machine state; " L"This action will reset the existing PS2 virtual machine state; "
L"all current progress will be lost. Are you sure?" L"all current progress will be lost. Are you sure?"
); );

View File

@ -61,6 +61,29 @@ void MainEmuFrame::UpdateIsoSrcSelection()
// exists ? Path::GetFilename(g_Conf->CurrentIso).c_str() : _("Empty") ) ); // exists ? Path::GetFilename(g_Conf->CurrentIso).c_str() : _("Empty") ) );
} }
bool MainEmuFrame::Destroy()
{
// Sigh: wxWidgets doesn't issue Destroy() calls for children windows when the parent
// is destroyed (it just deletes them, quite suddenly). So let's do it for them, since
// our children have configuration stuff they like to do when they're closing.
for (
wxWindowList::const_iterator
i = wxTopLevelWindows.begin(),
end = wxTopLevelWindows.end();
i != end; ++i
)
{
wxTopLevelWindow * const win = wx_static_cast(wxTopLevelWindow *, *i);
if (win == this) continue;
if (win->GetParent() != this) continue;
win->Destroy();
}
return _parent::Destroy();
}
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// MainFrame OnEvent Handlers // MainFrame OnEvent Handlers
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
@ -157,6 +180,7 @@ void MainEmuFrame::ConnectMenus()
ConnectMenu( MenuId_Config_AppSettings, Menu_WindowSettings_Click ); ConnectMenu( MenuId_Config_AppSettings, Menu_WindowSettings_Click );
ConnectMenu( MenuId_Config_GameDatabase,Menu_GameDatabase_Click ); ConnectMenu( MenuId_Config_GameDatabase,Menu_GameDatabase_Click );
ConnectMenu( MenuId_Config_BIOS, Menu_SelectPluginsBios_Click ); ConnectMenu( MenuId_Config_BIOS, Menu_SelectPluginsBios_Click );
ConnectMenu( MenuId_Config_Language, Menu_Language_Click );
ConnectMenu( MenuId_Config_ResetAll, Menu_ResetAllSettings_Click ); ConnectMenu( MenuId_Config_ResetAll, Menu_ResetAllSettings_Click );
ConnectMenu( MenuId_Config_Multitap0Toggle, Menu_MultitapToggle_Click ); ConnectMenu( MenuId_Config_Multitap0Toggle, Menu_MultitapToggle_Click );
@ -290,8 +314,8 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title)
, m_LoadStatesSubmenu( *MakeStatesSubMenu( MenuId_State_Load01 ) ) , m_LoadStatesSubmenu( *MakeStatesSubMenu( MenuId_State_Load01 ) )
, m_SaveStatesSubmenu( *MakeStatesSubMenu( MenuId_State_Save01 ) ) , m_SaveStatesSubmenu( *MakeStatesSubMenu( MenuId_State_Save01 ) )
, m_MenuItem_Console( *new wxMenuItem( &m_menuMisc, MenuId_Console, L"Show Console", wxEmptyString, wxITEM_CHECK ) ) , m_MenuItem_Console( *new wxMenuItem( &m_menuMisc, MenuId_Console, _("Show Console"), wxEmptyString, wxITEM_CHECK ) )
, m_MenuItem_Console_Stdio( *new wxMenuItem( &m_menuMisc, MenuId_Console_Stdio, L"Console to Stdio", wxEmptyString, wxITEM_CHECK ) ) , m_MenuItem_Console_Stdio( *new wxMenuItem( &m_menuMisc, MenuId_Console_Stdio, _("Console to Stdio"), wxEmptyString, wxITEM_CHECK ) )
{ {
m_RestartEmuOnDelete = false; m_RestartEmuOnDelete = false;
@ -423,12 +447,17 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title)
m_menuConfig.Append(MenuId_Config_SysSettings, _("Emulation &Settings") ); m_menuConfig.Append(MenuId_Config_SysSettings, _("Emulation &Settings") );
m_menuConfig.Append(MenuId_Config_McdSettings, _("&Memory cards") ); m_menuConfig.Append(MenuId_Config_McdSettings, _("&Memory cards") );
m_menuConfig.Append(MenuId_Config_BIOS, _("&Plugin/BIOS Selector") ); m_menuConfig.Append(MenuId_Config_BIOS, _("&Plugin/BIOS Selector") );
m_menuConfig.Append(MenuId_Config_GameDatabase, _("Game Database Editor") ); if (IsDebugBuild)
{
m_menuConfig.Append(MenuId_Config_GameDatabase, _("Game Database Editor") );
m_menuConfig.Append(MenuId_Config_Language, _("Language...") );
}
m_menuConfig.AppendSeparator(); m_menuConfig.AppendSeparator();
m_menuConfig.Append(MenuId_Config_GS, _("&Video (GS)"), m_PluginMenuPacks[PluginId_GS]); m_menuConfig.Append(MenuId_Config_GS, _("&Video (GS)"), m_PluginMenuPacks[PluginId_GS]);
m_menuConfig.Append(MenuId_Config_SPU2, _("&Audio (SPU2)"), m_PluginMenuPacks[PluginId_SPU2]); m_menuConfig.Append(MenuId_Config_SPU2, _("&Audio (SPU2)"), m_PluginMenuPacks[PluginId_SPU2]);
m_menuConfig.Append(MenuId_Config_PAD, _("&Controllers (PAD)"), m_PluginMenuPacks[PluginId_PAD]); m_menuConfig.Append(MenuId_Config_PAD, _("&Controllers (PAD)"),m_PluginMenuPacks[PluginId_PAD]);
m_menuConfig.Append(MenuId_Config_DEV9, _("Dev9"), m_PluginMenuPacks[PluginId_DEV9]); m_menuConfig.Append(MenuId_Config_DEV9, _("Dev9"), m_PluginMenuPacks[PluginId_DEV9]);
m_menuConfig.Append(MenuId_Config_USB, _("USB"), m_PluginMenuPacks[PluginId_USB]); m_menuConfig.Append(MenuId_Config_USB, _("USB"), m_PluginMenuPacks[PluginId_USB]);
m_menuConfig.Append(MenuId_Config_FireWire, _("Firewire"), m_PluginMenuPacks[PluginId_FW]); m_menuConfig.Append(MenuId_Config_FireWire, _("Firewire"), m_PluginMenuPacks[PluginId_FW]);
@ -458,7 +487,7 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title)
//m_menuMisc.Append(41, "Patch Browser...", wxEmptyString, wxITEM_NORMAL); //m_menuMisc.Append(41, "Patch Browser...", wxEmptyString, wxITEM_NORMAL);
//m_menuMisc.Append(42, "Patch Finder...", wxEmptyString, wxITEM_NORMAL); //m_menuMisc.Append(42, "Patch Finder...", wxEmptyString, wxITEM_NORMAL);
m_menuMisc.Append(MenuId_CDVD_Info, _T("Print CDVD Info"), wxEmptyString, wxITEM_CHECK); m_menuMisc.Append(MenuId_CDVD_Info, _("Print CDVD Info"), wxEmptyString, wxITEM_CHECK);
m_menuMisc.AppendSeparator(); m_menuMisc.AppendSeparator();
//Todo: //Todo:

View File

@ -145,6 +145,8 @@ public:
void UpdateIsoSrcSelection(); void UpdateIsoSrcSelection();
void RemoveCdvdMenu(); void RemoveCdvdMenu();
void EnableMenuItem( int id, bool enable ); void EnableMenuItem( int id, bool enable );
bool Destroy();
protected: protected:
void DoGiveHelp(const wxString& text, bool show); void DoGiveHelp(const wxString& text, bool show);
@ -166,6 +168,7 @@ protected:
void Menu_WindowSettings_Click(wxCommandEvent &event); void Menu_WindowSettings_Click(wxCommandEvent &event);
void Menu_GSSettings_Click(wxCommandEvent &event); void Menu_GSSettings_Click(wxCommandEvent &event);
void Menu_SelectPluginsBios_Click(wxCommandEvent &event); void Menu_SelectPluginsBios_Click(wxCommandEvent &event);
void Menu_Language_Click(wxCommandEvent &event);
void Menu_ResetAllSettings_Click(wxCommandEvent &event); void Menu_ResetAllSettings_Click(wxCommandEvent &event);
void Menu_IsoBrowse_Click(wxCommandEvent &event); void Menu_IsoBrowse_Click(wxCommandEvent &event);

View File

@ -50,7 +50,7 @@ void MainEmuFrame::Menu_McdSettings_Click(wxCommandEvent &event)
void MainEmuFrame::Menu_GameDatabase_Click(wxCommandEvent &event) void MainEmuFrame::Menu_GameDatabase_Click(wxCommandEvent &event)
{ {
AppOpenDialog<McdConfigDialog>( this ); AppOpenDialog<GameDatabaseDialog>( this );
} }
void MainEmuFrame::Menu_WindowSettings_Click(wxCommandEvent &event) void MainEmuFrame::Menu_WindowSettings_Click(wxCommandEvent &event)
@ -72,6 +72,11 @@ void MainEmuFrame::Menu_SelectPluginsBios_Click(wxCommandEvent &event)
AppOpenDialog<ComponentsConfigDialog>( this ); AppOpenDialog<ComponentsConfigDialog>( this );
} }
void MainEmuFrame::Menu_Language_Click(wxCommandEvent &event)
{
//AppOpenDialog<LanguageSelectionDialog>( this );
LanguageSelectionDialog(this).ShowModal();
}
static void WipeSettings() static void WipeSettings()
{ {
@ -104,7 +109,7 @@ void MainEmuFrame::Menu_ResetAllSettings_Click(wxCommandEvent &event)
{ {
ScopedCoreThreadPopup suspender; ScopedCoreThreadPopup suspender;
if( !Msgbox::OkCancel( pxsFmt( if( !Msgbox::OkCancel( pxsFmt(
pxE( ".Popup:DeleteSettings", pxE( "!Notice:DeleteSettings",
L"This command clears %s settings and allows you to re-run the First-Time Wizard. You will need to " L"This command clears %s settings and allows you to re-run the First-Time Wizard. You will need to "
L"manually restart %s after this operation.\n\n" L"manually restart %s after this operation.\n\n"
L"WARNING!! Click OK to delete *ALL* settings for %s and force-close the app, losing any current emulation progress. Are you absolutely sure?" L"WARNING!! Click OK to delete *ALL* settings for %s and force-close the app, losing any current emulation progress. Are you absolutely sure?"
@ -146,7 +151,7 @@ wxWindowID SwapOrReset_Iso( wxWindow* owner, IScopedCoreThread& core_control, co
dialog += dialog.GetCharHeight(); dialog += dialog.GetCharHeight();
dialog += dialog.Heading(_("Do you want to swap discs or boot the new image (via system reset)?")); dialog += dialog.Heading(_("Do you want to swap discs or boot the new image (via system reset)?"));
result = pxIssueConfirmation( dialog, MsgButtons().Reset().Cancel().Custom(_("Swap Disc")), L"DragDrop.BootSwapIso" ); result = pxIssueConfirmation( dialog, MsgButtons().Reset().Cancel().Custom(_("Swap Disc"), "swap"), L"DragDrop.BootSwapIso" );
if( result == wxID_CANCEL ) if( result == wxID_CANCEL )
{ {
core_control.AllowResume(); core_control.AllowResume();
@ -189,7 +194,7 @@ wxWindowID SwapOrReset_CdvdSrc( wxWindow* owner, CDVD_SourceType newsrc )
_("Do you want to swap discs or boot the new image (system reset)?") _("Do you want to swap discs or boot the new image (system reset)?")
); );
result = pxIssueConfirmation( dialog, MsgButtons().Reset().Cancel().Custom(_("Swap Disc")), L"DragDrop.BootSwapIso" ); result = pxIssueConfirmation( dialog, MsgButtons().Reset().Cancel().Custom(_("Swap Disc"), "swap"), L"DragDrop.BootSwapIso" );
if( result == wxID_CANCEL ) if( result == wxID_CANCEL )
{ {

View File

@ -74,7 +74,7 @@ protected:
wxString GetDisabledMessage( uint slot ) const wxString GetDisabledMessage( uint slot ) const
{ {
return pxE( ".Popup:Mcd:HasBeenDisabled", wxsFormat( return pxE( "!Notice:Mcd:HasBeenDisabled", wxsFormat(
L"The memory card in slot %d has been automatically disabled. You can correct the problem\n" L"The memory card in slot %d has been automatically disabled. You can correct the problem\n"
L"and re-enable the memory card at any time using Config:Memory cards from the main menu.", L"and re-enable the memory card at any time using Config:Memory cards from the main menu.",
slot slot

View File

@ -123,7 +123,7 @@ void Panels::BiosSelectorPanel::Apply()
{ {
throw Exception::CannotApplySettings(this) throw Exception::CannotApplySettings(this)
.SetDiagMsg(L"User did not specify a valid BIOS selection.") .SetDiagMsg(L"User did not specify a valid BIOS selection.")
.SetUserMsg( pxE( ".Error:BIOS:InvalidSelection", .SetUserMsg( pxE( "!Notice:BIOS:InvalidSelection",
L"Please select a valid BIOS. If you are unable to make a valid selection " L"Please select a valid BIOS. If you are unable to make a valid selection "
L"then press cancel to close the Configuration panel." L"then press cancel to close the Configuration panel."
) ); ) );

View File

@ -109,6 +109,9 @@ namespace Panels
void Apply(); void Apply();
void AppStatusEvent_OnSettingsApplied(); void AppStatusEvent_OnSettingsApplied();
protected:
void OnApplyLanguage_Clicked( wxCommandEvent& evt );
}; };
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------

View File

@ -60,12 +60,12 @@ void Panels::DirPickerPanel::Explore_Click( wxCommandEvent &evt )
createPathDlg += createPathDlg.Text( path ) | StdCenter(); createPathDlg += createPathDlg.Text( path ) | StdCenter();
createPathDlg += createPathDlg.Heading( pxE( ".Error:DirPicker:CreatePath", createPathDlg += createPathDlg.Heading( pxE( "!Notice:DirPicker:CreatePath",
L"The specified path/directory does not exist. Would you like to create it?" ) L"The specified path/directory does not exist. Would you like to create it?" )
); );
wxWindowID result = pxIssueConfirmation( createPathDlg, wxWindowID result = pxIssueConfirmation( createPathDlg,
MsgButtons().Custom(_("Create")).Cancel(), MsgButtons().Custom(_("Create"), "create").Cancel(),
L"DirPicker:CreateOnExplore" L"DirPicker:CreateOnExplore"
); );
@ -115,7 +115,7 @@ void Panels::DirPickerPanel::Init( FoldersEnum_t folderid, const wxString& dialo
{ {
m_checkCtrl = new pxCheckBox( this, _("Use default setting") ); m_checkCtrl = new pxCheckBox( this, _("Use default setting") );
pxSetToolTip( m_checkCtrl, pxE( ".Tooltip:DirPicker:UseDefault", pxSetToolTip( m_checkCtrl, pxEt( "!ContextTip:DirPicker:UseDefault",
L"When checked this folder will automatically reflect the default associated with PCSX2's current usermode setting. " ) L"When checked this folder will automatically reflect the default associated with PCSX2's current usermode setting. " )
); );
@ -225,7 +225,7 @@ void Panels::DirPickerPanel::Apply()
dialog += 12; dialog += 12;
dialog += dialog.Heading( path ); dialog += dialog.Heading( path );
if( wxID_CANCEL == pxIssueConfirmation( dialog, MsgButtons().Custom(_("Create")).Cancel(), L"CreateNewFolder" ) ) if( wxID_CANCEL == pxIssueConfirmation( dialog, MsgButtons().Custom(_("Create"), "create").Cancel(), L"CreateNewFolder" ) )
throw Exception::CannotApplySettings( this ); throw Exception::CannotApplySettings( this );
} }

View File

@ -48,28 +48,28 @@ Panels::GSWindowSettingsPanel::GSWindowSettingsPanel( wxWindow* parent )
m_check_VsyncEnable = new pxCheckBox( this, _("Wait for vsync on refresh") ); m_check_VsyncEnable = new pxCheckBox( this, _("Wait for vsync on refresh") );
m_check_ExclusiveFS = new pxCheckBox( this, _("Use exclusive fullscreen mode (if available)") ); m_check_ExclusiveFS = new pxCheckBox( this, _("Use exclusive fullscreen mode (if available)") );
m_check_VsyncEnable->SetToolTip( pxE( ".Tooltip:Window:Vsync", m_check_VsyncEnable->SetToolTip( pxEt( "!ContextTip:Window:Vsync",
L"Vsync eliminates screen tearing but typically has a big performance hit. " L"Vsync eliminates screen tearing but typically has a big performance hit. "
L"It usually only applies to fullscreen mode, and may not work with all GS plugins." L"It usually only applies to fullscreen mode, and may not work with all GS plugins."
) ); ) );
m_check_HideMouse->SetToolTip( pxE( ".Tooltip:Window:HideMouse", m_check_HideMouse->SetToolTip( pxEt( "!ContextTip:Window:HideMouse",
L"Check this to force the mouse cursor invisible inside the GS window; useful if using " L"Check this to force the mouse cursor invisible inside the GS window; useful if using "
L"the mouse as a primary control device for gaming. By default the mouse auto-hides after " L"the mouse as a primary control device for gaming. By default the mouse auto-hides after "
L"2 seconds of inactivity." L"2 seconds of inactivity."
) ); ) );
m_check_Fullscreen->SetToolTip( pxE( ".Tooltip:Window:Fullscreen", m_check_Fullscreen->SetToolTip( pxEt( "!ContextTip:Window:Fullscreen",
L"Enables automatic mode switch to fullscreen when starting or resuming emulation. " L"Enables automatic mode switch to fullscreen when starting or resuming emulation. "
L"You can still toggle fullscreen display at any time using alt-enter." L"You can still toggle fullscreen display at any time using alt-enter."
) ); ) );
m_check_ExclusiveFS->SetToolTip( pxE( ".Tooltip:Window:FullscreenExclusive", m_check_ExclusiveFS->SetToolTip( pxEt( "!ContextTip:Window:FullscreenExclusive",
L"Fullscreen Exclusive Mode may look better on older CRTs and might be a little faster on older video cards, " L"Fullscreen Exclusive Mode may look better on older CRTs and might be a little faster on older video cards, "
L"but typically can lead to memory leaks or random crashes when entering/leaving fullscreen mode." L"but typically can lead to memory leaks or random crashes when entering/leaving fullscreen mode."
) ); ) );
m_check_CloseGS->SetToolTip( pxE( ".Tooltip:Window:HideGS", m_check_CloseGS->SetToolTip( pxEt( "!ContextTip:Window:HideGS",
L"Completely closes the often large and bulky GS window when pressing " L"Completely closes the often large and bulky GS window when pressing "
L"ESC or suspending the emulator." L"ESC or suspending the emulator."
) ); ) );

View File

@ -18,11 +18,301 @@
#include "AppGameDatabase.h" #include "AppGameDatabase.h"
#include "ConfigurationPanels.h" #include "ConfigurationPanels.h"
#include <wx/listctrl.h>
extern wxString DiscSerial; extern wxString DiscSerial;
using namespace pxSizerFlags; using namespace pxSizerFlags;
#define blankLine() { \
sizer1+=5; sizer1+=5; sizer1+=Text(L""); sizer1+=5; sizer1+=5; \ enum GameDataColumnId
{
GdbCol_Serial = 0,
GdbCol_Title,
GdbCol_Region,
GdbCol_Compat,
GdbCol_Patches,
GdbCol_Count
};
struct ListViewColumnInfo
{
const wxChar* name;
int width;
wxListColumnFormat align;
};
// --------------------------------------------------------------------------------------
// GameDatabaseListView
// --------------------------------------------------------------------------------------
class GameDatabaseListView : public wxListView
{
typedef wxListView _parent;
protected:
wxArrayString m_GamesInView;
public:
virtual ~GameDatabaseListView() throw() { }
GameDatabaseListView( wxWindow* parent );
void CreateColumns();
GameDatabaseListView& AddGame( const wxString& serial );
GameDatabaseListView& RemoveGame( const wxString& serial );
GameDatabaseListView& ClearAllGames();
GameDatabaseListView& SortBy( GameDataColumnId column );
protected:
// Overrides for wxLC_VIRTUAL
virtual wxString OnGetItemText(long item, long column) const;
virtual int OnGetItemImage(long item) const;
virtual int OnGetItemColumnImage(long item, long column) const;
virtual wxListItemAttr* OnGetItemAttr(long item) const;
const ListViewColumnInfo& GetDefaultColumnInfo( uint idx ) const;
};
// --------------------------------------------------------------------------------------
// GameDatabaseListView (implementations)
// --------------------------------------------------------------------------------------
GameDatabaseListView::GameDatabaseListView( wxWindow* parent )
: _parent( parent )
{
CreateColumns();
}
const ListViewColumnInfo& GameDatabaseListView::GetDefaultColumnInfo( uint idx ) const
{
static const ListViewColumnInfo columns[] =
{
{ L"Serial", 96, wxLIST_FORMAT_LEFT },
{ L"Title", 132, wxLIST_FORMAT_LEFT },
{ L"Region", 72, wxLIST_FORMAT_CENTER },
{ L"Compat", 48, wxLIST_FORMAT_CENTER },
{ L"Patches", 48, wxLIST_FORMAT_CENTER },
};
pxAssumeDev( idx < ArraySize(columns), "ListView column index is out of bounds." );
return columns[idx];
}
void GameDatabaseListView::CreateColumns()
{
for( int i=0; i<GdbCol_Count; ++i )
{
const ListViewColumnInfo& info = GetDefaultColumnInfo(i);
InsertColumn( i, pxGetTranslation(info.name), info.align, info.width );
}
}
GameDatabaseListView& GameDatabaseListView::AddGame( const wxString& serial )
{
if (m_GamesInView.Index( serial, false ) != wxNOT_FOUND) return *this;
m_GamesInView.Add( serial );
return *this;
}
GameDatabaseListView& GameDatabaseListView::RemoveGame( const wxString& serial )
{
m_GamesInView.Remove( serial );
return *this;
}
GameDatabaseListView& GameDatabaseListView::ClearAllGames()
{
m_GamesInView.Clear();
return *this;
}
class BaseGameListSort
{
protected:
IGameDatabase* m_GameDB;
bool m_descending;
public:
BaseGameListSort( bool descend )
{
m_GameDB = AppHost_GetGameDatabase();
m_descending = descend;
}
virtual ~BaseGameListSort() throw() {}
// Note: Return TRUE if the first value is less than the second value.
bool operator()(const wxString& i1, const wxString& i2)
{
if (!m_GameDB || (i1 == i2)) return false;
// note: Anything not in the database gets sorted to the bottom of the list ...
Game_Data first, second;
if (!m_GameDB->findGame(first, i1)) return false;
if (!m_GameDB->findGame(second, i2)) return true;
if (int retval = _doCompare(first, second))
return m_descending ? (retval>0) : (retval<0);
return 0;
}
virtual int _doCompare( const Game_Data& first, const Game_Data& second )=0;
};
class GLSort_bySerial : public BaseGameListSort
{
public:
GLSort_bySerial( bool descend ) : BaseGameListSort( descend ) { }
protected:
int _doCompare( const Game_Data& g1, const Game_Data& g2 )
{
return g1.getString("Serial").CmpNoCase( g2.getString("Serial") );
}
};
class GLSort_byTitle : public BaseGameListSort
{
public:
GLSort_byTitle( bool descend ) : BaseGameListSort( descend ) { }
protected:
int _doCompare( const Game_Data& g1, const Game_Data& g2 )
{
return g1.getString("Name").Cmp( g2.getString("Name") );
}
};
class GLSort_byRegion : public BaseGameListSort
{
public:
GLSort_byRegion( bool descend ) : BaseGameListSort( descend ) { }
protected:
int _doCompare( const Game_Data& g1, const Game_Data& g2 )
{
return g1.getString("Region").CmpNoCase( g2.getString("Region") );
}
};
class GLSort_byCompat : public BaseGameListSort
{
public:
GLSort_byCompat( bool descend ) : BaseGameListSort( descend ) { }
protected:
int _doCompare( const Game_Data& g1, const Game_Data& g2 )
{
return g1.getInt("Compat") - g2.getInt("Compat");
}
};
class GLSort_byPatches : public BaseGameListSort
{
public:
GLSort_byPatches( bool descend ) : BaseGameListSort( descend ) { }
protected:
int _doCompare( const Game_Data& g1, const Game_Data& g2 )
{
bool hasPatches1 = !g1.getString("[patches]").IsEmpty();
bool hasPatches2 = !g2.getString("[patches]").IsEmpty();
if (hasPatches1 == hasPatches2) return 0;
return hasPatches1 ? -1 : 1;
}
};
GameDatabaseListView& GameDatabaseListView::SortBy( GameDataColumnId column )
{
wxArrayString::CompareFunction cmpfunc = NULL;
const bool isDescending = false;
wxArrayString::iterator begin = m_GamesInView.begin();
wxArrayString::iterator end = m_GamesInView.end();
// Note: std::sort does not pass predicate instances by reference, which means we can't use
// object polymorphism to simplify the code below. --air
switch( column )
{
case GdbCol_Serial: std::sort(begin, end, GLSort_bySerial(isDescending)); break;
case GdbCol_Title: std::sort(begin, end, GLSort_byTitle(isDescending)); break;
case GdbCol_Region: std::sort(begin, end, GLSort_byRegion(isDescending)); break;
case GdbCol_Compat: std::sort(begin, end, GLSort_byCompat(isDescending)); break;
case GdbCol_Patches: std::sort(begin, end, GLSort_byPatches(isDescending)); break;
// do not use jNO_DEFAULT here -- keeps release builds from crashing (it'll just
// ignore the sort request!)
}
//m_GamesInView.( );
return *this;
}
// return the text for the given column of the given item
wxString GameDatabaseListView::OnGetItemText(long item, long column) const
{
IGameDatabase* GameDB = AppHost_GetGameDatabase();
if (!GameDB || (item < 0) || ((uint)item >= m_GamesInView.GetCount()))
return _parent::OnGetItemText(item, column);
Game_Data game;
if (!GameDB->findGame(game, m_GamesInView[item]))
{
pxFail( "Unknown row index in GameDatabaseListView -- returning default value." );
return _parent::OnGetItemText(item, column);
}
switch( column )
{
case GdbCol_Serial: return m_GamesInView[item];
case GdbCol_Title: return game.getString("Name");
case GdbCol_Region: return game.getString("Region");
case GdbCol_Compat: return game.getString("Compat");
case GdbCol_Patches: return game.getString("[patches]").IsEmpty() ? L"No" : L"Yes";
}
pxFail( "Unknown column index in GameDatabaseListView -- returning an empty string." );
return wxEmptyString;
}
// return the icon for the given item. In report view, OnGetItemImage will
// only be called for the first column. See OnGetItemColumnImage for
// details.
int GameDatabaseListView::OnGetItemImage(long item) const
{
return _parent::OnGetItemImage( item );
}
// return the icon for the given item and column.
int GameDatabaseListView::OnGetItemColumnImage(long item, long column) const
{
return _parent::OnGetItemColumnImage( item, column );
}
static wxListItemAttr m_ItemAttr;
// return the attribute for the item (may return NULL if none)
wxListItemAttr* GameDatabaseListView::OnGetItemAttr(long item) const
{
m_ItemAttr = wxListItemAttr(); // Wipe it clean!
// For eventual drag&drop ?
//if( m_TargetedItem == item )
// m_ItemAttr.SetBackgroundColour( wxColour(L"Wheat") );
return &m_ItemAttr;
}
#define blankLine() { \
sizer1+=5; sizer1+=5; sizer1+=Text(wxEmptyString); sizer1+=5; sizer1+=5; \
} }
#define placeTextBox(wxBox, txt) { \ #define placeTextBox(wxBox, txt) { \
@ -43,9 +333,6 @@ wxTextCtrl* CreateMultiLineTextCtrl( wxWindow* parent, int digits, long flags =
Panels::GameDatabasePanel::GameDatabasePanel( wxWindow* parent ) Panels::GameDatabasePanel::GameDatabasePanel( wxWindow* parent )
: BaseApplicableConfigPanel( parent ) : BaseApplicableConfigPanel( parent )
{ {
IGameDatabase* GameDB = AppHost_GetGameDatabase();
pxAssume( GameDB != NULL );
searchBtn = new wxButton (this, wxID_ANY, _("Search")); searchBtn = new wxButton (this, wxID_ANY, _("Search"));
serialBox = CreateNumericalTextCtrl(this, 40, wxTE_LEFT); serialBox = CreateNumericalTextCtrl(this, 40, wxTE_LEFT);
@ -59,7 +346,8 @@ Panels::GameDatabasePanel::GameDatabasePanel( wxWindow* parent )
gameFixes[i] = new pxCheckBox(this, EnumToString(i), wxCHK_3STATE | wxCHK_ALLOW_3RD_STATE_FOR_USER ); gameFixes[i] = new pxCheckBox(this, EnumToString(i), wxCHK_3STATE | wxCHK_ALLOW_3RD_STATE_FOR_USER );
*this += Heading(_("Game Database Editor")).Bold() | StdExpand(); *this += Heading(_("Game Database Editor")).Bold() | StdExpand();
//*this += Heading(_("This panel lets you add and edit game titles, game fixes, and game patches.")) | StdExpand();
*this += new GameDatabaseListView( this ) | StdExpand();
wxFlexGridSizer& sizer1(*new wxFlexGridSizer(5, StdPadding)); wxFlexGridSizer& sizer1(*new wxFlexGridSizer(5, StdPadding));
sizer1.AddGrowableCol(0); sizer1.AddGrowableCol(0);

View File

@ -64,7 +64,7 @@ Panels::GameFixesPanel::GameFixesPanel( wxWindow* parent )
}, },
{ {
_("EE timing hack - Multi purpose hack. Try if all else fails."), _("EE timing hack - Multi purpose hack. Try if all else fails."),
pxE( ".Tooltip:Gamefixes:EE Timing Hack", pxEt( "!ContextTip:Gamefixes:EE Timing Hack",
L"Known to affect following games:\n" L"Known to affect following games:\n"
L" * Digital Devil Saga (Fixes FMV and crashes)\n" L" * Digital Devil Saga (Fixes FMV and crashes)\n"
L" * SSX (Fixes bad graphics and crashes)\n" L" * SSX (Fixes bad graphics and crashes)\n"
@ -77,7 +77,7 @@ Panels::GameFixesPanel::GameFixesPanel( wxWindow* parent )
}, },
{ {
_("OPH Flag hack - Try if your game freezes showing the same frame."), _("OPH Flag hack - Try if your game freezes showing the same frame."),
pxE( ".Tooltip:Gamefixes:OPH Flag hack", pxEt( "!ContextTip:Gamefixes:OPH Flag hack",
L"Known to affect following games:\n" L"Known to affect following games:\n"
L" * Bleach Blade Battler\n" L" * Bleach Blade Battler\n"
L" * Growlanser II and III\n" L" * Growlanser II and III\n"
@ -93,7 +93,7 @@ Panels::GameFixesPanel::GameFixesPanel( wxWindow* parent )
} }
m_check_Enable = new pxCheckBox( this, _("Enable game fixes"), m_check_Enable = new pxCheckBox( this, _("Enable game fixes"),
pxE( ".Panel:Gamefixes:Compat Warning", pxE( "!Panel:Gamefixes:Compat Warning",
L"Gamefixes can fix wrong emulation in some games. However " L"Gamefixes can fix wrong emulation in some games. However "
L"it can cause compatibility or performance issues in other games. You " L"it can cause compatibility or performance issues in other games. You "
L"will need to turn off fixes manually when changing games." L"will need to turn off fixes manually when changing games."

View File

@ -362,7 +362,7 @@ public:
if( dest.IsPresent && dest.IsFormatted ) if( dest.IsPresent && dest.IsFormatted )
{ {
pxsFmt( pxE( ".Popup:Mcd:Overwrite", pxsFmt( pxE( "!Notice:Mcd:Overwrite",
L"This will copy the contents of the memory card in slot %u over the memory card in slot %u. " L"This will copy the contents of the memory card in slot %u over the memory card in slot %u. "
L"All data on the target slot will be lost. Are you sure?" ), L"All data on the target slot will be lost. Are you sure?" ),
src.Slot, dest.Slot src.Slot, dest.Slot
@ -376,7 +376,7 @@ public:
if( !wxCopyFile( srcfile.GetFullPath(), destfile.GetFullPath(), true ) ) if( !wxCopyFile( srcfile.GetFullPath(), destfile.GetFullPath(), true ) )
{ {
wxString heading; wxString heading;
heading.Printf( pxE( ".Error:Mcd:Copy Failed", heading.Printf( pxE( "!Notice:Mcd:Copy Failed",
L"Error! Could not copy the memory card into slot %u. The destination file is in use." ), L"Error! Could not copy the memory card into slot %u. The destination file is in use." ),
dest.Slot dest.Slot
); );
@ -582,7 +582,7 @@ void Panels::MemoryCardListPanel_Simple::OnCreateCard(wxCommandEvent& evt)
{ {
wxString content; wxString content;
content.Printf( content.Printf(
pxE( ".Popup:Mcd:Delete", pxE( "!Notice:Mcd:Delete",
L"You are about to delete the formatted memory card in slot %u. " L"You are about to delete the formatted memory card in slot %u. "
L"All data on this card will be lost! Are you absolutely and quite positively sure?" L"All data on this card will be lost! Are you absolutely and quite positively sure?"
), slot ), slot

View File

@ -20,6 +20,13 @@
#include <wx/dnd.h> #include <wx/dnd.h>
#include <wx/listctrl.h> #include <wx/listctrl.h>
struct ListViewColumnInfo
{
const wxChar* name;
int width;
wxListColumnFormat align;
};
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
// McdListItem / IMcdList // McdListItem / IMcdList
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
@ -67,13 +74,6 @@ public:
virtual wxDirName GetMcdPath() const=0; virtual wxDirName GetMcdPath() const=0;
}; };
struct ListViewColumnInfo
{
const wxChar* name;
int width;
wxListColumnFormat align;
};
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
// BaseMcdListView // BaseMcdListView
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
@ -231,6 +231,7 @@ namespace Panels
protected: protected:
pxCheckBox* m_check_Multitap[2]; pxCheckBox* m_check_Multitap[2];
pxCheckBox* m_check_Ejection; pxCheckBox* m_check_Ejection;
pxCheckBox* m_check_SavestateBackup;
public: public:
McdConfigPanel_Toggles( wxWindow* parent ); McdConfigPanel_Toggles( wxWindow* parent );

View File

@ -32,13 +32,13 @@ using namespace pxSizerFlags;
Panels::DocsFolderPickerPanel::DocsFolderPickerPanel( wxWindow* parent, bool isFirstTime ) Panels::DocsFolderPickerPanel::DocsFolderPickerPanel( wxWindow* parent, bool isFirstTime )
: BaseApplicableConfigPanel( parent, wxVERTICAL, _("Usermode Selection") ) : BaseApplicableConfigPanel( parent, wxVERTICAL, _("Usermode Selection") )
{ {
const wxString usermodeExplained( pxE( ".Panel:Usermode:Explained", const wxString usermodeExplained( pxE( "!Panel:Usermode:Explained",
L"Please select your preferred default location for PCSX2 user-level documents below " L"Please select your preferred default location for PCSX2 user-level documents below "
L"(includes memory cards, screenshots, settings, and savestates). " L"(includes memory cards, screenshots, settings, and savestates). "
L"These folder locations can be overridden at any time using the Core Settings panel." L"These folder locations can be overridden at any time using the Core Settings panel."
) ); ) );
const wxString usermodeWarning( pxE( ".Panel:Usermode:Warning", const wxString usermodeWarning( pxE( "!Panel:Usermode:Warning",
L"You can change the preferred default location for PCSX2 user-level documents here " L"You can change the preferred default location for PCSX2 user-level documents here "
L"(includes memory cards, screenshots, settings, and savestates). " L"(includes memory cards, screenshots, settings, and savestates). "
L"This option only affects Standard Paths which are set to use the installation default value." L"This option only affects Standard Paths which are set to use the installation default value."
@ -113,26 +113,32 @@ Panels::LanguageSelectionPanel::LanguageSelectionPanel( wxWindow* parent )
i18n_EnumeratePackages( m_langs ); i18n_EnumeratePackages( m_langs );
int size = m_langs.size(); int size = m_langs.size();
int cursel = 0; ScopedArray<wxString> compiled( size );
ScopedArray<wxString> compiled( size ); //, L"Compiled Language Names" );
wxString configLangName( wxLocale::GetLanguageName( wxLANGUAGE_DEFAULT ) );
for( int i=0; i<size; ++i ) for( int i=0; i<size; ++i )
{ compiled[i].Printf( L"%s", m_langs[i].englishName.c_str() );
compiled[i].Printf( L"%s", m_langs[i].englishName.c_str() ); //, xltNames[i].c_str() );
if( m_langs[i].englishName == configLangName )
cursel = i;
}
m_picker = new wxComboBox( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, m_picker = new wxComboBox( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize,
size, compiled.GetPtr(), wxCB_READONLY | wxCB_SORT ); size, compiled.GetPtr(), wxCB_READONLY | wxCB_SORT );
*this += Label(_("Select a language: (unimplemented)")) | pxMiddle; wxButton* applyButton = new wxButton( this, pxID_RestartWizard, _("Apply") );
applyButton->SetToolTip(_("Make this language my default right now!"));
*this += Label(_("Select a language:")) | pxMiddle;
*this += 5; *this += 5;
*this += m_picker | pxSizerFlags::StdSpace(); *this += m_picker | pxSizerFlags::StdSpace();
*this += 5;
*this += applyButton | pxSizerFlags::StdSpace();
m_picker->SetSelection( cursel ); Connect( pxID_RestartWizard, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( LanguageSelectionPanel::OnApplyLanguage_Clicked ) );
//AppStatusEvent_OnSettingsApplied();
m_picker->SetSelection( 0 ); // always default to System Default
}
void Panels::LanguageSelectionPanel::OnApplyLanguage_Clicked( wxCommandEvent& evt )
{
evt.Skip();
Apply();
} }
void Panels::LanguageSelectionPanel::Apply() void Panels::LanguageSelectionPanel::Apply()
@ -144,19 +150,39 @@ void Panels::LanguageSelectionPanel::Apply()
wxString sel( m_picker->GetString( m_picker->GetSelection() ) ); wxString sel( m_picker->GetString( m_picker->GetSelection() ) );
g_Conf->LanguageId = wxLANGUAGE_DEFAULT; // use this if no matches found g_Conf->LanguageCode = L"default"; // use this if no matches found
g_Conf->LanguageId = wxLANGUAGE_DEFAULT;
int size = m_langs.size(); int size = m_langs.size();
for( int i=0; i<size; ++i ) for( int i=0; i<size; ++i )
{ {
if( m_langs[i].englishName == sel ) if( m_langs[i].englishName == sel )
{ {
g_Conf->LanguageId = m_langs[i].wxLangId; if( i18n_SetLanguage( m_langs[i].wxLangId, m_langs[i].canonicalName ) )
{
g_Conf->LanguageCode = m_langs[i].canonicalName;
g_Conf->LanguageId = m_langs[i].wxLangId;
}
break; break;
} }
} }
} }
void Panels::LanguageSelectionPanel::AppStatusEvent_OnSettingsApplied() void Panels::LanguageSelectionPanel::AppStatusEvent_OnSettingsApplied()
{ {
if( m_picker ) m_picker->SetSelection( g_Conf->LanguageId ); if (m_picker)
{
m_picker->SetSelection( 0 ); // always default to System Default
if (g_Conf->LanguageCode.IsEmpty())
g_Conf->LanguageCode = L"default";
for (uint i=0; i<m_langs.size(); ++i)
{
if (0==m_langs[i].canonicalName.CmpNoCase(g_Conf->LanguageCode))
{
m_picker->SetSelection( i );
}
}
}
} }

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