From 8b2e4e970ad3379fb294934e7720128986220d0e Mon Sep 17 00:00:00 2001 From: peter1138 Date: Wed, 27 Sep 2006 18:17:01 +0000 Subject: (svn r6532) - Feature: Add support for NewGRF sound effects. Currently sound priority isn't supported. --- Makefile | 1 + aircraft_cmd.c | 9 ++- newgrf.c | 189 +++++++++++++++++++++++++++++++++++++++++++++++++++- newgrf.h | 2 + newgrf_callbacks.h | 3 + newgrf_engine.c | 2 +- newgrf_engine.h | 1 + newgrf_sound.c | 73 ++++++++++++++++++++ newgrf_sound.h | 25 +++++++ openttd.vcproj | 6 ++ openttd_vs80.vcproj | 8 +++ roadveh_cmd.c | 17 +++-- ship_cmd.c | 11 ++- sound.c | 40 +++++++---- sound.h | 12 ++++ train_cmd.c | 15 ++++- tunnelbridge_cmd.c | 4 +- vehicle.c | 17 +++++ vehicle.h | 1 + 19 files changed, 404 insertions(+), 32 deletions(-) create mode 100644 newgrf_sound.c create mode 100644 newgrf_sound.h diff --git a/Makefile b/Makefile index c8afd3685..a7da3ac32 100644 --- a/Makefile +++ b/Makefile @@ -697,6 +697,7 @@ SRCS += network_udp.c SRCS += newgrf.c SRCS += newgrf_cargo.c SRCS += newgrf_engine.c +SRCS += newgrf_sound.c SRCS += newgrf_spritegroup.c SRCS += newgrf_station.c SRCS += newgrf_text.c diff --git a/aircraft_cmd.c b/aircraft_cmd.c index e9ed824b4..d7c8a31bd 100644 --- a/aircraft_cmd.c +++ b/aircraft_cmd.c @@ -23,6 +23,7 @@ #include "newgrf_engine.h" #include "newgrf_callbacks.h" #include "newgrf_text.h" +#include "newgrf_sound.h" #include "date.h" static bool AirportMove(Vehicle *v, const AirportFTAClass *Airport); @@ -858,7 +859,9 @@ static void ServiceAircraft(Vehicle *v) static void PlayAircraftSound(const Vehicle* v) { - SndPlayVehicleFx(AircraftVehInfo(v->engine_type)->sfx, v); + if (!PlayVehicleSound(v, VSE_START)) { + SndPlayVehicleFx(AircraftVehInfo(v->engine_type)->sfx, v); + } } static bool UpdateAircraftSpeed(Vehicle *v) @@ -1426,7 +1429,9 @@ static void AircraftLand(Vehicle *v) static void AircraftLandAirplane(Vehicle *v) { AircraftLand(v); - SndPlayVehicleFx(SND_17_SKID_PLANE, v); + if (!PlayVehicleSound(v, VSE_TOUCHDOWN)) { + SndPlayVehicleFx(SND_17_SKID_PLANE, v); + } MaybeCrashAirplane(v); } diff --git a/newgrf.c b/newgrf.c index 6a552066d..0db17f0e7 100644 --- a/newgrf.c +++ b/newgrf.c @@ -25,6 +25,8 @@ #include "table/sprites.h" #include "date.h" #include "currency.h" +#include "sound.h" +#include "newgrf_sound.h" #include "newgrf_spritegroup.h" /* TTDPatch extended GRF format codec @@ -58,6 +60,14 @@ static uint32 _ttdpatch_flags[8]; static byte *_preload_sprite = NULL; +typedef enum GrfDataType { + GDT_SOUND, +} GrfDataType; + +static byte _grf_data_blocks; +static GrfDataType _grf_data_type; + + typedef enum grfspec_feature { GSF_TRAIN, GSF_ROAD, @@ -1182,6 +1192,67 @@ static bool GlobalVarChangeInfo(uint gvid, int numinfo, int prop, byte **bufp, i return ret; } +static bool SoundEffectChangeInfo(uint sid, int numinfo, int prop, byte **bufp, int len) +{ + byte *buf = *bufp; + int i; + bool ret = false; + + if (_cur_grffile->sound_offset == 0) { + grfmsg(GMS_WARN, "SoundEffectChangeInfo: No effects defined, skipping."); + return false; + } + + switch (prop) { + case 0x08: /* Relative volume */ + FOR_EACH_OBJECT { + uint sound = sid + i + _cur_grffile->sound_offset - GetNumOriginalSounds(); + + if (sound >= GetNumSounds()) { + grfmsg(GMS_WARN, "SoundEffectChangeInfo: Sound %d not defined (max %d)", sound, GetNumSounds()); + } else { + GetSound(sound)->volume = grf_load_byte(&buf); + } + } + break; + + case 0x09: /* Priority */ + FOR_EACH_OBJECT { + uint sound = sid + i + _cur_grffile->sound_offset - GetNumOriginalSounds(); + + if (sound >= GetNumSounds()) { + grfmsg(GMS_WARN, "SoundEffectChangeInfo: Sound %d not defined (max %d)", sound, GetNumSounds()); + } else { + GetSound(sound)->priority = grf_load_byte(&buf); + } + } + break; + + case 0x0A: /* Override old sound */ + FOR_EACH_OBJECT { + uint sound = sid + i + _cur_grffile->sound_offset - GetNumOriginalSounds(); + uint orig_sound = grf_load_byte(&buf); + + if (sound >= GetNumSounds() || orig_sound >= GetNumSounds()) { + grfmsg(GMS_WARN, "SoundEffectChangeInfo: Sound %d or %d not defined (max %d)", sound, orig_sound, GetNumSounds()); + } else { + FileEntry *newfe = GetSound(sound); + FileEntry *oldfe = GetSound(orig_sound); + + /* Literally copy the data of the new sound over the original */ + memcpy(oldfe, newfe, sizeof(*oldfe)); + } + } + break; + + default: + ret = true; + } + + *bufp = buf; + return ret; +} + /* Action 0x00 */ static void FeatureChangeInfo(byte *buf, int len) { @@ -1214,7 +1285,7 @@ static void FeatureChangeInfo(byte *buf, int len) /* GSF_INDUSTRYTILES */NULL, /* GSF_INDUSTRIES */ NULL, /* GSF_CARGOS */ NULL, - /* GSF_SOUNDFX */ NULL, + /* GSF_SOUNDFX */ SoundEffectChangeInfo, }; uint8 feature; @@ -2708,6 +2779,113 @@ static void DefineGotoLabel(byte *buf, int len) grfmsg(GMS_NOTICE, "DefineGotoLabel: GOTO target with label 0x%02X", label->label); } +/* Action 0x11 */ +static void GRFSound(byte *buf, int len) +{ + /* <11> + * + * W num Number of sound files that follow */ + + uint16 num; + + check_length(len, 1, "GRFSound"); + buf++; + num = grf_load_word(&buf); + + _grf_data_blocks = num; + _grf_data_type = GDT_SOUND; + + if (_cur_grffile->sound_offset == 0) _cur_grffile->sound_offset = GetNumSounds(); +} + +static void LoadGRFSound(byte *buf, int len) +{ + byte *buf_start = buf; + FileEntry *se; + + /* Allocate a sound entry. This is done even if the data is not loaded + * so that the indices used elsewhere are still correct. */ + se = AllocateFileEntry(); + + if (grf_load_dword(&buf) != 'FFIR') { + grfmsg(GMS_WARN, "LoadGRFSound: Missing RIFF header"); + return; + } + + /* Size of file -- we ignore this */ + grf_load_dword(&buf); + + if (grf_load_dword(&buf) != 'EVAW') { + grfmsg(GMS_WARN, "LoadGRFSound: Invalid RIFF type"); + return; + } + + for (;;) { + uint32 tag = grf_load_dword(&buf); + uint32 size = grf_load_dword(&buf); + + switch (tag) { + case ' tmf': /* 'fmt ' */ + /* Audio format, must be 1 (PCM) */ + if (grf_load_word(&buf) != 1) { + grfmsg(GMS_WARN, "LoadGRFSound: Invalid audio format"); + return; + } + se->channels = grf_load_word(&buf); + se->rate = grf_load_dword(&buf); + grf_load_dword(&buf); + grf_load_word(&buf); + se->bits_per_sample = grf_load_word(&buf); + + /* Consume any extra bytes */ + for (; size > 16; size--) grf_load_byte(&buf); + break; + + case 'atad': /* 'data' */ + se->file_size = size; + se->file_offset = FioGetPos() - (len - (buf - buf_start)) + 1; + se->file_offset |= _file_index << 24; + + /* Set default volume and priority */ + se->volume = 0x80; + se->priority = 0; + + grfmsg(GMS_NOTICE, "LoadGRFSound: channels %u, sample rate %u, bits per sample %u, length %u", se->channels, se->rate, se->bits_per_sample, size); + return; + + default: + se->file_size = 0; + return; + } + } +} + +/* 'Action 0xFF' */ +static void GRFDataBlock(byte *buf, int len) +{ + byte name_len; + const char *name; + + if (_grf_data_blocks == 0) { + grfmsg(GMS_WARN, "GRFDataBlock: unexpected data block, skipping."); + return; + } + + buf++; + name_len = grf_load_byte(&buf); + name = (const char *)buf; + buf += name_len + 1; + + grfmsg(GMS_NOTICE, "GRFDataBlock: block name '%s'...", name); + + _grf_data_blocks--; + + switch (_grf_data_type) { + case GDT_SOUND: LoadGRFSound(buf, len - name_len - 2); break; + default: NOT_REACHED(); break; + } +} + static void InitializeGRFSpecial(void) { _ttdpatch_flags[0] = ((_patches.always_small_airport ? 1 : 0) << 0x0C) // keepsmallairport @@ -2878,6 +3056,7 @@ static void ResetNewGRFData(void) _traininfo_vehicle_pitch = 0; _traininfo_vehicle_width = 29; + InitializeSoundPool(); InitializeSpriteGroupPool(); } @@ -2986,7 +3165,7 @@ static void DecodeSpecialSprite(uint num, uint stage) /* We need a pre-stage to set up GOTO labels of Action 0x10 because the grf * is not in memory and scanning the file every time would be too expensive. * In other stages we skip action 0x10 since it's already dealt with. */ - static const uint32 action_mask[] = {0x10000, 0x0000FB40, 0x0000FFFF}; + static const uint32 action_mask[] = {0x10000, 0x0002FB40, 0x0000FFFF}; static const SpecialSpriteHandler handlers[] = { /* 0x00 */ FeatureChangeInfo, @@ -3006,6 +3185,7 @@ static void DecodeSpecialSprite(uint num, uint stage) /* 0x0E */ GRFInhibit, /* 0x0F */ NULL, // TODO implement /* 0x10 */ DefineGotoLabel, + /* 0x11 */ GRFSound, }; byte* buf; @@ -3029,7 +3209,10 @@ static void DecodeSpecialSprite(uint num, uint stage) action = buf[0]; - if (action >= lengthof(handlers)) { + if (action == 0xFF) { + DEBUG(grf, 7) ("Handling data block in stage %d", stage); + GRFDataBlock(buf, num); + } else if (action >= lengthof(handlers)) { DEBUG(grf, 7) ("Skipping unknown action 0x%02X", action); } else if (!HASBIT(action_mask[stage], action)) { DEBUG(grf, 7) ("Skipping action 0x%02X in stage %d", action, stage); diff --git a/newgrf.h b/newgrf.h index 5618fbdae..2d91fc5cc 100644 --- a/newgrf.h +++ b/newgrf.h @@ -39,6 +39,8 @@ typedef struct GRFFile { int spritegroups_count; struct SpriteGroup **spritegroups; + uint sound_offset; + StationSpec **stations; uint32 param[0x80]; diff --git a/newgrf_callbacks.h b/newgrf_callbacks.h index d7a91c04b..a52455a7c 100644 --- a/newgrf_callbacks.h +++ b/newgrf_callbacks.h @@ -45,6 +45,9 @@ enum CallbackID { /* Called when the player (or AI) tries to start or stop a vehicle. Mainly * used for preventing a vehicle from leaving the depot. */ CBID_VEHICLE_START_STOP_CHECK = 0x31, + + /* Called to play a special sound effect */ + CBID_VEHICLE_SOUND_EFFECT = 0x33, }; /** diff --git a/newgrf_engine.c b/newgrf_engine.c index 800be6523..8629d0470 100644 --- a/newgrf_engine.c +++ b/newgrf_engine.c @@ -651,7 +651,7 @@ static uint32 VehicleGetVariable(const ResolverObject *object, byte variable, by } case 0x46: /* Motion counter */ - return 0; + return v->motion_counter; case 0x47: { /* Vehicle cargo info */ /* Format: ccccwwtt diff --git a/newgrf_engine.h b/newgrf_engine.h index 8b88a9c77..7edfc957b 100644 --- a/newgrf_engine.h +++ b/newgrf_engine.h @@ -3,6 +3,7 @@ #ifndef NEWGRF_ENGINE_H #define NEWGRF_ENGINE_H +#include "newgrf.h" #include "direction.h" #include "newgrf_cargo.h" diff --git a/newgrf_sound.c b/newgrf_sound.c new file mode 100644 index 000000000..7d746f712 --- /dev/null +++ b/newgrf_sound.c @@ -0,0 +1,73 @@ +/* $Id$ */ + +#include "stdafx.h" +#include "openttd.h" +#include "pool.h" +#include "sound.h" +#include "engine.h" +#include "vehicle.h" +#include "newgrf_callbacks.h" +#include "newgrf_engine.h" +#include "newgrf_sound.h" + +enum { + SOUND_POOL_BLOCK_SIZE_BITS = 3, /* (1 << 3) == 8 items */ + SOUND_POOL_MAX_BLOCKS = 1000, +}; + +static uint _sound_count = 0; +static MemoryPool _sound_pool = { "Sound", SOUND_POOL_MAX_BLOCKS, SOUND_POOL_BLOCK_SIZE_BITS, sizeof(FileEntry), NULL, NULL, 0, 0, NULL }; + + +/* Allocate a new FileEntry */ +FileEntry *AllocateFileEntry(void) +{ + if (_sound_count == _sound_pool.total_items) { + if (!AddBlockToPool(&_sound_pool)) return NULL; + } + + return (FileEntry*)GetItemFromPool(&_sound_pool, _sound_count++); +} + + +void InitializeSoundPool(void) +{ + CleanPool(&_sound_pool); + _sound_count = 0; + + /* Copy original sound data to the pool */ + SndCopyToPool(); +} + + +FileEntry *GetSound(uint index) +{ + if (index >= _sound_count) return NULL; + return (FileEntry*)GetItemFromPool(&_sound_pool, index); +} + + +uint GetNumSounds(void) +{ + return _sound_count; +} + + +bool PlayVehicleSound(const Vehicle *v, VehicleSoundEvent event) +{ + const GRFFile *file = GetEngineGRF(v->engine_type); + uint16 callback; + + /* If the engine has no GRF ID associated it can't ever play any new sounds */ + if (file == NULL) return false; + + /* Check that the vehicle type uses the sound effect callback */ + if (!HASBIT(EngInfo(v->engine_type)->callbackmask, CBM_SOUND_EFFECT)) return false; + + callback = GetVehicleCallback(CBID_VEHICLE_SOUND_EFFECT, event, 0, v->engine_type, v); + if (callback == CALLBACK_FAILED) return false; + if (callback >= GetNumOriginalSounds()) callback += file->sound_offset - GetNumOriginalSounds(); + + SndPlayVehicleFx(callback, v); + return true; +} diff --git a/newgrf_sound.h b/newgrf_sound.h new file mode 100644 index 000000000..ec2727fb1 --- /dev/null +++ b/newgrf_sound.h @@ -0,0 +1,25 @@ +/* $Id$ */ + +#ifndef NEWGRF_SOUND_H +#define NEWGRF_SOUND_H + +typedef enum VehicleSoundEvents { + VSE_START = 1, + VSE_TUNNEL = 2, + VSE_BREAKDOWN = 3, + VSE_RUNNING = 4, + VSE_TOUCHDOWN = 5, + VSE_TRAIN_EFFECT = 6, + VSE_RUNNING_16 = 7, + VSE_STOPPED_16 = 8, + VSE_LOAD_UNLOAD = 9, +} VehicleSoundEvent; + + +FileEntry *AllocateFileEntry(void); +void InitializeSoundPool(void); +FileEntry *GetSound(uint index); +uint GetNumSounds(void); +bool PlayVehicleSound(const Vehicle *v, VehicleSoundEvent event); + +#endif /* NEWGRF_SOUND_H */ diff --git a/openttd.vcproj b/openttd.vcproj index b78a47e35..77aee0c7b 100644 --- a/openttd.vcproj +++ b/openttd.vcproj @@ -303,6 +303,9 @@ + + @@ -550,6 +553,9 @@ + + diff --git a/openttd_vs80.vcproj b/openttd_vs80.vcproj index 85c7ed734..073f7509b 100644 --- a/openttd_vs80.vcproj +++ b/openttd_vs80.vcproj @@ -652,6 +652,10 @@ RelativePath=".\newgrf_engine.c" > + + @@ -1027,6 +1031,10 @@ RelativePath=".\newgrf_engine.h" > + + diff --git a/roadveh_cmd.c b/roadveh_cmd.c index ef3cf4e10..e8f0d2884 100644 --- a/roadveh_cmd.c +++ b/roadveh_cmd.c @@ -26,6 +26,7 @@ #include "newgrf_callbacks.h" #include "newgrf_engine.h" #include "newgrf_text.h" +#include "newgrf_sound.h" #include "yapf/yapf.h" #include "date.h" @@ -621,8 +622,10 @@ static void HandleBrokenRoadVeh(Vehicle *v) InvalidateWindow(WC_VEHICLE_VIEW, v->index); InvalidateWindow(WC_VEHICLE_DETAILS, v->index); - SndPlayVehicleFx((_opt.landscape != LT_CANDY) ? - SND_0F_VEHICLE_BREAKDOWN : SND_35_COMEDY_BREAKDOWN, v); + if (!PlayVehicleSound(v, VSE_BREAKDOWN)) { + SndPlayVehicleFx((_opt.landscape != LT_CANDY) ? + SND_0F_VEHICLE_BREAKDOWN : SND_35_COMEDY_BREAKDOWN, v); + } if (!(v->vehstatus & VS_HIDDEN)) { Vehicle *u = CreateEffectVehicleRel(v, 4, 4, 5, EV_BREAKDOWN_SMOKE); @@ -760,10 +763,12 @@ static void HandleRoadVehLoading(Vehicle *v) static void StartRoadVehSound(const Vehicle* v) { - SoundFx s = RoadVehInfo(v->engine_type)->sfx; - if (s == SND_19_BUS_START_PULL_AWAY && (v->tick_counter & 3) == 0) - s = SND_1A_BUS_START_PULL_AWAY_WITH_HORN; - SndPlayVehicleFx(s, v); + if (!PlayVehicleSound(v, VSE_START)) { + SoundFx s = RoadVehInfo(v->engine_type)->sfx; + if (s == SND_19_BUS_START_PULL_AWAY && (v->tick_counter & 3) == 0) + s = SND_1A_BUS_START_PULL_AWAY_WITH_HORN; + SndPlayVehicleFx(s, v); + } } typedef struct RoadVehFindData { diff --git a/ship_cmd.c b/ship_cmd.c index 371a51e7f..f39e5d6ac 100644 --- a/ship_cmd.c +++ b/ship_cmd.c @@ -25,6 +25,7 @@ #include "debug.h" #include "newgrf_callbacks.h" #include "newgrf_text.h" +#include "newgrf_sound.h" #include "date.h" static const uint16 _ship_sprites[] = {0x0E5D, 0x0E55, 0x0E65, 0x0E6D}; @@ -173,8 +174,10 @@ static void HandleBrokenShip(Vehicle *v) InvalidateWindow(WC_VEHICLE_VIEW, v->index); InvalidateWindow(WC_VEHICLE_DETAILS, v->index); - SndPlayVehicleFx((_opt.landscape != LT_CANDY) ? - SND_10_TRAIN_BREAKDOWN : SND_3A_COMEDY_BREAKDOWN_2, v); + if (!PlayVehicleSound(v, VSE_BREAKDOWN)) { + SndPlayVehicleFx((_opt.landscape != LT_CANDY) ? + SND_10_TRAIN_BREAKDOWN : SND_3A_COMEDY_BREAKDOWN_2, v); + } if (!(v->vehstatus & VS_HIDDEN)) { Vehicle *u = CreateEffectVehicleRel(v, 4, 4, 5, EV_BREAKDOWN_SMOKE); @@ -198,7 +201,9 @@ static void MarkShipDirty(Vehicle *v) static void PlayShipSound(Vehicle *v) { - SndPlayVehicleFx(ShipVehInfo(v->engine_type)->sfx, v); + if (!PlayVehicleSound(v, VSE_START)) { + SndPlayVehicleFx(ShipVehInfo(v->engine_type)->sfx, v); + } } static void ProcessShipOrder(Vehicle *v) diff --git a/sound.c b/sound.c index c3eacd685..f8d194c97 100644 --- a/sound.c +++ b/sound.c @@ -10,14 +10,7 @@ #include "window.h" #include "viewport.h" #include "fileio.h" - -typedef struct FileEntry { - uint32 file_offset; - uint32 file_size; - uint16 rate; - uint8 bits_per_sample; - uint8 channels; -} FileEntry; +#include "newgrf_sound.h" static uint _file_count; static FileEntry *_files; @@ -100,14 +93,19 @@ static void OpenBankFile(const char *filename) } } +uint GetNumOriginalSounds(void) +{ + return _file_count; +} + static bool SetBankSource(MixerChannel *mc, uint bank) { const FileEntry *fe; int8 *mem; uint i; - if (bank >= _file_count) return false; - fe = &_files[bank]; + if (bank >= GetNumSounds()) return false; + fe = GetSound(bank); if (fe->file_size == 0) return false; @@ -180,6 +178,20 @@ static const byte _sound_idx[] = { 72, }; +void SndCopyToPool(void) +{ + uint i; + + for (i = 0; i < _file_count; i++) { + FileEntry *orig = &_files[_sound_idx[i]]; + FileEntry *fe = AllocateFileEntry(); + + memcpy(fe, orig, sizeof(*orig)); + fe->volume = _sound_base_vol[i]; + fe->priority = 0; + } +} + static void SndPlayScreenCoordFx(SoundFx sound, int x, int y) { const Window *w; @@ -195,9 +207,9 @@ static void SndPlayScreenCoordFx(SoundFx sound, int x, int y) int left = (x - vp->virtual_left); StartSound( - _sound_idx[sound], + sound, left / (vp->virtual_width / ((PANNING_LEVELS << 1) + 1)) - PANNING_LEVELS, - (_sound_base_vol[sound] * msf.effect_vol * _vol_factor_by_zoom[vp->zoom]) >> 15 + (GetSound(sound)->volume * msf.effect_vol * _vol_factor_by_zoom[vp->zoom]) >> 15 ); return; } @@ -225,8 +237,8 @@ void SndPlayVehicleFx(SoundFx sound, const Vehicle *v) void SndPlayFx(SoundFx sound) { StartSound( - _sound_idx[sound], + sound, 0, - (_sound_base_vol[sound] * msf.effect_vol) >> 7 + (GetSound(sound)->volume * msf.effect_vol) >> 7 ); } diff --git a/sound.h b/sound.h index 9f9edaddc..fd5638558 100644 --- a/sound.h +++ b/sound.h @@ -16,7 +16,18 @@ typedef struct MusicFileSettings { VARDEF MusicFileSettings msf; +typedef struct FileEntry { + uint32 file_offset; + uint32 file_size; + uint16 rate; + uint8 bits_per_sample; + uint8 channels; + uint8 volume; + uint8 priority; +} FileEntry; + bool SoundInitialize(const char *filename); +uint GetNumOriginalSounds(void); typedef enum SoundFx { SND_02_SPLAT, // 0 == 0x00 ! @@ -97,5 +108,6 @@ typedef enum SoundFx { void SndPlayTileFx(SoundFx sound, TileIndex tile); void SndPlayVehicleFx(SoundFx sound, const Vehicle *v); void SndPlayFx(SoundFx sound); +void SndCopyToPool(void); #endif /* SOUND_H */ diff --git a/train_cmd.c b/train_cmd.c index d3533ac39..44becd117 100644 --- a/train_cmd.c +++ b/train_cmd.c @@ -27,6 +27,7 @@ #include "train.h" #include "newgrf_callbacks.h" #include "newgrf_engine.h" +#include "newgrf_sound.h" #include "newgrf_text.h" #include "direction.h" #include "yapf/yapf.h" @@ -2021,6 +2022,7 @@ static const int8 _vehicle_smoke_pos[8] = { static void HandleLocomotiveSmokeCloud(const Vehicle* v) { const Vehicle* u; + bool sound = false; if (v->vehstatus & VS_TRAIN_SLOWING || v->load_unload_time_rem != 0 || v->cur_speed < 2) return; @@ -2068,6 +2070,7 @@ static void HandleLocomotiveSmokeCloud(const Vehicle* v) // steam smoke. if (GB(v->tick_counter, 0, 4) == 0) { CreateEffectVehicleRel(v, x, y, 10, EV_STEAM_SMOKE); + sound = true; } break; @@ -2075,6 +2078,7 @@ static void HandleLocomotiveSmokeCloud(const Vehicle* v) // diesel smoke if (u->cur_speed <= 40 && CHANCE16(15, 128)) { CreateEffectVehicleRel(v, 0, 0, 10, EV_DIESEL_SMOKE); + sound = true; } break; @@ -2082,10 +2086,13 @@ static void HandleLocomotiveSmokeCloud(const Vehicle* v) // blue spark if (GB(v->tick_counter, 0, 2) == 0 && CHANCE16(1, 45)) { CreateEffectVehicleRel(v, 0, 0, 10, EV_ELECTRIC_SPARK); + sound = true; } break; } } while ((v = v->next) != NULL); + + if (sound) PlayVehicleSound(u, VSE_TRAIN_EFFECT); } static void TrainPlayLeaveStationSound(const Vehicle* v) @@ -2098,6 +2105,8 @@ static void TrainPlayLeaveStationSound(const Vehicle* v) EngineID engtype = v->engine_type; + if (PlayVehicleSound(v, VSE_START)) return; + switch (GetEngine(engtype)->railtype) { case RAILTYPE_RAIL: case RAILTYPE_ELECTRIC: @@ -3262,8 +3271,10 @@ static void HandleBrokenTrain(Vehicle *v) InvalidateWindow(WC_VEHICLE_VIEW, v->index); InvalidateWindow(WC_VEHICLE_DETAILS, v->index); - SndPlayVehicleFx((_opt.landscape != LT_CANDY) ? - SND_10_TRAIN_BREAKDOWN : SND_3A_COMEDY_BREAKDOWN_2, v); + if (!PlayVehicleSound(v, VSE_BREAKDOWN)) { + SndPlayVehicleFx((_opt.landscape != LT_CANDY) ? + SND_10_TRAIN_BREAKDOWN : SND_3A_COMEDY_BREAKDOWN_2, v); + } if (!(v->vehstatus & VS_HIDDEN)) { Vehicle *u = CreateEffectVehicleRel(v, 4, 4, 5, EV_BREAKDOWN_SMOKE); diff --git a/tunnelbridge_cmd.c b/tunnelbridge_cmd.c index e16e1f4d7..c7c56a37f 100644 --- a/tunnelbridge_cmd.c +++ b/tunnelbridge_cmd.c @@ -28,6 +28,7 @@ #include "water_map.h" #include "yapf/yapf.h" #include "date.h" +#include "newgrf_sound.h" #include "table/bridge_land.h" @@ -1361,8 +1362,9 @@ static uint32 VehicleEnter_TunnelBridge(Vehicle *v, TileIndex tile, int x, int y if (v->u.rail.track != 0x40 && dir == vdir) { if (IsFrontEngine(v) && fc == _tunnel_fractcoord_1[dir]) { - if (v->spritenum < 4) + if (!PlayVehicleSound(v, VSE_TUNNEL) && v->spritenum < 4) { SndPlayVehicleFx(SND_05_TRAIN_THROUGH_TUNNEL, v); + } return 0; } if (fc == _tunnel_fractcoord_2[dir]) { diff --git a/vehicle.c b/vehicle.c index e5cff4fdf..760ff64f2 100644 --- a/vehicle.c +++ b/vehicle.c @@ -33,6 +33,7 @@ #include "yapf/yapf.h" #include "date.h" #include "newgrf_engine.h" +#include "newgrf_sound.h" #define INVALID_COORD (-0x8000) #define GEN_HASH(x, y) ((GB((y), 6, 6) << 6) + GB((x), 7, 6)) @@ -646,6 +647,22 @@ void CallVehicleTicks(void) FOR_ALL_VEHICLES(v) { _vehicle_tick_procs[v->type - 0x10](v); + + switch (v->type) { + case VEH_Train: + case VEH_Road: + case VEH_Aircraft: + case VEH_Ship: + if (v->type == VEH_Train && IsTrainWagon(v)) continue; + if (v->type == VEH_Aircraft && v->subtype > 0) continue; + + v->motion_counter += (v->direction & 1) ? (v->cur_speed * 3) / 4 : v->cur_speed; + /* Play a running sound if the motion counter passes 256 (Do we not skip sounds?) */ + if (GB(v->motion_counter, 0, 8) < v->cur_speed) PlayVehicleSound(v, VSE_RUNNING); + + /* Play an alterate running sound every 16 ticks */ + if (GB(v->tick_counter, 0, 4) == 0) PlayVehicleSound(v, v->cur_speed > 0 ? VSE_RUNNING_16 : VSE_STOPPED_16); + } } // now we handle all the vehicles that entered a depot this tick diff --git a/vehicle.h b/vehicle.h index 67961c468..c21c12477 100644 --- a/vehicle.h +++ b/vehicle.h @@ -174,6 +174,7 @@ struct Vehicle { byte subspeed; // fractional speed byte acceleration; // used by train & aircraft byte progress; + uint32 motion_counter; byte vehstatus; // Status StationID last_station_visited; -- cgit v1.2.3-70-g09d2