1 /*
2 * easyflash.c - Cartridge handling of the easyflash cart.
3 *
4 * Written by
5 * ALeX Kazik <alx@kazik.de>
6 * Marco van den Heuvel <blackystardust68@yahoo.com>
7 *
8 * This file is part of VICE, the Versatile Commodore Emulator.
9 * See README for copyright notice.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
24 * 02111-1307 USA.
25 *
26 */
27
28 #include "vice.h"
29
30 #include <stdio.h>
31 #include <string.h>
32
33 #include "archdep.h"
34 #define CARTRIDGE_INCLUDE_SLOTMAIN_API
35 #include "c64cartsystem.h"
36 #undef CARTRIDGE_INCLUDE_SLOTMAIN_API
37 #include "c64mem.h"
38 #include "cartio.h"
39 #include "cartridge.h"
40 #include "cmdline.h"
41 #include "crt.h"
42 #include "easyflash.h"
43 #include "export.h"
44 #include "flash040.h"
45 #include "lib.h"
46 #include "log.h"
47 #include "maincpu.h"
48 #include "mem.h"
49 #include "monitor.h"
50 #include "resources.h"
51 #include "snapshot.h"
52 #include "util.h"
53
54 #define EASYFLASH_N_BANK_BITS 6
55 #define EASYFLASH_N_BANKS (1 << (EASYFLASH_N_BANK_BITS))
56 #define EASYFLASH_BANK_MASK ((EASYFLASH_N_BANKS) -1)
57
58 /* the 29F040B statemachine */
59 static flash040_context_t *easyflash_state_low = NULL;
60 static flash040_context_t *easyflash_state_high = NULL;
61
62 /* the jumper */
63 static int easyflash_jumper;
64
65 /* writing back to crt enabled */
66 static int easyflash_crt_write;
67
68 /* optimizing crt enabled */
69 static int easyflash_crt_optimize;
70
71 /* backup of the registers */
72 static uint8_t easyflash_register_00, easyflash_register_02;
73
74 /* decoding table of the modes */
75 static const uint8_t easyflash_memconfig[] = {
76 /* bit3 = jumper, bit2 = mode, bit1 = !exrom, bit0 = game */
77
78 /* jumper off, mode 0, trough 00,01,10,11 in game/exrom bits */
79 3, /* exrom high, game low, jumper off */
80 3, /* Reserved, don't use this */
81 1, /* exrom low, game low, jumper off */
82 1, /* Reserved, don't use this */
83
84 /* jumper off, mode 1, trough 00,01,10,11 in game/exrom bits */
85 2, 3, 0, 1,
86
87 /* jumper on, mode 0, trough 00,01,10,11 in game/exrom bits */
88 2, /* exrom high, game low, jumper on */
89 3, /* Reserved, don't use this */
90 0, /* exrom low, game low, jumper on */
91 1, /* Reserved, don't use this */
92
93 /* jumper on, mode 1, trough 00,01,10,11 in game/exrom bits */
94 2, 3, 0, 1,
95 };
96
97 /* extra RAM */
98 static uint8_t easyflash_ram[256];
99
100 /* filename when attached */
101 static char *easyflash_filename = NULL;
102 static int easyflash_filetype = 0;
103
104 static const char STRING_EASYFLASH[] = CARTRIDGE_NAME_EASYFLASH;
105
106 static const unsigned char eapiam29f040[768] = {
107 0x65, 0x61, 0x70, 0x69, 0xc1, 0x4d,
108 0x2f, 0xcd, 0x32, 0x39, 0xc6, 0x30, 0x34, 0x30,
109 0x20, 0xd6, 0x31, 0x2e, 0x34, 0x00, 0x08, 0x78,
110 0xa5, 0x4b, 0x48, 0xa5, 0x4c, 0x48, 0xa9, 0x60,
111 0x85, 0x4b, 0x20, 0x4b, 0x00, 0xba, 0xbd, 0x00,
112 0x01, 0x85, 0x4c, 0xca, 0xbd, 0x00, 0x01, 0x85,
113 0x4b, 0x18, 0x90, 0x70, 0x4c, 0x67, 0x01, 0x4c,
114 0xa4, 0x01, 0x4c, 0x39, 0x02, 0x4c, 0x40, 0x02,
115 0x4c, 0x44, 0x02, 0x4c, 0x4e, 0x02, 0x4c, 0x58,
116 0x02, 0x4c, 0x8e, 0x02, 0x4c, 0xd9, 0x02, 0x4c,
117 0xd9, 0x02, 0x8d, 0x02, 0xde, 0xa9, 0xaa, 0x8d,
118 0x55, 0x85, 0xa9, 0x55, 0x8d, 0xaa, 0x82, 0xa9,
119 0xa0, 0x8d, 0x55, 0x85, 0xad, 0xf2, 0xdf, 0x8d,
120 0x00, 0xde, 0xa9, 0x00, 0x8d, 0xff, 0xff, 0xa2,
121 0x07, 0x8e, 0x02, 0xde, 0x60, 0x8d, 0x02, 0xde,
122 0xa9, 0xaa, 0x8d, 0x55, 0xe5, 0xa9, 0x55, 0x8d,
123 0xaa, 0xe2, 0xa9, 0xa0, 0x8d, 0x55, 0xe5, 0xd0,
124 0xdb, 0xa2, 0x55, 0x8e, 0xe3, 0xdf, 0x8c, 0xe4,
125 0xdf, 0xa2, 0x85, 0x8e, 0x02, 0xde, 0x8d, 0xff,
126 0xff, 0x4c, 0xbb, 0xdf, 0xad, 0xff, 0xff, 0x60,
127 0xcd, 0xff, 0xff, 0x60, 0xa2, 0x6f, 0xa0, 0x7f,
128 0xb1, 0x4b, 0x9d, 0x80, 0xdf, 0xdd, 0x80, 0xdf,
129 0xd0, 0x21, 0x88, 0xca, 0x10, 0xf2, 0xa2, 0x00,
130 0xe8, 0x18, 0xbd, 0x80, 0xdf, 0x65, 0x4b, 0x9d,
131 0x80, 0xdf, 0xe8, 0xbd, 0x80, 0xdf, 0x65, 0x4c,
132 0x9d, 0x80, 0xdf, 0xe8, 0xe0, 0x1e, 0xd0, 0xe8,
133 0x18, 0x90, 0x06, 0xa9, 0x01, 0x8d, 0xb9, 0xdf,
134 0x38, 0x68, 0x85, 0x4c, 0x68, 0x85, 0x4b, 0xb0,
135 0x48, 0xa9, 0xaa, 0xa0, 0xe5, 0x20, 0xd5, 0xdf,
136 0xa0, 0x85, 0x20, 0xd5, 0xdf, 0xa9, 0x55, 0xa2,
137 0xaa, 0xa0, 0xe2, 0x20, 0xd7, 0xdf, 0xa2, 0xaa,
138 0xa0, 0x82, 0x20, 0xd7, 0xdf, 0xa9, 0x90, 0xa0,
139 0xe5, 0x20, 0xd5, 0xdf, 0xa0, 0x85, 0x20, 0xd5,
140 0xdf, 0xad, 0x00, 0xa0, 0x8d, 0xf1, 0xdf, 0xae,
141 0x01, 0xa0, 0x8e, 0xb9, 0xdf, 0xc9, 0x01, 0xd0,
142 0x06, 0xe0, 0xa4, 0xd0, 0x02, 0xf0, 0x0c, 0xc9,
143 0x20, 0xd0, 0x39, 0xe0, 0xe2, 0xd0, 0x35, 0xf0,
144 0x02, 0xb0, 0x50, 0xad, 0x00, 0x80, 0xae, 0x01,
145 0x80, 0xc9, 0x01, 0xd0, 0x06, 0xe0, 0xa4, 0xd0,
146 0x02, 0xf0, 0x08, 0xc9, 0x20, 0xd0, 0x19, 0xe0,
147 0xe2, 0xd0, 0x15, 0xa0, 0x3f, 0x8c, 0x00, 0xde,
148 0xae, 0x02, 0x80, 0xd0, 0x13, 0xae, 0x02, 0xa0,
149 0xd0, 0x12, 0x88, 0x10, 0xf0, 0x18, 0x90, 0x12,
150 0xa9, 0x02, 0xd0, 0x0a, 0xa9, 0x03, 0xd0, 0x06,
151 0xa9, 0x04, 0xd0, 0x02, 0xa9, 0x05, 0x8d, 0xb9,
152 0xdf, 0x38, 0xa9, 0x00, 0x8d, 0x00, 0xde, 0xa0,
153 0xe0, 0xa9, 0xf0, 0x20, 0xd7, 0xdf, 0xa0, 0x80,
154 0x20, 0xd7, 0xdf, 0xad, 0xb9, 0xdf, 0xb0, 0x08,
155 0xae, 0xf1, 0xdf, 0xa0, 0x40, 0x28, 0x18, 0x60,
156 0x28, 0x38, 0x60, 0x8d, 0xb7, 0xdf, 0x8e, 0xb9,
157 0xdf, 0x8e, 0xed, 0xdf, 0x8c, 0xba, 0xdf, 0x08,
158 0x78, 0x98, 0x29, 0xbf, 0x8d, 0xee, 0xdf, 0xa9,
159 0x00, 0x8d, 0x00, 0xde, 0xa9, 0x85, 0xc0, 0xe0,
160 0x90, 0x05, 0x20, 0xc1, 0xdf, 0xb0, 0x03, 0x20,
161 0x9e, 0xdf, 0xa2, 0x14, 0x20, 0xec, 0xdf, 0xf0,
162 0x06, 0xca, 0xd0, 0xf8, 0x18, 0x90, 0x63, 0xad,
163 0xf2, 0xdf, 0x8d, 0x00, 0xde, 0x18, 0x90, 0x72,
164 0x8d, 0xb7, 0xdf, 0x8e, 0xb9, 0xdf, 0x8c, 0xba,
165 0xdf, 0x08, 0x78, 0x98, 0xc0, 0x80, 0xf0, 0x04,
166 0xa0, 0xe0, 0xa9, 0xa0, 0x8d, 0xee, 0xdf, 0xc8,
167 0xc8, 0xc8, 0xc8, 0xc8, 0xa9, 0xaa, 0x20, 0xd5,
168 0xdf, 0xa9, 0x55, 0xa2, 0xaa, 0x88, 0x88, 0x88,
169 0x20, 0xd7, 0xdf, 0xa9, 0x80, 0xc8, 0xc8, 0xc8,
170 0x20, 0xd5, 0xdf, 0xa9, 0xaa, 0x20, 0xd5, 0xdf,
171 0xa9, 0x55, 0xa2, 0xaa, 0x88, 0x88, 0x88, 0x20,
172 0xd7, 0xdf, 0xad, 0xb7, 0xdf, 0x8d, 0x00, 0xde,
173 0xa2, 0x00, 0x8e, 0xed, 0xdf, 0x88, 0x88, 0xa9,
174 0x30, 0x20, 0xd7, 0xdf, 0xa9, 0xff, 0xaa, 0xa8,
175 0xd0, 0x24, 0xad, 0xf2, 0xdf, 0x8d, 0x00, 0xde,
176 0xa0, 0x80, 0xa9, 0xf0, 0x20, 0xd7, 0xdf, 0xa0,
177 0xe0, 0xa9, 0xf0, 0x20, 0xd7, 0xdf, 0x28, 0x38,
178 0xb0, 0x02, 0x28, 0x18, 0xac, 0xba, 0xdf, 0xae,
179 0xb9, 0xdf, 0xad, 0xb7, 0xdf, 0x60, 0x20, 0xec,
180 0xdf, 0xf0, 0x09, 0xca, 0xd0, 0xf8, 0x88, 0xd0,
181 0xf5, 0x18, 0x90, 0xce, 0xad, 0xf2, 0xdf, 0x8d,
182 0x00, 0xde, 0x18, 0x90, 0xdd, 0x8d, 0xf2, 0xdf,
183 0x8d, 0x00, 0xde, 0x60, 0xad, 0xf2, 0xdf, 0x60,
184 0x8d, 0xf3, 0xdf, 0x8e, 0xe9, 0xdf, 0x8c, 0xea,
185 0xdf, 0x60, 0x8e, 0xf4, 0xdf, 0x8c, 0xf5, 0xdf,
186 0x8d, 0xf6, 0xdf, 0x60, 0xad, 0xf2, 0xdf, 0x8d,
187 0x00, 0xde, 0x20, 0xe8, 0xdf, 0x8d, 0xb7, 0xdf,
188 0x8e, 0xf0, 0xdf, 0x8c, 0xf1, 0xdf, 0xa9, 0x00,
189 0x8d, 0xba, 0xdf, 0xf0, 0x3b, 0xad, 0xf4, 0xdf,
190 0xd0, 0x10, 0xad, 0xf5, 0xdf, 0xd0, 0x08, 0xad,
191 0xf6, 0xdf, 0xf0, 0x0b, 0xce, 0xf6, 0xdf, 0xce,
192 0xf5, 0xdf, 0xce, 0xf4, 0xdf, 0x90, 0x45, 0x38,
193 0xb0, 0x42, 0x8d, 0xb7, 0xdf, 0x8e, 0xf0, 0xdf,
194 0x8c, 0xf1, 0xdf, 0xae, 0xe9, 0xdf, 0xad, 0xea,
195 0xdf, 0xc9, 0xa0, 0x90, 0x02, 0x09, 0x40, 0xa8,
196 0xad, 0xb7, 0xdf, 0x20, 0x80, 0xdf, 0xb0, 0x24,
197 0xee, 0xe9, 0xdf, 0xd0, 0x19, 0xee, 0xea, 0xdf,
198 0xad, 0xf3, 0xdf, 0x29, 0xe0, 0xcd, 0xea, 0xdf,
199 0xd0, 0x0c, 0xad, 0xf3, 0xdf, 0x0a, 0x0a, 0x0a,
200 0x8d, 0xea, 0xdf, 0xee, 0xf2, 0xdf, 0x18, 0xad,
201 0xba, 0xdf, 0xf0, 0xa1, 0xac, 0xf1, 0xdf, 0xae,
202 0xf0, 0xdf, 0xad, 0xb7, 0xdf, 0x60, 0xff, 0xff,
203 0xff, 0xff
204 };
205
206 /* ---------------------------------------------------------------------*/
207
easyflash_io1_store(uint16_t addr,uint8_t value)208 static void easyflash_io1_store(uint16_t addr, uint8_t value)
209 {
210 uint8_t mem_mode;
211
212 switch (addr & 2) {
213 case 0:
214 /* bank register */
215 easyflash_register_00 = (uint8_t)(value & EASYFLASH_BANK_MASK);
216 break;
217 default:
218 /* mode register */
219 easyflash_register_02 = value & 0x87; /* we only remember led, mode, exrom, game */
220 mem_mode = easyflash_memconfig[(easyflash_jumper << 3) | (easyflash_register_02 & 0x07)];
221 cart_config_changed_slotmain(mem_mode, mem_mode, CMODE_READ);
222 /* TODO: change led */
223 /* (value & 0x80) -> led on if true, led off if false */
224 }
225 cart_romhbank_set_slotmain(easyflash_register_00);
226 cart_romlbank_set_slotmain(easyflash_register_00);
227 cart_port_config_changed_slotmain();
228 }
229
easyflash_io2_read(uint16_t addr)230 static uint8_t easyflash_io2_read(uint16_t addr)
231 {
232 return easyflash_ram[addr & 0xff];
233 }
234
easyflash_io2_store(uint16_t addr,uint8_t value)235 static void easyflash_io2_store(uint16_t addr, uint8_t value)
236 {
237 easyflash_ram[addr & 0xff] = value;
238 }
239
240 /* ---------------------------------------------------------------------*/
241
easyflash_io1_peek(uint16_t addr)242 static uint8_t easyflash_io1_peek(uint16_t addr)
243 {
244 return (addr & 2) ? easyflash_register_02 : easyflash_register_00;
245 }
246
easyflash_io1_dump(void)247 static int easyflash_io1_dump(void)
248 {
249 mon_out("Mode: %s, Bank: %d, LED %s, jumper %s\n",
250 cart_config_string(easyflash_memconfig[(easyflash_jumper << 3) | (easyflash_register_02 & 0x07)]),
251 easyflash_register_00,
252 (easyflash_register_02 & 0x80) ? "on" : "off",
253 easyflash_jumper ? "on" : "off");
254 mon_out("EAPI found: %s\n", (memcmp(&romh_banks[0x1800], "eapi", 4) == 0) ? "yes" : "no");
255 return 0;
256 }
257
258 /* ---------------------------------------------------------------------*/
259
260 static io_source_t easyflash_io1_device = {
261 CARTRIDGE_NAME_EASYFLASH, /* name of the device */
262 IO_DETACH_CART, /* use cartridge ID to detach the device when involved in a read-collision */
263 IO_DETACH_NO_RESOURCE, /* does not use a resource for detach */
264 0xde00, 0xdeff, 0x03, /* range for the device, regs:$de00-$de03, mirrors:$de04-$deff */
265 0, /* read is never valid, regs are write only */
266 easyflash_io1_store, /* store function */
267 NULL, /* NO poke function */
268 NULL, /* NO read function */
269 easyflash_io1_peek, /* peek function */
270 easyflash_io1_dump, /* device state information dump function */
271 CARTRIDGE_EASYFLASH, /* cartridge ID */
272 IO_PRIO_NORMAL, /* normal priority, device read needs to be checked for collisions */
273 0 /* insertion order, gets filled in by the registration function */
274 };
275
276 static io_source_t easyflash_io2_device = {
277 CARTRIDGE_NAME_EASYFLASH, /* name of the device */
278 IO_DETACH_CART, /* use cartridge ID to detach the device when involved in a read-collision */
279 IO_DETACH_NO_RESOURCE, /* does not use a resource for detach */
280 0xdf00, 0xdfff, 0xff, /* range for the device, regs:$df00-$dfff */
281 1, /* read is always valid */
282 easyflash_io2_store, /* store function */
283 NULL, /* NO poke function */
284 easyflash_io2_read, /* read function */
285 easyflash_io2_read, /* peek function, same implementation */
286 NULL, /* device state information dump function */
287 CARTRIDGE_EASYFLASH, /* cartridge ID */
288 IO_PRIO_NORMAL, /* normal priority, device read needs to be checked for collisions */
289 0 /* insertion order, gets filled in by the registration function */
290 };
291
292 static io_source_list_t *easyflash_io1_list_item = NULL;
293 static io_source_list_t *easyflash_io2_list_item = NULL;
294
295 static const export_resource_t export_res = {
296 CARTRIDGE_NAME_EASYFLASH, 1, 1, &easyflash_io1_device, &easyflash_io2_device, CARTRIDGE_EASYFLASH
297 };
298
299 /* ---------------------------------------------------------------------*/
300
set_easyflash_jumper(int val,void * param)301 static int set_easyflash_jumper(int val, void *param)
302 {
303 easyflash_jumper = val ? 1 : 0;
304 return 0;
305 }
306
set_easyflash_crt_write(int val,void * param)307 static int set_easyflash_crt_write(int val, void *param)
308 {
309 easyflash_crt_write = val ? 1 : 0;
310 return 0;
311 }
312
set_easyflash_crt_optimize(int val,void * param)313 static int set_easyflash_crt_optimize(int val, void *param)
314 {
315 easyflash_crt_optimize = val ? 1 : 0;
316 return 0;
317 }
318
easyflash_write_chip_if_not_empty(FILE * fd,crt_chip_header_t * chip,uint8_t * data)319 static int easyflash_write_chip_if_not_empty(FILE* fd, crt_chip_header_t *chip, uint8_t *data)
320 {
321 int i;
322
323 for (i = 0; i < chip->size; i++) {
324 if ((data[i] != 0xff) || (easyflash_crt_optimize == 0)) {
325 if (crt_write_chip(data, chip, fd)) {
326 return -1;
327 }
328 return 0;
329 }
330 }
331 return 0;
332 }
333
334 /* ---------------------------------------------------------------------*/
335
336 static const resource_int_t resources_int[] = {
337 { "EasyFlashJumper", 0, RES_EVENT_STRICT, (resource_value_t)0,
338 &easyflash_jumper, set_easyflash_jumper, NULL },
339 { "EasyFlashWriteCRT", 1, RES_EVENT_STRICT, (resource_value_t)0,
340 &easyflash_crt_write, set_easyflash_crt_write, NULL },
341 { "EasyFlashOptimizeCRT", 1, RES_EVENT_STRICT, (resource_value_t)1,
342 &easyflash_crt_optimize, set_easyflash_crt_optimize, NULL },
343 RESOURCE_INT_LIST_END
344 };
345
easyflash_resources_init(void)346 int easyflash_resources_init(void)
347 {
348 return resources_register_int(resources_int);
349 }
350
easyflash_resources_shutdown(void)351 void easyflash_resources_shutdown(void)
352 {
353 }
354
355 /* ---------------------------------------------------------------------*/
356
357 static const cmdline_option_t cmdline_options[] =
358 {
359 { "-easyflashjumper", SET_RESOURCE, CMDLINE_ATTRIB_NONE,
360 NULL, NULL, "EasyFlashJumper", (resource_value_t)1,
361 NULL, "Enable EasyFlash jumper" },
362 { "+easyflashjumper", SET_RESOURCE, CMDLINE_ATTRIB_NONE,
363 NULL, NULL, "EasyFlashJumper", (resource_value_t)0,
364 NULL, "Disable EasyFlash jumper" },
365 { "-easyflashcrtwrite", SET_RESOURCE, CMDLINE_ATTRIB_NONE,
366 NULL, NULL, "EasyFlashWriteCRT", (resource_value_t)1,
367 NULL, "Enable writing to EasyFlash .crt image" },
368 { "+easyflashcrtwrite", SET_RESOURCE, CMDLINE_ATTRIB_NONE,
369 NULL, NULL, "EasyFlashWriteCRT", (resource_value_t)0,
370 NULL, "Disable writing to EasyFlash .crt image" },
371 { "-easyflashcrtoptimize", SET_RESOURCE, CMDLINE_ATTRIB_NONE,
372 NULL, NULL, "EasyFlashOptimizeCRT", (resource_value_t)1,
373 NULL, "Enable EasyFlash .crt image optimize on write" },
374 { "+easyflashcrtoptimize", SET_RESOURCE, CMDLINE_ATTRIB_NONE,
375 NULL, NULL, "EasyFlashOptimizeCRT", (resource_value_t)0,
376 NULL, "Disable writing to EasyFlash .crt image" },
377 CMDLINE_LIST_END
378 };
379
easyflash_cmdline_options_init(void)380 int easyflash_cmdline_options_init(void)
381 {
382 return cmdline_register_options(cmdline_options);
383 }
384
385 /* ---------------------------------------------------------------------*/
386
easyflash_roml_read(uint16_t addr)387 uint8_t easyflash_roml_read(uint16_t addr)
388 {
389 return flash040core_read(easyflash_state_low, (easyflash_register_00 * 0x2000) + (addr & 0x1fff));
390 }
391
easyflash_roml_store(uint16_t addr,uint8_t value)392 void easyflash_roml_store(uint16_t addr, uint8_t value)
393 {
394 flash040core_store(easyflash_state_low, (easyflash_register_00 * 0x2000) + (addr & 0x1fff), value);
395 }
396
easyflash_romh_read(uint16_t addr)397 uint8_t easyflash_romh_read(uint16_t addr)
398 {
399 return flash040core_read(easyflash_state_high, (easyflash_register_00 * 0x2000) + (addr & 0x1fff));
400 }
401
easyflash_romh_store(uint16_t addr,uint8_t value)402 void easyflash_romh_store(uint16_t addr, uint8_t value)
403 {
404 flash040core_store(easyflash_state_high, (easyflash_register_00 * 0x2000) + (addr & 0x1fff), value);
405 }
406
easyflash_mmu_translate(unsigned int addr,uint8_t ** base,int * start,int * limit)407 void easyflash_mmu_translate(unsigned int addr, uint8_t **base, int *start, int *limit)
408 {
409 if (easyflash_state_high && easyflash_state_high->flash_data &&
410 easyflash_state_low && easyflash_state_low->flash_data) {
411 switch (addr & 0xe000) {
412 case 0xe000:
413 if (easyflash_state_high->flash_state == FLASH040_STATE_READ) {
414 *base = easyflash_state_high->flash_data + (easyflash_register_00 * 0x2000) - 0xe000;
415 *start = 0xe000;
416 *limit = 0xfffd;
417 return;
418 }
419 break;
420 case 0xa000:
421 if (easyflash_state_high->flash_state == FLASH040_STATE_READ) {
422 *base = easyflash_state_high->flash_data + (easyflash_register_00 * 0x2000) - 0xa000;
423 *start = 0xa000;
424 *limit = 0xbffd;
425 return;
426 }
427 break;
428 case 0x8000:
429 if (easyflash_state_low->flash_state == FLASH040_STATE_READ) {
430 *base = easyflash_state_low->flash_data + (easyflash_register_00 * 0x2000) - 0x8000;
431 *start = 0x8000;
432 *limit = 0x9ffd;
433 return;
434 }
435 break;
436 default:
437 break;
438 }
439 }
440 *base = NULL;
441 *start = 0;
442 *limit = 0;
443 }
444
445 /* ---------------------------------------------------------------------*/
446
easyflash_config_init(void)447 void easyflash_config_init(void)
448 {
449 easyflash_io1_store((uint16_t)0xde00, 0);
450 easyflash_io1_store((uint16_t)0xde02, 0);
451 }
452
easyflash_config_setup(uint8_t * rawcart)453 void easyflash_config_setup(uint8_t *rawcart)
454 {
455 int i;
456
457 easyflash_state_low = lib_malloc(sizeof(flash040_context_t));
458 easyflash_state_high = lib_malloc(sizeof(flash040_context_t));
459
460 flash040core_init(easyflash_state_low, maincpu_alarm_context, FLASH040_TYPE_B, roml_banks);
461 flash040core_init(easyflash_state_high, maincpu_alarm_context, FLASH040_TYPE_B, romh_banks);
462
463 for (i = 0; i < EASYFLASH_N_BANKS; i++) { /* split interleaved low and high banks */
464 memcpy(easyflash_state_low->flash_data + i * 0x2000, rawcart + i * 0x4000, 0x2000);
465 memcpy(easyflash_state_high->flash_data + i * 0x2000, rawcart + i * 0x4000 + 0x2000, 0x2000);
466 }
467 /* fill easyflash ram with startup value(s). this shall not be zeros, see
468 * http://sourceforge.net/p/vice-emu/bugs/469/
469 *
470 * FIXME: the real hardware likely behaves somewhat differently
471 */
472 memset(easyflash_ram, 0xff, 256);
473 /*
474 * check for presence of EAPI
475 */
476 if (memcmp(&romh_banks[0x1800], "eapi", 4) == 0) {
477 char eapi[17];
478 int k;
479 for (k = 0; k < 16; k++) {
480 eapi[k] = romh_banks[0x1804 + k] & 0x7f;
481 }
482 eapi[k] = 0;
483 log_message(LOG_DEFAULT, "EF: EAPI found (%s)", eapi);
484 memcpy(romh_banks + 0x1800, eapiam29f040, 768);
485 } else {
486 log_warning(LOG_DEFAULT, "EF: EAPI not found! Are you sure this is a proper EasyFlash image?");
487 }
488 }
489
490 /* ---------------------------------------------------------------------*/
491
easyflash_common_attach(const char * filename)492 static int easyflash_common_attach(const char *filename)
493 {
494 if (export_add(&export_res) < 0) {
495 return -1;
496 }
497
498 easyflash_io1_list_item = io_source_register(&easyflash_io1_device);
499 easyflash_io2_list_item = io_source_register(&easyflash_io2_device);
500
501 easyflash_filename = lib_strdup(filename);
502
503 return 0;
504 }
505
easyflash_bin_attach(const char * filename,uint8_t * rawcart)506 int easyflash_bin_attach(const char *filename, uint8_t *rawcart)
507 {
508 easyflash_filetype = 0;
509
510 if (util_file_load(filename, rawcart, 0x4000 * EASYFLASH_N_BANKS, UTIL_FILE_LOAD_SKIP_ADDRESS) < 0) {
511 return -1;
512 }
513
514 easyflash_filetype = CARTRIDGE_FILETYPE_BIN;
515 return easyflash_common_attach(filename);
516 }
517
easyflash_crt_attach(FILE * fd,uint8_t * rawcart,const char * filename)518 int easyflash_crt_attach(FILE *fd, uint8_t *rawcart, const char *filename)
519 {
520 crt_chip_header_t chip;
521
522 easyflash_filetype = 0;
523 memset(rawcart, 0xff, 0x100000); /* empty flash */
524
525 while (1) {
526 if (crt_read_chip_header(&chip, fd)) {
527 break;
528 }
529
530 if (chip.size == 0x2000) {
531 if (chip.bank >= EASYFLASH_N_BANKS || !(chip.start == 0x8000 || chip.start == 0xa000 || chip.start == 0xe000)) {
532 return -1;
533 }
534 if (crt_read_chip(rawcart, (chip.bank << 14) | (chip.start & 0x2000), &chip, fd)) {
535 return -1;
536 }
537 } else if (chip.size == 0x4000) {
538 if (chip.bank >= EASYFLASH_N_BANKS || chip.start != 0x8000) {
539 return -1;
540 }
541 if (crt_read_chip(rawcart, chip.bank << 14, &chip, fd)) {
542 return -1;
543 }
544 } else {
545 return -1;
546 }
547 }
548
549 easyflash_filetype = CARTRIDGE_FILETYPE_CRT;
550 return easyflash_common_attach(filename);
551 }
552
easyflash_detach(void)553 void easyflash_detach(void)
554 {
555 if (easyflash_crt_write) {
556 easyflash_flush_image();
557 }
558 flash040core_shutdown(easyflash_state_low);
559 flash040core_shutdown(easyflash_state_high);
560 lib_free(easyflash_state_low);
561 lib_free(easyflash_state_high);
562 lib_free(easyflash_filename);
563 easyflash_filename = NULL;
564 io_source_unregister(easyflash_io1_list_item);
565 io_source_unregister(easyflash_io2_list_item);
566 easyflash_io1_list_item = NULL;
567 easyflash_io2_list_item = NULL;
568 export_remove(&export_res);
569 }
570
easyflash_flush_image(void)571 int easyflash_flush_image(void)
572 {
573 if (easyflash_filename != NULL) {
574 if (easyflash_filetype == CARTRIDGE_FILETYPE_BIN) {
575 return easyflash_bin_save(easyflash_filename);
576 } else if (easyflash_filetype == CARTRIDGE_FILETYPE_CRT) {
577 return easyflash_crt_save(easyflash_filename);
578 }
579 return -1;
580 }
581 return -2;
582 }
583
easyflash_bin_save(const char * filename)584 int easyflash_bin_save(const char *filename)
585 {
586 FILE *fd;
587 int i;
588 uint8_t *low;
589 uint8_t *high;
590
591 if (filename == NULL) {
592 return -1;
593 }
594
595 fd = fopen(filename, MODE_WRITE);
596
597 if (fd == NULL) {
598 return -1;
599 }
600
601 low = easyflash_state_low->flash_data;
602 high = easyflash_state_high->flash_data;
603
604 for (i = 0; i < EASYFLASH_N_BANKS; i++, low += 0x2000, high += 0x2000) {
605 if ((fwrite(low, 1, 0x2000, fd) != 0x2000) || (fwrite(high, 1, 0x2000, fd) != 0x2000)) {
606 fclose(fd);
607 return -1;
608 }
609 }
610
611 fclose(fd);
612 return 0;
613 }
614
easyflash_crt_save(const char * filename)615 int easyflash_crt_save(const char *filename)
616 {
617 FILE *fd;
618 crt_chip_header_t chip;
619 uint8_t *data;
620 int bank;
621
622 fd = crt_create(filename, CARTRIDGE_EASYFLASH, 1, 0, STRING_EASYFLASH);
623
624 if (fd == NULL) {
625 return -1;
626 }
627
628 chip.type = 2;
629 chip.size = 0x2000;
630
631 for (bank = 0; bank < EASYFLASH_N_BANKS; bank++) {
632 chip.bank = bank;
633
634 data = easyflash_state_low->flash_data + bank * 0x2000;
635 chip.start = 0x8000;
636 if (easyflash_write_chip_if_not_empty(fd, &chip, data) != 0) {
637 fclose(fd);
638 return -1;
639 }
640
641 data = easyflash_state_high->flash_data + bank * 0x2000;
642 chip.start = 0xa000;
643 if (easyflash_write_chip_if_not_empty(fd, &chip, data) != 0) {
644 fclose(fd);
645 return -1;
646 }
647 }
648 fclose(fd);
649 return 0;
650 }
651
652 /* ---------------------------------------------------------------------*/
653
654 /* CARTEF snapshot module format:
655
656 type | name | description
657 --------------------------------
658 BYTE | jumper | jumper
659 BYTE | register 0 | register 0
660 BYTE | register 2 | register 2
661 ARRAY | RAM | 256 BYTES of RAM data
662 ARRAY | ROML | 524288 BYTES of ROML data
663 ARRAY | ROMH | 524288 BYTES of ROMH data
664 */
665
666 static const char snap_module_name[] = "CARTEF";
667 static const char flash_snap_module_name[] = "FLASH040EF";
668 #define SNAP_MAJOR 0
669 #define SNAP_MINOR 0
670
easyflash_snapshot_write_module(snapshot_t * s)671 int easyflash_snapshot_write_module(snapshot_t *s)
672 {
673 snapshot_module_t *m;
674
675 m = snapshot_module_create(s, snap_module_name, SNAP_MAJOR, SNAP_MINOR);
676
677 if (m == NULL) {
678 return -1;
679 }
680
681 if (0
682 || (SMW_B(m, (uint8_t)easyflash_jumper) < 0)
683 || (SMW_B(m, easyflash_register_00) < 0)
684 || (SMW_B(m, easyflash_register_02) < 0)
685 || (SMW_BA(m, easyflash_ram, 256) < 0)
686 || (SMW_BA(m, roml_banks, 0x80000) < 0)
687 || (SMW_BA(m, romh_banks, 0x80000) < 0)) {
688 snapshot_module_close(m);
689 return -1;
690 }
691
692 snapshot_module_close(m);
693
694 if (0
695 || (flash040core_snapshot_write_module(s, easyflash_state_low, flash_snap_module_name) < 0)
696 || (flash040core_snapshot_write_module(s, easyflash_state_high, flash_snap_module_name) < 0)) {
697 return -1;
698 }
699
700 return 0;
701 }
702
easyflash_snapshot_read_module(snapshot_t * s)703 int easyflash_snapshot_read_module(snapshot_t *s)
704 {
705 uint8_t vmajor, vminor;
706 snapshot_module_t *m;
707
708 m = snapshot_module_open(s, snap_module_name, &vmajor, &vminor);
709 if (m == NULL) {
710 return -1;
711 }
712
713 /* Do not accept versions higher than current */
714 if (snapshot_version_is_bigger(vmajor, vminor, SNAP_MAJOR, SNAP_MINOR)) {
715 snapshot_set_error(SNAPSHOT_MODULE_HIGHER_VERSION);
716 goto fail;
717 }
718
719 if (0
720 || (SMR_B_INT(m, &easyflash_jumper) < 0)
721 || (SMR_B(m, &easyflash_register_00) < 0)
722 || (SMR_B(m, &easyflash_register_02) < 0)
723 || (SMR_BA(m, easyflash_ram, 256) < 0)
724 || (SMR_BA(m, roml_banks, 0x80000) < 0)
725 || (SMR_BA(m, romh_banks, 0x80000) < 0)) {
726 goto fail;
727 }
728
729 snapshot_module_close(m);
730
731 easyflash_state_low = lib_malloc(sizeof(flash040_context_t));
732 easyflash_state_high = lib_malloc(sizeof(flash040_context_t));
733
734 flash040core_init(easyflash_state_low, maincpu_alarm_context, FLASH040_TYPE_B, roml_banks);
735 flash040core_init(easyflash_state_high, maincpu_alarm_context, FLASH040_TYPE_B, romh_banks);
736
737 if (0
738 || (flash040core_snapshot_read_module(s, easyflash_state_low, flash_snap_module_name) < 0)
739 || (flash040core_snapshot_read_module(s, easyflash_state_low, flash_snap_module_name) < 0)) {
740 flash040core_shutdown(easyflash_state_low);
741 flash040core_shutdown(easyflash_state_high);
742 lib_free(easyflash_state_low);
743 lib_free(easyflash_state_high);
744 return -1;
745 }
746
747 easyflash_common_attach("dummy");
748
749 /* remove dummy filename, set filetype to none */
750 lib_free(easyflash_filename);
751 easyflash_filename = NULL;
752 easyflash_filetype = 0;
753
754 return 0;
755
756 fail:
757 snapshot_module_close(m);
758 return -1;
759 }
760