1 /*
2 * gs.c - Cartridge handling, GS 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 <string.h>
31
32 #define CARTRIDGE_INCLUDE_SLOTMAIN_API
33 #include "c64cartsystem.h"
34 #undef CARTRIDGE_INCLUDE_SLOTMAIN_API
35 #include "cartio.h"
36 #include "cartridge.h"
37 #include "export.h"
38 #include "gs.h"
39 #include "monitor.h"
40 #include "snapshot.h"
41 #include "types.h"
42 #include "util.h"
43 #include "crt.h"
44
45 /*
46 C64GS (C64 Game System/System 3) Cartridge
47
48 - 512kb ROM (64*8k), mapped to $8000 in 8k game config
49
50 - reading from io1 switches to bank 0
51
52 - writing to io1 switches banks. the lower 6 bits of the address are the
53 bank number
54 */
55
56 static int currbank = 0;
57 static uint8_t regval = 0;
58
gs_io1_store(uint16_t addr,uint8_t value)59 static void gs_io1_store(uint16_t addr, uint8_t value)
60 {
61 addr &= 0xff;
62 regval = value;
63 currbank = addr & 0x3f;
64 cart_romlbank_set_slotmain(currbank);
65 /* 8k config */
66 cart_set_port_exrom_slotmain(1);
67 cart_set_port_game_slotmain(0);
68 cart_port_config_changed_slotmain();
69 /* printf("C64GS: w addr: $de%02x value: $%02x bank: $%02x\n", addr, value, currbank); */
70 }
71
gs_io1_read(uint16_t addr)72 static uint8_t gs_io1_read(uint16_t addr)
73 {
74 currbank = 0;
75 /* 8k configuration */
76 cart_config_changed_slotmain(0, 0, CMODE_READ);
77 /* printf("C64GS: r addr: $de%02x\n", addr); */
78 return 0;
79 }
80
gs_io1_peek(uint16_t addr)81 static uint8_t gs_io1_peek(uint16_t addr)
82 {
83 return regval;
84 }
85
gs_dump(void)86 static int gs_dump(void)
87 {
88 mon_out("Bank: %d\n", currbank);
89 return 0;
90 }
91
92 /* ---------------------------------------------------------------------*/
93
94 static io_source_t gs_device = {
95 CARTRIDGE_NAME_GS,
96 IO_DETACH_CART,
97 NULL,
98 0xde00, 0xdeff, 0xff,
99 0, /* read is never valid */
100 gs_io1_store,
101 gs_io1_read,
102 gs_io1_peek,
103 gs_dump,
104 CARTRIDGE_GS,
105 0,
106 0
107 };
108
109 static io_source_list_t *gs_list_item = NULL;
110
111 static const export_resource_t export_res = {
112 CARTRIDGE_NAME_GS, 0, 1, &gs_device, NULL, CARTRIDGE_GS
113 };
114
115 /* ---------------------------------------------------------------------*/
116
gs_config_init(void)117 void gs_config_init(void)
118 {
119 /* 8k configuration */
120 cart_config_changed_slotmain(0, 0, CMODE_READ);
121 gs_io1_store((uint16_t)0xde00, 0);
122 }
123
gs_config_setup(uint8_t * rawcart)124 void gs_config_setup(uint8_t *rawcart)
125 {
126 memcpy(roml_banks, rawcart, 0x2000 * 64);
127 /* 8k configuration */
128 cart_config_changed_slotmain(0, 0, CMODE_READ);
129 }
130
131 /* ---------------------------------------------------------------------*/
gs_common_attach(void)132 static int gs_common_attach(void)
133 {
134 if (export_add(&export_res) < 0) {
135 return -1;
136 }
137 gs_list_item = io_source_register(&gs_device);
138 return 0;
139 }
140
gs_bin_attach(const char * filename,uint8_t * rawcart)141 int gs_bin_attach(const char *filename, uint8_t *rawcart)
142 {
143 if (util_file_load(filename, rawcart, 0x80000, UTIL_FILE_LOAD_SKIP_ADDRESS) < 0) {
144 return -1;
145 }
146 return gs_common_attach();
147 }
148
gs_crt_attach(FILE * fd,uint8_t * rawcart)149 int gs_crt_attach(FILE *fd, uint8_t *rawcart)
150 {
151 crt_chip_header_t chip;
152
153 while (1) {
154 if (crt_read_chip_header(&chip, fd)) {
155 break;
156 }
157 if (chip.bank > 63 || (chip.start != 0x8000) || chip.size != 0x2000) {
158 return -1;
159 }
160 if (crt_read_chip(rawcart, chip.bank << 13, &chip, fd)) {
161 return -1;
162 }
163 }
164 return gs_common_attach();
165 }
166
gs_detach(void)167 void gs_detach(void)
168 {
169 export_remove(&export_res);
170 io_source_unregister(gs_list_item);
171 gs_list_item = NULL;
172 }
173
174 /* ---------------------------------------------------------------------*/
175
176 #define CART_DUMP_VER_MAJOR 1
177 #define CART_DUMP_VER_MINOR 1
178 #define SNAP_MODULE_NAME "CARTGS"
179
gs_snapshot_write_module(snapshot_t * s)180 int gs_snapshot_write_module(snapshot_t *s)
181 {
182 snapshot_module_t *m;
183
184 m = snapshot_module_create(s, SNAP_MODULE_NAME,
185 CART_DUMP_VER_MAJOR, CART_DUMP_VER_MINOR);
186 if (m == NULL) {
187 return -1;
188 }
189
190 if (0
191 || (SMW_B(m, regval) < 0)
192 || (SMW_B(m, (uint8_t)currbank) < 0)
193 || (SMW_BA(m, roml_banks, 0x2000 * 64) < 0)) {
194 snapshot_module_close(m);
195 return -1;
196 }
197
198 snapshot_module_close(m);
199 return 0;
200 }
201
gs_snapshot_read_module(snapshot_t * s)202 int gs_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 if (m == NULL) {
209 return -1;
210 }
211
212 if ((vmajor != CART_DUMP_VER_MAJOR) || (vminor != CART_DUMP_VER_MINOR)) {
213 snapshot_module_close(m);
214 return -1;
215 }
216
217 if (0
218 || (SMR_B(m, ®val) < 0)
219 || (SMR_B_INT(m, &currbank) < 0)
220 || (SMR_BA(m, roml_banks, 0x2000 * 64) < 0)) {
221 snapshot_module_close(m);
222 return -1;
223 }
224
225 snapshot_module_close(m);
226
227 return gs_common_attach();
228 }
229