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