2000-03-16 11:25:00 +01:00
|
|
|
#include "3dc.h"
|
|
|
|
|
2001-07-28 23:13:49 +00:00
|
|
|
#include <sys/stat.h>
|
2000-03-16 11:25:00 +01:00
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "inline.h"
|
|
|
|
#include "module.h"
|
|
|
|
|
|
|
|
#include "chnktexi.h"
|
|
|
|
#include "d3d_hud.h"
|
|
|
|
#define UseLocalAssert Yes
|
|
|
|
#include "ourasert.h"
|
|
|
|
#include "hud_layout.h"
|
|
|
|
|
|
|
|
#undef textprint
|
|
|
|
|
|
|
|
#define textprintOn Yes
|
|
|
|
|
|
|
|
#define DHMtextprint Yes
|
|
|
|
/* define to use Dave Malcolm's replacement textprint routines */
|
|
|
|
|
|
|
|
|
|
|
|
/* As specified by Roxby */
|
|
|
|
#define ClearScreenColour 1000
|
|
|
|
|
|
|
|
/*
|
|
|
|
Experiment to try and fix mystery driver problems
|
|
|
|
Don't set with ForceWindowsPalette on!!!
|
|
|
|
Leave this on!!!
|
|
|
|
On some video cards it seems necessary not only to
|
|
|
|
set palette on vblanking interval, but also AFTER
|
|
|
|
D3D initialisation is complete...
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define ChangePaletteOnVBAlways Yes
|
|
|
|
|
|
|
|
/*
|
|
|
|
Turn on or off checking for the validity
|
|
|
|
of a video mode before switching to it.
|
|
|
|
Actually causes problems on some systems
|
|
|
|
because the DirectDraw enumerator fails to
|
|
|
|
report valid modes (although on other systems
|
|
|
|
it can report ones that can't be reached, ho
|
|
|
|
hum), so at least for Chris H. it needs to be
|
|
|
|
turned off.
|
|
|
|
NOTE THAT THIS SHOULD HAVE THE SAME SETTING AS
|
|
|
|
CheckVideoModes at the start of dd_func.cpp, at
|
|
|
|
least until we make it a system.h value or
|
|
|
|
something else sensible...
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define CheckVideoModes No
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
externs for commonly used global variables and arrays
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
extern SHAPEHEADER **mainshapelist;
|
|
|
|
extern SHAPEHEADER *testpaletteshapelist[];
|
|
|
|
extern SCREENDESCRIPTORBLOCK ScreenDescriptorBlock;
|
|
|
|
extern int sine[];
|
|
|
|
extern int cosine[];
|
|
|
|
extern int AdaptiveHazingFlag;
|
|
|
|
extern int *Global_ShapeNormals;
|
|
|
|
extern int *Global_ShapePoints;
|
|
|
|
extern int *ItemPointers[];
|
|
|
|
extern int ItemData[];
|
|
|
|
extern char projectsubdirectory[];
|
|
|
|
|
|
|
|
extern int WinLeftX;
|
|
|
|
extern int WinRightX;
|
|
|
|
extern int WinTopY;
|
|
|
|
extern int WinBotY;
|
|
|
|
|
|
|
|
extern int WindowRequestMode;
|
|
|
|
extern int VideoRequestMode;
|
|
|
|
extern int ZBufferRequestMode;
|
|
|
|
extern int RasterisationRequestMode;
|
|
|
|
extern int SoftwareScanDrawRequestMode;
|
|
|
|
extern int DXMemoryRequestMode;
|
|
|
|
|
|
|
|
extern int TotalVideoMemory;
|
|
|
|
extern int NumAvailableVideoModes;
|
|
|
|
extern VIDEOMODEINFO AvailableVideoModes[];
|
|
|
|
|
|
|
|
extern int memoryInitialisationFailure;
|
|
|
|
|
|
|
|
extern IMAGEHEADER ImageHeaderArray[]; /* Array of Image Headers */
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
Global Variables for PC Watcom Functions
|
|
|
|
and Windows 95!
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Timer */
|
|
|
|
long lastTickCount;
|
|
|
|
|
|
|
|
unsigned char *ScreenBuffer = 0; /* Ensure initialised to Null */
|
|
|
|
|
|
|
|
unsigned char LPTestPalette[1024]; /* to cast to lp*/
|
|
|
|
|
|
|
|
int InputMode;
|
|
|
|
|
|
|
|
int VideoMode;
|
|
|
|
int VideoModeType;
|
|
|
|
int VideoModeTypeScreen;
|
|
|
|
int WindowMode;
|
|
|
|
int ScanDrawMode;
|
|
|
|
int ZBufferMode;
|
|
|
|
int DXMemoryMode;
|
|
|
|
unsigned char AttemptVideoModeRestart;
|
|
|
|
VIDEORESTARTMODES VideoRestartMode;
|
|
|
|
|
|
|
|
PROCESSORTYPES ProcessorType;
|
|
|
|
BOOL MMXAvailable;
|
|
|
|
|
|
|
|
unsigned char *TextureLightingTable = 0;
|
|
|
|
|
|
|
|
unsigned char *PaletteRemapTable = 0;
|
|
|
|
|
|
|
|
int NumShadingTables = 0;
|
|
|
|
|
|
|
|
int NumPaletteShadingTables = 0;
|
|
|
|
|
|
|
|
int FrameRate;
|
|
|
|
int NormalFrameTime;
|
|
|
|
int PrevNormalFrameTime;
|
|
|
|
extern int CloakingPhase;
|
|
|
|
|
|
|
|
/* These two are dummy values to get the DOS platform to compile */
|
|
|
|
|
|
|
|
unsigned char KeyCode;
|
|
|
|
unsigned char KeyASCII;
|
|
|
|
|
|
|
|
|
|
|
|
#if SuppressWarnings
|
|
|
|
unsigned char *palette_tmp;
|
|
|
|
static VIEWDESCRIPTORBLOCK* vdb_tmp;
|
|
|
|
static SCREENDESCRIPTORBLOCK* sdb_tmp;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Keyboard */
|
|
|
|
unsigned char KeyboardInput[MAX_NUMBER_OF_INPUT_KEYS];
|
|
|
|
unsigned char GotAnyKey;
|
|
|
|
|
|
|
|
/* Input communication with Windows Procedure */
|
|
|
|
/* Print system */
|
|
|
|
|
|
|
|
#if !DHMtextprint
|
|
|
|
PRINTQUEUEITEM PrintQueue[MaxMessages];
|
|
|
|
int MessagesStoredThisFrame;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int textprintPosX;
|
|
|
|
int textprintPosY;
|
|
|
|
IMAGEHEADER* fontHeader;
|
|
|
|
|
|
|
|
/* Added 28/11/97 by DHM: boolean for run-time switching on/off of textprint */
|
|
|
|
int bEnableTextprint = No;
|
|
|
|
|
|
|
|
/* Added 28/1/98 by DHM: as above, but applies specifically to textprintXY */
|
|
|
|
int bEnableTextprintXY = Yes;
|
|
|
|
|
|
|
|
/* Palette */
|
|
|
|
|
|
|
|
unsigned char PaletteBuffer[768 + 1];
|
|
|
|
|
|
|
|
/* Test Palette */
|
|
|
|
|
|
|
|
unsigned char TestPalette[768];
|
|
|
|
unsigned char TestPalette2[768];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* KJL 11:48:45 28/01/98 - used to scale NormalFrameTime, so the game can be slowed down */
|
|
|
|
int TimeScale=65536;
|
|
|
|
|
|
|
|
/* KJL 16:00:11 28/01/98 - unscaled frame time */
|
|
|
|
int RealFrameTime;
|
|
|
|
int GlobalFrameCounter;
|
|
|
|
int RouteFinder_CallsThisFrame;
|
|
|
|
|
|
|
|
/* KJL 15:08:43 29/03/98 - added to give extra flexibility to debugging text */
|
|
|
|
int PrintDebuggingText(const char* t, ...);
|
|
|
|
int ReleasePrintDebuggingText(const char* t, ...);
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
IO and Other Functions for the PC
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
Get Shape Data
|
|
|
|
|
|
|
|
Function returns a pointer to the Shape Header Block
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
SHAPEHEADER* GetShapeData(int shapenum)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if(shapenum>=0 && shapenum< maxshapes)
|
|
|
|
{
|
|
|
|
SHAPEHEADER *sptr = mainshapelist[shapenum];
|
|
|
|
return sptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
Platform specific VDB functions for Initialisation and ShowView()
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
void PlatformSpecificVDBInit(VIEWDESCRIPTORBLOCK *vdb)
|
|
|
|
|
|
|
|
{
|
|
|
|
#if SuppressWarnings
|
|
|
|
vdb_tmp = vdb;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PlatformSpecificShowViewEntry(VIEWDESCRIPTORBLOCK *vdb, SCREENDESCRIPTORBLOCK *sdb)
|
|
|
|
|
|
|
|
{
|
|
|
|
#if SuppressWarnings
|
|
|
|
vdb_tmp = vdb;
|
|
|
|
sdb_tmp = sdb;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PlatformSpecificShowViewExit(VIEWDESCRIPTORBLOCK *vdb, SCREENDESCRIPTORBLOCK *sdb)
|
|
|
|
|
|
|
|
{
|
|
|
|
#if SuppressWarnings
|
|
|
|
vdb_tmp = vdb;
|
|
|
|
sdb_tmp = sdb;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
Convert UNIX to MS-DOS
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
void GetDOSFilename(char *fnameptr)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
while(*fnameptr) {
|
|
|
|
|
|
|
|
if(*fnameptr == 0x2f) *fnameptr = 0x5c;
|
|
|
|
fnameptr++;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
Compare two filenames.
|
|
|
|
|
|
|
|
The first filename is assumed to be raw i.e. has no project subdirectory appended.
|
|
|
|
The second is assumed to be ready for use.
|
|
|
|
|
|
|
|
Make a copy of both strings, prefix the copy of the first with the project subdirectory
|
|
|
|
and convert them to DOS format before the comparison.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
int CompareFilenameCH(char *string1, char *string2)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
char *srtmp1;
|
|
|
|
char *srtmp2;
|
|
|
|
int slen1 = 0;
|
|
|
|
int slen2 = 0;
|
|
|
|
int i;
|
|
|
|
char fname1[ImageNameSize];
|
|
|
|
char fname2[ImageNameSize];
|
|
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
textprint(" Compare "); textprint(string1); textprint("\n");
|
|
|
|
textprint(" with "); textprint(string2); textprint("\n");
|
|
|
|
/*WaitForReturn();*/
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
/* Make a copy of string 1, adding the project subdirectory */
|
|
|
|
|
|
|
|
srtmp1 = projectsubdirectory;
|
|
|
|
srtmp2 = fname1;
|
|
|
|
while(*srtmp1) *srtmp2++ = *srtmp1++;
|
|
|
|
srtmp1 = string1;
|
|
|
|
while(*srtmp1) *srtmp2++ = *srtmp1++;
|
|
|
|
*srtmp2 = 0;
|
|
|
|
|
|
|
|
/* Make a copy of string 2 */
|
|
|
|
|
|
|
|
srtmp1 = string2;
|
|
|
|
srtmp2 = fname2;
|
|
|
|
while(*srtmp1) *srtmp2++ = *srtmp1++;
|
|
|
|
*srtmp2 = 0;
|
|
|
|
|
|
|
|
/* How long are they? */
|
|
|
|
|
|
|
|
srtmp1 = fname1;
|
|
|
|
while(*srtmp1++ != 0)
|
|
|
|
slen1++;
|
|
|
|
|
|
|
|
srtmp2 = fname2;
|
|
|
|
while(*srtmp2++ != 0)
|
|
|
|
slen2++;
|
|
|
|
|
|
|
|
fname1[slen1] = 0; /* Term */
|
|
|
|
fname2[slen2] = 0;
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
textprint("slen1 = %d, ", slen1);
|
|
|
|
textprint("slen2 = %d\n", slen2);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
textprint(" Compare "); textprint(fname1); textprint("\n");
|
|
|
|
textprint(" with "); textprint(fname2); textprint("\n");
|
|
|
|
/*WaitForReturn();*/
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
GetDOSFilename(fname1);
|
|
|
|
GetDOSFilename(fname2);
|
|
|
|
|
|
|
|
|
|
|
|
if(slen1 != slen2) {
|
|
|
|
/*textprint("not same\n");*/
|
|
|
|
return No;
|
|
|
|
}
|
|
|
|
|
|
|
|
srtmp1 = fname1;
|
|
|
|
srtmp2 = fname2;
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
textprint(" Compare "); textprint(srtmp1); textprint("\n");
|
|
|
|
textprint(" with "); textprint(srtmp2); textprint("\n");
|
|
|
|
WaitForReturn();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
for(i = slen1; i!=0; i--) {
|
|
|
|
if(*srtmp1++ != *srtmp2++) {
|
|
|
|
/*textprint("not same\n");*/
|
|
|
|
return No;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*textprint("same\n");*/
|
|
|
|
return Yes;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
Create an RGB table for "palette"
|
|
|
|
|
|
|
|
"GetRemappedPaletteColour()" is an access function for this table
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#define remap_table_size (1 << (remap_table_rgb_bits * 3))
|
|
|
|
|
|
|
|
|
|
|
|
#define cprt_info No
|
|
|
|
#define cprt_cnt No
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int NearestColour(int rs, int gs, int bs, unsigned char *palette)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int i;
|
|
|
|
VECTORCH p0;
|
|
|
|
VECTORCH p1;
|
|
|
|
int nearest_index;
|
|
|
|
int nearest_delta;
|
|
|
|
int d;
|
|
|
|
|
|
|
|
|
|
|
|
p0.vx = rs;
|
|
|
|
p0.vy = gs;
|
|
|
|
p0.vz = bs;
|
|
|
|
|
|
|
|
nearest_index = 0;
|
|
|
|
nearest_delta = bigint;
|
|
|
|
|
|
|
|
for(i = 0; i < 256; i++) {
|
|
|
|
|
|
|
|
p1.vx = palette[0];
|
|
|
|
p1.vy = palette[1];
|
|
|
|
p1.vz = palette[2];
|
|
|
|
|
|
|
|
d = FandVD_Distance_3d(&p0, &p1);
|
|
|
|
|
|
|
|
if(d < nearest_delta) {
|
|
|
|
|
|
|
|
nearest_delta = d;
|
|
|
|
nearest_index = i;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
palette += 3;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return nearest_index;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************/
|
|
|
|
/*************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
PC Video Mode Array Functions
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#define m320diag (378 + 6)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
PC Video Mode Function Arrays
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
void (*SetVideoMode[]) (void) = {
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
Initialise System and System Variables
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
2001-07-28 23:13:49 +00:00
|
|
|
void InitialiseSystem()
|
2000-03-16 11:25:00 +01:00
|
|
|
{
|
|
|
|
BOOL rc;
|
2001-07-28 23:13:49 +00:00
|
|
|
HINSTANCE hInstance = 0;
|
|
|
|
int nCmdShow = 1;
|
|
|
|
|
2000-03-16 11:25:00 +01:00
|
|
|
/*
|
|
|
|
Pick up processor type
|
|
|
|
*/
|
|
|
|
|
|
|
|
ProcessorType = ReadProcessorType();
|
|
|
|
|
|
|
|
if ((ProcessorType == PType_PentiumMMX) ||
|
|
|
|
(ProcessorType == PType_Klamath) ||
|
|
|
|
(ProcessorType == PType_OffTopOfScale))
|
|
|
|
MMXAvailable = TRUE;
|
|
|
|
else
|
|
|
|
MMXAvailable = FALSE;
|
|
|
|
|
|
|
|
/*
|
|
|
|
Copy initial requests to current variables,
|
|
|
|
subject to later modification.
|
|
|
|
*/
|
|
|
|
|
|
|
|
VideoMode = VideoRequestMode;
|
|
|
|
WindowMode = WindowRequestMode;
|
|
|
|
|
|
|
|
/*
|
|
|
|
Initialise dubious restart
|
|
|
|
system for ModeX emulation
|
|
|
|
and other problems
|
|
|
|
*/
|
|
|
|
|
|
|
|
AttemptVideoModeRestart = No;
|
|
|
|
|
|
|
|
VideoRestartMode = NoRestartRequired;
|
|
|
|
|
|
|
|
/*
|
|
|
|
Potentially a whole suite of caps
|
|
|
|
functions could be sensibly called
|
|
|
|
from here, to determine available
|
|
|
|
sound hardware, network links, 3D
|
|
|
|
hardware acceleration etc
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
Initialise the basic Direct Draw object,
|
|
|
|
find a hardware 3D capable driver if
|
|
|
|
possible and appropriate, and
|
|
|
|
determine what display modes, available
|
|
|
|
video memory etc exist.
|
|
|
|
*/
|
|
|
|
|
2001-08-03 05:30:40 +00:00
|
|
|
#if 0 /* LINUX */
|
2000-03-16 11:25:00 +01:00
|
|
|
if (InitialiseDirectDrawObject()
|
|
|
|
== FALSE)
|
|
|
|
/*
|
|
|
|
If we cannot get a video mode,
|
|
|
|
fail. No point in a non debugging option
|
|
|
|
for this.
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
ReleaseDirect3D();
|
|
|
|
exit(0x997799);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Initialise global to say whether
|
|
|
|
we think there is an onboard 3D
|
|
|
|
acceleration card / motherboard
|
|
|
|
built-in
|
|
|
|
*/
|
|
|
|
|
|
|
|
TestInitD3DObject();
|
|
|
|
|
|
|
|
/*
|
|
|
|
This is (HOPEFULLY!!) now the right
|
|
|
|
place to put this call. Note that it is
|
|
|
|
not absolutely certain that we can do test
|
|
|
|
blits from DirectDraw without setting
|
|
|
|
a cooperative level, however... And note also
|
|
|
|
that MMX works better with the back buffer in
|
|
|
|
system memory...
|
|
|
|
*/
|
|
|
|
TestMemoryAccess();
|
2001-08-03 05:30:40 +00:00
|
|
|
#endif
|
2000-03-16 11:25:00 +01:00
|
|
|
|
|
|
|
/* Initialise main window, windows procedure etc */
|
|
|
|
rc = InitialiseWindowsSystem(hInstance, nCmdShow, WinInitFull);
|
|
|
|
|
|
|
|
/* Initialise input interface */
|
|
|
|
memset((void*)KeyboardInput, No, MAX_NUMBER_OF_INPUT_KEYS);
|
|
|
|
GotAnyKey = No;
|
|
|
|
|
2001-08-03 05:30:40 +00:00
|
|
|
#if 0 /* LINUX */
|
2000-03-16 11:25:00 +01:00
|
|
|
/* launch Direct Input */
|
|
|
|
InitialiseDirectInput();
|
|
|
|
InitialiseDirectKeyboard();
|
|
|
|
InitialiseDirectMouse();
|
|
|
|
InitJoysticks();
|
2001-08-03 05:30:40 +00:00
|
|
|
#endif
|
2000-03-16 11:25:00 +01:00
|
|
|
|
|
|
|
/* Initialise textprint system */
|
|
|
|
textprintPosX = 0;
|
|
|
|
textprintPosY = 0;
|
|
|
|
#if debug
|
|
|
|
InitPrintQueue();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SUPPORT_MMX
|
|
|
|
SelectMMXOptions();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
{
|
|
|
|
/* CDF 4/2/97 */
|
|
|
|
extern void ConstructOneOverSinTable(void);
|
|
|
|
|
|
|
|
ConstructOneOverSinTable();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
Exit the system
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
void ExitSystem(void)
|
|
|
|
{
|
|
|
|
/* Game specific exit functions */
|
|
|
|
ExitGame();
|
|
|
|
|
|
|
|
|
|
|
|
// Added by Mark so that Direct Sound exits cleanly
|
|
|
|
#if SOUND_ON
|
|
|
|
ExitSoundSystem(); // In ds_func.cpp
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
Shaft DirectDraw and hit Direct3D
|
|
|
|
with a blunt Bill.
|
|
|
|
Note that ReleaseDirect3D is currently
|
|
|
|
responsible for whacking DirectDraw
|
|
|
|
and DirectInput as well; I should probably
|
|
|
|
rename it ReleaseDirectX sometime...
|
|
|
|
*/
|
|
|
|
|
|
|
|
ReleaseDirect3D();
|
|
|
|
|
|
|
|
/* Kill windows procedures */
|
|
|
|
ExitWindowsSystem();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Timer functions are based on Windows timer
|
|
|
|
giving number of millisecond ticks since Windows
|
|
|
|
was last booted. Note this will wrap round after
|
|
|
|
Windows has been up continuously for approximately
|
|
|
|
49.7 days. This is not considered to be too
|
|
|
|
significant a limitation...
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void ResetFrameCounter(void)
|
|
|
|
{
|
|
|
|
lastTickCount = timeGetTime();
|
|
|
|
|
|
|
|
/* KJL 15:03:33 12/16/96 - I'm setting NormalFrameTime too, rather than checking that it's
|
|
|
|
non-zero everytime I have to divide by it, since it usually is zero on the first frame. */
|
|
|
|
NormalFrameTime = 65536 >> 4;
|
|
|
|
PrevNormalFrameTime = NormalFrameTime;
|
|
|
|
|
|
|
|
RealFrameTime = NormalFrameTime;
|
|
|
|
FrameRate = 16;
|
|
|
|
GlobalFrameCounter=0;
|
|
|
|
CloakingPhase = 0;
|
|
|
|
|
|
|
|
|
|
|
|
RouteFinder_CallsThisFrame=0;
|
|
|
|
}
|
|
|
|
void FrameCounterHandler(void)
|
|
|
|
{
|
|
|
|
int newTickCount = timeGetTime();
|
|
|
|
int fcnt;
|
|
|
|
|
|
|
|
fcnt = newTickCount - lastTickCount;
|
|
|
|
lastTickCount = newTickCount;
|
|
|
|
|
|
|
|
if (fcnt == 0)
|
|
|
|
fcnt = 1; /* for safety */
|
|
|
|
|
|
|
|
FrameRate = TimerFrame / fcnt;
|
|
|
|
|
|
|
|
PrevNormalFrameTime = NormalFrameTime;
|
|
|
|
NormalFrameTime = DIV_FIXED(fcnt,TimerFrame);
|
|
|
|
|
|
|
|
RealFrameTime = NormalFrameTime;
|
|
|
|
|
|
|
|
{
|
|
|
|
if (TimeScale!=ONE_FIXED)
|
|
|
|
{
|
|
|
|
NormalFrameTime = MUL_FIXED(NormalFrameTime,TimeScale);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
/* cap NormalFrameTime if frame rate is really low */
|
|
|
|
if (NormalFrameTime>16384) NormalFrameTime=16384;
|
|
|
|
GlobalFrameCounter++;
|
|
|
|
CloakingPhase += NormalFrameTime>>5;
|
|
|
|
|
|
|
|
RouteFinder_CallsThisFrame=0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
This jump table has been provided
|
|
|
|
solely to ensure compatibility with
|
|
|
|
DOS and other versions.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
void (*UpdateScreen[]) (void) = {
|
|
|
|
|
|
|
|
FlipBuffers,
|
|
|
|
FlipBuffers,
|
|
|
|
FlipBuffers,
|
|
|
|
FlipBuffers,
|
|
|
|
|
|
|
|
FlipBuffers,
|
|
|
|
FlipBuffers,
|
|
|
|
FlipBuffers,
|
|
|
|
FlipBuffers,
|
|
|
|
|
|
|
|
FlipBuffers,
|
|
|
|
FlipBuffers,
|
|
|
|
FlipBuffers,
|
|
|
|
FlipBuffers,
|
|
|
|
|
|
|
|
FlipBuffers,
|
|
|
|
FlipBuffers,
|
|
|
|
FlipBuffers,
|
|
|
|
FlipBuffers,
|
|
|
|
|
|
|
|
FlipBuffers,
|
|
|
|
FlipBuffers,
|
|
|
|
FlipBuffers,
|
|
|
|
FlipBuffers,
|
|
|
|
|
|
|
|
FlipBuffers,
|
|
|
|
FlipBuffers,
|
|
|
|
FlipBuffers,
|
|
|
|
FlipBuffers
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
Wait for Return Key
|
|
|
|
|
|
|
|
Such a function may not be defined on some platforms
|
|
|
|
|
|
|
|
On Windows 95 the description of this function has
|
|
|
|
been changed, so that it calls FlushTextprintBuffer
|
|
|
|
and FlipBuffers before going into the actual
|
|
|
|
WaitForReturn code. This is necessary if it is to
|
|
|
|
behave in the same way after a textprint call as it
|
|
|
|
does on the DOS platform.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
void WaitForReturn(void)
|
|
|
|
|
|
|
|
{
|
|
|
|
/* Crude but probably serviceable for now */
|
|
|
|
long SavedTickCount;
|
|
|
|
SavedTickCount = lastTickCount;
|
|
|
|
|
|
|
|
/* Display any lingering text */
|
|
|
|
FlushTextprintBuffer();
|
|
|
|
FlipBuffers();
|
|
|
|
|
|
|
|
while (!(KeyboardInput[KEY_CR]))
|
|
|
|
DirectReadKeyboard();
|
|
|
|
|
|
|
|
lastTickCount = SavedTickCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
By copying the globals here we guarantee
|
|
|
|
that game functions will receive a set of
|
|
|
|
input values updated at a defined time
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
void ReadUserInput(void)
|
|
|
|
{
|
|
|
|
DirectReadMouse();
|
|
|
|
ReadJoysticks();
|
|
|
|
DirectReadKeyboard();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
At present all keyboard and mouse input is handled
|
|
|
|
through project specific functionality in win_func,
|
|
|
|
and all these functions are therefore empty. Later
|
|
|
|
we may port to DirectInput, at which point we
|
|
|
|
may reactivate these.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void ReadKeyboard(void)
|
|
|
|
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ReadMouse(void)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
Not NECESSARILY the standard functionality,
|
|
|
|
but it seems good enough to me...
|
|
|
|
*/
|
|
|
|
|
|
|
|
void CursorHome(void)
|
|
|
|
|
|
|
|
{
|
|
|
|
/* Reset positions for textprint system */
|
|
|
|
textprintPosX = 0;
|
|
|
|
textprintPosY = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void GetProjectFilename(char *fname, char *image)
|
|
|
|
{
|
|
|
|
|
|
|
|
char *src;
|
|
|
|
char *dst;
|
|
|
|
|
|
|
|
|
|
|
|
src = projectsubdirectory;
|
|
|
|
dst = fname;
|
|
|
|
|
|
|
|
while(*src)
|
|
|
|
*dst++ = *src++;
|
|
|
|
|
|
|
|
src = image;
|
|
|
|
|
|
|
|
while(*src)
|
|
|
|
*dst++ = *src++;
|
|
|
|
|
|
|
|
*dst = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
Attempts to load the image file.
|
|
|
|
|
|
|
|
Returns a pointer to the image if successful, else zero.
|
|
|
|
|
|
|
|
Image Header is filled out if successful, else ignore it.
|
|
|
|
|
|
|
|
NOTE
|
|
|
|
|
|
|
|
The pointer to the image data is also stored in the image
|
|
|
|
header.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
TEXTURE* LoadImageCH(char *fname, IMAGEHEADER *iheader)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ConvertToDDPalette(unsigned char* src, unsigned char* dst, int length, int flags)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/*
|
|
|
|
Copy palette, introducing flags and shifting up
|
|
|
|
to 8 bit triple
|
|
|
|
*/
|
|
|
|
|
|
|
|
for (i=0; i<length; i++)
|
|
|
|
{
|
|
|
|
*dst++ = (*src++) << 2;
|
|
|
|
*dst++ = (*src++) << 2;
|
|
|
|
*dst++ = (*src++) << 2;
|
|
|
|
*dst++ = flags;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
Platform specific version of "printf()"
|
|
|
|
|
|
|
|
Not all platforms support, or indeed are ABLE to support printf() in its
|
|
|
|
general form. For this reasons calls to textprint() are made through this
|
|
|
|
function.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
If debug or textprintOn are not defined, these
|
|
|
|
function defintions are collapsed to a simple
|
|
|
|
return value, which should collapse to no object
|
|
|
|
code under optimisation.
|
|
|
|
The whole issue of turning on or off textprint
|
|
|
|
beyond this point is hereby left to Kevin and
|
|
|
|
Chris H to fight to the death about...
|
|
|
|
*/
|
|
|
|
|
|
|
|
#if DHMtextprint
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
Dave Malcolm 21/11/96:
|
|
|
|
|
|
|
|
I have rewritten the Win95 textprint routines below.
|
|
|
|
|
|
|
|
It should now support:
|
|
|
|
- carriage returns are no longer automatic at the end of lines; there is a #define if you want this behaviour back
|
|
|
|
- carriage return characters cause a carriage return
|
|
|
|
- wraparound at the right-hand edge of the screen, with textprint() wrapping to the left-hand edge,
|
|
|
|
and textprintXY() wrapping back to the X coordinate
|
|
|
|
- clipping at the bottom edge of the screen
|
|
|
|
- a warning message if text has been lost due to clipping or buffer overflows etc.
|
|
|
|
- a y-offset that can be used to scroll up and down the text overlay output from textprint
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* VERSION SETTINGS: */
|
|
|
|
#define AutomaticNewLines No
|
|
|
|
/* set this to Yes and you will get a \n inserted automatically at the end of each line */
|
|
|
|
#if AutomaticNewLines
|
|
|
|
#error Not yet written...
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* LOW LEVEL ASSERTION SUPPORT */
|
|
|
|
/*
|
|
|
|
We cannot use standard assertions in this routine because this routine is called by the standard
|
|
|
|
assertion routine, and so would run the risk of infinite loops and excitingly obscure bugs.
|
|
|
|
|
|
|
|
For this reason we define a special assert macro.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#if 1
|
|
|
|
#define LOWLEVELASSERT(ignore)
|
|
|
|
#else
|
|
|
|
#if debug
|
|
|
|
|
|
|
|
#define LOWLEVELASSERT(x) \
|
|
|
|
(void) \
|
|
|
|
( \
|
|
|
|
(x) \
|
|
|
|
? 1 : (ReleaseDirect3D(),exit(GlobalAssertCode),0) \
|
|
|
|
)
|
|
|
|
|
|
|
|
#else
|
|
|
|
/* Assertions are disabled at compile-time: */
|
|
|
|
#define LOWLEVELASSERT(ignore)
|
|
|
|
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
We extract arguments into a buffer, with a dodgy hack to increase it in size to give more defence
|
|
|
|
against buffer overflows; there seems to be no easy & robust way to give vsprintf() a buffer size...
|
|
|
|
|
|
|
|
This buffer is reset once per string per frame
|
|
|
|
*/
|
|
|
|
#define PARANOIA_BYTES (1024)
|
|
|
|
#define TEXTPRINT_BUFFER_SIZE (MaxMsgChars+PARANOIA_BYTES+1)
|
|
|
|
static char TextprintBuffer[TEXTPRINT_BUFFER_SIZE]="";
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
The PRINTQUEUEITEM structure from PLATFORM.H is not used by my system; instead of queueing strings to be
|
|
|
|
displayed we do it on a character by character basis, with a limit on the total number of chars per frame.
|
|
|
|
|
|
|
|
This limit is set to be (MaxMsgChars*MaxMessages), which gives the same power and more flexibility than the
|
|
|
|
old system.
|
|
|
|
|
|
|
|
When the queue is full, additional characters get ignored.
|
|
|
|
|
|
|
|
This is queue is reset once per frame.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
typedef struct daveprintchar {
|
|
|
|
char CharToPrint;
|
|
|
|
int x,y;
|
|
|
|
} DAVEPRINTCHAR;
|
|
|
|
|
|
|
|
#define DHM_PRINT_QUEUE_SIZE (MaxMsgChars*MaxMessages)
|
|
|
|
|
|
|
|
static DAVEPRINTCHAR DHM_PrintQueue[DHM_PRINT_QUEUE_SIZE];
|
|
|
|
static int DHM_NumCharsInQueue=0;
|
|
|
|
|
|
|
|
static int fTextLost=No;
|
|
|
|
static char TextLostMessage[]="textprint warning:TEXT LOST";
|
|
|
|
#define TEXT_LOST_X (50)
|
|
|
|
#define TEXT_LOST_Y (20)
|
|
|
|
|
|
|
|
volatile int textprint_Y_offset=0;
|
|
|
|
|
|
|
|
|
|
|
|
/* Dave's version of initialising the print queue */
|
|
|
|
void InitPrintQueue(void)
|
|
|
|
{
|
|
|
|
DHM_NumCharsInQueue=0;
|
|
|
|
fTextLost=No;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
Old systems comment:
|
|
|
|
Write all messages in buffer to screen
|
|
|
|
(to be called at end of frame, after surface
|
|
|
|
/ execute buffer unlock in DrawItemListContents,
|
|
|
|
so that text appears at the front of the back
|
|
|
|
buffer immediately before the flip).
|
|
|
|
|
|
|
|
This is Dave's version of the same:
|
|
|
|
*/
|
|
|
|
|
|
|
|
void FlushTextprintBuffer(void)
|
|
|
|
|
|
|
|
{
|
|
|
|
/* PRECONDITION: */
|
|
|
|
{
|
|
|
|
LOWLEVELASSERT(DHM_NumCharsInQueue<DHM_PRINT_QUEUE_SIZE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* CODE: */
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
DAVEPRINTCHAR* pDPR=&DHM_PrintQueue[0];
|
|
|
|
|
|
|
|
for (i=0; i<DHM_NumCharsInQueue; i++)
|
|
|
|
{
|
|
|
|
#if 0
|
|
|
|
BlitWin95Char
|
|
|
|
(
|
|
|
|
pDPR->x,
|
|
|
|
pDPR->y,
|
|
|
|
pDPR->CharToPrint
|
|
|
|
);
|
|
|
|
#else
|
|
|
|
D3D_BlitWhiteChar
|
|
|
|
(
|
|
|
|
pDPR->x,
|
|
|
|
pDPR->y,
|
|
|
|
pDPR->CharToPrint
|
|
|
|
);
|
|
|
|
#endif
|
|
|
|
pDPR++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fTextLost)
|
|
|
|
{
|
|
|
|
/* Display error message in case test has been lost due to clipping of Y edge, or buffer overflow */
|
|
|
|
int i;
|
|
|
|
int NumChars=strlen(TextLostMessage);
|
|
|
|
|
|
|
|
for (i=0;i<NumChars;i++)
|
|
|
|
{
|
|
|
|
// BlitWin95Char(TEXT_LOST_X+(i*CharWidth),TEXT_LOST_Y,TextLostMessage[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
fTextLost=No;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DHM_NumCharsInQueue=0;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int LastDisplayableXForChars(void)
|
|
|
|
{
|
|
|
|
return ScreenDescriptorBlock.SDB_Width-CharWidth;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int LastDisplayableYForChars(void)
|
|
|
|
{
|
|
|
|
return ScreenDescriptorBlock.SDB_Height-CharHeight;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void DHM_AddToQueue(int x,int y, char Ch)
|
|
|
|
{
|
|
|
|
|
|
|
|
if
|
|
|
|
(
|
|
|
|
(y>=0)
|
|
|
|
&&
|
|
|
|
(y<=LastDisplayableYForChars())
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if (DHM_NumCharsInQueue<DHM_PRINT_QUEUE_SIZE)
|
|
|
|
{
|
|
|
|
DAVEPRINTCHAR* pDPR=&DHM_PrintQueue[DHM_NumCharsInQueue++];
|
|
|
|
/* We insert into the queue at this position, updating the length of the queue */
|
|
|
|
|
|
|
|
pDPR->x=x;
|
|
|
|
pDPR->y=y;
|
|
|
|
pDPR->CharToPrint=Ch;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Otherwise the queue if full, we will have to ignore this char; set an error flag so we get a message*/
|
|
|
|
fTextLost=Yes;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Otherwise the text is off the top or bottom of the screen; set an error flag to get a message up*/
|
|
|
|
fTextLost=Yes;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int DHM_MoveBufferToQueue(int* pPosX,int* pPosY,int fZeroLeftMargin)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
Function takes two integers by reference (using pointers), and outputs whatever is in
|
|
|
|
the string buffer into the character queue, so that code can be shared by textprint() and textprintXY()
|
|
|
|
|
|
|
|
Returns "number of lines": any carriage returns or word wraps
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* PRECONDITION */
|
|
|
|
{
|
|
|
|
LOWLEVELASSERT(pPosX);
|
|
|
|
LOWLEVELASSERT(pPosY);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* CODE */
|
|
|
|
{
|
|
|
|
int NumLines=0;
|
|
|
|
|
|
|
|
int LeftMarginX;
|
|
|
|
|
|
|
|
if (fZeroLeftMargin)
|
|
|
|
{
|
|
|
|
LeftMarginX=0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LeftMarginX=*pPosX;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Iterate through the string in the buffer, adding the individual characters to the queue */
|
|
|
|
{
|
|
|
|
char* pCh=&TextprintBuffer[0];
|
|
|
|
int SafetyCount=0;
|
|
|
|
|
|
|
|
while
|
|
|
|
(
|
|
|
|
((*pCh)!='\0')
|
|
|
|
&&
|
|
|
|
((SafetyCount++)<MaxMsgChars)
|
|
|
|
)
|
|
|
|
{
|
|
|
|
switch (*pCh)
|
|
|
|
{
|
|
|
|
case '\n':
|
|
|
|
{
|
|
|
|
/* Wrap around to next line.,. */
|
|
|
|
(*pPosY)+=HUD_FONT_HEIGHT;
|
|
|
|
(*pPosX)=LeftMarginX;
|
|
|
|
NumLines++;
|
|
|
|
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
/* It is a standard character or a space */
|
|
|
|
DHM_AddToQueue(*pPosX,(*pPosY)+textprint_Y_offset, *pCh);
|
|
|
|
|
|
|
|
(*pPosX)+=AAFontWidths[*pCh];//CharWidthInPixels(*pCh);
|
|
|
|
|
|
|
|
if ((*pPosX)>LastDisplayableXForChars())
|
|
|
|
{
|
|
|
|
/* Wrap around to next line.,. */
|
|
|
|
(*pPosY)+=HUD_FONT_HEIGHT;
|
|
|
|
(*pPosX)=LeftMarginX;
|
|
|
|
NumLines++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ...and on to the next character*/
|
|
|
|
pCh++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Clear the string buffer */
|
|
|
|
{
|
|
|
|
TextprintBuffer[0]='\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
return NumLines;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int textprint(const char* t, ...)
|
|
|
|
{
|
|
|
|
#if (debug && textprintOn)
|
|
|
|
if
|
|
|
|
(
|
|
|
|
bEnableTextprint
|
|
|
|
)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
Get message string from arguments into buffer...
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
va_start(ap, t);
|
|
|
|
vsprintf(&TextprintBuffer[0], t, ap);
|
|
|
|
va_end(ap);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Attempt to trap buffer overflows...
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
LOWLEVELASSERT(strlen(TextprintBuffer)<TextprintBuffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
return DHM_MoveBufferToQueue(&textprintPosX,&textprintPosY,Yes);
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Run-time disabling of textprint()
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
/* Do nothing; hope the function call gets optimised away */
|
|
|
|
return 0;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
int PrintDebuggingText(const char* t, ...)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
Get message string from arguments into buffer...
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
va_start(ap, t);
|
|
|
|
vsprintf(&TextprintBuffer[0], t, ap);
|
|
|
|
va_end(ap);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Attempt to trap buffer overflows...
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
LOWLEVELASSERT(strlen(TextprintBuffer)<TextprintBuffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
return DHM_MoveBufferToQueue(&textprintPosX,&textprintPosY,Yes);
|
|
|
|
}
|
|
|
|
int ReleasePrintDebuggingText(const char* t, ...)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
Get message string from arguments into buffer...
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
va_start(ap, t);
|
|
|
|
vsprintf(&TextprintBuffer[0], t, ap);
|
|
|
|
va_end(ap);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Attempt to trap buffer overflows...
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
LOWLEVELASSERT(strlen(TextprintBuffer)<TextprintBuffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
return DHM_MoveBufferToQueue(&textprintPosX,&textprintPosY,Yes);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int textprintXY(int x, int y, const char* t, ...)
|
|
|
|
|
|
|
|
{
|
|
|
|
#if (debug && textprintOn)
|
|
|
|
if
|
|
|
|
(
|
|
|
|
bEnableTextprintXY
|
|
|
|
)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
Get message string from arguments into buffer...
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
va_start(ap, t);
|
|
|
|
vsprintf(&TextprintBuffer[0], t, ap);
|
|
|
|
va_end(ap);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Attempt to trap buffer overflows...
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
LOWLEVELASSERT(strlen(TextprintBuffer)<TextprintBuffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
int localX=x;
|
|
|
|
int localY=y;
|
|
|
|
|
|
|
|
return DHM_MoveBufferToQueue(&localX,&localY,No);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Run-time disabling of textprint()
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
{
|
|
|
|
/* Do nothing; hope the function call gets optimised away */
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
*
|
|
|
|
*
|
|
|
|
|
|
|
|
End of Dave Malcolm's text routines; old version is below
|
|
|
|
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
#else
|
|
|
|
|
|
|
|
/*
|
|
|
|
NOTE!!!! All this software is intended for debugging
|
|
|
|
only. It emulates the print interface in any video
|
|
|
|
mode supported by the engine, but there are limits -
|
|
|
|
messages will pile up at the bottom of the screen
|
|
|
|
and overwrite each other, all messages will appear at the
|
|
|
|
fron in the main screen (NOT clipped to the VDB), messages
|
|
|
|
will not wrap round if they are longer than a screen line
|
|
|
|
unless \n is inserted in the print string, and the text colour
|
|
|
|
is not guaranteed to be white in paletted modes.
|
|
|
|
So there.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
IMPORTANT!!!!
|
|
|
|
Messages longer than MaxMsgChars are liable
|
|
|
|
to CRASH this routine. I haven't bothered
|
|
|
|
to do anything about this on the grounds that
|
|
|
|
we can't tell how long the message is until after
|
|
|
|
the vsprintf call, and the crash is likely to
|
|
|
|
occur in vsprintf itself as it overflows the
|
|
|
|
buffer.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
!!!!! FIXME??
|
|
|
|
textprints don't seem to appear
|
|
|
|
in SubWindow mode --- possibly
|
|
|
|
because the colours in the font
|
|
|
|
are going to system font colours which
|
|
|
|
are invisible???
|
|
|
|
*/
|
|
|
|
|
|
|
|
#if (debug && textprintOn)
|
|
|
|
|
|
|
|
int textprint(const char* t, ...)
|
|
|
|
|
|
|
|
{
|
|
|
|
int i,j;
|
|
|
|
va_list ap;
|
|
|
|
char message[MaxMsgChars];
|
|
|
|
char outmsg[MaxMsgChars];
|
|
|
|
int numlines;
|
|
|
|
int CharCount;
|
|
|
|
int XPos=0;
|
|
|
|
|
|
|
|
va_start(ap, t);
|
|
|
|
|
|
|
|
vsprintf(&message[0], t, ap);
|
|
|
|
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
j = 0;
|
|
|
|
numlines = 0;
|
|
|
|
CharCount = strlen(&message[0]);
|
|
|
|
|
|
|
|
/* Read through message buffer until we reach the terminator */
|
|
|
|
while ((i < CharCount) && (message[i] != '\0'))
|
|
|
|
{
|
|
|
|
outmsg[j++] = message[i];
|
|
|
|
XPos+=CharWidth;
|
|
|
|
/* newline within string */
|
|
|
|
if ((message[i] == '\n')||(XPos>ScreenDescriptorBlock.SDB_Width))
|
|
|
|
{
|
|
|
|
/* Display string and reset to start of next line */
|
|
|
|
WriteStringToTextBuffer(textprintPosX, textprintPosY,
|
|
|
|
&outmsg[0]);
|
|
|
|
textprintPosX = 0;
|
|
|
|
textprintPosY += HUD_FONT_HEIGHT;
|
|
|
|
XPos=0;
|
|
|
|
/* Messages can pile up at bottom of screen */
|
|
|
|
if (textprintPosY > ScreenDescriptorBlock.SDB_Height)
|
|
|
|
textprintPosY = ScreenDescriptorBlock.SDB_Height;
|
|
|
|
/* Clear output string and reset variables */
|
|
|
|
{
|
|
|
|
int k;
|
|
|
|
for (k=0; k<(j+1); k++)
|
|
|
|
outmsg[k] = 0;
|
|
|
|
}
|
|
|
|
j = 0;
|
|
|
|
/* Record number of lines output */
|
|
|
|
numlines++;
|
|
|
|
}
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Flush any remaining characters */
|
|
|
|
WriteStringToTextBuffer(textprintPosX, textprintPosY,
|
|
|
|
&outmsg[0]);
|
|
|
|
textprintPosX = 0;
|
|
|
|
textprintPosY += HUD_FONT_HEIGHT;
|
|
|
|
/* Messages can pile up at bottom of screen */
|
|
|
|
if (textprintPosY > ScreenDescriptorBlock.SDB_Height)
|
|
|
|
textprintPosY = ScreenDescriptorBlock.SDB_Height;
|
|
|
|
numlines++;
|
|
|
|
|
|
|
|
return numlines;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Textprint to defined location on screen
|
|
|
|
(in screen coordinates for current video
|
|
|
|
mode).
|
|
|
|
NOTE!!! Newlines within strings sent to this
|
|
|
|
function will be IGNORED.
|
|
|
|
*/
|
|
|
|
|
|
|
|
int textprintXY(int x, int y, const char* t, ...)
|
|
|
|
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
char message[MaxMsgChars];
|
|
|
|
|
|
|
|
va_start(ap, t);
|
|
|
|
|
|
|
|
vsprintf(&message[0], t, ap);
|
|
|
|
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
WriteStringToTextBuffer(x, y, &message[0]);
|
|
|
|
|
|
|
|
return 1; /* for one line */
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
int textprint(const char* t, ...)
|
|
|
|
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int textprintXY(int x, int y, const char* t, ...)
|
|
|
|
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
Add string to text buffer
|
|
|
|
*/
|
|
|
|
|
|
|
|
void WriteStringToTextBuffer(int x, int y, unsigned char *buffer)
|
|
|
|
|
|
|
|
{
|
|
|
|
if (MessagesStoredThisFrame < MaxMessages)
|
|
|
|
{
|
|
|
|
strcpy(PrintQueue[MessagesStoredThisFrame].text, buffer);
|
|
|
|
|
|
|
|
PrintQueue[MessagesStoredThisFrame].text_length = strlen(buffer);
|
|
|
|
PrintQueue[MessagesStoredThisFrame].x = x;
|
|
|
|
PrintQueue[MessagesStoredThisFrame].y = y;
|
|
|
|
|
|
|
|
MessagesStoredThisFrame++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
Display string of chracters, starting at passed pointer,
|
|
|
|
at location on screen starting with x and y.
|
|
|
|
|
|
|
|
Patched by Dave Malcolm 20/11/96 so that text wraps around when it reaches the right hand edge of the screen, in
|
|
|
|
this routine, at least...
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
void DisplayWin95String(int x, int y, unsigned char *buffer)
|
|
|
|
|
|
|
|
{
|
|
|
|
int InitialX=x;
|
|
|
|
int stlen;
|
|
|
|
unsigned char ch;
|
|
|
|
|
|
|
|
stlen = strlen(buffer);
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
ch = (unsigned char) *buffer;
|
|
|
|
BlitWin95Char(x, y, ch);
|
|
|
|
x += CharWidth;
|
|
|
|
if (x > (ScreenDescriptorBlock.SDB_Width
|
|
|
|
- CharWidth))
|
|
|
|
{
|
|
|
|
#if 1
|
|
|
|
/* Wrap to new line, based on coordinates for display...*/
|
|
|
|
x=InitialX;
|
|
|
|
y+=HUD_FONT_HEIGHT;
|
|
|
|
#else
|
|
|
|
/* Characters will pile up at screen edge */
|
|
|
|
x = (ScreenDescriptorBlock.SDB_Width - CharWidth);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
buffer++;
|
|
|
|
stlen--;
|
|
|
|
}
|
|
|
|
while ((ch != '\n') && (ch != '\0') &&
|
|
|
|
(stlen > 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Write all messages in buffer to screen
|
|
|
|
(to be called at end of frame, after surface
|
|
|
|
/ execute buffer unlock in DrawItemListContents,
|
|
|
|
so that text appears at the front of the back
|
|
|
|
buffer immediately before the flip).
|
|
|
|
*/
|
|
|
|
|
|
|
|
void FlushTextprintBuffer(void)
|
|
|
|
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i=0; i<MessagesStoredThisFrame; i++)
|
|
|
|
{
|
|
|
|
if (PrintQueue[i].text_length)
|
|
|
|
DisplayWin95String(PrintQueue[i].x,
|
|
|
|
PrintQueue[i].y, PrintQueue[i].text);
|
|
|
|
|
|
|
|
/*
|
|
|
|
More mystery code from Roxby --- an extra safety
|
|
|
|
check for printing?? Or a hangover from a linked
|
|
|
|
list version of the data structure???
|
|
|
|
*/
|
|
|
|
PrintQueue[i].text_length = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
MessagesStoredThisFrame = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Initialise print queue */
|
|
|
|
|
|
|
|
void InitPrintQueue(void)
|
|
|
|
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* Mystery code from Roxby here... */
|
|
|
|
for (i=0; i < MaxMessages; i++)
|
|
|
|
PrintQueue[i].text_length = 0;
|
|
|
|
|
|
|
|
MessagesStoredThisFrame = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
/*end of old version of text routines */
|
|
|
|
|
|
|
|
/*
|
|
|
|
Load main, 8 bit paletted, font
|
|
|
|
(assumed to be on hard drive at present)
|
|
|
|
and create hi and true colour mode fonts
|
|
|
|
from it. Note that for this system to work
|
|
|
|
properly all bits on must be white or similar
|
|
|
|
in 8 bit mode 222 and Raw256 palettes as well
|
|
|
|
as mode 8T.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
MUST be called after GenerateDirectDrawSurface,
|
|
|
|
i.e. AFTER SetVideoMode.
|
|
|
|
AND ONLY ONCE!!!!
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
This function is intended to allow YOU,
|
|
|
|
the user, to obtain your heart's fondest desires
|
|
|
|
by one simple call. Money? Love? A better job?
|
|
|
|
It's all here, you have only to ask...
|
|
|
|
No, I was lying actually.
|
|
|
|
In fact, this should allow you to change
|
|
|
|
display modes cleanly. Pass your request modes
|
|
|
|
(as normally set up in system.c). For all entries
|
|
|
|
which you do not want to change, simply pass
|
|
|
|
the current global value (e.g. ZBufferRequestMode
|
|
|
|
in the NewZBufferMode entry).
|
|
|
|
|
|
|
|
Note that the function must always be passed the
|
|
|
|
HINSTANCE and nCmdShow from winmain.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
Note that this function will NOT
|
|
|
|
reinitialise the DirectDraw object
|
|
|
|
or switch to or from a hardware DD
|
|
|
|
device, but it will release and rebuild
|
|
|
|
all the Direct3D objects.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
Note that you MUST be in the right
|
|
|
|
directory for a texture reload before you
|
|
|
|
call this, and normal operations CAN change
|
|
|
|
the directory...
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
NOTE!!! If you start in DirectDraw mode
|
|
|
|
and go to Direct3D mode, this function
|
|
|
|
CANNOT POSSIBLY WORK WITHOUT A FULL SHAPE
|
|
|
|
RELOAD, since the shape data is overwritten
|
|
|
|
during DirectDraw initialisation!!!!
|
|
|
|
|
|
|
|
NOTE ALSO: TEXTURE RELOAD MAY BE DODGY
|
|
|
|
WITHOUT A SHAPE RELOAD!!!
|
|
|
|
*/
|
|
|
|
|
|
|
|
int ChangeDisplayModes(HINSTANCE hInst, int nCmd,
|
|
|
|
int NewVideoMode, int NewWindowMode,
|
|
|
|
int NewZBufferMode, int NewRasterisationMode,
|
|
|
|
int NewSoftwareScanDrawMode, int NewDXMemoryMode)
|
|
|
|
{
|
|
|
|
BOOL rc;
|
|
|
|
BOOL ChangeWindow = No;
|
|
|
|
|
|
|
|
/*
|
|
|
|
Shut down DirectX objects and destroy
|
|
|
|
the current window, if necessary.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (NewWindowMode != WindowMode)
|
|
|
|
ChangeWindow = Yes;
|
|
|
|
|
|
|
|
DeallocateAllImages();
|
|
|
|
|
|
|
|
ReleaseDirect3DNotDD();
|
|
|
|
|
|
|
|
finiObjectsExceptDD();
|
|
|
|
|
|
|
|
|
|
|
|
if (ChangeWindow)
|
|
|
|
ExitWindowsSystem();
|
|
|
|
|
|
|
|
/* Test!! */
|
|
|
|
|
|
|
|
/*
|
|
|
|
Set the request modes and actual modes
|
|
|
|
according to the passed values.
|
|
|
|
*/
|
|
|
|
|
|
|
|
VideoRequestMode = NewVideoMode;
|
|
|
|
WindowRequestMode = NewWindowMode;
|
|
|
|
ZBufferRequestMode = NewZBufferMode;
|
|
|
|
RasterisationRequestMode = NewRasterisationMode;
|
|
|
|
SoftwareScanDrawRequestMode = NewSoftwareScanDrawMode;
|
|
|
|
DXMemoryRequestMode = NewDXMemoryMode;
|
|
|
|
|
|
|
|
VideoMode = VideoRequestMode;
|
|
|
|
WindowMode = WindowRequestMode;
|
|
|
|
|
|
|
|
/* this may reconstruct the dd object depending
|
|
|
|
on the rasterisation request mode and whether
|
|
|
|
a hardware dd driver is selected or could be
|
|
|
|
available */
|
|
|
|
ChangeDirectDrawObject();
|
|
|
|
|
|
|
|
/*
|
|
|
|
Check that our new video mode exists,
|
|
|
|
and pick a valid option if it doesn't and
|
|
|
|
we can find one.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#if CheckVideoModes
|
|
|
|
if (WindowMode == WindowModeFullScreen)
|
|
|
|
{
|
|
|
|
if (!(CheckForVideoModes(VideoMode)))
|
|
|
|
{
|
|
|
|
VideoMode = VideoMode_DX_640x480x8;
|
|
|
|
if (!(CheckForVideoModes(VideoMode)))
|
|
|
|
{
|
|
|
|
VideoMode = VideoMode_DX_640x480x15;
|
|
|
|
if (!(CheckForVideoModes(VideoMode)))
|
|
|
|
{
|
|
|
|
ReleaseDirect3D(); // for safety
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
Recreate the window, allowing
|
|
|
|
for possible change in WindowMode.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (ChangeWindow)
|
|
|
|
{
|
|
|
|
rc = InitialiseWindowsSystem(hInst, nCmd,
|
|
|
|
WinInitChange);
|
|
|
|
|
|
|
|
if (rc == FALSE)
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Set the video mode again. This
|
|
|
|
will handle all changes to DirectDraw
|
|
|
|
objects, all Direct3D initialisation,
|
|
|
|
and other request modes such as
|
|
|
|
zbuffering.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
Err... shutting down and restarting
|
|
|
|
on a hardware driver appears to
|
|
|
|
screw up file handling somehow...
|
|
|
|
umm... but not for Microsoft demos,
|
|
|
|
obviously...
|
|
|
|
FIXME!!!
|
|
|
|
*/
|
|
|
|
/* test only!!! */
|
|
|
|
#if 0
|
|
|
|
chdir("d:\3dc");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
SetVideoMode[VideoMode]();
|
|
|
|
|
|
|
|
/*
|
|
|
|
Lose all the textures and reload the
|
|
|
|
debugging font
|
|
|
|
*/
|
|
|
|
|
|
|
|
InitialiseTextures();
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
Well, we HOPE it's okay...
|
|
|
|
*/
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
Reverse of ConvertToDDPalette, introduced
|
|
|
|
to maintain internal interfaces only...
|
|
|
|
*/
|
|
|
|
|
|
|
|
void ConvertDDToInternalPalette(unsigned char* src, unsigned char* dst, int length)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/*
|
|
|
|
Copy palette, shifting down
|
|
|
|
to 5 bit triple
|
|
|
|
*/
|
|
|
|
|
|
|
|
for (i=0; i<length; i++)
|
|
|
|
{
|
|
|
|
*dst++ = (*src++) >> 2;
|
|
|
|
*dst++ = (*src++) >> 2;
|
|
|
|
*dst++ = (*src++) >> 2;
|
|
|
|
}
|
|
|
|
}
|