Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,140 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef M4_WSCRIPT_WS_CRUNCHER_H
#define M4_WSCRIPT_WS_CRUNCHER_H
#include "m4/m4_types.h"
#include "m4/wscript/ws_machine.h"
namespace M4 {
#define OP_INSTR 0xfe000000
#define OP_FORMAT1 0x01c00000
#define OP_FORMAT2 0x00380000
#define OP_FORMAT3 0x00070000
#define OP_LOW_DATA 0x0000ffff
#define OP_DATA_SIGN 0x8000
#define OP_DATA_VALUE 0x7fff
#define FMT_NOTHING 0
#define FMT_LOCAL_SRC 1
#define FMT_GLOBAL_SRC 2
#define FMT_INT15 3
#define FMT_4_11 4
#define FMT_7_8 5
#define FMT_11_4 6
#define FMT_15_0 7
#define REG_SET_IDX 0x0fff
#define REG_SET_IDX_REG 0x8000
#define LOCAL_FMT 0x7000
#define LOCAL_FMT_PARENT 0x0000
#define LOCAL_FMT_REG 0x1000
#define LOCAL_FMT_DATA 0x2000
#define BRANCH_BR 0
#define BRANCH_BLT 1
#define BRANCH_BLE 2
#define BRANCH_BE 3
#define BRANCH_BNE 4
#define BRANCH_BGE 5
#define BRANCH_BGT 6
struct EOSreq {
EOSreq *next = nullptr;
EOSreq *prev = nullptr;
Anim8 *myAnim8 = nullptr;
};
struct cruncher {
Anim8 *backLayerAnim8;
Anim8 *frontLayerAnim8;
Anim8 *firstAnim8ToCrunch;
Anim8 *lastAnim8ToCrunch;
};
struct WSCruncher_Globals {
cruncher *_myCruncher = nullptr;
bool _cruncherInitialized = false;
EOSreq *_EOSreqList = nullptr;
int32 _memtypeEOS = -1;
int32 _stackSize = 0;
uint32 *_stackBase = nullptr;
uint32 *_stackTop = nullptr;
uint32 *_stackLimit = nullptr;
Anim8 *_crunchNext = nullptr;
// OPCODE PROCESSING GLOBALS
int16 *_myDepthTable = nullptr;
frac16 _dataArg1 = 0;
frac16 _dataArg2 = 0;
frac16 _dataArg3 = 0;
frac16 *_myArg1 = nullptr;
frac16 *_myArg2 = nullptr;
frac16 *_myArg3 = nullptr;
bool _keepProcessing = false, _terminated = false, _mapTheCel = false;
bool _bailOut = false;
int32 _compareCCR = 0;
int32 _indexReg = 0;
int32 _pcOffsetOld = 0;
};
int32 *ws_GetDataFormats();
bool ws_InitCruncher();
void ws_KillCruncher();
Anim8 *ws_AddAnim8ToCruncher(machine *m, int32 sequHash);
/**
* This procedure assumes a machine has a slot with it's own memory
*/
bool ws_ChangeAnim8Program(machine *m, int32 newSequHash);
/**
* This procedure flags the anim8 slot as empty
*/
void ws_RemoveAnim8FromCruncher(Anim8 *myAnim8);
bool ws_PauseAnim8(Anim8 *myAnim8);
bool ws_ResumeAnim8(Anim8 *myAnim8);
/**
* Pre-processes a pcode instruction parameters.
* The instruction number is returned by this function, and the arguments are
* pointed to by these external globals:
* Frac16 *myArg1
* Frac16 *myArg2
* Frac16 *myArg3
*/
int32 ws_PreProcessPcode(uint32 **PC, Anim8 *myAnim8);
void ws_CrunchAnim8s(int16 *depth_table);
void ws_CrunchEOSreqs();
bool ws_OnEndSeqRequest(Anim8 *myAnim8, int32 pcOffset, int32 pcCount);
void ws_CancelOnEndSeq(Anim8 *myAnim8);
} // End of namespace M4
#endif

View File

