1 /*
2 * superexplode5.c - Cartridge handling, Super Explode V5 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 "superexplode5.h"
43 #include "types.h"
44 #include "util.h"
45 #include "crt.h"
46
47 /*
48 FIXME: this one has been implemented purely based on guesswork and by
49 examining the cartridge rom dump.
50
51 The Soft Group "Super Explode V5"
52
53 - 2 ROM banks, 8k each == 16kb
54 - one button (reset)
55
56 ROM banks are always mapped to $8000
57 the last page of the ROM bank is also visible at DFxx
58
59 controlregister is $df00:
60 bit 7 selects bank
61
62 this is a very strange cartridge, almost no information about it seems
63 to exist, from http://www.mayhem64.co.uk/cartpower.htm:
64
65 Super Explode! version 5 is primarily a graphics cartridge. It is designed
66 to capture, manipulate, and edit screens and then print them. Its color
67 print capability includes recolorization, and it dumps to all but one
68 available color printer. Its extensive ability to manipulate graphics
69 images makes it the cartridge of choice for graphics buffs. (Note that
70 Super Explode! interfaces with The Soft Group's Video Byte system, a low-
71 cost video digitizer designed to capture full-color images from a VCR or
72 live camera.)
73
74 Super Explode! 5's modest utility repertoire includes a complete disk-turbo
75 feature, directory list to screen, single-stroke disk commands, and easy
76 access to the error channel. These commands are not implemented on function
77 keys, nor are the function keys programmed. There is no BASIC toolkit,
78 monitor, or disk-backup or archiving capability. There is a fast multiple-
79 copy file routine, as well as an unnew command. The freeze button doubles
80 as a reset.
81
82 The manual is on disk (you must print it out) and is rather haphazard.
83 Nonetheless, it contains a wealth of technical information. Topics include
84 split screens, elementary and advanced file conversion (for Doodle, Koala,
85 text screens, and custom character sets), sprite manipulation, and sprite
86 overlay. If you require few utility functions but extensive graphics
87 capability, Super Explode! 5 is for you.
88
89 */
90
91 /* #define SE5_DEBUG */
92
93 #ifdef SE5_DEBUG
94 #define DBG(x) printf x
95 #else
96 #define DBG(x)
97 #endif
98
99 #define SE5_CART_SIZE (2 * 0x2000)
100
101 /* ---------------------------------------------------------------------*/
102
103 static int se5_bank = 0;
104
se5_io2_store(uint16_t addr,uint8_t value)105 static void se5_io2_store(uint16_t addr, uint8_t value)
106 {
107 DBG(("io2 wr %04x %02x\n", addr, value));
108 se5_bank = (value & 0x80) ? 1 : 0;
109 cart_romlbank_set_slotmain(se5_bank);
110 }
111
se5_io2_read(uint16_t addr)112 static uint8_t se5_io2_read(uint16_t addr)
113 {
114 addr |= 0xdf00;
115 return roml_banks[(addr & 0x1fff) + (roml_bank << 13)];
116 }
117
se5_dump(void)118 static int se5_dump(void)
119 {
120 mon_out("Bank: %d\n", se5_bank);
121
122 return 0;
123 }
124
125 /* ---------------------------------------------------------------------*/
126
127 static io_source_t se5_io2_device = {
128 CARTRIDGE_NAME_SUPER_EXPLODE_V5, /* name of the device */
129 IO_DETACH_CART, /* use cartridge ID to detach the device when involved in a read-collision */
130 IO_DETACH_NO_RESOURCE, /* does not use a resource for detach */
131 0xdf00, 0xdfff, 0xff, /* range for the device, regs:$df00-$dfff */
132 1, /* read is always valid */
133 se5_io2_store, /* store function */
134 NULL, /* NO poke function */
135 se5_io2_read, /* read function */
136 NULL, /* NO peek function */
137 se5_dump, /* device state information dump function */
138 CARTRIDGE_SUPER_EXPLODE_V5, /* cartridge ID */
139 IO_PRIO_NORMAL, /* normal priority, device read needs to be checked for collisions */
140 0 /* insertion order, gets filled in by the registration function */
141 };
142
143 static io_source_list_t *se5_io2_list_item = NULL;
144
145 static const export_resource_t export_res = {
146 CARTRIDGE_NAME_SUPER_EXPLODE_V5, 0, 1, NULL, &se5_io2_device, CARTRIDGE_SUPER_EXPLODE_V5
147 };
148
149 /* ---------------------------------------------------------------------*/
150
se5_roml_read(uint16_t addr)151 uint8_t se5_roml_read(uint16_t addr)
152 {
153 if (addr < 0x9f00) {
154 return roml_banks[(addr & 0x1fff) + (roml_bank << 13)];
155 } else {
156 return ram_read(addr);
157 /* return mem_read_without_ultimax(addr); */
158 }
159 }
160
161 /* ---------------------------------------------------------------------*/
162
se5_config_init(void)163 void se5_config_init(void)
164 {
165 cart_config_changed_slotmain(0, 0, CMODE_READ);
166 cart_romlbank_set_slotmain(0);
167 se5_bank = 0;
168 }
169
se5_config_setup(uint8_t * rawcart)170 void se5_config_setup(uint8_t *rawcart)
171 {
172 memcpy(roml_banks, rawcart, SE5_CART_SIZE);
173 cart_config_changed_slotmain(0, 0, CMODE_READ);
174 cart_romlbank_set_slotmain(0);
175 se5_bank = 0;
176 }
177
178 /* ---------------------------------------------------------------------*/
179
se5_common_attach(void)180 static int se5_common_attach(void)
181 {
182 if (export_add(&export_res) < 0) {
183 return -1;
184 }
185
186 se5_io2_list_item = io_source_register(&se5_io2_device);
187
188 return 0;
189 }
190
se5_bin_attach(const char * filename,uint8_t * rawcart)191 int se5_bin_attach(const char *filename, uint8_t *rawcart)
192 {
193 if (util_file_load(filename, rawcart, SE5_CART_SIZE, UTIL_FILE_LOAD_SKIP_ADDRESS) < 0) {
194 return -1;
195 }
196
197 return se5_common_attach();
198 }
199
se5_crt_attach(FILE * fd,uint8_t * rawcart)200 int se5_crt_attach(FILE *fd, uint8_t *rawcart)
201 {
202 crt_chip_header_t chip;
203 int i, cnt = 0;
204
205 for (i = 0; i <= 0x01; i++) {
206 if (crt_read_chip_header(&chip, fd)) {
207 break;
208 }
209
210 if (chip.bank > 0x1f || chip.size != 0x2000) {
211 return -1;
212 }
213
214 if (crt_read_chip(rawcart, chip.bank << 13, &chip, fd)) {
215 return -1;
216 }
217 cnt++;
218 }
219
220 return se5_common_attach();
221 }
222
se5_detach(void)223 void se5_detach(void)
224 {
225 export_remove(&export_res);
226 io_source_unregister(se5_io2_list_item);
227 se5_io2_list_item = NULL;
228 }
229
230 /* ---------------------------------------------------------------------*/
231
232 /* CARTSE5 snapshot module format:
233
234 type | name | version | description
235 --------------------------------------
236 BYTE | bank | 0.1 | current bank
237 ARRAY | ROML | 0.0+ | 16384 BYTES of ROML data
238 */
239
240 static const char snap_module_name[] = "CARTSE5";
241 #define SNAP_MAJOR 0
242 #define SNAP_MINOR 1
243
se5_snapshot_write_module(snapshot_t * s)244 int se5_snapshot_write_module(snapshot_t *s)
245 {
246 snapshot_module_t *m;
247
248 m = snapshot_module_create(s, snap_module_name, SNAP_MAJOR, SNAP_MINOR);
249
250 if (m == NULL) {
251 return -1;
252 }
253
254 if (0
255 || SMW_B(m, (uint8_t)se5_bank) < 0
256 || SMW_BA(m, roml_banks, SE5_CART_SIZE) < 0) {
257 snapshot_module_close(m);
258 return -1;
259 }
260
261 return snapshot_module_close(m);
262 }
263
se5_snapshot_read_module(snapshot_t * s)264 int se5_snapshot_read_module(snapshot_t *s)
265 {
266 uint8_t vmajor, vminor;
267 snapshot_module_t *m;
268
269 m = snapshot_module_open(s, snap_module_name, &vmajor, &vminor);
270
271 if (m == NULL) {
272 return -1;
273 }
274
275 /* Do not accept versions higher than current */
276 if (snapshot_version_is_bigger(vmajor, vminor, SNAP_MAJOR, SNAP_MINOR)) {
277 snapshot_set_error(SNAPSHOT_MODULE_HIGHER_VERSION);
278 goto fail;
279 }
280
281 /* new in 0.1 */
282 if (!snapshot_version_is_smaller(vmajor, vminor, 0, 1)) {
283 if (SMR_B_INT(m, &se5_bank) < 0) {
284 goto fail;
285 }
286 } else {
287 se5_bank = 0;
288 }
289
290 if (SMR_BA(m, roml_banks, SE5_CART_SIZE) < 0) {
291 goto fail;
292 }
293
294 snapshot_module_close(m);
295
296 return se5_common_attach();
297
298 fail:
299 snapshot_module_close(m);
300 return -1;
301 }
302