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
This commit is contained in:
bladeoner 2018-07-29 19:33:25 +02:00 committed by GitHub
parent 8ea78dde4a
commit 74f3ee4caf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 83 additions and 62 deletions

View File

@ -510,7 +510,7 @@ bool8 S9xInitSound (int buffer_ms, int lag_ms)
return (FALSE); return (FALSE);
if (msu::landing_buffer) if (msu::landing_buffer)
delete[] 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) if (!msu::landing_buffer)
return (FALSE); return (FALSE);
@ -635,6 +635,8 @@ void S9xDeinitAPU (void)
delete[] msu::resample_buffer; delete[] msu::resample_buffer;
msu::resample_buffer = NULL; msu::resample_buffer = NULL;
} }
S9xMSU1DeInit();
} }
static inline int S9xAPUGetClock (int32 cpucycles) static inline int S9xAPUGetClock (int32 cpucycles)

View File

@ -17,7 +17,7 @@ class Resampler : public ring_buffer
{ {
} }
~Resampler () virtual ~Resampler ()
{ {
} }

View File

@ -4082,7 +4082,10 @@ static bool8 ReadBPSPatch (Reader *r, long, int32 &rom_size)
switch((int)mode) { switch((int)mode) {
case SourceRead: case SourceRead:
while(length--) patched_rom[outputOffset++] = Memory.ROM[outputOffset]; while(length--) {
patched_rom[outputOffset] = Memory.ROM[outputOffset];
outputOffset++;
}
break; break;
case TargetRead: case TargetRead:
while(length--) patched_rom[outputOffset++] = data[addr++]; 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")) if (strcasecmp(ext, "msu1") && strcasecmp(ext, ".msu1"))
{ {
_makepath(fname, drive, dir, name, "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); printf(" in %s", fname);
ret = ReadBPSPatch(new unzReader(file), offset, rom_size); Stream *s = new unzStream(msu1file);
unzCloseCurrentFile(file); ret = ReadBPSPatch(s, offset, rom_size);
s->closeStream();
if (ret) if (ret)
printf("!\n"); printf("!\n");

View File

@ -200,7 +200,7 @@
STREAM dataStream = NULL; STREAM dataStream = NULL;
STREAM audioStream = NULL; STREAM audioStream = NULL;
uint32 audioLoopPos; uint32 audioLoopPos;
size_t partial_samples; size_t partial_frames;
// Sample buffer // Sample buffer
int16 *bufPos, *bufBegin, *bufEnd; int16 *bufPos, *bufBegin, *bufEnd;
@ -239,17 +239,22 @@ static int unzFindExtension(unzFile &file, const char *ext, bool restart = TRUE,
} }
#endif #endif
STREAM S9xMSU1OpenFile(char *msu_ext) STREAM S9xMSU1OpenFile(const char *msu_ext, bool skip_unpacked)
{ {
char filename[MAXPATHLEN]; char filename[MAXPATHLEN];
sprintf(filename, "%s%s%s", Memory.ROMFilePath, Memory.ROMFilename, msu_ext); sprintf(filename, "%s%s%s", Memory.ROMFilePath, Memory.ROMFilename, msu_ext);
STREAM file = OPEN_STREAM(filename, "rb"); STREAM file = 0;
if (file)
printf("Using msu file %s.\n", filename); if (!skip_unpacked)
{
file = OPEN_STREAM(filename, "rb");
if (file)
printf("Using msu file %s.\n", filename);
}
#ifdef UNZIP_SUPPORT #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) if (!file)
{ {
char zip_filename[MAXPATHLEN]; char zip_filename[MAXPATHLEN];
@ -265,26 +270,28 @@ STREAM S9xMSU1OpenFile(char *msu_ext)
file = new unzStream(unzFile); file = new unzStream(unzFile);
} }
else else
unzCloseCurrentFile(unzFile); unzClose(unzFile);
} }
} }
#endif #endif
if(!file)
printf("Unable to find msu file %s.\n", filename);
return file; return file;
} }
bool AudioOpen() static void AudioClose()
{
if (audioStream)
{
CLOSE_STREAM(audioStream);
audioStream = NULL;
}
}
static bool AudioOpen()
{ {
MSU1.MSU1_STATUS |= AudioError; MSU1.MSU1_STATUS |= AudioError;
if (audioStream) AudioClose();
{
CLOSE_STREAM(audioStream);
audioStream = NULL;
}
char ext[_MAX_EXT]; char ext[_MAX_EXT];
snprintf(ext, _MAX_EXT, "-%d.pcm", MSU1.MSU1_CURRENT_TRACK); snprintf(ext, _MAX_EXT, "-%d.pcm", MSU1.MSU1_CURRENT_TRACK);
@ -305,6 +312,8 @@ bool AudioOpen()
audioLoopPos = GET_LE32(&audioLoopPos); audioLoopPos = GET_LE32(&audioLoopPos);
audioLoopPos <<= 2; audioLoopPos <<= 2;
audioLoopPos += 8; audioLoopPos += 8;
MSU1.MSU1_AUDIO_POS = 8;
MSU1.MSU1_STATUS &= ~AudioError; MSU1.MSU1_STATUS &= ~AudioError;
return true; return true;
@ -313,13 +322,18 @@ bool AudioOpen()
return false; return false;
} }
bool DataOpen() static void DataClose()
{ {
if (dataStream) if (dataStream)
{ {
CLOSE_STREAM(dataStream); CLOSE_STREAM(dataStream);
dataStream = NULL; dataStream = NULL;
} }
}
static bool DataOpen()
{
DataClose();
dataStream = S9xMSU1OpenFile(".msu"); dataStream = S9xMSU1OpenFile(".msu");
@ -347,19 +361,11 @@ void S9xResetMSU(void)
bufBegin = 0; bufBegin = 0;
bufEnd = 0; bufEnd = 0;
partial_samples = 0; partial_frames = 0;
if (dataStream) DataClose();
{
CLOSE_STREAM(dataStream);
dataStream = NULL;
}
if (audioStream) AudioClose();
{
CLOSE_STREAM(audioStream);
audioStream = NULL;
}
Settings.MSU1 = S9xMSU1ROMExists(); Settings.MSU1 = S9xMSU1ROMExists();
} }
@ -369,6 +375,13 @@ void S9xMSU1Init(void)
DataOpen(); DataOpen();
} }
void S9xMSU1DeInit(void)
{
DataClose();
AudioClose();
}
bool S9xMSU1ROMExists(void) bool S9xMSU1ROMExists(void)
{ {
STREAM s = S9xMSU1OpenFile(".msu"); STREAM s = S9xMSU1OpenFile(".msu");
@ -384,7 +397,7 @@ bool S9xMSU1ROMExists(void)
if (unzFile) if (unzFile)
{ {
unzCloseCurrentFile(unzFile); unzClose(unzFile);
return true; return true;
} }
#endif #endif
@ -393,31 +406,30 @@ bool S9xMSU1ROMExists(void)
void S9xMSU1Generate(size_t sample_count) 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) if (MSU1.MSU1_STATUS & AudioPlaying && audioStream)
{ {
int16 sample; int32 sample;
int bytes_read = READ_STREAM((char *)&sample, 2, audioStream); int16* left = (int16*)&sample;
if (bytes_read == 2) int16* right = left + 1;
{
sample = (int16)((double)(int16)GET_LE16(&sample) * (double)MSU1.MSU1_VOLUME / 255.0);
*(bufPos++) = sample; int bytes_read = READ_STREAM((char *)&sample, 4, audioStream);
MSU1.MSU1_AUDIO_POS += 2; if (bytes_read == 4)
partial_samples -= 3204; {
*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 else
if (bytes_read >= 0) 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) if (MSU1.MSU1_STATUS & AudioRepeating)
{ {
MSU1.MSU1_AUDIO_POS = audioLoopPos; MSU1.MSU1_AUDIO_POS = audioLoopPos;
@ -437,7 +449,8 @@ void S9xMSU1Generate(size_t sample_count)
else else
{ {
MSU1.MSU1_STATUS &= ~(AudioPlaying | AudioRepeating); MSU1.MSU1_STATUS &= ~(AudioPlaying | AudioRepeating);
partial_samples -= 3204; partial_frames -= 3204;
*(bufPos++) = 0;
*(bufPos++) = 0; *(bufPos++) = 0;
} }
} }
@ -449,7 +462,7 @@ uint8 S9xMSU1ReadPort(uint8 port)
switch (port) switch (port)
{ {
case 0: case 0:
return MSU1.MSU1_STATUS; return MSU1.MSU1_STATUS | MSU1_REVISION;
case 1: case 1:
{ {
if (MSU1.MSU1_STATUS & DataBusy) if (MSU1.MSU1_STATUS & DataBusy)
@ -594,5 +607,5 @@ void S9xMSU1PostLoadState(void)
bufBegin = 0; bufBegin = 0;
bufEnd = 0; bufEnd = 0;
partial_samples = 0; partial_frames = 0;
} }

View File

@ -196,6 +196,8 @@
#include <stdint.h> #include <stdint.h>
#include <sys\stat.h> #include <sys\stat.h>
#define MSU1_REVISION 0x02
struct SMSU1 struct SMSU1
{ {
uint8 MSU1_STATUS; uint8 MSU1_STATUS;
@ -211,8 +213,7 @@ struct SMSU1
}; };
enum SMSU1_FLAG { enum SMSU1_FLAG {
Revision = 0x02, //max: 0x07 Revision = 0x07, // bitmask, not the actual version number
AudioResume = 0x04,
AudioError = 0x08, AudioError = 0x08,
AudioPlaying = 0x10, AudioPlaying = 0x10,
AudioRepeating = 0x20, AudioRepeating = 0x20,
@ -230,8 +231,9 @@ extern struct SMSU1 MSU1;
void S9xResetMSU(void); void S9xResetMSU(void);
void S9xMSU1Init(void); void S9xMSU1Init(void);
void S9xMSU1DeInit(void);
bool S9xMSU1ROMExists(void); bool S9xMSU1ROMExists(void);
STREAM S9xMSU1OpenFile(char *msu_ext); STREAM S9xMSU1OpenFile(const char *msu_ext, bool skip_unpacked = FALSE);
void S9xMSU1Init(void); void S9xMSU1Init(void);
void S9xMSU1Generate(size_t sample_count); void S9xMSU1Generate(size_t sample_count);
uint8 S9xMSU1ReadPort(uint8 port); uint8 S9xMSU1ReadPort(uint8 port);