mirror of https://github.com/snes9xgit/snes9x.git
Add MSU-1 to snapshots.
This commit is contained in:
parent
fb24fc63ba
commit
0832528d9f
191
msu1.cpp
191
msu1.cpp
|
@ -199,29 +199,70 @@
|
|||
#define APU_DEFAULT_INPUT_RATE 32000
|
||||
|
||||
std::ifstream dataFile, audioFile;
|
||||
uint32 dataPos, audioPos, audioResumePos, audioLoopPos;
|
||||
uint16 audioTrack, audioResumeTrack;
|
||||
uint32 audioLoopPos;
|
||||
char fName[64];
|
||||
uint32 partial_samples;
|
||||
bool audioResume;
|
||||
|
||||
// Sample buffer
|
||||
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)
|
||||
{
|
||||
MSU1.MSU1_STATUS = 0;
|
||||
MSU1.MSU1_SEEK = 0;
|
||||
MSU1.MSU1_TRACK = 0;
|
||||
MSU1.MSU1_DATA_SEEK = 0;
|
||||
MSU1.MSU1_DATA_POS = 0;
|
||||
MSU1.MSU1_TRACK_SEEK = 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;
|
||||
bufBegin = 0;
|
||||
|
@ -235,7 +276,7 @@ void S9xMSU1Init(void)
|
|||
if (audioFile.is_open())
|
||||
audioFile.close();
|
||||
|
||||
dataFile.open(S9xGetFilename(".msu", ROMFILENAME_DIR), std::ios::in | std::ios::binary);
|
||||
DataOpen();
|
||||
}
|
||||
|
||||
void S9xMSU1Generate(int sample_count)
|
||||
|
@ -249,26 +290,26 @@ void S9xMSU1Generate(int sample_count)
|
|||
int16 sample;
|
||||
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;
|
||||
audioPos += 2;
|
||||
MSU1.MSU1_AUDIO_POS += 2;
|
||||
partial_samples -= 320405;
|
||||
}
|
||||
else
|
||||
if (audioFile.eof())
|
||||
{
|
||||
sample = (double)sample * (double)MSU1.MSU1_VOLUME / 255.0;
|
||||
sample = (int16)((double)sample * (double)MSU1.MSU1_VOLUME / 255.0);
|
||||
|
||||
*(bufPos++) = sample;
|
||||
audioPos += 2;
|
||||
MSU1.MSU1_AUDIO_POS += 2;
|
||||
partial_samples -= 320405;
|
||||
|
||||
if (MSU1.MSU1_STATUS & AudioRepeating)
|
||||
{
|
||||
audioFile.clear();
|
||||
audioPos = audioLoopPos;
|
||||
audioFile.seekg(audioPos);
|
||||
MSU1.MSU1_AUDIO_POS = audioLoopPos;
|
||||
audioFile.seekg(MSU1.MSU1_AUDIO_POS);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -304,6 +345,7 @@ uint8 S9xMSU1ReadPort(int port)
|
|||
return 0;
|
||||
if (dataFile.fail() || dataFile.bad() || dataFile.eof())
|
||||
return 0;
|
||||
MSU1.MSU1_DATA_POS++;
|
||||
return dataFile.get();
|
||||
case 2:
|
||||
return 'S';
|
||||
|
@ -318,6 +360,8 @@ uint8 S9xMSU1ReadPort(int port)
|
|||
case 7:
|
||||
return '1';
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -326,82 +370,44 @@ void S9xMSU1WritePort(int port, uint8 byte)
|
|||
switch (port)
|
||||
{
|
||||
case 0:
|
||||
((uint8 *)(&MSU1.MSU1_SEEK))[0] = byte;
|
||||
((uint8 *)(&MSU1.MSU1_DATA_SEEK))[0] = byte;
|
||||
break;
|
||||
case 1:
|
||||
((uint8 *)(&MSU1.MSU1_SEEK))[1] = byte;
|
||||
((uint8 *)(&MSU1.MSU1_DATA_SEEK))[1] = byte;
|
||||
break;
|
||||
case 2:
|
||||
((uint8 *)(&MSU1.MSU1_SEEK))[2] = byte;
|
||||
((uint8 *)(&MSU1.MSU1_DATA_SEEK))[2] = byte;
|
||||
break;
|
||||
case 3:
|
||||
((uint8 *)(&MSU1.MSU1_SEEK))[3] = byte;
|
||||
dataPos = MSU1.MSU1_SEEK;
|
||||
((uint8 *)(&MSU1.MSU1_DATA_SEEK))[3] = byte;
|
||||
MSU1.MSU1_DATA_POS = MSU1.MSU1_DATA_SEEK;
|
||||
if(dataFile.good())
|
||||
dataFile.seekg(dataPos);
|
||||
dataFile.seekg(MSU1.MSU1_DATA_POS);
|
||||
break;
|
||||
case 4:
|
||||
((uint8 *)(&MSU1.MSU1_TRACK))[0] = byte;
|
||||
((uint8 *)(&MSU1.MSU1_TRACK_SEEK))[0] = byte;
|
||||
break;
|
||||
case 5:
|
||||
((uint8 *)(&MSU1.MSU1_TRACK))[1] = byte;
|
||||
audioTrack = MSU1.MSU1_TRACK;
|
||||
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, audioTrack);
|
||||
|
||||
audioFile.clear();
|
||||
audioFile.open(fName, std::ios::in | std::ios::binary);
|
||||
if (audioFile.is_open())
|
||||
{
|
||||
MSU1.MSU1_STATUS |= AudioError;
|
||||
|
||||
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;
|
||||
((uint8 *)(&MSU1.MSU1_TRACK_SEEK))[1] = byte;
|
||||
MSU1.MSU1_CURRENT_TRACK = MSU1.MSU1_TRACK_SEEK;
|
||||
|
||||
MSU1.MSU1_STATUS &= ~AudioPlaying;
|
||||
MSU1.MSU1_STATUS &= ~AudioRepeating;
|
||||
|
||||
if (audioResume)
|
||||
if (AudioOpen())
|
||||
{
|
||||
audioResumeTrack = audioTrack;
|
||||
audioResumePos = audioPos;
|
||||
audioResume = FALSE;
|
||||
if (MSU1.MSU1_CURRENT_TRACK == MSU1.MSU1_RESUME_TRACK)
|
||||
{
|
||||
MSU1.MSU1_AUDIO_POS = MSU1.MSU1_RESUME_POS;
|
||||
MSU1.MSU1_RESUME_POS = 0;
|
||||
MSU1.MSU1_RESUME_TRACK = ~0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (audioTrack == audioResumeTrack)
|
||||
{
|
||||
audioPos = audioResumePos;
|
||||
audioResumeTrack = 0xFFFF;
|
||||
audioResumePos = 0;
|
||||
}
|
||||
else
|
||||
audioPos = 8;
|
||||
MSU1.MSU1_AUDIO_POS = 8;
|
||||
}
|
||||
|
||||
audioFile.seekg(audioPos);
|
||||
|
||||
MSU1.MSU1_STATUS &= ~AudioError;
|
||||
}
|
||||
else
|
||||
{
|
||||
char *e = strerror(errno);
|
||||
MSU1.MSU1_STATUS |= AudioError;
|
||||
audioFile.seekg(MSU1.MSU1_AUDIO_POS);
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
|
@ -413,11 +419,10 @@ void S9xMSU1WritePort(int port, uint8 byte)
|
|||
|
||||
MSU1.MSU1_STATUS = (MSU1.MSU1_STATUS & ~0x30) | ((byte & 0x03) << 4);
|
||||
|
||||
audioResume = ((byte & 0x05) == 0x05);
|
||||
if (byte & 0x04)
|
||||
if ((byte & (Play | Resume) == Resume))
|
||||
{
|
||||
audioResumeTrack = audioTrack;
|
||||
audioResumePos = audioPos;
|
||||
MSU1.MSU1_RESUME_TRACK = MSU1.MSU1_CURRENT_TRACK;
|
||||
MSU1.MSU1_RESUME_POS = MSU1.MSU1_AUDIO_POS;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -433,3 +438,35 @@ void S9xMSU1SetOutput(int16 * out, int size)
|
|||
bufPos = bufBegin = out;
|
||||
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
16
msu1.h
|
@ -197,10 +197,15 @@
|
|||
struct SMSU1
|
||||
{
|
||||
uint8 MSU1_STATUS;
|
||||
uint32 MSU1_SEEK;
|
||||
uint16 MSU1_TRACK;
|
||||
uint32 MSU1_DATA_SEEK;
|
||||
uint32 MSU1_DATA_POS;
|
||||
uint16 MSU1_TRACK_SEEK;
|
||||
uint16 MSU1_CURRENT_TRACK;
|
||||
uint32 MSU1_RESUME_TRACK;
|
||||
uint8 MSU1_VOLUME;
|
||||
uint8 MSU1_CONTROL;
|
||||
uint32 MSU1_AUDIO_POS;
|
||||
uint32 MSU1_RESUME_POS;
|
||||
};
|
||||
|
||||
enum SMSU1_FLAG : uint8 {
|
||||
|
@ -213,6 +218,12 @@ enum SMSU1_FLAG : uint8 {
|
|||
DataBusy = 0x80,
|
||||
};
|
||||
|
||||
enum SMSU1_CMD : uint8 {
|
||||
Play = 0x01,
|
||||
Repeat = 0x02,
|
||||
Resume = 0x04,
|
||||
};
|
||||
|
||||
extern struct SMSU1 MSU1;
|
||||
|
||||
void S9xMSU1Init(void);
|
||||
|
@ -221,5 +232,6 @@ uint8 S9xMSU1ReadPort(int port);
|
|||
void S9xMSU1WritePort(int port, uint8 byte);
|
||||
uint16 S9xMSU1Samples(void);
|
||||
void S9xMSU1SetOutput(int16 *out, int size);
|
||||
void S9xMSU1PostLoadState(void);
|
||||
|
||||
#endif
|
||||
|
|
31
snapshot.cpp
31
snapshot.cpp
|
@ -1135,6 +1135,23 @@ static FreezeData SnapBSX[] =
|
|||
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
|
||||
#define STRUCT struct SnapshotScreenshotInfo
|
||||
|
||||
|
@ -1394,6 +1411,9 @@ void S9xFreezeToStream (STREAM stream)
|
|||
if (Settings.BS)
|
||||
FreezeStruct(stream, "BSX", &BSX, SnapBSX, COUNT(SnapBSX));
|
||||
|
||||
if (Settings.MSU1)
|
||||
FreezeStruct(stream, "MSU", &MSU1, SnapMSU1, COUNT(SnapMSU1));
|
||||
|
||||
if (Settings.SnapshotScreenshots)
|
||||
{
|
||||
SnapshotScreenshotInfo *ssi = new SnapshotScreenshotInfo;
|
||||
|
@ -1494,6 +1514,7 @@ int S9xUnfreezeFromStream (STREAM stream)
|
|||
uint8 *local_srtc = NULL;
|
||||
uint8 *local_rtc_data = NULL;
|
||||
uint8 *local_bsx_data = NULL;
|
||||
uint8 *local_msu1_data = NULL;
|
||||
uint8 *local_screenshot = NULL;
|
||||
uint8 *local_movie_data = NULL;
|
||||
|
||||
|
@ -1599,6 +1620,10 @@ int S9xUnfreezeFromStream (STREAM stream)
|
|||
if (result != SUCCESS && Settings.BS)
|
||||
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);
|
||||
|
||||
SnapshotMovieInfo mi;
|
||||
|
@ -1717,6 +1742,9 @@ int S9xUnfreezeFromStream (STREAM stream)
|
|||
if (local_bsx_data)
|
||||
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)
|
||||
{
|
||||
printf("Converting old snapshot version %d to %d\n...", version, SNAPSHOT_VERSION);
|
||||
|
@ -1798,6 +1826,9 @@ int S9xUnfreezeFromStream (STREAM stream)
|
|||
if (local_bsx_data)
|
||||
S9xBSXPostLoadState();
|
||||
|
||||
if (local_msu1_data)
|
||||
S9xMSU1PostLoadState();
|
||||
|
||||
if (local_movie_data)
|
||||
{
|
||||
// restore last displayed pad_read status
|
||||
|
|
|
@ -196,7 +196,7 @@
|
|||
#define SNAPSHOT_MAGIC "#!s9xsnp"
|
||||
#define SNAPSHOT_VERSION_IRQ 7
|
||||
#define SNAPSHOT_VERSION_BAPU 8
|
||||
#define SNAPSHOT_VERSION 8
|
||||
#define SNAPSHOT_VERSION 9
|
||||
|
||||
#define SUCCESS 1
|
||||
#define WRONG_FORMAT (-1)
|
||||
|
|
Loading…
Reference in New Issue