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