diff options
-rw-r--r-- | engines/startrek/bitmap.cpp | 55 | ||||
-rw-r--r-- | engines/startrek/bitmap.h | 34 | ||||
-rwxr-xr-x | engines/startrek/font.cpp | 4 | ||||
-rwxr-xr-x | engines/startrek/font.h | 2 | ||||
-rwxr-xr-x | engines/startrek/graphics.cpp | 216 | ||||
-rwxr-xr-x | engines/startrek/graphics.h | 20 | ||||
-rwxr-xr-x | engines/startrek/module.mk | 1 | ||||
-rwxr-xr-x | engines/startrek/startrek.cpp | 3 |
8 files changed, 259 insertions, 76 deletions
diff --git a/engines/startrek/bitmap.cpp b/engines/startrek/bitmap.cpp new file mode 100644 index 0000000000..43aee81487 --- /dev/null +++ b/engines/startrek/bitmap.cpp @@ -0,0 +1,55 @@ +/* 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 "startrek/bitmap.h" +#include "startrek/startrek.h" + +namespace StarTrek { + +Bitmap::Bitmap(Common::ReadStreamEndian *stream) { + xoffset = stream->readUint16(); + yoffset = stream->readUint16(); + width = stream->readUint16(); + height = stream->readUint16(); + + pixels = new byte[width*height]; + stream->read(pixels, width*height); +} + +Bitmap::Bitmap(int w, int h) : width(w), height(h), xoffset(0), yoffset(0) { + pixels = new byte[width*height]; +} + +Bitmap::~Bitmap() { + delete[] pixels; +} + + +TextBitmap::TextBitmap(int w, int h) { + width = w; + height = h; + // Width and Height are the total dimensions. Since each character takes 8 pixels in + // each dimension, the "pixels" array (which actually stores character indices) must + // be smaller. + pixels = new byte[width/8*height/8]; +} + +} diff --git a/engines/startrek/bitmap.h b/engines/startrek/bitmap.h new file mode 100644 index 0000000000..d30aee1e79 --- /dev/null +++ b/engines/startrek/bitmap.h @@ -0,0 +1,34 @@ +#ifndef STARTREK_BITMAP_H +#define STARTREK_BITMAP_H + +#include "common/stream.h" + +namespace StarTrek { + +struct Bitmap { + uint16 xoffset; + uint16 yoffset; + uint16 width; + uint16 height; + byte *pixels; + + Bitmap(Common::ReadStreamEndian *stream); + Bitmap(int w, int h); + ~Bitmap(); + +protected: + Bitmap() : xoffset(0),yoffset(0),width(0),height(0),pixels(nullptr) {} +}; + + +// TextBitmap is the same as Bitmap, except it stores character indices in its "pixels" +// array instead of actual pixels. +// A consequence of this is that the pixels array is smaller than otherwise expected +// (since width/height still reflect the actual size when drawn). +struct TextBitmap : Bitmap { + TextBitmap(int w, int h); +}; + +} + +#endif diff --git a/engines/startrek/font.cpp b/engines/startrek/font.cpp index 157c9848f2..a6f583a312 100755 --- a/engines/startrek/font.cpp +++ b/engines/startrek/font.cpp @@ -66,4 +66,8 @@ Font::~Font() { delete[] _characters; } +byte *Font::getCharData(int i) { + return _characters[i].data; +} + } diff --git a/engines/startrek/font.h b/engines/startrek/font.h index 857c98e8e6..62a354c10a 100755 --- a/engines/startrek/font.h +++ b/engines/startrek/font.h @@ -36,6 +36,8 @@ class Font { public: Font(StarTrekEngine *vm); ~Font(); + + byte *getCharData(int i); private: StarTrekEngine *_vm; diff --git a/engines/startrek/graphics.cpp b/engines/startrek/graphics.cpp index acedd72ea1..c597568614 100755 --- a/engines/startrek/graphics.cpp +++ b/engines/startrek/graphics.cpp @@ -17,10 +17,6 @@ * 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. - * - * $URL: https://scummvm-startrek.googlecode.com/svn/trunk/graphics.cpp $ - * $Id: graphics.cpp 14 2010-05-26 15:44:12Z clone2727 $ - * */ #include "startrek/graphics.h" @@ -31,33 +27,14 @@ namespace StarTrek { -// Bitmap class - -Bitmap::Bitmap(Common::ReadStreamEndian *stream) { - xoffset = stream->readUint16(); - yoffset = stream->readUint16(); - width = stream->readUint16(); - height = stream->readUint16(); - - pixels = (byte*)malloc(width*height); - stream->read(pixels, width*height); -} - -Bitmap::Bitmap(int w, int h) : width(w), height(h) { - pixels = (byte*)malloc(width*height); -} - -Bitmap::~Bitmap() { - free(pixels); -} - +Graphics::Graphics(StarTrekEngine *vm) : _vm(vm), _egaMode(false) { + _font = nullptr; -// Graphics class + _egaData = nullptr; + _priData = nullptr; + _lutData = nullptr; -Graphics::Graphics(StarTrekEngine *vm) : _vm(vm), _egaMode(false) { - _font = 0; - _egaData = 0; - _priData = 0; + _screenRect = Common::Rect(SCREEN_WIDTH, SCREEN_HEIGHT); if (ConfMan.hasKey("render_mode")) _egaMode = (Common::parseRenderMode(ConfMan.get("render_mode").c_str()) == Common::kRenderEGA) && (_vm->getGameType() != GType_STJR) && !(_vm->getFeatures() & GF_DEMO); @@ -70,20 +47,21 @@ Graphics::Graphics(StarTrekEngine *vm) : _vm(vm), _egaMode(false) { } Graphics::~Graphics() { - if (_egaData) - free(_egaData); - if (_priData) - free(_priData); + delete[] _egaData; + delete[] _priData; + delete[] _lutData; delete _font; delete _backgroundImage; delete _canvas; } -void Graphics::loadPalette(const char *paletteFile) { +void Graphics::loadPalette(const Common::String &paletteName) { // Set the palette from a PAL file + Common::String palFile = paletteName + ".PAL"; + Common::String lutFile = paletteName + ".LUT"; - Common::SeekableReadStream *palStream = _vm->openFile(paletteFile); + Common::SeekableReadStream *palStream = _vm->openFile(palFile.c_str()); byte *palette = new byte[256 * 3]; palStream->read(palette, 256 * 3); @@ -96,13 +74,22 @@ void Graphics::loadPalette(const char *paletteFile) { delete[] palette; delete palStream; + + // Load LUT file + Common::SeekableReadStream *lutStream = _vm->openFile(lutFile.c_str()); + + delete[] _lutData; + _lutData = new byte[256]; + lutStream->read(_lutData, 256); + + delete lutStream; } void Graphics::loadPri(const char *priFile) { Common::SeekableReadStream *priStream = _vm->openFile(priFile); - free(_priData); - _priData = (byte*)malloc(SCREEN_WIDTH*SCREEN_HEIGHT/2); + delete[] _priData; + _priData = new byte[SCREEN_WIDTH*SCREEN_HEIGHT/2]; priStream->read(_priData, SCREEN_WIDTH*SCREEN_HEIGHT/2); } @@ -110,70 +97,177 @@ void Graphics::redrawScreen() { // TODO: get rid of _canvas for efficiency memcpy(_canvas->pixels, _backgroundImage->pixels, SCREEN_WIDTH*SCREEN_HEIGHT); - // drawSprite test + // drawSprite tests + + // Draw mode 0 Sprite spr; memset(&spr,0,sizeof(Sprite)); spr.bitmap = new Bitmap(_vm->openFile("MWALKE00.BMP")); spr.drawPriority = 1; spr.drawX = 150; spr.drawY = 30; + spr.drawMode = 0; + drawSprite(spr); + + // Draw mode 2 (translucent background) + memset(&spr,0,sizeof(Sprite)); + spr.bitmap = new Bitmap(_vm->openFile("KWALKS00.BMP")); + spr.drawPriority = 1; + spr.drawX = 200; + spr.drawY = 40; + spr.drawMode = 2; + drawSprite(spr); - drawSprite(spr, Common::Rect(spr.drawX,spr.drawY,spr.drawX+spr.bitmap->width,spr.drawY+spr.bitmap->height)); + // Draw mode 3 (text) + memset(&spr,0,sizeof(Sprite)); + spr.bitmap = new Bitmap(8*8,8*8); + for (int i=0;i<8*8;i++) + spr.bitmap->pixels[i] = 0x40+i; + spr.drawX = 8*10; + spr.drawY = 50; + spr.textColor = 0xb3; + spr.drawMode = 3; + drawSprite(spr); drawBitmapToScreen(_canvas); } -// rect is the rectangle on-screen to draw. It should encompass the sprite itself, but if -// it doesn't, part of the sprite will be cut off. +void Graphics::drawSprite(const Sprite &sprite) { + drawSprite(sprite, Common::Rect(sprite.drawX,sprite.drawY,sprite.drawX+sprite.bitmap->width-1,sprite.drawY+sprite.bitmap->height-1)); +} + +// rect is the portion of the sprite to update. It must be entirely contained within the +// sprite's actual, full rectangle. void Graphics::drawSprite(const Sprite &sprite, const Common::Rect &rect) { - int drawWidth = rect.right - rect.left; - int drawHeight = rect.bottom - rect.top; + Common::Rect spriteRect = Common::Rect(sprite.drawX, sprite.drawY, + sprite.drawX+sprite.bitmap->width-1, sprite.drawY+sprite.bitmap->height-1); - if (drawWidth <= 0 || drawHeight <= 0) - error("drawSprite: w/h <= 0"); - + assert(_screenRect.contains(rect)); + assert(spriteRect.contains(rect)); byte *dest = _canvas->pixels + rect.top*SCREEN_WIDTH + rect.left; - int canvasOffsetToNextLine = SCREEN_WIDTH - drawWidth; switch(sprite.drawMode) { case 0: { // Normal sprite byte *src = sprite.bitmap->pixels + (rect.left - sprite.drawX) + (rect.top - sprite.drawY) * sprite.bitmap->width; - int spriteOffsetToNextLine = sprite.bitmap->width - drawWidth; int priOffset = rect.top*SCREEN_WIDTH + rect.left; for (int y=rect.top; y<rect.bottom; y++) { for (int x=rect.left; x<rect.right; x++) { byte priByte = _priData[priOffset/2]; - byte bgPri; + byte bgPriority; if ((priOffset%2) == 1) - bgPri = (priByte)&0xf; + bgPriority = priByte&0xf; else - bgPri = (priByte)>>4; + bgPriority = priByte>>4; priOffset++; byte b = *src++; - if (b == 0 || sprite.drawPriority < bgPri) { + if (b == 0 || sprite.drawPriority < bgPriority) { dest++; continue; } *dest++ = b; } - src += spriteOffsetToNextLine; - dest += canvasOffsetToNextLine; - priOffset += canvasOffsetToNextLine; + src += sprite.bitmap->width - rect.width(); + dest += SCREEN_WIDTH - rect.width(); + priOffset += SCREEN_WIDTH - rect.width(); + } + break; + } + + case 1: // Invisible + break; + + case 2: { // Normal sprite with darkened background for "transparent" pixels (and no priority) + byte *src = sprite.bitmap->pixels + (rect.left - sprite.drawX) + + (rect.top - sprite.drawY) * sprite.bitmap->width; + + for (int y=rect.top; y<rect.bottom; y++) { + for (int x=rect.left; x<rect.right; x++) { + byte b = *src; + + if (b == 0) // Transparent (darken the pixel) + *dest = _lutData[*dest]; + else // Solid color + *dest = b; + + src++; + dest++; + } + + src += sprite.bitmap->width - rect.width(); + dest += SCREEN_WIDTH - rect.width(); + } + + break; + } + + case 3: { // Text + // The sprite's "bitmap" is not actually a bitmap, but instead the list of + // characters to display. + + Common::Rect rectangle1; + + rectangle1.left = (rect.left - sprite.drawX)/8; + rectangle1.top = (rect.top - sprite.drawY)/8; + rectangle1.right = (rect.right - sprite.drawX)/8; + rectangle1.bottom = (rect.bottom - sprite.drawY)/8; + + int drawWidth = rectangle1.width() + 1; + int drawHeight = rectangle1.height() + 1; + + dest =_canvas->pixels + sprite.drawY*SCREEN_WIDTH + sprite.drawX + + rectangle1.top*8*SCREEN_WIDTH + rectangle1.left*8; + + byte *src = sprite.bitmap->pixels + rectangle1.top*sprite.bitmap->width/8 + rectangle1.left; + + for (int y=0; y<drawHeight; y++) { + for (int x=0; x<drawWidth; x++) { + byte c = *src; + + int textColor; + if (c >= 0x10 && c <= 0x1A) // Border characters + textColor = 0xb3; + else + textColor = sprite.textColor; + + byte *fontData = _font->getCharData(c); + + for (int i=0;i<8;i++) { + for (int j=0;j<8;j++) { + byte b = *fontData; + + if (b == 0) // Transparent: use lookup table to darken this pixel + *dest = _lutData[*dest]; + else if (b == 0x78) // Inner part of character + *dest = textColor; + else // Outline of character + *dest = b; + + fontData++; + dest++; + } + dest += SCREEN_WIDTH - 8; + } + + dest -= (SCREEN_WIDTH*8 - 8); + src++; + } + + src += sprite.bitmap->width/8 - drawWidth; + dest += SCREEN_WIDTH*8 - drawWidth*8; + } + break; } - case 1: - case 2: - case 3: default: - error("drawSprite: draw mode %d not implemented", sprite.drawMode); + error("drawSprite: draw mode %d invalid", sprite.drawMode); break; } } @@ -185,7 +279,7 @@ void Graphics::loadEGAData(const char *filename) { return; if (!_egaData) - _egaData = (byte *)malloc(256); + _egaData = new byte[256]; Common::SeekableReadStream *egaStream = _vm->openFile(filename); egaStream->read(_egaData, 256); @@ -208,7 +302,7 @@ void Graphics::drawBackgroundImage(const char *filename) { uint16 width = imageStream->readUint16LE(); uint16 height = imageStream->readUint16LE(); - byte *pixels = (byte *)malloc(width * height); + byte *pixels = new byte[width * height]; imageStream->read(pixels, width * height); _vm->_system->getPaletteManager()->setPalette(palette, 0, 256); diff --git a/engines/startrek/graphics.h b/engines/startrek/graphics.h index a2d9f4fa1c..884f7edde0 100755 --- a/engines/startrek/graphics.h +++ b/engines/startrek/graphics.h @@ -26,6 +26,7 @@ #ifndef STARTREK_GRAPHICS_H #define STARTREK_GRAPHICS_H +#include "startrek/bitmap.h" #include "startrek/startrek.h" #include "startrek/font.h" @@ -42,18 +43,6 @@ const int SCREEN_WIDTH = 320; const int SCREEN_HEIGHT = 200; -struct Bitmap { - uint16 xoffset; - uint16 yoffset; - uint16 width; - uint16 height; - byte *pixels; - - Bitmap(Common::ReadStreamEndian *stream); - Bitmap(int w, int h); - ~Bitmap(); -}; - struct Sprite { uint16 x,y; uint16 drawPriority; @@ -61,7 +50,7 @@ struct Sprite { uint16 field8; Bitmap *bitmap; uint16 drawMode; - uint16 fieldE; + uint16 textColor; uint16 bitmapChanged; uint16 redrawCondition2; uint16 redrawCondition3; @@ -78,10 +67,11 @@ public: Graphics(StarTrekEngine *vm); ~Graphics(); - void loadPalette(const char *paletteFile); + void loadPalette(const Common::String &paletteFile); void loadPri(const char *priFile); void redrawScreen(); + void drawSprite(const Sprite &sprite); void drawSprite(const Sprite &sprite, const Common::Rect &rect); void loadEGAData(const char *egaFile); @@ -98,7 +88,9 @@ private: bool _egaMode; byte *_egaData; byte *_priData; + byte *_lutData; + Common::Rect _screenRect; Bitmap *_backgroundImage; Bitmap *_canvas; }; diff --git a/engines/startrek/module.mk b/engines/startrek/module.mk index 0b95d7dc14..c47c19a3b0 100755 --- a/engines/startrek/module.mk +++ b/engines/startrek/module.mk @@ -1,6 +1,7 @@ MODULE := engines/startrek MODULE_OBJS = \ + bitmap.o \ detection.o \ filestream.o \ font.o \ diff --git a/engines/startrek/startrek.cpp b/engines/startrek/startrek.cpp index f007301ed2..55cd646a6b 100755 --- a/engines/startrek/startrek.cpp +++ b/engines/startrek/startrek.cpp @@ -88,7 +88,7 @@ Common::Error StarTrekEngine::run() { // EGA not supported #if 1 if (getGameType() == GType_ST25) { - _gfx->loadPalette("PALETTE.PAL"); + _gfx->loadPalette("PALETTE"); _gfx->loadPri("DEMON0.PRI"); _gfx->redrawScreen(); @@ -116,6 +116,7 @@ Common::Error StarTrekEngine::run() { break; } } + _system->updateScreen(); _system->delayMillis(1000/60); } |