1 /*
2 * c64rom.c
3 *
4 * Written by
5 * Andreas Boose <viceteam@t-online.de>
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 #include "c64-resources.h"
33 #include "c64mem.h"
34 #include "c64memrom.h"
35 #include "c64rom.h"
36 #include "log.h"
37 #include "machine.h"
38 #include "mem.h"
39 #include "patchrom.h"
40 #include "resources.h"
41 #include "sysfile.h"
42 #include "types.h"
43
44 int kernal_revision_cmdline = -1;
45
46 static log_t c64rom_log = LOG_ERR;
47
48 /* Flag: nonzero if the Kernal and BASIC ROMs have been loaded. */
49 static int rom_loaded = 0;
50
c64rom_isloaded(void)51 int c64rom_isloaded(void)
52 {
53 return rom_loaded;
54 }
55
c64rom_get_kernal_chksum_id(uint16_t * sumout,int * idout)56 int c64rom_get_kernal_chksum_id(uint16_t *sumout, int *idout)
57 {
58 int i;
59 uint16_t sum; /* ROM checksum */
60 int id; /* ROM identification number */
61
62 /* Check Kernal ROM. */
63 for (i = 0, sum = 0; i < C64_KERNAL_ROM_SIZE; i++) {
64 sum += c64memrom_kernal64_rom[i];
65 }
66 /* get ID from Kernal ROM */
67 id = c64memrom_rom64_read(0xff80);
68 if (sumout) {
69 *sumout = sum;
70 }
71 if (idout) {
72 *idout = id;
73 }
74 /* check against known kernal versions */
75 if (((id == C64_KERNAL_ID_R01) && (sum == C64_KERNAL_CHECKSUM_R01)) ||
76 ((id == C64_KERNAL_ID_R02) && (sum == C64_KERNAL_CHECKSUM_R02)) ||
77 ((id == C64_KERNAL_ID_R03) && (sum == C64_KERNAL_CHECKSUM_R03)) ||
78 /* ((id == C64_KERNAL_ID_R03swe) && (sum == C64_KERNAL_CHECKSUM_R03swe)) || */
79 ((id == C64_KERNAL_ID_R43) && (sum == C64_KERNAL_CHECKSUM_R43)) ||
80 ((id == C64_KERNAL_ID_R64) && (sum == C64_KERNAL_CHECKSUM_R64))
81 ) {
82 /* known */
83 return 0;
84 }
85 return -1; /* unknown */
86 }
87
88 /* FIXME: this function should perhaps not patch the kernal, but return -1 on
89 unknown kernals, like the respective vic-20 functions */
c64rom_get_kernal_checksum(void)90 int c64rom_get_kernal_checksum(void)
91 {
92 uint16_t sum; /* ROM checksum */
93 int id; /* ROM identification number */
94
95 if (c64rom_get_kernal_chksum_id(&sum, &id) < 0) {
96 log_warning(c64rom_log, "Unknown Kernal image. ID: %d ($%02X) Sum: %d ($%04X).", id, (unsigned int)id, sum, sum);
97 return -1;
98 } else {
99 log_message(c64rom_log, "Kernal rev #%d ($%02X) Sum: %d ($%04X).", id, (unsigned int)id, sum, sum);
100 }
101
102 return 0;
103 }
104
105 int c64rom_cartkernal_active = 0;
106
107 /* the extra parameter cartkernal is used to replace the kernal
108 with a cartridge kernal rom image, if it is NULL normal kernal
109 is used */
c64rom_load_kernal(const char * rom_name,uint8_t * cartkernal)110 int c64rom_load_kernal(const char *rom_name, uint8_t *cartkernal)
111 {
112 int trapfl, rev;
113 uint16_t sum; /* ROM checksum */
114 int id; /* ROM identification number */
115
116 if (!rom_loaded) {
117 return 0;
118 }
119
120 /* disable traps before loading the ROM */
121 if (machine_class != VICE_MACHINE_VSID) {
122 resources_get_int("VirtualDevices", &trapfl);
123 resources_set_int("VirtualDevices", 0);
124 }
125
126 /* Load Kernal ROM. */
127 if (cartkernal == NULL) {
128 if (c64rom_cartkernal_active == 1) {
129 if (machine_class != VICE_MACHINE_VSID) {
130 resources_set_int("VirtualDevices", trapfl);
131 }
132 return -1;
133 }
134
135 if (sysfile_load(rom_name, c64memrom_kernal64_rom, C64_KERNAL_ROM_SIZE, C64_KERNAL_ROM_SIZE) < 0) {
136 log_error(c64rom_log, "Couldn't load kernal ROM `%s'.", rom_name);
137 if (machine_class != VICE_MACHINE_VSID) {
138 resources_set_int("VirtualDevices", trapfl);
139 }
140 return -1;
141 }
142 } else {
143 memcpy(c64memrom_kernal64_rom, cartkernal, 0x2000);
144 c64rom_cartkernal_active = 1;
145 }
146
147 if (machine_class != VICE_MACHINE_C64DTV) {
148 resources_get_int("KernalRev", &rev);
149 }
150 if (c64rom_get_kernal_chksum_id(&sum, &id) < 0) {
151 log_verbose("loaded unknown kernal revision:%d chksum: %d", id, sum);
152 rev = C64_KERNAL_UNKNOWN;
153 } else {
154 log_verbose("loaded known kernal revision:%d chksum: %d", id, sum);
155 rev = id;
156 }
157 if (machine_class != VICE_MACHINE_C64DTV) {
158 /* patch kernal to revision given on cmdline */
159 if (kernal_revision_cmdline != -1) {
160 if (rev != C64_KERNAL_UNKNOWN) {
161 log_verbose("patching kernal revision:%d to revision: %d", rev, kernal_revision_cmdline);
162 if (patch_rom_idx(kernal_revision_cmdline) >= 0) {
163 rev = kernal_revision_cmdline;
164 }
165 }
166 /* do this only once */
167 kernal_revision_cmdline = -1;
168 }
169 resources_set_int("KernalRev", rev);
170 }
171 memcpy(c64memrom_kernal64_trap_rom, c64memrom_kernal64_rom, C64_KERNAL_ROM_SIZE);
172
173 if (machine_class != VICE_MACHINE_VSID) {
174 resources_set_int("VirtualDevices", trapfl);
175 }
176
177 return 0;
178 }
179
c64rom_get_basic_checksum(void)180 int c64rom_get_basic_checksum(void)
181 {
182 int i;
183 uint16_t sum;
184
185 /* Check Basic ROM. */
186
187 for (i = 0, sum = 0; i < C64_BASIC_ROM_SIZE; i++) {
188 sum += c64memrom_basic64_rom[i];
189 }
190
191 if (sum != C64_BASIC_CHECKSUM) {
192 log_warning(c64rom_log, "Unknown Basic image. Sum: %d ($%04X).", sum, sum);
193 }
194
195 return 0;
196 }
197
c64rom_load_basic(const char * rom_name)198 int c64rom_load_basic(const char *rom_name)
199 {
200 if (!rom_loaded) {
201 return 0;
202 }
203
204 /* Load Basic ROM. */
205 if (sysfile_load(rom_name, c64memrom_basic64_rom, C64_BASIC_ROM_SIZE, C64_BASIC_ROM_SIZE) < 0) {
206 log_error(c64rom_log, "Couldn't load basic ROM `%s'.", rom_name);
207 return -1;
208 }
209 return c64rom_get_basic_checksum();
210 }
211
c64rom_load_chargen(const char * rom_name)212 int c64rom_load_chargen(const char *rom_name)
213 {
214 if (!rom_loaded) {
215 return 0;
216 }
217
218 /* Load chargen ROM. */
219
220 if (sysfile_load(rom_name, mem_chargen_rom, C64_CHARGEN_ROM_SIZE, C64_CHARGEN_ROM_SIZE) < 0) {
221 log_error(c64rom_log, "Couldn't load character ROM `%s'.", rom_name);
222 return -1;
223 }
224
225 return 0;
226 }
227
mem_load(void)228 int mem_load(void)
229 {
230 const char *rom_name = NULL;
231
232 if (c64rom_log == LOG_ERR) {
233 c64rom_log = log_open("C64MEM");
234 }
235
236 rom_loaded = 1;
237
238 if (resources_get_string("KernalName", &rom_name) < 0) {
239 return -1;
240 }
241 if (c64rom_load_kernal(rom_name, NULL) < 0) {
242 return -1;
243 }
244
245 if (resources_get_string("BasicName", &rom_name) < 0) {
246 return -1;
247 }
248 if (c64rom_load_basic(rom_name) < 0) {
249 return -1;
250 }
251
252 if (resources_get_string("ChargenName", &rom_name) < 0) {
253 return -1;
254 }
255 if (c64rom_load_chargen(rom_name) < 0) {
256 return -1;
257 }
258
259 return 0;
260 }
261