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