Skip to content

Commit

Permalink
FREESCAPE: reworked the C64 implementation of driller
Browse files Browse the repository at this point in the history
  • Loading branch information
neuromancer committed Jan 27, 2025
1 parent 1e6c477 commit 00c4aa1
Show file tree
Hide file tree
Showing 8 changed files with 163 additions and 53 deletions.
Binary file not shown.
Binary file modified dists/engine-data/freescape.dat
Binary file not shown.
9 changes: 9 additions & 0 deletions engines/freescape/detection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,15 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_UNSTABLE,
GUIO2(GUIO_NOMIDI, GAMEOPTION_AUTOMATIC_DRILLING)
},
{
"driller", // Tape re-releae
"",
AD_ENTRY1s("DRILLER.C64.DATA", "606bc969e5442634c8ab057bfde9d9d2", 64750),
Common::EN_ANY,
Common::kPlatformC64,
ADGF_UNSTABLE,
GUIO2(GUIO_NOMIDI, GAMEOPTION_AUTOMATIC_DRILLING)
},
{
"driller",
"",
Expand Down
15 changes: 10 additions & 5 deletions engines/freescape/font.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ Common::Array<Graphics::ManagedSurface *> FreescapeEngine::getChars(Common::Seek
file->read(fontBuffer, 6 * charsNumber);

Common::BitArray font;
font.set_size(48 * charsNumber);
font.set_size(48 * charsNumber); // Enough to hold characters for all platforms
font.set_bits(fontBuffer);

Common::Array<Graphics::ManagedSurface *> chars;
Expand All @@ -128,15 +128,20 @@ Common::Array<Graphics::ManagedSurface *> FreescapeEngine::getChars(Common::Seek
int position = sizeX * sizeY * c;

Graphics::ManagedSurface *surface = new Graphics::ManagedSurface();
surface->create(_renderMode == Common::kRenderHercG ? 16 : 8, sizeY, Graphics::PixelFormat::createFormatCLUT8());

int charWidth = sizeX;
if (_renderMode == Common::kRenderHercG || isC64())
charWidth *= 2;

surface->create(charWidth, sizeY, Graphics::PixelFormat::createFormatCLUT8());
for (int j = 0; j < sizeY; j++) {
for (int i = 0; i < sizeX; i++) {
if (font.get(position + additional + j * 8 + i)) {
if (_renderMode != Common::kRenderHercG) {
surface->setPixel(7 - i, j, 1);
} else {
if (_renderMode == Common::kRenderHercG || isC64()) {
surface->setPixel(2 * (7 - i), j, 1);
surface->setPixel(2 * (7 - i) + 1, j, 1);
} else {
surface->setPixel(7 - i, j, 1);
}
}
}
Expand Down
69 changes: 41 additions & 28 deletions engines/freescape/games/driller/c64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
namespace Freescape {

void DrillerEngine::initC64() {
_viewArea = Common::Rect(32, 16, 288, 119);
_viewArea = Common::Rect(32, 16, 288, 120);
}

void DrillerEngine::loadAssetsC64FullGame() {
Expand All @@ -41,23 +41,32 @@ void DrillerEngine::loadAssetsC64FullGame() {
loadGlobalObjects(&file, 0x1855, 8);
} else if (_targetName.hasPrefix("driller")) {
file.open("driller.c64.data");
loadMessagesFixedSize(&file, 0x167a - 0x400, 14, 20);
//loadMessagesFixedSize(&file, 0x167a - 0x400, 14, 20);
//loadFonts(&file, 0xae54);
load8bitBinary(&file, 0x8e02 - 0x400, 4);
loadGlobalObjects(&file, 0x1855 - 0x400, 8);
loadFonts(&file, 0x4ee);
load8bitBinary(&file, 0x8eef - 1, 16);
loadMessagesFixedSize(&file, 0x1766, 14, 20);

Graphics::Surface *surf = loadBundledImage("driller_border");
surf->convertToInPlace(_gfx->_texturePixelFormat);
_border = new Graphics::ManagedSurface();
_border->copyFrom(*surf);

//_border = _title;
//loadGlobalObjects(&file, 0x1855 - 0x400, 8);
} else
error("Unknown C64 release");
}


void DrillerEngine::drawC64UI(Graphics::Surface *surface) {
uint32 color = 1;

uint8 r, g, b;
uint32 front = _gfx->_texturePixelFormat.ARGBToColor(0xFF, 0xAA, 0xAA, 0xAA);

_gfx->selectColorFromFourColorPalette(color, r, g, b);
uint32 front = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
Common::Rect cover;

color = 0;
uint32 color = 0;
if (_gfx->_colorRemaps && _gfx->_colorRemaps->contains(color)) {
color = (*_gfx->_colorRemaps)[color];
}
Expand All @@ -66,30 +75,33 @@ void DrillerEngine::drawC64UI(Graphics::Surface *surface) {
uint32 back = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);

int score = _gameStateVars[k8bitVariableScore];
drawStringInSurface(_currentArea->_name, 200, 188, front, back, surface);
drawStringInSurface(Common::String::format("%04d", int(2 * _position.x())), 149, 148, front, back, surface);
drawStringInSurface(Common::String::format("%04d", int(2 * _position.z())), 149, 156, front, back, surface);
drawStringInSurface(Common::String::format("%04d", int(2 * _position.y())), 149, 164, front, back, surface);
drawStringInSurface(_currentArea->_name, 200, 184, front, back, surface);
cover = Common::Rect(150, 143, 183, 167);

surface->fillRect(cover, back);
drawStringInSurface(Common::String::format("%04d", int(2 * _position.x())), 150, 148 - 4, front, back, surface);
drawStringInSurface(Common::String::format("%04d", int(2 * _position.z())), 150, 156 - 4, front, back, surface);
drawStringInSurface(Common::String::format("%04d", int(2 * _position.y())), 150, 164 - 4, front, back, surface);
if (_playerHeightNumber >= 0)
drawStringInSurface(Common::String::format("%d", _playerHeightNumber), 54, 164, front, back, surface);
drawStringInSurface(Common::String::format("%d", _playerHeightNumber), 54 + 6, 164 - 3, front, back, surface);
else
drawStringInSurface(Common::String::format("%s", "J"), 54, 164, front, back, surface);
drawStringInSurface(Common::String::format("%s", "J"), 54 + 6, 164 - 3, front, back, surface);

drawStringInSurface(Common::String::format("%02d", int(_angleRotations[_angleRotationIndex])), 46, 148, front, back, surface);
drawStringInSurface(Common::String::format("%3d", _playerSteps[_playerStepIndex]), 44, 156, front, back, surface);
drawStringInSurface(Common::String::format("%07d", score), 240, 128, front, back, surface);
drawStringInSurface(Common::String::format("%02d", int(_angleRotations[_angleRotationIndex])), 46, 148 - 3, front, back, surface);
drawStringInSurface(Common::String::format("%3d", _playerSteps[_playerStepIndex]), 46, 156 - 3, front, back, surface);
drawStringInSurface(Common::String::format("%07d", score), 239, 128, front, back, surface);

int seconds, minutes, hours;
getTimeFromCountdown(seconds, minutes, hours);
drawStringInSurface(Common::String::format("%02d", hours), 209, 11, front, back, surface);
drawStringInSurface(Common::String::format("%02d", minutes), 232, 11, front, back, surface);
drawStringInSurface(Common::String::format("%02d", seconds), 254, 11, front, back, surface);
drawStringInSurface(Common::String::format("%02d", hours), 207, 8, front, back, surface);
drawStringInSurface(Common::String::format("%02d", minutes), 230, 8, front, back, surface);
drawStringInSurface(Common::String::format("%02d", seconds), 254, 8, front, back, surface);

Common::String message;
int deadline;
getLatestMessages(message, deadline);
if (deadline <= _countdown) {
drawStringInSurface(message, 191, 180, back, front, surface);
drawStringInSurface(message, 191, 176, back, front, surface);
_temporaryMessages.push_back(message);
_temporaryMessageDeadlines.push_back(deadline);
} else {
Expand All @@ -100,25 +112,26 @@ void DrillerEngine::drawC64UI(Graphics::Surface *surface) {
else
message = _messagesList[1];

drawStringInSurface(message, 191, 180, front, back, surface);
drawStringInSurface(message, 191, 176, front, back, surface);
}

uint32 green = _gfx->_texturePixelFormat.ARGBToColor(0xFF, 0x68, 0xa9, 0x41);
int energy = _gameStateVars[k8bitVariableEnergy];
int shield = _gameStateVars[k8bitVariableShield];

if (energy >= 0) {
Common::Rect backBar(25, 187, 89 - energy, 194);
Common::Rect backBar(21, 183, 85 - energy, 190);
surface->fillRect(backBar, back);
Common::Rect energyBar(88 - energy, 187, 88, 194);
surface->fillRect(energyBar, front);
Common::Rect energyBar(84 - energy, 184, 84, 190);
surface->fillRect(energyBar, green);
}

if (shield >= 0) {
Common::Rect backBar(25, 180, 89 - shield, 186);
Common::Rect backBar(25 - 4, 180 - 4, 89 - shield - 4, 186 - 4);
surface->fillRect(backBar, back);

Common::Rect shieldBar(88 - shield, 180, 88, 186);
surface->fillRect(shieldBar, front);
Common::Rect shieldBar(88 - 4 - shield, 180 - 4, 88 - 4, 186 - 4);
surface->fillRect(shieldBar, green);
}
}

Expand Down
33 changes: 33 additions & 0 deletions engines/freescape/games/driller/driller.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
*
*/

#include "audio/audiostream.h"
#include "audio/mixer.h"
#include "audio/softsynth/sid.h"

namespace Freescape {

class DrillerEngine : public FreescapeEngine {
Expand Down Expand Up @@ -114,4 +118,33 @@ enum DrillerReleaseFlags {
GF_ATARI_MAGAZINE_DEMO = (1 << 1),
};

class Player_SID : public Audio::AudioStream {
public:
Player_SID(Audio::Mixer *mixer);
~Player_SID() override;

void startMusic();
void stopMusic();

// AudioStream API
int readBuffer(int16 *buffer, const int numSamples) override;
bool isStereo() const override { return false; }
bool endOfData() const override { return false; }
int getRate() const override { return _sampleRate; }

private:
Resid::SID *_sid;
void SID_Write(int reg, uint8 data);
void initSID();
uint8 *getResource(int resID);

// Unclear if this is needed
// number of cpu cycles until next frame update
//Resid::cycle_count _cpuCyclesLeft;

Audio::Mixer *_mixer;
Audio::SoundHandle _soundHandle;
int _sampleRate;
};

}
69 changes: 51 additions & 18 deletions engines/freescape/gfx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,14 @@ byte getCGAPixel(byte x, int index) {
error("Invalid index %d requested", index);
}

byte getC64Pixel(byte x, int index) {
if (index < 0 || index > 3) {
error("Invalid index %d requested\n", index);
}
// Extract the corresponding 2-bit pair based on the index
return ((x >> (index * 2)) & 0x3);
}

byte getCGAStipple(byte x, int back, int fore) {
int c0 = getCGAPixel(x, 0);
assert(c0 == back || c0 == fore || back == fore);
Expand All @@ -137,6 +145,32 @@ byte getCGAStipple(byte x, int back, int fore) {
return st;
}

byte getC64Stipple(byte x, int back, int fore) {
int c0 = getC64Pixel(x, 0);
assert(c0 == back || c0 == fore || back == fore);
int c1 = getC64Pixel(x, 1);
assert(c1 == back || c1 == fore || back == fore);
int c2 = getC64Pixel(x, 2);
assert(c2 == back || c2 == fore || back == fore);
int c3 = getC64Pixel(x, 3);
assert(c3 == back || c3 == fore || back == fore);

byte st = 0;
if (c0 == fore)
st = st | 0x3;

if (c1 == fore)
st = st | (0x3 << 2);

if (c2 == fore)
st = st | (0x3 << 4);

if (c3 == fore)
st = st | (0x3 << 6);

return st;
}

void Renderer::clearColorPairArray() {
for (int i = 0; i < 16; i++)
_colorPair[i] = 0;
Expand All @@ -150,6 +184,8 @@ void Renderer::fillColorPairArray() {
c1 = getCGAPixel(entry[0], 0);
else if (_renderMode == Common::kRenderCPC)
c1 = getCPCPixel(entry[0], 0, true);
else if (_renderMode == Common::kRenderC64)
c1 = getC64Pixel(entry[0], 0);
else
error("Not implemented");

Expand All @@ -162,6 +198,8 @@ void Renderer::fillColorPairArray() {
c = getCGAPixel(entry[j], k);
else if (_renderMode == Common::kRenderCPC)
c = getCPCPixel(entry[j], k, true);
else if (_renderMode == Common::kRenderC64)
c = getC64Pixel(entry[j], k);
else
error("Not implemented");
if (c1 != c) {
Expand Down Expand Up @@ -226,7 +264,7 @@ void Renderer::setColorMap(ColorMap *colorMap_) {
byte c2 = (pair >> 4) & 0xf;
byte *entry = (*_colorMap)[i];
for (int j = 0; j < 128; j++)
_stipples[i][j] = getCPCStipple(entry[(j / 8) % 4], c1, c2) ;
_stipples[i][j] = getCPCStipple(entry[(j / 8) % 4], c1, c2);
}
} else if (_renderMode == Common::kRenderCGA) {
fillColorPairArray();
Expand All @@ -236,9 +274,19 @@ void Renderer::setColorMap(ColorMap *colorMap_) {
byte c2 = (pair >> 4) & 0xf;
byte *entry = (*_colorMap)[i];
for (int j = 0; j < 128; j++)
_stipples[i][j] = getCGAStipple(entry[(j / 8) % 4], c1, c2) ;
_stipples[i][j] = getCGAStipple(entry[(j / 8) % 4], c1, c2);
}
}
} /*else if (_renderMode == Common::kRenderC64) {
fillColorPairArray();
for (int i = 4; i < 15; i++) {
byte pair = _colorPair[i];
byte c1 = pair & 0xf;
byte c2 = (pair >> 4) & 0xf;
byte *entry = (*_colorMap)[i];
for (int j = 0; j < 128; j++)
_stipples[i][j] = getC64Stipple(entry[(j / 8) % 4], c1, c2);
}
}*/

if (_isAccelerated && _authenticGraphics) {
for (int i = 1; i <= 14; i++) {
Expand Down Expand Up @@ -315,21 +363,6 @@ void Renderer::extractC64Indexes(uint8 cm1, uint8 cm2, uint8 &i1, uint8 &i2) {
} else if (cm1 == 0x41 && cm2 == 0x52) {
i1 = 0;
i2 = 3;
// Covered by the default of i1 = 0, i2 = 0
#if 0
} else if (cm1 == 0x5a && cm2 == 0xa5) {
i1 = 0;
i2 = 0;
} else if (cm1 == 0xbb && cm2 == 0xee) {
i1 = 0;
i2 = 0;
} else if (cm1 == 0x5f && cm2 == 0xaf) {
i1 = 0;
i2 = 0;
} else if (cm1 == 0xfb && cm2 == 0xfe) {
i1 = 0;
i2 = 0;
#endif
} else {
i1 = 0;
i2 = 0;
Expand Down
21 changes: 19 additions & 2 deletions engines/freescape/loaders/8bitBinaryLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,7 @@ Area *FreescapeEngine::load8bitArea(Common::SeekableReadStream *file, uint16 nco
uint8 paperColor = 0;
uint8 inkColor = 0;

if (!(isCastle() && (isSpectrum() || isCPC()))) {
if (!(isCastle() && (isSpectrum() || isCPC() || isC64()))) {
usualBackgroundColor = readField(file, 8);
underFireBackgroundColor = readField(file, 8);
paperColor = readField(file, 8);
Expand Down Expand Up @@ -993,7 +993,24 @@ void FreescapeEngine::loadFonts(Common::SeekableReadStream *file, int offset) {

if (isAmiga() || isAtariST())
chars = getCharsAmigaAtari(file, offset, 85);
else
else if (isC64()) {
Common::Array<Graphics::ManagedSurface *> rawChars = getChars(file, offset, 85);

Common::Rect charRect;
for (Graphics::ManagedSurface *rawChar : rawChars) {
charRect = Common::Rect(0, 0, 8, 6);
Graphics::ManagedSurface *charSurface = new Graphics::ManagedSurface();
charSurface->create(8, 6, Graphics::PixelFormat::createFormatCLUT8());
charSurface->copyRectToSurface(*rawChar, 0, 0, charRect);
chars.push_back(charSurface);

charRect = Common::Rect(8, 0, 16, 6);
charSurface = new Graphics::ManagedSurface();
charSurface->create(8, 6, Graphics::PixelFormat::createFormatCLUT8());
charSurface->copyRectToSurface(*rawChar, 0, 0, charRect);
chars.push_back(charSurface);
}
} else
chars = getChars(file, offset, 85);

_font = Font(chars);
Expand Down

0 comments on commit 00c4aa1

Please sign in to comment.