/*
====================
=
= HitHorizPWall
=
= A pushable wall in action has been hit
=
====================
*/
void HitHorizPWall (void)
{
int wallpic;
unsigned texture,offset;
texture = (xintercept>>4)&0xfc0;
offset = pwallpos 10;
if (ytilestep == -1)
yintercept += TILEGLOBAL-offset;
else
{
texture = 0xfc0-texture;
yintercept += offset;
}
wallheight[pixx] = CalcHeight();
if (lasttilehit == tilehit)
{
// in the same wall type as last time, so check for optimized draw
if (texture == (unsigned)postsource)
{
// wide scale
postwidth++;
wallheight[pixx] = wallheight[pixx-1];
return;
}
else
{
ScalePost ();
(unsigned)postsource = texture;
postwidth = 1;
postx = pixx;
}
}
else
{
// new wall
if (lastside != -1) // if not the first scaled post
ScalePost ();
lasttilehit = tilehit;
postx = pixx;
postwidth = 1;
wallpic = horizwall[tilehit&63];
*( ((unsigned *)&postsource)+1) = (unsigned)PM_GetPage(wallpic);
(unsigned)postsource = texture;
}
}
/*
====================
=
= HitVertPWall
=
= A pushable wall in action has been hit
=
====================
*/
void HitVertPWall (void)
{
int wallpic;
unsigned texture,offset;
texture = (yintercept>>4)&0xfc0;
offset = pwallpos 10;
if (xtilestep == -1)
{
xintercept += TILEGLOBAL-offset;
texture = 0xfc0-texture;
}
else
xintercept += offset;
wallheight[pixx] = CalcHeight();
if (lasttilehit == tilehit)
{
// in the same wall type as last time, so check for optimized draw
if (texture == (unsigned)postsource)
{
// wide scale
postwidth++;
wallheight[pixx] = wallheight[pixx-1];
return;
}
else
{
ScalePost ();
(unsigned)postsource = texture;
postwidth = 1;
postx = pixx;
}
}
else
{
// new wall
if (lastside != -1) // if not the first scaled post
ScalePost ();
lasttilehit = tilehit;
postx = pixx;
postwidth = 1;
wallpic = vertwall[tilehit&63];
*( ((unsigned *)&postsource)+1) = (unsigned)PM_GetPage(wallpic);
(unsigned)postsource = texture;
}
}
//==========================================================================
//==========================================================================
#if 0
/*
=====================
=
= ClearScreen
=
=====================
*/
void ClearScreen (void)
{
unsigned floor=egaFloor[gamestate.episode*10+mapon],
ceiling=egaCeiling[gamestate.episode*10+mapon];
//
// clear the screen
//
asm mov dx,GC_INDEX
asm mov ax,GC_MODE + 256*2 // read mode 0, write mode 2
asm out dx,ax
asm mov ax,GC_BITMASK + 255*256
asm out dx,ax
asm mov dx,40
asm mov ax,[viewwidth]
asm shr ax,3
asm sub dx,ax // dx = 40-viewwidth/8
asm mov bx,[viewwidth]
asm shr bx,4 // bl = viewwidth/16
asm mov bh,BYTE PTR [viewheight]
asm shr bh,1 // half height
asm mov ax,[ceiling]
asm mov es,[screenseg]
asm mov di,[bufferofs]
toploop:
asm mov cl,bl
asm rep stosw
asm add di,dx
asm dec bh
asm jnz toploop
asm mov bh,BYTE PTR [viewheight]
asm shr bh,1 // half height
asm mov ax,[floor]
bottomloop:
asm mov cl,bl
asm rep stosw
asm add di,dx
asm dec bh
asm jnz bottomloop
asm mov dx,GC_INDEX
asm mov ax,GC_MODE + 256*10 // read mode 1, write mode 2
asm out dx,ax
asm mov al,GC_BITMASK
asm out dx,al
}
#endif
//==========================================================================
unsigned vgaCeiling[]=
{
#ifndef SPEAR
0x0f0f,";modf 0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,
0x0f0f,";modf 0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,
0x0f0f,";modf 0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,
0x0f0f,";modf 0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,
0x0f0f,";modf 0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,
0x0f0f,";modf 0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f
#else
0x0f0f,";modf 0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,
0x0f0f,";modf 0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f,0x0f0f
#endif
};
/*
=====================
=
= VGAClearScreen
=
=====================
*/
void VGAClearScreen (void)
{
unsigned ceiling=vgaCeiling[gamestate.episode*10+mapon];
//
// clear the screen
//
asm mov dx,SC_INDEX
asm mov ax,SC_MAPMASK+15*256 // write through all planes
asm out dx,ax
asm mov dx,80
asm mov ax,[viewwidth]
asm shr ax,2
asm sub dx,ax // dx = 40-viewwidth/2
asm mov bx,[viewwidth]
asm shr bx,3 // bl = viewwidth/8
asm mov bh,BYTE PTR [viewheight]
asm shr bh,1 // half height
asm mov es,[screenseg]
asm mov di,[bufferofs]
asm mov ax,[ceiling]
toploop:
asm mov cl,bl
asm rep stosw
asm add di,dx
asm dec bh
asm jnz toploop
asm mov bh,BYTE PTR [viewheight]
asm shr bh,1 // half height
asm mov ax,0x0f0f //0x0f0f;modf
bottomloop:
asm mov cl,bl
asm rep stosw
asm add di,dx
asm dec bh
asm jnz bottomloop
}
//==========================================================================
/*
=====================
=
= CalcRotate
=
=====================
*/
int CalcRotate (objtype *ob)
{
int angle,viewangle;
// this isn't exactly correct, as it should vary by a trig value,
// but it is close enough with only eight rotations
viewangle = player->angle + (centerx - ob->viewx)/8;
if (ob->obclass == rocketobj || ob->obclass == hrocketobj)
angle = (viewangle-180)- ob->angle;
else
angle = (viewangle-180)- dirangle[ob->dir];
angle+=ANGLES/16;
while (angle>=ANGLES)
angle-=ANGLES;
while (angle0)
angle+=ANGLES;
if (ob->state->rotate == 2) // 2 rotation pain frame
return 4*(angle/(ANGLES/2)); // seperated by 3 (art layout...)
return angle/(ANGLES/8);
}
/*
=====================
=
= DrawScaleds
=
= Draws all objects that are visable
=
=====================
*/
#define MAXVISABLE 50
typedef struct
{
int viewx,
viewheight,
shapenum;
} visobj_t;
visobj_t vislist[MAXVISABLE],*visptr,*visstep,*farthest;
void DrawScaleds (void)
{
int i,j,least,numvisable,height;
memptr shape;
byte *tilespot,*visspot;
int shapenum;
unsigned spotloc;
statobj_t *statptr;
objtype *obj;
visptr = &vislist[0];
//
// place static objects
//
for (statptr = &statobjlist[0] ; statptr !=laststatobj ; statptr++)
{
if ((visptr->shapenum = statptr->shapenum) == -1)
continue; // object has been deleted
if (!*statptr->visspot)
continue; // not visable
if (TransformTile (statptr->tilex,statptr->tiley
,&visptr->viewx,&visptr->viewheight) && statptr->flags & FL_BONUS)
{
GetBonus (statptr);
continue;
}
if (!visptr->viewheight)
continue; // to close to the object
if (visptr &vislist[MAXVISABLE-1]) // don't let it overflow
visptr++;
}
//
// place active objects
//
for (obj = player->next;obj;obj=obj->next)
{
if (!(visptr->shapenum = obj->state->shapenum))
continue; // no shape
spotloc = (obj->tilex 6)+obj->tiley; // optimize: keep in struct?
visspot = &spotvis[0][0]+spotloc;
tilespot = &tilemap[0][0]+spotloc;
//
// could be in any of the nine surrounding tiles
//
if (*visspot
|| ( *(visspot-1) && !*(tilespot-1) )
|| ( *(visspot+1) && !*(tilespot+1) )
|| ( *(visspot-65) && !*(tilespot-65) )
|| ( *(visspot-64) && !*(tilespot-64) )
|| ( *(visspot-63) && !*(tilespot-63) )
|| ( *(visspot+65) && !*(tilespot+65) )
|| ( *(visspot+64) && !*(tilespot+64) )
|| ( *(visspot+63) && !*(tilespot+63) ) )
{
obj->active = true;
TransformActor (obj);
if (!obj->viewheight)
continue; // too close or far away
visptr->viewx = obj->viewx;
visptr->viewheight = obj->viewheight;
if (visptr->shapenum == -1)
visptr->shapenum = obj->temp1; // special shape
if (obj->state->rotate)
visptr->shapenum += CalcRotate (obj);
if (visptr &vislist[MAXVISABLE-1]) // don't let it overflow
visptr++;
obj->flags |= FL_VISABLE;
}
else
obj->flags &= ~FL_VISABLE;
}
//
// draw from back to front
//
numvisable = visptr-&vislist[0];
if (!numvisable)
return; // no visable objects
for (i = 0; inumvisable; i++)
{
least = 32000;
for (visstep=&vislist[0] ; visstep visptr ; visstep++)
{
height = visstep->viewheight;
if (height least)
{
least = height;
farthest = visstep;
}
}
//
// draw farthest
//
ScaleShape(farthest->viewx,farthest->shapenum,farthest->viewheight);
farthest->viewheight = 32000;
}
}
//==========================================================================
/*
==============
=
= DrawPlayerWeapon
=
= Draw the player's hands
=
==============
*/
int weaponscale[NUMWEAPONS] = {SPR_KNIFEREADY,SPR_PISTOLREADY
,SPR_MACHINEGUNREADY,SPR_CHAINREADY};
void DrawPlayerWeapon (void)
{
int shapenum;
#ifndef SPEAR
if (gamestate.victoryflag)
{
if (player->state == &s_deathcam && (TimeCount&32) )
SimpleScaleShape(viewwidth/2,SPR_DEATHCAM,viewheight+1);
return;
}
#endif
if (gamestate.weapon != -1)
{
shapenum = weaponscale[gamestate.weapon]+gamestate.weaponframe;
SimpleScaleShape(viewwidth/2,shapenum,viewheight+1);
}
if (demorecord || demoplayback)
SimpleScaleShape(viewwidth/2,SPR_DEMO,viewheight+1);
}
//==========================================================================
/*
=====================
=
= CalcTics
=
=====================
*/
void CalcTics (void)
{
long newtime,oldtimecount;
//
// calculate tics since last refresh for adaptive timing
//
if (lasttimecount > TimeCount)
TimeCount = lasttimecount; // if the game was paused a LONG time
do
{
newtime = TimeCount;
tics = newtime-lasttimecount;
} while (!tics); // make sure at least one tic passes
lasttimecount = newtime;
#ifdef FILEPROFILE
strcpy (scratch,"\tTics:");
itoa (tics,str,10);
strcat (scratch,str);
strcat (scratch,"\n");
write (profilehandle,scratch,strlen(scratch));
#endif
if (tics>MAXTICS)
{
TimeCount -= (tics-MAXTICS);
tics = MAXTICS;
}
}
//==========================================================================
/*
========================
=
= FixOfs
=
========================
*/
void FixOfs (void)
{
VW_ScreenToScreen (displayofs,bufferofs,viewwidth/8,viewheight);
}
//==========================================================================
/*
====================
=
= WallRefresh
=
====================
*/
void WallRefresh (void)
{
//
// set up variables for this view
//
viewangle = player->angle;
midangle = viewangle*(FINEANGLES/ANGLES);
viewsin = sintable[viewangle];
viewcos = costable[viewangle];
viewx = player->x - FixedByFrac(focallength,viewcos);
viewy = player->y + FixedByFrac(focallength,viewsin);
focaltx = viewx>>TILESHIFT;
focalty = viewy>>TILESHIFT;
viewtx = player->x >> TILESHIFT;
viewty = player->y >> TILESHIFT;
xpartialdown = viewx&(TILEGLOBAL-1);
xpartialup = TILEGLOBAL-xpartialdown;
ypartialdown = viewy&(TILEGLOBAL-1);
ypartialup = TILEGLOBAL-ypartialdown;
lastside = -1; // the first pixel is on a new wall
AsmRefresh ();
ScalePost (); // no more optimization on last post
}
//==========================================================================
/*
========================
=
= ThreeDRefresh
=
========================
*/
void ThreeDRefresh (void)
{
int tracedir;
// this wouldn't need to be done except for my debugger/video wierdness
outportb (SC_INDEX,SC_MAPMASK);
//
// clear out the traced array
//
asm mov ax,ds
asm mov es,ax
asm mov di,OFFSET spotvis
asm xor ax,ax
asm mov cx,2048 // 64*64 / 2
asm rep stosw
bufferofs += screenofs;
//
// follow the walls from there to the right, drawwing as we go
//
VGAClearScreen ();
WallRefresh ();
//
// draw all the scaled images
//
DrawScaleds(); // draw scaled stuff
DrawPlayerWeapon (); // draw player's hands
//
// show screen and time last cycle
//
if (fizzlein)
{
FizzleFade(bufferofs,displayofs+screenofs,viewwidth,viewheight,20,false);
fizzlein = false;
lasttimecount = TimeCount = 0; // don't make a big tic count
}
bufferofs -= screenofs;
displayofs = bufferofs;
asm cli
asm mov cx,[displayofs]
asm mov dx,3d4h // CRTC address register
asm mov al,0ch // start address high register
asm out dx,al
asm inc dx
asm mov al,ch
asm out dx,al // set the high byte
asm sti
bufferofs += SCREENSIZE;
if (bufferofs > PAGE3START)
bufferofs = PAGE1START;
frameon++;
PM_NextFrame();>
}