Allow loading data files with lowercase name (#164)

* Allow loading data files with lowercase name

* Added lower case support for all game data files.

Co-authored-by: Muzychenko Andrey <33288308+k4zmu2a@users.noreply.github.com>
This commit is contained in:
Low-power 2022-11-22 17:40:50 +08:00 committed by GitHub
parent 1391eeba81
commit f561cadf63
Signed by untrusted user: GitHub
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 64 additions and 28 deletions

View File

@ -142,27 +142,34 @@ int loader::get_sound_id(int groupIndex)
FieldTypes::ShortValue)); FieldTypes::ShortValue));
if (value && *value == 202) if (value && *value == 202)
{ {
// File name is in lower case, while game data is usually in upper case.
std::string fileName = loader_table->field(soundGroupId, FieldTypes::String); std::string fileName = loader_table->field(soundGroupId, FieldTypes::String);
// File name is in lower case, while game data is in upper case.
std::transform(fileName.begin(), fileName.end(), fileName.begin(),
[](unsigned char c) { return std::toupper(c); });
if (pb::FullTiltMode) if (pb::FullTiltMode)
{ {
// FT sounds are in SOUND subfolder // FT sounds are in SOUND subfolder
fileName.insert(0, 1, PathSeparator); fileName.insert(0, 1, PathSeparator);
fileName.insert(0, "SOUND"); fileName.insert(0, "sound");
} }
std::string filePath;
float duration = -1; float duration = -1;
auto filePath = pb::make_path_name(fileName); for (int i = 0; i < 2; i++)
auto file = fopenu(filePath.c_str(), "rb");
if (file)
{ {
fread(&wavHeader, 1, sizeof wavHeader, file); if (i == 1)
fclose(file); std::transform(fileName.begin(), fileName.end(), fileName.begin(),
auto sampleCount = wavHeader.data_size / (wavHeader.channels * (wavHeader.bits_per_sample / 8.0)); [](unsigned char c) { return std::toupper(c); });
duration = static_cast<float>(sampleCount / wavHeader.sample_rate);
filePath = pb::make_path_name(fileName);
auto file = fopenu(filePath.c_str(), "rb");
if (file)
{
fread(&wavHeader, 1, sizeof wavHeader, file);
fclose(file);
auto sampleCount = wavHeader.data_size / (wavHeader.channels * (wavHeader.bits_per_sample /
8.0));
duration = static_cast<float>(sampleCount / wavHeader.sample_rate);
break;
}
} }
sound_list[soundIndex].Duration = duration; sound_list[soundIndex].Duration = duration;

View File

@ -107,7 +107,6 @@ void midi::SetVolume(int volume)
Mix_Music* midi::load_track(std::string fileName) Mix_Music* midi::load_track(std::string fileName)
{ {
Mix_Music* audio = nullptr;
if (pb::FullTiltMode) if (pb::FullTiltMode)
{ {
// FT sounds are in SOUND subfolder // FT sounds are in SOUND subfolder
@ -115,29 +114,47 @@ Mix_Music* midi::load_track(std::string fileName)
fileName.insert(0, "SOUND"); fileName.insert(0, "SOUND");
} }
auto audio = load_track_sub(fileName, true);
if (!audio)
audio = load_track_sub(fileName, false);
if (!audio)
return nullptr;
LoadedTracks.push_back(audio);
return audio;
}
Mix_Music* midi::load_track_sub(std::string fileName, bool isMidi)
{
// FT has music in two formats, depending on game version: MIDI in 16bit, MIDS in 32bit. // FT has music in two formats, depending on game version: MIDI in 16bit, MIDS in 32bit.
// 3DPB music is MIDI only. // 3DPB music is MIDI only.
auto basePath = pb::make_path_name(fileName); Mix_Music* audio = nullptr;
for (int i = 0; i <= 1 && !audio; i++) fileName += isMidi ? ".MID" : ".MDS";
for (int i = 0; i < 2; i++)
{ {
if (i == 0) if (i == 1)
std::transform(fileName.begin(), fileName.end(), fileName.begin(),
[](unsigned char c) { return std::tolower(c); });
if (isMidi)
{ {
auto filePath = basePath + ".MID"; auto filePath = pb::make_path_name(fileName);
auto fileHandle = fopenu(filePath.c_str(), "rb"); auto fileHandle = fopenu(filePath.c_str(), "rb");
if (fileHandle) if (fileHandle)
{ {
fclose(fileHandle); fclose(fileHandle);
auto rw = SDL_RWFromFile(filePath.c_str(), "rb"); auto rw = SDL_RWFromFile(filePath.c_str(), "rb");
audio = Mix_LoadMUS_RW(rw, 1); audio = Mix_LoadMUS_RW(rw, 1);
break;
} }
} }
else else
{ {
auto midi = MdsToMidi(basePath + ".MDS"); auto midi = MdsToMidi(pb::make_path_name(fileName));
if (midi) if (midi)
{ {
// Dump converted MIDI file // Dump converted MIDI file
/*auto filePath = basePath + ".midi"; /*auto filePath = fileName + ".midi";
FILE* fileHandle = fopenu(filePath.c_str(), "wb"); FILE* fileHandle = fopenu(filePath.c_str(), "wb");
fwrite(midi->data(), 1, midi->size(), fileHandle); fwrite(midi->data(), 1, midi->size(), fileHandle);
fclose(fileHandle);*/ fclose(fileHandle);*/
@ -145,14 +162,11 @@ Mix_Music* midi::load_track(std::string fileName)
auto rw = SDL_RWFromMem(midi->data(), static_cast<int>(midi->size())); auto rw = SDL_RWFromMem(midi->data(), static_cast<int>(midi->size()));
audio = Mix_LoadMUS_RW(rw, 1); // This call seems to leak memory no matter what. audio = Mix_LoadMUS_RW(rw, 1); // This call seems to leak memory no matter what.
delete midi; delete midi;
break;
} }
} }
} }
if (!audio)
return nullptr;
LoadedTracks.push_back(audio);
return audio; return audio;
} }

View File

@ -110,6 +110,7 @@ private:
static void StopPlayback(); static void StopPlayback();
static Mix_Music* load_track(std::string fileName); static Mix_Music* load_track(std::string fileName);
static Mix_Music* load_track_sub(std::string fileName, bool isMidi);
static Mix_Music* TrackToMidi(MidiTracks track); static Mix_Music* TrackToMidi(MidiTracks track);
static std::vector<uint8_t>* MdsToMidi(std::string file); static std::vector<uint8_t>* MdsToMidi(std::string file);
}; };

