Handle unaligned read/write (#82)

This commit is contained in:
Anders Jenbo 2025-05-18 22:27:44 +02:00 committed by GitHub
parent d5b5148cd5
commit 3a0366a3d9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 66 additions and 48 deletions

View File

@ -119,7 +119,8 @@ void LegoEntity::SetWorld()
{
LegoWorld* world = CurrentWorld();
if (world != NULL && world != (LegoWorld*) this) {
LegoWorld* maybeWorld = dynamic_cast<LegoWorld*>(this);
if (world != NULL && world != maybeWorld) {
world->Add(this);
}
}

View File

@ -50,7 +50,7 @@ public:
~MxAssignedDevice();
unsigned int GetFlags() { return m_flags; }
BOOL GetHardwareMode() { return ((int) m_flags << 31) >> 31; }
BOOL GetHardwareMode() { return (m_flags & 1) != 0; }
D3DDEVICEDESC& GetDesc() { return m_desc; }
friend class MxDirect3D;

View File

@ -4,6 +4,7 @@
#include "decomp.h"
#include "mxcore.h"
#include "mxtypes.h"
#include "mxutilities.h"
#define DS_CHUNK_BIT1 0x01
#define DS_CHUNK_END_OF_STREAM 0x02
@ -37,7 +38,10 @@ public:
static MxU32 GetHeaderSize();
// FUNCTION: BETA10 0x101641f0
static MxU32 Size(MxU8* p_buffer) { return (*(MxU32*) (p_buffer + 4) & 1) + *(MxU32*) (p_buffer + 4) + 8; }
static MxU32 Size(MxU8* p_buffer)
{
return (UnalignedRead<MxU32>(p_buffer + 4) & 1) + UnalignedRead<MxU32>(p_buffer + 4) + 8;
}
// FUNCTION: BETA10 0x10164220
static MxU8* End(MxU8* p_buffer) { return p_buffer + Size(p_buffer); }

View File

@ -29,6 +29,14 @@ inline T Max(T p_t1, T p_t2)
return p_t1 > p_t2 ? p_t1 : p_t2;
}
template <typename T>
T UnalignedRead(MxU8* p_source)
{
T value;
memcpy(&value, p_source, sizeof(T));
return value;
}
template <class T>
inline void GetScalar(MxU8*& p_source, T& p_dest)
{

View File

@ -261,21 +261,21 @@ void MxDSAction::Deserialize(MxU8*& p_source, MxS16 p_flags)
MxDSObject::Deserialize(p_source, p_flags);
// clang-format off
m_flags = *( MxU32*) p_source; p_source += sizeof(m_flags);
m_startTime = *(MxLong*) p_source; p_source += sizeof(m_startTime);
m_duration = *(MxLong*) p_source; p_source += sizeof(m_duration);
m_loopCount = *( MxS32*) p_source; p_source += sizeof(m_loopCount);
m_location[0] = *(double*) p_source; p_source += sizeof(double);
m_location[1] = *(double*) p_source; p_source += sizeof(double);
m_location[2] = *(double*) p_source; p_source += sizeof(double);
m_direction[0] = *(double*) p_source; p_source += sizeof(double);
m_direction[1] = *(double*) p_source; p_source += sizeof(double);
m_direction[2] = *(double*) p_source; p_source += sizeof(double);
m_up[0] = *(double*) p_source; p_source += sizeof(double);
m_up[1] = *(double*) p_source; p_source += sizeof(double);
m_up[2] = *(double*) p_source; p_source += sizeof(double);
m_flags = UnalignedRead<MxU32>(p_source); p_source += sizeof(MxU32);
m_startTime = UnalignedRead<MxLong>(p_source); p_source += sizeof(MxLong);
m_duration = UnalignedRead<MxLong>(p_source); p_source += sizeof(MxLong);
m_loopCount = UnalignedRead<MxS32>(p_source); p_source += sizeof(MxS32);
m_location[0] = UnalignedRead<double>(p_source); p_source += sizeof(double);
m_location[1] = UnalignedRead<double>(p_source); p_source += sizeof(double);
m_location[2] = UnalignedRead<double>(p_source); p_source += sizeof(double);
m_direction[0] = UnalignedRead<double>(p_source); p_source += sizeof(double);
m_direction[1] = UnalignedRead<double>(p_source); p_source += sizeof(double);
m_direction[2] = UnalignedRead<double>(p_source); p_source += sizeof(double);
m_up[0] = UnalignedRead<double>(p_source); p_source += sizeof(double);
m_up[1] = UnalignedRead<double>(p_source); p_source += sizeof(double);
m_up[2] = UnalignedRead<double>(p_source); p_source += sizeof(double);
MxU16 extraLength = *( MxU16*) p_source; p_source += sizeof(extraLength);
MxU16 extraLength = UnalignedRead<MxU16>(p_source); p_source += sizeof(extraLength);
// clang-format on
if (extraLength) {

View File

@ -137,12 +137,12 @@ void MxDSMediaAction::Deserialize(MxU8*& p_source, MxS16 p_flags)
p_source += strlen(m_mediaSrcPath) + 1;
// clang-format off
m_unk0x9c.SetUnk0x00(*(MxU32*) p_source); p_source += sizeof(m_unk0x9c.m_unk0x00);
m_unk0x9c.SetUnk0x04(*(MxU32*) p_source); p_source += sizeof(m_unk0x9c.m_unk0x04);
m_unk0x9c.SetUnk0x00(UnalignedRead<MxU32>(p_source)); p_source += sizeof(MxU32);
m_unk0x9c.SetUnk0x04(UnalignedRead<MxU32>(p_source)); p_source += sizeof(MxU32);
m_framesPerSecond = *(MxS32*) p_source; p_source += sizeof(m_framesPerSecond);
m_mediaFormat = *(MxS32*) p_source; p_source += sizeof(m_mediaFormat);
m_paletteManagement = *(MxS32*) p_source; p_source += sizeof(m_paletteManagement);
m_sustainTime = *(MxS32*) p_source; p_source += sizeof(m_sustainTime);
m_framesPerSecond = UnalignedRead<MxS32>(p_source); p_source += sizeof(MxS32);
m_mediaFormat = UnalignedRead<MxS32>(p_source); p_source += sizeof(MxS32);
m_paletteManagement = UnalignedRead<MxS32>(p_source); p_source += sizeof(MxS32);
m_sustainTime = UnalignedRead<MxS32>(p_source); p_source += sizeof(MxS32);
// clang-format on
}

View File

@ -1,5 +1,7 @@
#include "mxdsmultiaction.h"
#include "mxutilities.h"
#include <assert.h>
DECOMP_SIZE_ASSERT(MxDSMultiAction, 0x9c)
@ -153,15 +155,15 @@ void MxDSMultiAction::Deserialize(MxU8*& p_source, MxS16 p_flags)
{
MxDSAction::Deserialize(p_source, p_flags);
MxU32 extraFlag = *(MxU32*) (p_source + 4) & 1;
MxU32 extraFlag = UnalignedRead<MxU32>(p_source + 4) & 1;
p_source += 12;
MxU32 count = *(MxU32*) p_source;
MxU32 count = UnalignedRead<MxU32>(p_source);
p_source += sizeof(count);
if (count) {
while (count--) {
MxU32 extraFlag = *(MxU32*) (p_source + 4) & 1;
MxU32 extraFlag = UnalignedRead<MxU32>(p_source + 4) & 1;
p_source += 8;
MxDSAction* action = (MxDSAction*) DeserializeDSObjectDispatch(p_source, p_flags);

View File

@ -161,13 +161,13 @@ void MxDSObject::Deserialize(MxU8*& p_source, MxS16 p_flags)
SetSourceName((char*) p_source);
p_source += strlen(m_sourceName) + 1;
m_unk0x14 = *(undefined4*) p_source;
m_unk0x14 = UnalignedRead<undefined4>(p_source);
p_source += sizeof(m_unk0x14);
SetObjectName((char*) p_source);
p_source += strlen(m_objectName) + 1;
m_objectId = *(MxU32*) p_source;
m_objectId = UnalignedRead<MxU32>(p_source);
p_source += sizeof(m_objectId);
m_unk0x24 = p_flags;
@ -211,7 +211,7 @@ MxDSObject* DeserializeDSObjectDispatch(MxU8*& p_source, MxS16 p_flags)
{
MxDSObject* obj = NULL;
MxU16 type = *(MxU16*) p_source;
MxU16 type = UnalignedRead<MxU16>(p_source);
p_source += 2;
switch (type) {

View File

@ -1,5 +1,7 @@
#include "mxdssound.h"
#include "mxutilities.h"
DECOMP_SIZE_ASSERT(MxDSSound, 0xc0)
// FUNCTION: LEGO1 0x100c92c0
@ -61,7 +63,7 @@ MxDSAction* MxDSSound::Clone()
void MxDSSound::Deserialize(MxU8*& p_source, MxS16 p_flags)
{
MxDSMediaAction::Deserialize(p_source, p_flags);
m_volume = *(MxS32*) p_source;
m_volume = UnalignedRead<MxS32>(p_source);
p_source += sizeof(m_volume);
}

View File

@ -9,6 +9,7 @@
#include "mxstreamcontroller.h"
#include "mxstreamer.h"
#include "mxstreamprovider.h"
#include "mxutilities.h"
DECOMP_SIZE_ASSERT(MxDSBuffer, 0x34);
@ -177,11 +178,11 @@ MxResult MxDSBuffer::CreateObject(
return FAILURE;
}
if (*p_data == FOURCC('M', 'x', 'O', 'b')) {
if (UnalignedRead<MxU32>((MxU8*) p_data) == FOURCC('M', 'x', 'O', 'b')) {
MxDSAction* action = (MxDSAction*) header;
return StartPresenterFromAction(p_controller, p_action, action);
}
else if (*p_data == FOURCC('M', 'x', 'C', 'h')) {
else if (UnalignedRead<MxU32>((MxU8*) p_data) == FOURCC('M', 'x', 'C', 'h')) {
MxStreamChunk* chunk = (MxStreamChunk*) header;
if (!m_unk0x30->HasId((chunk)->GetObjectId())) {
delete header;
@ -326,7 +327,7 @@ MxCore* MxDSBuffer::ReadChunk(MxDSBuffer* p_buffer, MxU32* p_chunkData, MxU16 p_
MxCore* result = NULL;
MxU8* dataStart = (MxU8*) p_chunkData + 8;
switch (*p_chunkData) {
switch (UnalignedRead<MxU32>((MxU8*) p_chunkData)) {
case FOURCC('M', 'x', 'O', 'b'): {
MxDSObject* obj = DeserializeDSObjectDispatch(dataStart, p_flags);
result = obj;
@ -355,11 +356,12 @@ MxU8* MxDSBuffer::SkipToData()
if (m_pIntoBuffer != NULL) {
while (TRUE) {
switch (*(MxU32*) m_pIntoBuffer) {
switch (UnalignedRead<MxU32>(m_pIntoBuffer)) {
case FOURCC('M', 'x', 'O', 'b'):
case FOURCC('M', 'x', 'C', 'h'):
result = m_pIntoBuffer;
m_pIntoBuffer += (*(MxU32*) (m_pIntoBuffer + 4) & 1) + *(MxU32*) (m_pIntoBuffer + 4);
m_pIntoBuffer +=
(UnalignedRead<MxU32>(m_pIntoBuffer + 4) & 1) + UnalignedRead<MxU32>(m_pIntoBuffer + 4);
m_pIntoBuffer += 8;
if (m_pBuffer + m_writeOffset - 8 < m_pIntoBuffer) {
@ -372,7 +374,7 @@ MxU8* MxDSBuffer::SkipToData()
m_pIntoBuffer += 8;
break;
case FOURCC('M', 'x', 'H', 'd'):
m_pIntoBuffer += *(MxU32*) (m_pIntoBuffer + 4) + 8;
m_pIntoBuffer += UnalignedRead<MxU32>(m_pIntoBuffer + 4) + 8;
break;
case FOURCC('L', 'I', 'S', 'T'):
case FOURCC('R', 'I', 'F', 'F'):
@ -424,7 +426,7 @@ MxResult MxDSBuffer::CalcBytesRemaining(MxU8* p_data)
if (m_writeOffset == m_bytesRemaining) {
ptr = p_data;
bytesRead = *(MxU32*) (p_data + 4) + 8;
bytesRead = UnalignedRead<MxU32>(p_data + 4) + 8;
}
else {
ptr = p_data + MxStreamChunk::GetHeaderSize() + 8;
@ -435,7 +437,9 @@ MxResult MxDSBuffer::CalcBytesRemaining(MxU8* p_data)
memcpy(m_pBuffer + m_writeOffset - m_bytesRemaining, ptr, bytesRead);
if (m_writeOffset == m_bytesRemaining) {
*(MxU32*) (m_pBuffer + 4) = *MxStreamChunk::IntoLength(m_pBuffer) + MxStreamChunk::GetHeaderSize();
MxU32 length =
UnalignedRead<MxU32>((MxU8*) MxStreamChunk::IntoLength(m_pBuffer)) + MxStreamChunk::GetHeaderSize();
memcpy(m_pBuffer + 4, &length, sizeof(length));
}
m_bytesRemaining -= bytesRead;
@ -462,7 +466,7 @@ MxU8* MxDSBuffer::FUN_100c6fa0(MxU8* p_data)
MxU8* end = m_writeOffset + m_pBuffer - 8;
while (current <= end) {
switch (*((MxU32*) current)) {
switch (UnalignedRead<MxU32>(current)) {
case FOURCC('L', 'I', 'S', 'T'):
case FOURCC('R', 'I', 'F', 'F'):
current += 12;

View File

@ -5,6 +5,7 @@
#include "mxdsfile.h"
#include "mxomni.h"
#include "mxstreamcontroller.h"
#include "mxutilities.h"
DECOMP_SIZE_ASSERT(MxStreamProvider, 0x10)
DECOMP_SIZE_ASSERT(MxRAMStreamProvider, 0x24)
@ -109,10 +110,8 @@ MxU32 ReadData(MxU8* p_buffer, MxU32 p_size)
MxU8* data = p_buffer;
MxU8* data2;
#define IntoType(p) ((MxU32*) (p))
while (data < p_buffer + p_size) {
if (*IntoType(data) == FOURCC('M', 'x', 'O', 'b')) {
if (data + sizeof(MxU32) <= p_buffer + p_size && UnalignedRead<MxU32>(data) == FOURCC('M', 'x', 'O', 'b')) {
data2 = data;
data = data2 + 8;
@ -122,11 +121,11 @@ MxU32 ReadData(MxU8* p_buffer, MxU32 p_size)
data = MxDSChunk::End(data2);
while (data < p_buffer + p_size) {
if (*IntoType(data) == FOURCC('M', 'x', 'C', 'h')) {
if (UnalignedRead<MxU32>(data) == FOURCC('M', 'x', 'C', 'h')) {
MxU8* data3 = data;
data = MxDSChunk::End(data3);
if ((*IntoType(data2) == FOURCC('M', 'x', 'C', 'h')) &&
if ((UnalignedRead<MxU32>(data2) == FOURCC('M', 'x', 'C', 'h')) &&
(*MxStreamChunk::IntoFlags(data2) & DS_CHUNK_SPLIT)) {
if (*MxStreamChunk::IntoObjectId(data2) == *MxStreamChunk::IntoObjectId(data3) &&
(*MxStreamChunk::IntoFlags(data3) & DS_CHUNK_SPLIT) &&
@ -142,7 +141,7 @@ MxU32 ReadData(MxU8* p_buffer, MxU32 p_size)
data2 = MxDSChunk::End(data2);
memmove(data2, data3, MxDSChunk::Size(data3));
if (*MxStreamChunk::IntoObjectId(data2) == id &&
if (UnalignedRead<MxU32>((MxU8*) MxStreamChunk::IntoObjectId(data2)) == id &&
(*MxStreamChunk::IntoFlags(data2) & DS_CHUNK_END_OF_STREAM)) {
break;
}
@ -159,6 +158,4 @@ MxU32 ReadData(MxU8* p_buffer, MxU32 p_size)
*MxStreamChunk::IntoFlags(data2) &= ~DS_CHUNK_SPLIT;
return MxDSChunk::Size(data2) + (MxU32) (data2 - p_buffer);
#undef IntoType
}

View File

@ -17,7 +17,7 @@ MxResult MxStreamChunk::ReadChunk(MxDSBuffer* p_buffer, MxU8* p_chunkData)
{
MxResult result = FAILURE;
if (p_chunkData != NULL && *(MxU32*) p_chunkData == FOURCC('M', 'x', 'C', 'h')) {
if (p_chunkData != NULL && UnalignedRead<MxU32>(p_chunkData) == FOURCC('M', 'x', 'C', 'h')) {
if (ReadChunkHeader(p_chunkData + 8)) {
if (p_buffer) {
SetBuffer(p_buffer);