Subversion Repositories Games.Carmageddon

Rev

Rev 20 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 1
#include "s3sound.h"
2
#include "audio.h"
3
#include "backends/backend.h"
11 pmbaty 4
#include "harness/hooks.h"
1 pmbaty 5
#include "harness/trace.h"
6
#include "resource.h"
7
#include <stdio.h>
8
#include <stdlib.h>
9
#include <string.h>
10
 
11
#define MAX_PATH_LENGTH 1024
12
extern void dr_dprintf(char* fmt_string, ...);
13
 
14
int gS3_sample_filter_funcs_registered;
15
long gS3_last_file_length;
16
tS3_sample_filter* gS3_sample_filter_func;
17
tS3_sample_filter* gS3_sample_filter_disable_func;
18
 
19
int S3LoadSample(tS3_sound_id id) {
20
    // changed by dethrace for compatibility
21
    // char filename[80]; // [esp+10h] [ebp-5Ch] BYREF
22
    char filename[MAX_PATH_LENGTH];
23
    tS3_descriptor* descriptor;
24
    tS3_sample* sample;
25
    char* buf;
26
    // LPDIRECTSOUNDBUFFER dsound_buffer; // win95 only
27
 
28
    if (!gS3_enabled) {
29
        return 0;
30
    }
31
    descriptor = S3GetDescriptorByID(id);
32
    if (!descriptor) {
33
        return eS3_error_bad_id;
34
    }
35
    if (descriptor->type != eS3_ST_sample) {
36
        return 0;
37
    }
38
    if (descriptor->sound_data) {
39
        return 0;
40
    }
41
    filename[0] = 0;
42
    strcpy(filename, descriptor->filename);
43
    sample = S3MemAllocate(sizeof(tS3_sample), kMem_S3_sound_header);
44
    if (!sample) {
45
        return eS3_error_memory;
46
    }
47
 
48
    memset(sample, 0, sizeof(tS3_sample));
49
    buf = S3LoadWavFile_DOS(filename);
50
    if (buf == NULL) {
51
        S3MemFree(sample);
52
        return gS3_last_error;
53
    }
54
    sample->freeptr = buf;
55
    if (memcmp(buf, "RIFF", 4) == 0) {
56
        wav_header* hdr = (wav_header*)buf;
57
        sample->dataptr = &buf[sizeof(wav_header)];
58
        sample->size = hdr->data_bytes;
59
        sample->rate = hdr->sample_rate;
60
        sample->resolution = hdr->bit_depth;
61
        sample->channels = hdr->num_channels;
62
    } else {
63
        sample->rate = 16000;
64
        sample->resolution = 8;
65
        sample->channels = 1;
66
        sample->dataptr = buf;
67
        sample->size = gS3_last_file_length;
68
    }
69
 
70
    // win95
71
    // descriptor->sound_buffer = S3LoadWavFile(filename, sample);
72
    // if (!descriptor->sound_buffer) {
73
    //     S3MemFree(sample);
74
    //     return gS3_last_error;
75
    // }
76
    descriptor->special_fx = 0;
77
    descriptor->sound_data = (char*)sample;
78
    return eS3_error_none;
79
}
80
 
