1 /*
2 * c64cia2.c - Definitions for the second MOS6526 (CIA) chip in the C64
3 * ($DD00).
4 *
5 * Written by
6 * Andre Fachat <fachat@physik.tu-chemnitz.de>
7 * Ettore Perazzoli <ettore@comm2000.it>
8 * Andreas Boose <viceteam@t-online.de>
9 * Marco van den Heuvel <blackystardust68@yahoo.com>
10 *
11 * This file is part of VICE, the Versatile Commodore Emulator.
12 * See README for copyright notice.
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 * 02111-1307 USA.
28 * */
29
30
31 #include "vice.h"
32
33 #include <stdio.h>
34
35 #include "c64.h"
36 #include "c64mem.h"
37 #include "c64iec.h"
38 #include "c64cia.h"
39 #include "c64parallel.h"
40 #include "c64dtv-resources.h"
41 #include "cia.h"
42 #include "drive.h"
43 #include "hummeradc.h"
44 #include "iecbus.h"
45 #include "interrupt.h"
46 #include "joystick.h"
47 #include "keyboard.h"
48 #include "lib.h"
49 #include "log.h"
50 #include "maincpu.h"
51 #include "ps2mouse.h"
52 #include "types.h"
53 #include "userport.h"
54 #include "vicii.h"
55
56 #if defined(HAVE_RS232DEV) || defined(HAVE_RS232NET)
57 #include "rsuser.h"
58 #endif
59
60
cia2_store(uint16_t addr,uint8_t data)61 void cia2_store(uint16_t addr, uint8_t data)
62 {
63 if ((addr & 0x1f) == 1) {
64 store_userport_pbx(data);
65
66 /* The functions below will gradually be removed as the functionality is added to the new userport system. */
67 if (c64dtv_hummer_adc_enabled) {
68 hummeradc_store(data);
69 }
70 if (ps2mouse_enabled) {
71 ps2mouse_store(data);
72 }
73 }
74
75 ciacore_store(machine_context.cia2, addr, data);
76 }
77
cia2_read(uint16_t addr)78 uint8_t cia2_read(uint16_t addr)
79 {
80 uint8_t retval = 0xff;
81
82 if ((addr & 0x1f) == 1) {
83 retval = read_userport_pbx(0x1f, retval);
84
85 /* The functions below will gradually be removed as the functionality is added to the new userport system. */
86 if (ps2mouse_enabled) {
87 retval &= (ps2mouse_read() | 0x3f);
88 }
89 if (c64dtv_hummer_adc_enabled) {
90 retval &= (hummeradc_read() | 0xf8);
91 }
92 return retval;
93 }
94
95 /* disable TOD & serial */
96 if (((addr & 0xf) >= 8) && ((addr & 0xf) <= 0xc)) {
97 return 0xff;
98 }
99
100 return ciacore_read(machine_context.cia2, addr);
101 }
102
cia2_peek(uint16_t addr)103 uint8_t cia2_peek(uint16_t addr)
104 {
105 return ciacore_peek(machine_context.cia2, addr);
106 }
107
cia_set_int_clk(cia_context_t * cia_context,int value,CLOCK clk)108 static void cia_set_int_clk(cia_context_t *cia_context, int value, CLOCK clk)
109 {
110 interrupt_set_nmi(maincpu_int_status, cia_context->int_num, value, clk);
111 }
112
cia_restore_int(cia_context_t * cia_context,int value)113 static void cia_restore_int(cia_context_t *cia_context, int value)
114 {
115 interrupt_restore_nmi(maincpu_int_status, cia_context->int_num, value);
116 }
117
118 #define MYCIA CIA2
119
120 /*************************************************************************
121 * I/O
122 */
123
124 /* Current video bank (0, 1, 2 or 3). */
125 static int vbank;
126
127
do_reset_cia(cia_context_t * cia_context)128 static void do_reset_cia(cia_context_t *cia_context)
129 {
130 store_userport_pbx(0xff);
131
132 /* The functions below will gradually be removed as the functionality is added to the new userport system. */
133 #if defined(HAVE_RS232DEV) || defined(HAVE_RS232NET)
134 rsuser_write_ctrl((uint8_t)0xff);
135 rsuser_set_tx_bit(1);
136 #endif
137
138 vbank = 0;
139 mem_set_vbank(vbank);
140 }
141
pre_store(void)142 static void pre_store(void)
143 {
144 vicii_handle_pending_alarms_external_write();
145 }
146
pre_read(void)147 static void pre_read(void)
148 {
149 vicii_handle_pending_alarms_external(0);
150 }
151
pre_peek(void)152 static void pre_peek(void)
153 {
154 vicii_handle_pending_alarms_external(0);
155 }
156
store_ciapa(cia_context_t * cia_context,CLOCK rclk,uint8_t byte)157 static void store_ciapa(cia_context_t *cia_context, CLOCK rclk, uint8_t byte)
158 {
159 if (cia_context->old_pa != byte) {
160 uint8_t tmp;
161 int new_vbank;
162
163 #if defined(HAVE_RS232DEV) || defined(HAVE_RS232NET)
164 if (rsuser_enabled && ((cia_context->old_pa ^ byte) & 0x04)) {
165 rsuser_set_tx_bit(byte & 4);
166 }
167 #endif
168 tmp = ~byte;
169 new_vbank = tmp & 3;
170 if (new_vbank != vbank) {
171 vbank = new_vbank;
172 mem_set_vbank(new_vbank);
173 }
174 (*iecbus_callback_write)((uint8_t)tmp, maincpu_clk);
175 }
176 }
177
undump_ciapa(cia_context_t * cia_context,CLOCK rclk,uint8_t byte)178 static void undump_ciapa(cia_context_t *cia_context, CLOCK rclk, uint8_t byte)
179 {
180 #if defined(HAVE_RS232DEV) || defined(HAVE_RS232NET)
181 if (rsuser_enabled) {
182 rsuser_set_tx_bit((int)(byte & 4));
183 }
184 #endif
185 vbank = (byte ^ 3) & 3;
186 mem_set_vbank(vbank);
187 iecbus_cpu_undump((uint8_t)(byte ^ 0xff));
188 }
189
190
store_ciapb(cia_context_t * cia_context,CLOCK rclk,uint8_t byte)191 static void store_ciapb(cia_context_t *cia_context, CLOCK rclk, uint8_t byte)
192 {
193 store_userport_pbx(byte);
194
195 /* The functions below will gradually be removed as the functionality is added to the new userport system. */
196 parallel_cable_cpu_write(DRIVE_PC_STANDARD, (uint8_t)byte);
197 #if defined(HAVE_RS232DEV) || defined(HAVE_RS232NET)
198 rsuser_write_ctrl((uint8_t)byte);
199 #endif
200 }
201
pulse_ciapc(cia_context_t * cia_context,CLOCK rclk)202 static void pulse_ciapc(cia_context_t *cia_context, CLOCK rclk)
203 {
204 parallel_cable_cpu_pulse(DRIVE_PC_STANDARD);
205 }
206
207 /* FIXME! */
undump_ciapb(cia_context_t * cia_context,CLOCK rclk,uint8_t byte)208 static inline void undump_ciapb(cia_context_t *cia_context, CLOCK rclk,
209 uint8_t byte)
210 {
211 store_userport_pbx(byte);
212
213 /* The functions below will gradually be removed as the functionality is added to the new userport system. */
214 parallel_cable_cpu_undump(DRIVE_PC_STANDARD, (uint8_t)byte);
215 #if defined(HAVE_RS232DEV) || defined(HAVE_RS232NET)
216 rsuser_write_ctrl((uint8_t)byte);
217 #endif
218 }
219
220 /* read_* functions must return 0xff if nothing to read!!! */
read_ciapa(cia_context_t * cia_context)221 static uint8_t read_ciapa(cia_context_t *cia_context)
222 {
223 return ((cia_context->c_cia[CIA_PRA] | ~(cia_context->c_cia[CIA_DDRA]))
224 & 0x3f) | (*iecbus_callback_read)(maincpu_clk);
225 }
226
227 /* read_* functions must return 0xff if nothing to read!!! */
read_ciapb(cia_context_t * cia_context)228 static uint8_t read_ciapb(cia_context_t *cia_context)
229 {
230 uint8_t byte = 0xff;
231
232 byte = read_userport_pbx(0x1f, byte);
233
234 /* The functions below will gradually be removed as the functionality is added to the new userport system. */
235 #if defined(HAVE_RS232DEV) || defined(HAVE_RS232NET)
236 if (rsuser_enabled) {
237 byte = rsuser_read_ctrl(byte);
238 } else
239 #endif
240 byte = parallel_cable_cpu_read(DRIVE_PC_STANDARD, byte);
241
242 byte = (byte & ~(cia_context->c_cia[CIA_DDRB]))
243 | (cia_context->c_cia[CIA_PRB] & cia_context->c_cia[CIA_DDRB]);
244 return byte;
245 }
246
read_ciaicr(cia_context_t * cia_context)247 static void read_ciaicr(cia_context_t *cia_context)
248 {
249 parallel_cable_cpu_execute(DRIVE_PC_STANDARD);
250 }
251
read_sdr(cia_context_t * cia_context)252 static void read_sdr(cia_context_t *cia_context)
253 {
254 }
255
store_sdr(cia_context_t * cia_context,uint8_t byte)256 static void store_sdr(cia_context_t *cia_context, uint8_t byte)
257 {
258 }
259
260 /* Temporary! */
cia2_set_flagx(void)261 void cia2_set_flagx(void)
262 {
263 ciacore_set_flag(machine_context.cia2);
264 }
265
cia2_set_sdrx(uint8_t received_byte)266 void cia2_set_sdrx(uint8_t received_byte)
267 {
268 ciacore_set_sdr(machine_context.cia2, received_byte);
269 }
270
cia2_init(cia_context_t * cia_context)271 void cia2_init(cia_context_t *cia_context)
272 {
273 ciacore_init(machine_context.cia2, maincpu_alarm_context,
274 maincpu_int_status, maincpu_clk_guard);
275 }
276
cia2_set_timing(cia_context_t * cia_context,int tickspersec,int powerfreq)277 void cia2_set_timing(cia_context_t *cia_context, int tickspersec, int powerfreq)
278 {
279 cia_context->power_freq = powerfreq;
280 cia_context->ticks_per_sec = tickspersec;
281 cia_context->todticks = 0;
282 cia_context->power_tickcounter = 0;
283 cia_context->power_ticks = 0;
284 }
285
cia2_setup_context(machine_context_t * machine_ctx)286 void cia2_setup_context(machine_context_t *machine_ctx)
287 {
288 cia_context_t *cia;
289
290 machine_ctx->cia2 = lib_calloc(1, sizeof(cia_context_t));
291 cia = machine_ctx->cia2;
292
293 cia->prv = NULL;
294 cia->context = NULL;
295
296 cia->rmw_flag = &maincpu_rmw_flag;
297 cia->clk_ptr = &maincpu_clk;
298
299 cia2_set_timing(cia, C64_PAL_CYCLES_PER_SEC, 0);
300
301 ciacore_setup_context(cia);
302
303 cia->debugFlag = 0;
304 cia->irq_line = IK_NMI;
305 cia->myname = lib_msprintf("CIA2");
306
307 cia->undump_ciapa = undump_ciapa;
308 cia->undump_ciapb = undump_ciapb;
309 cia->store_ciapa = store_ciapa;
310 cia->store_ciapb = store_ciapb;
311 cia->store_sdr = store_sdr;
312 cia->read_ciapa = read_ciapa;
313 cia->read_ciapb = read_ciapb;
314 cia->read_ciaicr = read_ciaicr;
315 cia->read_sdr = read_sdr;
316 cia->cia_set_int_clk = cia_set_int_clk;
317 cia->cia_restore_int = cia_restore_int;
318 cia->do_reset_cia = do_reset_cia;
319 cia->pulse_ciapc = pulse_ciapc;
320 cia->pre_store = pre_store;
321 cia->pre_read = pre_read;
322 cia->pre_peek = pre_peek;
323 }
324