Isle
Loading...
Searching...
No Matches
mxstreamcontroller.cpp
Go to the documentation of this file.
2
3#include "mxautolock.h"
4#include "mxdebug.h"
5#include "mxdsmultiaction.h"
7#include "mxmisc.h"
9#include "mxstl/stlcompat.h"
10#include "mxstreamchunk.h"
11#include "mxstreamprovider.h"
12#include "mxtimer.h"
13#include "mxutilities.h"
14
18
19// FUNCTION: LEGO1 0x100c0b90
21{
22 m_provider = NULL;
23 m_unk0x2c = NULL;
24 m_action0x60 = NULL;
25}
26
27// FUNCTION: LEGO1 0x100c1290
28// FUNCTION: BETA10 0x1014e354
30{
31 MxTrace("Destroy %s controller.\n", m_atom.GetInternal());
33
34 MxDSSubscriber* subscriber;
35 while (m_subscribers.PopFront(subscriber)) {
36 delete subscriber;
37 }
38
39 MxDSObject* action;
40 while (m_unk0x3c.PopFront(action)) {
41 delete action;
42 }
43
44 if (m_provider) {
45 MxStreamProvider* provider = m_provider;
47#ifdef COMPAT_MODE
48 {
49 MxDSAction action;
50 provider->VTable0x20(&action);
51 }
52#else
53 provider->VTable0x20(&MxDSAction());
54#endif
55 delete provider;
56 }
57
58 if (m_unk0x2c) {
59 delete m_unk0x2c;
61 }
62
63 while (m_unk0x54.PopFront(action)) {
64 delete action;
65 }
66}
67
68// FUNCTION: LEGO1 0x100c1520
69MxResult MxStreamController::Open(const char* p_filename)
70{
71 char sourceName[256];
73
74 MakeSourceName(sourceName, p_filename);
75 m_atom = MxAtomId(sourceName, e_lowerCase2);
76 return SUCCESS;
77}
78
79// FUNCTION: LEGO1 0x100c15d0
80// FUNCTION: BETA10 0x1014e730
82{
83 m_subscribers.PushBack(p_subscriber);
84}
85
86// FUNCTION: LEGO1 0x100c1620
87// FUNCTION: BETA10 0x1014e7b4
89{
90 m_subscribers.remove(p_subscriber);
91}
92
93// FUNCTION: LEGO1 0x100c1690
95{
97
98 MxResult result;
99 MxU32 offset = 0;
100
101 MxS32 objectId = p_action->GetObjectId();
102 MxStreamProvider* provider = m_provider;
103
104 if ((MxS32) provider->GetLengthInDWords() > objectId) {
105 offset = provider->GetBufferForDWords()[objectId];
106 }
107
108 if (offset) {
109 result = VTable0x2c(p_action, offset);
110 }
111 else {
112 result = FAILURE;
113 }
114
115 return result;
116}
117
118// FUNCTION: LEGO1 0x100c1740
119// FUNCTION: BETA10 0x1014e922
121{
123 VTable0x30(p_action);
125
126 if (m_action0x60 == NULL) {
127 return FAILURE;
128 }
129 else {
133 }
134}
135
136// FUNCTION: LEGO1 0x100c1800
137// FUNCTION: BETA10 0x1014ea36
139{
140 MxNextActionDataStart* dataActionStart =
141 new MxNextActionDataStart(p_action->GetObjectId(), p_action->GetUnknown24(), p_val);
142 if (dataActionStart == NULL) {
143 return FAILURE;
144 }
145
146 m_nextActionList.PushBack(dataActionStart);
147 return SUCCESS;
148}
149
150// FUNCTION: LEGO1 0x100c1a00
151// FUNCTION: BETA10 0x1014eb04
153{
154 if (p_action->GetUnknown24() == -1) {
155 MxS16 newUnknown24 = -1;
156
157 // These loops might be a template function in the list classes
158 for (MxDSObjectList::iterator it = m_unk0x54.begin(); it != m_unk0x54.end(); it++) {
159 MxDSObject* action = *it;
160
161 if (action->GetObjectId() == p_action->GetObjectId()) {
162 newUnknown24 = Max(newUnknown24, action->GetUnknown24());
163 }
164 }
165
166 if (newUnknown24 == -1) {
167 for (MxDSObjectList::iterator it = m_unk0x3c.begin(); it != m_unk0x3c.end(); it++) {
168 MxDSObject* action = *it;
169
170 if (action->GetObjectId() == p_action->GetObjectId()) {
171 newUnknown24 = Max(newUnknown24, action->GetUnknown24());
172 }
173 }
174
175 if (newUnknown24 == -1) {
176 for (MxDSSubscriberList::iterator it = m_subscribers.begin(); it != m_subscribers.end(); it++) {
177 MxDSSubscriber* subscriber = *it;
178
179 if (subscriber->GetObjectId() == p_action->GetObjectId()) {
180 newUnknown24 = Max(newUnknown24, subscriber->GetUnknown48());
181 }
182 }
183 }
184 }
185
186 p_action->SetUnknown24(newUnknown24 + 1);
187 }
188 else {
189 if (m_unk0x3c.Find(p_action)) {
190 return FAILURE;
191 }
192 }
193
194 MxDSStreamingAction* streamingAction = new MxDSStreamingAction(*p_action, p_offset);
195
196 if (!streamingAction) {
197 return FAILURE;
198 }
199
200 MxU32 fileSize = m_provider->GetFileSize();
201 streamingAction->SetBufferOffset(fileSize * (p_offset / fileSize));
202 streamingAction->SetObjectId(p_action->GetObjectId());
203
204 MxLong time = Timer()->GetTime();
205 streamingAction->SetUnknown90(time);
206
207 m_unk0x3c.PushBack(streamingAction);
208 return SUCCESS;
209}
210
211// FUNCTION: LEGO1 0x100c1c10
212// FUNCTION: BETA10 0x1014ed8c
214{
216
217 if (FUN_100c1a00(p_action, p_bufferval) != SUCCESS) {
218 return FAILURE;
219 }
220
221 return FUN_100c1800(p_action, (p_bufferval / m_provider->GetFileSize()) * m_provider->GetFileSize());
222}
223
224// FUNCTION: LEGO1 0x100c1ce0
225// FUNCTION: BETA10 0x1014eeb5
227{
229 MxResult result = FAILURE;
230 MxDSObject* action = m_unk0x3c.FindAndErase(p_action);
231
232 if (action != NULL) {
234 delete action;
235 delete data;
236 result = SUCCESS;
237 }
238
239 return result;
240}
241
242// FUNCTION: LEGO1 0x100c1da0
243// FUNCTION: BETA10 0x1014efdc
245{
247 MxDSAction* action = p_action->Clone();
248
249 if (action == NULL) {
250 return FAILURE;
251 }
252 else {
253 m_unk0x54.PushBack(action);
254 return SUCCESS;
255 }
256}
257
258// FUNCTION: LEGO1 0x100c1e70
259// FUNCTION: BETA10 0x1014f0a1
261{
263 MxPresenter* result = NULL;
264
265 if (p_action.GetObjectId() != -1) {
266 MxDSObject* action = m_unk0x3c.Find(&p_action);
267 if (action != NULL) {
268 result = action->GetUnknown28();
269 }
270 }
271
272 return result;
273}
274
275// FUNCTION: LEGO1 0x100c1f00
276// FUNCTION: BETA10 0x1014f162
278{
280
281 MxU32 objectId = p_action->GetObjectId();
282 MxStreamChunk* chunk = new MxStreamChunk;
283
284 if (!chunk) {
285 return FAILURE;
286 }
287
289 chunk->SetObjectId(objectId);
290
291 if (chunk->SendChunk(m_subscribers, FALSE, p_action->GetUnknown24()) != SUCCESS) {
292 delete chunk;
293 }
294
295 if (p_action->IsA("MxDSMultiAction")) {
296 MxDSActionList* actions = ((MxDSMultiAction*) p_action)->GetActionList();
297 MxDSActionListCursor cursor(actions);
298 MxDSAction* action;
299
300 while (cursor.Next(action)) {
301 if (FUN_100c1f00(action) != SUCCESS) {
302 return FAILURE;
303 }
304 }
305 }
306
307 return SUCCESS;
308}
309
310// FUNCTION: LEGO1 0x100c20b0
311// FUNCTION: BETA10 0x1014f37d
313{
314 return m_nextActionList.Find(p_action->GetObjectId(), p_action->GetUnknown24());
315}
316
317// FUNCTION: LEGO1 0x100c20d0
318// FUNCTION: BETA10 0x1014f3b5
320{
321 MxDSSubscriber* subscriber = m_subscribers.Find(p_obj);
322
323 if (subscriber) {
324 MxTrace(
325 "Subscriber for action (stream %d, instance %d) from %s is still here.\n",
326 subscriber->GetObjectId(),
327 subscriber->GetUnknown48(),
328 GetAtom().GetInternal()
329 );
330 return FALSE;
331 }
332
333 if (p_obj->IsA("MxDSMultiAction")) {
334 MxDSActionListCursor cursor(((MxDSMultiAction*) p_obj)->GetActionList());
335 MxDSAction* action;
336
337 while (cursor.Next(action)) {
338 if (!IsStoped(action)) {
339 return FALSE;
340 }
341 }
342 }
343
344 return TRUE;
345}
346
347// FUNCTION: LEGO1 0x100c21e0
348// FUNCTION: BETA10 0x1014f4e6
350{
351 for (iterator it = begin(); it != end(); it++) {
352 if (p_id == (*it)->GetObjectId() && p_value == (*it)->GetUnknown24()) {
353 return *it;
354 }
355 }
356
357 return NULL;
358}
359
360// FUNCTION: LEGO1 0x100c2240
361// FUNCTION: BETA10 0x1014f58c
363{
365
366 for (iterator it = begin(); it != end(); it++) {
367 if (p_id == (*it)->GetObjectId() && (p_value == -2 || p_value == (*it)->GetUnknown24())) {
368 match = *it;
369 erase(it);
370 break;
371 }
372 }
373
374 return match;
375}
[AI] Atomized (unique) string identifier, managed by reference counting.
Definition: mxatom.h:124
const char * GetInternal() const
[AI] Returns a pointer to the internal string, or nullptr if not set.
Definition: mxatom.h:194
[AI] Convenience cursor class for iterating over an MxDSActionList.
[AI] A list (collection) of pointers to MxDSAction objects, supporting comparison,...
[AI] Represents an action deserialized from SI chunks, holding key animation or script parameters suc...
Definition: mxdsaction.h:17
virtual void SetUnknown90(MxLong p_unk0x90)
[AI] Set unknown value at offset 0x90, used as baseline in GetElapsedTime.
Definition: mxdsaction.cpp:60
MxBool IsA(const char *p_name) const override
[AI] Run-time type check, compares provided name with this or any ancestor type.
Definition: mxdsaction.h:80
virtual MxDSAction * Clone()
[AI] Clones (deep-copies) this action and returns a new pointer.
Definition: mxdsaction.cpp:146
void SetChunkFlags(MxU16 p_flags)
[AI] Sets all chunk header flag bits.
Definition: mxdschunk.h:77
void SetObjectId(undefined4 p_objectid)
[AI] Sets the object id for this chunk (links chunk data to logical entity, resource,...
Definition: mxdschunk.h:81
[AI] Represents a container for multiple MxDSAction objects, facilitating the grouping and management...
MxDSObject * FindAndErase(MxDSObject *p_action)
[AI] Finds the matching object and removes it from the list.
Definition: mxdsobject.h:23
MxDSObject * Find(MxDSObject *p_action)
[AI] Finds a matching object in the list without removing it.
Definition: mxdsobject.h:28
[AI] Base class for any object deserialized from an SI (script/data) file in the LEGO Island engine.
Definition: mxdsobject.h:44
MxBool IsA(const char *p_name) const override
[AI] Runtime type check; supports derived/parent class lookup by name.
Definition: mxdsobject.h:97
void SetUnknown24(MxS16 p_unk0x24)
[AI] Sets the unknown field at 0x24 (possibly version/state).
Definition: mxdsobject.h:151
MxPresenter * GetUnknown28()
[AI] Returns the pointer stored at 0x28, likely a presenter or handler for this DS object.
Definition: mxdsobject.h:139
MxS16 GetUnknown24()
[AI] Returns the unknown 0x24 value (may be data version or usage state). [AI]
Definition: mxdsobject.h:136
void SetObjectId(MxU32 p_objectId)
[AI] Sets the object id (for serialization or lookup).
Definition: mxdsobject.h:147
MxU32 GetObjectId()
[AI] Returns the object id numeric value.
Definition: mxdsobject.h:130
[AI] Represents an action that streams data from a buffer within a DirectScript (DS) media timeline.
void SetBufferOffset(MxU32 p_bufferOffset)
[AI] Sets the current buffer read offset.
MxDSSubscriber * Find(MxDSObject *p_object)
[AI] Searches for a subscriber corresponding to the provided MxDSObject.
[AI] Handles the receipt, queuing, and batch management of data chunks streamed by a MxStreamControll...
MxS16 GetUnknown48()
[AI] Returns the member field sometimes used for disambiguating media (purpose context-specific).
MxU32 GetObjectId()
[AI] Returns the object identifier associated with this subscriber.
MxBool Next()
[AI]
[AI] List class specialized for storing MxNextActionDataStart pointers, managing streaming action sta...
MxNextActionDataStart * FindAndErase(MxU32 p_id, MxS16 p_value)
[AI] Searches for a MxNextActionDataStart with the given properties and erases it from the list if fo...
MxNextActionDataStart * Find(MxU32 p_id, MxS16 p_value)
[AI] Searches for a MxNextActionDataStart element with the given object ID and unknown value.
[AI] Contains data for scheduling the next action in a process, storing an object id,...
[AI] Abstract base class for all presenter types in the LEGO Island engine, responsible for managing ...
Definition: mxpresenter.h:20
[AI] Represents a streamable chunk of data, typically sourced from a media buffer and designed for no...
Definition: mxstreamchunk.h:19
MxResult SendChunk(MxDSSubscriberList &p_subscriberList, MxBool p_append, MxS16 p_obj24val)
[AI] Dispatches this stream chunk to a list of subscribers matching certain criteria.
[AI] Controller for streaming and managing multimedia resources and actions during gameplay.
virtual MxResult VTable0x24(MxDSAction *p_action)
[AI] Matches and processes an action in the "unk0x54" (pending) list and triggers sending to subscrib...
MxDSSubscriberList m_subscribers
[AI] List of current subscribers (listening entities for streamed data).
undefined4 * m_unk0x2c
[AI] Unknown data, likely used for streaming internals or as a metadata pointer.
~MxStreamController() override
[AI] Destructor.
MxResult FUN_100c1a00(MxDSAction *p_action, MxU32 p_offset)
[AI] Allocates and inserts a streaming action chunk at a given buffer offset for the supplied action.
void RemoveSubscriber(MxDSSubscriber *p_subscriber)
[AI] Removes a previously registered subscriber from the stream notification list.
MxCriticalSection m_criticalSection
[AI] Protects streaming controller state for thread-safety.
virtual MxResult VTable0x20(MxDSAction *p_action)
[AI] Streams data for the provided action by determining data offset and reading required chunk.
MxAtomId m_atom
[AI] Unique identifier for this stream, derived from source/resource name.
MxBool IsStoped(MxDSObject *p_obj)
[AI] Checks if the streaming operation for a given object/action has fully stopped and no longer has ...
MxResult FUN_100c1f00(MxDSAction *p_action)
[AI] Sends a streaming chunk to all current subscribers for the specified action, handling recursive ...
MxNextActionDataStartList m_nextActionList
[AI] List mapping from streamed object/action to starting offset (used for internal tracking).
MxDSObjectList m_unk0x3c
[AI] List of actions currently being processed/streamed ("in progress" actions).
MxDSAction * m_action0x60
[AI] Current action pointer used during processing, moved from pending to active as actions are proce...
virtual MxResult Open(const char *p_filename)
[AI] Opens a data stream with the specified resource filename.
void AddSubscriber(MxDSSubscriber *p_subscriber)
[AI] Adds a subscriber to the list who will receive streaming action data.
MxStreamProvider * m_provider
[AI] Stream provider abstraction, handling resource IO (RAM/disk).
MxDSObjectList m_unk0x54
[AI] List of actions queued and ready to be streamed ("pending" actions).
MxPresenter * FUN_100c1e70(MxDSAction &p_action)
[AI] Returns the presenter associated with a given in-progress streaming action.
MxNextActionDataStart * FindNextActionDataStartFromStreamingAction(MxDSStreamingAction *p_action)
[AI] Finds the corresponding next action data start (offset info) for a streaming action.
MxResult FUN_100c1800(MxDSAction *p_action, MxU32 p_val)
[AI] Helper function to add a next action data start object for tracking offsets for streaming action...
MxAtomId & GetAtom()
[AI] Retrieves the atom ID (unique logical identifier) for this stream controller.
virtual MxResult VTable0x30(MxDSAction *p_action)
[AI] Removes a completed action from in-progress ("unk0x3c") list and deletes its data block.
virtual MxResult VTable0x2c(MxDSAction *p_action, MxU32 p_bufferval)
[AI] Handles allocation and setup of a new streaming action and associated chunk for the action,...
MxResult InsertActionToList54(MxDSAction *p_action)
[AI] Inserts a clone of the provided action into the pending ("unk0x54") list.
[AI] Abstract base class for stream resource providers in the LEGO Island engine.
virtual MxU32 GetFileSize()=0
[AI] Gets the file size, in bytes, of the underlying SI file resource.
virtual void VTable0x20(MxDSAction *p_action)
[AI] Virtual hook for subclasses to react to new stream actions being queued.
virtual MxU32 GetLengthInDWords()=0
[AI] Gets the full buffer length, interpreted as a DWORD-count, for direct buffer streaming.
virtual MxU32 * GetBufferForDWords()=0
[AI] Returns a pointer to the underlying buffer, cast as an array of DWORDs, for streaming purposes.
MxLong GetTime()
Returns the current timer value in ms, depending on running state.
Definition: mxtimer.h:50
void PushBack(T p_obj)
[AI] Pushes a copy of the provided object to the back of the list.
Definition: mxutilitylist.h:38
MxBool PopFront(T &p_obj)
[AI] Removes and returns the first element of the list.
Definition: mxutilitylist.h:22
#define TRUE
Definition: d3drmdef.h:28
#define FALSE
Definition: d3drmdef.h:27
#define DECOMP_SIZE_ASSERT(T, S)
Definition: decomp.h:19
#define NULL
[AI] Null pointer value (C/C++ semantics).
Definition: legotypes.h:26
#define FAILURE
[AI] Used to indicate a failed operation in result codes.
Definition: legotypes.h:34
#define SUCCESS
[AI] Used to indicate a successful operation in result codes.
Definition: legotypes.h:30
T Max(T p_t1, T p_t2)
[AI] Returns the maximum of two values.
Definition: legoutil.h:39
@ e_lowerCase2
[AI] Alternative or legacy lower case mode, functionally equivalent to e_lowerCase.
Definition: mxatom.h:109
#define AUTOLOCK(CS)
[AI] Macro for automatic locking using the MxAutoLock class. This macro instantiates an MxAutoLock ob...
Definition: mxautolock.h:5
#define MxTrace(args)
[AI] Macro for trace logging (non-variadic version, MSVC compatibility), expands to nothing.
Definition: mxdebug.h:55
#define DS_CHUNK_BIT3
[AI] Unknown bit flag, marked as BIT3 in decompilation.
Definition: mxdschunk.h:18
MxTimer * Timer()
[AI] Returns the global simulation timer.
Definition: mxmisc.cpp:33
MxU8 MxBool
[AI]
Definition: mxtypes.h:124
MxLong MxResult
[AI]
Definition: mxtypes.h:106
int MxLong
[AI]
Definition: mxtypes.h:83
signed short MxS16
[AI]
Definition: mxtypes.h:26
signed int MxS32
[AI]
Definition: mxtypes.h:38
unsigned int MxU32
[AI]
Definition: mxtypes.h:32
void MakeSourceName(char *, const char *)
Parses an SI source filename and normalizes it for use in the engine.
Definition: mxutilities.cpp:66
[AI] STL compatibility layer header to provide consistent STL (Standard Template Library) types and a...