Memory card work: Show "CHECKING" when we've seen the card and

havn't finished checking it out yet (eg. write check).  This improves responsiveness:
a slow card will indicate that we see the card immediately, and it helps
diagnostics since we can easily tell if the machine sees a card.  Allow re-
establishing a memory card removed after finalization, as long as it has the
same serial number.
This commit is contained in:
Glenn Maynard
2005-02-06 05:08:46 +00:00
parent e4117354ae
commit ca4589a8c3
7 changed files with 211 additions and 81 deletions
+2
View File
@@ -122,8 +122,10 @@ XToThemedString( HoldNoteScore, NUM_HOLD_NOTE_SCORES );
static const CString MemoryCardStateNames[NUM_MEMORY_CARD_STATES] = {
"ready",
"checking",
"late",
"error",
"removed",
"none",
};
XToString( MemoryCardState );
+2
View File
@@ -173,8 +173,10 @@ enum ProfileSlot
enum MemoryCardState
{
MEMORY_CARD_STATE_READY,
MEMORY_CARD_STATE_CHECKING,
MEMORY_CARD_STATE_TOO_LATE,
MEMORY_CARD_STATE_WRITE_ERROR,
MEMORY_CARD_STATE_REMOVED,
MEMORY_CARD_STATE_NO_CARD,
NUM_MEMORY_CARD_STATES,
MEMORY_CARD_STATE_INVALID,
+9 -9
View File
@@ -109,19 +109,14 @@ void GameState::Reset()
{
EndGame();
/* Don't do the OS mount for cards during the attract screens. Only do OS mounts in
* the time between BeginGame and PlayersFinalized. I think we do that anyway (except
* for background write tests, which happen anyway unless the memory card thread is
* paused). Can we remove this? */
MEMCARDMAN->LockCards();
ASSERT( THEME );
m_timeGameStarted.SetZero();
m_pCurStyle = NULL;
FOREACH_PlayerNumber( p )
m_bSideIsJoined[p] = false;
m_bPlayersFinalized = false;
MEMCARDMAN->SetPlayersFinalized( false );
MEMCARDMAN->UnlockCards();
// m_iCoins = 0; // don't reset coin count!
m_MasterPlayerNumber = PLAYER_INVALID;
m_mapEnv.clear();
@@ -161,6 +156,11 @@ void GameState::Reset()
ResetMusicStatistics();
ResetStageStatistics();
FOREACH_PlayerNumber( pn )
if( PROFILEMAN->ProfileWasLoadedFromMemoryCard(pn) )
PROFILEMAN->UnloadProfile( pn );
SONGMAN->FreeAllLoadedFromProfiles();
SONGMAN->UpdateBest();
SONGMAN->UpdateShuffled();
@@ -230,10 +230,10 @@ void GameState::BeginGame()
void GameState::PlayersFinalized()
{
if( m_bPlayersFinalized )
if( MEMCARDMAN->GetPlayersFinalized() )
return;
m_bPlayersFinalized = true;
MEMCARDMAN->SetPlayersFinalized( true );
MEMCARDMAN->LockCards();
-1
View File
@@ -47,7 +47,6 @@ public:
const Game* m_pCurGame;
const Style* m_pCurStyle;
bool m_bSideIsJoined[NUM_PLAYERS]; // left side, right side
bool m_bPlayersFinalized;
PlayMode m_PlayMode; // many screens display different info depending on this value
int m_iCoins; // not "credits"
PlayerNumber m_MasterPlayerNumber; // used in Styles where one player controls both sides
+174 -66
View File
@@ -11,7 +11,6 @@
#include "ScreenManager.h"
#include "ProfileManager.h"
#include "Foreach.h"
#include "GameState.h"
#include "RageUtil_WorkerThread.h"
MemoryCardManager* MEMCARDMAN = NULL; // global and accessable from anywhere in our program
@@ -241,10 +240,12 @@ MemoryCardManager::MemoryCardManager()
m_bCardsLocked = false;
FOREACH_PlayerNumber( p )
{
m_bTooLate[p] = false;
m_bMounted[p] = false;
m_State[p] = MEMORY_CARD_STATE_NO_CARD;
}
m_bPlayersFinalized = false;
/* These can play at any time. Preload them, so we don't cause a skip in gameplay. */
m_soundReady.Load( THEME->GetPathS("MemoryCardManager","ready"), true );
m_soundError.Load( THEME->GetPathS("MemoryCardManager","error"), true );
@@ -269,7 +270,7 @@ void MemoryCardManager::Update( float fDelta )
const vector<UsbStorageDevice> vOld = m_vStorageDevices; // copy
if( !g_pWorker->StorageDevicesChanged( m_vStorageDevices ) )
return;
const vector<UsbStorageDevice> &vNew = m_vStorageDevices;
/* const vector<UsbStorageDevice> &vNew = m_vStorageDevices;
vector<UsbStorageDevice> vConnects; // fill these in below
vector<UsbStorageDevice> vDisconnects; // fill these in below
@@ -305,35 +306,9 @@ void MemoryCardManager::Update( float fDelta )
vector<UsbStorageDevice>::iterator iter = find( vDisconnects.begin(), vDisconnects.end(), assigned_device );
if( iter != vDisconnects.end() )
{
UnmountCard( p );
assigned_device.MakeBlank();
m_soundDisconnect.Play();
if( PROFILEMAN->ProfileWasLoadedFromMemoryCard(p) )
PROFILEMAN->UnloadProfile( p );
}
}
// Update the status of already-assigned cards. It may contain updated info
// like WriteTest results and a new sName.
FOREACH_PlayerNumber( p )
{
UsbStorageDevice &assigned_device = m_Device[p];
if( assigned_device.IsBlank() ) // no card assigned to this player
continue;
vector<UsbStorageDevice>::iterator iter = find( m_vStorageDevices.begin(), m_vStorageDevices.end(), assigned_device );
if( iter != m_vStorageDevices.end() )
{
// play write test error sound if write test failed since we last checked
if( assigned_device.bNeedsWriteTest && !iter->bNeedsWriteTest && !iter->bWriteTestSucceeded )
m_soundError.Play();
assigned_device = *iter;
}
}
*/
// make a list of unassigned
vector<UsbStorageDevice> vUnassignedDevices = m_vStorageDevices; // copy
@@ -354,18 +329,32 @@ void MemoryCardManager::Update( float fDelta )
}
}
// try to assign each device to a player
// Try to assign each device to a player. If a player already has a device
// assigned, and the device still exists, keep him on the same card.
FOREACH_PlayerNumber( p )
{
LOG->Trace( "Looking for a card for Player %d", p+1 );
UsbStorageDevice &assigned_device = m_Device[p];
if( !assigned_device.IsBlank() ) // they already have an assigned card
UsbStorageDevice &assigned_device = m_Device[p];
if( !assigned_device.IsBlank() )
{
LOG->Trace( "Player %d already has a card: '%s'", p+1, assigned_device.sOsMountDir.c_str() );
continue; // skip
/* The player has a card assigned. If it's been removed, clear it. */
vector<UsbStorageDevice>::iterator it = find( m_vStorageDevices.begin(), m_vStorageDevices.end(), assigned_device );
if( it != m_vStorageDevices.end() )
{
/* The player has a card, and it's still plugged in. Update any changed
* state, such as m_State. */
LOG->Trace( "Player %d already has a card: '%s'", p+1, assigned_device.sOsMountDir.c_str() );
assigned_device = *it;
continue;
}
/* The assigned card has been removed; clear it and re-search. */
LOG->Trace( "Player %i: disconnected bus %d port %d device %d path %s",
p+1, assigned_device.iBus, assigned_device.iPort, assigned_device.iLevel, assigned_device.sOsMountDir.c_str() );
assigned_device.MakeBlank();
}
LOG->Trace( "Looking for a card for Player %d", p+1 );
FOREACH( UsbStorageDevice, vUnassignedDevices, d )
{
// search for card dir match
@@ -386,39 +375,106 @@ void MemoryCardManager::Update( float fDelta )
PREFSMAN->m_iMemoryCardUsbLevel[p] != d->iLevel )
continue; // not a match
LOG->Trace( "device match: iScsiIndex: %d, iBus: %d, iLevel: %d, iPort: %d, sOsMountDir: %s",
d->iScsiIndex, d->iBus, d->iLevel, d->iPort, d->sOsMountDir.c_str() );
LOG->Trace( "Player %i: device match: iScsiIndex: %d, iBus: %d, iLevel: %d, iPort: %d, sOsMountDir: %s",
p+1, d->iScsiIndex, d->iBus, d->iLevel, d->iPort, d->sOsMountDir.c_str() );
assigned_device = *d; // save a copy
vUnassignedDevices.erase( d ); // remove the device so we don't match it for another player
m_bTooLate[p] = GAMESTATE->m_bPlayersFinalized; // the device is too late if inserted when cards were locked
// play sound
if( m_bTooLate[p] )
m_soundTooLate.Play();
else if( !d->bNeedsWriteTest && !d->bWriteTestSucceeded )
m_soundError.Play();
else
m_soundReady.Play();
break;
}
}
SCREENMAN->RefreshCreditsMessages();
CheckStateChanges();
}
MemoryCardState MemoryCardManager::GetCardState( PlayerNumber pn )
void MemoryCardManager::CheckStateChanges()
{
UsbStorageDevice &d = m_Device[pn];
if( d.IsBlank() )
return MEMORY_CARD_STATE_NO_CARD;
else if( m_bTooLate[pn] )
return MEMORY_CARD_STATE_TOO_LATE;
else if( !d.bNeedsWriteTest && !d.bWriteTestSucceeded )
return MEMORY_CARD_STATE_WRITE_ERROR;
else
return MEMORY_CARD_STATE_READY;
/* Deal with assignment changes. */
FOREACH_PlayerNumber( p )
{
UsbStorageDevice &new_device = m_Device[p];
MemoryCardState state = MEMORY_CARD_STATE_INVALID;
if( m_bPlayersFinalized )
{
if( m_FinalDevice[p].m_State == UsbStorageDevice::STATE_NONE )
{
/* We didn't have a card when we finalized, so we won't accept anything.
* If anything is inserted (even if it's still checking), say TOO LATE. */
if( new_device.m_State == UsbStorageDevice::STATE_NONE )
state = MEMORY_CARD_STATE_NO_CARD;
else
state = MEMORY_CARD_STATE_TOO_LATE;
}
else
{
/* We had a card inserted when we finalized. */
if( new_device.m_State == UsbStorageDevice::STATE_NONE )
state = MEMORY_CARD_STATE_REMOVED;
if( new_device.m_State == UsbStorageDevice::STATE_READY )
{
if( m_FinalDevice[p].sSerial != new_device.sSerial )
{
/* A different card is inserted than we had when we finalized;
* ignore it. */
state = MEMORY_CARD_STATE_REMOVED;
}
}
/* Otherwise, the card is checking or has an error. Use the regular logic. */
}
}
if( state == MEMORY_CARD_STATE_INVALID )
{
switch( new_device.m_State )
{
case UsbStorageDevice::STATE_NONE:
state = MEMORY_CARD_STATE_NO_CARD;
break;
case UsbStorageDevice::STATE_CHECKING:
state = MEMORY_CARD_STATE_CHECKING;
break;
case UsbStorageDevice::STATE_WRITE_ERROR:
state = MEMORY_CARD_STATE_WRITE_ERROR;
break;
case UsbStorageDevice::STATE_READY:
state = MEMORY_CARD_STATE_READY;
break;
}
}
MemoryCardState LastState = m_State[p];
if( m_State[p] != state )
{
// play sound
switch( state )
{
case MEMORY_CARD_STATE_NO_CARD:
case MEMORY_CARD_STATE_REMOVED:
if( LastState == MEMORY_CARD_STATE_READY )
m_soundDisconnect.Play();
break;
case MEMORY_CARD_STATE_READY:
m_soundReady.Play();
break;
case MEMORY_CARD_STATE_TOO_LATE:
m_soundTooLate.Play();
break;
case MEMORY_CARD_STATE_WRITE_ERROR:
m_soundError.Play();
break;
}
m_State[p] = state;
}
}
SCREENMAN->RefreshCreditsMessages();
}
void MemoryCardManager::LockCards()
@@ -434,8 +490,8 @@ void MemoryCardManager::UnlockCards()
m_bCardsLocked = false;
// clear too late flag
FOREACH_PlayerNumber( p )
m_bTooLate[p] = false;
// FOREACH_PlayerNumber( p )
// m_State[p] = MEMORY_CARD_STATE_NO_CARD;
g_pWorker->SetMountThreadState( ThreadedMemoryCardWorker::detect_and_mount );
}
@@ -518,7 +574,7 @@ void MemoryCardManager::FlushAndReset()
UsbStorageDevice &d = m_Device[p];
if( d.IsBlank() ) // no card assigned
continue; // skip
if( (!d.bNeedsWriteTest && !d.bWriteTestSucceeded) || m_bTooLate[p] )
if( d.m_State == UsbStorageDevice::STATE_WRITE_ERROR )
continue; // skip
g_pWorker->Flush( &m_Device[p] );
}
@@ -526,6 +582,58 @@ void MemoryCardManager::FlushAndReset()
g_pWorker->Reset(); // forces cards to be re-detected
}
void MemoryCardManager::SetPlayersFinalized( bool bOn )
{
m_bPlayersFinalized = bOn;
if( !bOn )
{
m_bPlayersFinalized = false;
/* If a memory card was inserted too late last game, allow it now. */
CheckStateChanges();
return;
}
// g_pWorker->SetTimeout( 10 );
// ASSERT( g_pWorker->TimeoutEnabled() );
/* XXX: wait */
FOREACH_PlayerNumber( p )
{
/* If the card in this player's slot is ready, then use it. */
// XXX: share code with Update(): keep updating until timed out or
// STATE_READY or STATE_NONE
UsbStorageDevice &d = m_Device[p];
/* Set the final state. */
switch( d.m_State )
{
case UsbStorageDevice::STATE_READY:
m_State[p] = MEMORY_CARD_STATE_READY;
m_FinalDevice[p] = d;
break;
case UsbStorageDevice::STATE_NONE:
m_State[p] = MEMORY_CARD_STATE_NO_CARD;
break;
case UsbStorageDevice::STATE_CHECKING:
case UsbStorageDevice::STATE_WRITE_ERROR:
m_State[p] = MEMORY_CARD_STATE_WRITE_ERROR;
break;
default:
FAIL_M( ssprintf("%i", d.m_State) );
}
/* If there is no card ready when we finalize, the final device must be blank. */
if( m_State[p] != MEMORY_CARD_STATE_READY )
m_FinalDevice[p] = UsbStorageDevice();
}
}
bool MemoryCardManager::PathIsMemCard( CString sDir ) const
{
FOREACH_PlayerNumber( p )
+14 -3
View File
@@ -17,7 +17,7 @@ public:
void Update( float fDelta );
MemoryCardState GetCardState( PlayerNumber pn );
MemoryCardState GetCardState( PlayerNumber pn ) const { return m_State[pn]; }
void LockCards(); // prevent removing or changing of memory cards
void UnlockCards();
@@ -26,6 +26,10 @@ public:
void FlushAndReset(); // force all files to be flushed to mounted memory cards
/* If bOn is true, and a card is still initializing, block until it's ready. */
void SetPlayersFinalized( bool bOn );
bool GetPlayersFinalized() const { return m_bPlayersFinalized; }
bool PathIsMemCard( CString sDir ) const;
bool IsNameAvailable( PlayerNumber pn ) const;
@@ -34,13 +38,20 @@ public:
protected:
void PauseMountingThread(); // call this before mouting, reading, or writing to memory card
void UnPauseMountingThread(); // call this when done mouting, reading, or writing to memory card
void CheckStateChanges();
vector<UsbStorageDevice> m_vStorageDevices; // all currently connected
bool m_bCardsLocked;
bool m_bTooLate[NUM_PLAYERS]; // card was inserted after lock
bool m_bMounted[NUM_PLAYERS]; // card is currently mounted
UsbStorageDevice m_Device[NUM_PLAYERS]; // device in the memory card slot, NULL if none
UsbStorageDevice m_Device[NUM_PLAYERS]; // device in the memory card slot, blank if none
UsbStorageDevice m_FinalDevice[NUM_PLAYERS]; // device in the memory card slot when we finalized, blank if none
MemoryCardState m_State[NUM_PLAYERS];
bool m_bPlayersFinalized;
RageSound m_soundReady;
RageSound m_soundError;
+10 -2
View File
@@ -18,6 +18,8 @@
#define CREDITS_CARD_TOO_LATE THEME->GetMetric ("ScreenSystemLayer","CreditsCardTooLate")
#define CREDITS_CARD_NO_NAME THEME->GetMetric ("ScreenSystemLayer","CreditsCardNoName")
#define CREDITS_CARD_READY THEME->GetMetric ("ScreenSystemLayer","CreditsCardReady")
#define CREDITS_CARD_CHECKING THEME->GetMetric ("ScreenSystemLayer","CreditsCardChecking")
#define CREDITS_CARD_REMOVED THEME->GetMetric ("ScreenSystemLayer","CreditsCardRemoved")
#define CREDITS_FREE_PLAY THEME->GetMetric ("ScreenSystemLayer","CreditsFreePlay")
#define CREDITS_CREDITS THEME->GetMetric ("ScreenSystemLayer","CreditsCredits")
#define CREDITS_NOT_PRESENT THEME->GetMetric ("ScreenSystemLayer","CreditsNotPresent")
@@ -123,7 +125,7 @@ void ScreenSystemLayer::RefreshCreditsMessages()
bool bShowCreditsMessage;
if( GAMESTATE->m_bIsOnSystemMenu )
bShowCreditsMessage = true;
else if( GAMESTATE->m_bPlayersFinalized )
else if( MEMCARDMAN->GetPlayersFinalized() )
bShowCreditsMessage = !GAMESTATE->IsPlayerEnabled( p );
else
bShowCreditsMessage = !GAMESTATE->m_bSideIsJoined[p];
@@ -154,6 +156,12 @@ void ScreenSystemLayer::RefreshCreditsMessages()
case MEMORY_CARD_STATE_TOO_LATE:
sCredits = CREDITS_CARD_TOO_LATE;
break;
case MEMORY_CARD_STATE_CHECKING:
sCredits = CREDITS_CARD_CHECKING;
break;
case MEMORY_CARD_STATE_REMOVED:
sCredits = CREDITS_CARD_REMOVED;
break;
case MEMORY_CARD_STATE_READY:
if( PROFILEMAN->LastLoadWasFromLastGood(p) && pProfile )
sCredits = pProfile->GetDisplayName() + CREDITS_LOADED_FROM_LAST_GOOD_APPEND;
@@ -170,7 +178,7 @@ void ScreenSystemLayer::RefreshCreditsMessages()
sCredits = CREDITS_CARD_NO_NAME;
break;
default:
ASSERT(0);
FAIL_M( ssprintf("%i",mcs) );
}
}
else // bShowCreditsMessage