mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-23 02:11:38 +00:00
1588 lines
37 KiB
C++
1588 lines
37 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#include "cruise/cruise_main.h"
|
|
#include "cruise/polys.h"
|
|
#include "common/endian.h"
|
|
#include "common/util.h"
|
|
|
|
namespace Cruise {
|
|
|
|
struct autoCellStruct {
|
|
struct autoCellStruct *next;
|
|
short int ovlIdx;
|
|
short int objIdx;
|
|
short int type;
|
|
short int newValue;
|
|
cellStruct *pCell;
|
|
};
|
|
|
|
autoCellStruct autoCellHead;
|
|
|
|
void addAutoCell(int overlayIdx, int idx, int type, int newVal, cellStruct *pObject) {
|
|
autoCellStruct *pNewEntry;
|
|
|
|
pNewEntry = new autoCellStruct;
|
|
|
|
pNewEntry->next = autoCellHead.next;
|
|
autoCellHead.next = pNewEntry;
|
|
|
|
pNewEntry->ovlIdx = overlayIdx;
|
|
pNewEntry->objIdx = idx;
|
|
pNewEntry->type = type;
|
|
pNewEntry->newValue = newVal;
|
|
pNewEntry->pCell = pObject;
|
|
}
|
|
|
|
void freeAutoCell() {
|
|
autoCellStruct *pCurrent = autoCellHead.next;
|
|
|
|
while (pCurrent) {
|
|
autoCellStruct *next = pCurrent->next;
|
|
|
|
if (pCurrent->type == 5) {
|
|
objInit(pCurrent->ovlIdx, pCurrent->objIdx, pCurrent->newValue);
|
|
} else {
|
|
setObjectPosition(pCurrent->ovlIdx, pCurrent->objIdx, pCurrent->type, pCurrent->newValue);
|
|
}
|
|
|
|
if (pCurrent->pCell->animWait < 0) {
|
|
objectParamsQuery params;
|
|
|
|
getMultipleObjectParam(pCurrent->ovlIdx, pCurrent->objIdx, ¶ms);
|
|
|
|
pCurrent->pCell->animCounter = params.state2 - 1;
|
|
}
|
|
|
|
delete pCurrent;
|
|
|
|
pCurrent = next;
|
|
}
|
|
}
|
|
|
|
void calcRGB(uint8* pColorSrc, uint8* pColorDst, int* offsetTable) {
|
|
for (unsigned long int i = 0; i < 3; i++) {
|
|
int color = *(pColorSrc++);
|
|
int offset = offsetTable[i];
|
|
|
|
color += offset;
|
|
if (color < 0)
|
|
color = 0;
|
|
if (color > 0xFF)
|
|
color = 0xFF;
|
|
|
|
*(pColorDst++) = (uint8)color;
|
|
}
|
|
}
|
|
|
|
void fadeIn() {
|
|
for (long int i = 256; i >= 0; i -= 32) {
|
|
for (long int j = 0; j < 256; j++) {
|
|
int offsetTable[3];
|
|
offsetTable[0] = -i;
|
|
offsetTable[1] = -i;
|
|
offsetTable[2] = -i;
|
|
calcRGB(&palScreen[masterScreen][3*j], &workpal[3*j], offsetTable);
|
|
}
|
|
gfxModuleData_setPal256(workpal);
|
|
|
|
gfxModuleData_updatePalette();
|
|
gfxModuleData_updateScreen();
|
|
}
|
|
|
|
for (long int j = 0; j < 256; j++) {
|
|
int offsetTable[3];
|
|
offsetTable[0] = 0;
|
|
offsetTable[1] = 0;
|
|
offsetTable[2] = 0;
|
|
calcRGB(&palScreen[masterScreen][3*j], &workpal[3*j], offsetTable);
|
|
}
|
|
|
|
gfxModuleData_setPal256(workpal);
|
|
|
|
fadeFlag = 0;
|
|
PCFadeFlag = 0;
|
|
}
|
|
|
|
void flipScreen() {
|
|
if (switchPal) {
|
|
for (unsigned long int i = 0; i < 256*3; i++) {
|
|
workpal[i] = palScreen[masterScreen][i];
|
|
}
|
|
switchPal = 0;
|
|
gfxModuleData_setPal256(workpal);
|
|
}
|
|
|
|
SWAP(gfxModuleData.pPage00, gfxModuleData.pPage10);
|
|
|
|
gfxModuleData_flipScreen();
|
|
|
|
if (doFade) {
|
|
fadeIn();
|
|
doFade = 0;
|
|
}
|
|
}
|
|
|
|
int spriteX1;
|
|
int spriteX2;
|
|
int spriteY1;
|
|
int spriteY2;
|
|
|
|
char *polyOutputBuffer;
|
|
|
|
void pixel(int x, int y, char color) {
|
|
if (x >= 0 && x < 320 && y >= 0 && y < 200)
|
|
polyOutputBuffer[320 * y + x] = color;
|
|
}
|
|
|
|
// this function checks if the dataPtr is not 0, else it retrives the data for X, Y, scale and DataPtr again (OLD: mainDrawSub1Sub1)
|
|
void flipPoly(int fileId, int16 *dataPtr, int scale, char** newFrame, int X, int Y, int *outX, int *outY, int *outScale) {
|
|
if (*dataPtr == 0) {
|
|
int16 offset;
|
|
int16 newX;
|
|
int16 newY;
|
|
|
|
dataPtr ++;
|
|
|
|
offset = (int16)READ_BE_UINT16(dataPtr);
|
|
dataPtr++;
|
|
|
|
newX = (int16)READ_BE_UINT16(dataPtr);
|
|
dataPtr++;
|
|
|
|
newY = (int16)READ_BE_UINT16(dataPtr);
|
|
dataPtr++;
|
|
|
|
offset += fileId;
|
|
|
|
if (offset >= 0) {
|
|
if (filesDatabase[offset].resType == OBJ_TYPE_LINE && filesDatabase[offset].subData.ptr) {
|
|
dataPtr = (int16 *)filesDatabase[offset].subData.ptr;
|
|
}
|
|
}
|
|
|
|
scale = -scale;
|
|
X -= newX;
|
|
Y -= newY;
|
|
}
|
|
|
|
*newFrame = (char*)dataPtr;
|
|
*outX = X;
|
|
*outY = Y;
|
|
*outScale = scale;
|
|
}
|
|
|
|
int upscaleValue(int value, int scale) {
|
|
return (((value * scale) << 8) / 2);
|
|
}
|
|
|
|
int m_flipLeftRight;
|
|
int m_useSmallScale;
|
|
int m_lowerX;
|
|
int m_lowerY;
|
|
int m_coordCount;
|
|
int m_first_X;
|
|
int m_first_Y;
|
|
int m_scaleValue;
|
|
int m_color;
|
|
|
|
/*
|
|
FIXME: Whether intentional or not, the game often seems to use negative indexing
|
|
of one or more of the arrays below and expects(?) to end up in the preceding one.
|
|
This "worked" on many platforms so far, but on OSX apparently the buffers don't
|
|
occupy contiguous memory, and this causes severe corruption and subsequent crashes.
|
|
Since I'm not really familiar with how the strange drawing code is supposed to work,
|
|
or whether this behavior is intentional or not, the short-term fix is to allocate a big
|
|
buffer and setup pointers within it. This fixes the crashes I'm seeing without causing any
|
|
(visual) side-effects.
|
|
If anyone wants to look, this is easily reproduced by starting the game and examining the rug.
|
|
drawPolyMode1() will then (indirectly) negatively index polyBuffer4. Good luck!
|
|
*/
|
|
|
|
//int16 DIST_3D[512];
|
|
//int16 polyBuffer2[512];
|
|
//int16 XMIN_XMAX[404];
|
|
//int16 polyBuffer4[512];
|
|
|
|
int16 bigPolyBuf[512 + 512 + 404 + 512]; /* consolidates the 4 separate buffers above */
|
|
|
|
//set up the replacement index pointers.
|
|
int16 *DIST_3D = &bigPolyBuf[0];
|
|
int16 *polyBuffer2 = &bigPolyBuf[512];
|
|
int16 *XMIN_XMAX = &bigPolyBuf[512 + 512];
|
|
int16 *polyBuffer4 = &bigPolyBuf[512 + 512 + 404];
|
|
|
|
|
|
|
|
|
|
// this function fills the sizeTable for the poly (OLD: mainDrawSub1Sub2)
|
|
void getPolySize(int positionX, int positionY, int scale, int sizeTable[4], unsigned char *dataPtr) {
|
|
int upperBorder;
|
|
int lowerBorder;
|
|
m_flipLeftRight = 0;
|
|
|
|
if (scale < 0) { // flip left right
|
|
m_flipLeftRight = 1;
|
|
scale = -scale;
|
|
}
|
|
// X1
|
|
|
|
upperBorder = *(dataPtr + 3);
|
|
|
|
if (m_flipLeftRight) {
|
|
upperBorder = -upperBorder;
|
|
}
|
|
|
|
upperBorder = (upscaleValue(upperBorder, scale) + 0x8000) >> 16;
|
|
upperBorder = -upperBorder;
|
|
lowerBorder = upperBorder;
|
|
|
|
// X2
|
|
|
|
upperBorder = *(dataPtr + 1);
|
|
upperBorder -= *(dataPtr + 3);
|
|
|
|
if (m_flipLeftRight) {
|
|
upperBorder = -upperBorder;
|
|
}
|
|
|
|
upperBorder = (upscaleValue(upperBorder, scale) + 0x8000) >> 16;
|
|
|
|
if (upperBorder < lowerBorder) { // exchange borders if lower > upper
|
|
SWAP(upperBorder, lowerBorder);
|
|
}
|
|
|
|
sizeTable[0] = lowerBorder + positionX; // left
|
|
sizeTable[1] = upperBorder + positionX; // right
|
|
|
|
// Y1
|
|
|
|
upperBorder = *(dataPtr + 4);
|
|
upperBorder = (upscaleValue(upperBorder, scale) + 0x8000) >> 16;
|
|
upperBorder = -upperBorder;
|
|
lowerBorder = upperBorder;
|
|
|
|
// Y2
|
|
|
|
upperBorder = *(dataPtr + 2);
|
|
upperBorder -= *(dataPtr + 4);
|
|
upperBorder = (upscaleValue(upperBorder, scale) + 0x8000) >> 16;
|
|
|
|
if (upperBorder < lowerBorder) { // exchange borders if lower > upper
|
|
SWAP(upperBorder, lowerBorder);
|
|
}
|
|
|
|
sizeTable[2] = lowerBorder + positionY; // bottom
|
|
sizeTable[3] = upperBorder + positionY; // top
|
|
}
|
|
|
|
int nbseg;
|
|
int16 nbligne;
|
|
|
|
void blitPolyMode1(char *dest, char *pMask, int16 * buffer, char color) {
|
|
int Y = XMIN_XMAX[0];
|
|
|
|
for (int i = 0; i < nbligne; i++) {
|
|
int currentY = Y + i;
|
|
int XMIN = XMIN_XMAX[1+i*2];
|
|
int XMAX = XMIN_XMAX[1+i*2+1];
|
|
|
|
for (int x = XMIN; x <= XMAX; x++) {
|
|
if (testMask(x, currentY, (unsigned char*)pMask, 40)) {
|
|
*(dest + currentY * 320 + x) = color;
|
|
}
|
|
}
|
|
//line(XMIN, currentY, XMAX, currentY, color);
|
|
}
|
|
}
|
|
|
|
void blitPolyMode2(char *dest, int16 * buffer, char color) {
|
|
int Y = XMIN_XMAX[0];
|
|
|
|
for (int i = 0; i < nbligne; i++) {
|
|
int currentY = Y + i;
|
|
int XMIN = XMIN_XMAX[1+i*2];
|
|
int XMAX = XMIN_XMAX[1+i*2+1];
|
|
|
|
for (int x = XMIN; x <= XMAX; x++) {
|
|
*(dest + currentY * 320 + x) = color;
|
|
}
|
|
}
|
|
}
|
|
|
|
int polyXMin;
|
|
int polyXMax;
|
|
int polyYMax;
|
|
int polyYMin;
|
|
|
|
int16 *A2ptr;
|
|
|
|
|
|
|
|
void buildSegment() {
|
|
int16* pOut = XMIN_XMAX;
|
|
|
|
if ((polyXMin >= 320) || (polyXMax < 0) || (polyYMax < 0) || (polyYMin >= 200)) {
|
|
XMIN_XMAX[0] = -1;
|
|
nbligne = -1;
|
|
return;
|
|
}
|
|
|
|
if (polyYMin == polyYMax) { // line
|
|
*(pOut++) = polyYMin; // store initial Y
|
|
|
|
int cx = nbseg - 1;
|
|
int16* pIn = A2ptr;
|
|
|
|
int XLeft;
|
|
int XRight;
|
|
|
|
XLeft = XRight = *pIn; // init to first X
|
|
pIn += 2;
|
|
|
|
do {
|
|
int X = *pIn;
|
|
if (XLeft > X)
|
|
XLeft = X;
|
|
if (XRight < X)
|
|
XRight = X;
|
|
pIn += 2;
|
|
} while (--cx);
|
|
|
|
// now store left and right coordinates in XMIN_XMAX
|
|
|
|
int XMin = XLeft;
|
|
int XMax = XRight;
|
|
|
|
if (XLeft < 0)
|
|
XMin = 0;
|
|
|
|
if (XRight >= 320)
|
|
XMax = 319;
|
|
|
|
*(pOut++) = XMin;
|
|
*(pOut++) = XMax;
|
|
*(pOut++) = -1;
|
|
|
|
nbligne = 1;
|
|
return;
|
|
}
|
|
|
|
// true polygon
|
|
|
|
int ydep;
|
|
|
|
if (polyYMin < 0)
|
|
ydep = 0;
|
|
else
|
|
ydep = polyYMin;
|
|
|
|
int yfin;
|
|
|
|
if (polyYMax > 199)
|
|
yfin = 199;
|
|
else
|
|
yfin = polyYMax;
|
|
|
|
nbligne = yfin - ydep + 1;
|
|
|
|
int16* ptrMini = XMIN_XMAX + 1;
|
|
XMIN_XMAX[0] = ydep;
|
|
|
|
int16* ptrMax = XMIN_XMAX + ((yfin - ydep) * 2) + 1;
|
|
ptrMax[2] = -1; // mark the end
|
|
|
|
// init table with default values
|
|
int16* si = XMIN_XMAX + 1;
|
|
int tempCount = nbligne;
|
|
do {
|
|
si[0] = 5000;
|
|
si[1] = -5000;
|
|
si += 2;
|
|
} while (--tempCount);
|
|
|
|
int16* di = A2ptr;
|
|
int segCount = nbseg;
|
|
|
|
do {
|
|
int X2 = di[2];
|
|
int X1 = di[0];
|
|
int Y2 = di[3];
|
|
int Y1 = di[1];
|
|
|
|
|
|
int tempAX = Y1;
|
|
int tempDX = Y2;
|
|
if (tempAX > tempDX) {
|
|
// swap
|
|
tempAX = Y2;
|
|
tempDX = Y1;
|
|
}
|
|
|
|
// is segment on screen ?
|
|
if (!((tempAX > 199) || (tempDX < 0))) {
|
|
int cx = X2 - X1;
|
|
if (cx == 0) {
|
|
// vertical line
|
|
int CX = X2;
|
|
if (CX < 0)
|
|
CX = 0;
|
|
|
|
int DX = X2;
|
|
if (DX > 319)
|
|
DX = 319;
|
|
|
|
int16* BX = XMIN_XMAX + (Y2 - ydep) * 2 + 1;
|
|
int16* DI = XMIN_XMAX + (Y1 - ydep) * 2 + 1;
|
|
|
|
if (Y2 >= Y1) {
|
|
SWAP(BX, DI);
|
|
}
|
|
|
|
do {
|
|
if ((BX <= ptrMax) && (BX >= ptrMini)) { // are we in screen ?
|
|
if (CX < BX[0])
|
|
BX[0] = CX;
|
|
|
|
if (DX > BX[1])
|
|
BX[1] = DX;
|
|
}
|
|
|
|
BX += 2;
|
|
} while (BX <= DI);
|
|
} else {
|
|
if (cx < 0) {
|
|
cx = -cx;
|
|
|
|
SWAP(X1, X2);
|
|
SWAP(Y1, Y2);
|
|
}
|
|
// swap again ?
|
|
SWAP(X1, X2);
|
|
|
|
int patchAdd = 2;
|
|
|
|
int dy = Y2 - Y1;
|
|
|
|
if (dy == 0) {
|
|
// hline
|
|
int16* ptr = (Y1 - ydep) * 2 + XMIN_XMAX + 1;
|
|
|
|
if ((ptr <= ptrMax) && (ptr >= ptrMini)) { // are we in screen ?
|
|
int CX = X1;
|
|
if (CX < 0)
|
|
CX = 0;
|
|
|
|
int SI = X2;
|
|
if (SI > 319)
|
|
SI = 319;
|
|
|
|
if (CX < ptr[0])
|
|
ptr[0] = CX;
|
|
|
|
if (SI > ptr[1])
|
|
ptr[1] = SI;
|
|
}
|
|
} else {
|
|
if (dy < 0) {
|
|
dy = -dy;
|
|
patchAdd = -2;
|
|
}
|
|
|
|
int stepType = 0; // small DY <= DX
|
|
|
|
if (dy > cx) {
|
|
stepType = 1; // DX < DY
|
|
|
|
SWAP(dy, cx);
|
|
}
|
|
int patchinc1 = 2 * dy;
|
|
|
|
int d = 2 * dy - cx;
|
|
int bx = 2 * (dy - cx);
|
|
|
|
int patchinc2 = bx;
|
|
|
|
cx++; // cx is the number of pixels to trace
|
|
|
|
int16* ptr = (Y1 - ydep) * 2 + XMIN_XMAX + 1;
|
|
|
|
if (stepType == 0) {
|
|
// small step
|
|
int BP = X2;
|
|
|
|
int SI = BP;
|
|
if (SI < 0)
|
|
SI = 0;
|
|
int DX = BP;
|
|
if (DX > 319)
|
|
DX = 319;
|
|
|
|
do {
|
|
if ((ptr <= ptrMax) && (ptr >= ptrMini)) { // are we in screen ?
|
|
if (SI < ptr[0])
|
|
ptr[0] = SI;
|
|
|
|
if (DX > ptr[1])
|
|
ptr[1] = DX;
|
|
}
|
|
|
|
BP ++;
|
|
|
|
// test limits
|
|
SI = BP;
|
|
if (SI < 0)
|
|
SI = 0;
|
|
DX = BP;
|
|
if (DX > 319)
|
|
DX = 319;
|
|
|
|
if (d < 0) {
|
|
d += patchinc1;
|
|
if (cx == 1) { // last ?
|
|
if ((ptr <= ptrMax) && (ptr >= ptrMini)) { // are we in screen ?
|
|
if (SI < ptr[0])
|
|
ptr[0] = SI;
|
|
|
|
if (DX > ptr[1])
|
|
ptr[1] = DX;
|
|
}
|
|
}
|
|
} else {
|
|
d += patchinc2;
|
|
ptr += patchAdd;
|
|
}
|
|
} while (--cx);
|
|
} else {
|
|
// big step
|
|
int BP = X2;
|
|
|
|
int SI = BP;
|
|
if (SI < 0)
|
|
SI = 0;
|
|
int DX = BP;
|
|
if (DX > 319)
|
|
DX = 319;
|
|
|
|
do {
|
|
if ((ptr <= ptrMax) && (ptr >= ptrMini)) { // are we in screen ?
|
|
if (SI < ptr[0])
|
|
ptr[0] = SI;
|
|
|
|
if (DX > ptr[1])
|
|
ptr[1] = DX;
|
|
}
|
|
|
|
ptr += patchAdd; // next line
|
|
|
|
if (d < 0) {
|
|
d += patchinc1;
|
|
} else {
|
|
d += patchinc2;
|
|
BP ++;
|
|
|
|
// test limits
|
|
SI = BP;
|
|
if (SI < 0)
|
|
SI = 0;
|
|
DX = BP;
|
|
if (DX > 319)
|
|
DX = 319;
|
|
}
|
|
} while (--cx);
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
di += 2;
|
|
} while (--segCount);
|
|
}
|
|
|
|
unsigned char *drawPolyMode1(unsigned char *dataPointer, int linesToDraw) {
|
|
int index;
|
|
int16 *pBufferDest;
|
|
|
|
pBufferDest = polyBuffer4 + nbseg * 2;
|
|
nbseg = linesToDraw;
|
|
A2ptr = polyBuffer4;
|
|
index = *(dataPointer++);
|
|
|
|
polyXMin = polyXMax = pBufferDest[-2] = pBufferDest[-2 + linesToDraw * 2] = polyBuffer2[index * 2];
|
|
polyYMin = polyYMax = pBufferDest[-1] = pBufferDest[-1 + linesToDraw * 2] = polyBuffer2[(index * 2) + 1];
|
|
|
|
linesToDraw--;
|
|
|
|
pBufferDest -= 2;
|
|
|
|
A2ptr = pBufferDest;
|
|
|
|
do {
|
|
int value;
|
|
|
|
index = *(dataPointer++);
|
|
value = pBufferDest[-2] = pBufferDest[-2 + nbseg * 2] = polyBuffer2[index * 2];
|
|
|
|
if (value < polyXMin) {
|
|
polyXMin = value;
|
|
}
|
|
if (value > polyXMax) {
|
|
polyXMax = value;
|
|
}
|
|
|
|
value = pBufferDest[-1] = pBufferDest[-1 + nbseg * 2] = polyBuffer2[(index * 2) + 1];
|
|
|
|
if (value < polyYMin) {
|
|
polyYMin = value;
|
|
}
|
|
if (value > polyYMax) {
|
|
polyYMax = value;
|
|
A2ptr = pBufferDest;
|
|
}
|
|
|
|
pBufferDest -= 2;
|
|
|
|
} while (--linesToDraw);
|
|
|
|
buildSegment();
|
|
|
|
return dataPointer;
|
|
}
|
|
|
|
unsigned char *drawPolyMode2(unsigned char *dataPointer, int linesToDraw) {
|
|
int index;
|
|
int16 *pBufferDest;
|
|
|
|
pBufferDest = polyBuffer4;
|
|
nbseg = linesToDraw;
|
|
A2ptr = polyBuffer4;
|
|
index = *(dataPointer++);
|
|
|
|
polyXMin = polyXMax = pBufferDest[0] = pBufferDest[linesToDraw * 2] = polyBuffer2[index * 2];
|
|
polyYMin = polyYMax = pBufferDest[1] = pBufferDest[linesToDraw * 2 + 1] = polyBuffer2[(index * 2) + 1];
|
|
|
|
linesToDraw--;
|
|
|
|
pBufferDest += 2;
|
|
|
|
do {
|
|
int value;
|
|
|
|
index = *(dataPointer++);
|
|
value = pBufferDest[0] = pBufferDest[nbseg * 2] = polyBuffer2[index * 2];
|
|
|
|
if (value < polyXMin) {
|
|
polyXMin = value;
|
|
}
|
|
if (value > polyXMax) {
|
|
polyXMax = value;
|
|
}
|
|
|
|
value = pBufferDest[1] = pBufferDest[nbseg * 2 + 1] = polyBuffer2[(index * 2) + 1];
|
|
|
|
if (value < polyYMin) {
|
|
polyYMin = value;
|
|
}
|
|
if (value > polyYMax) {
|
|
polyYMax = value;
|
|
A2ptr = pBufferDest;
|
|
}
|
|
|
|
pBufferDest += 2;
|
|
|
|
} while (--linesToDraw);
|
|
|
|
buildSegment();
|
|
|
|
return dataPointer;
|
|
}
|
|
|
|
// this function builds the poly model and then calls the draw functions (OLD: mainDrawSub1Sub5)
|
|
void buildPolyModel(int positionX, int positionY, int scale, char *pMask, char *destBuffer, char *dataPtr) {
|
|
int counter = 0; // numbers of coordinates to process
|
|
int startX = 0; // first X in model
|
|
int startY = 0; // first Y in model
|
|
int x = 0; // current X
|
|
int y = 0; // current Y
|
|
int offsetXinModel = 0; // offset of the X value in the model
|
|
int offsetYinModel = 0; // offset of the Y value in the model
|
|
unsigned char *dataPointer = (unsigned char *)dataPtr;
|
|
int16 *ptrPoly_1_Buf = DIST_3D;
|
|
int16 *ptrPoly_2_Buf;
|
|
polyOutputBuffer = destBuffer; // global
|
|
|
|
m_flipLeftRight = 0;
|
|
m_useSmallScale = 0;
|
|
m_lowerX = *(dataPointer + 3);
|
|
m_lowerY = *(dataPointer + 4);
|
|
|
|
if (scale < 0) {
|
|
scale = -scale; // flip left right
|
|
m_flipLeftRight = 1;
|
|
}
|
|
|
|
if (scale < 0x180) { // If scale is smaller than 384
|
|
m_useSmallScale = 1;
|
|
m_scaleValue = scale << 1; // double scale
|
|
} else {
|
|
m_scaleValue = scale;
|
|
}
|
|
|
|
dataPointer += 5;
|
|
|
|
m_coordCount = (*(dataPointer++)) + 1; // original uses +1 here but its later substracted again, we could skip it
|
|
m_first_X = *(dataPointer);
|
|
dataPointer++;
|
|
m_first_Y = *(dataPointer);
|
|
dataPointer++;
|
|
startX = m_lowerX - m_first_X;
|
|
startY = m_lowerY - m_first_Y;
|
|
|
|
if (m_useSmallScale) {
|
|
startX >>= 1;
|
|
startY >>= 1;
|
|
}
|
|
|
|
if (m_flipLeftRight) {
|
|
startX = -startX;
|
|
}
|
|
|
|
/*
|
|
* NOTE:
|
|
*
|
|
* The original code continues here with using X, Y instead of startX and StartY.
|
|
*
|
|
* Original code:
|
|
* positionX -= (upscaleValue(startX, m_scaleValue) + 0x8000) >> 16;
|
|
* positionY -= (upscaleValue(startX, m_scaleValue) + 0x8000) >> 16;
|
|
*/
|
|
|
|
// get coordinates from data
|
|
|
|
startX = positionX - ((upscaleValue(startX, m_scaleValue) + 0x8000) >> 16);
|
|
startY = positionY - ((upscaleValue(startY, m_scaleValue) + 0x8000) >> 16);
|
|
|
|
ptrPoly_1_Buf[0] = 0;
|
|
ptrPoly_1_Buf[1] = 0;
|
|
ptrPoly_1_Buf += 2;
|
|
counter = m_coordCount - 1 - 1; // skip the first pair, we already have the values
|
|
|
|
// dpbcl0
|
|
do {
|
|
x = *(dataPointer) - m_first_X;
|
|
dataPointer++;
|
|
if (m_useSmallScale) { // shrink all coordinates by factor 2 if a scale smaller than 384 is used
|
|
x >>= 1;
|
|
}
|
|
ptrPoly_1_Buf[0] = offsetXinModel - x;
|
|
ptrPoly_1_Buf++;
|
|
offsetXinModel = x;
|
|
|
|
y = *(dataPointer) - m_first_Y;
|
|
dataPointer++;
|
|
if (m_useSmallScale) {
|
|
y >>= 1;
|
|
}
|
|
ptrPoly_1_Buf[0] = -(offsetYinModel - y);
|
|
ptrPoly_1_Buf++;
|
|
offsetYinModel = y;
|
|
|
|
} while (--counter);
|
|
|
|
// scale and adjust coordinates with offset (using two polybuffers by doing that)
|
|
ptrPoly_2_Buf = DIST_3D;
|
|
ptrPoly_1_Buf = polyBuffer2;
|
|
counter = m_coordCount - 1; // reset counter // process first pair two
|
|
int m_current_X = 0;
|
|
int m_current_Y = 0;
|
|
|
|
do {
|
|
x = ptrPoly_2_Buf[0];
|
|
|
|
if (m_flipLeftRight == 0) {
|
|
x = -x;
|
|
}
|
|
//////////////////
|
|
|
|
m_current_X += upscaleValue(x, m_scaleValue);
|
|
ptrPoly_1_Buf[0] = ((m_current_X + 0x8000) >> 16) + startX; // adjust X value with start offset
|
|
|
|
m_current_Y += upscaleValue(ptrPoly_2_Buf[1], m_scaleValue);
|
|
ptrPoly_1_Buf[1] = ((m_current_Y + 0x8000) >> 16) + startY; // adjust Y value with start offset
|
|
|
|
/////////////////
|
|
|
|
ptrPoly_1_Buf += 2;
|
|
ptrPoly_2_Buf += 2;
|
|
|
|
} while (--counter);
|
|
|
|
// position of the dataPointer is m_coordCount * 2
|
|
|
|
int polygonCount = 0;
|
|
|
|
do {
|
|
int linesToDraw = *dataPointer++;
|
|
|
|
if (linesToDraw > 1) { // if value not zero
|
|
uint16 minimumScale;
|
|
|
|
m_color = *dataPointer; // color
|
|
dataPointer += 2;
|
|
|
|
minimumScale = READ_BE_UINT16(dataPointer);
|
|
dataPointer += 2;
|
|
|
|
if ((minimumScale <= scale)) {
|
|
if (m_flipLeftRight) {
|
|
drawPolyMode1((unsigned char *)dataPointer, linesToDraw);
|
|
} else {
|
|
drawPolyMode2((unsigned char *)dataPointer, linesToDraw);
|
|
}
|
|
|
|
if (destBuffer) {
|
|
if (pMask) {
|
|
blitPolyMode1(destBuffer, pMask, polyBuffer4, m_color & 0xFF);
|
|
} else {
|
|
blitPolyMode2(destBuffer, polyBuffer4, m_color & 0xFF);
|
|
}
|
|
}
|
|
}
|
|
|
|
dataPointer += linesToDraw;
|
|
} else {
|
|
dataPointer += 4;
|
|
}
|
|
|
|
polygonCount ++;
|
|
} while (*dataPointer != 0xFF);
|
|
}
|
|
|
|
bool findPoly(char* dataPtr, int positionX, int positionY, int scale, int mouseX, int mouseY) {
|
|
int counter = 0; // numbers of coordinates to process
|
|
int startX = 0; // first X in model
|
|
int startY = 0; // first Y in model
|
|
int x = 0; // current X
|
|
int y = 0; // current Y
|
|
int offsetXinModel = 0; // offset of the X value in the model
|
|
int offsetYinModel = 0; // offset of the Y value in the model
|
|
unsigned char *dataPointer = (unsigned char *)dataPtr;
|
|
int16 *ptrPoly_1_Buf = DIST_3D;
|
|
int16 *ptrPoly_2_Buf;
|
|
|
|
m_flipLeftRight = 0;
|
|
m_useSmallScale = 0;
|
|
m_lowerX = *(dataPointer + 3);
|
|
m_lowerY = *(dataPointer + 4);
|
|
|
|
if (scale < 0) {
|
|
scale = -scale; // flip left right
|
|
m_flipLeftRight = 1;
|
|
}
|
|
|
|
if (scale < 0x180) { // If scale is smaller than 384
|
|
m_useSmallScale = 1;
|
|
m_scaleValue = scale << 1; // double scale
|
|
} else {
|
|
m_scaleValue = scale;
|
|
}
|
|
|
|
dataPointer += 5;
|
|
|
|
m_coordCount = (*(dataPointer++)) + 1; // original uses +1 here but its later substracted again, we could skip it
|
|
m_first_X = *(dataPointer);
|
|
dataPointer++;
|
|
m_first_Y = *(dataPointer);
|
|
dataPointer++;
|
|
startX = m_lowerX - m_first_X;
|
|
startY = m_lowerY - m_first_Y;
|
|
|
|
if (m_useSmallScale) {
|
|
startX >>= 1;
|
|
startY >>= 1;
|
|
}
|
|
|
|
if (m_flipLeftRight) {
|
|
startX = -startX;
|
|
}
|
|
|
|
/*
|
|
* NOTE:
|
|
*
|
|
* The original code continues here with using X, Y instead of startX and StartY.
|
|
*
|
|
* Original code:
|
|
* positionX -= (upscaleValue(startX, m_scaleValue) + 0x8000) >> 16;
|
|
* positionY -= (upscaleValue(startX, m_scaleValue) + 0x8000) >> 16;
|
|
*/
|
|
|
|
// get coordinates from data
|
|
|
|
startX = positionX - ((upscaleValue(startX, m_scaleValue) + 0x8000) >> 16);
|
|
startY = positionY - ((upscaleValue(startY, m_scaleValue) + 0x8000) >> 16);
|
|
|
|
ptrPoly_1_Buf[0] = 0;
|
|
ptrPoly_1_Buf[1] = 0;
|
|
ptrPoly_1_Buf += 2;
|
|
counter = m_coordCount - 1 - 1; // skip the first pair, we already have the values
|
|
|
|
// dpbcl0
|
|
do {
|
|
x = *(dataPointer) - m_first_X;
|
|
dataPointer++;
|
|
if (m_useSmallScale) { // shrink all coordinates by factor 2 if a scale smaller than 384 is used
|
|
x >>= 1;
|
|
}
|
|
ptrPoly_1_Buf[0] = offsetXinModel - x;
|
|
ptrPoly_1_Buf++;
|
|
offsetXinModel = x;
|
|
|
|
y = *(dataPointer) - m_first_Y;
|
|
dataPointer++;
|
|
if (m_useSmallScale) {
|
|
y >>= 1;
|
|
}
|
|
ptrPoly_1_Buf[0] = -(offsetYinModel - y);
|
|
ptrPoly_1_Buf++;
|
|
offsetYinModel = y;
|
|
|
|
} while (--counter);
|
|
|
|
// scale and adjust coordinates with offset (using two polybuffers by doing that)
|
|
ptrPoly_2_Buf = DIST_3D;
|
|
ptrPoly_1_Buf = polyBuffer2;
|
|
counter = m_coordCount - 1; // reset counter // process first pair two
|
|
int m_current_X = 0;
|
|
int m_current_Y = 0;
|
|
|
|
do {
|
|
x = ptrPoly_2_Buf[0];
|
|
|
|
if (m_flipLeftRight == 0) {
|
|
x = -x;
|
|
}
|
|
//////////////////
|
|
|
|
m_current_X += upscaleValue(x, m_scaleValue);
|
|
ptrPoly_1_Buf[0] = ((m_current_X + 0x8000) >> 16) + startX; // adjust X value with start offset
|
|
|
|
m_current_Y += upscaleValue(ptrPoly_2_Buf[1], m_scaleValue);
|
|
ptrPoly_1_Buf[1] = ((m_current_Y + 0x8000) >> 16) + startY; // adjust Y value with start offset
|
|
|
|
/////////////////
|
|
|
|
ptrPoly_1_Buf += 2;
|
|
ptrPoly_2_Buf += 2;
|
|
|
|
} while (--counter);
|
|
|
|
// position of the dataPointer is m_coordCount * 2
|
|
|
|
int polygonCount = 0;
|
|
|
|
do {
|
|
int linesToDraw = *dataPointer++;
|
|
|
|
if (linesToDraw > 1) { // if value not zero
|
|
uint16 minimumScale;
|
|
|
|
m_color = *dataPointer; // color
|
|
dataPointer += 2;
|
|
|
|
minimumScale = READ_BE_UINT16(dataPointer);
|
|
dataPointer += 2;
|
|
|
|
if ((minimumScale <= scale)) {
|
|
if (m_flipLeftRight) {
|
|
drawPolyMode1((unsigned char *)dataPointer, linesToDraw);
|
|
} else {
|
|
drawPolyMode2((unsigned char *)dataPointer, linesToDraw);
|
|
}
|
|
|
|
int polygonYMin = XMIN_XMAX[0];
|
|
int polygonYMax = polygonYMin + nbligne;
|
|
|
|
if ((mouseY >= polygonYMin) && (mouseY < polygonYMax)) {
|
|
int polygonLineNumber = mouseY - polygonYMin;
|
|
|
|
int XMIN = XMIN_XMAX[1+polygonLineNumber*2];
|
|
int XMAX = XMIN_XMAX[1+polygonLineNumber*2+1];
|
|
|
|
if ((mouseX >= XMIN) && (mouseX <= XMAX))
|
|
return true;
|
|
}
|
|
}
|
|
|
|
dataPointer += linesToDraw;
|
|
} else {
|
|
dataPointer += 4;
|
|
}
|
|
|
|
polygonCount ++;
|
|
} while (*dataPointer != 0xFF);
|
|
|
|
return false;
|
|
}
|
|
|
|
void clearMaskBit(int x, int y, unsigned char* pData, int stride) {
|
|
unsigned char* ptr = y * stride + x / 8 + pData;
|
|
|
|
unsigned char bitToTest = 0x80 >> (x & 7);
|
|
|
|
*(ptr) &= ~bitToTest;
|
|
}
|
|
|
|
|
|
void drawMask(unsigned char* workBuf, int wbWidth, int wbHeight, unsigned char* pMask, int maskWidth, int maskHeight, int maskX, int maskY, int passIdx) {
|
|
for (int y = 0; y < maskHeight; y++) {
|
|
for (int x = 0; x < maskWidth*8; x++) {
|
|
if (testMask(x, y, pMask, maskWidth)) {
|
|
int destX = maskX + x;
|
|
int destY = maskY + y;
|
|
|
|
if ((destX >= 0) && (destX < wbWidth*8) && (destY >= 0) && (destY < wbHeight))
|
|
clearMaskBit(destX, destY, workBuf, wbWidth);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
unsigned char polygonMask[(320*200)/8];
|
|
|
|
// draw poly sprite (OLD: mainDrawSub1)
|
|
void mainDrawPolygons(int fileIndex, cellStruct *plWork, int X, int scale, int Y, char *destBuffer, char *dataPtr) {
|
|
int newX;
|
|
int newY;
|
|
int newScale;
|
|
char *newFrame;
|
|
|
|
int sizeTable[4]; // 0 = left, 1 = right, 2 = bottom, 3 = top
|
|
|
|
// this function checks if the dataPtr is not 0, else it retrives the data for X, Y, scale and DataPtr again (OLD: mainDrawSub1Sub1)
|
|
flipPoly(fileIndex, (int16*)dataPtr, scale, &newFrame, X, Y, &newX, &newY, &newScale);
|
|
|
|
// this function fills the sizeTable for the poly (OLD: mainDrawSub1Sub2)
|
|
getPolySize(newX, newY, newScale, sizeTable, (unsigned char*)newFrame);
|
|
|
|
spriteX2 = sizeTable[0] - 2; // left border
|
|
spriteX1 = sizeTable[1] + 18; // right border
|
|
spriteY2 = sizeTable[2] - 2; // bottom border
|
|
spriteY1 = sizeTable[3] + 2; // top border
|
|
|
|
if (spriteX2 >= 320)
|
|
return;
|
|
if (spriteX1 < 0)
|
|
return;
|
|
if (spriteY2 >= 200)
|
|
return;
|
|
if (spriteY1 < 0)
|
|
return;
|
|
|
|
if (spriteX2 < 0) {
|
|
spriteX2 = 0;
|
|
}
|
|
if (spriteX1 > 320) {
|
|
spriteX1 = 320;
|
|
}
|
|
if (spriteY2 < 0) {
|
|
spriteY2 = 0;
|
|
}
|
|
if (spriteY1 > 200) {
|
|
spriteY1 = 200;
|
|
}
|
|
|
|
if (spriteX1 == spriteX2)
|
|
return;
|
|
if (spriteY1 == spriteY2)
|
|
return;
|
|
|
|
gfxModuleData_addDirtyRect(Common::Rect(spriteX2, spriteY2, spriteX1, spriteY1));
|
|
|
|
memset(polygonMask, 0xFF, (320*200) / 8);
|
|
|
|
int numPasses = 0;
|
|
|
|
while (plWork) {
|
|
if (plWork->type == OBJ_TYPE_BGMASK && plWork->freeze == 0) {
|
|
objectParamsQuery params;
|
|
|
|
getMultipleObjectParam(plWork->overlay, plWork->idx, ¶ms);
|
|
|
|
int maskX = params.X;
|
|
int maskY = params.Y;
|
|
int maskFrame = params.fileIdx;
|
|
|
|
if (filesDatabase[maskFrame].subData.resourceType == OBJ_TYPE_BGMASK && filesDatabase[maskFrame].subData.ptrMask) {
|
|
drawMask(polygonMask, 40, 200, filesDatabase[maskFrame].subData.ptrMask, filesDatabase[maskFrame].width / 8, filesDatabase[maskFrame].height, maskX, maskY, numPasses++);
|
|
} else
|
|
if (filesDatabase[maskFrame].subData.resourceType == OBJ_TYPE_SPRITE && filesDatabase[maskFrame].subData.ptrMask) {
|
|
drawMask(polygonMask, 40, 200, filesDatabase[maskFrame].subData.ptrMask, filesDatabase[maskFrame].width / 8, filesDatabase[maskFrame].height, maskX, maskY, numPasses++);
|
|
}
|
|
|
|
}
|
|
|
|
plWork = plWork->next;
|
|
}
|
|
|
|
// this function builds the poly model and then calls the draw functions (OLD: mainDrawSub1Sub5)
|
|
buildPolyModel(newX, newY, newScale, (char*)polygonMask, destBuffer, newFrame);
|
|
}
|
|
|
|
void drawMessage(const gfxEntryStruct *pGfxPtr, int globalX, int globalY, int width, int newColor, uint8 *ouputPtr) {
|
|
// this is used for font only
|
|
|
|
if (pGfxPtr) {
|
|
uint8 *initialOuput;
|
|
uint8 *output;
|
|
int xp, yp;
|
|
int x, y;
|
|
const uint8 *ptr = pGfxPtr->imagePtr;
|
|
int height = pGfxPtr->height;
|
|
|
|
if (width > 310)
|
|
width = 310;
|
|
if (width + globalX > 319)
|
|
globalX = 319 - width;
|
|
if (globalY < 0)
|
|
globalY = 0;
|
|
if (globalX < 0)
|
|
globalX = 0;
|
|
|
|
if (globalY + pGfxPtr->height >= 198) {
|
|
globalY = 198 - pGfxPtr->height;
|
|
}
|
|
|
|
gfxModuleData_addDirtyRect(Common::Rect(globalX, globalY, globalX + width, globalY + height));
|
|
|
|
initialOuput = ouputPtr + (globalY * 320) + globalX;
|
|
|
|
for (yp = 0; yp < height; yp++) {
|
|
output = initialOuput + 320 * yp;
|
|
y = globalY + yp;
|
|
|
|
for (xp = 0; xp < pGfxPtr->width; xp++) {
|
|
x = globalX + xp;
|
|
uint8 color = *(ptr++);
|
|
|
|
if (color) {
|
|
if ((x >= 0) && (x < 320) && (y >= 0) && (y < 200)) {
|
|
if (color == 1) {
|
|
*output = (uint8) 0;
|
|
} else {
|
|
*output = (uint8) newColor;
|
|
}
|
|
}
|
|
}
|
|
output++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void drawSprite(int width, int height, cellStruct *currentObjPtr, const uint8 *dataIn, int ys, int xs, uint8 *output, const uint8 *dataBuf) {
|
|
int x = 0;
|
|
int y = 0;
|
|
|
|
// Flag the given area as having been changed
|
|
Common::Point ps = Common::Point(MAX(MIN(xs, 320), 0), MAX(MIN(ys, 200), 0));
|
|
Common::Point pe = Common::Point(MAX(MIN(xs + width, 320), 0), MAX(MIN(ys + height, 200), 0));
|
|
if ((ps.x != pe.x) && (ps.y != pe.y))
|
|
// At least part of sprite is on-screen
|
|
gfxModuleData_addDirtyRect(Common::Rect(ps.x, ps.y, pe.x, pe.y));
|
|
|
|
cellStruct* plWork = currentObjPtr;
|
|
int workBufferSize = height * (width / 8);
|
|
|
|
unsigned char* workBuf = (unsigned char*)MemAlloc(workBufferSize);
|
|
memcpy(workBuf, dataBuf, workBufferSize);
|
|
|
|
int numPasses = 0;
|
|
|
|
while (plWork) {
|
|
if (plWork->type == OBJ_TYPE_BGMASK && plWork->freeze == 0) {
|
|
objectParamsQuery params;
|
|
|
|
getMultipleObjectParam(plWork->overlay, plWork->idx, ¶ms);
|
|
|
|
int maskX = params.X;
|
|
int maskY = params.Y;
|
|
int maskFrame = params.fileIdx;
|
|
|
|
if (filesDatabase[maskFrame].subData.resourceType == OBJ_TYPE_BGMASK && filesDatabase[maskFrame].subData.ptrMask) {
|
|
drawMask(workBuf, width / 8, height, filesDatabase[maskFrame].subData.ptrMask, filesDatabase[maskFrame].width / 8, filesDatabase[maskFrame].height, maskX - xs, maskY - ys, numPasses++);
|
|
} else
|
|
if (filesDatabase[maskFrame].subData.resourceType == OBJ_TYPE_SPRITE && filesDatabase[maskFrame].subData.ptrMask) {
|
|
drawMask(workBuf, width / 8, height, filesDatabase[maskFrame].subData.ptrMask, filesDatabase[maskFrame].width / 8, filesDatabase[maskFrame].height, maskX - xs, maskY - ys, numPasses++);
|
|
}
|
|
|
|
}
|
|
|
|
plWork = plWork->next;
|
|
}
|
|
|
|
for (y = 0; y < height; y++) {
|
|
for (x = 0; x < (width); x++) {
|
|
uint8 color = *dataIn++;
|
|
|
|
if ((x + xs) >= 0 && (x + xs) < 320 && (y + ys) >= 0 && (y + ys) < 200) {
|
|
if (testMask(x, y, workBuf, width / 8)) {
|
|
output[320 * (y + ys) + x + xs] = color;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
MemFree(workBuf);
|
|
}
|
|
|
|
#ifdef _DEBUG
|
|
void drawCtp() {
|
|
/* int i;
|
|
|
|
if (ctp_walkboxTable) {
|
|
for (i = 0; i < 15; i++) {
|
|
uint16 *dataPtr = &ctp_walkboxTable[i * 40];
|
|
int type = walkboxColor[i]; // show different types in different colors
|
|
|
|
if (*dataPtr) {
|
|
int j;
|
|
fillpoly((short *)dataPtr + 1, *dataPtr, type);
|
|
|
|
for (j = 0; j < (*dataPtr - 1); j++) {
|
|
line(dataPtr[1 + j * 2],
|
|
dataPtr[1 + j * 2 + 1],
|
|
dataPtr[1 + (j + 1) * 2],
|
|
dataPtr[1 + (j + 1) * 2 + 1], 0);
|
|
}
|
|
|
|
line(dataPtr[1 + j * 2],
|
|
dataPtr[1 + j * 2 + 1], dataPtr[1],
|
|
dataPtr[2], 0);
|
|
}
|
|
}
|
|
}*/
|
|
}
|
|
#endif
|
|
|
|
void drawMenu(menuStruct *pMenu) {
|
|
if (pMenu == NULL)
|
|
return;
|
|
|
|
if (pMenu->numElements == 0)
|
|
return;
|
|
|
|
int hline = pMenu->gfx->height;
|
|
int x = pMenu->x;
|
|
int y = pMenu->y + hline;
|
|
|
|
int numItemByLine = (199 - hline * 2) / hline;
|
|
int nbcol = pMenu->numElements / numItemByLine;
|
|
|
|
if (!nbcol) {
|
|
nbcol++;
|
|
|
|
if (y + pMenu->numElements*hline > 199 - hline) {
|
|
y = 200 - (pMenu->numElements * hline) - hline;
|
|
}
|
|
} else {
|
|
if (pMenu->numElements % numItemByLine) {
|
|
nbcol++;
|
|
}
|
|
|
|
y = hline;
|
|
}
|
|
|
|
if (x > (320 - (nbcol*160)))
|
|
x = 320 - (nbcol * 160);
|
|
|
|
if (x < 0)
|
|
x = 0;
|
|
|
|
int wx = x + (nbcol - 1) * (160 / 2);
|
|
|
|
if (wx <= 320 - 160) {
|
|
drawMessage(pMenu->gfx, wx, y - hline, 160, titleColor, gfxModuleData.pPage10);
|
|
}
|
|
|
|
wx = x;
|
|
int wy = y;
|
|
int wc = 0;
|
|
menuElementStruct* p1 = pMenu->ptrNextElement;
|
|
|
|
while (p1) {
|
|
gfxEntryStruct *p2 = p1->gfx;
|
|
|
|
p1->x = wx;
|
|
p1->y = wy;
|
|
p1->varA = 160;
|
|
|
|
int color;
|
|
|
|
if (p1->selected) {
|
|
color = selectColor;
|
|
} else {
|
|
if (p1->color != 255) {
|
|
color = p1->color;
|
|
} else {
|
|
color = itemColor;
|
|
}
|
|
}
|
|
|
|
if (wx <= (320 - 160)) {
|
|
drawMessage(p2, wx, wy, 160, color, gfxModuleData.pPage10);
|
|
}
|
|
|
|
wy += hline;
|
|
wc ++;
|
|
|
|
if (wc == numItemByLine) {
|
|
wc = 0;
|
|
wx += 160;
|
|
wy = y;
|
|
}
|
|
|
|
p1 = p1->next;
|
|
}
|
|
}
|
|
|
|
int getValueFromObjectQuerry(objectParamsQuery *params, int idx) {
|
|
switch (idx) {
|
|
case 0:
|
|
return params->X;
|
|
case 1:
|
|
return params->Y;
|
|
case 2:
|
|
return params->baseFileIdx;
|
|
case 3:
|
|
return params->fileIdx;
|
|
case 4:
|
|
return params->scale;
|
|
case 5:
|
|
return params->state;
|
|
case 6:
|
|
return params->state2;
|
|
case 7:
|
|
return params->nbState;
|
|
}
|
|
|
|
assert(0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void mainDraw(int16 param) {
|
|
uint8 *bgPtr;
|
|
cellStruct *currentObjPtr;
|
|
int16 currentObjIdx;
|
|
int16 objX1 = 0;
|
|
int16 objY1 = 0;
|
|
int16 objZ1 = 0;
|
|
int16 objX2 = 0;
|
|
int16 objY2 = 0;
|
|
int16 objZ2 = 0;
|
|
int16 spriteHeight;
|
|
|
|
/*if (PCFadeFlag) {
|
|
return;
|
|
}*/
|
|
|
|
bgPtr = backgroundScreens[masterScreen];
|
|
|
|
if (bgPtr) {
|
|
gfxModuleData_gfxCopyScreen(bgPtr, gfxModuleData.pPage10);
|
|
if (backgroundChanged[masterScreen]) {
|
|
backgroundChanged[masterScreen] = false;
|
|
switchBackground(bgPtr);
|
|
}
|
|
}
|
|
|
|
autoCellHead.next = NULL;
|
|
|
|
currentObjPtr = cellHead.next;
|
|
|
|
#ifdef _DEBUG
|
|
/* polyOutputBuffer = (char*)bgPtr;
|
|
drawCtp(); */
|
|
#endif
|
|
|
|
//-------------------------------------------------- PROCESS SPRITES -----------------------------------------//
|
|
|
|
while (currentObjPtr) {
|
|
if ((masterScreen == currentObjPtr->backgroundPlane) && (currentObjPtr->freeze == 0) && (currentObjPtr->type == OBJ_TYPE_SPRITE)) {
|
|
objectParamsQuery params;
|
|
|
|
currentObjIdx = currentObjPtr->idx;
|
|
|
|
if ((currentObjPtr->followObjectOverlayIdx != currentObjPtr->overlay) || (currentObjPtr->followObjectIdx != currentObjPtr->idx)) {
|
|
// Declaring this twice ?
|
|
// objectParamsQuery params;
|
|
|
|
getMultipleObjectParam(currentObjPtr->followObjectOverlayIdx, currentObjPtr->followObjectIdx, ¶ms);
|
|
|
|
objX1 = params.X;
|
|
objY1 = params.Y;
|
|
objZ1 = params.fileIdx;
|
|
} else {
|
|
objX1 = 0;
|
|
objY1 = 0;
|
|
objZ1 = 0;
|
|
}
|
|
|
|
getMultipleObjectParam(currentObjPtr->overlay, currentObjIdx, ¶ms);
|
|
|
|
objX2 = objX1 + params.X;
|
|
objY2 = objY1 + params.Y;
|
|
objZ2 = params.fileIdx;
|
|
|
|
if (objZ2 >= 0) {
|
|
objZ2 += objZ1;
|
|
}
|
|
|
|
if ((params.state >= 0) && (objZ2 >= 0) && filesDatabase[objZ2].subData.ptr) {
|
|
if (filesDatabase[objZ2].subData.resourceType == 8) { // Poly
|
|
mainDrawPolygons(objZ2, currentObjPtr, objX2, params.scale, objY2, (char *)gfxModuleData.pPage10, (char *)filesDatabase[objZ2].subData.ptr); // poly
|
|
} else if (filesDatabase[objZ2].subData.resourceType == OBJ_TYPE_SOUND) {
|
|
} else if (filesDatabase[objZ2].resType == OBJ_TYPE_MASK) {
|
|
} else if (filesDatabase[objZ2].subData.resourceType == OBJ_TYPE_SPRITE) {
|
|
objX1 = filesDatabase[objZ2].width; // width
|
|
spriteHeight = filesDatabase[objZ2].height; // height
|
|
|
|
if (filesDatabase[objZ2].subData.ptr) {
|
|
drawSprite(objX1, spriteHeight, currentObjPtr, filesDatabase[objZ2].subData.ptr, objY2, objX2, gfxModuleData.pPage10, filesDatabase[objZ2].subData.ptrMask);
|
|
}
|
|
}
|
|
}
|
|
|
|
// automatic animation process
|
|
if (currentObjPtr->animStep && !param) {
|
|
if (currentObjPtr->animCounter <= 0) {
|
|
|
|
bool change = true;
|
|
|
|
int newVal = getValueFromObjectQuerry(¶ms, currentObjPtr->animChange) + currentObjPtr->animStep;
|
|
|
|
if (currentObjPtr->animStep > 0) {
|
|
if (newVal > currentObjPtr->animEnd) {
|
|
if (currentObjPtr->animLoop) {
|
|
newVal = currentObjPtr->animStart;
|
|
if (currentObjPtr->animLoop > 0)
|
|
currentObjPtr->animLoop--;
|
|
} else {
|
|
change = false;
|
|
currentObjPtr->animStep = 0;
|
|
|
|
if (currentObjPtr->animType) { // should we resume the script ?
|
|
if (currentObjPtr->parentType == 20) {
|
|
changeScriptParamInList(currentObjPtr->parentOverlay, currentObjPtr->parent, &procHead, -1, 0);
|
|
} else if (currentObjPtr->parentType == 30) {
|
|
changeScriptParamInList(currentObjPtr->parentOverlay, currentObjPtr->parent, &relHead, -1, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
if (newVal < currentObjPtr->animEnd) {
|
|
if (currentObjPtr->animLoop) {
|
|
newVal = currentObjPtr->animStart;
|
|
if (currentObjPtr->animLoop > 0)
|
|
currentObjPtr->animLoop--;
|
|
} else {
|
|
change = false;
|
|
currentObjPtr->animStep = 0;
|
|
|
|
if (currentObjPtr->animType) { // should we resume the script ?
|
|
if (currentObjPtr->parentType == 20) {
|
|
changeScriptParamInList(currentObjPtr->parentOverlay, currentObjPtr->parent, &procHead, -1, 0);
|
|
} else if (currentObjPtr->parentType == 30) {
|
|
changeScriptParamInList(currentObjPtr->parentOverlay, currentObjPtr->parent, &relHead, -1, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (currentObjPtr->animWait >= 0) {
|
|
currentObjPtr->animCounter = currentObjPtr->animWait;
|
|
}
|
|
|
|
if ((currentObjPtr->animSignal >= 0) && (currentObjPtr->animSignal == newVal) && (currentObjPtr->animType != 0)) {
|
|
if (currentObjPtr->parentType == 20) {
|
|
changeScriptParamInList(currentObjPtr->parentOverlay, currentObjPtr->parent, &procHead, -1, 0);
|
|
} else if (currentObjPtr->parentType == 30) {
|
|
changeScriptParamInList(currentObjPtr->parentOverlay, currentObjPtr->parent, &relHead, -1, 0);
|
|
}
|
|
|
|
currentObjPtr->animType = 0;
|
|
}
|
|
|
|
if (change) {
|
|
addAutoCell(currentObjPtr->overlay, currentObjPtr->idx, currentObjPtr->animChange, newVal, currentObjPtr);
|
|
}
|
|
} else {
|
|
currentObjPtr->animCounter--;
|
|
}
|
|
}
|
|
}
|
|
|
|
currentObjPtr = currentObjPtr->next;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------------------//
|
|
|
|
freeAutoCell();
|
|
isMessage = 0;
|
|
|
|
//-------------------------------------------------- DRAW OBJECTS TYPE 5 (MSG)-----------------------------------------//
|
|
|
|
currentObjPtr = cellHead.next;
|
|
|
|
while (currentObjPtr) {
|
|
if (currentObjPtr->type == OBJ_TYPE_MESSAGE && currentObjPtr->freeze == 0) {
|
|
drawMessage(currentObjPtr->gfxPtr, currentObjPtr->x, currentObjPtr->field_C, currentObjPtr->spriteIdx, currentObjPtr->color, gfxModuleData.pPage10);
|
|
isMessage = 1;
|
|
}
|
|
currentObjPtr = currentObjPtr->next;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------------------//
|
|
|
|
if (currentActiveMenu != -1) {
|
|
if (menuTable[currentActiveMenu]) {
|
|
drawMenu(menuTable[currentActiveMenu]);
|
|
return;
|
|
}
|
|
} else if ((linkedRelation) && (linkedMsgList)) {
|
|
int16 mouseX;
|
|
int16 mouseY;
|
|
int16 button;
|
|
getMouseStatus(&main10, &mouseX, &button, &mouseY);
|
|
|
|
if (mouseY > (linkedMsgList->height)*2)
|
|
drawMessage(linkedMsgList, 0, 0, 320, findHighColor(), gfxModuleData.pPage10);
|
|
else
|
|
drawMessage(linkedMsgList, 0, 200, 320, findHighColor(), gfxModuleData.pPage10);
|
|
}
|
|
}
|
|
|
|
} // End of namespace Cruise
|