mirror of
https://github.com/mauiaaron/apple2.git
synced 2024-12-24 18:31:51 +00:00
Add save/load state to mockingboard
This commit is contained in:
parent
bb93b5c243
commit
37df740fd3
@ -1025,7 +1025,284 @@ void SetCLK(double CLK)
|
||||
#define SS_YAML_KEY_CHANGE "Change"
|
||||
#define SS_YAML_VALUE_CHANGE_FORMAT "%d, %d, 0x%1X, 0x%02X"
|
||||
|
||||
#if UNBREAK_SOON
|
||||
#if 1 // APPLE2IX
|
||||
static bool _saveState(StateHelper_s *helper, struct CAY8910 *_this) {
|
||||
int fd = helper->fd;
|
||||
|
||||
bool saved = false;
|
||||
do {
|
||||
unsigned int data = 0;
|
||||
|
||||
data = _this->ay_tone_tick[0];
|
||||
if (!helper->save(fd, (uint8_t *)&data, sizeof(data))) {
|
||||
break;
|
||||
}
|
||||
data = _this->ay_tone_tick[1];
|
||||
if (!helper->save(fd, (uint8_t *)&data, sizeof(data))) {
|
||||
break;
|
||||
}
|
||||
data = _this->ay_tone_tick[2];
|
||||
if (!helper->save(fd, (uint8_t *)&data, sizeof(data))) {
|
||||
break;
|
||||
}
|
||||
data = _this->ay_tone_high[0];
|
||||
if (!helper->save(fd, (uint8_t *)&data, sizeof(data))) {
|
||||
break;
|
||||
}
|
||||
data = _this->ay_tone_high[1];
|
||||
if (!helper->save(fd, (uint8_t *)&data, sizeof(data))) {
|
||||
break;
|
||||
}
|
||||
data = _this->ay_tone_high[2];
|
||||
if (!helper->save(fd, (uint8_t *)&data, sizeof(data))) {
|
||||
break;
|
||||
}
|
||||
data = _this->ay_noise_tick;
|
||||
if (!helper->save(fd, (uint8_t *)&data, sizeof(data))) {
|
||||
break;
|
||||
}
|
||||
data = _this->ay_tone_subcycles;
|
||||
if (!helper->save(fd, (uint8_t *)&data, sizeof(data))) {
|
||||
break;
|
||||
}
|
||||
data = _this->ay_env_subcycles;
|
||||
if (!helper->save(fd, (uint8_t *)&data, sizeof(data))) {
|
||||
break;
|
||||
}
|
||||
data = _this->ay_env_internal_tick;
|
||||
if (!helper->save(fd, (uint8_t *)&data, sizeof(data))) {
|
||||
break;
|
||||
}
|
||||
data = _this->ay_env_tick;
|
||||
if (!helper->save(fd, (uint8_t *)&data, sizeof(data))) {
|
||||
break;
|
||||
}
|
||||
data = _this->ay_tick_incr;
|
||||
if (!helper->save(fd, (uint8_t *)&data, sizeof(data))) {
|
||||
break;
|
||||
}
|
||||
data = _this->ay_tone_period[0];
|
||||
if (!helper->save(fd, (uint8_t *)&data, sizeof(data))) {
|
||||
break;
|
||||
}
|
||||
data = _this->ay_tone_period[1];
|
||||
if (!helper->save(fd, (uint8_t *)&data, sizeof(data))) {
|
||||
break;
|
||||
}
|
||||
data = _this->ay_tone_period[2];
|
||||
if (!helper->save(fd, (uint8_t *)&data, sizeof(data))) {
|
||||
break;
|
||||
}
|
||||
data = _this->ay_noise_period;
|
||||
if (!helper->save(fd, (uint8_t *)&data, sizeof(data))) {
|
||||
break;
|
||||
}
|
||||
data = _this->ay_env_period;
|
||||
if (!helper->save(fd, (uint8_t *)&data, sizeof(data))) {
|
||||
break;
|
||||
}
|
||||
data = _this->rng;
|
||||
if (!helper->save(fd, (uint8_t *)&data, sizeof(data))) {
|
||||
break;
|
||||
}
|
||||
data = _this->noise_toggle;
|
||||
if (!helper->save(fd, (uint8_t *)&data, sizeof(data))) {
|
||||
break;
|
||||
}
|
||||
data = _this->env_first;
|
||||
if (!helper->save(fd, (uint8_t *)&data, sizeof(data))) {
|
||||
break;
|
||||
}
|
||||
data = _this->env_rev;
|
||||
if (!helper->save(fd, (uint8_t *)&data, sizeof(data))) {
|
||||
break;
|
||||
}
|
||||
data = _this->env_counter;
|
||||
if (!helper->save(fd, (uint8_t *)&data, sizeof(data))) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Registers
|
||||
{
|
||||
bool success = true;
|
||||
for (unsigned int i=0; i<16; i++) {
|
||||
uint8_t reg = _this->sound_ay_registers[i];
|
||||
if (!helper->save(fd, ®, sizeof(reg))) {
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!success) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Queued changes
|
||||
assert(_this->ay_change_count >= 0);
|
||||
if (!helper->save(fd, (uint8_t *)&(_this->ay_change_count), sizeof(_this->ay_change_count))) {
|
||||
break;
|
||||
}
|
||||
if (_this->ay_change_count)
|
||||
{
|
||||
bool success = true;
|
||||
for (int i=0; i<_this->ay_change_count; i++) {
|
||||
unsigned long tstates = (_this->ay_change[i]).tstates;
|
||||
if (!helper->save(fd, (uint8_t *)&tstates, sizeof(tstates))) {
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
unsigned short ofs = (_this->ay_change[i]).ofs;
|
||||
if (!helper->save(fd, (uint8_t *)&ofs, sizeof(ofs))) {
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
unsigned char reg = (_this->ay_change[i]).reg;
|
||||
if (!helper->save(fd, (uint8_t *)®, sizeof(reg))) {
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
unsigned char val = (_this->ay_change[i]).val;
|
||||
if (!helper->save(fd, (uint8_t *)&val, sizeof(val))) {
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!success) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
saved = true;
|
||||
|
||||
} while (0);
|
||||
|
||||
return saved;
|
||||
}
|
||||
|
||||
static bool _loadState(StateHelper_s *helper, struct CAY8910 *_this) {
|
||||
int fd = helper->fd;
|
||||
|
||||
bool loaded = false;
|
||||
do {
|
||||
if (!helper->load(fd, (uint8_t *)&(_this->ay_tone_tick[0]), sizeof(unsigned int))) {
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, (uint8_t *)&(_this->ay_tone_tick[1]), sizeof(unsigned int))) {
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, (uint8_t *)&(_this->ay_tone_tick[2]), sizeof(unsigned int))) {
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, (uint8_t *)&(_this->ay_tone_high[0]), sizeof(unsigned int))) {
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, (uint8_t *)&(_this->ay_tone_high[1]), sizeof(unsigned int))) {
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, (uint8_t *)&(_this->ay_tone_high[2]), sizeof(unsigned int))) {
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, (uint8_t *)&(_this->ay_noise_tick), sizeof(unsigned int))) {
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, (uint8_t *)&(_this->ay_tone_subcycles), sizeof(unsigned int))) {
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, (uint8_t *)&(_this->ay_env_subcycles), sizeof(unsigned int))) {
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, (uint8_t *)&(_this->ay_env_internal_tick), sizeof(unsigned int))) {
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, (uint8_t *)&(_this->ay_env_tick), sizeof(unsigned int))) {
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, (uint8_t *)&(_this->ay_tick_incr), sizeof(unsigned int))) {
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, (uint8_t *)&(_this->ay_tone_period[0]), sizeof(unsigned int))) {
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, (uint8_t *)&(_this->ay_tone_period[1]), sizeof(unsigned int))) {
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, (uint8_t *)&(_this->ay_tone_period[2]), sizeof(unsigned int))) {
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, (uint8_t *)&(_this->ay_noise_period), sizeof(unsigned int))) {
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, (uint8_t *)&(_this->ay_env_period), sizeof(unsigned int))) {
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, (uint8_t *)&(_this->rng), sizeof(unsigned int))) {
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, (uint8_t *)&(_this->noise_toggle), sizeof(unsigned int))) {
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, (uint8_t *)&(_this->env_first), sizeof(unsigned int))) {
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, (uint8_t *)&(_this->env_rev), sizeof(unsigned int))) {
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, (uint8_t *)&(_this->env_counter), sizeof(unsigned int))) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Registers
|
||||
{
|
||||
bool success = true;
|
||||
for (unsigned int i=0; i<16; i++) {
|
||||
if (!helper->load(fd, &(_this->sound_ay_registers[i]), sizeof(_this->sound_ay_registers[i]))) {
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!success) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Queued changes
|
||||
if (!helper->load(fd, (uint8_t *)&(_this->ay_change_count), sizeof(_this->ay_change_count))) {
|
||||
break;
|
||||
}
|
||||
assert(_this->ay_change_count >= 0);
|
||||
if (_this->ay_change_count)
|
||||
{
|
||||
bool success = true;
|
||||
for (int i=0; i<_this->ay_change_count; i++) {
|
||||
if (!helper->load(fd, (uint8_t *)&(_this->ay_change[i].tstates), sizeof(_this->ay_change[i].tstates))) {
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, (uint8_t *)&(_this->ay_change[i].ofs), sizeof(_this->ay_change[i].ofs))) {
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, (uint8_t *)&(_this->ay_change[i].reg), sizeof(_this->ay_change[i].reg))) {
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, (uint8_t *)&(_this->ay_change[i].val), sizeof(_this->ay_change[i].val))) {
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
loaded = true;
|
||||
} while (0);
|
||||
|
||||
return loaded;
|
||||
}
|
||||
#else
|
||||
void CAY8910::SaveSnapshot(YamlSaveHelper& yamlSaveHelper, std::string& suffix)
|
||||
{
|
||||
std::string unit = std::string(SS_YAML_KEY_AY8910) + suffix;
|
||||
@ -1168,7 +1445,7 @@ bool CAY8910::LoadSnapshot(YamlLoadHelper& yamlLoadHelper, std::string& suffix)
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif // UNBREAK_SOON
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -1277,7 +1554,17 @@ uint8_t* AY8910_GetRegsPtr(unsigned int uChip)
|
||||
return GetAYRegsPtr(&g_AY8910[uChip]);
|
||||
}
|
||||
|
||||
#if UNBREAK_SOON
|
||||
#if 1 // APPLE2IX
|
||||
bool _ay8910_saveState(StateHelper_s *helper, unsigned int chip) {
|
||||
assert(chip < MAX_8910);
|
||||
return _saveState(helper, &g_AY8910[chip]);
|
||||
}
|
||||
|
||||
bool _ay8910_loadState(StateHelper_s *helper, unsigned int chip) {
|
||||
assert(chip < MAX_8910);
|
||||
return _loadState(helper, &g_AY8910[chip]);
|
||||
}
|
||||
#else
|
||||
UINT AY8910_SaveSnapshot(YamlSaveHelper& yamlSaveHelper, UINT uChip, std::string& suffix)
|
||||
{
|
||||
if (uChip >= MAX_8910)
|
||||
@ -1294,5 +1581,5 @@ UINT AY8910_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT uChip, std::string
|
||||
|
||||
return g_AY8910[uChip].LoadSnapshot(yamlLoadHelper, suffix) ? 1 : 0;
|
||||
}
|
||||
#endif // UNBREAK_SOON
|
||||
#endif
|
||||
|
||||
|
@ -32,7 +32,10 @@ uint8_t* AY8910_GetRegsPtr(unsigned int uChip);
|
||||
|
||||
void AY8910UpdateSetCycles();
|
||||
|
||||
#if UNBREAK_SOON
|
||||
#if 1 // APPLE2IX
|
||||
bool _ay8910_saveState(StateHelper_s *helper, unsigned int chip);
|
||||
bool _ay8910_loadState(StateHelper_s *helper, unsigned int chip);
|
||||
#else
|
||||
UINT AY8910_SaveSnapshot(class YamlSaveHelper& yamlSaveHelper, UINT uChip, std::string& suffix);
|
||||
UINT AY8910_LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT uChip, std::string& suffix);
|
||||
#endif
|
||||
@ -69,7 +72,8 @@ public:
|
||||
void sound_frame(struct CAY8910 *_this);
|
||||
uint8_t* GetAYRegsPtr(struct CAY8910 *_this);
|
||||
void SetCLK(double CLK);
|
||||
#if UNBREAK_SOON
|
||||
#if 1 // APPLE2IX
|
||||
#else
|
||||
void SaveSnapshot(class YamlSaveHelper& yamlSaveHelper, std::string& suffix);
|
||||
bool LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, std::string& suffix);
|
||||
#endif
|
||||
|
@ -2583,6 +2583,8 @@ int MB_SetSnapshot_v1(const SS_CARD_MOCKINGBOARD_v1* const pSS, const DWORD /*dw
|
||||
|
||||
//===========================================================================
|
||||
|
||||
#if 1 // APPLE2IX
|
||||
|
||||
static void mb_prefsChanged(const char *domain) {
|
||||
long lVal = 0;
|
||||
long goesToTen = prefs_parseLongValue(domain, PREF_MOCKINGBOARD_VOLUME, &lVal, /*base:*/10) ? lVal : 5; // expected range 0-10
|
||||
@ -2599,7 +2601,292 @@ static __attribute__((constructor)) void _init_mockingboard(void) {
|
||||
prefs_registerListener(PREF_DOMAIN_AUDIO, &mb_prefsChanged);
|
||||
}
|
||||
|
||||
#if 0 // !APPLE2IX
|
||||
static bool _sy6522_saveState(StateHelper_s *helper, SY6522 *sy6522) {
|
||||
int fd = helper->fd;
|
||||
|
||||
bool saved = false;
|
||||
do {
|
||||
uint8_t state8 = 0x0;
|
||||
|
||||
state8 = sy6522->ORA;
|
||||
if (!helper->save(fd, &state8, 1)) {
|
||||
break;
|
||||
}
|
||||
state8 = sy6522->ORB;
|
||||
if (!helper->save(fd, &state8, 1)) {
|
||||
break;
|
||||
}
|
||||
state8 = sy6522->DDRA;
|
||||
if (!helper->save(fd, &state8, 1)) {
|
||||
break;
|
||||
}
|
||||
state8 = sy6522->DDRB;
|
||||
if (!helper->save(fd, &state8, 1)) {
|
||||
break;
|
||||
}
|
||||
|
||||
uint16_t state16 = 0x0;
|
||||
state16 = sy6522->TIMER1_COUNTER.w;
|
||||
if (!helper->save(fd, (uint8_t *)&state16, 2)) {
|
||||
break;
|
||||
}
|
||||
state16 = sy6522->TIMER1_LATCH.w;
|
||||
if (!helper->save(fd, (uint8_t *)&state16, 2)) {
|
||||
break;
|
||||
}
|
||||
state16 = sy6522->TIMER2_COUNTER.w;
|
||||
if (!helper->save(fd, (uint8_t *)&state16, 2)) {
|
||||
break;
|
||||
}
|
||||
state16 = sy6522->TIMER2_LATCH.w;
|
||||
if (!helper->save(fd, (uint8_t *)&state16, 2)) {
|
||||
break;
|
||||
}
|
||||
|
||||
state8 = sy6522->SERIAL_SHIFT;
|
||||
if (!helper->save(fd, &state8, 1)) {
|
||||
break;
|
||||
}
|
||||
state8 = sy6522->ACR;
|
||||
if (!helper->save(fd, &state8, 1)) {
|
||||
break;
|
||||
}
|
||||
state8 = sy6522->PCR;
|
||||
if (!helper->save(fd, &state8, 1)) {
|
||||
break;
|
||||
}
|
||||
state8 = sy6522->IFR;
|
||||
if (!helper->save(fd, &state8, 1)) {
|
||||
break;
|
||||
}
|
||||
state8 = sy6522->IER;
|
||||
if (!helper->save(fd, &state8, 1)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// NB. No need to write ORA_NO_HS, since same data as ORA, just without handshake
|
||||
|
||||
saved = true;
|
||||
} while (0);
|
||||
|
||||
return saved;
|
||||
}
|
||||
|
||||
static bool _sy6522_loadState(StateHelper_s *helper, SY6522 *sy6522) {
|
||||
int fd = helper->fd;
|
||||
|
||||
bool loaded = false;
|
||||
do {
|
||||
if (!helper->load(fd, &(sy6522->ORA), 1)) {
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, &(sy6522->ORB), 1)) {
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, &(sy6522->DDRA), 1)) {
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, &(sy6522->DDRB), 1)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!helper->load(fd, (uint8_t *)&(sy6522->TIMER1_COUNTER.w), 2)) {
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, (uint8_t *)&(sy6522->TIMER1_LATCH.w), 2)) {
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, (uint8_t *)&(sy6522->TIMER2_COUNTER.w), 2)) {
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, (uint8_t *)&(sy6522->TIMER2_LATCH.w), 2)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!helper->load(fd, &(sy6522->SERIAL_SHIFT), 1)) {
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, &(sy6522->ACR), 1)) {
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, &(sy6522->PCR), 1)) {
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, &(sy6522->IFR), 1)) {
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, &(sy6522->IER), 1)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// NB. No need to write ORA_NO_HS, since same data as ORA, just without handshake
|
||||
|
||||
loaded = true;
|
||||
} while (0);
|
||||
|
||||
return loaded;
|
||||
}
|
||||
|
||||
static bool _ssi263_saveState(StateHelper_s *helper, SSI263A *ssi263) {
|
||||
int fd = helper->fd;
|
||||
|
||||
bool saved = false;
|
||||
do {
|
||||
if (!helper->save(fd, &(ssi263->DurationPhoneme), 1)) {
|
||||
break;
|
||||
}
|
||||
if (!helper->save(fd, &(ssi263->Inflection), 1)) {
|
||||
break;
|
||||
}
|
||||
if (!helper->save(fd, &(ssi263->RateInflection), 1)) {
|
||||
break;
|
||||
}
|
||||
if (!helper->save(fd, &(ssi263->CtrlArtAmp), 1)) {
|
||||
break;
|
||||
}
|
||||
if (!helper->save(fd, &(ssi263->FilterFreq), 1)) {
|
||||
break;
|
||||
}
|
||||
if (!helper->save(fd, &(ssi263->CurrentMode), 1)) {
|
||||
break;
|
||||
}
|
||||
|
||||
saved = true;
|
||||
} while (0);
|
||||
|
||||
return saved;
|
||||
}
|
||||
|
||||
static bool _ssi263_loadState(StateHelper_s *helper, SSI263A *ssi263) {
|
||||
int fd = helper->fd;
|
||||
|
||||
bool loaded = false;
|
||||
do {
|
||||
if (!helper->load(fd, &(ssi263->DurationPhoneme), 1)) {
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, &(ssi263->Inflection), 1)) {
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, &(ssi263->RateInflection), 1)) {
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, &(ssi263->CtrlArtAmp), 1)) {
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, &(ssi263->FilterFreq), 1)) {
|
||||
break;
|
||||
}
|
||||
if (!helper->load(fd, &(ssi263->CurrentMode), 1)) {
|
||||
break;
|
||||
}
|
||||
|
||||
loaded = true;
|
||||
} while (0);
|
||||
|
||||
return loaded;
|
||||
}
|
||||
|
||||
bool mb_saveState(StateHelper_s *helper) {
|
||||
LOG("SAVE mockingboard state ...");
|
||||
int fd = helper->fd;
|
||||
|
||||
bool saved = false;
|
||||
for (unsigned int i=0; i<NUM_DEVS_PER_MB; i++) {
|
||||
|
||||
unsigned int deviceIdx = i<<1;
|
||||
SY6522_AY8910 *mb = &g_MB[deviceIdx];
|
||||
|
||||
for (unsigned int j=0; j<NUM_MB; j++) {
|
||||
|
||||
if (!_sy6522_saveState(helper, &(mb->sy6522))) {
|
||||
goto exit_save;
|
||||
}
|
||||
if (!_ay8910_saveState(helper, deviceIdx)) {
|
||||
goto exit_save;
|
||||
}
|
||||
if (!_ssi263_saveState(helper, &(mb->SpeechChip))) {
|
||||
goto exit_save;
|
||||
}
|
||||
|
||||
if (!helper->save(fd, &(mb->nAYCurrentRegister), 1)) {
|
||||
goto exit_save;
|
||||
}
|
||||
|
||||
// TIMER1 IRQ
|
||||
// TIMER2 IRQ
|
||||
// SPEECH IRQ
|
||||
|
||||
deviceIdx++;
|
||||
mb++;
|
||||
}
|
||||
}
|
||||
saved = true;
|
||||
|
||||
exit_save:
|
||||
return saved;
|
||||
}
|
||||
|
||||
bool mb_loadState(StateHelper_s *helper) {
|
||||
LOG("LOAD mockingboard state ...");
|
||||
int fd = helper->fd;
|
||||
|
||||
// NOTE : always load state and calculate based on CPU @1.0 scale
|
||||
double cpuScaleFactor = cpu_scale_factor;
|
||||
double cpuAltScaleFactor = cpu_altscale_factor;
|
||||
cpu_scale_factor = 1.;
|
||||
cpu_altscale_factor = 1.;
|
||||
timing_initialize();
|
||||
|
||||
MB_Reset();
|
||||
AY8910UpdateSetCycles();
|
||||
|
||||
bool loaded = false;
|
||||
for (unsigned int i=0; i<NUM_DEVS_PER_MB; i++) {
|
||||
|
||||
for (unsigned int j=0; j<NUM_MB; j++) {
|
||||
|
||||
unsigned int idx = (i<<1) + j;
|
||||
SY6522_AY8910 *mb = &g_MB[idx];
|
||||
|
||||
if (!_sy6522_loadState(helper, &(mb->sy6522))) {
|
||||
goto exit_load;
|
||||
}
|
||||
if (!_ay8910_loadState(helper, idx)) {
|
||||
goto exit_load;
|
||||
}
|
||||
if (!_ssi263_loadState(helper, &(mb->SpeechChip))) {
|
||||
goto exit_load;
|
||||
}
|
||||
|
||||
if (!helper->load(fd, &(mb->nAYCurrentRegister), 1)) {
|
||||
goto exit_load;
|
||||
}
|
||||
|
||||
// TIMER1 IRQ
|
||||
// TIMER2 IRQ
|
||||
// SPEECH IRQ
|
||||
|
||||
StartTimer(mb);
|
||||
|
||||
++mb;
|
||||
}
|
||||
}
|
||||
loaded = true;
|
||||
|
||||
MB_Reinitialize();
|
||||
|
||||
exit_load:
|
||||
|
||||
cpu_scale_factor = cpuScaleFactor;
|
||||
cpu_altscale_factor = cpuAltScaleFactor;
|
||||
timing_initialize();
|
||||
|
||||
return loaded;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static UINT DoWriteFile(const HANDLE hFile, const void* const pData, const UINT Length)
|
||||
{
|
||||
DWORD dwBytesWritten;
|
||||
|
@ -114,14 +114,17 @@ bool MB_IsActive();
|
||||
unsigned long MB_GetVolume();
|
||||
void MB_SetVolumeZeroToTen(unsigned long goesToTen);
|
||||
void MB_SetVolume(unsigned long dwVolume, unsigned long dwVolumeMax);
|
||||
#if UNBREAK_SOON
|
||||
#if 1 // APPLE2IX
|
||||
bool mb_saveState(StateHelper_s *helper);
|
||||
bool mb_loadState(StateHelper_s *helper);
|
||||
#else
|
||||
void MB_GetSnapshot_v1(struct SS_CARD_MOCKINGBOARD_v1* const pSS, const DWORD dwSlot); // For debugger
|
||||
int MB_SetSnapshot_v1(const struct SS_CARD_MOCKINGBOARD_v1* const pSS, const DWORD dwSlot);
|
||||
std::string MB_GetSnapshotCardName(void);
|
||||
void MB_SaveSnapshot(class YamlSaveHelper& yamlSaveHelper, const UINT uSlot);
|
||||
bool MB_LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version);
|
||||
#endif
|
||||
#ifdef APPLE2IX
|
||||
#if 1 // APPLE2IX
|
||||
uint8_t mb_read(uint16_t ea);
|
||||
void mb_io_initialize(unsigned int slot4, unsigned int slot5);
|
||||
# if MB_TRACING
|
||||
|
26
src/misc.c
26
src/misc.c
@ -15,7 +15,9 @@
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define SAVE_MAGICK "A2VM"
|
||||
#define SAVE_MAGICK "A2VM"
|
||||
#define SAVE_MAGICK2 "A2V2"
|
||||
#define SAVE_VERSION 2
|
||||
#define SAVE_MAGICK_LEN sizeof(SAVE_MAGICK)
|
||||
|
||||
typedef struct module_ctor_node_s {
|
||||
@ -97,12 +99,13 @@ bool emulator_saveState(const char * const path) {
|
||||
assert(fd != 0 && "crazy platform");
|
||||
|
||||
// save header
|
||||
if (!_save_state(fd, (const uint8_t *)SAVE_MAGICK, SAVE_MAGICK_LEN)) {
|
||||
if (!_save_state(fd, (const uint8_t *)SAVE_MAGICK2, SAVE_MAGICK_LEN)) {
|
||||
break;
|
||||
}
|
||||
|
||||
StateHelper_s helper = {
|
||||
.fd = fd,
|
||||
.version = SAVE_VERSION,
|
||||
.save = &_save_state,
|
||||
.load = &_load_state,
|
||||
};
|
||||
@ -123,6 +126,10 @@ bool emulator_saveState(const char * const path) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!mb_saveState(&helper)) {
|
||||
break;
|
||||
}
|
||||
|
||||
TEMP_FAILURE_RETRY(fsync(fd));
|
||||
saved = true;
|
||||
} while (0);
|
||||
@ -149,6 +156,7 @@ bool emulator_loadState(const char * const path) {
|
||||
|
||||
video_setDirty(A2_DIRTY_FLAG);
|
||||
|
||||
int version=-1;
|
||||
do {
|
||||
TEMP_FAILURE_RETRY(fd = open(path, O_RDONLY));
|
||||
if (fd < 0) {
|
||||
@ -163,13 +171,19 @@ bool emulator_loadState(const char * const path) {
|
||||
}
|
||||
|
||||
// check header
|
||||
if (memcmp(magick, SAVE_MAGICK, SAVE_MAGICK_LEN) != 0) {
|
||||
|
||||
if (memcmp(magick, SAVE_MAGICK, SAVE_MAGICK_LEN) == 0) {
|
||||
version = 1;
|
||||
} else if (memcmp(magick, SAVE_MAGICK2, SAVE_MAGICK_LEN) == 0) {
|
||||
version = 2;
|
||||
} else {
|
||||
ERRLOG("bad header magick in emulator save state file");
|
||||
break;
|
||||
}
|
||||
|
||||
StateHelper_s helper = {
|
||||
.fd = fd,
|
||||
.version = version,
|
||||
.save = &_save_state,
|
||||
.load = &_load_state,
|
||||
};
|
||||
@ -190,6 +204,12 @@ bool emulator_loadState(const char * const path) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (version >= 2) {
|
||||
if (!mb_loadState(&helper)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
loaded = true;
|
||||
} while (0);
|
||||
|
||||
|
@ -59,6 +59,7 @@ bool emulator_isShuttingDown(void);
|
||||
|
||||
typedef struct StateHelper_s {
|
||||
int fd;
|
||||
int version;
|
||||
bool (*save)(int fd, const uint8_t * outbuf, ssize_t outmax);
|
||||
bool (*load)(int fd, uint8_t * inbuf, ssize_t inmax);
|
||||
} StateHelper_s;
|
||||
|
Loading…
Reference in New Issue
Block a user