Much work on menus, gui features. Partially-working recent-isos menu list. Bugfix for some of the new console stuff that could have caused some funny bunny business, or crashes, in a few games. Why dat wascaly wabbit! >_<

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2100 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2009-10-31 10:03:07 +00:00
parent c274d4e43c
commit 4cb8e21f94
27 changed files with 1215 additions and 771 deletions

View File

@ -268,7 +268,12 @@ typedef struct _PS2E_MenuItemInfo
// Specifies the handle of a sub menu to bind to this menu. If NULL, the menu is
// created normally. If non-NULL, the menu item will use sub-menu mode and will
// ignore the Style field.
PS2E_MenuHandle* SubMenu;
PS2E_MenuHandle SubMenu;
// Menu that this item is attached to. When this struct is passed into AddMenuItem,
// the menu item will be automatically appended to the menu specified in this field
// if the field is non-NULL (if the field is NULL then no action is taken).
PS2E_MenuHandle OwnerMenu;
// When FALSE the menu item will appear grayed out to the user, and unselectable.
BOOL Enabled;
@ -340,7 +345,7 @@ typedef struct _PS2E_MenuItemAPI
// fashion. When a submenu is assigned, the Style attribute of the menu will be
// ignored. Passing NULL into this function will clear the submenu and return the
// menu item to whatever it's current Style attribute is set to.
void (PS2E_CALLBACK* MenuItem_SetSubMenu)( PS2E_MenuItemHandle mitem, PS2E_MenuHandle* submenu );
void (PS2E_CALLBACK* MenuItem_SetSubMenu)( PS2E_MenuItemHandle mitem, PS2E_MenuHandle submenu );
// Assigns the callback function for this menu (important!). If passed NULL, the menu
// item will be automatically disabled (grayed out) by the emulator.
@ -352,6 +357,8 @@ typedef struct _PS2E_MenuItemAPI
// Returns the current enable status of the specified menu item.
BOOL (PS2E_CALLBACK* MenuItem_IsEnabled)( PS2E_MenuItemHandle mitem );
void* reserved[4];
} PS2E_MenuItemAPI;
// --------------------------------------------------------------------------------------
@ -437,6 +444,18 @@ typedef struct _PS2E_EmulatorInfo
// resources.
int LogicalCores;
// Specifies the size of the wchar_t of the emulator, in bytes. Plugin authors should be
// sure to check this against your own sizeof(wchar_t) before using any API that has
// a wchar_t parameter (such as the ConsoleWriterWide interface). wchar_t is a loosely
// defined type that can range from 8 bits to 32 bits (realistically, although there is
// no actual limit on size), and can vary between compilers for the same platform.
int Sizeof_wchar_t;
// Reserved area for future expansion of the structure (avoids having to upgrade the
// plugin api for amending new extensions).
int reserved1[6];
// GetInt
// Self-explanatory.
//
@ -496,19 +515,19 @@ typedef struct _PS2E_EmulatorInfo
//
void (PS2E_CALLBACK* OSD_WriteLn)( int icon, const char* msg );
void (PS2E_CALLBACK* AddMenuItem)( const PS2E_MenuItemInfo* item );
// ----------------------------------------------------------------------------
// Menu / MenuItem Section
// ----------------------------------------------------------------------------
void (PS2E_CALLBACK* AddMenuItem)( const PS2E_MenuItemInfo* item );
// Allocates a new menu handle and returns it. The returned menu can have any valid existing
// menu items bound to it, and can be assigned as a submenu to any created MenuItem. The menu
// can belong to multiple menu items, however menu items can only belong to a single menu.
PS2E_MenuHandle (PS2E_CALLBACK* Menu_Create)( PS2E_THISPTR thisptr );
// Deletes the specified menu and frees its allocated memory resources. NULL pointers are
// safely ignored. Any menu itels also attached to this menu will be deleted. Even if you
// safely ignored. Any menu items also attached to this menu will be deleted. Even if you
// do not explicitly delete your plugin's menu resources, the emulator will do automatic
// cleanup after the plugin's instance is free'd.
void (PS2E_CALLBACK* Menu_Delete)( PS2E_MenuHandle handle );
@ -533,6 +552,8 @@ typedef struct _PS2E_EmulatorInfo
// side before using this interface. See PS2E_ConsoleWriterWideAPI comments for more info.
PS2E_ConsoleWriterWideAPI ConsoleW;
void* reserved2[8];
} PS2E_EmulatorInfo;
@ -797,7 +818,7 @@ typedef struct _PS2E_LibraryAPI
// Reserved area at the end of the structure, for future API expansion. This area
// should always be zeroed out, so that future versions of emulators that may have
// defined functions here will recognize the functions as not supported.
// defined functions here will recognize the functions as not supported by the plugin.
void* reserved[12];
} PS2E_LibraryAPI;

View File

@ -179,8 +179,11 @@ void hwWrite8(u32 mem, u8 value)
if (( value == '\r' ) || ( sio_count == 1023 ) ||
( value == '\n' && sio_count != 0 ))
{
// Use "%s" below even though it feels indirect -- it's necessary to avoid
// errors if/when games use printf formatting control chars.
sio_buffer[sio_count] = 0;
Console.WriteLn( ConColor_EE, ShiftJIS_ConvertString(sio_buffer) );
Console.WriteLn( ConColor_EE, L"%s", ShiftJIS_ConvertString(sio_buffer).c_str() );
sio_count = 0;
}
else if( value != '\n' )

View File

@ -174,9 +174,7 @@ void bios_write() // 0x35/0x03
if (a0 == 1) // stdout
{
const char *ptr = Ra1;
//Console.Write( ConColor_IOP, "%.*s", a2, ptr);
Console.Write( ConColor_IOP, ShiftJIS_ConvertString(ptr, a2) );
Console.Write( ConColor_IOP, L"%s", ShiftJIS_ConvertString(ptr, a2).c_str() );
}
else
{
@ -284,10 +282,13 @@ _start:
}
*ptmp = 0;
// Note: Use Read to obtain a write pointer here, since we're just writing back the
// Use Read to obtain a write pointer here, since we're just writing back the
// temp buffer we saved earlier.
memcpy( (void*)iopVirtMemR<void>(sp), save, 4*4);
Console.Write( ConColor_IOP, ShiftJIS_ConvertString(tmp), 1023 );
// Use "%s" even though it seems indirect: this avoids chaos if/when the IOP decides
// to feed us strings that contain percentages or other printf formatting control chars.
Console.Write( ConColor_IOP, L"%s", ShiftJIS_ConvertString(tmp).c_str(), 1023 );
pc0 = ra;
}
@ -300,7 +301,7 @@ void bios_putchar () // 3d
void bios_puts () // 3e/3f
{
Console.Write( ConColor_IOP, Ra0 );
Console.Write( ConColor_IOP, L"%s", ShiftJIS_ConvertString(Ra0).c_str() );
pc0 = ra;
}

View File

@ -673,7 +673,7 @@ void psxHwWrite8(u32 add, u8 value) {
( value == '\n' && g_pbufi != 0 ) )
{
g_pbuf[g_pbufi] = 0;
Console.WriteLn( ConColor_IOP, g_pbuf );
Console.WriteLn( ConColor_IOP, "%s", g_pbuf );
g_pbufi = 0;
}
else if( value != '\n' )

View File

@ -308,6 +308,7 @@
<Unit filename="../gui/Panels/SpeedhacksPanel.cpp" />
<Unit filename="../gui/Panels/VideoPanel.cpp" />
<Unit filename="../gui/Plugins.cpp" />
<Unit filename="../gui/RecentIsoList.cpp" />
<Unit filename="../gui/Resources/AppIcon16.h" />
<Unit filename="../gui/Resources/AppIcon16.png">
<Option compile="1" />

View File

@ -690,6 +690,21 @@ PluginManager::PluginManager( const wxString (&folders)[PluginId_Count] )
//m_libs[i].GetSymbol( L"PS2E_InitAPI" );
// Fetch plugin name and version information
_PS2EgetLibName GetLibName = (_PS2EgetLibName)m_info[pid].Lib.GetSymbol( L"PS2EgetLibName" );
_PS2EgetLibVersion2 GetLibVersion2 = (_PS2EgetLibVersion2)m_info[pid].Lib.GetSymbol( L"PS2EgetLibVersion2" );
if( GetLibName == NULL || GetLibVersion2 == NULL )
throw Exception::PluginLoadError( pid, m_info[pid].Filename,
wxsFormat( L"\nMethod binding failure on GetLibName or GetLibVersion2.\n" ),
_( "Configured plugin is not a PCSX2 plugin, or is for an older unsupported version of PCSX2." )
);
m_info[pid].Name = fromUTF8( GetLibName() );
int version = GetLibVersion2( tbl_PluginInfo[pid].typemask );
m_info[pid].Version.Printf( L"%d.%d.%d", (version>>8)&0xff, version&0xff, (version>>24)&0xff );
// Bind Required Functions
// (generate critical error if binding fails)
@ -720,6 +735,9 @@ PluginManager::PluginManager( const wxString (&folders)[PluginId_Count] )
x86caps.PhysicalCores,
x86caps.LogicalCores,
sizeof(wchar_t),
0,0,0,0,0,0,
pcsx2_GetInt,
pcsx2_GetBoolean,
@ -1116,15 +1134,6 @@ void PluginManager::Configure( PluginsEnum_t pid )
m_info[pid].CommonBindings.Configure();
}
// Creates an instance of a plugin manager, using the specified plugin filenames for sources.
// Impl Note: Have to use this stupid effing 'friend' declaration because static members of
// classes can't access their own protected members. W-T-F?
//
PluginManager* PluginManager_Create( const wxString (&folders)[PluginId_Count] )
{
return new PluginManager( folders );
}
PluginManager* PluginManager_Create( const wxChar* (&folders)[PluginId_Count] )
{
wxString passins[PluginId_Count];
@ -1133,7 +1142,7 @@ PluginManager* PluginManager_Create( const wxChar* (&folders)[PluginId_Count] )
passins[pi->id] = folders[pi->id];
} while( ++pi, pi->shortname != NULL );
return PluginManager_Create( passins );
return new PluginManager( passins );
}
static PluginManagerBase s_pluginman_placebo;

