rott/rott/sbconfig.c

500 lines
10 KiB
C
Executable File

/*
Copyright (C) 1994-1995 Apogee Software, Ltd.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* Copyright 1995 Spacetec IMC Corporation */
#if defined(__BORLANDC__)
# pragma inline
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <dos.h>
typedef long fixed;
#include "rt_def.h"
#include "develop.h"
#include "sbconfig.h"
//MED
#include "memcheck.h"
/* ----------------------------------------------------------------------- */
#define DEFAULT_CONFIG_FILENAME "sbconfig.dat"
#define NUM_ELEMENTS(x) (sizeof(x)/sizeof(x[0]))
#define SIGN(x) ((x<0)?-1:1)
/* ----------------------------------------------------------------------- */
#if defined(__BORLANDC__)
fixed FIXED_MUL(fixed a, fixed b)
{
fixed ret_code;
asm {
mov eax,a
mov edx,b
imul edx
shrd eax,edx,16
mov ret_code,eax
}
return ret_code;
}
#elif defined(_MSC_VER)
/* Microsoft C7.0 can not be done with inline assembler because it
can not handle 32-bit instructions
*/
fixed FIXED_MUL(fixed a,fixed b)
{
fixed sgn,ah,al,bh,bl;
sgn = (SIGN(a) ^ SIGN(b)) ? -1 : 1 ;
ah = (a >> 16) & 0xffff ;
al = (a & 0xffff);
bh = (b >> 16) & 0xffff ;
bl = (b & 0xffff);
return sgn * ( ((al*bl)>>16) + (ah*bl) + (al*bh) + ((ah*bh)<<16) );
}
#elif defined(__WATCOMC__)
fixed FIXED_MUL(fixed a, fixed b);
#pragma aux FIXED_MUL = \
"imul edx" \
"shrd eax,edx,16" \
parm [eax] [edx] \
value [eax] \
modify exact [eax] ;
#endif /* definition of inline FIXED_MUL */
static
fixed StrToFx1616(char *string, char **ret_string)
{
long whole;
long fract;
fixed result;
int sign;
/* Skip whitespace */
while((*string==' ')||(*string=='\t')||(*string=='\n')) string++;
/* Accept numbers in the form: [+-]?[0-9]+(.[0-9]*)
*/
sign=1;
if(*string=='-')
{
string++;
sign=-1;
}
else if(*string=='+')
{
string++;
sign=1;
}
/* Read in the whole part */
whole=0;
while((*string>='0')&&(*string<='9'))
whole=whole*10+(*string++)-'0';
/* Read the optional fraction part */
fract=0;
if(*string=='.')
{
long place=1;
string++;
while((*string>='0')&&(*string<='9'))
{
fract=fract*10+(*string++)-'0';
place*=10;
}
/* Convert to fixed point */
fract=(fract<<16)/place;
}
if(ret_string) *ret_string=string;
if(sign==1)
result= (whole<<16) + fract;
else
result=-(whole<<16) + fract;
return result;
}
/* ----------------------------------------------------------------------- */
static char *SbButtonNames[]={
"BUTTON_A",
"BUTTON_B",
"BUTTON_C",
"BUTTON_D",
"BUTTON_E",
"BUTTON_F"};
static int cfgFileVersion=0;
static char cfgButtons[NUM_ELEMENTS(SbButtonNames)][MAX_STRING_LENGTH];
static WarpRecord *pCfgWarps;
static int nCfgWarps=0;
/*-------------------------------------------------------------------------*/
/* Read a string in the form: "{#, #, #}"
* and return a pointer to the character AFTER the '}'
* or NULL if error
*/
static char *GetWarpLevels(char *string, WarpRange *pw)
{
short value;
fixed fxvalue;
if((*string++)!='{')
return NULL;
if(!*string)
return NULL;
/* Expecting the first number - low */
value=(short)strtol(string, &string, 0);
if(pw) pw->low=value;
/* Skip any whitespace */
while(isspace(*string)) string++;
if(*string++!=',')
return NULL;
/* Expecting the second number - high */
value=(short)strtol(string, &string, 0);
if(pw) pw->high=value;
/* Skip any whitespace */
while(isspace(*string)) string++;
if(*string++!=',')
return NULL;
/* Expecting the third number - multiplier */
fxvalue=StrToFx1616(string, &string);
if(pw) pw->mult=fxvalue;
/* Skip any whitespace */
while(isspace(*string)) string++;
if(*string!='}')
return NULL;
return string+1;
}
static int GetWarp(char *string, WarpRecord *pRecord)
{
int nWarp;
WarpRange *pWarp;
/* Only update the field if we successfully read the entire line */
nWarp=0;
pWarp=NULL;
/* Skip whitespace */
while(isspace(*string)) string++;
if(*string++!='{') return 0;
while(string && *string)
{
switch(*string)
{
case ' ':
case '\t':
case '\n':
string++;
break;
case ',':
string++;
break;
case '{':
if(nWarp++==0)
pWarp=malloc(sizeof(WarpRange));
else
pWarp=realloc(pWarp, nWarp*sizeof(WarpRange));
string=GetWarpLevels(string, pWarp+nWarp-1);
break;
case '}':
pRecord->nWarp=nWarp;
pRecord->pWarp=pWarp;
return 1;
}
}
/* Early EOL (didn't get closing '}') */
if(nWarp) free(pWarp);
return 0;
}
/*-------------------------------------------------------------------------*/
int SbConfigParse(char *_filename)
{
int i;
FILE *file;
char *pc;
char buffer[128];
char filename[MAX_PATH];
if(!_filename) _filename=DEFAULT_CONFIG_FILENAME;
strncpy(filename, _filename, sizeof (filename));
filename[sizeof (filename) - 1] = '\0';
FixFilePath(filename);
if(!(file=fopen(filename, "r")))
{
printf("Config file: %s, not found\n", filename);
return 0;
}
while(fgets(buffer, sizeof(buffer), file))
{
int lineParsed=0;
/* each line in config file starts with either a ;, VERSION or an
** element of GameButtonNames or WarpNames
*/
pc=strtok(buffer, " \t\n,");
if(*pc==';') /* commented out line? */
continue;
/* VERSION? The version will be used in the future to allow fx1616
** values in the config file
*/
if(!stricmp(pc,"VERSION"))
{
pc=strtok(NULL, " \t\n,");
cfgFileVersion=atoi(pc);
}
/* Check if first token is an element of SbButtonNames */
for(i=0; i<NUM_ELEMENTS(SbButtonNames); i++)
if(!stricmp(pc, SbButtonNames[i]))
{
lineParsed=1;
/* Save the next token in the appropriate slot */
pc=strtok(NULL," \t\n,");
strncpy(cfgButtons[i], pc, MAX_STRING_LENGTH-1);
cfgButtons[i][MAX_STRING_LENGTH-1]=0;
}
/* If the first token is not from GameButtonNames,
** it must be a WarpName
*/
if(!lineParsed)
{
char *name;
name=pc;
pc=pc+strlen(pc)+1; /* Skip this token */
while(isspace(*pc)) pc++; /* Skip any whitespace */
if(*pc=='{')
{
WarpRecord warpRec;
strcpy(warpRec.name, name);
warpRec.pWarp=NULL;
warpRec.nWarp=0;
if(GetWarp(pc, &warpRec))
{
if(nCfgWarps++==0)
pCfgWarps=(WarpRecord *)malloc(sizeof(WarpRecord));
else
pCfgWarps=(WarpRecord *)realloc(pCfgWarps, nCfgWarps*sizeof(WarpRecord));
pCfgWarps[nCfgWarps-1]=warpRec;
}
}
}
} /* end of while getting lines from config file */
fclose(file);
return 1;
}
/*-------------------------------------------------------------------------*/
char *SbConfigGetButton(char *btnName)
{
int i;
for(i=0; i<NUM_ELEMENTS(SbButtonNames); i++)
{
if(!stricmp(btnName, SbButtonNames[i]))
if(cfgButtons[i][0])
return cfgButtons[i];
else
return NULL; /* Empty slot */
if(!stricmp(btnName, cfgButtons[i]))
return SbButtonNames[i];
}
/* Unknown button name */
return NULL;
}
int SbConfigGetButtonNumber(char *btnName)
{
int i;
for(i=0; i<NUM_ELEMENTS(SbButtonNames); i++)
{
if(!stricmp(btnName, cfgButtons[i]))
return i;
}
/* Unknown button name */
return -1;
}
/*-------------------------------------------------------------------------*/
WarpRecord *SbConfigGetWarpRange(char *rngName)
{
int i;
for(i=0; i<nCfgWarps; i++)
if(!stricmp(rngName, pCfgWarps[i].name))
return &pCfgWarps[i];
return NULL;
}
/*-------------------------------------------------------------------------*/
fixed SbFxConfigWarp(WarpRecord *warp, short value)
{
int i;
short absValue;
fixed accum;
int sign;
if(!warp) return INT_TO_FIXED(value);
absValue=value;
sign=1;
if(absValue<0)
{
absValue= (short)-absValue;
sign=-1;
}
accum=INT_TO_FIXED(0);
for(i=0; i<warp->nWarp; i++)
{
if(absValue<=warp->pWarp[i].low)
; /* Ignore it if below this range (if required, will have
** been caught by the previous warp)
*/
else if((absValue>warp->pWarp[i].low) && (absValue<=warp->pWarp[i].high))
{
fixed diff;
fixed partial;
diff=INT_TO_FIXED((long)absValue-(long)warp->pWarp[i].low);
partial=FIXED_MUL(diff, warp->pWarp[i].mult);
accum=FIXED_ADD(accum, partial);
break; /* Exit the for loop */
}
else /* Accumulate if greater than this range */
{
fixed partial;
partial=FIXED_MUL(INT_TO_FIXED((long)warp->pWarp[i].high-(long)warp->pWarp[i].low),
warp->pWarp[i].mult);
accum=FIXED_ADD(accum, partial);
}
}
if(sign==1)
return accum;
else
return -accum;
#if 0 /* Old technique */
if((absValue>=warp->pWarp[i].low) && (absValue<=warp->pWarp[i].high))
if(warp->pWarp[i].shift>=0)
value=accum+((absValue-warp->pWarp[i].low)<<warp->pWarp[i].shift);
else
value=accum+((absValue-warp->pWarp[i].low)>>abs(warp->pWarp[i].shift));
else
if(warp->pWarp[i].shift>=0)
accum+=(warp->pWarp[i].high-warp->pWarp[i].low)<<warp->pWarp[i].shift;
else
accum+=(warp->pWarp[i].high-warp->pWarp[i].low)>>abs(warp->pWarp[i].shift);
if(absValue>warp->pWarp[warp->nWarp-1].high)
value=accum;
return sign*value;
#endif
}
/*-------------------------------------------------------------------------*/
long SbConfigWarp(WarpRecord *warp, short value)
{
/* An apparent bug in the msc70 compiler, trashes r
if it is on the stack. Leave in unitialized global segment.
*/
static fixed r;
r = SbFxConfigWarp(warp,value);
return r >> 16 ;
}
/*-------------------------------------------------------------------------*/