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 "kc/system.h"
21
22 #include "kc/kc.h"
23 #include "kc/gdc.h"
24 #include "kc/memory.h"
25
26 #include "ui/generic/ui_0.h"
27
UI_0(void)28 UI_0::UI_0(void)
29 {
30 _font = NULL;
31 _dirty = NULL;
32 _bitmap = NULL;
33 _pix_cache = NULL;
34 _col_cache = NULL;
35
36 generic_set_mode(UI_GENERIC_MODE_Z1013_32x32);
37
38 init();
39 }
40
~UI_0(void)41 UI_0::~UI_0(void)
42 {
43 dispose();
44 }
45
46 void
init(void)47 UI_0::init(void)
48 {
49 _dirty_size = (get_real_width() * get_real_height()) / 64;
50 _dirty = new byte_t[_dirty_size];
51 _bitmap = new byte_t[get_real_width() * get_real_height()];
52 _pix_cache = new byte_t[_dirty_size];
53 _col_cache = new byte_t[_dirty_size];
54
55 memset(_dirty, 1, _dirty_size);
56 memset(_bitmap, 0, get_real_width() * get_real_height());
57 }
58
59 void
dispose(void)60 UI_0::dispose(void)
61 {
62 if (_dirty)
63 delete[] _dirty;
64 if (_bitmap)
65 delete[] _bitmap;
66 if (_pix_cache)
67 delete[] _pix_cache;
68 if (_col_cache)
69 delete[] _col_cache;
70 }
71
72 void
generic_put_pixels(byte_t * ptr,byte_t val,word_t color)73 UI_0::generic_put_pixels(byte_t *ptr, byte_t val, word_t color)
74 {
75 for (int a = 0;a < 8;a++)
76 ptr[a] = (val & (128 >> a)) ? (color >> 8) : color;
77 }
78
79 void
generic_update_gdc(byte_t * font,bool clear_cache)80 UI_0::generic_update_gdc(byte_t *font, bool clear_cache)
81 {
82 if (gdc == NULL)
83 return;
84
85 int a, x, y, z, p, c, fg, bg, col;
86 long offset = gdc->get_pram_SAD(0);
87
88 int width = 80;
89 int height = 25;
90 int lines = 10;
91 int linecount = 0;
92 int subscreen = 0;
93
94 byte_t *ptr = _bitmap;
95
96 z = -1;
97 for (y = 0;y < height;y++)
98 {
99 if (linecount >= gdc->get_pram_LEN(subscreen))
100 {
101 subscreen++;
102 linecount = 0;
103 offset = gdc->get_pram_SAD(subscreen) - z - 1; // compensate value of loop variable!
104 }
105
106 linecount += lines;
107
108 for (x = 0;x < width;x++)
109 {
110 z++;
111 p = gdc->get_mem(z + offset);
112 c = gdc->get_col(z + offset);
113
114 _dirty[z] = clear_cache;
115
116 if (p != _pix_cache[z])
117 {
118 _dirty[z]++;
119 _pix_cache[z] = p;
120 }
121
122 if (c != _col_cache[z])
123 {
124 _dirty[z]++;
125 _col_cache[z] = c;
126 }
127
128 if (gdc->get_cursor(z + offset))
129 {
130 _pix_cache[z] = 255; // invalidate cache on cursor position to force
131 _col_cache[z] = 255; // update there when cursor position changes
132 }
133
134 if (!_dirty[z])
135 continue;
136
137 fg = c & 15;
138 bg = (c >> 4) & 7;
139
140 col = 0x0100;
141 if (p & 0x80)
142 {
143 p &= 0x7f;
144 col = 0x0001;
145 }
146
147 ptr = _bitmap + y * 8 * 8 * width + 8 * x;
148 for (a = 0;a < 8;a++)
149 {
150 int xor_val = 0;
151 if (gdc->get_cursor(z + offset, a))
152 xor_val = 0x0101;
153 generic_put_pixels(ptr + a * 8 * width, font[8 * p + a], col ^ xor_val);
154 }
155 }
156 }
157 }
158
159 void
generic_update_32x32(byte_t * font,bool clear_cache)160 UI_0::generic_update_32x32(byte_t *font, bool clear_cache)
161 {
162 byte_t pix;
163 int a, i, x, y, z, width, height;
164
165 byte_t *irm = memory->get_irm();
166 byte_t *ptr = _bitmap;
167
168 width = get_real_width();
169 height = get_real_height();
170
171 i = -1;
172 z = 73;
173 ptr += 16 * width + 16;
174 for (y = 0;y < 256;y += 8)
175 {
176 for (x = 0;x < 256;x += 8)
177 {
178 i++;
179 z++;
180
181 _dirty[z] = clear_cache;
182
183 pix = irm[i];
184 if (_pix_cache[i] != pix)
185 _dirty[z]++;
186
187 if (!_dirty[z])
188 continue;
189
190 _pix_cache[i] = pix;
191 for (a = 0;a < 8;a++)
192 generic_put_pixels(ptr + a * width + x, font[8 * pix + a], 0x0100);
193 }
194 z += 4;
195 ptr += 8 * width;
196 }
197 }
198
199 void
generic_update_64x16(byte_t * font,bool clear_cache)200 UI_0::generic_update_64x16(byte_t *font, bool clear_cache)
201 {
202 byte_t pix;
203 int a, i, x, y, z, width, height, width8;
204
205 byte_t *irm = memory->get_irm();
206 byte_t *ptr = _bitmap;
207
208 width = get_real_width();
209 height = get_real_height();
210 width8 = width / 8;
211
212 i = -1;
213 ptr += 6 * width + 8;
214 for (y = 0;y < 16;y++)
215 {
216 z = (((12 * y + 6) / 8) * width8);
217 for (x = 0;x < 512;x += 8)
218 {
219 i++;
220 z++;
221
222 _dirty[z] = clear_cache;
223
224 pix = irm[i];
225 if (_pix_cache[i] != pix)
226 _dirty[z]++;
227
228 if (!_dirty[z])
229 continue;
230
231 _dirty[z + width8]++;
232
233 _pix_cache[i] = pix;
234 for (a = 0;a < 8;a++)
235 generic_put_pixels(ptr + a * width + x, font[8 * pix + a], 0x0100);
236 }
237 ptr += 12 * width;
238 }
239 }
240
241 void
generic_update(Scanline * scanline,MemAccess * memaccess,bool clear_cache)242 UI_0::generic_update(Scanline *scanline, MemAccess *memaccess, bool clear_cache)
243 {
244 byte_t *font = memory->get_char_rom();
245
246 if (_font != font)
247 {
248 _font = font;
249 clear_cache = true;
250 }
251
252 switch (_mode)
253 {
254 case UI_GENERIC_MODE_Z1013_32x32:
255 generic_update_32x32(font, clear_cache);
256 break;
257 case UI_GENERIC_MODE_Z1013_64x16:
258 generic_update_64x16(font, clear_cache);
259 break;
260 case UI_GENERIC_MODE_GDC:
261 generic_update_gdc(font, clear_cache);
262 break;
263 }
264 }
265
266 void
generic_signal_v_retrace(bool value)267 UI_0::generic_signal_v_retrace(bool value)
268 {
269 if (_mode == UI_GENERIC_MODE_GDC)
270 if (gdc != NULL)
271 gdc->v_retrace(value);
272 }
273
274 int
generic_get_mode(void)275 UI_0::generic_get_mode(void)
276 {
277 return _mode;
278 }
279
280 void
generic_set_mode(int mode)281 UI_0::generic_set_mode(int mode)
282 {
283 _mode = mode;
284
285 switch (_mode)
286 {
287 case UI_GENERIC_MODE_Z1013_32x32:
288 set_real_screen_size(288, 288);
289 break;
290 case UI_GENERIC_MODE_Z1013_64x16:
291 set_real_screen_size(528, 200);
292 break;
293 case UI_GENERIC_MODE_GDC:
294 set_real_screen_size(640, 200);
295 break;
296 }
297
298 dispose();
299 init();
300 }
301