1 /*
2 * petvia.c - VIA emulation in the PET.
3 *
4 * Written by
5 * Andre Fachat <fachat@physik.tu-chemnitz.de>
6 * Andreas Boose <viceteam@t-online.de>
7 * Marco van den Heuvel <blackystardust68@yahoo.com>
8 *
9 * This file is part of VICE, the Versatile Commodore Emulator.
10 * See README for copyright notice.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
25 * 02111-1307 USA.
26 *
27 */
28
29 #include "vice.h"
30
31 #include <stdio.h>
32
33 #include "crtc.h"
34 #include "datasette.h"
35 #include "drive.h"
36 #include "interrupt.h"
37 #include "joystick.h"
38 #include "keyboard.h"
39 #include "lib.h"
40 #include "log.h"
41 #include "maincpu.h"
42 #include "parallel.h"
43 #include "pet.h"
44 #include "petsound.h"
45 #include "petvia.h"
46 #include "tapeport.h"
47 #include "types.h"
48 #include "userport.h"
49 #include "via.h"
50
51
via_store(uint16_t addr,uint8_t data)52 void via_store(uint16_t addr, uint8_t data)
53 {
54 viacore_store(machine_context.via, addr, data);
55 }
56
via_read(uint16_t addr)57 uint8_t via_read(uint16_t addr)
58 {
59 return viacore_read(machine_context.via, addr);
60 }
61
via_peek(uint16_t addr)62 uint8_t via_peek(uint16_t addr)
63 {
64 return viacore_peek(machine_context.via, addr);
65 }
66
67 /* switching PET charrom with CA2 */
set_ca2(via_context_t * via_context,int state)68 static void set_ca2(via_context_t *via_context, int state)
69 {
70 crtc_set_chargen_offset(state ? 256 : 0);
71 }
72
73 /* switching userport strobe with CB2 */
set_cb2(via_context_t * via_context,int state)74 static void set_cb2(via_context_t *via_context, int state)
75 {
76 store_userport_pa2((uint8_t)state);
77 }
78
set_int(via_context_t * via_context,unsigned int int_num,int value,CLOCK rclk)79 static void set_int(via_context_t *via_context, unsigned int int_num,
80 int value, CLOCK rclk)
81 {
82 interrupt_set_irq(maincpu_int_status, int_num, value, rclk);
83 }
84
restore_int(via_context_t * via_context,unsigned int int_num,int value)85 static void restore_int(via_context_t *via_context, unsigned int int_num, int value)
86 {
87 interrupt_restore_irq(maincpu_int_status, int_num, value);
88 }
89
undump_pra(via_context_t * via_context,uint8_t byte)90 static void undump_pra(via_context_t *via_context, uint8_t byte)
91 {
92 store_userport_pbx(byte);
93 }
94
store_pra(via_context_t * via_context,uint8_t byte,uint8_t myoldpa,uint16_t addr)95 static void store_pra(via_context_t *via_context, uint8_t byte, uint8_t myoldpa,
96 uint16_t addr)
97 {
98 store_userport_pbx(byte);
99 }
100
undump_prb(via_context_t * via_context,uint8_t byte)101 static void undump_prb(via_context_t *via_context, uint8_t byte)
102 {
103 parallel_cpu_set_nrfd((uint8_t)(!(byte & 0x02)));
104 parallel_cpu_restore_atn((uint8_t)(!(byte & 0x04)));
105 }
106
store_prb(via_context_t * via_context,uint8_t byte,uint8_t myoldpb,uint16_t addr)107 static void store_prb(via_context_t *via_context, uint8_t byte, uint8_t myoldpb,
108 uint16_t addr)
109 {
110 if ((addr == VIA_DDRB) && (via_context->via[addr] & 0x20)) {
111 log_warning(via_context->log,
112 "PET: Killer POKE! might kill a real PET!\n");
113 }
114 parallel_cpu_set_nrfd((uint8_t)(!(byte & 0x02)));
115 parallel_cpu_set_atn((uint8_t)(!(byte & 0x04)));
116 if ((byte ^ myoldpb) & 0x8) {
117 tapeport_toggle_write_bit((~(via_context->via[VIA_DDRB]) | byte) & 0x8);
118 }
119 }
120
undump_pcr(via_context_t * via_context,uint8_t byte)121 static void undump_pcr(via_context_t *via_context, uint8_t byte)
122 {
123 #if 0
124 register uint8_t tmp = byte;
125 /* first set bit 1 and 5 to the real output values */
126 if ((tmp & 0x0c) != 0x0c) {
127 tmp |= 0x02;
128 }
129 if ((tmp & 0xc0) != 0xc0) {
130 tmp |= 0x20;
131 }
132 crtc_set_char(byte & 2); /* switching PET charrom with CA2 */
133 /* switching userport strobe with CB2 */
134 #endif
135 petsound_store_manual((byte & 0xe0) == 0xe0); /* Manual control of CB2 sound */
136 }
137
store_pcr(via_context_t * via_context,uint8_t byte,uint16_t addr)138 static uint8_t store_pcr(via_context_t *via_context, uint8_t byte, uint16_t addr)
139 {
140 #if 0
141 if (byte != via_context->via[VIA_PCR]) {
142 register uint8_t tmp = byte;
143 /* first set bit 1 and 5 to the real output values */
144 if ((tmp & 0x0c) != 0x0c) {
145 tmp |= 0x02;
146 }
147 if ((tmp & 0xc0) != 0xc0) {
148 tmp |= 0x20;
149 }
150 crtc_set_char(byte & 2); /* switching PET charrom with CA2 */
151 /* switching userport strobe with CB2 */
152 store_userport_pa2((byte & 0x20) >> 5);
153 }
154 #endif
155 petsound_store_manual((byte & 0xe0) == 0xe0); /* Manual control of CB2 sound */
156 return byte;
157 }
158
undump_acr(via_context_t * via_context,uint8_t byte)159 static void undump_acr(via_context_t *via_context, uint8_t byte)
160 {
161 petsound_store_onoff(via_context->via[VIA_T2LL]
162 ? (((byte & 0x1c) == 0x10) ? 1 : 0) : 0);
163 }
164
store_acr(via_context_t * via_context,uint8_t byte)165 static void store_acr(via_context_t *via_context, uint8_t byte)
166 {
167 petsound_store_onoff(via_context->via[VIA_T2LL]
168 ? (((byte & 0x1c) == 0x10) ? 1 : 0) : 0);
169 }
170
store_sr(via_context_t * via_context,uint8_t byte)171 static void store_sr(via_context_t *via_context, uint8_t byte)
172 {
173 petsound_store_sample(byte);
174 }
175
store_t2l(via_context_t * via_context,uint8_t byte)176 static void store_t2l(via_context_t *via_context, uint8_t byte)
177 {
178 petsound_store_rate(2 * byte + 4);
179 if (!byte) {
180 petsound_store_onoff(0);
181 } else {
182 petsound_store_onoff(((via_context->via[VIA_ACR] & 0x1c) == 0x10)
183 ? 1 : 0);
184 }
185 }
186
reset(via_context_t * via_context)187 static void reset(via_context_t *via_context)
188 {
189 /* set IEC output lines */
190 parallel_cpu_set_atn(0);
191 parallel_cpu_set_nrfd(0);
192
193 store_userport_pbx(0xff);
194 store_userport_pa2(1);
195 }
196
read_pra(via_context_t * via_context,uint16_t addr)197 inline static uint8_t read_pra(via_context_t *via_context, uint16_t addr)
198 {
199 uint8_t byte = 0xff;
200
201 byte = read_userport_pbx((uint8_t)~via_context->via[VIA_DDRA], byte);
202
203 /* The functions below will gradually be removed as the functionality is added to the new userport system. */
204
205 /* joystick always pulls low, even if high output, so no
206 masking with DDRA */
207 /*return ((j & ~(via_context->via[VIA_DDRA]))
208 | (via_context->via[VIA_PRA] & via_context->via[VIA_DDRA]));*/
209 return byte;
210 }
211
read_prb(via_context_t * via_context)212 static uint8_t read_prb(via_context_t *via_context)
213 {
214 uint8_t byte;
215
216 drive_cpu_execute_all(maincpu_clk);
217
218 /* read parallel IEC interface line states */
219 byte = 255
220 - (parallel_nrfd ? 64 : 0)
221 - (parallel_ndac ? 1 : 0)
222 - (parallel_dav ? 128 : 0);
223 /* vertical retrace */
224 byte -= crtc_offscreen() ? 32 : 0;
225
226 /* none of the load changes output register value -> std. masking */
227 byte = ((byte & ~(via_context->via[VIA_DDRB]))
228 | (via_context->via[VIA_PRB] & via_context->via[VIA_DDRB]));
229 return byte;
230 }
231
via_init(via_context_t * via_context)232 void via_init(via_context_t *via_context)
233 {
234 viacore_init(machine_context.via, maincpu_alarm_context,
235 maincpu_int_status, maincpu_clk_guard);
236 }
237
petvia_setup_context(machine_context_t * machinecontext)238 void petvia_setup_context(machine_context_t *machinecontext)
239 {
240 via_context_t *via;
241
242 machinecontext->via = lib_malloc(sizeof(via_context_t));
243 via = machinecontext->via;
244
245 via->prv = NULL;
246 via->context = NULL;
247
248 via->rmw_flag = &maincpu_rmw_flag;
249 via->clk_ptr = &maincpu_clk;
250
251 via->myname = lib_msprintf("Via");
252 via->my_module_name = lib_msprintf("VIA");
253
254 viacore_setup_context(via);
255
256 via->irq_line = IK_IRQ;
257
258 via->undump_pra = undump_pra;
259 via->undump_prb = undump_prb;
260 via->undump_pcr = undump_pcr;
261 via->undump_acr = undump_acr;
262 via->store_pra = store_pra;
263 via->store_prb = store_prb;
264 via->store_pcr = store_pcr;
265 via->store_acr = store_acr;
266 via->store_sr = store_sr;
267 via->store_t2l = store_t2l;
268 via->read_pra = read_pra;
269 via->read_prb = read_prb;
270 via->set_int = set_int;
271 via->restore_int = restore_int;
272 via->set_ca2 = set_ca2;
273 via->set_cb2 = set_cb2;
274 via->reset = reset;
275 }
276