cga.c 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. #include "u.h"
  2. #include "lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. enum {
  7. Width = 160,
  8. Height = 25,
  9. Attr = 7, /* white on black */
  10. };
  11. #define CGASCREENBASE ((uchar*)KADDR(0xB8000))
  12. static int pos;
  13. static int screeninitdone;
  14. static uchar
  15. cgaregr(int index)
  16. {
  17. outb(0x3D4, index);
  18. return inb(0x3D4+1) & 0xFF;
  19. }
  20. static void
  21. cgaregw(int index, int data)
  22. {
  23. outb(0x3D4, index);
  24. outb(0x3D4+1, data);
  25. }
  26. static void
  27. movecursor(void)
  28. {
  29. cgaregw(0x0E, (pos/2>>8) & 0xFF);
  30. cgaregw(0x0F, pos/2 & 0xFF);
  31. CGASCREENBASE[pos+1] = Attr;
  32. }
  33. static void
  34. cgascreenputc(int c)
  35. {
  36. int i;
  37. if(c == '\n'){
  38. pos = pos/Width;
  39. pos = (pos+1)*Width;
  40. }
  41. else if(c == '\t'){
  42. i = 8 - ((pos/2)&7);
  43. while(i-->0)
  44. cgascreenputc(' ');
  45. }
  46. else if(c == '\b'){
  47. if(pos >= 2)
  48. pos -= 2;
  49. cgascreenputc(' ');
  50. pos -= 2;
  51. }
  52. else{
  53. CGASCREENBASE[pos++] = c;
  54. CGASCREENBASE[pos++] = Attr;
  55. }
  56. if(pos >= Width*Height){
  57. memmove(CGASCREENBASE, &CGASCREENBASE[Width], Width*(Height-1));
  58. memset(&CGASCREENBASE[Width*(Height-1)], 0, Width);
  59. pos = Width*(Height-1);
  60. }
  61. movecursor();
  62. }
  63. static void
  64. screeninit(void)
  65. {
  66. if(screeninitdone == 0){
  67. pos = cgaregr(0x0E)<<8;
  68. pos |= cgaregr(0x0F);
  69. pos *= 2;
  70. screeninitdone = 1;
  71. }
  72. }
  73. void
  74. cgascreenputs(char* s, int n)
  75. {
  76. if(screeninitdone == 0)
  77. screeninit();
  78. while(n-- > 0)
  79. cgascreenputc(*s++);
  80. }