Wing Commander
Reconstructed Win32 source (1996)
Loading...
Searching...
No Matches
thread.cpp
Go to the documentation of this file.
1/**
2 * @file
3 * @ingroup ixlib
4 * @brief The streamer's worker thread.
5 *
6 * Originally `D:\Rnd\Prj\ix\Src\Streamer\thread.cpp`, address range
7 * 443b10-4446ff. INT3 fill separates it from the streamer API and the
8 * stream-file methods; its assert paths anchor the interior.
9 */
10#include "ix.h"
11#include <stdlib.h>
12#include <string.h>
13#include <process.h>
14#include <crtdbg.h>
15#include <fcntl.h>
16
17#pragma function(memcpy)
18
19#define IX_THREAD_FILE "D:\\Rnd\\Prj\\ix\\Src\\Streamer\\thread.cpp"
20
21/* Function start: 0x00443B10 */
22DWORD WINAPI ix_streamer_thread_proc(void *parameter)
23{
24 DWORD timeout;
25
26 timeout = 0;
27 EnterCriticalSection(&csIxStreamerThread);
31 EnterCriticalSection(&csStreamer);
37 ix_dsps_stop(0);
40 }
45 }
49 timeout = ix_streamer_service_audio();
54 ix_dsps_stop(0);
57 }
58 } else {
61 ix_dsps_play(0);
64 }
65 }
66 } else {
67 timeout = ix_thread_service_streams();
70 ix_dsps_stop(0);
74 }
75 }
76 LeaveCriticalSection(&csStreamer);
77 WaitForSingleObject(hStreamerWakeupEvent, timeout);
78 ResetEvent(hStreamerWakeupEvent);
79 } else {
81 ix_dsps_stop(0);
84 }
85 LeaveCriticalSection(&csStreamer);
86 WaitForSingleObject(hStreamerWakeupEvent, INFINITE);
87 ResetEvent(hStreamerWakeupEvent);
88 }
89 }
91 LeaveCriticalSection(&csIxStreamerThread);
92 (void)parameter;
93 return 0;
94}
95
96/* Function start: 0x00443CC0 */
97unsigned int ix_streamer_service_audio(void)
98{
99 unsigned int bytesUntilStop;
100
102 bytesUntilStop = pStreamerPackageInfo->audioBufferSize -
104 Sleep((bytesUntilStop * 1000U) /
106 dwIxStreamerStatus &= 0xfffff7db;
107 ix_dsps_stop(0);
108 } else if ((dwIxStreamerStatus &
113 (unsigned int)ix_dsps_get_buffer_free(0))
115 ix_dsps_play(0);
116 } else {
118 (unsigned int)ix_dsps_get_buffer_free(0))
120 }
122}
123
124/* Function start: 0x00443DA6 */ /* source line(s) 196: File chunk without packet! */
126{
127 unsigned int packagePosition;
128 unsigned int chunkIndex;
129 IxStreamerFileChunk *fileChunk;
130 unsigned int chunksToScan;
131 unsigned int chunkBytes;
132 unsigned int innerOffset;
133 IxStreamerFileEntry *packageRecord;
134 unsigned int copyBytes;
135 unsigned char *readPointer;
136 unsigned int pivot;
137 unsigned int firstPacket;
138 unsigned int endPacket;
139 unsigned int *packet;
140
141 packageRecord = streamFile->entry;
142 streamFile->serviceTick = dwStreamThreadTick;
143 if ((dwIxStreamerStatus & 0x100) != 0) {
144 ix_file_seek(streamFile->file, streamFile->position);
145 ix_file_read(streamFile->file, streamFile->destination,
146 streamFile->remaining);
147 EnterCriticalSection(&csStreamerFileList);
148 streamFile->flags &= ~IX_STREAM_FILE_READING;
149 if (streamFile->previous != 0)
150 streamFile->previous->next = streamFile->next;
151 if (streamFile->next == 0)
152 pStreamReadRequests = streamFile->previous;
153 else
154 streamFile->next->previous = streamFile->previous;
155 streamFile->previous = pStreamIdleFiles;
156 streamFile->next = 0;
157 if (pStreamIdleFiles != 0)
158 pStreamIdleFiles->next = streamFile;
159 pStreamIdleFiles = streamFile;
160 LeaveCriticalSection(&csStreamerFileList);
161 SetEvent(streamFile->completionEvent);
162 return;
163 }
164
165 chunkIndex = packageRecord->firstChunk;
166 chunksToScan = packageRecord->chunkCount;
167 fileChunk = &pStreamFileBlocks[chunkIndex];
168 packagePosition = (unsigned int)ix_file_tell(
170 while (chunksToScan--) {
171 if (fileChunk->fileOffset <= streamFile->position &&
172 fileChunk->fileEnd > streamFile->position) {
173 chunkBytes = fileChunk->fileEnd - fileChunk->fileOffset;
174 if (chunkIndex != nIxStreamerCurrentFileChunk) {
175 firstPacket = fileChunk->firstPacket;
176 endPacket = fileChunk->packetCount + firstPacket;
177 packet = 0;
178 nIxStreamerCurrentFileChunk = chunkIndex;
179 while (endPacket > firstPacket) {
180 pivot = (endPacket + firstPacket) >> 1;
181 packet = &pStreamerPacketOffsetTable[pivot];
182 if (*packet < packagePosition)
183 firstPacket = pivot + 1;
184 else if (*packet > packagePosition)
185 endPacket = pivot;
186 else
187 break;
188 }
189 if (packet == 0) {
190 ix_log_printf("Fatal [%s - %d]:\n", IX_THREAD_FILE, 196);
191 ix_log_printf("File chunk without packet!");
192 exit(-1);
193 }
194 if (fileChunk->packedSize < 0) {
198 -fileChunk->packedSize);
201 chunkBytes);
202 } else {
206 fileChunk->packedSize);
207 }
208 }
209 readPointer = pIxStreamerInputBuffer;
210 copyBytes = streamFile->remaining;
211 innerOffset = streamFile->position - fileChunk->fileOffset;
212 chunkBytes = chunkBytes - innerOffset;
213 readPointer += innerOffset;
214 if (copyBytes > chunkBytes)
215 copyBytes = chunkBytes;
216 memcpy(streamFile->destination, readPointer, copyBytes);
217 streamFile->destination += copyBytes;
218 streamFile->position += copyBytes;
219 streamFile->remaining = streamFile->remaining - copyBytes;
220 if (streamFile->remaining == 0) {
221 EnterCriticalSection(&csStreamerFileList);
222 if (streamFile->previous != 0)
223 streamFile->previous->next = streamFile->next;
224 if (streamFile->next == 0)
225 pStreamReadRequests = streamFile->previous;
226 else
227 streamFile->next->previous = streamFile->previous;
228 streamFile->previous = pStreamIdleFiles;
229 streamFile->next = 0;
230 if (pStreamIdleFiles != 0)
231 pStreamIdleFiles->next = streamFile;
232 pStreamIdleFiles = streamFile;
233 streamFile->flags &= ~IX_STREAM_FILE_READING;
234 LeaveCriticalSection(&csStreamerFileList);
235 SetEvent(streamFile->completionEvent);
236 }
237 return;
238 }
239 fileChunk++;
240 chunkIndex++;
241 }
242}
243
244/* Function start: 0x004441C6 */
246{
247 int bytesUntilRefill;
248 IxStreamFile *streamFile;
249 IxStreamFile *bestFile;
250
251 EnterCriticalSection(&csStreamerFileList);
252 if (pStreamReadRequests != 0) {
253 streamFile = pStreamReadRequests;
254 bestFile = 0;
255 while (streamFile != 0) {
256 if (bestFile != 0) {
257 if (bestFile->priority < streamFile->priority)
258 bestFile = streamFile;
259 else if (streamFile->serviceTick < bestFile->serviceTick)
260 bestFile = streamFile;
261 } else {
262 bestFile = streamFile;
263 }
264 streamFile = streamFile->previous;
265 }
266 LeaveCriticalSection(&csStreamerFileList);
267 if (bestFile != 0)
269 } else {
270 LeaveCriticalSection(&csStreamerFileList);
271 }
272
273 if (pStreamReadRequests != 0)
274 return 0;
275 if ((dwIxStreamerStatus & 4) == 0 ||
276 (dwIxStreamerStatus & 8) != 0)
277 return 1000;
278 bytesUntilRefill = ix_thread_get_audio_chunk_size() -
280 if (bytesUntilRefill > 0) {
281 bytesUntilRefill += 0x16f8;
282 return (bytesUntilRefill * 1000U) /
284 }
285 return 0;
286}
287
288/* Function start: 0x00444316 */
290{
292 nStreamerAudioBlock].triggerCount > 0) {
293 unsigned int triggerIndex;
294 unsigned int triggerCount;
295
296 triggerCount = pStreamedMusicAudioChunks[
298 triggerIndex = pStreamedMusicAudioChunks[
300 while (triggerCount--) {
301 if (pStreamTriggerList[triggerIndex].tag == 'A') {
303 (nStreamCallStackIndex - 1) & 0x1f;
307 return;
308 } else if (pStreamTriggerList[triggerIndex].tag == '@') {
309 dwIxStreamerStatus |= 0x800;
310 } else if (pStreamTriggerList[triggerIndex].tag ==
316 (nStreamCallStackIndex + 1) & 0x1f;
318 pStreamTriggerList[triggerIndex].audioChunk;
320 return;
321 }
322 triggerIndex++;
323 }
324 }
325
327 nStreamerAudioBlock].branchCount > 0) {
328 unsigned int branchesToCheck;
329 unsigned int candidateBranch;
330 unsigned int bestBranch;
331 unsigned int bestDistance;
332 unsigned int candidateDistance;
333
334 branchesToCheck = pStreamedMusicAudioChunks[
336 candidateBranch = pStreamedMusicAudioChunks[
338 bestDistance =
339 ((pMusicStreamBranchList[candidateBranch].intensity -
341 (pMusicStreamBranchList[candidateBranch].intensity -
343 ((pMusicStreamBranchList[candidateBranch].intensity -
345 bestBranch = candidateBranch;
346 candidateBranch++;
347 while (branchesToCheck--) {
348 candidateDistance =
349 ((pMusicStreamBranchList[candidateBranch].intensity -
351 (pMusicStreamBranchList[candidateBranch].intensity -
353 ((pMusicStreamBranchList[candidateBranch].intensity -
355 if (candidateDistance < bestDistance) {
356 bestDistance = candidateDistance;
357 bestBranch = candidateBranch;
358 }
359 candidateBranch++;
360 }
363 return;
364 }
369}
370
371/* Function start: 0x004445C9 */ /* source line(s) 394: failed to lock stream buffer */
373{
374 unsigned int lockedBytes;
375 unsigned int unreadBytes;
376 unsigned int packageOffset;
377 unsigned char *buffer;
378
379 unreadBytes = ix_thread_get_audio_chunk_size();
380 if (unreadBytes > 0) {
381 packageOffset = pStreamedMusicAudioChunks[
383 while (unreadBytes > 0) {
384 ix_dsps_lock(0, unreadBytes, &buffer, &lockedBytes);
385 if (buffer == 0) {
386 ix_log_printf("Fatal [%s - %d]:\n", IX_THREAD_FILE, 394);
387 ix_log_printf("failed to lock stream buffer");
388 exit(-1);
389 }
390 ix_file_seek(pStreamerPackFile, packageOffset);
392 lockedBytes);
393 unreadBytes = unreadBytes - lockedBytes;
394 packageOffset += lockedBytes;
396 }
397 }
399}
400
401/* Function start: 0x004446A6 */
403{
404 unsigned int fileOffset;
405
406 if (nStreamerAudioBlock != (unsigned int)-1) {
407 fileOffset = pStreamedMusicAudioChunks[
410 nStreamerAudioBlock].fileEnd - fileOffset;
411 }
412 return 0;
413}
void(__cdecl *pIxFree)(void *)
void ix_dsps_prepare(int stream)
Definition dsps.cpp:101
void ix_dsps_unlock(int stream)
Definition dsps.cpp:277
int ix_dsps_get_buffer_free(int streamIndex)
Definition dsps.cpp:210
void ix_dsps_stop(int stream)
Definition dsps.cpp:153
void ix_dsps_play(int stream)
Definition dsps.cpp:126
void ix_dsps_lock(int stream, unsigned int requestedBytes, unsigned char **buffer, unsigned int *lockedBytes)
Definition dsps.cpp:246
unsigned int dwIxStreamerStatus
Definition ix.h:521
The library's classes and shared declarations.
unsigned int dwStreamBytesPerSecond
Definition streamer.cpp:42
CRITICAL_SECTION csStreamer
Definition streamer.cpp:43
void ix_thread_handle_file_chunk(IxStreamFile *streamFile)
Definition thread.cpp:125
@ IX_STREAM_FILE_READING
Definition ix.h:341
unsigned int * pStreamerPacketOffsetTable
Definition streamer.cpp:17
unsigned int ix_thread_get_audio_chunk_size(void)
Definition thread.cpp:402
IxStreamFile * pStreamIdleFiles
Definition streamer.cpp:22
IxStreamerAudioChunk * pStreamedMusicAudioChunks
Definition streamer.cpp:32
void ix_thread_advance_audio_chunk(void)
Definition thread.cpp:289
FILE * pStreamerPackFile
Definition streamer.cpp:21
unsigned int ix_file_read(FILE *file, void *destination, unsigned int bytes)
Definition ixfile.cpp:62
unsigned int nIxStreamerCurrentFileChunk
Definition streamer.cpp:41
void ix_thread_lock_stream_buffer(void)
Definition thread.cpp:372
unsigned int ix_streamer_service_audio(void)
Definition thread.cpp:97
void ix_log_printf(const char *fmt,...)
Definition ixlog.cpp:32
void ix_file_seek(FILE *file, long position)
Definition ixfile.cpp:50
long ix_file_tell(FILE *file)
Definition ixfile.cpp:56
unsigned int dwStreamThreadTick
Definition streamer.cpp:18
IxStreamerTrigger * pStreamTriggerList
Definition streamer.cpp:44
unsigned char * pIxStreamerInputBuffer
Definition streamer.cpp:27
char cStreamerBranchTag
Definition streamer.cpp:47
IxStreamerFileChunk * pStreamFileBlocks
Definition streamer.cpp:34
unsigned int adwStreamCallStack[32]
Definition streamer.cpp:23
DWORD WINAPI ix_streamer_thread_proc(void *parameter)
Definition thread.cpp:22
unsigned char bStreamerIntensityLevel
Definition streamer.cpp:28
unsigned int nStreamCallStackIndex
Definition streamer.cpp:48
CRITICAL_SECTION csStreamerFileList
Definition streamer.cpp:35
unsigned int nStreamerAudioBlock
Definition streamer.cpp:37
IxStreamFile * pStreamReadRequests
Definition streamer.cpp:25
void ix_lzo1x_decompress(unsigned char *source, unsigned char *destination, unsigned int destinationBytes)
Definition lzo1x.cpp:22
CRITICAL_SECTION csIxStreamerThread
Definition streamer.cpp:36
unsigned char * pStreamerLzoBuffer
Definition streamer.cpp:24
IxStreamerHeader * pStreamerPackageInfo
Definition streamer.cpp:31
IxStreamerBranch * pMusicStreamBranchList
Definition streamer.cpp:33
unsigned int ix_thread_service_streams(void)
Definition thread.cpp:245
@ IX_STREAMER_FILE_OPEN
Definition ix.h:346
@ IX_STREAMER_HAS_AUDIO
Definition ix.h:352
@ IX_STREAMER_DSP_PLAYING
Definition ix.h:350
@ IX_STREAMER_AUDIO_PAUSED
Definition ix.h:348
@ IX_STREAMER_AUDIO_PLAYING
Definition ix.h:347
@ IX_STREAMER_THREAD_RUNNING
Definition ix.h:349
@ IX_STREAMER_SHUTDOWN
Definition ix.h:354
@ IX_STREAMER_REPREPARE_AUDIO
Definition ix.h:355
@ IX_STREAMER_END_TRIGGERED
Definition ix.h:356
@ IX_STREAMER_DSP_PAUSED
Definition ix.h:351
HANDLE hStreamerWakeupEvent
Definition streamer.cpp:40
unsigned char priority
Definition ix.h:431
FILE * file
Definition ix.h:429
unsigned int remaining
Definition ix.h:434
unsigned char * destination
Definition ix.h:435
IxStreamFile * previous
Definition ix.h:437
unsigned int position
Definition ix.h:433
IxStreamFile * next
Definition ix.h:438
unsigned int flags
Definition ix.h:427
IxStreamerFileEntry * entry
Definition ix.h:428
HANDLE completionEvent
Definition ix.h:436
unsigned int serviceTick
Definition ix.h:432
unsigned int triggerCount
Definition ix.h:400
unsigned int fileOffset
Definition ix.h:398
unsigned int firstBranch
Definition ix.h:403
unsigned int branchCount
Definition ix.h:402
unsigned int fileEnd
Definition ix.h:399
unsigned int firstTrigger
Definition ix.h:401
unsigned char intensity
Definition ix.h:408
unsigned int audioChunk
Definition ix.h:409
unsigned int firstPacket
Definition ix.h:423
unsigned int packetCount
Definition ix.h:422
unsigned int fileOffset
Definition ix.h:420
unsigned int fileEnd
Definition ix.h:421
unsigned int firstChunk
Definition ix.h:394
unsigned int chunkCount
Definition ix.h:393
unsigned int audioChunkCount
Definition ix.h:368
unsigned int audioBufferSize
Definition ix.h:365
unsigned int audioChunk
Definition ix.h:414
#define IX_THREAD_FILE
Definition thread.cpp:19