1 /*
2 * QEMU VGA Emulator templates
3 *
4 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
vga_draw_glyph_line(uint8_t * d,uint32_t font_data,uint32_t xorcol,uint32_t bgcol)25 static inline void vga_draw_glyph_line(uint8_t *d, uint32_t font_data,
26 uint32_t xorcol, uint32_t bgcol)
27 {
28 ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;
29 ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;
30 ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol;
31 ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol;
32 ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol;
33 ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol;
34 ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol;
35 ((uint32_t *)d)[7] = (-((font_data >> 0) & 1) & xorcol) ^ bgcol;
36 }
37
vga_draw_glyph8(uint8_t * d,int linesize,const uint8_t * font_ptr,int h,uint32_t fgcol,uint32_t bgcol)38 static void vga_draw_glyph8(uint8_t *d, int linesize,
39 const uint8_t *font_ptr, int h,
40 uint32_t fgcol, uint32_t bgcol)
41 {
42 uint32_t font_data, xorcol;
43
44 xorcol = bgcol ^ fgcol;
45 do {
46 font_data = font_ptr[0];
47 vga_draw_glyph_line(d, font_data, xorcol, bgcol);
48 font_ptr += 4;
49 d += linesize;
50 } while (--h);
51 }
52
vga_draw_glyph16(uint8_t * d,int linesize,const uint8_t * font_ptr,int h,uint32_t fgcol,uint32_t bgcol)53 static void vga_draw_glyph16(uint8_t *d, int linesize,
54 const uint8_t *font_ptr, int h,
55 uint32_t fgcol, uint32_t bgcol)
56 {
57 uint32_t font_data, xorcol;
58
59 xorcol = bgcol ^ fgcol;
60 do {
61 font_data = font_ptr[0];
62 vga_draw_glyph_line(d, expand4to8[font_data >> 4],
63 xorcol, bgcol);
64 vga_draw_glyph_line(d + 32, expand4to8[font_data & 0x0f],
65 xorcol, bgcol);
66 font_ptr += 4;
67 d += linesize;
68 } while (--h);
69 }
70
vga_draw_glyph9(uint8_t * d,int linesize,const uint8_t * font_ptr,int h,uint32_t fgcol,uint32_t bgcol,int dup9)71 static void vga_draw_glyph9(uint8_t *d, int linesize,
72 const uint8_t *font_ptr, int h,
73 uint32_t fgcol, uint32_t bgcol, int dup9)
74 {
75 uint32_t font_data, xorcol, v;
76
77 xorcol = bgcol ^ fgcol;
78 do {
79 font_data = font_ptr[0];
80 ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;
81 ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;
82 ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol;
83 ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol;
84 ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol;
85 ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol;
86 ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol;
87 v = (-((font_data >> 0) & 1) & xorcol) ^ bgcol;
88 ((uint32_t *)d)[7] = v;
89 if (dup9)
90 ((uint32_t *)d)[8] = v;
91 else
92 ((uint32_t *)d)[8] = bgcol;
93 font_ptr += 4;
94 d += linesize;
95 } while (--h);
96 }
97
98 /*
99 * 4 color mode
100 */
vga_draw_line2(VGACommonState * vga,uint8_t * d,uint32_t addr,int width,int hpel)101 static void *vga_draw_line2(VGACommonState *vga, uint8_t *d,
102 uint32_t addr, int width, int hpel)
103 {
104 uint32_t plane_mask, *palette, data, v;
105 int x;
106
107 palette = vga->last_palette;
108 plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
109 hpel &= 7;
110 if (hpel) {
111 width += 8;
112 d = vga->panning_buf;
113 }
114 width >>= 3;
115 for(x = 0; x < width; x++) {
116 data = vga_read_dword_le(vga, addr & (VGA_VRAM_SIZE - 1));
117 data &= plane_mask;
118 v = expand2[GET_PLANE(data, 0)];
119 v |= expand2[GET_PLANE(data, 2)] << 2;
120 ((uint32_t *)d)[0] = palette[v >> 12];
121 ((uint32_t *)d)[1] = palette[(v >> 8) & 0xf];
122 ((uint32_t *)d)[2] = palette[(v >> 4) & 0xf];
123 ((uint32_t *)d)[3] = palette[(v >> 0) & 0xf];
124
125 v = expand2[GET_PLANE(data, 1)];
126 v |= expand2[GET_PLANE(data, 3)] << 2;
127 ((uint32_t *)d)[4] = palette[v >> 12];
128 ((uint32_t *)d)[5] = palette[(v >> 8) & 0xf];
129 ((uint32_t *)d)[6] = palette[(v >> 4) & 0xf];
130 ((uint32_t *)d)[7] = palette[(v >> 0) & 0xf];
131 d += 32;
132 addr += 4;
133 }
134 return hpel ? vga->panning_buf + 4 * hpel : NULL;
135 }
136
137 #define PUT_PIXEL2(d, n, v) \
138 ((uint32_t *)d)[2*(n)] = ((uint32_t *)d)[2*(n)+1] = (v)
139
140 /*
141 * 4 color mode, dup2 horizontal
142 */
vga_draw_line2d2(VGACommonState * vga,uint8_t * d,uint32_t addr,int width,int hpel)143 static void *vga_draw_line2d2(VGACommonState *vga, uint8_t *d,
144 uint32_t addr, int width, int hpel)
145 {
146 uint32_t plane_mask, *palette, data, v;
147 int x;
148
149 palette = vga->last_palette;
150 plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
151 hpel &= 7;
152 if (hpel) {
153 width += 8;
154 d = vga->panning_buf;
155 }
156 width >>= 3;
157 for(x = 0; x < width; x++) {
158 data = vga_read_dword_le(vga, addr & (VGA_VRAM_SIZE - 1));
159 data &= plane_mask;
160 v = expand2[GET_PLANE(data, 0)];
161 v |= expand2[GET_PLANE(data, 2)] << 2;
162 PUT_PIXEL2(d, 0, palette[v >> 12]);
163 PUT_PIXEL2(d, 1, palette[(v >> 8) & 0xf]);
164 PUT_PIXEL2(d, 2, palette[(v >> 4) & 0xf]);
165 PUT_PIXEL2(d, 3, palette[(v >> 0) & 0xf]);
166
167 v = expand2[GET_PLANE(data, 1)];
168 v |= expand2[GET_PLANE(data, 3)] << 2;
169 PUT_PIXEL2(d, 4, palette[v >> 12]);
170 PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]);
171 PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]);
172 PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]);
173 d += 64;
174 addr += 4;
175 }
176 return hpel ? vga->panning_buf + 8 * hpel : NULL;
177 }
178
179 /*
180 * 16 color mode
181 */
vga_draw_line4(VGACommonState * vga,uint8_t * d,uint32_t addr,int width,int hpel)182 static void *vga_draw_line4(VGACommonState *vga, uint8_t *d,
183 uint32_t addr, int width, int hpel)
184 {
185 uint32_t plane_mask, data, v, *palette;
186 int x;
187
188 palette = vga->last_palette;
189 plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
190 hpel &= 7;
191 if (hpel) {
192 width += 8;
193 d = vga->panning_buf;
194 }
195 width >>= 3;
196 for(x = 0; x < width; x++) {
197 data = vga_read_dword_le(vga, addr & (VGA_VRAM_SIZE - 1));
198 data &= plane_mask;
199 v = expand4[GET_PLANE(data, 0)];
200 v |= expand4[GET_PLANE(data, 1)] << 1;
201 v |= expand4[GET_PLANE(data, 2)] << 2;
202 v |= expand4[GET_PLANE(data, 3)] << 3;
203 ((uint32_t *)d)[0] = palette[v >> 28];
204 ((uint32_t *)d)[1] = palette[(v >> 24) & 0xf];
205 ((uint32_t *)d)[2] = palette[(v >> 20) & 0xf];
206 ((uint32_t *)d)[3] = palette[(v >> 16) & 0xf];
207 ((uint32_t *)d)[4] = palette[(v >> 12) & 0xf];
208 ((uint32_t *)d)[5] = palette[(v >> 8) & 0xf];
209 ((uint32_t *)d)[6] = palette[(v >> 4) & 0xf];
210 ((uint32_t *)d)[7] = palette[(v >> 0) & 0xf];
211 d += 32;
212 addr += 4;
213 }
214 return hpel ? vga->panning_buf + 4 * hpel : NULL;
215 }
216
217 /*
218 * 16 color mode, dup2 horizontal
219 */
vga_draw_line4d2(VGACommonState * vga,uint8_t * d,uint32_t addr,int width,int hpel)220 static void *vga_draw_line4d2(VGACommonState *vga, uint8_t *d,
221 uint32_t addr, int width, int hpel)
222 {
223 uint32_t plane_mask, data, v, *palette;
224 int x;
225
226 palette = vga->last_palette;
227 plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
228 hpel &= 7;
229 if (hpel) {
230 width += 8;
231 d = vga->panning_buf;
232 }
233 width >>= 3;
234 for(x = 0; x < width; x++) {
235 data = vga_read_dword_le(vga, addr & (VGA_VRAM_SIZE - 1));
236 data &= plane_mask;
237 v = expand4[GET_PLANE(data, 0)];
238 v |= expand4[GET_PLANE(data, 1)] << 1;
239 v |= expand4[GET_PLANE(data, 2)] << 2;
240 v |= expand4[GET_PLANE(data, 3)] << 3;
241 PUT_PIXEL2(d, 0, palette[v >> 28]);
242 PUT_PIXEL2(d, 1, palette[(v >> 24) & 0xf]);
243 PUT_PIXEL2(d, 2, palette[(v >> 20) & 0xf]);
244 PUT_PIXEL2(d, 3, palette[(v >> 16) & 0xf]);
245 PUT_PIXEL2(d, 4, palette[(v >> 12) & 0xf]);
246 PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]);
247 PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]);
248 PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]);
249 d += 64;
250 addr += 4;
251 }
252 return hpel ? vga->panning_buf + 8 * hpel : NULL;
253 }
254
255 /*
256 * 256 color mode, double pixels
257 *
258 * XXX: add plane_mask support (never used in standard VGA modes)
259 */
vga_draw_line8d2(VGACommonState * vga,uint8_t * d,uint32_t addr,int width,int hpel)260 static void *vga_draw_line8d2(VGACommonState *vga, uint8_t *d,
261 uint32_t addr, int width, int hpel)
262 {
263 uint32_t *palette;
264 int x;
265
266 palette = vga->last_palette;
267 hpel = (hpel >> 1) & 3;
268
269 /* For 256 color modes, we can adjust the source address and write directly
270 * to the destination, even if horizontal pel panning is active. However,
271 * the loop below assumes that the address does not wrap in the middle of a
272 * plane. If that happens...
273 */
274 if (addr + (width >> 3) * 4 < VGA_VRAM_SIZE) {
275 addr += hpel * 4;
276 hpel = 0;
277 }
278
279 /* ... use the panning buffer as in planar modes. */
280 if (hpel) {
281 width += 8;
282 d = vga->panning_buf;
283 }
284 width >>= 3;
285 for(x = 0; x < width; x++) {
286 addr &= VGA_VRAM_SIZE - 1;
287 PUT_PIXEL2(d, 0, palette[vga_read_byte(vga, addr + 0)]);
288 PUT_PIXEL2(d, 1, palette[vga_read_byte(vga, addr + 1)]);
289 PUT_PIXEL2(d, 2, palette[vga_read_byte(vga, addr + 2)]);
290 PUT_PIXEL2(d, 3, palette[vga_read_byte(vga, addr + 3)]);
291 d += 32;
292 addr += 4;
293 }
294 return hpel ? vga->panning_buf + 8 * hpel : NULL;
295 }
296
297 /*
298 * standard 256 color mode
299 *
300 * XXX: add plane_mask support (never used in standard VGA modes)
301 */
vga_draw_line8(VGACommonState * vga,uint8_t * d,uint32_t addr,int width,int hpel)302 static void *vga_draw_line8(VGACommonState *vga, uint8_t *d,
303 uint32_t addr, int width, int hpel)
304 {
305 uint32_t *palette;
306 int x;
307
308 palette = vga->last_palette;
309 hpel = (hpel >> 1) & 3;
310 if (hpel) {
311 width += 8;
312 d = vga->panning_buf;
313 }
314 width >>= 3;
315 for(x = 0; x < width; x++) {
316 ((uint32_t *)d)[0] = palette[vga_read_byte(vga, addr + 0)];
317 ((uint32_t *)d)[1] = palette[vga_read_byte(vga, addr + 1)];
318 ((uint32_t *)d)[2] = palette[vga_read_byte(vga, addr + 2)];
319 ((uint32_t *)d)[3] = palette[vga_read_byte(vga, addr + 3)];
320 ((uint32_t *)d)[4] = palette[vga_read_byte(vga, addr + 4)];
321 ((uint32_t *)d)[5] = palette[vga_read_byte(vga, addr + 5)];
322 ((uint32_t *)d)[6] = palette[vga_read_byte(vga, addr + 6)];
323 ((uint32_t *)d)[7] = palette[vga_read_byte(vga, addr + 7)];
324 d += 32;
325 addr += 8;
326 }
327 return hpel ? vga->panning_buf + 4 * hpel : NULL;
328 }
329
330 /*
331 * 15 bit color
332 */
vga_draw_line15_le(VGACommonState * vga,uint8_t * d,uint32_t addr,int width,int hpel)333 static void *vga_draw_line15_le(VGACommonState *vga, uint8_t *d,
334 uint32_t addr, int width, int hpel)
335 {
336 int w;
337 uint32_t v, r, g, b;
338
339 w = width;
340 do {
341 v = vga_read_word_le(vga, addr);
342 r = (v >> 7) & 0xf8;
343 g = (v >> 2) & 0xf8;
344 b = (v << 3) & 0xf8;
345 ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
346 addr += 2;
347 d += 4;
348 } while (--w != 0);
349 return NULL;
350 }
351
vga_draw_line15_be(VGACommonState * vga,uint8_t * d,uint32_t addr,int width,int hpel)352 static void *vga_draw_line15_be(VGACommonState *vga, uint8_t *d,
353 uint32_t addr, int width, int hpel)
354 {
355 int w;
356 uint32_t v, r, g, b;
357
358 w = width;
359 do {
360 v = vga_read_word_be(vga, addr);
361 r = (v >> 7) & 0xf8;
362 g = (v >> 2) & 0xf8;
363 b = (v << 3) & 0xf8;
364 ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
365 addr += 2;
366 d += 4;
367 } while (--w != 0);
368 return NULL;
369 }
370
371 /*
372 * 16 bit color
373 */
vga_draw_line16_le(VGACommonState * vga,uint8_t * d,uint32_t addr,int width,int hpel)374 static void *vga_draw_line16_le(VGACommonState *vga, uint8_t *d,
375 uint32_t addr, int width, int hpel)
376 {
377 int w;
378 uint32_t v, r, g, b;
379
380 w = width;
381 do {
382 v = vga_read_word_le(vga, addr);
383 r = (v >> 8) & 0xf8;
384 g = (v >> 3) & 0xfc;
385 b = (v << 3) & 0xf8;
386 ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
387 addr += 2;
388 d += 4;
389 } while (--w != 0);
390 return NULL;
391 }
392
vga_draw_line16_be(VGACommonState * vga,uint8_t * d,uint32_t addr,int width,int hpel)393 static void *vga_draw_line16_be(VGACommonState *vga, uint8_t *d,
394 uint32_t addr, int width, int hpel)
395 {
396 int w;
397 uint32_t v, r, g, b;
398
399 w = width;
400 do {
401 v = vga_read_word_be(vga, addr);
402 r = (v >> 8) & 0xf8;
403 g = (v >> 3) & 0xfc;
404 b = (v << 3) & 0xf8;
405 ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
406 addr += 2;
407 d += 4;
408 } while (--w != 0);
409 return NULL;
410 }
411
412 /*
413 * 24 bit color
414 */
vga_draw_line24_le(VGACommonState * vga,uint8_t * d,uint32_t addr,int width,int hpel)415 static void *vga_draw_line24_le(VGACommonState *vga, uint8_t *d,
416 uint32_t addr, int width, int hpel)
417 {
418 int w;
419 uint32_t r, g, b;
420
421 w = width;
422 do {
423 b = vga_read_byte(vga, addr + 0);
424 g = vga_read_byte(vga, addr + 1);
425 r = vga_read_byte(vga, addr + 2);
426 ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
427 addr += 3;
428 d += 4;
429 } while (--w != 0);
430 return NULL;
431 }
432
vga_draw_line24_be(VGACommonState * vga,uint8_t * d,uint32_t addr,int width,int hpel)433 static void *vga_draw_line24_be(VGACommonState *vga, uint8_t *d,
434 uint32_t addr, int width, int hpel)
435 {
436 int w;
437 uint32_t r, g, b;
438
439 w = width;
440 do {
441 r = vga_read_byte(vga, addr + 0);
442 g = vga_read_byte(vga, addr + 1);
443 b = vga_read_byte(vga, addr + 2);
444 ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
445 addr += 3;
446 d += 4;
447 } while (--w != 0);
448 return NULL;
449 }
450
451 /*
452 * 32 bit color
453 */
vga_draw_line32_le(VGACommonState * vga,uint8_t * d,uint32_t addr,int width,int hpel)454 static void *vga_draw_line32_le(VGACommonState *vga, uint8_t *d,
455 uint32_t addr, int width, int hpel)
456 {
457 int w;
458 uint32_t r, g, b;
459
460 w = width;
461 do {
462 b = vga_read_byte(vga, addr + 0);
463 g = vga_read_byte(vga, addr + 1);
464 r = vga_read_byte(vga, addr + 2);
465 ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
466 addr += 4;
467 d += 4;
468 } while (--w != 0);
469 return NULL;
470 }
471
vga_draw_line32_be(VGACommonState * vga,uint8_t * d,uint32_t addr,int width,int hpel)472 static void *vga_draw_line32_be(VGACommonState *vga, uint8_t *d,
473 uint32_t addr, int width, int hpel)
474 {
475 int w;
476 uint32_t r, g, b;
477
478 w = width;
479 do {
480 r = vga_read_byte(vga, addr + 1);
481 g = vga_read_byte(vga, addr + 2);
482 b = vga_read_byte(vga, addr + 3);
483 ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
484 addr += 4;
485 d += 4;
486 } while (--w != 0);
487 return NULL;
488 }
489