1 /*
2 * delaep7x8.c - Cartridge handling, Dela EP7x8kb 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 "cartio.h"
37 #include "cartridge.h"
38 #include "delaep7x8.h"
39 #include "export.h"
40 #include "monitor.h"
41 #include "snapshot.h"
42 #include "types.h"
43 #include "util.h"
44 #include "crt.h"
45
46 /* This eprom system by DELA seems to be a bit more advanced
47 than the EP64 and EP256. It can handle what the EP64 can
48 handle, plus the following features :
49
50 - Alternate rom at $8000
51 - Alternate basic at $A000
52 - Extended basic
53 - Basic programs
54 - Simulated 16kb roms
55 - Kernel replacement
56
57 The system uses 8 8kb eproms, of which the first is used for
58 the base menu. 7 8kb banks are used for above named features.
59
60 Because of the fact that this system supports switching in a
61 different eprom at $8000 (followed by a reset) it is possible
62 to place generic 8kb carts (games/tools) in the eproms and
63 use them.
64
65 The bank selecting is done by writing to $DE00. Each low bit is used to
66 bank in the respective eprom. If all bits are high then the EXROM is
67 switched off.
68
69 The bit values for each eprom bank is:
70
71 eprom bank 1 : 11111110 ($FE) (base eprom)
72 eprom bank 2 : 11111101 ($FD)
73 eprom bank 3 : 11111011 ($FB)
74 eprom bank 4 : 11110111 ($F7)
75 eprom bank 5 : 11101111 ($EF)
76 eprom bank 6 : 11011111 ($DF)
77 eprom bank 7 : 10111111 ($BF)
78 eprom bank 8 : 01111111 ($7F)
79
80 EXROM off : 11111111 ($FF)
81 */
82
83 /* ---------------------------------------------------------------------*/
84
85 static int currbank = 0;
86
87 static uint8_t regval = 0xfe;
88
delaep7x8_io1_store(uint16_t addr,uint8_t value)89 static void delaep7x8_io1_store(uint16_t addr, uint8_t value)
90 {
91 uint8_t bank, config, test_value;
92
93 regval = value;
94
95 /* Each bit of the register set to low activates a
96 respective EPROM, $FF switches off EXROM */
97 config = (value == 0xff) ? 2 : 0;
98
99 cart_config_changed_slotmain(config, config, CMODE_WRITE);
100
101 bank = 0;
102 test_value = (~value);
103 while (test_value != 0) {
104 bank++;
105 test_value = (test_value >> 1);
106 }
107 if (bank != 0) {
108 cart_romlbank_set_slotmain(bank - 1);
109 currbank = bank - 1;
110 }
111 }
112
delaep7x8_io1_peek(uint16_t addr)113 static uint8_t delaep7x8_io1_peek(uint16_t addr)
114 {
115 return regval;
116 }
117
delaep7x8_dump(void)118 static int delaep7x8_dump(void)
119 {
120 mon_out("Currently active EPROM bank: %d, cart status: %s\n",
121 currbank,
122 (regval == 0xff) ? "Disabled" : "Enabled");
123 return 0;
124 }
125
126 /* ---------------------------------------------------------------------*/
127
128 static io_source_t delaep7x8_device = {
129 CARTRIDGE_NAME_DELA_EP7x8,
130 IO_DETACH_CART,
131 NULL,
132 0xde00, 0xdeff, 0xff,
133 0,
134 delaep7x8_io1_store,
135 NULL,
136 delaep7x8_io1_peek,
137 delaep7x8_dump,
138 CARTRIDGE_DELA_EP7x8,
139 0,
140 0
141 };
142
143 static io_source_list_t *delaep7x8_list_item = NULL;
144
145 static const export_resource_t export_res = {
146 CARTRIDGE_NAME_DELA_EP7x8, 0, 1, &delaep7x8_device, NULL, CARTRIDGE_DELA_EP7x8
147 };
148
149 /* ---------------------------------------------------------------------*/
150
delaep7x8_config_init(void)151 void delaep7x8_config_init(void)
152 {
153 cart_config_changed_slotmain(0, 0, CMODE_READ);
154 cart_romlbank_set_slotmain(0);
155 }
156
delaep7x8_config_setup(uint8_t * rawcart)157 void delaep7x8_config_setup(uint8_t *rawcart)
158 {
159 memcpy(roml_banks, rawcart, 0x2000 * 8);
160 cart_config_changed_slotmain(0, 0, CMODE_READ);
161 cart_romlbank_set_slotmain(0);
162 }
163
164 /* ---------------------------------------------------------------------*/
165
delaep7x8_common_attach(void)166 static int delaep7x8_common_attach(void)
167 {
168 if (export_add(&export_res) < 0) {
169 return -1;
170 }
171 delaep7x8_list_item = io_source_register(&delaep7x8_device);
172 return 0;
173 }
174
delaep7x8_bin_attach(const char * filename,uint8_t * rawcart)175 int delaep7x8_bin_attach(const char *filename, uint8_t *rawcart)
176 {
177 int size = 0x10000;
178
179 memset(rawcart, 0xff, 0x10000);
180
181 while (size != 0) {
182 if (util_file_load(filename, rawcart, size, UTIL_FILE_LOAD_SKIP_ADDRESS) < 0) {
183 size -= 0x2000;
184 } else {
185 return delaep7x8_common_attach();
186 }
187 }
188 return -1;
189 }
190
delaep7x8_crt_attach(FILE * fd,uint8_t * rawcart)191 int delaep7x8_crt_attach(FILE *fd, uint8_t *rawcart)
192 {
193 crt_chip_header_t chip;
194
195 memset(rawcart, 0xff, 0x10000);
196
197 while (1) {
198 if (crt_read_chip_header(&chip, fd)) {
199 break;
200 }
201
202 if (chip.bank > 7 || chip.size != 0x2000) {
203 return -1;
204 }
205
206 if (crt_read_chip(rawcart, chip.bank << 13, &chip, fd)) {
207 return -1;
208 }
209 }
210 return delaep7x8_common_attach();
211 }
212
delaep7x8_detach(void)213 void delaep7x8_detach(void)
214 {
215 export_remove(&export_res);
216 io_source_unregister(delaep7x8_list_item);
217 delaep7x8_list_item = NULL;
218 }
219
220 /* ---------------------------------------------------------------------*/
221
222 /* CARTDELAEP7X8 snapshot module format:
223
224 type | name | version | description
225 --------------------------------------
226 BYTE | regval | 0.1 | register
227 BYTE | bank | 0.0+ | current bank
228 ARRAY | ROML | 0.0+ | 65536 BYTES of ROML data
229 */
230
231 static char snap_module_name[] = "CARTDELAEP7X8";
232 #define SNAP_MAJOR 0
233 #define SNAP_MINOR 1
234
delaep7x8_snapshot_write_module(snapshot_t * s)235 int delaep7x8_snapshot_write_module(snapshot_t *s)
236 {
237 snapshot_module_t *m;
238
239 m = snapshot_module_create(s, snap_module_name, SNAP_MAJOR, SNAP_MINOR);
240
241 if (m == NULL) {
242 return -1;
243 }
244
245 if (0
246 || (SMW_B(m, regval) < 0)
247 || (SMW_B(m, (uint8_t)currbank) < 0)
248 || (SMW_BA(m, roml_banks, 0x2000 * 8) < 0)) {
249 snapshot_module_close(m);
250 return -1;
251 }
252
253 return snapshot_module_close(m);
254 }
255
delaep7x8_snapshot_read_module(snapshot_t * s)256 int delaep7x8_snapshot_read_module(snapshot_t *s)
257 {
258 uint8_t vmajor, vminor;
259 snapshot_module_t *m;
260
261 m = snapshot_module_open(s, snap_module_name, &vmajor, &vminor);
262
263 if (m == NULL) {
264 return -1;
265 }
266
267 /* Do not accept versions higher than current */
268 if (vmajor > SNAP_MAJOR || vminor > SNAP_MINOR) {
269 snapshot_set_error(SNAPSHOT_MODULE_HIGHER_VERSION);
270 goto fail;
271 }
272
273 /* new in 0.1 */
274 if (SNAPVAL(vmajor, vminor, 0, 1)) {
275 if (SMR_B(m, ®val) < 0) {
276 goto fail;
277 }
278 } else {
279 regval = 0;
280 }
281
282 if (0
283 || (SMR_B_INT(m, &currbank) < 0)
284 || (SMR_BA(m, roml_banks, 0x2000 * 8) < 0)) {
285 goto fail;
286 }
287
288 snapshot_module_close(m);
289
290 return delaep7x8_common_attach();
291
292 fail:
293 snapshot_module_close(m);
294 return -1;
295 }
296