vga.c 5.0 KB

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