diff --git a/src/client/refresh/files/wal.c b/src/client/refresh/files/wal.c index 343b45ff..172d1cbf 100644 --- a/src/client/refresh/files/wal.c +++ b/src/client/refresh/files/wal.c @@ -57,3 +57,30 @@ GetWalInfo(char *name, int *width, int *height) return; } +void +GetM8Info(char *name, int *width, int *height) +{ + m8tex_t *mt; + int size; + + size = ri.FS_LoadFile(name, (void **)&mt); + + if (!mt) + { + return; + } + + + if (size < sizeof(m8tex_t) || LittleLong (mt->version) != M8_VERSION) + { + ri.FS_FreeFile((void *)mt); + return; + } + + *width = LittleLong(mt->width[0]); + *height = LittleLong(mt->height[0]); + + ri.FS_FreeFile((void *)mt); + + return; +} diff --git a/src/client/refresh/gl1/gl1_image.c b/src/client/refresh/gl1/gl1_image.c index 835dacb1..de1f7f90 100644 --- a/src/client/refresh/gl1/gl1_image.c +++ b/src/client/refresh/gl1/gl1_image.c @@ -1024,6 +1024,75 @@ LoadWal(char *origname, imagetype_t type) return image; } +static image_t * +LoadM8(char *origname, imagetype_t type) +{ + m8tex_t *mt; + int width, height, ofs, size; + image_t *image; + char name[256]; + unsigned char *image_buffer = NULL; + + Q_strlcpy(name, origname, sizeof(name)); + + /* Add the extension */ + if (strcmp(COM_FileExtension(name), "m8")) + { + Q_strlcat(name, ".m8", sizeof(name)); + } + + size = ri.FS_LoadFile(name, (void **)&mt); + + if (!mt) + { + R_Printf(PRINT_ALL, "%s: can't load %s\n", __func__, name); + return r_notexture; + } + + if (size < sizeof(m8tex_t)) + { + R_Printf(PRINT_ALL, "%s: can't load %s, small header\n", __func__, name); + ri.FS_FreeFile((void *)mt); + return r_notexture; + } + + if (LittleLong (mt->version) != M8_VERSION) + { + R_Printf(PRINT_ALL, "%s: can't load %s, wrong magic value.\n", __func__, name); + ri.FS_FreeFile ((void *)mt); + return r_notexture; + } + + width = LittleLong(mt->width[0]); + height = LittleLong(mt->height[0]); + ofs = LittleLong(mt->offsets[0]); + + if ((ofs <= 0) || (width <= 0) || (height <= 0) || + (((size - ofs) / height) < width)) + { + R_Printf(PRINT_ALL, "%s: can't load %s, small body\n", __func__, name); + ri.FS_FreeFile((void *)mt); + return r_notexture; + } + + image_buffer = malloc (width * height * 4); + for(int i=0; ipalette[value].r; + image_buffer[i * 4 + 1] = mt->palette[value].g; + image_buffer[i * 4 + 2] = mt->palette[value].b; + image_buffer[i * 4 + 3] = value == 255 ? 0 : 255; + } + + image = R_LoadPic(name, image_buffer, width, 0, height, 0, type, 32); + free(image_buffer); + + ri.FS_FreeFile((void *)mt); + + return image; +} + /* * Finds or loads the given image */ @@ -1128,12 +1197,20 @@ R_FindImage(char *name, imagetype_t type) image = R_LoadPic(name, pic, width, 0, height, 0, type, 8); } } - else if (strcmp(ext, "wal") == 0) + else if (strcmp(ext, "wal") == 0 || strcmp(ext, "m8") == 0) { if (gl_retexturing->value) { /* Get size of the original texture */ - GetWalInfo(name, &realwidth, &realheight); + if (strcmp(ext, "m8") == 0) + { + GetM8Info(name, &realwidth, &realheight); + } + else + { + GetWalInfo(name, &realwidth, &realheight); + } + if(realwidth == 0) { /* No texture found */ @@ -1149,6 +1226,10 @@ R_FindImage(char *name, imagetype_t type) image = R_LoadPic(name, pic, width, realwidth, height, realheight, type, 32); } + else if (strcmp(ext, "m8") == 0) + { + image = LoadM8(namewe, type); + } else { /* WAL if no TGA/PNG/JPEG available (exists always) */ @@ -1161,6 +1242,16 @@ R_FindImage(char *name, imagetype_t type) return NULL; } } + else if (strcmp(ext, "m8") == 0) + { + image = LoadM8(name, type); + + if (!image) + { + /* No texture found */ + return NULL; + } + } else /* gl_retexture is not set */ { image = LoadWal(name, type); @@ -1183,6 +1274,12 @@ R_FindImage(char *name, imagetype_t type) strcat(tmp_name, ".wal"); GetWalInfo(tmp_name, &realwidth, &realheight); + if (realwidth == 0 || realheight == 0) { + strcpy(tmp_name, namewe); + strcat(tmp_name, ".m8"); + GetM8Info(tmp_name, &realwidth, &realheight); + } + if (realwidth == 0 || realheight == 0) { /* It's a sky or model skin. */ strcpy(tmp_name, namewe); @@ -1199,6 +1296,10 @@ R_FindImage(char *name, imagetype_t type) { image = R_LoadPic(name, pic, width, realwidth, height, realheight, type, 32); } + else + { + return NULL; + } } else { diff --git a/src/client/refresh/gl1/gl1_model.c b/src/client/refresh/gl1/gl1_model.c index f85525be..d526e226 100644 --- a/src/client/refresh/gl1/gl1_model.c +++ b/src/client/refresh/gl1/gl1_model.c @@ -414,6 +414,12 @@ Mod_LoadTexinfo(lump_t *l) out->image = R_FindImage(name, it_wall); + if (!out->image || out->image == r_notexture) + { + Com_sprintf(name, sizeof(name), "textures/%s.m8", in->texture); + out->image = R_FindImage(name, it_wall); + } + if (!out->image) { R_Printf(PRINT_ALL, "Couldn't load %s\n", name); diff --git a/src/client/refresh/gl1/gl1_warp.c b/src/client/refresh/gl1/gl1_warp.c index 9d9e5676..1253d673 100644 --- a/src/client/refresh/gl1/gl1_warp.c +++ b/src/client/refresh/gl1/gl1_warp.c @@ -748,6 +748,13 @@ RI_SetSky(char *name, float rotate, vec3_t axis) sky_images[i] = R_FindImage(pathname, it_sky); + if (!sky_images[i] || sky_images[i] == r_notexture) + { + Com_sprintf(pathname, sizeof(pathname), "pics/Skies/%s%s.m8", + skyname, suf[i]); + sky_images[i] = R_FindImage(pathname, it_sky); + } + if (!sky_images[i]) { sky_images[i] = r_notexture; diff --git a/src/client/refresh/gl3/gl3_image.c b/src/client/refresh/gl3/gl3_image.c index 1fc00e8c..6c3ce937 100644 --- a/src/client/refresh/gl3/gl3_image.c +++ b/src/client/refresh/gl3/gl3_image.c @@ -608,6 +608,75 @@ LoadWal(char *origname, imagetype_t type) return image; } +static gl3image_t * +LoadM8(char *origname, imagetype_t type) +{ + m8tex_t *mt; + int width, height, ofs, size; + gl3image_t *image; + char name[256]; + unsigned char *image_buffer = NULL; + + Q_strlcpy(name, origname, sizeof(name)); + + /* Add the extension */ + if (strcmp(COM_FileExtension(name), "m8")) + { + Q_strlcat(name, ".m8", sizeof(name)); + } + + size = ri.FS_LoadFile(name, (void **)&mt); + + if (!mt) + { + R_Printf(PRINT_ALL, "%s: can't load %s\n", __func__, name); + return gl3_notexture; + } + + if (size < sizeof(m8tex_t)) + { + R_Printf(PRINT_ALL, "%s: can't load %s, small header\n", __func__, name); + ri.FS_FreeFile((void *)mt); + return gl3_notexture; + } + + if (LittleLong (mt->version) != M8_VERSION) + { + R_Printf(PRINT_ALL, "LoadWal: can't load %s, wrong magic value.\n", name); + ri.FS_FreeFile ((void *)mt); + return gl3_notexture; + } + + width = LittleLong(mt->width[0]); + height = LittleLong(mt->height[0]); + ofs = LittleLong(mt->offsets[0]); + + if ((ofs <= 0) || (width <= 0) || (height <= 0) || + (((size - ofs) / height) < width)) + { + R_Printf(PRINT_ALL, "%s: can't load %s, small body\n", __func__, name); + ri.FS_FreeFile((void *)mt); + return gl3_notexture; + } + + image_buffer = malloc (width * height * 4); + for(int i=0; ipalette[value].r; + image_buffer[i * 4 + 1] = mt->palette[value].g; + image_buffer[i * 4 + 2] = mt->palette[value].b; + image_buffer[i * 4 + 3] = value == 255 ? 0 : 255; + } + + image = GL3_LoadPic(name, image_buffer, width, 0, height, 0, type, 32); + free(image_buffer); + + ri.FS_FreeFile((void *)mt); + + return image; +} + /* * Finds or loads the given image */ @@ -712,12 +781,20 @@ GL3_FindImage(char *name, imagetype_t type) image = GL3_LoadPic(name, pic, width, 0, height, 0, type, 8); } } - else if (strcmp(ext, "wal") == 0) + else if (strcmp(ext, "wal") == 0 || strcmp(ext, "m8") == 0) { if (gl_retexturing->value) { /* Get size of the original texture */ - GetWalInfo(name, &realwidth, &realheight); + if (strcmp(ext, "m8") == 0) + { + GetM8Info(name, &realwidth, &realheight); + } + else + { + GetWalInfo(name, &realwidth, &realheight); + } + if(realwidth == 0) { /* No texture found */ @@ -732,6 +809,10 @@ GL3_FindImage(char *name, imagetype_t type) /* upload tga or png or jpg */ image = GL3_LoadPic(name, pic, width, realwidth, height, realheight, type, 32); } + else if (strcmp(ext, "m8") == 0) + { + image = LoadM8(namewe, type); + } else { /* WAL if no TGA/PNG/JPEG available (exists always) */ @@ -744,6 +825,16 @@ GL3_FindImage(char *name, imagetype_t type) return NULL; } } + else if (strcmp(ext, "m8") == 0) + { + image = LoadM8(name, type); + + if (!image) + { + /* No texture found */ + return NULL; + } + } else /* gl_retexture is not set */ { image = LoadWal(name, type); @@ -766,6 +857,12 @@ GL3_FindImage(char *name, imagetype_t type) strcat(tmp_name, ".wal"); GetWalInfo(tmp_name, &realwidth, &realheight); + if (realwidth == 0 || realheight == 0) { + strcpy(tmp_name, namewe); + strcat(tmp_name, ".m8"); + GetM8Info(tmp_name, &realwidth, &realheight); + } + if (realwidth == 0 || realheight == 0) { /* It's a sky or model skin. */ strcpy(tmp_name, namewe); @@ -781,6 +878,8 @@ GL3_FindImage(char *name, imagetype_t type) if(LoadSTB(name, ext, &pic, &width, &height)) { image = GL3_LoadPic(name, pic, width, realwidth, height, realheight, type, 32); + } else { + return NULL; } } else diff --git a/src/client/refresh/gl3/gl3_model.c b/src/client/refresh/gl3/gl3_model.c index 6fc03dd8..4b03a452 100644 --- a/src/client/refresh/gl3/gl3_model.c +++ b/src/client/refresh/gl3/gl3_model.c @@ -297,6 +297,12 @@ Mod_LoadTexinfo(lump_t *l) out->image = GL3_FindImage(name, it_wall); + if (!out->image || out->image == gl3_notexture) + { + Com_sprintf(name, sizeof(name), "textures/%s.m8", in->texture); + out->image = GL3_FindImage(name, it_wall); + } + if (!out->image) { R_Printf(PRINT_ALL, "Couldn't load %s\n", name); diff --git a/src/client/refresh/gl3/gl3_warp.c b/src/client/refresh/gl3/gl3_warp.c index 5062231b..59673155 100644 --- a/src/client/refresh/gl3/gl3_warp.c +++ b/src/client/refresh/gl3/gl3_warp.c @@ -329,6 +329,13 @@ GL3_SetSky(char *name, float rotate, vec3_t axis) sky_images[i] = GL3_FindImage(pathname, it_sky); + if (sky_images[i] == NULL || sky_images[i] == gl3_notexture) + { + Com_sprintf(pathname, sizeof(pathname), "pics/Skies/%s%s.m8", skyname, suf[i]); + + sky_images[i] = GL3_FindImage(pathname, it_sky); + } + if (sky_images[i] == NULL) { sky_images[i] = gl3_notexture; diff --git a/src/client/refresh/gl3/header/local.h b/src/client/refresh/gl3/header/local.h index 430639c1..13242854 100644 --- a/src/client/refresh/gl3/header/local.h +++ b/src/client/refresh/gl3/header/local.h @@ -187,8 +187,6 @@ typedef struct int prev_mode; - unsigned char *d_16to8table; - // each lightmap consists of 4 sub-lightmaps allowing changing shadows on the same surface // used for switching on/off light and stuff like that. // most surfaces only have one really and the remaining for are filled with dummy data diff --git a/src/client/refresh/ref_shared.h b/src/client/refresh/ref_shared.h index 3eb0c98d..b1b232e5 100644 --- a/src/client/refresh/ref_shared.h +++ b/src/client/refresh/ref_shared.h @@ -71,6 +71,7 @@ extern void scale2x(byte *src, byte *dst, int width, int height); extern void scale3x(byte *src, byte *dst, int width, int height); extern void GetWalInfo(char *name, int *width, int *height); +extern void GetM8Info(char *name, int *width, int *height); extern float Mod_RadiusFromBounds(const vec3_t mins, const vec3_t maxs); extern byte* Mod_DecompressVis(byte *in, int row); diff --git a/src/client/refresh/soft/sw_image.c b/src/client/refresh/soft/sw_image.c index 5c38a93b..d626aa27 100644 --- a/src/client/refresh/soft/sw_image.c +++ b/src/client/refresh/soft/sw_image.c @@ -299,6 +299,119 @@ R_Convert32To8bit(unsigned char* pic_in, unsigned char* pic_out, size_t size) } } +static void +R_FixPalette(unsigned char* pixels, size_t size, rgb_t* pallette) +{ + unsigned char* convert = malloc(256); + + size_t i; + + if (!d_16to8table) + { + free(convert); + return; + } + + for(i=0; i < 256; i ++) + { + unsigned int r, g, b, c; + + r = ( pallette[i].r >> 3 ) & 31; + g = ( pallette[i].g >> 2 ) & 63; + b = ( pallette[i].b >> 3 ) & 31; + + c = r | ( g << 5 ) | ( b << 11 ); + + convert[i] = d_16to8table[c & 0xFFFF]; + } + + for(i=0; i < size; i++) + { + pixels[i] = convert[pixels[i]]; + } + free(convert); +} + +/* +================ +R_LoadM8 +================ +*/ +static image_t * +R_LoadM8 (char *name, imagetype_t type) +{ + m8tex_t *mt; + int ofs, file_size; + image_t *image; + int size; + + file_size = ri.FS_LoadFile (name, (void **)&mt); + if (!mt) + { + R_Printf(PRINT_ALL, "%s: can't load %s\n", __func__, name); + return r_notexture_mip; + } + + if (file_size < sizeof(m8tex_t)) + { + R_Printf(PRINT_ALL, "%s: can't load %s, small header\n", __func__, name); + ri.FS_FreeFile ((void *)mt); + return r_notexture_mip; + } + + if (LittleLong (mt->version) != M8_VERSION) + { + R_Printf(PRINT_ALL, "%s: can't load %s, wrong magic value.\n", __func__, name); + ri.FS_FreeFile ((void *)mt); + return r_notexture_mip; + } + + image = R_FindFreeImage (); + strcpy (image->name, name); + image->width = LittleLong (mt->width[0]); + image->height = LittleLong (mt->height[0]); + image->type = type; + image->registration_sequence = registration_sequence; + ofs = LittleLong (mt->offsets[0]); + size = image->width * image->height * (256+64+16+4)/256; + + if ((ofs <= 0) || (image->width <= 0) || (image->height <= 0) || + ((file_size - ofs) / image->width < image->height)) + { + R_Printf(PRINT_ALL, "%s: can't load %s, small body\n", __func__, name); + ri.FS_FreeFile((void *)mt); + return r_notexture_mip; + } + + image->pixels[0] = malloc (size); + image->pixels[1] = image->pixels[0] + image->width*image->height; + image->pixels[2] = image->pixels[1] + image->width*image->height/4; + image->pixels[3] = image->pixels[2] + image->width*image->height/16; + + if (size > (file_size - ofs)) + { + memcpy(image->pixels[0], (byte *)mt + ofs, file_size - ofs); + // looks short, restore everything from first image + R_ImageShrink(image->pixels[0], image->pixels[1], + image->height, image->height/2, + image->width, image->width/2); + R_ImageShrink(image->pixels[1], image->pixels[2], + image->height/2, image->height/4, + image->width/2, image->width/4); + R_ImageShrink(image->pixels[2], image->pixels[3], + image->height/4, image->height/8, + image->width/4, image->width/8); + } + else + { + memcpy ( image->pixels[0], (byte *)mt + ofs, size); + } + + R_FixPalette(image->pixels[0], size, mt->palette); + ri.FS_FreeFile ((void *)mt); + return image; +} + static image_t * R_LoadHiColorImage(char *name, const char* namewe, const char *ext, imagetype_t type) { @@ -317,6 +430,11 @@ R_LoadHiColorImage(char *name, const char* namewe, const char *ext, imagetype_t /* Get size of the original texture */ GetWalInfo(name, &realwidth, &realheight); } + else if (strcmp(ext, "m8") == 0) + { + /* Get size of the original texture */ + GetM8Info(name, &realwidth, &realheight); + } /* try to load a tga, png or jpg (in that order/priority) */ if ( LoadSTB(namewe, "tga", &pic, &width, &height) @@ -415,6 +533,10 @@ R_LoadImage(char *name, const char* namewe, const char *ext, imagetype_t type) { image = R_LoadWal(name, type); } + else if (strcmp(ext, "m8") == 0) + { + image = R_LoadM8 (name, type); + } } return image; diff --git a/src/client/refresh/soft/sw_main.c b/src/client/refresh/soft/sw_main.c index 6c631e2c..4ecf073e 100644 --- a/src/client/refresh/soft/sw_main.c +++ b/src/client/refresh/soft/sw_main.c @@ -1722,6 +1722,11 @@ RE_SetSky (char *name, float rotate, vec3_t axis) { Com_sprintf (pathname, sizeof(pathname), "env/%s%s.pcx", skyname, suf[r_skysideimage[i]]); r_skytexinfo[i].image = R_FindImage (pathname, it_sky); + if (!r_skytexinfo[i].image) + { + Com_sprintf (pathname, sizeof(pathname), "pics/Skies/%s%s.m8", skyname, suf[r_skysideimage[i]]); + r_skytexinfo[i].image = R_FindImage (pathname, it_sky); + } } } diff --git a/src/client/refresh/soft/sw_model.c b/src/client/refresh/soft/sw_model.c index c887147e..ad4ee8f5 100644 --- a/src/client/refresh/soft/sw_model.c +++ b/src/client/refresh/soft/sw_model.c @@ -514,6 +514,12 @@ Mod_LoadTexinfo (lump_t *l) Com_sprintf (name, sizeof(name), "textures/%s.wal", in->texture); out->image = R_FindImage (name, it_wall); + if (!out->image || out->image == r_notexture_mip) + { + Com_sprintf (name, sizeof(name), "textures/%s.m8", in->texture); + out->image = R_FindImage (name, it_wall); + } + if (!out->image) { out->image = r_notexture_mip; // texture not found diff --git a/src/client/refresh/vk/vk_image.c b/src/client/refresh/vk/vk_image.c index 18d9cacc..fc275293 100644 --- a/src/client/refresh/vk/vk_image.c +++ b/src/client/refresh/vk/vk_image.c @@ -1055,6 +1055,75 @@ static image_t *Vk_LoadWal (char *name, imagetype_t type) return image; } +static image_t * +Vk_LoadM8(char *origname, imagetype_t type) +{ + m8tex_t *mt; + int width, height, ofs, size; + image_t *image; + char name[256]; + unsigned char *image_buffer = NULL; + + Q_strlcpy(name, origname, sizeof(name)); + + /* Add the extension */ + if (strcmp(COM_FileExtension(name), "m8")) + { + Q_strlcat(name, ".m8", sizeof(name)); + } + + size = ri.FS_LoadFile(name, (void **)&mt); + + if (!mt) + { + R_Printf(PRINT_ALL, "%s: can't load %s\n", __func__, name); + return r_notexture; + } + + if (size < sizeof(m8tex_t)) + { + R_Printf(PRINT_ALL, "%s: can't load %s, small header\n", __func__, name); + ri.FS_FreeFile((void *)mt); + return r_notexture; + } + + if (LittleLong (mt->version) != M8_VERSION) + { + R_Printf(PRINT_ALL, "LoadWal: can't load %s, wrong magic value.\n", name); + ri.FS_FreeFile ((void *)mt); + return r_notexture; + } + + width = LittleLong(mt->width[0]); + height = LittleLong(mt->height[0]); + ofs = LittleLong(mt->offsets[0]); + + if ((ofs <= 0) || (width <= 0) || (height <= 0) || + (((size - ofs) / height) < width)) + { + R_Printf(PRINT_ALL, "%s: can't load %s, small body\n", __func__, name); + ri.FS_FreeFile((void *)mt); + return r_notexture; + } + + image_buffer = malloc (width * height * 4); + for(int i=0; ipalette[value].r; + image_buffer[i * 4 + 1] = mt->palette[value].g; + image_buffer[i * 4 + 2] = mt->palette[value].b; + image_buffer[i * 4 + 3] = value == 255 ? 0 : 255; + } + + image = Vk_LoadPic(name, image_buffer, width, width, height, height, type, 32); + free(image_buffer); + + ri.FS_FreeFile((void *)mt); + + return image; +} + static image_t* Vk_LoadHiColorImage(char *name, const char* namewe, const char *ext, imagetype_t type) { @@ -1073,6 +1142,11 @@ Vk_LoadHiColorImage(char *name, const char* namewe, const char *ext, imagetype_t /* Get size of the original texture */ GetWalInfo(name, &realwidth, &realheight); } + else if (strcmp(ext, "m8") == 0) + { + /* Get size of the original texture */ + GetM8Info(name, &realwidth, &realheight); + } /* try to load a tga, png or jpg (in that order/priority) */ if ( LoadSTB(namewe, "tga", &pic, &width, &height) @@ -1142,6 +1216,10 @@ Vk_LoadImage(char *name, const char* namewe, const char *ext, imagetype_t type) { image = Vk_LoadWal (name, type); } + else if (!strcmp(ext, "m8")) + { + image = Vk_LoadM8 (name, type); + } else if (!strcmp(ext, "tga")) { if (!LoadSTB (namewe, "tga", &pic, &width, &height)) diff --git a/src/client/refresh/vk/vk_model.c b/src/client/refresh/vk/vk_model.c index ac636070..016d059d 100644 --- a/src/client/refresh/vk/vk_model.c +++ b/src/client/refresh/vk/vk_model.c @@ -434,6 +434,12 @@ static void Mod_LoadTexinfo (lump_t *l) Com_sprintf (name, sizeof(name), "textures/%s.wal", in->texture); out->image = Vk_FindImage (name, it_wall); + if (!out->image || out->image == r_notexture) + { + Com_sprintf (name, sizeof(name), "textures/%s.m8", in->texture); + out->image = Vk_FindImage (name, it_wall); + } + if (!out->image) { R_Printf(PRINT_ALL, "Couldn't load %s\n", name); diff --git a/src/client/refresh/vk/vk_warp.c b/src/client/refresh/vk/vk_warp.c index 1b868245..c33befc7 100644 --- a/src/client/refresh/vk/vk_warp.c +++ b/src/client/refresh/vk/vk_warp.c @@ -687,6 +687,11 @@ void RE_SetSky (char *name, float rotate, vec3_t axis) Com_sprintf(pathname, sizeof(pathname), "env/%s%s.tga", skyname, suf[i]); sky_images[i] = Vk_FindImage(pathname, it_sky); + if (!sky_images[i]) { + Com_sprintf(pathname, sizeof(pathname), "pics/Skies/%s%s.m8", skyname, suf[i]); + sky_images[i] = Vk_FindImage(pathname, it_sky); + } + if (!sky_images[i]) sky_images[i] = r_notexture; diff --git a/src/common/header/files.h b/src/common/header/files.h index 87e1cf30..2d00a190 100644 --- a/src/common/header/files.h +++ b/src/common/header/files.h @@ -174,6 +174,31 @@ typedef struct miptex_s int value; } miptex_t; +/* .M8 texture file format */ + +#define M8_MIP_LEVELS 16 +#define M8_VERSION 0x2 + +typedef struct { + unsigned char r; + unsigned char g; + unsigned char b; +} rgb_t; + +typedef struct m8tex_s +{ + unsigned version; + char name[32]; + unsigned width[M8_MIP_LEVELS]; + unsigned height[M8_MIP_LEVELS]; + unsigned offsets[M8_MIP_LEVELS]; /* 16 mip maps stored */ + char animname[32]; /* next frame in animation chain */ + rgb_t palette[256]; + int flags; + int contents; + int value; +} m8tex_t; + /* .BSP file format */ #define IDBSPHEADER (('P' << 24) + ('S' << 16) + ('B' << 8) + 'I') /* little-endian "IBSP" */