git-svn-id: http://svn.purei.org/purei/trunk@66 b36208d7-6611-0410-8bec-b1987f11c4a2

This commit is contained in:
jpd002 2006-07-23 22:52:33 +00:00
parent b16ad93934
commit b2fe0c2c93
8 changed files with 274 additions and 12 deletions

View 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;
}
}

View File

@ -0,0 +1,12 @@
#ifndef _SAVEEXPORTER_H_
#define _SAVEEXPORTER_H_
#include <iostream>
class CSaveExporter
{
public:
static void ExportPSU(std::ostream&, const char*);
};
#endif

View File

@ -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);

View File

@ -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);

View File

@ -8,7 +8,7 @@
#include "MemoryCard.h"
#include "MemoryCardView.h"
#include "SaveView.h"
#include "SaveImporter.h"
#include "../saves/SaveImporter.h"
class CMcManagerWnd : public CModalWindow
{

View File

@ -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);
}

View File

@ -85,6 +85,7 @@ private:
void RefreshLayout();
void SetIconType(ICONTYPE);
void OpenSaveFolder();
void Export();
const CSave* m_pSave;
Framework::CVerticalLayout* m_pLayout;