TINSEL: Refactor and simplify image handling

This allows us to merge different code paths for Tinsel V1 - V3 and
simplify the relevant code.

- Images are now obtained as a copy via GetImage(), which handles
  endianess internally
- The GetImageFromFilm() / GetImageFromReel() wrappers have been removed
- Direct setting of the image palette has been removed in favor of
  PokeInPalette(). This allows us to make image pointers const
- Struct packing has been removed from the IMAGE class, as we no
  longer cast raw data to image pointers
- There is now a single IMAGE class for all Tinsel versions
This commit is contained in:
Filippos Karapetis 2022-01-09 16:52:35 +02:00
parent f4a0db227f
commit 0221bc5c02
13 changed files with 186 additions and 236 deletions

View File

@ -164,19 +164,21 @@ void Background::StartupBackground(CORO_PARAM, SCNHANDLE hFilm) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
const FILM *pfilm;
IMAGE *pim;
_hBackground = hFilm; // Save handle in case of Save_Scene()
pim = _vm->_cursor->GetImageFromFilm(hFilm, 0, NULL, NULL, &pfilm);
const FILM *pfilm = (const FILM *)_vm->_handle->LockMem(hFilm);
const FREEL *pfr = &pfilm->reels[0];
if (!TinselV3) {
SetBackPal(FROM_32(pim->hImgPal));
const MULTI_INIT *pmi = (const MULTI_INIT *)_vm->_handle->LockMem(FROM_32(pfr->mobj));
const FRAME *pFrame = (const FRAME *)_vm->_handle->LockMem(FROM_32(pmi->hMulFrame));
const IMAGE *pim = _vm->_handle->GetImage(READ_32(pFrame));
SetBackPal(pim->hImgPal);
delete pim;
}
CORO_BEGIN_CODE(_ctx);
_hBackground = hFilm; // Save handle in case of Save_Scene()
// Extract the film speed
_BGspeed = ONE_SECOND / FROM_32(pfilm->frate);

View File