81
int S3ReadWavHeader_Win95(char* buf, tWAVEFORMATEX_** pWav_format, char** data_ptr, int* pData_size) {
82
    int riff_len;
83
    char* file_eof;         // [esp+10h] [ebp-14h]
84
    unsigned int chunk_len; // [esp+18h] [ebp-Ch]
85
    char* chunk_data;       // [esp+1Ch] [ebp-8h]
86
    // char* chunk_name;       // [esp+20h] [ebp-4h]
87
    char* chunk_ptr;
88
 
89
    if (pWav_format) {
90
        *pWav_format = 0;
91
    }
92
    if (data_ptr) {
93
        *data_ptr = 0;
94
    }
95
    if (pData_size) {
96
        *pData_size = 0;
97
    }
98
    chunk_ptr = buf + 12;
99
    if (buf[0] != 'R' || buf[1] != 'I' || buf[2] != 'F' || buf[3] != 'F') {
100
        return 0;
101
    }
102
    if (buf[8] != 'W' || buf[9] != 'A' || buf[10] != 'V' || buf[11] != 'E') {
103
        return 0;
104
    }
105
    memcpy(&riff_len, &buf[4], sizeof(riff_len)); // (int32_t)buf[4];
106
#if BR_ENDIAN_BIG
107
    riff_len = BrSwap32(riff_len);
108
#endif
109
    file_eof = &chunk_ptr[riff_len - 4];
110
    while (file_eof > chunk_ptr) {
111
        memcpy(&chunk_len, chunk_ptr + 4, sizeof(chunk_len));
112
#if BR_ENDIAN_BIG
113
        chunk_len = BrSwap32(chunk_len);
114
#endif
115
        chunk_data = chunk_ptr + 8;
116
        if (strncmp(chunk_ptr, "fmt ", 4) == 0) {
117
            if (pWav_format && *pWav_format == NULL) {
118
                if (chunk_len < 14) {
119
                    return 0;
120
                }
121
                *pWav_format = (tWAVEFORMATEX_*)chunk_data;
122
                if ((!data_ptr || *data_ptr) && (!pData_size || *pData_size)) {
123
                    return 1;
124
                }
125
            }
126
        } else if (strncmp(chunk_ptr, "data", 4) == 0 && ((data_ptr && !*data_ptr) || (pData_size && !*pData_size))) {
127
            if (data_ptr) {
128
                *data_ptr = chunk_data;
129
            }
130
            if (pData_size) {
131
                *pData_size = chunk_len;
132
            }
133
            if (!pWav_format || *pWav_format) {
134
                return 1;
135
            }
136
        }
137
        chunk_ptr = &chunk_data[(chunk_len + 1) & 0xFFFFFFFE];
138
    }
139
    return 0;
140
}
141
 
142
void* S3LoadWavFile_DOS(char* pFile_name) {
143
    FILE* f;
144
    long file_len;
145
    size_t bytes_read;
146
    char* buf;
147
 
20 pmbaty 148
    f = Harness_Hook_fopen (pFile_name, "rb");
1 pmbaty 149
    if (f == NULL) {
150
        gS3_last_error = eS3_error_readfile;
151
        return 0;
152
    }
153
    fseek(f, 0, SEEK_END);
154
    file_len = ftell(f);
155
    fseek(f, 0, SEEK_SET);
156
 
157
    buf = S3MemAllocate(file_len + 1, kMem_S3_sample);
158
 
159
    if (buf) {
160
        bytes_read = fread(buf, 1, file_len, f);
161
        if (bytes_read == file_len) {
162
            gS3_last_file_length = file_len;
163
            fclose(f);
164
            return buf;
165
        } else {
166
            gS3_last_error = 4;
167
        }
168
    } else {
169
        fclose(f);
170
        gS3_last_error = eS3_error_memory;
171
    }
172
    return 0;
173
}
174
 