@@ -0,0 +1,659 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "common/savefile.h"
#include "common/textconsole.h"
#include "m4/wscript/ws_hal.h"
#include "m4/wscript/wst_regs.h"
#include "m4/core/errors.h"
#include "m4/core/imath.h"
#include "m4/dbg/debug.h"
#include "m4/graphics/gr_sprite.h"
#include "m4/graphics/rend.h"
#include "m4/gui/gui_vmng.h"
#include "m4/vars.h"
#include "m4/m4.h"
namespace M4 {
bool ws_InitHAL() {
_GWS(deadRectList) = nullptr;
return true;
}
void ws_KillHAL() {
vmng_DisposeRectList(&_GWS(deadRectList));
}
void ws_DumpMachine(machine *m, Common::WriteStream *logFile) {
int32 i;
double tempFloat;
if (!m || !logFile)
return;
// Print out the machine name, hash, and physical address
logFile->writeString(Common::String::format("Machine Name: %s\n\tHash: %d\n\tAddress: %p\n\n", m->machName, m->myHash, (void *)m));
// If we have an anim8 for this machine
if (m->myAnim8) {
Anim8 *myAnim8 = m->myAnim8;
// Print out the anim8 hash, and physical address
logFile->writeString(Common::String::format("Sequence Hash: %d\n\tAddress: %p\n\n", myAnim8->sequHash, (void *)myAnim8));
// And if this anim8 has registers
if (myAnim8->myRegs) {
frac16 *myRegs = myAnim8->myRegs;
logFile->writeString("Registers:\n");
// Loop through the main set of registers, and dump out the contents
for (i = 0; i < IDX_COUNT; i++) {
tempFloat = (float)(myRegs[i] >> 16) + (float)((float)(myRegs[i] & 0xffff) / (float)65536);
logFile->writeString(Common::String::format("\t%d\t%s:\t\t%.2f\t\t0x%08" PRIxPTR "\n", i, myRegLabels[i], tempFloat, myRegs[i]));
}
// If the anim8 has extra local regs
if (myAnim8->numLocalVars > 0) {
for (i = IDX_COUNT; i < IDX_COUNT + myAnim8->numLocalVars; i++) {
tempFloat = (float)(myRegs[i] >> 16) + (float)((float)(myRegs[i] & 0xffff) / (float)65536);
logFile->writeString(Common::String::format("\t%d\tlocal.%d:\t\t%.2f\t\t0x%08" PRIxPTR "\n", i, i - IDX_COUNT, tempFloat, myRegs[i]));
}
}
logFile->writeString(Common::String::format("\n"));
}
// If this anim8 has a CCB
if (myAnim8->myCCB) {
CCB *myCCB = myAnim8->myCCB;
logFile->writeString(Common::String::format("Sprite Series Name: %s\tAddress:%p\tFlags0x%08x\n", myCCB->seriesName, (void *)myCCB, myCCB->flags));
logFile->writeString(Common::String::format("\tCurrent Location: (%d, %d), (%d, %d)\n", myCCB->currLocation->x1, myCCB->currLocation->y1,
myCCB->currLocation->x2, myCCB->currLocation->y2));
logFile->writeString(Common::String::format("\tNew Location: (%d, %d), (%d, %d)\n", myCCB->newLocation->x1, myCCB->newLocation->y1,
myCCB->newLocation->x2, myCCB->newLocation->y2));
logFile->writeString(Common::String::format("\tscale: %d\n", myCCB->scaleX));
logFile->writeString(Common::String::format("\tlayer: %d\n", myCCB->layer));
}
}
}
void ws_Error(machine *m, int32 errorType, trigraph errorCode, const char *errMsg) {
char description[MAX_STRING_SIZE];
// Find the error description
error_look_up(errorCode, description);
// Open the logFile
Common::OutSaveFile *logFile = g_system->getSavefileManager()->openForSaving("ws_mach.log");
// Give the WS debugger a chance to indicate the error to the apps programmer
dbg_WSError(logFile, m, errorType, description, errMsg, _GWS(pcOffsetOld));
// Dump out the machine to the logFile
ws_DumpMachine(m, logFile);
// Close the logFile
if (logFile)
f_io_close(logFile);
// Now we fatal abort
error_show(FL, errorCode, errMsg);
}
void ws_LogErrorMsg(const char *filename, uint32 line, const char *fmt, ...) {
va_list argPtr;
va_start(argPtr, fmt);
const Common::String msg = Common::String::vformat(fmt, argPtr);
va_end(argPtr);
error("%s", msg.c_str());
}
machine *kernel_timer_callback(int32 ticks, int16 trigger, MessageCB callMe) {
_GWS(ws_globals)[GLB_TEMP_1] = (frac16)(ticks << 16);
_GWS(ws_globals)[GLB_TEMP_2] = (frac16)trigger;
return (TriggerMachineByHash(1, nullptr, -1, -1, callMe, false, "timer callback"));
}
static void drawSprite(CCB *myCCB, Anim8 *myAnim8, Buffer *halScrnBuf, Buffer *screenCodeBuff,
uint8 *myPalette, uint8 *ICT) {
// Temporary var to prevent excessive dereferences
M4sprite *source = myCCB->source;
if (!(myCCB->flags & CCB_DISC_STREAM)) {
// Make sure the sprite is still in memory
if (!source->sourceHandle || !*(source->sourceHandle)) {
ws_LogErrorMsg(FL, "Sprite series is no longer in memory.");
ws_Error(myAnim8->myMachine, ERR_INTERNAL, 0x02ff, "Error during ws_DoDisplay()");
}
// Lock the sprite handle
HLock(source->sourceHandle);
source->data = (uint8 *)((intptr)*(source->sourceHandle) + source->sourceOffset);
}
assert(myCCB->currLocation);
Buffer Destination;
DrawRequest dr;
Destination.w = source->w;
Destination.h = source->h;
Destination.stride = source->w;
Destination.encoding = (myPalette && ICT) ? source->encoding : source->encoding & 0x7f;
Destination.data = source->data;
dr.Src = &Destination;
dr.Dest = halScrnBuf;
dr.x = myCCB->currLocation->x1;
dr.y = myCCB->currLocation->y1;
dr.scaleX = myCCB->scaleX;
dr.scaleY = myCCB->scaleY;
dr.depthCode = screenCodeBuff->data;
dr.Pal = myPalette;
dr.ICT = ICT;
dr.srcDepth = myCCB->layer >> 8;
// And draw the sprite
gr_sprite_draw(&dr);
myCCB->flags &= ~CCB_REDRAW;
if (!(myCCB->flags & CCB_DISC_STREAM))
// Unlock the sprite's handle
HUnLock(source->sourceHandle);
}
void ws_DoDisplay(Buffer *background, int16 *depth_table, Buffer *screenCodeBuff,
uint8 *myPalette, uint8 *ICT, bool updateVideo) {
if (!background)
error("ws_DoDisplay : background not set");
CCB *myCCB;
RectList *myRect;
RectList *drawRectList;
int32 status;
int32 restoreBgndX1, restoreBgndY1, restoreBgndX2, restoreBgndY2;
M4Rect *currRect;
bool breakFlag;
ScreenContext *myScreen = vmng_screen_find(_G(gameDrawBuff), &status);
if ((myScreen == nullptr) || (status != SCRN_ACTIVE)) {
return;
}
Buffer *halScrnBuf = _G(gameDrawBuff)->get_buffer();
const int32 scrnX1 = myScreen->x1;
const int32 scrnY1 = myScreen->y1;
const bool greyMode = krn_GetGreyMode();
// Initialize the drawRectList to the deadRectList
drawRectList = _GWS(deadRectList);
_GWS(deadRectList) = nullptr;
// Now we loop back to front and set up a list of drawing areas
Anim8 *myAnim8 = _GWS(myCruncher)->backLayerAnim8;
while (myAnim8) {
myCCB = myAnim8->myCCB;
if (myCCB && myCCB->source && (!(myCCB->flags & CCB_NO_DRAW)) && (myCCB->flags & CCB_REDRAW)) {
currRect = myCCB->currLocation;
M4Rect *newRect = myCCB->newLocation;
if (!(myCCB->flags & CCB_STREAM) && (!greyMode || !(myCCB->source->encoding & 0x80))) {
vmng_AddRectToRectList(&drawRectList, currRect->x1, currRect->y1,
currRect->x2, currRect->y2);
if ((!greyMode && (myCCB->source->encoding & 0x80)) ||
(greyMode && !(myCCB->source->encoding & 0x80))) {
vmng_AddRectToRectList(&drawRectList, newRect->x1, newRect->y1,
newRect->x2, newRect->y2);
}
}
// Copy over rect
*currRect = *newRect;
}
myAnim8 = myAnim8->infront;
}
// The drawRectList now contains all the areas of the screen that need the background updated
// Update the background behind the current rect list - if we are in greyMode, we do this later
if (!greyMode && background->data) {
myRect = drawRectList;
while (myRect) {
restoreBgndX1 = imath_max(myRect->x1, 0);
restoreBgndY1 = imath_max(myRect->y1, 0);
restoreBgndX2 = imath_min(myRect->x2, background->w - 1);
restoreBgndY2 = imath_min(myRect->y2, background->h - 1);
gr_buffer_rect_copy(background, halScrnBuf, restoreBgndX1, restoreBgndY1,
restoreBgndX2 - restoreBgndX1 + 1, restoreBgndY2 - restoreBgndY1 + 1);
myRect = myRect->next;
}
}
// Further iteration to set up drawing rects
myAnim8 = _GWS(myCruncher)->backLayerAnim8;
while (myAnim8) {
myCCB = myAnim8->myCCB;
if (myCCB && myCCB->source && !(myCCB->flags & CCB_NO_DRAW) && (myCCB->flags & CCB_REDRAW)) {
if (!(myCCB->source->encoding & 0x80) || (myCCB->flags & CCB_STREAM)) {
currRect = myCCB->currLocation;
vmng_AddRectToRectList(&drawRectList, currRect->x1, currRect->y1,
currRect->x2, currRect->y2);
}
}
myAnim8 = myAnim8->infront;
}
// Handle merging intersecting draw rects
do {
// Presume we'll be able to break
breakFlag = true;
// Iterate through the rects
myAnim8 = _GWS(myCruncher)->backLayerAnim8;
while (myAnim8) {
myCCB = myAnim8->myCCB;
if (myCCB && myCCB->source && !(myCCB->flags & (CCB_NO_DRAW | CCB_REDRAW))) {
currRect = myCCB->currLocation;
if (vmng_RectIntersectsRectList(drawRectList, currRect->x1, currRect->y1,
currRect->x2, currRect->y2)) {
vmng_AddRectToRectList(&drawRectList, currRect->x1, currRect->y1,
currRect->x2, currRect->y2);
myCCB->flags |= CCB_REDRAW;
if (greyMode || (myCCB->source->encoding & 0x80))
breakFlag = false;
if (!greyMode && (myCCB->source->encoding & 0x80)) {
restoreBgndX1 = imath_max(currRect->x1, 0);
restoreBgndY1 = imath_max(currRect->y1, 0);
restoreBgndX2 = imath_min(currRect->x2, background->w - 1);
restoreBgndY2 = imath_min(currRect->y2, background->h - 1);
gr_buffer_rect_copy(background, halScrnBuf, restoreBgndX1, restoreBgndY1,
restoreBgndX2 - restoreBgndX1 + 1, restoreBgndY2 - restoreBgndY1 + 1);
}
}
}
myAnim8 = myAnim8->infront;
}
} while (!breakFlag);
// Handle update background rect area
if (greyMode && background->data) {
myRect = drawRectList;
while (myRect) {
restoreBgndX1 = imath_max(myRect->x1, 0);
restoreBgndY1 = imath_max(myRect->y1, 0);
restoreBgndX2 = imath_min(myRect->x2, background->w - 1);
restoreBgndY2 = imath_min(myRect->y2, background->h - 1);
gr_buffer_rect_copy(background, halScrnBuf, restoreBgndX1, restoreBgndY1,
restoreBgndX2 - restoreBgndX1 + 1, restoreBgndY2 - restoreBgndY1 + 1);
myRect = myRect->next;
}
}
// Now we loop back to front and update the area of each sprite that intersects the update list,
// or simply draw the sprite if it has been marked for redraw
myAnim8 = _GWS(myCruncher)->backLayerAnim8;
while (myAnim8) {
myCCB = myAnim8->myCCB;
if (myCCB && myCCB->source && (!(myCCB->flags & CCB_NO_DRAW))) {
if ((myCCB->flags & CCB_REDRAW) && (!greyMode || !(myCCB->source->encoding & 0x80))) {
// Draw the sprite
drawSprite(myCCB, myAnim8, halScrnBuf, screenCodeBuff, myPalette, ICT);
}
}
myAnim8 = myAnim8->infront;
}
myRect = drawRectList;
while (myRect) {
if (updateVideo) {
if (greyMode) {
krn_UpdateGreyArea(halScrnBuf, scrnX1, scrnY1, myRect->x1, myRect->y1, myRect->x2, myRect->y2);
}
RestoreScreens(scrnX1 + myRect->x1, scrnY1 + myRect->y1, scrnX1 + myRect->x2, scrnY1 + myRect->y2);
}
myRect = myRect->next;
}
_G(gameDrawBuff)->release();
// Turf the drawRectList
vmng_DisposeRectList(&drawRectList);
}
void ws_hal_RefreshWoodscriptBuffer(cruncher *myCruncher, Buffer *background,
int16 *depth_table, Buffer *screenCodes, uint8 *myPalette, uint8 *ICT) {
Buffer drawSpriteBuff;
DrawRequest spriteDrawReq;
if (!background || !background->data)
return;
term_message("Refresh");
// Restore the background
Buffer *halScrnBuf = _G(gameDrawBuff)->get_buffer();
gr_buffer_rect_copy(background, halScrnBuf, 0, 0, halScrnBuf->w, halScrnBuf->h);
// Now draw all the sprites that are not hidden
Anim8 *myAnim8 = myCruncher->backLayerAnim8;
while (myAnim8) {
CCB *myCCB = myAnim8->myCCB;
if (myCCB && (myCCB->source != nullptr) && (!(myCCB->flags & CCB_SKIP)) && (!(myCCB->flags & CCB_HIDE))) {
if (!(myCCB->flags & CCB_DISC_STREAM)) {
// Make sure the series is still in memory
if ((!myCCB->source->sourceHandle) || (!*(myCCB->source->sourceHandle))) {
ws_LogErrorMsg(FL, "Sprite series is no longer in memory.");
ws_Error(myAnim8->myMachine, ERR_INTERNAL, 0x02ff,
"Error discovered during ws_hal_RefreshWoodscriptBuffer()");
}
// Lock the sprite handle
HLock(myCCB->source->sourceHandle);
myCCB->source->data = (uint8 *)((intptr)*(myCCB->source->sourceHandle) +
myCCB->source->sourceOffset);
}
// Prepare a sprite for drawing, as in ws_DoDisplay
drawSpriteBuff.w = myCCB->source->w;
drawSpriteBuff.h = myCCB->source->h;
drawSpriteBuff.stride = myCCB->source->w;
if (!myPalette || !ICT)
drawSpriteBuff.encoding = (uint8)(myCCB->source->encoding & 0x7f);
else
drawSpriteBuff.encoding = (uint8)myCCB->source->encoding;
drawSpriteBuff.data = myCCB->source->data;
if (!depth_table || !screenCodes || !screenCodes->data) {
spriteDrawReq.srcDepth = 0;
spriteDrawReq.depthCode = nullptr;
} else {
spriteDrawReq.srcDepth = (uint8)(myCCB->layer >> 8);
spriteDrawReq.depthCode = screenCodes->data;
}
spriteDrawReq.Src = (Buffer *)&drawSpriteBuff;
spriteDrawReq.Dest = halScrnBuf;
spriteDrawReq.x = myCCB->currLocation->x1;
spriteDrawReq.y = myCCB->currLocation->y1;
spriteDrawReq.scaleX = myCCB->scaleX;
spriteDrawReq.scaleY = myCCB->scaleY;
spriteDrawReq.Pal = myPalette;
spriteDrawReq.ICT = ICT;
gr_sprite_draw(&spriteDrawReq);
myCCB->flags &= ~CCB_REDRAW;
if (!(myCCB->flags & CCB_DISC_STREAM)) {
// Unlock the handle
HUnLock(myCCB->source->sourceHandle);
}
}
myAnim8 = myAnim8->infront;
}
_G(gameDrawBuff)->release();
}
void GetBezCoeffs(frac16 *ctrlPoints, frac16 *coeffs) {
const frac16 x0 = ctrlPoints[0];
const frac16 x0mult3 = (x0 << 1) + x0;
const frac16 x1mult3 = (ctrlPoints[2] << 1) + ctrlPoints[2];
const frac16 x1mult6 = x1mult3 << 1;
const frac16 x2mult3 = (ctrlPoints[4] << 1) + ctrlPoints[4];
const frac16 x3 = ctrlPoints[6];
const frac16 y0 = ctrlPoints[1];
const frac16 y0mult3 = (y0 << 1) + y0;
const frac16 y1mult3 = (ctrlPoints[3] << 1) + ctrlPoints[3];
const frac16 y1mult6 = y1mult3 << 1;
const frac16 y2mult3 = (ctrlPoints[5] << 1) + ctrlPoints[5];
const frac16 y3 = ctrlPoints[7];
coeffs[0] = -(int)x0 + x1mult3 - x2mult3 + x3;
coeffs[2] = x0mult3 - x1mult6 + x2mult3;
coeffs[4] = -(int)x0mult3 + x1mult3;
coeffs[6] = x0;
coeffs[1] = -(int)y0 + y1mult3 - y2mult3 + y3;
coeffs[3] = y0mult3 - y1mult6 + y2mult3;
coeffs[5] = -(int)y0mult3 + y1mult3;
coeffs[7] = y0;
return;
}
void GetBezPoint(frac16 *x, frac16 *y, frac16 *coeffs, frac16 tVal) {
*x = coeffs[6] +
MulSF16(tVal, (coeffs[4] +
MulSF16(tVal, (coeffs[2] +
MulSF16(tVal, coeffs[0])))));
*y = coeffs[7] +
MulSF16(tVal, (coeffs[5] +
MulSF16(tVal, (coeffs[3] +
MulSF16(tVal, coeffs[1])))));
}
bool InitCCB(CCB *myCCB) {
myCCB->flags = CCB_SKIP;
myCCB->source = nullptr;
if ((myCCB->currLocation = (M4Rect *)mem_alloc(sizeof(M4Rect), "Rectangle")) == nullptr) {
return false;
}
myCCB->currLocation->x1 = -1;
myCCB->currLocation->y1 = -1;
myCCB->currLocation->x2 = -1;
myCCB->currLocation->y2 = -1;
if ((myCCB->newLocation = (M4Rect *)mem_alloc(sizeof(M4Rect), "Rectangle")) == nullptr) {
return false;
}
myCCB->newLocation->x1 = -1;
myCCB->newLocation->y1 = -1;
myCCB->newLocation->x2 = -1;
myCCB->newLocation->y2 = -1;
myCCB->maxArea = nullptr;
myCCB->scaleX = 0;
myCCB->scaleY = 0;
myCCB->layer = 0;
myCCB->streamSSHeader = nullptr;
myCCB->streamSpriteSource = nullptr;
myCCB->myStream = nullptr;
myCCB->seriesName = nullptr;
return true;
}
void HideCCB(CCB *myCCB) {
if (!myCCB)
return;
myCCB->flags |= CCB_HIDE;
if ((myCCB->flags & CCB_STREAM) && myCCB->maxArea) {
vmng_AddRectToRectList(&_GWS(deadRectList), myCCB->maxArea->x1, myCCB->maxArea->y1, myCCB->maxArea->x2, myCCB->maxArea->y2);
mem_free(myCCB->maxArea);
myCCB->maxArea = nullptr;
} else {
vmng_AddRectToRectList(&_GWS(deadRectList), myCCB->currLocation->x1, myCCB->currLocation->y1, myCCB->currLocation->x2, myCCB->currLocation->y2);
}
}
void ShowCCB(CCB *myCCB) {
if (!myCCB)
return;
myCCB->flags &= ~CCB_HIDE;
}
void MoveCCB(CCB *myCCB, frac16 deltaX, frac16 deltaY) {
if (!myCCB || !myCCB->source) {
error_show(FL, 'WSIC');
}
myCCB->newLocation->x1 = myCCB->currLocation->x1 + (deltaX >> 16);
myCCB->newLocation->y1 = myCCB->currLocation->y1 + (deltaY >> 16);
myCCB->newLocation->x2 = myCCB->currLocation->x2 + (deltaX >> 16);
myCCB->newLocation->y2 = myCCB->currLocation->y2 + (deltaY >> 16);
if (myCCB->flags & CCB_STREAM) {
if (!myCCB->maxArea) {
if ((myCCB->maxArea = (M4Rect *)mem_alloc(sizeof(M4Rect), "Rectangle")) == nullptr) {
error_show(FL, 'OOM!');
}
myCCB->maxArea->x1 = myCCB->newLocation->x1;
myCCB->maxArea->y1 = myCCB->newLocation->y1;
myCCB->maxArea->x2 = myCCB->newLocation->x2;
myCCB->maxArea->y2 = myCCB->newLocation->y2;
} else {
myCCB->maxArea->x1 = imath_min(myCCB->maxArea->x1, myCCB->newLocation->x1);
myCCB->maxArea->y1 = imath_min(myCCB->maxArea->y1, myCCB->newLocation->y1);
myCCB->maxArea->x2 = imath_max(myCCB->maxArea->x2, myCCB->newLocation->x2);
myCCB->maxArea->y2 = imath_max(myCCB->maxArea->y2, myCCB->newLocation->y2);
}
}
if ((myCCB->source->w != 0) && (myCCB->source->h != 0)) {
myCCB->flags |= CCB_REDRAW;
}
}
void KillCCB(CCB *myCCB, bool restoreFlag) {
if (!myCCB) {
error_show(FL, 'WSIC');
}
if (restoreFlag && (!(myCCB->flags & CCB_SKIP)) && (!(myCCB->flags & CCB_HIDE))) {
if ((myCCB->flags & CCB_STREAM) && myCCB->maxArea) {
vmng_AddRectToRectList(&_GWS(deadRectList), myCCB->maxArea->x1, myCCB->maxArea->y1,
myCCB->maxArea->x2, myCCB->maxArea->y2);
} else {
vmng_AddRectToRectList(&_GWS(deadRectList), myCCB->currLocation->x1, myCCB->currLocation->y1,
myCCB->currLocation->x2, myCCB->currLocation->y2);
}
}
if (myCCB->flags & CCB_DISC_STREAM) {
ws_CloseSSstream(myCCB);
}
if (myCCB->currLocation) {
mem_free(myCCB->currLocation);
}
if (myCCB->newLocation) {
mem_free(myCCB->newLocation);
}
if (myCCB->maxArea) {
mem_free(myCCB->maxArea);
}
if (myCCB->source) {
mem_free(myCCB->source);
}
mem_free(myCCB);
}
void Cel_msr(Anim8 *myAnim8) {
if (!myAnim8) {
error_show(FL, 'WSAI');
}
CCB *myCCB = myAnim8->myCCB;
if ((!myCCB) || (!myCCB->source)) {
error_show(FL, 'WSIC');
}
if ((myCCB->source->w == 0) || (myCCB->source->h == 0)) {
return;
}
frac16 *myRegs = myAnim8->myRegs;
if (!myRegs) {
error_show(FL, 'WSAI');
}
const int32 scaler = FixedMul(myRegs[IDX_S], 100 << 16) >> 16;
myCCB->scaleX = myRegs[IDX_W] < 0 ? -scaler : scaler;
myCCB->scaleY = scaler;
GetUpdateRectangle(myRegs[IDX_X] >> 16, myRegs[IDX_Y] >> 16, myCCB->source->xOffset, myCCB->source->yOffset,
myCCB->scaleX, myCCB->scaleY, myCCB->source->w, myCCB->source->h, myCCB->newLocation);
if (myCCB->flags & CCB_STREAM) {
if (!myCCB->maxArea) {
if ((myCCB->maxArea = (M4Rect *)mem_alloc(sizeof(M4Rect), "Rectangle")) == nullptr) {
error_show(FL, 'OOM!');
}
myCCB->maxArea->x1 = myCCB->newLocation->x1;
myCCB->maxArea->y1 = myCCB->newLocation->y1;
myCCB->maxArea->x2 = myCCB->newLocation->x2;
myCCB->maxArea->y2 = myCCB->newLocation->y2;
} else {
myCCB->maxArea->x1 = imath_min(myCCB->maxArea->x1, myCCB->newLocation->x1);
myCCB->maxArea->y1 = imath_min(myCCB->maxArea->y1, myCCB->newLocation->y1);
myCCB->maxArea->x2 = imath_max(myCCB->maxArea->x2, myCCB->newLocation->x2);
myCCB->maxArea->y2 = imath_max(myCCB->maxArea->y2, myCCB->newLocation->y2);
}
} else {
vmng_AddRectToRectList(&_GWS(deadRectList), myCCB->currLocation->x1, myCCB->currLocation->y1,
myCCB->currLocation->x2, myCCB->currLocation->y2);
}
myAnim8->flags &= ~(TAG_MAP_CEL | TAG_MOVE_CEL);
myCCB->layer = imath_max(0, myAnim8->myLayer);
myCCB->flags &= ~CCB_SKIP;
myCCB->flags |= CCB_REDRAW;
return;
}
void ws_OverrideCrunchTime(machine *m) {
if ((!m) || (!m->myAnim8)) {
return;
}
m->myAnim8->switchTime = 0;
}
} // End of namespace M4

