2006-02-25 20:50:29 +00:00
/*
AppleWin : An Apple //e emulator for Windows
Copyright ( C ) 1994 - 1996 , Michael O ' Brien
Copyright ( C ) 1999 - 2001 , Oliver Schmidt
Copyright ( C ) 2002 - 2005 , Tom Charlesworth
2016-03-21 23:48:02 +00:00
Copyright ( C ) 2006 - 2015 , Tom Charlesworth , Michael Pohoreski
2006-02-25 20:50:29 +00:00
AppleWin is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
AppleWin is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with AppleWin ; if not , write to the Free Software
Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
/* Description: Save-state (snapshot) module
*
2016-03-21 23:48:02 +00:00
* Author : Copyright ( c ) 2004 - 2015 Tom Charlesworth
2006-02-25 20:50:29 +00:00
*/
# include "StdAfx.h"
2014-08-13 21:30:35 +01:00
2016-03-21 23:48:02 +00:00
# include "YamlHelper.h"
2018-02-24 15:12:40 +00:00
# include "Applewin.h"
2014-08-13 21:30:35 +01:00
# include "CPU.h"
# include "Disk.h"
# include "Frame.h"
2013-12-31 22:40:10 +00:00
# include "Joystick.h"
2014-08-13 21:30:35 +01:00
# include "Keyboard.h"
2018-10-26 11:23:30 -07:00
# include "LanguageCard.h"
2014-08-13 21:30:35 +01:00
# include "Memory.h"
# include "Mockingboard.h"
2016-03-21 23:48:02 +00:00
# include "MouseInterface.h"
# include "ParallelPrinter.h"
# include "Pravets.h"
2014-08-13 21:30:35 +01:00
# include "SerialComms.h"
# include "Speaker.h"
2016-03-21 23:48:02 +00:00
# include "Speech.h"
2014-08-13 21:30:35 +01:00
# include "Video.h"
2016-03-21 23:48:02 +00:00
# include "z80emu.h"
2018-02-24 15:12:40 +00:00
# include "Configuration/Config.h"
# include "Configuration/IPropertySheet.h"
2010-02-14 21:11:26 +00:00
2006-02-25 20:50:29 +00:00
2016-03-21 23:48:02 +00:00
# define DEFAULT_SNAPSHOT_NAME "SaveState.aws.yaml"
2006-02-25 20:50:29 +00:00
bool g_bSaveStateOnExit = false ;
2013-12-29 22:09:41 +00:00
static std : : string g_strSaveStateFilename ;
static std : : string g_strSaveStatePathname ;
static std : : string g_strSaveStatePath ;
2006-02-25 20:50:29 +00:00
2016-03-21 23:48:02 +00:00
static YamlHelper yamlHelper ;
# define SS_FILE_VER 2
2019-04-06 11:18:48 +01:00
// Unit version history:
// v2: Extended: keyboard (added 'Key Waiting'), memory (LC mem type for II/II+, inverted MF_INTCXROM bit)
// v3: Extended: memory (added 'AnnunciatorN')
2019-06-28 21:34:34 +01:00
// v4: Extended: video (added 'Video Refresh Rate')
# define UNIT_APPLE2_VER 4
2019-04-06 11:18:48 +01:00
2016-03-21 23:48:02 +00:00
# define UNIT_SLOTS_VER 1
2006-02-25 20:50:29 +00:00
//-----------------------------------------------------------------------------
2019-09-07 19:37:19 +01:00
void Snapshot_SetFilename ( const std : : string & strPathname )
2006-02-25 20:50:29 +00:00
{
2013-12-29 22:09:41 +00:00
if ( strPathname . empty ( ) )
{
g_strSaveStateFilename = DEFAULT_SNAPSHOT_NAME ;
g_strSaveStatePathname = g_sCurrentDir ;
if ( g_strSaveStatePathname . length ( ) & & g_strSaveStatePathname [ g_strSaveStatePathname . length ( ) - 1 ] ! = ' \\ ' )
g_strSaveStatePathname + = " \\ " ;
g_strSaveStatePathname . append ( DEFAULT_SNAPSHOT_NAME ) ;
g_strSaveStatePath = g_sCurrentDir ;
return ;
}
std : : string strFilename = strPathname ; // Set default, as maybe there's no path
g_strSaveStatePath . clear ( ) ;
int nIdx = strPathname . find_last_of ( ' \\ ' ) ;
if ( nIdx > = 0 & & nIdx + 1 < ( int ) strPathname . length ( ) )
{
strFilename = & strPathname [ nIdx + 1 ] ;
2014-09-02 08:48:46 -07:00
g_strSaveStatePath = strPathname . substr ( 0 , nIdx + 1 ) ; // Bugfix: 1.25.0.2 // Snapshot_LoadState() -> SetCurrentImageDir() -> g_sCurrentDir
2013-12-29 22:09:41 +00:00
}
g_strSaveStateFilename = strFilename ;
g_strSaveStatePathname = strPathname ;
2006-02-25 20:50:29 +00:00
}
2019-09-07 09:02:39 +01:00
const std : : string & Snapshot_GetFilename ( )
2006-02-25 20:50:29 +00:00
{
2019-09-07 09:02:39 +01:00
return g_strSaveStateFilename ;
2013-12-29 22:09:41 +00:00
}
2019-09-07 09:02:39 +01:00
const std : : string & Snapshot_GetPath ( )
2013-12-29 22:09:41 +00:00
{
2019-09-07 09:02:39 +01:00
return g_strSaveStatePath ;
2006-02-25 20:50:29 +00:00
}
//-----------------------------------------------------------------------------
2016-03-21 23:48:02 +00:00
static HANDLE m_hFile = INVALID_HANDLE_VALUE ;
static CConfigNeedingRestart m_ConfigNew ;
static std : : string GetSnapshotUnitApple2Name ( void )
{
static const std : : string name ( " Apple2 " ) ;
return name ;
}
static std : : string GetSnapshotUnitSlotsName ( void )
{
static const std : : string name ( " Slots " ) ;
return name ;
}
# define SS_YAML_KEY_MODEL "Model"
# define SS_YAML_VALUE_APPLE2 "Apple]["
# define SS_YAML_VALUE_APPLE2PLUS "Apple][+"
# define SS_YAML_VALUE_APPLE2E "Apple //e"
# define SS_YAML_VALUE_APPLE2EENHANCED "Enhanced Apple //e"
# define SS_YAML_VALUE_APPLE2C "Apple2c"
# define SS_YAML_VALUE_PRAVETS82 "Pravets82"
# define SS_YAML_VALUE_PRAVETS8M "Pravets8M"
# define SS_YAML_VALUE_PRAVETS8A "Pravets8A"
2016-10-23 10:35:18 +01:00
# define SS_YAML_VALUE_TK30002E "TK3000 //e"
2016-03-21 23:48:02 +00:00
static eApple2Type ParseApple2Type ( std : : string type )
2006-02-25 20:50:29 +00:00
{
2016-03-21 23:48:02 +00:00
if ( type = = SS_YAML_VALUE_APPLE2 ) return A2TYPE_APPLE2 ;
else if ( type = = SS_YAML_VALUE_APPLE2PLUS ) return A2TYPE_APPLE2PLUS ;
else if ( type = = SS_YAML_VALUE_APPLE2E ) return A2TYPE_APPLE2E ;
else if ( type = = SS_YAML_VALUE_APPLE2EENHANCED ) return A2TYPE_APPLE2EENHANCED ;
else if ( type = = SS_YAML_VALUE_APPLE2C ) return A2TYPE_APPLE2C ;
else if ( type = = SS_YAML_VALUE_PRAVETS82 ) return A2TYPE_PRAVETS82 ;
else if ( type = = SS_YAML_VALUE_PRAVETS8M ) return A2TYPE_PRAVETS8M ;
else if ( type = = SS_YAML_VALUE_PRAVETS8A ) return A2TYPE_PRAVETS8A ;
2016-10-23 10:35:18 +01:00
else if ( type = = SS_YAML_VALUE_TK30002E ) return A2TYPE_TK30002E ;
2016-03-21 23:48:02 +00:00
throw std : : string ( " Load: Unknown Apple2 type " ) ;
}
static std : : string GetApple2TypeAsString ( void )
{
switch ( GetApple2Type ( ) )
2006-02-25 20:50:29 +00:00
{
2016-03-21 23:48:02 +00:00
case A2TYPE_APPLE2 : return SS_YAML_VALUE_APPLE2 ;
case A2TYPE_APPLE2PLUS : return SS_YAML_VALUE_APPLE2PLUS ;
case A2TYPE_APPLE2E : return SS_YAML_VALUE_APPLE2E ;
case A2TYPE_APPLE2EENHANCED : return SS_YAML_VALUE_APPLE2EENHANCED ;
case A2TYPE_APPLE2C : return SS_YAML_VALUE_APPLE2C ;
case A2TYPE_PRAVETS82 : return SS_YAML_VALUE_PRAVETS82 ;
case A2TYPE_PRAVETS8M : return SS_YAML_VALUE_PRAVETS8M ;
case A2TYPE_PRAVETS8A : return SS_YAML_VALUE_PRAVETS8A ;
2016-10-23 10:35:18 +01:00
case A2TYPE_TK30002E : return SS_YAML_VALUE_TK30002E ;
2016-03-21 23:48:02 +00:00
default :
throw std : : string ( " Save: Unknown Apple2 type " ) ;
2006-02-25 20:50:29 +00:00
}
2016-03-21 23:48:02 +00:00
}
2006-02-25 20:50:29 +00:00
2016-03-21 23:48:02 +00:00
//---
2006-02-25 20:50:29 +00:00
2016-03-21 23:48:02 +00:00
static UINT ParseFileHdr ( void )
{
std : : string scalar ;
if ( ! yamlHelper . GetScalar ( scalar ) )
throw std : : string ( SS_YAML_KEY_FILEHDR " : Failed to find scalar " ) ;
2006-02-25 20:50:29 +00:00
2016-03-21 23:48:02 +00:00
if ( scalar ! = SS_YAML_KEY_FILEHDR )
throw std : : string ( " Failed to find file header " ) ;
2006-02-25 20:50:29 +00:00
2016-03-21 23:48:02 +00:00
yamlHelper . GetMapStartEvent ( ) ;
2006-02-25 20:50:29 +00:00
2016-03-21 23:48:02 +00:00
YamlLoadHelper yamlLoadHelper ( yamlHelper ) ;
2006-02-25 20:50:29 +00:00
//
2016-03-21 23:48:02 +00:00
std : : string value = yamlLoadHelper . LoadString ( SS_YAML_KEY_TAG ) ;
if ( value ! = SS_YAML_VALUE_AWSS )
{
//printf("%s: Bad tag (%s) - expected %s\n", SS_YAML_KEY_FILEHDR, value.c_str(), SS_YAML_VALUE_AWSS);
throw std : : string ( SS_YAML_KEY_FILEHDR " : Bad tag " ) ;
}
2006-02-25 20:50:29 +00:00
2016-03-21 23:48:02 +00:00
return yamlLoadHelper . LoadUint ( SS_YAML_KEY_VERSION ) ;
}
2006-02-25 20:50:29 +00:00
2016-03-21 23:48:02 +00:00
//---
2006-02-25 20:50:29 +00:00
2016-03-21 23:48:02 +00:00
static void ParseUnitApple2 ( YamlLoadHelper & yamlLoadHelper , UINT version )
{
2018-10-26 11:23:30 -07:00
if ( version = = 0 | | version > UNIT_APPLE2_VER )
2016-03-21 23:48:02 +00:00
throw std : : string ( SS_YAML_KEY_UNIT " : Apple2: Version mismatch " ) ;
2006-02-25 20:50:29 +00:00
2016-03-21 23:48:02 +00:00
std : : string model = yamlLoadHelper . LoadString ( SS_YAML_KEY_MODEL ) ;
SetApple2Type ( ParseApple2Type ( model ) ) ; // NB. Sets default main CPU type
m_ConfigNew . m_Apple2Type = GetApple2Type ( ) ;
2006-02-25 20:50:29 +00:00
2016-03-21 23:48:02 +00:00
CpuLoadSnapshot ( yamlLoadHelper ) ; // NB. Overrides default main CPU type
m_ConfigNew . m_CpuType = GetMainCpu ( ) ;
2006-02-25 20:50:29 +00:00
2016-03-21 23:48:02 +00:00
JoyLoadSnapshot ( yamlLoadHelper ) ;
2018-11-01 21:14:16 +00:00
KeybLoadSnapshot ( yamlLoadHelper , version ) ;
2016-03-21 23:48:02 +00:00
SpkrLoadSnapshot ( yamlLoadHelper ) ;
2019-06-28 21:34:34 +01:00
VideoLoadSnapshot ( yamlLoadHelper , version ) ;
2018-10-26 11:23:30 -07:00
MemLoadSnapshot ( yamlLoadHelper , version ) ;
2016-12-11 16:31:25 +00:00
// g_Apple2Type may've changed: so redraw frame (title, buttons, leds, etc)
VideoReinitialize ( ) ; // g_CharsetType changed
2019-02-02 15:51:27 +00:00
FrameUpdateApple2Type ( ) ; // Calls VideoRedrawScreen() before the aux mem has been loaded (so if DHGR is enabled, then aux mem will be zeros at this stage)
2016-03-21 23:48:02 +00:00
}
2006-02-25 20:50:29 +00:00
2016-03-21 23:48:02 +00:00
//---
2006-02-25 20:50:29 +00:00
2019-02-02 15:51:27 +00:00
static void ParseSlots ( YamlLoadHelper & yamlLoadHelper , UINT unitVersion )
2016-03-21 23:48:02 +00:00
{
2019-02-02 15:51:27 +00:00
if ( unitVersion ! = UNIT_SLOTS_VER )
2016-03-21 23:48:02 +00:00
throw std : : string ( SS_YAML_KEY_UNIT " : Slots: Version mismatch " ) ;
while ( 1 )
2006-02-25 20:50:29 +00:00
{
2016-03-21 23:48:02 +00:00
std : : string scalar = yamlLoadHelper . GetMapNextSlotNumber ( ) ;
if ( scalar . empty ( ) )
break ; // done all slots
2006-02-25 20:50:29 +00:00
2016-03-21 23:48:02 +00:00
const int slot = strtoul ( scalar . c_str ( ) , NULL , 10 ) ; // NB. aux slot supported as a different "unit"
2018-10-26 11:23:30 -07:00
// NB. slot-0 only supported for Apple II or II+ (or similar clones)
if ( slot < 0 | | slot > 7 )
2016-03-21 23:48:02 +00:00
throw std : : string ( " Slots: Invalid slot #: " ) + scalar ;
2006-02-25 20:50:29 +00:00
2016-03-21 23:48:02 +00:00
yamlLoadHelper . GetSubMap ( scalar ) ;
std : : string card = yamlLoadHelper . LoadString ( SS_YAML_KEY_CARD ) ;
2019-02-02 15:51:27 +00:00
UINT cardVersion = yamlLoadHelper . LoadUint ( SS_YAML_KEY_VERSION ) ;
2016-03-21 23:48:02 +00:00
if ( ! yamlLoadHelper . GetSubMap ( std : : string ( SS_YAML_KEY_STATE ) ) )
throw std : : string ( SS_YAML_KEY_UNIT " : Expected sub-map name: " SS_YAML_KEY_STATE ) ;
SS_CARDTYPE type = CT_Empty ;
bool bRes = false ;
if ( card = = Printer_GetSnapshotCardName ( ) )
{
2019-02-02 15:51:27 +00:00
bRes = Printer_LoadSnapshot ( yamlLoadHelper , slot , cardVersion ) ;
2016-03-21 23:48:02 +00:00
type = CT_GenericPrinter ;
}
else if ( card = = sg_SSC . GetSnapshotCardName ( ) )
{
2019-02-02 15:51:27 +00:00
bRes = sg_SSC . LoadSnapshot ( yamlLoadHelper , slot , cardVersion ) ;
2016-03-21 23:48:02 +00:00
type = CT_SSC ;
}
else if ( card = = sg_Mouse . GetSnapshotCardName ( ) )
{
2019-02-02 15:51:27 +00:00
bRes = sg_Mouse . LoadSnapshot ( yamlLoadHelper , slot , cardVersion ) ;
2016-03-21 23:48:02 +00:00
type = CT_MouseInterface ;
}
else if ( card = = Z80_GetSnapshotCardName ( ) )
{
2019-02-02 15:51:27 +00:00
bRes = Z80_LoadSnapshot ( yamlLoadHelper , slot , cardVersion ) ;
2016-03-21 23:48:02 +00:00
type = CT_Z80 ;
}
else if ( card = = MB_GetSnapshotCardName ( ) )
{
2019-02-02 15:51:27 +00:00
bRes = MB_LoadSnapshot ( yamlLoadHelper , slot , cardVersion ) ;
2016-03-21 23:48:02 +00:00
type = CT_MockingboardC ;
}
else if ( card = = Phasor_GetSnapshotCardName ( ) )
{
2019-02-02 15:51:27 +00:00
bRes = Phasor_LoadSnapshot ( yamlLoadHelper , slot , cardVersion ) ;
2016-03-21 23:48:02 +00:00
type = CT_Phasor ;
}
2019-04-14 17:01:49 +01:00
else if ( card = = sg_Disk2Card . GetSnapshotCardName ( ) )
2016-03-21 23:48:02 +00:00
{
2019-04-14 17:01:49 +01:00
bRes = sg_Disk2Card . LoadSnapshot ( yamlLoadHelper , slot , cardVersion ) ;
2016-03-21 23:48:02 +00:00
type = CT_Disk2 ;
}
else if ( card = = HD_GetSnapshotCardName ( ) )
{
2019-02-02 15:51:27 +00:00
bRes = HD_LoadSnapshot ( yamlLoadHelper , slot , cardVersion , g_strSaveStatePath ) ;
2016-03-21 23:48:02 +00:00
m_ConfigNew . m_bEnableHDD = true ;
type = CT_GenericHDD ;
}
2018-10-26 11:23:30 -07:00
else if ( card = = LanguageCardSlot0 : : GetSnapshotCardName ( ) )
{
type = CT_LanguageCard ;
SetExpansionMemType ( type ) ;
2018-11-09 20:51:51 +00:00
CreateLanguageCard ( ) ;
2019-02-02 15:51:27 +00:00
bRes = GetLanguageCard ( ) - > LoadSnapshot ( yamlLoadHelper , slot , cardVersion ) ;
2018-10-26 11:23:30 -07:00
}
else if ( card = = Saturn128K : : GetSnapshotCardName ( ) )
{
type = CT_Saturn128K ;
SetExpansionMemType ( type ) ;
2018-11-09 20:51:51 +00:00
CreateLanguageCard ( ) ;
2019-02-02 15:51:27 +00:00
bRes = GetLanguageCard ( ) - > LoadSnapshot ( yamlLoadHelper , slot , cardVersion ) ;
2018-10-26 11:23:30 -07:00
}
2016-03-21 23:48:02 +00:00
else
{
throw std : : string ( " Slots: Unknown card: " + card ) ; // todo: don't throw - just ignore & continue
}
2018-11-09 20:51:51 +00:00
if ( bRes )
2016-03-21 23:48:02 +00:00
{
m_ConfigNew . m_Slot [ slot ] = type ;
}
yamlLoadHelper . PopMap ( ) ;
yamlLoadHelper . PopMap ( ) ;
}
}
//---
static void ParseUnit ( void )
{
yamlHelper . GetMapStartEvent ( ) ;
YamlLoadHelper yamlLoadHelper ( yamlHelper ) ;
std : : string unit = yamlLoadHelper . LoadString ( SS_YAML_KEY_TYPE ) ;
2019-02-02 15:51:27 +00:00
UINT unitVersion = yamlLoadHelper . LoadUint ( SS_YAML_KEY_VERSION ) ;
2016-03-21 23:48:02 +00:00
if ( ! yamlLoadHelper . GetSubMap ( std : : string ( SS_YAML_KEY_STATE ) ) )
throw std : : string ( SS_YAML_KEY_UNIT " : Expected sub-map name: " SS_YAML_KEY_STATE ) ;
if ( unit = = GetSnapshotUnitApple2Name ( ) )
{
2019-02-02 15:51:27 +00:00
ParseUnitApple2 ( yamlLoadHelper , unitVersion ) ;
2016-03-21 23:48:02 +00:00
}
else if ( unit = = MemGetSnapshotUnitAuxSlotName ( ) )
{
2019-02-02 15:51:27 +00:00
MemLoadSnapshotAux ( yamlLoadHelper , unitVersion ) ;
2016-03-21 23:48:02 +00:00
}
else if ( unit = = GetSnapshotUnitSlotsName ( ) )
{
2019-02-02 15:51:27 +00:00
ParseSlots ( yamlLoadHelper , unitVersion ) ;
2006-02-25 20:50:29 +00:00
}
else
{
2016-03-21 23:48:02 +00:00
throw std : : string ( SS_YAML_KEY_UNIT " : Unknown type: " ) + unit ;
2006-02-25 20:50:29 +00:00
}
2016-03-21 23:48:02 +00:00
}
static void Snapshot_LoadState_v2 ( void )
{
2019-02-24 10:29:34 +00:00
bool restart = false ; // Only need to restart if any VM state has change
2016-03-21 23:48:02 +00:00
try
{
2019-02-24 10:29:34 +00:00
if ( ! yamlHelper . InitParser ( g_strSaveStatePathname . c_str ( ) ) )
throw std : : string ( " Failed to initialize parser or open file " ) ;
2019-02-23 04:17:29 -05:00
2019-02-24 10:29:34 +00:00
if ( ParseFileHdr ( ) ! = SS_FILE_VER )
throw std : : string ( " Version mismatch " ) ;
2006-02-25 20:50:29 +00:00
2016-03-21 23:48:02 +00:00
//
2019-02-24 10:29:34 +00:00
restart = true ;
2016-03-21 23:48:02 +00:00
CConfigNeedingRestart ConfigOld ;
2018-10-26 11:23:30 -07:00
//ConfigOld.m_Slot[0] = CT_LanguageCard; // fixme: II/II+=LC, //e=empty
2016-03-21 23:48:02 +00:00
ConfigOld . m_Slot [ 1 ] = CT_GenericPrinter ; // fixme
ConfigOld . m_Slot [ 2 ] = CT_SSC ; // fixme
//ConfigOld.m_Slot[3] = CT_Uthernet; // todo
ConfigOld . m_Slot [ 6 ] = CT_Disk2 ; // fixme
ConfigOld . m_Slot [ 7 ] = ConfigOld . m_bEnableHDD ? CT_GenericHDD : CT_Empty ; // fixme
//ConfigOld.m_SlotAux = ?; // fixme
for ( UINT i = 0 ; i < NUM_SLOTS ; i + + )
m_ConfigNew . m_Slot [ i ] = CT_Empty ;
m_ConfigNew . m_SlotAux = CT_Empty ;
m_ConfigNew . m_bEnableHDD = false ;
//m_ConfigNew.m_bEnableTheFreezesF8Rom = ?; // todo: when support saving config
MemReset ( ) ;
PravetsReset ( ) ;
2019-04-14 17:01:49 +01:00
sg_Disk2Card . Reset ( ) ;
2017-12-03 21:05:05 +00:00
HD_Reset ( ) ;
2016-03-21 23:48:02 +00:00
KeybReset ( ) ;
VideoResetState ( ) ;
2019-06-28 21:34:34 +01:00
SetVideoRefreshRate ( VR_60HZ ) ; // Default to 60Hz as older save-states won't contain refresh rate
2019-02-24 10:49:09 +00:00
MB_InitializeForLoadingSnapshot ( ) ; // GH#609
2018-04-08 17:37:26 +01:00
sg_SSC . CommReset ( ) ;
2016-03-21 23:48:02 +00:00
# ifdef USE_SPEECH_API
g_Speech . Reset ( ) ;
# endif
sg_Mouse . Uninitialize ( ) ;
sg_Mouse . Reset ( ) ;
HD_SetEnabled ( false ) ;
std : : string scalar ;
while ( yamlHelper . GetScalar ( scalar ) )
{
if ( scalar = = SS_YAML_KEY_UNIT )
ParseUnit ( ) ;
else
throw std : : string ( " Unknown top-level scalar: " + scalar ) ;
}
SetLoadedSaveStateFlag ( true ) ;
// NB. The following disparity should be resolved:
// . A change in h/w via the Configuration property sheets results in a the VM completely restarting (via WM_USER_RESTART)
// . A change in h/w via loading a save-state avoids this VM restart
// The latter is the desired approach (as the former needs a "power-on" / F2 to start things again)
2019-06-28 21:34:34 +01:00
sg_PropertySheet . ApplyNewConfig ( m_ConfigNew , ConfigOld ) ; // Mainly just saves (some) new state to Registry
2016-03-21 23:48:02 +00:00
MemInitializeROM ( ) ;
MemInitializeCustomF8ROM ( ) ;
MemInitializeIO ( ) ;
2017-09-22 22:23:13 +01:00
MemInitializeCardExpansionRomFromSnapshot ( ) ;
2016-03-21 23:48:02 +00:00
MemUpdatePaging ( TRUE ) ;
}
catch ( std : : string szMessage )
{
MessageBox ( g_hFrameWindow ,
szMessage . c_str ( ) ,
TEXT ( " Load State " ) ,
MB_ICONEXCLAMATION | MB_SETFOREGROUND ) ;
2019-02-24 10:29:34 +00:00
if ( restart )
PostMessage ( g_hFrameWindow , WM_USER_RESTART , 0 , 0 ) ; // Power-cycle VM (undoing all the new state just loaded)
2016-03-21 23:48:02 +00:00
}
yamlHelper . FinaliseParser ( ) ;
}
void Snapshot_LoadState ( )
{
const std : : string ext_aws = ( " .aws " ) ;
const size_t pos = g_strSaveStatePathname . size ( ) - ext_aws . size ( ) ;
if ( g_strSaveStatePathname . find ( ext_aws , pos ) ! = std : : string : : npos ) // find ".aws" at end of pathname
{
2019-01-05 22:20:51 +00:00
MessageBox ( g_hFrameWindow ,
" Save-state v1 no longer supported. \n "
" Please load using AppleWin 1.27, and re-save as a v2 state file. " ,
TEXT ( " Load State " ) ,
MB_ICONEXCLAMATION | MB_SETFOREGROUND ) ;
2016-03-21 23:48:02 +00:00
return ;
}
Snapshot_LoadState_v2 ( ) ;
}
//-----------------------------------------------------------------------------
// todo:
// . Uthernet card
void Snapshot_SaveState ( void )
{
try
{
YamlSaveHelper yamlSaveHelper ( g_strSaveStatePathname ) ;
yamlSaveHelper . FileHdr ( SS_FILE_VER ) ;
// Unit: Apple2
{
yamlSaveHelper . UnitHdr ( GetSnapshotUnitApple2Name ( ) , UNIT_APPLE2_VER ) ;
YamlSaveHelper : : Label state ( yamlSaveHelper , " %s: \n " , SS_YAML_KEY_STATE ) ;
yamlSaveHelper . Save ( " %s: %s \n " , SS_YAML_KEY_MODEL , GetApple2TypeAsString ( ) . c_str ( ) ) ;
CpuSaveSnapshot ( yamlSaveHelper ) ;
JoySaveSnapshot ( yamlSaveHelper ) ;
KeybSaveSnapshot ( yamlSaveHelper ) ;
SpkrSaveSnapshot ( yamlSaveHelper ) ;
VideoSaveSnapshot ( yamlSaveHelper ) ;
MemSaveSnapshot ( yamlSaveHelper ) ;
}
// Unit: Aux slot
MemSaveSnapshotAux ( yamlSaveHelper ) ;
// Unit: Slots
{
yamlSaveHelper . UnitHdr ( GetSnapshotUnitSlotsName ( ) , UNIT_SLOTS_VER ) ;
YamlSaveHelper : : Label state ( yamlSaveHelper , " %s: \n " , SS_YAML_KEY_STATE ) ;
2019-09-15 20:37:20 +01:00
if ( g_Slot [ 0 ] ! = CT_Empty & & IsApple2PlusOrClone ( GetApple2Type ( ) ) )
2018-10-26 11:23:30 -07:00
GetLanguageCard ( ) - > SaveSnapshot ( yamlSaveHelper ) ; // Language Card or Saturn 128K
2019-09-15 20:37:20 +01:00
if ( g_Slot [ 1 ] = = CT_GenericPrinter )
Printer_SaveSnapshot ( yamlSaveHelper ) ;
2016-03-21 23:48:02 +00:00
2019-09-15 20:37:20 +01:00
if ( g_Slot [ 2 ] = = CT_SSC )
sg_SSC . SaveSnapshot ( yamlSaveHelper ) ;
// if (g_Slot[3] == CT_Uthernet)
// sg_Uthernet.SaveSnapshot(yamlSaveHelper);
2016-03-21 23:48:02 +00:00
sg_Mouse . SaveSnapshot ( yamlSaveHelper ) ;
2019-09-15 20:37:20 +01:00
if ( g_Slot [ 4 ] = = CT_Z80 )
2016-03-21 23:48:02 +00:00
Z80_SaveSnapshot ( yamlSaveHelper , 4 ) ;
2019-09-15 20:37:20 +01:00
if ( g_Slot [ 5 ] = = CT_Z80 )
2016-03-21 23:48:02 +00:00
Z80_SaveSnapshot ( yamlSaveHelper , 5 ) ;
2019-09-15 20:37:20 +01:00
if ( g_Slot [ 4 ] = = CT_MockingboardC )
2016-03-21 23:48:02 +00:00
MB_SaveSnapshot ( yamlSaveHelper , 4 ) ;
2019-09-15 20:37:20 +01:00
if ( g_Slot [ 5 ] = = CT_MockingboardC )
2016-03-21 23:48:02 +00:00
MB_SaveSnapshot ( yamlSaveHelper , 5 ) ;
2019-09-15 20:37:20 +01:00
if ( g_Slot [ 4 ] = = CT_Phasor )
2016-03-21 23:48:02 +00:00
Phasor_SaveSnapshot ( yamlSaveHelper , 4 ) ;
2019-09-15 20:37:20 +01:00
if ( g_Slot [ 6 ] = = CT_Disk2 )
sg_Disk2Card . SaveSnapshot ( yamlSaveHelper ) ;
2016-03-21 23:48:02 +00:00
HD_SaveSnapshot ( yamlSaveHelper ) ;
}
}
catch ( std : : string szMessage )
{
MessageBox ( g_hFrameWindow ,
szMessage . c_str ( ) ,
TEXT ( " Save State " ) ,
MB_ICONEXCLAMATION | MB_SETFOREGROUND ) ;
}
2006-02-25 20:50:29 +00:00
}
//-----------------------------------------------------------------------------
void Snapshot_Startup ( )
{
static bool bDone = false ;
if ( ! g_bSaveStateOnExit | | bDone )
return ;
Snapshot_LoadState ( ) ;
2018-07-31 18:06:53 +01:00
bDone = true ; // Prevents a g_bRestart from loading an old save-state
2006-02-25 20:50:29 +00:00
}
void Snapshot_Shutdown ( )
{
static bool bDone = false ;
2018-07-31 18:06:53 +01:00
_ASSERT ( ! bDone ) ;
_ASSERT ( ! g_bRestart ) ;
2006-02-25 20:50:29 +00:00
if ( ! g_bSaveStateOnExit | | bDone )
return ;
Snapshot_SaveState ( ) ;
2018-07-31 18:17:42 +01:00
bDone = true ; // Debug flag: this func should only be called once, and never on a g_bRestart
2006-02-25 20:50:29 +00:00
}