MADS: In progress implementation of PaletteUsage::process

This commit is contained in:
Paul Gilbert 2014-03-10 00:00:39 -04:00
parent c89193f24f
commit 680b5a4487
15 changed files with 390 additions and 44 deletions

View File

@ -54,6 +54,7 @@ void SpriteAsset::load(Common::SeekableReadStream *stream, int flags) {
_pixelSpeed = 0;
_maxWidth = 0;
_maxHeight = 0;
_field6 = -1;
Common::SeekableReadStream *spriteStream = sprite.getItemStream(0);
_mode = spriteStream->readByte();

View File

@ -77,6 +77,7 @@ private:
void load(Common::SeekableReadStream *stream, int flags);
public:
SpriteSetCharInfo *_charInfo;
int _field6;
public:
/**
* Constructor

View File

@ -191,15 +191,16 @@ void Game::sectionLoop() {
switch (_vm->_screenFade) {
case SCREEN_FADE_SMOOTH:
_abortTimers2 = 2;
_abortTimers2 = kTransitionFadeOutIn;
break;
case SCREEN_FADE_FAST:
_abortTimers2 = 20;
_abortTimers2 = kCenterVertTransition;
break;
default:
_abortTimers2 = 21;
_abortTimers2 = kTransitionNone;
break;
}
_abortTimers = 0;
_abortTimersMode2 = ABORTMODE_1;
_priorFrameTimer = _scene._frameStartTime;

View File

@ -22,7 +22,9 @@
#include "common/scummsys.h"
#include "mads/mads.h"
#include "mads/game.h"
#include "mads/graphics.h"
#include "mads/palette.h"
namespace MADS {
@ -35,8 +37,41 @@ void ScreenSurface::updateScreen() {
g_system->updateScreen();
}
void ScreenSurface::transition(bool transitionFlag, bool surfaceFlag) {
void ScreenSurface::transition(ScreenTransition transitionType, bool surfaceFlag) {
switch (transitionType) {
case kTransitionFadeOutIn:
fadeOut();
fadeIn();
break;
case kTransitionFadeIn:
fadeIn();
break;
case kTransitionBoxInBottomLeft:
case kTransitionBoxInBottomRight:
case kTransitionBoxInTopLeft:
case kTransitionBoxInTopRight:
error("TODO: transition");
break;
case kTransitionPanLeftToRight:
case kTransitionPanRightToLeft:
error("TODO: transition");
case kTransitionCircleIn1:
case kTransitionCircleIn2:
case kTransitionCircleIn3:
case kTransitionCircleIn4:
error("TODO circle transition");
case kCenterVertTransition:
error("TODO: center vert transition");
default:
// Quick transitions
break;
}
}
void ScreenSurface::setPointer(MSurface *s) {
@ -44,5 +79,13 @@ void ScreenSurface::setPointer(MSurface *s) {
_pitch = s->w;
}
void ScreenSurface::fadeOut() {
warning("TODO: Proper fade out");
}
void ScreenSurface::fadeIn() {
warning("TODO: Proper fade in");
_vm->_palette->setFullPalette(_vm->_palette->_mainPalette);
}
} // End of namespace MADS

View File

@ -32,7 +32,30 @@ namespace MADS {
#define MADS_SCREEN_WIDTH 320
#define MADS_SCREEN_HEIGHT 200
enum ScreenTransition {
kTransitionNone = 0,
kTransitionFadeIn, kTransitionFadeOutIn,
kTransitionBoxInBottomLeft, kTransitionBoxInBottomRight,
kTransitionBoxInTopLeft, kTransitionBoxInTopRight,
kTransitionPanLeftToRight, kTransitionPanRightToLeft,
kTransitionCircleIn1, kTransitionCircleIn2,
kTransitionCircleIn3, kTransitionCircleIn4,
kVertTransition1, kVertTransition2, kVertTransition3,
kVertTransition4, kVertTransition5, kVertTransition6,
kVertTransition7, kCenterVertTransition
};
class ScreenSurface : public MSurface {
private:
/**
* Handles screen fade out
*/
void fadeOut();
/**
* Handles screen fade in
*/
void fadeIn();
public:
Common::Point _offset;
byte *_pixels;
@ -55,7 +78,7 @@ public:
*/
void updateScreen();
void transition(bool transitionFlag, bool surfaceFlag);
void transition(ScreenTransition transitionType, bool surfaceFlag);
};
} // End of namespace MADS

