FREESCAPE: refactored and improved reading of dos images based on farmboy0 code

This commit is contained in:
neuromancer 2023-08-27 13:12:43 +02:00
parent 130b41995e
commit bedf52f9dc
9 changed files with 140 additions and 194 deletions

View File

@ -204,12 +204,17 @@ public:
Group *load8bitGroupV2(Common::SeekableReadStream *file, byte rawFlagsAndType);
void loadGlobalObjects(Common::SeekableReadStream *file, int offset, int size);
void renderPixels8bitBinImage(Graphics::ManagedSurface *surface, int &i, int &j, uint8 pixels, int color);
void renderPixels8bitBinImage(Graphics::ManagedSurface *surface, int row, int column, int bit, int count);
void renderPixels8bitBinCGAImage(Graphics::ManagedSurface *surface, int &i, int &j, uint8 pixels, int color);
void renderPixels8bitBinEGAImage(Graphics::ManagedSurface *surface, int &i, int &j, uint8 pixels, int color);
Graphics::ManagedSurface *load8bitBinImage(Common::SeekableReadStream *file, int offset);
void load8bitBinImageRow(Common::SeekableReadStream *file, Graphics::ManagedSurface *surface, int row);
void load8bitBinImageRowIteration(Common::SeekableReadStream *file, Graphics::ManagedSurface *surface, int row, int bit);
int execute8bitBinImageCommand(Common::SeekableReadStream *file, Graphics::ManagedSurface *surface, int row, int pixels, int bit);
int execute8bitBinImageSingleCommand(Common::SeekableReadStream *file, Graphics::ManagedSurface *surface, int row, int pixels, int bit, int count);
int execute8bitBinImageMultiCommand(Common::SeekableReadStream *file, Graphics::ManagedSurface *surface, int row, int pixels, int bit, int count);
// Areas
uint16 _startArea;

View File

