From 74f3ee4cafb68f1956f34296952e78ac155ca9bf Mon Sep 17 00:00:00 2001 From: bladeoner Date: Sun, 29 Jul 2018 19:33:25 +0200 Subject: [PATCH] MSU1 fixes backported The following fixes are backported from the Snes9x master branch: - Release msu data and audio streams on exit, use unzClose when closing - Fix MSU-1 channel swap on loop - Ensure all MSU-1 reads are stereo channel aligned - Clean up S9xMSU1Generate code - Fix MSU1 swapping. - Fix casting on MSU1 volume - Get rid of "Unable to find msu file" console spam --- source/snes9x/apu/apu.cpp | 4 +- source/snes9x/apu/resampler.h | 2 +- source/snes9x/memmap.cpp | 12 ++-- source/snes9x/msu1.cpp | 119 +++++++++++++++++++--------------- source/snes9x/msu1.h | 8 ++- 5 files changed, 83 insertions(+), 62 deletions(-) diff --git a/source/snes9x/apu/apu.cpp b/source/snes9x/apu/apu.cpp index d9b07f6..2337b78 100644 --- a/source/snes9x/apu/apu.cpp +++ b/source/snes9x/apu/apu.cpp @@ -510,7 +510,7 @@ bool8 S9xInitSound (int buffer_ms, int lag_ms) return (FALSE); if (msu::landing_buffer) delete[] msu::landing_buffer; - msu::landing_buffer = new uint8[msu::buffer_size * 2]; + msu::landing_buffer = (uint8*) new uint32[msu::buffer_size / 2]; // Ensure 4-byte alignment if (!msu::landing_buffer) return (FALSE); @@ -635,6 +635,8 @@ void S9xDeinitAPU (void) delete[] msu::resample_buffer; msu::resample_buffer = NULL; } + + S9xMSU1DeInit(); } static inline int S9xAPUGetClock (int32 cpucycles) diff --git a/source/snes9x/apu/resampler.h b/source/snes9x/apu/resampler.h index 2e62add..267546f 100644 --- a/source/snes9x/apu/resampler.h +++ b/source/snes9x/apu/resampler.h @@ -17,7 +17,7 @@ class Resampler : public ring_buffer { } - ~Resampler () + virtual ~Resampler () { } diff --git a/source/snes9x/memmap.cpp b/source/snes9x/memmap.cpp index d106435..2aa1d0a 100644 --- a/source/snes9x/memmap.cpp +++ b/source/snes9x/memmap.cpp @@ -4082,7 +4082,10 @@ static bool8 ReadBPSPatch (Reader *r, long, int32 &rom_size) switch((int)mode) { case SourceRead: - while(length--) patched_rom[outputOffset++] = Memory.ROM[outputOffset]; + while(length--) { + patched_rom[outputOffset] = Memory.ROM[outputOffset]; + outputOffset++; + } break; case TargetRead: while(length--) patched_rom[outputOffset++] = data[addr++]; @@ -4337,7 +4340,7 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r } } - // Mercurial Magic (MSU-1 distribution pack) + // Mercurial Magic (MSU-1 distribution pack) if (strcasecmp(ext, "msu1") && strcasecmp(ext, ".msu1")) { _makepath(fname, drive, dir, name, "msu1"); @@ -4350,8 +4353,9 @@ void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &r { printf(" in %s", fname); - ret = ReadBPSPatch(new unzReader(file), offset, rom_size); - unzCloseCurrentFile(file); + Stream *s = new unzStream(msu1file); + ret = ReadBPSPatch(s, offset, rom_size); + s->closeStream(); if (ret) printf("!\n"); diff --git a/source/snes9x/msu1.cpp b/source/snes9x/msu1.cpp index bd8911b..6f63bcb 100644 --- a/source/snes9x/msu1.cpp +++ b/source/snes9x/msu1.cpp @@ -200,7 +200,7 @@ STREAM dataStream = NULL; STREAM audioStream = NULL; uint32 audioLoopPos; -size_t partial_samples; +size_t partial_frames; // Sample buffer int16 *bufPos, *bufBegin, *bufEnd; @@ -239,17 +239,22 @@ static int unzFindExtension(unzFile &file, const char *ext, bool restart = TRUE, } #endif -STREAM S9xMSU1OpenFile(char *msu_ext) +STREAM S9xMSU1OpenFile(const char *msu_ext, bool skip_unpacked) { char filename[MAXPATHLEN]; sprintf(filename, "%s%s%s", Memory.ROMFilePath, Memory.ROMFilename, msu_ext); - STREAM file = OPEN_STREAM(filename, "rb"); - if (file) - printf("Using msu file %s.\n", filename); + STREAM file = 0; + + if (!skip_unpacked) + { + file = OPEN_STREAM(filename, "rb"); + if (file) + printf("Using msu file %s.\n", filename); + } #ifdef UNZIP_SUPPORT - // look for msu file in .msu1 (Mercurial Magic pack) if not found in rom dir + // look for msu1 pack file in the rom or patch dir if msu data file not found in rom dir if (!file) { char zip_filename[MAXPATHLEN]; @@ -265,26 +270,28 @@ STREAM S9xMSU1OpenFile(char *msu_ext) file = new unzStream(unzFile); } else - unzCloseCurrentFile(unzFile); + unzClose(unzFile); } } #endif - if(!file) - printf("Unable to find msu file %s.\n", filename); - return file; } -bool AudioOpen() +static void AudioClose() +{ + if (audioStream) + { + CLOSE_STREAM(audioStream); + audioStream = NULL; + } +} + +static bool AudioOpen() { MSU1.MSU1_STATUS |= AudioError; - if (audioStream) - { - CLOSE_STREAM(audioStream); - audioStream = NULL; - } + AudioClose(); char ext[_MAX_EXT]; snprintf(ext, _MAX_EXT, "-%d.pcm", MSU1.MSU1_CURRENT_TRACK); @@ -305,6 +312,8 @@ bool AudioOpen() audioLoopPos = GET_LE32(&audioLoopPos); audioLoopPos <<= 2; audioLoopPos += 8; + + MSU1.MSU1_AUDIO_POS = 8; MSU1.MSU1_STATUS &= ~AudioError; return true; @@ -313,13 +322,18 @@ bool AudioOpen() return false; } -bool DataOpen() +static void DataClose() { - if (dataStream) - { - CLOSE_STREAM(dataStream); - dataStream = NULL; - } + if (dataStream) + { + CLOSE_STREAM(dataStream); + dataStream = NULL; + } +} + +static bool DataOpen() +{ + DataClose(); dataStream = S9xMSU1OpenFile(".msu"); @@ -347,19 +361,11 @@ void S9xResetMSU(void) bufBegin = 0; bufEnd = 0; - partial_samples = 0; + partial_frames = 0; - if (dataStream) - { - CLOSE_STREAM(dataStream); - dataStream = NULL; - } + DataClose(); - if (audioStream) - { - CLOSE_STREAM(audioStream); - audioStream = NULL; - } + AudioClose(); Settings.MSU1 = S9xMSU1ROMExists(); } @@ -369,6 +375,13 @@ void S9xMSU1Init(void) DataOpen(); } +void S9xMSU1DeInit(void) +{ + DataClose(); + AudioClose(); +} + + bool S9xMSU1ROMExists(void) { STREAM s = S9xMSU1OpenFile(".msu"); @@ -384,7 +397,7 @@ bool S9xMSU1ROMExists(void) if (unzFile) { - unzCloseCurrentFile(unzFile); + unzClose(unzFile); return true; } #endif @@ -393,31 +406,30 @@ bool S9xMSU1ROMExists(void) void S9xMSU1Generate(size_t sample_count) { - partial_samples += 4410 * sample_count; + partial_frames += 4410 * (sample_count / 2); - while (((uintptr_t)bufPos < (uintptr_t)bufEnd) && partial_samples > 3204) + while ((bufPos < (bufEnd - 2)) && partial_frames >= 3204) { if (MSU1.MSU1_STATUS & AudioPlaying && audioStream) { - int16 sample; - int bytes_read = READ_STREAM((char *)&sample, 2, audioStream); - if (bytes_read == 2) - { - sample = (int16)((double)(int16)GET_LE16(&sample) * (double)MSU1.MSU1_VOLUME / 255.0); + int32 sample; + int16* left = (int16*)&sample; + int16* right = left + 1; - *(bufPos++) = sample; - MSU1.MSU1_AUDIO_POS += 2; - partial_samples -= 3204; + int bytes_read = READ_STREAM((char *)&sample, 4, audioStream); + if (bytes_read == 4) + { + *left = ((int32)(int16)GET_LE16(left) * MSU1.MSU1_VOLUME / 255); + *right = ((int32)(int16)GET_LE16(right) * MSU1.MSU1_VOLUME / 255); + + *(bufPos++) = *left; + *(bufPos++) = *right; + MSU1.MSU1_AUDIO_POS += 4; + partial_frames -= 3204; } else if (bytes_read >= 0) { - sample = (int16)((double)(int16)GET_LE16(&sample) * (double)MSU1.MSU1_VOLUME / 255.0); - - *(bufPos++) = sample; - MSU1.MSU1_AUDIO_POS += 2; - partial_samples -= 3204; - if (MSU1.MSU1_STATUS & AudioRepeating) { MSU1.MSU1_AUDIO_POS = audioLoopPos; @@ -437,7 +449,8 @@ void S9xMSU1Generate(size_t sample_count) else { MSU1.MSU1_STATUS &= ~(AudioPlaying | AudioRepeating); - partial_samples -= 3204; + partial_frames -= 3204; + *(bufPos++) = 0; *(bufPos++) = 0; } } @@ -449,7 +462,7 @@ uint8 S9xMSU1ReadPort(uint8 port) switch (port) { case 0: - return MSU1.MSU1_STATUS; + return MSU1.MSU1_STATUS | MSU1_REVISION; case 1: { if (MSU1.MSU1_STATUS & DataBusy) @@ -594,5 +607,5 @@ void S9xMSU1PostLoadState(void) bufBegin = 0; bufEnd = 0; - partial_samples = 0; + partial_frames = 0; } diff --git a/source/snes9x/msu1.h b/source/snes9x/msu1.h index a0ff8b2..37d635b 100644 --- a/source/snes9x/msu1.h +++ b/source/snes9x/msu1.h @@ -196,6 +196,8 @@ #include #include +#define MSU1_REVISION 0x02 + struct SMSU1 { uint8 MSU1_STATUS; @@ -211,8 +213,7 @@ struct SMSU1 }; enum SMSU1_FLAG { - Revision = 0x02, //max: 0x07 - AudioResume = 0x04, + Revision = 0x07, // bitmask, not the actual version number AudioError = 0x08, AudioPlaying = 0x10, AudioRepeating = 0x20, @@ -230,8 +231,9 @@ extern struct SMSU1 MSU1; void S9xResetMSU(void); void S9xMSU1Init(void); +void S9xMSU1DeInit(void); bool S9xMSU1ROMExists(void); -STREAM S9xMSU1OpenFile(char *msu_ext); +STREAM S9xMSU1OpenFile(const char *msu_ext, bool skip_unpacked = FALSE); void S9xMSU1Init(void); void S9xMSU1Generate(size_t sample_count); uint8 S9xMSU1ReadPort(uint8 port);