FREESCAPE: allow to change the palette of title and border per level using managed surfaces

This commit is contained in:
neuromancer 2023-03-07 16:09:41 +01:00
parent 3c9cbb3fe0
commit 22fcff4ece
6 changed files with 113 additions and 131 deletions

View File

@ -193,16 +193,12 @@ void FreescapeEngine::drawBorder() {
void FreescapeEngine::drawTitle() {
_gfx->setViewport(_fullscreenViewArea);
if (isSpectrum()) {
Graphics::ManagedSurface *title = new Graphics::ManagedSurface();
title->create(320, 200, _title->format);
title->copyRectToSurface(*_title, (320 - _title->w) / 2, (200 - _title->h) / 2, Common::Rect(_title->w, _title->h));
_title->free();
delete _title;
_title = title;
if (!_titleTexture) {
Graphics::Surface *title = _gfx->convertImageFormatIfNecessary(_title);
_titleTexture = _gfx->createTexture(title);
title->free();
delete title;
}
if (!_titleTexture)
_titleTexture = _gfx->createTexture(&_title->rawSurface());
_gfx->drawTexturedRect2D(_fullscreenViewArea, _fullscreenViewArea, _titleTexture);
_gfx->setViewport(_viewArea);
}
@ -540,8 +536,6 @@ Common::Error FreescapeEngine::run() {
initGameState();
loadColorPalette();
_gfx->convertImageFormatIfNecessary(_title);
_gfx->convertImageFormatIfNecessary(_border);
g_system->lockMouse(true);
// Simple main event loop
@ -597,28 +591,37 @@ void FreescapeEngine::titleScreen() {}
void FreescapeEngine::borderScreen() {}
void FreescapeEngine::loadBorder() {
if (_border)
_borderTexture = _gfx->createTexture(&_border->rawSurface());
if (_border) {
Graphics::Surface *border = _gfx->convertImageFormatIfNecessary(_border);
_borderTexture = _gfx->createTexture(border);
border->free();
delete border;
}
}
void FreescapeEngine::processBorder() {
if (_border) {
if (_borderTexture)
delete _borderTexture;
Graphics::Surface *border = _gfx->convertImageFormatIfNecessary(_border);
uint32 gray = _gfx->_texturePixelFormat.ARGBToColor(0x00, 0xA0, 0xA0, 0xA0);
_border->fillRect(_viewArea, gray);
border->fillRect(_viewArea, gray);
// Replace black pixel for transparent ones
uint32 black = _border->format.ARGBToColor(0xFF, 0x00, 0x00, 0x00);
uint32 transparent = _border->format.ARGBToColor(0x00, 0x00, 0x00, 0x00);
uint32 black = border->format.ARGBToColor(0xFF, 0x00, 0x00, 0x00);
uint32 transparent = border->format.ARGBToColor(0x00, 0x00, 0x00, 0x00);
for (int i = 0; i < _border->w; i++) {
for (int j = 0; j < _border->h; j++) {
if (_border->getPixel(i, j) == black)
_border->setPixel(i, j, transparent);
for (int i = 0; i < border->w; i++) {
for (int j = 0; j < border->h; j++) {
if (border->getPixel(i, j) == black)
border->setPixel(i, j, transparent);
}
}
_borderTexture = _gfx->createTexture(&_border->rawSurface());
_borderTexture = _gfx->createTexture(border);
border->free();
delete border;
}
}

View File

@ -29,59 +29,6 @@
namespace Freescape {
enum {
kDrillerCGAPalettePinkBlue = 0,
kDrillerCGAPaletteRedGreen = 1,
};
static const struct CGAPalettteEntry {
int areaId;
int palette;
} rawCGAPaletteTable[] {
{1, kDrillerCGAPaletteRedGreen},
{2, kDrillerCGAPalettePinkBlue},
{3, kDrillerCGAPaletteRedGreen},
{4, kDrillerCGAPalettePinkBlue},
{5, kDrillerCGAPaletteRedGreen},
{6, kDrillerCGAPalettePinkBlue},
{7, kDrillerCGAPaletteRedGreen},
{8, kDrillerCGAPalettePinkBlue},
{9, kDrillerCGAPaletteRedGreen},
{10, kDrillerCGAPalettePinkBlue},
{11, kDrillerCGAPaletteRedGreen},
{12, kDrillerCGAPalettePinkBlue},
{14, kDrillerCGAPalettePinkBlue},
{16, kDrillerCGAPalettePinkBlue},
{19, kDrillerCGAPaletteRedGreen},
{20, kDrillerCGAPalettePinkBlue},
{21, kDrillerCGAPaletteRedGreen},
{22, kDrillerCGAPalettePinkBlue},
{23, kDrillerCGAPaletteRedGreen},
{28, kDrillerCGAPalettePinkBlue},
{32, kDrillerCGAPalettePinkBlue},
{127, kDrillerCGAPaletteRedGreen},
{0, 0} // This marks the end
};
byte kDrillerCGAPalettePinkBlueData[4][3] = {
{0x00, 0x00, 0x00},
{0x00, 0xaa, 0xaa},
{0xaa, 0x00, 0xaa},
{0xaa, 0xaa, 0xaa},
};
byte kDrillerCGAPaletteRedGreenData[4][3] = {
{0x00, 0x00, 0x00},
{0x00, 0xaa, 0x00},
{0xaa, 0x00, 0x00},
{0xaa, 0x55, 0x00},
};
enum {
kDrillerNoRig = 0,
kDrillerRigInPlace = 1,
@ -147,7 +94,7 @@ void DrillerEngine::titleScreen() {
if (isDOS() && isDemo()) // Demo will not show any title screen
return;
if (isAmiga() || isAtariST()) // These releases has their own screens
if (isAmiga() || isAtariST()) // TODO: implement these with their own animations
return;
if (_title) {
@ -161,7 +108,7 @@ void DrillerEngine::borderScreen() {
if (isDOS() && isDemo()) // Demo will not show the border
return;
if (isAmiga() || isAtariST()) // These releases has their own screens
if (isAmiga() || isAtariST()) // TODO: implement these with their own animations
return;
if (_border) {
@ -346,47 +293,6 @@ void DrillerEngine::loadAssetsFullGame() {
void DrillerEngine::processBorder() {
FreescapeEngine::processBorder();
if (isDOS() && _renderMode == Common::kRenderCGA) { // Replace some colors for the CGA borders
uint32 color1 = _border->format.ARGBToColor(0xFF, 0xAA, 0x00, 0xAA);
uint32 color2 = _border->format.ARGBToColor(0xFF, 0xAA, 0x55, 0x00);
uint32 colorA = _border->format.ARGBToColor(0xFF, 0x00, 0xAA, 0xAA);
uint32 colorB = _border->format.ARGBToColor(0xFF, 0x00, 0xAA, 0x00);
uint32 colorX = _border->format.ARGBToColor(0xFF, 0xAA, 0xAA, 0xAA);
uint32 colorY = _border->format.ARGBToColor(0xFF, 0xAA, 0x00, 0x00);
Graphics::Surface *borderRedGreen = new Graphics::Surface();
borderRedGreen->create(1, 1, _border->format);
borderRedGreen->copyFrom(*_border);
for (int i = 0; i < _border->w; i++) {
for (int j = 0; j < _border->h; j++) {
if (borderRedGreen->getPixel(i, j) == color1)
borderRedGreen->setPixel(i, j, color2);
else if (borderRedGreen->getPixel(i, j) == colorA)
borderRedGreen->setPixel(i, j, colorB);
else if (borderRedGreen->getPixel(i, j) == colorX)
borderRedGreen->setPixel(i, j, colorY);
}
}
Texture *borderTextureRedGreen = _gfx->createTexture(borderRedGreen);
const CGAPalettteEntry *entry = rawCGAPaletteTable;
while (entry->areaId) {
if (entry->palette == kDrillerCGAPaletteRedGreen) {
_borderCGAByArea[entry->areaId] = borderTextureRedGreen;
_paletteCGAByArea[entry->areaId] = (byte *)kDrillerCGAPaletteRedGreenData;
} else if (entry->palette == kDrillerCGAPalettePinkBlue) {
_borderCGAByArea[entry->areaId] = _borderTexture;
_paletteCGAByArea[entry->areaId] = (byte *)kDrillerCGAPalettePinkBlueData;
} else
error("Invalid CGA palette to use");
entry++;
}
}
}
void DrillerEngine::drawUI() {

View File

@ -155,6 +155,59 @@ void FreescapeEngine::loadPalettes(Common::SeekableReadStream *file, int offset)
}
}
enum {
kDrillerCGAPalettePinkBlue = 0,
kDrillerCGAPaletteRedGreen = 1,
};
static const struct CGAPalettteEntry {
int areaId;
int palette;
} rawCGAPaletteTable[] {
{1, kDrillerCGAPaletteRedGreen},
{2, kDrillerCGAPalettePinkBlue},
{3, kDrillerCGAPaletteRedGreen},
{4, kDrillerCGAPalettePinkBlue},
{5, kDrillerCGAPaletteRedGreen},
{6, kDrillerCGAPalettePinkBlue},
{7, kDrillerCGAPaletteRedGreen},
{8, kDrillerCGAPalettePinkBlue},
{9, kDrillerCGAPaletteRedGreen},
{10, kDrillerCGAPalettePinkBlue},
{11, kDrillerCGAPaletteRedGreen},
{12, kDrillerCGAPalettePinkBlue},
{14, kDrillerCGAPalettePinkBlue},
{16, kDrillerCGAPalettePinkBlue},
{19, kDrillerCGAPaletteRedGreen},
{20, kDrillerCGAPalettePinkBlue},
{21, kDrillerCGAPaletteRedGreen},
{22, kDrillerCGAPalettePinkBlue},
{23, kDrillerCGAPaletteRedGreen},
{28, kDrillerCGAPalettePinkBlue},
{32, kDrillerCGAPalettePinkBlue},
{127, kDrillerCGAPaletteRedGreen},
{0, 0} // This marks the end
};
byte kDrillerCGAPalettePinkBlueData[4][3] = {
{0x00, 0x00, 0x00},
{0x00, 0xaa, 0xaa},
{0xaa, 0x00, 0xaa},
{0xaa, 0xaa, 0xaa},
};
byte kDrillerCGAPaletteRedGreenData[4][3] = {
{0x00, 0x00, 0x00},
{0x00, 0xaa, 0x00},
{0xaa, 0x00, 0x00},
{0xaa, 0x55, 0x00},
};
void FreescapeEngine::swapPalette(uint16 levelID) {
if (isAmiga() || isAtariST())
_gfx->_palette = _paletteByArea[levelID];
@ -163,11 +216,28 @@ void FreescapeEngine::swapPalette(uint16 levelID) {
_gfx->_paperColor = _areaMap[levelID]->_paperColor;
_gfx->_underFireBackgroundColor = _areaMap[levelID]->_underFireBackgroundColor;
} else if (isDOS() && _renderMode == Common::kRenderCGA) {
assert(_borderCGAByArea.contains(levelID));
assert(_paletteCGAByArea.contains(levelID));
_borderTexture = _borderCGAByArea.getVal(levelID);
_gfx->_palette = _paletteCGAByArea.getVal(levelID);
const CGAPalettteEntry *entry = rawCGAPaletteTable;
while (entry->areaId) {
if (entry->areaId == levelID) {
if (entry->palette == kDrillerCGAPaletteRedGreen) {
_gfx->_palette = (byte *)kDrillerCGAPaletteRedGreenData;
} else if (entry->palette == kDrillerCGAPalettePinkBlue) {
_gfx->_palette = (byte *)kDrillerCGAPalettePinkBlueData;
} else
error("Invalid CGA palette to use");
break;
}
entry++;
}
assert(entry->areaId == levelID);
_border->setPalette(_gfx->_palette, 0, 4);
processBorder();
} else if (isDOS() && _renderMode == Common::kRenderEGA) {
_border->setPalette(_gfx->_palette, 0, 4);
processBorder();
}
}
} // End of namespace Freescape

View File

@ -342,16 +342,18 @@ void Renderer::flipVertical(Graphics::Surface *s) {
}
}
void Renderer::convertImageFormatIfNecessary(Graphics::ManagedSurface *surface) {
if (!surface)
return;
Graphics::Surface *Renderer::convertImageFormatIfNecessary(Graphics::ManagedSurface *msurface) {
if (!msurface)
return nullptr;
if (surface->format != _texturePixelFormat) {
byte *palette = (byte *)malloc(sizeof(byte) * 16 * 3);
surface->grabPalette(palette, 0, 16); // Maximum should be 16 colours
surface->convertToInPlace(_texturePixelFormat, palette);
free(palette);
}
assert(msurface->format != _texturePixelFormat);
Graphics::Surface *surface = new Graphics::Surface();
surface->copyFrom(msurface->rawSurface());
byte *palette = (byte *)malloc(sizeof(byte) * 16 * 3);
msurface->grabPalette(palette, 0, 16); // Maximum should be 16 colours
surface->convertToInPlace(_texturePixelFormat, palette);
free(palette);
return surface;
}
Common::Rect Renderer::viewport() const {

View File

@ -77,7 +77,7 @@ public:
virtual void polygonOffset(bool enabled) = 0;
virtual Texture *createTexture(const Graphics::Surface *surface) = 0;
void convertImageFormatIfNecessary(Graphics::ManagedSurface *surface);
Graphics::Surface *convertImageFormatIfNecessary(Graphics::ManagedSurface *surface);
virtual void freeTexture(Texture *texture) = 0;
virtual void drawTexturedRect2D(const Common::Rect &screenRect, const Common::Rect &textureRect, Texture *texture) = 0;

View File

@ -310,6 +310,7 @@ void FreescapeEngine::renderPixels8bitBinImage(Graphics::ManagedSurface *surface
if (acc & pixels) {
int previousColor = surface->getPixel(i, j);
surface->setPixel(i, j, previousColor + color);
assert(previousColor + color < 16);
}
i++;
acc = acc >> 1;