Merge branch 'msu1-zip'

This commit is contained in:
OV2 2017-06-12 21:52:26 +02:00
commit b22f5b5c44
4 changed files with 203 additions and 76 deletions

167
msu1.cpp
View File

@ -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();
} }
@ -287,7 +368,11 @@ 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) if (MSU1.MSU1_STATUS & DataBusy)
return 0; return 0;
if (dataFile.fail() || dataFile.bad() || dataFile.eof()) if (!dataStream)
return 0; return 0;
int data = GETC_STREAM(dataStream);
if (data >= 0)
{
MSU1.MSU1_DATA_POS++; MSU1.MSU1_DATA_POS++;
return dataFile.get(); 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
View File

@ -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);

View File

@ -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;
do
{ {
memcpy(buf, head, len); size_t in_buffer = buffer_remaining();
numbytes -= len; if (to_read <= in_buffer)
head += len; {
return (len); 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()

View File

@ -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