Skip to content

Commit

Permalink
Merge pull request #7808 from hrydgard/savedata-screen
Browse files Browse the repository at this point in the history
Savedata management screen
  • Loading branch information
hrydgard committed Jun 12, 2015
2 parents f356b0c + 56ed0f9 commit 00e57b1
Show file tree
Hide file tree
Showing 23 changed files with 672 additions and 128 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -820,6 +820,7 @@ set(NativeAppSource
UI/OnScreenDisplay.cpp
UI/ControlMappingScreen.cpp
UI/ReportScreen.cpp
UI/SavedataScreen.cpp
UI/Store.cpp
UI/CwCheatScreen.cpp
UI/InstallZipScreen.cpp
Expand Down
2 changes: 0 additions & 2 deletions Core/HLE/sceIo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -317,8 +317,6 @@ static void __IoFreeFd(int fd, u32 &error) {
// TODO: We don't do any of that yet.
// For now, let's at least delay the callback notification.
static void __IoAsyncNotify(u64 userdata, int cyclesLate) {
PROFILE_THIS_SCOPE("io_rw");

int fd = (int) userdata;

u32 error;
Expand Down
32 changes: 25 additions & 7 deletions Core/Loaders.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -758,7 +758,7 @@ IdentifiedFileType Identify_File(FileLoader *fileLoader)
}

std::string extension = fileLoader->Extension();
if (!strcasecmp(extension.c_str(),".iso"))
if (!strcasecmp(extension.c_str(), ".iso"))
{
// may be a psx iso, they have 2352 byte sectors. You never know what some people try to open
if ((fileLoader->FileSize() % 2352) == 0)
Expand All @@ -780,26 +780,36 @@ IdentifiedFileType Identify_File(FileLoader *fileLoader)
{
return FILETYPE_PSP_ISO;
}

else if (!strcasecmp(extension.c_str(),".ppst"))
{
return FILETYPE_PPSSPP_SAVESTATE;
}

// First, check if it's a directory with an EBOOT.PBP in it.
if (fileLoader->IsDirectory()) {
std::string filename = fileLoader->Path();
if (filename.size() > 4) {
FileInfo ebootInfo;
FileInfo fileInfo;
// Check for existence of EBOOT.PBP, as required for "Directory games".
if (getFileInfo((filename + "/EBOOT.PBP").c_str(), &ebootInfo)) {
if (ebootInfo.exists) {
if (getFileInfo((filename + "/EBOOT.PBP").c_str(), &fileInfo)) {
if (fileInfo.exists) {
return FILETYPE_PSP_PBP_DIRECTORY;
}
}

// check if it's a disc directory
if (getFileInfo((filename + "/PSP_GAME").c_str(), &ebootInfo)) {
if (ebootInfo.exists) {
if (getFileInfo((filename + "/PSP_GAME").c_str(), &fileInfo)) {
if (fileInfo.exists) {
return FILETYPE_PSP_DISC_DIRECTORY;
}
}

// Not that, okay, let's guess it's a savedata directory if it has a param.sfo...
if (getFileInfo((filename + "/PARAM.SFO").c_str(), &fileInfo)) {
if (fileInfo.exists) {
return FILETYPE_PSP_SAVEDATA_DIRECTORY;
}
}
}

return FILETYPE_NORMAL_DIRECTORY;
Expand Down Expand Up @@ -990,6 +1000,14 @@ bool LoadFile(FileLoader **fileLoaderPtr, std::string *error_string) {
*error_string = "Just a directory.";
break;

case FILETYPE_PPSSPP_SAVESTATE:
*error_string = "This is a saved state, not a game."; // Actually, we could make it load it...
break;

case FILETYPE_PSP_SAVEDATA_DIRECTORY:
*error_string = "This is save data, not a game."; // Actually, we could make it load it...
break;

case FILETYPE_UNKNOWN_BIN:
case FILETYPE_UNKNOWN_ELF:
case FILETYPE_UNKNOWN:
Expand Down
3 changes: 3 additions & 0 deletions Core/Loaders.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ enum IdentifiedFileType {

FILETYPE_NORMAL_DIRECTORY,

FILETYPE_PSP_SAVEDATA_DIRECTORY,
FILETYPE_PPSSPP_SAVESTATE,

FILETYPE_UNKNOWN
};

Expand Down
2 changes: 2 additions & 0 deletions Core/System.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,8 @@ std::string GetSysDirectory(PSPDirectories directoryType) {
return g_Config.memStickDirectory + "PAUTH/";
case DIRECTORY_DUMP:
return g_Config.memStickDirectory + "PSP/SYSTEM/DUMP/";
case DIRECTORY_SAVESTATE:
return g_Config.memStickDirectory + "PSP/PPSSPP_STATE/";
// Just return the memory stick root if we run into some sort of problem.
default:
ERROR_LOG(FILESYS, "Unknown directory type.");
Expand Down
1 change: 1 addition & 0 deletions Core/System.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ enum PSPDirectories {
DIRECTORY_SAVEDATA,
DIRECTORY_PAUTH,
DIRECTORY_DUMP,
DIRECTORY_SAVESTATE,
};


Expand Down
2 changes: 1 addition & 1 deletion GPU/Software/SoftGpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ void SoftGPU::ExecuteOp(u32 op, u32 diff)
}

if (!(gstate_c.skipDrawReason & SKIPDRAW_SKIPFRAME)) {
TransformUnit::SubmitSpline(control_points, indices, sp_ucount, sp_vcount, sp_utype, sp_vtype, gstate.getPatchPrimitiveType(), gstate.vertType);
//TransformUnit::SubmitSpline(control_points, indices, sp_ucount, sp_vcount, sp_utype, sp_vtype, gstate.getPatchPrimitiveType(), gstate.vertType);
}
framebufferDirty_ = true;
DEBUG_LOG(G3D,"DL DRAW SPLINE: %i x %i, %i x %i", sp_ucount, sp_vcount, sp_utype, sp_vtype);
Expand Down
7 changes: 3 additions & 4 deletions UI/DevScreens.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,8 @@ class DevMenu : public PopupScreen {
public:
DevMenu() : PopupScreen("Dev Tools") {}

virtual void CreatePopupContents(UI::ViewGroup *parent);

virtual void dialogFinished(const Screen *dialog, DialogResult result);
void CreatePopupContents(UI::ViewGroup *parent) override;
void dialogFinished(const Screen *dialog, DialogResult result) override;

protected:
UI::EventReturn OnLogView(UI::EventParams &e);
Expand All @@ -48,7 +47,7 @@ class DevMenu : public PopupScreen {
class LogConfigScreen : public UIDialogScreenWithBackground {
public:
LogConfigScreen() {}
virtual void CreateViews();
virtual void CreateViews() override;

private:
UI::EventReturn OnToggleAll(UI::EventParams &e);
Expand Down
97 changes: 78 additions & 19 deletions UI/GameInfoCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ GameInfo::~GameInfo() {
delete fileLoader;
}

bool GameInfo::DeleteGame() {
bool GameInfo::Delete() {
switch (fileType) {
case FILETYPE_PSP_ISO:
case FILETYPE_PSP_ISO_NP:
Expand All @@ -63,9 +63,9 @@ bool GameInfo::DeleteGame() {
return true;
}
case FILETYPE_PSP_PBP_DIRECTORY:
case FILETYPE_PSP_SAVEDATA_DIRECTORY:
{
// TODO: This could be handled by Core/Util/GameManager too somehow.

const char *directoryToRemove = filePath_.c_str();
INFO_LOG(HLE, "Deleting %s", directoryToRemove);
if (!File::DeleteDirRecursively(directoryToRemove)) {
Expand All @@ -76,6 +76,12 @@ bool GameInfo::DeleteGame() {
return true;
}
case FILETYPE_PSP_ELF:
case FILETYPE_PPSSPP_SAVESTATE:
case FILETYPE_UNKNOWN_BIN:
case FILETYPE_UNKNOWN_ELF:
case FILETYPE_ARCHIVE_RAR:
case FILETYPE_ARCHIVE_ZIP:
case FILETYPE_ARCHIVE_7Z:
{
const char *fileToRemove = filePath_.c_str();
deleteFile(fileToRemove);
Expand All @@ -87,16 +93,35 @@ bool GameInfo::DeleteGame() {
}
}

static int64_t GetDirectoryRecursiveSize(std::string path) {
std::vector<FileInfo> fileInfo;
getFilesInDir(path.c_str(), &fileInfo);
int64_t sizeSum = 0;
// Note: getFileInDir does not fill in fileSize properly.
for (size_t i = 0; i < fileInfo.size(); i++) {
FileInfo finfo;
getFileInfo(fileInfo[i].fullName.c_str(), &finfo);
if (!finfo.isDirectory)
sizeSum += finfo.size;
else
sizeSum += GetDirectoryRecursiveSize(finfo.fullName);
}
return sizeSum;
}

u64 GameInfo::GetGameSizeInBytes() {
switch (fileType) {
case FILETYPE_PSP_PBP_DIRECTORY:
// TODO: Need to recurse here.
return 0;
case FILETYPE_PSP_SAVEDATA_DIRECTORY:
{
return GetDirectoryRecursiveSize(filePath_);
}
default:
return GetFileLoader()->FileSize();
}
}

// Not too meaningful if the object itself is a savedata directory...
std::vector<std::string> GameInfo::GetSaveDataDirectories() {
std::string memc = GetSysDirectory(DIRECTORY_SAVEDATA);

Expand All @@ -117,6 +142,9 @@ std::vector<std::string> GameInfo::GetSaveDataDirectories() {
}

u64 GameInfo::GetSaveDataSizeInBytes() {
if (fileType == FILETYPE_PSP_SAVEDATA_DIRECTORY || fileType == FILETYPE_PPSSPP_SAVESTATE) {
return 0;
}
std::vector<std::string> saveDataDir = GetSaveDataDirectories();

u64 totalSize = 0;
Expand All @@ -132,7 +160,7 @@ u64 GameInfo::GetSaveDataSizeInBytes() {
filesSizeInDir += finfo.size;
}
if (filesSizeInDir < 0xA00000) {
//Generally the savedata size in a dir shouldn't be more than 10MB.
// HACK: Generally the savedata size in a dir shouldn't be more than 10MB.
totalSize += filesSizeInDir;
}
filesSizeInDir = 0;
Expand All @@ -141,6 +169,9 @@ u64 GameInfo::GetSaveDataSizeInBytes() {
}

u64 GameInfo::GetInstallDataSizeInBytes() {
if (fileType == FILETYPE_PSP_SAVEDATA_DIRECTORY || fileType == FILETYPE_PPSSPP_SAVESTATE) {
return 0;
}
std::vector<std::string> saveDataDir = GetSaveDataDirectories();

u64 totalSize = 0;
Expand All @@ -156,7 +187,7 @@ u64 GameInfo::GetInstallDataSizeInBytes() {
filesSizeInDir += finfo.size;
}
if (filesSizeInDir >= 0xA00000) {
// Generally the savedata size in a dir shouldn't be more than 10MB.
// HACK: Generally the savedata size in a dir shouldn't be more than 10MB.
// This is probably GameInstall data.
totalSize += filesSizeInDir;
}
Expand Down Expand Up @@ -371,6 +402,33 @@ class GameInfoWorkItem : public PrioritizedWorkQueueItem {
}
break;

case FILETYPE_PSP_SAVEDATA_DIRECTORY:
{
SequentialHandleAllocator handles;
VirtualDiscFileSystem umd(&handles, gamePath_.c_str());

// Alright, let's fetch the PARAM.SFO.
std::string paramSFOcontents;
if (ReadFileToString(&umd, "/PARAM.SFO", &paramSFOcontents, 0)) {
lock_guard lock(info_->lock);
info_->paramSFO.ReadSFO((const u8 *)paramSFOcontents.data(), paramSFOcontents.size());
info_->ParseParamSFO();
}

ReadFileToString(&umd, "/ICON0.PNG", &info_->iconTextureData, &info_->lock);
info_->iconDataLoaded = true;
if (info_->wantFlags & GAMEINFO_WANTBG) {
ReadFileToString(&umd, "/PIC1.PNG", &info_->pic1TextureData, &info_->lock);
info_->pic1DataLoaded = true;
}
break;
}

case FILETYPE_PPSSPP_SAVESTATE:
{
break;
}

case FILETYPE_PSP_DISC_DIRECTORY:
{
info_->fileType = FILETYPE_PSP_ISO;
Expand Down Expand Up @@ -399,6 +457,7 @@ class GameInfoWorkItem : public PrioritizedWorkQueueItem {
}
break;
}

case FILETYPE_PSP_ISO:
case FILETYPE_PSP_ISO_NP:
{
Expand Down Expand Up @@ -517,7 +576,6 @@ class GameInfoWorkItem : public PrioritizedWorkQueueItem {
};



GameInfoCache::~GameInfoCache() {
Clear();
}
Expand All @@ -531,18 +589,6 @@ void GameInfoCache::Shutdown() {
StopProcessingWorkQueue(gameInfoWQ_);
}

void GameInfoCache::Save() {
// TODO
}

void GameInfoCache::Load() {
// TODO
}

void GameInfoCache::Decimate() {
// TODO
}

void GameInfoCache::Clear() {
if (gameInfoWQ_)
gameInfoWQ_->Flush();
Expand Down Expand Up @@ -610,6 +656,19 @@ void GameInfoCache::FlushBGs() {
}
}

void GameInfoCache::PurgeType(IdentifiedFileType fileType) {
if (gameInfoWQ_)
gameInfoWQ_->Flush();
restart:
for (auto iter = info_.begin(); iter != info_.end(); iter++) {
if (iter->second->fileType == fileType) {
info_.erase(iter);
goto restart;
}
}
}


// Runs on the main thread.
GameInfo *GameInfoCache::GetInfo(Thin3DContext *thin3d, const std::string &gamePath, int wantFlags) {
GameInfo *info = 0;
Expand Down
15 changes: 7 additions & 8 deletions UI/GameInfoCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ class Thin3DTexture;
// does on the PSP, namely checking for and deleting savedata, and similar things.
// Only cares about games that are installed on the current device.

// A GameInfo object can also represent a piece of savedata.

// Guessed from GameID, not necessarily accurate
enum GameRegion {
GAMEREGION_JAPAN,
Expand Down Expand Up @@ -94,14 +96,15 @@ class GameInfo {
public:
GameInfo()
: disc_total(0), disc_number(0), region(-1), fileType(FILETYPE_UNKNOWN), paramSFOLoaded(false),
iconTexture(NULL), pic0Texture(NULL), pic1Texture(NULL), wantFlags(0),
timeIconWasLoaded(0.0), timePic0WasLoaded(0.0), timePic1WasLoaded(0.0),
iconTexture(nullptr), pic0Texture(nullptr), pic1Texture(nullptr), wantFlags(0),
lastAccessedTime(0.0), timeIconWasLoaded(0.0), timePic0WasLoaded(0.0), timePic1WasLoaded(0.0),
gameSize(0), saveDataSize(0), installDataSize(0), fileLoader(nullptr) {}
~GameInfo();

bool DeleteGame(); // Better be sure what you're doing when calling this.
bool Delete(); // Better be sure what you're doing when calling this.
bool DeleteAllSaveData();
bool LoadFromPath(const std::string &gamePath);

FileLoader *GetFileLoader();
void DisposeFileLoader();

Expand Down Expand Up @@ -174,19 +177,15 @@ class GameInfoCache {
void Init();
void Shutdown();
void Clear();
void PurgeType(IdentifiedFileType fileType);

// All data in GameInfo including iconTexture may be zero the first time you call this
// but filled in later asynchronously in the background. So keep calling this,
// redrawing the UI often. Only set flags to GAMEINFO_WANTBG or WANTSND if you really want them
// because they're big. bgTextures and sound may be discarded over time as well.
GameInfo *GetInfo(Thin3DContext *thin3d, const std::string &gamePath, int wantFlags);
void Decimate(); // Deletes old info.
void FlushBGs(); // Gets rid of all BG textures. Also gets rid of bg sounds.

// TODO - save cache between sessions
void Save();
void Load();

PrioritizedWorkQueue *WorkQueue() { return gameInfoWQ_; }

private:
Expand Down
2 changes: 1 addition & 1 deletion UI/GameScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ UI::EventReturn GameScreen::OnDeleteGame(UI::EventParams &e) {
void GameScreen::CallbackDeleteGame(bool yes) {
GameInfo *info = g_gameInfoCache.GetInfo(NULL, gamePath_, 0);
if (yes) {
info->DeleteGame();
info->Delete();
g_gameInfoCache.Clear();
screenManager()->switchScreen(new MainScreen());
}
Expand Down
Loading

0 comments on commit 00e57b1

Please sign in to comment.