@ -84,23 +84,19 @@ Cursor::Cursor() {
* it. Also initialize its animation script.
*/
void Cursor::InitCurTrailObj(int i, int x, int y) {
const FREEL *pfr; // pointer to reel
IMAGE *pim; // pointer to image
const MULTI_INIT *pmi; // MULTI_INIT structure
const FILM *pfilm;
if (!_numTrails)
return;
const FILM *pFilm = (const FILM *)_vm->_handle->LockMem(_cursorFilm);
const FREEL *pfr = (const FREEL *)&pFilm->reels[i + 1];
const MULTI_INIT *pmi = (MULTI_INIT *)_vm->_handle->LockMem(FROM_32(pfr->mobj));
PokeInPalette(pmi);
// Get rid of old object
if (_trailData[i].trailObj != NULL)
MultiDeleteObject(_vm->_bg->GetPlayfieldList(FIELD_STATUS), _trailData[i].trailObj);
pim = GetImageFromFilm(_cursorFilm, i+1, &pfr, &pmi, &pfilm);// Get pointer to image
assert(_vm->_bg->BgPal()); // No background palette
pim->hImgPal = TO_32(_vm->_bg->BgPal());
// Initialize and insert the object, set its Z-pos, and hide it
_trailData[i].trailObj = MultiInitObject(pmi);
MultiInsertObject(_vm->_bg->GetPlayfieldList(FIELD_STATUS), _trailData[i].trailObj);
@ -108,7 +104,7 @@ void Cursor::InitCurTrailObj(int i, int x, int y) {
MultiSetAniXY(_trailData[i].trailObj, x, y);
// Initialize the animation script
InitStepAnimScript(&_trailData[i].trailAnim, _trailData[i].trailObj, FROM_32(pfr->script), ONE_SECOND / FROM_32(pfilm->frate));
InitStepAnimScript(&_trailData[i].trailAnim, _trailData[i].trailObj, FROM_32(pfr->script), ONE_SECOND / FROM_32(pFilm->frate));
StepAnimScript(&_trailData[i].trailAnim);
}
@ -301,41 +297,6 @@ void Cursor::UnHideCursorTrails() {
_hiddenTrails = false;
}
/**
* Get pointer to image from a film reel. And the rest.
*/
IMAGE *Cursor::GetImageFromReel(const FREEL *pfr, const MULTI_INIT **ppmi) {
const MULTI_INIT *pmi;
const FRAME *pFrame;
pmi = (const MULTI_INIT *)_vm->_handle->LockMem(FROM_32(pfr->mobj));
if (ppmi)
*ppmi = pmi;
pFrame = (const FRAME *)_vm->_handle->LockMem(FROM_32(pmi->hMulFrame));
// get pointer to image
return (IMAGE *)_vm->_handle->LockMem(READ_32(pFrame));
}
/**
* Get pointer to image from a film. And the rest.
*/
IMAGE *Cursor::GetImageFromFilm(SCNHANDLE hFilm, int reel, const FREEL **ppfr, const MULTI_INIT **ppmi, const FILM **ppfilm) {
const FILM *pfilm;
const FREEL *pfr;
pfilm = (const FILM *)_vm->_handle->LockMem(hFilm);
if (ppfilm)
*ppfilm = pfilm;
pfr = &pfilm->reels[reel];
if (ppfr)
*ppfr = pfr;
return GetImageFromReel(pfr, ppmi);
}
/**
* Delete auxillary cursor. Restore animation offsets in the image.
*/
@ -351,10 +312,11 @@ void Cursor::DelAuxCursor() {
* Save animation offsets from the image if required.
*/
void Cursor::SetAuxCursor(SCNHANDLE hFilm) {
IMAGE *pim; // Pointer to auxillary cursor's image
const FREEL *pfr;
const MULTI_INIT *pmi;
const FILM *pfilm;
const FILM *pfilm = (const FILM *)_vm->_handle->LockMem(hFilm);
const FREEL *pfr = &pfilm->reels[0];
const MULTI_INIT *pmi = (const MULTI_INIT *)_vm->_handle->LockMem(FROM_32(pfr->mobj));
const FRAME *pFrame = (const FRAME *)_vm->_handle->LockMem(FROM_32(pmi->hMulFrame));
const IMAGE *pim;
int x, y; // Cursor position
DelAuxCursor(); // Get rid of previous
@ -365,13 +327,14 @@ void Cursor::SetAuxCursor(SCNHANDLE hFilm) {
GetCursorXY(&x, &y, false); // Note: also waits for cursor to appear
pim = GetImageFromFilm(hFilm, 0, &pfr, &pmi, &pfilm);// Get pointer to image
pim = _vm->_handle->GetImage(READ_32(pFrame)); // Get pointer to auxillary cursor's image
assert(_vm->_bg->BgPal()); // no background palette
pim->hImgPal = TO_32(_vm->_bg->BgPal()); // Poke in the background palette
PokeInPalette(pmi);
_auxCursorOffsetX = (short)(FROM_16(pim->imgWidth)/2 - ((int16) FROM_16(pim->anioffX)));
_auxCursorOffsetY = (short)((FROM_16(pim->imgHeight) & ~C16_FLAG_MASK)/2 -
((int16) FROM_16(pim->anioffY)));
_auxCursorOffsetX = (short)(pim->imgWidth / 2 - ((int16) pim->anioffX));
_auxCursorOffsetY = (short)((pim->imgHeight & ~C16_FLAG_MASK) / 2 -
((int16) pim->anioffY));
delete pim;
// Initialize and insert the auxillary cursor object
_auxCursor = MultiInitObject(pmi);
@ -461,28 +424,17 @@ void Cursor::DoCursorMove() {
* Initialize cursor object.
*/
void Cursor::InitCurObj() {
const FILM *pFilm;
const FREEL *pfr;
const MULTI_INIT *pmi;
IMAGE *pim;
const FILM *pFilm = (const FILM *)_vm->_handle->LockMem(_cursorFilm);
const FREEL *pfr = (const FREEL *)&pFilm->reels[0];
const MULTI_INIT *pmi = (MULTI_INIT *)_vm->_handle->LockMem(FROM_32(pfr->mobj));
if (TinselV2 || TinselV3) {
pFilm = (const FILM *)_vm->_handle->LockMem(_cursorFilm);
pfr = (const FREEL *)&pFilm->reels[0];
pmi = (MULTI_INIT *)_vm->_handle->LockMem(FROM_32(pfr->mobj));
if (!TinselV3) {
PokeInPalette(pmi);
}
} else {
assert(_vm->_bg->BgPal()); // no background palette
pim = GetImageFromFilm(_cursorFilm, 0, &pfr, &pmi, &pFilm);// Get pointer to image
pim->hImgPal = TO_32(_vm->_bg->BgPal());
_auxCursor = nullptr; // No auxillary cursor
if (!TinselV3) {
PokeInPalette(pmi);
}
if (!TinselV2)
_auxCursor = nullptr; // No auxillary cursor
_mainCursor = MultiInitObject(pmi);
MultiInsertObject(_vm->_bg->GetPlayfieldList(FIELD_STATUS), _mainCursor);

View File

@ -69,8 +69,6 @@ public:
void InitCurObj();
void InitCurPos();
void DoCursorMove();
IMAGE *GetImageFromReel(const FREEL *pfr, const MULTI_INIT **ppmi = nullptr);
IMAGE *GetImageFromFilm(SCNHANDLE hFilm, int reel, const FREEL **ppfr = nullptr, const MULTI_INIT **ppmi = nullptr, const FILM **ppfilm = nullptr);
bool CursorIsFrozen() { return _frozenCursor; }
int NumTrails() { return _numTrails; }

View File

@ -2153,21 +2153,17 @@ void Dialogs::AdjustTop() {
* Insert an inventory icon object onto the display list.
*/
OBJECT *Dialogs::AddInvObject(int num, const FREEL **pfreel, const FILM **pfilm) {
INV_OBJECT *invObj; // Icon data
const MULTI_INIT *pmi; // Its INIT structure - from the reel
IMAGE *pim; // ... you get the picture
OBJECT *pPlayObj; // The object we insert
INV_OBJECT *invObj = GetInvObject(num);
const FILM *pFilm = (const FILM *)_vm->_handle->LockMem(invObj->hIconFilm);
const FREEL *pfr = (const FREEL *)&pFilm->reels[0];
const MULTI_INIT *pmi = (MULTI_INIT *)_vm->_handle->LockMem(FROM_32(pfr->mobj));
OBJECT *pPlayObj; // The object we insert
invObj = GetInvObject(num);
*pfreel = pfr;
*pfilm = pFilm;
PokeInPalette(pmi);
pPlayObj = MultiInitObject(pmi); // Needs to be initialized after the palette is set
// Get pointer to image
pim = _vm->_cursor->GetImageFromFilm(invObj->hIconFilm, 0, pfreel, &pmi, pfilm);
// Poke in the background palette
pim->hImgPal = TO_32(_vm->_bg->BgPal());
// Set up the multi-object
pPlayObj = MultiInitObject(pmi);
MultiInsertObject(_vm->_bg->GetPlayfieldList(FIELD_STATUS), pPlayObj);
return pPlayObj;
@ -2285,27 +2281,28 @@ void Dialogs::AddTitle(POBJECT *title, int extraH) {
* Insert a part of the inventory window frame onto the display list.
*/
OBJECT *Dialogs::AddObject(const FREEL *pfreel, int num) {
const MULTI_INIT *pmi; // Get the MULTI_INIT structure
IMAGE *pim;
const MULTI_INIT *pmi = (const MULTI_INIT *)_vm->_handle->LockMem(FROM_32(pfreel->mobj));
const FRAME *pFrame = (const FRAME *)_vm->_handle->LockMem(FROM_32(pmi->hMulFrame));
const IMAGE *pim;
OBJECT *pPlayObj;
// Get pointer to image
pim = _vm->_cursor->GetImageFromReel(pfreel, &pmi);
PokeInPalette(pmi);
// Poke in the background palette
pim->hImgPal = TO_32(_vm->_bg->BgPal());
pim = _vm->_handle->GetImage(READ_32(pFrame));
// Horrible bodge involving global variables to save
// width and/or height of some window frame components
if (num == _TL) {
_TLwidth = FROM_16(pim->imgWidth);
_TLheight = FROM_16(pim->imgHeight) & ~C16_FLAG_MASK;
_TLwidth = pim->imgWidth;
_TLheight = pim->imgHeight & ~C16_FLAG_MASK;
} else if (num == _TR) {
_TRwidth = FROM_16(pim->imgWidth);
_TRwidth = pim->imgWidth;
} else if (num == _BL) {
_BLheight = FROM_16(pim->imgHeight) & ~C16_FLAG_MASK;
_BLheight = pim->imgHeight & ~C16_FLAG_MASK;
}
delete pim;
// Set up and insert the multi-object
pPlayObj = MultiInitObject(pmi);
MultiInsertObject(_vm->_bg->GetPlayfieldList(FIELD_STATUS), pPlayObj);
@ -2990,16 +2987,13 @@ bool Dialogs::RePosition() {
* and customise the cursor.
*/
void Dialogs::AlterCursor(int num) {
const FREEL *pfreel;
IMAGE *pim;
const FILM *pFilm = (const FILM *)_vm->_handle->LockMem(_hWinParts);
const FREEL *pfr = (const FREEL *)&pFilm->reels[num];
const MULTI_INIT *pmi = (MULTI_INIT *)_vm->_handle->LockMem(FROM_32(pfr->mobj));
// Get pointer to image
pim = _vm->_cursor->GetImageFromFilm(_hWinParts, num, &pfreel);
PokeInPalette(pmi);
// Poke in the background palette
pim->hImgPal = TO_32(_vm->_bg->BgPal());
_vm->_cursor->SetTempCursor(FROM_32(pfreel->script));
_vm->_cursor->SetTempCursor(FROM_32(pfr->script));
}
/**

View File

@ -42,23 +42,14 @@ SCNHANDLE Font::GetTalkFontHandle() {
}
void Font::FettleFontPal(SCNHANDLE fontPal) {
IMAGE *pImg;
Handle *h = _vm->_handle;
assert(fontPal);
assert(_hTagFont); // Tag font not declared
assert(_hTalkFont); // Talk font not declared
pImg = (IMAGE *)_vm->_handle->LockMem(_vm->_handle->GetFontImageHandle(_hTagFont)); // get image for char 0
if (!TinselV2)
pImg->hImgPal = TO_32(fontPal);
else
pImg->hImgPal = 0;
pImg = (IMAGE *)_vm->_handle->LockMem(_vm->_handle->GetFontImageHandle(_hTalkFont)); // get image for char 0
if (!TinselV2)
pImg->hImgPal = TO_32(fontPal);
else
pImg->hImgPal = 0;
h->SetImagePalette(h->GetFontImageHandle(_hTagFont), !TinselV2 ? fontPal : 0); // get image for char 0
h->SetImagePalette(h->GetFontImageHandle(_hTalkFont), !TinselV2 ? fontPal : 0); // get image for char 0
if (TinselV2 && SysVar(SV_TAGCOLOR)) {
const COLORREF c = _vm->_actor->GetActorRGB(-1);

View File

@ -26,6 +26,7 @@
#include "common/memstream.h"
#include "common/textconsole.h"
#include "tinsel/background.h"
#include "tinsel/drives.h"
#include "tinsel/dw.h"
#include "tinsel/handle.h"
@ -305,28 +306,28 @@ void Handle::LoadFile(MEMHANDLE *pH) {
* @return FONT structure
*/
FONT *Handle::GetFont(SCNHANDLE offset) {
byte *fontData = LockMem(offset);
byte *data = LockMem(offset);
const bool isBE = TinselV1Mac || TinselV1Saturn;
const uint32 size = (TinselV3 ? 12 * 4 : 11 * 4) + 300 * 4; // FONT struct size
Common::MemoryReadStreamEndian *fontStream = new Common::MemoryReadStreamEndian(fontData, size, isBE);
Common::MemoryReadStreamEndian *stream = new Common::MemoryReadStreamEndian(data, size, isBE);
FONT *font = new FONT();
font->xSpacing = fontStream->readSint32();
font->ySpacing = fontStream->readSint32();
font->xShadow = fontStream->readSint32();
font->yShadow = fontStream->readSint32();
font->spaceSize = fontStream->readSint32();
font->baseColor = TinselV3 ? fontStream->readSint32() : 0;
font->fontInit.hObjImg = fontStream->readUint32();
font->fontInit.objFlags = fontStream->readSint32();
font->fontInit.objID = fontStream->readSint32();
font->fontInit.objX = fontStream->readSint32();
font->fontInit.objY = fontStream->readSint32();
font->fontInit.objZ = fontStream->readSint32();
font->xSpacing = stream->readSint32();
font->ySpacing = stream->readSint32();
font->xShadow = stream->readSint32();
font->yShadow = stream->readSint32();
font->spaceSize = stream->readSint32();
font->baseColor = TinselV3 ? stream->readSint32() : 0;
font->fontInit.hObjImg = stream->readUint32();
font->fontInit.objFlags = stream->readSint32();
font->fontInit.objID = stream->readSint32();
font->fontInit.objX = stream->readSint32();
font->fontInit.objY = stream->readSint32();
font->fontInit.objZ = stream->readSint32();
for (int i = 0; i < 300; i++)
font->fontDef[i] = fontStream->readUint32();
font->fontDef[i] = stream->readUint32();
delete fontStream;
delete stream;
return font;
}
@ -338,16 +339,16 @@ FONT *Handle::GetFont(SCNHANDLE offset) {
* @return PALETTE structure
*/
PALETTE *Handle::GetPalette(SCNHANDLE offset) {
byte *palData = LockMem(offset);
byte *data = LockMem(offset);
const bool isBE = TinselV1Mac || TinselV1Saturn;
const uint32 size = 4 + 256 * 4; // numColors + 256 COLORREF (max)
Common::MemoryReadStreamEndian *palStream = new Common::MemoryReadStreamEndian(palData, size, isBE);
Common::MemoryReadStreamEndian *stream = new Common::MemoryReadStreamEndian(data, size, isBE);
PALETTE *pal = new PALETTE();
pal->numColors = palStream->readSint32();
pal->numColors = stream->readSint32();
for (int32 i = 0; i < pal->numColors; i++) {
pal->palRGB[i] = palStream->readUint32();
pal->palRGB[i] = stream->readUint32();
// get the RGB color model values
pal->palette[i * 3] = (byte)(pal->palRGB[i] & 0xFF);
@ -355,11 +356,49 @@ PALETTE *Handle::GetPalette(SCNHANDLE offset) {
pal->palette[i * 3 + 2] = (byte)((pal->palRGB[i] >> 16) & 0xFF);
}
delete palStream;
delete stream;
return pal;
}
/**
* Return an image specified by a SCNHANDLE
* Handles endianess internally
* @param offset Handle and offset to data
* @return IMAGE structure
*/
const IMAGE *Handle::GetImage(SCNHANDLE offset) {
byte *data = LockMem(offset);
const bool isBE = TinselV1Mac || TinselV1Saturn;
const uint32 size = 16; // IMAGE struct size
Common::MemoryReadStreamEndian *stream = new Common::MemoryReadStreamEndian(data, size, isBE);
IMAGE *img = new IMAGE();
img->imgWidth = stream->readSint16();
img->imgHeight = stream->readUint16();
img->anioffX = stream->readSint16();
img->anioffY = stream->readSint16();
img->hImgBits = stream->readUint32();
if (!TinselV3) {
img->hImgPal = stream->readUint32();
} else {
img->isRLE = stream->readSint16();
img->colorFlags = stream->readSint16();
}
delete stream;
return img;
}
void Handle::SetImagePalette(SCNHANDLE offset, SCNHANDLE palHandle) {
byte *img = LockMem(offset);
WRITE_32(img + 12, palHandle); // hImgPal
}
SCNHANDLE Handle::GetFontImageHandle(SCNHANDLE offset) {
FONT *font = GetFont(offset);
SCNHANDLE handle = font->fontInit.hObjImg;

View File

@ -35,6 +35,7 @@ namespace Tinsel {
struct FONT;
struct MEMHANDLE;
struct PALETTE;
struct IMAGE;
class Handle {
public:
@ -48,6 +49,8 @@ public:
FONT *GetFont(SCNHANDLE offset);
PALETTE *GetPalette(SCNHANDLE offset);
const IMAGE *GetImage(SCNHANDLE offset);
void SetImagePalette(SCNHANDLE offset, SCNHANDLE palHandle);
SCNHANDLE GetFontImageHandle(SCNHANDLE offset);
byte *LockMem(SCNHANDLE offset);

View File

@ -718,11 +718,9 @@ static void InitialPathChecks(PMOVER pMover, int xpos, int ypos) {
}
static void MoverProcessHelper(int X, int Y, int id, PMOVER pMover) {
const FILM *pfilm;
const MULTI_INIT *pmi;
const FRAME *pFrame;
IMAGE *pim;
const FILM *pfilm = (const FILM *)_vm->_handle->LockMem(pMover->walkReels[0][FORWARD]);
const MULTI_INIT *pmi = (const MULTI_INIT *)_vm->_handle->LockMem(FROM_32(pfilm->reels[0].mobj));
const FRAME *pFrame = (const FRAME *)_vm->_handle->LockMem(FROM_32(pmi->hMulFrame));
assert(_vm->_bg->BgPal()); // Can't start actor without a background palette
assert(pMover->walkReels[0][FORWARD]); // Starting actor process without walk reels
@ -730,19 +728,11 @@ static void MoverProcessHelper(int X, int Y, int id, PMOVER pMover) {
InitMover(pMover);
InitialPathChecks(pMover, X, Y);
pfilm = (const FILM *)_vm->_handle->LockMem(pMover->walkReels[0][FORWARD]);
pmi = (const MULTI_INIT *)_vm->_handle->LockMem(FROM_32(pfilm->reels[0].mobj));
PokeInPalette(pmi);
//---
pFrame = (const FRAME *)_vm->_handle->LockMem(FROM_32(pmi->hMulFrame));
// get pointer to image
pim = (IMAGE *)_vm->_handle->LockMem(READ_32(pFrame)); // handle to image
pim->hImgPal = TO_32(_vm->_bg->BgPal());
//---
pMover->actorObj = MultiInitObject(pmi);
/**/ assert(pMover->actorID == id);
assert(pMover->actorID == id);
pMover->actorID = id;
// add it to display list

View File

@ -298,27 +298,29 @@ void SortObjectList(OBJECT **pObjList) {
*/
void GetAniOffset(SCNHANDLE hImg, int flags, int *pAniX, int *pAniY) {
if (hImg) {
const IMAGE *pImg = (const IMAGE *)_vm->_handle->LockMem(hImg);
const IMAGE *pImg = _vm->_handle->GetImage(hImg);
// set ani X
*pAniX = (int16) FROM_16(pImg->anioffX);
*pAniX = (int16) pImg->anioffX;
// set ani Y
*pAniY = (int16) FROM_16(pImg->anioffY);
*pAniY = (int16) pImg->anioffY;
if (flags & DMA_FLIPH) {
// we are flipped horizontally
// set ani X = -ani X + width - 1
*pAniX = -*pAniX + FROM_16(pImg->imgWidth) - 1;
*pAniX = -*pAniX + pImg->imgWidth - 1;
}
if (flags & DMA_FLIPV) {
// we are flipped vertically
// set ani Y = -ani Y + height - 1
*pAniY = -*pAniY + (FROM_16(pImg->imgHeight) & ~C16_FLAG_MASK) - 1;
*pAniY = -*pAniY + (pImg->imgHeight & ~C16_FLAG_MASK) - 1;
}
delete pImg;
} else
// null image
*pAniX = *pAniY = 0;
@ -370,12 +372,12 @@ OBJECT *InitObject(const OBJ_INIT *pInitTbl) {
if (pInitTbl->hObjImg) {
int aniX, aniY; // objects animation offsets
PALQ *pPalQ= nullptr; // palette queue pointer
const IMAGE *pImg = (const IMAGE *)_vm->_handle->LockMem(pInitTbl->hObjImg); // handle to image
const IMAGE *pImg = _vm->_handle->GetImage(pInitTbl->hObjImg); // handle to image
if (!TinselV3) {
if (pImg->hImgPal) {
// allocate a palette for this object
pPalQ = AllocPalette(FROM_32(pImg->hImgPal));
pPalQ = AllocPalette(pImg->hImgPal);
// make sure palette allocated
assert(pPalQ != NULL);
@ -384,26 +386,26 @@ OBJECT *InitObject(const OBJ_INIT *pInitTbl) {
// assign palette to object
pObj->pPal = pPalQ;
} else {
const IMAGE_T3 *pImgT3 = (const IMAGE_T3 *)pImg;
if ((pImgT3->colorFlags & 0x0C) == 0) { // bits 0b1100 are used to select blending mode
if ((pImg->colorFlags & 0x0C) == 0) { // bits 0b1100 are used to select blending mode
pObj->flags = pObj->flags & ~DMA_GHOST;
} else {
assert((pObj->flags & DMA_WNZ) != 0);
pObj->flags |= DMA_GHOST;
}
pObj->isRLE = pImgT3->isRLE;
pObj->colorFlags = pImgT3->colorFlags;
pObj->isRLE = pImg->isRLE;
pObj->colorFlags = pImg->colorFlags;
}
// set objects size
pObj->width = FROM_16(pImg->imgWidth);
pObj->height = FROM_16(pImg->imgHeight) & ~C16_FLAG_MASK;
pObj->width = pImg->imgWidth;
pObj->height = pImg->imgHeight & ~C16_FLAG_MASK;
pObj->flags &= ~C16_FLAG_MASK;
pObj->flags |= FROM_16(pImg->imgHeight) & C16_FLAG_MASK;
pObj->flags |= pImg->imgHeight & C16_FLAG_MASK;
// set objects bitmap definition
pObj->hBits = FROM_32(pImg->hImgBits);
pObj->hBits = pImg->hImgBits;
delete pImg;
// get animation offset of object
GetAniOffset(pObj->hImg, pInitTbl->objFlags, &aniX, &aniY);
@ -451,16 +453,18 @@ void AnimateObjectFlags(OBJECT *pAniObj, int newflags, SCNHANDLE hNewImg) {
if (hNewImg) {
// get pointer to image
const IMAGE *pNewImg = (IMAGE *)_vm->_handle->LockMem(hNewImg);
const IMAGE *pNewImg = _vm->_handle->GetImage(hNewImg);
// setup new shape
pAniObj->width = FROM_16(pNewImg->imgWidth);
pAniObj->height = FROM_16(pNewImg->imgHeight) & ~C16_FLAG_MASK;
pAniObj->width = pNewImg->imgWidth;
pAniObj->height = pNewImg->imgHeight & ~C16_FLAG_MASK;
newflags &= ~C16_FLAG_MASK;
newflags |= FROM_16(pNewImg->imgHeight) & C16_FLAG_MASK;
newflags |= pNewImg->imgHeight & C16_FLAG_MASK;
// set objects bitmap definition
pAniObj->hBits = FROM_32(pNewImg->hImgBits);
pAniObj->hBits = pNewImg->hImgBits;
delete pNewImg;
} else { // null image
pAniObj->width = 0;
pAniObj->height = 0;

View File

@ -55,34 +55,20 @@ enum {
};
/** structure for image */
#include "common/pack-start.h" // START STRUCT PACKING
struct IMAGE {
short imgWidth; ///< image width
unsigned short imgHeight; ///< image height
short anioffX; ///< image x animation offset
short anioffY; ///< image y animation offset
SCNHANDLE hImgBits; ///< image bitmap handle
SCNHANDLE hImgPal; ///< image palette handle
} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
/** structure for image in Tinsel 3 */
#include "common/pack-start.h" // START STRUCT PACKING
struct IMAGE_T3 {
short imgWidth; ///< image width
unsigned short imgHeight; ///< image height
short anioffX; ///< image x animation offset
short anioffY; ///< image y animation offset
SCNHANDLE hImgBits; ///< image bitmap handle
short isRLE; ///< if image is using run-length encoding
short colorFlags; ///< type of blending
} PACKED_STRUCT;
#include "common/pack-end.h" // END STRUCT PACKING
short imgWidth; ///< image width
unsigned short imgHeight; ///< image height
short anioffX; ///< image x animation offset
short anioffY; ///< image y animation offset
SCNHANDLE hImgBits; ///< image bitmap handle
SCNHANDLE hImgPal; ///< image palette handle (Tinsel V1/V2)
short isRLE; ///< if image is using run-length encoding (Tinsel V3)
short colorFlags; ///< type of blending (Tinsel V3)
};
/** a multi-object animation frame is a list of multi-image handles */
typedef uint32 FRAME;
// object structure
struct OBJECT {
OBJECT *pNext; ///< pointer to next object in list

View File

@ -88,17 +88,10 @@ void ResetVarsPlay() {
* Poke the background palette into an image.
*/
static void PokeInPalette(SCNHANDLE hMulFrame) {
const FRAME *pFrame; // Pointer to frame
IMAGE *pim; // Pointer to image
// Could be an empty column
if (hMulFrame) {
pFrame = (const FRAME *)_vm->_handle->LockMem(hMulFrame);
// get pointer to image
pim = (IMAGE *)_vm->_handle->LockMem(READ_32(pFrame)); // handle to image
pim->hImgPal = TO_32(_vm->_bg->BgPal());
const FRAME *pFrame = (const FRAME *)_vm->_handle->LockMem(hMulFrame);
_vm->_handle->SetImagePalette(READ_32(pFrame), _vm->_bg->BgPal());
}
}
@ -106,17 +99,10 @@ static void PokeInPalette(SCNHANDLE hMulFrame) {
* Poke the background palette into an image.
*/
void PokeInPalette(const MULTI_INIT *pmi) {
FRAME *pFrame; // Pointer to frame
IMAGE *pim; // Pointer to image
// Could be an empty column
if (pmi->hMulFrame) {
pFrame = (FRAME *)_vm->_handle->LockMem(FROM_32(pmi->hMulFrame));
// get pointer to image
pim = (IMAGE *)_vm->_handle->LockMem(READ_32(pFrame)); // handle to image
pim->hImgPal = TO_32(_vm->_bg->BgPal());
const FRAME *pFrame = (const FRAME *)_vm->_handle->LockMem(FROM_32(pmi->hMulFrame));
_vm->_handle->SetImagePalette(READ_32(pFrame), _vm->_bg->BgPal());
}
}

View File

@ -54,10 +54,12 @@ int StringLengthPix(char *szStr, const FONT *pFont) {
if (hImg) {
// there is a IMAGE for this character
const IMAGE *pChar = (const IMAGE *)_vm->_handle->LockMem(hImg);
const IMAGE *pChar = _vm->_handle->GetImage(hImg);
// add width of font bitmap
strLen += FROM_16(pChar->imgWidth);
strLen += pChar->imgWidth;
delete pChar;
} else
// use width of space character
strLen += pFont->spaceSize;
@ -116,7 +118,6 @@ OBJECT *ObjectTextOut(OBJECT **pList, char *szStr, int color,
OBJECT *pChar = 0; // object ptr for the character
byte c;
SCNHANDLE hImg;
const IMAGE *pImg;
// make sure there is a linked list to add text to
assert(pList);
@ -131,10 +132,11 @@ OBJECT *ObjectTextOut(OBJECT **pList, char *szStr, int color,
// get image for capital W
SCNHANDLE imgHandle = pFont->fontDef[(int)'W'];
assert(imgHandle);
pImg = (const IMAGE *)_vm->_handle->LockMem(imgHandle);
// get height of capital W for offset to next line
yOffset = FROM_16(pImg->imgHeight) & ~C16_FLAG_MASK;
const IMAGE *pImg = _vm->_handle->GetImage(imgHandle);
yOffset = pImg->imgHeight & ~C16_FLAG_MASK;
delete pImg;
while (*szStr) {
// x justify the text according to the mode flags
@ -166,13 +168,13 @@ OBJECT *ObjectTextOut(OBJECT **pList, char *szStr, int color,
pChar = pChar->pSlave = InitObject(pFontInit);
// convert image handle to pointer
pImg = (const IMAGE *)_vm->_handle->LockMem(hImg);
const IMAGE *pImg = _vm->_handle->GetImage(hImg);
// fill in character object
pChar->hImg = hImg; // image def
pChar->width = FROM_16(pImg->imgWidth); // width of chars bitmap
pChar->height = FROM_16(pImg->imgHeight) & ~C16_FLAG_MASK; // height of chars bitmap
pChar->hBits = FROM_32(pImg->hImgBits); // bitmap
pChar->width = pImg->imgWidth; // width of chars bitmap
pChar->height = pImg->imgHeight & ~C16_FLAG_MASK; // height of chars bitmap
pChar->hBits = pImg->hImgBits; // bitmap
// check for absolute positioning
if (mode & TXT_ABSOLUTE)
@ -233,7 +235,9 @@ OBJECT *ObjectTextOut(OBJECT **pList, char *szStr, int color,
pChar = pChar->pSlave;
// add character spacing
xJustify += FROM_16(pImg->imgWidth);
xJustify += pImg->imgWidth;
delete pImg;
}
// finally add the inter-character spacing

View File

@ -110,6 +110,7 @@ typedef bool (*KEYFPTR)(const Common::KeyState &);
#define READ_16(v) (TinselV1Mac || TinselV1Saturn ? READ_BE_UINT16(v) : READ_LE_UINT16(v))
#define READ_32(v) (TinselV1Mac || TinselV1Saturn ? READ_BE_UINT32(v) : READ_LE_UINT32(v))
#define WRITE_32(p, v) (TinselV1Mac || TinselV1Saturn ? WRITE_BE_UINT32(p, v) : WRITE_LE_UINT32(p, v))
#define FROM_16(v) (TinselV1Mac || TinselV1Saturn ? FROM_BE_16(v) : FROM_LE_16(v))
#define FROM_32(v) (TinselV1Mac || TinselV1Saturn ? FROM_BE_32(v) : FROM_LE_32(v))
#define TO_32(v) (TinselV1Mac || TinselV1Saturn ? TO_BE_32(v) : TO_LE_32(v))