mirror of
https://github.com/libretro/scummvm.git
synced 2025-03-04 01:07:22 +00:00
M4: Implementing lots of wscript and dependencies
Oh, soooo many dependencies.
This commit is contained in:
parent
f9490f9b91
commit
fd4e2883b1
@ -50,4 +50,14 @@ void player_set_commands_allowed(bool t_or_f) {
|
||||
}
|
||||
}
|
||||
|
||||
void game_pause(bool flag) {
|
||||
if (flag) {
|
||||
_G(kernel).pause = true;
|
||||
PauseEngines();
|
||||
} else {
|
||||
_G(kernel).pause = false;
|
||||
UnpauseEngines();
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace M4
|
||||
|
@ -30,6 +30,7 @@ namespace M4 {
|
||||
|
||||
extern bool kernel_section_startup();
|
||||
extern void player_set_commands_allowed(bool t_or_f);
|
||||
extern void game_pause(bool flag);
|
||||
|
||||
} // End of namespace M4
|
||||
|
||||
|
@ -19,12 +19,16 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/str.h"
|
||||
#include "common/file.h"
|
||||
#include "common/textconsole.h"
|
||||
#include "m4/core/errors.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
inline static bool quadchar_equals_string(uint32 code, const Common::String &str) {
|
||||
return READ_BE_UINT32(str.c_str()) == code;
|
||||
}
|
||||
|
||||
void error_show(const char *filename, uint32 line, quadchar errorcode, const char *fmt, ...) {
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
@ -38,4 +42,33 @@ void error_show(const char *filename, uint32 line, quadchar errorcode) {
|
||||
error_show(filename, line, errorcode, "No extra description");
|
||||
}
|
||||
|
||||
void error_look_up(quadchar errorcode, char *result_string) {
|
||||
Common::File f;
|
||||
*result_string = '\0';
|
||||
|
||||
if (!f.open(ERROR_FILE))
|
||||
return;
|
||||
|
||||
Common::String buffer;
|
||||
|
||||
while (!f.eos()) {
|
||||
buffer = f.readString();
|
||||
const char *mark = buffer.c_str() + 1;
|
||||
|
||||
if (quadchar_equals_string(errorcode, buffer) || quadchar_equals_string(errorcode, mark)) {
|
||||
const char *src = (const char *)buffer.c_str() + 5;
|
||||
int16 count = 0;
|
||||
|
||||
do {
|
||||
*result_string++ = *src;
|
||||
++count;
|
||||
} while (*src++ && (count < MAX_STRING_LEN));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace M4
|
||||
|
@ -27,9 +27,11 @@
|
||||
namespace M4 {
|
||||
|
||||
#define FL __FILE__,__LINE__
|
||||
#define ERROR_FILE "error.m4"
|
||||
|
||||
extern void error_show(const char *filename, uint32 line, quadchar errorcode, const char *fmt, ...);
|
||||
extern void error_show(const char *filename, uint32 line, quadchar errorcode);
|
||||
extern void error_look_up(quadchar errorcode, char *result_string);
|
||||
|
||||
} // namespace M4
|
||||
|
||||
|
@ -76,7 +76,6 @@ enum {
|
||||
};
|
||||
|
||||
constexpr int GLB_SHARED_VARS = 256;
|
||||
constexpr int GLOB_COUNT = 39;
|
||||
|
||||
struct GlobalVars : public Common::Array<int32> {
|
||||
void syncGame(Common::Serializer &s);
|
||||
|
@ -117,6 +117,21 @@ frac16 SqrtF16(frac16 n) {
|
||||
return (frac16)r;
|
||||
}
|
||||
|
||||
#define DIV_128_PI 0x28be61
|
||||
|
||||
frac16 ArcTan(frac16 x, frac16 y) {
|
||||
double floatX, floatY, result;
|
||||
frac16 fracResult;
|
||||
|
||||
floatX = (float)(x >> 16) + (float)((float)(x & 0xffff) / (float)65536);
|
||||
floatY = (float)(y >> 16) + (float)((float)(y & 0xffff) / (float)65536);
|
||||
result = atan2(floatY, floatX);
|
||||
fracResult = (((int32)(floor(result))) << 16) + (int32)(floor((result - floor(result)) * 65536));
|
||||
fracResult = MulSF16(fracResult, DIV_128_PI);
|
||||
if (fracResult < 0) fracResult += 0x1000000;
|
||||
return fracResult;
|
||||
}
|
||||
|
||||
uint16 HighWord(uint32 n) {
|
||||
return (uint16)(n >> 16);
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ frac16 imath_ranged_rand16(frac16 a, frac16 b);
|
||||
|
||||
frac16 dist2d(int32 x1, int32 y1, int32 x2, int32 y2);
|
||||
frac16 SqrtF16(frac16 n);
|
||||
//frac16 ArcTan(frac16 x, frac16 y);
|
||||
frac16 ArcTan(frac16 x, frac16 y);
|
||||
|
||||
uint16 HighWord(uint32 n);
|
||||
uint16 LowWord(uint32 n);
|
||||
|
51
engines/m4/dbg/dbg_defs.h
Normal file
51
engines/m4/dbg/dbg_defs.h
Normal file
@ -0,0 +1,51 @@
|
||||
/* 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_DBG_DBG_DEFS_H
|
||||
#define M4_DBG_DBG_DEFS_H
|
||||
|
||||
#include "m4/m4_types.h"
|
||||
#include "m4/dbg/dbg_defs.h"
|
||||
#include "m4/gui/gui_dialog.h"
|
||||
#include "m4/wscript/ws_machine.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
struct DBGSequSR {
|
||||
DBGSequSR *next;
|
||||
int32 prevSequHash;
|
||||
int32 returnOffset;
|
||||
};
|
||||
|
||||
struct DBGWatch {
|
||||
DBGWatch *next;
|
||||
DBGWatch *prev;
|
||||
machine *m;
|
||||
Dialog *d;
|
||||
bool moreInfo;
|
||||
bool machStep;
|
||||
int32 sequHash;
|
||||
bool sequStep;
|
||||
};
|
||||
|
||||
} // namespace M4
|
||||
|
||||
#endif
|
67
engines/m4/dbg/dbg_wscript.cpp
Normal file
67
engines/m4/dbg/dbg_wscript.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
/* 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/dbg/dbg_wscript.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
bool dbg_ws_init(bool showTheScreen, Font *useThisFont, frac16 *theGlobals) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void dbg_ws_shutdown() {
|
||||
// No implementation
|
||||
}
|
||||
|
||||
void dbg_ws_update() {
|
||||
// No implementation
|
||||
}
|
||||
|
||||
void dbg_LaunchSequence(Anim8 *myAnim8) {
|
||||
// No implementation
|
||||
}
|
||||
|
||||
void dbg_DebugWSMach(machine *m, bool debug) {
|
||||
// No implementation
|
||||
}
|
||||
|
||||
void dbg_DebugNextCycle() {
|
||||
// No implementation
|
||||
}
|
||||
|
||||
void dbg_RemoveWSMach(machine *m) {
|
||||
// No implementation
|
||||
}
|
||||
|
||||
void dbg_SetCurrMachInstr(machine *m, int32 pcOffset) {
|
||||
// No implementation
|
||||
}
|
||||
|
||||
void dbg_SetCurrSequInstr(Anim8 *myAnim8, int32 compareCCR) {
|
||||
// No implementation
|
||||
}
|
||||
|
||||
void dbg_WSError(Common::WriteStream *logFile, machine *m, int32 errorType,
|
||||
const char *errDesc, const char *errMsg, int32 pcOffset) {
|
||||
// No implementation
|
||||
}
|
||||
|
||||
} // namespace M4
|
48
engines/m4/dbg/dbg_wscript.h
Normal file
48
engines/m4/dbg/dbg_wscript.h
Normal file
@ -0,0 +1,48 @@
|
||||
/* 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_DBG_DBG_WSCRIPT_H
|
||||
#define M4_DBG_DBG_WSCRIPT_H
|
||||
|
||||
#include "common/stream.h"
|
||||
#include "m4/m4_types.h"
|
||||
#include "m4/dbg/dbg_defs.h"
|
||||
#include "m4/graphics/gr_font.h"
|
||||
#include "m4/wscript/ws_machine.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
extern bool dbg_ws_init(bool showTheScreen, Font *useThisFont, frac16 *theGlobals);
|
||||
extern void dbg_ws_shutdown();
|
||||
extern void dbg_ws_update();
|
||||
|
||||
extern void dbg_LaunchSequence(Anim8 *myAnim8);
|
||||
extern void dbg_DebugWSMach(machine *m, bool debug);
|
||||
extern void dbg_DebugNextCycle();
|
||||
extern void dbg_RemoveWSMach(machine *m);
|
||||
extern void dbg_SetCurrMachInstr(machine *m, int32 pcOffset);
|
||||
extern void dbg_SetCurrSequInstr(Anim8 *myAnim8, int32 compareCCR);
|
||||
extern void dbg_WSError(Common::WriteStream *logFile, machine *m, int32 errorType,
|
||||
const char *errDesc, const char *errMsg, int32 pcOffset);
|
||||
|
||||
} // namespace M4
|
||||
|
||||
#endif
|
27
engines/m4/dbg/debug.h
Normal file
27
engines/m4/dbg/debug.h
Normal file
@ -0,0 +1,27 @@
|
||||
/* 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_DBG_DEBUG_H
|
||||
#define M4_DBG_DEBUG_H
|
||||
|
||||
#include "m4/dbg/dbg_wscript.h"
|
||||
|
||||
#endif
|
@ -20,15 +20,13 @@
|
||||
*/
|
||||
|
||||
#include "m4/fileio/fstream.h"
|
||||
#include "m4/core/errors.h"
|
||||
#include "m4/core/imath.h"
|
||||
#include "m4/vars.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
bool f_stream_Init() {
|
||||
_G(firstStream) = nullptr;
|
||||
_G(lastStream) = nullptr;
|
||||
return true;
|
||||
}
|
||||
#define STR_STRMREQ "stream request"
|
||||
|
||||
StreamFile::StreamFile(const Common::String &filename) {
|
||||
if (!_file.open(filename))
|
||||
@ -43,7 +41,7 @@ bool StreamFile::seek(uint32 n) {
|
||||
return _file.seek(n);
|
||||
}
|
||||
|
||||
bool StreamFile::seek_ahead(uint32 n) {
|
||||
bool StreamFile::seek_ahead(int32 n) {
|
||||
return _file.skip(n);
|
||||
}
|
||||
|
||||
@ -51,4 +49,537 @@ uint32 StreamFile::get_pos() {
|
||||
return _file.pos();
|
||||
}
|
||||
|
||||
bool f_stream_Init() {
|
||||
_G(firstStream) = nullptr;
|
||||
_G(lastStream) = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
void f_stream_Shutdown(void) {
|
||||
strmRequest *myStream;
|
||||
|
||||
// Loop through the list, closing all stream requests, which also deallocs the request
|
||||
myStream = _G(firstStream);
|
||||
while (myStream) {
|
||||
_G(firstStream) = _G(firstStream)->next;
|
||||
f_stream_Close(myStream);
|
||||
myStream = _G(firstStream);
|
||||
}
|
||||
}
|
||||
|
||||
strmRequest *f_stream_Open(StreamFile *srcFile, int32 fileOffset, int32 strmMinBuffSize, int32 strmBuffSize,
|
||||
int32 numBlocksToRead, int32 *blockSizeArray, int32 initialRead, bool wrapStream) {
|
||||
|
||||
strmRequest *newStream;
|
||||
int32 bytesRead, i, bytesToRead;
|
||||
bool finished;
|
||||
void *bufferHandle;
|
||||
int32 memAvail;
|
||||
|
||||
const int32 PADDING = 256;
|
||||
|
||||
// Parameter verification
|
||||
if (!srcFile) {
|
||||
error_show(FL, 'FSF!');
|
||||
}
|
||||
|
||||
if (strmMinBuffSize < 0) {
|
||||
error_show(FL, 'FSF1', "neg min buffsize: %ld", strmMinBuffSize);
|
||||
}
|
||||
|
||||
// Allocate a new stream request struct
|
||||
if ((newStream = (strmRequest *)mem_alloc(sizeof(strmRequest), STR_STRMREQ)) == nullptr) {
|
||||
error_show(FL, 'OOM!', "%ld", sizeof(strmRequest));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Try to get memory
|
||||
newStream->strmHandle = NewHandle(strmBuffSize, "stream buff");
|
||||
if (newStream->strmHandle) {
|
||||
goto got_mem;
|
||||
}
|
||||
|
||||
// Maximize available memory
|
||||
MaxMem((Size *)&memAvail); // param on PC is max mem avail in one block
|
||||
|
||||
// try to get requested size
|
||||
if (memAvail >= strmBuffSize) {
|
||||
/*
|
||||
if ((newStream->strmBuff = (uint8*)mem_alloc(strmBuffSize, STR_STRMBUFF)) != nullptr) {
|
||||
goto got_mem;
|
||||
}
|
||||
*/
|
||||
// try to get memory
|
||||
newStream->strmHandle = NewHandle(strmBuffSize, "stream buff");
|
||||
if (newStream->strmHandle) {
|
||||
goto got_mem;
|
||||
}
|
||||
}
|
||||
|
||||
// try to get what's left if it's enough
|
||||
// get a compromise between free and requested.
|
||||
// if we get it all, system gets unstable...
|
||||
if (memAvail > strmMinBuffSize) {
|
||||
int32 alloc_me = ((memAvail - strmMinBuffSize) / 2) + strmMinBuffSize;
|
||||
/*
|
||||
if ((newStream->strmBuff = (uint8*)mem_alloc(alloc_me, STR_STRMBUFF)) != nullptr) {
|
||||
strmBuffSize = alloc_me;
|
||||
goto got_mem;
|
||||
}
|
||||
*/
|
||||
// try to get memory
|
||||
newStream->strmHandle = NewHandle(alloc_me, "stream buff");
|
||||
if (newStream->strmHandle) {
|
||||
strmBuffSize = alloc_me;
|
||||
goto got_mem;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// sorry, bud.
|
||||
error_show(FL, 'FSOM', "want: %ld, have: %ld", strmMinBuffSize, memAvail);
|
||||
|
||||
got_mem:
|
||||
//lock the buffer - to be locked until the stream is closed
|
||||
HLock(newStream->strmHandle);
|
||||
newStream->strmBuff = (uint8 *) * (newStream->strmHandle);
|
||||
|
||||
// Initialize the stream request
|
||||
newStream->strmSize = strmBuffSize;
|
||||
newStream->strmHead = newStream->strmBuff;
|
||||
newStream->strmTail = newStream->strmBuff;
|
||||
newStream->endStrmBuff = newStream->strmBuff + strmBuffSize;
|
||||
newStream->strmWrap = newStream->endStrmBuff;
|
||||
newStream->strmLastRead = newStream->endStrmBuff;
|
||||
newStream->numBlocksToRead = numBlocksToRead;
|
||||
newStream->blockSizeArray = blockSizeArray;
|
||||
newStream->wrapStream = wrapStream;
|
||||
newStream->srcFile = srcFile;
|
||||
|
||||
// If the streaming should begin part way into the file, seek to the beginning of where to start streaming
|
||||
if (fileOffset > 0) {
|
||||
// If (fseek(newStream->srcFile, fileOffset, SEEK_SET) != 0) {
|
||||
if (!newStream->srcFile->seek(fileOffset)) {
|
||||
delete newStream->srcFile;
|
||||
mem_free(newStream);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we are to initially read the stream
|
||||
if (initialRead > 0) {
|
||||
|
||||
// If the blockSizeArray exists, then initialRead is the number of blocks to read
|
||||
if (newStream->blockSizeArray) {
|
||||
// Calculate the total number of bytes to read in initially
|
||||
initialRead = (int32)imath_min(initialRead, numBlocksToRead);
|
||||
finished = false;
|
||||
bytesToRead = 0;
|
||||
i = 0;
|
||||
while ((i < initialRead) && (!finished)) {
|
||||
if ((bytesToRead + blockSizeArray[i]) <= strmBuffSize) {
|
||||
bytesToRead += blockSizeArray[i];
|
||||
i++;
|
||||
} else {
|
||||
finished = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Update the blockSizeArray, and numBlocksToRead entries. We plan to read in "i" blocks so far.
|
||||
newStream->numBlocksToRead -= i;
|
||||
newStream->blockSizeArray += i;
|
||||
}
|
||||
|
||||
// Else the initialRead refers to the number of bytes to initially read
|
||||
else {
|
||||
|
||||
//bounds check the initialRead and set the nextReadSize field
|
||||
bytesToRead = (int32)imath_min(initialRead, strmBuffSize);
|
||||
newStream->nextReadSize = bytesToRead;
|
||||
}
|
||||
|
||||
// Make sure we still have something to read
|
||||
if (bytesToRead > 0) {
|
||||
|
||||
// Read in the initial bytes to read
|
||||
//bytesRead = fread((void*)newStream->strmHead, 1, bytesToRead, newStream->srcFile);
|
||||
bufferHandle = newStream->strmHead;
|
||||
bytesRead = newStream->srcFile->read((Handle)&bufferHandle, bytesToRead);
|
||||
|
||||
//did we actually read that many? If not, close the file
|
||||
if (bytesRead < bytesToRead) {
|
||||
delete newStream->srcFile;
|
||||
newStream->srcFile = nullptr;
|
||||
}
|
||||
|
||||
// Update the strmHead pointer
|
||||
newStream->strmHead += bytesRead;
|
||||
}
|
||||
}
|
||||
|
||||
//link the stream request into the list of requests
|
||||
newStream->prev = nullptr;
|
||||
newStream->next = _G(firstStream);
|
||||
if (_G(firstStream)) {
|
||||
_G(firstStream)->prev = newStream;
|
||||
} else {
|
||||
_G(lastStream) = newStream;
|
||||
}
|
||||
_G(firstStream) = newStream;
|
||||
|
||||
// Return the stream request
|
||||
return newStream;
|
||||
}
|
||||
|
||||
|
||||
static bool UnwrapStream(strmRequest *myStream) {
|
||||
int32 bytesToMove = 0, bytesAvail;
|
||||
uint8 *tempBuff;
|
||||
|
||||
// Using tempBuff as a flag to determine whether data needs to be temporarily stored
|
||||
tempBuff = nullptr;
|
||||
|
||||
// Since strmTail is never allowed to be equal to strmWrap if it is > strmHead, there must be a
|
||||
// Non-zero amount of data at the end which we must move.
|
||||
//Therefore, we may have to temporarily store anything at the beginning of the buffer
|
||||
if (myStream->strmHead > myStream->strmBuff) {
|
||||
|
||||
// Calculate how many bytes to store and copy to a temporary buffer
|
||||
bytesToMove = (int32)myStream->strmHead - (int32)myStream->strmBuff;
|
||||
|
||||
if ((tempBuff = (uint8 *)mem_alloc(bytesToMove, "stream temp buff")) == nullptr)
|
||||
error_show(FL, 'OOM!', "UnwrapStream() failed - temp buff avail: %ld", bytesToMove);
|
||||
|
||||
memcpy(tempBuff, myStream->strmBuff, bytesToMove);
|
||||
}
|
||||
|
||||
// Move the data at the end of the buffer to the beginning and reset the strmWrap pointer
|
||||
bytesAvail = (int32)myStream->strmWrap - (int32)myStream->strmTail;
|
||||
memmove(myStream->strmBuff, myStream->strmTail, bytesAvail);
|
||||
myStream->strmTail = myStream->strmBuff;
|
||||
myStream->strmHead = (uint8 *)((int32)(myStream->strmTail) + bytesAvail);
|
||||
myStream->strmWrap = myStream->endStrmBuff;
|
||||
|
||||
// Now check if we temporarily store data. if so, copy it back to the stream and turf the temp buffer
|
||||
if (tempBuff) {
|
||||
memcpy(myStream->strmHead, tempBuff, bytesToMove);
|
||||
myStream->strmHead += bytesToMove;
|
||||
mem_free(tempBuff);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void f_stream_DumpPreviouslyRead(strmRequest *myStream) {
|
||||
// This is used to allow the f_stream_Process() function to overwrite the stream buffer space where
|
||||
// the previously read data was stored. ie. If you call f_stream_Read(), and then make a copy,
|
||||
// you wouldn't care if the data in the stream buffer was overwritten, so call this procedure.
|
||||
if (myStream) {
|
||||
myStream->strmLastRead = myStream->strmTail;
|
||||
if (myStream->strmTail == myStream->strmHead) {
|
||||
myStream->strmTail = myStream->strmBuff;
|
||||
myStream->strmHead = myStream->strmBuff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int32 f_stream_Read(strmRequest *myStream, uint8 **dest, int32 numBytes) {
|
||||
int32 bytesAvail, bytesNeeded, bytesRead;
|
||||
void *bufferHandle;
|
||||
|
||||
// Parameter verification
|
||||
if (!myStream)
|
||||
error_show(FL, 'FSIS', "f_stream_Read() failed - invalid stream request");
|
||||
|
||||
if ((numBytes <= 0) || (numBytes >= myStream->strmSize))
|
||||
error_show(FL, 'FSR!', "%ld stream size %ld", numBytes, myStream->strmSize);
|
||||
|
||||
// If the stream tail is > the stream head, and the number of bytes at the end of the buffer is < numBytes
|
||||
// we must unwrap the stream, moving the data at the end of the buffer to the beginning, and slide the beginning down
|
||||
if ((myStream->strmTail > myStream->strmHead) && (((int32)myStream->strmWrap - (int32)myStream->strmTail) < numBytes)) {
|
||||
UnwrapStream(myStream);
|
||||
}
|
||||
|
||||
// Now either the strmHead is >= the strmTail, or there is enough data at the end of the buffer to fulfill numBytes
|
||||
|
||||
// Calculate the number of bytes available
|
||||
if (myStream->strmTail <= myStream->strmHead) {
|
||||
bytesAvail = (int32)(myStream->strmHead - myStream->strmTail);
|
||||
} else {
|
||||
// No extra data is available at the beginning of the stream buffer, since we "unwrapped" the stream
|
||||
bytesAvail = (int32)(myStream->strmWrap - myStream->strmTail);
|
||||
}
|
||||
|
||||
// Now check and see if we have enough bytes available
|
||||
if (bytesAvail >= numBytes) {
|
||||
// Set the destination pointer
|
||||
*dest = (uint8 *)myStream->strmTail;
|
||||
myStream->strmLastRead = myStream->strmTail;
|
||||
|
||||
// Update the strmTail pointer
|
||||
myStream->strmTail += numBytes;
|
||||
|
||||
// If there is no data left at the end of the stream buffer, reset the strmTail and strmWrap pointers
|
||||
if (myStream->strmTail == myStream->strmWrap) {
|
||||
myStream->strmTail = myStream->strmBuff;
|
||||
myStream->strmWrap = myStream->endStrmBuff;
|
||||
}
|
||||
|
||||
return numBytes;
|
||||
} else {
|
||||
// Else we will have to read more data from disc
|
||||
// If this has happened, since we "unwrapped" the stream buff, we can guarantee that strmTail < strmHead
|
||||
|
||||
// Calculate how much more must be read in
|
||||
bytesNeeded = numBytes - bytesAvail;
|
||||
|
||||
// Make sure we have enough room at the end of the buffer to accommodate
|
||||
if ((int32)(myStream->endStrmBuff - myStream->strmHead) < bytesNeeded) {
|
||||
// We need to memmove the contents of the stream to the beginning of the buff to allow
|
||||
// F_stream_read() to return a pointer to a contiguous block
|
||||
|
||||
// Move the data to the beginning of the stream buffer, and reset the head and tail pointers
|
||||
memmove((void *)myStream->strmBuff, myStream->strmTail, bytesAvail);
|
||||
myStream->strmTail = myStream->strmBuff;
|
||||
myStream->strmHead = (uint8 *)((int32)myStream->strmTail + bytesAvail);
|
||||
}
|
||||
|
||||
// If the client is using a blockSizeArray, hopefully bytesNeeded will be equal to the next blockSize
|
||||
if (myStream->blockSizeArray && (*myStream->blockSizeArray == bytesNeeded) && (myStream->numBlocksToRead > 0)) {
|
||||
myStream->blockSizeArray++;
|
||||
myStream->numBlocksToRead--;
|
||||
} else {
|
||||
// Otherwise we just trashed the whole point of using a calculated blockSizeArray
|
||||
myStream->blockSizeArray = nullptr;
|
||||
myStream->numBlocksToRead = -1;
|
||||
myStream->nextReadSize = numBytes;
|
||||
}
|
||||
|
||||
// Read in the bytesNeeded
|
||||
bufferHandle = myStream->strmHead;
|
||||
bytesRead = myStream->srcFile->read((Handle)&bufferHandle, bytesNeeded);
|
||||
|
||||
if (bytesRead < bytesNeeded) {
|
||||
// If we could not read that much in, close the srcFile
|
||||
delete myStream->srcFile;
|
||||
myStream->srcFile = nullptr;
|
||||
}
|
||||
|
||||
// Set the destination pointer and update the stream pointers
|
||||
*dest = (uint8 *)myStream->strmTail;
|
||||
myStream->strmLastRead = myStream->strmTail;
|
||||
myStream->strmHead += bytesRead;
|
||||
myStream->strmTail = myStream->strmHead;
|
||||
|
||||
// Return the number of bytes successfully available
|
||||
return (bytesRead + bytesAvail);
|
||||
}
|
||||
}
|
||||
|
||||
void f_stream_Close(strmRequest *myStream) {
|
||||
// Parameter verification
|
||||
if (!myStream) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Close the stream and throw out the stream buffer
|
||||
if (myStream->srcFile) {
|
||||
delete myStream->srcFile;
|
||||
}
|
||||
|
||||
// Kill the stream buffer
|
||||
HUnLock(myStream->strmHandle);
|
||||
DisposeHandle(myStream->strmHandle);
|
||||
myStream->strmBuff = nullptr;
|
||||
|
||||
|
||||
// Remove the stream request from the list of requests
|
||||
if (myStream->next) {
|
||||
myStream->next->prev = myStream->prev;
|
||||
} else {
|
||||
_G(lastStream) = myStream->prev;
|
||||
}
|
||||
if (myStream->prev) {
|
||||
myStream->prev->next = myStream->next;
|
||||
} else {
|
||||
_G(firstStream) = myStream->next;
|
||||
}
|
||||
|
||||
// Final, turf the stream request
|
||||
mem_free(myStream);
|
||||
}
|
||||
|
||||
void f_stream_Process(int32 numToProcess) {
|
||||
strmRequest *myStream, *firstProcessStream;
|
||||
int32 buffEndBytesAvail = 0, buffStartBytesAvail = 0;
|
||||
int32 bytesRead, bytesAvail, nextReadSize;
|
||||
bool buffWrap, useBlockSizeArray;
|
||||
void *bufferHandle;
|
||||
|
||||
// No sense wasting time if there are no stream requests to process
|
||||
if (!_G(firstStream)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Loop through until either the end of the list of requests, or we've serviced the "numToProcess"
|
||||
firstProcessStream = _G(firstStream);
|
||||
myStream = _G(firstStream);
|
||||
while (myStream && (numToProcess > 0)) {
|
||||
|
||||
// Make sure we still have an open srcFile
|
||||
if (myStream->srcFile && (myStream->numBlocksToRead != 0)) {
|
||||
buffWrap = false;
|
||||
useBlockSizeArray = false;
|
||||
|
||||
// Calculate the amount of empty space in the stream buff
|
||||
// If all the empty space in the stream buff is between the head and the lastRead...
|
||||
if (myStream->strmLastRead >= myStream->strmHead) {
|
||||
bytesAvail = (int32)myStream->strmLastRead - (int32)myStream->strmHead;
|
||||
|
||||
// strmTail and strmHead can never equal unless the buffer is completely empty, therefore,
|
||||
// make sure the amout of bytes available won't cause strmHead to become equal to strmTail
|
||||
if ((bytesAvail > 0) && (myStream->strmLastRead == myStream->strmTail)) {
|
||||
bytesAvail--;
|
||||
}
|
||||
} else {
|
||||
// Else all the empty space is wrapped around the end of the buffer
|
||||
buffWrap = true;
|
||||
|
||||
// Calculate how much space is available at the start and at the end of the buffer
|
||||
buffEndBytesAvail = (int32)myStream->endStrmBuff - (int32)myStream->strmHead;
|
||||
buffStartBytesAvail = (int32)myStream->strmLastRead - (int32)myStream->strmBuff;
|
||||
|
||||
// As above, ensure strmHead won't become equal to strmTail
|
||||
if ((buffStartBytesAvail > 0) && (myStream->strmLastRead == myStream->strmTail)) {
|
||||
buffStartBytesAvail--;
|
||||
}
|
||||
|
||||
// Calculate the total bytes available
|
||||
bytesAvail = buffEndBytesAvail + buffStartBytesAvail;
|
||||
}
|
||||
|
||||
// Now find the number of bytes to read - either from the blockSizeArray...
|
||||
if (myStream->blockSizeArray) {
|
||||
useBlockSizeArray = true;
|
||||
nextReadSize = *myStream->blockSizeArray;
|
||||
} else {
|
||||
// ...or directly from the nextReadSize field of the stream request
|
||||
nextReadSize = myStream->nextReadSize;
|
||||
}
|
||||
|
||||
// See if we can simply read the next chunk into the strmHead, without worrying about "wrapping" the buffer
|
||||
if ((buffWrap && (buffEndBytesAvail >= nextReadSize)) ||
|
||||
((!buffWrap) && (bytesAvail >= nextReadSize))) {
|
||||
// Read the bytes into the stream buffer
|
||||
bufferHandle = myStream->strmHead;
|
||||
bytesRead = myStream->srcFile->read((Handle)&bufferHandle, nextReadSize);
|
||||
|
||||
// If we could not read that much in, close the srcFile
|
||||
if (bytesRead < nextReadSize) {
|
||||
delete myStream->srcFile;
|
||||
myStream->srcFile = nullptr;
|
||||
}
|
||||
|
||||
// Update the stream head
|
||||
myStream->strmHead += bytesRead;
|
||||
|
||||
// Update the blockSizeArray pointer if necessary
|
||||
if (useBlockSizeArray) {
|
||||
myStream->blockSizeArray++;
|
||||
myStream->numBlocksToRead--;
|
||||
}
|
||||
} else if (buffWrap) {
|
||||
// Else if the empty space is wrapped, we may still be able to store the next data chunk, otherwise no more room
|
||||
|
||||
// See if we can wrap the next data chunk around
|
||||
if (!myStream->wrapStream) {
|
||||
|
||||
// No wrapping allowed, so do we have room for it at the beginning of the stream
|
||||
if (buffStartBytesAvail >= nextReadSize) {
|
||||
|
||||
//we can read it in at the beginning, so set the strmWrap pointer
|
||||
myStream->strmWrap = myStream->strmHead;
|
||||
|
||||
// Read the bytes into the stream buffer
|
||||
//bytesRead = (int32)fread((void*)myStream->strmBuff, 1, nextReadSize, myStream->srcFile);
|
||||
bufferHandle = myStream->strmBuff;
|
||||
bytesRead = myStream->srcFile->read((Handle)&bufferHandle, nextReadSize);
|
||||
|
||||
// If we could not read that much in, close the srcFile
|
||||
if (bytesRead < nextReadSize) {
|
||||
delete myStream->srcFile;
|
||||
myStream->srcFile = nullptr;
|
||||
}
|
||||
|
||||
// Update the stream head
|
||||
myStream->strmHead = (uint8 *)((int32)myStream->strmBuff + bytesRead);
|
||||
|
||||
// Update the blockSizeArray pointer if necessary
|
||||
if (useBlockSizeArray) {
|
||||
myStream->blockSizeArray++;
|
||||
myStream->numBlocksToRead--;
|
||||
}
|
||||
}
|
||||
} else if (bytesAvail >= nextReadSize) {
|
||||
// Else we might have to read in part at the end, and part at the beginning of the stream buffer
|
||||
|
||||
// Read into the end of the stream buffer
|
||||
if (buffEndBytesAvail > 0) {
|
||||
|
||||
// Read into the end of the buffer
|
||||
bufferHandle = myStream->strmHead;
|
||||
bytesRead = (int32)myStream->srcFile->read((Handle)&bufferHandle, buffEndBytesAvail);
|
||||
|
||||
// If we could not read that much in, close the srcFile and update the head pointer
|
||||
if (bytesRead < buffEndBytesAvail) {
|
||||
delete myStream->srcFile;
|
||||
myStream->srcFile = nullptr;
|
||||
myStream->strmHead += bytesRead;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure we didn't close the srcFile in the last read
|
||||
if (myStream->srcFile) {
|
||||
|
||||
// Read into the beginning of the buffer
|
||||
bufferHandle = myStream->strmBuff;
|
||||
bytesRead = myStream->srcFile->read((Handle)&bufferHandle, nextReadSize - buffEndBytesAvail);
|
||||
|
||||
// If we could not read that much in, close the srcFile
|
||||
if (bytesRead < (nextReadSize - buffEndBytesAvail)) {
|
||||
delete myStream->srcFile;
|
||||
myStream->srcFile = nullptr;
|
||||
}
|
||||
|
||||
// Update the head pointer
|
||||
myStream->strmHead = (uint8 *)((int32)myStream->strmBuff + bytesRead);
|
||||
|
||||
// Update the blockSizeArray pointer if necessary
|
||||
if (useBlockSizeArray) {
|
||||
myStream->blockSizeArray++;
|
||||
myStream->numBlocksToRead--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we were able, we serviced the above stream request. Get the next request and decriment the counter
|
||||
myStream = myStream->next;
|
||||
numToProcess--;
|
||||
}
|
||||
|
||||
// See if we ran out of processes or if the counter ran out
|
||||
if (myStream) {
|
||||
// This implies the counter ran out. Move the front of the list to myStream->prev to the end of the list
|
||||
myStream->prev->next = nullptr;
|
||||
_G(lastStream)->next = _G(firstStream);
|
||||
_G(firstStream)->prev = _G(lastStream);
|
||||
_G(lastStream) = myStream->prev;
|
||||
myStream->prev = nullptr;
|
||||
_G(firstStream) = myStream;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace M4
|
||||
|
@ -23,6 +23,7 @@
|
||||
#define M4_FILEIO_FSTREAM_H
|
||||
|
||||
#include "common/file.h"
|
||||
#include "m4/mem/reloc.h"
|
||||
#include "m4/m4_types.h"
|
||||
|
||||
namespace M4 {
|
||||
@ -36,7 +37,7 @@ public:
|
||||
|
||||
int32 read(Handle bufferHandle, int32 n);
|
||||
bool seek(uint32 n);
|
||||
bool seek_ahead(uint32 n);
|
||||
bool seek_ahead(int32 n);
|
||||
uint32 get_pos();
|
||||
};
|
||||
|
||||
@ -45,7 +46,7 @@ struct strmRequest {
|
||||
strmRequest *prev;
|
||||
StreamFile *srcFile;
|
||||
int32 strmSize;
|
||||
Handle strmHandle;
|
||||
MemHandle strmHandle;
|
||||
uint8 *strmBuff;
|
||||
uint8 *endStrmBuff;
|
||||
uint8 *strmHead;
|
||||
@ -59,6 +60,13 @@ struct strmRequest {
|
||||
};
|
||||
|
||||
extern bool f_stream_Init();
|
||||
extern void f_stream_Shutdown();
|
||||
|
||||
extern strmRequest *f_stream_Open(StreamFile *srcFile, int32 fileOffset, int32 strmMinBuffSize, int32 strmBuffSize,
|
||||
int32 numBlocksToRead, int32 *blockSizeArray, int32 initialRead, bool wrapStream);
|
||||
extern int32 f_stream_Read(strmRequest *myStream, uint8 **dest, int32 numBytes);
|
||||
extern void f_stream_Close(strmRequest *myStream);
|
||||
extern void f_stream_Process(int32 numToProcess);
|
||||
|
||||
} // namespace M4
|
||||
|
||||
|
@ -47,4 +47,10 @@ bool series_show_frame(int32 spriteHash, int32 index, Buffer *destBuff, int32 x,
|
||||
return series_draw_sprite(spriteHash, index, destBuff, x, y);
|
||||
}
|
||||
|
||||
machine *series_play_xy(char *seriesName, int32 loopCount, uint32 flags,
|
||||
int32 x, int32 y, int32 s, int32 layer, int32 frameRate, int16 triggerNum) {
|
||||
error("TODO: series_play_xy");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace M4
|
||||
|
@ -27,6 +27,12 @@
|
||||
|
||||
namespace M4 {
|
||||
|
||||
constexpr uint32 FORWARD = 0;
|
||||
constexpr uint32 PINGPONG = 1;
|
||||
constexpr uint32 BACKWARD = 2;
|
||||
constexpr uint32 STICK = 4;
|
||||
constexpr uint32 NO_TOSS = 8;
|
||||
|
||||
extern int32 series_load(const char *seriesName, int32 assetIndex, RGB8 *myPal);
|
||||
extern void series_unload(int32 assetIndex);
|
||||
extern bool series_draw_sprite(int32 spriteHash, int32 index, Buffer *destBuff, int32 x, int32 y);
|
||||
|
@ -19,20 +19,501 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "m4/m4_types.h"
|
||||
#include "m4/adv_r/adv_control.h"
|
||||
#include "m4/core/errors.h"
|
||||
#include "m4/core/imath.h"
|
||||
#include "m4/events/keys.h"
|
||||
#include "m4/graphics/krn_pal.h"
|
||||
#include "m4/graphics/gr_pal.h"
|
||||
#include "m4/graphics/gr_series.h"
|
||||
#include "m4/gui/gui_sys.h"
|
||||
#include "m4/gui/gui_vmng.h"
|
||||
#include "m4/vars.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
void krn_ChangeBufferLuminance(Buffer *target, int32 percent) {
|
||||
int32 x, y, r, g, b, i;
|
||||
uint8 *inverse_palette, pixel, *tempPtr;
|
||||
frac16 fracPercent;
|
||||
RGB8 *pal;
|
||||
uint8 luminancePal[256];
|
||||
#define _GP(X) _G(krnPal)._##X
|
||||
|
||||
//paremeter verification
|
||||
#define BACKGROUND_HEIGHT (int32)639
|
||||
|
||||
#define GREY_START 32
|
||||
#define NUM_GREYS 32 // gotta have 32 greys to fade to (hardcoded algorithm)
|
||||
#define GREY_END GREY_START+NUM_GREYS
|
||||
|
||||
#define FREE_START GREY_END+1
|
||||
#define FREE_END 255
|
||||
#define NUM_FREE FREE_END-(FREE_START)+1
|
||||
|
||||
static void krn_pal_game_task() {
|
||||
int32 status;
|
||||
|
||||
ScreenContext *game_buff_ptr = vmng_screen_find(_G(gameDrawBuff), &status);
|
||||
if (!game_buff_ptr)
|
||||
error_show(FL, 'BUF!');
|
||||
|
||||
CycleEngines(_G(game_bgBuff)->get_buffer(), &(_G(currentSceneDef).depth_table[0]),
|
||||
_G(screenCodeBuff), (uint8 *)&_G(master_palette)[0], _G(inverse_pal)->get_ptr(), true);
|
||||
|
||||
_G(inverse_pal)->release();
|
||||
_G(game_bgBuff)->release();
|
||||
|
||||
_G(digi).task();
|
||||
_G(midi).task();
|
||||
|
||||
gui_system_event_handler();
|
||||
|
||||
f_stream_Process(2);
|
||||
}
|
||||
|
||||
static int32 screen_height(Buffer *grey_screen) {
|
||||
return imath_min(BACKGROUND_HEIGHT + _G(kernel).letter_box_y, grey_screen->h);
|
||||
}
|
||||
|
||||
static void grey_fade(RGB8 *pal, int32 to_from_flag, int32 from, int32 to, int32 steps, int32 delay) {
|
||||
int i;
|
||||
#ifdef TODO
|
||||
int j;
|
||||
clock_t begin_time;
|
||||
RGB8 *working = (RGB8 *)mem_alloc(sizeof(RGB8) * 256, STR_FADEPAL);
|
||||
|
||||
// perform the fade
|
||||
for (i = 1; i < steps; i++) {
|
||||
for (j = from; j <= to; j++) {
|
||||
if (to_from_flag == TO_GREY) { // fade to grey from full color
|
||||
working[j].r = (Byte)((int)pal[j].r + ((((int)_GP(fadeToMe)[j].r - (int)pal[j].r) * i) / steps));
|
||||
working[j].g = (Byte)((int)pal[j].g + ((((int)_GP(fadeToMe)[j].g - (int)pal[j].g) * i) / steps));
|
||||
working[j].b = (Byte)((int)pal[j].b + ((((int)_GP(fadeToMe)[j].b - (int)pal[j].b) * i) / steps));
|
||||
} else if (to_from_flag == TO_COLOR) { // fade from grey to full color
|
||||
working[j].r = (Byte)((int)_GP(fadeToMe)[j].r + ((((int)pal[j].r - (int)_GP(fadeToMe)[j].r) * i) / steps));
|
||||
working[j].g = (Byte)((int)_GP(fadeToMe)[j].g + ((((int)pal[j].g - (int)_GP(fadeToMe)[j].g) * i) / steps));
|
||||
working[j].b = (Byte)((int)_GP(fadeToMe)[j].b + ((((int)pal[j].b - (int)_GP(fadeToMe)[j].b) * i) / steps));
|
||||
} else { //fade from grey to black
|
||||
working[j].r = (Byte)((int)_GP(fadeToMe)[j].r - ((((int)_GP(fadeToMe)[j].r) * i) / steps));
|
||||
working[j].g = (Byte)((int)_GP(fadeToMe)[j].g - ((((int)_GP(fadeToMe)[j].g) * i) / steps));
|
||||
working[j].b = (Byte)((int)_GP(fadeToMe)[j].b - ((((int)_GP(fadeToMe)[j].b) * i) / steps));
|
||||
}
|
||||
}
|
||||
|
||||
gr_pal_set_range(working, from, to - from + 1); ///set pal 21-255
|
||||
|
||||
// Time delay of "delay" milliseconds
|
||||
begin_time = clock();
|
||||
while ((((clock() - begin_time) * 1000) / CLOCKS_PER_SEC) < delay)
|
||||
krn_pal_game_task();
|
||||
}
|
||||
#else
|
||||
error("TODO: grey_fade");
|
||||
#endif
|
||||
|
||||
// Eliminate round off error
|
||||
if (to_from_flag == TO_GREY) {
|
||||
gr_pal_set_range(_GP(fadeToMe), from, to - from + 1); ///set pal 21-255
|
||||
} else if (to_from_flag == TO_COLOR) {
|
||||
gr_pal_set_range(pal, from, to - from + 1); ///set pal 21-255
|
||||
} else {
|
||||
for (i = from; i <= to; i++) {
|
||||
pal[i].r = pal[i].g = pal[i].b = 0;
|
||||
}
|
||||
gr_pal_set_range(pal, from, to - from + 1); ///set pal 21-255
|
||||
}
|
||||
#ifdef TODO
|
||||
mem_free(working);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
// screen is the currently displayed screen
|
||||
// screenPicture is the data to restore the screen with
|
||||
// note: color 0 doesn't fade.
|
||||
|
||||
static void create_luminance_map(RGB8 *pal) {
|
||||
for (int i = GREY_START; i <= FREE_END; i++) {
|
||||
Byte luminance = (Byte)((pal[i].r + pal[i].g + pal[i].b) / 3);
|
||||
_GP(fadeToMe)[i].g = (Byte)imath_min(255, luminance); // MattP new green screen!
|
||||
_GP(fadeToMe)[i].r = _GP(fadeToMe)[i].b = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static HotkeyCB remember_esc_key;
|
||||
|
||||
|
||||
// finds the best macthes for the in the greys in the grey ramp range using the free range greys
|
||||
// used to map greys out of the grey ramp area, and then again to map the grey ramp out of the grey ramp area!
|
||||
static void make_translation_table(RGB8 *pal) {
|
||||
int32 i, j, bestMatch, minDist;
|
||||
|
||||
for (i = 0; i < NUM_GREYS; i++) {
|
||||
bestMatch = FREE_START; // assume the first of the free indexes is best match to start with
|
||||
minDist = 255; // assume that it's really far away to start with
|
||||
|
||||
if (!(i & 0x3ff)) {
|
||||
digi_read_another_chunk();
|
||||
midi_loop();
|
||||
}
|
||||
|
||||
// look for best match in the free indexes for the greys in GREY_START-GREY_END range (we need these available)
|
||||
int32 matchGrey = pal[GREY_START + i].g; // MattP use green instead of red cause we're having a green screen
|
||||
|
||||
for (j = FREE_START; j <= FREE_END; j++) {
|
||||
int32 tryGrey = pal[j].g;
|
||||
if (imath_abs(tryGrey - matchGrey) < minDist) {
|
||||
minDist = imath_abs(tryGrey - matchGrey);
|
||||
bestMatch = j;
|
||||
}
|
||||
if (minDist == 0)
|
||||
break; // no need to continue searching if we found a perfect match
|
||||
}
|
||||
_GP(translation)[i] = (uint8)bestMatch;
|
||||
}
|
||||
}
|
||||
|
||||
void krn_fade_to_grey(RGB8 *pal, int32 steps, int32 delay) {
|
||||
int32 i, j, bestMatch, minDist;
|
||||
uint8 *tempPtr;
|
||||
|
||||
if (_G(kernel).fading_to_grey) {
|
||||
return;
|
||||
}
|
||||
_G(kernel).fading_to_grey = true;
|
||||
|
||||
Buffer *grey_screen = _G(gameDrawBuff)->get_buffer();
|
||||
|
||||
_GP(fadeToMe) = (RGB8 *)mem_alloc(sizeof(RGB8) * 256, STR_FADEPAL);
|
||||
_GP(trick) = (RGB8 *)mem_alloc(sizeof(RGB8) * 256, STR_FADEPAL);
|
||||
_GP(picPal) = (RGB8 *)mem_alloc(sizeof(RGB8) * 256, STR_FADEPAL);
|
||||
|
||||
memcpy(_GP(picPal), pal, sizeof(RGB8) * 256);
|
||||
create_luminance_map(pal);
|
||||
|
||||
grey_fade(pal, TO_GREY, 21, 255, steps, delay);
|
||||
|
||||
// make _GP(translation) table
|
||||
// to translate colors using entries 59-255 into 21-58 range
|
||||
|
||||
for (i = 0; i < 64; i++) {
|
||||
bestMatch = 63;
|
||||
minDist = 255;
|
||||
|
||||
if (!(i & 0x3ff)) {
|
||||
_G(digi).task();
|
||||
_G(midi).task();
|
||||
}
|
||||
|
||||
for (j = 59; j <= 255; j++) {
|
||||
if (imath_abs((_GP(fadeToMe)[j].r >> 2) - i) < minDist) {
|
||||
minDist = imath_abs((_GP(fadeToMe)[j].r >> 2) - i);
|
||||
bestMatch = j;
|
||||
}
|
||||
if (minDist == 0)
|
||||
break; // no need to continue searching if we found a perfect match
|
||||
}
|
||||
|
||||
_GP(translation)[i] = (uint8)bestMatch;
|
||||
}
|
||||
|
||||
// palette now grey scale. Remap any pixels which are in the range 21-58 to the range 53-255
|
||||
// because we need to use those palette entries soon
|
||||
|
||||
tempPtr = grey_screen->data;
|
||||
// note: this loop should be y0 to y1, x0 to x1, not a stride*h loop.
|
||||
for (i = 0; i < (grey_screen->stride * grey_screen->h); i++) {
|
||||
if ((*tempPtr >= GREY_START) && (*tempPtr <= GREY_END)) {
|
||||
// must move the pixel index to the best match in FREE_START-FREE_END range with _GP(translation) table
|
||||
*tempPtr = _GP(translation)[*tempPtr - GREY_START];
|
||||
}
|
||||
tempPtr++;
|
||||
|
||||
if (!(i & 0x3ff)) {
|
||||
_G(digi).task();
|
||||
_G(midi).task();
|
||||
}
|
||||
|
||||
}
|
||||
RestoreScreens(MIN_VIDEO_X, MIN_VIDEO_Y, MAX_VIDEO_X, MAX_VIDEO_Y);
|
||||
|
||||
// make new trickPal with grey-scale ramp entries and load it into VGA registers
|
||||
memcpy(_GP(trick), _GP(fadeToMe), sizeof(RGB8) * 256); // MattP _GP(trick) pal is the greyed version plus the grey ramp overlayed on top
|
||||
int8 grey_step = 256 / NUM_GREYS;
|
||||
int8 grey_ramp = 0;
|
||||
for (i = GREY_START; i <= GREY_END; i++) {
|
||||
// _GP(trick)[i].r = _GP(trick)[i].g = _GP(trick)[i].b = (Byte) (grey_ramp); old grey ramp
|
||||
_GP(trick)[i].g = (Byte)(grey_ramp); // MattP new green screen
|
||||
_GP(trick)[i].r = _GP(trick)[i].b = 0;
|
||||
grey_ramp += grey_step;
|
||||
}
|
||||
gr_pal_set_range(_GP(trick), GREY_START, NUM_GREYS); ///set pal GREY_START-GREY_END
|
||||
|
||||
remap_buffer_with_luminance_map(grey_screen, 0, 0, grey_screen->W - 1, screen_height(grey_screen) - 1);
|
||||
_G(gameDrawBuff)->release();
|
||||
RestoreScreens(MIN_VIDEO_X, MIN_VIDEO_Y, MAX_VIDEO_X, MAX_VIDEO_Y);
|
||||
}
|
||||
|
||||
|
||||
void krn_fade_from_grey(RGB8 *pal, int32 steps, int32 delay, int32 fadeType) {
|
||||
uint8 *tempPtr;
|
||||
int32 i;
|
||||
|
||||
if (!_G(kernel).fading_to_grey) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the screen
|
||||
Buffer *grey_screen = _G(gameDrawBuff)->get_buffer();
|
||||
|
||||
// load original faded greys into the free indexes (no pixels have these indexs yet)
|
||||
gr_pal_set_range(_GP(fadeToMe), FREE_START, NUM_FREE); // Load _GP(fadeToMe) colors into VGA
|
||||
|
||||
make_translation_table(_GP(trick)); // Mattp this is used in fade_to_grey too!
|
||||
|
||||
// for every pixel in the screen, move any pixel in the GREY_START-GREY_END range out in to the free range
|
||||
tempPtr = grey_screen->data;
|
||||
// note: this loop should be y0 to y1, x0 to x1, not a stride*h loop.
|
||||
for (i = 0; i < (grey_screen->stride * grey_screen->h); ++i) {
|
||||
if (!(i & 0x3ff)) {
|
||||
_G(digi).task();
|
||||
_G(midi).task();
|
||||
}
|
||||
|
||||
// if the pixel is within the GREY range, move it to where the _GP(translation) table says
|
||||
if ((*tempPtr >= GREY_START) && (*tempPtr <= GREY_END)) {
|
||||
*tempPtr = _GP(translation)[*tempPtr - GREY_START];
|
||||
}
|
||||
tempPtr++;
|
||||
}
|
||||
|
||||
// Term_message ("remaped indexes out of grey ramp");
|
||||
RestoreScreens(MIN_VIDEO_X, MIN_VIDEO_Y, MAX_VIDEO_X, MAX_VIDEO_Y);
|
||||
// Term_message ("setting grey ramp indexes back to picture greys");
|
||||
gr_pal_set_range(_GP(fadeToMe), GREY_START, NUM_GREYS); // get the rest of the original re-luminance colors
|
||||
|
||||
//recopy screenPicture to screen to restore original pixels
|
||||
krn_UnsetGreyVideoMode();
|
||||
RestoreScreens(0, 0, MAX_VIDEO_X, MAX_VIDEO_Y);
|
||||
|
||||
memcpy(pal, _GP(picPal), sizeof(RGB8) * 256);
|
||||
|
||||
ws_RefreshWoodscriptBuffer(_G(game_bgBuff)->get_buffer(), &(_G(currentSceneDef).depth_table[0]), _G(screenCodeBuff),
|
||||
(uint8 *)&_G(master_palette)[0], _G(inverse_pal)->get_ptr());
|
||||
_G(game_bgBuff)->release();
|
||||
_G(inverse_pal)->release();
|
||||
|
||||
RestoreScreens(MIN_VIDEO_X, MIN_VIDEO_Y, MAX_VIDEO_X, MAX_VIDEO_Y);
|
||||
|
||||
grey_fade(pal, fadeType, GREY_START, FREE_END, steps, delay);
|
||||
|
||||
mem_free((char *)_GP(trick));
|
||||
mem_free((char *)_GP(fadeToMe));
|
||||
mem_free((char *)_GP(picPal));
|
||||
_G(kernel).fading_to_grey = false;
|
||||
_G(gameDrawBuff)->release();
|
||||
gr_pal_set(_G(master_palette));
|
||||
}
|
||||
|
||||
bool examining_inventory_object = false;
|
||||
|
||||
|
||||
void kernel_examine_inventory_object(char *picName, RGB8 *pal, int steps, int delay,
|
||||
int32 x, int32 y, int32 triggerNum, char *digi_name, int32 digi_trigger) {
|
||||
|
||||
remember_esc_key = GetSystemHotkey(KEY_ESCAPE);
|
||||
RemoveSystemHotkey(KEY_ESCAPE);
|
||||
|
||||
interface_hide();
|
||||
|
||||
_GP(exam_saved_hotspots) = _G(currentSceneDef).hotspots;
|
||||
_G(currentSceneDef).hotspots = NULL;
|
||||
|
||||
_GP(myFadeTrigger) = kernel_trigger_create(triggerNum);
|
||||
|
||||
krn_fade_to_grey(pal, steps, delay);
|
||||
|
||||
_GP(seriesHash) = series_load(picName, -1, pal); // Preload sprite so we can unload it
|
||||
gr_pal_set_range(pal, FREE_START, 197); // Set that series colors into VGA
|
||||
RestoreScreens(MIN_VIDEO_X, MIN_VIDEO_Y, MAX_VIDEO_X, MAX_VIDEO_Y);
|
||||
|
||||
Buffer *grey_screen = _G(gameDrawBuff)->get_buffer();
|
||||
krn_SetGreyVideoMode(
|
||||
// Grey rectangle
|
||||
0, 0, MAX_VIDEO_X, screen_height(grey_screen) + _G(kernel).letter_box_y,
|
||||
// Color rectangle
|
||||
x, y, x + ws_get_sprite_width(_GP(seriesHash), 0) - 1, y + ws_get_sprite_height(_GP(seriesHash), 0) - 1);
|
||||
_G(gameDrawBuff)->release();
|
||||
|
||||
// Play the sprite series as a loop
|
||||
int32 status;
|
||||
ScreenContext *game_buff_ptr = vmng_screen_find(_G(gameDrawBuff), &status);
|
||||
_GP(seriesAnim8) = series_play_xy(picName, -1, FORWARD,
|
||||
x - game_buff_ptr->x1, y - game_buff_ptr->y1, 100, 0, 7, -1);
|
||||
|
||||
if (digi_name) {
|
||||
digi_play(digi_name, 1, 255, digi_trigger);
|
||||
}
|
||||
|
||||
player_set_commands_allowed(true);
|
||||
|
||||
CycleEngines(_G(game_bgBuff)->get_buffer(), &(_G(currentSceneDef).depth_table[0]),
|
||||
_G(screenCodeBuff), (uint8 *)&_G(master_palette)[0], _G(inverse_pal)->get_ptr(), true);
|
||||
|
||||
game_pause(true);
|
||||
|
||||
_G(inverse_pal)->release();
|
||||
_G(game_bgBuff)->release();
|
||||
|
||||
PauseEngines();
|
||||
}
|
||||
|
||||
void kernel_unexamine_inventory_object(RGB8 *pal, int steps, int delay) {
|
||||
if (!_GP(seriesAnim8) || _GP(seriesHash) < 0)
|
||||
return;
|
||||
|
||||
player_set_commands_allowed(false);
|
||||
game_pause(false);
|
||||
UnpauseEngines();
|
||||
|
||||
TerminateMachine(_GP(seriesAnim8));
|
||||
series_unload(_GP(seriesHash));
|
||||
_GP(seriesAnim8) = NULL;
|
||||
_GP(seriesHash) = 0;
|
||||
|
||||
Buffer *grey_screen = _G(gameDrawBuff)->get_buffer();
|
||||
krn_SetGreyVideoMode(0, 0, MAX_VIDEO_X, screen_height(grey_screen) + _G(kernel).letter_box_y, -1, -1, -1, -1);
|
||||
_G(gameDrawBuff)->release();
|
||||
|
||||
krn_pal_game_task();
|
||||
|
||||
krn_fade_from_grey(pal, steps, delay, TO_COLOR);
|
||||
|
||||
krn_pal_game_task();
|
||||
|
||||
// set in kernel_examine_inventory_object (above)
|
||||
kernel_trigger_dispatch(_GP(myFadeTrigger));
|
||||
|
||||
// gr_pal_set(master_palette);
|
||||
|
||||
RestoreScreens(0, 0, MAX_VIDEO_X, MAX_VIDEO_Y);
|
||||
|
||||
_G(currentSceneDef).hotspots = _GP(exam_saved_hotspots);
|
||||
|
||||
interface_show();
|
||||
AddSystemHotkey(KEY_ESCAPE, remember_esc_key);
|
||||
}
|
||||
|
||||
|
||||
// This is an inplace remap
|
||||
// _GP(fadeToMe) must already have been set up to correspond to the image on the screen
|
||||
void remap_buffer_with_luminance_map(Buffer *src, int32 x1, int32 y1, int32 x2, int32 y2) {
|
||||
uint8 *ptr;
|
||||
int32 x, y;
|
||||
if ((!src) || (!src->data)) return;
|
||||
if ((x2 - x1 < 0) || (y2 - y1 < 0)) return;
|
||||
if (x2 - x1 + 1 > src->W) x2 = src->W - 1;
|
||||
if (y2 - y1 + 1 > src->h) y2 = src->h - 1;
|
||||
|
||||
x2 -= x1;
|
||||
y2 -= y1;
|
||||
for (y = 0; y <= y2; y++) {
|
||||
ptr = &src->data[(y + y1) * src->stride + x1];
|
||||
for (x = 0; x <= x2; x++) // for each pixel in row
|
||||
|
||||
// remap the greyed out pixel to the closest grey in GREY_START to GREY_END range
|
||||
// shift right 3, takes a 255 value and makes it out of 32 (the number of greys in reduced grey ramp)
|
||||
ptr[x] = (uint8)(GREY_START + (_GP(fadeToMe)[ptr[x]].g >> 3)); // MattP use green instead of red cause we're having a green screen
|
||||
|
||||
if (!(y & 0xff)) {
|
||||
_G(digi).task();
|
||||
_G(midi).task();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void krn_SetGreyVideoMode(int32 grey_x1, int32 grey_y1, int32 grey_x2, int32 grey_y2, int32 color_x1, int32 color_y1, int32 color_x2, int32 color_y2) {
|
||||
_GP(greyAreaX1) = grey_x1;
|
||||
_GP(greyAreaY1) = grey_y1;
|
||||
_GP(greyAreaX2) = grey_x2;
|
||||
_GP(greyAreaY2) = grey_y2;
|
||||
|
||||
_GP(colorAreaX1) = color_x1;
|
||||
_GP(colorAreaY1) = color_y1;
|
||||
_GP(colorAreaX2) = color_x2;
|
||||
_GP(colorAreaY2) = color_y2;
|
||||
|
||||
_GP(greyVideoMode) = true;
|
||||
}
|
||||
|
||||
void krn_UnsetGreyVideoMode() {
|
||||
_GP(greyAreaX1) = -1;
|
||||
_GP(greyAreaY1) = -1;
|
||||
_GP(greyAreaX2) = -1;
|
||||
_GP(greyAreaY2) = -1;
|
||||
|
||||
_GP(colorAreaX1) = -1;
|
||||
_GP(colorAreaY1) = -1;
|
||||
_GP(colorAreaX2) = -1;
|
||||
_GP(colorAreaY2) = -1;
|
||||
|
||||
_GP(greyVideoMode) = false;
|
||||
}
|
||||
|
||||
bool krn_GetGreyMode() {
|
||||
return _GP(greyVideoMode);
|
||||
}
|
||||
|
||||
void krn_UpdateGreyArea(Buffer *greyOutThisBuffer, int32 scrnX, int32 scrnY, int32 greyX1, int32 greyY1, int32 greyX2, int32 greyY2) {
|
||||
bool finished;
|
||||
int32 x1, y1, x2, y2;
|
||||
|
||||
if ((!_GP(greyVideoMode)) || (!greyOutThisBuffer) || (!greyOutThisBuffer->data)) {
|
||||
return;
|
||||
}
|
||||
x1 = imath_max(greyX1 + scrnX, _GP(greyAreaX1));
|
||||
y1 = imath_max(greyY1 + scrnY, _GP(greyAreaY1));
|
||||
x2 = imath_min(greyX2 + scrnX, _GP(greyAreaX2));
|
||||
y2 = imath_min(greyY2 + scrnY, _GP(greyAreaY2));
|
||||
if ((x1 > x2) || (y1 > y2)) return;
|
||||
finished = false;
|
||||
if (!finished) {
|
||||
if (y1 < _GP(colorAreaY1)) {
|
||||
remap_buffer_with_luminance_map(greyOutThisBuffer,
|
||||
x1 - scrnX, y1 - scrnY, x2 - scrnX, imath_min(y2, _GP(colorAreaY1) - 1) - scrnY);
|
||||
y1 = imath_min(y2, _GP(colorAreaY1));
|
||||
if (y1 >= y2) finished = true;
|
||||
}
|
||||
}
|
||||
if (!finished) {
|
||||
if (y2 > _GP(colorAreaY2)) {
|
||||
remap_buffer_with_luminance_map(greyOutThisBuffer,
|
||||
x1 - scrnX, imath_max(y1, _GP(colorAreaY2) + 1) - scrnY, x2 - scrnX, y2 - scrnY);
|
||||
y2 = imath_max(y1, _GP(colorAreaY2));
|
||||
if (y1 >= y2) finished = true;
|
||||
}
|
||||
}
|
||||
if (!finished) {
|
||||
if (x1 < _GP(colorAreaX1)) {
|
||||
remap_buffer_with_luminance_map(greyOutThisBuffer,
|
||||
x1 - scrnX, y1 - scrnY, imath_min(x2, _GP(colorAreaX1) - 1) - scrnX, y2 - scrnY);
|
||||
x1 = imath_min(x2, _GP(colorAreaX1));
|
||||
if (x1 >= x2) finished = true;
|
||||
}
|
||||
}
|
||||
if (!finished) {
|
||||
if (x2 > _GP(colorAreaX2)) {
|
||||
remap_buffer_with_luminance_map(greyOutThisBuffer,
|
||||
imath_max(x1, _GP(colorAreaX2) + 1) - scrnX, y1 - scrnY, x2 - scrnX, y2 - scrnY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void krn_ChangeBufferLuminance(Buffer *target, int32 percent) {
|
||||
int32 x, y, r, g, b, i;
|
||||
uint8 *inverse_palette, pixel, *tempPtr;
|
||||
frac16 fracPercent;
|
||||
RGB8 *pal;
|
||||
uint8 luminancePal[256];
|
||||
|
||||
// Paremeter verification
|
||||
if ((!target) || (!target->data)) {
|
||||
return;
|
||||
}
|
||||
@ -46,17 +527,17 @@ void krn_ChangeBufferLuminance(Buffer *target, int32 percent) {
|
||||
return;
|
||||
}
|
||||
|
||||
//calculate the frac16 form of the percent
|
||||
// Calculate the frac16 form of the percent
|
||||
fracPercent = (percent * 255) / 100;
|
||||
|
||||
//get the palette and the inverse palette
|
||||
// Get the palette and the inverse palette
|
||||
pal = &_G(master_palette)[0];
|
||||
inverse_palette = _G(inverse_pal)->get_ptr();
|
||||
if ((!pal) || (!inverse_palette)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//calculate the luminance Pal table
|
||||
// Calculate the luminance Pal table
|
||||
for (i = 0; i < 256; i++) {
|
||||
r = ((((pal[i].r * fracPercent) >> 10) >> 1)) & 0x1f;
|
||||
g = ((((pal[i].g * fracPercent) >> 10) >> 1)) & 0x1f;
|
||||
@ -64,8 +545,8 @@ void krn_ChangeBufferLuminance(Buffer *target, int32 percent) {
|
||||
luminancePal[i] = inverse_palette[(r << 10) + (g << 5) + b];
|
||||
}
|
||||
|
||||
// note: this loop should be y0 to y1, x0 to x1, not a stride*h loop.
|
||||
//loop through every pixel replacing it with the index into the luminance table
|
||||
// Note: this loop should be y0 to y1, x0 to x1, not a stride*h loop.
|
||||
// Loop through every pixel replacing it with the index into the luminance table
|
||||
tempPtr = target->data;
|
||||
for (y = 0; y < target->h; y++) {
|
||||
for (x = 0; x < target->stride; x++) {
|
||||
@ -78,4 +559,340 @@ void krn_ChangeBufferLuminance(Buffer *target, int32 percent) {
|
||||
_G(inverse_pal)->release();
|
||||
}
|
||||
|
||||
|
||||
static void pal_fade_callback(frac16 myMessage) {
|
||||
_G(pal_fade_in_progress) = false;
|
||||
kernel_trigger_dispatch((uint32)myMessage);
|
||||
}
|
||||
|
||||
void pal_fade_init(RGB8 *origPalette, int32 firstPalEntry, int32 lastPalEntry,
|
||||
int32 targetPercent, int32 numTicks, uint32 triggerNum) {
|
||||
if ((!origPalette) || (firstPalEntry < 0) || (lastPalEntry > 255) || (firstPalEntry > lastPalEntry))
|
||||
return;
|
||||
if ((targetPercent < 0) || (targetPercent > 100))
|
||||
return;
|
||||
|
||||
_GP(myFadeReq) = true;
|
||||
_GP(myFadeFinished) = false;
|
||||
_GP(myFadeStartTime) = timer_read_60();
|
||||
_GP(myFadeEndDelayTime) = timer_read_60();
|
||||
_GP(myFadeStartIndex) = firstPalEntry;
|
||||
_GP(myFadeEndIndex) = lastPalEntry;
|
||||
_GP(myFadeEndTime) = _GP(myFadeStartTime) + numTicks;
|
||||
_GP(myFadeTrigger) = kernel_trigger_create(triggerNum);
|
||||
_GP(myFadeStartPercentFrac) = _GP(myFadeCurrPercentFrac);
|
||||
_GP(myFadePercentFrac) = DivSF16(targetPercent << 16, 0x640000);
|
||||
|
||||
// Disable_end_user_hot_keys();
|
||||
_G(pal_fade_in_progress) = true;
|
||||
}
|
||||
|
||||
static void pal_fade_update(RGB8 *origPalette) {
|
||||
int32 i, currTime;
|
||||
frac16 tempFrac, tempFrac2;
|
||||
|
||||
currTime = timer_read_60();
|
||||
|
||||
if (currTime >= _GP(myFadeEndDelayTime)) { // If the delay has expired, fade more
|
||||
if (currTime >= _GP(myFadeEndTime)) {
|
||||
tempFrac2 = _GP(myFadePercentFrac);
|
||||
_GP(myFadeStartPercentFrac) = _GP(myFadePercentFrac);
|
||||
_GP(myFadeFinished) = true;
|
||||
} else if (currTime <= _GP(myFadeStartTime)) return;
|
||||
else {
|
||||
tempFrac = DivSF16((currTime - _GP(myFadeStartTime)) << 16, (_GP(myFadeEndTime) - _GP(myFadeStartTime)) << 16);
|
||||
tempFrac2 = MulSF16(tempFrac, _GP(myFadePercentFrac) - _GP(myFadeStartPercentFrac)) + _GP(myFadeStartPercentFrac);
|
||||
}
|
||||
|
||||
_GP(myFadeCurrPercentFrac) = tempFrac2;
|
||||
|
||||
for (i = _GP(myFadeStartIndex); i <= _GP(myFadeEndIndex); i++) {
|
||||
_GP(myFXPalette)[i].r = (Byte)(MulSF16(origPalette[i].r << 16, tempFrac2) >> 16);
|
||||
_GP(myFXPalette)[i].g = (Byte)(MulSF16(origPalette[i].g << 16, tempFrac2) >> 16);
|
||||
_GP(myFXPalette)[i].b = (Byte)(MulSF16(origPalette[i].b << 16, tempFrac2) >> 16);
|
||||
}
|
||||
|
||||
// Recalculate the end delay time again
|
||||
_GP(myFadeEndDelayTime) = currTime + _GP(myFadeDelayTicks); // Recalculate the end delay time again
|
||||
|
||||
// Must reresh the DAC
|
||||
_GP(myFadeDACrefresh) = true;
|
||||
}
|
||||
}
|
||||
|
||||
void clear_DAC() {
|
||||
RGB8 color;
|
||||
|
||||
color.r = color.b = color.g = 0;
|
||||
for (int i = 0; i < 256; i++)
|
||||
gr_pal_set_entry(i, &color);
|
||||
}
|
||||
|
||||
void pal_fade_set_start(RGB8 *origPalette, int32 percent) {
|
||||
pal_fade_init(origPalette, _G(kernel).first_fade, 255, percent, 0, (uint)-1);
|
||||
pal_fade_update(origPalette);
|
||||
pal_fx_update();
|
||||
}
|
||||
|
||||
static void pal_cycle_callback(frac16 myMessage) {
|
||||
kernel_trigger_dispatch((uint32)myMessage);
|
||||
}
|
||||
|
||||
void pal_cycle_init(int32 firstPalEntry, int32 lastPalEntry,
|
||||
int32 delayTicks, int32 totalTicks, uint32 triggerNum) {
|
||||
if ((firstPalEntry < 0) || (lastPalEntry > 255) || (firstPalEntry > lastPalEntry)) {
|
||||
// This should generate an error
|
||||
return;
|
||||
}
|
||||
if (delayTicks <= 0) {
|
||||
// This should generate an error (Nick debug plarg MattP)
|
||||
return;
|
||||
}
|
||||
|
||||
_GP(myCycleReq) = true;
|
||||
_GP(myCycleFinished) = false;
|
||||
_GP(myCycleDelayTicks) = delayTicks;
|
||||
_GP(myCycleStartTime) = timer_read_60();
|
||||
_GP(myCycleEndDelayTime) = timer_read_60();
|
||||
_GP(myCycleStartIndex) = firstPalEntry;
|
||||
_GP(myCycleEndIndex) = lastPalEntry;
|
||||
_GP(myCycleTrigger) = kernel_trigger_create(triggerNum); // Returned when _GP(myCycleEndTime) is reached
|
||||
|
||||
if (totalTicks > 0) { // If totalTicks > 0, calculate end time
|
||||
_GP(myCycleEndTime) = _GP(myCycleStartTime) + totalTicks;
|
||||
_GP(myCycleNeverStopCycling) = false;
|
||||
|
||||
} else if (totalTicks < 0) { // If totalTicks < 0, never stop the cycling
|
||||
_GP(myCycleNeverStopCycling) = true;
|
||||
|
||||
} else { // If totalTicks is 0, stop cycling now
|
||||
_GP(myCycleReq) = false;
|
||||
_GP(myCycleFinished) = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool pal_cycle_active() {
|
||||
return _GP(myCycleReq);
|
||||
}
|
||||
|
||||
void pal_cycle_stop() {
|
||||
_GP(myCycleReq) = false;
|
||||
}
|
||||
|
||||
void pal_cycle_resume() {
|
||||
_GP(myCycleReq) = true;
|
||||
}
|
||||
|
||||
static void pal_cycle_update() {
|
||||
int32 i, currTime;
|
||||
RGB8 firstColour;
|
||||
|
||||
currTime = timer_read_60(); // Get current time
|
||||
|
||||
if (_GP(myCycleNeverStopCycling) == false) { // If there is an end time to get to...
|
||||
|
||||
if (currTime >= _GP(myCycleEndTime)) { // See if we have reached it
|
||||
_GP(myCycleFinished) = true; // Mark cycling as finished
|
||||
return; // Return
|
||||
}
|
||||
} else {
|
||||
// See if we should colour cycle right now
|
||||
if (currTime >= _GP(myCycleEndDelayTime)) { // If the delay has expired, colour cycle
|
||||
// Cycle the master palette
|
||||
firstColour.r = _G(master_palette)[_GP(myCycleStartIndex)].r; // Remember first colour
|
||||
firstColour.g = _G(master_palette)[_GP(myCycleStartIndex)].g;
|
||||
firstColour.b = _G(master_palette)[_GP(myCycleStartIndex)].b;
|
||||
for (i = _GP(myCycleStartIndex); i < _GP(myCycleEndIndex); ++i) { // Shift colours down one in palette
|
||||
_G(master_palette)[i].r = _G(master_palette)[i + 1].r;
|
||||
_G(master_palette)[i].g = _G(master_palette)[i + 1].g;
|
||||
_G(master_palette)[i].b = _G(master_palette)[i + 1].b;
|
||||
}
|
||||
_G(master_palette)[_GP(myCycleEndIndex)].r = firstColour.r; // Set last colour to the first colour
|
||||
_G(master_palette)[_GP(myCycleEndIndex)].g = firstColour.g;
|
||||
_G(master_palette)[_GP(myCycleEndIndex)].b = firstColour.b;
|
||||
|
||||
// Then cycle the FX palette
|
||||
firstColour.r = _GP(myFXPalette)[_GP(myCycleStartIndex)].r; // Remember first colour
|
||||
firstColour.g = _GP(myFXPalette)[_GP(myCycleStartIndex)].g;
|
||||
firstColour.b = _GP(myFXPalette)[_GP(myCycleStartIndex)].b;
|
||||
for (i = _GP(myCycleStartIndex); i < _GP(myCycleEndIndex); ++i) { // Shift colours down one in palette
|
||||
_GP(myFXPalette)[i].r = _GP(myFXPalette)[i + 1].r;
|
||||
_GP(myFXPalette)[i].g = _GP(myFXPalette)[i + 1].g;
|
||||
_GP(myFXPalette)[i].b = _GP(myFXPalette)[i + 1].b;
|
||||
}
|
||||
_GP(myFXPalette)[_GP(myCycleEndIndex)].r = firstColour.r; // Set last colour to the first colour
|
||||
_GP(myFXPalette)[_GP(myCycleEndIndex)].g = firstColour.g;
|
||||
_GP(myFXPalette)[_GP(myCycleEndIndex)].b = firstColour.b;
|
||||
|
||||
|
||||
// Recalculate the end delay time again
|
||||
_GP(myCycleEndDelayTime) = currTime + _GP(myCycleDelayTicks); // Recalculate the end delay time again
|
||||
|
||||
// must reresh the DAC
|
||||
_GP(myCycleDACrefresh) = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// pal_fx_update() is called each game loop
|
||||
//
|
||||
void pal_fx_update() {
|
||||
int32 startA = 0, endA = 0, startB = 0, endB = 0, startDAC = 0, endDAC = 0;
|
||||
|
||||
if (!_GP(myCycleReq) && !_GP(myFadeReq))
|
||||
// Crap out quickly if no effects required
|
||||
return;
|
||||
|
||||
// Perform any effect required and track index ranges
|
||||
if (_GP(myCycleReq)) {
|
||||
pal_cycle_update(); // Do the cycling (cycles master_palette and _GP(myFXPalette))
|
||||
if (_GP(myCycleDACrefresh)) { // If it needs the DAC to be refreshed,
|
||||
startA = _GP(myCycleStartIndex); // remember the range
|
||||
endA = _GP(myCycleEndIndex);
|
||||
_GP(myCycleDACrefresh) = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (_GP(myFadeReq)) {
|
||||
pal_fade_update(&_G(master_palette)[0]); // Do the fading (sets myFXPalette to faded master_palette)
|
||||
if (_GP(myFadeDACrefresh)) { // If it needs the DAC to be refreshed,
|
||||
startB = _GP(myFadeStartIndex); // remember the range
|
||||
endB = _GP(myFadeEndIndex);
|
||||
_GP(myFadeDACrefresh) = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check ranges to perform minimum calls of gr_pal_set_range() (to minimize snow on monitor due to OUT instructions)
|
||||
if (endA < startB || endB < startA) { // if A and B ranges don't overlap
|
||||
|
||||
if (!(startA == 0 && endA == 0)) // if this is not the degenerate case (just the transparent color)
|
||||
gr_pal_set_range(&_GP(myFXPalette)[0], startA, endA - startA + 1); // set A range of the DAC
|
||||
|
||||
if (!(startB == 0 && endB == 0)) // if this is not the degenerate case (just the transparent color)
|
||||
gr_pal_set_range(&_GP(myFXPalette)[0], startB, endB - startB + 1); // set B range of the DAC
|
||||
|
||||
} else {
|
||||
// They overlap, so find the extent of the overlap
|
||||
(startA < startB) ? (startDAC = startA) : (startDAC = startB); // which start is less
|
||||
(endA > endB) ? (endDAC = endA) : (endDAC = endB); // which end is more
|
||||
|
||||
if (!(startDAC == 0 && endDAC == 0)) // if this is not the degenerate case (just the transparent color)
|
||||
gr_pal_set_range(&_GP(myFXPalette)[0], startDAC, endDAC - startDAC + 1); // set the whole range of the DAC
|
||||
}
|
||||
|
||||
// Turn off flags and call callbacks if effects are finished
|
||||
if (_GP(myFadeReq) && _GP(myFadeFinished)) {
|
||||
_GP(myFadeReq) = false;
|
||||
pal_fade_callback(_GP(myFadeTrigger));
|
||||
}
|
||||
|
||||
if (_GP(myCycleReq) && _GP(myCycleFinished)) {
|
||||
_GP(myCycleReq) = false;
|
||||
pal_cycle_callback(_GP(myCycleTrigger));
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================================
|
||||
//
|
||||
// DAC_tint_effect() is used to effect the screen colours (not the master palette) temporarily
|
||||
// until something else updates the DAC e.g. refresh_DAC()
|
||||
//
|
||||
|
||||
void DAC_tint_range(RGB8 *tintColor, int32 percent, int32 firstPalEntry, int32 lastPalEntry, bool transparent) {
|
||||
int32 i;
|
||||
int32 r, g, b, dr, dg, db;
|
||||
RGB8 color, targetColor;
|
||||
int32 percent_r, percent_g, percent_b;
|
||||
|
||||
if ((firstPalEntry < 0) || (lastPalEntry > 255) || (firstPalEntry > lastPalEntry)) {
|
||||
// this should generate an error (Nick debug plarg MattP)
|
||||
term_message("*** palette index error");
|
||||
return;
|
||||
}
|
||||
|
||||
term_message("Colour tint DAC to: %d %d %d, %d percent, range (%d - %d)",
|
||||
tintColor->r, tintColor->g, tintColor->b, percent, firstPalEntry, lastPalEntry); // debug
|
||||
percent = DivSF16(percent << 16, 100 << 16); // convert percent to frac16 format
|
||||
|
||||
targetColor.r = tintColor->r;
|
||||
targetColor.g = tintColor->g;
|
||||
targetColor.b = tintColor->b;
|
||||
|
||||
term_message("Doing palette.....");
|
||||
|
||||
if (!transparent) {
|
||||
for (i = firstPalEntry; i <= lastPalEntry; ++i) {
|
||||
|
||||
// calculate deltas for RGB's and put them in frac16 format
|
||||
dr = (targetColor.r - _G(master_palette)[i].r) << 16;
|
||||
dg = (targetColor.g - _G(master_palette)[i].g) << 16;
|
||||
db = (targetColor.b - _G(master_palette)[i].b) << 16;
|
||||
|
||||
// new = orig + (delta * percent)
|
||||
r = _G(master_palette)[i].r + (MulSF16(percent, dr) >> 16);
|
||||
g = _G(master_palette)[i].g + (MulSF16(percent, dg) >> 16);
|
||||
b = _G(master_palette)[i].b + (MulSF16(percent, db) >> 16);
|
||||
|
||||
// check for under/overflow
|
||||
if (r > 255) r = 255; if (r < 0) r = 0;
|
||||
if (g > 255) g = 255; if (g < 0) g = 0;
|
||||
if (b > 255) b = 255; if (b < 0) b = 0;
|
||||
|
||||
color.r = (byte)r;
|
||||
color.g = (byte)g;
|
||||
color.b = (byte)b;
|
||||
|
||||
gr_pal_set_entry(i, &color); // set the new colour to the DAC
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// This is for filtering colors. For example, a completely red filter
|
||||
// (255, 0, 0) will block out the blue and green parts of the palette.
|
||||
// 50% of the same filter will block out only 50% of the blue and
|
||||
// green, but leaving all of the rest blue.
|
||||
for (i = firstPalEntry; i <= lastPalEntry; ++i) {
|
||||
|
||||
// Converting rgb to a frac16 ( << 16) dividing by 256 ( >> 8)
|
||||
// (the range of the palette values)
|
||||
percent_r = (targetColor.r) << 8;
|
||||
percent_g = (targetColor.g) << 8;
|
||||
percent_b = (targetColor.b) << 8;
|
||||
|
||||
// This is the difference between the color and the full effect
|
||||
// of the filter at 100%, as a frac16.
|
||||
dr = (_G(master_palette)[i].r << 16) - (MulSF16(percent_r, _G(master_palette)[i].r << 16));
|
||||
dg = (_G(master_palette)[i].g << 16) - (MulSF16(percent_g, _G(master_palette)[i].g << 16));
|
||||
db = (_G(master_palette)[i].b << 16) - (MulSF16(percent_b, _G(master_palette)[i].b << 16));
|
||||
|
||||
// Scaling the effect to the right percentage. This is a frac16.
|
||||
dr = MulSF16(dr, percent);
|
||||
dg = MulSF16(dg, percent);
|
||||
db = MulSF16(db, percent);
|
||||
|
||||
// Subtract the result to palette.
|
||||
r = (_G(master_palette)[i].r - (dr >> 16));
|
||||
g = (_G(master_palette)[i].g - (dg >> 16));
|
||||
b = (_G(master_palette)[i].b - (db >> 16));
|
||||
|
||||
// check for under/overflow
|
||||
if (r > 255) r = 255; if (r < 0) r = 0;
|
||||
if (g > 255) g = 255; if (g < 0) g = 0;
|
||||
if (b > 255) b = 255; if (b < 0) b = 0;
|
||||
|
||||
color.r = (byte)r;
|
||||
color.g = (byte)g;
|
||||
color.b = (byte)b;
|
||||
|
||||
gr_pal_set_entry(i, &color); // Set new colors to DAC.
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void DAC_restore() {
|
||||
term_message("DAC restored");//debug
|
||||
gr_pal_set_range(&_G(master_palette)[0], 0, 256);
|
||||
}
|
||||
|
||||
} // namespace M4
|
||||
|
@ -23,9 +23,85 @@
|
||||
#define M4_GRAPHICS_KRN_PAL_H
|
||||
|
||||
#include "m4/m4_types.h"
|
||||
#include "m4/adv_r/adv_hotspot.h"
|
||||
#include "m4/wscript/ws_machine.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
#define TO_GREY (int32)0
|
||||
#define TO_COLOR (int32)1
|
||||
#define TO_BLACK (int32)2
|
||||
|
||||
struct KernelPal_Globals {
|
||||
RGB8 _myFXPalette[256];
|
||||
|
||||
bool _myCycleReq = false;
|
||||
bool _myCycleFinished = true;
|
||||
bool _myCycleDACrefresh = false;
|
||||
int32 _myCycleDelayTicks = 6; // 10 times a second
|
||||
int32 _myCycleStartTime = 0;
|
||||
int32 _myCycleEndTime = 0;
|
||||
int32 _myCycleEndDelayTime = 0;
|
||||
int32 _myCycleStartIndex;
|
||||
int32 _myCycleEndIndex;
|
||||
uint32 _myCycleTrigger = 0;
|
||||
int32 _myCycleNeverStopCycling = false;
|
||||
|
||||
bool _myFadeReq = false;
|
||||
bool _myFadeFinished = true;
|
||||
bool _myFadeDACrefresh = false;
|
||||
int32 _myFadeDelayTicks = 3; // 20 times a second
|
||||
int32 _myFadeStartTime = 0;
|
||||
int32 _myFadeEndTime = 0;
|
||||
int32 _myFadeEndDelayTime = 0;
|
||||
int32 _myFadeStartIndex = 0;
|
||||
int32 _myFadeEndIndex = 0;
|
||||
uint32 _myFadeTrigger = 0;
|
||||
frac16 _myFadeStartPercentFrac = 0x10000;
|
||||
frac16 _myFadeCurrPercentFrac = 0x10000;
|
||||
frac16 _myFadePercentFrac = 0;
|
||||
|
||||
HotSpotRec *_exam_saved_hotspots = nullptr;
|
||||
|
||||
RGB8 *_fadeToMe = nullptr;
|
||||
RGB8 *_trick = nullptr;
|
||||
RGB8 *_picPal = nullptr;
|
||||
int32 _seriesHash = 0;
|
||||
machine *_seriesAnim8 = nullptr;
|
||||
uint8 _translation[32]; // Only 32 greys in ramp
|
||||
|
||||
int32 _colorAreaX1 = -1;
|
||||
int32 _colorAreaY1 = -1;
|
||||
int32 _colorAreaX2 = -1;
|
||||
int32 _colorAreaY2 = -1;
|
||||
|
||||
int32 _greyAreaX1 = -1;
|
||||
int32 _greyAreaY1 = -1;
|
||||
int32 _greyAreaX2 = -1;
|
||||
int32 _greyAreaY2 = -1;
|
||||
|
||||
bool _greyVideoMode = false;
|
||||
};
|
||||
|
||||
extern void pal_fade_set_start(RGB8 *origPalette, int32 percent);
|
||||
extern void pal_fade_init(RGB8 *origPalette, int32 firstPalEntry, int32 lastPalEntry, int32 targetPercent, int32 numTicks, uint32 triggerNum);
|
||||
|
||||
extern void pal_cycle_init(int32 firstPalEntry, int32 lastPalEntry, int32 delayTicks, int32 totalTicks, uint32 triggerNum);
|
||||
extern bool pal_cycle_active(); // Returns true if color cycling is on
|
||||
extern void pal_cycle_stop(); // Stops color cycling
|
||||
extern void pal_cycle_resume(); // Starts color cycling
|
||||
extern void pal_fx_update(); // Handles fading and cycling MattP
|
||||
|
||||
extern void kernel_examine_inventory_object(char *picName, RGB8 *pal, int steps, int delay,
|
||||
int32 x, int32 y, int32 triggerNum, char *digi_name, int32 digi_trigger);
|
||||
extern void kernel_unexamine_inventory_object(RGB8 *pal, int steps, int delay);
|
||||
|
||||
extern void remap_buffer_with_luminance_map(Buffer *src, int32 x1, int32 y1, int32 x2, int32 y2);
|
||||
extern void krn_SetGreyVideoMode(int32 grey_x1, int32 grey_y1, int32 grey_x2, int32 grey_y2, int32 color_x1, int32 color_y1, int32 color_x2, int32 color_y2);
|
||||
extern void krn_UnsetGreyVideoMode(void);
|
||||
extern bool krn_GetGreyMode(void);
|
||||
extern void krn_UpdateGreyArea(Buffer *greyOutThisBuffer, int32 scrnX, int32 scrnY,
|
||||
int32 greyX1, int32 greyY1, int32 greyX2, int32 greyY2);
|
||||
extern void krn_ChangeBufferLuminance(Buffer *target, int32 percent);
|
||||
|
||||
} // namespace M4
|
||||
|
35
engines/m4/graphics/rend.cpp
Normal file
35
engines/m4/graphics/rend.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
/* 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/textconsole.h"
|
||||
#include "m4/graphics/rend.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
void GetUpdateRectangle(int32 x, int32 y, int32 hot_x, int32 hot_y, int32 scale_x, int32 scale_y, int32 Width, int32 Height, M4Rect *UpdateRect) {
|
||||
error("TODO: GetUpdateRectangle");
|
||||
}
|
||||
|
||||
void render_sprite_to_8BBM(RendGrBuff *Destination, DrawRequestX *dr, RendCell *Frame, M4Rect *ClipRectangle, M4Rect *UpdateRect) {
|
||||
error("TODO: render_sprite_to_8BBM");
|
||||
}
|
||||
|
||||
} // namespace M4
|
68
engines/m4/graphics/rend.h
Normal file
68
engines/m4/graphics/rend.h
Normal file
@ -0,0 +1,68 @@
|
||||
/* 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_GRAPHICS_REND_H
|
||||
#define M4_GRAPHICS_REND_H
|
||||
|
||||
#include "m4/m4_types.h"
|
||||
#include "m4/gui/gui.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
struct RGBcolor {
|
||||
uint8 b, g, r;
|
||||
};
|
||||
|
||||
struct RendGrBuff {
|
||||
uint32 Width;
|
||||
uint32 Height;
|
||||
void *PixMap;
|
||||
};
|
||||
|
||||
struct DrawRequestX {
|
||||
int32 x; // X position relative to GrBuff(0, 0)
|
||||
int32 y; // Y position relative to GrBuff(0, 0)
|
||||
int32 scale_x; // X scale factor (can be negative for reverse draw)
|
||||
int32 scale_y; // Y scale factor (can't be negative)
|
||||
uint8 *depth_map; // Depth code array for destination (doesn't care if srcDepth is 0)
|
||||
RGBcolor *Pal; // Palette for shadow draw (doesn't care if SHADOW bit is not set in Src.encoding)
|
||||
uint8 *ICT; // Inverse Color Table (doesn't care if SHADOW bit is not set in Src.encoding)
|
||||
uint8 depth; // Depth code for source (0 if no depth processing)
|
||||
};
|
||||
|
||||
struct RendCell {
|
||||
uint32 Pack;
|
||||
uint32 Stream;
|
||||
long hot_x;
|
||||
long hot_y;
|
||||
uint32 Width;
|
||||
uint32 Height;
|
||||
uint32 Comp;
|
||||
uint32 Reserved[8];
|
||||
uint8 *data;
|
||||
};
|
||||
|
||||
extern void GetUpdateRectangle(int32 x, int32 y, int32 hot_x, int32 hot_y, int32 scale_x, int32 scale_y, int32 Width, int32 Height, M4Rect *UpdateRect);
|
||||
extern void render_sprite_to_8BBM(RendGrBuff *Destination, DrawRequestX *dr, RendCell *Frame, M4Rect *ClipRectangle, M4Rect *UpdateRect);
|
||||
|
||||
} // namespace M4
|
||||
|
||||
#endif
|
@ -29,8 +29,8 @@
|
||||
namespace M4 {
|
||||
|
||||
struct M4sprite {
|
||||
struct M4sprite *next;
|
||||
struct M4sprite *prev;
|
||||
M4sprite *next;
|
||||
M4sprite *prev;
|
||||
int32 x;
|
||||
int32 y;
|
||||
int32 w;
|
||||
@ -39,7 +39,7 @@ struct M4sprite {
|
||||
int32 yOffset;
|
||||
uint8 encoding;
|
||||
uint8 *data;
|
||||
Handle sourceHandle;
|
||||
MemHandle sourceHandle;
|
||||
int32 sourceOffset;
|
||||
};
|
||||
|
||||
@ -60,7 +60,7 @@ struct RectList {
|
||||
};
|
||||
|
||||
struct matte {
|
||||
struct matte *nextMatte;
|
||||
matte *nextMatte;
|
||||
void *myScreen;
|
||||
int32 x1;
|
||||
int32 y1;
|
||||
|
@ -26,6 +26,8 @@
|
||||
|
||||
namespace M4 {
|
||||
|
||||
#define MAX_STRING_SIZE 144
|
||||
#define MAX_STRING_LEN 144
|
||||
#define MAX_FILENAME_SIZE 144
|
||||
#define MIN_VIDEO_X 0
|
||||
#define MIN_VIDEO_Y 0
|
||||
|
@ -51,4 +51,8 @@ void DisposeHandle(MemHandle handle) {
|
||||
free(handle);
|
||||
}
|
||||
|
||||
uint32 MaxMem(Size *growBytes) {
|
||||
return 7999999;
|
||||
}
|
||||
|
||||
} // namespace M4
|
||||
|
@ -28,6 +28,7 @@
|
||||
namespace M4 {
|
||||
|
||||
typedef void **MemHandle;
|
||||
typedef int32 Size;
|
||||
|
||||
inline void HLock(Handle h) {}
|
||||
inline void HUnLock(Handle h) {}
|
||||
@ -42,6 +43,7 @@ extern MemHandle MakeNewHandle(size_t size, const Common::String &);
|
||||
extern bool mem_ReallocateHandle(MemHandle h, size_t size, const Common::String &name);
|
||||
extern MemHandle NewHandle(size_t size, const Common::String &);
|
||||
extern void DisposeHandle(MemHandle handle);
|
||||
extern uint32 MaxMem(Size *growBytes);
|
||||
|
||||
} // namespace M4
|
||||
|
||||
|
@ -29,6 +29,7 @@ MODULE_OBJS = \
|
||||
core/param.o \
|
||||
core/rooms.o \
|
||||
core/term.o \
|
||||
dbg/dbg_wscript.o \
|
||||
events/mickey.o \
|
||||
events/mouse_handler.o \
|
||||
fileio/extensions.o \
|
||||
@ -45,6 +46,7 @@ MODULE_OBJS = \
|
||||
graphics/gr_series.o \
|
||||
graphics/graphics.o \
|
||||
graphics/krn_pal.o \
|
||||
graphics/rend.o \
|
||||
gui/gui_buffer.o \
|
||||
gui/gui_dialog.o \
|
||||
gui/gui_item.o \
|
||||
@ -69,6 +71,7 @@ MODULE_OBJS = \
|
||||
wscript/ws_machine.o \
|
||||
wscript/ws_timer.o \
|
||||
wscript/wscript.o \
|
||||
wscript/wst_regs.o \
|
||||
burger/gui/game_menu.o \
|
||||
burger/gui/gui_cheapo.o \
|
||||
burger/gui/interface.o \
|
||||
|
@ -52,5 +52,36 @@ void Digi::unload(const Common::String &name) {
|
||||
warning("TODO: Digi::unload");
|
||||
}
|
||||
|
||||
void Digi::task() {
|
||||
warning("TODO: Digi::task");
|
||||
}
|
||||
|
||||
int32 Digi::play(const char *name, int32 channel, int32 vol, int32 trigger, int32 room_num) {
|
||||
error("TODO: Digi::play");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32 Digi::play_loop(const char *name, int32 channel, int32 vol, int32 trigger, int32 room_num) {
|
||||
error("TODO: Digi::play_loop");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Digi::read_another_chunk() {
|
||||
warning("TODO: Digi::read_another_chunk");
|
||||
}
|
||||
|
||||
} // namespace Sound
|
||||
|
||||
int32 digi_play(const char *name, int32 channel, int32 vol, int32 trigger, int32 room_num) {
|
||||
return _G(digi).play(name, channel, vol, trigger, room_num);
|
||||
}
|
||||
|
||||
int32 digi_play_loop(const char *name, int32 channel, int32 vol, int32 trigger, int32 room_num) {
|
||||
return _G(digi).play_loop(name, channel, vol, trigger, room_num);
|
||||
}
|
||||
|
||||
void digi_read_another_chunk() {
|
||||
return _G(digi).read_another_chunk();
|
||||
}
|
||||
|
||||
} // namespace M4
|
||||
|
@ -40,9 +40,27 @@ private:
|
||||
public:
|
||||
void preload_sounds(const char **names);
|
||||
void unload_sounds();
|
||||
void task();
|
||||
|
||||
// digi_play and digi_play_loop play a particular sound file in a given channel,
|
||||
// at a particular volume. The room_num parameter tells us what directory the sound
|
||||
// is stored in (all sounds are AIFFs). Trigger is an integer that is fed into
|
||||
// kernel_dispatch_trigger when the sound has finished playing
|
||||
// If the sound has been preloaded it will be played from memory, otherwise it will
|
||||
// be streamed from disk
|
||||
|
||||
int32 play(const char *name, int32 channel, int32 vol, int32 trigger, int32 room_num = -1);
|
||||
int32 play_loop(const char *name, int32 channel, int32 vol, int32 trigger, int32 room_num = -1);
|
||||
|
||||
void read_another_chunk();
|
||||
};
|
||||
|
||||
} // namespace Sound
|
||||
|
||||
extern int32 digi_play(const char *name, int32 channel, int32 vol, int32 trigger, int32 room_num = -1);
|
||||
extern int32 digi_play_loop(const char *name, int32 channel, int32 vol, int32 trigger, int32 room_num = -1);
|
||||
extern void digi_read_another_chunk();
|
||||
|
||||
} // namespace M4
|
||||
|
||||
#endif
|
||||
|
@ -25,5 +25,18 @@
|
||||
namespace M4 {
|
||||
namespace Sound {
|
||||
|
||||
void Midi::task() {
|
||||
warning("TODO: Midi::task");
|
||||
}
|
||||
|
||||
void Midi::loop() {
|
||||
warning("TODO: Midi::loop");
|
||||
}
|
||||
|
||||
} // namespace Sound
|
||||
|
||||
void midi_loop() {
|
||||
_G(midi).loop();
|
||||
}
|
||||
|
||||
} // namespace M4
|
||||
|
@ -30,9 +30,14 @@ namespace Sound {
|
||||
|
||||
class Midi {
|
||||
public:
|
||||
void task();
|
||||
void loop();
|
||||
};
|
||||
|
||||
} // namespace Sound
|
||||
|
||||
extern void midi_loop();
|
||||
|
||||
} // namespace M4
|
||||
|
||||
#endif
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "m4/adv_r/adv.h"
|
||||
#include "m4/adv_r/adv_been.h"
|
||||
#include "m4/core/errors.h"
|
||||
#include "m4/dbg/debug.h"
|
||||
#include "m4/graphics/gr_pal.h"
|
||||
#include "m4/gui/gui_buffer.h"
|
||||
#include "m4/gui/gui_dialog.h"
|
||||
@ -47,6 +48,7 @@ Vars::~Vars() {
|
||||
game_systems_shutdown();
|
||||
|
||||
sysfile_shutdown();
|
||||
f_stream_Shutdown();
|
||||
player_been_shutdown();
|
||||
gui_system_shutdown();
|
||||
gui_buffer_system_shutdown();
|
||||
@ -54,6 +56,7 @@ Vars::~Vars() {
|
||||
mem_stash_shutdown();
|
||||
param_shutdown();
|
||||
woodscript_shutdown();
|
||||
dbg_ws_shutdown();
|
||||
|
||||
g_vars = nullptr;
|
||||
}
|
||||
@ -80,6 +83,14 @@ bool Vars::init() {
|
||||
if (!LoadWSAssets("stream script", &_master_palette[0]))
|
||||
error_show(FL, 'FNF!', "stream script");
|
||||
|
||||
grab_fonts();
|
||||
gr_font_set(_font_inter);
|
||||
|
||||
if (_cheat_keys_enabled) {
|
||||
if (!dbg_ws_init(_kernel.start_up_with_dbg_ws, _font_tiny_prop, _globals))
|
||||
error(FL, 'DWIF');
|
||||
}
|
||||
|
||||
main_cold_data_init();
|
||||
create_mouse_watch_dialog();
|
||||
global_menu_system_init();
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "m4/fileio/sys_file.h"
|
||||
#include "m4/graphics/gr_color.h"
|
||||
#include "m4/graphics/gr_font.h"
|
||||
#include "m4/graphics/krn_pal.h"
|
||||
#include "m4/gui/gui_dialog.h"
|
||||
#include "m4/gui/gui_item.h"
|
||||
#include "m4/gui/gui_mouse.h"
|
||||
@ -61,7 +62,7 @@ class Vars;
|
||||
|
||||
extern Vars *g_vars;
|
||||
|
||||
class Vars : public Mouse_Globals, public WS_Globals, public Timer_Globals {
|
||||
class Vars : public Mouse_Globals, public Timer_Globals {
|
||||
private:
|
||||
void game_systems_initialize(byte flags);
|
||||
void game_systems_shutdown();
|
||||
@ -101,9 +102,11 @@ public:
|
||||
Dialog_Globals _dialog;
|
||||
Item_Globals _items;
|
||||
Converstation_Globals _conversations;
|
||||
WS_Globals _ws;
|
||||
Triggers _triggers;
|
||||
Sound::Digi _digi;
|
||||
Sound::Midi _midi;
|
||||
KernelPal_Globals _krnPal;
|
||||
|
||||
bool _cheating_enabled = false;
|
||||
bool _cheat_keys_enabled = false;
|
||||
@ -173,6 +176,7 @@ public:
|
||||
#define _GV() (*g_vars->getGlobals())
|
||||
#define _GI() (*g_vars->getInterface())
|
||||
#define _GW() (*g_vars->getWalker())
|
||||
#define _GWS(X) _G(ws)._##X
|
||||
|
||||
} // namespace M4
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -28,6 +28,38 @@
|
||||
|
||||
namespace M4 {
|
||||
|
||||
#define OP_INSTR 0xfe000000
|
||||
#define OP_FORMAT1 0x01c00000
|
||||
#define OP_FORMAT2 0x00380000
|
||||
#define OP_FORMAT3 0x00070000
|
||||
#define OP_HIGH_DATA 0xffff0000
|
||||
#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;
|
||||
@ -70,10 +102,29 @@ struct WSCruncher_Globals {
|
||||
};
|
||||
|
||||
extern int32 *ws_GetDataFormats();
|
||||
|
||||
extern bool ws_InitCruncher();
|
||||
extern void ws_KillCruncher();
|
||||
|
||||
extern Anim8 *ws_AddAnim8ToCruncher(machine *m, int32 sequHash);
|
||||
|
||||
/**
|
||||
* This procedure assumes a machine has a slot with it's own memory
|
||||
*/
|
||||
extern bool ws_ChangeAnim8Program(machine *m, int32 newSequHash);
|
||||
|
||||
/**
|
||||
* This procedure flags the anim8 slot as empty
|
||||
*/
|
||||
extern void ws_RemoveAnim8FromCruncher(Anim8 *myAnim8);
|
||||
|
||||
extern bool ws_PauseAnim8(Anim8 *myAnim8);
|
||||
extern bool ws_ResumeAnim8(Anim8 *myAnim8);
|
||||
extern int32 ws_PreProcessPcode(uint32 **PC, Anim8 *myAnim8);
|
||||
extern void ws_CrunchAnim8s(int16 *depth_table);
|
||||
extern void ws_CrunchEOSreqs();
|
||||
extern bool ws_OnEndSeqRequest(Anim8 *myAnim8, int32 pcOffset, int32 pcCount);
|
||||
extern void ws_CancelOnEndSeq(Anim8 *myAnim8);
|
||||
|
||||
} // End of namespace M4
|
||||
|
||||
#endif
|
||||
|
@ -19,34 +19,454 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#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/rend.h"
|
||||
#include "m4/gui/gui_vmng.h"
|
||||
#include "m4/vars.h"
|
||||
#include "m4/m4.h"
|
||||
|
||||
namespace M4 {
|
||||
|
||||
bool ws_InitHAL() {
|
||||
_G(deadRectList) = NULL;
|
||||
_GWS(deadRectList) = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ws_KillHAL() {
|
||||
vmng_DisposeRectList(&_G(deadRectList));
|
||||
vmng_DisposeRectList(&_GWS(deadRectList));
|
||||
}
|
||||
|
||||
void ws_DumpMachine(machine *m, Common::WriteStream *logFile) {
|
||||
Anim8 *myAnim8;
|
||||
CCB *myCCB;
|
||||
frac16 *myRegs;
|
||||
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: %ld\n\tAddress: 0x%08lx\n\n", m->machName, m->myHash, (int32)m));
|
||||
|
||||
// If we have an anim8 for this machine
|
||||
if (m->myAnim8) {
|
||||
myAnim8 = m->myAnim8;
|
||||
|
||||
// Print out the anim8 hash, and physical address
|
||||
logFile->writeString(Common::String::format("Sequence Hash: %ld\n\tAddress: 0x%08lx\n\n", myAnim8->sequHash, (int32)myAnim8));
|
||||
|
||||
// And if this anim8 has registers
|
||||
if (myAnim8->myRegs) {
|
||||
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%ld\t%s:\t\t%.2f\t\t0x%08lx\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%ld\tlocal.%ld:\t\t%.2f\t\t0x%08lx\n", i, i - IDX_COUNT, tempFloat, myRegs[i]));
|
||||
}
|
||||
}
|
||||
logFile->writeString(Common::String::format("\n"));
|
||||
}
|
||||
|
||||
// If this anim8 has a CCB
|
||||
if (myAnim8->myCCB) {
|
||||
myCCB = myAnim8->myCCB;
|
||||
|
||||
logFile->writeString(Common::String::format("Sprite Series Name: %s\tAddress:0x%08lx\tFlags0x%08lx\n", myCCB->seriesName, (uint32)myCCB, myCCB->flags));
|
||||
logFile->writeString(Common::String::format("\tCurrent Location: (%ld, %ld), (%ld, %ld)\n", myCCB->currLocation->x1, myCCB->currLocation->y1,
|
||||
myCCB->currLocation->x2, myCCB->currLocation->y2));
|
||||
logFile->writeString(Common::String::format("\tNew Location: (%ld, %ld), (%ld, %ld)\n", myCCB->newLocation->x1, myCCB->newLocation->y1,
|
||||
myCCB->newLocation->x2, myCCB->newLocation->y2));
|
||||
logFile->writeString(Common::String::format("\tscale: %ld\n", myCCB->scaleX));
|
||||
logFile->writeString(Common::String::format("\tlayer: %ld\n", myCCB->layer));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ws_Error(machine *m, int32 errorType, trigraph errorCode, const char *errMsg) {
|
||||
Common::OutSaveFile *logFile;
|
||||
char description[MAX_STRING_SIZE];
|
||||
|
||||
// Find the error description
|
||||
error_look_up(errorCode, description);
|
||||
|
||||
// Open the logFile
|
||||
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(char *sourceFile, int32 lineNum, const char *fmt, ...) {
|
||||
Common::OutSaveFile *logFile;
|
||||
Common::String msgBuff;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
msgBuff == Common::String::vformat(fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
logFile = g_system->getSavefileManager()->openForSaving("ws_mach.log");
|
||||
if (logFile) {
|
||||
logFile->writeString(Common::String::format("Source Code Index: %s:%ld\n", sourceFile, lineNum));
|
||||
logFile->writeString(Common::String::format("%s\n\n", msgBuff.c_str()));
|
||||
|
||||
logFile->finalize();
|
||||
delete logFile;
|
||||
}
|
||||
|
||||
term_message("Source Code Index: %s:%ld", sourceFile, lineNum);
|
||||
term_message("%s", msgBuff.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"));
|
||||
}
|
||||
|
||||
void DrawSprite(CCB *myCCB, Anim8 *myAnim8, Buffer *halScrnBuf, GrBuff *screenCodeBuff, uint8 *myPalette, uint8 *ICT,
|
||||
M4Rect *clipRect, M4Rect *updateRect) {
|
||||
#ifdef TODO
|
||||
M4sprite *source;
|
||||
|
||||
// Temporary var to prevent excessive dereferences
|
||||
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 *)((int32) * (source->sourceHandle) + source->sourceOffset);
|
||||
}
|
||||
|
||||
RendGrBuff Destination;
|
||||
DrawRequestX dr;
|
||||
RendCell Frame;
|
||||
|
||||
Destination.Width = halScrnBuf->stride;
|
||||
Destination.Height = halScrnBuf->h;
|
||||
Destination.PixMap = (void *)halScrnBuf->data;
|
||||
|
||||
dr.x = myAnim8->myRegs[IDX_X] >> 16;
|
||||
dr.y = myAnim8->myRegs[IDX_Y] >> 16;
|
||||
dr.scale_x = myCCB->scaleX;
|
||||
dr.scale_y = myCCB->scaleY;
|
||||
dr.depth_map = screenCodeBuff->data;
|
||||
dr.Pal = (RGBcolor *)myPalette;
|
||||
dr.ICT = ICT;
|
||||
dr.depth = myCCB->layer >> 8;
|
||||
|
||||
Frame.hot_x = myCCB->source->xOffset;
|
||||
Frame.hot_y = myCCB->source->yOffset;
|
||||
Frame.Width = source->w;
|
||||
Frame.Height = source->h;
|
||||
if ((!myPalette) || (!ICT)) {
|
||||
Frame.Comp = (uint32)(source->encoding & 0x7f);
|
||||
} else {
|
||||
Frame.Comp = (uint32)source->encoding;
|
||||
}
|
||||
Frame.data = source->data;
|
||||
|
||||
// And draw the sprite
|
||||
render_sprite_to_8BBM(&Destination, &dr, &Frame, clipRect, updateRect);
|
||||
myCCB->flags &= ~CCB_REDRAW;
|
||||
|
||||
if (!(myCCB->flags & CCB_DISC_STREAM)) {
|
||||
//unlock the sprite's handle
|
||||
HUnLock(source->sourceHandle);
|
||||
}
|
||||
|
||||
#else
|
||||
error("TODO: DrawSprite");
|
||||
#endif
|
||||
}
|
||||
|
||||
void ws_DoDisplay(Buffer *background, int16 *depth_table, GrBuff *screenCodeBuff,
|
||||
uint8 *myPalette, uint8 *ICT, bool updateVideo) {
|
||||
CCB *myCCB;
|
||||
ScreenContext *myScreen;
|
||||
RectList *myRect;
|
||||
RectList *drawRectList = nullptr;
|
||||
int32 status, scrnX1, scrnY1;
|
||||
int32 restoreBgndX1, restoreBgndY1, restoreBgndX2, restoreBgndY2;
|
||||
Anim8 *myAnim8;
|
||||
M4Rect *currRect, intersectRect, noClipRect, dummyRect;
|
||||
bool greyMode;
|
||||
#ifdef TODO
|
||||
Buffer drawSpriteBuff;
|
||||
bool finished;
|
||||
M4sprite *source;
|
||||
uint8 myDepth;
|
||||
M4Rect *newRect;
|
||||
DrawRequest spriteDrawReq;
|
||||
#endif
|
||||
|
||||
if (((myScreen = vmng_screen_find(_G(gameDrawBuff), &status)) == nullptr) || (status != SCRN_ACTIVE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Buffer *halScrnBuf = _G(gameDrawBuff)->get_buffer();
|
||||
noClipRect.x1 = 0;
|
||||
noClipRect.y1 = 0;
|
||||
noClipRect.x2 = halScrnBuf->W - 1;
|
||||
noClipRect.y2 = halScrnBuf->h - 1;
|
||||
|
||||
scrnX1 = myScreen->x1;
|
||||
scrnY1 = myScreen->y1;
|
||||
|
||||
greyMode = krn_GetGreyMode();
|
||||
|
||||
// Intialize the drawRectList to the deadRectList
|
||||
drawRectList = _GWS(deadRectList);
|
||||
_GWS(deadRectList) = nullptr;
|
||||
|
||||
// The drawRectList already 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 (background && 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;
|
||||
currRect = myCCB->currLocation;
|
||||
if (myCCB && myCCB->source && (!(myCCB->flags & CCB_NO_DRAW))) {
|
||||
if (myCCB->flags & CCB_REDRAW) {
|
||||
|
||||
// Draw the sprite
|
||||
DrawSprite(myCCB, myAnim8, halScrnBuf, screenCodeBuff, myPalette, ICT, &noClipRect, currRect);
|
||||
|
||||
// Add it's new location to the update list
|
||||
vmng_AddRectToRectList(&drawRectList, currRect->x1, currRect->y1, currRect->x2, currRect->y2);
|
||||
} else {
|
||||
|
||||
// Loop through the update list, intersect each rect with the sprites
|
||||
// current location, and update redraw all overlapping areas
|
||||
myRect = drawRectList;
|
||||
while (myRect) {
|
||||
intersectRect.x1 = imath_max(myRect->x1, currRect->x1);
|
||||
intersectRect.y1 = imath_max(myRect->y1, currRect->y1);
|
||||
intersectRect.x2 = imath_min(myRect->x2, currRect->x2);
|
||||
intersectRect.y2 = imath_min(myRect->y2, currRect->y2);
|
||||
|
||||
// Now see if there was an intersection
|
||||
if ((intersectRect.x1 <= intersectRect.x2) && (intersectRect.y1 <= intersectRect.y2)) {
|
||||
// Draw just the intersected region
|
||||
DrawSprite(myCCB, myAnim8, halScrnBuf, screenCodeBuff, myPalette, ICT, &intersectRect, &dummyRect);
|
||||
}
|
||||
|
||||
// Next rect
|
||||
myRect = myRect->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
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, GrBuff *screenCodes, uint8 *myPalette, uint8 *ICT) {
|
||||
error("TODO: ws_hal_RefreshWoodscriptBuffer");
|
||||
}
|
||||
|
||||
void GetBezCoeffs(frac16 *ctrlPoints, frac16 *coeffs) {
|
||||
frac16 x0, x0mult3, x1mult3, x1mult6, x2mult3, x3;
|
||||
frac16 y0, y0mult3, y1mult3, y1mult6, y2mult3, y3;
|
||||
|
||||
x0 = ctrlPoints[0];
|
||||
x0mult3 = (x0 << 1) + x0;
|
||||
x1mult3 = (ctrlPoints[2] << 1) + ctrlPoints[2];
|
||||
x1mult6 = x1mult3 << 1;
|
||||
x2mult3 = (ctrlPoints[4] << 1) + ctrlPoints[4];
|
||||
x3 = ctrlPoints[6];
|
||||
|
||||
y0 = ctrlPoints[1];
|
||||
y0mult3 = (y0 << 1) + y0;
|
||||
y1mult3 = (ctrlPoints[3] << 1) + ctrlPoints[3];
|
||||
y1mult6 = y1mult3 << 1;
|
||||
y2mult3 = (ctrlPoints[5] << 1) + ctrlPoints[5];
|
||||
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])))));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
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) {
|
||||
error("TODO: KillCCB");
|
||||
#ifdef TODO
|
||||
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(&_G(deadRectList), myCCB->maxArea->x1, myCCB->maxArea->y1,
|
||||
vmng_AddRectToRectList(&_GWS(deadRectList), myCCB->maxArea->x1, myCCB->maxArea->y1,
|
||||
myCCB->maxArea->x2, myCCB->maxArea->y2);
|
||||
} else {
|
||||
vmng_AddRectToRectList(&_G(deadRectList), myCCB->currLocation->x1, myCCB->currLocation->y1,
|
||||
vmng_AddRectToRectList(&_GWS(deadRectList), myCCB->currLocation->x1, myCCB->currLocation->y1,
|
||||
myCCB->currLocation->x2, myCCB->currLocation->y2);
|
||||
}
|
||||
}
|
||||
@ -54,19 +474,83 @@ void KillCCB(CCB *myCCB, bool restoreFlag) {
|
||||
ws_CloseSSstream(myCCB);
|
||||
}
|
||||
if (myCCB->currLocation) {
|
||||
mem_free((void *)myCCB->currLocation);
|
||||
mem_free(myCCB->currLocation);
|
||||
}
|
||||
if (myCCB->newLocation) {
|
||||
mem_free((void *)myCCB->newLocation);
|
||||
mem_free(myCCB->newLocation);
|
||||
}
|
||||
if (myCCB->maxArea) {
|
||||
mem_free((void *)myCCB->maxArea);
|
||||
mem_free(myCCB->maxArea);
|
||||
}
|
||||
if (myCCB->source) {
|
||||
mem_free((char *)myCCB->source);
|
||||
mem_free(myCCB->source);
|
||||
}
|
||||
mem_free((void *)myCCB);
|
||||
#endif
|
||||
|
||||
mem_free(myCCB);
|
||||
}
|
||||
|
||||
void Cel_msr(Anim8 *myAnim8) {
|
||||
CCB *myCCB;
|
||||
frac16 *myRegs;
|
||||
int32 scaler;
|
||||
|
||||
if (!myAnim8) {
|
||||
error_show(FL, 'WSAI');
|
||||
}
|
||||
|
||||
myCCB = myAnim8->myCCB;
|
||||
if ((!myCCB) || (!myCCB->source)) {
|
||||
error_show(FL, 'WSIC');
|
||||
}
|
||||
|
||||
if ((myCCB->source->w == 0) || (myCCB->source->h == 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
myRegs = myAnim8->myRegs;
|
||||
if (!myRegs) {
|
||||
error_show(FL, 'WSAI');
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -24,17 +24,47 @@
|
||||
#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;
|
||||
int32 _pcOffsetOld;
|
||||
};
|
||||
|
||||
extern bool ws_InitHAL();
|
||||
extern void ws_KillHAL();
|
||||
|
||||
extern void ws_DoDisplay(Buffer *background, int16 *depth_table, GrBuff *screenCodeBuff,
|
||||
uint8 *myPalette, uint8 *ICT, bool updateVideo);
|
||||
extern void ws_hal_RefreshWoodscriptBuffer(cruncher *myCruncher, Buffer *background, int16 *depth_table, GrBuff *screenCodes, uint8 *myPalette, uint8 *ICT);
|
||||
extern void GetBezCoeffs(frac16 *ctrlPoints, frac16 *coeffs);
|
||||
extern void GetBezPoint(frac16 *x, frac16 *y, frac16 *coeffs, frac16 tVal);
|
||||
extern bool InitCCB(CCB *myCCB);
|
||||
extern void HideCCB(CCB *myCCB);
|
||||
extern void ShowCCB(CCB *myCCB);
|
||||
//extern void SetLastCCB(CCB *myCCB);
|
||||
extern void MoveCCB(CCB *myCCB, frac16 deltaX, frac16 deltaY);
|
||||
extern void KillCCB(CCB *myCCB, bool restoreFlag);
|
||||
extern void Cel_msr(Anim8 *myAnim8);
|
||||
extern void ws_OverrideCrunchTime(machine *m);
|
||||
|
||||
extern bool CheckAddr();
|
||||
extern void ws_Error(machine *m, int32 errorType, quadchar errorCode, const char *errMsg);
|
||||
extern void ws_DumpMachine(machine *m);
|
||||
extern void ws_LogErrorMsg(char *sourceFile, int32 lineNum, char *fmt, ...);
|
||||
|
||||
} // End of namespace M4
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -66,13 +66,13 @@ struct WSLoad_Globals {
|
||||
char **_globalDATAnames = nullptr;
|
||||
char **_globalCELSnames = nullptr;
|
||||
|
||||
Handle *_globalMACHHandles = nullptr;
|
||||
MemHandle *_globalMACHHandles = nullptr;
|
||||
int32 *_globalMACHoffsets = nullptr;
|
||||
Handle *_globalSEQUHandles = nullptr;
|
||||
MemHandle *_globalSEQUHandles = nullptr;
|
||||
int32 *_globalSEQUoffsets = nullptr;
|
||||
Handle *_globalDATAHandles = nullptr;
|
||||
MemHandle *_globalDATAHandles = nullptr;
|
||||
int32 *_globalDATAoffsets = nullptr;
|
||||
Handle *_globalCELSHandles = nullptr;
|
||||
MemHandle *_globalCELSHandles = nullptr;
|
||||
int32 *_globalCELSoffsets = nullptr;
|
||||
int32 *_globalCELSPaloffsets = nullptr;
|
||||
};
|
||||
@ -81,20 +81,19 @@ extern bool InitWSAssets();
|
||||
extern bool ClearWSAssets(uint32 assetType, int32 minHash, int32 maxHash);
|
||||
extern void ShutdownWSAssets();
|
||||
|
||||
extern bool ws_CELSIntegrity(int32 minHash, int32 maxHash);
|
||||
extern bool LoadWSAssets(const char *wsAssetName, RGB8 *myPalette);
|
||||
extern int32 AddWSAssetCELS(const char *wsAssetName, int32 hash, RGB8 *myPalette);
|
||||
extern uint32 *FindSpriteSource(uint32 *celsPtr, int32 index);
|
||||
extern M4sprite *GetWSAssetSprite(char *spriteName, uint32 hash, uint32 index, M4sprite *mySprite, bool *streamSeries);
|
||||
|
||||
extern CCB *GetWSAssetCEL(uint32 hash, uint32 index, CCB *myCCB);
|
||||
extern int32 GetWSAssetCELCount(uint32 hash);
|
||||
extern int32 GetWSAssetCELFrameRate(uint32 hash);
|
||||
extern int32 GetWSAssetCELPixSpeed(uint32 hash);
|
||||
extern int32 ws_get_sprite_width(uint32 hash, int32 index);
|
||||
extern int32 ws_get_sprite_height(uint32 hash, int32 index);
|
||||
extern Handle ws_GetSEQU(uint32 hash, int32 *numLocalVars, int32 *offset);
|
||||
extern Handle ws_GetMACH(uint32 hash, int32 *numStates, int32 *stateTableOffset, int32 *machInstrOffset);
|
||||
extern Handle ws_GetDATA(uint32 hash, uint32 index, int32 *rowOffset);
|
||||
extern MemHandle ws_GetSEQU(uint32 hash, int32 *numLocalVars, int32 *offset);
|
||||
extern MemHandle ws_GetMACH(uint32 hash, int32 *numStates, int32 *stateTableOffset, int32 *machInstrOffset);
|
||||
extern MemHandle ws_GetDATA(uint32 hash, uint32 index, int32 *rowOffset);
|
||||
extern int32 ws_GetDATACount(uint32 hash);
|
||||
extern int32 GetSSHeaderInfo(Common::SeekableReadStream *stream, uint32 **data, RGB8 *myPalette);
|
||||
extern bool ws_GetSSMaxWH(MemHandle ssHandle, int32 ssOffset, int32 *maxW, int32 *maxH);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -97,11 +97,11 @@ struct Anim8 {
|
||||
Anim8 *behind = nullptr;
|
||||
Anim8 *myParent = nullptr; // The parent anim8
|
||||
int32 sequHash = 0; // The current sequence Hash = 0;
|
||||
Handle sequHandle = nullptr; // The sequence Handle
|
||||
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
|
||||
Handle dataHandle = nullptr;
|
||||
MemHandle dataHandle = nullptr;
|
||||
int32 dataOffset = 0;
|
||||
int32 startTime = 0;
|
||||
int32 switchTime = 0;
|
||||
@ -125,7 +125,7 @@ struct machine {
|
||||
uint32 myHash = 0;
|
||||
uint32 machID = 0;
|
||||
char *machName = nullptr;
|
||||
Handle machHandle = 0;
|
||||
MemHandle machHandle = 0;
|
||||
int32 machInstrOffset = 0;
|
||||
int32 stateTableOffset = 0;
|
||||
int32 curState = 0;
|
||||
@ -134,7 +134,7 @@ struct machine {
|
||||
Anim8 *myAnim8 = nullptr;
|
||||
Anim8 *parentAnim8 = nullptr;
|
||||
int32 dataHash = 0;
|
||||
Handle dataHandle = 0;
|
||||
MemHandle dataHandle = 0;
|
||||
int32 dataOffset = 0;
|
||||
int32 targetCount = 0;
|
||||
struct machine *msgReplyXM = nullptr;
|
||||
@ -168,11 +168,26 @@ struct WSMachine_Globals {
|
||||
|
||||
// Used for processing pCodes
|
||||
frac16 *_ws_globals = nullptr;
|
||||
void *_addrExists = nullptr;
|
||||
};
|
||||
|
||||
extern bool ws_Initialize(frac16 *theGlobals);
|
||||
extern void ws_Shutdown();
|
||||
extern void TerminateMachinesByHash(int32 machHash);
|
||||
extern void PauseEngines();
|
||||
extern void UnpauseEngines();
|
||||
extern void AddPauseTime(int32 myTime);
|
||||
|
||||
void CycleEngines(Buffer *cleanBackground, int16 *depth_table, GrBuff *screenCodes,
|
||||
uint8 *myPalette, uint8 *ICT, bool updateVideo);
|
||||
void ws_RefreshWoodscriptBuffer(Buffer *cleanBackground, int16 *depth_table, GrBuff *screenCodes, uint8 *myPalette, uint8 *ICT);
|
||||
|
||||
void TerminateMachine(machine *m);
|
||||
void TerminateMachinesByHash(uint32 machHash);
|
||||
bool VerifyMachineExists(machine *m);
|
||||
int32 ws_KillMachines();
|
||||
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);
|
||||
|
||||
/**
|
||||
* This proc is what allows a machine to send a message to another machine(s)
|
||||
@ -180,6 +195,9 @@ extern void TerminateMachinesByHash(int32 machHash);
|
||||
extern void SendWSMessage(uint32 msgHash, frac16 msgValue, machine *recvM,
|
||||
uint32 machHash, machine *sendM, int32 msgCount);
|
||||
|
||||
#define kernel_spawn_machine(name,hash,callback) TriggerMachineByHash(hash, NULL, -1, -1, callback, FALSE, (char*)name)
|
||||
#define kernel_terminate_machine(m) TerminateMachine(m)
|
||||
|
||||
} // End of namespace M4
|
||||
|
||||
#endif
|
||||
|
@ -27,18 +27,18 @@ namespace M4 {
|
||||
static void dispose_timeRequest(onTimeReq *timeReq);
|
||||
|
||||
bool ws_InitWSTimer(void) {
|
||||
_G(firstTimeReq) = nullptr;
|
||||
_GWS(firstTimeReq) = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ws_KillTime() {
|
||||
onTimeReq *tempTime;
|
||||
|
||||
tempTime = _G(firstTimeReq);
|
||||
tempTime = _GWS(firstTimeReq);
|
||||
while (tempTime) {
|
||||
_G(firstTimeReq) = _G(firstTimeReq)->next;
|
||||
_GWS(firstTimeReq) = _GWS(firstTimeReq)->next;
|
||||
dispose_timeRequest(tempTime);
|
||||
tempTime = _G(firstTimeReq);
|
||||
tempTime = _GWS(firstTimeReq);
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,4 +48,17 @@ static void dispose_timeRequest(onTimeReq *timeReq) {
|
||||
}
|
||||
}
|
||||
|
||||
void ws_MakeOnTimeReq(int32 wakeUpTime, machine *myXM, int32 pcOffset, int32 pcCount) {
|
||||
error("TODO: ws_MakeOnTimeReq");
|
||||
}
|
||||
|
||||
void ws_CancelOnTimeReqs(machine *m) {
|
||||
error("TODO: ws_CancelOnTimeReqs");
|
||||
}
|
||||
|
||||
void ws_CheckTimeReqs(int32 curTime) {
|
||||
error("TODO: ws_CheckTimeReqs");
|
||||
}
|
||||
|
||||
|
||||
} // End of namespace M4
|
||||
|
122
engines/m4/wscript/wst_regs.cpp
Normal file
122
engines/m4/wscript/wst_regs.cpp
Normal 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
|
@ -85,9 +85,11 @@ enum {
|
||||
#define TAG_MOVE_CEL 0x00004000
|
||||
#define TAG_MAP_CEL 0x00002000
|
||||
|
||||
extern char *myRegLabels[];
|
||||
extern char *myGlobLabels[];
|
||||
extern char *tagLabels[];
|
||||
#define GLOB_COUNT 39
|
||||
|
||||
extern const char *myRegLabels[];
|
||||
extern const char *myGlobLabels[];
|
||||
extern const char *tagLabels[];
|
||||
|
||||
} // End of namespace M4
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user