* Re-implemented memorycard ejection (yay!) -- helps avoid memorycard corruption when using savestates on many games (due to them caching memorycard contents).

* Memorycard settings are now applied on-the-fly (can add/remove/disable memory cards in the BIOS browser and it'll act just as if you plugged or unplugged cards on a real PS2)
* Bugfixed memorycard creation dialog; which wasn't creating the memorycards in the right place (oops).

* Removed the CWD option from the first time wizard (was redundant since adding the custom location option).

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@3081 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2010-05-26 01:57:08 +00:00
parent 9708f279e0
commit 24e70bd524
20 changed files with 194 additions and 73 deletions

View File

@ -450,7 +450,7 @@ typedef struct _PS2E_VersionInfo
// PS2E_SessionInfo // PS2E_SessionInfo
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
// This struct is populated by the emulator prior to starting emulation, and is passed to // This struct is populated by the emulator prior to starting emulation, and is passed to
// each plugin via a call to PS2E_PluginLibAPI::EmuStart(). // each plugin via a call to PS2E_PluginLibAPI::EmuOpen().
// //
typedef struct _PS2E_SessionInfo typedef struct _PS2E_SessionInfo
{ {
@ -649,7 +649,7 @@ typedef struct _PS2E_FreezeData
// //
typedef struct _PS2E_ComponentAPI typedef struct _PS2E_ComponentAPI
{ {
// EmuStart // EmuOpen
// This function is called by the emulator when an emulation session is started. The // This function is called by the emulator when an emulation session is started. The
// plugin should take this opportunity to bind itself to the given window handle, open // plugin should take this opportunity to bind itself to the given window handle, open
// necessary audio/video/input devices, etc. // necessary audio/video/input devices, etc.
@ -658,14 +658,14 @@ typedef struct _PS2E_ComponentAPI
// session - provides relevant emulation session information. Provided pointer is // session - provides relevant emulation session information. Provided pointer is
// valid until after the subsequent call to EmuClose() // valid until after the subsequent call to EmuClose()
// //
// Threading: EmuStart is called from the GUI thread. All other emulation threads are // Threading: EmuOpen is called from the GUI thread. All other emulation threads are
// guaranteed to be suspended or closed at the time of this call (no locks required). // guaranteed to be suspended or closed at the time of this call (no locks required).
// //
void (PS2E_CALLBACK* EmuStart)( PS2E_THISPTR thisptr, const PS2E_SessionInfo *session ); void (PS2E_CALLBACK* EmuOpen)( PS2E_THISPTR thisptr, const PS2E_SessionInfo *session );
// EmuClose // EmuClose
// This function is called by the emulator prior to stopping emulation. The window // This function is called by the emulator prior to stopping emulation. The window
// handle specified in EmuStart is guaranteed to be valid at the time EmuClose is called, // handle specified in EmuOpen is guaranteed to be valid at the time EmuClose is called,
// and the plugin should unload/unbind all window dependencies at this time. // and the plugin should unload/unbind all window dependencies at this time.
// //
// Threading: EmuClose is called from the GUI thread. All other emulation threads are // Threading: EmuClose is called from the GUI thread. All other emulation threads are
@ -691,7 +691,7 @@ typedef struct _PS2E_ComponentAPI
// This function should make a complete copy of the plugin's emulation state into the // This function should make a complete copy of the plugin's emulation state into the
// provided dest->Data pointer. The plugin is allowed to reduce the dest->Size value // provided dest->Data pointer. The plugin is allowed to reduce the dest->Size value
// but is not allowed to make it larger. The plugin will only receive calls to Freeze // but is not allowed to make it larger. The plugin will only receive calls to Freeze
// and Thaw while a plugin is in an EmuStart() state. // and Thaw while a plugin is in an EmuOpen() state.
// //
// Parameters: // Parameters:
// dest - a pointer to the Data/Size destination buffer (never NULL). // dest - a pointer to the Data/Size destination buffer (never NULL).
@ -704,7 +704,7 @@ typedef struct _PS2E_ComponentAPI
// Thaw // Thaw
// Plugin should restore a complete emulation state from the given FreezeData. The // Plugin should restore a complete emulation state from the given FreezeData. The
// plugin will only receive calls to Freeze and Thaw while a plugin is in an EmuStart() // plugin will only receive calls to Freeze and Thaw while a plugin is in an EmuOpen()
// state. // state.
// //
// Thread Safety: // Thread Safety:
@ -719,10 +719,10 @@ typedef struct _PS2E_ComponentAPI
// this plugin is grayed out. // this plugin is grayed out.
// //
// All emulation is suspended and the plugin's state is saved to memory prior to this // All emulation is suspended and the plugin's state is saved to memory prior to this
// function being called. Configure is only called outside the context of EmuStart() // function being called. Configure is only called outside the context of EmuOpen()
// (after a call to EmuClose()). // (after a call to EmuClose()).
// //
// Plugin authors should ensure to re-read and re-apply all settings on EmuStart(), // Plugin authors should ensure to re-read and re-apply all settings on EmuOpen(),
// which will ensure that any user changes will be applied immediately. For changes // which will ensure that any user changes will be applied immediately. For changes
// that can be applied without emulation suspension, see/use the GUI extensions for // that can be applied without emulation suspension, see/use the GUI extensions for
// menu and toolbar shortcuts. // menu and toolbar shortcuts.

View File

@ -23,6 +23,8 @@ BEGIN_DECLARE_EVENT_TYPES()
DECLARE_EVENT_TYPE( pxEvt_SynchronousCommand, -1 ) DECLARE_EVENT_TYPE( pxEvt_SynchronousCommand, -1 )
END_DECLARE_EVENT_TYPES() END_DECLARE_EVENT_TYPES()
typedef void FnType_Void();
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
// SynchronousActionState // SynchronousActionState
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------

View File

@ -41,8 +41,6 @@ public:
virtual void OnActionButtonClicked( wxCommandEvent& evt ); virtual void OnActionButtonClicked( wxCommandEvent& evt );
}; };
typedef void FnType_Void();
typedef std::list<wxEvent*> wxEventList; typedef std::list<wxEvent*> wxEventList;
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------

View File

@ -1020,6 +1020,17 @@ bool PluginManager::OpenPlugin_FW()
return true; return true;
} }
bool PluginManager::OpenPlugin_Mcd()
{
ScopedLock lock( m_mtx_PluginStatus );
// [TODO] Fix up and implement PS2E_SessionInfo here!! (the currently NULL parameter)
if( SysPlugins.Mcd )
SysPlugins.Mcd->Base.EmuOpen( (PS2E_THISPTR) SysPlugins.Mcd, NULL );
return true;
}
void PluginManager::Open( PluginsEnum_t pid ) void PluginManager::Open( PluginsEnum_t pid )
{ {
pxAssume( (uint)pid < PluginId_Count ); pxAssume( (uint)pid < PluginId_Count );
@ -1039,6 +1050,7 @@ void PluginManager::Open( PluginsEnum_t pid )
case PluginId_USB: result = OpenPlugin_USB(); break; case PluginId_USB: result = OpenPlugin_USB(); break;
case PluginId_FW: result = OpenPlugin_FW(); break; case PluginId_FW: result = OpenPlugin_FW(); break;
case PluginId_DEV9: result = OpenPlugin_DEV9(); break; case PluginId_DEV9: result = OpenPlugin_DEV9(); break;
jNO_DEFAULT; jNO_DEFAULT;
} }
if( !result ) if( !result )
@ -1068,6 +1080,12 @@ void PluginManager::Open()
if (GSopen2) GetMTGS().WaitForOpen(); if (GSopen2) GetMTGS().WaitForOpen();
if( !AtomicExchange( m_mcdOpen, true ) )
{
DbgCon.Indent().WriteLn( "Opening Memorycards");
OpenPlugin_Mcd();
}
Console.WriteLn( Color_StrongBlue, "Plugins opened successfully." ); Console.WriteLn( Color_StrongBlue, "Plugins opened successfully." );
} }
@ -1120,6 +1138,11 @@ void PluginManager::ClosePlugin_FW()
_generalclose( PluginId_FW ); _generalclose( PluginId_FW );
} }
void PluginManager::ClosePlugin_Mcd()
{
ScopedLock lock( m_mtx_PluginStatus );
if( SysPlugins.Mcd ) SysPlugins.Mcd->Base.EmuClose( (PS2E_THISPTR) SysPlugins.Mcd );
}
void PluginManager::Close( PluginsEnum_t pid ) void PluginManager::Close( PluginsEnum_t pid )
{ {
@ -1139,6 +1162,7 @@ void PluginManager::Close( PluginsEnum_t pid )
case PluginId_USB: ClosePlugin_USB(); break; case PluginId_USB: ClosePlugin_USB(); break;
case PluginId_FW: ClosePlugin_FW(); break; case PluginId_FW: ClosePlugin_FW(); break;
case PluginId_DEV9: ClosePlugin_DEV9(); break; case PluginId_DEV9: ClosePlugin_DEV9(); break;
case PluginId_Mcd: ClosePlugin_Mcd(); break;
jNO_DEFAULT; jNO_DEFAULT;
} }
@ -1156,9 +1180,15 @@ void PluginManager::Close()
DbgCon.WriteLn( Color_StrongBlue, "Closing plugins..." ); DbgCon.WriteLn( Color_StrongBlue, "Closing plugins..." );
if( AtomicExchange( m_mcdOpen, false ) )
{
DbgCon.Indent().WriteLn( "Closing Memorycards");
ClosePlugin_Mcd();
}
for( int i=PluginId_Count-1; i>=0; --i ) for( int i=PluginId_Count-1; i>=0; --i )
Close( tbl_PluginInfo[i].id ); Close( tbl_PluginInfo[i].id );
DbgCon.WriteLn( Color_StrongBlue, "Plugins closed successfully." ); DbgCon.WriteLn( Color_StrongBlue, "Plugins closed successfully." );
} }

