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

177
msu1.cpp
View File

@ -197,37 +197,110 @@
#include <fstream>
#include <sys/stat.h>
std::ifstream dataFile, audioFile;
STREAM dataStream = NULL;
STREAM audioStream = NULL;
uint32 audioLoopPos;
uint32 partial_samples;
// Sample buffer
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()
{
MSU1.MSU1_STATUS |= AudioError;
if (audioFile.is_open())
audioFile.close();
if (audioStream)
{
CLOSE_STREAM(audioStream);
audioStream = NULL;
}
char ext[_MAX_EXT];
snprintf(ext, _MAX_EXT, "-%d.pcm", MSU1.MSU1_CURRENT_TRACK);
audioFile.clear();
audioFile.open(S9xGetFilename(ext, ROMFILENAME_DIR), std::ios::in | std::ios::binary);
if (audioFile.good())
audioStream = S9xMSU1OpenFile(ext);
if (audioStream)
{
if (audioFile.get() != 'M')
if (GETC_STREAM(audioStream) != 'M')
return false;
if (audioFile.get() != 'S')
if (GETC_STREAM(audioStream) != 'S')
return false;
if (audioFile.get() != 'U')
if (GETC_STREAM(audioStream) != 'U')
return false;
if (audioFile.get() != '1')
if (GETC_STREAM(audioStream) != '1')
return false;
audioFile.read((char *)&audioLoopPos, 4);
READ_STREAM((char *)&audioLoopPos, 4, audioStream);
audioLoopPos = GET_LE32(&audioLoopPos);
audioLoopPos <<= 2;
audioLoopPos += 8;
@ -241,12 +314,14 @@ bool AudioOpen()
bool DataOpen()
{
if (dataFile.is_open())
dataFile.close();
if (dataStream)
{
CLOSE_STREAM(dataStream);
dataStream = NULL;
}
dataFile.clear();
dataFile.open(S9xGetFilename(".msu", ROMFILENAME_DIR), std::ios::in | std::ios::binary);
return dataFile.is_open();
dataStream = S9xMSU1OpenFile(".msu");
return dataStream != NULL;
}
void S9xResetMSU(void)
@ -269,11 +344,17 @@ void S9xResetMSU(void)
partial_samples = 0;
if (dataFile.is_open())
dataFile.close();
if (dataStream)
{
CLOSE_STREAM(dataStream);
dataStream = NULL;
}
if (audioFile.is_open())
audioFile.close();
if (audioStream)
{
CLOSE_STREAM(audioStream);
audioStream = NULL;
}
Settings.MSU1 = S9xMSU1ROMExists();
}
@ -286,8 +367,12 @@ void S9xMSU1Init(void)
bool S9xMSU1ROMExists(void)
{
struct stat buf;
return (stat(S9xGetFilename(".msu", ROMFILENAME_DIR), &buf) == 0);
struct stat buf;
STREAM s = S9xMSU1OpenFile(".msu");
bool8 exists = (s != NULL);
if(s)
CLOSE_STREAM(s);
return exists;
}
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)
{
if (audioFile.is_open())
if (audioStream)
{
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);
@ -308,7 +394,7 @@ void S9xMSU1Generate(int sample_count)
partial_samples -= 32040;
}
else
if (audioFile.eof())
if (bytes_read >= 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)
{
audioFile.clear();
MSU1.MSU1_AUDIO_POS = audioLoopPos;
audioFile.seekg(MSU1.MSU1_AUDIO_POS);
REVERT_STREAM(audioStream, MSU1.MSU1_AUDIO_POS, 0);
}
else
{
MSU1.MSU1_STATUS &= ~(AudioPlaying | AudioRepeating);
audioFile.clear();
audioFile.seekg(8);
REVERT_STREAM(audioStream, 8, 0);
return;
}
}
@ -352,12 +436,19 @@ uint8 S9xMSU1ReadPort(int port)
case 0:
return MSU1.MSU1_STATUS;
case 1:
if (MSU1.MSU1_STATUS & DataBusy)
return 0;
if (dataFile.fail() || dataFile.bad() || dataFile.eof())
return 0;
MSU1.MSU1_DATA_POS++;
return dataFile.get();
{
if (MSU1.MSU1_STATUS & DataBusy)
return 0;
if (!dataStream)
return 0;
int data = GETC_STREAM(dataStream);
if (data >= 0)
{
MSU1.MSU1_DATA_POS++;
return data;
}
return 0;
}
case 2:
return 'S';
case 3:
@ -396,8 +487,10 @@ void S9xMSU1WritePort(int port, uint8 byte)
MSU1.MSU1_DATA_SEEK &= 0x00FFFFFF;
MSU1.MSU1_DATA_SEEK |= byte << 24;
MSU1.MSU1_DATA_POS = MSU1.MSU1_DATA_SEEK;
if(dataFile.good())
dataFile.seekg(MSU1.MSU1_DATA_POS);
if (dataStream)
{
REVERT_STREAM(dataStream, MSU1.MSU1_DATA_POS, 0);
}
break;
case 4:
MSU1.MSU1_TRACK_SEEK &= 0xFF00;
@ -424,7 +517,7 @@ void S9xMSU1WritePort(int port, uint8 byte)
MSU1.MSU1_AUDIO_POS = 8;
}
audioFile.seekg(MSU1.MSU1_AUDIO_POS);
REVERT_STREAM(audioStream, MSU1.MSU1_AUDIO_POS, 0);
}
break;
case 6:
@ -460,20 +553,20 @@ void S9xMSU1PostLoadState(void)
{
if (DataOpen())
{
dataFile.seekg(MSU1.MSU1_DATA_POS);
REVERT_STREAM(dataStream, MSU1.MSU1_DATA_POS, 0);
}
if (MSU1.MSU1_STATUS & AudioPlaying)
{
if (AudioOpen())
{
audioFile.seekg(4);
audioFile.read((char *)&audioLoopPos, 4);
REVERT_STREAM(audioStream, 4, 0);
READ_STREAM((char *)&audioLoopPos, 4, audioStream);
audioLoopPos = GET_LE32(&audioLoopPos);
audioLoopPos <<= 2;
audioLoopPos += 8;
audioFile.seekg(MSU1.MSU1_AUDIO_POS);
REVERT_STREAM(audioStream, MSU1.MSU1_AUDIO_POS, 0);
}
else
{

2
msu1.h
View File

@ -229,6 +229,8 @@ extern struct SMSU1 MSU1;
void S9xResetMSU(void);
void S9xMSU1Init(void);
bool S9xMSU1ROMExists(void);
STREAM S9xMSU1OpenFile(char *msu_ext);
void S9xMSU1Init(void);
void S9xMSU1Generate(int sample_count);
uint8 S9xMSU1ReadPort(int port);
void S9xMSU1WritePort(int port, uint8 byte);

View File

@ -315,8 +315,12 @@ void fStream::closeStream()
unzStream::unzStream (unzFile &v)
{
file = v;
head = NULL;
numbytes = 0;
pos_in_buf = 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)
@ -324,21 +328,31 @@ unzStream::~unzStream (void)
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)
{
unsigned char c;
if (numbytes <= 0)
if (buffer_remaining() <= 0)
{
numbytes = unzReadCurrentFile(file, buffer, unz_BUFFSIZ);
if (numbytes <= 0)
fill_buffer();
if (bytes_in_buf <= 0)
return (EOF);
head = buffer;
}
c = *head;
head++;
numbytes--;
c = *(buffer + pos_in_buf);
pos_in_buf++;
return ((int) c);
}
@ -373,28 +387,25 @@ size_t unzStream::read (void *buf, size_t len)
if (len == 0)
return (len);
if (len <= numbytes)
{
memcpy(buf, head, len);
numbytes -= len;
head += len;
return (len);
}
size_t to_read = len;
uint8 *read_to = (uint8 * )buf;
do
{
size_t in_buffer = buffer_remaining();
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;
if (numbytes > 0)
{
memcpy(buf, head, numbytes);
numread += numbytes;
head = NULL;
numbytes = 0;
}
memcpy(read_to, buffer + pos_in_buf, in_buffer);
to_read -= in_buffer;
fill_buffer();
} while (bytes_in_buf);
int l = unzReadCurrentFile(file, (uint8 *)buf + numread, len - numread);
if (l > 0)
numread += l;
return (numread);
return (len - to_read);
}
// not supported
@ -405,7 +416,7 @@ size_t unzStream::write (void *buf, size_t len)
size_t unzStream::pos (void)
{
return (unztell(file));
return buf_pos_in_unzipped + pos_in_buf;
}
size_t unzStream::size (void)
@ -415,10 +426,26 @@ size_t unzStream::size (void)
return info.uncompressed_size;
}
// not supported
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()

View File

@ -252,10 +252,15 @@ class unzStream : public Stream
virtual void closeStream();
private:
void fill_buffer();
size_t buffer_remaining();
unzFile file;
char buffer[unz_BUFFSIZ];
char *head;
size_t numbytes;
size_t pos_in_buf;
size_t buf_pos_in_unzipped;
size_t bytes_in_buf;
unz_file_pos unz_file_start_pos;
};
#endif