1 /*
2 * warpspeed.c - Cartridge handling, Warpspeed cart.
3 *
4 * Written by
5 * groepaz <groepaz@gmx.net>
6 *
7 * This file is part of VICE, the Versatile Commodore Emulator.
8 * See README for copyright notice.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
23 * 02111-1307 USA.
24 *
25 */
26
27 #include "vice.h"
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32
33 #define CARTRIDGE_INCLUDE_SLOTMAIN_API
34 #include "c64cartsystem.h"
35 #undef CARTRIDGE_INCLUDE_SLOTMAIN_API
36 #include "c64mem.h"
37 #include "cartio.h"
38 #include "cartridge.h"
39 #include "export.h"
40 #include "monitor.h"
41 #include "snapshot.h"
42 #include "types.h"
43 #include "util.h"
44 #include "warpspeed.h"
45 #include "crt.h"
46
47 /*
48 Warpspeed
49
50 - 16k ROM
51 - uses full io1/io2
52
53 io1
54 - read: ROM (offset $1e00)
55 - write: enable rom at 8000
56
57 io2
58 - read: ROM (offset $1f00)
59 - write: disable rom at 8000
60 */
61
62 /* some prototypes are needed */
63 static uint8_t warpspeed_io1_read(uint16_t addr);
64 static void warpspeed_io1_store(uint16_t addr, uint8_t value);
65 static uint8_t warpspeed_io2_read(uint16_t addr);
66 static void warpspeed_io2_store(uint16_t addr, uint8_t value);
67 static int warpspeed_dump(void);
68
69 static io_source_t warpspeed_io1_device = {
70 CARTRIDGE_NAME_WARPSPEED,
71 IO_DETACH_CART,
72 NULL,
73 0xde00, 0xdeff, 0xff,
74 1, /* read is always valid */
75 warpspeed_io1_store,
76 warpspeed_io1_read,
77 warpspeed_io1_read,
78 warpspeed_dump,
79 CARTRIDGE_WARPSPEED,
80 0,
81 0
82 };
83
84 static io_source_t warpspeed_io2_device = {
85 CARTRIDGE_NAME_WARPSPEED,
86 IO_DETACH_CART,
87 NULL,
88 0xdf00, 0xdfff, 0xff,
89 1, /* read is always valid */
90 warpspeed_io2_store,
91 warpspeed_io2_read,
92 warpspeed_io2_read,
93 warpspeed_dump,
94 CARTRIDGE_WARPSPEED,
95 0,
96 0
97 };
98
99 static io_source_list_t *warpspeed_io1_list_item = NULL;
100 static io_source_list_t *warpspeed_io2_list_item = NULL;
101
102 /* ---------------------------------------------------------------------*/
103
104 static int warpspeed_8000 = 0;
105
warpspeed_io1_read(uint16_t addr)106 static uint8_t warpspeed_io1_read(uint16_t addr)
107 {
108 return roml_banks[0x1e00 + (addr & 0xff)];
109 }
110
warpspeed_io1_store(uint16_t addr,uint8_t value)111 static void warpspeed_io1_store(uint16_t addr, uint8_t value)
112 {
113 cart_config_changed_slotmain(1, 1, CMODE_WRITE);
114 warpspeed_8000 = 1;
115 }
116
warpspeed_io2_read(uint16_t addr)117 static uint8_t warpspeed_io2_read(uint16_t addr)
118 {
119 return roml_banks[0x1f00 + (addr & 0xff)];
120 }
121
warpspeed_io2_store(uint16_t addr,uint8_t value)122 static void warpspeed_io2_store(uint16_t addr, uint8_t value)
123 {
124 cart_config_changed_slotmain(2, 2, CMODE_WRITE);
125 warpspeed_8000 = 0;
126 }
127
warpspeed_dump(void)128 static int warpspeed_dump(void)
129 {
130 mon_out("$8000-$9FFF ROM: %s\n", (warpspeed_8000) ? "enabled" : "disabled");
131
132 return 0;
133 }
134
135 /* ---------------------------------------------------------------------*/
136
137 static const export_resource_t export_res_warpspeed = {
138 CARTRIDGE_NAME_WARPSPEED, 1, 1, &warpspeed_io1_device, &warpspeed_io2_device, CARTRIDGE_WARPSPEED
139 };
140
141 /* ---------------------------------------------------------------------*/
142
warpspeed_config_init(void)143 void warpspeed_config_init(void)
144 {
145 cart_config_changed_slotmain(1, 1, CMODE_READ);
146 warpspeed_8000 = 1;
147 }
148
warpspeed_config_setup(uint8_t * rawcart)149 void warpspeed_config_setup(uint8_t *rawcart)
150 {
151 memcpy(roml_banks, rawcart, 0x2000);
152 memcpy(romh_banks, &rawcart[0x2000], 0x2000);
153 cart_config_changed_slotmain(1, 1, CMODE_READ);
154 warpspeed_8000 = 1;
155 }
156
warpspeed_common_attach(void)157 static int warpspeed_common_attach(void)
158 {
159 if (export_add(&export_res_warpspeed) < 0) {
160 return -1;
161 }
162
163 warpspeed_io1_list_item = io_source_register(&warpspeed_io1_device);
164 warpspeed_io2_list_item = io_source_register(&warpspeed_io2_device);
165
166 return 0;
167 }
168
warpspeed_bin_attach(const char * filename,uint8_t * rawcart)169 int warpspeed_bin_attach(const char *filename, uint8_t *rawcart)
170 {
171 if (util_file_load(filename, rawcart, 0x4000, UTIL_FILE_LOAD_SKIP_ADDRESS) < 0) {
172 return -1;
173 }
174 return warpspeed_common_attach();
175 }
176
warpspeed_crt_attach(FILE * fd,uint8_t * rawcart)177 int warpspeed_crt_attach(FILE *fd, uint8_t *rawcart)
178 {
179 crt_chip_header_t chip;
180
181 if (crt_read_chip_header(&chip, fd)) {
182 return -1;
183 }
184
185 if (chip.start != 0x8000 || chip.size != 0x4000) {
186 return -1;
187 }
188
189 if (crt_read_chip(rawcart, 0, &chip, fd)) {
190 return -1;
191 }
192
193 return warpspeed_common_attach();
194 }
195
warpspeed_detach(void)196 void warpspeed_detach(void)
197 {
198 export_remove(&export_res_warpspeed);
199 io_source_unregister(warpspeed_io1_list_item);
200 io_source_unregister(warpspeed_io2_list_item);
201 warpspeed_io1_list_item = NULL;
202 warpspeed_io2_list_item = NULL;
203 }
204
205 /* ---------------------------------------------------------------------*/
206
207 /* CARTWARP snapshot module format:
208
209 type | name | version | description
210 ----------------------------------------
211 BYTE | ROM 8000 | 0.1 | ROM at $8000 flag
212 ARRAY | ROML | 0.0+ | 8192 BYTES of ROML data
213 ARRAY | ROMH | 0.0+ | 8192 BYTES of ROMH data
214 */
215
216 static char snap_module_name[] = "CARTWARP";
217 #define SNAP_MAJOR 0
218 #define SNAP_MINOR 1
219
warpspeed_snapshot_write_module(snapshot_t * s)220 int warpspeed_snapshot_write_module(snapshot_t *s)
221 {
222 snapshot_module_t *m;
223
224 m = snapshot_module_create(s, snap_module_name, SNAP_MAJOR, SNAP_MINOR);
225
226 if (m == NULL) {
227 return -1;
228 }
229
230 if (0
231 || SMW_B(m, (uint8_t)warpspeed_8000) < 0
232 || SMW_BA(m, roml_banks, 0x2000) < 0
233 || SMW_BA(m, romh_banks, 0x2000) < 0) {
234 snapshot_module_close(m);
235 return -1;
236 }
237
238 return snapshot_module_close(m);
239 }
240
warpspeed_snapshot_read_module(snapshot_t * s)241 int warpspeed_snapshot_read_module(snapshot_t *s)
242 {
243 uint8_t vmajor, vminor;
244 snapshot_module_t *m;
245
246 m = snapshot_module_open(s, snap_module_name, &vmajor, &vminor);
247
248 if (m == NULL) {
249 return -1;
250 }
251
252 /* Do not accept versions higher than current */
253 if (vmajor > SNAP_MAJOR || vminor > SNAP_MINOR) {
254 snapshot_set_error(SNAPSHOT_MODULE_HIGHER_VERSION);
255 goto fail;
256 }
257
258 /* new in 0.1 */
259 if (SNAPVAL(vmajor, vminor, 0, 1)) {
260 if (SMR_B_INT(m, &warpspeed_8000) < 0) {
261 goto fail;
262 }
263 } else {
264 warpspeed_8000 = 0;
265 }
266
267 if (0
268 || SMR_BA(m, roml_banks, 0x2000) < 0
269 || SMR_BA(m, romh_banks, 0x2000) < 0) {
270 goto fail;
271 }
272
273 snapshot_module_close(m);
274
275 return warpspeed_common_attach();
276
277 fail:
278 snapshot_module_close(m);
279 return -1;
280 }
281