1 #include "nvram.h"
2 #include "retro_callbacks.h"
3
4 #include <file/file_path.h>
5 #include <retro_endianness.h>
6 #include <retro_miscellaneous.h>
7 #include <streams/file_stream.h>
8
9 static char NVRAM_FILENAME[] = "3DO.nvram";
10
11 /*
12 At some point it'd be good to put the init code into a separate
13 module as part of the core emulator.
14 */
15 void
nvram_init(void * nvram_)16 nvram_init(void *nvram_)
17 {
18 struct NVRAM_Header *nvram_hdr = (struct NVRAM_Header*)nvram_;
19
20 memset(nvram_,0,sizeof(struct NVRAM_Header));
21
22 nvram_hdr->record_type = 0x01;
23 nvram_hdr->sync_bytes[0] = 'Z';
24 nvram_hdr->sync_bytes[1] = 'Z';
25 nvram_hdr->sync_bytes[2] = 'Z';
26 nvram_hdr->sync_bytes[3] = 'Z';
27 nvram_hdr->sync_bytes[4] = 'Z';
28 nvram_hdr->record_version = 0x02;
29 nvram_hdr->label[0] = 'N';
30 nvram_hdr->label[1] = 'V';
31 nvram_hdr->label[2] = 'R';
32 nvram_hdr->label[3] = 'A';
33 nvram_hdr->label[4] = 'M';
34 nvram_hdr->id = swap_if_little32(0xFFFFFFFF);
35 nvram_hdr->block_size = swap_if_little32(0x00000001);
36 nvram_hdr->block_count = swap_if_little32(0x00008000);
37 nvram_hdr->root_dir_id = swap_if_little32(0xFFFFFFFE);
38 nvram_hdr->root_dir_blocks = swap_if_little32(0x00000000);
39 nvram_hdr->root_dir_block_size = swap_if_little32(0x00000001);
40 nvram_hdr->last_root_dir_copy = swap_if_little32(0x00000000);
41 nvram_hdr->root_dir_copies[0] = swap_if_little32(0x00000084);
42 nvram_hdr->unknown_value0 = swap_if_little32(0x855A02B6);
43 nvram_hdr->unknown_value1 = swap_if_little32(0x00000098);
44 nvram_hdr->unknown_value2 = swap_if_little32(0x00000098);
45 nvram_hdr->unknown_value3 = swap_if_little32(0x00000014);
46 nvram_hdr->unknown_value4 = swap_if_little32(0x00000014);
47 nvram_hdr->unknown_value5 = swap_if_little32(0x7AA565BD);
48 nvram_hdr->unknown_value6 = swap_if_little32(0x00000084);
49 nvram_hdr->unknown_value7 = swap_if_little32(0x00000084);
50 nvram_hdr->blocks_remaining = swap_if_little32(0x00007F68);
51 nvram_hdr->unknown_value8 = swap_if_little32(0x00000014);
52 }
53
54 int
nvram_save(const void * nvram_,const size_t size_,const char * basepath_,const char * filename_)55 nvram_save(const void *nvram_,
56 const size_t size_,
57 const char *basepath_,
58 const char *filename_)
59 {
60 int rv;
61 char fullpath[PATH_MAX_LENGTH];
62 char fullpath_tmp[PATH_MAX_LENGTH];
63
64 fill_pathname_join(fullpath,basepath_,filename_,sizeof(fullpath));
65 strncpy(fullpath_tmp,fullpath,sizeof(fullpath_tmp));
66 strncat(fullpath_tmp,".tmp",sizeof(fullpath_tmp) - strlen(fullpath_tmp) - 1);
67
68 rv = filestream_write_file(fullpath_tmp,nvram_,size_);
69 if(rv == 0)
70 return -1;
71
72 rv = filestream_rename(fullpath_tmp,fullpath);
73 if(rv != 0)
74 {
75 filestream_delete(fullpath);
76 rv = filestream_rename(fullpath_tmp,fullpath);
77 }
78
79 return rv;
80 }
81
82 int
nvram_load(void * nvram_,const size_t size_,const char * basepath_,const char * filename_)83 nvram_load(void *nvram_,
84 const size_t size_,
85 const char *basepath_,
86 const char *filename_)
87 {
88 RFILE *f;
89 int64_t rv;
90 char fullpath[PATH_MAX_LENGTH];
91
92 fill_pathname_join(fullpath,basepath_,filename_,sizeof(fullpath));
93
94 f = filestream_open(fullpath,
95 RETRO_VFS_FILE_ACCESS_READ,
96 RETRO_VFS_FILE_ACCESS_HINT_NONE);
97 if(f == NULL)
98 return -1;
99
100 rv = filestream_read(f,nvram_,size_);
101
102 filestream_close(f);
103
104 return ((rv == size_) ? 0 : -1);
105 }
106
107 /*
108 Ideally there would be a core specific directory available
109 regardless content is loaded but for now we'll save to the system
110 directory.
111 */
112 void
retro_nvram_save(const uint8_t * nvram_)113 retro_nvram_save(const uint8_t *nvram_)
114 {
115 int rv;
116 const char *basepath;
117 struct retro_variable var;
118
119 rv = retro_environment_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY,&basepath);
120 if((rv == 0) || (basepath == NULL))
121 {
122 retro_log_printf_cb(RETRO_LOG_ERROR,
123 "[Opera]: unable to save %s - system directory unavailable",
124 NVRAM_FILENAME);
125 return;
126 }
127
128 rv = nvram_save(nvram_,NVRAM_SIZE,basepath,NVRAM_FILENAME);
129 if(rv)
130 retro_log_printf_cb(RETRO_LOG_ERROR,
131 "[Opera]: unknown error saving %s\n",
132 NVRAM_FILENAME);
133 }
134
135 void
retro_nvram_load(uint8_t * nvram_)136 retro_nvram_load(uint8_t *nvram_)
137 {
138 int rv;
139 const char *basepath;
140 struct retro_variable var;
141
142 rv = retro_environment_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY,&basepath);
143 if((rv == 0) || (basepath == NULL))
144 {
145 retro_log_printf_cb(RETRO_LOG_ERROR,
146 "[Opera]: unable to load %s - system directory unavailable",
147 NVRAM_FILENAME);
148 return;
149 }
150
151 rv = nvram_load(nvram_,NVRAM_SIZE,basepath,NVRAM_FILENAME);
152 if(rv)
153 retro_log_printf_cb(RETRO_LOG_ERROR,
154 "[Opera]: unknown error loading %s\n",
155 NVRAM_FILENAME);
156 }
157