diff --git a/REDALERT/GADGET.CPP b/REDALERT/GADGET.CPP
index 019e1fa..ca5a3f6 100644
--- a/REDALERT/GADGET.CPP
+++ b/REDALERT/GADGET.CPP
@@ -535,6 +535,8 @@ KeyNumType GadgetClass::Input(void)
// jmarshall
int flags = 0;
WWSDL_ProcessEvents(key, flags);
+
+ Show_Mouse(); // jmarshall: thsi shouldn't be here!
// jmarshall end
/*
diff --git a/REDALERT/GSCREEN.CPP b/REDALERT/GSCREEN.CPP
index e8e9195..f0a7213 100644
--- a/REDALERT/GSCREEN.CPP
+++ b/REDALERT/GSCREEN.CPP
@@ -275,6 +275,8 @@ void GScreenClass::Input(KeyNumType & key, int & x, int & y)
x = Keyboard->Mouse_X();
y = Keyboard->Mouse_Y();
+ Show_Mouse();
+
if (Buttons != NULL) {
/*
diff --git a/REDALERT/INIT.CPP b/REDALERT/INIT.CPP
index e1980bf..2b811b0 100644
--- a/REDALERT/INIT.CPP
+++ b/REDALERT/INIT.CPP
@@ -672,7 +672,7 @@ bool Select_Game(bool fade)
// }
Set_Logic_Page(SeenBuff);
- display = false;
+ // display = false;
Show_Mouse();
}
else {
@@ -3387,7 +3387,7 @@ static void Init_Mouse(void)
** to set one of our own.
*/
#ifdef WIN32
-// ShowCursor(false);
+ ShowCursor(false);
#endif
if (MouseInstalled) {
void const * temp_mouse_shapes = MFCD::Retrieve("MOUSE.SHP");
diff --git a/REDALERT/MSGBOX.CPP b/REDALERT/MSGBOX.CPP
index 87f948d..f05a1fe 100644
--- a/REDALERT/MSGBOX.CPP
+++ b/REDALERT/MSGBOX.CPP
@@ -274,7 +274,7 @@ int WWMessageBox::Process(const char * msg, const char * b1txt, const char * b2t
#endif
if (display) {
- display = false;
+ //display = false;
Hide_Mouse();
Dialog_Box(x, y, width, height);
diff --git a/REDALERT/RedAlert.vcxproj b/REDALERT/RedAlert.vcxproj
index 5bf13cc..e01f669 100644
--- a/REDALERT/RedAlert.vcxproj
+++ b/REDALERT/RedAlert.vcxproj
@@ -449,6 +449,7 @@
+
@@ -739,6 +740,7 @@
+
diff --git a/REDALERT/RedAlert.vcxproj.filters b/REDALERT/RedAlert.vcxproj.filters
index 45979bb..265aab1 100644
--- a/REDALERT/RedAlert.vcxproj.filters
+++ b/REDALERT/RedAlert.vcxproj.filters
@@ -942,6 +942,9 @@
Source Files\win32lib
+
+ Source Files\win32lib
+
@@ -1838,6 +1841,9 @@
Source Files\libsmacker
+
+ Source Files\win32lib
+
diff --git a/REDALERT/SPECIAL.CPP b/REDALERT/SPECIAL.CPP
index 69f23f0..091b0cf 100644
--- a/REDALERT/SPECIAL.CPP
+++ b/REDALERT/SPECIAL.CPP
@@ -527,12 +527,12 @@ int Fetch_Difficulty(void)
** Main Processing Loop.
*/
Set_Logic_Page(SeenBuff);
- bool redraw = true;
+ //bool redraw = true;
bool process = true;
while (process) {
- if (redraw) {
- redraw = false;
+ {
+ // redraw = false;
/*
** Draw the background of the dialog.
@@ -575,7 +575,7 @@ int Fetch_Difficulty(void)
*/
if (AllSurfaces.SurfacesRestored) {
AllSurfaces.SurfacesRestored=FALSE;
- redraw = true;
+ //redraw = true;
continue;
}
#endif //WIN32
diff --git a/REDALERT/WIN32LIB/MOUSE.H b/REDALERT/WIN32LIB/MOUSE.H
index b40d07e..4c8781c 100644
--- a/REDALERT/WIN32LIB/MOUSE.H
+++ b/REDALERT/WIN32LIB/MOUSE.H
@@ -60,6 +60,24 @@ class WWMouseClass {
void Set_Cursor_Clip(void);
void Clear_Cursor_Clip(void);
+// jmarshall - accessor functions to hook up mouse code from chronoshift.
+ int Get_Hotspot_X(void) { return MouseXHot; }
+ int Get_Hotspot_Y(void) { return MouseYHot; }
+ int Get_Cursor_Width(void) { return CursorWidth; }
+ int Get_Cursor_Height(void) { return CursorHeight; }
+ int Get_Max_Width(void) { return MaxWidth; }
+ int Get_Max_Height(void) { return MaxHeight; }
+ void Set_Hotspot_X(int hotspotX) { MouseXHot = hotspotX; }
+ void Set_Hotspot_Y(int hotspotY) { MouseYHot = hotspotY; }
+ void Set_Cursor_Width(int width) { CursorWidth = width; }
+ void Set_Cursor_Height(int height) { CursorHeight = height; }
+ void Set_Max_Width(int width) { MaxWidth = width; }
+ void Set_Max_Height(int height) { MaxHeight = height; }
+
+ char* Get_Image_Buff(void) { return MouseCursor; }
+ void* Get_Frame_Pointer() { return PrevCursor; }
+ void Set_Frame_Pointer(void* frame) { PrevCursor = (char *)frame; }
+// jmarshall end
private:
enum {
CONDHIDE = 1,
@@ -105,11 +123,9 @@ class WWMouseClass {
};
-extern "C" {
- void __cdecl Mouse_Shadow_Buffer(void *thisptr, GraphicViewPortClass *srcdst, void *buffer, int x, int y, int hotx, int hoty, int store);
- void __cdecl Draw_Mouse(void *thisptr, GraphicViewPortClass *srcdst, int x, int y);
- void * __cdecl ASM_Set_Mouse_Cursor(void * thisptr, int hotspotx, int hotspoty, VOID *cursor);
-};
+void __cdecl Mouse_Shadow_Buffer(WWMouseClass& mouse, GraphicViewPortClass& viewport, void* buffer, int x_pos, int y_pos, int hspot_x, int hspot_y, BOOL save);
+void __cdecl Mouse_Draw(WWMouseClass& mouse, GraphicViewPortClass& viewport, int x_pos, int y_pos);
+void* __cdecl Mouse_Set_Cursor(WWMouseClass& mouse, int hspot_x, int hspot_y, void* frame);
void Hide_Mouse(void);
void Show_Mouse(void);
diff --git a/REDALERT/WIN32LIB/MOUSEWW.CPP b/REDALERT/WIN32LIB/MOUSEWW.CPP
index bdeb01a..1b080ed 100644
--- a/REDALERT/WIN32LIB/MOUSEWW.CPP
+++ b/REDALERT/WIN32LIB/MOUSEWW.CPP
@@ -37,6 +37,7 @@ static WWMouseClass *_Mouse=NULL;
void CALLBACK Process_Mouse( UINT event_id, UINT res1 , DWORD user, DWORD res2, DWORD res3 );
extern bool GameInFocus;
+extern int mousex, mousey;
/***********************************************************************************************
* MOUSECLASS::MOUSECLASS -- Constructor for the Mouse Class *
@@ -184,9 +185,6 @@ void WWMouseClass::Clear_Cursor_Clip(void)
void WWMouseClass::Process_Mouse(void)
{
-//ST - 1/3/2019 10:50AM
- return;
-#if (0)
POINT pt; // define a structure to hold current cursor pos
//
@@ -255,19 +253,10 @@ void WWMouseClass::Process_Mouse(void)
// Allow other threads to lock the screen again
//
//Unblock_Mouse(Screen->Get_Graphic_Buffer());
-#endif
}
void *WWMouseClass::Set_Cursor(int xhotspot, int yhotspot, void *cursor)
{
-//ST - 1/3/2019 10:50AM
- xhotspot;
- yhotspot;
- cursor;
- return cursor;
-
-#if (0)
-
//
// If the pointer to the cursor we got is invalid, or its the same as the
// currently set cursor then just return.
@@ -287,7 +276,7 @@ void *WWMouseClass::Set_Cursor(int xhotspot, int yhotspot, void *cursor)
// Now convert the shape to a mouse cursor with the given hotspots and
// set it as our current mouse.
//
- void *retval = ASM_Set_Mouse_Cursor(this, xhotspot, yhotspot, cursor);
+ void *retval = Mouse_Set_Cursor(*this, xhotspot, yhotspot, cursor);
//
// Show the mouse which will force it to appear with the new shape we
// have assigned.
@@ -302,24 +291,21 @@ void *WWMouseClass::Set_Cursor(int xhotspot, int yhotspot, void *cursor)
// Asm_Set_Mouse_Cursor.
//
return(retval);
-#endif
}
void WWMouseClass::Low_Hide_Mouse()
{
-//ST - 1/3/2019 10:50AM
-#if (0)
if (!State) {
if (MouseBuffX != -1 || MouseBuffY != -1) {
if (Screen->Lock()){
- Mouse_Shadow_Buffer(this, Screen, MouseBuffer, MouseBuffX, MouseBuffY, MouseXHot, MouseYHot, 0);
+ Mouse_Shadow_Buffer(*this, *Screen, MouseBuffer, MouseBuffX, MouseBuffY, MouseXHot, MouseYHot, 0);
Screen->Unlock();
}
}
MouseBuffX = -1;
MouseBuffY = -1;
}
-#endif
+
State++;
}
void WWMouseClass::Hide_Mouse()
@@ -332,23 +318,11 @@ void WWMouseClass::Hide_Mouse()
void WWMouseClass::Low_Show_Mouse(int x, int y)
{
- //
- // If the mouse is already visible then just ignore the problem.
- //
- if (State == 0) return;
- //
- // Make the mouse a little bit more visible
- //
- State--;
-
-//ST - 1/3/2019 10:50AM
-#if (0)
-
//
// If the mouse is completely visible then draw it at its current
// position.
//
- if (!State) {
+ {
//
// Try to lock the screen til we sucessfully get a lock.
//
@@ -356,11 +330,11 @@ void WWMouseClass::Low_Show_Mouse(int x, int y)
//
// Save off the area behind the mouse.
//
- Mouse_Shadow_Buffer(this, Screen, MouseBuffer, x, y, MouseXHot, MouseYHot, 1);
+ Mouse_Shadow_Buffer(*this, *Screen, MouseBuffer, x, y, MouseXHot, MouseYHot, 1);
//
// Draw the mouse in its new location
//
- ::Draw_Mouse(this, Screen, x, y);
+ Mouse_Draw(*this, *Screen, x, y);
//
// Save off the positions that we saved the buffer from
//
@@ -372,17 +346,16 @@ void WWMouseClass::Low_Show_Mouse(int x, int y)
Screen->Unlock();
}
}
-#endif
}
void WWMouseClass::Show_Mouse()
{
- POINT pt;
- GetCursorPos(&pt);
-
- MouseUpdate++;
- Low_Show_Mouse(pt.x, pt.y);
- MouseUpdate--;
+ //POINT pt;
+ //GetCursorPos(&pt);
+ //
+ //MouseUpdate++;
+ Low_Show_Mouse(mousex, mousey);
+ //MouseUpdate--;
}
void WWMouseClass::Conditional_Hide_Mouse(int x1, int y1, int x2, int y2)
@@ -589,7 +562,7 @@ void WWMouseClass::Erase_Mouse(GraphicViewPortClass *scr, int forced)
int WWMouseClass::Get_Mouse_State(void)
{
- return(State);
+ return 0;//(State);
}
/***********************************************************************************************
* WWKeyboardClass::Get_Mouse_X -- Returns the mouses current x position in pixels *
@@ -603,9 +576,7 @@ int WWMouseClass::Get_Mouse_State(void)
*=============================================================================================*/
int WWMouseClass::Get_Mouse_X(void)
{
- POINT pt;
- GetCursorPos(&pt);
- return(pt.x);
+ return mousex;
}
@@ -621,9 +592,7 @@ int WWMouseClass::Get_Mouse_X(void)
*=============================================================================================*/
int WWMouseClass::Get_Mouse_Y(void)
{
- POINT pt;
- GetCursorPos(&pt);
- return(pt.y);
+ return mousey;
}
/***********************************************************************************************
@@ -638,12 +607,9 @@ int WWMouseClass::Get_Mouse_Y(void)
* 10/17/1995 PWG : Created. *
*=============================================================================================*/
void WWMouseClass::Get_Mouse_XY(int &x, int &y)
-{
- POINT pt;
-
- GetCursorPos(&pt);
- x = pt.x;
- y = pt.y;
+{
+ x = mousex;
+ y = mousey;
}
//#pragma off(unreferenced)
diff --git a/REDALERT/WIN32LIB/MouseShape.cpp b/REDALERT/WIN32LIB/MouseShape.cpp
new file mode 100644
index 0000000..6808c9f
--- /dev/null
+++ b/REDALERT/WIN32LIB/MouseShape.cpp
@@ -0,0 +1,304 @@
+/**
+ * @file
+ *
+ * @author OmniBlade
+ * @author CCHyper
+ *
+ * @brief Low level sprite drawing functions for Dune2 sprite format (used for mouse in early C&C games).
+ *
+ * @copyright Chronoshift is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version
+ * 2 of the License, or (at your option) any later version.
+ * A full copy of the GNU General Public License can be found in
+ * LICENSE
+ */
+#include "../FUNCTION.H"
+#include
+#include "mouse.h"
+#include "mouseshape.h"
+#include "gbuffer.h"
+//#include "lcw.h"
+#include
+#include
+
+#define MIN(a,b) (((a)<(b))?(a):(b))
+#define MAX(a,b) (((a)>(b))?(a):(b))
+
+using std::memcpy;
+
+uint8_t g_mouseShapeBuffer[65000]; // Original code shares the global ShapeBuffer with other sprite drawing.
+
+int Get_Shape_Uncomp_Size(void* shape)
+{
+ return static_cast(shape)->data_length;
+}
+
+int Extract_Shape_Count(void* shape)
+{
+ return static_cast(shape)->frame_count;
+}
+
+void* Extract_Shape(void* shape, int frame)
+{
+ char* data = static_cast(shape);
+ MouseShapeHeader* header = static_cast(shape);
+
+ if (shape && frame >= 0 && header->frame_count > frame) {
+ return data + (&header->offset)[frame] + 2;
+ }
+
+ return nullptr;
+}
+
+int Get_Shape_Width(void* shape)
+{
+ // return static_cast(shape)->Width;
+ return static_cast(shape)->width;
+}
+
+int Get_Shape_Height(void* shape)
+{
+ return static_cast(shape)->height;
+}
+
+//int Restore_Shape_Height(void* shape)
+//{
+// int oldheight = static_cast(shape)->height;
+// static_cast(shape)->height = static_cast(shape)->original_height;
+// return oldheight;
+//}
+
+int Get_Shape_Original_Height(void* shape)
+{
+ return static_cast(shape)->original_height;
+}
+
+void __cdecl Mouse_Shadow_Buffer(WWMouseClass& mouse, GraphicViewPortClass& viewport, void* buffer, int x_pos, int y_pos, int hspot_x, int hspot_y, BOOL save)
+{
+ int xstart = x_pos - hspot_x;
+ int ystart = y_pos - hspot_y;
+ int yend = mouse.Get_Cursor_Height() + ystart - 1;
+ int xend = mouse.Get_Cursor_Width() + xstart - 1;
+ int ms_img_offset = 0;
+ uint8_t* mouse_img = static_cast(buffer);
+
+ //If we aren't drawing within the viewport, return
+ if (xstart >= viewport.Get_Width() ||
+ ystart >= viewport.Get_Height() ||
+ xend <= 0 || yend <= 0) {
+ return;
+ }
+
+ if (xstart < 0) {
+ ms_img_offset = -xstart;
+ xstart = 0;
+ }
+
+ if (ystart < 0) {
+ mouse_img += mouse.Get_Cursor_Width() * (-ystart);
+ ystart = 0;
+ }
+
+ xend = MIN(xend, viewport.Get_Width() - 1);
+ yend = MIN(yend, viewport.Get_Height() - 1);
+
+ int blit_height = yend - ystart + 1;
+ int blit_width = xend - xstart + 1;
+ int src_pitch;
+ int dst_pitch;
+ uint8_t* src;
+ uint8_t* dst;
+
+ // Bool will control if we are copying to or from shadow buffer, set vars here
+ if (save) {
+ src_pitch = (viewport.Get_Pitch() + viewport.Get_XAdd() + viewport.Get_Width());
+ dst_pitch = mouse.Get_Cursor_Width();
+ src = (uint8_t*)(viewport.Get_Offset()) + src_pitch * ystart + xstart;
+ dst = mouse_img + ms_img_offset;
+ }
+ else {
+ src_pitch = mouse.Get_Cursor_Width();
+ dst_pitch = (viewport.Get_Pitch() + viewport.Get_XAdd() + viewport.Get_Width());
+ src = mouse_img + ms_img_offset;
+ dst = (uint8_t*)(viewport.Get_Offset()) + dst_pitch * ystart + xstart;
+ }
+
+ while (blit_height--) {
+ memcpy(dst, src, blit_width);
+ src += src_pitch;
+ dst += dst_pitch;
+ }
+}
+
+void __cdecl Mouse_Draw(WWMouseClass& mouse, GraphicViewPortClass& viewport, int x_pos, int y_pos)
+{
+ int xstart = x_pos - mouse.Get_Hotspot_X();
+ int ystart = y_pos - mouse.Get_Hotspot_Y();
+ int yend = mouse.Get_Cursor_Height() + ystart - 1;
+ int xend = mouse.Get_Cursor_Width() + xstart - 1;
+ int ms_img_offset = 0;
+ uint8_t* mouse_img = (uint8_t * )mouse.Get_Image_Buff();
+
+ //If we aren't drawing within the viewport, return
+ if (xstart >= viewport.Get_Width() ||
+ ystart >= viewport.Get_Height() ||
+ xend <= 0 || yend <= 0) {
+ return;
+ }
+
+ if (xstart < 0) {
+ ms_img_offset = -xstart;
+ xstart = 0;
+ }
+
+ if (ystart < 0) {
+ mouse_img += mouse.Get_Cursor_Width() * (-ystart);
+ ystart = 0;
+ }
+
+ xend = MIN(xend, viewport.Get_Width() - 1);
+ yend = MIN(yend, viewport.Get_Height() - 1);
+
+ int pitch = viewport.Get_Pitch() + viewport.Get_XAdd() + viewport.Get_Width();
+ uint8_t* dst = xstart + pitch * ystart + (uint8_t*)(viewport.Get_Offset());
+ uint8_t* src = ms_img_offset + mouse_img;
+ int blit_pitch = xend - xstart + 1;
+
+ if ((xend > xstart) && (yend > ystart)) {
+ int blit_height = yend - ystart + 1;
+ int dst_pitch = pitch - blit_pitch;
+ int src_pitch = mouse.Get_Cursor_Width() - blit_pitch;
+
+ while (blit_height--) {
+ int blit_width = blit_pitch;
+ while (blit_width--) {
+ uint8_t current = *src++;
+ if (current) {
+ *dst = current;
+ }
+
+ ++dst;
+ //--blit_width;
+ }
+
+ src += src_pitch;
+ dst += dst_pitch;
+ //--blit_height;
+ }
+ }
+}
+
+void* __cdecl Mouse_Set_Cursor(WWMouseClass& mouse, int hspot_x, int hspot_y, void* frame)
+{
+ uint8_t* frame_buff;
+ uint8_t* data_buff;
+ uint8_t* decmp_buff;
+ uint8_t* lcw_buff;
+ int16_t frame_flags;
+
+ int height;
+ int width;
+ int uncompsz;
+
+ MouseShapeFrameHeader* frame_header = static_cast(frame);
+
+ //Get the dimensions of our frame, mouse shp format can have variable
+ //dimensions for each frame.
+ uncompsz = Get_Shape_Uncomp_Size(frame);
+ width = Get_Shape_Width(frame);
+ height = Get_Shape_Original_Height(frame);
+
+ if (width <= mouse.Get_Max_Width() && height <= mouse.Get_Max_Height()) {
+ frame_buff = (uint8_t * )mouse.Get_Image_Buff();
+ data_buff = static_cast(frame);
+ frame_flags = frame_header->flags;
+
+ //Flag bit 2 is flag for no compression on frame, decompress to
+ //intermediate buffer if flag is clear
+ if (!(frame_header->flags & 2)) {
+ decmp_buff = g_mouseShapeBuffer;
+ lcw_buff = reinterpret_cast(frame_header);
+ frame_flags = frame_header->flags | 2;
+
+ memcpy(decmp_buff, lcw_buff, sizeof(MouseShapeFrameHeader));
+ decmp_buff += sizeof(MouseShapeFrameHeader);
+ lcw_buff += sizeof(MouseShapeFrameHeader);
+
+ //Copies a small lookup table if it exists, probably not in RA.
+ if (frame_flags & 1) {
+ memcpy(decmp_buff, lcw_buff, 16);
+ decmp_buff += 16;
+ lcw_buff += 16;
+ }
+
+ LCW_Uncomp(lcw_buff, decmp_buff, uncompsz);
+ data_buff = g_mouseShapeBuffer;
+ }
+
+ if (frame_flags & 1) {
+ uint8_t* data_start = data_buff + sizeof(MouseShapeFrameHeader);
+ uint8_t* image_start = data_buff + sizeof(MouseShapeFrameHeader) + 16;
+ int image_size = height * width;
+ //uint8_t current_byte = 0;
+ int run_len = 0;
+
+ while (image_size) {
+ uint8_t current_byte = *image_start++;
+ if (current_byte) {
+ *frame_buff++ = data_start[current_byte];
+ --image_size;
+ continue;
+ }
+
+ if (!image_size) {
+ break;
+ }
+
+ run_len = *image_start;
+ image_size -= run_len;
+ ++image_start;
+
+ while (run_len--) {
+ *frame_buff++ = 0;
+ }
+ }
+ }
+ else {
+ uint8_t* data_start = data_buff + sizeof(MouseShapeFrameHeader);
+ int image_size = height * width;
+ int run_len = 0;
+
+ while (image_size) {
+ uint8_t current_byte = *data_start++;
+ if (current_byte) {
+ *frame_buff++ = current_byte;
+ --image_size;
+ continue;
+ }
+
+ if (!image_size) {
+ break;
+ }
+
+ run_len = *data_start;
+ image_size -= run_len;
+ ++data_start;
+
+ while (run_len--) {
+ *frame_buff++ = 0;
+ }
+ }
+ }
+
+ mouse.Set_Hotspot_X(hspot_x);
+ mouse.Set_Hotspot_Y(hspot_y);
+ mouse.Set_Cursor_Height(height);
+ mouse.Set_Cursor_Width(width);
+ }
+
+ void* result = mouse.Get_Frame_Pointer();
+ mouse.Set_Frame_Pointer(frame);
+
+ return result;
+}
diff --git a/REDALERT/WIN32LIB/MouseShape.h b/REDALERT/WIN32LIB/MouseShape.h
new file mode 100644
index 0000000..dbfded0
--- /dev/null
+++ b/REDALERT/WIN32LIB/MouseShape.h
@@ -0,0 +1,67 @@
+/**
+ * @file
+ *
+ * @author OmniBlade
+ * @author CCHyper
+ *
+ * @brief Low level sprite drawing functions for Dune2 sprite format (used for mouse in early C&C games).
+ *
+ * @copyright Chronoshift is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version
+ * 2 of the License, or (at your option) any later version.
+ * A full copy of the GNU General Public License can be found in
+ * LICENSE
+ */
+#pragma once
+
+#ifndef MOUSESHAPE_H
+#define MOUSESHAPE_H
+
+#pragma pack(push, 1)
+ // Header for each frame in the old SHP format... only used for mouse now.
+struct MouseShapeFrameHeader
+{
+ //"MAKESHAPE_NORMAL" 0
+ //"MAKESHAPE_COMPACT" 1
+ //"MAKESHAPE_NOCOMP" 2
+ //"MAKESHAPE_VARIABLE" 4
+ uint16_t flags; // flag 1 specifies that a 16 byte color table follows the header.
+ // flag 2 specifies that this frame doesn't have LCW compression,
+ // this frame would only have RLE compression.
+ // flag 4 specifies a custom length color table follows the header.
+ uint8_t height; //height after RLE compression?
+ uint16_t width;
+ uint8_t original_height; // original frame height without any compression.
+ uint16_t shape_size; // full frame size including this header.
+ uint16_t data_length; // uncompressed size, frame size minus header if flag 2 is specified.
+ //
+ // Following this is optional data, in Dune 2 this was used to specify remap indexes.
+ // If flag 1 is set then a uint8_t color_table[16] follows.
+ // if flag 4 is set then a uint8_t color_table_size and uint8_t color_table[color_table_size] follows.
+};
+
+// Header for the old SHP format... only used for mouse now. Offset values need +2 to get actual frame pos.
+struct MouseShapeHeader
+{
+ uint16_t frame_count;
+ uint32_t offset;
+};
+#pragma pack(pop)
+
+class WWMouseClass;
+class GraphicViewPortClass;
+
+int Get_Shape_Uncomp_Size(void* shape);
+int Extract_Shape_Count(void* shape);
+void* Extract_Shape(void* shape, int frame = 0);
+int Get_Shape_Width(void* shape);
+int Get_Shape_Height(void* shape);
+int Restore_Shape_Height(void* shape);
+int Get_Shape_Original_Height(void* shape);
+
+void __cdecl Mouse_Shadow_Buffer(WWMouseClass& mouse, GraphicViewPortClass& viewport, void* buffer, int x_pos, int y_pos, int hspot_x, int hspot_y, BOOL save);
+void __cdecl Mouse_Draw(WWMouseClass& mouse, GraphicViewPortClass& viewport, int x_pos, int y_pos);
+void* __cdecl Mouse_Set_Cursor(WWMouseClass& mouse, int hspot_x, int hspot_y, void* shape);
+
+#endif