Improved PSF loader.

Improved Game Viewer.
Implemented cellPadGetInfo.
Minor improvements.
This commit is contained in:
DH 2013-12-08 15:47:54 +02:00
parent 34f5997f82
commit eaef09df91
10 changed files with 1024 additions and 1040 deletions

View file

@ -5,6 +5,17 @@ PSFLoader::PSFLoader(vfsStream& f) : psf_f(f)
{
}
PsfEntry* PSFLoader::SearchEntry(const std::string& key)
{
for(uint i=0; i<m_entries.GetCount(); ++i)
{
if(m_entries[i].name == key)
return &m_entries[i];
}
return nullptr;
}
bool PSFLoader::Load(bool show)
{
if(!psf_f.IsOpened()) return false;
@ -13,17 +24,7 @@ bool PSFLoader::Load(bool show)
if(!LoadHdr()) return false;
if(!LoadKeyTable()) return false;
if(!LoadValuesTable()) return false;
if(show)
{
ConLog.SkipLn();
for(uint i=0; i<m_table.GetCount(); ++i)
{
ConLog.Write("%s", m_table[i].mb_str());
}
ConLog.SkipLn();
}
if(!LoadDataTable()) return false;
return true;
}
@ -35,198 +36,71 @@ bool PSFLoader::Close()
bool PSFLoader::LoadHdr()
{
psf_f.Read(&psfhdr, sizeof(PsfHeader));
if(psf_f.Read(&psfhdr, sizeof(PsfHeader)) != sizeof(PsfHeader))
return false;
if(!psfhdr.CheckMagic()) return false;
if(m_show_log) ConLog.Write("PSF version: %x", psfhdr.psf_version);
m_psfindxs.Clear();
m_entries.Clear();
m_psfindxs.SetCount(psfhdr.psf_entries_num);
m_entries.SetCount(psfhdr.psf_entries_num);
for(u32 i=0; i<psfhdr.psf_entries_num; ++i)
{
if(psf_f.Read(&m_psfindxs[i], sizeof(PsfDefTbl)) != sizeof(PsfDefTbl))
return false;
m_entries[i].fmt = m_psfindxs[i].psf_param_fmt;
}
return true;
}
bool PSFLoader::LoadKeyTable()
{
psf_f.Seek(psfhdr.psf_offset_key_table);
m_table.Clear();
m_table.Add(wxEmptyString);
while(!psf_f.Eof())
for(u32 i=0; i<psfhdr.psf_entries_num; ++i)
{
char c;
psf_f.Read(&c, 1);
if(c == 0)
psf_f.Seek(psfhdr.psf_offset_key_table + m_psfindxs[i].psf_key_table_offset);
int c_pos = 0;
while(!psf_f.Eof())
{
char c;
psf_f.Read(&c, 1);
if(c == 0) break;
m_entries[i].name[c_pos++] = c;
m_table.Add(wxEmptyString);
if(c_pos >= sizeof(m_entries[i].name) || c == '\0')
break;
}
m_table[m_table.GetCount() - 1].Append(c);
}
if(m_table.GetCount() != psfhdr.psf_entries_num)
{
if(m_show_log) ConLog.Error("PSF error: Entries loaded with error! [%d - %d]", m_table.GetCount(), psfhdr.psf_entries_num);
m_table.Clear();
return false;
}
return true;
}
struct PsfHelper
bool PSFLoader::LoadDataTable()
{
static wxString ReadString(vfsStream& f, const u32 size)
for(u32 i=0; i<psfhdr.psf_entries_num; ++i)
{
wxString ret = wxEmptyString;
for(uint i=0; i<size && !f.Eof(); ++i)
{
ret += ReadChar(f);
}
return ret;
psf_f.Seek(psfhdr.psf_offset_data_table + m_psfindxs[i].psf_data_tbl_offset);
psf_f.Read(m_entries[i].param, m_psfindxs[i].psf_param_len);
memset(m_entries[i].param + m_psfindxs[i].psf_param_len, 0, m_psfindxs[i].psf_param_max_len - m_psfindxs[i].psf_param_len);
}
static wxString ReadString(vfsStream& f)
{
wxString ret = wxEmptyString;
while(!f.Eof())
{
const char c = ReadChar(f);
if(c == 0) break;
ret += c;
}
return ret;
}
static char ReadChar(vfsStream& f)
{
char c;
f.Read(&c, 1);
return c;
}
static char ReadCharNN(vfsStream& f)
{
char c;
while(!f.Eof())
{
f.Read(&c, 1);
if(c != 0) break;
}
return c;
}
static void GoToNN(vfsStream& f)
{
while(!f.Eof())
{
char c;
f.Read(&c, 1);
if(c != 0)
{
f.Seek(f.Tell() - 1);
break;
}
}
}
static wxString FixName(const wxString& name)
{
wxString ret = wxEmptyString;
for(uint i=0; i<name.Length(); ++i)
{
switch((u8)name[i])
{
case 0xE2: case 0xA2: case 0x84: continue;
default: ret += name[i]; break;
};
}
return ret;
}
};
bool PSFLoader::LoadValuesTable()
{
psf_f.Seek(psfhdr.psf_offset_values_table);
m_info.Reset();
for(uint i=0;i<m_table.GetCount(); i++)
{
if(!m_table[i].Cmp("TITLE_ID"))
{
m_info.serial = PsfHelper::ReadString(psf_f);
m_table[i].Append(wxString::Format(": %s", m_info.serial.mb_str()));
PsfHelper::GoToNN(psf_f);
}
else if(!m_table[i](0, 5).Cmp("TITLE"))
{
m_info.name = PsfHelper::FixName(PsfHelper::ReadString(psf_f));
m_table[i].Append(wxString::Format(": %s", m_info.name.mb_str()));
PsfHelper::GoToNN(psf_f);
}
else if(!m_table[i].Cmp("APP_VER"))
{
m_info.app_ver = PsfHelper::ReadString(psf_f, sizeof(u64));
m_table[i].Append(wxString::Format(": %s", m_info.app_ver.mb_str()));
}
else if(!m_table[i].Cmp("ATTRIBUTE"))
{
psf_f.Read(&m_info.attr, sizeof(m_info.attr));
m_table[i].Append(wxString::Format(": 0x%x", m_info.attr));
}
else if(!m_table[i].Cmp("CATEGORY"))
{
m_info.category = PsfHelper::ReadString(psf_f, sizeof(u32));
m_table[i].Append(wxString::Format(": %s", m_info.category.mb_str()));
}
else if(!m_table[i].Cmp("BOOTABLE"))
{
psf_f.Read(&m_info.bootable, sizeof(m_info.bootable));
m_table[i].Append(wxString::Format(": %d", m_info.bootable));
}
else if(!m_table[i].Cmp("LICENSE"))
{
m_table[i].Append(wxString::Format(": %s", PsfHelper::ReadString(psf_f).mb_str()));
psf_f.Seek(psf_f.Tell() + (sizeof(u64) * 7 * 2) - 1);
}
else if(!m_table[i](0, 14).Cmp("PARENTAL_LEVEL"))
{
u32 buf;
psf_f.Read(&buf, sizeof(buf));
if(!m_table[i].Cmp("PARENTAL_LEVEL"))
{
m_info.parental_lvl = buf;
}
m_table[i].Append(wxString::Format(": %d", buf));
}
else if(!m_table[i].Cmp("PS3_SYSTEM_VER"))
{
m_info.fw = PsfHelper::ReadString(psf_f, sizeof(u64));
m_table[i].Append(wxString::Format(": %s", m_info.fw.mb_str()));
}
else if(!m_table[i].Cmp("SOUND_FORMAT"))
{
m_info.sound_format = Read32(psf_f);
m_table[i].Append(wxString::Format(": 0x%x", m_info.sound_format));
}
else if(!m_table[i].Cmp("RESOLUTION"))
{
m_info.resolution = Read32(psf_f);
m_table[i].Append(wxString::Format(": 0x%x", m_info.resolution));
}
else
{
m_table[i].Append(wxString::Format(": %s", PsfHelper::ReadString(psf_f).mb_str()));
PsfHelper::GoToNN(psf_f);
}
}
if(PsfEntry* entry = SearchEntry("TITLE_ID")) m_info.serial = entry->Format();
if(PsfEntry* entry = SearchEntry("TITLE")) m_info.name = entry->Format();
if(PsfEntry* entry = SearchEntry("APP_VER")) m_info.app_ver = entry->Format();
if(PsfEntry* entry = SearchEntry("CATEGORY")) m_info.category = entry->Format();
if(PsfEntry* entry = SearchEntry("PS3_SYSTEM_VER")) m_info.fw = entry->Format();
if(PsfEntry* entry = SearchEntry("SOUND_FORMAT")) m_info.sound_format = entry->FormatInteger();
if(PsfEntry* entry = SearchEntry("RESOLUTION")) m_info.resolution = entry->FormatInteger();
if(PsfEntry* entry = SearchEntry("PARENTAL_LEVEL")) m_info.parental_lvl = entry->FormatInteger();
if(m_info.serial.Length() == 9)
{