diff --git a/code/redalert/2keyfram.cpp b/code/redalert/2keyfram.cpp index ece0af5..9172958 100644 --- a/code/redalert/2keyfram.cpp +++ b/code/redalert/2keyfram.cpp @@ -554,6 +554,17 @@ unsigned short Get_Build_Frame_Y(void const *dataptr, int frame) return(0); } +bool Get_Build_Is_Compressed(void const *dataptr, int frame) { + if(dataptr) { + if (Get_Build_TS_Shape(dataptr)) { + return Get_Build_TS_FrameInfo(dataptr, frame)->Flags & 2; + } + + return false; + } + + return false; +} /*********************************************************************************************** * Get_Build_Frame_Width -- Fetches the width of the shape image. * @@ -574,6 +585,11 @@ unsigned short Get_Build_Frame_Width(void const *dataptr, int frame) { if (dataptr) { if(Get_Build_TS_Shape(dataptr)) { + if(frame == -1) { + const TiberianSunShapeHeader* ts = (const TiberianSunShapeHeader*)dataptr; + return ts->width; + } + return Get_Build_TS_FrameInfo(dataptr, frame)->FrameWidth; } @@ -582,7 +598,6 @@ unsigned short Get_Build_Frame_Width(void const *dataptr, int frame) return(0); } - /*********************************************************************************************** * Get_Build_Frame_Height -- Fetches the height of the shape image. * * * @@ -602,6 +617,10 @@ unsigned short Get_Build_Frame_Height(void const *dataptr, int frame) { if (dataptr) { if (Get_Build_TS_Shape(dataptr)) { + if (frame == -1) { + const TiberianSunShapeHeader* ts = (const TiberianSunShapeHeader*)dataptr; + return ts->height; + } return Get_Build_TS_FrameInfo(dataptr, frame)->FrameHeight; } return(((RedAlertShapeHeader const *)dataptr)->height); diff --git a/code/redalert/bdata.cpp b/code/redalert/bdata.cpp index ef10153..b2d3db1 100644 --- a/code/redalert/bdata.cpp +++ b/code/redalert/bdata.cpp @@ -2946,6 +2946,7 @@ BuildingTypeClass::BuildingTypeClass( { memset(CustomTheatrePalette, 0, sizeof(CustomTheatrePalette)); + IdleAnimShape = NULL; Anims[BSTATE_CONSTRUCTION].Start = 0; Anims[BSTATE_CONSTRUCTION].Count = 1; @@ -4002,6 +4003,9 @@ bool BuildingTypeClass::Flush_For_Placement(CELL cell, HouseClass * house) cons *=============================================================================================*/ bool BuildingTypeClass::Read_INI(CCINIClass & ini) { + char customPalName[512]; + char idleAnimName[512]; + if (TechnoTypeClass::Read_INI(ini)) { Speed = ini.Get_Bool(Name(), "WaterBound", (Speed == SPEED_FLOAT)) ? SPEED_FLOAT : SPEED_NONE; Capacity = ini.Get_Int(Name(), "Storage", Capacity); @@ -4011,9 +4015,7 @@ bool BuildingTypeClass::Read_INI(CCINIClass & ini) IsBibbed = ini.Get_Bool(Name(), "Bib", IsBibbed); IsUnsellable = ini.Get_Bool(Name(), "Unsellable", IsUnsellable); IsBase = ini.Get_Bool(Name(), "BaseNormal", IsBase); - Power = ini.Get_Int(Name(), "Power", (Power > 0) ? Power : -Drain); - - char customPalName[512]; + Power = ini.Get_Int(Name(), "Power", (Power > 0) ? Power : -Drain); if(ini.Get_String(Name(), "Snow", "", &customPalName[0], sizeof(customPalName)) > 0) { CustomTheatrePalette[THEATER_SNOW] = MFCD::Retrieve(customPalName); @@ -4022,6 +4024,9 @@ bool BuildingTypeClass::Read_INI(CCINIClass & ini) CustomTheatrePalette[THEATER_TEMPERATE] = MFCD::Retrieve(customPalName); } + if (ini.Get_String(Name(), "IdleAnim", "", &idleAnimName[0], sizeof(idleAnimName)) > 0) { + IdleAnimShape = MFCD::Retrieve(idleAnimName); + } if (Power < 0) { Drain = -Power; diff --git a/code/redalert/building.cpp b/code/redalert/building.cpp index e762535..03648ba 100644 --- a/code/redalert/building.cpp +++ b/code/redalert/building.cpp @@ -480,9 +480,18 @@ void BuildingClass::Draw_It(int x, int y, WindowNumberType window) const else { Techno_Draw_Object(shapefile, Shape_Number(), x, y, window); } +// jmarshall end + +// jmarshall idle animation + if (Class->IdleAnimShape != NULL) { + int shapeNum = animFrameNum; + shapeNum = shapeNum % Get_Build_Frame_Count(Class->IdleAnimShape); + Techno_Draw_Object(Class->IdleAnimShape, shapeNum, x, y, window); + } CCGlobalOveridePalette = NULL; // jmarshall end + IsTheaterShape = false; /* diff --git a/code/redalert/conquer.cpp b/code/redalert/conquer.cpp index 00b864c..c774e91 100644 --- a/code/redalert/conquer.cpp +++ b/code/redalert/conquer.cpp @@ -3696,8 +3696,9 @@ void CC_Draw_Shape(void const * shapefile, int shapenum, int x, int y, WindowNum if (shapefile != NULL && shapenum != -1) { - int width = Get_Build_Frame_Width(shapefile, shapenum); - int height = Get_Build_Frame_Height(shapefile, shapenum); + // With TS tiles, the smaller image buffer gets blit into a buffer that's the size of the entire image. + int width = Get_Build_Frame_Width(shapefile, -1); + int height = Get_Build_Frame_Height(shapefile, -1); #ifdef NEVER /* diff --git a/code/redalert/function.h b/code/redalert/function.h index d233030..c03f9c1 100644 --- a/code/redalert/function.h +++ b/code/redalert/function.h @@ -726,6 +726,7 @@ unsigned short Get_Build_Frame_Count(void const *dataptr); bool Get_Build_TiberianSun_Format(void const* dataptr); unsigned short Get_Build_Frame_X(void const *dataptr, int frame); unsigned short Get_Build_Frame_Y(void const *dataptr, int frame); +bool Get_Build_Is_Compressed(void const* dataptr, int frame); unsigned short Get_Build_Frame_Width(void const *dataptr, int frame); unsigned short Get_Build_Frame_Height(void const *dataptr, int frame); bool Get_Build_Frame_Palette(void const *dataptr, void *palette); diff --git a/code/redalert/shape.cpp b/code/redalert/shape.cpp index 57f463b..c9997f1 100644 --- a/code/redalert/shape.cpp +++ b/code/redalert/shape.cpp @@ -19,6 +19,7 @@ Originally this file came from Chronoshift, and we still have some legacy bits from their code in here, however this file has been **heavily** modified by IceColdDuke(Justin Marshall) to render with OpenGL. +We also added Tiberian Sun SHP format render support, this code uses some code from XCC. ============================ */ @@ -42,6 +43,8 @@ using std::memcpy; #define SHAPE_TRANSPARENT 0x40 +char shape_ts_global[2048 * 2048]; + struct ShapeHeaderStruct { uint16_t m_FrameCount; @@ -212,6 +215,23 @@ int TiberianSunSHPDecode(const byte* s, byte* d, int cx, int cy) return w - d; } +INT_PTR Build_Full_Frame(int frameX, int frameY, int frameWidth, int frameHeight, int imageWidth, int imageHeight, byte *uncompressedBuffer) { + if (frameWidth == imageWidth && frameHeight == imageHeight) { + return (INT_PTR)uncompressedBuffer; + } + + memset(shape_ts_global, 0, imageWidth * imageHeight); + + byte* w = (byte *)shape_ts_global + frameX + imageWidth * frameY; + for (int y = 0; y < frameHeight; y++) + { + memcpy(w, uncompressedBuffer, frameWidth); + uncompressedBuffer += frameWidth; + w += imageWidth; + } + + return (INT_PTR)shape_ts_global; +} INT_PTR Build_Frame(void const* dataptr, unsigned short framenumber, void* buffptr) { // Check to see if we need to render a Tiberian Sun SHP file. @@ -221,10 +241,20 @@ INT_PTR Build_Frame(void const* dataptr, unsigned short framenumber, void* buffp } byte* frame_offset = (byte *)Get_Build_TS_FrameOffset(dataptr, framenumber); - int frameX = Get_Build_Frame_Width(dataptr, framenumber); - int frameY = Get_Build_Frame_Height(dataptr, framenumber); - TiberianSunSHPDecode(frame_offset, (byte *)buffptr, frameX, frameY); - return (INT_PTR)buffptr; + int frameWidth = Get_Build_Frame_Width(dataptr, framenumber); + int frameHeight = Get_Build_Frame_Height(dataptr, framenumber); + + int frame_X = Get_Build_Frame_X(dataptr, framenumber); + int frame_Y = Get_Build_Frame_Y(dataptr, framenumber); + + int imageWidth = Get_Build_Frame_Width(dataptr, -1); + int imageHeight = Get_Build_Frame_Height(dataptr, -1); + if (Get_Build_Is_Compressed(dataptr, framenumber)) { + TiberianSunSHPDecode(frame_offset, (byte*)buffptr, frameWidth, frameHeight); + return (INT_PTR)Build_Full_Frame(frame_X, frame_Y, frameWidth, frameHeight, imageWidth, imageHeight, (byte *)buffptr); + } + + return (INT_PTR)Build_Full_Frame(frame_X, frame_Y, frameWidth, frameHeight, imageWidth, imageHeight, frame_offset); } // Regular Red Alert sprite. diff --git a/code/redalert/type.h b/code/redalert/type.h index f52648b..66dbe1e 100644 --- a/code/redalert/type.h +++ b/code/redalert/type.h @@ -819,6 +819,7 @@ class BuildingTypeClass : public TechnoTypeClass { static Image_t* WarFactoryHDOverlay; const void* CustomTheatrePalette[3]; + const void* IdleAnimShape; private: /* diff --git a/redalert.ini b/redalert.ini index 5058990..be00c54 100644 --- a/redalert.ini +++ b/redalert.ini @@ -23,11 +23,11 @@ UseSmallInfantry=No NoCD=Yes CounterstrikeEnabled=Yes AftermathEnabled=Yes +ScoreVolume=0.5 GameSpeed=2 ScrollRate=5 Brightness=0.5 Volume=0.375 -ScoreVolume=0.5 MultiplayerScoreVolume=0.5 Contrast=0.5 Color=0.5 diff --git a/rules.ini b/rules.ini index 09b4d1e..fbfd54a 100644 --- a/rules.ini +++ b/rules.ini @@ -1420,6 +1420,7 @@ Capturable=true Crewed=yes Snow=eapal1sno.pal Temperate=eapal1tem.pal +IdleAnim=EACNST_A.SHP ; refinery [PROC]