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