diff options
Diffstat (limited to 'engines/adl/display_a2.cpp')
-rw-r--r-- | engines/adl/display_a2.cpp | 430 |
1 files changed, 244 insertions, 186 deletions
diff --git a/engines/adl/display_a2.cpp b/engines/adl/display_a2.cpp index 3a62e33ca6..e738e77154 100644 --- a/engines/adl/display_a2.cpp +++ b/engines/adl/display_a2.cpp @@ -101,183 +101,6 @@ static const byte font[64][5] = { { 0x00, 0x82, 0x44, 0x28, 0x10 }, { 0x04, 0x02, 0xb2, 0x0a, 0x04 } // >? }; -Display_A2::Display_A2() : _showCursor(false) { - initGraphics(Display_A2::kGfxWidth * 2, Display_A2::kGfxHeight * 2); -} - -Display_A2::~Display_A2() { - delete[] _frameBuf; - - if (_font) { - _font->free(); - delete _font; - } -} - -void Display_A2::init() { - _monochrome = !ConfMan.getBool("color"); - _scanlines = ConfMan.getBool("scanlines"); - - if (_monochrome) - g_system->getPaletteManager()->setPalette(monoPalette, 0, MONO_PALETTE_ENTRIES); - else - g_system->getPaletteManager()->setPalette(colorPalette, 0, COLOR_PALETTE_ENTRIES); - - showScanlines(_scanlines); - - // We need 2x scaling to properly render the half-pixel shift - // of the second palette - createSurfaces(Display_A2::kGfxWidth * 2, Display_A2::kGfxHeight * 2, 64); - createTextBuffer(Display_A2::kTextWidth, Display_A2::kTextHeight); - - _frameBuf = new byte[Display_A2::kGfxSize]; - memset(_frameBuf, 0, Display_A2::kGfxSize); - - createFont(); - - _startMillis = g_system->getMillis(); -} - -bool Display_A2::saveThumbnail(Common::WriteStream &out) { - if (_scanlines) { - showScanlines(false); - g_system->updateScreen(); - } - - bool retval = Graphics::saveThumbnail(out); - - if (_scanlines) { - showScanlines(true); - g_system->updateScreen(); - } - - return retval; -} - -void Display_A2::loadFrameBuffer(Common::ReadStream &stream, byte *dst) { - for (uint j = 0; j < 8; ++j) { - for (uint i = 0; i < 8; ++i) { - stream.read(dst, Display_A2::kGfxPitch); - dst += Display_A2::kGfxPitch * 64; - stream.read(dst, Display_A2::kGfxPitch); - dst += Display_A2::kGfxPitch * 64; - stream.read(dst, Display_A2::kGfxPitch); - stream.readUint32LE(); - stream.readUint32LE(); - dst -= Display_A2::kGfxPitch * 120; - } - dst -= Display_A2::kGfxPitch * 63; - } - - if (stream.eos() || stream.err()) - error("Failed to read frame buffer"); -} - -void Display_A2::loadFrameBuffer(Common::ReadStream &stream) { - loadFrameBuffer(stream, _frameBuf); -} - -void Display_A2::putPixel(const Common::Point &p, byte color) { - byte offset = p.x / 7; - byte mask = 0x80 | (1 << (p.x % 7)); - - // Since white and black are in both palettes, we leave - // the palette bit alone - if ((color & 0x7f) == 0x7f || (color & 0x7f) == 0) - mask &= 0x7f; - - // Adjust colors starting with bits '01' or '10' for - // odd offsets - if (offset & 1) { - byte c = color << 1; - if (c >= 0x40 && c < 0xc0) - color ^= 0x7f; - } - - writeFrameBuffer(p, color, mask); -} - -void Display_A2::setPixelByte(const Common::Point &p, byte color) { - assert(p.x >= 0 && p.x < Display_A2::kGfxWidth && p.y >= 0 && p.y < Display_A2::kGfxHeight); - - _frameBuf[p.y * Display_A2::kGfxPitch + p.x / 7] = color; -} - -void Display_A2::setPixelBit(const Common::Point &p, byte color) { - writeFrameBuffer(p, color, 1 << (p.x % 7)); -} - -void Display_A2::setPixelPalette(const Common::Point &p, byte color) { - writeFrameBuffer(p, color, 0x80); -} - -byte Display_A2::getPixelByte(const Common::Point &p) const { - assert(p.x >= 0 && p.x < Display_A2::kGfxWidth && p.y >= 0 && p.y < Display_A2::kGfxHeight); - - return _frameBuf[p.y * Display_A2::kGfxPitch + p.x / 7]; -} - -bool Display_A2::getPixelBit(const Common::Point &p) const { - assert(p.x >= 0 && p.x < Display_A2::kGfxWidth && p.y >= 0 && p.y < Display_A2::kGfxHeight); - - byte *b = _frameBuf + p.y * Display_A2::kGfxPitch + p.x / 7; - return *b & (1 << (p.x % 7)); -} - -void Display_A2::clear(byte color) { - byte val = 0; - - byte c = color << 1; - if (c >= 0x40 && c < 0xc0) - val = 0x7f; - - for (uint i = 0; i < Display_A2::kGfxSize; ++i) { - _frameBuf[i] = color; - color ^= val; - } -} - -// FIXME: This does not currently update the surfaces -void Display_A2::printChar(char c) { - if (c == Display_A2::asciiToNative('\r')) - _cursorPos = (_cursorPos / Display_A2::kTextWidth + 1) * Display_A2::kTextWidth; - else if (c == Display_A2::asciiToNative('\a')) { - copyTextSurface(); - static_cast<AdlEngine *>(g_engine)->bell(); - } else if ((byte)c < 0x80 || (byte)c >= 0xa0) { - setCharAtCursor(c); - ++_cursorPos; - } - - if (_cursorPos == Display_A2::kTextWidth * Display_A2::kTextHeight) - scrollUp(); -} - -void Display_A2::showCursor(bool enable) { - _showCursor = enable; -} - -void Display_A2::writeFrameBuffer(const Common::Point &p, byte color, byte mask) { - assert(p.x >= 0 && p.x < Display_A2::kGfxWidth && p.y >= 0 && p.y < Display_A2::kGfxHeight); - - byte *b = _frameBuf + p.y * Display_A2::kGfxPitch + p.x / 7; - color ^= *b; - color &= mask; - *b ^= color; -} - -void Display_A2::showScanlines(bool enable) { - byte pal[COLOR_PALETTE_ENTRIES * 3]; - - g_system->getPaletteManager()->grabPalette(pal, 0, COLOR_PALETTE_ENTRIES); - - if (enable) { - for (uint i = 0; i < ARRAYSIZE(pal); ++i) - pal[i] = pal[i] * (100 - SCANLINE_OPACITY) / 100; - } - - g_system->getPaletteManager()->setPalette(pal, COLOR_PALETTE_ENTRIES, COLOR_PALETTE_ENTRIES); -} static byte processColorBits(uint16 &bits, bool &odd, bool secondPal) { byte color = 0; @@ -395,7 +218,82 @@ static void copyEvenSurfaceRows(Graphics::Surface &surf) { } } -void Display_A2::updateGfxSurface() { +class Display_A2_Monitor : public Display_A2 { +public: + Display_A2_Monitor(); + ~Display_A2_Monitor(); + + enum { + kSplitHeight = 64 + }; + + void init() override; + void renderText() override; + void renderGraphics() override; + +private: + void updateTextSurface(); + void updateGfxSurface(); + void drawChar(byte c, int x, int y); + void createFont(); + void showScanlines(bool enable); + void createSurfaces(uint gfxWidth, uint gfxHeight); + + Graphics::Surface *_textSurface; + Graphics::Surface *_gfxSurface; + Graphics::Surface *_font; + bool _scanlines; + bool _monochrome; +}; + +Display_A2_Monitor::Display_A2_Monitor() : + _textSurface(nullptr), + _gfxSurface(nullptr), + _font(nullptr), + _scanlines(false), + _monochrome(false) { } + +Display_A2_Monitor::~Display_A2_Monitor() { + if (_font) { + _font->free(); + delete _font; + } + + _textSurface->free(); + delete _textSurface; + + _gfxSurface->free(); + delete _gfxSurface; +} + +void Display_A2_Monitor::createSurfaces(uint gfxWidth, uint gfxHeight) { + _gfxSurface = new Graphics::Surface; + _gfxSurface->create(gfxWidth, gfxHeight, Graphics::PixelFormat::createFormatCLUT8()); + _textSurface = new Graphics::Surface; + _textSurface->create(gfxWidth, gfxHeight, Graphics::PixelFormat::createFormatCLUT8()); +} + +void Display_A2_Monitor::init() { + Display_A2::init(); + + // We need 2x scaling to properly render the half-pixel shift + // of the second palette + createSurfaces(Display_A2::kGfxWidth * 2, Display_A2::kGfxHeight * 2); + + _monochrome = !ConfMan.getBool("color"); + _scanlines = ConfMan.getBool("scanlines"); + + if (_monochrome) + g_system->getPaletteManager()->setPalette(monoPalette, 0, MONO_PALETTE_ENTRIES); + else + g_system->getPaletteManager()->setPalette(colorPalette, 0, COLOR_PALETTE_ENTRIES); + + createFont(); + + showScanlines(_scanlines); +} + +void Display_A2_Monitor::updateGfxSurface() { byte *src = _frameBuf; byte *dst = (byte *)_gfxSurface->getPixels(); @@ -411,7 +309,7 @@ void Display_A2::updateGfxSurface() { copyEvenSurfaceRows(*_gfxSurface); } -void Display_A2::updateTextSurface() { +void Display_A2_Monitor::updateTextSurface() { for (uint row = 0; row < 24; ++row) for (uint col = 0; col < Display_A2::kTextWidth; ++col) { uint charPos = row * Display_A2::kTextWidth + col; @@ -424,11 +322,7 @@ void Display_A2::updateTextSurface() { r.translate(((c & 0x3f) % 16) * 7 * 2, (c & 0x3f) / 16 * 8 * 2); if (!(c & 0x80)) { - // Blink text. We subtract _startMillis to make this compatible - // with the event recorder, which returns offsetted values on - // playback. - const uint32 millisPassed = g_system->getMillis() - _startMillis; - if (!(c & 0x40) || ((millisPassed / 270) & 1)) + if (!(c & 0x40) || ((g_system->getMillis() / 270) & 1)) r.translate(0, 4 * 8 * 2); } @@ -436,7 +330,29 @@ void Display_A2::updateTextSurface() { } } -void Display_A2::drawChar(byte c, int x, int y) { +void Display_A2_Monitor::renderText() { + updateTextSurface(); + + if (_mode == Display::kModeText) + g_system->copyRectToScreen(_textSurface->getPixels(), _textSurface->pitch, 0, 0, _textSurface->w, _textSurface->h); + else if (_mode == Display::kModeMixed) + g_system->copyRectToScreen(_textSurface->getBasePtr(0, _textSurface->h - kSplitHeight), _textSurface->pitch, 0, _textSurface->h - kSplitHeight, _textSurface->w, kSplitHeight); + + g_system->updateScreen(); +} + +void Display_A2_Monitor::renderGraphics() { + updateGfxSurface(); + + if (_mode == kModeGraphics) + g_system->copyRectToScreen(_gfxSurface->getPixels(), _gfxSurface->pitch, 0, 0, _gfxSurface->w, _gfxSurface->h); + else if (_mode == kModeMixed) + g_system->copyRectToScreen(_gfxSurface->getPixels(), _gfxSurface->pitch, 0, 0, _gfxSurface->w, _gfxSurface->h - kSplitHeight); + + g_system->updateScreen(); +} + +void Display_A2_Monitor::drawChar(byte c, int x, int y) { byte *buf = (byte *)_font->getPixels() + y * _font->pitch + x; for (uint row = 0; row < 8; ++row) { @@ -451,7 +367,7 @@ void Display_A2::drawChar(byte c, int x, int y) { } } -void Display_A2::createFont() { +void Display_A2_Monitor::createFont() { _font = new Graphics::Surface; _font->create(16 * 7 * 2, 4 * 8 * 2 * 2, Graphics::PixelFormat::createFormatCLUT8()); @@ -474,4 +390,146 @@ void Display_A2::createFont() { copyEvenSurfaceRows(*_font); } +void Display_A2_Monitor::showScanlines(bool enable) { + byte pal[COLOR_PALETTE_ENTRIES * 3]; + + g_system->getPaletteManager()->grabPalette(pal, 0, COLOR_PALETTE_ENTRIES); + + if (enable) { + for (uint i = 0; i < ARRAYSIZE(pal); ++i) + pal[i] = pal[i] * (100 - SCANLINE_OPACITY) / 100; + } + + g_system->getPaletteManager()->setPalette(pal, COLOR_PALETTE_ENTRIES, COLOR_PALETTE_ENTRIES); +} + +Display_A2::Display_A2() : _frameBuf(nullptr), _showCursor(false) { + initGraphics(Display_A2::kGfxWidth * 2, Display_A2::kGfxHeight * 2); +} + +Display_A2::~Display_A2() { + delete[] _frameBuf; +} + +void Display_A2::init() { + createTextBuffer(Display_A2::kTextWidth, Display_A2::kTextHeight); + + _frameBuf = new byte[Display_A2::kGfxSize]; + memset(_frameBuf, 0, Display_A2::kGfxSize); +} + +void Display_A2::loadFrameBuffer(Common::ReadStream &stream, byte *dst) { + for (uint j = 0; j < 8; ++j) { + for (uint i = 0; i < 8; ++i) { + stream.read(dst, Display_A2::kGfxPitch); + dst += Display_A2::kGfxPitch * 64; + stream.read(dst, Display_A2::kGfxPitch); + dst += Display_A2::kGfxPitch * 64; + stream.read(dst, Display_A2::kGfxPitch); + stream.readUint32LE(); + stream.readUint32LE(); + dst -= Display_A2::kGfxPitch * 120; + } + dst -= Display_A2::kGfxPitch * 63; + } + + if (stream.eos() || stream.err()) + error("Failed to read frame buffer"); +} + +void Display_A2::loadFrameBuffer(Common::ReadStream &stream) { + loadFrameBuffer(stream, _frameBuf); +} + +void Display_A2::putPixel(const Common::Point &p, byte color) { + byte offset = p.x / 7; + byte mask = 0x80 | (1 << (p.x % 7)); + + // Since white and black are in both palettes, we leave + // the palette bit alone + if ((color & 0x7f) == 0x7f || (color & 0x7f) == 0) + mask &= 0x7f; + + // Adjust colors starting with bits '01' or '10' for + // odd offsets + if (offset & 1) { + byte c = color << 1; + if (c >= 0x40 && c < 0xc0) + color ^= 0x7f; + } + + writeFrameBuffer(p, color, mask); +} + +void Display_A2::setPixelByte(const Common::Point &p, byte color) { + assert(p.x >= 0 && p.x < Display_A2::kGfxWidth && p.y >= 0 && p.y < Display_A2::kGfxHeight); + + _frameBuf[p.y * Display_A2::kGfxPitch + p.x / 7] = color; +} + +void Display_A2::setPixelBit(const Common::Point &p, byte color) { + writeFrameBuffer(p, color, 1 << (p.x % 7)); +} + +void Display_A2::setPixelPalette(const Common::Point &p, byte color) { + writeFrameBuffer(p, color, 0x80); +} + +byte Display_A2::getPixelByte(const Common::Point &p) const { + assert(p.x >= 0 && p.x < Display_A2::kGfxWidth && p.y >= 0 && p.y < Display_A2::kGfxHeight); + + return _frameBuf[p.y * Display_A2::kGfxPitch + p.x / 7]; +} + +bool Display_A2::getPixelBit(const Common::Point &p) const { + assert(p.x >= 0 && p.x < Display_A2::kGfxWidth && p.y >= 0 && p.y < Display_A2::kGfxHeight); + + byte *b = _frameBuf + p.y * Display_A2::kGfxPitch + p.x / 7; + return *b & (1 << (p.x % 7)); +} + +void Display_A2::clear(byte color) { + byte val = 0; + + byte c = color << 1; + if (c >= 0x40 && c < 0xc0) + val = 0x7f; + + for (uint i = 0; i < Display_A2::kGfxSize; ++i) { + _frameBuf[i] = color; + color ^= val; + } +} + +// FIXME: This does not currently update the surfaces +void Display_A2::printChar(char c) { + if (c == Display_A2::asciiToNative('\r')) + _cursorPos = (_cursorPos / Display_A2::kTextWidth + 1) * Display_A2::kTextWidth; + else if (c == Display_A2::asciiToNative('\a')) { + renderText(); + static_cast<AdlEngine *>(g_engine)->bell(); + } else if ((byte)c < 0x80 || (byte)c >= 0xa0) { + setCharAtCursor(c); + ++_cursorPos; + } + + if (_cursorPos == Display_A2::kTextWidth * Display_A2::kTextHeight) + scrollUp(); +} + +void Display_A2::showCursor(bool enable) { + _showCursor = enable; +} + +void Display_A2::writeFrameBuffer(const Common::Point &p, byte color, byte mask) { + assert(p.x >= 0 && p.x < Display_A2::kGfxWidth && p.y >= 0 && p.y < Display_A2::kGfxHeight); + + byte *b = _frameBuf + p.y * Display_A2::kGfxPitch + p.x / 7; + color ^= *b; + color &= mask; + *b ^= color; +} + +Display_A2 *Display_A2_create() { return new Display_A2_Monitor(); } + } // End of namespace Adl |