added psf file format
This commit is contained in:
parent
47e2619b51
commit
8afc346f55
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.16.3)
|
cmake_minimum_required(VERSION 3.16.3)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 20)
|
set(CMAKE_CXX_STANDARD 23)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||||
|
|
||||||
if (NOT CMAKE_BUILD_TYPE)
|
if (NOT CMAKE_BUILD_TYPE)
|
||||||
|
@ -127,11 +127,21 @@ set(HOST_SOURCES src/Emulator/Host/controller.cpp
|
||||||
src/Emulator/Host/controller.h
|
src/Emulator/Host/controller.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
set(COMMON src/common/types.h
|
||||||
|
src/common/endian.h
|
||||||
|
src/common/concepts.h
|
||||||
|
src/common/io_file.cpp
|
||||||
|
src/common/io_file.h
|
||||||
|
)
|
||||||
|
|
||||||
|
set(FILE_FORMAT src/core/file_format/psf.cpp
|
||||||
|
src/core/file_format/psf.h
|
||||||
|
)
|
||||||
|
|
||||||
add_executable(shadps4
|
add_executable(shadps4
|
||||||
src/common/assert.cpp
|
src/common/assert.cpp
|
||||||
src/common/assert.h
|
src/common/assert.h
|
||||||
src/common/bounded_threadsafe_queue.h
|
src/common/bounded_threadsafe_queue.h
|
||||||
src/common/concepts.h
|
|
||||||
src/common/debug.h
|
src/common/debug.h
|
||||||
src/common/disassembler.cpp
|
src/common/disassembler.cpp
|
||||||
src/common/disassembler.h
|
src/common/disassembler.h
|
||||||
|
@ -139,8 +149,6 @@ add_executable(shadps4
|
||||||
src/common/discord.h
|
src/common/discord.h
|
||||||
src/common/error.cpp
|
src/common/error.cpp
|
||||||
src/common/error.h
|
src/common/error.h
|
||||||
src/common/io_file.cpp
|
|
||||||
src/common/io_file.h
|
|
||||||
src/common/path_util.cpp
|
src/common/path_util.cpp
|
||||||
src/common/path_util.h
|
src/common/path_util.h
|
||||||
src/common/logging/backend.cpp
|
src/common/logging/backend.cpp
|
||||||
|
@ -162,7 +170,6 @@ add_executable(shadps4
|
||||||
src/common/string_util.h
|
src/common/string_util.h
|
||||||
src/common/thread.cpp
|
src/common/thread.cpp
|
||||||
src/common/thread.h
|
src/common/thread.h
|
||||||
src/common/types.h
|
|
||||||
src/common/uint128.h
|
src/common/uint128.h
|
||||||
src/common/version.h
|
src/common/version.h
|
||||||
${LIBC_SOURCES}
|
${LIBC_SOURCES}
|
||||||
|
@ -227,6 +234,8 @@ add_executable(shadps4
|
||||||
src/core/hle/libraries/libkernel/time_management.h
|
src/core/hle/libraries/libkernel/time_management.h
|
||||||
src/core/tls.cpp
|
src/core/tls.cpp
|
||||||
src/core/tls.h
|
src/core/tls.h
|
||||||
|
${COMMON}
|
||||||
|
${FILE_FORMAT}
|
||||||
)
|
)
|
||||||
|
|
||||||
create_target_directory_groups(shadps4)
|
create_target_directory_groups(shadps4)
|
||||||
|
|
|
@ -0,0 +1,242 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (c) 2014-2016 Alexandro Sanchez Bach. All rights reserved.
|
||||||
|
* Released under GPL v2 license. Read LICENSE for more details.
|
||||||
|
* Some modifications for using with shadps4 by georgemoralis
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <bit>
|
||||||
|
#include <concepts>
|
||||||
|
#include "common/types.h"
|
||||||
|
|
||||||
|
namespace Common {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Native endianness
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
using NativeEndian = T;
|
||||||
|
|
||||||
|
template <std::integral T>
|
||||||
|
class SwappedEndian {
|
||||||
|
public:
|
||||||
|
const T& Raw() const {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
T Swap() const {
|
||||||
|
return std::byteswap(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FromRaw(const T& value) {
|
||||||
|
data = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FromSwap(const T& value) {
|
||||||
|
data = std::byteswap(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
operator const T() const {
|
||||||
|
return Swap();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T1>
|
||||||
|
explicit operator const SwappedEndian<T1>() const {
|
||||||
|
SwappedEndian<T1> res;
|
||||||
|
if (sizeof(T1) < sizeof(T)) {
|
||||||
|
res.FromRaw(Raw() >> ((sizeof(T) - sizeof(T1)) * 8));
|
||||||
|
} else if (sizeof(T1) > sizeof(T)) {
|
||||||
|
res.FromSwap(Swap());
|
||||||
|
} else {
|
||||||
|
res.FromRaw(Raw());
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
SwappedEndian<T>& operator=(const T& right) {
|
||||||
|
FromSwap(right);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
SwappedEndian<T>& operator=(const SwappedEndian<T>& right) = default;
|
||||||
|
|
||||||
|
template <typename T1>
|
||||||
|
SwappedEndian<T>& operator+=(T1 right) {
|
||||||
|
return *this = T(*this) + right;
|
||||||
|
}
|
||||||
|
template <typename T1>
|
||||||
|
SwappedEndian<T>& operator-=(T1 right) {
|
||||||
|
return *this = T(*this) - right;
|
||||||
|
}
|
||||||
|
template <typename T1>
|
||||||
|
SwappedEndian<T>& operator*=(T1 right) {
|
||||||
|
return *this = T(*this) * right;
|
||||||
|
}
|
||||||
|
template <typename T1>
|
||||||
|
SwappedEndian<T>& operator/=(T1 right) {
|
||||||
|
return *this = T(*this) / right;
|
||||||
|
}
|
||||||
|
template <typename T1>
|
||||||
|
SwappedEndian<T>& operator%=(T1 right) {
|
||||||
|
return *this = T(*this) % right;
|
||||||
|
}
|
||||||
|
template <typename T1>
|
||||||
|
SwappedEndian<T>& operator&=(T1 right) {
|
||||||
|
return *this = T(*this) & right;
|
||||||
|
}
|
||||||
|
template <typename T1>
|
||||||
|
SwappedEndian<T>& operator|=(T1 right) {
|
||||||
|
return *this = T(*this) | right;
|
||||||
|
}
|
||||||
|
template <typename T1>
|
||||||
|
SwappedEndian<T>& operator^=(T1 right) {
|
||||||
|
return *this = T(*this) ^ right;
|
||||||
|
}
|
||||||
|
template <typename T1>
|
||||||
|
SwappedEndian<T>& operator<<=(T1 right) {
|
||||||
|
return *this = T(*this) << right;
|
||||||
|
}
|
||||||
|
template <typename T1>
|
||||||
|
SwappedEndian<T>& operator>>=(T1 right) {
|
||||||
|
return *this = T(*this) >> right;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T1>
|
||||||
|
SwappedEndian<T>& operator+=(const SwappedEndian<T1>& right) {
|
||||||
|
return *this = Swap() + right.Swap();
|
||||||
|
}
|
||||||
|
template <typename T1>
|
||||||
|
SwappedEndian<T>& operator-=(const SwappedEndian<T1>& right) {
|
||||||
|
return *this = Swap() - right.Swap();
|
||||||
|
}
|
||||||
|
template <typename T1>
|
||||||
|
SwappedEndian<T>& operator*=(const SwappedEndian<T1>& right) {
|
||||||
|
return *this = Swap() * right.Swap();
|
||||||
|
}
|
||||||
|
template <typename T1>
|
||||||
|
SwappedEndian<T>& operator/=(const SwappedEndian<T1>& right) {
|
||||||
|
return *this = Swap() / right.Swap();
|
||||||
|
}
|
||||||
|
template <typename T1>
|
||||||
|
SwappedEndian<T>& operator%=(const SwappedEndian<T1>& right) {
|
||||||
|
return *this = Swap() % right.Swap();
|
||||||
|
}
|
||||||
|
template <typename T1>
|
||||||
|
SwappedEndian<T>& operator&=(const SwappedEndian<T1>& right) {
|
||||||
|
return *this = Raw() & right.Raw();
|
||||||
|
}
|
||||||
|
template <typename T1>
|
||||||
|
SwappedEndian<T>& operator|=(const SwappedEndian<T1>& right) {
|
||||||
|
return *this = Raw() | right.Raw();
|
||||||
|
}
|
||||||
|
template <typename T1>
|
||||||
|
SwappedEndian<T>& operator^=(const SwappedEndian<T1>& right) {
|
||||||
|
return *this = Raw() ^ right.Raw();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T1>
|
||||||
|
SwappedEndian<T> operator&(const SwappedEndian<T1>& right) const {
|
||||||
|
return SwappedEndian<T>{Raw() & right.Raw()};
|
||||||
|
}
|
||||||
|
template <typename T1>
|
||||||
|
SwappedEndian<T> operator|(const SwappedEndian<T1>& right) const {
|
||||||
|
return SwappedEndian<T>{Raw() | right.Raw()};
|
||||||
|
}
|
||||||
|
template <typename T1>
|
||||||
|
SwappedEndian<T> operator^(const SwappedEndian<T1>& right) const {
|
||||||
|
return SwappedEndian<T>{Raw() ^ right.Raw()};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T1>
|
||||||
|
bool operator==(T1 right) const {
|
||||||
|
return (T1)Swap() == right;
|
||||||
|
}
|
||||||
|
template <typename T1>
|
||||||
|
bool operator!=(T1 right) const {
|
||||||
|
return !(*this == right);
|
||||||
|
}
|
||||||
|
template <typename T1>
|
||||||
|
bool operator>(T1 right) const {
|
||||||
|
return (T1)Swap() > right;
|
||||||
|
}
|
||||||
|
template <typename T1>
|
||||||
|
bool operator<(T1 right) const {
|
||||||
|
return (T1)Swap() < right;
|
||||||
|
}
|
||||||
|
template <typename T1>
|
||||||
|
bool operator>=(T1 right) const {
|
||||||
|
return (T1)Swap() >= right;
|
||||||
|
}
|
||||||
|
template <typename T1>
|
||||||
|
bool operator<=(T1 right) const {
|
||||||
|
return (T1)Swap() <= right;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T1>
|
||||||
|
bool operator==(const SwappedEndian<T1>& right) const {
|
||||||
|
return Raw() == right.Raw();
|
||||||
|
}
|
||||||
|
template <typename T1>
|
||||||
|
bool operator!=(const SwappedEndian<T1>& right) const {
|
||||||
|
return !(*this == right);
|
||||||
|
}
|
||||||
|
template <typename T1>
|
||||||
|
bool operator>(const SwappedEndian<T1>& right) const {
|
||||||
|
return (T1)Swap() > right.Swap();
|
||||||
|
}
|
||||||
|
template <typename T1>
|
||||||
|
bool operator<(const SwappedEndian<T1>& right) const {
|
||||||
|
return (T1)Swap() < right.Swap();
|
||||||
|
}
|
||||||
|
template <typename T1>
|
||||||
|
bool operator>=(const SwappedEndian<T1>& right) const {
|
||||||
|
return (T1)Swap() >= right.Swap();
|
||||||
|
}
|
||||||
|
template <typename T1>
|
||||||
|
bool operator<=(const SwappedEndian<T1>& right) const {
|
||||||
|
return (T1)Swap() <= right.Swap();
|
||||||
|
}
|
||||||
|
|
||||||
|
SwappedEndian<T> operator++(int) {
|
||||||
|
SwappedEndian<T> res = *this;
|
||||||
|
*this += 1;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
SwappedEndian<T> operator--(int) {
|
||||||
|
SwappedEndian<T> res = *this;
|
||||||
|
*this -= 1;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
SwappedEndian<T>& operator++() {
|
||||||
|
*this += 1;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
SwappedEndian<T>& operator--() {
|
||||||
|
*this -= 1;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
T data;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
using LittleEndian = std::conditional_t<std::endian::native == std::endian::little, NativeEndian<T>,
|
||||||
|
SwappedEndian<T>>;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
using BigEndian =
|
||||||
|
std::conditional_t<std::endian::native == std::endian::big, NativeEndian<T>, SwappedEndian<T>>;
|
||||||
|
|
||||||
|
} // namespace Common
|
||||||
|
|
||||||
|
using u16_be = Common::BigEndian<u16>;
|
||||||
|
using u32_be = Common::BigEndian<u32>;
|
||||||
|
using u64_be = Common::BigEndian<u64>;
|
||||||
|
|
||||||
|
using u16_le = Common::LittleEndian<u16>;
|
||||||
|
using u32_le = Common::LittleEndian<u32>;
|
||||||
|
using u64_le = Common::LittleEndian<u64>;
|
|
@ -0,0 +1,59 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "common/io_file.h"
|
||||||
|
#include "psf.h"
|
||||||
|
|
||||||
|
PSF::PSF() = default;
|
||||||
|
|
||||||
|
PSF::~PSF() = default;
|
||||||
|
|
||||||
|
bool PSF::open(const std::string& filepath) {
|
||||||
|
Common::FS::IOFile file(filepath,Common::FS::FileAccessMode::Read);
|
||||||
|
if (!file.IsOpen()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const u64 psfSize = file.GetSize();
|
||||||
|
psf.resize(psfSize);
|
||||||
|
file.Seek(0);
|
||||||
|
file.ReadRaw<u8>(&psf[0], psfSize);
|
||||||
|
|
||||||
|
// Parse file contents
|
||||||
|
PSFHeader header;
|
||||||
|
std::memcpy(&header, psf.data(), sizeof(header));
|
||||||
|
for (u32 i = 0; i < header.index_table_entries; i++) {
|
||||||
|
PSFEntry entry;
|
||||||
|
std::memcpy(&entry, &psf[sizeof(PSFHeader) + i * sizeof(PSFEntry)], sizeof(entry));
|
||||||
|
|
||||||
|
const std::string key = (char*)&psf[header.key_table_offset + entry.key_offset];
|
||||||
|
if (entry.param_fmt == PSFEntry::Fmt::TextRaw ||
|
||||||
|
entry.param_fmt == PSFEntry::Fmt::TextNormal) {
|
||||||
|
map_strings[key] = (char*)&psf[header.data_table_offset + entry.data_offset];
|
||||||
|
}
|
||||||
|
if (entry.param_fmt == PSFEntry::Fmt::Integer) {
|
||||||
|
u32 value;
|
||||||
|
std::memcpy(&value, &psf[header.data_table_offset + entry.data_offset], sizeof(value));
|
||||||
|
map_integers[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string PSF::GetString(const std::string& key) {
|
||||||
|
if (map_strings.find(key) != map_strings.end()) {
|
||||||
|
return map_strings.at(key);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 PSF::GetInteger(const std::string& key) {
|
||||||
|
if (map_integers.find(key) != map_integers.end()) {
|
||||||
|
return map_integers.at(key); // TODO std::invalid_argument exception if it fails?
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
#include "common/endian.h"
|
||||||
|
|
||||||
|
struct PSFHeader {
|
||||||
|
u32_be magic;
|
||||||
|
u32_le version;
|
||||||
|
u32_le key_table_offset;
|
||||||
|
u32_le data_table_offset;
|
||||||
|
u32_le index_table_entries;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PSFEntry {
|
||||||
|
enum Fmt : u16 {
|
||||||
|
TextRaw = 0x0400, // String in UTF-8 format and not NULL terminated
|
||||||
|
TextNormal = 0x0402, // String in UTF-8 format and NULL terminated
|
||||||
|
Integer = 0x0404, // Unsigned 32-bit integer
|
||||||
|
};
|
||||||
|
|
||||||
|
u16_le key_offset;
|
||||||
|
u16_be param_fmt;
|
||||||
|
u32_le param_len;
|
||||||
|
u32_le param_max_len;
|
||||||
|
u32_le data_offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PSF {
|
||||||
|
public:
|
||||||
|
PSF();
|
||||||
|
~PSF();
|
||||||
|
|
||||||
|
bool open(const std::string& filepath);
|
||||||
|
|
||||||
|
std::string GetString(const std::string& key);
|
||||||
|
u32 GetInteger(const std::string& key);
|
||||||
|
|
||||||
|
std::unordered_map<std::string, std::string> map_strings;
|
||||||
|
std::unordered_map<std::string, u32> map_integers;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<u8> psf;
|
||||||
|
};
|
Loading…
Reference in New Issue