[Scummvm-git-logs] scummvm master -> fb95a2e5ffdf0d486d47fad068ff1184c971e385
neuromancer
noreply at scummvm.org
Tue Mar 4 07:39:41 UTC 2025
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
fb95a2e5ff FREESCAPE: some code to load doodle images in c64 releases
Commit: fb95a2e5ffdf0d486d47fad068ff1184c971e385
https://github.com/scummvm/scummvm/commit/fb95a2e5ffdf0d486d47fad068ff1184c971e385
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2025-03-04T08:38:34+01:00
Commit Message:
FREESCAPE: some code to load doodle images in c64 releases
Changed paths:
A engines/freescape/doodle.cpp
A engines/freescape/doodle.h
engines/freescape/detection.cpp
engines/freescape/freescape.cpp
engines/freescape/freescape.h
engines/freescape/games/driller/c64.cpp
engines/freescape/module.mk
diff --git a/engines/freescape/detection.cpp b/engines/freescape/detection.cpp
index be8737da048..d3116cbe0ae 100644
--- a/engines/freescape/detection.cpp
+++ b/engines/freescape/detection.cpp
@@ -95,21 +95,21 @@ static const ADGameDescription gameDescriptions[] = {
GUIO2(GUIO_NOMIDI, GAMEOPTION_AUTOMATIC_DRILLING)
},
{
- "driller",
+ "driller", // Original tape relase?
"",
- AD_ENTRY1s("DRILLER.C64.DATA", "73a6f206e54fb13245fe6d92f60fbb34", 41071),
+ AD_ENTRY1s("DRILLER.C64.DATA", "055b261bf28f313041bc4c23ff03c8da", 54532),
Common::EN_ANY,
Common::kPlatformC64,
- ADGF_UNSTABLE,
+ ADGF_UNSTABLE | GF_C64_RETAIL,
GUIO2(GUIO_NOMIDI, GAMEOPTION_AUTOMATIC_DRILLING)
},
{
- "driller", // Tape re-releae
+ "driller", // Tape re-relase
"",
- AD_ENTRY1s("DRILLER.C64.DATA", "606bc969e5442634c8ab057bfde9d9d2", 64750),
+ AD_ENTRY1s("DRILLER.C64.DATA", "4afec6eea3887343e7f91fb21a2f2948", 43278),
Common::EN_ANY,
Common::kPlatformC64,
- ADGF_UNSTABLE,
+ ADGF_UNSTABLE | GF_C64_BUDGET,
GUIO2(GUIO_NOMIDI, GAMEOPTION_AUTOMATIC_DRILLING)
},
{
diff --git a/engines/freescape/doodle.cpp b/engines/freescape/doodle.cpp
new file mode 100644
index 00000000000..bb018e463a1
--- /dev/null
+++ b/engines/freescape/doodle.cpp
@@ -0,0 +1,123 @@
+#include "common/file.h"
+#include "common/stream.h"
+#include "graphics/pixelformat.h"
+#include "graphics/surface.h"
+
+#include "engines/freescape/doodle.h"
+
+namespace Image {
+
+DoodleDecoder::DoodleDecoder(const byte *palette) : _surface(nullptr), _palette(nullptr) {
+ // Copy the pointer to the provided palette
+ _palette = palette;
+}
+
+DoodleDecoder::~DoodleDecoder() {
+ destroy();
+}
+
+void DoodleDecoder::destroy() {
+ if (_surface) {
+ _surface->free();
+ delete _surface;
+ _surface = nullptr;
+ }
+}
+
+bool DoodleDecoder::loadStream(Common::SeekableReadStream &stream) {
+ // This method should not be used
+ error("DoodleDecoder::loadStream - Use loadStreams instead");
+ return false;
+}
+
+bool DoodleDecoder::loadStreams(Common::SeekableReadStream &highresStream,
+ Common::SeekableReadStream &colorStream1,
+ Common::SeekableReadStream &colorStream2) {
+ destroy();
+
+ // Check stream sizes
+ if (highresStream.size() != 8192) {
+ error("DoodleDecoder: Invalid high-resolution data size");
+ return false;
+ }
+
+ if (colorStream1.size() != 1026 || colorStream2.size() != 1026) {
+ error("DoodleDecoder: Invalid color data size");
+ return false;
+ }
+
+ // Skip headers
+ highresStream.skip(2);
+ colorStream1.skip(2);
+ colorStream2.skip(2);
+
+ // Read high-resolution data
+ byte *highresData = new byte[8000];
+ highresStream.read(highresData, 8000);
+
+ // Skip remaining header bytes in highres file
+ highresStream.skip(190);
+
+ // Read color data
+ byte *colorData1 = new byte[kColorDataSize];
+ byte *colorData2 = new byte[kColorDataSize];
+
+ colorStream1.read(colorData1, kColorDataSize);
+ colorStream2.read(colorData2, kColorDataSize);
+
+ int width = 320;
+ int height = 200;
+
+ // Create surface
+ _surface = new Graphics::Surface();
+ _surface->create(width, height, Graphics::PixelFormat::createFormatCLUT8());
+
+ // Process each cell
+ for (int cellIdx = 0; cellIdx < 1000; ++cellIdx) {
+ processDoodleCell(cellIdx, highresData, colorData1, colorData2);
+ }
+
+ // Cleanup
+ delete[] highresData;
+ delete[] colorData1;
+ delete[] colorData2;
+
+ return true;
+}
+
+void DoodleDecoder::processDoodleCell(int cellIdx, const byte *highresData,
+ const byte *colorData1, const byte *colorData2) {
+ // Calculate cell coordinates
+ int cellX = (cellIdx % 40) * 8;
+ int cellY = (cellIdx / 40) * 8;
+
+ // Get colors for this cell
+ byte color1 = colorData2[cellIdx] & 0xf;
+ byte color2 = colorData1[cellIdx] >> 4;
+ byte color3 = colorData1[cellIdx] & 0xf;
+
+ // Process each row in the cell
+ for (int row = 0; row < 8; ++row) {
+ byte pixelByte = highresData[cellIdx * 8 + row];
+
+ // Process 4 pixel pairs (8 pixels total) in multicolor mode
+ for (int bit = 0; bit < 4; ++bit) {
+ byte pixelPair = (pixelByte >> (6 - bit * 2)) & 0x03;
+
+ // Determine final color
+ byte color = 0;
+ switch (pixelPair) {
+ case 0: color = 0; break;
+ case 1: color = color2; break;
+ case 2: color = color3; break;
+ case 3: color = color1; break;
+ }
+
+ // Set pixel colors (2 pixels for each pair due to multicolor mode)
+ _surface->setPixel(cellX + bit * 2, cellY + row, color);
+ _surface->setPixel(cellX + bit * 2 + 1, cellY + row, color);
+ }
+ }
+}
+
+} // End of namespace Image
\ No newline at end of file
diff --git a/engines/freescape/doodle.h b/engines/freescape/doodle.h
new file mode 100644
index 00000000000..85a4bf063a6
--- /dev/null
+++ b/engines/freescape/doodle.h
@@ -0,0 +1,59 @@
+#ifndef IMAGE_DOODLE_DECODER_H
+#define IMAGE_DOODLE_DECODER_H
+
+#include "image/image_decoder.h"
+#include "common/stream.h"
+#include "graphics/surface.h"
+
+namespace Image {
+
+class DoodleDecoder : public ImageDecoder {
+public:
+ /**
+ * Constructor for the DoodleDecoder
+ * @param palette Pointer to RGB palette data (16 colors * 3 components)
+ */
+ DoodleDecoder(const byte *palette);
+ ~DoodleDecoder() override;
+
+ // ImageDecoder interface
+ bool loadStream(Common::SeekableReadStream &stream) override;
+ void destroy() override;
+ const Graphics::Surface *getSurface() const override { return _surface; }
+ const byte *getPalette() const override { return _palette; }
+ uint16 getPaletteColorCount() const override { return 16; }
+
+ /**
+ * Load a C64 doodle image from its component streams
+ * @param highresStream Stream containing high-resolution pixel data
+ * @param colorStream1 Stream containing first color data file
+ * @param colorStream2 Stream containing second color data file
+ * @return Whether loading succeeded
+ */
+ bool loadStreams(Common::SeekableReadStream &highresStream,
+ Common::SeekableReadStream &colorStream1,
+ Common::SeekableReadStream &colorStream2);
+
+private:
+ static const int kWidth = 320;
+ static const int kHeight = 200;
+ static const int kHeaderSize = 192;
+ static const int kColorDataSize = 1000; // 40x25 color cells
+
+ Graphics::Surface *_surface;
+ const byte *_palette;
+
+ /**
+ * Process an 8x8 cell of the image
+ * @param cellIdx Cell index (0-999)
+ * @param highresData Pointer to high-resolution pixel data
+ * @param colorData1 First color data array
+ * @param colorData2 Second color data array
+ */
+ void processDoodleCell(int cellIdx, const byte *highresData,
+ const byte *colorData1, const byte *colorData2);
+};
+
+} // End of namespace Image
+
+#endif
\ No newline at end of file
diff --git a/engines/freescape/freescape.cpp b/engines/freescape/freescape.cpp
index 2ed5e8eca06..2a38a4b048f 100644
--- a/engines/freescape/freescape.cpp
+++ b/engines/freescape/freescape.cpp
@@ -32,6 +32,7 @@
#include "freescape/language/8bitDetokeniser.h"
#include "freescape/objects/sensor.h"
#include "freescape/sweepAABB.h"
+#include "freescape/doodle.h"
namespace Freescape {
@@ -641,7 +642,7 @@ void FreescapeEngine::processInput() {
_eventManager->purgeMouseEvents();
rotate(event.relMouse.x * _mouseSensitivity, event.relMouse.y * _mouseSensitivity);
- }
+ }
break;
case Common::EVENT_LBUTTONDOWN:
@@ -1127,6 +1128,16 @@ Graphics::ManagedSurface *FreescapeEngine::loadAndConvertNeoImage(Common::Seekab
return surface;
}
+Graphics::ManagedSurface *FreescapeEngine::loadAndConvertDoodleImage(Common::SeekableReadStream *bitmap, Common::SeekableReadStream *color1, Common::SeekableReadStream *color2, byte *palette) {
+ Image::DoodleDecoder decoder(palette);
+ decoder.loadStreams(*bitmap, *color1, *color2);
+ Graphics::ManagedSurface *surface = new Graphics::ManagedSurface();
+ surface->copyFrom(*decoder.getSurface());
+ surface->convertToInPlace(_gfx->_currentPixelFormat, decoder.getPalette(), decoder.getPaletteColorCount());
+ return surface;
+}
+
+
Graphics::ManagedSurface *FreescapeEngine::loadAndCenterScrImage(Common::SeekableReadStream *stream) {
Image::ScrDecoder decoder;
decoder.loadStream(*stream);
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index e8e7d911435..fbd859368de 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -253,6 +253,8 @@ public:
byte *getPaletteFromNeoImage(Common::SeekableReadStream *stream, int offset);
Graphics::ManagedSurface *loadAndConvertNeoImage(Common::SeekableReadStream *stream, int offset, byte *palette = nullptr);
Graphics::ManagedSurface *loadAndCenterScrImage(Common::SeekableReadStream *stream);
+ Graphics::ManagedSurface *loadAndConvertDoodleImage(Common::SeekableReadStream *bitmap, Common::SeekableReadStream *color1, Common::SeekableReadStream *color2, byte *palette);
+
void loadPalettes(Common::SeekableReadStream *file, int offset);
byte *loadPalette(Common::SeekableReadStream *file);
void swapPalette(uint16 areaID);
@@ -599,7 +601,9 @@ enum GameReleaseFlags {
GF_CPC_BUDGET = (1 << 7),
GF_CPC_VIRTUALWORLDS = (1 << 8),
GF_ATARI_RETAIL = (1 << 9),
- GF_ATARI_BUDGET = (1 << 10)
+ GF_ATARI_BUDGET = (1 << 10),
+ GF_C64_RETAIL = (1 << 11),
+ GF_C64_BUDGET = (1 << 12),
};
extern FreescapeEngine *g_freescape;
diff --git a/engines/freescape/games/driller/c64.cpp b/engines/freescape/games/driller/c64.cpp
index 556b86f8707..a3bfd4edb08 100644
--- a/engines/freescape/games/driller/c64.cpp
+++ b/engines/freescape/games/driller/c64.cpp
@@ -27,6 +27,8 @@
namespace Freescape {
+extern byte kDrillerC64Palette[16][3];
+
void DrillerEngine::initC64() {
_viewArea = Common::Rect(32, 16, 288, 120);
}
@@ -41,12 +43,22 @@ void DrillerEngine::loadAssetsC64FullGame() {
loadGlobalObjects(&file, 0x1855, 8);
} else if (_targetName.hasPrefix("driller")) {
file.open("driller.c64.data");
- //loadMessagesFixedSize(&file, 0x167a - 0x400, 14, 20);
- //loadFonts(&file, 0xae54);
- loadFonts(&file, 0x4ee);
- load8bitBinary(&file, 0x8eee, 16);
- loadMessagesFixedSize(&file, 0x1766, 14, 20);
- loadGlobalObjects(&file, 0x1941, 8);
+
+ if (_variant & GF_C64_RETAIL) {
+ loadFonts(&file, 0x402);
+ load8bitBinary(&file, 0x8b04, 16);
+ loadMessagesFixedSize(&file, 0x167a, 14, 20);
+ loadGlobalObjects(&file, 0x1855, 8);
+ } else if (_variant & GF_C64_BUDGET) {
+ //loadFonts(&file, 0x402);
+ load8bitBinary(&file, 0x7df7, 16);
+ loadMessagesFixedSize(&file, 0x1399, 14, 20);
+ loadGlobalObjects(&file, 0x150a, 8);
+ } else {
+ //error("Unknown C64 release");
+ assert(false);
+ }
+
// The color map from the C64 version looks invalid
// so we'll just hardcode the Dark Side one which works fine
@@ -134,8 +146,15 @@ void DrillerEngine::loadAssetsC64FullGame() {
_border = new Graphics::ManagedSurface();
_border->copyFrom(*surf);
- //_border = _title;
- //loadGlobalObjects(&file, 0x1855 - 0x400, 8);
+ /*file.close();
+ file.open("driller.c64.title.bitmap");
+
+ Common::File colorFile1;
+ colorFile1.open("driller.c64.title.colors1");
+ Common::File colorFile2;
+ colorFile2.open("driller.c64.title.colors2");
+
+ _title = loadAndConvertDoodleImage(&file, &colorFile1, &colorFile2, (byte *)&kDrillerC64Palette);*/
} else
error("Unknown C64 release");
}
diff --git a/engines/freescape/module.mk b/engines/freescape/module.mk
index 9c860d08f8b..2c03a2d26e9 100644
--- a/engines/freescape/module.mk
+++ b/engines/freescape/module.mk
@@ -6,6 +6,7 @@ MODULE_OBJS := \
font.o \
events.o \
demo.o \
+ doodle.o \
freescape.o \
games/castle/castle.o \
games/castle/amiga.o \
More information about the Scummvm-git-logs
mailing list