Fixed a bug in BiosTools.cpp that caused Bios-Not-Found errors.

MemoryCard / Multitap Renovations:
 * Memorycards should now support multitap (somewhat untested)
 * Implemented a memorycard plugin interface, using the new API defined in PluginCallbacks.h (still prelim and hackish)
 * Memorycard settings are saved to ini!
 * Multitap is now controlled by PCSX2 instead of the pad plugin (which means no multitap until we implement the gui toggles to enable it)

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1817 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2009-09-13 17:11:35 +00:00
parent f72c913c4b
commit 4fbc2c26aa
25 changed files with 1063 additions and 724 deletions

View File

@ -17,9 +17,41 @@
#ifndef __PLUGINCALLBACKS_H__
#define __PLUGINCALLBACKS_H__
#include "x86caps.h" // fixme: x86caps.h needs to be implemented from the pcsx2 emitter cpucaps structs
// --------------------------------------------------------------------------------------
// <<< Important Notes to Plugin Authors >>>
// --------------------------------------------------------------------------------------
// * Exceptions thrown by plugins may not be handled correctly if allowed to escape the
// scope of the plugin, and could result in odd crashes. For C++ plugins this means
// ensuring that any code that uses 'new' or STL containers (string, list, vector, etc)
// are contained within a try{} block, since the STL can throw std::bad_alloc.
//
// * Many callbacks are optional, and have been marked as such. Any optional callback can be
// left NULL. Any callback not marked optional and left NULL will cause the emulator to
// invalidate the plugin on either enumeration or initialization.
//////////////////////////////////////////////////////////////////////////////////////////
// --------------------------------------------------------------------------------------
// <<< Important Notes to All Developers >>>
// --------------------------------------------------------------------------------------
// * Callback APIs cannot involve LIB-C or STL objects (such as FILE or std::string). The
// internal layout of these structures can vary between versions of GLIB-C / MSVCRT.
//
// * Callback APIs cannot alloc/free memory across dynamic library boundaries. An object
// allocated by a plugin must be freed by that plugin.
//
// * C++ exception handling cannot be used by either plugin callbacks or emulator callbacks.
// This includes the Console callbacks, for example, since the nature of C++ RTTI could
// cause a C++ plugin wth its own catch handlers to catch exceptions of mismatched types
// from the emulator.
//
#ifndef BOOL
typedef int BOOL;
#endif
// --------------------------------------------------------------------------------------
// PS2E_HWND - OS-independent window handle
// --------------------------------------------------------------------------------------
// HWND is our only operating system dependent type. For it to be defined as accurately
// as possible, this header file needs to be included after whatever window/GUI platform
// headers you need (wxWidgets, Windows.h, GTK, etc).
@ -30,24 +62,19 @@
// platform available defines when they exist.
//
#if defined( _WX_DEFS_H_ )
typedef WXWidget PS2E_HWND;
typedef WXWidget PS2E_HWND;
#elif defined( _WINDEF_ )
// For Windows let's use HWND, since it has some type strictness applied to it.
typedef HWND PS2E_HWND;
// For Windows let's use HWND, since it has some type strictness applied to it.
typedef HWND PS2E_HWND;
#else
// Unsupported platform... use void* as a best guess. Should work fine for almost
// any GUI platform, and certainly works for any currently supported one.
typedef void* PS2E_HWND;
// Unsupported platform... use void* as a best guess. Should work fine for almost
// any GUI platform, and certainly works for any currently supported one.
typedef void* PS2E_HWND;
#endif
//////////////////////////////////////////////////////////////////////////////////////////
// PS2E_THISPTR - (ps2 component scope 'this' object pointer type)
//
// --------------------------------------------------------------------------------------
// PS2E_THISPTR - (ps2 component scope 'this' object pointer type)
// --------------------------------------------------------------------------------------
// This macro provides C++ plugin authors with a reasonably friendly way to automatically
// typecast the session objects for your plugin to your internal type. Just #define
// PS2E_THISPTR to your internal structure type prior to loading this header file, and all
@ -81,12 +108,13 @@ typedef void* PS2E_HWND;
extern "C" {
#endif
//////////////////////////////////////////////////////////////////////////////////////////
// Plugin Type / Version Enumerations
//
// ------------------------------------------------------------------------------------
// Plugin Type / Version Enumerations
// ------------------------------------------------------------------------------------
enum PS2E_ComponentTypes
{
PS2E_TYPE_GS=0,
PS2E_TYPE_GS = 0,
PS2E_TYPE_PAD,
PS2E_TYPE_SPU2,
PS2E_TYPE_CDVD,
@ -94,7 +122,7 @@ enum PS2E_ComponentTypes
PS2E_TYPE_USB,
PS2E_TYPE_FW,
PS2E_TYPE_SIO,
PS2E_TYPE_Mcd,
};
enum PluginLibVersion
@ -122,20 +150,21 @@ enum OSDIconTypes
OSD_Icon_ReserveEnd = 0x1000
};
/////////////////////////////////////////////////////////////////////////////////////////
// PS2E_VersionInfo
//
//-
// --------------------------------------------------------------------------------------
// PS2E_VersionInfo
// --------------------------------------------------------------------------------------
// This structure is populated by the plugin via the PS2E_PluginLibAPI::GetVersion()
// callback. Specify -1 for any Version or Revision to disable/ignore it. The emulator
// will not factor that info into the display name of the plugin.
//
typedef struct PS2E_VersionInfo
typedef struct _PS2E_VersionInfo
{
// Low/Mid/High versions combine to form a number in the format of: 2.3.1
// ... where 2 is the high version, 3 mid, and 1 low.
s16 VersionLow;
s16 VersionMid;
s16 VersionHigh;
s16 VersionMid;
s16 VersionLow;
// Revision typically refers a revision control system (such as SVN). When displayed
// by the emulator it will have an 'r' prefixed before it.
@ -143,35 +172,9 @@ typedef struct PS2E_VersionInfo
} PS2E_VersionInfo;
//////////////////////////////////////////////////////////////////////////////////////////
// PS2E_MachineInfo
//
// This struct is populated by the emulator when the application is started, and is passed
// to plugins via PS2E_PluginLibAPI::Init(). Plugins may optionally use this information
// to determine compatibility or to select which special CPU-oriented builds and/or functions
// to bind to callbacks.
//
// Fields marked as Optional can either be NULL or -1, denoting the field is unused/ignored.
//
typedef struct _PS2E_MachineInfo
{
const x86CPU_INFO* x86caps;
// brief name of the emulator (ex: "PCSX2") [required]
// Depending on the design of the emulator, this string may optionally include version
// information, however that is not recommended since it can inhibit backward support.
const char* EmuName;
s16 EmuVersionLow; // [optional]
s16 EmuVersionMid; // [optional]
s16 EmuVersionHigh; // [optional]
s32 EmuRevision; // emulator's revision number. [optional]
} PS2E_MachineInfo;
//////////////////////////////////////////////////////////////////////////////////////////
// PS2E_SessionInfo
//
// --------------------------------------------------------------------------------------
// PS2E_SessionInfo
// --------------------------------------------------------------------------------------
// This struct is populated by the emulator prior to starting emulation, and is passed to
// each plugin via a call to PS2E_PluginLibAPI::EmuStart().
//
@ -191,51 +194,81 @@ typedef struct _PS2E_SessionInfo
} PS2E_SessionInfo;
/////////////////////////////////////////////////////////////////////////////////////////
// --------------------------------------------------------------------------------------
// PS2E_EmulatorInfo
// --------------------------------------------------------------------------------------
// This struct is populated by the emulator when the application is started, and is passed
// to plugins via PS2E_InitAPI. Plugins may optionally use this information to determine
// compatibility or to select which special CPU-oriented builds and/or functions to bind
// to callbacks.
//
typedef struct _PS2E_CustomSettingsAPI
// The GetInt/GetBoolean/GetString/etc methods Provide an interface through which a plugin
// can retrieve special emulator-specific settings and information, or fetch options straight
// from the emulator's ini file itself. These are intended for advanced plugin/emu binding
// only, and should generally be accompanied with the appropriate version/name checks.
//
// Emulators may implement this as a direct match to the emu's ini file/registry contents
// (recommended), or may provide additional and/or alternative custom strings. Direct
// ini.registry relationships are preferred since those are easy for a plugin author to
// reference without documentation.
//
typedef struct _PS2E_EmulatorInfo
{
int (PS2E_CALLBACK* GetInt)( const char* name );
// brief name of the emulator (ex: "PCSX2") [required]
// Depending on the design of the emulator, this string may optionally include version
// information, however that is not recommended since it can inhibit backward support.
const char* EmuName;
// Version information. All fields besides the emulator's name are optional.
struct _PS2E_VersionInfo EmuVersion;
// Number of Physical Cores, as detected by the emulator.
// This should always match the real # of cores supported by hardware.
int PhysicalCores;
// Number of Logical Cores, as detected and/or managed by the emulator.
// This is not necessarily a reflection of real hardware capabilities. The emu reserves
// the right to report this value as it deems appropriate, in management of threading
// resources.
int LogicalCores;
// GetInt
// Self-explanatory.
//
// Returns:
// 0 - Value was retrieved successfully.
// 1 - Unknown value. Contents of dest are unchanged.
BOOL (PS2E_CALLBACK* GetInt)( const char* name, int* dest );
// GetBoolean
// Should return either 1 (true) or 0 (false). Returning any non-zero value for true
// probably "works" but is not recommended, since C/C++ standard specifically defines
// the result of bool->int conversions as a 0 or 1 result.
int (PS2E_CALLBACK* GetBoolean)( const char* name );
// Assigns *dest either 1 (true) or 0 (false). Note to Emulators: Returning any non-
// zero value for true probably "works" but is not recommended, since C/C++ standard
// specifically defines the result of bool->int conversions as a 0 or 1 result.
//
// Returns:
// 0 - Value was retrieved successfully.
// 1 - Unknown value. Contents of dest are unchanged.
BOOL (PS2E_CALLBACK* GetBoolean)( const char* name, BOOL* result );
// GetString
// Copies an ASCII-Z string into the dest pointer, to max length allowed. The result
// is always safely zero-terminated (none of that snprintf crap where you have to
// zero-terminate yourself >_<).
//
int (PS2E_CALLBACK* GetString)( const char* name, char* dest, int maxlen );
// Returns:
// 0 - Value was retrieved successfully.
// 1 - Unknown value. Contents of dest are unchanged.
BOOL (PS2E_CALLBACK* GetString)( const char* name, char* dest, int maxlen );
// GetStringAlloc
// Provides an alternative to GetString, that can rerieve strings of arbitrary length.
// The plugin must provide a valid allocator callback, which takes a sice parameter and
// Provides an alternative to GetString, that can retrieve strings of arbitrary length.
// The plugin must provide a valid allocator callback, which takes a size parameter and
// returns a pointer to an allocation large enough to hold the size.
//
// It is then the responsibility of the plugin to free the allocated pointer when it
// is done with it.
//
char* (PS2E_CALLBACK* GetStringAlloc)( const char* name, void* (*allocator)(int size) );
} PS2E_CustomSettingsAPI;
/////////////////////////////////////////////////////////////////////////////////////////
// PS2E_EmulatorAPI
//
// These functions are provided to the PS2 plugins by the emulator. Plugins may call these
// functions to perform operations or retrieve data.
//
typedef struct _PS2E_EmulatorAPI
{
// TODO : Create the ConsoleLogger class.
// Provides a set of basic console functions for writing text to the emulator's
// console. Some emulators may not support a console, in which case these functions
// will be NOPs. For plain and simple to-disk logging, plugins should create and use
// their own logging facilities.
ConsoleLogger Console;
char* (PS2E_CALLBACK* GetStringAlloc)( const char* name, void* (PS2E_CALLBACK *allocator)(int size) );
// OSD_WriteLn
// This function allows the plugin to post messages to the emulator's On-Screen Display.
@ -255,26 +288,22 @@ typedef struct _PS2E_EmulatorAPI
// silently ignore unrecognized icon identifiers, thus retaining cross-compat.
//
// msg - string message displayed to the user.
//
void (PS2E_CALLBACK* OSD_WriteLn)( int icon, const char* msg );
// CustomSettings
// Provides an interface through which a plugin can retrieve custom setting values straight
// from the emulator's ini file itself; intended for advanced plugin/emu binding only, and
// should generally be accompanied with the appropriate version/name checks.
//
// Emulators may implement this as a direct match to the emu's ini file/registry contents
// (recommended), or may provide additional and/or alternative custom strings. Direct
// ini.registry relationships are preferred since those are easy for a plugin author to
// reference without documentation.
//
PS2E_CustomSettingsAPI CustomSettings;
} PS2E_EmulatorAPI;
// TODO : Create the ConsoleLogger class.
// Provides a set of basic console functions for writing text to the emulator's
// console. Some emulators may not support a console, in which case these functions
// will be NOPs. For plain and simple to-disk logging, plugins should create and use
// their own logging facilities.
//ConsoleLogger Console;
} PS2E_EmulatorInfo;
//////////////////////////////////////////////////////////////////////////////////////////
// PS2E_FreezeData
//
// --------------------------------------------------------------------------------------
// PS2E_FreezeData
// --------------------------------------------------------------------------------------
// Structure used to pass savestate info between emulator and plugin.
//
typedef struct _PS2E_FreezeData
@ -285,9 +314,9 @@ typedef struct _PS2E_FreezeData
} PS2E_FreezeData;
//////////////////////////////////////////////////////////////////////////////////////////
// PS2E_ComponentAPI
//
// --------------------------------------------------------------------------------------
// PS2E_ComponentAPI
// --------------------------------------------------------------------------------------
// The PluginTypeAPI is provided for every PS2 component plugin (see PS2E_ComponentTypes
// enumeration). For typical dlls which only provide one plugin type of functionality,
// the plugin only needs one instance of this struct. For multi-type plugins, for example
@ -382,15 +411,39 @@ typedef struct _PS2E_ComponentAPI
// needed).
void (PS2E_CALLBACK* Configure)( PS2E_THISPTR thisptr );
// GetLastError
// This is an optional method with allows the emulator to retrieve extended formatted
// error information about a recent failed plugin call. If implemented by the plugin,
// it should store message information in it's PS2E_THISPTR allocation, and free the
// string buffers when the plugin's instance is deleted.
//
// The plugin is allowed to return NULL for either msg_diag or msg_user (or both).
// Returned pointers should be static global arrays, and must be NULL terminated. If
// only one message is provided, it will be used for both console log and popup.
//
// Parameters:
// msg_diag - diagnostic message, which is english only and typically intended for
// console or disk logging.
//
// msg_user - optional translated user message, which is displayed as a popup to explain
// to the user why the plugin failed to initialize.
//
// Thread safety:
// * Thread Affinity: none. May be called from any thread.
// * Interlocking: Instance. All calls from the emu are fully interlocked against
// the plugin instance.
//
void (PS2E_CALLBACK* GetLastError)( PS2E_THISPTR thisptr, char* const* msg_diag, wchar_t* const* msg_user );
// Reserved area at the end of the structure, for future API expansion.
void* reserved[16];
void* reserved[8];
} PS2E_ComponentAPI;
/////////////////////////////////////////////////////////////////////////////////////////
// PS2E_LibraryAPI
//
// --------------------------------------------------------------------------------------
// PS2E_LibraryAPI
// --------------------------------------------------------------------------------------
// The LibraryAPI is an overall library-scope set of functions that perform basic Init,
// Shutdown, and global configuration operations.
//
@ -450,11 +503,7 @@ typedef struct _PS2E_LibraryAPI
// have provisions in its interface to allow for the forced disabling of extended CPU cap-
// abilities, for testing purposes.
//
// Exceptions:
// C++ Plugins may alternately use exception handling to return more detailed
// information on why the plugin failed it's availability test. [TODO]
//
s32 (PS2E_CALLBACK* Test)( u32 component, const PS2E_MachineInfo* xinfo );
BOOL (PS2E_CALLBACK* Test)( u32 component, const PS2E_EmulatorInfo* xinfo );
// NewComponentInstance
// The emulator calls this function to fetch the API for the requested component.
@ -477,9 +526,9 @@ typedef struct _PS2E_LibraryAPI
// dest - structure to fill with plugin function implementations. Dest should
// be manually typecast by the plugin to match the requested component.
//
// Exceptions:
// C++ Plugins may alternately use exception handling to return more detailed
// information on why the plugin failed it's availability test. [TODO]
// OnError:
// Plugins may optionally prepare more detailed information on why the plugin failed
// it's availability test which the emu can request via GetLastError.
//
PS2E_THISPTR (PS2E_CALLBACK* NewComponentInstance)( u32 component );
@ -518,9 +567,9 @@ typedef struct _PS2E_LibraryAPI
} PS2E_LibraryAPI;
//////////////////////////////////////////////////////////////////////////////////////////
// PS2E_Image
//
// --------------------------------------------------------------------------------------
// PS2E_Image
// --------------------------------------------------------------------------------------
// Simple RGBA image data container, for passing surface textures to the GS plugin, and
// for receiving snapshots from the GS plugin.
//
@ -528,15 +577,15 @@ typedef struct _PS2E_LibraryAPI
//
typedef struct _PS2E_Image
{
u32 width
u32 width;
u32 height;
u8* data; // RGBA data. top to bottom.
} PS2E_Image;
//////////////////////////////////////////////////////////////////////////////////////////
// PS2E_ComponentAPI_GS
//
// --------------------------------------------------------------------------------------
// PS2E_ComponentAPI_GS
// --------------------------------------------------------------------------------------
// Thread Safety:
// All GS callbacks are issued from the GS thread only, and are always called synchronously
// with all other component API functions. No locks are needed, and DirectX-based GS
@ -563,7 +612,10 @@ typedef struct _PS2E_ComponentAPI_GS
// The GS plugin is to save the current frame into the given target image. This
// function is always called immediately after a GSvsync(), ensuring that the current
// framebuffer is safely intact for capture.
void (PS2E_CALLBACK* TakeSnapshot)( PS2E_THISPTR thisptr, PS2E_Image* dest );
//
// Returns TRUE if the snapshot succeeded, or FALSE if it failed (contents of dest
// are considered indeterminate and will be ignored by the emu).
BOOL (PS2E_CALLBACK* TakeSnapshot)( PS2E_THISPTR thisptr, PS2E_Image* dest );
// OSD_SetTexture
// Uploads a new OSD texture to the GS. Display of the OSD should be performed at
@ -581,9 +633,18 @@ typedef struct _PS2E_ComponentAPI_GS
// honor the fade value of 0.0 (OSD is not displayed).
void (PS2E_CALLBACK* OSD_SetAlpha)( PS2E_THISPTR thisptr, float alphaOverall, float alphaFade );
// OSD_SetPosition
// Self-explanatory.
void (PS2E_CALLBACK* OSD_SetPosition)( PS2E_THISPTR thisptr, int xpos, int ypos );
void (PS2E_CALLBACK* GSvsync)(int field);
// GSvsync
//
// Returns FALSE if the plugin encountered a critical error while updating the display;
// indicating a device or emulation failure that should terminate the current emulation.
// (if any critical errors accumulated during GStransferTags or GStransferImage, they
// should also be handled here by returning FALSE)
//
BOOL (PS2E_CALLBACK* GSvsync)(int field);
//
//
@ -594,6 +655,9 @@ typedef struct _PS2E_ComponentAPI_GS
// internally by the emulator in a thread-safe manner -- the GS plugin can safely
// ignore the tags (and there is no guarantee the emulator will even bother to
// pass the tags onto the GS).
//
// Returns FALSE if the plugin encountered a critical error while setting texture;
// indicating a device failure.
void (PS2E_CALLBACK* GStransferTags)(u128 *pMem, int tagcnt);
// GStransferPackedTag
@ -605,35 +669,130 @@ typedef struct _PS2E_ComponentAPI_GS
// GStransferImage
// Uploads GIFtag image data.
//
// fixme: Make sure this is designed sufficiently to account for emulator-side texture
// caching.
void (PS2E_CALLBACK* GStransferImage)(u128 *pMem, u32 len_qwc);
void* reserved[8];
} PS2E_ComponentAPI_GS;
// PS2E_InitAPI
// --------------------------------------------------------------------------------------
// PS2E_ComponentAPI_Mcd
// --------------------------------------------------------------------------------------
// Thread Safety:
// * Thread affinity is not guaranteed. Calls may be made from either the main emu thread
// or an IOP child thread (if the emulator uses one).
//
// * No locking required: All calls to the memory cards are interlocked by the emulator.
//
typedef struct _PS2E_ComponentAPI_Mcd
{
// Base Component API (inherited structure)
struct _PS2E_ComponentAPI Base;
// McdIsPresent
// Called by the emulator to detect the availability of a memory card. This function
// will be called frequently -- essentially whenever the SIO port for the memory card
// has its status polled - so its overhead should be minimal when possible.
//
// Returns:
// 0 if the card is not available, or 1 if it is available.
//
// Exceptions:
// None. This function should not throw.
//
BOOL (PS2E_CALLBACK* McdIsPresent)( PS2E_THISPTR thisptr, uint port, uint slot );
// McdRead
// Requests that a block of data be loaded from the memorycard into the specified dest
// buffer (which is allocated by the caller). Bytes read should match the requested
// size. Reads *must* be performed synchronously (function cannot return until the
// read op has finished).
//
// Returns:
// 0 on failure, and 1 on success. Emulator may use GetLastError to retrieve additional
// information for logging or displaying to the user.
//
BOOL (PS2E_CALLBACK* McdRead)( PS2E_THISPTR thisptr, uint port, uint slot, u8 *dest, u32 adr, int size );
// McdSave
// Saves the provided block of data to the memorycard at the specified seek address.
// Writes *must* be performed synchronously (function cannot return until the write op
// has finished). Write cache flushing is optional.
//
// Returns:
// 0 on failure, and 1 on success. Emulator may use GetLastError to retrieve additional
// information for logging or displaying to the user.
//
BOOL (PS2E_CALLBACK* McdSave)( PS2E_THISPTR thisptr, uint port, uint slot, const u8 *src, u32 adr, int size );
// McdErase
// Saves "cleared" data to the memorycard at the specified seek address. Cleared data
// is a series of 0xff values (all bits set to 1).
// Writes *must* be performed synchronously (function cannot return until the write op
// has finished). Write cache flushing is optional.
//
// Returns:
// 0 on failure, and 1 on success. Emulator may use GetLastError to retrieve additional
// information for logging or displaying to the user.
//
BOOL (PS2E_CALLBACK* McdEraseBlock)( PS2E_THISPTR thisptr, uint port, uint slot, u32 adr );
u64 (PS2E_CALLBACK* McdGetCRC)( PS2E_THISPTR thisptr, uint port, uint slot );
void* reserved[8];
} PS2E_ComponentAPI_Mcd;
// --------------------------------------------------------------------------------------
// PS2E_InitAPI
// --------------------------------------------------------------------------------------
// Called by the emulator when the plugin is loaded into memory. The emulator uses the
// presence of this function to detect PS2E-v2 plugin API, and will direct all subsequent
// calls through the returned LibraryAPI. The function is allowed to return NULL if the
// emulator's version information or machine capabilities are insufficient for the
// plugin's needs.
//
// Note: It is recommended that plugins query machine capabilities from the emulator rather
// than the operating system or CPUID directly, since it allows the emulator the option of
// overriding the reported capabilities, for diagnostic purposes. (such behavior is not
// required, however)
//
// This function is called *once* for the duration of a loaded plugin.
//
// Parameters:
// xinfo - Machine info and capabilities, usable for cpu detection. This pointer is
// valid for the duration of the plugin's tenure in memory.
//
// Returns:
// A pointer to a static structure that contains the API for this plugin, or NULL if
// the plugin explicitly does not support the emulator version.
// the plugin explicitly does not support the emulator version or machine specs.
//
// Exceptions:
// C++ Plugins can use exceptions instead of NULL to return additional information on
// why the plugin failed to init the API. [TODO]
// OnError:
// Plugins may optionally prepare more detailed information on why the plugin failed
// it's availability test which the emu can request via PS2E_GetLastError.
//
typedef const PS2E_LibraryAPI* (PS2E_CALLBACK* _PS2E_InitAPI)( const PS2E_MachineInfo* xinfo );
// Thread Safety:
// * Affinity: Called only from the Main/GUI thread.
// * Interlocking: Full interlocking garaunteed.
//
typedef const PS2E_LibraryAPI* (PS2E_CALLBACK* _PS2E_InitAPI)( const PS2E_EmulatorInfo* emuinfo );
// --------------------------------------------------------------------------------------
// PS2E_GetLastError
// --------------------------------------------------------------------------------------
// Optional method which may be called by the emulator if the plugin returned NULL on
// PS2E_InitAPI. Plugins may return NULL for either/both msg_diag and msg_user. Returned
// pointers should be static global arrays, and must be NULL terminated. If only one
// message is provided, it will be used for both console log and popup.
//
// Parameters:
// msg_diag - diagnostic message, which is english only and typically intended for console
// or disk logging.
//
// msg_user - optional translated user message, which is displayed as a popup to explain
// to the user why the plugin failed to initialize.
//
typedef void (PS2E_CALLBACK* _PS2E_GetLastError)( char* const* msg_diag, wchar_t* const* msg_user );
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
@ -642,7 +801,7 @@ typedef const PS2E_LibraryAPI* (PS2E_CALLBACK* _PS2E_InitAPI)( const PS2E_Machin
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
#if 0
// PAD
typedef s32 (CALLBACK* _PADinit)(char *configpath, u32 flags);
typedef s32 (CALLBACK* _PADopen)(void *pDisplay);
@ -809,166 +968,7 @@ extern _PS2EgetLibVersion2 PS2EgetLibVersion2;
extern _PS2EgetLibName PS2EgetLibName;
extern _PS2EpassConfig PS2EpassConfig;
// PAD1
extern _PADinit PAD1init;
extern _PADopen PAD1open;
extern _PADclose PAD1close;
extern _PADshutdown PAD1shutdown;
extern _PADkeyEvent PAD1keyEvent;
extern _PADstartPoll PAD1startPoll;
extern _PADpoll PAD1poll;
extern _PADquery PAD1query;
extern _PADupdate PAD1update;
extern _PADfreeze PAD1freeze;
extern _PADgsDriverInfo PAD1gsDriverInfo;
extern _PADconfigure PAD1configure;
extern _PADtest PAD1test;
extern _PADabout PAD1about;
// PAD2
extern _PADinit PAD2init;
extern _PADopen PAD2open;
extern _PADclose PAD2close;
extern _PADshutdown PAD2shutdown;
extern _PADkeyEvent PAD2keyEvent;
extern _PADstartPoll PAD2startPoll;
extern _PADpoll PAD2poll;
extern _PADquery PAD2query;
extern _PADupdate PAD2update;
extern _PADfreeze PAD2freeze;
extern _PADgsDriverInfo PAD2gsDriverInfo;
extern _PADconfigure PAD2configure;
extern _PADtest PAD2test;
extern _PADabout PAD2about;
// SIO[2]
extern _SIOinit SIOinit[2][9];
extern _SIOopen SIOopen[2][9];
extern _SIOclose SIOclose[2][9];
extern _SIOshutdown SIOshutdown[2][9];
extern _SIOstartPoll SIOstartPoll[2][9];
extern _SIOpoll SIOpoll[2][9];
extern _SIOquery SIOquery[2][9];
extern _SIOkeyEvent SIOkeyEvent;
extern _SIOfreeze SIOfreeze[2][9];
extern _SIOconfigure SIOconfigure[2][9];
extern _SIOtest SIOtest[2][9];
extern _SIOabout SIOabout[2][9];
// SPU2
extern _SPU2init SPU2init;
extern _SPU2open SPU2open;
extern _SPU2close SPU2close;
extern _SPU2shutdown SPU2shutdown;
extern _SPU2write SPU2write;
extern _SPU2read SPU2read;
extern _SPU2readDMA4Mem SPU2readDMA4Mem;
extern _SPU2writeDMA4Mem SPU2writeDMA4Mem;
extern _SPU2interruptDMA4 SPU2interruptDMA4;
extern _SPU2readDMA7Mem SPU2readDMA7Mem;
extern _SPU2writeDMA7Mem SPU2writeDMA7Mem;
extern _SPU2setDMABaseAddr SPU2setDMABaseAddr;
extern _SPU2interruptDMA7 SPU2interruptDMA7;
extern _SPU2ReadMemAddr SPU2ReadMemAddr;
extern _SPU2setupRecording SPU2setupRecording;
extern _SPU2WriteMemAddr SPU2WriteMemAddr;
extern _SPU2irqCallback SPU2irqCallback;
extern _SPU2setClockPtr SPU2setClockPtr;
extern _SPU2setTimeStretcher SPU2setTimeStretcher;
extern _SPU2keyEvent SPU2keyEvent;
extern _SPU2async SPU2async;
extern _SPU2freeze SPU2freeze;
extern _SPU2configure SPU2configure;
extern _SPU2test SPU2test;
extern _SPU2about SPU2about;
// CDVD
extern _CDVDinit CDVDinit;
extern _CDVDopen CDVDopen;
extern _CDVDclose CDVDclose;
extern _CDVDshutdown CDVDshutdown;
extern _CDVDreadTrack CDVDreadTrack;
extern _CDVDgetBuffer CDVDgetBuffer;
extern _CDVDreadSubQ CDVDreadSubQ;
extern _CDVDgetTN CDVDgetTN;
extern _CDVDgetTD CDVDgetTD;
extern _CDVDgetTOC CDVDgetTOC;
extern _CDVDgetDiskType CDVDgetDiskType;
extern _CDVDgetTrayStatus CDVDgetTrayStatus;
extern _CDVDctrlTrayOpen CDVDctrlTrayOpen;
extern _CDVDctrlTrayClose CDVDctrlTrayClose;
extern _CDVDkeyEvent CDVDkeyEvent;
extern _CDVDfreeze CDVDfreeze;
extern _CDVDconfigure CDVDconfigure;
extern _CDVDtest CDVDtest;
extern _CDVDabout CDVDabout;
extern _CDVDnewDiskCB CDVDnewDiskCB;
// DEV9
extern _DEV9init DEV9init;
extern _DEV9open DEV9open;
extern _DEV9close DEV9close;
extern _DEV9shutdown DEV9shutdown;
extern _DEV9read8 DEV9read8;
extern _DEV9read16 DEV9read16;
extern _DEV9read32 DEV9read32;
extern _DEV9write8 DEV9write8;
extern _DEV9write16 DEV9write16;
extern _DEV9write32 DEV9write32;
extern _DEV9readDMA8Mem DEV9readDMA8Mem;
extern _DEV9writeDMA8Mem DEV9writeDMA8Mem;
extern _DEV9irqCallback DEV9irqCallback;
extern _DEV9irqHandler DEV9irqHandler;
extern _DEV9keyEvent DEV9keyEvent;
extern _DEV9configure DEV9configure;
extern _DEV9freeze DEV9freeze;
extern _DEV9test DEV9test;
extern _DEV9about DEV9about;
// USB
extern _USBinit USBinit;
extern _USBopen USBopen;
extern _USBclose USBclose;
extern _USBshutdown USBshutdown;
extern _USBread8 USBread8;
extern _USBread16 USBread16;
extern _USBread32 USBread32;
extern _USBwrite8 USBwrite8;
extern _USBwrite16 USBwrite16;
extern _USBwrite32 USBwrite32;
extern _USBasync USBasync;
extern _USBirqCallback USBirqCallback;
extern _USBirqHandler USBirqHandler;
extern _USBsetRAM USBsetRAM;
extern _USBkeyEvent USBkeyEvent;
extern _USBconfigure USBconfigure;
extern _USBfreeze USBfreeze;
extern _USBtest USBtest;
extern _USBabout USBabout;
// FW
extern _FWinit FWinit;
extern _FWopen FWopen;
extern _FWclose FWclose;
extern _FWshutdown FWshutdown;
extern _FWread32 FWread32;
extern _FWwrite32 FWwrite32;
extern _FWirqCallback FWirqCallback;
extern _FWkeyEvent FWkeyEvent;
extern _FWconfigure FWconfigure;
extern _FWfreeze FWfreeze;
extern _FWtest FWtest;
extern _FWabout FWabout;
#endif
#ifndef __cplusplus
}