View File

@@ -0,0 +1,72 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef M4_WSCRIPT_WS_HAL_H
#define M4_WSCRIPT_WS_HAL_H
#include "m4/wscript/ws_machine.h"
#include "m4/wscript/ws_cruncher.h"
namespace M4 {
#define CCB_SKIP 0x0001
#define CCB_HIDE 0x0002
#define CCB_REDRAW 0x0004
#define CCB_STREAM 0x0008
#define CCB_DISC_STREAM 0x0010
#define CCB_NO_DRAW (CCB_SKIP | CCB_HIDE)
#define ERR_INTERNAL 0
#define ERR_SEQU 1
#define ERR_MACH 2
struct WSHal_Globals {
RectList *_deadRectList = nullptr;
};
bool ws_InitHAL();
void ws_KillHAL();
void ws_DoDisplay(Buffer *background, int16 *depth_table, Buffer *screenCodeBuff,
uint8 *myPalette, uint8 *ICT, bool updateVideo);
void ws_hal_RefreshWoodscriptBuffer(cruncher *myCruncher, Buffer *background,
int16 *depth_table, Buffer *screenCodes, uint8 *myPalette, uint8 *ICT);
void GetBezCoeffs(frac16 *ctrlPoints, frac16 *coeffs);
void GetBezPoint(frac16 *x, frac16 *y, frac16 *coeffs, frac16 tVal);
bool InitCCB(CCB *myCCB);
void HideCCB(CCB *myCCB);
void ShowCCB(CCB *myCCB);
//void SetLastCCB(CCB *myCCB);
void MoveCCB(CCB *myCCB, frac16 deltaX, frac16 deltaY);
void KillCCB(CCB *myCCB, bool restoreFlag);
void Cel_msr(Anim8 *myAnim8);
void ws_OverrideCrunchTime(machine *m);
bool CheckAddr();
void ws_Error(machine *m, int32 errorType, quadchar errorCode, const char *errMsg);
void ws_DumpMachine(machine *m);
void ws_LogErrorMsg(const char *sourceFile, uint32 lineNum, const char *fmt, ...);
} // End of namespace M4
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,113 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef M4_WSCRIPT_WS_LOAD_H
#define M4_WSCRIPT_WS_LOAD_H
#include "m4/m4_types.h"
#include "m4/fileio/sys_file.h"
#include "m4/mem/reloc.h"
#include "m4/wscript/ws_machine.h"
namespace M4 {
#define _WS_ASSET_MACH 0
#define _WS_ASSET_SEQU 1
#define _WS_ASSET_CELS 2
#define _WS_ASSET_DATA 3
#define CHUNK_MACH 0x4D414348 //'MACH'
#define CHUNK_SEQU 0x53455155 //'SEQU'
#define CHUNK_DATA 0x44415441 //'DATA'
#define CHUNK_CELS 0x43454C53 //'CELS'
#define CHUNK_NECS 0x4E454353 //INTEL 'SCEN'
#define CHUNK_HCAM 0x4843414D //INTEL 'MACH'
#define CHUNK_UQES 0x55514553 //INTEL 'SEQU'
#define CHUNK_SLEC 0x534C4543 //INTEL 'CELS'
#define CHUNK_ATAD 0x41544144 //INTEL 'DATA'
#define MACH_NUM_STATES 0
#define MACH_OFFSETS 1
#define SEQU_NUM_VARS 0
#define SEQU_SEQU_START 1
#define DATA_REC_COUNT 0
#define DATA_REC_SIZE 1
#define DATA_REC_START 2
#define MAX_ASSET_HASH 255
struct WSLoad_Globals {
bool _wsloaderInitialized = false;
char **_globalMACHnames = nullptr;
char **_globalSEQUnames = nullptr;
char **_globalDATAnames = nullptr;
char **_globalCELSnames = nullptr;
MemHandle *_globalMACHHandles = nullptr;
int32 *_globalMACHoffsets = nullptr;
MemHandle *_globalSEQUHandles = nullptr;
int32 *_globalSEQUoffsets = nullptr;
MemHandle *_globalDATAHandles = nullptr;
int32 *_globalDATAoffsets = nullptr;
MemHandle *_globalCELSHandles = nullptr;
int32 *_globalCELSoffsets = nullptr;
int32 *_globalCELSPaloffsets = nullptr;
};
bool InitWSAssets();
bool ClearWSAssets(uint32 assetType, int32 minHash, int32 maxHash);
void ShutdownWSAssets();
bool LoadWSAssets(const char *wsAssetName);
bool LoadWSAssets(const char *wsAssetName, RGB8 *myPalette);
int32 AddWSAssetCELS(const char *wsAssetName, int32 hash, RGB8 *myPalette);
M4sprite *GetWSAssetSprite(char *spriteName, uint32 hash, uint32 index, M4sprite *mySprite, bool *streamSeries);
CCB *GetWSAssetCEL(uint32 hash, uint32 index, CCB *myCCB);
int32 GetWSAssetCELCount(uint32 hash);
int32 GetWSAssetCELFrameRate(uint32 hash);
int32 GetWSAssetCELPixSpeed(uint32 hash);
int32 ws_get_sprite_width(uint32 hash, int32 index);
int32 ws_get_sprite_height(uint32 hash, int32 index);
MemHandle ws_GetSEQU(uint32 hash, int32 *numLocalVars, int32 *offset);
MemHandle ws_GetMACH(uint32 hash, int32 *numStates, int32 *stateTableOffset, int32 *machInstrOffset);
MemHandle ws_GetDATA(uint32 hash, uint32 index, int32 *rowOffset);
int32 ws_GetDATACount(uint32 hash);
int32 GetSSHeaderInfo(Common::SeekableReadStream *stream, uint32 **data, RGB8 *myPalette);
bool ws_GetSSMaxWH(MemHandle ssHandle, int32 ssOffset, int32 *maxW, int32 *maxH);
// USING SPRITES WITHOUT GOING THROUGH THE WOODSCRIPT TREE
int32 LoadSpriteSeries(const char *assetName, MemHandle *seriesHandle, int32 *celsOffset, int32 *palOffset, RGB8 *myPalette);
int32 LoadSpriteSeriesDirect(const char *assetName, MemHandle *seriesHandle, int32 *celsOffset, int32 *palOffset, RGB8 *myPalette);
M4sprite *CreateSprite(MemHandle resourceHandle, int32 handleOffset, int32 index, M4sprite *mySprite, bool *streamSeries);
// WOODSCRIPT STREAMING API
bool ws_OpenSSstream(SysFile *streamFile, Anim8 *anim8);
bool ws_GetNextSSstreamCel(Anim8 *anim8);
void ws_CloseSSstream(CCB *myCCB);
} // End of namespace M4
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,245 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#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

