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(); LegoWorld* world = CurrentWorld();
if (world != NULL && world != (LegoWorld*) this) { LegoWorld* maybeWorld = dynamic_cast<LegoWorld*>(this);
if (world != NULL && world != maybeWorld) {
world->Add(this); world->Add(this);
} }
} }

View File

@ -50,7 +50,7 @@ public:
~MxAssignedDevice(); ~MxAssignedDevice();
unsigned int GetFlags() { return m_flags; } 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; } D3DDEVICEDESC& GetDesc() { return m_desc; }
friend class MxDirect3D; friend class MxDirect3D;

View File

@ -4,6 +4,7 @@
#include "decomp.h" #include "decomp.h"
#include "mxcore.h" #include "mxcore.h"
#include "mxtypes.h" #include "mxtypes.h"
#include "mxutilities.h"
#define DS_CHUNK_BIT1 0x01 #define DS_CHUNK_BIT1 0x01
#define DS_CHUNK_END_OF_STREAM 0x02 #define DS_CHUNK_END_OF_STREAM 0x02
@ -37,7 +38,10 @@ public:
static MxU32 GetHeaderSize(); static MxU32 GetHeaderSize();
// FUNCTION: BETA10 0x101641f0 // 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 // FUNCTION: BETA10 0x10164220
static MxU8* End(MxU8* p_buffer) { return p_buffer + Size(p_buffer); } 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; 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> template <class T>
inline void GetScalar(MxU8*& p_source, T& p_dest) 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); MxDSObject::Deserialize(p_source, p_flags);
// clang-format off // clang-format off
m_flags = *( MxU32*) p_source; p_source += sizeof(m_flags); m_flags = UnalignedRead<MxU32>(p_source); p_source += sizeof(MxU32);
m_startTime = *(MxLong*) p_source; p_source += sizeof(m_startTime); m_startTime = UnalignedRead<MxLong>(p_source); p_source += sizeof(MxLong);
m_duration = *(MxLong*) p_source; p_source += sizeof(m_duration); m_duration = UnalignedRead<MxLong>(p_source); p_source += sizeof(MxLong);
m_loopCount = *( MxS32*) p_source; p_source += sizeof(m_loopCount); m_loopCount = UnalignedRead<MxS32>(p_source); p_source += sizeof(MxS32);
m_location[0] = *(double*) p_source; p_source += sizeof(double); m_location[0] = UnalignedRead<double>(p_source); p_source += sizeof(double);
m_location[1] = *(double*) p_source; p_source += sizeof(double); m_location[1] = UnalignedRead<double>(p_source); p_source += sizeof(double);
m_location[2] = *(double*) p_source; p_source += sizeof(double); m_location[2] = UnalignedRead<double>(p_source); p_source += sizeof(double);
m_direction[0] = *(double*) p_source; p_source += sizeof(double); m_direction[0] = UnalignedRead<double>(p_source); p_source += sizeof(double);
m_direction[1] = *(double*) p_source; p_source += sizeof(double); m_direction[1] = UnalignedRead<double>(p_source); p_source += sizeof(double);
m_direction[2] = *(double*) p_source; p_source += sizeof(double); m_direction[2] = UnalignedRead<double>(p_source); p_source += sizeof(double);
m_up[0] = *(double*) p_source; p_source += sizeof(double); m_up[0] = UnalignedRead<double>(p_source); p_source += sizeof(double);
m_up[1] = *(double*) p_source; p_source += sizeof(double); m_up[1] = UnalignedRead<double>(p_source); p_source += sizeof(double);
m_up[2] = *(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 // clang-format on
if (extraLength) { if (extraLength) {

View File

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

View File

@ -1,5 +1,7 @@
#include "mxdsmultiaction.h" #include "mxdsmultiaction.h"
#include "mxutilities.h"
#include <assert.h> #include <assert.h>
DECOMP_SIZE_ASSERT(MxDSMultiAction, 0x9c) DECOMP_SIZE_ASSERT(MxDSMultiAction, 0x9c)
@ -153,15 +155,15 @@ void MxDSMultiAction::Deserialize(MxU8*& p_source, MxS16 p_flags)
{ {
MxDSAction::Deserialize(p_source, 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; p_source += 12;
MxU32 count = *(MxU32*) p_source; MxU32 count = UnalignedRead<MxU32>(p_source);
p_source += sizeof(count); p_source += sizeof(count);
if (count) { if (count) {
while (count--) { while (count--) {
MxU32 extraFlag = *(MxU32*) (p_source + 4) & 1; MxU32 extraFlag = UnalignedRead<MxU32>(p_source + 4) & 1;
p_source += 8; p_source += 8;
MxDSAction* action = (MxDSAction*) DeserializeDSObjectDispatch(p_source, p_flags); 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); SetSourceName((char*) p_source);
p_source += strlen(m_sourceName) + 1; p_source += strlen(m_sourceName) + 1;
m_unk0x14 = *(undefined4*) p_source; m_unk0x14 = UnalignedRead<undefined4>(p_source);
p_source += sizeof(m_unk0x14); p_source += sizeof(m_unk0x14);
SetObjectName((char*) p_source); SetObjectName((char*) p_source);
p_source += strlen(m_objectName) + 1; p_source += strlen(m_objectName) + 1;
m_objectId = *(MxU32*) p_source; m_objectId = UnalignedRead<MxU32>(p_source);
p_source += sizeof(m_objectId); p_source += sizeof(m_objectId);
m_unk0x24 = p_flags; m_unk0x24 = p_flags;
@ -211,7 +211,7 @@ MxDSObject* DeserializeDSObjectDispatch(MxU8*& p_source, MxS16 p_flags)
{ {
MxDSObject* obj = NULL; MxDSObject* obj = NULL;
MxU16 type = *(MxU16*) p_source; MxU16 type = UnalignedRead<MxU16>(p_source);
p_source += 2; p_source += 2;
switch (type) { switch (type) {

View File

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

View File

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

View File

@ -5,6 +5,7 @@
#include "mxdsfile.h" #include "mxdsfile.h"
#include "mxomni.h" #include "mxomni.h"
#include "mxstreamcontroller.h" #include "mxstreamcontroller.h"
#include "mxutilities.h"
DECOMP_SIZE_ASSERT(MxStreamProvider, 0x10) DECOMP_SIZE_ASSERT(MxStreamProvider, 0x10)
DECOMP_SIZE_ASSERT(MxRAMStreamProvider, 0x24) DECOMP_SIZE_ASSERT(MxRAMStreamProvider, 0x24)
@ -109,10 +110,8 @@ MxU32 ReadData(MxU8* p_buffer, MxU32 p_size)
MxU8* data = p_buffer; MxU8* data = p_buffer;
MxU8* data2; MxU8* data2;
#define IntoType(p) ((MxU32*) (p))
while (data < p_buffer + p_size) { 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; data2 = data;
data = data2 + 8; data = data2 + 8;
@ -122,11 +121,11 @@ MxU32 ReadData(MxU8* p_buffer, MxU32 p_size)
data = MxDSChunk::End(data2); data = MxDSChunk::End(data2);
while (data < p_buffer + p_size) { 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; MxU8* data3 = data;
data = MxDSChunk::End(data3); 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)) { (*MxStreamChunk::IntoFlags(data2) & DS_CHUNK_SPLIT)) {
if (*MxStreamChunk::IntoObjectId(data2) == *MxStreamChunk::IntoObjectId(data3) && if (*MxStreamChunk::IntoObjectId(data2) == *MxStreamChunk::IntoObjectId(data3) &&
(*MxStreamChunk::IntoFlags(data3) & DS_CHUNK_SPLIT) && (*MxStreamChunk::IntoFlags(data3) & DS_CHUNK_SPLIT) &&
@ -142,7 +141,7 @@ MxU32 ReadData(MxU8* p_buffer, MxU32 p_size)
data2 = MxDSChunk::End(data2); data2 = MxDSChunk::End(data2);
memmove(data2, data3, MxDSChunk::Size(data3)); 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)) { (*MxStreamChunk::IntoFlags(data2) & DS_CHUNK_END_OF_STREAM)) {
break; break;
} }
@ -159,6 +158,4 @@ MxU32 ReadData(MxU8* p_buffer, MxU32 p_size)
*MxStreamChunk::IntoFlags(data2) &= ~DS_CHUNK_SPLIT; *MxStreamChunk::IntoFlags(data2) &= ~DS_CHUNK_SPLIT;
return MxDSChunk::Size(data2) + (MxU32) (data2 - p_buffer); 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; 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 (ReadChunkHeader(p_chunkData + 8)) {
if (p_buffer) { if (p_buffer) {
SetBuffer(p_buffer); SetBuffer(p_buffer);