View File

@ -217,7 +217,7 @@ public:
void McdRead( uint port, uint slot, u8 *dest, u32 adr, int size ); void McdRead( uint port, uint slot, u8 *dest, u32 adr, int size );
void McdSave( uint port, uint slot, const u8 *src, u32 adr, int size ); void McdSave( uint port, uint slot, const u8 *src, u32 adr, int size );
void McdEraseBlock( uint port, uint slot, u32 adr ); void McdEraseBlock( uint port, uint slot, u32 adr );
u64 McdGetCRC( uint port, uint slot ); u64 McdGetCRC( uint port, uint slot );
friend class PluginManager; friend class PluginManager;
}; };
@ -268,6 +268,9 @@ protected:
wxString m_SettingsFolder; wxString m_SettingsFolder;
Threading::MutexRecursive m_mtx_PluginStatus; Threading::MutexRecursive m_mtx_PluginStatus;
// Lovely hack until the new PS2E API is completed.
volatile u32 m_mcdOpen;
public: // hack until we unsuck plugins... public: // hack until we unsuck plugins...
ScopedPtr<PluginStatus_t> m_info[PluginId_Count]; ScopedPtr<PluginStatus_t> m_info[PluginId_Count];
@ -327,7 +330,8 @@ protected:
virtual bool OpenPlugin_DEV9(); virtual bool OpenPlugin_DEV9();
virtual bool OpenPlugin_USB(); virtual bool OpenPlugin_USB();
virtual bool OpenPlugin_FW(); virtual bool OpenPlugin_FW();
virtual bool OpenPlugin_Mcd();
void _generalclose( PluginsEnum_t pid ); void _generalclose( PluginsEnum_t pid );
virtual void ClosePlugin_GS(); virtual void ClosePlugin_GS();
@ -337,6 +341,7 @@ protected:
virtual void ClosePlugin_DEV9(); virtual void ClosePlugin_DEV9();
virtual void ClosePlugin_USB(); virtual void ClosePlugin_USB();
virtual void ClosePlugin_FW(); virtual void ClosePlugin_FW();
virtual void ClosePlugin_Mcd();
friend class SysMtgsThread; friend class SysMtgsThread;
}; };