View File

@@ -0,0 +1,135 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "m4/wscript/ws_timer.h"
#include "m4/vars.h"
namespace M4 {
static void dispose_timeRequest(onTimeReq *timeReq);
bool ws_InitWSTimer(void) {
_GWS(firstTimeReq) = nullptr;
return true;
}
void ws_KillTime() {
onTimeReq *tempTime = _GWS(firstTimeReq);
while (tempTime) {
_GWS(firstTimeReq) = _GWS(firstTimeReq)->next;
dispose_timeRequest(tempTime);
tempTime = _GWS(firstTimeReq);
}
}
static onTimeReq *new_timeRequest() {
return (onTimeReq *)mem_alloc(sizeof(onTimeReq), "onTimeReq");
}
static void dispose_timeRequest(onTimeReq *timeReq) {
if (timeReq) {
mem_free(timeReq);
}
}
void ws_MakeOnTimeReq(int32 wakeUpTime, machine *myXM, int32 pcOffset, int32 pcCount) {
// Create a new time request struct and set it's fields
onTimeReq *newTimeReq = new_timeRequest();
newTimeReq->myTime = wakeUpTime;
newTimeReq->myXM = myXM;
newTimeReq->pcOffset = pcOffset;
newTimeReq->pcCount = pcCount;
// Insert the new time req into the list in ascending order
// If the list is empty...
if (!_GWS(firstTimeReq)) {
newTimeReq->next = nullptr;
_GWS(firstTimeReq) = newTimeReq;
} else if (newTimeReq->myTime <= _GWS(firstTimeReq)->myTime) {
// Else if it belongs at the front of a non-empty list..
newTimeReq->next = _GWS(firstTimeReq);
_GWS(firstTimeReq) = newTimeReq;
} else {
// Else it belongs in the middle/end of a non-empty list...
onTimeReq *tempTimeReq = _GWS(firstTimeReq);
while (tempTimeReq->next && (tempTimeReq->next->myTime < newTimeReq->myTime)) {
tempTimeReq = tempTimeReq->next;
}
newTimeReq->next = tempTimeReq->next;
tempTimeReq->next = newTimeReq;
}
}
void ws_CancelOnTimeReqs(machine *m) {
if (!m)
return;
// Pass through the linked list, removing any requests for machine* m.
onTimeReq *prevTimeReq = _GWS(firstTimeReq);
onTimeReq *tempTimeReq = _GWS(firstTimeReq);
while (tempTimeReq) {
// If tempTimeReq is one to be cancelled...
if (tempTimeReq->myXM == m) {
// If req is first in the list
if (tempTimeReq == _GWS(firstTimeReq)) {
_GWS(firstTimeReq) = _GWS(firstTimeReq)->next;
prevTimeReq = _GWS(firstTimeReq);
dispose_timeRequest(tempTimeReq);
tempTimeReq = _GWS(firstTimeReq);
} else {
// Else prevTimeReq is the parent of tempTimeReq
prevTimeReq->next = tempTimeReq->next;
dispose_timeRequest(tempTimeReq);
tempTimeReq = prevTimeReq->next;
}
} else {
// Else check next req in list, maintain prevTimeReq is parent of tempTimeReq
if (prevTimeReq != tempTimeReq) {
prevTimeReq = prevTimeReq->next;
}
tempTimeReq = tempTimeReq->next;
}
}
}
void ws_CheckTimeReqs(int32 curTime) {
// Loop through the list, answering all expired time requests
onTimeReq *tempTimeReq = _GWS(firstTimeReq);
while (tempTimeReq && (tempTimeReq->myTime <= curTime)) {
// Extract all important information from request
machine *myXM = tempTimeReq->myXM;
int32 pcOffset = tempTimeReq->pcOffset;
int32 pcCount = tempTimeReq->pcCount;
// Remove it from the list and dispose
_GWS(firstTimeReq) = _GWS(firstTimeReq)->next;
dispose_timeRequest(tempTimeReq);
// Execute machine instructions for onTimeReq
ws_StepWhile(myXM, pcOffset, pcCount);
tempTimeReq = _GWS(firstTimeReq);
}
}
} // End of namespace M4

