1 /* RetroArch - A frontend for libretro.
2 * Copyright (C) 2011-2017 - Daniel De Matteis
3 * Copyright (C) 2016-2019 - Brad Parker
4 *
5 * RetroArch is free software: you can redistribute it and/or modify it under the terms
6 * of the GNU General Public License as published by the Free Software Found-
7 * ation, either version 3 of the License, or (at your option) any later version.
8 *
9 * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along with RetroArch.
14 * If not, see <http://www.gnu.org/licenses/>.
15 */
16 #include <stdint.h>
17 #include <stdlib.h>
18 #include <sys/types.h>
19 #include <string.h>
20 #include <time.h>
21
22 #ifdef _WIN32
23 #include <direct.h>
24 #else
25 #include <unistd.h>
26 #endif
27 #include <errno.h>
28
29 #include <compat/strl.h>
30 #include <retro_assert.h>
31 #include <lists/string_list.h>
32 #include <streams/interface_stream.h>
33 #include <streams/file_stream.h>
34 #include <streams/rzip_stream.h>
35 #include <rthreads/rthreads.h>
36 #include <file/file_path.h>
37 #include <retro_miscellaneous.h>
38 #include <string/stdstring.h>
39 #include <time/rtime.h>
40
41 #ifdef HAVE_CONFIG_H
42 #include "../core.h"
43 #endif
44
45 #ifdef HAVE_NETWORKING
46 #include "../network/netplay/netplay.h"
47 #endif
48
49 #ifdef HAVE_CHEEVOS
50 #include "../cheevos/cheevos.h"
51 #endif
52
53 #include "../content.h"
54 #include "../core.h"
55 #include "../file_path_special.h"
56 #include "../configuration.h"
57 #include "../msg_hash.h"
58 #include "../retroarch.h"
59 #include "../verbosity.h"
60 #include "tasks_internal.h"
61 #ifdef HAVE_CHEATS
62 #include "../cheat_manager.h"
63 #endif
64
65 #if defined(HAVE_LIBNX) || defined(_3DS)
66 #define SAVE_STATE_CHUNK 4096 * 10
67 #else
68 #define SAVE_STATE_CHUNK 4096
69 #endif
70
71 #define RASTATE_VERSION 1
72 #define RASTATE_MEM_BLOCK "MEM "
73 #define RASTATE_CHEEVOS_BLOCK "ACHV"
74 #define RASTATE_END_BLOCK "END "
75
76 struct ram_type
77 {
78 const char *path;
79 int type;
80 };
81
82 struct save_state_buf
83 {
84 void* data;
85 size_t size;
86 char path[PATH_MAX_LENGTH];
87 };
88
89 struct sram_block
90 {
91 void *data;
92 size_t size;
93 unsigned type;
94 };
95
96 typedef struct
97 {
98 intfstream_t *file;
99 void *data;
100 void *undo_data;
101 ssize_t size;
102 ssize_t undo_size;
103 ssize_t written;
104 ssize_t bytes_read;
105 int state_slot;
106 char path[PATH_MAX_LENGTH];
107 bool load_to_backup_buffer;
108 bool autoload;
109 bool autosave;
110 bool undo_save;
111 bool mute;
112 bool thumbnail_enable;
113 bool has_valid_framebuffer;
114 bool compress_files;
115 } save_task_state_t;
116
117 #ifdef HAVE_THREADS
118 typedef struct autosave autosave_t;
119
120 /* Autosave support. */
121 struct autosave_st
122 {
123 autosave_t **list;
124 unsigned num;
125 };
126
127 struct autosave
128 {
129 void *buffer;
130 const void *retro_buffer;
131 const char *path;
132 slock_t *lock;
133 slock_t *cond_lock;
134 scond_t *cond;
135 sthread_t *thread;
136 size_t bufsize;
137 unsigned interval;
138 volatile bool quit;
139 bool compress_files;
140 };
141 #endif
142
143 typedef save_task_state_t load_task_data_t;
144
145 /* Holds the previous saved state
146 * Can be restored to disk with undo_save_state(). */
147 /* TODO/FIXME - global state - perhaps move outside this file */
148 static struct save_state_buf undo_save_buf;
149
150 /* Holds the data from before a load_state() operation
151 * Can be restored with undo_load_state(). */
152 static struct save_state_buf undo_load_buf;
153
154 #ifdef HAVE_THREADS
155 /* TODO/FIXME - global state - perhaps move outside this file */
156 static struct autosave_st autosave_state;
157 #endif
158
159 /* TODO/FIXME - global state - perhaps move outside this file */
160 static bool save_state_in_background = false;
161 static struct string_list *task_save_files = NULL;
162
163 typedef struct rastate_size_info
164 {
165 size_t total_size;
166 size_t coremem_size;
167 #ifdef HAVE_CHEEVOS
168 size_t cheevos_size;
169 #endif
170 } rastate_size_info_t;
171
172 #ifdef HAVE_THREADS
173 /**
174 * autosave_thread:
175 * @data : pointer to autosave object
176 *
177 * Callback function for (threaded) autosave.
178 **/
autosave_thread(void * data)179 static void autosave_thread(void *data)
180 {
181 autosave_t *save = (autosave_t*)data;
182
183 while (!save->quit)
184 {
185 bool differ;
186
187 slock_lock(save->lock);
188 differ = string_is_not_equal_fast(save->buffer, save->retro_buffer,
189 save->bufsize);
190 if (differ)
191 memcpy(save->buffer, save->retro_buffer, save->bufsize);
192 slock_unlock(save->lock);
193
194 if (differ)
195 {
196 intfstream_t *file = NULL;
197
198 /* Should probably deal with this more elegantly. */
199 if (save->compress_files)
200 file = intfstream_open_rzip_file(save->path,
201 RETRO_VFS_FILE_ACCESS_WRITE);
202 else
203 file = intfstream_open_file(save->path,
204 RETRO_VFS_FILE_ACCESS_WRITE, RETRO_VFS_FILE_ACCESS_HINT_NONE);
205
206 if (file)
207 {
208 intfstream_write(file, save->buffer, save->bufsize);
209 intfstream_flush(file);
210 intfstream_close(file);
211 free(file);
212 }
213 }
214
215 slock_lock(save->cond_lock);
216
217 if (!save->quit)
218 {
219 #if defined(_MSC_VER) && _MSC_VER <= 1200
220 int64_t timeout_us = 1000000;
221 #else
222 int64_t timeout_us = 1000000LL;
223 #endif
224 scond_wait_timeout(save->cond, save->cond_lock,
225 save->interval * timeout_us);
226 }
227
228 slock_unlock(save->cond_lock);
229 }
230 }
231
232 /**
233 * autosave_new:
234 * @path : path to autosave file
235 * @data : pointer to buffer
236 * @size : size of @data buffer
237 * @interval : interval at which saves should be performed.
238 *
239 * Create and initialize autosave object.
240 *
241 * Returns: pointer to new autosave_t object if successful, otherwise
242 * NULL.
243 **/
autosave_new(const char * path,const void * data,size_t size,unsigned interval,bool compress)244 static autosave_t *autosave_new(const char *path,
245 const void *data, size_t size,
246 unsigned interval, bool compress)
247 {
248 void *buf = NULL;
249 autosave_t *handle = (autosave_t*)malloc(sizeof(*handle));
250 if (!handle)
251 return NULL;
252
253 handle->quit = false;
254 handle->bufsize = size;
255 handle->interval = interval;
256 handle->compress_files = compress;
257 handle->retro_buffer = data;
258 handle->path = path;
259
260 buf = malloc(size);
261
262 if (!buf)
263 {
264 free(handle);
265 return NULL;
266 }
267
268 handle->buffer = buf;
269
270 memcpy(handle->buffer, handle->retro_buffer, handle->bufsize);
271
272 handle->lock = slock_new();
273 handle->cond_lock = slock_new();
274 handle->cond = scond_new();
275 handle->thread = sthread_create(autosave_thread, handle);
276
277 return handle;
278 }
279
280 /**
281 * autosave_free:
282 * @handle : pointer to autosave object
283 *
284 * Frees autosave object.
285 **/
autosave_free(autosave_t * handle)286 static void autosave_free(autosave_t *handle)
287 {
288 slock_lock(handle->cond_lock);
289 handle->quit = true;
290 slock_unlock(handle->cond_lock);
291 scond_signal(handle->cond);
292 sthread_join(handle->thread);
293
294 slock_free(handle->lock);
295 slock_free(handle->cond_lock);
296 scond_free(handle->cond);
297
298 if (handle->buffer)
299 free(handle->buffer);
300 handle->buffer = NULL;
301 }
302
autosave_init(void)303 bool autosave_init(void)
304 {
305 unsigned i;
306 autosave_t **list = NULL;
307 settings_t *settings = config_get_ptr();
308 unsigned autosave_interval = settings->uints.autosave_interval;
309 #if defined(HAVE_ZLIB)
310 bool compress_files = settings->bools.save_file_compression;
311 #else
312 bool compress_files = false;
313 #endif
314
315 if (autosave_interval < 1 || !task_save_files)
316 return false;
317
318 list = (autosave_t**)
319 calloc(task_save_files->size,
320 sizeof(*autosave_state.list));
321
322 if (!list)
323 return false;
324
325 autosave_state.list = list;
326 autosave_state.num = (unsigned)task_save_files->size;
327
328 for (i = 0; i < task_save_files->size; i++)
329 {
330 retro_ctx_memory_info_t mem_info;
331 autosave_t *auto_st = NULL;
332 const char *path = task_save_files->elems[i].data;
333 unsigned type = task_save_files->elems[i].attr.i;
334
335 mem_info.id = type;
336
337 core_get_memory(&mem_info);
338
339 if (mem_info.size <= 0)
340 continue;
341
342 auto_st = autosave_new(path,
343 mem_info.data,
344 mem_info.size,
345 autosave_interval,
346 compress_files);
347
348 if (!auto_st)
349 {
350 RARCH_WARN("%s\n", msg_hash_to_str(MSG_AUTOSAVE_FAILED));
351 continue;
352 }
353
354 autosave_state.list[i] = auto_st;
355 }
356
357 return true;
358 }
359
autosave_deinit(void)360 void autosave_deinit(void)
361 {
362 unsigned i;
363
364 for (i = 0; i < autosave_state.num; i++)
365 {
366 autosave_t *handle = autosave_state.list[i];
367 if (handle)
368 {
369 autosave_free(handle);
370 free(autosave_state.list[i]);
371 }
372 autosave_state.list[i] = NULL;
373 }
374
375 free(autosave_state.list);
376
377 autosave_state.list = NULL;
378 autosave_state.num = 0;
379 }
380
381 /**
382 * autosave_lock:
383 *
384 * Lock autosave.
385 **/
autosave_lock(void)386 void autosave_lock(void)
387 {
388 unsigned i;
389
390 for (i = 0; i < autosave_state.num; i++)
391 {
392 autosave_t *handle = autosave_state.list[i];
393 if (handle)
394 slock_lock(handle->lock);
395 }
396 }
397
398 /**
399 * autosave_unlock:
400 *
401 * Unlocks autosave.
402 **/
autosave_unlock(void)403 void autosave_unlock(void)
404 {
405 unsigned i;
406
407 for (i = 0; i < autosave_state.num; i++)
408 {
409 autosave_t *handle = autosave_state.list[i];
410 if (handle)
411 slock_unlock(handle->lock);
412 }
413 }
414 #endif
415
416 /**
417 * undo_load_state:
418 * Revert to the state before a state was loaded.
419 *
420 * Returns: true if successful, false otherwise.
421 **/
content_undo_load_state(void)422 bool content_undo_load_state(void)
423 {
424 unsigned i;
425 size_t temp_data_size;
426 bool ret = false;
427 unsigned num_blocks = 0;
428 void* temp_data = NULL;
429 struct sram_block *blocks = NULL;
430 settings_t *settings = config_get_ptr();
431 bool block_sram_overwrite = settings->bools.block_sram_overwrite;
432
433 RARCH_LOG("[State]: %s \"%s\", %u %s.\n",
434 msg_hash_to_str(MSG_LOADING_STATE),
435 undo_load_buf.path,
436 (unsigned)undo_load_buf.size,
437 msg_hash_to_str(MSG_BYTES));
438
439 /* TODO/FIXME - This checking of SRAM overwrite,
440 * the backing up of it and
441 * its flushing could all be in their
442 * own functions... */
443 if (block_sram_overwrite && task_save_files
444 && task_save_files->size)
445 {
446 RARCH_LOG("[SRAM]: %s.\n",
447 msg_hash_to_str(MSG_BLOCKING_SRAM_OVERWRITE));
448 blocks = (struct sram_block*)
449 calloc(task_save_files->size, sizeof(*blocks));
450
451 if (blocks)
452 {
453 num_blocks = (unsigned)task_save_files->size;
454 for (i = 0; i < num_blocks; i++)
455 blocks[i].type = task_save_files->elems[i].attr.i;
456 }
457 }
458
459 for (i = 0; i < num_blocks; i++)
460 {
461 retro_ctx_memory_info_t mem_info;
462
463 mem_info.id = blocks[i].type;
464 core_get_memory(&mem_info);
465
466 blocks[i].size = mem_info.size;
467 }
468
469 for (i = 0; i < num_blocks; i++)
470 if (blocks[i].size)
471 blocks[i].data = malloc(blocks[i].size);
472
473 /* Backup current SRAM which is overwritten by unserialize. */
474 for (i = 0; i < num_blocks; i++)
475 {
476 if (blocks[i].data)
477 {
478 retro_ctx_memory_info_t mem_info;
479 const void *ptr = NULL;
480
481 mem_info.id = blocks[i].type;
482
483 core_get_memory(&mem_info);
484
485 ptr = mem_info.data;
486 if (ptr)
487 memcpy(blocks[i].data, ptr, blocks[i].size);
488 }
489 }
490
491 /* We need to make a temporary copy of the buffer, to allow the swap below */
492 temp_data = malloc(undo_load_buf.size);
493 temp_data_size = undo_load_buf.size;
494 memcpy(temp_data, undo_load_buf.data, undo_load_buf.size);
495
496 /* Swap the current state with the backup state. This way, we can undo
497 what we're undoing */
498 content_save_state("RAM", false, false);
499
500 ret = content_deserialize_state(temp_data, temp_data_size);
501
502 /* Clean up the temporary copy */
503 free(temp_data);
504 temp_data = NULL;
505
506 /* Flush back. */
507 for (i = 0; i < num_blocks; i++)
508 {
509 if (blocks[i].data)
510 {
511 retro_ctx_memory_info_t mem_info;
512 void *ptr = NULL;
513
514 mem_info.id = blocks[i].type;
515
516 core_get_memory(&mem_info);
517
518 ptr = mem_info.data;
519 if (ptr)
520 memcpy(ptr, blocks[i].data, blocks[i].size);
521 }
522 }
523
524 for (i = 0; i < num_blocks; i++)
525 free(blocks[i].data);
526 free(blocks);
527
528 if (!ret)
529 {
530 RARCH_ERR("[State]: %s \"%s\".\n",
531 msg_hash_to_str(MSG_FAILED_TO_UNDO_LOAD_STATE),
532 undo_load_buf.path);
533 }
534
535 return ret;
536 }
537
undo_save_state_cb(retro_task_t * task,void * task_data,void * user_data,const char * error)538 static void undo_save_state_cb(retro_task_t *task,
539 void *task_data,
540 void *user_data, const char *error)
541 {
542 save_task_state_t *state = (save_task_state_t*)task_data;
543
544 /* Wipe the save file buffer as it's intended to be one use only */
545 undo_save_buf.path[0] = '\0';
546 undo_save_buf.size = 0;
547 if (undo_save_buf.data)
548 {
549 free(undo_save_buf.data);
550 undo_save_buf.data = NULL;
551 }
552
553 free(state);
554 }
555
556 /**
557 * task_save_handler_finished:
558 * @task : the task to finish
559 * @state : the state associated with this task
560 *
561 * Close the save state file and finish the task.
562 **/
task_save_handler_finished(retro_task_t * task,save_task_state_t * state)563 static void task_save_handler_finished(retro_task_t *task,
564 save_task_state_t *state)
565 {
566 save_task_state_t *task_data = NULL;
567
568 task_set_finished(task, true);
569
570 intfstream_close(state->file);
571 free(state->file);
572
573 if (!task_get_error(task) && task_get_cancelled(task))
574 task_set_error(task, strdup("Task canceled"));
575
576 task_data = (save_task_state_t*)calloc(1, sizeof(*task_data));
577 memcpy(task_data, state, sizeof(*state));
578
579 task_set_data(task, task_data);
580
581 if (state->data)
582 {
583 if (state->undo_save && state->data == undo_save_buf.data)
584 undo_save_buf.data = NULL;
585 free(state->data);
586 state->data = NULL;
587 }
588
589 free(state);
590 }
591
content_align_size(size_t size)592 static size_t content_align_size(size_t size)
593 {
594 /* align to 8-byte boundary */
595 return ((size + 7) & ~7);
596 }
597
content_get_rastate_size(rastate_size_info_t * size)598 static bool content_get_rastate_size(rastate_size_info_t* size)
599 {
600 retro_ctx_size_info_t info;
601
602 core_serialize_size(&info);
603 if (!info.size)
604 return false;
605
606 size->coremem_size = info.size;
607 /* 8-byte identifier, 8-byte block header, content, 8-byte terminator */
608 size->total_size = 8 + 8 + content_align_size(info.size) + 8;
609
610 #ifdef HAVE_CHEEVOS
611 size->cheevos_size = rcheevos_get_serialize_size();
612 if (size->cheevos_size > 0)
613 size->total_size += 8 + content_align_size(size->cheevos_size); /* 8-byte block header + content */
614 #endif
615
616 return true;
617 }
618
content_get_serialized_size(void)619 size_t content_get_serialized_size(void)
620 {
621 rastate_size_info_t size;
622 if (!content_get_rastate_size(&size))
623 return 0;
624
625 return size.total_size;
626 }
627
content_write_block_header(unsigned char * output,const char * header,size_t size)628 static void content_write_block_header(unsigned char* output, const char* header, size_t size)
629 {
630 memcpy(output, header, 4);
631 output[4] = ((size) & 0xFF);
632 output[5] = ((size >> 8) & 0xFF);
633 output[6] = ((size >> 16) & 0xFF);
634 output[7] = ((size >> 24) & 0xFF);
635 }
636
content_write_serialized_state(void * buffer,rastate_size_info_t * size)637 static bool content_write_serialized_state(void* buffer, rastate_size_info_t* size)
638 {
639 retro_ctx_serialize_info_t serial_info;
640 unsigned char* output = (unsigned char*)buffer;
641
642 /* 8-byte identifier "RASTATE1" where 1 is the version */
643 memcpy(output, "RASTATE", 7);
644 output[7] = RASTATE_VERSION;
645 output += 8;
646
647 /* important - write the unaligned size - some cores fail if they aren't passed the exact right size. */
648 content_write_block_header(output, RASTATE_MEM_BLOCK, size->coremem_size);
649 output += 8;
650
651 /* important - pass the unaligned size to the core. some fail if it isn't exactly what they're expecting. */
652 serial_info.size = size->coremem_size;
653 serial_info.data = (void*)output;
654 if (!core_serialize(&serial_info))
655 return false;
656
657 output += content_align_size(size->coremem_size);
658
659 #ifdef HAVE_CHEEVOS
660 if (size->cheevos_size)
661 {
662 content_write_block_header(output, RASTATE_CHEEVOS_BLOCK, size->cheevos_size);
663
664 if (rcheevos_get_serialized_data(output + 8))
665 output += content_align_size(size->cheevos_size) + 8;
666 }
667 #endif
668
669 content_write_block_header(output, RASTATE_END_BLOCK, 0);
670
671 return true;
672 }
673
content_serialize_state(void * buffer,size_t buffer_size)674 bool content_serialize_state(void* buffer, size_t buffer_size)
675 {
676 rastate_size_info_t size;
677 if (!content_get_rastate_size(&size))
678 return false;
679
680 if (size.total_size > buffer_size)
681 return false;
682
683 return content_write_serialized_state(buffer, &size);
684 }
685
content_get_serialized_data(size_t * serial_size)686 static void *content_get_serialized_data(size_t* serial_size)
687 {
688 void* data;
689
690 rastate_size_info_t size;
691 if (!content_get_rastate_size(&size))
692 return NULL;
693
694 /* Ensure buffer is initialised to zero
695 * > Prevents inconsistent compressed state file
696 * sizes when core requests a larger buffer
697 * than it needs (and leaves the excess
698 * as uninitialised garbage) */
699 data = calloc(size.total_size, 1);
700 if (!data)
701 return NULL;
702
703 if (!content_write_serialized_state(data, &size))
704 {
705 free(data);
706 return NULL;
707 }
708
709 *serial_size = size.total_size;
710 return data;
711 }
712
713 /**
714 * task_save_handler:
715 * @task : the task being worked on
716 *
717 * Write a chunk of data to the save state file.
718 **/
task_save_handler(retro_task_t * task)719 static void task_save_handler(retro_task_t *task)
720 {
721 int written;
722 ssize_t remaining;
723 save_task_state_t *state = (save_task_state_t*)task->state;
724
725 if (!state->file)
726 {
727 if (state->compress_files)
728 state->file = intfstream_open_rzip_file(
729 state->path, RETRO_VFS_FILE_ACCESS_WRITE);
730 else
731 state->file = intfstream_open_file(
732 state->path, RETRO_VFS_FILE_ACCESS_WRITE,
733 RETRO_VFS_FILE_ACCESS_HINT_NONE);
734
735 if (!state->file)
736 return;
737 }
738
739 if (!state->data)
740 {
741 size_t size;
742 state->data = content_get_serialized_data(&size);
743 state->size = (ssize_t)size;
744 }
745
746 remaining = MIN(state->size - state->written, SAVE_STATE_CHUNK);
747
748 if (state->data)
749 written = (int)intfstream_write(state->file,
750 (uint8_t*)state->data + state->written, remaining);
751 else
752 written = 0;
753
754 state->written += written;
755
756 task_set_progress(task, (state->written / (float)state->size) * 100);
757
758 if (task_get_cancelled(task) || written != remaining)
759 {
760 size_t err_size = 8192 * sizeof(char);
761 char *err = (char*)malloc(err_size);
762 err[0] = '\0';
763
764 if (state->undo_save)
765 {
766 RARCH_ERR("[State]: %s \"%s\".\n",
767 msg_hash_to_str(MSG_FAILED_TO_UNDO_SAVE_STATE),
768 undo_save_buf.path);
769
770 snprintf(err, err_size - 1, "%s \"%s\".",
771 msg_hash_to_str(MSG_FAILED_TO_UNDO_SAVE_STATE),
772 "RAM");
773 }
774 else
775 snprintf(err, err_size - 1,
776 "%s %s",
777 msg_hash_to_str(MSG_FAILED_TO_SAVE_STATE_TO), state->path);
778
779 task_set_error(task, strdup(err));
780 free(err);
781 task_save_handler_finished(task, state);
782 return;
783 }
784
785 if (state->written == state->size)
786 {
787 char *msg = NULL;
788
789 task_free_title(task);
790
791 if (state->undo_save)
792 msg = strdup(msg_hash_to_str(MSG_RESTORED_OLD_SAVE_STATE));
793 else if (state->state_slot < 0)
794 msg = strdup(msg_hash_to_str(MSG_SAVED_STATE_TO_SLOT_AUTO));
795 else
796 {
797 char new_msg[128];
798 new_msg[0] = '\0';
799
800 snprintf(new_msg, sizeof(new_msg), msg_hash_to_str(MSG_SAVED_STATE_TO_SLOT),
801 state->state_slot);
802 msg = strdup(new_msg);
803 }
804
805 if (!task_get_mute(task) && msg)
806 {
807 task_set_title(task, msg);
808 msg = NULL;
809 }
810
811 task_save_handler_finished(task, state);
812
813 if (!string_is_empty(msg))
814 free(msg);
815
816 return;
817 }
818 }
819
820 /**
821 * task_push_undo_save_state:
822 * @path : file path of the save state
823 * @data : the save state data to write
824 * @size : the total size of the save state
825 *
826 * Create a new task to undo the last save of the content state.
827 **/
task_push_undo_save_state(const char * path,void * data,size_t size)828 static bool task_push_undo_save_state(const char *path, void *data, size_t size)
829 {
830 retro_task_t *task = task_init();
831 save_task_state_t *state = (save_task_state_t*)calloc(1, sizeof(*state));
832 settings_t *settings = config_get_ptr();
833 #if defined(HAVE_ZLIB)
834 bool compress_files = settings->bools.savestate_file_compression;
835 #else
836 bool compress_files = false;
837 #endif
838
839 if (!task || !state)
840 goto error;
841
842 strlcpy(state->path, path, sizeof(state->path));
843 state->data = data;
844 state->size = size;
845 state->undo_save = true;
846 state->state_slot = settings->ints.state_slot;
847 state->has_valid_framebuffer = video_driver_cached_frame_has_valid_framebuffer();
848 state->compress_files = compress_files;
849
850 task->type = TASK_TYPE_BLOCKING;
851 task->state = state;
852 task->handler = task_save_handler;
853 task->callback = undo_save_state_cb;
854 task->title = strdup(msg_hash_to_str(MSG_UNDOING_SAVE_STATE));
855
856 task_queue_push(task);
857
858 return true;
859
860 error:
861 if (data)
862 free(data);
863 if (state)
864 free(state);
865 if (task)
866 free(task);
867
868 return false;
869 }
870
871 /**
872 * undo_save_state:
873 * Reverts the last save operation
874 *
875 * Returns: true if successful, false otherwise.
876 **/
content_undo_save_state(void)877 bool content_undo_save_state(void)
878 {
879 return task_push_undo_save_state(undo_save_buf.path,
880 undo_save_buf.data,
881 undo_save_buf.size);
882 }
883
884 /**
885 * task_load_handler_finished:
886 * @task : the task to finish
887 * @state : the state associated with this task
888 *
889 * Close the loaded state file and finish the task.
890 **/
task_load_handler_finished(retro_task_t * task,save_task_state_t * state)891 static void task_load_handler_finished(retro_task_t *task,
892 save_task_state_t *state)
893 {
894 load_task_data_t *task_data = NULL;
895
896 task_set_finished(task, true);
897
898 if (state->file)
899 {
900 intfstream_close(state->file);
901 free(state->file);
902 }
903
904 if (!task_get_error(task) && task_get_cancelled(task))
905 task_set_error(task, strdup("Task canceled"));
906
907 task_data = (load_task_data_t*)calloc(1, sizeof(*task_data));
908
909 if (!task_data)
910 return;
911
912 memcpy(task_data, state, sizeof(*task_data));
913
914 task_set_data(task, task_data);
915
916 free(state);
917 }
918
919 /**
920 * task_load_handler:
921 * @task : the task being worked on
922 *
923 * Load a chunk of data from the save state file.
924 **/
task_load_handler(retro_task_t * task)925 static void task_load_handler(retro_task_t *task)
926 {
927 ssize_t remaining, bytes_read;
928 save_task_state_t *state = (save_task_state_t*)task->state;
929
930 if (!state->file)
931 {
932 #if defined(HAVE_ZLIB)
933 /* Always use RZIP interface when reading state
934 * files - this will automatically handle uncompressed
935 * data */
936 state->file = intfstream_open_rzip_file(state->path,
937 RETRO_VFS_FILE_ACCESS_READ);
938 #else
939 state->file = intfstream_open_file(state->path,
940 RETRO_VFS_FILE_ACCESS_READ,
941 RETRO_VFS_FILE_ACCESS_HINT_NONE);
942 #endif
943
944 if (!state->file)
945 goto end;
946
947 state->size = intfstream_get_size(state->file);
948
949 if (state->size < 0)
950 goto end;
951
952 state->data = malloc(state->size + 1);
953
954 if (!state->data)
955 goto end;
956 }
957
958 #ifdef HAVE_CHEEVOS
959 if (rcheevos_hardcore_active())
960 task_set_cancelled(task, true);
961 #endif
962
963 remaining = MIN(state->size - state->bytes_read, SAVE_STATE_CHUNK);
964 bytes_read = intfstream_read(state->file,
965 (uint8_t*)state->data + state->bytes_read, remaining);
966 state->bytes_read += bytes_read;
967
968 if (state->size > 0)
969 task_set_progress(task, (state->bytes_read / (float)state->size) * 100);
970
971 if (task_get_cancelled(task) || bytes_read != remaining)
972 {
973 if (state->autoload)
974 {
975 char *msg = (char*)malloc(8192 * sizeof(char));
976
977 msg[0] = '\0';
978
979 snprintf(msg,
980 8192 * sizeof(char),
981 "%s \"%s\" %s.",
982 msg_hash_to_str(MSG_AUTOLOADING_SAVESTATE_FROM),
983 state->path,
984 msg_hash_to_str(MSG_FAILED));
985 task_set_error(task, strdup(msg));
986 free(msg);
987 }
988 else
989 task_set_error(task, strdup(msg_hash_to_str(MSG_FAILED_TO_LOAD_STATE)));
990
991 free(state->data);
992 state->data = NULL;
993 task_load_handler_finished(task, state);
994 return;
995 }
996
997 if (state->bytes_read == state->size)
998 {
999 task_free_title(task);
1000
1001 if (!task_get_mute(task))
1002 {
1003 size_t msg_size = 8192 * sizeof(char);
1004 char *msg = (char*)malloc(msg_size);
1005
1006 msg[0] = '\0';
1007
1008 if (state->autoload)
1009 snprintf(msg, msg_size - 1,
1010 "%s \"%s\" %s.",
1011 msg_hash_to_str(MSG_AUTOLOADING_SAVESTATE_FROM),
1012 state->path,
1013 msg_hash_to_str(MSG_SUCCEEDED));
1014 else
1015 {
1016 if (state->state_slot < 0)
1017 strlcpy(msg, msg_hash_to_str(MSG_LOADED_STATE_FROM_SLOT_AUTO),
1018 msg_size - 1);
1019 else
1020 snprintf(msg, msg_size - 1,
1021 msg_hash_to_str(MSG_LOADED_STATE_FROM_SLOT),
1022 state->state_slot);
1023 }
1024
1025 task_set_title(task, strdup(msg));
1026 free(msg);
1027 }
1028
1029 goto end;
1030 }
1031
1032 return;
1033
1034 end:
1035 task_load_handler_finished(task, state);
1036 }
1037
content_load_rastate1(unsigned char * input,size_t size)1038 static bool content_load_rastate1(unsigned char* input, size_t size)
1039 {
1040 unsigned char* stop = input + size;
1041 unsigned char* marker;
1042 bool seen_core = false;
1043 #ifdef HAVE_CHEEVOS
1044 bool seen_cheevos = false;
1045 #endif
1046
1047 input += 8;
1048 while (input < stop)
1049 {
1050 size_t block_size = (input[7] << 24 | input[6] << 16 | input[5] << 8 | input[4]);
1051 marker = input;
1052 input += 8;
1053
1054 if (memcmp(marker, RASTATE_MEM_BLOCK, 4) == 0)
1055 {
1056 retro_ctx_serialize_info_t serial_info;
1057 serial_info.data_const = (void*)input;
1058 serial_info.size = block_size;
1059 if (!core_unserialize(&serial_info))
1060 return false;
1061
1062 seen_core = true;
1063 }
1064 #ifdef HAVE_CHEEVOS
1065 else if (memcmp(marker, RASTATE_CHEEVOS_BLOCK, 4) == 0)
1066 {
1067 if (rcheevos_set_serialized_data((void*)input))
1068 seen_cheevos = true;
1069 }
1070 #endif
1071 else if (memcmp(marker, RASTATE_END_BLOCK, 4) == 0)
1072 {
1073 break;
1074 }
1075
1076 input += content_align_size(block_size);
1077 }
1078
1079 if (!seen_core)
1080 return false;
1081
1082 #ifdef HAVE_CHEEVOS
1083 if (!seen_cheevos)
1084 rcheevos_set_serialized_data(NULL);
1085 #endif
1086
1087 return true;
1088 }
1089
content_deserialize_state(const void * serialized_data,size_t serialized_size)1090 bool content_deserialize_state(const void* serialized_data, size_t serialized_size)
1091 {
1092 if (memcmp(serialized_data, "RASTATE", 7) != 0)
1093 {
1094 /* old format is just core data, load it directly */
1095 retro_ctx_serialize_info_t serial_info;
1096 serial_info.data_const = serialized_data;
1097 serial_info.size = serialized_size;
1098 if (!core_unserialize(&serial_info))
1099 return false;
1100
1101 #ifdef HAVE_CHEEVOS
1102 rcheevos_set_serialized_data(NULL);
1103 #endif
1104 }
1105 else
1106 {
1107 unsigned char* input = (unsigned char*)serialized_data;
1108 switch (input[7]) /* version */
1109 {
1110 case 1:
1111 if (!content_load_rastate1(input, serialized_size))
1112 return false;
1113 break;
1114
1115 default:
1116 return false;
1117 }
1118 }
1119
1120 return true;
1121 }
1122
1123 /**
1124 * content_load_state_cb:
1125 * @path : path that state will be loaded from.
1126 * Load a state from disk to memory.
1127 *
1128 **/
content_load_state_cb(retro_task_t * task,void * task_data,void * user_data,const char * error)1129 static void content_load_state_cb(retro_task_t *task,
1130 void *task_data,
1131 void *user_data, const char *error)
1132 {
1133 unsigned i;
1134 bool ret;
1135 load_task_data_t *load_data = (load_task_data_t*)task_data;
1136 ssize_t size = load_data->size;
1137 unsigned num_blocks = 0;
1138 void *buf = load_data->data;
1139 struct sram_block *blocks = NULL;
1140 settings_t *settings = config_get_ptr();
1141 bool block_sram_overwrite = settings->bools.block_sram_overwrite;
1142
1143 #ifdef HAVE_CHEEVOS
1144 if (rcheevos_hardcore_active())
1145 goto error;
1146 #endif
1147
1148 RARCH_LOG("[State]: %s \"%s\", %u %s.\n",
1149 msg_hash_to_str(MSG_LOADING_STATE),
1150 load_data->path,
1151 (unsigned)size,
1152 msg_hash_to_str(MSG_BYTES));
1153
1154 if (size < 0 || !buf)
1155 goto error;
1156
1157 /* This means we're backing up the file in memory,
1158 * so content_undo_save_state()
1159 * can restore it */
1160 if (load_data->load_to_backup_buffer)
1161 {
1162 /* If we were previously backing up a file, let go of it first */
1163 if (undo_save_buf.data)
1164 {
1165 free(undo_save_buf.data);
1166 undo_save_buf.data = NULL;
1167 }
1168
1169 undo_save_buf.data = malloc(size);
1170 if (!undo_save_buf.data)
1171 goto error;
1172
1173 memcpy(undo_save_buf.data, buf, size);
1174 undo_save_buf.size = size;
1175 strlcpy(undo_save_buf.path, load_data->path, sizeof(undo_save_buf.path));
1176
1177 free(buf);
1178 free(load_data);
1179 return;
1180 }
1181
1182 if (block_sram_overwrite && task_save_files
1183 && task_save_files->size)
1184 {
1185 RARCH_LOG("[SRAM]: %s.\n",
1186 msg_hash_to_str(MSG_BLOCKING_SRAM_OVERWRITE));
1187 blocks = (struct sram_block*)
1188 calloc(task_save_files->size, sizeof(*blocks));
1189
1190 if (blocks)
1191 {
1192 num_blocks = (unsigned)task_save_files->size;
1193 for (i = 0; i < num_blocks; i++)
1194 blocks[i].type = task_save_files->elems[i].attr.i;
1195 }
1196 }
1197
1198 for (i = 0; i < num_blocks; i++)
1199 {
1200 retro_ctx_memory_info_t mem_info;
1201
1202 mem_info.id = blocks[i].type;
1203 core_get_memory(&mem_info);
1204
1205 blocks[i].size = mem_info.size;
1206 }
1207
1208 for (i = 0; i < num_blocks; i++)
1209 if (blocks[i].size)
1210 blocks[i].data = malloc(blocks[i].size);
1211
1212 /* Backup current SRAM which is overwritten by unserialize. */
1213 for (i = 0; i < num_blocks; i++)
1214 {
1215 if (blocks[i].data)
1216 {
1217 retro_ctx_memory_info_t mem_info;
1218 const void *ptr = NULL;
1219
1220 mem_info.id = blocks[i].type;
1221
1222 core_get_memory(&mem_info);
1223
1224 ptr = mem_info.data;
1225 if (ptr)
1226 memcpy(blocks[i].data, ptr, blocks[i].size);
1227 }
1228 }
1229
1230 /* Backup the current state so we can undo this load */
1231 content_save_state("RAM", false, false);
1232
1233 ret = content_deserialize_state(buf, size);
1234
1235 /* Flush back. */
1236 for (i = 0; i < num_blocks; i++)
1237 {
1238 if (blocks[i].data)
1239 {
1240 retro_ctx_memory_info_t mem_info;
1241 void *ptr = NULL;
1242
1243 mem_info.id = blocks[i].type;
1244
1245 core_get_memory(&mem_info);
1246
1247 ptr = mem_info.data;
1248 if (ptr)
1249 memcpy(ptr, blocks[i].data, blocks[i].size);
1250 }
1251 }
1252
1253 for (i = 0; i < num_blocks; i++)
1254 free(blocks[i].data);
1255 free(blocks);
1256
1257 if (!ret)
1258 goto error;
1259
1260 free(buf);
1261 free(load_data);
1262
1263 return;
1264
1265 error:
1266 RARCH_ERR("[State]: %s \"%s\".\n",
1267 msg_hash_to_str(MSG_FAILED_TO_LOAD_STATE),
1268 load_data->path);
1269 if (buf)
1270 free(buf);
1271 free(load_data);
1272 }
1273
1274 /**
1275 * save_state_cb:
1276 *
1277 * Called after the save state is done. Takes a screenshot if needed.
1278 **/
save_state_cb(retro_task_t * task,void * task_data,void * user_data,const char * error)1279 static void save_state_cb(retro_task_t *task,
1280 void *task_data,
1281 void *user_data, const char *error)
1282 {
1283 save_task_state_t *state = (save_task_state_t*)task_data;
1284 #ifdef HAVE_SCREENSHOTS
1285 char *path = strdup(state->path);
1286 settings_t *settings = config_get_ptr();
1287 const char *dir_screenshot = settings->paths.directory_screenshot;
1288
1289 if (state->thumbnail_enable)
1290 take_screenshot(dir_screenshot,
1291 path, true, state->has_valid_framebuffer, false, true);
1292 free(path);
1293 #endif
1294
1295 free(state);
1296 }
1297
1298 /**
1299 * task_push_save_state:
1300 * @path : file path of the save state
1301 * @data : the save state data to write
1302 * @size : the total size of the save state
1303 *
1304 * Create a new task to save the content state.
1305 **/
task_push_save_state(const char * path,void * data,size_t size,bool autosave)1306 static void task_push_save_state(const char *path, void *data, size_t size, bool autosave)
1307 {
1308 retro_task_t *task = task_init();
1309 save_task_state_t *state = (save_task_state_t*)calloc(1, sizeof(*state));
1310 settings_t *settings = config_get_ptr();
1311 bool savestate_thumbnail_enable = settings->bools.savestate_thumbnail_enable;
1312 int state_slot = settings->ints.state_slot;
1313 #if defined(HAVE_ZLIB)
1314 bool compress_files = settings->bools.savestate_file_compression;
1315 #else
1316 bool compress_files = false;
1317 #endif
1318
1319 if (!task || !state)
1320 goto error;
1321
1322 strlcpy(state->path, path, sizeof(state->path));
1323 state->data = data;
1324 state->size = size;
1325 state->autosave = autosave;
1326 state->mute = autosave; /* don't show OSD messages if we are auto-saving */
1327 state->thumbnail_enable = savestate_thumbnail_enable;
1328 state->state_slot = state_slot;
1329 state->has_valid_framebuffer = video_driver_cached_frame_has_valid_framebuffer();
1330 state->compress_files = compress_files;
1331
1332 task->type = TASK_TYPE_BLOCKING;
1333 task->state = state;
1334 task->handler = task_save_handler;
1335 task->callback = save_state_cb;
1336 task->title = strdup(msg_hash_to_str(MSG_SAVING_STATE));
1337 task->mute = state->mute;
1338
1339 if (!task_queue_push(task))
1340 {
1341 /* Another blocking task is already active. */
1342 if (data)
1343 free(data);
1344 if (task->title)
1345 task_free_title(task);
1346 free(task);
1347 free(state);
1348 }
1349
1350 return;
1351
1352 error:
1353 if (data)
1354 free(data);
1355 if (state)
1356 free(state);
1357 if (task)
1358 {
1359 if (task->title)
1360 task_free_title(task);
1361 free(task);
1362 }
1363 }
1364
1365 /**
1366 * content_load_and_save_state_cb:
1367 * @path : path that state will be loaded from.
1368 * Load then save a state.
1369 *
1370 **/
content_load_and_save_state_cb(retro_task_t * task,void * task_data,void * user_data,const char * error)1371 static void content_load_and_save_state_cb(retro_task_t *task,
1372 void *task_data,
1373 void *user_data, const char *error)
1374 {
1375 load_task_data_t *load_data = (load_task_data_t*)task_data;
1376 char *path = strdup(load_data->path);
1377 void *data = load_data->undo_data;
1378 size_t size = load_data->undo_size;
1379 bool autosave = load_data->autosave;
1380
1381 content_load_state_cb(task, task_data, user_data, error);
1382
1383 task_push_save_state(path, data, size, autosave);
1384
1385 free(path);
1386 }
1387
1388 /**
1389 * task_push_load_and_save_state:
1390 * @path : file path of the save state
1391 * @data : the save state data to write
1392 * @size : the total size of the save state
1393 * @load_to_backup_buffer : If true, the state will be loaded into undo_save_buf.
1394 *
1395 * Create a new task to load current state first into a backup buffer (for undo)
1396 * and then save the content state.
1397 **/
task_push_load_and_save_state(const char * path,void * data,size_t size,bool load_to_backup_buffer,bool autosave)1398 static void task_push_load_and_save_state(const char *path, void *data,
1399 size_t size, bool load_to_backup_buffer, bool autosave)
1400 {
1401 retro_task_t *task = NULL;
1402 settings_t *settings = config_get_ptr();
1403 int state_slot = settings->ints.state_slot;
1404 #if defined(HAVE_ZLIB)
1405 bool compress_files = settings->bools.savestate_file_compression;
1406 #else
1407 bool compress_files = false;
1408 #endif
1409 save_task_state_t *state = (save_task_state_t*)
1410 calloc(1, sizeof(*state));
1411
1412 if (!state)
1413 return;
1414
1415 task = task_init();
1416
1417 if (!task)
1418 {
1419 free(state);
1420 return;
1421 }
1422
1423
1424 strlcpy(state->path, path, sizeof(state->path));
1425 state->load_to_backup_buffer = load_to_backup_buffer;
1426 state->undo_size = size;
1427 state->undo_data = data;
1428 state->autosave = autosave;
1429 state->mute = autosave; /* don't show OSD messages if we
1430 are auto-saving */
1431 if (load_to_backup_buffer)
1432 state->mute = true;
1433 state->state_slot = state_slot;
1434 state->has_valid_framebuffer =
1435 video_driver_cached_frame_has_valid_framebuffer();
1436 state->compress_files = compress_files;
1437
1438 task->state = state;
1439 task->type = TASK_TYPE_BLOCKING;
1440 task->handler = task_load_handler;
1441 task->callback = content_load_and_save_state_cb;
1442 task->title = strdup(msg_hash_to_str(MSG_LOADING_STATE));
1443 task->mute = state->mute;
1444
1445 if (!task_queue_push(task))
1446 {
1447 /* Another blocking task is already active. */
1448 if (data)
1449 free(data);
1450 if (task->title)
1451 task_free_title(task);
1452 free(task);
1453 free(state);
1454 }
1455 }
1456
1457 /**
1458 * content_save_state:
1459 * @path : path of saved state that shall be written to.
1460 * @save_to_disk: If false, saves the state onto undo_load_buf.
1461 * Save a state from memory to disk.
1462 *
1463 * Returns: true if successful, false otherwise.
1464 **/
content_save_state(const char * path,bool save_to_disk,bool autosave)1465 bool content_save_state(const char *path, bool save_to_disk, bool autosave)
1466 {
1467 retro_ctx_size_info_t info;
1468 void *data = NULL;
1469 size_t serial_size;
1470
1471 core_serialize_size(&info);
1472
1473 if (info.size == 0)
1474 return false;
1475 serial_size = info.size;
1476
1477 if (!save_state_in_background)
1478 {
1479 data = content_get_serialized_data(&serial_size);
1480
1481 if (!data)
1482 {
1483 RARCH_ERR("[State]: %s \"%s\".\n",
1484 msg_hash_to_str(MSG_FAILED_TO_SAVE_STATE_TO),
1485 path);
1486 return false;
1487 }
1488
1489 RARCH_LOG("[State]: %s \"%s\", %u %s.\n",
1490 msg_hash_to_str(MSG_SAVING_STATE),
1491 path,
1492 (unsigned)serial_size,
1493 msg_hash_to_str(MSG_BYTES));
1494 }
1495
1496 if (save_to_disk)
1497 {
1498 if (path_is_valid(path) && !autosave)
1499 {
1500 /* Before overwriting the savestate file, load it into a buffer
1501 to allow undo_save_state() to work */
1502 /* TODO/FIXME - Use msg_hash_to_str here */
1503 RARCH_LOG("[State]: %s ...\n",
1504 msg_hash_to_str(MSG_FILE_ALREADY_EXISTS_SAVING_TO_BACKUP_BUFFER));
1505
1506 task_push_load_and_save_state(path, data, serial_size, true, autosave);
1507 }
1508 else
1509 task_push_save_state(path, data, serial_size, autosave);
1510 }
1511 else
1512 {
1513 if (!data)
1514 data = content_get_serialized_data(&serial_size);
1515
1516 if (!data)
1517 {
1518 RARCH_ERR("[State]: %s \"%s\".\n",
1519 msg_hash_to_str(MSG_FAILED_TO_SAVE_STATE_TO),
1520 path);
1521 return false;
1522 }
1523 /* save_to_disk is false, which means we are saving the state
1524 in undo_load_buf to allow content_undo_load_state() to restore it */
1525
1526 /* If we were holding onto an old state already, clean it up first */
1527 if (undo_load_buf.data)
1528 {
1529 free(undo_load_buf.data);
1530 undo_load_buf.data = NULL;
1531 }
1532
1533 undo_load_buf.data = malloc(serial_size);
1534 if (!undo_load_buf.data)
1535 {
1536 free(data);
1537 return false;
1538 }
1539
1540 memcpy(undo_load_buf.data, data, serial_size);
1541 free(data);
1542 undo_load_buf.size = serial_size;
1543 strlcpy(undo_load_buf.path, path, sizeof(undo_load_buf.path));
1544 }
1545
1546 return true;
1547 }
1548
task_save_state_finder(retro_task_t * task,void * user_data)1549 static bool task_save_state_finder(retro_task_t *task, void *user_data)
1550 {
1551 if (!task)
1552 return false;
1553
1554 if (task->handler == task_save_handler)
1555 return true;
1556
1557 return false;
1558 }
1559
1560 /* Returns true if a save state task is in progress */
content_save_state_in_progress(void * data)1561 static bool content_save_state_in_progress(void* data)
1562 {
1563 task_finder_data_t find_data;
1564
1565 find_data.func = task_save_state_finder;
1566 find_data.userdata = NULL;
1567
1568 if (task_queue_find(&find_data))
1569 return true;
1570
1571 return false;
1572 }
1573
content_wait_for_save_state_task(void)1574 void content_wait_for_save_state_task(void)
1575 {
1576 task_queue_wait(content_save_state_in_progress, NULL);
1577 }
1578
1579 /**
1580 * content_load_state:
1581 * @path : path that state will be loaded from.
1582 * @load_to_backup_buffer: If true, the state will be loaded into undo_save_buf.
1583 * Load a state from disk to memory.
1584 *
1585 * Returns: true if successful, false otherwise.
1586 *
1587 *
1588 **/
content_load_state(const char * path,bool load_to_backup_buffer,bool autoload)1589 bool content_load_state(const char *path,
1590 bool load_to_backup_buffer, bool autoload)
1591 {
1592 retro_task_t *task = task_init();
1593 save_task_state_t *state = (save_task_state_t*)calloc(1, sizeof(*state));
1594 settings_t *settings = config_get_ptr();
1595 int state_slot = settings->ints.state_slot;
1596 #if defined(HAVE_ZLIB)
1597 bool compress_files = settings->bools.savestate_file_compression;
1598 #else
1599 bool compress_files = false;
1600 #endif
1601
1602 if (!task || !state)
1603 goto error;
1604
1605 strlcpy(state->path, path, sizeof(state->path));
1606 state->load_to_backup_buffer = load_to_backup_buffer;
1607 state->autoload = autoload;
1608 state->state_slot = state_slot;
1609 state->has_valid_framebuffer =
1610 video_driver_cached_frame_has_valid_framebuffer();
1611 state->compress_files = compress_files;
1612
1613 task->type = TASK_TYPE_BLOCKING;
1614 task->state = state;
1615 task->handler = task_load_handler;
1616 task->callback = content_load_state_cb;
1617 task->title = strdup(msg_hash_to_str(MSG_LOADING_STATE));
1618
1619 task_queue_push(task);
1620
1621 return true;
1622
1623 error:
1624 if (state)
1625 free(state);
1626 if (task)
1627 free(task);
1628
1629 return false;
1630 }
1631
content_rename_state(const char * origin,const char * dest)1632 bool content_rename_state(const char *origin, const char *dest)
1633 {
1634 int ret = 0;
1635 if (filestream_exists(dest))
1636 filestream_delete(dest);
1637
1638 ret = filestream_rename(origin, dest);
1639 if (!ret)
1640 return true;
1641
1642 RARCH_ERR("[State]: Error %d renaming file \"%s\".\n", ret, origin);
1643 return false;
1644 }
1645
1646 /*
1647 *
1648 * TODO/FIXME: Figure out when and where this should be called.
1649 * As it is, when e.g. closing Gambatte, we get the
1650 * same printf message 4 times.
1651 */
content_reset_savestate_backups(void)1652 bool content_reset_savestate_backups(void)
1653 {
1654 if (undo_save_buf.data)
1655 {
1656 free(undo_save_buf.data);
1657 undo_save_buf.data = NULL;
1658 }
1659
1660 undo_save_buf.path[0] = '\0';
1661 undo_save_buf.size = 0;
1662
1663 if (undo_load_buf.data)
1664 {
1665 free(undo_load_buf.data);
1666 undo_load_buf.data = NULL;
1667 }
1668
1669 undo_load_buf.path[0] = '\0';
1670 undo_load_buf.size = 0;
1671
1672 return true;
1673 }
1674
content_undo_load_buf_is_empty(void)1675 bool content_undo_load_buf_is_empty(void)
1676 {
1677 return undo_load_buf.data == NULL || undo_load_buf.size == 0;
1678 }
1679
content_undo_save_buf_is_empty(void)1680 bool content_undo_save_buf_is_empty(void)
1681 {
1682 return undo_save_buf.data == NULL || undo_save_buf.size == 0;
1683 }
1684
content_get_memory(retro_ctx_memory_info_t * mem_info,struct ram_type * ram,unsigned slot)1685 static bool content_get_memory(retro_ctx_memory_info_t *mem_info,
1686 struct ram_type *ram, unsigned slot)
1687 {
1688 ram->type = task_save_files->elems[slot].attr.i;
1689 ram->path = task_save_files->elems[slot].data;
1690
1691 mem_info->id = ram->type;
1692
1693 core_get_memory(mem_info);
1694
1695 if (!mem_info->data || mem_info->size == 0)
1696 return false;
1697
1698 return true;
1699 }
1700
1701 /**
1702 * content_load_ram_file:
1703 * @path : path of RAM state that will be loaded from.
1704 * @type : type of memory
1705 *
1706 * Load a RAM state from disk to memory.
1707 */
content_load_ram_file(unsigned slot)1708 bool content_load_ram_file(unsigned slot)
1709 {
1710 int64_t rc;
1711 struct ram_type ram;
1712 retro_ctx_memory_info_t mem_info;
1713 void *buf = NULL;
1714
1715 if (!content_get_memory(&mem_info, &ram, slot))
1716 return false;
1717
1718 /* On first run of content, SRAM file will
1719 * not exist. This is a common enough occurrence
1720 * that we should check before attempting to
1721 * invoke the relevant read_file() function */
1722 if (string_is_empty(ram.path) ||
1723 !path_is_valid(ram.path))
1724 return false;
1725
1726 #if defined(HAVE_ZLIB)
1727 /* Always use RZIP interface when reading SRAM
1728 * files - this will automatically handle uncompressed
1729 * data */
1730 if (!rzipstream_read_file(ram.path, &buf, &rc))
1731 #else
1732 if (!filestream_read_file(ram.path, &buf, &rc))
1733 #endif
1734 return false;
1735
1736 if (rc > 0)
1737 {
1738 if (rc > (ssize_t)mem_info.size)
1739 {
1740 RARCH_WARN("[SRAM]: SRAM is larger than implementation expects, "
1741 "doing partial load (truncating %u %s %s %u).\n",
1742 (unsigned)rc,
1743 msg_hash_to_str(MSG_BYTES),
1744 msg_hash_to_str(MSG_TO),
1745 (unsigned)mem_info.size);
1746 rc = mem_info.size;
1747 }
1748 memcpy(mem_info.data, buf, (size_t)rc);
1749 }
1750
1751 if (buf)
1752 free(buf);
1753
1754 return true;
1755 }
1756
1757 /**
1758 * dump_to_file_desperate:
1759 * @data : pointer to data buffer.
1760 * @size : size of @data.
1761 * @type : type of file to be saved.
1762 *
1763 * Attempt to save valuable RAM data somewhere.
1764 **/
dump_to_file_desperate(const void * data,size_t size,unsigned type)1765 static bool dump_to_file_desperate(const void *data,
1766 size_t size, unsigned type)
1767 {
1768 time_t time_;
1769 struct tm tm_;
1770 char timebuf[256];
1771 char path[PATH_MAX_LENGTH];
1772 char application_data[PATH_MAX_LENGTH];
1773
1774 application_data[0] = '\0';
1775 path [0] = '\0';
1776 timebuf [0] = '\0';
1777
1778 if (!fill_pathname_application_data(application_data,
1779 sizeof(application_data)))
1780 return false;
1781
1782 time(&time_);
1783
1784 rtime_localtime(&time_, &tm_);
1785
1786 strftime(timebuf,
1787 256 * sizeof(char),
1788 "%Y-%m-%d-%H-%M-%S", &tm_);
1789
1790 snprintf(path, sizeof(path),
1791 "%s/RetroArch-recovery-%u%s",
1792 application_data, type,
1793 timebuf);
1794
1795 /* Fallback (emergency) saves are always
1796 * uncompressed
1797 * > If a regular save fails, then the host
1798 * system is experiencing serious technical
1799 * difficulties (most likely some kind of
1800 * hardware failure)
1801 * > In this case, we don't want to further
1802 * complicate matters by introducing zlib
1803 * compression overheads */
1804 if (!filestream_write_file(path, data, size))
1805 return false;
1806
1807 RARCH_WARN("[SRAM]: Succeeded in saving RAM data to \"%s\".\n", path);
1808 return true;
1809 }
1810
1811 /**
1812 * content_save_ram_file:
1813 * @path : path of RAM state that shall be written to.
1814 * @type : type of memory
1815 *
1816 * Save a RAM state from memory to disk.
1817 *
1818 */
content_save_ram_file(unsigned slot,bool compress)1819 bool content_save_ram_file(unsigned slot, bool compress)
1820 {
1821 struct ram_type ram;
1822 retro_ctx_memory_info_t mem_info;
1823 bool write_success;
1824
1825 if (!content_get_memory(&mem_info, &ram, slot))
1826 return false;
1827
1828 RARCH_LOG("[SRAM]: %s #%u %s \"%s\".\n",
1829 msg_hash_to_str(MSG_SAVING_RAM_TYPE),
1830 ram.type,
1831 msg_hash_to_str(MSG_TO),
1832 ram.path);
1833
1834 #if defined(HAVE_ZLIB)
1835 if (compress)
1836 write_success = rzipstream_write_file(
1837 ram.path, mem_info.data, mem_info.size);
1838 else
1839 #endif
1840 write_success = filestream_write_file(
1841 ram.path, mem_info.data, mem_info.size);
1842
1843 if (!write_success)
1844 {
1845 RARCH_ERR("[SRAM]: %s.\n",
1846 msg_hash_to_str(MSG_FAILED_TO_SAVE_SRAM));
1847 RARCH_WARN("[SRAM]: Attempting to recover ...\n");
1848
1849 /* In case the file could not be written to,
1850 * the fallback function 'dump_to_file_desperate'
1851 * will be called. */
1852 if (!dump_to_file_desperate(
1853 mem_info.data, mem_info.size, ram.type))
1854 {
1855 RARCH_WARN("[SRAM]: Failed ... Cannot recover save file.\n");
1856 }
1857 return false;
1858 }
1859
1860 RARCH_LOG("[SRAM]: %s \"%s\".\n",
1861 msg_hash_to_str(MSG_SAVED_SUCCESSFULLY_TO),
1862 ram.path);
1863
1864 return true;
1865 }
1866
event_save_files(bool is_sram_used)1867 bool event_save_files(bool is_sram_used)
1868 {
1869 unsigned i;
1870 settings_t *settings = config_get_ptr();
1871 #ifdef HAVE_CHEATS
1872 const char *path_cheat_database = settings->paths.path_cheat_database;
1873 #endif
1874 #if defined(HAVE_ZLIB)
1875 bool compress_files = settings->bools.save_file_compression;
1876 #else
1877 bool compress_files = false;
1878 #endif
1879
1880 #ifdef HAVE_CHEATS
1881 cheat_manager_save_game_specific_cheats(
1882 path_cheat_database);
1883 #endif
1884 if (!task_save_files || !is_sram_used)
1885 return false;
1886
1887 for (i = 0; i < task_save_files->size; i++)
1888 content_save_ram_file(i, compress_files);
1889
1890 return true;
1891 }
1892
event_load_save_files(bool is_sram_load_disabled)1893 bool event_load_save_files(bool is_sram_load_disabled)
1894 {
1895 unsigned i;
1896
1897 if (!task_save_files || is_sram_load_disabled)
1898 return false;
1899
1900 for (i = 0; i < task_save_files->size; i++)
1901 content_load_ram_file(i);
1902
1903 return true;
1904 }
1905
path_init_savefile_rtc(const char * savefile_path)1906 void path_init_savefile_rtc(const char *savefile_path)
1907 {
1908 union string_list_elem_attr attr;
1909 char savefile_name_rtc[PATH_MAX_LENGTH];
1910
1911 savefile_name_rtc[0] = '\0';
1912
1913 attr.i = RETRO_MEMORY_SAVE_RAM;
1914 string_list_append(task_save_files, savefile_path, attr);
1915
1916 /* Infer .rtc save path from save ram path. */
1917 attr.i = RETRO_MEMORY_RTC;
1918 fill_pathname(savefile_name_rtc,
1919 savefile_path, ".rtc",
1920 sizeof(savefile_name_rtc));
1921 string_list_append(task_save_files, savefile_name_rtc, attr);
1922 }
1923
path_deinit_savefile(void)1924 void path_deinit_savefile(void)
1925 {
1926 if (task_save_files)
1927 string_list_free(task_save_files);
1928 task_save_files = NULL;
1929 }
1930
path_init_savefile_new(void)1931 void path_init_savefile_new(void)
1932 {
1933 task_save_files = string_list_new();
1934 retro_assert(task_save_files);
1935 }
1936
savefile_ptr_get(void)1937 void *savefile_ptr_get(void)
1938 {
1939 return task_save_files;
1940 }
1941
set_save_state_in_background(bool state)1942 void set_save_state_in_background(bool state)
1943 {
1944 save_state_in_background = state;
1945 }
1946