- #include "audio.h" 
- #include "resource.h" 
-   
- #include "3d.h" 
- #include "backends/backend.h" 
- #include "harness/config.h" 
- #include "harness/os.h" 
- #include "harness/trace.h" 
- #include "s3/s3.h" 
- #include "s3cda.h" 
- #include "s3music.h" 
- #include "s3sound.h" 
- #include <ctype.h> 
- #include <errno.h> 
- #include <stddef.h> 
- #include <stdio.h> 
- #include <stdlib.h> 
- #include <string.h> 
-   
- extern int PDGetTotalTime(void); 
-   
- int gS3_enabled; 
- int gS3_noutlets; 
- int gS3_nsound_sources; 
- int gS3_next_outlet_id; 
- tS3_outlet* gS3_outlets; 
- tS3_sound_source* gS3_sound_sources; 
- tS3_descriptor* gS3_descriptors; 
- tS3_descriptor* gS3_root_descriptor; 
- int gS3_opened_output_devices; 
- int gS3_last_service_time; 
- int gS3_service_time_delta; 
- tS3_channel* gS3_unbound_channels; 
- tS3_channel* gS3_last_unbound_channel; 
- int gS3_last_error; 
- int gS3_default_pitch; 
- tS3_hardware_info gS3_hardware_info; 
- char* gS3_soundbank_buffer; 
- int gS3_soundbank_buffer_len; 
- int gS3_inside_cockpit; 
-   
- tS3_channel gS3_channel_template; 
- int gS3_tag_seed; 
-   
- char gS3_directory_separator[4]; 
- char gS3_directory_name[8]; 
- int gS3_have_current_dir; 
- char gS3_current_dir[260]; 
-   
- int dword_5216C0; 
-   
- int S3Init(char* pPath, int pLow_memory_mode) { 
-     tS3_descriptor* root_descriptor; 
-   
-     gS3_noutlets = 0; 
-     gS3_nsound_sources = 0; 
-     gS3_next_outlet_id = 0; 
-     gS3_outlets = NULL; 
-     gS3_sound_sources = NULL; 
-     gS3_descriptors = NULL; 
-     gS3_root_descriptor = NULL; 
-   
-     S3Disable(); 
-     S3DisableMIDI(); 
-     S3DisableCDA(); 
-     gS3_sample_filter_funcs_registered = 0; 
-     gS3_sample_filter_func = NULL; 
-     gS3_sample_filter_disable_func = NULL; 
-     if (S3OpenOutputDevices() == 0) { 
-         return 1; 
-     } 
-     gS3_opened_output_devices = 1; 
-     root_descriptor = S3MemAllocate(sizeof(tS3_descriptor), kMem_S3_sentinel); 
-     if (!root_descriptor) { 
-         return 3; 
-     } 
-     memset(- root_descriptor , 0, sizeof(- tS3_descriptor ));
 
-     root_descriptor->id = 2495081; 
-     gS3_root_descriptor = root_descriptor; 
-     gS3_descriptors = root_descriptor; 
-     if (S3LoadSoundbank(pPath, pLow_memory_mode)) { 
-         return 5; 
-     } 
-     gS3_last_service_time = PDGetTotalTime(); 
-     gS3_unbound_channels = 0; 
-     gS3_last_unbound_channel = 0; 
-     return 0; 
- } 
-   
- void S3Shutdown(void) { 
-     tS3_outlet* outlet;              // [esp+10h] [ebp-10h] 
-     tS3_outlet* next_outlet;         // [esp+14h] [ebp-Ch] 
-     tS3_descriptor* next_descriptor; // [esp+18h] [ebp-8h] 
-     tS3_descriptor* descriptor;      // [esp+1Ch] [ebp-4h] 
-   
-     S3StopAllOutletSounds(); 
-     S3DisableMIDI(); 
-     S3DisableCDA(); 
-     if (gS3_enabled) { 
-         S3Disable(); 
-         for (descriptor = gS3_descriptors; descriptor != NULL; descriptor = next_descriptor) { 
-             next_descriptor = descriptor->next; 
-             S3ReleaseSound(descriptor->id); 
-             S3MemFree(descriptor); 
-         } 
-         for (outlet = gS3_outlets; outlet != NULL; outlet = next_outlet) { 
-             next_outlet = outlet->next; 
-             S3ReleaseOutlet(outlet); 
-         } 
-         S3ReleaseUnboundChannels(); 
-     } 
-     if (gS3_opened_output_devices) { 
-         S3CloseDevices(); 
-     } 
- } 
-   
- void S3Enable(void) { 
-     gS3_enabled = 1; 
- } 
-   
- void S3Disable(void) { 
-     S3StopAllOutletSounds(); 
-     gS3_enabled = 0; 
- } 
-   
- int S3OpenOutputDevices(void) { 
-   
-     // strcpy(gS3_directory_separator, "\\"); 
-     strcpy(- gS3_directory_separator , "/");
 
-     strcpy(- gS3_directory_name , "SOUND");
 
-     memset(&- gS3_hardware_info , 0, sizeof(- gS3_hardware_info ));
 
-     if (S3OpenSampleDevice() == 0) { 
-         return 0; 
-     } 
-     S3OpenCDADevice(); 
-     gS3_hardware_info.timer_installed = 0; 
-     gS3_hardware_info.device_installed = 1; 
-     gS3_hardware_info.independent_pitch = 0; 
-     return 1; 
- } 
-   
- int S3OpenSampleDevice(void) { 
-   
-     // if (DirectSoundCreate(0, &gS3_direct_sound_ptr, 0)) { 
-     //     return 0; 
-     // } 
-     // if (gS3_direct_sound_ptr->lpVtbl->SetCooperativeLevel(gS3_direct_sound_ptr, gWin32_hwnd, 3)) { 
-     //     return 0; 
-     // } 
-   
-     if (AudioBackend_Init() != eAB_success) { 
-         return 0; 
-     } 
-     S3Enable(); 
-     return 1; 
- } 
-   
- // returns 0 on failure, 1 on success 
- int S3OpenCDADevice(void) { 
-     // gS3_cda_device.lpstrDeviceType = (LPCSTR)516; 
-     // if (mciSendCommandA(0, 0x803u, 0x3000u, (DWORD_PTR)&gS3_cda_device) 
-     //     && mciSendCommandA(0, 0x803u, 0x3100u, (DWORD_PTR)&gS3_cda_device)) { 
-     //     return 0; 
-     // } 
-     // stru_550560.dwTimeFormat = 10; // MCI_FORMAT_TMSF 
-     // mciSendCommandA(gS3_cda_device.wDeviceID, 0x80Du, 0x400u, (DWORD_PTR)&stru_550560); 
-   
-     if (AudioBackend_InitCDA() != eAB_success) { 
-         return 0; 
-     } 
-   
-     S3EnableCDA(); 
-     return 1; 
- } 
-   
- void S3CloseDevices(void) { 
-     if (gS3_hardware_info.device_installed) { 
-         // gS3_direct_sound_ptr->lpVtbl->Release(gS3_direct_sound_ptr); 
-         // gS3_direct_sound_ptr = NULL; 
-   
-         AudioBackend_UnInit(); 
-     } 
-     // if (gS3_cda_device.wDeviceID) { 
-     //     mciSendCommandA(gS3_cda_device.wDeviceID, 0x804u, 0, 0); // MCI_CLOSE 
-     // } 
-   
-     AudioBackend_UnInitCDA(); 
- } 
-   
- int S3ReleaseSound(tS3_sound_id id) { 
-     tS3_channel* c;       // [esp+Ch] [ebp-10h] 
-     tS3_outlet* o;        // [esp+10h] [ebp-Ch] 
-     tS3_descriptor* desc; // [esp+14h] [ebp-8h] 
-     tS3_sample* sample_ptr; 
-   
-     if (!gS3_enabled) { 
-         return 0; 
-     } 
-   
-     desc = S3GetDescriptorByID(id); 
-     if (desc == NULL) { 
-         return eS3_error_bad_id; 
-     } 
-     if (desc->type == eS3_ST_midi) { 
-         for (o = gS3_outlets; o; o = o->next) { 
-             for (c = o->channel_list; c; c = c->next) { 
-                 if (c->descriptor && c->descriptor->id == id) { 
-                     S3ReleaseMIDI(c->tag); 
-                 } 
-             } 
-         } 
-     } else if (desc->type == eS3_ST_sample) { 
-         sample_ptr = (tS3_sample*)desc->sound_data; 
-         if (sample_ptr == NULL) { 
-             return 0; 
-         } 
-         S3MemFree(sample_ptr->freeptr); 
-         S3MemFree(sample_ptr); 
-         desc->sound_data = NULL; 
-     } 
-     return 0; 
- } 
-   
- int S3LoadSoundbank(const char* pSoundbank_filename, int pLow_memory_mode) { 
-     char soundbank_filename[256];    // [esp+Ch] [ebp-218h] BYREF 
-     void* buffer;                    // [esp+10Ch] [ebp-118h] 
-     tS3_soundbank_read_ctx read_ctx; // [esp+110h] [ebp-114h] BYREF 
-     char* cur_dir;                   // [esp+120h] [ebp-104h] 
-     char dir_name[256];              // [esp+124h] [ebp-100h] BYREF 
-   
-     if (gS3_enabled) { 
-         dir_name[0] = 0; 
-         soundbank_filename[0] = 0; 
-         cur_dir = S3GetCurrentDir(); 
-         strcat(- dir_name ,-  gS3_directory_separator );
 
-         strcat(- dir_name ,-  gS3_directory_separator );
 
-         strcat(- dir_name ,-  gS3_directory_name );
 
-         strcat(- dir_name ,-  gS3_directory_separator );
 
-         strcpy(- soundbank_filename ,-  pSoundbank_filename );
 
-         buffer = S3LoadSoundBankFile(soundbank_filename); 
-         if (!buffer) { 
-             return gS3_last_error; 
-         } 
-         read_ctx.data = (char*)buffer; 
-         read_ctx.data_len = gS3_soundbank_buffer_len; 
-         read_ctx.nlines = 0; 
-         S3SoundBankReaderSkipWhitespace(&read_ctx); 
-         while (S3SoundBankReadEntry(&read_ctx, dir_name, pLow_memory_mode)) { 
-             ; 
-         } 
-         S3MemFree(buffer); 
-     } 
-     return 0; 
- } 
-   
- char* S3LoadSoundBankFile(char* pThe_path) { 
-     size_t bytes_read; 
-     // int fd;                   // [esp+Ch] [ebp-2Ch] 
-     char* buffer; 
-     // struct _stat stat_result; 
-   
-     FILE* fd; 
-     size_t file_size; 
-   
-     // fd = _open(pThe_path, 0x8000); 
-     fd = OS_fopen(pThe_path, "rb"); 
-     if (!fd) { 
-         gS3_last_error = eS3_error_readfile; 
-         return 0; 
-     } 
-   
-     // if (_fstat(fd, &stat_result)) { 
-     //     gS3_last_error = eS3_error_readfile; 
-     //     return 0; 
-     // } 
-   
-     if (fseek(- fd , 0,-  SEEK_END ) != 0) {
 
-         gS3_last_error = eS3_error_readfile; 
-         return 0; 
-     } 
-   
-     buffer = S3MemAllocate(file_size + 1, kMem_S3_sample); 
-     if (buffer == NULL) { 
-         gS3_last_error = eS3_error_memory; 
-         return 0; 
-     } 
-     buffer[file_size] = 0; 
-     bytes_read  = fread(- buffer , 1,-  file_size ,-  fd );
-     if (bytes_read == file_size) { 
-         gS3_soundbank_buffer = buffer; 
-         gS3_soundbank_buffer_len = file_size; 
-         return buffer; 
-     } 
-     gS3_last_error = eS3_error_readfile; 
-     return 0; 
- } 
-   
- void S3SoundBankReaderNextLine(tS3_soundbank_read_ctx* ctx) { 
-     S3SoundBankReaderSkipToNewline(ctx); 
-     S3SoundBankReaderSkipWhitespace(ctx); 
- } 
-   
- void S3SoundBankReaderSkipWhitespace(tS3_soundbank_read_ctx* ctx) { 
-     while (ctx->data_len) { 
-         if (isalnum(*- ctx ->- data ) || *- ctx ->- data  == '-') {
 
-             break; 
-         } 
-         S3SoundBankReaderSkipToNewline(ctx); 
-     } 
- } 
-   
- void S3SoundBankReaderSkipToNewline(tS3_soundbank_read_ctx* ctx) { 
-     char* newline_ptr; // [esp+Ch] [ebp-4h] 
-   
-     newline_ptr  = memchr(- ctx ->- data , '\n',-  ctx ->- data_len );
-     if (newline_ptr) { 
-         S3SoundBankReaderAdvance(ctx, newline_ptr + 1 - ctx->data); 
-         ctx->nlines++; 
-     } else { 
-         ctx->data_len = 0; 
-     } 
- } 
-   
- void S3SoundBankReaderAdvance(tS3_soundbank_read_ctx* buffer, int bytes_read) { 
-     buffer->data += bytes_read; 
-     buffer->data_len -= bytes_read; 
- } 
-   
- int S3SoundBankReadEntry(tS3_soundbank_read_ctx* ctx, char* dir_name, int low_memory_mode) { 
-     int nmemory_proxies;  // [esp+Ch] [ebp-24h] BYREF 
-     int i;                // [esp+10h] [ebp-20h] 
-     int proxy_id;         // [esp+14h] [ebp-1Ch] BYREF 
-     tS3_descriptor* desc; // [esp+18h] [ebp-18h] 
-     double tmp1;          // [esp+1Ch] [ebp-14h] BYREF 
-     double tmp2;          // [esp+24h] [ebp-Ch] BYREF 
-     int char_count;       // [esp+2Ch] [ebp-4h] BYREF 
-     char cda_dir_name[4]; 
-   
-     desc = S3CreateDescriptor(); 
-     if (!desc) { 
-         return gS3_last_error; 
-     } 
-     if (sscanf(- ctx ->- data , "%i%n", &- desc ->- id , &- char_count ) != 1) {
 
-         return 0; 
-     } 
-     S3SoundBankReaderAdvance(ctx, char_count); 
-     S3SoundBankReaderNextLine(ctx); 
-     if (sscanf(- ctx ->- data , "%i,%i%n", &- desc ->- type , &- desc ->- flags , &- char_count ) != 2) {
 
-         return 0; 
-     } 
-     S3SoundBankReaderAdvance(ctx, char_count); 
-     S3SoundBankReaderNextLine(ctx); 
-     if (desc->type == eS3_ST_cda) { 
-         dir_name = cda_dir_name; 
-         cda_dir_name[0] = '\0'; 
-     } 
-     if (!S3SoundBankReaderReadFilename(&desc->filename, ctx, dir_name)) { 
-         return 0; 
-     } 
-     S3SoundBankReaderNextLine(ctx); 
-     if (sscanf(- ctx ->- data , "%i%n", (int*)&- desc ->- priority , &- char_count ) != 1) {
 
-         return 0; 
-     } 
-     S3SoundBankReaderAdvance(ctx, char_count); 
-     S3SoundBankReaderNextLine(ctx); 
-     if (sscanf(- ctx ->- data , "%i%n", &- desc ->- repeats , &- char_count ) != 1) {
 
-         return 0; 
-     } 
-     S3SoundBankReaderAdvance(ctx, char_count); 
-     S3SoundBankReaderNextLine(ctx); 
-     if (sscanf(- ctx ->- data , "%i,%i%n", &- desc ->- min_volume , &- desc ->- max_volume , &- char_count ) != 2) {
 
-         return 0; 
-     } 
-     S3SoundBankReaderAdvance(ctx, char_count); 
-     S3SoundBankReaderNextLine(ctx); 
-     if (sscanf(- ctx ->- data , "%lf,%lf%n", &- tmp1 , &- tmp2 , &- char_count ) != 2) {
 
-         return 0; 
-     } 
-     S3SoundBankReaderAdvance(ctx, char_count); 
-     S3SoundBankReaderNextLine(ctx); 
-     if (tmp1 == 0.0f) { 
-         tmp1 = 1.0f; 
-     } 
-     if (tmp2 == 0.0f) { 
-         tmp2 = 1.0f; 
-     } 
-     desc->min_pitch = ldexpf(tmp1, 16); 
-     desc->max_pitch = ldexpf(tmp2, 16); 
-     if (sscanf(- ctx ->- data , "%lf,%lf%n", &- tmp1 , &- tmp2 , &- char_count ) != 2) {
 
-         return 0; 
-     } 
-     S3SoundBankReaderAdvance(ctx, char_count); 
-     S3SoundBankReaderNextLine(ctx); 
-     if (tmp1 == 0.0) { 
-         tmp1 = 1.0; 
-     } 
-     if (tmp2 == 0.0) { 
-         tmp2 = 1.0; 
-     } 
-     desc->min_speed = ldexpf(tmp1, 16); 
-     desc->max_speed = ldexpf(tmp2, 16); 
-     if (sscanf(- ctx ->- data , "%i%n", &- desc ->- special_fx , &- char_count ) != 1) {
 
-         return 0; 
-     } 
-     S3SoundBankReaderAdvance(ctx, char_count); 
-     S3SoundBankReaderNextLine(ctx); 
-     if (sscanf(- ctx ->- data , "%d%n", &- nmemory_proxies , &- char_count ) != 1) {
 
-         return 0; 
-     } 
-     S3SoundBankReaderAdvance(ctx, char_count); 
-     S3SoundBankReaderNextLine(ctx); 
-     desc->memory_proxy = -1; 
-     for (i = 0; i < nmemory_proxies; i++) { 
-         if (sscanf(- ctx ->- data , "%d%n", &- proxy_id , &- char_count ) != 1) {
 
-             return 0; 
-         } 
-         if (low_memory_mode == i + 1) { 
-             desc->memory_proxy = proxy_id; 
-         } 
-         S3SoundBankReaderAdvance(ctx, char_count); 
-         S3SoundBankReaderNextLine(ctx); 
-     } 
-     if ((desc->flags & 1) != 0 && desc->memory_proxy == -1) { 
-         if (desc->type == eS3_ST_midi) { 
-             desc->sound_data = NULL; 
-         } else if (S3LoadSample(desc->id) != 0) { 
-             printf("\nSound bank file: couldn't load '%s'\n",-  desc ->- filename );
 
-             ctx->data_len = 1; 
-             return 0; 
-         } 
-     } 
-     return 1; 
- } 
-   
- tS3_descriptor* S3CreateDescriptor(void) { 
-     tS3_descriptor* root; 
-     tS3_descriptor* d; 
-   
-     d = S3MemAllocate(sizeof(tS3_descriptor), kMem_S3_descriptor); 
-     if (!d) { 
-         gS3_last_error = eS3_error_memory; 
-         return NULL; 
-     } 
-     memset(- d , 0, sizeof(- tS3_descriptor ));
 
-     root = gS3_root_descriptor; 
-     gS3_root_descriptor->next = d; 
-     d->prev = root; 
-     gS3_root_descriptor = d; 
-     return d; 
- } 
-   
- int S3SoundBankReaderReadFilename(char** filename, tS3_soundbank_read_ctx* ctx, const char* dir_name) { 
-     char* data_start;          // [esp+10h] [ebp-Ch] 
-     unsigned int bytes_read;   // [esp+14h] [ebp-8h] 
-     unsigned int dir_name_len; // [esp+18h] [ebp-4h] 
-   
-     data_start = ctx->data; 
-     dir_name_len  = strlen(- dir_name );
-     while (ctx->data_len) { 
-             break; 
-         } 
-         S3SoundBankReaderAdvance(ctx, 1); 
-     } 
-     bytes_read = ctx->data - data_start; 
-     if (!bytes_read) { 
-         return 0; 
-     } 
-     *filename = S3MemAllocate(bytes_read + dir_name_len + 1, kMem_S3_scan_name); 
-     if (!*filename) { 
-         return 0; 
-     } 
-     memcpy(&(*- filename )[- dir_name_len ],-  data_start ,-  bytes_read );
 