View File

@ -140,15 +140,26 @@ void pb::SelectDatFile(const std::vector<const char*>& dataSearchPaths)
// Default game data test order: CADET.DAT, PINBALL.DAT, DEMO.DAT // Default game data test order: CADET.DAT, PINBALL.DAT, DEMO.DAT
if (options::Options.Prefer3DPBGameData) if (options::Options.Prefer3DPBGameData)
{
std::swap(datFileNames[0], datFileNames[1]); std::swap(datFileNames[0], datFileNames[1]);
}
for (auto path : dataSearchPaths) for (auto path : dataSearchPaths)
{ {
if (DatFileName.empty() && path) if (!DatFileName.empty() || !path)
continue;
BasePath = path;
for (const auto& datFileName : datFileNames)
{ {
BasePath = path; auto fileName = datFileName;
for (auto datFileName : datFileNames) auto found = false;
for (int i = 0; i < 2; i++)
{ {
auto datFilePath = make_path_name(datFileName); if (i == 1)
std::transform(fileName.begin(), fileName.end(), fileName.begin(),
[](unsigned char c) { return std::tolower(c); });
auto datFilePath = make_path_name(fileName);
auto datFile = fopenu(datFilePath.c_str(), "r"); auto datFile = fopenu(datFilePath.c_str(), "r");
if (datFile) if (datFile)
{ {
@ -158,11 +169,14 @@ void pb::SelectDatFile(const std::vector<const char*>& dataSearchPaths)
FullTiltMode = true; FullTiltMode = true;
if (datFileName == "DEMO.DAT") if (datFileName == "DEMO.DAT")
FullTiltDemoMode = FullTiltMode = true; FullTiltDemoMode = FullTiltMode = true;
printf("Loading game from: %s\n", datFilePath.c_str()); printf("Loading game from: %s\n", datFilePath.c_str());
found = true;
break; break;
} }
} }
if (found)
break;
} }
} }
} }