[Scummvm-git-logs] scummvm master -> 71f928c26b3c681f5e53d79971a9aaee434acfa4
somaen
noreply at scummvm.org
Thu Apr 17 23:34:34 UTC 2025
This automated email contains information about 5 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
a9ec3835cd WATCHMAKER: Add detection entry for 0.92
c8c6b00070 WATCHMAKER: Add logic for parsing the game data DebugMode-style
58c3d3df01 WATCHMAKER: Add logic to use the debug mode game data
aae6c2c336 WATCHMAKER: Avoid loading fastFile if explicitly disabled.
71f928c26b WATCHMAKER: Refactor meshlinks to avoid using raw char* as type
Commit: a9ec3835cdcb7bd95df089dbe31a7f239591dbf4
https://github.com/scummvm/scummvm/commit/a9ec3835cdcb7bd95df089dbe31a7f239591dbf4
Author: Einar Johan Trøan SømaÌen (somaen at scummvm.org)
Date: 2025-04-18T00:58:03+02:00
Commit Message:
WATCHMAKER: Add detection entry for 0.92
Changed paths:
engines/watchmaker/detection.cpp
diff --git a/engines/watchmaker/detection.cpp b/engines/watchmaker/detection.cpp
index 9b52bacadb2..27894ba0094 100644
--- a/engines/watchmaker/detection.cpp
+++ b/engines/watchmaker/detection.cpp
@@ -34,6 +34,17 @@ static const PlainGameDescriptor watchmakerGames[] = {
namespace Watchmaker {
static const ADGameDescription gameDescriptions[] = {
+ // The Watchmaker English 0.92
+ {
+ "watchmaker",
+ nullptr,
+ AD_ENTRY1s("WmStart.dat", "a0532ab9a2ea33ce1c6953168ed04d7c", 190251),
+ Common::EN_ANY,
+ Common::kPlatformWindows,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOMIDI)
+ },
+
// The Watchmaker English Retail
{
"watchmaker",
Commit: c8c6b000705e852911b5437d9ab78efc67f310be
https://github.com/scummvm/scummvm/commit/c8c6b000705e852911b5437d9ab78efc67f310be
Author: Einar Johan Trøan SømaÌen (somaen at scummvm.org)
Date: 2025-04-18T01:22:02+02:00
Commit Message:
WATCHMAKER: Add logic for parsing the game data DebugMode-style
In practice this means adding the logic needed to parse the data from
the editor friendly formats used during development, which should help
us get the 0.92 version of the game running.
Changed paths:
engines/watchmaker/define.h
engines/watchmaker/init/nl_init.cpp
engines/watchmaker/init/nl_init.h
engines/watchmaker/init/nl_parse.cpp
engines/watchmaker/init/nl_parse.h
diff --git a/engines/watchmaker/define.h b/engines/watchmaker/define.h
index fba68fe687c..81f8d25c005 100644
--- a/engines/watchmaker/define.h
+++ b/engines/watchmaker/define.h
@@ -623,8 +623,10 @@ namespace Watchmaker {
#define ocLASTCHAR 24
#define ocCURPLAYER 25
+#define ocBOTH 25
#define oCAMERAMAX 26
+#define ocNOTRANS 26
#define oTOOLTIPS 98
#define oNEXTPORTAL 99
diff --git a/engines/watchmaker/init/nl_init.cpp b/engines/watchmaker/init/nl_init.cpp
index 37b8d9aff01..f32503a2eda 100644
--- a/engines/watchmaker/init/nl_init.cpp
+++ b/engines/watchmaker/init/nl_init.cpp
@@ -21,9 +21,11 @@
#define FORBIDDEN_SYMBOL_EXCEPTION_strcpy
-#include "watchmaker/init/nl_parse.h"
+#include "watchmaker/define.h"
#include "watchmaker/extraLS.h"
+#include "watchmaker/game.h"
#include "watchmaker/globvar.h"
+#include "watchmaker/init/nl_parse.h"
#include "watchmaker/ll/ll_system.h"
#include "watchmaker/types.h"
@@ -37,6 +39,626 @@ int DlgItemNum = 1;
uint16 Credits_numRoles = 0;
uint16 Credits_numNames = 0;
+#define DEFAULT_DEFINE_INPUT "src/define.h"
+
+#define MAXFLAGS 360
+#define MAXTOKENLEN 30
+
+#define ANIM_MARKER 'a'
+#define CREDIT_MARKER 'c'
+#define DLG_MARKER 'd'
+#define DIARY_MARKER 'e'
+#define ATFDO_MARKER 'f'
+#define ACT_MARKER 'h'
+#define INV_MARKER 'i'
+#define PDALOG_MARKER 'l'
+#define MENU_MARKER 'm'
+#define MUSIC_MARKER 'n'
+#define OBJ_MARKER 'o'
+#define ROOM_MARKER 'r'
+#define DESC_MARKER 's'
+#define ENV_MARKER 'v'
+#define SOUND_MARKER 'w'
+
+#define TOKEN_NOT_FOUND 0xffff
+
+typedef struct {
+ char token[MAXTOKENLEN];
+ unsigned int value;
+} TOKEN; // 32 bytes
+
+int SaveTextTable(char *name);
+
+#define AddSound2Room(inx,val) \
+ { \
+ \
+ unsigned short j=0,err=0,*tab=_init.Room[inx].sounds.rawArray(); \
+ while(*tab!=0) \
+ { \
+ \
+ tab++; \
+ if(j++>=MAX_SOUNDS_IN_ROOM) \
+ err=1; \
+ } \
+ if(err) \
+ _parser->ParseError("Too many Sounds in room %s max is %d",_init.Room[inx].name,MAX_SOUNDS_IN_ROOM); \
+ else \
+ *tab=val; \
+ }
+
+#define AddAnim2Room(room,inx) \
+ { \
+ \
+ room->anims[animcnt++]=inx; \
+ if(animcnt>=MAX_ANIMS_IN_ROOM) \
+ return _parser->ParseError("Too many Anims in room %s max is %d",s,MAX_ANIMS_IN_ROOM); \
+ }
+
+#define AddAct2Room(room,inx) \
+ { \
+ \
+ room->actions[actcnt++]=inx; \
+ if(actcnt>=MAX_ACTIONS_IN_ROOM) \
+ return _parser->ParseError("Too many Acts in room %s max is %d",s,MAX_ACTIONS_IN_ROOM); \
+ }
+
+#define AddObject2Room(room,inx) \
+ { \
+ \
+ room->objects[objcnt++]=inx; \
+ if(objcnt>=MAX_OBJS_IN_ROOM) \
+ return _parser->ParseError("Too many Objects in room %s max is %d",s,MAX_OBJS_IN_ROOM); \
+ }
+
+TOKEN *FlagToken = NULL;
+TOKEN *RoomToken = NULL;
+TOKEN *ObjToken = NULL;
+TOKEN *AnimToken = NULL;
+TOKEN *InvToken = NULL;
+TOKEN *WaveToken = NULL;
+TOKEN *DoToken = NULL;
+TOKEN *DlgToken = NULL;
+TOKEN *ActToken = NULL;
+TOKEN *MenuToken = NULL;
+TOKEN *DiaryToken = NULL;
+TOKEN *EnvToken = NULL;
+TOKEN *PDALogToken = NULL;
+TOKEN *MusicToken = NULL;
+
+const char *ShortName[] = {
+ "???",
+ "DAR",
+ "VIC",
+ "CUO",
+ "DOM",
+ "GIA",
+ "CUS",
+ "SER",
+ "SUP",
+ "MOG",
+ "MOG",
+ "CAC",
+ "VEC",
+ "CHI",
+ "TRA",
+ "ORO",
+ "KRE",
+ "DUK",
+ "COR",
+ "VAL",
+ "NOT",
+ "MOO",
+ "DAR",
+ "CAC",
+ "MOO",
+ "BOT",
+ "***"
+};
+char csn = 0;
+
+
+/* -----------------16/03/98 18.14-------------------
+ * FreeDefineTable
+ * --------------------------------------------------*/
+void FreeDefineTable(void) {
+ free(FlagToken);
+ free(RoomToken);
+ free(ObjToken);
+ free(AnimToken);
+ free(InvToken);
+ free(WaveToken);
+ free(DoToken);
+ free(ActToken);
+ free(MenuToken);
+ free(DlgToken);
+ free(DiaryToken);
+ free(EnvToken);
+ free(PDALogToken);
+ free(MusicToken);
+
+ FlagToken = RoomToken = DiaryToken = ObjToken = ActToken = MenuToken = PDALogToken = MusicToken = NULL;
+ AnimToken = InvToken = WaveToken = DoToken = DlgToken = EnvToken = NULL;
+}
+
+/* -----------------16/03/98 18.14-------------------
+ * BuildDefineTable
+ * --------------------------------------------------*/
+int BuildDefineTable(const char *name) {
+ auto parser = NLParser::open(DEFAULT_DEFINE_INPUT);
+ if (!parser) {
+ parser = NLParser::open(name);
+ if (!parser) {
+ error("Error Opening File NL %s", name);
+ }
+ }
+ parser->IfParseErrorDo(FreeDefineTable);
+
+ char str[MAXTOKENLEN];
+ int res, done = FALSE;
+ TOKEN *token = NULL;
+ int cur_dlg, cur_flag, cur_room, cur_obj, cur_anim, cur_inv, cur_wave, cur_do, cur_act, cur_menu, cur_diary, cur_env, cur_pdalog, cur_music;
+
+ CurText = TextBucket = t3dCalloc<char>(TEXT_BUCKET_SIZE);
+ if (TextBucket == nullptr)
+ return parser->ParseError("Error Allocating TextBucket");
+
+ FlagToken = t3dCalloc<TOKEN>(MAXFLAGS);
+ RoomToken = t3dCalloc<TOKEN>(MAX_ROOMS);
+ ObjToken = t3dCalloc<TOKEN>(MAX_OBJS);
+ AnimToken = t3dCalloc<TOKEN>(MAX_ANIMS);
+ InvToken = t3dCalloc<TOKEN>(MAX_ICONS);
+ WaveToken = t3dCalloc<TOKEN>(MAX_SOUNDS);
+ DoToken = t3dCalloc<TOKEN>(MAX_ATF_DO);
+ ActToken = t3dCalloc<TOKEN>(MAX_ACTIONS);
+ MenuToken = t3dCalloc<TOKEN>(MAX_DLG_MENUS);
+ DiaryToken = t3dCalloc<TOKEN>(MAX_DIARIES);
+ DlgToken = t3dCalloc<TOKEN>(MAX_DIALOGS);
+ EnvToken = t3dCalloc<TOKEN>(MAX_ENVIRONMENTS);
+ PDALogToken = t3dCalloc<TOKEN>(MAX_PDALOGS);
+ MusicToken = t3dCalloc<TOKEN>(MAX_MUSICS);
+
+ if (!DlgToken || !MenuToken || !ActToken || !RoomToken || !ObjToken || !AnimToken || !InvToken || !DiaryToken || !WaveToken || !DoToken || !EnvToken || !PDALogToken || !MusicToken)
+ return parser->ParseError("Error Allocating Define Tables");
+
+ cur_dlg = cur_act = cur_menu = cur_flag = cur_room = cur_obj = cur_anim = cur_inv = cur_wave = cur_do = cur_diary = cur_env = cur_pdalog = cur_music = 0;
+
+ while (!done) {
+ res = parser->ReadArgument(str);
+ warning("Cur res: %d Cur str: '%s'", res, str);
+ if (res == EOF_PARSED)break;
+ if (scumm_stricmp("#define", str))
+ return parser->ParseError("Match %s instead of %s", str, "#define");
+
+ if (parser->ReadArgument(str) < 0)
+ return parser->ParseError("Error reading a string in file %s at line %d", name, parser->getCurLine());
+ warning("Argument: '%s'", str);
+ switch (str[0]) {
+ case ROOM_MARKER:
+ token = &RoomToken[cur_room++];
+ if (cur_room >= MAX_ROOMS)return parser->ParseError("Too many Rooms defined (MAX is %d)", MAX_ROOMS);
+ break;
+ case OBJ_MARKER:
+ token = &ObjToken[cur_obj++];
+ if (cur_obj >= MAX_OBJS)return parser->ParseError("Too many Objects defined (MAX is %d)", MAX_OBJS);
+ break;
+ case INV_MARKER:
+ token = &InvToken[cur_inv++];
+ if (cur_inv >= MAX_ICONS)return parser->ParseError("Too many Icons defined (MAX is %d)", MAX_ICONS);
+ break;
+ case ANIM_MARKER:
+ token = &AnimToken[cur_anim++];
+ if (cur_anim >= MAX_ANIMS)return parser->ParseError("Too many Anims defined (MAX is %d)", MAX_ANIMS);
+ break;
+ case SOUND_MARKER:
+ token = &WaveToken[cur_wave++];
+ if (cur_wave >= MAX_SOUNDS)return parser->ParseError("Too many Samples defined (MAX is %d)", MAX_SOUNDS);
+ break;
+ case ATFDO_MARKER:
+ token = &DoToken[cur_do++];
+ if (cur_do >= MAX_ATF_DO)return parser->ParseError("Too many AtfDo defined (MAX is %d)", MAX_ATF_DO);
+ break;
+ case ACT_MARKER:
+ token = &ActToken[cur_act++];
+ if (cur_act >= MAX_ACTIONS)return parser->ParseError("Too many Action defined (MAX is %d)", MAX_ACTIONS);
+ break;
+ case MENU_MARKER:
+ token = &MenuToken[cur_menu++];
+ if (cur_menu >= MAX_DLG_MENUS)return parser->ParseError("Too many Menus defined (MAX is %d)", MAX_DLG_MENUS);
+ break;
+ case DIARY_MARKER:
+ token = &DiaryToken[cur_diary++];
+ if (cur_diary >= MAX_DIARIES)return parser->ParseError("Too many Diaries defined (MAX is %d)", MAX_DIARIES);
+ break;
+ case DLG_MARKER:
+ token = &DlgToken[cur_dlg++];
+ if (cur_dlg >= MAX_DIALOGS)return parser->ParseError("Too many Dialogs defined (MAX is %d) ", MAX_DIALOGS);
+ break;
+ case ENV_MARKER:
+ token = &EnvToken[cur_env++];
+ if (cur_env >= MAX_ENVIRONMENTS)return parser->ParseError("Too many Environments defined (MAX is %d) ", MAX_ENVIRONMENTS);
+ break;
+ case PDALOG_MARKER:
+ token = &PDALogToken[cur_pdalog++];
+ if (cur_pdalog >= MAX_PDALOGS)return parser->ParseError("Too many PDALogs defined (MAX is %d) ", MAX_PDALOGS);
+ break;
+ case MUSIC_MARKER:
+ token = &MusicToken[cur_music++];
+ if (cur_music >= MAX_MUSICS)return parser->ParseError("Too many Musics defined (MAX is %d) ", MAX_MUSICS);
+ break;
+
+ default:
+ if (cur_flag >= MAXFLAGS) { //ne legge solo un po'
+ parser->ReadNumber();
+ token = NULL;
+ break;
+ }
+ token = &FlagToken[cur_flag++];
+ break;
+ }
+ if (token) {
+ strcpy(token->token, str);
+ token->value = parser->ReadNumber();
+ }
+ }
+ parser.reset();
+ return 1;
+}
+
+/*PELS: end DEFINE ***********************************/
+
+#undef Match
+#define Match(t) {if((_parser->ReadArgument(str)<0) || scumm_stricmp(str,t))return _parser->ParseError("Syntax Error! can't match '%s' but found '%s'",t,str);}
+
+static const char *InitFile[] = {
+ "Init.nl",
+ "InitLev1.nl",
+ "InitLev2.nl",
+ "InitLev3.nl",
+ "InitLev4.nl",
+ "InitAnim.nl",
+ "InitAnim1.nl",
+ "InitAnim2.nl",
+ "InitAnim3.nl",
+ "InitAnim4.nl",
+ "InitAnimRtv.nl",
+ "InitBkg.nl",
+ "InitText.nl",
+ "InitIcon.nl",
+ "InitDlg.nl",
+ "InitRtv1.nl",
+ "InitRtv2.nl",
+ "InitRtv3.nl",
+ "InitRtv4.nl",
+ "InitSound.nl",
+ "InitT2D.nl",
+ "InitDiary.nl",
+ "Credits.nl",
+ NULL
+};
+
+class StructureInitializer {
+ Common::SharedPtr<NLParser> _parser;
+ Common::String _filename;
+ Init &_init;
+public:
+ StructureInitializer(Common::SharedPtr<NLParser> &parser, const Common::String &filename, Init &init) : _parser(parser), _filename(filename), _init(init) {
+ }
+ static Common::SharedPtr<StructureInitializer> open(Common::String &path, Init &init) {
+ // TODO: Hook up the table-freeing
+ auto parser = NLParser::open(path);
+ if (!parser) {
+ return nullptr;
+ }
+ warning("Casting away constness");
+ if (parser->SearchArgument((char *)path.c_str(), "NL.", NULL) < 0)
+ parser->ParseError("%s is not a NL file", path.c_str());
+ return Common::SharedPtr<StructureInitializer>(new StructureInitializer(parser, path, init));
+ }
+
+ int parseLoop() {
+ int res = 1;
+ while (true) {
+ char str[J_MAXSTRLEN];
+ if (_parser->ReadArgument(str) < 0) {
+ if (!scumm_stricmp(str, "end."))break;
+ else if ((toupper(str[0]) == 'E') && (toupper(str[1]) == 'N') &&
+ (toupper(str[2]) == 'D') && (toupper(str[3]) == '.'))
+ break;
+ else
+ return _parser->ParseError("Error Reading File %s -%s-", _filename.c_str(), str);
+ }
+ if (!scumm_stricmp(str, "end."))break;
+ if ((toupper(str[0]) == 'E') && (toupper(str[1]) == 'N') &&
+ (toupper(str[2]) == 'D') && (toupper(str[3]) == '.'))
+ break;
+
+ res = 0;
+ switch (str[0]) {
+ case OBJ_MARKER:
+ res = ParseObject(str);
+ break;
+ case ROOM_MARKER:
+ res = ParseRoom(str);
+ break;
+ case ANIM_MARKER:
+ res = ParseAnim(str);
+ break;
+ case INV_MARKER:
+ res = ParseInv(str);
+ break;
+ case SOUND_MARKER:
+ res = ParseSound(str);
+ break;
+ case DLG_MARKER:
+ res = ParseDialog(str);
+ break;
+ case DIARY_MARKER:
+ res = ParseDiary(str);
+ break;
+ case MENU_MARKER:
+ res = ParseMenu(str);
+ break;
+ case PDALOG_MARKER:
+ res = ParsePDALog(str);
+ break;
+ case MUSIC_MARKER:
+ res = ParseMusic(str);
+ break;
+ case CREDIT_MARKER:
+ res = ParseCredits(str);
+ break;
+ }
+ if (!res)
+ error("Some parse error occurred");
+ }
+ return 1;
+ }
+
+ /* -----------------16/03/98 18.13-------------------
+ * GetTokenValue
+ * --------------------------------------------------*/
+ unsigned int GetTokenValue(TOKEN *where, char *what) {
+ if (!scumm_stricmp("none", what))return 0;
+ while (where->token[0] != 0) {
+ if (!strcmp(where->token, what))
+ return where->value;
+ where++;
+ }
+ _parser->ParseError("Can't find token %s", what);
+ return TOKEN_NOT_FOUND;
+ }
+
+ /* -----------------16/03/98 18.13-------------------
+ * GetTokenValueDefault
+ * --------------------------------------------------*/
+ unsigned short GetTokenValueDefault(TOKEN *where, char *what) {
+ if (!scumm_stricmp("none", what))return 0;
+ while (where->token[0] != 0) {
+ if (!strcmp(where->token, what))
+ return where->value;
+ where++;
+ }
+ return TOKEN_NOT_FOUND;
+ }
+
+ /* -----------------16/03/98 17.48-------------------
+ * ReadSentence
+ * --------------------------------------------------*/
+ int ReadSentence(void) {
+ int a;
+ if ((a = _parser->ReadArgument(CurText)) < 0)
+ _parser->ParseError("Error Reading a string in ReadSentence");
+ Sentence[SentenceNum++] = CurText;
+ switch (SentenceNum - 1) {
+ case 2:
+ case 3:
+ case 6:
+ case 8:
+ case 10:
+ case 12:
+ case 13:
+ case 15:
+ csn = ocVECCHIO;
+ break;
+ case 4:
+ case 5:
+ case 7:
+ case 9:
+ case 11:
+ csn = ocCHIRURGO;
+ break;
+ case 14:
+ csn = ocTRADUTTORE;
+ break;
+ case 1:
+ csn = ocOROLOGIAIO;
+ break;
+ }
+ debug("%s s%04d %s\n", ShortName[csn], SentenceNum - 1, CurText);
+ CurText += a;
+ return (SentenceNum - 1);
+ }
+
+ /* -----------------16/03/98 17.48-------------------
+ * ReadSysSent
+ * --------------------------------------------------*/
+ int ReadSysSent(void) {
+ int a;
+ if ((a = _parser->ReadArgument(CurText)) < 0)
+ _parser->ParseError("Error Reading a string in ReadSysSent");
+ SysSent[SysSentNum++] = CurText;
+ csn = ocNOTRANS;
+ debug("%s y%04d %s\n", ShortName[csn], SysSentNum - 1, CurText);
+ CurText += a;
+ return (SysSentNum - 1);
+ }
+
+ /* -----------------19/01/99 10.34-------------------
+ * ReadTooltipSent
+ * --------------------------------------------------*/
+ int ReadTooltipSent(void) {
+ int a;
+ if ((a = _parser->ReadArgument(CurText)) < 0)
+ _parser->ParseError("Error Reading a string in ReadTooltipSent");
+ TooltipSent[TooltipSentNum++] = CurText;
+ csn = ocNOTRANS;
+ debug("%s t%04d %s\n", ShortName[csn], TooltipSentNum - 1, CurText);
+ CurText += a;
+ return (TooltipSentNum - 1);
+ }
+
+
+ /* -----------------21/03/01 09.40-------------------
+ * ReadExtraLS
+ * --------------------------------------------------*/
+ int ReadExtraLS(void) {
+ int a;
+ if ((a = _parser->ReadArgument(CurText)) < 0)
+ _parser->ParseError("Error Reading a string in ReadExtraLS");
+ ExtraLS[ExtraLSNum++] = CurText;
+ csn = ocNOTRANS;
+ debug("%s e%04d %s\n", ShortName[csn], ExtraLSNum - 1, CurText);
+ CurText += a;
+ return (ExtraLSNum - 1);
+ }
+
+ /* -----------------16/03/98 17.47-------------------
+ * ReadObjName
+ * --------------------------------------------------*/
+ int ReadObjName(void) {
+ int a;
+ if ((a = _parser->ReadArgument(CurText)) < 0)
+ _parser->ParseError("Error Reading a string in ReadObjName");
+ ObjName[ObjNameNum++] = CurText;
+ csn = ocNOTRANS;
+ debug("%s n%04d %s\n", ShortName[csn], ObjNameNum - 1, CurText);
+ CurText += a;
+ return (ObjNameNum - 1);
+ }
+
+ /* -----------------16/03/98 17.47-------------------
+ * ReadIndex
+ * --------------------------------------------------*/
+ int ReadIndex() {
+ char str[J_MAXSTRLEN];
+ int inx;
+ if (_parser->ReadArgument(str) <= 0)
+ _parser->ParseError("Error Reading a string in ReadIndex");
+ if ((inx = GetTokenValueDefault(WaveToken, str)) != TOKEN_NOT_FOUND)
+ return inx;
+ if ((inx = GetTokenValueDefault(ObjToken, str)) != TOKEN_NOT_FOUND)
+ return inx;
+ if ((inx = GetTokenValueDefault(DoToken, str)) != TOKEN_NOT_FOUND)
+ return inx;
+ if ((inx = GetTokenValueDefault(RoomToken, str)) != TOKEN_NOT_FOUND)
+ return inx;
+ if ((inx = GetTokenValueDefault(AnimToken, str)) != TOKEN_NOT_FOUND)
+ return inx;
+ if ((inx = GetTokenValueDefault(InvToken, str)) != TOKEN_NOT_FOUND)
+ return inx;
+ if ((inx = GetTokenValueDefault(MenuToken, str)) != TOKEN_NOT_FOUND)
+ return inx;
+ if ((inx = GetTokenValueDefault(DiaryToken, str)) != TOKEN_NOT_FOUND)
+ return inx;
+ if ((inx = GetTokenValueDefault(DlgToken, str)) != TOKEN_NOT_FOUND)
+ return inx;
+ if ((inx = GetTokenValueDefault(FlagToken, str)) != TOKEN_NOT_FOUND)
+ return inx;
+ if ((inx = GetTokenValueDefault(EnvToken, str)) != TOKEN_NOT_FOUND)
+ return inx;
+ if ((inx = GetTokenValueDefault(PDALogToken, str)) != TOKEN_NOT_FOUND)
+ return inx;
+ if ((inx = GetTokenValueDefault(MusicToken, str)) != TOKEN_NOT_FOUND)
+ return inx;
+
+ return atoi(str);
+ }
+
+ /* -----------------16/03/98 17.47-------------------
+ * ReadFlags
+ * --------------------------------------------------*/
+ int ReadFlags() {
+ int val = 0;
+ char str[J_MAXSTRLEN];
+ while (_parser->ReadArgumentEOL(str) > 0) {
+ val |= GetTokenValue(FlagToken, str);
+ }
+ return val;
+ }
+
+ float ReadFloat(void) {
+ char str[J_MAXSTRLEN];
+ if (_parser->ReadArgument(str) < 0)
+ return 0;
+ return (float)atof(str);
+ }
+
+
+ /* -----------------16/03/98 17.47-------------------
+ * AssignSound
+ * --------------------------------------------------*/
+ void AssignSound(int val) {
+ int inx;
+ char str[J_MAXSTRLEN];
+ while (_parser->ReadArgumentEOL(str) > 0) {
+ if ((inx = GetTokenValue(RoomToken, str)) != TOKEN_NOT_FOUND)
+ AddSound2Room(inx, val);
+ }
+ }
+
+
+ int ParseInv(char *s);
+ int ParseRoom(char *s);
+ int ParseAnim(char *s);
+ int ParseObject(char *s);
+ int ParseSound(char *s);
+ int ParseItem(int d);
+ int ParseDialog(char *s);
+ int ParseDiary(char *s);
+ int ParseMenu(char *s);
+ int ParsePDALog(char *s);
+ int ParseMusic(char *s);
+ int ParseCredits(char *s);
+};
+
+int InitStructures(WGame &game) {
+ const char **filelist = InitFile;
+ //
+ int res = TRUE;
+ if (!BuildDefineTable(game.workDirs._define.c_str()))
+ return 0;
+
+ SaveTextTable("SentUK.txt");
+
+ for (; *filelist != NULL; filelist++) {
+ Common::String path = game.workDirs._initDir + *filelist;
+ auto initializer = StructureInitializer::open(path, game.init);
+ if (!initializer)
+ error("Error Opening File NL %s", path.c_str());
+
+ initializer->parseLoop();
+
+ initializer.reset();
+ }
+
+ FreeDefineTable();
+ if ((CurText - TextBucket) > TEXT_BUCKET_SIZE)
+ error("TextBucket OverFlow in %s by %d", *filelist, (CurText - TextBucket));
+
+ {
+ debug("\n// ROOMS DESCRIPTIONS\n");
+ for (int i = 0; i < MAX_ROOMS; i++)
+ debug("*** d%04d %s\n", i, game.init.Room[i].desc);
+ }
+
+// tapullo perchè mancava il nome della porta in inittext
+ game.init.Obj[o2MBp2ME].name = game.init.Obj[o2MFp2MB].name;
+ game.init.Obj[0] = SObject();
+
+ return 1;
+}
+
+
/* -----------------24/08/00 9.31--------------------
* LoadExternalText
* --------------------------------------------------*/
@@ -59,12 +681,12 @@ int LoadExternalText(Init *init, char *et) {
if ((line[0] == '/') && (line[1] == '/')) continue;
if ((len = strlen(line)) > 260)
- return ParseError("ExternalText: line too long! curlen %d (MAX 250)\n%s", len - 10, line);
+ error("ExternalText: line too long! curlen %d (MAX 250)\n%s", len - 10, line);
if (len < 2) continue;
if (sscanf(&line[5], "%d", &num) < 1)
- return ParseError("ExternalText: sentence number not found in line:\n%s", line);
+ error("ExternalText: sentence number not found in line:\n%s", line);
switch (line[4]) {
case 's':
@@ -90,7 +712,7 @@ int LoadExternalText(Init *init, char *et) {
case 'd':
break;
default:
- return ParseError("ExternalText: unknown paramenters in line:\n%s", line);
+ error("ExternalText: unknown paramenters in line:\n%s", line);
}
if ((len - 10 - 1) > 0) {
@@ -117,4 +739,881 @@ int LoadExternalText(Init *init, char *et) {
return true;
}
+/* -----------------16/03/98 17.46-------------------
+ * ParseObject
+ * --------------------------------------------------*/
+int StructureInitializer::ParseObject(char *s) {
+ int inx = GetTokenValue(ObjToken, s);
+ int done = FALSE, arg, a, len;
+ struct SObject *obj;
+ char str[J_MAXSTRLEN];
+ if (inx == TOKEN_NOT_FOUND)return _parser->ParseError("Object %s doesn't exist!", s);
+ obj = &_init.Obj[inx];
+ obj->room = cr;
+ Match("{");
+ while (!done) {
+ if ((arg = _parser->SearchArgument(str, "}",
+ "name:", "examine:", "examined:", "examinev:", "action:", "actiond:", "actionv:",
+ "anim:", "animd:", "animv:", "goroom:", "godlg:", "ninv:", "flags:", "pos:", "meshlink:",
+ "text:", "log:", "sys:", "tooltip:", "anim2:", "anim2d:", "anim2v:", "log2:", "extrals:",
+ NULL)) < 0)return _parser->ParseError("Keyword %s Unknown in %s", str, s);
+ switch (arg) {
+ case 0:
+ done = TRUE;
+ break;
+ case 1:
+ debug("\n// %s\n", s);
+ obj->name = ReadObjName();
+ break;
+ case 2:
+ csn = ocBOTH;
+ obj->examine[DARRELL] = ReadSentence();
+ obj->examine[VICTORIA] = obj->examine[DARRELL];
+ break;
+ case 3:
+ csn = ocDARRELL;
+ obj->examine[DARRELL] = ReadSentence();
+ break;
+ case 4:
+ csn = ocVICTORIA;
+ obj->examine[VICTORIA] = ReadSentence();
+ break;
+ case 5:
+ csn = ocBOTH;
+ obj->action[DARRELL] = ReadSentence();
+ obj->action[VICTORIA] = obj->action[DARRELL];
+ break;
+ case 6:
+ csn = ocDARRELL;
+ obj->action[DARRELL] = ReadSentence();
+ break;
+ case 7:
+ csn = ocVICTORIA;
+ obj->action[VICTORIA] = ReadSentence();
+ break;
+ case 8:
+ _parser->ReadArgument(str);
+ obj->anim[DARRELL] = GetTokenValue(AnimToken, str);
+ obj->anim[VICTORIA] = obj->anim[DARRELL];
+ break;
+ case 9:
+ _parser->ReadArgument(str);
+ obj->anim[DARRELL] = GetTokenValue(AnimToken, str);
+ break;
+ case 10:
+ _parser->ReadArgument(str);
+ obj->anim[VICTORIA] = GetTokenValue(AnimToken, str);
+ break;
+ case 11:
+ _parser->ReadArgument(str);
+ obj->goroom = (uint8)GetTokenValue(RoomToken, str);
+ break;
+ case 12:
+ _parser->ReadArgument(str);
+ obj->goroom = (uint8)GetTokenValue(DlgToken, str);
+ break;
+ case 13:
+ _parser->ReadArgument(str);
+ obj->ninv = (uint8)GetTokenValue(InvToken, str);
+ break;
+ case 14:
+ obj->flags = ReadFlags();
+ break;
+ case 15:
+ obj->pos = _parser->ReadNumber();
+ break;
+ case 16:
+ for (a = 0; a < MAX_OBJ_MESHLINKS; a++) if (obj->meshlink[a][0] == 0) break;
+ if (a < MAX_OBJ_MESHLINKS)
+ if ((len = _parser->ReadArgument(str)) < 0 || len > sizeof(obj->meshlink[a]))return _parser->ParseError("Error reading meshlink %s in %s", str, s);
+ else strcpy((char*)obj->meshlink[a], str);
+ else _parser->ParseError("Too many Meshlink in Obj %s %d max is %d", s, a, MAX_OBJ_MESHLINKS);
+ break;
+ case 17:
+ for (a = 0; a < MAX_OBJ_USER_SENTS; a++) if (!obj->text[a]) break;
+ csn = ocBOTH;
+ if (a < MAX_OBJ_USER_SENTS) obj->text[a] = ReadSentence();
+ else _parser->ParseError("Too many UserText in Obj %s %d max is %d", s, a, MAX_OBJ_USER_SENTS);
+ break;
+ case 18:
+ _parser->ReadArgument(str);
+ debug("\n// %s\n", str);
+ break;
+ case 19:
+ ReadSysSent();
+ break;
+ case 20:
+ ReadTooltipSent();
+ break;
+ case 21:
+ _parser->ReadArgument(str);
+ obj->anim2[DARRELL] = GetTokenValue(AnimToken, str);
+ obj->anim2[VICTORIA] = obj->anim2[DARRELL];
+ break;
+ case 22:
+ _parser->ReadArgument(str);
+ obj->anim2[DARRELL] = GetTokenValue(AnimToken, str);
+ break;
+ case 23:
+ _parser->ReadArgument(str);
+ obj->anim2[VICTORIA] = GetTokenValue(AnimToken, str);
+ break;
+ case 24:
+ _parser->ReadArgument(str);
+ debug("// %s\n", str);
+ break;
+ case 25:
+ ReadExtraLS();
+ break;
+ }
+ }
+ return TRUE;
+}
+
+/* -----------------16/03/98 17.50-------------------
+ * ParseRoom
+ * --------------------------------------------------*/
+int StructureInitializer::ParseRoom(char *s) {
+ int inx = GetTokenValue(RoomToken, s);
+ int a, done = FALSE, res = TRUE, objcnt = 0, animcnt = 0, actcnt = 0;
+ char str[J_MAXSTRLEN];
+ struct SRoom *room;
+ if (inx == TOKEN_NOT_FOUND)return _parser->ParseError("Room %s doesn't exist!", s);
+ room = &_init.Room[inx];
+
+ a = _parser->ReadArgument(str);
+ if (a < 0 || a > sizeof(room->name))return _parser->ParseError("Error reading basename in room %s", s);
+ strcpy((char *)room->name, str);
+
+ cr = inx;
+ Match("{");
+ while (!done) {
+ if (_parser->ReadArgument(str) < 0)
+ return _parser->ParseError("Error Reading room %s at line %d", s, _parser->getCurLine());
+ if (!scumm_stricmp(str, "}"))break;
+ switch (str[0]) {
+ case OBJ_MARKER:
+ inx = GetTokenValue(ObjToken, str);
+ if (inx == TOKEN_NOT_FOUND)return _parser->ParseError("Can't process %s", str);
+ AddObject2Room(room, inx);
+ res = ParseObject(str);
+ break;
+ case ANIM_MARKER:
+ inx = GetTokenValue(AnimToken, str);
+ if (inx == TOKEN_NOT_FOUND)return _parser->ParseError("Can't process %s", str);
+ AddAnim2Room(room, inx);
+ //res=ParseAnim(str);
+ break;
+ case ACT_MARKER:
+ inx = GetTokenValue(ActToken, str);
+ if (inx == TOKEN_NOT_FOUND)return _parser->ParseError("Can't process %s", str);
+ AddAct2Room(room, inx);
+ break;
+ case ENV_MARKER:
+ inx = GetTokenValue(EnvToken, str);
+ if (inx == TOKEN_NOT_FOUND)return _parser->ParseError("Can't process %s", str);
+ room->env = inx;
+ break;
+ case DESC_MARKER:
+ Match("{");
+ _parser->ReadArgument(str);
+ strncpy(room->desc, str, 62);
+ Match("}");
+ break;
+ default:
+ return _parser->ParseError("Can't process word %s", str);
+ }
+ if (!res)
+ return _parser->ParseError("Error Parsing room %s", s);
+ }
+ cr = 0;
+
+ return TRUE;
+}
+
+/* -----------------16/03/98 18.01-------------------
+ * ParseAnim
+ * --------------------------------------------------*/
+int StructureInitializer::ParseAnim(char *s) {
+ int inx = GetTokenValue(AnimToken, s);
+ int done = FALSE, arg, a, j, len;
+ struct SAnim *anim;
+ char str[J_MAXSTRLEN];
+ if (inx == TOKEN_NOT_FOUND)return _parser->ParseError("Anim %s doesn't exist!", s);
+ anim = &_init.Anim[inx];
+ /* a=_parser->ReadArgument(str);
+ if(a<0 || a>sizeof(anim->name))return _parser->ParseError("Error reading name in anim %s",s);
+ strcpy(anim->name,str);
+ */ a = 0;
+
+ Match("{");
+ while (!done) {
+ if ((arg = _parser->SearchArgument(str, "}", "flags:", "name:", "objlink:", "meshlink:", "roomname:", "portallink:", "pos:",
+ "camera:", "obj:", "atframe:", NULL)) < 0)return _parser->ParseError("Keyword %s Unknown in %s", str, s);
+ switch (arg) {
+ case 0:
+ done = TRUE;
+ break;
+ case 1:
+ anim->flags = ReadFlags();
+ break;
+ case 2:
+ for (a = 0; a < MAX_SUBANIMS; a++) if (anim->meshlink[a][0] == 0) break;
+ if ((a < MAX_SUBANIMS) && (--a >= 0))
+ if ((len = _parser->ReadArgument(str)) < 0 || len > sizeof(anim->name[a])) return _parser->ParseError("Error reading animname %s in %s", str, s);
+ else strcpy((char*)anim->name[a].rawArray(), str);
+ else return _parser->ParseError("Too many subanim in Anim %s sub %d max is %d", str, a, MAX_SUBANIMS);
+ break;
+ case 3:
+ for (a = 0; a < MAX_SUBANIMS; a++) if (anim->meshlink[a][0] == 0) break;
+ if ((a < MAX_SUBANIMS) && (len = _parser->ReadArgument(str)))
+ strcpy((char *)anim->meshlink[a].rawArray(), (char *)_init.Obj[GetTokenValue(ObjToken, str)].meshlink[0]);
+ else return _parser->ParseError("Too many Objlinks in Anim %s sub %d max is %d", str, a, MAX_SUBANIMS);
+ break;
+ case 4:
+ for (a = 0; a < MAX_SUBANIMS; a++) if (anim->meshlink[a][0] == 0) break;
+ if (a < MAX_SUBANIMS)
+ if ((len = _parser->ReadArgument(str)) < 0 || len > sizeof(anim->meshlink[a])) return _parser->ParseError("Error reading meshlink %s in %s", str, s);
+ else strcpy((char*)anim->meshlink[a].rawArray(), str);
+ else return _parser->ParseError("Too many Meshlinks in Anim %s sub %d max is %d", str, a, MAX_SUBANIMS);
+ break;
+ case 5:
+ if ((len = _parser->ReadArgument(str)) < 0 || len > sizeof(anim->RoomName)) return _parser->ParseError("Error reading RoomName %s in %s", str, s);
+ else strcpy((char*)anim->RoomName.rawArray(), str);
+ break;
+ case 6:
+ if ((len = _parser->ReadArgument(str)) < 0 || len > sizeof(anim->RoomName)) return _parser->ParseError("Error reading PortalLink %s in %s", str, s);
+ else strcpy((char*)anim->RoomName.rawArray(), str);
+ break;
+ case 7:
+ anim->pos = _parser->ReadNumber();
+ break;
+ case 8:
+ anim->cam = _parser->ReadNumber();
+ break;
+ case 9:
+ _parser->ReadArgument(str);
+ anim->obj = GetTokenValue(ObjToken, str);
+ break;
+ case 10:
+ while (_parser->ReadArgumentEOL(str) > 0) {
+ j = 0;
+ while (anim->atframe[j].type != 0)
+ if (j++ >= MAX_ATFRAMES) return _parser->ParseError("Too many ATFrame in Anim %s max is %d", anim->name[a].rawArray(), MAX_ATFRAMES);
+ anim->atframe[j].nframe = atoi(str);
+ if ((anim->atframe[j].nframe > 1) && (anim->atframe[j].nframe < 9000))
+ anim->atframe[j].nframe *= 3;
+ anim->atframe[j].anim = _parser->ReadNumber();
+ _parser->ReadArgument(str);
+ anim->atframe[j].type = (uint8)GetTokenValue(FlagToken, str);
+ anim->atframe[j].index = ReadIndex();
+ }
+ break;
+ }
+ }
+
+// for(a=0;a<MAX_SUBANIMS;a++)
+// DebugFile("Anim |%s| |%s| |%s|",s,anim->meshlink[a],anim->name[a]);
+
+ return TRUE;
+}
+
+/* -----------------16/03/98 18.06-------------------
+ * ParseInv
+ * --------------------------------------------------*/
+int StructureInitializer::ParseInv(char *s) {
+ int inx = GetTokenValue(InvToken, s);
+ int done = FALSE, arg, a, len;
+ char str[J_MAXSTRLEN];
+ struct SInvObject *inv;
+ if (inx == TOKEN_NOT_FOUND)return _parser->ParseError("Inv %s doesn't exist!", s);
+ inv = &_init.InvObj[inx];
+ Match("{");
+ while (!done) {
+ if ((arg = _parser->SearchArgument(str, "}", "name:", "examine:", "examined:", "examinev:", "action:", "actiond:", "actionv:",
+ "meshlink:", "flags:", "text:", "log:", "uwobj:", "anim:", "animd:", "animv:", "anim2:", "anim2d:", "anim2v:",
+ NULL)) < 0)return _parser->ParseError("Keyword %s Unknown in %s", str, s);
+ switch (arg) {
+ case 0:
+ done = TRUE;
+ break;
+ case 1:
+ debug("\n// %s\n", s);
+ inv->name = ReadObjName();
+ break;
+ case 2:
+ csn = ocBOTH;
+ inv->examine[DARRELL] = ReadSentence();
+ inv->examine[VICTORIA] = inv->examine[DARRELL];
+ break;
+ case 3:
+ csn = ocDARRELL;
+ inv->examine[DARRELL] = ReadSentence();
+ break;
+ case 4:
+ csn = ocVICTORIA;
+ inv->examine[VICTORIA] = ReadSentence();
+ break;
+ case 5:
+ csn = ocBOTH;
+ inv->action[DARRELL] = ReadSentence();
+ inv->action[VICTORIA] = inv->action[DARRELL];
+ break;
+ case 6:
+ csn = ocDARRELL;
+ inv->action[DARRELL] = ReadSentence();
+ break;
+ case 7:
+ csn = ocVICTORIA;
+ inv->action[VICTORIA] = ReadSentence();
+ break;
+ case 8:
+ if ((len = _parser->ReadArgument(str)) < 0 || len > sizeof(inv->meshlink)) return _parser->ParseError("Error reading meshlink %s in %s", str, s);
+ else strcpy((char*)inv->meshlink.rawArray(), str);
+ break;
+ case 9:
+ inv->flags = ReadFlags();
+ break;
+ case 10:
+ for (a = 0; a < MAX_ICON_USER_SENTS; a++) if (!inv->text[a]) break;
+ csn = ocBOTH;
+ if (a < MAX_ICON_USER_SENTS) inv->text[a] = ReadSentence();
+ else _parser->ParseError("Too many UserText in Inv %s %d max is %d", str, a, MAX_ICON_USER_SENTS);
+ break;
+ case 11:
+ _parser->ReadArgument(str);
+ debug("\n// %s\n", str);
+ break;
+ case 12:
+ _parser->ReadArgument(str);
+ inv->uwobj = GetTokenValue(ObjToken, str);
+ break;
+ case 13:
+ _parser->ReadArgument(str);
+ inv->anim[DARRELL] = GetTokenValue(AnimToken, str);
+ inv->anim[VICTORIA] = inv->anim[DARRELL];
+ break;
+ case 14:
+ _parser->ReadArgument(str);
+ inv->anim[DARRELL] = GetTokenValue(AnimToken, str);
+ break;
+ case 15:
+ _parser->ReadArgument(str);
+ inv->anim[VICTORIA] = GetTokenValue(AnimToken, str);
+ break;
+ case 16:
+ _parser->ReadArgument(str);
+ inv->anim2[DARRELL] = GetTokenValue(AnimToken, str);
+ inv->anim2[VICTORIA] = inv->anim2[DARRELL];
+ break;
+ case 17:
+ _parser->ReadArgument(str);
+ inv->anim2[DARRELL] = GetTokenValue(AnimToken, str);
+ break;
+ case 18:
+ _parser->ReadArgument(str);
+ inv->anim2[VICTORIA] = GetTokenValue(AnimToken, str);
+ break;
+ }
+ }
+ return TRUE;
+}
+
+/* -----------------16/03/98 18.11-------------------
+ * ParseSound
+ * --------------------------------------------------*/
+int StructureInitializer::ParseSound(char *s) {
+ int inx = GetTokenValue(WaveToken, s);
+ int done = FALSE, arg, len, a;
+ char str[J_MAXSTRLEN];
+ struct SSound *sound;
+ if (inx == TOKEN_NOT_FOUND)return _parser->ParseError("Sound %s doesn't exist!", s);
+ sound = &_init.Sound[inx];
+ Match("{");
+ while (!done) {
+ if ((arg = _parser->SearchArgument(str, "}", "name:", "flags:", "room:", "meshlink:", "cone:", "dist:", "angle:",
+ NULL)) < 0)return _parser->ParseError("Keyword %s Unknown in %s", str, s);
+ switch (arg) {
+ case 0:
+ done = TRUE;
+ break;
+ case 1:
+ len = _parser->ReadArgument(str);
+ if (len < 0 || len > sizeof(sound->name))return _parser->ParseError("Error reading sound 'filename' %s in %s", str, s);
+ strcpy(sound->name, str);
+ break;
+ case 2:
+ sound->flags = ReadFlags();
+ break;
+ case 3:
+ AssignSound(inx);
+ break;
+ case 4:
+ for (a = 0; a < MAX_SOUND_MESHLINKS; a++) if (sound->meshlink[a][0] == 0) break;
+ if (a < MAX_SOUND_MESHLINKS)
+ if ((len = _parser->ReadArgument(str)) < 0 || len > sizeof(sound->meshlink[a]))return _parser->ParseError("Error reading meshlink %s in %s", str, s);
+ else strcpy((char*)sound->meshlink[a].rawArray(), str);
+ else _parser->ParseError("Too many Meshlink in Sound %s %d max is %d", s, a, MAX_SOUND_MESHLINKS);
+ break;
+ case 5:
+ sound->ConeInside = _parser->ReadNumber();
+ sound->ConeOutside = _parser->ReadNumber();
+ sound->ConeOutsideVolume = _parser->ReadNumber();
+ break;
+ case 6:
+ sound->MinDist = ReadFloat();
+ sound->MaxDist = ReadFloat();
+ break;
+ case 7:
+ sound->Angle = _parser->ReadNumber();
+ break;
+ }
+ }
+ return TRUE;
+}
+
+/* -----------------01/06/98 10.02-------------------
+ * ParseItem
+ * --------------------------------------------------*/
+int StructureInitializer::ParseItem(int d) {
+ char str[J_MAXSTRLEN];
+ int done = FALSE, arg, a, cp = ocBOTH, i1, i2;
+ struct SItemCommand *ic[MAX_PLAYERS];
+ unsigned short com, p1, p2;
+
+ _parser->ReadArgument(str);
+ debug("\n// %s\n", str);
+ a = GetTokenValue(MenuToken, str);
+ if (a >= MAX_DLG_MENUS)
+ return _parser->ParseError("Troppi Menu nel Dialogo %d MAX = %d", d, MAX_DLG_MENUS);
+
+ _init.Dialog[d].ItemIndex[a] = DlgItemNum;
+ DlgItemNum ++;
+ if (DlgItemNum >= MAX_DLG_ITEMS)
+ return _parser->ParseError("Troppi DlgItem nel Dialogo %d MAX = %d", d, MAX_DLG_ITEMS);
+
+ ic[0] = (struct SItemCommand *)&_init.DlgItem[DlgItemNum - 1].item[0];
+ ic[1] = (struct SItemCommand *)&_init.DlgItem[DlgItemNum - 1].item[1];
+
+ for (i1 = 0; i1 < MAX_IC_PER_DLG_ITEM; i1++) if (!ic[DARRELL][i1].com) break;
+ for (i2 = 0; i2 < MAX_IC_PER_DLG_ITEM; i2++) if (!ic[VICTORIA][i2].com) break;
+
+ Match("{");
+ while (!done) {
+ if ((arg = _parser->SearchArgument(str, "}", "setplayer:", "anim:", "setcamera:", "movecamerato:", "settarget:",
+ "setchar:", "walkchar:", "runchar:", "backchar:", "hidechar:", "unhidechar:", "changeroom:",
+ "expression:", "changeplayer:", "debug:", "item:", "setflags:", "clrflags:", "atframe:", "nextdlg:", "setchar2:",
+ "introt1:", "introt2:",
+ "tanim:", "tanim2:", "twalkchar:", "trunchar:", "tbackchar:", "twaitcamera:", "twait:", "tfadout:", NULL)) < 0)
+ return _parser->ParseError("ParseItem %d %d error %s", d, a, str);
+ com = arg;
+ p1 = 0;
+ p2 = 0;
+ switch (arg) {
+ case IC_NULL:
+ done = TRUE;
+ break;
+ case IC_SET_PLAYER:
+ _parser->ReadArgument(str);
+ cp = GetTokenValue(ObjToken, str);
+ break;
+ case IC_TIME_ANIM2:
+ case IC_ANIM:
+ _parser->ReadArgument(str);
+ p1 = GetTokenValue(AnimToken, str);
+ break;
+ case IC_SET_CAMERA:
+ case IC_TIME_WAIT_CAMERA:
+ case IC_MOVE_CAMERA_TO:
+ p1 = _parser->ReadNumber();
+ break;
+ case IC_CHANGE_PLAYER:
+ case IC_HIDE_CHAR:
+ case IC_UNHIDE_CHAR:
+ _parser->ReadArgument(str);
+ p1 = GetTokenValue(ObjToken, str);
+ break;
+ case IC_CHANGE_ROOM:
+ _parser->ReadArgument(str);
+ p1 = GetTokenValue(RoomToken, str);
+ break;
+ case IC_SET_TARGET:
+ case IC_SET_CHAR2:
+ case IC_SET_CHAR:
+ case IC_WALK_CHAR:
+ case IC_RUN_CHAR:
+ case IC_BACK_CHAR:
+ case IC_TIME_WALK_CHAR:
+ case IC_TIME_RUN_CHAR:
+ case IC_TIME_BACK_CHAR:
+ _parser->ReadArgument(str);
+ p1 = GetTokenValue(ObjToken, str);
+ p2 = _parser->ReadNumber();
+ break;
+ case IC_TIME_ANIM:
+ _parser->ReadArgument(str);
+ p1 = GetTokenValue(AnimToken, str);
+ csn = _init.Anim[p1].obj;
+ if (csn > ocBOTH) csn = oNULL;
+ p2 = ReadSentence();
+ if (strlen(Sentence[SentenceNum - 1]) < 2) {
+ p2 = 0;
+ SentenceNum--;
+ }
+ break;
+ case IC_TIME_FADOUT:
+ case IC_TIME_WAIT:
+ p1 = (unsigned short)(ReadFloat() * FRAME_PER_SECOND);
+ break;
+ case IC_EXPRESSION:
+ _parser->ReadArgument(str);
+ p1 = GetTokenValue(ObjToken, str);
+ p2 = ReadFlags();
+ break;
+ case IC_DEBUG:
+ csn = ocNOTRANS;
+ p1 = ReadSentence();
+ break;
+ case IC_ITEM:
+ _parser->ReadArgument(str);
+ p1 = GetTokenValue(MenuToken, str);
+ p2 = _parser->ReadNumber();
+ break;
+ case IC_SET_FLAGS:
+ case IC_CLR_FLAGS:
+ _parser->ReadArgument(str);
+ p1 = GetTokenValue(DlgToken, str);
+ p2 = ReadFlags();
+ break;
+ case IC_NEXT_DLG:
+ _parser->ReadArgument(str);
+ p1 = GetTokenValue(DlgToken, str);
+ break;
+ case IC_ATFRAME:
+ _parser->ReadArgument(str);
+ p1 = (uint8)GetTokenValue(FlagToken, str);
+ p2 = ReadIndex();
+ break;
+ case IC_INTRO_TEXT1:
+ case IC_INTRO_TEXT2:
+ p1 = _parser->ReadNumber();
+ p2 = ReadSysSent();
+ if (strlen(SysSent[SysSentNum - 1]) < 2) {
+ p2 = 0;
+ SysSentNum--;
+ }
+ break;
+ }
+ if ((i1 >= MAX_IC_PER_DLG_ITEM) || (i2 >= MAX_IC_PER_DLG_ITEM))
+ return _parser->ParseError("Troppi ItemCommands nel Dialogo %d item %d,%d MAX = %d", d, i1, i2, MAX_IC_PER_DLG_ITEM);
+ if (cp == ocBOTH) {
+ ic[DARRELL][i1].com = ic[VICTORIA][i2].com = (uint8)com;
+ ic[DARRELL][i1].param1 = ic[VICTORIA][i2].param1 = p1;
+ ic[DARRELL][i1++].param2 = ic[VICTORIA][i2++].param2 = p2;
+ } else if (cp == ocVICTORIA) {
+ ic[VICTORIA][i2].com = (uint8)com;
+ ic[VICTORIA][i2].param1 = p1;
+ ic[VICTORIA][i2++].param2 = p2;
+ } else {
+ ic[DARRELL][i1].com = (uint8)com;
+ ic[DARRELL][i1].param1 = p1;
+ ic[DARRELL][i1++].param2 = p2;
+ }
+ }
+ return TRUE;
+}
+
+/* -----------------01/06/98 9.55--------------------
+ * ParseDialog
+ * --------------------------------------------------*/
+int StructureInitializer::ParseDialog(char *s) {
+ int inx = GetTokenValue(DlgToken, s);
+ int arg, done = FALSE, a, alt;
+ char str[J_MAXSTRLEN];
+ struct SDialog *d;
+ if (inx == TOKEN_NOT_FOUND)return _parser->ParseError("Dialog %s doesn't exist!", s);
+ d = &_init.Dialog[inx];
+ debug("\n// %s\n", s);
+ Match("{");
+
+ while (!done) {
+ if ((arg = _parser->SearchArgument(str, "}", "flags:", "item:", "alt1pos:", "alt2pos:", "alt3pos:",
+ "alt1cam:", "alt2cam:", "alt3cam:", "alt1an:", "alt2an:", "alt3an:", "obj:", "log:",
+ NULL)) < 0) return _parser->ParseError("Keyword %s Unknown in %s", str, s);
+ switch (arg) {
+ case 0:
+ done = TRUE;
+ break;
+ case 1:
+ d->flags = ReadFlags();
+ break;
+ case 2:
+ if (!ParseItem(inx)) return FALSE;
+ break;
+
+ case 3:
+ case 4:
+ case 5:
+ d->AltPosSco[arg - 3] = _parser->ReadNumber();
+ break;
+ case 6:
+ case 7:
+ case 8:
+ d->AltCamSco[arg - 6] = _parser->ReadNumber();
+ break;
+ case 9:
+ case 10:
+ case 11:
+ for (a = 0, alt = arg - 9; a < MAX_ALT_ANIMS; a++)
+ if (d->AltAnims[alt][a][0] == aNULL)
+ break;
+ if (a >= MAX_ALT_ANIMS)
+ return _parser->ParseError("Too many Alternate Anims defined in Dialog %d max is %d", inx, MAX_ALT_ANIMS);
+ _parser->ReadArgument(str);
+ d->AltAnims[alt][a][0] = GetTokenValue(AnimToken, str);
+ _parser->ReadArgument(str);
+ d->AltAnims[alt][a][1] = GetTokenValue(AnimToken, str);
+ break;
+ case 12:
+ _parser->ReadArgument(str);
+ d->obj = GetTokenValue(ObjToken, str);
+ break;
+ case 13:
+ _parser->ReadArgument(str);
+ debug("\n// %s\n", str);
+ break;
+ }
+ }
+ return TRUE;
+}
+
+/* -----------------02/06/98 16.15-------------------
+ * ParseDiary
+ * --------------------------------------------------*/
+int StructureInitializer::ParseDiary(char *s) {
+ int inx = GetTokenValue(DiaryToken, s);
+ int done = FALSE, arg, i, j;
+ struct SDiary *e;
+ char str[J_MAXSTRLEN];
+
+ if (inx == TOKEN_NOT_FOUND)return _parser->ParseError("Diary %s doesn't exist!", s);
+
+ e = &_init.Diary[inx];
+ e->startt = _parser->ReadNumber();
+ e->endt = _parser->ReadNumber();
+
+ Match("{");
+ while (!done) {
+ if ((arg = _parser->SearchArgument(str, "}", "room:", "obj:", "rand:", "end_hideobj:", NULL)) < 0) return _parser->ParseError("Keyword %s Unknown in %s", str, s);
+ switch (arg) {
+ case 0:
+ done = TRUE;
+ break;
+ case 1:
+ _parser->ReadArgument(str);
+ e->room = GetTokenValue(RoomToken, str);
+ break;
+ case 2:
+ _parser->ReadArgument(str);
+ e->obj = GetTokenValue(ObjToken, str);
+ break;
+ case 3:
+ i = 0;
+ while (e->item[i].anim[0] != aNULL)
+ if (i++ >= MAX_DIARY_ITEMS)
+ return _parser->ParseError("Too many DiaryItem in Diary %d max is %d", inx, MAX_DIARY_ITEMS);
+ e->item[i].rand = _parser->ReadNumber();
+ e->item[i].loop = _parser->ReadNumber();
+ e->item[i].bnd = _parser->ReadNumber();
+
+ while (_parser->ReadArgumentEOL(str) > 0) {
+ j = 0;
+ while (e->item[i].anim[j] != aNULL)
+ if (j++ >= MAX_ANIMS_PER_DIARY_ITEM)
+ return _parser->ParseError("Too many Anims per DiaryItem in Diary %d max is %d", inx, MAX_ANIMS_PER_DIARY_ITEM);
+ e->item[i].anim[j] = GetTokenValue(AnimToken, str);
+ }
+ break;
+ case 4:
+ _parser->ReadArgument(str);
+ e->end_hideobj = GetTokenValue(ObjToken, str);
+ break;
+ }
+ }
+ return TRUE;
+}
+
+/* -----------------04/06/98 10.04--------------------
+ * ParseMenu
+ * --------------------------------------------------*/
+int StructureInitializer::ParseMenu(char *s) {
+ int inx = GetTokenValue(MenuToken, s);
+ char str[J_MAXSTRLEN];
+ struct SDlgMenu *m;
+ if (inx == TOKEN_NOT_FOUND)return _parser->ParseError("Menu %s doesn't exist!", s);
+ m = &_init.DlgMenu[inx];
+
+ csn = ocNOTRANS;
+ m->titolo = ReadSentence();
+ _parser->ReadArgument(str);
+ m->parent = (uint8)GetTokenValue(MenuToken, str);
+ m->on = _parser->ReadNumber();
+
+ return TRUE;
+}
+
+/* -----------------26/04/00 16.36-------------------
+ * ParsePDALog
+ * --------------------------------------------------*/
+int StructureInitializer::ParsePDALog(char *s) {
+ int done = FALSE, arg, a;
+ int inx = GetTokenValue(PDALogToken, s);
+ char str[J_MAXSTRLEN];
+ struct SPDALog *l;
+ if (inx == TOKEN_NOT_FOUND)return _parser->ParseError("PDALog %s doesn't exist!", s);
+ l = &_init.PDALog[inx];
+
+
+ Match("{");
+ while (!done) {
+ if ((arg = _parser->SearchArgument(str, "}", "flags:", "time:", "menu_appartenenza:", "menu_creato:", "text:", NULL)) < 0) return _parser->ParseError("Keyword %s Unknown in %s", str, s);
+
+ switch (arg) {
+ case 0:
+ done = TRUE;
+ break;
+ case 1:
+ l->flags = ReadFlags();
+ break;
+ case 2:
+ l->time = _parser->ReadNumber();
+ break;
+ case 3:
+ l->menu_appartenenza = _parser->ReadNumber();
+ break;
+ case 4:
+ l->menu_creato = _parser->ReadNumber();
+ break;
+ case 5:
+ csn = ocNOTRANS;
+ for (a = 0; a < MAX_PDA_INFO; a++)
+ if (l->text[a] == 0)
+ break;
+ if (a >= MAX_PDA_INFO) return _parser->ParseError("Too many Info in PDALog item %s: cur %d (MAX %d)", s, a, MAX_PDA_INFO);
+ l->text[a] = ReadSentence();
+ break;
+ }
+ }
+
+ return TRUE;
+}
+
+/* -----------------23/06/00 16.46-------------------
+ * ParseMusic
+ * --------------------------------------------------*/
+int StructureInitializer::ParseMusic(char *s) {
+ int done = FALSE, arg;
+ int inx = GetTokenValue(MusicToken, s), len;
+ char str[J_MAXSTRLEN];
+ struct SMusic *n;
+ if (inx == TOKEN_NOT_FOUND)return _parser->ParseError("Music %s doesn't exist!", s);
+ n = &_init.Music[inx];
+
+ Match("{");
+ while (!done) {
+ if ((arg = _parser->SearchArgument(str, "}", "sub0:", "sub1:", "sub2:", "sub3:", "sub4:", "sub5:", "sub6:", "sub7:", "sub8:", "sub9:", "room:",
+ NULL)) < 0) return _parser->ParseError("Keyword %s Unknown in %s", str, s);
+ switch (arg) {
+ case 0:
+ done = TRUE;
+ break;
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ len = _parser->ReadArgument(str);
+ if (len < 0 || len > sizeof(n->name[arg - 1]))return _parser->ParseError("Error reading music 'filename' %s in %s", str, s);
+ strcpy(n->name[arg - 1], str);
+ n->vol[arg - 1] = _parser->ReadNumber();
+ break;
+ case 11:
+ _parser->ReadArgument(str);
+ _init.Room[GetTokenValue(RoomToken, str)].music = inx;
+ break;
+ }
+ }
+
+ return TRUE;
+}
+
+/* -----------------22/11/00 15.16-------------------
+ * ParseCredits
+ * --------------------------------------------------*/
+int StructureInitializer::ParseCredits(char *s) {
+ char str[J_MAXSTRLEN];
+ int done, arg, len;
+ uint8 curflags;
+
+ curflags = 0;
+ done = FALSE;
+ Match("{");
+ while (!done) {
+ if ((arg = _parser->SearchArgument(str, "}",
+ "role:", "name:", "flags:",
+ NULL)) < 0)return _parser->ParseError("Keyword %s Unknown in %s", str, s);
+ switch (arg) {
+ case 0:
+ done = TRUE;
+ break;
+ case 1:
+ _init._creditsRoles = SerializableDynamicArray<SCreditsRole>((Credits_numRoles + 1));
+
+ len = _parser->ReadArgument(str);
+ if (len) {
+ if (len >= 48) return _parser->ParseError("Credits role string too long (max is 47)");
+ strcpy(_init._creditsRoles[Credits_numRoles].role, str);
+ } else
+ strcpy(_init._creditsRoles[Credits_numRoles].role, "");
+ _init._creditsRoles[Credits_numRoles].flags = curflags;
+
+ Credits_numRoles ++;
+
+ if (!(curflags & CF_STATIC)) curflags = CF_NULL;
+ break;
+ case 2:
+ _init._creditsNames = SerializableDynamicArray<SCreditsName>((Credits_numNames + 1));
+
+ len = _parser->ReadArgument(str);
+ if (len) {
+ if (len >= 64) return _parser->ParseError("Credits name string too long (max is 31)");
+ strcpy(_init._creditsNames[Credits_numNames].name, str);
+ } else
+ strcpy(_init._creditsNames[Credits_numNames].name, "");
+ _init._creditsNames[Credits_numNames].role = Credits_numRoles - 1;
+ _init._creditsNames[Credits_numNames].flags = curflags;
+
+ Credits_numNames ++;
+
+ if (!(curflags & CF_STATIC)) curflags = CF_NULL;
+ break;
+ case 3:
+ curflags = (uint8)ReadFlags();
+ break;
+ }
+ }
+
+ return TRUE;
+}
+
+int SaveTextTable(char *name) {
+ warning("TODO: Implement SaveTextTable(%s)", name);
+}
+
+
} // End of namespace Watchmaker
diff --git a/engines/watchmaker/init/nl_init.h b/engines/watchmaker/init/nl_init.h
index 5868f1b86c0..60f189fc1d1 100644
--- a/engines/watchmaker/init/nl_init.h
+++ b/engines/watchmaker/init/nl_init.h
@@ -25,6 +25,7 @@
namespace Watchmaker {
int LoadExternalText(Init *init, char *et);
+int InitStructures(WGame &game);
} // End of namespace Watchmaker
diff --git a/engines/watchmaker/init/nl_parse.cpp b/engines/watchmaker/init/nl_parse.cpp
index f4709a6aaa0..9949d5638bd 100644
--- a/engines/watchmaker/init/nl_parse.cpp
+++ b/engines/watchmaker/init/nl_parse.cpp
@@ -22,15 +22,26 @@
#include "watchmaker/init/nl_parse.h"
#include "common/stream.h"
#include "common/textconsole.h"
+#include "watchmaker/ll/ll_system.h"
namespace Watchmaker {
-unsigned int jStringLimit = J_MAXSTRLEN, jTillEOL = 0, jUsingComments = 0;
+#define JParse_EOF() (_stream->eos())
+
+int NLParser::MatchWord(char *token) {
+ char *str = token;
+ while (!JParse_EOF() && (*str) != 0) {
+ if (JParse_ReadByte() != *str)
+ str = token;
+ else
+ str++;
+ }
+ return (*str);
+}
// PELS: supporto per il parsing dei .nl **********************************
-static void (*ErrorFunc)() = nullptr;
-int ParseError(const char *ln, ...) {
+int NLParser::ParseError(const char *ln, ...) {
char err[J_MAXSTRLEN];
va_list ap;
if (ErrorFunc)
@@ -43,4 +54,166 @@ int ParseError(const char *ln, ...) {
return 0;
}
+void NLParser::IfParseErrorDo(void (*func)()) {
+ ErrorFunc = func;
+}
+
+Common::SharedPtr<NLParser> NLParser::open(const Common::String &name) {
+ auto stream = openFile(name);
+ if (!stream) {
+ return nullptr;
+ }
+ return Common::SharedPtr<NLParser>(new NLParser(stream));
+}
+
+NLParser::NLParser(Common::SharedPtr<Common::SeekableReadStream> stream) : _stream(stream), nlLineCounter(0), jUsingComments(1) {
+
+}
+
+static int lastreadeol = 0;
+int NLParser::ReadArgument_(char *str, int teol) {
+ int a, notstring = 1, t;
+ unsigned long c = 0;
+ if (teol & lastreadeol)
+ return -1;
+ while (!JParse_EOF()) {
+skipped_comms:
+ a = JParse_ReadByte();
+ if (notstring) {
+ if (jUsingComments)
+ if (a == '/') {
+ t = JParse_ReadByte() & 0xff;
+ switch (t) {
+ case '/':
+ if (MatchWord("\n"))
+ return -1;
+ if (teol) {
+ lastreadeol = 1;
+ return -1;
+ }
+ goto skipped_comms;
+ case '*':
+ if (MatchWord("*/"))
+ return -1;
+ goto skipped_comms;
+ default:
+ if (JParse_PrevByte())
+ return -1;
+ }
+ }
+ switch (a) {
+ case '\"':
+ notstring = 0;
+ break;
+ case '\r':
+ case '\f':
+ case '\n':
+ if (teol && c == 0) {
+ lastreadeol = 1;
+ return -1;
+ }
+
+ case '\t':
+ case ' ':
+ case '(':
+ if (c) {
+ lastreadeol = 0;
+ if (a == '\n')lastreadeol = 1;
+ *str = 0;
+ return (c + 1);
+ }
+ break;
+ case ')':
+ case ',':
+ case ';':
+ case '|':
+
+ lastreadeol = 0;
+ *str = 0;
+ return (c + 1);
+ default:
+ if (c++ >= jStringLimit)
+ return -1;
+ *str = a;
+ str++;
+ break;
+ } //end switch
+ } else
+ switch (a) {
+ case '\"':
+ /*while(!JParse_EOF())
+ switch(JParse_ReadByte()) {
+ case '(':
+ case ')':
+ case ',':
+ case ';': */
+
+ *str = 0;
+ return (c + 1);
+ // }
+ // break;
+ case '\\':
+ t = JParse_ReadByte();
+ switch (t) {
+ case '\\':
+ a = '\\';
+ break;
+ case 't':
+ a = '\t';
+ break;
+ case 'n':
+ a = '\n';
+ break;
+ case '\"':
+ a = '\"';
+ break;
+ default:
+ a = ' ';
+ } // senza break....ok
+ default:
+ if (c++ >= jStringLimit)
+ return -1;
+ *str = a;
+ str++;
+ break;
+ }
+ }
+
+ return EOF_PARSED;
+
+}
+
+
+
+int NLParser::ReadNumber(void) {
+ char stri[J_MAXSTRLEN];
+ int res;
+ if (ReadArgument(stri) < 0)
+ return 0;
+ if (stri[1] == 'x' || stri[1] == 'X')
+ sscanf(stri, "%x", &res);
+ else
+ sscanf(stri, "%d", &res);
+ return (int)res;
+}
+
+int NLParser::SearchArgument(char *t, ...) {
+ va_list args;
+ char *curarg;
+ int c = 0, res;
+ va_start(args, t);
+ if (ReadArgument(t) < 0)
+ return -1;
+ res = -2;
+ curarg = va_arg(args, char *);
+ while (curarg != NULL) {
+ if (!scumm_stricmp(curarg, t))
+ res = c;
+ c++;
+ curarg = va_arg(args, char *);
+ }
+ va_end(args);
+ return res;
+}
+
} // End of namespace Watchmaker
diff --git a/engines/watchmaker/init/nl_parse.h b/engines/watchmaker/init/nl_parse.h
index 5e929303ee3..640375ad07b 100644
--- a/engines/watchmaker/init/nl_parse.h
+++ b/engines/watchmaker/init/nl_parse.h
@@ -23,10 +23,53 @@
#define WATCHMAKER_NL_PARSE_H
#define J_MAXSTRLEN 512L
+#include "common/stream.h"
namespace Watchmaker {
-int ParseError(const char *ln, ...);
+class NLParser {
+ unsigned int jStringLimit = J_MAXSTRLEN, jTillEOL = 0, jUsingComments = 0;
+ unsigned long nlLineCounter;
+ int ReadArgument_(char *str, int teol);
+ Common::SharedPtr<Common::SeekableReadStream> _stream = nullptr;
+ void (*ErrorFunc)() = nullptr;
+public:
+ // TODO: Need a static version that allows for failure, as we have fallbacks in the code to use.
+ static Common::SharedPtr<NLParser> open(const Common::String &name);
+ NLParser(Common::SharedPtr<Common::SeekableReadStream> stream);
+ int ParseError(const char *ln, ...);
+ void IfParseErrorDo(void (*func)());
+ int ReadArgumentEOL(char *str) {
+ return ReadArgument_(str, 1);
+ }
+ int ReadArgument(char *str) {
+ return ReadArgument_(str, 0);
+ }
+ int ReadNumber(); //max 80 cifre
+ int SearchArgument(char *t, ...);
+ int getCurLine() {
+ return nlLineCounter;
+ }
+
+ int JParse_ReadByte(void) {
+ int a = _stream->readByte();
+ if (a == '\n')
+ nlLineCounter++;
+ return a;
+ }
+
+ int JParse_PrevByte(void) {
+
+ if (_stream->seek(-1, SEEK_SET))
+ return 0;
+ return 1;
+ }
+
+ int MatchWord(char *token);
+
+#define EOF_PARSED -2
+};
+
} // End of namespace Watchmaker
Commit: 58c3d3df01c0de3d7537d844c01117febde46b9a
https://github.com/scummvm/scummvm/commit/58c3d3df01c0de3d7537d844c01117febde46b9a
Author: Einar Johan Trøan SømaÌen (somaen at scummvm.org)
Date: 2025-04-18T01:22:04+02:00
Commit Message:
WATCHMAKER: Add logic to use the debug mode game data
(For now this is hardcoded to being disabled)
Changed paths:
engines/watchmaker/game.cpp
engines/watchmaker/game.h
diff --git a/engines/watchmaker/game.cpp b/engines/watchmaker/game.cpp
index 8ded27e1b8a..69210a34dae 100644
--- a/engines/watchmaker/game.cpp
+++ b/engines/watchmaker/game.cpp
@@ -20,13 +20,17 @@
*/
#include "watchmaker/game.h"
-#include "watchmaker/windows_hacks.h"
-#include "watchmaker/classes/do_system.h"
+
+#include "watchmaker/3d/animation.h"
#include "watchmaker/3d/geometry.h"
#include "watchmaker/3d/loader.h"
#include "watchmaker/3d/math/llmath.h"
-#include "watchmaker/3d/animation.h"
+#include "watchmaker/classes/do_camera.h"
+#include "watchmaker/classes/do_keyboard.h"
+#include "watchmaker/classes/do_player.h"
+#include "watchmaker/classes/do_system.h"
#include "watchmaker/define.h"
+#include "watchmaker/init/nl_init.h"
#include "watchmaker/ll/ll_anim.h"
#include "watchmaker/ll/ll_diary.h"
#include "watchmaker/ll/ll_mesh.h"
@@ -34,13 +38,11 @@
#include "watchmaker/ll/ll_regen.h"
#include "watchmaker/ll/ll_system.h"
#include "watchmaker/ll/ll_util.h"
+#include "watchmaker/renderer.h"
+#include "watchmaker/sdl_wrapper.h"
#include "watchmaker/walk/act.h"
-#include "watchmaker/classes/do_player.h"
-#include "watchmaker/classes/do_keyboard.h"
-#include "watchmaker/classes/do_camera.h"
#include "watchmaker/walk/ball.h"
-#include "watchmaker/sdl_wrapper.h"
-#include "watchmaker/renderer.h"
+#include "watchmaker/windows_hacks.h"
namespace Watchmaker {
@@ -184,7 +186,7 @@ WGame::WGame() : workDirs(WATCHMAKER_CFG_NAME) {
_meshModifiers = new MeshModifiers();
_roomManager = RoomManager::create(this);
_cameraMan = new CameraMan();
- configLoaderFlags(); // TODO: This should probably happen before the constructor
+ configLoaderFlags(false); // TODO: This should probably happen before the constructor
// if LoaderFlags & T3D_DEBUGMODE
// ...
@@ -192,12 +194,12 @@ WGame::WGame() : workDirs(WATCHMAKER_CFG_NAME) {
gameOptions.load(workDirs);
- // if (LoaderFlags & T3D_DEBUGMODE) {
- // ...
- // } else
-
- warning("Currently doing an unnecessary copy here");
- loadAll(workDirs, init);
+ if (LoaderFlags & T3D_DEBUGMODE) {
+ InitStructures(*this);
+ } else {
+ warning("Currently doing an unnecessary copy here");
+ loadAll(workDirs, init);
+ }
sdl = new sdl_wrapper();
diff --git a/engines/watchmaker/game.h b/engines/watchmaker/game.h
index f7943a6d4ce..af012b4164d 100644
--- a/engines/watchmaker/game.h
+++ b/engines/watchmaker/game.h
@@ -82,13 +82,16 @@ public:
Common::SharedPtr<Common::SeekableReadStream> resolveFile(const char *path, bool noFastFile = false);
- void configLoaderFlags() {
+ void configLoaderFlags(bool debugMode) {
// TODO: Add back some of the configurability from the argument parsing.
LoadChar = 3;
LoaderFlags = T3D_STATIC_SET0;
LoaderFlags |= T3D_OUTDOORLIGHTS;
LoaderFlags |= T3D_PRELOADBASE;
LoaderFlags |= T3D_STATIC_SET1;
+ if (debugMode) {
+ LoaderFlags |= T3D_DEBUGMODE;
+ }
if (!(LoaderFlags & T3D_DEBUGMODE)) {
LoadChar = 3;
Commit: aae6c2c336f65755a52f5d9d753a15de33d4ca88
https://github.com/scummvm/scummvm/commit/aae6c2c336f65755a52f5d9d753a15de33d4ca88
Author: Einar Johan Trøan SømaÌen (somaen at scummvm.org)
Date: 2025-04-18T01:22:09+02:00
Commit Message:
WATCHMAKER: Avoid loading fastFile if explicitly disabled.
(Such as in debug mode)
Changed paths:
engines/watchmaker/work_dirs.cpp
diff --git a/engines/watchmaker/work_dirs.cpp b/engines/watchmaker/work_dirs.cpp
index 5f84145529e..97163eb5eea 100644
--- a/engines/watchmaker/work_dirs.cpp
+++ b/engines/watchmaker/work_dirs.cpp
@@ -22,6 +22,8 @@
#define FORBIDDEN_SYMBOL_EXCEPTION_strcpy
#include "watchmaker/work_dirs.h"
+
+#include "watchmaker/3d/loader.h"
#include "watchmaker/ll/ll_system.h"
namespace Watchmaker {
@@ -65,7 +67,9 @@ static bool readKeyValuePair(Common::SeekableReadStream &stream, Common::String
}
WorkDirs::WorkDirs(const Common::String &filename) {
- _fastFile = Common::SharedPtr<FastFile>(new FastFile(WmGameDataPak_FilePath));
+ if (LoaderFlags & T3D_FASTFILE) {
+ _fastFile = Common::SharedPtr<FastFile>(new FastFile(WmGameDataPak_FilePath));
+ }
auto fcfg = openFile(filename.c_str());
if (fcfg) {
Commit: 71f928c26b3c681f5e53d79971a9aaee434acfa4
https://github.com/scummvm/scummvm/commit/71f928c26b3c681f5e53d79971a9aaee434acfa4
Author: Einar Johan Trøan SømaÌen (somaen at scummvm.org)
Date: 2025-04-18T01:33:13+02:00
Commit Message:
WATCHMAKER: Refactor meshlinks to avoid using raw char* as type
This makes things easier when dealing with debug mode,
as we can use Common::String instead along with getters/setters
to deal with the case where the meshlinks aren't yet initialized.
Changed paths:
engines/watchmaker/3d/loader.cpp
engines/watchmaker/classes/do_keyboard.cpp
engines/watchmaker/classes/do_operate.cpp
engines/watchmaker/init/nl_init.cpp
engines/watchmaker/ll/ll_anim.cpp
engines/watchmaker/ll/ll_mesh.cpp
engines/watchmaker/ll/ll_util.cpp
engines/watchmaker/struct.h
engines/watchmaker/sysdef.h
engines/watchmaker/walk/ball.cpp
diff --git a/engines/watchmaker/3d/loader.cpp b/engines/watchmaker/3d/loader.cpp
index 250f25290f5..d83e24a9571 100644
--- a/engines/watchmaker/3d/loader.cpp
+++ b/engines/watchmaker/3d/loader.cpp
@@ -211,7 +211,7 @@ public:
return &init._globals._invVars.CameraDummy;
// Cerca tra i personaggi
for (uint16 i = 0; i < T3D_MAX_CHARACTERS; i++)
- if ((Character[i]) && (str.equalsIgnoreCase((char *)init.Obj[i].meshlink[0])))
+ if ((Character[i]) && (str.equalsIgnoreCase(init.Obj[i].getMeshLink(0))))
return Character[i]->Mesh;
// Cerca nelle stanze caricate
for (uint16 i = 0; i < NumLoadedFiles; i++) {
diff --git a/engines/watchmaker/classes/do_keyboard.cpp b/engines/watchmaker/classes/do_keyboard.cpp
index 62efc82bb7c..2baffcc8255 100644
--- a/engines/watchmaker/classes/do_keyboard.cpp
+++ b/engines/watchmaker/classes/do_keyboard.cpp
@@ -681,7 +681,7 @@ void doClock33(WGame &game, int32 obj, t3dV3F *mp) {
obj = (int32)bClock33 + o33LANCETTAHSX - 1;
// Trova il puntatore alla mesh
- if (!(l = LinkMeshToStr(game.init, (char *)game.init.Obj[obj].meshlink[0]))) return;
+ if (!(l = LinkMeshToStr(game.init, game.init.Obj[obj].getMeshLink(0)))) return;
// Trova il punto centrale attorno a cui ruotare
pos.x = l->Pos.x;
pos.y = 350.0f;
diff --git a/engines/watchmaker/classes/do_operate.cpp b/engines/watchmaker/classes/do_operate.cpp
index ceaa3ca9855..788f99bd43a 100644
--- a/engines/watchmaker/classes/do_operate.cpp
+++ b/engines/watchmaker/classes/do_operate.cpp
@@ -142,11 +142,11 @@ void UpdateSpecial(WGame &game, int32 room) {
break;
case r31:
- if ((m = LinkMeshToStr(init, (char *)init.Obj[o31LEVETTA1].meshlink[0]))) t3dSetSpecialAnimFrame(game, "r31-cles01.a3d", m, Comb31[0] + 1);
- if ((m = LinkMeshToStr(init, (char *)init.Obj[o31LEVETTA2].meshlink[0]))) t3dSetSpecialAnimFrame(game, "r31-cles02.a3d", m, Comb31[1] + 1);
- if ((m = LinkMeshToStr(init, (char *)init.Obj[o31LEVETTA3].meshlink[0]))) t3dSetSpecialAnimFrame(game, "r31-cles03.a3d", m, Comb31[2] + 1);
- if ((m = LinkMeshToStr(init, (char *)init.Obj[o31LEVETTA4].meshlink[0]))) t3dSetSpecialAnimFrame(game, "r31-cles04.a3d", m, Comb31[3] + 1);
- if ((m = LinkMeshToStr(init, (char *)init.Obj[o31LEVETTA5].meshlink[0]))) t3dSetSpecialAnimFrame(game, "r31-cles05.a3d", m, Comb31[4] + 1);
+ if ((m = LinkMeshToStr(init, init.Obj[o31LEVETTA1].getMeshLink(0)))) t3dSetSpecialAnimFrame(game, "r31-cles01.a3d", m, Comb31[0] + 1);
+ if ((m = LinkMeshToStr(init, init.Obj[o31LEVETTA2].getMeshLink(0)))) t3dSetSpecialAnimFrame(game, "r31-cles02.a3d", m, Comb31[1] + 1);
+ if ((m = LinkMeshToStr(init, init.Obj[o31LEVETTA3].getMeshLink(0)))) t3dSetSpecialAnimFrame(game, "r31-cles03.a3d", m, Comb31[2] + 1);
+ if ((m = LinkMeshToStr(init, init.Obj[o31LEVETTA4].getMeshLink(0)))) t3dSetSpecialAnimFrame(game, "r31-cles04.a3d", m, Comb31[3] + 1);
+ if ((m = LinkMeshToStr(init, init.Obj[o31LEVETTA5].getMeshLink(0)))) t3dSetSpecialAnimFrame(game, "r31-cles05.a3d", m, Comb31[4] + 1);
break;
case r38:
diff --git a/engines/watchmaker/init/nl_init.cpp b/engines/watchmaker/init/nl_init.cpp
index f32503a2eda..1f1a63b4d9a 100644
--- a/engines/watchmaker/init/nl_init.cpp
+++ b/engines/watchmaker/init/nl_init.cpp
@@ -823,10 +823,10 @@ int StructureInitializer::ParseObject(char *s) {
obj->pos = _parser->ReadNumber();
break;
case 16:
- for (a = 0; a < MAX_OBJ_MESHLINKS; a++) if (obj->meshlink[a][0] == 0) break;
+ for (a = 0; a < MAX_OBJ_MESHLINKS; a++) if (obj->meshLinkIsEmpty(a)) break;
if (a < MAX_OBJ_MESHLINKS)
- if ((len = _parser->ReadArgument(str)) < 0 || len > sizeof(obj->meshlink[a]))return _parser->ParseError("Error reading meshlink %s in %s", str, s);
- else strcpy((char*)obj->meshlink[a], str);
+ if ((len = _parser->ReadArgument(str)) < 0 || len > MAX_MESHLINK_SIZE)return _parser->ParseError("Error reading meshlink %s in %s", str, s);
+ else obj->setMeshLink(a, str);
else _parser->ParseError("Too many Meshlink in Obj %s %d max is %d", s, a, MAX_OBJ_MESHLINKS);
break;
case 17:
@@ -958,23 +958,23 @@ int StructureInitializer::ParseAnim(char *s) {
anim->flags = ReadFlags();
break;
case 2:
- for (a = 0; a < MAX_SUBANIMS; a++) if (anim->meshlink[a][0] == 0) break;
+ for (a = 0; a < MAX_SUBANIMS; a++) if (anim->meshLinkIsEmpty(a)) break;
if ((a < MAX_SUBANIMS) && (--a >= 0))
if ((len = _parser->ReadArgument(str)) < 0 || len > sizeof(anim->name[a])) return _parser->ParseError("Error reading animname %s in %s", str, s);
else strcpy((char*)anim->name[a].rawArray(), str);
else return _parser->ParseError("Too many subanim in Anim %s sub %d max is %d", str, a, MAX_SUBANIMS);
break;
case 3:
- for (a = 0; a < MAX_SUBANIMS; a++) if (anim->meshlink[a][0] == 0) break;
+ for (a = 0; a < MAX_SUBANIMS; a++) if (anim->meshLinkIsEmpty(a)) break;
if ((a < MAX_SUBANIMS) && (len = _parser->ReadArgument(str)))
- strcpy((char *)anim->meshlink[a].rawArray(), (char *)_init.Obj[GetTokenValue(ObjToken, str)].meshlink[0]);
+ anim->setMeshLink(a, _init.Obj[GetTokenValue(ObjToken, str)].getMeshLink(0));
else return _parser->ParseError("Too many Objlinks in Anim %s sub %d max is %d", str, a, MAX_SUBANIMS);
break;
case 4:
- for (a = 0; a < MAX_SUBANIMS; a++) if (anim->meshlink[a][0] == 0) break;
+ for (a = 0; a < MAX_SUBANIMS; a++) if (anim->meshLinkIsEmpty(a)) break;
if (a < MAX_SUBANIMS)
- if ((len = _parser->ReadArgument(str)) < 0 || len > sizeof(anim->meshlink[a])) return _parser->ParseError("Error reading meshlink %s in %s", str, s);
- else strcpy((char*)anim->meshlink[a].rawArray(), str);
+ if ((len = _parser->ReadArgument(str)) < 0 || len > MAX_MESHLINK_SIZE) return _parser->ParseError("Error reading meshlink %s in %s", str, s);
+ else anim->setMeshLink(a, str);
else return _parser->ParseError("Too many Meshlinks in Anim %s sub %d max is %d", str, a, MAX_SUBANIMS);
break;
case 5:
diff --git a/engines/watchmaker/ll/ll_anim.cpp b/engines/watchmaker/ll/ll_anim.cpp
index 86daee4f6b9..13c96578a41 100644
--- a/engines/watchmaker/ll/ll_anim.cpp
+++ b/engines/watchmaker/ll/ll_anim.cpp
@@ -1414,7 +1414,7 @@ void StartAnim(WGame &game, int32 an) {
// Se esiste gia' un'animazione sullo stesso oggetto base, la termina
for (b = 0; b < MAX_ACTIVE_ANIMS; b++)
if ((ActiveAnim[b].index) && (ActiveAnim[b].CurFrame >= 0) && !(ActiveAnim[b].flags & ANIM_PAUSED) &&
- (Common::String((const char *)init.Anim[ActiveAnim[b].index].meshlink[0].rawArray()).equalsIgnoreCase((const char *)init.Anim[an].meshlink[0].rawArray())))
+ (init.Anim[ActiveAnim[b].index].getMeshLink(0).equalsIgnoreCase(init.Anim[an].getMeshLink(0))))
StopAnim(game, ActiveAnim[b].index);
// Se trova uno slot vuoto
@@ -1449,11 +1449,11 @@ void StartAnim(WGame &game, int32 an) {
h->sub[a].LastFrame = -3;
// se non c'e' un link skippa
- if (init.Anim[an].meshlink[a][0] == 0) continue;
+ if (init.Anim[an].meshLinkIsEmpty(a)) continue;
- h->sub[a].ptr = LinkMeshToStr(init, (char *)init.Anim[an].meshlink[a].rawArray());
+ h->sub[a].ptr = LinkMeshToStr(init, init.Anim[an].getMeshLink(a));
if (h->sub[a].ptr != nullptr) h->sub[a].ptr->CurFrame = -2;
- else DebugLogFile("Mesh not Found: |%s|", (char *)init.Anim[an].meshlink[a].rawArray());
+ else DebugLogFile("Mesh not Found: |%s|", init.Anim[an].getMeshLink(a).c_str());
// se non deve caricare file skippa
if ((init.Anim[an].name[a][0] == '\0') || (h->sub[a].ptr == nullptr) /*|| (h->sub[a].ptr->Flags & T3D_MESH_HIDDEN) */)
@@ -1702,8 +1702,8 @@ void StopObjAnim(WGame &game, int32 obj) {
// Se esiste gia' un'animazione sullo stesso oggetto base, la termina
for (int32 b = 0; b < MAX_ACTIVE_ANIMS; b++)
if ((ActiveAnim[b].index) && (ActiveAnim[b].CurFrame >= 0)/* && !( ActiveAnim[b].flags & ANIM_PAUSED )*/ &&
- ((Common::String((const char *)init.Anim[ActiveAnim[b].index].meshlink[0].rawArray()).equalsIgnoreCase((const char *)init.Obj[obj].meshlink[0])) || (ActiveAnim[b].obj == obj) ||
- ((CurPlayer == obj - ocDARRELL) && (Common::String((const char *)init.Anim[ActiveAnim[b].index].meshlink[0].rawArray()).equalsIgnoreCase((const char *)init.Obj[ocCURPLAYER].meshlink[0]))
+ ((init.Anim[ActiveAnim[b].index].getMeshLink(0).equalsIgnoreCase(init.Obj[obj].getMeshLink(0))) || (ActiveAnim[b].obj == obj) ||
+ ((CurPlayer == obj - ocDARRELL) && (init.Anim[ActiveAnim[b].index].getMeshLink(0).equalsIgnoreCase(init.Obj[ocCURPLAYER].getMeshLink(0)))
&& (ActiveAnim[b].sub[0].ptr) && Player && Player->Mesh && (ActiveAnim[b].sub[0].ptr == Player->Mesh))))
StopAnim(game, ActiveAnim[b].index);
}
diff --git a/engines/watchmaker/ll/ll_mesh.cpp b/engines/watchmaker/ll/ll_mesh.cpp
index 5009d4f2d29..05bab5e7e8a 100644
--- a/engines/watchmaker/ll/ll_mesh.cpp
+++ b/engines/watchmaker/ll/ll_mesh.cpp
@@ -119,7 +119,7 @@ void t3dLightRoom(Init &init, t3dBODY *b, t3dV3F *p, t3dF32 NearRange, t3dF32 Fa
sbl = (uint32 *)&SavedBodyLight[j][0];
for (k = 0; k < MAX_OBJ_MESHLINKS ; k++) {
- if (((init.Obj[oNEXTPORTAL].meshlink[k][0] != '\0') && (m->name.equalsIgnoreCase((const char *)init.Obj[oNEXTPORTAL].meshlink[k]))) ||
+ if (((!init.Obj[oNEXTPORTAL].meshLinkIsEmpty(k)) && (m->name.equalsIgnoreCase(init.Obj[oNEXTPORTAL].getMeshLink(k)))) ||
m->name.equalsIgnoreCase("p50-sentierini01") || m->name.equalsIgnoreCase("p50-sentierini02") || m->name.equalsIgnoreCase("p50-sentierini03") ||
m->name.equalsIgnoreCase("p50-sentierini04") || m->name.equalsIgnoreCase("p50-sentierini05") || m->name.equalsIgnoreCase("p50-sentierini06")) {
tmp.x = m->Pos.x - p->x;
@@ -359,7 +359,7 @@ uint8 t3dClipToSurface(Init &init, t3dV3F *pt) {
t3dVectCopy(&end, pt);
end.y = -130000.0f;
for (i = 0; i < 6; i++) {
- if ((m = LinkMeshToStr(init, (char *)init.Obj[oNEXTPORTAL].meshlink[i])) && (t3dVectMeshInters(m, start, end, &tmp))) {
+ if ((m = LinkMeshToStr(init, init.Obj[oNEXTPORTAL].getMeshLink(i))) && (t3dVectMeshInters(m, start, end, &tmp))) {
pt->y = tmp.y;
return true;
}
@@ -633,7 +633,6 @@ void MeshModifiers::applyAllMeshModifiers(WGame &game, t3dBODY *b) {
* --------------------------------------------------*/
void HideRoomMeshes(Init &init, t3dBODY *body) {
int32 cr, c, a, b, i, j, k, h, skip;
- char *str;
t3dMESH *m;
if (!(cr = getRoomFromStr(init, body->name))) return;
@@ -643,9 +642,9 @@ void HideRoomMeshes(Init &init, t3dBODY *body) {
if (init.Obj[c].flags & NOUPDATE) continue;
if (!(init.Obj[c].flags & ON) || (init.Obj[c].flags & HIDE)) {
for (b = 0; b < MAX_OBJ_MESHLINKS; b++) {
- if (init.Obj[c].meshlink[b][0] == '\0') continue;
+ if (init.Obj[c].meshLinkIsEmpty(b)) continue;
m = nullptr;
- str = (char *)init.Obj[c].meshlink[b];
+ const Common::String &str = init.Obj[c].getMeshLink(b);
for (h = 0; h < (uint16)body->NumMeshes(); h++) {
if (body->MeshTable[h].name.equalsIgnoreCase(str)) {
m = &body->MeshTable[h];
@@ -661,8 +660,8 @@ void HideRoomMeshes(Init &init, t3dBODY *body) {
if (!(init.Obj[k].flags & ON) || (init.Obj[k].flags & HIDE)) continue;
for (j = 0; j < MAX_OBJ_MESHLINKS; j++) {
- if (init.Obj[k].meshlink[j][0] == '\0') continue;
- if (!Common::String((char *)init.Obj[c].meshlink[b]).equalsIgnoreCase((char *)init.Obj[k].meshlink[j])) continue;
+ if (init.Obj[k].meshLinkIsEmpty(j)) continue;
+ if (!init.Obj[c].getMeshLink(b).equalsIgnoreCase(init.Obj[k].getMeshLink(j))) continue;
// DebugFile("Skipped for %d,%d",k,j);
skip ++;
@@ -803,7 +802,7 @@ void UpdateObjMesh(Init &init, int32 in) {
if (init.Obj[in].flags & NOUPDATE) return;
for (a = 0; a < MAX_OBJ_MESHLINKS; a++) {
- m = LinkMeshToStr(init, (char *)init.Obj[in].meshlink[a]);
+ m = LinkMeshToStr(init, init.Obj[in].getMeshLink(a));
if (m) {
if ((init.Obj[in].flags & ON) && !(init.Obj[in].flags & HIDE))
// m->Flags &= ~T3D_MESH_HIDDEN;
@@ -816,11 +815,11 @@ void UpdateObjMesh(Init &init, int32 in) {
uint32 newflags;
newflags = T3D_MESH_HIDDEN;
- if (init.Obj[in].meshlink[a][0] != '\0') {
+ if (!init.Obj[in].meshLinkIsEmpty(a)) {
if ((init.Obj[in].flags & ON) && !(init.Obj[in].flags & HIDE))
- _vm->addMeshModifier((char *)init.Obj[in].meshlink[a], MM_REMOVE_FLAGS, &newflags);
+ _vm->addMeshModifier(init.Obj[in].getMeshLink(a), MM_REMOVE_FLAGS, &newflags);
else
- _vm->addMeshModifier((char *)init.Obj[in].meshlink[a], MM_ADD_FLAGS, &newflags);
+ _vm->addMeshModifier(init.Obj[in].getMeshLink(a), MM_ADD_FLAGS, &newflags);
}
}
}//for
diff --git a/engines/watchmaker/ll/ll_util.cpp b/engines/watchmaker/ll/ll_util.cpp
index 7128be394ea..73750f76e1d 100644
--- a/engines/watchmaker/ll/ll_util.cpp
+++ b/engines/watchmaker/ll/ll_util.cpp
@@ -63,7 +63,7 @@ uint16 LinkObjToMesh(WGame &game, t3dMESH *m, uint8 op) {
for (c = ocCUOCO; c <= ocLASTCHAR; c++) {
for (b = 0; b < MAX_OBJ_MESHLINKS; b++)
if (Character[c] && Character[c]->Mesh)
- if ((init.Obj[c].meshlink[b][0] != 0) && (m->name.equalsIgnoreCase((const char *) init.Obj[c].meshlink[b])))
+ if ((!init.Obj[c].meshLinkIsEmpty(b)) && (m->name.equalsIgnoreCase(init.Obj[c].getMeshLink(b))))
return (c);
}
@@ -74,7 +74,7 @@ uint16 LinkObjToMesh(WGame &game, t3dMESH *m, uint8 op) {
(((bFirstPerson) && !(init.Obj[c].flags & HIDEIN1ST)) ||
(!(bFirstPerson) && !(init.Obj[c].flags & HIDEIN3RD)))) {
for (b = 0; b < MAX_OBJ_MESHLINKS; b++)
- if ((init.Obj[c].meshlink[b][0] != 0) && (m->name.equalsIgnoreCase((const char *)init.Obj[c].meshlink[b])))
+ if ((!init.Obj[c].meshLinkIsEmpty(b)) && (m->name.equalsIgnoreCase(init.Obj[c].getMeshLink(b))))
for (i = 0; i < t3dCurRoom->NumMeshes(); i++)
if ((m->name.equalsIgnoreCase(t3dCurRoom->MeshTable[i].name)))
return (c);
@@ -105,7 +105,7 @@ uint16 LinkObjToMesh(WGame &game, t3dMESH *m, uint8 op) {
(((bFirstPerson) && !(init.Obj[c].flags & HIDEIN1ST)) ||
(!(bFirstPerson) && !(init.Obj[c].flags & HIDEIN3RD)))) {
for (b = 0; b < MAX_OBJ_MESHLINKS; b++) {
- if ((init.Obj[c].meshlink[b][0] != 0) && m->name.equalsIgnoreCase((const char *)init.Obj[c].meshlink[b])) {
+ if ((!init.Obj[c].meshLinkIsEmpty(b)) && m->name.equalsIgnoreCase(init.Obj[c].getMeshLink(b))) {
if ((op == ME_MRIGHT) || (op == ME_MLEFT))
NextPortalObj = c;
return (c);
diff --git a/engines/watchmaker/struct.h b/engines/watchmaker/struct.h
index ce19108595f..52262fac42a 100644
--- a/engines/watchmaker/struct.h
+++ b/engines/watchmaker/struct.h
@@ -143,6 +143,9 @@ struct SRoom : public SerializableAsset {
};
struct SObject : public SerializableAsset {
+private:
+ Common::String meshlink[MAX_OBJ_MESHLINKS]; // link -> oggetto mesh (nome mesh) -> da rimuovere
+public:
uint16 name; // frase nome
SerializableArray<uint16, MAX_PLAYERS> examine; // frase esamina
SerializableArray<uint16, MAX_PLAYERS> action; // frase azione
@@ -154,10 +157,14 @@ struct SObject : public SerializableAsset {
uint8 ninv; // ptr inventario
uint16 flags; // EXAMINE | EXAMINEACT | ROOM | PERSON | TAKE | USEWITH | EXTRA | EXTRA2 | DONE | ON | HIDE
uint8 pos; // 0 se no position
- SerializableArray<SerializableArray<uint8, T3D_NAMELEN>, MAX_OBJ_MESHLINKS> meshlink_int = {};// link -> oggetto mesh (nome mesh) -> da rimuovere
- uint8 *meshlink[MAX_OBJ_MESHLINKS];
+ bool meshLinkIsEmpty(int index) { return meshlink[index].empty() || meshlink[index][0] == '\0'; }
+ const Common::String& getMeshLink(int index) { return meshlink[index]; };
+ void setMeshLink(int index, const char *value) {
+ meshlink[index] = value;
+ }
void loadFromStream(Common::SeekableReadStream &stream) override {
+ SerializableArray<SerializableArray<uint8, T3D_NAMELEN>, MAX_OBJ_MESHLINKS> meshlink_int = {};
name = stream.readUint16LE();
examine.loadFromStream(stream);
action.loadFromStream(stream);
@@ -172,7 +179,7 @@ struct SObject : public SerializableAsset {
meshlink_int.loadFromStream(stream);
// HACK:
for (int i = 0; i < MAX_OBJ_MESHLINKS; i++) {
- meshlink[i] = meshlink_int.rawArray()[i].rawArray();
+ meshlink[i] = (char*)meshlink_int.rawArray()[i].rawArray();
}
}
};
@@ -216,7 +223,10 @@ struct SAtFrame : public SerializableAsset {
};
struct SAnim : public SerializableAsset {
- SerializableArray<SerializableArray<uint8, T3D_NAMELEN>, MAX_SUBANIMS> meshlink; // link -> anim mesh (nome mesh) -> da rimuovere
+private:
+
+ Common::String meshlink[MAX_SUBANIMS]; // link -> anim mesh (nome mesh) -> da rimuovere
+public:
SerializableArray<SerializableArray<uint8, T3D_NAMELEN>, MAX_SUBANIMS> name; // nome animazione
SerializableArray<uint8, T3D_NAMELEN> RoomName; // nome stanza destinazione
SerializableArray<SAtFrame, MAX_ATFRAMES> atframe; // atframe
@@ -226,8 +236,21 @@ struct SAnim : public SerializableAsset {
uint8 pos; // posizione
uint8 cam; // camera per l'azione
+ bool meshLinkIsEmpty(int index) { return meshlink[index].empty() || meshlink[index][0] == '\0'; }
+ const Common::String& getMeshLink(int index) { return meshlink[index]; }
+ void setMeshLink(int index, const char *value) {
+ meshlink[index] = value;
+ }
+ void setMeshLink(int index, const Common::String &value) {
+ meshlink[index] = value;
+ }
+
void loadFromStream(Common::SeekableReadStream &stream) override {
- meshlink.loadFromStream(stream);
+ SerializableArray<SerializableArray<uint8, T3D_NAMELEN>, MAX_SUBANIMS> meshlink_raw;
+ meshlink_raw.loadFromStream(stream);
+ for (int i = 0; i < MAX_SUBANIMS; i++) {
+ meshlink[i] = (const char*)meshlink_raw.rawArray();
+ }
name.loadFromStream(stream);
RoomName.loadFromStream(stream);
atframe.loadFromStream(stream);
diff --git a/engines/watchmaker/sysdef.h b/engines/watchmaker/sysdef.h
index 494f9c6a68c..5b83884b2a2 100644
--- a/engines/watchmaker/sysdef.h
+++ b/engines/watchmaker/sysdef.h
@@ -111,6 +111,7 @@ namespace Watchmaker {
#define MAX_TEXT_LINES 10 // numero massimo di linee per la formattazione
#define MAX_TEXT_CHARS 160 // numero massimo di caratteri per linea per la formattazione
+#define MAX_MESHLINK_SIZE T3D_NAMELEN
// GESTIONE DELL'USA CON..
#define USED 0
diff --git a/engines/watchmaker/walk/ball.cpp b/engines/watchmaker/walk/ball.cpp
index e3c9ef82871..3c9233b0f72 100644
--- a/engines/watchmaker/walk/ball.cpp
+++ b/engines/watchmaker/walk/ball.cpp
@@ -195,7 +195,7 @@ void UpdateBall(WGame &game, struct SPhys *p) {
t3dVectCopy(&end, &Palla50->Mesh->Trasl);
end.y = -130000.0f;
for (i = 0; i < 6; i++)
- if ((m = LinkMeshToStr(init, (const char *)init.Obj[oNEXTPORTAL].meshlink[i])) && (t3dVectMeshInters(m, start, end, &tmp)))
+ if ((m = LinkMeshToStr(init, init.Obj[oNEXTPORTAL].getMeshLink(i))) && (t3dVectMeshInters(m, start, end, &tmp)))
break;
if (tmp.y < 0.0f) tmp.y = 0.0f;
if ((Palla50->Mesh->Trasl.y < (tmp.y + 0.01f)) && (p->MVt > 0.1)) {
More information about the Scummvm-git-logs
mailing list