dolphin/Source/Core/Common/Src/SysConf.cpp

186 lines
4.7 KiB
C++

// Copyright (C) 2003 Dolphin Project.
// 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, version 2.0.
// 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 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "FileUtil.h"
#include "SysConf.h"
SysConf::SysConf()
: m_IsValid(false)
{
m_FilenameDefault = File::GetUserPath(F_WIISYSCONF_IDX);
m_IsValid = LoadFromFile(m_FilenameDefault.c_str());
}
SysConf::~SysConf()
{
if (!m_IsValid)
return;
Save();
Clear();
}
void SysConf::Clear()
{
for (std::vector<SSysConfEntry>::const_iterator i = m_Entries.begin();
i < m_Entries.end() - 1; i++)
delete [] i->data;
m_Entries.clear();
}
bool SysConf::LoadFromFile(const char *filename)
{
// Basic check
u64 size = File::GetSize(filename);
if (size == 0)
return false; //most likely: file does not exist
if (size != SYSCONF_SIZE)
{
PanicAlertT("Your SYSCONF file is the wrong size - should be 0x%04x (but is 0x%04llx)",
SYSCONF_SIZE, size);
return false;
}
FILE* f = fopen(filename, "rb");
if (f == NULL)
return false;
bool result = LoadFromFileInternal(f);
if (result)
{
// OK, done!
m_Filename = filename;
}
fclose(f);
return result;
}
bool SysConf::LoadFromFileInternal(FILE *f)
{
// Fill in infos
if (fread(&m_Header.version, sizeof(m_Header.version), 1, f) != 1) return false;
if (fread(&m_Header.numEntries, sizeof(m_Header.numEntries), 1, f) != 1) return false;
m_Header.numEntries = Common::swap16(m_Header.numEntries) + 1;
for (u16 index = 0; index < m_Header.numEntries; index++)
{
SSysConfEntry tmpEntry;
if (fread(&tmpEntry.offset, sizeof(tmpEntry.offset), 1, f) != 1) return false;
tmpEntry.offset = Common::swap16(tmpEntry.offset);
m_Entries.push_back(tmpEntry);
}
// Last offset is an invalid entry. We ignore it throughout this class
for (std::vector<SSysConfEntry>::iterator i = m_Entries.begin();
i < m_Entries.end() - 1; i++)
{
SSysConfEntry& curEntry = *i;
if (fseeko(f, curEntry.offset, SEEK_SET) != 0) return false;
u8 description = 0;
if (fread(&description, sizeof(description), 1, f) != 1) return false;
// Data type
curEntry.type = (SysconfType)((description & 0xe0) >> 5);
// Length of name in bytes - 1
curEntry.nameLength = (description & 0x1f) + 1;
// Name
if (fread(&curEntry.name, curEntry.nameLength, 1, f) != 1) return false;
curEntry.name[curEntry.nameLength] = '\0';
// Get length of data
curEntry.dataLength = 0;
switch (curEntry.type)
{
case Type_BigArray:
if (fread(&curEntry.dataLength, 2, 1, f) != 1) return false;
curEntry.dataLength = Common::swap16(curEntry.dataLength);
break;
case Type_SmallArray:
if (fread(&curEntry.dataLength, 1, 1, f) != 1) return false;
break;
case Type_Byte:
case Type_Bool:
curEntry.dataLength = 1;
break;
case Type_Short:
curEntry.dataLength = 2;
break;
case Type_Long:
curEntry.dataLength = 4;
break;
default:
PanicAlertT("Unknown entry type %i in SYSCONF (%s@%x)!",
curEntry.type, curEntry.name, curEntry.offset);
return false;
}
// Fill in the actual data
if (curEntry.dataLength)
{
curEntry.data = new u8[curEntry.dataLength];
if (fread(curEntry.data, curEntry.dataLength, 1, f) != 1) return false;
}
}
return true;
}
bool SysConf::SaveToFile(const char *filename)
{
FILE *f = fopen(filename, "r+b");
if (f == NULL)
return false;
for (std::vector<SSysConfEntry>::iterator i = m_Entries.begin();
i < m_Entries.end() - 1; i++)
{
// Seek to after the name of this entry
if (fseeko(f, i->offset + i->nameLength + 1, SEEK_SET) != 0) return false;
// We may have to write array length value...
if (i->type == Type_BigArray)
{
u16 tmpDataLength = Common::swap16(i->dataLength);
if (fwrite(&tmpDataLength, 2, 1, f) != 1) return false;
}
else if (i->type == Type_SmallArray)
{
if (fwrite(&i->dataLength, 1, 1, f) != 1) return false;
}
// Now write the actual data
if (fwrite(i->data, i->dataLength, 1, f) != 1) return false;
}
fclose(f);
return true;
}
bool SysConf::Save()
{
if (!m_IsValid)
return false;
return SaveToFile(m_Filename.c_str());
}
bool SysConf::Reload()
{
if (m_IsValid)
Clear();
std::string& filename = m_Filename.empty() ? m_FilenameDefault : m_Filename;
m_IsValid = LoadFromFile(filename.c_str());
return m_IsValid;
}