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