forked from LIJI32/SameBoy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
save_state.h
56 lines (48 loc) · 2.53 KB
/
save_state.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#pragma once
/* Macros to make the GB_gameboy_t struct more future compatible when state saving */
#include <stddef.h>
#define GB_PADDING(type, old_usage) type old_usage##__do_not_use
#ifdef __cplusplus
/* For bsnes integration. C++ code does not need section information, and throws a fit over certain types such
as anonymous enums inside unions */
#if __clang__
#define GB_SECTION(name, ...) __attribute__ ((aligned (8))) __VA_ARGS__
#else
// GCC's handling of attributes is so awfully bad, that it is alone a good enough reason to never use that compiler
#define GB_SECTION(name, ...) _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wpedantic\"") alignas(8) char _align_##name[0]; __VA_ARGS__ _Pragma("GCC diagnostic pop")
#endif
#else
#define GB_SECTION(name, ...) union __attribute__ ((aligned (8))) {uint8_t name##_section_start; struct {__VA_ARGS__};}; uint8_t name##_section_end[0];
#ifdef GB_INTERNAL
#define GB_SECTION_OFFSET(name) (offsetof(GB_gameboy_t, name##_section_start))
#define GB_SECTION_SIZE(name) (offsetof(GB_gameboy_t, name##_section_end) - offsetof(GB_gameboy_t, name##_section_start))
/* This roundabout way to get the section offset is because GCC 9 is a bad compiler and will false-positively complain
about memset buffer overflows otherwise */
#define GB_GET_SECTION(gb, name) (void *)((uint8_t *)(gb) + GB_SECTION_OFFSET(name))
#endif
#endif
#if __clang_major__ >= 8 || __GNUC__ >= 13
#define GB_ENUM(type, ...) enum : type __VA_ARGS__
#else
#define GB_ENUM(type, ...) __typeof__((type)((enum __VA_ARGS__)0))
#endif
/* Public calls related to save states */
int GB_save_state(GB_gameboy_t *gb, const char *path);
size_t GB_get_save_state_size(GB_gameboy_t *gb);
/* Assumes buffer is big enough to contain the save state. Use with GB_get_save_state_size(). */
void GB_save_state_to_buffer(GB_gameboy_t *gb, uint8_t *buffer);
int GB_load_state(GB_gameboy_t *gb, const char *path);
int GB_load_state_from_buffer(GB_gameboy_t *gb, const uint8_t *buffer, size_t length);
bool GB_is_save_state(const char *path);
int GB_get_state_model(const char *path, GB_model_t *model);
int GB_get_state_model_from_buffer(const uint8_t *buffer, size_t length, GB_model_t *model);
#ifdef GB_INTERNAL
static inline uint32_t GB_state_magic(void)
{
if (sizeof(bool) == 1) return 'SAME';
return 'S4ME';
}
/* For internal in-memory save states (rewind, debugger) that do not need BESS */
internal size_t GB_get_save_state_size_no_bess(GB_gameboy_t *gb);
internal void GB_save_state_to_buffer_no_bess(GB_gameboy_t *gb, uint8_t *buffer);
#endif