@@ -33,24 +33,6 @@ struct LoadRomConfig
3333 bool own_fd ;
3434};
3535
36- // savestates compressed with defalte/inflate
37- // lz4 was considered, but it seemed silly to have 2 compression
38- // algorithims included in my code, although lz4 is arguably
39- struct StateMeta
40- {
41- uint32_t magic ;
42- char platform_string [64 ]; // todo:
43- uint32_t state_size ;
44- // if 0, then the state is uncompressed!
45- uint32_t state_compressed_size ;
46- uint32_t padding ;
47- uint64_t timestamp ;
48- uint64_t playtime ;
49- uint8_t reserved [160 ];
50- };
51-
52- enum { STATE_MAGIC = 0x536A0535 };
53-
5436// struct RewindState
5537// {
5638// struct SMS_State state;
@@ -983,3 +965,120 @@ void mgb_set_on_convert_pixels_to_png_format(convert_pixels_to_png_format_func c
983965{
984966 mgb .on_png_convert_cb = cb ;
985967}
968+
969+ struct StateInfo * mgb_load_state_info_file (const char * path , bool load_png )
970+ {
971+ IFile_t * file = NULL ;
972+ struct StateInfo * info = NULL ;
973+ struct StateMeta meta = {0 };
974+ struct SafeString ss = {0 };
975+
976+ if (!mgb_has_rom ())
977+ {
978+ mgb_log_err ("[MGB] tried to load state without rom\n" );
979+ goto fail ;
980+ }
981+
982+ if (path )
983+ {
984+ strncpy (ss .str , path , sizeof (ss .str ) - 1 );
985+ }
986+ else
987+ {
988+ ss = util_create_state_path (mgb_get_state_folder (), mgb_rom_path ());
989+ }
990+
991+ if (!ss_valid (& ss ))
992+ {
993+ goto fail ;
994+ }
995+
996+ mgb_log ("[MGB] trying to load state from: %s\n" , ss .str );
997+
998+ file = icfile_open (ss .str , IFileMode_READ , 0 );
999+ if (!file )
1000+ {
1001+ mgb_log_err ("[MGB] failed to open file: %s\n" , ss .str );
1002+ goto fail ;
1003+ }
1004+
1005+ // check for png data by reading header
1006+ uint8_t png_header [PNG_HEADER_SIZE ];
1007+ if (!ifile_read (file , png_header , sizeof (png_header )))
1008+ {
1009+ mgb_log_err ("[MGB] failed to read file: %s\n" , ss .str );
1010+ goto fail ;
1011+ }
1012+
1013+ const uint32_t png_size = png_get_absolute_size (png_header , sizeof (png_header ));
1014+
1015+ // skip over png data
1016+ if (!ifile_seek (file , png_size , SEEK_SET ))
1017+ {
1018+ mgb_log_err ("[MGB] failed to read file: %s\n" , ss .str );
1019+ goto fail ;
1020+ }
1021+
1022+ // read meta data
1023+ if (!ifile_read (file , & meta , sizeof (meta )))
1024+ {
1025+ mgb_log_err ("[MGB] failed to read file: %s\n" , ss .str );
1026+ goto fail ;
1027+ }
1028+
1029+ // todo: check values here...
1030+ // todo: compare state size with sms
1031+ if (meta .magic != STATE_MAGIC )
1032+ {
1033+ mgb_log ("bad state magic...\n" );
1034+ goto fail ;
1035+ }
1036+
1037+ info = calloc (1 , sizeof (* info ));
1038+ memcpy (& info -> meta , & meta , sizeof (meta ));
1039+
1040+ if (load_png && png_size )
1041+ {
1042+ info -> png = malloc (png_size );
1043+ info -> png_size = png_size ;
1044+
1045+ if (!ifile_seek (file , 0 , SEEK_SET ))
1046+ {
1047+ mgb_log_err ("[MGB] failed to read file: %s\n" , ss .str );
1048+ goto fail ;
1049+ }
1050+
1051+ if (!ifile_read (file , info -> png , info -> png_size ))
1052+ {
1053+ mgb_log_err ("[MGB] failed to read file: %s\n" , ss .str );
1054+ goto fail ;
1055+ }
1056+ }
1057+
1058+ ifile_close (file );
1059+
1060+ return info ;
1061+
1062+ fail :
1063+ if (file )
1064+ {
1065+ ifile_close (file );
1066+ }
1067+
1068+ mgb_free_state_info (info );
1069+
1070+ mgb_log_err ("[MGB] failed to load state info from: %s\n" , ss .str );
1071+ return NULL ;
1072+ }
1073+
1074+ void mgb_free_state_info (struct StateInfo * info )
1075+ {
1076+ if (info ) {
1077+ if (info -> png ) {
1078+ free (info -> png );
1079+ }
1080+
1081+ memset (info , 0 , sizeof (* info ));
1082+ free (info );
1083+ }
1084+ }
0 commit comments