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 <ctype.h>
21
22 #include "kc/system.h"
23
24 #include "kc/kc.h"
25 #include "kc/z80.h"
26 #include "kc/vis.h"
27
28 #include "libdbg/dbg.h"
29
VIS(void)30 VIS::VIS(void) : InterfaceCircuit("VIS")
31 {
32 reset(true);
33 z80->register_ic(this);
34 }
35
~VIS(void)36 VIS::~VIS(void)
37 {
38 z80->unregister_ic(this);
39 }
40
41 byte_t
in(word_t addr)42 VIS::in(word_t addr)
43 {
44 byte_t val = 0xff;
45
46 switch (addr & 0xff)
47 {
48 case 0x9c:
49 val = _char[_idx];
50 _idx = (_idx + 1) & 0x07ff;
51 break;
52 }
53
54 DBG(2, form("KCemu/VIS/in",
55 "VIS::in(): %04xh val = %02x\n",
56 addr, val));
57
58 return val;
59 }
60
61 /*
62 * screen 0/8:
63 *
64 * VIS::out(): 129dh val = 12 [.] Text 25x40
65 * VIS::out(): 009dh val = 00 [.]
66 *
67 * screen 1/9:
68 *
69 * VIS::out(): 109dh val = 10 [.] Text 25x80
70 * VIS::out(): 009dh val = 00 [.]
71 *
72 * screen 2:
73 *
74 * VIS::out(): 129dh val = 12 [.] Graphic 360 x 200 (4 of 16 Colors)
75 * VIS::out(): 019dh val = 01 [.]
76 *
77 * screen 3:
78 *
79 * VIS::out(): 109dh val = 10 [.] Graphic 640 x 200 (4 of 16 Colors)
80 * VIS::out(): 019dh val = 01 [.]
81 *
82 * screen 5:
83 *
84 * VIS::out(): 109dh val = 10 [.] Graphic 320 x 200 (16 of 16 Colors)
85 * VIS::out(): 029dh val = 02 [.]
86 *
87 * border color:
88 *
89 * VIS::out(): 209dh / command: val = 20 [ ] -> border color = 0
90 * VIS::out(): 219dh / command: val = 21 [!] -> border color = 1
91 * VIS::out(): 229dh / command: val = 22 ["] -> border color = 2
92 * VIS::out(): 239dh / command: val = 23 [#] -> border color = 3
93 * VIS::out(): 2f9dh / command: val = 2f [/] -> border color = 15
94 *
95 * COLOR 0,0
96 * VIS::out(): 309dh / command: val = 30 [0]
97 * VIS::out(): 029dh / command: val = 42 [B]
98 * VIS::out(): 019dh / command: val = 54 [T]
99 * VIS::out(): 009dh / command: val = 66 [f]
100 *
101 * COLOR 0,1
102 * VIS::out(): 309dh / command: val = 30 [0]
103 * VIS::out(): 029dh / command: val = 43 [C]
104 * VIS::out(): 019dh / command: val = 55 [U]
105 * VIS::out(): 009dh / command: val = 67 [g]
106 *
107 * COLOR 1,0
108 * VIS::out(): 319dh / command: val = 31 [1]
109 * VIS::out(): 029dh / command: val = 42 [B]
110 * VIS::out(): 019dh / command: val = 54 [T]
111 * VIS::out(): 009dh / command: val = 66 [f]
112 *
113 * COLOR 1,1
114 * VIS::out(): 319dh / command: val = 31 [1]
115 * VIS::out(): 029dh / command: val = 43 [C]
116 * VIS::out(): 019dh / command: val = 55 [U]
117 * VIS::out(): 009dh / command: val = 67 [g]
118 *
119 * COLOR 2,0
120 * VIS::out(): 329dh / command: val = 32 [2]
121 * VIS::out(): 029dh / command: val = 42 [B]
122 * VIS::out(): 019dh / command: val = 54 [T]
123 * VIS::out(): 009dh / command: val = 66 [f]
124 *
125 * COLOR 2,1
126 * VIS::out(): 329dh / command: val = 32 [2]
127 * VIS::out(): 029dh / command: val = 43 [C]
128 * VIS::out(): 019dh / command: val = 55 [U]
129 * VIS::out(): 009dh / command: val = 67 [g]
130 */
131 void
out(word_t addr,byte_t val)132 VIS::out(word_t addr, byte_t val)
133 {
134 static byte_t last_val = 0;
135
136 DBG(2, form("KCemu/VIS/out",
137 "VIS::out(): %04xh val = %02x [%c]\n",
138 addr, val, isprint(val) ? val : '.'));
139
140 switch (addr & 0xff)
141 {
142 case 0x9c:
143 DBG(2, form("KCemu/VIS/out_9C",
144 "VIS::out(): %04xh / char data: val = %02x [%c] %c%c%c%c%c%c%c%c\n",
145 addr, val, isprint(val) ? val : '.',
146 (val & 1) ? '#' : ' ',
147 (val & 2) ? '#' : ' ',
148 (val & 4) ? '#' : ' ',
149 (val & 8) ? '#' : ' ',
150 (val & 16) ? '#' : ' ',
151 (val & 32) ? '#' : ' ',
152 (val & 64) ? '#' : ' ',
153 (val & 128) ? '#' : ' '));
154 _char[_idx] = val;
155 _changed[_idx / 8] = 1;
156 _idx = (_idx + 1) & 0x07ff;
157 break;
158 case 0x9d:
159 DBG(2, form("KCemu/VIS/out_9D",
160 "VIS::out(): %04xh / command: val = %02x [%c]\n",
161 addr, val, isprint(val) ? val : '.'));
162
163 if ((last_val == 0x12) && (val == 0x00))
164 set_mode(0);
165 else if ((last_val == 0x10) && (val == 0x00))
166 set_mode(1);
167 else if ((last_val == 0x12) && (val == 0x01))
168 set_mode(2);
169 else if ((last_val == 0x10) && (val == 0x01))
170 set_mode(3);
171 else if ((last_val == 0x10) && (val == 0x02))
172 set_mode(5);
173 else if ((val & 0xf0) == 0x20)
174 set_border(val & 0x0f);
175 else if ((val & 0xf0) == 0x30)
176 set_color(0, val & 0x0f);
177 else if ((val & 0xf0) == 0x40)
178 set_color(1, val & 0x0f);
179 else if ((val & 0xf0) == 0x50)
180 set_color(2, val & 0x0f);
181 else if ((val & 0xf0) == 0x60)
182 set_color(3, val & 0x0f);
183
184 last_val = val;
185
186 break;
187 case 0x9e:
188 DBG(2, form("KCemu/VIS/out_9E",
189 "VIS::out(): %04xh / char idx: val = %02x (%d)\n",
190 addr, val, val));
191 _idx = 8 * val;
192 break;
193 }
194 }
195
196 int
get_mode()197 VIS::get_mode()
198 {
199 return _mode;
200 }
201
202 void
set_mode(int mode)203 VIS::set_mode(int mode)
204 {
205 DBG(1, form("KCemu/VIS/mode",
206 "VIS::out(): mode change %d -> %d\n",
207 _mode, mode));
208 _mode = mode;
209 }
210
211 int
get_border(void)212 VIS::get_border(void)
213 {
214 return _border;
215 }
216
217 void
set_border(int border)218 VIS::set_border(int border)
219 {
220 DBG(1, form("KCemu/VIS/border",
221 "VIS::out(): border change %2d -> %2d\n",
222 _border, border));
223 _border = border;
224 }
225
226 int
get_color(int idx)227 VIS::get_color(int idx)
228 {
229 idx &= 3;
230 return _color[idx];
231 }
232
233 void
set_color(int idx,int color)234 VIS::set_color(int idx, int color)
235 {
236 idx &= 3;
237 DBG(1, form("KCemu/VIS/color",
238 "VIS::out(): color change [%d] %2d -> %2d [%2d/%2d/%2d/%2d]\n",
239 idx, _color[idx], color,
240 _color[0], _color[1], _color[2], _color[3]));
241
242 if (_color[idx] != color)
243 {
244 _color[idx] = color;
245 _color_palette_changed = 1;
246 }
247 }
248
249 int
get_changed(byte_t idx)250 VIS::get_changed(byte_t idx)
251 {
252 return _changed[idx];
253 }
254
255 void
reset_changed(void)256 VIS::reset_changed(void)
257 {
258 memset(_changed, 0, 0x100);
259 }
260
261 int
is_color_palette_changed(void)262 VIS::is_color_palette_changed(void)
263 {
264 return _color_palette_changed;
265 }
266
267 void
reset_color_palette_changed(void)268 VIS::reset_color_palette_changed(void)
269 {
270 _color_palette_changed = 0;
271 }
272
273 byte_t *
get_memory(void)274 VIS::get_memory(void)
275 {
276 return _char;
277 }
278
279 void
reti(void)280 VIS::reti(void)
281 {
282 }
283
284 void
irqreq(void)285 VIS::irqreq(void)
286 {
287 }
288
289 word_t
irqack(void)290 VIS::irqack(void)
291 {
292 return IRQ_NOT_ACK;
293 }
294
295 void
reset(bool power_on)296 VIS::reset(bool power_on)
297 {
298 int a;
299
300 _mode = 0;
301 _border = 0;
302 _color[0] = 0;
303 _color[1] = 0;
304 _color[2] = 0;
305 _color[3] = 0;
306 _color_palette_changed = 0;
307
308 if (power_on)
309 for (a = 0;a < 0x0800;a++)
310 _char[a] = 0;
311 }
312