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 /* 99 * 4 color mode 100 */ 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 */ 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 */ 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 */ 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 */ 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 if (hpel) { 269 width += 8; 270 d = vga->panning_buf; 271 } 272 width >>= 3; 273 for(x = 0; x < width; x++) { 274 addr &= VGA_VRAM_SIZE - 1; 275 PUT_PIXEL2(d, 0, palette[vga_read_byte(vga, addr + 0)]); 276 PUT_PIXEL2(d, 1, palette[vga_read_byte(vga, addr + 1)]); 277 PUT_PIXEL2(d, 2, palette[vga_read_byte(vga, addr + 2)]); 278 PUT_PIXEL2(d, 3, palette[vga_read_byte(vga, addr + 3)]); 279 d += 32; 280 addr += 4; 281 } 282 return hpel ? vga->panning_buf + 8 * hpel : NULL; 283 } 284 285 /* 286 * standard 256 color mode 287 * 288 * XXX: add plane_mask support (never used in standard VGA modes) 289 */ 290 static void *vga_draw_line8(VGACommonState *vga, uint8_t *d, 291 uint32_t addr, int width, int hpel) 292 { 293 uint32_t *palette; 294 int x; 295 296 palette = vga->last_palette; 297 hpel = (hpel >> 1) & 3; 298 if (hpel) { 299 width += 8; 300 d = vga->panning_buf; 301 } 302 width >>= 3; 303 for(x = 0; x < width; x++) { 304 ((uint32_t *)d)[0] = palette[vga_read_byte(vga, addr + 0)]; 305 ((uint32_t *)d)[1] = palette[vga_read_byte(vga, addr + 1)]; 306 ((uint32_t *)d)[2] = palette[vga_read_byte(vga, addr + 2)]; 307 ((uint32_t *)d)[3] = palette[vga_read_byte(vga, addr + 3)]; 308 ((uint32_t *)d)[4] = palette[vga_read_byte(vga, addr + 4)]; 309 ((uint32_t *)d)[5] = palette[vga_read_byte(vga, addr + 5)]; 310 ((uint32_t *)d)[6] = palette[vga_read_byte(vga, addr + 6)]; 311 ((uint32_t *)d)[7] = palette[vga_read_byte(vga, addr + 7)]; 312 d += 32; 313 addr += 8; 314 } 315 return hpel ? vga->panning_buf + 4 * hpel : NULL; 316 } 317 318 /* 319 * 15 bit color 320 */ 321 static void *vga_draw_line15_le(VGACommonState *vga, uint8_t *d, 322 uint32_t addr, int width, int hpel) 323 { 324 int w; 325 uint32_t v, r, g, b; 326 327 w = width; 328 do { 329 v = vga_read_word_le(vga, addr); 330 r = (v >> 7) & 0xf8; 331 g = (v >> 2) & 0xf8; 332 b = (v << 3) & 0xf8; 333 ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); 334 addr += 2; 335 d += 4; 336 } while (--w != 0); 337 return NULL; 338 } 339 340 static void *vga_draw_line15_be(VGACommonState *vga, uint8_t *d, 341 uint32_t addr, int width, int hpel) 342 { 343 int w; 344 uint32_t v, r, g, b; 345 346 w = width; 347 do { 348 v = vga_read_word_be(vga, addr); 349 r = (v >> 7) & 0xf8; 350 g = (v >> 2) & 0xf8; 351 b = (v << 3) & 0xf8; 352 ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); 353 addr += 2; 354 d += 4; 355 } while (--w != 0); 356 return NULL; 357 } 358 359 /* 360 * 16 bit color 361 */ 362 static void *vga_draw_line16_le(VGACommonState *vga, uint8_t *d, 363 uint32_t addr, int width, int hpel) 364 { 365 int w; 366 uint32_t v, r, g, b; 367 368 w = width; 369 do { 370 v = vga_read_word_le(vga, addr); 371 r = (v >> 8) & 0xf8; 372 g = (v >> 3) & 0xfc; 373 b = (v << 3) & 0xf8; 374 ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); 375 addr += 2; 376 d += 4; 377 } while (--w != 0); 378 return NULL; 379 } 380 381 static void *vga_draw_line16_be(VGACommonState *vga, uint8_t *d, 382 uint32_t addr, int width, int hpel) 383 { 384 int w; 385 uint32_t v, r, g, b; 386 387 w = width; 388 do { 389 v = vga_read_word_be(vga, addr); 390 r = (v >> 8) & 0xf8; 391 g = (v >> 3) & 0xfc; 392 b = (v << 3) & 0xf8; 393 ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); 394 addr += 2; 395 d += 4; 396 } while (--w != 0); 397 return NULL; 398 } 399 400 /* 401 * 24 bit color 402 */ 403 static void *vga_draw_line24_le(VGACommonState *vga, uint8_t *d, 404 uint32_t addr, int width, int hpel) 405 { 406 int w; 407 uint32_t r, g, b; 408 409 w = width; 410 do { 411 b = vga_read_byte(vga, addr + 0); 412 g = vga_read_byte(vga, addr + 1); 413 r = vga_read_byte(vga, addr + 2); 414 ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); 415 addr += 3; 416 d += 4; 417 } while (--w != 0); 418 return NULL; 419 } 420 421 static void *vga_draw_line24_be(VGACommonState *vga, uint8_t *d, 422 uint32_t addr, int width, int hpel) 423 { 424 int w; 425 uint32_t r, g, b; 426 427 w = width; 428 do { 429 r = vga_read_byte(vga, addr + 0); 430 g = vga_read_byte(vga, addr + 1); 431 b = vga_read_byte(vga, addr + 2); 432 ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); 433 addr += 3; 434 d += 4; 435 } while (--w != 0); 436 return NULL; 437 } 438 439 /* 440 * 32 bit color 441 */ 442 static void *vga_draw_line32_le(VGACommonState *vga, uint8_t *d, 443 uint32_t addr, int width, int hpel) 444 { 445 int w; 446 uint32_t r, g, b; 447 448 w = width; 449 do { 450 b = vga_read_byte(vga, addr + 0); 451 g = vga_read_byte(vga, addr + 1); 452 r = vga_read_byte(vga, addr + 2); 453 ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); 454 addr += 4; 455 d += 4; 456 } while (--w != 0); 457 return NULL; 458 } 459 460 static void *vga_draw_line32_be(VGACommonState *vga, uint8_t *d, 461 uint32_t addr, int width, int hpel) 462 { 463 int w; 464 uint32_t r, g, b; 465 466 w = width; 467 do { 468 r = vga_read_byte(vga, addr + 1); 469 g = vga_read_byte(vga, addr + 2); 470 b = vga_read_byte(vga, addr + 3); 471 ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b); 472 addr += 4; 473 d += 4; 474 } while (--w != 0); 475 return NULL; 476 } 477