CAR Format (Chasm: The Rift)

From ModdingWiki
(Redirected from CAR Format)
Jump to navigation Jump to search
CAR Format (Chasm: The Rift)
Format type3D Model
Model typePolygon
Maximum number of polygons400
Maximum number of vertices938
Games

The CAR Format is used by Chasm: The Rift to store most of the game's monsters and the player.

The data in the CAR is a 0x66 bytes header followed by 3O Format file content

Offset Type Description
0x0000 UINT16LE[20] Animations array
0x0028 UINT16LE[3][2] Submodel animations array
0x0034 UINT16LE[6] ! Unknown
0x0040 UINT16LE[3] Fall Sound id array defaults to 73
0x0046 UINT16LE[8] Sound length array
0x0056 UINT16LE[8] Sound volume array

! Figure out 12 byte 0x0034 (0 padding, gib type or another submodel animation)

! GSND Sound id Monster/id Fall sounds relations

Chasm Modding Toolkit Package is a comprehensive Windows package for customizing and modding game assets for both DOS and REMAKE version of Chasm the Rift. It supports CAR, OBJ, CEL and SPR formats for models, sprites, textures, animations and many more. You can extract, replace and preview textures, edit palettes, import/export audio, generate skyboxes and cube maps, and view assets with dedicated GUI or CLI tools.

AwesomeChasm#models Example C++ code including sound offset calculation

/* QUAD/TRIANGLE polygon face */
struct face
{
        vec::u16 <               4>              indices;
        arr::type<vec::u16<2>,   4>                   uv;
        sca::i16                                    next;
        sca::i16                                 distant;
        sca::u8                                      num;
        sca::u8                                    flags;
        sca::u16                              sprite_off;
};

/* .CAR format header */ 
struct car_header
{
        arr::type<sca::u16   ,  20>                anims;
        arr::type<vec::u16<2>,   3>            sub_anims;
        arr::type<sca::u16   ,   6>             unknown0;

        /* SepPartInfo[monster_index + i].FallSound gsnd id defaults to 73 for gibs */
        arr::type<sca::u16   ,   3>                 gsnd;
        arr::type<sca::u16   ,   8>              sfx_len;
        arr::type<sca::u16   ,   8>              sfx_vol;
};

/* .3O Chasm: The Rift 3D model file format */
struct c3o
{
        arr::type<face       , 400>                faces; // 0x0000
        arr::type<vec::i16<3>, 256>                overt; // 0x3200
        arr::type<vec::i16<3>, 256>                rvert;
        arr::type<vec::i16<3>, 256>               shvert;
        arr::type<vec::i16<2>, 256>               scvert;

        sca::u16                            vertex_count; // 0x4800
        sca::u16                              face_count; // 0x4802
        sca::u16                                      th; // 0x4804
};

/* .CAR Chasm: The Rift Carrara Caracter 3D model file format */ 
struct car : car_header, c3o
{
        size_t sounds_offset()
        {
                size_t dst = th + sizeof(struct car_header) + 0x4806u;
                for(size_t i = 0; i < 20; i++) dst += anims[i];
                for(size_t i = 0; i < 3u; i++)
                {
                        const size_t sum = sub_anims[i].sum();
                        dst += sum == 0 ? 0 : sum + 0x4806u;
                }
                return dst;
        }
        bool verify_length(size_t len)
        {
            size_t acc = sounds_offset();
            for(size_t i = 0; i < sfx_len.size(); i++)
                acc += sfx_len[i];
            return acc == len;
        }
        bool set_sound(const size_t monster_number)
        {
            const size_t monster_index = monster_number - 100;
            if(monster_index >= 23)
                return false;

            for (size_t i = 0; i < gsnd.size(); ++i)
                SepPartInfo[monster_index + i].FallSound = gsnd[i];
            return true;
        }
};