3692 lines
90 KiB
C
3692 lines
90 KiB
C
/* Catacomb 3-D Source Code
|
|
* Copyright (C) 1993-2014 Flat Rock Software
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
//
|
|
// ID Engine
|
|
// ID_US.c - User Manager
|
|
// v1.0d1
|
|
// By Jason Blochowiak
|
|
//
|
|
|
|
//
|
|
// 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
|
|
//
|
|
|
|
// DEBUG - handle LPT3 for Sound Source
|
|
|
|
#include "ID_HEADS.H"
|
|
|
|
#define CTL_M_ADLIBUPPIC CTL_S_ADLIBUPPIC
|
|
#define CTL_M_ADLIBDNPIC CTL_S_ADLIBDNPIC
|
|
|
|
#pragma hdrstop
|
|
|
|
#pragma warn -pia
|
|
|
|
#define MaxX 320
|
|
#define MaxY 200
|
|
|
|
#define MaxHelpLines 500
|
|
|
|
#define MaxHighName 57
|
|
#define MaxScores 10
|
|
typedef struct
|
|
{
|
|
char name[MaxHighName + 1];
|
|
long score;
|
|
word completed;
|
|
} HighScore;
|
|
|
|
#define MaxGameName 32
|
|
#define MaxSaveGames 7
|
|
typedef struct
|
|
{
|
|
char signature[4];
|
|
boolean present;
|
|
char name[MaxGameName + 1];
|
|
} SaveGame;
|
|
|
|
// Hack import for TED launch support
|
|
extern boolean tedlevel;
|
|
extern word tedlevelnum;
|
|
extern void TEDDeath(void);
|
|
static char *ParmStrings[] = {"TEDLEVEL","NOWAIT",""};
|
|
|
|
|
|
// Global variables
|
|
boolean ingame,abortgame,loadedgame;
|
|
char *abortprogram;
|
|
GameDiff restartgame = gd_Continue;
|
|
word PrintX,PrintY;
|
|
word WindowX,WindowY,WindowW,WindowH;
|
|
|
|
// Internal variables
|
|
static boolean US_Started;
|
|
static boolean GameIsDirty,
|
|
HighScoresDirty,
|
|
QuitToDos,
|
|
ResumeGame,
|
|
NoWait;
|
|
|
|
static memptr LineOffsets;
|
|
|
|
static boolean Button0,Button1,
|
|
CursorBad;
|
|
static int CursorX,CursorY;
|
|
|
|
static void (*USL_MeasureString)(char far *,word *,word *) = VW_MeasurePropString,
|
|
(*USL_DrawString)(char far *) = VWB_DrawPropString;
|
|
|
|
static boolean (*USL_SaveGame)(int),(*USL_LoadGame)(int);
|
|
static void (*USL_ResetGame)(void);
|
|
static SaveGame Games[MaxSaveGames];
|
|
static HighScore Scores[MaxScores] =
|
|
{
|
|
{"Sir Lancelot",500},
|
|
{"",0},
|
|
{"",0},
|
|
{"",0},
|
|
{"",0},
|
|
{"",0},
|
|
{"",0},
|
|
{"",0},
|
|
{"",0},
|
|
{"",0}
|
|
};
|
|
|
|
// 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;
|
|
static boolean oldleavedriveon;
|
|
int di;
|
|
char c,*s,*t;
|
|
|
|
|
|
di = _DI;
|
|
|
|
oldleavedriveon = LeaveDriveOn;
|
|
LeaveDriveOn = false;
|
|
|
|
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);
|
|
LeaveDriveOn = oldleavedriveon;
|
|
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
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_GiveSaveName() - Returns a pointer to a static buffer that contains
|
|
// the filename to use for the specified save game
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static char *
|
|
USL_GiveSaveName(word game)
|
|
{
|
|
static char filename[32];
|
|
char *s,*t;
|
|
|
|
for (s = "SAVEGM",t = filename;*s;)
|
|
*t++ = *s++;
|
|
*t++ = game + '0';
|
|
for (s = "."EXTENSION;*s;)
|
|
*t++ = *s++;
|
|
*t = '\0';
|
|
|
|
return(filename);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// US_SetLoadSaveHooks() - Sets the routines that the User Mgr calls after
|
|
// reading or writing the save game headers
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
void
|
|
US_SetLoadSaveHooks(boolean (*load)(int),boolean (*save)(int),void (*reset)(void))
|
|
{
|
|
USL_LoadGame = load;
|
|
USL_SaveGame = save;
|
|
USL_ResetGame = reset;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_ReadConfig() - Reads the configuration file, if present, and sets
|
|
// things up accordingly. If it's not present, uses defaults. This file
|
|
// includes the high scores.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static void
|
|
USL_ReadConfig(void)
|
|
{
|
|
boolean gotit;
|
|
int file;
|
|
SDMode sd;
|
|
SMMode sm;
|
|
ControlType ctl;
|
|
|
|
if ((file = open("CONFIG."EXTENSION,O_BINARY | O_RDONLY)) != -1)
|
|
{
|
|
read(file,Scores,sizeof(HighScore) * MaxScores);
|
|
read(file,&sd,sizeof(sd));
|
|
read(file,&sm,sizeof(sm));
|
|
read(file,&ctl,sizeof(ctl));
|
|
read(file,&(KbdDefs[0]),sizeof(KbdDefs[0]));
|
|
close(file);
|
|
|
|
HighScoresDirty = false;
|
|
gotit = true;
|
|
}
|
|
else
|
|
{
|
|
sd = sdm_Off;
|
|
sm = smm_Off;
|
|
ctl = ctrl_Keyboard;
|
|
|
|
gotit = false;
|
|
HighScoresDirty = true;
|
|
}
|
|
|
|
SD_Default(gotit,sd,sm);
|
|
IN_Default(gotit,ctl);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_WriteConfig() - Writes out the current configuration, including the
|
|
// high scores.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static void
|
|
USL_WriteConfig(void)
|
|
{
|
|
int file;
|
|
|
|
file = open("CONFIG."EXTENSION,O_CREAT | O_BINARY | O_WRONLY,
|
|
S_IREAD | S_IWRITE | S_IFREG);
|
|
if (file != -1)
|
|
{
|
|
write(file,Scores,sizeof(HighScore) * MaxScores);
|
|
write(file,&SoundMode,sizeof(SoundMode));
|
|
write(file,&MusicMode,sizeof(MusicMode));
|
|
write(file,&(Controls[0]),sizeof(Controls[0]));
|
|
write(file,&(KbdDefs[0]),sizeof(KbdDefs[0]));
|
|
close(file);
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_CheckSavedGames() - Checks to see which saved games are present
|
|
// & valid
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static void
|
|
USL_CheckSavedGames(void)
|
|
{
|
|
boolean ok;
|
|
char *filename;
|
|
word i;
|
|
int file;
|
|
SaveGame *game;
|
|
|
|
USL_SaveGame = 0;
|
|
USL_LoadGame = 0;
|
|
|
|
for (i = 0,game = Games;i < MaxSaveGames;i++,game++)
|
|
{
|
|
filename = USL_GiveSaveName(i);
|
|
ok = false;
|
|
if ((file = open(filename,O_BINARY | O_RDONLY)) != -1)
|
|
{
|
|
if
|
|
(
|
|
(read(file,game,sizeof(*game)) == sizeof(*game))
|
|
&& (!strcmp(game->signature,EXTENSION))
|
|
)
|
|
ok = true;
|
|
|
|
close(file);
|
|
}
|
|
|
|
if (ok)
|
|
game->present = true;
|
|
else
|
|
{
|
|
strcpy(game->signature,EXTENSION);
|
|
game->present = false;
|
|
strcpy(game->name,"Empty");
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// US_Startup() - Starts the User Mgr
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
void
|
|
US_Startup(void)
|
|
{
|
|
if (US_Started)
|
|
return;
|
|
|
|
harderr(USL_HardError); // Install the fatal error handler
|
|
|
|
US_InitRndT(true); // Initialize the random number generator
|
|
|
|
USL_ReadConfig(); // Read config file
|
|
|
|
US_Started = true;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// US_Setup() - Does the disk access part of the User Mgr's startup
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
void
|
|
US_Setup(void)
|
|
{
|
|
USL_CheckSavedGames(); // Check which saved games are present
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// US_Shutdown() - Shuts down the User Mgr
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
void
|
|
US_Shutdown(void)
|
|
{
|
|
if (!US_Started)
|
|
return;
|
|
|
|
if (!abortprogram)
|
|
USL_WriteConfig();
|
|
|
|
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);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_ScreenDraw() - Draws a chunk of the text screen (called only by
|
|
// US_TextScreen())
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static void
|
|
USL_ScreenDraw(word x,word y,char *s,byte attr)
|
|
{
|
|
byte far *screen;
|
|
|
|
// screen = MK_FP(0xb800,(x * 2) + (y * 80 * 2));
|
|
// while (*s)
|
|
// {
|
|
// *screen++ = *s++;
|
|
// *screen++ = attr;
|
|
// }
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_ClearTextScreen() - Makes sure the screen is in text mode, clears it,
|
|
// and moves the cursor to the leftmost column of the bottom line
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static void
|
|
USL_ClearTextScreen(void)
|
|
{
|
|
// Set to 80x25 color text mode
|
|
_AL = 3; // Mode 3
|
|
_AH = 0x00;
|
|
geninterrupt(0x10);
|
|
|
|
// Use BIOS to move the cursor to the bottom of the screen
|
|
_AH = 0x0f;
|
|
geninterrupt(0x10); // Get current video mode into _BH
|
|
_DL = 0; // Lefthand side of the screen
|
|
_DH = 24; // Bottom row
|
|
_AH = 0x02;
|
|
geninterrupt(0x10);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// US_TextScreen() - Puts up the startup text screen
|
|
// Note: These are the only User Manager functions that can be safely called
|
|
// before the User Mgr has been started up
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
void
|
|
US_TextScreen(void)
|
|
{
|
|
word i,n,
|
|
sx,sy;
|
|
extern char far introscn;
|
|
|
|
USL_ClearTextScreen();
|
|
|
|
// _fmemcpy(MK_FP(0xb800,0),7 + &introscn,80 * 25 * 2);
|
|
|
|
// Check for TED launching here
|
|
for (i = 1;i < _argc;i++)
|
|
{
|
|
n = US_CheckParm(_argv[i],ParmStrings);
|
|
if (n == 0)
|
|
{
|
|
tedlevelnum = atoi(_argv[i + 1]);
|
|
if (tedlevelnum >= 0)
|
|
{
|
|
tedlevel = true;
|
|
return;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
else if (n == 1)
|
|
{
|
|
NoWait = true;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_Show() - Changes the appearance of one of the fields on the text
|
|
// screen. Possibly adds a checkmark in front of it and highlights it
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static void
|
|
USL_Show(word x,word y,word w,boolean show,boolean hilight)
|
|
{
|
|
byte far *screen;
|
|
|
|
screen = MK_FP(0xb800,((x - 1) * 2) + (y * 80 * 2));
|
|
*screen++ = show? 251 : ' '; // Checkmark char or space
|
|
*screen = 0x48;
|
|
if (show && hilight)
|
|
{
|
|
for (w++;w--;screen += 2)
|
|
*screen = 0x4f;
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_ShowMem() - Right justifies a longword in one of the memory fields on
|
|
// the text screen
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static void
|
|
USL_ShowMem(word x,word y,long mem)
|
|
{
|
|
char buf[16];
|
|
word i;
|
|
|
|
for (i = strlen(ltoa(mem,buf,10));i < 5;i++)
|
|
USL_ScreenDraw(x++,y," ",0x48);
|
|
USL_ScreenDraw(x,y,buf,0x48);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// US_UpdateTextScreen() - Called after the ID libraries are started up.
|
|
// Displays what hardware is present.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
void
|
|
US_UpdateTextScreen(void)
|
|
{
|
|
boolean b;
|
|
byte far *screen;
|
|
word i;
|
|
longword totalmem;
|
|
|
|
// Show video card info
|
|
b = (grmode == CGAGR);
|
|
USL_Show(21,7,4,(videocard >= CGAcard) && (videocard <= VGAcard),b);
|
|
b = (grmode == EGAGR);
|
|
USL_Show(21,8,4,(videocard >= EGAcard) && (videocard <= VGAcard),b);
|
|
b = (grmode == VGAGR);
|
|
USL_Show(21,9,4,videocard == VGAcard,b);
|
|
if (compatability)
|
|
USL_ScreenDraw(5,10,"SVGA Compatibility Mode Enabled.",0x4f);
|
|
|
|
// Show input device info
|
|
USL_Show(60,7,8,true,true);
|
|
USL_Show(60,8,11,JoysPresent[0],true);
|
|
USL_Show(60,9,11,JoysPresent[1],true);
|
|
USL_Show(60,10,5,MousePresent,true);
|
|
|
|
// Show sound hardware info
|
|
USL_Show(21,14,11,true,SoundMode == sdm_PC);
|
|
b = (SoundMode == sdm_AdLib) || (MusicMode == smm_AdLib);
|
|
USL_Show(21,15,5,AdLibPresent && !SoundBlasterPresent,
|
|
b && !SoundBlasterPresent);
|
|
USL_Show(21,16,13,SoundBlasterPresent,
|
|
SoundBlasterPresent && (b || (SoundMode == sdm_SoundBlaster)));
|
|
USL_Show(21,17,13,SoundSourcePresent,SoundMode == sdm_SoundSource);
|
|
|
|
// Show memory available/used
|
|
USL_ShowMem(63,15,mminfo.mainmem / 1024);
|
|
USL_Show(53,15,23,true,true);
|
|
USL_ShowMem(63,16,mminfo.EMSmem / 1024);
|
|
USL_Show(53,16,23,mminfo.EMSmem? true : false,true);
|
|
USL_ShowMem(63,17,mminfo.XMSmem / 1024);
|
|
USL_Show(53,17,23,mminfo.XMSmem? true : false,true);
|
|
totalmem = mminfo.mainmem + mminfo.EMSmem + mminfo.XMSmem;
|
|
USL_ShowMem(63,18,totalmem / 1024);
|
|
screen = MK_FP(0xb800,1 + (((63 - 1) * 2) + (18 * 80 * 2)));
|
|
for (i = 0;i < 13;i++,screen += 2)
|
|
*screen = 0x4f;
|
|
|
|
// Change Initializing... to Loading...
|
|
USL_ScreenDraw(27,22," Loading... ",0x9c);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// US_FinishTextScreen() - After the main program has finished its initial
|
|
// loading, this routine waits for a keypress and then clears the screen
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
void
|
|
US_FinishTextScreen(void)
|
|
{
|
|
// Change Loading... to Press a Key
|
|
// USL_ScreenDraw(29,22," Ready - Press a Key ",0x9a);
|
|
|
|
if (!(tedlevel || NoWait))
|
|
{
|
|
IN_ClearKeysDown();
|
|
// IN_Ack();
|
|
}
|
|
IN_ClearKeysDown();
|
|
|
|
USL_ClearTextScreen();
|
|
}
|
|
|
|
// 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 *s)
|
|
{
|
|
char c,*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
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static void
|
|
USL_PrintInCenter(char *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 *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 *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 *s)
|
|
{
|
|
char c,*se;
|
|
word w,h;
|
|
|
|
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_DrawTile8M(sx,sy,0),VWB_DrawTile8M(sx,sy + sh,6);
|
|
for (i = sx + 8;i <= sx + sw - 8;i += 8)
|
|
VWB_DrawTile8M(i,sy,1),VWB_DrawTile8M(i,sy + sh,7);
|
|
VWB_DrawTile8M(i,sy,2),VWB_DrawTile8M(i,sy + sh,8);
|
|
|
|
for (i = sy + 8;i <= sy + sh - 8;i += 8)
|
|
VWB_DrawTile8M(sx,i,3),VWB_DrawTile8M(sx + sw,i,5);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 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_CenterSaveWindow() - Generates a window of a given width & height in
|
|
// the middle of the screen, saving the background
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
void
|
|
US_CenterSaveWindow(word w,word h,memptr *save)
|
|
{
|
|
word x,y,
|
|
screen;
|
|
|
|
x = ((MaxX / 8) - w) / 2;
|
|
y = ((MaxY / 8) - h) / 2;
|
|
MM_GetPtr(save,(w * h) * CHARWIDTH);
|
|
screen = bufferofs + panadjust + ylookup[y] + (x * CHARWIDTH);
|
|
VW_ScreenToMem(screen,*save,w * CHARWIDTH,h);
|
|
US_DrawWindow(((MaxX / 8) - w) / 2,((MaxY / 8) - h) / 2,w,h);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// US_RestoreSaveWindow() - Restores the background of the size of the
|
|
// current window from the memory specified by save
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
void
|
|
US_RestoreSaveWindow(memptr *save)
|
|
{
|
|
word screen;
|
|
|
|
screen = bufferofs + panadjust + ylookup[WindowY] + (WindowX * CHARWIDTH);
|
|
VW_MemToScreen(*save,screen,WindowW * CHARWIDTH,WindowH);
|
|
MM_FreePtr(save);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 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;
|
|
}
|
|
|
|
// Cursor routines
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// US_StartCursor() - Sets up the cursor for User Mgr use
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
void
|
|
US_StartCursor(void)
|
|
{
|
|
CursorInfo info;
|
|
|
|
VW_SetCursor(CURSORARROWSPR);
|
|
CursorX = MaxX / 2;
|
|
CursorY = MaxY / 2;
|
|
VW_MoveCursor(CursorX,CursorY);
|
|
VW_ShowCursor();
|
|
|
|
IN_ReadCursor(&info); // Dispose of any accumulated movement
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// US_ShutCursor() - Cleans up after US_StartCursor()
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
void
|
|
US_ShutCursor(void)
|
|
{
|
|
VW_HideCursor();
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// US_UpdateCursor() - Gets the new cursor position & button states from
|
|
// the Input Mgr and tells the View Mgr where the cursor is
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
boolean
|
|
US_UpdateCursor(void)
|
|
{
|
|
CursorInfo info;
|
|
|
|
IN_ReadCursor(&info);
|
|
if (info.x || info.y || CursorBad)
|
|
{
|
|
CursorX += info.x;
|
|
if (CursorX >= MaxX)
|
|
CursorX = MaxX - 1;
|
|
else if (CursorX < 0)
|
|
CursorX = 0;
|
|
|
|
CursorY += info.y;
|
|
if (CursorY >= MaxY)
|
|
CursorY = MaxY - 1;
|
|
else if (CursorY < 0)
|
|
CursorY = 0;
|
|
|
|
VW_MoveCursor(CursorX,CursorY);
|
|
CursorBad = false;
|
|
}
|
|
Button0 = info.button0;
|
|
Button1 = info.button1;
|
|
return(Button0 || Button1);
|
|
}
|
|
|
|
// 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)
|
|
{
|
|
char buf[MaxString];
|
|
word w,h;
|
|
|
|
strcpy(buf,s);
|
|
buf[cursor] = '\0';
|
|
USL_MeasureString(buf,&w,&h);
|
|
|
|
px = x + w - 1;
|
|
py = y;
|
|
USL_DrawString("\x80");
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 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;
|
|
longword lasttime;
|
|
|
|
VW_HideCursor();
|
|
|
|
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;
|
|
USL_DrawString(olds);
|
|
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_ShowCursor();
|
|
VW_UpdateScreen();
|
|
|
|
IN_ClearKeysDown();
|
|
return(result);
|
|
}
|
|
|
|
// Control panel routines
|
|
|
|
static boolean FlushHelp;
|
|
static WindowRec HelpWindow,BottomWindow;
|
|
typedef enum
|
|
{
|
|
uic_Draw,uic_Hit
|
|
} UserCall;
|
|
typedef enum
|
|
{
|
|
uii_Bad,uii_Button,uii_RadioButton,uii_CheckBox,uii_KeyCap
|
|
} UIType;
|
|
#define ui_Normal 0
|
|
#define ui_Selected 1
|
|
#define ui_Disabled 2
|
|
|
|
// Prototype the custom routines
|
|
static boolean USL_CtlButtonCustom(UserCall,word,word),
|
|
USL_CtlPButtonCustom(UserCall,word,word),
|
|
USL_CtlPSButtonCustom(UserCall,word,word),
|
|
USL_CtlPRButtonCustom(UserCall,word,word),
|
|
USL_CtlHButtonCustom(UserCall,word,word),
|
|
USL_CtlDButtonCustom(UserCall,word,word),
|
|
USL_CtlDEButtonCustom(UserCall,word,word),
|
|
USL_CtlDLButtonCustom(UserCall,word,word),
|
|
USL_CtlDSButtonCustom(UserCall,word,word),
|
|
USL_CtlSButtonCustom(UserCall,word,word),
|
|
USL_CtlCButtonCustom(UserCall,word,word),
|
|
USL_CtlCKbdButtonCustom(UserCall,word,word),
|
|
USL_CtlCJoyButtonCustom(UserCall,word,word);
|
|
|
|
// The structure of a user interaction item
|
|
typedef struct {
|
|
Rect r; // The enclosing rectangle
|
|
UIType type; // The type of item
|
|
int picup,picdown; // What to draw when up/down
|
|
char *help; // Floating help string
|
|
ScanCode key; // Key equiv
|
|
word sel; // Interaction flags (ui_XXX)
|
|
boolean (*custom)(UserCall,word,word); // Custom routine
|
|
char *text; // Text for some items
|
|
} UserItem;
|
|
typedef struct {
|
|
ScanCode key;
|
|
word i,n, // Hit CtlPanels2[i][n]
|
|
toi,ton; // Move to CtlPanels2[toi][ton]
|
|
} HotKey; // MARK
|
|
|
|
static ScanCode *KeyMaps[] =
|
|
{
|
|
&KbdDefs[0].button0,&KbdDefs[0].button1,
|
|
&KbdDefs[0].upleft,&KbdDefs[0].up,&KbdDefs[0].upright,
|
|
&KbdDefs[0].left, &KbdDefs[0].right,
|
|
&KbdDefs[0].downleft,&KbdDefs[0].down,&KbdDefs[0].downright,
|
|
};
|
|
|
|
// Some macros to make rectangle definition quite a bit less unpleasant
|
|
#define CtlPanelX 8
|
|
#define CtlPanelY 4
|
|
#define CtlPanel2X (8*8)
|
|
#define CtlPanel2Y (2*8)
|
|
#define CtlPanel3X (8*8)
|
|
#define CtlPanel3Y (7*8)
|
|
|
|
#define CtlPanelR(n) { CtlPanelX,CtlPanelY+(32 * (n)),\
|
|
CtlPanelX+40,CtlPanelY+(32 * (n)) + 32}
|
|
#define CtlPanel2R(x,y) { CtlPanel2X+(x)*8,CtlPanel2Y+(y)*8,\
|
|
CtlPanel2X+32+(x)*8,CtlPanel2Y+24+(y)*8}
|
|
#define CtlPanel3R(x,y) { CtlPanel3X+(x)*8,CtlPanel3Y+(y)*8,\
|
|
CtlPanel3X+32+(x)*8,CtlPanel3Y+24+(y)*8}
|
|
static UserItem CtlPanels[] =
|
|
{
|
|
{CtlPanelR(0),uii_RadioButton,CTL_STARTUPPIC,CTL_STARTDNPIC,"Start or Resume a Game",sc_None,ui_Normal,USL_CtlButtonCustom},
|
|
{CtlPanelR(1),uii_RadioButton,CTL_HELPUPPIC,CTL_HELPDNPIC,"Get Help With Commander Keen",sc_None,ui_Normal,USL_CtlButtonCustom},
|
|
{CtlPanelR(2),uii_RadioButton,CTL_DISKUPPIC,CTL_DISKDNPIC,"Load / Save / Quit",sc_None,ui_Normal,USL_CtlButtonCustom},
|
|
{CtlPanelR(3),uii_RadioButton,CTL_CONTROLSUPPIC,CTL_CONTROLSDNPIC,"Choose Controls",sc_C,ui_Normal,USL_CtlButtonCustom},
|
|
{CtlPanelR(4),uii_RadioButton,CTL_SOUNDUPPIC,CTL_SOUNDDNPIC,"Select Sound Device",sc_F2,ui_Normal,USL_CtlButtonCustom},
|
|
{CtlPanelR(5),uii_RadioButton,CTL_MUSICUPPIC,CTL_MUSICDNPIC,"Turn Music On / Off",sc_F7,ui_Normal,USL_CtlButtonCustom},
|
|
{-1,-1,-1,-1,uii_Bad}
|
|
},
|
|
CtlPPanels[] =
|
|
{
|
|
{CtlPanel2R(10,0),uii_RadioButton,CTL_P_NEWGAMEUPPIC,CTL_P_NEWGAMEDNPIC,"Choose Difficulty for the New Game",sc_F5,ui_Normal,USL_CtlPButtonCustom},
|
|
{CtlPanel2R(15,0),uii_RadioButton,CTL_P_RESUMEUPPIC,CTL_P_RESUMEDNPIC,"Go Back to Current Game",sc_None,ui_Normal,USL_CtlPButtonCustom},
|
|
{-1,-1,-1,-1,uii_Bad}
|
|
},
|
|
CtlPSPanels[] =
|
|
{
|
|
{CtlPanel3R(13,5),uii_Button,CTL_P_MEDUPPIC,CTL_P_MEDDNPIC,"Start New Game in Normal Mode",sc_None,ui_Normal,USL_CtlPSButtonCustom},
|
|
{CtlPanel3R(8,5),uii_Button,CTL_P_EASYUPPIC,CTL_P_EASYDNPIC,"Start New Game in Easy Mode",sc_None,ui_Normal,USL_CtlPSButtonCustom},
|
|
{CtlPanel3R(18,5),uii_Button,CTL_P_HARDUPPIC,CTL_P_HARDDNPIC,"Start New Game in Hard Mode",sc_None,ui_Normal,USL_CtlPSButtonCustom},
|
|
{-1,-1,-1,-1,uii_Bad}
|
|
},
|
|
CtlPRPanels[] =
|
|
{
|
|
{CtlPanel3R(13,5),uii_Button,CTL_P_GORESUMEUPPIC,CTL_P_GORESUMEDNPIC,"Resume Current Game",sc_None,ui_Normal,USL_CtlPRButtonCustom},
|
|
{-1,-1,-1,-1,uii_Bad}
|
|
},
|
|
CtlHPanels[] =
|
|
{
|
|
{CtlPanel2R(8,0),uii_Button,CTL_H_LOSTUPPIC,CTL_H_LOSTDNPIC,"Help Me, I'm Lost!",sc_F1,ui_Normal,USL_CtlHButtonCustom},
|
|
{CtlPanel2R(13,0),uii_Button,CTL_H_CTRLUPPIC,CTL_H_CTRLDNPIC,"Get Help with Controls",sc_None,ui_Normal,USL_CtlHButtonCustom},
|
|
{CtlPanel2R(18,0),uii_Button,CTL_H_STORYUPPIC,CTL_H_STORYDNPIC,"Read Story & Game Tips",sc_None,ui_Normal,USL_CtlHButtonCustom},
|
|
{-1,-1,-1,-1,uii_Bad}
|
|
},
|
|
CtlDPanels[] =
|
|
{
|
|
{CtlPanel2R(9,0),uii_RadioButton,CTL_D_LSGAMEUPPIC,CTL_D_LSGAMEDNPIC,"Load or Save a Game",sc_F6,ui_Normal,USL_CtlDButtonCustom},
|
|
{CtlPanel2R(15,0),uii_RadioButton,CTL_D_DOSUPPIC,CTL_D_DOSDNPIC,"Exit to DOS",sc_Q,ui_Normal,USL_CtlDButtonCustom},
|
|
{-1,-1,-1,-1,uii_Bad}
|
|
},
|
|
CtlDLSPanels[] =
|
|
{
|
|
#define CtlPanel3LSR(x,y) { CtlPanel3X+(x)*8,CtlPanel3Y+(y)*8,\
|
|
CtlPanel3X+32+(x)*8,CtlPanel3Y+16+(y)*8}
|
|
{CtlPanel3LSR(1,0),uii_Button,CTL_D_LOADUPPIC,CTL_D_LOADDNPIC,"Load This Game",sc_None,ui_Normal,USL_CtlDLButtonCustom},
|
|
{CtlPanel3LSR(6,0),uii_Button,CTL_D_SAVEUPPIC,CTL_D_SAVEDNPIC,"Save Current Game Here",sc_None,ui_Normal,USL_CtlDSButtonCustom},
|
|
{CtlPanel3LSR(1,2),uii_Button,CTL_D_LOADUPPIC,CTL_D_LOADDNPIC,"Load This Game",sc_None,ui_Normal,USL_CtlDLButtonCustom},
|
|
{CtlPanel3LSR(6,2),uii_Button,CTL_D_SAVEUPPIC,CTL_D_SAVEDNPIC,"Save Current Game Here",sc_None,ui_Normal,USL_CtlDSButtonCustom},
|
|
{CtlPanel3LSR(1,4),uii_Button,CTL_D_LOADUPPIC,CTL_D_LOADDNPIC,"Load This Game",sc_None,ui_Normal,USL_CtlDLButtonCustom},
|
|
{CtlPanel3LSR(6,4),uii_Button,CTL_D_SAVEUPPIC,CTL_D_SAVEDNPIC,"Save Current Game Here",sc_None,ui_Normal,USL_CtlDSButtonCustom},
|
|
{CtlPanel3LSR(1,6),uii_Button,CTL_D_LOADUPPIC,CTL_D_LOADDNPIC,"Load This Game",sc_None,ui_Normal,USL_CtlDLButtonCustom},
|
|
{CtlPanel3LSR(6,6),uii_Button,CTL_D_SAVEUPPIC,CTL_D_SAVEDNPIC,"Save Current Game Here",sc_None,ui_Normal,USL_CtlDSButtonCustom},
|
|
{CtlPanel3LSR(1,8),uii_Button,CTL_D_LOADUPPIC,CTL_D_LOADDNPIC,"Load This Game",sc_None,ui_Normal,USL_CtlDLButtonCustom},
|
|
{CtlPanel3LSR(6,8),uii_Button,CTL_D_SAVEUPPIC,CTL_D_SAVEDNPIC,"Save Current Game Here",sc_None,ui_Normal,USL_CtlDSButtonCustom},
|
|
{CtlPanel3LSR(1,10),uii_Button,CTL_D_LOADUPPIC,CTL_D_LOADDNPIC,"Load This Game",sc_None,ui_Normal,USL_CtlDLButtonCustom},
|
|
{CtlPanel3LSR(6,10),uii_Button,CTL_D_SAVEUPPIC,CTL_D_SAVEDNPIC,"Save Current Game Here",sc_None,ui_Normal,USL_CtlDSButtonCustom},
|
|
{CtlPanel3LSR(1,12),uii_Button,CTL_D_LOADUPPIC,CTL_D_LOADDNPIC,"Load This Game",sc_None,ui_Normal,USL_CtlDLButtonCustom},
|
|
{CtlPanel3LSR(6,12),uii_Button,CTL_D_SAVEUPPIC,CTL_D_SAVEDNPIC,"Save Current Game Here",sc_None,ui_Normal,USL_CtlDSButtonCustom},
|
|
{-1,-1,-1,-1,uii_Bad}
|
|
},
|
|
CtlDEPanels[] =
|
|
{
|
|
#define CtlPanel3ER(x,y) { CtlPanel3X+(x)*8,CtlPanel3Y+(y)*8,\
|
|
CtlPanel3X+40+(x)*8,CtlPanel3Y+24+(y)*8}
|
|
{CtlPanel3ER(12,5),uii_Button,CTL_D_EXITUPPIC,CTL_D_EXITDNPIC,"Really Exit to DOS",sc_None,ui_Normal,USL_CtlDEButtonCustom},
|
|
{-1,-1,-1,-1,uii_Bad}
|
|
},
|
|
CtlCPanels[] =
|
|
{
|
|
{CtlPanel2R(8,0),uii_RadioButton,CTL_C_KBDUPPIC,CTL_C_KBDDNPIC,"Use / Configure Keyboard",sc_F3,ui_Normal,USL_CtlCButtonCustom},
|
|
{CtlPanel2R(13,0),uii_RadioButton,CTL_C_JOY1UPPIC,CTL_C_JOY1DNPIC,"Use / Configure Joystick 1",sc_None,ui_Normal,USL_CtlCButtonCustom},
|
|
{CtlPanel2R(18,0),uii_RadioButton,CTL_C_JOY2UPPIC,CTL_C_JOY2DNPIC,"Use / Configure Joystick 2",sc_None,ui_Normal,USL_CtlCButtonCustom},
|
|
{-1,-1,-1,-1,uii_Bad}
|
|
},
|
|
#define CtlPanelKC3R(x,y) { CtlPanel3X+(x)*8,CtlPanel3Y+(y)*8,\
|
|
CtlPanel3X+56+(x)*8,CtlPanel3Y+32+(y)*8}
|
|
CtlCKbdPanels[] =
|
|
{
|
|
{CtlPanelKC3R(1,2),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key for Jumping",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},
|
|
{CtlPanelKC3R(1,6),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key for Throwing",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},
|
|
{CtlPanelKC3R(8,0),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key to move Up & Left",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},
|
|
{CtlPanelKC3R(15,0),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key to move Up",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},
|
|
{CtlPanelKC3R(22,0),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key to move Up & Right",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},
|
|
{CtlPanelKC3R(8,4),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key to move Left",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},
|
|
{CtlPanelKC3R(22,4),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key to move Right",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},
|
|
{CtlPanelKC3R(8,8),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key to move Down & Left",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},
|
|
{CtlPanelKC3R(15,8),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key to move Down",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},
|
|
{CtlPanelKC3R(22,8),uii_KeyCap,CTL_KEYCAPPIC,CTL_KEYCAPCURPIC,"Define Key to move Down & Right",sc_None,ui_Normal,USL_CtlCKbdButtonCustom},
|
|
{-1,-1,-1,-1,uii_Bad}
|
|
},
|
|
CtlCJoyPanels[] =
|
|
{
|
|
{CtlPanel3R(13,5),uii_Button,CTL_C_CALIBRATEUPPIC,CTL_C_CALIBRATEDNPIC,"Configure Joystick",sc_None,ui_Normal,USL_CtlCJoyButtonCustom},
|
|
{-1,-1,-1,-1,uii_Bad}
|
|
},
|
|
CtlSPanels[] =
|
|
{
|
|
{CtlPanel2R(3,0),uii_RadioButton,CTL_S_NOSNDUPPIC,CTL_S_NOSNDDNPIC,"Turn Sound Off",sc_None,ui_Normal,USL_CtlSButtonCustom},
|
|
{CtlPanel2R(8,0),uii_RadioButton,CTL_S_PCSNDUPPIC,CTL_S_PCSNDDNPIC,"Use PC Speaker",sc_None,ui_Normal,USL_CtlSButtonCustom},
|
|
{CtlPanel2R(13,0),uii_RadioButton,CTL_S_ADLIBUPPIC,CTL_S_ADLIBDNPIC,"Use AdLib Sound Effects",sc_None,ui_Normal,USL_CtlSButtonCustom},
|
|
{CtlPanel2R(18,0),uii_RadioButton,CTL_S_SNDBLUPPIC,CTL_S_SNDBLDNPIC,"Use SoundBlaster Sound Effects",sc_None,ui_Normal,USL_CtlSButtonCustom},
|
|
{CtlPanel2R(23,0),uii_RadioButton,CTL_S_SNDSRCUPPIC,CTL_S_SNDSRCDNPIC,"Use Sound Source Sound Effects",sc_None,ui_Normal,USL_CtlSButtonCustom},
|
|
{-1,-1,-1,-1,uii_Bad}
|
|
},
|
|
CtlSSSPanels[] =
|
|
{
|
|
{CtlPanel3R(7,2),uii_CheckBox,CTL_CHECKUPPIC,CTL_CHECKDNPIC,"Turn Tandy Mode On / Off",sc_None,ui_Normal,0,"Tandy Mode"},
|
|
{CtlPanel3R(7,6),uii_CheckBox,CTL_CHECKUPPIC,CTL_CHECKDNPIC,"Switch between LPT1 & LPT2",sc_None,ui_Normal,0,"Use LPT2"},
|
|
{-1,-1,-1,-1,uii_Bad}
|
|
},
|
|
CtlMPanels[] =
|
|
{
|
|
{CtlPanel2R(9,0),uii_RadioButton,CTL_M_NOMUSUPPIC,CTL_M_NOMUSDNPIC,"Background Music Off"},
|
|
{CtlPanel2R(15,0),uii_RadioButton,CTL_M_ADLIBUPPIC,CTL_M_ADLIBDNPIC,"Use AdLib/SoundBlaster Music"},
|
|
{-1,-1,-1,-1,uii_Bad}
|
|
},
|
|
*CtlPanels2[] =
|
|
{
|
|
CtlPPanels, // Start
|
|
CtlHPanels, // Help
|
|
CtlDPanels, // Disk
|
|
CtlCPanels, // Controls
|
|
CtlSPanels, // Sound
|
|
CtlMPanels // Music
|
|
},
|
|
*TheItems[4] = {CtlPanels};
|
|
static int CtlPanelButton;
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_TurnOff() - Goes through a list of UserItems and sets them all to
|
|
// the normal state
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static void
|
|
USL_TurnOff(UserItem *ip)
|
|
{
|
|
while (ip->type != uii_Bad)
|
|
{
|
|
ip->sel = ui_Normal;
|
|
ip++;
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_FindDown() - Finds which UserItem, if any, is selected in the given
|
|
// list
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static int
|
|
USL_FindDown(UserItem *ip)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0;ip->type != uii_Bad;i++,ip++)
|
|
if (ip->sel & ui_Selected)
|
|
return(i);
|
|
return(-1);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_ShowHelp() - Shows the specified string in the help window
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static void
|
|
USL_ShowHelp(char *s)
|
|
{
|
|
WindowRec wr;
|
|
|
|
if (!s)
|
|
return;
|
|
|
|
US_SaveWindow(&wr);
|
|
US_RestoreWindow(&HelpWindow);
|
|
|
|
US_ClearWindow();
|
|
US_PrintCentered(s);
|
|
|
|
US_RestoreWindow(&wr);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_HandleError() - Handles telling the user that there's been an error
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static void
|
|
USL_HandleError(int num)
|
|
{
|
|
char buf[64];
|
|
|
|
strcpy(buf,"Error: ");
|
|
if (num < 0)
|
|
strcat(buf,"Unknown");
|
|
else if (num == ENOMEM)
|
|
strcat(buf,"Disk is Full");
|
|
else if (num == EINVFMT)
|
|
strcat(buf,"File is Incomplete");
|
|
else
|
|
strcat(buf,sys_errlist[num]);
|
|
|
|
VW_HideCursor();
|
|
|
|
fontcolor = F_SECONDCOLOR;
|
|
USL_ShowHelp(buf);
|
|
fontcolor = F_BLACK;
|
|
VW_UpdateScreen();
|
|
|
|
IN_ClearKeysDown();
|
|
IN_Ack();
|
|
|
|
VW_ShowCursor();
|
|
VW_UpdateScreen();
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_DrawItem() - Draws a UserItem. If there's a custom routine, this will
|
|
// call it with a uic_Draw command. If the custom routine returns true,
|
|
// then the routine handled all of the drawing. If it returns false,
|
|
// then this routine does the default drawing.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static void
|
|
USL_DrawItem(word hiti,word hitn)
|
|
{
|
|
boolean handled,centered;
|
|
char *text;
|
|
word w,h;
|
|
int picup,picdown;
|
|
Rect r;
|
|
UserItem *ip;
|
|
|
|
ip = &TheItems[hiti][hitn];
|
|
if (ip->custom)
|
|
handled = ip->custom(uic_Draw,hiti,hitn);
|
|
else
|
|
handled = false;
|
|
|
|
if (!handled)
|
|
{
|
|
picup = ip->picup;
|
|
picdown = ip->picdown;
|
|
switch (ip->type)
|
|
{
|
|
case uii_CheckBox:
|
|
px = ip->r.lr.x + 8;
|
|
py = ip->r.ul.y + 8;
|
|
text = ip->text;
|
|
centered = false;
|
|
break;
|
|
case uii_KeyCap:
|
|
if (!(ip->sel & ui_Selected))
|
|
{
|
|
text = ip->text;
|
|
if (text)
|
|
{
|
|
r = ip->r;
|
|
centered = true;
|
|
}
|
|
}
|
|
else
|
|
text = nil;
|
|
break;
|
|
default:
|
|
text = nil;
|
|
break;
|
|
}
|
|
|
|
VWB_DrawPic(ip->r.ul.x,ip->r.ul.y,
|
|
(ip->sel & ui_Selected)? picdown : picup);
|
|
if (text)
|
|
{
|
|
if (centered)
|
|
USL_PrintInCenter(text,r);
|
|
else
|
|
{
|
|
USL_MeasureString(text,&w,&h);
|
|
VWB_Bar(px,py,w + 7,h,WHITE);
|
|
USL_DrawString(text);
|
|
}
|
|
}
|
|
if (ip->sel & ui_Disabled)
|
|
{
|
|
if ((picup == CTL_D_LOADUPPIC) || (picup == CTL_D_SAVEUPPIC))
|
|
VWB_DrawMPic(ip->r.ul.x,ip->r.ul.y,CTL_LSMASKPICM);
|
|
else
|
|
VWB_DrawMPic(ip->r.ul.x,ip->r.ul.y,CTL_LITTLEMASKPICM);
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_DoHit() - Handles a hit on a UserItem. If there's a custom routine,
|
|
// it will be called. If it returns true, then don't do anything
|
|
// more. If it returns false, then use the standard behaviour
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static void
|
|
USL_DoHit(word hiti,word hitn)
|
|
{
|
|
boolean handled;
|
|
word i;
|
|
UserItem *ip;
|
|
|
|
ip = &TheItems[hiti][hitn];
|
|
if (ip->custom)
|
|
handled = ip->custom(uic_Hit,hiti,hitn);
|
|
else
|
|
handled = false;
|
|
|
|
if (!handled)
|
|
{
|
|
if (TheItems[hiti][hitn].sel & ui_Disabled)
|
|
{
|
|
fontcolor = F_SECONDCOLOR;
|
|
USL_ShowHelp("This Item is Disabled");
|
|
fontcolor = F_BLACK;
|
|
return;
|
|
}
|
|
|
|
FlushHelp = true;
|
|
|
|
switch (ip->type)
|
|
{
|
|
case uii_Button:
|
|
// Must have a custom routine to handle hits - this just redraws
|
|
ip->sel ^= ui_Selected;
|
|
USL_DrawItem(hiti,hitn);
|
|
case uii_CheckBox:
|
|
ip->sel ^= ui_Selected;
|
|
USL_DrawItem(hiti,hitn);
|
|
break;
|
|
case uii_RadioButton:
|
|
for (i = 0,ip = TheItems[hiti];ip->type != uii_Bad;i++,ip++)
|
|
{
|
|
if
|
|
(
|
|
(i != hitn)
|
|
&& (ip->type == uii_RadioButton)
|
|
&& (ip->sel & ui_Selected)
|
|
)
|
|
{
|
|
ip->sel &= ~ui_Selected;
|
|
USL_DrawItem(hiti,i);
|
|
}
|
|
}
|
|
TheItems[hiti][hitn].sel |= ui_Selected;
|
|
USL_DrawItem(hiti,hitn);
|
|
break;
|
|
case uii_KeyCap:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_IsInRect() - Checks to see if the coordinates given are within any
|
|
// of the Rects in the UserItem list. If so, returns true & sets the
|
|
// index & number for lookup. If not, returns false.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static boolean
|
|
USL_IsInRect(word x,word y,word *index,word *number)
|
|
{
|
|
UserItem *item,**items;
|
|
|
|
items = TheItems;
|
|
*index = 0;
|
|
while (*items)
|
|
{
|
|
item = *items;
|
|
*number = 0;
|
|
while (item->type != uii_Bad)
|
|
{
|
|
if
|
|
(
|
|
(x >= item->r.ul.x)
|
|
&& (x < item->r.lr.x)
|
|
&& (y >= item->r.ul.y)
|
|
&& (y < item->r.lr.y)
|
|
)
|
|
return(true);
|
|
(*number)++;
|
|
item++;
|
|
}
|
|
|
|
(*index)++;
|
|
items++;
|
|
}
|
|
return(false);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_TrackItem() - Tracks the given item. If the cursor is inside of the
|
|
// item, it's redrawn as down. If the cursor is outside, the item is
|
|
// drawn in its original state. Returns true if the button was released
|
|
// while the cursor was inside the item, or false if it wasn't.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static boolean
|
|
USL_TrackItem(word hiti,word hitn)
|
|
{
|
|
boolean inside,last;
|
|
word ini,inn,
|
|
on,
|
|
sel,othersel;
|
|
UserItem *ip,*op;
|
|
|
|
ip = &TheItems[hiti][hitn];
|
|
sel = ip->sel;
|
|
if (ip->type == uii_RadioButton)
|
|
{
|
|
inside = false;
|
|
for (op = TheItems[hiti],on = 0;op->type != uii_Bad;op++,on++)
|
|
{
|
|
if (op->sel & ui_Selected)
|
|
{
|
|
inside = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!inside)
|
|
op = ip;
|
|
othersel = op->sel;
|
|
}
|
|
else
|
|
op = nil;
|
|
|
|
if (ip->sel & ui_Disabled)
|
|
{
|
|
fontcolor = F_SECONDCOLOR;
|
|
USL_ShowHelp("This item is disabled");
|
|
fontcolor = F_BLACK;
|
|
|
|
while (US_UpdateCursor())
|
|
VW_UpdateScreen();
|
|
|
|
FlushHelp = true;
|
|
return(false);
|
|
}
|
|
|
|
last = false;
|
|
do
|
|
{
|
|
USL_IsInRect(CursorX,CursorY,&ini,&inn);
|
|
inside = (ini == hiti) && (inn == hitn);
|
|
if (inside != last)
|
|
{
|
|
if (inside)
|
|
{
|
|
if (op)
|
|
{
|
|
op->sel &= ~ui_Selected;
|
|
ip->sel |= ui_Selected;
|
|
}
|
|
else
|
|
ip->sel = sel ^ ui_Selected;
|
|
}
|
|
else
|
|
{
|
|
if (op && (op != ip))
|
|
{
|
|
op->sel |= ui_Selected;
|
|
ip->sel &= ~ui_Selected;
|
|
}
|
|
else
|
|
ip->sel = sel;
|
|
}
|
|
|
|
USL_DrawItem(hiti,hitn);
|
|
if (op && (op != ip))
|
|
USL_DrawItem(hiti,on);
|
|
|
|
last = inside;
|
|
}
|
|
VW_UpdateScreen();
|
|
} while (US_UpdateCursor());
|
|
|
|
if (op)
|
|
op->sel = othersel;
|
|
ip->sel = sel;
|
|
if (!inside)
|
|
{
|
|
if (op && (op != ip))
|
|
USL_DrawItem(hiti,on);
|
|
USL_DrawItem(hiti,hitn);
|
|
VW_UpdateScreen();
|
|
}
|
|
|
|
return(inside);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_GlideCursor() - Smoothly moves the cursor to the given location
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static void
|
|
USL_GlideCursor(long newx,long newy)
|
|
{
|
|
word steps;
|
|
long x,y,
|
|
dx,dy;
|
|
|
|
if (grmode == CGAGR)
|
|
steps = 1;
|
|
else
|
|
steps = 8;
|
|
|
|
x = (long)CursorX << 16;
|
|
dx = ((newx << 16) - x) / steps;
|
|
y = (long)CursorY << 16;
|
|
dy = ((newy << 16) - y) / steps;
|
|
|
|
while ((CursorX != newx) || (CursorY != newy))
|
|
{
|
|
x += dx;
|
|
y += dy;
|
|
|
|
CursorX = x >> 16;
|
|
CursorY = y >> 16;
|
|
VW_MoveCursor(CursorX,CursorY);
|
|
VW_UpdateScreen();
|
|
}
|
|
CursorBad = true;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_FindRect() - Code so ugly you'll puke! Given a Rect and direction,
|
|
// this routine will try to find a UserItem to move the cursor to
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static void
|
|
USL_FindRect(Rect r,Motion xd,Motion yd)
|
|
{
|
|
word i,i1,i2,i3;
|
|
Motion m1,m2;
|
|
Point diffs[9],diff,*dp;
|
|
Rect *rp,*good,*goods[9];
|
|
UserItem *ip,**items;
|
|
|
|
for (m1 = motion_Up,dp = diffs;m1 <= motion_Down;m1++)
|
|
{
|
|
for (m2 = motion_Left;m2 <= motion_Right;m2++,dp++)
|
|
{
|
|
dp->x = m2 * 1024;
|
|
dp->y = m1 * 1024;
|
|
}
|
|
}
|
|
for (i = 0;i < 9;i++)
|
|
goods[i] = nil;
|
|
|
|
// Find out which octants all of the rects (except r) are in
|
|
for (items = TheItems;*items;items++)
|
|
{
|
|
for (ip = *items;ip->type != uii_Bad;ip++)
|
|
{
|
|
rp = &ip->r;
|
|
diff.x = rp->ul.x - r.ul.x;
|
|
diff.y = rp->ul.y - r.ul.y;
|
|
if (!(diff.x || diff.y))
|
|
continue;
|
|
|
|
if // 1,4,7
|
|
(
|
|
((rp->ul.x >= r.ul.x) && (rp->ul.x < r.lr.x))
|
|
|| ((rp->lr.x > r.ul.x) && (rp->lr.x <= r.lr.x))
|
|
)
|
|
{
|
|
if (rp->lr.y <= r.ul.y)
|
|
{
|
|
if (!(goods[1] && (diff.y < diffs[1].y)))
|
|
{
|
|
goods[1] = rp;
|
|
diffs[1] = diff;
|
|
}
|
|
}
|
|
else if (rp->ul.y >= r.lr.y)
|
|
{
|
|
if (!(goods[7] && (diff.y > diffs[7].y)))
|
|
{
|
|
goods[7] = rp;
|
|
diffs[7] = diff;
|
|
}
|
|
}
|
|
}
|
|
|
|
if // 3,4,5
|
|
(
|
|
((rp->ul.y >= r.ul.y) && (rp->ul.y < r.lr.y))
|
|
|| ((rp->lr.y > r.ul.y) && (rp->lr.y <= r.lr.y))
|
|
)
|
|
{
|
|
if (rp->lr.x <= r.ul.x)
|
|
{
|
|
if (!(goods[3] && (diff.x < diffs[3].x)))
|
|
{
|
|
goods[3] = rp;
|
|
diffs[3] = diff;
|
|
}
|
|
}
|
|
else if (rp->ul.x >= r.lr.x)
|
|
{
|
|
if (!(goods[5] && (diff.x > diffs[5].x)))
|
|
{
|
|
goods[5] = rp;
|
|
diffs[5] = diff;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (rp->ul.x < r.ul.x) // 0,6
|
|
{
|
|
if (rp->lr.y <= r.ul.y)
|
|
{
|
|
if
|
|
(
|
|
(!goods[0])
|
|
|| (diff.y > diffs[0].y)
|
|
|| (diff.x > diffs[6].x)
|
|
)
|
|
{
|
|
goods[0] = rp;
|
|
diffs[0] = diff;
|
|
}
|
|
}
|
|
else if (rp->ul.y >= r.lr.y)
|
|
{
|
|
if
|
|
(
|
|
(!goods[6])
|
|
|| (diff.y < diffs[6].y)
|
|
|| (diff.x > diffs[6].x)
|
|
)
|
|
{
|
|
goods[6] = rp;
|
|
diffs[6] = diff;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (rp->lr.x > r.lr.x) // 2,8
|
|
{
|
|
if (rp->lr.y <= r.ul.y)
|
|
{
|
|
if
|
|
(
|
|
(!goods[2])
|
|
|| (diff.y > diffs[2].y)
|
|
|| (diff.x < diffs[2].x)
|
|
)
|
|
{
|
|
goods[2] = rp;
|
|
diffs[2] = diff;
|
|
}
|
|
}
|
|
else if (rp->ul.y >= r.lr.y)
|
|
{
|
|
if
|
|
(
|
|
(!goods[8])
|
|
|| (diff.y < diffs[8].y)
|
|
|| (diff.x < diffs[8].x)
|
|
)
|
|
{
|
|
goods[8] = rp;
|
|
diffs[8] = diff;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
switch (yd)
|
|
{
|
|
case motion_Up:
|
|
i1 = 1,i2 = 0,i3 = 2;
|
|
break;
|
|
case motion_None:
|
|
switch (xd)
|
|
{
|
|
case motion_Left:
|
|
i1 = 3,i2 = 0,i3 = 6;
|
|
break;
|
|
case motion_Right:
|
|
i1 = 5,i2 = 8,i3 = 2;
|
|
break;
|
|
}
|
|
break;
|
|
case motion_Down:
|
|
i1 = 7,i2 = 8,i3 = 6;
|
|
break;
|
|
}
|
|
|
|
(
|
|
(good = goods[i1])
|
|
|| (good = goods[i2])
|
|
|| (good = goods[i3])
|
|
|| (good = &r)
|
|
);
|
|
#if 0
|
|
CursorX = good->lr.x - 8;
|
|
CursorY = good->lr.y - 8;
|
|
CursorBad = true;
|
|
US_UpdateCursor();
|
|
#endif
|
|
USL_GlideCursor(good->lr.x - 8,good->lr.y - 8);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_CtlButtonCustom() - The custom routine for all of the Control Panel
|
|
// (leftmost) buttons. Clears all of the other item lists, clears the
|
|
// large area, and draws the line dividing the top and bottom areas.
|
|
// Then it sets up and draws the appropriate top row of icons.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static boolean
|
|
USL_CtlButtonCustom(UserCall call,word i,word n)
|
|
{
|
|
word j;
|
|
UserItem *ip;
|
|
|
|
if (call != uic_Hit)
|
|
return(false);
|
|
|
|
if (n == CtlPanelButton)
|
|
return(true);
|
|
|
|
US_ClearWindow();
|
|
for (j = 8;j < 38;j++)
|
|
{
|
|
VWB_DrawTile8M(j * 8,6 * 8,10);
|
|
VWB_DrawTile8M(j * 8,21 * 8,10);
|
|
}
|
|
VWB_DrawTile8M(7 * 8,6 * 8,9);
|
|
VWB_DrawTile8M(38 * 8,6 * 8,11);
|
|
VWB_DrawTile8M(7 * 8,21 * 8,9);
|
|
VWB_DrawTile8M(38 * 8,21 * 8,11);
|
|
|
|
for (j = 1;j < 4;j++)
|
|
TheItems[j] = nil;
|
|
|
|
// Set to new button
|
|
CtlPanelButton = n;
|
|
|
|
// Draw new items
|
|
TheItems[1] = ip = CtlPanels2[CtlPanelButton];
|
|
j = 0;
|
|
while (ip && (ip->type != uii_Bad))
|
|
{
|
|
USL_DrawItem(i + 1,j);
|
|
if (ip->sel & ui_Selected)
|
|
USL_DoHit(i + 1,j);
|
|
j++;
|
|
ip++;
|
|
}
|
|
|
|
return(false);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_CtlCKbdButtonCustom() - The custom routine for the keyboard keycaps.
|
|
// This routine gets a scancode and puts it in the appropriate
|
|
// KbdDefs[0] member.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static boolean
|
|
USL_CtlCKbdButtonCustom(UserCall call,word i,word n)
|
|
{
|
|
boolean state;
|
|
word j;
|
|
ScanCode scan;
|
|
longword time;
|
|
UserItem *ip;
|
|
|
|
if (call != uic_Hit)
|
|
return(false);
|
|
|
|
ip = &TheItems[i][n];
|
|
|
|
fontcolor = F_SECONDCOLOR;
|
|
USL_ShowHelp(ip->help);
|
|
fontcolor = F_BLACK;
|
|
VW_HideCursor();
|
|
VWB_DrawPic(ip->r.ul.x,ip->r.ul.y,ip->picdown);
|
|
VW_UpdateScreen();
|
|
|
|
LastScan = sc_None;
|
|
time = TimeCount;
|
|
state = true;
|
|
do
|
|
{
|
|
if (TimeCount - time > 35) // Half-second delays
|
|
{
|
|
state ^= true;
|
|
VWB_DrawPic(ip->r.ul.x,ip->r.ul.y,state? ip->picdown : ip->picup);
|
|
VW_UpdateScreen();
|
|
time = TimeCount;
|
|
}
|
|
if (US_UpdateCursor())
|
|
{
|
|
while (US_UpdateCursor())
|
|
;
|
|
scan = sc_Escape;
|
|
break;
|
|
}
|
|
|
|
asm pushf
|
|
asm cli
|
|
if (LastScan == sc_LShift)
|
|
LastScan = sc_None;
|
|
asm popf
|
|
} while (!(scan = LastScan));
|
|
IN_ClearKey(scan);
|
|
if (scan != sc_Escape)
|
|
{
|
|
for (j = 0,state = false;j < 10;j++)
|
|
{
|
|
if (j == n)
|
|
continue;
|
|
if (*(KeyMaps[j]) == scan)
|
|
{
|
|
state = true;
|
|
break;
|
|
}
|
|
}
|
|
if (state)
|
|
{
|
|
fontcolor = F_SECONDCOLOR;
|
|
USL_ShowHelp("That Key is Already Used!");
|
|
fontcolor = F_BLACK;
|
|
}
|
|
else
|
|
{
|
|
ip->text = IN_GetScanName(scan);
|
|
*(KeyMaps[n]) = scan;
|
|
FlushHelp = true;
|
|
}
|
|
}
|
|
|
|
USL_DrawItem(i,n);
|
|
VW_ShowCursor();
|
|
VW_UpdateScreen();
|
|
|
|
return(true);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_CtlCJoyButtonCustom() - The custom button routine for joystick
|
|
// calibration
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static boolean
|
|
USL_CtlCJoyButtonCustom(UserCall call,word i,word n)
|
|
{
|
|
word joy,
|
|
minx,maxx,
|
|
miny,maxy;
|
|
|
|
i++,n++; // Shut the compiler up
|
|
|
|
if (call != uic_Hit)
|
|
return(false);
|
|
|
|
IN_ClearKeysDown();
|
|
joy = USL_FindDown(CtlCPanels) - 1;
|
|
|
|
VW_HideCursor();
|
|
FlushHelp = true;
|
|
fontcolor = F_SECONDCOLOR;
|
|
|
|
USL_ShowHelp("Move Joystick to the Upper-Left");
|
|
VW_UpdateScreen();
|
|
while ((LastScan != sc_Escape) && !IN_GetJoyButtonsDB(joy))
|
|
;
|
|
if (LastScan != sc_Escape)
|
|
{
|
|
IN_GetJoyAbs(joy,&minx,&miny);
|
|
while (IN_GetJoyButtonsDB(joy))
|
|
;
|
|
|
|
USL_ShowHelp("Move Joystick to the Lower-Right");
|
|
VW_UpdateScreen();
|
|
while ((LastScan != sc_Escape) && !IN_GetJoyButtonsDB(joy))
|
|
;
|
|
if (LastScan != sc_Escape)
|
|
{
|
|
IN_GetJoyAbs(0,&maxx,&maxy);
|
|
IN_SetupJoy(joy,minx,maxx,miny,maxy);
|
|
}
|
|
}
|
|
|
|
if (LastScan != sc_Escape)
|
|
while (IN_GetJoyButtonsDB(joy))
|
|
;
|
|
|
|
if (LastScan)
|
|
IN_ClearKeysDown();
|
|
|
|
fontcolor = F_BLACK;
|
|
VW_ShowCursor();
|
|
|
|
return(false);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_ClearBottom() - Clears the bottom part of the window
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static void
|
|
USL_ClearBottom(void)
|
|
{
|
|
WindowRec wr;
|
|
|
|
US_SaveWindow(&wr);
|
|
US_RestoreWindow(&BottomWindow);
|
|
|
|
US_ClearWindow();
|
|
|
|
US_RestoreWindow(&wr);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_FormatHelp() - Formats helptext. Runs through and calculates the
|
|
// number of lines, and the offset for the start of each line. Stops
|
|
// after len bytes or when it hits a tilde ('~'). Munges the text.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static word
|
|
USL_FormatHelp(char far *text,long len)
|
|
{
|
|
word line,
|
|
w,h,
|
|
far *off;
|
|
char c,
|
|
far *s,far *l,far *le;
|
|
|
|
WindowX += 4;
|
|
WindowW -= 4;
|
|
|
|
MM_GetPtr(&LineOffsets,MaxHelpLines * sizeof(word));
|
|
off = (word far *)LineOffsets;
|
|
for (line = 0,le = l = s = text;(s - text < len) && (*s != '~');s++)
|
|
{
|
|
if ((c = *s) == '\n')
|
|
{
|
|
*s = '\0';
|
|
*off++ = l - text; // Save offset of start of line
|
|
line++; // Bump line number
|
|
le = l = s + 1; // Set start of line ptr
|
|
}
|
|
|
|
if (c == '\r')
|
|
c = *s = ' ';
|
|
if // Strip orphaned spaces
|
|
(
|
|
(c == ' ')
|
|
&& (s == l)
|
|
&& (*(s - 1) == '\0')
|
|
&& (*(s + 1) != ' ')
|
|
&& (s > text)
|
|
)
|
|
le = l = s + 1;
|
|
else if (c == ' ')
|
|
{
|
|
*s = '\0';
|
|
USL_MeasureString(l,&w,&h);
|
|
if (w >= WindowW) // If string width exceeds window,
|
|
{
|
|
*s = c; // Replace null char with proper char
|
|
*le = '\0'; // Go back to last line end
|
|
*off++ = l - text; // Save offset of start of line
|
|
line++; // Bump line number
|
|
l = s = le + 1; // Start next time through after last line end
|
|
}
|
|
else
|
|
{
|
|
*s = c; // Width still ok - put char back
|
|
le = s; // And save ptr to last ok end of word
|
|
}
|
|
}
|
|
}
|
|
|
|
WindowX -= 4;
|
|
WindowW += 4;
|
|
|
|
return(line);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_DrawHelp() - Draws helptext in the current window
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static void
|
|
USL_DrawHelp(char far *text,word start,word end,word line,word h,word far *lp)
|
|
{
|
|
px = WindowX + 4;
|
|
py = WindowY + (line * h);
|
|
for (lp += start;start < end;start++,px = WindowX + 4,py += h)
|
|
USL_DrawString(text + *lp++);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_DoHelp() - Formats and displays the specified help
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static void
|
|
USL_DoHelp(memptr text,long len)
|
|
{
|
|
boolean done,
|
|
moved;
|
|
int scroll;
|
|
word i,
|
|
pixdiv,
|
|
w,h,
|
|
lines,cur,page,
|
|
top,num,loc,
|
|
far *lp,
|
|
base,srcbase,destbase;
|
|
ScanCode waitkey;
|
|
longword lasttime;
|
|
WindowRec wr;
|
|
CursorInfo info;
|
|
|
|
USL_ShowHelp("Arrow Keys Move / Escape Exits");
|
|
fontcolor = F_BLACK;
|
|
|
|
US_SaveWindow(&wr);
|
|
US_RestoreWindow(&BottomWindow);
|
|
US_ClearWindow();
|
|
|
|
VW_HideCursor();
|
|
VW_UpdateScreen();
|
|
|
|
lines = USL_FormatHelp((char far *)text,len);
|
|
USL_MeasureString("",&w,&h);
|
|
page = WindowH / h;
|
|
cur = 0;
|
|
lp = LineOffsets;
|
|
|
|
IN_ClearKeysDown();
|
|
moved = true;
|
|
lasttime = 0;
|
|
scroll = 0;
|
|
done = false;
|
|
waitkey = sc_None;
|
|
while (!done)
|
|
{
|
|
if (moved)
|
|
{
|
|
while (TimeCount - lasttime < 5)
|
|
;
|
|
lasttime = TimeCount;
|
|
|
|
if (scroll == -1)
|
|
{
|
|
top = cur;
|
|
num = 1;
|
|
loc = 0;
|
|
}
|
|
else if (scroll == +1)
|
|
{
|
|
num = 1;
|
|
loc = page - 1;
|
|
top = cur + loc;
|
|
}
|
|
else
|
|
{
|
|
top = cur;
|
|
num = (page < lines)? page : lines;
|
|
loc = 0;
|
|
}
|
|
if (scroll)
|
|
{
|
|
if (grmode == CGAGR)
|
|
{
|
|
pixdiv = 4;
|
|
base = bufferofs + panadjust + (WindowX / pixdiv);
|
|
}
|
|
else if (grmode == EGAGR)
|
|
{
|
|
VWB_Bar(WindowX,WindowY + (loc * h),WindowW,num * h,WHITE);
|
|
USL_DrawHelp((char far *)text,top,top + num,loc,h,lp);
|
|
|
|
pixdiv = 8;
|
|
base = displayofs + panadjust + (WindowX / pixdiv);
|
|
}
|
|
else if (grmode == VGAGR)
|
|
pixdiv = 1;
|
|
|
|
if (scroll == 1)
|
|
{
|
|
srcbase = base + ylookup[WindowY + h];
|
|
destbase = base + ylookup[WindowY];
|
|
if (grmode == EGAGR)
|
|
{
|
|
EGAWRITEMODE(1);
|
|
VW_WaitVBL(1);
|
|
}
|
|
VW_ScreenToScreen(srcbase,destbase,WindowW / pixdiv,
|
|
WindowH - h);
|
|
}
|
|
else
|
|
{
|
|
i = WindowY + (h * (page - 1));
|
|
srcbase = base + ylookup[i - h];
|
|
destbase = base + ylookup[i];
|
|
base = ylookup[h];
|
|
for (i = page - 1;i;i--,srcbase -= base,destbase -= base)
|
|
VW_ScreenToScreen(srcbase,destbase,WindowW / pixdiv,h);
|
|
}
|
|
if (grmode == CGAGR)
|
|
{
|
|
VWB_Bar(WindowX,WindowY + (loc * h),WindowW,num * h,WHITE);
|
|
USL_DrawHelp((char far *)text,top,top + num,loc,h,lp);
|
|
VW_UpdateScreen();
|
|
}
|
|
else if (grmode == EGAGR)
|
|
{
|
|
base = panadjust + (WindowX / pixdiv) +
|
|
ylookup[WindowY + (loc * h)];
|
|
VW_ScreenToScreen(base + bufferofs,base + displayofs,
|
|
WindowW / pixdiv,h);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
US_ClearWindow();
|
|
USL_DrawHelp((char far *)text,top,top + num,loc,h,lp);
|
|
VW_UpdateScreen();
|
|
}
|
|
|
|
moved = false;
|
|
scroll = 0;
|
|
}
|
|
|
|
if (waitkey)
|
|
while (IN_KeyDown(waitkey))
|
|
;
|
|
waitkey = sc_None;
|
|
|
|
IN_ReadCursor(&info);
|
|
if (info.y < 0)
|
|
{
|
|
if (cur > 0)
|
|
{
|
|
scroll = -1;
|
|
cur--;
|
|
moved = true;
|
|
}
|
|
}
|
|
else if (info.y > 0)
|
|
{
|
|
if (cur + page < lines)
|
|
{
|
|
scroll = +1;
|
|
cur++;
|
|
moved = true;
|
|
}
|
|
}
|
|
else if (info.button0 || info.button1)
|
|
done = true;
|
|
else if (IN_KeyDown(LastScan))
|
|
{
|
|
switch (LastScan)
|
|
{
|
|
case sc_Escape:
|
|
done = true;
|
|
break;
|
|
case sc_UpArrow:
|
|
if (cur > 0)
|
|
{
|
|
scroll = -1;
|
|
cur--;
|
|
moved = true;
|
|
}
|
|
break;
|
|
case sc_DownArrow:
|
|
if (cur + page < lines)
|
|
{
|
|
scroll = +1;
|
|
cur++;
|
|
moved = true;
|
|
}
|
|
break;
|
|
case sc_PgUp:
|
|
if (cur > page)
|
|
cur -= page;
|
|
else
|
|
cur = 0;
|
|
moved = true;
|
|
waitkey = sc_PgUp;
|
|
break;
|
|
case sc_PgDn:
|
|
if (cur + page < lines)
|
|
{
|
|
cur += page;
|
|
if (cur + page >= lines)
|
|
cur = lines - page;
|
|
moved = true;
|
|
}
|
|
waitkey = sc_PgDn;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
IN_ClearKeysDown();
|
|
do
|
|
{
|
|
IN_ReadCursor(&info);
|
|
} while (info.button0 || info.button1);
|
|
|
|
VW_ShowCursor();
|
|
US_ClearWindow();
|
|
VW_UpdateScreen();
|
|
US_RestoreWindow(&wr);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_CtlHButtonCustom() - The custom routine for all of the help buttons
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static boolean
|
|
USL_CtlHButtonCustom(UserCall call,word i,word n)
|
|
{
|
|
word j;
|
|
UserItem *ip;
|
|
|
|
if (call != uic_Hit)
|
|
return(false);
|
|
|
|
ip = &TheItems[i][n];
|
|
if (ip->sel & ui_Disabled)
|
|
return(false);
|
|
|
|
ip->sel |= ui_Selected;
|
|
USL_DrawItem(i,n);
|
|
|
|
USL_ClearBottom();
|
|
|
|
fontcolor = F_SECONDCOLOR;
|
|
USL_ShowHelp("Loading & Formatting Text...");
|
|
VW_UpdateScreen();
|
|
|
|
#ifdef HELPTEXTLINKED // Ugly hack because of lack of disk space...
|
|
{
|
|
extern char far gametext,far context,far story;
|
|
char far *buf;
|
|
memptr dupe;
|
|
|
|
switch (n)
|
|
{
|
|
case 0:
|
|
buf = &gametext;
|
|
break;
|
|
case 1:
|
|
buf = &context;
|
|
break;
|
|
case 2:
|
|
buf = &story;
|
|
break;
|
|
}
|
|
|
|
MM_GetPtr(&dupe,5000);
|
|
_fmemcpy((char far *)dupe,buf,5000);
|
|
|
|
USL_DoHelp(dupe,5000);
|
|
|
|
MM_FreePtr(&dupe);
|
|
if (LineOffsets)
|
|
MM_FreePtr(&LineOffsets);
|
|
}
|
|
#else
|
|
{
|
|
char *name;
|
|
int file;
|
|
long len;
|
|
memptr buf;
|
|
|
|
switch (n)
|
|
{
|
|
case 0:
|
|
name = "GAMETEXT."EXTENSION;
|
|
break;
|
|
case 1:
|
|
name = "CONTEXT."EXTENSION;
|
|
break;
|
|
case 2:
|
|
name = "STORY."EXTENSION;
|
|
break;
|
|
default:
|
|
Quit("Bad help button number");
|
|
}
|
|
|
|
if ((file = open(name,O_RDONLY | O_TEXT)) == -1)
|
|
USL_HandleError(errno);
|
|
else
|
|
{
|
|
len = filelength(file);
|
|
MM_GetPtr(&buf,len);
|
|
|
|
if (CA_FarRead(file,(byte far *)buf,len))
|
|
USL_DoHelp(buf,len);
|
|
else
|
|
USL_HandleError(errno);
|
|
|
|
close(file);
|
|
MM_FreePtr(&buf);
|
|
}
|
|
|
|
if (LineOffsets)
|
|
MM_FreePtr(&LineOffsets);
|
|
}
|
|
#endif
|
|
|
|
fontcolor = F_BLACK;
|
|
|
|
ip->sel &= ~ui_Selected;
|
|
USL_DrawItem(i,n);
|
|
|
|
return(false);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_CtlDButtonCustom() - The custom routine for all of the disk buttons.
|
|
// Sets up the bottom area of the window with the appropriate buttons
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static boolean
|
|
USL_CtlDButtonCustom(UserCall call,word i,word n)
|
|
{
|
|
word j;
|
|
UserItem *ip;
|
|
|
|
if (call != uic_Hit)
|
|
return(false);
|
|
|
|
ip = &TheItems[i][n];
|
|
if (ip->sel & ui_Disabled)
|
|
return(false);
|
|
|
|
USL_ClearBottom();
|
|
|
|
j = 0;
|
|
TheItems[i + 1] = ip = n? CtlDEPanels : CtlDLSPanels;
|
|
while (ip && (ip->type != uii_Bad))
|
|
{
|
|
USL_DrawItem(i + 1,j++);
|
|
ip++;
|
|
}
|
|
|
|
return(false);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_DLSRect() - Draw the rectangle for the save game names
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static Rect
|
|
USL_DLSRect(UserItem *ip)
|
|
{
|
|
Rect r;
|
|
|
|
r.ul.x = ip->r.lr.x + 40 + 2;
|
|
r.ul.y = ip->r.ul.y + 2;
|
|
r.lr.x = WindowX + WindowW - 8 - 2;
|
|
r.lr.y = ip->r.lr.y - 2;
|
|
|
|
VWB_Bar(r.ul.x,r.ul.y,r.lr.x - r.ul.x,r.lr.y - r.ul.y,WHITE);
|
|
|
|
VWB_Hlin(r.ul.x,r.lr.x,r.ul.y,BLACK);
|
|
VWB_Hlin(r.ul.x,r.lr.x,r.lr.y,BLACK);
|
|
VWB_Vlin(r.ul.y,r.lr.y,r.ul.x,BLACK);
|
|
VWB_Vlin(r.ul.y,r.lr.y,r.lr.x,BLACK);
|
|
|
|
px = r.ul.x + 2;
|
|
py = r.ul.y + 2;
|
|
|
|
return(r);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_CtlDLButtonCustom() - The load game custom routine
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static boolean
|
|
USL_CtlDLButtonCustom(UserCall call,word i,word n)
|
|
{
|
|
char *filename,
|
|
msg[MaxGameName + 12];
|
|
word err;
|
|
int file;
|
|
UserItem *ip;
|
|
SaveGame *game;
|
|
WindowRec wr;
|
|
|
|
// DEBUG - deal with warning user about loading a game causing abort
|
|
|
|
game = &Games[n / 2];
|
|
ip = &TheItems[i][n];
|
|
|
|
switch (call)
|
|
{
|
|
case uic_Draw:
|
|
if (!loadedgame)
|
|
{
|
|
USL_DLSRect(ip);
|
|
fontcolor = game->present? F_BLACK : F_FIRSTCOLOR;
|
|
USL_DrawString(game->present? game->name : "Empty");
|
|
fontcolor = F_BLACK;
|
|
}
|
|
break;
|
|
case uic_Hit:
|
|
if (ip->sel & ui_Disabled)
|
|
return(false);
|
|
|
|
LeaveDriveOn++;
|
|
filename = USL_GiveSaveName(n / 2);
|
|
|
|
US_SaveWindow(&wr);
|
|
US_CenterWindow(30,3);
|
|
strcpy(msg,"Loading `");
|
|
strcat(msg,game->name);
|
|
strcat(msg,"\'");
|
|
US_PrintCentered(msg);
|
|
VW_HideCursor();
|
|
VW_UpdateScreen();
|
|
|
|
err = 0;
|
|
if ((file = open(filename,O_BINARY | O_RDONLY)) != -1)
|
|
{
|
|
if (read(file,game,sizeof(*game)) == sizeof(*game))
|
|
{
|
|
if (USL_LoadGame)
|
|
if (!USL_LoadGame(file))
|
|
USL_HandleError(err = errno);
|
|
}
|
|
else
|
|
USL_HandleError(err = errno);
|
|
close(file);
|
|
}
|
|
else
|
|
USL_HandleError(err = errno);
|
|
if (err)
|
|
abortgame = true;
|
|
else
|
|
loadedgame = true;
|
|
game->present = true;
|
|
|
|
if (loadedgame)
|
|
Paused = true;
|
|
|
|
VW_ShowCursor();
|
|
US_RestoreWindow(&wr);
|
|
|
|
LeaveDriveOn--;
|
|
break;
|
|
}
|
|
return(false);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_CtlDSButtonCustom() - The save game custom routine
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static boolean
|
|
USL_CtlDSButtonCustom(UserCall call,word i,word n)
|
|
{
|
|
boolean ok;
|
|
char *filename;
|
|
word err;
|
|
int file;
|
|
Rect r;
|
|
UserItem *ip;
|
|
SaveGame *game;
|
|
WindowRec wr;
|
|
|
|
if (call != uic_Hit)
|
|
return(false);
|
|
|
|
game = &Games[n / 2];
|
|
ip = &TheItems[i][n];
|
|
if (ip->sel & ui_Disabled)
|
|
return(false);
|
|
|
|
FlushHelp = true;
|
|
fontcolor = F_SECONDCOLOR;
|
|
USL_ShowHelp("Enter Game Name / Escape Aborts");
|
|
fontcolor = F_BLACK;
|
|
|
|
r = USL_DLSRect(ip - 1);
|
|
ok = US_LineInput(px,py,game->name,game->present? game->name : nil,true,
|
|
MaxGameName,r.lr.x - r.ul.x - 8);
|
|
if (!strlen(game->name))
|
|
strcpy(game->name,"Untitled");
|
|
if (ok)
|
|
{
|
|
US_SaveWindow(&wr);
|
|
US_CenterWindow(10,3);
|
|
US_PrintCentered("Saving");
|
|
VW_HideCursor();
|
|
VW_UpdateScreen();
|
|
|
|
LeaveDriveOn++;
|
|
filename = USL_GiveSaveName(n / 2);
|
|
err = 0;
|
|
file = open(filename,O_CREAT | O_BINARY | O_WRONLY,
|
|
S_IREAD | S_IWRITE | S_IFREG);
|
|
if (file != -1)
|
|
{
|
|
if (write(file,game,sizeof(*game)) == sizeof(*game))
|
|
{
|
|
if (USL_SaveGame)
|
|
ok = USL_SaveGame(file);
|
|
if (!ok)
|
|
USL_HandleError(err = errno);
|
|
}
|
|
else
|
|
USL_HandleError(err = ((errno == ENOENT)? ENOMEM : errno));
|
|
close(file);
|
|
}
|
|
else
|
|
USL_HandleError(err = ((errno == ENOENT)? ENOMEM : errno));
|
|
if (err)
|
|
{
|
|
remove(filename);
|
|
ok = false;
|
|
}
|
|
LeaveDriveOn--;
|
|
|
|
VW_ShowCursor();
|
|
US_RestoreWindow(&wr);
|
|
USL_DoHit(i - 1,0);
|
|
VW_UpdateScreen();
|
|
}
|
|
|
|
if (!game->present)
|
|
game->present = ok;
|
|
|
|
if (ok)
|
|
{
|
|
GameIsDirty = false;
|
|
(ip - 1)->sel &= ~ui_Disabled;
|
|
}
|
|
|
|
USL_DrawItem(i,n - 1);
|
|
// USL_CtlDLButtonCustom(uic_Draw,i,n - 1);
|
|
|
|
return(true);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_CtlSButtonCustom() - The custom routine for all of the sound buttons
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static boolean
|
|
USL_CtlSButtonCustom(UserCall call,word i,word n)
|
|
{
|
|
word j;
|
|
UserItem *ip;
|
|
|
|
if (call != uic_Hit)
|
|
return(false);
|
|
|
|
ip = &TheItems[i][n];
|
|
if (ip->sel & ui_Disabled)
|
|
return(false);
|
|
|
|
USL_ClearBottom();
|
|
|
|
if (n == sdm_SoundSource)
|
|
{
|
|
j = 0;
|
|
TheItems[i + 1] = ip = CtlSSSPanels;
|
|
while (ip && (ip->type != uii_Bad))
|
|
{
|
|
USL_DrawItem(i + 1,j++);
|
|
ip++;
|
|
}
|
|
}
|
|
else
|
|
TheItems[i + 1] = nil;
|
|
|
|
return(false);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_CtlPButtonCustom() - The custom routine for all of the start game btns
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static boolean
|
|
USL_CtlPButtonCustom(UserCall call,word i,word n)
|
|
{
|
|
word j;
|
|
UserItem *ip;
|
|
|
|
if (call != uic_Hit)
|
|
return(false);
|
|
|
|
ip = &TheItems[i][n];
|
|
if (ip->sel & ui_Disabled)
|
|
return(false);
|
|
|
|
USL_ClearBottom();
|
|
|
|
j = 0;
|
|
TheItems[i + 1] = ip = n? CtlPRPanels : CtlPSPanels;
|
|
while (ip && (ip->type != uii_Bad))
|
|
{
|
|
USL_DrawItem(i + 1,j++);
|
|
ip++;
|
|
}
|
|
|
|
return(false);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_GiveAbortWarning() - Draws a string that warns the user that an
|
|
// action they're about to take will abort the game in progress
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static void
|
|
USL_GiveAbortWarning(void)
|
|
{
|
|
WindowRec wr;
|
|
|
|
if (!GameIsDirty)
|
|
return;
|
|
|
|
US_SaveWindow(&wr);
|
|
US_RestoreWindow(&BottomWindow);
|
|
US_HomeWindow();
|
|
PrintY += 5;
|
|
|
|
VWB_Bar(WindowX,WindowY,WindowW,30,WHITE);
|
|
fontcolor = F_SECONDCOLOR;
|
|
US_CPrint("Warning! If you do this, you'll");
|
|
US_CPrint("abort the current game.");
|
|
fontcolor = F_BLACK;
|
|
|
|
US_RestoreWindow(&wr);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_CtlPSButtonCustom() - The custom routine for the start game button
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static boolean
|
|
USL_CtlPSButtonCustom(UserCall call,word i,word n)
|
|
{
|
|
boolean result;
|
|
UserItem *ip;
|
|
|
|
i++; // Shut the compiler up
|
|
|
|
switch (call)
|
|
{
|
|
case uic_Hit:
|
|
switch (n)
|
|
{
|
|
case 0:
|
|
restartgame = gd_Normal;
|
|
break;
|
|
case 1:
|
|
restartgame = gd_Easy;
|
|
break;
|
|
case 2:
|
|
restartgame = gd_Hard;
|
|
break;
|
|
}
|
|
if (restartgame && ingame && USL_ResetGame)
|
|
USL_ResetGame();
|
|
result = false;
|
|
break;
|
|
case uic_Draw:
|
|
USL_GiveAbortWarning();
|
|
result = false;
|
|
break;
|
|
default:
|
|
result = false;
|
|
break;
|
|
}
|
|
return(result);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_CtlPRButtonCustom() - The custom routine for the resume game button
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static boolean
|
|
USL_CtlPRButtonCustom(UserCall call,word i,word n)
|
|
{
|
|
if (call != uic_Hit)
|
|
return(false);
|
|
|
|
i++,n++; // Shut the compiler up
|
|
ResumeGame = true;
|
|
return(false);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_CtlDEButtonCustom() - The custom routine for the exit to DOS button
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static boolean
|
|
USL_CtlDEButtonCustom(UserCall call,word i,word n)
|
|
{
|
|
boolean result;
|
|
UserItem *ip;
|
|
|
|
i++,n++; // Shut the compiler up
|
|
|
|
switch (call)
|
|
{
|
|
case uic_Hit:
|
|
QuitToDos = true;
|
|
break;
|
|
case uic_Draw:
|
|
USL_GiveAbortWarning();
|
|
default:
|
|
result = false;
|
|
break;
|
|
}
|
|
return(result);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_CtlCButtonCustom() - The custom routine for all of the control
|
|
// buttons
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static boolean
|
|
USL_CtlCButtonCustom(UserCall call,word i,word n)
|
|
{
|
|
word j;
|
|
Point p;
|
|
UserItem *ip;
|
|
|
|
if (call != uic_Hit)
|
|
return(false);
|
|
|
|
ip = &TheItems[i][n];
|
|
if (ip->sel & ui_Disabled)
|
|
return(false);
|
|
|
|
USL_ClearBottom();
|
|
if (n == 0) // Keyboard
|
|
{
|
|
TheItems[i + 1] = ip = CtlCKbdPanels;
|
|
p = CtlCKbdPanels[2].r.lr;
|
|
VWB_DrawPic(p.x,p.y,CTL_DIRSPIC);
|
|
}
|
|
else
|
|
TheItems[i + 1] = ip = CtlCJoyPanels;
|
|
|
|
j = 0;
|
|
while (ip && (ip->type != uii_Bad))
|
|
{
|
|
USL_DrawItem(i + 1,j++);
|
|
ip++;
|
|
}
|
|
|
|
return(false);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_HitHotKey() - After a hotkey was hit, move the cursor to the first
|
|
// selected item in the group after the group containing the item
|
|
// holding the hotkey
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static void
|
|
USL_HitHotKey(int i,int n)
|
|
{
|
|
UserItem *ip;
|
|
|
|
if (ip = TheItems[++i])
|
|
{
|
|
if ((n = USL_FindDown(TheItems[i])) == -1)
|
|
n = 0;
|
|
ip += n;
|
|
CursorX = ip->r.lr.x - 8;
|
|
CursorY = ip->r.lr.y - 8;
|
|
CursorBad = true;
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_CheckScan() - Checks to see if the scancode in LastScan corresponds
|
|
// to anything in the list of useritems. If so, selects the item.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static boolean
|
|
USL_CheckScan(word *ci,word *cn)
|
|
{
|
|
word i,n;
|
|
UserItem *ip;
|
|
|
|
if (!LastScan)
|
|
return(false);
|
|
|
|
#if 1 // DEBUG - probably kill this code
|
|
// Use 1..? for the items across the top row
|
|
if (TheItems[1] && !IN_KeyDown(sc_RShift))
|
|
{
|
|
for (i = 0,ip = TheItems[1];(ip->type != uii_Bad) && (i < 9);i++,ip++)
|
|
;
|
|
for (n = 0;n < i;n++)
|
|
{
|
|
if (LastScan == 2 + n) // Numbers from 1..9
|
|
{
|
|
if (!(TheItems[1][n].sel & ui_Disabled))
|
|
{
|
|
LastScan = sc_None;
|
|
USL_DoHit(1,n);
|
|
return(true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Use Alt-1..6 for the items in the leftmost column
|
|
if (IN_KeyDown(sc_RShift))
|
|
{
|
|
n = LastScan - 2;
|
|
if (n < 6) // Numbers from 1..6
|
|
{
|
|
USL_DoHit(0,n);
|
|
LastScan = sc_None;
|
|
return(true);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// Check normal hotkeys for the leftmost column
|
|
for (i = 0;CtlPanels[i].type != uii_Bad;i++)
|
|
{
|
|
if (CtlPanels[i].key == LastScan)
|
|
{
|
|
LastScan = sc_None;
|
|
USL_DoHit(0,i);
|
|
*ci = 0;
|
|
*cn = i;
|
|
USL_HitHotKey(0,i);
|
|
return(true);
|
|
}
|
|
}
|
|
|
|
// Check normal hotkeys for the top row
|
|
for (i = 0;i < 6;i++)
|
|
{
|
|
for (n = 0,ip = CtlPanels2[i];ip && ip->type != uii_Bad;n++,ip++)
|
|
{
|
|
if ((ip->key == LastScan) && !(ip->sel & ui_Disabled))
|
|
{
|
|
LastScan = sc_None;
|
|
USL_DoHit(0,i);
|
|
USL_DoHit(1,n);
|
|
*ci = 1;
|
|
*cn = n;
|
|
USL_HitHotKey(1,n);
|
|
return(true);
|
|
}
|
|
}
|
|
}
|
|
return(false);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_SetUpCtlPanel() - Sets the states of the UserItems to reflect the
|
|
// values of all the appropriate variables
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static void
|
|
USL_SetUpCtlPanel(void)
|
|
{
|
|
word i,j;
|
|
|
|
GameIsDirty = ingame;
|
|
|
|
// Set up restart game
|
|
USL_TurnOff(CtlPPanels);
|
|
CtlPPanels[0].sel = ingame? ui_Normal : ui_Selected;
|
|
CtlPPanels[1].sel = ingame? ui_Selected : ui_Disabled;
|
|
|
|
// Set up disk stuff - default to load/save game
|
|
USL_TurnOff(CtlDPanels);
|
|
CtlDPanels[0].sel = ui_Selected;
|
|
|
|
// Set up load/save buttons
|
|
USL_TurnOff(CtlDLSPanels);
|
|
for (i = 0;i < MaxSaveGames;i++)
|
|
{
|
|
if (!Games[i].present)
|
|
CtlDLSPanels[i * 2].sel = ui_Disabled;
|
|
if (!ingame)
|
|
CtlDLSPanels[(i * 2) + 1].sel = ui_Disabled;
|
|
}
|
|
|
|
// Set up Controls
|
|
USL_TurnOff(CtlCPanels);
|
|
CtlCPanels[1].sel = JoysPresent[0]? ui_Normal : ui_Disabled;
|
|
CtlCPanels[2].sel = JoysPresent[1]? ui_Normal : ui_Disabled;
|
|
if (Controls[0] == ctrl_Keyboard)
|
|
i = 0;
|
|
else
|
|
i = (Controls[0] == ctrl_Joystick1)? 1 : 2;
|
|
CtlCPanels[i].sel |= ui_Selected;
|
|
if (JoysPresent[1] && !JoysPresent[0])
|
|
CtlCPanels[2].key = sc_F4;
|
|
else
|
|
CtlCPanels[1].key = sc_F4;
|
|
|
|
// Set up Keyboard
|
|
for (i = 0;i < 10;i++)
|
|
CtlCKbdPanels[i].text = IN_GetScanName(*(KeyMaps[i]));
|
|
|
|
// Set up Sounds
|
|
USL_TurnOff(CtlSPanels);
|
|
CtlSPanels[sdm_AdLib].sel = AdLibPresent? ui_Normal : ui_Disabled;
|
|
#if 0 // DEBUG - hack because no space for digitized sounds on Keen Dreams
|
|
CtlSPanels[sdm_SoundBlaster].sel =
|
|
SoundBlasterPresent? ui_Normal : ui_Disabled;
|
|
CtlSPanels[sdm_SoundSource].sel =
|
|
SoundSourcePresent? ui_Normal : ui_Disabled;
|
|
#else
|
|
CtlSPanels[sdm_SoundBlaster].sel = ui_Disabled;
|
|
CtlSPanels[sdm_SoundSource].sel = ui_Disabled;
|
|
#endif
|
|
CtlSPanels[SoundMode].sel |= ui_Selected;
|
|
|
|
// Set up SoundSource
|
|
USL_TurnOff(CtlSSSPanels);
|
|
CtlSSSPanels[0].sel = ssIsTandy? ui_Selected : ui_Normal;
|
|
CtlSSSPanels[1].sel = (ssPort == 2)? ui_Selected : ui_Normal;
|
|
|
|
// Set up Music
|
|
USL_TurnOff(CtlMPanels);
|
|
CtlMPanels[smm_AdLib].sel = AdLibPresent? ui_Normal : ui_Disabled;
|
|
CtlMPanels[MusicMode].sel |= ui_Selected;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// USL_TearDownCtlPanel() - Given the state of the control panel, sets the
|
|
// modes and values as appropriate
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
static void
|
|
USL_TearDownCtlPanel(void)
|
|
{
|
|
int i;
|
|
|
|
i = USL_FindDown(CtlCPanels);
|
|
if (i != -1)
|
|
{
|
|
i = i? (i == 1? ctrl_Joystick1 : ctrl_Joystick2) : ctrl_Keyboard;
|
|
IN_SetControlType(0,i);
|
|
}
|
|
|
|
CtlCPanels[1].key = CtlCPanels[2].key = sc_None;
|
|
|
|
i = USL_FindDown(CtlSPanels);
|
|
if (i != -1)
|
|
SD_SetSoundMode(i);
|
|
|
|
ssIsTandy = CtlSSSPanels[0].sel & ui_Selected;
|
|
ssPort = (CtlSSSPanels[1].sel & ui_Selected)? 2 : 1;
|
|
|
|
i = USL_FindDown(CtlMPanels);
|
|
if (i != -1)
|
|
{
|
|
SD_SetMusicMode(i);
|
|
|
|
if (!QuitToDos)
|
|
{
|
|
US_CenterWindow(20,8);
|
|
US_CPrint("Loading");
|
|
#if 0
|
|
fontcolor = F_SECONDCOLOR;
|
|
US_CPrint("Sounds");
|
|
fontcolor = F_BLACK;
|
|
#endif
|
|
VW_UpdateScreen();
|
|
|
|
CA_LoadAllSounds();
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// US_ControlPanel() - This is the main routine for the control panel
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
void
|
|
US_ControlPanel(void)
|
|
{
|
|
char gamename[MaxGameName + 10 + 1];
|
|
ScanCode c;
|
|
boolean done,
|
|
buttondown,inrect;
|
|
word hiti,hitn,
|
|
i,n,
|
|
lasti,lastn,
|
|
lastx,lasty;
|
|
longword lasttime;
|
|
Point p;
|
|
Rect userect;
|
|
UserItem *ip;
|
|
|
|
c = LastScan;
|
|
if (c == sc_Escape) // Map escape from game to Exit to DOS
|
|
c = sc_Q;
|
|
|
|
CA_UpLevel();
|
|
for (i = CONTROLS_LUMP_START;i <= CONTROLS_LUMP_END;i++)
|
|
CA_MarkGrChunk(i);
|
|
CA_MarkGrChunk(CTL_LITTLEMASKPICM);
|
|
CA_MarkGrChunk(CTL_LSMASKPICM);
|
|
CA_CacheMarks("Options Screen");
|
|
|
|
USL_SetUpCtlPanel();
|
|
|
|
US_SetPrintRoutines(VW_MeasurePropString,VWB_DrawPropString);
|
|
fontcolor = F_BLACK;
|
|
|
|
VW_InitDoubleBuffer();
|
|
|
|
VWB_Bar(0,0,MaxX,MaxY,FIRSTCOLOR);
|
|
US_DrawWindow(8,22,30,2);
|
|
US_SaveWindow(&HelpWindow);
|
|
US_DrawWindow(8,7,30,14);
|
|
US_SaveWindow(&BottomWindow);
|
|
US_DrawWindow(8,1,30,20);
|
|
|
|
for (ip = CtlPanels;ip->type != uii_Bad;ip++)
|
|
VWB_DrawPic(ip->r.ul.x,ip->r.ul.y,ip->picup);
|
|
|
|
US_StartCursor();
|
|
CursorX = (8 * 8) + ((MaxX - (8 * 8)) / 2);
|
|
CursorBad = true;
|
|
|
|
CtlPanelButton = -1;
|
|
LastScan = c;
|
|
USL_CheckScan(&i,&n);
|
|
if (CtlPanelButton == -1)
|
|
USL_DoHit(0,0);
|
|
|
|
ResumeGame = false;
|
|
done = false;
|
|
FlushHelp = true;
|
|
lastx = lasty = -1;
|
|
while
|
|
(
|
|
(restartgame == gd_Continue)
|
|
&& !(done || loadedgame || ResumeGame)
|
|
)
|
|
{
|
|
VW_UpdateScreen();
|
|
|
|
buttondown = US_UpdateCursor();
|
|
inrect = USL_IsInRect(CursorX,CursorY,&i,&n);
|
|
|
|
if (FlushHelp)
|
|
{
|
|
lasti = -2;
|
|
lasttime = TimeCount;
|
|
FlushHelp = false;
|
|
}
|
|
if (inrect)
|
|
{
|
|
if ((lasti != i) || (lastn != n))
|
|
{
|
|
// If over a Load button
|
|
if
|
|
(
|
|
(CtlPanelButton == 2)
|
|
&& (i == 2)
|
|
&& (TheItems[1][0].sel & ui_Selected)
|
|
&& (Games[n / 2].present)
|
|
&& !(n & 1)
|
|
)
|
|
{
|
|
strcpy(gamename,"Load `");
|
|
strcat(gamename,Games[n / 2].name);
|
|
strcat(gamename,"'");
|
|
USL_ShowHelp(gamename);
|
|
}
|
|
else
|
|
USL_ShowHelp(TheItems[i][n].help);
|
|
lasti = i;
|
|
lastn = n;
|
|
}
|
|
}
|
|
else if (lasti != (word)-1)
|
|
{
|
|
USL_ShowHelp("Select a Button");
|
|
lasti = -1;
|
|
}
|
|
|
|
hiti = i;
|
|
hitn = n;
|
|
|
|
if (inrect)
|
|
userect = TheItems[i][n].r;
|
|
else
|
|
{
|
|
userect.ul.x = CursorX;
|
|
userect.ul.y = CursorY;
|
|
userect.lr = userect.ul;
|
|
}
|
|
|
|
if (IN_KeyDown(sc_UpArrow))
|
|
{
|
|
USL_FindRect(userect,motion_None,motion_Up);
|
|
buttondown = false;
|
|
IN_ClearKey(sc_UpArrow);
|
|
}
|
|
else if (IN_KeyDown(sc_DownArrow))
|
|
{
|
|
USL_FindRect(userect,motion_None,motion_Down);
|
|
buttondown = false;
|
|
IN_ClearKey(sc_DownArrow);
|
|
}
|
|
else if (IN_KeyDown(sc_LeftArrow))
|
|
{
|
|
USL_FindRect(userect,motion_Left,motion_None);
|
|
buttondown = false;
|
|
IN_ClearKey(sc_LeftArrow);
|
|
}
|
|
else if (IN_KeyDown(sc_RightArrow))
|
|
{
|
|
USL_FindRect(userect,motion_Right,motion_None);
|
|
buttondown = false;
|
|
IN_ClearKey(sc_RightArrow);
|
|
}
|
|
else if
|
|
(
|
|
IN_KeyDown(c = sc_Return)
|
|
|| IN_KeyDown(c = KbdDefs[0].button0)
|
|
|| IN_KeyDown(c = KbdDefs[0].button1)
|
|
)
|
|
{
|
|
IN_ClearKey(c);
|
|
if (inrect)
|
|
{
|
|
ip = &TheItems[hiti][hitn];
|
|
|
|
if ((ip->type == uii_Button) && !(ip->sel & ui_Disabled))
|
|
{
|
|
lasttime = TimeCount;
|
|
|
|
ip->sel |= ui_Selected;
|
|
USL_DrawItem(hiti,hitn);
|
|
VW_UpdateScreen();
|
|
|
|
while (TimeCount - lasttime < TickBase / 4)
|
|
;
|
|
lasttime = TimeCount;
|
|
|
|
ip->sel &= ~ui_Selected;
|
|
USL_DrawItem(hiti,hitn);
|
|
VW_UpdateScreen();
|
|
|
|
while (TimeCount - lasttime < TickBase / 4)
|
|
;
|
|
}
|
|
|
|
USL_DoHit(hiti,hitn);
|
|
}
|
|
}
|
|
else if (USL_CheckScan(&i,&n))
|
|
;
|
|
else if (buttondown && inrect && USL_TrackItem(hiti,hitn))
|
|
USL_DoHit(hiti,hitn);
|
|
|
|
if (LastScan == sc_Escape)
|
|
{
|
|
IN_ClearKey(sc_Escape);
|
|
done = true;
|
|
}
|
|
|
|
if (QuitToDos)
|
|
done = true;
|
|
|
|
if ((lastx != CursorX) || (lasty != CursorY))
|
|
{
|
|
lastx = CursorX;
|
|
lasty = CursorY;
|
|
lasttime = TimeCount;
|
|
}
|
|
if (TimeCount - lasttime > TickBase * 10)
|
|
{
|
|
if (((TimeCount - lasttime) / TickBase) & 2)
|
|
fontcolor = F_SECONDCOLOR;
|
|
USL_ShowHelp("Press F1 for Help");
|
|
fontcolor = F_BLACK;
|
|
}
|
|
}
|
|
|
|
US_ShutCursor();
|
|
|
|
USL_TearDownCtlPanel();
|
|
|
|
if (restartgame && USL_ResetGame)
|
|
USL_ResetGame();
|
|
|
|
if (QuitToDos)
|
|
{
|
|
if (tedlevel)
|
|
TEDDeath();
|
|
else
|
|
{
|
|
US_CenterWindow(20,3);
|
|
fontcolor = F_SECONDCOLOR;
|
|
US_PrintCentered("Now Exiting to DOS...");
|
|
fontcolor = F_BLACK;
|
|
VW_UpdateScreen();
|
|
Quit(nil);
|
|
}
|
|
}
|
|
|
|
CA_DownLevel();
|
|
}
|
|
|
|
// High score routines
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// US_DisplayHighScores() - Assumes that double buffering has been started.
|
|
// If passed a -1 will just display the high scores, but if passed
|
|
// a non-negative number will display that entry in red and let the
|
|
// user type in a name
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
void
|
|
US_DisplayHighScores(int which)
|
|
{
|
|
char buffer[16],*str;
|
|
word i,
|
|
w,h,
|
|
x,y;
|
|
HighScore *s;
|
|
|
|
US_CenterWindow(30,MaxScores + (MaxScores / 2));
|
|
|
|
x = WindowX + (WindowW / 2);
|
|
US_Print(" Name");
|
|
PrintX = x + 20;
|
|
US_Print("Score");
|
|
PrintX = x + 60;
|
|
US_Print("Done\n\n");
|
|
PrintY -= 3;
|
|
|
|
for (i = WindowX;i < WindowX + WindowW;i += 8)
|
|
VWB_DrawTile8M(i,WindowY + 8,10);
|
|
VWB_DrawTile8M(WindowX - 8,WindowY + 8,9);
|
|
VWB_DrawTile8M(WindowX + WindowW,WindowY + 8,11);
|
|
|
|
for (i = 0,s = Scores;i < MaxScores;i++,s++)
|
|
{
|
|
fontcolor = (i == which)? F_SECONDCOLOR : F_BLACK;
|
|
|
|
if (i != which)
|
|
{
|
|
US_Print(" ");
|
|
if (strlen(s->name))
|
|
US_Print(s->name);
|
|
else
|
|
US_Print("-");
|
|
}
|
|
else
|
|
y = PrintY;
|
|
|
|
PrintX = x + (7 * 8);
|
|
ultoa(s->score,buffer,10);
|
|
for (str = buffer;*str;str++)
|
|
*str = *str + (129 - '0'); // Used fixed-width numbers (129...)
|
|
USL_MeasureString(buffer,&w,&h);
|
|
PrintX -= w;
|
|
US_Print(buffer);
|
|
|
|
PrintX = x + 60;
|
|
if (s->completed)
|
|
US_PrintUnsigned(s->completed);
|
|
else
|
|
US_Print("-");
|
|
|
|
US_Print("\n");
|
|
}
|
|
|
|
if (which != -1)
|
|
{
|
|
fontcolor = F_SECONDCOLOR;
|
|
PrintY = y;
|
|
PrintX = WindowX;
|
|
US_Print(" ");
|
|
strcpy(Scores[which].name,"");
|
|
US_LineInput(PrintX,PrintY,Scores[which].name,nil,true,MaxHighName,
|
|
(WindowW / 2) - 8);
|
|
}
|
|
fontcolor = F_BLACK;
|
|
|
|
VW_UpdateScreen();
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// US_CheckHighScore() - Checks gamestate to see if the just-ended game
|
|
// should be entered in the high score list. If so, lets the user
|
|
// enter their name
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////
|
|
void
|
|
US_CheckHighScore(long score,word other)
|
|
{
|
|
word i,j,
|
|
n;
|
|
HighScore myscore;
|
|
|
|
strcpy(myscore.name,"");
|
|
myscore.score = score;
|
|
myscore.completed = other;
|
|
|
|
for (i = 0,n = -1;i < MaxScores;i++)
|
|
{
|
|
if
|
|
(
|
|
(myscore.score > Scores[i].score)
|
|
|| (
|
|
(myscore.score == Scores[i].score)
|
|
&& (myscore.completed > Scores[i].completed)
|
|
)
|
|
)
|
|
{
|
|
for (j = MaxScores;--j > i;)
|
|
Scores[j] = Scores[j - 1];
|
|
Scores[i] = myscore;
|
|
|
|
n = i;
|
|
HighScoresDirty = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
VW_InitDoubleBuffer();
|
|
VWB_Bar(0,0,MaxX,MaxY,FIRSTCOLOR);
|
|
|
|
US_DisplayHighScores(n);
|
|
IN_UserInput(5 * TickBase,false);
|
|
}
|