Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

19 лет назад
19 лет назад
19 лет назад
19 лет назад
19 лет назад
19 лет назад
19 лет назад
19 лет назад
19 лет назад
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /*
  2. * libcaca ASCII-Art library
  3. * Copyright (c) 2002-2006 Sam Hocevar <sam@zoy.org>
  4. * All Rights Reserved
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the Do What The Fuck You Want To
  8. * Public License, Version 2, as published by Sam Hocevar. See
  9. * http://sam.zoy.org/wtfpl/COPYING for more details.
  10. */
  11. /** \file driver_vga.c
  12. * \version \$Id$
  13. * \author Sam Hocevar <sam@zoy.org>
  14. * \brief VGA driver
  15. *
  16. * This file contains the libcaca VGA input and output driver
  17. */
  18. #include "config.h"
  19. #if defined(USE_VGA)
  20. #include "caca.h"
  21. #include "caca_internals.h"
  22. #include "cucul.h"
  23. #include "cucul_internals.h"
  24. static uint8_t vga_utf32_to_cp437(uint32_t);
  25. /* Address of the VGA screen */
  26. #define VGA_SCREEN ((char *)(intptr_t)0x000b8000)
  27. static uint8_t const vga_colors[][4] =
  28. {
  29. /* Colour values range from 0x00 to 0x3f */
  30. { 0, 0x00, 0x00, 0x00 },
  31. { 1, 0x00, 0x00, 0x1f },
  32. { 2, 0x00, 0x1f, 0x00 },
  33. { 3, 0x00, 0x1f, 0x1f },
  34. { 4, 0x1f, 0x00, 0x00 },
  35. { 5, 0x1f, 0x00, 0x1f },
  36. { 0x14, 0x1f, 0x1f, 0x00 },
  37. { 7, 0x1f, 0x1f, 0x1f },
  38. { 0x38, 0x0f, 0x0f, 0x0f },
  39. { 0x39, 0x0f, 0x0f, 0x3f },
  40. { 0x3a, 0x0f, 0x3f, 0x0f },
  41. { 0x3b, 0x0f, 0x3f, 0x3f },
  42. { 0x3c, 0x3f, 0x0f, 0x0f },
  43. { 0x3d, 0x3f, 0x0f, 0x3f },
  44. { 0x3e, 0x3f, 0x3f, 0x0f },
  45. { 0x3f, 0x3f, 0x3f, 0x3f },
  46. };
  47. static int vga_init_graphics(caca_t *kk)
  48. {
  49. int i;
  50. uint8_t tmp;
  51. /* Blank screen */
  52. memset(VGA_SCREEN, 0, 80 * 25 * 2);
  53. /* Fill VGA palette */
  54. for(i = 0; i < 16; i++)
  55. {
  56. outb(vga_colors[i][0], 0x3c8);
  57. outb(vga_colors[i][1], 0x3c9);
  58. outb(vga_colors[i][2], 0x3c9);
  59. outb(vga_colors[i][3], 0x3c9);
  60. }
  61. /* Hide cursor */
  62. outb(0x0a, 0x3d4);
  63. tmp = inb(0x3d5);
  64. tmp |= 0x20;
  65. outb(0x0a, 0x3d4);
  66. outb(tmp, 0x3d5);
  67. /* We don't have much choice */
  68. _cucul_set_size(kk->qq, 80, 25);
  69. return 0;
  70. }
  71. static int vga_end_graphics(caca_t *kk)
  72. {
  73. uint8_t tmp;
  74. /* Show cursor again */
  75. outb(0x0a, 0x3d4);
  76. tmp = inb(0x3d5);
  77. tmp &= 0xdf;
  78. outb(0x0a, 0x3d4);
  79. outb(tmp, 0x3d5);
  80. return 0;
  81. }
  82. static int vga_set_window_title(caca_t *kk, char const *title)
  83. {
  84. /* Unsupported, of course. */
  85. return 0;
  86. }
  87. static unsigned int vga_get_window_width(caca_t *kk)
  88. {
  89. /* Fallback to a 320x200 screen */
  90. return 320;
  91. }
  92. static unsigned int vga_get_window_height(caca_t *kk)
  93. {
  94. /* Fallback to a 320x200 screen */
  95. return 200;
  96. }
  97. static void vga_display(caca_t *kk)
  98. {
  99. char *screen = (char *)(intptr_t)0x000b8000;
  100. uint8_t *attr = kk->qq->attr;
  101. uint32_t *chars = kk->qq->chars;
  102. int n;
  103. for(n = kk->qq->height * kk->qq->width; n--; )
  104. {
  105. *screen++ = vga_utf32_to_cp437(*chars++);
  106. *screen++ = *attr++;
  107. }
  108. }
  109. static void vga_handle_resize(caca_t *kk)
  110. {
  111. /* We know nothing about our window */
  112. kk->resize.w = kk->qq->width;
  113. kk->resize.h = kk->qq->height;
  114. }
  115. static unsigned int vga_get_event(caca_t *kk)
  116. {
  117. /* FIXME */
  118. return CACA_EVENT_NONE;
  119. }
  120. /*
  121. * XXX: following functions are local
  122. */
  123. static uint8_t vga_utf32_to_cp437(uint32_t c)
  124. {
  125. static uint32_t const lookup1[] =
  126. {
  127. /* 0x01 - 0x0f: ☺ ☻ ♥ ♦ ♣ ♠ • ◘ ○ ◙ ♂ ♀ ♪ ♫ ☼ */
  128. 0x263a, 0x263b, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022,
  129. 0x25d8, 0x25cb, 0x25d9, 0x2642, 0x2640, 0x266a, 0x266b, 0x263c,
  130. /* 0x10 - 0x1f: ► ◄ ↕ ‼ ¶ § ▬ ↨ ↑ ↓ → ← ∟ ↔ ▲ ▼ */
  131. 0x25ba, 0x25c4, 0x2195, 0x203c, 0xb6, 0xa7, 0x25ac, 0x21a8,
  132. 0x2191, 0x2193, 0x2192, 0x2190, 0x221f, 0x2194, 0x25b2, 0x25bc
  133. };
  134. static uint32_t const lookup2[] =
  135. {
  136. /* 0x7f: ⌂ */
  137. 0x2302,
  138. /* 0x80 - 0x8f: Ç ü é â ä à å ç ê ë è ï î ì Ä Å */
  139. 0xc7, 0xfc, 0xe9, 0xe2, 0xe4, 0xe0, 0xe5, 0xe7,
  140. 0xea, 0xeb, 0xe8, 0xef, 0xee, 0xec, 0xc4, 0xc5,
  141. /* 0x90 - 0x9f: É æ Æ ô ö ò û ù ÿ Ö Ü ¢ £ ¥ ₧ ƒ */
  142. 0xc9, 0xe6, 0xc6, 0xf4, 0xf6, 0xf2, 0xfb, 0xf9,
  143. 0xff, 0xd6, 0xdc, 0xa2, 0xa3, 0xa5, 0x20a7, 0x192,
  144. /* 0xa0 - 0xaf: á í ó ú ñ Ñ ª º ¿ ⌐ ¬ ½ ¼ ¡ « » */
  145. 0xe1, 0xed, 0xf3, 0xfa, 0xf1, 0xd1, 0xaa, 0xba,
  146. 0xbf, 0x2310, 0xac, 0xbd, 0xbc, 0xa1, 0xab, 0xbb,
  147. /* 0xb0 - 0xbf: ░ ▒ ▓ │ ┤ ╡ ╢ ╖ ╕ ╣ ║ ╗ ╝ ╜ ╛ ┐ */
  148. 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
  149. 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
  150. /* 0xc0 - 0xcf: └ ┴ ┬ ├ ─ ┼ ╞ ╟ ╚ ╔ ╩ ╦ ╠ ═ ╬ ╧ */
  151. 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
  152. 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
  153. /* 0xd0 - 0xdf: ╨ ╤ ╥ ╙ ╘ ╒ ╓ ╫ ╪ ┘ ┌ █ ▄ ▌ ▐ ▀ */
  154. 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
  155. 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
  156. /* 0xe0 - 0xef: α ß Γ π Σ σ µ τ Φ Θ Ω δ ∞ φ ε ∩ */
  157. 0x3b1, 0xdf, 0x393, 0x3c0, 0x3a3, 0x3c3, 0xb5, 0x3c4,
  158. 0x3a6, 0x398, 0x3a9, 0x3b4, 0x221e, 0x3c6, 0x3b5, 0x2229,
  159. /* 0xf0 - 0xff: ≡ ± ≥ ≤ ⌠ ⌡ ÷ ≈ ° ∙ · √ ⁿ ² ■ <nbsp> */
  160. 0x2261, 0xb1, 0x2265, 0x2264, 0x2320, 0x2321, 0xf7, 0x2248,
  161. 0xb0, 0x2219, 0xb7, 0x221a, 0x207f, 0xb2, 0x25a0, 0xa0
  162. };
  163. unsigned int i;
  164. if(c < 0x00000020)
  165. return '?';
  166. if(c < 0x00000080)
  167. return c;
  168. for(i = 0; i < sizeof(lookup1) / sizeof(*lookup1); i++)
  169. if(lookup1[i] == c)
  170. return 0x01 + i;
  171. for(i = 0; i < sizeof(lookup2) / sizeof(*lookup2); i++)
  172. if(lookup2[i] == c)
  173. return 0x7f + i;
  174. return '?';
  175. }
  176. /*
  177. * Driver initialisation
  178. */
  179. void vga_init_driver(caca_t *kk)
  180. {
  181. kk->drv.driver = CACA_DRIVER_VGA;
  182. kk->drv.init_graphics = vga_init_graphics;
  183. kk->drv.end_graphics = vga_end_graphics;
  184. kk->drv.set_window_title = vga_set_window_title;
  185. kk->drv.get_window_width = vga_get_window_width;
  186. kk->drv.get_window_height = vga_get_window_height;
  187. kk->drv.display = vga_display;
  188. kk->drv.handle_resize = vga_handle_resize;
  189. kk->drv.get_event = vga_get_event;
  190. }
  191. #endif /* USE_VGA */