/*************************************************************************** ** AGIFILES.C ** ** Routines to handle AGI file system. These functions should enable you ** to load individual LOGIC, VIEW, PIC, and SOUND files into memory. The ** data is stored in a structure of type AGIFile. There is no code that ** is specific to the above types of data file though. ** ** (c) 1997 Lance Ewing ***************************************************************************/ #include #include #include "general.h" #include "agifiles.h" #define EMPTY 0xFFFFF /* Empty DIR entry */ AGIFilePosType logdir[256], picdir[256], viewdir[256], snddir[256]; int numLogics, numPictures, numViews, numSounds; /*************************************************************************** ** loadAGIDir ** ** Purpose: To read in an individual AGI directory file. This function ** should only be called by loadAGIDirs() below. ***************************************************************************/ void loadAGIDir(int dirNum, char *fName, int *count) { FILE *fp; unsigned char byte1, byte2, byte3; AGIFilePosType tempPos; fpos_t pos; if ((fp = fopen(fName, "rb")) == NULL) { printf("Could not find file : %s.\n", fName); printf("Make sure you are in an AGI version 2 game directory.\n"); exit(0); } while (!feof(fp)) { byte1 = fgetc(fp); byte2 = fgetc(fp); byte3 = fgetc(fp); fgetpos(fp, &pos); tempPos.fileName = (char *)malloc(10); sprintf(tempPos.fileName, "VOL.%d", ((byte1 & 0xF0) >> 4)); tempPos.filePos = ((long)((byte1 & 0x0F) << 16) + (long)((byte2 & 0xFF) << 8) + (long)(byte3 & 0xFF)); switch (dirNum) { case 0: logdir[*count] = tempPos; break; case 1: picdir[*count] = tempPos; break; case 2: viewdir[*count] = tempPos; break; case 3: snddir[*count] = tempPos; break; } (*count)++; } fclose(fp); } /*************************************************************************** ** loadAGIDirs ** ** Purpose: To read the AGI directory files LOGDIR, PICDIR, VIEWDIR, and ** SNDDIR and store the information in a usable format. This function must ** be called once at the start of the interpreter. ***************************************************************************/ void loadAGIDirs() { numLogics = numPictures = numViews = numSounds = 0; loadAGIDir(0, "LOGDIR", &numLogics); loadAGIDir(1, "PICDIR", &numPictures); loadAGIDir(2, "VIEWDIR", &numViews); loadAGIDir(3, "SNDDIR", &numSounds); } /************************************************************************** ** loadAGIFile ** ** Purpose: To read an AGI data file out of a VOL file and store the data ** and data size into the AGIFile structure whose pointer is passed in. **************************************************************************/ void loadAGIFile(AGIFilePosType location, AGIFile *AGIData) { FILE *fp; short int sig; unsigned char byte1, byte2; if (location.filePos == EMPTY) { printf("Could not find requested AGI file.\n"); printf("This could indicate problems with your game data files\n"); printf("or there may be something wrong with MEKA.\n"); exit(0); } if ((fp = fopen(location.fileName, "rb")) == NULL) { printf("Could not find file : %s.\n", location.fileName); printf("Make sure you are in an AGI version 2 game directory.\n"); exit(0); } fseek(fp, location.filePos, SEEK_SET); fread(&sig, 2, 1, fp); if (sig != 0x3412) { /* All AGI data files start with 0x1234 */ printf("Data error reading %s.\n", location.fileName); printf("The requested AGI file did not have a signature.\n"); printf("Check that if your game files are corrupt.\n"); exit(0); } fgetc(fp); /* Ignore VOL file number. Not needed. */ byte1 = fgetc(fp); byte2 = fgetc(fp); AGIData->size = (unsigned int)(byte1) + (unsigned int)(byte2 << 8); AGIData->data = (char *)malloc(AGIData->size); fread(AGIData->data, AGIData->size, 1, fp); fclose(fp); }