Wing Commander II
Reconstructed Win32 source (1996)
Loading...
Searching...
No Matches
thread.cpp
Go to the documentation of this file.
1/*
2 * ix / D:\Rnd\Prj\ix\Src\Streamer\thread.cpp
3 *
4 * Retail address range: 0x0046D110 - 0x0046DCFF (7 functions)
5 * Object boundaries follow retail padding and alignment; diagnostic paths
6 * identify the source subsystem (see docs/ORDER.md).
7 *
8 * Implement in ADDRESS ORDER -- MSVC emits functions in source order, so the
9 * list below is the original source order of this file.
10 */
11#define IX_THREAD_CPP
12#include "ix.h"
13#include <stdlib.h>
14#include <string.h>
15
16#pragma function(memcpy)
17
18#define IX_THREAD_FILE "D:\\Rnd\\Prj\\ix\\Src\\Streamer\\thread.cpp"
19
20/* Function start: 0x46D110 */
21DWORD WINAPI ix_streamer_thread_proc(void *parameter)
22{
23 DWORD timeout;
24
25 timeout = 0;
26 EnterCriticalSection(&g_49_csStreamWorker);
28 while ((g_dwStreamerMode & IX_STREAMER_SHUTDOWN) == 0) {
30 EnterCriticalSection(&g_1_csStreamer);
32 if ((g_dwStreamerMode &
34 if ((g_dwStreamerMode &
36 ix_dsps_stop(0);
39 }
44 }
45 if ((g_dwStreamerMode &
48 timeout = ix_streamer_service_audio();
49 if ((g_dwStreamerMode &
51 if ((g_dwStreamerMode &
53 ix_dsps_stop(0);
56 }
57 } else {
58 if ((g_dwStreamerMode &
60 ix_dsps_play(0);
63 }
64 }
65 } else {
66 timeout = ix_thread_service_streams();
67 if ((g_dwStreamerMode &
69 ix_dsps_stop(0);
73 }
74 }
75 LeaveCriticalSection(&g_1_csStreamer);
76 WaitForSingleObject(g_1_hStreamRouseEvent, timeout);
77 ResetEvent(g_1_hStreamRouseEvent);
78 } else {
80 ix_dsps_stop(0);
83 }
84 LeaveCriticalSection(&g_1_csStreamer);
85 WaitForSingleObject(g_1_hStreamRouseEvent, INFINITE);
86 ResetEvent(g_1_hStreamRouseEvent);
87 }
88 }
90 LeaveCriticalSection(&g_49_csStreamWorker);
91 (void)parameter;
92 return 0;
93}
94
95/* Function start: 0x46D2C0 */
96unsigned int ix_streamer_service_audio(void)
97{
98 unsigned int bytesUntilStop;
99
101 bytesUntilStop = g_pStreamPrologue->audioBufferSize -
103 Sleep((bytesUntilStop * 1000U) /
105 g_dwStreamerMode &= 0xfffff7db;
106 ix_dsps_stop(0);
107 } else if ((g_dwStreamerMode &
112 (unsigned int)ix_dsps_get_buffer_free(0))
114 ix_dsps_play(0);
115 } else {
117 (unsigned int)ix_dsps_get_buffer_free(0))
119 }
121}
122
123/* Function start: 0x46D3A6 */ /* source line(s) 196: File chunk without packet! */
125{
126 unsigned int archiveOffset;
127 IxStreamerFileChunk *sourceChunk;
128 unsigned int chunkIndex;
129 unsigned int unreadChunks;
130 IxStreamerFileEntry *directoryRecord;
131 unsigned int offsetInPart;
132 unsigned int partDataSize;
133 unsigned char *readSource;
134 unsigned int byteCount;
135 unsigned int midpoint;
136 unsigned int firstPacket;
137 unsigned int *selectedPacket;
138 unsigned int endPacket;
139
140 directoryRecord = streamFile->entry;
142 if ((g_dwStreamerMode & 0x100) != 0) {
143 ix_file_seek(streamFile->file, streamFile->position);
144 ix_file_read(streamFile->file, streamFile->destination,
145 streamFile->remaining);
146 EnterCriticalSection(&g_csStreamerFileFifo);
147 streamFile->flags &= ~IX_STREAM_FILE_READING;
148 if (streamFile->previous != 0)
149 streamFile->previous->next = streamFile->next;
150 if (streamFile->next == 0)
151 g_1_pPlayerReadQueue = streamFile->previous;
152 else
153 streamFile->next->previous = streamFile->previous;
154 streamFile->previous = g_48_pPumpIdleFiles;
155 streamFile->next = 0;
156 if (g_48_pPumpIdleFiles != 0)
157 g_48_pPumpIdleFiles->next = streamFile;
158 g_48_pPumpIdleFiles = streamFile;
159 LeaveCriticalSection(&g_csStreamerFileFifo);
160 SetEvent(streamFile->completionEvent);
161 return;
162 }
163
164 chunkIndex = directoryRecord->firstChunk;
165 unreadChunks = directoryRecord->chunkCount;
166 sourceChunk = &g_17_pStreamerFileParts[chunkIndex];
167 archiveOffset = (unsigned int)ix_file_tell(
169 while (unreadChunks--) {
170 if (sourceChunk->fileOffset <= streamFile->position &&
171 sourceChunk->fileEnd > streamFile->position) {
172 partDataSize = sourceChunk->fileEnd - sourceChunk->fileOffset;
173 if (chunkIndex != g_nSpoolerDiskChunk) {
174 firstPacket = sourceChunk->firstPacket;
175 endPacket = sourceChunk->packetCount + firstPacket;
176 selectedPacket = 0;
177 g_nSpoolerDiskChunk = chunkIndex;
178 while (endPacket > firstPacket) {
179 midpoint = (endPacket + firstPacket) >> 1;
180 selectedPacket = &g_7_pStreamerPacketOffsets[midpoint];
181 if (*selectedPacket < archiveOffset)
182 firstPacket = midpoint + 1;
183 else if (*selectedPacket > archiveOffset)
184 endPacket = midpoint;
185 else
186 break;
187 }
188 if (selectedPacket == 0) {
189 ix_log_printf("Fatal [%s - %d]:\n", IX_THREAD_FILE, 196);
190 ix_log_printf("File chunk without packet!");
191 exit(-1);
192 }
193 if (sourceChunk->packedSize < 0) {
194 ix_file_seek(g_1_pFeederPackageDisk, *selectedPacket);
197 -sourceChunk->packedSize);
200 partDataSize);
201 } else {
202 ix_file_seek(g_1_pFeederPackageDisk, *selectedPacket);
205 sourceChunk->packedSize);
206 }
207 }
208 readSource = g_pStreamerFileStore;
209 byteCount = streamFile->remaining;
210 offsetInPart = streamFile->position - sourceChunk->fileOffset;
211 partDataSize = partDataSize - offsetInPart;
212 readSource += offsetInPart;
213 if (byteCount > partDataSize)
214 byteCount = partDataSize;
215 memcpy(streamFile->destination, readSource, byteCount);
216 streamFile->destination += byteCount;
217 streamFile->position += byteCount;
218 streamFile->remaining = streamFile->remaining - byteCount;
219 if (streamFile->remaining == 0) {
220 EnterCriticalSection(&g_csStreamerFileFifo);
221 if (streamFile->previous != 0)
222 streamFile->previous->next = streamFile->next;
223 if (streamFile->next == 0)
224 g_1_pPlayerReadQueue = streamFile->previous;
225 else
226 streamFile->next->previous = streamFile->previous;
227 streamFile->previous = g_48_pPumpIdleFiles;
228 streamFile->next = 0;
229 if (g_48_pPumpIdleFiles != 0)
230 g_48_pPumpIdleFiles->next = streamFile;
231 g_48_pPumpIdleFiles = streamFile;
232 streamFile->flags &= ~IX_STREAM_FILE_READING;
233 LeaveCriticalSection(&g_csStreamerFileFifo);
234 SetEvent(streamFile->completionEvent);
235 }
236 return;
237 }
238 sourceChunk++;
239 chunkIndex++;
240 }
241}
242
243int ix_dsps_get_buffer_free(int stream);
244void ix_dsps_unlock(int stream);
245
246/* Function start: 0x46D7C6 */
248{
249 int bytesUntilRefill;
250 IxStreamFile *streamFile;
251 IxStreamFile *chosenFile;
252
253 EnterCriticalSection(&g_csStreamerFileFifo);
254 if (g_1_pPlayerReadQueue != 0) {
255 streamFile = g_1_pPlayerReadQueue;
256 chosenFile = 0;
257 while (streamFile != 0) {
258 if (chosenFile != 0) {
259 if (chosenFile->priority < streamFile->priority)
260 chosenFile = streamFile;
261 else if (streamFile->serviceTick < chosenFile->serviceTick)
262 chosenFile = streamFile;
263 } else
264 chosenFile = streamFile;
265 streamFile = streamFile->previous;
266 }
267 LeaveCriticalSection(&g_csStreamerFileFifo);
268 if (chosenFile != 0)
269 ix_thread_handle_file_chunk(chosenFile);
270 } else {
271 LeaveCriticalSection(&g_csStreamerFileFifo);
272 }
273
274 if (g_1_pPlayerReadQueue != 0)
275 return 0;
276 if ((g_dwStreamerMode & 4) == 0 ||
277 (g_dwStreamerMode & 8) != 0)
278 return 1000;
279 bytesUntilRefill = ix_thread_get_audio_chunk_size() -
281 if (bytesUntilRefill > 0) {
282 bytesUntilRefill += 0x16f8;
283 return (bytesUntilRefill * 1000U) /
285 }
286 return 0;
287}
288
289/* Function start: 0x46D916 */
291{
293 g_6_dwStreamSoundChunk].triggerCount > 0) {
294 unsigned int triggerIndex;
295 unsigned int triggerCount;
296
297 triggerCount = g_15_pStreamerSoundChunks[
299 triggerIndex = g_15_pStreamerSoundChunks[
301 while (triggerCount--) {
302 if (g_6_pFeederTriggers[triggerIndex].tag == 'A') {
304 (g_nStreamerBranchStackIndex - 1) & 0x1f;
308 return;
309 } else if (g_6_pFeederTriggers[triggerIndex].tag ==
310 '@') {
311 g_dwStreamerMode |= 0x800;
312 } else if (g_6_pFeederTriggers[triggerIndex].tag ==
318 (g_nStreamerBranchStackIndex + 1) & 0x1f;
320 g_6_pFeederTriggers[triggerIndex].audioChunk;
322 return;
323 }
324 triggerIndex++;
325 }
326 }
327
329 g_6_dwStreamSoundChunk].branchCount > 0) {
330 unsigned int branch;
331 unsigned int count;
332 unsigned int pick;
333 unsigned int bestGap;
334 unsigned int gap;
335
340 bestGap =
342 g_6_bFeederLevel) >> 31 ^
345 ((g_7_pStreamBranches[branch].intensity -
346 g_6_bFeederLevel) >> 31);
347 pick = branch;
348 branch++;
349 while (count--) {
350 gap =
352 g_6_bFeederLevel) >> 31 ^
355 ((g_7_pStreamBranches[branch].intensity -
356 g_6_bFeederLevel) >> 31);
357 if (gap < bestGap) {
358 bestGap = gap;
359 pick = branch;
360 }
361 branch++;
362 }
365 return;
366 }
371 return;
372}
373
374/* Function start: 0x46DBC9 */ /* source line(s) 394: failed to lock stream buffer */
376{
377 unsigned int bytesToCopy;
378 unsigned int lockedBytes;
379 unsigned char *data;
380 unsigned int fileOffset;
381
382 bytesToCopy = ix_thread_get_audio_chunk_size();
383 if (bytesToCopy > 0) {
384 fileOffset = g_15_pStreamerSoundChunks[
386 while (bytesToCopy > 0) {
387 ix_dsps_lock(0, bytesToCopy, &data, &lockedBytes);
388 if (data == 0) {
389 ix_log_printf("Fatal [%s - %d]:\n", IX_THREAD_FILE, 394);
390 ix_log_printf("failed to lock stream buffer");
391 exit(-1);
392 }
395 lockedBytes);
396 bytesToCopy = bytesToCopy - lockedBytes;
397 fileOffset += lockedBytes;
399 }
400 }
402}
403
404/* Function start: 0x46DCA6 */
406{
407 unsigned int fileOffset;
408
409 if (g_6_dwStreamSoundChunk != (unsigned int)-1) {
410 fileOffset = g_15_pStreamerSoundChunks[
413 g_6_dwStreamSoundChunk].fileEnd - fileOffset;
414 }
415 return 0;
416}
void(__cdecl *g_pIxFree)(void *)
void ix_dsps_prepare(int stream)
Definition dsps.cpp:109
void ix_dsps_unlock(int stream)
Definition dsps.cpp:296
void ix_dsps_stop(int stream)
Definition dsps.cpp:161
void ix_dsps_play(int stream)
Definition dsps.cpp:134
int ix_dsps_get_buffer_free(int stream)
Definition dsps.cpp:223
void ix_dsps_lock(int stream, unsigned int requestedBytes, unsigned char **buffer, unsigned int *lockedBytes)
Definition dsps.cpp:265
unsigned int g_dwStreamerMode
Definition ix.h:506
Audio classes, DirectSound interfaces and shared ix state.
IxStreamerTrigger * g_6_pFeederTriggers
Definition streamer.cpp:41
IxStreamerHeader * g_pStreamPrologue
Definition streamer.cpp:28
unsigned int g_nStreamerBranchStackIndex
Definition streamer.cpp:45
unsigned int * g_7_pStreamerPacketOffsets
Definition streamer.cpp:16
void ix_thread_handle_file_chunk(IxStreamFile *streamFile)
Definition thread.cpp:124
@ IX_STREAM_FILE_READING
Definition ix.h:299
unsigned int ix_thread_get_audio_chunk_size(void)
Definition thread.cpp:405
HANDLE g_1_hStreamRouseEvent
Definition streamer.cpp:37
IxStreamFile * g_48_pPumpIdleFiles
Definition streamer.cpp:19
void ix_thread_advance_audio_chunk(void)
Definition thread.cpp:290
unsigned int ix_file_read(FILE *file, void *destination, unsigned int bytes)
Definition ixfile.cpp:60
FILE * g_1_pFeederPackageDisk
Definition streamer.cpp:18
unsigned int g_nSpoolerDiskChunk
Definition streamer.cpp:38
void ix_thread_lock_stream_buffer(void)
Definition thread.cpp:375
unsigned int ix_streamer_service_audio(void)
Definition thread.cpp:96
void ix_log_printf(const char *fmt,...)
Definition stream.cpp:164
void ix_file_seek(FILE *file, long position)
Definition ixfile.cpp:48
CRITICAL_SECTION g_csStreamerFileFifo
Definition streamer.cpp:32
long ix_file_tell(FILE *file)
Definition ixfile.cpp:54
unsigned int g_6_dwStreamSoundChunk
Definition streamer.cpp:34
CRITICAL_SECTION g_49_csStreamWorker
Definition streamer.cpp:33
DWORD WINAPI ix_streamer_thread_proc(void *parameter)
Definition thread.cpp:21
unsigned char * g_pStreamerFileStore
Definition streamer.cpp:24
IxStreamFile * g_1_pPlayerReadQueue
Definition streamer.cpp:22
char g_cStreamerBranchTag
Definition streamer.cpp:44
unsigned char * g_126_pReaderCompressedBuf
Definition streamer.cpp:21
void ix_lzo1x_decompress(unsigned char *source, unsigned char *destination, unsigned int destinationBytes)
Definition lzo1x.cpp:16
unsigned int g_13_adwPlayerBranchingStack[32]
Definition streamer.cpp:20
IxStreamerFileChunk * g_17_pStreamerFileParts
Definition streamer.cpp:31
CRITICAL_SECTION g_1_csStreamer
Definition streamer.cpp:40
IxStreamerBranch * g_7_pStreamBranches
Definition streamer.cpp:30
unsigned int g_16_nStreamerBytesEachSecond
Definition streamer.cpp:39
unsigned int ix_thread_service_streams(void)
Definition thread.cpp:247
@ IX_STREAMER_FILE_OPEN
Definition ix.h:304
@ IX_STREAMER_HAS_AUDIO
Definition ix.h:310
@ IX_STREAMER_DSP_PLAYING
Definition ix.h:308
@ IX_STREAMER_AUDIO_PAUSED
Definition ix.h:306
@ IX_STREAMER_AUDIO_PLAYING
Definition ix.h:305
@ IX_STREAMER_THREAD_RUNNING
Definition ix.h:307
@ IX_STREAMER_SHUTDOWN
Definition ix.h:312
@ IX_STREAMER_REPREPARE_AUDIO
Definition ix.h:313
@ IX_STREAMER_END_TRIGGERED
Definition ix.h:314
@ IX_STREAMER_DSP_PAUSED
Definition ix.h:309
IxStreamerAudioChunk * g_15_pStreamerSoundChunks
Definition streamer.cpp:29
unsigned int g_18_dwStreamerThreadTick
Definition streamer.cpp:17
unsigned char g_6_bFeederLevel
Definition streamer.cpp:25
unsigned char priority
Definition ix.h:389
FILE * file
Definition ix.h:387
unsigned int remaining
Definition ix.h:392
unsigned char * destination
Definition ix.h:393
IxStreamFile * previous
Definition ix.h:395
unsigned int position
Definition ix.h:391
IxStreamFile * next
Definition ix.h:396
unsigned int flags
Definition ix.h:385
IxStreamerFileEntry * entry
Definition ix.h:386
HANDLE completionEvent
Definition ix.h:394
unsigned int serviceTick
Definition ix.h:390
unsigned int triggerCount
Definition ix.h:358
unsigned int fileOffset
Definition ix.h:356
unsigned int firstBranch
Definition ix.h:361
unsigned int branchCount
Definition ix.h:360
unsigned int fileEnd
Definition ix.h:357
unsigned int firstTrigger
Definition ix.h:359
unsigned char intensity
Definition ix.h:366
unsigned int audioChunk
Definition ix.h:367
unsigned int firstPacket
Definition ix.h:381
unsigned int packetCount
Definition ix.h:380
unsigned int fileOffset
Definition ix.h:378
unsigned int fileEnd
Definition ix.h:379
unsigned int firstChunk
Definition ix.h:352
unsigned int chunkCount
Definition ix.h:351
unsigned int audioChunkCount
Definition ix.h:326
unsigned int audioBufferSize
Definition ix.h:323
unsigned int audioChunk
Definition ix.h:372
#define IX_THREAD_FILE
Definition thread.cpp:18