2023-11-11 00:39:08 +02:00
/*
* CLoadFile . cpp , part of VCMI engine
*
* Authors : listed in file AUTHORS in main folder
*
* License : GNU General Public License v2 .0 or later
* Full text of license available in license . txt file , in main folder
*
*/
# include "StdInc.h"
# include "CLoadFile.h"
VCMI_LIB_NAMESPACE_BEGIN
2025-04-16 17:05:52 +03:00
template < typename From , typename To >
struct static_caster
{
To operator ( ) ( From p ) { return static_cast < To > ( p ) ; }
} ;
2025-04-12 21:25:23 +03:00
CLoadFile : : CLoadFile ( const boost : : filesystem : : path & fname , IGameCallback * cb )
2023-11-11 00:39:08 +02:00
: serializer ( this )
2025-04-12 21:25:23 +03:00
, fName ( fname . string ( ) )
, sfile ( fname . c_str ( ) , std : : ios : : in | std : : ios : : binary )
2023-11-11 00:39:08 +02:00
{
2025-04-12 21:25:23 +03:00
serializer . cb = cb ;
2024-07-27 16:51:23 +00:00
serializer . loadingGamestate = true ;
2024-03-28 03:03:44 +01:00
assert ( ! serializer . reverseEndianness ) ;
2023-11-11 00:39:08 +02:00
2025-04-12 21:25:23 +03:00
fName = fname . string ( ) ;
sfile . exceptions ( std : : ifstream : : failbit | std : : ifstream : : badbit ) ; //we throw a lot anyway
2023-11-11 00:39:08 +02:00
2025-04-12 21:25:23 +03:00
if ( ! sfile )
throw std : : runtime_error ( " Error: cannot open file ' " + fName + " ' for reading! " ) ;
2023-11-11 00:39:08 +02:00
2025-04-12 21:25:23 +03:00
//we can read
2025-04-16 17:05:52 +03:00
char magic [ 4 ] ;
sfile . read ( magic , 4 ) ;
if ( std : : memcmp ( magic , " VCMI " , 4 ) ! = 0 )
2025-04-12 21:25:23 +03:00
throw std : : runtime_error ( " Error: ' " + fName + " ' is not a VCMI file! " ) ;
2023-11-11 00:39:08 +02:00
2025-04-16 17:05:52 +03:00
sfile . read ( reinterpret_cast < char * > ( & serializer . version ) , sizeof ( serializer . version ) ) ;
2025-04-12 21:25:23 +03:00
if ( serializer . version < ESerializationVersion : : MINIMAL )
throw std : : runtime_error ( " Error: too old file format detected in ' " + fName + " '! " ) ;
2023-11-11 00:39:08 +02:00
2025-04-12 21:25:23 +03:00
if ( serializer . version > ESerializationVersion : : CURRENT )
{
logGlobal - > warn ( " Warning format version mismatch: found %d when current is %d! (file %s) \n " , vstd : : to_underlying ( serializer . version ) , vstd : : to_underlying ( ESerializationVersion : : CURRENT ) , fName ) ;
2023-11-11 00:39:08 +02:00
2025-04-12 21:25:23 +03:00
auto * versionptr = reinterpret_cast < char * > ( & serializer . version ) ;
std : : reverse ( versionptr , versionptr + 4 ) ;
logGlobal - > warn ( " Version number reversed is %x, checking... " , vstd : : to_underlying ( serializer . version ) ) ;
2023-11-11 00:39:08 +02:00
2025-04-12 21:25:23 +03:00
if ( serializer . version = = ESerializationVersion : : CURRENT )
{
logGlobal - > warn ( " %s seems to have different endianness! Entering reversing mode. " , fname . string ( ) ) ;
serializer . reverseEndianness = true ;
2023-11-11 00:39:08 +02:00
}
2025-04-12 21:25:23 +03:00
else
throw std : : runtime_error ( " Error: too new file format detected in ' " + fName + " '! " ) ;
2023-11-11 00:39:08 +02:00
}
2025-04-12 21:25:23 +03:00
std : : string loaded = SAVEGAME_MAGIC ;
sfile . read ( loaded . data ( ) , SAVEGAME_MAGIC . length ( ) ) ;
if ( loaded ! = SAVEGAME_MAGIC )
throw std : : runtime_error ( " Magic bytes doesn't match! " ) ;
2023-11-11 00:39:08 +02:00
}
2025-04-12 21:25:23 +03:00
int CLoadFile : : read ( std : : byte * data , unsigned size )
2023-11-11 00:39:08 +02:00
{
2025-04-12 21:25:23 +03:00
sfile . read ( reinterpret_cast < char * > ( data ) , size ) ;
return size ;
2023-11-11 00:39:08 +02:00
}
VCMI_LIB_NAMESPACE_END