From c097bc9d7d610b613f76152b3cdcb9be2af7a1c7 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Tue, 13 Apr 2021 21:58:56 +0200 Subject: [PATCH] Codechange: let NewGRF sounds make use of RandomAccessFile instead of the FIO slot functions --- src/fileio.cpp | 8 ++++++ src/fileio_func.h | 1 + src/fios.h | 2 -- src/newgrf.cpp | 2 +- src/newgrf_sound.cpp | 63 +++++++++++++++++++++--------------------- src/sound.cpp | 65 ++++++++++++++++++++++++-------------------- src/sound_type.h | 2 +- 7 files changed, 79 insertions(+), 64 deletions(-) diff --git a/src/fileio.cpp b/src/fileio.cpp index 465e713048..6b13e30890 100644 --- a/src/fileio.cpp +++ b/src/fileio.cpp @@ -39,6 +39,14 @@ static bool _do_scan_working_directory = true; extern std::string _config_file; extern std::string _highscore_file; +/** + * Transition helper to get the RandomAccessFile associated with a given slot. + */ +RandomAccessFile *FioGetRandomAccessFile(int slot) +{ + return _fio_files[slot]; +} + /** * Get position in the current file. * @return Position in the file. diff --git a/src/fileio_func.h b/src/fileio_func.h index 4b9b2dd9ee..55fac39efd 100644 --- a/src/fileio_func.h +++ b/src/fileio_func.h @@ -26,6 +26,7 @@ void FioCloseAll(); void FioOpenFile(int slot, const std::string &filename, Subdirectory subdir); void FioReadBlock(void *ptr, size_t size); void FioSkipBytes(int n); +class RandomAccessFile *FioGetRandomAccessFile(int slot); void FioFCloseFile(FILE *f); FILE *FioFOpenFile(const std::string &filename, const char *mode, Subdirectory subdir, size_t *filesize = nullptr); diff --git a/src/fios.h b/src/fios.h index 28a1cc6aa5..5029d4862f 100644 --- a/src/fios.h +++ b/src/fios.h @@ -91,8 +91,6 @@ enum FileSlots { * and thus cannot be used for files, which are continuously accessed during a game. */ CONFIG_SLOT = 0, - /** Slot for the sound. */ - SOUND_SLOT = 1, /** First slot usable for (New)GRFs used during the game. */ FIRST_GRF_SLOT = 2, /** Maximum number of slots. */ diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 3a4fe12619..b51a18b437 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -7553,7 +7553,7 @@ static void LoadGRFSound(size_t offs, SoundEntry *sound) if (offs != SIZE_MAX) { /* Sound is present in the NewGRF. */ - sound->file_slot = _cur.file_index; + sound->file = FioGetRandomAccessFile(_cur.file_index); sound->file_offset = offs; sound->grf_container_ver = _cur.grf_container_ver; } diff --git a/src/newgrf_sound.cpp b/src/newgrf_sound.cpp index aead090016..523b210d1c 100644 --- a/src/newgrf_sound.cpp +++ b/src/newgrf_sound.cpp @@ -14,7 +14,7 @@ #include "newgrf_sound.h" #include "vehicle_base.h" #include "sound_func.h" -#include "fileio_func.h" +#include "random_access_file_type.h" #include "debug.h" #include "settings_type.h" @@ -65,56 +65,57 @@ uint GetNumSounds() */ bool LoadNewGRFSound(SoundEntry *sound) { - if (sound->file_offset == SIZE_MAX || sound->file_slot == 0) return false; + if (sound->file_offset == SIZE_MAX || sound->file == nullptr) return false; - FioSeekToFile(sound->file_slot, sound->file_offset); + RandomAccessFile &file = *sound->file; + file.SeekTo(sound->file_offset, SEEK_SET); /* Skip ID for container version >= 2 as we only look at the first * entry and ignore any further entries with the same ID. */ - if (sound->grf_container_ver >= 2) FioReadDword(); + if (sound->grf_container_ver >= 2) file.ReadDword(); /* Format: '\0' */ - uint32 num = sound->grf_container_ver >= 2 ? FioReadDword() : FioReadWord(); - if (FioReadByte() != 0xFF) return false; - if (FioReadByte() != 0xFF) return false; + uint32 num = sound->grf_container_ver >= 2 ? file.ReadDword() : file.ReadWord(); + if (file.ReadByte() != 0xFF) return false; + if (file.ReadByte() != 0xFF) return false; - uint8 name_len = FioReadByte(); + uint8 name_len = file.ReadByte(); char *name = AllocaM(char, name_len + 1); - FioReadBlock(name, name_len + 1); + file.ReadBlock(name, name_len + 1); /* Test string termination */ if (name[name_len] != 0) { - DEBUG(grf, 2, "LoadNewGRFSound [%s]: Name not properly terminated", FioGetFilename(sound->file_slot)); + DEBUG(grf, 2, "LoadNewGRFSound [%s]: Name not properly terminated", file.GetSimplifiedFilename().c_str()); return false; } - DEBUG(grf, 2, "LoadNewGRFSound [%s]: Sound name '%s'...", FioGetFilename(sound->file_slot), name); + DEBUG(grf, 2, "LoadNewGRFSound [%s]: Sound name '%s'...", file.GetSimplifiedFilename().c_str(), name); - if (FioReadDword() != BSWAP32('RIFF')) { - DEBUG(grf, 1, "LoadNewGRFSound [%s]: Missing RIFF header", FioGetFilename(sound->file_slot)); + if (file.ReadDword() != BSWAP32('RIFF')) { + DEBUG(grf, 1, "LoadNewGRFSound [%s]: Missing RIFF header", file.GetSimplifiedFilename().c_str()); return false; } - uint32 total_size = FioReadDword(); + uint32 total_size = file.ReadDword(); uint header_size = 11; if (sound->grf_container_ver >= 2) header_size++; // The first FF in the sprite is only counted for container version >= 2. if (total_size + name_len + header_size > num) { - DEBUG(grf, 1, "LoadNewGRFSound [%s]: RIFF was truncated", FioGetFilename(sound->file_slot)); + DEBUG(grf, 1, "LoadNewGRFSound [%s]: RIFF was truncated", file.GetSimplifiedFilename().c_str()); return false; } - if (FioReadDword() != BSWAP32('WAVE')) { - DEBUG(grf, 1, "LoadNewGRFSound [%s]: Invalid RIFF type", FioGetFilename(sound->file_slot)); + if (file.ReadDword() != BSWAP32('WAVE')) { + DEBUG(grf, 1, "LoadNewGRFSound [%s]: Invalid RIFF type", file.GetSimplifiedFilename().c_str()); return false; } while (total_size >= 8) { - uint32 tag = FioReadDword(); - uint32 size = FioReadDword(); + uint32 tag = file.ReadDword(); + uint32 size = file.ReadDword(); total_size -= 8; if (total_size < size) { - DEBUG(grf, 1, "LoadNewGRFSound [%s]: Invalid RIFF", FioGetFilename(sound->file_slot)); + DEBUG(grf, 1, "LoadNewGRFSound [%s]: Invalid RIFF", file.GetSimplifiedFilename().c_str()); return false; } total_size -= size; @@ -122,15 +123,15 @@ bool LoadNewGRFSound(SoundEntry *sound) switch (tag) { case ' tmf': // 'fmt ' /* Audio format, must be 1 (PCM) */ - if (size < 16 || FioReadWord() != 1) { - DEBUG(grf, 1, "LoadGRFSound [%s]: Invalid audio format", FioGetFilename(sound->file_slot)); + if (size < 16 || file.ReadWord() != 1) { + DEBUG(grf, 1, "LoadGRFSound [%s]: Invalid audio format", file.GetSimplifiedFilename().c_str()); return false; } - sound->channels = FioReadWord(); - sound->rate = FioReadDword(); - FioReadDword(); - FioReadWord(); - sound->bits_per_sample = FioReadWord(); + sound->channels = file.ReadWord(); + sound->rate = file.ReadDword(); + file.ReadDword(); + file.ReadWord(); + sound->bits_per_sample = file.ReadWord(); /* The rest will be skipped */ size -= 16; @@ -138,9 +139,9 @@ bool LoadNewGRFSound(SoundEntry *sound) case 'atad': // 'data' sound->file_size = size; - sound->file_offset = FioGetPos(); + sound->file_offset = file.GetPos(); - DEBUG(grf, 2, "LoadNewGRFSound [%s]: channels %u, sample rate %u, bits per sample %u, length %u", FioGetFilename(sound->file_slot), sound->channels, sound->rate, sound->bits_per_sample, size); + DEBUG(grf, 2, "LoadNewGRFSound [%s]: channels %u, sample rate %u, bits per sample %u, length %u", file.GetSimplifiedFilename().c_str(), sound->channels, sound->rate, sound->bits_per_sample, size); return true; // the fmt chunk has to appear before data, so we are finished default: @@ -149,10 +150,10 @@ bool LoadNewGRFSound(SoundEntry *sound) } /* Skip rest of chunk */ - if (size > 0) FioSkipBytes(size); + if (size > 0) file.SkipBytes(size); } - DEBUG(grf, 1, "LoadNewGRFSound [%s]: RIFF does not contain any sound data", FioGetFilename(sound->file_slot)); + DEBUG(grf, 1, "LoadNewGRFSound [%s]: RIFF does not contain any sound data", file.GetSimplifiedFilename().c_str()); /* Clear everything that was read */ MemSetT(sound, 0); diff --git a/src/sound.cpp b/src/sound.cpp index d91476729b..413c70af2a 100644 --- a/src/sound.cpp +++ b/src/sound.cpp @@ -11,7 +11,7 @@ #include "landscape.h" #include "mixer.h" #include "newgrf_sound.h" -#include "fios.h" +#include "random_access_file_type.h" #include "window_gui.h" #include "vehicle_base.h" @@ -25,14 +25,20 @@ static SoundEntry _original_sounds[ORIGINAL_SAMPLE_COUNT]; static void OpenBankFile(const char *filename) { + /** + * The sound file for the original sounds, i.e. those not defined/overridden by a NewGRF. + * Needs to be kept alive during the game as _original_sounds[n].file refers to this. + */ + static std::unique_ptr original_sound_file; + memset(_original_sounds, 0, sizeof(_original_sounds)); /* If there is no sound file (nosound set), don't load anything */ if (filename == nullptr) return; - FioOpenFile(SOUND_SLOT, filename, BASESET_DIR); - size_t pos = FioGetPos(); - uint count = FioReadDword(); + original_sound_file.reset(new RandomAccessFile(filename, BASESET_DIR)); + size_t pos = original_sound_file->GetPos(); + uint count = original_sound_file->ReadDword(); /* The new format has the highest bit always set */ bool new_format = HasBit(count, 31); @@ -48,43 +54,43 @@ static void OpenBankFile(const char *filename) return; } - FioSeekTo(pos, SEEK_SET); + original_sound_file->SeekTo(pos, SEEK_SET); for (uint i = 0; i != ORIGINAL_SAMPLE_COUNT; i++) { - _original_sounds[i].file_slot = SOUND_SLOT; - _original_sounds[i].file_offset = GB(FioReadDword(), 0, 31) + pos; - _original_sounds[i].file_size = FioReadDword(); + _original_sounds[i].file = original_sound_file.get(); + _original_sounds[i].file_offset = GB(original_sound_file->ReadDword(), 0, 31) + pos; + _original_sounds[i].file_size = original_sound_file->ReadDword(); } for (uint i = 0; i != ORIGINAL_SAMPLE_COUNT; i++) { SoundEntry *sound = &_original_sounds[i]; char name[255]; - FioSeekTo(sound->file_offset, SEEK_SET); + original_sound_file->SeekTo(sound->file_offset, SEEK_SET); /* Check for special case, see else case */ - FioReadBlock(name, FioReadByte()); // Read the name of the sound + original_sound_file->ReadBlock(name, original_sound_file->ReadByte()); // Read the name of the sound if (new_format || strcmp(name, "Corrupt sound") != 0) { - FioSeekTo(12, SEEK_CUR); // Skip past RIFF header + original_sound_file->SeekTo(12, SEEK_CUR); // Skip past RIFF header /* Read riff tags */ for (;;) { - uint32 tag = FioReadDword(); - uint32 size = FioReadDword(); + uint32 tag = original_sound_file->ReadDword(); + uint32 size = original_sound_file->ReadDword(); if (tag == ' tmf') { - FioReadWord(); // wFormatTag - sound->channels = FioReadWord(); // wChannels - sound->rate = FioReadDword(); // samples per second - if (!new_format) sound->rate = 11025; // seems like all old samples should be played at this rate. - FioReadDword(); // avg bytes per second - FioReadWord(); // alignment - sound->bits_per_sample = FioReadByte(); // bits per sample - FioSeekTo(size - (2 + 2 + 4 + 4 + 2 + 1), SEEK_CUR); + original_sound_file->ReadWord(); // wFormatTag + sound->channels = original_sound_file->ReadWord(); // wChannels + sound->rate = original_sound_file->ReadDword(); // samples per second + if (!new_format) sound->rate = 11025; // seems like all old samples should be played at this rate. + original_sound_file->ReadDword(); // avg bytes per second + original_sound_file->ReadWord(); // alignment + sound->bits_per_sample = original_sound_file->ReadByte(); // bits per sample + original_sound_file->SeekTo(size - (2 + 2 + 4 + 4 + 2 + 1), SEEK_CUR); } else if (tag == 'atad') { sound->file_size = size; - sound->file_slot = SOUND_SLOT; - sound->file_offset = FioGetPos(); + sound->file = original_sound_file.get(); + sound->file_offset = original_sound_file->GetPos(); break; } else { sound->file_size = 0; @@ -100,8 +106,8 @@ static void OpenBankFile(const char *filename) sound->channels = 1; sound->rate = 11025; sound->bits_per_sample = 8; - sound->file_slot = SOUND_SLOT; - sound->file_offset = FioGetPos(); + sound->file = original_sound_file.get(); + sound->file_offset = original_sound_file->GetPos(); } } } @@ -119,8 +125,9 @@ static bool SetBankSource(MixerChannel *mc, const SoundEntry *sound) mem[sound->file_size ] = 0; mem[sound->file_size + 1] = 0; - FioSeekToFile(sound->file_slot, sound->file_offset); - FioReadBlock(mem, sound->file_size); + RandomAccessFile *file = sound->file; + file->SeekTo(sound->file_offset, SEEK_SET); + file->ReadBlock(mem, sound->file_size); /* 16-bit PCM WAV files should be signed by default */ if (sound->bits_per_sample == 8) { @@ -163,10 +170,10 @@ static void StartSound(SoundID sound_id, float pan, uint volume) if (sound == nullptr) return; /* NewGRF sound that wasn't loaded yet? */ - if (sound->rate == 0 && sound->file_slot != 0) { + if (sound->rate == 0 && sound->file != nullptr) { if (!LoadNewGRFSound(sound)) { /* Mark as invalid. */ - sound->file_slot = 0; + sound->file = nullptr; return; } } diff --git a/src/sound_type.h b/src/sound_type.h index e8d4b7becb..02bfc4f835 100644 --- a/src/sound_type.h +++ b/src/sound_type.h @@ -11,7 +11,7 @@ #define SOUND_TYPE_H struct SoundEntry { - uint8 file_slot; + class RandomAccessFile *file; size_t file_offset; size_t file_size; uint16 rate;