569 lines
10 KiB
C
569 lines
10 KiB
C
// 3DS converter V2.0
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
#include <conio.h>
|
|
#include <ctype.h>
|
|
#include <stdlib.h>
|
|
#include <malloc.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
|
|
#include "..\cd.h"
|
|
#include "..\c.h"
|
|
|
|
void vDraw(void);
|
|
void vDeinit(void);
|
|
void vClear(void);
|
|
void vNext(void);
|
|
void vInit(void);
|
|
void vPalette(void);
|
|
int drawpass=0;
|
|
|
|
void doscene(int scene);
|
|
|
|
int addvx(long x,long y,long z);
|
|
int addnr(long x,long y,long z);
|
|
|
|
char far *vram=(char far *)0xa0000000L;
|
|
|
|
char fill_color[64000];
|
|
char fill_object[64000];
|
|
char fill_curobj;
|
|
|
|
//----------------------------------------------------------------
|
|
|
|
// filenames
|
|
char *inname="NoName";
|
|
char ascname[64];
|
|
char vuename[64];
|
|
char tmpname[64];
|
|
char scenename[64];
|
|
|
|
// flags
|
|
int cityflag=0;
|
|
int debug=0;
|
|
int printon=0;
|
|
int reporton=1;
|
|
int playloop=0;
|
|
int materials=0;
|
|
int vuedone=0;
|
|
|
|
// variables
|
|
float fxadd,fxmul;
|
|
float fyadd,fymul;
|
|
float fzadd,fzmul;
|
|
float scale=100.0F;
|
|
|
|
#define BIGLONG 2000000000L
|
|
#define MAXMAT 32
|
|
#define MAXFACE 16 // in a polygon
|
|
#define MAXOBJ 256
|
|
#define MAXVX 500
|
|
#define MAXNR 500
|
|
#define MAXFC 500
|
|
#define NORMALSIZE UNIT // length of normals
|
|
|
|
//----------------------------------------------------------------
|
|
|
|
// globals
|
|
rmatrix camera;
|
|
FILE *in,*in2;
|
|
FILE *outb,*outb2,*outb3;
|
|
FILE *freport=NULL;
|
|
FILE *fdeb;
|
|
int debcount=0;
|
|
char palette[768];
|
|
|
|
// prototypes
|
|
void readvue(void);
|
|
void readasc(void);
|
|
|
|
// world structs
|
|
struct s_cobject
|
|
{
|
|
char name[18];
|
|
int index;
|
|
int duplicate;
|
|
int original;
|
|
int lastused;
|
|
int f1,f2,n1,n2,v1,v2,ng;
|
|
long size;
|
|
char fname[16];
|
|
object *o;
|
|
long dist;
|
|
int on;
|
|
int last_on;
|
|
long last_x,last_y,last_z;
|
|
long last_m[9];
|
|
} co[MAXOBJ];
|
|
int conum=0;
|
|
|
|
struct s_material
|
|
{
|
|
char name[32];
|
|
int flags;
|
|
int color;
|
|
int colorlen;
|
|
} mat[MAXMAT];
|
|
int matnum=0;
|
|
char matpal[768];
|
|
int matpalenabled=0;
|
|
|
|
int usefov;
|
|
|
|
object camobject;
|
|
|
|
// other c code included
|
|
#include "save.c"
|
|
#include "util.c"
|
|
#include "osort.c"
|
|
#include "readasc.c"
|
|
#include "readvue.c"
|
|
#include "readmat.c"
|
|
#include "readinf.c"
|
|
|
|
// main
|
|
|
|
main(int argc,char *argv[])
|
|
{
|
|
char tmpfname[64];
|
|
int pause=0;
|
|
int a;
|
|
int totalfaces=0,totalvertices=0,totalnormals=0;
|
|
|
|
fdeb=fopen("debug.tmp","wt");
|
|
|
|
if(argc==1)
|
|
{
|
|
printf("\n"
|
|
"usage: C [options] <scenename(no extensions)>\n"
|
|
"-c Set Cityflag\n"
|
|
"-w Set Runflag\n"
|
|
"-r Generate report (to file REPORT)\n"
|
|
"-p Print report to screen as well\n"
|
|
"-l Loop the animation phase until key pressed\n"
|
|
"-s### Specify scale factor (default 100.0)\n"
|
|
);
|
|
return(0);
|
|
}
|
|
|
|
reporton=0;
|
|
for(a=1;a<argc;a++) if(argv[a][0]=='-') switch(argv[a][1])
|
|
{
|
|
case 'c' :
|
|
case 'C' : cityflag=1; break;
|
|
case 'w' :
|
|
case 'W' : cityflag=2; break;
|
|
case 'r' :
|
|
case 'R' : reporton=1; break;
|
|
case 'p' :
|
|
case 'P' : reporton=printon=1; break;
|
|
case 's' :
|
|
case 'S' : sscanf(argv[a]+2,"%f",&scale); break;
|
|
case 'l' :
|
|
case 'L' : playloop=1; break;
|
|
}
|
|
else strcpy(inname,argv[a]);
|
|
|
|
// defaults
|
|
strupr(inname);
|
|
strcpy(ascname,inname);
|
|
strcat(ascname,".ASC");
|
|
strcpy(vuename,inname);
|
|
strcat(vuename,".VUE");
|
|
strcpy(scenename,inname);
|
|
|
|
fxmul=scale; fxadd=0.0F;
|
|
fymul=scale; fyadd=0.0F;
|
|
fzmul=scale; fzadd=0.0F;
|
|
|
|
in=fopen(ascname,"rt");
|
|
if(!in)
|
|
{
|
|
printf("%s not found!\n",ascname);
|
|
exit(3);
|
|
}
|
|
fclose(in);
|
|
|
|
if(reporton) freport=fopen("report","wt");
|
|
|
|
// blue screen
|
|
printf( "\n");
|
|
printf( "Analyzing and converting (while screen is blue)\n");
|
|
printf( " Scene name: %s\n",inname);
|
|
printf( "Scale factor: %f\n",scale);
|
|
if(pause)
|
|
{
|
|
printf("Press any key to start.\n");
|
|
getch();
|
|
}
|
|
else printf("\n");
|
|
outp(0x3c8,0); outp(0x3c9,0); outp(0x3c9,0); outp(0x3c9,32);
|
|
|
|
strcpy(co[0].name,"CAMERA");
|
|
co[0].on=1; // camera is always on
|
|
co[0].index=-1;
|
|
co[0].duplicate=1; // let's lie
|
|
co[0].original=0;
|
|
co[0].lastused=0;
|
|
co[0].o=&camobject;
|
|
camobject.r=&camera;
|
|
camobject.r0=&camera;
|
|
conum=1;
|
|
|
|
strcpy(tmpname,inname);
|
|
strcat(tmpname,".INF");
|
|
in=fopen(tmpname,"rt");
|
|
if(in) fclose(in);
|
|
else
|
|
{
|
|
printf("%s.INF file not found!\n",inname);
|
|
exit(3);
|
|
}
|
|
|
|
strcpy(tmpname,inname);
|
|
strcat(tmpname,".MAT");
|
|
in=fopen(tmpname,"rt");
|
|
if(in)
|
|
{
|
|
readmat();
|
|
fclose(in);
|
|
}
|
|
|
|
strcpy(tmpname,inname);
|
|
strcat(tmpname,".PAL");
|
|
in=fopen(tmpname,"rb");
|
|
if(in)
|
|
{
|
|
matpalenabled=1;
|
|
fread(matpal,768,1,in);
|
|
fclose(in);
|
|
}
|
|
else
|
|
{
|
|
for(a=0;a<32;a++)
|
|
{
|
|
matpal[a*3+0]=a*2;
|
|
matpal[a*3+1]=a*2;
|
|
matpal[a*3+2]=a*2;
|
|
}
|
|
}
|
|
|
|
sprintf(tmpfname,"%s.00M",scenename);
|
|
outb3=fopen(tmpfname,"wb");
|
|
putw(0,outb3);
|
|
putw(0,outb3);
|
|
putw(0,outb3);
|
|
putw(0,outb3);
|
|
putw(0,outb3);
|
|
putw(0,outb3);
|
|
putw(0,outb3);
|
|
putw(0,outb3);
|
|
fwrite(matpal,768,1,outb3);
|
|
|
|
in=fopen(ascname,"rt");
|
|
if(!in)
|
|
{
|
|
printf("%s not found!\n",ascname);
|
|
exit(3);
|
|
}
|
|
readasc();
|
|
fclose(in);
|
|
|
|
vInit();
|
|
|
|
printon=0;
|
|
|
|
for(a=1;a<conum;a++)
|
|
{
|
|
objectsort(co[a].o);
|
|
}
|
|
|
|
_asm mov ax,13h
|
|
_asm int 10h
|
|
vPalette();
|
|
|
|
sprintf(tmpfname,"%s.0AA",scenename);
|
|
outb2=fopen(tmpfname,"wb");
|
|
strcpy(tmpname,inname);
|
|
strcat(tmpname,".INF");
|
|
in=fopen(tmpname,"rt");
|
|
readinf();
|
|
fclose(in);
|
|
putw(0xffff,outb2);
|
|
putw(0xffff,outb2);
|
|
fclose(outb2);
|
|
|
|
{ // init stuff for script
|
|
int coi;
|
|
long l,l2;
|
|
struct s_cobject *cop;
|
|
l=ftell(outb3);
|
|
putw(conum,outb3);
|
|
for(coi=1;coi<conum;coi++)
|
|
{
|
|
cop=co+coi;
|
|
putw(cop->index,outb3);
|
|
}
|
|
fseek(outb3,0L,SEEK_SET);
|
|
putc('F',outb3);
|
|
putc('C',outb3);
|
|
putc(0xfc,outb3);
|
|
putc(0x1a,outb3);
|
|
putl(l,outb3);
|
|
putw(0,outb3);
|
|
putw(0,outb3);
|
|
putw(0,outb3);
|
|
putc(0,outb3);
|
|
if(cityflag==1) putc('C',outb3);
|
|
else if(cityflag==2) putc('R',outb3);
|
|
else putc(0,outb3);
|
|
}
|
|
|
|
if(!kbhit()) vuedone=1;
|
|
if(kbhit()) getch();
|
|
vDeinit();
|
|
|
|
{
|
|
if(vuedone) printf("Saving scenery: (%s.00O,%s.00M,%s.0$$)\n\n",scenename,scenename,scenename);
|
|
else printf("Saving objects: (%s.00M)\n\n",scenename);
|
|
for(a=1;a<conum;a++)
|
|
{
|
|
if(!co[a].duplicate)
|
|
{
|
|
printf("Object: %s",co[a].name);
|
|
saveobject(co+a); // save object to disk
|
|
printf(" File: %s Size:%li\n",co[a].fname,co[a].size);
|
|
printf(" Faces:%i=>%i Vertices:%i=>%i Normals:%i Gouraudnormals:%i\n",
|
|
co[a].f1,co[a].f2,
|
|
co[a].v1,co[a].v2,
|
|
co[a].n2,co[a].ng-co[a].n2);
|
|
}
|
|
totalfaces+=co[co[a].index].f1;
|
|
totalvertices+=co[co[a].index].v1;
|
|
totalnormals+=co[co[a].index].n2;
|
|
}
|
|
}
|
|
print("Conversion finished (or escaped)!\n");
|
|
printf("Total sum of stuff in animation:\n"
|
|
" faces: %i\n"
|
|
"vertices: %i\n"
|
|
" normals: %i\n",
|
|
totalfaces,
|
|
totalvertices,
|
|
totalnormals);
|
|
if(freport) fclose(freport);
|
|
fclose(fdeb);
|
|
return(0);
|
|
}
|
|
|
|
void doscene(int scene)
|
|
{
|
|
int a;
|
|
char tmpfname[64];
|
|
sprintf(tmpfname,"%s-%i.vue",inname,scene);
|
|
in=fopen(tmpfname,"rt");
|
|
if(!in)
|
|
{
|
|
print("Scene %s not found.\n",tmpfname);
|
|
return;
|
|
}
|
|
vuedone=1;
|
|
putw(scene,outb2);
|
|
putw(0,outb2);
|
|
sprintf(tmpfname,"%s.0%c%c",inname,scene/10+'A',scene%10+'A');
|
|
outb=fopen(tmpfname,"wb");
|
|
readvue();
|
|
fclose(in);
|
|
fclose(outb);
|
|
}
|
|
|
|
void vPalette(void)
|
|
{
|
|
int a,b;
|
|
if(matpalenabled)
|
|
{
|
|
vid_setpal(matpal);
|
|
return;
|
|
}
|
|
for(a=0;a<256;a++)
|
|
{
|
|
palette[a*3+0]=(char)((a&15)*3+((a/16)&3)*0);
|
|
palette[a*3+1]=(char)((a&15)*3+((a/16)&3)*2);
|
|
palette[a*3+2]=(char)((a&15)*3+((a/16)&3)*4);
|
|
}
|
|
for(a=0;a<32;a++)
|
|
{
|
|
palette[16*3+a*3+0]=(char)(63-a*2);
|
|
palette[16*3+a*3+1]=(char)(63-a*2);
|
|
palette[16*3+a*3+2]=(char)(63-a*2);
|
|
}
|
|
palette[2]=32;
|
|
palette[255*3+0]=63;
|
|
palette[255*3+1]=32;
|
|
palette[255*3+2]=16;
|
|
vid_setpal(palette);
|
|
}
|
|
|
|
void vInit(void)
|
|
{
|
|
vid_init(1);
|
|
vPalette();
|
|
}
|
|
|
|
void vDeinit(void)
|
|
{
|
|
vid_deinit();
|
|
}
|
|
|
|
void vNext(void)
|
|
{
|
|
vid_switch();
|
|
vid_waitb();
|
|
vid_clear();
|
|
}
|
|
|
|
void vClear(void)
|
|
{
|
|
vid_clear();
|
|
}
|
|
|
|
#pragma check_stack(off)
|
|
void _loadds cfill(int *fd)
|
|
{
|
|
int color,y,a,x,cnt;
|
|
long lx,la,rx,ra;
|
|
char *p,*pp;
|
|
a=*fd++;
|
|
if(a!=0) return; // not flat shading!
|
|
color=*fd++;
|
|
y=*fd++;
|
|
for(;;)
|
|
{
|
|
a=*fd++;
|
|
if(a<0) break;
|
|
if(a)
|
|
{
|
|
lx=(unsigned)(*fd++);
|
|
lx|=(long)(*fd++)<<16;
|
|
la=(unsigned)(*fd++);
|
|
la|=(long)(*fd++)<<16;
|
|
}
|
|
a=*fd++;
|
|
if(a<0) break;
|
|
if(a)
|
|
{
|
|
rx=(unsigned)(*fd++);
|
|
rx|=(long)(*fd++)<<16;
|
|
ra=(unsigned)(*fd++);
|
|
ra|=(long)(*fd++)<<16;
|
|
}
|
|
a=*fd++;
|
|
while(a--)
|
|
{
|
|
lx+=la;
|
|
rx+=ra;
|
|
if(lx<rx)
|
|
{
|
|
x=lx>>16;
|
|
cnt=(rx>>16)-x;
|
|
}
|
|
else
|
|
{
|
|
x=rx>>16;
|
|
cnt=(lx>>16)-x;
|
|
}
|
|
p=fill_color+x+y*320;
|
|
pp=fill_object+x+y*320;
|
|
#if 0
|
|
p[0]=color;
|
|
p[cnt-1]=color;
|
|
#else
|
|
while(cnt--)
|
|
{
|
|
*p++=color;
|
|
*pp++=fill_curobj;
|
|
}
|
|
#endif
|
|
y++;
|
|
}
|
|
}
|
|
}
|
|
#pragma check_stack(on)
|
|
|
|
int order[MAXOBJ],ordernum;
|
|
void vDraw(void)
|
|
{
|
|
rmatrix cam;
|
|
rmatrix tmp;
|
|
object *o;
|
|
long dis;
|
|
int a,b,c;
|
|
if(!drawpass)
|
|
{
|
|
vid_waitb();
|
|
memcpy(vram,fill_color,64000);
|
|
memset(fill_color,0,64000);
|
|
memset(fill_object,0,64000);
|
|
draw_setfillroutine(cfill);
|
|
}
|
|
else
|
|
{
|
|
vNext();
|
|
draw_setfillroutine(NULL);
|
|
}
|
|
memcpy(&cam,&camera,sizeof(rmatrix));
|
|
{
|
|
ordernum=0;
|
|
for(a=1;a<conum;a++)
|
|
{
|
|
order[ordernum++]=a;
|
|
o=co[a].o;
|
|
memcpy(o->r,o->r0,sizeof(rmatrix));
|
|
calc_applyrmatrix(o->r,&cam);
|
|
b=o->pl[0][1]; // center vertex
|
|
if(co[a].name[1]=='_') co[a].dist=100000000L;
|
|
else co[a].dist=calc_singlez(b,o->v0,o->r);
|
|
}
|
|
|
|
for(a=0;a<ordernum;a++)
|
|
{
|
|
dis=co[c=order[a]].dist;
|
|
for(b=a-1;b>=0 && dis>co[order[b]].dist;b--)
|
|
order[b+1]=order[b];
|
|
order[b+1]=c;
|
|
}
|
|
|
|
if(!drawpass)
|
|
{
|
|
print("[Zsort order: (conum=%i)]\n",conum);
|
|
}
|
|
for(a=0;a<ordernum;a++)
|
|
{
|
|
int x,y;
|
|
o=co[order[a]].o;
|
|
fill_curobj=order[a];
|
|
vis_drawobject(o);
|
|
co[order[a]].on=!o->vf;
|
|
if(!drawpass)
|
|
{
|
|
print("[%s(%i): %li (v%i)]\n",co[order[a]].name,order[a],co[order[a]].dist,o->pl[0][1]);
|
|
if(!o->vf)
|
|
{
|
|
x=o->pv[o->pl[0][1]].x;
|
|
y=o->pv[o->pl[0][1]].y;
|
|
x=x+y*320;
|
|
vram[x]=255;
|
|
vram[x-1]=255;
|
|
vram[x+1]=255;
|
|
vram[x-320]=255;
|
|
vram[x+320]=255;
|
|
}
|
|
}
|
|
}
|
|
if(!drawpass)
|
|
{
|
|
print("\n");
|
|
}
|
|
}
|
|
}
|