View File

@ -19,9 +19,31 @@
extern void DevAssert( bool condition, const char* msg );
// --------------------------------------------------------------------------------------
// DESTRUCTOR_CATCHALL - safe destructor helper
// --------------------------------------------------------------------------------------
// In C++ destructors *really* need to be "nothrow" garaunteed, otherwise you can have
// disasterous nested exception throws during the unwinding process of an originating
// exception. Use this macro to dispose of these dangerous exceptions, and generate a
// friendly error log in their wake.
//
#define DESTRUCTOR_CATCHALL \
catch( Exception::BaseException& ex ) \
{ \
Console::Error( "Unhandled BaseException in " __FUNCTION__ " (ignored!):" ); \
Console::Error( ex.FormatDiagnosticMessage() ); \
} \
catch( std::exception& ex ) \
{ \
Console::Error( "Unhandled std::exception in " __FUNCTION__ " (ignored!):" ); \
Console::Error( ex.what() ); \
}
namespace Exception
{
//////////////////////////////////////////////////////////////////////////////////
// --------------------------------------------------------------------------------------
// BaseException
// --------------------------------------------------------------------------------------
// std::exception sucks, and isn't entirely cross-platform reliable in its implementation,
// so I made a replacement. The internal messages are non-const, which means that a
// catch clause can optionally modify them and then re-throw to a top-level handler.
@ -68,8 +90,9 @@ namespace Exception
void InitBaseEx( const char* msg_eng );
};
//////////////////////////////////////////////////////////////////////////////////////////
// Ps2Generic
// --------------------------------------------------------------------------------------
// Ps2Generic Exception
// --------------------------------------------------------------------------------------
// This class is used as a base exception for things tossed by PS2 cpus (EE, IOP, etc).
//
// Implementation note: does not derive from BaseException, so that we can use different

