1 /*
2 * ross.c - Cartridge handling, Ross 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 #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 "ross.h"
42 #include "snapshot.h"
43 #include "types.h"
44 #include "util.h"
45 #include "crt.h"
46
47 /*
48 "Ross" Cartridge
49
50 - 16kb or 32kb ROM
51
52 - 16Kb ROM mapped in at $8000-$BFFF in 16k game config
53
54 - Any read access to $DE00 will switch in bank 1 (if cart is 32Kb).
55
56 - Any read access to $DF00 will switch off EXROM and GAME.
57 */
58
59 static int currbank = 0;
60
61 static int ross_is_32k = 0;
62
ross_io1_read(uint16_t addr)63 static uint8_t ross_io1_read(uint16_t addr)
64 {
65 if (ross_is_32k) {
66 cart_romhbank_set_slotmain(1);
67 cart_romlbank_set_slotmain(1);
68 currbank = 1;
69 }
70 return 0;
71 }
72
ross_io_peek(uint16_t addr)73 static uint8_t ross_io_peek(uint16_t addr)
74 {
75 return 0;
76 }
77
ross_io2_read(uint16_t addr)78 static uint8_t ross_io2_read(uint16_t addr)
79 {
80 cart_set_port_exrom_slotmain(0);
81 cart_set_port_game_slotmain(0);
82 cart_port_config_changed_slotmain();
83 return 0;
84 }
85
ross_dump(void)86 static int ross_dump(void)
87 {
88 mon_out("Size: %s, bank: %d\n",
89 (ross_is_32k) ? "32Kb" : "16Kb",
90 currbank);
91 return 0;
92 }
93
94 /* ---------------------------------------------------------------------*/
95
96 static io_source_t ross_io1_device = {
97 CARTRIDGE_NAME_ROSS,
98 IO_DETACH_CART,
99 NULL,
100 0xde00, 0xdeff, 0xff,
101 0, /* read is never valid */
102 NULL,
103 ross_io1_read,
104 ross_io_peek,
105 ross_dump,
106 CARTRIDGE_ROSS,
107 0,
108 0
109 };
110
111 static io_source_t ross_io2_device = {
112 CARTRIDGE_NAME_ROSS,
113 IO_DETACH_CART,
114 NULL,
115 0xdf00, 0xdfff, 0xff,
116 0, /* read is never valid */
117 NULL,
118 ross_io2_read,
119 ross_io_peek,
120 ross_dump,
121 CARTRIDGE_ROSS,
122 0,
123 0
124 };
125
126 static io_source_list_t *ross_io1_list_item = NULL;
127 static io_source_list_t *ross_io2_list_item = NULL;
128
129 static const export_resource_t export_res = {
130 CARTRIDGE_NAME_ROSS, 1, 1, &ross_io1_device, &ross_io2_device, CARTRIDGE_ROSS
131 };
132
133 /* ---------------------------------------------------------------------*/
134
ross_config_init(void)135 void ross_config_init(void)
136 {
137 cart_config_changed_slotmain(1, 1, CMODE_READ);
138 }
139
ross_config_setup(uint8_t * rawcart)140 void ross_config_setup(uint8_t *rawcart)
141 {
142 memcpy(&roml_banks[0x0000], &rawcart[0x0000], 0x2000);
143 memcpy(&romh_banks[0x0000], &rawcart[0x2000], 0x2000);
144 memcpy(&roml_banks[0x2000], &rawcart[0x4000], 0x2000);
145 memcpy(&romh_banks[0x2000], &rawcart[0x6000], 0x2000);
146 cart_config_changed_slotmain(0, 0, CMODE_READ);
147 currbank = 0;
148 }
149
150 /* ---------------------------------------------------------------------*/
151
ross_common_attach(void)152 static int ross_common_attach(void)
153 {
154 if (export_add(&export_res) < 0) {
155 return -1;
156 }
157 ross_io1_list_item = io_source_register(&ross_io1_device);
158 ross_io2_list_item = io_source_register(&ross_io2_device);
159 return 0;
160 }
161
ross_bin_attach(const char * filename,uint8_t * rawcart)162 int ross_bin_attach(const char *filename, uint8_t *rawcart)
163 {
164 if (util_file_load(filename, rawcart, 0x8000, UTIL_FILE_LOAD_SKIP_ADDRESS) < 0) {
165 if (util_file_load(filename, rawcart, 0x4000, UTIL_FILE_LOAD_SKIP_ADDRESS) < 0) {
166 return -1;
167 }
168 ross_is_32k = 0;
169 } else {
170 ross_is_32k = 1;
171 }
172 return ross_common_attach();
173 }
174
ross_crt_attach(FILE * fd,uint8_t * rawcart)175 int ross_crt_attach(FILE *fd, uint8_t *rawcart)
176 {
177 crt_chip_header_t chip;
178 int amount = 0;
179
180 while (1) {
181 if (crt_read_chip_header(&chip, fd)) {
182 break;
183 }
184
185 amount++;
186
187 if (chip.start != 0x8000 || chip.size != 0x4000 || chip.bank > 1) {
188 return -1;
189 }
190
191 if (crt_read_chip(rawcart, chip.bank << 14, &chip, fd)) {
192 return -1;
193 }
194 }
195
196 if (amount == 1) {
197 ross_is_32k = 0;
198 } else {
199 ross_is_32k = 1;
200 }
201 return ross_common_attach();
202 }
203
ross_detach(void)204 void ross_detach(void)
205 {
206 export_remove(&export_res);
207 io_source_unregister(ross_io1_list_item);
208 io_source_unregister(ross_io2_list_item);
209 ross_io1_list_item = NULL;
210 ross_io2_list_item = NULL;
211 }
212
213 /* ---------------------------------------------------------------------*/
214
215 /* CARTROSS snapshot module format:
216
217 type | name | version | description
218 -------------------------------------
219 BYTE | is32k | 0.1 | cart is 32KB flag
220 BYTE | bank | 0.0+ | current bank
221 ARRAY | ROML | 0.0+ | 16384 BYTES of ROML data
222 ARRAY | ROMH | 0.0+ | 16384 BYTES of ROMH data
223 */
224
225 static char snap_module_name[] = "CARTROSS";
226 #define SNAP_MAJOR 0
227 #define SNAP_MINOR 1
228
ross_snapshot_write_module(snapshot_t * s)229 int ross_snapshot_write_module(snapshot_t *s)
230 {
231 snapshot_module_t *m;
232
233 m = snapshot_module_create(s, snap_module_name, SNAP_MAJOR, SNAP_MINOR);
234
235 if (m == NULL) {
236 return -1;
237 }
238
239 if (0
240 || SMW_B(m, (uint8_t)ross_is_32k) < 0
241 || SMW_B(m, (uint8_t)currbank) < 0
242 || SMW_BA(m, roml_banks, 0x4000) < 0
243 || SMW_BA(m, romh_banks, 0x4000) < 0) {
244 snapshot_module_close(m);
245 return -1;
246 }
247
248 return snapshot_module_close(m);
249 }
250
ross_snapshot_read_module(snapshot_t * s)251 int ross_snapshot_read_module(snapshot_t *s)
252 {
253 uint8_t vmajor, vminor;
254 snapshot_module_t *m;
255
256 m = snapshot_module_open(s, snap_module_name, &vmajor, &vminor);
257
258 if (m == NULL) {
259 return -1;
260 }
261
262 /* Do not accept versions higher than current */
263 if (vmajor > SNAP_MAJOR || vminor > SNAP_MINOR) {
264 snapshot_set_error(SNAPSHOT_MODULE_HIGHER_VERSION);
265 goto fail;
266 }
267
268 /* new in 0.1 */
269 if (SNAPVAL(vmajor, vminor, 0, 1)) {
270 if (SMR_B_INT(m, &ross_is_32k) < 0) {
271 goto fail;
272 }
273 } else {
274 ross_is_32k = 0;
275 }
276
277 if (0
278 || SMR_B_INT(m, &currbank) < 0
279 || SMR_BA(m, roml_banks, 0x4000) < 0
280 || SMR_BA(m, romh_banks, 0x4000) < 0) {
281 goto fail;
282 }
283
284 snapshot_module_close(m);
285
286 return ross_common_attach();
287
288 fail:
289 snapshot_module_close(m);
290 return -1;
291 }
292