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 | |
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 | |
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 | |
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 | |
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 | static inline uint8_t vga_read_byte(VGACommonState *vga, uint32_t addr) |
99 | { |
100 | return vga->vram_ptr[addr & vga->vbe_size_mask]; |
101 | } |
102 | |
103 | static inline uint16_t vga_read_word_le(VGACommonState *vga, uint32_t addr) |
104 | { |
105 | uint32_t offset = addr & vga->vbe_size_mask & ~1; |
106 | uint16_t *ptr = (uint16_t *)(vga->vram_ptr + offset); |
107 | return lduw_le_p(ptr); |
108 | } |
109 | |
110 | static inline uint16_t vga_read_word_be(VGACommonState *vga, uint32_t addr) |
111 | { |
112 | uint32_t offset = addr & vga->vbe_size_mask & ~1; |
113 | uint16_t *ptr = (uint16_t *)(vga->vram_ptr + offset); |
114 | return lduw_be_p(ptr); |
115 | } |
116 | |
117 | static inline uint32_t vga_read_dword_le(VGACommonState *vga, uint32_t addr) |
118 | { |
119 | uint32_t offset = addr & vga->vbe_size_mask & ~3; |
120 | uint32_t *ptr = (uint32_t *)(vga->vram_ptr + offset); |
121 | return ldl_le_p(ptr); |
122 | } |
123 | |
124 | /* |
125 | * 4 color mode |
126 | */ |
127 | static void vga_draw_line2(VGACommonState *vga, uint8_t *d, |
128 | uint32_t addr, int width) |
129 | { |
130 | uint32_t plane_mask, *palette, data, v; |
131 | int x; |
132 | |
133 | palette = vga->last_palette; |
134 | plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; |
135 | width >>= 3; |
136 | for(x = 0; x < width; x++) { |
137 | data = vga_read_dword_le(vga, addr); |
138 | data &= plane_mask; |
139 | v = expand2[GET_PLANE(data, 0)]; |
140 | v |= expand2[GET_PLANE(data, 2)] << 2; |
141 | ((uint32_t *)d)[0] = palette[v >> 12]; |
142 | ((uint32_t *)d)[1] = palette[(v >> 8) & 0xf]; |
143 | ((uint32_t *)d)[2] = palette[(v >> 4) & 0xf]; |
144 | ((uint32_t *)d)[3] = palette[(v >> 0) & 0xf]; |
145 | |
146 | v = expand2[GET_PLANE(data, 1)]; |
147 | v |= expand2[GET_PLANE(data, 3)] << 2; |
148 | ((uint32_t *)d)[4] = palette[v >> 12]; |
149 | ((uint32_t *)d)[5] = palette[(v >> 8) & 0xf]; |
150 | ((uint32_t *)d)[6] = palette[(v >> 4) & 0xf]; |
151 | ((uint32_t *)d)[7] = palette[(v >> 0) & 0xf]; |
152 | d += 32; |
153 | addr += 4; |
154 | } |
155 | } |
156 | |
157 | #define PUT_PIXEL2(d, n, v) \ |
158 | ((uint32_t *)d)[2*(n)] = ((uint32_t *)d)[2*(n)+1] = (v) |
159 | |
160 | /* |
161 | * 4 color mode, dup2 horizontal |
162 | */ |
163 | static void vga_draw_line2d2(VGACommonState *vga, uint8_t *d, |
164 | uint32_t addr, int width) |
165 | { |
166 | uint32_t plane_mask, *palette, data, v; |
167 | int x; |
168 | |
169 | palette = vga->last_palette; |
170 | plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; |
171 | width >>= 3; |
172 | for(x = 0; x < width; x++) { |
173 | data = vga_read_dword_le(vga, addr); |
174 | data &= plane_mask; |
175 | v = expand2[GET_PLANE(data, 0)]; |
176 | v |= expand2[GET_PLANE(data, 2)] << 2; |
177 | PUT_PIXEL2(d, 0, palette[v >> 12]); |
178 | PUT_PIXEL2(d, 1, palette[(v >> 8) & 0xf]); |
179 | PUT_PIXEL2(d, 2, palette[(v >> 4) & 0xf]); |
180 | PUT_PIXEL2(d, 3, palette[(v >> 0) & 0xf]); |
181 | |
182 | v = expand2[GET_PLANE(data, 1)]; |
183 | v |= expand2[GET_PLANE(data, 3)] << 2; |
184 | PUT_PIXEL2(d, 4, palette[v >> 12]); |
185 | PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]); |
186 | PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]); |
187 | PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]); |
188 | d += 64; |
189 | addr += 4; |
190 | } |
191 | } |
192 | |
193 | /* |
194 | * 16 color mode |
195 | */ |
196 | static void vga_draw_line4(VGACommonState *vga, uint8_t *d, |
197 | uint32_t addr, int width) |
198 | { |
199 | uint32_t plane_mask, data, v, *palette; |
200 | int x; |
201 | |
202 | palette = vga->last_palette; |
203 | plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; |
204 | width >>= 3; |
205 | for(x = 0; x < width; x++) { |
206 | data = vga_read_dword_le(vga, addr); |
207 | data &= plane_mask; |
208 | v = expand4[GET_PLANE(data, 0)]; |
209 | v |= expand4[GET_PLANE(data, 1)] << 1; |
210 | v |= expand4[GET_PLANE(data, 2)] << 2; |
211 | v |= expand4[GET_PLANE(data, 3)] << 3; |
212 | ((uint32_t *)d)[0] = palette[v >> 28]; |
213 | ((uint32_t *)d)[1] = palette[(v >> 24) & 0xf]; |
214 | ((uint32_t *)d)[2] = palette[(v >> 20) & 0xf]; |
215 | ((uint32_t *)d)[3] = palette[(v >> 16) & 0xf]; |
216 | ((uint32_t *)d)[4] = palette[(v >> 12) & 0xf]; |
217 | ((uint32_t *)d)[5] = palette[(v >> 8) & 0xf]; |
218 | ((uint32_t *)d)[6] = palette[(v >> 4) & 0xf]; |
219 | ((uint32_t *)d)[7] = palette[(v >> 0) & 0xf]; |
220 | d += 32; |
221 | addr += 4; |
222 | } |
223 | } |
224 | |
225 | /* |
226 | * 16 color mode, dup2 horizontal |
227 | */ |
228 | static void vga_draw_line4d2(VGACommonState *vga, uint8_t *d, |
229 | uint32_t addr, int width) |
230 | { |
231 | uint32_t plane_mask, data, v, *palette; |
232 | int x; |
233 | |
234 | palette = vga->last_palette; |
235 | plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf]; |
236 | width >>= 3; |
237 | for(x = 0; x < width; x++) { |
238 | data = vga_read_dword_le(vga, addr); |
239 | data &= plane_mask; |
240 | v = expand4[GET_PLANE(data, 0)]; |
241 | v |= expand4[GET_PLANE(data, 1)] << 1; |
242 | v |= expand4[GET_PLANE(data, 2)] << 2; |
243 | v |= expand4[GET_PLANE(data, 3)] << 3; |
244 | PUT_PIXEL2(d, 0, palette[v >> 28]); |
245 | PUT_PIXEL2(d, 1, palette[(v >> 24) & 0xf]); |
246 | PUT_PIXEL2(d, 2, palette[(v >> 20) & 0xf]); |
247 | PUT_PIXEL2(d, 3, palette[(v >> 16) & 0xf]); |
248 | PUT_PIXEL2(d, 4, palette[(v >> 12) & 0xf]); |
249 | PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]); |
250 | PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]); |
251 | PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]); |
252 | d += 64; |
253 | addr += 4; |
254 | } |
255 | } |
256 | |
257 | /* |
258 | * 256 color mode, double pixels |
259 | * |
260 | * XXX: add plane_mask support (never used in standard VGA modes) |
261 | */ |
262 | static void vga_draw_line8d2(VGACommonState *vga, uint8_t *d, |
263 | uint32_t addr, int width) |
264 | { |
265 | uint32_t *palette; |
266 | int x; |
267 | |
268 | palette = vga->last_palette; |
269 | width >>= 3; |
270 | for(x = 0; x < width; x++) { |
271 | PUT_PIXEL2(d, 0, palette[vga_read_byte(vga, addr + 0)]); |
272 | PUT_PIXEL2(d, 1, palette[vga_read_byte(vga, addr + 1)]); |
273 | PUT_PIXEL2(d, 2, palette[vga_read_byte(vga, addr + 2)]); |
274 | PUT_PIXEL2(d, 3, palette[vga_read_byte(vga, addr + 3)]); |
275 | d += 32; |
276 | addr += 4; |
277 | } |
278 | } |
279 | |
280 | /* |
281 | * standard 256 color mode |
282 | * |
283 | * XXX: add plane_mask support (never used in standard VGA modes) |
284 | */ |
285 | static void vga_draw_line8(VGACommonState *vga, uint8_t *d, |
286 | uint32_t addr, int width) |
287 | { |
288 | uint32_t *palette; |
289 | int x; |
290 | |
291 | palette = vga->last_palette; |
292 | width >>= 3; |
293 | for(x = 0; x < width; x++) { |
294 | ((uint32_t *)d)[0] = palette[vga_read_byte(vga, addr + 0)]; |
295 | ((uint32_t *)d)[1] = palette[vga_read_byte(vga, addr + 1)]; |
296 | ((uint32_t *)d)[2] = palette[vga_read_byte(vga, addr + 2)]; |
297 | ((uint32_t *)d)[3] = palette[vga_read_byte(vga, addr + 3)]; |
298 | ((uint32_t *)d)[4] = palette[vga_read_byte(vga, addr + 4)]; |
299 | ((uint32_t *)d)[5] = palette[vga_read_byte(vga, addr + 5)]; |
300 | ((uint32_t *)d)[6] = palette[vga_read_byte(vga, addr + 6)]; |
301 | ((uint32_t *)d)[7] = palette[vga_read_byte(vga, addr + 7)]; |
302 | d += 32; |
303 | addr += 8; |
304 | } |
305 | } |
306 | |
307 | /* |
308 | * 15 bit color |
309 | */ |
310 | static void vga_draw_line15_le(VGACommonState *vga, uint8_t *d, |
311 | uint32_t addr, int width) |
312 | { |
313 | int w; |
314 | uint32_t v, r, g, b; |
315 | |
316 | w = width; |
317 | do { |
318 | v = vga_read_word_le(vga, addr); |
319 | r = (v >> 7) & 0xf8; |
320 | g = (v >> 2) & 0xf8; |
321 | b = (v << 3) & 0xf8; |
322 | ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); |
323 | addr += 2; |
324 | d += 4; |
325 | } while (--w != 0); |
326 | } |
327 | |
328 | static void vga_draw_line15_be(VGACommonState *vga, uint8_t *d, |
329 | uint32_t addr, int width) |
330 | { |
331 | int w; |
332 | uint32_t v, r, g, b; |
333 | |
334 | w = width; |
335 | do { |
336 | v = vga_read_word_be(vga, addr); |
337 | r = (v >> 7) & 0xf8; |
338 | g = (v >> 2) & 0xf8; |
339 | b = (v << 3) & 0xf8; |
340 | ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); |
341 | addr += 2; |
342 | d += 4; |
343 | } while (--w != 0); |
344 | } |
345 | |
346 | /* |
347 | * 16 bit color |
348 | */ |
349 | static void vga_draw_line16_le(VGACommonState *vga, uint8_t *d, |
350 | uint32_t addr, int width) |
351 | { |
352 | int w; |
353 | uint32_t v, r, g, b; |
354 | |
355 | w = width; |
356 | do { |
357 | v = vga_read_word_le(vga, addr); |
358 | r = (v >> 8) & 0xf8; |
359 | g = (v >> 3) & 0xfc; |
360 | b = (v << 3) & 0xf8; |
361 | ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); |
362 | addr += 2; |
363 | d += 4; |
364 | } while (--w != 0); |
365 | } |
366 | |
367 | static void vga_draw_line16_be(VGACommonState *vga, uint8_t *d, |
368 | uint32_t addr, int width) |
369 | { |
370 | int w; |
371 | uint32_t v, r, g, b; |
372 | |
373 | w = width; |
374 | do { |
375 | v = vga_read_word_be(vga, addr); |
376 | r = (v >> 8) & 0xf8; |
377 | g = (v >> 3) & 0xfc; |
378 | b = (v << 3) & 0xf8; |
379 | ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); |
380 | addr += 2; |
381 | d += 4; |
382 | } while (--w != 0); |
383 | } |
384 | |
385 | /* |
386 | * 24 bit color |
387 | */ |
388 | static void vga_draw_line24_le(VGACommonState *vga, uint8_t *d, |
389 | uint32_t addr, int width) |
390 | { |
391 | int w; |
392 | uint32_t r, g, b; |
393 | |
394 | w = width; |
395 | do { |
396 | b = vga_read_byte(vga, addr + 0); |
397 | g = vga_read_byte(vga, addr + 1); |
398 | r = vga_read_byte(vga, addr + 2); |
399 | ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); |
400 | addr += 3; |
401 | d += 4; |
402 | } while (--w != 0); |
403 | } |
404 | |
405 | static void vga_draw_line24_be(VGACommonState *vga, uint8_t *d, |
406 | uint32_t addr, int width) |
407 | { |
408 | int w; |
409 | uint32_t r, g, b; |
410 | |
411 | w = width; |
412 | do { |
413 | r = vga_read_byte(vga, addr + 0); |
414 | g = vga_read_byte(vga, addr + 1); |
415 | b = vga_read_byte(vga, addr + 2); |
416 | ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); |
417 | addr += 3; |
418 | d += 4; |
419 | } while (--w != 0); |
420 | } |
421 | |
422 | /* |
423 | * 32 bit color |
424 | */ |
425 | static void vga_draw_line32_le(VGACommonState *vga, uint8_t *d, |
426 | uint32_t addr, int width) |
427 | { |
428 | int w; |
429 | uint32_t r, g, b; |
430 | |
431 | w = width; |
432 | do { |
433 | b = vga_read_byte(vga, addr + 0); |
434 | g = vga_read_byte(vga, addr + 1); |
435 | r = vga_read_byte(vga, addr + 2); |
436 | ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); |
437 | addr += 4; |
438 | d += 4; |
439 | } while (--w != 0); |
440 | } |
441 | |
442 | static void vga_draw_line32_be(VGACommonState *vga, uint8_t *d, |
443 | uint32_t addr, int width) |
444 | { |
445 | int w; |
446 | uint32_t r, g, b; |
447 | |
448 | w = width; |
449 | do { |
450 | r = vga_read_byte(vga, addr + 1); |
451 | g = vga_read_byte(vga, addr + 2); |
452 | b = vga_read_byte(vga, addr + 3); |
453 | ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); |
454 | addr += 4; |
455 | d += 4; |
456 | } while (--w != 0); |
457 | } |
458 | |