00001
00002
00003
00004
00005
00006
00007 #include <stdlib.h>
00008 #include <math.h>
00009 #include <Assert.h>
00010 #include <ctype.h>
00011
00012 #define WIN32_LEAN_AND_MEAN
00013 #include <windows.h>
00014
00015 #include "Genesis.h"
00016 #include "Ram.h"
00017 #include "Errorlog.h"
00018 #include "Stdio.h"
00019 #include "String.h"
00020
00021 #include "ProcEng.h"
00022 #include "Procedural.h"
00023
00024
00025 typedef Procedural_Table * (*GetProceduralFunc)(void);
00026
00027 extern GetProceduralFunc GetProceduralFunctions[];
00028 extern int NumGetProceduralFunctions;
00029
00030 #define PROCENG_MAX_PTABLES 32 // Pre-Loaded tables that procs attach to
00031 #define PROCENG_MAX_PROCS 256 // Actual procs (created from table data)
00032
00033
00034
00035 typedef struct ProcEng_PTable
00036 {
00037 char DllName[_MAX_PATH];
00038 HINSTANCE DllHandle;
00039 Procedural_Table *Table;
00040 int Uses;
00041 } ProcEng_PTable;
00042
00043 typedef struct ProcEng_Proc
00044 {
00045 Procedural_Table *Table;
00046 Procedural *Proc;
00047 geBitmap *Bitmap;
00048 } ProcEng_Proc;
00049
00050 typedef struct ProcEng
00051 {
00052 geWorld *World;
00053
00054 int32 NumPTables;
00055 ProcEng_PTable PTables[PROCENG_MAX_PTABLES];
00056
00057 int32 NumProcs;
00058 ProcEng_Proc Procs[PROCENG_MAX_PROCS];
00059 } ProcEng;
00060
00061 geBoolean VFile_ReadBetween(geVFile * File,char *Into,char Start,char Stop);
00062 geBoolean VFile_SeekPastString(geVFile * File,const char *str);
00063 geBoolean VFile_SeekPastSpaces(geVFile * File);
00064 int VFile_GetC(geVFile * File);
00065 void VFile_UnGetC(geVFile * File);
00066 static char * stristr(const char *StrBase,const char *SubBase);
00067
00068 #define SkipWhite(p) while ( isspace(*p) ) p++
00069 #define SkipNonWhite(p) while ( ! isspace(*p) && *p ) p++
00070
00071
00072
00073
00074 ProcEng *ProcEng_Create(geVFile *CfgFile, geWorld *World)
00075 {
00076 ProcEng *PEng;
00077 int32 i;
00078
00079
00080 PEng = geRam_Allocate(sizeof(*PEng));
00081
00082 if (!PEng)
00083 return GE_FALSE;
00084
00085 memset(PEng, 0, sizeof(*PEng));
00086
00087
00088
00089 for(i=0;i<NumGetProceduralFunctions;i++)
00090 {
00091 if ( GetProceduralFunctions[i] )
00092 {
00093 Procedural_Table * pTable;
00094 pTable = (*GetProceduralFunctions[i]) ();
00095 if ( pTable->Tag == Procedurals_Tag &&
00096 pTable->Version == Procedurals_Version )
00097 {
00098 PEng->PTables[PEng->NumPTables].DllHandle = NULL;
00099 PEng->PTables[PEng->NumPTables].Table = pTable;
00100 PEng->PTables[PEng->NumPTables].Uses = 0;
00101 PEng->NumPTables ++;
00102 }
00103 else if ( pTable->Tag == Procedurals_Tag )
00104 {
00105
00106
00107
00108 }
00109 }
00110 }
00111
00112 do
00113 {
00114 geVFile * FileBase;
00115 geVFile_Finder * Finder;
00116 char BasePath[1024];
00117
00118
00119
00120 strcpy(BasePath,"c:\\genesis\\procedurals");
00121
00122 FileBase = geVFile_OpenNewSystem(NULL,GE_VFILE_TYPE_DOS,BasePath,NULL,GE_VFILE_OPEN_READONLY|GE_VFILE_OPEN_DIRECTORY);
00123 if ( ! FileBase )
00124 {
00125
00126
00127 break;
00128 }
00129
00130 Finder = geVFile_CreateFinder(FileBase,"*.dll");
00131 if ( ! Finder )
00132 {
00133
00134 geVFile_Close(FileBase);
00135 break;
00136 }
00137
00138 while( geVFile_FinderGetNextFile(Finder) )
00139 {
00140 GetProceduralFunc GetProcFunc;
00141 HMODULE TheDll;
00142 geVFile_Properties Properties;
00143 char DLLName[_MAX_PATH];
00144 Procedural_Table * pTable;
00145
00146 geVFile_FinderGetProperties(Finder,&Properties);
00147
00148 strcpy(DLLName,BasePath);
00149 strcat(DLLName,"\\");
00150 strcat(DLLName,Properties.Name);
00151
00152 TheDll = LoadLibrary(DLLName);
00153 if ( ! TheDll )
00154 {
00155 #if 0
00156
00157
00158
00159
00160
00161 {
00162 char string[1024];
00163 int plen;
00164 DWORD err;
00165
00166 err = GetLastError();
00167 sprintf(string,"Windows Error : %d = %08X : \0",err,err);
00168 plen = strlen(string);
00169 FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM , NULL, err, 0, string+plen, sizeof(string)-plen, NULL);
00170 geErrorLog_AddString(-1,string);
00171 }
00172 #endif
00173
00174 continue;
00175 }
00176
00177 GetProcFunc = (GetProceduralFunc) GetProcAddress(TheDll,"GetProceduralTable");
00178
00179 if ( ! GetProcFunc )
00180 {
00181
00182
00183
00184 FreeLibrary(TheDll);
00185 continue;
00186 }
00187
00188 pTable = GetProcFunc();
00189 if ( !pTable || pTable->Tag != Procedurals_Tag || pTable->Version != Procedurals_Version )
00190 {
00191
00192
00193
00194 FreeLibrary(TheDll);
00195 continue;
00196 }
00197
00198 strcpy(PEng->PTables[PEng->NumPTables].DllName,DLLName);
00199 PEng->PTables[PEng->NumPTables].DllHandle = TheDll;
00200 PEng->PTables[PEng->NumPTables].Table = pTable;
00201 PEng->PTables[PEng->NumPTables].Uses = 0;
00202 PEng->NumPTables ++;
00203 }
00204
00205 geVFile_DestroyFinder(Finder);
00206 geVFile_Close(FileBase);
00207 }
00208 while(0);
00209
00210 if ( CfgFile && VFile_SeekPastString(CfgFile,"procedurals") )
00211 {
00212
00213 if ( ! VFile_SeekPastString(CfgFile,"{") )
00214 goto ExitWithError;
00215
00216 for(;;)
00217 {
00218 char *TargetName,*ProcName;
00219 geBitmap *Bitmap;
00220 char InputStr[1024];
00221 char *p;
00222 int ReadLen;
00223
00224 if ( ! VFile_SeekPastSpaces(CfgFile) )
00225 goto ExitWithError;
00226
00227 if ( ! geVFile_GetS(CfgFile,InputStr,sizeof(InputStr)) )
00228 goto ExitWithError;
00229
00230 ReadLen = strlen(InputStr) + 1;
00231
00232 if ( p = strchr(InputStr,'}') )
00233 {
00234 p ++;
00235
00236 geVFile_Seek(CfgFile, (int)p - ((int)InputStr + ReadLen), GE_VFILE_SEEKCUR);
00237 break;
00238 }
00239
00240 p = InputStr;
00241 SkipWhite(p);
00242 if ( strnicmp(p,"wbm:",4) == 0 )
00243 {
00244 char ParamStr[4096];
00245 int SeekLen;
00246
00247
00248 p += 4;
00249 SkipWhite(p);
00250 TargetName = p;
00251 SkipNonWhite(p);
00252 if ( *p ) *p++ = 0;
00253 SkipWhite(p);
00254 ProcName = p;
00255 SkipNonWhite(p);
00256
00257 if ( strchr(ProcName,'(') < p && strchr(ProcName,'(') )
00258 {
00259 p = strchr(ProcName,'(');
00260 SeekLen = (int)p - ((int)InputStr + ReadLen);
00261
00262 *p = 0;
00263 }
00264 else
00265 {
00266 SeekLen = (int)p - ((int)InputStr + ReadLen);
00267 *p = 0;
00268 }
00269
00270
00271 if ( ! geVFile_Seek(CfgFile, SeekLen, GE_VFILE_SEEKCUR) )
00272 goto ExitWithError;
00273
00274 VFile_ReadBetween(CfgFile,ParamStr,'(',')');
00275
00276
00277 Bitmap = geWorld_GetBitmapByName(World, TargetName);
00278
00279 if (!Bitmap)
00280 {
00281
00282
00283
00284 }
00285
00286
00287 if ( ! ProcEng_AddProcedural(PEng, ProcName, &Bitmap, ParamStr) )
00288 {
00289
00290
00291
00292 }
00293 }
00294 }
00295 }
00296
00297 PEng->World = World;
00298
00299
00300 return PEng;
00301
00302 ExitWithError:
00303
00304 geErrorLog_AddString(-1,"ProcEng_Create : failure!", NULL);
00305
00306 if (PEng)
00307 {
00308 ProcEng_Destroy(&PEng);
00309 }
00310
00311 return NULL;
00312 }
00313
00314
00315
00316
00317 void ProcEng_Destroy(ProcEng **pPEng)
00318 {
00319 int32 i;
00320 ProcEng_Proc *pProc;
00321 ProcEng_PTable *pTable;
00322 ProcEng *PEng;
00323
00324 assert(pPEng);
00325
00326 PEng = *pPEng;
00327 if ( ! PEng )
00328 return;
00329
00330
00331 pProc = PEng->Procs;
00332 for (i=0; i< PEng->NumProcs; i++, pProc++)
00333 {
00334 assert(pProc->Table);
00335 assert(pProc->Proc);
00336
00337 pProc->Table->Destroy(pProc->Proc);
00338
00339 geBitmap_Destroy(&(pProc->Bitmap));
00340
00341 memset(pProc, 0, sizeof(*pProc));
00342 }
00343 PEng->NumProcs = 0;
00344
00345
00346 pTable = PEng->PTables;
00347 for (i=0; i< PEng->NumPTables; i++, pTable++)
00348 {
00349 if ( pTable->DllHandle )
00350 {
00351 FreeLibrary(pTable->DllHandle);
00352 }
00353 memset(pTable, 0, sizeof(*pTable));
00354 }
00355 PEng->NumPTables = 0;
00356
00357
00358
00359 PEng->World = NULL;
00360
00361 geRam_Free(PEng);
00362
00363 *pPEng = NULL;
00364 }
00365
00366
00367
00368
00369 geBoolean ProcEng_Minimize(ProcEng *PEng)
00370 {
00371 ProcEng_PTable *pTable;
00372 ProcEng_PTable *pTableLast;
00373
00374 assert(PEng);
00375
00376
00377 pTable = PEng->PTables;
00378 pTableLast = pTable + (PEng->NumPTables - 1);
00379 while( pTable <= pTableLast )
00380 {
00381 if ( pTable->Uses < 1 )
00382 {
00383 if ( pTable->DllHandle )
00384 {
00385 FreeLibrary(pTable->DllHandle);
00386 }
00387 *pTable = *pTableLast;
00388 pTableLast--;
00389 PEng->NumPTables --;
00390 }
00391 else
00392 {
00393 pTable ++;
00394 }
00395 }
00396 return GE_TRUE;
00397 }
00398
00399
00400
00401
00402
00403 geBoolean ProcEng_AddProcedural(ProcEng *PEng, const char *ProcName, geBitmap **pBitmap, const char * Params)
00404 {
00405 int32 i;
00406 ProcEng_PTable *pTable;
00407
00408 assert(PEng);
00409 assert(ProcName);
00410 assert(pBitmap);
00411
00412 if (PEng->NumProcs+1 >= PROCENG_MAX_PROCS)
00413 {
00414 geErrorLog_AddString(-1, "ProcEng_AddProcedural: Max procs.", NULL);
00415 return GE_FALSE;
00416 }
00417
00418
00419 pTable = PEng->PTables;
00420 for (i=0; i< PEng->NumPTables; i++, pTable++)
00421 {
00422
00423 if ( stricmp(pTable->Table->Name, ProcName) == 0)
00424 break;
00425 }
00426
00427 if (i == PEng->NumPTables)
00428 {
00429 geErrorLog_AddString(-1, "ProcEng_AddProcedural: Table not found for procedural.", NULL);
00430 return GE_FALSE;
00431 }
00432
00433 assert(pTable->Table);
00434
00435
00436 PEng->Procs[PEng->NumProcs].Proc = pTable->Table->Create(pBitmap, Params);
00437
00438 if (!PEng->Procs[PEng->NumProcs].Proc)
00439 {
00440 geErrorLog_AddString(-1," ProcEng_AddProcedural: (%s)->Create failed", pTable->Table->Name);
00441 return GE_FALSE;
00442 }
00443 if (! *pBitmap)
00444 {
00445 geErrorLog_AddString(-1,"ProcEng_AddProcedural: No Bitmap:", pTable->Table->Name);
00446 return GE_FALSE;
00447 }
00448
00449 PEng->Procs[PEng->NumProcs].Bitmap = *pBitmap;
00450 PEng->Procs[PEng->NumProcs].Table = pTable->Table;
00451
00452 geBitmap_CreateRef(*pBitmap);
00453
00454
00455 PEng->NumProcs++;
00456
00457 pTable->Uses ++;
00458
00459 return GE_TRUE;
00460 }
00461
00462
00463
00464
00465 geBoolean ProcEng_Animate(ProcEng *PEng, float ElapsedTime)
00466 {
00467 int32 i;
00468 ProcEng_Proc *pProc;
00469
00470 pProc = PEng->Procs;
00471 for (i=0; i< PEng->NumProcs; i++, pProc++)
00472 {
00473 assert(pProc->Table);
00474 assert(pProc->Proc);
00475
00476 if (!geWorld_BitmapIsVisible(PEng->World, pProc->Bitmap))
00477 continue;
00478
00479 if (!pProc->Table->Animate(pProc->Proc, ElapsedTime))
00480 {
00481 geErrorLog_AddString(-1,"ProcEng_Animate: pProc->Table->Animate failed", NULL);
00482 return GE_FALSE;
00483 }
00484 }
00485 return GE_TRUE;
00486 }
00487
00488
00489
00490
00491
00492
00493 geBoolean VFile_SeekPastString(geVFile * File,const char *str)
00494 {
00495 long LastPosition;
00496 char Buf[1024];
00497 int len;
00498
00499 if ( strlen(str) == 0 )
00500 return GE_FALSE;
00501
00502 if ( ! geVFile_Tell(File,&LastPosition) )
00503 return GE_FALSE;
00504
00505 for(;;)
00506 {
00507 if ( ! VFile_SeekPastSpaces(File) )
00508 goto fail;
00509
00510 len = strlen(str);
00511 if ( ! geVFile_Read(File,Buf,len) )
00512 goto fail;
00513 Buf[len] = 0;
00514
00515 if ( stricmp(Buf,str) == 0 )
00516 return GE_TRUE;
00517
00518 len = 1 - len;
00519 if ( ! geVFile_Seek(File,len,GE_VFILE_SEEKCUR) )
00520 goto fail;
00521 }
00522
00523 fail:
00524
00525 geVFile_Seek(File,LastPosition,GE_VFILE_SEEKSET);
00526 return GE_FALSE;
00527 }
00528
00529 int VFile_GetC(geVFile * File)
00530 {
00531 uint8 Char;
00532 if ( ! geVFile_Read(File,&Char,1) )
00533 return -1;
00534 return (int)Char;
00535 }
00536
00537 void VFile_UnGetC(geVFile * File)
00538 {
00539 geVFile_Seek(File,-1,GE_VFILE_SEEKCUR);
00540 }
00541
00542 geBoolean VFile_SeekPastSpaces(geVFile * File)
00543 {
00544 long LastPosition;
00545 int Char;
00546
00547 if ( ! geVFile_Tell(File,&LastPosition) )
00548 return GE_FALSE;
00549
00550 while( (Char = VFile_GetC(File)) != -1 )
00551 {
00552 if ( ! isspace(Char) )
00553 {
00554 VFile_UnGetC(File);
00555 return GE_TRUE;
00556 }
00557 }
00558 geVFile_Seek(File,LastPosition,GE_VFILE_SEEKSET);
00559 return GE_FALSE;
00560 }
00561
00562 static char * stristr(const char *StrBase,const char *SubBase)
00563 {
00564
00565 while ( *StrBase )
00566 {
00567 if ( toupper(*StrBase) == toupper(*SubBase) )
00568 {
00569 const char * Str,* Sub;
00570 Str = StrBase + 1;
00571 Sub = SubBase + 1;
00572 while ( *Sub && toupper(*Sub) == toupper(*Str) )
00573 {
00574 Sub++; Str++;
00575 }
00576 if ( ! *Sub) return((char *)StrBase);
00577 }
00578 StrBase++;
00579 }
00580
00581 return(NULL);
00582 }
00583
00584 geBoolean VFile_ReadBetween(geVFile * File,char *Into,char Start,char Stop)
00585 {
00586 int c;
00587 int ins;
00588
00589 Into[0] = 0;
00590
00591 if ( ! VFile_SeekPastSpaces(File) )
00592 return GE_FALSE;
00593
00594 if ( (c = VFile_GetC(File)) == Start )
00595 {
00596 char *p;
00597 ins = 1;
00598 p = Into;
00599 for(;;)
00600 {
00601 c = VFile_GetC(File);
00602 if ( c == -1 )
00603 {
00604 *p = 0;
00605 return GE_FALSE;
00606 }
00607 *p = c;
00608 if ( c == Start ) ins ++;
00609 else if ( c == Stop ) ins --;
00610 if ( ins == 0 ) break;
00611 p++;
00612 }
00613 *p = 0;
00614 }
00615 else
00616 {
00617 if ( c == -1 )
00618 return GE_FALSE;
00619 else
00620 VFile_UnGetC(File);
00621 }
00622
00623 return GE_TRUE;
00624 }