aboutsummaryrefslogtreecommitdiff
path: root/kyra
diff options
context:
space:
mode:
authorGregory Montoir2005-08-31 20:14:20 +0000
committerGregory Montoir2005-08-31 20:14:20 +0000
commit288759abd26e5b6bb93429e331791ebeead668ab (patch)
treebd13516f996210b186bcb0699dd7f4d47b54728a /kyra
parente64b22f5bd47bffe2d9e4f1bbbd0a90b05d11ba4 (diff)
downloadscummvm-rg350-288759abd26e5b6bb93429e331791ebeead668ab.tar.gz
scummvm-rg350-288759abd26e5b6bb93429e331791ebeead668ab.tar.bz2
scummvm-rg350-288759abd26e5b6bb93429e331791ebeead668ab.zip
some WIP code, add drawShape()
svn-id: r18724
Diffstat (limited to 'kyra')
-rw-r--r--kyra/kyra.cpp104
-rw-r--r--kyra/kyra.h15
-rw-r--r--kyra/screen.cpp214
-rw-r--r--kyra/screen.h43
-rw-r--r--kyra/staticres.cpp22
5 files changed, 372 insertions, 26 deletions
diff --git a/kyra/kyra.cpp b/kyra/kyra.cpp
index 1df94805ad..250ad0986d 100644
--- a/kyra/kyra.cpp
+++ b/kyra/kyra.cpp
@@ -165,6 +165,9 @@ int KyraEngine::init(GameDetector &detector) {
_talkCoords.y = 0x88;
_talkCoords.x = 0;
_talkCoords.w = 0;
+ _talkMessageY = 0xC;
+ _talkMessageH = 0;
+ _talkMessagePrinted = false;
return 0;
}
@@ -185,10 +188,6 @@ int KyraEngine::go() {
return 0;
}
-void KyraEngine::setTalkCoords(uint16 y) {
- _talkCoords.y = y;
-}
-
void KyraEngine::loadBitmap(const char *filename, int tempPage, int dstPage, uint8 *palData) {
debug(9, "KyraEngine::copyBitmap('%s', %d, %d, 0x%X)", filename, tempPage, dstPage, palData);
uint32 fileSize;
@@ -218,14 +217,105 @@ void KyraEngine::loadBitmap(const char *filename, int tempPage, int dstPage, uin
delete[] srcData;
}
+void KyraEngine::setTalkCoords(uint16 y) {
+ debug(9, "KyraEngine::setTalkCoords(%d)", y);
+ _talkCoords.y = y;
+}
+
+int KyraEngine::getCenterStringX(const char *str, int x1, int x2) {
+ debug(9, "KyraEngine::getCenterStringX('%s', %d, %d)", str, x1, x2);
+ warning("KyraEngine::getCenterStringX() UNIMPLEMENTED");
+ return 0;
+}
+
+int KyraEngine::getCharLength(const char *str, int len) {
+ debug(9, "KyraEngine::preprocessString('%s', %d)", str, len);
+ warning("KyraEngine::preprocessString() UNIMPLEMENTED");
+ return 0;
+}
+
+int KyraEngine::dropCRIntoString(char *str, int offs) {
+ debug(9, "KyraEngine::dropCRIntoString('%s', %d)", str, offs);
+ int pos = 0;
+ while (*str != '\0') {
+ if (*str == 0x20) {
+ *str = 0xD;
+ return pos;
+ }
+ ++str;
+ ++pos;
+ }
+ return 0;
+}
+
+char *KyraEngine::preprocessString(const char *str) {
+ debug(9, "KyraEngine::preprocessString('%s')", str);
+ warning("KyraEngine::preprocessString() UNIMPLEMENTED");
+ return 0;
+}
+
+int KyraEngine::buildMessageSubstrings(const char *str) {
+ debug(9, "KyraEngine::buildMessageSubstrings('%s')", str);
+ int currentLine = 0;
+ int pos = 0;
+ while (*str) {
+ if (*str == 0xD) {
+ _talkSubstrings[currentLine * 80 + pos] = 0;
+ ++currentLine;
+ pos = 0;
+ } else {
+ _talkSubstrings[currentLine * 80 + pos] = *str;
+ ++pos;
+ if (pos > 78) {
+ pos = 78;
+ }
+ }
+ ++str;
+ }
+ _talkSubstrings[currentLine * 80 + pos] = '\0';
+ return currentLine + 1;
+}
+
+int KyraEngine::getWidestLineWidth(int linesCount) {
+ debug(9, "KyraEngine::getWidestLineWidth(%d)", linesCount);
+ warning("KyraEngine::getWidestLineWidth() UNIMPLEMENTED");
+ return 0;
+}
+
+void KyraEngine::calcWidestLineBounds(int &x1, int &x2, int w, int cx) {
+ debug(9, "KyraEngine::calcWidestLineBounds(%d, %d)", w, cx);
+ x1 = cx - w / 2;
+ if (x1 + w >= Screen::SCREEN_W - 12) {
+ x1 = Screen::SCREEN_W - 12 - w - 1;
+ } else if (x1 < 12) {
+ x1 = 12;
+ }
+ x2 = x1 + w + 1;
+}
+
void KyraEngine::restoreTalkTextMessageBkgd(int srcPage, int dstPage) {
- debug(9, "KyraEngine::printTalkTextMessage(%d, %d)", srcPage, dstPage);
- warning("KyraEngine::restoreTalkTextMessageBkgd() UNIMPLEMENTED");
+ debug(9, "KyraEngine::restoreTalkTextMessageBkgd(%d, %d)", srcPage, dstPage);
+ if (_talkMessagePrinted) {
+ _talkMessagePrinted = false;
+ _screen->copyRegion(_talkCoords.x, _talkCoords.y, _talkCoords.x, _talkMessageY, _talkCoords.w, _talkMessageH, srcPage, dstPage);
+ }
}
void KyraEngine::printTalkTextMessage(const char *text, int x, int y, uint8 color, int srcPage, int dstPage) {
debug(9, "KyraEngine::printTalkTextMessage('%s', %d, %d, %d, %d, %d)", text, x, y, color, srcPage, dstPage);
warning("KyraEngine::printTalkTextMessage() UNIMPLEMENTED");
+ _talkMessagePrinted = true;
+}
+
+void KyraEngine::printText(const char *str, int x, int y, uint8 c0, uint8 c1, uint8 c2) {
+ uint8 colorMap[] = { 0, 15, 12, 12 };
+ colorMap[3] = c1;
+ _screen->setTextColor(colorMap, 0, 3);
+// const uint8 *currentFont = _screen->setupFont(_res->_8fat_fnt);
+ _screen->_charWidth = -2;
+ _screen->printText(str, x, y, c0, c2);
+ _screen->_charWidth = 0;
+// _screen->setupFont(currentFont);
}
void KyraEngine::waitTicks(int ticks) {
@@ -385,6 +475,7 @@ void KyraEngine::seq_copyView() {
}
bool KyraEngine::seq_skipSequence() const {
+ debug(9, "KyraEngine::seq_skipSequence()");
return _quitFlag;
}
@@ -580,7 +671,6 @@ bool KyraEngine::seq_playSpecialSequence(const uint8 *seqData, bool skipSeq) {
displayedTextX = (Screen::SCREEN_W - _screen->getTextWidth(str)) / 2;
}
}
- warning("Sequence opcode 15 skipped");
break;
case 16: {
uint8 txt = *seqData++;
diff --git a/kyra/kyra.h b/kyra/kyra.h
index 457b460bb1..7634242a82 100644
--- a/kyra/kyra.h
+++ b/kyra/kyra.h
@@ -77,10 +77,19 @@ protected:
int go();
int init(GameDetector &detector);
- void setTalkCoords(uint16 y);
void loadBitmap(const char *filename, int tempPage, int dstPage, uint8 *palData);
+
+ void setTalkCoords(uint16 y);
+ int getCenterStringX(const char *str, int x1, int x2);
+ int getCharLength(const char *str, int len);
+ int dropCRIntoString(char *str, int offs);
+ char *preprocessString(const char *str);
+ int buildMessageSubstrings(const char *str);
+ int getWidestLineWidth(int linesCount);
+ void calcWidestLineBounds(int &x1, int &x2, int w, int cx);
void restoreTalkTextMessageBkgd(int srcPage, int dstPage);
void printTalkTextMessage(const char *text, int x, int y, uint8 color, int srcPage, int dstPage);
+ void printText(const char *str, int x, int y, uint8 c0, uint8 c1, uint8 c2);
void waitTicks(int ticks);
void seq_intro();
@@ -102,7 +111,11 @@ protected:
bool _fastMode;
bool _quitFlag;
bool _skipIntroFlag;
+ char _talkSubstrings[80 * 3];
TalkCoords _talkCoords;
+ uint16 _talkMessageY;
+ uint16 _talkMessageH;
+ bool _talkMessagePrinted;
int _seq_copyViewOffs;
uint8 *_seq_handShapes[3];
diff --git a/kyra/screen.cpp b/kyra/screen.cpp
index 6edd357388..4171bb65c1 100644
--- a/kyra/screen.cpp
+++ b/kyra/screen.cpp
@@ -29,21 +29,23 @@ namespace Kyra {
Screen::Screen(KyraEngine *vm, OSystem *system)
: _system(system), _vm(vm) {
_curPage = 0;
- for (int pageNum = 0; pageNum < KYRA_PAGE_NUM; pageNum += 2) {
- uint8 *pagePtr = (uint8 *)malloc(KYRA_PAGE_SIZE);
+ for (int pageNum = 0; pageNum < SCREEN_PAGE_NUM; pageNum += 2) {
+ uint8 *pagePtr = (uint8 *)malloc(SCREEN_PAGE_SIZE);
if (pagePtr) {
- memset(pagePtr, 0, KYRA_PAGE_SIZE);
+ memset(pagePtr, 0, SCREEN_PAGE_SIZE);
_pagePtrs[pageNum] = _pagePtrs[pageNum + 1] = pagePtr;
}
}
_palette1 = (uint8 *)malloc(768);
- if (_palette1) {
- memset(_palette1, 0, 768);
- }
+ _palette3 = (uint8 *)malloc(768);
+ _fadePalette = (uint8 *)malloc(768);
+ _curDim = &_screenDimTable[0];
+ _decodeShapeBuffer = NULL;
+ _decodeShapeBufferSize = 0;
}
Screen::~Screen() {
- for (int pageNum = 0; pageNum < KYRA_PAGE_NUM; pageNum += 2) {
+ for (int pageNum = 0; pageNum < SCREEN_PAGE_NUM; pageNum += 2) {
free(_pagePtrs[pageNum]);
_pagePtrs[pageNum] = _pagePtrs[pageNum + 1] = 0;
}
@@ -58,14 +60,14 @@ void Screen::updateScreen() {
uint8 *Screen::getPagePtr(int pageNum) {
debug(9, "Screen::getPagePtr(%d)", pageNum);
- assert(pageNum < KYRA_PAGE_NUM);
+ assert(pageNum < SCREEN_PAGE_NUM);
return _pagePtrs[pageNum];
}
void Screen::clearPage(int pageNum) {
debug(9, "Screen::clearPage(%d)", pageNum);
- assert(pageNum < KYRA_PAGE_NUM);
- memset(getPagePtr(pageNum), 0, KYRA_PAGE_SIZE);
+ assert(pageNum < SCREEN_PAGE_NUM);
+ memset(getPagePtr(pageNum), 0, SCREEN_PAGE_SIZE);
}
int Screen::setCurPage(int pageNum) {
@@ -77,11 +79,12 @@ int Screen::setCurPage(int pageNum) {
void Screen::clearCurPage() {
debug(9, "Screen::clearCurPage()");
- memset(getPagePtr(_curPage), 0, KYRA_PAGE_SIZE);
+ memset(getPagePtr(_curPage), 0, SCREEN_PAGE_SIZE);
}
void Screen::fadeFromBlack() {
debug(9, "Screen::fadeFromBlack()");
+ memset(_palette3, 0, 768);
setScreenPalette(_palette1);
warning("Screen::fadeFromBlack() UNIMPLEMENTED");
}
@@ -191,9 +194,194 @@ void Screen::printText(const char *str, int x, int y, uint8 color1, uint8 color2
warning("Screen::printText() UNIMPLEMENTED");
}
+void Screen::setScreenDim(int dim) {
+ debug(9, "setScreenDim(%d)", dim);
+ _curDim = &_screenDimTable[dim];
+ // XXX
+}
+
+void Screen::drawShapePlotPixelCallback1(uint8 *dst, uint8 color) {
+ debug(9, "Screen::drawShapePlotPixelCallback1(0x%X, %d)", dst, color);
+ *dst = color;
+}
+
void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int sd, int flags, int *flagsTable) {
debug(9, "Screen::drawShape(%d, %d, %d, %d, %d)", pageNum, x, y, sd, flags);
- warning("Screen::drawShape() UNIMPLEMENTED");
+ assert(shapeData);
+ if (flags & 0x8000) {
+ warning("unhandled (flags & 0x8000) in Video::drawShape()");
+ }
+ if (flags & 0x100) {
+ warning("unhandled (flags & 0x100) in Video::drawShape()");
+ }
+ if (flags & 0x1000) {
+ warning("unhandled (flags & 0x1000) in Video::drawShape()");
+ }
+ if (flags & 0x200) {
+ warning("unhandled (flags & 0x200) in Video::drawShape()");
+ }
+ if (flags & 0x4000) {
+ warning("unhandled (flags & 0x4000) in Video::drawShape()");
+ }
+ if (flags & 0x800) {
+ warning("unhandled (flags & 0x800) in Video::drawShape()");
+ }
+ int scale_w, scale_h;
+ if (flags & DSF_SCALE) {
+ scale_w = *flagsTable++;
+ scale_h = *flagsTable++;
+ } else {
+ scale_w = 0x100;
+ scale_h = 0x100;
+ }
+
+ int ppc = (flags >> 8) & 0x3F;
+ assert(ppc < _drawShapePlotPixelCount);
+ DrawShapePlotPixelCallback plotPixel = _drawShapePlotPixelTable[ppc];
+
+ const uint8 *src = shapeData;
+ uint16 shapeFlags = READ_LE_UINT16(src); src += 2;
+
+ int shapeHeight = *src++;
+ int scaledShapeHeight = (shapeHeight * scale_h) >> 8;
+ if (scaledShapeHeight == 0) {
+ return;
+ }
+
+ int shapeWidth = READ_LE_UINT16(src); src += 2;
+ int scaledShapeWidth = (shapeWidth * scale_w) >> 8;
+ if (scaledShapeWidth == 0) {
+ return;
+ }
+
+ if (flags & DSF_CENTER) {
+ x -= scaledShapeWidth >> 1;
+ y -= scaledShapeHeight >> 1;
+ }
+
+ src += 3;
+
+ uint16 frameSize = READ_LE_UINT16(src); src += 2;
+ if ((shapeFlags & 1) || (flags & 0x400)) {
+ src += 0x10;
+ }
+ if (!(shapeFlags & 2)) {
+ decodeFrame4(src, _animBlockPtr, frameSize);
+ src = _animBlockPtr;
+ }
+
+ int shapeSize = shapeWidth * shapeHeight;
+ if (_decodeShapeBufferSize < shapeSize) {
+ free(_decodeShapeBuffer);
+ _decodeShapeBuffer = (uint8 *)malloc(shapeSize);
+ _decodeShapeBufferSize = shapeSize;
+ }
+ if (!_decodeShapeBuffer) {
+ _decodeShapeBufferSize = 0;
+ return;
+ }
+ memset(_decodeShapeBuffer, 0, _decodeShapeBufferSize);
+ uint8 *decodedShapeFrame = _decodeShapeBuffer;
+ for (int j = 0; j < shapeHeight; ++j) {
+ uint8 *dsbNextLine = decodedShapeFrame + shapeWidth;
+ int count = shapeWidth;
+ while (count > 0) {
+ uint8 code = *src++;
+ if (code != 0) {
+ *decodedShapeFrame++ = code;
+ --count;
+ } else {
+ code = *src++;
+ decodedShapeFrame += code;
+ count -= code;
+ }
+ }
+ decodedShapeFrame = dsbNextLine;
+ }
+
+ uint16 sx1 = _screenDimTable[sd].sx * 8;
+ uint16 sy1 = _screenDimTable[sd].sy;
+ uint16 sx2 = sx1 + _screenDimTable[sd].w * 8;
+ uint16 sy2 = sy1 + _screenDimTable[sd].h;
+ if (flags & DSF_WND_COORDS) {
+ x += sx1;
+ y += sy1;
+ }
+
+ int x1, x2;
+ if (x >= 0) {
+ x1 = 0;
+ if (x + scaledShapeWidth < sx2) {
+ x2 = scaledShapeWidth;
+ } else {
+ x2 = sx2 - x;
+ }
+ } else {
+ x2 = scaledShapeWidth;
+ x1 = -x;
+ x = 0;
+ if (x2 > sx2) {
+ x2 = sx2;
+ }
+ }
+
+ int y1, y2;
+ if (y >= 0) {
+ y1 = 0;
+ if (y + scaledShapeHeight < sy2) {
+ y2 = scaledShapeHeight;
+ } else {
+ y2 = sy2 - y;
+ }
+ } else {
+ y2 = scaledShapeHeight;
+ y1 = -y;
+ y = 0;
+ if (y2 > sy2) {
+ y2 = sy2;
+ }
+ }
+
+ uint8 *dst = getPagePtr(pageNum) + y * SCREEN_W + x;
+
+ int scaleYTable[SCREEN_H];
+ assert(y1 >= 0 && y2 < SCREEN_H);
+ for (y = y1; y < y2; ++y) {
+ scaleYTable[y] = (y << 8) / scale_h;
+ }
+ int scaleXTable[SCREEN_W];
+ assert(x1 >= 0 && x2 < SCREEN_W);
+ for (x = x1; x < x2; ++x) {
+ scaleXTable[x] = (x << 8) / scale_w;
+ }
+
+ const uint8 *shapeBuffer = _decodeShapeBuffer;
+ if (flags & DSF_Y_FLIPPED) {
+ shapeBuffer += shapeWidth * (shapeHeight - 1);
+ }
+ if (flags & DSF_X_FLIPPED) {
+ shapeBuffer += shapeWidth - 1;
+ }
+
+ for (y = y1; y < y2; ++y) {
+ uint8 *dstNextLine = dst + SCREEN_W;
+ int j = scaleYTable[y];
+ if (flags & DSF_Y_FLIPPED) {
+ j = -j;
+ }
+ for (x = x1; x < x2; ++x) {
+ int i = scaleXTable[x];
+ if (flags & DSF_X_FLIPPED) {
+ i = -i;
+ }
+ uint8 color = shapeBuffer[j * shapeWidth + i];
+ if (color != 0) {
+ (this->*plotPixel)(dst, color);
+ }
+ ++dst;
+ }
+ dst = dstNextLine;
+ }
}
void Screen::decodeFrame3(const uint8 *src, uint8 *dst, uint32 size) {
@@ -382,7 +570,7 @@ void Screen::decodeFrameDeltaPage(uint8 *dst, const uint8 *src, int pitch) {
*dst++ ^= *src++;
if (++count == pitch) {
count = 0;
- dstNext += 320;
+ dstNext += SCREEN_W;
dst = dstNext;
}
}
diff --git a/kyra/screen.h b/kyra/screen.h
index b6a54ec7b1..43fdae094c 100644
--- a/kyra/screen.h
+++ b/kyra/screen.h
@@ -1,5 +1,5 @@
/* ScummVM - Scumm Interpreter
- * Copyright (C) 2003-2005 The ScummVM project
+ * Copyright (C) 2004-2005 The ScummVM project
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -31,6 +31,17 @@ namespace Kyra {
class CPSImage;
class KyraEngine;
+struct ScreenDim {
+ uint16 sx;
+ uint16 sy;
+ uint16 w;
+ uint16 h;
+ uint16 unk8;
+ uint16 unkA;
+ uint16 unkC;
+ uint16 unkE;
+};
+
class Screen {
public:
@@ -55,6 +66,8 @@ public:
int getCharWidth(uint8 c) const;
int getTextWidth(const char *str) const;
void printText(const char *str, int x, int y, uint8 color1, uint8 color2);
+ void setScreenDim(int dim);
+ void drawShapePlotPixelCallback1(uint8 *dst, uint8 color);
void drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int sd, int flags, int *flagsTable);
static void decodeFrame3(const uint8 *src, uint8 *dst, uint32 size);
static void decodeFrame4(const uint8 *src, uint8 *dst, uint32 dstSize);
@@ -67,20 +80,40 @@ public:
uint8 *_palette1;
enum {
- SCREEN_W = 320,
- SCREEN_H = 200,
- KYRA_PAGE_SIZE = 320 * 200 + 1024,
- KYRA_PAGE_NUM = 16
+ SCREEN_W = 320,
+ SCREEN_H = 200,
+ SCREEN_PAGE_SIZE = 320 * 200 + 1024,
+ SCREEN_PAGE_NUM = 16
};
+ enum DrawShapeFlags {
+ DSF_X_FLIPPED = 0x01,
+ DSF_Y_FLIPPED = 0x02,
+ DSF_SCALE = 0x04,
+ DSF_WND_COORDS = 0x10,
+ DSF_CENTER = 0x20
+ };
+
+ typedef void (Screen::*DrawShapePlotPixelCallback)(uint8 *dst, uint8 c);
+
private:
uint8 _textColorsMap[16];
uint8 *_animBlockPtr;
int _animBlockSize;
uint8 *_pagePtrs[16];
+ uint8 *_palette3;
+ uint8 *_fadePalette;
+ const ScreenDim *_curDim;
+ uint8 *_decodeShapeBuffer;
+ int _decodeShapeBufferSize;
+
OSystem *_system;
KyraEngine *_vm;
+
+ static const ScreenDim _screenDimTable[];
+ static const DrawShapePlotPixelCallback _drawShapePlotPixelTable[];
+ static const int _drawShapePlotPixelCount;
};
} // End of namespace Kyra
diff --git a/kyra/staticres.cpp b/kyra/staticres.cpp
index ec4a1f0375..98774824a4 100644
--- a/kyra/staticres.cpp
+++ b/kyra/staticres.cpp
@@ -21,9 +21,31 @@
#include "common/stdafx.h"
#include "kyra/kyra.h"
+#include "kyra/screen.h"
namespace Kyra {
+const ScreenDim Screen::_screenDimTable[] = {
+ { 0x00, 0x00, 0x28, 0xC8, 0x0F, 0x0C, 0x00, 0x00 },
+ { 0x08, 0x48, 0x18, 0x38, 0x0F, 0x0C, 0x00, 0x00 },
+ { 0x01, 0x08, 0x26, 0x80, 0x0F, 0x0C, 0x00, 0x00 },
+ { 0x00, 0xC2, 0x28, 0x06, 0x0F, 0x0C, 0x00, 0x00 },
+ { 0x00, 0x90, 0x28, 0x38, 0x04, 0x0C, 0x00, 0x00 },
+ { 0x01, 0x94, 0x26, 0x30, 0x04, 0x1B, 0x00, 0x00 },
+ { 0x00, 0x90, 0x28, 0x38, 0x0F, 0x0D, 0x00, 0x00 },
+ { 0x01, 0x96, 0x26, 0x32, 0x0F, 0x0D, 0x00, 0x00 },
+ { 0x00, 0x00, 0x28, 0x88, 0x0F, 0x0C, 0x00, 0x00 },
+ { 0x01, 0x20, 0x26, 0x80, 0x0F, 0x0C, 0x00, 0x00 },
+ { 0x03, 0x28, 0x22, 0x46, 0x0F, 0x0D, 0x00, 0x00 }
+};
+
+const Screen::DrawShapePlotPixelCallback Screen::_drawShapePlotPixelTable[] = {
+ &Screen::drawShapePlotPixelCallback1
+ // XXX
+};
+
+const int Screen::_drawShapePlotPixelCount = ARRAYSIZE(_drawShapePlotPixelTable);
+
const uint8 KyraEngine::_seq_introData_Forest[] = {
0x00, 0x05, 0x01, 0x00, 0x07, 0x01, 0x1A, 0x02, 0x07, 0x00, 0x00, 0x00, 0x08, 0x02, 0x05, 0x00,
0x98, 0x00, 0x38, 0x0A, 0x00, 0x03, 0x07, 0x16, 0x02, 0x06, 0x09, 0x00, 0x0B, 0x00, 0x41, 0x00,