diff --git a/EXPAND3.mix b/EXPAND3.mix new file mode 100644 index 0000000..dcfdf4e Binary files /dev/null and b/EXPAND3.mix differ diff --git a/code/redalert/2keyfram.cpp b/code/redalert/2keyfram.cpp index 6d19884..ece0af5 100644 --- a/code/redalert/2keyfram.cpp +++ b/code/redalert/2keyfram.cpp @@ -51,7 +51,25 @@ typedef struct { unsigned short height; unsigned short largest_frame_size; short flags; -} KeyFrameHeaderType; +} RedAlertShapeHeader; + +typedef struct { + unsigned short iden; // Always 0! + unsigned short width; // Width of the frames. + unsigned short height; // Height of the frames. + unsigned short NumFrames; +} TiberianSunShapeHeader; + +typedef struct { + unsigned short FrameX; + unsigned short FrameY; + unsigned short FrameWidth; + unsigned short FrameHeight; + unsigned int Flags; + byte FrameColor[4]; + unsigned int Reserved; + unsigned int DataOffset; +} TiberianSunShapeFrameInfo; #define INITIAL_BIG_SHAPE_BUFFER_SIZE (64 * 1024 * 1024) #define THEATER_BIG_SHAPE_BUFFER_SIZE 4000000 @@ -212,7 +230,7 @@ void Check_Use_Compressed_Shapes (void) // unsigned long offcurr, off16, offdiff; //#endif // unsigned long offset[SUBFRAMEOFFS]; -// KeyFrameHeaderType *keyfr; +// RedAlertShapeHeader *keyfr; // unsigned short buffsize, currframe, subframe; // unsigned long length = 0; // char frameflags; @@ -231,7 +249,7 @@ void Check_Use_Compressed_Shapes (void) // // look at header then check that frame to build is not greater // // than total frames // // -// keyfr = (KeyFrameHeaderType *) dataptr; +// keyfr = (RedAlertShapeHeader *) dataptr; // // if ( framenumber >= keyfr->frames ) { // return(0); @@ -300,7 +318,7 @@ void Check_Use_Compressed_Shapes (void) // buffsize = keyfr->width * keyfr->height; // // // get offset into data -// ptr = (char *)Add_Long_To_Pointer( dataptr, (((unsigned long)framenumber << 3) + sizeof(KeyFrameHeaderType)) ); +// ptr = (char *)Add_Long_To_Pointer( dataptr, (((unsigned long)framenumber << 3) + sizeof(RedAlertShapeHeader)) ); // Mem_Copy( ptr, &offset[0], 12L ); // frameflags = (char)(offset[0] >> 24); // @@ -318,7 +336,7 @@ void Check_Use_Compressed_Shapes (void) // if ( (frameflags & KF_DELTA) ) { // currframe = (unsigned short)offset[1]; // -// ptr = (char *)Add_Long_To_Pointer( dataptr, (((unsigned long)currframe << 3) + sizeof(KeyFrameHeaderType)) ); +// ptr = (char *)Add_Long_To_Pointer( dataptr, (((unsigned long)currframe << 3) + sizeof(RedAlertShapeHeader)) ); // Mem_Copy( ptr, &offset[0], (long)(SUBFRAMEOFFS * sizeof(unsigned long)) ); // } // @@ -388,7 +406,7 @@ void Check_Use_Compressed_Shapes (void) // currframe <= framenumber ) { // Mem_Copy( Add_Long_To_Pointer( dataptr, // (((unsigned long)currframe << 3) + -// sizeof(KeyFrameHeaderType)) ), +// sizeof(RedAlertShapeHeader)) ), // &offset[0], (long)(SUBFRAMEOFFS * sizeof(unsigned long)) ); // subframe = 0; // } @@ -463,6 +481,27 @@ void Check_Use_Compressed_Shapes (void) // } //} +bool Get_Build_TS_Shape(const void *dataptr) { + if(dataptr) { + const TiberianSunShapeHeader* ts = (const TiberianSunShapeHeader*)dataptr; + if(ts->iden == 0) { + return true; + } + + return false; + } + return false; +} + +TiberianSunShapeFrameInfo *Get_Build_TS_FrameInfo(const void *dataptr, int frameNum) { + const byte* tsptr = (const byte*)dataptr; + return (TiberianSunShapeFrameInfo*)((byte*)(tsptr + (sizeof(TiberianSunShapeFrameInfo) * frameNum) + sizeof(TiberianSunShapeHeader))); +} + +void *Get_Build_TS_FrameOffset(const void *dataptr, int framenum) { + TiberianSunShapeFrameInfo* frameInfo = Get_Build_TS_FrameInfo(dataptr, framenum); + return (void *)(((byte *)dataptr) + frameInfo->DataOffset); +} /*********************************************************************************************** * Get_Build_Frame_Count -- Fetches the number of frames in data block. * @@ -481,25 +520,36 @@ void Check_Use_Compressed_Shapes (void) unsigned short Get_Build_Frame_Count(void const *dataptr) { if (dataptr) { - return(((KeyFrameHeaderType const *)dataptr)->frames); + if(Get_Build_TS_Shape(dataptr)) { + const TiberianSunShapeHeader* ts = (const TiberianSunShapeHeader*)dataptr; + return ts->NumFrames; + } + + return(((RedAlertShapeHeader const *)dataptr)->frames); } return(0); } -unsigned short Get_Build_Frame_X(void const *dataptr) +unsigned short Get_Build_Frame_X(void const *dataptr, int frame) { if (dataptr) { - return(((KeyFrameHeaderType const *)dataptr)->x); + if (Get_Build_TS_Shape(dataptr)) { + return Get_Build_TS_FrameInfo(dataptr, frame)->FrameX; + } + return(((RedAlertShapeHeader const *)dataptr)->x); } return(0); } -unsigned short Get_Build_Frame_Y(void const *dataptr) +unsigned short Get_Build_Frame_Y(void const *dataptr, int frame) { if (dataptr) { - return(((KeyFrameHeaderType const *)dataptr)->y); + if (Get_Build_TS_Shape(dataptr)) { + return Get_Build_TS_FrameInfo(dataptr, frame)->FrameY; + } + return(((RedAlertShapeHeader const *)dataptr)->y); } return(0); } @@ -520,10 +570,14 @@ unsigned short Get_Build_Frame_Y(void const *dataptr) * HISTORY: * * 06/25/1995 JLB : Commented * *=============================================================================================*/ -unsigned short Get_Build_Frame_Width(void const *dataptr) +unsigned short Get_Build_Frame_Width(void const *dataptr, int frame) { if (dataptr) { - return(((KeyFrameHeaderType const *)dataptr)->width); + if(Get_Build_TS_Shape(dataptr)) { + return Get_Build_TS_FrameInfo(dataptr, frame)->FrameWidth; + } + + return(((RedAlertShapeHeader const *)dataptr)->width); } return(0); } @@ -544,10 +598,13 @@ unsigned short Get_Build_Frame_Width(void const *dataptr) * HISTORY: * * 06/25/1995 JLB : Commented * *=============================================================================================*/ -unsigned short Get_Build_Frame_Height(void const *dataptr) +unsigned short Get_Build_Frame_Height(void const *dataptr, int frame) { if (dataptr) { - return(((KeyFrameHeaderType const *)dataptr)->height); + if (Get_Build_TS_Shape(dataptr)) { + return Get_Build_TS_FrameInfo(dataptr, frame)->FrameHeight; + } + return(((RedAlertShapeHeader const *)dataptr)->height); } return(0); } @@ -555,11 +612,11 @@ unsigned short Get_Build_Frame_Height(void const *dataptr) bool Get_Build_Frame_Palette(void const * dataptr, void * palette) { - if (dataptr && (((KeyFrameHeaderType const *)dataptr)->flags & 1)) { + if (dataptr && (((RedAlertShapeHeader const *)dataptr)->flags & 1)) { char const * ptr = (char const *)Add_Long_To_Pointer( dataptr, ( (( (long)sizeof(unsigned long) << 1) * - ((KeyFrameHeaderType *) dataptr)->frames ) + - 16 + sizeof(KeyFrameHeaderType) ) ); + ((RedAlertShapeHeader *) dataptr)->frames ) + + 16 + sizeof(RedAlertShapeHeader) ) ); memcpy(palette, ptr, 768L); return(true); diff --git a/code/redalert/anim.cpp b/code/redalert/anim.cpp index 09796df..36e211e 100644 --- a/code/redalert/anim.cpp +++ b/code/redalert/anim.cpp @@ -273,7 +273,7 @@ void AnimClass::Draw_It(int x, int y, WindowNumberType window) const case ANIM_FLAG: x += (ICON_PIXEL_W / 2) - 2; - y += (3 * ICON_PIXEL_H / 4) - Get_Build_Frame_Height(shapefile); + y += (3 * ICON_PIXEL_H / 4) - Get_Build_Frame_Height(shapefile, shapenum); transtable = Map.UnitShadow; alt = true; break; diff --git a/code/redalert/conquer.cpp b/code/redalert/conquer.cpp index ff82bbd..00b864c 100644 --- a/code/redalert/conquer.cpp +++ b/code/redalert/conquer.cpp @@ -3366,8 +3366,8 @@ void const * Get_Radar_Icon(void const * shapefile, int shapenum, int frames, in ** Get the pixel width and height of the frame we built. This will ** be used to extract icons and build pixels. */ - int pixel_width = Get_Build_Frame_Width( shapefile ); - int pixel_height = Get_Build_Frame_Height( shapefile ); + int pixel_width = Get_Build_Frame_Width( shapefile, shapenum); + int pixel_height = Get_Build_Frame_Height( shapefile, shapenum); /* ** Find the width and height in icons, adjust these by half an @@ -3467,8 +3467,8 @@ void CC_Draw_Shape(void const * shapefile, int shapenum, int x, int y, WindowNum void CC_Draw_Shape(const ObjectClass *object, void const * shapefile, int shapenum, int x, int y, WindowNumberType window, ShapeFlags_Type flags, void const * fadingdata, void const * ghostdata, DirType rotation, long virtualscale) { if (window == WINDOW_VIRTUAL) { - int width = Get_Build_Frame_Width(shapefile); - int height = Get_Build_Frame_Height(shapefile); + int width = Get_Build_Frame_Width(shapefile, shapenum); + int height = Get_Build_Frame_Height(shapefile, shapenum); DLL_Draw_Intercept(shapenum, x, y, width, height, (int)flags, object, rotation, virtualscale, NULL, HOUSE_NONE); return; } @@ -3479,8 +3479,8 @@ void CC_Draw_Shape(const ObjectClass *object, void const * shapefile, int shapen void CC_Draw_Shape(const ObjectClass *object, const char *shape_file_name, void const * shapefile, int shapenum, int x, int y, WindowNumberType window, ShapeFlags_Type flags, void const * fadingdata, void const * ghostdata, DirType rotation, long virtualscale, char override_owner) { if (window == WINDOW_VIRTUAL) { - int width = Get_Build_Frame_Width(shapefile); - int height = Get_Build_Frame_Height(shapefile); + int width = Get_Build_Frame_Width(shapefile, shapenum); + int height = Get_Build_Frame_Height(shapefile, shapenum); DLL_Draw_Intercept(shapenum, x, y, width, height, (int)flags, object, rotation, virtualscale, shape_file_name, override_owner); return; } @@ -3696,8 +3696,8 @@ 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); - int height = Get_Build_Frame_Height(shapefile); + int width = Get_Build_Frame_Width(shapefile, shapenum); + int height = Get_Build_Frame_Height(shapefile, shapenum); #ifdef NEVER /* @@ -3854,8 +3854,8 @@ Rect const Shape_Dimensions(void const * shapedata, int shapenum) shape = (char *)_ShapeBuffer; #endif - int width = Get_Build_Frame_Width(shapedata); - int height = Get_Build_Frame_Height(shapedata); + int width = Get_Build_Frame_Width(shapedata, shapenum); + int height = Get_Build_Frame_Height(shapedata, shapenum); rect.X = 0; rect.Y = 0; diff --git a/code/redalert/dllinterface.cpp b/code/redalert/dllinterface.cpp index 8856242..172e8ea 100644 --- a/code/redalert/dllinterface.cpp +++ b/code/redalert/dllinterface.cpp @@ -6290,8 +6290,8 @@ if (debug_output) { smudge_entry.DrawFlags = SHAPE_WIN_REL; // Looks like smudges are drawn top left smudge_entry.PositionX = xpixel; smudge_entry.PositionY = ypixel; - smudge_entry.Width = Get_Build_Frame_Width(smudge_type.Get_Image_Data()); - smudge_entry.Height = Get_Build_Frame_Height(smudge_type.Get_Image_Data()); + smudge_entry.Width = Get_Build_Frame_Width(smudge_type.Get_Image_Data(), 0); + smudge_entry.Height = Get_Build_Frame_Height(smudge_type.Get_Image_Data(), 0); smudge_entry.CellX = Cell_X(cell); smudge_entry.CellY = Cell_Y(cell); smudge_entry.ShapeIndex = cell_ptr->SmudgeData; @@ -6332,8 +6332,8 @@ if (debug_output) { overlay_entry.DrawFlags = SHAPE_CENTER|SHAPE_WIN_REL|SHAPE_GHOST; // Looks like overlays are drawn centered and translucent overlay_entry.PositionX = xpixel + (CELL_PIXEL_W>>1); overlay_entry.PositionY = ypixel + (CELL_PIXEL_H>>1); - overlay_entry.Width = Get_Build_Frame_Width(overlay_type.Get_Image_Data()); - overlay_entry.Height = Get_Build_Frame_Height(overlay_type.Get_Image_Data()); + overlay_entry.Width = Get_Build_Frame_Width(overlay_type.Get_Image_Data(), 0); + overlay_entry.Height = Get_Build_Frame_Height(overlay_type.Get_Image_Data(), 0); overlay_entry.CellX = Cell_X(cell); overlay_entry.CellY = Cell_Y(cell); overlay_entry.ShapeIndex = cell_ptr->OverlayData; @@ -6361,8 +6361,8 @@ if (debug_output) { flag_entry.DrawFlags = SHAPE_CENTER|SHAPE_GHOST|SHAPE_FADING; flag_entry.PositionX = xpixel + (ICON_PIXEL_W / 2); flag_entry.PositionY = ypixel + (ICON_PIXEL_H / 2); - flag_entry.Width = Get_Build_Frame_Width(image_data); - flag_entry.Height = Get_Build_Frame_Height(image_data); + flag_entry.Width = Get_Build_Frame_Width(image_data, 0); + flag_entry.Height = Get_Build_Frame_Height(image_data, 0); flag_entry.CellX = Cell_X(cell); flag_entry.CellY = Cell_Y(cell); flag_entry.ShapeIndex = Frame % 14; diff --git a/code/redalert/drop.cpp b/code/redalert/drop.cpp index ebd4185..26d5ea4 100644 --- a/code/redalert/drop.cpp +++ b/code/redalert/drop.cpp @@ -41,7 +41,7 @@ DropListClass::DropListClass(int id, char * text, int max_len, TextPrintType fla IsDropped(false), ListHeight(h), DropButton(0, down, x+w, y), - List(0, x, y+Get_Build_Frame_Height(down), w+Get_Build_Frame_Width(down), h, flags, up, down) + List(0, x, y+Get_Build_Frame_Height(down, 0), w+Get_Build_Frame_Width(down, 0), h, flags, up, down) { Fancy_Text_Print("", 0, 0, 0, 0, flags); EditClass::Height = FontHeight+1; @@ -189,7 +189,7 @@ DropListClass::DropListClass(DropListClass const & list) : void DropListClass::Set_Position(int x, int y) { EditClass::Set_Position(x, y); - List.Set_Position(x, y + Get_Build_Frame_Height(DropButton.Get_Shape_Data())); + List.Set_Position(x, y + Get_Build_Frame_Height(DropButton.Get_Shape_Data(), 0)); DropButton.Set_Position(x + Width, y); } diff --git a/code/redalert/drop.h b/code/redalert/drop.h index 7fcb258..0be802c 100644 --- a/code/redalert/drop.h +++ b/code/redalert/drop.h @@ -157,7 +157,7 @@ TDropListClass::TDropListClass(int id, char * text, int max_len, TextPrintTyp IsDropped(false), ListHeight(h), DropButton(0, down, x+w, y), - List(0, x, y+Get_Build_Frame_Height(down), w+Get_Build_Frame_Width(down), h, flags, up, down) + List(0, x, y+Get_Build_Frame_Height(down, 0), w+Get_Build_Frame_Width(down, 0), h, flags, up, down) { List.Make_Peer(*this); DropButton.Make_Peer(*this); @@ -330,7 +330,7 @@ template void TDropListClass::Set_Position(int x, int y) { EditClass::Set_Position(x, y); - List.Set_Position(x, y + Get_Build_Frame_Height(DropButton.Get_Shape_Data())); + List.Set_Position(x, y + Get_Build_Frame_Height(DropButton.Get_Shape_Data(), 0)); DropButton.Set_Position(x + Width, y); } diff --git a/code/redalert/function.h b/code/redalert/function.h index a30bc55..d233030 100644 --- a/code/redalert/function.h +++ b/code/redalert/function.h @@ -718,13 +718,16 @@ long __cdecl Buffer_Frame_To_Page(int shapeNum, int x, int y, int w, int h, Imag /* ** KEYFRAME.CPP */ +bool Get_Build_TS_Shape(const void* dataptr); +void* Get_Build_TS_FrameOffset(const void* dataptr, int framenum); + INT_PTR Build_Frame(void const *dataptr, unsigned short framenumber, void *buffptr); 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); -unsigned short Get_Build_Frame_Y(void const *dataptr); -unsigned short Get_Build_Frame_Width(void const *dataptr); -unsigned short Get_Build_Frame_Height(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); +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); int Get_Last_Frame_Length(void); diff --git a/code/redalert/init.cpp b/code/redalert/init.cpp index 3221f98..08ccc72 100644 --- a/code/redalert/init.cpp +++ b/code/redalert/init.cpp @@ -2996,6 +2996,12 @@ static void Init_Bootstrap_Mixfiles(void) int temp = RequiredCD; RequiredCD = -2; + new MFCD("expand3.mix", &FastKey, MIX_FILE_TS); + { + bool ok = MFCD::Cache("expand3.mix"); + assert(ok); + } + // Isometric Files new MFCD("isosnow.mix", &FastKey, MIX_FILE_TS); { diff --git a/code/redalert/shape.cpp b/code/redalert/shape.cpp index efa3e28..802b016 100644 --- a/code/redalert/shape.cpp +++ b/code/redalert/shape.cpp @@ -180,8 +180,51 @@ void* Build_Frame2(void* shape, uint16_t frame, void* buffer) return buffer; } +int TiberianSunSHPDecode(const byte* s, byte* d, int cx, int cy) +{ + const byte* r = s; + byte* w = d; + for (int y = 0; y < cy; y++) + { + int count = *reinterpret_cast(r) - 2; + r += 2; + int x = 0; + while (count--) + { + int v = *r++; + if (v) + { + x++; + *w++ = v; + } + else + { + count--; + v = *r++; + if (x + v > cx) + v = cx - x; + x += v; + while (v--) + *w++ = 0; + } + } + } + return w - d; +} + + INT_PTR Build_Frame(void const* dataptr, unsigned short framenumber, void* buffptr) { - return (INT_PTR)Build_Frame2((void*)dataptr, framenumber, buffptr); // 32 bit to 64 bit issue + // Check to see if we need to render a Tiberian Sun SHP file. + if(Get_Build_TS_Shape(dataptr)) { + 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; + } + + // Regular Red Alert sprite. + return (INT_PTR)Build_Frame2((void*)dataptr, framenumber, buffptr); // 32 bit to 64 bit issue } // This one appears to deal with the buffered shape data diff --git a/code/redalert/shapebtn.cpp b/code/redalert/shapebtn.cpp index ea07f16..f729b43 100644 --- a/code/redalert/shapebtn.cpp +++ b/code/redalert/shapebtn.cpp @@ -110,8 +110,8 @@ void ShapeButtonClass::Set_Shape(void const * data) { ShapeData = data; if (ShapeData) { - Width = Get_Build_Frame_Width(ShapeData); - Height = Get_Build_Frame_Height(ShapeData); + Width = Get_Build_Frame_Width(ShapeData, 0); + Height = Get_Build_Frame_Height(ShapeData, 0); } } diff --git a/code/redalert/sidebareditor.cpp b/code/redalert/sidebareditor.cpp index c030ea3..3d23bd6 100644 --- a/code/redalert/sidebareditor.cpp +++ b/code/redalert/sidebareditor.cpp @@ -18,8 +18,8 @@ Image_t* SidebarEditor::LoadEditorImage(const char* name) { return NULL; } - int width = Get_Build_Frame_Width(shapefile); - int height = Get_Build_Frame_Height(shapefile); + int width = Get_Build_Frame_Width(shapefile, 0); + int height = Get_Build_Frame_Height(shapefile, 0); unsigned char *shape_pointer = (unsigned char*)Build_Frame(shapefile, 0, _ShapeBuffer); short frameCount = Get_Build_Frame_Count(shapefile); diff --git a/code/redalert/udata.cpp b/code/redalert/udata.cpp index 7ff9096..ac61d13 100644 --- a/code/redalert/udata.cpp +++ b/code/redalert/udata.cpp @@ -1114,8 +1114,8 @@ void UnitTypeClass::One_Time(void) ((void const *&)uclass.ImageData) = ptr; if (ptr != NULL) { - largest = max(largest, (int)Get_Build_Frame_Width(ptr)); - largest = max(largest, (int)Get_Build_Frame_Height(ptr)); + largest = max(largest, (int)Get_Build_Frame_Width(ptr, 0)); + largest = max(largest, (int)Get_Build_Frame_Height(ptr, 0)); } { const char* imageFileName = Units_FindHDTexture(fullname, 0, 0); diff --git a/code/redalert/unit.cpp b/code/redalert/unit.cpp index 926fa5b..dda4895 100644 --- a/code/redalert/unit.cpp +++ b/code/redalert/unit.cpp @@ -2188,7 +2188,7 @@ void UnitClass::Draw_It(int x, int y, WindowNumberType window) const if (Flagged != HOUSE_NONE) { shapefile = MFCD::Retrieve("FLAGFLY.SHP"); int flag_x = x + (ICON_PIXEL_W / 2) - 2; - int flag_y = y + (3 * ICON_PIXEL_H / 4) - Get_Build_Frame_Height(shapefile); + int flag_y = y + (3 * ICON_PIXEL_H / 4) - Get_Build_Frame_Height(shapefile, 0); CC_Draw_Shape(this, "FLAGFLY", shapefile, Frame % 14, flag_x, flag_y, window, SHAPE_CENTER|SHAPE_FADING|SHAPE_GHOST, HouseClass::As_Pointer(Flagged)->Remap_Table(false, Class->Remap), Map.UnitShadow, DIR_N, 0x0100, Flagged); }