/*
savemngr.cpp
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
//�
#include "savemngr.h"
#include "inifile.h"
#include "dsrom.h"
#include "dbgtool.h"
#include "systemfilenames.h"
#include "progresswnd.h"
#include "language.h"
#include "datetime.h"
#include "ui.h"
#include
#include
#include
using namespace akui;
cSaveManager::cSaveManager()
{
}
cSaveManager::~cSaveManager()
{
}
static bool loadSaveList(const std::string& filename,std::vector& buffer)
{
u8* data=NULL;
FILE* f=fopen(filename.c_str(),"rb");
if(NULL==f)
{
dbg_printf("fopen %s fail\n",filename.c_str());
return false;
}
bool res=false;
do
{
u32 saveCount=0;
SAVE_INFO_EX_HEADER header={SAVE_INFO_EX_HEADER_MAGIC,sizeof(SAVE_INFO),saveCount,0};
if(1!=fread(&header,sizeof(header),1,f)) break;
if(header.marker!=SAVE_INFO_EX_HEADER_MAGIC) break;
data=new u8[header.itemSize*header.itemCount];
u32 copiedSize=std::min((unsigned int)header.itemSize,sizeof(SAVE_INFO_EX));
if(header.itemCount!=fread(data,header.itemSize,header.itemCount,f)) break;
buffer.resize(header.itemCount);
for(u32 ii=0;ii& buffer)
{
FILE* f=fopen(filename.c_str(),"rb");
if(NULL==f)
{
dbg_printf("fopen %s fail\n",filename.c_str());
return false;
}
fseek(f,0,SEEK_END);
u32 filesize=ftell(f);
if(0==filesize||0!=(filesize%19))
{
dbg_printf("%s size error %d\n", filename.c_str(), filesize );
fclose(f);
f=NULL;
return false;
}
u32 saveCount=filesize/19;
buffer.resize(saveCount);
fseek(f,0,SEEK_SET);
u32 readed=fread(&buffer[0],1,filesize,f);
if(filesize!=readed)
{
dbg_printf("%s read length error %d\n",filename.c_str(),readed);
fclose(f);
f=NULL;
return false;
}
fclose(f);
return true;
}
bool cSaveManager::importSaveList( const std::string & customFile, const std::string & officialFile )
{
loadSaveList(customFile,_customSaveList);
loadOfficialSaveList(officialFile,_saveList);
return true;
}
bool cSaveManager::exportCustomSaveList(const std::string& filename)
{
int f=open(filename.c_str(),O_WRONLY|O_CREAT|O_TRUNC);
if(f<0)
{
dbg_printf("fopen %s fail\n",filename.c_str());
return false;
}
bool res=false;
do
{
u32 count=_customSaveList.size();
SAVE_INFO_EX_HEADER header={SAVE_INFO_EX_HEADER_MAGIC,sizeof(SAVE_INFO_EX),count,0};
//libelm hack
lseek(f,sizeof(header)+sizeof(SAVE_INFO_EX)*count,SEEK_SET);
lseek(f,0,SEEK_SET);
//
ssize_t written=write(f,&header,sizeof(header));
if(written!=sizeof(header))
{
dbg_printf("%s write length error %d\n",filename.c_str(),written);
break;
}
written=write(f,&_customSaveList[0],sizeof(SAVE_INFO_EX)*count);
if(static_cast(sizeof(SAVE_INFO_EX)*count)!=written)
{
dbg_printf("%s write length error %d\n",filename.c_str(),written);
break;
}
res=true;
} while(false);
close(f);
return res;
}
void cSaveManager::updateCustomSaveList( const SAVE_INFO_EX & aSaveInfo )
{
size_t i = 0;
for( i = 0; i < _customSaveList.size(); ++i )
{
if( 0 == memcmp( &_customSaveList[i], &aSaveInfo, SAVE_INFO_EX_COMPARE_SIZE ) ) {
_customSaveList[i] = aSaveInfo;
break;
}
}
if( i == _customSaveList.size() )
_customSaveList.push_back( aSaveInfo );
exportCustomSaveList( SFN_CUSTOM_SAVELIST );
}
bool cSaveManager::saveLastInfo( const std::string & romFilename )
{
CIniFile f;
f.SetString( "Save Info", "lastLoaded", romFilename );
if( !f.SaveIniFile( SFN_LAST_SAVEINFO ) )
return false;
return true;
}
bool cSaveManager::loadLastInfo( std::string & lastLoadedFilename )
{
CIniFile f;
if( !f.LoadIniFile( SFN_LAST_SAVEINFO ) ) {
lastLoadedFilename = "";
return false;
}
lastLoadedFilename = f.GetString( "Save Info", "lastLoaded", "" );
if( "" == lastLoadedFilename )
return false;
return true;
}
bool cSaveManager::clearLastInfo()
{
std::string loadLoadedFile;
if(loadLastInfo(loadLoadedFile))
{
return saveLastInfo("");
}
return true;
}
bool cSaveManager::initializeSaveFile(const std::string& romFilename,u8 slot,u32 size)
{
bool res=false;
std::string saveFilename=generateSaveName(romFilename,slot);
int f=open(saveFilename.c_str(),O_WRONLY|O_CREAT);
if(f>=0)
{
off_t filesize=lseek(f,0,SEEK_END);
if(filesize>=0)
{
if((u32)filesize>=size)
{
write(f,NULL,0); //update time stamp
res=true;
}
else
{
progressWnd().setTipText(LANG("progress window","processing save"));
progressWnd().show();
progressWnd().setPercent(0);
u32 tail=size-filesize;
const u32 bufferSize=128*1024; u32 ii=0;
u8* buffer=new u8[bufferSize];
memset(buffer,0,bufferSize);
res=true;
while(tail>0)
{
ssize_t writtenSize=(tail>bufferSize)?bufferSize:tail;
if(write(f,buffer,writtenSize)!=writtenSize)
{
res=false;
break;
}
tail-=writtenSize; ii++;
if(0==ii%8) progressWnd().setPercent((lseek(f,0,SEEK_END))*100/size);
}
progressWnd().setPercent(100);
progressWnd().hide();
}
}
close(f);
}
return res;
}
std::string cSaveManager::generateSaveName(const std::string& romFilename,u8 slot)
{
std::string saveFilename(romFilename);
if(gs().saveExt&&saveFilename.length()>3)
{
size_t nameLength=saveFilename.length()-4;
if(saveFilename[nameLength]=='.') saveFilename=saveFilename.substr(0,nameLength);
}
if(slot)
{
saveFilename+=".";
saveFilename+=(slot+'0');
}
saveFilename+=".sav";
return saveFilename;
}
SAVE_TYPE cSaveManager::getSaveTypeByFile( const std::string & romFilename )
{
return ST_UNKNOWN;
}
void cSaveManager::updateSaveInfoByInfo( SAVE_INFO_EX & gameInfo )
{
size_t saveCount = _customSaveList.size();
for( size_t i = 0; i < saveCount; ++i )
{
if( 0 == memcmp( &gameInfo, &_customSaveList[i], SAVE_INFO_EX_COMPARE_SIZE ) )
{
gameInfo=_customSaveList[i];
return;
}
}
gameInfo.defaults();
saveCount=_saveList.size();
for(size_t ii=0;iiST_UNKNOWN&&saveType<=ST_8M) gameInfo.saveType=_saveList[ii].saveType;
return;
}
}
return;
}
DISPLAY_SAVE_TYPE cSaveManager::SaveTypeToDisplaySaveType(SAVE_TYPE aSaveType)
{
switch(aSaveType)
{
case ST_UNKNOWN:
return D_ST_UNKNOWN;
case ST_NOSAVE:
return D_ST_NOSAVE;
case ST_4K:
return D_ST_4K;
case ST_64K:
return D_ST_64K;
case ST_512K:
return D_ST_512K;
case ST_2M:
return D_ST_2M;
case ST_4M:
return D_ST_4M;
case ST_8M:
return D_ST_8M;
case ST_NEW:
return D_ST_UNKNOWN;
case ST_AUTO:
return D_ST_UNKNOWN;
case ST_1M:
return D_ST_1M;
case ST_16M:
return D_ST_16M;
case ST_32M:
return D_ST_32M;
case ST_64M:
return D_ST_64M;
default:
return D_ST_UNKNOWN;
}
}
SAVE_TYPE cSaveManager::DisplaySaveTypeToSaveType(DISPLAY_SAVE_TYPE aSaveType)
{
switch(aSaveType)
{
case D_ST_UNKNOWN:
return ST_UNKNOWN;
case D_ST_NOSAVE:
return ST_NOSAVE;
case D_ST_4K:
return ST_4K;
case D_ST_64K:
return ST_64K;
case D_ST_512K:
return ST_512K;
case D_ST_1M:
return ST_1M;
case D_ST_2M:
return ST_2M;
case D_ST_4M:
return ST_4M;
case D_ST_8M:
return ST_8M;
case D_ST_16M:
return ST_16M;
case D_ST_32M:
return ST_32M;
case D_ST_64M:
return ST_64M;
}
return ST_UNKNOWN;
}