1 /*
2  *  KCemu -- The emulator for the KC85 homecomputer series and much more.
3  *  Copyright (C) 1997-2010 Torsten Paul
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License along
16  *  with this program; if not, write to the Free Software Foundation, Inc.,
17  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 #include <iostream>
21 #include <iomanip>
22 
23 #include "kc/system.h"
24 
25 #include "kc/kc.h"
26 #include "kc/pio4.h"
27 #include "kc/tape.h"
28 #include "kc/memory4.h"
29 
30 #include "libdbg/dbg.h"
31 
32 #define memory ((Memory4 *)memory)
33 
PIO4(void)34 PIO4::PIO4(void)
35 {
36 }
37 
~PIO4(void)38 PIO4::~PIO4(void)
39 {
40 }
41 
42 byte_t
in(word_t addr)43 PIO4::in(word_t addr)
44 {
45   DBG(2, form("KCemu/PIO/4/in",
46               "PIO4::in(): addr = %04x\n",
47               addr));
48 
49   switch (addr & 3)
50     {
51     case 0:
52       return in_A_DATA();
53     case 1:
54       return in_B_DATA();
55     case 2:
56       return in_A_CTRL();
57     case 3:
58       return in_B_CTRL();
59     }
60 
61   return 0; // shouldn't be reached
62 }
63 
64 void
out(word_t addr,byte_t val)65 PIO4::out(word_t addr, byte_t val)
66 {
67   DBG(2, form("KCemu/PIO/4/out",
68               "PIO4::out(): addr = %04x, val = %02x\n",
69               addr, val));
70 
71   switch (addr & 3)
72     {
73     case 0:
74       out_A_DATA(val);
75       break;
76     case 1:
77       out_B_DATA(val);
78       break;
79     case 2:
80       out_A_CTRL(val);
81       break;
82     case 3:
83       out_B_CTRL(val);
84       break;
85     }
86 }
87 
88 void
change_A(byte_t changed,byte_t val)89 PIO4::change_A(byte_t changed, byte_t val)
90 {
91   if (changed & 0x01)
92     {
93       DBG(2, form("KCemu/PIO/4/change/A",
94                   "PIO A: CAOS ROM E [%d]\n",
95                   (val & 1)));
96       memory->enableCAOS_E(val & 0x01);
97     }
98   if (changed & 0x02)
99     {
100       DBG(2, form("KCemu/PIO/4/change/A",
101                   "PIO A: RAM 0 [%d]\n",
102                   ((val >> 1) & 1)));
103       memory->enableRAM_0(val & 0x02);
104     }
105   if (changed & 0x04)
106     {
107       DBG(2, form("KCemu/PIO/4/change/A",
108                   "PIO A: IRM [%d]\n",
109                   ((val >> 2) & 1)));
110       memory->enableIRM(val & 0x04);
111     }
112   if (changed & 0x08)
113     {
114       DBG(2, form("KCemu/PIO/4/change/A",
115                   "PIO A: write protect RAM 0 [%d]\n",
116                   ((val >> 3) & 1)));
117       memory->protectRAM_0(val & 0x08);
118     }
119   if (changed & 0x10)
120     {
121       DBG(2, form("KCemu/PIO/4/change/A",
122                   "PIO A: K OUT (unused) [%d]\n",
123                   ((val >> 4) & 1)));
124     }
125   if (changed & 0x20)
126     {
127       DBG(2, form("KCemu/PIO/4/change/A",
128                   "PIO A: LED [%d]\n",
129                   ((val >> 5) & 1)));
130     }
131   if (changed & 0x40)
132     {
133       DBG(2, form("KCemu/PIO/4/change/A",
134                   "PIO A: TAPE Power [%d]\n",
135                   ((val >> 6) & 1)));
136       tape->power((val >> 6) & 1);
137     }
138   if (changed & 0x80)
139     {
140       DBG(2, form("KCemu/PIO/4/change/A",
141                   "PIO A: ROM C (BASIC) [%d]\n",
142                   ((val >> 7) & 1)));
143       memory->enableBASIC_C(val & 0x80);
144     }
145 }
146 
147 void
change_B(byte_t changed,byte_t val)148 PIO4::change_B(byte_t changed, byte_t val)
149 {
150   if (changed & 0x01)
151     DBG(2, form("KCemu/PIO/4/change/B",
152                 "PIO B: flip-flop [%d]\n",
153                 (val & 1)));
154   if (changed & 0x0e)
155     DBG(2, form("KCemu/PIO/4/change/B",
156                 "PIO B: volume [%d]\n",
157                 ((val >> 1) & 7)));
158   if (changed & 0x10)
159     DBG(2, form("KCemu/PIO/4/change/B",
160                 "PIO B: unused 0x10 [%d]\n",
161                 ((val >> 4) & 1)));
162   if (changed & 0x20)
163     {
164       DBG(2, form("KCemu/PIO/4/change/B",
165                   "PIO B: RAM 8 [%d]\n",
166                   ((val >> 5) & 1)));
167       memory->enableRAM_8(val & 0x20);
168     }
169   if (changed & 0x40)
170     {
171       DBG(2, form("KCemu/PIO/4/change/B",
172                   "PIO B: RAM 8 write protect [%d]\n",
173                   ((val >> 6) & 1)));
174       memory->protectRAM_8(val & 0x40);
175     }
176   if (changed & 0x80)
177     DBG(2, form("KCemu/PIO/4/change/B",
178                 "PIO B: foreground blink [%d]\n",
179                 ((val >> 6) & 1)));
180 }
181 
182 void
tape_callback(byte_t val)183 PIO4::tape_callback(byte_t val)
184 {
185   strobe_A();
186 }
187