area51/Support/MemCardMgr/MemCardMgr.hpp
Andrew Sampson 431f72b93a source
2021-08-27 19:22:41 -07:00

1032 lines
34 KiB
C++

///////////////////////////////////////////////////////////////////////////////
//
//
// MemCardMgr.hpp
// Wed Feb 26 11:43:28 2003
//
///////////////////////////////////////////////////////////////////////////////
#ifndef __MEMCARDMGR__
#define __MEMCARDMGR__
///////////////////////////////////////////////////////////////////////////////
//
// Includes
//
///////////////////////////////////////////////////////////////////////////////
#include "StateMgr\StateMgr.hpp"
#include "MemCardMgr\MemCardMgr.hpp"
#include "Dialogs\dlg_download.hpp"
class dlg_mcmessage;
///////////////////////////////////////////////////////////////////////////////
//
// Externals
//
///////////////////////////////////////////////////////////////////////////////
enum memcard_mode
{
MEMCARD_FORMAT_MODE,
MEMCARD_CREATE_MODE,
MEMCARD_DELETE_MODE,
MEMCARD_CHECK_MODE,
MEMCARD_SAVE_MODE,
MEMCARD_LOAD_MODE,
MEMCARD_IDLE_MODE
} ;
///////////////////////////////////////////////////////////////////////////////
//
// Defines
//
///////////////////////////////////////////////////////////////////////////////
#ifdef TARGET_XBOX
# define MC_TEXT_BOX_POPUP_SIZE_W 320
# define MC_TEXT_BOX_POPUP_SIZE_H 240
#else
# define MC_TEXT_BOX_POPUP_SIZE_W 400
# define MC_TEXT_BOX_POPUP_SIZE_H 280
#endif
#define MC_STATE_STACK_SIZE 10
#define MEMCARD_VERSION 0x10000000
#define MEMCARD_CORRUPT 0xFFFFFFFF
#define MAX_PROFILE_CAPACITY 32
#ifdef TARGET_XBOX
# define MAX_CARD_SLOTS 1 // hdd
# define MAX_PLAYER_SLOTS 5
#endif
#ifdef TARGET_PS2
# define MAX_CARD_SLOTS 2
# define MAX_PLAYER_SLOTS 3
#endif
#ifdef TARGET_PC
# define MAX_CARD_SLOTS 1
# define MAX_PLAYER_SLOTS 3
#endif
#ifndef __id
#define __id &MemCardMgr::
#endif
///////////////////////////////////////////////////////////////////////////////
//
// Prototypes
//
///////////////////////////////////////////////////////////////////////////////
struct MemCardMgr;
//! Queue machine class
/** This is the event dispatching class.
*/
template< s32 Capacity >struct queue_machine
{
// ------------------------------------------------------------------------
typedef void( MemCardMgr::*ID )(void);
union CbMethod
{
void run( void )
{
#ifdef TARGET_PS2
MemCardMgr* pThis=( MemCardMgr* )Me;
( pThis->*Fn )();
#else
__asm // Curse you .NET! This code works 90%
{ // of the time under Microsoft's .POO!
// #pragma( biscuit_lint:disable )
mov eax,[ecx+8] // Fn
mov ecx,[ecx] // Me
call eax
}
#endif
}
void* Data[4];
struct
{
void* Me;
ID Fn;
};
};
// ------------------------------------------------------------------------
//! Default constructor.
/** This routine is designed for use by other defaults.
*/
queue_machine( MemCardMgr* pParent,ID Idle )
{
x_memset( this,0,sizeof(*this) );
m_pParent = pParent;
m_Idle = Idle;
FlushStateStack();
Control = 0;
}
//! Destructor.
/** This is the place to destroy all those lovely little
member function pointers.
*/
~ queue_machine( void )
{
}
// ------------------------------------------------------------------------
//! Flush states
/** This routine empties the state stack.
*/
void FlushStateStack( void )
{
m_iTail = m_iHead;
}
//! Change state
/** This routine changes the current state.
*/
void ChangeState( ID Id )
{
ASSERT( m_iHead != m_iTail );
m_MethodQueue[m_iHead].Fn=Id;
m_MethodQueue[m_iHead].Me=this;
}
//! Push state
/** This routine pushes the current state onto the stack.
DO NOT PUSH IN REVERSE ORDER!!
*/
template< class t >void PushState( ID Id,t* CbThis,void(t::*Cb)(void) )
{
m_CbMethod[m_iTail].Fn = *(ID*)&Cb;
m_CbMethod[m_iTail].Me = CbThis;
PushState( Id );
}
//! Push state
/** This routine pushes the current state onto the stack.
DO NOT PUSH IN REVERSE ORDER!!
*/
void PushState( ID Id )
{
// add ID .............................................................
m_MethodQueue[m_iTail].Me = m_pParent;
m_MethodQueue[m_iTail].Fn = Id;
// update tail ........................................................
if( m_iTail==m_iHead )
bDirty = true;
if( m_iTail+1 < Capacity )
m_iTail++;
else
m_iTail=0;
// report end of space ................................................
ASSERT( m_iTail != m_iHead );
}
//! Pop state
/** This routine pops the current state and
sets the engine to idle when it's empty.
*/
void PopState( void )
{
if( m_iTail == m_iHead )
return;
// run callback .......................................................
if( m_CbMethod[m_iHead].Me )
{
m_CbMethod[m_iHead].run();
m_CbMethod[m_iHead].Me=0;
m_CbMethod[m_iHead].Fn=0;
}
// move head ..........................................................
if( m_iHead+1 < Capacity )
m_iHead++;
else
m_iHead = 0;
bDirty=true;
}
//! Clear all callbacks.
/** This routine clears all callback methods and owner pointers.
*/
void ClearCBs( void )
{
x_memset( m_CbMethod,0,Capacity*sizeof( CbMethod ));
}
//! Return current state.
/** This routine returns the current ID.
*/
ID GetState( void )
{
if( m_iHead != m_iTail )
return m_MethodQueue[m_iHead].Fn;
return m_Idle;
}
//! Execute id.
/** This routine executes the current state by literally
calling into the m_Id member function pointer.
Very sneaky.
*/
void Exec( void )
{
if( bDirty || bAlways )
{
if( m_iHead != m_iTail )
m_MethodQueue[m_iHead].run();
else
(m_pParent->*m_Idle)();
bDirty = false;
}
}
// ------------------------------------------------------------------------
union
{
struct
{
u32 bWasPolling:1;
u32 bPolling :1;
u32 bAlways :1;
u32 bDirty :1; // Used for single stepping execution
};
u32 Control;
};
///////////////////////////////////////////////////////////////////////////
//! Stack elements
/** This member is an array of pointers to memeber functions
in the class "MemCardMgr". Instead of having named identifiers
to represent states we'll name the functions. Thus
the code can look the same as the pre-A51 days but
with much greater efficiency.
*/
CbMethod m_MethodQueue[Capacity];
//! Callback queue.
/** This member is an array of member function callbacks
corresponding to the m_MethodQueue.
*/
CbMethod m_CbMethod[Capacity];
///////////////////////////////////////////////////////////////////////////
//! Parent class.
/** This member contains the parent to which the methods belong.
*/
MemCardMgr* m_pParent;
//! Head index.
/** This is the current execution point of the stack.
*/
s32 m_iHead;
//! Tail index.
/** This is the end of the stack. When you PopState m_iHead
is incremented. The stack is said to be empty when it
equals m_iTail. When you PushState() m_iTail is
incremented, wrapping to zero if it passes
the array capacity.
*/
s32 m_iTail;
//! Idle routine.
/** This member points to the idle routine.
*/
ID m_Idle;
};
typedef queue_machine< 8 >::ID action;
typedef queue_machine< 64 >::ID mc_id;
///////////////////////////////////////////////////////////////////////////////
struct MemCardMgr: public queue_machine< 64 >
{
// ------------------------------------------------------------------------
// Memory card actions
// ------------------------------------------------------------------------
void MC_NO_ACTION ( void );
void MC_STATE_FINISH ( void );
void MC_STATE_DONE ( void );
void MC_ACTION_CREATE_PROFILE ( void );
void MC_ACTION_DELETE_PROFILE ( void );
void MC_ACTION_SAVE_PROFILE ( void );
void MC_ACTION_OVERWRITE_PROFILE ( void );
void MC_ACTION_LOAD_PROFILE ( void );
void MC_ACTION_CREATE_SETTINGS ( void );
void MC_ACTION_SAVE_SETTINGS ( void );
void MC_ACTION_OVERWRITE_SETTINGS ( void );
void MC_ACTION_LOAD_SETTINGS ( void );
void MC_ACTION_FORMAT ( void );
// ------------------------------------------------------------------------
void MC_ACTION_POLL_CARDS ( void );
void MC_ACTION_REPOLL_CARDS ( void );
void MC_ACTION_BOOT_CHECK ( void );
void MC_ACTION_REBOOT_CHECK ( void );
void MC_ACTION_POLL_CONTENT ( void );
void MC_ACTION_SAVE_CONTENT ( void );
void MC_ACTION_LOAD_CONTENT ( void );
void MC_ACTION_DELETE_CONTENT ( void );
/* polling states */
void MC_STATE_TRAWL_DIRS ( void );
void MC_STATE_TRAWL_DIRS_WAIT ( void );
void MC_STATE_GET_PROFILE_NAMES ( void );
void MC_STATE_GET_PROFILE_NAMES_WAIT ( void );
void MC_STATE_PROFILE_NAME_WAIT ( void );
void MC_STATE_FIND_SETTINGS ( void );
void MC_STATE_FIND_SETTINGS_WAIT ( void );
void MC_STATE_TRAWL_CHECK_CARD ( void );
void MC_STATE_TRAWL_CHECK_CARD_WAIT ( void );
void MC_STATE_TRAWL_CHECK_CARD_HOLD ( void );
/* boot check */
void MC_CHECK_CARD_HOLD ( void );
void MC_CHECK_CARD_WAIT ( void );
void MC_CHECK_CARD_HOLD_WAIT ( void );
void MC_STATE_NO_CARD_ASK ( void );
void MC_STATE_BOOT_CHECK ( void );
void MC_STATE_BOOT_CHECK_WAIT ( void );
void MC_STATE_FIND_PROFILE ( void );
void MC_STATE_FIND_PROFILE_WAIT ( void );
void MC_STATE_FIND_PROFILE_CHECK ( void );
void MC_STATE_BOOT_FAILED_ASK ( void );
void MC_STATE_UNMOUNT ( void );
void MC_STATE_UNMOUNT_WAIT ( void );
void MC_STATE_MOUNT ( void );
void MC_STATE_MOUNT_WAIT ( void );
void MC_STATE_BOOT_ACTION_DONE ( void );
void MC_STATE_REMOUNT ( void );
void MC_STATE_REMOUNT_WAIT ( void );
/* create profile */
void MC_STATE_CREATE_PROFILE_CREATE_DIR_WAIT ( void );
void MC_STATE_CREATE_PROFILE_SET_DIR_WAIT ( void );
void MC_STATE_CREATE_PROFILE ( void );
void MC_STATE_CREATE_PROFILE_FAILED ( void );
void MC_STATE_CREATE_PROFILE_FAILED_WAIT ( void );
/* delete profile */
void MC_STATE_DELETE_PROFILE ( void );
void MC_STATE_DELETE_PROFILE_WAIT ( void );
void MC_STATE_DELETE_PROFILE_FAILED ( void );
void MC_STATE_DELETE_PROFILE_SUCCESS ( void );
void MC_STATE_DELETE_PROFILE_SUCCESS_WAIT ( void );
/* load profile */
void MC_STATE_LOAD_PROFILE_SET_DIR ( void );
void MC_STATE_LOAD_PROFILE_SET_DIR_WAIT ( void );
void MC_STATE_PROFILE_READ_WAIT ( void );
void MC_STATE_LOAD_PROFILE_FAILED ( void );
void MC_STATE_LOAD_PROFILE_SUCCESS ( void );
void MC_STATE_LOAD_PROFILE_SUCCESS_WAIT ( void );
/* load manifest and patch */
void MC_STATE_LOAD_MANIFEST ( void );
void MC_STATE_LOAD_MANIFEST_SET_DIR_WAIT ( void );
void MC_STATE_LOAD_MANIFEST_READ_WAIT ( void );
/* save profile */
void MC_STATE_SAVE_PROFILE ( void );
void MC_STATE_SAVE_PROFILE_SET_DIR_WAIT ( void );
void MC_STATE_PROFILE_WRITE_WAIT ( void );
void MC_STATE_SAVE_PROFILE_FAILED ( void );
void MC_STATE_SAVE_PROFILE_FAILED_WAIT ( void );
void MC_STATE_SAVE_PROFILE_SUCCESS ( void );
void MC_STATE_SAVE_PROFILE_SUCCESS_WAIT ( void );
/* create settings */
void MC_STATE_CREATE_SETTINGS ( void );
void MC_STATE_CREATE_SETTINGS_CREATE_DIR_WAIT( void );
/* save settings */
void MC_STATE_SAVE_SETTINGS ( void );
void MC_STATE_SAVE_SETTINGS_SET_DIR_WAIT ( void );
void MC_STATE_SAVE_SETTINGS_WRITE_WAIT ( void );
void MC_STATE_SAVE_SETTINGS_FAILED ( void );
void MC_STATE_SAVE_SETTINGS_FAILED_WAIT ( void );
void MC_STATE_SAVE_SETTINGS_SUCCESS ( void );
void MC_STATE_SAVE_SETTINGS_SUCCESS_WAIT ( void );
/* overwrite settings */
void MC_STATE_OVERWRITE_SETTINGS_CONFIRM ( void );
void MC_STATE_OVERWRITE_SETTINGS_CONFIRM_WAIT( void );
void MC_STATE_OVERWRITE_SETTINGS_RECHECK ( void );
/* load settings */
void MC_STATE_LOAD_SETTINGS ( void );
void MC_STATE_LOAD_SETTINGS_SET_DIR_WAIT ( void );
void MC_STATE_LOAD_SETTINGS_READ_WAIT ( void );
void MC_STATE_LOAD_CONTENT ( void );
void MC_STATE_SAVE_CONTENT ( void );
void MC_STATE_POLL_CONTENT ( void );
void MC_STATE_DELETE_CONTENT ( void );
void MC_STATE_LOAD_CONTENT_SET_DIR_WAIT ( void );
void MC_STATE_LOAD_CONTENT_GET_SIZE_WAIT ( void );
void MC_STATE_LOAD_CONTENT_READ_WAIT ( void );
void MC_STATE_LOAD_CONTENT_FAILED ( void );
void MC_STATE_DELETE_CONTENT_CONFIRM ( void );
void MC_STATE_DELETE_CONTENT_CONFIRM_WAIT ( void );
void MC_STATE_DELETE_CONTENT_SET_DIR_WAIT ( void );
void MC_STATE_DELETE_CONTENT_DELETE_WAIT ( void );
void MC_STATE_SAVE_CONTENT_CREATE_DIR_WAIT ( void );
void MC_STATE_SAVE_CONTENT_SET_DIR_WAIT ( void );
void MC_STATE_SAVE_CONTENT_WRITE_WAIT ( void );
void MC_STATE_SAVE_CONTENT_FAILED ( void );
void MC_STATE_SAVE_MANIFEST_WRITE_WAIT ( void );
void MC_STATE_POLL_SET_DIR_WAIT ( void );
void MC_STATE_POLL_READ_WAIT ( void );
/* overwrite profile */
void MC_STATE_OVERWRITE_CONFIRM ( void );
void MC_STATE_OVERWRITE_CONFIRM_WAIT ( void );
void MC_STATE_OVERWRITE_RECHECK ( void );
void MC_STATE_OVERWRITE_PROFILE ( void );
void MC_STATE_OVERWRITE_SUCCESS ( void );
void MC_STATE_OVERWRITE_SUCCESS_WAIT ( void );
/* formatting */
void MC_STATE_INIT_FORMAT ( void );
void MC_STATE_ASK_FORMAT ( void );
void MC_STATE_FORMAT_CONFIRM ( void );
void MC_STATE_WAIT_RECHECK_FORMAT ( void );
void MC_STATE_FORMAT_WAIT ( void );
void MC_STATE_FORMAT_CANCEL ( void );
void MC_STATE_FORMAT_FAILED ( void );
void MC_STATE_FORMAT_SUCCESS ( void );
void MC_STATE_FORMAT_SUCCESS_WAIT ( void );
// ------------------------------------------------------------------------
# ifdef TARGET_XBOX
void MC_ACTION_XBOX_CHECK_BLOCK_AVAIL ( void );
# endif
// ------------------------------------------------------------------------
// Actionable memory card states
// ------------------------------------------------------------------------
void MC_STATE_NEXT_CARD ( void );
void MC_STATE_IDLE ( void );
// ------------------------------------------------------------------------
// PS2 PS2 PS2 PS2 PS2 Actionable memory card states
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
// XBOX XBOX XBOX XBOX Actionable memory card states
// ------------------------------------------------------------------------
# if defined( TARGET_XBOX ) || defined( TARGET_PC )
void MC_STATE_MESSAGE_OUT_OF_BLOCKS_ASK ( void );
void MC_STATE_MESSAGE_OUT_OF_BLOCKS ( void );
# endif
// ------------------------------------------------------------------------
enum return_values
{
kNO_RETURN_VALUE = 0,
kACTION_IN_PROCESS,
kNEW_FILE_ERROR,
kDELETE_ERROR,
kFORMAT_ERROR,
kUSER_CANCEL,
kSAVE_ERROR,
kLOAD_ERROR,
kPICKAGAIN,
kRETURN_OK,
kNO_CARD,
};
// ------------------------------------------------------------------------
void ClearProfileNames ( s32 CardID );
void GetProfileNames ( xarray< profile_info* >& Result ); // Get names
s32 Update ( f32 DeltaTime );
void Init ( void );
void Kill ( void );
void SetCard ( s32 CardId ) { m_iCard = CardId; }
s32 GetCard ( void ) { return m_iCard; }
void SetManifest ( const map_list& Manifest ) { m_Manifest = Manifest; }
map_list& GetManifest ( void ) { return m_Manifest; }
map_list& GetManifest ( s32 Card ) { return m_CardManifest[Card]; }
void* GetBuffer ( void ) { return m_pLoadBuffer; }
s32 GetBufferLength ( void ) { return m_LoadBufferSize; }
void FreeBuffer ( void );
MemCardMgr ( void );
~ MemCardMgr ( void );
public:
// ------------------------------------------------------------------------
template< class t >void LoadProfile( profile_info& Info,s32 PlayerID,t* pThis,void(t::* pMethod)(void))
{
m_Action.PushState( __id MC_ACTION_LOAD_PROFILE,pThis,pMethod );
ASSERT( PlayerID >= 0 );
ASSERT( PlayerID < MAX_PLAYER_SLOTS );
m_PreservedProfile[PlayerID] = Info;
m_iPlayer = PlayerID;
bWasPolling = bPolling;
m_iSlot = -1;
}
// ------------------------------------------------------------------------
template< class t >void SaveProfile( profile_info& Info,s32 PlayerID,t* pThis,void(t::* pMethod)(void))
{
m_Action.PushState( __id MC_ACTION_SAVE_PROFILE,pThis,pMethod );
ASSERT( PlayerID >= 0 );
ASSERT( PlayerID < MAX_PLAYER_SLOTS );
m_PreservedProfile[PlayerID] = Info;
m_iPlayer = PlayerID;
bWasPolling = bPolling;
m_iSlot = -1;
}
// ------------------------------------------------------------------------
template< class t >void CreateSettings( t* pThis, void(t::* pMethod)(void) )
{
m_Action.PushState( __id MC_ACTION_CREATE_SETTINGS, pThis, pMethod );
}
// ------------------------------------------------------------------------
template< class t >void SaveSettings( t* pThis, void(t::* pMethod)(void) )
{
m_Action.PushState( __id MC_ACTION_SAVE_SETTINGS, pThis, pMethod );
}
// ------------------------------------------------------------------------
template< class t >void OverwriteSettings( t* pThis, void(t::* pMethod)(void) )
{
m_Action.PushState( __id MC_ACTION_OVERWRITE_SETTINGS, pThis, pMethod );
}
// ------------------------------------------------------------------------
template< class t>void LoadManifest( s32 CardId, map_list& Manifest, t* pThis, void(t::* pMethod)(void))
{
SetCard( CardId );
m_Action.PushState( __id MC_ACTION_LOAD_MANIFEST, pThis, pMethod );
bDirty = TRUE;
}
template< class t>void LoadContent( const map_entry& Manifest, t* pThis, void(t::* pMethod)(void))
{
//
// There is an assumption made here that the information about the manifest entry is contained
// within the global map list, so we don't need to pass that in to get the filename for this
// manifest entry.
//
m_PreservedProfile[MAX_PLAYER_SLOTS-1].CardID = Manifest.GetLocation();
m_PreservedProfile[MAX_PLAYER_SLOTS-1].Dir = Manifest.GetFilename();
m_Action.PushState( __id MC_ACTION_LOAD_CONTENT, pThis, pMethod );
bDirty = TRUE;
}
// ------------------------------------------------------------------------
template< class t>void SaveContent( map_list& Manifest, map_entry& Entry, t* pThis, void(t::* pMethod)(void))
{
const map_info* pMapInfo = Manifest.GetMapInfo( Entry.GetMapID() );
// The manifest for this card will have already been rebuilt to include the new maps to be
// saved, so this map info should exist always!
ASSERT( pMapInfo );
m_PreservedProfile[MAX_PLAYER_SLOTS-1].Dir = pMapInfo->Filename;
m_PreservedProfile[MAX_PLAYER_SLOTS-1].ProfileID = Entry.GetMapID();
m_PreservedProfile[MAX_PLAYER_SLOTS-1].CardID = Entry.GetLocation();
m_Manifest = Manifest;
m_Action.PushState( __id MC_ACTION_SAVE_CONTENT, pThis, pMethod );
bDirty = TRUE;
}
// ------------------------------------------------------------------------
template< class t>void DeleteContent( const map_entry& Manifest, t* pThis, void(t::* pMethod)(void))
{
//
// The content gets deleted from the actual manifest list when
// the manifest list gets serialized in the delete phase.
//
m_PreservedProfile[MAX_PLAYER_SLOTS-1].ProfileID = Manifest.GetMapID();
m_PreservedProfile[MAX_PLAYER_SLOTS-1].CardID = Manifest.GetLocation();
m_Action.PushState( __id MC_ACTION_DELETE_CONTENT, pThis, pMethod );
bDirty = TRUE;
}
// ------------------------------------------------------------------------
template< class t >void OverwriteProfile( profile_info& Info,s32 PlayerID,t* pThis,void(t::* pMethod)(void))
{
m_Action.PushState( __id MC_ACTION_OVERWRITE_PROFILE,pThis,pMethod );
ASSERT( PlayerID >= 0 );
ASSERT( PlayerID < MAX_PLAYER_SLOTS );
m_PreservedProfile[PlayerID] = Info;
m_iPlayer = PlayerID;
bWasPolling = bPolling;
m_iSlot = -1;
}
// ------------------------------------------------------------------------
profile_info& GetProfileInfo( s32 PlayerID )
{
ASSERT( PlayerID >= 0 );
ASSERT( PlayerID < MAX_PLAYER_SLOTS );
return m_PreservedProfile[PlayerID];
}
// ------------------------------------------------------------------------
template< class t >void DeleteProfile( profile_info& Info,t* pThis,void(t::* pMethod)(void))
{
m_Action.PushState( __id MC_ACTION_DELETE_PROFILE,pThis,pMethod );
m_PreservedProfile[0] = Info;
bWasPolling = bPolling;
m_iSlot = -1;
}
// ------------------------------------------------------------------------
template< class t >void CreateProfile( s32 CardID,s32 PlayerID,t* pThis,void(t::* pMethod)(void))
{
m_Action.PushState( __id MC_ACTION_CREATE_PROFILE,pThis,pMethod );
ASSERT( PlayerID >= 0 );
ASSERT( PlayerID < MAX_PLAYER_SLOTS );
bWasPolling = bPolling;
m_iPlayer = PlayerID;
m_PreservedProfile[PlayerID].CardID = CardID;
m_iSlot = -1;
m_iProfile = 0;
}
// ------------------------------------------------------------------------
template< class t >void Format( s32 CardID, s32 PlayerID, card_data_mode Mode, t* pThis,void(t::* pMethod)(void))
{
m_Action.PushState( __id MC_ACTION_FORMAT,pThis,pMethod );
ASSERT( PlayerID >= 0 );
ASSERT( PlayerID < MAX_PLAYER_SLOTS );
bWasPolling = bPolling;
m_PreservedProfile[PlayerID].CardID = CardID;
m_iPlayer = PlayerID;
m_iSlot = -1;
m_iProfile = 0;
m_CardDataMode = Mode;
}
// ------------------------------------------------------------------------
template< class t >void Poll( card_data_mode Mode, t* pThis,void(t::* pMethod)(void))
{
if( ! bPolling )
{
m_CardDataMode = Mode;
m_Action.PushState( __id MC_ACTION_POLL_CARDS,pThis,pMethod );
bPolling = true;
}
}
// ------------------------------------------------------------------------
template< class t >void Repoll( t* pThis,void(t::* pMethod)(void))
{
m_Action.PushState( __id MC_ACTION_REPOLL_CARDS,pThis,pMethod );
bPolling = true;
}
// ------------------------------------------------------------------------
template< class t >void PollContent( xbool ForcePoll, t* pThis, void(t::* pMethod)(void) )
{
if( ForcePoll )
{
s32 i;
for( i=0; i<MAX_CARD_SLOTS; i++ )
{
m_bForcePoll[i] = TRUE;
}
}
if( !bPolling || ForcePoll )
{
m_Action.PushState( __id MC_ACTION_POLL_CONTENT, pThis, pMethod );
bPolling = true;
}
}
// ------------------------------------------------------------------------
void BootCheck( void )
{
m_Action.PushState( __id MC_ACTION_BOOT_CHECK );
}
// ------------------------------------------------------------------------
void RebootCheck( void )
{
m_Action.PushState( __id MC_ACTION_REBOOT_CHECK );
}
// ------------------------------------------------------------------------
void ActionComplete( void );
// ------------------------------------------------------------------------
void ClearCallback( void )
{
m_Action.ClearCBs();
}
// ------------------------------------------------------------------------
xbool IsActionDone( void )
{
return m_ActionDone;
}
// ------------------------------------------------------------------------
private:
void SelectCard ( s32 iCardSelect ){ m_iCard = iCardSelect; }
void SetProfile ( s32 iProfile ) { m_iProfile = iProfile; }
void InitAction ( memcard_mode Mode );
s32 ResetAction ( void );
action PollState ( void );
xbool HandleFaultyIoOp ( void );
xbool GetMemCardEngaged ( void );
void WarningBox ( const char *pTitle,const char *pMessage,xbool AllowPrematureExit=TRUE );
void OptionBox ( const char *pTitle,const char *pMessage,const xwchar* pYes = NULL,const xwchar* pNo = NULL,const xbool DefaultToNo=TRUE,const xbool AllowCancel=FALSE );
void WarningBox ( const xwchar* pTitle,const xwchar* pMessage, xbool AllowPrematureExit=TRUE );
void OptionBox ( const xwchar* pTitle,const xwchar* pMessage, const xwchar *pYes = NULL, const xwchar *pNo = NULL, const xwchar *pMaybe = NULL, const xbool DefaultToNo=TRUE, const xbool AllowCancel=FALSE );
void PopUpBox ( const xwchar* pTitle,const xwchar* pMessage, const xwchar* pNavText, const xbool bYes = TRUE, const xbool bNo = FALSE, const xbool bMaybe = FALSE );
void EnableProgress ( xbool Enabled );
void UpdateProgress ( f32 Progress );
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
#define MAX_PROFILE_COUNT 32
// ------------------------------------------------------------------------
public:
void Clear ( void );
xbool IsPolling ( void ) { return( m_bPollInProgress | m_bForcePoll[0] | m_bForcePoll[1] ); }
xbool FoundProfile ( void ) { return m_bFoundProfile; }
xbool FoundSettings ( void ) { return m_bFoundSettings; }
xbool CardHasSettings ( s32 CardID ) { ASSERT(CardID>=0); ASSERT(CardID<MAX_CARD_SLOTS); return m_bCardHasSettings[CardID]; }
// ------------------------------------------------------------------------
struct condition
{
xarray< profile_info >InfoList;
s32 BytesFree;
// ActionComplete is set to zero when the action begins
// and will contain a value if there was an I/O error,
// the action was cancelled or everything was good.
// It will be zero at the beginning. (SHOULD NEVER
// BE NON-ZERO! A GOOD RULE TO ASSERT.)
void Clear( void )
{
SuccessCode = 0;
ErrorCode = 0;
}
// The ErrorCode will contain a value if something
// bad happened. What *exactly* went south will be
// represented by the individual error state fields.
union
{
u32 ErrorCode;
struct
{
u32 bInsufficientSpace:1;
u32 bIsFull :1;
u32 bBusy :1;
u32 bFileAlreadyExists:1;
u32 bNoFilesAvailable :1;
u32 bFileNameTooLong :1;
u32 bCardHasChanged :1;
u32 bNotEnoughSpace :1;
u32 bFileNotFound :1;
u32 bIncompatible :1;
u32 bAccessDenied :1;
u32 bNotAMemcard :1;
u32 bIoCancelled :1;
u32 bUnformatted :1;
u32 bWrongRegion :1;
u32 bFatalError :1;
u32 bDamaged :1;
u32 bPastEof :1;
u32 bWornOut :1;
u32 bNoCard :1;
u32 bFull :1;
};
};
// The SuccessCode will contain a value when the
// action is said to have completed. This goes
// for both cancelled actions and finished
// ones. The current (front) condition
// should never be zero. Assert this!
union
{
u32 SuccessCode;
struct
{
u32 bCancelled :1;
u32 bComplete :1;
};
};
};
condition& GetPendingCondition( s32 CardID )
{
ASSERT( CardID < MAX_CARD_SLOTS );
return m_Condition[CardID][(m_PollTurn[CardID]&1)^1];
}
condition& GetCondition( s32 CardID )
{
ASSERT( CardID < MAX_CARD_SLOTS );
return m_Condition[CardID][m_PollTurn[CardID]&1];
}
void FlipCondition( s32 CardID )
{
m_PollTurn[CardID]++;
}
enum op_code
{
kFAILURE, // operation failed
kSUCCESS, // operation succeeded
kPENDING, // operation still pending
kRESET // card pulled
};
op_code GetMcResult( void );
op_code m_McResult;
// ------------------------------------------------------------------------
private:
s32 AllocBuffer( s32 Size );
condition m_Condition[ MAX_CARD_SLOTS ][2];
s32 m_PollTurn [ MAX_CARD_SLOTS ];
profile_info m_PreservedProfile[ MAX_PLAYER_SLOTS ];
map_list m_CardManifest[ MAX_CARD_SLOTS ];
map_list m_Manifest;
s32 m_iCard;
s32 m_iDir;
s32 m_iProfile;
s32 m_iPlayer;
s32 m_iSlot;
char m_OptionsPostfix[16];
char m_SavePrefix[16]; // For PS2, will be something like BASLUS-20595
char m_ContentPostfix[16];
s32 m_LastCardState[ MAX_CARD_SLOTS ];
card_data_mode m_CardDataMode;
void* m_pLoadBuffer;
s32 m_LoadBufferSize;
s32 m_bForcePoll[ MAX_CARD_SLOTS ];
xbool m_bPollInProgress;
s16 m_DialogsAllocated;
s32 m_MessageResult;
f32 m_MessageDelay;
s32 m_ActionDone;
s32 m_Closure;
s32 m_SlotArea;
dlg_mcmessage* m_pMessage;
xwstring m_Message;
char* m_pBuffer;
s32 m_nBytes;
u32 m_EncryptionKey[4];
u64 m_LastSettingsDatestamp;
s32 m_CardWait;
memcard_mode m_MemcardMode;
queue_machine< 8 > m_Action;
xbool m_bFoundProfile;
xbool m_bFoundSettings;
xbool m_bPassedBootCheck;
xbool m_bCardHasSettings[ MAX_CARD_SLOTS ];
s32 m_BlocksRequired;
};
///////////////////////////////////////////////////////////////////////////////
extern MemCardMgr g_UIMemCardMgr;
#ifdef _MSC_VER
#pragma warning( disable:4355 )
#endif
#endif // MEMCARDMGR