1 #include "gb.h"
2 #include <stdio.h>
3 #include <errno.h>
4 #include <assert.h>
5 
6 #ifdef GB_BIG_ENDIAN
7 #define BESS_NAME "SameBoy v" GB_VERSION " (Big Endian)"
8 #else
9 #define BESS_NAME "SameBoy v" GB_VERSION
10 #endif
11 
12 _Static_assert((GB_SECTION_OFFSET(core_state) & 7) == 0, "Section core_state is not aligned");
13 _Static_assert((GB_SECTION_OFFSET(dma) & 7) == 0, "Section dma is not aligned");
14 _Static_assert((GB_SECTION_OFFSET(mbc) & 7) == 0, "Section mbc is not aligned");
15 _Static_assert((GB_SECTION_OFFSET(hram) & 7) == 0, "Section hram is not aligned");
16 _Static_assert((GB_SECTION_OFFSET(timing) & 7) == 0, "Section timing is not aligned");
17 _Static_assert((GB_SECTION_OFFSET(apu) & 7) == 0, "Section apu is not aligned");
18 _Static_assert((GB_SECTION_OFFSET(rtc) & 7) == 0, "Section rtc is not aligned");
19 _Static_assert((GB_SECTION_OFFSET(video) & 7) == 0, "Section video is not aligned");
20 
21 typedef struct __attribute__((packed)) {
22     uint32_t magic;
23     uint32_t size;
24 } BESS_block_t;
25 
26 typedef struct __attribute__((packed)) {
27     uint32_t size;
28     uint32_t offset;
29 } BESS_buffer_t;
30 
31 typedef struct __attribute__((packed)) {
32     uint32_t start_offset;
33     uint32_t magic;
34 } BESS_footer_t;
35 
36 typedef struct __attribute__((packed)) {
37     BESS_block_t header;
38     uint16_t  major;
39     uint16_t  minor;
40     union {
41         struct {
42             char family;
43             char model;
44             char revision;
45             char padding;
46         };
47         uint32_t full_model;
48     };
49 
50     uint16_t pc;
51     uint16_t af;
52     uint16_t bc;
53     uint16_t de;
54     uint16_t hl;
55     uint16_t sp;
56 
57     uint8_t ime;
58     uint8_t ie;
59     uint8_t execution_mode; // 0 = running; 1 = halted; 2 = stopped
60     uint8_t _padding;
61 
62     uint8_t io_registers[0x80];
63 
64     BESS_buffer_t ram;
65     BESS_buffer_t vram;
66     BESS_buffer_t mbc_ram;
67     BESS_buffer_t oam;
68     BESS_buffer_t hram;
69     BESS_buffer_t background_palettes;
70     BESS_buffer_t sprite_palettes;
71 } BESS_CORE_t;
72 
73 typedef struct __attribute__((packed)) {
74     BESS_block_t header;
75     uint8_t extra_oam[96];
76 } BESS_XOAM_t;
77 
78 typedef struct __attribute__((packed)) {
79     BESS_block_t header;
80     BESS_buffer_t border_tiles;
81     BESS_buffer_t border_tilemap;
82     BESS_buffer_t border_palettes;
83 
84     BESS_buffer_t active_palettes;
85     BESS_buffer_t ram_palettes;
86     BESS_buffer_t attribute_map;
87     BESS_buffer_t attribute_files;
88 
89     uint8_t multiplayer_state;
90 } BESS_SGB_t;
91 
92 typedef struct __attribute__((packed)){
93     BESS_block_t header;
94     char title[0x10];
95     uint8_t checksum[2];
96 } BESS_INFO_t;
97 
98 /* Same RTC format as used by VBA, BGB and SameBoy in battery saves*/
99 typedef struct __attribute__((packed)){
100     BESS_block_t header;
101     struct {
102         uint8_t seconds;
103         uint8_t padding1[3];
104         uint8_t minutes;
105         uint8_t padding2[3];
106         uint8_t hours;
107         uint8_t padding3[3];
108         uint8_t days;
109         uint8_t padding4[3];
110         uint8_t high;
111         uint8_t padding5[3];
112     } real, latched;
113     uint64_t last_rtc_second;
114 } BESS_RTC_t;
115 
116 /* Same HuC3 RTC format as used by SameBoy and BGB in battery saves */
117 typedef struct __attribute__((packed)){
118     BESS_block_t header;
119     GB_huc3_rtc_time_t data;
120 } BESS_HUC3_t;
121 
122 typedef struct __attribute__((packed)){
123     BESS_block_t header;
124     uint64_t last_rtc_second;
125     uint8_t real_rtc_data[4];
126     uint8_t latched_rtc_data[4];
127     uint8_t mr4;
128 } BESS_TPP1_t;
129 
130 typedef struct  __attribute__((packed)) {
131     uint16_t address;
132     uint8_t value;
133 } BESS_MBC_pair_t;
134 
135 typedef struct virtual_file_s virtual_file_t;
136 struct virtual_file_s
137 {
138     size_t (*read)(virtual_file_t *file, void *dest, size_t length);
139     size_t (*write)(virtual_file_t *file, const void *dest, size_t length);
140     void (*seek)(virtual_file_t *file, ssize_t ammount, int origin);
141     size_t (*tell)(virtual_file_t *file);
142     union {
143         FILE *file;
144         struct {
145             uint8_t *buffer;
146             size_t position;
147             size_t size;
148         };
149     };
150 };
151 
file_read(virtual_file_t * file,void * dest,size_t length)152 static size_t file_read(virtual_file_t *file, void *dest, size_t length)
153 {
154     return fread(dest, 1, length, file->file);
155 }
156 
file_seek(virtual_file_t * file,ssize_t ammount,int origin)157 static void file_seek(virtual_file_t *file, ssize_t ammount, int origin)
158 {
159     fseek(file->file, ammount, origin);
160 }
161 
file_write(virtual_file_t * file,const void * src,size_t length)162 static size_t file_write(virtual_file_t *file, const void *src, size_t length)
163 {
164     return fwrite(src, 1, length, file->file);
165 }
166 
file_tell(virtual_file_t * file)167 static size_t file_tell(virtual_file_t *file)
168 {
169     return ftell(file->file);
170 }
171 
buffer_read(virtual_file_t * file,void * dest,size_t length)172 static size_t buffer_read(virtual_file_t *file, void *dest, size_t length)
173 {
174     if (length & 0x80000000) {
175         return 0;
176     }
177     errno = 0;
178     if (length > file->size - file->position) {
179         errno = EIO;
180         length = file->size - file->position;
181     }
182 
183     memcpy(dest, file->buffer + file->position, length);
184     file->position += length;
185 
186     return length;
187 }
188 
buffer_seek(virtual_file_t * file,ssize_t ammount,int origin)189 static void buffer_seek(virtual_file_t *file, ssize_t ammount, int origin)
190 {
191     switch (origin) {
192         case SEEK_SET:
193             file->position = ammount;
194             break;
195         case SEEK_CUR:
196             file->position += ammount;
197             break;
198         case SEEK_END:
199             file->position = file->size + ammount;
200             break;
201         default:
202             break;
203     }
204 
205     if (file->position > file->size) {
206         file->position = file->size;
207     }
208 }
209 
buffer_write(virtual_file_t * file,const void * src,size_t size)210 static size_t buffer_write(virtual_file_t *file, const void *src, size_t size)
211 {
212     memcpy(file->buffer + file->position, src, size);
213     file->position += size;
214     return size;
215 }
216 
buffer_tell(virtual_file_t * file)217 static size_t buffer_tell(virtual_file_t *file)
218 {
219     return file->position;
220 }
221 
bess_size_for_cartridge(const GB_cartridge_t * cart)222 static size_t bess_size_for_cartridge(const GB_cartridge_t *cart)
223 {
224     switch (cart->mbc_type) {
225         default:
226         case GB_NO_MBC: return 0;
227         case GB_MBC1:
228             return sizeof(BESS_block_t) + 4 * sizeof(BESS_MBC_pair_t);
229         case GB_MBC2:
230             return sizeof(BESS_block_t) + 2 * sizeof(BESS_MBC_pair_t);
231         case GB_MBC3:
232             return sizeof(BESS_block_t) + 3 * sizeof(BESS_MBC_pair_t) + (cart->has_rtc? sizeof(BESS_RTC_t) : 0);
233         case GB_MBC5:
234             return sizeof(BESS_block_t) + 4 * sizeof(BESS_MBC_pair_t);
235         case GB_HUC1:
236             return sizeof(BESS_block_t) + 4 * sizeof(BESS_MBC_pair_t);
237         case GB_HUC3:
238             return sizeof(BESS_block_t) + 3 * sizeof(BESS_MBC_pair_t) + sizeof(BESS_HUC3_t);
239         case GB_TPP1:
240             return sizeof(BESS_block_t) + 4 * sizeof(BESS_MBC_pair_t) + sizeof(BESS_TPP1_t);
241     }
242 }
243 
GB_get_save_state_size_no_bess(GB_gameboy_t * gb)244 size_t GB_get_save_state_size_no_bess(GB_gameboy_t *gb)
245 {
246     return GB_SECTION_SIZE(header)
247     + GB_SECTION_SIZE(core_state) + sizeof(uint32_t)
248     + GB_SECTION_SIZE(dma       ) + sizeof(uint32_t)
249     + GB_SECTION_SIZE(mbc       ) + sizeof(uint32_t)
250     + GB_SECTION_SIZE(hram      ) + sizeof(uint32_t)
251     + GB_SECTION_SIZE(timing    ) + sizeof(uint32_t)
252     + GB_SECTION_SIZE(apu       ) + sizeof(uint32_t)
253     + GB_SECTION_SIZE(rtc       ) + sizeof(uint32_t)
254     + GB_SECTION_SIZE(video     ) + sizeof(uint32_t)
255     + (GB_is_hle_sgb(gb)? sizeof(*gb->sgb) + sizeof(uint32_t) : 0)
256     + gb->mbc_ram_size
257     + gb->ram_size
258     + gb->vram_size;
259 }
260 
GB_get_save_state_size(GB_gameboy_t * gb)261 size_t GB_get_save_state_size(GB_gameboy_t *gb)
262 {
263     return GB_get_save_state_size_no_bess(gb) +
264     // BESS
265     + sizeof(BESS_block_t) // NAME
266     + sizeof(BESS_NAME) - 1
267     + sizeof(BESS_INFO_t) // INFO
268     + sizeof(BESS_CORE_t)
269     + sizeof(BESS_XOAM_t)
270     + (gb->sgb? sizeof(BESS_SGB_t) : 0)
271     + bess_size_for_cartridge(gb->cartridge_type) // MBC & RTC/HUC3/TPP1 block
272     + sizeof(BESS_block_t) // END block
273     + sizeof(BESS_footer_t);
274 }
275 
verify_and_update_state_compatibility(GB_gameboy_t * gb,GB_gameboy_t * save,bool * attempt_bess)276 static bool verify_and_update_state_compatibility(GB_gameboy_t *gb, GB_gameboy_t *save, bool *attempt_bess)
277 {
278     *attempt_bess = false;
279     if (save->ram_size == 0 && (&save->ram_size)[-1] == gb->ram_size) {
280         /* This is a save state with a bad printer struct from a 32-bit OS */
281         memmove(save->extra_oam + 4, save->extra_oam, (uintptr_t)&save->ram_size - (uintptr_t)&save->extra_oam);
282     }
283     if (save->ram_size == 0) {
284         /* Save doesn't have ram size specified, it's a pre 0.12 save state with potentially
285          incorrect RAM amount if it's a CGB instance */
286         if (GB_is_cgb(save)) {
287             save->ram_size = 0x2000 * 8; // Incorrect RAM size
288         }
289         else {
290             save->ram_size = gb->ram_size;
291         }
292     }
293 
294     if (save->model & GB_MODEL_PAL_BIT_OLD) {
295         save->model &= ~GB_MODEL_PAL_BIT_OLD;
296         save->model |= GB_MODEL_PAL_BIT;
297     }
298 
299     if (save->model & GB_MODEL_NO_SFC_BIT_OLD) {
300         save->model &= ~GB_MODEL_NO_SFC_BIT_OLD;
301         save->model |= GB_MODEL_NO_SFC_BIT;
302     }
303 
304     if (gb->version != save->version) {
305         GB_log(gb, "The save state is for a different version of SameBoy.\n");
306         *attempt_bess = true;
307         return false;
308     }
309 
310     if (GB_is_cgb(gb) != GB_is_cgb(save) || GB_is_hle_sgb(gb) != GB_is_hle_sgb(save)) {
311         GB_log(gb, "The save state is for a different Game Boy model. Try changing the emulated model.\n");
312         return false;
313     }
314 
315     if (gb->mbc_ram_size < save->mbc_ram_size) {
316         GB_log(gb, "The save state has non-matching MBC RAM size.\n");
317         return false;
318     }
319 
320     if (gb->vram_size != save->vram_size) {
321         GB_log(gb, "The save state has non-matching VRAM size. Try changing the emulated model.\n");
322         return false;
323     }
324 
325     if (GB_is_hle_sgb(gb) != GB_is_hle_sgb(save)) {
326         GB_log(gb, "The save state is %sfor a Super Game Boy. Try changing the emulated model.\n", GB_is_hle_sgb(save)? "" : "not ");
327         return false;
328     }
329 
330     if (gb->ram_size != save->ram_size) {
331         if (gb->ram_size == 0x1000 * 8 && save->ram_size == 0x2000 * 8) {
332             /* A bug in versions prior to 0.12 made CGB instances allocate twice the ammount of RAM.
333                Ignore this issue to retain compatibility with older, 0.11, save states. */
334         }
335         else {
336             GB_log(gb, "The save state has non-matching RAM size. Try changing the emulated model.\n");
337             return false;
338         }
339     }
340 
341     switch (save->model) {
342         case GB_MODEL_DMG_B: return true;
343         case GB_MODEL_SGB_NTSC: return true;
344         case GB_MODEL_SGB_PAL: return true;
345         case GB_MODEL_SGB_NTSC_NO_SFC: return true;
346         case GB_MODEL_SGB_PAL_NO_SFC: return true;
347         case GB_MODEL_SGB2: return true;
348         case GB_MODEL_SGB2_NO_SFC: return true;
349         case GB_MODEL_CGB_C: return true;
350         case GB_MODEL_CGB_E: return true;
351         case GB_MODEL_AGB: return true;
352     }
353     if ((gb->model & GB_MODEL_FAMILY_MASK) == (save->model & GB_MODEL_FAMILY_MASK)) {
354         save->model = gb->model;
355         return true;
356     }
357     GB_log(gb, "This save state is for an unknown Game Boy model\n");
358     return false;
359 }
360 
sanitize_state(GB_gameboy_t * gb)361 static void sanitize_state(GB_gameboy_t *gb)
362 {
363     for (unsigned i = 0; i < 32; i++) {
364         GB_palette_changed(gb, false, i * 2);
365         GB_palette_changed(gb, true, i * 2);
366     }
367 
368     gb->bg_fifo.read_end &= 0xF;
369     gb->bg_fifo.write_end &= 0xF;
370     gb->oam_fifo.read_end &= 0xF;
371     gb->oam_fifo.write_end &= 0xF;
372     gb->last_tile_index_address &= 0x1FFF;
373     gb->window_tile_x &= 0x1F;
374 
375     /* These are kind of DOS-ish if too large */
376     if (abs(gb->display_cycles) > 0x8000) {
377         gb->display_cycles = 0;
378     }
379 
380     if (abs(gb->div_cycles) > 0x8000) {
381         gb->div_cycles = 0;
382     }
383 
384     if (!GB_is_cgb(gb)) {
385         gb->cgb_mode = false;
386     }
387 
388     if (gb->ram_size == 0x8000) {
389         gb->cgb_ram_bank &= 0x7;
390     }
391     else {
392         gb->cgb_ram_bank = 1;
393     }
394     if (gb->vram_size != 0x4000) {
395         gb->cgb_vram_bank = 0;
396     }
397     if (!GB_is_cgb(gb)) {
398         gb->current_tile_attributes = 0;
399     }
400 
401     gb->object_low_line_address &= gb->vram_size & ~1;
402     if (gb->lcd_x > gb->position_in_line) {
403         gb->lcd_x = gb->position_in_line;
404     }
405 
406     if (gb->object_priority == GB_OBJECT_PRIORITY_UNDEFINED) {
407         gb->object_priority = gb->cgb_mode? GB_OBJECT_PRIORITY_INDEX : GB_OBJECT_PRIORITY_X;
408     }
409     if (gb->sgb) {
410         if (gb->sgb->player_count != 1 && gb->sgb->player_count != 2 && gb->sgb->player_count != 4) {
411             gb->sgb->player_count = 1;
412         }
413         gb->sgb->current_player &= gb->sgb->player_count - 1;
414     }
415     if (gb->sgb && !gb->sgb->v14_3) {
416 #ifdef GB_BIG_ENDIAN
417         for (unsigned i = 0; i < sizeof(gb->sgb->border.raw_data) / 2; i++) {
418             gb->sgb->border.raw_data[i] = LE16(gb->sgb->border.raw_data[i]);
419         }
420 
421         for (unsigned i = 0; i < sizeof(gb->sgb->pending_border.raw_data) / 2; i++) {
422             gb->sgb->pending_border.raw_data[i] = LE16(gb->sgb->pending_border.raw_data[i]);
423         }
424 
425         for (unsigned i = 0; i < sizeof(gb->sgb->effective_palettes) / 2; i++) {
426             gb->sgb->effective_palettes[i] = LE16(gb->sgb->effective_palettes[i]);
427         }
428 
429         for (unsigned i = 0; i < sizeof(gb->sgb->ram_palettes) / 2; i++) {
430             gb->sgb->ram_palettes[i] = LE16(gb->sgb->ram_palettes[i]);
431         }
432 #endif
433         uint8_t converted_tiles[sizeof(gb->sgb->border.tiles)] = {0,};
434         for (unsigned tile = 0; tile < sizeof(gb->sgb->border.tiles_legacy) / 64; tile++) {
435             for (unsigned y = 0; y < 8; y++) {
436                 unsigned base = tile * 32 + y * 2;
437                 for (unsigned x = 0; x < 8; x++) {
438                     uint8_t pixel = gb->sgb->border.tiles_legacy[tile * 8 * 8 + y * 8 + x];
439                     if (pixel & 1) converted_tiles[base]      |= (1 << (7 ^ x));
440                     if (pixel & 2) converted_tiles[base + 1]  |= (1 << (7 ^ x));
441                     if (pixel & 4) converted_tiles[base + 16] |= (1 << (7 ^ x));
442                     if (pixel & 8) converted_tiles[base + 17] |= (1 << (7 ^ x));
443                 }
444             }
445         }
446         memcpy(gb->sgb->border.tiles, converted_tiles, sizeof(converted_tiles));
447         memset(converted_tiles, 0, sizeof(converted_tiles));
448         for (unsigned tile = 0; tile < sizeof(gb->sgb->pending_border.tiles_legacy) / 64; tile++) {
449             for (unsigned y = 0; y < 8; y++) {
450                 unsigned base = tile * 32 + y * 2;
451                 for (unsigned x = 0; x < 8; x++) {
452                     uint8_t pixel = gb->sgb->pending_border.tiles_legacy[tile * 8 * 8 + y * 8 + x];
453                     if (pixel & 1) converted_tiles[base]      |= (1 << (7 ^ x));
454                     if (pixel & 2) converted_tiles[base + 1]  |= (1 << (7 ^ x));
455                     if (pixel & 4) converted_tiles[base + 16] |= (1 << (7 ^ x));
456                     if (pixel & 8) converted_tiles[base + 17] |= (1 << (7 ^ x));
457                 }
458             }
459         }
460         memcpy(gb->sgb->pending_border.tiles, converted_tiles, sizeof(converted_tiles));
461     }
462 }
463 
dump_section(virtual_file_t * file,const void * src,uint32_t size)464 static bool dump_section(virtual_file_t *file, const void *src, uint32_t size)
465 {
466     if (file->write(file, &size, sizeof(size)) != sizeof(size)) {
467         return false;
468     }
469 
470     if (file->write(file, src, size) != size) {
471         return false;
472     }
473 
474     return true;
475 }
476 
477 #define DUMP_SECTION(gb, f, section) dump_section(f, GB_GET_SECTION(gb, section), GB_SECTION_SIZE(section))
478 
save_bess_mbc_block(GB_gameboy_t * gb,virtual_file_t * file)479 static int save_bess_mbc_block(GB_gameboy_t *gb, virtual_file_t *file)
480 {
481 
482     BESS_block_t mbc_block = {BE32('MBC '), 0};
483     BESS_MBC_pair_t pairs[4];
484     switch (gb->cartridge_type->mbc_type) {
485         default:
486         case GB_NO_MBC: return 0;
487         case GB_MBC1:
488             pairs[0] = (BESS_MBC_pair_t){LE16(0x0000), gb->mbc_ram_enable? 0xA : 0x0};
489             pairs[1] = (BESS_MBC_pair_t){LE16(0x2000), gb->mbc1.bank_low};
490             pairs[2] = (BESS_MBC_pair_t){LE16(0x4000), gb->mbc1.bank_high};
491             pairs[3] = (BESS_MBC_pair_t){LE16(0x6000), gb->mbc1.mode};
492             mbc_block.size = 4 * sizeof(pairs[0]);
493             break;
494         case GB_MBC2:
495             pairs[0] = (BESS_MBC_pair_t){LE16(0x0000), gb->mbc_ram_enable? 0xA : 0x0};
496             pairs[1] = (BESS_MBC_pair_t){LE16(0x0100), gb->mbc2.rom_bank};
497             mbc_block.size = 2 * sizeof(pairs[0]);
498             break;
499         case GB_MBC3:
500             pairs[0] = (BESS_MBC_pair_t){LE16(0x0000), gb->mbc_ram_enable? 0xA : 0x0};
501             pairs[1] = (BESS_MBC_pair_t){LE16(0x2000), gb->mbc3.rom_bank};
502             pairs[2] = (BESS_MBC_pair_t){LE16(0x4000), gb->mbc3.ram_bank | (gb->mbc3_rtc_mapped? 8 : 0)};
503             mbc_block.size = 3 * sizeof(pairs[0]);
504             break;
505         case GB_MBC5:
506             pairs[0] = (BESS_MBC_pair_t){LE16(0x0000), gb->mbc_ram_enable? 0xA : 0x0};
507             pairs[1] = (BESS_MBC_pair_t){LE16(0x2000), gb->mbc5.rom_bank_low};
508             pairs[2] = (BESS_MBC_pair_t){LE16(0x3000), gb->mbc5.rom_bank_high};
509             pairs[3] = (BESS_MBC_pair_t){LE16(0x4000), gb->mbc5.ram_bank};
510             mbc_block.size = 4 * sizeof(pairs[0]);
511             break;
512         case GB_HUC1:
513             pairs[0] = (BESS_MBC_pair_t){LE16(0x0000), gb->huc1.ir_mode? 0xE : 0x0};
514             pairs[1] = (BESS_MBC_pair_t){LE16(0x2000), gb->huc1.bank_low};
515             pairs[2] = (BESS_MBC_pair_t){LE16(0x4000), gb->huc1.bank_high};
516             pairs[3] = (BESS_MBC_pair_t){LE16(0x6000), gb->huc1.mode};
517             mbc_block.size = 4 * sizeof(pairs[0]);
518 
519         case GB_HUC3:
520             pairs[0] = (BESS_MBC_pair_t){LE16(0x0000), gb->huc3_mode};
521             pairs[1] = (BESS_MBC_pair_t){LE16(0x2000), gb->huc3.rom_bank};
522             pairs[2] = (BESS_MBC_pair_t){LE16(0x4000), gb->huc3.ram_bank};
523             mbc_block.size = 3 * sizeof(pairs[0]);
524             break;
525 
526         case GB_TPP1:
527             pairs[0] = (BESS_MBC_pair_t){LE16(0x0000), gb->tpp1_rom_bank};
528             pairs[1] = (BESS_MBC_pair_t){LE16(0x0001), gb->tpp1_rom_bank >> 8};
529             pairs[2] = (BESS_MBC_pair_t){LE16(0x0002), gb->tpp1_rom_bank};
530             pairs[3] = (BESS_MBC_pair_t){LE16(0x0003), gb->tpp1_mode};
531             mbc_block.size = 4 * sizeof(pairs[0]);
532             break;
533     }
534 
535     mbc_block.size = LE32(mbc_block.size);
536 
537     if (file->write(file, &mbc_block, sizeof(mbc_block)) != sizeof(mbc_block)) {
538         return errno;
539     }
540 
541     if (file->write(file, &pairs, LE32(mbc_block.size)) != LE32(mbc_block.size)) {
542         return errno;
543     }
544 
545     return 0;
546 }
547 
save_state_internal(GB_gameboy_t * gb,virtual_file_t * file,bool append_bess)548 static int save_state_internal(GB_gameboy_t *gb, virtual_file_t *file, bool append_bess)
549 {
550     if (file->write(file, GB_GET_SECTION(gb, header), GB_SECTION_SIZE(header)) != GB_SECTION_SIZE(header)) goto error;
551     if (!DUMP_SECTION(gb, file, core_state)) goto error;
552     if (!DUMP_SECTION(gb, file, dma       )) goto error;
553     if (!DUMP_SECTION(gb, file, mbc       )) goto error;
554     uint32_t hram_offset = file->tell(file) + 4;
555     if (!DUMP_SECTION(gb, file, hram      )) goto error;
556     if (!DUMP_SECTION(gb, file, timing    )) goto error;
557     if (!DUMP_SECTION(gb, file, apu       )) goto error;
558     if (!DUMP_SECTION(gb, file, rtc       )) goto error;
559     uint32_t video_offset = file->tell(file) + 4;
560     if (!DUMP_SECTION(gb, file, video     )) goto error;
561 
562     uint32_t sgb_offset = 0;
563 
564     if (GB_is_hle_sgb(gb)) {
565         gb->sgb->v14_3 = true;
566         sgb_offset = file->tell(file) + 4;
567         if (!dump_section(file, gb->sgb, sizeof(*gb->sgb))) goto error;
568     }
569 
570 
571     BESS_CORE_t bess_core = {0,};
572 
573     bess_core.mbc_ram.offset = LE32(file->tell(file));
574     bess_core.mbc_ram.size = LE32(gb->mbc_ram_size);
575     if (file->write(file, gb->mbc_ram, gb->mbc_ram_size) != gb->mbc_ram_size) {
576         goto error;
577     }
578 
579     bess_core.ram.offset = LE32(file->tell(file));
580     bess_core.ram.size = LE32(gb->ram_size);
581     if (file->write(file, gb->ram, gb->ram_size) != gb->ram_size) {
582         goto error;
583     }
584 
585     bess_core.vram.offset = LE32(file->tell(file));
586     bess_core.vram.size = LE32(gb->vram_size);
587     if (file->write(file, gb->vram, gb->vram_size) != gb->vram_size) {
588         goto error;
589     }
590 
591     if (!append_bess) return 0;
592 
593     BESS_footer_t bess_footer = {
594         .start_offset = LE32(file->tell(file)),
595         .magic = BE32('BESS'),
596     };
597 
598     /* BESS NAME */
599 
600     static const BESS_block_t bess_name = {BE32('NAME'), LE32(sizeof(BESS_NAME) - 1)};
601 
602     if (file->write(file, &bess_name, sizeof(bess_name)) != sizeof(bess_name)) {
603         goto error;
604     }
605 
606     if (file->write(file, BESS_NAME, sizeof(BESS_NAME) - 1) != sizeof(BESS_NAME) - 1) {
607         goto error;
608     }
609 
610     /* BESS INFO */
611 
612     static const BESS_block_t bess_info = {BE32('INFO'), LE32(sizeof(BESS_INFO_t) - sizeof(BESS_block_t))};
613 
614     if (file->write(file, &bess_info, sizeof(bess_info)) != sizeof(bess_info)) {
615         goto error;
616     }
617 
618     if (file->write(file, gb->rom + 0x134, 0x10) != 0x10) {
619         goto error;
620     }
621 
622     if (file->write(file, gb->rom + 0x14e, 2) != 2) {
623         goto error;
624     }
625 
626     /* BESS CORE */
627 
628     bess_core.header = (BESS_block_t){BE32('CORE'), LE32(sizeof(bess_core) - sizeof(bess_core.header))};
629     bess_core.major = LE16(1);
630     bess_core.minor = LE16(1);
631     switch (gb->model) {
632 
633         case GB_MODEL_DMG_B: bess_core.full_model = BE32('GDB '); break;
634 
635         case GB_MODEL_SGB_NTSC:
636         case GB_MODEL_SGB_NTSC_NO_SFC:
637             bess_core.full_model = BE32('SN  '); break;
638 
639         case GB_MODEL_SGB_PAL_NO_SFC:
640         case GB_MODEL_SGB_PAL:
641             bess_core.full_model = BE32('SP  '); break;
642 
643         case GB_MODEL_SGB2_NO_SFC:
644         case GB_MODEL_SGB2:
645             bess_core.full_model = BE32('S2  '); break;
646 
647 
648         case GB_MODEL_CGB_C: bess_core.full_model = BE32('CCC '); break;
649         case GB_MODEL_CGB_E: bess_core.full_model = BE32('CCE '); break;
650         case GB_MODEL_AGB: bess_core.full_model = BE32('CA  '); break; // SameBoy doesn't emulate a specific AGB revision yet
651     }
652 
653     bess_core.pc = LE16(gb->pc);
654     bess_core.af = LE16(gb->af);
655     bess_core.bc = LE16(gb->bc);
656     bess_core.de = LE16(gb->de);
657     bess_core.hl = LE16(gb->hl);
658     bess_core.sp = LE16(gb->sp);
659 
660     bess_core.ime = gb->ime;
661     bess_core.ie = gb->interrupt_enable;
662     bess_core.execution_mode = 0;
663     if (gb->halted) {
664         bess_core.execution_mode = 1;
665     }
666     else if (gb->stopped) {
667         bess_core.execution_mode = 2;
668     }
669 
670     memcpy(bess_core.io_registers, gb->io_registers, sizeof(gb->io_registers));
671     bess_core.io_registers[GB_IO_DIV] = gb->div_counter >> 8;
672     bess_core.io_registers[GB_IO_BANK] = gb->boot_rom_finished;
673     bess_core.io_registers[GB_IO_KEY1] |= gb->cgb_double_speed? 0x80 : 0;
674     bess_core.hram.size = LE32(sizeof(gb->hram));
675     bess_core.hram.offset = LE32(hram_offset + offsetof(GB_gameboy_t, hram) - GB_SECTION_OFFSET(hram));
676     bess_core.oam.size = LE32(sizeof(gb->oam));
677     bess_core.oam.offset = LE32(video_offset + offsetof(GB_gameboy_t, oam) - GB_SECTION_OFFSET(video));
678     if (GB_is_cgb(gb)) {
679         bess_core.background_palettes.size = LE32(sizeof(gb->background_palettes_data));
680         bess_core.background_palettes.offset = LE32(video_offset + offsetof(GB_gameboy_t, background_palettes_data) - GB_SECTION_OFFSET(video));
681         bess_core.sprite_palettes.size = LE32(sizeof(gb->sprite_palettes_data));
682         bess_core.sprite_palettes.offset = LE32(video_offset + offsetof(GB_gameboy_t, sprite_palettes_data) - GB_SECTION_OFFSET(video));
683     }
684 
685     if (file->write(file, &bess_core, sizeof(bess_core)) != sizeof(bess_core)) {
686         goto error;
687     }
688 
689     /* BESS XOAM */
690 
691     BESS_XOAM_t bess_xoam = {0,};
692     bess_xoam.header = (BESS_block_t){BE32('XOAM'), LE32(sizeof(bess_xoam) - sizeof(bess_xoam.header))};
693     if (GB_is_cgb(gb)) {
694         memcpy(bess_xoam.extra_oam, gb->extra_oam, sizeof(bess_xoam.extra_oam));
695     }
696 
697     if (file->write(file, &bess_xoam, sizeof(bess_xoam)) != sizeof(bess_xoam)) {
698         goto error;
699     }
700 
701     save_bess_mbc_block(gb, file);
702     if (gb->cartridge_type->has_rtc) {
703         if (gb->cartridge_type ->mbc_type == GB_TPP1) {
704             BESS_TPP1_t bess_tpp1 = {0,};
705             bess_tpp1.header = (BESS_block_t){BE32('TPP1'), LE32(sizeof(bess_tpp1) - sizeof(bess_tpp1.header))};
706 
707             bess_tpp1.last_rtc_second = LE64(gb->last_rtc_second);
708             unrolled for (unsigned i = 4; i--;) {
709                 bess_tpp1.real_rtc_data[i] = gb->rtc_real.data[i ^ 3];
710                 bess_tpp1.latched_rtc_data[i] = gb->rtc_latched.data[i ^ 3];
711             }
712             bess_tpp1.mr4 = gb->tpp1_mr4;
713 
714             if (file->write(file, &bess_tpp1, sizeof(bess_tpp1)) != sizeof(bess_tpp1)) {
715                 goto error;
716             }
717         }
718         else if (gb->cartridge_type ->mbc_type != GB_HUC3) {
719             BESS_RTC_t bess_rtc = {0,};
720             bess_rtc.header = (BESS_block_t){BE32('RTC '), LE32(sizeof(bess_rtc) - sizeof(bess_rtc.header))};
721             bess_rtc.real.seconds = gb->rtc_real.seconds;
722             bess_rtc.real.minutes = gb->rtc_real.minutes;
723             bess_rtc.real.hours = gb->rtc_real.hours;
724             bess_rtc.real.days = gb->rtc_real.days;
725             bess_rtc.real.high = gb->rtc_real.high;
726             bess_rtc.latched.seconds = gb->rtc_latched.seconds;
727             bess_rtc.latched.minutes = gb->rtc_latched.minutes;
728             bess_rtc.latched.hours = gb->rtc_latched.hours;
729             bess_rtc.latched.days = gb->rtc_latched.days;
730             bess_rtc.latched.high = gb->rtc_latched.high;
731             bess_rtc.last_rtc_second = LE64(gb->last_rtc_second);
732             if (file->write(file, &bess_rtc, sizeof(bess_rtc)) != sizeof(bess_rtc)) {
733                 goto error;
734             }
735         }
736         else {
737             BESS_HUC3_t bess_huc3 = {0,};
738             bess_huc3.header = (BESS_block_t){BE32('HUC3'), LE32(sizeof(bess_huc3) - sizeof(bess_huc3.header))};
739 
740             bess_huc3.data = (GB_huc3_rtc_time_t) {
741                 LE64(gb->last_rtc_second),
742                 LE16(gb->huc3_minutes),
743                 LE16(gb->huc3_days),
744                 LE16(gb->huc3_alarm_minutes),
745                 LE16(gb->huc3_alarm_days),
746                 gb->huc3_alarm_enabled,
747             };
748             if (file->write(file, &bess_huc3, sizeof(bess_huc3)) != sizeof(bess_huc3)) {
749                 goto error;
750             }
751         }
752     }
753 
754     bool needs_sgb_padding = false;
755     if (gb->sgb) {
756         /* BESS SGB */
757         if (gb->sgb->disable_commands) {
758             needs_sgb_padding = true;
759         }
760         else {
761             BESS_SGB_t bess_sgb = {{BE32('SGB '), LE32(sizeof(bess_sgb) - sizeof(bess_sgb.header))}, };
762 
763             bess_sgb.border_tiles    = (BESS_buffer_t){LE32(sizeof(gb->sgb->pending_border.tiles)),
764                                                        LE32(sgb_offset + offsetof(GB_sgb_t, pending_border.tiles))};
765             bess_sgb.border_tilemap  = (BESS_buffer_t){LE32(sizeof(gb->sgb->pending_border.map)),
766                                                        LE32(sgb_offset + offsetof(GB_sgb_t, pending_border.map))};
767             bess_sgb.border_palettes = (BESS_buffer_t){LE32(sizeof(gb->sgb->pending_border.palette)),
768                                                        LE32(sgb_offset + offsetof(GB_sgb_t, pending_border.palette))};
769 
770             bess_sgb.active_palettes = (BESS_buffer_t){LE32(sizeof(gb->sgb->effective_palettes)),
771                                                        LE32(sgb_offset + offsetof(GB_sgb_t, effective_palettes))};
772             bess_sgb.ram_palettes    = (BESS_buffer_t){LE32(sizeof(gb->sgb->ram_palettes)),
773                                                        LE32(sgb_offset + offsetof(GB_sgb_t, ram_palettes))};
774             bess_sgb.attribute_map   = (BESS_buffer_t){LE32(sizeof(gb->sgb->attribute_map)),
775                                                        LE32(sgb_offset + offsetof(GB_sgb_t, attribute_map))};
776             bess_sgb.attribute_files = (BESS_buffer_t){LE32(sizeof(gb->sgb->attribute_files)),
777                                                        LE32(sgb_offset + offsetof(GB_sgb_t, attribute_files))};
778 
779             bess_sgb.multiplayer_state = (gb->sgb->player_count << 4) | gb->sgb->current_player;
780             if (file->write(file, &bess_sgb, sizeof(bess_sgb)) != sizeof(bess_sgb)) {
781                 goto error;
782             }
783         }
784     }
785 
786     /* BESS END */
787 
788     static const BESS_block_t bess_end = {BE32('END '), 0};
789 
790     if (file->write(file, &bess_end, sizeof(bess_end)) != sizeof(bess_end)) {
791         goto error;
792     }
793 
794     if (needs_sgb_padding) {
795         static const uint8_t sgb_padding[sizeof(BESS_SGB_t)] = {0,};
796         file->write(file, sgb_padding, sizeof(sgb_padding));
797     }
798 
799     /* BESS Footer */
800 
801     if (file->write(file, &bess_footer, sizeof(bess_footer)) != sizeof(bess_footer)) {
802         goto error;
803     }
804 
805     errno = 0;
806 error:
807     return errno;
808 }
809 
GB_save_state(GB_gameboy_t * gb,const char * path)810 int GB_save_state(GB_gameboy_t *gb, const char *path)
811 {
812     FILE *f = fopen(path, "wb");
813     if (!f) {
814         GB_log(gb, "Could not open save state: %s.\n", strerror(errno));
815         return errno;
816     }
817     virtual_file_t file = {
818         .write = file_write,
819         .seek = file_seek,
820         .tell = file_tell,
821         .file = f,
822     };
823     int ret = save_state_internal(gb, &file, true);
824     fclose(f);
825     return ret;
826 }
827 
GB_save_state_to_buffer(GB_gameboy_t * gb,uint8_t * buffer)828 void GB_save_state_to_buffer(GB_gameboy_t *gb, uint8_t *buffer)
829 {
830     virtual_file_t file = {
831         .write = buffer_write,
832         .seek = buffer_seek,
833         .tell = buffer_tell,
834         .buffer = (uint8_t *)buffer,
835         .position = 0,
836     };
837 
838     save_state_internal(gb, &file, true);
839     assert(file.position == GB_get_save_state_size(gb));
840 }
841 
GB_save_state_to_buffer_no_bess(GB_gameboy_t * gb,uint8_t * buffer)842 void GB_save_state_to_buffer_no_bess(GB_gameboy_t *gb, uint8_t *buffer)
843 {
844     virtual_file_t file = {
845         .write = buffer_write,
846         .seek = buffer_seek,
847         .tell = buffer_tell,
848         .buffer = (uint8_t *)buffer,
849         .position = 0,
850     };
851 
852     save_state_internal(gb, &file, false);
853     assert(file.position == GB_get_save_state_size_no_bess(gb));
854 }
855 
read_section(virtual_file_t * file,void * dest,uint32_t size,bool fix_broken_windows_saves)856 static bool read_section(virtual_file_t *file, void *dest, uint32_t size, bool fix_broken_windows_saves)
857 {
858     uint32_t saved_size = 0;
859     if (file->read(file, &saved_size, sizeof(size)) != sizeof(size)) {
860         return false;
861     }
862 
863     if (fix_broken_windows_saves) {
864         if (saved_size < 4) {
865             return false;
866         }
867         saved_size -= 4;
868         file->seek(file, 4, SEEK_CUR);
869     }
870 
871     if (saved_size <= size) {
872         if (file->read(file, dest, saved_size) != saved_size) {
873             return false;
874         }
875     }
876     else {
877         if (file->read(file, dest, size) != size) {
878             return false;
879         }
880         file->seek(file, saved_size - size, SEEK_CUR);
881     }
882 
883     return true;
884 }
885 
read_bess_buffer(const BESS_buffer_t * buffer,virtual_file_t * file,uint8_t * dest,size_t max_size)886 static void read_bess_buffer(const BESS_buffer_t *buffer, virtual_file_t *file, uint8_t *dest, size_t max_size)
887 {
888     size_t pos = file->tell(file);
889     file->seek(file, LE32(buffer->offset), SEEK_SET);
890     file->read(file, dest, MIN(LE32(buffer->size), max_size));
891     file->seek(file, pos, SEEK_SET);
892 
893     if (LE32(buffer->size) < max_size) {
894         memset(dest + LE32(buffer->size), 0, max_size - LE32(buffer->size));
895     }
896 }
897 
load_bess_save(GB_gameboy_t * gb,virtual_file_t * file,bool is_sameboy)898 static int load_bess_save(GB_gameboy_t *gb, virtual_file_t *file, bool is_sameboy)
899 {
900     char emulator_name[65] = {0,};
901     file->seek(file, -sizeof(BESS_footer_t), SEEK_END);
902     BESS_footer_t footer = {0, };
903     file->read(file, &footer, sizeof(footer));
904     if (footer.magic != BE32('BESS')) {
905         // Not a BESS file
906         if (!is_sameboy) {
907             GB_log(gb, "The file is not a save state, or is from an incompatible operating system.\n");
908         }
909         return -1;
910     }
911 
912     GB_gameboy_t save;
913     GB_init(&save, gb->model);
914     save.cartridge_type = gb->cartridge_type;
915 
916     file->seek(file, LE32(footer.start_offset), SEEK_SET);
917     bool found_core = false;
918     BESS_CORE_t core = {0,};
919     bool found_sgb = false;
920     BESS_SGB_t sgb = {0,};
921     while (true) {
922         BESS_block_t block;
923         if (file->read(file, &block, sizeof(block)) != sizeof(block)) goto error;
924         switch (block.magic) {
925             case BE32('CORE'):
926                 if (found_core) goto parse_error;
927                 found_core = true;
928                 if (LE32(block.size) > sizeof(core) - sizeof(block)) {
929                     if (file->read(file, &core.header + 1, sizeof(core) - sizeof(block)) != sizeof(core) - sizeof(block)) goto error;
930                     file->seek(file, LE32(block.size) - (sizeof(core) - sizeof(block)), SEEK_CUR);
931                 }
932                 else {
933                     if (file->read(file, &core.header + 1, LE32(block.size)) != LE32(block.size)) goto error;
934                 }
935 
936                 if (core.major != LE16(1)) {
937                     GB_log(gb, "This save state uses an incompatible version of the BESS specification");
938                     GB_free(&save);
939                     return -1;
940                 }
941 
942                 switch (core.family) {
943                     case 'C':
944                         if (!GB_is_cgb(&save)) goto wrong_model;
945                         break;
946                     case 'S':
947                         if (!GB_is_sgb(&save)) goto wrong_model;
948                         break;
949                     case 'G':
950                         if (GB_is_cgb(&save) || GB_is_sgb(&save)) goto wrong_model;
951                         break;
952                     default:
953                     wrong_model:
954                         GB_log(gb, "The save state is for a different model. Try changing the emulated model.\n");
955                         GB_free(&save);
956                         return -1;
957                 }
958 
959 
960                 save.pc = LE16(core.pc);
961                 save.af = LE16(core.af);
962                 save.bc = LE16(core.bc);
963                 save.de = LE16(core.de);
964                 save.hl = LE16(core.hl);
965                 save.sp = LE16(core.sp);
966 
967                 save.ime = core.ime;
968                 save.interrupt_enable = core.ie;
969 
970                 save.halted = core.execution_mode == 1;
971                 save.stopped = core.execution_mode == 2;
972 
973                 // Done early for compatibility with 0.14.x
974                 GB_write_memory(&save, 0xFF00 + GB_IO_SVBK, core.io_registers[GB_IO_SVBK]);
975                 // CPU related
976 
977                 // Determines DMG mode
978                 GB_write_memory(&save, 0xFF00 + GB_IO_KEY0, core.io_registers[GB_IO_KEY0]);
979                 save.boot_rom_finished = core.io_registers[GB_IO_BANK];
980                 GB_write_memory(&save, 0xFF00 + GB_IO_KEY1, core.io_registers[GB_IO_KEY1]);
981                 if (save.cgb_mode) {
982                     save.cgb_double_speed = core.io_registers[GB_IO_KEY1] & 0x80;
983                     save.object_priority = GB_OBJECT_PRIORITY_INDEX;
984                 }
985                 else {
986                     save.object_priority = GB_OBJECT_PRIORITY_X;
987                 }
988 
989                 // Timers, Joypad and Serial
990                 GB_write_memory(&save, 0xFF00 + GB_IO_JOYP, core.io_registers[GB_IO_JOYP]);
991                 GB_write_memory(&save, 0xFF00 + GB_IO_SB, core.io_registers[GB_IO_SB]);
992                 save.io_registers[GB_IO_SC] = core.io_registers[GB_IO_SC];
993                 save.div_counter = core.io_registers[GB_IO_DIV] << 8;
994                 GB_write_memory(&save, 0xFF00 + GB_IO_TIMA, core.io_registers[GB_IO_TIMA]);
995                 GB_write_memory(&save, 0xFF00 + GB_IO_TMA, core.io_registers[GB_IO_TMA]);
996                 GB_write_memory(&save, 0xFF00 + GB_IO_TAC, core.io_registers[GB_IO_TAC]);
997 
998                 // APU
999                 GB_write_memory(&save, 0xFF00 + GB_IO_NR52, core.io_registers[GB_IO_NR52]);
1000                 for (unsigned i = GB_IO_NR10; i < GB_IO_NR52; i++) {
1001                     uint8_t value = core.io_registers[i];
1002                     if (i == GB_IO_NR14 || i == GB_IO_NR24 || i == GB_IO_NR34 || i == GB_IO_NR44) {
1003                         value &= ~0x80;
1004                     }
1005                     GB_write_memory(&save, 0xFF00 + i, value);
1006                 }
1007 
1008                 for (unsigned i = GB_IO_WAV_START; i <= GB_IO_WAV_END; i++) {
1009                     GB_write_memory(&save, 0xFF00 + i, core.io_registers[i]);
1010                 }
1011 
1012                 // PPU
1013                 GB_write_memory(&save, 0xFF00 + GB_IO_LCDC, core.io_registers[GB_IO_LCDC]);
1014                 GB_write_memory(&save, 0xFF00 + GB_IO_STAT, core.io_registers[GB_IO_STAT]);
1015                 GB_write_memory(&save, 0xFF00 + GB_IO_SCY, core.io_registers[GB_IO_SCY]);
1016                 GB_write_memory(&save, 0xFF00 + GB_IO_SCX, core.io_registers[GB_IO_SCX]);
1017                 GB_write_memory(&save, 0xFF00 + GB_IO_LYC, core.io_registers[GB_IO_LYC]);
1018                 save.io_registers[GB_IO_DMA] = core.io_registers[GB_IO_DMA];
1019                 GB_write_memory(&save, 0xFF00 + GB_IO_BGP, core.io_registers[GB_IO_BGP]);
1020                 GB_write_memory(&save, 0xFF00 + GB_IO_OBP0, core.io_registers[GB_IO_OBP0]);
1021                 GB_write_memory(&save, 0xFF00 + GB_IO_OBP1, core.io_registers[GB_IO_OBP1]);
1022                 GB_write_memory(&save, 0xFF00 + GB_IO_WX, core.io_registers[GB_IO_WX]);
1023                 GB_write_memory(&save, 0xFF00 + GB_IO_WY, core.io_registers[GB_IO_WY]);
1024 
1025                 // Other registers
1026                 GB_write_memory(&save, 0xFF00 + GB_IO_VBK, core.io_registers[GB_IO_VBK]);
1027                 GB_write_memory(&save, 0xFF00 + GB_IO_HDMA1, core.io_registers[GB_IO_HDMA1]);
1028                 GB_write_memory(&save, 0xFF00 + GB_IO_HDMA2, core.io_registers[GB_IO_HDMA2]);
1029                 GB_write_memory(&save, 0xFF00 + GB_IO_HDMA3, core.io_registers[GB_IO_HDMA3]);
1030                 GB_write_memory(&save, 0xFF00 + GB_IO_HDMA4, core.io_registers[GB_IO_HDMA4]);
1031                 GB_write_memory(&save, 0xFF00 + GB_IO_RP, core.io_registers[GB_IO_RP]);
1032                 GB_write_memory(&save, 0xFF00 + GB_IO_BGPI, core.io_registers[GB_IO_BGPI]);
1033                 GB_write_memory(&save, 0xFF00 + GB_IO_OBPI, core.io_registers[GB_IO_OBPI]);
1034                 GB_write_memory(&save, 0xFF00 + GB_IO_OPRI, core.io_registers[GB_IO_OPRI]);
1035 
1036                 // Interrupts
1037                 GB_write_memory(&save, 0xFF00 + GB_IO_IF, core.io_registers[GB_IO_IF]);
1038 
1039                 break;
1040             case BE32('NAME'):
1041                 if (LE32(block.size) > sizeof(emulator_name) - 1) {
1042                     file->seek(file, LE32(block.size), SEEK_CUR);
1043                 }
1044                 else {
1045                     file->read(file, emulator_name, LE32(block.size));
1046                 }
1047                 break;
1048             case BE32('INFO'): {
1049                 BESS_INFO_t bess_info = {0,};
1050                 if (LE32(block.size) != sizeof(bess_info) - sizeof(block)) goto parse_error;
1051                 if (file->read(file, &bess_info.header + 1, LE32(block.size)) != LE32(block.size)) goto error;
1052                 if (memcmp(bess_info.title, gb->rom + 0x134, sizeof(bess_info.title))) {
1053                     char ascii_title[0x11] = {0,};
1054                     for (unsigned i = 0; i < 0x10; i++) {
1055                         if (bess_info.title[i] < 0x20 || bess_info.title[i] > 0x7E) break;
1056                         ascii_title[i] = bess_info.title[i];
1057                     }
1058                     GB_log(gb, "Save state was made on another ROM: '%s'\n", ascii_title);
1059                 }
1060                 else if (memcmp(bess_info.checksum, gb->rom + 0x14E, 2)) {
1061                     GB_log(gb, "Save state was potentially made on another revision of the same ROM.\n");
1062                 }
1063                 break;
1064             }
1065             case BE32('XOAM'):
1066                 if (!found_core) goto parse_error;
1067                 if (LE32(block.size) != 96) goto parse_error;
1068                 file->read(file, save.extra_oam, sizeof(save.extra_oam));
1069                 break;
1070             case BE32('MBC '):
1071                 if (!found_core) goto parse_error;
1072                 if (LE32(block.size) % 3 != 0) goto parse_error;
1073                 if (LE32(block.size) > 0x1000) goto parse_error;
1074                 for (unsigned i = LE32(block.size); i > 0;  i -= 3) {
1075                     BESS_MBC_pair_t pair;
1076                     file->read(file, &pair, sizeof(pair));
1077                     if (LE16(pair.address) >= 0x8000 && LE16(pair.address) < 0xA000) goto parse_error;
1078                     if (LE16(pair.address) >= 0xC000) goto parse_error;
1079                     GB_write_memory(&save, LE16(pair.address), pair.value);
1080                 }
1081                 break;
1082             case BE32('RTC '):
1083                 if (!found_core) goto parse_error;
1084                 BESS_RTC_t bess_rtc;
1085                 if (LE32(block.size) != sizeof(bess_rtc) - sizeof(block)) goto parse_error;
1086                 if (file->read(file, &bess_rtc.header + 1, LE32(block.size)) != LE32(block.size)) goto error;
1087                 if (!gb->cartridge_type->has_rtc || gb->cartridge_type->mbc_type != GB_MBC3) break;
1088                 save.rtc_real.seconds = bess_rtc.real.seconds;
1089                 save.rtc_real.minutes = bess_rtc.real.minutes;
1090                 save.rtc_real.hours = bess_rtc.real.hours;
1091                 save.rtc_real.days = bess_rtc.real.days;
1092                 save.rtc_real.high = bess_rtc.real.high;
1093                 save.rtc_latched.seconds = bess_rtc.latched.seconds;
1094                 save.rtc_latched.minutes = bess_rtc.latched.minutes;
1095                 save.rtc_latched.hours = bess_rtc.latched.hours;
1096                 save.rtc_latched.days = bess_rtc.latched.days;
1097                 save.rtc_latched.high = bess_rtc.latched.high;
1098                 if (gb->rtc_mode == GB_RTC_MODE_SYNC_TO_HOST) {
1099                     save.last_rtc_second = MIN(LE64(bess_rtc.last_rtc_second), time(NULL));
1100                 }
1101 
1102                 break;
1103             case BE32('HUC3'):
1104                 if (!found_core) goto parse_error;
1105                 BESS_HUC3_t bess_huc3;
1106                 if (LE32(block.size) != sizeof(bess_huc3) - sizeof(block)) goto parse_error;
1107                 if (file->read(file, &bess_huc3.header + 1, LE32(block.size)) != LE32(block.size)) goto error;
1108                 if (gb->cartridge_type->mbc_type != GB_HUC3) break;
1109                 if (gb->rtc_mode == GB_RTC_MODE_SYNC_TO_HOST) {
1110                     save.last_rtc_second = MIN(LE64(bess_huc3.data.last_rtc_second), time(NULL));
1111                 }
1112                 save.huc3_minutes = LE16(bess_huc3.data.minutes);
1113                 save.huc3_days = LE16(bess_huc3.data.days);
1114                 save.huc3_alarm_minutes = LE16(bess_huc3.data.alarm_minutes);
1115                 save.huc3_alarm_days = LE16(bess_huc3.data.alarm_days);
1116                 save.huc3_alarm_enabled = bess_huc3.data.alarm_enabled;
1117                 break;
1118             case BE32('TPP1'):
1119                 if (!found_core) goto parse_error;
1120                 BESS_TPP1_t bess_tpp1;
1121                 if (LE32(block.size) != sizeof(bess_tpp1) - sizeof(block)) goto parse_error;
1122                 if (file->read(file, &bess_tpp1.header + 1, LE32(block.size)) != LE32(block.size)) goto error;
1123                 if (gb->cartridge_type->mbc_type != GB_TPP1) break;
1124                 if (gb->rtc_mode == GB_RTC_MODE_SYNC_TO_HOST) {
1125                     save.last_rtc_second = MIN(LE64(bess_tpp1.last_rtc_second), time(NULL));
1126                 }
1127                 unrolled for (unsigned i = 4; i--;) {
1128                     save.rtc_real.data[i ^ 3] = bess_tpp1.real_rtc_data[i];
1129                     save.rtc_latched.data[i ^ 3] = bess_tpp1.latched_rtc_data[i];
1130                 }
1131                 save.tpp1_mr4 = bess_tpp1.mr4;
1132                 break;
1133             case BE32('SGB '):
1134                 if (!found_core) goto parse_error;
1135                 if (!gb->sgb) goto parse_error;
1136                 if (LE32(block.size) > sizeof(sgb) - sizeof(block)) {
1137                     if (file->read(file, &sgb.header + 1, sizeof(sgb) - sizeof(block)) != sizeof(sgb) - sizeof(block)) goto error;
1138                     file->seek(file, LE32(block.size) - (sizeof(sgb) - sizeof(block)), SEEK_CUR);
1139                 }
1140                 else {
1141                     if (file->read(file, &sgb.header + 1, LE32(block.size)) != LE32(block.size)) goto error;
1142                 }
1143                 found_sgb = true;
1144                 break;
1145             case BE32('END '):
1146                 if (!found_core) goto parse_error;
1147                 if (LE32(block.size) != 0) goto parse_error;
1148                 goto done;
1149             default:
1150                 file->seek(file, LE32(block.size), SEEK_CUR);
1151                 break;
1152         }
1153     }
1154 done:
1155     save.mbc_ram_size = gb->mbc_ram_size;
1156     memcpy(gb, &save, GB_SECTION_OFFSET(unsaved));
1157     assert(GB_get_save_state_size(gb) == GB_get_save_state_size(&save));
1158     GB_free(&save);
1159     read_bess_buffer(&core.ram, file, gb->ram, gb->ram_size);
1160     read_bess_buffer(&core.vram, file, gb->vram, gb->vram_size);
1161     read_bess_buffer(&core.mbc_ram, file, gb->mbc_ram, gb->mbc_ram_size);
1162     read_bess_buffer(&core.oam, file, gb->oam, sizeof(gb->oam));
1163     read_bess_buffer(&core.hram, file, gb->hram, sizeof(gb->hram));
1164     read_bess_buffer(&core.background_palettes, file, gb->background_palettes_data, sizeof(gb->background_palettes_data));
1165     read_bess_buffer(&core.sprite_palettes, file, gb->sprite_palettes_data, sizeof(gb->sprite_palettes_data));
1166     if (gb->sgb) {
1167         memset(gb->sgb, 0, sizeof(*gb->sgb));
1168         GB_sgb_load_default_data(gb);
1169         if (gb->boot_rom_finished) {
1170             gb->sgb->intro_animation = GB_SGB_INTRO_ANIMATION_LENGTH;
1171             if (!found_sgb) {
1172                 gb->sgb->disable_commands = true;
1173             }
1174             else {
1175                 read_bess_buffer(&sgb.border_tiles, file, gb->sgb->border.tiles, sizeof(gb->sgb->border.tiles));
1176                 read_bess_buffer(&sgb.border_tilemap, file, (void *)gb->sgb->border.map, sizeof(gb->sgb->border.map));
1177                 read_bess_buffer(&sgb.border_palettes, file, (void *)gb->sgb->border.palette, sizeof(gb->sgb->border.palette));
1178 
1179                 read_bess_buffer(&sgb.active_palettes, file, (void *)gb->sgb->effective_palettes, sizeof(gb->sgb->effective_palettes));
1180                 read_bess_buffer(&sgb.ram_palettes, file, (void *)gb->sgb->ram_palettes, sizeof(gb->sgb->ram_palettes));
1181                 read_bess_buffer(&sgb.attribute_map, file, (void *)gb->sgb->attribute_map, sizeof(gb->sgb->attribute_map));
1182                 read_bess_buffer(&sgb.attribute_files, file, (void *)gb->sgb->attribute_files, sizeof(gb->sgb->attribute_files));
1183 
1184                 gb->sgb->effective_palettes[12] = gb->sgb->effective_palettes[8] =
1185                 gb->sgb->effective_palettes[4] = gb->sgb->effective_palettes[0];
1186 
1187                 gb->sgb->player_count = sgb.multiplayer_state >> 4;
1188                 gb->sgb->current_player = sgb.multiplayer_state & 0xF;
1189                 if (gb->sgb->player_count > 4 || gb->sgb->player_count == 3 || gb->sgb->player_count == 0) {
1190                     gb->sgb->player_count = 1;
1191                     gb->sgb->current_player = 0;
1192                 }
1193             }
1194         }
1195         else {
1196             // Effectively reset if didn't finish the boot ROM
1197             gb->pc = 0;
1198         }
1199     }
1200     if (emulator_name[0]) {
1201         GB_log(gb, "Save state imported from %s.\n", emulator_name);
1202     }
1203     else {
1204         GB_log(gb, "Save state imported from another emulator.\n"); // SameBoy always contains a NAME block
1205     }
1206     for (unsigned i = 0; i < 32; i++) {
1207         GB_palette_changed(gb, false, i * 2);
1208         GB_palette_changed(gb, true, i * 2);
1209     }
1210     return 0;
1211 parse_error:
1212     errno = -1;
1213 error:
1214     if (emulator_name[0]) {
1215         GB_log(gb, "Attempted to import a save state from %s, but the save state is invalid.\n", emulator_name);
1216     }
1217     else {
1218         GB_log(gb, "Attempted to import a save state from a different emulator or incompatible version, but the save state is invalid.\n");
1219     }
1220     GB_free(&save);
1221     sanitize_state(gb);
1222     return errno;
1223 }
1224 
load_state_internal(GB_gameboy_t * gb,virtual_file_t * file)1225 static int load_state_internal(GB_gameboy_t *gb, virtual_file_t *file)
1226 {
1227     GB_gameboy_t save;
1228 
1229     /* Every unread value should be kept the same. */
1230     memcpy(&save, gb, sizeof(save));
1231     /* ...Except ram size, we use it to detect old saves with incorrect ram sizes */
1232     save.ram_size = 0;
1233 
1234     bool fix_broken_windows_saves = false;
1235 
1236     if (file->read(file, GB_GET_SECTION(&save, header), GB_SECTION_SIZE(header)) != GB_SECTION_SIZE(header)) return errno;
1237     if (save.magic == 0) {
1238         /* Potentially legacy, broken Windows save state*/
1239 
1240         file->seek(file, 4, SEEK_SET);
1241         if (file->read(file, GB_GET_SECTION(&save, header), GB_SECTION_SIZE(header)) != GB_SECTION_SIZE(header)) return errno;
1242         fix_broken_windows_saves = true;
1243     }
1244     if (gb->magic != save.magic) {
1245         return load_bess_save(gb, file, false);
1246     }
1247 #define READ_SECTION(gb, file, section) read_section(file, GB_GET_SECTION(gb, section), GB_SECTION_SIZE(section), fix_broken_windows_saves)
1248     if (!READ_SECTION(&save, file, core_state)) return errno ?: EIO;
1249     if (!READ_SECTION(&save, file, dma       )) return errno ?: EIO;
1250     if (!READ_SECTION(&save, file, mbc       )) return errno ?: EIO;
1251     if (!READ_SECTION(&save, file, hram      )) return errno ?: EIO;
1252     if (!READ_SECTION(&save, file, timing    )) return errno ?: EIO;
1253     if (!READ_SECTION(&save, file, apu       )) return errno ?: EIO;
1254     if (!READ_SECTION(&save, file, rtc       )) return errno ?: EIO;
1255     if (!READ_SECTION(&save, file, video     )) return errno ?: EIO;
1256 #undef READ_SECTION
1257 
1258 
1259     bool attempt_bess = false;
1260     if (!verify_and_update_state_compatibility(gb, &save, &attempt_bess)) {
1261         if (attempt_bess) {
1262             return load_bess_save(gb, file, true);
1263         }
1264         return errno;
1265     }
1266 
1267     if (GB_is_hle_sgb(gb)) {
1268         if (!read_section(file, gb->sgb, sizeof(*gb->sgb), false)) return errno ?: EIO;
1269     }
1270 
1271     memset(gb->mbc_ram + save.mbc_ram_size, 0xFF, gb->mbc_ram_size - save.mbc_ram_size);
1272     if (file->read(file, gb->mbc_ram, save.mbc_ram_size) != save.mbc_ram_size) {
1273         return errno ?: EIO;
1274     }
1275 
1276     if (file->read(file, gb->ram, gb->ram_size) != gb->ram_size) {
1277         return errno ?: EIO;
1278     }
1279 
1280     /* Fix for 0.11 save states that allocate twice the amount of RAM in CGB instances */
1281     file->seek(file, save.ram_size - gb->ram_size, SEEK_CUR);
1282 
1283     if (file->read(file, gb->vram, gb->vram_size) != gb->vram_size) {
1284         return errno ?: EIO;
1285     }
1286 
1287     size_t orig_ram_size = gb->ram_size;
1288     memcpy(gb, &save, sizeof(save));
1289     gb->ram_size = orig_ram_size;
1290 
1291     sanitize_state(gb);
1292 
1293     return 0;
1294 }
1295 
GB_load_state(GB_gameboy_t * gb,const char * path)1296 int GB_load_state(GB_gameboy_t *gb, const char *path)
1297 {
1298     FILE *f = fopen(path, "rb");
1299     if (!f) {
1300         GB_log(gb, "Could not open save state: %s.\n", strerror(errno));
1301         return errno;
1302     }
1303     virtual_file_t file = {
1304         .read = file_read,
1305         .seek = file_seek,
1306         .tell = file_tell,
1307         .file = f,
1308     };
1309     int ret = load_state_internal(gb, &file);
1310     fclose(f);
1311     return ret;
1312 }
1313 
GB_load_state_from_buffer(GB_gameboy_t * gb,const uint8_t * buffer,size_t length)1314 int GB_load_state_from_buffer(GB_gameboy_t *gb, const uint8_t *buffer, size_t length)
1315 {
1316     virtual_file_t file = {
1317         .read = buffer_read,
1318         .seek = buffer_seek,
1319         .tell = buffer_tell,
1320         .buffer = (uint8_t *)buffer,
1321         .position = 0,
1322         .size = length,
1323     };
1324 
1325     return load_state_internal(gb, &file);
1326 }
1327 
1328 
GB_is_save_state(const char * path)1329 bool GB_is_save_state(const char *path)
1330 {
1331     bool ret = false;
1332     FILE *f = fopen(path, "rb");
1333     if (!f) return false;
1334     uint32_t magic = 0;
1335     fread(&magic, sizeof(magic), 1, f);
1336     if (magic == state_magic()) {
1337         ret = true;
1338         goto exit;
1339     }
1340 
1341     // Legacy corrupted Windows save state
1342     if (magic == 0) {
1343         fread(&magic, sizeof(magic), 1, f);
1344         if (magic == state_magic()) {
1345             ret = true;
1346             goto exit;
1347         }
1348     }
1349 
1350     fseek(f, -sizeof(magic), SEEK_END);
1351     fread(&magic, sizeof(magic), 1, f);
1352     if (magic == BE32('BESS')) {
1353         ret = true;
1354     }
1355 
1356 exit:
1357     fclose(f);
1358     return ret;
1359 }
1360