Skip to content

Commit 15df0c7

Browse files
committed
[mgb] add state info loading support
1 parent bfca717 commit 15df0c7

2 files changed

Lines changed: 144 additions & 25 deletions

File tree

src/mgb/mgb.c

Lines changed: 117 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
}

src/mgb/mgb.h

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,31 @@ enum CallbackType
2121
CallbackType_PATCH_ROM,
2222
};
2323

24+
// savestates compressed with defalte/inflate
25+
// lz4 was considered, but it seemed silly to have 2 compression
26+
// algorithims included in my code, although lz4 is arguably
27+
struct StateMeta
28+
{
29+
uint32_t magic;
30+
char platform_string[64]; // todo:
31+
uint32_t state_size;
32+
// if 0, then the state is uncompressed!
33+
uint32_t state_compressed_size;
34+
uint32_t padding;
35+
uint64_t timestamp;
36+
uint64_t playtime;
37+
uint8_t reserved[160];
38+
};
39+
40+
enum { STATE_MAGIC = 0x536A0535 };
41+
42+
struct StateInfo
43+
{
44+
struct StateMeta meta;
45+
uint8_t* png;
46+
size_t png_size;
47+
};
48+
2449
#if 0
2550
#include <stdio.h>
2651
#define mgb_log(...) fprintf(stdout, __VA_ARGS__)
@@ -82,13 +107,8 @@ bool mgb_patch_rom_data(const char* path, const uint8_t* data, size_t size);
82107
bool mgb_has_rom(void);
83108
const char* mgb_rom_path(void);
84109

85-
// bool mgb_rewind_init(size_t frames);
86-
// void mgb_rewind_close(void);
87-
88-
// save states and stores pixel data for that frame
89-
// bool mgb_rewind_push_frame(const void* pixels, size_t size);
90-
// loads state and loads pixel data for that frame
91-
// bool mgb_rewind_pop_frame(void* pixels, size_t size);
110+
struct StateInfo* mgb_load_state_info_file(const char* path, bool load_png);
111+
void mgb_free_state_info(struct StateInfo* info);
92112

93113
#ifdef __cplusplus
94114
}

0 commit comments

Comments
 (0)