1 /*
2  * vic20memsnapshot.c - VIC20 memory snapshot handling.
3  *
4  * Written by
5  *  Ettore Perazzoli <ettore@comm2000.it>
6  *  Andre Fachat <fachat@physik.tu-chemnitz.de>
7  *  Andreas Boose <viceteam@t-online.de>
8  *
9  * Multiple memory configuration support originally by
10  *  Alexander Lehmann <alex@mathematik.th-darmstadt.de>
11  *
12  * This file is part of VICE, the Versatile Commodore Emulator.
13  * See README for copyright notice.
14  *
15  *  This program is free software; you can redistribute it and/or modify
16  *  it under the terms of the GNU General Public License as published by
17  *  the Free Software Foundation; either version 2 of the License, or
18  *  (at your option) any later version.
19  *
20  *  This program is distributed in the hope that it will be useful,
21  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
22  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  *  GNU General Public License for more details.
24  *
25  *  You should have received a copy of the GNU General Public License
26  *  along with this program; if not, write to the Free Software
27  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28  *  02111-1307  USA.
29  *
30  */
31 
32 #include "vice.h"
33 
34 #include <stdio.h>
35 #include <string.h>
36 
37 #ifdef HAVE_MEMORY_H
38 #include <memory.h>
39 #endif
40 
41 #include "cart/vic20cart.h"
42 #include "log.h"
43 #include "mem.h"
44 #include "resources.h"
45 #include "snapshot.h"
46 #include "types.h"
47 #include "vic20-resources.h"
48 #include "vic20mem.h"
49 #include "vic20memrom.h"
50 #include "vic20memsnapshot.h"
51 #include "vic20rom.h"
52 
53 
54 static log_t vic20_snapshot_log = LOG_ERR;
55 
56 /************************************************************************/
57 
58 /*
59  * VIC20 memory dump contains the available memory at the moment
60  */
61 #define VIC20MEM_DUMP_VER_MAJOR   1
62 #define VIC20MEM_DUMP_VER_MINOR   1
63 #define SNAP_MEM_MODULE_NAME      "VIC20MEM"
64 
65 /*
66  * UBYTE        CONFIG          Bit 0: 1 = expansion block 0 RAM enabled
67  *                                  1: 1 = expansion block 1 RAM enabled
68  *                                  2: 1 = expansion block 2 RAM enabled
69  *                                  3: 1 = expansion block 3 RAM enabled
70  *                                  5: 1 = expansion block 5 RAM enabled
71  *
72  * UBYTE        cpu_last_data
73  * UBYTE        v_bus_last_data
74  * UBYTE        v_bus_last_high
75  * ARRAY        RAM0            1k RAM $0000-$03ff
76  * ARRAY        RAM1            4k RAM $1000-$1fff
77  * ARRAY        BLK0            3k RAM $0400-$0fff (if blk 0 RAM enabled)
78  * ARRAY        BLK1            8k RAM $2000-$3fff (if blk 1 RAM enabled)
79  * ARRAY        BLK2            8k RAM $4000-$5fff (if blk 2 RAM enabled)
80  * ARRAY        BLK3            8k RAM $6000-$7fff (if blk 3 RAM enabled)
81  * ARRAY        BLK5            8k RAM $A000-$Bfff (if blk 5 RAM enabled)
82  *
83  */
84 
85 
mem_write_ram_snapshot_module(snapshot_t * p)86 static int mem_write_ram_snapshot_module(snapshot_t *p)
87 {
88     snapshot_module_t *m;
89     uint8_t config;
90 
91     config = (ram_block_0_enabled ? 1 : 0)
92              | (ram_block_1_enabled ? 2 : 0)
93              | (ram_block_2_enabled ? 4 : 0)
94              | (ram_block_3_enabled ? 8 : 0)
95              | (ram_block_5_enabled ? 32 : 0);
96 
97     m = snapshot_module_create(p, SNAP_MEM_MODULE_NAME,
98                                VIC20MEM_DUMP_VER_MAJOR,
99                                VIC20MEM_DUMP_VER_MINOR);
100     if (m == NULL) {
101         return -1;
102     }
103 
104     SMW_B(m, config);
105 
106     SMW_B(m, vic20_cpu_last_data);
107     SMW_B(m, vic20_v_bus_last_data);
108     SMW_B(m, vic20_v_bus_last_high);
109 
110     SMW_BA(m, mem_ram, 0x0400);
111     SMW_BA(m, mem_ram + 0x1000, 0x1000);
112 
113     if (config & 1) {
114         SMW_BA(m, mem_ram + 0x0400, 0x0c00);
115     }
116     if (config & 2) {
117         SMW_BA(m, mem_ram + 0x2000, 0x2000);
118     }
119     if (config & 4) {
120         SMW_BA(m, mem_ram + 0x4000, 0x2000);
121     }
122     if (config & 8) {
123         SMW_BA(m, mem_ram + 0x6000, 0x2000);
124     }
125     if (config & 32) {
126         SMW_BA(m, mem_ram + 0xA000, 0x2000);
127     }
128 
129     snapshot_module_close(m);
130 
131     return 0;
132 }
133 
mem_read_ram_snapshot_module(snapshot_t * p)134 static int mem_read_ram_snapshot_module(snapshot_t *p)
135 {
136     uint8_t vmajor, vminor;
137     snapshot_module_t *m;
138     uint8_t config;
139 
140     m = snapshot_module_open(p, SNAP_MEM_MODULE_NAME, &vmajor, &vminor);
141     if (m == NULL) {
142         return -1;
143     }
144 
145     if (vmajor != VIC20MEM_DUMP_VER_MAJOR) {
146         snapshot_module_close(m);
147         return -1;
148     }
149 
150     SMR_B(m, &config);
151 
152     SMR_B(m, &vic20_cpu_last_data);
153     SMR_B(m, &vic20_v_bus_last_data);
154     SMR_B(m, &vic20_v_bus_last_high);
155 
156     SMR_BA(m, mem_ram, 0x0400);
157     SMR_BA(m, mem_ram + 0x1000, 0x1000);
158 
159     resources_set_int("RAMBlock0", (config & 1) ? 1 : 0 );
160     if (config & 1) {
161         SMR_BA(m, mem_ram + 0x0400, 0x0c00);
162     }
163     resources_set_int("RAMBlock1", (config & 2) ? 1 : 0 );
164     if (config & 2) {
165         SMR_BA(m, mem_ram + 0x2000, 0x2000);
166     }
167     resources_set_int("RAMBlock2", (config & 4) ? 1 : 0 );
168     if (config & 4) {
169         SMR_BA(m, mem_ram + 0x4000, 0x2000);
170     }
171     resources_set_int("RAMBlock3", (config & 8) ? 1 : 0 );
172     if (config & 8) {
173         SMR_BA(m, mem_ram + 0x6000, 0x2000);
174     }
175     resources_set_int("RAMBlock5", (config & 32) ? 1 : 0 );
176     if (config & 32) {
177         SMR_BA(m, mem_ram + 0xA000, 0x2000);
178     }
179 
180     snapshot_module_close(m);
181 
182     mem_initialize_memory();
183 
184     return 0;
185 }
186 
187 /*
188  * VIC20 ROM dump
189  */
190 #define VIC20ROM_DUMP_VER_MAJOR   1
191 #define VIC20ROM_DUMP_VER_MINOR   1
192 #define SNAP_ROM_MODULE_NAME      "VIC20ROM"
193 
194 /*
195  * UBYTE        CONFIG          Bit 0: 1 = ROM block $2*** enabled
196  *                                  1: 1 = ROM block $3*** enabled
197  *                                  2: 1 = ROM block $4*** enabled
198  *                                  3: 1 = ROM block $5*** enabled
199  *                                  4: 1 = ROM block $6*** enabled
200  *                                  5: 1 = ROM block $7*** enabled
201  *                                  6: 1 = ROM block $A*** enabled
202  *                                  7: 1 = ROM block $B*** enabled
203  *
204  * ARRAY        KERNAL          8k KERNAL ROM $e000-$ffff
205  * ARRAY        BASIC           8k BASIC ROM $c000-$dfff
206  * ARRAY        CHARGEN         4k CHARGEN ROM
207  * ARRAY        BLK1A           4k ROM $2*** (if CONFIG & 1)
208  * ARRAY        BLK1B           4k ROM $3*** (if CONFIG & 2)
209  * ARRAY        BLK3A           4k ROM $6*** (if CONFIG & 16)
210  * ARRAY        BLK3B           4k ROM $7*** (if CONFIG & 32)
211  * ARRAY        BLK5A           4k ROM $A*** (if CONFIG & 64)
212  * ARRAY        BLK5B           4k ROM $B*** (if CONFIG & 128)
213  *
214  * ARRAY        BLK2A           4k ROM $4*** (if CONFIG & 4)
215  * ARRAY        BLK2B           4k ROM $5*** (if CONFIG & 8)
216  */
217 
218 
mem_write_rom_snapshot_module(snapshot_t * p,int save_roms)219 static int mem_write_rom_snapshot_module(snapshot_t *p, int save_roms)
220 {
221     snapshot_module_t *m;
222 
223     if (!save_roms) {
224         return 0;
225     }
226 
227     m = snapshot_module_create(p, SNAP_ROM_MODULE_NAME, VIC20MEM_DUMP_VER_MAJOR, VIC20MEM_DUMP_VER_MINOR);
228     if (m == NULL) {
229         return -1;
230     }
231 
232     /* old cart system config bits.  all zero = no roms */
233     SMW_B(m, 0x00);
234 
235     /* save kernal */
236     SMW_BA(m, vic20memrom_kernal_rom, 0x2000);
237     /* save basic */
238     SMW_BA(m, vic20memrom_basic_rom, 0x2000);
239 
240     SMW_BA(m, vic20memrom_chargen_rom, 0x1000);
241 
242     snapshot_module_close(m);
243 
244     return 0;
245 }
246 
mem_read_rom_snapshot_module(snapshot_t * p)247 static int mem_read_rom_snapshot_module(snapshot_t *p)
248 {
249     uint8_t vmajor, vminor;
250     snapshot_module_t *m;
251     uint8_t config;
252     int trapfl;
253 
254     m = snapshot_module_open(p, SNAP_ROM_MODULE_NAME, &vmajor, &vminor);
255     if (m == NULL) {
256         return 0;       /* optional */
257     }
258 
259     if (vmajor != VIC20ROM_DUMP_VER_MAJOR) {
260         snapshot_module_close(m);
261         return -1;
262     }
263 
264     /* disable traps before loading the ROM */
265     resources_get_int("VirtualDevices", &trapfl);
266     resources_set_int("VirtualDevices", 0);
267 
268     /* old cart system ROMs (ignored) */
269     SMR_B(m, &config);
270 
271     /* read kernal */
272     SMR_BA(m, vic20memrom_kernal_rom, 0x2000);
273     /* read basic */
274     SMR_BA(m, vic20memrom_basic_rom, 0x2000);
275 
276     SMR_BA(m, vic20memrom_chargen_rom, 0x1000);
277 
278     vic20rom_kernal_checksum();
279     vic20rom_basic_checksum();
280 
281     log_warning(vic20_snapshot_log,
282                 "Dumped Romset files and saved settings will "
283                 "represent\nthe state before loading the snapshot!");
284 
285     /* enable traps again when necessary */
286     resources_set_int("VirtualDevices", trapfl);
287 
288     snapshot_module_close(m);
289 
290     mem_initialize_memory();
291 
292     return 0;
293 }
294 
vic20_snapshot_write_module(snapshot_t * m,int save_roms)295 int vic20_snapshot_write_module(snapshot_t *m, int save_roms)
296 {
297     if (mem_write_ram_snapshot_module(m) < 0
298         || mem_write_rom_snapshot_module(m, save_roms) < 0
299         || vic20cart_snapshot_write_module(m) < 0) {
300         return -1;
301     }
302     return 0;
303 }
304 
vic20_snapshot_read_module(snapshot_t * m)305 int vic20_snapshot_read_module(snapshot_t *m)
306 {
307     if (mem_read_ram_snapshot_module(m) < 0
308         || mem_read_rom_snapshot_module(m) < 0
309         || vic20cart_snapshot_read_module(m) < 0) {
310         return -1;
311     }
312     return 0;
313 }
314