IDEAL
MODEL MEDIUM,C
; Assembly portion of the User Mgr. This is just John Carmack's table
; driven pseudo-random number generator, and we put it in the User Mgr
; because we couldn't figure out where it should go
;============================================================================
;
; RANDOM ROUTINES
;
;============================================================================
FARDATA
rndindex dw ?
rndtable db 0, 8, 109, 220, 222, 241, 149, 107, 75, 248, 254, 140, 16, 66
db 74, 21, 211, 47, 80, 242, 154, 27, 205, 128, 161, 89, 77, 36
db 95, 110, 85, 48, 212, 140, 211, 249, 22, 79, 200, 50, 28, 188
db 52, 140, 202, 120, 68, 145, 62, 70, 184, 190, 91, 197, 152, 224
db 149, 104, 25, 178, 252, 182, 202, 182, 141, 197, 4, 81, 181, 242
db 145, 42, 39, 227, 156, 198, 225, 193, 219, 93, 122, 175, 249, 0
db 175, 143, 70, 239, 46, 246, 163, 53, 163, 109, 168, 135, 2, 235
db 25, 92, 20, 145, 138, 77, 69, 166, 78, 176, 173, 212, 166, 113
db 94, 161, 41, 50, 239, 49, 111, 164, 70, 60, 2, 37, 171, 75
db 136, 156, 11, 56, 42, 146, 138, 229, 73, 146, 77, 61, 98, 196
db 135, 106, 63, 197, 195, 86, 96, 203, 113, 101, 170, 247, 181, 113
db 80, 250, 108, 7, 255, 237, 129, 226, 79, 107, 112, 166, 103, 241
db 24, 223, 239, 120, 198, 58, 60, 82, 128, 3, 184, 66, 143, 224
db 145, 224, 81, 206, 163, 45, 63, 90, 168, 114, 59, 33, 159, 95
db 28, 139, 123, 98, 125, 196, 15, 70, 194, 253, 54, 14, 109, 226
db 71, 17, 161, 93, 186, 87, 244, 138, 20, 52, 123, 251, 26, 36
db 17, 46, 52, 231, 232, 76, 31, 221, 84, 37, 216, 165, 212, 106
db 197, 242, 98, 43, 39, 175, 254, 145, 190, 84, 118, 222, 187, 136
db 120, 163, 236, 249
PUBLIC rndtable
CODESEG
Lastrnd dw ?
;=================================================
;
; void US_InitrndT (boolean randomize)
; Init table based rnd generator
; if randomize is false, the counter is set to 0
;
;=================================================
PROC US_InitrndT randomize:word
uses si,di
public US_InitrndT
mov ax,SEG rndtable
mov es,ax
mov ax,[randomize]
or ax,ax
jne @@timeit ;if randomize is true, really random
mov dx,0 ;set to a definite value
jmp @@setit
@@timeit:
mov ah,2ch
int 21h ;GetSystemTime
and dx,0ffh
@@setit:
mov [es:rndindex],dx
ret
ENDP
;=================================================
;
; int US_rndT (void)
; Return a random # between 0-255
; Exit : AX = value
;
;=================================================
PROC US_rndT
public US_rndT
mov ax,SEG rndtable
mov es,ax
mov bx,[es:rndindex]
inc bx
and bx,0ffh
mov [es:rndindex],bx
mov al,[es:rndtable+BX]
xor ah,ah
ret
ENDP
END
// ID_VH.C
#include "ID_HEADS.H"
#define SCREENwidth 80
#define CHARwidth 2
#define TILEwidth 4
#define GRPLANES 4
#define bytePIXELS 4
#define SCREENXMASK (~3)
#define SCREENXPLUS (3)
#define SCREENXDIV (4)
#define VIEWwidth 80
#define PIXTOBLOCK 4 // 16 pixels to an update block
#define UNCACHEGRCHUNK(chunk) {MM_FreePtr(&grsegs[chunk]);grneeded[chunk]&=~ca_levelbit;}
byte update[UPDATEHIGH][UPDATEWIDE];
//==========================================================================
pictabletype _seg *pictable;
int px,py;
byte fontcolor,backcolor;
int fontnumber;
int bufferwidth,bufferheight;
//==========================================================================
void VWL_UpdateScreenBlocks (void);
//==========================================================================
void VW_DrawPropstring (char far *string)
{
fontstruct far *font;
int width,step,height,i;
byte far *source, far *dest, far *origdest;
byte ch,mask;
font = (fontstruct far *)grsegs[STARTFONT+fontnumber];
height = bufferheight = font->height;
dest = origdest = MK_FP(SCREENSEG,bufferofs+ylookup[py]+(px>>2));
mask = 1 (px&3);
while ((ch = *string++)!=0)
{
width = step = font->width[ch];
source = ((byte far *)font)+font->location[ch];
while (width--)
{
VGAMAPMASK(mask);
asm mov ah,[byte PTR fontcolor]
asm mov bx,[step]
asm mov cx,[height]
asm mov dx,[linewidth]
asm lds si,[source]
asm les di,[dest]
vertloop:
asm mov al,[si]
asm or al,al
asm je next
asm mov [es:di],ah // draw color
next:
asm add si,bx
asm add di,dx
asm loop vertloop
asm mov ax,ss
asm mov ds,ax
source++;
px++;
mask = 1;
if (mask == 16)
{
mask = 1;
dest++;
}
}
}
bufferheight = height;
bufferwidth = ((dest+1)-origdest)*4;
}
void VW_DrawColorPropstring (char far *string)
{
fontstruct far *font;
int width,step,height,i;
byte far *source, far *dest, far *origdest;
byte ch,mask;
font = (fontstruct far *)grsegs[STARTFONT+fontnumber];
height = bufferheight = font->height;
dest = origdest = MK_FP(SCREENSEG,bufferofs+ylookup[py]+(px>>2));
mask = 1 (px&3);
while ((ch = *string++)!=0)
{
width = step = font->width[ch];
source = ((byte far *)font)+font->location[ch];
while (width--)
{
VGAMAPMASK(mask);
asm mov ah,[byte PTR fontcolor]
asm mov bx,[step]
asm mov cx,[height]
asm mov dx,[linewidth]
asm lds si,[source]
asm les di,[dest]
vertloop:
asm mov al,[si]
asm or al,al
asm je next
asm mov [es:di],ah // draw color
next:
asm add si,bx
asm add di,dx
asm rcr cx,1 // inc font color
asm jc cont
asm inc ah
cont:
asm rcl cx,1
asm loop vertloop
asm mov ax,ss
asm mov ds,ax
source++;
px++;
mask = 1;
if (mask == 16)
{
mask = 1;
dest++;
}
}
}
bufferheight = height;
bufferwidth = ((dest+1)-origdest)*4;
}
//==========================================================================
/*
=================
=
= VL_MungePic
=
=================
*/
void VL_MungePic (byte far *source, unsigned width, unsigned height)
{
unsigned x,y,plane,size,pwidth;
byte _seg *temp, far *dest, far *srcline;
size = width*height;
if (width&3)
MS_Quit ("VL_MungePic: Not divisable by 4!");
//
// copy the pic to a temp buffer
//
MM_GetPtr (&(memptr)temp,size);
_fmemcpy (temp,source,size);
//
// munge it back into the original buffer
//
dest = source;
pwidth = width/4;
for (plane=0;plane 4;plane++)
{
srcline = temp;
for (y=0;y height;y++)
{
for (x=0;x pwidth;x++)
*dest++ = *(srcline+x*4+plane);
srcline+=width;
}
}
MM_FreePtr (&(memptr)temp);
}
void VWL_Measurestring (char far *string, word *width, word *height
, fontstruct _seg *font)
{
*height = font->height;
for (*width = 0;*string;string++)
*width += font->width[*((byte far *)string)]; // proportional width
}
void VW_MeasurePropstring (char far *string, word *width, word *height)
{
VWL_Measurestring(string,width,height,(fontstruct _seg *)grsegs[STARTFONT+fontnumber]);
}
void VW_MeasureMPropstring (char far *string, word *width, word *height)
{
VWL_Measurestring(string,width,height,(fontstruct _seg *)grsegs[STARTFONTM+fontnumber]);
}
/*
=============================================================================
Double buffer management routines
=============================================================================
*/
/*
=======================
=
= VW_MarkUpdateBlock
=
= Takes a pixel bounded block and marks the tiles in bufferblocks
= Returns 0 if the entire block is off the buffer screen
=
=======================
*/
int VW_MarkUpdateBlock (int x1, int y1, int x2, int y2)
{
int x,y,xt1,yt1,xt2,yt2,nextline;
byte *mark;
xt1 = x1>>PIXTOBLOCK;
yt1 = y1>>PIXTOBLOCK;
xt2 = x2>>PIXTOBLOCK;
yt2 = y2>>PIXTOBLOCK;
if (xt1 0)
xt1=0;
else if (xt1>=UPDATEWIDE)
return 0;
if (yt1 0)
yt1=0;
else if (yt1>UPDATEHIGH)
return 0;
if (xt2 0)
return 0;
else if (xt2>=UPDATEWIDE)
xt2 = UPDATEWIDE-1;
if (yt2 0)
return 0;
else if (yt2>=UPDATEHIGH)
yt2 = UPDATEHIGH-1;
mark = updateptr + uwidthtable[yt1] + xt1;
nextline = UPDATEWIDE - (xt2-xt1) - 1;
for (y=yt1;y =yt2;y++)
{
for (x=xt1;x =xt2;x++)
*mark++ = 1; // this tile will need to be updated
mark += nextline;
}
return 1;
}
void VWB_DrawTile8 (int x, int y, int tile)
{
if (VW_MarkUpdateBlock (x,y,x+7,y+7))
LatchDrawChar(x,y,tile);
}
void VWB_DrawTile8M (int x, int y, int tile)
{
if (VW_MarkUpdateBlock (x,y,x+7,y+7))
VL_MemToScreen (((byte far *)grsegs[STARTTILE8M])+tile*64,8,8,x,y);
}
void VWB_DrawPic (int x, int y, int chunknum)
{
int picnum = chunknum - STARTPICS;
unsigned width,height;
x &= ~7;
width = pictable[picnum].width;
height = pictable[picnum].height;
if (VW_MarkUpdateBlock (x,y,x+width-1,y+height-1))
VL_MemToScreen (grsegs[chunknum],width,height,x,y);
}
void VWB_DrawPropstring (char far *string)
{
int x;
x=px;
VW_DrawPropstring (string);
VW_MarkUpdateBlock(x,py,px-1,py+bufferheight-1);
}
void VWB_Bar (int x, int y, int width, int height, int color)
{
if (VW_MarkUpdateBlock (x,y,x+width,y+height-1) )
VW_Bar (x,y,width,height,color);
}
void VWB_Plot (int x, int y, int color)
{
if (VW_MarkUpdateBlock (x,y,x,y))
VW_Plot(x,y,color);
}
void VWB_Hlin (int x1, int x2, int y, int color)
{
if (VW_MarkUpdateBlock (x1,y,x2,y))
VW_Hlin(x1,x2,y,color);
}
void VWB_Vlin (int y1, int y2, int x, int color)
{
if (VW_MarkUpdateBlock (x,y1,x,y2))
VW_Vlin(y1,y2,x,color);
}
void VW_UpdateScreen (void)
{
VH_UpdateScreen ();
}
/*
=============================================================================
WOLFENSTEIN STUFF
=============================================================================
*/
/*
=====================
=
= LatchDrawPic
=
=====================
*/
void LatchDrawPic (unsigned x, unsigned y, unsigned picnum)
{
unsigned wide, height, source;
wide = pictable[picnum-STARTPICS].width;
height = pictable[picnum-STARTPICS].height;
source = latchpics[2+picnum-LATCHPICS_LUMP_START];
VL_LatchToScreen (source,wide/4,height,x*8,y);
}
//==========================================================================
/*
===================
=
= LoadLatchMem
=
===================
*/
void LoadLatchMem (void)
{
int i,j,p,m,width,height,start,end;
byte far *src;
unsigned destoff;
//
// tile 8s
//
latchpics[0] = freelatch;
CA_CacheGrChunk (STARTTILE8);
src = (byte _seg *)grsegs[STARTTILE8];
destoff = freelatch;
for (i=0;i NUMTILE8;i++)
{
VL_MemToLatch (src,8,8,destoff);
src += 64;
destoff +=16;
}
UNCACHEGRCHUNK (STARTTILE8);
#if 0 // ran out of latch space!
//
// tile 16s
//
src = (byte _seg *)grsegs[STARTTILE16];
latchpics[1] = destoff;
for (i=0;i NUMTILE16;i++)
{
CA_CacheGrChunk (STARTTILE16+i);
src = (byte _seg *)grsegs[STARTTILE16+i];
VL_MemToLatch (src,16,16,destoff);
destoff+=64;
if (src)
UNCACHEGRCHUNK (STARTTILE16+i);
}
#endif
//
// pics
//
start = LATCHPICS_LUMP_START;
end = LATCHPICS_LUMP_END;
for (i=start;i =end;i++)
{
latchpics[2+i-start] = destoff;
CA_CacheGrChunk (i);
width = pictable[i-STARTPICS].width;
height = pictable[i-STARTPICS].height;
VL_MemToLatch (grsegs[i],width,height,destoff);
destoff += width/4 *height;
UNCACHEGRCHUNK(i);
}
EGAMAPMASK(15);
}
//==========================================================================
/*
===================
=
= FizzleFade
=
= returns true if aborted
=
===================
*/
extern ControlInfo c;
boolean FizzleFade (unsigned source, unsigned dest,
unsigned width,unsigned height, unsigned frames, boolean abortable)
{
int pixperframe;
unsigned drawofs,pagedelta;
byte mask,maskb[8] = {1,2,4,8};
unsigned x,y,p,frame;
long rndval;
pagedelta = dest-source;
rndval = 1;
y = 0;
pixperframe = 64000/frames;
IN_StartAck ();
TimeCount=frame=0;
do // while (1)
{
if (abortable && IN_CheckAck () )
return true;
asm mov es,[screenseg]
for (p=0;p pixperframe;p++)
{
//
// seperate random value into x/y pair
//
asm mov ax,[WORD PTR rndval]
asm mov dx,[WORD PTR rndval+2]
asm mov bx,ax
asm dec bl
asm mov [byte PTR y],bl // low 8 bits - 1 = y xoordinate
asm mov bx,ax
asm mov cx,dx
asm mov [byte PTR x],ah // next 9 bits = x xoordinate
asm mov [byte PTR x+1],dl
//
// advance to next random element
//
asm shr dx,1
asm rcr ax,1
asm jnc noxor
asm xor dx,0x0001
asm xor ax,0x2000
noxor:
asm mov [WORD PTR rndval],ax
asm mov [WORD PTR rndval+2],dx
if (x>width || y>height)
continue;
drawofs = source+ylookup[y] + (x>>2);
//
// copy one pixel
//
mask = x&3;
VGAREADMAP(mask);
mask = maskb[mask];
VGAMAPMASK(mask);
asm mov di,[drawofs]
asm mov al,[es:di]
asm add di,[pagedelta]
asm mov [es:di],al
if (rndval == 1) // entire sequence has been completed
return false;
}
frame++;
while (TimeCount frame) // don't go too fast
;
} while (1);
}
//
// ID Engine
// ID_US_1.c - User Manager - General routines
// v1.1d1
// By Jason Blochowiak
// Hacked up for Catacomb 3D
//
//
// This module handles dealing with user input & feedback
//
// Depends on: Input Mgr, View Mgr, some variables from the Sound, Caching,
// and Refresh Mgrs, Memory Mgr for background save/restore
//
// Globals:
// ingame - Flag set by game indicating if a game is in progress
// abortgame - Flag set if the current game should be aborted (if a load
// game fails)
// loadedgame - Flag set if a game was loaded
// abortprogram - Normally nil, this points to a terminal error message
// if the program needs to abort
// restartgame - Normally set to gd_Continue, this is set to one of the
// difficulty levels if a new game should be started
// PrintX, PrintY - Where the User Mgr will print (global coords)
// windowX,windowY,windowW,windowH - The dimensions of the current
// window
//
#include "ID_HEADS.H"
#pragma hdrstop
#pragma warn -pia
// Global variables
char *abortprogram;
boolean NoWait;
word PrintX,PrintY;
word windowX,windowY,windowW,windowH;
// Internal variables
#define ConfigVersion 1
static char *Parmstrings[] = {"TEDLEVEL","NOWAIT"},
*Parmstrings2[] = {"COMP","NOCOMP"};
static boolean US_Started;
boolean Button0,Button1,
CursorBad;
int CursorX,CursorY;
void (*USL_Measurestring)(char far *,word *,word *) = VW_MeasurePropstring,
(*USL_Drawstring)(char far *) = VWB_DrawPropstring;
SaveGame Games[MaxSaveGames];
HighScore Scores[MaxScores] =
{
{"id software-'92",10000,1},
{"Adrian Carmack",10000,1},
{"John Carmack",10000,1},
{"Kevin Cloud",10000,1},
{"Tom Hall",10000,1},
{"John Romero",10000,1},
{"Jay Wilbur",10000,1},
};
// Internal routines
// Public routines
///////////////////////////////////////////////////////////////////////////
//
// USL_HardError() - Handles the Abort/Retry/Fail sort of errors passed
// from DOS.
//
///////////////////////////////////////////////////////////////////////////
#pragma warn -par
#pragma warn -rch
int
USL_HardError(word errval,int ax,int bp,int si)
{
#define IGNORE 0
#define RETRY 1
#define ABORT 2
extern void ShutdownId(void);
static char buf[32];
static windowRec wr;
int di;
char c,*s,*t;
di = _DI;
if (ax 0)
s = "Device Error";
else
{
if ((di & 0x00ff) == 0)
s = "Drive ~ is Write Protected";
else
s = "Error on Drive ~";
for (t = buf;*s;s++,t++) // Can't use sprintf()
if ((*t = *s) == '~')
*t = (ax & 0x00ff) + 'A';
*t = '\0';
s = buf;
}
c = peekb(0x40,0x49); // Get the current screen mode
if ((c 4) || (c == 7))
goto oh_kill_me;
// DEBUG - handle screen cleanup
US_Savewindow(&wr);
US_Centerwindow(30,3);
US_CPrint(s);
US_CPrint("(R)etry or (A)bort?");
VW_UpdateScreen();
IN_ClearKeysDown();
asm sti // Let the keyboard interrupts come through
while (true)
{
switch (IN_WaitForASCII())
{
case key_Escape:
case 'a':
case 'A':
goto oh_kill_me;
break;
case key_Return:
case key_Space:
case 'r':
case 'R':
US_Clearwindow();
VW_UpdateScreen();
US_Restorewindow(&wr);
return(RETRY);
break;
}
}
oh_kill_me:
abortprogram = s;
ShutdownId();
fprintf(stderr,"Terminal Error: %s\n",s);
if (tedlevel)
fprintf(stderr,"You launched from TED. I suggest that you reboot...\n");
return(ABORT);
#undef IGNORE
#undef RETRY
#undef ABORT
}
#pragma warn +par
#pragma warn +rch
///////////////////////////////////////////////////////////////////////////
//
// US_Startup() - Starts the User Mgr
//
///////////////////////////////////////////////////////////////////////////
void
US_Startup(void)
{
int i,n;
if (US_Started)
return;
harderr(USL_HardError); // Install the fatal error handler
US_InitrndT(true); // Initialize the random number generator
for (i = 1;i _argc;i++)
{
switch (US_CheckParm(_argv[i],Parmstrings2))
{
case 0:
compatability = true;
break;
case 1:
compatability = false;
break;
}
}
// Check for TED launching here
for (i = 1;i _argc;i++)
{
n = US_CheckParm(_argv[i],Parmstrings);
switch(n)
{
case 0:
tedlevelnum = atoi(_argv[i + 1]);
if (tedlevelnum >= 0)
tedlevel = true;
break;
case 1:
NoWait = true;
break;
}
}
US_Started = true;
}
///////////////////////////////////////////////////////////////////////////
//
// US_Shutdown() - Shuts down the User Mgr
//
///////////////////////////////////////////////////////////////////////////
void
US_Shutdown(void)
{
if (!US_Started)
return;
US_Started = false;
}
///////////////////////////////////////////////////////////////////////////
//
// US_CheckParm() - checks to see if a string matches one of a set of
// strings. The check is case insensitive. The routine returns the
// index of the string that matched, or -1 if no matches were found
//
///////////////////////////////////////////////////////////////////////////
int
US_CheckParm(char *parm,char **strings)
{
char cp,cs,
*p,*s;
int i;
while (!isalpha(*parm)) // Skip non-alphas
parm++;
for (i = 0;*strings && **strings;i++)
{
for (s = *strings++,p = parm,cs = cp = 0;cs == cp;)
{
cs = *s++;
if (!cs)
return(i);
cp = *p++;
if (isupper(cs))
cs = tolower(cs);
if (isupper(cp))
cp = tolower(cp);
}
}
return(-1);
}
// window/Printing routines
///////////////////////////////////////////////////////////////////////////
//
// US_SetPrintRoutines() - Sets the routines used to measure and print
// from within the User Mgr. Primarily provided to allow switching
// between masked and non-masked fonts
//
///////////////////////////////////////////////////////////////////////////
void
US_SetPrintRoutines(void (*measure)(char far *,word *,word *),void (*print)(char far *))
{
USL_Measurestring = measure;
USL_Drawstring = print;
}
///////////////////////////////////////////////////////////////////////////
//
// US_Print() - Prints a string in the current window. Newlines are
// supported.
//
///////////////////////////////////////////////////////////////////////////
void
US_Print(char far *s)
{
char c,far *se;
word w,h;
while (*s)
{
se = s;
while ((c = *se) && (c != '\n'))
se++;
*se = '\0';
USL_Measurestring(s,&w,&h);
px = PrintX;
py = PrintY;
USL_Drawstring(s);
s = se;
if (c)
{
*se = c;
s++;
PrintX = windowX;
PrintY += h;
}
else
PrintX += w;
}
}
///////////////////////////////////////////////////////////////////////////
//
// US_Printunsigned() - Prints an unsigned long
//
///////////////////////////////////////////////////////////////////////////
void
US_Printunsigned(longword n)
{
char buffer[32];
US_Print(ultoa(n,buffer,10));
}
///////////////////////////////////////////////////////////////////////////
//
// US_PrintSigned() - Prints a signed long
//
///////////////////////////////////////////////////////////////////////////
void
US_PrintSigned(long n)
{
char buffer[32];
US_Print(ltoa(n,buffer,10));
}
///////////////////////////////////////////////////////////////////////////
//
// USL_PrintInCenter() - Prints a string in the center of the given rect
//
///////////////////////////////////////////////////////////////////////////
void
USL_PrintInCenter(char far *s,Rect r)
{
word w,h,
rw,rh;
USL_Measurestring(s,&w,&h);
rw = r.lr.x - r.ul.x;
rh = r.lr.y - r.ul.y;
px = r.ul.x + ((rw - w) / 2);
py = r.ul.y + ((rh - h) / 2);
USL_Drawstring(s);
}
///////////////////////////////////////////////////////////////////////////
//
// US_PrintCentered() - Prints a string centered in the current window.
//
///////////////////////////////////////////////////////////////////////////
void
US_PrintCentered(char far *s)
{
Rect r;
r.ul.x = windowX;
r.ul.y = windowY;
r.lr.x = r.ul.x + windowW;
r.lr.y = r.ul.y + windowH;
USL_PrintInCenter(s,r);
}
///////////////////////////////////////////////////////////////////////////
//
// US_CPrintLine() - Prints a string centered on the current line and
// advances to the next line. Newlines are not supported.
//
///////////////////////////////////////////////////////////////////////////
void
US_CPrintLine(char far *s)
{
word w,h;
USL_Measurestring(s,&w,&h);
if (w > windowW)
Quit("US_CPrintLine() - string exceeds width");
px = windowX + ((windowW - w) / 2);
py = PrintY;
USL_Drawstring(s);
PrintY += h;
}
///////////////////////////////////////////////////////////////////////////
//
// US_CPrint() - Prints a string in the current window. Newlines are
// supported.
//
///////////////////////////////////////////////////////////////////////////
void
US_CPrint(char far *s)
{
char c,far *se;
while (*s)
{
se = s;
while ((c = *se) && (c != '\n'))
se++;
*se = '\0';
US_CPrintLine(s);
s = se;
if (c)
{
*se = c;
s++;
}
}
}
///////////////////////////////////////////////////////////////////////////
//
// US_Clearwindow() - Clears the current window to white and homes the
// cursor
//
///////////////////////////////////////////////////////////////////////////
void
US_Clearwindow(void)
{
VWB_Bar(windowX,windowY,windowW,windowH,WHITE);
PrintX = windowX;
PrintY = windowY;
}
///////////////////////////////////////////////////////////////////////////
//
// US_Drawwindow() - Draws a frame and sets the current window parms
//
///////////////////////////////////////////////////////////////////////////
void
US_Drawwindow(word x,word y,word w,word h)
{
word i,
sx,sy,sw,sh;
windowX = x * 8;
windowY = y * 8;
windowW = w * 8;
windowH = h * 8;
PrintX = windowX;
PrintY = windowY;
sx = (x - 1) * 8;
sy = (y - 1) * 8;
sw = (w + 1) * 8;
sh = (h + 1) * 8;
US_Clearwindow();
VWB_DrawTile8(sx,sy,0),VWB_DrawTile8(sx,sy + sh,5);
for (i = sx + 8;i = sx + sw - 8;i += 8)
VWB_DrawTile8(i,sy,1),VWB_DrawTile8(i,sy + sh,6);
VWB_DrawTile8(i,sy,2),VWB_DrawTile8(i,sy + sh,7);
for (i = sy + 8;i = sy + sh - 8;i += 8)
VWB_DrawTile8(sx,i,3),VWB_DrawTile8(sx + sw,i,4);
}
///////////////////////////////////////////////////////////////////////////
//
// US_Centerwindow() - Generates a window of a given width & height in the
// middle of the screen
//
///////////////////////////////////////////////////////////////////////////
void
US_Centerwindow(word w,word h)
{
US_Drawwindow(((MaxX / 8) - w) / 2,((MaxY / 8) - h) / 2,w,h);
}
///////////////////////////////////////////////////////////////////////////
//
// US_Savewindow() - Saves the current window parms into a record for
// later restoration
//
///////////////////////////////////////////////////////////////////////////
void
US_Savewindow(windowRec *win)
{
win->x = windowX;
win->y = windowY;
win->w = windowW;
win->h = windowH;
win->px = PrintX;
win->py = PrintY;
}
///////////////////////////////////////////////////////////////////////////
//
// US_Restorewindow() - Sets the current window parms to those held in the
// record
//
///////////////////////////////////////////////////////////////////////////
void
US_Restorewindow(windowRec *win)
{
windowX = win->x;
windowY = win->y;
windowW = win->w;
windowH = win->h;
PrintX = win->px;
PrintY = win->py;
}
// Input routines
///////////////////////////////////////////////////////////////////////////
//
// USL_XORICursor() - XORs the I-bar text cursor. Used by US_LineInput()
//
///////////////////////////////////////////////////////////////////////////
static void
USL_XORICursor(int x,int y,char *s,word cursor)
{
static boolean status; // VGA doesn't XOR...
char buf[Maxstring];
int temp;
word w,h;
strcpy(buf,s);
buf[cursor] = '\0';
USL_Measurestring(buf,&w,&h);
px = x + w - 1;
py = y;
if (status^=1)
USL_Drawstring("\x80");
else
{
temp = fontcolor;
fontcolor = backcolor;
USL_Drawstring("\x80");
fontcolor = temp;
}
}
///////////////////////////////////////////////////////////////////////////
//
// US_LineInput() - Gets a line of user input at (x,y), the string defaults
// to whatever is pointed at by def. Input is restricted to maxchars
// chars or maxwidth pixels wide. if the user hits escape (and escok is
// true), nothing is copied into buf, and false is returned. if the
// user hits return, the current string is copied into buf, and true is
// returned
//
///////////////////////////////////////////////////////////////////////////
boolean
US_LineInput(int x,int y,char *buf,char *def,boolean escok,
int maxchars,int maxwidth)
{
boolean redraw,
cursorvis,cursormoved,
done,result;
ScanCode sc;
char c,
s[Maxstring],olds[Maxstring];
word i,
cursor,
w,h,
len,temp;
longword lasttime;
if (def)
strcpy(s,def);
else
*s = '\0';
*olds = '\0';
cursor = strlen(s);
cursormoved = redraw = true;
cursorvis = done = false;
lasttime = TimeCount;
LastASCII = key_None;
LastScan = sc_None;
while (!done)
{
if (cursorvis)
USL_XORICursor(x,y,s,cursor);
asm pushf
asm cli
sc = LastScan;
LastScan = sc_None;
c = LastASCII;
LastASCII = key_None;
asm popf
switch (sc)
{
case sc_LeftArrow:
if (cursor)
cursor--;
c = key_None;
cursormoved = true;
break;
case sc_RightArrow:
if (s[cursor])
cursor++;
c = key_None;
cursormoved = true;
break;
case sc_Home:
cursor = 0;
c = key_None;
cursormoved = true;
break;
case sc_End:
cursor = strlen(s);
c = key_None;
cursormoved = true;
break;
case sc_Return:
strcpy(buf,s);
done = true;
result = true;
c = key_None;
break;
case sc_Escape:
if (escok)
{
done = true;
result = false;
}
c = key_None;
break;
case sc_BackSpace:
if (cursor)
{
strcpy(s + cursor - 1,s + cursor);
cursor--;
redraw = true;
}
c = key_None;
cursormoved = true;
break;
case sc_Delete:
if (s[cursor])
{
strcpy(s + cursor,s + cursor + 1);
redraw = true;
}
c = key_None;
cursormoved = true;
break;
case 0x4c: // Keypad 5
case sc_UpArrow:
case sc_DownArrow:
case sc_PgUp:
case sc_PgDn:
case sc_Insert:
c = key_None;
break;
}
if (c)
{
len = strlen(s);
USL_Measurestring(s,&w,&h);
if
(
isprint(c)
&& (len Maxstring - 1)
&& ((!maxchars) || (len maxchars))
&& ((!maxwidth) || (w maxwidth))
)
{
for (i = len + 1;i > cursor;i--)
s[i] = s[i - 1];
s[cursor++] = c;
redraw = true;
}
}
if (redraw)
{
px = x;
py = y;
temp = fontcolor;
fontcolor = backcolor;
USL_Drawstring(olds);
fontcolor = temp;
strcpy(olds,s);
px = x;
py = y;
USL_Drawstring(s);
redraw = false;
}
if (cursormoved)
{
cursorvis = false;
lasttime = TimeCount - TickBase;
cursormoved = false;
}
if (TimeCount - lasttime > TickBase / 2)
{
lasttime = TimeCount;
cursorvis ^= true;
}
if (cursorvis)
USL_XORICursor(x,y,s,cursor);
VW_UpdateScreen();
}
if (cursorvis)
USL_XORICursor(x,y,s,cursor);
if (!result)
{
px = x;
py = y;
USL_Drawstring(olds);
}
VW_UpdateScreen();
IN_ClearKeysDown();
return(result);
}