]>
Commit | Line | Data |
---|---|---|
e89f66ec FB |
1 | /* |
2 | * QEMU VGA Emulator templates | |
5fafdf24 | 3 | * |
e89f66ec | 4 | * Copyright (c) 2003 Fabrice Bellard |
5fafdf24 | 5 | * |
e89f66ec FB |
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 | ||
d2e043a8 BH |
25 | static inline void vga_draw_glyph_line(uint8_t *d, uint32_t font_data, |
26 | uint32_t xorcol, uint32_t bgcol) | |
e89f66ec | 27 | { |
b1ba6574 FB |
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; | |
17b0018b FB |
36 | } |
37 | ||
d2e043a8 BH |
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) | |
17b0018b FB |
41 | { |
42 | uint32_t font_data, xorcol; | |
3b46e624 | 43 | |
17b0018b FB |
44 | xorcol = bgcol ^ fgcol; |
45 | do { | |
46 | font_data = font_ptr[0]; | |
d2e043a8 | 47 | vga_draw_glyph_line(d, font_data, xorcol, bgcol); |
17b0018b FB |
48 | font_ptr += 4; |
49 | d += linesize; | |
50 | } while (--h); | |
51 | } | |
52 | ||
d2e043a8 | 53 | static void vga_draw_glyph16(uint8_t *d, int linesize, |
17b0018b FB |
54 | const uint8_t *font_ptr, int h, |
55 | uint32_t fgcol, uint32_t bgcol) | |
56 | { | |
57 | uint32_t font_data, xorcol; | |
3b46e624 | 58 | |
17b0018b FB |
59 | xorcol = bgcol ^ fgcol; |
60 | do { | |
61 | font_data = font_ptr[0]; | |
d2e043a8 BH |
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); | |
e89f66ec FB |
66 | font_ptr += 4; |
67 | d += linesize; | |
68 | } while (--h); | |
69 | } | |
70 | ||
d2e043a8 BH |
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) | |
e89f66ec FB |
74 | { |
75 | uint32_t font_data, xorcol, v; | |
3b46e624 | 76 | |
e89f66ec FB |
77 | xorcol = bgcol ^ fgcol; |
78 | do { | |
79 | font_data = font_ptr[0]; | |
eccabc6e FB |
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; | |
e89f66ec FB |
88 | ((uint32_t *)d)[7] = v; |
89 | if (dup9) | |
39cf7803 | 90 | ((uint32_t *)d)[8] = v; |
e89f66ec | 91 | else |
39cf7803 | 92 | ((uint32_t *)d)[8] = bgcol; |
e89f66ec FB |
93 | font_ptr += 4; |
94 | d += linesize; | |
95 | } while (--h); | |
96 | } | |
97 | ||
5fafdf24 | 98 | /* |
e89f66ec FB |
99 | * 4 color mode |
100 | */ | |
d2e043a8 BH |
101 | static void vga_draw_line2(VGACommonState *s1, uint8_t *d, |
102 | const uint8_t *s, int width) | |
e89f66ec FB |
103 | { |
104 | uint32_t plane_mask, *palette, data, v; | |
105 | int x; | |
106 | ||
107 | palette = s1->last_palette; | |
5e55efc9 | 108 | plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; |
e89f66ec FB |
109 | width >>= 3; |
110 | for(x = 0; x < width; x++) { | |
111 | data = ((uint32_t *)s)[0]; | |
112 | data &= plane_mask; | |
113 | v = expand2[GET_PLANE(data, 0)]; | |
114 | v |= expand2[GET_PLANE(data, 2)] << 2; | |
d2e043a8 BH |
115 | ((uint32_t *)d)[0] = palette[v >> 12]; |
116 | ((uint32_t *)d)[1] = palette[(v >> 8) & 0xf]; | |
117 | ((uint32_t *)d)[2] = palette[(v >> 4) & 0xf]; | |
118 | ((uint32_t *)d)[3] = palette[(v >> 0) & 0xf]; | |
e89f66ec FB |
119 | |
120 | v = expand2[GET_PLANE(data, 1)]; | |
121 | v |= expand2[GET_PLANE(data, 3)] << 2; | |
d2e043a8 BH |
122 | ((uint32_t *)d)[4] = palette[v >> 12]; |
123 | ((uint32_t *)d)[5] = palette[(v >> 8) & 0xf]; | |
124 | ((uint32_t *)d)[6] = palette[(v >> 4) & 0xf]; | |
125 | ((uint32_t *)d)[7] = palette[(v >> 0) & 0xf]; | |
126 | d += 32; | |
e89f66ec FB |
127 | s += 4; |
128 | } | |
129 | } | |
130 | ||
17b0018b FB |
131 | #define PUT_PIXEL2(d, n, v) \ |
132 | ((uint32_t *)d)[2*(n)] = ((uint32_t *)d)[2*(n)+1] = (v) | |
17b0018b | 133 | |
5fafdf24 | 134 | /* |
17b0018b FB |
135 | * 4 color mode, dup2 horizontal |
136 | */ | |
d2e043a8 BH |
137 | static void vga_draw_line2d2(VGACommonState *s1, uint8_t *d, |
138 | const uint8_t *s, int width) | |
17b0018b FB |
139 | { |
140 | uint32_t plane_mask, *palette, data, v; | |
141 | int x; | |
142 | ||
143 | palette = s1->last_palette; | |
5e55efc9 | 144 | plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; |
17b0018b FB |
145 | width >>= 3; |
146 | for(x = 0; x < width; x++) { | |
147 | data = ((uint32_t *)s)[0]; | |
148 | data &= plane_mask; | |
149 | v = expand2[GET_PLANE(data, 0)]; | |
150 | v |= expand2[GET_PLANE(data, 2)] << 2; | |
151 | PUT_PIXEL2(d, 0, palette[v >> 12]); | |
152 | PUT_PIXEL2(d, 1, palette[(v >> 8) & 0xf]); | |
153 | PUT_PIXEL2(d, 2, palette[(v >> 4) & 0xf]); | |
154 | PUT_PIXEL2(d, 3, palette[(v >> 0) & 0xf]); | |
155 | ||
156 | v = expand2[GET_PLANE(data, 1)]; | |
157 | v |= expand2[GET_PLANE(data, 3)] << 2; | |
158 | PUT_PIXEL2(d, 4, palette[v >> 12]); | |
159 | PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]); | |
160 | PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]); | |
161 | PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]); | |
d2e043a8 | 162 | d += 64; |
17b0018b FB |
163 | s += 4; |
164 | } | |
165 | } | |
166 | ||
5fafdf24 | 167 | /* |
e89f66ec FB |
168 | * 16 color mode |
169 | */ | |
d2e043a8 BH |
170 | static void vga_draw_line4(VGACommonState *s1, uint8_t *d, |
171 | const uint8_t *s, int width) | |
e89f66ec FB |
172 | { |
173 | uint32_t plane_mask, data, v, *palette; | |
174 | int x; | |
175 | ||
176 | palette = s1->last_palette; | |
5e55efc9 | 177 | plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; |
e89f66ec FB |
178 | width >>= 3; |
179 | for(x = 0; x < width; x++) { | |
180 | data = ((uint32_t *)s)[0]; | |
181 | data &= plane_mask; | |
182 | v = expand4[GET_PLANE(data, 0)]; | |
183 | v |= expand4[GET_PLANE(data, 1)] << 1; | |
184 | v |= expand4[GET_PLANE(data, 2)] << 2; | |
185 | v |= expand4[GET_PLANE(data, 3)] << 3; | |
d2e043a8 BH |
186 | ((uint32_t *)d)[0] = palette[v >> 28]; |
187 | ((uint32_t *)d)[1] = palette[(v >> 24) & 0xf]; | |
188 | ((uint32_t *)d)[2] = palette[(v >> 20) & 0xf]; | |
189 | ((uint32_t *)d)[3] = palette[(v >> 16) & 0xf]; | |
190 | ((uint32_t *)d)[4] = palette[(v >> 12) & 0xf]; | |
191 | ((uint32_t *)d)[5] = palette[(v >> 8) & 0xf]; | |
192 | ((uint32_t *)d)[6] = palette[(v >> 4) & 0xf]; | |
193 | ((uint32_t *)d)[7] = palette[(v >> 0) & 0xf]; | |
194 | d += 32; | |
e89f66ec FB |
195 | s += 4; |
196 | } | |
197 | } | |
198 | ||
5fafdf24 | 199 | /* |
17b0018b FB |
200 | * 16 color mode, dup2 horizontal |
201 | */ | |
d2e043a8 BH |
202 | static void vga_draw_line4d2(VGACommonState *s1, uint8_t *d, |
203 | const uint8_t *s, int width) | |
17b0018b FB |
204 | { |
205 | uint32_t plane_mask, data, v, *palette; | |
206 | int x; | |
207 | ||
208 | palette = s1->last_palette; | |
5e55efc9 | 209 | plane_mask = mask16[s1->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; |
17b0018b FB |
210 | width >>= 3; |
211 | for(x = 0; x < width; x++) { | |
212 | data = ((uint32_t *)s)[0]; | |
213 | data &= plane_mask; | |
214 | v = expand4[GET_PLANE(data, 0)]; | |
215 | v |= expand4[GET_PLANE(data, 1)] << 1; | |
216 | v |= expand4[GET_PLANE(data, 2)] << 2; | |
217 | v |= expand4[GET_PLANE(data, 3)] << 3; | |
218 | PUT_PIXEL2(d, 0, palette[v >> 28]); | |
219 | PUT_PIXEL2(d, 1, palette[(v >> 24) & 0xf]); | |
220 | PUT_PIXEL2(d, 2, palette[(v >> 20) & 0xf]); | |
221 | PUT_PIXEL2(d, 3, palette[(v >> 16) & 0xf]); | |
222 | PUT_PIXEL2(d, 4, palette[(v >> 12) & 0xf]); | |
223 | PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]); | |
224 | PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]); | |
225 | PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]); | |
d2e043a8 | 226 | d += 64; |
17b0018b FB |
227 | s += 4; |
228 | } | |
229 | } | |
230 | ||
5fafdf24 | 231 | /* |
17b0018b FB |
232 | * 256 color mode, double pixels |
233 | * | |
234 | * XXX: add plane_mask support (never used in standard VGA modes) | |
235 | */ | |
d2e043a8 BH |
236 | static void vga_draw_line8d2(VGACommonState *s1, uint8_t *d, |
237 | const uint8_t *s, int width) | |
17b0018b FB |
238 | { |
239 | uint32_t *palette; | |
240 | int x; | |
241 | ||
242 | palette = s1->last_palette; | |
243 | width >>= 3; | |
244 | for(x = 0; x < width; x++) { | |
245 | PUT_PIXEL2(d, 0, palette[s[0]]); | |
246 | PUT_PIXEL2(d, 1, palette[s[1]]); | |
247 | PUT_PIXEL2(d, 2, palette[s[2]]); | |
248 | PUT_PIXEL2(d, 3, palette[s[3]]); | |
d2e043a8 | 249 | d += 32; |
17b0018b FB |
250 | s += 4; |
251 | } | |
252 | } | |
253 | ||
5fafdf24 | 254 | /* |
17b0018b | 255 | * standard 256 color mode |
e89f66ec FB |
256 | * |
257 | * XXX: add plane_mask support (never used in standard VGA modes) | |
258 | */ | |
d2e043a8 BH |
259 | static void vga_draw_line8(VGACommonState *s1, uint8_t *d, |
260 | const uint8_t *s, int width) | |
e89f66ec FB |
261 | { |
262 | uint32_t *palette; | |
263 | int x; | |
264 | ||
265 | palette = s1->last_palette; | |
266 | width >>= 3; | |
267 | for(x = 0; x < width; x++) { | |
d2e043a8 BH |
268 | ((uint32_t *)d)[0] = palette[s[0]]; |
269 | ((uint32_t *)d)[1] = palette[s[1]]; | |
270 | ((uint32_t *)d)[2] = palette[s[2]]; | |
271 | ((uint32_t *)d)[3] = palette[s[3]]; | |
272 | ((uint32_t *)d)[4] = palette[s[4]]; | |
273 | ((uint32_t *)d)[5] = palette[s[5]]; | |
274 | ((uint32_t *)d)[6] = palette[s[6]]; | |
275 | ((uint32_t *)d)[7] = palette[s[7]]; | |
276 | d += 32; | |
e89f66ec FB |
277 | s += 8; |
278 | } | |
279 | } | |
280 | ||
5fafdf24 | 281 | /* |
e89f66ec FB |
282 | * 15 bit color |
283 | */ | |
46c3a8c8 BH |
284 | static void vga_draw_line15_le(VGACommonState *s1, uint8_t *d, |
285 | const uint8_t *s, int width) | |
e89f66ec | 286 | { |
e89f66ec FB |
287 | int w; |
288 | uint32_t v, r, g, b; | |
289 | ||
290 | w = width; | |
291 | do { | |
46c3a8c8 BH |
292 | v = lduw_le_p((void *)s); |
293 | r = (v >> 7) & 0xf8; | |
294 | g = (v >> 2) & 0xf8; | |
295 | b = (v << 3) & 0xf8; | |
296 | ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); | |
297 | s += 2; | |
298 | d += 4; | |
299 | } while (--w != 0); | |
300 | } | |
301 | ||
302 | static void vga_draw_line15_be(VGACommonState *s1, uint8_t *d, | |
303 | const uint8_t *s, int width) | |
304 | { | |
305 | int w; | |
306 | uint32_t v, r, g, b; | |
307 | ||
308 | w = width; | |
309 | do { | |
310 | v = lduw_be_p((void *)s); | |
e89f66ec FB |
311 | r = (v >> 7) & 0xf8; |
312 | g = (v >> 2) & 0xf8; | |
313 | b = (v << 3) & 0xf8; | |
d2e043a8 | 314 | ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); |
e89f66ec | 315 | s += 2; |
d2e043a8 | 316 | d += 4; |
e89f66ec | 317 | } while (--w != 0); |
e89f66ec FB |
318 | } |
319 | ||
5fafdf24 | 320 | /* |
e89f66ec FB |
321 | * 16 bit color |
322 | */ | |
46c3a8c8 BH |
323 | static void vga_draw_line16_le(VGACommonState *s1, uint8_t *d, |
324 | const uint8_t *s, int width) | |
e89f66ec | 325 | { |
e89f66ec FB |
326 | int w; |
327 | uint32_t v, r, g, b; | |
328 | ||
329 | w = width; | |
330 | do { | |
46c3a8c8 BH |
331 | v = lduw_le_p((void *)s); |
332 | r = (v >> 8) & 0xf8; | |
333 | g = (v >> 3) & 0xfc; | |
334 | b = (v << 3) & 0xf8; | |
335 | ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); | |
336 | s += 2; | |
337 | d += 4; | |
338 | } while (--w != 0); | |
339 | } | |
340 | ||
341 | static void vga_draw_line16_be(VGACommonState *s1, uint8_t *d, | |
342 | const uint8_t *s, int width) | |
343 | { | |
344 | int w; | |
345 | uint32_t v, r, g, b; | |
346 | ||
347 | w = width; | |
348 | do { | |
349 | v = lduw_be_p((void *)s); | |
e89f66ec FB |
350 | r = (v >> 8) & 0xf8; |
351 | g = (v >> 3) & 0xfc; | |
352 | b = (v << 3) & 0xf8; | |
d2e043a8 | 353 | ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); |
e89f66ec | 354 | s += 2; |
d2e043a8 | 355 | d += 4; |
e89f66ec | 356 | } while (--w != 0); |
e89f66ec FB |
357 | } |
358 | ||
5fafdf24 | 359 | /* |
4fa0f5d2 FB |
360 | * 24 bit color |
361 | */ | |
46c3a8c8 BH |
362 | static void vga_draw_line24_le(VGACommonState *s1, uint8_t *d, |
363 | const uint8_t *s, int width) | |
4fa0f5d2 FB |
364 | { |
365 | int w; | |
366 | uint32_t r, g, b; | |
367 | ||
368 | w = width; | |
369 | do { | |
370 | b = s[0]; | |
371 | g = s[1]; | |
372 | r = s[2]; | |
46c3a8c8 BH |
373 | ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); |
374 | s += 3; | |
375 | d += 4; | |
376 | } while (--w != 0); | |
377 | } | |
378 | ||
379 | static void vga_draw_line24_be(VGACommonState *s1, uint8_t *d, | |
380 | const uint8_t *s, int width) | |
381 | { | |
382 | int w; | |
383 | uint32_t r, g, b; | |
384 | ||
385 | w = width; | |
386 | do { | |
387 | r = s[0]; | |
388 | g = s[1]; | |
389 | b = s[2]; | |
d2e043a8 | 390 | ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); |
4fa0f5d2 | 391 | s += 3; |
d2e043a8 | 392 | d += 4; |
4fa0f5d2 FB |
393 | } while (--w != 0); |
394 | } | |
395 | ||
5fafdf24 | 396 | /* |
e89f66ec FB |
397 | * 32 bit color |
398 | */ | |
46c3a8c8 BH |
399 | static void vga_draw_line32_le(VGACommonState *s1, uint8_t *d, |
400 | const uint8_t *s, int width) | |
e89f66ec | 401 | { |
46c3a8c8 | 402 | #ifndef HOST_WORDS_BIGENDIAN |
e89f66ec FB |
403 | memcpy(d, s, width * 4); |
404 | #else | |
405 | int w; | |
406 | uint32_t r, g, b; | |
407 | ||
408 | w = width; | |
409 | do { | |
410 | b = s[0]; | |
411 | g = s[1]; | |
412 | r = s[2]; | |
46c3a8c8 BH |
413 | ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); |
414 | s += 4; | |
415 | d += 4; | |
416 | } while (--w != 0); | |
53c862a8 | 417 | #endif |
46c3a8c8 BH |
418 | } |
419 | ||
420 | static void vga_draw_line32_be(VGACommonState *s1, uint8_t *d, | |
421 | const uint8_t *s, int width) | |
422 | { | |
423 | #ifdef HOST_WORDS_BIGENDIAN | |
424 | memcpy(d, s, width * 4); | |
425 | #else | |
426 | int w; | |
427 | uint32_t r, g, b; | |
428 | ||
429 | w = width; | |
430 | do { | |
431 | r = s[1]; | |
432 | g = s[2]; | |
433 | b = s[3]; | |
d2e043a8 | 434 | ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); |
e89f66ec | 435 | s += 4; |
d2e043a8 | 436 | d += 4; |
e89f66ec FB |
437 | } while (--w != 0); |
438 | #endif | |
439 | } |