Added Tiberian Sun/Red Alert SHP file support. Added EXPAND3.MIX for Allied Force data.

This commit is contained in:
Justin Marshall
2020-07-31 21:52:32 -07:00
parent 1d8cd100b0
commit 32a81a0174
14 changed files with 160 additions and 51 deletions
BIN
View File
Binary file not shown.
+75 -18
View File
@@ -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);
+1 -1
View File
@@ -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;
+10 -10
View File
@@ -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;
+6 -6
View File
@@ -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;
+2 -2
View File
@@ -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);
}
+2 -2
View File
@@ -157,7 +157,7 @@ TDropListClass<T>::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<class T>
void TDropListClass<T>::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);
}
+7 -4
View File
@@ -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);
+6
View File
@@ -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);
{
+43
View File
@@ -180,7 +180,50 @@ 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<const unsigned __int16*>(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) {
// 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
}
+2 -2
View File
@@ -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);
}
}
+2 -2
View File
@@ -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);
+2 -2
View File
@@ -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);
+1 -1
View File
@@ -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);
}