mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-17 17:11:23 +00:00
Improved PSF loader.
Improved Game Viewer. Implemented cellPadGetInfo. Minor improvements.
This commit is contained in:
parent
34f5997f82
commit
eaef09df91
@ -1238,8 +1238,10 @@ private:
|
||||
}
|
||||
void AI(u32 rt, u32 ra, s32 i10)
|
||||
{
|
||||
const __u32x4 imm = {i10, i10, i10, i10};
|
||||
CPU.GPR[rt]._m128i = _mm_add_epi32(CPU.GPR[ra]._m128i, imm.m128i);
|
||||
CPU.GPR[rt]._i32[0] = CPU.GPR[ra]._i32[0] + i10;
|
||||
CPU.GPR[rt]._i32[1] = CPU.GPR[ra]._i32[1] + i10;
|
||||
CPU.GPR[rt]._i32[2] = CPU.GPR[ra]._i32[2] + i10;
|
||||
CPU.GPR[rt]._i32[3] = CPU.GPR[ra]._i32[3] + i10;
|
||||
}
|
||||
void AHI(u32 rt, u32 ra, s32 i10)
|
||||
{
|
||||
|
@ -1058,8 +1058,6 @@ void GLGSRender::Flip()
|
||||
u32 height = re(buffers[m_gcm_current_buffer].height);
|
||||
u32 addr = GetAddress(re(buffers[m_gcm_current_buffer].offset), CELL_GCM_LOCATION_LOCAL);
|
||||
|
||||
glRotated(90, 1, 0, 0);
|
||||
|
||||
if(Memory.IsGoodAddr(addr))
|
||||
{
|
||||
//TODO
|
||||
|
@ -13,6 +13,7 @@ void sys_io_init()
|
||||
sys_io.AddFunc(0x8b72cda1, cellPadGetData);
|
||||
sys_io.AddFunc(0x6bc09c61, cellPadGetDataExtra);
|
||||
sys_io.AddFunc(0xf65544ee, cellPadSetActDirect);
|
||||
sys_io.AddFunc(0x3aaad464, cellPadGetInfo);
|
||||
sys_io.AddFunc(0xa703a51d, cellPadGetInfo2);
|
||||
sys_io.AddFunc(0x578e3c98, cellPadSetPortSetting);
|
||||
|
||||
|
@ -240,6 +240,7 @@ extern int cellPadClearBuf(u32 port_no);
|
||||
extern int cellPadGetData(u32 port_no, u32 data_addr);
|
||||
extern int cellPadGetDataExtra(u32 port_no, u32 device_type_addr, u32 data_addr);
|
||||
extern int cellPadSetActDirect(u32 port_no, u32 param_addr);
|
||||
extern int cellPadGetInfo(u32 info_addr);
|
||||
extern int cellPadGetInfo2(u32 info_addr);
|
||||
extern int cellPadSetPortSetting(u32 port_no, u32 port_setting);
|
||||
|
||||
|
@ -80,7 +80,28 @@ int sys_mmapper_allocate_address(u32 size, u64 flags, u32 alignment, u32 alloc_a
|
||||
{
|
||||
sc_mem.Warning("sys_mmapper_allocate_address(size=0x%x, flags=0x%llx, alignment=0x%x, alloc_addr=0x%x)", size, flags, alignment, alloc_addr);
|
||||
|
||||
Memory.Write32(alloc_addr, Memory.Alloc(size, alignment));
|
||||
if(!Memory.IsGoodAddr(alloc_addr)) return CELL_EFAULT;
|
||||
|
||||
if(!alignment)
|
||||
alignment = 1;
|
||||
|
||||
u32 addr;
|
||||
|
||||
switch(flags & (SYS_MEMORY_PAGE_SIZE_1M | SYS_MEMORY_PAGE_SIZE_64K))
|
||||
{
|
||||
default:
|
||||
case SYS_MEMORY_PAGE_SIZE_1M:
|
||||
if(Memory.AlignAddr(size, alignment) & 0xfffff) return CELL_EALIGN;
|
||||
addr = Memory.Alloc(size, 0x100000);
|
||||
break;
|
||||
|
||||
case SYS_MEMORY_PAGE_SIZE_64K:
|
||||
if(Memory.AlignAddr(size, alignment) & 0xffff) return CELL_EALIGN;
|
||||
addr = Memory.Alloc(size, 0x10000);
|
||||
break;
|
||||
}
|
||||
|
||||
Memory.Write32(alloc_addr, addr);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -91,7 +112,22 @@ int sys_mmapper_allocate_memory(u32 size, u64 flags, u32 mem_id_addr)
|
||||
|
||||
if(!Memory.IsGoodAddr(mem_id_addr)) return CELL_EFAULT;
|
||||
|
||||
u64 addr = Memory.Alloc(size, 4);
|
||||
u32 addr;
|
||||
switch(flags & (SYS_MEMORY_PAGE_SIZE_1M | SYS_MEMORY_PAGE_SIZE_64K))
|
||||
{
|
||||
case SYS_MEMORY_PAGE_SIZE_1M:
|
||||
if(size & 0xfffff) return CELL_EALIGN;
|
||||
addr = Memory.Alloc(size, 0x100000);
|
||||
break;
|
||||
|
||||
case SYS_MEMORY_PAGE_SIZE_64K:
|
||||
if(size & 0xffff) return CELL_EALIGN;
|
||||
addr = Memory.Alloc(size, 0x10000);
|
||||
break;
|
||||
|
||||
default:
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
if(!addr)
|
||||
return CELL_ENOMEM;
|
||||
|
@ -24,6 +24,16 @@ struct CellPadData
|
||||
u16 button[CELL_PAD_MAX_CODES];
|
||||
};
|
||||
|
||||
struct CellPadInfo
|
||||
{
|
||||
u32 max_connect;
|
||||
u32 now_connect;
|
||||
u32 system_info;
|
||||
u16 vendor_id[CELL_MAX_PADS];
|
||||
u16 product_id[CELL_MAX_PADS];
|
||||
u8 status[CELL_MAX_PADS];
|
||||
};
|
||||
|
||||
struct CellPadInfo2
|
||||
{
|
||||
u32 max_connect;
|
||||
@ -142,6 +152,35 @@ int cellPadSetActDirect(u32 port_no, u32 param_addr)
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellPadGetInfo(u32 info_addr)
|
||||
{
|
||||
sys_io.Log("cellPadGetInfo(info_addr=0x%x)", info_addr);
|
||||
if(!Emu.GetPadManager().IsInited()) return CELL_PAD_ERROR_UNINITIALIZED;
|
||||
|
||||
CellPadInfo info;
|
||||
memset(&info, 0, sizeof(CellPadInfo));
|
||||
|
||||
const PadInfo& rinfo = Emu.GetPadManager().GetInfo();
|
||||
info.max_connect = re(rinfo.max_connect);
|
||||
info.now_connect = re(rinfo.now_connect);
|
||||
info.system_info = re(rinfo.system_info);
|
||||
|
||||
const Array<Pad>& pads = Emu.GetPadManager().GetPads();
|
||||
|
||||
for(u32 i=0; i<CELL_MAX_PADS; ++i)
|
||||
{
|
||||
if(i >= pads.GetCount()) break;
|
||||
|
||||
info.status[i] = re(pads[i].m_port_status);
|
||||
info.product_id[i] = 0xdead; //TODO
|
||||
info.vendor_id[i] = 0xbeaf; //TODO
|
||||
}
|
||||
|
||||
Memory.WriteData(info_addr, info);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellPadGetInfo2(u32 info_addr)
|
||||
{
|
||||
sys_io.Log("cellPadGetInfo2(info_addr=0x%x)", info_addr);
|
||||
|
@ -8,7 +8,7 @@ GameViewer::GameViewer(wxWindow* parent) : wxListView(parent)
|
||||
LoadSettings();
|
||||
m_columns.Show(this);
|
||||
|
||||
m_path = wxGetCwd(); //TODO
|
||||
m_path = wxGetCwd() + "\\dev_hdd0\\game\\"; //TODO
|
||||
|
||||
Connect(GetId(), wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler(GameViewer::DClick));
|
||||
|
||||
@ -34,16 +34,13 @@ void GameViewer::LoadGames()
|
||||
if(!dir.HasSubDirs()) return;
|
||||
|
||||
wxString buf;
|
||||
if(!dir.GetFirst(&buf)) return;
|
||||
if(wxDirExists(buf)) m_games.Add(buf);
|
||||
|
||||
for(;;)
|
||||
for(bool ok = dir.GetFirst(&buf); ok; ok = dir.GetNext(&buf))
|
||||
{
|
||||
if(!dir.GetNext(&buf)) break;
|
||||
if(wxDirExists(buf)) m_games.Add(buf);
|
||||
if(wxDirExists(m_path + buf))
|
||||
m_games.Add(buf);
|
||||
}
|
||||
|
||||
//ConLog.Write("path: %s", m_path);
|
||||
//ConLog.Write("path: %s", m_path.c_str());
|
||||
//ConLog.Write("folders count: %d", m_games.GetCount());
|
||||
}
|
||||
|
||||
@ -52,7 +49,7 @@ void GameViewer::LoadPSF()
|
||||
m_game_data.Clear();
|
||||
for(uint i=0; i<m_games.GetCount(); ++i)
|
||||
{
|
||||
const wxString& path = m_games[i] + "\\" + "PARAM.SFO";
|
||||
const wxString& path = m_path + m_games[i] + "\\PARAM.SFO";
|
||||
if(!wxFileExists(path)) continue;
|
||||
vfsLocalFile f(path);
|
||||
PSFLoader psf(f);
|
||||
@ -91,7 +88,7 @@ void GameViewer::DClick(wxListEvent& event)
|
||||
long i = GetFirstSelected();
|
||||
if(i < 0) return;
|
||||
|
||||
const wxString& path = m_path + "\\" + m_game_data[i].root + "\\" + "USRDIR" + "\\" + "BOOT.BIN";
|
||||
const wxString& path = m_path + "\\" + m_game_data[i].root + "\\USRDIR\\BOOT.BIN";
|
||||
if(!wxFileExists(path))
|
||||
{
|
||||
ConLog.Error("Boot error: elf not found! [%s]", path.mb_str());
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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)
|
||||
{
|
||||
|
@ -6,7 +6,7 @@ struct PsfHeader
|
||||
u32 psf_magic;
|
||||
u32 psf_version;
|
||||
u32 psf_offset_key_table;
|
||||
u32 psf_offset_values_table;
|
||||
u32 psf_offset_data_table;
|
||||
u32 psf_entries_num;
|
||||
|
||||
bool CheckMagic() const { return psf_magic == *(u32*)"\0PSF"; }
|
||||
@ -14,13 +14,44 @@ struct PsfHeader
|
||||
|
||||
struct PsfDefTbl
|
||||
{
|
||||
u16 psf_name_tbl_offset;
|
||||
u16 psf_data_type;
|
||||
u32 psf_data_size;
|
||||
u32 psf_data_fsize;
|
||||
u16 psf_key_table_offset;
|
||||
u16 psf_param_fmt;
|
||||
u32 psf_param_len;
|
||||
u32 psf_param_max_len;
|
||||
u32 psf_data_tbl_offset;
|
||||
};
|
||||
|
||||
struct PsfEntry
|
||||
{
|
||||
char name[128];
|
||||
u16 fmt;
|
||||
char param[4096];
|
||||
|
||||
std::string Format() const
|
||||
{
|
||||
switch(fmt)
|
||||
{
|
||||
default:
|
||||
case 0x0400:
|
||||
case 0x0402:
|
||||
return FormatString();
|
||||
|
||||
case 0x0404:
|
||||
return wxString::Format("0x%x", FormatInteger()).c_str();
|
||||
}
|
||||
}
|
||||
|
||||
u32 FormatInteger() const
|
||||
{
|
||||
return *(u32*)param;
|
||||
}
|
||||
|
||||
char* FormatString() const
|
||||
{
|
||||
return (char*)param;
|
||||
}
|
||||
};
|
||||
|
||||
class PSFLoader
|
||||
{
|
||||
vfsStream& psf_f;
|
||||
@ -29,14 +60,19 @@ class PSFLoader
|
||||
public:
|
||||
PSFLoader(vfsStream& f);
|
||||
|
||||
wxArrayString m_table;
|
||||
Array<PsfEntry> m_entries;
|
||||
|
||||
PsfEntry* SearchEntry(const std::string& key);
|
||||
|
||||
//wxArrayString m_table;
|
||||
GameInfo m_info;
|
||||
PsfHeader psfhdr;
|
||||
Array<PsfDefTbl> m_psfindxs;
|
||||
virtual bool Load(bool show = true);
|
||||
virtual bool Close();
|
||||
|
||||
private:
|
||||
bool LoadHdr();
|
||||
bool LoadKeyTable();
|
||||
bool LoadValuesTable();
|
||||
bool LoadDataTable();
|
||||
};
|
Loading…
Reference in New Issue
Block a user