diff --git a/.gitignore b/.gitignore index 6b0ff60..4b893ed 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,15 @@ /.vs/ /out/ -/code/out/ \ No newline at end of file +/code/out/ +/fonts +/sound +/ui +/*.mix +/*.pal +/*.ini +/*.exe +/*.ilk +/*.dat +/savegame* + diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 2a6e5a7..db17383 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -8,6 +8,11 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../) set(CMAKE_VERBOSE_MAKEFILE ON) +set(src_io + ./REDALERT/io/UserInput.cpp + ./REDALERT/io/UserInput.h +) + set(src_win32lib ./REDALERT/WIN32LIB/TOBUFF.cpp ./RedAlert/WIN32LIB/ALLOC.CPP @@ -711,7 +716,7 @@ set(src_external add_definitions(-D RA_AF -DCHEAT_KEYS -DIMGUI_IMPL_OPENGL_LOADER_GLEW -DSCENARIO_EDITOR -DWINDOWS_IGNORE_PACKING_MISMATCH -DTRUE_FALSE_DEFINED -DWIN32 -DWINDOWS -DENGLISH -D_USRDLL -DREDALERT_EXPORTS) add_compile_options(/permissive+ /Zc:forScope- /Zp1) -add_executable(RedAlert ${src_win32lib} ${src_redalert} ${src_external}) +add_executable(RedAlert ${src_io} ${src_win32lib} ${src_redalert} ${src_external}) set_target_properties(RedAlert PROPERTIES OUTPUT_NAME "RedAlert" LINK_FLAGS "/PDB:\"RedAlert.pdb\" /SUBSYSTEM:WINDOWS" RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/../" ) target_include_directories(RedAlert PRIVATE ./external/devil/;./external/;./redalert/win32lib;./external/lua/;./external/imgui;./external/dxsdk/Include;./external/ffmpeg-win32/include;./external/sdl2/include;./win32lib;./external/openal/include) diff --git a/code/REDALERT/BDATA.CPP b/code/REDALERT/BDATA.CPP index 56553f7..5fe0762 100644 --- a/code/REDALERT/BDATA.CPP +++ b/code/REDALERT/BDATA.CPP @@ -3145,6 +3145,11 @@ void BuildingTypeClass::One_Time(void) sprintf(imageFileName, "DATA/ART/TEXTURES/SRGB/RED_ALERT/STRUCTURES/%s/%s-0000.TGA", building.Graphic_Name(), building.Graphic_Name()); ((void const*&)building.HDImageData) = Image_LoadImage(imageFileName, true, true); + if (!building.HDImageData) { + sprintf(imageFileName, "DATA/ART/TEXTURES/SRGB/RED_ALERT/STRUCTURES/%s/%s-0000-0000.TGA", building.Graphic_Name(), building.Graphic_Name()); + ((void const*&)building.HDImageData) = Image_LoadImage(imageFileName, true, true); + } + if (building.ImageData != NULL && building.HDImageData != NULL) { int width = Get_Build_Frame_Width(building.ImageData); int height = Get_Build_Frame_Height(building.ImageData); diff --git a/code/REDALERT/CDATA.CPP b/code/REDALERT/CDATA.CPP index 02e12b5..06cdfc4 100644 --- a/code/REDALERT/CDATA.CPP +++ b/code/REDALERT/CDATA.CPP @@ -3136,6 +3136,12 @@ void TemplateTypeClass::Init(TheaterType theater) ((unsigned char &)tplate.Width) = Get_IconSet_MapWidth(ptr); ((unsigned char &)tplate.Height) = Get_IconSet_MapHeight(ptr); + + { + char tmp[512]; + sprintf(tmp, "icon_%s", fullname); + ((void const*&)tplate.HDImageData) = Load_Stamp(fullname, tplate.ImageData); + } } } } diff --git a/code/REDALERT/CELL.CPP b/code/REDALERT/CELL.CPP index 6d776c7..c3be89a 100644 --- a/code/REDALERT/CELL.CPP +++ b/code/REDALERT/CELL.CPP @@ -1091,7 +1091,9 @@ void CellClass::Draw_It(int x, int y, bool objects) const ** This is the underlying terrain icon. */ if (ttype->Get_Image_Data()) { - LogicPage->Draw_Stamp(ttype, icon, x, y, NULL, WINDOW_TACTICAL); +// jmarshall - hd image should always be valid even if loading legacy assets + LogicPage->Draw_Stamp(ttype->Get_HDImage_Data(), icon, x, y, NULL, WINDOW_TACTICAL); +// jmarshall end if (remap) { LogicPage->Remap(x+Map.TacPixelX, y+Map.TacPixelY, ICON_PIXEL_W, ICON_PIXEL_H, remap); } @@ -1190,9 +1192,9 @@ void CellClass::Draw_It(int x, int y, bool objects) const ** Draw the hash-mark cursor: */ if (Map.ProximityCheck && Is_Clear_To_Build(loco)) { - LogicPage->Draw_Stamp(DisplayClass::TransIconset, 0, x, y, NULL, WINDOW_TACTICAL); + LogicPage->Draw_Stamp(DisplayClass::TransIconsetHD, 0, x, y, NULL, WINDOW_TACTICAL); } else { - LogicPage->Draw_Stamp(DisplayClass::TransIconset, 2, x, y, NULL, WINDOW_TACTICAL); + LogicPage->Draw_Stamp(DisplayClass::TransIconsetHD, 2, x, y, NULL, WINDOW_TACTICAL); } #ifdef SCENARIO_EDITOR @@ -1213,8 +1215,8 @@ void CellClass::Draw_It(int x, int y, bool objects) const icon = (Cell_X(cell) - Cell_X(Map.ZoneCell + Map.ZoneOffset)) + (Cell_Y(cell) - Cell_Y(Map.ZoneCell + Map.ZoneOffset)) * tptr->Width; -// jmarshall - pass in raw tptr - LogicPage->Draw_Stamp(tptr, icon, x, y, NULL, WINDOW_TACTICAL); +// jmarshall - hd image should always be valid even if loading legacy assets + LogicPage->Draw_Stamp(tptr->Get_HDImage_Data(), icon, x, y, NULL, WINDOW_TACTICAL); // jmarshall end } break; diff --git a/code/REDALERT/CONQUER.CPP b/code/REDALERT/CONQUER.CPP index 2455d61..ff2a75a 100644 --- a/code/REDALERT/CONQUER.CPP +++ b/code/REDALERT/CONQUER.CPP @@ -899,45 +899,45 @@ void Keyboard_Process(KeyNumType & input) ** state! */ if (input != 0 && (plain == Options.KeyTeam1 || plain == KN_1)) { - Handle_Team(0, action); - input = KN_NONE; - } - if (input != 0 && (plain == Options.KeyTeam2 || plain == KN_2)) { Handle_Team(1, action); input = KN_NONE; } - if (input != 0 && (plain == Options.KeyTeam3 || plain == KN_3)) { + if (input != 0 && (plain == Options.KeyTeam2 || plain == KN_2)) { Handle_Team(2, action); input = KN_NONE; } - if (input != 0 && (plain == Options.KeyTeam4 || plain == KN_4)) { + if (input != 0 && (plain == Options.KeyTeam3 || plain == KN_3)) { Handle_Team(3, action); input = KN_NONE; } - if (input != 0 && (plain == Options.KeyTeam5 || plain == KN_5)) { + if (input != 0 && (plain == Options.KeyTeam4 || plain == KN_4)) { Handle_Team(4, action); input = KN_NONE; } - if (input != 0 && (plain == Options.KeyTeam6 || plain == KN_6)) { + if (input != 0 && (plain == Options.KeyTeam5 || plain == KN_5)) { Handle_Team(5, action); input = KN_NONE; } - if (input != 0 && (plain == Options.KeyTeam7 || plain == KN_7)) { + if (input != 0 && (plain == Options.KeyTeam6 || plain == KN_6)) { Handle_Team(6, action); input = KN_NONE; } - if (input != 0 && (plain == Options.KeyTeam8 || plain == KN_8)) { + if (input != 0 && (plain == Options.KeyTeam7 || plain == KN_7)) { Handle_Team(7, action); input = KN_NONE; } - if (input != 0 && (plain == Options.KeyTeam9 || plain == KN_9)) { + if (input != 0 && (plain == Options.KeyTeam8 || plain == KN_8)) { Handle_Team(8, action); input = KN_NONE; } - if (input != 0 && (plain == Options.KeyTeam10 || plain == KN_0)) { + if (input != 0 && (plain == Options.KeyTeam9 || plain == KN_9)) { Handle_Team(9, action); input = KN_NONE; } + if (input != 0 && (plain == Options.KeyTeam10 || plain == KN_0)) { + Handle_Team(0, action); + input = KN_NONE; + } /* ** Handle the bookmark hotkeys. diff --git a/code/REDALERT/CREDITS.CPP b/code/REDALERT/CREDITS.CPP index e81076c..834476e 100644 --- a/code/REDALERT/CREDITS.CPP +++ b/code/REDALERT/CREDITS.CPP @@ -89,14 +89,7 @@ void CreditClass::Graphic_Logic(bool forced) { BStart(BENCH_TABS); - int xx = SeenBuff.Get_Width() - (120 * RESFACTOR); - - /* - ** Adjust the credits display to be above the sidebar for 640x400 - */ -#ifdef WIN32 - xx += 80 * RESFACTOR; -#endif + int xx = SeenBuff.Get_Width() - (120 * RESFACTOR) + ( 80 * RESFACTOR ); /* ** Play a sound effect when the money display changes, but only if a sound @@ -116,7 +109,8 @@ void CreditClass::Graphic_Logic(bool forced) TabClass::Draw_Credits_Tab(); Fancy_Text_Print("%ld", xx, 0, &MetalScheme, TBLACK, TPF_METAL12 | TPF_CENTER | TPF_USE_GRAD_PAL, Current); - if (Scen.MissionTimer.Is_Active()) { + if (Scen.MissionTimer.Is_Active()) + { long secs = Scen.MissionTimer / TICKS_PER_SECOND; long mins = secs / 60; long hours = mins / 60; @@ -141,10 +135,11 @@ void CreditClass::Graphic_Logic(bool forced) Map.FlasherTimer = 7; } + xx = SeenBuff.Get_Width() - (120 * RESFACTOR); if (hours) { - Fancy_Text_Print(TXT_TIME_FORMAT_HOURS, 200 * RESFACTOR, 0, &MetalScheme, TBLACK, TPF_METAL12|TPF_CENTER|TPF_USE_GRAD_PAL, hours, mins, secs); + Fancy_Text_Print(TXT_TIME_FORMAT_HOURS, xx, 0, &MetalScheme, TBLACK, TPF_METAL12|TPF_CENTER|TPF_USE_GRAD_PAL, hours, mins, secs); } else { - Fancy_Text_Print(TXT_TIME_FORMAT_NO_HOURS, 200 * RESFACTOR, 0, &MetalScheme, TBLACK, TPF_METAL12|TPF_CENTER|TPF_USE_GRAD_PAL, mins, secs); + Fancy_Text_Print(TXT_TIME_FORMAT_NO_HOURS, xx, 0, &MetalScheme, TBLACK, TPF_METAL12|TPF_CENTER|TPF_USE_GRAD_PAL, mins, secs); } } diff --git a/code/REDALERT/DISPLAY.CPP b/code/REDALERT/DISPLAY.CPP index 21cd688..c162eea 100644 --- a/code/REDALERT/DISPLAY.CPP +++ b/code/REDALERT/DISPLAY.CPP @@ -108,6 +108,9 @@ unsigned char DisplayClass::TranslucentTable[(MAGIC_COL_COUNT+1)*256]; unsigned char DisplayClass::WhiteTranslucentTable[(1+1)*256]; unsigned char DisplayClass::MouseTranslucentTable[(4+1)*256]; void const * DisplayClass::TransIconset; +// jmarshall +Image_t* DisplayClass::TransIconsetHD; +// jmarshall end unsigned char DisplayClass::UnitShadow[(USHADOW_COL_COUNT+1)*256]; unsigned char DisplayClass::UnitShadowAir[(USHADOW_COL_COUNT+1)*256]; unsigned char DisplayClass::SpecialGhost[2*256]; @@ -187,8 +190,9 @@ DisplayClass::DisplayClass(void) : { ShadowShapes = 0; TransIconset = 0; + TransIconsetHD = 0; - Set_View_Dimensions(0, 0, ScreenWidth, ScreenHeight); + Set_View_Dimensions(0, 8 * RESFACTOR, ScreenWidth, ScreenHeight); } @@ -228,6 +232,9 @@ void DisplayClass::One_Time(void) ** Load the generic transparent icon set. */ TransIconset = MFCD::Retrieve("TRANS.ICN"); +// jmarshall + TransIconsetHD = Load_Stamp("TRANS_ICON", TransIconset); +// jmarshall end #ifndef NDEBUG RawFileClass file("SHADOW.SHP"); @@ -561,33 +568,18 @@ short const * DisplayClass::Text_Overlap_List(char const * text, int x, int y) c *=============================================================================================*/ void DisplayClass::Set_View_Dimensions(int x, int y, int width, int height) { - //if (width == -1) { - // TacLeptonWidth = Pixel_To_Lepton(SeenBuff.Get_Width()-x); - //} else { - // TacLeptonWidth = width * CELL_LEPTON_W; - //} - TacLeptonWidth = Pixel_To_Lepton(SeenBuff.Get_Width() - x); + if (width == -1) width = SeenBuff.Get_Width(); + TacLeptonWidth = Pixel_To_Lepton( width - x); - // ST - 3/1/2019 12:05PM - // Made the below code more consistent with the width calculation. This is needed if we aren't going to draw the tabs at the top of the screen - // - //if (height == -1) { - // TacLeptonHeight = Pixel_To_Lepton(SeenBuff.Get_Height() - y); - // //height = (SeenBuff.Get_Height()-y) / CELL_PIXEL_H; - //} - //else { - // TacLeptonHeight = height * CELL_LEPTON_H; - //} - //TacLeptonHeight = height * CELL_LEPTON_H; - - TacLeptonHeight = Pixel_To_Lepton(SeenBuff.Get_Height() - y); + if (height == -1) height = SeenBuff.Get_Height(); + TacLeptonHeight = Pixel_To_Lepton(height - y); /* ** Adjust the tactical cell if it is now in an invalid position ** because of the changed dimensions. */ - int xx = 0;// Coord_X(TacticalCoord) - (MapCellX * CELL_LEPTON_W); - int yy = 0;// Coord_Y(TacticalCoord) - (MapCellY * CELL_LEPTON_H); + int xx = Coord_X(TacticalCoord) - (MapCellX * CELL_LEPTON_W); + int yy = Coord_Y(TacticalCoord) - (MapCellY * CELL_LEPTON_H); Confine_Rect(&xx, &yy, TacLeptonWidth, TacLeptonHeight, MapCellWidth * CELL_LEPTON_W, MapCellHeight * CELL_LEPTON_H); @@ -3105,7 +3097,6 @@ int DisplayClass::TacticalClass::Action(unsigned flags, KeyNumType & key) x = Get_Mouse_X(); y = Get_Mouse_Y(); - bool edge = (y == 0 || x == 0 || x == SeenBuff.Get_Width()-1 || y == SeenBuff.Get_Height()-1); COORDINATE coord = Map.Pixel_To_Coord(x, y); CELL cell = Coord_Cell(coord); @@ -3324,16 +3315,15 @@ int DisplayClass::TacticalClass::Selection_At_Mouse(unsigned flags, KeyNumType & { int x, y; // Sub cell pixel coordinates. bool edge = false; - if (flags & (LEFTPRESS | LEFTRELEASE | RIGHTPRESS | RIGHTRELEASE)) { - x = Keyboard->MouseQX; - y = Keyboard->MouseQY; - } - else { - x = Get_Mouse_X(); - y = Get_Mouse_Y(); + + x = UserInput.Mouse.X; + y = UserInput.Mouse.Y; - if (x == 0 || y == 199 || x == 319) edge = true; + if (x == 0 || y == SeenBuff.Get_Height() || x == SeenBuff.Get_Width()) + { + edge = true; } + COORDINATE coord = Map.Pixel_To_Coord(x, y); CELL cell = Coord_Cell(coord); @@ -3360,7 +3350,7 @@ int DisplayClass::TacticalClass::Selection_At_Mouse(unsigned flags, KeyNumType & if (object != nullptr) { - bool shiftdown = DLL_Export_Get_Input_Key_State(KN_LSHIFT); + bool shiftdown = UserInput.KeyB.Shift == true; if (shiftdown) { @@ -3402,16 +3392,15 @@ int DisplayClass::TacticalClass::Command_Object(unsigned flags, KeyNumType & key { int x, y; // Sub cell pixel coordinates. bool edge = false; - if (flags & (LEFTPRESS | LEFTRELEASE | RIGHTPRESS | RIGHTRELEASE)) { - x = Keyboard->MouseQX; - y = Keyboard->MouseQY; - } - else { - x = Get_Mouse_X(); - y = Get_Mouse_Y(); - if (x == 0 || y == 199 || x == 319) edge = true; + x = UserInput.Mouse.X; + y = UserInput.Mouse.Y; + + if (x == 0 || y == SeenBuff.Get_Height() || x == SeenBuff.Get_Width()) + { + edge = true; } + COORDINATE coord = Map.Pixel_To_Coord(x, y); CELL cell = Coord_Cell(coord); diff --git a/code/REDALERT/DISPLAY.H b/code/REDALERT/DISPLAY.H index 73c37b0..f47315a 100644 --- a/code/REDALERT/DISPLAY.H +++ b/code/REDALERT/DISPLAY.H @@ -38,6 +38,7 @@ #include "map.h" #include "layer.h" +struct Image_t; #define ICON_PIXEL_W 24 #define ICON_PIXEL_H 24 @@ -114,6 +115,9 @@ class DisplayClass: public MapClass static unsigned char WhiteTranslucentTable[(1+1)*256]; static unsigned char MouseTranslucentTable[(4+1)*256]; static void const *TransIconset; +// jmarshall + static Image_t* TransIconsetHD; +// jmarshall end static unsigned char UnitShadow[(USHADOW_COL_COUNT+1)*256]; static unsigned char UnitShadowAir[(USHADOW_COL_COUNT+1)*256]; static unsigned char SpecialGhost[2*256]; diff --git a/code/REDALERT/EDIT.CPP b/code/REDALERT/EDIT.CPP index 5de95fd..45783a9 100644 --- a/code/REDALERT/EDIT.CPP +++ b/code/REDALERT/EDIT.CPP @@ -376,6 +376,8 @@ void EditClass::Draw_Text(char const * text) *=============================================================================================*/ bool EditClass::Handle_Key(KeyASCIIType ascii) { + unsigned char testAscii = (unsigned char)ascii; + switch (ascii) { /* ** Handle the special case of a non-keyboard event. It is possible that this @@ -416,7 +418,7 @@ bool EditClass::Handle_Key(KeyASCIIType ascii) /* ** Don't add a character if the length is greater than edit width. */ - if (((int)String_Pixel_Width(String) + (int)Char_Pixel_Width(ascii) ) >= (Width-2)) { + if (((int)String_Pixel_Width(String) + (int)Char_Pixel_Width(testAscii) ) >= (Width-2)) { break; } @@ -429,21 +431,21 @@ bool EditClass::Handle_Key(KeyASCIIType ascii) ** Invisible characters are never added to the string. This is ** especially true for spaces at the beginning of the string. */ - if (!isgraph(ascii) && ascii != ' ') break; - if (ascii == ' ' && Length == 0) break; + if (!isgraph(testAscii) && testAscii != ' ') break; + if (testAscii == ' ' && Length == 0) break; /* ** If this is an upper case only edit gadget, then force the alphabetic ** character to upper case. */ - if ((EditFlags & UPPERCASE) && isalpha(ascii)) { - ascii = (KeyASCIIType)toupper(ascii); + if ((EditFlags & UPPERCASE) && isalpha(testAscii)) { + testAscii = (KeyASCIIType)toupper(testAscii); } - if ((!(EditFlags & NUMERIC) || !isdigit(ascii)) && - (!(EditFlags & ALPHA) || !isalpha(ascii)) && - (!(EditFlags & MISC) || isalnum(ascii)) && - ascii != ' ') { + if ((!(EditFlags & NUMERIC) || !isdigit(testAscii)) && + (!(EditFlags & ALPHA) || !isalpha(testAscii)) && + (!(EditFlags & MISC) || isalnum(testAscii)) && + testAscii != ' ') { break; } @@ -453,7 +455,7 @@ bool EditClass::Handle_Key(KeyASCIIType ascii) ** because the event flag has been cleared. This prevents the gadget's ID ** number from being returned just because the gadget has been edited. */ - String[Length++] = ascii; + String[Length++] = testAscii; String[Length] = '\0'; Flag_To_Redraw(); break; diff --git a/code/REDALERT/ENDING.CPP b/code/REDALERT/ENDING.CPP index 8f5e10f..f7d0ff9 100644 --- a/code/REDALERT/ENDING.CPP +++ b/code/REDALERT/ENDING.CPP @@ -122,10 +122,10 @@ void Nod_Ending(void) if ((key & 0xFF) == KN_LMOUSE && !(key & KN_RLSE_BIT)) { int mousex = MouseQX; int mousey = MouseQY; - if (mousey >= 22 && mousey <= 177) { + if (mousex >= 22 && mousey <= 177) { done++; - if (mousex < 160 && mousey < 100) selection = 2; - if (mousex < 160 && mousey >= 100) selection = 3; + if (mousex < 160 && mousey < 100) selection = 2; + if (mousex < 160 && mousey >= 100) selection = 3; if (mousex >= 160 && mousey >= 100) selection = 4; } } diff --git a/code/REDALERT/EXTERNS.H b/code/REDALERT/EXTERNS.H index 4526440..4b91e44 100644 --- a/code/REDALERT/EXTERNS.H +++ b/code/REDALERT/EXTERNS.H @@ -91,6 +91,8 @@ extern void const *LightningShapes; extern int NewINIFormat; +extern bool renderConsole; + #ifdef FIXIT_ANTS extern bool AntsEnabled; @@ -158,6 +160,7 @@ extern PKey FastKey; extern PKey SlowKey; extern RulesClass Rule; extern KeyboardClass * Keyboard; +extern UserInputClass UserInput; extern RandomStraw CryptRandom; extern RandomClass NonCriticalRandomNumber; extern CarryoverClass * Carryover; @@ -365,6 +368,8 @@ extern GroundType Ground[LAND_COUNT]; /* ** Constant externs (data is not modified during game play). */ +extern std::map const sdl_keyMapping; + extern char const * Missions[MISSION_COUNT]; extern char const Keys[]; extern char const * const VQName[VQ_COUNT]; diff --git a/code/REDALERT/FUNCTION.H b/code/REDALERT/FUNCTION.H index 6c4decc..a145999 100644 --- a/code/REDALERT/FUNCTION.H +++ b/code/REDALERT/FUNCTION.H @@ -199,11 +199,10 @@ struct NoInitClass { #define TIMER_H #endif -#ifdef WIN32 #include "key.h" -#endif +#include "io/UserInput.h" -#include +#include #include "mpu.h" #include "bench.h" #include "rect.h" @@ -212,7 +211,7 @@ struct NoInitClass { #include "face.h" #include "random.h" #include "crc.h" -#include "compat.h" +#include "compat.h" #include "fixed.h" #include "base64.h" #include "pipe.h" diff --git a/code/REDALERT/GADGET.CPP b/code/REDALERT/GADGET.CPP index 3b8d5aa..185d008 100644 --- a/code/REDALERT/GADGET.CPP +++ b/code/REDALERT/GADGET.CPP @@ -84,8 +84,6 @@ GadgetClass * GadgetClass::Focused = 0; static RemapControlType _GreyScheme = {15}; RemapControlType * GadgetClass::ColorScheme = &_GreyScheme; -int mousex, mousey; - /*********************************************************************************************** * GadgetClass::GadgetClass -- Constructor for gadget object. * * * @@ -495,37 +493,6 @@ KeyNumType GadgetClass::Input(void) key = Keyboard->Get(); } -#ifdef WIN32 -#ifdef CHEAT_KEYS - //if (key == KN_K && !Debug_Map && (Debug_Flag || Debug_Playtest)) { - // /* - // ** time to create a screen shot using the PCX code (if it works) - // */ - // if (!Debug_MotionCapture) { - // GraphicBufferClass temp_page( SeenBuff.Get_Width(), - // SeenBuff.Get_Height(), - // NULL, - // SeenBuff.Get_Width() * SeenBuff.Get_Height()); - // CDFileClass file; - // char filename[30]; - // -// // Hide_Mouse(); - // SeenBuff.Blit(temp_page); -// // Show_Mouse(); - // for (int lp = 0; lp < 99; lp ++) { - // sprintf(filename, "scrsht%02d.pcx", lp); - // file.Set_Name(filename); - // if (!file.Is_Available()) break; - // } - // - // file.Cache(200000); - // Write_PCX_File(file, temp_page, & GamePalette); - // Sound_Effect(VOC_BEEP); - // } - //} -#endif -#endif - /* ** For mouse button clicks, the mouse position is actually held in the MouseQ... ** globals rather than their normal Mouse... globals. This is because we need to @@ -597,7 +564,7 @@ KeyNumType GadgetClass::Input(void) if (StuckOn) { StuckOn->Draw_Me(false); GadgetClass * oldstuck = StuckOn; - StuckOn->Clicked_On(key, flags, mousex, mousey); + StuckOn->Clicked_On(key, flags, UserInput.Mouse.X, UserInput.Mouse.Y); if (StuckOn) { StuckOn->Draw_Me(false); } else { @@ -611,7 +578,7 @@ KeyNumType GadgetClass::Input(void) */ if (Focused && (flags & KEYBOARD)) { Focused->Draw_Me(false); - Focused->Clicked_On(key, flags, mousex, mousey); + Focused->Clicked_On(key, flags, UserInput.Mouse.X, UserInput.Mouse.Y); if (Focused) { Focused->Draw_Me(false); } @@ -638,7 +605,7 @@ KeyNumType GadgetClass::Input(void) ** Process this button. If the button was recognized and action was ** performed, then bail from further processing (speed reasons?). */ - if (next_button->Clicked_On(key, flags, mousex, mousey)) { + if (next_button->Clicked_On(key, flags, UserInput.Mouse.X, UserInput.Mouse.Y)) { /* ** Some buttons will require repainting when they perform some action. diff --git a/code/REDALERT/GLOBALS.CPP b/code/REDALERT/GLOBALS.CPP index ac288ad..2e9c522 100644 --- a/code/REDALERT/GLOBALS.CPP +++ b/code/REDALERT/GLOBALS.CPP @@ -252,6 +252,12 @@ CCINIClass AftermathINI; RulesClass Rule; +/*************************************************************************** +** All user input, mouse and keyboard, is routed through the object pointed to by this +** user input class pointer. +*/ +UserInputClass UserInput; + /*************************************************************************** ** All keyboard input is routed through the object pointed to by this ** keyboard class pointer. diff --git a/code/REDALERT/HOUSE.H b/code/REDALERT/HOUSE.H index 9ae63e1..d21a745 100644 --- a/code/REDALERT/HOUSE.H +++ b/code/REDALERT/HOUSE.H @@ -522,7 +522,8 @@ class HouseClass { ** This records information about the location and size of ** the base. */ - COORDINATE Center; // Center of the base. + COORDINATE Center; // Center COORDINATE of the base. + //CELL CenterCell; // Center CELL of the base. int Radius; // Average building distance from center (leptons). struct { int AirDefense; diff --git a/code/REDALERT/Image.h b/code/REDALERT/Image.h index 51700f2..9c01ed8 100644 --- a/code/REDALERT/Image.h +++ b/code/REDALERT/Image.h @@ -15,20 +15,18 @@ struct Image_t { int height; int renderwidth; int renderheight; - //unsigned char* buffer[MAX_HOUSE_COLORS][MAX_IMAGE_FRAMES]; + void* IconMapPtr; }; __forceinline Image_t::Image_t() { -// buffer = NULL; + IconMapPtr = NULL; numAnimFrames = 0; } __forceinline Image_t::~Image_t() { - //if (buffer) { - // delete buffer; - // buffer = NULL; - //} } Image_t* Image_LoadImage(const char* name, bool loadAnims = false, bool loadHouseColor = false); -Image_t* Image_CreateImageFrom8Bit(const char* name, int Width, int Height, unsigned char* data, unsigned char *remap = NULL); \ No newline at end of file +Image_t* Image_CreateImageFrom8Bit(const char* name, int Width, int Height, unsigned char* data, unsigned char *remap = NULL); +Image_t* Find_Image(const char* name); +void Image_Add8BitImage(Image_t* image, int HouseId, int ShapeID, int Width, int Height, unsigned char* data, unsigned char* remap); \ No newline at end of file diff --git a/code/REDALERT/KEY.CPP b/code/REDALERT/KEY.CPP index 1d96f9d..5424cc2 100644 --- a/code/REDALERT/KEY.CPP +++ b/code/REDALERT/KEY.CPP @@ -51,7 +51,8 @@ * WWKeyboardClass::Put_Mouse_Message -- Stores a mouse type message into the keyboard buffer* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ -#include "key.h" +//#include "key.h" +#include "FUNCTION.H" #include "monoc.h" @@ -102,10 +103,12 @@ unsigned short WWKeyboardClass::Buff_Get(void) while (!Check()) {} // wait for key in buffer unsigned short temp = Fetch_Element(); + /* if (Is_Mouse_Key(temp)) { MouseQX = Fetch_Element(); MouseQY = Fetch_Element(); } + */ return(temp); } @@ -192,7 +195,6 @@ bool WWKeyboardClass::Put(unsigned short key) return(false); } - /*********************************************************************************************** * WWKeyboardClass::Put_Key_Message -- Translates and inserts wParam into Keyboard Buffer * * * @@ -317,8 +319,9 @@ char WWKeyboardClass::To_ASCII(unsigned short key) int result = 1; int scancode = 0; - scancode = MapVirtualKey(key & 0xFF, 0); - result = ToAscii((UINT)(key & 0xFF), (UINT)scancode, (PBYTE)KeyState, (LPWORD)buffer, (UINT)0); + //scancode = MapVirtualKey(key & 0xFF, 0); + //result = ToAscii((UINT)(key & 0xFF), (UINT)scancode, (PBYTE)KeyState, (LPWORD)buffer, (UINT)0); + buffer[0] = UserInput.KeyB.ASCII; /* ** Restore the KeyState buffer back to pristine condition. diff --git a/code/REDALERT/KEY.H b/code/REDALERT/KEY.H index 67f4cef..3a09594 100644 --- a/code/REDALERT/KEY.H +++ b/code/REDALERT/KEY.H @@ -33,10 +33,6 @@ #ifndef KEYBOARD_H #define KEYBOARD_H -#ifndef WIN32 -#include "..\wwflat32\include\keyboard.h" -#else - #include /* @@ -44,18 +40,10 @@ ** November of '94. Until the compiler supports this, use the following ** definition. */ -#ifndef __BORLANDC__ -#ifndef TRUE_FALSE_DEFINED -#define TRUE_FALSE_DEFINED -enum {false=0,true=1}; -typedef int bool; -#endif -#endif - #pragma warning(disable : 4005) typedef enum { - WWKEY_SHIFT_BIT = 0x100, + WWKEY_SHIFT_BIT = 0x100, WWKEY_CTRL_BIT = 0x200, WWKEY_ALT_BIT = 0x400, WWKEY_RLS_BIT = 0x800, @@ -656,4 +644,3 @@ typedef enum KeyNumType { //extern WWKeyboardClass *_Kbd; #endif -#endif diff --git a/code/REDALERT/KEYBOARD.CPP b/code/REDALERT/KEYBOARD.CPP deleted file mode 100644 index 116fee4..0000000 --- a/code/REDALERT/KEYBOARD.CPP +++ /dev/null @@ -1,466 +0,0 @@ -// -// Copyright 2020 Electronic Arts Inc. -// -// TiberianDawn.DLL and RedAlert.dll and corresponding source code 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 3 of the License, or (at your option) any later version. - -// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed -// in the hope that it will be useful, but with permitted additional restrictions -// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT -// distributed with this program. You should have received a copy of the -// GNU General Public License along with permitted additional restrictions -// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection - -/* $Header: F:\projects\c&c0\vcs\code\conquer.cpv 4.74 23 Sep 1996 12:36:00 JOE_BOSTIC $ */ -/*********************************************************************************************** - * * - * Project Name : Westwood Keyboard Library * - * * - * File Name : KEYBOARD.CPP * - * * - * Programmer : Philip W. Gorrow * - * * - * Start Date : 10/16/95 * - * * - * Last Update : September 24, 1996 [JLB] * - * * - *---------------------------------------------------------------------------------------------* - * Functions: * - * WWKeyboardClass::Put -- Logic to insert a key into the keybuffer] * - * WWKeyboardClass::Get -- Logic to get a metakey from the buffer * - * WWKeyboardClass::Check -- Checks to see if a key is in the buffer * - * WWKeyboardClass::Put_Key_Message -- Translates and inserts wParam into Keyboard Buffer * - * WWKeyboardClass::Buff_Get -- Lowlevel function to get a key from key buffer * - * WWKeyboardClass::Get_Mouse_X -- Returns the mouses current x position in pixels * - * WWKeyboardClass::Get_Mouse_Y -- returns the mouses current y position in pixels * - * WWKeyboardClass::Get_Mouse_XY -- Returns the mouses x,y position via reference vars * - * Check_Key -- compatability routine for old 32 bit library * - * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - -#include "keyboard.h" - -#include "monoc.h" - -//void Message_Loop(void); - -WWKeyboardClass * _Kbd = NULL; - - -#define ARRAY_SIZE(x) int(sizeof(x)/sizeof(x[0])) - - -/*********************************************************************************************** - * WWKeyboardClass::WWKeyBoardClass -- Construction for Westwood Keyboard Class * - * * - * INPUT: none * - * * - * OUTPUT: none * - * * - * HISTORY: * - * 10/16/1995 PWG : Created. * - *=============================================================================================*/ -WWKeyboardClass::WWKeyboardClass(void) : - MouseQX(0), - MouseQY(0), - Head(0), - Tail(0) -// MState(0), -// Conditional(0), -// CurrentCursor(0) -{ - _Kbd = this; - - memset(KeyState, '\0', sizeof(KeyState)); -} - - -/*********************************************************************************************** - * WWKeyboardClass::Buff_Get -- Lowlevel function to get a key from key buffer * - * * - * INPUT: none * - * * - * OUTPUT: int - the key value that was pulled from buffer (includes bits) * * - * * - * WARNINGS: If the key was a mouse event MouseQX and MouseQY will be updated * - * * - * HISTORY: * - * 10/17/1995 PWG : Created. * - *=============================================================================================*/ -unsigned short WWKeyboardClass::Buff_Get(void) -{ - while (!Check()) {} // wait for key in buffer - - unsigned short temp = Fetch_Element(); - if (Is_Mouse_Key(temp)) { - MouseQX = Fetch_Element(); - MouseQY = Fetch_Element(); - } - return(temp); -} - - -bool WWKeyboardClass::Is_Mouse_Key(unsigned short key) -{ - key &= 0xFF; - return (key == VK_LBUTTON || key == VK_MBUTTON || key == VK_RBUTTON); -} - - -/*********************************************************************************************** - * WWKeyboardClass::Check -- Checks to see if a key is in the buffer * - * * - * INPUT: * - * * - * OUTPUT: * - * * - * WARNINGS: * - * * - * HISTORY: * - * 10/16/1995 PWG : Created. * - * 09/24/1996 JLB : Converted to new style keyboard system. * - *=============================================================================================*/ -unsigned short WWKeyboardClass::Check(void) const -{ - ((WWKeyboardClass *)this)->Fill_Buffer_From_System(); - if (Is_Buffer_Empty()) return(false); - return(Peek_Element()); -} - - -/*********************************************************************************************** - * WWKeyboardClass::Get -- Logic to get a metakey from the buffer * - * * - * INPUT: none * - * * - * OUTPUT: int - the meta key taken from the buffer. * - * * - * WARNINGS: This routine will not return until a keypress is received * - * * - * HISTORY: * - * 10/16/1995 PWG : Created. * - *=============================================================================================*/ -unsigned short WWKeyboardClass::Get(void) -{ - while (!Check()) {} // wait for key in buffer - return (Buff_Get()); -} - - -/*********************************************************************************************** - * WWKeyboardClass::Put -- Logic to insert a key into the keybuffer] * - * * - * INPUT: int - the key to insert into the buffer * - * * - * OUTPUT: bool - true if key is sucessfuly inserted. * - * * - * WARNINGS: none * - * * - * HISTORY: * - * 10/16/1995 PWG : Created. * - *=============================================================================================*/ -bool WWKeyboardClass::Put(unsigned short key) -{ - if (!Is_Buffer_Full()) { - Put_Element(key); - return(true); - } - return(false); -} - - -/*********************************************************************************************** - * WWKeyboardClass::Put_Key_Message -- Translates and inserts wParam into Keyboard Buffer * - * * - * INPUT: * - * * - * OUTPUT: * - * * - * WARNINGS: * - * * - * HISTORY: * - * 10/16/1995 PWG : Created. * - *=============================================================================================*/ -bool WWKeyboardClass::Put_Key_Message(unsigned short vk_key, bool release) -{ - // - // Get the status of all of the different keyboard modifiers. Note, only pay attention - // to numlock and caps lock if we are dealing with a key that is affected by them. Note - // that we do not want to set the shift, ctrl and alt bits for Mouse keypresses as this - // would be incompatible with the dos version. - // - if (!Is_Mouse_Key(vk_key)) { - if (((GetKeyState(VK_SHIFT) & 0x8000) != 0) || - ((GetKeyState(VK_CAPITAL) & 0x0008) != 0) || - ((GetKeyState(VK_NUMLOCK) & 0x0008) != 0)) { - - vk_key |= WWKEY_SHIFT_BIT; - } - if ((GetKeyState(VK_CONTROL) & 0x8000) != 0) { - vk_key |= WWKEY_CTRL_BIT; - } - if ((GetKeyState(VK_MENU) & 0x8000) != 0) { - vk_key |= WWKEY_ALT_BIT; - } - } - - if (release) { - vk_key |= WWKEY_RLS_BIT; - } - - // - // Finally use the put command to enter the key into the keyboard - // system. - // - return(Put(vk_key)); - - - -} - -#pragma warning (disable : 4065) -char WWKeyboardClass::To_ASCII(unsigned short key) -{ - /* - ** Released keys never translate into an ASCII value. - */ - if (key & WWKEY_RLS_BIT) { - return('\0'); - } - - /* - ** Set the KeyState buffer to reflect the shift bits stored in the key value. - */ - if (key & WWKEY_SHIFT_BIT) { - KeyState[VK_SHIFT] = 0x80; - } - if (key & WWKEY_CTRL_BIT) { - KeyState[VK_CONTROL] = 0x80; - } - if (key & WWKEY_ALT_BIT) { - KeyState[VK_MENU] = 0x80; - } - - /* - ** Ask windows to translate the key into an ASCII equivalent. - */ - char buffer[10]; - int result = 1; - int scancode = 0; - char override = '\0'; - - switch (key & 0xFF) { -// case KN_RETURN: -// override = KA_RETURN; -// break; - -// case KN_BACKSPACE: -// override = KA_BACKSPACE; -// break; - - default: - scancode = MapVirtualKey(key & 0xFF, 0); - result = ToAscii((UINT)(key & 0xFF), (UINT)scancode, (PBYTE)KeyState, (LPWORD)buffer, (UINT)0); - break; - } - - /* - ** Restore the KeyState buffer back to pristine condition. - */ - if (key & WWKEY_SHIFT_BIT) { - KeyState[VK_SHIFT] = 0; - } - if (key & WWKEY_CTRL_BIT) { - KeyState[VK_CONTROL] = 0; - } - if (key & WWKEY_ALT_BIT) { - KeyState[VK_MENU] = 0; - } - - /* - ** If Windows could not perform the translation as expected, then - ** return with a null ASCII value. - */ - if (result != 1) { - return('\0'); - } - - if (override != 0) { - return(override); - } - - return(buffer[0]); -} - - -bool WWKeyboardClass::Down(unsigned short key) -{ - return(GetAsyncKeyState(key & 0xFF) == 0 ? false : true); -} - - -extern "C" { - void __cdecl Stop_Execution (void); -} - - - -unsigned short WWKeyboardClass::Fetch_Element(void) -{ - unsigned short val = 0; - if (Head != Tail) { - val = Buffer[Head]; - - Head = (Head + 1) % ARRAY_SIZE(Buffer); - } - return(val); -} - - -unsigned short WWKeyboardClass::Peek_Element(void) const -{ - if (!Is_Buffer_Empty()) { - return(Buffer[Head]); - } - return(0); -} - - -bool WWKeyboardClass::Put_Element(unsigned short val) -{ - if (!Is_Buffer_Full()) { - int temp = (Tail+1) % ARRAY_SIZE(Buffer); - Buffer[Tail] = val; - Tail = temp; - return(true); - } - return(false); -} - - -bool WWKeyboardClass::Is_Buffer_Full(void) const -{ - if ((Tail + 1) % ARRAY_SIZE(Buffer) == Head) { - return(true); - } - return(false); -} - - -bool WWKeyboardClass::Is_Buffer_Empty(void) const -{ - if (Head == Tail) { - return(true); - } - return(false); -} - - -void WWKeyboardClass::Fill_Buffer_From_System(void) -{ - if (!Is_Buffer_Full()) { - MSG msg; - while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { - if (!GetMessage( &msg, NULL, 0, 0 )) { - return; - } - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } -} - - -void WWKeyboardClass::Clear(void) -{ - Head = Tail; -} - - -void WWKeyboardClass::Message_Handler(HWND , UINT message, UINT wParam, LONG lParam) -{ - switch (message) { - case WM_SYSKEYDOWN: - case WM_KEYDOWN: - if ( wParam==VK_SCROLL ){ - Stop_Execution(); - } else { - Put_Key_Message((unsigned short)wParam); - } - break; - - case WM_SYSKEYUP: - case WM_KEYUP: - Put_Key_Message((unsigned short)wParam, true); - break; - - case WM_LBUTTONDOWN: - Put_Key_Message(VK_LBUTTON); - Put(LOWORD(lParam)); - Put(HIWORD(lParam)); - break; - - case WM_LBUTTONUP: - Put_Key_Message(VK_LBUTTON, true); - Put(LOWORD(lParam)); - Put(HIWORD(lParam)); - break; - - case WM_LBUTTONDBLCLK: - Put_Key_Message(VK_LBUTTON, true); - Put(LOWORD(lParam)); - Put(HIWORD(lParam)); - Put_Key_Message(VK_LBUTTON, true); - Put(LOWORD(lParam)); - Put(HIWORD(lParam)); - break; - - case WM_MBUTTONDOWN: - Put_Key_Message(VK_MBUTTON); - Put(LOWORD(lParam)); - Put(HIWORD(lParam)); - break; - - case WM_MBUTTONUP: - Put_Key_Message(VK_MBUTTON, true); - Put(LOWORD(lParam)); - Put(HIWORD(lParam)); - break; - - case WM_MBUTTONDBLCLK: - Put_Key_Message(VK_MBUTTON, true); - Put(LOWORD(lParam)); - Put(HIWORD(lParam)); - Put_Key_Message(VK_MBUTTON, true); - Put(LOWORD(lParam)); - Put(HIWORD(lParam)); - break; - - case WM_RBUTTONDOWN: - Put_Key_Message(VK_RBUTTON); - Put(LOWORD(lParam)); - Put(HIWORD(lParam)); - break; - - case WM_RBUTTONUP: - Put_Key_Message(VK_RBUTTON, true); - Put(LOWORD(lParam)); - Put(HIWORD(lParam)); - break; - - case WM_RBUTTONDBLCLK: - Put_Key_Message(VK_RBUTTON, true); - Put(LOWORD(lParam)); - Put(HIWORD(lParam)); - Put_Key_Message(VK_RBUTTON, true); - Put(LOWORD(lParam)); - Put(HIWORD(lParam)); - break; - -// case WM_MOUSEMOVE: -// if (CurrentCursor) -// SetCursor(CurrentCursor); -// break; - } -} diff --git a/code/REDALERT/LOADDLG.CPP b/code/REDALERT/LOADDLG.CPP index 368059c..cd0e812 100644 --- a/code/REDALERT/LOADDLG.CPP +++ b/code/REDALERT/LOADDLG.CPP @@ -111,8 +111,9 @@ int LoadOptionsClass::Process(void) */ int d_dialog_w = 250 * RESFACTOR; // dialog width int d_dialog_h = 156 * RESFACTOR; // dialog height - int d_dialog_x = (((320 * RESFACTOR) - d_dialog_w) / 2); // centered x-coord - int d_dialog_y = (((200 * RESFACTOR) - d_dialog_h) / 2); // centered y-coord + + int d_dialog_x = ((SeenBuff.Get_Width() - d_dialog_w) / 2); + int d_dialog_y = ((SeenBuff.Get_Height() - d_dialog_h) / 2); int d_dialog_cx = d_dialog_x + (d_dialog_w / 2); // coord of x-center int d_txt8_h = 11 * RESFACTOR; // ht of 8-pt text diff --git a/code/REDALERT/MAPEDDLG.CPP b/code/REDALERT/MAPEDDLG.CPP index e19b0f6..7d80932 100644 --- a/code/REDALERT/MAPEDDLG.CPP +++ b/code/REDALERT/MAPEDDLG.CPP @@ -719,7 +719,6 @@ static int map_y2; // map coords y2, pixel coords bool sizemap_cancel = false; // true = user cancels bool sizemap_process = true; void Imgui_SizeMap(void) { - extern int mousex, mousey; bool toolActive = false; ImGuiStyle& style = ImGui::GetStyle(); diff --git a/code/REDALERT/MAPEDIT.CPP b/code/REDALERT/MAPEDIT.CPP index d8f7dfe..ff3c30c 100644 --- a/code/REDALERT/MAPEDIT.CPP +++ b/code/REDALERT/MAPEDIT.CPP @@ -1506,7 +1506,6 @@ int mainmenu_x = -1; int mainmenu_y = -1; void Imgui_MapEdit_MainMenu(void) { - extern int mousex, mousey; bool toolActive = false; ImGuiStyle& style = ImGui::GetStyle(); @@ -1559,15 +1558,14 @@ void Imgui_MapEdit_MainMenu(void) { *=========================================================================*/ void MapEditClass::Main_Menu(void) { - extern int mousex, mousey; int selection; // option the user picks bool process; // menu stays up while true int rc; Imgui_Dialog_Function = Imgui_MapEdit_MainMenu; mainmenu_selection = -1; - mainmenu_x = mousex; - mainmenu_y = mousey; + mainmenu_x = UserInput.Mouse.X; + mainmenu_y = UserInput.Mouse.Y; /* ** Main Menu loop diff --git a/code/REDALERT/MAPSEL.CPP b/code/REDALERT/MAPSEL.CPP index d893c50..9d1989a 100644 --- a/code/REDALERT/MAPSEL.CPP +++ b/code/REDALERT/MAPSEL.CPP @@ -326,12 +326,12 @@ int Mouse_Over_Spot(int house, int scenario) { int retval = -1; for (int selection = 0; selection < 3 && MapCoords[house][scenario][selection].x != -1; selection++) { - int mousex = Get_Mouse_X() / RESFACTOR; + int mousex = UserInput.Mouse.X / RESFACTOR; int mousey = Get_Mouse_Y() / RESFACTOR; - if (mousex >= MapCoords[house][scenario][selection].x && - mousey >= MapCoords[house][scenario][selection].y && - mousex <= MapCoords[house][scenario][selection].x+11 && - mousey <= MapCoords[house][scenario][selection].y+9) { + if (UserInput.Mouse.X >= MapCoords[house][scenario][selection].x && + UserInput.Mouse.Y >= MapCoords[house][scenario][selection].y && + UserInput.Mouse.X <= MapCoords[house][scenario][selection].x+11 && + UserInput.Mouse.Y <= MapCoords[house][scenario][selection].y+9) { retval = selection; break; diff --git a/code/REDALERT/MENUS.CPP b/code/REDALERT/MENUS.CPP index aa49cd3..7c4603c 100644 --- a/code/REDALERT/MENUS.CPP +++ b/code/REDALERT/MENUS.CPP @@ -267,8 +267,8 @@ int Check_Menu(int menu, char const * text[], char *, long field, int index, Key mx2=mx1+(menuptr[ITEMWIDTH]*FontWidth)-1; /* structure as */ my2=my1+(menuptr[ITEMSHIGH]*menuskip)-1; /* necessary */ - tempy=Get_Mouse_Y(); - if (Coordinates_In_Region(Get_Mouse_X(), tempy, mx1, my1, mx2, my2)&& MenuUpdate) { + tempy=UserInput.Mouse.Y; + if (Coordinates_In_Region(UserInput.Mouse.X, tempy, mx1, my1, mx2, my2)&& MenuUpdate) { newitem=(tempy-my1)/menuskip; } @@ -299,8 +299,8 @@ int Check_Menu(int menu, char const * text[], char *, long field, int index, Key */ case KN_RMOUSE: case KN_LMOUSE: - if (Coordinates_In_Region(Keyboard->MouseQX, Keyboard->MouseQY, mx1, my1, mx2, my2)) { - newitem = (Keyboard->MouseQY - my1) / menuskip; + if (Coordinates_In_Region(UserInput.Mouse.X, UserInput.Mouse.Y, mx1, my1, mx2, my2)) { + newitem = (UserInput.Mouse.Y - my1) / menuskip; } else { UnknownKey = key; // Pass the unprocessed button click back. break; @@ -772,7 +772,7 @@ int Main_Menu(unsigned long ) case KN_LMOUSE: - if (Coordinates_In_Region(Keyboard->MouseQX, Keyboard->MouseQY, + if (Coordinates_In_Region(UserInput.Mouse.X, UserInput.Mouse.Y, 9*RESFACTOR, 10*RESFACTOR, 79*RESFACTOR, 24*RESFACTOR)){ @@ -786,7 +786,7 @@ int Main_Menu(unsigned long ) // secret ANT missions if (Is_Counterstrike_Installed() == true) { - if ((Keyboard->Down(KN_LSHIFT) || Keyboard->Down(KN_RSHIFT)) && Coordinates_In_Region(Keyboard->MouseQX, Keyboard->MouseQY, 260*RESFACTOR, 0, 320*RESFACTOR, 50*RESFACTOR)) { + if ((Keyboard->Down(KN_LSHIFT) || Keyboard->Down(KN_RSHIFT)) && Coordinates_In_Region(UserInput.Mouse.X, UserInput.Mouse.Y, 260*RESFACTOR, 0, 320*RESFACTOR, 50*RESFACTOR)) { AntsEnabled = true; process = false; retval = 2; // To match SEL_START_NEW_GAME diff --git a/code/REDALERT/MPLAYER.CPP b/code/REDALERT/MPLAYER.CPP index 9b0b91e..88bebf3 100644 --- a/code/REDALERT/MPLAYER.CPP +++ b/code/REDALERT/MPLAYER.CPP @@ -617,10 +617,7 @@ int Surrender_Dialog(int text) //------------------------------------------------------------------------ enum { D_DIALOG_W = 240*RESFACTOR, // dialog width - D_DIALOG_H = 63*RESFACTOR, // dialog height - D_DIALOG_X = ((320*RESFACTOR - D_DIALOG_W) / 2),// centered x-coord - D_DIALOG_Y = ((200*RESFACTOR - D_DIALOG_H) / 2),// centered y-coord - D_DIALOG_CX = D_DIALOG_X + (D_DIALOG_W / 2), // coord of x-center + D_DIALOG_H = 63*RESFACTOR, // dialog height D_TXT6_H = 7*RESFACTOR, // ht of 6-pt text D_MARGIN = 5*RESFACTOR, // margin width/height @@ -628,13 +625,9 @@ int Surrender_Dialog(int text) D_OK_W = 45*RESFACTOR, // OK width D_OK_H = 9*RESFACTOR, // OK height - D_OK_X = D_DIALOG_CX - D_OK_W - 5*RESFACTOR, // OK x - D_OK_Y = D_DIALOG_Y + D_DIALOG_H - D_OK_H - D_MARGIN*2, // OK y D_CANCEL_W = 45*RESFACTOR, // Cancel width D_CANCEL_H = 9*RESFACTOR, // Cancel height - D_CANCEL_X = D_DIALOG_CX + 5*RESFACTOR, // Cancel x - D_CANCEL_Y = D_DIALOG_Y + D_DIALOG_H - D_CANCEL_H - D_MARGIN*2, // Cancel y }; //------------------------------------------------------------------------ @@ -645,6 +638,16 @@ int Surrender_Dialog(int text) BUTTON_CANCEL, }; + int D_DIALOG_X = (SeenBuff.Get_Width() - D_DIALOG_W) / 2; // centered x-coord + int D_DIALOG_Y = (SeenBuff.Get_Height() - D_DIALOG_H) / 2; // centered y-coord + int D_DIALOG_CX = D_DIALOG_X + (D_DIALOG_W / 2); // coord of x-center + + int D_OK_X = D_DIALOG_CX - D_OK_W - 5 * RESFACTOR; // OK x + int D_OK_Y = D_DIALOG_Y + D_DIALOG_H - D_OK_H - D_MARGIN * 2; // OK y + + int D_CANCEL_X = D_DIALOG_CX + 5 * RESFACTOR; // Cancel x + int D_CANCEL_Y = D_DIALOG_Y + D_DIALOG_H - D_CANCEL_H - D_MARGIN * 2; // Cancel y + //------------------------------------------------------------------------ // Buttons //------------------------------------------------------------------------ diff --git a/code/REDALERT/NEWBLIT.CPP b/code/REDALERT/NEWBLIT.CPP index 693953c..cccf6d0 100644 --- a/code/REDALERT/NEWBLIT.CPP +++ b/code/REDALERT/NEWBLIT.CPP @@ -18,10 +18,10 @@ void GL_ResetClipRect(void) { ImGui::GetForegroundDrawList()->PopClipRect(); } -void GL_RenderImage(Image_t* image, int x, int y, int width, int height, int colorRemap) { +void GL_RenderImage(Image_t* image, int x, int y, int width, int height, int colorRemap, int shapeId) { ImVec2 mi(x, y); ImVec2 ma(x + width, y + height); - ImGui::GetForegroundDrawList()->AddImage((ImTextureID)image->image[colorRemap][0], mi, ma); + ImGui::GetForegroundDrawList()->AddImage((ImTextureID)image->image[colorRemap][shapeId], mi, ma); } void GL_FillRect(int color, int x, int y, int width, int height) { diff --git a/code/REDALERT/NEWBLIT.H b/code/REDALERT/NEWBLIT.H index b3e9508..36cab3a 100644 --- a/code/REDALERT/NEWBLIT.H +++ b/code/REDALERT/NEWBLIT.H @@ -2,7 +2,7 @@ // struct Image_t; -void GL_RenderImage(Image_t* image, int x, int y, int width, int height, int colorRemap = 0); +void GL_RenderImage(Image_t* image, int x, int y, int width, int height, int colorRemap = 0, int shapeId = 0); void GL_DrawText(int color, int x, int y, char* text); void GL_FillRect(int color, int x, int y, int width, int height); void GL_DrawLine(int color, int x, int y, int dx, int dy); diff --git a/code/REDALERT/POWER.CPP b/code/REDALERT/POWER.CPP index 1f55d49..7499cb5 100644 --- a/code/REDALERT/POWER.CPP +++ b/code/REDALERT/POWER.CPP @@ -208,6 +208,8 @@ void PowerClass::Draw_It(bool complete) power_height = Bound(power_height, 0, PowerButton.Height - 2); drain_height = Bound(drain_height, 0, PowerButton.Height - 2); + bottom -= (15 * RESFACTOR); + /* ** Draw the power output graphic on top of the power bar framework. */ diff --git a/code/REDALERT/RADAR.CPP b/code/REDALERT/RADAR.CPP index 7626dd6..2c40ad3 100644 --- a/code/REDALERT/RADAR.CPP +++ b/code/REDALERT/RADAR.CPP @@ -148,35 +148,23 @@ RadarClass::RadarClass(void) : void RadarClass::One_Time(void) { RadWidth = 80 * RESFACTOR; - RadHeight = 70 * RESFACTOR; + RadHeight = 70 * RESFACTOR; RadX = SeenBuff.Get_Width() - RadWidth; RadY = 7 * RESFACTOR; - RadPWidth = 64 * RESFACTOR; - RadPHeight = 64 * RESFACTOR; - #ifdef WIN32 - RadOffX = 6; - RadOffY = 7; - RadIWidth = 128+18;//************ - RadIHeight = 128+2;//************ - #else - RadOffX = 4; - RadOffY = 1; - RadIWidth = 72; - RadIHeight = 69; - #endif + RadPWidth = 64 * RESFACTOR; + RadPHeight = 64 * RESFACTOR; + + RadOffX = 6; + RadOffY = 7; + RadIWidth = 128+18;//************ + RadIHeight = 128+2;//************ DisplayClass::One_Time(); -#ifdef OBSOLETE - RadarButton.X = RadX+RadOffX; - RadarButton.Y = RadY+RadOffY; - RadarButton.Width = RadIWidth; - RadarButton.Height = RadIHeight; -#else + RadarButton.X = RadX; RadarButton.Y = RadY; RadarButton.Width = RadWidth; RadarButton.Height = RadHeight; -#endif } @@ -1784,13 +1772,8 @@ int RadarClass::RTacticalClass::Action(unsigned flags, KeyNumType & key) ** or release event, special mouse queuing storage variables are used. Other ** events must use the current mouse position globals. */ - if (flags & (LEFTPRESS|LEFTRELEASE|RIGHTPRESS|RIGHTRELEASE)) { - x = Keyboard->MouseQX; - y = Keyboard->MouseQY; - } else { - x = Get_Mouse_X(); - y = Get_Mouse_Y(); - } + x = Get_Mouse_X(); + y = Get_Mouse_Y(); /* ** See if the mouse is over the radar general area, but not yet diff --git a/code/REDALERT/SCENARIO.CPP b/code/REDALERT/SCENARIO.CPP index baf5d9a..79d37cd 100644 --- a/code/REDALERT/SCENARIO.CPP +++ b/code/REDALERT/SCENARIO.CPP @@ -398,7 +398,7 @@ bool Start_Scenario(char * name, bool briefing) if (Scen.BriefMovie != VQ_NONE) { sprintf(buffer, "%s.VQA", VQName[Scen.BriefMovie]); } - if (Session.Type == GAME_NORMAL && Scen.BriefMovie == VQ_NONE || !CCFileClass(buffer).Is_Available()) { + if (Session.Type == GAME_NORMAL && ( Scen.BriefMovie == VQ_NONE || !CCFileClass(buffer).Is_Available() ) ) { /* ** Make sure the mouse is visible before showing the restatement. */ @@ -569,7 +569,10 @@ bool Read_Scenario(char * name) } #endif Fill_In_Data(); - Map.Set_View_Dimensions(0, 0, Map.MapCellWidth, Map.MapCellHeight); + + // BL 2020-06-15 : not needed !! + //Map.Set_View_Dimensions(0, 0, Map.MapCellWidth, Map.MapCellHeight); + } else { #if (1) @@ -639,10 +642,15 @@ void Fill_In_Data(void) */ if (!Debug_Map) { Map.SidebarClass::Activate(1); -// if (Session.Type == GAME_NORMAL) { + if (Session.Type == GAME_NORMAL) { Scen.Views[0] = Scen.Views[1] = Scen.Views[2] = Scen.Views[3] = Scen.Waypoint[WAYPT_HOME]; Map.Set_Tactical_Position(Cell_Coord((Scen.Waypoint[WAYPT_HOME] - (MAP_CELL_W * 4 * RESFACTOR)) - (5*RESFACTOR))); -// } + } + if (Session.Type == GAME_SKIRMISH) { + CELL PlayerCenterCell = XY_Cell( Coord_XCell(PlayerPtr->Center), Coord_YCell( PlayerPtr->Center) ); + Scen.Views[0] = Scen.Views[1] = Scen.Views[2] = Scen.Views[3] = PlayerCenterCell; + Map.Set_Tactical_Position( Cell_Coord( (PlayerCenterCell - (MAP_CELL_W * 4 * RESFACTOR) ) - (5 * RESFACTOR) ) ); + } } #endif @@ -757,7 +765,9 @@ void Fill_In_Data(void) *=============================================================================================*/ void Post_Load_Game(int load_multi) { - Map.Set_View_Dimensions(0, 0, Map.MapCellWidth, Map.MapCellHeight); + // BL 2020-06-15 : not needed !! + //Map.Set_View_Dimensions(0, 0, Map.MapCellWidth, Map.MapCellHeight); + // // Do NOT call Overpass if we're loading a multiplayer game; it calls the // random # generator, which throws the games out of sync if they were @@ -910,11 +920,6 @@ void Do_Win(void) Session.GameName[0] = 0; } - /* - ** Determine a cosmetic center point for the text. - */ - int x = Map.TacPixelX + (Lepton_To_Pixel(Map.TacLeptonWidth)/2); - /* ** Hack section. If it's allied scenario 10, variation A, then skip the ** score and map selection, don't increment scenario, and set it to @@ -933,7 +938,7 @@ void Do_Win(void) Map.Flag_To_Redraw (true); Map.Render(); #ifdef WIN32 - Fancy_Text_Print(TXT_SCENARIO_WON, x, 90*RESFACTOR, &ColorRemaps[PCOLOR_RED], TBLACK, TPF_CENTER|TPF_VCR|TPF_USE_GRAD_PAL|TPF_DROPSHADOW); + Fancy_Text_Print(TXT_SCENARIO_WON, (SeenBuff.Get_Width() / 2), 90*RESFACTOR, &ColorRemaps[PCOLOR_RED], TBLACK, TPF_CENTER|TPF_VCR|TPF_USE_GRAD_PAL|TPF_DROPSHADOW); #else Fancy_Text_Print(TXT_MISSION, x, 90*RESFACTOR, &ColorRemaps[PCOLOR_RED], TBLACK, TPF_CENTER|TPF_VCR|TPF_USE_GRAD_PAL|TPF_DROPSHADOW); Fancy_Text_Print(TXT_HACKHACK, x, 110*RESFACTOR, &ColorRemaps[PCOLOR_RED], TBLACK, TPF_CENTER|TPF_VCR|TPF_USE_GRAD_PAL|TPF_DROPSHADOW); diff --git a/code/REDALERT/SIDEBAR.CPP b/code/REDALERT/SIDEBAR.CPP index 916368f..f3db0df 100644 --- a/code/REDALERT/SIDEBAR.CPP +++ b/code/REDALERT/SIDEBAR.CPP @@ -325,7 +325,7 @@ void SidebarClass::Init_IO(void) Zoom.IsSticky = true; Zoom.ID = BUTTON_ZOOM; - Zoom.X = 1024 - (640 - ((0x24c/2)*RESFACTOR)); + Zoom.X = ScreenWidth - (640 - ((0x24c/2)*RESFACTOR)); Zoom.Y = (0x96/2)*RESFACTOR; Zoom.IsPressed = false; Zoom.Set_Shape(MFCD::Retrieve("MAP.SHP")); @@ -1030,7 +1030,8 @@ bool SidebarClass::Activate(int control) ** activate it on the left side of the screen. */ if (IsSidebarActive /*&& X*/) { - Set_View_Dimensions(0, 0, (((ScreenWidth/2)-SIDE_WIDTH)/ICON_PIXEL_W) * RESFACTOR); + Set_View_Dimensions( 0, 8 * RESFACTOR, SeenBuff.Get_Width() - ( SIDE_WIDTH * RESFACTOR ) ); + IsToRedraw = true; Help_Text(TXT_NONE); Repair.Zap(); diff --git a/code/REDALERT/TAB.CPP b/code/REDALERT/TAB.CPP index f408886..8527a0e 100644 --- a/code/REDALERT/TAB.CPP +++ b/code/REDALERT/TAB.CPP @@ -139,10 +139,9 @@ void TabClass::Draw_Credits_Tab(void) int width = SeenBuff.Get_Width(); CC_Draw_Shape(TabShape, Map.MoneyFlashTimer > 1 ? 8 : 6, width - (EVA_WIDTH * RESFACTOR), 0, WINDOW_MAIN, SHAPE_NORMAL); - if (Scen.MissionTimer.Is_Active()) { bool light = ((int)Scen.MissionTimer < TICKS_PER_MINUTE * Rule.TimerWarning) || Map.FlasherTimer > 0; - CC_Draw_Shape(TabShape, light ? 4 : 2, 320, 0, WINDOW_MAIN, SHAPE_NORMAL); + CC_Draw_Shape(TabShape, light ? 4 : 2, width - ( ( EVA_WIDTH * 2 ) * RESFACTOR) , 0, WINDOW_MAIN, SHAPE_NORMAL); } } diff --git a/code/REDALERT/TDATA.CPP b/code/REDALERT/TDATA.CPP index cc463f2..3dadc71 100644 --- a/code/REDALERT/TDATA.CPP +++ b/code/REDALERT/TDATA.CPP @@ -49,6 +49,7 @@ #include "function.h" #include "terrain.h" #include "type.h" +#include "Image.h" static short const _List000011101000[] = {MAP_CELL_W, MAP_CELL_W+1, MAP_CELL_W+2, MAP_CELL_W*2, REFRESH_EOL}; @@ -689,6 +690,12 @@ void TerrainTypeClass::Init(TheaterType theater) _makepath(fullname, NULL, NULL, terrain.IniName, Theaters[theater].Suffix); ((void const *&)terrain.ImageData) = MFCD::Retrieve(fullname); + { + char tmp[512]; + sprintf(tmp, "icon_%s", fullname); + ((void const*&)terrain.HDImageData) = Load_Stamp(fullname, terrain.ImageData); + } + IsTheaterShape = true; //Let Build_Frame know that this is a theater specific shape if (terrain.RadarIcon != NULL) delete[] (char *)terrain.RadarIcon; ((void const *&)terrain.RadarIcon) = Get_Radar_Icon(terrain.Get_Image_Data(), 0, 1, 3); diff --git a/code/REDALERT/TECHNO.CPP b/code/REDALERT/TECHNO.CPP index 7f9ea58..29d6634 100644 --- a/code/REDALERT/TECHNO.CPP +++ b/code/REDALERT/TECHNO.CPP @@ -138,11 +138,6 @@ */ #define MAX_UNCLOAK_STAGE 38 -//Added for getting the input for special character keys from the client -// - 6/26/2019 JAS -extern bool DLL_Export_Get_Input_Key_State(KeyNumType key); - - /*************************************************************************** ** These are the pointers to the special shape data that the units may need. */ @@ -3523,14 +3518,9 @@ ActionType TechnoClass::What_Action(ObjectClass const * object) const return(ACTION_SELF); } - //bool altdown = (Keyboard->Down(Options.KeyForceMove1) || Keyboard->Down(Options.KeyForceMove2)); - //bool ctrldown = (Keyboard->Down(Options.KeyForceAttack1) || Keyboard->Down(Options.KeyForceAttack2)); - //bool shiftdown = (Keyboard->Down(Options.KeySelect1) || Keyboard->Down(Options.KeySelect2)); - //Added for getting the input for special character keys from the client - // - 6/26/2019 JAS - bool altdown = DLL_Export_Get_Input_Key_State(KN_LALT); - bool ctrldown = DLL_Export_Get_Input_Key_State(KN_LCTRL); - bool shiftdown = DLL_Export_Get_Input_Key_State(KN_LSHIFT); + bool altdown = (Keyboard->Down(Options.KeyForceMove1) || Keyboard->Down(Options.KeyForceMove2)); + bool ctrldown = (Keyboard->Down(Options.KeyForceAttack1) || Keyboard->Down(Options.KeyForceAttack2)); + bool shiftdown = (Keyboard->Down(Options.KeySelect1) || Keyboard->Down(Options.KeySelect2)); /* ** Special guard area mission is possible if both the control and the @@ -3646,14 +3636,9 @@ ActionType TechnoClass::What_Action(CELL cell) const CellClass const * cellptr = &Map[cell]; OverlayTypeClass const * optr = NULL; - //bool altdown = (Keyboard->Down(Options.KeyForceMove1) || Keyboard->Down(Options.KeyForceMove2)); - //bool ctrldown = (Keyboard->Down(Options.KeyForceAttack1) || Keyboard->Down(Options.KeyForceAttack2)); - //bool shiftdown = (Keyboard->Down(Options.KeySelect1) || Keyboard->Down(Options.KeySelect2)); - //Added for getting the input for special character keys from the client - // - 6/26/2019 JAS - bool altdown = DLL_Export_Get_Input_Key_State(KN_LALT); - bool ctrldown = DLL_Export_Get_Input_Key_State(KN_LCTRL); - bool shiftdown = DLL_Export_Get_Input_Key_State(KN_LSHIFT); + bool altdown = (Keyboard->Down(Options.KeyForceMove1) || Keyboard->Down(Options.KeyForceMove2)); + bool ctrldown = (Keyboard->Down(Options.KeyForceAttack1) || Keyboard->Down(Options.KeyForceAttack2)); + bool shiftdown = (Keyboard->Down(Options.KeySelect1) || Keyboard->Down(Options.KeySelect2)); /* ** Disable recognizing the key forced fire option when dealing with buildings. @@ -6733,7 +6718,7 @@ bool TechnoTypeClass::Read_INI(CCINIClass & ini) SightRange = ini.Get_Int(Name(), "Sight", SightRange); Level = ini.Get_Int(Name(), "TechLevel", Level); MaxSpeed = MPHType(_Scale_To_256(ini.Get_Int(Name(), "Speed", fixed(MaxSpeed, 256) * 100))); - Cost = ini.Get_Int(Name(), "Cost", Cost); + Cost = 50; // ini.Get_Int(Name(), "Cost", Cost); MaxAmmo = ini.Get_Int(Name(), "Ammo", MaxAmmo); Risk = Reward = Points = ini.Get_Int(Name(), "Points", Points); Ownable = ini.Get_Owners(Name(), "Owner", Ownable); diff --git a/code/REDALERT/TILESET.CPP b/code/REDALERT/TILESET.CPP index 95f639e..a17da1d 100644 --- a/code/REDALERT/TILESET.CPP +++ b/code/REDALERT/TILESET.CPP @@ -32,8 +32,6 @@ class GraphicViewPortClass; #define TD_TILESET_CHECK 0x20 -Image_t* tileset_icon_cache[4096]; - /** * @brief union is to handle the parts of the header which vary between TD and RA format tiles. */ @@ -103,8 +101,7 @@ static int IconSize; static int IconCount; void __cdecl Init_Stamps(IconControlType* iconset) -{ - memset(&tileset_icon_cache, 0, sizeof(tileset_icon_cache)); +{ if (iconset && LastIconset != iconset) { IconCount = (iconset->count); IconWidth = (iconset->width); @@ -193,51 +190,67 @@ void __cdecl Buffer_Draw_Stamp2(GraphicViewPortClass& viewport, IconControlType* } } +struct Image_t *__cdecl Load_Stamp(const char *name, const void* icondata) +{ + IconControlType* tileset = (IconControlType*)icondata; + + if (!tileset) { + return NULL; + } + + if (LastIconset != tileset) { + Init_Stamps(tileset); + } + + + int icon_index = 0; + + if (icon_index >= IconCount) { + return NULL; + } + + uint8_t* src = &StampPtr[IconSize * icon_index]; + + // Check to see if the image is already loaded. + { + Image_t* image = Find_Image(name); + if (image) { + return image; + } + } + + Image_t *image = Image_CreateImageFrom8Bit(name, IconWidth, IconHeight, (unsigned char*)src); + image->IconMapPtr = MapPtr; + if (IconCount == 1) + return image; + + for (int i = 1; i < IconCount; i++) { + icon_index = i; + src = &StampPtr[IconSize * icon_index]; + Image_Add8BitImage(image, 0, i, IconWidth, IconHeight, src, NULL); + } + + return image; +} + void __cdecl Buffer_Draw_Stamp_Clip2(GraphicViewPortClass& viewport, const void *icondata, int icon, int x, int y, const void* remapper, int left, int top, int right, int bottom) { - const TemplateTypeClass* ttype = (TemplateTypeClass const*)icondata; - IconControlType* tileset = (IconControlType * )ttype->Get_Image_Data(); - - // This is a awful hack, but need type info to generate unique id's for tileset generation. - if (icondata == DisplayClass::TransIconset) { - tileset = (IconControlType*)DisplayClass::TransIconset; - ttype = NULL; - } - - if (!tileset) { - return; - } - - if (LastIconset != tileset) { - Init_Stamps(tileset); - } - - int icon_index = MapPtr != nullptr ? MapPtr[icon] : icon; - - if (icon_index < IconCount) { + Image_t* iconImage = (Image_t*)icondata; + uint8_t* MapPtr = (uint8_t * )iconImage->IconMapPtr; + int icon_index = MapPtr != nullptr ? MapPtr[icon] : icon; + { int blit_height = IconHeight; int blit_width = IconWidth; - uint8_t* src = &StampPtr[IconSize * icon_index]; + int width = left + right; int xstart = left + x; int height = top + bottom; int ystart = top + y; - // - if (!tileset_icon_cache[icon_index]) { - char tmp[512]; - if (ttype != NULL) { - sprintf(tmp, "icon_%d_%d", ttype->Type, icon_index); - } - else { - sprintf(tmp, "icon_%d_%d", icondata, icon_index); - } - tileset_icon_cache[icon_index] = Image_CreateImageFrom8Bit(tmp, IconWidth, IconHeight, (unsigned char *)src); - } - + if (xstart < width && ystart < height && IconHeight + ystart > top && IconWidth + xstart > left) { if (xstart < left) { - src += left - xstart; +// src += left - xstart; blit_width -= left - xstart; xstart = left; } @@ -251,7 +264,7 @@ void __cdecl Buffer_Draw_Stamp_Clip2(GraphicViewPortClass& viewport, const void if (top > ystart) { blit_height = IconHeight - (top - ystart); - src += IconWidth * (top - ystart); + // src += IconWidth * (top - ystart); ystart = top; } @@ -308,7 +321,7 @@ void __cdecl Buffer_Draw_Stamp_Clip2(GraphicViewPortClass& viewport, const void //} GL_SetClipRect(xstart, ystart, blit_width, blit_height); - GL_RenderImage(tileset_icon_cache[icon_index], xstart, ystart, blit_width, blit_height); + GL_RenderImage(iconImage, xstart, ystart, blit_width, blit_height, 0, icon_index); GL_ResetClipRect(); } } diff --git a/code/REDALERT/WIN32LIB/DRAWBUFF.H b/code/REDALERT/WIN32LIB/DRAWBUFF.H index 38b46d4..72ace4c 100644 --- a/code/REDALERT/WIN32LIB/DRAWBUFF.H +++ b/code/REDALERT/WIN32LIB/DRAWBUFF.H @@ -61,6 +61,8 @@ extern "C" { void * __cdecl Get_Font_Palette_Ptr ( void ); } +struct Image_t* __cdecl Load_Stamp(const char* name, const void* icondata); + extern GraphicViewPortClass *LogicPage; extern BOOL AllowHardwareBlitFills; #endif diff --git a/code/REDALERT/WIN32LIB/MOUSEWW.CPP b/code/REDALERT/WIN32LIB/MOUSEWW.CPP index da56f02..91c07fb 100644 --- a/code/REDALERT/WIN32LIB/MOUSEWW.CPP +++ b/code/REDALERT/WIN32LIB/MOUSEWW.CPP @@ -31,15 +31,15 @@ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #include "imgui.h" -#include "mouse.h" +#include "../FUNCTION.H" +#include "MOUSE.H" #include "../image.h" -#include 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; +extern bool GameInFocus; +extern UserInputClass UserInput; /*********************************************************************************************** * MOUSECLASS::MOUSECLASS -- Constructor for the Mouse Class * @@ -241,8 +241,8 @@ void WWMouseClass::RenderMouse(void) { //ImVec2 size(current_cursor->width, current_cursor->height); // Image((ImTextureID)current_cursor->image, size); - int _my = mousey + (current_cursor->height * 0.25); - int xstart = mousex - Get_Hotspot_X(); + int _my = UserInput.Mouse.Y + (current_cursor->height * 0.25); + int xstart = UserInput.Mouse.X - Get_Hotspot_X(); int ystart = _my - Get_Hotspot_Y(); int yend = current_cursor->height + ystart - 1; int xend = current_cursor->width + xstart - 1; @@ -483,7 +483,7 @@ int WWMouseClass::Get_Mouse_State(void) *=============================================================================================*/ int WWMouseClass::Get_Mouse_X(void) { - return mousex; + return UserInput.Mouse.X; } @@ -499,7 +499,7 @@ int WWMouseClass::Get_Mouse_X(void) *=============================================================================================*/ int WWMouseClass::Get_Mouse_Y(void) { - return mousey; + return UserInput.Mouse.Y; } /*********************************************************************************************** @@ -515,8 +515,8 @@ int WWMouseClass::Get_Mouse_Y(void) *=============================================================================================*/ void WWMouseClass::Get_Mouse_XY(int &x, int &y) { - x = mousex; - y = mousey; + x = UserInput.Mouse.X; + y = UserInput.Mouse.Y; } //#pragma off(unreferenced) @@ -575,14 +575,13 @@ void *Set_Mouse_Cursor(int hotx, int hoty, int cursor) extern int DLLForceMouseX; extern int DLLForceMouseY; -extern int mousex, mousey; int Get_Mouse_X(void) { - return mousex; + return UserInput.Mouse.X; } int Get_Mouse_Y(void) { - return mousey; + return UserInput.Mouse.Y; } \ No newline at end of file diff --git a/code/REDALERT/WINSTUB.CPP b/code/REDALERT/WINSTUB.CPP index ccab983..7a9f856 100644 --- a/code/REDALERT/WINSTUB.CPP +++ b/code/REDALERT/WINSTUB.CPP @@ -61,6 +61,8 @@ #include #include +#include +#include #include #include "HOUSECOLOR.H" @@ -288,6 +290,25 @@ Image_t* Image_LoadImage(const char* name, bool loadAnims, bool loadHouseColor) return image; } +Image_t *Find_Image(const char* name) { + int64_t hash = generateHashValue(name, strlen(name)); + + int image_table_size = loaded_images.size(); + if (image_table_size > 0) + { + Image_t** image_table = &loaded_images[0]; + + // Check to see if the image is already loaded. + for (int i = 0; i < image_table_size; i++) { + if (image_table[i]->namehash == hash) { + return image_table[i]; + } + } + } + + return NULL; +} + Image_t* Image_CreateImageFrom8Bit(const char* name, int Width, int Height, unsigned char *data, unsigned char* remap) { int64_t hash = generateHashValue(name, strlen(name)); @@ -358,6 +379,61 @@ Image_t* Image_CreateImageFrom8Bit(const char* name, int Width, int Height, unsi return image; } +void Image_Add8BitImage(Image_t *image, int HouseId, int ShapeID, int Width, int Height, unsigned char* data, unsigned char* remap) { + unsigned char* buffer = new unsigned char[Width * Height * 4]; + unsigned char* ccpalete = (unsigned char*)CCPalette.Get_Data(); + + if (image->width != Width || image->height != Height) { + assert(!"Image_Add8BitImage: Invalid new dimensions!"); + } + + for (int i = 0; i < Width * Height; i++) { + unsigned char c = data[i]; + if (remap) { + c = remap[c]; + } + + unsigned char r = ccpalete[(c * 3) + 0] << 2; + unsigned char g = ccpalete[(c * 3) + 1] << 2; + unsigned char b = ccpalete[(c * 3) + 2] << 2; + unsigned char a = 0; + + if ((r == 84 && g == 252 && b == 84) || (r == 0 && g == 168 && b == 0)) { + r = 0; + g = 0; + b = 0; + a = 128; + } + else if (c != 0) { + a = 255; + } + + + buffer[(i * 4) + 0] = r; + buffer[(i * 4) + 1] = g; + buffer[(i * 4) + 2] = b; + buffer[(i * 4) + 3] = a; + } + + + GLuint texture; + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + + image->image[HouseId][ShapeID] = texture; + image->numAnimFrames = -1; + image->renderwidth = image->width = Width; + image->renderheight = image->height = Height; + + delete buffer; +} + + BOOL Set_Video_Mode(HWND hwnd, int w, int h, int bits_per_pixel) { // Todo implement resoluton scaling. @@ -884,134 +960,9 @@ void __cdecl SetPalette(unsigned char *palette, long, unsigned long) void WWSDL_ProcessEvents(KeyNumType& key, int& flags, bool presentBuffer) { - static int numFramesLMouse = 0; - extern int mousex, mousey; - bool leftMouseProcessed = false; - - key = KN_NONE; - flags = 0; - - SDL_GetMouseState(&mousex, &mousey); - - Keyboard->MouseQX = mousex; - Keyboard->MouseQY = mousey; - - // if (flags == LEFTRELEASE || flags == RIGHTRELEASE) - // flags = 0; - - static SDL_Event event; - memset(&event, 0, sizeof(SDL_Event)); - while (SDL_PollEvent(&event)) { - switch (event.type) - { - case SDL_SYSWMEVENT: - if ( event.syswm.msg->msg.win.msg == WM_DESTROY ) - { - Invalidate_Cached_Icons(); - VisiblePage.Un_Init(); - HiddenPage.Un_Init(); - AllSurfaces.Release(); - if (!InDebugger) Reset_Video_Mode(); - - /* - ** If we are shutting down gracefully than flag that the message loop has finished. - ** If this is a forced shutdown (ReadyToQuit == 0) then try and close down everything - ** before we exit. - */ - PostQuitMessage(0); - - switch (ReadyToQuit) { - case 1: - ReadyToQuit = 2; - break; - case 0: - ExitProcess(0); - break; - } - } - - break; - - case SDL_MOUSEMOTION: - flags = GadgetClass::LEFTUP; - break; - - - case SDL_MOUSEBUTTONDOWN: - if (event.button.button == SDL_BUTTON_LEFT) { - flags = GadgetClass::LEFTPRESS; - leftMouseProcessed = true; - numFramesLMouse++; - key = KN_LMOUSE; - Keyboard->Put_Element(KN_LMOUSE); - } - else if (event.button.button == SDL_BUTTON_RIGHT) { - numFramesLMouse = 0; - flags = GadgetClass::RIGHTPRESS; - Keyboard->Put_Element(KN_RMOUSE); - key = KN_RMOUSE; - } - break; - - case SDL_MOUSEBUTTONUP: - if (event.button.button == SDL_BUTTON_LEFT) { - flags = GadgetClass::LEFTRELEASE; - numFramesLMouse = 0; - } - else if (event.button.button == SDL_BUTTON_RIGHT) { - flags = GadgetClass::RIGHTRELEASE; - numFramesLMouse = 0; - } - break; - - case SDL_KEYDOWN: - if (event.key.keysym.scancode == SDL_SCANCODE_GRAVE) { - renderConsole = !renderConsole; - - if (renderConsole) { - // ShowCursor(TRUE); - // Hide_Mouse(); - } - else { - // ShowCursor(FALSE); - // Show_Mouse(); - } - break; - } - - const Uint8* state = SDL_GetKeyboardState(NULL); - - if (state[SDL_SCANCODE_RALT] || state[SDL_SCANCODE_LALT]) - { - Keyboard->Put_Element(event.key.keysym.sym | KN_ALT_BIT); - } - else - { - Keyboard->Put_Element(event.key.keysym.sym); - } - - break; - } - - if (Debug_Map || renderConsole) - { - ImGui_ImplSDL2_ProcessEvent(&event); - } - - } - - if (!leftMouseProcessed && numFramesLMouse != 0) - { - flags = GadgetClass::LEFTHELD; - } - - if (presentBuffer) { - Device_Present(); - } + UserInput.Process_Input(key, flags, presentBuffer); } - - #ifndef NDEBUG /*********************************************************************************************** * Assert_Failure -- display the line and source file where a failed assert occurred * diff --git a/code/REDALERT/io/UserInput.cpp b/code/REDALERT/io/UserInput.cpp new file mode 100644 index 0000000..6fc66d8 --- /dev/null +++ b/code/REDALERT/io/UserInput.cpp @@ -0,0 +1,146 @@ +#include "../FUNCTION.H" +#include "UserInput.h" + +extern KeyboardClass * Keyboard; + +void UserInputClass::Process_Input(KeyNumType& key, int& flags, bool presentBuffer) +{ + bool leftMouseProcessed = false; + SDL_GetMouseState(&Mouse.X, &Mouse.Y); + + Keyboard->MouseQX = Mouse.X; + Keyboard->MouseQY = Mouse.Y; + + static SDL_Event event; + memset(&event, 0, sizeof(SDL_Event)); + + while (SDL_PollEvent(&event)) { + const Uint8* state = SDL_GetKeyboardState(NULL); + + switch (event.type) + { + case SDL_SYSWMEVENT: + if (event.syswm.msg->msg.win.msg == WM_DESTROY) + { + Invalidate_Cached_Icons(); + VisiblePage.Un_Init(); + HiddenPage.Un_Init(); + AllSurfaces.Release(); + if (!InDebugger) Reset_Video_Mode(); + + PostQuitMessage(0); + + switch (ReadyToQuit) { + case 1: + ReadyToQuit = 2; + break; + case 0: + ExitProcess(0); + break; + } + } + + break; + + case SDL_MOUSEMOTION: + flags = GadgetClass::LEFTUP; + break; + + case SDL_MOUSEBUTTONDOWN: + if (event.button.button == SDL_BUTTON_LEFT) { + Mouse.Button_Left == MouseButtonState::MOUSE_BUTTON_DOWN; + + flags = GadgetClass::LEFTPRESS; + leftMouseProcessed = true; + numFramesLMouse++; + key = KN_LMOUSE; + } + else if (event.button.button == SDL_BUTTON_RIGHT) { + Mouse.Button_Right == MouseButtonState::MOUSE_BUTTON_DOWN; + + numFramesLMouse = 0; + flags = GadgetClass::RIGHTPRESS; + key = KN_RMOUSE; + } + break; + + case SDL_MOUSEBUTTONUP: + if (event.button.button == SDL_BUTTON_LEFT) { + Mouse.Button_Left == MouseButtonState::MOUSE_BUTTON_RELEASE; + + flags = GadgetClass::LEFTRELEASE; + numFramesLMouse = 0; + } + else if (event.button.button == SDL_BUTTON_RIGHT) { + Mouse.Button_Right == MouseButtonState::MOUSE_BUTTON_RELEASE; + + flags = GadgetClass::RIGHTRELEASE; + numFramesLMouse = 0; + } + break; + + case SDL_KEYDOWN: + { + if (event.key.keysym.scancode == SDL_SCANCODE_GRAVE) { + renderConsole = !renderConsole; + + if (renderConsole) { + ShowCursor(TRUE); + Hide_Mouse(); + } + else { + ShowCursor(FALSE); + Show_Mouse(); + } + break; + } + + int keyFlags = 0x00; + if (state[SDL_SCANCODE_RSHIFT] || state[SDL_SCANCODE_LSHIFT]) { + KeyB.Shift = true; + keyFlags |= KN_SHIFT_BIT; + } + if (state[SDL_SCANCODE_RALT] || state[SDL_SCANCODE_LALT]) { + keyFlags |= KN_ALT_BIT; + KeyB.Alt = true; + } + if (state[SDL_SCANCODE_RCTRL] || state[SDL_SCANCODE_LCTRL]) { + keyFlags |= KN_CTRL_BIT; + KeyB.Control = true; + } + + // handle match between SDL and internals (non-text keys) + auto element = sdl_keyMapping.find((SDL_KeyCode)event.key.keysym.sym); + if (element != sdl_keyMapping.end()) + { + Keyboard->Put_Element(element->second | keyFlags); + KeyB.ASCII = element->second; + } + + break; + } + case SDL_TEXTINPUT: + // limit to range 0-255 + if (event.text.text[0] == ( event.text.text[0] & 0xFF ) ) + { + KeyB.ASCII = (char)event.text.text[0]; + } + } + + if (Debug_Map || renderConsole) + { + ImGui_ImplSDL2_ProcessEvent(&event); + } + } + + if (!leftMouseProcessed && numFramesLMouse != 0) + { + Mouse.Button_Left == MouseButtonState::MOUSE_BUTTON_HOLD; + flags = GadgetClass::LEFTHELD; + } + + if (presentBuffer) + { + Device_Present(); + } +} \ No newline at end of file diff --git a/code/REDALERT/io/UserInput.h b/code/REDALERT/io/UserInput.h new file mode 100644 index 0000000..7f405e2 --- /dev/null +++ b/code/REDALERT/io/UserInput.h @@ -0,0 +1,147 @@ +#ifndef USERINPUT_H +#define USERINPUT_H + +#include +#include +#include + +#include "examples/imgui_impl_sdl.h" + +// Mapping of SDL KeyCode values to internal KeyNumType +std::map const sdl_keyMapping = { + { SDLK_a, KN_A }, + { SDLK_b, KN_B }, + { SDLK_c, KN_C }, + { SDLK_d, KN_D }, + { SDLK_e, KN_E }, + { SDLK_f, KN_F }, + { SDLK_g, KN_G }, + { SDLK_h, KN_H }, + { SDLK_i, KN_I }, + { SDLK_j, KN_J }, + { SDLK_k, KN_K }, + { SDLK_l, KN_N }, + { SDLK_m, KN_M }, + { SDLK_n, KN_N }, + { SDLK_o, KN_O }, + { SDLK_p, KN_P }, + { SDLK_q, KN_Q }, + { SDLK_r, KN_R }, + { SDLK_s, KN_S }, + { SDLK_t, KN_T }, + { SDLK_u, KN_U }, + { SDLK_v, KN_V }, + { SDLK_w, KN_W }, + { SDLK_x, KN_X }, + { SDLK_y, KN_Y }, + { SDLK_z, KN_Z }, + + { SDLK_0, KN_0 }, + { SDLK_1, KN_1 }, + { SDLK_2, KN_2 }, + { SDLK_3, KN_3 }, + { SDLK_4, KN_4 }, + { SDLK_5, KN_5 }, + { SDLK_6, KN_6 }, + { SDLK_7, KN_7 }, + { SDLK_8, KN_8 }, + { SDLK_9, KN_9 }, + + { SDLK_KP_MULTIPLY, KN_KEYPAD_ASTERISK }, + { SDLK_KP_DIVIDE, KN_KEYPAD_SLASH }, + { SDLK_MINUS, KN_MINUS }, + { SDLK_EQUALS, KN_EQUAL }, + + { SDLK_RIGHTBRACKET, KN_RBRACKET }, + { SDLK_LEFTBRACKET, KN_LBRACKET }, + { SDLK_SEMICOLON, KN_SEMICOLON }, + { SDLK_COMMA, KN_COMMA }, + { SDLK_PERIOD, KN_PERIOD }, + { SDLK_SLASH, KN_SLASH }, + { SDLK_BACKSLASH, KN_BACKSLASH }, + + { SDLK_F1, KN_F1 }, + { SDLK_F2, KN_F2 }, + { SDLK_F3, KN_F3 }, + { SDLK_F4, KN_F4 }, + { SDLK_F5, KN_F5 }, + { SDLK_F6, KN_F6 }, + { SDLK_F7, KN_F7 }, + { SDLK_F8, KN_F8 }, + { SDLK_F9, KN_F9 }, + { SDLK_F10, KN_F10 }, + { SDLK_F11, KN_F12 }, + { SDLK_F12, KN_F12 }, + + { SDLK_BACKSPACE, KN_BACKSPACE }, + { SDLK_SPACE, KN_SPACE }, + { SDLK_KP_ENTER, KN_RETURN }, + { SDLK_RETURN, KN_RETURN }, + { SDLK_ESCAPE, KN_ESC }, + + { SDLK_UP, KN_UP }, + { SDLK_DOWN, KN_DOWN }, + { SDLK_LEFT, KN_LEFT }, + { SDLK_RIGHT, KN_RIGHT }, +}; + +class UserInputClass +{ + public: + typedef enum { + MOUSE_BUTTON_UP, + MOUSE_BUTTON_DOWN, + MOUSE_BUTTON_HOLD, + MOUSE_BUTTON_RELEASE, + } MouseButtonState; + + typedef enum { + INPUT_ACTION_NONE, + INPUT_ACTION_KEYBOARD, + INPUT_ACTION_MOUSE, + } InputAction; + + void UserInputClass::Process_Input(KeyNumType& key, int& flags, bool presentBuffer = true); + + InputAction LastAction; + + class KeyboardState { + public: + SDL_KeyCode LastKey; + char ASCII; + + bool Shift; + bool Control; + bool Alt; + + void ResetState() { + this->Shift = false; + this->Control = false; + this->Alt = false; + } + }; + + KeyboardState KeyB; + + class MouseState { + public: + int X; + int Y; + + MouseButtonState Button_Left; + MouseButtonState Button_Middle; + MouseButtonState Button_Right; + + void ResetState() { + this->Button_Left = MouseButtonState::MOUSE_BUTTON_UP; + this->Button_Middle = MouseButtonState::MOUSE_BUTTON_UP; + this->Button_Right = MouseButtonState::MOUSE_BUTTON_UP; + } + }; + + MouseState Mouse; + private: + int numFramesLMouse = 0; +}; + +#endif \ No newline at end of file