From c8ab2909c67703ad1255aa27159049f058d1a361 Mon Sep 17 00:00:00 2001 From: Walter van Niftrik Date: Fri, 26 Feb 2016 23:32:06 +0100 Subject: ADL: Initial check-in for ADL engine --- engines/adl/display.cpp | 611 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 611 insertions(+) create mode 100644 engines/adl/display.cpp (limited to 'engines/adl/display.cpp') diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp new file mode 100644 index 0000000000..02b8d51b7f --- /dev/null +++ b/engines/adl/display.cpp @@ -0,0 +1,611 @@ +/* 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 2 + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "adl/display.h" +#include "common/stream.h" +#include "common/rect.h" +#include "graphics/surface.h" +#include "common/system.h" +#include "common/str.h" +#include "common/events.h" +#include "common/rect.h" +#include "common/array.h" +#include "engines/engine.h" + +namespace Adl { + +static byte font[64][5] = { + { 0x7c, 0x82, 0xba, 0xb2, 0x9c }, { 0xf8, 0x24, 0x22, 0x24, 0xf8 }, // @A + { 0xfe, 0x92, 0x92, 0x92, 0x6c }, { 0x7c, 0x82, 0x82, 0x82, 0x44 }, // BC + { 0xfe, 0x82, 0x82, 0x82, 0x7c }, { 0xfe, 0x92, 0x92, 0x92, 0x82 }, // DE + { 0xfe, 0x12, 0x12, 0x12, 0x02 }, { 0x7c, 0x82, 0x82, 0xa2, 0xe2 }, // FG + { 0xfe, 0x10, 0x10, 0x10, 0xfe }, { 0x00, 0x82, 0xfe, 0x82, 0x00 }, // HI + { 0x40, 0x80, 0x80, 0x80, 0x7e }, { 0xfe, 0x10, 0x28, 0x44, 0x82 }, // JK + { 0xfe, 0x80, 0x80, 0x80, 0x80 }, { 0xfe, 0x04, 0x18, 0x04, 0xfe }, // LM + { 0xfe, 0x08, 0x10, 0x20, 0xfe }, { 0x7c, 0x82, 0x82, 0x82, 0x7c }, // NO + { 0xfe, 0x12, 0x12, 0x12, 0x0c }, { 0x7c, 0x82, 0xa2, 0x42, 0xbc }, // PQ + { 0xfe, 0x12, 0x32, 0x52, 0x8c }, { 0x4c, 0x92, 0x92, 0x92, 0x64 }, // RS + { 0x02, 0x02, 0xfe, 0x02, 0x02 }, { 0x7e, 0x80, 0x80, 0x80, 0x7e }, // TU + { 0x3e, 0x40, 0x80, 0x40, 0x3e }, { 0xfe, 0x40, 0x30, 0x40, 0xfe }, // VW + { 0xc6, 0x28, 0x10, 0x28, 0xc6 }, { 0x06, 0x08, 0xf0, 0x08, 0x06 }, // XY + { 0xc2, 0xa2, 0x92, 0x8a, 0x86 }, { 0xfe, 0xfe, 0x82, 0x82, 0x82 }, // Z[ + { 0x04, 0x08, 0x10, 0x20, 0x40 }, { 0x82, 0x82, 0x82, 0xfe, 0xfe }, // \] + { 0x20, 0x10, 0x08, 0x10, 0x20 }, { 0x80, 0x80, 0x80, 0x80, 0x80 }, // ^_ + { 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0xbe, 0x00, 0x00 }, // ! + { 0x00, 0x0e, 0x00, 0x0e, 0x00 }, { 0x28, 0xfe, 0x28, 0xfe, 0x28 }, // "# + { 0x48, 0x54, 0xfe, 0x54, 0x24 }, { 0x46, 0x26, 0x10, 0xc8, 0xc4 }, // $% + { 0x6c, 0x92, 0xac, 0x40, 0xa0 }, { 0x00, 0x00, 0x0e, 0x00, 0x00 }, // &' + { 0x38, 0x44, 0x82, 0x00, 0x00 }, { 0x00, 0x00, 0x82, 0x44, 0x38 }, // () + { 0x44, 0x28, 0xfe, 0x28, 0x44 }, { 0x10, 0x10, 0x7c, 0x10, 0x10 }, // *+ + { 0x00, 0x80, 0x60, 0x00, 0x00 }, { 0x10, 0x10, 0x10, 0x10, 0x10 }, // ,- + { 0x00, 0x00, 0x80, 0x00, 0x00 }, { 0x40, 0x20, 0x10, 0x08, 0x04 }, // ./ + { 0x7c, 0xa2, 0x92, 0x8a, 0x7c }, { 0x00, 0x84, 0xfe, 0x80, 0x00 }, // 01 + { 0xc4, 0xa2, 0x92, 0x92, 0x8c }, { 0x42, 0x82, 0x92, 0x9a, 0x66 }, // 23 + { 0x30, 0x28, 0x24, 0xfe, 0x20 }, { 0x4e, 0x8a, 0x8a, 0x8a, 0x72 }, // 45 + { 0x78, 0x94, 0x92, 0x92, 0x62 }, { 0x02, 0xe2, 0x12, 0x0a, 0x06 }, // 67 + { 0x6c, 0x92, 0x92, 0x92, 0x6c }, { 0x8c, 0x92, 0x92, 0x52, 0x3c }, // 89 + { 0x00, 0x00, 0x28, 0x00, 0x00 }, { 0x00, 0x80, 0x68, 0x00, 0x00 }, // :; + { 0x10, 0x28, 0x44, 0x82, 0x00 }, { 0x28, 0x28, 0x28, 0x28, 0x28 }, // <= + { 0x00, 0x82, 0x44, 0x28, 0x10 }, { 0x04, 0x02, 0xb2, 0x0a, 0x04 } // >? +}; + +Display::Display() : + _scanlines(false), + _cursorPos(0), + _mode(kModeText) { + _frameBuf = new byte[kFrameBufSize]; + _frameBufSurface = new Graphics::Surface; + _frameBufSurface->create(kWidth * 2, kHeight * 2, Graphics::PixelFormat::createFormatCLUT8()); + + _textBuf = new byte[kTextBufSize]; + memset(_textBuf, ' ' | 0x80, kTextBufSize); + _textBufSurface = new Graphics::Surface; + _textBufSurface->create(kWidth * 2, kHeight * 2, Graphics::PixelFormat::createFormatCLUT8()); + + createFont(); + + struct PixelPos rel = getPixelPos(0, 191); + struct PixelPos absy; + for (int i = 191; i >= 0; --i) { + absy = getPixelPos(0, i); + if (absy.rowAddr != rel.rowAddr) + debug("%i: %04x %04x", i, absy.rowAddr, rel.rowAddr); + moveY(rel, false); + } + absy = getPixelPos(0, 191); + if (absy.rowAddr != rel.rowAddr) + debug("%i: %04x %04x", 191, absy.rowAddr, rel.rowAddr); + + rel = getPixelPos(0, 0); + for (int i = 0; i < 192; ++i) { + absy = getPixelPos(0, i); + if (absy.rowAddr != rel.rowAddr) + debug("%i: %04x %04x", i, absy.rowAddr, rel.rowAddr); + moveY(rel, true); + } + absy = getPixelPos(0, 0); + if (absy.rowAddr != rel.rowAddr) + debug("%i: %04x %04x", 191, absy.rowAddr, rel.rowAddr); +} + +Display::~Display() { + delete[] _frameBuf; + _frameBufSurface->free(); + delete _frameBufSurface; + + delete[] _textBuf; + _textBufSurface->free(); + delete _textBufSurface; + + _font->free(); + delete _font; +} + +void Display::loadFrameBuffer(Common::ReadStream &stream) { + stream.read(_frameBuf, kFrameBufSize); +} + +void Display::decodeScanline(byte *dst, int pitch, byte *src) { + // TODO: shift secondPal by half a pixel + + bool prevOn = false; + + for (uint j = 0; j < 39; ++j) { + bool secondPal = src[j] & 0x80; + byte cur = src[j]; + byte next = 0; + if (j != 39) + next = src[j + 1]; + + for (uint k = 0; k < 7; ++k) { + bool curOn = cur & (1 << k); + bool nextOn; + + if (k != 6) + nextOn = cur & (1 << (k + 1)); + else + nextOn = next & 1; + + byte color; + if (curOn == prevOn || curOn == nextOn) + color = curOn ? 1 : 0; + else { + if (secondPal) + color = (curOn == ((j + k) % 2) ? 5 : 4); + else + color = (curOn == ((j + k) % 2) ? 3 : 2); + } + + dst[0] = color; + dst[1] = color; + + if (!_scanlines) { + dst[pitch] = color; + dst[pitch + 1] = color; + } + + dst += 2; + prevOn = curOn; + } + } +} + +Display::PixelPos Display::getPixelPos(byte x, byte y) { + PixelPos pixelPos; + + // FIXME: check X, Y range + + byte offsetL = y & 0xc0; + offsetL |= offsetL >> 2; + byte offsetH = y; + y <<= 2; + offsetH <<= 1; + offsetH |= y >> 7; + y <<= 1; + offsetH <<= 1; + offsetH |= y >> 7; + y <<= 1; + offsetL >>= 1; + offsetL |= y & 0x80; + y <<= 1; + offsetH = offsetH & 0x1f; + pixelPos.rowAddr = (offsetH << 8) | offsetL; + pixelPos.byteOffset = x / 7; + pixelPos.bitMask = 0x80 | (1 << x % 7); + + return pixelPos; +} + +byte Display::getPixelColor(byte offset, byte color) { + if (offset & 1) { + byte c = color << 1; + if (c >= 0x40 && c < 0xc0) + return color ^ 0x7f; + } + + return color; +} + +void Display::decodeFrameBuffer() { + byte *src = _frameBuf; + int pitch = _frameBufSurface->pitch; + for (int j = 0; j < 8; ++j) { + for (int i = 0; i < 8; ++i) { + byte *dst = (byte *)_frameBufSurface->getPixels() + pitch * 2 * (i * 8 + j); + decodeScanline(dst, pitch, src); + src += 40; + dst += pitch * 2 * 64; + decodeScanline(dst, pitch, src); + src += 40; + dst += pitch * 2 * 64; + decodeScanline(dst, pitch, src); + src += 48; + dst += pitch * 2 * 64; + } + } +} + +void Display::drawPixel(byte x, byte y, byte color) { + PixelPos p = getPixelPos(x, y); + byte c = getPixelColor(p.byteOffset, color); + byte *b = _frameBuf + p.rowAddr + p.byteOffset; + c ^= *b; + c &= p.bitMask; + c ^= *b; + *b = c; +} + +void Display::moveX(PixelPos &p, byte &color, bool left) { + if (left) { + byte bit = p.bitMask; + bool b = bit & 1; + bit >>= 1; + if (!b) { + bit ^= 0xc0; + p.bitMask = bit; + return; + } + --p.byteOffset; + if (p.byteOffset & 0x80) + p.byteOffset = 39; + p.bitMask = 0xc0; + } else { + byte bit = p.bitMask; + bit <<= 1; + bit ^= 0x80; + if (bit & 0x80) { + p.bitMask = bit; + return; + } + p.bitMask = 0x81; + ++p.byteOffset; + if (p.byteOffset == 40) + p.byteOffset = 0; + } + + color = getPixelColor(p.byteOffset, color); +} + +void Display::moveY(PixelPos &p, bool down) { + if (!down) { + if (p.rowAddr & 0x1c00) + p.rowAddr -= 0x400; + else if (p.rowAddr & 0x380) + p.rowAddr += 0x1b80; + else { + p.rowAddr += 0x1f58; + if (!(p.rowAddr & 0x80)) + p.rowAddr += 0x78; // Wrap around + } + } else { + p.rowAddr += 0x400; + if (p.rowAddr & 0x1c00) + return; + else if ((p.rowAddr & 0x380) != 0x380) + p.rowAddr -= 0x1f80; + else { + p.rowAddr -= 0x2358; + if ((p.rowAddr & 0x78) == 0x78) + p.rowAddr -= 0x78; // Wrap around + } + } +} + +void Display::drawNextPixel(Display::PixelPos &p, byte &color, byte bits, byte quadrant) { + if (bits & 4) { + byte b = (_frameBuf[p.rowAddr + p.byteOffset] ^ color) & p.bitMask; + _frameBuf[p.rowAddr + p.byteOffset] ^= b; + } + + bits += quadrant; + + if (bits & 1) + moveX(p, color, bits & 2); + else + moveY(p, bits & 2); +} + +void Display::drawRightAngles(Common::Array &rightAngles, Common::Point p, byte rotation, byte scaling, byte color) { + const byte stepping[] = { + 0xff, 0xfe, 0xfa, 0xf4, 0xec, 0xe1, 0xd4, 0xc5, + 0xb4, 0xa1, 0x8d, 0x78, 0x61, 0x49, 0x31, 0x18, + 0xff + }; + + PixelPos pos = getPixelPos(p.x, p.y); + byte c = getPixelColor(pos.byteOffset, color); + + byte quadrant = rotation >> 4; + rotation &= 0xf; + byte xStep = stepping[rotation]; + byte yStep = stepping[(rotation ^ 0xf) + 1] + 1; + + for (uint i = 0; i < rightAngles.size(); ++i) { + byte b = rightAngles[i]; + + do { + byte xFrac = 0x80; + byte yFrac = 0x80; + for (uint j = 0; j < scaling; ++j) { + if (xFrac + xStep + 1 > 255) + drawNextPixel(pos, c, b, quadrant); + xFrac += xStep + 1; + if (yFrac + yStep > 255) + drawNextPixel(pos, c, b, quadrant + 1); + yFrac += yStep; + } + b >>= 3; + } while (b != 0); + } +} + +void Display::drawLine(Common::Point p1, Common::Point p2, byte color) { + PixelPos p = getPixelPos(p1.x, p1.y); + byte c = getPixelColor(p.byteOffset, color); + + int16 deltaX = p2.x - p1.x; + byte dir = deltaX >> 8; + + if (deltaX < 0) + deltaX = -deltaX; + + int16 err = deltaX; + + int16 deltaY = p2.y - p1.y - 1; + dir >>= 1; + if (deltaY >= 0) { + deltaY = -deltaY - 2; + dir |= 0x80; + } + + int16 steps = deltaY - deltaX; + + err += deltaY + 1; + + while (1) { + byte *b = _frameBuf + p.rowAddr + p.byteOffset; + byte d = *b; + d ^= c; + d &= p.bitMask; + d ^= *b; + *b = d; + + if (++steps == 0) + return; + + if (err < 0) { + moveY(p, dir & 0x80); + err += deltaX; + } else { + moveX(p, c, dir & 0x40); + err += deltaY + 1; + } + } +} + +void Display::clear(byte color) { + for (uint i = 0; i < kFrameBufSize; ++i) + _frameBuf[i] = getPixelColor(i & 1, color); +} + +void Display::updateTextSurface() { + for (uint row = 0; row < 24; ++row) + for (uint col = 0; col < 40; ++col) { + char c = _textBuf[row * 40 + col]; + + Common::Rect r(7 * 2, 8 * 2); + r.translate(((c & 0x3f) % 16) * 7 * 2, (c & 0x3f) / 16 * 8 * 2); + + if (!(c & 0x80)) { + if (!(c & 0x40) || ((g_system->getMillis() / 270) & 1)) + r.translate(0, 4 * 8 * 2); + } + + _textBufSurface->copyRectToSurface(*_font, col * 7 * 2, row * 8 * 2, r); + } +} + +void Display::printString(const Common::String &str) { + Common::String::const_iterator it; + for (it = str.begin(); it != str.end(); ++it) { + byte b = *it; + + if (b == ('\r' | 0x80)) + _cursorPos = (_cursorPos / 40 + 1) * 40; + else if (b < 0x80 || b >= 0xa0) + _textBuf[_cursorPos++] = b; + + if (_cursorPos == kTextBufSize) { + memmove(_textBuf, _textBuf + 40, kTextBufSize - 40); + memset(_textBuf + kTextBufSize - 40, ' ' | 0x80, 40); + _cursorPos -= 40; + } + } + + updateTextSurface(); +} + +void Display::printASCIIString(const Common::String &str) { + Common::String aStr; + + Common::String::const_iterator it; + for (it = str.begin(); it != str.end(); ++it) + aStr += *it | 0x80; + + printString(aStr); +} + +void Display::drawChar(byte c, int x, int y) { + byte *buf = (byte *)_font->getPixels() + y * _font->pitch + x; + + for (uint row = 0; row < 8; ++row) { + for (uint col = 1; col < 6; ++col) + if (font[c][col - 1] & (1 << row)) { + buf[col * 2] = 1; + buf[col * 2 + 1] = 1; + + if (!_scanlines) { + buf[_font->pitch + col * 2] = 1; + buf[_font->pitch + col * 2 + 1] = 1; + } + } + + buf += 2 * _font->pitch; + } +} + +void Display::createFont() { + _font = new Graphics::Surface; + _font->create(16 * 7 * 2, 4 * 8 * 2 * 2, Graphics::PixelFormat::createFormatCLUT8()); + + for (uint i = 0; i < 4; ++i) + for (uint j = 0; j < 16; ++j) + drawChar(i * 16 + j, j * 7 * 2, i * 8 * 2); + + // Create inverted font + byte *buf = (byte *)_font->getPixels(); + byte *bufInv = buf + (_font->h / 2) * _font->pitch; + + for (uint row = 0; row < _font->h / 2; ++row) { + if (!_scanlines || !(row & 1)) + for (uint col = 0; col < _font->w; ++col) + bufInv[col] = buf[col] ? 0 : 1; + + buf += _font->pitch; + bufInv += _font->pitch; + } +} + +void Display::updateScreen() { + if (_mode == kModeText) { + g_system->copyRectToScreen(_textBufSurface->getPixels(), _textBufSurface->pitch, 0, 0, _textBufSurface->w, _textBufSurface->h); + } else if (_mode == kModeHires) { + g_system->copyRectToScreen(_frameBufSurface->getPixels(), _frameBufSurface->pitch, 0, 0, _frameBufSurface->w, _frameBufSurface->h); + } else { + g_system->copyRectToScreen(_frameBufSurface->getPixels(), _frameBufSurface->pitch, 0, 0, _frameBufSurface->w, _frameBufSurface->h - 4 * 8 * 2); + g_system->copyRectToScreen(_textBufSurface->getBasePtr(0, _textBufSurface->h - 4 * 8 * 2), _textBufSurface->pitch, 0, _textBufSurface->h - 4 * 8 * 2, _textBufSurface->w, 4 * 8 * 2); + } +} + +Common::String Display::inputString(byte prompt) { + Common::String s; + + if (prompt > 0) + printString(Common::String(prompt)); + + while (1) { + byte b = inputKey(); + + if (g_engine->shouldQuit()) + return 0; + + if (b == 0) + continue; + + if (b == ('\r' | 0x80)) { + s += b; + printString(Common::String(b)); + return s; + } + + if (b < 0xa0) { + switch (b) { + case Common::KEYCODE_BACKSPACE | 0x80: + if (!s.empty()) { + --_cursorPos; + _textBuf[_cursorPos] = ' ' | 0x80; + s.deleteLastChar(); + } + break; + }; + } else { + s += b; + printString(Common::String(b)); + } + } +} + +byte Display::convertKey(uint16 ascii) { + ascii = toupper(ascii); + + if (ascii >= 0x80) + return 0; + + ascii |= 0x80; + + if (ascii >= 0x80 && ascii <= 0xe0) + return ascii; + + return 0; +} + +byte Display::inputKey() { + Common::EventManager *ev = g_system->getEventManager(); + + byte orgChar = _textBuf[_cursorPos]; + _textBuf[_cursorPos] = (orgChar & 0x3f) | 0x40; + + byte key = 0; + + while (!g_engine->shouldQuit() && key == 0) { + Common::Event event; + if (ev->pollEvent(event)) { + if (event.type != Common::EVENT_KEYDOWN) + continue; + + if (event.kbd.flags & Common::KBD_CTRL) { + if (event.kbd.keycode == Common::KEYCODE_q) + g_engine->quitGame(); + continue; + } + + switch (event.kbd.keycode) { + case Common::KEYCODE_BACKSPACE: + case Common::KEYCODE_RETURN: + key = convertKey(event.kbd.keycode); + break; + default: + if (event.kbd.ascii >= 0x20 && event.kbd.ascii < 0x80) + key = convertKey(event.kbd.ascii); + }; + } + + updateTextSurface(); + updateScreen(); + g_system->updateScreen(); + g_system->delayMillis(16); + } + + _textBuf[_cursorPos] = orgChar; + return key; +} + +void Display::delay(uint32 ms) { + Common::EventManager *ev = g_system->getEventManager(); + + uint32 start = g_system->getMillis(); + + while (!g_engine->shouldQuit() && g_system->getMillis() - start < ms) { + Common::Event event; + if (ev->pollEvent(event)) { + if (event.type == Common::EVENT_KEYDOWN && (event.kbd.flags & Common::KBD_CTRL)) { + switch(event.kbd.keycode) { + case Common::KEYCODE_q: + g_engine->quitGame(); + break; + default: + break; + } + } + } + updateScreen(); + g_system->updateScreen(); + g_system->delayMillis(16); + } +} + +void Display::home() { + memset(_textBuf, ' ' | 0x80, kTextBufSize); + _cursorPos = 0; +} + +} // End of namespace Adl -- cgit v1.2.3 From 9717aa956197480a608622a2e294fa8302258a0e Mon Sep 17 00:00:00 2001 From: Walter van Niftrik Date: Sat, 27 Feb 2016 13:35:49 +0100 Subject: ADL: Clean-up string handling --- engines/adl/display.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines/adl/display.cpp') diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp index 02b8d51b7f..47b1533582 100644 --- a/engines/adl/display.cpp +++ b/engines/adl/display.cpp @@ -429,7 +429,7 @@ void Display::printASCIIString(const Common::String &str) { Common::String::const_iterator it; for (it = str.begin(); it != str.end(); ++it) - aStr += *it | 0x80; + aStr += APPLECHAR(*it); printString(aStr); } -- cgit v1.2.3 From 1abaf60cf04c5bc2bf8a3fb37aa8dd83816a7771 Mon Sep 17 00:00:00 2001 From: Walter van Niftrik Date: Sun, 28 Feb 2016 17:21:09 +0100 Subject: ADL: Rename rightAngles to lineArt --- engines/adl/display.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'engines/adl/display.cpp') diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp index 47b1533582..8ea0a7bcba 100644 --- a/engines/adl/display.cpp +++ b/engines/adl/display.cpp @@ -304,7 +304,7 @@ void Display::drawNextPixel(Display::PixelPos &p, byte &color, byte bits, byte q moveY(p, bits & 2); } -void Display::drawRightAngles(Common::Array &rightAngles, Common::Point p, byte rotation, byte scaling, byte color) { +void Display::drawLineArt(const Common::Array &lineArt, Common::Point p, byte rotation, byte scaling, byte color) { const byte stepping[] = { 0xff, 0xfe, 0xfa, 0xf4, 0xec, 0xe1, 0xd4, 0xc5, 0xb4, 0xa1, 0x8d, 0x78, 0x61, 0x49, 0x31, 0x18, @@ -319,8 +319,8 @@ void Display::drawRightAngles(Common::Array &rightAngles, Common::Point p, byte xStep = stepping[rotation]; byte yStep = stepping[(rotation ^ 0xf) + 1] + 1; - for (uint i = 0; i < rightAngles.size(); ++i) { - byte b = rightAngles[i]; + for (uint i = 0; i < lineArt.size(); ++i) { + byte b = lineArt[i]; do { byte xFrac = 0x80; -- cgit v1.2.3 From 301b2fdc219ecc92cc81cc94d8e2904fc21cec6e Mon Sep 17 00:00:00 2001 From: Walter van Niftrik Date: Sun, 28 Feb 2016 21:04:21 +0100 Subject: ADL: Remove leftover debug code --- engines/adl/display.cpp | 23 ----------------------- 1 file changed, 23 deletions(-) (limited to 'engines/adl/display.cpp') diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp index 8ea0a7bcba..05e7c2e67c 100644 --- a/engines/adl/display.cpp +++ b/engines/adl/display.cpp @@ -82,29 +82,6 @@ Display::Display() : _textBufSurface->create(kWidth * 2, kHeight * 2, Graphics::PixelFormat::createFormatCLUT8()); createFont(); - - struct PixelPos rel = getPixelPos(0, 191); - struct PixelPos absy; - for (int i = 191; i >= 0; --i) { - absy = getPixelPos(0, i); - if (absy.rowAddr != rel.rowAddr) - debug("%i: %04x %04x", i, absy.rowAddr, rel.rowAddr); - moveY(rel, false); - } - absy = getPixelPos(0, 191); - if (absy.rowAddr != rel.rowAddr) - debug("%i: %04x %04x", 191, absy.rowAddr, rel.rowAddr); - - rel = getPixelPos(0, 0); - for (int i = 0; i < 192; ++i) { - absy = getPixelPos(0, i); - if (absy.rowAddr != rel.rowAddr) - debug("%i: %04x %04x", i, absy.rowAddr, rel.rowAddr); - moveY(rel, true); - } - absy = getPixelPos(0, 0); - if (absy.rowAddr != rel.rowAddr) - debug("%i: %04x %04x", 191, absy.rowAddr, rel.rowAddr); } Display::~Display() { -- cgit v1.2.3 From ba54955bffec15ed95aa1ca1ec955aecaa315478 Mon Sep 17 00:00:00 2001 From: Walter van Niftrik Date: Mon, 29 Feb 2016 16:50:24 +0100 Subject: ADL: Add loading from launcher --- engines/adl/display.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'engines/adl/display.cpp') diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp index 05e7c2e67c..ffb98c4a1b 100644 --- a/engines/adl/display.cpp +++ b/engines/adl/display.cpp @@ -585,4 +585,8 @@ void Display::home() { _cursorPos = 0; } +void Display::setCursorPos(Common::Point pos) { + _cursorPos = pos.y * 40 + pos.x; +} + } // End of namespace Adl -- cgit v1.2.3 From 339d3bc86813b454447b02481f82b85c4c8be75b Mon Sep 17 00:00:00 2001 From: Walter van Niftrik Date: Tue, 1 Mar 2016 15:47:34 +0100 Subject: ADL: Move input code into AdlEngine --- engines/adl/display.cpp | 178 ++++++++++++------------------------------------ 1 file changed, 45 insertions(+), 133 deletions(-) (limited to 'engines/adl/display.cpp') diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp index ffb98c4a1b..a6d94f6e13 100644 --- a/engines/adl/display.cpp +++ b/engines/adl/display.cpp @@ -71,7 +71,8 @@ static byte font[64][5] = { Display::Display() : _scanlines(false), _cursorPos(0), - _mode(kModeText) { + _mode(kModeText), + _showCursor(false) { _frameBuf = new byte[kFrameBufSize]; _frameBufSurface = new Graphics::Surface; _frameBufSurface->create(kWidth * 2, kHeight * 2, Graphics::PixelFormat::createFormatCLUT8()); @@ -367,8 +368,12 @@ void Display::clear(byte color) { void Display::updateTextSurface() { for (uint row = 0; row < 24; ++row) for (uint col = 0; col < 40; ++col) { + int charPos = row * 40 + col; char c = _textBuf[row * 40 + col]; + if (charPos == _cursorPos && _showCursor) + c = (c & 0x3f) | 0x40; + Common::Rect r(7 * 2, 8 * 2); r.translate(((c & 0x3f) % 16) * 7 * 2, (c & 0x3f) / 16 * 8 * 2); @@ -381,36 +386,6 @@ void Display::updateTextSurface() { } } -void Display::printString(const Common::String &str) { - Common::String::const_iterator it; - for (it = str.begin(); it != str.end(); ++it) { - byte b = *it; - - if (b == ('\r' | 0x80)) - _cursorPos = (_cursorPos / 40 + 1) * 40; - else if (b < 0x80 || b >= 0xa0) - _textBuf[_cursorPos++] = b; - - if (_cursorPos == kTextBufSize) { - memmove(_textBuf, _textBuf + 40, kTextBufSize - 40); - memset(_textBuf + kTextBufSize - 40, ' ' | 0x80, 40); - _cursorPos -= 40; - } - } - - updateTextSurface(); -} - -void Display::printASCIIString(const Common::String &str) { - Common::String aStr; - - Common::String::const_iterator it; - for (it = str.begin(); it != str.end(); ++it) - aStr += APPLECHAR(*it); - - printString(aStr); -} - void Display::drawChar(byte c, int x, int y) { byte *buf = (byte *)_font->getPixels() + y * _font->pitch + x; @@ -463,126 +438,63 @@ void Display::updateScreen() { } } -Common::String Display::inputString(byte prompt) { - Common::String s; - - if (prompt > 0) - printString(Common::String(prompt)); - - while (1) { - byte b = inputKey(); - - if (g_engine->shouldQuit()) - return 0; - - if (b == 0) - continue; - - if (b == ('\r' | 0x80)) { - s += b; - printString(Common::String(b)); - return s; - } - - if (b < 0xa0) { - switch (b) { - case Common::KEYCODE_BACKSPACE | 0x80: - if (!s.empty()) { - --_cursorPos; - _textBuf[_cursorPos] = ' ' | 0x80; - s.deleteLastChar(); - } - break; - }; - } else { - s += b; - printString(Common::String(b)); - } - } +void Display::home() { + memset(_textBuf, APPLECHAR(' '), kTextBufSize); + _cursorPos = 0; } -byte Display::convertKey(uint16 ascii) { - ascii = toupper(ascii); - - if (ascii >= 0x80) - return 0; +void Display::moveCursorForward() { + ++_cursorPos; - ascii |= 0x80; + if (_cursorPos >= kTextBufSize) + scrollUp(); +} - if (ascii >= 0x80 && ascii <= 0xe0) - return ascii; +void Display::moveCursorBackward() { + --_cursorPos; - return 0; + if (_cursorPos < 0) + _cursorPos = 0; } -byte Display::inputKey() { - Common::EventManager *ev = g_system->getEventManager(); +void Display::moveCursorTo(const Common::Point &pos) { + _cursorPos = pos.y * 40 + pos.x; - byte orgChar = _textBuf[_cursorPos]; - _textBuf[_cursorPos] = (orgChar & 0x3f) | 0x40; + if (_cursorPos >= kTextBufSize) + error("Cursor position (%i, %i) out of bounds", pos.x, pos.y); +} - byte key = 0; +void Display::setCharAtCursor(byte c) { + _textBuf[_cursorPos] = c; +} - while (!g_engine->shouldQuit() && key == 0) { - Common::Event event; - if (ev->pollEvent(event)) { - if (event.type != Common::EVENT_KEYDOWN) - continue; +void Display::scrollUp() { + memmove(_textBuf, _textBuf + 40, kTextBufSize - 40); + memset(_textBuf + kTextBufSize - 40, ' ' | 0x80, 40); + _cursorPos -= 40; +} - if (event.kbd.flags & Common::KBD_CTRL) { - if (event.kbd.keycode == Common::KEYCODE_q) - g_engine->quitGame(); - continue; - } +void Display::printString(const Common::String &str) { + Common::String::const_iterator c; + for (c = str.begin(); c != str.end(); ++c) { + byte b = *c; - switch (event.kbd.keycode) { - case Common::KEYCODE_BACKSPACE: - case Common::KEYCODE_RETURN: - key = convertKey(event.kbd.keycode); - break; - default: - if (event.kbd.ascii >= 0x20 && event.kbd.ascii < 0x80) - key = convertKey(event.kbd.ascii); - }; + if (*c == APPLECHAR('\r')) + _cursorPos = (_cursorPos / 40 + 1) * 40; + else if (b < 0x80 || b >= 0xa0) { + setCharAtCursor(b); + ++_cursorPos; } - updateTextSurface(); - updateScreen(); - g_system->updateScreen(); - g_system->delayMillis(16); + if (_cursorPos == kTextBufSize) + scrollUp(); } - _textBuf[_cursorPos] = orgChar; - return key; -} - -void Display::delay(uint32 ms) { - Common::EventManager *ev = g_system->getEventManager(); - - uint32 start = g_system->getMillis(); - - while (!g_engine->shouldQuit() && g_system->getMillis() - start < ms) { - Common::Event event; - if (ev->pollEvent(event)) { - if (event.type == Common::EVENT_KEYDOWN && (event.kbd.flags & Common::KBD_CTRL)) { - switch(event.kbd.keycode) { - case Common::KEYCODE_q: - g_engine->quitGame(); - break; - default: - break; - } - } - } - updateScreen(); - g_system->updateScreen(); - g_system->delayMillis(16); - } + updateTextSurface(); } -void Display::home() { - memset(_textBuf, ' ' | 0x80, kTextBufSize); - _cursorPos = 0; +void Display::showCursor(bool enable) { + _showCursor = enable; } void Display::setCursorPos(Common::Point pos) { -- cgit v1.2.3 From 912a31fa652c389b14e3d77998736813e3b621d0 Mon Sep 17 00:00:00 2001 From: Walter van Niftrik Date: Thu, 3 Mar 2016 13:43:26 +0100 Subject: ADL: Add monochrome and scanline rendering --- engines/adl/display.cpp | 108 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 90 insertions(+), 18 deletions(-) (limited to 'engines/adl/display.cpp') diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp index a6d94f6e13..ade05ab06d 100644 --- a/engines/adl/display.cpp +++ b/engines/adl/display.cpp @@ -29,11 +29,14 @@ #include "common/events.h" #include "common/rect.h" #include "common/array.h" +#include "common/config-manager.h" #include "engines/engine.h" +#include "engines/util.h" +#include "graphics/palette.h" namespace Adl { -static byte font[64][5] = { +static const byte font[64][5] = { { 0x7c, 0x82, 0xba, 0xb2, 0x9c }, { 0xf8, 0x24, 0x22, 0x24, 0xf8 }, // @A { 0xfe, 0x92, 0x92, 0x92, 0x6c }, { 0x7c, 0x82, 0x82, 0x82, 0x44 }, // BC { 0xfe, 0x82, 0x82, 0x82, 0x7c }, { 0xfe, 0x92, 0x92, 0x92, 0x82 }, // DE @@ -69,10 +72,17 @@ static byte font[64][5] = { }; Display::Display() : - _scanlines(false), _cursorPos(0), _mode(kModeText), _showCursor(false) { + + initGraphics(560, 384, true); + + _monochrome = !ConfMan.getBool("color"); + _scanlines = ConfMan.getBool("scanlines"); + + setPalette(_scanlines, _monochrome); + _frameBuf = new byte[kFrameBufSize]; _frameBufSurface = new Graphics::Surface; _frameBufSurface->create(kWidth * 2, kHeight * 2, Graphics::PixelFormat::createFormatCLUT8()); @@ -98,11 +108,37 @@ Display::~Display() { delete _font; } +void Display::setPalette(bool scanlines, bool monochrome) { + const byte colorPal[6 * 3] = { + 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, + 0xc7, 0x34, 0xff, + 0x38, 0xcb, 0x00, + 0x0d, 0xa1, 0xff, + 0xf2, 0x5e, 0x00 + }; + + const byte monoPal[2 * 3] = { + 0x00, 0x00, 0x00, + 0x00, 0xc0, 0x01 + }; + + if (monochrome) { + g_system->getPaletteManager()->setPalette(monoPal, 0, 2); + if (!scanlines) + g_system->getPaletteManager()->setPalette(monoPal, 6, 2); + } else { + g_system->getPaletteManager()->setPalette(colorPal, 0, 6); + if (!scanlines) + g_system->getPaletteManager()->setPalette(colorPal, 6, 6); + } +} + void Display::loadFrameBuffer(Common::ReadStream &stream) { stream.read(_frameBuf, kFrameBufSize); } -void Display::decodeScanline(byte *dst, int pitch, byte *src) { +void Display::decodeScanlineColor(byte *dst, int pitch, byte *src) { // TODO: shift secondPal by half a pixel bool prevOn = false; @@ -135,11 +171,8 @@ void Display::decodeScanline(byte *dst, int pitch, byte *src) { dst[0] = color; dst[1] = color; - - if (!_scanlines) { - dst[pitch] = color; - dst[pitch + 1] = color; - } + dst[pitch] = color + 6; + dst[pitch + 1] = color + 6; dst += 2; prevOn = curOn; @@ -147,6 +180,33 @@ void Display::decodeScanline(byte *dst, int pitch, byte *src) { } } +void Display::decodeScanlineMono(byte *dst, int pitch, byte *src) { + // TODO: shift secondPal by half a pixel + + for (uint j = 0; j < 39; ++j) { + for (uint k = 0; k < 7; ++k) { + byte color = 0; + + if (src[j] & (1 << k)) + color = 1; + + dst[0] = color; + dst[1] = color; + dst[pitch] = color + 6; + dst[pitch + 1] = color + 6; + + dst += 2; + } + } +} + +void Display::decodeScanline(byte *dst, int pitch, byte *src) { + if (_monochrome) + decodeScanlineMono(dst, pitch, src); + else + decodeScanlineColor(dst, pitch, src); +} + Display::PixelPos Display::getPixelPos(byte x, byte y) { PixelPos pixelPos; @@ -390,16 +450,23 @@ void Display::drawChar(byte c, int x, int y) { byte *buf = (byte *)_font->getPixels() + y * _font->pitch + x; for (uint row = 0; row < 8; ++row) { - for (uint col = 1; col < 6; ++col) + if (row & 1) { + buf[_font->pitch] = 6; + buf[_font->pitch + 1] = 6; + buf[_font->pitch + 6 * 2] = 6; + buf[_font->pitch + 6 * 2 + 1] = 6; + } + for (uint col = 1; col < 6; ++col) { if (font[c][col - 1] & (1 << row)) { buf[col * 2] = 1; buf[col * 2 + 1] = 1; - - if (!_scanlines) { - buf[_font->pitch + col * 2] = 1; - buf[_font->pitch + col * 2 + 1] = 1; - } + buf[_font->pitch + col * 2] = 1 + 6; + buf[_font->pitch + col * 2 + 1] = 1 + 6; + } else { + buf[_font->pitch + col * 2] = 6; + buf[_font->pitch + col * 2 + 1] = 6; } + } buf += 2 * _font->pitch; } @@ -417,10 +484,15 @@ void Display::createFont() { byte *buf = (byte *)_font->getPixels(); byte *bufInv = buf + (_font->h / 2) * _font->pitch; - for (uint row = 0; row < _font->h / 2; ++row) { - if (!_scanlines || !(row & 1)) - for (uint col = 0; col < _font->w; ++col) - bufInv[col] = buf[col] ? 0 : 1; + for (uint row = 0; row < _font->h / 2; row += 2) { + for (uint col = 0; col < _font->w; ++col) + bufInv[col] = (buf[col] ? 0 : 1); + + buf += _font->pitch; + bufInv += _font->pitch; + + for (uint col = 0; col < _font->w; ++col) + bufInv[col] = (buf[col] == 7 ? 6 : 7); buf += _font->pitch; bufInv += _font->pitch; -- cgit v1.2.3 From b30fb417acb29dee415a784f15f63772a010b4d3 Mon Sep 17 00:00:00 2001 From: Walter van Niftrik Date: Thu, 3 Mar 2016 14:05:19 +0100 Subject: ADL: Disable scanlines when saving thumbnail --- engines/adl/display.cpp | 51 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 40 insertions(+), 11 deletions(-) (limited to 'engines/adl/display.cpp') diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp index ade05ab06d..6a7cc6900b 100644 --- a/engines/adl/display.cpp +++ b/engines/adl/display.cpp @@ -33,6 +33,7 @@ #include "engines/engine.h" #include "engines/util.h" #include "graphics/palette.h" +#include "graphics/thumbnail.h" namespace Adl { @@ -81,7 +82,12 @@ Display::Display() : _monochrome = !ConfMan.getBool("color"); _scanlines = ConfMan.getBool("scanlines"); - setPalette(_scanlines, _monochrome); + if (_monochrome) + setMonoPalette(); + else + setColorPalette(); + + enableScanlines(_scanlines); _frameBuf = new byte[kFrameBufSize]; _frameBufSurface = new Graphics::Surface; @@ -108,7 +114,34 @@ Display::~Display() { delete _font; } -void Display::setPalette(bool scanlines, bool monochrome) { +bool Display::saveThumbnail(Common::WriteStream &out) { + if (_scanlines) { + enableScanlines(false); + g_system->updateScreen(); + } + + bool retval = Graphics::saveThumbnail(out); + + if (_scanlines) { + enableScanlines(true); + g_system->updateScreen(); + } + + return retval; +} + +void Display::enableScanlines(bool enable) { + byte pal[6 * 3] = { }; + + if (enable) + g_system->getPaletteManager()->setPalette(pal, 6, 6); + else { + g_system->getPaletteManager()->grabPalette(pal, 0, 6); + g_system->getPaletteManager()->setPalette(pal, 6, 6); + } +} + +void Display::setColorPalette() { const byte colorPal[6 * 3] = { 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, @@ -118,20 +151,16 @@ void Display::setPalette(bool scanlines, bool monochrome) { 0xf2, 0x5e, 0x00 }; + g_system->getPaletteManager()->setPalette(colorPal, 0, 6); +} + +void Display::setMonoPalette() { const byte monoPal[2 * 3] = { 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01 }; - if (monochrome) { - g_system->getPaletteManager()->setPalette(monoPal, 0, 2); - if (!scanlines) - g_system->getPaletteManager()->setPalette(monoPal, 6, 2); - } else { - g_system->getPaletteManager()->setPalette(colorPal, 0, 6); - if (!scanlines) - g_system->getPaletteManager()->setPalette(colorPal, 6, 6); - } + g_system->getPaletteManager()->setPalette(monoPal, 0, 2); } void Display::loadFrameBuffer(Common::ReadStream &stream) { -- cgit v1.2.3 From d5cc42f1c233a45abb879818af503ec7b91c6f34 Mon Sep 17 00:00:00 2001 From: Walter van Niftrik Date: Thu, 3 Mar 2016 19:17:49 +0100 Subject: ADL: Make frame buffer linear --- engines/adl/display.cpp | 241 ++++++++---------------------------------------- 1 file changed, 37 insertions(+), 204 deletions(-) (limited to 'engines/adl/display.cpp') diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp index 6a7cc6900b..90ca1b60db 100644 --- a/engines/adl/display.cpp +++ b/engines/adl/display.cpp @@ -89,7 +89,7 @@ Display::Display() : enableScanlines(_scanlines); - _frameBuf = new byte[kFrameBufSize]; + _frameBuf = new byte[kWidth * kHeight / 7]; _frameBufSurface = new Graphics::Surface; _frameBufSurface->create(kWidth * 2, kHeight * 2, Graphics::PixelFormat::createFormatCLUT8()); @@ -164,7 +164,19 @@ void Display::setMonoPalette() { } void Display::loadFrameBuffer(Common::ReadStream &stream) { - stream.read(_frameBuf, kFrameBufSize); + for (uint j = 0; j < 8; ++j) { + for (uint i = 0; i < 8; ++i) { + byte *dst = _frameBuf + kWidth / 7 * (i * 8 + j); + stream.read(dst, kWidth / 7); + dst += kWidth / 7 * 64; + stream.read(dst, kWidth / 7); + dst += kWidth / 7 * 64; + stream.read(dst, kWidth / 7); + stream.readUint32LE(); + stream.readUint32LE(); + dst += kWidth / 7 * 64; + } + } } void Display::decodeScanlineColor(byte *dst, int pitch, byte *src) { @@ -236,224 +248,45 @@ void Display::decodeScanline(byte *dst, int pitch, byte *src) { decodeScanlineColor(dst, pitch, src); } -Display::PixelPos Display::getPixelPos(byte x, byte y) { - PixelPos pixelPos; - - // FIXME: check X, Y range - - byte offsetL = y & 0xc0; - offsetL |= offsetL >> 2; - byte offsetH = y; - y <<= 2; - offsetH <<= 1; - offsetH |= y >> 7; - y <<= 1; - offsetH <<= 1; - offsetH |= y >> 7; - y <<= 1; - offsetL >>= 1; - offsetL |= y & 0x80; - y <<= 1; - offsetH = offsetH & 0x1f; - pixelPos.rowAddr = (offsetH << 8) | offsetL; - pixelPos.byteOffset = x / 7; - pixelPos.bitMask = 0x80 | (1 << x % 7); - - return pixelPos; -} - -byte Display::getPixelColor(byte offset, byte color) { - if (offset & 1) { - byte c = color << 1; - if (c >= 0x40 && c < 0xc0) - return color ^ 0x7f; - } - - return color; -} - void Display::decodeFrameBuffer() { byte *src = _frameBuf; - int pitch = _frameBufSurface->pitch; - for (int j = 0; j < 8; ++j) { - for (int i = 0; i < 8; ++i) { - byte *dst = (byte *)_frameBufSurface->getPixels() + pitch * 2 * (i * 8 + j); - decodeScanline(dst, pitch, src); - src += 40; - dst += pitch * 2 * 64; - decodeScanline(dst, pitch, src); - src += 40; - dst += pitch * 2 * 64; - decodeScanline(dst, pitch, src); - src += 48; - dst += pitch * 2 * 64; - } - } -} - -void Display::drawPixel(byte x, byte y, byte color) { - PixelPos p = getPixelPos(x, y); - byte c = getPixelColor(p.byteOffset, color); - byte *b = _frameBuf + p.rowAddr + p.byteOffset; - c ^= *b; - c &= p.bitMask; - c ^= *b; - *b = c; -} + byte *dst = (byte *)_frameBufSurface->getPixels(); -void Display::moveX(PixelPos &p, byte &color, bool left) { - if (left) { - byte bit = p.bitMask; - bool b = bit & 1; - bit >>= 1; - if (!b) { - bit ^= 0xc0; - p.bitMask = bit; - return; - } - --p.byteOffset; - if (p.byteOffset & 0x80) - p.byteOffset = 39; - p.bitMask = 0xc0; - } else { - byte bit = p.bitMask; - bit <<= 1; - bit ^= 0x80; - if (bit & 0x80) { - p.bitMask = bit; - return; - } - p.bitMask = 0x81; - ++p.byteOffset; - if (p.byteOffset == 40) - p.byteOffset = 0; + for (uint i = 0; i < kHeight; ++i) { + decodeScanline(dst, _frameBufSurface->pitch, src); + src += kWidth / 7; + dst += _frameBufSurface->pitch * 2; } - - color = getPixelColor(p.byteOffset, color); } -void Display::moveY(PixelPos &p, bool down) { - if (!down) { - if (p.rowAddr & 0x1c00) - p.rowAddr -= 0x400; - else if (p.rowAddr & 0x380) - p.rowAddr += 0x1b80; - else { - p.rowAddr += 0x1f58; - if (!(p.rowAddr & 0x80)) - p.rowAddr += 0x78; // Wrap around - } - } else { - p.rowAddr += 0x400; - if (p.rowAddr & 0x1c00) - return; - else if ((p.rowAddr & 0x380) != 0x380) - p.rowAddr -= 0x1f80; - else { - p.rowAddr -= 0x2358; - if ((p.rowAddr & 0x78) == 0x78) - p.rowAddr -= 0x78; // Wrap around - } - } -} +void Display::putPixel(Common::Point p, byte color) { + byte offset = p.x / 7; -void Display::drawNextPixel(Display::PixelPos &p, byte &color, byte bits, byte quadrant) { - if (bits & 4) { - byte b = (_frameBuf[p.rowAddr + p.byteOffset] ^ color) & p.bitMask; - _frameBuf[p.rowAddr + p.byteOffset] ^= b; + if (offset & 1) { + byte c = color << 1; + if (c >= 0x40 && c < 0xc0) + color ^= 0x7f; } - bits += quadrant; - - if (bits & 1) - moveX(p, color, bits & 2); - else - moveY(p, bits & 2); -} - -void Display::drawLineArt(const Common::Array &lineArt, Common::Point p, byte rotation, byte scaling, byte color) { - const byte stepping[] = { - 0xff, 0xfe, 0xfa, 0xf4, 0xec, 0xe1, 0xd4, 0xc5, - 0xb4, 0xa1, 0x8d, 0x78, 0x61, 0x49, 0x31, 0x18, - 0xff - }; - - PixelPos pos = getPixelPos(p.x, p.y); - byte c = getPixelColor(pos.byteOffset, color); - - byte quadrant = rotation >> 4; - rotation &= 0xf; - byte xStep = stepping[rotation]; - byte yStep = stepping[(rotation ^ 0xf) + 1] + 1; - - for (uint i = 0; i < lineArt.size(); ++i) { - byte b = lineArt[i]; - - do { - byte xFrac = 0x80; - byte yFrac = 0x80; - for (uint j = 0; j < scaling; ++j) { - if (xFrac + xStep + 1 > 255) - drawNextPixel(pos, c, b, quadrant); - xFrac += xStep + 1; - if (yFrac + yStep > 255) - drawNextPixel(pos, c, b, quadrant + 1); - yFrac += yStep; - } - b >>= 3; - } while (b != 0); - } + byte *b = _frameBuf + p.y * kWidth / 7 + offset; + color ^= *b; + color &= 1 << (p.x % 7); + *b ^= color; } -void Display::drawLine(Common::Point p1, Common::Point p2, byte color) { - PixelPos p = getPixelPos(p1.x, p1.y); - byte c = getPixelColor(p.byteOffset, color); - - int16 deltaX = p2.x - p1.x; - byte dir = deltaX >> 8; - - if (deltaX < 0) - deltaX = -deltaX; - - int16 err = deltaX; - - int16 deltaY = p2.y - p1.y - 1; - dir >>= 1; - if (deltaY >= 0) { - deltaY = -deltaY - 2; - dir |= 0x80; - } - - int16 steps = deltaY - deltaX; - - err += deltaY + 1; - - while (1) { - byte *b = _frameBuf + p.rowAddr + p.byteOffset; - byte d = *b; - d ^= c; - d &= p.bitMask; - d ^= *b; - *b = d; +void Display::clear(byte color) { + byte val = 0; - if (++steps == 0) - return; + byte c = color << 1; + if (c >= 0x40 && c < 0xc0) + val = 0x7f; - if (err < 0) { - moveY(p, dir & 0x80); - err += deltaX; - } else { - moveX(p, c, dir & 0x40); - err += deltaY + 1; - } + for (uint i = 0; i < kWidth / 7 * kHeight; ++i) { + _frameBuf[i] = color; + color ^= val; } } -void Display::clear(byte color) { - for (uint i = 0; i < kFrameBufSize; ++i) - _frameBuf[i] = getPixelColor(i & 1, color); -} - void Display::updateTextSurface() { for (uint row = 0; row < 24; ++row) for (uint col = 0; col < 40; ++col) { -- cgit v1.2.3 From 4f7e5da4dad61f11553e5f51f00d33506b9ef342 Mon Sep 17 00:00:00 2001 From: Walter van Niftrik Date: Fri, 4 Mar 2016 16:12:11 +0100 Subject: ADL: Clean up Display class --- engines/adl/display.cpp | 364 ++++++++++++++++++++++++------------------------ 1 file changed, 182 insertions(+), 182 deletions(-) (limited to 'engines/adl/display.cpp') diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp index 90ca1b60db..55166f4e30 100644 --- a/engines/adl/display.cpp +++ b/engines/adl/display.cpp @@ -20,23 +20,40 @@ * */ -#include "adl/display.h" #include "common/stream.h" #include "common/rect.h" -#include "graphics/surface.h" #include "common/system.h" #include "common/str.h" -#include "common/events.h" -#include "common/rect.h" -#include "common/array.h" #include "common/config-manager.h" -#include "engines/engine.h" -#include "engines/util.h" + +#include "graphics/surface.h" #include "graphics/palette.h" #include "graphics/thumbnail.h" +#include "engines/util.h" + +#include "adl/display.h" + namespace Adl { +#define DISPLAY_PITCH (DISPLAY_WIDTH / 7) + +#define COLOR_PALETTE_SIZE 6 +const byte colorPalette[COLOR_PALETTE_SIZE * 3] = { + 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, + 0xc7, 0x34, 0xff, + 0x38, 0xcb, 0x00, + 0x0d, 0xa1, 0xff, + 0xf2, 0x5e, 0x00 +}; + +#define MONO_PALETTE_SIZE 2 +const byte monoPalette[MONO_PALETTE_SIZE * 3] = { + 0x00, 0x00, 0x00, + 0x00, 0xc0, 0x01 +}; + static const byte font[64][5] = { { 0x7c, 0x82, 0xba, 0xb2, 0x9c }, { 0xf8, 0x24, 0x22, 0x24, 0xf8 }, // @A { 0xfe, 0x92, 0x92, 0x92, 0x6c }, { 0x7c, 0x82, 0x82, 0x82, 0x44 }, // BC @@ -73,8 +90,8 @@ static const byte font[64][5] = { }; Display::Display() : - _cursorPos(0), _mode(kModeText), + _cursorPos(0), _showCursor(false) { initGraphics(560, 384, true); @@ -83,20 +100,23 @@ Display::Display() : _scanlines = ConfMan.getBool("scanlines"); if (_monochrome) - setMonoPalette(); + g_system->getPaletteManager()->setPalette(monoPalette, 0, MONO_PALETTE_SIZE); else - setColorPalette(); + g_system->getPaletteManager()->setPalette(colorPalette, 0, COLOR_PALETTE_SIZE); enableScanlines(_scanlines); - _frameBuf = new byte[kWidth * kHeight / 7]; + _frameBuf = new byte[DISPLAY_PITCH * DISPLAY_HEIGHT]; _frameBufSurface = new Graphics::Surface; - _frameBufSurface->create(kWidth * 2, kHeight * 2, Graphics::PixelFormat::createFormatCLUT8()); + // We need 2x scaling to properly render the half-pixel shift + // of the second palette + _frameBufSurface->create(DISPLAY_WIDTH * 2, DISPLAY_HEIGHT * 2, Graphics::PixelFormat::createFormatCLUT8()); _textBuf = new byte[kTextBufSize]; - memset(_textBuf, ' ' | 0x80, kTextBufSize); + memset(_textBuf, APPLECHAR(' '), kTextBufSize); _textBufSurface = new Graphics::Surface; - _textBufSurface->create(kWidth * 2, kHeight * 2, Graphics::PixelFormat::createFormatCLUT8()); + // For ease of copying, also use 2x scaling here + _textBufSurface->create(DISPLAY_WIDTH * 2, DISPLAY_HEIGHT * 2, Graphics::PixelFormat::createFormatCLUT8()); createFont(); } @@ -114,6 +134,17 @@ Display::~Display() { delete _font; } +void Display::updateScreen() { + if (_mode == kModeText) { + g_system->copyRectToScreen(_textBufSurface->getPixels(), _textBufSurface->pitch, 0, 0, _textBufSurface->w, _textBufSurface->h); + } else if (_mode == kModeHires) { + g_system->copyRectToScreen(_frameBufSurface->getPixels(), _frameBufSurface->pitch, 0, 0, _frameBufSurface->w, _frameBufSurface->h); + } else { + g_system->copyRectToScreen(_frameBufSurface->getPixels(), _frameBufSurface->pitch, 0, 0, _frameBufSurface->w, _frameBufSurface->h - 4 * 8 * 2); + g_system->copyRectToScreen(_textBufSurface->getBasePtr(0, _textBufSurface->h - 4 * 8 * 2), _textBufSurface->pitch, 0, _textBufSurface->h - 4 * 8 * 2, _textBufSurface->w, 4 * 8 * 2); + } +} + bool Display::saveThumbnail(Common::WriteStream &out) { if (_scanlines) { enableScanlines(false); @@ -130,56 +161,153 @@ bool Display::saveThumbnail(Common::WriteStream &out) { return retval; } -void Display::enableScanlines(bool enable) { - byte pal[6 * 3] = { }; +void Display::loadFrameBuffer(Common::ReadStream &stream) { + for (uint j = 0; j < 8; ++j) { + for (uint i = 0; i < 8; ++i) { + byte *dst = _frameBuf + DISPLAY_PITCH * (i * 8 + j); + stream.read(dst, DISPLAY_PITCH); + dst += DISPLAY_PITCH * 64; + stream.read(dst, DISPLAY_PITCH); + dst += DISPLAY_PITCH * 64; + stream.read(dst, DISPLAY_PITCH); + stream.readUint32LE(); + stream.readUint32LE(); + dst += DISPLAY_PITCH * 64; + } + } +} - if (enable) - g_system->getPaletteManager()->setPalette(pal, 6, 6); - else { - g_system->getPaletteManager()->grabPalette(pal, 0, 6); - g_system->getPaletteManager()->setPalette(pal, 6, 6); +void Display::decodeFrameBuffer() { + byte *src = _frameBuf; + byte *dst = (byte *)_frameBufSurface->getPixels(); + + for (uint i = 0; i < DISPLAY_HEIGHT; ++i) { + decodeScanline(dst, _frameBufSurface->pitch, src); + src += DISPLAY_PITCH; + dst += _frameBufSurface->pitch * 2; } } -void Display::setColorPalette() { - const byte colorPal[6 * 3] = { - 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, - 0xc7, 0x34, 0xff, - 0x38, 0xcb, 0x00, - 0x0d, 0xa1, 0xff, - 0xf2, 0x5e, 0x00 - }; - - g_system->getPaletteManager()->setPalette(colorPal, 0, 6); +void Display::putPixel(Common::Point p, byte color) { + byte offset = p.x / 7; + + if (offset & 1) { + byte c = color << 1; + if (c >= 0x40 && c < 0xc0) + color ^= 0x7f; + } + + byte *b = _frameBuf + p.y * DISPLAY_PITCH + offset; + color ^= *b; + color &= 1 << (p.x % 7); + *b ^= color; } -void Display::setMonoPalette() { - const byte monoPal[2 * 3] = { - 0x00, 0x00, 0x00, - 0x00, 0xc0, 0x01 - }; +void Display::clear(byte color) { + byte val = 0; + + byte c = color << 1; + if (c >= 0x40 && c < 0xc0) + val = 0x7f; - g_system->getPaletteManager()->setPalette(monoPal, 0, 2); + for (uint i = 0; i < DISPLAY_PITCH * DISPLAY_HEIGHT; ++i) { + _frameBuf[i] = color; + color ^= val; + } } -void Display::loadFrameBuffer(Common::ReadStream &stream) { - for (uint j = 0; j < 8; ++j) { - for (uint i = 0; i < 8; ++i) { - byte *dst = _frameBuf + kWidth / 7 * (i * 8 + j); - stream.read(dst, kWidth / 7); - dst += kWidth / 7 * 64; - stream.read(dst, kWidth / 7); - dst += kWidth / 7 * 64; - stream.read(dst, kWidth / 7); - stream.readUint32LE(); - stream.readUint32LE(); - dst += kWidth / 7 * 64; +void Display::updateTextSurface() { + for (uint row = 0; row < 24; ++row) + for (uint col = 0; col < 40; ++col) { + int charPos = row * 40 + col; + char c = _textBuf[row * 40 + col]; + + if (charPos == _cursorPos && _showCursor) + c = (c & 0x3f) | 0x40; + + Common::Rect r(7 * 2, 8 * 2); + r.translate(((c & 0x3f) % 16) * 7 * 2, (c & 0x3f) / 16 * 8 * 2); + + if (!(c & 0x80)) { + if (!(c & 0x40) || ((g_system->getMillis() / 270) & 1)) + r.translate(0, 4 * 8 * 2); + } + + _textBufSurface->copyRectToSurface(*_font, col * 7 * 2, row * 8 * 2, r); + } +} + + +void Display::setCursorPos(Common::Point pos) { + _cursorPos = pos.y * 40 + pos.x; +} + + +void Display::home() { + memset(_textBuf, APPLECHAR(' '), kTextBufSize); + _cursorPos = 0; +} + +void Display::moveCursorForward() { + ++_cursorPos; + + if (_cursorPos >= kTextBufSize) + scrollUp(); +} + +void Display::moveCursorBackward() { + --_cursorPos; + + if (_cursorPos < 0) + _cursorPos = 0; +} + +void Display::moveCursorTo(const Common::Point &pos) { + _cursorPos = pos.y * 40 + pos.x; + + if (_cursorPos >= kTextBufSize) + error("Cursor position (%i, %i) out of bounds", pos.x, pos.y); +} + +void Display::printString(const Common::String &str) { + Common::String::const_iterator c; + for (c = str.begin(); c != str.end(); ++c) { + byte b = *c; + + if (*c == APPLECHAR('\r')) + _cursorPos = (_cursorPos / 40 + 1) * 40; + else if (b < 0x80 || b >= 0xa0) { + setCharAtCursor(b); + ++_cursorPos; } + + if (_cursorPos == kTextBufSize) + scrollUp(); } + + updateTextSurface(); } -void Display::decodeScanlineColor(byte *dst, int pitch, byte *src) { +void Display::setCharAtCursor(byte c) { + _textBuf[_cursorPos] = c; +} + +void Display::showCursor(bool enable) { + _showCursor = enable; +} + +void Display::enableScanlines(bool enable) { + byte pal[6 * 3] = { }; + + if (enable) + g_system->getPaletteManager()->setPalette(pal, 6, 6); + else { + g_system->getPaletteManager()->grabPalette(pal, 0, 6); + g_system->getPaletteManager()->setPalette(pal, 6, 6); + } +} + +void Display::decodeScanlineColor(byte *dst, int pitch, byte *src) const { // TODO: shift secondPal by half a pixel bool prevOn = false; @@ -221,7 +349,7 @@ void Display::decodeScanlineColor(byte *dst, int pitch, byte *src) { } } -void Display::decodeScanlineMono(byte *dst, int pitch, byte *src) { +void Display::decodeScanlineMono(byte *dst, int pitch, byte *src) const { // TODO: shift secondPal by half a pixel for (uint j = 0; j < 39; ++j) { @@ -241,73 +369,13 @@ void Display::decodeScanlineMono(byte *dst, int pitch, byte *src) { } } -void Display::decodeScanline(byte *dst, int pitch, byte *src) { +void Display::decodeScanline(byte *dst, int pitch, byte *src) const { if (_monochrome) decodeScanlineMono(dst, pitch, src); else decodeScanlineColor(dst, pitch, src); } -void Display::decodeFrameBuffer() { - byte *src = _frameBuf; - byte *dst = (byte *)_frameBufSurface->getPixels(); - - for (uint i = 0; i < kHeight; ++i) { - decodeScanline(dst, _frameBufSurface->pitch, src); - src += kWidth / 7; - dst += _frameBufSurface->pitch * 2; - } -} - -void Display::putPixel(Common::Point p, byte color) { - byte offset = p.x / 7; - - if (offset & 1) { - byte c = color << 1; - if (c >= 0x40 && c < 0xc0) - color ^= 0x7f; - } - - byte *b = _frameBuf + p.y * kWidth / 7 + offset; - color ^= *b; - color &= 1 << (p.x % 7); - *b ^= color; -} - -void Display::clear(byte color) { - byte val = 0; - - byte c = color << 1; - if (c >= 0x40 && c < 0xc0) - val = 0x7f; - - for (uint i = 0; i < kWidth / 7 * kHeight; ++i) { - _frameBuf[i] = color; - color ^= val; - } -} - -void Display::updateTextSurface() { - for (uint row = 0; row < 24; ++row) - for (uint col = 0; col < 40; ++col) { - int charPos = row * 40 + col; - char c = _textBuf[row * 40 + col]; - - if (charPos == _cursorPos && _showCursor) - c = (c & 0x3f) | 0x40; - - Common::Rect r(7 * 2, 8 * 2); - r.translate(((c & 0x3f) % 16) * 7 * 2, (c & 0x3f) / 16 * 8 * 2); - - if (!(c & 0x80)) { - if (!(c & 0x40) || ((g_system->getMillis() / 270) & 1)) - r.translate(0, 4 * 8 * 2); - } - - _textBufSurface->copyRectToSurface(*_font, col * 7 * 2, row * 8 * 2, r); - } -} - void Display::drawChar(byte c, int x, int y) { byte *buf = (byte *)_font->getPixels() + y * _font->pitch + x; @@ -361,78 +429,10 @@ void Display::createFont() { } } -void Display::updateScreen() { - if (_mode == kModeText) { - g_system->copyRectToScreen(_textBufSurface->getPixels(), _textBufSurface->pitch, 0, 0, _textBufSurface->w, _textBufSurface->h); - } else if (_mode == kModeHires) { - g_system->copyRectToScreen(_frameBufSurface->getPixels(), _frameBufSurface->pitch, 0, 0, _frameBufSurface->w, _frameBufSurface->h); - } else { - g_system->copyRectToScreen(_frameBufSurface->getPixels(), _frameBufSurface->pitch, 0, 0, _frameBufSurface->w, _frameBufSurface->h - 4 * 8 * 2); - g_system->copyRectToScreen(_textBufSurface->getBasePtr(0, _textBufSurface->h - 4 * 8 * 2), _textBufSurface->pitch, 0, _textBufSurface->h - 4 * 8 * 2, _textBufSurface->w, 4 * 8 * 2); - } -} - -void Display::home() { - memset(_textBuf, APPLECHAR(' '), kTextBufSize); - _cursorPos = 0; -} - -void Display::moveCursorForward() { - ++_cursorPos; - - if (_cursorPos >= kTextBufSize) - scrollUp(); -} - -void Display::moveCursorBackward() { - --_cursorPos; - - if (_cursorPos < 0) - _cursorPos = 0; -} - -void Display::moveCursorTo(const Common::Point &pos) { - _cursorPos = pos.y * 40 + pos.x; - - if (_cursorPos >= kTextBufSize) - error("Cursor position (%i, %i) out of bounds", pos.x, pos.y); -} - -void Display::setCharAtCursor(byte c) { - _textBuf[_cursorPos] = c; -} - void Display::scrollUp() { memmove(_textBuf, _textBuf + 40, kTextBufSize - 40); - memset(_textBuf + kTextBufSize - 40, ' ' | 0x80, 40); + memset(_textBuf + kTextBufSize - 40, APPLECHAR(' '), 40); _cursorPos -= 40; } -void Display::printString(const Common::String &str) { - Common::String::const_iterator c; - for (c = str.begin(); c != str.end(); ++c) { - byte b = *c; - - if (*c == APPLECHAR('\r')) - _cursorPos = (_cursorPos / 40 + 1) * 40; - else if (b < 0x80 || b >= 0xa0) { - setCharAtCursor(b); - ++_cursorPos; - } - - if (_cursorPos == kTextBufSize) - scrollUp(); - } - - updateTextSurface(); -} - -void Display::showCursor(bool enable) { - _showCursor = enable; -} - -void Display::setCursorPos(Common::Point pos) { - _cursorPos = pos.y * 40 + pos.x; -} - } // End of namespace Adl -- cgit v1.2.3 From ec14c397eec87ee66337a9f15c044b47fec8855d Mon Sep 17 00:00:00 2001 From: Walter van Niftrik Date: Fri, 4 Mar 2016 18:48:31 +0100 Subject: ADL: Clean up Display class --- engines/adl/display.cpp | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'engines/adl/display.cpp') diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp index 55166f4e30..a75b129dc8 100644 --- a/engines/adl/display.cpp +++ b/engines/adl/display.cpp @@ -90,7 +90,7 @@ static const byte font[64][5] = { }; Display::Display() : - _mode(kModeText), + _mode(DISPLAY_MODE_TEXT), _cursorPos(0), _showCursor(false) { @@ -135,9 +135,9 @@ Display::~Display() { } void Display::updateScreen() { - if (_mode == kModeText) { + if (_mode == DISPLAY_MODE_TEXT) { g_system->copyRectToScreen(_textBufSurface->getPixels(), _textBufSurface->pitch, 0, 0, _textBufSurface->w, _textBufSurface->h); - } else if (_mode == kModeHires) { + } else if (_mode == DISPLAY_MODE_HIRES) { g_system->copyRectToScreen(_frameBufSurface->getPixels(), _frameBufSurface->pitch, 0, 0, _frameBufSurface->w, _frameBufSurface->h); } else { g_system->copyRectToScreen(_frameBufSurface->getPixels(), _frameBufSurface->pitch, 0, 0, _frameBufSurface->w, _frameBufSurface->h - 4 * 8 * 2); @@ -237,12 +237,6 @@ void Display::updateTextSurface() { } } - -void Display::setCursorPos(Common::Point pos) { - _cursorPos = pos.y * 40 + pos.x; -} - - void Display::home() { memset(_textBuf, APPLECHAR(' '), kTextBufSize); _cursorPos = 0; -- cgit v1.2.3 From e6d478ad150f7eb702f12c8d3a60bfcd416f2b2e Mon Sep 17 00:00:00 2001 From: Walter van Niftrik Date: Fri, 4 Mar 2016 20:06:16 +0100 Subject: ADL: Clean up Display class --- engines/adl/display.cpp | 114 +++++++++++++++++++++++++++++------------------- 1 file changed, 68 insertions(+), 46 deletions(-) (limited to 'engines/adl/display.cpp') diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp index a75b129dc8..05c96cfcda 100644 --- a/engines/adl/display.cpp +++ b/engines/adl/display.cpp @@ -36,10 +36,12 @@ namespace Adl { +// TODO: Implement partial screen updates + #define DISPLAY_PITCH (DISPLAY_WIDTH / 7) -#define COLOR_PALETTE_SIZE 6 -const byte colorPalette[COLOR_PALETTE_SIZE * 3] = { +#define COLOR_PALETTE_ENTRIES 6 +const byte colorPalette[COLOR_PALETTE_ENTRIES * 3] = { 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xc7, 0x34, 0xff, @@ -48,8 +50,8 @@ const byte colorPalette[COLOR_PALETTE_SIZE * 3] = { 0xf2, 0x5e, 0x00 }; -#define MONO_PALETTE_SIZE 2 -const byte monoPalette[MONO_PALETTE_SIZE * 3] = { +#define MONO_PALETTE_ENTRIES 2 +const byte monoPalette[MONO_PALETTE_ENTRIES * 3] = { 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01 }; @@ -100,9 +102,9 @@ Display::Display() : _scanlines = ConfMan.getBool("scanlines"); if (_monochrome) - g_system->getPaletteManager()->setPalette(monoPalette, 0, MONO_PALETTE_SIZE); + g_system->getPaletteManager()->setPalette(monoPalette, 0, MONO_PALETTE_ENTRIES); else - g_system->getPaletteManager()->setPalette(colorPalette, 0, COLOR_PALETTE_SIZE); + g_system->getPaletteManager()->setPalette(colorPalette, 0, COLOR_PALETTE_ENTRIES); enableScanlines(_scanlines); @@ -134,15 +136,35 @@ Display::~Display() { delete _font; } -void Display::updateScreen() { - if (_mode == DISPLAY_MODE_TEXT) { +void Display::setMode(DisplayMode mode) { + _mode = mode; + + if (_mode == DISPLAY_MODE_TEXT || _mode == DISPLAY_MODE_MIXED) + updateTextScreen(); + if (_mode == DISPLAY_MODE_HIRES || _mode == DISPLAY_MODE_MIXED) + updateHiResScreen(); +} + +void Display::updateTextScreen() { + updateTextSurface(); + + if (_mode == DISPLAY_MODE_TEXT) g_system->copyRectToScreen(_textBufSurface->getPixels(), _textBufSurface->pitch, 0, 0, _textBufSurface->w, _textBufSurface->h); - } else if (_mode == DISPLAY_MODE_HIRES) { + else if (_mode == DISPLAY_MODE_MIXED) + g_system->copyRectToScreen(_textBufSurface->getBasePtr(0, _textBufSurface->h - 4 * 8 * 2), _textBufSurface->pitch, 0, _textBufSurface->h - 4 * 8 * 2, _textBufSurface->w, 4 * 8 * 2); + + g_system->updateScreen(); +} + +void Display::updateHiResScreen() { + updateHiResSurface(); + + if (_mode == DISPLAY_MODE_HIRES) g_system->copyRectToScreen(_frameBufSurface->getPixels(), _frameBufSurface->pitch, 0, 0, _frameBufSurface->w, _frameBufSurface->h); - } else { + else if (_mode == DISPLAY_MODE_MIXED) g_system->copyRectToScreen(_frameBufSurface->getPixels(), _frameBufSurface->pitch, 0, 0, _frameBufSurface->w, _frameBufSurface->h - 4 * 8 * 2); - g_system->copyRectToScreen(_textBufSurface->getBasePtr(0, _textBufSurface->h - 4 * 8 * 2), _textBufSurface->pitch, 0, _textBufSurface->h - 4 * 8 * 2, _textBufSurface->w, 4 * 8 * 2); - } + + g_system->updateScreen(); } bool Display::saveThumbnail(Common::WriteStream &out) { @@ -177,17 +199,6 @@ void Display::loadFrameBuffer(Common::ReadStream &stream) { } } -void Display::decodeFrameBuffer() { - byte *src = _frameBuf; - byte *dst = (byte *)_frameBufSurface->getPixels(); - - for (uint i = 0; i < DISPLAY_HEIGHT; ++i) { - decodeScanline(dst, _frameBufSurface->pitch, src); - src += DISPLAY_PITCH; - dst += _frameBufSurface->pitch * 2; - } -} - void Display::putPixel(Common::Point p, byte color) { byte offset = p.x / 7; @@ -216,27 +227,6 @@ void Display::clear(byte color) { } } -void Display::updateTextSurface() { - for (uint row = 0; row < 24; ++row) - for (uint col = 0; col < 40; ++col) { - int charPos = row * 40 + col; - char c = _textBuf[row * 40 + col]; - - if (charPos == _cursorPos && _showCursor) - c = (c & 0x3f) | 0x40; - - Common::Rect r(7 * 2, 8 * 2); - r.translate(((c & 0x3f) % 16) * 7 * 2, (c & 0x3f) / 16 * 8 * 2); - - if (!(c & 0x80)) { - if (!(c & 0x40) || ((g_system->getMillis() / 270) & 1)) - r.translate(0, 4 * 8 * 2); - } - - _textBufSurface->copyRectToSurface(*_font, col * 7 * 2, row * 8 * 2, r); - } -} - void Display::home() { memset(_textBuf, APPLECHAR(' '), kTextBufSize); _cursorPos = 0; @@ -279,7 +269,7 @@ void Display::printString(const Common::String &str) { scrollUp(); } - updateTextSurface(); + updateTextScreen(); } void Display::setCharAtCursor(byte c) { @@ -291,7 +281,7 @@ void Display::showCursor(bool enable) { } void Display::enableScanlines(bool enable) { - byte pal[6 * 3] = { }; + byte pal[COLOR_PALETTE_ENTRIES * 3] = { }; if (enable) g_system->getPaletteManager()->setPalette(pal, 6, 6); @@ -301,6 +291,17 @@ void Display::enableScanlines(bool enable) { } } +void Display::updateHiResSurface() { + byte *src = _frameBuf; + byte *dst = (byte *)_frameBufSurface->getPixels(); + + for (uint i = 0; i < DISPLAY_HEIGHT; ++i) { + decodeScanline(dst, _frameBufSurface->pitch, src); + src += DISPLAY_PITCH; + dst += _frameBufSurface->pitch * 2; + } +} + void Display::decodeScanlineColor(byte *dst, int pitch, byte *src) const { // TODO: shift secondPal by half a pixel @@ -370,6 +371,27 @@ void Display::decodeScanline(byte *dst, int pitch, byte *src) const { decodeScanlineColor(dst, pitch, src); } +void Display::updateTextSurface() { + for (uint row = 0; row < 24; ++row) + for (uint col = 0; col < 40; ++col) { + int charPos = row * 40 + col; + char c = _textBuf[row * 40 + col]; + + if (charPos == _cursorPos && _showCursor) + c = (c & 0x3f) | 0x40; + + Common::Rect r(7 * 2, 8 * 2); + r.translate(((c & 0x3f) % 16) * 7 * 2, (c & 0x3f) / 16 * 8 * 2); + + if (!(c & 0x80)) { + if (!(c & 0x40) || ((g_system->getMillis() / 270) & 1)) + r.translate(0, 4 * 8 * 2); + } + + _textBufSurface->copyRectToSurface(*_font, col * 7 * 2, row * 8 * 2, r); + } +} + void Display::drawChar(byte c, int x, int y) { byte *buf = (byte *)_font->getPixels() + y * _font->pitch + x; -- cgit v1.2.3 From 6f9128983847d78a41da7cf2f16a1243c7c1fa28 Mon Sep 17 00:00:00 2001 From: Walter van Niftrik Date: Fri, 4 Mar 2016 22:35:12 +0100 Subject: ADL: Clean up Display class --- engines/adl/display.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'engines/adl/display.cpp') diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp index 05c96cfcda..e8ea8211ce 100644 --- a/engines/adl/display.cpp +++ b/engines/adl/display.cpp @@ -106,7 +106,7 @@ Display::Display() : else g_system->getPaletteManager()->setPalette(colorPalette, 0, COLOR_PALETTE_ENTRIES); - enableScanlines(_scanlines); + showScanlines(_scanlines); _frameBuf = new byte[DISPLAY_PITCH * DISPLAY_HEIGHT]; _frameBufSurface = new Graphics::Surface; @@ -169,14 +169,14 @@ void Display::updateHiResScreen() { bool Display::saveThumbnail(Common::WriteStream &out) { if (_scanlines) { - enableScanlines(false); + showScanlines(false); g_system->updateScreen(); } bool retval = Graphics::saveThumbnail(out); if (_scanlines) { - enableScanlines(true); + showScanlines(true); g_system->updateScreen(); } @@ -280,14 +280,14 @@ void Display::showCursor(bool enable) { _showCursor = enable; } -void Display::enableScanlines(bool enable) { +void Display::showScanlines(bool enable) { byte pal[COLOR_PALETTE_ENTRIES * 3] = { }; if (enable) - g_system->getPaletteManager()->setPalette(pal, 6, 6); + g_system->getPaletteManager()->setPalette(pal, COLOR_PALETTE_ENTRIES, COLOR_PALETTE_ENTRIES); else { - g_system->getPaletteManager()->grabPalette(pal, 0, 6); - g_system->getPaletteManager()->setPalette(pal, 6, 6); + g_system->getPaletteManager()->grabPalette(pal, 0, COLOR_PALETTE_ENTRIES); + g_system->getPaletteManager()->setPalette(pal, COLOR_PALETTE_ENTRIES, COLOR_PALETTE_ENTRIES); } } -- cgit v1.2.3 From f5430f961bd937755e85da17d24e8d3f22470545 Mon Sep 17 00:00:00 2001 From: Walter van Niftrik Date: Sat, 5 Mar 2016 08:10:43 +0100 Subject: ADL: Implement half-pixel shift in color mode --- engines/adl/display.cpp | 72 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 48 insertions(+), 24 deletions(-) (limited to 'engines/adl/display.cpp') diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp index e8ea8211ce..678b8c8bcf 100644 --- a/engines/adl/display.cpp +++ b/engines/adl/display.cpp @@ -36,20 +36,23 @@ namespace Adl { -// TODO: Implement partial screen updates +// This implements the Apple II "Hi-Res" display mode #define DISPLAY_PITCH (DISPLAY_WIDTH / 7) -#define COLOR_PALETTE_ENTRIES 6 +#define COLOR_PALETTE_ENTRIES 8 const byte colorPalette[COLOR_PALETTE_ENTRIES * 3] = { 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xc7, 0x34, 0xff, 0x38, 0xcb, 0x00, + 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0d, 0xa1, 0xff, 0xf2, 0x5e, 0x00 }; +// Green monochrome palette #define MONO_PALETTE_ENTRIES 2 const byte monoPalette[MONO_PALETTE_ENTRIES * 3] = { 0x00, 0x00, 0x00, @@ -303,11 +306,12 @@ void Display::updateHiResSurface() { } void Display::decodeScanlineColor(byte *dst, int pitch, byte *src) const { - // TODO: shift secondPal by half a pixel - bool prevOn = false; - for (uint j = 0; j < 39; ++j) { + if (src[0] & 0x80) + dst++; + + for (uint j = 0; j < 40; ++j) { bool secondPal = src[j] & 0x80; byte cur = src[j]; byte next = 0; @@ -326,19 +330,39 @@ void Display::decodeScanlineColor(byte *dst, int pitch, byte *src) const { byte color; if (curOn == prevOn || curOn == nextOn) color = curOn ? 1 : 0; - else { - if (secondPal) - color = (curOn == ((j + k) % 2) ? 5 : 4); - else - color = (curOn == ((j + k) % 2) ? 3 : 2); - } + else + color = (curOn == ((j + k) % 2) ? 3 : 2); + + if (secondPal) + color |= 4; dst[0] = color; - dst[1] = color; - dst[pitch] = color + 6; - dst[pitch + 1] = color + 6; + dst[pitch] = color + COLOR_PALETTE_ENTRIES; + ++dst; + + if (k == 6) { + if (secondPal) { + if (next & 0x80) { + dst[0] = color; + dst[pitch] = color + COLOR_PALETTE_ENTRIES; + ++dst; + } + } else { + dst[0] = color; + dst[pitch] = color + COLOR_PALETTE_ENTRIES; + ++dst; + if (next & 0x80) { + dst[0] = color | 4; + dst[pitch] = (color | 4) + COLOR_PALETTE_ENTRIES; + ++dst; + } + } + } else { + dst[0] = color; + dst[pitch] = color + COLOR_PALETTE_ENTRIES; + ++dst; + } - dst += 2; prevOn = curOn; } } @@ -397,20 +421,20 @@ void Display::drawChar(byte c, int x, int y) { for (uint row = 0; row < 8; ++row) { if (row & 1) { - buf[_font->pitch] = 6; - buf[_font->pitch + 1] = 6; - buf[_font->pitch + 6 * 2] = 6; - buf[_font->pitch + 6 * 2 + 1] = 6; + buf[_font->pitch] = COLOR_PALETTE_ENTRIES; + buf[_font->pitch + 1] = COLOR_PALETTE_ENTRIES; + buf[_font->pitch + 6 * 2] = COLOR_PALETTE_ENTRIES; + buf[_font->pitch + 6 * 2 + 1] = COLOR_PALETTE_ENTRIES; } for (uint col = 1; col < 6; ++col) { if (font[c][col - 1] & (1 << row)) { buf[col * 2] = 1; buf[col * 2 + 1] = 1; - buf[_font->pitch + col * 2] = 1 + 6; - buf[_font->pitch + col * 2 + 1] = 1 + 6; + buf[_font->pitch + col * 2] = 1 + COLOR_PALETTE_ENTRIES; + buf[_font->pitch + col * 2 + 1] = 1 + COLOR_PALETTE_ENTRIES; } else { - buf[_font->pitch + col * 2] = 6; - buf[_font->pitch + col * 2 + 1] = 6; + buf[_font->pitch + col * 2] = COLOR_PALETTE_ENTRIES; + buf[_font->pitch + col * 2 + 1] = COLOR_PALETTE_ENTRIES; } } @@ -438,7 +462,7 @@ void Display::createFont() { bufInv += _font->pitch; for (uint col = 0; col < _font->w; ++col) - bufInv[col] = (buf[col] == 7 ? 6 : 7); + bufInv[col] = (buf[col] == COLOR_PALETTE_ENTRIES + 1 ? COLOR_PALETTE_ENTRIES : COLOR_PALETTE_ENTRIES + 1); buf += _font->pitch; bufInv += _font->pitch; -- cgit v1.2.3 From 50d6e6938a60b323e1a1fbe2559e175492625cba Mon Sep 17 00:00:00 2001 From: Walter van Niftrik Date: Sat, 5 Mar 2016 12:34:48 +0100 Subject: ADL: Refactor graphics code --- engines/adl/display.cpp | 155 ++++++++++++++++++++++++++---------------------- 1 file changed, 84 insertions(+), 71 deletions(-) (limited to 'engines/adl/display.cpp') diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp index 678b8c8bcf..2a24b65a18 100644 --- a/engines/adl/display.cpp +++ b/engines/adl/display.cpp @@ -52,6 +52,12 @@ const byte colorPalette[COLOR_PALETTE_ENTRIES * 3] = { 0xf2, 0x5e, 0x00 }; +// Corresponding color in second palette +#define PAL2(X) ((X) | 0x04) + +// Alternate color for odd pixel rows (for scanlines) +#define ALTCOL(X) ((X) | 0x08) + // Green monochrome palette #define MONO_PALETTE_ENTRIES 2 const byte monoPalette[MONO_PALETTE_ENTRIES * 3] = { @@ -294,6 +300,17 @@ void Display::showScanlines(bool enable) { } } +static void copyEvenSurfaceRows(Graphics::Surface &surf) { + byte *src = (byte *)surf.getPixels(); + + for (uint y = 0; y < surf.h / 2; ++y) { + byte *dst = src + surf.pitch; + for (uint x = 0; x < surf.w; ++x) + dst[x] = ALTCOL(src[x]); + src += surf.pitch * 2; + } +} + void Display::updateHiResSurface() { byte *src = _frameBuf; byte *dst = (byte *)_frameBufSurface->getPixels(); @@ -303,68 +320,78 @@ void Display::updateHiResSurface() { src += DISPLAY_PITCH; dst += _frameBufSurface->pitch * 2; } + + copyEvenSurfaceRows(*_frameBufSurface); } -void Display::decodeScanlineColor(byte *dst, int pitch, byte *src) const { - bool prevOn = false; +static inline byte processColorBits(uint16 &bits, bool &odd, bool secondPal) { + byte color = 0; + + switch (bits & 0x7) { + case 0x3: // 011 (white) + case 0x6: // 110 + case 0x7: // 111 + color = 1; + break; + case 0x2: // 010 (color) + color = 2 + odd; + break; + case 0x5: // 101 (color) + color = 2 + !odd; + } - if (src[0] & 0x80) - dst++; + if (secondPal) + color = PAL2(color); - for (uint j = 0; j < 40; ++j) { - bool secondPal = src[j] & 0x80; - byte cur = src[j]; - byte next = 0; - if (j != 39) - next = src[j + 1]; + odd = !odd; + bits >>= 1; - for (uint k = 0; k < 7; ++k) { - bool curOn = cur & (1 << k); - bool nextOn; + return color; +} - if (k != 6) - nextOn = cur & (1 << (k + 1)); - else - nextOn = next & 1; +void Display::decodeScanlineColor(byte *dst, int pitch, byte *src) const { + uint16 bits = (src[0] & 0x7f) << 1; + byte pal = src[0] >> 7; - byte color; - if (curOn == prevOn || curOn == nextOn) - color = curOn ? 1 : 0; - else - color = (curOn == ((j + k) % 2) ? 3 : 2); + if (pal != 0) + *dst++ = 0; - if (secondPal) - color |= 4; + bool odd = false; - dst[0] = color; - dst[pitch] = color + COLOR_PALETTE_ENTRIES; - ++dst; - - if (k == 6) { - if (secondPal) { - if (next & 0x80) { - dst[0] = color; - dst[pitch] = color + COLOR_PALETTE_ENTRIES; - ++dst; - } - } else { - dst[0] = color; - dst[pitch] = color + COLOR_PALETTE_ENTRIES; - ++dst; - if (next & 0x80) { - dst[0] = color | 4; - dst[pitch] = (color | 4) + COLOR_PALETTE_ENTRIES; - ++dst; - } - } - } else { - dst[0] = color; - dst[pitch] = color + COLOR_PALETTE_ENTRIES; - ++dst; - } + for (uint i = 0; i < 40; ++i) { + if (i != 39) { + bits |= (src[i + 1] & 0x7f) << 8; + pal |= (src[i + 1] >> 7) << 1; + } - prevOn = curOn; + // For the first 6 bits in the block we draw two pixels + for (uint j = 0; j < 6; ++j) { + byte color = processColorBits(bits, odd, pal & 1); + *dst++ = color; + *dst++ = color; } + + // Last bit of the block, draw one, two or three pixels + byte color = processColorBits(bits, odd, pal & 1); + + // Draw the first pixel + *dst++ = color; + + switch (pal) { + case 0x0: + case 0x3: + // If palette stays the same, draw a second pixel + *dst++ = color; + break; + case 0x2: + // If we're moving from first to second palette, + // draw a second pixel, and a third in the second + // palette. + *dst++ = color; + *dst++ = PAL2(color); + } + + pal >>= 1; } } @@ -420,21 +447,10 @@ void Display::drawChar(byte c, int x, int y) { byte *buf = (byte *)_font->getPixels() + y * _font->pitch + x; for (uint row = 0; row < 8; ++row) { - if (row & 1) { - buf[_font->pitch] = COLOR_PALETTE_ENTRIES; - buf[_font->pitch + 1] = COLOR_PALETTE_ENTRIES; - buf[_font->pitch + 6 * 2] = COLOR_PALETTE_ENTRIES; - buf[_font->pitch + 6 * 2 + 1] = COLOR_PALETTE_ENTRIES; - } for (uint col = 1; col < 6; ++col) { if (font[c][col - 1] & (1 << row)) { buf[col * 2] = 1; buf[col * 2 + 1] = 1; - buf[_font->pitch + col * 2] = 1 + COLOR_PALETTE_ENTRIES; - buf[_font->pitch + col * 2 + 1] = 1 + COLOR_PALETTE_ENTRIES; - } else { - buf[_font->pitch + col * 2] = COLOR_PALETTE_ENTRIES; - buf[_font->pitch + col * 2 + 1] = COLOR_PALETTE_ENTRIES; } } @@ -458,21 +474,18 @@ void Display::createFont() { for (uint col = 0; col < _font->w; ++col) bufInv[col] = (buf[col] ? 0 : 1); - buf += _font->pitch; - bufInv += _font->pitch; - - for (uint col = 0; col < _font->w; ++col) - bufInv[col] = (buf[col] == COLOR_PALETTE_ENTRIES + 1 ? COLOR_PALETTE_ENTRIES : COLOR_PALETTE_ENTRIES + 1); - - buf += _font->pitch; - bufInv += _font->pitch; + buf += _font->pitch * 2; + bufInv += _font->pitch * 2; } + + copyEvenSurfaceRows(*_font); } void Display::scrollUp() { memmove(_textBuf, _textBuf + 40, kTextBufSize - 40); memset(_textBuf + kTextBufSize - 40, APPLECHAR(' '), 40); - _cursorPos -= 40; + if (_cursorPos >= 40) + _cursorPos -= 40; } } // End of namespace Adl -- cgit v1.2.3 From d3bfdc36578f137352589b8efacc3f4eb24054aa Mon Sep 17 00:00:00 2001 From: Walter van Niftrik Date: Sat, 5 Mar 2016 16:30:23 +0100 Subject: ADL: Add more #defines to replace literals --- engines/adl/display.cpp | 57 +++++++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 26 deletions(-) (limited to 'engines/adl/display.cpp') diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp index 2a24b65a18..6f72f91b32 100644 --- a/engines/adl/display.cpp +++ b/engines/adl/display.cpp @@ -39,6 +39,11 @@ namespace Adl { // This implements the Apple II "Hi-Res" display mode #define DISPLAY_PITCH (DISPLAY_WIDTH / 7) +#define DISPLAY_SIZE (DISPLAY_PITCH * DISPLAY_HEIGHT) + +#define TEXT_WIDTH 40 +#define TEXT_HEIGHT 24 +#define TEXT_BUF_SIZE (TEXT_WIDTH * TEXT_HEIGHT) #define COLOR_PALETTE_ENTRIES 8 const byte colorPalette[COLOR_PALETTE_ENTRIES * 3] = { @@ -117,14 +122,15 @@ Display::Display() : showScanlines(_scanlines); - _frameBuf = new byte[DISPLAY_PITCH * DISPLAY_HEIGHT]; + _frameBuf = new byte[DISPLAY_SIZE]; + memset(_frameBuf, 0, DISPLAY_SIZE); _frameBufSurface = new Graphics::Surface; // We need 2x scaling to properly render the half-pixel shift // of the second palette _frameBufSurface->create(DISPLAY_WIDTH * 2, DISPLAY_HEIGHT * 2, Graphics::PixelFormat::createFormatCLUT8()); - _textBuf = new byte[kTextBufSize]; - memset(_textBuf, APPLECHAR(' '), kTextBufSize); + _textBuf = new byte[TEXT_BUF_SIZE]; + memset(_textBuf, APPLECHAR(' '), TEXT_BUF_SIZE); _textBufSurface = new Graphics::Surface; // For ease of copying, also use 2x scaling here _textBufSurface->create(DISPLAY_WIDTH * 2, DISPLAY_HEIGHT * 2, Graphics::PixelFormat::createFormatCLUT8()); @@ -193,9 +199,9 @@ bool Display::saveThumbnail(Common::WriteStream &out) { } void Display::loadFrameBuffer(Common::ReadStream &stream) { + byte *dst = _frameBuf; for (uint j = 0; j < 8; ++j) { for (uint i = 0; i < 8; ++i) { - byte *dst = _frameBuf + DISPLAY_PITCH * (i * 8 + j); stream.read(dst, DISPLAY_PITCH); dst += DISPLAY_PITCH * 64; stream.read(dst, DISPLAY_PITCH); @@ -203,12 +209,13 @@ void Display::loadFrameBuffer(Common::ReadStream &stream) { stream.read(dst, DISPLAY_PITCH); stream.readUint32LE(); stream.readUint32LE(); - dst += DISPLAY_PITCH * 64; + dst -= DISPLAY_PITCH * 120; } + dst -= DISPLAY_PITCH * 63; } } -void Display::putPixel(Common::Point p, byte color) { +void Display::putPixel(const Common::Point &p, byte color) { byte offset = p.x / 7; if (offset & 1) { @@ -230,35 +237,33 @@ void Display::clear(byte color) { if (c >= 0x40 && c < 0xc0) val = 0x7f; - for (uint i = 0; i < DISPLAY_PITCH * DISPLAY_HEIGHT; ++i) { + for (uint i = 0; i < DISPLAY_SIZE; ++i) { _frameBuf[i] = color; color ^= val; } } void Display::home() { - memset(_textBuf, APPLECHAR(' '), kTextBufSize); + memset(_textBuf, APPLECHAR(' '), TEXT_BUF_SIZE); _cursorPos = 0; } void Display::moveCursorForward() { ++_cursorPos; - if (_cursorPos >= kTextBufSize) + if (_cursorPos >= TEXT_BUF_SIZE) scrollUp(); } void Display::moveCursorBackward() { - --_cursorPos; - - if (_cursorPos < 0) - _cursorPos = 0; + if (_cursorPos > 0) + --_cursorPos; } void Display::moveCursorTo(const Common::Point &pos) { - _cursorPos = pos.y * 40 + pos.x; + _cursorPos = pos.y * TEXT_WIDTH + pos.x; - if (_cursorPos >= kTextBufSize) + if (_cursorPos >= TEXT_BUF_SIZE) error("Cursor position (%i, %i) out of bounds", pos.x, pos.y); } @@ -268,13 +273,13 @@ void Display::printString(const Common::String &str) { byte b = *c; if (*c == APPLECHAR('\r')) - _cursorPos = (_cursorPos / 40 + 1) * 40; + _cursorPos = (_cursorPos / TEXT_WIDTH + 1) * TEXT_WIDTH; else if (b < 0x80 || b >= 0xa0) { setCharAtCursor(b); ++_cursorPos; } - if (_cursorPos == kTextBufSize) + if (_cursorPos == TEXT_BUF_SIZE) scrollUp(); } @@ -358,8 +363,8 @@ void Display::decodeScanlineColor(byte *dst, int pitch, byte *src) const { bool odd = false; - for (uint i = 0; i < 40; ++i) { - if (i != 39) { + for (uint i = 0; i < DISPLAY_PITCH; ++i) { + if (i != DISPLAY_PITCH - 1) { bits |= (src[i + 1] & 0x7f) << 8; pal |= (src[i + 1] >> 7) << 1; } @@ -424,9 +429,9 @@ void Display::decodeScanline(byte *dst, int pitch, byte *src) const { void Display::updateTextSurface() { for (uint row = 0; row < 24; ++row) - for (uint col = 0; col < 40; ++col) { - int charPos = row * 40 + col; - char c = _textBuf[row * 40 + col]; + for (uint col = 0; col < TEXT_WIDTH; ++col) { + uint charPos = row * TEXT_WIDTH + col; + char c = _textBuf[row * TEXT_WIDTH + col]; if (charPos == _cursorPos && _showCursor) c = (c & 0x3f) | 0x40; @@ -482,10 +487,10 @@ void Display::createFont() { } void Display::scrollUp() { - memmove(_textBuf, _textBuf + 40, kTextBufSize - 40); - memset(_textBuf + kTextBufSize - 40, APPLECHAR(' '), 40); - if (_cursorPos >= 40) - _cursorPos -= 40; + memmove(_textBuf, _textBuf + TEXT_WIDTH, TEXT_BUF_SIZE - TEXT_WIDTH); + memset(_textBuf + TEXT_BUF_SIZE - TEXT_WIDTH, APPLECHAR(' '), TEXT_WIDTH); + if (_cursorPos >= TEXT_WIDTH) + _cursorPos -= TEXT_WIDTH; } } // End of namespace Adl -- cgit v1.2.3 From b2d2f3405e0b36e92402b6c38bc2c406ea960147 Mon Sep 17 00:00:00 2001 From: Walter van Niftrik Date: Sat, 5 Mar 2016 16:34:39 +0100 Subject: ADL: Make palettes static --- engines/adl/display.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'engines/adl/display.cpp') diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp index 6f72f91b32..235e42bb73 100644 --- a/engines/adl/display.cpp +++ b/engines/adl/display.cpp @@ -46,7 +46,7 @@ namespace Adl { #define TEXT_BUF_SIZE (TEXT_WIDTH * TEXT_HEIGHT) #define COLOR_PALETTE_ENTRIES 8 -const byte colorPalette[COLOR_PALETTE_ENTRIES * 3] = { +static const byte colorPalette[COLOR_PALETTE_ENTRIES * 3] = { 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xc7, 0x34, 0xff, @@ -65,7 +65,7 @@ const byte colorPalette[COLOR_PALETTE_ENTRIES * 3] = { // Green monochrome palette #define MONO_PALETTE_ENTRIES 2 -const byte monoPalette[MONO_PALETTE_ENTRIES * 3] = { +static const byte monoPalette[MONO_PALETTE_ENTRIES * 3] = { 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01 }; @@ -110,7 +110,7 @@ Display::Display() : _cursorPos(0), _showCursor(false) { - initGraphics(560, 384, true); + initGraphics(DISPLAY_WIDTH * 2, DISPLAY_HEIGHT * 2, true); _monochrome = !ConfMan.getBool("color"); _scanlines = ConfMan.getBool("scanlines"); -- cgit v1.2.3 From 165e333f4f3fbde90f83c6cd8fe587e89e7455d7 Mon Sep 17 00:00:00 2001 From: Walter van Niftrik Date: Sat, 5 Mar 2016 17:13:26 +0100 Subject: ADL: Implement half-pixel shift for monochrome --- engines/adl/display.cpp | 96 +++++++++++++++++++++++++++---------------------- 1 file changed, 53 insertions(+), 43 deletions(-) (limited to 'engines/adl/display.cpp') diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp index 235e42bb73..cc51e4ae7e 100644 --- a/engines/adl/display.cpp +++ b/engines/adl/display.cpp @@ -305,31 +305,7 @@ void Display::showScanlines(bool enable) { } } -static void copyEvenSurfaceRows(Graphics::Surface &surf) { - byte *src = (byte *)surf.getPixels(); - - for (uint y = 0; y < surf.h / 2; ++y) { - byte *dst = src + surf.pitch; - for (uint x = 0; x < surf.w; ++x) - dst[x] = ALTCOL(src[x]); - src += surf.pitch * 2; - } -} - -void Display::updateHiResSurface() { - byte *src = _frameBuf; - byte *dst = (byte *)_frameBufSurface->getPixels(); - - for (uint i = 0; i < DISPLAY_HEIGHT; ++i) { - decodeScanline(dst, _frameBufSurface->pitch, src); - src += DISPLAY_PITCH; - dst += _frameBufSurface->pitch * 2; - } - - copyEvenSurfaceRows(*_frameBufSurface); -} - -static inline byte processColorBits(uint16 &bits, bool &odd, bool secondPal) { +static byte processColorBits(uint16 &bits, bool &odd, bool secondPal) { byte color = 0; switch (bits & 0x7) { @@ -354,7 +330,7 @@ static inline byte processColorBits(uint16 &bits, bool &odd, bool secondPal) { return color; } -void Display::decodeScanlineColor(byte *dst, int pitch, byte *src) const { +static void renderPixelRowColor(byte *dst, byte *src) { uint16 bits = (src[0] & 0x7f) << 1; byte pal = src[0] >> 7; @@ -400,31 +376,65 @@ void Display::decodeScanlineColor(byte *dst, int pitch, byte *src) const { } } -void Display::decodeScanlineMono(byte *dst, int pitch, byte *src) const { - // TODO: shift secondPal by half a pixel +static void renderPixelRowMono(byte *dst, byte *src) { + byte pal = src[0] >> 7; - for (uint j = 0; j < 39; ++j) { - for (uint k = 0; k < 7; ++k) { - byte color = 0; + if (pal != 0) + *dst++ = 0; + + for (uint i = 0; i < DISPLAY_PITCH; ++i) { + if (i != DISPLAY_PITCH - 1) + pal |= (src[i + 1] >> 7) << 1; + + for (uint j = 0; j < 6; ++j) { + bool color = src[i] & (1 << j); + *dst++ = color; + *dst++ = color; + } - if (src[j] & (1 << k)) - color = 1; + bool color = src[i] & (1 << 6); - dst[0] = color; - dst[1] = color; - dst[pitch] = color + 6; - dst[pitch + 1] = color + 6; + *dst++ = color; - dst += 2; + switch (pal) { + case 0x0: + case 0x3: + *dst++ = color; + break; + case 0x2: + *dst++ = color; + *dst++ = color; } + + pal >>= 1; } } -void Display::decodeScanline(byte *dst, int pitch, byte *src) const { - if (_monochrome) - decodeScanlineMono(dst, pitch, src); - else - decodeScanlineColor(dst, pitch, src); +static void copyEvenSurfaceRows(Graphics::Surface &surf) { + byte *src = (byte *)surf.getPixels(); + + for (uint y = 0; y < surf.h / 2; ++y) { + byte *dst = src + surf.pitch; + for (uint x = 0; x < surf.w; ++x) + dst[x] = ALTCOL(src[x]); + src += surf.pitch * 2; + } +} + +void Display::updateHiResSurface() { + byte *src = _frameBuf; + byte *dst = (byte *)_frameBufSurface->getPixels(); + + for (uint i = 0; i < DISPLAY_HEIGHT; ++i) { + if (_monochrome) + renderPixelRowMono(dst, src); + else + renderPixelRowColor(dst, src); + src += DISPLAY_PITCH; + dst += _frameBufSurface->pitch * 2; + } + + copyEvenSurfaceRows(*_frameBufSurface); } void Display::updateTextSurface() { -- cgit v1.2.3 From af42795ffa9331a16c1c6fa819f5c3960fd3cfe1 Mon Sep 17 00:00:00 2001 From: Walter van Niftrik Date: Sun, 6 Mar 2016 11:58:21 +0100 Subject: ADL: Improve error messages --- engines/adl/display.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'engines/adl/display.cpp') diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp index cc51e4ae7e..7af6f660fd 100644 --- a/engines/adl/display.cpp +++ b/engines/adl/display.cpp @@ -213,6 +213,9 @@ void Display::loadFrameBuffer(Common::ReadStream &stream) { } dst -= DISPLAY_PITCH * 63; } + + if (stream.eos() || stream.err()) + error("Failed to read frame buffer"); } void Display::putPixel(const Common::Point &p, byte color) { -- cgit v1.2.3 From 86d58534e7138c7b58995e1f730c8531ca2d4273 Mon Sep 17 00:00:00 2001 From: Walter van Niftrik Date: Mon, 7 Mar 2016 15:26:01 +0100 Subject: ADL: Move ASCII print function into Display class --- engines/adl/display.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'engines/adl/display.cpp') diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp index 7af6f660fd..d48296e9ee 100644 --- a/engines/adl/display.cpp +++ b/engines/adl/display.cpp @@ -289,6 +289,16 @@ void Display::printString(const Common::String &str) { updateTextScreen(); } +void Display::printAsciiString(const Common::String &str) { + Common::String aStr; + + Common::String::const_iterator it; + for (it = str.begin(); it != str.end(); ++it) + aStr += APPLECHAR(*it); + + printString(aStr); +} + void Display::setCharAtCursor(byte c) { _textBuf[_cursorPos] = c; } -- cgit v1.2.3 From d01da596ef596883847d6c3da2b714367e314a06 Mon Sep 17 00:00:00 2001 From: Walter van Niftrik Date: Tue, 8 Mar 2016 11:16:16 +0100 Subject: ADL: Add note about font --- engines/adl/display.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines/adl/display.cpp') diff --git a/engines/adl/display.cpp b/engines/adl/display.cpp index d48296e9ee..6342504bc3 100644 --- a/engines/adl/display.cpp +++ b/engines/adl/display.cpp @@ -70,6 +70,7 @@ static const byte monoPalette[MONO_PALETTE_ENTRIES * 3] = { 0x00, 0xc0, 0x01 }; +// Uppercase-only Apple II font (manually created). static const byte font[64][5] = { { 0x7c, 0x82, 0xba, 0xb2, 0x9c }, { 0xf8, 0x24, 0x22, 0x24, 0xf8 }, // @A { 0xfe, 0x92, 0x92, 0x92, 0x6c }, { 0x7c, 0x82, 0x82, 0x82, 0x44 }, // BC -- cgit v1.2.3