@@ -6871,16 +6871,19 @@ static void DefineGotoLabel(ByteReader *
l->next = label;
}
grfmsg(2, "DefineGotoLabel: GOTO target with label 0x%02X", label->label);
static void ImportGRFSound()
/**
* Process a sound import from another GRF file.
* @param sound Destination for sound.
*/
static void ImportGRFSound(SoundEntry *sound)
{
const GRFFile *file;
SoundEntry *sound = AllocateSound();
uint32 grfid = FioReadDword();
SoundID sound_id = FioReadWord();
file = GetFileByGRFID(grfid);
if (file == NULL || file->sound_offset == 0) {
grfmsg(1, "ImportGRFSound: Source file not available");
@@ -6898,16 +6901,19 @@ static void ImportGRFSound()
/* Reset volume and priority, which TTDPatch doesn't copy */
sound->volume = 128;
sound->priority = 0;
static void LoadGRFSound(size_t offs)
* Load a sound from a file.
* @param offs File offset to read sound from.
static void LoadGRFSound(size_t offs, SoundEntry *sound)
/* Set default volume and priority */
sound->volume = 0x80;
if (offs != SIZE_MAX) {
/* Sound is present in the NewGRF. */
@@ -6922,65 +6928,82 @@ static void GRFSound(ByteReader *buf)
/* <11> <num>
*
* W num Number of sound files that follow */
uint16 num = buf->ReadWord();
if (num == 0) return;
SoundEntry *sound;
if (_cur.grffile->sound_offset == 0) {
_cur.grffile->sound_offset = GetNumSounds();
_cur.grffile->num_sounds = num;
sound = AllocateSound(num);
} else {
sound = GetSound(_cur.grffile->sound_offset);
for (int i = 0; i < num; i++) {
_cur.nfo_line++;
/* Check whether the index is in range. This might happen if multiple action 11 are present.
* While this is invalid, we do not check for this. But we should prevent it from causing bigger trouble */
bool invalid = i >= _cur.grffile->num_sounds;
size_t offs = FioGetPos();
uint32 len = _cur.grf_container_ver >= 2 ? FioReadDword() : FioReadWord();
byte type = FioReadByte();
if (_cur.grf_container_ver >= 2 && type == 0xFD) {
/* Reference to sprite section. */
if (len != 4) {
if (invalid) {
grfmsg(1, "GRFSound: Sound index out of range (multiple Action 11?)");
FioSkipBytes(len);
} else if (len != 4) {
grfmsg(1, "GRFSound: Invalid sprite section import");
uint32 id = FioReadDword();
if (_cur.stage == GLS_INIT) LoadGRFSound(GetGRFSpriteOffset(id));
if (_cur.stage == GLS_INIT) LoadGRFSound(GetGRFSpriteOffset(id), sound + i);
continue;
if (type != 0xFF) {
grfmsg(1, "GRFSound: Unexpected RealSprite found, skipping");
FioSkipBytes(7);
SkipSpriteData(type, len - 8);
byte action = FioReadByte();
switch (action) {
case 0xFF:
/* Allocate sound only in init stage. */
if (_cur.stage == GLS_INIT) {
if (_cur.grf_container_ver >= 2) {
grfmsg(1, "GRFSound: Inline sounds are not supported for container version >= 2");
LoadGRFSound(offs);
LoadGRFSound(offs, sound + i);
FioSkipBytes(len - 1); // already read <action>
break;
case 0xFE:
if (_cur.stage == GLS_ACTIVATION) {
/* XXX 'Action 0xFE' isn't really specified. It is only mentioned for
* importing sounds, so this is probably all wrong... */
if (FioReadByte() != 0) grfmsg(1, "GRFSound: Import type mismatch");
ImportGRFSound();
ImportGRFSound(sound + i);
default:
@@ -19,17 +19,21 @@
#include "fileio_func.h"
#include "debug.h"
static SmallVector<SoundEntry, 8> _sounds;
/* Allocate a new Sound */
SoundEntry *AllocateSound()
* Allocate sound slots.
* @param num Number of slots to allocate.
* @return First allocated slot.
SoundEntry *AllocateSound(uint num)
SoundEntry *sound = _sounds.Append();
MemSetT(sound, 0);
SoundEntry *sound = _sounds.Append(num);
MemSetT(sound, 0, num);
return sound;
void InitializeSoundPool()
@@ -27,13 +27,13 @@ enum VehicleSoundEvent {
VSE_RUNNING_16 = 7, ///< Every 16 ticks while the vehicle is running (speed > 0).
VSE_STOPPED_16 = 8, ///< Every 16 ticks while the vehicle is stopped (speed == 0).
VSE_LOAD_UNLOAD = 9, ///< Whenever cargo payment is made for a vehicle.
};
SoundEntry *AllocateSound();
SoundEntry *AllocateSound(uint num);
void InitializeSoundPool();
bool LoadNewGRFSound(SoundEntry *sound);
SoundEntry *GetSound(SoundID sound_id);
uint GetNumSounds();
bool PlayVehicleSound(const Vehicle *v, VehicleSoundEvent event);
void PlayTileSound(const struct GRFFile *file, SoundID sound_id, TileIndex tile);
@@ -215,17 +215,17 @@ static const byte _sound_idx[] = {
64, 65, 66, 67, 68, 69, 70, 71,
72,
void SndCopyToPool()
SoundEntry *sound = AllocateSound(ORIGINAL_SAMPLE_COUNT);
for (uint i = 0; i < ORIGINAL_SAMPLE_COUNT; i++) {
*sound = _original_sounds[_sound_idx[i]];
sound->volume = _sound_base_vol[i];
sound[i] = _original_sounds[_sound_idx[i]];
sound[i].volume = _sound_base_vol[i];
sound[i].priority = 0;
* Decide 'where' (between left and right speaker) to play the sound effect.
* @param sound Sound effect to play
Status change: