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:
electromuis
2019-01-19 08:07:13 -08:00
committed by Colby Klein
parent d395028bd4
commit 021d494157
9 changed files with 496 additions and 90 deletions
+2
View File
@@ -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)
+6 -1
View File
@@ -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() ) );
@@ -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 )
+2
View File
@@ -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.
+188 -4
View File
@@ -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,7 +245,13 @@ 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 // Save recent scores
auto_ptr<XNode> xml( new XNode("Stats") ); auto_ptr<XNode> xml( new XNode("Stats") );
xml->AppendChild( "MachineGuid", PROFILEMAN->GetMachineProfile()->m_sGuid ); xml->AppendChild( "MachineGuid", PROFILEMAN->GetMachineProfile()->m_sGuid );
@@ -278,9 +295,176 @@ void StatsManager::CommitStatsToProfiles( const StageStats *pSS )
RString sStatsXmlSigFile = fn + SIGNATURE_APPEND; RString sStatsXmlSigFile = fn + SIGNATURE_APPEND;
CryptManager::SignFileToFile(fn, sStatsXmlSigFile); CryptManager::SignFileToFile(fn, sStatsXmlSigFile);
} }
} }
//FileCopy( "Data/TempTestGroups.xml", "Save/Upload/data.xml" ); 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 )
+4
View File
@@ -35,6 +35,10 @@ public:
// 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;
}; };
+26
View File
@@ -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.
*/
+1
View File
@@ -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