View File

@ -26,7 +26,9 @@ static const u8 cardh[4] = { 0xFF, 0xFF, 0x5a, 0x5d };
// Memory Card Specs : Sector size etc. // Memory Card Specs : Sector size etc.
static const mc_command_0x26_tag mc_command_0x26= {'+', 512, 16, 0x4000, 0x52, 0x5A}; static const mc_command_0x26_tag mc_command_0x26= {'+', 512, 16, 0x4000, 0x52, 0x5A};
static int m_PostSavestateCards[2] = { 0, 0 }; // Ejection timeout management belongs in the MemoryCardFile plugin, except the plugin
// interface is not yet complete.
static int m_ForceEjectionTimeout[2];
// SIO Inline'd IRQs : Calls the SIO interrupt handlers directly instead of // SIO Inline'd IRQs : Calls the SIO interrupt handlers directly instead of
// feeding them through the IOP's branch test. (see SIO.H for details) // feeding them through the IOP's branch test. (see SIO.H for details)
@ -88,7 +90,7 @@ static u8 sio_xor( const u8 *buf, uint length )
void sioInit() void sioInit()
{ {
memzero(sio); memzero(sio);
memzero(m_PostSavestateCards); memzero(m_ForceEjectionTimeout);
// Transfer(?) Ready and the Buffer is Empty // Transfer(?) Ready and the Buffer is Empty
sio.StatReg = TX_RDY | TX_EMPTY; sio.StatReg = TX_RDY | TX_EMPTY;
@ -602,7 +604,18 @@ void InitializeSIO(u8 value)
const uint port = sio.GetMemcardIndex(); const uint port = sio.GetMemcardIndex();
const uint slot = sio.activeMemcardSlot[port]; const uint slot = sio.activeMemcardSlot[port];
if( SysPlugins.McdIsPresent( port, slot ) ) // forced ejection logic. Technically belongs in the McdIsPresent handler for
// the plugin, once the memorycard plugin system is completed.
// (ejection is only supported for the default non-multitap cards at this time)
bool forceEject = false;
if( slot == 0 && m_ForceEjectionTimeout[port] )
{
--m_ForceEjectionTimeout[port];
forceEject = true;
}
if( !forceEject && SysPlugins.McdIsPresent( port, slot ) )
{ {
sio2.packet.recvVal1 = 0x1100; sio2.packet.recvVal1 = 0x1100;
PAD_LOG("START MEMCARD [port:%d, slot:%d] - Present", port, slot ); PAD_LOG("START MEMCARD [port:%d, slot:%d] - Present", port, slot );
@ -654,19 +667,29 @@ void SaveStateBase::sioFreeze()
FreezeTag( "sio" ); FreezeTag( "sio" );
Freeze( sio ); Freeze( sio );
// TODO : This stuff should all be moved to the memorycard plugin eventually,
// but that requires adding memorycard plugin to the savestate, and I'm not in
// the mood to do that (let's plan it for 0.9.8) --air
// Note: The Ejection system only works for the default non-multitap MemoryCards
// only. This is because it could become very (very!) slow to do a full CRC check
// on multiple 32 or 64 meg carts. I have chosen to save
if( IsSaving() ) if( IsSaving() )
{ {
for( int port=0; port<2; ++port ) for( uint port=0; port<2; ++port )
//for( uint slot=0; slot<4; ++slot )
{ {
for( int slot=0; slot<4; ++slot ) const int slot = 0; // see above comment about multitap slowness
m_mcdCRCs[port][slot] = SysPlugins.McdGetCRC( port, slot ); m_mcdCRCs[port][slot] = SysPlugins.McdGetCRC( port, slot );
} }
} }
Freeze( m_mcdCRCs ); Freeze( m_mcdCRCs );
if( IsLoading() && EmuConfig.McdEnableEjection ) if( IsLoading() && EmuConfig.McdEnableEjection )
{ {
// Notes: // Notes on the ForceEjectionTimeout:
// * TOTA works with values as low as 20 here. // * TOTA works with values as low as 20 here.
// It "times out" with values around 1800 (forces user to check the memcard // It "times out" with values around 1800 (forces user to check the memcard
// twice to find it). Other games could be different. :| // twice to find it). Other games could be different. :|
@ -680,14 +703,14 @@ void SaveStateBase::sioFreeze()
// ejecting it, the game freezes (which is actually good emulation, but annoying!) // ejecting it, the game freezes (which is actually good emulation, but annoying!)
for( int port=0; port<2; ++port ) for( int port=0; port<2; ++port )
//for( int slot=0; slot<4; ++slot )
{ {
for( int slot=0; slot<4; ++slot ) const int slot = 0; // see above comment about multitap slowness
u64 newCRC = SysPlugins.McdGetCRC( port, slot );
if( newCRC != m_mcdCRCs[port][slot] )
{ {
u64 newCRC = SysPlugins.McdGetCRC( port, slot ); //m_mcdCRCs[port][slot] = newCRC;
if( newCRC != m_mcdCRCs[port][slot] ) m_ForceEjectionTimeout[port] = 128;
{
m_mcdCRCs[port][slot] = newCRC;
}
} }
} }
} }

View File

@ -100,7 +100,7 @@ namespace PathDefs
switch( mode ) switch( mode )
{ {
case DocsFolder_User: return (wxDirName)Path::Combine( wxStandardPaths::Get().GetDocumentsDir(), wxGetApp().GetAppName() ); case DocsFolder_User: return (wxDirName)Path::Combine( wxStandardPaths::Get().GetDocumentsDir(), wxGetApp().GetAppName() );
case DocsFolder_CWD: return (wxDirName)wxGetCwd(); //case DocsFolder_CWD: return (wxDirName)wxGetCwd();
case DocsFolder_Custom: return CustomDocumentsFolder; case DocsFolder_Custom: return CustomDocumentsFolder;
jNO_DEFAULT jNO_DEFAULT
@ -561,7 +561,7 @@ void AppConfig::FolderOptions::LoadSave( IniInterface& ini )
{ {
ApplyDefaults(); ApplyDefaults();
if( DocsFolderMode != DocsFolder_CWD ) //if( DocsFolderMode != DocsFolder_CWD )
{ {
for( int i=0; i<FolderId_COUNT; ++i ) for( int i=0; i<FolderId_COUNT; ++i )
operator[]( (FoldersEnum_t)i ).Normalize(); operator[]( (FoldersEnum_t)i ).Normalize();
@ -719,7 +719,7 @@ void RelocateLogfile()
// //
void AppConfig_OnChangedSettingsFolder( bool overwrite ) void AppConfig_OnChangedSettingsFolder( bool overwrite )
{ {
if( DocsFolderMode != DocsFolder_CWD ) //if( DocsFolderMode != DocsFolder_CWD )
PathDefs::GetDocuments().Mkdir(); PathDefs::GetDocuments().Mkdir();
GetSettingsFolder().Mkdir(); GetSettingsFolder().Mkdir();

View File

@ -25,7 +25,7 @@ enum DocsModeType
DocsFolder_User, DocsFolder_User,
// uses the current working directory for program data // uses the current working directory for program data
DocsFolder_CWD, //DocsFolder_CWD,
// uses a custom location for program data // uses a custom location for program data
DocsFolder_Custom, DocsFolder_Custom,

View File

@ -500,26 +500,29 @@ void SysExecEvent_SaveSinglePlugin::InvokeEvent()
s_DisableGsWindow = true; // keeps the GS window smooth by avoiding closing the window s_DisableGsWindow = true; // keeps the GS window smooth by avoiding closing the window
ScopedCoreThreadPause paused_core; ScopedCoreThreadPause paused_core;
_LoadPluginsImmediate(); //_LoadPluginsImmediate();
ScopedPtr<VmStateBuffer> plugstore; if( CorePlugins.AreLoaded() )
if( CoreThread.HasActiveMachine() )
{ {
Console.WriteLn( Color_Green, L"Suspending single plugin: " + tbl_PluginInfo[m_pid].GetShortname() ); ScopedPtr<VmStateBuffer> plugstore;
memSavingState save( plugstore=new VmStateBuffer(L"StateCopy_SinglePlugin") );
GetCorePlugins().Freeze( m_pid, save );
}
GetCorePlugins().Close( m_pid );
_post_and_wait( paused_core );
if( plugstore ) if( CoreThread.HasActiveMachine() )
{ {
Console.WriteLn( Color_Green, L"Recovering single plugin: " + tbl_PluginInfo[m_pid].GetShortname() ); Console.WriteLn( Color_Green, L"Suspending single plugin: " + tbl_PluginInfo[m_pid].GetShortname() );
memLoadingState load( plugstore ); memSavingState save( plugstore=new VmStateBuffer(L"StateCopy_SinglePlugin") );
GetCorePlugins().Freeze( m_pid, load ); GetCorePlugins().Freeze( m_pid, save );
GetCorePlugins().Close( m_pid ); // hack for stupid GS plugins. }
GetCorePlugins().Close( m_pid );
_post_and_wait( paused_core );
if( plugstore )
{
Console.WriteLn( Color_Green, L"Recovering single plugin: " + tbl_PluginInfo[m_pid].GetShortname() );
memLoadingState load( plugstore );
GetCorePlugins().Freeze( m_pid, load );
GetCorePlugins().Close( m_pid ); // hack for stupid GS plugins.
}
} }
s_DisableGsWindow = false; s_DisableGsWindow = false;

View File

@ -16,6 +16,8 @@
#pragma once #pragma once
#include "System/SysThreads.h" #include "System/SysThreads.h"
#include "pxEventThread.h"
#include "AppCommon.h" #include "AppCommon.h"
#include "AppCorePlugins.h" #include "AppCorePlugins.h"
#include "SaveState.h" #include "SaveState.h"

View File

@ -41,7 +41,7 @@ public:
SysExecEvent_SaveSinglePlugin( PluginsEnum_t pid=PluginId_GS ) SysExecEvent_SaveSinglePlugin( PluginsEnum_t pid=PluginId_GS )
{ {
m_pid = pid; m_pid = pid;
} }
SysExecEvent_SaveSinglePlugin& SetPluginId( PluginsEnum_t pid ) SysExecEvent_SaveSinglePlugin& SetPluginId( PluginsEnum_t pid )

View File

@ -170,13 +170,16 @@ void Dialogs::BaseConfigurationDialog::OnSetSettingsPage( wxCommandEvent& evt )
} }
} }
void Dialogs::BaseConfigurationDialog::SomethingChanged()
{
if( wxWindow* apply = FindWindow( wxID_APPLY ) ) apply->Enable();
}
void Dialogs::BaseConfigurationDialog::OnSomethingChanged( wxCommandEvent& evt ) void Dialogs::BaseConfigurationDialog::OnSomethingChanged( wxCommandEvent& evt )
{ {
evt.Skip(); evt.Skip();
if( (evt.GetId() != wxID_OK) && (evt.GetId() != wxID_CANCEL) && (evt.GetId() != wxID_APPLY) ) if( (evt.GetId() != wxID_OK) && (evt.GetId() != wxID_CANCEL) && (evt.GetId() != wxID_APPLY) )
{ SomethingChanged();
if( wxWindow* apply = FindWindow( wxID_APPLY ) ) apply->Enable();
}
} }

View File

@ -55,6 +55,8 @@ namespace Dialogs
void AddListbook( wxSizer* sizer=NULL ); void AddListbook( wxSizer* sizer=NULL );
void CreateListbook( wxImageList& bookicons ); void CreateListbook( wxImageList& bookicons );
virtual void SomethingChanged();
template< typename T > template< typename T >
void AddPage( const char* label, int iconid ); void AddPage( const char* label, int iconid );
@ -68,8 +70,8 @@ namespace Dialogs
void OnCloseWindow( wxCloseEvent& evt ); void OnCloseWindow( wxCloseEvent& evt );
void OnSetSettingsPage( wxCommandEvent& evt ); void OnSetSettingsPage( wxCommandEvent& evt );
void OnSomethingChanged( wxCommandEvent& evt );
virtual void OnSomethingChanged( wxCommandEvent& evt );
virtual wxString& GetConfSettingsTabName() const=0; virtual wxString& GetConfSettingsTabName() const=0;
}; };

View File

@ -61,9 +61,9 @@ Dialogs::CreateMemoryCardDialog::CreateMemoryCardDialog( wxWindow* parent, uint
if( m_radio_CardSize ) m_radio_CardSize->Realize(); if( m_radio_CardSize ) m_radio_CardSize->Realize();
wxBoxSizer& s_buttons( *new wxBoxSizer(wxHORIZONTAL) ); wxBoxSizer& s_buttons( *new wxBoxSizer(wxHORIZONTAL) );
s_buttons += new wxButton( this, wxID_OK, _("Create") ) | pxProportion(2); s_buttons += new wxButton( this, wxID_OK, _("Create") ) | pxProportion(2);
s_buttons += pxStretchSpacer(3); s_buttons += pxStretchSpacer(3);
s_buttons += new wxButton( this, wxID_CANCEL ) | pxProportion(2); s_buttons += new wxButton( this, wxID_CANCEL ) | pxProportion(2);
wxBoxSizer& s_padding( *new wxBoxSizer(wxVERTICAL) ); wxBoxSizer& s_padding( *new wxBoxSizer(wxVERTICAL) );
@ -73,13 +73,14 @@ Dialogs::CreateMemoryCardDialog::CreateMemoryCardDialog( wxWindow* parent, uint
s_padding += m_filepicker | StdExpand(); s_padding += m_filepicker | StdExpand();
else else
{ {
s_padding += Heading( _( "(new card will be saved to:" ) ); s_padding += Heading( _( "New card will be saved to:" ) );
s_padding += Heading( (m_mcdpath + m_mcdfile).GetFullPath() ); s_padding += Heading( (m_mcdpath + m_mcdfile).GetFullPath() );
} }
s_padding += m_radio_CardSize | StdExpand(); s_padding += m_radio_CardSize | StdExpand();
#ifdef __WXMSW__ #ifdef __WXMSW__
if( m_check_CompressNTFS ) s_padding += m_check_CompressNTFS | StdExpand(); if( m_check_CompressNTFS )
s_padding += m_check_CompressNTFS | StdExpand();
#endif #endif
s_padding += 12; s_padding += 12;
@ -87,8 +88,6 @@ Dialogs::CreateMemoryCardDialog::CreateMemoryCardDialog( wxWindow* parent, uint
*this += s_padding | StdExpand(); *this += s_padding | StdExpand();
//FindItem( wxID_OK )->SetLabel(_("Create"));
Connect( wxID_OK, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CreateMemoryCardDialog::OnOk_Click ) ); Connect( wxID_OK, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CreateMemoryCardDialog::OnOk_Click ) );
//Connect( wxID_APPLY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CreateMemoryCardDialog::OnApply_Click ) ); //Connect( wxID_APPLY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( CreateMemoryCardDialog::OnApply_Click ) );
} }
@ -126,7 +125,7 @@ static bool CreateIt( const wxString& mcdFile, uint sizeInMB )
void Dialogs::CreateMemoryCardDialog::OnOk_Click( wxCommandEvent& evt ) void Dialogs::CreateMemoryCardDialog::OnOk_Click( wxCommandEvent& evt )
{ {
if( !CreateIt( if( !CreateIt(
m_filepicker ? m_filepicker->GetPath() : m_mcdfile, m_filepicker ? m_filepicker->GetPath() : (m_mcdpath + m_mcdfile).GetFullPath(),
m_radio_CardSize ? m_radio_CardSize->SelectedItem().SomeInt : 8 m_radio_CardSize ? m_radio_CardSize->SelectedItem().SomeInt : 8
) ) ) )
{ {

View File

@ -172,6 +172,9 @@ Dialogs::McdConfigDialog::McdConfigDialog( wxWindow* parent )
//AddPage<McdConfigPanel_Toggles> ( wxLt("Settings"), cfgid.MemoryCard ); //AddPage<McdConfigPanel_Toggles> ( wxLt("Settings"), cfgid.MemoryCard );
//AddPage<McdConfigPanel_Standard> ( wxLt("Slots 1/2"), cfgid.MemoryCard ); //AddPage<McdConfigPanel_Standard> ( wxLt("Slots 1/2"), cfgid.MemoryCard );
*this += Heading(_("Drag items in the list over other items to swap or copy MemoryCards."));
*this += StdPadding;
*this += m_panel_mcdlist | StdExpand(); *this += m_panel_mcdlist | StdExpand();
//*this += StdPadding; //*this += StdPadding;
*this += new wxStaticLine( this ) | StdExpand(); *this += new wxStaticLine( this ) | StdExpand();

View File

@ -58,6 +58,9 @@ public:
void Lock(); void Lock();
void Unlock(); void Unlock();
void Open();
void Close();
s32 IsPresent ( uint slot ); s32 IsPresent ( uint slot );
s32 Read ( uint slot, u8 *dest, u32 adr, int size ); s32 Read ( uint slot, u8 *dest, u32 adr, int size );
s32 Save ( uint slot, const u8 *src, u32 adr, int size ); s32 Save ( uint slot, const u8 *src, u32 adr, int size );
@ -132,17 +135,44 @@ wxString FileMcd_GetDefaultName(uint slot)
FileMemoryCard::FileMemoryCard() FileMemoryCard::FileMemoryCard()
{ {
memset8<0xff>( m_effeffs ); memset8<0xff>( m_effeffs );
}
void FileMemoryCard::Open()
{
for( int slot=0; slot<8; ++slot ) for( int slot=0; slot<8; ++slot )
{ {
if( !g_Conf->Mcd[slot].Enabled || g_Conf->Mcd[slot].Filename.GetFullName().IsEmpty() ) continue; if( FileMcd_IsMultitapSlot(slot) )
{
if( !EmuConfig.MultitapPort0_Enabled && (FileMcd_GetMtapPort(slot) == 0) ) continue;
if( !EmuConfig.MultitapPort1_Enabled && (FileMcd_GetMtapPort(slot) == 1) ) continue;
}
wxFileName fname( g_Conf->FullpathToMcd( slot ) ); wxFileName fname( g_Conf->FullpathToMcd( slot ) );
wxString str( fname.GetFullPath() ); wxString str( fname.GetFullPath() );
bool cont = false;
if( fname.GetFullName().IsEmpty() )
{
str = L"[empty filename]";
cont = true;
}
if( !g_Conf->Mcd[slot].Enabled )
{
str = L"[disabled]";
cont = true;
}
Console.WriteLn( cont ? Color_Gray : Color_Green, L"McdSlot %u: " + str, slot );
if( cont ) continue;
const wxULongLong fsz = fname.GetSize(); const wxULongLong fsz = fname.GetSize();
if( (fsz == 0) || (fsz == wxInvalidSize) ) if( (fsz == 0) || (fsz == wxInvalidSize) )
{ {
// FIXME : Ideally this should prompt the user for the size of the
// memorycard file they would like to create, instead of trying to
// create one automatically.
if( !Create( str, 8 ) ) if( !Create( str, 8 ) )
{ {
Msgbox::Alert( Msgbox::Alert(
@ -153,7 +183,7 @@ FileMemoryCard::FileMemoryCard()
} }
// [TODO] : Add memcard size detection and report it to the console log. // [TODO] : Add memcard size detection and report it to the console log.
// (8MB, 256Mb, whatever) // (8MB, 256Mb, formatted, unformatted, etc ...)
#ifdef __WXMSW__ #ifdef __WXMSW__
NTFS_CompressFile( str, g_Conf->McdCompressNTFS ); NTFS_CompressFile( str, g_Conf->McdCompressNTFS );
@ -171,6 +201,12 @@ FileMemoryCard::FileMemoryCard()
} }
} }
void FileMemoryCard::Close()
{
for( int slot=0; slot<8; ++slot )
m_file[slot].Close();
}
// Returns FALSE if the seek failed (is outside the bounds of the file). // Returns FALSE if the seek failed (is outside the bounds of the file).
bool FileMemoryCard::Seek( wxFFile& f, u32 adr ) bool FileMemoryCard::Seek( wxFFile& f, u32 adr )
{ {
@ -308,6 +344,16 @@ uint FileMcd_ConvertToSlot( uint port, uint slot )
return slot + 4; // multitap 2 return slot + 4; // multitap 2
} }
static void PS2E_CALLBACK FileMcd_EmuOpen( PS2E_THISPTR thisptr, const PS2E_SessionInfo *session )
{
thisptr->impl.Open();
}
static void PS2E_CALLBACK FileMcd_EmuClose( PS2E_THISPTR thisptr )
{
thisptr->impl.Close();
}
static s32 PS2E_CALLBACK FileMcd_IsPresent( PS2E_THISPTR thisptr, uint port, uint slot ) static s32 PS2E_CALLBACK FileMcd_IsPresent( PS2E_THISPTR thisptr, uint port, uint slot )
{ {
return thisptr->impl.IsPresent( FileMcd_ConvertToSlot( port, slot ) ); return thisptr->impl.IsPresent( FileMcd_ConvertToSlot( port, slot ) );
@ -337,6 +383,9 @@ Component_FileMcd::Component_FileMcd()
{ {
memzero( api ); memzero( api );
api.Base.EmuOpen = FileMcd_EmuOpen;
api.Base.EmuClose = FileMcd_EmuClose;
api.McdIsPresent = FileMcd_IsPresent; api.McdIsPresent = FileMcd_IsPresent;
api.McdRead = FileMcd_Read; api.McdRead = FileMcd_Read;
api.McdSave = FileMcd_Save; api.McdSave = FileMcd_Save;

View File

@ -69,6 +69,7 @@ void Panels::BaseSelectorPanel::RefreshSelections()
void Panels::BaseSelectorPanel::OnRefreshSelections( wxCommandEvent& evt ) void Panels::BaseSelectorPanel::OnRefreshSelections( wxCommandEvent& evt )
{ {
evt.Skip();
RefreshSelections(); RefreshSelections();
} }
@ -104,7 +105,7 @@ Panels::BiosSelectorPanel::BiosSelectorPanel( wxWindow* parent, int idealWidth )
*this += refreshButton | pxBorder(wxLEFT, StdPadding); *this += refreshButton | pxBorder(wxLEFT, StdPadding);
*this += 8; *this += 8;
*this += m_FolderPicker | StdExpand(); *this += m_FolderPicker | StdExpand();
Connect( refreshButton->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(BiosSelectorPanel::OnRefreshSelections) ); Connect( refreshButton->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(BiosSelectorPanel::OnRefreshSelections) );
} }

View File

@ -14,9 +14,11 @@
*/ */
#include "PrecompiledHeader.h" #include "PrecompiledHeader.h"
#include "AppCoreThread.h"
#include "System.h"
#include "ConfigurationPanels.h" #include "ConfigurationPanels.h"
#include "MemoryCardPanels.h" #include "MemoryCardPanels.h"
#include "System.h"
#include <wx/filepicker.h> #include <wx/filepicker.h>
#include <wx/ffile.h> #include <wx/ffile.h>
@ -490,7 +492,10 @@ void Panels::MemoryCardListPanel_Simple::UpdateUI()
void Panels::MemoryCardListPanel_Simple::Apply() void Panels::MemoryCardListPanel_Simple::Apply()
{ {
//_parent::Apply(); //_parent::Apply();
ScopedCoreThreadClose closed_core;
closed_core.AllowResume();
for( uint slot=0; slot<8; ++slot ) for( uint slot=0; slot<8; ++slot )
{ {
g_Conf->Mcd[slot].Enabled = m_Cards[slot].IsEnabled && m_Cards[slot].IsPresent; g_Conf->Mcd[slot].Enabled = m_Cards[slot].IsEnabled && m_Cards[slot].IsPresent;
@ -581,6 +586,8 @@ void Panels::MemoryCardListPanel_Simple::OnCreateCard(wxCommandEvent& evt)
void Panels::MemoryCardListPanel_Simple::OnMountCard(wxCommandEvent& evt) void Panels::MemoryCardListPanel_Simple::OnMountCard(wxCommandEvent& evt)
{ {
evt.Skip();
const int sel = m_listview->GetFirstSelected(); const int sel = m_listview->GetFirstSelected();
if( wxNOT_FOUND == sel ) return; if( wxNOT_FOUND == sel ) return;
const uint slot = sel; const uint slot = sel;

View File

@ -51,12 +51,6 @@ Panels::DocsFolderPickerPanel::DocsFolderPickerPanel( wxWindow* parent, bool isF
_("Location: ") + wxStandardPaths::Get().GetDocumentsDir() _("Location: ") + wxStandardPaths::Get().GetDocumentsDir()
), ),
RadioPanelItem(
_("Current working folder (intended for developer use only)"),
_("Location: ") + wxGetCwd(),
_("This setting requires administration privileges from your operating system.")
),
RadioPanelItem( RadioPanelItem(
_("Custom folder:"), _("Custom folder:"),
wxEmptyString, wxEmptyString,

View File

@ -672,7 +672,7 @@ void Panels::PluginSelectorPanel::OnEnumComplete( wxCommandEvent& evt )
else if( m_ComponentBoxes->Get(pid).GetSelection() == wxNOT_FOUND ) else if( m_ComponentBoxes->Get(pid).GetSelection() == wxNOT_FOUND )
{ {
m_ComponentBoxes->Get(pid).SetSelection( 0 ); m_ComponentBoxes->Get(pid).SetSelection( 0 );
m_ComponentBoxes->GetConfigButton(pid).Enable( CorePlugins.AreLoaded() ); m_ComponentBoxes->GetConfigButton(pid).Enable( !CorePlugins.AreLoaded() );
} }
} while( ++pi, pi->shortname != NULL ); } while( ++pi, pi->shortname != NULL );