Files
Cesarus85--ringfall-mjolnir-vr/source/bitmaps/bitmap_extract.c
T

1085 lines
29 KiB
C

/*
BITMAP_EXTRACT.C
symbols in this file:
00061EA0 0130:
_extract_initialize (0000)
00061FD0 0120:
_extract_find_sequence_bounds (0000)
000620F0 0080:
_extract_warn_about_horizontal_border (0000)
00062170 0340:
_extract_plateless_cube_map (0000)
000624B0 0190:
_extract_find_bitmap_bounds (0000)
00062640 0240:
_code_00062640 (0000)
00062880 03b0:
_code_00062880 (0000)
00062C30 0210:
_code_00062c30 (0000)
00062E40 0260:
_code_00062e40 (0000)
000630A0 0580:
_extract_build_debug_plate (0000)
00063620 03d0:
_code_00063620 (0000)
000639F0 02b0:
_extract_add_bitmap (0000)
00063CA0 01d0:
_extract_3d_textures (0000)
00063E70 0220:
_extract_cube_maps (0000)
00064090 0450:
_extract_sprites (0000)
000644E0 0490:
_extract_bitmap (0000)
00064970 0110:
_extract_without_sequences (0000)
00064A80 02d0:
_extract_sequence (0000)
00064D50 00b0:
_extract_sequences (0000)
00064E00 02e0:
_bitmaps_extract (0000)
000650E0 0130:
_bitmaps_extract_from_plate (0000)
00251290 000e:
??_C@_0O@IOJAHIHH@top_reference?$AA@ (0000)
002512A0 0028:
??_C@_0CI@MDNPJHJC@c?3?2halo?2SOURCE?2bitmaps?2bitmap_ex@ (0000)
002512C8 0034:
??_C@_0DE@MPBEDKDP@?$CD?$CD?$CD?5WARNING?5horizontal?5border?5br@ (0000)
00251300 0045:
??_C@_0EF@HOBDLMPH@?$CD?$CD?$CD?5ERROR?5extract?3?5plateless?5cub@ (0000)
00251348 0042:
??_C@_0EC@CNAGFICN@?$CD?$CD?$CD?5ERROR?5extract?3?5can?8t?5handle?5@ (0000)
0025138C 0037:
??_C@_0DH@JLCLDNBC@?$CD?$CD?$CD?5ERROR?5extract?3?5failed?5to?5all@ (0000)
002513C4 001c:
??_C@_0BM@HDLJMFAA@bitmap_verify?$CIbitmap?0?5TRUE?$CJ?$AA@ (0000)
002513E0 001a:
??_C@_0BK@OPAPKIME@adjusted_bounds_reference?$AA@ (0000)
002513FC 0007:
??_C@_06CGBPGGIE@bounds?$AA@ (0000)
00251404 0033:
??_C@_0DD@OAKGMMJC@?$CD?$CD?$CD?5ERROR?5extract?3?5unsupported?5b@ (0000)
00251438 0024:
??_C@_0CE@MAGCMLBE@?$CD?$CD?$CD?5ERROR?5unsupported?5bitmap?5for@ (0000)
0025145C 003c:
??_C@_0DM@JCMHMNJE@?$CBTEST_FLAG?$CIdestination_bitmap?9?$DOf@ (0000)
00251498 005a:
??_C@_0FK@KAGBNKPE@destination_mipmap_index?$DO?$DN0?5?$CG?$CG?5d@ (0000)
002514F4 002e:
??_C@_0CO@MKAFAHJI@destination_bitmap?9?$DOtype?$DN?$DNsource@ (0000)
00251524 0029:
??_C@_0CJ@PMPPCDAH@bitmap_verify?$CIdestination_bitmap@ (0000)
00251550 0054:
??_C@_0FE@NNBMCEJD@source_bitmap?9?$DOdepth?5?$DN?$DNMAX?$CI1?0?5de@ (0000)
002515A8 0054:
??_C@_0FE@NIAAMOKD@source_bitmap?9?$DOheight?$DN?$DNMAX?$CI1?0?5de@ (0000)
00251600 0054:
??_C@_0FE@OGKNFLAG@source_bitmap?9?$DOwidth?5?$DN?$DNMAX?$CI1?0?5de@ (0000)
00251654 0023:
??_C@_0CD@ECDENEFB@bitmap_verify?$CIsource_bitmap?0?5TRU@ (0000)
00251678 004b:
??_C@_0EL@CICFBLGI@source_mipmap_index?$DO?$DN0?5?$CG?$CG?5source@ (0000)
002516C4 002e:
??_C@_0CO@LIKJMDNH@source_bitmap?9?$DOtype?$DN?$DNdestination@ (0000)
002516F4 0024:
??_C@_0CE@HECEPIHL@bitmap_verify?$CIsource_bitmap?0?5FAL@ (0000)
00251718 004f:
??_C@_0EP@JCFKDNGM@destination_bitmap?9?$DOdepth?5?$DN?$DNMAX?$CI@ (0000)
00251768 004f:
??_C@_0EP@KOPMFNGM@destination_bitmap?9?$DOheight?$DN?$DNMAX?$CI@ (0000)
002517B8 004f:
??_C@_0EP@OEMHGOAI@destination_bitmap?9?$DOwidth?5?$DN?$DNMAX?$CI@ (0000)
00251808 0028:
??_C@_0CI@JBLFEOIJ@bitmap_verify?$CIdestination_bitmap@ (0000)
00251830 0024:
??_C@_0CE@LCCMCEAJ@sequence?5spanned?5?$CFd?5texture?5page@ (0000)
00251854 0030:
??_C@_0DA@BOIOHNMC@?$CD?$CD?$CD?5ERROR?5failed?5to?5allocate?5deb@ (0000)
00251884 0030:
??_C@_0DA@NMPFGKNI@?$CD?$CD?$CD?5ERROR?5failed?5to?5allocate?5deb@ (0000)
002518B4 002a:
??_C@_0CK@DMHGHFA@?$CD?$CD?$CD?5ERROR?5failed?5to?5allocate?5deb@ (0000)
002518E0 0022:
??_C@_0CC@DECIGGNF@?$CD?$CD?$CD?5ERROR?5unsupported?5bitmap?5typ@ (0000)
00251904 0024:
??_C@_0CE@BAFBIHF@alpha_bias?$DO?$DN?9255?5?$CG?$CG?5alpha_bias?$DM?$DN@ (0000)
00251928 0030:
??_C@_0DA@KOPAIHGJ@destination_bitmap?9?$DOdepth?$DN?$DNsourc@ (0000)
00251958 0032:
??_C@_0DC@IECBCEHB@destination_bitmap?9?$DOheight?$DN?$DNsour@ (0000)
0025198C 0030:
??_C@_0DA@LLNHMAL@destination_bitmap?9?$DOwidth?$DN?$DNsourc@ (0000)
002519BC 0021:
??_C@_0CB@CLPJEELI@destination_bitmap?9?$DObase_address@ (0000)
002519E0 0013:
??_C@_0BD@JMEMKNJH@destination_bitmap?$AA@ (0000)
002519F4 0029:
??_C@_0CJ@PEGGHKHE@bitmap?5created?3?5?$CD?$CFdx?$CD?$CFd?0?5?$CFs?0?5?$CFdK@ (0000)
00251A20 002d:
??_C@_0CN@MGDDLHDM@bitmap?5created?3?5?$CD?$CFdx?$CD?$CFdx?$CD?$CFd?0?5?$CFs?0@ (0000)
00251A50 0028:
??_C@_0CI@GPIJKLOM@?$CD?$CD?$CD?5ERROR?5unsupported?5bitmap?5gro@ (0000)
00251A78 0036:
??_C@_0DG@OFJIKCDA@?$CD?$CD?$CD?5WARNING?5tried?5to?5smooth?5an?5i@ (0000)
00251AB0 002b:
??_C@_0CL@CJDNFNLC@?$CD?$CD?$CD?5WARNING?5tried?5to?5smooth?5a?5sp@ (0000)
00251ADC 0003:
??_C@_02PCIJFNDE@?$AN?6?$AA@ (0000)
00251AE0 0038:
??_C@_0DI@GIJPOGBA@skipping?53D?5texture?5with?5non?5pow@ (0000)
00251B18 002f:
??_C@_0CP@OCGAOEDI@skipping?53D?5texture?5with?5incompa@ (0000)
00251B48 0035:
??_C@_0DF@CHABNBMJ@?$CD?$CD?$CD?5ERROR?5extract?3?5failed?5to?5cre@ (0000)
00251B80 002b:
??_C@_0CL@KIGCKIOC@skipping?5cube?5map?5which?5spanned?5@ (0000)
00251BAC 0031:
??_C@_0DB@JFFHMOLJ@skipping?5cube?5map?5with?5incompati@ (0000)
00251BE0 002d:
??_C@_0CN@GHMACEEI@skipping?5cube?5map?5with?5less?5than@ (0000)
00251C10 002a:
??_C@_0CK@MAFGCHJA@skipping?5cube?5map?5with?5non?9squar@ (0000)
00251C3C 0012:
??_C@_0BC@OIPPCJDD@?$CBtemporary_bitmap?$AA@ (0000)
00251C50 002b:
??_C@_0CL@MNFLENMO@?$CD?$CD?$CD?5ERROR?5sprite?5budget?5exceeded@ (0000)
00251C7C 001e:
??_C@_0BO@PEKHFDDE@sprite?5budget?5met?5?$CI?$CF3?40f?$CF?$CF?$CJ?$AN?6?$AA@ (0000)
00251C9C 0023:
??_C@_0CD@PAPLMEDP@?$CD?$CD?$CD?5WARNING?5no?5sprite?5budget?5set@ (0000)
00251CC0 002e:
??_C@_0CO@CKBCALDJ@texture?5page?5created?5?$CD?$CFdx?$CD?$CFd?5?$CI?$CF3@ (0000)
00251CF0 0041:
??_C@_0EB@GJMFGLDP@?$CD?$CD?$CD?5ERROR?5extract_sprite?3?5failed@ (0000)
00251D38 0084:
??_C@_0IE@MKAIONEP@?$CD?$CD?$CD?5ERROR?5hey?5?9?5don?8t?5even?5try?5i@ (0000)
00251DC0 0044:
??_C@_0EE@DCBFAMBD@?$CD?$CD?$CD?5ERROR?5one?5or?5more?5sprites?5do@ (0000)
00251E04 0037:
??_C@_0DH@NFCBCMJC@?$CD?$CD?$CD?5WARNING?5skipped?5a?5bitmap?5whi@ (0000)
00251E3C 0034:
??_C@_0DE@MGADPMCF@?$CD?$CD?$CD?5ERROR?5extract?3?5failed?5to?5add@ (0000)
00251E70 0097:
??_C@_0JH@OBKFAPGC@?$CD?$CD?$CD?5ERROR?5extract?3?5tried?5to?5extr@ (0000)
00251F08 003b:
??_C@_0DL@FLDEAMAO@?$CD?$CD?$CD?5ERROR?5interface?1linear?5bitma@ (0000)
00251F48 0054:
??_C@_0FE@BCCMGDBK@?$DN?$DN?$DO?5?$CB?$CBWARNING?$CB?$CB?5bitmap?5with?5grea@ (0000)
00251FA0 0052:
??_C@_0FC@GFFGPBON@?$DN?$DN?$DO?5?$CB?$CBWARNING?$CB?$CB?5usage?5set?5to?5alp@ (0000)
00251FF4 0036:
??_C@_0DG@DKLFGIJN@?$CD?$CD?$CD?5ERROR?5can?8t?5extract?5sprites?5@ (0000)
0025202C 003a:
??_C@_0DK@PBJHAOGB@?$CD?$CD?$CD?5ERROR?5can?8t?5extract?53D?5textu@ (0000)
00252068 0053:
??_C@_0FD@OJBFAEHG@?$CD?$CD?$CD?5ERROR?5extract?3?5compressed?5co@ (0000)
002520BC 0023:
??_C@_0CD@LJHCCFGP@bottom?$DM?$DNextract_data?4plate?9?$DOheig@ (0000)
002520E0 000c:
??_C@_0M@NNAAFJDK@bottom?$DO?$DNtop?$AA@ (0000)
002520EC 0007:
??_C@_06JJMFEGFL@top?$DO?$DN0?$AA@ (0000)
002520F4 002f:
??_C@_0CP@LHGGIDHB@?$CD?$CD?$CD?5ERROR?5extract?3?5failed?5to?5all@ (0000)
00252124 0032:
??_C@_0DC@MGLFJBKA@?$CD?$CD?$CD?5ERROR?5extract?3?5failed?5to?5all@ (0000)
00252158 0034:
??_C@_0DE@BGBBNNDB@?$CD?$CD?$CD?5ERROR?5extract?3?5failed?5to?5dec@ (0000)
00252190 0052:
??_C@_0FC@OEKPABF@decompressed_plate_size?$DN?$DNsizeof?$CI@ (0000)
002521E4 003e:
??_C@_0DO@EDMJDNFC@?$CD?$CD?$CD?5ERROR?5extract?3?5failed?5to?5res@ (0000)
00252224 0033:
??_C@_0DD@FAIEDAFJ@?$CD?$CD?$CD?5ERROR?5extract?3?5failed?5to?5all@ (0000)
00252258 0040:
??_C@_0EA@PFFINKKO@group?9?$DOusage?5?$DO?$DN0?5?$CG?$CG?5group?9?$DOusage@ (0000)
00252298 0041:
??_C@_0EB@OKMLMBHL@group?9?$DOformat?$DO?$DN0?5?$CG?$CG?5group?9?$DOforma@ (0000)
002522DC 003d:
??_C@_0DN@FIMFNAFO@group?9?$DOtype?5?$DO?$DN0?5?$CG?$CG?5group?9?$DOtype?5?$DM@ (0000)
0025231C 0006:
??_C@_05MGJOOGAJ@group?$AA@ (0000)
00252324 0037:
??_C@_0DH@BHCBHGEP@?$CD?$CD?$CD?5ERROR?5extract?3?5failed?5to?5all@ (0000)
0025235C 0032:
??_C@_0DC@MDFBMDEG@?$CD?$CD?$CD?5ERROR?5extract?3?5failed?5to?5com@ (0000)
00252390 0031:
??_C@_0DB@KLKAOHKM@?$CD?$CD?$CD?5ERROR?5extract?3?5failed?5to?5rea@ (0000)
002523C4 001b:
??_C@_0BL@KAAMGFCF@bitmap_verify?$CIplate?0?5TRUE?$CJ?$AA@ (0000)
0031BED4 002c:
_extract_data (0000)
*/
/* ---------- headers */
#include "cseries.h"
#include "bitmaps/bitmap_group.h"
#include "bitmaps/bitmaps.h"
#include "bitmaps/bitmaps_internal.h"
#include "cache/cache_files.h"
#include "cseries/errors.h"
#include "math/integer_math.h"
#include "memory/data_compress.h"
/* ---------- constants */
enum
{
_bitmap_group_type_2d_textures,
_bitmap_group_type_3d_textures,
_bitmap_group_type_cube_maps,
_bitmap_group_type_sprites,
_bitmap_group_type_interface_bitmaps,
NUMBER_OF_BITMAP_GROUP_TYPES
};
enum
{
_bitmap_group_format_compressed_color_key_transparency,
_bitmap_group_format_compressed_explicit_alpha,
_bitmap_group_format_compressed_interpolated_alpha,
_bitmap_group_format_16bit_color,
_bitmap_group_format_32bit_color,
_bitmap_group_format_monochrome,
NUMBER_OF_BITMAP_GROUP_FORMATS
};
enum
{
_bitmap_group_usage_alpha_blend,
_bitmap_group_usage_default,
_bitmap_group_usage_height_map,
_bitmap_group_usage_detail_map,
_bitmap_group_usage_light_map,
_bitmap_group_usage_vector_map,
NUMBER_OF_BITMAP_GROUP_USAGES
};
enum
{
_bitmap_format_a8r8g8b8 = 11,
};
enum
{
_bitmap_group_extract_sprites_filthy_bug_fix_bit = 3,
};
/* ---------- macros */
/* ---------- structures */
struct bitmap_group_sprite
{
short bitmap_index;
word bitmap_pad;
long unused;
real_rectangle2d bounds;
real_point2d registration_point;
};
struct bitmap_group_sequence
{
char name[32];
short first_bitmap_index;
short bitmap_count;
long unused[4];
struct tag_block sprites;
};
struct bitmap_extract_data
{
struct bitmap_extract_entry *bitmaps;
short bitmap_count;
pixel32 top_reference;
pixel32 bottom_reference;
pixel32 adjusted_bounds_reference;
boolean extract_sequences;
boolean single_sequence;
struct bitmap_group *group;
struct bitmap_data *plate;
long build_debug_plate;
struct bitmap_group_sequence *sequence;
short sequence_index;
short bitmap_index;
};
struct bitmap_extract_entry
{
struct bitmap_data *bitmap;
short sequence_index;
short sprite_index;
short page_index;
word unused;
long page_entry_index;
};
typedef char bitmap_group_sprite_size_assert[
sizeof(struct bitmap_group_sprite) == 0x20 ? 1 : -1];
typedef char bitmap_group_sequence_size_assert[
sizeof(struct bitmap_group_sequence) == 0x40 ? 1 : -1];
typedef char bitmap_extract_entry_size_assert[
sizeof(struct bitmap_extract_entry) == 0x10 ? 1 : -1];
typedef char bitmap_extract_data_size_assert[
sizeof(struct bitmap_extract_data) == 0x2C ? 1 : -1];
/* ---------- prototypes */
static void extract_initialize(
void);
static short extract_find_sequence_bounds(
short *top_reference);
static void extract_warn_about_horizontal_border(
short bottom);
static boolean extract_find_bitmap_bounds(
rectangle2d const *bounds,
rectangle2d *adjusted_bounds_reference);
static boolean extract_sequences(
void);
static boolean extract_without_sequences(
void);
boolean extract_plateless_cube_map(
struct bitmap_data *bitmap);
short extract_add_bitmap(
struct bitmap_data *bitmap);
boolean extract_3d_textures(
void);
boolean extract_cube_maps(
void);
boolean extract_sprites(
void);
static boolean extract_bitmap(
rectangle2d const *bounds);
boolean extract_sequence(
short top,
short bottom);
/* ---------- globals */
static struct bitmap_extract_data extract_data;
/* ---------- public code */
boolean bitmaps_extract(
struct bitmap_group *group,
long build_debug_plate)
{
unsigned long decompressed_plate_size;
boolean should_extract_sequences;
boolean result;
match_assert("c:\\halo\\SOURCE\\bitmaps\\bitmap_extract.c", 0xB4, group);
match_assert(
"c:\\halo\\SOURCE\\bitmaps\\bitmap_extract.c",
0xB5,
group->type >=0 && group->type <NUMBER_OF_BITMAP_GROUP_TYPES);
match_assert(
"c:\\halo\\SOURCE\\bitmaps\\bitmap_extract.c",
0xB6,
group->format>=0 && group->format<NUMBER_OF_BITMAP_GROUP_FORMATS);
match_assert(
"c:\\halo\\SOURCE\\bitmaps\\bitmap_extract.c",
0xB7,
group->usage >=0 && group->usage <NUMBER_OF_BITMAP_GROUP_USAGES);
extract_data.bitmap_count = 0;
extract_data.bitmaps = match_malloc(
"c:\\halo\\SOURCE\\bitmaps\\bitmap_extract.c",
0xBA,
0x4000);
if (!extract_data.bitmaps)
{
error(_error_silent, "### ERROR extract: failed to allocate bitmap array");
}
else if (tag_block_resize(&group->bitmap_data, 0) &&
tag_block_resize(&group->sequences, 0) &&
tag_data_resize(&group->pixel_data, 0))
{
extract_data.sequence = NULL;
extract_data.sequence_index = NONE;
extract_data.group = group;
extract_data.plate = bitmap_2d_new(
group->import_width,
group->import_height,
0,
_bitmap_format_a8r8g8b8);
if (!extract_data.plate)
{
error(_error_silent, "### ERROR extract: failed to allocate color plate");
result = FALSE;
}
else
{
decompressed_plate_size = data_decompressed_size(
group->import_bitmap.address,
group->import_bitmap.size);
match_assert(
"c:\\halo\\SOURCE\\bitmaps\\bitmap_extract.c",
0x104,
decompressed_plate_size == sizeof(pixel32) * group->import_width * group->import_height);
if (data_decompress(
group->import_bitmap.address,
group->import_bitmap.size,
bitmap_mipmap_address(extract_data.plate, 0),
&decompressed_plate_size,
decompressed_plate_size))
{
extract_initialize();
should_extract_sequences = extract_data.extract_sequences;
extract_data.build_debug_plate = build_debug_plate;
if (should_extract_sequences)
result = extract_sequences();
else
result = extract_without_sequences();
bitmap_delete(extract_data.plate);
if (result)
{
switch (extract_data.group->type)
{
case _bitmap_group_type_2d_textures:
case _bitmap_group_type_interface_bitmaps:
break;
case _bitmap_group_type_3d_textures:
result = extract_3d_textures();
break;
case _bitmap_group_type_cube_maps:
result = extract_cube_maps();
break;
case _bitmap_group_type_sprites:
result = extract_sprites();
break;
default:
match_vassert(
"c:\\halo\\SOURCE\\bitmaps\\bitmap_extract.c",
0x137,
FALSE,
"### ERROR unsupported bitmap group type");
}
}
}
else
{
error(_error_silent, "### ERROR extract: failed to decompress color plate");
result = FALSE;
}
}
goto cleanup;
}
error(_error_silent, "### ERROR extract: failed to resize bitmap group tags to zero");
result = FALSE;
cleanup:
if (extract_data.bitmaps)
{
match_free(
"c:\\halo\\SOURCE\\bitmaps\\bitmap_extract.c",
0x13D,
extract_data.bitmaps);
}
return result;
}
boolean bitmaps_extract_from_plate(
struct bitmap_data *plate,
struct bitmap_group *group,
long build_debug_plate)
{
long compressed_color_plate_size;
void *compressed_color_plate;
match_assert("c:\\halo\\SOURCE\\bitmaps\\bitmap_extract.c", 0x83, bitmap_verify(plate, TRUE));
match_assert("c:\\halo\\SOURCE\\bitmaps\\bitmap_extract.c", 0x84, group);
compressed_color_plate_size = bitmap_get_pixel_data_size(plate);
group->import_width = plate->width;
group->import_height = plate->height;
group->import_bitmap.address = match_malloc(
"c:\\halo\\SOURCE\\bitmaps\\bitmap_extract.c",
0x8A,
compressed_color_plate_size);
if (group->import_bitmap.address)
{
if (data_compress(
bitmap_mipmap_address(plate, 0),
compressed_color_plate_size,
group->import_bitmap.address,
&compressed_color_plate_size,
compressed_color_plate_size))
{
compressed_color_plate = match_realloc(
"c:\\halo\\SOURCE\\bitmaps\\bitmap_extract.c",
0x90,
group->import_bitmap.address,
compressed_color_plate_size);
if (compressed_color_plate)
{
group->import_bitmap.address = compressed_color_plate;
group->import_bitmap.size = compressed_color_plate_size;
return bitmaps_extract(group, build_debug_plate);
}
error(_error_silent, "### ERROR extract: failed to realloc color plate");
return FALSE;
}
error(_error_silent, "### ERROR extract: failed to compress color plate");
return FALSE;
}
error(_error_silent, "### ERROR extract: failed to allocate temporary buffer");
return FALSE;
}
/* ---------- private code */
static void extract_initialize(
void)
{
short x;
extract_data.extract_sequences = TRUE;
extract_data.single_sequence = FALSE;
extract_data.top_reference =
*(pixel32 *)bitmap_2d_address(extract_data.plate, 0, 0, 0) & 0xFFFFFF;
extract_data.bottom_reference =
*(pixel32 *)bitmap_2d_address(extract_data.plate, 1, 0, 0) & 0xFFFFFF;
extract_data.adjusted_bounds_reference =
*(pixel32 *)bitmap_2d_address(extract_data.plate, 2, 0, 0) & 0xFFFFFF;
if (extract_data.adjusted_bounds_reference == extract_data.bottom_reference &&
extract_data.bottom_reference != 0xFF)
{
extract_data.extract_sequences = FALSE;
}
if (extract_data.top_reference == extract_data.bottom_reference)
{
extract_data.adjusted_bounds_reference = 0xFFFF;
extract_data.single_sequence = TRUE;
}
for (x = 3; x < extract_data.plate->width; x++)
{
pixel32 top = *(pixel32 *)bitmap_2d_address(extract_data.plate, x, 0, 0) & 0xFFFFFF;
pixel32 bottom = *(pixel32 *)bitmap_2d_address(extract_data.plate, x, 1, 0) & 0xFFFFFF;
if (top != extract_data.top_reference &&
bottom != extract_data.bottom_reference)
{
extract_data.extract_sequences = FALSE;
}
}
if (!extract_data.extract_sequences)
{
extract_data.adjusted_bounds_reference = 0xFF000000;
extract_data.bottom_reference = 0xFF000000;
extract_data.top_reference = 0xFF000000;
}
return;
}
static short extract_find_sequence_bounds(
short *top_reference)
{
short bottom;
match_assert(
"c:\\halo\\SOURCE\\bitmaps\\bitmap_extract.c",
0x1D9,
top_reference);
if (extract_data.single_sequence)
{
boolean found_sequence = FALSE;
for (bottom = *top_reference; bottom < extract_data.plate->height; bottom++)
{
short x;
boolean found_sequence_pixel = FALSE;
for (x = 0; x < extract_data.plate->width; x++)
{
pixel32 color = *(pixel32 *)bitmap_2d_address(
extract_data.plate,
x,
bottom,
0) & 0xFFFFFF;
if (color != extract_data.top_reference)
found_sequence_pixel = TRUE;
}
if (found_sequence_pixel)
{
found_sequence = TRUE;
}
else if (found_sequence)
{
break;
}
else
{
*top_reference = bottom + 1;
}
}
}
else
{
boolean found_top_reference = FALSE;
for (bottom = *top_reference; bottom < extract_data.plate->height; bottom++)
{
pixel32 color = *(pixel32 *)bitmap_2d_address(
extract_data.plate,
0,
bottom,
0) & 0xFFFFFF;
if (color == extract_data.top_reference)
{
found_top_reference = TRUE;
}
else if (color == extract_data.bottom_reference && found_top_reference)
{
break;
}
else
{
*top_reference = bottom + 1;
}
}
}
return bottom;
}
static void extract_warn_about_horizontal_border(
short bottom)
{
if (VALID_INDEX(bottom, extract_data.plate->height))
{
short x;
for (x = 0; x < extract_data.plate->width; x++)
{
pixel32 color = *(pixel32 *)bitmap_2d_address(
extract_data.plate,
x,
bottom,
0) & 0xFFFFFF;
if (color != extract_data.bottom_reference)
{
fprintf(stdout, "### WARNING horizontal border broken at (#%d,#%d)\r\n", x, bottom);
fflush(stdout);
break;
}
}
}
return;
}
static boolean extract_find_bitmap_bounds(
rectangle2d const *bounds,
rectangle2d *adjusted_bounds_reference)
{
boolean result = FALSE;
short y;
match_assert(
"c:\\halo\\SOURCE\\bitmaps\\bitmap_extract.c",
0x3F7,
bounds);
match_assert(
"c:\\halo\\SOURCE\\bitmaps\\bitmap_extract.c",
0x3F8,
adjusted_bounds_reference);
adjusted_bounds_reference->y0 = SHORT_MAX;
adjusted_bounds_reference->x0 = SHORT_MAX;
adjusted_bounds_reference->y1 = SHORT_MIN;
adjusted_bounds_reference->x1 = SHORT_MIN;
for (y = bounds->y0; y < bounds->y1; y++)
{
short x;
for (x = bounds->x0; x < bounds->x1; x++)
{
if (VALID_INDEX(x, extract_data.plate->width) &&
VALID_INDEX(y, extract_data.plate->height))
{
pixel32 color = *(pixel32 *)bitmap_2d_address(extract_data.plate, x, y, 0);
pixel32 rgb = color & 0xFFFFFF;
boolean contains_data = TRUE;
if (extract_data.extract_sequences)
{
if (rgb == extract_data.top_reference ||
rgb == extract_data.bottom_reference ||
rgb == extract_data.adjusted_bounds_reference)
{
contains_data = FALSE;
}
else if (extract_data.group->usage == _bitmap_group_usage_alpha_blend &&
!(color & 0xFF000000))
{
contains_data = FALSE;
}
}
if (contains_data)
{
adjusted_bounds_reference->x0 = MIN(x, adjusted_bounds_reference->x0);
adjusted_bounds_reference->y0 = MIN(y, adjusted_bounds_reference->y0);
adjusted_bounds_reference->x1 = MAX(x, adjusted_bounds_reference->x1);
adjusted_bounds_reference->y1 = MAX(y, adjusted_bounds_reference->y1);
result = TRUE;
}
}
}
}
adjusted_bounds_reference->x1++;
adjusted_bounds_reference->y1++;
return result;
}
static boolean extract_bitmap(
rectangle2d const *bounds)
{
boolean result = TRUE;
boolean warned_about_zero_alpha = FALSE;
boolean warned_about_dxt1_alpha = FALSE;
rectangle2d adjusted_bounds;
struct bitmap_data *bitmap;
short source_y;
short destination_y;
match_assert(
"c:\\halo\\SOURCE\\bitmaps\\bitmap_extract.c",
0x322,
bounds);
if (extract_find_bitmap_bounds(bounds, &adjusted_bounds))
{
bitmap = bitmap_2d_new(
adjusted_bounds.x1 - adjusted_bounds.x0,
adjusted_bounds.y1 - adjusted_bounds.y0,
0,
_bitmap_format_a8r8g8b8);
if (bitmap)
{
if (TEST_FLAG(
extract_data.group->flags,
_bitmap_group_extract_sprites_filthy_bug_fix_bit))
{
bitmap->registration_point_x =
bounds->x0 + bounds->x1 - 2 * adjusted_bounds.x0;
bitmap->registration_point_y =
bounds->y0 + bounds->y1 - 2 * adjusted_bounds.y0;
}
else
{
bitmap->registration_point_x =
(bounds->x0 + bounds->x1) / 2 - adjusted_bounds.x0;
bitmap->registration_point_y =
(bounds->y0 + bounds->y1) / 2 - adjusted_bounds.y0;
}
for (
source_y = adjusted_bounds.y0, destination_y = 0;
source_y < adjusted_bounds.y1;
source_y++, destination_y++)
{
pixel32 *destination = bitmap_2d_address(bitmap, 0, destination_y, 0);
short source_x;
for (source_x = adjusted_bounds.x0; source_x < adjusted_bounds.x1; source_x++)
{
pixel32 color = *(pixel32 *)bitmap_2d_address(
extract_data.plate,
source_x,
source_y,
0);
if (extract_data.extract_sequences)
{
pixel32 rgb = color & 0xFFFFFF;
if (rgb == extract_data.top_reference ||
rgb == extract_data.adjusted_bounds_reference ||
rgb == extract_data.bottom_reference)
{
color = 0;
}
}
if (extract_data.group->usage == _bitmap_group_usage_alpha_blend &&
!(color & 0xFF000000) &&
(color & 0xFFFFFF) &&
!warned_about_zero_alpha)
{
fprintf(
stdout,
"==> !!WARNING!! usage set to alpha; non-zero color overlaps with zero-alpha <==\r\n");
fflush(stdout);
warned_about_zero_alpha = TRUE;
}
if (extract_data.group->format ==
_bitmap_group_format_compressed_color_key_transparency)
{
unsigned long alpha = color >> 24;
if (alpha != 0 && alpha != 255 && !warned_about_dxt1_alpha)
{
fprintf(
stdout,
"==> !!WARNING!! bitmap with greater than 1-bit alpha being compressed as DXT1 <==\r\n");
fflush(stdout);
warned_about_dxt1_alpha = TRUE;
}
if (!alpha &&
((color & 0xFFFFFF) == extract_data.adjusted_bounds_reference ||
!extract_data.extract_sequences))
{
color = 0;
}
else
{
color |= 0xFF000000;
}
}
if ((extract_data.group->format ==
_bitmap_group_format_compressed_color_key_transparency ||
extract_data.group->format ==
_bitmap_group_format_compressed_explicit_alpha ||
extract_data.group->format ==
_bitmap_group_format_compressed_interpolated_alpha) &&
extract_data.group->type == _bitmap_group_type_interface_bitmaps)
{
error(
_error_immediate,
"### ERROR interface/linear bitmap cannot be DXT-compressed");
}
*destination++ = color;
}
}
if (extract_data.group->type == _bitmap_group_type_2d_textures ||
extract_data.group->type == _bitmap_group_type_interface_bitmaps)
{
short bitmap_index = extract_add_bitmap(bitmap);
if (bitmap_index != NONE)
{
if (extract_data.sequence->first_bitmap_index == NONE)
{
extract_data.sequence->first_bitmap_index = bitmap_index;
extract_data.sequence->bitmap_count = 0;
}
extract_data.sequence->bitmap_count++;
}
bitmap_delete(bitmap);
return result;
}
if (!extract_data.extract_sequences)
{
if (extract_data.group->type == _bitmap_group_type_cube_maps)
{
extract_plateless_cube_map(bitmap);
}
else
{
error(
_error_silent,
"### ERROR extract: tried to extract non-2d textures without a valid place but they weren't cube maps and/or EXTRACT_PLATELESS_CUBE_MAPS aren't allowed");
result = FALSE;
}
bitmap_delete(bitmap);
return result;
}
if (extract_data.bitmap_count < 0x400)
{
struct bitmap_extract_entry *entry =
&extract_data.bitmaps[extract_data.bitmap_count++];
entry->bitmap = bitmap;
entry->sequence_index = extract_data.sequence_index;
entry->sprite_index = NONE;
entry->page_index = NONE;
entry->page_entry_index = NONE;
if (extract_data.group->type == _bitmap_group_type_sprites)
{
short sprite_index =
(short)tag_block_add_element(&extract_data.sequence->sprites);
struct bitmap_group_sprite *sprite;
if (sprite_index == NONE)
{
error(_error_silent, "### ERROR extract: failed to add sprite to sequence");
return FALSE;
}
sprite = TAG_BLOCK_GET_ELEMENT(
&extract_data.sequence->sprites,
sprite_index,
struct bitmap_group_sprite);
sprite->bitmap_index = NONE;
if (TEST_FLAG(
extract_data.group->flags,
_bitmap_group_extract_sprites_filthy_bug_fix_bit))
{
sprite->registration_point.x =
(real)bitmap->registration_point_x * 0.5f;
sprite->registration_point.y =
(real)bitmap->registration_point_y * 0.5f;
}
else
{
sprite->registration_point.x = (real)bitmap->registration_point_x;
sprite->registration_point.y = (real)bitmap->registration_point_y;
}
entry->sprite_index = sprite_index;
}
return result;
}
error(
_error_silent,
"### ERROR extract: can't handle more than (#%d) temporary bitmaps",
0x400);
return FALSE;
}
error(_error_silent, "### ERROR extract: failed to allocate temporary bitmap");
result = FALSE;
}
else
{
fprintf(stdout, "### WARNING skipped a bitmap which contained no data\r\n");
fflush(stdout);
}
return result;
}
static boolean extract_without_sequences(
void)
{
rectangle2d bounds;
struct bitmap_group *group = extract_data.group;
boolean result = TRUE;
if (group->format == _bitmap_group_format_compressed_color_key_transparency &&
extract_data.extract_sequences)
{
error(
_error_silent,
"### ERROR extract: compressed color-key transparency format must use a valid plate");
result = FALSE;
}
else
{
switch (group->type)
{
case _bitmap_group_type_2d_textures:
case _bitmap_group_type_cube_maps:
case _bitmap_group_type_interface_bitmaps:
{
short plate_width;
short plate_height;
short sequence_index;
bounds.y0 = 0;
bounds.x0 = 0;
plate_width = extract_data.plate->width;
plate_height = extract_data.plate->height;
bounds.x1 = plate_width;
bounds.y1 = plate_height;
sequence_index = (short)tag_block_add_element(&group->sequences);
extract_data.sequence_index = sequence_index;
extract_data.sequence = tag_block_get_element_with_size(
&extract_data.group->sequences,
sequence_index,
sizeof(struct bitmap_group_sequence));
extract_data.sequence->first_bitmap_index = NONE;
extract_bitmap(&bounds);
break;
}
case _bitmap_group_type_3d_textures:
error(_error_silent, "### ERROR can't extract 3D textures without a valid plate");
result = FALSE;
break;
case _bitmap_group_type_sprites:
error(_error_silent, "### ERROR can't extract sprites without a valid plate");
result = FALSE;
break;
default:
match_vassert(
"c:\\halo\\SOURCE\\bitmaps\\bitmap_extract.c",
0x1A6,
FALSE,
"### ERROR unsupported bitmap group type");
break;
}
}
return result;
}
static boolean extract_sequences(
void)
{
boolean result = TRUE;
short top = 1;
while (result && top < extract_data.plate->height)
{
short bottom;
short sequence_index;
bottom = extract_find_sequence_bounds(&top);
extract_warn_about_horizontal_border(bottom);
sequence_index = (short)tag_block_add_element(&extract_data.group->sequences);
if (sequence_index == NONE)
{
error(_error_silent, "### ERROR extract: failed to allocate sequence");
return FALSE;
}
extract_data.sequence_index = sequence_index;
extract_data.sequence = tag_block_get_element_with_size(
&extract_data.group->sequences,
sequence_index,
sizeof(struct bitmap_group_sequence));
extract_data.sequence->first_bitmap_index = NONE;
extract_data.sequence->bitmap_count = 0;
result = extract_sequence(top, bottom);
top = bottom + 1;
}
return result;
}