View File

@ -272,7 +272,10 @@ protected:
{
bool IsInitialized;
bool IsOpened;
wxString Filename;
wxString Name;
wxString Version;
LegacyPluginAPI_Common CommonBindings;
wxDynamicLibrary Lib;
@ -280,7 +283,6 @@ protected:
PluginStatus_t() :
IsInitialized( false )
, IsOpened( false )
, Filename()
, CommonBindings()
, Lib()
{
@ -295,6 +297,7 @@ public: // hack until we unsuck plugins...
PluginStatus_t m_info[PluginId_Count];
public:
PluginManager( const wxString (&folders)[PluginId_Count] );
virtual ~PluginManager() throw();
void Init();
@ -310,13 +313,12 @@ public:
bool KeyEvent( const keyEvent& evt );
void Configure( PluginsEnum_t pid );
friend PluginManager* PluginManager_Create( const wxString (&folders)[PluginId_Count] );
const wxString& GetName( PluginsEnum_t pid ) const { return m_info[pid].Name; }
const wxString& GetVersion( PluginsEnum_t pid ) const { return m_info[pid].Version; }
friend PluginManager* PluginManager_Create( const wxChar* (&folders)[PluginId_Count] );
protected:
// Internal constructor, should be called by Create only.
PluginManager( const wxString (&folders)[PluginId_Count] );
void BindCommon( PluginsEnum_t pid );
void BindRequired( PluginsEnum_t pid );
void BindOptional( PluginsEnum_t pid );
@ -327,7 +329,6 @@ protected:
extern const PluginInfo tbl_PluginInfo[];
extern PluginManager* g_plugins;
extern PluginManager* PluginManager_Create( const wxString (&folders)[PluginId_Count] );
extern PluginManager* PluginManager_Create( const wxChar* (&folders)[PluginId_Count] );
extern PluginManagerBase& GetPluginManager();

View File

@ -790,7 +790,7 @@ int __Deci2Call(int call, u32 *addr)
pdeciaddr += (deci2addr[4]+0xc)%16;
memcpy(deci2buffer, pdeciaddr, deci2addr[1]-0xc);
deci2buffer[deci2addr[1]-0xc>=255?255:deci2addr[1]-0xc]='\0';
Console.Write( ConColor_EE, ShiftJIS_ConvertString(deci2buffer) );
Console.Write( ConColor_EE, L"%s", ShiftJIS_ConvertString(deci2buffer).c_str() );
}
deci2addr[3] = 0;
return 1;
@ -809,7 +809,7 @@ int __Deci2Call(int call, u32 *addr)
case 0x10://kputs
if( addr != NULL )
Console.Write( ConColor_EE, ShiftJIS_ConvertString((char*)PSM(*addr)) );
Console.Write( ConColor_EE, L"%s", ShiftJIS_ConvertString((char*)PSM(*addr)).c_str() );
return 1;
}
@ -831,7 +831,7 @@ void SYSCALL()
if (call == 0x7c)
{
if(cpuRegs.GPR.n.a0.UL[0] == 0x10)
Console.Write( ConColor_EE, ShiftJIS_ConvertString((char*)PSM(memRead32(cpuRegs.GPR.n.a1.UL[0]))) );
Console.Write( ConColor_EE, L"%s", ShiftJIS_ConvertString((char*)PSM(memRead32(cpuRegs.GPR.n.a1.UL[0]))).c_str() );
else
__Deci2Call( cpuRegs.GPR.n.a0.UL[0], (u32*)PSM(cpuRegs.GPR.n.a1.UL[0]) );
}

View File