175
void* S3LoadWavFile_Win95(char* pFile_name, tS3_sample* pSample) {
176
    FILE* f;           // [esp+Ch] [ebp-C8h]
177
    size_t bytes_read; // [esp+14h] [ebp-C0h] BYREF
178
    //  unsigned int locked_buffer_data_len; // [esp+18h] [ebp-BCh] BYREF
179
    //   struct _OFSTRUCT ReOpenBuff;         // [esp+1Ch] [ebp-B8h] BYREF
180
    char* buf; // [esp+A4h] [ebp-30h]
181
    // LPDIRECTSOUNDBUFFER ds_buffer;       // [esp+A8h] [ebp-2Ch] BYREF
182
    // DSBUFFERDESC buffer_desc;   // [esp+ACh] [ebp-28h] BYREF
183
    int data_size;              // [esp+C0h] [ebp-14h] BYREF
184
    tWAVEFORMATEX_* wav_format; // [esp+C4h] [ebp-10h] BYREF
185
    char* data_ptr;             // [esp+C8h] [ebp-Ch] BYREF
186
    // char* locked_buffer_data;   // [esp+CCh] [ebp-8h] BYREF
187
    size_t file_len; // [esp+D0h] [ebp-4h]
188
 
20 pmbaty 189
    f = Harness_Hook_fopen (pFile_name, "rb");
1 pmbaty 190
    if (f == NULL) {
191
        gS3_last_error = eS3_error_readfile;
192
        return 0;
193
    }
194
    fseek(f, 0, SEEK_END);
195
    file_len = (size_t)ftell(f);
196
    fseek(f, 0, SEEK_SET);
197
 
198
    buf = S3MemAllocate(file_len, kMem_S3_Windows_95_load_WAV_file);
199
    if (buf == NULL) {
200
        fclose(f);
201
        gS3_last_error = eS3_error_memory;
202
        return 0;
203
    }
204
    bytes_read = fread(buf, file_len, 1, f);
205
    fclose(f);
206
 
207
    data_size = 0;
208
    wav_format = 0;
209
    data_ptr = 0;
210
    if (S3ReadWavHeader_Win95(buf, &wav_format, &data_ptr, &data_size) == 0) {
211
        gS3_last_error = eS3_error_readfile;
212
        dr_dprintf("ERROR: .WAV file '%s' is crap", pFile_name);
213
        return 0;
214
    }
215
    pSample->freeptr = 0;
216
    pSample->dataptr = 0;
217
    pSample->size = data_size;
218
    pSample->rate = wav_format->nSamplesPerSec;
219
    pSample->resolution = wav_format->nAvgBytesPerSec;
220
    pSample->channels = wav_format->nChannels;
221
#if BR_ENDIAN_BIG
222
    pSample->rate = BrSwap32(pSample->rate);
223
    pSample->resolution = BrSwap32(pSample->resolution);
224
    pSample->channels = BrSwap32(pSample->channels);
225
#endif
226
 
227
    // buffer_desc.dwReserved = 0;
228
    // buffer_desc.dwSize = 20;
229
    // buffer_desc.dwFlags = 226;
230
    // buffer_desc.dwBufferBytes = data_size;
231
    // buffer_desc.lpwfxFormat = wav_format;
232
    // if (gS3_direct_sound_ptr->lpVtbl->CreateSoundBuffer(gS3_direct_sound_ptr, &buffer_desc, &ds_buffer, 0)) {
233
    //     return 0;
234
    // } else if (ds_buffer->lpVtbl->Lock(
235
    //                ds_buffer,
236
    //                0,
237
    //                data_size,
238
    //                (LPVOID*)&locked_buffer_data,
239
    //                &locked_buffer_data_len,
240
    //                0,
241
    //                0,
242
    //                0)) {
243
    //     return 0;
244
    // } else {
245
    //     qmemcpy(locked_buffer_data, data_ptr, locked_buffer_data_len);
246
    //     S3MemFree(buf);
247
    //     ds_buffer->lpVtbl->Unlock(ds_buffer, locked_buffer_data, locked_buffer_data_len, 0, 0);
248
    //     return ds_buffer;
249
    // }
250
    return NULL;
251
}
252
 
253
int S3StopSample(tS3_channel* chan) {
254
    if (chan->tag == 0) {
255
        return 1;
256
    }
257
 
258
    if (chan->type_struct_sample == NULL) {
259
        return 0;
260
    }
261
 
262
    AudioBackend_StopSample(chan);
263
 
264
    if (chan->active) {
265
        chan->needs_service = 1;
266
    }
267
 
268
    return 1;
269
}
270
 
271
int S3ExecuteSampleFilterFuncs(tS3_channel* chan) {
272
    if (((chan->descriptor->special_fx == 0) & gS3_sample_filter_funcs_registered) != 0) {
273
        gS3_sample_filter_func(1, chan->tag);
274
        chan->descriptor->special_fx = 1;
275
    } else if (((gS3_sample_filter_funcs_registered == 0) & chan->descriptor->special_fx) != 0) {
276
        gS3_sample_filter_disable_func(1, chan->tag);
277
        chan->descriptor->special_fx = 0;
278
    }
279
    return 0;
280
}
281
 
