1 /*
2 * comal80.c - Cartridge handling, Comal80 cart.
3 *
4 * Written by
5 * Marco van den Heuvel <blackystardust68@yahoo.com>
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 /* #define DEBUGCART */
28
29 #include "vice.h"
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35 #define CARTRIDGE_INCLUDE_SLOTMAIN_API
36 #include "c64cartsystem.h"
37 #undef CARTRIDGE_INCLUDE_SLOTMAIN_API
38 #include "c64mem.h"
39 #include "cartio.h"
40 #include "cartridge.h"
41 #include "comal80.h"
42 #include "export.h"
43 #include "monitor.h"
44 #include "snapshot.h"
45 #include "types.h"
46 #include "util.h"
47 #include "crt.h"
48
49 #ifdef DEBUGCART
50 #define DBG(x) printf x
51 #else
52 #define DBG(x)
53 #endif
54
55 /*
56 Comal80 Cartridge
57
58 - 64K ROM (32K mapped to $8000 and 32K mapped to $A000)
59 - free socket for another 64K eprom
60
61 The cart has 1 (write-only) bank control register which
62 is located at $DE00 and mirrored throughout the $DE00-$DEFF
63 range.
64
65 bit 7 : exrom?
66 bit 6 : game?
67 bit 5 : unknown function (used by the software to disable the cartridge)
68 bit 4 : unused?
69 bit 3 : unused?
70 bit 2 : selects user eprom (bank MSB)
71 bit 0-1 : selects bank
72 */
73
74 static int currregval = 0;
75 static int extrarom = 0;
76
comal80_io1_store(uint16_t addr,uint8_t value)77 static void comal80_io1_store(uint16_t addr, uint8_t value)
78 {
79 int cmode, currbank;
80
81 currregval = value & 0xc7;
82 currbank = value & 7;
83
84 switch (value & 0xe0) {
85 case 0xe0:
86 cmode = CMODE_RAM;
87 break;
88 default:
89 case 0x80:
90 cmode = CMODE_16KGAME;
91 break;
92 case 0x40:
93 cmode = CMODE_8KGAME;
94 break;
95 }
96 #ifdef DEBUGCART
97 if ((value != 0x82) && (value != 0x83)) {
98 DBG(("COMAL80: IO1W %04x %02x mode: %d bank: %d\n", addr, value, cmode, currbank));
99 }
100 #endif
101 cart_config_changed_slotmain(0, (uint8_t)(cmode | (currbank << CMODE_BANK_SHIFT)), CMODE_READ);
102 }
103
comal80_io1_peek(uint16_t addr)104 static uint8_t comal80_io1_peek(uint16_t addr)
105 {
106 return currregval;
107 }
108
comal80_dump(void)109 static int comal80_dump(void)
110 {
111 mon_out("extra eprom is installed: %s\n", extrarom ? "yes" : "no");
112 mon_out("register value: $%02x\n", currregval);
113 mon_out(" bank: %d/%d\n", currregval & 7, extrarom ? 8 : 4);
114 return 0;
115 }
116
117 /* ---------------------------------------------------------------------*/
118
119 static io_source_t comal80_device = {
120 CARTRIDGE_NAME_COMAL80,
121 IO_DETACH_CART,
122 NULL,
123 0xde00, 0xdeff, 0xff,
124 0,
125 comal80_io1_store,
126 NULL,
127 comal80_io1_peek,
128 comal80_dump,
129 CARTRIDGE_COMAL80,
130 0,
131 0
132 };
133
134 static io_source_list_t *comal80_list_item = NULL;
135
136 static const export_resource_t export_res = {
137 CARTRIDGE_NAME_COMAL80, 1, 1, &comal80_device, NULL, CARTRIDGE_COMAL80
138 };
139
140 /* ---------------------------------------------------------------------*/
141
comal80_config_init(void)142 void comal80_config_init(void)
143 {
144 cart_config_changed_slotmain(CMODE_16KGAME, CMODE_16KGAME, CMODE_READ);
145 currregval = 0;
146 }
147
comal80_config_setup(uint8_t * rawcart)148 void comal80_config_setup(uint8_t *rawcart)
149 {
150 memcpy(&roml_banks[0x0000], &rawcart[0x0000], 0x2000);
151 memcpy(&romh_banks[0x0000], &rawcart[0x2000], 0x2000);
152 memcpy(&roml_banks[0x2000], &rawcart[0x4000], 0x2000);
153 memcpy(&romh_banks[0x2000], &rawcart[0x6000], 0x2000);
154 memcpy(&roml_banks[0x4000], &rawcart[0x8000], 0x2000);
155 memcpy(&romh_banks[0x4000], &rawcart[0xa000], 0x2000);
156 memcpy(&roml_banks[0x6000], &rawcart[0xc000], 0x2000);
157 memcpy(&romh_banks[0x6000], &rawcart[0xe000], 0x2000);
158
159 memset(&roml_banks[0x8000], 0xff, 0x8000);
160 memset(&romh_banks[0x8000], 0xff, 0x8000);
161
162 if (extrarom) {
163 memcpy(&roml_banks[0x8000], &rawcart[0x10000], 0x2000);
164 memcpy(&romh_banks[0x8000], &rawcart[0x12000], 0x2000);
165 memcpy(&roml_banks[0xa000], &rawcart[0x14000], 0x2000);
166 memcpy(&romh_banks[0xa000], &rawcart[0x16000], 0x2000);
167 memcpy(&roml_banks[0xc000], &rawcart[0x18000], 0x2000);
168 memcpy(&romh_banks[0xc000], &rawcart[0x1a000], 0x2000);
169 memcpy(&roml_banks[0xe000], &rawcart[0x1c000], 0x2000);
170 memcpy(&romh_banks[0xe000], &rawcart[0x1e000], 0x2000);
171 }
172
173 cart_config_changed_slotmain(CMODE_8KGAME, CMODE_8KGAME, CMODE_READ);
174 }
175
176 /* ---------------------------------------------------------------------*/
comal80_common_attach(void)177 static int comal80_common_attach(void)
178 {
179 if (export_add(&export_res) < 0) {
180 return -1;
181 }
182 comal80_list_item = io_source_register(&comal80_device);
183 return 0;
184 }
185
comal80_bin_attach(const char * filename,uint8_t * rawcart)186 int comal80_bin_attach(const char *filename, uint8_t *rawcart)
187 {
188 extrarom = 1;
189 if (util_file_load(filename, rawcart, 0x20000, UTIL_FILE_LOAD_SKIP_ADDRESS) < 0) {
190 extrarom = 0;
191 if (util_file_load(filename, rawcart, 0x10000, UTIL_FILE_LOAD_SKIP_ADDRESS) < 0) {
192 return -1;
193 }
194 }
195 return comal80_common_attach();
196 }
197
comal80_crt_attach(FILE * fd,uint8_t * rawcart)198 int comal80_crt_attach(FILE *fd, uint8_t *rawcart)
199 {
200 crt_chip_header_t chip;
201
202 extrarom = 0;
203
204 while (1) {
205 if (crt_read_chip_header(&chip, fd)) {
206 break;
207 }
208
209 if (chip.start != 0x8000 || chip.size != 0x4000 || chip.bank > 7) {
210 return -1;
211 }
212
213 if (crt_read_chip(rawcart, chip.bank << 14, &chip, fd)) {
214 return -1;
215 }
216
217 if (chip.bank > 3) {
218 extrarom = 1;
219 }
220 }
221 return comal80_common_attach();
222 }
223
comal80_detach(void)224 void comal80_detach(void)
225 {
226 export_remove(&export_res);
227 io_source_unregister(comal80_list_item);
228 comal80_list_item = NULL;
229 }
230
231 /* ---------------------------------------------------------------------*/
232
233 /* CARTCOMAL snapshot module format:
234
235 type | name | description
236 ------------------------------
237 BYTE | register | control register
238 BYTE | extra rom| image contains extra eprom
239 ARRAY | ROML | 32768 or 65536 BYTES of ROML data
240 ARRAY | ROMH | 32768 or 65536 BYTES of ROMH data
241 */
242
243 static char snap_module_name[] = "CARTCOMAL";
244 #define SNAP_MAJOR 0
245 #define SNAP_MINOR 1
246
comal80_snapshot_write_module(snapshot_t * s)247 int comal80_snapshot_write_module(snapshot_t *s)
248 {
249 snapshot_module_t *m;
250
251 m = snapshot_module_create(s, snap_module_name, SNAP_MAJOR, SNAP_MINOR);
252
253 if (m == NULL) {
254 return -1;
255 }
256
257 if (0
258 || (SMW_B(m, (uint8_t)currregval) < 0)
259 || (SMW_B(m, (uint8_t)extrarom) < 0)
260 || (SMW_BA(m, roml_banks, extrarom ? 0x10000 : 0x8000) < 0)
261 || (SMW_BA(m, romh_banks, extrarom ? 0x10000 : 0x8000) < 0)) {
262 snapshot_module_close(m);
263 return -1;
264 }
265
266 return snapshot_module_close(m);
267 }
268
comal80_snapshot_read_module(snapshot_t * s)269 int comal80_snapshot_read_module(snapshot_t *s)
270 {
271 uint8_t vmajor, vminor;
272 snapshot_module_t *m;
273
274 m = snapshot_module_open(s, snap_module_name, &vmajor, &vminor);
275
276 if (m == NULL) {
277 return -1;
278 }
279
280 /* Do not accept versions higher than current */
281 if (vmajor > SNAP_MAJOR || vminor > SNAP_MINOR) {
282 snapshot_set_error(SNAPSHOT_MODULE_HIGHER_VERSION);
283 goto fail;
284 }
285
286 if (0
287 || (SMR_B_INT(m, &currregval) < 0)
288 || (SMR_B_INT(m, &extrarom) < 0)
289 || (SMR_BA(m, roml_banks, extrarom ? 0x10000 : 0x8000) < 0)
290 || (SMR_BA(m, romh_banks, extrarom ? 0x10000 : 0x8000) < 0)) {
291 goto fail;
292 }
293
294 snapshot_module_close(m);
295
296 return comal80_common_attach();
297
298 fail:
299 snapshot_module_close(m);
300 return -1;
301 }
302