/* ScummVM - Graphic Adventure Engine
 *
 * ScummVM is the legal property of its developers, whose names
 * are too numerous to list here. Please refer to the COPYRIGHT
 * file distributed with this source distribution.
 *
 * 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 3 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, see <http://www.gnu.org/licenses/>.
 *
 */

#include "common/memstream.h"
#include "common/textconsole.h"

#include "cruise/cruise.h"
#include "cruise/cruise_main.h"

namespace Cruise {

overlayStruct overlayTable[90];
int numOfLoadedOverlay;

void initOverlayTable() {
	for (int i = 0; i < 90; i++) {
		overlayTable[i].overlayName[0] = 0;
		overlayTable[i].ovlData = nullptr;
		overlayTable[i].alreadyLoaded = 0;
		overlayTable[i].executeScripts = 0;
	}

	numOfLoadedOverlay = 1;
}

void freeOverlayTable() {
	for (int i = 0; i < 90; i++) {
		if (overlayTable[i].alreadyLoaded)
			freeOverlay(i);
	}
}

int freeOverlay(int overlayIdx) {
	ovlDataStruct *ovlDataPtr;

	if (overlayTable[overlayIdx].alreadyLoaded == 0)
		return -4;

	overlayTable[overlayIdx].alreadyLoaded = 0;

	ovlDataPtr = overlayTable[overlayIdx].ovlData;

	if (!ovlDataPtr)
		return -4;

	/*
	  if (overlayTable[overlayIdx].var1E) {
	    MemFree(overlayTable[overlayIdx].var1E);
	    overlayTable[overlayIdx].var1E = NULL;
	  }

	  if (overlayTable[overlayIdx].var16) {
	    MemFree(overlayTable[overlayIdx].var16);
	    overlayTable[overlayIdx].var16 = NULL;
	  } */

	removeScript(overlayIdx, -1, &procHead);
	removeScript(overlayIdx, -1, &procHead);

	removeScript(overlayIdx, -1, &relHead);
	removeScript(overlayIdx, -1, &relHead);

	if (ovlDataPtr->stringTable) {
		for (int i = 0; i < ovlDataPtr->numStrings; ++i)
			MemFree(ovlDataPtr->stringTable[i].string);
		MemFree(ovlDataPtr->stringTable);
	}
	if (ovlDataPtr->arrayProc) {
		ovlData3Struct *tempPtr = ovlDataPtr->arrayProc;
		for (int i = 0; i < ovlDataPtr->numProc; ++i, ++tempPtr)
			MemFree(tempPtr->dataPtr);
		MemFree(ovlDataPtr->arrayProc);
	}
	if (ovlDataPtr->ptr1) {
		ovlData3Struct *tempPtr = (ovlData3Struct *)ovlDataPtr->ptr1;
		for (int i = 0; i < ovlDataPtr->numRel; ++i, ++tempPtr)
			MemFree(tempPtr->dataPtr);
		MemFree(ovlDataPtr->ptr1);
	}

	MemFree(ovlDataPtr->arraySymbGlob);
	MemFree(ovlDataPtr->arrayNameSymbGlob);
	MemFree(ovlDataPtr->data4Ptr);
	MemFree(ovlDataPtr->arrayMsgRelHeader);
	MemFree(ovlDataPtr->ptr8);
	MemFree(ovlDataPtr->arrayObject);
	MemFree(ovlDataPtr->arrayObjVar);
	MemFree(ovlDataPtr->arrayStates);
	MemFree(ovlDataPtr->nameVerbGlob);
	MemFree(ovlDataPtr->arrayNameObj);
	MemFree(ovlDataPtr->arrayRelocGlob);
	MemFree(ovlDataPtr->arrayNameRelocGlob);

	MemFree(ovlDataPtr);
	overlayTable[overlayIdx].ovlData = nullptr;

	debug(1, "freeOverlay: finish !");

	return 0;
}

int loadOverlay(const char *scriptName) {
	int newNumberOfScript;
	bool scriptNotLoadedBefore;
	int scriptIdx;
	char fileName[50];
	int fileIdx;
	int unpackedSize;
	byte *unpackedBuffer;
	ovlDataStruct *ovlData;

	debug(1, "Load overlay: %s", scriptName);

	newNumberOfScript = numOfLoadedOverlay;

	scriptNotLoadedBefore = false;

	scriptIdx = findOverlayByName((const char *)scriptName);

	if (scriptIdx == -4) {
		scriptIdx = numOfLoadedOverlay;

		newNumberOfScript++;

		scriptNotLoadedBefore = true;
	}

	if (overlayTable[scriptIdx].alreadyLoaded) {
		return (scriptIdx);
	}

	overlayTable[scriptIdx].ovlData =
	    (ovlDataStruct *) mallocAndZero(sizeof(ovlDataStruct));

	if (!overlayTable[scriptIdx].ovlData)
		return (-2);

	if (scriptName != overlayTable[scriptIdx].overlayName)
		Common::strlcpy(overlayTable[scriptIdx].overlayName, scriptName, sizeof(overlayTable[scriptIdx].overlayName));

	overlayTable[scriptIdx].alreadyLoaded = 1;

	numOfLoadedOverlay = newNumberOfScript;

	overlayTable[scriptIdx].ovlData->scriptNumber = scriptIdx;

	Common::strlcpy(fileName, scriptName, sizeof(fileName));
	Common::strlcat(fileName, ".OVL", sizeof(fileName));

	debug(1, "Attempting to load overlay file %s...", fileName);

	fileIdx = findFileInDisks(fileName);

	if (fileIdx < 0) {
		warning("Unable to load overlay %s", scriptName);
		//releaseScript(scriptName);
		return (-18);
	}

	unpackedSize = volumePtrToFileDescriptor[fileIdx].extSize + 2;

	// This memory block will be later passed to a MemoryReadStream, which will dispose of it
	unpackedBuffer = (byte *)malloc(unpackedSize);
	if (!unpackedBuffer) {
		return (-2);
	}
	memset(unpackedBuffer, 0, unpackedSize);

	if (volumePtrToFileDescriptor[fileIdx].size + 2 != unpackedSize) {
		char *pakedBuffer =
		    (char *)mallocAndZero(volumePtrToFileDescriptor[fileIdx].
		                          size + 2);

		loadPackedFileToMem(fileIdx, (uint8 *) pakedBuffer);

		delphineUnpack((uint8 *)unpackedBuffer, (const uint8 *)pakedBuffer, volumePtrToFileDescriptor[fileIdx].size);

		MemFree(pakedBuffer);
	} else {
		loadPackedFileToMem(fileIdx, (uint8 *) unpackedBuffer);
	}

	debug(1, "OVL loading done...");

	Common::MemoryReadStream s(unpackedBuffer, unpackedSize, DisposeAfterUse::YES);
	unpackedBuffer = nullptr;

	ovlData = overlayTable[scriptIdx].ovlData;

	// Skip pointers
	s.skip(60);

	ovlData->arrayProc = nullptr;
	ovlData->ptr1 = nullptr;
	ovlData->arrayObject = nullptr;
	ovlData->arrayStates = nullptr;
	ovlData->arrayObjVar = nullptr;
	ovlData->stringTable = nullptr;
	ovlData->arraySymbGlob = nullptr;
	ovlData->arrayRelocGlob = nullptr;
	ovlData->arrayMsgRelHeader = nullptr;
	ovlData->nameVerbGlob = nullptr;
	ovlData->arrayNameObj = nullptr;
	ovlData->arrayNameRelocGlob = nullptr;
	ovlData->arrayNameSymbGlob = nullptr;
	ovlData->data4Ptr = nullptr;
	ovlData->ptr8 = nullptr;
	ovlData->numProc = s.readUint16BE();
	ovlData->numRel = s.readUint16BE();
	ovlData->numSymbGlob = s.readUint16BE();
	ovlData->numRelocGlob = s.readUint16BE();
	ovlData->numMsgRelHeader = s.readUint16BE();
	ovlData->numObj = s.readUint16BE();
	ovlData->numStrings = s.readUint16BE();
	ovlData->size8 = s.readUint16BE();
	ovlData->size9 = s.readUint16BE();
	ovlData->nameExportSize = s.readUint16BE();
	ovlData->exportNamesSize = s.readUint16BE();
	ovlData->specialString2Length = s.readUint16BE();
	ovlData->sizeOfData4 = s.readUint16BE();
	ovlData->size12 = s.readUint16BE();
	ovlData->specialString1Length = s.readUint16BE();
	ovlData->scriptNumber = s.readUint16BE();

	if (ovlData->numSymbGlob)	{ // export data
		ovlData->arraySymbGlob =
		    (exportEntryStruct *) mallocAndZero(ovlData->numSymbGlob * sizeof(exportEntryStruct));

		if (!ovlData->arraySymbGlob)
			return (-2);

		for (int i = 0; i < ovlData->numSymbGlob; i++) {
			ovlData->arraySymbGlob[i].var0 = s.readUint16BE();
			ovlData->arraySymbGlob[i].var2 = s.readUint16BE();
			ovlData->arraySymbGlob[i].var4 = s.readUint16BE();
			ovlData->arraySymbGlob[i].idx = s.readUint16BE();
			ovlData->arraySymbGlob[i].offsetToName = s.readUint16BE();
		}
	}

	if (ovlData->exportNamesSize) {	// export names
		ovlData->arrayNameSymbGlob = (char *) mallocAndZero(ovlData->exportNamesSize);

		if (!ovlData->arrayNameSymbGlob) {
			return (-2);
		}

		s.read(ovlData->arrayNameSymbGlob, ovlData->exportNamesSize);
	}

	if (ovlData->numRelocGlob) {	// import data
		ovlData->arrayRelocGlob =
		    (importDataStruct *) mallocAndZero(ovlData->numRelocGlob *
		                                       sizeof(importDataStruct));

		if (!ovlData->arrayRelocGlob)
			return (-2);

		for (int i = 0; i < ovlData->numRelocGlob; i++) {
			ovlData->arrayRelocGlob[i].var0 = s.readUint16BE();
			ovlData->arrayRelocGlob[i].var1 = s.readUint16BE();
			ovlData->arrayRelocGlob[i].linkType = s.readUint16BE();
			ovlData->arrayRelocGlob[i].linkIdx = s.readUint16BE();
			ovlData->arrayRelocGlob[i].nameOffset = s.readUint16BE();
		}
	}

	if (ovlData->nameExportSize) {	// import name
		ovlData->arrayNameRelocGlob = (char *) mallocAndZero(ovlData->nameExportSize);

		if (!ovlData->arrayNameRelocGlob) {
			return (-2);
		}

		s.read(ovlData->arrayNameRelocGlob, ovlData->nameExportSize);
	}

	if (ovlData->numMsgRelHeader) {	// link data
		assert(sizeof(linkDataStruct) == 0x22);

		ovlData->arrayMsgRelHeader = (linkDataStruct *) mallocAndZero(ovlData->numMsgRelHeader * sizeof(linkDataStruct));

		if (!ovlData->arrayMsgRelHeader)
			return (-2);

		for (int i = 0; i < ovlData->numMsgRelHeader; i++) {
			ovlData->arrayMsgRelHeader[i].type = s.readUint16BE();
			ovlData->arrayMsgRelHeader[i].id = s.readUint16BE();
			ovlData->arrayMsgRelHeader[i].offsetVerbeName = s.readUint16BE();
			ovlData->arrayMsgRelHeader[i].verbOverlay = s.readUint16BE();
			ovlData->arrayMsgRelHeader[i].verbNumber = s.readUint16BE();

			ovlData->arrayMsgRelHeader[i].obj1Overlay = s.readUint16BE();
			ovlData->arrayMsgRelHeader[i].obj1Number = s.readUint16BE();
			ovlData->arrayMsgRelHeader[i].obj2Overlay = s.readUint16BE();
			ovlData->arrayMsgRelHeader[i].obj2Number = s.readUint16BE();

			ovlData->arrayMsgRelHeader[i].trackX = s.readUint16BE();
			ovlData->arrayMsgRelHeader[i].trackY = s.readUint16BE();

			ovlData->arrayMsgRelHeader[i].obj1NewState = s.readUint16BE();
			ovlData->arrayMsgRelHeader[i].obj2NewState = s.readUint16BE();

			ovlData->arrayMsgRelHeader[i].obj1OldState = s.readUint16BE();
			ovlData->arrayMsgRelHeader[i].obj2OldState = s.readUint16BE();

			ovlData->arrayMsgRelHeader[i].trackDirection = s.readUint16BE();
			ovlData->arrayMsgRelHeader[i].dialog = s.readUint16BE();
		}
	}

	if (ovlData->numProc) {	// script
		ovlData3Struct *tempPtr;

		ovlData->arrayProc = (ovlData3Struct *) mallocAndZero(ovlData->numProc * sizeof(ovlData3Struct));

		if (!ovlData->arrayProc)
			return (-2);

		for (int i = 0; i < ovlData->numProc; i++) {
			s.skip(4);
			ovlData->arrayProc[i].dataPtr = nullptr;
			ovlData->arrayProc[i].sizeOfData = s.readUint16BE();
			ovlData->arrayProc[i].offsetToSubData3 = s.readUint16BE();
			ovlData->arrayProc[i].offsetToImportData = s.readUint16BE();
			ovlData->arrayProc[i].offsetToSubData2 = s.readUint16BE();
			ovlData->arrayProc[i].offsetToImportName = s.readUint16BE();
			ovlData->arrayProc[i].offsetToSubData5 = s.readUint16BE();
			ovlData->arrayProc[i].sysKey = s.readUint16BE();
			ovlData->arrayProc[i].var12 = s.readUint16BE();
			ovlData->arrayProc[i].numRelocGlob = s.readUint16BE();
			ovlData->arrayProc[i].subData2Size = s.readUint16BE();
			ovlData->arrayProc[i].var18 = s.readUint16BE();
			ovlData->arrayProc[i].var1A = s.readUint16BE();
		}

		tempPtr = ovlData->arrayProc;

		for (int i = 0; i < ovlData->numProc; i++) {
			tempPtr->dataPtr = (uint8 *) mallocAndZero(tempPtr->sizeOfData);

			if (!tempPtr->dataPtr) {
				return (-2);
			}

			s.read(tempPtr->dataPtr, tempPtr->sizeOfData);

			if (tempPtr->offsetToImportData) {
				flipGen(tempPtr->dataPtr + tempPtr->offsetToImportData,
				        tempPtr->numRelocGlob * 10);
			}

			if (tempPtr->offsetToSubData2) {
				flipGen(tempPtr->dataPtr + tempPtr->offsetToSubData2,
				        tempPtr->subData2Size * 10);
			}

			tempPtr++;
		}
	}

	if (ovlData->numRel) {
		ovlData3Struct *tempPtr;

		ovlData->ptr1 = (ovlData3Struct *) mallocAndZero(ovlData->numRel * sizeof(ovlData3Struct));

		if (!ovlData->ptr1)
			return (-2);

		for (int i = 0; i < ovlData->numRel; i++) {
			s.skip(4);
			ovlData->ptr1[i].dataPtr = nullptr;
			ovlData->ptr1[i].sizeOfData = s.readUint16BE();
			ovlData->ptr1[i].offsetToSubData3 = s.readUint16BE();
			ovlData->ptr1[i].offsetToImportData = s.readUint16BE();
			ovlData->ptr1[i].offsetToSubData2 = s.readUint16BE();
			ovlData->ptr1[i].offsetToImportName = s.readUint16BE();
			ovlData->ptr1[i].offsetToSubData5 = s.readUint16BE();
			ovlData->ptr1[i].sysKey = s.readUint16BE();
			ovlData->ptr1[i].var12 = s.readUint16BE();
			ovlData->ptr1[i].numRelocGlob = s.readUint16BE();
			ovlData->ptr1[i].subData2Size = s.readUint16BE();
			ovlData->ptr1[i].var18 = s.readUint16BE();
			ovlData->ptr1[i].var1A = s.readUint16BE();
		}

		tempPtr = (ovlData3Struct *) ovlData->ptr1;

		for (int i = 0; i < ovlData->numRel; i++) {
			tempPtr->dataPtr = (uint8 *) mallocAndZero(tempPtr->sizeOfData);

			if (!tempPtr->dataPtr)
				return (-2);

			s.read(tempPtr->dataPtr, tempPtr->sizeOfData);

			if (tempPtr->offsetToImportData) {
				flipGen(tempPtr->dataPtr + tempPtr->offsetToImportData,
				        tempPtr->numRelocGlob * 10);
			}

			if (tempPtr->offsetToSubData2) {
				flipGen(tempPtr->dataPtr + tempPtr->offsetToSubData2,
				        tempPtr->subData2Size * 10);
			}

			tempPtr++;
		}
	}

	if (ovlData->size12) {
		ovlData->ptr8 = (uint8 *) mallocAndZero(ovlData->size12);

		if (!ovlData->ptr8) {
			/*      releaseScript(scriptIdx,scriptName);

			      if (freeIsNeeded) {
			        freePtr(unpackedBuffer);
			      } */

			return (-2);
		}

		s.read(ovlData->ptr8, ovlData->size12);
	}

	if (ovlData->numObj) {
		ovlData->arrayObject = (objDataStruct *) mallocAndZero(ovlData->numObj * sizeof(objDataStruct));

		if (!ovlData->arrayObject)
			return (-2);

		for (int i = 0; i < ovlData->numObj; i++) {
			ovlData->arrayObject[i]._type = s.readUint16BE();
			ovlData->arrayObject[i]._class = (eClass) s.readUint16BE();
			ovlData->arrayObject[i]._nameOffset = s.readUint16BE();
			ovlData->arrayObject[i]._numStates = s.readUint16BE();
			ovlData->arrayObject[i]._varTableIdx = s.readUint16BE();
			ovlData->arrayObject[i]._firstStateIdx = s.readUint16BE();
			ovlData->arrayObject[i]._stateTableIdx = s.readUint16BE();
		}

		// allocate states for object with multiple states

		if (scriptNotLoadedBefore) {
			overlayTable[scriptIdx].state = stateID;
			stateID += getNumObjectsByClass(scriptIdx, MULTIPLE) + getNumObjectsByClass(scriptIdx, THEME);
		}
	}

	if (ovlData->size9) {
		ovlData->arrayObjVar =
		    (objectParams *) mallocAndZero(ovlData->size9 *
		                                   sizeof(objectParams));

		if (!ovlData->arrayObjVar) {
			return (-2);
		}
	}

	if (ovlData->size8) {
		ovlData->arrayStates = (objectParams *) mallocAndZero(ovlData->size8 * sizeof(objectParams));

		if (!ovlData->arrayStates)
			return (-2);

		for (int i = 0; i < ovlData->size8; i++) {
			ovlData->arrayStates[i].X = s.readUint16BE();
			ovlData->arrayStates[i].Y = s.readUint16BE();
			ovlData->arrayStates[i].Z = s.readUint16BE();
			ovlData->arrayStates[i].frame = s.readUint16BE();
			ovlData->arrayStates[i].scale = s.readUint16BE();
			ovlData->arrayStates[i].state = s.readUint16BE();
		}
	}

	if (ovlData->numStrings) {
		ovlData->stringTable = (stringEntryStruct *) mallocAndZero(ovlData->numStrings * sizeof(stringEntryStruct));

		for (int i = 0; i < ovlData->numStrings; i++)
			ovlData->stringTable[i].idx = s.readUint16BE();
	}

	if (ovlData->sizeOfData4) {
		ovlData->data4Ptr = (uint8 *) mallocAndZero(ovlData->sizeOfData4);

		if (!ovlData->data4Ptr)
			return (-2);
	}

	if (ovlData->specialString1Length /*|| ovlData->specialString2Length */
	        || ovlData->stringTable) {
		//int unpackedSize;
		//int fileIdx;
		//uint8 fileName[50];
		//char* unpackedBuffer;

		Common::strlcpy(fileName, scriptName, sizeof(fileName));
		Common::strlcat(fileName, ".FR", sizeof(fileName));

		fileIdx = findFileInDisks(fileName);

		if (fileIdx < 0) {
			//releaseScript(scriptName);
			return (-18);
		}

		unpackedSize = volumePtrToFileDescriptor[fileIdx].extSize + 2;

		// This memory block will be later passed to a MemoryReadStream, which will dispose of it
		unpackedBuffer = (byte *)malloc(unpackedSize);
		if (!unpackedBuffer) {
			return (-2);
		}
		memset(unpackedBuffer, 0, unpackedSize);

		if (volumePtrToFileDescriptor[fileIdx].size + 2 !=
		        unpackedSize) {
			char *pakedBuffer =
			    (char *)
			    mallocAndZero(volumePtrToFileDescriptor[fileIdx].
			                  size + 2);

			loadPackedFileToMem(fileIdx, (uint8 *) pakedBuffer);

			delphineUnpack((uint8 *) unpackedBuffer, (const uint8 *)pakedBuffer, volumePtrToFileDescriptor[fileIdx].size);

			MemFree(pakedBuffer);
		} else {
			loadPackedFileToMem(fileIdx, (uint8 *) unpackedBuffer);
		}

		Common::MemoryReadStream s2(unpackedBuffer, unpackedSize, DisposeAfterUse::YES);
		unpackedBuffer = nullptr;

		ovlData->specialString1Length = s2.readUint16BE();
		if (ovlData->specialString1Length) {
			ovlData->nameVerbGlob = (char *) mallocAndZero(ovlData->specialString1Length);

			if (!ovlData->nameVerbGlob) {
				/*      releaseScript(scriptIdx,scriptName);
				 *
				 * if (freeIsNeeded)
				 * {
				 * freePtr(unpackedBuffer);
				 * } */

				return (-2);
			}

			s2.read(ovlData->nameVerbGlob, ovlData->specialString1Length);
		}

		ovlData->specialString2Length = s2.readUint16BE();
		if (ovlData->specialString2Length) {
			ovlData->arrayNameObj = (char *) mallocAndZero(ovlData->specialString2Length);

			if (!ovlData->arrayNameObj) {
				/*      releaseScript(scriptIdx,scriptName);
				 *
				 * if (freeIsNeeded)
				 * {
				 * freePtr(unpackedBuffer);
				 * } */

				return (-2);
			}

			s2.read(ovlData->arrayNameObj, ovlData->specialString2Length);
		}

		for (int i = 0; i < ovlData->numStrings; i++) {
			ovlData->stringTable[i].length = s2.readUint16BE();

			if (ovlData->stringTable[i].length) {
				ovlData->stringTable[i].string =
				    (char *)mallocAndZero(ovlData->
				                          stringTable[i].length);

				if (!ovlData->stringTable[i].string) {
					/*      releaseScript(scriptIdx,scriptName);
					 *
					 * if (freeIsNeeded)
					 * {
					 * freePtr(unpackedBuffer);
					 * } */

					return (-2);
				}

				s2.read(ovlData->stringTable[i].string, ovlData->stringTable[i].length);
			}
		}
	}
#ifdef DUMP_SCRIPT
	{
		for (int i = 0; i < ovlData->numProc; i++) {
			dumpScript(scriptName, ovlData, i);
		}
	}
#endif
#ifdef DUMP_OBJECT
	{
		// TODO: Rewrite this to use Common::DumpFile
		FILE *fHandle;
		char nameBundle[100];
		Common::sprintf_s(nameBundle, "%s-objs.txt", scriptName);

		fHandle = fopen(nameBundle, "w+");
		assert(fHandle);

		for (int i = 0; i < ovlData->numMsgRelHeader; i++) {
			linkDataStruct *var_34;
			var_34 = &ovlData->arrayMsgRelHeader[i];

			if (ovlData->arrayNameObj) {
				fprintf(fHandle, "----- object %02d -----\n",
				        i);
				if (var_34->stringNameOffset != 0xFFFF) {
					fprintf(fHandle, "name: %s\n",
					        getObjectName(var_34->
					                      stringNameOffset,
					                      ovlData->arrayNameObj));
				}
			}
		}

		fclose(fHandle);
	}
#endif

	return (scriptIdx);
}

int releaseOverlay(const char *name) {
	int overlayIdx = findOverlayByName(name);

	if (overlayIdx == -4)
		return -4;

	return freeOverlay(overlayIdx);
}

int32 findOverlayByName2(const char *name) {
	for (int i = 1; i < numOfLoadedOverlay; i++) {
		if (!strcmp(overlayTable[i].overlayName, name))
			return (i);
	}

	return (-4);
}

int findOverlayByName(const char *overlayName) {
	for (int i = 1; i < numOfLoadedOverlay; i++) {
		if (!strcmp(overlayTable[i].overlayName, overlayName))
			return (i);
	}

	return (-4);
}

} // End of namespace Cruise