View File

@@ -0,0 +1,42 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef M4_WSCRIPT_WS_TIMER_H
#define M4_WSCRIPT_WS_TIMER_H
#include "m4/wscript/ws_machine.h"
namespace M4 {
struct WSTimer_Globals {
onTimeReq *_firstTimeReq = nullptr;
};
bool ws_InitWSTimer(void);
void ws_KillTime(void);
void ws_MakeOnTimeReq(int32 wakeUpTime, machine *myXM, int32 pcOffset, int32 pcCount);
void ws_CancelOnTimeReqs(machine *m);
void ws_CheckTimeReqs(int32 curTime);
} // End of namespace M4
#endif

View File

@@ -0,0 +1,33 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef M4_WSCRIPT_WS_UNIV_H
#define M4_WSCRIPT_WS_UNIV_H
#include "m4/m4_types.h"
namespace M4 {
} // End of namespace M4
#endif

View File

@@ -0,0 +1,26 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "m4/wscript/wscript.h"
namespace M4 {
} // End of namespace M4

View File

@@ -0,0 +1,40 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef M4_WSCRIPT_WS_SCRIPT_H
#define M4_WSCRIPT_WS_SCRIPT_H
#include "m4/wscript/ws_cruncher.h"
#include "m4/wscript/ws_hal.h"
#include "m4/wscript/ws_load.h"
#include "m4/wscript/ws_machine.h"
#include "m4/wscript/ws_timer.h"
namespace M4 {
struct WS_Globals : public WSCruncher_Globals, public WSHal_Globals,
public WSLoad_Globals, public WSMachine_Globals, public WSTimer_Globals {
};
} // End of namespace M4
#endif