282
int S3PlaySample(tS3_channel* chan) {
283
 
284
    if (chan->type_struct_sample == NULL) {
285
        return 0;
286
    }
287
 
288
    S3SyncSampleVolumeAndPan(chan);
289
    S3SyncSampleRate(chan);
290
 
291
    if (AudioBackend_PlaySample(chan) != eAB_success) {
292
        return 0;
293
    }
294
    // if (chan->descriptor && chan->descriptor->type == chan->type) {
295
    //     dsound_buffer = chan->descriptor->dsound_buffer;
296
    //     if (dsound_buffer) {
297
    //         dsound_buffer->lpVtbl->SetCurrentPosition(dsound_buffer, 0);
298
    //         play_flags = chan->repetitions == 0; // 1 = DSBPLAY_LOOPING
299
    //         dsound_buffer->lpVtbl->Play(dsound_buffer, 0, 0, play_flags);
300
    //         if (!dsound_buffer->lpVtbl->GetStatus(dsound_buffer, (LPDWORD)&status)) {
301
    //             if ((status & 1) != 0) // DSBSTATUS_PLAYING
302
    //             {
303
    //                 dsound_buffer->lpVtbl->SetCurrentPosition(dsound_buffer, 0);
304
    //             } else {
305
    //                 dsound_buffer->lpVtbl->Play(dsound_buffer, 0, 0, play_flags);
306
    //             }
307
    //         }
308
    //     }
309
    //   }
310
 
311
    return 1;
312
}
313
 
314
// this function was only called in DOS build
315
int S3CreateTypeStructs(tS3_channel* chan) {
316
    void* result;
317
 
318
    result = AudioBackend_AllocateSampleTypeStruct();
319
    if (result == NULL) {
320
        return 0;
321
    }
322
    chan->type_struct_midi = NULL;
323
    chan->type_struct_cda = NULL;
324
    chan->type_struct_sample = (char*)result;
325
    return 1;
326
}
327
 
328
int S3ReleaseTypeStructs(tS3_channel* chan) {
329
    if (chan->type_struct_sample) {
330
        S3MemFree(chan->type_struct_sample);
331
        chan->type_struct_sample = NULL;
332
    }
333
    if (chan->type_struct_cda) {
334
        S3MemFree(chan->type_struct_cda);
335
        chan->type_struct_cda = NULL;
336
    }
337
    return 1;
338
}
339
 
340
int S3SyncSampleVolumeAndPan(tS3_channel* chan) {
341
 
342
    float pan_ratio; // [esp+38h] [ebp-8h]
343
    float total_vol; // [esp+3Ch] [ebp-4h]
344
 
345
    int pan;
346
 
347
    if (chan->type != eS3_ST_sample) {
348
        return 1;
349
    }
350
    total_vol = (float) (chan->left_volume + chan->right_volume); // Pierre-Marie Baty -- added type cast
351
    if (total_vol == 0.0f) {
352
        total_vol = 1.0f;
353
    }
354
    if (chan->descriptor && chan->descriptor->type == chan->type) {
355
 
21 pmbaty 356
        if (AudioBackend_SetVolume(chan, total_vol) == eAB_success && chan->spatial_sound) {
1 pmbaty 357
 
358
            if (chan->left_volume != 0 && chan->right_volume > chan->left_volume) {
359
                pan_ratio = chan->right_volume / (float)chan->left_volume;
360
            } else if (chan->right_volume != 0) {
361
                pan_ratio = chan->left_volume / (float)chan->right_volume;
362
            }
363
            if (chan->left_volume != 0 && chan->right_volume != 0) {
364
                pan = (int) ((chan->right_volume - chan->left_volume) * pan_ratio); // Pierre-Marie Baty -- added type cast
365
                pan = MAX(pan, -10000);
366
                pan = MIN(pan, 10000);
367
            } else if (chan->left_volume != 0) {
368
                pan = -10000;
369
            } else {
370
                pan = 10000;
371
            }
372
            AudioBackend_SetPan(chan, pan);
373
        }
374
    }
375
    return 1;
376
}
377
 
378
int S3SyncSampleRate(tS3_channel* chan) {
379
    if (chan->type != eS3_ST_sample) {
380
        return 1;
381
    }
382
 
383
    int rate = chan->rate;
384
    if (rate >= 100000) {
385
        rate = 100000;
386
    }
387
 
388
    // sound_buffer->lpVtbl->SetFrequency(sound_buffer, rate);
389
    AudioBackend_SetFrequency(chan, rate);
390
 
391
    return 1;
392
}
393
 
394
int S3SetEffects(tS3_sample_filter* filter1, tS3_sample_filter* filter2) {
395
    STUB_ONCE();
396
    return 0;
397
}