mirror of
https://github.com/libretro/Play-.git
synced 2025-02-22 12:41:34 +00:00
git-svn-id: http://svn.purei.org/purei/trunk@66 b36208d7-6611-0410-8bec-b1987f11c4a2
This commit is contained in:
parent
b16ad93934
commit
b2fe0c2c93
190
Source/saves/SaveExporter.cpp
Normal file
190
Source/saves/SaveExporter.cpp
Normal file
@ -0,0 +1,190 @@
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#include <fstream>
|
||||
#include "SaveExporter.h"
|
||||
#include "Types.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
|
||||
void CSaveExporter::ExportPSU(ostream& Output, const char* sSavePath)
|
||||
{
|
||||
filesystem::path SavePath(sSavePath, filesystem::native);
|
||||
filesystem::directory_iterator itEnd;
|
||||
|
||||
uint32 nSector = 0x18D;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
struct ENTRY
|
||||
{
|
||||
//All fields seem to be BCDs except for year
|
||||
struct TIME
|
||||
{
|
||||
uint8 nUnknown;
|
||||
uint8 nSecond;
|
||||
uint8 nMinute;
|
||||
uint8 nHour;
|
||||
uint8 nDay;
|
||||
uint8 nMonth;
|
||||
uint16 nYear;
|
||||
};
|
||||
|
||||
uint32 nFlags;
|
||||
uint32 nSize;
|
||||
TIME CreationTime;
|
||||
uint32 nSector;
|
||||
uint32 nChecksum;
|
||||
TIME ModificationTime;
|
||||
uint8 Padding[0x20];
|
||||
uint8 sName[0x1C0];
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
assert(sizeof(ENTRY) == 0x200);
|
||||
|
||||
{
|
||||
//Save base directory entry
|
||||
|
||||
ENTRY Entry;
|
||||
|
||||
memset(&Entry, 0, sizeof(ENTRY));
|
||||
|
||||
Entry.nSize = 2;
|
||||
|
||||
for(filesystem::directory_iterator itElement(SavePath);
|
||||
itElement != itEnd;
|
||||
itElement++)
|
||||
{
|
||||
if(filesystem::is_directory(*itElement)) continue;
|
||||
Entry.nSize++;
|
||||
}
|
||||
|
||||
Entry.nFlags = 0x8427;
|
||||
Entry.nSector = nSector;
|
||||
|
||||
Entry.CreationTime.nSecond = 0x27;
|
||||
Entry.CreationTime.nMinute = 0x23;
|
||||
Entry.CreationTime.nHour = 0x11;
|
||||
Entry.CreationTime.nDay = 0x17;
|
||||
Entry.CreationTime.nMonth = 0x06;
|
||||
Entry.CreationTime.nYear = 2006;
|
||||
|
||||
Entry.ModificationTime.nSecond = 0x27;
|
||||
Entry.ModificationTime.nMinute = 0x23;
|
||||
Entry.ModificationTime.nHour = 0x11;
|
||||
Entry.ModificationTime.nDay = 0x17;
|
||||
Entry.ModificationTime.nMonth = 0x06;
|
||||
Entry.ModificationTime.nYear = 2006;
|
||||
|
||||
strncpy(reinterpret_cast<char*>(Entry.sName), SavePath.leaf().c_str(), 0x1C0);
|
||||
|
||||
Output.write(reinterpret_cast<char*>(&Entry), sizeof(ENTRY));
|
||||
}
|
||||
|
||||
static const char* sRelDirName[2] =
|
||||
{
|
||||
".",
|
||||
"..",
|
||||
};
|
||||
|
||||
//Save "relative" directories
|
||||
|
||||
for(unsigned int i = 0; i < 2; i++)
|
||||
{
|
||||
ENTRY Entry;
|
||||
|
||||
memset(&Entry, 0, sizeof(ENTRY));
|
||||
|
||||
Entry.nFlags = 0x8427;
|
||||
Entry.nSector = 0;
|
||||
|
||||
Entry.CreationTime.nSecond = 0x27;
|
||||
Entry.CreationTime.nMinute = 0x23;
|
||||
Entry.CreationTime.nHour = 0x11;
|
||||
Entry.CreationTime.nDay = 0x17;
|
||||
Entry.CreationTime.nMonth = 0x06;
|
||||
Entry.CreationTime.nYear = 2006;
|
||||
|
||||
Entry.ModificationTime.nSecond = 0x27;
|
||||
Entry.ModificationTime.nMinute = 0x23;
|
||||
Entry.ModificationTime.nHour = 0x11;
|
||||
Entry.ModificationTime.nDay = 0x17;
|
||||
Entry.ModificationTime.nMonth = 0x06;
|
||||
Entry.ModificationTime.nYear = 2006;
|
||||
|
||||
strncpy(reinterpret_cast<char*>(Entry.sName), sRelDirName[i], 0x1C0);
|
||||
|
||||
Output.write(reinterpret_cast<char*>(&Entry), sizeof(ENTRY));
|
||||
}
|
||||
|
||||
nSector += 2;
|
||||
|
||||
//Save individual file entries
|
||||
for(filesystem::directory_iterator itElement(SavePath);
|
||||
itElement != itEnd;
|
||||
itElement++)
|
||||
{
|
||||
if(filesystem::is_directory(*itElement)) continue;
|
||||
|
||||
ENTRY Entry;
|
||||
uint32 nSize;
|
||||
|
||||
memset(&Entry, 0, sizeof(ENTRY));
|
||||
|
||||
Entry.nFlags = 0x8497;
|
||||
Entry.nSize = static_cast<uint32>(filesystem::file_size(*itElement));
|
||||
Entry.nSector = nSector;
|
||||
|
||||
Entry.CreationTime.nSecond = 0x27;
|
||||
Entry.CreationTime.nMinute = 0x23;
|
||||
Entry.CreationTime.nHour = 0x11;
|
||||
Entry.CreationTime.nDay = 0x17;
|
||||
Entry.CreationTime.nMonth = 0x06;
|
||||
Entry.CreationTime.nYear = 2006;
|
||||
|
||||
Entry.ModificationTime.nSecond = 0x27;
|
||||
Entry.ModificationTime.nMinute = 0x23;
|
||||
Entry.ModificationTime.nHour = 0x11;
|
||||
Entry.ModificationTime.nDay = 0x17;
|
||||
Entry.ModificationTime.nMonth = 0x06;
|
||||
Entry.ModificationTime.nYear = 2006;
|
||||
|
||||
strncpy(reinterpret_cast<char*>(Entry.sName), (*itElement).leaf().c_str(), 0x1C0);
|
||||
|
||||
Output.write(reinterpret_cast<char*>(&Entry), sizeof(ENTRY));
|
||||
|
||||
//Write file contents
|
||||
{
|
||||
ifstream Input((*itElement).string().c_str(), ios::in | ios::binary);
|
||||
nSize = Entry.nSize;
|
||||
|
||||
while(nSize != 0)
|
||||
{
|
||||
uint32 nRead;
|
||||
char sBuffer[0x1000];
|
||||
|
||||
nRead = min<uint32>(nSize, 0x1000);
|
||||
Input.read(sBuffer, nRead);
|
||||
Output.write(sBuffer, nRead);
|
||||
nSize -= nRead;
|
||||
}
|
||||
|
||||
Input.close();
|
||||
}
|
||||
|
||||
//Align on 0x400 boundary
|
||||
{
|
||||
unsigned int nPosition;
|
||||
char sBuffer[0x400];
|
||||
|
||||
nPosition = Entry.nSize;
|
||||
memset(sBuffer, 0, 0x400);
|
||||
|
||||
Output.write(sBuffer, 0x400 - (nPosition & 0x3FF));
|
||||
}
|
||||
|
||||
nSector += (Entry.nSize + 0x3FF) / 0x400;
|
||||
}
|
||||
}
|
12
Source/saves/SaveExporter.h
Normal file
12
Source/saves/SaveExporter.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef _SAVEEXPORTER_H_
|
||||
#define _SAVEEXPORTER_H_
|
||||
|
||||
#include <iostream>
|
||||
|
||||
class CSaveExporter
|
||||
{
|
||||
public:
|
||||
static void ExportPSU(std::ostream&, const char*);
|
||||
};
|
||||
|
||||
#endif
|
@ -187,9 +187,12 @@ void CSaveImporter::PSU_Import(istream& Input, const char* sOutputPath)
|
||||
Input.seekg(0x38, ios::cur);
|
||||
Input.read(sEntryName, 0x1C0);
|
||||
|
||||
if(nEntryType == 0x8427 && (nEntrySize != 0))
|
||||
if(nEntryType == 0x8427)
|
||||
{
|
||||
PSU_Import(Input, (Path / sEntryName).string().c_str());
|
||||
if(nEntrySize != 0)
|
||||
{
|
||||
PSU_Import(Input, (Path / sEntryName).string().c_str());
|
||||
}
|
||||
}
|
||||
else if(nEntryType == 0x8497)
|
||||
{
|
||||
@ -202,27 +205,31 @@ void CSaveImporter::PSU_Import(istream& Input, const char* sOutputPath)
|
||||
}
|
||||
else
|
||||
{
|
||||
char sBuffer[1024];
|
||||
unsigned int nEntrySizeDrain;
|
||||
|
||||
iostreams::filtering_ostream Output;
|
||||
Output.push(iostreams::file_sink(OutputPath.string(), ios::out | ios::binary));
|
||||
|
||||
while(nEntrySize != 0)
|
||||
nEntrySizeDrain = nEntrySize;
|
||||
|
||||
while(nEntrySizeDrain != 0)
|
||||
{
|
||||
unsigned int nRead;
|
||||
char sBuffer[1024];
|
||||
|
||||
nRead = min<unsigned int>(nEntrySize, 1024);
|
||||
nRead = min<unsigned int>(nEntrySizeDrain, 1024);
|
||||
Input.read(sBuffer, nRead);
|
||||
Output.write(sBuffer, nRead);
|
||||
|
||||
nEntrySize -= nRead;
|
||||
nEntrySizeDrain -= nRead;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned int nPosition;
|
||||
nPosition = Input.tellg();
|
||||
Input.seekg(0x200 - (nPosition & 0x1FF), ios::cur);
|
||||
Input.seekg(0x400 - (nEntrySize & 0x3FF), ios::cur);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw exception("Invalid entry type encountered.");
|
||||
}
|
||||
|
||||
Input.read(reinterpret_cast<char*>(&nEntryType), 2);
|
@ -166,7 +166,7 @@ void CMcManagerWnd::Import()
|
||||
unsigned int nRet;
|
||||
|
||||
Win32::CFileDialog FileDialog;
|
||||
FileDialog.m_OFN.lpstrFilter = _X("All supported types\0*.psu;*.xps\0EMS Memory Adapder Save Dumps (*.psu)\0*.psu\0X-Port Save Dumps(*.xps)\0*.xps\0All files (*.*)\0*.*\0");
|
||||
FileDialog.m_OFN.lpstrFilter = _X("All supported types\0*.psu;*.xps\0EMS Memory Adapter Save Dumps (*.psu)\0*.psu\0X-Port Save Dumps(*.xps)\0*.xps\0All files (*.*)\0*.*\0");
|
||||
|
||||
Enable(FALSE);
|
||||
nRet = FileDialog.Summon(m_hWnd);
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include "MemoryCard.h"
|
||||
#include "MemoryCardView.h"
|
||||
#include "SaveView.h"
|
||||
#include "SaveImporter.h"
|
||||
#include "../saves/SaveImporter.h"
|
||||
|
||||
class CMcManagerWnd : public CModalWindow
|
||||
{
|
||||
|
@ -1,9 +1,12 @@
|
||||
#include <fstream>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
#include "../saves/SaveExporter.h"
|
||||
#include "SaveView.h"
|
||||
#include "string_cast.h"
|
||||
#include "win32/Static.h"
|
||||
#include "win32/FileDialog.h"
|
||||
|
||||
#define CLSNAME _X("CSaveView")
|
||||
|
||||
@ -173,6 +176,10 @@ long CSaveView::OnCommand(unsigned short nCmd, unsigned short nId, HWND hWndFrom
|
||||
{
|
||||
if(m_pDeletingIcon->m_hWnd == hWndFrom) SetIconType(ICON_DELETING);
|
||||
}
|
||||
if(m_pExport != NULL)
|
||||
{
|
||||
if(m_pExport->m_hWnd == hWndFrom) Export();
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -209,3 +216,48 @@ void CSaveView::OpenSaveFolder()
|
||||
|
||||
ShellExecuteA(m_hWnd, "open", Path.string().c_str(), NULL, NULL, SW_SHOW);
|
||||
}
|
||||
|
||||
void CSaveView::Export()
|
||||
{
|
||||
if(m_pSave == NULL) return;
|
||||
|
||||
unsigned int nRet;
|
||||
|
||||
Win32::CFileDialog FileDialog;
|
||||
FileDialog.m_OFN.lpstrFilter = _X("EMS Memory Adapter Save Dumps (*.psu)\0*.psu\0");
|
||||
|
||||
EnableWindow(GetParent(), FALSE);
|
||||
nRet = FileDialog.Summon(m_hWnd);
|
||||
EnableWindow(GetParent(), TRUE);
|
||||
|
||||
if(nRet == 0) return;
|
||||
|
||||
FILE* pStream;
|
||||
pStream = xfopen(FileDialog.m_sFile, _X("wb"));
|
||||
|
||||
if(pStream == NULL)
|
||||
{
|
||||
MessageBox(m_hWnd, _X("Couldn't open file for writing."), NULL, 16);
|
||||
return;
|
||||
}
|
||||
|
||||
ofstream Output(pStream);
|
||||
|
||||
try
|
||||
{
|
||||
CSaveExporter::ExportPSU(Output, m_pSave->GetPath().string().c_str());
|
||||
Output.close();
|
||||
}
|
||||
catch(const exception& Exception)
|
||||
{
|
||||
Output.close();
|
||||
|
||||
string sMessage;
|
||||
sMessage = "Couldn't export save:\r\n\r\n";
|
||||
sMessage += Exception.what();
|
||||
MessageBoxA(m_hWnd, sMessage.c_str(), NULL, 16);
|
||||
return;
|
||||
}
|
||||
|
||||
MessageBox(m_hWnd, _X("Save exported successfully."), NULL, MB_ICONINFORMATION);
|
||||
}
|
||||
|
@ -85,6 +85,7 @@ private:
|
||||
void RefreshLayout();
|
||||
void SetIconType(ICONTYPE);
|
||||
void OpenSaveFolder();
|
||||
void Export();
|
||||
|
||||
const CSave* m_pSave;
|
||||
Framework::CVerticalLayout* m_pLayout;
|
||||
|
Loading…
x
Reference in New Issue
Block a user