163 lines
5.2 KiB
C++
163 lines
5.2 KiB
C++
#pragma once
|
|
|
|
#include <phosg/Encoding.hh>
|
|
#include <phosg/Vector.hh>
|
|
|
|
#include "Text.hh"
|
|
|
|
constexpr double radians_for_fixed_point_angle(uint16_t angle) {
|
|
return static_cast<double>(angle * 2 * M_PI) / 0x10000;
|
|
}
|
|
|
|
struct VectorXZF {
|
|
le_float x = 0.0;
|
|
le_float z = 0.0;
|
|
|
|
inline VectorXZF operator-() const {
|
|
return VectorXZF{-this->x, -this->z};
|
|
}
|
|
|
|
inline VectorXZF operator+(const VectorXZF& other) const {
|
|
return VectorXZF{this->x + other.x, this->z + other.z};
|
|
}
|
|
inline VectorXZF operator-(const VectorXZF& other) const {
|
|
return VectorXZF{this->x - other.x, this->z - other.z};
|
|
}
|
|
|
|
inline bool operator==(const VectorXZF& other) const {
|
|
return ((this->x == other.x) && (this->z == other.z));
|
|
}
|
|
inline bool operator!=(const VectorXZF& other) const {
|
|
return !this->operator==(other);
|
|
}
|
|
|
|
inline double norm() const {
|
|
return sqrt(this->norm2());
|
|
}
|
|
inline double norm2() const {
|
|
return ((this->x * this->x) + (this->z * this->z));
|
|
}
|
|
inline double dist(const VectorXZF& other) const {
|
|
return sqrt(this->dist2(other));
|
|
}
|
|
inline double dist2(const VectorXZF& other) const {
|
|
double x = this->x - other.x;
|
|
double z = this->z - other.z;
|
|
return ((x * x) + (z * z));
|
|
}
|
|
|
|
inline VectorXZF rotate_y(double angle) const {
|
|
double s = sin(angle);
|
|
double c = cos(angle);
|
|
return VectorXZF{this->x * c - this->z * s, this->x * s + this->z * c};
|
|
}
|
|
|
|
inline std::string str() const {
|
|
return std::format("[VectorXZF x={:g} z={:g}]", this->x, this->z);
|
|
}
|
|
} __packed_ws__(VectorXZF, 0x08);
|
|
|
|
struct VectorXYZF {
|
|
le_float x = 0.0;
|
|
le_float y = 0.0;
|
|
le_float z = 0.0;
|
|
|
|
inline operator VectorXZF() const {
|
|
return VectorXZF{this->x, this->z};
|
|
}
|
|
|
|
inline VectorXYZF operator-() const {
|
|
return VectorXYZF{-this->x, -this->y, -this->z};
|
|
}
|
|
|
|
inline VectorXYZF operator+(const VectorXYZF& other) const {
|
|
return VectorXYZF{this->x + other.x, this->y + other.y, this->z + other.z};
|
|
}
|
|
inline VectorXYZF operator-(const VectorXYZF& other) const {
|
|
return VectorXYZF{this->x - other.x, this->y - other.y, this->z - other.z};
|
|
}
|
|
|
|
inline bool operator==(const VectorXYZF& other) const {
|
|
return ((this->x == other.x) && (this->y == other.y) && (this->z == other.z));
|
|
}
|
|
inline bool operator!=(const VectorXYZF& other) const {
|
|
return !this->operator==(other);
|
|
}
|
|
|
|
inline double norm() const {
|
|
return sqrt(this->norm2());
|
|
}
|
|
inline double norm2() const {
|
|
return ((this->x * this->x) + (this->y * this->y) + (this->z * this->z));
|
|
}
|
|
|
|
inline VectorXYZF rotate_x(double angle) const {
|
|
double s = sin(angle);
|
|
double c = cos(angle);
|
|
return VectorXYZF{this->x, this->y * c - this->z * s, this->y * s + this->z * c};
|
|
}
|
|
inline VectorXYZF rotate_y(double angle) const {
|
|
double s = sin(angle);
|
|
double c = cos(angle);
|
|
return VectorXYZF{this->x * c + this->z * s, this->y, -this->x * s + this->z * c};
|
|
}
|
|
inline VectorXYZF rotate_z(double angle) const {
|
|
double s = sin(angle);
|
|
double c = cos(angle);
|
|
return VectorXYZF{this->x * c - this->y * s, this->x * s + this->y * c, this->z};
|
|
}
|
|
|
|
inline std::string str() const {
|
|
return std::format("[VectorXYZF x={:g} y={:g} z={:g}]", this->x, this->y, this->z);
|
|
}
|
|
} __packed_ws__(VectorXYZF, 0x0C);
|
|
|
|
struct VectorXYZTF {
|
|
le_float x = 0.0;
|
|
le_float y = 0.0;
|
|
le_float z = 0.0;
|
|
le_float t = 0.0;
|
|
} __packed_ws__(VectorXYZTF, 0x10);
|
|
|
|
struct VectorXYZI {
|
|
le_uint32_t x = 0;
|
|
le_uint32_t y = 0;
|
|
le_uint32_t z = 0;
|
|
} __packed_ws__(VectorXYZI, 0x0C);
|
|
|
|
template <bool BE>
|
|
struct ArrayRefT {
|
|
static constexpr bool IsBE = BE;
|
|
/* 00 */ U32T<BE> count;
|
|
/* 04 */ U32T<BE> offset;
|
|
/* 08 */
|
|
} __packed_ws_be__(ArrayRefT, 8);
|
|
using ArrayRef = ArrayRefT<false>;
|
|
using ArrayRefBE = ArrayRefT<true>;
|
|
|
|
template <bool BE>
|
|
struct RELFileFooterT {
|
|
static constexpr bool IsBE = BE;
|
|
// Relocations is a list of words (le_uint16_t on DC/PC/XB/BB, be_uint16_t on GC) containing the number of
|
|
// doublewords (uint32_t) to skip for each relocation. The relocation pointer starts at the beginning of the file
|
|
// data, and advances by the value of one relocation word (times 4) before each relocation. At each relocated
|
|
// doubleword, the address of the first byte of the file is added to the existing value.
|
|
//
|
|
// For example, if the file data contains the following data (where R specifies doublewords to relocate):
|
|
// RR RR RR RR ?? ?? ?? ?? ?? ?? ?? ?? RR RR RR RR
|
|
// RR RR RR RR ?? ?? ?? ?? RR RR RR RR
|
|
// then the relocation words should be 0000, 0003, 0001, and 0002.
|
|
//
|
|
// If there is a small number of relocations, they may be placed in the unused fields of this structure to save space
|
|
// and/or confuse reverse engineers. The game never accesses the last 12 bytes of this structure unless
|
|
// relocations_offset points there, so those 12 bytes may also be omitted entirely in some situations (e.g. in the B2
|
|
// command, without changing code_size, so code_size would technically extend beyond the end of the B2 command).
|
|
U32T<BE> relocations_offset = 0;
|
|
U32T<BE> num_relocations = 0;
|
|
parray<U32T<BE>, 2> unused1;
|
|
U32T<BE> root_offset = 0;
|
|
parray<U32T<BE>, 3> unused2;
|
|
} __packed_ws_be__(RELFileFooterT, 0x20);
|
|
using RELFileFooter = RELFileFooterT<false>;
|
|
using RELFileFooterBE = RELFileFooterT<true>;
|