1 // Compatibility file functions
2
3 #include <libretro.h>
4 #include <externs.h>
5 #include <compat.h>
6 #include <ui/ui.h>
7 #include <utils.h>
8 #include <string.h>
9
10 #include <fuse/roms/48.h>
11 #include <fuse/roms/128-0.h>
12 #include <fuse/roms/128-1.h>
13 #include <fuse/roms/plus2-0.h>
14 #include <fuse/roms/plus2-1.h>
15 #include <fuse/roms/plus3-0.h>
16 #include <fuse/roms/plus3-1.h>
17 #include <fuse/roms/plus3-2.h>
18 #include <fuse/roms/plus3-3.h>
19 #include <fuse/roms/plus3e-0.h>
20 #include <fuse/roms/plus3e-1.h>
21 #include <fuse/roms/plus3e-2.h>
22 #include <fuse/roms/plus3e-3.h>
23 #include <fuse/roms/se-0.h>
24 #include <fuse/roms/se-1.h>
25 #include <fuse/roms/tc2048.h>
26 #include <fuse/roms/tc2068-0.h>
27 #include <fuse/roms/tc2068-1.h>
28
29 #include <fuse/lib/compressed/tape_16.h>
30 #include <fuse/lib/compressed/tape_48.h>
31 #include <fuse/lib/compressed/tape_48_ntsc.h>
32 #include <fuse/lib/compressed/tape_128.h>
33 #include <fuse/lib/compressed/tape_plus2.h>
34 #include <fuse/lib/compressed/tape_plus2a.h>
35 #include <fuse/lib/compressed/tape_plus3.h>
36 #include <fuse/lib/compressed/tape_plus3e.h>
37 #include <fuse/lib/compressed/tape_se.h>
38 #include <fuse/lib/compressed/tape_2048.h>
39 #include <fuse/lib/compressed/tape_2068.h>
40 #include <fuse/lib/compressed/tape_ts2068.h>
41 #include <fuse/lib/compressed/tape_pentagon.h>
42 #include <fuse/lib/compressed/tape_scorpion.h>
43
44 /* 4096 ought to be enough for anybody */
45 #define MAX_PATH_LEN 4096
46
47 typedef struct
48 {
49 const char *name;
50 const unsigned char* ptr;
51 size_t size;
52 }
53 entry_t;
54
55 static const entry_t mem_entries[] = {
56 { "48.rom", fuse_roms_48_rom, sizeof(fuse_roms_48_rom) },
57 { "128-0.rom", fuse_roms_128_0_rom, sizeof(fuse_roms_128_0_rom) },
58 { "128-1.rom", fuse_roms_128_1_rom, sizeof(fuse_roms_128_1_rom) },
59 { "plus2-0.rom", fuse_roms_plus2_0_rom, sizeof(fuse_roms_plus2_0_rom) },
60 { "plus2-1.rom", fuse_roms_plus2_1_rom, sizeof(fuse_roms_plus2_1_rom) },
61 { "plus3-0.rom", fuse_roms_plus3_0_rom, sizeof(fuse_roms_plus3_0_rom) },
62 { "plus3-1.rom", fuse_roms_plus3_1_rom, sizeof(fuse_roms_plus3_1_rom) },
63 { "plus3-2.rom", fuse_roms_plus3_2_rom, sizeof(fuse_roms_plus3_2_rom) },
64 { "plus3-3.rom", fuse_roms_plus3_3_rom, sizeof(fuse_roms_plus3_3_rom) },
65 { "plus3e-0.rom", fuse_roms_plus3e_0_rom, sizeof(fuse_roms_plus3e_0_rom) },
66 { "plus3e-1.rom", fuse_roms_plus3e_1_rom, sizeof(fuse_roms_plus3e_1_rom) },
67 { "plus3e-2.rom", fuse_roms_plus3e_2_rom, sizeof(fuse_roms_plus3e_2_rom) },
68 { "plus3e-3.rom", fuse_roms_plus3e_3_rom, sizeof(fuse_roms_plus3e_3_rom) },
69 { "se-0.rom", fuse_roms_se_0_rom, sizeof(fuse_roms_se_0_rom) },
70 { "se-1.rom", fuse_roms_se_1_rom, sizeof(fuse_roms_se_1_rom) },
71 { "tc2048.rom", fuse_roms_tc2048_rom, sizeof(fuse_roms_tc2048_rom) },
72 { "tc2068-0.rom", fuse_roms_tc2068_0_rom, sizeof(fuse_roms_tc2068_0_rom) },
73 { "tc2068-1.rom", fuse_roms_tc2068_1_rom, sizeof(fuse_roms_tc2068_1_rom) },
74
75 { "tape_16.szx", fuse_lib_compressed_tape_16_szx, sizeof(fuse_lib_compressed_tape_16_szx) },
76 { "tape_48.szx", fuse_lib_compressed_tape_48_szx, sizeof(fuse_lib_compressed_tape_48_szx) },
77 { "tape_48_ntsc.szx", fuse_lib_compressed_tape_48_ntsc_szx, sizeof(fuse_lib_compressed_tape_48_ntsc_szx) },
78 { "tape_128.szx", fuse_lib_compressed_tape_128_szx, sizeof(fuse_lib_compressed_tape_128_szx) },
79 { "tape_plus2.szx", fuse_lib_compressed_tape_plus2_szx, sizeof(fuse_lib_compressed_tape_plus2_szx) },
80 { "tape_plus2a.szx", fuse_lib_compressed_tape_plus2a_szx, sizeof(fuse_lib_compressed_tape_plus2a_szx) },
81 { "tape_plus3.szx", fuse_lib_compressed_tape_plus3_szx, sizeof(fuse_lib_compressed_tape_plus3_szx) },
82 { "tape_plus3e.szx", fuse_lib_compressed_tape_plus3e_szx, sizeof(fuse_lib_compressed_tape_plus3e_szx) },
83 { "tape_se.szx", fuse_lib_compressed_tape_se_szx, sizeof(fuse_lib_compressed_tape_se_szx) },
84 { "tape_2048.szx", fuse_lib_compressed_tape_2048_szx, sizeof(fuse_lib_compressed_tape_2048_szx) },
85 { "tape_2068.szx", fuse_lib_compressed_tape_2068_szx, sizeof(fuse_lib_compressed_tape_2068_szx) },
86 { "tape_ts2068.szx", fuse_lib_compressed_tape_ts2068_szx, sizeof(fuse_lib_compressed_tape_ts2068_szx) },
87 { "tape_pentagon.szx", fuse_lib_compressed_tape_pentagon_szx, sizeof(fuse_lib_compressed_tape_pentagon_szx) },
88 { "tape_scorpion.szx", fuse_lib_compressed_tape_scorpion_szx, sizeof(fuse_lib_compressed_tape_scorpion_szx) },
89 };
90
find_entry(const char * path)91 static const entry_t* find_entry(const char *path)
92 {
93 static entry_t tape;
94
95 int i;
96 size_t len = strlen(path);
97
98 // * signals us to load the tape data
99 if (path[0] == '*')
100 {
101 tape.name = NULL;
102 tape.ptr = (const unsigned char*)tape_data;
103 tape.size = tape_size;
104 return &tape;
105 }
106
107 for (i = 0; i < sizeof(mem_entries) / sizeof(mem_entries[0]); i++)
108 {
109 size_t len2 = strlen(mem_entries[i].name);
110
111 if (!strcmp(path + len - len2, mem_entries[i].name))
112 {
113 return mem_entries + i;
114 }
115 }
116
117 return NULL;
118 }
119
120 typedef struct
121 {
122 const char* ptr;
123 size_t length, remain;
124 }
125 compat_fd_internal;
126
127 const compat_fd COMPAT_FILE_OPEN_FAILED = NULL;
128
compat_file_open(const char * path,int write)129 compat_fd compat_file_open(const char *path, int write)
130 {
131 if (write)
132 {
133 log_cb(RETRO_LOG_ERROR, "Cannot open \"%s\" for writing\n", path);
134 return COMPAT_FILE_OPEN_FAILED;
135 }
136
137 compat_fd_internal *fd = (compat_fd_internal*)malloc(sizeof(compat_fd_internal));
138
139 if (!fd)
140 {
141 log_cb(RETRO_LOG_ERROR, "Out of memory while opening \"%s\"\n", path);
142 return COMPAT_FILE_OPEN_FAILED;
143 }
144
145 const entry_t* entry = find_entry(path);
146
147 if (entry != NULL)
148 {
149 fd->ptr = (const char*)entry->ptr;
150 fd->length = fd->remain = entry->size;
151
152 log_cb(RETRO_LOG_INFO, "Opened \"%s\" from memory\n", path);
153 return (compat_fd)fd;
154 }
155
156 log_cb(RETRO_LOG_INFO, "Could not find file \"%s\", trying file system\n", path);
157
158 const char *sys;
159
160 if (!env_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &sys) || !sys)
161 {
162 log_cb(RETRO_LOG_ERROR, "Error getting the system folder while opening \"%s\"\n", path);
163 free(fd);
164 return COMPAT_FILE_OPEN_FAILED;
165 }
166
167 char system[MAX_PATH_LEN];
168 strncpy(system, sys, MAX_PATH_LEN);
169 system[MAX_PATH_LEN - 1] = 0;
170
171 strncat(system, "/fuse", MAX_PATH_LEN);
172 system[MAX_PATH_LEN - 1] = 0;
173
174 strncat(system, path, MAX_PATH_LEN);
175 system[MAX_PATH_LEN - 1] = 0;
176
177 log_cb(RETRO_LOG_INFO, "Trying to open \"%s\" from the file system\n", system);
178 FILE* file = fopen(system, "rb");
179
180 if (!file)
181 {
182 log_cb(RETRO_LOG_ERROR, "Could not find file \"%s\" on the file system\n", system);
183 free(fd);
184 return COMPAT_FILE_OPEN_FAILED;
185 }
186
187 long size;
188
189 if (fseek(file, 0, SEEK_END) != 0 || (size = ftell(file)) < 0 || fseek(file, 0, SEEK_SET) != 0)
190 {
191 log_cb(RETRO_LOG_ERROR, "Could not determine size of \"%s\"\n", system);
192 fclose(file);
193 free(fd);
194 return COMPAT_FILE_OPEN_FAILED;
195 }
196
197 void* ptr = malloc(size);
198
199 if (!ptr)
200 {
201 log_cb(RETRO_LOG_ERROR, "Out of memory while opening \"%s\"\n", system);
202 fclose(file);
203 free(fd);
204 return COMPAT_FILE_OPEN_FAILED;
205 }
206
207 if (fread(ptr, 1, size, file) != size)
208 {
209 log_cb(RETRO_LOG_ERROR, "Error reading from \"%s\"\n", system);
210 free(ptr);
211 fclose(file);
212 free(fd);
213 return COMPAT_FILE_OPEN_FAILED;
214 }
215
216 fclose(file);
217
218 fd->ptr = (const char*)ptr;
219 fd->length = fd->remain = size;
220
221 log_cb(RETRO_LOG_INFO, "Opened \"%s\" from the file system\n", system);
222 return (compat_fd)fd;
223 }
224
compat_file_get_length(compat_fd cfd)225 off_t compat_file_get_length(compat_fd cfd)
226 {
227 compat_fd_internal *fd = (compat_fd_internal*)cfd;
228 return (off_t)fd->length;
229 }
230
compat_file_read(compat_fd cfd,utils_file * file)231 int compat_file_read(compat_fd cfd, utils_file *file)
232 {
233 compat_fd_internal *fd = (compat_fd_internal*)cfd;
234 size_t numread;
235
236 numread = file->length < fd->remain ? file->length : fd->remain;
237 memcpy(file->buffer, fd->ptr, numread);
238 fd->ptr += numread;
239 fd->remain -= numread;
240
241 if (numread == file->length)
242 {
243 return 0;
244 }
245
246 ui_error( UI_ERROR_ERROR,
247 "error reading file: expected %lu bytes, but read only %lu",
248 (unsigned long)file->length, (unsigned long)numread );
249 return 1;
250 }
251
compat_file_write(compat_fd cfd,const unsigned char * buffer,size_t length)252 int compat_file_write(compat_fd cfd, const unsigned char *buffer, size_t length)
253 {
254 (void)cfd;
255 (void)buffer;
256 (void)length;
257 return 1;
258 }
259
compat_file_close(compat_fd cfd)260 int compat_file_close(compat_fd cfd)
261 {
262 free(cfd);
263 return 0;
264 }
265
compat_file_exists(const char * path)266 int compat_file_exists(const char *path)
267 {
268 log_cb(RETRO_LOG_INFO, "Checking if \"%s\" exists\n", path);
269
270 int exists = 0;
271 compat_fd fd = compat_file_open(path, 0);
272
273 if (fd != COMPAT_FILE_OPEN_FAILED)
274 {
275 compat_file_close(fd);
276 exists = 1;
277 }
278
279 return exists;
280 }
281