View File

@@ -0,0 +1,122 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "m4/wscript/wst_regs.h"
namespace M4 {
const char *myRegLabels[IDX_COUNT] = {
"timer", //0
"tag", //1
"layer", //2
"w", //3
"h", //4
"x", //5
"y", //6
"s", //7
"r", //8
"cels_hash", //9
"cels_index", //10
"cels_count", //11
"cels_frame_rate", //12
"cels_pix_speed", //13
"targ_s", //14
"targ_r", //15
"targ_x", //16
"targ_y", //17
"delta_s", //18
"delta_r", //19
"delta_x", //20
"delta_y", //21
"velocity", //22
"theta", //23
"ztemp1", //24
"ztemp2", //25
"ztemp3", //26
"ztemp4", //27
"ztemp5", //28
"ztemp6", //29
"ztemp7", //30
"ztemp8", //31
"mach_id" //32
};
const char *myGlobLabels[GLOB_COUNT] = {
"***SYSTEM - TIME",
"***SYSTEM - WATCHDOG",
"min_y",
"max_y",
"min_scale",
"max_scale",
"scaler",
"g_temp1",
"g_temp2",
"g_temp3",
"g_temp4",
"g_temp5",
"g_temp6",
"g_temp7",
"g_temp8",
"g_temp9",
"g_temp10",
"g_temp11",
"g_temp12",
"g_temp13",
"g_temp14",
"g_temp15",
"g_temp16",
"g_temp17",
"g_temp18",
"g_temp19",
"g_temp20",
"g_temp21",
"g_temp22",
"g_temp23",
"g_temp24",
"g_temp25",
"g_temp26",
"g_temp27",
"g_temp28",
"g_temp29",
"g_temp30",
"g_temp31",
"g_temp32",
};
const char *tagLabels[TAG_COUNT] = {
"tag_none",
"tag_targs",
"tag_bez",
"tag_deltas",
"tag_vectors",
"tag_text",
"tag_move_cel",
"tag_map_cel"
};
} // End of namespace M4

