VESA cursor now works, TODO: Allow setting of colour
[tpg/acess2.git] / Modules / Display / VESA / main.c
index 43b7147..703e708 100644 (file)
@@ -16,6 +16,7 @@
 // === CONSTANTS ===\r
 #define        FLAG_LFB        0x1\r
 #define VESA_DEFAULT_FRAMEBUFFER       (KERNEL_BASE|0xA0000)\r
+#define VESA_CURSOR_PERIOD     1000\r
 \r
 // === PROTOTYPES ===\r
  int   Vesa_Install(char **Arguments);\r
@@ -25,6 +26,7 @@ Uint64        Vesa_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
  int   Vesa_Int_SetMode(int Mode);\r
  int   Vesa_Int_FindMode(tVideo_IOCtl_Mode *data);\r
  int   Vesa_Int_ModeInfo(tVideo_IOCtl_Mode *data);\r
+void   Vesa_FlipCursor(void *Arg);\r
 // --- 2D Acceleration Functions --\r
 void   Vesa_2D_Fill(void *Ent, Uint16 X, Uint16 Y, Uint16 W, Uint16 H, Uint32 Colour);\r
 void   Vesa_2D_Blit(void *Ent, Uint16 DstX, Uint16 DstY, Uint16 SrcX, Uint16 SrcY, Uint16 W, Uint16 H);\r
@@ -41,20 +43,27 @@ tDevFS_Driver       gVesa_DriverStruct = {
 };\r
 tSpinlock      glVesa_Lock;\r
 tVM8086        *gpVesa_BiosState;\r
+ int   giVesaDriverId = -1;\r
+// --- Video Modes ---\r
  int   giVesaCurrentMode = 0;\r
  int   giVesaCurrentFormat = VIDEO_BUFFMT_TEXT;\r
- int   giVesaDriverId = -1;\r
-char   *gpVesa_Framebuffer = (void*)VESA_DEFAULT_FRAMEBUFFER;\r
 tVesa_Mode     *gVesa_Modes;\r
  int   giVesaModeCount = 0;\r
- int   giVesaPageCount = 0;\r
+// --- Framebuffer ---\r
+char   *gpVesa_Framebuffer = (void*)VESA_DEFAULT_FRAMEBUFFER;\r
+ int   giVesaPageCount = 0;    //!< Framebuffer size in pages\r
+// --- Cursor Control ---\r
+ int   giVesaCursorX = -1;\r
+ int   giVesaCursorY = -1;\r
+ int   giVesaCursorTimer = -1; // Invalid timer\r
+// --- 2D Video Stream Handlers ---\r
 tDrvUtil_Video_2DHandlers      gVesa_2DFunctions = {\r
        NULL,\r
        Vesa_2D_Fill,\r
        Vesa_2D_Blit\r
 };\r
 \r
-//CODE\r
+// === CODE ===\r
 int Vesa_Install(char **Arguments)\r
 {\r
        tVesa_CallInfo  *info;\r
@@ -240,7 +249,7 @@ Uint64 Vesa_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
                        );\r
                \r
                // Sanity Check\r
-               if(y > heightInChars) {\r
+               if(y >= heightInChars) {\r
                        LEAVE('i', 0);\r
                        return 0;\r
                }\r
@@ -348,6 +357,22 @@ int Vesa_Ioctl(tVFS_Node *Node, int ID, void *Data)
                return ret;\r
        \r
        case VIDEO_IOCTL_SETCURSOR:     // Set cursor position\r
+               giVesaCursorX = ((tVideo_IOCtl_Pos*)Data)->x;\r
+               giVesaCursorY = ((tVideo_IOCtl_Pos*)Data)->y;\r
+               if(\r
+                       giVesaCursorX < 0 || giVesaCursorY < 0\r
+               ||      giVesaCursorX >= gVesa_Modes[giVesaCurrentMode].width\r
+               ||      giVesaCursorY >= gVesa_Modes[giVesaCurrentMode].height)\r
+               {\r
+                       if(giVesaCursorTimer != -1)\r
+                               Time_RemoveTimer(giVesaCursorTimer);\r
+                       giVesaCursorX = -1;\r
+                       giVesaCursorY = -1;\r
+               }\r
+               else {\r
+                       if(giVesaCursorTimer == -1)\r
+                               giVesaCursorTimer = Time_CreateTimer(VESA_CURSOR_PERIOD, Vesa_FlipCursor, Node);\r
+               }\r
                return 0;\r
        \r
        case VIDEO_IOCTL_REQLFB:        // Request Linear Framebuffer\r
@@ -356,6 +381,9 @@ int Vesa_Ioctl(tVFS_Node *Node, int ID, void *Data)
        return 0;\r
 }\r
 \r
