Skip to content
Jon Daniel edited this page Jul 20, 2025 · 13 revisions

3O CAR Home

typedef   int8_t  i8;
typedef  uint8_t  u8;
typedef  int16_t i16;
typedef uint16_t u16;
typedef  int32_t i32;
typedef uint32_t u32;
typedef float    f32;

typedef i16 __attribute__((vector_size(sizeof(i16  ) * 4))) i16x4;
typedef u16 __attribute__((vector_size(sizeof(u16  ) * 4))) u16x4;
typedef i16 __attribute__((vector_size(sizeof(i16  ) * 2))) i16x2;
typedef u16 __attribute__((vector_size(sizeof(u16  ) * 2))) u16x2;

typedef i16x4 i16ax3;
typedef i16 i16x3[3];

enum format
{
        CHASM_FORMAT_NONE = 0 << 0,
        CHASM_FORMAT_3O   = 1 << 0,
        CHASM_FORMAT_CAR  = CHASM_FORMAT_3O + 1 << 1,
};

enum format csm_model_format(const u8* buf, size_t len) 
{                       
        size_t       hdr_len = sizeof(c3o_header); 
        const size_t car_len = sizeof(car_header) - hdr_len;
        size_t            tw = 64;      
        c3o_header*      c3o = (c3o_header*)buf;
        car_header*      car = (car_header*)buf;
                        
        if(buf != NULL && len > 0)
        {       
                if(hdr_len + c3o->th * tw == len)
                        return CHASM_FORMAT_3O;
        
                hdr_len += car_len;
                tw       = csm_model_car_frame_count(car);
                tw      += csm_model_car_sfx_len(car);

                if(hdr_len + car->th + tw == len)
                        return CHASM_FORMAT_CAR;
        }
        return CHASM_FORMAT_NONE;
}

typedef struct anim_info
{
        size_t start;
        size_t count;
} anim_info;

typedef struct model
{
        /* raw file data */
        u8*              data;
        /* pointer to header */
        c3o_header*       c3o;
        car_header*       car;
        /* pointer to post header suffix tail */
        u8*             tdata;
        i16x3*    anim_frames;
        /* content description */
        size_t    frame_count;
        enum format       fmt;
        size_t            len;
        char         name[32];
        GLsizei            th;
        GLsizei            tw;
        GLsizei          tdim;
        palette*          pal;
        u8x4*           trgba;
        anim_info   anims[20];
        size_t     anim_count;
        size_t   anim_current;
        size_t anim_frame_idx;
} model;

size_t acc(u16* src, size_t cnt, size_t init)
{
        for(size_t i = 0; i < cnt; i++)
                init += src[i];
        return init;    
}                       

u8x4* tpal2rgba(u8* buf, size_t len, palette* pal)
{               
        if(buf == NULL || pal == NULL || len <= 0) return NULL;

        u8x4* dst = (u8x4*)calloc(sizeof(u8x4), len);
        for(size_t i = 0; i < len; i++)
        {       
                const size_t
                idx      =     buf[i];
                dst[i].r =  (*pal)[idx].r;
                dst[i].g =  (*pal)[idx].g;
                dst[i].b =  (*pal)[idx].b;
                dst[i].a = ((*pal)[idx].r == 4 && (*pal)[idx].g == 4 && (*pal)[idx].b == 4) ? 0 : 255;
        }
        return dst;
}

size_t csm_model_car_frame_count(car_header* hdr)
{
        size_t dst = acc(hdr->anims.model, 20, 0);

        for(size_t i = 0; i < 6; i++)
        {
                const size_t sum = acc(hdr->anims.sub_model[i], 2, 0);
                dst += sum == 0 ? 0 : dst + sizeof(c3o_header);
        }
        return dst;
}

size_t csm_model_car_sfx_len(car_header* hdr)
{
        return acc(hdr->sfx.len, 8, 0);
}

size_t csm_model_car_anim_count(model* hdr)
{
        hdr->frame_count = csm_model_car_frame_count(hdr->car);
        size_t off = 0;
        for(size_t i = 0; i < 20; i++)
        {
                uint16_t b = hdr->car->anims.model[i];
                if(b)
                {
                        size_t n = b / (hdr->car->vcount * sizeof(i16x3));
                        hdr->anims[hdr->anim_count].start = off;
                        hdr->anims[hdr->anim_count].count = n;
                        off += n; hdr->anim_count++;
                }
        }
        if(hdr->anim_count == 0)
        {
                hdr->anims[0].start = 0;
                hdr->anims[0].count = hdr->frame_count;
                hdr->anim_count = 1;
        }
        hdr->anim_current   = 0;
        hdr->anim_frame_idx = 0;
        printf("[NFO][MDL] anim_count: %zu frame_count: %zu\n", hdr->anim_count, hdr->frame_count);
        return hdr->anim_count;
}
Clone this wiki locally