static void printtrace(regcontext_t *REGS, char *buf) { static int first = 1; #if BIG_DEBUG u_char *addr = (u_char *)MAKEPTR(R_CS, R_IP); #endif if (first) { fprintf(debugf, "%4s:%4s " #if BIG_DEBUG ".. .. .. .. .. .. " #endif "%-30s " "%4s %4s %4s %4s %4s %4s %4s %4s %4s %4s %4s\n", "CS", "IP", "instruction", "AX", "BX", "CX", "DX", "DI", "SI", "SP", "BP", "SS", "DS", "ES"); first = 0; } fprintf(debugf, "%04x:%04x " #if BIG_DEBUG "%02x %02x %02x %02x %02x %02x " #endif "%-30s " "%04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x ", R_CS, R_IP, #if BIG_DEBUG addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], #endif buf, R_AX, R_BX, R_CX, R_DX, R_DI, R_SI, R_SP, R_BP, R_SS, R_DS, R_ES); #if 0 fprintf(debugf, "%04x %04x %04x %04x ", ((u_short *)VECPTR(0x0D760FCA-14))[0], ((u_short *)VECPTR(0x0D760FCA-14))[1], ((u_short *)VECPTR(0x0D760F7A+8))[0], ((u_short *)VECPTR(0x0D760F7A+8))[1]); #endif showstate(R_EFLAGS, PSL_C, 'C'); showstate(R_EFLAGS, PSL_PF, 'P'); showstate(R_EFLAGS, PSL_AF, 'c'); showstate(R_EFLAGS, PSL_Z, 'Z'); showstate(R_EFLAGS, PSL_N, 'N'); showstate(R_EFLAGS, PSL_T, 'T'); showstate(R_EFLAGS, PSL_I, 'I'); showstate(R_EFLAGS, PSL_D, 'D'); showstate(R_EFLAGS, PSL_V, 'V'); showstate(R_EFLAGS, PSL_NT, 'n'); showstate(R_EFLAGS, PSL_RF, 'r'); showstate(R_EFLAGS, PSL_VM, 'v'); showstate(R_EFLAGS, PSL_AC, 'a'); showstate(R_EFLAGS, PSL_VIF, 'i'); showstate(R_EFLAGS, PSL_VIP, 'p'); putc('\n', debugf); }
void bios_init(void) { int i, j, k; u_char *jtab; struct timeval tv; time_t tv_sec; struct timezone tz; struct tm tm; u_long vec; strcpy((char *)BIOS_copyright, "Copyright (C) 1993 Krystal Technologies/BSDI"); *(u_short *)BIOS_reset = 0xffcd; *(u_short *)BIOS_nmi = 0xffcd; *(u_short *)BIOS_boot = 0xffcd; *(u_short *)BIOS_comm_io = 0xffcd; *(u_short *)BIOS_keyboard_io = 0xffcd; *(u_short *)BIOS_keyboard_isr = 0xffcd; *(u_short *)BIOS_fdisk_io = 0xffcd; *(u_short *)BIOS_fdisk_isr = 0xffcd; *(u_short *)BIOS_printer_io = 0xffcd; *(u_short *)BIOS_video_io = 0xffcd; *(u_short *)BIOS_cassette_io = 0xffcd; *(u_short *)BIOS_time_of_day = 0xffcd; *(u_short *)BIOS_timer_int = 0xffcd; *(u_short *)BIOS_dummy_iret = 0xffcd; *(u_short *)BIOS_print_screen = 0xffcd; *(u_short *)BIOS_hard_reset = 0xffcd; *(u_short *)BIOS_mem_size = 0xffcd; *(u_short *)BIOS_equipment = 0xffcd; *(u_short *)BIOS_vector = 0xffcd; *(u_char *)0xffff2 = 0xcf; /* IRET */ memcpy((u_char *)BIOS_disk_parms, disk_params, sizeof(disk_params)); memcpy((u_char *)BIOS_comm_table, comm_table, sizeof(comm_table)); *(u_short *)BIOS_video_font = 0xffcd; jtab = (u_char *)BIOS_date_stamp; *jtab++ = '1'; *jtab++ = '0'; *jtab++ = '/'; *jtab++ = '3'; *jtab++ = '1'; *jtab++ = '/'; *jtab++ = '9'; *jtab++ = '3'; *(u_char *)BIOS_hardware_id = 0xfc; /* Identify as a PC/AT */ /* * Interrupt revectors F000:0000 - F000:03ff */ for (i = 0, j = 0, k = 0; i < 0x100; ++i) { if ((i >= 0x60 && i < 0x68) || (i >= 0x78 && i < 0xe2)) continue; if ((i >= 0x00 && i < 0x2f) || (i >= 0x30 && i < 0xfe)) { ivec[i] = 0xF0300000L | (k * 1); jtab = (u_char *)VECPTR(ivec[i]); *jtab++ = 0xf4; /* HLT */ ++k; } else { ivec[i] = 0xF0000000L | (j * 6); jtab = (u_char *)VECPTR(ivec[i]); *jtab++ = 0xcd; /* INT i */ *jtab++ = i; *jtab++ = 0xca; /* RETF 2 */ *jtab++ = 2; *jtab++ = 0; ++j; } } /* * Misc variables from F000:0400 - F000:0fff */ rom_config = 0xF0000400; jtab = (u_char *)VECPTR(rom_config); *jtab++ = 20; /* length of entry */ *jtab++ = 0; *jtab++ = *(u_char *)BIOS_hardware_id; *jtab++ = 0x00; /* Sub model */ *jtab++ = 0x01; /* Bios Rev Enhanced kbd w/3.5" floppy */ *jtab++ = 0x20; /* real time clock present */ *jtab++ = 0; /* Reserved */ *jtab++ = 0; *jtab++ = 0; *jtab++ = 0; strcpy((char *)jtab, "BSDI BIOS"); *jtab += 10; InDOS = jtab++; *InDOS = 0; mouse_area = jtab; jtab += 0x10; *(u_short *)&BIOSDATA[0x10] = (1 << 0) | /* Diskette avail for boot */ (1 << 1) | /* Math co-processor */ (nmice << 2) | /* No pointing device */ (2 << 4) | /* Initial video (80 x 25 C) */ ((nfloppies - 1) << 6) | /* Number of floppies - 1 */ (nserial << 9) | /* Number of serial devices */ (nparallel << 14); /* Number of parallel devices */ *(u_short *)&BIOSDATA[0x13] = 640; /* Amount of memory */ BIOSDATA[0x75] = ndisks; /* number of fixed disks */ BIOSDATA[0x8F] = 0; if (nfloppies >= 1) { BIOSDATA[0x8F] |= 0x04; BIOSDATA[0x90] = 0x40; } if (nfloppies >= 2) { BIOSDATA[0x8F] |= 0x40; BIOSDATA[0x91] = 0x40; } gettimeofday(&tv, &tz); tv_sec = tv.tv_sec; tm = *localtime(&tv_sec); *(u_long *)&BIOSDATA[0x6c] = (((tm.tm_hour * 60 + tm.tm_min) * 60) + tm.tm_sec) * 182 / 10; vec = insert_softint_trampoline(); ivec[0x11] = vec; register_callback(vec, int11, "int 11"); vec = insert_softint_trampoline(); ivec[0x12] = vec; register_callback(vec, int12, "int 12"); vec = insert_softint_trampoline(); ivec[0x14] = vec; register_callback(vec, int14, "int 14"); vec = insert_softint_trampoline(); ivec[0x15] = vec; register_callback(vec, int15, "int 15"); vec = insert_softint_trampoline(); ivec[0x16] = vec; register_callback(vec, int16, "int 16"); vec = insert_softint_trampoline(); ivec[0x17] = vec; register_callback(vec, int17, "int 17"); vec = insert_softint_trampoline(); ivec[0x1a] = vec; register_callback(vec, int1a, "int 1a"); }
//walks through all submodels of a polymodel and determines the coordinate extremes int GetPolyModelMinMax (void *modelP, tHitbox *phb, int nSubModels) { ubyte *p = (ubyte *) modelP; int i, n, nVerts; vmsVector *v, hv; tHitbox hb = *phb; G3CheckAndSwap (modelP); for (;;) switch (WORDVAL (p)) { case OP_EOF: goto done; case OP_DEFPOINTS: n = WORDVAL (p + 2); v = VECPTR (p + 4); for (i = n; i; i--, v++) { hv = *v; if (hb.vMin.p.x > hv.p.x) hb.vMin.p.x = hv.p.x; else if (hb.vMax.p.x < hv.p.x) hb.vMax.p.x = hv.p.x; if (hb.vMin.p.y > hv.p.y) hb.vMin.p.y = hv.p.y; else if (hb.vMax.p.y < hv.p.y) hb.vMax.p.y = hv.p.y; if (hb.vMin.p.z > hv.p.z) hb.vMin.p.z = hv.p.z; else if (hb.vMax.p.z < hv.p.z) hb.vMax.p.z = hv.p.z; } p += n * sizeof (vmsVector) + 4; break; case OP_DEFP_START: n = WORDVAL (p + 2); v = VECPTR (p + 8); for (i = n; i; i--, v++) { hv = *v; if (hb.vMin.p.x > hv.p.x) hb.vMin.p.x = hv.p.x; else if (hb.vMax.p.x < hv.p.x) hb.vMax.p.x = hv.p.x; if (hb.vMin.p.y > hv.p.y) hb.vMin.p.y = hv.p.y; else if (hb.vMax.p.y < hv.p.y) hb.vMax.p.y = hv.p.y; if (hb.vMin.p.z > hv.p.z) hb.vMin.p.z = hv.p.z; else if (hb.vMax.p.z < hv.p.z) hb.vMax.p.z = hv.p.z; } p += n * sizeof (vmsVector) + 8; break; case OP_FLATPOLY: nVerts = WORDVAL (p + 2); p += 30 + (nVerts | 1) * 2; break; case OP_TMAPPOLY: nVerts = WORDVAL (p + 2); p += 30 + (nVerts | 1) * 2 + nVerts * 12; break; case OP_SORTNORM: *phb = hb; if (G3CheckNormalFacing (VECPTR (p+16), VECPTR (p+4))) { //facing nSubModels = GetPolyModelMinMax (p + WORDVAL (p+30), phb, nSubModels); nSubModels = GetPolyModelMinMax (p + WORDVAL (p+28), phb, nSubModels); } else { nSubModels = GetPolyModelMinMax (p + WORDVAL (p+28), phb, nSubModels); nSubModels = GetPolyModelMinMax (p + WORDVAL (p+30), phb, nSubModels); } hb = *phb; p += 32; break; case OP_RODBM: p += 36; break; case OP_SUBCALL: #if 1 VmVecAdd (&phb [++nSubModels].vOffset, &phb->vOffset, VECPTR (p+4)); #else pvOffs [nSubModels] = *VECPTR (p+4); #endif nSubModels += GetPolyModelMinMax (p + WORDVAL (p+16), phb + nSubModels, 0); p += 20; break; case OP_GLOW: p += 4; break; default: Error ("invalid polygon model\n"); } done: *phb = hb; return nSubModels; }
//------------------------------------------------------------------------------ //calls the tObject interpreter to render an tObject. The tObject renderer //is really a seperate pipeline. returns true if drew fix G3PolyModelSize (void *modelP) { ubyte *p = modelP; int i, n, nv; vmsVector *v, pMin = {0x7fffffff, 0x7fffffff, 0x7fffffff}, pMax = {-0x7fffffff, -0x7fffffff, -0x7fffffff}; G3CheckAndSwap (modelP); for (;;) switch (WORDVAL (p)) { case OP_EOF: goto done; case OP_DEFPOINTS: n = WORDVAL (p + 2); v = VECPTR (p + 4); for (i = n; i; i--, v++) { if (pMin.x > v->x) pMin.x = v->x; else if (pMax.x < v->x) pMax.x = v->x; if (pMin.y > v->y) pMin.y = v->y; else if (pMax.y < v->y) pMax.y = v->y; if (pMin.z > v->z) pMin.z = v->z; else if (pMax.z < v->z) pMax.z = v->z; } p += n * sizeof (struct vmsVector) + 4; break; case OP_DEFP_START: n = WORDVAL (p + 2); v = VECPTR (p + 8); for (i = n; i; i--, v++) { if (pMin.x > v->x) pMin.x = v->x; else if (pMax.x < v->x) pMax.x = v->x; if (pMin.y > v->y) pMin.y = v->y; else if (pMax.y < v->y) pMax.y = v->y; if (pMin.z > v->z) pMin.z = v->z; else if (pMax.z < v->z) pMax.z = v->z; } p += n * sizeof (struct vmsVector) + 8; break; case OP_FLATPOLY: nv = WORDVAL (p + 2); p += 30 + ((nv & ~1) + 1) * 2; break; case OP_TMAPPOLY: nv = WORDVAL (p + 2); p += 30 + ((nv & ~1) + 1) * 2 + nv * 12; break; case OP_SORTNORM: p += 32; break; case OP_RODBM: p += 36; break; case OP_SUBCALL: p += 20; break; case OP_GLOW: p += 4; break; default: Error ("invalid polygon model\n"); } done: { double dx = (pMax.x - pMin.x) / 2; double dy = (pMax.y - pMin.y) / 2; double dz = (pMax.z - pMin.z) / 2; return (fix) sqrt (dx * dx + dy * dy + dz + dz); } //return VmVecDist (&pMin, &pMax) / 2; }
void G3SwapPolyModelData (ubyte *data) { int i; short n; uvl *uvl_val; ubyte *p = data; for (;;) { ShortSwap (WORDPTR (p)); switch (WORDVAL (p)) { case OP_EOF: return; case OP_DEFPOINTS: ShortSwap (WORDPTR (p + 2)); n = WORDVAL (p+2); for (i = 0; i < n; i++) VmsVectorSwap (VECPTR ((p + 4) + (i * sizeof (vmsVector)))); p += n*sizeof (struct vmsVector) + 4; break; case OP_DEFP_START: ShortSwap (WORDPTR (p + 2)); ShortSwap (WORDPTR (p + 4)); n = WORDVAL (p+2); for (i = 0; i < n; i++) VmsVectorSwap (VECPTR ((p + 8) + (i * sizeof (vmsVector)))); p += n*sizeof (struct vmsVector) + 8; break; case OP_FLATPOLY: ShortSwap (WORDPTR (p+2)); n = WORDVAL (p+2); VmsVectorSwap (VECPTR (p + 4)); VmsVectorSwap (VECPTR (p + 16)); ShortSwap (WORDPTR (p+28)); for (i=0; i < n; i++) ShortSwap (WORDPTR (p + 30 + (i * 2))); p += 30 + ((n&~1)+1)*2; break; case OP_TMAPPOLY: ShortSwap (WORDPTR (p+2)); n = WORDVAL (p+2); VmsVectorSwap (VECPTR (p + 4)); VmsVectorSwap (VECPTR (p + 16)); for (i = 0; i < n; i++) { uvl_val = (uvl *) ((p+30+ ((n&~1)+1)*2) + (i * sizeof (uvl))); FixSwap (&uvl_val->u); FixSwap (&uvl_val->v); } ShortSwap (WORDPTR (p+28)); for (i=0;i<n;i++) ShortSwap (WORDPTR (p + 30 + (i * 2))); p += 30 + ((n&~1)+1)*2 + n*12; break; case OP_SORTNORM: VmsVectorSwap (VECPTR (p + 4)); VmsVectorSwap (VECPTR (p + 16)); ShortSwap (WORDPTR (p + 28)); ShortSwap (WORDPTR (p + 30)); G3SwapPolyModelData (p + WORDVAL (p+28)); G3SwapPolyModelData (p + WORDVAL (p+30)); p += 32; break; case OP_RODBM: VmsVectorSwap (VECPTR (p + 20)); VmsVectorSwap (VECPTR (p + 4)); ShortSwap (WORDPTR (p+2)); FixSwap (FIXPTR (p + 16)); FixSwap (FIXPTR (p + 32)); p+=36; break; case OP_SUBCALL: ShortSwap (WORDPTR (p+2)); VmsVectorSwap (VECPTR (p+4)); ShortSwap (WORDPTR (p+16)); G3SwapPolyModelData (p + WORDVAL (p+16)); p += 20; break; case OP_GLOW: ShortSwap (WORDPTR (p + 2)); p += 4; break; default: Error ("invalid polygon model\n"); //Int3 (); } } }
int G3GetPOFModelItems (void *modelP, vmsAngVec *pAnimAngles, tG3Model *pm, int nThis, int nParent, int bSubObject, grsBitmap **modelBitmaps, tRgbaColorf *pObjColor) { ubyte *p = (ubyte *) modelP; tG3SubModel *psm = pm->pSubModels + nThis; tG3ModelFace *pmf = pm->pFaces + pm->iFace; int nChild; short nTag; G3CheckAndSwap (modelP); nGlow = -1; if (bSubObject) { G3InitSubModelMinMax (psm); psm->nIndex = -1; psm->nParent = nParent; psm->nBomb = -1; psm->nMissile = -1; psm->nGun = -1; psm->nGunPoint = -1; psm->bBullets = 0; psm->bThruster = 0; psm->bGlow = 0; psm->bRender = 1; } for (;;) { nTag = WORDVAL (p); switch (nTag) { case OP_EOF: return 1; case OP_DEFPOINTS: { int i, n = WORDVAL (p+2); fVector3 *pfv = pm->pVerts; vmsVector *pv = VECPTR (p+4); for (i = n; i; i--) { *pfv = pv->ToFloat3(); pfv++; pv++; } p += n * sizeof (vmsVector) + 4; break; } case OP_DEFP_START: { int i, n = WORDVAL (p+2); int s = WORDVAL (p+4); fVector3 *pfv = pm->pVerts + s; vmsVector *pv = VECPTR (p+8); for (i = n; i; i--) { *pfv = pv->ToFloat3(); pfv++; pv++; } p += n * sizeof (vmsVector) + 8; break; } case OP_FLATPOLY: { int nVerts = WORDVAL (p+2); pmf = G3AddModelFace (pm, psm, pmf, VECPTR (p+16), p, NULL, pObjColor); p += 30 + (nVerts | 1) * 2; break; } case OP_TMAPPOLY: { int nVerts = WORDVAL (p + 2); pmf = G3AddModelFace (pm, psm, pmf, VECPTR (p+16), p, modelBitmaps, pObjColor); p += 30 + (nVerts | 1) * 2 + nVerts * 12; break; } case OP_SORTNORM: if (!G3GetPOFModelItems (p + WORDVAL (p+28), pAnimAngles, pm, nThis, nParent, 0, modelBitmaps, pObjColor)) return 0; pmf = pm->pFaces + pm->iFace; if (!G3GetPOFModelItems (p + WORDVAL (p+30), pAnimAngles, pm, nThis, nParent, 0, modelBitmaps, pObjColor)) return 0; pmf = pm->pFaces + pm->iFace; p += 32; break; case OP_RODBM: p += 36; break; case OP_SUBCALL: nChild = ++pm->iSubModel; pm->pSubModels [nChild].vOffset = *VECPTR (p+4); pm->pSubModels [nChild].nAngles = WORDVAL (p+2); G3InitSubModelMinMax (pm->pSubModels + nChild); if (!G3GetPOFModelItems (p + WORDVAL (p+16), pAnimAngles, pm, nChild, nThis, 1, modelBitmaps, pObjColor)) return 0; pmf = pm->pFaces + pm->iFace; p += 20; break; case OP_GLOW: nGlow = WORDVAL (p+2); p += 4; break; default: Error ("invalid polygon model\n"); return 0; } } return 1; }
//------------------------------------------------------------------------------ //alternate interpreter for morphing tObject bool G3DrawMorphingModel (void *modelP, grsBitmap **modelBitmaps, vmsAngVec *pAnimAngles, vmsVector *vOffset, fix xModelLight, vmsVector *new_points, int nModel) { ubyte *p = modelP; fix *xGlowValues = NULL; G3CheckAndSwap (modelP); nGlow = -1; //glow off by default for (;;) { switch (WORDVAL (p)) { case OP_EOF: return 1; case OP_DEFPOINTS: { int n = WORDVAL (p+2); RotatePointList (modelPointList, new_points, NULL, n, 0); p += n*sizeof (vmsVector) + 4; break; } case OP_DEFP_START: { int n = WORDVAL (p+2); int s = WORDVAL (p+4); RotatePointList (modelPointList, new_points, NULL, n, s); p += n*sizeof (vmsVector) + 8; break; } case OP_FLATPOLY: { int nVerts = WORDVAL (p+2); int i, nTris; GrSetColor (WORDVAL (p+28)); for (i = 0; i < 2; i++) pointList [i] = modelPointList + WORDPTR (p+30) [i]; for (nTris=nVerts-2;nTris;nTris--) { pointList [2] = modelPointList + WORDPTR (p+30) [i++]; G3CheckAndDrawPoly (3, pointList, NULL, NULL); pointList [1] = pointList [2]; } p += 30 + ((nVerts&~1)+1)*2; break; } case OP_TMAPPOLY: { int nVerts = WORDVAL (p+2); tUVL *uvlList; tUVL morph_uvls [3]; int i, nTris; fix light; //calculate light from surface normal if (nGlow < 0) { //no glow light = -VmVecDot (&viewInfo.view [0].fVec, VECPTR (p+16)); light = f1_0/4 + (light*3)/4; light = FixMul (light, xModelLight); } else { //yes glow light = xGlowValues [nGlow]; nGlow = -1; } //now poke light into l values uvlList = (tUVL *) (p+30+ ((nVerts&~1)+1)*2); for (i = 0; i < 3; i++) morph_uvls [i].l = light; for (i = 0; i < 2; i++) { pointList [i] = modelPointList + WORDPTR (p+30) [i]; morph_uvls [i].u = uvlList [i].u; morph_uvls [i].v = uvlList [i].v; } for (nTris = nVerts - 2; nTris; nTris--) { pointList [2] = modelPointList + WORDPTR (p+30) [i]; morph_uvls [2].u = uvlList [i].u; morph_uvls [2].v = uvlList [i].v; i++; G3CheckAndDrawTMap (3, pointList, uvlList, modelBitmaps [WORDVAL (p+28)], NULL, NULL); pointList [1] = pointList [2]; morph_uvls [1].u = morph_uvls [2].u; morph_uvls [1].v = morph_uvls [2].v; } p += 30 + ((nVerts&~1)+1)*2 + nVerts*12; break; } case OP_SORTNORM: if (G3CheckNormalFacing (VECPTR (p+16), VECPTR (p+4)) > 0) { //facing //draw back then front G3DrawMorphingModel (p + WORDVAL (p+30), modelBitmaps, pAnimAngles, vOffset, xModelLight, new_points, nModel); G3DrawMorphingModel (p + WORDVAL (p+28), modelBitmaps, pAnimAngles, vOffset, xModelLight, new_points, nModel); } else { //not facing. draw front then back G3DrawMorphingModel (p + WORDVAL (p+28), modelBitmaps, pAnimAngles, vOffset, xModelLight, new_points, nModel); G3DrawMorphingModel (p + WORDVAL (p+30), modelBitmaps, pAnimAngles, vOffset, xModelLight, new_points, nModel); } p += 32; break; case OP_RODBM: { g3sPoint rodBotP, rodTopP; G3TransformAndEncodePoint (&rodBotP, VECPTR (p+20)); G3TransformAndEncodePoint (&rodTopP, VECPTR (p+4)); G3DrawRodTexPoly (modelBitmaps [WORDVAL (p+2)], &rodBotP, WORDVAL (p+16), &rodTopP, WORDVAL (p+32), f1_0, NULL); p += 36; break; } case OP_SUBCALL: { vmsAngVec *va = pAnimAngles ? &pAnimAngles [WORDVAL (p+2)] : &avZero; vmsVector vo = *VECPTR (p+4); if (gameData.models.nScale) VmVecScale (&vo, gameData.models.nScale); G3StartInstanceAngles (&vo, va); if (vOffset) VmVecInc (&vo, vOffset); G3DrawPolyModel (NULL, p + WORDVAL (p+16), modelBitmaps, pAnimAngles, &vo, xModelLight, xGlowValues, NULL, NULL, nModel); G3DoneInstance (); p += 20; break; } case OP_GLOW: if (xGlowValues) nGlow = WORDVAL (p+2); p += 4; break; } } return 1; }
bool G3DrawPolyModel ( tObject *objP, void *modelP, grsBitmap **modelBitmaps, vmsAngVec *pAnimAngles, vmsVector *vOffset, fix xModelLight, fix *xGlowValues, tRgbaColorf *pObjColor, tPOFObject *po, int nModel) { ubyte *p = modelP; short h; short bGetThrusterPos = !objP || ((objP->nType == OBJ_PLAYER) || (objP->nType == OBJ_ROBOT) || ((objP->nType == OBJ_WEAPON) && gameData.objs.bIsMissile [objP->id])); short bLightnings = SHOW_LIGHTNINGS && gameOpts->render.lightnings.bDamage && objP && (ObjectDamage (objP) < 0.5f); static int nDepth = -1; #if DBG_SHADOWS if (bShadowTest) return 1; #endif #if CONTOUR_OUTLINE //if (extraGameInfo [0].bShadows && (gameStates.render.nShadowPass < 3)) return 1; #endif nDepth++; G3CheckAndSwap (modelP); if (SHOW_DYN_LIGHT && !nDepth && !po && objP && ((objP->nType == OBJ_ROBOT) || (objP->nType == OBJ_PLAYER))) { po = gameData.models.pofData [gameStates.app.bD1Mission][0] + nModel; POFGatherPolyModelItems (objP, modelP, pAnimAngles, po, 0); } nGlow = -1; //glow off by default glEnable (GL_CULL_FACE); glCullFace (GL_BACK); for (;;) { h = WORDVAL (p); if (h == OP_EOF) break; else if (h == OP_DEFPOINTS) { int n = WORDVAL (p+2); RotatePointList (modelPointList, VECPTR (p+4), po ? po->pVertNorms : NULL, n, 0); p += n * sizeof (vmsVector) + 4; break; } else if (h == OP_DEFP_START) { int n = WORDVAL (p+2); int s = WORDVAL (p+4); RotatePointList (modelPointList, VECPTR (p+8), po ? po->pVertNorms : NULL, n, s); p += n * sizeof (vmsVector) + 8; } else if (h == OP_FLATPOLY) { int nVerts = WORDVAL (p+2); Assert (nVerts < MAX_POINTS_PER_POLY); #if CHECK_NORMAL_FACING if (G3CheckNormalFacing (VECPTR (p+4), VECPTR (p+16)) > 0) #endif { int i; //fix l = f2i (32 * xModelLight); GrSetColorRGB15bpp (WORDVAL (p+28), (ubyte) (255 * GrAlpha ())); GrFadeColorRGB (1.0); if (pObjColor) { pObjColor->red = (float) grdCurCanv->cvColor.color.red / 255.0f; pObjColor->green = (float) grdCurCanv->cvColor.color.green / 255.0f; pObjColor->blue = (float) grdCurCanv->cvColor.color.blue / 255.0f; } p += 30; for (i = 0; i < nVerts; i++) pointList [i] = modelPointList + WORDPTR (p) [i]; G3DrawPoly (nVerts, pointList); } #if CHECK_NORMAL_FACING else p += 30; #endif p += (nVerts | 1) * 2; } else if (h == OP_TMAPPOLY) { int nVerts = WORDVAL (p+2); Assert ( nVerts < MAX_POINTS_PER_POLY ); #if CHECK_NORMAL_FACING if (G3CheckNormalFacing (VECPTR (p+4), VECPTR (p+16)) > 0) #endif { tUVL *uvlList; int i; fix l; vmsVector *pvn = VECPTR (p+16); //calculate light from surface normal if (nGlow < 0) { //no glow l = -VmVecDot (&viewInfo.view [0].fVec, VECPTR (p+16)); l = f1_0 / 4 + (l * 3) / 4; l = FixMul (l, xModelLight); } else { //yes glow l = xGlowValues [nGlow]; nGlow = -1; } //now poke light into l values uvlList = (tUVL *) (p + 30 + (nVerts | 1) * 2); for (i = 0; i < nVerts; i++) uvlList [i].l = l; if (pObjColor) { unsigned char c = modelBitmaps [WORDVAL (p+28)]->bmAvgColor; pObjColor->red = CPAL2Tr (gamePalette, c); pObjColor->green = CPAL2Tg (gamePalette, c); pObjColor->blue = CPAL2Tb (gamePalette, c); } p += 30; for (i = 0; i < nVerts; i++) pointList [i] = modelPointList + WORDPTR (p) [i]; tMapColor = gameData.objs.color; if (gameStates.render.bCloaked) G3DrawTexPolyFlat (nVerts, pointList, uvlList, NULL, modelBitmaps [WORDVAL (p-2)], NULL, NULL, VECPTR (p+16), 0, 1); else G3DrawTexPolySimple (nVerts, pointList, uvlList, modelBitmaps [WORDVAL (p-2)], VECPTR (p+16), 1); if (!gameStates.render.bBriefing) { if (bLightnings) RenderDamageLightnings (objP, pointList, NULL, nVerts); if (bGetThrusterPos) GetThrusterPos (nModel, pvn, vOffset, modelBitmaps [WORDVAL (p-2)], nVerts); } } #if CHECK_NORMAL_FACING else p += 30; #endif p += (nVerts | 1) * 2 + nVerts * 12; } else if (h == OP_SORTNORM) { #if CHECK_NORMAL_FACING if (G3CheckNormalFacing (VECPTR (p+16), VECPTR (p+4)) > 0) #endif { //facing //draw back then front if (!(G3DrawPolyModel (objP, p + WORDVAL (p+30), modelBitmaps, pAnimAngles, vOffset, xModelLight, xGlowValues, pObjColor, po, nModel) && G3DrawPolyModel (objP, p + WORDVAL (p+28), modelBitmaps, pAnimAngles, vOffset, xModelLight, xGlowValues, pObjColor, po, nModel))) return 0; } #if CHECK_NORMAL_FACING else { //not facing. draw front then back if (!(G3DrawPolyModel (objP, p + WORDVAL (p+28), modelBitmaps, pAnimAngles, vOffset, xModelLight, xGlowValues, pObjColor, po, nModel) && G3DrawPolyModel (objP, p + WORDVAL (p+30), modelBitmaps, pAnimAngles, vOffset, xModelLight, xGlowValues, pObjColor, po, nModel))) return 0; } #endif p += 32; } else if (h == OP_RODBM) { g3sPoint rodBotP, rodTopP; G3TransformAndEncodePoint (&rodBotP, VECPTR (p+20)); G3TransformAndEncodePoint (&rodTopP, VECPTR (p+4)); G3DrawRodTexPoly (modelBitmaps [WORDVAL (p+2)], &rodBotP, WORDVAL (p+16), &rodTopP, WORDVAL (p+32), f1_0, NULL); p += 36; } else if (h == OP_SUBCALL) { vmsAngVec *va; vmsVector vo; va = pAnimAngles ? pAnimAngles + WORDVAL (p+2) : NULL; vo = *VECPTR (p+4); if (gameData.models.nScale) VmVecScale (&vo, gameData.models.nScale); G3StartInstanceAngles (&vo, va); if (vOffset) VmVecInc (&vo, vOffset); if (!G3DrawPolyModel (objP, p + WORDVAL (p+16), modelBitmaps, pAnimAngles, &vo, xModelLight, xGlowValues, pObjColor, po, nModel)) { G3DoneInstance (); return 0; } G3DoneInstance (); p += 20; } else if (h == OP_GLOW) { if (xGlowValues) nGlow = WORDVAL (p+2); p += 4; } else { #ifdef _DEBUG LogErr ("invalid polygon model\n"); #endif return 0; } } nDepth--; return 1; }