Isle
Loading...
Searching...
No Matches
mxdiskstreamprovider.cpp
Go to the documentation of this file.
2
3#include "mxautolock.h"
5#include "mxdsbuffer.h"
6#include "mxdsfile.h"
8#include "mxomni.h"
10#include "mxstreamcontroller.h"
11#include "mxstring.h"
12#include "mxthread.h"
13
16
17// GLOBAL: LEGO1 0x10102878
19
20// FUNCTION: LEGO1 0x100d0f30
22{
23 if (m_target) {
24 ((MxDiskStreamProvider*) m_target)->WaitForWorkToComplete();
25 }
27 // They should probably have writen "return MxThread::Run()" but they didn't.
28 return SUCCESS;
29}
30
31// FUNCTION: LEGO1 0x100d0f50
33{
34 m_target = p_target;
35 return Start(0x1000, 0);
36}
37
38// FUNCTION: LEGO1 0x100d0f70
40{
41 m_pFile = NULL;
44}
45
46// FUNCTION: LEGO1 0x100d1240
48{
49 MxDSObject* action;
51
52 do {
53 action = NULL;
54
55 {
57 m_list.PopFront(action);
58 }
59
60 if (!action) {
61 break;
62 }
63
64 if (((MxDSStreamingAction*) action)->GetUnknowna0()->GetWriteOffset() < 0x20000) {
66 }
67
68 ((MxDiskStreamController*) m_pLookup)->FUN_100c8670((MxDSStreamingAction*) action);
69 } while (action);
70
71 if (m_remainingWork) {
75 }
76
77 if (m_pFile) {
78 delete m_pFile;
79 }
80
81 m_pFile = NULL;
82}
83
84// FUNCTION: LEGO1 0x100d13d0
86{
87 MxResult result = FAILURE;
88 MxString path;
89 m_pLookup = p_resource;
90
91 path = (MxString(MxOmni::GetHD()) + p_resource->GetAtom().GetInternal() + ".si");
92
93 m_pFile = new MxDSFile(path.GetData(), 0);
94 if (m_pFile != NULL) {
95 if (m_pFile->Open(OF_READ) != 0) {
96 path = MxString(MxOmni::GetCD()) + p_resource->GetAtom().GetInternal() + ".si";
98
99 if (m_pFile->Open(OF_READ) != 0) {
100 goto done;
101 }
102 }
103
105 m_busySemaphore.Init(0, 100);
106
107 if (m_thread.StartWithTarget(this) == SUCCESS && p_resource != NULL) {
108 result = SUCCESS;
109 }
110 }
111
112done:
113 return result;
114}
115
116// FUNCTION: LEGO1 0x100d15e0
118{
119 MxDSObject* action;
120
121 if (p_action->GetObjectId() == -1) {
123
124 do {
125 action = NULL;
126
127 {
129 m_list.PopFront(action);
130 }
131
132 if (!action) {
133 return;
134 }
135
136 if (((MxDSStreamingAction*) action)->GetUnknowna0()->GetWriteOffset() < 0x20000) {
138 }
139
140 ((MxDiskStreamController*) m_pLookup)->FUN_100c8670((MxDSStreamingAction*) action);
141 } while (action);
142 }
143 else {
144 do {
145 {
147 action = (MxDSStreamingAction*) m_list.FindAndErase(p_action);
148 }
149
150 if (!action) {
151 return;
152 }
153
154 if (((MxDSStreamingAction*) action)->GetUnknowna0()->GetWriteOffset() < 0x20000) {
156 }
157
158 ((MxDiskStreamController*) m_pLookup)->FUN_100c8670((MxDSStreamingAction*) action);
159 } while (action);
160 }
161}
162
163// FUNCTION: LEGO1 0x100d1750
165{
166 while (m_remainingWork) {
167 m_busySemaphore.Wait(INFINITE);
168 if (m_unk0x35) {
169 PerformWork();
170 }
171 }
172
173 return SUCCESS;
174}
175
176// FUNCTION: LEGO1 0x100d1780
178{
179 if (!m_remainingWork) {
180 return FAILURE;
181 }
182
183 if (p_action->GetUnknown9c() > 0 && !p_action->GetUnknowna0()) {
184 MxDSBuffer* buffer = new MxDSBuffer();
185
186 if (!buffer) {
187 return FAILURE;
188 }
189
191 delete buffer;
192 return FAILURE;
193 }
194
195 p_action->SetUnknowna0(buffer);
196 }
197
198 if (p_action->GetUnknowna0()->GetWriteOffset() < 0x20000) {
200 }
201
202 {
204 m_list.PushBack(p_action);
205 }
206
207 m_unk0x35 = TRUE;
209 return SUCCESS;
210}
211
212// FUNCTION: LEGO1 0x100d18f0
214{
216 MxDSObject* streamingAction = NULL;
217
218 {
220 if (!m_list.empty()) {
221 streamingAction = m_list.front();
222
223 if (streamingAction && !FUN_100d1af0((MxDSStreamingAction*) streamingAction)) {
224 m_thread.Sleep(500);
226 return;
227 }
228 }
229 }
230
231 MxDSBuffer* buffer;
232
233 {
235
236 if (!m_list.PopFront(streamingAction)) {
237 goto done;
238 }
239 }
240
241 if (((MxDSStreamingAction*) streamingAction)->GetUnknowna0()->GetWriteOffset() < 0x20000) {
243 }
244
245 buffer = ((MxDSStreamingAction*) streamingAction)->GetUnknowna0();
246
247 if (m_pFile->GetPosition() == ((MxDSStreamingAction*) streamingAction)->GetBufferOffset() ||
248 m_pFile->Seek(((MxDSStreamingAction*) streamingAction)->GetBufferOffset(), SEEK_SET) == 0) {
249 buffer->SetUnknown14(m_pFile->GetPosition());
250
251 if (m_pFile->ReadToBuffer(buffer) == SUCCESS) {
252 buffer->SetUnknown1c(m_pFile->GetPosition());
253
254 if (((MxDSStreamingAction*) streamingAction)->GetUnknown9c() > 0) {
255 FUN_100d1b20(((MxDSStreamingAction*) streamingAction));
256 }
257 else {
258 if (m_pLookup == NULL || !((MxDiskStreamController*) m_pLookup)->GetUnk0xc4()) {
259 controller->FUN_100c8670(((MxDSStreamingAction*) streamingAction));
260 }
261 else {
262 controller->FUN_100c7f40(((MxDSStreamingAction*) streamingAction));
263 }
264 }
265
266 streamingAction = NULL;
267 }
268 }
269
270done:
271 if (streamingAction) {
272 controller->FUN_100c8670(((MxDSStreamingAction*) streamingAction));
273 }
274
275 m_thread.Sleep(0);
276}
277
278// FUNCTION: LEGO1 0x100d1af0
280{
281 if (p_action->GetUnknowna0()->GetWriteOffset() == 0x20000) {
282 return g_unk0x10102878 == 0;
283 }
284
285 return TRUE;
286}
287
288// FUNCTION: LEGO1 0x100d1b20
289// FUNCTION: BETA10 0x10163712
291{
292 MxDSBuffer* buffer = new MxDSBuffer();
293
294 if (!buffer) {
295 return FAILURE;
296 }
297
298 MxU32 size = (p_action->GetUnknowna4() ? p_action->GetUnknowna4()->GetWriteOffset() : 0) +
299 p_action->GetUnknowna0()->GetWriteOffset() - (p_action->GetUnknown94() - p_action->GetBufferOffset());
300
301 if (buffer->AllocateBuffer(size, MxDSBuffer::e_allocate) != SUCCESS) {
302 delete buffer;
303 return FAILURE;
304 }
305
306 MxU8* data;
307
308 if (p_action->GetUnknowna4()) {
309 buffer->FUN_100c7090(p_action->GetUnknowna4());
310 data = buffer->GetBuffer() + p_action->GetUnknowna4()->GetWriteOffset();
311
312 memcpy(data, p_action->GetUnknowna0()->GetBuffer(), p_action->GetUnknowna0()->GetWriteOffset());
313
314 delete p_action->GetUnknowna4();
315 }
316 else {
317 data = buffer->GetBuffer();
318
319 memcpy(
320 data,
321 p_action->GetUnknowna0()->GetBuffer() + (p_action->GetUnknown94() - p_action->GetBufferOffset()),
322 size
323 );
324 }
325
326 p_action->SetUnknowna4(buffer);
327
328#define IntoType(p) ((MxU32*) (p))
329
330 while (data) {
331 if (*IntoType(data) != FOURCC('M', 'x', 'O', 'b') &&
332 *MxStreamChunk::IntoTime(data) > p_action->GetUnknown9c()) {
333 *IntoType(data) = FOURCC('p', 'a', 'd', ' ');
334
335 // DECOMP: prefer order that matches retail versus beta
336 *(MxU32*) (data + 4) = buffer->GetBuffer() + buffer->GetWriteOffset() - data - 8;
337 memset(data + 8, 0, *(MxU32*) (data + 4));
338 size = ReadData(buffer->GetBuffer(), buffer->GetWriteOffset());
339
340 buffer = new MxDSBuffer();
341 if (buffer == NULL || buffer->AllocateBuffer(size, MxDSBuffer::e_allocate) != SUCCESS) {
342 delete buffer;
343 return FAILURE;
344 }
345
346 memcpy(buffer->GetBuffer(), p_action->GetUnknowna4()->GetBuffer(), size);
348 delete p_action->GetUnknowna4();
349
351 p_action->SetUnknowna4(buffer);
352 MxU32 unk0x14 = p_action->GetUnknowna0()->GetUnknown14();
353
354 for (data = p_action->GetUnknowna0()->GetBuffer();
355 *MxStreamChunk::IntoTime(data) <= p_action->GetUnknown9c();
356 data = MxDSChunk::End(data)) {
357 unk0x14 += MxDSChunk::Size(data);
358 }
359
360 p_action->SetUnknown94(unk0x14);
361 p_action->SetBufferOffset(p_action->GetUnknowna0()->GetUnknown14());
362 delete p_action->GetUnknowna0();
363 p_action->ClearUnknowna0();
364 ((MxDiskStreamController*) m_pLookup)->FUN_100c7890(p_action);
365 return SUCCESS;
366 }
367
368 data = buffer->FUN_100c6fa0(data);
369 }
370
371 p_action->SetUnknown94(GetFileSize() + p_action->GetBufferOffset());
372 p_action->SetBufferOffset(GetFileSize() + p_action->GetBufferOffset());
373 FUN_100d1780(p_action);
374 return SUCCESS;
375
376#undef IntoType
377}
378
379// FUNCTION: LEGO1 0x100d1e90
381{
382 return m_pFile->GetBufferSize();
383}
384
385// FUNCTION: LEGO1 0x100d1ea0
387{
389}
390
391// FUNCTION: LEGO1 0x100d1eb0
393{
394 return m_pFile->GetLengthInDWords();
395}
396
397// FUNCTION: LEGO1 0x100d1ec0
399{
400 return m_pFile->GetBuffer();
401}
const char * GetInternal() const
[AI] Returns a pointer to the internal string, or nullptr if not set.
Definition: mxatom.h:194
[AI] Represents an action deserialized from SI chunks, holding key animation or script parameters suc...
Definition: mxdsaction.h:17
[AI] Buffer for managing streamed DS (Data Stream) chunks and actions.
Definition: mxdsbuffer.h:50
MxResult FUN_100c7090(MxDSBuffer *p_buf)
[AI] Copies buffer data and selected internal state from another buffer, if space allows.
Definition: mxdsbuffer.cpp:495
MxU8 * GetBuffer()
[AI] Returns a pointer to the managed chunk data buffer.
void SetUnknown1c(undefined4 p_unk0x1c)
[AI] Sets the unknown value at offset 0x1c.
undefined4 GetUnknown14()
[AI] Returns the internal value at offset 0x14.
void SetUnknown14(undefined4 p_unk0x14)
[AI] Sets the unknown value at offset 0x14.
MxU32 GetWriteOffset()
[AI] Returns the current buffer write offset (number of bytes with valid data).
void SetMode(Type p_mode)
[AI] Sets the buffer memory management mode.
MxU8 * FUN_100c6fa0(MxU8 *p_data)
[AI] Finds the next chunk boundary in the buffer, starting from an optional pointer.
Definition: mxdsbuffer.cpp:459
MxResult AllocateBuffer(MxU32 p_bufferSize, Type p_mode)
[AI] Allocates a buffer of a given size and memory mode.
Definition: mxdsbuffer.cpp:60
@ e_allocate
[AI] Newly allocated memory with new[].
Definition: mxdsbuffer.h:57
@ e_unknown
[AI] Unknown/other (may be unused or special).
Definition: mxdsbuffer.h:59
static MxU32 Size(MxU8 *p_buffer)
[AI] Returns the total size (header + data) of a chunk from a raw buffer pointer.
Definition: mxdschunk.h:68
static MxU8 * End(MxU8 *p_buffer)
[AI] Returns a pointer to the end of this chunk for sequential iteration through a chunked buffer.
Definition: mxdschunk.h:73
[AI] Represents a source file handler for SI (Streamer Interface) files, providing buffered access fo...
Definition: mxdsfile.h:20
void SetFileName(const char *p_filename)
[AI] Sets the SI file's name.
Definition: mxdsfile.h:102
MxResult Seek(MxLong, MxS32) override
[AI] Seeks to an absolute or relative position in the file.
Definition: mxdsfile.cpp:120
MxULong GetStreamBuffersNum() override
[AI] Returns the number of streaming buffers, as specified in the SI file header.
Definition: mxdsfile.cpp:139
MxResult Open(MxULong) override
[AI] Opens the SI file for reading or writing with the specified style flags.
Definition: mxdsfile.cpp:25
MxULong GetBufferSize() override
[AI] Returns the SI chunk's buffer size, as obtained from the SI file header.
Definition: mxdsfile.cpp:132
MxDSObject * FindAndErase(MxDSObject *p_action)
[AI] Finds the matching object and removes it from the list.
Definition: mxdsobject.h:23
[AI] Base class for any object deserialized from an SI (script/data) file in the LEGO Island engine.
Definition: mxdsobject.h:44
MxU32 GetObjectId()
[AI] Returns the object id numeric value.
Definition: mxdsobject.h:130
virtual MxU32 * GetBuffer()
[AI] Returns a pointer to the internal buffer as a DWORD (32-bit) pointer.
Definition: mxdssource.h:116
MxLong GetPosition() const
[AI] Returns the current per-source seek/read/write position.
Definition: mxdssource.h:122
virtual MxLong GetLengthInDWords()
[AI] Gets the length of the data in DWORDs (32-bit units).
Definition: mxdssource.h:109
virtual MxResult ReadToBuffer(MxDSBuffer *p_buffer)
[AI] Reads from this source into a provided MxDSBuffer up to the buffer's current write offset.
Definition: mxdssource.h:73
[AI] Represents an action that streams data from a buffer within a DirectScript (DS) media timeline.
void SetUnknowna0(MxDSBuffer *p_unk0xa0)
[AI] Assigns a streaming buffer to this action (ownership rules apply).
MxDSBuffer * GetUnknowna0()
[AI] Returns a pointer to the first streaming buffer (possibly current read buffer).
void SetUnknowna4(MxDSBuffer *p_unk0xa4)
[AI] Assigns a secondary streaming buffer to this action.
void SetBufferOffset(MxU32 p_bufferOffset)
[AI] Sets the current buffer read offset.
void ClearUnknowna0()
[AI] Clears/deallocates (sets to NULL) the current buffer pointer (a0).
MxS32 GetUnknown9c()
[AI] Retrieves an internal integer—purpose unknown—held at 0x9c.
void SetUnknown94(MxU32 p_unk0x94)
[AI] Sets the streaming offset/status at 0x94.
MxU32 GetUnknown94()
[AI] Gets the streaming offset or status value at 0x94.
MxU32 GetBufferOffset()
[AI] Gets the buffer offset where streaming is currently positioned.
MxDSBuffer * GetUnknowna4()
[AI] Returns a pointer to the second streaming buffer (possibly for prefetch or double buffering).
[AI] Controller for streaming from disk-based SI resources, manages buffers and streaming actions.
void FUN_100c7f40(MxDSStreamingAction *p_streamingaction)
[AI] Adds a streaming action to m_list0x64 for processing.
void FUN_100c8670(MxDSStreamingAction *p_streamingAction)
[AI] Pushes an action to a private list (m_list0xb8) for later cleanup.
[AI] Thread to handle disk-based streaming for MxDiskStreamProvider, running as a worker for disk str...
MxResult StartWithTarget(MxDiskStreamProvider *p_target)
[AI] Starts the thread with a specific MxDiskStreamProvider as its target.
MxDiskStreamProvider * m_target
[AI] Target provider instance for this worker thread.
[AI] Disk-based stream provider for resource loading using background streaming and multithreading.
MxResult FUN_100d1780(MxDSStreamingAction *p_action)
[AI] Schedules a streaming action to read data (SI chunk) from disk and buffers it asynchronously.
MxS32 GetStreamBuffersNum() override
[AI] Gets the number of stream buffers/splits for the file, used to drive parallel reads.
MxDSObjectList m_list
[AI] List of streaming actions to be processed/completed by the thread.
MxU32 GetFileSize() override
[AI] Gets the size, in bytes, of the open file/buffer to be streamed.
void PerformWork()
[AI] Performs a single unit of scheduled streaming work, i.e., loading data for queued actions.
void VTable0x20(MxDSAction *p_action) override
[AI] Cancels or reclaims outstanding streaming actions based on object ID, returning associated actio...
MxDiskStreamProviderThread m_thread
[AI] Thread object handling streaming actions asynchronously.
MxResult FUN_100d1b20(MxDSStreamingAction *p_action)
[AI] Finalizes merging of streaming buffers and updates streamed data for a given action.
MxResult SetResourceToGet(MxStreamController *p_resource) override
[AI] Opens and prepares a resource for streaming from disk based on the controller's atom (resource k...
static MxBool FUN_100d1af0(MxDSStreamingAction *p_action)
[AI] Returns whether a streaming action can be processed (buffer conditions met).
~MxDiskStreamProvider() override
[AI] Cleans up the disk stream provider, including terminating the worker thread and releasing file a...
MxU32 GetLengthInDWords() override
[AI] Returns file length as dword-count for bulk/integer-based streaming use cases.
MxResult WaitForWorkToComplete()
[AI] Blocks until all scheduled streaming work is finished (used by the streaming worker thread).
MxU32 * GetBufferForDWords() override
[AI] Returns a pointer to the buffer for raw dword access (SI file data block).
MxBool m_unk0x35
[AI] Internal flag signaling available work for the thread or shutdown in progress.
MxDiskStreamProvider()
[AI] Constructs a disk stream provider, initializing critical members and preparing for disk-based st...
MxSemaphore m_busySemaphore
[AI] Semaphore used to synchronize and signal work for the background thread.
MxBool m_remainingWork
[AI] Indicates whether more streaming work remains for the thread.
MxCriticalSection m_criticalSection
[AI] Synchronizes access to the work item queue (m_list).
static const char * GetCD()
[AI] Retrieves the configured CD-ROM media path string used for resource location.
Definition: mxomni.cpp:375
static const char * GetHD()
[AI] Retrieves the configured hard disk media path string used for resource location.
Definition: mxomni.cpp:363
virtual MxResult Init(MxU32 p_initialCount, MxU32 p_maxCount)
Initializes the semaphore with both initial and maximum counts.
Definition: mxsemaphore.cpp:15
void Release(MxU32 p_releaseCount)
Increases the semaphore count, unblocking waiting threads if any.
Definition: mxsemaphore.cpp:33
void Wait(MxU32 p_timeoutMS)
Waits on the semaphore for the specified timeout (in milliseconds).
Definition: mxsemaphore.cpp:27
static MxLong * IntoTime(MxU8 *p_buffer)
[AI] Utility to cast a chunk header buffer into the time field pointer, facilitating direct parsing.
[AI] Controller for streaming and managing multimedia resources and actions during gameplay.
MxAtomId & GetAtom()
[AI] Retrieves the atom ID (unique logical identifier) for this stream controller.
MxDSFile * m_pFile
[AI] Pointer to the loaded SI file associated with this provider. [AI]
MxStreamController * m_pLookup
[AI] The stream controller using this provider as its data source. [AI]
Mindscape custom string class for managing dynamic C-strings within the game engine.
Definition: mxstring.h:14
char * GetData() const
Returns a pointer to the internal character buffer.
Definition: mxstring.h:110
void Terminate()
[AI] Signals the thread to terminate.
Definition: mxthread.cpp:50
virtual MxResult Run()
[AI] Virtual function executed when the thread runs.
Definition: mxthread.cpp:63
MxResult Start(MxS32 p_stackSize, MxS32 p_flag)
[AI] Starts the thread with a given stack size and creation flags.
Definition: mxthread.cpp:28
void Sleep(MxS32 p_milliseconds)
[AI] Sleeps the current thread for the given duration in milliseconds.
Definition: mxthread.cpp:44
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
#define AUTOLOCK(CS)
[AI] Macro for automatic locking using the MxAutoLock class. This macro instantiates an MxAutoLock ob...
Definition: mxautolock.h:5
MxU32 g_unk0x10102878
#define IntoType(p)
MxU32 ReadData(MxU8 *p_fileSizeBuffer, MxU32 p_fileSize)
[AI] Rearranges split and unordered chunks within a memory buffer for SI resource files,...
MxU8 MxBool
[AI]
Definition: mxtypes.h:124
MxLong MxResult
[AI]
Definition: mxtypes.h:106
#define FOURCC(a, b, c, d)
[AI] Macro to compose a 32-bit code from four 8-bit characters (e.g., for resource and chunk IDs).
Definition: mxtypes.h:162
unsigned char MxU8
[AI]
Definition: mxtypes.h:8
signed int MxS32
[AI]
Definition: mxtypes.h:38
unsigned int MxU32
[AI]
Definition: mxtypes.h:32