diff options
author | Gregory Montoir | 2005-08-31 20:14:20 +0000 |
---|---|---|
committer | Gregory Montoir | 2005-08-31 20:14:20 +0000 |
commit | 288759abd26e5b6bb93429e331791ebeead668ab (patch) | |
tree | bd13516f996210b186bcb0699dd7f4d47b54728a | |
parent | e64b22f5bd47bffe2d9e4f1bbbd0a90b05d11ba4 (diff) | |
download | scummvm-rg350-288759abd26e5b6bb93429e331791ebeead668ab.tar.gz scummvm-rg350-288759abd26e5b6bb93429e331791ebeead668ab.tar.bz2 scummvm-rg350-288759abd26e5b6bb93429e331791ebeead668ab.zip |
some WIP code, add drawShape()
svn-id: r18724
-rw-r--r-- | kyra/kyra.cpp | 104 | ||||
-rw-r--r-- | kyra/kyra.h | 15 | ||||
-rw-r--r-- | kyra/screen.cpp | 214 | ||||
-rw-r--r-- | kyra/screen.h | 43 | ||||
-rw-r--r-- | kyra/staticres.cpp | 22 |
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, |