CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/Core/HW/MemoryStick.cpp
Views: 1401
// Copyright (c) 2012- PPSSPP Project.12// This program is free software: you can redistribute it and/or modify3// it under the terms of the GNU General Public License as published by4// the Free Software Foundation, version 2.0 or later versions.56// This program is distributed in the hope that it will be useful,7// but WITHOUT ANY WARRANTY; without even the implied warranty of8// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the9// GNU General Public License 2.0 for more details.1011// A copy of the GPL 2.0 should have been included with the program.12// If not, see http://www.gnu.org/licenses/1314// Official git repository and contact information can be found at15// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.1617#include <algorithm>18#include <condition_variable>19#include <mutex>20#include <thread>2122#include "Common/Serialize/Serializer.h"23#include "Common/Serialize/SerializeFuncs.h"24#include "Common/Thread/ThreadUtil.h"25#include "Core/Config.h"26#include "Core/CoreTiming.h"27#include "Core/Compatibility.h"28#include "Core/FileSystems/MetaFileSystem.h"29#include "Core/HW/MemoryStick.h"30#include "Core/System.h"3132// MS and FatMS states.33static MemStickState memStickState;34static MemStickFatState memStickFatState;35static bool memStickNeedsAssign = false;36static u64 memStickInsertedAt = 0;37static uint64_t memstickInitialFree = 0;38static uint64_t memstickCurrentUse = 0;39static bool memstickCurrentUseValid = false;4041enum FreeCalcStatus {42NONE,43RUNNING,44DONE,45CLEANED_UP,46};4748static std::thread freeCalcThread;49static std::condition_variable freeCalcCond;50static std::mutex freeCalcMutex;51static FreeCalcStatus freeCalcStatus = FreeCalcStatus::NONE;5253static const u64 normalMemstickSize = 9ULL * 1024 * 1024 * 1024;54static const u64 smallMemstickSize = 1ULL * 1024 * 1024 * 1024;5556void MemoryStick_DoState(PointerWrap &p) {57auto s = p.Section("MemoryStick", 1, 5);58if (!s)59return;6061Do(p, memStickState);62Do(p, memStickFatState);63if (s >= 4) {64// Do nothing.65} else if (s >= 2) {66// Really no point in storing the memstick size.67u64 memStickSize = normalMemstickSize;68Do(p, memStickSize);69}70if (s >= 5) {71Do(p, memstickInitialFree);72}7374if (s >= 3) {75Do(p, memStickNeedsAssign);76Do(p, memStickInsertedAt);77}78}7980MemStickState MemoryStick_State() {81return memStickState;82}8384MemStickFatState MemoryStick_FatState() {85if (memStickNeedsAssign && CoreTiming::GetTicks() > memStickInsertedAt + msToCycles(500)) {86// It's been long enough for us to be done mounting the memory stick.87memStickFatState = PSP_FAT_MEMORYSTICK_STATE_ASSIGNED;88memStickNeedsAssign = false;89}90return memStickFatState;91}9293u64 MemoryStick_SectorSize() {94return 32 * 1024; // 32KB95}9697static void MemoryStick_CalcInitialFree() {98std::unique_lock<std::mutex> guard(freeCalcMutex);99freeCalcStatus = FreeCalcStatus::RUNNING;100freeCalcThread = std::thread([] {101SetCurrentThreadName("CalcInitialFree");102103AndroidJNIThreadContext jniContext;104105memstickInitialFree = pspFileSystem.FreeSpace("ms0:/") + pspFileSystem.ComputeRecursiveDirectorySize("ms0:/PSP/SAVEDATA/");106107std::unique_lock<std::mutex> guard(freeCalcMutex);108freeCalcStatus = FreeCalcStatus::DONE;109freeCalcCond.notify_all();110});111}112113static void MemoryStick_WaitInitialFree() {114std::unique_lock<std::mutex> guard(freeCalcMutex);115while (freeCalcStatus == FreeCalcStatus::RUNNING) {116freeCalcCond.wait(guard);117}118if (freeCalcStatus == FreeCalcStatus::DONE)119freeCalcThread.join();120freeCalcStatus = FreeCalcStatus::CLEANED_UP;121}122123u64 MemoryStick_FreeSpace() {124MemoryStick_WaitInitialFree();125126const CompatFlags &flags = PSP_CoreParameter().compat.flags();127u64 realFreeSpace = pspFileSystem.FreeSpace("ms0:/");128129// Cap the memory stick size to avoid math errors when old games get sizes that were130// not planned for back then (even though 2GB cards were available.)131// We have a compat setting to make it even smaller for Harry Potter : Goblet of Fire, see #13266.132const u64 memStickSize = flags.ReportSmallMemstick ? smallMemstickSize : (u64)g_Config.iMemStickSizeGB * 1024 * 1024 * 1024;133134// Assume the memory stick is only used to store savedata.135if (!memstickCurrentUseValid) {136memstickCurrentUse = pspFileSystem.ComputeRecursiveDirectorySize("ms0:/PSP/SAVEDATA/");137memstickCurrentUseValid = true;138}139140u64 simulatedFreeSpace = 0;141if (memstickCurrentUse < memStickSize) {142simulatedFreeSpace = memStickSize - memstickCurrentUse;143} else if (flags.ReportSmallMemstick) {144// There's more stuff in the memstick than the size we report.145// This doesn't work, so we'll just have to lie. Not sure what the best way is.146simulatedFreeSpace = smallMemstickSize / 2; // just pick a value.147}148if (flags.MemstickFixedFree) {149// Assassin's Creed: Bloodlines fails to save if free space changes incorrectly during game.150realFreeSpace = 0;151if (memstickCurrentUse <= memstickInitialFree) {152realFreeSpace = memstickInitialFree - memstickCurrentUse;153}154}155156return std::min(simulatedFreeSpace, realFreeSpace);157}158159void MemoryStick_NotifyWrite() {160memstickCurrentUseValid = false;161}162163void MemoryStick_SetFatState(MemStickFatState state) {164memStickFatState = state;165memStickNeedsAssign = false;166}167168void MemoryStick_SetState(MemStickState state) {169if (memStickState == state) {170return;171}172173memStickState = state;174175// If removed, we unmount. Otherwise, mounting is delayed.176if (state == PSP_MEMORYSTICK_STATE_NOT_INSERTED) {177MemoryStick_SetFatState(PSP_FAT_MEMORYSTICK_STATE_UNASSIGNED);178} else {179memStickInsertedAt = CoreTiming::GetTicks();180memStickNeedsAssign = true;181}182}183184void MemoryStick_Init() {185if (g_Config.bMemStickInserted) {186memStickState = PSP_MEMORYSTICK_STATE_INSERTED;187memStickFatState = PSP_FAT_MEMORYSTICK_STATE_ASSIGNED;188} else {189memStickState = PSP_MEMORYSTICK_STATE_NOT_INSERTED;190memStickFatState = PSP_FAT_MEMORYSTICK_STATE_UNASSIGNED;191}192193memStickNeedsAssign = false;194MemoryStick_CalcInitialFree();195}196197void MemoryStick_Shutdown() {198MemoryStick_WaitInitialFree();199}200201202