Changeset View
Changeset View
Standalone View
Standalone View
source/ps/XMB/XMBData.cpp
- This file was moved from source/ps/XML/XeroXMB.cpp.
/* Copyright (C) 2015 Wildfire Games. | /* Copyright (C) 2021 Wildfire Games. | ||||
* This file is part of 0 A.D. | * This file is part of 0 A.D. | ||||
* | * | ||||
* 0 A.D. is free software: you can redistribute it and/or modify | * 0 A.D. is free software: you can redistribute it and/or modify | ||||
* it under the terms of the GNU General Public License as published by | * it under the terms of the GNU General Public License as published by | ||||
* the Free Software Foundation, either version 2 of the License, or | * the Free Software Foundation, either version 2 of the License, or | ||||
* (at your option) any later version. | * (at your option) any later version. | ||||
* | * | ||||
* 0 A.D. is distributed in the hope that it will be useful, | * 0 A.D. is distributed in the hope that it will be useful, | ||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
* GNU General Public License for more details. | * GNU General Public License for more details. | ||||
* | * | ||||
* You should have received a copy of the GNU General Public License | * You should have received a copy of the GNU General Public License | ||||
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. | * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. | ||||
*/ | */ | ||||
#include "precompiled.h" | #include "precompiled.h" | ||||
#include "Xeromyces.h" | |||||
#include "lib/byte_order.h" // FOURCC_LE | #include "lib/byte_order.h" // FOURCC_LE | ||||
#include "ps/XMB/XMBStorage.h" | |||||
#include "ps/XML/Xeromyces.h" | |||||
// external linkage (also used by Xeromyces.cpp) | const char* XMBStorage::HeaderMagicStr = "XMB0"; | ||||
const char* HeaderMagicStr = "XMB0"; | const char* XMBStorage::UnfinishedHeaderMagicStr = "XMBu"; | ||||
const char* UnfinishedHeaderMagicStr = "XMBu"; | |||||
// Arbitrary version number - change this if we update the code and | // Arbitrary version number - change this if we update the code and | ||||
// need to invalidate old users' caches | // need to invalidate old users' caches | ||||
const u32 XMBVersion = 3; | const u32 XMBStorage::XMBVersion = 4; | ||||
template<typename T> | template<typename T> | ||||
static inline T read(const void* ptr) | static inline T read(const void* ptr) | ||||
{ | { | ||||
T ret; | T ret; | ||||
memcpy(&ret, ptr, sizeof(T)); | memcpy(&ret, ptr, sizeof(T)); | ||||
return ret; | return ret; | ||||
} | } | ||||
bool XMBFile::Initialise(const char* FileData) | bool XMBData::Initialise(const XMBStorage& doc) | ||||
{ | { | ||||
m_Pointer = FileData; | const char* start = reinterpret_cast<const char*>(doc.m_Buffer.get()); | ||||
m_Pointer = start; | |||||
char Header[5] = { 0 }; | char Header[5] = { 0 }; | ||||
strncpy_s(Header, 5, m_Pointer, 4); | strncpy_s(Header, 5, m_Pointer, 4); | ||||
m_Pointer += 4; | m_Pointer += 4; | ||||
// (c.f. @return documentation of this function) | |||||
if(!strcmp(Header, UnfinishedHeaderMagicStr)) | if (strcmp(Header, XMBStorage::UnfinishedHeaderMagicStr) == 0) | ||||
return false; | return false; | ||||
ENSURE(!strcmp(Header, HeaderMagicStr) && "Invalid XMB header!"); | ENSURE(strcmp(Header, XMBStorage::HeaderMagicStr) == 0 && "Invalid XMB header!"); | ||||
u32 Version = read<u32>(m_Pointer); | u32 Version = read<u32>(m_Pointer); | ||||
m_Pointer += 4; | m_Pointer += 4; | ||||
if (Version != XMBVersion) | if (Version != XMBStorage::XMBVersion) | ||||
return false; | return false; | ||||
int i; | |||||
// FIXME Check that m_Pointer doesn't end up past the end of the buffer | // FIXME Check that m_Pointer doesn't end up past the end of the buffer | ||||
// (it shouldn't be all that dangerous since we're only doing read-only | // (it shouldn't be all that dangerous since we're only doing read-only | ||||
// access, but it might crash on an invalid file, reading a couple of | // access, but it might crash on an invalid file, reading a couple of | ||||
// billion random element names from RAM) | // billion random element names from RAM) | ||||
#ifdef XERO_USEMAP | m_ElementPointer = start + read<u32>(m_Pointer); m_Pointer += 4; | ||||
// Build a std::map of all the names->ids | |||||
u32 ElementNameCount = read<u32>(m_Pointer); m_Pointer += 4; | |||||
for (i = 0; i < ElementNameCount; ++i) | |||||
m_ElementNames[ReadZStr8()] = i; | |||||
u32 AttributeNameCount = read<u32>(m_Pointer); m_Pointer += 4; | |||||
for (i = 0; i < AttributeNameCount; ++i) | |||||
m_AttributeNames[ReadZStr8()] = i; | |||||
#else | |||||
// Ignore all the names for now, and skip over them | |||||
// (remembering the position of the first) | |||||
m_ElementNameCount = read<int>(m_Pointer); m_Pointer += 4; | m_ElementNameCount = read<int>(m_Pointer); m_Pointer += 4; | ||||
m_ElementPointer = m_Pointer; | m_AttributePointer = start + read<u32>(m_Pointer); m_Pointer += 4; | ||||
for (i = 0; i < m_ElementNameCount; ++i) | |||||
m_Pointer += 4 + read<int>(m_Pointer); // skip over the string | |||||
m_AttributeNameCount = read<int>(m_Pointer); m_Pointer += 4; | m_AttributeNameCount = read<int>(m_Pointer); m_Pointer += 4; | ||||
m_AttributePointer = m_Pointer; | // At this point m_Pointer points to the element start, as expected. | ||||
for (i = 0; i < m_AttributeNameCount; ++i) | |||||
m_Pointer += 4 + read<int>(m_Pointer); // skip over the string | |||||
#endif | |||||
return true; // success | return true; // success | ||||
} | } | ||||
std::string XMBFile::ReadZStr8() | XMBElement XMBData::GetRoot() const | ||||
{ | |||||
int Length = read<int>(m_Pointer); | |||||
m_Pointer += 4; | |||||
std::string String (m_Pointer); // reads up until the first NULL | |||||
m_Pointer += Length; | |||||
return String; | |||||
} | |||||
XMBElement XMBFile::GetRoot() const | |||||
{ | { | ||||
return XMBElement(m_Pointer); | return XMBElement(m_Pointer); | ||||
} | } | ||||
int XMBData::GetElementID(const char* Name) const | |||||
#ifdef XERO_USEMAP | |||||
int XMBFile::GetElementID(const char* Name) const | |||||
{ | |||||
return m_ElementNames[Name]; | |||||
} | |||||
int XMBFile::GetAttributeID(const char* Name) const | |||||
{ | |||||
return m_AttributeNames[Name]; | |||||
} | |||||
#else // #ifdef XERO_USEMAP | |||||
int XMBFile::GetElementID(const char* Name) const | |||||
{ | { | ||||
const char* Pos = m_ElementPointer; | const char* Pos = m_ElementPointer; | ||||
int len = (int)strlen(Name)+1; // count bytes, including null terminator | int len = (int)strlen(Name)+1; // count bytes, including null terminator | ||||
// Loop through each string to find a match | // Loop through each string to find a match | ||||
for (int i = 0; i < m_ElementNameCount; ++i) | for (int i = 0; i < m_ElementNameCount; ++i) | ||||
{ | { | ||||
// See if this could be the right string, checking its | // See if this could be the right string, checking its | ||||
// length and then its contents | // length and then its contents | ||||
if (read<int>(Pos) == len && strncasecmp(Pos+4, Name, len) == 0) | if (read<int>(Pos) == len && strncasecmp(Pos+4, Name, len) == 0) | ||||
return i; | return static_cast<int>(Pos - m_ElementPointer); | ||||
// If not, jump to the next string | // If not, jump to the next string | ||||
Pos += 4 + read<int>(Pos); | Pos += 4 + read<int>(Pos); | ||||
} | } | ||||
// Failed | // Failed | ||||
return -1; | return -1; | ||||
} | } | ||||
int XMBFile::GetAttributeID(const char* Name) const | int XMBData::GetAttributeID(const char* Name) const | ||||
{ | { | ||||
const char* Pos = m_AttributePointer; | const char* Pos = m_AttributePointer; | ||||
int len = (int)strlen(Name)+1; // count bytes, including null terminator | int len = (int)strlen(Name)+1; // count bytes, including null terminator | ||||
// Loop through each string to find a match | // Loop through each string to find a match | ||||
for (int i = 0; i < m_AttributeNameCount; ++i) | for (int i = 0; i < m_AttributeNameCount; ++i) | ||||
{ | { | ||||
// See if this could be the right string, checking its | // See if this could be the right string, checking its | ||||
// length and then its contents | // length and then its contents | ||||
if (read<int>(Pos) == len && strncasecmp(Pos+4, Name, len) == 0) | if (read<int>(Pos) == len && strncasecmp(Pos+4, Name, len) == 0) | ||||
return i; | return static_cast<int>(Pos - m_AttributePointer); | ||||
// If not, jump to the next string | // If not, jump to the next string | ||||
Pos += 4 + read<int>(Pos); | Pos += 4 + read<int>(Pos); | ||||
} | } | ||||
// Failed | // Failed | ||||
return -1; | return -1; | ||||
} | } | ||||
#endif // #ifdef XERO_USEMAP / #else | |||||
const char* XMBData::GetElementString(const int ID) const | |||||
// Relatively inefficient, so only use when | |||||
// laziness overcomes the need for speed | |||||
std::string XMBFile::GetElementString(const int ID) const | |||||
{ | { | ||||
const char* Pos = m_ElementPointer; | return reinterpret_cast<const char*>(m_ElementPointer + ID + 4); | ||||
for (int i = 0; i < ID; ++i) | |||||
Pos += 4 + read<int>(Pos); | |||||
return std::string(Pos+4); | |||||
} | } | ||||
std::string XMBFile::GetAttributeString(const int ID) const | const char* XMBData::GetAttributeString(const int ID) const | ||||
{ | { | ||||
const char* Pos = m_AttributePointer; | return reinterpret_cast<const char*>(m_AttributePointer + ID + 4); | ||||
for (int i = 0; i < ID; ++i) | |||||
Pos += 4 + read<int>(Pos); | |||||
return std::string(Pos+4); | |||||
} | } | ||||
std::string_view XMBData::GetElementStringView(const int ID) const | |||||
{ | |||||
return std::string_view(reinterpret_cast<const char*>(m_ElementPointer + ID + 4), read<int>(m_ElementPointer + ID) - 1); | |||||
} | |||||
std::string_view XMBData::GetAttributeStringView(const int ID) const | |||||
{ | |||||
return std::string_view(reinterpret_cast<const char*>(m_AttributePointer + ID + 4), read<int>(m_AttributePointer + ID) - 1); | |||||
} | |||||
int XMBElement::GetNodeName() const | int XMBElement::GetNodeName() const | ||||
{ | { | ||||
if (m_Pointer == NULL) | if (m_Pointer == NULL) | ||||
return -1; | return -1; | ||||
return read<int>(m_Pointer + 4); // == ElementName | return read<int>(m_Pointer + 4); // == ElementName | ||||
} | } | ||||
▲ Show 20 Lines • Show All 157 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator