mirror of
https://github.com/mauiaaron/apple2.git
synced 2024-12-26 00:31:44 +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_KEY_CHANGE "Change"
|
||||||
#define SS_YAML_VALUE_CHANGE_FORMAT "%d, %d, 0x%1X, 0x%02X"
|
#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)
|
void CAY8910::SaveSnapshot(YamlSaveHelper& yamlSaveHelper, std::string& suffix)
|
||||||
{
|
{
|
||||||
std::string unit = std::string(SS_YAML_KEY_AY8910) + 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;
|
return true;
|
||||||
}
|
}
|
||||||
#endif // UNBREAK_SOON
|
#endif
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@ -1277,7 +1554,17 @@ uint8_t* AY8910_GetRegsPtr(unsigned int uChip)
|
|||||||
return GetAYRegsPtr(&g_AY8910[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)
|
UINT AY8910_SaveSnapshot(YamlSaveHelper& yamlSaveHelper, UINT uChip, std::string& suffix)
|
||||||
{
|
{
|
||||||
if (uChip >= MAX_8910)
|
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;
|
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();
|
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_SaveSnapshot(class YamlSaveHelper& yamlSaveHelper, UINT uChip, std::string& suffix);
|
||||||
UINT AY8910_LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT uChip, std::string& suffix);
|
UINT AY8910_LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT uChip, std::string& suffix);
|
||||||
#endif
|
#endif
|
||||||
@ -69,7 +72,8 @@ public:
|
|||||||
void sound_frame(struct CAY8910 *_this);
|
void sound_frame(struct CAY8910 *_this);
|
||||||
uint8_t* GetAYRegsPtr(struct CAY8910 *_this);
|
uint8_t* GetAYRegsPtr(struct CAY8910 *_this);
|
||||||
void SetCLK(double CLK);
|
void SetCLK(double CLK);
|
||||||
#if UNBREAK_SOON
|
#if 1 // APPLE2IX
|
||||||
|
#else
|
||||||
void SaveSnapshot(class YamlSaveHelper& yamlSaveHelper, std::string& suffix);
|
void SaveSnapshot(class YamlSaveHelper& yamlSaveHelper, std::string& suffix);
|
||||||
bool LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, std::string& suffix);
|
bool LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, std::string& suffix);
|
||||||
#endif
|
#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) {
|
static void mb_prefsChanged(const char *domain) {
|
||||||
long lVal = 0;
|
long lVal = 0;
|
||||||
long goesToTen = prefs_parseLongValue(domain, PREF_MOCKINGBOARD_VOLUME, &lVal, /*base:*/10) ? lVal : 5; // expected range 0-10
|
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);
|
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)
|
static UINT DoWriteFile(const HANDLE hFile, const void* const pData, const UINT Length)
|
||||||
{
|
{
|
||||||
DWORD dwBytesWritten;
|
DWORD dwBytesWritten;
|
||||||
|
@ -114,14 +114,17 @@ bool MB_IsActive();
|
|||||||
unsigned long MB_GetVolume();
|
unsigned long MB_GetVolume();
|
||||||
void MB_SetVolumeZeroToTen(unsigned long goesToTen);
|
void MB_SetVolumeZeroToTen(unsigned long goesToTen);
|
||||||
void MB_SetVolume(unsigned long dwVolume, unsigned long dwVolumeMax);
|
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
|
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);
|
int MB_SetSnapshot_v1(const struct SS_CARD_MOCKINGBOARD_v1* const pSS, const DWORD dwSlot);
|
||||||
std::string MB_GetSnapshotCardName(void);
|
std::string MB_GetSnapshotCardName(void);
|
||||||
void MB_SaveSnapshot(class YamlSaveHelper& yamlSaveHelper, const UINT uSlot);
|
void MB_SaveSnapshot(class YamlSaveHelper& yamlSaveHelper, const UINT uSlot);
|
||||||
bool MB_LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version);
|
bool MB_LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version);
|
||||||
#endif
|
#endif
|
||||||
#ifdef APPLE2IX
|
#if 1 // APPLE2IX
|
||||||
uint8_t mb_read(uint16_t ea);
|
uint8_t mb_read(uint16_t ea);
|
||||||
void mb_io_initialize(unsigned int slot4, unsigned int slot5);
|
void mb_io_initialize(unsigned int slot4, unsigned int slot5);
|
||||||
# if MB_TRACING
|
# if MB_TRACING
|
||||||
|
24
src/misc.c
24
src/misc.c
@ -16,6 +16,8 @@
|
|||||||
#include "common.h"
|
#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)
|
#define SAVE_MAGICK_LEN sizeof(SAVE_MAGICK)
|
||||||
|
|
||||||
typedef struct module_ctor_node_s {
|
typedef struct module_ctor_node_s {
|
||||||
@ -97,12 +99,13 @@ bool emulator_saveState(const char * const path) {
|
|||||||
assert(fd != 0 && "crazy platform");
|
assert(fd != 0 && "crazy platform");
|
||||||
|
|
||||||
// save header
|
// 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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
StateHelper_s helper = {
|
StateHelper_s helper = {
|
||||||
.fd = fd,
|
.fd = fd,
|
||||||
|
.version = SAVE_VERSION,
|
||||||
.save = &_save_state,
|
.save = &_save_state,
|
||||||
.load = &_load_state,
|
.load = &_load_state,
|
||||||
};
|
};
|
||||||
@ -123,6 +126,10 @@ bool emulator_saveState(const char * const path) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!mb_saveState(&helper)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
TEMP_FAILURE_RETRY(fsync(fd));
|
TEMP_FAILURE_RETRY(fsync(fd));
|
||||||
saved = true;
|
saved = true;
|
||||||
} while (0);
|
} while (0);
|
||||||
@ -149,6 +156,7 @@ bool emulator_loadState(const char * const path) {
|
|||||||
|
|
||||||
video_setDirty(A2_DIRTY_FLAG);
|
video_setDirty(A2_DIRTY_FLAG);
|
||||||
|
|
||||||
|
int version=-1;
|
||||||
do {
|
do {
|
||||||
TEMP_FAILURE_RETRY(fd = open(path, O_RDONLY));
|
TEMP_FAILURE_RETRY(fd = open(path, O_RDONLY));
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
@ -163,13 +171,19 @@ bool emulator_loadState(const char * const path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check header
|
// 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");
|
ERRLOG("bad header magick in emulator save state file");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
StateHelper_s helper = {
|
StateHelper_s helper = {
|
||||||
.fd = fd,
|
.fd = fd,
|
||||||
|
.version = version,
|
||||||
.save = &_save_state,
|
.save = &_save_state,
|
||||||
.load = &_load_state,
|
.load = &_load_state,
|
||||||
};
|
};
|
||||||
@ -190,6 +204,12 @@ bool emulator_loadState(const char * const path) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (version >= 2) {
|
||||||
|
if (!mb_loadState(&helper)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
loaded = true;
|
loaded = true;
|
||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
|
@ -59,6 +59,7 @@ bool emulator_isShuttingDown(void);
|
|||||||
|
|
||||||
typedef struct StateHelper_s {
|
typedef struct StateHelper_s {
|
||||||
int fd;
|
int fd;
|
||||||
|
int version;
|
||||||
bool (*save)(int fd, const uint8_t * outbuf, ssize_t outmax);
|
bool (*save)(int fd, const uint8_t * outbuf, ssize_t outmax);
|
||||||
bool (*load)(int fd, uint8_t * inbuf, ssize_t inmax);
|
bool (*load)(int fd, uint8_t * inbuf, ssize_t inmax);
|
||||||
} StateHelper_s;
|
} StateHelper_s;
|
||||||
|
Loading…
Reference in New Issue
Block a user