@ -96,6 +96,16 @@ void SysCoreThread::Reset()
m_resetVirtualMachine = true;
}
// This function *will* reset the emulator in order to allow the specified elf file to
// take effect. This is because it really doesn't make sense to change the elf file outside
// the context of a reset/restart.
void SysCoreThread::SetElfOverride( const wxString& elf )
{
pxAssertDev( !m_hasValidState, "Thread synchronization error while assigning ELF override." );
m_elf_override = elf;
}
// Applies a full suite of new settings, which will automatically facilitate the necessary
// resets of the core and components (including plugins, if needed). The scope of resetting
// is determined by comparing the current settings against the new settings.
@ -128,6 +138,24 @@ bool SysCoreThread::HasPendingStateChangeRequest() const
return m_CoreCancelDamnit || mtgsThread.HasPendingException() || _parent::HasPendingStateChangeRequest();
}
struct ScopedBool_ClearOnError
{
bool& m_target;
bool m_success;
ScopedBool_ClearOnError( bool& target ) :
m_target( target ), m_success( false )
{
m_target = true;
}
virtual ~ScopedBool_ClearOnError()
{
m_target = m_success;
}
void Success() { m_success = true; }
};
void SysCoreThread::CpuInitializeMess()
{
@ -139,8 +167,10 @@ void SysCoreThread::CpuInitializeMess()
m_resetRecompilers = false;
m_resetProfilers = false;
wxString elf_file;
if( EmuConfig.SkipBiosSplash )
ScopedBool_ClearOnError sbcoe( m_hasValidState );
wxString elf_file( m_elf_override );
if( elf_file.IsEmpty() && EmuConfig.SkipBiosSplash )
{
// Fetch the ELF filename and CD type from the CDVD provider.
wxString ename;
@ -164,19 +194,19 @@ void SysCoreThread::CpuInitializeMess()
if( !elf_file.IsEmpty() )
{
// Skip Bios Hack -- Runs the PS2 BIOS stub, and then manually loads the ELF
// executable data, and injects the cpuRegs.pc with the address of the
// execution start point.
// Skip Bios Hack *or* Manual ELF override:
// Runs the PS2 BIOS stub, and then manually loads the ELF executable data, and
// injects the cpuRegs.pc with the address of the execution start point.
//
// This hack is necessary for non-CD ELF files, and is optional for game CDs
// (though not recommended for games because of rare ill side effects).
// This hack is necessary for non-CD ELF files, and is optional for game CDs as a
// fast bott up option. (though not recommended for games because of rare ill side
// effects).
m_hasValidState = true;
cpuExecuteBios();
m_hasValidState = false; // because loadElfFile might error...
loadElfFile( elf_file );
}
m_hasValidState = true;
sbcoe.Success();
}
void SysCoreThread::StateCheckInThread()
@ -227,6 +257,8 @@ void SysCoreThread::OnResumeInThread( bool isSuspended )
// Invoked by the pthread_exit or pthread_cancel.
void SysCoreThread::OnCleanupInThread()
{
m_hasValidState = false;
Threading::DisableHiresScheduler();
if( g_plugins != NULL )

View File

@ -188,7 +188,6 @@ void SysThreadBase::Resume()
{
if( IsSelf() ) return;
if( m_ExecMode == ExecMode_Opened ) return;
if( !pxAssert( g_plugins != NULL ) ) return;
ScopedLock locker( m_ExecModeMutex );

View File

@ -186,6 +186,8 @@ protected:
// Used by SETJMP only, but ifdef'ing it out clutters up the code.
bool m_CoreCancelDamnit;
wxString m_elf_override;
public:
static SysCoreThread& Get();
@ -204,9 +206,11 @@ public:
}
bool HasPendingStateChangeRequest() const;
virtual void StateCheckInThread();
virtual const wxString& GetElfOverride() const { return m_elf_override; }
virtual void SetElfOverride( const wxString& elf );
protected:
void CpuInitializeMess();

View File

@ -18,7 +18,6 @@
#include <wx/wx.h>
#include <wx/fileconf.h>
#include <wx/imaglist.h>
#include <wx/docview.h>
#include <wx/apptrait.h>
#include "Utilities/EventSource.h"
@ -56,6 +55,9 @@ END_DECLARE_EVENT_TYPES()
// the universal Accelerator table.
static const int pxID_PadHandler_Keydown = 8030;
// Plugin ID sections are spaced out evenly at intervals to make it easy to use a
// single for-loop to create them.
static const int PluginMenuId_Interval = 0x10;
// ------------------------------------------------------------------------
// All Menu Options for the Main Window! :D
@ -82,6 +84,7 @@ enum MenuIdentifiers
MenuId_Src_Plugin,
MenuId_Src_NoDisc,
MenuId_Boot_Iso, // Opens submenu with Iso browser, and recent isos.
MenuId_IsoSelector, // Contains a submenu of selectable "favorite" isos
MenuId_IsoBrowse, // Open dialog, runs selected iso.
MenuId_Boot_CDVD, // opens a submenu filled by CDVD plugin (usually list of drives)
MenuId_Boot_ELF,
@ -122,20 +125,17 @@ enum MenuIdentifiers
MenuId_Config_Multitap0Toggle,
MenuId_Config_Multitap1Toggle,
// Video Subsection
// Top items are PCSX2-controlled. GS plugin items are inserted beneath.
MenuId_Video_Basics, // includes frame timings and skippings settings
MenuId_Video_Advanced, // inserted at the bottom of the menu
// Plugin Sections
// ---------------
// Each plugin menu begins with its name, which is a grayed out option that's
// intended for display purposes only. Plugin ID sections are spaced out evenly
// at intervals to make it easy to use a single for-loop to create them.
// Audio subsection
// Top items are PCSX2-controlled. SPU2 plugin items are inserted beneath.
// [no items at this time]
MenuId_Audio_Advanced, // inserted at the bottom of the menu
MenuId_PluginBase_Name = 0x100,
MenuId_PluginBase_Settings = 0x101,
MenuId_Video_CoreSettings = 0x200,// includes frame timings and skippings settings
// Controller subsection
// Top items are PCSX2-controlled. Pad plugin items are inserted beneath.
// [no items at this time]
MenuId_Pad_Advanced,
// Miscellaneous Menu! (Misc)
MenuId_Website, // Visit our awesome website!
@ -163,6 +163,17 @@ enum AppEventType
AppStatus_Exiting
};
enum PluginEventType
{
PluginsEvt_Loaded,
PluginsEvt_Init,
PluginsEvt_Open,
PluginsEvt_Close,
PluginsEvt_Shutdown,
PluginsEvt_Unloaded,
};
// --------------------------------------------------------------------------------------
// KeyAcceleratorCode
// A custom keyboard accelerator that I like better than wx's wxAcceleratorEntry.
@ -251,6 +262,54 @@ public:
};
// --------------------------------------------------------------------------------------
// RecentIsoList
// --------------------------------------------------------------------------------------
class RecentIsoList : public wxEvtHandler
{
protected:
struct RecentItem
{
wxString Filename;
wxMenuItem* ItemPtr;
RecentItem() { ItemPtr = NULL; }
RecentItem( const wxString& src ) :
Filename( src )
, ItemPtr( NULL )
{
}
};
std::vector<RecentItem> m_Items;
wxMenu* m_Menu;
uint m_MaxLength;
int m_cursel;
wxMenuItem* m_Separator;
EventListenerBinding<IniInterface> m_Listener_SettingsLoadSave;
public:
RecentIsoList( wxMenu* menu );
virtual ~RecentIsoList() throw();
void RemoveAllFromMenu();
void Repopulate();
void Add( const wxString& src );
protected:
void InsertIntoMenu( int id );
void DoSettingsLoadSave( IniInterface& ini );
void OnChangedSelection( wxCommandEvent& evt );
static void __evt_fastcall OnSettingsLoadSave( void* obj, IniInterface& evt );
};
// --------------------------------------------------------------------------------------
// AppImageIds - Config and Toolbar Images and Icons
// --------------------------------------------------------------------------------------
@ -265,14 +324,11 @@ struct AppImageIds
Video,
Cpu;
ConfigIds() :
Paths( -1 )
, Plugins( -1 )
, Speedhacks( -1 )
, Gamefixes( -1 )
, Video( -1 )
, Cpu( -1 )
ConfigIds()
{
Paths = Plugins =
Speedhacks = Gamefixes =
Video = Cpu = -1;
}
} Config;
@ -285,13 +341,12 @@ struct AppImageIds
PluginAudio,
PluginPad;
ToolbarIds() :
Settings( -1 )
, Play( -1 )
, PluginVideo( -1 )
, PluginAudio( -1 )
, PluginPad( -1 )
ToolbarIds()
{
Settings = Play =
PluginVideo =
PluginAudio =
PluginPad = -1;
}
} Toolbars;
};
@ -324,12 +379,31 @@ public:
virtual ~AppIniLoader() {}
};
// --------------------------------------------------------------------------------------
// =====================================================================================================
// Pcsx2App - main wxApp class
// --------------------------------------------------------------------------------------
// =====================================================================================================
class Pcsx2App : public wxApp
{
// ----------------------------------------------------------------------------
// Event Sources!
// ----------------------------------------------------------------------------
// These need to be at the top of the App class, because a lot of other things depend
// on them and they are, themselves, fairly self-contained.
protected:
EventSource<PluginEventType>m_evtsrc_CorePluginStatus;
CmdEvt_Source m_evtsrc_CoreThreadStatus;
EventSource<int> m_evtsrc_SettingsApplied;
EventSource<IniInterface> m_evtsrc_SettingsLoadSave;
EventSource<AppEventType> m_evtsrc_AppStatus;
public:
CmdEvt_Source& Source_CoreThreadStatus() { return m_evtsrc_CoreThreadStatus; }
EventSource<int>& Source_SettingsApplied() { return m_evtsrc_SettingsApplied; }
EventSource<AppEventType>& Source_AppStatus() { return m_evtsrc_AppStatus; }
EventSource<PluginEventType>& Source_CorePluginStatus() { return m_evtsrc_CorePluginStatus; }
EventSource<IniInterface>& Source_SettingsLoadSave() { return m_evtsrc_SettingsLoadSave; }
public:
CommandDictionary GlobalCommands;
AcceleratorDictionary GlobalAccels;
@ -342,6 +416,9 @@ protected:
ScopedPtr<PipeRedirectionBase> m_StdoutRedirHandle;
ScopedPtr<PipeRedirectionBase> m_StderrRedirHandle;
ScopedPtr<wxMenu> m_RecentIsoMenu;
ScopedPtr<RecentIsoList> m_RecentIsoList;
public:
ScopedPtr<SysCoreAllocations> m_CoreAllocs;
ScopedPtr<PluginManager> m_CorePlugins;
@ -368,7 +445,7 @@ public:
bool PrepForExit( bool canCancel );
void SysExecute();
void SysExecute( CDVD_SourceType cdvdsrc );
void SysExecute( CDVD_SourceType cdvdsrc, const wxString& elf_override=wxEmptyString );
void SysReset();
const wxBitmap& GetLogoBitmap();
@ -376,6 +453,8 @@ public:
wxImageList& GetImgList_Toolbars();
const AppImageIds& GetImgId() const { return m_ImageId; }
wxMenu& GetRecentIsoMenu() { return *m_RecentIsoMenu; }
RecentIsoList& GetRecentIsoList() { return *m_RecentIsoList; }
MainEmuFrame& GetMainFrame() const;
MainEmuFrame* GetMainFramePtr() const { return m_MainFrame; }
@ -409,24 +488,6 @@ public:
void DisableDiskLogging() const;
void OnProgramLogClosed();
// ----------------------------------------------------------------------------
// Event Sources!
// ----------------------------------------------------------------------------
protected:
CmdEvt_Source m_evtsrc_CorePluginStatus;
CmdEvt_Source m_evtsrc_CoreThreadStatus;
EventSource<int> m_evtsrc_SettingsApplied;
EventSource<IniInterface> m_evtsrc_SettingsLoadSave;
EventSource<AppEventType> m_evtsrc_AppStatus;
public:
CmdEvt_Source& Source_CoreThreadStatus() { return m_evtsrc_CoreThreadStatus; }
CmdEvt_Source& Source_CorePluginStatus() { return m_evtsrc_CorePluginStatus; }
EventSource<int>& Source_SettingsApplied() { return m_evtsrc_SettingsApplied; }
EventSource<IniInterface>& Source_SettingsLoadSave() { return m_evtsrc_SettingsLoadSave; }
EventSource<AppEventType>& Source_AppStatus() { return m_evtsrc_AppStatus; }
protected:
void InitDefaultGlobalAccelerators();
void BuildCommandHash();

View File

@ -323,6 +323,7 @@ AppConfig::AppConfig() :
, CloseGSonEsc( true )
, CurrentIso()
, CurrentELF()
, CdvdSource( CDVDsrc_Iso )
, ProgLogBox()
@ -394,6 +395,7 @@ void AppConfig::LoadSaveRootItems( IniInterface& ini )
IniEntry( Toolbar_ShowLabels );
IniEntry( CurrentIso );
IniEntry( CurrentELF );
ini.EnumEntry( L"CdvdSource", CdvdSource, CDVD_SourceLabels, defaults.CdvdSource );
}
@ -459,6 +461,7 @@ AppConfig::FolderOptions::FolderOptions() :
, Logs( PathDefs::GetLogs() )
, RunIso( PathDefs::GetDocuments() ) // raw default is always the Documents folder.
, RunELF( PathDefs::GetDocuments() ) // raw default is always the Documents folder.
{
}
@ -488,6 +491,7 @@ void AppConfig::FolderOptions::LoadSave( IniInterface& ini )
IniEntry( Logs );
IniEntry( RunIso );
IniEntry( RunELF );
if( ini.IsLoading() )
{

View File

@ -76,6 +76,7 @@ public:
Logs;
wxDirName RunIso; // last used location for Iso loading.
wxDirName RunELF; // last used location for ELF loading.
FolderOptions();
void LoadSave( IniInterface& conf );
@ -142,6 +143,7 @@ public:
bool CloseGSonEsc;
wxString CurrentIso;
wxString CurrentELF;
CDVD_SourceType CdvdSource;
McdOptions Mcd[2][4];

View File

@ -31,10 +31,6 @@ bool AppCoreThread::Suspend( bool isBlocking )
{
bool retval = _parent::Suspend( isBlocking );
/*wxCommandEvent evt( pxEVT_CoreThreadStatus );
evt.SetInt( CoreStatus_Suspended );
wxGetApp().AddPendingEvent( evt );*/
// Clear the sticky key statuses, because hell knows what'll change while the PAD
// plugin is suspended.
@ -52,6 +48,8 @@ void AppCoreThread::Resume()
{
// Thread control (suspend / resume) should only be performed from the main/gui thread.
if( !AllowFromMainThreadOnly() ) return;
if( m_ExecMode == ExecMode_Opened ) return;
if( !pxAssert( g_plugins != NULL ) ) return;
if( sys_resume_lock > 0 )
{

View File

@ -263,10 +263,11 @@ bool Pcsx2App::OnInit()
try
{
InitDefaultGlobalAccelerators();
delete wxLog::SetActiveTarget( new pxLogConsole() );
ReadUserModeSettings();
m_RecentIsoList = new RecentIsoList( m_RecentIsoMenu );
ReadUserModeSettings();
AppConfig_OnChangedSettingsFolder();
m_MainFrame = new MainEmuFrame( NULL, L"PCSX2" );
@ -396,9 +397,12 @@ Pcsx2App::Pcsx2App() :
, m_ConfigImagesAreLoaded( false )
, m_ToolbarImages( NULL )
, m_Bitmap_Logo( NULL )
, m_RecentIsoMenu( new wxMenu() )
{
SetAppName( L"pcsx2" );
BuildCommandHash();
m_RecentIsoMenu->Append( MenuId_IsoBrowse, _("Browse..."), _("Browse for an Iso that is not in your recent history.") );
}
Pcsx2App::~Pcsx2App()
@ -434,7 +438,7 @@ Pcsx2App::~Pcsx2App()
// this feature you need to execute pcsx in no-gui mode, and then not move the mouse or use
// the keyboard until you get to the leak. >_<
//
// (but this tool is still still better than nothing!)
// (but this tool is still better than nothing!)
#ifdef PCSX2_DEBUG
struct CrtDebugBreak
@ -447,6 +451,6 @@ struct CrtDebugBreak
}
};
//CrtDebugBreak breakAt( 7586 );
//CrtDebugBreak breakAt( 4327 );
#endif

View File

@ -42,6 +42,7 @@ DEFINE_EVENT_TYPE( pxEVT_FreezeThreadFinished );
#include "Utilities/EventSource.inl"
EventSource_ImplementType( IniInterface );
EventSource_ImplementType( AppEventType );
EventSource_ImplementType( PluginEventType );
bool UseAdminMode = false;
wxDirName SettingsFolder;
@ -442,6 +443,7 @@ void Pcsx2App::OnMainFrameClosed()
// --------------------------------------------------------------------------------------
static int _sysexec_cdvdsrc_type = -1;
static wxString _sysexec_elf_override;
static void _sendmsg_SysExecute()
{
@ -461,6 +463,7 @@ static void OnSysExecuteAfterPlugins( const wxCommandEvent& loadevt )
void Pcsx2App::SysExecute()
{
_sysexec_cdvdsrc_type = -1;
_sysexec_elf_override = CoreThread.GetElfOverride();
if( !m_CorePlugins )
{
LoadPluginsPassive( OnSysExecuteAfterPlugins );
@ -472,9 +475,11 @@ void Pcsx2App::SysExecute()
// Executes the specified cdvd source and optional elf file. This command performs a
// full closure of any existing VM state and starts a fresh VM with the requested
// sources.
void Pcsx2App::SysExecute( CDVD_SourceType cdvdsrc )
void Pcsx2App::SysExecute( CDVD_SourceType cdvdsrc, const wxString& elf_override )
{
_sysexec_cdvdsrc_type = (int)cdvdsrc;
_sysexec_elf_override = elf_override;
if( !m_CorePlugins )
{
LoadPluginsPassive( OnSysExecuteAfterPlugins );
@ -499,6 +504,8 @@ void Pcsx2App::OnSysExecute( wxCommandEvent& evt )
CDVDsys_SetFile( CDVDsrc_Iso, g_Conf->CurrentIso );
if( evt.GetInt() != -1 ) CDVDsys_ChangeSource( (CDVD_SourceType)evt.GetInt() );
if( !CoreThread.HasValidState() )
CoreThread.SetElfOverride( _sysexec_elf_override );
CoreThread.Resume();
}

View File

@ -25,7 +25,6 @@
#ifdef __WXMSW__
# include <wx/msw/wrapwin.h> // needed for OutputDebugStirng
# include <richedit.h>
#endif
BEGIN_DECLARE_EVENT_TYPES()
@ -206,14 +205,14 @@ void ConsoleLogFrame::ColorArray::Cleanup()
// The contents of m_table were created with placement new, and must be
// disposed of manually:
for( int i=0; i<8; ++i )
for( int i=0; i<ConsoleColors_Count; ++i )
m_table[i].~wxTextAttr();
}
// fixme - not implemented yet.
void ConsoleLogFrame::ColorArray::SetFont( const wxFont& font )
{
//for( int i=0; i<8; ++i )
//for( int i=0; i<ConsoleColors_Count; ++i )
// m_table[i].SetFont( font );
}
@ -257,13 +256,6 @@ ConsoleLogFrame::ConsoleLogFrame( MainEmuFrame *parent, const wxString& title, A
m_TextCtrl.SetBackgroundColour( wxColor( 230, 235, 242 ) );
m_TextCtrl.SetDefaultStyle( m_ColorTable[DefaultConsoleColor] );
#ifdef __WXMSW__
// This improves Asian text display behavior on Windows. The IMF_DUALFONT flag helps
// the rich edit box reset back to the default font after displaying japanese characters.
// Other editing and messages have been disabled since our console is read-only anyway.
SendMessage( (HWND)m_TextCtrl.GetHWND(), EM_SETLANGOPTIONS, 0, IMF_AUTOFONT | IMF_DUALFONT );
#endif
// create Log menu (contains most options)
wxMenuBar *pMenuBar = new wxMenuBar();
wxMenu& menuLog = *new wxMenu();
@ -301,12 +293,12 @@ ConsoleLogFrame::ConsoleLogFrame( MainEmuFrame *parent, const wxString& title, A
// Bind Events:
Connect( wxID_OPEN, wxEVT_COMMAND_MENU_SELECTED, wxMenuEventHandler(ConsoleLogFrame::OnOpen) );
Connect( wxID_CLOSE, wxEVT_COMMAND_MENU_SELECTED, wxMenuEventHandler(ConsoleLogFrame::OnClose) );
Connect( wxID_SAVE, wxEVT_COMMAND_MENU_SELECTED, wxMenuEventHandler(ConsoleLogFrame::OnSave) );
Connect( wxID_CLEAR, wxEVT_COMMAND_MENU_SELECTED, wxMenuEventHandler(ConsoleLogFrame::OnClear) );
Connect( wxID_OPEN, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(ConsoleLogFrame::OnOpen) );
Connect( wxID_CLOSE, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(ConsoleLogFrame::OnClose) );
Connect( wxID_SAVE, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(ConsoleLogFrame::OnSave) );
Connect( wxID_CLEAR, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(ConsoleLogFrame::OnClear) );
Connect( MenuID_FontSize_Small, MenuID_FontSize_Huge, wxEVT_COMMAND_MENU_SELECTED, wxMenuEventHandler( ConsoleLogFrame::OnFontSize ) );
Connect( MenuID_FontSize_Small, MenuID_FontSize_Huge, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( ConsoleLogFrame::OnFontSize ) );
Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler(ConsoleLogFrame::OnCloseWindow) );
Connect( wxEVT_MOVE, wxMoveEventHandler(ConsoleLogFrame::OnMoveAround) );
@ -461,17 +453,17 @@ void ConsoleLogFrame::OnCloseWindow(wxCloseEvent& event)
}
}
void ConsoleLogFrame::OnOpen(wxMenuEvent& WXUNUSED(event))
void ConsoleLogFrame::OnOpen(wxCommandEvent& WXUNUSED(event))
{
Show(true);
}
void ConsoleLogFrame::OnClose( wxMenuEvent& event )
void ConsoleLogFrame::OnClose( wxCommandEvent& event )
{
DoClose();
}
void ConsoleLogFrame::OnSave(wxMenuEvent& WXUNUSED(event))
void ConsoleLogFrame::OnSave(wxCommandEvent& WXUNUSED(event))
{
wxString filename;
wxFile file;
@ -497,12 +489,12 @@ void ConsoleLogFrame::OnSave(wxMenuEvent& WXUNUSED(event))
wxLogStatus(this, L"Log saved to the file '%s'.", filename.c_str());
}
void ConsoleLogFrame::OnClear(wxMenuEvent& WXUNUSED(event))
void ConsoleLogFrame::OnClear(wxCommandEvent& WXUNUSED(event))
{
m_TextCtrl.Clear();
}
void ConsoleLogFrame::OnFontSize( wxMenuEvent& evt )
void ConsoleLogFrame::OnFontSize( wxCommandEvent& evt )
{
int ptsize = 8;
switch( evt.GetId() )

View File

@ -200,12 +200,12 @@ public:
protected:
// menu callbacks
virtual void OnOpen (wxMenuEvent& event);
virtual void OnClose(wxMenuEvent& event);
virtual void OnSave (wxMenuEvent& event);
virtual void OnClear(wxMenuEvent& event);
virtual void OnOpen (wxCommandEvent& event);
virtual void OnClose(wxCommandEvent& event);
virtual void OnSave (wxCommandEvent& event);
virtual void OnClear(wxCommandEvent& event);
void OnFontSize(wxMenuEvent& event);
void OnFontSize(wxCommandEvent& event);
virtual void OnCloseWindow(wxCloseEvent& event);

View File

@ -42,22 +42,6 @@ wxMenu* MainEmuFrame::MakeStatesSubMenu( int baseid ) const
return mnuSubstates;
}
// ------------------------------------------------------------------------
wxMenu* MainEmuFrame::MakeCdvdMenu()
{
wxMenu* mnuCdvd = new wxMenu();
mnuCdvd->Append( MenuId_Src_Iso, _("Iso"), wxEmptyString, wxITEM_RADIO );
mnuCdvd->Append( MenuId_Src_Plugin, _("Plugin"), wxEmptyString, wxITEM_RADIO );
mnuCdvd->Append( MenuId_Src_NoDisc, _("No disc"), wxEmptyString, wxITEM_RADIO );
mnuCdvd->AppendSeparator();
mnuCdvd->Append( MenuId_IsoBrowse, _("Iso Browser..."), _("Select the Iso source image.") );
mnuCdvd->Append( MenuId_Config_CDVD, _("Plugin settings..."),
_("Opens the CDVD plugin configuration dialog") );
return mnuCdvd;
}
void MainEmuFrame::UpdateIsoSrcSelection()
{
MenuIdentifiers cdsrc = MenuId_Src_Iso;
@ -81,47 +65,8 @@ void MainEmuFrame::UpdateIsoSrcFile()
if( !exists )
g_Conf->CurrentIso.Clear();
wxString label;
label.Printf( L"%s -> %s", _("Iso"),
exists ? g_Conf->CurrentIso.c_str() : _("Empty")
);
sMenuBar.SetLabel( MenuId_Src_Iso, label );
}
void MainEmuFrame::LoadSaveRecentIsoList( IniInterface& conf )
{
if( conf.IsLoading() )
m_RecentIsoList->Load( conf.GetConfig() );
else
m_RecentIsoList->Save( conf.GetConfig() );
}
// ------------------------------------------------------------------------
// Video / Audio / Pad "Extensible" Menus
// ------------------------------------------------------------------------
void MainEmuFrame::PopulateVideoMenu()
{
m_menuVideo.Append( MenuId_Video_Basics, _("Basic Settings..."), wxEmptyString, wxITEM_CHECK );
m_menuVideo.AppendSeparator();
// Populate options from the plugin here.
m_menuVideo.Append( MenuId_Video_Advanced, _("Advanced..."), wxEmptyString, wxITEM_NORMAL );
}
void MainEmuFrame::PopulateAudioMenu()
{
// Populate options from the plugin here.
m_menuAudio.Append( MenuId_Audio_Advanced, _("Advanced..."), wxEmptyString, wxITEM_NORMAL );
}
void MainEmuFrame::PopulatePadMenu()
{
// Populate options from the plugin here.
m_menuPad.Append( MenuId_Pad_Advanced, _("Advanced..."), wxEmptyString, wxITEM_NORMAL );
//sMenuBar.SetLabel( MenuId_Src_Iso, wxsFormat( L"%s -> %s", _("Iso"),
// exists ? Path::GetFilename(g_Conf->CurrentIso).c_str() : _("Empty") ) );
}
// ------------------------------------------------------------------------
@ -206,9 +151,8 @@ void MainEmuFrame::ConnectMenus()
ConnectMenuRange(MenuId_Config_GS, PluginId_Count, Menu_ConfigPlugin_Click);
ConnectMenuRange(MenuId_Src_Iso, 3, Menu_CdvdSource_Click);
ConnectMenu( MenuId_Video_Advanced, Menu_ConfigPlugin_Click);
ConnectMenu( MenuId_Audio_Advanced, Menu_ConfigPlugin_Click);
ConnectMenu( MenuId_Pad_Advanced, Menu_ConfigPlugin_Click);
for( int i=0; i<PluginId_Count; ++i )
ConnectMenu( MenuId_PluginBase_Settings + (i*PluginMenuId_Interval), Menu_ConfigPlugin_Click);
ConnectMenu( MenuId_Boot_CDVD, Menu_BootCdvd_Click );
ConnectMenu( MenuId_Boot_ELF, Menu_OpenELF_Click );
@ -258,20 +202,29 @@ void __evt_fastcall MainEmuFrame::OnCoreThreadStatusChanged( void* obj, wxComman
{
if( obj == NULL ) return;
MainEmuFrame* mframe = (MainEmuFrame*)obj;
if( !pxAssertMsg( mframe->GetMenuBar()!=NULL, "Mainframe menu bar is NULL!" ) ) return;
mframe->ApplyCoreStatus();
}
void __evt_fastcall MainEmuFrame::OnCorePluginStatusChanged( void* obj, wxCommandEvent& evt )
void __evt_fastcall MainEmuFrame::OnCorePluginStatusChanged( void* obj, PluginEventType& evt )
{
if( obj == NULL ) return;
MainEmuFrame* mframe = (MainEmuFrame*)obj;
mframe->ApplyCoreStatus();
if( (evt != PluginsEvt_Loaded) && (evt != PluginsEvt_Unloaded) ) return; // everything else we don't care about
MainEmuFrame& mframe = *(MainEmuFrame*)obj;
if( !pxAssertMsg( mframe.GetMenuBar()!=NULL, "Mainframe menu bar is NULL!" ) ) return;
mframe.ApplyCoreStatus();
mframe.ApplyPluginStatus();
}
void __evt_fastcall MainEmuFrame::OnSettingsApplied( void* obj, int& evt )
{
if( obj == NULL ) return;
MainEmuFrame* mframe = (MainEmuFrame*)obj;
if( !pxAssertMsg( mframe->GetMenuBar()!=NULL, "Mainframe menu bar is NULL!" ) ) return;
mframe->ApplySettings();
}
@ -280,15 +233,22 @@ void __evt_fastcall MainEmuFrame::OnSettingsLoadSave( void* obj, IniInterface& e
if( obj == NULL ) return;
MainEmuFrame* mframe = (MainEmuFrame*)obj;
mframe->LoadSaveRecentIsoList( evt );
}
static int GetPluginMenuId_Settings( PluginsEnum_t pid )
{
return MenuId_PluginBase_Settings + ((int)pid * PluginMenuId_Interval);
}
static int GetPluginMenuId_Name( PluginsEnum_t pid )
{
return MenuId_PluginBase_Name + ((int)pid * PluginMenuId_Interval);
}
// ------------------------------------------------------------------------
MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title):
wxFrame(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE & ~(wxMAXIMIZE_BOX | wxRESIZE_BORDER) ),
m_RecentIsoList( new wxFileHistory( g_Conf->RecentFileCount ) ),
m_statusbar( *CreateStatusBar(2, 0) ),
m_background( this, wxID_ANY, wxGetApp().GetLogoBitmap() ),
@ -297,13 +257,10 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title):
m_menubar( *new wxMenuBar() ),
m_menuBoot ( *new wxMenu() ),
m_menuEmu ( *new wxMenu() ),
m_menuCDVD ( *new wxMenu() ),
m_menuSys ( *new wxMenu() ),
m_menuConfig( *new wxMenu() ),
m_menuMisc ( *new wxMenu() ),
m_menuVideo ( *new wxMenu() ),
m_menuAudio ( *new wxMenu() ),
m_menuPad ( *new wxMenu() ),
m_menuDebug ( *new wxMenu() ),
m_LoadStatesSubmenu( *MakeStatesSubMenu( MenuId_State_Load01 ) ),
@ -312,19 +269,22 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title):
m_MenuItem_Console( *new wxMenuItem( &m_menuMisc, MenuId_Console, L"Show Console", wxEmptyString, wxITEM_CHECK ) ),
m_Listener_CoreThreadStatus( wxGetApp().Source_CoreThreadStatus(), CmdEvt_Listener( this, OnCoreThreadStatusChanged ) ),
m_Listener_CorePluginStatus( wxGetApp().Source_CorePluginStatus(), CmdEvt_Listener( this, OnCorePluginStatusChanged ) ),
m_Listener_CorePluginStatus( wxGetApp().Source_CorePluginStatus(), EventListener<PluginEventType>( this, OnCorePluginStatusChanged ) ),
m_Listener_SettingsApplied( wxGetApp().Source_SettingsApplied(), EventListener<int>( this, OnSettingsApplied ) ),
m_Listener_SettingsLoadSave( wxGetApp().Source_SettingsLoadSave(), EventListener<IniInterface>( this, OnSettingsLoadSave ) )
{
for( int i=0; i<PluginId_Count; ++i )
m_PluginMenuPacks[i].Populate( (PluginsEnum_t)i );
// ------------------------------------------------------------------------
// Initial menubar setup. This needs to be done first so that the menu bar's visible size
// can be factored into the window size (which ends up being background+status+menus)
m_menubar.Append( &m_menuBoot, _("&Boot") );
m_menubar.Append( &m_menuEmu, _("&System") );
m_menubar.Append( &m_menuCDVD, _("CD&VD") );
m_menubar.Append( &m_menuSys, _("&System") );
m_menubar.Append( &m_menuConfig, _("&Config") );
m_menubar.Append( &m_menuVideo, _("&Video") );
m_menubar.Append( &m_menuAudio, _("&Audio") );
m_menubar.Append( &m_menuMisc, _("&Misc") );
m_menubar.Append( &m_menuDebug, _("&Debug") );
SetMenuBar( &m_menubar );
@ -393,35 +353,43 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title):
wxMenu* recentRunMenu = new wxMenu();
m_menuBoot.Append(MenuId_Boot_Recent, _("Run Recent"), recentRunMenu);
m_RecentIsoList->UseMenu( recentRunMenu );
m_RecentIsoList->AddFilesToMenu( recentRunMenu );
m_menuBoot.AppendSeparator();
m_menuBoot.Append(MenuId_Cdvd_Source, _("Select CDVD source"), MakeCdvdMenu() );
m_menuBoot.Append(MenuId_SkipBiosToggle,_("BIOS Skip Hack"),
_("Skips PS2 splash screens when booting from Iso or CDVD media"), wxITEM_CHECK );
m_menuBoot.AppendSeparator();
m_menuBoot.Append(MenuId_Exit, _("Exit"),
_("Closing PCSX2 may be hazardous to your health"));
// ------------------------------------------------------------------------
m_menuEmu.Append(MenuId_Sys_SuspendResume, _("Suspend") )->Enable( SysHasValidState() );
wxMenu& isoRecents( wxGetApp().GetRecentIsoMenu() );
m_menuEmu.AppendSeparator();
//m_menuCDVD.AppendSeparator();
m_menuCDVD.Append( MenuId_IsoSelector, _("Iso Selector"), &isoRecents );
m_menuCDVD.Append( GetPluginMenuId_Settings(PluginId_CDVD), _("Plugin Menu"), m_PluginMenuPacks[PluginId_CDVD] );
//m_menuEmu.Append(MenuId_Sys_Close, _("Close"),
m_menuCDVD.AppendSeparator();
m_menuCDVD.Append( MenuId_Src_Iso, _("Iso"), _("Makes the specified ISO image the CDVD source."), wxITEM_RADIO );
m_menuCDVD.Append( MenuId_Src_Plugin, _("Plugin"), _("Uses an external plugin as the CDVD source."), wxITEM_RADIO );
m_menuCDVD.Append( MenuId_Src_NoDisc, _("No disc"), _("Use this to boot into your virtual PS2's BIOS configuration."), wxITEM_RADIO );
m_menuCDVD.AppendSeparator();
m_menuCDVD.Append( MenuId_SkipBiosToggle,_("Enable Skip BIOS Hack"),
_("Skips PS2 splash screens when booting from Iso or CDVD media"), wxITEM_CHECK );
// ------------------------------------------------------------------------
m_menuSys.Append(MenuId_Sys_SuspendResume, _("Suspend") )->Enable( SysHasValidState() );
m_menuSys.AppendSeparator();
//m_menuSys.Append(MenuId_Sys_Close, _("Close"),
// _("Stops emulation and closes the GS window."));
m_menuEmu.Append(MenuId_Sys_LoadStates, _("Load state"), &m_LoadStatesSubmenu);
m_menuEmu.Append(MenuId_Sys_SaveStates, _("Save state"), &m_SaveStatesSubmenu);
m_menuSys.Append(MenuId_Sys_LoadStates, _("Load state"), &m_LoadStatesSubmenu);
m_menuSys.Append(MenuId_Sys_SaveStates, _("Save state"), &m_SaveStatesSubmenu);
m_menuEmu.AppendSeparator();
m_menuEmu.Append(MenuId_EnablePatches, _("Enable Patches"),
m_menuSys.AppendSeparator();
m_menuSys.Append(MenuId_EnablePatches, _("Enable Patches"),
wxEmptyString, wxITEM_CHECK);
m_menuEmu.AppendSeparator();
m_menuEmu.Append(MenuId_Sys_Reset, _("Reset"),
m_menuSys.AppendSeparator();
m_menuSys.Append(MenuId_Sys_Reset, _("Reset"),
_("Resets emulation state and re-runs current image"));
// ------------------------------------------------------------------------
@ -429,13 +397,13 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title):
m_menuConfig.Append(MenuId_Config_Settings, _("General &Settings") );
m_menuConfig.AppendSeparator();
m_menuConfig.Append(MenuId_Config_PAD, _("PAD"), &m_menuPad );
// Query installed "tertiary" plugins for name and menu options.
m_menuConfig.Append(MenuId_Config_CDVD, _("CDVD"), wxEmptyString);
m_menuConfig.Append(MenuId_Config_DEV9, _("Dev9"), wxEmptyString);
m_menuConfig.Append(MenuId_Config_USB, _("USB"), wxEmptyString);
m_menuConfig.Append(MenuId_Config_FireWire, _("Firewire"), wxEmptyString);
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_PAD, _("Controllers (PAD)"), m_PluginMenuPacks[PluginId_PAD]);
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_FireWire, _("Firewire"), m_PluginMenuPacks[PluginId_FW]);
m_menuConfig.AppendSeparator();
m_menuConfig.Append(MenuId_Config_Patches, _("Patches"), wxEmptyString);
@ -451,12 +419,6 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title):
// ------------------------------------------------------------------------
PopulateVideoMenu();
PopulateAudioMenu();
PopulatePadMenu();
// ------------------------------------------------------------------------
m_menuMisc.Append( &m_MenuItem_Console );
m_menuMisc.Append(MenuId_Profiler, _("Show Profiler"), wxEmptyString, wxITEM_CHECK);
m_menuMisc.AppendSeparator();
@ -487,36 +449,18 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title):
MainEmuFrame::~MainEmuFrame() throw()
{
try
{
if( m_RecentIsoList && GetAppConfig() )
m_RecentIsoList->Save( *GetAppConfig() );
}
DESTRUCTOR_CATCHALL
m_menuCDVD.Remove( MenuId_IsoSelector );
}
// This should be called whenever major changes to the ini configs have occurred,
// or when the recent file count mismatches the max filecount.
void MainEmuFrame::ReloadRecentLists()
{
// Always perform delete and reload of the Recent Iso List. This handles cases where
// the recent file count has been changed, and it's a helluva lot easier than trying
// to make a clone copy of this complex object. ;)
wxConfigBase* cfg = GetAppConfig();
pxAssert( cfg != NULL );
if( m_RecentIsoList )
m_RecentIsoList->Save( *cfg );
m_RecentIsoList.Reassign( new wxFileHistory(g_Conf->RecentFileCount) )->Load( *cfg );
UpdateIsoSrcFile();
cfg->Flush();
}
void MainEmuFrame::ApplyCoreStatus()
{
wxMenuBar& menubar( *GetMenuBar() );
if( !pxAssertMsg( &menubar!=NULL, "Mainframe menu bar is NULL!" ) ) return;
wxMenuItem& susres( *menubar.FindItem( MenuId_Sys_SuspendResume ) );
if( !pxAssertMsg( &susres!=NULL, "Suspend/Resume Menubar Item is NULL!" ) ) return;
@ -544,19 +488,96 @@ void MainEmuFrame::ApplyCoreStatus()
menubar.Enable( MenuId_Sys_Reset, SysHasValidState() || (g_plugins!=NULL) );
}
void MainEmuFrame::ApplyPluginStatus()
{
wxMenuBar& menubar( *GetMenuBar() );
if( g_plugins == NULL )
{
for( int i=0; i<PluginId_Count; ++i )
m_PluginMenuPacks[i].OnUnloaded();
}
else
{
for( int i=0; i<PluginId_Count; ++i )
m_PluginMenuPacks[i].OnLoaded();
// bleh this makes the menu too cluttered. --air
//m_menuCDVD.SetLabel( MenuId_Src_Plugin, wxsFormat( L"%s (%s)", _("Plugin"),
// g_plugins->GetName( PluginId_CDVD ).c_str() ) );
}
// Re-populate plugin menus.
// Delete any menu options added by plugins (typically a plugin will have already
// done its own proper cleanup when the plugin was shutdown or unloaded, but lets
// not trust them, shall we?)
}
void MainEmuFrame::ApplySettings()
{
wxMenuBar& menubar( *GetMenuBar() );
if( !pxAssertMsg( &menubar!=NULL, "Mainframe menu bar is NULL!" ) ) return;
menubar.Check( MenuId_SkipBiosToggle, g_Conf->EmuOptions.SkipBiosSplash );
menubar.Check( MenuId_Config_Multitap0Toggle, g_Conf->EmuOptions.MultitapPort0_Enabled );
menubar.Check( MenuId_Config_Multitap1Toggle, g_Conf->EmuOptions.MultitapPort1_Enabled );
if( m_RecentIsoList )
{
if( m_RecentIsoList->GetMaxFiles() != g_Conf->RecentFileCount )
ReloadRecentLists();
}
UpdateIsoSrcFile();
}
// ------------------------------------------------------------------------
// "Extensible" Plugin Menus
// ------------------------------------------------------------------------
PerPluginMenuInfo::~PerPluginMenuInfo() throw()
{
}
void PerPluginMenuInfo::Populate( PluginsEnum_t pid )
{
if( !pxAssert(pid < PluginId_Count) ) return;
PluginId = pid;
MyMenu.Append( GetPluginMenuId_Name(PluginId), _("No plugin loaded") )->Enable( false );
MyMenu.AppendSeparator();
if( PluginId == PluginId_GS )
{
MyMenu.Append( MenuId_Video_CoreSettings, _("Core Settings..."),
_("Modify video emulation settings regulated by the PCSX2 core virtual machine."), wxITEM_CHECK );
MyMenu.AppendSeparator();
}
// Populate options from the plugin here.
MyMenu.Append( GetPluginMenuId_Settings(PluginId), _("Plugin Settings..."),
wxsFormat( _("Opens the %s plugin's advanced settings dialog."), tbl_PluginInfo[pid].GetShortname() )
);
}
// deletes menu items belonging to (created by) the plugin. Leaves menu items created
// by the PCSX2 core intact.
void PerPluginMenuInfo::OnUnloaded()
{
MenuItemAddonList& curlist( m_PluginMenuItems );
for( uint mx=0; mx<curlist.size(); ++mx )
MyMenu.Delete( curlist[mx].Item );
curlist.clear();
MyMenu.SetLabel( GetPluginMenuId_Name(PluginId), _("No plugin loaded") );
MyMenu.Enable( GetPluginMenuId_Settings(PluginId), false );
}
void PerPluginMenuInfo::OnLoaded()
{
MenuItemAddonList& curlist( m_PluginMenuItems );
MyMenu.SetLabel( GetPluginMenuId_Name(PluginId),
g_plugins->GetName( PluginId ) + L" " + g_plugins->GetVersion( PluginId )
);
MyMenu.Enable( GetPluginMenuId_Settings(PluginId), true );
}

