/* (c) J Pitts 1997 26/3/97 Hacked together demo program to read tmd files. There is not error checking for stupid users. This is just to demonstrate the structure of tmd files. ** Please Do Not distribute outside of the Yaroze Community ** Jim sigill@geocities.com http://www.playstation.co.uk/~Sig1LL */ #include #include #include #include #pragma pack (1) typedef struct{ unsigned long Id; unsigned long Flags; unsigned long NumObjs; }header_t; typedef struct{ unsigned long VertOff; unsigned long NumVert; unsigned long NormOff; unsigned long NumNorm; unsigned long PrimOff; unsigned long NumPrim; long scale; } object_header_t; typedef struct{ unsigned char olen, ilen, flag, mode; } prim_head_t; typedef struct{ short x,y,z; short filler; } vert_t; typedef vert_t norm_t; typedef struct { unsigned char r, g, b, mode; } rgb_t; typedef union { struct { rgb_t rgb; unsigned short norm, vert[3]; }pd_20; struct { rgb_t rgb; unsigned short norm, vert[4], filler; }pd_28; struct { rgb_t rgb; unsigned short norm0, vert0; unsigned short norm1, vert1; unsigned short norm2, vert2; }pd_30; struct { rgb_t rgb; unsigned short norm0, vert0; unsigned short norm1, vert1; unsigned short norm2, vert2; unsigned short norm3, vert3; }pd_38; } primdata_u; void PrimDump20 (primdata_u *); void PrimDump28 (primdata_u *); void PrimDump30 (primdata_u *); void PrimDump38 (primdata_u *); typedef struct{ unsigned char Index; char On[80]; } desc_t; desc_t PrimMode[] = { { 0x01, "unlit"}, { 0x02, "Transparent"}, { 0x04, "Textured"}, { 0x08, "Quadrangle"}, { 0x10, "Gouraud"}, { 0x40, "Line"}, { 0xFF, "" } }; desc_t PrimFlag[] = { { 0x01, "unlit" }, { 0x02, "double sided"}, { 0x04, "Graduated"}, { 0xFF, "" } }; struct { unsigned char mode; unsigned char flag; void (*Dump)(primdata_u *); } PrimData[] ={ { 0x20, 0, PrimDump20 }, { 0x21, 0, NULL }, { 0x24, 0, NULL }, { 0x25, 0, NULL }, { 0x28, 0, PrimDump28 }, { 0x29, 0, NULL }, { 0x2c, 0, NULL }, { 0x2d, 0, NULL }, { 0x30, 0, PrimDump30 }, { 0x31, 0, NULL }, { 0x34, 0, NULL }, { 0x35, 0, NULL }, { 0x38, 0, PrimDump38 }, { 0x39, 0, NULL }, { 0x3c, 0, NULL }, { 0x3d, 0, NULL }, { 0x40, 0, NULL }, { 0x50, 0, NULL }, { 0xFF, 0xFF, NULL} }; #pragma pack (8) static FILE *fp; void ReadHeader(header_t *Header){ fread (Header, 1, sizeof(header_t), fp); if (Header->Id != 0x41){ printf("Not a TMD file\n"); exit(1); } } void ReadObjectHeader(object_header_t *ObjHead){ fread (ObjHead, 1 ,sizeof (object_header_t), fp); } void ReadPrimatives (prim_head_t *P){ fread (P, 1 ,sizeof (prim_head_t), fp); } void ReadNormals (norm_t *N){ fread (N, 1 ,sizeof (norm_t), fp); } void ReadVertices (vert_t *V){ fread (V, 1 ,sizeof (vert_t), fp); } void DumpRGB(rgb_t *rgb){ printf("rgb (%d %d %d) ", rgb->r, rgb->g, rgb->b); } void PrimDump20 (primdata_u *pd){ DumpRGB(&pd->pd_20.rgb); printf("Normal %d ", pd->pd_20.norm); printf("Points (%d %d %d)\n", *pd->pd_20.vert, pd->pd_20.vert[1], pd->pd_20.vert[2]); } void PrimDump28 (primdata_u *pd){ DumpRGB(&pd->pd_28.rgb); printf("Normal %d ", pd->pd_28.norm); printf("Points (%d %d %d %d)\n", *pd->pd_28.vert, pd->pd_28.vert[1], pd->pd_28.vert[2], pd->pd_28.vert[3]); } void PrimDump30 (primdata_u *pd){ DumpRGB(&pd->pd_30.rgb); printf("\nNormal %d Vert %d", pd->pd_30.norm0, pd->pd_30.vert0); printf("\nNormal %d Vert %d", pd->pd_30.norm1, pd->pd_30.vert1); printf("\nNormal %d Vert %d\n", pd->pd_30.norm2, pd->pd_30.vert2); } void PrimDump38 (primdata_u *pd){ DumpRGB(&pd->pd_38.rgb); printf("\nNormal %d Vert %d", pd->pd_38.norm0, pd->pd_38.vert0); printf("\nNormal %d Vert %d", pd->pd_30.norm1, pd->pd_38.vert1); printf("\nNormal %d Vert %d\n", pd->pd_38.norm2, pd->pd_38.vert2); printf("\nNormal %d Vert %d\n", pd->pd_38.norm3, pd->pd_38.vert3); } void DumpObjectHeader(object_header_t *ObjHead){ printf("Vertices %5d Offset 0x%X\n",ObjHead->NumVert, ObjHead->VertOff); printf("Normals %5d Offset 0x%X\n",ObjHead->NumNorm, ObjHead->NormOff); printf("Primatives %5d Offset 0x%X\n",ObjHead->NumPrim, ObjHead->PrimOff); } void DumpHeader(header_t *Header){ printf("Id\t0x%X\n", Header->Id); printf("Flags\t0x%x\n", Header->Flags); printf("Number Objects\t%d\n", Header->NumObjs); } long ModeSearch (desc_t *tab, unsigned char index){ long i=0; while (tab[i].Index != 0xFF){ if (tab[i].Index == index){ return i; } ++i; } return i; } void DumpBitwise (desc_t *d, unsigned char b){ unsigned char M = b; unsigned char mask = 1; long index; while (M != 0){ index = ModeSearch (d, M & mask); if (index != 0xFF) printf ("%s ", d[index].On); M = M & ~mask; mask <<= 1; assert (mask < 0x80); } } void DumpPrimatives(prim_head_t *P){ printf("olen (%d) ", P->olen); printf("ilen (%d) ", P->ilen); #ifdef DEBUG printf("flag (0x%x) ", P->flag); printf("mode (0x%x) ", P->mode); #endif DumpBitwise (PrimFlag, P->flag&0x7); DumpBitwise (PrimMode, P->mode&0x3F); } void DumpNormals (norm_t *N){ printf("(%d %d %d)\n", N->x, N->y, N->z); } void DumpVertices (vert_t *N){ printf("(%d %d %d)\n", N->x, N->y, N->z); } long SearchTable (unsigned char mode, unsigned char flag){ long loc=0; while (PrimData[loc].mode < mode){ loc++; } if (PrimData[loc].mode != mode) { return -1; } while (PrimData[loc].mode == mode){ if (PrimData[loc].flag == flag){ return loc; } ++loc; } return -1; } long ReadPrimData (prim_head_t *P){ long Entry; primdata_u Data; //fseek (fp, P->ilen*4, SEEK_CUR); if ((Entry = SearchTable (P->mode, P->flag)) == -1){ printf("Primative does not exist!\n"); fseek (fp, P->ilen*4, SEEK_CUR); return 0; } fread (&Data, 1, P->ilen*4, fp); if (PrimData[Entry].Dump != NULL) PrimData[Entry].Dump (&Data); putchar ('\n'); return 0; } void main (int argc, char *argv[]){ header_t Header; object_header_t ObjHead; prim_head_t PHead; norm_t Norm; vert_t Vert; unsigned i; fp = fopen (argv[1], "rb"); if (fp == NULL) exit(0); ReadHeader (&Header); DumpHeader (&Header); ReadObjectHeader (&ObjHead); DumpObjectHeader (&ObjHead); printf("\n\n *** Vertices ***\n"); fseek (fp, ObjHead.VertOff + sizeof (header_t), SEEK_SET); for (i = 0; i < ObjHead.NumVert; ++i){ ReadVertices(&Vert); DumpVertices(&Vert); } printf("\n\n *** Normal Vectors ***\n"); fseek (fp, ObjHead.NormOff + sizeof (header_t), SEEK_SET); for (i = 0; i < ObjHead.NumNorm; ++i){ ReadNormals(&Norm); DumpNormals(&Norm); } printf("\n\n *** Primatives ***\n"); fseek (fp, ObjHead.PrimOff + sizeof (header_t), SEEK_SET); for (i = 0; i < ObjHead.NumPrim; ++i){ ReadPrimatives (&PHead); DumpPrimatives (&PHead); if (ReadPrimData (&PHead) == -1) break; } fclose(fp); }