/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #ifndef M4_WSCRIPT_WS_MACHINE_H #define M4_WSCRIPT_WS_MACHINE_H #include "common/algorithm.h" #include "m4/m4_types.h" #include "m4/gui/gui.h" namespace M4 { #define DEAD_MACHINE_ID 0xdeaddead enum { NOSEPICK = 0, STARTWALK = 1, WALKSEQ = 2, ENDWALK = 3, DEMAND_FACING = 4, DEMAND_LOCATION = 5, TERMINATE = 6, PLAYER_HIDE = 7, PLAYER_UNHIDE = 8, TURN_TO_FACE = 9, ACTION_11 = 11, ACTION_12 = 12, ACTION_13 = 13, ACTION_14 = 14, ACTION_15 = 15, ACTION_17 = 17, ACTION_18 = 18, ACTION_19 = 19, ACTION_20 = 20, ACTION_21 = 21, ACTION_22 = 22, ACTION_23 = 23, ACTION_24 = 24, ACTION_25 = 25, ACTION_26 = 26, ACTION_27 = 27, ACTION_28 = 28, ACTION_29 = 29, ACTION_30 = 30, ACTION_31 = 31, ACTION_32 = 32, ACTION_33 = 33, ACTION_666 = 666, ACTION_900 = 900, ACTION_902 = 902 }; // A message request struct msgRequest { msgRequest *nextMsg = nullptr; uint32 msgHash = 0; frac16 msgValue = 0; int32 pcOffset = 0; int32 pcCount = 0; }; struct machine; typedef void (*MessageCB)(frac16 myMessage, struct machine *sender); //timebase request structure. struct onTimeReq { onTimeReq *next = nullptr; int32 myTime = 0; struct machine *myXM = nullptr; int32 pcOffset = 0; int32 pcCount = 0; }; // rails algorithm struct struct railNode { uint8 nodeID = 0; int32 x = 0, y = 0; railNode *shortPath = nullptr; int32 pathWeight = 0; }; struct CCB { uint32 flags = 0; M4sprite *source = nullptr; M4Rect *currLocation = nullptr; M4Rect *newLocation = nullptr; M4Rect *maxArea = nullptr; int32 scaleX = 0; int32 scaleY = 0; int32 layer = 0; uint32 *streamSSHeader = nullptr; uint32 *streamSpriteSource = nullptr; void *myStream = nullptr; char *seriesName = nullptr; }; #define JSR_STACK_MAX 8 struct Anim8 { machine *myMachine = nullptr; // Pointer back to myMachine int32 eosReqOffset = 0; // The machine PC offset to be executed at the EOS int32 eosReqCount = 0; Anim8 *next = nullptr; // The linked list used for execution order Anim8 *prev = nullptr; int32 myLayer = 0; Anim8 *infront = nullptr; // The linked list used for layering Anim8 *behind = nullptr; Anim8 *myParent = nullptr; // The parent anim8 int32 sequHash = 0; // The current sequence Hash = 0; MemHandle sequHandle = nullptr; // The sequence Handle int32 pcOffset = 0; // The offset into the sequence of the current PC CCB *myCCB = nullptr; int32 dataHash = 0; // The array of data MemHandle dataHandle = nullptr; int32 dataOffset = 0; int32 startTime = 0; int32 switchTime = 0; frac16 transTime = 0; int32 flags = 0; frac16 start_s = 0; frac16 start_r = 0; frac16 start_x = 0; frac16 start_y = 0; int32 numLocalVars = 0; frac16 *myRegs = nullptr; bool active = false; int32 returnStackIndex = 0; uint32 returnHashes[JSR_STACK_MAX] = { 0 }; int32 returnOffsets[JSR_STACK_MAX] = { 0 }; Anim8() { Common::fill(returnHashes, returnHashes + JSR_STACK_MAX, 0); Common::fill(returnOffsets, returnOffsets + JSR_STACK_MAX, 0); } }; struct machine { machine *next = nullptr; machine *prev = nullptr; uint32 myHash = 0; uint32 machID = 0; char *machName = nullptr; MemHandle machHandle = 0; int32 machInstrOffset = 0; int32 stateTableOffset = 0; int32 curState = 0; int32 numOfStates = 0; uint32 recurseLevel = 0; Anim8 *myAnim8 = nullptr; Anim8 *parentAnim8 = nullptr; int32 dataHash = 0; MemHandle dataHandle = 0; int32 dataOffset = 0; int32 targetCount = 0; struct machine *msgReplyXM = nullptr; MessageCB CintrMsg; msgRequest *myMsgs = nullptr; msgRequest *myPersistentMsgs = nullptr; msgRequest *usedPersistentMsgs = nullptr; railNode *walkPath = nullptr; }; struct globalMsgReq { globalMsgReq *next = nullptr; ulong msgHash = 0; frac16 msgValue = 0; ulong machHash = 0; machine *sendM = nullptr; int32 msgCount = 0; }; struct WSMachine_Globals { int32 _pauseTime = 0; int32 _oldTime = 0; bool _enginesPaused = false; int32 *_dataFormats = nullptr; uint32 _machineIDCount = 0; machine *_firstMachine = nullptr; machine *_nextXM = nullptr; globalMsgReq *_myGlobalMessages = nullptr; // Used for processing pCodes frac16 *_ws_globals = nullptr; void *_addrExists = nullptr; }; bool ws_Initialize(frac16 *theGlobals); void ws_Shutdown(); void pauseEngines(); void unpauseEngines(); void addPauseTime(int32 myTime); void cycleEngines(Buffer *cleanBackground, int16 *depth_table, Buffer *screenCodes, uint8 *myPalette, uint8 *ICT, bool updateVideo); void ws_RefreshWoodscriptBuffer(Buffer *cleanBackground, int16 *depth_table, Buffer *screenCodes, uint8 *myPalette, uint8 *ICT); void terminateMachine(machine *m); void terminateMachinesByHash(uint32 machHash); void terminateMachineAndNull(machine *&m); bool verifyMachineExists(machine *m); int32 ws_KillMachines(); void ws_KillDeadMachines(); void ws_StepWhile(machine *m, int32 pcOffset, int32 pcCount); void IntoTheState(machine *m); machine *TriggerMachineByHash(int32 myHash, Anim8 *parentAnim8, int32 dataHash, int32 dataRow, MessageCB CintrMsg, bool debug, const char *machName); machine *TriggerMachineByHash(int32 val1, int32 val2, int32 val3, int32 val4, int32 val5, int32 val6, int32 x, int32 y, int32 scale, int32 layer, bool flag, MessageCB intrMsg, const char *machName); machine *TriggerMachineByHash(MessageCB intrMsg, const char *machName); /** * This proc is what allows a machine to send a message to another machine(s) */ void sendWSMessage(uint32 msgHash, frac16 msgValue, machine *recvM, uint32 machHash, machine *sendM, int32 msgCount); void sendWSMessage(int32 val1, machine *recv, int32 series1, int32 val3, int32 val4, int32 trigger, int32 series2, int32 val6, int32 val7, int32 val8); #define kernel_spawn_machine(name,hash,callback) TriggerMachineByHash(hash, nullptr, -1, -1, callback, false, name) #define kernel_terminate_machine(m) terminateMachine(m) } // End of namespace M4 #endif