Padmiss support (#1771)
* Add support for folder based MemoryCard usage * Add support for the padmiss.com network by saving scores to individual files.
This commit is contained in:
@@ -155,10 +155,12 @@ source_group("Arch Specific\\\\Movie Texture" FILES ${SMDATA_ARCH_MOVIE_TEXTURE_
|
|||||||
|
|
||||||
list(APPEND SMDATA_ARCH_MEMORY_SRC
|
list(APPEND SMDATA_ARCH_MEMORY_SRC
|
||||||
"arch/MemoryCard/MemoryCardDriver.cpp"
|
"arch/MemoryCard/MemoryCardDriver.cpp"
|
||||||
|
"arch/MemoryCard/MemoryCardDriverThreaded_Folder.cpp"
|
||||||
)
|
)
|
||||||
list(APPEND SMDATA_ARCH_MEMORY_HPP
|
list(APPEND SMDATA_ARCH_MEMORY_HPP
|
||||||
"arch/MemoryCard/MemoryCardDriver.h"
|
"arch/MemoryCard/MemoryCardDriver.h"
|
||||||
"arch/MemoryCard/MemoryCardDriver_Null.h"
|
"arch/MemoryCard/MemoryCardDriver_Null.h"
|
||||||
|
"arch/MemoryCard/MemoryCardDriverThreaded_Folder.h"
|
||||||
)
|
)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
|
|||||||
+12
-7
@@ -23,7 +23,7 @@ ThemeMetric<bool> USE_CREDIT ( "NotesWriterSM", "DescriptionUsesCreditField" );
|
|||||||
* @brief Write out the common tags for .SM files.
|
* @brief Write out the common tags for .SM files.
|
||||||
* @param f the file in question.
|
* @param f the file in question.
|
||||||
* @param out the Song in question. */
|
* @param out the Song in question. */
|
||||||
static void WriteGlobalTags( RageFile &f, Song &out )
|
static void WriteGlobalTags( RageFileBasic &f, Song &out )
|
||||||
{
|
{
|
||||||
TimingData &timing = out.m_SongTiming;
|
TimingData &timing = out.m_SongTiming;
|
||||||
f.PutLine( ssprintf( "#TITLE:%s;", SmEscape(out.m_sMainTitle).c_str() ) );
|
f.PutLine( ssprintf( "#TITLE:%s;", SmEscape(out.m_sMainTitle).c_str() ) );
|
||||||
@@ -52,7 +52,7 @@ static void WriteGlobalTags( RageFile &f, Song &out )
|
|||||||
default:
|
default:
|
||||||
FAIL_M(ssprintf("Invalid selection display: %i", out.m_SelectionDisplay));
|
FAIL_M(ssprintf("Invalid selection display: %i", out.m_SelectionDisplay));
|
||||||
case Song::SHOW_ALWAYS: f.Write( "YES" ); break;
|
case Song::SHOW_ALWAYS: f.Write( "YES" ); break;
|
||||||
//case Song::SHOW_NONSTOP: f.Write( "NONSTOP" ); break;
|
//case Song::SHOW_NONSTOP: f.Write( "NONSTOP" ); break;
|
||||||
case Song::SHOW_NEVER: f.Write( "NO" ); break;
|
case Song::SHOW_NEVER: f.Write( "NO" ); break;
|
||||||
}
|
}
|
||||||
f.PutLine( ";" );
|
f.PutLine( ";" );
|
||||||
@@ -67,7 +67,7 @@ static void WriteGlobalTags( RageFile &f, Song &out )
|
|||||||
f.PutLine( ssprintf( "#DISPLAYBPM:%.6f;", out.m_fSpecifiedBPMMin ) );
|
f.PutLine( ssprintf( "#DISPLAYBPM:%.6f;", out.m_fSpecifiedBPMMin ) );
|
||||||
else
|
else
|
||||||
f.PutLine( ssprintf( "#DISPLAYBPM:%.6f:%.6f;",
|
f.PutLine( ssprintf( "#DISPLAYBPM:%.6f:%.6f;",
|
||||||
out.m_fSpecifiedBPMMin, out.m_fSpecifiedBPMMax ) );
|
out.m_fSpecifiedBPMMin, out.m_fSpecifiedBPMMax ) );
|
||||||
break;
|
break;
|
||||||
case DISPLAY_BPM_RANDOM:
|
case DISPLAY_BPM_RANDOM:
|
||||||
f.PutLine( ssprintf( "#DISPLAYBPM:*;" ) );
|
f.PutLine( ssprintf( "#DISPLAYBPM:*;" ) );
|
||||||
@@ -220,7 +220,7 @@ static RString GetSMNotesTag( const Song &song, const Steps &in )
|
|||||||
lines.push_back( "" );
|
lines.push_back( "" );
|
||||||
// Escape to prevent some clown from making a comment of "\r\n;"
|
// Escape to prevent some clown from making a comment of "\r\n;"
|
||||||
lines.push_back( ssprintf("//---------------%s - %s----------------",
|
lines.push_back( ssprintf("//---------------%s - %s----------------",
|
||||||
in.m_StepsTypeStr.c_str(), SmEscape(in.GetDescription()).c_str()) );
|
in.m_StepsTypeStr.c_str(), SmEscape(in.GetDescription()).c_str()) );
|
||||||
lines.push_back( song.m_vsKeysoundFile.empty() ? "#NOTES:" : "#NOTES2:" );
|
lines.push_back( song.m_vsKeysoundFile.empty() ? "#NOTES:" : "#NOTES2:" );
|
||||||
lines.push_back( ssprintf( " %s:", in.m_StepsTypeStr.c_str() ) );
|
lines.push_back( ssprintf( " %s:", in.m_StepsTypeStr.c_str() ) );
|
||||||
RString desc = (USE_CREDIT ? in.GetCredit() : in.GetChartName());
|
RString desc = (USE_CREDIT ? in.GetCredit() : in.GetChartName());
|
||||||
@@ -236,7 +236,7 @@ static RString GetSMNotesTag( const Song &song, const Steps &in )
|
|||||||
const RadarValues &rv = in.GetRadarValues( pn );
|
const RadarValues &rv = in.GetRadarValues( pn );
|
||||||
// Can't use the foreach anymore due to flexible radar lines.
|
// Can't use the foreach anymore due to flexible radar lines.
|
||||||
for( RadarCategory rc = (RadarCategory)0; rc < categories;
|
for( RadarCategory rc = (RadarCategory)0; rc < categories;
|
||||||
enum_add<RadarCategory>( rc, 1 ) )
|
enum_add<RadarCategory>( rc, 1 ) )
|
||||||
{
|
{
|
||||||
asRadarValues.push_back( ssprintf("%.6f", rv[rc]) );
|
asRadarValues.push_back( ssprintf("%.6f", rv[rc]) );
|
||||||
}
|
}
|
||||||
@@ -265,6 +265,11 @@ bool NotesWriterSM::Write( RString sPath, Song &out, const vector<Steps*>& vpSte
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Write( f, out, vpStepsToSave );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NotesWriterSM::Write( RageFileBasic &f, Song &out, const vector<Steps*>& vpStepsToSave )
|
||||||
|
{
|
||||||
WriteGlobalTags( f, out );
|
WriteGlobalTags( f, out );
|
||||||
|
|
||||||
FOREACH_CONST( Steps*, vpStepsToSave, s )
|
FOREACH_CONST( Steps*, vpStepsToSave, s )
|
||||||
@@ -320,8 +325,8 @@ bool NotesWriterSM::WriteEditFileToMachine( const Song *pSong, Steps *pSteps, RS
|
|||||||
|
|
||||||
// Check to make sure that we're not clobering an existing file before opening.
|
// Check to make sure that we're not clobering an existing file before opening.
|
||||||
bool bFileNameChanging =
|
bool bFileNameChanging =
|
||||||
pSteps->GetSavedToDisk() &&
|
pSteps->GetSavedToDisk() &&
|
||||||
pSteps->GetFilename() != sPath;
|
pSteps->GetFilename() != sPath;
|
||||||
if( bFileNameChanging && DoesFileExist(sPath) )
|
if( bFileNameChanging && DoesFileExist(sPath) )
|
||||||
{
|
{
|
||||||
sErrorOut = ssprintf( DESTINATION_ALREADY_EXISTS.GetValue(), sPath.c_str() );
|
sErrorOut = ssprintf( DESTINATION_ALREADY_EXISTS.GetValue(), sPath.c_str() );
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
class Song;
|
class Song;
|
||||||
class Steps;
|
class Steps;
|
||||||
|
class RageFileBasic;
|
||||||
/** @brief Writes a Song to an .SM file. */
|
/** @brief Writes a Song to an .SM file. */
|
||||||
namespace NotesWriterSM
|
namespace NotesWriterSM
|
||||||
{
|
{
|
||||||
@@ -11,6 +12,7 @@ namespace NotesWriterSM
|
|||||||
* @param sPath the path to write the file.
|
* @param sPath the path to write the file.
|
||||||
* @param out the Song to be written out.
|
* @param out the Song to be written out.
|
||||||
* @return its success or failure. */
|
* @return its success or failure. */
|
||||||
|
bool Write( RageFileBasic &file, Song &out, const vector<Steps*>& vpStepsToSave );
|
||||||
bool Write( RString sPath, Song &out, const vector<Steps*>& vpStepsToSave );
|
bool Write( RString sPath, Song &out, const vector<Steps*>& vpStepsToSave );
|
||||||
/**
|
/**
|
||||||
* @brief Get some contents about the edit file first.
|
* @brief Get some contents about the edit file first.
|
||||||
|
|||||||
+225
-41
@@ -1,4 +1,4 @@
|
|||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "StatsManager.h"
|
#include "StatsManager.h"
|
||||||
#include "RageFileManager.h"
|
#include "RageFileManager.h"
|
||||||
#include "GameState.h"
|
#include "GameState.h"
|
||||||
@@ -13,11 +13,18 @@
|
|||||||
#include "XmlFile.h"
|
#include "XmlFile.h"
|
||||||
#include "CryptManager.h"
|
#include "CryptManager.h"
|
||||||
#include "XmlFileUtil.h"
|
#include "XmlFileUtil.h"
|
||||||
|
#include "Song.h"
|
||||||
|
#include "RageFileDriverMemory.h"
|
||||||
|
#include "NotesWriterSM.h"
|
||||||
|
#include "PlayerOptions.h"
|
||||||
|
#include "PlayerState.h"
|
||||||
|
#include "Player.h"
|
||||||
|
|
||||||
StatsManager* STATSMAN = NULL; // global object accessible from anywhere in the program
|
StatsManager* STATSMAN = NULL; // global object accessible from anywhere in the program
|
||||||
|
|
||||||
void AddPlayerStatsToProfile( Profile *pProfile, const StageStats &ss, PlayerNumber pn );
|
void AddPlayerStatsToProfile( Profile *pProfile, const StageStats &ss, PlayerNumber pn );
|
||||||
XNode* MakeRecentScoreNode( const StageStats &ss, Trail *pTrail, const PlayerStageStats &pss, MultiPlayer mp );
|
XNode* MakeRecentScoreNode( const StageStats &ss, Trail *pTrail, const PlayerStageStats &pss, MultiPlayer mp );
|
||||||
|
Preference<bool> g_PadmissEnabled("MemoryCardPadmissEnabled", false);
|
||||||
|
|
||||||
StatsManager::StatsManager()
|
StatsManager::StatsManager()
|
||||||
{
|
{
|
||||||
@@ -227,6 +234,10 @@ void StatsManager::CommitStatsToProfiles( const StageStats *pSS )
|
|||||||
LOG->Trace("Adding stats to player profile...");
|
LOG->Trace("Adding stats to player profile...");
|
||||||
AddPlayerStatsToProfile( pPlayerProfile, *pSS, pn );
|
AddPlayerStatsToProfile( pPlayerProfile, *pSS, pn );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// No marathons etc for now...
|
||||||
|
if ( g_PadmissEnabled.Get() && pSS->m_playMode == PLAY_MODE_REGULAR )
|
||||||
|
SavePadmissScore( pSS, pn );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,53 +245,226 @@ void StatsManager::CommitStatsToProfiles( const StageStats *pSS )
|
|||||||
// in it just accumulate uselessly, wasting several seconds when finishing
|
// in it just accumulate uselessly, wasting several seconds when finishing
|
||||||
// a song. So this pref disables it. -Kyz
|
// a song. So this pref disables it. -Kyz
|
||||||
if(!PREFSMAN->m_DisableUploadDir)
|
if(!PREFSMAN->m_DisableUploadDir)
|
||||||
|
SaveUploadFile( pSS );
|
||||||
|
|
||||||
|
//FileCopy( "Data/TempTestGroups.xml", "Save/Upload/data.xml" );
|
||||||
|
}
|
||||||
|
|
||||||
|
void StatsManager::SaveUploadFile( const StageStats *pSS )
|
||||||
|
{
|
||||||
|
// Save recent scores
|
||||||
|
auto_ptr<XNode> xml( new XNode("Stats") );
|
||||||
|
xml->AppendChild( "MachineGuid", PROFILEMAN->GetMachineProfile()->m_sGuid );
|
||||||
|
|
||||||
|
XNode *recent = NULL;
|
||||||
|
if( GAMESTATE->IsCourseMode() )
|
||||||
|
recent = xml->AppendChild( new XNode("RecentCourseScores") );
|
||||||
|
else
|
||||||
|
recent = xml->AppendChild( new XNode("RecentSongScores") );
|
||||||
|
|
||||||
|
if(!GAMESTATE->m_bMultiplayer)
|
||||||
{
|
{
|
||||||
// Save recent scores
|
FOREACH_HumanPlayer( p )
|
||||||
auto_ptr<XNode> xml( new XNode("Stats") );
|
|
||||||
xml->AppendChild( "MachineGuid", PROFILEMAN->GetMachineProfile()->m_sGuid );
|
|
||||||
|
|
||||||
XNode *recent = NULL;
|
|
||||||
if( GAMESTATE->IsCourseMode() )
|
|
||||||
recent = xml->AppendChild( new XNode("RecentCourseScores") );
|
|
||||||
else
|
|
||||||
recent = xml->AppendChild( new XNode("RecentSongScores") );
|
|
||||||
|
|
||||||
if(!GAMESTATE->m_bMultiplayer)
|
|
||||||
{
|
{
|
||||||
FOREACH_HumanPlayer( p )
|
if( pSS->m_player[p].m_HighScore.IsEmpty() )
|
||||||
{
|
continue;
|
||||||
if( pSS->m_player[p].m_HighScore.IsEmpty() )
|
recent->AppendChild( MakeRecentScoreNode( *pSS, GAMESTATE->m_pCurTrail[p], pSS->m_player[p], MultiPlayer_Invalid ) );
|
||||||
continue;
|
|
||||||
recent->AppendChild( MakeRecentScoreNode( *pSS, GAMESTATE->m_pCurTrail[p], pSS->m_player[p], MultiPlayer_Invalid ) );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FOREACH_EnabledMultiPlayer( mp )
|
||||||
{
|
{
|
||||||
FOREACH_EnabledMultiPlayer( mp )
|
if( pSS->m_multiPlayer[mp].m_HighScore.IsEmpty() )
|
||||||
{
|
continue;
|
||||||
if( pSS->m_multiPlayer[mp].m_HighScore.IsEmpty() )
|
recent->AppendChild( MakeRecentScoreNode( *pSS, GAMESTATE->m_pCurTrail[GAMESTATE->GetMasterPlayerNumber()], pSS->m_multiPlayer[mp], mp ) );
|
||||||
continue;
|
|
||||||
recent->AppendChild( MakeRecentScoreNode( *pSS, GAMESTATE->m_pCurTrail[GAMESTATE->GetMasterPlayerNumber()], pSS->m_multiPlayer[mp], mp ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RString sDate = DateTime::GetNowDate().GetString();
|
|
||||||
sDate.Replace(":","-");
|
|
||||||
|
|
||||||
const RString UPLOAD_DIR = "/Save/Upload/";
|
|
||||||
RString sFileNameNoExtension = Profile::MakeUniqueFileNameNoExtension(UPLOAD_DIR, sDate + " " );
|
|
||||||
RString fn = UPLOAD_DIR + sFileNameNoExtension + ".xml";
|
|
||||||
|
|
||||||
bool bSaved = XmlFileUtil::SaveToFile( xml.get(), fn, "", false );
|
|
||||||
|
|
||||||
if( bSaved )
|
|
||||||
{
|
|
||||||
RString sStatsXmlSigFile = fn + SIGNATURE_APPEND;
|
|
||||||
CryptManager::SignFileToFile(fn, sStatsXmlSigFile);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//FileCopy( "Data/TempTestGroups.xml", "Save/Upload/data.xml" );
|
RString sDate = DateTime::GetNowDate().GetString();
|
||||||
|
sDate.Replace(":","-");
|
||||||
|
|
||||||
|
const RString UPLOAD_DIR = "/Save/Upload/";
|
||||||
|
RString sFileNameNoExtension = Profile::MakeUniqueFileNameNoExtension(UPLOAD_DIR, sDate + " " );
|
||||||
|
RString fn = UPLOAD_DIR + sFileNameNoExtension + ".xml";
|
||||||
|
|
||||||
|
bool bSaved = XmlFileUtil::SaveToFile( xml.get(), fn, "", false );
|
||||||
|
|
||||||
|
if( bSaved )
|
||||||
|
{
|
||||||
|
RString sStatsXmlSigFile = fn + SIGNATURE_APPEND;
|
||||||
|
CryptManager::SignFileToFile(fn, sStatsXmlSigFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void StatsManager::SavePadmissScore( const StageStats *pSS, PlayerNumber pn )
|
||||||
|
{
|
||||||
|
const PlayerStageStats *playerStats = &pSS->m_player[ pn ];
|
||||||
|
|
||||||
|
auto_ptr<XNode> xml( new XNode("SongScore") );
|
||||||
|
|
||||||
|
RString sDate = DateTime::GetNowDate().GetString();
|
||||||
|
sDate.Replace(":","-");
|
||||||
|
|
||||||
|
XNode *taps = xml->AppendChild( "TapNoteScores" );
|
||||||
|
FOREACH_ENUM( TapNoteScore, tns )
|
||||||
|
if ( tns != TNS_None )
|
||||||
|
taps->AppendChild( TapNoteScoreToString( tns ), playerStats->m_iTapNoteScores[ tns ] );
|
||||||
|
|
||||||
|
XNode *radar_actual = xml->AppendChild( "RadarActual" );
|
||||||
|
radar_actual->AppendChild( playerStats->m_radarActual.CreateNode( true, false) );
|
||||||
|
|
||||||
|
XNode *radar_possible = xml->AppendChild( "RadarPossible" );
|
||||||
|
radar_possible->AppendChild( playerStats->m_radarPossible.CreateNode( true, false ) );
|
||||||
|
|
||||||
|
Profile *pp = PROFILEMAN->GetProfile( playerStats->m_player_number );
|
||||||
|
xml->AppendChild( "ScoreValue", playerStats->GetPercentDancePoints() );
|
||||||
|
xml->AppendChild( "PlayerNumber", playerStats->m_player_number );
|
||||||
|
xml->AppendChild( "PlayerName", pp->m_sDisplayName );
|
||||||
|
xml->AppendChild( "PlayerGuid", pp->m_sGuid );
|
||||||
|
|
||||||
|
Steps *steps = playerStats->m_vpPossibleSteps[0]; // XXX Courses and such
|
||||||
|
Song *song = steps->m_pSong;
|
||||||
|
steps->Decompress(); // Hashing won't work unless the steps are decompressed
|
||||||
|
XNode *stepdata = xml->AppendChild( "Steps" );
|
||||||
|
stepdata->AppendChild( "Hash", steps->GetHash() );
|
||||||
|
stepdata->AppendChild( "Meter", steps->GetMeter() );
|
||||||
|
stepdata->AppendChild( "StepArtist", steps->GetCredit() );
|
||||||
|
stepdata->AppendChild( "StepsType", steps->m_StepsTypeStr );
|
||||||
|
RageFileObjMem f;
|
||||||
|
vector<Steps*> stepv;
|
||||||
|
stepv.push_back(steps);
|
||||||
|
NotesWriterSM::Write( f, *song, stepv );
|
||||||
|
stepdata->AppendChild( "StepData", f.GetString() );
|
||||||
|
|
||||||
|
XNode *songdata = xml->AppendChild( "SongData" );
|
||||||
|
songdata->AppendChild( "Title", song->m_sMainTitle );
|
||||||
|
songdata->AppendChild( "TitleTranslit", song->m_sMainTitleTranslit );
|
||||||
|
songdata->AppendChild( "SubTitle", song->m_sSubTitle );
|
||||||
|
songdata->AppendChild( "SubTitleTranslit", song->m_sSubTitleTranslit );
|
||||||
|
songdata->AppendChild( "Artist", song->m_sArtist );
|
||||||
|
songdata->AppendChild( "ArtistTranslit", song->m_sArtistTranslit );
|
||||||
|
songdata->AppendChild( "Duration", song->m_fMusicLengthSeconds );
|
||||||
|
|
||||||
|
const PlayerOptions &opts = GAMESTATE->m_pPlayerState[ pn ]->m_PlayerOptions.Get( ModsLevel_Preferred );
|
||||||
|
XNode *mods = xml->AppendChild( "Mods" );
|
||||||
|
mods->AppendChild( "MusicRate", pSS->m_fMusicRate );
|
||||||
|
#define ADD_BOOLEAN_OPTION( parent, name, opts ) \
|
||||||
|
if ( opts[ PlayerOptions::name ] ) \
|
||||||
|
parent->AppendChild( #name )
|
||||||
|
|
||||||
|
XNode *turns = mods->AppendChild( "Turns" );
|
||||||
|
ADD_BOOLEAN_OPTION( turns, TURN_MIRROR, opts.m_bTurns );
|
||||||
|
ADD_BOOLEAN_OPTION( turns, TURN_BACKWARDS, opts.m_bTurns );
|
||||||
|
ADD_BOOLEAN_OPTION( turns, TURN_LEFT, opts.m_bTurns );
|
||||||
|
ADD_BOOLEAN_OPTION( turns, TURN_RIGHT, opts.m_bTurns );
|
||||||
|
ADD_BOOLEAN_OPTION( turns, TURN_SHUFFLE, opts.m_bTurns );
|
||||||
|
ADD_BOOLEAN_OPTION( turns, TURN_SOFT_SHUFFLE, opts.m_bTurns );
|
||||||
|
ADD_BOOLEAN_OPTION( turns, TURN_SUPER_SHUFFLE, opts.m_bTurns );
|
||||||
|
|
||||||
|
XNode *transforms = mods->AppendChild( "Transforms" );
|
||||||
|
ADD_BOOLEAN_OPTION( transforms, TRANSFORM_NOHOLDS, opts.m_bTransforms );
|
||||||
|
ADD_BOOLEAN_OPTION( transforms, TRANSFORM_NOROLLS, opts.m_bTransforms );
|
||||||
|
ADD_BOOLEAN_OPTION( transforms, TRANSFORM_NOMINES, opts.m_bTransforms );
|
||||||
|
ADD_BOOLEAN_OPTION( transforms, TRANSFORM_LITTLE, opts.m_bTransforms );
|
||||||
|
ADD_BOOLEAN_OPTION( transforms, TRANSFORM_WIDE, opts.m_bTransforms );
|
||||||
|
ADD_BOOLEAN_OPTION( transforms, TRANSFORM_BIG, opts.m_bTransforms );
|
||||||
|
ADD_BOOLEAN_OPTION( transforms, TRANSFORM_QUICK, opts.m_bTransforms );
|
||||||
|
ADD_BOOLEAN_OPTION( transforms, TRANSFORM_BMRIZE, opts.m_bTransforms );
|
||||||
|
ADD_BOOLEAN_OPTION( transforms, TRANSFORM_SKIPPY, opts.m_bTransforms );
|
||||||
|
ADD_BOOLEAN_OPTION( transforms, TRANSFORM_MINES, opts.m_bTransforms );
|
||||||
|
ADD_BOOLEAN_OPTION( transforms, TRANSFORM_ATTACKMINES, opts.m_bTransforms );
|
||||||
|
ADD_BOOLEAN_OPTION( transforms, TRANSFORM_ECHO, opts.m_bTransforms );
|
||||||
|
ADD_BOOLEAN_OPTION( transforms, TRANSFORM_STOMP, opts.m_bTransforms );
|
||||||
|
ADD_BOOLEAN_OPTION( transforms, TRANSFORM_PLANTED, opts.m_bTransforms );
|
||||||
|
ADD_BOOLEAN_OPTION( transforms, TRANSFORM_FLOORED, opts.m_bTransforms );
|
||||||
|
ADD_BOOLEAN_OPTION( transforms, TRANSFORM_TWISTER, opts.m_bTransforms );
|
||||||
|
ADD_BOOLEAN_OPTION( transforms, TRANSFORM_HOLDROLLS, opts.m_bTransforms );
|
||||||
|
ADD_BOOLEAN_OPTION( transforms, TRANSFORM_NOJUMPS, opts.m_bTransforms );
|
||||||
|
ADD_BOOLEAN_OPTION( transforms, TRANSFORM_NOHANDS, opts.m_bTransforms );
|
||||||
|
ADD_BOOLEAN_OPTION( transforms, TRANSFORM_NOLIFTS, opts.m_bTransforms );
|
||||||
|
ADD_BOOLEAN_OPTION( transforms, TRANSFORM_NOFAKES, opts.m_bTransforms );
|
||||||
|
ADD_BOOLEAN_OPTION( transforms, TRANSFORM_NOQUADS, opts.m_bTransforms );
|
||||||
|
ADD_BOOLEAN_OPTION( transforms, TRANSFORM_NOSTRETCH, opts.m_bTransforms );
|
||||||
|
|
||||||
|
#define ADD_FLOAT_OPTION( parent, name, opts ) \
|
||||||
|
do { \
|
||||||
|
float val = opts[ PlayerOptions::name ]; \
|
||||||
|
if ( val != 0.0f ) \
|
||||||
|
parent->AppendChild( #name, val ); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
XNode *accels = mods->AppendChild( "Accels" );
|
||||||
|
ADD_FLOAT_OPTION( accels, ACCEL_BOOST, opts.m_fAccels );
|
||||||
|
ADD_FLOAT_OPTION( accels, ACCEL_BRAKE, opts.m_fAccels );
|
||||||
|
ADD_FLOAT_OPTION( accels, ACCEL_WAVE, opts.m_fAccels );
|
||||||
|
ADD_FLOAT_OPTION( accels, ACCEL_EXPAND, opts.m_fAccels );
|
||||||
|
ADD_FLOAT_OPTION( accels, ACCEL_BOOMERANG, opts.m_fAccels );
|
||||||
|
|
||||||
|
XNode *effects = mods->AppendChild( "Effects" );
|
||||||
|
ADD_FLOAT_OPTION( effects, EFFECT_DRUNK, opts.m_fEffects );
|
||||||
|
ADD_FLOAT_OPTION( effects, EFFECT_DIZZY, opts.m_fEffects );
|
||||||
|
ADD_FLOAT_OPTION( effects, EFFECT_CONFUSION, opts.m_fEffects );
|
||||||
|
ADD_FLOAT_OPTION( effects, EFFECT_MINI, opts.m_fEffects );
|
||||||
|
ADD_FLOAT_OPTION( effects, EFFECT_TINY, opts.m_fEffects );
|
||||||
|
ADD_FLOAT_OPTION( effects, EFFECT_FLIP, opts.m_fEffects );
|
||||||
|
ADD_FLOAT_OPTION( effects, EFFECT_INVERT, opts.m_fEffects );
|
||||||
|
ADD_FLOAT_OPTION( effects, EFFECT_TORNADO, opts.m_fEffects );
|
||||||
|
ADD_FLOAT_OPTION( effects, EFFECT_TIPSY, opts.m_fEffects );
|
||||||
|
ADD_FLOAT_OPTION( effects, EFFECT_BUMPY, opts.m_fEffects );
|
||||||
|
ADD_FLOAT_OPTION( effects, EFFECT_BEAT, opts.m_fEffects );
|
||||||
|
ADD_FLOAT_OPTION( effects, EFFECT_XMODE, opts.m_fEffects );
|
||||||
|
ADD_FLOAT_OPTION( effects, EFFECT_TWIRL, opts.m_fEffects );
|
||||||
|
ADD_FLOAT_OPTION( effects, EFFECT_ROLL, opts.m_fEffects );
|
||||||
|
|
||||||
|
XNode *appearances = mods->AppendChild( "Appearances" );
|
||||||
|
ADD_FLOAT_OPTION( appearances, APPEARANCE_HIDDEN, opts.m_fAppearances );
|
||||||
|
ADD_FLOAT_OPTION( appearances, APPEARANCE_HIDDEN_OFFSET, opts.m_fAppearances );
|
||||||
|
ADD_FLOAT_OPTION( appearances, APPEARANCE_SUDDEN, opts.m_fAppearances );
|
||||||
|
ADD_FLOAT_OPTION( appearances, APPEARANCE_SUDDEN_OFFSET, opts.m_fAppearances );
|
||||||
|
ADD_FLOAT_OPTION( appearances, APPEARANCE_STEALTH, opts.m_fAppearances );
|
||||||
|
ADD_FLOAT_OPTION( appearances, APPEARANCE_BLINK, opts.m_fAppearances );
|
||||||
|
ADD_FLOAT_OPTION( appearances, APPEARANCE_RANDOMVANISH, opts.m_fAppearances );
|
||||||
|
|
||||||
|
XNode *scrolls = mods->AppendChild( "Scrolls" );
|
||||||
|
ADD_FLOAT_OPTION( scrolls, SCROLL_REVERSE, opts.m_fScrolls );
|
||||||
|
ADD_FLOAT_OPTION( scrolls, SCROLL_SPLIT, opts.m_fScrolls );
|
||||||
|
ADD_FLOAT_OPTION( scrolls, SCROLL_ALTERNATE, opts.m_fScrolls );
|
||||||
|
ADD_FLOAT_OPTION( scrolls, SCROLL_CROSS, opts.m_fScrolls );
|
||||||
|
ADD_FLOAT_OPTION( scrolls, SCROLL_CENTERED, opts.m_fScrolls );
|
||||||
|
|
||||||
|
mods->AppendChild( "NoteSkin", opts.m_sNoteSkin );
|
||||||
|
|
||||||
|
XNode *perspectives = mods->AppendChild( "Perspectives" );
|
||||||
|
perspectives->AppendChild( "Tilt", opts.m_fPerspectiveTilt );
|
||||||
|
perspectives->AppendChild( "Skew", opts.m_fSkew );
|
||||||
|
|
||||||
|
RString speedModType;
|
||||||
|
float speedModValue;
|
||||||
|
if ( opts.m_fTimeSpacing )
|
||||||
|
{
|
||||||
|
speedModType = "ConstantBPM";
|
||||||
|
speedModValue = opts.m_fScrollBPM;
|
||||||
|
}
|
||||||
|
else if ( opts.m_fMaxScrollBPM )
|
||||||
|
{
|
||||||
|
speedModType = "MaxBPM";
|
||||||
|
speedModValue = opts.m_fMaxScrollBPM;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
speedModType = "Multiplier";
|
||||||
|
speedModValue = opts.m_fScrollSpeed;
|
||||||
|
}
|
||||||
|
mods->AppendChild( "ScrollSpeed", speedModValue )->AppendAttr( "Type", speedModType );
|
||||||
|
|
||||||
|
XNode *timingWindows = xml->AppendChild( "TimingWindows" );
|
||||||
|
FOREACH_ENUM( TimingWindow, tw )
|
||||||
|
timingWindows->AppendChild( TimingWindowToString( tw ), Player::GetWindowSeconds( tw ) );
|
||||||
|
|
||||||
|
RString dir = "/Save/Padmiss/";
|
||||||
|
RString fn = dir + Profile::MakeUniqueFileNameNoExtension( dir, sDate + " " ) + ".xml";
|
||||||
|
XmlFileUtil::SaveToFile( xml.get(), fn, "", true );
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatsManager::UnjoinPlayer( PlayerNumber pn )
|
void StatsManager::UnjoinPlayer( PlayerNumber pn )
|
||||||
|
|||||||
+25
-21
@@ -7,36 +7,40 @@
|
|||||||
class StatsManager
|
class StatsManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
StatsManager();
|
StatsManager();
|
||||||
~StatsManager();
|
~StatsManager();
|
||||||
|
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The current Stage stats.
|
* @brief The current Stage stats.
|
||||||
*
|
*
|
||||||
* This is not necessarily passed stage stats if this is an Extra Stage. */
|
* This is not necessarily passed stage stats if this is an Extra Stage. */
|
||||||
StageStats m_CurStageStats;
|
StageStats m_CurStageStats;
|
||||||
vector<StageStats> m_vPlayedStageStats;
|
vector<StageStats> m_vPlayedStageStats;
|
||||||
|
|
||||||
// Only the latest 3 normal songs + passed extra stages.
|
// Only the latest 3 normal songs + passed extra stages.
|
||||||
void GetFinalEvalStageStats( StageStats& statsOut ) const;
|
void GetFinalEvalStageStats( StageStats& statsOut ) const;
|
||||||
|
|
||||||
// All stages played. Returns a ref to the private member so that
|
// All stages played. Returns a ref to the private member so that
|
||||||
// the object will remain alive while Lua is operating on it.
|
// the object will remain alive while Lua is operating on it.
|
||||||
void CalcAccumPlayedStageStats();
|
void CalcAccumPlayedStageStats();
|
||||||
StageStats& GetAccumPlayedStageStats() { return m_AccumPlayedStageStats; }
|
StageStats& GetAccumPlayedStageStats() { return m_AccumPlayedStageStats; }
|
||||||
|
|
||||||
static void CommitStatsToProfiles( const StageStats *pSS );
|
static void CommitStatsToProfiles( const StageStats *pSS );
|
||||||
|
|
||||||
void UnjoinPlayer( PlayerNumber pn );
|
void UnjoinPlayer( PlayerNumber pn );
|
||||||
void GetStepsInUse( set<Steps*> &apInUseOut ) const;
|
void GetStepsInUse( set<Steps*> &apInUseOut ) const;
|
||||||
|
|
||||||
// Lua
|
// Lua
|
||||||
void PushSelf( lua_State *L );
|
void PushSelf( lua_State *L );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void SaveUploadFile( const StageStats *pSS );
|
||||||
|
static void SavePadmissScore( const StageStats *pSS, PlayerNumber pn );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
StageStats m_AccumPlayedStageStats;
|
StageStats m_AccumPlayedStageStats;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern StatsManager* STATSMAN; // global and accessible from anywhere in our program
|
extern StatsManager* STATSMAN; // global and accessible from anywhere in our program
|
||||||
|
|||||||
@@ -7,6 +7,23 @@
|
|||||||
|
|
||||||
static const RString TEMP_MOUNT_POINT = "/@mctemptimeout/";
|
static const RString TEMP_MOUNT_POINT = "/@mctemptimeout/";
|
||||||
|
|
||||||
|
enum MemoryCardDriverType {
|
||||||
|
MemoryCardDriverType_Usb,
|
||||||
|
MemoryCardDriverType_Directory,
|
||||||
|
NUM_MemoryCardDriverType,
|
||||||
|
MemoryCardDriverType_Invalid
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *MemoryCardDriverTypeNames[] = {
|
||||||
|
"USB",
|
||||||
|
"Directory"
|
||||||
|
};
|
||||||
|
XToString(MemoryCardDriverType);
|
||||||
|
StringToX(MemoryCardDriverType);
|
||||||
|
LuaXType(MemoryCardDriverType);
|
||||||
|
|
||||||
|
Preference<MemoryCardDriverType> g_MemoryCardDriver("MemoryCardDriver", MemoryCardDriverType_Usb);
|
||||||
|
|
||||||
bool UsbStorageDevice::operator==(const UsbStorageDevice& other) const
|
bool UsbStorageDevice::operator==(const UsbStorageDevice& other) const
|
||||||
{
|
{
|
||||||
// LOG->Trace( "Comparing %d %d %d %s %s to %d %d %d %s %s",
|
// LOG->Trace( "Comparing %d %d %d %s %s to %d %d %d %s %s",
|
||||||
@@ -126,9 +143,17 @@ MemoryCardDriver *MemoryCardDriver::Create()
|
|||||||
{
|
{
|
||||||
MemoryCardDriver *ret = NULL;
|
MemoryCardDriver *ret = NULL;
|
||||||
|
|
||||||
|
switch( g_MemoryCardDriver )
|
||||||
|
{
|
||||||
|
case MemoryCardDriverType_Directory:
|
||||||
|
ret = new MemoryCardDriverThreaded_Folder;
|
||||||
|
break;
|
||||||
|
case MemoryCardDriverType_Usb:
|
||||||
#ifdef ARCH_MEMORY_CARD_DRIVER
|
#ifdef ARCH_MEMORY_CARD_DRIVER
|
||||||
ret = new ARCH_MEMORY_CARD_DRIVER;
|
ret = new ARCH_MEMORY_CARD_DRIVER;
|
||||||
#endif
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if( !ret )
|
if( !ret )
|
||||||
ret = new MemoryCardDriver_Null;
|
ret = new MemoryCardDriver_Null;
|
||||||
@@ -136,6 +161,7 @@ MemoryCardDriver *MemoryCardDriver::Create()
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (c) 2002-2004 Glenn Maynard
|
* (c) 2002-2004 Glenn Maynard
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
|
|||||||
@@ -0,0 +1,131 @@
|
|||||||
|
#include "global.h"
|
||||||
|
#include "MemoryCardDriverThreaded_Folder.h"
|
||||||
|
#include "RageLog.h"
|
||||||
|
#include "RageUtil.h"
|
||||||
|
#include "Foreach.h"
|
||||||
|
#include "PlayerNumber.h"
|
||||||
|
#include "MemoryCardManager.h"
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <bitset>
|
||||||
|
|
||||||
|
static int g_currentSerial = 0;
|
||||||
|
|
||||||
|
MemoryCardDriverThreaded_Folder::MemoryCardDriverThreaded_Folder()
|
||||||
|
{
|
||||||
|
m_LastDevices = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryCardDriverThreaded_Folder::~MemoryCardDriverThreaded_Folder()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MemoryCardDriverThreaded_Folder::FolderExists(RString path)
|
||||||
|
{
|
||||||
|
if (path.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *pathname = path.c_str();
|
||||||
|
struct stat info;
|
||||||
|
|
||||||
|
int statRC = stat( pathname, &info );
|
||||||
|
if( statRC != 0 )
|
||||||
|
{
|
||||||
|
if (errno == ENOENT) { return false; } // something along the path does not exist
|
||||||
|
if (errno == ENOTDIR) { return false; } // something in path prefix is not a dir
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( info.st_mode & S_IFDIR ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MemoryCardDriverThreaded_Folder::TestWrite( UsbStorageDevice* pDevice )
|
||||||
|
{
|
||||||
|
//TODO
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MemoryCardDriverThreaded_Folder::GetActivePlayerMask()
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
FOREACH_PlayerNumber( p )
|
||||||
|
{
|
||||||
|
const RString folder = MEMCARDMAN->m_sMemoryCardOsMountPoint[p];
|
||||||
|
|
||||||
|
if(FolderExists(folder)) {
|
||||||
|
ret |= 1 << p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MemoryCardDriverThreaded_Folder::USBStorageDevicesChanged()
|
||||||
|
{
|
||||||
|
return GetActivePlayerMask() != m_LastDevices;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemoryCardDriverThreaded_Folder::GetUSBStorageDevices( vector<UsbStorageDevice>& vDevicesOut )
|
||||||
|
{
|
||||||
|
LOG->Trace( "GetUSBStorageDevices" );
|
||||||
|
|
||||||
|
vDevicesOut.clear();
|
||||||
|
m_LastDevices = GetActivePlayerMask();
|
||||||
|
|
||||||
|
FOREACH_PlayerNumber( p )
|
||||||
|
{
|
||||||
|
if((m_LastDevices & (1 << p)) > 0){
|
||||||
|
UsbStorageDevice usbd;
|
||||||
|
usbd.sSerial = StringConversion::ToString(g_currentSerial++);
|
||||||
|
usbd.sSysPath = MEMCARDMAN->m_sMemoryCardOsMountPoint[p];
|
||||||
|
usbd.sOsMountDir = MEMCARDMAN->m_sMemoryCardOsMountPoint[p];
|
||||||
|
|
||||||
|
vDevicesOut.push_back( usbd );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MemoryCardDriverThreaded_Folder::Mount( UsbStorageDevice* pDevice )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemoryCardDriverThreaded_Folder::Unmount( UsbStorageDevice* pDevice )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (c) 2018-2019 Electromuis
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||||
|
* whom the Software is furnished to do so, provided that the above
|
||||||
|
* copyright notice(s) and this permission notice appear in all copies of
|
||||||
|
* the Software and that both the above copyright notice(s) and this
|
||||||
|
* permission notice appear in supporting documentation.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||||
|
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||||
|
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||||
|
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||||
|
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||||
|
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
#ifndef MemoryCardDriverThreaded_Folder_H
|
||||||
|
#define MemoryCardDriverThreaded_Folder_H 1
|
||||||
|
|
||||||
|
#include "MemoryCardDriver.h"
|
||||||
|
|
||||||
|
class MemoryCardDriverThreaded_Folder : public MemoryCardDriver
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MemoryCardDriverThreaded_Folder();
|
||||||
|
virtual ~MemoryCardDriverThreaded_Folder();
|
||||||
|
|
||||||
|
virtual bool Mount( UsbStorageDevice* pDevice );
|
||||||
|
virtual void Unmount( UsbStorageDevice* pDevice );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void GetUSBStorageDevices( vector<UsbStorageDevice>& vDevicesOut );
|
||||||
|
bool USBStorageDevicesChanged();
|
||||||
|
bool TestWrite( UsbStorageDevice* pDevice );
|
||||||
|
bool FolderExists(RString path);
|
||||||
|
|
||||||
|
int GetActivePlayerMask();
|
||||||
|
int m_LastDevices;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (c) 2018-2019 Electromuis
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, and/or sell copies of the Software, and to permit persons to
|
||||||
|
* whom the Software is furnished to do so, provided that the above
|
||||||
|
* copyright notice(s) and this permission notice appear in all copies of
|
||||||
|
* the Software and that both the above copyright notice(s) and this
|
||||||
|
* permission notice appear in supporting documentation.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF
|
||||||
|
* THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS
|
||||||
|
* INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT
|
||||||
|
* OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||||
|
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||||
|
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
* PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
@@ -54,6 +54,7 @@
|
|||||||
/* All use these. */
|
/* All use these. */
|
||||||
#include "LoadingWindow/LoadingWindow_Null.h"
|
#include "LoadingWindow/LoadingWindow_Null.h"
|
||||||
#include "MemoryCard/MemoryCardDriver_Null.h"
|
#include "MemoryCard/MemoryCardDriver_Null.h"
|
||||||
|
#include "MemoryCard/MemoryCardDriverThreaded_Folder.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user