-     (*filename)[bytes_read + dir_name_len] = '\0'; 
-     return 1; 
- } 
-   
- tS3_outlet* S3CreateOutlet(int unk1, int pChannel_count) { 
-     tS3_outlet* o; 
-     int nchannels; 
-     tS3_outlet* outlet; 
-     int channels_remaining; 
-   
-     // nchannels = (int)operator new(unk1, (void*)pChannel_count); 
-     nchannels = pChannel_count; 
-   
-     if (nchannels == 0) { 
-         gS3_last_error = eS3_error_channel_alloc; 
-         return NULL; 
-     } 
-     outlet = S3MemAllocate(sizeof(tS3_outlet), kMem_S3_outlet); 
-     if (outlet == NULL) { 
-         gS3_last_error = eS3_error_memory; 
-         return 0; 
-     } 
-     memset(- outlet , 0, sizeof(- tS3_outlet ));
 
-     channels_remaining = S3CreateOutletChannels(outlet, nchannels); 
-     if (channels_remaining == nchannels) { 
-         S3MemFree(outlet); 
-         return NULL; 
-     } 
-     o = gS3_outlets; 
-     if (gS3_outlets) { 
-         while (o->next) { 
-             o = o->next; 
-         } 
-         o->next = outlet; 
-         outlet->prev = o; 
-     } else { 
-         gS3_outlets = outlet; 
-     } 
-     outlet->max_channels = nchannels - channels_remaining; 
-     outlet->id = gS3_next_outlet_id; 
-     gS3_next_outlet_id++; 
-     outlet->independent_pitch = gS3_hardware_info.independent_pitch; 
-     gS3_noutlets++; 
-     return outlet; 
- } 
-   
- int S3CreateOutletChannels(tS3_outlet* outlet, int pChannel_count) { 
-     tS3_channel* chan;      // [esp+Ch] [ebp-8h] 
-     tS3_channel* last_chan; // [esp+10h] [ebp-4h] 
-   
-     last_chan = NULL; 
-     while (pChannel_count) { 
-         chan = (tS3_channel*)S3MemAllocate(sizeof(tS3_channel), kMem_S3_channel); 
-         if (!chan) { 
-             return pChannel_count; 
-         } 
-         memset(- chan , 0, sizeof(- tS3_channel ));
 
-         chan->owner_outlet = outlet; 
-   
-         if (S3CreateTypeStructs(chan) == 0) { 
-             S3MemFree(chan); 
-             return pChannel_count; 
-         } 
-         chan->volume_multiplier = 1.0f; 
-         if (last_chan) { 
-             last_chan->next = chan; 
-         } else { 
-             outlet->channel_list = chan; 
-         } 
-         last_chan = chan; 
-         pChannel_count--; 
-     } 
-     return 0; 
- } 
-   
- void S3ReleaseOutlet(tS3_outlet* outlet) { 
-     tS3_outlet* next; 
-     tS3_outlet* prev; 
-   
-     if (outlet) { 
-         S3UnbindChannels(outlet); 
-         prev = outlet->prev; 
-         next = outlet->next; 
-         if (prev != NULL) { 
-             prev->next = next; 
-         } else { 
-             gS3_outlets = outlet->next; 
-         } 
-         if (next != NULL) { 
-             next->prev = prev; 
-         } 
-         if (gS3_noutlets) { 
-             gS3_noutlets--; 
-             if (gS3_noutlets == 0) { 
-                 gS3_outlets = NULL; 
-             } 
-         } 
-         S3MemFree(outlet); 
-     } 
- } 
-   
- int S3UnbindChannels(tS3_outlet* outlet) { 
-     tS3_channel* chan; 
-     tS3_channel* next; 
-   
-     for (chan = outlet->channel_list; chan; chan = next) { 
-         next = chan->next; 
-         S3ReleaseTypeStructs(chan); 
-         if (gS3_unbound_channels) { 
-             gS3_last_unbound_channel->next = chan; 
-         } else { 
-             gS3_unbound_channels = chan; 
-         } 
-         gS3_last_unbound_channel = chan; 
-         memset(- chan , 0, sizeof(- tS3_channel ));
 
-     } 
-     outlet->channel_list = NULL; 
-     return 1; 
- } 
-   
- void S3ReleaseUnboundChannels(void) { 
-     tS3_channel* channel;      // [esp+Ch] [ebp-8h] 
-     tS3_channel* next_channel; // [esp+10h] [ebp-4h] 
-   
-     for (channel = gS3_unbound_channels; channel != NULL; channel = next_channel) { 
-         next_channel = channel->next; 
-         S3MemFree(channel); 
-     } 
- } 
-   
- tS3_channel* S3AllocateChannel(tS3_outlet* outlet, int priority) { 
-     tS3_channel* c;                    // [esp+Ch] [ebp-10h] 
-     int lowest_priority;               // [esp+10h] [ebp-Ch] MAPDST 
-     int this_priority;                 // [esp+14h] [ebp-8h] 
-     tS3_channel* lowest_priority_chan; // [esp+18h] [ebp-4h] 
-   
-     lowest_priority_chan = outlet->channel_list; 
-     c = outlet->channel_list; 
-     if (lowest_priority_chan == NULL) { 
-         return NULL; 
-     } 
-     while (c) { 
-         if (!c->active || c->needs_service) { 
-             if (!c->needs_service) { 
-                 c->active = 1; 
-                 return c; 
-             } 
-         } else { 
-             if (lowest_priority_chan->descriptor) { 
-                 lowest_priority = lowest_priority_chan->descriptor->priority 
-                     * (lowest_priority_chan->right_volume + lowest_priority_chan->left_volume + 1); 
-             } else { 
-                 lowest_priority = 0; 
-             } 
-             if (c->descriptor) { 
-                 this_priority = c->descriptor->priority * (c->left_volume + c->right_volume + 1); 
-             } else { 
-                 this_priority = 0; 
-             } 
-             if (this_priority <= lowest_priority) { 
-                 lowest_priority_chan = c; 
-             } 
-         } 
-         c = c->next; 
-     } 
-     if (!lowest_priority_chan->descriptor || lowest_priority_chan->needs_service) { 
-         lowest_priority = 0; 
-     } else { 
-         lowest_priority = lowest_priority_chan->descriptor->priority * (lowest_priority_chan->right_volume + lowest_priority_chan->left_volume + 1); 
-     } 
-     if (priority > lowest_priority && !lowest_priority_chan->needs_service) { 
-         lowest_priority_chan->termination_reason = 2; 
-         S3StopChannel(lowest_priority_chan); 
-         lowest_priority_chan->active = 1; 
-     } 
-   
-     return NULL; 
- } 
-   
- int S3StopChannel(tS3_channel* chan) { 
-     if (!chan->tag) { 
-         return eS3_error_bad_stag; 
-     } 
-     chan->termination_reason = eS3_tr_stopped; 
-     if (chan->active) { 
-         chan->needs_service = 1; 
-     } 
-     if (chan->type == eS3_ST_sample) { 
-         if (chan->sound_source_ptr) { 
-             chan->sound_source_ptr->tag = 0; 
-             chan->sound_source_ptr->channel = 0; 
-             chan->sound_source_ptr->volume = 0; 
-         } 
-         if (S3StopSample(chan) == 0) { 
-             return eS3_error_function_failed; 
-         } 
-     } else if (chan->type == eS3_ST_midi) { 
-         if (S3StopMIDI(chan) != 0) { 
-             return eS3_error_function_failed; 
-         } 
-     } else if (chan->type == eS3_ST_cda) { 
-         if (S3StopCDA(chan) != 0) { 
-             return eS3_error_function_failed; 
-         } 
-     } 
-   
-     if ((chan->descriptor->flags & 2) != 0) { 
-         S3ReleaseSound(chan->descriptor->id); 
-     } 
-     chan->repetitions = 1; 
-     return 0; 
- } 
-   
- tS3_sound_source* S3CreateSoundSourceBR(br_vector3* pPosition, br_vector3* pVelocity, tS3_outlet* pBound_outlet) { 
-     tS3_sound_source* source; // [esp+Ch] [ebp-4h] 
-   
-     if (!gS3_enabled) { 
-         return 0; 
-     } 
-     source = S3CreateSoundSource(pPosition, pVelocity, pBound_outlet); 
-     if (source != NULL) { 
-         source->brender_vector = 1; 
-     } 
-     return source; 
- } 
-   
- tS3_sound_source* S3CreateSoundSource(void* pPosition, void* pVelocity, tS3_outlet* pBound_outlet) { 
-     tS3_sound_source* src; // [esp+Ch] [ebp-8h] 
-     tS3_sound_source* s;   // [esp+10h] [ebp-4h] 
-   
-     src = S3MemAllocate(sizeof(tS3_sound_source), kMem_S3_source); 
-     if (src == NULL) { 
-         gS3_last_error = eS3_error_memory; 
-         return 0; 
-     } 
-     memset(- src , 0, sizeof(- tS3_sound_source ));
 
-     src->bound_outlet = pBound_outlet; 
-     src->position_ptr = pPosition; 
-     src->velocity_ptr = pVelocity; 
-     s = gS3_sound_sources; 
-     if (gS3_sound_sources) { 
-         while (s->next) { 
-             s = s->next; 
-         } 
-         s->next = src; 
-         src->prev = s; 
-     } else { 
-         gS3_sound_sources = src; 
-     } 
-     gS3_nsound_sources++; 
-     return src; 
- } 
-   
- int S3ReleaseSoundSource(tS3_sound_source* src) { 
-     tS3_sound_source* prev; // [esp+Ch] [ebp-8h] 
-     tS3_sound_source* next; // [esp+10h] [ebp-4h] 
-   
-     if (!gS3_enabled) { 
-         return 0; 
-     } 
-   
-     if (src) { 
-         prev = src->prev; 
-         next = src->next; 
-         if (prev) { 
-             prev->next = next; 
-         } else { 
-             gS3_sound_sources = src->next; 
-         } 
-         if (next) { 
-             next->prev = prev; 
-         } 
-         if (gS3_nsound_sources) { 
-             gS3_nsound_sources--; 
-             if (gS3_nsound_sources == 0) { 
-                 gS3_sound_sources = NULL; 
-             } 
-         } 
-         S3StopSoundSource(src); 
-         S3MemFree(src); 
-     } 
-     return 0; 
- } 
-   
- void S3Service(int inside_cockpit, int unk1) { 
-   
-     int now;        // [esp+Ch] [ebp-10h] 
-     tS3_channel* c; // [esp+10h] [ebp-Ch] 
-     tS3_outlet* o;  // [esp+14h] [ebp-8h] 
-     int v5;         // [esp+18h] [ebp-4h] 
-   
-     v5 = 0; 
-     gS3_inside_cockpit = inside_cockpit; 
-     if (!gS3_enabled) { 
-         return; 
-     } 
-     now = PDGetTotalTime(); 
-     gS3_service_time_delta = now - gS3_last_service_time; 
-     gS3_last_service_time = now; 
-     S3ServiceOutlets(); 
-     if (unk1 == 1) { 
-         S3UpdateListenerVectors(); 
-         S3ServiceAmbientSoundSources(); 
-     } 
-     for (o = gS3_outlets; o; o = o->next) { 
-         for (c = o->channel_list; c; c = c->next) { 
-             if (c->needs_service) { 
-                 c->needs_service = 0; 
-                 if (c->descriptor && c->descriptor->flags == 2) { 
-                     S3ReleaseSound(c->descriptor->id); 
-                 } 
-                 c->active = 0; 
-                 if (c->type != eS3_ST_midi) { 
-                     c->tag = 0; 
-                 } 
-             } else if (c->spatial_sound && c->active) { 
-                 if (S3UpdateSpatialSound(c)) { 
-                     if (c->sound_source_ptr && c->sound_source_ptr->ambient && !S3SoundStillPlaying(c->tag)) { 
-                         S3UpdateSoundSource(NULL, -1, c->sound_source_ptr, -1.0f, -1, -1, 0, -1, -1); 
-                     } 
-                 } else if (c->sound_source_ptr) { 
-                     if (c->sound_source_ptr->ambient) { 
-                         S3UpdateSoundSource(NULL, -1, c->sound_source_ptr, -1.0f, -1, -1, 0, -1, -1); 
-                     } 
-                 } else { 
-                     S3StopChannel(c); 
-                 } 
-             } else if (c->type == eS3_ST_midi && c->active) { 
-                 // sub_4124BE(c); 
-             } 
-             if (unk1 < 2 && gS3_last_service_time > dword_5216C0) { 
-                 v5 = 1; 
-                 if (!c->active && c->spatial_sound == 2) { 
-                     // null_unknown_libname_8();  /* no-op */ 
-                 } 
-             } 
-         } 
-     } 
-     if (v5) { 
-         dword_5216C0 = gS3_last_service_time; 
-     } 
- } 
-   
- void S3ServiceOutlets(void) { 
-     tS3_channel* c; // [esp+Ch] [ebp-8h] 
-     tS3_outlet* o;  // [esp+10h] [ebp-4h] 
-   
-     for (o = gS3_outlets; o; o = o->next) { 
-         for (c = o->channel_list; c; c = c->next) { 
-             S3ServiceChannel(c); 
-         } 
-     } 
- } 
-   
- int S3ServiceChannel(tS3_channel* chan) { 
-     if (chan->type == eS3_ST_sample) { 
-         if (AudioBackend_SoundIsPlaying(chan)) { 
-             return 1; 
-         } 
-         S3StopSample(chan); 
-         return 0; 
-     } else if (chan->type == eS3_ST_midi) { 
-         return !S3IsMIDIStopped(chan); 
-     } else if (chan->type == eS3_ST_cda) { 
-         return S3IsCDAPlaying(); 
-     } else { 
-         return 0; 
-     } 
- } 
-   
- void S3StopAllOutletSounds(void) { 
-     tS3_outlet* o; // [esp+Ch] [ebp-4h] 
-   
-     if (!gS3_enabled) { 
-         return; 
-     } 
-   
-     for (o = gS3_outlets; o; o = o->next) { 
-         S3StopOutletSound(o); 
-     } 
- } 
-   
- tS3_sound_tag S3StartSound(tS3_outlet* pOutlet, tS3_sound_id pSound) { 
-     int repetitions;      // eax 
-     tS3_channel* chan;    // [esp+14h] [ebp-Ch] 
-     tS3_descriptor* desc; // [esp+1Ch] [ebp-4h] 
-   
-     if (!gS3_enabled) { 
-         return 0; 
-     } 
-     if (!pOutlet) { 
-         gS3_last_error = eS3_error_bad_id; 
-         return 0; 
-     } 
-     desc = S3GetDescriptorByID(pSound); 
-     if (!desc) { 
-         gS3_last_error = eS3_error_bad_id; 
-         return 0; 
-     } 
-     memset(&- gS3_channel_template , 0, sizeof(- gS3_channel_template ));
 
-     S3CalculateRandomizedFields(&gS3_channel_template, desc); 
-     chan = S3AllocateChannel(pOutlet, desc->priority * (gS3_channel_template.right_volume + gS3_channel_template.left_volume + 1)); 
-     if (!chan) { 
-         gS3_last_error = eS3_error_channel_alloc; 
-         return 0; 
-     } 
-     chan->left_volume = gS3_channel_template.left_volume * chan->volume_multiplier; 
-     chan->right_volume = gS3_channel_template.right_volume * chan->volume_multiplier; 
-     chan->rate = gS3_channel_template.rate; 
-     if (desc->type == eS3_ST_sample && (!desc->sound_data || desc->flags == 2)) { 
-         if (!S3LoadSample(pSound)) { 
-             chan->needs_service = 1; 
-             gS3_last_error = eS3_error_load_sound; 
-             return 0; 
-         } 
-     } 
-     if (chan->descriptor && chan->descriptor->type == 1 && chan->descriptor->id != pSound) { 
-         S3ReleaseMIDI(chan->tag); 
-     } 
-     chan->spatial_sound = 0; 
-     chan->sound_source_ptr = 0; 
-     chan->descriptor = desc; 
-     chan->type = desc->type; 
-     repetitions = desc->repeats; 
-     if (repetitions <= 0) { 
-         repetitions = 0; 
-     } 
-     chan->repetitions = repetitions; 
-     chan->needs_service = 0; 
-     chan->termination_reason = eS3_tr_natural; 
-     chan->tag = S3GenerateTag(pOutlet); 
-     if (desc->type == eS3_ST_midi && !desc->sound_data) { 
-         if (S3MIDILoadSong(chan)) { 
-             chan->needs_service = 1; 
-             return 0; 
-         } 
-     } 
-     if (chan->type == eS3_ST_sample) { 
-         S3ExecuteSampleFilterFuncs(chan); 
-         if (S3PlaySample(chan) == 0) { 
-             gS3_last_error = eS3_error_start_sound; 
-             chan->needs_service = 1; 
-             return 0; 
-         } 
-     } else if (chan->type == eS3_ST_midi) { 
-         if (S3PlayMIDI(chan)) { 
-             chan->needs_service = 1; 
-             gS3_last_error = eS3_error_start_song; 
-             return 0; 
-         } 
-         S3SetMIDIVolume(chan); 
-     } else if (chan->type == eS3_ST_cda) { 
-         if (S3PlayCDA(chan)) { 
-             chan->needs_service = 1; 
-             gS3_last_error = eS3_error_start_cda; 
-             return 0; 
-         } 
-     } 
-   
-     return chan->tag; 
- } 
-   
- tS3_sound_tag S3StartSound2(tS3_outlet* pOutlet, tS3_sound_id pSound, tS3_repeats pRepeats, tS3_volume pLVolume, tS3_volume pRVolume, tS3_pitch pPitch, tS3_speed pSpeed) { 
-     tS3_channel* chan;    // [esp+30h] [ebp-Ch] 
-     tS3_descriptor* desc; // [esp+38h] [ebp-4h] 
-   
-     if (!gS3_enabled) { 
-         return 0; 
-     } 
-     desc = S3GetDescriptorByID(pSound); 
-     if (!desc) { 
-         gS3_last_error = eS3_error_bad_id; 
-         return 0; 
-     } 
-     if (pLVolume < 0) { 
-         pLVolume = 128; 
-     } 
-     if (pRVolume < 0) { 
-         pRVolume = 128; 
-     } 
-     if (pLVolume > 255) { 
-         pLVolume = 255; 
-     } 
-     if (pRVolume > 255) { 
-         pRVolume = 255; 
-     } 
-     chan = S3AllocateChannel(pOutlet, desc->priority * (pLVolume + pRVolume + 1)); 
-     if (chan == NULL) { 
-         gS3_last_error = eS3_error_channel_alloc; 
-         return 0; 
-     } 
-     if (desc->type == eS3_ST_sample) { 
-         if (desc->sound_data == NULL && (!S3LoadSample(pSound) || (desc->flags & 2) != 0)) { 
-             chan->needs_service = 1; 
-             gS3_last_error = eS3_error_load_sound; 
-             return 0; 
-         } 
-     } 
-   
-     if (chan->descriptor && chan->descriptor->type == eS3_ST_midi) { 
-         if (chan->descriptor->id != pSound) { 
-             S3ReleaseMIDI(chan->tag); 
-         } 
-     } 
-     chan->spatial_sound = 0; 
-     chan->descriptor = desc; 
-     chan->needs_service = 0; 
-     chan->termination_reason = eS3_tr_natural; 
-     chan->type = desc->type; 
-     chan->sound_source_ptr = NULL; 
-     chan->repetitions = MAX(pRepeats, 0); 
-     S3CalculateRandomizedFields(chan, desc); 
-     chan->left_volume = pLVolume * chan->volume_multiplier; 
-     chan->right_volume = pRVolume * chan->volume_multiplier; 
-     chan->tag = S3GenerateTag(pOutlet); 
-     if (pPitch == -1) { 
-         pPitch = 0x10000; 
-     } 
-     if (pSpeed == -1) { 
-         pSpeed = 0x10000; 
-     } 
-     chan->rate = ldexpf(pPitch, -16) * chan->rate; 
-     if (!pOutlet->independent_pitch) { 
-         chan->rate = ldexpf(pSpeed, -16) * chan->rate; 
-     } 
-     if (desc->type == eS3_ST_midi && desc->sound_data == NULL && S3MIDILoadSong(chan)) { 
-         chan->needs_service = 1; 
-         return 0; 
-     } 
-   
-     switch (chan->type) { 
-     case eS3_ST_sample: 
-         S3ExecuteSampleFilterFuncs(chan); 
-         if (!S3PlaySample(chan)) { 
-             chan->needs_service = 1; 
-             gS3_last_error = eS3_error_start_sound; 
-             return 0; 
-         } 
-         break; 
-   
-     case eS3_ST_midi: 
-         if (S3PlayMIDI(chan)) { 
-             chan->needs_service = 1; 
-             gS3_last_error = eS3_error_start_song; 
-             return 0; 
-         } 
-         S3SetMIDIVolume(chan); 
-         break; 
-   
-     case eS3_ST_cda: 
-         if (S3PlayCDA(chan)) { 
-             chan->needs_service = 1; 
-             gS3_last_error = eS3_error_start_cda; 
-             return 0; 
-         } 
-         break; 
-     } 
-   
-     return chan->tag; 
- } 
-   
- void S3CalculateRandomizedFields(tS3_channel* chan, tS3_descriptor* desc) { 
-     int vol; // eax 
-   
-     vol = S3IRandomBetween(desc->min_volume, desc->max_volume, 128); 
-     chan->left_volume = vol; 
-     chan->right_volume = vol; 
-     if (desc->type == eS3_ST_sample) { 
- #if defined(DETHRACE_FIX_BUGS) 
-         /* Avoid a possible NULL pointer dereference. */ 
-         if (desc->sound_data == NULL) { 
-             chan->rate = desc->min_pitch; 
-             return; 
-         } 
- #endif 
-         chan->rate = S3IRandomBetweenLog(desc->min_pitch, desc->max_pitch, ((tS3_sample*)desc->sound_data)->rate); 
-     } 
- } 
-   
- // duplicate of S3IRandomBetween2 
- int S3IRandomBetween(int pMin, int pMax, int pDefault) { 
-     if (pMin == -1) { 
-         return pDefault; 
-     } 
-     if (pMax <= pMin) { 
-         return pMin; 
-     } 
-     return rand() % (- pMax  --  pMin ) +-  pMin ;
 
- } 
-   
- // duplicate of S3IRandomBetweenLog2 
- int S3IRandomBetweenLog(int pMin, int pMax, int pDefault) { 
-     float v4; // st7 
-   
-     if (pMin == -1 || pMin >= pMax) { 
-         return pDefault; 
-     } 
-     v4  =-  S3FRandomBetween (log(- pMin ), log(- pMax ));
- } 
-   
- // duplicate of S3FRandomBetween2 
- double S3FRandomBetween(double pMin, double pMax) { 
-     return (double)rand() * (- pMax  --  pMin ) / (double)- RAND_MAX  +-  pMin ;
 
- } 
-   
- int S3GenerateTag(tS3_outlet* outlet) { 
-     gS3_tag_seed += 256; 
-     return gS3_tag_seed | outlet->id; 
- } 
-   
- int S3SoundStillPlaying(tS3_sound_tag pTag) { 
-     tS3_channel* chan; 
-   
-     if (!gS3_enabled) { 
-         return 0; 
-     } 
-     if (!pTag) { 
-         return 0; 
-     } 
-     chan = S3GetChannelForTag(pTag); 
-     if (!chan) { 
-         return 0; 
-     } 
-     return S3ServiceChannel(chan) != 0; 
- } 
-   
- int S3ChangePitchSpeed(tS3_sound_tag pTag, tS3_pitch pNew_pitch) { 
-     tS3_channel* chan; 
-   
-     if (!gS3_enabled) { 
-         return 0; 
-     } 
-     if (pNew_pitch == -1) { 
-         pNew_pitch = 0x10000; 
-     } 
-     chan = S3GetChannelForTag(pTag); 
-     if (chan == NULL) { 
-         return eS3_error_bad_stag; 
-     } 
-     if (chan->type != eS3_ST_sample) { 
-         return 0; 
-     } 
-     chan ->- rate  = ldexp(- pNew_pitch , -16) * ((- tS3_sample *)- chan ->- descriptor ->- sound_data )->- rate ;
-     if (S3SyncSampleRate(chan)) { 
-         return 0; 
-     } else { 
-         return eS3_error_function_failed; 
-     } 
- } 
-   
- int S3StopSound(tS3_sound_tag pTag) { 
-     tS3_channel* chan; // [esp+Ch] [ebp-4h] 
-   
-     if (!gS3_enabled) { 
-         return 0; 
-     } 
-     if (!pTag) { 
-         return eS3_error_bad_stag; 
-     } 
-     chan = S3GetChannelForTag(pTag); 
-     if (!chan) { 
-         return eS3_error_bad_stag; 
-     } 
-     chan->termination_reason = eS3_tr_stopped; 
-     chan->initial_volume = 0; 
-     if (chan->active) { 
-         chan->needs_service = 1; 
-     } 
-     if (chan->type == eS3_ST_sample) { 
-         if (chan->sound_source_ptr) { 
-             chan->sound_source_ptr->tag = 0; 
-             chan->sound_source_ptr->channel = NULL; 
-             chan->sound_source_ptr->volume = 0; 
-         } 
-         if (!S3StopSample(chan)) { 
-             return eS3_error_function_failed; 
-         } 
-     } else if (chan->type == eS3_ST_midi) { 
-         if (S3StopMIDI(chan)) { 
-             return eS3_error_function_failed; 
-         } 
-     } else if (chan->type == eS3_ST_cda) { 
-         if (S3StopCDA(chan)) { 
-             return eS3_error_function_failed; 
-         } 
-     } 
-   
-     if ((chan->descriptor->flags & 2) != 0) { 
-         S3ReleaseSound(chan->descriptor->id); 
-     } 
-     chan->repetitions = 1; 
-     return 0; 
- } 
-   
- int S3StopOutletSound(tS3_outlet* pOutlet) { 
-     tS3_channel* c; // [esp+Ch] [ebp-4h] 
-   
-     if (!gS3_enabled) { 
-         return 0; 
-     } 
-     for (c = pOutlet->channel_list; c; c = c->next) { 
-         // null_unknown_libname_8(); 
-         if (c->active) { 
-             c->spatial_sound = 0; 
-             S3StopChannel(c); 
-             c->needs_service = 1; 
-         } 
-     } 
-     return 0; 
- } 
-   
- char* S3GetCurrentDir(void) { 
-     if (!gS3_have_current_dir) { 
-         if (getcwd(gS3_current_dir, 260) == NULL) { 
-             LOG_PANIC("failed to call getcwd"); // added by dethrace 
-         }; 
-         gS3_have_current_dir = 1; 
-     } 
-     return gS3_current_dir; 
- } 
-   
- tS3_descriptor* S3GetDescriptorByID(tS3_sound_tag id) { 
-     tS3_descriptor* d; // [esp+Ch] [ebp-4h] 
-   
-     for (d = gS3_descriptors;; d = d->next) { 
-         if (!d) { 
-             return 0; 
-         } 
-         if (d->id == id) { 
-             break; 
-         } 
-     } 
-     if (d->memory_proxy < 0) { 
-         return d; 
-     } else { 
-         return S3GetDescriptorByID(d->memory_proxy); 
-     } 
- } 
-   
- int S3SetOutletVolume(tS3_outlet* pOutlet, tS3_volume pVolume) { 
-     tS3_channel* c; // [esp+10h] [ebp-4h] 
-   
-     if (!gS3_enabled) { 
-         return 0; 
-     } 
-     if (pVolume > 255) { 
-         pVolume = 255; 
-     } 
-     if (pVolume < 10) { 
-         pVolume = 10; 
-     } 
-     if (!pOutlet) { 
-         return 0; 
-     } 
-     for (c = pOutlet->channel_list; c; c = c->next) { 
-         c->volume_multiplier = pVolume / 150.0f; 
-         if (c->active) { 
-             S3ChangeVolume(c->tag, pVolume); 
-         } 
-     } 
-     return 0; 
- } 
-   
- tS3_channel* S3GetChannelForTag(tS3_sound_tag tag) { 
-     tS3_channel* c; // [esp+Ch] [ebp-Ch] 
-     tS3_outlet* o;  // [esp+14h] [ebp-4h] 
-   
-     if (!tag) { 
-         return 0; 
-     } 
-     for (o = gS3_outlets; o && o->id != (uint8_t)tag; o = o->next) { 
-         ; 
-     } 
-     if (!o) { 
-         return 0; 
-     } 
-     for (c = o->channel_list; c; c = c->next) { 
-         if (c->tag == tag) { 
-             return c; 
-         } 
-     } 
-     return 0; 
- } 
-   
- int S3ChangeVolume(tS3_sound_tag pTag, tS3_volume pVolume) { 
-     tS3_channel* chan; // [esp+14h] [ebp-4h] 
-   
-     if (!gS3_enabled) { 
-         return 0; 
-     } 
-     chan = S3GetChannelForTag(pTag); 
-     if (!chan) { 
-         return eS3_error_bad_stag; 
-     } 
-     if (pVolume < 0) { 
-         pVolume = 128; 
-     } 
-     if (pVolume > 255) { 
-         pVolume = 255; 
-     } 
-     if (chan->type == eS3_ST_sample) { 
-         chan->left_volume = pVolume * chan->volume_multiplier; 
-         chan->right_volume = pVolume * chan->volume_multiplier; 
-         if (!S3SyncSampleVolumeAndPan(chan)) { 
-             return eS3_error_function_failed; 
-         } 
-     } else if (chan->type == eS3_ST_midi) { 
-         S3SetMIDIVolume(chan); 
-     } else if (chan->type == eS3_ST_cda) { 
-         S3SetCDAVolume(chan, pVolume); 
-     } 
-   
-     return 0; 
- } 
-