vgatvp3020.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  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. /*
  14. * TVP3020 Viewpoint Video Interface Pallette.
  15. * Assumes hooked up to an S3 86C928.
  16. */
  17. enum {
  18. Index = 0x06, /* Index register */
  19. Data = 0x07, /* Data register */
  20. };
  21. /*
  22. * Lower 2-bits of indirect DAC register
  23. * addressing.
  24. */
  25. static ushort dacxreg[4] = {
  26. PaddrW, Pdata, Pixmask, PaddrR
  27. };
  28. static uchar
  29. tvp3020io(uchar reg, uchar data)
  30. {
  31. uchar crt55;
  32. crt55 = vgaxi(Crtx, 0x55) & 0xFC;
  33. vgaxo(Crtx, 0x55, crt55|((reg>>2) & 0x03));
  34. vgao(dacxreg[reg & 0x03], data);
  35. return crt55;
  36. }
  37. static void
  38. tvp3020xo(uchar index, uchar data)
  39. {
  40. uchar crt55;
  41. crt55 = tvp3020io(Index, index);
  42. vgao(dacxreg[Data & 0x03], data);
  43. vgaxo(Crtx, 0x55, crt55);
  44. }
  45. static void
  46. tvp3020disable(VGAscr*)
  47. {
  48. uchar r;
  49. /*
  50. * Disable
  51. * cursor;
  52. * cursor control enable for Bt485 DAC (!);
  53. * the hardware cursor external operation mode.
  54. */
  55. tvp3020xo(0x06, 0x10); /* Cursor Control Register */
  56. r = vgaxi(Crtx, 0x45) & ~0x20;
  57. vgaxo(Crtx, 0x45, r);
  58. r = vgaxi(Crtx, 0x55) & ~0x20;
  59. vgaxo(Crtx, 0x55, r);
  60. }
  61. static void
  62. tvp3020enable(VGAscr*)
  63. {
  64. uchar r;
  65. /*
  66. * Make sure cursor is off by initialising the cursor
  67. * control to defaults + X-Windows cursor mode.
  68. */
  69. tvp3020xo(0x06, 0x10); /* Cursor Control Register */
  70. /*
  71. * Overscan colour,
  72. * cursor colour 1 (white),
  73. * cursor colour 2 (black).
  74. */
  75. tvp3020xo(0x20, Pwhite); tvp3020xo(0x21, Pwhite); tvp3020xo(0x22, Pwhite);
  76. tvp3020xo(0x23, Pwhite); tvp3020xo(0x24, Pwhite); tvp3020xo(0x25, Pwhite);
  77. tvp3020xo(0x26, Pblack); tvp3020xo(0x27, Pblack); tvp3020xo(0x28, Pblack);
  78. /*
  79. * Finally, enable
  80. * the hardware cursor external operation mode;
  81. * cursor control enable for Bt485 DAC (!).
  82. */
  83. r = vgaxi(Crtx, 0x55)|0x20;
  84. vgaxo(Crtx, 0x55, r);
  85. r = vgaxi(Crtx, 0x45)|0x20;
  86. vgaxo(Crtx, 0x45, r);
  87. }
  88. static void
  89. tvp3020load(VGAscr*, Cursor* curs)
  90. {
  91. uchar p, p0, p1;
  92. int x, y;
  93. /*
  94. * Make sure cursor is off by initialising the cursor
  95. * control to defaults + X-Windows cursor mode.
  96. */
  97. tvp3020xo(0x06, 0x10); /* Cursor Control Register */
  98. /*
  99. * Initialise the cursor RAM LS and MS address
  100. * (LS must be first).
  101. */
  102. tvp3020xo(0x08, 0x00); /* Cursor RAM LS Address */
  103. tvp3020xo(0x09, 0x00); /* Cursor RAM MS Address */
  104. /*
  105. * Initialise the 64x64 cursor RAM array. There are 2 planes,
  106. * p0 and p1. Data is written 4 pixels per byte, with p1 the
  107. * MS bit of each pixel.
  108. * The cursor is set in X-Windows mode which gives the following
  109. * truth table:
  110. * p1 p0 colour
  111. * 0 0 underlying pixel colour
  112. * 0 1 underlying pixel colour
  113. * 1 0 cursor colour 1
  114. * 1 1 cursor colour 2
  115. * Put the cursor into the top-left of the 64x64 array.
  116. */
  117. for(y = 0; y < 64; y++){
  118. for(x = 0; x < 64/8; x++){
  119. if(x < 16/8 && y < 16){
  120. p0 = curs->clr[x+y*2];
  121. p1 = curs->set[x+y*2];
  122. p = 0x00;
  123. if(p1 & 0x10)
  124. p |= 0x03;
  125. else if(p0 & 0x10)
  126. p |= 0x02;
  127. if(p1 & 0x20)
  128. p |= 0x0C;
  129. else if(p0 & 0x20)
  130. p |= 0x08;
  131. if(p1 & 0x40)
  132. p |= 0x30;
  133. else if(p0 & 0x40)
  134. p |= 0x20;
  135. if(p1 & 0x80)
  136. p |= 0xC0;
  137. else if(p0 & 0x80)
  138. p |= 0x80;
  139. tvp3020xo(0x0A, p); /* Cursor RAM Data */
  140. p = 0x00;
  141. if(p1 & 0x01)
  142. p |= 0x03;
  143. else if(p0 & 0x01)
  144. p |= 0x02;
  145. if(p1 & 0x02)
  146. p |= 0x0C;
  147. else if(p0 & 0x02)
  148. p |= 0x08;
  149. if(p1 & 0x04)
  150. p |= 0x30;
  151. else if(p0 & 0x04)
  152. p |= 0x20;
  153. if(p1 & 0x08)
  154. p |= 0xC0;
  155. else if(p0 & 0x08)
  156. p |= 0x80;
  157. tvp3020xo(0x0A, p); /* Cursor RAM Data */
  158. }
  159. else{
  160. tvp3020xo(0x0A, 0x00); /* Cursor RAM Data */
  161. tvp3020xo(0x0A, 0x00);
  162. }
  163. }
  164. }
  165. /*
  166. * Initialise the cursor hotpoint
  167. * and enable the cursor.
  168. */
  169. tvp3020xo(0x04, -curs->offset.x); /* Sprite Origin X */
  170. tvp3020xo(0x05, -curs->offset.y); /* Sprite Origin Y */
  171. tvp3020xo(0x06, 0x40|0x10); /* Cursor Control Register */
  172. }
  173. static int
  174. tvp3020move(VGAscr*, Point p)
  175. {
  176. tvp3020xo(0x00, p.x & 0xFF); /* Cursor Position X LSB */
  177. tvp3020xo(0x01, (p.x>>8) & 0x0F); /* Cursor Position X MSB */
  178. tvp3020xo(0x02, p.y & 0xFF); /* Cursor Position Y LSB */
  179. tvp3020xo(0x03, (p.y>>8) & 0x0F); /* Cursor Position Y MSB */
  180. return 0;
  181. }
  182. VGAcur vgatvp3020cur = {
  183. "tvp3020hwgc",
  184. tvp3020enable,
  185. tvp3020disable,
  186. tvp3020load,
  187. tvp3020move,
  188. };