@ -46,62 +46,6 @@ CastleEngine::~CastleEngine() {
}
}
byte kCastleTitleDOSPalette[16][3] = {
{0x00, 0x00, 0x00}, // correct!
{0x00, 0x00, 0xaa}, // correct!
{0x00, 0x00, 0x00}, // ????
{0x00, 0xaa, 0xaa}, // changed
{0x55, 0x55, 0x55}, // changed
{0x55, 0x55, 0xff}, // changed
{0xaa, 0xaa, 0xaa}, // changed
{0x55, 0xff, 0xff}, // changed
{0xff, 0x55, 0xff}, // changed
{0x00, 0x00, 0x00},
{0xff, 0xff, 0xff}, // changed
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00}
};
byte kCastleOptionDOSPalette[16][3] = {
{0x00, 0x00, 0x00},
{0x00, 0x00, 0xaa},
{0x00, 0xaa, 0x00},
{0xaa, 0x00, 0x00},
{0x55, 0x55, 0x55},
{0xaa, 0x55, 0x00},
{0xaa, 0xaa, 0xaa},
{0xff, 0x55, 0x55},
{0x12, 0x34, 0x56},
{0xff, 0xff, 0x55},
{0xff, 0xff, 0xff},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00}
};
byte kCastleBorderDOSPalette[16][3] = {
{0x00, 0x00, 0x00},
{0x00, 0x00, 0xaa},
{0x00, 0xaa, 0x00},
{0xaa, 0x00, 0x00},
{0x55, 0x55, 0x55},
{0xaa, 0x55, 0x00},
{0xaa, 0xaa, 0xaa}, // can be also green
{0xff, 0x55, 0x55},
{0x00, 0x00, 0x00},
{0xff, 0xff, 0x55},
{0xff, 0xff, 0xff},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00}
};
byte kFreescapeCastleFont[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1c, 0x1c, 0x1c, 0x18, 0x18, 0x00, 0x18, 0x18,
@ -184,7 +128,7 @@ Common::SeekableReadStream *CastleEngine::decryptFile(const Common::String filen
return (new Common::MemoryReadStream(encryptedBuffer, size));
}
extern byte kEGADefaultPaletteData[16][3];
extern byte kEGADefaultPalette[16][3];
void CastleEngine::loadAssetsDOSFullGame() {
Common::File file;
@ -195,17 +139,17 @@ void CastleEngine::loadAssetsDOSFullGame() {
file.open("CMLE.DAT");
_title = load8bitBinImage(&file, 0x0);
_title->setPalette((byte *)&kCastleTitleDOSPalette, 0, 16);
_title->setPalette((byte *)&kEGADefaultPalette, 0, 16);
file.close();
file.open("CMOE.DAT");
_option = load8bitBinImage(&file, 0x0);
_option->setPalette((byte *)&kCastleOptionDOSPalette, 0, 16);
_option->setPalette((byte *)&kEGADefaultPalette, 0, 16);
file.close();
file.open("CME.DAT");
_border = load8bitBinImage(&file, 0x0);
_border->setPalette((byte *)&kCastleBorderDOSPalette, 0, 16);
_border->setPalette((byte *)&kEGADefaultPalette, 0, 16);
file.close();
switch (_language) {
@ -254,17 +198,17 @@ void CastleEngine::loadAssetsDOSDemo() {
file.open("CMLE.DAT");
_title = load8bitBinImage(&file, 0x0);
_title->setPalette((byte *)&kCastleTitleDOSPalette, 0, 16);
_title->setPalette((byte *)&kEGADefaultPalette, 0, 16);
file.close();
file.open("CMOE.DAT");
_option = load8bitBinImage(&file, 0x0);
_option->setPalette((byte *)&kCastleOptionDOSPalette, 0, 16);
_option->setPalette((byte *)&kEGADefaultPalette, 0, 16);
file.close();
file.open("CME.DAT");
_border = load8bitBinImage(&file, 0x0);
_border->setPalette((byte *)&kCastleBorderDOSPalette, 0, 16);
_border->setPalette((byte *)&kEGADefaultPalette, 0, 16);
file.close();
stream = decryptFile("CMLD"); // Only english

View File

@ -27,7 +27,7 @@
namespace Freescape {
extern byte kEGADefaultPaletteData[16][3];
extern byte kEGADefaultPalette[16][3];
void DarkEngine::initDOS() {
if (_renderMode == Common::kRenderEGA)
@ -45,7 +45,7 @@ void DarkEngine::loadAssetsDOSDemo() {
file.open("SCN1E.DAT");
if (file.isOpen()) {
_title = load8bitBinImage(&file, 0x0);
_title->setPalette((byte *)&kEGADefaultPaletteData, 0, 16);
_title->setPalette((byte *)&kEGADefaultPalette, 0, 16);
}
file.close();
file.open("DSIDEE.EXE");
@ -58,7 +58,7 @@ void DarkEngine::loadAssetsDOSDemo() {
loadGlobalObjects(&file, 0x3d04, 23);
load8bitBinary(&file, 0xa700, 16);
_border = load8bitBinImage(&file, 0x210);
_border->setPalette((byte *)&kEGADefaultPaletteData, 0, 16);
_border->setPalette((byte *)&kEGADefaultPalette, 0, 16);
for (auto &it : _areaMap) {
addWalls(it._value);
@ -88,7 +88,7 @@ void DarkEngine::loadAssetsDOSFullGame() {
file.open("SCN1E.DAT");
if (file.isOpen()) {
_title = load8bitBinImage(&file, 0x0);
_title->setPalette((byte *)&kEGADefaultPaletteData, 0, 16);
_title->setPalette((byte *)&kEGADefaultPalette, 0, 16);
}
file.close();
file.open("DSIDEE.EXE");
@ -101,7 +101,7 @@ void DarkEngine::loadAssetsDOSFullGame() {
loadGlobalObjects(&file, 0x3d04, 23);
load8bitBinary(&file, 0xa280, 16);
_border = load8bitBinImage(&file, 0x210);
_border->setPalette((byte *)&kEGADefaultPaletteData, 0, 16);
_border->setPalette((byte *)&kEGADefaultPalette, 0, 16);
for (auto &it : _areaMap) {
addWalls(it._value);

View File

@ -27,7 +27,7 @@
namespace Freescape {
extern byte kCGAPalettePinkBlueWhiteData[4][3];
extern byte kEGADefaultPaletteData[16][3];
extern byte kEGADefaultPalette[16][3];
void DrillerEngine::initDOS() {
if (_renderMode == Common::kRenderEGA)
@ -196,24 +196,6 @@ byte kCGAPalettePinkBlueWhiteData[4][3] = {
{0xff, 0xff, 0xff},
};
byte kEGADefaultPaletteData[16][3] = {
{0x00, 0x00, 0x00},
{0x00, 0x00, 0xaa},
{0x00, 0xaa, 0x00},
{0xaa, 0x00, 0x00},
{0xaa, 0x00, 0xaa},
{0xaa, 0x55, 0x00},
{0x55, 0xff, 0x55},
{0xff, 0x55, 0x55},
{0x12, 0x34, 0x56},
{0xff, 0xff, 0x55},
{0xff, 0xff, 0xff},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x00}
};
/*
The following function is only used for decoding images for
the Driller DOS demo
@ -269,13 +251,13 @@ void DrillerEngine::loadAssetsDOSFullGame() {
file.open("SCN1E.DAT");
if (file.isOpen()) {
_title = load8bitBinImage(&file, 0x0);
_title->setPalette((byte*)&kEGADefaultPaletteData, 0, 16);
_title->setPalette((byte*)&kEGADefaultPalette, 0, 16);
}
file.close();
file.open("EGATITLE.RL");
if (file.isOpen()) {
_title = load8bitTitleImage(&file, 0x1b3);
_title->setPalette((byte*)&kEGADefaultPaletteData, 0, 16);
_title->setPalette((byte*)&kEGADefaultPalette, 0, 16);
}
file.close();
@ -289,7 +271,7 @@ void DrillerEngine::loadAssetsDOSFullGame() {
loadGlobalObjects(&file, 0x3b42, 8);
load8bitBinary(&file, 0x9b40, 16);
_border = load8bitBinImage(&file, 0x210);
_border->setPalette((byte*)&kEGADefaultPaletteData, 0, 16);
_border->setPalette((byte*)&kEGADefaultPalette, 0, 16);
} else if (_renderMode == Common::kRenderCGA) {
file.open("SCN1C.DAT");
if (file.isOpen()) {

View File

@ -74,7 +74,7 @@ EclipseEngine::EclipseEngine(OSystem *syst, const ADGameDescription *gd) : Frees
_playerSteps.push_back(25);
}
extern byte kEGADefaultPaletteData[16][3];
extern byte kEGADefaultPalette[16][3];
void EclipseEngine::loadAssetsDOSFullGame() {
Common::File file;
@ -82,7 +82,7 @@ void EclipseEngine::loadAssetsDOSFullGame() {
file.open("SCN1E.DAT");
if (file.isOpen()) {
_title = load8bitBinImage(&file, 0x0);
_title->setPalette((byte *)&kEGADefaultPaletteData, 0, 16);
_title->setPalette((byte *)&kEGADefaultPalette, 0, 16);
}
file.close();
file.open("TOTEE.EXE");
@ -98,7 +98,7 @@ void EclipseEngine::loadAssetsDOSFullGame() {
it._value->addObjectFromArea(id, _areaMap[255]);
}
_border = load8bitBinImage(&file, 0x210);
_border->setPalette((byte *)&kEGADefaultPaletteData, 0, 16);
_border->setPalette((byte *)&kEGADefaultPalette, 0, 16);
} else if (_renderMode == Common::kRenderCGA) {
file.open("TOTEC.EXE");

View File

@ -23,7 +23,7 @@
namespace Freescape {
byte dos_EGA_palette[16][3] = {
byte kEGADefaultPalette[16][3] = {
{0x00, 0x00, 0x00},
{0x00, 0x00, 0xaa},
{0x00, 0xaa, 0x00},
@ -110,7 +110,7 @@ byte kDrillerCPCPalette[32][3] = {
void FreescapeEngine::loadColorPalette() {
if (_renderMode == Common::kRenderEGA) {
_gfx->_palette = (byte *)&dos_EGA_palette;
_gfx->_palette = (byte *)&kEGADefaultPalette;
} else if (_renderMode == Common::kRenderC64) {
_gfx->_palette = (byte *)&kDrillerC64Palette;
} else if (_renderMode == Common::kRenderZX) {

View File

@ -493,104 +493,6 @@ static const char *eclipseRoomName[] = {
"ILLUSION",
"????????"};
void FreescapeEngine::renderPixels8bitBinImage(Graphics::ManagedSurface *surface, int &i, int &j, uint8 pixels, int color) {
if (i >= 320) {
//debug("cannot continue, stopping here at row %d!", j);
return;
}
int acc = 1 << 7;
while (acc > 0) {
assert(i < 320);
if (acc & pixels) {
int previousColor = surface->getPixel(i, j);
surface->setPixel(i, j, previousColor + color);
assert(previousColor + color < 16);
}
i++;
acc = acc >> 1;
}
}
Graphics::ManagedSurface *FreescapeEngine::load8bitBinImage(Common::SeekableReadStream *file, int offset) {
Graphics::ManagedSurface *surface = new Graphics::ManagedSurface();
surface->create(_screenW, _screenH, Graphics::PixelFormat::createFormatCLUT8());
surface->fillRect(Common::Rect(0, 0, 320, 200), 0);
file->seek(offset);
int imageSize = file->readUint16BE();
int i = 0;
int j = 0;
int hPixelsWritten = 0;
int color = 1;
int command = 0;
while (file->pos() <= offset + imageSize) {
//debug("pos: %lx", file->pos());
command = file->readByte();
color = 1 + hPixelsWritten / 320;
//debug("command: %x with j: %d", command, j);
if (j >= 200)
return surface;
if (command <= 0x7f) {
//debug("starting singles at i: %d j: %d", i, j);
int start = i;
while (command-- >= 0) {
int pixels = file->readByte();
//debug("single pixels command: %d with pixels: %x", command, pixels);
renderPixels8bitBinImage(surface, i, j, pixels, color);
}
hPixelsWritten = hPixelsWritten + i - start;
} else if (command <= 0xff && command >= 0xf0) {
int size = (136 - 8*(command - 0xf0)) / 2;
int start = i;
int pixels = file->readByte();
//debug("starting 0xfX: at i: %d j: %d with pixels: %x", i, j, pixels);
while (size > 0) {
renderPixels8bitBinImage(surface, i, j, pixels, color);
size = size - 4;
}
hPixelsWritten = hPixelsWritten + i - start;
assert(i <= 320);
} else if (command <= 0xef && command >= 0xe0) {
int size = (264 - 8*(command - 0xe0)) / 2;
int start = i;
int pixels = file->readByte();
//debug("starting 0xeX: at i: %d j: %d with pixels: %x", i, j, pixels);
while (size > 0) {
renderPixels8bitBinImage(surface, i, j, pixels, color);
size = size - 4;
}
hPixelsWritten = hPixelsWritten + i - start;
} else if (command <= 0xdf && command >= 0xd0) {
int size = (272 + 8*(0xdf - command)) / 2;
int start = i;
int pixels = file->readByte();
while (size > 0) {
renderPixels8bitBinImage(surface, i, j, pixels, color);
size = size - 4;
}
hPixelsWritten = hPixelsWritten + i - start;
} else {
error("unknown command: %x", command);
}
if (i >= 320) {
i = 0;
if (hPixelsWritten >= (_renderMode == Common::kRenderCGA ? 640 : 1280)) {
j++;
hPixelsWritten = 0;
}
}
}
return surface;
}
Area *FreescapeEngine::load8bitArea(Common::SeekableReadStream *file, uint16 ncolors) {
Common::String name;

View File

@ -0,0 +1,112 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "freescape/freescape.h"
namespace Freescape {
void FreescapeEngine::renderPixels8bitBinImage(Graphics::ManagedSurface *surface, int row, int column, int pixels, int bit) {
int mask = 0x80;
for (int i = 0; i < 8; i++) {
if ((pixels & mask) > 0) {
int sample = surface->getPixel(column + i, row) | bit;
surface->setPixel(column + i, row, sample);
}
mask >>= 1;
}
}
int FreescapeEngine::execute8bitBinImageSingleCommand(Common::SeekableReadStream *file, Graphics::ManagedSurface *surface, int row, int column, int bit, int count) {
int pixel = file->readByte();
for (int i = 0; i < count; i++) {
renderPixels8bitBinImage(surface, row, column + 8 * i, pixel, bit);
}
return 8 * count;
}
int FreescapeEngine::execute8bitBinImageMultiCommand(Common::SeekableReadStream *file, Graphics::ManagedSurface *surface, int row, int column, int bit, int count) {
for (int i = 0; i < count; i++) {
int pixel = file->readByte();
renderPixels8bitBinImage(surface, row, column + 8 * i, pixel, bit);
}
return 8 * count;
}
int FreescapeEngine::execute8bitBinImageCommand(Common::SeekableReadStream *file, Graphics::ManagedSurface *surface, int row, int column, int bit) {
int code = file->readByte();
if (code >= 0xD0) {
int count;
if (code >= 0xF0) {
count = 17 - (code & 0x0F);
} else if (code >= 0xE0) {
count = 33 - (code & 0x0F);
} else {
count = 34 + (0xDF - code);
}
return execute8bitBinImageSingleCommand(file, surface, row, column, bit, count);
} else if ((code & 0x80) == 0) {
int count = code + 1;
return execute8bitBinImageMultiCommand(file, surface, row, column, bit, count);
}
error("Unknown code %d", code);
}
void FreescapeEngine::load8bitBinImageRowIteration(Common::SeekableReadStream *file, Graphics::ManagedSurface *surface, int row, int bit) {
int pixels = 0;
while (pixels < 320) {
pixels += execute8bitBinImageCommand(file, surface, row, pixels, bit);
}
}
void FreescapeEngine::load8bitBinImageRow(Common::SeekableReadStream *file, Graphics::ManagedSurface *surface, int row) {
int bit = 1;
int nBits = 0;
if (_renderMode == Common::kRenderCGA)
nBits = 2;
else if (_renderMode == Common::kRenderEGA)
nBits = 4;
else
error("Unimplemented render mode for reading images");
for (int i = 0; i < nBits; i++) {
load8bitBinImageRowIteration(file, surface, row, bit);
bit <<= 1;
}
}
Graphics::ManagedSurface *FreescapeEngine::load8bitBinImage(Common::SeekableReadStream *file, int offset) {
Graphics::ManagedSurface *surface = new Graphics::ManagedSurface();
surface->create(_screenW, _screenH, Graphics::PixelFormat::createFormatCLUT8());
surface->fillRect(Common::Rect(0, 0, 320, 200), 0);
file->seek(offset);
int imageSize = file->readUint16BE();
int startImage = file->pos();
for (int row = 0; row < 200; row++)
load8bitBinImageRow(file, surface, row);
assert(startImage + imageSize == file->pos());
return surface;
}
} // namespace Freescape

View File

@ -20,6 +20,7 @@ MODULE_OBJS := \
games/eclipse.o \
games/palettes.o \
gfx.o \
loaders/8bitImage.o \
loaders/8bitBinaryLoader.o \
language/8bitDetokeniser.o \
language/instruction.o \