vga.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "../port/error.h"
  7. #define Image IMAGE
  8. #include <draw.h>
  9. #include <memdraw.h>
  10. #include <cursor.h>
  11. #include "screen.h"
  12. static Memimage* back;
  13. static Memimage *conscol;
  14. static Point curpos;
  15. static Rectangle window;
  16. static int *xp;
  17. static int xbuf[256];
  18. static Lock vgascreenlock;
  19. int drawdebug;
  20. void
  21. vgaimageinit(ulong chan)
  22. {
  23. if(back == nil){
  24. back = allocmemimage(Rect(0,0,1,1), chan); /* RSC BUG */
  25. if(back == nil)
  26. panic("back alloc"); /* RSC BUG */
  27. back->flags |= Frepl;
  28. back->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF);
  29. memfillcolor(back, DBlack);
  30. }
  31. if(conscol == nil){
  32. conscol = allocmemimage(Rect(0,0,1,1), chan); /* RSC BUG */
  33. if(conscol == nil)
  34. panic("conscol alloc"); /* RSC BUG */
  35. conscol->flags |= Frepl;
  36. conscol->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF);
  37. memfillcolor(conscol, DWhite);
  38. }
  39. }
  40. static void
  41. vgascroll(VGAscr* scr)
  42. {
  43. int h, o;
  44. Point p;
  45. Rectangle r;
  46. h = scr->memdefont->height;
  47. o = 8*h;
  48. r = Rpt(window.min, Pt(window.max.x, window.max.y-o));
  49. p = Pt(window.min.x, window.min.y+o);
  50. memimagedraw(scr->gscreen, r, scr->gscreen, p, nil, p, S);
  51. r = Rpt(Pt(window.min.x, window.max.y-o), window.max);
  52. memimagedraw(scr->gscreen, r, back, ZP, nil, ZP, S);
  53. curpos.y -= o;
  54. }
  55. static void
  56. vgascreenputc(VGAscr* scr, char* buf, Rectangle *flushr)
  57. {
  58. Point p;
  59. int h, w, pos;
  60. Rectangle r;
  61. // drawdebug = 1;
  62. if(xp < xbuf || xp >= &xbuf[sizeof(xbuf)])
  63. xp = xbuf;
  64. h = scr->memdefont->height;
  65. switch(buf[0]){
  66. case '\n':
  67. if(curpos.y+h >= window.max.y){
  68. vgascroll(scr);
  69. *flushr = window;
  70. }
  71. curpos.y += h;
  72. vgascreenputc(scr, "\r", flushr);
  73. break;
  74. case '\r':
  75. xp = xbuf;
  76. curpos.x = window.min.x;
  77. break;
  78. case '\t':
  79. p = memsubfontwidth(scr->memdefont, " ");
  80. w = p.x;
  81. if(curpos.x >= window.max.x-4*w)
  82. vgascreenputc(scr, "\n", flushr);
  83. pos = (curpos.x-window.min.x)/w;
  84. pos = 4-(pos%4);
  85. *xp++ = curpos.x;
  86. r = Rect(curpos.x, curpos.y, curpos.x+pos*w, curpos.y + h);
  87. memimagedraw(scr->gscreen, r, back, back->r.min, nil, back->r.min, S);
  88. curpos.x += pos*w;
  89. break;
  90. case '\b':
  91. if(xp <= xbuf)
  92. break;
  93. xp--;
  94. r = Rect(*xp, curpos.y, curpos.x, curpos.y+h);
  95. memimagedraw(scr->gscreen, r, back, back->r.min, nil, ZP, S);
  96. combinerect(flushr, r);
  97. curpos.x = *xp;
  98. break;
  99. case '\0':
  100. break;
  101. default:
  102. p = memsubfontwidth(scr->memdefont, buf);
  103. w = p.x;
  104. if(curpos.x >= window.max.x-w)
  105. vgascreenputc(scr, "\n", flushr);
  106. *xp++ = curpos.x;
  107. r = Rect(curpos.x, curpos.y, curpos.x+w, curpos.y+h);
  108. memimagedraw(scr->gscreen, r, back, back->r.min, nil, back->r.min, S);
  109. memimagestring(scr->gscreen, curpos, conscol, ZP, scr->memdefont, buf);
  110. combinerect(flushr, r);
  111. curpos.x += w;
  112. }
  113. // drawdebug = 0;
  114. }
  115. static void
  116. vgascreenputs(char* s, int n)
  117. {
  118. int i;
  119. Rune r;
  120. char buf[4];
  121. VGAscr *scr;
  122. Rectangle flushr;
  123. scr = &vgascreen[0];
  124. if(!islo()){
  125. /*
  126. * Don't deadlock trying to
  127. * print in an interrupt.
  128. */
  129. if(!canlock(&vgascreenlock))
  130. return;
  131. }
  132. else
  133. lock(&vgascreenlock);
  134. flushr = Rect(10000, 10000, -10000, -10000);
  135. while(n > 0){
  136. i = chartorune(&r, s);
  137. if(i == 0){
  138. s++;
  139. --n;
  140. continue;
  141. }
  142. memmove(buf, s, i);
  143. buf[i] = 0;
  144. n -= i;
  145. s += i;
  146. vgascreenputc(scr, buf, &flushr);
  147. }
  148. flushmemscreen(flushr);
  149. unlock(&vgascreenlock);
  150. }
  151. void
  152. vgascreenwin(VGAscr* scr)
  153. {
  154. int h, w;
  155. h = scr->memdefont->height;
  156. w = scr->memdefont->info[' '].width;
  157. window = insetrect(scr->gscreen->r, 48);
  158. window.max.x = window.min.x+((window.max.x-window.min.x)/w)*w;
  159. window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h;
  160. curpos = window.min;
  161. screenputs = vgascreenputs;
  162. }
  163. /*
  164. * Supposedly this is the way to turn DPMS
  165. * monitors off using just the VGA registers.
  166. * Unfortunately, it seems to mess up the video mode
  167. * on the cards I've tried.
  168. */
  169. void
  170. vgablank(VGAscr*, int blank)
  171. {
  172. uchar seq1, crtc17;
  173. if(blank) {
  174. seq1 = 0x00;
  175. crtc17 = 0x80;
  176. } else {
  177. seq1 = 0x20;
  178. crtc17 = 0x00;
  179. }
  180. outs(Seqx, 0x0100); /* synchronous reset */
  181. seq1 |= vgaxi(Seqx, 1) & ~0x20;
  182. vgaxo(Seqx, 1, seq1);
  183. crtc17 |= vgaxi(Crtx, 0x17) & ~0x80;
  184. delay(10);
  185. vgaxo(Crtx, 0x17, crtc17);
  186. outs(Crtx, 0x0300); /* end synchronous reset */
  187. }
  188. void
  189. addvgaseg(char *name, ulong pa, ulong size)
  190. {
  191. Physseg seg;
  192. memset(&seg, 0, sizeof seg);
  193. seg.attr = SG_PHYSICAL;
  194. seg.name = name;
  195. seg.pa = pa;
  196. seg.size = size;
  197. addphysseg(&seg);
  198. }
  199. void
  200. cornerstring(char *s)
  201. {
  202. int h, w;
  203. VGAscr *scr;
  204. Rectangle r;
  205. Point p;
  206. scr = &vgascreen[0];
  207. if(scr->aperture == 0 || screenputs != vgascreenputs)
  208. return;
  209. p = memsubfontwidth(scr->memdefont, s);
  210. w = p.x;
  211. h = scr->memdefont->height;
  212. r = Rect(0, 0, w, h);
  213. memimagedraw(scr->gscreen, r, back, back->r.min, nil, back->r.min, S);
  214. memimagestring(scr->gscreen, r.min, conscol, ZP, scr->memdefont, s);
  215. // flushmemscreen(r);
  216. }