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 20:30:35 +00:00
2020-11-11 21:15:27 +00:00
# include "SaveState.h"
2016-03-21 23:48:02 +00:00
# include "YamlHelper.h"
2020-11-29 17:30:06 +00:00
# include "Interface.h"
2019-12-19 19:42:30 +00:00
# include "CardManager.h"
2014-08-13 20:30:35 +00:00
# include "CPU.h"
2019-12-20 09:15:24 +00:00
# include "Debug.h"
2014-08-13 20:30:35 +00:00
# include "Disk.h"
2013-12-31 22:40:10 +00:00
# include "Joystick.h"
2014-08-13 20:30:35 +00:00
# include "Keyboard.h"
2018-10-26 18:23:30 +00:00
# include "LanguageCard.h"
2014-08-13 20:30:35 +00: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 20:30:35 +00:00
# include "SerialComms.h"
# include "Speaker.h"
2016-03-21 23:48:02 +00:00
# include "Speech.h"
# 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 10:18:48 +00: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 20:34:34 +00:00
// v4: Extended: video (added 'Video Refresh Rate')
2019-11-18 15:08:59 +00:00
// v5: Extended: cpu (added 'Defer IRQ By 1 Opcode')
2020-06-10 19:56:00 +00:00
// v6: Added 'Unit Miscellaneous' for NoSlotClock(NSC)
# define UNIT_APPLE2_VER 6
2019-04-06 10:18:48 +00:00
2016-03-21 23:48:02 +00:00
# define UNIT_SLOTS_VER 1
2020-06-10 19:56:00 +00:00
# define UNIT_MISC_VER 1
2006-02-25 20:50:29 +00:00
//-----------------------------------------------------------------------------
2020-10-25 17:14:23 +00:00
static void Snapshot_SetPathname ( 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 ;
2020-10-25 17:14:23 +00:00
if ( ! g_strSaveStatePathname . empty ( ) & & * g_strSaveStatePathname . rbegin ( ) ! = ' \\ ' )
2013-12-29 22:09:41 +00:00
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 ( ' \\ ' ) ;
2020-10-25 17:14:23 +00:00
if ( nIdx > = 0 & & nIdx + 1 < ( int ) strPathname . length ( ) ) // path exists?
2013-12-29 22:09:41 +00:00
{
strFilename = & strPathname [ nIdx + 1 ] ;
2014-09-02 15:48:46 +00: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
}
2020-10-25 17:14:23 +00:00
void Snapshot_SetFilename ( const std : : string & filename , const std : : string & path /*=""*/ )
{
if ( path . empty ( ) )
return Snapshot_SetPathname ( filename ) ;
_ASSERT ( filename . find ( ' \\ ' ) = = std : : string : : npos ) ; // since we have a path, then filename mustn't contain a path too!
// Ensure path is suffixed with '\' before adding filename
std : : string pathname = path ;
if ( * pathname . rbegin ( ) ! = ' \\ ' )
pathname + = " \\ " ;
Snapshot_SetPathname ( pathname + filename ) ;
}
const std : : string & Snapshot_GetFilename ( void )
2006-02-25 20:50:29 +00:00
{
2019-09-07 08:02:39 +00:00
return g_strSaveStateFilename ;
2013-12-29 22:09:41 +00:00
}
2020-10-25 17:14:23 +00:00
const std : : string & Snapshot_GetPath ( void )
2013-12-29 22:09:41 +00:00
{
2019-09-07 08:02:39 +00:00
return g_strSaveStatePath ;
2006-02-25 20:50:29 +00:00
}
2020-10-25 17:14:23 +00:00
const std : : string & Snapshot_GetPathname ( void )
{
return g_strSaveStatePathname ;
}
// Called on successful insertion and on prompting to save/load a save-state
void Snapshot_GetDefaultFilenameAndPath ( std : : string & defaultFilename , std : : string & defaultPath )
{
// Attempt to get a default filename/path based on harddisk plugged-in or floppy disk inserted
// . Priority given to harddisk over floppy images
HD_GetFilenameAndPathForSaveState ( defaultFilename , defaultPath ) ;
if ( defaultFilename . empty ( ) )
GetCardMgr ( ) . GetDisk2CardMgr ( ) . GetFilenameAndPathForSaveState ( defaultFilename , defaultPath ) ;
}
// Called by Disk2InterfaceCard::InsertDisk() and HD_Insert() after a successful insertion
// Called by Disk2InterfaceCard::EjectDisk() and HD_Unplug()
// Called by RepeatInitialization() when Harddisk Controller card is disabled
void Snapshot_UpdatePath ( void )
{
std : : string defaultFilename ;
std : : string defaultPath ;
Snapshot_GetDefaultFilenameAndPath ( defaultFilename , defaultPath ) ;
if ( defaultPath . empty ( ) | | g_strSaveStatePath = = defaultPath )
return ;
if ( ! defaultFilename . empty ( ) )
defaultFilename + = " .aws.yaml " ;
Snapshot_SetFilename ( defaultFilename , defaultPath ) ;
}
2006-02-25 20:50:29 +00:00
//-----------------------------------------------------------------------------
2016-03-21 23:48:02 +00:00
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 ;
}
2020-06-10 19:56:00 +00:00
static std : : string GetSnapshotUnitMiscName ( void )
{
static const std : : string name ( " Miscellaneous " ) ;
return name ;
}
2016-03-21 23:48:02 +00:00
# define SS_YAML_KEY_MODEL "Model"
# define SS_YAML_VALUE_APPLE2 "Apple]["
# define SS_YAML_VALUE_APPLE2PLUS "Apple][+"
2020-04-02 19:17:32 +00:00
# define SS_YAML_VALUE_APPLE2JPLUS "Apple][ J-Plus"
2016-03-21 23:48:02 +00:00
# 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 09:35:18 +00:00
# define SS_YAML_VALUE_TK30002E "TK3000 //e"
2020-07-06 19:24:16 +00:00
# define SS_YAML_VALUE_BASE64A "Base 64A"
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 ;
2020-04-02 19:17:32 +00:00
else if ( type = = SS_YAML_VALUE_APPLE2JPLUS ) return A2TYPE_APPLE2JPLUS ;
2016-03-21 23:48:02 +00:00
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 09:35:18 +00:00
else if ( type = = SS_YAML_VALUE_TK30002E ) return A2TYPE_TK30002E ;
2020-07-06 19:24:16 +00:00
else if ( type = = SS_YAML_VALUE_BASE64A ) return A2TYPE_BASE64A ;
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 ;
2020-04-02 19:17:32 +00:00
case A2TYPE_APPLE2JPLUS : return SS_YAML_VALUE_APPLE2JPLUS ;
2016-03-21 23:48:02 +00:00
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 09:35:18 +00:00
case A2TYPE_TK30002E : return SS_YAML_VALUE_TK30002E ;
2020-07-06 19:24:16 +00:00
case A2TYPE_BASE64A : return SS_YAML_VALUE_BASE64A ;
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 18:23:30 +00: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
2019-11-18 15:08:59 +00:00
CpuLoadSnapshot ( yamlLoadHelper , version ) ; // NB. Overrides default main CPU type
2016-03-21 23:48:02 +00:00
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 ) ;
2020-12-28 16:25:29 +00:00
GetVideo ( ) . VideoLoadSnapshot ( yamlLoadHelper , version ) ;
2018-10-26 18:23:30 +00:00
MemLoadSnapshot ( yamlLoadHelper , version ) ;
2016-12-11 16:31:25 +00:00
// g_Apple2Type may've changed: so redraw frame (title, buttons, leds, etc)
2021-01-13 22:02:48 +00:00
GetVideo ( ) . VideoReinitialize ( true ) ; // g_CharsetType changed
2020-12-24 15:08:50 +00:00
GetFrame ( ) . 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 18:23:30 +00: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 ;
}
2019-12-19 19:42:30 +00:00
else if ( card = = CSuperSerialCard : : GetSnapshotCardName ( ) )
2016-03-21 23:48:02 +00:00
{
type = CT_SSC ;
2020-10-11 16:34:44 +00:00
GetCardMgr ( ) . Insert ( slot , type ) ;
bRes = dynamic_cast < CSuperSerialCard & > ( GetCardMgr ( ) . GetRef ( slot ) ) . LoadSnapshot ( yamlLoadHelper , slot , cardVersion ) ;
2016-03-21 23:48:02 +00:00
}
2019-12-19 19:42:30 +00:00
else if ( card = = CMouseInterface : : GetSnapshotCardName ( ) )
2016-03-21 23:48:02 +00:00
{
type = CT_MouseInterface ;
2020-10-11 16:34:44 +00:00
GetCardMgr ( ) . Insert ( slot , type ) ;
bRes = dynamic_cast < CMouseInterface & > ( GetCardMgr ( ) . GetRef ( slot ) ) . LoadSnapshot ( yamlLoadHelper , slot , cardVersion ) ;
2016-03-21 23:48:02 +00:00
}
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-12-19 19:42:30 +00:00
else if ( card = = Disk2InterfaceCard : : GetSnapshotCardName ( ) )
2016-03-21 23:48:02 +00:00
{
type = CT_Disk2 ;
2020-10-11 16:34:44 +00:00
GetCardMgr ( ) . Insert ( slot , type ) ;
bRes = dynamic_cast < Disk2InterfaceCard & > ( GetCardMgr ( ) . GetRef ( slot ) ) . LoadSnapshot ( yamlLoadHelper , slot , cardVersion ) ;
2016-03-21 23:48:02 +00:00
}
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 18:23:30 +00: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 18:23:30 +00: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 18:23:30 +00: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 ) ;
2020-06-10 19:56:00 +00:00
if ( unitVersion < 6 ) MemInsertNoSlotClock ( ) ; // NSC always inserted
else MemRemoveNoSlotClock ( ) ; // NSC only add if there's a misc unit
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
}
2020-06-10 19:56:00 +00:00
else if ( unit = = GetSnapshotUnitMiscName ( ) )
{
// NB. could extend for other misc devices - see how ParseSlots() calls GetMapNextSlotNumber()
NoSlotClockLoadSnapshot ( yamlLoadHelper ) ;
}
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
2020-06-03 19:26:06 +00:00
HCURSOR oldcursor = SetCursor ( LoadCursor ( 0 , IDC_WAIT ) ) ;
2019-02-24 10:29:34 +00:00
2021-01-19 20:37:43 +00:00
FrameBase & frame = GetFrame ( ) ;
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 09:17:29 +00: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 18:23:30 +00: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
2020-06-10 19:56:00 +00:00
MemReset ( ) ; // Also calls CpuInitialize()
2021-01-17 10:48:06 +00:00
GetPravets ( ) . Reset ( ) ;
2019-12-19 19:42:30 +00:00
2020-10-11 16:34:44 +00:00
if ( GetCardMgr ( ) . IsSSCInstalled ( ) )
2019-12-19 19:42:30 +00:00
{
2020-10-11 16:34:44 +00:00
GetCardMgr ( ) . GetSSC ( ) - > CommReset ( ) ;
2019-12-19 19:42:30 +00:00
}
else
{
2020-10-11 16:34:44 +00:00
_ASSERT ( GetCardMgr ( ) . QuerySlot ( SLOT2 ) = = CT_Empty ) ;
2019-12-19 19:42:30 +00:00
ConfigOld . m_Slot [ 2 ] = CT_Empty ;
}
2020-10-11 16:34:44 +00:00
if ( GetCardMgr ( ) . QuerySlot ( SLOT4 ) = = CT_MouseInterface )
GetCardMgr ( ) . Remove ( SLOT4 ) ; // Remove Mouse card from slot-4
2019-12-19 19:42:30 +00:00
2020-10-11 16:34:44 +00:00
if ( GetCardMgr ( ) . QuerySlot ( SLOT5 ) = = CT_Disk2 )
GetCardMgr ( ) . Remove ( SLOT5 ) ; // Remove Disk2 card from slot-5
2019-12-19 19:42:30 +00:00
2020-10-11 16:34:44 +00:00
GetCardMgr ( ) . GetDisk2CardMgr ( ) . Reset ( false ) ;
2019-12-19 19:42:30 +00:00
2017-12-03 21:05:05 +00:00
HD_Reset ( ) ;
2019-12-19 19:42:30 +00:00
HD_SetEnabled ( false ) ;
2016-03-21 23:48:02 +00:00
KeybReset ( ) ;
2020-12-28 16:25:29 +00:00
GetVideo ( ) . VideoResetState ( ) ;
GetVideo ( ) . 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
2016-03-21 23:48:02 +00:00
# ifdef USE_SPEECH_API
g_Speech . Reset ( ) ;
# endif
std : : string scalar ;
while ( yamlHelper . GetScalar ( scalar ) )
{
if ( scalar = = SS_YAML_KEY_UNIT )
ParseUnit ( ) ;
else
throw std : : string ( " Unknown top-level scalar: " + scalar ) ;
}
2019-12-24 13:58:20 +00:00
MB_SetCumulativeCycles ( ) ;
2021-01-19 20:37:43 +00:00
frame . SetLoadedSaveStateFlag ( true ) ;
2016-03-21 23:48:02 +00:00
// 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)
2020-12-20 15:32:51 +00:00
GetPropertySheet ( ) . ApplyNewConfig ( m_ConfigNew , ConfigOld ) ; // Mainly just saves (some) new state to Registry
2016-03-21 23:48:02 +00:00
MemInitializeROM ( ) ;
2020-03-25 23:05:02 +00:00
MemInitializeCustomROM ( ) ;
2016-03-21 23:48:02 +00:00
MemInitializeCustomF8ROM ( ) ;
MemInitializeIO ( ) ;
2020-06-08 21:06:17 +00:00
MemInitializeCardSlotAndExpansionRomFromSnapshot ( ) ;
2016-03-21 23:48:02 +00:00
MemUpdatePaging ( TRUE ) ;
2019-12-19 19:42:30 +00:00
2019-12-20 09:15:24 +00:00
DebugReset ( ) ;
2019-12-20 15:23:54 +00:00
if ( g_nAppMode = = MODE_DEBUG )
DebugDisplay ( TRUE ) ;
2016-03-21 23:48:02 +00:00
}
catch ( std : : string szMessage )
{
2021-01-19 20:37:43 +00:00
frame . FrameMessageBox (
2016-03-21 23:48:02 +00:00
szMessage . c_str ( ) ,
TEXT ( " Load State " ) ,
MB_ICONEXCLAMATION | MB_SETFOREGROUND ) ;
2019-02-24 10:29:34 +00:00
if ( restart )
2021-01-19 20:37:43 +00:00
frame . Restart ( ) ; // Power-cycle VM (undoing all the new state just loaded)
2016-03-21 23:48:02 +00:00
}
2020-06-03 19:26:06 +00:00
SetCursor ( oldcursor ) ;
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
{
2021-01-19 20:37:43 +00:00
GetFrame ( ) . FrameMessageBox (
2019-01-05 22:20:51 +00:00
" 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 ) ;
2020-12-28 16:25:29 +00:00
GetVideo ( ) . VideoSaveSnapshot ( yamlSaveHelper ) ;
2016-03-21 23:48:02 +00:00
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 ) ;
2020-10-11 16:34:44 +00:00
if ( GetCardMgr ( ) . QuerySlot ( SLOT0 ) ! = CT_Empty & & IsApple2PlusOrClone ( GetApple2Type ( ) ) )
2018-10-26 18:23:30 +00:00
GetLanguageCard ( ) - > SaveSnapshot ( yamlSaveHelper ) ; // Language Card or Saturn 128K
2020-10-11 16:34:44 +00:00
if ( GetCardMgr ( ) . QuerySlot ( SLOT1 ) = = CT_GenericPrinter )
2019-09-15 19:37:20 +00:00
Printer_SaveSnapshot ( yamlSaveHelper ) ;
2016-03-21 23:48:02 +00:00
2020-10-11 16:34:44 +00:00
if ( GetCardMgr ( ) . QuerySlot ( SLOT2 ) = = CT_SSC )
dynamic_cast < CSuperSerialCard & > ( GetCardMgr ( ) . GetRef ( SLOT2 ) ) . SaveSnapshot ( yamlSaveHelper ) ;
2019-09-15 19:37:20 +00:00
2020-10-11 16:34:44 +00:00
// if (GetCardMgr().QuerySlot(SLOT3) == CT_Uthernet)
2019-09-15 19:37:20 +00:00
// sg_Uthernet.SaveSnapshot(yamlSaveHelper);
2016-03-21 23:48:02 +00:00
2020-10-11 16:34:44 +00:00
if ( GetCardMgr ( ) . QuerySlot ( SLOT4 ) = = CT_MouseInterface )
dynamic_cast < CMouseInterface & > ( GetCardMgr ( ) . GetRef ( SLOT4 ) ) . SaveSnapshot ( yamlSaveHelper ) ;
2019-12-19 19:42:30 +00:00
2020-10-11 16:34:44 +00:00
if ( GetCardMgr ( ) . QuerySlot ( SLOT4 ) = = CT_Z80 )
2019-12-19 19:42:30 +00:00
Z80_SaveSnapshot ( yamlSaveHelper , SLOT4 ) ;
2016-03-21 23:48:02 +00:00
2020-10-11 16:34:44 +00:00
if ( GetCardMgr ( ) . QuerySlot ( SLOT5 ) = = CT_Z80 )
2019-12-19 19:42:30 +00:00
Z80_SaveSnapshot ( yamlSaveHelper , SLOT5 ) ;
2016-03-21 23:48:02 +00:00
2020-10-11 16:34:44 +00:00
if ( GetCardMgr ( ) . QuerySlot ( SLOT4 ) = = CT_MockingboardC )
2019-12-19 19:42:30 +00:00
MB_SaveSnapshot ( yamlSaveHelper , SLOT4 ) ;
2016-03-21 23:48:02 +00:00
2020-10-11 16:34:44 +00:00
if ( GetCardMgr ( ) . QuerySlot ( SLOT5 ) = = CT_MockingboardC )
2019-12-19 19:42:30 +00:00
MB_SaveSnapshot ( yamlSaveHelper , SLOT5 ) ;
2016-03-21 23:48:02 +00:00
2020-10-11 16:34:44 +00:00
if ( GetCardMgr ( ) . QuerySlot ( SLOT4 ) = = CT_Phasor )
2019-12-19 19:42:30 +00:00
Phasor_SaveSnapshot ( yamlSaveHelper , SLOT4 ) ;
2016-03-21 23:48:02 +00:00
2020-10-11 16:34:44 +00:00
if ( GetCardMgr ( ) . QuerySlot ( SLOT5 ) = = CT_Disk2 )
dynamic_cast < Disk2InterfaceCard & > ( GetCardMgr ( ) . GetRef ( SLOT5 ) ) . SaveSnapshot ( yamlSaveHelper ) ;
2016-03-21 23:48:02 +00:00
2020-10-11 16:34:44 +00:00
if ( GetCardMgr ( ) . QuerySlot ( SLOT6 ) = = CT_Disk2 )
dynamic_cast < Disk2InterfaceCard & > ( GetCardMgr ( ) . GetRef ( SLOT6 ) ) . SaveSnapshot ( yamlSaveHelper ) ;
2016-03-21 23:48:02 +00:00
2020-10-11 16:34:44 +00:00
if ( GetCardMgr ( ) . QuerySlot ( SLOT7 ) = = CT_GenericHDD )
2019-12-19 19:42:30 +00:00
HD_SaveSnapshot ( yamlSaveHelper ) ;
2016-03-21 23:48:02 +00:00
}
2020-06-10 19:56:00 +00:00
// Miscellaneous
if ( MemHasNoSlotClock ( ) )
{
yamlSaveHelper . UnitHdr ( GetSnapshotUnitMiscName ( ) , UNIT_MISC_VER ) ;
YamlSaveHelper : : Label state ( yamlSaveHelper , " %s: \n " , SS_YAML_KEY_STATE ) ;
NoSlotClockSaveSnapshot ( yamlSaveHelper ) ;
}
2016-03-21 23:48:02 +00:00
}
catch ( std : : string szMessage )
{
2021-01-19 20:37:43 +00:00
GetFrame ( ) . FrameMessageBox (
2016-03-21 23:48:02 +00:00
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 17:06:53 +00: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 17:06:53 +00:00
_ASSERT ( ! bDone ) ;
_ASSERT ( ! g_bRestart ) ;
2006-02-25 20:50:29 +00:00
if ( ! g_bSaveStateOnExit | | bDone )
return ;
Snapshot_SaveState ( ) ;
2018-07-31 17:17:42 +00: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
}