View File

@ -36,6 +36,59 @@ protected:
void OnKeyDown( wxKeyEvent& evt );
};
struct PluginMenuAddition
{
wxString Text;
wxString HelpText;
PS2E_MenuItemStyle Flags;
wxMenuItem* Item;
int ItemId;
// Optional user data pointer (or typecast integer value)
void* UserPtr;
void (PS2E_CALLBACK *OnClicked)( PS2E_THISPTR* thisptr, void* userptr );
};
// --------------------------------------------------------------------------------------
// PerPluginMenuInfo
// --------------------------------------------------------------------------------------
class PerPluginMenuInfo
{
protected:
typedef std::vector<PluginMenuAddition> MenuItemAddonList;
// A list of menu items belonging to this plugin's menu.
MenuItemAddonList m_PluginMenuItems;
// Base index for inserting items, usually points to the position
// after the heading entry and separator.
int m_InsertIndexBase;
// Current index for inserting menu items; increments with each item
// added by a plugin.
int m_InsertIndexCur;
public:
PluginsEnum_t PluginId;
wxMenu& MyMenu;
public:
PerPluginMenuInfo() : MyMenu( *new wxMenu() )
{
}
virtual ~PerPluginMenuInfo() throw();
void Populate( PluginsEnum_t pid );
void OnUnloaded();
void OnLoaded();
operator wxMenu*() { return &MyMenu; }
operator const wxMenu*() const { return &MyMenu; }
};
class MainEmuFrame : public wxFrame
{
// ------------------------------------------------------------------------
@ -43,31 +96,29 @@ class MainEmuFrame : public wxFrame
// ------------------------------------------------------------------------
protected:
ScopedPtr<wxFileHistory> m_RecentIsoList;
wxStatusBar& m_statusbar;
wxStaticBitmap m_background;
wxMenuBar& m_menubar;
wxMenu& m_menuBoot;
wxMenu& m_menuEmu;
wxMenu& m_menuCDVD;
wxMenu& m_menuSys;
wxMenu& m_menuConfig;
wxMenu& m_menuMisc;
wxMenu& m_menuDebug;
wxMenu& m_menuVideo;
wxMenu& m_menuAudio;
wxMenu& m_menuPad;
wxMenu& m_LoadStatesSubmenu;
wxMenu& m_SaveStatesSubmenu;
wxMenuItem& m_MenuItem_Console;
CmdEvt_ListenerBinding m_Listener_CoreThreadStatus;
CmdEvt_ListenerBinding m_Listener_CorePluginStatus;
EventListenerBinding<int> m_Listener_SettingsApplied;
EventListenerBinding<IniInterface> m_Listener_SettingsLoadSave;
PerPluginMenuInfo m_PluginMenuPacks[PluginId_Count];
CmdEvt_ListenerBinding m_Listener_CoreThreadStatus;
EventListenerBinding<PluginEventType> m_Listener_CorePluginStatus;
EventListenerBinding<int> m_Listener_SettingsApplied;
EventListenerBinding<IniInterface> m_Listener_SettingsLoadSave;
// ------------------------------------------------------------------------
// MainEmuFrame Constructors and Member Methods
@ -86,13 +137,13 @@ public:
protected:
static void __evt_fastcall OnCoreThreadStatusChanged( void* obj, wxCommandEvent& evt );
static void __evt_fastcall OnCorePluginStatusChanged( void* obj, wxCommandEvent& evt );
static void __evt_fastcall OnCorePluginStatusChanged( void* obj, PluginEventType& evt );
static void __evt_fastcall OnSettingsApplied( void* obj, int& evt );
static void __evt_fastcall OnSettingsLoadSave( void* obj, IniInterface& evt );
void LoadSaveRecentIsoList( IniInterface& conf );
void ApplySettings();
void ApplyCoreStatus();
void ApplyPluginStatus();
void InitLogBoxPosition( AppConfig::ConsoleLogOptions& conf );
@ -131,6 +182,7 @@ protected:
void Menu_ShowAboutBox(wxCommandEvent &event);
bool _DoSelectIsoBrowser();
bool _DoSelectELFBrowser();
// ------------------------------------------------------------------------
// MainEmuFram Internal API for Populating Main Menu Contents
@ -139,11 +191,7 @@ protected:
wxMenu* MakeStatesSubMenu( int baseid ) const;
wxMenu* MakeStatesMenu();
wxMenu* MakeLanguagesMenu() const;
wxMenu* MakeCdvdMenu();
void PopulateVideoMenu();
void PopulateAudioMenu();
void PopulatePadMenu();
void ConnectMenus();
friend class Pcsx2App;

View File

@ -65,8 +65,9 @@ bool MainEmuFrame::_DoSelectIsoBrowser()
{
g_Conf->Folders.RunIso = wxFileName( ctrl.GetPath() ).GetPath();
g_Conf->CurrentIso = ctrl.GetPath();
AppSaveSettings();
sApp.GetRecentIsoList().Add( g_Conf->CurrentIso );
AppSaveSettings();
UpdateIsoSrcFile();
return true;
}
@ -74,6 +75,26 @@ bool MainEmuFrame::_DoSelectIsoBrowser()
return false;
}
bool MainEmuFrame::_DoSelectELFBrowser()
{
static const wxChar* elfFilterTypes =
L"ELF Files (.elf)|*.elf|"
L"All Files (*.*)|*.*";
wxFileDialog ctrl( this, _("Select ELF file..."), g_Conf->Folders.RunELF.ToString(), wxEmptyString,
elfFilterTypes, wxFD_OPEN | wxFD_FILE_MUST_EXIST );
if( ctrl.ShowModal() != wxID_CANCEL )
{
g_Conf->Folders.RunELF = wxFileName( ctrl.GetPath() ).GetPath();
g_Conf->CurrentELF = ctrl.GetPath();
AppSaveSettings();
return true;
}
return false;
}
void MainEmuFrame::Menu_BootCdvd_Click( wxCommandEvent &event )
{
CoreThread.Suspend();
@ -116,13 +137,12 @@ void MainEmuFrame::Menu_RunIso_Click( wxCommandEvent &event )
{
CoreThread.Suspend();
if( !_DoSelectIsoBrowser() )
if( _DoSelectIsoBrowser() )
{
CoreThread.Resume();
return;
sApp.SysExecute( CDVDsrc_Iso );
}
sApp.SysExecute( CDVDsrc_Iso );
CoreThread.Resume();
}
void MainEmuFrame::Menu_IsoRecent_Click(wxCommandEvent &event)
@ -153,6 +173,13 @@ void MainEmuFrame::Menu_SkipBiosToggle_Click( wxCommandEvent &event )
void MainEmuFrame::Menu_OpenELF_Click(wxCommandEvent &event)
{
CoreThread.Suspend();
if( _DoSelectELFBrowser() )
{
sApp.SysExecute( g_Conf->CdvdSource, g_Conf->CurrentELF );
}
CoreThread.Resume();
}
void MainEmuFrame::Menu_LoadStates_Click(wxCommandEvent &event)
@ -206,7 +233,9 @@ void MainEmuFrame::Menu_SysReset_Click(wxCommandEvent &event)
sApp.SysReset();
if( resume )
{
sApp.SysExecute();
}
GetMenuBar()->Enable( MenuId_Sys_Reset, resume );
}
@ -214,22 +243,10 @@ void MainEmuFrame::Menu_SysReset_Click(wxCommandEvent &event)
void MainEmuFrame::Menu_ConfigPlugin_Click(wxCommandEvent &event)
{
typedef void (CALLBACK* PluginConfigureFnptr)();
const int eventId = event.GetId();
PluginsEnum_t pid;
switch (eventId) {
case MenuId_Video_Advanced:
pid = PluginId_GS;
break;
case MenuId_Audio_Advanced:
pid = PluginId_SPU2;
break;
case MenuId_Pad_Advanced:
pid = PluginId_PAD;
break;
default:
pid = (PluginsEnum_t)( event.GetId() - MenuId_Config_GS );
break;
}
const int eventId = event.GetId() - MenuId_PluginBase_Settings;
PluginsEnum_t pid = (PluginsEnum_t)(eventId / PluginMenuId_Interval);
if( !pxAssertDev( (eventId >= 0) || (pid < PluginId_Count), "Invalid plugin identifier passed to ConfigPlugin event handler." ) ) return;
LoadPluginsImmediate();
if( g_plugins == NULL ) return;

View File

@ -29,6 +29,54 @@ using namespace Threading;
static FnType_OnThreadComplete* Callback_PluginsLoadComplete = NULL;
class AppPluginManager : public PluginManager
{
typedef PluginManager _parent;
public:
AppPluginManager( const wxString (&folders)[PluginId_Count] ) : PluginManager( folders )
{
}
virtual ~AppPluginManager() throw()
{
PluginEventType pevt = PluginsEvt_Unloaded;
sApp.Source_CorePluginStatus().Dispatch( pevt );
}
void Init()
{
_parent::Init();
PluginEventType pevt = PluginsEvt_Init;
sApp.Source_CorePluginStatus().Dispatch( pevt );
}
void Shutdown()
{
_parent::Shutdown();
PluginEventType pevt = PluginsEvt_Shutdown;
sApp.Source_CorePluginStatus().Dispatch( pevt );
}
void Close()
{
_parent::Close();
PluginEventType pevt = PluginsEvt_Close;
sApp.Source_CorePluginStatus().Dispatch( pevt );
}
void Open()
{
_parent::Open();
PluginEventType pevt = PluginsEvt_Open;
sApp.Source_CorePluginStatus().Dispatch( pevt );
}
};
// --------------------------------------------------------------------------------------
// LoadPluginsTask
// --------------------------------------------------------------------------------------
@ -74,7 +122,7 @@ void LoadPluginsTask::ExecuteTaskInThread()
// This is for testing of the error handler... uncomment for fun?
//throw Exception::PluginError( PluginId_PAD, "This one is for testing the error handler!" );
Result = PluginManager_Create( m_folders );
Result = new AppPluginManager( m_folders );
}
void LoadPluginsTask::OnCleanupInThread()
@ -166,7 +214,9 @@ void Pcsx2App::OnLoadPluginsComplete( wxCommandEvent& evt )
if( fn_tmp != NULL ) fn_tmp( evt );
//m_evtsrc_PluginLoadFinished.Dispatch( evt );
PluginEventType pevt = PluginsEvt_Loaded;
sApp.Source_CorePluginStatus().Dispatch( pevt );
Source_CorePluginStatus().Dispatch( pevt );
}
// Posts a message to the App to reload plugins. Plugins are loaded via a background thread
@ -206,12 +256,12 @@ void LoadPluginsImmediate()
wxString passins[PluginId_Count];
ConvertPluginFilenames( passins );
wxGetApp().m_CorePlugins = PluginManager_Create( passins );
wxGetApp().m_CorePlugins = new AppPluginManager( passins );
}
void UnloadPlugins()
{
CoreThread.Cancel();
wxGetApp().m_CorePlugins = NULL;
sApp.m_CorePlugins = NULL;
}

