vga-helpers.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  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. static inline void vga_draw_glyph_line(uint8_t *d, uint32_t font_data,
  25. uint32_t xorcol, uint32_t bgcol)
  26. {
  27. ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;
  28. ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;
  29. ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol;
  30. ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol;
  31. ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol;
  32. ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol;
  33. ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol;
  34. ((uint32_t *)d)[7] = (-((font_data >> 0) & 1) & xorcol) ^ bgcol;
  35. }
  36. static void vga_draw_glyph8(uint8_t *d, int linesize,
  37. const uint8_t *font_ptr, int h,
  38. uint32_t fgcol, uint32_t bgcol)
  39. {
  40. uint32_t font_data, xorcol;
  41. xorcol = bgcol ^ fgcol;
  42. do {
  43. font_data = font_ptr[0];
  44. vga_draw_glyph_line(d, font_data, xorcol, bgcol);
  45. font_ptr += 4;
  46. d += linesize;
  47. } while (--h);
  48. }
  49. static void vga_draw_glyph16(uint8_t *d, int linesize,
  50. const uint8_t *font_ptr, int h,
  51. uint32_t fgcol, uint32_t bgcol)
  52. {
  53. uint32_t font_data, xorcol;
  54. xorcol = bgcol ^ fgcol;
  55. do {
  56. font_data = font_ptr[0];
  57. vga_draw_glyph_line(d, expand4to8[font_data >> 4],
  58. xorcol, bgcol);
  59. vga_draw_glyph_line(d + 32, expand4to8[font_data & 0x0f],
  60. xorcol, bgcol);
  61. font_ptr += 4;
  62. d += linesize;
  63. } while (--h);
  64. }
  65. static void vga_draw_glyph9(uint8_t *d, int linesize,
  66. const uint8_t *font_ptr, int h,
  67. uint32_t fgcol, uint32_t bgcol, int dup9)
  68. {
  69. uint32_t font_data, xorcol, v;
  70. xorcol = bgcol ^ fgcol;
  71. do {
  72. font_data = font_ptr[0];
  73. ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;
  74. ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;
  75. ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol;
  76. ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol;
  77. ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol;
  78. ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol;
  79. ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol;
  80. v = (-((font_data >> 0) & 1) & xorcol) ^ bgcol;
  81. ((uint32_t *)d)[7] = v;
  82. if (dup9)
  83. ((uint32_t *)d)[8] = v;
  84. else
  85. ((uint32_t *)d)[8] = bgcol;
  86. font_ptr += 4;
  87. d += linesize;
  88. } while (--h);
  89. }
  90. /*
  91. * 4 color mode
  92. */
  93. static void *vga_draw_line2(VGACommonState *vga, uint8_t *d,
  94. uint32_t addr, int width, int hpel)
  95. {
  96. uint32_t plane_mask, *palette, data, v;
  97. int x;
  98. palette = vga->last_palette;
  99. plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
  100. hpel &= 7;
  101. if (hpel) {
  102. width += 8;
  103. d = vga->panning_buf;
  104. }
  105. width >>= 3;
  106. for(x = 0; x < width; x++) {
  107. data = vga_read_dword_le(vga, addr & (VGA_VRAM_SIZE - 1));
  108. data &= plane_mask;
  109. v = expand2[GET_PLANE(data, 0)];
  110. v |= expand2[GET_PLANE(data, 2)] << 2;
  111. ((uint32_t *)d)[0] = palette[v >> 12];
  112. ((uint32_t *)d)[1] = palette[(v >> 8) & 0xf];
  113. ((uint32_t *)d)[2] = palette[(v >> 4) & 0xf];
  114. ((uint32_t *)d)[3] = palette[(v >> 0) & 0xf];
  115. v = expand2[GET_PLANE(data, 1)];
  116. v |= expand2[GET_PLANE(data, 3)] << 2;
  117. ((uint32_t *)d)[4] = palette[v >> 12];
  118. ((uint32_t *)d)[5] = palette[(v >> 8) & 0xf];
  119. ((uint32_t *)d)[6] = palette[(v >> 4) & 0xf];
  120. ((uint32_t *)d)[7] = palette[(v >> 0) & 0xf];
  121. d += 32;
  122. addr += 4;
  123. }
  124. return hpel ? vga->panning_buf + 4 * hpel : NULL;
  125. }
  126. #define PUT_PIXEL2(d, n, v) \
  127. ((uint32_t *)d)[2*(n)] = ((uint32_t *)d)[2*(n)+1] = (v)
  128. /*
  129. * 4 color mode, dup2 horizontal
  130. */
  131. static void *vga_draw_line2d2(VGACommonState *vga, uint8_t *d,
  132. uint32_t addr, int width, int hpel)
  133. {
  134. uint32_t plane_mask, *palette, data, v;
  135. int x;
  136. palette = vga->last_palette;
  137. plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
  138. hpel &= 7;
  139. if (hpel) {
  140. width += 8;
  141. d = vga->panning_buf;
  142. }
  143. width >>= 3;
  144. for(x = 0; x < width; x++) {
  145. data = vga_read_dword_le(vga, addr & (VGA_VRAM_SIZE - 1));
  146. data &= plane_mask;
  147. v = expand2[GET_PLANE(data, 0)];
  148. v |= expand2[GET_PLANE(data, 2)] << 2;
  149. PUT_PIXEL2(d, 0, palette[v >> 12]);
  150. PUT_PIXEL2(d, 1, palette[(v >> 8) & 0xf]);
  151. PUT_PIXEL2(d, 2, palette[(v >> 4) & 0xf]);
  152. PUT_PIXEL2(d, 3, palette[(v >> 0) & 0xf]);
  153. v = expand2[GET_PLANE(data, 1)];
  154. v |= expand2[GET_PLANE(data, 3)] << 2;
  155. PUT_PIXEL2(d, 4, palette[v >> 12]);
  156. PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]);
  157. PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]);
  158. PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]);
  159. d += 64;
  160. addr += 4;
  161. }
  162. return hpel ? vga->panning_buf + 8 * hpel : NULL;
  163. }
  164. /*
  165. * 16 color mode
  166. */
  167. static void *vga_draw_line4(VGACommonState *vga, uint8_t *d,
  168. uint32_t addr, int width, int hpel)
  169. {
  170. uint32_t plane_mask, data, v, *palette;
  171. int x;
  172. palette = vga->last_palette;
  173. plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
  174. hpel &= 7;
  175. if (hpel) {
  176. width += 8;
  177. d = vga->panning_buf;
  178. }
  179. width >>= 3;
  180. for(x = 0; x < width; x++) {
  181. data = vga_read_dword_le(vga, addr & (VGA_VRAM_SIZE - 1));
  182. data &= plane_mask;
  183. v = expand4[GET_PLANE(data, 0)];
  184. v |= expand4[GET_PLANE(data, 1)] << 1;
  185. v |= expand4[GET_PLANE(data, 2)] << 2;
  186. v |= expand4[GET_PLANE(data, 3)] << 3;
  187. ((uint32_t *)d)[0] = palette[v >> 28];
  188. ((uint32_t *)d)[1] = palette[(v >> 24) & 0xf];
  189. ((uint32_t *)d)[2] = palette[(v >> 20) & 0xf];
  190. ((uint32_t *)d)[3] = palette[(v >> 16) & 0xf];
  191. ((uint32_t *)d)[4] = palette[(v >> 12) & 0xf];
  192. ((uint32_t *)d)[5] = palette[(v >> 8) & 0xf];
  193. ((uint32_t *)d)[6] = palette[(v >> 4) & 0xf];
  194. ((uint32_t *)d)[7] = palette[(v >> 0) & 0xf];
  195. d += 32;
  196. addr += 4;
  197. }
  198. return hpel ? vga->panning_buf + 4 * hpel : NULL;
  199. }
  200. /*
  201. * 16 color mode, dup2 horizontal
  202. */
  203. static void *vga_draw_line4d2(VGACommonState *vga, uint8_t *d,
  204. uint32_t addr, int width, int hpel)
  205. {
  206. uint32_t plane_mask, data, v, *palette;
  207. int x;
  208. palette = vga->last_palette;
  209. plane_mask = mask16[vga->ar[VGA_ATC_PLANE_ENABLE] & 0xf];
  210. hpel &= 7;
  211. if (hpel) {
  212. width += 8;
  213. d = vga->panning_buf;
  214. }
  215. width >>= 3;
  216. for(x = 0; x < width; x++) {
  217. data = vga_read_dword_le(vga, addr & (VGA_VRAM_SIZE - 1));
  218. data &= plane_mask;
  219. v = expand4[GET_PLANE(data, 0)];
  220. v |= expand4[GET_PLANE(data, 1)] << 1;
  221. v |= expand4[GET_PLANE(data, 2)] << 2;
  222. v |= expand4[GET_PLANE(data, 3)] << 3;
  223. PUT_PIXEL2(d, 0, palette[v >> 28]);
  224. PUT_PIXEL2(d, 1, palette[(v >> 24) & 0xf]);
  225. PUT_PIXEL2(d, 2, palette[(v >> 20) & 0xf]);
  226. PUT_PIXEL2(d, 3, palette[(v >> 16) & 0xf]);
  227. PUT_PIXEL2(d, 4, palette[(v >> 12) & 0xf]);
  228. PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]);
  229. PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]);
  230. PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]);
  231. d += 64;
  232. addr += 4;
  233. }
  234. return hpel ? vga->panning_buf + 8 * hpel : NULL;
  235. }
  236. /*
  237. * 256 color mode, double pixels
  238. *
  239. * XXX: add plane_mask support (never used in standard VGA modes)
  240. */
  241. static void *vga_draw_line8d2(VGACommonState *vga, uint8_t *d,
  242. uint32_t addr, int width, int hpel)
  243. {
  244. uint32_t *palette;
  245. int x;
  246. palette = vga->last_palette;
  247. hpel = (hpel >> 1) & 3;
  248. /* For 256 color modes, we can adjust the source address and write directly
  249. * to the destination, even if horizontal pel panning is active. However,
  250. * the loop below assumes that the address does not wrap in the middle of a
  251. * plane. If that happens...
  252. */
  253. if (addr + (width >> 3) * 4 < VGA_VRAM_SIZE) {
  254. addr += hpel * 4;
  255. hpel = 0;
  256. }
  257. /* ... use the panning buffer as in planar modes. */
  258. if (hpel) {
  259. width += 8;
  260. d = vga->panning_buf;
  261. }
  262. width >>= 3;
  263. for(x = 0; x < width; x++) {
  264. addr &= VGA_VRAM_SIZE - 1;
  265. PUT_PIXEL2(d, 0, palette[vga_read_byte(vga, addr + 0)]);
  266. PUT_PIXEL2(d, 1, palette[vga_read_byte(vga, addr + 1)]);
  267. PUT_PIXEL2(d, 2, palette[vga_read_byte(vga, addr + 2)]);
  268. PUT_PIXEL2(d, 3, palette[vga_read_byte(vga, addr + 3)]);
  269. d += 32;
  270. addr += 4;
  271. }
  272. return hpel ? vga->panning_buf + 8 * hpel : NULL;
  273. }
  274. /*
  275. * standard 256 color mode
  276. *
  277. * XXX: add plane_mask support (never used in standard VGA modes)
  278. */
  279. static void *vga_draw_line8(VGACommonState *vga, uint8_t *d,
  280. uint32_t addr, int width, int hpel)
  281. {
  282. uint32_t *palette;
  283. int x;
  284. palette = vga->last_palette;
  285. hpel = (hpel >> 1) & 3;
  286. if (hpel) {
  287. width += 8;
  288. d = vga->panning_buf;
  289. }
  290. width >>= 3;
  291. for(x = 0; x < width; x++) {
  292. ((uint32_t *)d)[0] = palette[vga_read_byte(vga, addr + 0)];
  293. ((uint32_t *)d)[1] = palette[vga_read_byte(vga, addr + 1)];
  294. ((uint32_t *)d)[2] = palette[vga_read_byte(vga, addr + 2)];
  295. ((uint32_t *)d)[3] = palette[vga_read_byte(vga, addr + 3)];
  296. ((uint32_t *)d)[4] = palette[vga_read_byte(vga, addr + 4)];
  297. ((uint32_t *)d)[5] = palette[vga_read_byte(vga, addr + 5)];
  298. ((uint32_t *)d)[6] = palette[vga_read_byte(vga, addr + 6)];
  299. ((uint32_t *)d)[7] = palette[vga_read_byte(vga, addr + 7)];
  300. d += 32;
  301. addr += 8;
  302. }
  303. return hpel ? vga->panning_buf + 4 * hpel : NULL;
  304. }
  305. /*
  306. * 15 bit color
  307. */
  308. static void *vga_draw_line15_le(VGACommonState *vga, uint8_t *d,
  309. uint32_t addr, int width, int hpel)
  310. {
  311. int w;
  312. uint32_t v, r, g, b;
  313. w = width;
  314. do {
  315. v = vga_read_word_le(vga, addr);
  316. r = (v >> 7) & 0xf8;
  317. g = (v >> 2) & 0xf8;
  318. b = (v << 3) & 0xf8;
  319. ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
  320. addr += 2;
  321. d += 4;
  322. } while (--w != 0);
  323. return NULL;
  324. }
  325. static void *vga_draw_line15_be(VGACommonState *vga, uint8_t *d,
  326. uint32_t addr, int width, int hpel)
  327. {
  328. int w;
  329. uint32_t v, r, g, b;
  330. w = width;
  331. do {
  332. v = vga_read_word_be(vga, addr);
  333. r = (v >> 7) & 0xf8;
  334. g = (v >> 2) & 0xf8;
  335. b = (v << 3) & 0xf8;
  336. ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
  337. addr += 2;
  338. d += 4;
  339. } while (--w != 0);
  340. return NULL;
  341. }
  342. /*
  343. * 16 bit color
  344. */
  345. static void *vga_draw_line16_le(VGACommonState *vga, uint8_t *d,
  346. uint32_t addr, int width, int hpel)
  347. {
  348. int w;
  349. uint32_t v, r, g, b;
  350. w = width;
  351. do {
  352. v = vga_read_word_le(vga, addr);
  353. r = (v >> 8) & 0xf8;
  354. g = (v >> 3) & 0xfc;
  355. b = (v << 3) & 0xf8;
  356. ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
  357. addr += 2;
  358. d += 4;
  359. } while (--w != 0);
  360. return NULL;
  361. }
  362. static void *vga_draw_line16_be(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. w = width;
  368. do {
  369. v = vga_read_word_be(vga, addr);
  370. r = (v >> 8) & 0xf8;
  371. g = (v >> 3) & 0xfc;
  372. b = (v << 3) & 0xf8;
  373. ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
  374. addr += 2;
  375. d += 4;
  376. } while (--w != 0);
  377. return NULL;
  378. }
  379. /*
  380. * 24 bit color
  381. */
  382. static void *vga_draw_line24_le(VGACommonState *vga, uint8_t *d,
  383. uint32_t addr, int width, int hpel)
  384. {
  385. int w;
  386. uint32_t r, g, b;
  387. w = width;
  388. do {
  389. b = vga_read_byte(vga, addr + 0);
  390. g = vga_read_byte(vga, addr + 1);
  391. r = vga_read_byte(vga, addr + 2);
  392. ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
  393. addr += 3;
  394. d += 4;
  395. } while (--w != 0);
  396. return NULL;
  397. }
  398. static void *vga_draw_line24_be(VGACommonState *vga, uint8_t *d,
  399. uint32_t addr, int width, int hpel)
  400. {
  401. int w;
  402. uint32_t r, g, b;
  403. w = width;
  404. do {
  405. r = vga_read_byte(vga, addr + 0);
  406. g = vga_read_byte(vga, addr + 1);
  407. b = vga_read_byte(vga, addr + 2);
  408. ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
  409. addr += 3;
  410. d += 4;
  411. } while (--w != 0);
  412. return NULL;
  413. }
  414. /*
  415. * 32 bit color
  416. */
  417. static void *vga_draw_line32_le(VGACommonState *vga, uint8_t *d,
  418. uint32_t addr, int width, int hpel)
  419. {
  420. int w;
  421. uint32_t r, g, b;
  422. w = width;
  423. do {
  424. b = vga_read_byte(vga, addr + 0);
  425. g = vga_read_byte(vga, addr + 1);
  426. r = vga_read_byte(vga, addr + 2);
  427. ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
  428. addr += 4;
  429. d += 4;
  430. } while (--w != 0);
  431. return NULL;
  432. }
  433. static void *vga_draw_line32_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. w = width;
  439. do {
  440. r = vga_read_byte(vga, addr + 1);
  441. g = vga_read_byte(vga, addr + 2);
  442. b = vga_read_byte(vga, addr + 3);
  443. ((uint32_t *)d)[0] = rgb_to_pixel32(r, g, b);
  444. addr += 4;
  445. d += 4;
  446. } while (--w != 0);
  447. return NULL;
  448. }