Savestates: Add quicksave/quickload. Add Android UI for savestates. All single slot for now.

This commit is contained in:
Henrik Rydgard committed 2013-01-02 21:05:02 +01:00
1 parent 28684a3ba2
commit 883f61e3dd
25 files changed
+267 -91

No files matched your search

+8
View File
@@ -376,3 +376,11 @@ std::string UriEncode(const std::string & sSrc)
delete [] pStart;
return sResult;
}
bool StringEndsWith(std::string const &fullString, std::string const &ending) {
if (fullString.length() >= ending.length()) {
return (0 == fullString.compare (fullString.length() - ending.length(), ending.length(), ending));
} else {
return false;
}
}
+2
View File
@@ -129,4 +129,6 @@ std::string ReplaceAll(std::string result, const std::string& src, const std::st
std::string UriDecode(const std::string & sSrc);
std::string UriEncode(const std::string & sSrc);
bool StringEndsWith(std::string const &fullString, std::string const &ending);
#endif // _STRINGUTIL_H_
+1 -2
View File
@@ -59,7 +59,7 @@ void CConfig::Load(const char *iniFileName)
graphics->Get("DisplayFramebuffer", &bDisplayFramebuffer, false);
graphics->Get("WindowZoom", &iWindowZoom, 1);
graphics->Get("BufferedRendering", &bBufferedRendering, true);
graphics->Get("HardwareTransform", &bHardwareTransform, false);
graphics->Get("HardwareTransform", &bHardwareTransform, true);
graphics->Get("LinearFiltering", &bLinearFiltering, false);
IniFile::Section *sound = iniFile.GetOrCreateSection("Sound");
@@ -69,7 +69,6 @@ void CConfig::Load(const char *iniFileName)
control->Get("ShowStick", &bShowAnalogStick, false);
control->Get("ShowTouchControls", &bShowTouchControls, true);
// Ephemeral settings
bDrawWireframe = false;
}
+7 -7
View File
@@ -226,8 +226,8 @@ bool SavedataParam::Save(SceUtilitySavedataParam* param, int saveId)
PSPFileInfo sfoInfo = pspFileSystem.GetFileInfo(sfopath);
if(sfoInfo.exists) // Read old sfo if exist
{
u8 *sfoData = new u8[sfoInfo.size];
size_t sfoSize = sfoInfo.size;
u8 *sfoData = new u8[(size_t)sfoInfo.size];
size_t sfoSize = (size_t)sfoInfo.size;
if(ReadPSPFile(sfopath,sfoData,sfoSize))
{
sfoFile.ReadSFO(sfoData,sfoSize);
@@ -475,7 +475,7 @@ bool SavedataParam::GetList(SceUtilitySavedataParam *param)
if (Memory::IsValidAddress(outputBuffer))
{
std::string searchString = GetGameName(param)+GetSaveName(param);
for(int i = 0; i < allDir.size() && i < maxFile; i++)
for (size_t i = 0; i < allDir.size() && i < maxFile; i++)
{
std::string dirName = allDir[i].name;
if(PSPMatch(dirName, searchString))
@@ -484,7 +484,7 @@ bool SavedataParam::GetList(SceUtilitySavedataParam *param)
}
}
for(int i = 0; i < validDir.size(); i++)
for (size_t i = 0; i < validDir.size(); i++)
{
u32 baseAddr = outputBuffer + (i*72);
Memory::Write_U32(0x11FF,baseAddr + 0); // mode
@@ -514,7 +514,7 @@ bool SavedataParam::GetFilesList(SceUtilitySavedataParam *param)
}
u32 dataAddr = param->fileListAddr;
if(!Memory::IsValidAddress(dataAddr))
if (!Memory::IsValidAddress(dataAddr))
return false;
// TODO : Need to be checked against more game
@@ -524,7 +524,7 @@ bool SavedataParam::GetFilesList(SceUtilitySavedataParam *param)
//for Valkyria2, dataAddr+0 and dataAddr+12 has "5" for 5 files
int numFiles = Memory::Read_U32(dataAddr+12);
int foundFiles = 0;
for(int i = 0; i < numFiles; i++)
for (int i = 0; i < numFiles; i++)
{
// for each file (80 bytes):
// u32 mode, u32 ??, u64 size, u64 ctime, u64 ??, u64 atime, u64 ???, u64 mtime, u64 ???
@@ -535,7 +535,7 @@ bool SavedataParam::GetFilesList(SceUtilitySavedataParam *param)
strncpy(fileName, Memory::GetCharPointer(curFileInfoAddr + 64),16);
std::string filePath = savePath + GetGameName(param) + GetSaveName(param) + "/" + fileName;
PSPFileInfo info = pspFileSystem.GetFileInfo(filePath);
if(info.exists)
if (info.exists)
{
Memory::Write_U32(0x21FF, curFileInfoAddr+0);
Memory::Write_U64(info.size, curFileInfoAddr+8);
+7 -7
View File
@@ -147,7 +147,7 @@ bool ParamSFOData::WriteSFO(u8 **paramsfo, size_t *size)
total_size += sizeof(Header);
// Get size info
for(std::map<std::string,ValueData>::iterator it = values.begin(); it != values.end(); it++)
for (std::map<std::string,ValueData>::iterator it = values.begin(); it != values.end(); it++)
{
key_size += it->first.size()+1;
data_size += it->second.max_size;
@@ -168,29 +168,29 @@ bool ParamSFOData::WriteSFO(u8 **paramsfo, size_t *size)
u8* data = new u8[total_size];
*paramsfo = data;
memset(data,0,total_size);
memcpy(data,&header,sizeof(Header));
memset(data, 0, total_size);
memcpy(data, &header, sizeof(Header));
// Now fill
IndexTable *index_ptr = (IndexTable*)(data + sizeof(Header));
u8* key_ptr = data + header.key_table_start;
u8* data_ptr = data + header.data_table_start;
for(std::map<std::string,ValueData>::iterator it = values.begin(); it != values.end(); it++)
for (std::map<std::string,ValueData>::iterator it = values.begin(); it != values.end(); it++)
{
u16 offset = (u16)(key_ptr - (data+header.key_table_start));
index_ptr->key_table_offset = offset;
offset = (u16)(data_ptr - (data+header.data_table_start));
index_ptr->data_table_offset = offset;
index_ptr->param_max_len = it->second.max_size;
if(it->second.type == VT_INT)
if (it->second.type == VT_INT)
{
index_ptr->param_fmt = 0x0404;
index_ptr->param_len = 4;
*(int*)data_ptr = it->second.i_value;
}
else if(it->second.type == VT_UTF8_SPE)
else if (it->second.type == VT_UTF8_SPE)
{
index_ptr->param_fmt = 0x0004;
index_ptr->param_len = it->second.u_size;
@@ -198,7 +198,7 @@ bool ParamSFOData::WriteSFO(u8 **paramsfo, size_t *size)
memset(data_ptr,0,index_ptr->param_max_len);
memcpy(data_ptr,it->second.u_value,index_ptr->param_len);
}
else if(it->second.type == VT_UTF8)
else if (it->second.type == VT_UTF8)
{
index_ptr->param_fmt = 0x0204;
index_ptr->param_len = it->second.s_value.size()+1;
+2 -1
View File
@@ -33,14 +33,15 @@ public:
bool ReadSFO(const u8 *paramsfo, size_t size);
bool WriteSFO(u8 **paramsfo, size_t *size);
private:
private:
enum ValueType
{
VT_INT,
VT_UTF8,
VT_UTF8_SPE // raw data in u8
};
class ValueData
{
public:
+13 -9
View File
@@ -38,28 +38,32 @@ public:
class CISOFileBlockDevice : public BlockDevice
{
public:
CISOFileBlockDevice(std::string _filename);
~CISOFileBlockDevice();
bool ReadBlock(int blockNumber, u8 *outPtr);
int GetNumBlocks() { return numBlocks;}
private:
std::string filename;
FILE *f;
u32 *index;
int indexShift;
u32 blockSize;
int numBlocks;
public:
CISOFileBlockDevice(std::string _filename);
~CISOFileBlockDevice();
bool ReadBlock(int blockNumber, u8 *outPtr);
int GetNumBlocks() { return numBlocks;}
};
class FileBlockDevice : public BlockDevice
{
std::string filename;
FILE *f;
size_t filesize;
public:
FileBlockDevice(std::string _filename);
~FileBlockDevice();
bool ReadBlock(int blockNumber, u8 *outPtr);
int GetNumBlocks() {return (int)(filesize/GetBlockSize());}
int GetNumBlocks() {return (int)(filesize / GetBlockSize());}
private:
std::string filename;
FILE *f;
size_t filesize;
};
+5
View File
@@ -510,6 +510,11 @@ PSPFileInfo DirectoryFileSystem::GetFileInfo(std::string filename) {
return x;
}
bool DirectoryFileSystem::GetHostPath(const std::string &inpath, std::string &outpath) {
outpath = GetLocalPath(inpath);
return true;
}
std::vector<PSPFileInfo> DirectoryFileSystem::GetDirListing(std::string path) {
std::vector<PSPFileInfo> myVector;
#ifdef _WIN32
+1
View File
@@ -67,6 +67,7 @@ public:
bool RmDir(const std::string &dirname);
bool RenameFile(const std::string &from, const std::string &to);
bool DeleteFile(const std::string &filename);
bool GetHostPath(const std::string &inpath, std::string &outpath);
private:
struct OpenFileEntry {
+2
View File
@@ -103,6 +103,7 @@ public:
virtual bool RmDir(const std::string &dirname) = 0;
virtual bool RenameFile(const std::string &from, const std::string &to) = 0;
virtual bool DeleteFile(const std::string &filename) = 0;
virtual bool GetHostPath(const std::string &inpath, std::string &outpath) = 0;
};
@@ -122,6 +123,7 @@ public:
virtual bool RmDir(const std::string &dirname) {return false;}
virtual bool RenameFile(const std::string &from, const std::string &to) {return false;}
virtual bool DeleteFile(const std::string &filename) {return false;}
virtual bool GetHostPath(const std::string &inpath, std::string &outpath) {return false;}
};
+20 -18
View File
@@ -27,6 +27,26 @@
class ISOFileSystem : public IFileSystem
{
public:
ISOFileSystem(IHandleAllocator *_hAlloc, BlockDevice *_blockDevice);
~ISOFileSystem();
void DoState(PointerWrap &p);
std::vector<PSPFileInfo> GetDirListing(std::string path);
u32 OpenFile(std::string filename, FileAccess access);
void CloseFile(u32 handle);
size_t ReadFile(u32 handle, u8 *pointer, s64 size);
size_t SeekFile(u32 handle, s32 position, FileMove type);
PSPFileInfo GetFileInfo(std::string filename);
bool OwnsHandle(u32 handle);
size_t WriteFile(u32 handle, const u8 *pointer, s64 size);
bool GetHostPath(const std::string &inpath, std::string &outpath) {return false;}
virtual bool MkDir(const std::string &dirname) {return false;}
virtual bool RmDir(const std::string &dirname) {return false;}
virtual bool RenameFile(const std::string &from, const std::string &to) {return false;}
virtual bool DeleteFile(const std::string &filename) {return false;}
private:
struct TreeEntry
{
TreeEntry(){}
@@ -69,22 +89,4 @@ class ISOFileSystem : public IFileSystem
void ReadDirectory(u32 startsector, u32 dirsize, TreeEntry *root);
TreeEntry *GetFromPath(std::string path, bool catchError=true);
std::string EntryFullPath(TreeEntry *e);
public:
ISOFileSystem(IHandleAllocator *_hAlloc, BlockDevice *_blockDevice);
~ISOFileSystem();
void DoState(PointerWrap &p);
std::vector<PSPFileInfo> GetDirListing(std::string path);
u32 OpenFile(std::string filename, FileAccess access);
void CloseFile(u32 handle);
size_t ReadFile(u32 handle, u8 *pointer, s64 size);
size_t WriteFile(u32 handle, const u8 *pointer, s64 size);
size_t SeekFile(u32 handle, s32 position, FileMove type);
PSPFileInfo GetFileInfo(std::string filename);
bool OwnsHandle(u32 handle);
virtual bool MkDir(const std::string &dirname) {return false;}
virtual bool RmDir(const std::string &dirname) {return false;}
virtual bool RenameFile(const std::string &from, const std::string &to) {return false;}
virtual bool DeleteFile(const std::string &filename) {return false;}
};
+9 -7
View File
@@ -16,6 +16,7 @@
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include <set>
#include "Common/StringUtil.h"
#include "MetaFileSystem.h"
static bool ApplyPathStringToComponentsVector(std::vector<std::string> &vector, const std::string &pathString)
@@ -251,14 +252,15 @@ PSPFileInfo MetaFileSystem::GetFileInfo(std::string filename)
}
}
//TODO: Not sure where this should live. Seems a bit wrong putting it in common
bool stringEndsWith (std::string const &fullString, std::string const &ending)
bool MetaFileSystem::GetHostPath(const std::string &inpath, std::string &outpath)
{
if (fullString.length() >= ending.length()) {
return (0 == fullString.compare (fullString.length() - ending.length(), ending.length(), ending));
} else {
return false;
}
std::string of;
IFileSystem *system;
if (MapFilePath(inpath, of, &system)) {
return system->GetHostPath(of, outpath);
} else {
return false;
}
}
std::vector<PSPFileInfo> MetaFileSystem::GetDirListing(std::string path)
+3
View File
@@ -41,6 +41,9 @@ public:
IFileSystem *GetHandleOwner(u32 handle);
bool MapFilePath(const std::string &inpath, std::string &outpath, IFileSystem **system);
// Only possible if a file system is a DirectoryFileSystem or similar.
bool GetHostPath(const std::string &inpath, std::string &outpath);
std::vector<PSPFileInfo> GetDirListing(std::string path);
u32 OpenFile(std::string filename, FileAccess access);
void CloseFile(u32 handle);
+1 -1
View File
@@ -78,7 +78,6 @@ void __KernelInit()
return;
}
SaveState::Init();
__KernelTimeInit();
__InterruptsInit();
__KernelMemoryInit();
@@ -101,6 +100,7 @@ void __KernelInit()
__ImposeInit();
__UsbInit();
__FontInit();
SaveState::Init(); // Must be after IO, as it may create a directory
// "Internal" PSP libraries
__PPGeInit();
+2 -3
View File
@@ -77,11 +77,10 @@ bool Load_PSP_ISO(const char *filename, std::string *error_string)
u32 fd = pspFileSystem.OpenFile(sfoPath, FILEACCESS_READ);
pspFileSystem.ReadFile(fd, paramsfo, fileInfo.size);
pspFileSystem.CloseFile(fd);
ParamSFOData data;
if (data.ReadSFO(paramsfo, (size_t)fileInfo.size))
if (g_paramSFO.ReadSFO(paramsfo, (size_t)fileInfo.size))
{
char title[1024];
sprintf(title, "%s : %s", data.GetValueString("DISC_ID").c_str(), data.GetValueString("TITLE").c_str());
sprintf(title, "%s : %s", g_paramSFO.GetValueString("DISC_ID").c_str(), g_paramSFO.GetValueString("TITLE").c_str());
INFO_LOG(LOADER, "%s", title);
host->SetWindowTitle(title);
}
+88 -10
View File
@@ -16,6 +16,7 @@
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "../Common/StdMutex.h"
#include "../Common/FileUtil.h"
#include <vector>
#include "SaveState.h"
@@ -45,14 +46,15 @@ namespace SaveState
struct Operation
{
Operation(OperationType t, const std::string &f, Callback cb)
: type(t), filename(f), callback(cb)
Operation(OperationType t, const std::string &f, Callback cb, void *cbUserData_)
: type(t), filename(f), callback(cb), cbUserData(cbUserData_)
{
}
OperationType type;
std::string filename;
Callback callback;
void *cbUserData;
};
static int timer;
@@ -61,7 +63,6 @@ namespace SaveState
void Process(u64 userdata, int cyclesLate);
// This is where the magic happens.
void SaveStart::DoState(PointerWrap &p)
{
// Gotta do CoreTiming first since we'll restore into it.
@@ -96,19 +97,94 @@ namespace SaveState
CoreTiming::ScheduleEvent_Threadsafe(0, timer);
}
void Load(const std::string &filename, Callback callback)
void Load(const std::string &filename, Callback callback, void *cbUserData)
{
Enqueue(Operation(SAVESTATE_LOAD, filename, callback));
Enqueue(Operation(SAVESTATE_LOAD, filename, callback, cbUserData));
}
void Save(const std::string &filename, Callback callback)
void Save(const std::string &filename, Callback callback, void *cbUserData)
{
Enqueue(Operation(SAVESTATE_SAVE, filename, callback));
Enqueue(Operation(SAVESTATE_SAVE, filename, callback, cbUserData));
}
void Verify(Callback callback)
// Slot utilities
std::string GenerateSaveSlotFilename(int slot)
{
Enqueue(Operation(SAVESTATE_VERIFY, std::string(""), callback));
char discID[256];
char temp[256];
sprintf(discID, "%s_%s",
g_paramSFO.GetValueString("DISC_ID").c_str(),
g_paramSFO.GetValueString("DISC_VERSION").c_str());
sprintf(temp, "ms0:/PSP/PPSSPP_STATE/%s_%i.ppst", discID, slot);
std::string hostPath;
if (pspFileSystem.GetHostPath(std::string(temp), hostPath)) {
return hostPath;
} else {
return "";
}
}
void LoadSlot(int slot, Callback callback, void *cbUserData)
{
std::string fn = GenerateSaveSlotFilename(slot);
if (!fn.empty())
Load(fn, callback, cbUserData);
else
(*callback)(false, cbUserData);
}
void SaveSlot(int slot, Callback callback, void *cbUserData)
{
std::string fn = GenerateSaveSlotFilename(slot);
if (!fn.empty())
Save(fn, callback, cbUserData);
else
(*callback)(false, cbUserData);
}
void HasSaveInSlot(int slot)
{
std::string fn = GenerateSaveSlotFilename(slot);
}
bool operator < (const tm &t1, const tm &t2) {
if (t1.tm_year < t2.tm_year) return true;
if (t1.tm_year > t2.tm_year) return false;
if (t1.tm_mon < t2.tm_mon) return true;
if (t1.tm_mon > t2.tm_mon) return false;
if (t1.tm_mday < t2.tm_mday) return true;
if (t1.tm_mday > t2.tm_mday) return false;
if (t1.tm_hour < t2.tm_hour) return true;
if (t1.tm_hour > t2.tm_hour) return false;
if (t1.tm_min < t2.tm_min) return true;
if (t1.tm_min > t2.tm_min) return false;
if (t1.tm_sec < t2.tm_sec) return true;
if (t1.tm_sec > t2.tm_sec) return false;
return false;
}
int GetMostRecentSaveSlot() {
int newestSlot = -1;
tm newestDate = {0};
for (int i = 0; i < SAVESTATESLOTS; i++) {
std::string fn = GenerateSaveSlotFilename(i);
if (File::Exists(fn)) {
tm time = File::GetModifTime(fn);
if (newestDate < time) {
newestDate = time;
newestSlot = i;
}
}
}
return newestSlot;
}
void Verify(Callback callback, void *cbUserData)
{
Enqueue(Operation(SAVESTATE_VERIFY, std::string(""), callback, cbUserData));
}
std::vector<Operation> Flush()
@@ -164,12 +240,14 @@ namespace SaveState
}
if (op.callback != NULL)
op.callback(result);
op.callback(result, op.cbUserData);
}
}
void Init()
{
timer = CoreTiming::RegisterEvent("SaveState", Process);
// Make sure there's a directory for save slots
pspFileSystem.MkDir("ms0:/PSP/PPSSPP_STATE");
}
}
+12 -4
View File
@@ -20,20 +20,28 @@
namespace SaveState
{
typedef void (*Callback)(bool status);
typedef void (*Callback)(bool status, void *cbUserData);
// TODO: Better place for this?
const int REVISION = 1;
const int SAVESTATESLOTS = 4;
void Init();
void SaveSlot(int slot, Callback callback, void *cbUserData = 0);
void LoadSlot(int slot, Callback callback, void *cbUserData = 0);
void HasSaveInSlot(int slot);
int GetNewestSlot();
// Load the specified file into the current state (async.)
// Warning: callback will be called on a different thread.
void Load(const std::string &filename, Callback callback = NULL);
void Load(const std::string &filename, Callback callback = 0, void *cbUserData = 0);
// Save the current state to the specified file (async.)
// Warning: callback will be called on a different thread.
void Save(const std::string &filename, Callback callback = NULL);
void Save(const std::string &filename, Callback callback = 0, void *cbUserData = 0);
// For testing / automated tests. Runs a save state verification pass (async.)
// Warning: callback will be called on a different thread.
void Verify(Callback callback = NULL);
void Verify(Callback callback = 0, void *cbUserData = 0);
};
+2 -2
View File
@@ -37,10 +37,10 @@
#include "CoreParameter.h"
#include "FileSystems/MetaFileSystem.h"
#include "Loaders.h"
#include "ELF/ParamSFO.h"
MetaFileSystem pspFileSystem;
ParamSFOData g_paramSFO;
static CoreParameter coreParameter;
bool PSP_Init(const CoreParameter &coreParam, std::string *error_string)
+2
View File
@@ -21,8 +21,10 @@
#include "MemMap.h"
#include "FileSystems/MetaFileSystem.h"
#include "CoreParameter.h"
#include "ELF/ParamSFO.h"
extern MetaFileSystem pspFileSystem;
extern ParamSFOData g_paramSFO;
bool PSP_Init(const CoreParameter &coreParam, std::string *error_string);
bool PSP_IsInited();
+33 -5
View File
@@ -312,7 +312,7 @@ namespace MainWindow
UpdateMenus();
break;
case ID_FILE_LOADSTATE:
case ID_FILE_LOADSTATEFILE:
if (g_State.bEmuThreadStarted)
{
nextState = Core_IsStepping() ? CORE_STEPPING : CORE_RUNNING;
@@ -327,7 +327,7 @@ namespace MainWindow
}
break;
case ID_FILE_SAVESTATE:
case ID_FILE_SAVESTATEFILE:
if (g_State.bEmuThreadStarted)
{
nextState = Core_IsStepping() ? CORE_STEPPING : CORE_RUNNING;
@@ -342,6 +342,32 @@ namespace MainWindow
}
break;
// TODO: Add UI for multiple slots
case ID_FILE_QUICKLOADSTATE:
if (g_State.bEmuThreadStarted)
{
nextState = Core_IsStepping() ? CORE_STEPPING : CORE_RUNNING;
for (int i=0; i<numCPUs; i++)
if (disasmWindow[i])
SendMessage(disasmWindow[i]->GetDlgHandle(), WM_COMMAND, IDC_STOP, 0);
}
SetCursor(LoadCursor(0,IDC_WAIT));
SaveState::LoadSlot(0, SaveStateActionFinished);
break;
case ID_FILE_QUICKSAVESTATE:
if (g_State.bEmuThreadStarted)
{
nextState = Core_IsStepping() ? CORE_STEPPING : CORE_RUNNING;
for (int i=0; i<numCPUs; i++)
if (disasmWindow[i])
SendMessage(disasmWindow[i]->GetDlgHandle(), WM_COMMAND, IDC_STOP, 0);
}
SetCursor(LoadCursor(0,IDC_WAIT));
SaveState::SaveSlot(0, SaveStateActionFinished);
break;
case ID_OPTIONS_SCREEN1X:
SetZoom(1);
UpdateMenus();
@@ -675,8 +701,10 @@ namespace MainWindow
enable = g_State.bEmuThreadStarted ? MF_GRAYED : MF_ENABLED;
EnableMenuItem(menu,ID_FILE_LOAD,enable);
EnableMenuItem(menu,ID_FILE_SAVESTATE,!enable);
EnableMenuItem(menu,ID_FILE_LOADSTATE,!enable);
EnableMenuItem(menu,ID_FILE_SAVESTATEFILE,!enable);
EnableMenuItem(menu,ID_FILE_LOADSTATEFILE,!enable);
EnableMenuItem(menu,ID_FILE_QUICKSAVESTATE,!enable);
EnableMenuItem(menu,ID_FILE_QUICKLOADSTATE,!enable);
EnableMenuItem(menu,ID_CPU_DYNAREC,enable);
EnableMenuItem(menu,ID_CPU_INTERPRETER,enable);
EnableMenuItem(menu,ID_CPU_FASTINTERPRETER,enable);
@@ -788,7 +816,7 @@ namespace MainWindow
}
}
void SaveStateActionFinished(bool result)
void SaveStateActionFinished(bool result, void *userdata)
{
// TODO: Improve messaging?
if (!result)
+1 -1
View File
@@ -17,7 +17,7 @@ namespace MainWindow
void SetPlaying(const char*text);
void BrowseAndBoot();
void SetNextState(CoreState state);
void SaveStateActionFinished(bool result);
void SaveStateActionFinished(bool result, void *userdata);
void _ViewFullScreen(HWND hWnd);
void _ViewNormal(HWND hWnd);
}
+7 -5
View File
@@ -187,9 +187,11 @@ BEGIN
MENUITEM "&Open...", ID_FILE_LOAD
MENUITEM "&Close", ID_EMULATION_STOP
MENUITEM SEPARATOR
MENUITEM "&Load State\tF4" ID_FILE_LOADSTATE
MENUITEM "&Save State\tF2" ID_FILE_SAVESTATE
MENUITEM SEPARATOR
MENUITEM "Quickload state\tF4" ID_FILE_QUICKLOADSTATE
MENUITEM "Quicksave state\tF2" ID_FILE_QUICKSAVESTATE
MENUITEM "&Load State File..." ID_FILE_LOADSTATEFILE
MENUITEM "&Save State File..." ID_FILE_SAVESTATEFILE
MENUITEM SEPARATOR
MENUITEM "E&xit", ID_FILE_EXIT
END
POPUP "&Emulation"
@@ -321,8 +323,8 @@ BEGIN
"R", ID_DEBUG_REGISTERS, VIRTKEY, CONTROL, NOINVERT
VK_F7, ID_EMULATION_RUN, VIRTKEY, NOINVERT
VK_F8, ID_EMULATION_PAUSE, VIRTKEY, NOINVERT
VK_F2, ID_FILE_SAVESTATE, VIRTKEY, NOINVERT
VK_F4, ID_FILE_LOADSTATE, VIRTKEY, NOINVERT
VK_F2, ID_FILE_QUICKSAVESTATE, VIRTKEY, NOINVERT
VK_F4, ID_FILE_QUICKLOADSTATE, VIRTKEY, NOINVERT
"1", ID_OPTIONS_SCREEN1X, VIRTKEY, CONTROL, NOINVERT
"2", ID_OPTIONS_SCREEN2X, VIRTKEY, CONTROL, NOINVERT
"3", ID_OPTIONS_SCREEN3X, VIRTKEY, CONTROL, NOINVERT
+5 -3
View File
@@ -53,8 +53,8 @@
#define ID_DEBUG_BREAKPOINTS 122
#define ID_FILE_LOAD_BIN 123
#define ID_FILE_LOAD_ISO 125
#define ID_FILE_LOADSTATE 126
#define ID_FILE_SAVESTATE 127
#define ID_FILE_LOADSTATEFILE 126
#define ID_FILE_SAVESTATEFILE 127
#define ID_EMULATION_RESET 130
#define IDD_ABOUTBOX 133
#define ID_DEBUG_LOADMAPFILE 134
@@ -248,13 +248,15 @@
#define ID_OPTIONS_FASTMEMORY 40125
#define IDC_STEPHLE 40126
#define ID_OPTIONS_LINEARFILTERING 40127
#define ID_FILE_QUICKSAVESTATE 40128
#define ID_FILE_QUICKLOADSTATE 40129
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 232
#define _APS_NEXT_COMMAND_VALUE 40127
#define _APS_NEXT_COMMAND_VALUE 40130
#define _APS_NEXT_CONTROL_VALUE 1162
#define _APS_NEXT_SYMED_VALUE 101
#endif
+30 -6
View File
@@ -29,6 +29,7 @@
#include "ui/ui.h"
#include "ui_atlas.h"
#include "util/random/rng.h"
#include "util/text/utf8.h"
#include "UIShader.h"
#include "../../GPU/ge_constants.h"
@@ -36,10 +37,16 @@
#include "../../GPU/GPUInterface.h"
#include "../../Core/Config.h"
#include "../../Core/CoreParameter.h"
#include "../../Core/SaveState.h"
#include "MenuScreens.h"
#include "EmuScreen.h"
// Ugly communication with NativeApp
extern std::string game_title;
static const int symbols[4] = {
I_CROSS,
I_CIRCLE,
@@ -207,22 +214,39 @@ void InGameMenuScreen::render() {
UIBegin();
DrawBackground(1.0f);
ui_draw2d.DrawText(UBUNTU48, "Emulation Paused", dp_xres / 2, 30, 0xFFFFFFFF, ALIGN_HCENTER);
const char *title;
if (UTF8StringHasNonASCII(game_title.c_str())) {
title = "(can't display japanese title)";
} else {
title = game_title.c_str();
}
ui_draw2d.DrawText(UBUNTU48, title, dp_xres / 2, 30, 0xFFFFFFFF, ALIGN_HCENTER);
int x = 30;
int y = 50;
UICheckBox(GEN_ID, x, y += 50, "Show Debug Statistics (experimental)", ALIGN_TOPLEFT, &g_Config.bShowDebugStats);
UICheckBox(GEN_ID, x, y += 50, "Hardware Transform (experimental)", ALIGN_TOPLEFT, &g_Config.bHardwareTransform);
UICheckBox(GEN_ID, x, y += 50, "Show Debug Statistics", ALIGN_TOPLEFT, &g_Config.bShowDebugStats);
UICheckBox(GEN_ID, x, y += 50, "Hardware Transform", ALIGN_TOPLEFT, &g_Config.bHardwareTransform);
// TODO: Add UI for more than one slot.
VLinear vlinear1(x, y + 80, 20);
UIText(UBUNTU24, vlinear1, "Save states are experimental (and large)", 0xFFFFFFFF);
if (UIButton(GEN_ID, vlinear1, LARGE_BUTTON_WIDTH, "Save State", ALIGN_LEFT)) {
SaveState::SaveSlot(0, 0, 0);
screenManager()->finishDialog(this, DR_CANCEL);
}
if (UIButton(GEN_ID, vlinear1, LARGE_BUTTON_WIDTH, "Load State", ALIGN_LEFT)) {
SaveState::LoadSlot(0, 0, 0);
screenManager()->finishDialog(this, DR_CANCEL);
}
VLinear vlinear(dp_xres - 10, 160, 20);
if (UIButton(GEN_ID, vlinear, LARGE_BUTTON_WIDTH, "Continue", ALIGN_RIGHT)) {
screenManager()->finishDialog(this, DR_CANCEL);
}
if (UIButton(GEN_ID, vlinear, LARGE_BUTTON_WIDTH, "Return to Menu", ALIGN_RIGHT)) {
screenManager()->finishDialog(this, DR_OK);
}
if (UIButton(GEN_ID, vlinear, LARGE_BUTTON_WIDTH, "Dump Next Frame", ALIGN_RIGHT)) {
gpu->DumpNextFrame();
}
@@ -253,7 +277,7 @@ void SettingsScreen::render() {
int y = 50;
UICheckBox(GEN_ID, x, y += 50, "Sound Emulation", ALIGN_TOPLEFT, &g_Config.bEnableSound);
UICheckBox(GEN_ID, x, y += 50, "Buffered Rendering (may fix flicker)", ALIGN_TOPLEFT, &g_Config.bBufferedRendering);
UICheckBox(GEN_ID, x, y += 50, "Hardware Transform (experimental)", ALIGN_TOPLEFT, &g_Config.bHardwareTransform);
UICheckBox(GEN_ID, x, y += 50, "Hardware Transform", ALIGN_TOPLEFT, &g_Config.bHardwareTransform);
bool useFastInt = g_Config.iCpuCore == CPU_FASTINTERPRETER;
UICheckBox(GEN_ID, x, y += 50, "Slightly faster interpreter (may crash)", ALIGN_TOPLEFT, &useFastInt);
+4
View File
@@ -53,6 +53,7 @@ Texture *uiTexture;
ScreenManager *screenManager;
std::string config_filename;
std::string game_title;
class AndroidLogger : public LogListener
{
@@ -112,6 +113,9 @@ public:
virtual bool AttemptLoadSymbolMap() {return false;}
virtual void ResetSymbolMap() {}
virtual void AddSymbol(std::string name, u32 addr, u32 size, int type=0) {}
virtual void SetWindowTitle(const char *message) {
game_title = message;
}
};
// globals