View File

@ -112,13 +112,17 @@ public:
wxFileName& GetFilename() { return *this; }
};
//////////////////////////////////////////////////////////////////////////////////////////
// Path Namespace
// Cross-platform utilities for manipulation of paths and filenames.
// --------------------------------------------------------------------------------------
// Path Namespace
// --------------------------------------------------------------------------------------
// Cross-platform utilities for manipulation of paths and filenames. Mostly these fall
// back on wxWidgets APIs internally, but are still helpful because some of wx's file stuff
// has minor glitches, or requies sloppy wxFileName typecasting.
//
namespace Path
{
extern bool IsRelative( const wxString& path );
extern s64 GetFileSize( const wxString& path );
extern wxString Combine( const wxString& srcPath, const wxString& srcFile );
extern wxString Combine( const wxDirName& srcPath, const wxFileName& srcFile );

View File

@ -18,9 +18,9 @@
// this is all that needs to be called and will fill up the below structs
extern void cpudetectInit();
//////////////////////////////////////////////////////////////////////////////////////////
//
// --------------------------------------------------------------------------------------
struct x86CPU_INFO
// --------------------------------------------------------------------------------------
{
u32 FamilyID; // Processor Family
u32 Model; // Processor Model

View File

@ -16,6 +16,8 @@
#include "PrecompiledHeader.h"
#include "Path.h"
#include <wx/file.h>
#ifdef __LINUX__
#ifndef _S_IFDIR
#define _S_IFDIR S_IFDIR
@ -29,7 +31,7 @@
#endif
// ---------------------------------------------------------------------------------
// wxDirName Implementations
// wxDirName Implementations
// ---------------------------------------------------------------------------------
wxFileName wxDirName::Combine( const wxFileName& right ) const
@ -101,7 +103,7 @@ bool wxDirName::Mkdir()
// ---------------------------------------------------------------------------------
// Path namespace (wxFileName helpers)
// Path namespace (wxFileName helpers)
// ---------------------------------------------------------------------------------
@ -110,6 +112,13 @@ bool Path::IsRelative( const wxString& path )
return wxDirName( path ).IsRelative();
}
// Returns -1 if the file does not exist.
s64 Path::GetFileSize( const wxString& path )
{
if( !wxFile::Exists( path.c_str() ) ) return -1;
return (s64)wxFileName::GetSize( path ).GetValue();
}
// Concatenates two pathnames together, inserting delimiters (backslash on win32)
// as needed! Assumes the 'dest' is allocated to at least g_MaxPath length.
//

View File

@ -26,7 +26,13 @@ enum PluginsEnum_t
PluginId_USB,
PluginId_FW,
PluginId_DEV9,
PluginId_Count
PluginId_Count,
// Memorycard plugin support is preliminary, and is only hacked/hardcoded in at this
// time. So it's placed afer PluginId_Count so that it doesn't show up in the conf
// screens or other plugin tables.
PluginId_Mcd
};
// This macro is actually useful for about any and every possible application of C++
@ -265,7 +271,10 @@ public:
SkipBiosSplash:1,
// enables simulated ejection of memory cards when loading savestates
McdEnableEjection:1;
McdEnableEjection:1,
MultitapPort0_Enabled:1,
MultitapPort1_Enabled:1;
}; };
CpuOptions Cpu;
@ -284,6 +293,12 @@ public:
void Save( const wxString& dstfile );
void Save( const wxOutputStream& deststream );
bool MultitapEnabled( uint port ) const
{
wxASSERT( port < 2 );
return (port==0) ? MultitapPort0_Enabled : MultitapPort1_Enabled;
}
bool operator ==( const Pcsx2Config& right ) const
{
return

View File

@ -539,7 +539,7 @@ void loadElfFile(const wxString& filename)
{
if( filename.IsEmpty() ) return;
wxULongLong elfsize;
s64 elfsize;
Console::Status( wxsFormat( L"loadElfFile: %s", filename.c_str() ) );
const wxCharBuffer buffer( filename.ToAscii() );
@ -549,7 +549,7 @@ void loadElfFile(const wxString& filename)
if( !filename.StartsWith( L"cdrom0:" ) && !filename.StartsWith( L"cdrom1:" ) )
{
DevCon::WriteLn("Loading from a file (or non-cd image)");
elfsize = wxFileName::GetSize( filename );
elfsize = Path::GetFileSize( filename );
}
else
{
@ -562,14 +562,14 @@ void loadElfFile(const wxString& filename)
elfsize = toc.fileSize;
}
if( elfsize.GetHi() != 0 )
throw Exception::BadStream( filename, wxLt("Illegal ELF file size, over 4GB: ") );
if( elfsize > 0xfffffff )
throw Exception::BadStream( filename, wxLt("Illegal ELF file size, over 2GB!") );
Console::Status( wxsFormat(L"loadElfFile: %d", elfsize.GetLo()) );
Console::Status( wxsFormat(L"loadElfFile: %d", wxULongLong(elfsize).GetLo() ) );
if( elfsize == 0 )
throw Exception::BadStream( filename, wxLt("Unexpected end of ELF file: ") );
ElfObject elfobj( filename, elfsize.GetLo() );
ElfObject elfobj( filename, wxULongLong(elfsize).GetLo() );
if( elfobj.proghead == NULL )
{

View File

@ -206,8 +206,6 @@
<Unit filename="../MTGS.cpp" />
<Unit filename="../Memory.cpp" />
<Unit filename="../Memory.h" />
<Unit filename="../MemoryCard.cpp" />
<Unit filename="../MemoryCard.h" />
<Unit filename="../NakedAsm.h" />
<Unit filename="../Patch.cpp" />
<Unit filename="../Patch.h" />
@ -289,7 +287,8 @@
<Unit filename="../gui/MainFrame.cpp" />
<Unit filename="../gui/MainFrame.h" />
<Unit filename="../gui/MainMenuClicks.cpp" />
<Unit filename="../gui/Panels/AudioPanel.cpp" />
<Unit filename="../gui/MemoryCardFile.cpp" />
<Unit filename="../gui/Panels/AudioPanel.cpp" />
<Unit filename="../gui/Panels/BiosSelectorPanel.cpp" />
<Unit filename="../gui/Panels/ConfigurationPanels.h" />
<Unit filename="../gui/Panels/CpuPanel.cpp" />

View File

@ -1,198 +0,0 @@
/* 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 "System.h"
#include "MemoryCard.h"
#include "AppConfig.h"
#include <wx/file.h>
#ifdef WIN32
extern void NTFS_CompressFile( const wxString& file, bool compressMode );
#endif
wxFile MemoryCard::cardfile[2];
// Ensures memory card files are created/initialized.
void MemoryCard::Init()
{
for( int i=0; i<2; i++ )
{
if( g_Conf->Mcd[i].Enabled && !cardfile[i].IsOpened() )
Load( i );
}
}
void MemoryCard::Shutdown()
{
for( int i=0; i<2; i++ )
Unload( i );
}
void MemoryCard::Unload( uint mcd )
{
jASSUME( mcd < 2 );
cardfile[mcd].Close();
}
bool MemoryCard::IsPresent( uint mcd )
{
jASSUME( mcd < 2 );
return cardfile[mcd].IsOpened();
}
void MemoryCard::Load( uint mcd )
{
jASSUME( mcd < 2 );
wxFileName fname( g_Conf->FullpathToMcd( mcd ) );
wxString str( fname.GetFullPath() );
const wxULongLong fsz = fname.GetSize();
if( (fsz == 0) || (fsz == wxInvalidSize) )
Create( str );
// [TODO] : Add memcard size detection and report it to the console log.
// (8MB, 256Mb, whatever)
#ifdef _WIN32
NTFS_CompressFile( str, g_Conf->McdEnableNTFS );
#endif
cardfile[mcd].Open( str.c_str(), wxFile::read_write );
if( !cardfile[mcd].IsOpened() )
{
// Translation note: detailed description should mention that the memory card will be disabled
// for the duration of this session.
Msgbox::Alert( pxE( ".Popup:MemoryCard:FailedtoOpen",
wxsFormat(
L"Could not load or create a MemoryCard from the file:\n\n%s\n\n"
L"The MemoryCard in slot %d has been automatically disabled. You can correct the problem\n"
L"and re-enable the MemoryCard at any time using Config:MemoryCards from the main menu.",
str.c_str(), mcd
) )
);
}
}
void MemoryCard::Seek( wxFile& f, u32 adr )
{
u32 size = f.Length();
if (size == MCD_SIZE + 64)
f.Seek( adr + 64 );
else if (size == MCD_SIZE + 3904)
f.Seek( adr + 3904 );
else
f.Seek( adr );
}
void MemoryCard::Read( uint mcd, u8 *data, u32 adr, int size )
{
jASSUME( mcd < 2 );
wxFile& mcfp( cardfile[mcd] );
if( !mcfp.IsOpened() )
{
DevCon::Error( "MemoryCard: Ignoring attempted read from disabled card." );
memset(data, 0, size);
return;
}
Seek(mcfp, adr);
mcfp.Read( data, size );
}
void MemoryCard::Save( uint mcd, const u8 *data, u32 adr, int size )
{
jASSUME( mcd < 2 );
wxFile& mcfp( cardfile[mcd] );
if( !mcfp.IsOpened() )
{
DevCon::Error( "MemoryCard: Ignoring attempted save/write to disabled card." );
return;
}
Seek(mcfp, adr);
u8 *currentdata = (u8 *)malloc(size);
mcfp.Read( currentdata, size);
for (int i=0; i<size; i++)
{
if ((currentdata[i] & data[i]) != data[i])
Console::Notice("MemoryCard : writing odd data");
currentdata[i] &= data[i];
}
Seek(mcfp, adr);
mcfp.Write( currentdata, size );
free(currentdata);
}
void MemoryCard::Erase( uint mcd, u32 adr )
{
u8 data[528*16];
memset8_obj<0xff>(data); // clears to -1's
jASSUME( mcd < 2 );
wxFile& mcfp( cardfile[mcd] );
if( !mcfp.IsOpened() )
{
DevCon::Error( "MemoryCard: Ignoring seek for disabled card." );
return;
}
Seek(mcfp, adr);
mcfp.Write( data, sizeof(data) );
}
void MemoryCard::Create( const wxString& mcdFile )
{
//int enc[16] = {0x77,0x7f,0x7f,0x77,0x7f,0x7f,0x77,0x7f,0x7f,0x77,0x7f,0x7f,0,0,0,0};
wxFile fp( mcdFile, wxFile::write );
if( !fp.IsOpened() ) return;
u8 effeffs[528];
memset8_obj<0xff>( effeffs );
for( uint i=0; i<16384; i++ )
fp.Write( effeffs, sizeof(effeffs) );
}
u64 MemoryCard::GetCRC( uint mcd )
{
jASSUME( mcd < 2 );
wxFile& mcfp( cardfile[mcd] );
if( !mcfp.IsOpened() ) return 0;
Seek( mcfp, 0 );
u64 retval = 0;
for( uint i=MC2_SIZE/sizeof(u64); i; --i )
{
u64 temp; mcfp.Read( &temp, sizeof(temp) );
retval ^= temp;
}
return retval;
}

View File

@ -1,80 +0,0 @@
/* 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/>.
*/
#ifndef _MEMORYCARD_H_
#define _MEMORYCARD_H_
static const int MCD_SIZE = 1024 * 8 * 16;
static const int MC2_SIZE = 1024 * 528 * 16;
class MemoryCard
{
protected:
static wxFile cardfile[2];
public:
static void Load( uint mcdId );
static void Seek( wxFile& mcdfp, u32 adr );
static void Create( const wxString& mcd );
public:
static void Init();
static void Shutdown();
static void Unload( uint mcd );
static bool IsPresent( uint mcdId );
static void Read( uint mcdId, u8 *data, u32 adr, int size );
static void Save( uint mcdId, const u8 *data, u32 adr, int size );
static void Erase( uint mcdId, u32 adr );
static bool HasChanged( uint mcdId );
static u64 GetCRC( uint mcdId );
};
struct superblock
{
char magic[28]; // 0x00
char version[12]; // 0x1c
u16 page_len; // 0x28
u16 pages_per_cluster; // 0x2a
u16 pages_per_block; // 0x2c
u16 unused; // 0x2e
u32 clusters_per_card; // 0x30
u32 alloc_offset; // 0x34
u32 alloc_end; // 0x38
u32 rootdir_cluster; // 0x3c
u32 backup_block1; // 0x40
u32 backup_block2; // 0x44
u32 ifc_list[32]; // 0x50
u32 bad_block_list[32]; // 0xd0
u8 card_type; // 0x150
u8 card_flags; // 0x151
};
#if 0 // unused code?
struct McdBlock
{
s8 Title[48];
s8 ID[14];
s8 Name[16];
int IconCount;
u16 Icon[16*16*3];
u8 Flags;
};
void GetMcdBlockInfo(int mcd, int block, McdBlock *info);
#endif
#endif

View File

@ -69,6 +69,6 @@ namespace FilenameDefs
{
extern wxFileName GetConfig();
extern wxFileName GetUsermodeConfig();
extern const wxFileName& Memcard( int slot );
extern const wxFileName& Memcard( uint port, uint slot );
};

View File

@ -153,6 +153,8 @@ void Pcsx2Config::LoadSave( IniInterface& ini )
IniBitBool( EnablePatches );
IniBitBool( McdEnableEjection );
IniBitBool( MultitapPort0_Enabled );
IniBitBool( MultitapPort1_Enabled );
// Process various sub-components:

View File

@ -24,6 +24,38 @@
#include "HostGui.h"
#include "CDVD/CDVDisoReader.h"
#if _MSC_VER
# include "svnrev.h"
#endif
EmuPluginBindings EmuPlugins;
bool EmuPluginBindings::McdIsPresent( uint port, uint slot )
{
return !!Mcd->McdIsPresent( (PS2E_THISPTR) Mcd, port, slot );
}
void EmuPluginBindings::McdRead( uint port, uint slot, u8 *dest, u32 adr, int size )
{
Mcd->McdRead( (PS2E_THISPTR) Mcd, port, slot, dest, adr, size );
}
void EmuPluginBindings::McdSave( uint port, uint slot, const u8 *src, u32 adr, int size )
{
Mcd->McdSave( (PS2E_THISPTR) Mcd, port, slot, src, adr, size );
}
void EmuPluginBindings::McdEraseBlock( uint port, uint slot, u32 adr )
{
Mcd->McdEraseBlock( (PS2E_THISPTR) Mcd, port, slot, adr );
}
u64 EmuPluginBindings::McdGetCRC( uint port, uint slot )
{
return Mcd->McdGetCRC( (PS2E_THISPTR) Mcd, port, slot );
}
// ----------------------------------------------------------------------------
// Yay, order of this array shouldn't be important. :)
//
@ -37,11 +69,10 @@ const PluginInfo tbl_PluginInfo[] =
{ "FW", PluginId_FW, PS2E_LT_FW, PS2E_FW_VERSION },
{ "DEV9", PluginId_DEV9, PS2E_LT_DEV9, PS2E_DEV9_VERSION },
{ NULL }
// SIO is currently unused (legacy?)
//{ "SIO", PluginId_SIO, PS2E_LT_SIO, PS2E_SIO_VERSION }
{ NULL },
// See PluginEnums_t for details on the MemoryCard plugin hack.
{ "Mcd", PluginId_Mcd, 0, 0 },
};
typedef void CALLBACK VoidMethod();
@ -562,6 +593,38 @@ wxString Exception::PluginError::FormatDisplayMessage() const
return wxsFormat( m_message_user, tbl_PluginInfo[PluginId].GetShortname().c_str() );
}
// --------------------------------------------------------------------------------------
// PCSX2 Callbacks passed to Plugins
// --------------------------------------------------------------------------------------
// This is currently unimplemented, and should be provided by the AppHost (gui) rather
// than the EmuCore. But as a quickhackfix until the new plugin API is fleshed out, this
// will suit our needs nicely. :)
static BOOL PS2E_CALLBACK pcsx2_GetInt( const char* name, int* dest )
{
return FALSE; // not implemented...
}
static BOOL PS2E_CALLBACK pcsx2_GetBoolean( const char* name, BOOL* result )
{
return FALSE; // not implemented...
}
static BOOL PS2E_CALLBACK pcsx2_GetString( const char* name, char* dest, int maxlen )
{
return FALSE; // not implemented...
}
static char* PS2E_CALLBACK pcsx2_GetStringAlloc( const char* name, void* (PS2E_CALLBACK* allocator)(int size) )
{
return FALSE; // not implemented...
}
static void PS2E_CALLBACK pcsx2_OSD_WriteLn( int icon, const char* msg )
{
return; // not implemented...
}
// ---------------------------------------------------------------------------------
// Plugin Manager Implementation
// ---------------------------------------------------------------------------------
@ -613,12 +676,42 @@ PluginManager::PluginManager( const wxString (&folders)[PluginId_Count] )
m_info[PluginId_PAD].CommonBindings.Init = _hack_PADinit;
Console::Status( "Plugins loaded successfully.\n" );
// HACK! Manually bind the Internal MemoryCard plugin for now, until
// we get things more completed in the new plugin api.
static const PS2E_EmulatorInfo myself =
{
"PCSX2",
{ 0, PCSX2_VersionHi, PCSX2_VersionLo, SVN_REV },
x86caps.PhysicalCores,
x86caps.LogicalCores,
pcsx2_GetInt,
pcsx2_GetBoolean,
pcsx2_GetString,
pcsx2_GetStringAlloc,
pcsx2_OSD_WriteLn
};
m_mcdPlugin = FileMcd_InitAPI( &myself );
if( m_mcdPlugin == NULL )
{
// fixme: use plugin's GetLastError (not implemented yet!)
throw Exception::PluginLoadError( PluginId_Mcd, wxEmptyString, "Internal Memorycard Plugin failed to load." );
}
}
PluginManager::~PluginManager()
{
Close();
Shutdown();
try
{
Close();
Shutdown();
}
DESTRUCTOR_CATCHALL
// All library unloading done automatically.
}
@ -858,6 +951,17 @@ void PluginManager::Init()
if( 0 != m_info[pid].CommonBindings.Init() )
throw Exception::PluginInitError( pid );
}
if( EmuPlugins.Mcd == NULL )
{
EmuPlugins.Mcd = (PS2E_ComponentAPI_Mcd*)m_mcdPlugin->NewComponentInstance( PS2E_TYPE_Mcd );
if( EmuPlugins.Mcd == NULL )
{
// fixme: use plugin's GetLastError (not implemented yet!)
throw Exception::PluginInitError( PluginId_Mcd, "Internal Memorycard Plugin failed to initialize." );
}
}
if( printlog )
Console::Status( "Plugins initialized successfully.\n" );
}
@ -884,6 +988,15 @@ void PluginManager::Shutdown()
m_info[pid].IsInitialized = false;
m_info[pid].CommonBindings.Shutdown();
}
// More memorycard hacks!!
if( EmuPlugins.Mcd != NULL && m_mcdPlugin != NULL )
{
m_mcdPlugin->DeleteComponentInstance( (PS2E_THISPTR)EmuPlugins.Mcd );
EmuPlugins.Mcd = NULL;
}
Console::Status( "Plugins shutdown successfully." );
}

