1 /*
2 * scpu64gluelogic.c - SCPU64 glue logic emulation.
3 *
4 * Written by
5 * Hannu Nuotio <hannu.nuotio@tut.fi>
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
31 #include "alarm.h"
32 #include "scpu64gluelogic.h"
33 #include "scpu64mem.h"
34 #include "cmdline.h"
35 #include "log.h"
36 #include "main65816cpu.h"
37 #include "resources.h"
38 #include "snapshot.h"
39 #include "types.h"
40 #include "vicii.h"
41
42 static int glue_logic_type = 0;
43 static int old_vbank = 0;
44 static int glue_alarm_active = 0;
45 static alarm_t *glue_alarm = NULL;
46
47 /* ------------------------------------------------------------------------- */
48
perform_vbank_switch(int vbank)49 static void perform_vbank_switch(int vbank)
50 {
51 mem_set_vbank(vbank);
52 }
53
glue_alarm_set(void)54 static void glue_alarm_set(void)
55 {
56 alarm_set(glue_alarm, maincpu_clk + 1);
57 glue_alarm_active = 1;
58 }
59
glue_alarm_unset(void)60 static void glue_alarm_unset(void)
61 {
62 alarm_unset(glue_alarm);
63 glue_alarm_active = 0;
64 }
65
glue_alarm_handler(CLOCK offset,void * data)66 static void glue_alarm_handler(CLOCK offset, void *data)
67 {
68 perform_vbank_switch(old_vbank);
69 glue_alarm_unset();
70 }
71
72 /* ------------------------------------------------------------------------- */
73
c64_glue_undump(int vbank)74 void c64_glue_undump(int vbank)
75 {
76 perform_vbank_switch(vbank);
77 old_vbank = vbank;
78 }
79
c64_glue_set_vbank(int vbank,int ddr_flag)80 void c64_glue_set_vbank(int vbank, int ddr_flag)
81 {
82 int new_vbank = vbank;
83 int update_now = 1;
84
85 if (glue_logic_type == 1) {
86 if (((old_vbank ^ vbank) == 3) && ((vbank & (vbank - 1)) == 0) && (vbank != 0)) {
87 new_vbank = 3;
88 glue_alarm_set();
89 } else if (ddr_flag && (vbank < old_vbank) && ((old_vbank ^ vbank) != 3)) {
90 /* this is not quite accurate; the results flicker in some cases */
91 update_now = 0;
92 glue_alarm_set();
93 }
94 }
95
96 if (update_now) {
97 perform_vbank_switch(new_vbank);
98 }
99
100 old_vbank = vbank;
101 }
102
c64_glue_reset(void)103 void c64_glue_reset(void)
104 {
105 if (glue_alarm_active) {
106 glue_alarm_unset();
107 }
108
109 old_vbank = 0;
110 perform_vbank_switch(old_vbank);
111 }
112
113 /* ------------------------------------------------------------------------- */
114
set_glue_type(int val,void * param)115 static int set_glue_type(int val, void *param)
116 {
117 switch (val) {
118 case GLUE_LOGIC_DISCRETE:
119 case GLUE_LOGIC_CUSTOM_IC:
120 break;
121 default:
122 return -1;
123 }
124
125 glue_logic_type = val;
126
127 return 0;
128 }
129
130 static const resource_int_t resources_int[] = {
131 { "GlueLogic", GLUE_LOGIC_CUSTOM_IC, RES_EVENT_NO, NULL,
132 &glue_logic_type, set_glue_type, NULL },
133 RESOURCE_INT_LIST_END
134 };
135
scpu64_glue_resources_init(void)136 int scpu64_glue_resources_init(void)
137 {
138 return resources_register_int(resources_int);
139 }
140
141 static const cmdline_option_t cmdline_options[] =
142 {
143 { "-gluelogictype", SET_RESOURCE, CMDLINE_ATTRIB_NEED_ARGS,
144 NULL, NULL, "GlueLogic", NULL,
145 "<Type>", "Set glue logic type (0 = discrete, 1 = 252535-01)" },
146 CMDLINE_LIST_END
147 };
148
scpu64_glue_cmdline_options_init(void)149 int scpu64_glue_cmdline_options_init(void)
150 {
151 return cmdline_register_options(cmdline_options);
152 }
153
scpu64_glue_init(void)154 void scpu64_glue_init(void)
155 {
156 glue_alarm = alarm_new(maincpu_alarm_context, "Glue", glue_alarm_handler, NULL);
157 }
158
159 /* ------------------------------------------------------------------------- */
160
161 static char snap_module_name[] = "GLUE";
162 #define SNAP_MAJOR 1
163 #define SNAP_MINOR 0
164
scpu64_glue_snapshot_write_module(snapshot_t * s)165 int scpu64_glue_snapshot_write_module(snapshot_t *s)
166 {
167 snapshot_module_t *m;
168
169 m = snapshot_module_create(s, snap_module_name, SNAP_MAJOR, SNAP_MINOR);
170 if (m == NULL) {
171 return -1;
172 }
173
174 if (0
175 || SMW_B(m, (uint8_t)glue_logic_type) < 0
176 || SMW_B(m, (uint8_t)old_vbank) < 0
177 || SMW_B(m, (uint8_t)glue_alarm_active) < 0) {
178 goto fail;
179 }
180
181 return snapshot_module_close(m);
182
183 fail:
184 if (m != NULL) {
185 snapshot_module_close(m);
186 }
187 return -1;
188 }
189
scpu64_glue_snapshot_read_module(snapshot_t * s)190 int scpu64_glue_snapshot_read_module(snapshot_t *s)
191 {
192 uint8_t major_version, minor_version;
193 int snap_type, snap_alarm_active;
194 snapshot_module_t *m;
195
196 m = snapshot_module_open(s, snap_module_name,
197 &major_version, &minor_version);
198 if (m == NULL) {
199 return -1;
200 }
201
202 if (snapshot_version_is_bigger(major_version, minor_version, SNAP_MAJOR, SNAP_MINOR)) {
203 log_error(LOG_ERR,
204 "GlueLogic: Snapshot module version (%d.%d) newer than %d.%d.",
205 major_version, minor_version,
206 SNAP_MAJOR, SNAP_MINOR);
207 goto fail;
208 }
209
210 if (0
211 || SMR_B_INT(m, &snap_type) < 0
212 || SMR_B_INT(m, &old_vbank) < 0
213 || SMR_B_INT(m, &snap_alarm_active) < 0) {
214 goto fail;
215 }
216
217 if (snap_type != glue_logic_type) {
218 log_warning(LOG_DEFAULT,
219 "GlueLogic: Snapshot type %i differs from selected type %i, changing.",
220 snap_type, glue_logic_type);
221 glue_logic_type = snap_type;
222 }
223
224 if (glue_alarm_active) {
225 glue_alarm_unset();
226 }
227
228 glue_alarm_active = snap_alarm_active;
229
230 if (glue_alarm_active && (glue_logic_type == 1)) {
231 glue_alarm_set();
232 }
233
234 snapshot_module_close(m);
235 return 0;
236
237 fail:
238 if (m != NULL) {
239 snapshot_module_close(m);
240 }
241 return -1;
242 }
243