-
Notifications
You must be signed in to change notification settings - Fork 0
Home
Jon Daniel edited this page Jul 20, 2025
·
13 revisions
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;
}