View File

@ -17,7 +17,9 @@
#define PLUGINtypedefs
#define PLUGINfuncs
#include "PS2Edefs.h"
#include "PluginCallbacks.h"
#include <wx/dynlib.h>
@ -34,6 +36,9 @@ struct PluginInfo
}
};
// --------------------------------------------------------------------------------------
// Plugin-related Exceptions
// --------------------------------------------------------------------------------------
namespace Exception
{
class PluginError : public virtual RuntimeError
@ -103,7 +108,9 @@ namespace Exception
};
};
//////////////////////////////////////////////////////////////////////////////////////////
// --------------------------------------------------------------------------------------
// LegacyPluginAPI_Common
// --------------------------------------------------------------------------------------
// Important: Contents of this structure must match the order of the contents of the
// s_MethMessCommon[] array defined in Plugins.cpp.
//
@ -136,8 +143,40 @@ struct LegacyPluginAPI_Common
class SaveState;
class mtgsThreadObject;
//////////////////////////////////////////////////////////////////////////////////////////
// IPluginManager
// --------------------------------------------------------------------------------------
// PluginBindings
// --------------------------------------------------------------------------------------
// This structure is intended to be the "future" of PCSX2's plugin interface, and will hopefully
// make the current PluginManager largely obsolete (with the exception of the general Load/Unload
// management facilities)
//
class EmuPluginBindings
{
protected:
PS2E_ComponentAPI_Mcd* Mcd;
public:
EmuPluginBindings() :
Mcd( NULL )
{
}
bool McdIsPresent( uint port, uint slot );
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 McdEraseBlock( uint port, uint slot, u32 adr );
u64 McdGetCRC( uint port, uint slot );
friend class PluginManager;
};
extern EmuPluginBindings EmuPlugins;
// --------------------------------------------------------------------------------------
// PluginManagerBase Class
// --------------------------------------------------------------------------------------
// Provides a basic placebo "do-nothing" interface for plugin management. This is used
// to avoid NULL pointer exceptions/segfaults when referencing the plugin manager global
// handle.
@ -169,7 +208,9 @@ public:
virtual bool KeyEvent( const keyEvent& evt ) { return false; }
};
//////////////////////////////////////////////////////////////////////////////////////////
// --------------------------------------------------------------------------------------
// PluginManager Class
// --------------------------------------------------------------------------------------
//
class PluginManager : public PluginManagerBase
{
@ -197,7 +238,8 @@ protected:
bool m_initialized;
PluginStatus_t m_info[PluginId_Count];
PluginStatus_t m_info[PluginId_Count];
const PS2E_LibraryAPI* m_mcdPlugin;
public:
virtual ~PluginManager();
@ -238,6 +280,11 @@ extern PluginManager* PluginManager_Create( const wxChar* (&folders)[PluginId_Co
extern PluginManagerBase& GetPluginManager();
// Hack to expose internal MemoryCard plugin:
extern "C" extern const PS2E_LibraryAPI* FileMcd_InitAPI( const PS2E_EmulatorInfo* emuinfo );
// Per ChickenLiver, this is being used to pass the GS plugins window handle to the Pad plugins.
// So a rename to pDisplay is in the works, but it will not, in fact, be removed.
extern uptr pDsp;
extern uptr pDsp;

View File

@ -16,7 +16,6 @@
#include "PrecompiledHeader.h"
#include "IopCommon.h"
#include "MemoryCard.h"
#include "sio_internal.h"
_sio sio;
@ -46,27 +45,43 @@ __forceinline void SIO_INT()
// Currently only check if pad wants mtap to be active.
// Could lets PCSX2 have its own options, if anyone ever
// wants to add support for using the extra memcard slots.
static bool IsMtapPresent( uint port ) {
return 0 != PADqueryMtap(port+1);
static bool IsMtapPresent( uint port )
{
return EmuConfig.MultitapEnabled( port );
//return (0 != PADqueryMtap(port+1));
}
static void _ReadMcd(u8 *data, u32 adr, int size) {
MemoryCard::Read(sio.GetMemcardIndex(), data, adr, size);
static void _ReadMcd(u8 *data, u32 adr, int size)
{
EmuPlugins.McdRead(
sio.GetMemcardIndex(), sio.activeMemcardSlot[sio.GetMemcardIndex()],
data, adr, size
);
}
static void _SaveMcd(const u8 *data, u32 adr, int size) {
MemoryCard::Save(sio.GetMemcardIndex(), data, adr, size);
static void _SaveMcd(const u8 *data, u32 adr, int size)
{
EmuPlugins.McdSave(
sio.GetMemcardIndex(), sio.activeMemcardSlot[sio.GetMemcardIndex()],
data, adr, size
);
}
static void _EraseMCDBlock(u32 adr) {
MemoryCard::Erase(sio.GetMemcardIndex(), adr);
static void _EraseMCDBlock(u32 adr)
{
EmuPlugins.McdEraseBlock( sio.GetMemcardIndex(), sio.activeMemcardSlot[sio.GetMemcardIndex()], adr );
}
u8 sio_xor(u8 *buf, uint length){
static u8 sio_xor( const u8 *buf, uint length )
{
u8 i, x;
for (x=0, i=0; i<length; i++) x ^= buf[i];
return x & 0xFF;
/*u8 x = 0;
for( uint i=0; i<length; ++i) { x ^= buf[i]; }
return x;*/
}
void sioInit()
@ -78,8 +93,6 @@ void sioInit()
sio.StatReg = TX_RDY | TX_EMPTY;
sio.packetsize = 0;
sio.terminator = 0x55; // Command terminator 'U'
MemoryCard::Init();
}
u8 sioRead8() {
@ -223,6 +236,8 @@ void SIO_CommandWrite(u8 value,int way) {
case 0x42: // WRITE
case 0x43: // READ
case 0x82:
// fixme: THEORY! Clearing either sio.sector or sio.lastsector when loading from
// savestate may safely invalidate games' memorycard caches! -- air
if(value==0x82 && sio.lastsector==sio.sector) sio.mode = 2;
if(value==0x42) sio.mode = 0;
if(value==0x43) sio.lastsector = sio.sector; // Reading
@ -284,8 +299,7 @@ void SIO_CommandWrite(u8 value,int way) {
if (sio.parp==6)
{
if (sio_xor((u8 *)&sio.sector, 4) == value)
MEMCARDS_LOG("MC(%d) SET PAGE sio.sector 0x%04X",
sio.GetMemcardIndex()+1, sio.sector);
MEMCARDS_LOG("MC(%d) SET PAGE sio.sector, sector=0x%04X", sio.GetMemcardIndex()+1, sio.sector);
else
MEMCARDS_LOG("MC(%d) SET PAGE XOR value ERROR 0x%02X != ^0x%02X",
sio.GetMemcardIndex()+1, value, sio_xor((u8 *)&sio.sector, 4));
@ -297,7 +311,7 @@ void SIO_CommandWrite(u8 value,int way) {
if(sio.parp==2) {
sio.terminator = value;
sio.buf[4] = value;
MEMCARDS_LOG("MC(%d) SET TERMINATOR command 0x%02X", sio.GetMemcardIndex()+1, value);
MEMCARDS_LOG("MC(%d) SET TERMINATOR command, value=0x%02X", sio.GetMemcardIndex()+1, value);
}
break;
@ -311,7 +325,7 @@ void SIO_CommandWrite(u8 value,int way) {
//if(value == 0) sio.buf[4] = 0xFF;
sio.buf[4] = 0x55;
MEMCARDS_LOG("MC(%d) GET TERMINATOR command 0x%02X", sio.GetMemcardIndex()+1, value);
MEMCARDS_LOG("MC(%d) GET TERMINATOR command, value=0x%02X", sio.GetMemcardIndex()+1, value);
}
break;
// WRITE DATA
@ -321,19 +335,19 @@ void SIO_CommandWrite(u8 value,int way) {
memset8_obj<0xff>(sio.buf);
sio.buf[sio.bufcount-1]='+';
sio.buf[sio.bufcount]=sio.terminator;
MEMCARDS_LOG("MC(%d) WRITE command 0x%02X\n\n\n\n", sio.GetMemcardIndex()+1, value);
MEMCARDS_LOG("MC(%d) WRITE command, size=0x%02X", sio.GetMemcardIndex()+1, value);
}
else
if ((sio.parp>2) && (sio.parp<sio.bufcount-2)) {
sio.buf[sio.parp]=value;
//MEMCARDS_LOG("MC(%d) WRITING 0x%02X", sio.GetMemcardIndex()+1, value);
//MEMCARDS_LOG("MC(%d) WRITING 0x%02X", sio.GetMemcardIndex()+1, value);
} else
if (sio.parp==sio.bufcount-2) {
if (sio_xor(&sio.buf[3], sio.bufcount-5)==value) {
_SaveMcd(&sio.buf[3], (512+16)*sio.sector+sio.k, sio.bufcount-5);
sio.buf[sio.bufcount-1]=value;
sio.k+=sio.bufcount-5;
}else {
} else {
MEMCARDS_LOG("MC(%d) write XOR value error 0x%02X != ^0x%02X",
sio.GetMemcardIndex()+1, value, sio_xor(&sio.buf[3], sio.bufcount-5));
}
@ -341,12 +355,14 @@ void SIO_CommandWrite(u8 value,int way) {
break;
// READ DATA
case 0x43:
if (sio.parp==2){
if (sio.parp==2)
{
//int i;
sio.bufcount=value+5;
sio.buf[3]='+';
MEMCARDS_LOG("MC(%d) READ command 0x%02X", sio.GetMemcardIndex()+1, value);
MEMCARDS_LOG("MC(%d) READ command, size=0x%02X", sio.GetMemcardIndex()+1, value);
_ReadMcd(&sio.buf[4], (512+16)*sio.sector+sio.k, value);
/*if(sio.mode==2)
{
int j;
@ -361,7 +377,8 @@ void SIO_CommandWrite(u8 value,int way) {
break;
// INTERNAL ERASE
case 0x82:
if(sio.parp==2) {
if(sio.parp==2)
{
sio.buf[2]='+';
sio.buf[3]=sio.terminator;
//if (sio.k != 0 || (sio.sector & 0xf) != 0)
@ -376,7 +393,7 @@ void SIO_CommandWrite(u8 value,int way) {
sio.buf[2]='+';
sio.buf[3]=sio.terminator;*/
//sio.buf[sio.bufcount] = sio.terminator;
MEMCARDS_LOG("MC(%d) INTERNAL ERASE command 0x%02X", sio.GetMemcardIndex()+1, value);
MEMCARDS_LOG("MC(%d) INTERNAL ERASE command 0x%02X", sio.GetMemcardIndex()+1, value);
}
break;
// CARD AUTHENTICATION CHECKS
@ -577,35 +594,22 @@ void InitializeSIO(u8 value)
sio.count = 0;
// Memcard presence reporting!
// In addition to checking the presence of MemoryCard1/2 file handles, we check a
// variable which force-disables all memory cards after a savestate recovery. This
// is needed to inform certain games to clear their cached memorycard indexes.
// Note:
// 0x01100 means Memcard is present
// 0x1D100 means Memcard is missing.
const int mcidx = sio.GetMemcardIndex();
const uint port = sio.GetMemcardIndex();
const uint slot = sio.activeMemcardSlot[port];
if( sio.activeMemcardSlot[mcidx] != 0 )
if( EmuPlugins.McdIsPresent( port, slot ) )
{
// Might want to more aggressively declare a card's non-existence here.
// As non-zero slots always report a failure, and have to read
// the FAT before writing, think this should be fine.
sio2.packet.recvVal1 = 0x1D100;
PAD_LOG( "START MEMCARD[%d][%d] - Only one memcard supported per slot - reported as missing.", sio.GetMemcardIndex(), sio.activeMemcardSlot[mcidx]);
}
else if( m_PostSavestateCards[mcidx] )
{
m_PostSavestateCards[mcidx]--;
sio2.packet.recvVal1 = 0x1D100;
PAD_LOG( "START MEMCARD[%d] - post-savestate ejection - reporting as missing!", sio.GetMemcardIndex() );
sio2.packet.recvVal1 = 0x1100;
PAD_LOG("START MEMCARD [port:%d, slot:%d] - Present", port, slot );
}
else
{
sio2.packet.recvVal1 = MemoryCard::IsPresent( sio.GetMemcardIndex() ) ? 0x1100 : 0x1D100;
PAD_LOG("START MEMCARD [%d] - %s",
sio.GetMemcardIndex(), MemoryCard::IsPresent( sio.GetMemcardIndex() ) ? "Present" : "Missing" );
sio2.packet.recvVal1 = 0x1D100;
PAD_LOG("START MEMCARD [port:%d, slot:%d] - Missing", port, slot );
}
SIO_INT();
@ -641,23 +645,10 @@ void SIO_FORCEINLINE sioInterrupt() {
psxHu32(0x1070)|=0x80;
}
// Signals the sio to eject the specified memory card.
// Called from the memory card configuration when a user changes memory cards.
void sioEjectCard( uint mcdId )
{
jASSUME( mcdId < 2 );
m_PostSavestateCards[mcdId] = 64;
// Reload the new memory card:
MemoryCard::Unload( mcdId );
MemoryCard::Init();
}
void SaveState::sioFreeze()
{
// CRCs for memory cards.
u64 m_mcdCRCs[2];
u64 m_mcdCRCs[2][8];
FreezeTag( "sio" );
if (GetVersion() == 0) {
@ -671,8 +662,11 @@ void SaveState::sioFreeze()
if( IsSaving() )
{
for( int i=0; i<2; ++i )
m_mcdCRCs[i] = MemoryCard::GetCRC( i );
for( int port=0; port<2; ++port )
{
for( int slot=0; slot<8; ++slot )
m_mcdCRCs[port][slot] = EmuPlugins.McdGetCRC( port, slot );
}
}
Freeze( m_mcdCRCs );
@ -691,13 +685,15 @@ void SaveState::sioFreeze()
// it has a "rule" that the memcard should never be ejected during a song. So by
// ejecting it, the game freezes (which is actually good emulation, but annoying!)
for( int i=0; i<2; ++i )
for( int port=0; port<2; ++port )
{
u64 newCRC = MemoryCard::GetCRC( i );
if( newCRC != m_mcdCRCs[i] )
for( int slot=0; slot<8; ++slot )
{
m_PostSavestateCards[i] = 64;
m_mcdCRCs[i] = newCRC;
u64 newCRC = EmuPlugins.McdGetCRC( port, slot );
if( newCRC != m_mcdCRCs[port][slot] )
{
m_mcdCRCs[port][slot] = newCRC;
}
}
}
}

View File

@ -15,7 +15,8 @@
#pragma once
struct _sio {
struct _sio
{
u16 StatReg;
u16 ModeReg;
u16 CtrlReg;
@ -62,5 +63,4 @@ extern void sioWrite8(u8 value);
extern void sioWriteCtrl16(u16 value);
extern void sioInterrupt();
extern void InitializeSIO(u8 value);
extern void sioEjectCard( uint mcdId );

View File

@ -29,8 +29,8 @@
#include "CDVD/CDVD.h"
#include "ps2/CoreEmuThread.h"
#ifndef __LINUX__
#include "svnrev.h"
#if _MSC_VER
# include "svnrev.h"
#endif
using namespace std;

View File

@ -257,18 +257,31 @@ namespace FilenameDefs
return wxFileName( L"usermode.ini" );
}
const wxFileName& Memcard( int slot )
const wxFileName& Memcard( uint port, uint slot )
{
static const wxFileName retval[2] =
static const wxFileName retval[2][4] =
{
wxFileName( L"Mcd001.ps2" ),
wxFileName( L"Mcd002.ps2" )
{
wxFileName( L"Mcd001.ps2" ),
wxFileName( L"Mcd003.ps2" ),
wxFileName( L"Mcd005.ps2" ),
wxFileName( L"Mcd007.ps2" ),
},
{
wxFileName( L"Mcd002.ps2" ),
wxFileName( L"Mcd004.ps2" ),
wxFileName( L"Mcd006.ps2" ),
wxFileName( L"Mcd008.ps2" ),
}
};
if( IsDevBuild && ((uint)slot) >= 2 )
throw Exception::IndexBoundsFault( L"FilenameDefs::Memcard", slot, 2 );
if( IsDevBuild && (port >= 2) )
throw Exception::IndexBoundsFault( L"FilenameDefs::Memcard", port, 2 );
return retval[slot];
if( IsDevBuild && (slot >= 4) )
throw Exception::IndexBoundsFault( L"FilenameDefs::Memcard", slot, 4 );
return retval[port][slot];
}
};
@ -284,7 +297,10 @@ wxString AppConfig::FullPathToConfig() const
wxString AppConfig::FullpathToBios() const { return Path::Combine( Folders.Bios, BaseFilenames.Bios ); }
wxString AppConfig::FullpathToMcd( uint mcdidx ) const { return Path::Combine( Folders.MemoryCards, Mcd[mcdidx].Filename ); }
wxString AppConfig::FullpathToMcd( uint port, uint slot ) const
{
return Path::Combine( Folders.MemoryCards, Mcd[port][slot].Filename );
}
AppConfig::AppConfig() :
MainGuiPosition( wxDefaultPosition )
@ -308,10 +324,14 @@ AppConfig::AppConfig() :
, BaseFilenames()
, EmuOptions()
{
Mcd[0].Enabled = true;
Mcd[1].Enabled = true;
Mcd[0].Filename = FilenameDefs::Memcard(0);
Mcd[1].Filename = FilenameDefs::Memcard(1);
for( uint port=0; port<2; ++port )
{
for( uint slot=0; slot<4; ++slot )
{
Mcd[port][slot].Enabled = (slot==0); // enables main 2 slots
Mcd[port][slot].Filename = FilenameDefs::Memcard( port, slot );
}
}
}
// ------------------------------------------------------------------------
@ -337,12 +357,19 @@ void AppConfig::LoadSaveUserMode( IniInterface& ini, const wxString& cwdhash )
// ------------------------------------------------------------------------
void AppConfig::LoadSaveMemcards( IniInterface& ini )
{
AppConfig defaults;
IniScopedGroup path( ini, L"MemoryCards" );
ini.Entry( L"Slot1Enable", Mcd[0].Enabled, true );
ini.Entry( L"Slot2Enable", Mcd[1].Enabled, true );
ini.Entry( L"Slot1Filename", Mcd[0].Filename, FilenameDefs::Memcard(0) );
ini.Entry( L"Slot2Filename", Mcd[1].Filename, FilenameDefs::Memcard(1) );
for( uint port=0; port<2; ++port )
{
for( int slot=0; slot<4; ++slot )
{
ini.Entry( wxsFormat( L"Port%d_Slot%d_Enable", port, slot ),
Mcd[port][slot].Enabled, defaults.Mcd[port][slot].Enabled );
ini.Entry( wxsFormat( L"Port%d_Slot%d_Filename", port, slot ),
Mcd[port][slot].Filename, defaults.Mcd[port][slot].Filename );
}
}
}
// ------------------------------------------------------------------------
@ -363,6 +390,8 @@ void AppConfig::LoadSave( IniInterface& ini )
ini.EnumEntry( L"CdvdSource", CdvdSource, CDVD_SourceLabels, defaults.CdvdSource );
LoadSaveMemcards( ini );
// Process various sub-components:
ProgLogBox.LoadSave( ini, L"ProgramLog" );
Ps2ConBox.LoadSave( ini, L"Ps2Console" );

View File

@ -138,7 +138,7 @@ public:
wxString CurrentIso;
CDVD_SourceType CdvdSource;
McdOptions Mcd[2];
McdOptions Mcd[2][4];
ConsoleLogOptions ProgLogBox;
ConsoleLogOptions Ps2ConBox;
FolderOptions Folders;
@ -154,7 +154,7 @@ public:
AppConfig();
wxString FullpathToBios() const;
wxString FullpathToMcd( uint mcdidx ) const;
wxString FullpathToMcd( uint port, uint slot ) const;
wxString FullpathTo( PluginsEnum_t pluginId ) const;
wxString FullPathToConfig() const;

View File

@ -16,7 +16,6 @@
#include "PrecompiledHeader.h"
#include "IniInterface.h"
#include "MainFrame.h"
#include "MemoryCard.h"
#include "Plugins.h"
#include "Dialogs/ModalPopups.h"
@ -62,7 +61,6 @@ AppEmuThread::AppEmuThread() :
CoreEmuThread()
, m_kevt()
{
MemoryCard::Init();
}
void AppEmuThread::Resume()
@ -511,7 +509,6 @@ void Pcsx2App::HandleEvent(wxEvtHandler *handler, wxEventFunction func, wxEvent&
bool Pcsx2App::PrepForExit()
{
SysShutdown();
MemoryCard::Shutdown();
CleanupMess();
m_ProgramLogBox = NULL;

View File

@ -23,7 +23,7 @@
#include <wx/iconbndl.h>
#ifdef _WIN32
#if _MSC_VER
# include "svnrev.h"
#endif

View File

@ -0,0 +1,391 @@
/* 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 "Utilities/SafeArray.h"
// IMPORTANT! If this gets a macro redefinition error it means PluginCallbacks.h is included
// in a global-scope header, and that's a BAD THING. Include it only into modules that need
// it, because some need to be able to alter its behavior using defines. Like this:
struct Component_FileMcd;
#define PS2E_THISPTR Component_FileMcd*
#include "System.h"
#include "AppConfig.h"
#if _MSC_VER
# include "svnrev.h"
#endif
#include <wx/file.h>
#ifdef _WIN32
extern void NTFS_CompressFile( const wxString& file, bool compressMode );
#endif
static const int MCD_SIZE = 1024 * 8 * 16;
static const int MC2_SIZE = 1024 * 528 * 16;
// --------------------------------------------------------------------------------------
// FileMemoryCard
// --------------------------------------------------------------------------------------
// Provides thread-safe direct file IO mapping.
//
class FileMemoryCard
{
protected:
wxFile m_file[2][4];
u8 m_effeffs[528*16];
SafeArray<u8> m_currentdata;
public:
FileMemoryCard();
virtual ~FileMemoryCard() {}
void Lock();
void Unlock();
s32 IsPresent( uint port, uint slot );
s32 Read( uint port, uint slot, u8 *dest, u32 adr, int size );
s32 Save( uint port, uint slot, const u8 *src, u32 adr, int size );
s32 EraseBlock( uint port, uint slot, u32 adr );
u64 GetCRC( uint port, uint slot );
protected:
bool Seek( wxFile& f, u32 adr );
bool Create( const wxString& mcdFile );
wxString GetDisabledMessage( uint port, uint slot ) const
{
return pxE( ".Popup:MemoryCard:HasBeenDisabled", wxsFormat(
L"The MemoryCard in port %d/slot %d has been automatically disabled. You can correct the problem\n"
L"and re-enable the MemoryCard at any time using Config:MemoryCards from the main menu.",
port, slot
) );
}
};
FileMemoryCard::FileMemoryCard()
{
memset8_obj<0xff>( m_effeffs );
for( int port=0; port<2; ++port )
{
for( int slot=0; slot<4; ++slot )
{
if( !g_Conf->Mcd[port][slot].Enabled || g_Conf->Mcd[port][slot].Filename.GetFullName().IsEmpty() ) continue;
wxFileName fname( g_Conf->FullpathToMcd( port, slot ) );
wxString str( fname.GetFullPath() );
const wxULongLong fsz = fname.GetSize();
if( (fsz == 0) || (fsz == wxInvalidSize) )
{
if( !Create( str ) )
{
Msgbox::Alert(
wxsFormat( _( "Could not create a MemoryCard file: \n\n%s\n\n" ), str.c_str() ) +
GetDisabledMessage( port, slot )
);
}
}
// [TODO] : Add memcard size detection and report it to the console log.
// (8MB, 256Mb, whatever)
#ifdef _WIN32
NTFS_CompressFile( str, g_Conf->McdEnableNTFS );
#endif
if( !m_file[port][slot].Open( str.c_str(), wxFile::read_write ) )
{
// Translation note: detailed description should mention that the memory card will be disabled
// for the duration of this session.
Msgbox::Alert(
wxsFormat( _( "Access denied to MemoryCard file: \n\n%s\n\n" ), str.c_str() ) +
GetDisabledMessage( port, slot )
);
}
}
}
}
// Returns FALSE if the seek failed (is outside the bounds of the file).
bool FileMemoryCard::Seek( wxFile& f, u32 adr )
{
const u32 size = f.Length();
// If anyone knows why this filesize logic is here (it appears to be related to legacy PSX
// cards, perhaps hacked support for some special memcard formats that had header info?),
// then please replace this comment with something useful. Thanks! -- air
u32 offset = 0;
if( size == MCD_SIZE + 64 )
offset = 64;
else if( size == MCD_SIZE + 3904 )
offset = 3904;
else
{
// perform sanity checks here?
}
return wxInvalidOffset != f.Seek( adr + offset );
}
// returns FALSE if an error occurred (either permission denied or disk full)
bool FileMemoryCard::Create( const wxString& mcdFile )
{
//int enc[16] = {0x77,0x7f,0x7f,0x77,0x7f,0x7f,0x77,0x7f,0x7f,0x77,0x7f,0x7f,0,0,0,0};
wxFile fp( mcdFile, wxFile::write );
if( !fp.IsOpened() ) return false;
for( uint i=0; i<MC2_SIZE/sizeof(m_effeffs); i++ )
{
if( fp.Write( m_effeffs, sizeof(m_effeffs) ) == 0 )
return false;
}
return true;
}
s32 FileMemoryCard::IsPresent( uint port, uint slot )
{
return m_file[port][slot].IsOpened();
}
s32 FileMemoryCard::Read( uint port, uint slot, u8 *dest, u32 adr, int size )
{
wxFile& mcfp( m_file[port][slot] );
if( !mcfp.IsOpened() )
{
DevCon::Error( "MemoryCard: Ignoring attempted read from disabled card." );
memset(dest, 0, size);
return 1;
}
if( !Seek(mcfp, adr) ) return 0;
return mcfp.Read( dest, size ) != 0;
}
s32 FileMemoryCard::Save( uint port, uint slot, const u8 *src, u32 adr, int size )
{
wxFile& mcfp( m_file[port][slot] );
if( !mcfp.IsOpened() )
{
DevCon::Error( "MemoryCard: Ignoring attempted save/write to disabled card." );
return 1;
}
if( !Seek(mcfp, adr) ) return 0;
m_currentdata.MakeRoomFor( size );
mcfp.Read( m_currentdata.GetPtr(), size);
for (int i=0; i<size; i++)
{
if ((m_currentdata[i] & src[i]) != src[i])
Console::Notice("MemoryCard: (warning) writing to uncleared data.");
m_currentdata[i] &= src[i];
}
if( !Seek(mcfp, adr) ) return 0;
return mcfp.Write( m_currentdata.GetPtr(), size ) != 0;
}
s32 FileMemoryCard::EraseBlock( uint port, uint slot, u32 adr )
{
wxFile& mcfp( m_file[port][slot] );
if( !mcfp.IsOpened() )
{
DevCon::Error( "MemoryCard: Ignoring erase for disabled card." );
return 1;
}
if( !Seek(mcfp, adr) ) return 0;
return mcfp.Write( m_effeffs, sizeof(m_effeffs) ) != 0;
}
u64 FileMemoryCard::GetCRC( uint port, uint slot )
{
wxFile& mcfp( m_file[port][slot] );
if( !mcfp.IsOpened() ) return 0;
if( !Seek( mcfp, 0 ) ) return 0;
u64 retval = 0;
for( uint i=MC2_SIZE/sizeof(u64); i; --i )
{
u64 temp; mcfp.Read( &temp, sizeof(temp) );
retval ^= temp;
}
return retval;
}
// --------------------------------------------------------------------------------------
// MemoryCard Component API Bindings
// --------------------------------------------------------------------------------------
struct Component_FileMcd
{
PS2E_ComponentAPI_Mcd api; // callbacks the plugin provides back to the emulator
FileMemoryCard impl; // class-based implementations we refer to when API is invoked
Component_FileMcd();
};
static s32 PS2E_CALLBACK FileMcd_IsPresent( PS2E_THISPTR thisptr, uint port, uint slot )
{
return thisptr->impl.IsPresent( port, slot );
}
static s32 PS2E_CALLBACK FileMcd_Read( PS2E_THISPTR thisptr, uint port, uint slot, u8 *dest, u32 adr, int size )
{
return thisptr->impl.Read( port, slot, dest, adr, size );
}
static s32 PS2E_CALLBACK FileMcd_Save( PS2E_THISPTR thisptr, uint port, uint slot, const u8 *src, u32 adr, int size )
{
return thisptr->impl.Save( port, slot, src, adr, size );
}
static s32 PS2E_CALLBACK FileMcd_EraseBlock( PS2E_THISPTR thisptr, uint port, uint slot, u32 adr )
{
return thisptr->impl.EraseBlock( port, slot, adr );
}
static u64 PS2E_CALLBACK FileMcd_GetCRC( PS2E_THISPTR thisptr, uint port, uint slot )
{
return thisptr->impl.GetCRC( port, slot );
}
Component_FileMcd::Component_FileMcd()
{
api.McdIsPresent = FileMcd_IsPresent;
api.McdRead = FileMcd_Read;
api.McdSave = FileMcd_Save;
api.McdEraseBlock = FileMcd_EraseBlock;
api.McdGetCRC = FileMcd_GetCRC;
}
// --------------------------------------------------------------------------------------
// Library API Implementations
// --------------------------------------------------------------------------------------
static const char* PS2E_CALLBACK FileMcd_GetName()
{
return "PlainJane Mcd";
}
static const PS2E_VersionInfo* PS2E_CALLBACK FileMcd_GetVersion( u32 component )
{
static const PS2E_VersionInfo version = { 0,1,0, SVN_REV };
return &version;
}
static s32 PS2E_CALLBACK FileMcd_Test( u32 component, const PS2E_EmulatorInfo* xinfo )
{
if( component != PS2E_TYPE_Mcd ) return 0;
// Check and make sure the user has a hard drive?
// Probably not necessary :p
return 1;
}
static PS2E_THISPTR PS2E_CALLBACK FileMcd_NewComponentInstance( u32 component )
{
if( component != PS2E_TYPE_Mcd ) return NULL;
try
{
return new Component_FileMcd();
}
catch( std::bad_alloc& )
{
Console::Error( "Allocation failed on Component_FileMcd! (out of memory?)" );
}
return NULL;
}
static void PS2E_CALLBACK FileMcd_DeleteComponentInstance( PS2E_THISPTR instance )
{
delete instance;
}
static void PS2E_CALLBACK FileMcd_SetSettingsFolder( const char* folder )
{
}
static void PS2E_CALLBACK FileMcd_SetLogFolder( const char* folder )
{
}
static const PS2E_LibraryAPI FileMcd_Library =
{
FileMcd_GetName,
FileMcd_GetVersion,
FileMcd_Test,
FileMcd_NewComponentInstance,
FileMcd_DeleteComponentInstance,
FileMcd_SetSettingsFolder,
FileMcd_SetLogFolder
};
// If made into an external plugin, this function should be renamed to PS2E_InitAPI, so that
// PCSX2 can find the export in the expected location.
extern "C" const PS2E_LibraryAPI* FileMcd_InitAPI( const PS2E_EmulatorInfo* emuinfo )
{
return &FileMcd_Library;
}
// --------------------------------------------------------------------------------------
// Currently Unused Superblock Header Structs
// --------------------------------------------------------------------------------------
struct superblock
{
char magic[28]; // 0x00
char version[12]; // 0x1c
u16 page_len; // 0x28
u16 pages_per_cluster; // 0x2a
u16 pages_per_block; // 0x2c
u16 unused; // 0x2e
u32 clusters_per_card; // 0x30
u32 alloc_offset; // 0x34
u32 alloc_end; // 0x38
u32 rootdir_cluster; // 0x3c
u32 backup_block1; // 0x40
u32 backup_block2; // 0x44
u32 ifc_list[32]; // 0x50
u32 bad_block_list[32]; // 0xd0
u8 card_type; // 0x150
u8 card_flags; // 0x151
};
#if 0 // unused code?
struct McdBlock
{
s8 Title[48];
s8 ID[14];
s8 Name[16];
int IconCount;
u16 Icon[16*16*3];
u8 Flags;
};
void GetMcdBlockInfo(int mcd, int block, McdBlock *info);
#endif

View File

@ -107,20 +107,20 @@ static u32 GetBiosVersion()
// Parameters:
// ext - extension of the sub-component to load. Valid options are rom1, rom2, AND erom.
//
static void loadBiosRom( const wxChar *ext, u8 *dest, u64 maxSize )
static void loadBiosRom( const wxChar *ext, u8 *dest, s64 maxSize )
{
wxString Bios1;
u64 filesize;
s64 filesize;
// Try first a basic extension concatenation (normally results in something like name.bin.rom1)
const wxString Bios( g_Conf->FullpathToBios() );
Bios1.Printf( L"%s.%s", Bios.c_str(), ext);
if( (filesize=wxFileName::GetSize( Bios1 ).GetValue() ) <= 0 )
if( (filesize=Path::GetFileSize( Bios1 ) ) <= 0 )
{
// Try the name properly extensioned next (name.rom1)
Bios1 = Path::ReplaceExtension( Bios, ext );
if( (filesize=wxFileName::GetSize( Bios1 ).GetValue() ) <= 0 )
if( (filesize=Path::GetFileSize( Bios1 ) ) <= 0 )
{
Console::Notice( "Load Bios Warning: %s not found (this is not an error!)", wxString(ext).ToAscii().data() );
return;
@ -149,11 +149,11 @@ void LoadBIOS()
wxString Bios( g_Conf->FullpathToBios() );
u64 filesize = wxFileName::GetSize( Bios ).GetValue();
s64 filesize = Path::GetFileSize( Bios );
if( filesize > 0 )
{
wxFile fp( Bios.c_str() );
fp.Read( PS2MEM_ROM, min( (u64)Ps2MemSize::Rom, filesize ) );
fp.Read( PS2MEM_ROM, min( (s64)Ps2MemSize::Rom, filesize ) );
}
else
{

View File

@ -683,17 +683,13 @@
>
</File>
<File
RelativePath="..\..\x86\BaseblockEx.h"
RelativePath="..\..\ps2\BiosTools.cpp"
>
</File>
<File
RelativePath="..\..\ps2\CoreEmuThread.cpp"
>
</File>
<File
RelativePath="..\..\ps2\CoreEmuThread.h"
>
</File>
<Filter
Name="EmotionEngine"
>
@ -1879,28 +1875,20 @@
</Filter>
</Filter>
<Filter
Name="MemoryCard"
Name="Include"
>
<File
RelativePath="..\..\MemoryCard.cpp"
>
</File>
<File
RelativePath="..\..\MemoryCard.h"
>
</File>
</Filter>
<Filter
Name="BIOS"
>
<File
RelativePath="..\..\ps2\BiosTools.cpp"
RelativePath="..\..\x86\BaseblockEx.h"
>
</File>
<File
RelativePath="..\..\ps2\BiosTools.h"
>
</File>
<File
RelativePath="..\..\ps2\CoreEmuThread.h"
>
</File>
</Filter>
</Filter>
</Filter>
@ -1955,6 +1943,10 @@
RelativePath="..\..\gui\MainMenuClicks.cpp"
>
</File>
<File
RelativePath="..\..\gui\MemoryCardFile.cpp"
>
</File>
<File
RelativePath="..\..\gui\Plugins.cpp"
>

View File

@ -599,10 +599,10 @@ Global
{5307BBB7-EBB9-4AA4-8CB6-A94EC473C8C4} = {703FD00B-D7A0-41E3-BD03-CEC86B385DAF}
{18E42F6F-3A62-41EE-B42F-79366C4F1E95} = {703FD00B-D7A0-41E3-BD03-CEC86B385DAF}
{E4081455-398C-4610-A87C-90A8A7D72DC3} = {703FD00B-D7A0-41E3-BD03-CEC86B385DAF}
{7F059854-568D-4E08-9D00-1E78E203E4DC} = {703FD00B-D7A0-41E3-BD03-CEC86B385DAF}
{6F3C4136-5801-4EBC-AC6E-37DF6FAB150A} = {703FD00B-D7A0-41E3-BD03-CEC86B385DAF}
{FCDF5AE2-EA47-4CC6-9F20-23A0517FEBCB} = {703FD00B-D7A0-41E3-BD03-CEC86B385DAF}
{E1828E40-2FBB-48FE-AE7F-5587755DCE0E} = {703FD00B-D7A0-41E3-BD03-CEC86B385DAF}
{7F059854-568D-4E08-9D00-1E78E203E4DC} = {703FD00B-D7A0-41E3-BD03-CEC86B385DAF}
{5C6B7D28-E73D-4F71-8FC0-17ADA640EBD8} = {703FD00B-D7A0-41E3-BD03-CEC86B385DAF}
{2F6C0388-20CB-4242-9F6C-A6EBB6A83F47} = {78EBE642-7A4D-4EA7-86BE-5639C6646C38}
{F4EB4AB2-C595-4B05-8BC0-059024BC796C} = {78EBE642-7A4D-4EA7-86BE-5639C6646C38}