scummvm/engines/lab/readparse.cpp
2015-12-15 00:05:02 +01:00

474 lines
11 KiB
C++

/* 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 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
/*
* This code is based on Labyrinth of Time code with assistance of
*
* Copyright (c) 1993 Terra Nova Development
* Copyright (c) 2004 The Wyrmkeep Entertainment Co.
*
*/
#include "lab/labfun.h"
#include "lab/parsetypes.h"
#include "lab/parsefun.h"
#include "lab/stddefines.h"
namespace Lab {
#define MAXSTRINGLENGTH 250
static bool UseMemory = false;
/* Global parser data */
extern RoomData *Rooms;
extern InventoryData *Inventory;
extern uint16 NumInv, ManyRooms, HighestCondition, Direction;
static uint16 allocroom;
static bool rallocate(void **Ptr, uint32 Size) {
if (UseMemory)
return ((*Ptr = calloc(Size, 1)) != 0);
else {
allocRoom(Ptr, (uint16) Size, allocroom);
return true;
}
}
/*****************************************************************************/
/* Reads in the RoomData. */
/*****************************************************************************/
bool readRoomData(const char *fileName) {
byte **file;
uint16 Counter;
char Temp[5];
if ((file = g_music->newOpen(fileName)) != NULL) {
readBlock(Temp, 4L, file);
Temp[4] = '\0';
if (strcmp(Temp, "DOR1") != 0)
return false;
readBlock(&ManyRooms, 2L, file);
#if !defined(DOSCODE)
swapUShortPtr(&ManyRooms, 1);
#endif
readBlock(&HighestCondition, 2L, file);
#if !defined(DOSCODE)
swapUShortPtr(&HighestCondition, 1);
#endif
if ((Rooms = (RoomData *)calloc(ManyRooms + 1, sizeof(RoomData)))) {
for (Counter = 1; Counter <= ManyRooms; Counter++) {
readBlock(&(Rooms[Counter].NorthDoor), 2L, file);
readBlock(&(Rooms[Counter].SouthDoor), 2L, file);
readBlock(&(Rooms[Counter].EastDoor), 2L, file);
readBlock(&(Rooms[Counter].WestDoor), 2L, file);
#if !defined(DOSCODE)
swapUShortPtr(&(Rooms[Counter].NorthDoor), 1);
swapUShortPtr(&(Rooms[Counter].SouthDoor), 1);
swapUShortPtr(&(Rooms[Counter].EastDoor), 1);
swapUShortPtr(&(Rooms[Counter].WestDoor), 1);
#endif
readBlock(&(Rooms[Counter].WipeType), 1L, file);
}
} else
return false;
} else
return false;
return true;
}
/*****************************************************************************/
/* Reads in a NULL terminated string, and allocates memory for it. */
/*****************************************************************************/
static bool readString(char **string, byte **file) {
char len;
uint32 counter = 0L;
readBlock(&len, 1L, file);
if (len) {
counter = len;
if (rallocate((void **) string, counter)) {
readBlock(*string, counter, file);
(*string)[counter - 1] = 0; /* Sanity modification */
decrypt((byte *)*string);
return true;
}
} else {
*string = NULL;
return true;
}
return false;
}
/*****************************************************************************/
/* Reads in the Inventory data. */
/*****************************************************************************/
bool readInventory(const char *fileName) {
byte **file;
uint16 Counter;
char Temp[5];
if ((file = g_music->newOpen(fileName)) != NULL) {
readBlock(Temp, 4L, file);
Temp[4] = '\0';
if (strcmp(Temp, "INV1") != 0)
return false;
readBlock(&NumInv, 2L, file);
#if !defined(DOSCODE)
swapUShortPtr(&NumInv, 1);
#endif
UseMemory = true;
if (rallocate((void **) &Inventory, (NumInv + 1) * sizeof(InventoryData))) {
for (Counter = 1; Counter <= NumInv; Counter++) {
readBlock(&(Inventory[Counter].Many), 2L, file);
#if !defined(DOSCODE)
swapUShortPtr(&(Inventory[Counter].Many), 1);
#endif
if (!readString(&(Inventory[Counter].name), file)) {
UseMemory = false;
return false;
}
if (!readString(&(Inventory[Counter].BInvName), file)) {
UseMemory = false;
return false;
}
}
} else {
UseMemory = false;
return false;
}
} else
return false;
UseMemory = false;
return true;
}
/*****************************************************************************/
/* Converts a number to a string. */
/*****************************************************************************/
char *numtostr(char *text, uint16 Num) {
uint16 Counter = 0;
if (Num == 0) {
text[0] = '0';
text[1] = 0;
return text;
}
strcpy(text, "00000");
if (Num >= 10000) {
text[0] = (Num / 10000) + '0';
Num -= (Num / 10000) * 10000;
}
if (Num >= 1000) {
text[1] = (Num / 1000) + '0';
Num -= (Num / 1000) * 1000;
}
if (Num >= 100) {
text[2] = (Num / 100) + '0';
Num -= (Num / 100) * 100;
}
if (Num >= 10) {
text[3] = (Num / 10) + '0';
Num -= (Num / 10) * 10;
}
text[4] = Num + '0';
text[5] = 0;
while (text[Counter] == '0')
Counter++;
return (&text[Counter]);
}
/*****************************************************************************/
/* Reads in a list of conditions. */
/*****************************************************************************/
static int16 *readConditions(byte **file) {
int16 Counter = 0, last, list[25], *ptr;
do {
readBlock(&last, 2L, file);
#if !defined(DOSCODE)
swapUShortPtr((uint16 *)&last, 1);
#endif
if (Counter < 25) {
list[Counter] = last;
Counter++;
} else
list[Counter] = 0;
} while (last);
if (!rallocate((void **) & (ptr), Counter * 2L))
return NULL;
memcpy(ptr, list, (size_t)(Counter * 2L));
return ptr;
}
/*****************************************************************************/
/* Reads in some CloseUp data. */
/*****************************************************************************/
static bool readCloseUps(CloseDataPtr *CPtr, uint16 depth, byte **file) {
char c;
while (1) {
*CPtr = NULL;
readBlock(&c, 1L, file);
if (c != '\0') {
if (rallocate((void **) CPtr, sizeof(CloseData))) {
(*CPtr)->SubCloseUps = NULL;
(*CPtr)->NextCloseUp = NULL;
(*CPtr)->depth = depth;
readBlock(*CPtr, 10L, file);
#if !defined(DOSCODE)
swapUShortPtr((uint16 *)*CPtr, 5);
#endif
if (!readString(&((*CPtr)->GraphicName), file))
return false;
if (!readString(&((*CPtr)->Message), file))
return false;
if (!readCloseUps(&((*CPtr)->SubCloseUps), depth + 1, file))
return false;
CPtr = &((*CPtr)->NextCloseUp);
} else
return false;
} else
return true;
}
}
/*****************************************************************************/
/* Reads in a View. */
/*****************************************************************************/
static bool readView(ViewDataPtr *VPtr, byte **file) {
char c;
while (1) {
*VPtr = NULL;
readBlock(&c, 1L, file);
if (c == 1) {
if (rallocate((void **) VPtr, sizeof(viewData))) {
(*VPtr)->closeUps = NULL;
(*VPtr)->NextCondition = NULL;
(*VPtr)->Condition = readConditions(file);
if (!(*VPtr)->Condition)
return false;
if (!readString(&((*VPtr)->GraphicName), file))
return false;
readCloseUps(&((*VPtr)->closeUps), 0, file);
VPtr = &((*VPtr)->NextCondition);
} else
return false;
} else
return true;
}
}
/*****************************************************************************/
/* Reads in an Action. */
/*****************************************************************************/
static bool readAction(ActionPtr *APtr, byte **file) {
char c;
byte **ptrarray;
uint16 counter;
while (1) {
*APtr = NULL;
readBlock(&c, 1L, file);
if (c == 1) {
if (rallocate((void **) APtr, sizeof(Action))) {
readBlock(*APtr, 8L, file);
#if !defined(DOSCODE)
swapShortPtr((int16 *)*APtr, 4);
#endif
if ((*APtr)->ActionType == SHOWMESSAGES) {
if (!rallocate((void **) &ptrarray, 4L * (*APtr)->Param1))
return false;
for (counter = 0; counter < (*APtr)->Param1; counter++)
readString((char **) & (ptrarray[counter]), file);
(*APtr)->Data = (byte *)ptrarray;
} else
readString((char **) & ((*APtr)->Data), file);
APtr = &((*APtr)->NextAction);
} else
return false;
} else
return true;
}
}
/*****************************************************************************/
/* Reads in a rule. */
/*****************************************************************************/
static bool readRule(RulePtr *RPtr, byte **file) {
char c;
while (1) {
*RPtr = NULL;
readBlock(&c, 1L, file);
if (c == 1) {
if (rallocate((void **) RPtr, sizeof(Rule))) {
readBlock(*RPtr, 6L, file);
#if !defined(DOSCODE)
swapShortPtr((int16 *)*RPtr, 3);
#endif
(*RPtr)->Condition = readConditions(file);
if (!(*RPtr)->Condition)
return false;
readAction(&((*RPtr)->ActionList), file);
} else
return false;
RPtr = &((*RPtr)->NextRule);
} else
return true;
}
}
/*****************************************************************************/
/* Reads in the views of a room. */
/*****************************************************************************/
bool readViews(uint16 RoomNum, const char *Path) {
char Temp[10], *RoomString, fileName[250];
byte **file;
allocroom = RoomNum;
RoomString = numtostr(Temp, RoomNum);
strcpy(fileName, Path);
strcat(fileName, RoomString);
if ((file = g_music->newOpen(fileName)) != NULL) {
readBlock(Temp, 4L, file);
Temp[4] = '\0';
if (strcmp(Temp, "ROM4") != 0)
return false;
readString(&(Rooms[RoomNum].RoomMsg), file);
readView(&Rooms[RoomNum].NorthView, file);
g_music->checkMusic();
readView(&Rooms[RoomNum].SouthView, file);
g_music->checkMusic();
readView(&Rooms[RoomNum].EastView, file);
g_music->checkMusic();
readView(&Rooms[RoomNum].WestView, file);
g_music->checkMusic();
readRule(&Rooms[RoomNum].RuleList, file);
return true;
} else
return false;
return false;
}
} // End of namespace Lab