@@ 9,7 9,11 @@
#include "screen.h"
#include "vga.h"
+extern Bitmap gscreen;
+extern Cursor curcursor;
+
static Lock clgd542xlock;
+static ulong storage;
static void
clgd542xpage(int page)
@@ 19,6 23,205 @@ clgd542xpage(int page)
unlock(&clgd542xlock);
}
+static void
+disable(void)
+{
+ uchar sr12;
+
+ lock(&clgd542xlock);
+ sr12 = vgaxi(Seqx, 0x12);
+ vgaxo(Seqx, 0x12, sr12 & ~0x01);
+ unlock(&clgd542xlock);
+}
+
+static void
+enable(void)
+{
+ uchar sr12;
+
+ /*
+ * Disable the cursor.
+ */
+ lock(&clgd542xlock);
+ sr12 = vgaxi(Seqx, 0x12);
+ vgaxo(Seqx, 0x12, sr12 & ~0x01);
+
+ /*
+ * Cursor colours.
+ */
+ vgaxo(Seqx, 0x12, sr12|0x02);
+ setcolor(0x00, Pwhite<<(32-6), Pwhite<<(32-6), Pwhite<<(32-6));
+ setcolor(0x0F, Pblack<<(32-6), Pblack<<(32-6), Pblack<<(32-6));
+ vgaxo(Seqx, 0x12, sr12);
+
+ /*
+ * Memory size. The BIOS leaves this in Seq0A, bits 4 and 3.
+ * See Technical Reference Manual Appendix E1, Section 1.3.2.
+ *
+ * The storage area for the 64x64 cursors is the last 16Kb of
+ * display memory.
+ */
+ switch((vgaxi(Seqx, 0x0A)>>3) & 0x03){
+
+ case 0:
+ storage = (256-16)*1024;
+ break;
+
+ case 1:
+ storage = (512-16)*1024;
+ break;
+
+ case 2:
+ storage = (1024-16)*1024;
+ break;
+
+ case 3:
+ storage = (2048-16)*1024;
+ break;
+ }
+
+ /*
+ * Set the current cursor to index 0
+ * and turn the 64x64 cursor on.
+ */
+ vgaxo(Seqx, 0x13, 0);
+ vgaxo(Seqx, 0x12, sr12|0x05);
+
+ unlock(&clgd542xlock);
+}
+
+static void
+initcursor(Cursor* c, int xo, int yo, int index)
+{
+ uchar *p;
+ uint p0, p1;
+ int x, y;
+
+ /*
+ * Is linear addressing turned on? This will determine
+ * how we access the cursor storage.
+ */
+ if(vgaxi(Seqx, 0x07) & 0xF0)
+ p = ((uchar*)gscreen.base) + storage;
+ else {
+ vgaxo(Grx, 0x09, (storage>>16)<<4);
+ p = ((uchar*)gscreen.base) + (storage & 0xFFFF);
+ }
+ p += index*1024;
+
+ for(y = yo; y < 16; y++){
+ p0 = c->clr[2*y];
+ p1 = c->clr[2*y+1];
+ if(xo){
+ p0 = (p0<<xo)|(p1>>(8-xo));
+ p1 <<= xo;
+ }
+ *p++ = p0;
+ *p++ = p1;
+
+ for(x = 16; x < 64; x += 8)
+ *p++ = 0x00;
+
+ p0 = c->clr[2*y]|c->set[2*y];
+ p1 = c->clr[2*y+1]|c->set[2*y+1];
+ if(xo){
+ p0 = (p0<<xo)|(p1>>(8-xo));
+ p1 <<= xo;
+ }
+ *p++ = p0;
+ *p++ = p1;
+
+ for(x = 16; x < 64; x += 8)
+ *p++ = 0x00;
+ }
+ while(y < 64+yo){
+ for(x = 0; x < 64; x += 8){
+ *p++ = 0x00;
+ *p++ = 0x00;
+ }
+ y++;
+ }
+}
+
+static void
+load(Cursor* c)
+{
+ uchar sr12;
+
+ /*
+ * Lock the display memory so we can update the
+ * cursor bitmap if necessary.
+ * Disable the cursor.
+ * If it's the same as the last cursor loaded,
+ * just make sure it's enabled and index 0.
+ */
+ lock(&clgd542xlock);
+ sr12 = vgaxi(Seqx, 0x12);
+ vgaxo(Seqx, 0x12, sr12 & ~0x01);
+
+ if(memcmp(c, &curcursor, sizeof(Cursor)) == 0){
+ vgaxo(Seqx, 0x13, 0);
+ vgaxo(Seqx, 0x12, sr12|0x05);
+ unlock(&clgd542xlock);
+ return;
+ }
+ memmove(&curcursor, c, sizeof(Cursor));
+ initcursor(c, 0, 0, 0);
+
+ /*
+ * Enable the cursor.
+ */
+ vgaxo(Seqx, 0x13, 0);
+ vgaxo(Seqx, 0x12, sr12|0x05);
+
+ unlock(&clgd542xlock);
+}
+
+static int
+move(Point p)
+{
+ int index, x, xo, y, yo;
+
+ if(canlock(&clgd542xlock) == 0)
+ return 1;
+
+ index = 0;
+ if((x = p.x+curcursor.offset.x) < 0){
+ xo = -x;
+ x = 0;
+ }
+ else
+ xo = 0;
+ if((y = p.y+curcursor.offset.y) < 0){
+ yo = -y;
+ y = 0;
+ }
+ else
+ yo = 0;
+
+ if(xo || yo){
+ initcursor(&curcursor, xo, yo, 1);
+ index = 1;
+ }
+ vgaxo(Seqx, 0x13, index<<2);
+
+ vgaxo(Seqx, 0x10|((x & 0x07)<<5), (x>>3) & 0xFF);
+ vgaxo(Seqx, 0x11|((y & 0x07)<<5), (y>>3) & 0xFF);
+
+ unlock(&clgd542xlock);
+ return 0;
+}
+
+static Hwgc clgd542xhwgc = {
+ "clgd542xhwgc",
+ enable,
+ load,
+ move,
+ disable,
+
+ 0,
+};
+
static Vgac clgd542x = {
"clgd542x",
clgd542xpage,
@@ 30,4 233,5 @@ void
vgaclgd542xlink(void)
{
addvgaclink(&clgd542x);
+ addhwgclink(&clgd542xhwgc);
}