Add MSU-1 to snapshots.

This commit is contained in:
qwertymodo 2016-11-07 11:03:37 -08:00
parent fb24fc63ba
commit 0832528d9f
4 changed files with 164 additions and 84 deletions

199
msu1.cpp
View File

@ -199,29 +199,70 @@
#define APU_DEFAULT_INPUT_RATE 32000 #define APU_DEFAULT_INPUT_RATE 32000
std::ifstream dataFile, audioFile; std::ifstream dataFile, audioFile;
uint32 dataPos, audioPos, audioResumePos, audioLoopPos; uint32 audioLoopPos;
uint16 audioTrack, audioResumeTrack;
char fName[64]; char fName[64];
uint32 partial_samples; uint32 partial_samples;
bool audioResume;
// Sample buffer // Sample buffer
int16 *bufPos, *bufBegin, *bufEnd; int16 *bufPos, *bufBegin, *bufEnd;
bool AudioOpen()
{
MSU1.MSU1_STATUS |= AudioError;
if (audioFile.is_open())
audioFile.close();
// This is an ugly hack... need to see if there's a better way to get the base name without extension
sprintf(fName, "%s", S9xGetFilename(".msu", ROMFILENAME_DIR));
fName[strlen(fName) - 4] = '\0';
sprintf(fName, "%s-%d.pcm", fName, MSU1.MSU1_CURRENT_TRACK);
audioFile.clear();
audioFile.open(fName, std::ios::in | std::ios::binary);
if (audioFile.good())
{
if (audioFile.get() != 'M')
return false;
if (audioFile.get() != 'S')
return false;
if (audioFile.get() != 'U')
return false;
if (audioFile.get() != '1')
return false;
audioFile.read((char *)&audioLoopPos, 4);
audioLoopPos <<= 2;
audioLoopPos += 8;
}
MSU1.MSU1_STATUS &= ~AudioError;
return true;
}
bool DataOpen()
{
if (dataFile.is_open())
dataFile.close();
dataFile.clear();
dataFile.open(S9xGetFilename(".msu", ROMFILENAME_DIR), std::ios::in | std::ios::binary);
return dataFile.is_open();
}
void S9xMSU1Init(void) void S9xMSU1Init(void)
{ {
MSU1.MSU1_STATUS = 0; MSU1.MSU1_STATUS = 0;
MSU1.MSU1_SEEK = 0; MSU1.MSU1_DATA_SEEK = 0;
MSU1.MSU1_TRACK = 0; MSU1.MSU1_DATA_POS = 0;
MSU1.MSU1_VOLUME = 0; MSU1.MSU1_TRACK_SEEK = 0;
MSU1.MSU1_CONTROL = 0; MSU1.MSU1_CURRENT_TRACK = 0;
MSU1.MSU1_RESUME_TRACK = 0;
MSU1.MSU1_VOLUME = 0;
MSU1.MSU1_CONTROL = 0;
MSU1.MSU1_AUDIO_POS = 0;
MSU1.MSU1_RESUME_POS = 0;
dataPos = 0;
audioPos = 0;
audioResumePos = 0;
audioTrack = 0;
audioResumeTrack = 0;
bufPos = 0; bufPos = 0;
bufBegin = 0; bufBegin = 0;
@ -235,7 +276,7 @@ void S9xMSU1Init(void)
if (audioFile.is_open()) if (audioFile.is_open())
audioFile.close(); audioFile.close();
dataFile.open(S9xGetFilename(".msu", ROMFILENAME_DIR), std::ios::in | std::ios::binary); DataOpen();
} }
void S9xMSU1Generate(int sample_count) void S9xMSU1Generate(int sample_count)
@ -249,26 +290,26 @@ void S9xMSU1Generate(int sample_count)
int16 sample; int16 sample;
if (audioFile.read((char *)&sample, 2).good()) if (audioFile.read((char *)&sample, 2).good())
{ {
sample = (double)sample * (double)MSU1.MSU1_VOLUME / 255.0; sample = (int16)((double)sample * (double)MSU1.MSU1_VOLUME / 255.0);
*(bufPos++) = sample; *(bufPos++) = sample;
audioPos += 2; MSU1.MSU1_AUDIO_POS += 2;
partial_samples -= 320405; partial_samples -= 320405;
} }
else else
if (audioFile.eof()) if (audioFile.eof())
{ {
sample = (double)sample * (double)MSU1.MSU1_VOLUME / 255.0; sample = (int16)((double)sample * (double)MSU1.MSU1_VOLUME / 255.0);
*(bufPos++) = sample; *(bufPos++) = sample;
audioPos += 2; MSU1.MSU1_AUDIO_POS += 2;
partial_samples -= 320405; partial_samples -= 320405;
if (MSU1.MSU1_STATUS & AudioRepeating) if (MSU1.MSU1_STATUS & AudioRepeating)
{ {
audioFile.clear(); audioFile.clear();
audioPos = audioLoopPos; MSU1.MSU1_AUDIO_POS = audioLoopPos;
audioFile.seekg(audioPos); audioFile.seekg(MSU1.MSU1_AUDIO_POS);
} }
else else
{ {
@ -304,6 +345,7 @@ uint8 S9xMSU1ReadPort(int port)
return 0; return 0;
if (dataFile.fail() || dataFile.bad() || dataFile.eof()) if (dataFile.fail() || dataFile.bad() || dataFile.eof())
return 0; return 0;
MSU1.MSU1_DATA_POS++;
return dataFile.get(); return dataFile.get();
case 2: case 2:
return 'S'; return 'S';
@ -318,6 +360,8 @@ uint8 S9xMSU1ReadPort(int port)
case 7: case 7:
return '1'; return '1';
} }
return 0;
} }
@ -326,82 +370,44 @@ void S9xMSU1WritePort(int port, uint8 byte)
switch (port) switch (port)
{ {
case 0: case 0:
((uint8 *)(&MSU1.MSU1_SEEK))[0] = byte; ((uint8 *)(&MSU1.MSU1_DATA_SEEK))[0] = byte;
break; break;
case 1: case 1:
((uint8 *)(&MSU1.MSU1_SEEK))[1] = byte; ((uint8 *)(&MSU1.MSU1_DATA_SEEK))[1] = byte;
break; break;
case 2: case 2:
((uint8 *)(&MSU1.MSU1_SEEK))[2] = byte; ((uint8 *)(&MSU1.MSU1_DATA_SEEK))[2] = byte;
break; break;
case 3: case 3:
((uint8 *)(&MSU1.MSU1_SEEK))[3] = byte; ((uint8 *)(&MSU1.MSU1_DATA_SEEK))[3] = byte;
dataPos = MSU1.MSU1_SEEK; MSU1.MSU1_DATA_POS = MSU1.MSU1_DATA_SEEK;
if(dataFile.good()) if(dataFile.good())
dataFile.seekg(dataPos); dataFile.seekg(MSU1.MSU1_DATA_POS);
break; break;
case 4: case 4:
((uint8 *)(&MSU1.MSU1_TRACK))[0] = byte; ((uint8 *)(&MSU1.MSU1_TRACK_SEEK))[0] = byte;
break; break;
case 5: case 5:
((uint8 *)(&MSU1.MSU1_TRACK))[1] = byte; ((uint8 *)(&MSU1.MSU1_TRACK_SEEK))[1] = byte;
audioTrack = MSU1.MSU1_TRACK; MSU1.MSU1_CURRENT_TRACK = MSU1.MSU1_TRACK_SEEK;
if (audioFile.is_open())
audioFile.close();
// This is an ugly hack... need to see if there's a better way to get the base name without extension MSU1.MSU1_STATUS &= ~AudioPlaying;
sprintf(fName, "%s", S9xGetFilename(".msu", ROMFILENAME_DIR)); MSU1.MSU1_STATUS &= ~AudioRepeating;
fName[strlen(fName) - 4] = '\0';
sprintf(fName, "%s-%d.pcm", fName, audioTrack);
audioFile.clear(); if (AudioOpen())
audioFile.open(fName, std::ios::in | std::ios::binary);
if (audioFile.is_open())
{ {
MSU1.MSU1_STATUS |= AudioError; if (MSU1.MSU1_CURRENT_TRACK == MSU1.MSU1_RESUME_TRACK)
if (audioFile.get() != 'M')
break;
if (audioFile.get() != 'S')
break;
if (audioFile.get() != 'U')
break;
if (audioFile.get() != '1')
break;
audioFile.read((char *)&audioLoopPos, 4);
audioLoopPos <<= 2;
audioLoopPos += 8;
MSU1.MSU1_STATUS &= ~AudioPlaying;
MSU1.MSU1_STATUS &= ~AudioRepeating;
if (audioResume)
{ {
audioResumeTrack = audioTrack; MSU1.MSU1_AUDIO_POS = MSU1.MSU1_RESUME_POS;
audioResumePos = audioPos; MSU1.MSU1_RESUME_POS = 0;
audioResume = FALSE; MSU1.MSU1_RESUME_TRACK = ~0;
} }
else else
{ {
if (audioTrack == audioResumeTrack) MSU1.MSU1_AUDIO_POS = 8;
{
audioPos = audioResumePos;
audioResumeTrack = 0xFFFF;
audioResumePos = 0;
}
else
audioPos = 8;
} }
audioFile.seekg(audioPos); audioFile.seekg(MSU1.MSU1_AUDIO_POS);
MSU1.MSU1_STATUS &= ~AudioError;
}
else
{
char *e = strerror(errno);
MSU1.MSU1_STATUS |= AudioError;
} }
break; break;
case 6: case 6:
@ -413,11 +419,10 @@ void S9xMSU1WritePort(int port, uint8 byte)
MSU1.MSU1_STATUS = (MSU1.MSU1_STATUS & ~0x30) | ((byte & 0x03) << 4); MSU1.MSU1_STATUS = (MSU1.MSU1_STATUS & ~0x30) | ((byte & 0x03) << 4);
audioResume = ((byte & 0x05) == 0x05); if ((byte & (Play | Resume) == Resume))
if (byte & 0x04)
{ {
audioResumeTrack = audioTrack; MSU1.MSU1_RESUME_TRACK = MSU1.MSU1_CURRENT_TRACK;
audioResumePos = audioPos; MSU1.MSU1_RESUME_POS = MSU1.MSU1_AUDIO_POS;
} }
break; break;
} }
@ -433,3 +438,35 @@ void S9xMSU1SetOutput(int16 * out, int size)
bufPos = bufBegin = out; bufPos = bufBegin = out;
bufEnd = out + size; bufEnd = out + size;
} }
void S9xMSU1PostLoadState(void)
{
if (DataOpen())
{
dataFile.seekg(MSU1.MSU1_DATA_POS);
}
if (MSU1.MSU1_STATUS & AudioPlaying)
{
if (AudioOpen())
{
audioFile.seekg(4);
audioFile.read((char *)&audioLoopPos, 4);
audioLoopPos <<= 2;
audioLoopPos += 8;
audioFile.seekg(MSU1.MSU1_AUDIO_POS);
}
else
{
MSU1.MSU1_STATUS &= ~(AudioPlaying | AudioRepeating);
MSU1.MSU1_STATUS |= AudioError;
}
}
bufPos = 0;
bufBegin = 0;
bufEnd = 0;
partial_samples = 0;
}

