1 /*
2 * maxbasic.c - Cartridge handling, max-basic 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 <string.h>
31
32 #define CARTRIDGE_INCLUDE_SLOTMAIN_API
33 #include "c64cartsystem.h"
34 #undef CARTRIDGE_INCLUDE_SLOTMAIN_API
35 #include "c64mem.h"
36 #include "c64memrom.h"
37 #include "c64rom.h"
38 #include "cartio.h"
39 #include "cartridge.h"
40 #include "maxbasic.h"
41 #include "export.h"
42 #include "resources.h"
43 #include "snapshot.h"
44 #include "types.h"
45 #include "util.h"
46 #include "crt.h"
47
48 /*
49 MAX Basic
50
51 16K ROM
52 - ROM is mapped to $8000 and $e000 using ultimax mode
53
54 2K RAM
55 - RAM is mapped to $0800
56 */
57
58 static const export_resource_t export_res = {
59 CARTRIDGE_NAME_MAX_BASIC, 0, 1, NULL, NULL, CARTRIDGE_MAX_BASIC
60 };
61
62 /* ---------------------------------------------------------------------*/
63
maxbasic_0800_0fff_read(uint16_t addr)64 uint8_t maxbasic_0800_0fff_read(uint16_t addr)
65 {
66 return export_ram0[addr & 0x07ff];
67 }
68
maxbasic_0800_0fff_store(uint16_t addr,uint8_t value)69 void maxbasic_0800_0fff_store(uint16_t addr, uint8_t value)
70 {
71 export_ram0[addr & 0x07ff] = value;
72 }
73
maxbasic_roml_read(uint16_t addr)74 uint8_t maxbasic_roml_read(uint16_t addr)
75 {
76 return roml_banks[(addr & 0x1fff)];
77 }
78
maxbasic_romh_read(uint16_t addr)79 uint8_t maxbasic_romh_read(uint16_t addr)
80 {
81 return romh_banks[(addr & 0x1fff)];
82 }
83
maxbasic_peek_mem(export_t * ex,uint16_t addr,uint8_t * value)84 int maxbasic_peek_mem(export_t *ex, uint16_t addr, uint8_t *value)
85 {
86 if (addr >= 0xe000) {
87 *value = romh_banks[addr & 0x1fff];
88 return CART_READ_VALID;
89 } else if ((addr >= 0xa000) && (addr <= 0xbfff)) {
90 *value = roml_banks[addr & 0x1fff];
91 return CART_READ_VALID;
92 } else if ((addr >= 0x0800) && (addr <= 0x0fff)) {
93 *value = export_ram0[addr & 0x07ff];
94 return CART_READ_VALID;
95 }
96 return CART_READ_THROUGH;
97 }
98
maxbasic_config_init(void)99 void maxbasic_config_init(void)
100 {
101 cart_config_changed_slotmain(3, 3, CMODE_READ);
102 }
103
104 /* ---------------------------------------------------------------------*/
105
maxbasic_config_setup(uint8_t * rawcart)106 void maxbasic_config_setup(uint8_t *rawcart)
107 {
108 memcpy(&roml_banks[0x0000], &rawcart[0x0000], 0x2000);
109 memcpy(&romh_banks[0x0000], &rawcart[0x2000], 0x2000);
110 cart_config_changed_slotmain(3, 3, CMODE_READ);
111 }
112
113 /* ---------------------------------------------------------------------*/
114
maxbasic_common_attach(void)115 static int maxbasic_common_attach(void)
116 {
117 if (export_add(&export_res) < 0) {
118 return -1;
119 }
120 return 0;
121 }
122
maxbasic_bin_attach(const char * filename,uint8_t * rawcart)123 int maxbasic_bin_attach(const char *filename, uint8_t *rawcart)
124 {
125 if (util_file_load(filename, rawcart, 0x4000, UTIL_FILE_LOAD_SKIP_ADDRESS) < 0) {
126 return -1;
127 }
128
129 return maxbasic_common_attach();
130 }
131
maxbasic_crt_attach(FILE * fd,uint8_t * rawcart)132 int maxbasic_crt_attach(FILE *fd, uint8_t *rawcart)
133 {
134 crt_chip_header_t chip;
135 int i;
136
137 for (i = 0; i < 2; i++) {
138 if (crt_read_chip_header(&chip, fd)) {
139 return -1;
140 }
141
142 if (chip.size != 0x2000) {
143 return -1;
144 }
145
146 if (crt_read_chip(rawcart + (i * 0x2000), 0, &chip, fd)) {
147 return -1;
148 }
149 }
150
151 return maxbasic_common_attach();
152 }
153
maxbasic_detach(void)154 void maxbasic_detach(void)
155 {
156 export_remove(&export_res);
157 }
158
159 /* ---------------------------------------------------------------------*/
160
161 /* CARTMAXBASIC snapshot module format:
162
163 type | name | description
164 --------------------------
165 ARRAY | ROML | 8192 BYTES of ROML data
166 ARRAY | ROMH | 8192 BYTES of ROMH data
167 ARRAY | RAM | 2048 BYTES of RAM data
168 */
169
170 static const char snap_module_name[] = "CARTMAXBASIC";
171 #define SNAP_MAJOR 0
172 #define SNAP_MINOR 0
173
maxbasic_snapshot_write_module(snapshot_t * s)174 int maxbasic_snapshot_write_module(snapshot_t *s)
175 {
176 snapshot_module_t *m;
177
178 m = snapshot_module_create(s, snap_module_name, SNAP_MAJOR, SNAP_MINOR);
179
180 if (m == NULL) {
181 return -1;
182 }
183
184 if (SMW_BA(m, roml_banks, 0x2000) < 0) {
185 snapshot_module_close(m);
186 return -1;
187 }
188
189 if (SMW_BA(m, romh_banks, 0x2000) < 0) {
190 snapshot_module_close(m);
191 return -1;
192 }
193
194 if (SMW_BA(m, export_ram0, 0x0800) < 0) {
195 snapshot_module_close(m);
196 return -1;
197 }
198
199 return snapshot_module_close(m);
200 }
201
maxbasic_snapshot_read_module(snapshot_t * s)202 int maxbasic_snapshot_read_module(snapshot_t *s)
203 {
204 uint8_t vmajor, vminor;
205 snapshot_module_t *m;
206
207 m = snapshot_module_open(s, snap_module_name, &vmajor, &vminor);
208
209 if (m == NULL) {
210 return -1;
211 }
212
213 /* Do not accept versions higher than current */
214 if (snapshot_version_is_bigger(vmajor, vminor, SNAP_MAJOR, SNAP_MINOR)) {
215 snapshot_set_error(SNAPSHOT_MODULE_HIGHER_VERSION);
216 goto fail;
217 }
218
219 if (SMR_BA(m, roml_banks, 0x2000) < 0) {
220 goto fail;
221 }
222
223 if (SMR_BA(m, romh_banks, 0x2000) < 0) {
224 goto fail;
225 }
226
227 if (SMR_BA(m, export_ram0, 0x0800) < 0) {
228 goto fail;
229 }
230
231 snapshot_module_close(m);
232
233 return maxbasic_common_attach();
234
235 fail:
236 snapshot_module_close(m);
237 return -1;
238 }
239