diff --git a/CMakeLists.txt b/CMakeLists.txt index e6678b8a..df71ccf0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -128,6 +128,7 @@ add_library(lego1 SHARED LEGO1/mxloopingflcpresenter.cpp LEGO1/mxloopingmidipresenter.cpp LEGO1/mxloopingsmkpresenter.cpp + LEGO1/mxmatrix.cpp LEGO1/mxmediapresenter.cpp LEGO1/mxmidipresenter.cpp LEGO1/mxmusicpresenter.cpp @@ -156,6 +157,7 @@ add_library(lego1 SHARED LEGO1/mxunknown100dc6b0.cpp LEGO1/mxunknown100dc6e0.cpp LEGO1/mxvariabletable.cpp + LEGO1/mxvector.cpp LEGO1/mxvideomanager.cpp LEGO1/mxvideoparam.cpp LEGO1/mxvideoparamflags.cpp diff --git a/LEGO1/mxmatrix.cpp b/LEGO1/mxmatrix.cpp new file mode 100644 index 00000000..534db6a9 --- /dev/null +++ b/LEGO1/mxmatrix.cpp @@ -0,0 +1,188 @@ + +#include "mxmatrix.h" + +#include +#include "math.h" + +#include "decomp.h" + +DECOMP_SIZE_ASSERT(MxMatrix, 0x8); +DECOMP_SIZE_ASSERT(MxMatrixData, 0x48); + +// OFFSET: LEGO1 0x10002340 +void MxMatrix::EqualsMxMatrix(const MxMatrix *p_other) +{ + memcpy(m_data, p_other->m_data, 16 * sizeof(float)); +} + +// OFFSET: LEGO1 0x10002320 +void MxMatrix::EqualsMatrixData(const float *p_matrix) +{ + memcpy(m_data, p_matrix, 16 * sizeof(float)); +} + +// OFFSET: LEGO1 0x10002370 +void MxMatrix::SetData(float *p_data) +{ + m_data = p_data; +} + +// OFFSET: LEGO1 0x10002360 +void MxMatrix::AnotherSetData(float *p_data) +{ + m_data = p_data; +} + +// OFFSET: LEGO1 0x10002390 +float *MxMatrix::GetData() +{ + return m_data; +} + +// OFFSET: LEGO1 0x10002380 +const float *MxMatrix::GetData() const +{ + return m_data; +} + +// OFFSET: LEGO1 0x100023c0 +float *MxMatrix::Element(int p_row, int p_col) +{ + return &m_data[p_row * 4 + p_col]; +} + +// OFFSET: LEGO1 0x100023a0 +const float *MxMatrix::Element(int p_row, int p_col) const +{ + return &m_data[p_row * 4 + p_col]; +} + +// OFFSET: LEGO1 0x100023e0 +void MxMatrix::Clear() +{ + memset(m_data, 0, 16 * sizeof(float)); +} + +// OFFSET: LEGO1 0x100023f0 +void MxMatrix::SetIdentity() +{ + Clear(); + m_data[0] = 1.0f; + m_data[5] = 1.0f; + m_data[10] = 1.0f; + m_data[15] = 1.0f; +} + +// OFFSET: LEGO1 0x10002850 +void MxMatrix::operator=(const MxMatrix& p_other) +{ + EqualsMxMatrix(&p_other); +} + +// OFFSET: LEGO1 0x10002430 +MxMatrix* MxMatrix::operator+=(const float *p_matrix) +{ + for (int i = 0; i < 16; ++i) + m_data[i] += p_matrix[i]; + return this; +} + +// Matches but instructions are significantly out of order. Probably not wrong +// code given that the very similar SetTranslation does match. +// OFFSET: LEGO1 0x10002460 +void MxMatrix::TranslateBy(const float *p_x, const float *p_y, const float *p_z) +{ + m_data[12] += *p_x; + m_data[13] += *p_y; + m_data[14] += *p_z; +} + +// OFFSET: LEGO1 0x100024a0 +void MxMatrix::SetTranslation(const float *p_x, const float *p_y, const float *p_z) +{ + m_data[12] = *p_x; + m_data[13] = *p_y; + m_data[14] = *p_z; +} + +// OFFSET: LEGO1 0x10002530 +void MxMatrix::EqualsMxProduct(const MxMatrix *p_a, const MxMatrix *p_b) +{ + EqualsDataProduct(p_a->m_data, p_b->m_data); +} + +// Just a placeholder matrix multiply implementation. I think the decomp will +// look roughly like this but it's not close to matching and won't be until +// an exact match is found given it's all loop and float crunching. +// OFFSET: LEGO1 0x100024d0 STUB +void MxMatrix::EqualsDataProduct(const float *p_a, const float *p_b) +{ + for (int row = 0; row < 4; ++row) + { + for (int col = 0; col < 4; ++col) + { + m_data[row * 4 + col] = 0.0f; + for (int k = 0; k < 4; ++k) + { + m_data[row * 4 + col] += p_a[row * 4 + k] * p_b[k * 4 + col]; + } + } + } +} + +// Not close, Ghidra struggles understinging this method so it will have to +// be manually worked out. Included since I at least figured out what it was +// doing with rotateIndex and what overall operation it's trying to do. +// OFFSET: LEGO1 0x10002550 STUB +void MxMatrix::ToQuaternion(MxVector4 *p_outQuat) +{ + float trace = m_data[0] + m_data[5] + m_data[10]; + if (trace > 0) + { + trace = sqrt(trace + 1.0); + p_outQuat->GetData()[3] = trace * 0.5f; + p_outQuat->GetData()[0] = (m_data[9] - m_data[6]) * trace; + p_outQuat->GetData()[1] = (m_data[2] - m_data[8]) * trace; + p_outQuat->GetData()[2] = (m_data[4] - m_data[1]) * trace; + return; + } + + // OFFSET: LEGO1 0x100d4090 + static int rotateIndex[] = {1, 2, 0}; + + // Largest element along the trace + int largest = m_data[0] < m_data[5]; + if (*Element(largest, largest) < m_data[10]) + largest = 2; + + int next = rotateIndex[largest]; + int nextNext = rotateIndex[next]; + float valueA = *Element(nextNext, nextNext); + float valueB = *Element(next, next); + float valueC = *Element(largest, largest); + + // Above is somewhat decomped, below is pure speculation since the automatic + // decomp becomes very garbled. + float traceValue = sqrt(valueA - valueB - valueC + 1.0); + + p_outQuat->GetData()[largest] = traceValue * 0.5f; + traceValue = 0.5f / traceValue; + + p_outQuat->GetData()[3] = (m_data[next + 4 * nextNext] - m_data[nextNext + 4 * next]) * traceValue; + p_outQuat->GetData()[next] = (m_data[next + 4 * largest] + m_data[largest + 4 * next]) * traceValue; + p_outQuat->GetData()[nextNext] = (m_data[nextNext + 4 * largest] + m_data[largest + 4 * nextNext]) * traceValue; +} + +// No idea what this function is doing and it will be hard to tell until +// we have a confirmed usage site. +// OFFSET: LEGO1 0x10002710 STUB +MxResult MxMatrix::DoSomethingWithLength(const MxVector3 *p_vec) +{ + return FAILURE; +} + +// OFFSET: LEGO1 0x10002860 +void MxMatrixData::operator=(const MxMatrixData& p_other) +{ + EqualsMxMatrix(&p_other); +} diff --git a/LEGO1/mxmatrix.h b/LEGO1/mxmatrix.h new file mode 100644 index 00000000..0dcb20cb --- /dev/null +++ b/LEGO1/mxmatrix.h @@ -0,0 +1,70 @@ +#ifndef MXMATRIX_H +#define MXMATRIX_H + +#include "mxvector.h" + +// VTABLE 0x100d4350 +// SIZE 0x8 +class MxMatrix +{ +public: + inline MxMatrix(float *p_data) : m_data(p_data) {} + + // vtable + 0x00 + virtual void EqualsMxMatrix(const MxMatrix *p_other); + virtual void EqualsMatrixData(const float *p_matrix); + virtual void SetData(float *p_data); + virtual void AnotherSetData(float *p_data); + + // vtable + 0x10 + virtual float *GetData(); + virtual const float *GetData() const; + virtual float *Element(int p_row, int p_col); + virtual const float *Element(int p_row, int p_col) const; + + // vtable + 0x20 + virtual void Clear(); + virtual void SetIdentity(); + virtual void operator=(const MxMatrix& p_other); + virtual MxMatrix *operator+=(const float *p_matrix); + + // vtable + 0x30 + virtual void TranslateBy(const float *p_x, const float *p_y, const float *p_z); + virtual void SetTranslation(const float *p_x, const float *p_y, const float *p_z); + virtual void EqualsMxProduct(const MxMatrix *p_a, const MxMatrix *p_b); + virtual void EqualsDataProduct(const float *p_a, const float *p_b); + + // vtable + 0x40 + virtual void ToQuaternion(MxVector4 *p_resultQuat); + virtual MxResult DoSomethingWithLength(const MxVector3 *p_vec); + +private: + float *m_data; +}; + +// VTABLE 0x100d4300 +// SIZE 0x48 +class MxMatrixData : public MxMatrix +{ +public: + inline MxMatrixData() : MxMatrix(e) {} + + // No idea why there's another equals. Maybe to some other type like the + // DirectX Retained Mode Matrix type which is also a float* alias? + // vtable + 0x44 + virtual void operator=(const MxMatrixData& p_other); + + // Alias an easy way to access the translation part of the matrix, because + // various members / other functions benefit from the clarity. + union + { + float e[16]; + struct + { + float _[12]; + float x, y, z, w; + }; + }; +}; + +#endif // MXMATRIX_H \ No newline at end of file diff --git a/LEGO1/mxvector.cpp b/LEGO1/mxvector.cpp new file mode 100644 index 00000000..80ca1a17 --- /dev/null +++ b/LEGO1/mxvector.cpp @@ -0,0 +1,466 @@ + +#include "mxvector.h" + +#include +#include + +#include "decomp.h" + +DECOMP_SIZE_ASSERT(MxVector2, 0x8); +DECOMP_SIZE_ASSERT(MxVector3, 0x8); +DECOMP_SIZE_ASSERT(MxVector4, 0x8); +DECOMP_SIZE_ASSERT(MxVector3Data, 0x14); +DECOMP_SIZE_ASSERT(MxVector4Data, 0x18); + +// OFFSET: LEGO1 0x10002060 +void MxVector2::SetData(float *p_data) +{ + m_data = p_data; +} + +// OFFSET: LEGO1 0x100020a0 +const float *MxVector2::GetData() const +{ + return m_data; +} + +// OFFSET: LEGO1 0x10002090 +float *MxVector2::GetData() +{ + return m_data; +} + +// OFFSET: LEGO1 0x10002130 +float MxVector2::Dot(MxVector2 *p_a, float *p_b) const +{ + return DotImpl(p_a->m_data, p_b); +} + +// OFFSET: LEGO1 0x10002110 +float MxVector2::Dot(float *p_a, MxVector2 *p_b) const +{ + return DotImpl(p_a, p_b->m_data); +} + +// OFFSET: LEGO1 0x100020f0 +float MxVector2::Dot(MxVector2 *p_a, MxVector2 *p_b) const +{ + return DotImpl(p_a->m_data, p_b->m_data); +} + +// OFFSET: LEGO1 0x100020d0 +float MxVector2::Dot(float *p_a, float *p_b) const +{ + return DotImpl(p_a, p_b); +} + +// OFFSET: LEGO1 0x10002160 +MxResult MxVector2::Unitize() +{ + float sq = LenSquared(); + if (sq > 0.0f) + { + float root = sqrt(sq); + if (root > 0) + { + DivScalarImpl(&root); + return SUCCESS; + } + } + return FAILURE; +} + +// OFFSET: LEGO1 0x100021e0 +void MxVector2::AddVector(MxVector2 *p_other) +{ + AddVectorImpl(p_other->m_data); +} + +// OFFSET: LEGO1 0x100021d0 +void MxVector2::AddVector(float *p_other) +{ + AddVectorImpl(p_other); +} + +// OFFSET: LEGO1 0x100021c0 +void MxVector2::AddScalar(float p_value) +{ + AddScalarImpl(p_value); +} + +// OFFSET: LEGO1 0x10002200 +void MxVector2::SubVector(MxVector2 *p_other) +{ + SubVectorImpl(p_other->m_data); +} + +// OFFSET: LEGO1 0x100021f0 +void MxVector2::SubVector(float *p_other) +{ + SubVectorImpl(p_other); +} + +// OFFSET: LEGO1 0x10002230 +void MxVector2::MullScalar(float *p_value) +{ + MullScalarImpl(p_value); +} + +// OFFSET: LEGO1 0x10002220 +void MxVector2::MullVector(MxVector2 *p_other) +{ + MullVectorImpl(p_other->m_data); +} + +// OFFSET: LEGO1 0x10002210 +void MxVector2::MullVector(float *p_other) +{ + MullVectorImpl(p_other); +} + +// OFFSET: LEGO1 0x10002240 +void MxVector2::DivScalar(float *p_value) +{ + DivScalarImpl(p_value); +} + +// OFFSET: LEGO1 0x10002260 +void MxVector2::SetVector(MxVector2 *p_other) +{ + EqualsImpl(p_other->m_data); +} + +// OFFSET: LEGO1 0x10002250 +void MxVector2::SetVector(float *p_other) +{ + EqualsImpl(p_other); +} + +// OFFSET: LEGO1 0x10001fa0 +void MxVector2::AddScalarImpl(float p_value) +{ + m_data[0] += p_value; + m_data[1] += p_value; +} + +// OFFSET: LEGO1 0x10001f80 +void MxVector2::AddVectorImpl(float *p_value) +{ + m_data[0] += p_value[0]; + m_data[1] += p_value[1]; +} + +// OFFSET: LEGO1 0x10001fc0 +void MxVector2::SubVectorImpl(float *p_value) +{ + m_data[0] -= p_value[0]; + m_data[1] -= p_value[1]; +} + +// OFFSET: LEGO1 0x10002000 +void MxVector2::MullScalarImpl(float *p_value) +{ + m_data[0] *= *p_value; + m_data[1] *= *p_value; +} + +// OFFSET: LEGO1 0x10001fe0 +void MxVector2::MullVectorImpl(float *p_value) +{ + m_data[0] *= p_value[0]; + m_data[1] *= p_value[1]; +} + +// OFFSET: LEGO1 0x10002020 +void MxVector2::DivScalarImpl(float *p_value) +{ + m_data[0] /= *p_value; + m_data[1] /= *p_value; +} + +// OFFSET: LEGO1 0x10002040 +float MxVector2::DotImpl(float *p_a, float *p_b) const +{ + return p_b[0] * p_a[0] + p_b[1] * p_a[1]; +} + +// OFFSET: LEGO1 0x10002070 +void MxVector2::EqualsImpl(float *p_data) +{ + float *vec = m_data; + vec[0] = p_data[0]; + vec[1] = p_data[1]; +} + +// OFFSET: LEGO1 0x100020b0 +void MxVector2::Clear() +{ + float *vec = m_data; + vec[0] = 0.0f; + vec[1] = 0.0f; +} + +// OFFSET: LEGO1 0x10002150 +float MxVector2::LenSquared() const +{ + return m_data[0] * m_data[0] + m_data[1] * m_data[1]; +} + +// OFFSET: LEGO1 0x10003a90 +void MxVector3::AddScalarImpl(float p_value) +{ + m_data[0] += p_value; + m_data[1] += p_value; + m_data[2] += p_value; +} + +// OFFSET: LEGO1 0x10003a60 +void MxVector3::AddVectorImpl(float *p_value) +{ + m_data[0] += p_value[0]; + m_data[1] += p_value[1]; + m_data[2] += p_value[2]; +} + +// OFFSET: LEGO1 0x10003ac0 +void MxVector3::SubVectorImpl(float *p_value) +{ + m_data[0] -= p_value[0]; + m_data[1] -= p_value[1]; + m_data[2] -= p_value[2]; +} + +// OFFSET: LEGO1 0x10003b20 +void MxVector3::MullScalarImpl(float *p_value) +{ + m_data[0] *= *p_value; + m_data[1] *= *p_value; + m_data[2] *= *p_value; +} + +// OFFSET: LEGO1 0x10003af0 +void MxVector3::MullVectorImpl(float *p_value) +{ + m_data[0] *= p_value[0]; + m_data[1] *= p_value[1]; + m_data[2] *= p_value[2]; +} + +// OFFSET: LEGO1 0x10003b50 +void MxVector3::DivScalarImpl(float *p_value) +{ + m_data[0] /= *p_value; + m_data[1] /= *p_value; + m_data[2] /= *p_value; +} + +// OFFSET: LEGO1 0x10003b80 +float MxVector3::DotImpl(float *p_a, float *p_b) const +{ + return p_a[0] * p_b[0] + p_a[2] * p_b[2] + p_a[1] * p_b[1]; +} + +// OFFSET: LEGO1 0x10003ba0 +void MxVector3::EqualsImpl(float *p_data) +{ + float *vec = m_data; + vec[0] = p_data[0]; + vec[1] = p_data[1]; + vec[2] = p_data[2]; +} + +// OFFSET: LEGO1 0x10003bc0 +void MxVector3::Clear() +{ + float *vec = m_data; + vec[0] = 0.0f; + vec[1] = 0.0f; + vec[2] = 0.0f; +} + +// OFFSET: LEGO1 0x10003bd0 +float MxVector3::LenSquared() const +{ + return m_data[1] * m_data[1] + m_data[0] * m_data[0] + m_data[2] * m_data[2]; +} + +// OFFSET: LEGO1 0x10002270 +void MxVector3::EqualsCrossImpl(float* p_a, float* p_b) +{ + m_data[0] = p_a[1] * p_b[2] - p_a[2] * p_b[1]; + m_data[1] = p_a[2] * p_b[0] - p_a[0] * p_b[2]; + m_data[2] = p_a[0] * p_b[1] - p_a[1] * p_b[0]; +} + +// OFFSET: LEGO1 0x10002300 +void MxVector3::EqualsCross(float *p_a, MxVector3 *p_b) +{ + EqualsCrossImpl(p_a, p_b->m_data); +} + +// OFFSET: LEGO1 0x100022e0 +void MxVector3::EqualsCross(MxVector3 *p_a, float *p_b) +{ + EqualsCrossImpl(p_a->m_data, p_b); +} + +// OFFSET: LEGO1 0x100022c0 +void MxVector3::EqualsCross(MxVector3 *p_a, MxVector3 *p_b) +{ + EqualsCrossImpl(p_a->m_data, p_b->m_data); +} + +// OFFSET: LEGO1 0x10003bf0 +void MxVector3::EqualsScalar(float *p_value) +{ + m_data[0] = *p_value; + m_data[1] = *p_value; + m_data[2] = *p_value; +} + +// OFFSET: LEGO1 0x100028b0 +void MxVector4::AddScalarImpl(float p_value) +{ + m_data[0] += p_value; + m_data[1] += p_value; + m_data[2] += p_value; + m_data[3] += p_value; +} + +// OFFSET: LEGO1 0x10002870 +void MxVector4::AddVectorImpl(float *p_value) +{ + m_data[0] += p_value[0]; + m_data[1] += p_value[1]; + m_data[2] += p_value[2]; + m_data[3] += p_value[3]; +} + +// OFFSET: LEGO1 0x100028f0 +void MxVector4::SubVectorImpl(float *p_value) +{ + m_data[0] -= p_value[0]; + m_data[1] -= p_value[1]; + m_data[2] -= p_value[2]; + m_data[3] -= p_value[3]; +} + +// OFFSET: LEGO1 0x10002970 +void MxVector4::MullScalarImpl(float *p_value) +{ + m_data[0] *= *p_value; + m_data[1] *= *p_value; + m_data[2] *= *p_value; + m_data[3] *= *p_value; +} + +// OFFSET: LEGO1 0x10002930 +void MxVector4::MullVectorImpl(float *p_value) +{ + m_data[0] *= p_value[0]; + m_data[1] *= p_value[1]; + m_data[2] *= p_value[2]; + m_data[3] *= p_value[3]; +} + +// OFFSET: LEGO1 0x100029b0 +void MxVector4::DivScalarImpl(float *p_value) +{ + m_data[0] /= *p_value; + m_data[1] /= *p_value; + m_data[2] /= *p_value; + m_data[3] /= *p_value; +} + +// OFFSET: LEGO1 0x100029f0 +float MxVector4::DotImpl(float *p_a, float *p_b) const +{ + return + p_a[0] * p_b[0] + p_a[2] * p_b[2] + + p_a[1] * p_b[1] + p_a[3] * p_b[3]; +} + +// OFFSET: LEGO1 0x10002a20 +void MxVector4::EqualsImpl(float *p_data) +{ + float *vec = m_data; + vec[0] = p_data[0]; + vec[1] = p_data[1]; + vec[2] = p_data[2]; + vec[3] = p_data[3]; +} + +// OFFSET: LEGO1 0x10002b00 +void MxVector4::Clear() +{ + float *vec = m_data; + vec[0] = 0.0f; + vec[1] = 0.0f; + vec[2] = 0.0f; + vec[3] = 0.0f; +} + +// OFFSET: LEGO1 0x10002b20 +float MxVector4::LenSquared() const +{ + return m_data[1] * m_data[1] + m_data[0] * m_data[0] + + m_data[2] * m_data[2] + m_data[3] * m_data[3]; +} + +// OFFSET: LEGO1 0x10002b40 +void MxVector4::EqualsScalar(float *p_value) +{ + m_data[0] = *p_value; + m_data[1] = *p_value; + m_data[2] = *p_value; + m_data[3] = *p_value; +} + +// OFFSET: LEGO1 0x10002ae0 STUB +void MxVector4::unk1(MxVector4 *p_a, float *p_b) +{ +} + +// OFFSET: LEGO1 0x10002a40 +void MxVector4::SetMatrixProduct(float *p_vec, float *p_mat) +{ + m_data[0] = + p_vec[0] * p_mat[0] + p_vec[1] * p_mat[4] + + p_vec[2] * p_mat[8] + p_vec[3] * p_mat[12]; + m_data[1] = + p_vec[0] * p_mat[1] + p_vec[1] * p_mat[5] + + p_vec[2] * p_mat[9] + p_vec[4] * p_mat[13]; + m_data[2] = + p_vec[0] * p_mat[2] + p_vec[1] * p_mat[6] + + p_vec[2] * p_mat[10] + p_vec[4] * p_mat[14]; + m_data[3] = + p_vec[0] * p_mat[3] + p_vec[1] * p_mat[7] + + p_vec[2] * p_mat[11] + p_vec[4] * p_mat[15]; +} + +// Note close yet, included because I'm at least confident I know what operation +// it's trying to do. +// OFFSET: LEGO1 0x10002b70 STUB +MxResult MxVector4::NormalizeQuaternion() +{ + float *v = m_data; + float magnitude = v[1] * v[1] + v[2] * v[2] + v[0] * v[0]; + if (magnitude > 0.0f) + { + float theta = v[3] * 0.5f; + v[3] = cos(theta); + float frac = sin(theta); + magnitude = frac / sqrt(magnitude); + v[0] *= magnitude; + v[1] *= magnitude; + v[2] *= magnitude; + return SUCCESS; + } + return FAILURE; +} + +// OFFSET: LEGO1 0x10002bf0 STUB +void MxVector4::UnknownQuaternionOp(MxVector4 *p_a, MxVector4 *p_b) +{ + +} \ No newline at end of file diff --git a/LEGO1/mxvector.h b/LEGO1/mxvector.h new file mode 100644 index 00000000..0b766348 --- /dev/null +++ b/LEGO1/mxvector.h @@ -0,0 +1,150 @@ +#ifndef MXVECTOR_H +#define MXVECTOR_H + +#include "mxtypes.h" + +// VTABLE 0x100d4288 +// SIZE 0x8 +class MxVector2 +{ +public: + // OFFSET: LEGO1 0x1000c0f0 + inline MxVector2(float* p_data) : m_data(p_data) {} + + // vtable + 0x00 (no virtual destructor) + virtual void AddScalarImpl(float p_value) = 0; + virtual void AddVectorImpl(float *p_value) = 0; + virtual void SubVectorImpl(float *p_value) = 0; + virtual void MullScalarImpl(float *p_value) = 0; + + // vtable + 0x10 + virtual void MullVectorImpl(float *p_value) = 0; + virtual void DivScalarImpl(float *p_value) = 0; + virtual float DotImpl(float *p_a, float *p_b) const = 0; + virtual void SetData(float *p_data); + + // vtable + 0x20 + virtual void EqualsImpl(float *p_data) = 0; + virtual const float *GetData() const; + virtual float *GetData(); + virtual void Clear() = 0; + + // vtable + 0x30 + virtual float Dot(MxVector2 *p_a, float *p_b) const; + virtual float Dot(float *p_a, MxVector2 *p_b) const; + virtual float Dot(MxVector2 *p_a, MxVector2 *p_b) const; + virtual float Dot(float *p_a, float *p_b) const; + + // vtable + 0x40 + virtual float LenSquared() const = 0; + virtual MxResult Unitize(); + + // vtable + 0x48 + virtual void AddVector(MxVector2 *p_other); + virtual void AddVector(float *p_other); + virtual void AddScalar(float p_value); + + // vtable + 0x54 + virtual void SubVector(MxVector2 *p_other); + virtual void SubVector(float *p_other); + + // vtable + 0x5C + virtual void MullScalar(float *p_value); + virtual void MullVector(MxVector2 *p_other); + virtual void MullVector(float *p_other); + virtual void DivScalar(float *p_value); + + // vtable + 0x6C + virtual void SetVector(MxVector2 *other); + virtual void SetVector(float *other); + +protected: + float *m_data; +}; + +// VTABLE 0x100d4518 +// SIZE 0x8 +class MxVector3 : public MxVector2 +{ +public: + inline MxVector3(float* p_data) : MxVector2(p_data) {} + + void AddScalarImpl(float p_value); + + void AddVectorImpl(float *p_value); + + void SubVectorImpl(float *p_value); + void MullScalarImpl(float *p_value); + void MullVectorImpl(float *p_value); + void DivScalarImpl(float *p_value); + float DotImpl(float *p_a, float *p_b) const; + + void EqualsImpl(float *p_data); + + void Clear(); + + float LenSquared() const; + + // vtable + 0x74 + virtual void EqualsCrossImpl(float* p_a, float* p_b); + virtual void EqualsCross(float *p_a, MxVector3 *p_b); + virtual void EqualsCross(MxVector3 *p_a, float *p_b); + virtual void EqualsCross(MxVector3 *p_a, MxVector3 *p_b); + virtual void EqualsScalar(float *p_value); +}; + +// VTABLE 0x100d45a0 +// SIZE 0x8 +class MxVector4 : public MxVector3 +{ +public: + inline MxVector4(float* p_data) : MxVector3(p_data) {} + + void AddScalarImpl(float p_value); + + void AddVectorImpl(float *p_value); + + void SubVectorImpl(float *p_value); + void MullScalarImpl(float *p_value); + void MullVectorImpl(float *p_value); + void DivScalarImpl(float *p_value); + float DotImpl(float *p_a, float *p_b) const; + + void EqualsImpl(float *p_data); + + void Clear(); + + float LenSquared() const; + + void EqualsScalar(float *p_value); + + // vtable + 0x84 + virtual void unk1(MxVector4 *p_a, float *p_b); + virtual void SetMatrixProduct(float *p_vec, float *p_mat); + virtual MxResult NormalizeQuaternion(); + virtual void UnknownQuaternionOp(MxVector4 *p_a, MxVector4 *p_b); +}; + +// VTABLE 0x100d4488 +// SIZE 0x14 +class MxVector3Data : public MxVector3 +{ +public: + inline MxVector3Data() : MxVector3(&x) {} + inline MxVector3Data(float p_x, float p_y, float p_z) + : MxVector3(&x) + , x(p_x), y(p_y), z(p_z) + {} + float x, y, z; +}; + +// VTABLE 0x100d41e8 +// SIZE 0x18 +class MxVector4Data : public MxVector4 +{ +public: + inline MxVector4Data() : MxVector4(&x) {} + float x, y, z, w; +}; + +#endif // MXVECTOR_H \ No newline at end of file diff --git a/tools/reccmp/reccmp.py b/tools/reccmp/reccmp.py index 69779872..1beec5dd 100755 --- a/tools/reccmp/reccmp.py +++ b/tools/reccmp/reccmp.py @@ -343,14 +343,15 @@ def replace_register(lines: list[str], start_line: int, reg: str, replacement: s # Is it possible to make new_asm the same as original_asm by swapping registers? def can_resolve_register_differences(original_asm, new_asm): + # Split the ASM on spaces to get more granularity, and so + # that we don't modify the original arrays passed in. + original_asm = [part for line in original_asm for part in line.split()] + new_asm = [part for line in new_asm for part in line.split()] + # Swapping ain't gonna help if the lengths are different if len(original_asm) != len(new_asm): return False - # Make copies so we don't modify the original - original_asm = original_asm.copy() - new_asm = new_asm.copy() - # Look for the mismatching lines for i in range(len(original_asm)): new_line = new_asm[i]