View File

@@ -0,0 +1,94 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef M4_WSCRIPT_WST_REGS_H
#define M4_WSCRIPT_WST_REGS_H
namespace M4 {
enum {
IDX_TIMER = 0,
IDX_TAG = 1,
IDX_LAYER = 2,
IDX_W = 3,
IDX_H = 4,
IDX_X = 5,
IDX_Y = 6,
IDX_S = 7,
IDX_R = 8,
IDX_CELS_HASH = 9,
IDX_CELS_INDEX = 10,
IDX_CELS_COUNT = 11,
IDX_CELS_FRAME_RATE = 12,
IDX_CELS_PIX_SPEED = 13,
IDX_TARG_S = 14,
IDX_TARG_R = 15,
IDX_TARG_X = 16,
IDX_TARG_Y = 17,
IDX_DELTA_S = 18,
IDX_DELTA_R = 19,
IDX_DELTA_X = 20,
IDX_DELTA_Y = 21,
IDX_VELOCITY = 22,
IDX_THETA = 23,
IDX_ZTEMP1 = 24,
IDX_ZTEMP2 = 25,
IDX_ZTEMP3 = 26,
IDX_ZTEMP4 = 27,
IDX_ZTEMP5 = 28,
IDX_ZTEMP6 = 29,
IDX_ZTEMP7 = 30,
IDX_ZTEMP8 = 31,
IDX_MACH_ID = 32
};
#define IDX_COUNT 33
#define IDX_BEZ_CTRL IDX_TARG_X
#define IDX_BEZ_COEFF IDX_ZTEMP1
#define TAG_COUNT 8
#define TAG_NONE 0x00000000
#define TAG_TARGS 0x00000001
#define TAG_BEZ 0x00000002
#define TAG_DELTAS 0x00000004
#define TAG_VECTORS 0x00000008
#define TAG_TEXT 0x00000010
#define TAG_MOVE_CEL 0x00004000
#define TAG_MAP_CEL 0x00002000
#define GLOB_COUNT 39
extern const char *myRegLabels[];
extern const char *myGlobLabels[];
extern const char *tagLabels[];
} // End of namespace M4
#endif