mirror of
https://github.com/isledecomp/isle.git
synced 2026-01-27 18:21:15 +00:00
Merge remote-tracking branch 'upstream/master' into impl/legosoundmanager
This commit is contained in:
commit
b49307475c
36
.github/workflows/unittest.yml
vendored
Normal file
36
.github/workflows/unittest.yml
vendored
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
name: Unit Tests
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
pytest-win:
|
||||||
|
runs-on: windows-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Install python libraries
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
pip install pytest -r tools/requirements.txt
|
||||||
|
|
||||||
|
- name: Run python unit tests (Windows)
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
pytest tools/isledecomp
|
||||||
|
|
||||||
|
pytest-ubuntu:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Install python libraries
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
pip install pytest -r tools/requirements.txt
|
||||||
|
|
||||||
|
- name: Run python unit tests (Ubuntu)
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
pytest tools/isledecomp
|
||||||
@ -1,7 +1,14 @@
|
|||||||
#include "jukebox.h"
|
#include "jukebox.h"
|
||||||
|
|
||||||
// STUB: LEGO1 0x1005d660
|
#include "mxnotificationmanager.h"
|
||||||
|
#include "mxomni.h"
|
||||||
|
|
||||||
|
DECOMP_SIZE_ASSERT(JukeBox, 0x104)
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x1005d660
|
||||||
JukeBox::JukeBox()
|
JukeBox::JukeBox()
|
||||||
{
|
{
|
||||||
// TODO
|
m_unk0x100 = 0;
|
||||||
|
m_unk0xfc = 0;
|
||||||
|
NotificationManager()->Register(this);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
#ifndef JUKEBOX_H
|
#ifndef JUKEBOX_H
|
||||||
#define JUKEBOX_H
|
#define JUKEBOX_H
|
||||||
|
|
||||||
|
#include "decomp.h"
|
||||||
#include "legoworld.h"
|
#include "legoworld.h"
|
||||||
|
|
||||||
// VTABLE: LEGO1 0x100d8958
|
// VTABLE: LEGO1 0x100d8958
|
||||||
@ -21,6 +22,11 @@ class JukeBox : public LegoWorld {
|
|||||||
{
|
{
|
||||||
return !strcmp(p_name, JukeBox::ClassName()) || LegoWorld::IsA(p_name);
|
return !strcmp(p_name, JukeBox::ClassName()) || LegoWorld::IsA(p_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
undefined m_unk0xf8[4]; // 0xf8
|
||||||
|
undefined4 m_unk0xfc; // 0xfc
|
||||||
|
undefined2 m_unk0x100; // 0x100
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // JUKEBOX_H
|
#endif // JUKEBOX_H
|
||||||
|
|||||||
@ -33,7 +33,7 @@ class MxCore {
|
|||||||
inline MxU32 GetId() { return m_id; }
|
inline MxU32 GetId() { return m_id; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MxU32 m_id;
|
MxU32 m_id; // 0x04
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MXCORE_H
|
#endif // MXCORE_H
|
||||||
|
|||||||
@ -58,18 +58,134 @@ MxResult MxDiskStreamController::VTable0x34(undefined4)
|
|||||||
return FAILURE;
|
return FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// STUB: LEGO1 0x100c7ac0
|
// FUNCTION: LEGO1 0x100c7980
|
||||||
MxResult MxDiskStreamController::VTable0x28()
|
void MxDiskStreamController::FUN_100c7980()
|
||||||
{
|
{
|
||||||
// TODO
|
MxDSBuffer* buffer;
|
||||||
return FAILURE;
|
MxDSStreamingAction* action = NULL;
|
||||||
|
|
||||||
|
{
|
||||||
|
MxAutoLocker lock(&this->m_criticalSection);
|
||||||
|
|
||||||
|
if (m_unk0x3c.size() && m_unk0x8c < m_provider->GetStreamBuffersNum()) {
|
||||||
|
buffer = new MxDSBuffer();
|
||||||
|
|
||||||
|
if (buffer->AllocateBuffer(m_provider->GetFileSize(), MxDSBufferType_Chunk) != SUCCESS) {
|
||||||
|
if (buffer)
|
||||||
|
delete buffer;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
action = VTable0x28();
|
||||||
|
if (!action) {
|
||||||
|
if (buffer)
|
||||||
|
delete buffer;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
action->SetUnknowna0(buffer);
|
||||||
|
m_unk0x8c++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action) {
|
||||||
|
((MxDiskStreamProvider*) m_provider)->FUN_100d1780(action);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// STUB: LEGO1 0x100c7c00
|
// FUNCTION: LEGO1 0x100c7ac0
|
||||||
|
MxDSStreamingAction* MxDiskStreamController::VTable0x28()
|
||||||
|
{
|
||||||
|
MxAutoLocker lock(&this->m_criticalSection);
|
||||||
|
MxDSAction* oldAction;
|
||||||
|
MxDSStreamingAction* result = NULL;
|
||||||
|
MxU32 filesize = m_provider->GetFileSize();
|
||||||
|
|
||||||
|
if (m_unk0x3c.PopFront(oldAction)) {
|
||||||
|
result = new MxDSStreamingAction((MxDSStreamingAction&) *oldAction);
|
||||||
|
if (result) {
|
||||||
|
MxU32 offset = result->GetBufferOffset() + filesize;
|
||||||
|
((MxDSStreamingAction*) oldAction)->SetUnknown94(offset);
|
||||||
|
((MxDSStreamingAction*) oldAction)->SetBufferOffset(offset);
|
||||||
|
m_unk0x3c.push_back(oldAction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100c7c00
|
||||||
MxResult MxDiskStreamController::VTable0x30(MxDSAction* p_action)
|
MxResult MxDiskStreamController::VTable0x30(MxDSAction* p_action)
|
||||||
|
{
|
||||||
|
MxAutoLocker lock(&this->m_criticalSection);
|
||||||
|
MxResult result = MxStreamController::VTable0x30(p_action);
|
||||||
|
|
||||||
|
MxDSStreamingAction* item;
|
||||||
|
while (TRUE) {
|
||||||
|
item = (MxDSStreamingAction*) m_list0x90.Find(p_action, TRUE);
|
||||||
|
if (item == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
FUN_100c7cb0(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (TRUE) {
|
||||||
|
item = (MxDSStreamingAction*) m_list0x64.Find(p_action, TRUE);
|
||||||
|
if (item == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
FUN_100c7cb0(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100c7cb0
|
||||||
|
void MxDiskStreamController::FUN_100c7cb0(MxDSStreamingAction* p_action)
|
||||||
|
{
|
||||||
|
if (p_action->GetUnknowna0()) {
|
||||||
|
FUN_100c7ce0(p_action->GetUnknowna0());
|
||||||
|
}
|
||||||
|
p_action->SetUnknowna0(NULL);
|
||||||
|
delete p_action;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100c7ce0
|
||||||
|
void MxDiskStreamController::FUN_100c7ce0(MxDSBuffer* p_buffer)
|
||||||
|
{
|
||||||
|
switch (p_buffer->GetMode()) {
|
||||||
|
case MxDSBufferType_Chunk:
|
||||||
|
m_unk0x8c--;
|
||||||
|
case MxDSBufferType_Allocate:
|
||||||
|
case MxDSBufferType_Unknown:
|
||||||
|
delete p_buffer;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100c7d10
|
||||||
|
MxResult MxDiskStreamController::FUN_100c7d10()
|
||||||
|
{
|
||||||
|
MxAutoLocker lock(&this->m_criticalSection);
|
||||||
|
MxDSStreamingAction* action = FUN_100c7db0();
|
||||||
|
|
||||||
|
if (!action)
|
||||||
|
return FAILURE;
|
||||||
|
|
||||||
|
if (FUN_100c8360(action) != SUCCESS) {
|
||||||
|
VTable0x24(action);
|
||||||
|
FUN_100c7cb0(action);
|
||||||
|
return FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// STUB: LEGO1 0x100c7db0
|
||||||
|
MxDSStreamingAction* MxDiskStreamController::FUN_100c7db0()
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
return FAILURE;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x100c7f40
|
// FUNCTION: LEGO1 0x100c7f40
|
||||||
@ -115,6 +231,37 @@ MxResult MxDiskStreamController::VTable0x24(MxDSAction* p_action)
|
|||||||
return FAILURE;
|
return FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100c8360
|
||||||
|
MxResult MxDiskStreamController::FUN_100c8360(MxDSStreamingAction* p_action)
|
||||||
|
{
|
||||||
|
MxAutoLocker lock(&this->m_criticalSection);
|
||||||
|
MxDSBuffer* buffer = p_action->GetUnknowna0();
|
||||||
|
MxDSStreamingAction* action2 = (MxDSStreamingAction*) m_list0x90.Find(p_action, TRUE);
|
||||||
|
buffer->FUN_100c6f80(p_action->GetUnknown94() - p_action->GetBufferOffset());
|
||||||
|
buffer->FUN_100c67b0(this, p_action, &action2);
|
||||||
|
|
||||||
|
if (buffer->GetRefCount()) {
|
||||||
|
p_action->SetUnknowna0(NULL);
|
||||||
|
InsertToList74(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action2) {
|
||||||
|
if (action2->GetUnknowna0() == NULL) {
|
||||||
|
FUN_100c7cb0(action2);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (action2->GetObjectId() == -1) {
|
||||||
|
action2->SetObjectId(p_action->GetObjectId());
|
||||||
|
}
|
||||||
|
|
||||||
|
m_list0x90.push_back(action2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FUN_100c7cb0(p_action);
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x100c84a0
|
// FUNCTION: LEGO1 0x100c84a0
|
||||||
void MxDiskStreamController::InsertToList74(MxDSBuffer* p_buffer)
|
void MxDiskStreamController::InsertToList74(MxDSBuffer* p_buffer)
|
||||||
{
|
{
|
||||||
@ -122,9 +269,39 @@ void MxDiskStreamController::InsertToList74(MxDSBuffer* p_buffer)
|
|||||||
m_list0x74.push_back(p_buffer);
|
m_list0x74.push_back(p_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// STUB: LEGO1 0x100c8640
|
// STUB: LEGO1 0x100c8540
|
||||||
MxResult MxDiskStreamController::Tickle()
|
void MxDiskStreamController::FUN_100c8540()
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100c8640
|
||||||
|
MxResult MxDiskStreamController::Tickle()
|
||||||
|
{
|
||||||
|
if (m_unk0xc4) {
|
||||||
|
FUN_100c7d10();
|
||||||
|
}
|
||||||
|
|
||||||
|
FUN_100c8540();
|
||||||
|
FUN_100c8720();
|
||||||
|
|
||||||
|
if (m_unk0x70) {
|
||||||
|
FUN_100c7980();
|
||||||
|
}
|
||||||
|
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100c8720
|
||||||
|
void MxDiskStreamController::FUN_100c8720()
|
||||||
|
{
|
||||||
|
MxAutoLocker lock(&this->m_critical9c);
|
||||||
|
|
||||||
|
MxDSStreamingAction* action;
|
||||||
|
while (m_list0xb8.size() != 0) {
|
||||||
|
action = (MxDSStreamingAction*) m_list0xb8.front();
|
||||||
|
m_list0xb8.pop_front();
|
||||||
|
|
||||||
|
FUN_100c7cb0(action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -22,7 +22,7 @@ class MxDiskStreamController : public MxStreamController {
|
|||||||
virtual MxResult VTable0x18(undefined4, undefined4) override; // vtable+0x18
|
virtual MxResult VTable0x18(undefined4, undefined4) override; // vtable+0x18
|
||||||
virtual MxResult VTable0x20(MxDSAction* p_action) override; // vtable+0x20
|
virtual MxResult VTable0x20(MxDSAction* p_action) override; // vtable+0x20
|
||||||
virtual MxResult VTable0x24(MxDSAction* p_action) override; // vtable+0x24
|
virtual MxResult VTable0x24(MxDSAction* p_action) override; // vtable+0x24
|
||||||
virtual MxResult VTable0x28() override; // vtable+0x28
|
virtual MxDSStreamingAction* VTable0x28() override; // vtable+0x28
|
||||||
virtual MxResult VTable0x30(MxDSAction* p_action) override; // vtable+0x30
|
virtual MxResult VTable0x30(MxDSAction* p_action) override; // vtable+0x30
|
||||||
virtual MxResult VTable0x34(undefined4); // vtable+0x34
|
virtual MxResult VTable0x34(undefined4); // vtable+0x34
|
||||||
|
|
||||||
@ -50,8 +50,16 @@ class MxDiskStreamController : public MxStreamController {
|
|||||||
MxStreamListMxDSAction m_list0xb8; // 0xb8
|
MxStreamListMxDSAction m_list0xb8; // 0xb8
|
||||||
undefined m_unk0xc4; // 0xc4
|
undefined m_unk0xc4; // 0xc4
|
||||||
|
|
||||||
|
void FUN_100c7cb0(MxDSStreamingAction* p_action);
|
||||||
|
void FUN_100c7ce0(MxDSBuffer* p_buffer);
|
||||||
|
MxResult FUN_100c7d10();
|
||||||
|
void FUN_100c7980();
|
||||||
|
MxDSStreamingAction* FUN_100c7db0();
|
||||||
void FUN_100c7f40(MxDSStreamingAction* p_streamingaction);
|
void FUN_100c7f40(MxDSStreamingAction* p_streamingaction);
|
||||||
|
MxResult FUN_100c8360(MxDSStreamingAction* p_action);
|
||||||
void InsertToList74(MxDSBuffer* p_buffer);
|
void InsertToList74(MxDSBuffer* p_buffer);
|
||||||
|
void FUN_100c8540();
|
||||||
|
void FUN_100c8720();
|
||||||
};
|
};
|
||||||
|
|
||||||
// TEMPLATE: LEGO1 0x100c7330
|
// TEMPLATE: LEGO1 0x100c7330
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
#include "mxdiskstreamprovider.h"
|
#include "mxdiskstreamprovider.h"
|
||||||
|
|
||||||
|
#include "mxdsbuffer.h"
|
||||||
#include "mxomni.h"
|
#include "mxomni.h"
|
||||||
#include "mxstreamcontroller.h"
|
#include "mxstreamcontroller.h"
|
||||||
#include "mxstring.h"
|
#include "mxstring.h"
|
||||||
@ -58,10 +59,9 @@ MxResult MxDiskStreamProvider::SetResourceToGet(MxStreamController* p_resource)
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_remainingWork = 1;
|
m_remainingWork = 1;
|
||||||
MxResult success = m_busySemaphore.Init(0, 100);
|
m_busySemaphore.Init(0, 100);
|
||||||
m_thread.StartWithTarget(this);
|
|
||||||
|
|
||||||
if (success == SUCCESS && p_resource != NULL) {
|
if (m_thread.StartWithTarget(this) == SUCCESS && p_resource != NULL) {
|
||||||
result = SUCCESS;
|
result = SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -71,7 +71,7 @@ MxResult MxDiskStreamProvider::SetResourceToGet(MxStreamController* p_resource)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// STUB: LEGO1 0x100d15e0
|
// STUB: LEGO1 0x100d15e0
|
||||||
void MxDiskStreamProvider::VTable0x20(undefined4)
|
void MxDiskStreamProvider::VTable0x20(MxDSAction* p_action)
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
@ -87,6 +87,13 @@ MxResult MxDiskStreamProvider::WaitForWorkToComplete()
|
|||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// STUB: LEGO1 0x100d1780
|
||||||
|
MxResult MxDiskStreamProvider::FUN_100d1780(MxDSStreamingAction* p_action)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
return FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
// STUB: LEGO1 0x100d18f0
|
// STUB: LEGO1 0x100d18f0
|
||||||
void MxDiskStreamProvider::PerformWork()
|
void MxDiskStreamProvider::PerformWork()
|
||||||
{
|
{
|
||||||
@ -100,7 +107,7 @@ MxU32 MxDiskStreamProvider::GetFileSize()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x100d1ea0
|
// FUNCTION: LEGO1 0x100d1ea0
|
||||||
MxU32 MxDiskStreamProvider::GetStreamBuffersNum()
|
MxS32 MxDiskStreamProvider::GetStreamBuffersNum()
|
||||||
{
|
{
|
||||||
return m_pFile->GetStreamBuffersNum();
|
return m_pFile->GetStreamBuffersNum();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,6 +10,7 @@
|
|||||||
#include "mxthread.h"
|
#include "mxthread.h"
|
||||||
|
|
||||||
class MxDiskStreamProvider;
|
class MxDiskStreamProvider;
|
||||||
|
class MxDSStreamingAction;
|
||||||
|
|
||||||
// VTABLE: LEGO1 0x100dd130
|
// VTABLE: LEGO1 0x100dd130
|
||||||
class MxDiskStreamProviderThread : public MxThread {
|
class MxDiskStreamProviderThread : public MxThread {
|
||||||
@ -43,13 +44,13 @@ class MxDiskStreamProvider : public MxStreamProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MxResult WaitForWorkToComplete();
|
MxResult WaitForWorkToComplete();
|
||||||
|
MxResult FUN_100d1780(MxDSStreamingAction* p_action);
|
||||||
void PerformWork();
|
void PerformWork();
|
||||||
|
|
||||||
virtual MxResult SetResourceToGet(MxStreamController* p_resource) override; // vtable+0x14
|
virtual MxResult SetResourceToGet(MxStreamController* p_resource) override; // vtable+0x14
|
||||||
virtual MxU32 GetFileSize() override; // vtable+0x18
|
virtual MxU32 GetFileSize() override; // vtable+0x18
|
||||||
virtual MxU32 GetStreamBuffersNum() override; // vtable+0x1c
|
virtual MxS32 GetStreamBuffersNum() override; // vtable+0x1c
|
||||||
virtual void VTable0x20(undefined4) override; // vtable+0x20
|
virtual void VTable0x20(MxDSAction* p_action) override; // vtable+0x20
|
||||||
virtual MxU32 GetLengthInDWords() override; // vtable+0x24
|
virtual MxU32 GetLengthInDWords() override; // vtable+0x24
|
||||||
virtual MxU32* GetBufferForDWords() override; // vtable+0x28
|
virtual MxU32* GetBufferForDWords() override; // vtable+0x28
|
||||||
|
|
||||||
|
|||||||
@ -123,7 +123,11 @@ MxResult MxDSBuffer::SetBufferPointer(MxU32* p_buffer, MxU32 p_size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// STUB: LEGO1 0x100c67b0
|
// STUB: LEGO1 0x100c67b0
|
||||||
MxResult MxDSBuffer::FUN_100c67b0(MxStreamController* p_controller, MxDSAction* p_action, undefined4*)
|
MxResult MxDSBuffer::FUN_100c67b0(
|
||||||
|
MxStreamController* p_controller,
|
||||||
|
MxDSAction* p_action,
|
||||||
|
MxDSStreamingAction** p_streamingAction
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// TODO STUB
|
// TODO STUB
|
||||||
return FAILURE;
|
return FAILURE;
|
||||||
|
|||||||
@ -33,7 +33,11 @@ class MxDSBuffer : public MxCore {
|
|||||||
|
|
||||||
MxResult AllocateBuffer(MxU32 p_bufferSize, MxDSBufferType p_mode);
|
MxResult AllocateBuffer(MxU32 p_bufferSize, MxDSBufferType p_mode);
|
||||||
MxResult SetBufferPointer(MxU32* p_buffer, MxU32 p_size);
|
MxResult SetBufferPointer(MxU32* p_buffer, MxU32 p_size);
|
||||||
MxResult FUN_100c67b0(MxStreamController* p_controller, MxDSAction* p_action, undefined4*);
|
MxResult FUN_100c67b0(
|
||||||
|
MxStreamController* p_controller,
|
||||||
|
MxDSAction* p_action,
|
||||||
|
MxDSStreamingAction** p_streamingAction
|
||||||
|
);
|
||||||
MxResult CreateObject(
|
MxResult CreateObject(
|
||||||
MxStreamController* p_controller,
|
MxStreamController* p_controller,
|
||||||
MxU32* p_data,
|
MxU32* p_data,
|
||||||
@ -55,6 +59,8 @@ class MxDSBuffer : public MxCore {
|
|||||||
|
|
||||||
inline MxU8* GetBuffer() { return m_pBuffer; }
|
inline MxU8* GetBuffer() { return m_pBuffer; }
|
||||||
inline MxU32 GetWriteOffset() { return m_writeOffset; }
|
inline MxU32 GetWriteOffset() { return m_writeOffset; }
|
||||||
|
inline MxU16 GetRefCount() { return m_refcount; }
|
||||||
|
inline MxDSBufferType GetMode() { return m_mode; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MxU8* m_pBuffer; // 0x08
|
MxU8* m_pBuffer; // 0x08
|
||||||
|
|||||||
@ -33,6 +33,7 @@ class MxDSMediaAction : public MxDSAction {
|
|||||||
|
|
||||||
void CopyMediaSrcPath(const char* p_mediaSrcPath);
|
void CopyMediaSrcPath(const char* p_mediaSrcPath);
|
||||||
|
|
||||||
|
inline MxS32 GetFramesPerSecond() const { return this->m_framesPerSecond; }
|
||||||
inline MxS32 GetMediaFormat() const { return this->m_mediaFormat; }
|
inline MxS32 GetMediaFormat() const { return this->m_mediaFormat; }
|
||||||
inline MxS32 GetPaletteManagement() const { return this->m_paletteManagement; }
|
inline MxS32 GetPaletteManagement() const { return this->m_paletteManagement; }
|
||||||
inline MxLong GetSustainTime() const { return this->m_sustainTime; }
|
inline MxLong GetSustainTime() const { return this->m_sustainTime; }
|
||||||
|
|||||||
@ -35,7 +35,10 @@ class MxDSStreamingAction : public MxDSAction {
|
|||||||
inline MxDSBuffer* GetUnknowna0() { return m_unk0xa0; }
|
inline MxDSBuffer* GetUnknowna0() { return m_unk0xa0; }
|
||||||
inline MxDSBuffer* GetUnknowna4() { return m_unk0xa4; }
|
inline MxDSBuffer* GetUnknowna4() { return m_unk0xa4; }
|
||||||
inline MxDSAction* GetInternalAction() { return m_internalAction; }
|
inline MxDSAction* GetInternalAction() { return m_internalAction; }
|
||||||
|
inline MxU32 GetBufferOffset() { return m_bufferOffset; }
|
||||||
|
inline void SetUnknown94(MxU32 p_unk0x94) { m_unk0x94 = p_unk0x94; }
|
||||||
inline void SetUnknowna0(MxDSBuffer* p_unk0xa0) { m_unk0xa0 = p_unk0xa0; }
|
inline void SetUnknowna0(MxDSBuffer* p_unk0xa0) { m_unk0xa0 = p_unk0xa0; }
|
||||||
|
inline void SetBufferOffset(MxU32 p_bufferOffset) { m_bufferOffset = p_bufferOffset; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MxU32 m_unk0x94;
|
MxU32 m_unk0x94;
|
||||||
|
|||||||
@ -1,42 +1,125 @@
|
|||||||
#include "mxdssubscriber.h"
|
#include "mxdssubscriber.h"
|
||||||
|
|
||||||
|
#include "mxstreamcontroller.h"
|
||||||
|
|
||||||
DECOMP_SIZE_ASSERT(MxDSSubscriber, 0x4c);
|
DECOMP_SIZE_ASSERT(MxDSSubscriber, 0x4c);
|
||||||
|
|
||||||
// STUB: LEGO1 0x100b7bb0
|
// FUNCTION: LEGO1 0x100b7bb0
|
||||||
MxDSSubscriber::MxDSSubscriber()
|
MxDSSubscriber::MxDSSubscriber()
|
||||||
{
|
{
|
||||||
// TODO
|
m_unk0x48 = -1;
|
||||||
|
m_objectId = -1;
|
||||||
|
m_unk0x20 = NULL;
|
||||||
|
m_unk0x3c = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// STUB: LEGO1 0x100b7e00
|
// FUNCTION: LEGO1 0x100b7e00
|
||||||
MxDSSubscriber::~MxDSSubscriber()
|
MxDSSubscriber::~MxDSSubscriber()
|
||||||
{
|
{
|
||||||
// TODO
|
if (m_controller)
|
||||||
|
m_controller->FUN_100c1620(this);
|
||||||
|
|
||||||
|
DeleteChunks();
|
||||||
|
|
||||||
|
if (m_unk0x20)
|
||||||
|
delete m_unk0x20;
|
||||||
|
m_unk0x20 = NULL;
|
||||||
|
|
||||||
|
if (m_unk0x3c)
|
||||||
|
delete m_unk0x3c;
|
||||||
|
m_unk0x3c = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// STUB: LEGO1 0x100b7ed0
|
// FUNCTION: LEGO1 0x100b7ed0
|
||||||
MxResult MxDSSubscriber::FUN_100b7ed0(MxStreamController*, MxU32, MxS16)
|
MxResult MxDSSubscriber::Create(MxStreamController* p_controller, MxU32 p_objectId, MxS16 p_unk0x48)
|
||||||
{
|
{
|
||||||
// TODO
|
m_objectId = p_objectId;
|
||||||
|
m_unk0x48 = p_unk0x48;
|
||||||
|
|
||||||
|
if (!p_controller)
|
||||||
|
return FAILURE;
|
||||||
|
m_controller = p_controller;
|
||||||
|
|
||||||
|
m_unk0x20 = new MxStreamChunkListCursor(&m_unk0x08);
|
||||||
|
if (!m_unk0x20)
|
||||||
|
return FAILURE;
|
||||||
|
|
||||||
|
m_unk0x3c = new MxStreamChunkListCursor(&m_unk0x24);
|
||||||
|
if (!m_unk0x3c)
|
||||||
|
return FAILURE;
|
||||||
|
|
||||||
|
m_controller->FUN_100c15d0(this);
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// STUB: LEGO1 0x100b8250
|
// FUNCTION: LEGO1 0x100b8030
|
||||||
|
void MxDSSubscriber::DeleteChunks()
|
||||||
|
{
|
||||||
|
if (m_controller) {
|
||||||
|
MxStreamChunk* chunk = NULL;
|
||||||
|
|
||||||
|
while (m_unk0x20->First(chunk)) {
|
||||||
|
m_unk0x20->Detach();
|
||||||
|
delete chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (m_unk0x3c->First(chunk)) {
|
||||||
|
m_unk0x3c->Detach();
|
||||||
|
delete chunk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100b8150
|
||||||
|
MxResult MxDSSubscriber::AddChunk(MxStreamChunk* p_chunk, MxBool p_append)
|
||||||
|
{
|
||||||
|
if (m_unk0x20) {
|
||||||
|
if (p_append)
|
||||||
|
m_unk0x08.Append(p_chunk);
|
||||||
|
else
|
||||||
|
m_unk0x08.Prepend(p_chunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100b8250
|
||||||
MxStreamChunk* MxDSSubscriber::FUN_100b8250()
|
MxStreamChunk* MxDSSubscriber::FUN_100b8250()
|
||||||
{
|
{
|
||||||
// TODO
|
MxStreamChunk* chunk = NULL;
|
||||||
return NULL;
|
|
||||||
|
if (m_unk0x20)
|
||||||
|
m_unk0x20->First(chunk);
|
||||||
|
|
||||||
|
if (chunk) {
|
||||||
|
m_unk0x20->Detach();
|
||||||
|
m_unk0x24.Append(chunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
return chunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
// STUB: LEGO1 0x100b8360
|
// FUNCTION: LEGO1 0x100b8360
|
||||||
MxStreamChunk* MxDSSubscriber::FUN_100b8360()
|
MxStreamChunk* MxDSSubscriber::FUN_100b8360()
|
||||||
{
|
{
|
||||||
// TODO
|
MxStreamChunk* chunk = NULL;
|
||||||
return NULL;
|
|
||||||
|
if (m_unk0x20)
|
||||||
|
m_unk0x20->First(chunk);
|
||||||
|
|
||||||
|
return chunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
// STUB: LEGO1 0x100b8390
|
// FUNCTION: LEGO1 0x100b8390
|
||||||
void MxDSSubscriber::FUN_100b8390(MxStreamChunk*)
|
void MxDSSubscriber::FUN_100b8390(MxStreamChunk* p_chunk)
|
||||||
{
|
{
|
||||||
// TODO
|
if (p_chunk) {
|
||||||
|
if (m_unk0x3c->Find(p_chunk)) {
|
||||||
|
m_unk0x3c->Detach();
|
||||||
|
if (p_chunk)
|
||||||
|
delete p_chunk;
|
||||||
|
}
|
||||||
|
else if ((p_chunk->GetFlags() & MxStreamChunk::Flag_Bit1) != 0 && p_chunk)
|
||||||
|
delete p_chunk;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
#include "mxcore.h"
|
#include "mxcore.h"
|
||||||
#include "mxdschunk.h"
|
#include "mxdschunk.h"
|
||||||
#include "mxstreamchunk.h"
|
#include "mxstreamchunk.h"
|
||||||
|
#include "mxstreamchunklist.h"
|
||||||
|
|
||||||
class MxStreamController;
|
class MxStreamController;
|
||||||
|
|
||||||
@ -28,13 +29,27 @@ class MxDSSubscriber : public MxCore {
|
|||||||
return !strcmp(p_name, MxDSSubscriber::ClassName()) || MxCore::IsA(p_name);
|
return !strcmp(p_name, MxDSSubscriber::ClassName()) || MxCore::IsA(p_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
MxResult FUN_100b7ed0(MxStreamController*, MxU32, MxS16);
|
MxResult Create(MxStreamController* p_controller, MxU32 p_objectId, MxS16 p_unk0x48);
|
||||||
|
void DeleteChunks();
|
||||||
|
MxResult AddChunk(MxStreamChunk* p_chunk, MxBool p_append);
|
||||||
MxStreamChunk* FUN_100b8250();
|
MxStreamChunk* FUN_100b8250();
|
||||||
MxStreamChunk* FUN_100b8360();
|
MxStreamChunk* FUN_100b8360();
|
||||||
void FUN_100b8390(MxStreamChunk*);
|
void FUN_100b8390(MxStreamChunk* p_chunk);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
undefined m_pad[0x44]; // 0x8
|
MxStreamChunkList m_unk0x08; // 0x08
|
||||||
|
MxStreamChunkListCursor* m_unk0x20; // 0x20
|
||||||
|
MxStreamChunkList m_unk0x24; // 0x24
|
||||||
|
MxStreamChunkListCursor* m_unk0x3c; // 0x3c
|
||||||
|
MxStreamController* m_controller; // 0x40
|
||||||
|
MxU32 m_objectId; // 0x44
|
||||||
|
MxS16 m_unk0x48; // 0x48
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// SYNTHETIC: LEGO1 0x100b7de0
|
||||||
|
// MxDSSubscriber::`scalar deleting destructor'
|
||||||
|
|
||||||
|
// TEMPLATE: LEGO1 0x100b7d00
|
||||||
|
// MxStreamChunkList::~MxStreamChunkList
|
||||||
|
|
||||||
#endif // MXDSSUBSCRIBER_H
|
#endif // MXDSSUBSCRIBER_H
|
||||||
|
|||||||
@ -12,8 +12,8 @@ DECOMP_SIZE_ASSERT(MxFlcPresenter, 0x68);
|
|||||||
MxFlcPresenter::MxFlcPresenter()
|
MxFlcPresenter::MxFlcPresenter()
|
||||||
{
|
{
|
||||||
this->m_flicHeader = NULL;
|
this->m_flicHeader = NULL;
|
||||||
this->m_flags &= 0xfd;
|
this->m_flags &= ~Flag_Bit2;
|
||||||
this->m_flags &= 0xfb;
|
this->m_flags &= ~Flag_Bit3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x100b3420
|
// FUNCTION: LEGO1 0x100b3420
|
||||||
|
|||||||
@ -54,6 +54,7 @@ class MxList : protected MxCollection<T> {
|
|||||||
virtual ~MxList() override;
|
virtual ~MxList() override;
|
||||||
|
|
||||||
void Append(T p_obj) { InsertEntry(p_obj, this->m_last, NULL); };
|
void Append(T p_obj) { InsertEntry(p_obj, this->m_last, NULL); };
|
||||||
|
void Prepend(T p_obj) { InsertEntry(p_obj, NULL, this->m_first); };
|
||||||
void DeleteAll(MxBool p_destroy = TRUE);
|
void DeleteAll(MxBool p_destroy = TRUE);
|
||||||
MxU32 GetCount() { return this->m_count; }
|
MxU32 GetCount() { return this->m_count; }
|
||||||
|
|
||||||
@ -92,6 +93,8 @@ class MxListCursor : public MxCore {
|
|||||||
void Destroy();
|
void Destroy();
|
||||||
MxBool Next(T& p_obj);
|
MxBool Next(T& p_obj);
|
||||||
MxBool Current(T& p_obj);
|
MxBool Current(T& p_obj);
|
||||||
|
MxBool First(T& p_obj);
|
||||||
|
MxBool Last(T& p_obj);
|
||||||
MxBool Advance();
|
MxBool Advance();
|
||||||
MxBool HasMatch() { return m_match != NULL; }
|
MxBool HasMatch() { return m_match != NULL; }
|
||||||
void SetValue(T p_obj);
|
void SetValue(T p_obj);
|
||||||
@ -193,8 +196,10 @@ inline MxBool MxListCursor<T>::Find(T p_obj)
|
|||||||
template <class T>
|
template <class T>
|
||||||
inline void MxListCursor<T>::Detach()
|
inline void MxListCursor<T>::Detach()
|
||||||
{
|
{
|
||||||
m_list->DeleteEntry(m_match);
|
if (m_match) {
|
||||||
m_match = NULL;
|
m_list->DeleteEntry(m_match);
|
||||||
|
m_match = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
@ -202,7 +207,8 @@ inline void MxListCursor<T>::Destroy()
|
|||||||
{
|
{
|
||||||
if (m_match) {
|
if (m_match) {
|
||||||
m_list->m_customDestructor(m_match->GetValue());
|
m_list->m_customDestructor(m_match->GetValue());
|
||||||
Detach();
|
m_list->DeleteEntry(m_match);
|
||||||
|
m_match = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,6 +235,26 @@ inline MxBool MxListCursor<T>::Current(T& p_obj)
|
|||||||
return m_match != NULL;
|
return m_match != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline MxBool MxListCursor<T>::First(T& p_obj)
|
||||||
|
{
|
||||||
|
m_match = m_list->m_first;
|
||||||
|
if (m_match)
|
||||||
|
p_obj = m_match->GetValue();
|
||||||
|
|
||||||
|
return m_match != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline MxBool MxListCursor<T>::Last(T& p_obj)
|
||||||
|
{
|
||||||
|
m_match = m_list->m_last;
|
||||||
|
if (m_match)
|
||||||
|
p_obj = m_match->GetValue();
|
||||||
|
|
||||||
|
return m_match != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline MxBool MxListCursor<T>::Advance()
|
inline MxBool MxListCursor<T>::Advance()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -20,8 +20,8 @@ MxLoopingFlcPresenter::~MxLoopingFlcPresenter()
|
|||||||
void MxLoopingFlcPresenter::Init()
|
void MxLoopingFlcPresenter::Init()
|
||||||
{
|
{
|
||||||
this->m_unk0x68 = 0;
|
this->m_unk0x68 = 0;
|
||||||
this->m_flags &= 0xfd;
|
this->m_flags &= ~Flag_Bit2;
|
||||||
this->m_flags &= 0xfb;
|
this->m_flags &= ~Flag_Bit3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// STUB: LEGO1 0x100b4432
|
// STUB: LEGO1 0x100b4432
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
#include "mxloopingsmkpresenter.h"
|
#include "mxloopingsmkpresenter.h"
|
||||||
|
|
||||||
#include "decomp.h"
|
#include "mxautolocker.h"
|
||||||
|
#include "mxdsmediaaction.h"
|
||||||
|
|
||||||
DECOMP_SIZE_ASSERT(MxLoopingSmkPresenter, 0x724);
|
DECOMP_SIZE_ASSERT(MxLoopingSmkPresenter, 0x724);
|
||||||
|
|
||||||
@ -19,12 +20,112 @@ MxLoopingSmkPresenter::~MxLoopingSmkPresenter()
|
|||||||
// FUNCTION: LEGO1 0x100b49b0
|
// FUNCTION: LEGO1 0x100b49b0
|
||||||
void MxLoopingSmkPresenter::Init()
|
void MxLoopingSmkPresenter::Init()
|
||||||
{
|
{
|
||||||
this->m_unk0x720 = 0;
|
this->m_elapsedDuration = 0;
|
||||||
this->m_flags &= 0xfd;
|
this->m_flags &= ~Flag_Bit2;
|
||||||
this->m_flags &= 0xfb;
|
this->m_flags &= ~Flag_Bit3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// STUB: LEGO1 0x100b49d0
|
// FUNCTION: LEGO1 0x100b49d0
|
||||||
void MxLoopingSmkPresenter::Destroy(MxBool p_fromDestructor)
|
void MxLoopingSmkPresenter::Destroy(MxBool p_fromDestructor)
|
||||||
{
|
{
|
||||||
|
m_criticalSection.Enter();
|
||||||
|
Init();
|
||||||
|
m_criticalSection.Leave();
|
||||||
|
|
||||||
|
if (!p_fromDestructor)
|
||||||
|
MxSmkPresenter::Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100b4a00
|
||||||
|
void MxLoopingSmkPresenter::VTable0x88()
|
||||||
|
{
|
||||||
|
if (m_mxSmack.m_smackTag.Frames == m_currentFrame) {
|
||||||
|
m_currentFrame = 0;
|
||||||
|
// TODO: struct incorrect, Palette at wrong offset?
|
||||||
|
memset(&m_mxSmack.m_smackTag.Palette[4], 0, sizeof(m_mxSmack.m_smackTag.Palette));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100b4a30
|
||||||
|
void MxLoopingSmkPresenter::NextFrame()
|
||||||
|
{
|
||||||
|
MxStreamChunk* chunk = NextChunk();
|
||||||
|
|
||||||
|
if (chunk->GetFlags() & MxStreamChunk::Flag_Bit2) {
|
||||||
|
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
|
||||||
|
m_currentTickleState = TickleState_Repeating;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LoadFrame(chunk);
|
||||||
|
AppendChunk(chunk);
|
||||||
|
m_elapsedDuration += 1000 / ((MxDSMediaAction*) m_action)->GetFramesPerSecond();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_subscriber->FUN_100b8390(chunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100b4a90
|
||||||
|
void MxLoopingSmkPresenter::VTable0x8c()
|
||||||
|
{
|
||||||
|
if (m_action->GetDuration() < m_elapsedDuration) {
|
||||||
|
m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState;
|
||||||
|
m_currentTickleState = TickleState_unk5;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
MxStreamChunk* chunk;
|
||||||
|
m_cursor->Current(chunk);
|
||||||
|
LoadFrame(chunk);
|
||||||
|
m_elapsedDuration += 1000 / ((MxDSMediaAction*) m_action)->GetFramesPerSecond();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100b4b00
|
||||||
|
void MxLoopingSmkPresenter::RepeatingTickle()
|
||||||
|
{
|
||||||
|
for (MxS16 i = 0; i < m_unk0x5c; i++) {
|
||||||
|
if (!m_cursor->HasMatch()) {
|
||||||
|
MxStreamChunk* chunk;
|
||||||
|
MxStreamChunkListCursor cursor(m_chunks);
|
||||||
|
|
||||||
|
cursor.Last(chunk);
|
||||||
|
MxLong time = chunk->GetTime();
|
||||||
|
|
||||||
|
cursor.First(chunk);
|
||||||
|
|
||||||
|
time -= chunk->GetTime();
|
||||||
|
time += 1000 / ((MxDSMediaAction*) m_action)->GetFramesPerSecond();
|
||||||
|
|
||||||
|
cursor.Reset();
|
||||||
|
while (cursor.Next(chunk))
|
||||||
|
chunk->SetTime(chunk->GetTime() + time);
|
||||||
|
|
||||||
|
m_cursor->Advance();
|
||||||
|
}
|
||||||
|
|
||||||
|
MxStreamChunk* chunk;
|
||||||
|
m_cursor->Current(chunk);
|
||||||
|
|
||||||
|
if (m_action->GetElapsedTime() < chunk->GetTime())
|
||||||
|
break;
|
||||||
|
|
||||||
|
VTable0x8c();
|
||||||
|
|
||||||
|
m_cursor->Next(chunk);
|
||||||
|
|
||||||
|
if (m_currentTickleState != TickleState_Repeating)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100b4cd0
|
||||||
|
MxResult MxLoopingSmkPresenter::AddToManager()
|
||||||
|
{
|
||||||
|
MxAutoLocker lock(&m_criticalSection);
|
||||||
|
return MxSmkPresenter::AddToManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100b4d40
|
||||||
|
void MxLoopingSmkPresenter::Destroy()
|
||||||
|
{
|
||||||
|
Destroy(FALSE);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,11 +18,21 @@ class MxLoopingSmkPresenter : public MxSmkPresenter {
|
|||||||
return "MxLoopingSmkPresenter";
|
return "MxLoopingSmkPresenter";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void RepeatingTickle() override; // vtable+0x24
|
||||||
|
virtual MxResult AddToManager() override; // vtable+0x34
|
||||||
|
virtual void Destroy() override; // vtable+0x38
|
||||||
|
virtual void NextFrame() override; // vtable+0x64
|
||||||
|
virtual void VTable0x88() override; // vtable+0x88
|
||||||
|
virtual void VTable0x8c(); // vtable+0x8c
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Init();
|
void Init();
|
||||||
void Destroy(MxBool p_fromDestructor);
|
void Destroy(MxBool p_fromDestructor);
|
||||||
|
|
||||||
undefined4 m_unk0x720;
|
MxLong m_elapsedDuration; // 0x720
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// SYNTHETIC: LEGO1 0x100b4930
|
||||||
|
// MxLoopingSmkPresenter::`scalar deleting destructor'
|
||||||
|
|
||||||
#endif // MXLOOPINGSMKPRESENTER_H
|
#endif // MXLOOPINGSMKPRESENTER_H
|
||||||
|
|||||||
@ -124,7 +124,7 @@ MxResult MxMediaPresenter::StartAction(MxStreamController* p_controller, MxDSAct
|
|||||||
m_subscriber = new MxDSSubscriber;
|
m_subscriber = new MxDSSubscriber;
|
||||||
|
|
||||||
if (!m_subscriber ||
|
if (!m_subscriber ||
|
||||||
m_subscriber->FUN_100b7ed0(p_controller, p_action->GetObjectId(), p_action->GetUnknown24()) != SUCCESS)
|
m_subscriber->Create(p_controller, p_action->GetObjectId(), p_action->GetUnknown24()) != SUCCESS)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -40,8 +40,9 @@ MxResult MxRAMStreamController::Open(const char* p_filename)
|
|||||||
MxResult MxRAMStreamController::VTable0x20(MxDSAction* p_action)
|
MxResult MxRAMStreamController::VTable0x20(MxDSAction* p_action)
|
||||||
{
|
{
|
||||||
MxAutoLocker locker(&m_criticalSection);
|
MxAutoLocker locker(&m_criticalSection);
|
||||||
MxS16 unk0x24 = 0;
|
MxS32 unk0x24 = 0;
|
||||||
MxResult result = FAILURE;
|
MxResult result = FAILURE;
|
||||||
|
|
||||||
if (p_action->GetUnknown24() == -1) {
|
if (p_action->GetUnknown24() == -1) {
|
||||||
p_action->SetUnknown24(-3);
|
p_action->SetUnknown24(-3);
|
||||||
MxDSAction* action = m_unk0x54.Find(p_action, FALSE);
|
MxDSAction* action = m_unk0x54.Find(p_action, FALSE);
|
||||||
@ -84,12 +85,15 @@ MxResult MxRAMStreamController::DeserializeObject(MxDSStreamingAction& p_action)
|
|||||||
{
|
{
|
||||||
MxAutoLocker locker(&m_criticalSection);
|
MxAutoLocker locker(&m_criticalSection);
|
||||||
MxResult result;
|
MxResult result;
|
||||||
undefined4 value = 0;
|
MxDSStreamingAction* value = NULL;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
m_buffer.FUN_100c6f80(p_action.GetUnknown94());
|
m_buffer.FUN_100c6f80(p_action.GetUnknown94());
|
||||||
|
// Probably not MxResult, see below
|
||||||
result = m_buffer.FUN_100c67b0(this, &p_action, &value);
|
result = m_buffer.FUN_100c67b0(this, &p_action, &value);
|
||||||
} while (m_unk0x3c.Find(&p_action, FALSE) != NULL);
|
} while (m_unk0x3c.Find(&p_action, FALSE) != NULL);
|
||||||
return result;
|
|
||||||
|
return result == SUCCESS ? SUCCESS : FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// STUB: LEGO1 0x100d0d80
|
// STUB: LEGO1 0x100d0d80
|
||||||
|
|||||||
@ -23,7 +23,7 @@ MxU32 MxRAMStreamProvider::GetFileSize()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x100d0940
|
// FUNCTION: LEGO1 0x100d0940
|
||||||
MxU32 MxRAMStreamProvider::GetStreamBuffersNum()
|
MxS32 MxRAMStreamProvider::GetStreamBuffersNum()
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,7 +24,7 @@ class MxRAMStreamProvider : public MxStreamProvider {
|
|||||||
|
|
||||||
virtual MxResult SetResourceToGet(MxStreamController* p_resource) override; // vtable+0x14
|
virtual MxResult SetResourceToGet(MxStreamController* p_resource) override; // vtable+0x14
|
||||||
virtual MxU32 GetFileSize() override; // vtable+0x18
|
virtual MxU32 GetFileSize() override; // vtable+0x18
|
||||||
virtual MxU32 GetStreamBuffersNum() override; // vtable+0x1c
|
virtual MxS32 GetStreamBuffersNum() override; // vtable+0x1c
|
||||||
virtual MxU32 GetLengthInDWords() override; // vtable+0x24
|
virtual MxU32 GetLengthInDWords() override; // vtable+0x24
|
||||||
virtual MxU32* GetBufferForDWords() override; // vtable+0x28
|
virtual MxU32* GetBufferForDWords() override; // vtable+0x28
|
||||||
|
|
||||||
|
|||||||
@ -21,10 +21,10 @@ MxSmkPresenter::~MxSmkPresenter()
|
|||||||
// FUNCTION: LEGO1 0x100b38d0
|
// FUNCTION: LEGO1 0x100b38d0
|
||||||
void MxSmkPresenter::Init()
|
void MxSmkPresenter::Init()
|
||||||
{
|
{
|
||||||
m_unk0x71c = 0;
|
m_currentFrame = 0;
|
||||||
memset(&m_mxSmack, 0, sizeof(m_mxSmack));
|
memset(&m_mxSmack, 0, sizeof(m_mxSmack));
|
||||||
m_flags &= 0xfd;
|
m_flags &= ~Flag_Bit2;
|
||||||
m_flags &= 0xfb;
|
m_flags &= ~Flag_Bit3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x100b3900
|
// FUNCTION: LEGO1 0x100b3900
|
||||||
@ -65,8 +65,8 @@ void MxSmkPresenter::LoadFrame(MxStreamChunk* p_chunk)
|
|||||||
MxU8* bitmapData = m_bitmap->GetBitmapData();
|
MxU8* bitmapData = m_bitmap->GetBitmapData();
|
||||||
MxU8* chunkData = p_chunk->GetData();
|
MxU8* chunkData = p_chunk->GetData();
|
||||||
|
|
||||||
MxBool paletteChanged = m_mxSmack.m_frameTypes[m_unk0x71c] & 1;
|
MxBool paletteChanged = m_mxSmack.m_frameTypes[m_currentFrame] & 1;
|
||||||
m_unk0x71c++;
|
m_currentFrame++;
|
||||||
VTable0x88();
|
VTable0x88();
|
||||||
|
|
||||||
MxRectList list(TRUE);
|
MxRectList list(TRUE);
|
||||||
@ -90,13 +90,13 @@ void MxSmkPresenter::LoadFrame(MxStreamChunk* p_chunk)
|
|||||||
void MxSmkPresenter::VTable0x88()
|
void MxSmkPresenter::VTable0x88()
|
||||||
{
|
{
|
||||||
if ((m_mxSmack.m_smackTag.SmackerType & 1) != 0) {
|
if ((m_mxSmack.m_smackTag.SmackerType & 1) != 0) {
|
||||||
MxU32 und = (m_unk0x71c % m_mxSmack.m_smackTag.Frames);
|
MxU32 und = (m_currentFrame % m_mxSmack.m_smackTag.Frames);
|
||||||
if (1 < m_unk0x71c && und == 1)
|
if (1 < m_currentFrame && und == 1)
|
||||||
m_unk0x71c = 1;
|
m_currentFrame = 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (m_mxSmack.m_smackTag.Frames == m_unk0x71c) {
|
if (m_mxSmack.m_smackTag.Frames == m_currentFrame) {
|
||||||
m_unk0x71c = 0;
|
m_currentFrame = 0;
|
||||||
// TODO: struct incorrect, Palette at wrong offset?
|
// TODO: struct incorrect, Palette at wrong offset?
|
||||||
memset(&m_mxSmack.m_smackTag.Palette[4], 0, sizeof(m_mxSmack.m_smackTag.Palette));
|
memset(&m_mxSmack.m_smackTag.Palette[4], 0, sizeof(m_mxSmack.m_smackTag.Palette));
|
||||||
}
|
}
|
||||||
@ -111,6 +111,12 @@ void MxSmkPresenter::RealizePalette()
|
|||||||
delete palette;
|
delete palette;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FUNCTION: LEGO1 0x100b42f0
|
||||||
|
MxResult MxSmkPresenter::AddToManager()
|
||||||
|
{
|
||||||
|
return MxVideoPresenter::AddToManager();
|
||||||
|
}
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x100b4300
|
// FUNCTION: LEGO1 0x100b4300
|
||||||
void MxSmkPresenter::Destroy()
|
void MxSmkPresenter::Destroy()
|
||||||
{
|
{
|
||||||
|
|||||||
@ -25,6 +25,7 @@ class MxSmkPresenter : public MxVideoPresenter {
|
|||||||
return !strcmp(p_name, MxSmkPresenter::ClassName()) || MxVideoPresenter::IsA(p_name);
|
return !strcmp(p_name, MxSmkPresenter::ClassName()) || MxVideoPresenter::IsA(p_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual MxResult AddToManager() override; // vtable+0x34
|
||||||
virtual void Destroy() override; // vtable+0x38
|
virtual void Destroy() override; // vtable+0x38
|
||||||
virtual void LoadHeader(MxStreamChunk* p_chunk) override; // vtable+0x5c
|
virtual void LoadHeader(MxStreamChunk* p_chunk) override; // vtable+0x5c
|
||||||
virtual void CreateBitmap() override; // vtable+0x60
|
virtual void CreateBitmap() override; // vtable+0x60
|
||||||
@ -36,8 +37,9 @@ class MxSmkPresenter : public MxVideoPresenter {
|
|||||||
void Init();
|
void Init();
|
||||||
void Destroy(MxBool p_fromDestructor);
|
void Destroy(MxBool p_fromDestructor);
|
||||||
|
|
||||||
MxSmack m_mxSmack; // 0x64
|
protected:
|
||||||
undefined4 m_unk0x71c; // 0x71c
|
MxSmack m_mxSmack; // 0x64
|
||||||
|
MxU32 m_currentFrame; // 0x71c
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MXSMKPRESENTER_H
|
#endif // MXSMKPRESENTER_H
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "legoomni.h"
|
#include "legoomni.h"
|
||||||
#include "mxautolocker.h"
|
#include "mxautolocker.h"
|
||||||
|
#include "mxdsstreamingaction.h"
|
||||||
#include "mxnextactiondatastart.h"
|
#include "mxnextactiondatastart.h"
|
||||||
#include "mxstreamchunk.h"
|
#include "mxstreamchunk.h"
|
||||||
|
|
||||||
@ -21,23 +22,46 @@ MxResult MxStreamController::VTable0x1c(undefined4, undefined4)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x100b9420
|
// FUNCTION: LEGO1 0x100b9420
|
||||||
MxResult MxStreamController::VTable0x28()
|
MxDSStreamingAction* MxStreamController::VTable0x28()
|
||||||
{
|
{
|
||||||
return SUCCESS;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x100c0b90
|
// FUNCTION: LEGO1 0x100c0b90
|
||||||
MxStreamController::MxStreamController()
|
MxStreamController::MxStreamController()
|
||||||
{
|
{
|
||||||
m_provider = NULL;
|
m_provider = NULL;
|
||||||
m_unk0x2c = 0; // TODO: probably also NULL
|
m_unk0x2c = NULL;
|
||||||
m_action0x60 = NULL;
|
m_action0x60 = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// STUB: LEGO1 0x100c1290
|
// FUNCTION: LEGO1 0x100c1290
|
||||||
MxStreamController::~MxStreamController()
|
MxStreamController::~MxStreamController()
|
||||||
{
|
{
|
||||||
// TODO
|
MxAutoLocker lock(&m_criticalSection);
|
||||||
|
|
||||||
|
MxDSSubscriber* subscriber;
|
||||||
|
while (m_subscriberList.PopFront(subscriber))
|
||||||
|
delete subscriber;
|
||||||
|
|
||||||
|
MxDSAction* action;
|
||||||
|
while (m_unk0x3c.PopFront(action))
|
||||||
|
delete action;
|
||||||
|
|
||||||
|
if (m_provider) {
|
||||||
|
MxStreamProvider* provider = m_provider;
|
||||||
|
m_provider = NULL;
|
||||||
|
provider->VTable0x20(&MxDSAction());
|
||||||
|
delete provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_unk0x2c) {
|
||||||
|
delete m_unk0x2c;
|
||||||
|
m_unk0x2c = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (m_unk0x54.PopFront(action))
|
||||||
|
delete action;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x100c1520
|
// FUNCTION: LEGO1 0x100c1520
|
||||||
@ -51,6 +75,18 @@ MxResult MxStreamController::Open(const char* p_filename)
|
|||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// STUB: LEGO1 0x100c15d0
|
||||||
|
void MxStreamController::FUN_100c15d0(MxDSSubscriber* p_subscriber)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
// STUB: LEGO1 0x100c1620
|
||||||
|
void MxStreamController::FUN_100c1620(MxDSSubscriber* p_subscriber)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x100c1690
|
// FUNCTION: LEGO1 0x100c1690
|
||||||
MxResult MxStreamController::VTable0x20(MxDSAction* p_action)
|
MxResult MxStreamController::VTable0x20(MxDSAction* p_action)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -7,16 +7,18 @@
|
|||||||
#include "mxcriticalsection.h"
|
#include "mxcriticalsection.h"
|
||||||
#include "mxdsaction.h"
|
#include "mxdsaction.h"
|
||||||
#include "mxdsobject.h"
|
#include "mxdsobject.h"
|
||||||
|
#include "mxdssubscriber.h"
|
||||||
#include "mxstl/stlcompat.h"
|
#include "mxstl/stlcompat.h"
|
||||||
#include "mxstreamlist.h"
|
#include "mxstreamlist.h"
|
||||||
#include "mxstreamprovider.h"
|
#include "mxstreamprovider.h"
|
||||||
|
|
||||||
|
class MxDSStreamingAction;
|
||||||
|
|
||||||
// VTABLE: LEGO1 0x100dc968
|
// VTABLE: LEGO1 0x100dc968
|
||||||
// SIZE 0x64
|
// SIZE 0x64
|
||||||
class MxStreamController : public MxCore {
|
class MxStreamController : public MxCore {
|
||||||
public:
|
public:
|
||||||
MxStreamController();
|
MxStreamController();
|
||||||
|
|
||||||
virtual ~MxStreamController() override; // vtable+0x0
|
virtual ~MxStreamController() override; // vtable+0x0
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x100c0f10
|
// FUNCTION: LEGO1 0x100c0f10
|
||||||
@ -37,16 +39,18 @@ class MxStreamController : public MxCore {
|
|||||||
virtual MxResult VTable0x1c(undefined4, undefined4); // vtable+0x1c
|
virtual MxResult VTable0x1c(undefined4, undefined4); // vtable+0x1c
|
||||||
virtual MxResult VTable0x20(MxDSAction* p_action); // vtable+0x20
|
virtual MxResult VTable0x20(MxDSAction* p_action); // vtable+0x20
|
||||||
virtual MxResult VTable0x24(MxDSAction* p_action); // vtable+0x24
|
virtual MxResult VTable0x24(MxDSAction* p_action); // vtable+0x24
|
||||||
virtual MxResult VTable0x28(); // vtable+0x28
|
virtual MxDSStreamingAction* VTable0x28(); // vtable+0x28
|
||||||
virtual MxResult VTable0x2c(MxDSAction* p_action, MxU32 p_bufferval); // vtable+0x2c
|
virtual MxResult VTable0x2c(MxDSAction* p_action, MxU32 p_bufferval); // vtable+0x2c
|
||||||
virtual MxResult VTable0x30(MxDSAction* p_action); // vtable+0x30
|
virtual MxResult VTable0x30(MxDSAction* p_action); // vtable+0x30
|
||||||
|
|
||||||
|
void FUN_100c15d0(MxDSSubscriber* p_subscriber);
|
||||||
|
void FUN_100c1620(MxDSSubscriber* p_subscriber);
|
||||||
MxResult FUN_100c1800(MxDSAction* p_action, MxU32 p_val);
|
MxResult FUN_100c1800(MxDSAction* p_action, MxU32 p_val);
|
||||||
MxBool FUN_100c20d0(MxDSObject& p_obj);
|
|
||||||
MxResult FUN_100c1a00(MxDSAction* p_action, MxU32 p_bufferval);
|
MxResult FUN_100c1a00(MxDSAction* p_action, MxU32 p_bufferval);
|
||||||
MxPresenter* FUN_100c1e70(MxDSAction& p_action);
|
MxPresenter* FUN_100c1e70(MxDSAction& p_action);
|
||||||
MxResult InsertActionToList54(MxDSAction* p_action);
|
|
||||||
MxResult FUN_100c1f00(MxDSAction* p_action);
|
MxResult FUN_100c1f00(MxDSAction* p_action);
|
||||||
|
MxBool FUN_100c20d0(MxDSObject& p_obj);
|
||||||
|
MxResult InsertActionToList54(MxDSAction* p_action);
|
||||||
|
|
||||||
inline MxAtomId& GetAtom() { return m_atom; };
|
inline MxAtomId& GetAtom() { return m_atom; };
|
||||||
inline MxStreamListMxDSAction& GetUnk0x54() { return m_unk0x54; };
|
inline MxStreamListMxDSAction& GetUnk0x54() { return m_unk0x54; };
|
||||||
@ -55,7 +59,7 @@ class MxStreamController : public MxCore {
|
|||||||
MxCriticalSection m_criticalSection; // 0x8
|
MxCriticalSection m_criticalSection; // 0x8
|
||||||
MxAtomId m_atom; // 0x24
|
MxAtomId m_atom; // 0x24
|
||||||
MxStreamProvider* m_provider; // 0x28
|
MxStreamProvider* m_provider; // 0x28
|
||||||
undefined4 m_unk0x2c; // 0x2c
|
undefined4* m_unk0x2c; // 0x2c
|
||||||
MxStreamListMxDSSubscriber m_subscriberList; // 0x30
|
MxStreamListMxDSSubscriber m_subscriberList; // 0x30
|
||||||
MxStreamListMxDSAction m_unk0x3c; // 0x3c
|
MxStreamListMxDSAction m_unk0x3c; // 0x3c
|
||||||
MxStreamListMxNextActionDataStart m_nextActionList; // 0x48
|
MxStreamListMxNextActionDataStart m_nextActionList; // 0x48
|
||||||
|
|||||||
@ -46,7 +46,6 @@ MxStreamer::~MxStreamer()
|
|||||||
// FUNCTION: LEGO1 0x100b92c0
|
// FUNCTION: LEGO1 0x100b92c0
|
||||||
MxStreamController* MxStreamer::Open(const char* p_name, MxU16 p_lookupType)
|
MxStreamController* MxStreamer::Open(const char* p_name, MxU16 p_lookupType)
|
||||||
{
|
{
|
||||||
// TODO
|
|
||||||
MxStreamController* stream = NULL;
|
MxStreamController* stream = NULL;
|
||||||
|
|
||||||
if (!GetOpenStream(p_name)) {
|
if (!GetOpenStream(p_name)) {
|
||||||
@ -59,7 +58,7 @@ MxStreamController* MxStreamer::Open(const char* p_name, MxU16 p_lookupType)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!stream || stream->Open(p_name) != SUCCESS || AddStreamControllerToOpenList(stream) != SUCCESS) {
|
if (stream && (stream->Open(p_name) != SUCCESS || AddStreamControllerToOpenList(stream) != SUCCESS)) {
|
||||||
delete stream;
|
delete stream;
|
||||||
stream = NULL;
|
stream = NULL;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,18 @@
|
|||||||
#include "mxstl/stlcompat.h"
|
#include "mxstl/stlcompat.h"
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
class MxStreamList : public list<T> {};
|
class MxStreamList : public list<T> {
|
||||||
|
public:
|
||||||
|
MxBool PopFront(T& p_obj)
|
||||||
|
{
|
||||||
|
if (empty())
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
p_obj = front();
|
||||||
|
pop_front();
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// SIZE 0xc
|
// SIZE 0xc
|
||||||
class MxStreamListMxDSAction : public MxStreamList<MxDSAction*> {
|
class MxStreamListMxDSAction : public MxStreamList<MxDSAction*> {
|
||||||
|
|||||||
@ -12,6 +12,6 @@ MxResult MxStreamProvider::SetResourceToGet(MxStreamController* p_resource)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x100d07d0
|
// FUNCTION: LEGO1 0x100d07d0
|
||||||
void MxStreamProvider::VTable0x20(undefined4)
|
void MxStreamProvider::VTable0x20(MxDSAction* p_action)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
#include "mxdsfile.h"
|
#include "mxdsfile.h"
|
||||||
|
|
||||||
class MxStreamController;
|
class MxStreamController;
|
||||||
|
class MxDSAction;
|
||||||
|
|
||||||
// VTABLE: LEGO1 0x100dd100
|
// VTABLE: LEGO1 0x100dd100
|
||||||
// SIZE 0x10
|
// SIZE 0x10
|
||||||
@ -27,8 +28,8 @@ class MxStreamProvider : public MxCore {
|
|||||||
|
|
||||||
virtual MxResult SetResourceToGet(MxStreamController* p_resource); // vtable+0x14
|
virtual MxResult SetResourceToGet(MxStreamController* p_resource); // vtable+0x14
|
||||||
virtual MxU32 GetFileSize() = 0; // vtable+0x18
|
virtual MxU32 GetFileSize() = 0; // vtable+0x18
|
||||||
virtual MxU32 GetStreamBuffersNum() = 0; // vtable+0x1c
|
virtual MxS32 GetStreamBuffersNum() = 0; // vtable+0x1c
|
||||||
virtual void VTable0x20(undefined4); // vtable+0x20
|
virtual void VTable0x20(MxDSAction* p_action); // vtable+0x20
|
||||||
virtual MxU32 GetLengthInDWords() = 0; // vtable+0x24
|
virtual MxU32 GetLengthInDWords() = 0; // vtable+0x24
|
||||||
virtual MxU32* GetBufferForDWords() = 0; // vtable+0x28
|
virtual MxU32* GetBufferForDWords() = 0; // vtable+0x28
|
||||||
|
|
||||||
|
|||||||
@ -29,30 +29,29 @@ MxTickleManager::~MxTickleManager()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Match.
|
|
||||||
// FUNCTION: LEGO1 0x100bdde0
|
// FUNCTION: LEGO1 0x100bdde0
|
||||||
MxResult MxTickleManager::Tickle()
|
MxResult MxTickleManager::Tickle()
|
||||||
{
|
{
|
||||||
MxTime time = Timer()->GetTime();
|
MxTime time = Timer()->GetTime();
|
||||||
|
|
||||||
MxTickleClientPtrList::iterator it = m_clients.begin();
|
for (MxTickleClientPtrList::iterator it = m_clients.begin(); it != m_clients.end();) {
|
||||||
|
|
||||||
while (it != m_clients.end()) {
|
|
||||||
MxTickleClient* client = *it;
|
MxTickleClient* client = *it;
|
||||||
if ((client->GetFlags() & TICKLE_MANAGER_FLAG_DESTROY) == 0) {
|
|
||||||
if (client->GetLastUpdateTime() >= time)
|
// TODO: Match.
|
||||||
|
if ((MxU8) client->GetFlags() & TICKLE_MANAGER_FLAG_DESTROY) {
|
||||||
|
m_clients.erase(it++);
|
||||||
|
delete client;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
it++;
|
||||||
|
|
||||||
|
if (client->GetLastUpdateTime() > time)
|
||||||
client->SetLastUpdateTime(-client->GetTickleInterval());
|
client->SetLastUpdateTime(-client->GetTickleInterval());
|
||||||
|
|
||||||
if ((client->GetTickleInterval() + client->GetLastUpdateTime()) < time) {
|
if ((client->GetTickleInterval() + client->GetLastUpdateTime()) < time) {
|
||||||
client->GetClient()->Tickle();
|
client->GetClient()->Tickle();
|
||||||
client->SetLastUpdateTime(time);
|
client->SetLastUpdateTime(time);
|
||||||
}
|
}
|
||||||
|
|
||||||
it++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
m_clients.erase(it++);
|
|
||||||
delete client;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -188,16 +188,16 @@ void MxVideoPresenter::Init()
|
|||||||
m_unk0x5c = 1;
|
m_unk0x5c = 1;
|
||||||
m_unk0x58 = NULL;
|
m_unk0x58 = NULL;
|
||||||
m_unk0x60 = -1;
|
m_unk0x60 = -1;
|
||||||
m_flags = m_flags & 0xfe;
|
m_flags &= ~Flag_Bit1;
|
||||||
|
|
||||||
if (MVideoManager() != NULL) {
|
if (MVideoManager() != NULL) {
|
||||||
MVideoManager();
|
MVideoManager();
|
||||||
m_flags = m_flags | 2;
|
m_flags |= Flag_Bit2;
|
||||||
m_flags = m_flags & 0xfb;
|
m_flags &= ~Flag_Bit3;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_flags = m_flags & 0xf7;
|
m_flags &= ~Flag_Bit4;
|
||||||
m_flags = m_flags & 0xef;
|
m_flags &= ~Flag_Bit5;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x100b27b0
|
// FUNCTION: LEGO1 0x100b27b0
|
||||||
@ -209,8 +209,8 @@ void MxVideoPresenter::Destroy(MxBool p_fromDestructor)
|
|||||||
if (m_unk0x58) {
|
if (m_unk0x58) {
|
||||||
m_unk0x58->Release();
|
m_unk0x58->Release();
|
||||||
m_unk0x58 = NULL;
|
m_unk0x58 = NULL;
|
||||||
m_flags = m_flags & 0xfd;
|
m_flags &= ~Flag_Bit2;
|
||||||
m_flags = m_flags & 0xfb;
|
m_flags &= ~Flag_Bit3;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MVideoManager() && (m_alpha || m_bitmap)) {
|
if (MVideoManager() && (m_alpha || m_bitmap)) {
|
||||||
|
|||||||
@ -1,43 +1,83 @@
|
|||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
import pathlib
|
||||||
from typing import Iterator
|
from typing import Iterator
|
||||||
|
|
||||||
|
|
||||||
class WinePathConverter:
|
def winepath_win_to_unix(path: str) -> str:
|
||||||
def __init__(self, unix_cwd):
|
return subprocess.check_output(["winepath", path], text=True).strip()
|
||||||
self.unix_cwd = unix_cwd
|
|
||||||
self.win_cwd = self._call_winepath_unix2win(self.unix_cwd)
|
|
||||||
|
|
||||||
def get_wine_path(self, unix_fn: str) -> str:
|
|
||||||
if unix_fn.startswith("./"):
|
def winepath_unix_to_win(path: str) -> str:
|
||||||
return self.win_cwd + "\\" + unix_fn[2:].replace("/", "\\")
|
return subprocess.check_output(["winepath", "-w", path], text=True).strip()
|
||||||
if unix_fn.startswith(self.unix_cwd):
|
|
||||||
return (
|
|
||||||
self.win_cwd
|
class PathResolver:
|
||||||
+ "\\"
|
"""Intended to resolve Windows/Wine paths used in the PDB (cvdump) output
|
||||||
+ unix_fn.removeprefix(self.unix_cwd).replace("/", "\\").lstrip("\\")
|
into a "canonical" format to be matched against code file paths from os.walk.
|
||||||
|
MSVC may include files from the parent dir using `..`. We eliminate those and create
|
||||||
|
an absolute path so that information about the same file under different names
|
||||||
|
will be combined into the same record. (i.e. line_no/addr pairs from LINES section.)
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, basedir) -> None:
|
||||||
|
"""basedir is the root path of the code directory in the format for your OS.
|
||||||
|
We will convert it to a PureWindowsPath to be platform-independent
|
||||||
|
and match that to the paths from the PDB."""
|
||||||
|
|
||||||
|
# Memoize the converted paths. We will need to do this for each path
|
||||||
|
# in the PDB, for each function in that file. (i.e. lots of repeated work)
|
||||||
|
self._memo = {}
|
||||||
|
|
||||||
|
# Convert basedir to an absolute path if it is not already.
|
||||||
|
# If it is not absolute, we cannot do the path swap on unix.
|
||||||
|
self._realdir = pathlib.Path(basedir).resolve()
|
||||||
|
|
||||||
|
self._is_unix = os.name != "nt"
|
||||||
|
if self._is_unix:
|
||||||
|
self._basedir = pathlib.PureWindowsPath(
|
||||||
|
winepath_unix_to_win(str(self._realdir))
|
||||||
)
|
)
|
||||||
return self._call_winepath_unix2win(unix_fn)
|
else:
|
||||||
|
self._basedir = self._realdir
|
||||||
|
|
||||||
def get_unix_path(self, win_fn: str) -> str:
|
def _memo_wrapper(self, path_str: str) -> str:
|
||||||
if win_fn.startswith(".\\") or win_fn.startswith("./"):
|
"""Wrapper so we can memoize from the public caller method"""
|
||||||
return self.unix_cwd + "/" + win_fn[2:].replace("\\", "/")
|
path = pathlib.PureWindowsPath(path_str)
|
||||||
if win_fn.startswith(self.win_cwd):
|
if not path.is_absolute():
|
||||||
return (
|
# pathlib syntactic sugar for path concat
|
||||||
self.unix_cwd
|
path = self._basedir / path
|
||||||
+ "/"
|
|
||||||
+ win_fn.removeprefix(self.win_cwd).replace("\\", "/")
|
|
||||||
)
|
|
||||||
return self._call_winepath_win2unix(win_fn)
|
|
||||||
|
|
||||||
@staticmethod
|
if self._is_unix:
|
||||||
def _call_winepath_unix2win(fn: str) -> str:
|
# If the given path is relative to the basedir, deconstruct the path
|
||||||
return subprocess.check_output(["winepath", "-w", fn], text=True).strip()
|
# and swap in our unix path to avoid an expensive call to winepath.
|
||||||
|
try:
|
||||||
|
# Will raise ValueError if we are not relative to the base.
|
||||||
|
section = path.relative_to(self._basedir)
|
||||||
|
# Should combine to pathlib.PosixPath
|
||||||
|
mockpath = (self._realdir / section).resolve()
|
||||||
|
if mockpath.is_file():
|
||||||
|
return str(mockpath)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
@staticmethod
|
# We are not relative to the basedir, or our path swap attempt
|
||||||
def _call_winepath_win2unix(fn: str) -> str:
|
# did not point at an actual file. Either way, we are forced
|
||||||
return subprocess.check_output(["winepath", fn], text=True).strip()
|
# to call winepath using our original path.
|
||||||
|
return winepath_win_to_unix(str(path))
|
||||||
|
|
||||||
|
# We must be on Windows. Convert back to WindowsPath.
|
||||||
|
# The resolve() call will eliminate intermediate backdir references.
|
||||||
|
return str(pathlib.Path(path).resolve())
|
||||||
|
|
||||||
|
def resolve_cvdump(self, path_str: str) -> str:
|
||||||
|
"""path_str is in Windows/Wine path format.
|
||||||
|
We will return a path in the format for the host OS."""
|
||||||
|
if path_str not in self._memo:
|
||||||
|
self._memo[path_str] = self._memo_wrapper(path_str)
|
||||||
|
|
||||||
|
return self._memo[path_str]
|
||||||
|
|
||||||
|
|
||||||
def is_file_cpp(filename: str) -> bool:
|
def is_file_cpp(filename: str) -> bool:
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
from isledecomp.lib import lib_path_join
|
from isledecomp.lib import lib_path_join
|
||||||
|
from isledecomp.dir import PathResolver, winepath_unix_to_win
|
||||||
|
|
||||||
|
|
||||||
class RecompiledInfo:
|
class RecompiledInfo:
|
||||||
@ -16,14 +17,15 @@ class SymInfo:
|
|||||||
lines = {}
|
lines = {}
|
||||||
names = {}
|
names = {}
|
||||||
|
|
||||||
def __init__(self, pdb, sym_recompfile, sym_logger, sym_wine_path_converter=None):
|
def __init__(self, pdb, sym_recompfile, sym_logger, base_dir):
|
||||||
self.logger = sym_logger
|
self.logger = sym_logger
|
||||||
|
path_resolver = PathResolver(base_dir)
|
||||||
call = [lib_path_join("cvdump.exe"), "-l", "-s"]
|
call = [lib_path_join("cvdump.exe"), "-l", "-s"]
|
||||||
|
|
||||||
if sym_wine_path_converter:
|
if os.name != "nt":
|
||||||
# Run cvdump through wine and convert path to Windows-friendly wine path
|
# Run cvdump through wine and convert path to Windows-friendly wine path
|
||||||
call.insert(0, "wine")
|
call.insert(0, "wine")
|
||||||
call.append(sym_wine_path_converter.get_wine_path(pdb))
|
call.append(winepath_unix_to_win(pdb))
|
||||||
else:
|
else:
|
||||||
call.append(pdb)
|
call.append(pdb)
|
||||||
|
|
||||||
@ -70,10 +72,7 @@ def __init__(self, pdb, sym_recompfile, sym_logger, sym_wine_path_converter=None
|
|||||||
and not line.startswith(" ")
|
and not line.startswith(" ")
|
||||||
):
|
):
|
||||||
sourcepath = line.split()[0]
|
sourcepath = line.split()[0]
|
||||||
|
sourcepath = path_resolver.resolve_cvdump(sourcepath)
|
||||||
if sym_wine_path_converter:
|
|
||||||
# Convert filename to Unix path for file compare
|
|
||||||
sourcepath = sym_wine_path_converter.get_unix_path(sourcepath)
|
|
||||||
|
|
||||||
if sourcepath not in self.lines:
|
if sourcepath not in self.lines:
|
||||||
self.lines[sourcepath] = {}
|
self.lines[sourcepath] = {}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
from typing import Optional
|
||||||
import pytest
|
import pytest
|
||||||
from isledecomp.parser.parser import (
|
from isledecomp.parser.parser import (
|
||||||
ReaderState as _rs,
|
ReaderState as _rs,
|
||||||
@ -70,7 +71,7 @@
|
|||||||
"state, marker_type, new_state, expected_error", state_change_marker_cases
|
"state, marker_type, new_state, expected_error", state_change_marker_cases
|
||||||
)
|
)
|
||||||
def test_state_change_by_marker(
|
def test_state_change_by_marker(
|
||||||
state: _rs, marker_type: str, new_state: _rs, expected_error: None | _pe
|
state: _rs, marker_type: str, new_state: _rs, expected_error: Optional[_pe]
|
||||||
):
|
):
|
||||||
p = DecompParser()
|
p = DecompParser()
|
||||||
p.state = state
|
p.state = state
|
||||||
|
|||||||
32
tools/isledecomp/tests/test_path_resolver_nt.py
Normal file
32
tools/isledecomp/tests/test_path_resolver_nt.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
from os import name as os_name
|
||||||
|
import pytest
|
||||||
|
from isledecomp.dir import PathResolver
|
||||||
|
|
||||||
|
|
||||||
|
if os_name != "nt":
|
||||||
|
pytest.skip(reason="Skip Windows-only tests", allow_module_level=True)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(name="resolver")
|
||||||
|
def fixture_resolver_win():
|
||||||
|
yield PathResolver("C:\\isle")
|
||||||
|
|
||||||
|
|
||||||
|
def test_identity(resolver):
|
||||||
|
assert resolver.resolve_cvdump("C:\\isle\\test.h") == "C:\\isle\\test.h"
|
||||||
|
|
||||||
|
|
||||||
|
def test_outside_basedir(resolver):
|
||||||
|
assert resolver.resolve_cvdump("C:\\lego\\test.h") == "C:\\lego\\test.h"
|
||||||
|
|
||||||
|
|
||||||
|
def test_relative(resolver):
|
||||||
|
assert resolver.resolve_cvdump(".\\test.h") == "C:\\isle\\test.h"
|
||||||
|
assert resolver.resolve_cvdump("..\\test.h") == "C:\\test.h"
|
||||||
|
|
||||||
|
|
||||||
|
def test_intermediate_relative(resolver):
|
||||||
|
"""These paths may not register as `relative` paths, but we want to
|
||||||
|
produce a single absolute path for each."""
|
||||||
|
assert resolver.resolve_cvdump("C:\\isle\\test\\..\\test.h") == "C:\\isle\\test.h"
|
||||||
|
assert resolver.resolve_cvdump(".\\subdir\\..\\test.h") == "C:\\isle\\test.h"
|
||||||
69
tools/isledecomp/tests/test_path_resolver_posix.py
Normal file
69
tools/isledecomp/tests/test_path_resolver_posix.py
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
from os import name as os_name
|
||||||
|
from unittest.mock import patch
|
||||||
|
import pytest
|
||||||
|
from isledecomp.dir import PathResolver
|
||||||
|
|
||||||
|
|
||||||
|
if os_name == "nt":
|
||||||
|
pytest.skip(reason="Skip Posix-only tests", allow_module_level=True)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(name="resolver")
|
||||||
|
def fixture_resolver_posix():
|
||||||
|
# Skip the call to winepath by using a patch, although this is not strictly necessary.
|
||||||
|
with patch("isledecomp.dir.winepath_unix_to_win", return_value="Z:\\usr\\isle"):
|
||||||
|
yield PathResolver("/usr/isle")
|
||||||
|
|
||||||
|
|
||||||
|
@patch("isledecomp.dir.winepath_win_to_unix")
|
||||||
|
def test_identity(winepath_mock, resolver):
|
||||||
|
"""Test with an absolute Wine path where a path swap is possible."""
|
||||||
|
# In this and upcoming tests, patch is_file so we always assume there is
|
||||||
|
# a file at the given unix path. We want to test the conversion logic only.
|
||||||
|
with patch("pathlib.Path.is_file", return_value=True):
|
||||||
|
assert resolver.resolve_cvdump("Z:\\usr\\isle\\test.h") == "/usr/isle/test.h"
|
||||||
|
winepath_mock.assert_not_called()
|
||||||
|
|
||||||
|
# Without the patch, this should call the winepath_mock, but we have
|
||||||
|
# memoized the value from the previous run.
|
||||||
|
assert resolver.resolve_cvdump("Z:\\usr\\isle\\test.h") == "/usr/isle/test.h"
|
||||||
|
winepath_mock.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
|
@patch("isledecomp.dir.winepath_win_to_unix")
|
||||||
|
def test_file_does_not_exist(winepath_mock, resolver):
|
||||||
|
"""These test files (probably) don't exist, so we always assume
|
||||||
|
the path swap failed and defer to winepath."""
|
||||||
|
resolver.resolve_cvdump("Z:\\usr\\isle\\test.h")
|
||||||
|
winepath_mock.assert_called_once_with("Z:\\usr\\isle\\test.h")
|
||||||
|
|
||||||
|
|
||||||
|
@patch("isledecomp.dir.winepath_win_to_unix")
|
||||||
|
def test_outside_basedir(winepath_mock, resolver):
|
||||||
|
"""Test an absolute path where we cannot do a path swap."""
|
||||||
|
with patch("pathlib.Path.is_file", return_value=True):
|
||||||
|
resolver.resolve_cvdump("Z:\\lego\\test.h")
|
||||||
|
winepath_mock.assert_called_once_with("Z:\\lego\\test.h")
|
||||||
|
|
||||||
|
|
||||||
|
@patch("isledecomp.dir.winepath_win_to_unix")
|
||||||
|
def test_relative(winepath_mock, resolver):
|
||||||
|
"""Test relative paths inside and outside of the base dir."""
|
||||||
|
with patch("pathlib.Path.is_file", return_value=True):
|
||||||
|
assert resolver.resolve_cvdump("./test.h") == "/usr/isle/test.h"
|
||||||
|
|
||||||
|
# This works because we will resolve "/usr/isle/test/../test.h"
|
||||||
|
assert resolver.resolve_cvdump("../test.h") == "/usr/test.h"
|
||||||
|
winepath_mock.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
|
@patch("isledecomp.dir.winepath_win_to_unix")
|
||||||
|
def test_intermediate_relative(winepath_mock, resolver):
|
||||||
|
"""We can resolve intermediate backdirs if they are relative to the basedir."""
|
||||||
|
with patch("pathlib.Path.is_file", return_value=True):
|
||||||
|
assert (
|
||||||
|
resolver.resolve_cvdump("Z:\\usr\\isle\\test\\..\\test.h")
|
||||||
|
== "/usr/isle/test.h"
|
||||||
|
)
|
||||||
|
assert resolver.resolve_cvdump(".\\subdir\\..\\test.h") == "/usr/isle/test.h"
|
||||||
|
winepath_mock.assert_not_called()
|
||||||
@ -16,7 +16,6 @@
|
|||||||
print_diff,
|
print_diff,
|
||||||
SymInfo,
|
SymInfo,
|
||||||
walk_source_dir,
|
walk_source_dir,
|
||||||
WinePathConverter,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
from capstone import Cs, CS_ARCH_X86, CS_MODE_32
|
from capstone import Cs, CS_ARCH_X86, CS_MODE_32
|
||||||
@ -295,13 +294,8 @@ def main():
|
|||||||
|
|
||||||
svg = args.svg
|
svg = args.svg
|
||||||
|
|
||||||
wine_path_converter = None
|
|
||||||
if os.name != "nt":
|
|
||||||
wine_path_converter = WinePathConverter(source)
|
|
||||||
with Bin(original, logger) as origfile, Bin(recomp, logger) as recompfile:
|
with Bin(original, logger) as origfile, Bin(recomp, logger) as recompfile:
|
||||||
syminfo = SymInfo(
|
syminfo = SymInfo(syms, recompfile, logger, source)
|
||||||
syms, recompfile, logger, sym_wine_path_converter=wine_path_converter
|
|
||||||
)
|
|
||||||
|
|
||||||
print()
|
print()
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user