474 lines
11 KiB
C++
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
|