mirror of
https://github.com/isledecomp/isle.git
synced 2024-11-26 09:38:14 -05:00
Implement MxVector2/3/4 and MxMatrix (#100)
* All of the MxVectors share an inheritance chain. MxVector4 inherits from MxVector3 which inherits from MxVector2. * They all operate on a shared `float*` data member which points to the underlying storage. * There are also MxVector3/4Data classes, which inherit from Vector3/4, but add concrete storage for the Vector data rather than just an abstract data pointer. * The same is true for MxMatrix, with there being an abstract and a concrete variant of it. * Also improve reccmp.py register matching algorithm. It previously could not recognize an effective match when a swap had to take place between two registers used on the same line. It turns out this happens a lot in floating point math code so I adjusted the implementation to break the disassembly lines on spaces rather than just linebreaks allowing the existing effective match code to handle that case too.
This commit is contained in:
parent
ee7c419be8
commit
694045abd8
6 changed files with 881 additions and 4 deletions
|
@ -128,6 +128,7 @@ add_library(lego1 SHARED
|
||||||
LEGO1/mxloopingflcpresenter.cpp
|
LEGO1/mxloopingflcpresenter.cpp
|
||||||
LEGO1/mxloopingmidipresenter.cpp
|
LEGO1/mxloopingmidipresenter.cpp
|
||||||
LEGO1/mxloopingsmkpresenter.cpp
|
LEGO1/mxloopingsmkpresenter.cpp
|
||||||
|
LEGO1/mxmatrix.cpp
|
||||||
LEGO1/mxmediapresenter.cpp
|
LEGO1/mxmediapresenter.cpp
|
||||||
LEGO1/mxmidipresenter.cpp
|
LEGO1/mxmidipresenter.cpp
|
||||||
LEGO1/mxmusicpresenter.cpp
|
LEGO1/mxmusicpresenter.cpp
|
||||||
|
@ -156,6 +157,7 @@ add_library(lego1 SHARED
|
||||||
LEGO1/mxunknown100dc6b0.cpp
|
LEGO1/mxunknown100dc6b0.cpp
|
||||||
LEGO1/mxunknown100dc6e0.cpp
|
LEGO1/mxunknown100dc6e0.cpp
|
||||||
LEGO1/mxvariabletable.cpp
|
LEGO1/mxvariabletable.cpp
|
||||||
|
LEGO1/mxvector.cpp
|
||||||
LEGO1/mxvideomanager.cpp
|
LEGO1/mxvideomanager.cpp
|
||||||
LEGO1/mxvideoparam.cpp
|
LEGO1/mxvideoparam.cpp
|
||||||
LEGO1/mxvideoparamflags.cpp
|
LEGO1/mxvideoparamflags.cpp
|
||||||
|
|
188
LEGO1/mxmatrix.cpp
Normal file
188
LEGO1/mxmatrix.cpp
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
|
||||||
|
#include "mxmatrix.h"
|
||||||
|
|
||||||
|
#include <memory.h>
|
||||||
|
#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);
|
||||||
|
}
|
70
LEGO1/mxmatrix.h
Normal file
70
LEGO1/mxmatrix.h
Normal file
|
@ -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
|
466
LEGO1/mxvector.cpp
Normal file
466
LEGO1/mxvector.cpp
Normal file
|
@ -0,0 +1,466 @@
|
||||||
|
|
||||||
|
#include "mxvector.h"
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include <memory.h>
|
||||||
|
|
||||||
|
#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)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
150
LEGO1/mxvector.h
Normal file
150
LEGO1/mxvector.h
Normal file
|
@ -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
|
|
@ -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?
|
# Is it possible to make new_asm the same as original_asm by swapping registers?
|
||||||
def can_resolve_register_differences(original_asm, new_asm):
|
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
|
# Swapping ain't gonna help if the lengths are different
|
||||||
if len(original_asm) != len(new_asm):
|
if len(original_asm) != len(new_asm):
|
||||||
return False
|
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
|
# Look for the mismatching lines
|
||||||
for i in range(len(original_asm)):
|
for i in range(len(original_asm)):
|
||||||
new_line = new_asm[i]
|
new_line = new_asm[i]
|
||||||
|
|
Loading…
Reference in a new issue