aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Stewart2018-02-23 02:11:40 -0500
committerEugene Sandulenko2018-08-09 08:37:30 +0200
commitcd45502501787c8003cfd86b7adf48a6f86d68de (patch)
tree1d2a917fba484f3a5c7b4333ed290cb430bc3f92
parentc71a8a6d2acb3be145731e6af344cb16a38c6b46 (diff)
downloadscummvm-rg350-cd45502501787c8003cfd86b7adf48a6f86d68de.tar.gz
scummvm-rg350-cd45502501787c8003cfd86b7adf48a6f86d68de.tar.bz2
scummvm-rg350-cd45502501787c8003cfd86b7adf48a6f86d68de.zip
STARTREK: Implement draw modes 2 and 3 for sprites
-rw-r--r--engines/startrek/bitmap.cpp55
-rw-r--r--engines/startrek/bitmap.h34
-rwxr-xr-xengines/startrek/font.cpp4
-rwxr-xr-xengines/startrek/font.h2
-rwxr-xr-xengines/startrek/graphics.cpp216
-rwxr-xr-xengines/startrek/graphics.h20
-rwxr-xr-xengines/startrek/module.mk1
-rwxr-xr-xengines/startrek/startrek.cpp3
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);
}