mirror of https://github.com/snes9xgit/snes9x.git
Merge branch 'msu1-zip'
This commit is contained in:
commit
b22f5b5c44
177
msu1.cpp
177
msu1.cpp
|
@ -197,37 +197,110 @@
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
std::ifstream dataFile, audioFile;
|
STREAM dataStream = NULL;
|
||||||
|
STREAM audioStream = NULL;
|
||||||
uint32 audioLoopPos;
|
uint32 audioLoopPos;
|
||||||
uint32 partial_samples;
|
uint32 partial_samples;
|
||||||
|
|
||||||
// Sample buffer
|
// Sample buffer
|
||||||
int16 *bufPos, *bufBegin, *bufEnd;
|
int16 *bufPos, *bufBegin, *bufEnd;
|
||||||
|
|
||||||
|
#ifdef UNZIP_SUPPORT
|
||||||
|
static int unzFindExtension(unzFile &file, const char *ext, bool restart = TRUE, bool print = TRUE)
|
||||||
|
{
|
||||||
|
unz_file_info info;
|
||||||
|
int port, l = strlen(ext);
|
||||||
|
|
||||||
|
if (restart)
|
||||||
|
port = unzGoToFirstFile(file);
|
||||||
|
else
|
||||||
|
port = unzGoToNextFile(file);
|
||||||
|
|
||||||
|
while (port == UNZ_OK)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
char name[132];
|
||||||
|
|
||||||
|
unzGetCurrentFileInfo(file, &info, name, 128, NULL, 0, NULL, 0);
|
||||||
|
len = strlen(name);
|
||||||
|
|
||||||
|
if (len >= l + 1 && strcasecmp(name + len - l, ext) == 0 && unzOpenCurrentFile(file) == UNZ_OK)
|
||||||
|
{
|
||||||
|
if (print)
|
||||||
|
printf("Using msu file %s", name);
|
||||||
|
|
||||||
|
return (port);
|
||||||
|
}
|
||||||
|
|
||||||
|
port = unzGoToNextFile(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (port);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
STREAM S9xMSU1OpenFile(char *msu_ext)
|
||||||
|
{
|
||||||
|
const char *filename = S9xGetFilename(msu_ext, ROMFILENAME_DIR);
|
||||||
|
STREAM file = OPEN_STREAM(filename, "rb");
|
||||||
|
if (file)
|
||||||
|
printf("Using msu file %s.\n", filename);
|
||||||
|
|
||||||
|
#ifdef UNZIP_SUPPORT
|
||||||
|
// look for msu file in .msu.zip if not found in rom dir
|
||||||
|
if (!file)
|
||||||
|
{
|
||||||
|
const char *zip_filename = S9xGetFilename(".msu.zip", ROMFILENAME_DIR);
|
||||||
|
if (zip_filename)
|
||||||
|
{
|
||||||
|
unzFile unzFile = unzOpen(zip_filename);
|
||||||
|
if (unzFile)
|
||||||
|
{
|
||||||
|
int port = unzFindExtension(unzFile, msu_ext);
|
||||||
|
if (port == UNZ_OK)
|
||||||
|
{
|
||||||
|
printf(" in %s.\n", zip_filename);
|
||||||
|
file = new unzStream(unzFile);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
unzCloseCurrentFile(unzFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(!file)
|
||||||
|
printf("Unable to find msu file %s.\n", filename);
|
||||||
|
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
bool AudioOpen()
|
bool AudioOpen()
|
||||||
{
|
{
|
||||||
MSU1.MSU1_STATUS |= AudioError;
|
MSU1.MSU1_STATUS |= AudioError;
|
||||||
|
|
||||||
if (audioFile.is_open())
|
if (audioStream)
|
||||||
audioFile.close();
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
audioFile.clear();
|
audioStream = S9xMSU1OpenFile(ext);
|
||||||
audioFile.open(S9xGetFilename(ext, ROMFILENAME_DIR), std::ios::in | std::ios::binary);
|
if (audioStream)
|
||||||
if (audioFile.good())
|
|
||||||
{
|
{
|
||||||
if (audioFile.get() != 'M')
|
if (GETC_STREAM(audioStream) != 'M')
|
||||||
return false;
|
return false;
|
||||||
if (audioFile.get() != 'S')
|
if (GETC_STREAM(audioStream) != 'S')
|
||||||
return false;
|
return false;
|
||||||
if (audioFile.get() != 'U')
|
if (GETC_STREAM(audioStream) != 'U')
|
||||||
return false;
|
return false;
|
||||||
if (audioFile.get() != '1')
|
if (GETC_STREAM(audioStream) != '1')
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
audioFile.read((char *)&audioLoopPos, 4);
|
READ_STREAM((char *)&audioLoopPos, 4, audioStream);
|
||||||
audioLoopPos = GET_LE32(&audioLoopPos);
|
audioLoopPos = GET_LE32(&audioLoopPos);
|
||||||
audioLoopPos <<= 2;
|
audioLoopPos <<= 2;
|
||||||
audioLoopPos += 8;
|
audioLoopPos += 8;
|
||||||
|
@ -241,12 +314,14 @@ bool AudioOpen()
|
||||||
|
|
||||||
bool DataOpen()
|
bool DataOpen()
|
||||||
{
|
{
|
||||||
if (dataFile.is_open())
|
if (dataStream)
|
||||||
dataFile.close();
|
{
|
||||||
|
CLOSE_STREAM(dataStream);
|
||||||
|
dataStream = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
dataFile.clear();
|
dataStream = S9xMSU1OpenFile(".msu");
|
||||||
dataFile.open(S9xGetFilename(".msu", ROMFILENAME_DIR), std::ios::in | std::ios::binary);
|
return dataStream != NULL;
|
||||||
return dataFile.is_open();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void S9xResetMSU(void)
|
void S9xResetMSU(void)
|
||||||
|
@ -269,11 +344,17 @@ void S9xResetMSU(void)
|
||||||
|
|
||||||
partial_samples = 0;
|
partial_samples = 0;
|
||||||
|
|
||||||
if (dataFile.is_open())
|
if (dataStream)
|
||||||
dataFile.close();
|
{
|
||||||
|
CLOSE_STREAM(dataStream);
|
||||||
|
dataStream = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (audioFile.is_open())
|
if (audioStream)
|
||||||
audioFile.close();
|
{
|
||||||
|
CLOSE_STREAM(audioStream);
|
||||||
|
audioStream = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
Settings.MSU1 = S9xMSU1ROMExists();
|
Settings.MSU1 = S9xMSU1ROMExists();
|
||||||
}
|
}
|
||||||
|
@ -286,8 +367,12 @@ void S9xMSU1Init(void)
|
||||||
|
|
||||||
bool S9xMSU1ROMExists(void)
|
bool S9xMSU1ROMExists(void)
|
||||||
{
|
{
|
||||||
struct stat buf;
|
struct stat buf;
|
||||||
return (stat(S9xGetFilename(".msu", ROMFILENAME_DIR), &buf) == 0);
|
STREAM s = S9xMSU1OpenFile(".msu");
|
||||||
|
bool8 exists = (s != NULL);
|
||||||
|
if(s)
|
||||||
|
CLOSE_STREAM(s);
|
||||||
|
return exists;
|
||||||
}
|
}
|
||||||
|
|
||||||
void S9xMSU1Generate(int sample_count)
|
void S9xMSU1Generate(int sample_count)
|
||||||
|
@ -296,10 +381,11 @@ void S9xMSU1Generate(int sample_count)
|
||||||
|
|
||||||
while (((uintptr_t)bufPos < (uintptr_t)bufEnd) && (MSU1.MSU1_STATUS & AudioPlaying) && partial_samples > 32040)
|
while (((uintptr_t)bufPos < (uintptr_t)bufEnd) && (MSU1.MSU1_STATUS & AudioPlaying) && partial_samples > 32040)
|
||||||
{
|
{
|
||||||
if (audioFile.is_open())
|
if (audioStream)
|
||||||
{
|
{
|
||||||
int16 sample;
|
int16 sample;
|
||||||
if (audioFile.read((char *)&sample, 2).good())
|
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);
|
sample = (int16)((double)(int16)GET_LE16(&sample) * (double)MSU1.MSU1_VOLUME / 255.0);
|
||||||
|
|
||||||
|
@ -308,7 +394,7 @@ void S9xMSU1Generate(int sample_count)
|
||||||
partial_samples -= 32040;
|
partial_samples -= 32040;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (audioFile.eof())
|
if (bytes_read >= 0)
|
||||||
{
|
{
|
||||||
sample = (int16)((double)(int16)GET_LE16(&sample) * (double)MSU1.MSU1_VOLUME / 255.0);
|
sample = (int16)((double)(int16)GET_LE16(&sample) * (double)MSU1.MSU1_VOLUME / 255.0);
|
||||||
|
|
||||||
|
@ -318,15 +404,13 @@ void S9xMSU1Generate(int sample_count)
|
||||||
|
|
||||||
if (MSU1.MSU1_STATUS & AudioRepeating)
|
if (MSU1.MSU1_STATUS & AudioRepeating)
|
||||||
{
|
{
|
||||||
audioFile.clear();
|
|
||||||
MSU1.MSU1_AUDIO_POS = audioLoopPos;
|
MSU1.MSU1_AUDIO_POS = audioLoopPos;
|
||||||
audioFile.seekg(MSU1.MSU1_AUDIO_POS);
|
REVERT_STREAM(audioStream, MSU1.MSU1_AUDIO_POS, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MSU1.MSU1_STATUS &= ~(AudioPlaying | AudioRepeating);
|
MSU1.MSU1_STATUS &= ~(AudioPlaying | AudioRepeating);
|
||||||
audioFile.clear();
|
REVERT_STREAM(audioStream, 8, 0);
|
||||||
audioFile.seekg(8);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -352,12 +436,19 @@ uint8 S9xMSU1ReadPort(int port)
|
||||||
case 0:
|
case 0:
|
||||||
return MSU1.MSU1_STATUS;
|
return MSU1.MSU1_STATUS;
|
||||||
case 1:
|
case 1:
|
||||||
if (MSU1.MSU1_STATUS & DataBusy)
|
{
|
||||||
return 0;
|
if (MSU1.MSU1_STATUS & DataBusy)
|
||||||
if (dataFile.fail() || dataFile.bad() || dataFile.eof())
|
return 0;
|
||||||
return 0;
|
if (!dataStream)
|
||||||
MSU1.MSU1_DATA_POS++;
|
return 0;
|
||||||
return dataFile.get();
|
int data = GETC_STREAM(dataStream);
|
||||||
|
if (data >= 0)
|
||||||
|
{
|
||||||
|
MSU1.MSU1_DATA_POS++;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
case 2:
|
case 2:
|
||||||
return 'S';
|
return 'S';
|
||||||
case 3:
|
case 3:
|
||||||
|
@ -396,8 +487,10 @@ void S9xMSU1WritePort(int port, uint8 byte)
|
||||||
MSU1.MSU1_DATA_SEEK &= 0x00FFFFFF;
|
MSU1.MSU1_DATA_SEEK &= 0x00FFFFFF;
|
||||||
MSU1.MSU1_DATA_SEEK |= byte << 24;
|
MSU1.MSU1_DATA_SEEK |= byte << 24;
|
||||||
MSU1.MSU1_DATA_POS = MSU1.MSU1_DATA_SEEK;
|
MSU1.MSU1_DATA_POS = MSU1.MSU1_DATA_SEEK;
|
||||||
if(dataFile.good())
|
if (dataStream)
|
||||||
dataFile.seekg(MSU1.MSU1_DATA_POS);
|
{
|
||||||
|
REVERT_STREAM(dataStream, MSU1.MSU1_DATA_POS, 0);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
MSU1.MSU1_TRACK_SEEK &= 0xFF00;
|
MSU1.MSU1_TRACK_SEEK &= 0xFF00;
|
||||||
|
@ -424,7 +517,7 @@ void S9xMSU1WritePort(int port, uint8 byte)
|
||||||
MSU1.MSU1_AUDIO_POS = 8;
|
MSU1.MSU1_AUDIO_POS = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
audioFile.seekg(MSU1.MSU1_AUDIO_POS);
|
REVERT_STREAM(audioStream, MSU1.MSU1_AUDIO_POS, 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
|
@ -460,20 +553,20 @@ void S9xMSU1PostLoadState(void)
|
||||||
{
|
{
|
||||||
if (DataOpen())
|
if (DataOpen())
|
||||||
{
|
{
|
||||||
dataFile.seekg(MSU1.MSU1_DATA_POS);
|
REVERT_STREAM(dataStream, MSU1.MSU1_DATA_POS, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MSU1.MSU1_STATUS & AudioPlaying)
|
if (MSU1.MSU1_STATUS & AudioPlaying)
|
||||||
{
|
{
|
||||||
if (AudioOpen())
|
if (AudioOpen())
|
||||||
{
|
{
|
||||||
audioFile.seekg(4);
|
REVERT_STREAM(audioStream, 4, 0);
|
||||||
audioFile.read((char *)&audioLoopPos, 4);
|
READ_STREAM((char *)&audioLoopPos, 4, audioStream);
|
||||||
audioLoopPos = GET_LE32(&audioLoopPos);
|
audioLoopPos = GET_LE32(&audioLoopPos);
|
||||||
audioLoopPos <<= 2;
|
audioLoopPos <<= 2;
|
||||||
audioLoopPos += 8;
|
audioLoopPos += 8;
|
||||||
|
|
||||||
audioFile.seekg(MSU1.MSU1_AUDIO_POS);
|
REVERT_STREAM(audioStream, MSU1.MSU1_AUDIO_POS, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
2
msu1.h
2
msu1.h
|
@ -229,6 +229,8 @@ extern struct SMSU1 MSU1;
|
||||||
void S9xResetMSU(void);
|
void S9xResetMSU(void);
|
||||||
void S9xMSU1Init(void);
|
void S9xMSU1Init(void);
|
||||||
bool S9xMSU1ROMExists(void);
|
bool S9xMSU1ROMExists(void);
|
||||||
|
STREAM S9xMSU1OpenFile(char *msu_ext);
|
||||||
|
void S9xMSU1Init(void);
|
||||||
void S9xMSU1Generate(int sample_count);
|
void S9xMSU1Generate(int sample_count);
|
||||||
uint8 S9xMSU1ReadPort(int port);
|
uint8 S9xMSU1ReadPort(int port);
|
||||||
void S9xMSU1WritePort(int port, uint8 byte);
|
void S9xMSU1WritePort(int port, uint8 byte);
|
||||||
|
|
91
stream.cpp
91
stream.cpp
|
@ -315,8 +315,12 @@ void fStream::closeStream()
|
||||||
unzStream::unzStream (unzFile &v)
|
unzStream::unzStream (unzFile &v)
|
||||||
{
|
{
|
||||||
file = v;
|
file = v;
|
||||||
head = NULL;
|
pos_in_buf = 0;
|
||||||
numbytes = 0;
|
buf_pos_in_unzipped = unztell(file);
|
||||||
|
bytes_in_buf = 0;
|
||||||
|
|
||||||
|
// remember start pos for seeks
|
||||||
|
unzGetFilePos(file, &unz_file_start_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
unzStream::~unzStream (void)
|
unzStream::~unzStream (void)
|
||||||
|
@ -324,21 +328,31 @@ unzStream::~unzStream (void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t unzStream::buffer_remaining()
|
||||||
|
{
|
||||||
|
return bytes_in_buf - pos_in_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void unzStream::fill_buffer()
|
||||||
|
{
|
||||||
|
buf_pos_in_unzipped = unztell(file);
|
||||||
|
bytes_in_buf = unzReadCurrentFile(file, buffer, unz_BUFFSIZ);
|
||||||
|
pos_in_buf = 0;
|
||||||
|
}
|
||||||
|
|
||||||
int unzStream::get_char (void)
|
int unzStream::get_char (void)
|
||||||
{
|
{
|
||||||
unsigned char c;
|
unsigned char c;
|
||||||
|
|
||||||
if (numbytes <= 0)
|
if (buffer_remaining() <= 0)
|
||||||
{
|
{
|
||||||
numbytes = unzReadCurrentFile(file, buffer, unz_BUFFSIZ);
|
fill_buffer();
|
||||||
if (numbytes <= 0)
|
if (bytes_in_buf <= 0)
|
||||||
return (EOF);
|
return (EOF);
|
||||||
head = buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c = *head;
|
c = *(buffer + pos_in_buf);
|
||||||
head++;
|
pos_in_buf++;
|
||||||
numbytes--;
|
|
||||||
|
|
||||||
return ((int) c);
|
return ((int) c);
|
||||||
}
|
}
|
||||||
|
@ -373,28 +387,25 @@ size_t unzStream::read (void *buf, size_t len)
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
return (len);
|
return (len);
|
||||||
|
|
||||||
if (len <= numbytes)
|
size_t to_read = len;
|
||||||
{
|
uint8 *read_to = (uint8 * )buf;
|
||||||
memcpy(buf, head, len);
|
do
|
||||||
numbytes -= len;
|
{
|
||||||
head += len;
|
size_t in_buffer = buffer_remaining();
|
||||||
return (len);
|
if (to_read <= in_buffer)
|
||||||
}
|
{
|
||||||
|
memcpy(read_to, buffer + pos_in_buf, to_read);
|
||||||
|
pos_in_buf += to_read;
|
||||||
|
to_read = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
size_t numread = 0;
|
memcpy(read_to, buffer + pos_in_buf, in_buffer);
|
||||||
if (numbytes > 0)
|
to_read -= in_buffer;
|
||||||
{
|
fill_buffer();
|
||||||
memcpy(buf, head, numbytes);
|
} while (bytes_in_buf);
|
||||||
numread += numbytes;
|
|
||||||
head = NULL;
|
|
||||||
numbytes = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int l = unzReadCurrentFile(file, (uint8 *)buf + numread, len - numread);
|
return (len - to_read);
|
||||||
if (l > 0)
|
|
||||||
numread += l;
|
|
||||||
|
|
||||||
return (numread);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// not supported
|
// not supported
|
||||||
|
@ -405,7 +416,7 @@ size_t unzStream::write (void *buf, size_t len)
|
||||||
|
|
||||||
size_t unzStream::pos (void)
|
size_t unzStream::pos (void)
|
||||||
{
|
{
|
||||||
return (unztell(file));
|
return buf_pos_in_unzipped + pos_in_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t unzStream::size (void)
|
size_t unzStream::size (void)
|
||||||
|
@ -415,10 +426,26 @@ size_t unzStream::size (void)
|
||||||
return info.uncompressed_size;
|
return info.uncompressed_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
// not supported
|
|
||||||
int unzStream::revert (size_t from, size_t offset)
|
int unzStream::revert (size_t from, size_t offset)
|
||||||
{
|
{
|
||||||
return -1;
|
size_t target_pos = from + offset;
|
||||||
|
|
||||||
|
// new pos inside buffered data
|
||||||
|
if (target_pos >= buf_pos_in_unzipped && target_pos < buf_pos_in_unzipped + bytes_in_buf)
|
||||||
|
{
|
||||||
|
pos_in_buf = target_pos - buf_pos_in_unzipped;
|
||||||
|
}
|
||||||
|
else // outside of buffer, reset file and read until pos
|
||||||
|
{
|
||||||
|
unzGoToFilePos(file, &unz_file_start_pos);
|
||||||
|
int times_to_read = target_pos / unz_BUFFSIZ + 1;
|
||||||
|
for( int i = 0; i < times_to_read; i++)
|
||||||
|
{
|
||||||
|
fill_buffer();
|
||||||
|
}
|
||||||
|
pos_in_buf = target_pos % unz_BUFFSIZ;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void unzStream::closeStream()
|
void unzStream::closeStream()
|
||||||
|
|
9
stream.h
9
stream.h
|
@ -252,10 +252,15 @@ class unzStream : public Stream
|
||||||
virtual void closeStream();
|
virtual void closeStream();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void fill_buffer();
|
||||||
|
size_t buffer_remaining();
|
||||||
|
|
||||||
unzFile file;
|
unzFile file;
|
||||||
char buffer[unz_BUFFSIZ];
|
char buffer[unz_BUFFSIZ];
|
||||||
char *head;
|
size_t pos_in_buf;
|
||||||
size_t numbytes;
|
size_t buf_pos_in_unzipped;
|
||||||
|
size_t bytes_in_buf;
|
||||||
|
unz_file_pos unz_file_start_pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue