1 /*
2  * stb.c - Cartridge handling, Structured Basic cart.
3  *
4  * Written by
5  *  Walter Zimmer, adapted from kcs.c
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 "export.h"
39 #include "monitor.h"
40 #include "snapshot.h"
41 #include "stb.h"
42 #include "types.h"
43 #include "util.h"
44 #include "crt.h"
45 
46 /* Structured Basic IO1 logic for the roml range $8000-$9fff
47 *
48 *  Any read/write access for IO/1 latch the lower two address bits:
49 *  - bit 1 selects bank 1 of the stb rom
50 *  - bit 0 and bit 1 set deactivate EXROM and expose the RAM
51 */
52 
53 /* ---------------------------------------------------------------------*/
54 
55 static uint8_t stb_io1_read(uint16_t addr);
56 static uint8_t stb_io1_peek(uint16_t addr);
57 static void stb_io1_store(uint16_t addr, uint8_t value);
58 static int stb_dump(void);
59 
60 static io_source_t stb_device = {
61     CARTRIDGE_NAME_STRUCTURED_BASIC,
62     IO_DETACH_CART,
63     NULL,
64     0xde00, 0xdeff, 0xff,
65     0, /* read is never valid */
66     stb_io1_store,
67     stb_io1_read,
68     stb_io1_peek,
69     stb_dump,
70     CARTRIDGE_STRUCTURED_BASIC,
71     0,
72     0
73 };
74 
75 static io_source_list_t *stb_list_item = NULL;
76 
77 static const export_resource_t export_res = {
78     CARTRIDGE_NAME_STRUCTURED_BASIC, 1, 0, &stb_device, NULL, CARTRIDGE_STRUCTURED_BASIC
79 };
80 
81 /* ---------------------------------------------------------------------*/
82 
83 static int stb_bank = 0;
84 static int stb_active = 0;
85 
stb_io(uint16_t addr)86 static void stb_io(uint16_t addr)
87 {
88     switch (addr & 3) {
89         /* normal config: bank 0 visible */
90         case 0:
91         case 1:
92             cart_config_changed_slotmain(0, 0, CMODE_READ);
93             stb_bank = 0;
94             stb_active = 1;
95             break;
96 
97         /* bank 1 visible, gets copied to RAM during reset */
98         case 2:
99             cart_config_changed_slotmain(0 | (1 << CMODE_BANK_SHIFT), 0 | (1 << CMODE_BANK_SHIFT), CMODE_READ);
100             stb_bank = 1;
101             stb_active = 1;
102             break;
103 
104         /* RAM visible, which contains bank 1 */
105         case 3:
106             cart_config_changed_slotmain(2, 2, CMODE_READ);
107             stb_bank = 1;
108             stb_active = 0;
109             break;
110     }
111 }
112 
stb_io1_read(uint16_t addr)113 static uint8_t stb_io1_read(uint16_t addr)
114 {
115     stb_io(addr);
116     return 0;
117 }
118 
stb_io1_peek(uint16_t addr)119 static uint8_t stb_io1_peek(uint16_t addr)
120 {
121     return 0;
122 }
123 
stb_io1_store(uint16_t addr,uint8_t value)124 static void stb_io1_store(uint16_t addr, uint8_t value)
125 {
126     stb_io(addr);
127 }
128 
stb_dump(void)129 static int stb_dump(void)
130 {
131     mon_out("$8000-$9FFF ROM: %s\n", (stb_active) ? "enabled" : "disabled");
132     if (stb_active) {
133         mon_out("bank: %d\n", stb_bank);
134     }
135     return 0;
136 }
137 
138 /* ---------------------------------------------------------------------*/
139 
stb_config_init(void)140 void stb_config_init(void)
141 {
142     /* turn on normal config: bank 0 */
143     cart_config_changed_slotmain(0, 0, CMODE_READ);
144     stb_bank = 0;
145     stb_active = 1;
146 }
147 
stb_config_setup(uint8_t * rawcart)148 void stb_config_setup(uint8_t *rawcart)
149 {
150     /* copy banks 0 and 1 */
151     memcpy(roml_banks, rawcart, 0x4000);
152 
153     /* turn on normal config: bank 0 */
154     cart_config_changed_slotmain(0, 0, CMODE_READ);
155     stb_bank = 0;
156     stb_active = 1;
157 }
158 
159 /* ---------------------------------------------------------------------*/
160 
stb_common_attach(void)161 static int stb_common_attach(void)
162 {
163     /* add export */
164     if (export_add(&export_res) < 0) {
165         return -1;
166     }
167 
168     stb_list_item = io_source_register(&stb_device);
169 
170     return 0;
171 }
172 
stb_bin_attach(const char * filename,uint8_t * rawcart)173 int stb_bin_attach(const char *filename, uint8_t *rawcart)
174 {
175     /* load file into cartridge address space */
176     if (util_file_load(filename, rawcart, 0x4000, UTIL_FILE_LOAD_RAW) < 0) {
177         return -1;
178     }
179 
180     return stb_common_attach();
181 }
182 
stb_crt_attach(FILE * fd,uint8_t * rawcart)183 int stb_crt_attach(FILE *fd, uint8_t *rawcart)
184 {
185     crt_chip_header_t chip;
186 
187     while (1) {
188         if (crt_read_chip_header(&chip, fd)) {
189             break;
190         }
191 
192         if (chip.start != 0x8000 || chip.size != 0x2000 || chip.bank > 1) {
193             return -1;
194         }
195 
196         if (crt_read_chip(rawcart, chip.bank << 13, &chip, fd)) {
197             return -1;
198         }
199     }
200 
201     return stb_common_attach();
202 }
203 
stb_detach(void)204 void stb_detach(void)
205 {
206     export_remove(&export_res);
207     io_source_unregister(stb_list_item);
208     stb_list_item = NULL;
209 }
210 
211 /* ---------------------------------------------------------------------*/
212 
213 /* CARTSTB snapshot module format:
214 
215    type  | name   | version | description
216    --------------------------------------
217    BYTE  | bank   |   0.1   | current bank
218    BYTE  | active |   0.1   | cartridge active flag
219    ARRAY | ROML   |   0.0+  | 16384 BYTES of ROML data
220  */
221 
222 static char snap_module_name[] = "CARTSTB";
223 #define SNAP_MAJOR   0
224 #define SNAP_MINOR   1
225 
stb_snapshot_write_module(snapshot_t * s)226 int stb_snapshot_write_module(snapshot_t *s)
227 {
228     snapshot_module_t *m;
229 
230     m = snapshot_module_create(s, snap_module_name, SNAP_MAJOR, SNAP_MINOR);
231 
232     if (m == NULL) {
233         return -1;
234     }
235 
236     if (0
237         || SMW_B(m, (uint8_t)stb_bank) < 0
238         || SMW_B(m, (uint8_t)stb_active) < 0
239         || SMW_BA(m, roml_banks, 0x4000) < 0) {
240         snapshot_module_close(m);
241         return -1;
242     }
243 
244     return snapshot_module_close(m);
245 }
246 
stb_snapshot_read_module(snapshot_t * s)247 int stb_snapshot_read_module(snapshot_t *s)
248 {
249     uint8_t vmajor, vminor;
250     snapshot_module_t *m;
251 
252     m = snapshot_module_open(s, snap_module_name, &vmajor, &vminor);
253 
254     if (m == NULL) {
255         return -1;
256     }
257 
258     /* Do not accept versions higher than current */
259     if (vmajor > SNAP_MAJOR || vminor > SNAP_MINOR) {
260         snapshot_set_error(SNAPSHOT_MODULE_HIGHER_VERSION);
261         goto fail;
262     }
263 
264     /* new in 0.1 */
265     if (SNAPVAL(vmajor, vminor, 0, 1)) {
266         if (0
267             || SMR_B_INT(m, &stb_bank) < 0
268             || SMR_B_INT(m, &stb_active) < 0) {
269             goto fail;
270         }
271     } else {
272         stb_bank = 0;
273         stb_active = 0;
274     }
275 
276     if (SMR_BA(m, roml_banks, 0x4000) < 0) {
277         goto fail;
278     }
279 
280     snapshot_module_close(m);
281 
282     return stb_common_attach();
283 
284 fail:
285     snapshot_module_close(m);
286     return -1;
287 }
288