Wing Commander II
Reconstructed Win32 source (1996)
Loading...
Searching...
No Matches
dsp.cpp
Go to the documentation of this file.
1/*
2 * ix / D:\rnd\prj\ix\win95\dsp\dsp.cpp
3 *
4 * Original address range: 0x00444910 - 0x004451B4 (21 functions)
5 * Range is exact: recovered from this module's own assert __FILE__ anchors in
6 * the shipped debug build (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#include "ix.h"
12#include <dsound.h>
13#include <stdlib.h>
14#include <string.h>
15
16#define IX_DSP_FILE "D:\\rnd\\prj\\ix\\win95\\dsp\\dsp.cpp"
17
18HANDLE g_hMixerTask; /* 0x005c4ec0 */
19HWND g_4_hDspWnd; /* 0x005c4ec4 */
20HANDLE g_2_hMixerRouseEvent; /* 0x005c4ec8 */
21unsigned int g_3_dwMixWriteOffset; /* 0x005c4ecc */
22LPDIRECTSOUND g_1_pDirectSound; /* 0x005c4ed0 */
23unsigned int g_dwMixerScratchSize; /* 0x005c4ed4 */
24unsigned int g_5_dwSoundOptions; /* 0x005c4ed8 */
25DWORD g_1_dwMixWorkerId; /* 0x005c4edc */
26LPDIRECTSOUNDBUFFER g_pMixerBuffer; /* 0x005c4ee0 */
27unsigned int g_6_dwDsoundTick; /* 0x005c52e8 */
28LPDIRECTSOUNDBUFFER g_1_pPrimarySoundBuffer; /* 0x005c52ec */
29short g_3_anPanTable[512]; /* 0x005c4ee8 */
30/* Kept in dspv.cpp's storage in retail. */
31extern int g_nVoicesReserved; /* 0x005c574c */
32/* The host CRT's malloc takes size_t, which is not unsigned int on every
33 * modern target; keep one definition so the globals audit sees one range. */
34#define IX_MALLOC_HOOK malloc
35unsigned short g_nMasterVolume = 0xffff; /* 0x004a0c14 */
36void *(__cdecl *g_pIxMalloc)(unsigned int) = IX_MALLOC_HOOK; /* 0x004a0c18 */
37void (__cdecl *g_pIxFree)(void *) = free; /* 0x004a0c1c */
38
39/* Function start: 0x489990 */ /* source line 62 */
40int ix_dsp_init(void)
41{
42 if ((g_5_dwSoundOptions & 1) == 0) {
46 InitializeCriticalSection(&g_7_csMixer);
47 g_2_hMixerRouseEvent = CreateEventA(0, TRUE, FALSE, 0);
49 g_hMixerTask = CreateThread(
50 0, 0x1000, ix_mixer_thread_proc, 0, 0,
52 if (g_hMixerTask == 0) {
53 ix_log_printf("Fatal [%s - %d]:\n", IX_DSP_FILE, 62);
54 ix_log_printf("Failed to start mixer");
55 exit(-1);
56 }
58 }
59 return 0;
60}
61
62/* Function start: 0x489A4F */
64{
65 if ((g_5_dwSoundOptions & 1) != 0) {
66 if ((g_5_dwSoundOptions & 4) != 0) {
67 g_5_dwSoundOptions &= ~4U;
68 SetEvent(g_2_hMixerRouseEvent);
69 WaitForSingleObject(g_hMixerTask, INFINITE);
70 }
71 if (g_1_pDirectSound != 0) {
72 g_1_pDirectSound->Release();
74 }
75 DeleteCriticalSection(&g_7_csMixer);
76 CloseHandle(g_2_hMixerRouseEvent);
77 g_5_dwSoundOptions &= 0x7ffffffe;
78 }
79}
80
81/* Function start: 0x489AE2 */
82void ix_dsp_configure(int option, void *value)
83{
84 switch (option) {
85 case 0:
86 g_4_hDspWnd = (HWND)value;
87 break;
88 case 1:
89 g_1_pDirectSound = (LPDIRECTSOUND)value;
90 break;
91 case 2:
92 if ((g_5_dwSoundOptions & 1) != 0)
93 SetEvent(g_2_hMixerRouseEvent);
94 break;
95 case 3:
96 if (value != 0)
97 g_5_dwSoundOptions |= 0x10;
98 else
99 g_5_dwSoundOptions &= ~0x10U;
100 break;
101 case 4:
102 g_pIxMalloc = (void *(__cdecl *)(unsigned int))value;
103 break;
104 case 5:
105 g_pIxFree = (void (__cdecl *)(void *))value;
106 break;
107 }
108}
109
110/* Function start: 0x489BA5 */
111BOOL CALLBACK ix_dsp_open_driver(LPGUID guid, LPSTR description,
112 LPSTR module, LPVOID context)
113{
114 HRESULT result;
115
116 if (g_1_pDirectSound != 0) {
117 g_1_pDirectSound->Release();
119 }
120 result = DirectSoundCreate(guid, &g_1_pDirectSound, 0);
121 if (result == DS_OK) {
122 result = g_1_pDirectSound->SetCooperativeLevel(
124 (g_5_dwSoundOptions & 0x10) == 0
125 ? DSSCL_WRITEPRIMARY : DSSCL_EXCLUSIVE);
126 if (result == DS_OK) {
127 ix_log_printf("sound driver: %s [%s]\n", description, module);
128 return FALSE;
129 }
130 if (g_1_pDirectSound != 0) {
131 g_1_pDirectSound->Release();
133 }
134 }
135 return TRUE;
136}
137
138/* Function start: 0x489C7D */
139unsigned int ix_dsp_get_tick(void)
140{
141 return g_6_dwDsoundTick;
142}
143
144/* Function start: 0x489C92 */
145unsigned int ix_dsp_get_flags(void)
146{
147 return g_5_dwSoundOptions;
148}
149
150/* Function start: 0x489CA7 */
151void ix_dsp_set_config_bit1(int enabled)
152{
153 if (enabled != 0)
155 else
156 g_5_dwSoundOptions &= ~2U;
157}
158
159/* Function start: 0x489CD4 */
160void ix_dsp_set_config_bit3(int enabled)
161{
162 if (enabled != 0)
164 else
165 g_5_dwSoundOptions &= ~8U;
166}
167
168/* Function start: 0x489D01 */
170{
171 return g_nVoiceCapacity;
172}
173
174/* Function start: 0x489D16 */ /* source line(s) 176: can't change voice count while voices are in use */
175void ix_dsp_set_voice_count(int voiceCount)
176{
177 if (g_nVoicesReserved != 0 ||
178 g_nStreamsTaken != 0) {
179 ix_log_printf("Warning [%s - %d]:\n", IX_DSP_FILE, 176);
180 ix_log_printf("can't change voice count while voices are in use");
181 return;
182 }
183 if (voiceCount >= 0)
184 g_nVoiceCapacity = voiceCount < 32 ? voiceCount : 32;
185 else
187 return;
188}
189
190/* Function start: 0x489D98 */
192{
193 return g_3_nStreamCount;
194}
195
196/* Function start: 0x489DAD */ /* source line(s) 187: can't change stream count while voices are in use */
197void ix_dsp_set_stream_count(int streamCount)
198{
199 if (g_nVoicesReserved != 0 ||
200 g_nStreamsTaken != 0) {
201 ix_log_printf("Warning [%s - %d]:\n", IX_DSP_FILE, 187);
202 ix_log_printf("can't change stream count while voices are in use");
203 return;
204 }
205 if (streamCount >= 0)
206 g_3_nStreamCount = streamCount < 2 ? streamCount : 2;
207 else
209 return;
210}
211
212/* Function start: 0x489E2F */
213unsigned short ix_dsp_get_master_volume(void)
214{
215 return g_nMasterVolume;
216}
217
218/* Function start: 0x489E45 */
219void ix_dsp_set_master_volume(unsigned short volume)
220{
221 int voice;
222
223 if ((volume & 0xffff) >= 0) {
224 g_nMasterVolume = (unsigned short)(
225 (volume & 0xffff) < 0xffff ? (volume & 0xffff) : 0xffff);
226 } else {
227 g_nMasterVolume = 0;
228 }
229 for (voice = 0; voice < g_nVoiceCapacity; voice++) {
230 if ((g_2_voices[voice].flags & IX_VOICE_ACTIVE) != 0)
231 ix_dspv_recalc_mix(voice);
232 }
233}
234
235/* Function start: 0x489ED2 */
237{
238 short step;
239 short leftAmp;
240 short offset;
241 short entry;
242 short right;
243
244 step = 0x3ff;
245 leftAmp = 0x7fff;
246 for (entry = 0; entry < 0x40; entry++) {
247 offset = (short)(0x20 - entry);
248 right = (short)(offset * step);
249 g_3_anPanTable[entry * 2] = leftAmp;
250 g_3_anPanTable[entry * 2 + 1] = right;
251 g_3_anPanTable[0x100 + entry * 2] =
252 (short)(leftAmp * -1);
253 g_3_anPanTable[0x100 + entry * 2 + 1] =
254 (short)(right * -1);
255 }
256 right = (short)0x8001;
257 for (entry = 0x40; entry < 0x80; entry++) {
258 offset = (short)(0x60 - entry);
259 leftAmp = (short)(offset * step);
260 g_3_anPanTable[entry * 2] = leftAmp;
261 g_3_anPanTable[entry * 2 + 1] = right;
262 g_3_anPanTable[0x100 + entry * 2] =
263 (short)(leftAmp * -1);
264 g_3_anPanTable[0x100 + entry * 2 + 1] =
265 (short)(right * -1);
266 }
267}
268
269/* Function start: 0x48A017 */
270const char *ix_dsp_result_to_text(int result)
271{
272 switch (result) {
273 case DS_OK:
274 return "The function succeeded.";
275 case DSERR_ALLOCATED:
276 return "The function failed because resources (such as a priority level) were already in use by another caller.";
277 case DSERR_ALREADYINITIALIZED:
278 return "This object is already initialized.";
279 case DSERR_BADFORMAT:
280 return "The specified wave format is not supported.";
281 case DSERR_BUFFERLOST:
282 return "The buffer memory has been lost and must be restored.";
283 case DSERR_CONTROLUNAVAIL:
284 return "The control (volume, pan, and so forth) requested by the caller is not available.";
285 case DSERR_INVALIDCALL:
286 return "This function is not valid for the current state of this object";
287 case DSERR_INVALIDPARAM:
288 return "An invalid parameter was passed to the returning function.";
289 case DSERR_NOAGGREGATION:
290 return "This object does not support aggregation.";
291 case DSERR_NODRIVER:
292 return "No sound driver is available for use.";
293 case DSERR_OUTOFMEMORY:
294 return "The DirectSound subsystem couldn't allocate sufficient memory to complete the caller's request.";
295 case DSERR_PRIOLEVELNEEDED:
296 return "The caller does not have the priority level required for the function to succeed.";
297 case E_NOINTERFACE:
298 return "The requested COM interface is not available.";
299 default:
300 return "Unknow dsound error!";
301 }
302}
303
304/* Function start: 0x48A1A3 */
305void *ix_dsp_alloc(unsigned int bytes)
306{
307 return g_pIxMalloc(bytes);
308}
309
310/* Function start: 0x48A1C0 */
311#pragma function(memcpy)
312void *ix_dsp_copy(void *destination, const void *source, unsigned int bytes)
313{
314 return memcpy(destination, source, bytes);
315}
316
317/* Function start: 0x48A1E4 */
318void ix_dsp_free(void *memory)
319{
320 g_pIxFree(memory);
321}
void ix_dsp_build_pan_tables(void)
Definition dsp.cpp:236
int ix_dsp_get_stream_count(void)
Definition dsp.cpp:191
int g_nVoicesReserved
Definition dspv.cpp:249
unsigned short g_nMasterVolume
Definition dsp.cpp:35
int ix_dsp_init(void)
Definition dsp.cpp:40
void ix_dsp_configure(int option, void *value)
Definition dsp.cpp:82
int ix_dsp_get_voice_count(void)
Definition dsp.cpp:169
void ix_dsp_set_stream_count(int streamCount)
Definition dsp.cpp:197
unsigned int ix_dsp_get_tick(void)
Definition dsp.cpp:139
void ix_dsp_shutdown(void)
Definition dsp.cpp:63
unsigned int ix_dsp_get_flags(void)
Definition dsp.cpp:145
void ix_dsp_set_config_bit3(int enabled)
Definition dsp.cpp:160
void ix_dsp_set_voice_count(int voiceCount)
Definition dsp.cpp:175
unsigned int g_6_dwDsoundTick
Definition dsp.cpp:27
HWND g_4_hDspWnd
Definition dsp.cpp:19
void *__cdecl * g_pIxMalloc(unsigned int)
HANDLE g_hMixerTask
Definition dsp.cpp:18
LPDIRECTSOUND g_1_pDirectSound
Definition dsp.cpp:22
LPDIRECTSOUNDBUFFER g_1_pPrimarySoundBuffer
Definition dsp.cpp:28
BOOL CALLBACK ix_dsp_open_driver(LPGUID guid, LPSTR description, LPSTR module, LPVOID context)
Definition dsp.cpp:111
LPDIRECTSOUNDBUFFER g_pMixerBuffer
Definition dsp.cpp:26
void ix_dsp_free(void *memory)
Definition dsp.cpp:318
unsigned short ix_dsp_get_master_volume(void)
Definition dsp.cpp:213
void ix_dsp_set_config_bit1(int enabled)
Definition dsp.cpp:151
short g_3_anPanTable[512]
Definition dsp.cpp:29
void * ix_dsp_copy(void *destination, const void *source, unsigned int bytes)
Definition dsp.cpp:312
#define IX_DSP_FILE
Definition dsp.cpp:16
DWORD g_1_dwMixWorkerId
Definition dsp.cpp:25
void(__cdecl *g_pIxFree)(void *)
void ix_dsp_set_master_volume(unsigned short volume)
Definition dsp.cpp:219
unsigned int g_5_dwSoundOptions
Definition dsp.cpp:24
const char * ix_dsp_result_to_text(int result)
Definition dsp.cpp:270
HANDLE g_2_hMixerRouseEvent
Definition dsp.cpp:20
#define IX_MALLOC_HOOK
Definition dsp.cpp:34
void * ix_dsp_alloc(unsigned int bytes)
Definition dsp.cpp:305
unsigned int g_dwMixerScratchSize
Definition dsp.cpp:23
unsigned int g_3_dwMixWriteOffset
Definition dsp.cpp:21
int g_nStreamsTaken
Definition dsps.cpp:16
int g_3_nStreamCount
Definition dsps.cpp:15
int g_nVoiceCapacity
Definition dspv.cpp:21
IxVoice g_2_voices[34]
Definition dspv.cpp:19
CRITICAL_SECTION g_7_csMixer
Definition dspv.cpp:20
void ix_dspv_recalc_mix(int voice)
Definition dspv.cpp:227
Audio classes, DirectSound interfaces and shared ix state.
void ix_log_printf(const char *fmt,...)
Definition stream.cpp:164
DWORD WINAPI ix_mixer_thread_proc(void *parameter)
Definition mixer.cpp:35
@ IX_VOICE_ACTIVE
Definition ix.h:42