16
msu1.h
View File

@ -197,10 +197,15 @@
struct SMSU1 struct SMSU1
{ {
uint8 MSU1_STATUS; uint8 MSU1_STATUS;
uint32 MSU1_SEEK; uint32 MSU1_DATA_SEEK;
uint16 MSU1_TRACK; uint32 MSU1_DATA_POS;
uint16 MSU1_TRACK_SEEK;
uint16 MSU1_CURRENT_TRACK;
uint32 MSU1_RESUME_TRACK;
uint8 MSU1_VOLUME; uint8 MSU1_VOLUME;
uint8 MSU1_CONTROL; uint8 MSU1_CONTROL;
uint32 MSU1_AUDIO_POS;
uint32 MSU1_RESUME_POS;
}; };
enum SMSU1_FLAG : uint8 { enum SMSU1_FLAG : uint8 {
@ -213,6 +218,12 @@ enum SMSU1_FLAG : uint8 {
DataBusy = 0x80, DataBusy = 0x80,
}; };
enum SMSU1_CMD : uint8 {
Play = 0x01,
Repeat = 0x02,
Resume = 0x04,
};
extern struct SMSU1 MSU1; extern struct SMSU1 MSU1;
void S9xMSU1Init(void); void S9xMSU1Init(void);
@ -221,5 +232,6 @@ uint8 S9xMSU1ReadPort(int port);
void S9xMSU1WritePort(int port, uint8 byte); void S9xMSU1WritePort(int port, uint8 byte);
uint16 S9xMSU1Samples(void); uint16 S9xMSU1Samples(void);
void S9xMSU1SetOutput(int16 *out, int size); void S9xMSU1SetOutput(int16 *out, int size);
void S9xMSU1PostLoadState(void);
#endif #endif

View File

@ -1135,6 +1135,23 @@ static FreezeData SnapBSX[] =
ARRAY_ENTRY(6, test2192, 32, uint8_ARRAY_V) ARRAY_ENTRY(6, test2192, 32, uint8_ARRAY_V)
}; };
#undef STRUCT
#define STRUCT struct SMSU1
static FreezeData SnapMSU1[] =
{
INT_ENTRY(9, MSU1_STATUS),
INT_ENTRY(9, MSU1_DATA_SEEK),
INT_ENTRY(9, MSU1_DATA_POS),
INT_ENTRY(9, MSU1_TRACK_SEEK),
INT_ENTRY(9, MSU1_CURRENT_TRACK),
INT_ENTRY(9, MSU1_RESUME_TRACK),
INT_ENTRY(9, MSU1_VOLUME),
INT_ENTRY(9, MSU1_CONTROL),
INT_ENTRY(9, MSU1_AUDIO_POS),
INT_ENTRY(9, MSU1_RESUME_POS)
};
#undef STRUCT #undef STRUCT
#define STRUCT struct SnapshotScreenshotInfo #define STRUCT struct SnapshotScreenshotInfo
@ -1394,6 +1411,9 @@ void S9xFreezeToStream (STREAM stream)
if (Settings.BS) if (Settings.BS)
FreezeStruct(stream, "BSX", &BSX, SnapBSX, COUNT(SnapBSX)); FreezeStruct(stream, "BSX", &BSX, SnapBSX, COUNT(SnapBSX));
if (Settings.MSU1)
FreezeStruct(stream, "MSU", &MSU1, SnapMSU1, COUNT(SnapMSU1));
if (Settings.SnapshotScreenshots) if (Settings.SnapshotScreenshots)
{ {
SnapshotScreenshotInfo *ssi = new SnapshotScreenshotInfo; SnapshotScreenshotInfo *ssi = new SnapshotScreenshotInfo;
@ -1494,6 +1514,7 @@ int S9xUnfreezeFromStream (STREAM stream)
uint8 *local_srtc = NULL; uint8 *local_srtc = NULL;
uint8 *local_rtc_data = NULL; uint8 *local_rtc_data = NULL;
uint8 *local_bsx_data = NULL; uint8 *local_bsx_data = NULL;
uint8 *local_msu1_data = NULL;
uint8 *local_screenshot = NULL; uint8 *local_screenshot = NULL;
uint8 *local_movie_data = NULL; uint8 *local_movie_data = NULL;
@ -1599,6 +1620,10 @@ int S9xUnfreezeFromStream (STREAM stream)
if (result != SUCCESS && Settings.BS) if (result != SUCCESS && Settings.BS)
break; break;
result = UnfreezeStructCopy(stream, "MSU", &local_msu1_data, SnapMSU1, COUNT(SnapMSU1), version);
if (result != SUCCESS && Settings.MSU1)
break;
result = UnfreezeStructCopy(stream, "SHO", &local_screenshot, SnapScreenshot, COUNT(SnapScreenshot), version); result = UnfreezeStructCopy(stream, "SHO", &local_screenshot, SnapScreenshot, COUNT(SnapScreenshot), version);
SnapshotMovieInfo mi; SnapshotMovieInfo mi;
@ -1717,6 +1742,9 @@ int S9xUnfreezeFromStream (STREAM stream)
if (local_bsx_data) if (local_bsx_data)
UnfreezeStructFromCopy(&BSX, SnapBSX, COUNT(SnapBSX), local_bsx_data, version); UnfreezeStructFromCopy(&BSX, SnapBSX, COUNT(SnapBSX), local_bsx_data, version);
if (local_msu1_data)
UnfreezeStructFromCopy(&MSU1, SnapMSU1, COUNT(SnapMSU1), local_msu1_data, version);
if (version < SNAPSHOT_VERSION_IRQ) if (version < SNAPSHOT_VERSION_IRQ)
{ {
printf("Converting old snapshot version %d to %d\n...", version, SNAPSHOT_VERSION); printf("Converting old snapshot version %d to %d\n...", version, SNAPSHOT_VERSION);
@ -1798,6 +1826,9 @@ int S9xUnfreezeFromStream (STREAM stream)
if (local_bsx_data) if (local_bsx_data)
S9xBSXPostLoadState(); S9xBSXPostLoadState();
if (local_msu1_data)
S9xMSU1PostLoadState();
if (local_movie_data) if (local_movie_data)
{ {
// restore last displayed pad_read status // restore last displayed pad_read status

View File

@ -196,7 +196,7 @@
#define SNAPSHOT_MAGIC "#!s9xsnp" #define SNAPSHOT_MAGIC "#!s9xsnp"
#define SNAPSHOT_VERSION_IRQ 7 #define SNAPSHOT_VERSION_IRQ 7
#define SNAPSHOT_VERSION_BAPU 8 #define SNAPSHOT_VERSION_BAPU 8
#define SNAPSHOT_VERSION 8 #define SNAPSHOT_VERSION 9
#define SUCCESS 1 #define SUCCESS 1
#define WRONG_FORMAT (-1) #define WRONG_FORMAT (-1)