167
pcsx2/gui/RecentIsoList.cpp Normal file
View File

@ -0,0 +1,167 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2009 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"
#include "MainFrame.h"
RecentIsoList::RecentIsoList( wxMenu* menu ) :
m_Menu( menu )
, m_MaxLength( g_Conf->RecentFileCount )
, m_cursel( 0 )
, m_Separator( NULL )
, m_Listener_SettingsLoadSave( wxGetApp().Source_SettingsLoadSave(), EventListener<IniInterface>( this, OnSettingsLoadSave ) )
{
m_Menu->Connect( wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(RecentIsoList::OnChangedSelection) );
}
RecentIsoList::~RecentIsoList() throw()
{
}
void RecentIsoList::OnChangedSelection( wxCommandEvent& evt )
{
uint cnt = m_Items.size();
uint i=0;
for( ; i<cnt; ++i )
{
if( (m_Items[i].ItemPtr == NULL) || (m_Items[i].ItemPtr->GetId() != evt.GetId()) ) continue;
}
if( i >= m_Items.size() ) return;
m_cursel = i;
g_Conf->CurrentIso = m_Items[i].Filename;
sMainFrame.UpdateIsoSrcFile();
}
void RecentIsoList::RemoveAllFromMenu()
{
if( m_Menu == NULL ) return;
int cnt = m_Items.size();
for( int i=0; i<cnt; ++i )
{
if( m_Items[i].ItemPtr == NULL ) continue;
m_Menu->Destroy( m_Items[i].ItemPtr );
m_Items[i].ItemPtr = NULL;
}
if( m_Separator != NULL )
{
m_Menu->Destroy( m_Separator );
m_Separator = NULL;
}
}
void RecentIsoList::Repopulate()
{
int cnt = m_Items.size();
if( cnt <= 0 ) return;
m_Separator = m_Menu->AppendSeparator();
for( int i=0; i<cnt; ++i )
InsertIntoMenu( i );
}
void RecentIsoList::Add( const wxString& src )
{
if( src.IsEmpty() ) return;
wxFileName temp( src );
temp.Normalize();
wxString normalized( temp.GetFullPath() );
int cnt = m_Items.size();
if( cnt <= 0 )
{
pxAssert( m_Separator == NULL );
m_Separator = m_Menu->AppendSeparator();
}
else
{
for( int i=0; i<cnt; ++i )
{
if( m_Items[i].Filename == normalized )
{
m_cursel = i;
if( m_Items[i].ItemPtr != NULL )
m_Items[i].ItemPtr->Check();
return;
}
}
}
m_Items.push_back( RecentItem( normalized ) );
InsertIntoMenu( m_cursel = (m_Items.size()-1) );
while( m_Items.size() > m_MaxLength )
{
m_Items.erase( m_Items.begin() );
}
}
void RecentIsoList::InsertIntoMenu( int id )
{
if( m_Menu == NULL ) return;
RecentItem& curitem( m_Items[id] );
curitem.ItemPtr = m_Menu->Append( wxID_ANY, Path::GetFilename(curitem.Filename), curitem.Filename, wxITEM_RADIO );
if( m_cursel == id )
curitem.ItemPtr->Check();
}
void RecentIsoList::DoSettingsLoadSave( IniInterface& ini )
{
ini.GetConfig().SetRecordDefaults( false );
if( ini.IsSaving() )
{
// Wipe existing recent iso list if we're saving, because our size might have changed
// and that could leave some residual entries in the config.
ini.GetConfig().DeleteGroup( L"RecentIso" );
IniScopedGroup groupie( ini, L"RecentIso" );
int cnt = m_Items.size();
for( int i=0; i<cnt; ++i )
{
ini.Entry( wxsFormat( L"Filename%02d", i ), m_Items[i].Filename );
}
}
else
{
RemoveAllFromMenu();
m_MaxLength = g_Conf->RecentFileCount;
IniScopedGroup groupie( ini, L"RecentIso" );
for( uint i=0; i<m_MaxLength; ++i )
{
wxString loadtmp;
ini.Entry( wxsFormat( L"Filename%02d", i ), loadtmp );
if( !loadtmp.IsEmpty() ) Add( loadtmp );
}
Add( g_Conf->CurrentIso );
}
ini.GetConfig().SetRecordDefaults( true );
}
void __evt_fastcall RecentIsoList::OnSettingsLoadSave( void* obj, IniInterface& ini )
{
if( obj == NULL ) return;
((RecentIsoList*)obj)->DoSettingsLoadSave( ini );
}

View File

@ -119,7 +119,7 @@ void __fastcall iopHwWrite8_Page3( u32 addr, mem8_t val )
( val == '\n' && g_pbufi != 0 ) )
{
g_pbuf[g_pbufi] = 0;
Console.WriteLn( ConColor_IOP, g_pbuf );
Console.WriteLn( ConColor_IOP, "%s", g_pbuf );
g_pbufi = 0;
}
else if( val != '\n' )

View File

@ -1844,6 +1844,10 @@
RelativePath="..\..\gui\Plugins.cpp"
>
</File>
<File
RelativePath="..\..\gui\RecentIsoList.cpp"
>
</File>
<File
RelativePath="..\..\RecoverySystem.cpp"
>

View File

@ -31,8 +31,6 @@ namespace Savestate
{
memset( pcm_cache_data, 0, pcm_BlockCount * sizeof(PcmCacheEntry) );
}
static s16 old_state_sBuffer[pcm_DecodedSamplesPerBlock] = {0};
}
struct Savestate::DataBlock