mirror of
https://github.com/isledecomp/isle-portable.git
synced 2026-01-10 02:01:16 +00:00
Add hdmusic.si asset pack, extend SiLoader with Replace directive (#671)
* Replace SI objects * Changes * Fix * Remove obsolete file * Add delete handler * Updates * Update assets * Configure git LFS * Add HD music * Move files to LFS * chmod files * fix gitattributes * Fixes * Fixes * Add other HD music * Fix file perms * Add comment * Minor update * Refactor * Fix * Add LFS flag * Add check for file replace * Exclude assets from CPack * Attempt fix * Update libweaver * Fix MxDSBuffer leak * Add .lfsconfig * Set LFS URL * Fix LFS CI * Fix * Space
This commit is contained in:
parent
73c6be7abf
commit
d10ac7e77c
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -9,3 +9,5 @@
|
||||
**/*.png binary
|
||||
**/*.svg text eol=lf
|
||||
**/*.desktop text eol=lf
|
||||
assets/widescreen/** filter=lfs diff=lfs merge=lfs -text
|
||||
assets/hdmusic/** filter=lfs diff=lfs merge=lfs -text
|
||||
|
||||
5
.github/workflows/ci.yml
vendored
5
.github/workflows/ci.yml
vendored
@ -113,6 +113,11 @@ jobs:
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Checkout LFS
|
||||
if: ${{ matrix.build-assets }}
|
||||
run: |
|
||||
git lfs pull
|
||||
|
||||
- name: Setup Java (Android)
|
||||
if: ${{ matrix.android }}
|
||||
uses: actions/setup-java@v4
|
||||
|
||||
2
.lfsconfig
Normal file
2
.lfsconfig
Normal file
@ -0,0 +1,2 @@
|
||||
[lfs]
|
||||
url = https://f9622702b3bbcac0705052a10e62a5a5:31adabe20fe975a919bd1909a6f598f37b0d6486225efa84b38da1aaf27cbd35@assets.isle.pizza/a70a70ae5ebee06d2333bb1132711de1.r2.cloudflarestorage.com/assets
|
||||
4
3rdparty/CMakeLists.txt
vendored
4
3rdparty/CMakeLists.txt
vendored
@ -78,8 +78,8 @@ if(DOWNLOAD_DEPENDENCIES)
|
||||
include(FetchContent)
|
||||
FetchContent_Populate(
|
||||
libweaver
|
||||
URL https://github.com/isledecomp/SIEdit/archive/6da93b2072c41c41d526b8b9df7d4292be1f0f55.tar.gz
|
||||
URL_MD5 ae59007fcb9efadc06c67621e1e107cb
|
||||
URL https://github.com/isledecomp/SIEdit/archive/ae447259389f3bf8273c7e7a4844743faf7cbdb8.tar.gz
|
||||
URL_MD5 dee68424fde8db6d5cef3b9034a8151f
|
||||
)
|
||||
else()
|
||||
set(libweaver_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/libweaver")
|
||||
|
||||
2
3rdparty/libweaver
vendored
2
3rdparty/libweaver
vendored
@ -1 +1 @@
|
||||
Subproject commit 6da93b2072c41c41d526b8b9df7d4292be1f0f55
|
||||
Subproject commit ae447259389f3bf8273c7e7a4844743faf7cbdb8
|
||||
@ -691,10 +691,6 @@ if(ISLE_BUILD_ASSETS)
|
||||
add_custom_target(build_assets ALL
|
||||
DEPENDS ${GENERATED_ASSETS_DIR}/.stamp
|
||||
)
|
||||
|
||||
install(DIRECTORY ${GENERATED_ASSETS_DIR}/
|
||||
DESTINATION assets
|
||||
)
|
||||
endif()
|
||||
|
||||
if (ISLE_MINIWIN)
|
||||
|
||||
@ -119,7 +119,12 @@ void MxBackgroundAudioManager::FadeInPendingPresenter()
|
||||
MxS32 compare, volume;
|
||||
|
||||
if (m_activePresenter == NULL) {
|
||||
if (m_pendingPresenter) {
|
||||
if (m_pendingPresenter && m_pendingPresenter->GetCurrentTickleState() >= MxPresenter::e_streaming) {
|
||||
if (!m_pendingPresenter->IsEnabled()) {
|
||||
m_pendingPresenter->Enable(TRUE);
|
||||
m_pendingPresenter->SetTickleState(MxPresenter::e_streaming);
|
||||
}
|
||||
|
||||
if (m_volumeSuppressionAmount != 0) {
|
||||
compare = 30;
|
||||
}
|
||||
@ -221,6 +226,12 @@ void MxBackgroundAudioManager::StartAction(MxParam& p_param)
|
||||
m_action2.SetObjectId(m_pendingPresenter->GetAction()->GetObjectId());
|
||||
m_targetVolume = ((MxDSSound*) (m_pendingPresenter->GetAction()))->GetVolume();
|
||||
m_pendingPresenter->SetVolume(0);
|
||||
|
||||
// Disabling the action here and starting it later once the actively presented music has been faded out.
|
||||
// This was not necessary in retail because the streaming layer would implicitly not start another action
|
||||
// before the previous one has ended (since it's all coming from JUKEBOX.SI), however since we now
|
||||
// allow loading music from multiple SI files this would cause the new music to start immediately.
|
||||
m_pendingPresenter->GetAction()->SetFlags(m_pendingPresenter->GetAction()->GetFlags() & ~MxDSAction::c_enabled);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1007f200
|
||||
@ -254,7 +265,8 @@ MxResult MxBackgroundAudioManager::PlayMusic(
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
if (m_action2.GetObjectId() == -1 && m_action1.GetObjectId() != p_action.GetObjectId()) {
|
||||
if (m_action2.GetObjectId() == -1 &&
|
||||
(m_action1.GetObjectId() != p_action.GetObjectId() || m_action1.GetAtomId() != p_action.GetAtomId())) {
|
||||
MxDSAction action;
|
||||
action.SetAtomId(GetCurrentAction().GetAtomId());
|
||||
action.SetObjectId(GetCurrentAction().GetObjectId());
|
||||
|
||||
@ -503,6 +503,12 @@ MxBool RemoveFromCurrentWorld(const MxAtomId& p_atomId, MxS32 p_id)
|
||||
{
|
||||
LegoWorld* world = CurrentWorld();
|
||||
|
||||
auto result =
|
||||
Extension<SiLoader>::Call(HandleRemove, SiLoader::StreamObject{p_atomId, p_id}, world).value_or(std::nullopt);
|
||||
if (result) {
|
||||
return result.value();
|
||||
}
|
||||
|
||||
if (world) {
|
||||
MxCore* object = world->Find(p_atomId, p_id);
|
||||
|
||||
@ -518,8 +524,6 @@ MxBool RemoveFromCurrentWorld(const MxAtomId& p_atomId, MxS32 p_id)
|
||||
}
|
||||
|
||||
((MxPresenter*) object)->EndAction();
|
||||
|
||||
Extension<SiLoader>::Call(RemoveWith, SiLoader::StreamObject{p_atomId, p_id}, world);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
@ -539,6 +543,12 @@ MxBool RemoveFromWorld(
|
||||
{
|
||||
LegoWorld* world = FindWorld(p_worldAtom, p_worldEntityId);
|
||||
|
||||
auto result = Extension<SiLoader>::Call(HandleRemove, SiLoader::StreamObject{p_entityAtom, p_entityId}, world)
|
||||
.value_or(std::nullopt);
|
||||
if (result) {
|
||||
return result.value();
|
||||
}
|
||||
|
||||
if (world) {
|
||||
MxCore* object = world->Find(p_entityAtom, p_entityId);
|
||||
|
||||
@ -554,8 +564,6 @@ MxBool RemoveFromWorld(
|
||||
}
|
||||
|
||||
((MxPresenter*) object)->EndAction();
|
||||
|
||||
Extension<SiLoader>::Call(RemoveWith, SiLoader::StreamObject{p_entityAtom, p_entityId}, world);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#include "legoworld.h"
|
||||
|
||||
#include "anim/legoanim.h"
|
||||
#include "extensions/siloader.h"
|
||||
#include "legoanimationmanager.h"
|
||||
#include "legoanimpresenter.h"
|
||||
#include "legobuildingmanager.h"
|
||||
@ -32,6 +33,8 @@ DECOMP_SIZE_ASSERT(LegoEntityListCursor, 0x10)
|
||||
DECOMP_SIZE_ASSERT(LegoCacheSoundList, 0x18)
|
||||
DECOMP_SIZE_ASSERT(LegoCacheSoundListCursor, 0x10)
|
||||
|
||||
using namespace Extensions;
|
||||
|
||||
// FUNCTION: LEGO1 0x1001ca40
|
||||
LegoWorld::LegoWorld() : m_pathControllerList(TRUE)
|
||||
{
|
||||
@ -636,6 +639,12 @@ MxCore* LegoWorld::Find(const char* p_class, const char* p_name)
|
||||
// FUNCTION: BETA10 0x100db3de
|
||||
MxCore* LegoWorld::Find(const MxAtomId& p_atom, MxS32 p_entityId)
|
||||
{
|
||||
auto result =
|
||||
Extension<SiLoader>::Call(HandleFind, SiLoader::StreamObject{p_atom, p_entityId}, this).value_or(std::nullopt);
|
||||
if (result) {
|
||||
return result.value();
|
||||
}
|
||||
|
||||
LegoEntityListCursor entityCursor(m_entityList);
|
||||
LegoEntity* entity;
|
||||
|
||||
|
||||
@ -474,6 +474,11 @@ LegoWorld* LegoOmni::FindWorld(const MxAtomId& p_atom, MxS32 p_entityid)
|
||||
// STUB: BETA10 0x1008e93e
|
||||
void LegoOmni::DeleteObject(MxDSAction& p_dsAction)
|
||||
{
|
||||
auto result = Extension<SiLoader>::Call(HandleDelete, p_dsAction).value_or(std::nullopt);
|
||||
if (result && result.value()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (p_dsAction.GetAtomId().GetInternal() != NULL) {
|
||||
LegoWorld* world = FindWorld(p_dsAction.GetAtomId(), p_dsAction.GetObjectId());
|
||||
if (world) {
|
||||
@ -663,6 +668,13 @@ void LegoOmni::CreateBackgroundAudio()
|
||||
// FUNCTION: BETA10 0x1008f7e0
|
||||
MxResult LegoOmni::Start(MxDSAction* p_dsAction)
|
||||
{
|
||||
{
|
||||
auto result = Extension<SiLoader>::Call(HandleStart, *p_dsAction).value_or(std::nullopt);
|
||||
if (result) {
|
||||
return result.value();
|
||||
}
|
||||
}
|
||||
|
||||
MxResult result = MxOmni::Start(p_dsAction);
|
||||
#ifdef BETA10
|
||||
this->m_action = *p_dsAction;
|
||||
@ -673,14 +685,6 @@ MxResult LegoOmni::Start(MxDSAction* p_dsAction)
|
||||
this->m_action.SetObjectId(p_dsAction->GetObjectId());
|
||||
this->m_action.SetUnknown24(p_dsAction->GetUnknown24());
|
||||
#endif
|
||||
|
||||
if (result == SUCCESS) {
|
||||
Extension<SiLoader>::Call(
|
||||
StartWith,
|
||||
SiLoader::StreamObject{p_dsAction->GetAtomId(), p_dsAction->GetObjectId()}
|
||||
);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@ -91,6 +91,12 @@ class MxDSBuffer : public MxCore {
|
||||
|
||||
void SetUnk30(MxDSStreamingAction* p_unk0x30) { m_unk0x30 = p_unk0x30; }
|
||||
|
||||
void SetSourceBuffer(MxDSBuffer* p_sourceBuffer)
|
||||
{
|
||||
m_sourceBuffer = p_sourceBuffer;
|
||||
m_sourceBuffer->AddRef(NULL);
|
||||
}
|
||||
|
||||
// SYNTHETIC: LEGO1 0x100c6510
|
||||
// SYNTHETIC: BETA10 0x10158530
|
||||
// MxDSBuffer::`scalar deleting destructor'
|
||||
@ -107,6 +113,7 @@ class MxDSBuffer : public MxCore {
|
||||
MxU32 m_writeOffset; // 0x28
|
||||
MxU32 m_bytesRemaining; // 0x2c
|
||||
MxDSStreamingAction* m_unk0x30; // 0x30
|
||||
MxDSBuffer* m_sourceBuffer;
|
||||
};
|
||||
|
||||
#endif // MXDSBUFFER_H
|
||||
|
||||
@ -28,6 +28,7 @@ MxDSBuffer::MxDSBuffer()
|
||||
m_bytesRemaining = 0;
|
||||
m_mode = e_preallocated;
|
||||
m_unk0x30 = 0;
|
||||
m_sourceBuffer = NULL;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c6530
|
||||
@ -36,6 +37,10 @@ MxDSBuffer::~MxDSBuffer()
|
||||
{
|
||||
assert(m_referenceCount == 0);
|
||||
|
||||
if (m_sourceBuffer) {
|
||||
m_sourceBuffer->ReleaseRef(NULL);
|
||||
}
|
||||
|
||||
if (m_pBuffer != NULL) {
|
||||
switch (m_mode) {
|
||||
case e_allocate:
|
||||
@ -267,6 +272,28 @@ MxResult MxDSBuffer::ParseChunk(
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
// START FIX: Ref-Counting Backpressure for Split Chunks
|
||||
//
|
||||
// PROBLEM: When a `DS_CHUNK_SPLIT` is found, the temporary `MxStreamChunk`
|
||||
// header that holds a reference to the source buffer is immediately
|
||||
// destroyed. This prematurely releases the reference, causing the source
|
||||
// buffer's ref-count to drop to zero.
|
||||
//
|
||||
// EFFECT: The source buffer is freed immediately instead of being kept
|
||||
// alive on the m_list0x74 "keep-alive" list. This breaks the natural
|
||||
// ref-counting backpressure mechanism, as the controller is blind to the
|
||||
// downstream workload and keeps reading new data from the stream at full
|
||||
// speed, eventually leading to a memory leak.
|
||||
//
|
||||
// SOLUTION: We explicitly link the new reassembly buffer to the original
|
||||
// source buffer. We then add an artificial reference to the source buffer.
|
||||
// This reference is designed to be released by the reassembly buffer's
|
||||
// destructor, ensuring the source buffer is kept alive for the correct
|
||||
// duration and that the backpressure system functions as intended.
|
||||
if (p_header->GetBuffer()) {
|
||||
buffer->SetSourceBuffer(p_header->GetBuffer());
|
||||
}
|
||||
|
||||
MxU16* flags = MxStreamChunk::IntoFlags(buffer->GetBuffer());
|
||||
*flags = p_header->GetChunkFlags() & ~DS_CHUNK_SPLIT;
|
||||
|
||||
@ -409,9 +436,7 @@ MxU8 MxDSBuffer::ReleaseRef(MxDSChunk*)
|
||||
// FUNCTION: LEGO1 0x100c6ee0
|
||||
void MxDSBuffer::AddRef(MxDSChunk* p_chunk)
|
||||
{
|
||||
if (p_chunk) {
|
||||
m_referenceCount++;
|
||||
}
|
||||
m_referenceCount++;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c6ef0
|
||||
|
||||
3
assets/hdmusic/Act3Music_HD.wav
Normal file
3
assets/hdmusic/Act3Music_HD.wav
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7c3e3080ea1af626bc202d091ead654ef38ac8e27779c2908dca390f3106ced3
|
||||
size 14201934
|
||||
3
assets/hdmusic/BeachBlvd_Music_HD.wav
Normal file
3
assets/hdmusic/BeachBlvd_Music_HD.wav
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1143a85549ca76ec8edccc164e8c54d803d7eb9a5bddd5c0387ce102b5397f2c
|
||||
size 26919040
|
||||
3
assets/hdmusic/Beach_Music_HD.wav
Normal file
3
assets/hdmusic/Beach_Music_HD.wav
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9e84733243a6d1d3044aab8032cf5d2b5769b1e3e3f0787c3b3bf18689c9f535
|
||||
size 22490016
|
||||
3
assets/hdmusic/BrickHunt_HD.wav
Normal file
3
assets/hdmusic/BrickHunt_HD.wav
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:cfbd44517186635ad270a971e9328f65890b94258c456aafda6658830147dce2
|
||||
size 33980544
|
||||
3
assets/hdmusic/BrickstrChase_HD.wav
Normal file
3
assets/hdmusic/BrickstrChase_HD.wav
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a158faeb0b651da3c0663cfa871851ad226dae02577be97d049bc4f84e4d9251
|
||||
size 14614784
|
||||
3
assets/hdmusic/Cave_Music_HD.wav
Normal file
3
assets/hdmusic/Cave_Music_HD.wav
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6ae808110329a64ae06a96b08210bea8938f92ac0006b850a62b941541339359
|
||||
size 12214400
|
||||
3
assets/hdmusic/CentralRoads_Music_HD.wav
Normal file
3
assets/hdmusic/CentralRoads_Music_HD.wav
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:39bd028528e1c9e2c9cea0b090c3c54f78b1889135a863c09080b90d3b13b3d2
|
||||
size 34113102
|
||||
3
assets/hdmusic/Hospital_Music_HD.wav
Normal file
3
assets/hdmusic/Hospital_Music_HD.wav
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f253c05dcf77d5b7d5109f2e95ac5af85ee7a699a8689d8c276951617bbfd0e6
|
||||
size 40701386
|
||||
3
assets/hdmusic/InfoCenter_3rd_Floor_Music_HD.wav
Normal file
3
assets/hdmusic/InfoCenter_3rd_Floor_Music_HD.wav
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:de7bf7bc1512aa6430b35e94c952c9b815b13ceded533f458ff9806a3915f948
|
||||
size 20201550
|
||||
3
assets/hdmusic/InformationCenter_Music_HD.wav
Normal file
3
assets/hdmusic/InformationCenter_Music_HD.wav
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8c1ade0044cef699f526898cd44c34f426f3f057312f8d457ebc4b454096bdb0
|
||||
size 27256398
|
||||
3
assets/hdmusic/JBMusic1_HD.wav
Normal file
3
assets/hdmusic/JBMusic1_HD.wav
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5c11ed75397b677a069cd9302bec3e1178067b030c42a47ef6853cb9212ff716
|
||||
size 22200448
|
||||
3
assets/hdmusic/JBMusic2_HD.wav
Normal file
3
assets/hdmusic/JBMusic2_HD.wav
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8964ca0fb9698abab90398bfa62f04e52830b647af8b4014a129edd9fbfdae47
|
||||
size 28735604
|
||||
3
assets/hdmusic/JBMusic3_HD.wav
Normal file
3
assets/hdmusic/JBMusic3_HD.wav
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:98b02da1c3900a9e906b88692ecb2087f2091b4af7303565eaeff242cdf7c313
|
||||
size 21653144
|
||||
3
assets/hdmusic/JBMusic4_HD.wav
Normal file
3
assets/hdmusic/JBMusic4_HD.wav
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:13c787e61647e22a1f4535d2491cbad5638c835142c075ebe6a39964ff769466
|
||||
size 24699000
|
||||
3
assets/hdmusic/JBMusic5_HD.wav
Normal file
3
assets/hdmusic/JBMusic5_HD.wav
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:3b744d204a6bcb3c659f490fc9caa6a2bff96e6c91ab7ba8770508b208f0fffd
|
||||
size 12828932
|
||||
3
assets/hdmusic/JBMusic6_HD.wav
Normal file
3
assets/hdmusic/JBMusic6_HD.wav
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8779860718e07a6093c979d77ec1723dcef93762bc7759e960e70ee730b66fb3
|
||||
size 10059690
|
||||
3
assets/hdmusic/Jail_Music_HD.wav
Normal file
3
assets/hdmusic/Jail_Music_HD.wav
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b39644468a172178738aa8854b514580f2b098a810dba127b2f5ae25534fe87e
|
||||
size 12140672
|
||||
3
assets/hdmusic/JetskiRace_Music_HD.wav
Normal file
3
assets/hdmusic/JetskiRace_Music_HD.wav
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:82ccad0d9877ccf915fc050d9b245785cf6bcb2406a6fcb9f6bdb9a75a3fc8c4
|
||||
size 11367404
|
||||
3
assets/hdmusic/Park_Music_HD.wav
Normal file
3
assets/hdmusic/Park_Music_HD.wav
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6b645676140604d078be9cb1dc7d5f0ee17700878ff50a5280b426616898be64
|
||||
size 16089216
|
||||
3
assets/hdmusic/PoliceStation_Music_HD.wav
Normal file
3
assets/hdmusic/PoliceStation_Music_HD.wav
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:59c5ad73804bf813a852a5486e6ab13739a16542d06c736c28c164694ed424fd
|
||||
size 10070544
|
||||
3
assets/hdmusic/RaceTrackRoad_Music_HD.wav
Normal file
3
assets/hdmusic/RaceTrackRoad_Music_HD.wav
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:002c09354642fd8757ea999d62badf0b346f5ab1d4fb6b6ce31e471b0a6bdb1a
|
||||
size 33341560
|
||||
3
assets/hdmusic/ResidentalArea_Music_HD.wav
Normal file
3
assets/hdmusic/ResidentalArea_Music_HD.wav
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f24f80d0979e1794d42000b55e95f0674be196af94c30abfa2a8d971e106a309
|
||||
size 15794304
|
||||
191
assets/main.cpp
191
assets/main.cpp
@ -16,30 +16,182 @@ si::MemoryBuffer mxHd;
|
||||
|
||||
void CreateWidescreen()
|
||||
{
|
||||
std::string result = out + "/widescreen.si";
|
||||
struct AssetView {
|
||||
std::string name;
|
||||
std::string extra;
|
||||
};
|
||||
const AssetView widescreenBitmaps[] = {
|
||||
{"GaraDoor_Background_Wide",
|
||||
"World:current, StartWith:\\Lego\\Scripts\\Isle\\Isle;1160, RemoveWith:\\Lego\\Scripts\\Isle\\Isle;1161"}
|
||||
};
|
||||
|
||||
si::Interleaf si;
|
||||
std::string file = out + "/widescreen.si";
|
||||
mxHd.seek(0, si::MemoryBuffer::SeekStart);
|
||||
si.Read(&mxHd);
|
||||
|
||||
si::Object GaraDoor_Wide;
|
||||
const char extra[] =
|
||||
"World:current, StartWith:\\Lego\\Scripts\\Isle\\Isle;1160, RemoveWith:\\Lego\\Scripts\\Isle\\Isle;1161";
|
||||
GaraDoor_Wide.type_ = si::MxOb::Bitmap;
|
||||
GaraDoor_Wide.flags_ = MxDSAction::c_enabled | MxDSAction::c_bit4;
|
||||
GaraDoor_Wide.duration_ = -1;
|
||||
GaraDoor_Wide.loops_ = 1;
|
||||
GaraDoor_Wide.extra_ = si::bytearray(extra, sizeof(extra));
|
||||
GaraDoor_Wide.presenter_ = "MxStillPresenter";
|
||||
GaraDoor_Wide.name_ = "GaraDoor_Wide";
|
||||
GaraDoor_Wide.filetype_ = si::MxOb::STL;
|
||||
GaraDoor_Wide.location_.x = -240.0;
|
||||
GaraDoor_Wide.location_.z = -1.0;
|
||||
GaraDoor_Wide.up_.y = 1.0;
|
||||
GaraDoor_Wide.ReplaceWithFile("widescreen/garadoor.bmp");
|
||||
si.AppendChild(&GaraDoor_Wide);
|
||||
depfile << file << ": " << (std::filesystem::current_path() / "widescreen/garadoor.bmp").string() << std::endl;
|
||||
int i = 0;
|
||||
for (const AssetView& asset : widescreenBitmaps) {
|
||||
si::Object* object = new si::Object;
|
||||
std::string file = std::string("widescreen/") + asset.name + ".bmp";
|
||||
|
||||
si.Write(file.c_str());
|
||||
object->id_ = i;
|
||||
object->type_ = si::MxOb::Bitmap;
|
||||
object->flags_ = MxDSAction::c_enabled | MxDSAction::c_bit4;
|
||||
object->duration_ = -1;
|
||||
object->loops_ = 1;
|
||||
object->extra_ = si::bytearray(asset.extra.c_str(), asset.extra.length() + 1);
|
||||
object->presenter_ = "MxStillPresenter";
|
||||
object->name_ = asset.name;
|
||||
object->filetype_ = si::MxOb::STL;
|
||||
object->location_ = si::Vector3(-240.0, 0.0, -1.0);
|
||||
object->direction_ = si::Vector3(0, 0, 0);
|
||||
object->up_ = si::Vector3(0, 1.0, 0);
|
||||
|
||||
if (!object->ReplaceWithFile(file.c_str())) {
|
||||
abort();
|
||||
}
|
||||
|
||||
si.AppendChild(object);
|
||||
depfile << result << ": " << (std::filesystem::current_path() / file).string() << std::endl;
|
||||
i++;
|
||||
}
|
||||
|
||||
si.Write(result.c_str());
|
||||
}
|
||||
|
||||
void CreateHDMusic()
|
||||
{
|
||||
std::string result = out + "/hdmusic.si";
|
||||
struct AssetView {
|
||||
std::string name;
|
||||
std::string extra;
|
||||
uint32_t duration;
|
||||
uint32_t loops;
|
||||
uint32_t flags;
|
||||
};
|
||||
const AssetView wavAudio[] = {
|
||||
{"BrickstrChase_HD",
|
||||
"Replace:\\Lego\\Scripts\\Isle\\Jukebox;3",
|
||||
82850,
|
||||
10000,
|
||||
MxDSAction::c_enabled | MxDSAction::c_bit3},
|
||||
{"BrickHunt_HD",
|
||||
"Replace:\\Lego\\Scripts\\Isle\\Jukebox;4",
|
||||
192630,
|
||||
10000,
|
||||
MxDSAction::c_enabled | MxDSAction::c_bit3},
|
||||
{"ResidentalArea_Music_HD",
|
||||
"Replace:\\Lego\\Scripts\\Isle\\Jukebox;5",
|
||||
89540,
|
||||
10000,
|
||||
MxDSAction::c_enabled | MxDSAction::c_bit3},
|
||||
{"BeachBlvd_Music_HD",
|
||||
"Replace:\\Lego\\Scripts\\Isle\\Jukebox;6",
|
||||
152600,
|
||||
10000,
|
||||
MxDSAction::c_enabled | MxDSAction::c_bit3},
|
||||
{"Cave_Music_HD",
|
||||
"Replace:\\Lego\\Scripts\\Isle\\Jukebox;7",
|
||||
69240,
|
||||
10000,
|
||||
MxDSAction::c_enabled | MxDSAction::c_bit3},
|
||||
{"CentralRoads_Music_HD",
|
||||
"Replace:\\Lego\\Scripts\\Isle\\Jukebox;8",
|
||||
193380,
|
||||
10000,
|
||||
MxDSAction::c_enabled | MxDSAction::c_bit3},
|
||||
{"Jail_Music_HD",
|
||||
"Replace:\\Lego\\Scripts\\Isle\\Jukebox;9",
|
||||
68820,
|
||||
10000,
|
||||
MxDSAction::c_enabled | MxDSAction::c_bit3},
|
||||
{"Hospital_Music_HD",
|
||||
"Replace:\\Lego\\Scripts\\Isle\\Jukebox;10",
|
||||
211990,
|
||||
10000,
|
||||
MxDSAction::c_enabled | MxDSAction::c_bit3},
|
||||
{"InformationCenter_Music_HD",
|
||||
"Replace:\\Lego\\Scripts\\Isle\\Jukebox;11",
|
||||
154510,
|
||||
10000,
|
||||
MxDSAction::c_enabled | MxDSAction::c_bit3},
|
||||
{"PoliceStation_Music_HD",
|
||||
"Replace:\\Lego\\Scripts\\Isle\\Jukebox;12",
|
||||
57090,
|
||||
10000,
|
||||
MxDSAction::c_enabled | MxDSAction::c_bit3},
|
||||
{"Park_Music_HD",
|
||||
"Replace:\\Lego\\Scripts\\Isle\\Jukebox;13",
|
||||
91210,
|
||||
10000,
|
||||
MxDSAction::c_enabled | MxDSAction::c_bit3},
|
||||
{"RaceTrackRoad_Music_HD",
|
||||
"Replace:\\Lego\\Scripts\\Isle\\Jukebox;16",
|
||||
189000,
|
||||
10000,
|
||||
MxDSAction::c_enabled | MxDSAction::c_bit3},
|
||||
{"Beach_Music_HD",
|
||||
"Replace:\\Lego\\Scripts\\Isle\\Jukebox;17",
|
||||
127490,
|
||||
10000,
|
||||
MxDSAction::c_enabled | MxDSAction::c_bit3},
|
||||
{"JetskiRace_Music_HD",
|
||||
"Replace:\\Lego\\Scripts\\Isle\\Jukebox;19",
|
||||
64440,
|
||||
10000,
|
||||
MxDSAction::c_enabled | MxDSAction::c_bit3},
|
||||
{"Act3Music_HD",
|
||||
"Replace:\\Lego\\Scripts\\Isle\\Jukebox;20",
|
||||
80510,
|
||||
10000,
|
||||
MxDSAction::c_enabled | MxDSAction::c_bit3},
|
||||
{"JBMusic1_HD", "Replace:\\Lego\\Scripts\\Isle\\Jukebox;55", 125850, 1, MxDSAction::c_enabled},
|
||||
{"JBMusic2_HD", "Replace:\\Lego\\Scripts\\Isle\\Jukebox;56", 162900, 1, MxDSAction::c_enabled},
|
||||
{"JBMusic3_HD", "Replace:\\Lego\\Scripts\\Isle\\Jukebox;57", 122750, 1, MxDSAction::c_enabled},
|
||||
{"JBMusic4_HD", "Replace:\\Lego\\Scripts\\Isle\\Jukebox;58", 140000, 1, MxDSAction::c_enabled},
|
||||
{"JBMusic5_HD", "Replace:\\Lego\\Scripts\\Isle\\Jukebox;59", 72720, 1, MxDSAction::c_enabled},
|
||||
{"JBMusic6_HD", "Replace:\\Lego\\Scripts\\Isle\\Jukebox;60", 57030, 1, MxDSAction::c_enabled},
|
||||
{"InfoCenter_3rd_Floor_Music_HD",
|
||||
"Replace:\\Lego\\Scripts\\Isle\\Jukebox;61",
|
||||
114520,
|
||||
10000,
|
||||
MxDSAction::c_enabled | MxDSAction::c_bit3}
|
||||
};
|
||||
|
||||
si::Interleaf si;
|
||||
mxHd.seek(0, si::MemoryBuffer::SeekStart);
|
||||
si.Read(&mxHd);
|
||||
|
||||
int i = 0;
|
||||
for (const AssetView& asset : wavAudio) {
|
||||
si::Object* object = new si::Object;
|
||||
std::string file = std::string("hdmusic/") + asset.name + ".wav";
|
||||
|
||||
object->id_ = i;
|
||||
object->type_ = si::MxOb::Sound;
|
||||
object->flags_ = asset.flags;
|
||||
object->duration_ = asset.duration * asset.loops;
|
||||
object->loops_ = asset.loops;
|
||||
object->extra_ = si::bytearray(asset.extra.c_str(), asset.extra.length() + 1);
|
||||
object->presenter_ = "MxWavePresenter";
|
||||
object->name_ = asset.name;
|
||||
object->filetype_ = si::MxOb::WAV;
|
||||
object->location_ = si::Vector3(0, 0, 0);
|
||||
object->direction_ = si::Vector3(0, 0, 1);
|
||||
object->up_ = si::Vector3(0, 1, 0);
|
||||
object->volume_ = 79;
|
||||
|
||||
if (!object->ReplaceWithFile(file.c_str())) {
|
||||
abort();
|
||||
}
|
||||
|
||||
si.AppendChild(object);
|
||||
depfile << result << ": " << (std::filesystem::current_path() / file).string() << std::endl;
|
||||
i++;
|
||||
}
|
||||
|
||||
si.Write(result.c_str());
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
@ -54,5 +206,6 @@ int main(int argc, char* argv[])
|
||||
mxHd.WriteU32(bufferCount);
|
||||
|
||||
CreateWidescreen();
|
||||
CreateHDMusic();
|
||||
return 0;
|
||||
}
|
||||
|
||||
3
assets/widescreen/GaraDoor_Background_Wide.bmp
Normal file
3
assets/widescreen/GaraDoor_Background_Wide.bmp
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:3d245fde39c95f788a9406f2c4bbc94680d566cef925f03883a0824e3485c23d
|
||||
size 538678
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 526 KiB |
@ -7,6 +7,11 @@
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace si
|
||||
{
|
||||
class Core;
|
||||
}
|
||||
|
||||
namespace Extensions
|
||||
{
|
||||
class SiLoader {
|
||||
@ -15,8 +20,10 @@ class SiLoader {
|
||||
|
||||
static void Initialize();
|
||||
static bool Load();
|
||||
static bool StartWith(StreamObject p_object);
|
||||
static bool RemoveWith(StreamObject p_object, LegoWorld* world);
|
||||
static std::optional<MxCore*> HandleFind(StreamObject p_object, LegoWorld* world);
|
||||
static std::optional<MxResult> HandleStart(MxDSAction& p_action);
|
||||
static std::optional<MxBool> HandleRemove(StreamObject p_object, LegoWorld* world);
|
||||
static std::optional<MxBool> HandleDelete(MxDSAction& p_action);
|
||||
|
||||
static std::map<std::string, std::string> options;
|
||||
static std::vector<std::string> files;
|
||||
@ -25,17 +32,23 @@ class SiLoader {
|
||||
private:
|
||||
static std::vector<std::pair<StreamObject, StreamObject>> startWith;
|
||||
static std::vector<std::pair<StreamObject, StreamObject>> removeWith;
|
||||
static std::vector<std::pair<StreamObject, StreamObject>> replace;
|
||||
|
||||
static bool LoadFile(const char* p_file);
|
||||
static void ParseDirectives(const MxAtomId& p_atom, si::Core* p_core, MxAtomId p_parentReplacedAtom = MxAtomId());
|
||||
};
|
||||
|
||||
#ifdef EXTENSIONS
|
||||
constexpr auto Load = &SiLoader::Load;
|
||||
constexpr auto StartWith = &SiLoader::StartWith;
|
||||
constexpr auto RemoveWith = &SiLoader::RemoveWith;
|
||||
constexpr auto HandleFind = &SiLoader::HandleFind;
|
||||
constexpr auto HandleStart = &SiLoader::HandleStart;
|
||||
constexpr auto HandleRemove = &SiLoader::HandleRemove;
|
||||
constexpr auto HandleDelete = &SiLoader::HandleDelete;
|
||||
#else
|
||||
constexpr decltype(&SiLoader::Load) Load = nullptr;
|
||||
constexpr decltype(&SiLoader::StartWith) StartWith = nullptr;
|
||||
constexpr decltype(&SiLoader::RemoveWith) RemoveWith = nullptr;
|
||||
constexpr decltype(&SiLoader::HandleFind) HandleFind = nullptr;
|
||||
constexpr decltype(&SiLoader::HandleStart) HandleStart = nullptr;
|
||||
constexpr decltype(&SiLoader::HandleRemove) HandleRemove = nullptr;
|
||||
constexpr decltype(&SiLoader::HandleDelete) HandleDelete = nullptr;
|
||||
#endif
|
||||
}; // namespace Extensions
|
||||
|
||||
@ -13,6 +13,7 @@ std::map<std::string, std::string> SiLoader::options;
|
||||
std::vector<std::string> SiLoader::files;
|
||||
std::vector<std::pair<SiLoader::StreamObject, SiLoader::StreamObject>> SiLoader::startWith;
|
||||
std::vector<std::pair<SiLoader::StreamObject, SiLoader::StreamObject>> SiLoader::removeWith;
|
||||
std::vector<std::pair<SiLoader::StreamObject, SiLoader::StreamObject>> SiLoader::replace;
|
||||
bool SiLoader::enabled = false;
|
||||
|
||||
void SiLoader::Initialize()
|
||||
@ -36,21 +37,52 @@ bool SiLoader::Load()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SiLoader::StartWith(StreamObject p_object)
|
||||
std::optional<MxCore*> SiLoader::HandleFind(StreamObject p_object, LegoWorld* world)
|
||||
{
|
||||
for (const auto& key : startWith) {
|
||||
for (const auto& key : replace) {
|
||||
if (key.first == p_object) {
|
||||
return world->Find(key.second.first, key.second.second);
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<MxResult> SiLoader::HandleStart(MxDSAction& p_action)
|
||||
{
|
||||
StreamObject object{p_action.GetAtomId(), p_action.GetObjectId()};
|
||||
|
||||
for (const auto& key : startWith) {
|
||||
if (key.first == object) {
|
||||
MxDSAction action;
|
||||
action.SetAtomId(key.second.first);
|
||||
action.SetObjectId(key.second.second);
|
||||
action.SetUnknown24(p_action.GetUnknown24());
|
||||
action.SetNotificationObject(p_action.GetNotificationObject());
|
||||
action.SetOrigin(p_action.GetOrigin());
|
||||
Start(&action);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
for (const auto& key : replace) {
|
||||
if (key.first == object) {
|
||||
MxDSAction action;
|
||||
action.SetAtomId(key.second.first);
|
||||
action.SetObjectId(key.second.second);
|
||||
action.SetUnknown24(p_action.GetUnknown24());
|
||||
action.SetNotificationObject(p_action.GetNotificationObject());
|
||||
action.SetOrigin(p_action.GetOrigin());
|
||||
|
||||
MxResult result = Start(&action);
|
||||
p_action.SetUnknown24(action.GetUnknown24());
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
bool SiLoader::RemoveWith(StreamObject p_object, LegoWorld* world)
|
||||
std::optional<MxBool> SiLoader::HandleRemove(StreamObject p_object, LegoWorld* world)
|
||||
{
|
||||
for (const auto& key : removeWith) {
|
||||
if (key.first == p_object) {
|
||||
@ -58,7 +90,47 @@ bool SiLoader::RemoveWith(StreamObject p_object, LegoWorld* world)
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
for (const auto& key : replace) {
|
||||
if (key.first == p_object) {
|
||||
return RemoveFromWorld(key.second.first, key.second.second, world->GetAtomId(), world->GetEntityId());
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<MxBool> SiLoader::HandleDelete(MxDSAction& p_action)
|
||||
{
|
||||
StreamObject object{p_action.GetAtomId(), p_action.GetObjectId()};
|
||||
|
||||
for (const auto& key : removeWith) {
|
||||
if (key.first == object) {
|
||||
MxDSAction action;
|
||||
action.SetAtomId(key.second.first);
|
||||
action.SetObjectId(key.second.second);
|
||||
action.SetUnknown24(p_action.GetUnknown24());
|
||||
action.SetNotificationObject(p_action.GetNotificationObject());
|
||||
action.SetOrigin(p_action.GetOrigin());
|
||||
DeleteObject(action);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& key : replace) {
|
||||
if (key.first == object) {
|
||||
MxDSAction action;
|
||||
action.SetAtomId(key.second.first);
|
||||
action.SetObjectId(key.second.second);
|
||||
action.SetUnknown24(p_action.GetUnknown24());
|
||||
action.SetNotificationObject(p_action.GetNotificationObject());
|
||||
action.SetOrigin(p_action.GetOrigin());
|
||||
|
||||
DeleteObject(action);
|
||||
p_action.SetUnknown24(action.GetUnknown24());
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
bool SiLoader::LoadFile(const char* p_file)
|
||||
@ -68,10 +140,11 @@ bool SiLoader::LoadFile(const char* p_file)
|
||||
|
||||
MxString path = MxString(MxOmni::GetHD()) + p_file;
|
||||
path.MapPathToFilesystem();
|
||||
if (si.Read(path.GetData()) != si::Interleaf::ERROR_SUCCESS) {
|
||||
if (si.Read(path.GetData(), si::Interleaf::ObjectsOnly | si::Interleaf::NoInfo) != si::Interleaf::ERROR_SUCCESS) {
|
||||
path = MxString(MxOmni::GetCD()) + p_file;
|
||||
path.MapPathToFilesystem();
|
||||
if (si.Read(path.GetData()) != si::Interleaf::ERROR_SUCCESS) {
|
||||
if (si.Read(path.GetData(), si::Interleaf::ObjectsOnly | si::Interleaf::NoInfo) !=
|
||||
si::Interleaf::ERROR_SUCCESS) {
|
||||
SDL_Log("Could not parse SI file %s", p_file);
|
||||
return false;
|
||||
}
|
||||
@ -82,7 +155,15 @@ bool SiLoader::LoadFile(const char* p_file)
|
||||
return false;
|
||||
}
|
||||
|
||||
for (si::Core* child : si.GetChildren()) {
|
||||
ParseDirectives(controller->GetAtom(), &si);
|
||||
return true;
|
||||
}
|
||||
|
||||
void SiLoader::ParseDirectives(const MxAtomId& p_atom, si::Core* p_core, MxAtomId p_parentReplacedAtom)
|
||||
{
|
||||
for (si::Core* child : p_core->GetChildren()) {
|
||||
MxAtomId replacedAtom = p_parentReplacedAtom;
|
||||
|
||||
if (si::Object* object = dynamic_cast<si::Object*>(child)) {
|
||||
if (object->type() != si::MxOb::Null) {
|
||||
std::string extra(object->extra_.data(), object->extra_.size());
|
||||
@ -94,7 +175,7 @@ bool SiLoader::LoadFile(const char* p_file)
|
||||
if (SDL_sscanf(directive, "StartWith:%255[^;];%d", atom, &id) == 2) {
|
||||
startWith.emplace_back(
|
||||
StreamObject{MxAtomId{atom, e_lowerCase2}, id},
|
||||
StreamObject{controller->GetAtom(), object->id_}
|
||||
StreamObject{p_atom, object->id_}
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -103,13 +184,31 @@ bool SiLoader::LoadFile(const char* p_file)
|
||||
if (SDL_sscanf(directive, "RemoveWith:%255[^;];%d", atom, &id) == 2) {
|
||||
removeWith.emplace_back(
|
||||
StreamObject{MxAtomId{atom, e_lowerCase2}, id},
|
||||
StreamObject{controller->GetAtom(), object->id_}
|
||||
StreamObject{p_atom, object->id_}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (p_parentReplacedAtom.GetInternal()) {
|
||||
replace.emplace_back(
|
||||
StreamObject{p_parentReplacedAtom, object->id_},
|
||||
StreamObject{p_atom, object->id_}
|
||||
);
|
||||
}
|
||||
else {
|
||||
if ((directive = SDL_strstr(extra.c_str(), "Replace:"))) {
|
||||
if (SDL_sscanf(directive, "Replace:%255[^;];%d", atom, &id) == 2) {
|
||||
replace.emplace_back(
|
||||
StreamObject{MxAtomId{atom, e_lowerCase2}, id},
|
||||
StreamObject{p_atom, object->id_}
|
||||
);
|
||||
replacedAtom = replace.back().first.first;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
ParseDirectives(p_atom, child, replacedAtom);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user