mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-22 06:23:04 +01:00
386 lines
8.0 KiB
C
386 lines
8.0 KiB
C
/*****************************************************************************
|
|
* Copyright (c) 2014 Ted John
|
|
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
|
*
|
|
* This file is part of OpenRCT2.
|
|
*
|
|
* OpenRCT2 is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*****************************************************************************/
|
|
|
|
#include "../addresses.h"
|
|
#include "../config.h"
|
|
#include "../interface/viewport.h"
|
|
#include "../interface/window.h"
|
|
#include "../localisation/language.h"
|
|
#include "../platform/platform.h"
|
|
#include "../ride/ride.h"
|
|
#include "../world/map.h"
|
|
#include "../world/sprite.h"
|
|
#include "audio.h"
|
|
#include "mixer.h"
|
|
#include "../openrct2.h"
|
|
#include "../util/util.h"
|
|
|
|
audio_device *gAudioDevices = NULL;
|
|
int gAudioDeviceCount;
|
|
void *gCrowdSoundChannel = 0;
|
|
bool gGameSoundsOff = false;
|
|
void *gRainSoundChannel = 0;
|
|
rct_ride_music gRideMusicList[AUDIO_MAX_RIDE_MUSIC];
|
|
rct_ride_music_info *gRideMusicInfoList[NUM_DEFAULT_MUSIC_TRACKS];
|
|
rct_ride_music_params gRideMusicParamsList[AUDIO_MAX_RIDE_MUSIC];
|
|
rct_ride_music_params *gRideMusicParamsListEnd;
|
|
void *gTitleMusicChannel = 0;
|
|
rct_vehicle_sound gVehicleSoundList[AUDIO_MAX_VEHICLE_SOUNDS];
|
|
rct_vehicle_sound_params gVehicleSoundParamsList[AUDIO_MAX_VEHICLE_SOUNDS];
|
|
rct_vehicle_sound_params *gVehicleSoundParamsListEnd;
|
|
|
|
void audio_init()
|
|
{
|
|
int result = SDL_Init(SDL_INIT_AUDIO);
|
|
if (result >= 0)
|
|
return;
|
|
|
|
log_fatal("SDL_Init %s", SDL_GetError());
|
|
exit(-1);
|
|
}
|
|
|
|
void audio_quit()
|
|
{
|
|
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
|
}
|
|
|
|
void audio_populate_devices()
|
|
{
|
|
if (gAudioDevices != NULL)
|
|
free(gAudioDevices);
|
|
|
|
gAudioDeviceCount = SDL_GetNumAudioDevices(SDL_FALSE);
|
|
if (gAudioDeviceCount <= 0)
|
|
return;
|
|
|
|
gAudioDeviceCount++;
|
|
gAudioDevices = malloc(gAudioDeviceCount * sizeof(audio_device));
|
|
safe_strncpy(
|
|
gAudioDevices[0].name,
|
|
language_get_string(5510),
|
|
AUDIO_DEVICE_NAME_SIZE
|
|
);
|
|
|
|
for (int i = 1; i < gAudioDeviceCount; i++) {
|
|
const char *utf8Name = SDL_GetAudioDeviceName(i - 1, SDL_FALSE);
|
|
if (utf8Name == NULL)
|
|
utf8Name = language_get_string(5511);
|
|
|
|
safe_strncpy(gAudioDevices[i].name, utf8Name, AUDIO_DEVICE_NAME_SIZE);
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* rct2: 0x006BB76E
|
|
*
|
|
* @param sound_id (eax)
|
|
* @param ebx (ebx)
|
|
* @param x (cx)
|
|
* @param y (dx)
|
|
* @param z (bp)
|
|
*/
|
|
int audio_sound_play_panned(int soundId, int ebx, sint16 x, sint16 y, sint16 z)
|
|
{
|
|
if (gGameSoundsOff)
|
|
return 0;
|
|
|
|
int volume = 0;
|
|
if (ebx == 0x8001) {
|
|
int volumeDown = 0;
|
|
rct_map_element *element = map_get_surface_element_at(x / 32, y / 32);
|
|
if (element && (element->base_height * 8) - 5 > z)
|
|
volumeDown = 10;
|
|
|
|
sint16 rx;
|
|
sint16 ry;
|
|
switch (get_current_rotation()) {
|
|
case 0:
|
|
rx = y - x;
|
|
ry = ((y + x) / 2) - z;
|
|
break;
|
|
case 1:
|
|
rx = -x - y;
|
|
ry = ((y - x) / 2) - z;
|
|
break;
|
|
case 2:
|
|
rx = x - y;
|
|
ry = ((-y - x) / 2) - z;
|
|
break;
|
|
case 3:
|
|
rx = y + x;
|
|
ry = ((x - y) / 2) - z;
|
|
break;
|
|
}
|
|
|
|
rct_window *window = RCT2_GLOBAL(
|
|
RCT2_ADDRESS_NEW_WINDOW_PTR,
|
|
rct_window*
|
|
);
|
|
while (true) {
|
|
window--;
|
|
if (window < RCT2_ADDRESS(RCT2_ADDRESS_WINDOW_LIST, rct_window)) {
|
|
break;
|
|
}
|
|
rct_viewport *viewport = window->viewport;
|
|
if (viewport && viewport->flags & VIEWPORT_FLAG_SOUND_ON) {
|
|
sint16 vy = ry - viewport->view_y;
|
|
sint16 vx = rx - viewport->view_x;
|
|
ebx = viewport->x + (vx >> viewport->zoom);
|
|
volume = RCT2_ADDRESS(0x0099282C, int)[soundId]
|
|
+ ((-1024 * viewport->zoom - 1) << volumeDown) + 1;
|
|
|
|
if (vy < 0
|
|
|| vy >= viewport->view_height
|
|
|| vx < 0
|
|
|| vx >= viewport->view_width
|
|
|| volume < -10000)
|
|
return soundId;
|
|
}
|
|
}
|
|
}
|
|
|
|
int pan = 0;
|
|
if (ebx != (sint16)0x8000) {
|
|
int x2 = ebx << 16;
|
|
uint16 screenWidth = max(
|
|
64,
|
|
RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16)
|
|
);
|
|
|
|
pan = ((x2 / screenWidth) - 0x8000) >> 4;
|
|
}
|
|
|
|
Mixer_Play_Effect(
|
|
soundId,
|
|
MIXER_LOOP_NONE,
|
|
DStoMixerVolume(volume),
|
|
DStoMixerPan(pan),
|
|
1,
|
|
1
|
|
);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* rct2: 0x006BD0F8
|
|
*/
|
|
void audio_start_title_music()
|
|
{
|
|
if (gGameSoundsOff || !RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TITLE_DEMO) {
|
|
audio_stop_title_music();
|
|
return;
|
|
}
|
|
|
|
if (gTitleMusicChannel)
|
|
return;
|
|
|
|
int pathId;
|
|
switch (gConfigSound.title_music) {
|
|
case 1:
|
|
pathId = PATH_ID_CSS50;
|
|
break;
|
|
case 2:
|
|
pathId = PATH_ID_CSS17;
|
|
break;
|
|
case 3:
|
|
if (rand() & 1)
|
|
pathId = PATH_ID_CSS50;
|
|
else
|
|
pathId = PATH_ID_CSS17;
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
gTitleMusicChannel = Mixer_Play_Music(pathId, MIXER_LOOP_INFINITE, true);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* rct2: 0x006BCA9F
|
|
*/
|
|
void audio_stop_ride_music()
|
|
{
|
|
for (int i = 0; i < AUDIO_MAX_RIDE_MUSIC; i++) {
|
|
rct_ride_music *rideMusic = &gRideMusicList[i];
|
|
if (rideMusic->ride_id == (uint8)-1)
|
|
continue;
|
|
|
|
if (rideMusic->sound_channel) {
|
|
Mixer_Stop_Channel(rideMusic->sound_channel);
|
|
}
|
|
|
|
rideMusic->ride_id = -1;
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* rct2: 0x006BD07F
|
|
*/
|
|
void audio_stop_crowd_sound()
|
|
{
|
|
if (gCrowdSoundChannel) {
|
|
Mixer_Stop_Channel(gCrowdSoundChannel);
|
|
gCrowdSoundChannel = 0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* rct2: 0x006BD0BD
|
|
*/
|
|
void audio_stop_title_music()
|
|
{
|
|
if (gTitleMusicChannel) {
|
|
Mixer_Stop_Channel(gTitleMusicChannel);
|
|
gTitleMusicChannel = 0;
|
|
}
|
|
}
|
|
|
|
void stop_rain_sound()
|
|
{
|
|
if (gRainSoundChannel) {
|
|
Mixer_Stop_Channel(gRainSoundChannel);
|
|
gRainSoundChannel = 0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* rct2: 0x006BA8E0
|
|
*/
|
|
void audio_init1()
|
|
{
|
|
int deviceNum = 0;
|
|
audio_init2(deviceNum);
|
|
|
|
for (int m = 0; m < countof(gRideMusicInfoList); m++) {
|
|
rct_ride_music_info *rideMusicInfo = gRideMusicInfoList[m];
|
|
const utf8 *path = get_file_path(rideMusicInfo->path_id);
|
|
SDL_RWops *file = SDL_RWFromFile(path, "rb");
|
|
if (file == NULL)
|
|
continue;
|
|
|
|
uint32 head;
|
|
SDL_RWread(file, &head, sizeof(head), 1);
|
|
SDL_RWclose(file);
|
|
RCT2_GLOBAL(0x014241BC, uint32) = 0;
|
|
if (head == 0x78787878)
|
|
rideMusicInfo->length = 0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* rct2: 0x006BA9B5
|
|
*/
|
|
void audio_init2(int device)
|
|
{
|
|
audio_close();
|
|
for (int i = 0; i < AUDIO_MAX_VEHICLE_SOUNDS; i++) {
|
|
rct_vehicle_sound *vehicleSound = &gVehicleSoundList[i];
|
|
vehicleSound->id = -1;
|
|
}
|
|
|
|
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SOUND_DEVICE, uint32) = device;
|
|
config_save_default();
|
|
for (int i = 0; i < AUDIO_MAX_RIDE_MUSIC; i++) {
|
|
rct_ride_music *rideMusic = &gRideMusicList[i];
|
|
rideMusic->ride_id = -1;
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* rct2: 0x006BAB21
|
|
*/
|
|
void audio_close()
|
|
{
|
|
audio_stop_crowd_sound();
|
|
audio_stop_title_music();
|
|
audio_stop_ride_music();
|
|
stop_rain_sound();
|
|
RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SOUND_DEVICE, uint32) = -1;
|
|
}
|
|
|
|
/* rct2: 0x006BAB8A */
|
|
void audio_toggle_all_sounds(){
|
|
gConfigSound.sound = !gConfigSound.sound;
|
|
if (gConfigSound.sound)
|
|
audio_unpause_sounds();
|
|
else {
|
|
audio_stop_title_music();
|
|
audio_pause_sounds();
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* rct2: 0x006BABB4
|
|
*/
|
|
void audio_pause_sounds()
|
|
{
|
|
gGameSoundsOff = true;
|
|
audio_stop_vehicle_sounds();
|
|
audio_stop_ride_music();
|
|
audio_stop_crowd_sound();
|
|
stop_rain_sound();
|
|
}
|
|
|
|
/**
|
|
*
|
|
* rct2: 0x006BABD8
|
|
*/
|
|
void audio_unpause_sounds()
|
|
{
|
|
gGameSoundsOff = false;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* rct2: 0x006BABDF
|
|
*/
|
|
void audio_stop_vehicle_sounds()
|
|
{
|
|
if (gOpenRCT2Headless
|
|
|| RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SOUND_DEVICE, sint32) == -1)
|
|
return;
|
|
|
|
for (int i = 0; i < countof(gVehicleSoundList); i++) {
|
|
rct_vehicle_sound *vehicleSound = &gVehicleSoundList[i];
|
|
if (vehicleSound->id == 0xFFFF)
|
|
continue;
|
|
|
|
if (vehicleSound->sound1_id != 0xFFFF) {
|
|
Mixer_Stop_Channel(vehicleSound->sound1_channel);
|
|
}
|
|
|
|
if (vehicleSound->sound2_id != 0xFFFF) {
|
|
Mixer_Stop_Channel(vehicleSound->sound2_channel);
|
|
}
|
|
|
|
vehicleSound->id = 0xFFFF;
|
|
}
|
|
}
|