+/**\r
+ * \brief Updates the video mode\r
+ */\r
 int Vesa_Int_SetMode(int mode)\r
 {\r
        Log_Log("VESA", "Setting mode to %i", mode);\r
@@ -366,6 +394,8 @@ int Vesa_Int_SetMode(int mode)
        // Check for fast return\r
        if(mode == giVesaCurrentMode)   return 1;\r
        \r
+       Time_RemoveTimer(giVesaCursorTimer);\r
+       \r
        LOCK( &glVesa_Lock );\r
        \r
        gpVesa_BiosState->AX = 0x4F02;\r
@@ -446,6 +476,26 @@ int Vesa_Int_ModeInfo(tVideo_IOCtl_Mode *data)
        return 1;\r
 }\r
 \r
+/**\r
+ * \brief Updates the state of the text cursor\r
+ * \note Just does a bitwise not on the cursor region\r
+ */\r
+void Vesa_FlipCursor(void *Arg)\r
+{\r
+        int    pitch = gVesa_Modes[giVesaCurrentMode].pitch/4;\r
+        int    x = giVesaCursorX*giVT_CharWidth;\r
+        int    y = giVesaCursorY*giVT_CharHeight;\r
+        int    i;\r
+       Uint32  *fb = (void*)gpVesa_Framebuffer;\r
+       \r
+       if(giVesaCursorX < 0 || giVesaCursorY < 0)      return;\r
+       \r
+       for( i = 1; i < giVT_CharHeight-1; i++ )\r
+               fb[(y+i)*pitch+x] = ~fb[(y+i)*pitch+x];\r
+       \r
+       giVesaCursorTimer = Time_CreateTimer(VESA_CURSOR_PERIOD, Vesa_FlipCursor, Arg);\r
+}\r
+\r
 // ------------------------\r
 // --- 2D Accelleration ---\r
 // ------------------------\r
@@ -461,42 +511,44 @@ void Vesa_2D_Fill(void *Ent, Uint16 X, Uint16 Y, Uint16 W, Uint16 H, Uint32 Colo
 \r
 void Vesa_2D_Blit(void *Ent, Uint16 DstX, Uint16 DstY, Uint16 SrcX, Uint16 SrcY, Uint16 W, Uint16 H)\r
 {\r
-        int    scrnwidth = gVesa_Modes[giVesaCurrentMode].width;\r
-        int    dst = DstY*scrnwidth + DstX;\r
-        int    src = SrcY*scrnwidth + SrcX;\r
+        int    scrnpitch = gVesa_Modes[giVesaCurrentMode].pitch;\r
+        int    dst = DstY*scrnpitch + DstX;\r
+        int    src = SrcY*scrnpitch + SrcX;\r
         int    tmp;\r
        \r
        //Log("Vesa_2D_Blit: (Ent=%p, DstX=%i, DstY=%i, SrcX=%i, SrcY=%i, W=%i, H=%i)",\r
        //      Ent, DstX, DstY, SrcX, SrcY, W, H);\r
        \r
-       if(SrcX + W > scrnwidth)\r
-               W = scrnwidth - SrcX;\r
-       if(DstX + W > scrnwidth)\r
-               W = scrnwidth - DstX;\r
+       if(SrcX + W > gVesa_Modes[giVesaCurrentMode].width)\r
+               W = gVesa_Modes[giVesaCurrentMode].width - SrcX;\r
+       if(DstX + W > gVesa_Modes[giVesaCurrentMode].width)\r
+               W = gVesa_Modes[giVesaCurrentMode].width - DstX;\r
        if(SrcY + H > gVesa_Modes[giVesaCurrentMode].height)\r
                H = gVesa_Modes[giVesaCurrentMode].height - SrcY;\r
        if(DstY + H > gVesa_Modes[giVesaCurrentMode].height)\r
                H = gVesa_Modes[giVesaCurrentMode].height - DstY;\r
        \r
+       //Debug("W = %i, H = %i", W, H);\r
+       \r
        if( dst > src ) {\r
                // Reverse copy\r
-               dst += H*scrnwidth;\r
-               src += H*scrnwidth;\r
+               dst += H*scrnpitch;\r
+               src += H*scrnpitch;\r
                while( H -- ) {\r
-                       dst -= scrnwidth;\r
-                       src -= scrnwidth;\r
+                       dst -= scrnpitch;\r
+                       src -= scrnpitch;\r
                        tmp = W;\r
                        for( tmp = W; tmp --; ) {\r
-                               *((Uint32*)gpVesa_Framebuffer + dst + tmp) = *((Uint32*)gpVesa_Framebuffer + src + tmp);\r
+                               *(Uint32*)(gpVesa_Framebuffer + dst + tmp) = *(Uint32*)(gpVesa_Framebuffer + src + tmp);\r
                        }\r
                }\r
        }\r
        else {\r
                // Normal copy is OK\r
                while( H -- ) {\r
-                       memcpyd((Uint32*)gpVesa_Framebuffer + dst, (Uint32*)gpVesa_Framebuffer + src, W);\r
-                       dst += scrnwidth;\r
-                       src += scrnwidth;\r
+                       memcpy((void*)gpVesa_Framebuffer + dst, (void*)gpVesa_Framebuffer + src, W*sizeof(Uint32));\r
+                       dst += scrnpitch;\r
+                       src += scrnpitch;\r
                }\r
        }\r
 }\r

UCC git Repository :: git.ucc.asn.au