[Scummvm-git-logs] scummvm master -> 1391e297221719715b206b61e34eac991ca58231
neuromancer
noreply at scummvm.org
Sat Dec 24 16:23:09 UTC 2022
This automated email contains information about 6 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
bcbd5dd6a3 FREESCAPE: preliminary support for zx spectrum release of driller
6841227241 COMMON: added zx spectrum render mode
d4129d5aa2 COMMON: corrected kRenderZX to avoid duplicates in RenderMode
eaedfdb3b4 FREESCAPE: initial implementation of getRGBAtZX
40f34b2e92 FREESCAPE: implemented UI for Driller ZX release
1391e29722 FREESCAPE: implemented stipple data usage for ZX renderer
Commit: bcbd5dd6a37814640bc1e8f001c174670f8b2525
https://github.com/scummvm/scummvm/commit/bcbd5dd6a37814640bc1e8f001c174670f8b2525
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2022-12-24T13:18:53-03:00
Commit Message:
FREESCAPE: preliminary support for zx spectrum release of driller
Changed paths:
A devtools/create_freescape/driller-zx_cga.bmp
dists/engine-data/freescape.dat
engines/freescape/detection.cpp
engines/freescape/freescape.cpp
engines/freescape/freescape.h
engines/freescape/games/driller.cpp
engines/freescape/games/palettes.cpp
engines/freescape/loaders/8bitBinaryLoader.cpp
diff --git a/devtools/create_freescape/driller-zx_cga.bmp b/devtools/create_freescape/driller-zx_cga.bmp
new file mode 100644
index 00000000000..6cc207a6913
Binary files /dev/null and b/devtools/create_freescape/driller-zx_cga.bmp differ
diff --git a/dists/engine-data/freescape.dat b/dists/engine-data/freescape.dat
index d507c5172f3..c45d25c66c7 100644
Binary files a/dists/engine-data/freescape.dat and b/dists/engine-data/freescape.dat differ
diff --git a/engines/freescape/detection.cpp b/engines/freescape/detection.cpp
index ce0ee0ab5ad..ac44744f815 100644
--- a/engines/freescape/detection.cpp
+++ b/engines/freescape/detection.cpp
@@ -35,6 +35,18 @@ static const PlainGameDescriptor freescapeGames[] = {
static const ADGameDescription gameDescriptions[] = {
// Original Freescape games
+ {
+ "driller",
+ "",
+ {
+ {"DRILLER.ZXSPECTRUM.DATA", 0, "396c1789a7da3db5058d18eb8d2d35a3", 37590},
+ AD_LISTEND
+ },
+ Common::EN_ANY,
+ Common::kPlatformZX,
+ ADGF_TESTING,
+ GUIO2(GUIO_NOMIDI, GAMEOPTION_AUTOMATIC_DRILLING)
+ },
{
"driller",
"",
diff --git a/engines/freescape/freescape.cpp b/engines/freescape/freescape.cpp
index b8cb4efd0e9..b7487bef7d8 100644
--- a/engines/freescape/freescape.cpp
+++ b/engines/freescape/freescape.cpp
@@ -49,6 +49,8 @@ FreescapeEngine::FreescapeEngine(OSystem *syst, const ADGameDescription *gd)
_renderMode = Common::kRenderAmiga;
} else if (isAtariST()) {
_renderMode = Common::kRenderAtariST;
+ } else if (isSpectrum()) {
+ _renderMode = Common::kRenderCGA;
}
_variant = gd->flags;
@@ -511,7 +513,7 @@ Common::Error FreescapeEngine::run() {
}
loadBorder(); // Border is load unmodified
- if (_border && isDOS()) {
+ if (_border && (isDOS() || isSpectrum())) {
if (saveSlot == -1) {
drawBorder();
_gfx->flipBuffer();
@@ -561,7 +563,8 @@ Common::Error FreescapeEngine::run() {
}
void FreescapeEngine::loadBorder() {
- _borderTexture = _gfx->createTexture(_border);
+ if (_border)
+ _borderTexture = _gfx->createTexture(_border);
}
void FreescapeEngine::processBorder() {
@@ -663,7 +666,7 @@ void FreescapeEngine::drawStringInSurface(const Common::String &str, int x, int
Common::String ustr = str;
ustr.toUppercase();
- if (isDOS()) {
+ if (isDOS() || isSpectrum()) {
for (uint32 c = 0; c < ustr.size(); c++) {
assert(ustr[c] >= 32);
for (int j = 0; j < 6; j++) {
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index bbbf3e31388..931d11e3821 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -96,6 +96,7 @@ public:
bool isAmiga() { return _gameDescription->platform == Common::kPlatformAmiga; }
bool isAtariST() { return _gameDescription->platform == Common::kPlatformAtariST; }
bool isDOS() { return _gameDescription->platform == Common::kPlatformDOS; }
+ bool isSpectrum() { return _gameDescription->platform == Common::kPlatformZX; }
Common::Error run() override;
diff --git a/engines/freescape/games/driller.cpp b/engines/freescape/games/driller.cpp
index cc6aea9d61a..f17d45922c1 100644
--- a/engines/freescape/games/driller.cpp
+++ b/engines/freescape/games/driller.cpp
@@ -82,6 +82,8 @@ DrillerEngine::DrillerEngine(OSystem *syst, const ADGameDescription *gd) : Frees
}
else if (isAmiga() || isAtariST())
_viewArea = Common::Rect(36, 16, 284, 118);
+ else if (isSpectrum())
+ _viewArea = Common::Rect(58, 20, 266, 124);
_playerHeightNumber = 1;
_playerHeights.push_back(16);
@@ -406,6 +408,17 @@ void DrillerEngine::loadAssetsFullGame() {
load8bitBinary(&file, 0x29b3c, 16);
loadPalettes(&file, 0x296fa);
loadSoundsFx(&file, 0x30da6, 25);
+ } else if (isSpectrum()) {
+ loadBundledImages();
+ file.open("driller.zxspectrum.data");
+
+ if (!file.isOpen())
+ error("Failed to open driller.zxspectrum.data");
+
+ loadMessagesFixedSize(&file, 0x20e4, 14, 20);
+ loadFonts(&file, 0x62ca);
+ //loadGlobalObjects(&file, 0x3b42);
+ load8bitBinary(&file, 0x642c, 4);
} else if (_renderMode == Common::kRenderEGA) {
loadBundledImages();
file.open("DRILLE.EXE");
@@ -512,7 +525,7 @@ void DrillerEngine::drawUI() {
} else
return;
- if (isDOS())
+ if (isDOS() || isSpectrum())
drawDOSUI(surface);
else if (isAmiga() || isAtariST())
drawAmigaAtariSTUI(surface);
diff --git a/engines/freescape/games/palettes.cpp b/engines/freescape/games/palettes.cpp
index 75f4b509717..d7783149e25 100644
--- a/engines/freescape/games/palettes.cpp
+++ b/engines/freescape/games/palettes.cpp
@@ -41,9 +41,18 @@ byte dos_EGA_palette[16][3] = {
{0xff, 0xff, 0x55},
{0xff, 0xff, 0xff}};
+byte kDrillerZXPalettePinkBlueData[4][3] = {
+ {0x00, 0x00, 0x00},
+ {0x00, 0xaa, 0xaa},
+ {0xaa, 0x00, 0xaa},
+ {0xaa, 0xaa, 0xaa},
+};
+
void FreescapeEngine::loadColorPalette() {
if (_renderMode == Common::kRenderEGA) {
_gfx->_palette = (byte *)&dos_EGA_palette;
+ } else if (_renderMode == Common::kRenderCGA) {
+ _gfx->_palette = (byte *)&kDrillerZXPalettePinkBlueData;
} else if (_renderMode == Common::kRenderCGA) {
_gfx->_palette = nullptr; // palette depends on the area
} else if (_renderMode == Common::kRenderAmiga || _renderMode == Common::kRenderAtariST) {
diff --git a/engines/freescape/loaders/8bitBinaryLoader.cpp b/engines/freescape/loaders/8bitBinaryLoader.cpp
index 029b03a9dff..af1e7e4de10 100644
--- a/engines/freescape/loaders/8bitBinaryLoader.cpp
+++ b/engines/freescape/loaders/8bitBinaryLoader.cpp
@@ -600,7 +600,7 @@ void FreescapeEngine::loadFonts(Common::SeekableReadStream *file, int offset) {
file->seek(offset);
int charNumber = 60;
byte *font = nullptr;
- if (isDOS()) {
+ if (isDOS() || isSpectrum()) {
font = (byte *)malloc(6 * charNumber);
file->read(font, 6 * charNumber);
Commit: 6841227241d53226c8fa28b76e5a7b60e2e0c5b3
https://github.com/scummvm/scummvm/commit/6841227241d53226c8fa28b76e5a7b60e2e0c5b3
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2022-12-24T13:18:53-03:00
Commit Message:
COMMON: added zx spectrum render mode
Changed paths:
common/rendermode.cpp
common/rendermode.h
diff --git a/common/rendermode.cpp b/common/rendermode.cpp
index 300102fb1c9..95eabc9b00c 100644
--- a/common/rendermode.cpp
+++ b/common/rendermode.cpp
@@ -48,6 +48,7 @@ const RenderModeDescription g_renderModes[] = {
{ "macintosh", "Macintosh", kRenderMacintosh },
// I18N: Macintosh black-and-white
{ "macintoshbw", _s("Macintosh b/w"), kRenderMacintoshBW },
+ { "zx", "ZX Spectrum", kRenderZX },
{nullptr, nullptr, kRenderDefault}
};
diff --git a/common/rendermode.h b/common/rendermode.h
index 240ebee07d4..1895f182266 100644
--- a/common/rendermode.h
+++ b/common/rendermode.h
@@ -60,6 +60,7 @@ enum RenderMode {
kRenderMacintoshBW = 13,
kRenderCGAComp = 14,
kRenderCGA_BW = 15,
+ kRenderZX = 15,
};
struct RenderModeDescription {
Commit: d4129d5aa243aba49b3ab29d39593d549b77e4ec
https://github.com/scummvm/scummvm/commit/d4129d5aa243aba49b3ab29d39593d549b77e4ec
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2022-12-24T13:18:53-03:00
Commit Message:
COMMON: corrected kRenderZX to avoid duplicates in RenderMode
Changed paths:
common/rendermode.h
diff --git a/common/rendermode.h b/common/rendermode.h
index 1895f182266..fd7d131404a 100644
--- a/common/rendermode.h
+++ b/common/rendermode.h
@@ -60,7 +60,7 @@ enum RenderMode {
kRenderMacintoshBW = 13,
kRenderCGAComp = 14,
kRenderCGA_BW = 15,
- kRenderZX = 15,
+ kRenderZX = 16,
};
struct RenderModeDescription {
Commit: eaedfdb3b4b8e42f2d45d983a1c55ee56cb98a01
https://github.com/scummvm/scummvm/commit/eaedfdb3b4b8e42f2d45d983a1c55ee56cb98a01
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2022-12-24T13:18:53-03:00
Commit Message:
FREESCAPE: initial implementation of getRGBAtZX
Changed paths:
R devtools/create_freescape/driller-zx_cga.bmp
dists/engine-data/freescape.dat
engines/freescape/area.h
engines/freescape/freescape.cpp
engines/freescape/games/palettes.cpp
engines/freescape/gfx.cpp
engines/freescape/gfx.h
engines/freescape/loaders/8bitBinaryLoader.cpp
diff --git a/devtools/create_freescape/driller-zx_cga.bmp b/devtools/create_freescape/driller-zx_cga.bmp
deleted file mode 100644
index 6cc207a6913..00000000000
Binary files a/devtools/create_freescape/driller-zx_cga.bmp and /dev/null differ
diff --git a/dists/engine-data/freescape.dat b/dists/engine-data/freescape.dat
index c45d25c66c7..901f77e4620 100644
Binary files a/dists/engine-data/freescape.dat and b/dists/engine-data/freescape.dat differ
diff --git a/engines/freescape/area.h b/engines/freescape/area.h
index 1c71490efa2..49cffb6632a 100644
--- a/engines/freescape/area.h
+++ b/engines/freescape/area.h
@@ -77,6 +77,8 @@ public:
uint8 _groundColor;
uint8 _usualBackgroundColor;
uint8 _underFireBackgroundColor;
+ uint8 _inkColor;
+ uint8 _paperColor;
ColorReMap _colorRemaps;
private:
diff --git a/engines/freescape/freescape.cpp b/engines/freescape/freescape.cpp
index b7487bef7d8..e4535974386 100644
--- a/engines/freescape/freescape.cpp
+++ b/engines/freescape/freescape.cpp
@@ -50,7 +50,7 @@ FreescapeEngine::FreescapeEngine(OSystem *syst, const ADGameDescription *gd)
} else if (isAtariST()) {
_renderMode = Common::kRenderAtariST;
} else if (isSpectrum()) {
- _renderMode = Common::kRenderCGA;
+ _renderMode = Common::kRenderZX;
}
_variant = gd->flags;
diff --git a/engines/freescape/games/palettes.cpp b/engines/freescape/games/palettes.cpp
index d7783149e25..080c10afc06 100644
--- a/engines/freescape/games/palettes.cpp
+++ b/engines/freescape/games/palettes.cpp
@@ -41,18 +41,22 @@ byte dos_EGA_palette[16][3] = {
{0xff, 0xff, 0x55},
{0xff, 0xff, 0xff}};
-byte kDrillerZXPalettePinkBlueData[4][3] = {
+byte kDrillerZXPalette[8][3] = {
{0x00, 0x00, 0x00},
- {0x00, 0xaa, 0xaa},
- {0xaa, 0x00, 0xaa},
- {0xaa, 0xaa, 0xaa},
+ {0x00, 0x00, 0xee},
+ {0xee, 0x00, 0x00},
+ {0xee, 0x00, 0xee},
+ {0x00, 0xee, 0x00},
+ {0x00, 0xee, 0xee},
+ {0xee, 0xee, 0x00},
+ {0xee, 0xee, 0xee},
};
void FreescapeEngine::loadColorPalette() {
if (_renderMode == Common::kRenderEGA) {
_gfx->_palette = (byte *)&dos_EGA_palette;
- } else if (_renderMode == Common::kRenderCGA) {
- _gfx->_palette = (byte *)&kDrillerZXPalettePinkBlueData;
+ } else if (_renderMode == Common::kRenderZX) {
+ _gfx->_palette = (byte *)kDrillerZXPalette;
} else if (_renderMode == Common::kRenderCGA) {
_gfx->_palette = nullptr; // palette depends on the area
} else if (_renderMode == Common::kRenderAmiga || _renderMode == Common::kRenderAtariST) {
@@ -94,7 +98,10 @@ void FreescapeEngine::loadPalettes(Common::SeekableReadStream *file, int offset)
void FreescapeEngine::swapPalette(uint16 levelID) {
if (isAmiga() || isAtariST())
_gfx->_palette = _paletteByArea[levelID];
- else if (isDOS() && _renderMode == Common::kRenderCGA) {
+ else if (isSpectrum()) {
+ _gfx->_inkColor = _areaMap[levelID]->_inkColor;
+ _gfx->_paperColor = _areaMap[levelID]->_paperColor;
+ } else if (isDOS() && _renderMode == Common::kRenderCGA) {
assert(_borderCGAByArea.contains(levelID));
assert(_paletteCGAByArea.contains(levelID));
_borderTexture = _borderCGAByArea.getVal(levelID);
diff --git a/engines/freescape/gfx.cpp b/engines/freescape/gfx.cpp
index 281fbb410b7..38fc9f84e25 100644
--- a/engines/freescape/gfx.cpp
+++ b/engines/freescape/gfx.cpp
@@ -40,6 +40,8 @@ Renderer::Renderer(int screenW, int screenH, Common::RenderMode renderMode) {
_currentPixelFormat = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
_palettePixelFormat = Graphics::PixelFormat(3, 8, 8, 8, 0, 0, 8, 16, 0);
_keyColor = -1;
+ _inkColor = -1;
+ _paperColor = -1;
_palette = nullptr;
_colorMap = nullptr;
_colorRemaps = nullptr;
@@ -90,6 +92,28 @@ bool Renderer::getRGBAtCGA(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &
return true;
}
+bool Renderer::getRGBAtZX(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2) {
+ if (index == _keyColor)
+ return false;
+
+ byte *entry = (*_colorMap)[index - 1];
+ if (entry[0] == 0 && entry[1] == 0 && entry[2] == 0 && entry[3] == 0) {
+ readFromPalette(_paperColor, r1, g1, b1);
+ readFromPalette(_paperColor, r2, g2, b2);
+ return true;
+ }
+
+ if (entry[0] == 0xff && entry[1] == 0xff && entry[2] == 0xff && entry[3] == 0xff) {
+ readFromPalette(_inkColor, r1, g1, b1);
+ readFromPalette(_inkColor, r2, g2, b2);
+ return true;
+ }
+
+ //setStippleData(entry);
+ readFromPalette(_inkColor, r1, g1, b1);
+ readFromPalette(_paperColor, r2, g2, b2);
+ return true;
+}
bool Renderer::getRGBAtEGA(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2) {
// assert(index-1 < _colorMap->size());
@@ -145,6 +169,9 @@ bool Renderer::getRGBAt(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2,
return getRGBAtEGA(index, r1, g1, b1, r2, g2, b2);
else if (_renderMode == Common::kRenderCGA)
return getRGBAtCGA(index, r1, g1, b1, r2, g2, b2);
+ else if (_renderMode == Common::kRenderZX)
+ return getRGBAtZX(index, r1, g1, b1, r2, g2, b2);
+
error("Invalid or unsupported render mode");
}
diff --git a/engines/freescape/gfx.h b/engines/freescape/gfx.h
index 8aaf8119b86..fe0f740b69f 100644
--- a/engines/freescape/gfx.h
+++ b/engines/freescape/gfx.h
@@ -101,12 +101,15 @@ public:
bool getRGBAt(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2);
bool getRGBAtCGA(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2);
bool getRGBAtEGA(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2);
+ bool getRGBAtZX(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2);
virtual void useStipple(bool enabled) {};
byte *_palette;
ColorMap *_colorMap;
ColorReMap *_colorRemaps;
int _keyColor;
+ int _inkColor;
+ int _paperColor;
/**
* Select the window where to render
diff --git a/engines/freescape/loaders/8bitBinaryLoader.cpp b/engines/freescape/loaders/8bitBinaryLoader.cpp
index af1e7e4de10..299f1daf8eb 100644
--- a/engines/freescape/loaders/8bitBinaryLoader.cpp
+++ b/engines/freescape/loaders/8bitBinaryLoader.cpp
@@ -296,8 +296,6 @@ Area *FreescapeEngine::load8bitArea(Common::SeekableReadStream *file, uint16 nco
uint8 scale = readField(file, 8);
debugC(1, kFreescapeDebugParser, "Scale: %d", scale);
- uint8 ci3 = 0;
- uint8 ci4 = 0;
uint8 skyColor = areaFlags & 15;
uint8 groundColor = areaFlags >> 4;
@@ -306,12 +304,14 @@ Area *FreescapeEngine::load8bitArea(Common::SeekableReadStream *file, uint16 nco
uint8 usualBackgroundColor = readField(file, 8);
uint8 underFireBackgroundColor = readField(file, 8);
- ci3 = readField(file, 8);
- ci4 = readField(file, 8);
+ uint8 paperColor = readField(file, 8);
+ uint8 inkColor = readField(file, 8);
debugC(1, kFreescapeDebugParser, "Colors usual background: %d", usualBackgroundColor);
debugC(1, kFreescapeDebugParser, "Colors under fire background: %d", underFireBackgroundColor);
+ debugC(1, kFreescapeDebugParser, "Color Paper: %d", paperColor);
+ debugC(1, kFreescapeDebugParser, "Color Ink: %d", inkColor);
- debugC(1, kFreescapeDebugParser, "Colors: %d %d %d %d", ci3, ci4, skyColor, groundColor);
+ debugC(1, kFreescapeDebugParser, "Additional colors: %d %d", skyColor, groundColor);
// CPC
// groundColor = file->readByte() & 15;
// skyColor = file->readByte() & 15;
@@ -397,6 +397,8 @@ Area *FreescapeEngine::load8bitArea(Common::SeekableReadStream *file, uint16 nco
area->_scale = scale;
area->_skyColor = skyColor;
area->_groundColor = groundColor;
+ area->_inkColor = inkColor;
+ area->_paperColor = paperColor;
area->_usualBackgroundColor = usualBackgroundColor;
area->_underFireBackgroundColor = underFireBackgroundColor;
Commit: 40f34b2e9219d65a7d4dae40d91e2553df9b5ecd
https://github.com/scummvm/scummvm/commit/40f34b2e9219d65a7d4dae40d91e2553df9b5ecd
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2022-12-24T13:18:53-03:00
Commit Message:
FREESCAPE: implemented UI for Driller ZX release
Changed paths:
engines/freescape/freescape.h
engines/freescape/games/driller.cpp
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index 931d11e3821..2becd748687 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -387,6 +387,7 @@ private:
void loadAssetsFullGame();
void drawDOSUI(Graphics::Surface *surface);
+ void drawZXUI(Graphics::Surface *surface);
void drawAmigaAtariSTUI(Graphics::Surface *surface);
};
diff --git a/engines/freescape/games/driller.cpp b/engines/freescape/games/driller.cpp
index f17d45922c1..4dfdbf71339 100644
--- a/engines/freescape/games/driller.cpp
+++ b/engines/freescape/games/driller.cpp
@@ -525,8 +525,10 @@ void DrillerEngine::drawUI() {
} else
return;
- if (isDOS() || isSpectrum())
+ if (isDOS())
drawDOSUI(surface);
+ else if (isSpectrum())
+ drawZXUI(surface);
else if (isAmiga() || isAtariST())
drawAmigaAtariSTUI(surface);
@@ -616,6 +618,80 @@ void DrillerEngine::drawDOSUI(Graphics::Surface *surface) {
}
}
+
+void DrillerEngine::drawZXUI(Graphics::Surface *surface) {
+ uint32 color = 5;
+ uint8 r, g, b;
+
+ _gfx->readFromPalette(color, r, g, b);
+ uint32 front = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
+
+ color = _currentArea->_usualBackgroundColor;
+ if (_gfx->_colorRemaps && _gfx->_colorRemaps->contains(color)) {
+ color = (*_gfx->_colorRemaps)[color];
+ }
+
+ _gfx->readFromPalette(color, r, g, b);
+ uint32 back = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
+
+ int score = _gameStateVars[k8bitVariableScore];
+ drawStringInSurface(_currentArea->_name, 176, 188, front, back, surface);
+ drawStringInSurface(Common::String::format("%04d", 2 * int(_position.x())), 152, 149, front, back, surface);
+ drawStringInSurface(Common::String::format("%04d", 2 * int(_position.z())), 152, 157, front, back, surface);
+ drawStringInSurface(Common::String::format("%04d", 2 * int(_position.y())), 152, 165, front, back, surface);
+ if (_playerHeightNumber >= 0)
+ drawStringInSurface(Common::String::format("%d", _playerHeightNumber), 74, 165, front, back, surface);
+ else
+ drawStringInSurface(Common::String::format("%s", "J"), 74, 165, front, back, surface);
+
+ drawStringInSurface(Common::String::format("%02d", int(_angleRotations[_angleRotationIndex])), 64, 149, front, back, surface);
+ drawStringInSurface(Common::String::format("%3d", _playerSteps[_playerStepIndex]), 65, 157, front, back, surface);
+ drawStringInSurface(Common::String::format("%07d", score), 217, 133, front, back, surface);
+
+ int hours = _countdown <= 0 ? 0 : _countdown / 3600;
+ drawStringInSurface(Common::String::format("%02d", hours), 187, 12, front, back, surface);
+ int minutes = _countdown <= 0 ? 0 : (_countdown - hours * 3600) / 60;
+ drawStringInSurface(Common::String::format("%02d", minutes), 209, 12, front, back, surface);
+ int seconds = _countdown <= 0 ? 0 : _countdown - hours * 3600 - minutes * 60;
+ drawStringInSurface(Common::String::format("%02d", seconds), 233, 12, front, back, surface);
+
+ Common::String message;
+ int deadline;
+ getLatestMessages(message, deadline);
+ if (deadline <= _countdown) {
+ drawStringInSurface(message, 169, 181, back, front, surface);
+ _temporaryMessages.push_back(message);
+ _temporaryMessageDeadlines.push_back(deadline);
+ } else {
+ if (_currentArea->_gasPocketRadius == 0)
+ message = _messagesList[2];
+ else if (_drillStatusByArea[_currentArea->getAreaID()])
+ message = _messagesList[0];
+ else
+ message = _messagesList[1];
+
+ drawStringInSurface(message, 169, 181, front, back, surface);
+ }
+
+ int energy = _gameStateVars[k8bitVariableEnergy];
+ int shield = _gameStateVars[k8bitVariableShield];
+
+ if (energy >= 0) {
+ Common::Rect backBar(43, 188, 105 - energy, 194);
+ surface->fillRect(backBar, back);
+ Common::Rect energyBar(105 - energy, 188, 106, 194);
+ surface->fillRect(energyBar, front);
+ }
+
+ if (shield >= 0) {
+ Common::Rect backBar(43, 181, 106 - shield, 187);
+ surface->fillRect(backBar, back);
+
+ Common::Rect shieldBar(106 - shield, 181, 106, 187);
+ surface->fillRect(shieldBar, front);
+ }
+}
+
void DrillerEngine::drawAmigaAtariSTUI(Graphics::Surface *surface) {
uint32 white = _gfx->_texturePixelFormat.ARGBToColor(0xFF, 0xFF, 0xFF, 0xFF);
uint32 yellow = _gfx->_texturePixelFormat.ARGBToColor(0xFF, 0xFF, 0xFF, 0x55);
Commit: 1391e297221719715b206b61e34eac991ca58231
https://github.com/scummvm/scummvm/commit/1391e297221719715b206b61e34eac991ca58231
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2022-12-24T13:18:53-03:00
Commit Message:
FREESCAPE: implemented stipple data usage for ZX renderer
Changed paths:
engines/freescape/games/driller.cpp
engines/freescape/gfx.cpp
engines/freescape/gfx.h
engines/freescape/gfx_opengl.cpp
engines/freescape/gfx_opengl.h
engines/freescape/gfx_tinygl.cpp
diff --git a/engines/freescape/games/driller.cpp b/engines/freescape/games/driller.cpp
index 4dfdbf71339..25788e9616a 100644
--- a/engines/freescape/games/driller.cpp
+++ b/engines/freescape/games/driller.cpp
@@ -653,7 +653,7 @@ void DrillerEngine::drawZXUI(Graphics::Surface *surface) {
int minutes = _countdown <= 0 ? 0 : (_countdown - hours * 3600) / 60;
drawStringInSurface(Common::String::format("%02d", minutes), 209, 12, front, back, surface);
int seconds = _countdown <= 0 ? 0 : _countdown - hours * 3600 - minutes * 60;
- drawStringInSurface(Common::String::format("%02d", seconds), 233, 12, front, back, surface);
+ drawStringInSurface(Common::String::format("%02d", seconds), 232, 12, front, back, surface);
Common::String message;
int deadline;
diff --git a/engines/freescape/gfx.cpp b/engines/freescape/gfx.cpp
index 38fc9f84e25..11fc4fd5ef5 100644
--- a/engines/freescape/gfx.cpp
+++ b/engines/freescape/gfx.cpp
@@ -92,7 +92,7 @@ bool Renderer::getRGBAtCGA(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &
return true;
}
-bool Renderer::getRGBAtZX(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2) {
+bool Renderer::getRGBAtZX(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2, byte *stipple) {
if (index == _keyColor)
return false;
@@ -109,9 +109,15 @@ bool Renderer::getRGBAtZX(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r
return true;
}
- //setStippleData(entry);
- readFromPalette(_inkColor, r1, g1, b1);
- readFromPalette(_paperColor, r2, g2, b2);
+ if (stipple) {
+ stipple[0] = entry[0];
+ stipple[1] = entry[1];
+ stipple[2] = entry[2];
+ stipple[3] = entry[3];
+ }
+
+ readFromPalette(_paperColor, r1, g1, b1);
+ readFromPalette(_inkColor, r2, g2, b2);
return true;
}
@@ -137,7 +143,7 @@ bool Renderer::getRGBAtEGA(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &
return true;
}
-bool Renderer::getRGBAt(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2) {
+bool Renderer::getRGBAt(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2, byte *stipple) {
if (_colorRemaps && _colorRemaps->contains(index)) {
index = (*_colorRemaps)[index];
@@ -170,7 +176,7 @@ bool Renderer::getRGBAt(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2,
else if (_renderMode == Common::kRenderCGA)
return getRGBAtCGA(index, r1, g1, b1, r2, g2, b2);
else if (_renderMode == Common::kRenderZX)
- return getRGBAtZX(index, r1, g1, b1, r2, g2, b2);
+ return getRGBAtZX(index, r1, g1, b1, r2, g2, b2, stipple);
error("Invalid or unsupported render mode");
@@ -302,8 +308,10 @@ void Renderer::renderPyramid(const Math::Vector3d &origin, const Math::Vector3d
}
Common::Array<Math::Vector3d> face;
+ uint32 stipple = 0;
uint8 r1, g1, b1, r2, g2, b2;
- if (getRGBAt((*colours)[0], r1, g1, b1, r2, g2, b2)) {
+ if (getRGBAt((*colours)[0], r1, g1, b1, r2, g2, b2, (byte *)&stipple)) {
+ setStippleData((byte *)&stipple);
useColor(r1, g1, b1);
face.push_back(vertices[4]);
@@ -323,7 +331,8 @@ void Renderer::renderPyramid(const Math::Vector3d &origin, const Math::Vector3d
face.clear();
}
- if (getRGBAt((*colours)[1], r1, g1, b1, r2, g2, b2)) {
+ if (getRGBAt((*colours)[1], r1, g1, b1, r2, g2, b2, (byte *)&stipple)) {
+ setStippleData((byte *)&stipple);
useColor(r1, g1, b1);
face.push_back(vertices[5]);
@@ -342,7 +351,8 @@ void Renderer::renderPyramid(const Math::Vector3d &origin, const Math::Vector3d
face.clear();
}
- if (getRGBAt((*colours)[2], r1, g1, b1, r2, g2, b2)) {
+ if (getRGBAt((*colours)[2], r1, g1, b1, r2, g2, b2, (byte *)&stipple)) {
+ setStippleData((byte *)&stipple);
useColor(r1, g1, b1);
face.push_back(vertices[6]);
@@ -360,7 +370,8 @@ void Renderer::renderPyramid(const Math::Vector3d &origin, const Math::Vector3d
face.clear();
}
- if (getRGBAt((*colours)[3], r1, g1, b1, r2, g2, b2)) {
+ if (getRGBAt((*colours)[3], r1, g1, b1, r2, g2, b2, (byte *)&stipple)) {
+ setStippleData((byte *)&stipple);
useColor(r1, g1, b1);
face.push_back(vertices[7]);
@@ -379,7 +390,8 @@ void Renderer::renderPyramid(const Math::Vector3d &origin, const Math::Vector3d
face.clear();
}
- if (getRGBAt((*colours)[4], r1, g1, b1, r2, g2, b2)) {
+ if (getRGBAt((*colours)[4], r1, g1, b1, r2, g2, b2, (byte *)&stipple)) {
+ setStippleData((byte *)&stipple);
useColor(r1, g1, b1);
face.push_back(vertices[0]);
@@ -397,7 +409,8 @@ void Renderer::renderPyramid(const Math::Vector3d &origin, const Math::Vector3d
face.clear();
}
- if (getRGBAt((*colours)[5], r1, g1, b1, r2, g2, b2)) {
+ if (getRGBAt((*colours)[5], r1, g1, b1, r2, g2, b2, (byte *)&stipple)) {
+ setStippleData((byte *)&stipple);
useColor(r1, g1, b1);
face.push_back(vertices[7]);
@@ -415,10 +428,12 @@ void Renderer::renderPyramid(const Math::Vector3d &origin, const Math::Vector3d
}
void Renderer::renderCube(const Math::Vector3d &origin, const Math::Vector3d &size, Common::Array<uint8> *colours) {
+ uint32 stipple = 0;
uint8 r1, g1, b1, r2, g2, b2;
Common::Array<Math::Vector3d> face;
- if (getRGBAt((*colours)[0], r1, g1, b1, r2, g2, b2)) {
+ if (getRGBAt((*colours)[0], r1, g1, b1, r2, g2, b2, (byte *)&stipple)) {
+ setStippleData((byte *)&stipple);
useColor(r1, g1, b1);
face.push_back(origin);
face.push_back(Math::Vector3d(origin.x(), origin.y(), origin.z() + size.z()));
@@ -433,7 +448,8 @@ void Renderer::renderCube(const Math::Vector3d &origin, const Math::Vector3d &si
}
}
- if (getRGBAt((*colours)[1], r1, g1, b1, r2, g2, b2)) {
+ if (getRGBAt((*colours)[1], r1, g1, b1, r2, g2, b2, (byte *)&stipple)) {
+ setStippleData((byte *)&stipple);
useColor(r1, g1, b1);
face.clear();
face.push_back(Math::Vector3d(origin.x() + size.x(), origin.y() + size.y(), origin.z()));
@@ -449,7 +465,8 @@ void Renderer::renderCube(const Math::Vector3d &origin, const Math::Vector3d &si
}
}
- if (getRGBAt((*colours)[2], r1, g1, b1, r2, g2, b2)) {
+ if (getRGBAt((*colours)[2], r1, g1, b1, r2, g2, b2, (byte *)&stipple)) {
+ setStippleData((byte *)&stipple);
useColor(r1, g1, b1);
face.clear();
face.push_back(Math::Vector3d(origin.x() + size.x(), origin.y(), origin.z()));
@@ -465,7 +482,8 @@ void Renderer::renderCube(const Math::Vector3d &origin, const Math::Vector3d &si
}
}
- if (getRGBAt((*colours)[3], r1, g1, b1, r2, g2, b2)) {
+ if (getRGBAt((*colours)[3], r1, g1, b1, r2, g2, b2, (byte *)&stipple)) {
+ setStippleData((byte *)&stipple);
useColor(r1, g1, b1);
face.clear();
face.push_back(Math::Vector3d(origin.x(), origin.y() + size.y(), origin.z()));
@@ -481,7 +499,8 @@ void Renderer::renderCube(const Math::Vector3d &origin, const Math::Vector3d &si
}
}
- if (getRGBAt((*colours)[4], r1, g1, b1, r2, g2, b2)) {
+ if (getRGBAt((*colours)[4], r1, g1, b1, r2, g2, b2, (byte *)&stipple)) {
+ setStippleData((byte *)&stipple);
useColor(r1, g1, b1);
face.clear();
face.push_back(Math::Vector3d(origin.x(), origin.y() + size.y(), origin.z()));
@@ -497,7 +516,8 @@ void Renderer::renderCube(const Math::Vector3d &origin, const Math::Vector3d &si
}
}
- if (getRGBAt((*colours)[5], r1, g1, b1, r2, g2, b2)) {
+ if (getRGBAt((*colours)[5], r1, g1, b1, r2, g2, b2, (byte *)&stipple)) {
+ setStippleData((byte *)&stipple);
useColor(r1, g1, b1);
face.clear();
face.push_back(Math::Vector3d(origin.x(), origin.y(), origin.z() + size.z()));
@@ -521,11 +541,13 @@ void Renderer::renderRectangle(const Math::Vector3d &origin, const Math::Vector3
float dx, dy, dz;
uint8 r1, g1, b1, r2, g2, b2;
+ uint32 stipple = 0;
Common::Array<Math::Vector3d> vertices;
for (int i = 0; i < 2; i++) {
// debug("rec color: %d", (*colours)[i]);
- if (getRGBAt((*colours)[i], r1, g1, b1, r2, g2, b2)) {
+ if (getRGBAt((*colours)[i], r1, g1, b1, r2, g2, b2, (byte *)&stipple)) {
+ setStippleData((byte *)&stipple);
useColor(r1, g1, b1);
vertices.clear();
vertices.push_back(Math::Vector3d(origin.x(), origin.y(), origin.z()));
@@ -577,6 +599,7 @@ void Renderer::renderRectangle(const Math::Vector3d &origin, const Math::Vector3
void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d &size, const Common::Array<uint16> *ordinates, Common::Array<uint8> *colours) {
uint8 r1, g1, b1, r2, g2, b2;
+ uint32 stipple = 0;
if (ordinates->size() % 3 > 0 && ordinates->size() > 0)
error("Invalid polygon with size %f %f %f and ordinates %d", size.x(), size.y(), size.z(), ordinates->size());
@@ -584,7 +607,8 @@ void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d
polygonOffset(true);
if (ordinates->size() == 6) { // Line
- assert(getRGBAt((*colours)[0], r1, g1, b1, r2, g2, b2)); // It will never return false?
+ assert(getRGBAt((*colours)[0], r1, g1, b1, r2, g2, b2, (byte *)&stipple)); // It will never return false?
+ setStippleData((byte *)&stipple);
useColor(r1, g1, b1);
for (uint i = 0; i < ordinates->size(); i = i + 3)
vertices.push_back(Math::Vector3d((*ordinates)[i], (*ordinates)[i + 1], (*ordinates)[i + 2]));
@@ -597,7 +621,8 @@ void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d
}
vertices.clear();
- assert(getRGBAt((*colours)[1], r1, g1, b1, r2, g2, b2)); // It will never return false?
+ assert(getRGBAt((*colours)[1], r1, g1, b1, r2, g2, b2, (byte *)&stipple)); // It will never return false?
+ setStippleData((byte *)&stipple);
useColor(r1, g1, b1);
for (int i = ordinates->size(); i > 0; i = i - 3)
vertices.push_back(Math::Vector3d((*ordinates)[i - 3], (*ordinates)[i - 2], (*ordinates)[i - 1]));
@@ -610,7 +635,8 @@ void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d
}
} else {
- if (getRGBAt((*colours)[0], r1, g1, b1, r2, g2, b2)) {
+ if (getRGBAt((*colours)[0], r1, g1, b1, r2, g2, b2, (byte *)&stipple)) {
+ setStippleData((byte *)&stipple);
useColor(r1, g1, b1);
for (uint i = 0; i < ordinates->size(); i = i + 3) {
vertices.push_back(Math::Vector3d((*ordinates)[i], (*ordinates)[i + 1], (*ordinates)[i + 2]));
@@ -624,7 +650,8 @@ void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d
}
}
vertices.clear();
- if (getRGBAt((*colours)[1], r1, g1, b1, r2, g2, b2)) {
+ if (getRGBAt((*colours)[1], r1, g1, b1, r2, g2, b2, (byte *)&stipple)) {
+ setStippleData((byte *)&stipple);
useColor(r1, g1, b1);
for (int i = ordinates->size(); i > 0; i = i - 3) {
vertices.push_back(Math::Vector3d((*ordinates)[i - 3], (*ordinates)[i - 2], (*ordinates)[i - 1]));
diff --git a/engines/freescape/gfx.h b/engines/freescape/gfx.h
index fe0f740b69f..3d2730654d7 100644
--- a/engines/freescape/gfx.h
+++ b/engines/freescape/gfx.h
@@ -98,11 +98,12 @@ public:
// palette
void readFromPalette(uint8 index, uint8 &r, uint8 &g, uint8 &b);
uint8 indexFromColor(uint8 r, uint8 g, uint8 b);
- bool getRGBAt(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2);
+ bool getRGBAt(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2, byte *stipple);
bool getRGBAtCGA(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2);
bool getRGBAtEGA(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2);
- bool getRGBAtZX(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2);
+ bool getRGBAtZX(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2, byte *stipple);
+ virtual void setStippleData(byte *data) {};
virtual void useStipple(bool enabled) {};
byte *_palette;
ColorMap *_colorMap;
diff --git a/engines/freescape/gfx_opengl.cpp b/engines/freescape/gfx_opengl.cpp
index 245ffa02193..d638449a9a6 100644
--- a/engines/freescape/gfx_opengl.cpp
+++ b/engines/freescape/gfx_opengl.cpp
@@ -272,12 +272,20 @@ void OpenGLRenderer::polygonOffset(bool enabled) {
}
}
+void OpenGLRenderer::setStippleData(byte *data) {
+ if (!data)
+ return;
+
+ for (int i = 0; i < 128; i++)
+ _variableStippleArray[i] = data[(i / 16) % 4];
+}
+
void OpenGLRenderer::useStipple(bool enabled) {
if (enabled) {
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(-5.0f, 1.0f);
glEnable(GL_POLYGON_STIPPLE);
- glPolygonStipple(_stippleArray);
+ glPolygonStipple(_renderMode == Common::kRenderCGA ? _defaultStippleArray : _variableStippleArray);
} else {
glPolygonOffset(0, 0);
glDisable(GL_POLYGON_OFFSET_FILL);
@@ -303,7 +311,8 @@ void OpenGLRenderer::clear(uint8 color) {
void OpenGLRenderer::drawFloor(uint8 color) {
uint8 r1, g1, b1, r2, g2, b2;
- assert(getRGBAt(color, r1, g1, b1, r2, g2, b2)); // TODO: move check inside this function
+ uint32 stipple = 0;
+ assert(getRGBAt(color, r1, g1, b1, r2, g2, b2, (byte *)&stipple)); // TODO: move check inside this function
glColor3ub(r1, g1, b1);
glEnableClientState(GL_VERTEX_ARRAY);
diff --git a/engines/freescape/gfx_opengl.h b/engines/freescape/gfx_opengl.h
index 2dd0deaec3e..cc9536eac79 100644
--- a/engines/freescape/gfx_opengl.h
+++ b/engines/freescape/gfx_opengl.h
@@ -60,7 +60,7 @@ public:
_coords[idx].x = src.getValue(0); _coords[idx].y = src.getValue(1);
}
- GLubyte _stippleArray[128] = {
+ GLubyte _defaultStippleArray[128] = {
0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
@@ -79,6 +79,25 @@ public:
0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
};
+ GLubyte _variableStippleArray[128] = {
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ };
+
virtual void init() override;
virtual void clear(uint8 color) override;
virtual void setViewport(const Common::Rect &rect) override;
@@ -87,8 +106,10 @@ public:
virtual void useColor(uint8 r, uint8 g, uint8 b) override;
virtual void polygonOffset(bool enabled) override;
+ virtual void setStippleData(byte *data) override;
virtual void useStipple(bool enabled) override;
+
Texture *createTexture(const Graphics::Surface *surface) override;
void freeTexture(Texture *texture) override;
virtual void drawTexturedRect2D(const Common::Rect &screenRect, const Common::Rect &textureRect, Texture *texture) override;
diff --git a/engines/freescape/gfx_tinygl.cpp b/engines/freescape/gfx_tinygl.cpp
index 6cc77743985..15456f24118 100644
--- a/engines/freescape/gfx_tinygl.cpp
+++ b/engines/freescape/gfx_tinygl.cpp
@@ -227,7 +227,7 @@ void TinyGLRenderer::clear(uint8 color) {
void TinyGLRenderer::drawFloor(uint8 color) {
uint8 r1, g1, b1, r2, g2, b2;
- assert(getRGBAt(color, r1, g1, b1, r2, g2, b2)); // TODO: move check inside this function
+ assert(getRGBAt(color, r1, g1, b1, r2, g2, b2, nullptr)); // TODO: move check inside this function
tglColor3ub(r1, g1, b1);
tglEnableClientState(TGL_VERTEX_ARRAY);
More information about the Scummvm-git-logs
mailing list