View File

@ -101,7 +101,7 @@ void InterfaceSurface::setup(int id) {
copyTo(&_surface);
if (_vm->_game->_v1 == 5)
scene._imageInterEntries.call(0);
scene._imageInterEntries.call(0, 0);
scene._action.clear();
writeText();

View File

@ -41,7 +41,7 @@ MADSEngine::MADSEngine(OSystem *syst, const MADSGameDescription *gameDesc) :
_easyMouse = true;
_invObjectStill = false;
_textWindowStill = false;
_screenFade = SCREEN_FADE_FAST;
_screenFade = SCREEN_FADE_SMOOTH;
_musicFlag = false;
_debugger = nullptr;

View File

@ -478,7 +478,7 @@ void MSurface::translate(Common::Array<RGB6> &palette) {
byte *pDest = getBasePtr(0, y);
for (int x = 0; x < this->w; ++x, ++pDest) {
*pDest = palette[*pDest].palIndex;
*pDest = palette[*pDest]._palIndex;
}
}
}

View File

@ -50,7 +50,7 @@ struct SpriteInfo {
* MADS graphics surface
*/
class MSurface : public Graphics::Surface {
private:
protected:
static MADSEngine *_vm;
public:
/**

View File

@ -32,14 +32,15 @@ void RGB6::load(Common::SeekableReadStream *f) {
r = f->readByte();
g = f->readByte();
b = f->readByte();
palIndex = f->readByte();
u2 = f->readByte();
flags = f->readByte();
_palIndex = f->readByte();
_u2 = f->readByte();
_flags = f->readByte();
}
/*------------------------------------------------------------------------*/
PaletteUsage::PaletteUsage() {
PaletteUsage::PaletteUsage(MADSEngine *vm) {
_vm = vm;
}
void PaletteUsage::load(int count, ...) {
@ -58,7 +59,7 @@ void PaletteUsage::getKeyEntries(Common::Array<RGB6> &palette) {
_data.clear();
for (uint i = 0; i < palette.size(); ++i) {
byte *uPtr = &palette[i].flags;
byte *uPtr = &palette[i]._flags;
if ((*uPtr & 0x10) && _data.size() < 3) {
_data.push_back(i);
}
@ -76,6 +77,124 @@ void PaletteUsage::prioritize(Common::Array<RGB6> &palette) {
prioritizeFromList(lst);
}
int PaletteUsage::process(Common::Array<RGB6> &palette, int v) {
byte *palette1 = nullptr, *palette2 = nullptr;
int palLow;
int palHigh = (v & 0x800) ? 0x100 : 0xC;
int palIdx;
assert(v >= 0);
if (v & 0x4000) {
palLow = 0;
palIdx = palHigh;
} else {
palLow = _vm->_palette->_lowRange;
if ((PALETTE_COUNT - _vm->_palette->_highRange) > palHigh) {
palIdx = palHigh;
} else {
palIdx = PALETTE_COUNT - _vm->_palette->_highRange;
}
}
int rgbIndex = _vm->_palette->_rgbList.scan();
uint32 rgbMask = 1 << rgbIndex;
int varA = v & 0x8000;
bool hasUsage = !_vm->_palette->_paletteUsage.empty();
bool flag1 = false;
if (hasUsage) {
if (varA || !_vm->_palette->_paletteUsage[0])
hasUsage = false;
if (varA && _vm->_palette->_paletteUsage[0])
flag1 = true;
}
if (hasUsage) {
getKeyEntries(palette);
prioritize(palette);
}
int freeIndex;
int palCount = getGamePalFreeIndex(&freeIndex);
byte *pal1 = new byte[PALETTE_COUNT];
byte *pal2 = new byte[PALETTE_COUNT];
for (uint palIndex = 0; palIndex < palette.size(); ++palIndex) {
pal2[palIndex] = palIndex;
pal1[palIndex] = 0;
if (!(palette[palIndex]._flags & 0x80)) {
pal1[palIndex] = 0x40;
}
if (!(palette[palIndex]._flags & 0x60)) {
pal1[palIndex] |= 0x20;
}
}
_vm->_palette->processLists(palette.size(), pal1, pal2);
int var3A = (v & 0x4000) ? 0xffff : 0xfffe;
for (uint palIndex = 0; palIndex < palette.size(); ++palIndex) {
bool var48 = false;
int var4 = 0xffff;
int v1 = pal1[palIndex];
if (palette[v1]._flags & 8) {
var48 = true;
var4 = 0xFD;
}
if (hasUsage && palette[v1]._flags & 0x10) {
for (uint usageIndex = 0; usageIndex < _data.size() && !var48; ++usageIndex) {
if (_data[usageIndex] == palIndex) {
var48 = true;
int dataIndex = MIN(usageIndex, _data.size() - 1);
var4 = _data[dataIndex];
}
}
}
if (flag1 && palette[palIndex]._flags & 0x10) {
for (uint usageIndex = 0; usageIndex < _data.size() && !var48; ++usageIndex) {
if (_data[usageIndex] == palIndex) {
var48 = true;
var4 = 0xF0 + usageIndex;
// Copy data into the high end of the main palette
RGB6 &pSrc = palette[palIndex];
byte *pDest = &_vm->_palette->_mainPalette[var4 * 3];
pDest[0] = pSrc.r;
pDest[1] = pSrc.g;
pDest[2] = pSrc.b;
}
}
}
if (!var48 && !varA) {
int var2 = !(palette[palIndex]._flags & 0x20) && (
((v & 0x2000) && !(palette[palIndex]._flags & 0x40)) ||
((v & 0x1000) && (palCount > 0))
) ? 1 : 0x7fff;
int var36 = (palette[palIndex]._flags & 0x80) ? 0 : 2;
for (int idx = palLow; idx < palIdx; ++idx) {
// TODO
}
}
//TODO
}
_vm->_palette->_rgbList[rgbIndex] = 0xffff;
delete[] pal1;
delete[] pal2;
return rgbIndex;
}
int PaletteUsage::rgbMerge(RGB6 &palEntry) {
return palEntry.r * 38 + palEntry.g * 76 + palEntry.b * 14;
}
@ -137,19 +256,56 @@ void PaletteUsage::transform(Common::Array<RGB6> &palette) {
if (!empty()) {
for (uint i = 0; i < _data.size(); ++i) {
int palIndex = _data[i];
_data[i] = palette[palIndex].palIndex;
_data[i] = palette[palIndex]._palIndex;
}
}
}
int PaletteUsage::getGamePalFreeIndex(int *palIndex) {
*palIndex = -1;
int count = 0;
for (int i = 0; i < PALETTE_COUNT; ++i) {
RGB4 &r = _vm->_palette->_gamePalette[i];
if (!(r.r | r.g | r.b | r.u)) {
++count;
if (*palIndex < 0)
*palIndex = i;
}
}
return count;
}
/*------------------------------------------------------------------------*/
void RGBList::clear() {
Common::fill(&_data[0], &_data[32], 0);
}
void RGBList::reset() {
Common::fill(&_data[2], &_data[32], 0);
}
int RGBList::scan() {
for (int i = 0; i < 32; ++i) {
if (!_data[i])
return i;
}
error("List was full");
}
/*------------------------------------------------------------------------*/
#define VGA_COLOR_TRANS(x) (x == 0x3f ? 255 : x << 2)
Palette::Palette(MADSEngine *vm) : _vm(vm) {
Palette::Palette(MADSEngine *vm) : _vm(vm), _paletteUsage(vm) {
reset();
_fading_in_progress = false;
Common::fill(&_usageCount[0], &_usageCount[PALETTE_COUNT], 0);
_v1 = 0;
_lowRange = 0;
_highRange = 0;
Common::fill(&_mainPalette[0], &_mainPalette[PALETTE_SIZE], 0);
}
@ -228,6 +384,49 @@ void Palette::setGradient(byte *palette, int start, int count, int rgbValue1, in
}
}
void Palette::processLists(int count, byte *pal1, byte *pal2) {
bool continueFlag;
int endIndex = count - 1;
do {
continueFlag = false;
for (int palIndex = 0; palIndex < endIndex && !continueFlag; ++palIndex) {
byte *palP = &pal1[palIndex];
byte *pal2P = &pal2[palIndex];
if (palP[1] < palP[0]) {
int v1 = palP[0];
int v2 = pal2P[0];
int size = count - palIndex - 1;
if (size > 0) {
Common::copy(palP + 1, palP + size + 1, palP);
Common::copy(pal2P + 1, pal2P + size + 1, pal2P);
}
int idx;
for (idx = 0; idx < endIndex && !continueFlag; ++idx) {
if (pal1[idx] > v1)
continueFlag = true;
}
continueFlag = true;
int size2 = count - idx - 1;
if (size2 > 0) {
Common::copy(palP + idx, palP + idx + size2 + 1, palP);
Common::copy(pal2P + idx, pal2P + idx + size2 + 1, pal2P);
}
pal1[idx] = v1;
pal2[idx] = v2;
}
}
} while (continueFlag);
}
byte *Palette::decodePalette(Common::SeekableReadStream *palStream, int *numColors) {
*numColors = palStream->readUint16LE();
assert(*numColors <= 252);
@ -288,10 +487,43 @@ void Palette::resetGamePalette(int lowRange, int highRange) {
Common::fill(&_gamePalette[255 - highRange], &_gamePalette[254], _gamePalette[255]);
}
_rgbList.clear();
_v1 = 0;
_lowRange = lowRange;
_highRange = highRange;
}
void Palette::initGamePalette() {
// TODO
RGB4 rgb;
rgb.r = 1;
if (_vm->_game->_player._spritesLoaded && _vm->_game->_player._numSprites) {
for (int idx = 0; idx < _vm->_game->_player._numSprites; ++idx) {
SpriteAsset *asset = _vm->_game->_scene._sprites[
_vm->_game->_player._spritesStart + idx];
uint32 mask = 1;
if (asset->_field6)
mask <<= asset->_field6;
rgb.r = mask & 0xff;
rgb.g = (mask >> 8) & 0xff;
rgb.b = (mask >> 16) & 0xff;
rgb.u = (mask >> 24) & 0xff;
}
}
for (int idx = 0; idx < PALETTE_COUNT; ++idx) {
_gamePalette[idx].r &= rgb.r;
_gamePalette[idx].g &= rgb.g;
_gamePalette[idx].b &= rgb.b;
_gamePalette[idx].u &= rgb.u;
}
_v1 = 0;
_rgbList.reset();
}
void Palette::initRange(byte *palette) {
@ -337,4 +569,9 @@ void Palette::setLowRange() {
_vm->_palette->setPalette(_mainPalette, 0, 4);
}
void Palette::fadeOut(byte palette[PALETTE_SIZE], int v1, int v2, int v3, int v4, int v5, int v6) {
}
} // End of namespace MADS

View File

@ -37,28 +37,36 @@ struct RGB4 {
byte g;
byte b;
byte u;
RGB4() { r = g = b = u = 0; }
};
struct RGB6 {
byte r;
byte g;
byte b;
byte palIndex;
byte u2;
byte flags;
byte _palIndex;
byte _u2;
byte _flags;
void load(Common::SeekableReadStream *f);
};
class PaletteUsage {
private:
Common::Array<int> _data;
MADSEngine *_vm;
Common::Array<uint16> _data;
int rgbMerge(RGB6 &palEntry);
void prioritizeFromList(int lst[3]);
int getGamePalFreeIndex(int *palIndex);
public:
PaletteUsage();
/**
* Constructor
*/
PaletteUsage(MADSEngine *vm);
void load(int count, ...);
@ -67,6 +75,8 @@ public:
*/
bool empty() const { return _data.size() == 0; }
uint16 &operator[](int index) { return _data[index]; }
/**
* Gets key entries from the passed palette
* @param palette 6-bit per entry read in palette
@ -79,14 +89,28 @@ public:
*/
void prioritize(Common::Array<RGB6> &palette);
bool process(Common::Array<RGB6> &palette, int v) {
warning("TODO: PaletteUsage::process");
return 0;
}
int process(Common::Array<RGB6> &palette, int v);
void transform(Common::Array<RGB6> &palette);
};
class RGBList {
private:
uint16 _data[32];
public:
RGBList() { clear(); }
void clear();
void reset();
/**
* Scans for a free slot
*/
int scan();
uint16 &operator[](int idx) { return _data[idx]; }
};
#define PALETTE_COUNT 256
#define PALETTE_SIZE (256 * 3)
@ -99,12 +123,6 @@ private:
void initRange(byte *palette);
protected:
MADSEngine *_vm;
bool _colorsChanged;
bool _fading_in_progress;
byte _originalPalette[PALETTE_COUNT * 4];
byte _fadedPalette[PALETTE_COUNT * 4];
int _usageCount[PALETTE_COUNT];
void reset();
public:
@ -112,6 +130,10 @@ public:
byte _savedPalette[PALETTE_SIZE];
RGB4 _gamePalette[PALETTE_COUNT];
PaletteUsage _paletteUsage;
RGBList _rgbList;
int _v1;
int _lowRange;
int _highRange;
public:
/**
* Constructor
@ -138,6 +160,20 @@ public:
*/
void grabPalette(byte *colors, uint start, uint num);
/**
* Gets the entire palette at once
*/
void getFullPalette(byte palette[PALETTE_SIZE]) {
grabPalette(&palette[0], 0, PALETTE_COUNT);
}
/**
* Sets the entire palette at once
*/
void setFullPalette(byte palette[PALETTE_SIZE]) {
setPalette(&palette[0], 0, PALETTE_COUNT);
}
/**
* Returns the palette index in the palette that most closely matches the
* specified RGB pair
@ -164,6 +200,8 @@ public:
*/
static void setGradient(byte *palette, int start, int count, int rgbValue1, int rgbValue2);
static void processLists(int count, byte *pal1, byte *pal2);
/**
* Resets the game palette
*/
@ -185,6 +223,8 @@ public:
void close() {
warning("TODO: Palette::close");
}
void fadeOut(byte palette[PALETTE_SIZE], int v1, int v2, int v3, int v4, int v5, int v6);
};
} // End of namespace MADS

View File

@ -384,16 +384,15 @@ void Scene::doFrame() {
_kernelMessages.update();
}
_vm->_game->_abortTimers2 = !_vm->_game->_abortTimers2;
warning("TODO: image_inter_list_call");
_imageInterEntries.call(_vm->_game->_abortTimers2 == kTransitionFadeIn ? 0xff : 0,
_vm->_game->_abortTimers2);
// Write any text needed by the interface
if (_vm->_game->_abortTimers2)
_interface.writeText();
// Draw any elements
drawElements(_vm->_game->_abortTimers2, _vm->_game->_abortTimers2);
drawElements((ScreenTransition)_vm->_game->_abortTimers2, _vm->_game->_abortTimers2);
// Handle message updates
if (_vm->_game->_abortTimers2) {
@ -425,7 +424,7 @@ void Scene::doFrame() {
_vm->_events->waitForNextFrame();
}
void Scene::drawElements(bool transitionFlag, bool surfaceFlag) {
void Scene::drawElements(ScreenTransition transitionType, bool surfaceFlag) {
// Draw any sprites
_spriteSlots.drawBackground();
@ -455,9 +454,9 @@ void Scene::drawElements(bool transitionFlag, bool surfaceFlag) {
_interface.setBounds(Common::Rect(_vm->_screen._offset.x, _vm->_screen._offset.y,
_vm->_screen._offset.x + _vm->_screen.w, _vm->_screen._offset.y + _vm->_screen.h));
if (transitionFlag) {
if (transitionType) {
// Fading in the screen
_vm->_screen.transition(transitionFlag, surfaceFlag);
_vm->_screen.transition(transitionType, surfaceFlag);
_vm->_sound->startQueuedCommands();
} else {
// Copy dirty areas to the screen

View File

@ -27,6 +27,7 @@
#include "common/array.h"
#include "common/rect.h"
#include "mads/assets.h"
#include "mads/graphics.h"
#include "mads/hotspots.h"
#include "mads/messages.h"
#include "mads/msurface.h"
@ -189,7 +190,7 @@ public:
/**
* Draw all the elements onto the scene
*/
void drawElements(bool transitionFlag, bool surfaceFlag);
void drawElements(ScreenTransition transitionType, bool surfaceFlag);
/**
* Execute a click within the scene

View File

@ -395,7 +395,7 @@ int ImageInterEntries::add(int field0, int field2) {
return size() - 1;
}
void ImageInterEntries::call(int v1) {
void ImageInterEntries::call(int v1, int v2) {
debug("TODO: ImageInterEntries::call");
}

View File

@ -235,7 +235,7 @@ class ImageInterEntries: public Common::Array<ImageInterEntry> {
public:
int add(int field0, int field2);
void call(int v1);
void call(int v1, int v2);
};
} // End of namespace MADS