1 /*
2 * cbm2memsnapshot.c - CBM-II memory snapshot handling.
3 *
4 * Written by
5 * Andre Fachat <fachat@physik.tu-chemnitz.de>
6 * Andreas Boose <viceteam@t-online.de>
7 *
8 * This file is part of VICE, the Versatile Commodore Emulator.
9 * See README for copyright notice.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
24 * 02111-1307 USA.
25 *
26 */
27
28 #include "vice.h"
29
30 #include <stdio.h>
31
32 #include "cbm2-resources.h"
33 #include "cbm2.h"
34 #include "cbm2mem.h"
35 #include "cbm2memsnapshot.h"
36 #include "cbm2rom.h"
37 #include "log.h"
38 #include "machine.h"
39 #include "mem.h"
40 #include "resources.h"
41 #include "snapshot.h"
42 #include "types.h"
43
44 static log_t cbm2_snapshot_log = LOG_ERR;
45
46 /*
47 * CBM2 memory dump should be 128, 256, 512 or 1024k, depending on the
48 * config, as RAM.
49 */
50 #define CBM2MEM_DUMP_VER_MAJOR 1
51 #define CBM2MEM_DUMP_VER_MINOR 0
52
53 /*
54 * UBYTE MEMSIZE size in 128k (1=128, 2=256, 4=512, 8=1024)
55 * UBYTE CONFIG Bit 0: cart08_ram
56 * 1: cart1_ram
57 * 2: cart2_ram
58 * 3: cart4_ram
59 * 4: cart6_ram
60 * 5: cartC_ram
61 * 6: 1= RAM starts at 0 (C500), videoram is
62 * 1k VIC-II video, 1k colorram
63 * 0= RAM starts at 0x10000 (others),
64 * videoram is 2k crtc videoram
65 *
66 * UBYTE HCONFIG Bit 0-1: ModelLine
67 *
68 * UBYTE EXECBANK CPU exec bank register
69 * UBYTE INDBANK CPU indirect bank register
70 * ARRAY SYSRAM 2k system RAM, Bank15 $0000-$07ff
71 * ARRAY VIDEO 2k video RAM, Bank15 $d000-$d7ff
72 * ARRAY RAM size according to MEMSIZE
73 * ARRAY RAM08 (only if memsize < 1M) 2k for cart08_ram
74 * ARRAY RAM1 (only if memsize < 1M) 4k for cart1_ram
75 * ARRAY RAM2 (only if memsize < 1M) 8k for cart2_ram
76 * ARRAY RAM4 (only if memsize < 1M) 8k for cart4_ram
77 * ARRAY RAM6 (only if memsize < 1M) 8k for cart6_ram
78 * ARRAY RAMC (only if memsize < 1M) 4k for cartC_ram
79 *
80 */
81
82 static const char module_name[] = "CBM2MEM";
83
mem_write_ram_snapshot_module(snapshot_t * p)84 static int mem_write_ram_snapshot_module(snapshot_t *p)
85 {
86 snapshot_module_t *m;
87 uint8_t config, memsize;
88 int effective_ramsize, effective_start;
89
90 m = snapshot_module_create(p, module_name,
91 CBM2MEM_DUMP_VER_MAJOR, CBM2MEM_DUMP_VER_MINOR);
92 if (m == NULL) {
93 return -1;
94 }
95
96 /* calculate start and size of RAM to save */
97 /* ramsize starts counting at 0x10000 if less than 512k */
98 effective_ramsize = ramsize;
99 effective_start = 0x10000;
100 if ((machine_class == VICE_MACHINE_CBM5x0) && ramsize < 512) {
101 effective_ramsize += 64;
102 }
103 if ((machine_class == VICE_MACHINE_CBM5x0) || ramsize >= 512) {
104 effective_start = 0;
105 }
106 memsize = effective_ramsize >> 7; /* rescale from 1k to 128k */
107
108 config = (cart08_ram ? 1 : 0)
109 | (cart1_ram ? 2 : 0)
110 | (cart2_ram ? 4 : 0)
111 | (cart4_ram ? 8 : 0)
112 | (cart6_ram ? 16 : 0)
113 | (cartC_ram ? 32 : 0)
114 | ((machine_class == VICE_MACHINE_CBM5x0) ? 64 : 0);
115
116 SMW_B(m, memsize);
117 SMW_B(m, config);
118 SMW_B(m, (uint8_t)(cbm2_model_line & 3));
119
120 SMW_B(m, (uint8_t)(cbm2mem_bank_exec));
121 SMW_B(m, (uint8_t)(cbm2mem_bank_ind));
122
123 SMW_BA(m, mem_ram + 0xf0000, 0x0800);
124 SMW_BA(m, mem_rom + 0xd000, 0x0800);
125
126 /* main memory array */
127 SMW_BA(m, mem_ram + effective_start, ((int)memsize) << 17);
128
129 if (memsize < 4) { /* if 1M memory, bank 15 is included */
130 if (config & 1) {
131 SMW_BA(m, mem_ram + 0xf0800, 0x0800);
132 }
133 if (config & 2) {
134 SMW_BA(m, mem_ram + 0xf1000, 0x1000);
135 }
136 if (config & 4) {
137 SMW_BA(m, mem_ram + 0xf2000, 0x2000);
138 }
139 if (config & 8) {
140 SMW_BA(m, mem_ram + 0xf4000, 0x2000);
141 }
142 if (config & 16) {
143 SMW_BA(m, mem_ram + 0xf6000, 0x2000);
144 }
145 if (config & 32) {
146 SMW_BA(m, mem_ram + 0xfc000, 0x1000);
147 }
148 }
149
150 snapshot_module_close(m);
151
152 return 0;
153 }
154
mem_read_ram_snapshot_module(snapshot_t * p)155 static int mem_read_ram_snapshot_module(snapshot_t *p)
156 {
157 uint8_t byte, vmajor, vminor;
158 snapshot_module_t *m;
159 uint8_t config, hwconfig;
160 int memsize;
161 int effective_ramsize, effective_start;
162 int bank0;
163
164 m = snapshot_module_open(p, module_name, &vmajor, &vminor);
165 if (m == NULL) {
166 return -1;
167 }
168
169 if (vmajor != CBM2MEM_DUMP_VER_MAJOR) {
170 snapshot_module_close(m);
171 return -1;
172 }
173
174 SMR_B(m, &byte);
175 memsize = ((int)byte) & 0xff;
176
177 SMR_B(m, &config);
178
179 SMR_B(m, &hwconfig);
180 resources_set_int("ModelLine", hwconfig & 3);
181
182 SMR_B(m, &byte);
183 cbm2mem_set_bank_exec(byte);
184 SMR_B(m, &byte);
185 cbm2mem_set_bank_ind(byte);
186
187 SMR_BA(m, mem_ram + 0xf0000, 0x0800);
188 SMR_BA(m, mem_rom + 0xd000, 0x0800);
189
190 /* calculate start and size of RAM to load */
191 /* ramsize starts counting at 0x10000 if less than 512k */
192 bank0 = config & 64;
193 effective_ramsize = memsize << 7;
194 effective_start = 0x10000;
195 if (bank0 || effective_ramsize >= 512) {
196 effective_start = 0;
197 }
198 if (bank0 && effective_ramsize < 512) {
199 effective_ramsize -= 64;
200 }
201
202 SMR_BA(m, mem_ram + effective_start, memsize << 17);
203
204 ramsize = effective_ramsize;
205
206 cart08_ram = config & 1;
207 cart1_ram = config & 2;
208 cart2_ram = config & 4;
209 cart4_ram = config & 8;
210 cart6_ram = config & 16;
211 cartC_ram = config & 32;
212
213 if (memsize < 4) {
214 SMR_BA(m, mem_ram + 0x10000, memsize << 17);
215 } else {
216 SMR_BA(m, mem_ram, memsize << 17);
217 }
218
219 if (memsize < 4) { /* if 1M memory, bank 15 is included */
220 if (config & 1) {
221 SMR_BA(m, mem_ram + 0xf0800, 0x0800);
222 }
223 if (config & 2) {
224 SMR_BA(m, mem_ram + 0xf1000, 0x1000);
225 }
226 if (config & 4) {
227 SMR_BA(m, mem_ram + 0xf2000, 0x2000);
228 }
229 if (config & 8) {
230 SMR_BA(m, mem_ram + 0xf4000, 0x2000);
231 }
232 if (config & 16) {
233 SMR_BA(m, mem_ram + 0xf6000, 0x2000);
234 }
235 if (config & 32) {
236 SMR_BA(m, mem_ram + 0xfc000, 0x1000);
237 }
238 }
239
240 mem_initialize_memory();
241
242 snapshot_module_close(m);
243
244 return 0;
245 }
246
247 /*********************************************************************/
248
249 /*
250 * UBYTE CONFIG Bit 1: cart1 ROM included
251 * 2: cart2 ROM included
252 * 3: cart4 ROM included
253 * 4: cart6 ROM included
254 * 5: chargen is of C510 type (VIC-II)
255 *
256 * ARRAY KERNAL 8k Kernal ROM ($e000-$ffff)
257 * ARRAY BASIC 16k Basic ROM ($8000-$bfff)
258 * ARRAY CHARGEN 4k chargen ROM image ($c*** for VIC-II)
259 * ARRAY ROM1 4k for cart1 (if config & 2)
260 * ARRAY ROM2 8k for cart2 (if config & 4)
261 * ARRAY ROM4 8k for cart4 (if config & 8)
262 * ARRAY ROM6 8k for cart6 (if config & 16)
263 */
264
265 static const char module_rom_name[] = "CBM2ROM";
266 #define CBM2ROM_DUMP_VER_MAJOR 1
267 #define CBM2ROM_DUMP_VER_MINOR 0
268
mem_write_rom_snapshot_module(snapshot_t * p,int save_roms)269 static int mem_write_rom_snapshot_module(snapshot_t *p, int save_roms)
270 {
271 snapshot_module_t *m;
272 uint8_t config;
273 int trapfl;
274 const char *cart_1_name, *cart_2_name, *cart_4_name, *cart_6_name;
275
276 if (!save_roms) {
277 return 0;
278 }
279
280 m = snapshot_module_create(p, module_rom_name,
281 CBM2ROM_DUMP_VER_MAJOR, CBM2ROM_DUMP_VER_MINOR);
282 if (m == NULL) {
283 return -1;
284 }
285
286 /* disable traps before saving the ROM */
287 resources_get_int("VirtualDevices", &trapfl);
288 resources_set_int("VirtualDevices", 0);
289
290 resources_get_string("Cart1Name", &cart_1_name);
291 resources_get_string("Cart2Name", &cart_2_name);
292 resources_get_string("Cart4Name", &cart_4_name);
293 resources_get_string("Cart6Name", &cart_6_name);
294
295 config = ((cart_1_name ? 2 : 0)
296 | (cart_2_name ? 4 : 0)
297 | (cart_4_name ? 8 : 0)
298 | (cart_6_name ? 16 : 0)
299 | ((machine_class == VICE_MACHINE_CBM5x0) ? 32 : 0));
300
301 /* SMW_B(m, save_roms & 3); */
302 SMW_B(m, config);
303
304 {
305 /* kernal */
306 SMW_BA(m, mem_rom + 0xe000, 0x2000);
307 /* basic */
308 SMW_BA(m, mem_rom + 0x8000, 0x4000);
309 /* chargen */
310 if (machine_class == VICE_MACHINE_CBM5x0) {
311 SMW_BA(m, mem_chargen_rom, 0x1000);
312 } else {
313 SMW_BA(m, mem_chargen_rom, 0x0800);
314 SMW_BA(m, mem_chargen_rom + 0x1000, 0x0800);
315 }
316
317 if (config & 2) {
318 SMW_BA(m, mem_rom + 0x1000, 0x1000);
319 }
320 if (config & 4) {
321 SMW_BA(m, mem_rom + 0x2000, 0x2000);
322 }
323 if (config & 8) {
324 SMW_BA(m, mem_rom + 0x4000, 0x2000);
325 }
326 if (config & 16) {
327 SMW_BA(m, mem_rom + 0x6000, 0x2000);
328 }
329 }
330
331 /* enable traps again when necessary */
332 resources_set_int("VirtualDevices", trapfl);
333
334 snapshot_module_close(m);
335
336 return 0;
337 }
338
mem_read_rom_snapshot_module(snapshot_t * p)339 static int mem_read_rom_snapshot_module(snapshot_t *p)
340 {
341 uint8_t vmajor, vminor;
342 snapshot_module_t *m;
343 uint8_t config;
344 int i, trapfl;
345
346 m = snapshot_module_open(p, module_rom_name, &vmajor, &vminor);
347 if (m == NULL) {
348 return 0; /* optional */
349 }
350 if (vmajor != CBM2ROM_DUMP_VER_MAJOR) {
351 snapshot_module_close(m);
352 return -1;
353 }
354
355 /* disable traps before loading the ROM */
356 resources_get_int("VirtualDevices", &trapfl);
357 resources_set_int("VirtualDevices", 0);
358
359 SMR_B(m, &config);
360
361 /* kernal */
362 SMR_BA(m, mem_rom + 0xe000, 0x2000);
363 /* basic */
364 SMR_BA(m, mem_rom + 0x8000, 0x4000);
365
366 /* chargen */
367 if (config & 32) {
368 SMR_BA(m, mem_chargen_rom, 0x1000);
369 } else {
370 SMR_BA(m, mem_chargen_rom, 0x0800);
371 SMR_BA(m, mem_chargen_rom + 0x1000, 0x0800);
372 /* Inverted chargen into second half. This is a hardware feature. */
373 for (i = 0; i < 2048; i++) {
374 mem_chargen_rom[i + 2048] = mem_chargen_rom[i] ^ 0xff;
375 mem_chargen_rom[i + 6144] = mem_chargen_rom[i + 4096] ^ 0xff;
376 }
377 }
378
379 if (config & 2) {
380 SMR_BA(m, mem_rom + 0x1000, 0x1000);
381 }
382 if (config & 4) {
383 SMR_BA(m, mem_rom + 0x2000, 0x2000);
384 }
385 if (config & 8) {
386 SMR_BA(m, mem_rom + 0x4000, 0x2000);
387 }
388 if (config & 16) {
389 SMR_BA(m, mem_rom + 0x6000, 0x2000);
390 }
391
392 log_warning(cbm2_snapshot_log,
393 "Dumped Romset files and saved settings will "
394 "represent\nthe state before loading the snapshot!");
395
396 cbm2rom_checksum();
397
398 /* enable traps again when necessary */
399 resources_set_int("VirtualDevices", trapfl);
400
401 snapshot_module_close(m);
402
403 return 0;
404 }
405
406 /*********************************************************************/
407
cbm2_snapshot_write_module(snapshot_t * p,int save_roms)408 int cbm2_snapshot_write_module(snapshot_t *p, int save_roms)
409 {
410 if (mem_write_ram_snapshot_module(p) < 0
411 || mem_write_rom_snapshot_module(p, save_roms) < 0
412 ) {
413 return -1;
414 }
415 return 0;
416 }
417
cbm2_snapshot_read_module(snapshot_t * p)418 int cbm2_snapshot_read_module(snapshot_t *p)
419 {
420 if (mem_read_ram_snapshot_module(p) < 0
421 || mem_read_rom_snapshot_module(p) < 0) {
422 return -1;
423 }
424
425 return 0;
426 }
427