SCI: Merge new GUI code written by m_kiewitz.

This is a major rewrite of the graphics code. A slightly adapted
version of the old code is still available and currently the default.
The new code is selectable in sci.cpp, but is not yet finished.

svn-id: r44565
This commit is contained in:
Willem Jan Palenstijn 2009-10-03 20:49:18 +00:00
parent f6de0b4ec9
commit b9cdb1abb7
35 changed files with 5702 additions and 625 deletions

View file

@ -92,6 +92,29 @@
<File RelativePath="..\..\engines\sci\gfx\seq_decoder.cpp" /> <File RelativePath="..\..\engines\sci\gfx\seq_decoder.cpp" />
<File RelativePath="..\..\engines\sci\gfx\seq_decoder.h" /> <File RelativePath="..\..\engines\sci\gfx\seq_decoder.h" />
</Filter> </Filter>
<Filter Name="gui">
<File RelativePath="..\..\engines\sci\gui\gui.cpp" />
<File RelativePath="..\..\engines\sci\gui\gui.h" />
<File RelativePath="..\..\engines\sci\gui\gui_dbllist.cpp" />
<File RelativePath="..\..\engines\sci\gui\gui_dbllist.h" />
<File RelativePath="..\..\engines\sci\gui\gui_font.cpp" />
<File RelativePath="..\..\engines\sci\gui\gui_font.h" />
<File RelativePath="..\..\engines\sci\gui\gui_gfx.cpp" />
<File RelativePath="..\..\engines\sci\gui\gui_gfx.h" />
<File RelativePath="..\..\engines\sci\gui\gui_helpers.h" />
<File RelativePath="..\..\engines\sci\gui\gui_memmgr.cpp" />
<File RelativePath="..\..\engines\sci\gui\gui_memmgr.h" />
<File RelativePath="..\..\engines\sci\gui\gui_picture.cpp" />
<File RelativePath="..\..\engines\sci\gui\gui_picture.h" />
<File RelativePath="..\..\engines\sci\gui\gui_screen.cpp" />
<File RelativePath="..\..\engines\sci\gui\gui_screen.h" />
<File RelativePath="..\..\engines\sci\gui\gui_view.cpp" />
<File RelativePath="..\..\engines\sci\gui\gui_view.h" />
<File RelativePath="..\..\engines\sci\gui\gui_windowmgr.cpp" />
<File RelativePath="..\..\engines\sci\gui\gui_windowmgr.h" />
<File RelativePath="..\..\engines\sci\gui32\gui32.h" />
<File RelativePath="..\..\engines\sci\gui32\gui32.cpp" />
</Filter>
<Filter Name="sfx"> <Filter Name="sfx">
<File RelativePath="..\..\engines\sci\sfx\core.cpp" /> <File RelativePath="..\..\engines\sci\sfx\core.cpp" />
<File RelativePath="..\..\engines\sci\sfx\core.h" /> <File RelativePath="..\..\engines\sci\sfx\core.h" />

View file

@ -93,6 +93,29 @@
<File RelativePath="..\..\engines\sci\gfx\seq_decoder.cpp" /> <File RelativePath="..\..\engines\sci\gfx\seq_decoder.cpp" />
<File RelativePath="..\..\engines\sci\gfx\seq_decoder.h" /> <File RelativePath="..\..\engines\sci\gfx\seq_decoder.h" />
</Filter> </Filter>
<Filter Name="gui">
<File RelativePath="..\..\engines\sci\gui\gui.cpp" />
<File RelativePath="..\..\engines\sci\gui\gui.h" />
<File RelativePath="..\..\engines\sci\gui\gui_dbllist.cpp" />
<File RelativePath="..\..\engines\sci\gui\gui_dbllist.h" />
<File RelativePath="..\..\engines\sci\gui\gui_font.cpp" />
<File RelativePath="..\..\engines\sci\gui\gui_font.h" />
<File RelativePath="..\..\engines\sci\gui\gui_gfx.cpp" />
<File RelativePath="..\..\engines\sci\gui\gui_gfx.h" />
<File RelativePath="..\..\engines\sci\gui\gui_helpers.h" />
<File RelativePath="..\..\engines\sci\gui\gui_memmgr.cpp" />
<File RelativePath="..\..\engines\sci\gui\gui_memmgr.h" />
<File RelativePath="..\..\engines\sci\gui\gui_picture.cpp" />
<File RelativePath="..\..\engines\sci\gui\gui_picture.h" />
<File RelativePath="..\..\engines\sci\gui\gui_screen.cpp" />
<File RelativePath="..\..\engines\sci\gui\gui_screen.h" />
<File RelativePath="..\..\engines\sci\gui\gui_view.cpp" />
<File RelativePath="..\..\engines\sci\gui\gui_view.h" />
<File RelativePath="..\..\engines\sci\gui\gui_windowmgr.cpp" />
<File RelativePath="..\..\engines\sci\gui\gui_windowmgr.h" />
<File RelativePath="..\..\engines\sci\gui32\gui32.h" />
<File RelativePath="..\..\engines\sci\gui32\gui32.cpp" />
</Filter>
<Filter Name="sfx"> <Filter Name="sfx">
<File RelativePath="..\..\engines\sci\sfx\core.cpp" /> <File RelativePath="..\..\engines\sci\sfx\core.cpp" />
<File RelativePath="..\..\engines\sci\sfx\core.h" /> <File RelativePath="..\..\engines\sci\sfx\core.h" />

View file

@ -332,18 +332,18 @@ SciKernelFunction kfunct_mappers[] = {
DEFUN("ShowMovie", kShowMovie, "..*"), DEFUN("ShowMovie", kShowMovie, "..*"),
DEFUN("SetVideoMode", kSetVideoMode, "i"), DEFUN("SetVideoMode", kSetVideoMode, "i"),
DEFUN("Platform", kPlatform, "i*"), DEFUN("Platform", kPlatform, "i*"),
DEFUN("PalVary", kPalVary, "ii*"), DEFUN("TextColors", kTextColors, ".*"),
DEFUN("TextFonts", kTextFonts, ".*"),
#if 0 #if 0
// Stub functions // Stub functions
DEFUN("PalVary", kPalVary, "ii*"),
DEFUN("ShiftScreen", kShiftScreen, ".*"), DEFUN("ShiftScreen", kShiftScreen, ".*"),
DEFUN("MemorySegment", kMemorySegment, ".*"), DEFUN("MemorySegment", kMemorySegment, ".*"),
DEFUN("ListOps", kListOps, ".*"), DEFUN("ListOps", kListOps, ".*"),
DEFUN("ATan", kATan, ".*"), DEFUN("ATan", kATan, ".*"),
DEFUN("MergePoly", kMergePoly, ".*"), DEFUN("MergePoly", kMergePoly, ".*"),
DEFUN("AssertPalette", kAssertPalette, ".*"), DEFUN("AssertPalette", kAssertPalette, ".*"),
DEFUN("TextColors", kTextColors, ".*"),
DEFUN("TextFonts", kTextFonts, ".*"),
DEFUN("Record", kRecord, ".*"), DEFUN("Record", kRecord, ".*"),
DEFUN("PlayBack", kPlayBack, ".*"), DEFUN("PlayBack", kPlayBack, ".*"),
DEFUN("DbugStr", kDbugStr, ".*"), DEFUN("DbugStr", kDbugStr, ".*"),

View file

@ -454,7 +454,8 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv);
reg_t kSetVideoMode(EngineState *s, int argc, reg_t *argv); reg_t kSetVideoMode(EngineState *s, int argc, reg_t *argv);
reg_t kStrSplit(EngineState *s, int argc, reg_t *argv); reg_t kStrSplit(EngineState *s, int argc, reg_t *argv);
reg_t kPlatform(EngineState *s, int argc, reg_t *argv); reg_t kPlatform(EngineState *s, int argc, reg_t *argv);
reg_t kPalVary(EngineState *s, int argc, reg_t *argv); reg_t kTextColors(EngineState *s, int argc, reg_t *argv);
reg_t kTextFonts(EngineState *s, int argc, reg_t *argv);
} // End of namespace Sci } // End of namespace Sci

View file

@ -206,11 +206,13 @@ reg_t kGlobalToLocal(EngineState *s, int argc, reg_t *argv) {
SegManager *segMan = s->segMan; SegManager *segMan = s->segMan;
if (obj.segment) { if (obj.segment) {
int x = GET_SEL32V(obj, x); int16 x = GET_SEL32V(obj, x);
int y = GET_SEL32V(obj, y); int16 y = GET_SEL32V(obj, y);
PUT_SEL32V(obj, x, x - s->port->zone.x); s->gui->globalToLocal(&x, &y);
PUT_SEL32V(obj, y, y - s->port->zone.y);
PUT_SEL32V(obj, x, x);
PUT_SEL32V(obj, y, y);
} }
return s->r_acc; return s->r_acc;
@ -222,11 +224,13 @@ reg_t kLocalToGlobal(EngineState *s, int argc, reg_t *argv) {
SegManager *segMan = s->segMan; SegManager *segMan = s->segMan;
if (obj.segment) { if (obj.segment) {
int x = GET_SEL32V(obj, x); int16 x = GET_SEL32V(obj, x);
int y = GET_SEL32V(obj, y); int16 y = GET_SEL32V(obj, y);
PUT_SEL32V(obj, x, x + s->port->zone.x); s->gui->localToGlobal(&x, &y);
PUT_SEL32V(obj, y, y + s->port->zone.y);
PUT_SEL32V(obj, x, x);
PUT_SEL32V(obj, y, y);
} }
return s->r_acc; return s->r_acc;

File diff suppressed because it is too large Load diff

View file

@ -131,7 +131,8 @@ reg_t kGetTime(EngineState *s, int argc, reg_t *argv) {
switch (mode) { switch (mode) {
case K_NEW_GETTIME_TICKS : case K_NEW_GETTIME_TICKS :
retval = start_time * 60 / 1000; retval = s->gui->getTimeTicks(); // FIXME
//retval = start_time * 60 / 1000;
debugC(2, kDebugLevelTime, "GetTime(elapsed) returns %d", retval); debugC(2, kDebugLevelTime, "GetTime(elapsed) returns %d", retval);
break; break;
case K_NEW_GETTIME_TIME_12HOUR : case K_NEW_GETTIME_TIME_12HOUR :

View file

@ -44,6 +44,7 @@ namespace Common {
#include "sci/engine/seg_manager.h" #include "sci/engine/seg_manager.h"
#include "sci/gfx/gfx_system.h" #include "sci/gfx/gfx_system.h"
#include "sci/sfx/core.h" #include "sci/sfx/core.h"
#include "sci/gui/gui.h"
namespace Sci { namespace Sci {
@ -175,6 +176,8 @@ public:
/* Non-VM information */ /* Non-VM information */
SciGUI *gui; /* Currently active GUI */
GfxState *gfx_state; /**< Graphics state and driver */ GfxState *gfx_state; /**< Graphics state and driver */
gfx_pixmap_t *old_screen; /**< Old screen content: Stored during kDrawPic() for kAnimate() */ gfx_pixmap_t *old_screen; /**< Old screen content: Stored during kDrawPic() for kAnimate() */
@ -319,6 +322,12 @@ private:
*/ */
PaletteEntry get_pic_color(EngineState *s, int color); PaletteEntry get_pic_color(EngineState *s, int color);
/* Functions used in gui32\gui32.cpp */
reg_t graph_save_box(EngineState *s, rect_t area);
void graph_restore_box(EngineState *s, reg_t handle);
void assert_primary_widget_lists(EngineState *s);
void reparentize_primary_widget_lists(EngineState *s, GfxPort *newport);
} // End of namespace Sci } // End of namespace Sci
#endif // SCI_INCLUDE_ENGINE_H #endif // SCI_INCLUDE_ENGINE_H

View file

@ -248,4 +248,19 @@ void GfxDriver::setPointer(gfx_pixmap_t *pointer, Common::Point *hotspot) {
cursorData = 0; cursorData = 0;
} }
void GfxDriver::animatePalette(int fromColor, int toColor, int stepCount) {
int i;
PaletteEntry firstColor = _mode->palette->getColor(fromColor);
PaletteEntry loopColor;
for (i=fromColor+1; i<=toColor; i++) {
loopColor = _mode->palette->getColor(i);
loopColor.r = 0;
loopColor.g = 0;
loopColor.b = 0;
_mode->palette->makeSystemColor(i-1, loopColor); // loopColor.r, loopColor.g, loopColor.b);
}
// _mode->palette->setColor(toColor, firstColor.r, firstColor.g, firstColor.b);
_mode->palette->makeSystemColor(toColor, firstColor);
}
} // End of namespace Sci } // End of namespace Sci

View file

@ -228,6 +228,11 @@ public:
gfx_mode_t *getMode() { return _mode; } gfx_mode_t *getMode() { return _mode; }
byte *getVisual0() { return _visual[0]; } byte *getVisual0() { return _visual[0]; }
/**
* Animates palette
*/
void animatePalette(int fromColor, int toColor, int stepCount);
private: private:
gfx_pixmap_t *_priority[2]; gfx_pixmap_t *_priority[2];
byte *_visual[2]; byte *_visual[2];

View file

@ -365,6 +365,12 @@ gfx_pixmap_t *gfxr_draw_cel1(int id, int loop, int cel, int mirrored, byte *reso
return retval; return retval;
} }
// SCI1:
// [LoopCount:WORD] [MirrorMask:WORD] [??:WORD] [PaletteOffset:WORD] [LoopOffset0:WORD] [LoopOffset1:WORD]...
// Loop-data:
// [CellCount:WORD] [Unknown:WORD] [CellOffset0:WORD] [CellOffset1:WORD]...
// SCI11:
// [HeaderSize:WORD] [LoopCount:BYTE] [Unknown:BYTE] [??:WORD] [??:WORD] [PaletteOffset:WORD]
gfxr_view_t *getVGAView(int id, byte *resource, int size, ViewType viewType) { gfxr_view_t *getVGAView(int id, byte *resource, int size, ViewType viewType) {
uint16 palOffset = READ_LE_UINT16(resource + V1_PALETTE_OFFSET + ((viewType == kViewVga11) ? 2 : 0)); uint16 palOffset = READ_LE_UINT16(resource + V1_PALETTE_OFFSET + ((viewType == kViewVga11) ? 2 : 0));
uint16 headerSize = (viewType == kViewVga11) ? READ_LE_UINT16(resource + V2_HEADER_SIZE) : 0; uint16 headerSize = (viewType == kViewVga11) ? READ_LE_UINT16(resource + V2_HEADER_SIZE) : 0;

330
engines/sci/gui/gui.cpp Normal file
View file

@ -0,0 +1,330 @@
/* 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.
*
* $URL$
* $Id$
*
*/
#include "common/util.h"
#include "sci/sci.h"
#include "sci/engine/state.h"
#include "sci/tools.h"
#include "sci/gui/gui_screen.h"
#include "sci/gui/gui_gfx.h"
#include "sci/gui/gui_windowmgr.h"
#include "sci/gui/gui_memmgr.h"
#include "sci/gui/gui_view.h"
#include "sci/gfx/operations.h"
namespace Sci {
SciGUI::SciGUI(OSystem *system, EngineState *state)
: _system(system), _s(state) {
_screen = new SciGUIscreen(_system, _s);
_gfx = new SciGUIgfx(_system, _s, _screen);
_windowMgr = new SciGUIwindowMgr(_s, _gfx);
}
SciGUI::SciGUI() {
}
SciGUI::~SciGUI() {
}
void SciGUI::init(bool oldGfxFunctions) {
_usesOldGfxFunctions = oldGfxFunctions;
/* Set default SCI0 palette */
}
int16 SciGUI::getTimeTicks() {
return _gfx->_sysTicks;
}
void SciGUI::wait(int16 ticks) {
uint32 waitto = _gfx->_sysTicks + ticks;
do {
//eventMgr->pollEvents();
_system->delayMillis(_gfx->_sysSpeed >> 11);
} while (_gfx->_sysTicks < waitto);
}
void SciGUI::setPort(uint16 portPtr) {
switch (portPtr) {
case 0: _gfx->SetPort(_windowMgr->_wmgrPort); break;
case 0xFFFF: _gfx->SetPort(_gfx->_menuPort); break;
default:
_gfx->SetPort((sciPort *)heap2Ptr(portPtr));
};
}
void SciGUI::setPortPic(Common::Rect rect, int16 picTop, int16 picLeft) {
_windowMgr->_picWind->rect = rect;
_windowMgr->_picWind->top = picTop;
_windowMgr->_picWind->left = picLeft;
//if (argc >= 7)
//InitPri(42,190);
}
reg_t SciGUI::getPort() {
return make_reg(0, ptr2heap((byte *)_gfx->GetPort()));
}
void SciGUI::globalToLocal(int16 *x, int16 *y) {
sciPort *curPort = _gfx->GetPort();
*x = *x - curPort->left;
*y = *y - curPort->top;
}
void SciGUI::localToGlobal(int16 *x, int16 *y) {
sciPort *curPort = _gfx->GetPort();
*x = *x + curPort->left;
*y = *y + curPort->top;
}
reg_t SciGUI::newWindow(Common::Rect rect1, Common::Rect rect2, uint16 style, int16 priority, int16 colorPen, int16 colorBack, const char *title) {
sciWnd *wnd = NULL;
if (rect2.top != 0 && rect2.left != 0 && rect2.height() != 0 && rect2.width() != 0)
wnd = _windowMgr->NewWindow(&rect1, &rect2, "", style, priority, 0);
else
wnd = _windowMgr->NewWindow(&rect1, NULL, "", style, priority, 0);
wnd->penClr = colorPen;
wnd->backClr = colorBack;
_windowMgr->DrawWindow(wnd);
return make_reg(0, ptr2heap((byte *)wnd));
}
void SciGUI::disposeWindow(uint16 windowPtr, int16 arg2) {
sciWnd *wnd = (sciWnd *)heap2Ptr(windowPtr);
_windowMgr->DisposeWindow(wnd, arg2);
}
void SciGUI::display(const char *text, int argc, reg_t *argv) {
int displayArg;
sciPort oldPort;
int16 align = 0;
int16 bgcolor = -1, width = 0xFFFF, bRedraw = 1;
byte bSaveUnder = false;
Common::Rect rect, *orect = &((sciWnd *)_gfx->GetPort())->rect0;
memcpy(&oldPort, _gfx->GetPort(), sizeof(sciPort));
// setting defaults
_gfx->PenMode(0);
_gfx->PenColor(0);
_gfx->TextFace(0);
// processing codes in argv
while (argc > 0) {
displayArg = argv[0].toUint16();
argc--; argv++;
switch (displayArg - 100) {
case 0:
_gfx->MoveTo(argv[0].toUint16(), argv[1].toUint16());
argc -= 2; argv += 2;
break;// move pen
case 1:
align = argv[0].toUint16();
argc--; argv++;
break;// set alignment
case 2:
_gfx->PenColor(argv[0].toUint16());
argc--; argv++;
break;// set pen color
case 3:
bgcolor = argv[0].toUint16();
argc--; argv++;
break;
case 4:
_gfx->TextFace(argv[0].toUint16());
argc--; argv++;
break;// set text grayout flag
case 5:
_gfx->SetFont(argv[0].toUint16());
argc--; argv++;
break;// set font
case 6:
width = argv[0].toUint16();
argc--; argv++;
break;
case 7:
bSaveUnder = 1;
break;
case 8: // restore under
// if (hunk2Ptr(*pArgs)) {
// memcpy(&rect, hunk2Ptr(*pArgs), sizeof(Common::Rect));
// // rect is now absolute. Have to move it to be port-relative
// rect.translate(-_gfx->RGetPort()->left, -_gfx->RGetPort()->top);
// _gfx->RestoreBits(*pArgs);
// ReAnimate(&rect);
// }
// finishing loop
argc = 0;
break;
case 0x15:
bRedraw = 0;
break;
default:
warning("Unknown kDisplay argument %X", displayArg);
break;
}
}
// now drawing the text
_gfx->TextSize(rect, text, -1, width);
_gfx->Move((orect->left <= 320 ? 0 : 320 - orect->left), (orect->top <= 200 ? 0 : 200 - orect->top)); // move port to (0,0)
rect.moveTo(_gfx->GetPort()->curLeft, _gfx->GetPort()->curTop);
// if (bSaveUnder)
// _acc = _gfx->SaveBits(rect, 1);
if (bgcolor != -1)
_gfx->FillRect(rect, 1, bgcolor, 0, 0);
_gfx->TextBox(text, 0, rect, align, 0xFFFF);
// if (_picNotValid == 0 && bRedraw)
// _gfx->ShowBits(rect, 1);
// restoring port and cursor pos
sciPort *currport = _gfx->GetPort();
uint16 tTop = currport->curTop;
uint16 tLeft = currport->curLeft;
memcpy(currport, &oldPort, sizeof(sciPort));
currport->curTop = tTop;
currport->curLeft = tLeft;
_screen->UpdateWhole();
}
void SciGUI::textSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight) {
Common::Rect rect(0, 0, *textWidth, *textHeight);
_gfx->TextSize(rect, text, font, maxWidth);
*textWidth = rect.width(); *textHeight = rect.height();
}
// Used SCI1+ for text codes
void SciGUI::textFonts(int argc, reg_t *argv) {
}
// Used SCI1+ for text codes
void SciGUI::textColors(int argc, reg_t *argv) {
}
void SciGUI::drawPicture(sciResourceId pictureId, uint16 style, uint16 flags, int16 EGApaletteNo) {
bool addToFlag = flags ? true : false;
sciPort *oldPort = _gfx->SetPort((sciPort *)_windowMgr->_picWind);
if (_windowMgr->isFrontWindow(_windowMgr->_picWind)) {
_gfx->drawPicture(pictureId, style, addToFlag, EGApaletteNo);
} else {
_windowMgr->BeginUpdate(_windowMgr->_picWind);
_gfx->drawPicture(pictureId, style, addToFlag, EGApaletteNo);
_windowMgr->EndUpdate(_windowMgr->_picWind);
}
_screen->UpdateWhole();
_gfx->SetPort(oldPort);
_s->pic_not_valid = 1;
}
void SciGUI::drawCell(sciResourceId viewId, uint16 loopNo, uint16 cellNo, uint16 leftPos, uint16 topPos, int16 priority, uint16 paletteNo) {
_gfx->drawCell(viewId, loopNo, cellNo, leftPos, topPos, priority, paletteNo);
_gfx->SetCLUT(&_gfx->_sysPalette);
_screen->UpdateWhole();
}
void SciGUI::drawControlButton(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 style, bool inverse) {
rect.grow(1);
_gfx->EraseRect(rect);
_gfx->FrameRect(rect);
rect.grow(-2);
_gfx->TextFace(style & 1 ? 0 : 1);
_gfx->TextBox(text, 0, rect, 1, fontId);
_gfx->TextFace(0);
if (style & 8) { // selected
rect.grow(1);
_gfx->FrameRect(rect);
}
_screen->UpdateWhole();
}
void SciGUI::drawControlText(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 mode, int16 style, bool inverse) {
rect.grow(1);
_gfx->EraseRect(rect);
rect.grow(-1);
_gfx->TextBox(text, 0, rect, mode, fontId);
if (style & 8) { // selected
_gfx->FrameRect(rect);
}
_screen->UpdateWhole();
}
void SciGUI::graphFillBoxForeground(Common::Rect rect) {
_gfx->PaintRect(rect);
_screen->UpdateWhole();
}
void SciGUI::graphFillBoxBackground(Common::Rect rect) {
_gfx->EraseRect(rect);
_screen->UpdateWhole();
}
void SciGUI::graphFillBox(Common::Rect rect, uint16 colorMask, int16 color, int16 priority, int16 control) {
_gfx->FillRect(rect, colorMask, color, priority, control);
_screen->UpdateWhole();
}
void SciGUI::graphDrawLine(Common::Rect rect, int16 color, int16 priority, int16 control) {
_gfx->Draw_Line(rect.left, rect.top, rect.right, rect.bottom, color, priority, control);
_screen->UpdateWhole();
}
reg_t SciGUI::graphSaveBox(Common::Rect rect, uint16 flags) {
return _gfx->SaveBits(rect, flags);
}
void SciGUI::graphRestoreBox(reg_t handle) {
_gfx->RestoreBits(handle);
_screen->UpdateWhole();
}
void SciGUI::paletteSet(int resourceNo, int flags) {
_gfx->SetResPalette(resourceNo, flags);
}
int16 SciGUI::paletteFind(int r, int g, int b) {
return _gfx->MatchColor(&_gfx->_sysPalette, r, g, b) & 0xFF;
}
void SciGUI::paletteAnimate(int fromColor, int toColor, int speed) {
_gfx->animatePalette(fromColor, toColor, speed);
}
void SciGUI::moveCursor(int16 x, int16 y) {
Common::Point newPos;
sciPort *curPort = _gfx->GetPort();
x += _windowMgr->_picWind->rect.left;
y += _windowMgr->_picWind->rect.top;
newPos.x = CLIP<int16> (x, _windowMgr->_picWind->rect.left, _windowMgr->_picWind->rect.right - 1);
newPos.y = CLIP<int16> (y, _windowMgr->_picWind->rect.top, _windowMgr->_picWind->rect.bottom - 1);
gfxop_set_pointer_position(_s->gfx_state, newPos);
}
} // End of namespace Sci

86
engines/sci/gui/gui.h Normal file
View file

@ -0,0 +1,86 @@
/* 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.
*
* $URL$
* $Id$
*
*/
#include "sci/gui/gui_helpers.h"
namespace Sci {
class SciGUIscreen;
class SciGUIgfx;
class SciGUIresources;
class SciGUIwindowMgr;
class SciGUI {
public:
SciGUI(OSystem *system, EngineState *s);
SciGUI();
~SciGUI();
virtual void init(bool oldGfxFunctions);
virtual int16 getTimeTicks();
virtual void wait(int16 ticks);
virtual void setPort(uint16 portPtr);
virtual void setPortPic(Common::Rect rect, int16 picTop, int16 picLeft);
virtual reg_t getPort();
virtual void globalToLocal(int16 *x, int16 *y);
virtual void localToGlobal(int16 *x, int16 *y);
virtual reg_t newWindow(Common::Rect rect1, Common::Rect rect2, uint16 style, int16 priority, int16 colorPen, int16 colorBack, const char *title);
virtual void disposeWindow(uint16 windowPtr, int16 arg2);
virtual void display(const char *text, int argc, reg_t *argv);
virtual void textSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight);
virtual void textFonts(int argc, reg_t *argv);
virtual void textColors(int argc, reg_t *argv);
virtual void drawPicture(sciResourceId pictureId, uint16 showStyle, uint16 flags, int16 EGApaletteNo);
virtual void drawCell(sciResourceId viewId, uint16 loopNo, uint16 cellNo, uint16 leftPos, uint16 topPos, int16 priority, uint16 paletteNo);
virtual void drawControlButton(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 style, bool inverse);
virtual void drawControlText(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 mode, int16 style, bool inverse);
virtual void graphFillBoxForeground(Common::Rect rect);
virtual void graphFillBoxBackground(Common::Rect rect);
virtual void graphFillBox(Common::Rect rect, uint16 colorMask, int16 color, int16 priority, int16 control);
virtual void graphDrawLine(Common::Rect rect, int16 color, int16 priority, int16 control);
virtual reg_t graphSaveBox(Common::Rect rect, uint16 flags);
virtual void graphRestoreBox(reg_t handle);
virtual void paletteSet(int resourceNo, int flags);
virtual int16 paletteFind(int r, int g, int b);
virtual void paletteAnimate(int fromColor, int toColor, int speed);
virtual void moveCursor(int16 x, int16 y);
private:
OSystem *_system;
EngineState *_s;
SciGUIscreen *_screen;
SciGUIgfx *_gfx;
SciGUIresources *_resources;
SciGUIwindowMgr *_windowMgr;
bool _usesOldGfxFunctions;
};
} // End of namespace Sci

View file

@ -0,0 +1,257 @@
/* 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.
*
* $URL$
* $Id$
*
*/
#include "common/util.h"
#include "sci/sci.h"
#include "sci/gui/gui_helpers.h"
#include "sci/gui/gui_memmgr.h"
#include "sci/gui/gui_dbllist.h"
namespace Sci {
DblList::DblList() {
_hFirst = 0;
_hLast = 0;
}
DblList::DblList(HEAPHANDLE heap) {
byte *ptr = heap2Ptr(heap);
_hFirst = READ_UINT16(ptr);
_hLast = READ_UINT16(ptr + 2);
}
DblList::~DblList(void) {
}
//--------------------------------------
// Prints all list contents
void DblList::Dump(char*caption) {
debug("DumpList %s:", caption);
debug(" First: %04X Last: %04X", _hFirst, _hLast);
HEAPHANDLE node = _hFirst;
while (node) {
sciNode *pNode = (sciNode *)heap2Ptr(node);
debug(" %04X key=%04X prev=%04X next=%04X add.data=%db", node,
pNode->key, pNode->prev, pNode->next, heapGetDataSize(node) - 6);
node = pNode->next;
}
debug("End of list");
}
//--------------------------------------
// Add a new node to front of the list
HEAPHANDLE DblList::AddToFront(HEAPHANDLE node, uint16 key) {
if (!node) {
warning("Bad node handler (%04X) passed to DblList::AddToFront !",
node);
return node;
}
sciNode *pNode = (sciNode *)heap2Ptr(node);
pNode->key = key;
if (_hFirst) { // we already have a 1st node
sciNode *pnext = (sciNode *)heap2Ptr(_hFirst);
pnext->prev = node;
pNode->next = _hFirst;
} else { // list is empty, to passed node becames 1st one
_hLast = node;
pNode->next = 0;
}
_hFirst = node;
pNode->prev = 0;
return node;
}
//-------------------------------------
//
HEAPHANDLE DblList::AddToEnd(HEAPHANDLE node, uint16 key) {
if (!node) {
warning("Bad node handler (%04X) passed to DblList::AddToEnd !", node);
return node;
}
sciNode *pNode = (sciNode *)heap2Ptr(node);
if (_hFirst) { // list is not empty
sciNode *plast = (sciNode *)heap2Ptr(_hLast);
plast->next = node;
pNode->prev = _hLast;
} else { // list is empty, so the node becames 1st one
_hFirst = node;
pNode->prev = 0;
}
_hLast = node;
pNode->next = 0;
pNode->key = key;
return node;
}
//------------------------------------------------
// returns node that contains the key
HEAPHANDLE DblList::FindKey(uint16 key) {
HEAPHANDLE node = _hFirst;
while (node) {
sciNode *pNode = (sciNode *)heap2Ptr(node);
if (pNode->key == key)
break;
node = pNode->next;
}
return node;
}
//------------------------------------------------
// detaches node with specified key and returning the node
HEAPHANDLE DblList::DeleteKey(uint16 key) {
HEAPHANDLE node = FindKey(key);
if (node)
DeleteNode(node);
return node;
}
//------------------------------------------------
// detaches specified node from list
byte DblList::DeleteNode(HEAPHANDLE node) {
if (!node) {
warning("Bad node handler (%04X) passed to DblList::AddToEnd !", node);
return node;
}
// updating the links
sciNode *pNode = (sciNode *)heap2Ptr(node);
if (pNode->prev) {
sciNode *pprev = (sciNode *)heap2Ptr(pNode->prev);
pprev->next = pNode->next;
}
if (pNode->next) {
sciNode *pnext = (sciNode *)heap2Ptr(pNode->next);
pnext->prev = pNode->prev;
}
// updating list head if needed
if (_hFirst == node)
_hFirst = pNode->next;
if (_hLast == node)
_hLast = pNode->prev;
pNode->prev = 0;
pNode->next = 0;
return 1;
}
//------------------------------------------------
// Moves node to the end of the list
HEAPHANDLE DblList::MoveToEnd(HEAPHANDLE node) {
if (!node) {
warning("Bad node handler (%04X) passed to DblList::MoveToEnd !", node);
return node;
}
sciNode *pNode = (sciNode *)heap2Ptr(node);
if (pNode->next) { // node is not the last one in list
DeleteNode(node);
AddToEnd(node, pNode->key);
}
return node;
}
//------------------------------------------------
// Moves node to the front of the list
HEAPHANDLE DblList::MoveToFront(HEAPHANDLE node) {
if (!node) {
warning("Bad node handler (%04X) passed to DblList::MoveToFront !",
node);
return node;
}
sciNode *pNode = (sciNode *)heap2Ptr(node);
if (pNode->prev) { // node is not 1st one in list
DeleteNode(node);
AddToFront(node, pNode->key);
}
return node;
}
//------------------------------------------------
HEAPHANDLE DblList::AddAfter(HEAPHANDLE ref, HEAPHANDLE node, uint16 key) {
if (!node) {
warning("Bad node handler (%04X) passed to DblList::AddAfter !", node);
return node;
}
sciNode *pNode = (sciNode *)heap2Ptr(node);
sciNode *pref = (sciNode *)heap2Ptr(ref);
pNode->key = key;
if (pref->next == 0) { // ref node is the last one
pNode->next = 0;
_hLast = node;
} else {
sciNode *pnext = (sciNode *)heap2Ptr(pref->next);
pNode->next = pref->next;
pnext->prev = node;
}
pref->next = node;
pNode->prev = ref;
return node;
}
//------------------------------------------------
//
HEAPHANDLE DblList::AddBefore(HEAPHANDLE ref, HEAPHANDLE node, uint16 key) {
if (!node) {
warning("Bad node handler (%04X) passed to DblList::AddBefore !", node);
return node;
}
sciNode *pNode = (sciNode *)heap2Ptr(node);
sciNode *pref = (sciNode *)heap2Ptr(ref);
pNode->key = key;
if (pref->prev == 0) { // ref node is the 1st one
pNode->prev = 0;
_hFirst = node;
} else {
sciNode*pprev = (sciNode *)heap2Ptr(pref->prev);
pNode->prev = pref->prev;
pprev->next = node;
}
pref->prev = node;
pNode->next = ref;
return node;
}
//------------------------------------------------
void DblList::toHeap(HEAPHANDLE heap) {
byte *ptr = heap2Ptr(heap);
WRITE_UINT16(ptr, _hFirst);
WRITE_UINT16(ptr + 2, _hLast);
}
//------------------------------------------------
void DblList::DeleteList() {
HEAPHANDLE node = getFirst(), next;
sciNode *pNode;
while (node) {
pNode = (sciNode *)heap2Ptr(node);
next = pNode->next;
heapDisposePtr(node);
node = next;
}
_hFirst = _hLast = 0;
}
//------------------------------------------------
uint16 DblList::getSize() {
uint16 cnt = 0;
HEAPHANDLE node = getFirst();
sciNode *pNode;
while (node) {
pNode = (sciNode *)heap2Ptr(node);
node = pNode->next;
cnt++;
}
return cnt;
}
//------------------------------------------------
} // end of namespace

View file

@ -0,0 +1,74 @@
/* 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.
*
* $URL$
* $Id$
*
*/
/*
Each node contains handles to next and previous node and an optional key for searching
Head node contains handles to first and last node
*/
namespace Sci {
typedef uint16 HEAPHANDLE;
class DblList {
public:
DblList();
DblList(HEAPHANDLE heap);
~DblList(void);
protected:
HEAPHANDLE _hFirst, _hLast;
public:
// Add a new node to front of the list
HEAPHANDLE AddToFront(HEAPHANDLE node, uint16 key = 0);
HEAPHANDLE AddToEnd(HEAPHANDLE node, uint16 key = 0);
HEAPHANDLE MoveToEnd(HEAPHANDLE node);
HEAPHANDLE MoveToFront(HEAPHANDLE node);
HEAPHANDLE AddAfter(HEAPHANDLE ref, HEAPHANDLE node, uint16 key = 0);
HEAPHANDLE AddBefore(HEAPHANDLE ref, HEAPHANDLE node, uint16 key = 0);
HEAPHANDLE FindKey(uint16 key);
HEAPHANDLE DeleteKey(uint16 key);
byte DeleteNode(HEAPHANDLE node);
void DeleteList();
void Dump(char*caption = ""); // for debug
HEAPHANDLE getFirst() {
return _hFirst;
}
HEAPHANDLE getLast() {
return _hLast;
}
void toHeap(HEAPHANDLE heap);
bool isEmpty() {
return (_hFirst == 0 && _hLast == 0);
}
uint16 getSize();
void set(HEAPHANDLE first, HEAPHANDLE last){
_hFirst = first;
_hLast = last;
}
};
} // end of namespace

View file

@ -0,0 +1,100 @@
/* 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.
*
* $URL$
* $Id$
*
*/
#include "sci/sci.h"
#include "sci/engine/state.h"
#include "sci/tools.h"
#include "sci/gui/gui_screen.h"
#include "sci/gui/gui_font.h"
namespace Sci {
SciGUIfont::SciGUIfont(OSystem *system, EngineState *state, SciGUIscreen *screen, sciResourceId resourceId)
: _system(system), _s(state), _screen(screen), _resourceId(resourceId) {
assert(resourceId != -1);
initData(resourceId);
}
SciGUIfont::~SciGUIfont() {
}
void SciGUIfont::initData(sciResourceId resourceId) {
Resource *fontResource = _s->resMan->findResource(ResourceId(kResourceTypeFont, resourceId), false);
if (!fontResource) {
error("font resource %d not found", resourceId);
}
_resourceData = fontResource->data;
mCharMax = READ_LE_UINT16(_resourceData + 2);
mFontH = READ_LE_UINT16(_resourceData + 4);
mChars = new charinfo[mCharMax];
// filling info for every char
for (int16 i = 0; i < mCharMax; i++) {
mChars[i].offset = READ_LE_UINT16(_resourceData + 6 + i * 2);
mChars[i].w = _resourceData[mChars[i].offset];
mChars[i].h = _resourceData[mChars[i].offset + 1];
}
}
sciResourceId SciGUIfont::getResourceId() {
return _resourceId;
}
byte SciGUIfont::getHeight() {
return mFontH;
}
byte SciGUIfont::getCharWidth(byte chr) {
return chr < mCharMax ? mChars[chr].w : 0;
}
byte SciGUIfont::getCharHeight(byte chr) {
return chr < mCharMax ? mChars[chr].h : 0;
}
byte *SciGUIfont::getCharData(byte chr) {
return chr < mCharMax ? _resourceData + mChars[chr].offset + 2 : 0;
}
void SciGUIfont::draw(int16 chr, int16 top, int16 left, byte color, byte textface) {
int charWidth = MIN<int>(getCharWidth(chr), _screen->_width - left);
int charHeight = MIN<int>(getCharHeight(chr), 200 - top);
byte b = 0, mask = 0xFF;
int pitch = _screen->_width;
int y = top;
byte *pIn = getCharData(chr);
for (int i = 0; i < charHeight; i++, y++) {
if (textface & 1) // "grayed" output
mask = top++ % 2 ? 0xAA : 0x55;
for (int done = 0; done < charWidth; done++) {
if ((done & 7) == 0) // fetching next data byte
b = *(pIn++) & mask;
if (b & 0x80) // if MSB is set - paint it
_screen->Put_Pixel(left + done, y, 1, color, 0, 0);
b = b << 1;
}
}
}
} // end of namespace Sci

View file

@ -0,0 +1,59 @@
/* 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.
*
* $URL$
* $Id$
*
*/
namespace Sci {
class SciGUIfont {
public:
SciGUIfont(OSystem *system, EngineState *state, SciGUIscreen *screen, sciResourceId resourceId);
~SciGUIfont();
sciResourceId getResourceId();
byte getHeight();
byte getCharWidth(byte chr);
byte getCharHeight(byte chr);
byte *getCharData(byte chr);
void draw(int16 chr, int16 top, int16 left, byte color, byte textface);
private:
void initData(sciResourceId resourceId);
OSystem *_system;
EngineState *_s;
SciGUIscreen *_screen;
sciResourceId _resourceId;
byte *_resourceData;
struct charinfo {
byte w, h;
int16 offset;
};
byte mFontH;
uint16 mCharMax;
charinfo* mChars;
};
} // end of namespace Sci

1194
engines/sci/gui/gui_gfx.cpp Normal file

File diff suppressed because it is too large Load diff

150
engines/sci/gui/gui_gfx.h Normal file
View file

@ -0,0 +1,150 @@
/* 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.
*
* $URL$
* $Id$
*
*/
namespace Sci {
#define SCI_PATTERN_CODE_RECTANGLE 0x10
#define SCI_PATTERN_CODE_USE_TEXTURE 0x20
#define SCI_PATTERN_CODE_PENSIZE 0x07
class SciGUIscreen;
class SciGUIfont;
class SciGUIpicture;
class SciGUIview;
class SciGUIgfx {
public:
SciGUIgfx(OSystem *system, EngineState *state, SciGUIscreen *screen);
~SciGUIgfx();
void init(void);
void initPalette();
virtual void initTimer();
static void timerHandler(void*ref);
sciPort *mallocPort ();
byte *GetSegment(byte seg);
void ResetScreen();
void SetEGApalette();
void CreatePaletteFromData(byte *paletteData, sciPalette *paletteOut);
bool SetResPalette(int16 resourceNo, int16 flag);
void SetPalette(sciPalette *sciPal, int16 flag);
void MergePalettes(sciPalette*pFrom, sciPalette*pTo, uint16 flag);
uint16 MatchColor(sciPalette*pPal, byte r, byte g, byte b);
void SetCLUT(sciPalette*pal);
void GetCLUT(sciPalette*pal);
sciPort *SetPort(sciPort *port);
sciPort *GetPort();
void SetOrigin(int16 left, int16 top);
void MoveTo(int16 left, int16 top);
void Move(int16 left, int16 top);
void SetFont(int16 fontId);
void OpenPort(sciPort *port);
void PenColor(int16 color);
void PenMode(int16 mode);
void TextFace(int16 textFace);
int16 GetPointSize(void);
int16 GetFontId();
SciGUIfont *GetFont();
void ClearScreen(byte color = 255);
void InvertRect(const Common::Rect &rect);
void EraseRect(const Common::Rect &rect);
void PaintRect(const Common::Rect &rect);
void FillRect(const Common::Rect &rect, int16 arg2, byte clrPen, byte clrBack = 0, byte bControl = 0);
void FrameRect(const Common::Rect &rect);
void OffsetRect(Common::Rect &r);
byte CharHeight(int16 ch);
byte CharWidth(int16 ch);
int16 TextWidth(const char*text, int16 from, int16 len);
int16 StringWidth(const char*str) {
return TextWidth(str, 0, (int16)strlen(str));
}
void ClearChar(int16 chr);
void DrawChar(int16 chr);
void StdChar(int16 chr);
SCILanguage getSCILanguage();
char* StrSplit(char*buff, const char*msg, const char*fmt);
char* getIntlString(char*buff, const char*msg, const char*fmt, SCILanguage lang, SCILanguage prop);
int16 TextSize(Common::Rect &rect, const char *str, int16 fontId, int16 maxwidth);
int16 GetLongest(const char *str, int16 maxwidth);
void DrawText(const char *str, int16 from, int16 len);
void ShowText(const char *str, int16 from, int16 len);
void ShowString(const char *str) {
ShowText(str, 0, (int16)strlen(str));
}
void DrawString(const char *str) {
DrawText(str, 0, (int16)strlen(str));
}
void TextBox(const char *str, int16 bshow, const Common::Rect &rect, int16 align, int16 fontId);
void ShowBits(const Common::Rect &r, uint16 flags);
sciMemoryHandle SaveBits(const Common::Rect &rect, byte screenFlags);
void RestoreBits(sciMemoryHandle memoryHandle);
void Draw_Line(int16 left, int16 top, int16 right, int16 bottom, byte color, byte prio, byte control);
void Draw_Horiz(int16 left, int16 right, int16 top, byte flag, byte color, byte prio, byte control);
void Draw_Vert(int16 top, int16 bottom, int16 left, byte flag, byte color, byte prio, byte control);
void Draw_Box(Common::Rect box, byte color, byte prio, byte control);
void Draw_TexturedBox(Common::Rect box, byte color, byte prio, byte control, byte texture);
void Draw_Circle(Common::Rect box, byte size, byte color, byte prio, byte control);
void Draw_TexturedCircle(Common::Rect box, byte size, byte color, byte prio, byte control, byte texture);
void Draw_Pattern(int16 x, int16 y, byte pic_color, byte pic_priority, byte pic_control, byte code, byte texture);
void Pic_Fill(int16 x, int16 y, byte color, byte prio, byte control);
void drawPicture(sciResourceId pictureId, uint16 style, bool addToFlag, sciResourceId paletteId);
void drawCell(sciResourceId viewId, uint16 loopNo, uint16 cellNo, uint16 leftPos, uint16 topPos, byte priority, uint16 paletteNo);
void animatePalette(byte fromColor, byte toColor, int speed);
sciPort *_menuPort;
uint32 _sysTicks;
int32 _sysSpeed; // ticker timer in ms
sciPalette _sysPalette;
uint16 _resolutionWidth;
uint16 _resolutionHeight;
uint _resolutionPixels;
private:
OSystem *_system;
EngineState *_s;
SciGUIscreen *_screen;
Common::Rect _bounds;
sciPort *_mainPort;
sciPort *_curPort;
// byte *_visualScreen;
// byte *_pcSeg;
uint16 _clrPowers[256];
byte bMapColors;
sciPalette *pPicPal;
Common::Array<sciPalSched> _palSchedules;
SciGUIfont *_font;
};
} // end of namespace Sci

View file

@ -0,0 +1,150 @@
/* 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.
*
* $URL$
* $Id$
*
*/
#include "common/rect.h"
#include "sci/engine/vm_types.h"
namespace Sci {
typedef int sciResourceId; // is a resource-number and -1 means no parameter given
typedef reg_t sciMemoryHandle;
typedef uint16 SCIHANDLE;
struct sciNode {
SCIHANDLE next; // heap handle to next node
SCIHANDLE prev; // heap handle to data
uint16 key; // maybe also a heap handle
};
struct sciNode1 : sciNode {
uint16 value;
};
// sciPort and sciWnd need to be binary identical, so if you change anything in one, you have to change it in the other one
// as well!
struct sciPort {
sciNode node; // node struct for list operations
int16 top, left;
Common::Rect rect;
int16 curTop, curLeft;
int16 fontH;
sciResourceId fontId;
int16 textFace, penClr, backClr;
int16 penMode;
};
struct sciWnd {
// begins like sciPort (needs to be binary identical!!)
sciNode node; // node struct for list operations
int16 top, left;
Common::Rect rect;
int16 curTop, curLeft;
int16 fontH;
sciResourceId fontId;
int16 textFace, penClr, backClr;
int16 penMode;
// window specific members
Common::Rect rect0; // client area of window
Common::Rect rect1; // total area of window including borders
uint16 wndStyle;
uint16 uSaveFlag;
reg_t hSaved1;
reg_t hSaved2;
SCIHANDLE hTitle;
bool bDrawed;
};
struct sciCast {
sciNode node;
uint16 view;
uint16 loop;
uint16 cel;
uint16 z;
uint16 pal;
SCIHANDLE hSaved;
Common::Rect rect;
};
struct sciColor {
byte used;
byte r, g, b;
};
struct sciPalette {
byte mapping[256];
uint32 timestamp;
sciColor colors[256];
byte intencity[256];
};
struct sciPalSched {
byte from;
uint32 schedule;
};
#define STUB(str) debug("STUB: '%s' at file %s line %d",str,__FILE__,__LINE__)
// FIXME: The following feature enums and macros should be reconsidered.
// The way they are done right now is highly error prone.
enum {
FTR_WINDOWMGR_SCI0 = (0<<0), // SCI0 based window manager
FTR_WINDOWMGR_SCI1 = (1<<0), // SCI1 based window manager
FTR_CAN_BEHERE = (0<<1), // Kernel77 is kCanBeHere (SCI0)
FTR_CANT_BEHERE = (1<<1), // Kernel77 is kCantBeHere(SCI1)
FTR_SOUND_SCI0 = (0<<2), // SCI0 Sound functions
FTR_SOUND_SCI01 = (1<<2), // SCI0+ Sound functions
FTR_SOUND_SCI1 = (2<<2), // SCI1 Sound functions
FTR_SHOWPIC_SCI0 = (0<<4), // SCI0 ShowPic (44 effect codes)
FTR_SHOWPIC_SCI1 = (1<<4), // SCI1 ShowPic (15 effect codes)
FTR_GL_ANIMATE = (1<<5) // Animate can be paused by global flag
};
#define GETFTR_WINDOWMGR(x) (x & 0x00000001)
#define GETFTR_CANBEHERE(x) (x & 0x00000002)
#define GETFTR_SOUND(x) (x & 0x0000000C)
#define GETFTR_SHOWPIC(x) (x & 0x00000010)
enum {
GFX_STOPUPDATE = 0x01,
GFX_VIEWUPDATED = 0x02,
GFX_NOUPDATE = 0x04,
GFX_HIDDEN = 0x08,
GFX_FIXEDPRIO=0x10,
GFX_ALWAYSUPDATE = 0x20,
GFX_FORCEUPDATE = 0x40,
GFX_REMOVEVIEW = 0x80
};
enum SCILanguage{
kLangNone = 0,
kLangEnglish = 1,
kLangFrench = 33,
kLangSpanish = 34,
kLangItalian = 39,
kLangGerman = 49
};
}

View file

@ -0,0 +1,373 @@
/* 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.
*
* $URL$
* $Id$
*
*/
#include "sci/sci.h"
#include "sci/gui/gui_helpers.h"
#include "sci/gui/gui_memmgr.h"
namespace Sci {
static tagHandle *pHandles = 0;
static int16 nHandles = 0;
static byte *_heap = 0;
SCIHANDLE _firstfree = 0;
Common::HashMap<HEAPHANDLE, tagHeapInfo> heapInfo;
#define HEAP_BOTTOM 1000
//----------------------
void FreeMem(void) {
// deleting handles
if (pHandles) {
for (uint16 i = 0; i < nHandles; i++)
hunkDisposeHandle(i);
delete[] pHandles;
pHandles = 0;
}
// deleting heap
if (_heap) {
delete[] _heap;
_heap = 0;
}
}
//----------------------
bool InitMem(int16 max_handles) {
// heap
_heap = new byte[HEAP_SIZE];
memset(_heap, 0x55, HEAP_SIZE);
_firstfree = HEAP_START;
heapSetBlockSize(_firstfree, HEAP_SIZE - 1 - HEAP_START);
heapSetBlockNext(_firstfree, (SCIHANDLE)(HEAP_SIZE - 1));
//hunk
pHandles = new tagHandle[max_handles];
if (pHandles) {
nHandles = max_handles;
memset(pHandles, 0, sizeof(tagHandle) * max_handles); // zerofy all
return 1;
}
return 0;
}
//----------------------
SCIHANDLE hunkNeedHandle(uint16 size, uint32 resId) {
SCIHANDLE newh = 0;
// see if there is an empty handle available
for (int16 i = 1; i < nHandles; i++)
if (pHandles[i].ptr == 0) {
newh = i;
break;
}
// if unused handle was found - allocate memory and return it
if (newh == nHandles)
return 0;
pHandles[newh].ptr = (byte*)malloc(size);
assert(pHandles[newh].ptr);
if (pHandles[newh].ptr) {
pHandles[newh].size = size;
pHandles[newh].resId = resId;
debug(
5,
" MemMgr: Requested %6db for res %08X, allocated handle %04X",
size, resId, newh);
return newh;
}
return 0;
}
//----------------------
void hunkDisposeHandle(SCIHANDLE handle) {
// if (handle > 0 && handle < nHandles && pHandles[handle].ptr) {
// debug(
// 5,
// " MemMgr: disposing handle 0x%04X, size=%8db, associated res %08X",
// handle, pHandles[handle].size, pHandles[handle].resId);
// free(pHandles[handle].ptr);
// pHandles[handle].ptr = 0;
// // deleting associated resource handler
// // Check that this don't fail on delete as ResGetLoaded could return 0;
// if (pHandles[handle].resId != 0xFFFFFFFF)
// delete g_sci->ResMgr.ResGetLoaded(pHandles[handle].resId);
// }
}
//----------------------
byte *hunk2Ptr(SCIHANDLE handle) {
if (handle > 0 && handle < nHandles && pHandles[handle].ptr)
return (byte *)pHandles[handle].ptr;
return 0;
}
//----------------------
SCIHANDLE ptr2hunk(byte *ptr) {
for (int i = 0; i < nHandles; i++) {
if (ptr >= pHandles[i].ptr && ptr <= pHandles[i].ptr + pHandles[i].size)
return i;
}
return 0;
}
//----------------------
uint32 hunkHandleSize(SCIHANDLE handle) {
if (handle > 0 && handle < nHandles && pHandles[handle].ptr)
return pHandles[handle].size;
return 0;
}
//----------------------
// int16 hunkResourceNum(SCIHANDLE handle) {
// if (handle > 0 && handle < nHandles && pHandles[handle].ptr)
// return RES_ID2NUM(pHandles[handle].resId);
// return -1;
// }
//----------------------
void hunkDump() {
debug("\nMemMgr: Hunk dump:");
uint32 size = 0;
for (int i = 0; i < nHandles; i++)
if (pHandles[i].ptr) {
debug(" %04X, size=%8db, associated res %08X", i,
pHandles[i].size, pHandles[i].resId);
size += pHandles[i].size;
}
debug("Total memory allocated: %db", size);
debug("End dump");
}
uint32 hunkUsed() {
uint32 size = 0;
for (int i = 0; i < nHandles; i++)
if (pHandles[i].ptr)
size += pHandles[i].size;
return size;
}
//----------------------
// HEAP
//----------------------
//---------------------------------------------
// TODO : make sure that STRING, STACK and SCRIPT DATA is never allocated below HEAP_BOTTOM=1000
// otherwise it will cause problems with kernel string fuctions that assumes that anything below 1000 is res number
HEAPHANDLE heapNewPtr(uint16 size, kDataType type, const char *info) {
if (size == 0)
warning("Zero Heap Allocation Request!");
HEAPHANDLE ptr, prev, next;
ptr = prev = _firstfree;
// 2 bytes block header header + block size must be odd
size += 2 + (size & 1);
// looking for an empty block to use
uint16 blocksize;
bool bBottomSafe = !(type == kDataString || type == kDataUnknown);
while (ptr < HEAP_SIZE - 1) {
blocksize = heapGetBlockSize(ptr);
next = heapGetBlockNext(ptr);
if (blocksize >= size) {
if (bBottomSafe || (!bBottomSafe && ptr > HEAP_BOTTOM)) {
if (blocksize <= size + 4) { // use all block
size = blocksize;
heapSetBlockNext(prev, next);
} else { // split block in 2 blocks
HEAPHANDLE newblock = ptr + size;
heapSetBlockNext(prev, newblock);
heapSetBlockSize(newblock, blocksize - size);
heapSetBlockNext(newblock, next);
next = newblock;
}
// setting allocated block
heapSetBlockSize(ptr, size);
// updating firstfree pointer
if (ptr == _firstfree)
_firstfree = next;
setHeapInfo(ptr, type, info);
return ptr;
} //if (bBottomSafe || (!bBottomSafe && ptr>HEAP_BOTTOM))
else { // !bottomsafe && ptr < HEAP_BOTTOM
if (blocksize + ptr - HEAP_BOTTOM >= size) {
// splitting the block into 3 parts
// [2][ptr...999] [2][1002...1000+size-1] [2][1002+size...ptr+blocksize]
// free returned free
heapSetBlockSize(ptr, HEAP_BOTTOM-ptr + 2);
heapSetBlockSize(HEAP_BOTTOM+2, size);
heapSetBlockSize(HEAP_BOTTOM+2 + size, blocksize - size
- (HEAP_BOTTOM-ptr + 2));
heapSetBlockNext(HEAP_BOTTOM+2 + size, next);
heapSetBlockNext(ptr, HEAP_BOTTOM+2 + size);
setHeapInfo(HEAP_BOTTOM+2, type, info);
return HEAP_BOTTOM + 2;
}
}
} // if (blocksize >= size)
// block too small - moving to next one
prev = ptr;
ptr = next;
}
// allocation error - out of heap
warning("Out of heap space");
return 0;
}
//--------------------------------------------
void heapDisposePtr(HEAPHANDLE handle) {
HEAPHANDLE prev, next;
prev = next = _firstfree;
// searching for prev and next free blocks (before & after deleted block)
while (next < handle) {
prev = next;
next = heapGetBlockNext(prev);
}
// if deleted block is before 1st free space then it'll be 1st free space
if (handle < _firstfree) {
next = _firstfree;
_firstfree = handle;
} else
heapSetBlockNext(prev, handle);
heapSetBlockNext(handle, next);
//Try to merge with previous
if (prev + heapGetBlockSize(prev) == handle) {
heapSetBlockSize(prev, heapGetBlockSize(prev)
+ heapGetBlockSize(handle));
heapSetBlockNext(prev, next);
handle = prev;
}
//Try to merge with next
if (handle + heapGetBlockSize(handle) == next && next != (HEAP_SIZE - 1)) {
heapSetBlockSize(handle, heapGetBlockSize(handle) + heapGetBlockSize(
next));
heapSetBlockNext(handle, heapGetBlockNext(next));
}
}
//-------------------------------------
uint16 heapFreeSize() {
HEAPHANDLE free = _firstfree;
uint16 szFree = 0;
while (free < HEAP_SIZE - 1) {
int size = heapGetBlockSize(free);
free = heapGetBlockNext(free);
szFree += size;
}
return szFree;
}
//-------------------------------------
uint16 heapLargestFreeSize() {
HEAPHANDLE free = _firstfree;
uint16 maxFree = 0;
while (free < HEAP_SIZE - 1) {
int size = heapGetBlockSize(free);
free = heapGetBlockNext(free);
if (size > maxFree)
maxFree = size;
}
return maxFree ? maxFree - 2 : 0;
}
//-------------------------------------
void heapDump() {
debug("\nMemMgr:Heap dump:");
HEAPHANDLE ptr = HEAP_START;
HEAPHANDLE free = _firstfree;
uint16 szFree = 0, szUsed = 0;
while (ptr < HEAP_SIZE - 1) {
int size = heapGetBlockSize(ptr);
if (ptr == free) {
free = heapGetBlockNext(free);
debug(" %04X %6u size:%6d FREE next=%04X", ptr, ptr,
heapGetDataSize(ptr), free);
szFree += size;
} else {
debug(" %04X %6u size:%6d USED", ptr, ptr, heapGetDataSize(ptr));
szUsed += size;
}
ptr += size;
}
debug("Total %db used, %db free\nEnd Dump", szUsed, szFree);
}
//----------------------------
inline byte *heap2Ptr(HEAPHANDLE ptr) {
return (ptr >= HEAP_START) ? (byte *)(_heap + ptr) : NULL;
}
//----------------------------
HEAPHANDLE ptr2heap(byte *ptr) {
return ptr > _heap && ptr < (_heap + HEAP_SIZE) ? (HEAPHANDLE)(ptr - _heap)
: 0;
}
//----------------------------
uint16 heapGetBlockSize(HEAPHANDLE ptr) {
return READ_UINT16(_heap + ptr - 2);
}
//----------------------------
uint16 heapGetDataSize(HEAPHANDLE ptr) {
return heapGetBlockSize(ptr) - 2;
}
//----------------------------
void heapFillPtr(HEAPHANDLE ptr, byte filler) {
memset(heap2Ptr(ptr), filler, heapGetDataSize(ptr));
}
//----------------------------
void heapClearPtr(HEAPHANDLE ptr) {
heapFillPtr(ptr, 0);
}
//----------------------------
void heapSetBlockSize(HEAPHANDLE ptr, uint16 nbytes) {
WRITE_UINT16(_heap + ptr - 2, nbytes);
}
//----------------------------
HEAPHANDLE heapGetBlockNext(HEAPHANDLE ptr) {
return READ_UINT16(_heap + ptr);
}
//----------------------------
void heapSetBlockNext(HEAPHANDLE ptr, SCIHANDLE next) {
WRITE_UINT16(_heap + ptr, next);
}
//----------------------------
void heapDisposePtr(byte *ptr) {
heapDisposePtr(ptr - _heap);
}
//---------------------------------------------
//
//
void setHeapInfo(HEAPHANDLE hnd, kDataType type, const char *szinfo) {
tagHeapInfo info = { kDataUnknown, 0 };
info.type = type;
if (szinfo)
strncpy(info.info, szinfo, 20);
heapInfo.setVal(hnd, info);
}
//--------------------------------
bool saveMemState(Common::OutSaveFile *pFile) {
pFile->writeString("MEMORY\n");
// saving heap
pFile->write(_heap, HEAP_SIZE);
pFile->writeUint16LE(_firstfree);
// TODO : process and write hunk handles
//pFile->writeString("HUNK\n");
return true;
}
//--------------------------------
bool restoreMemState(Common::InSaveFile *pFile) {
if (pFile->readLine() != "MEMORY")
return false;
pFile->read(_heap, HEAP_SIZE);
_firstfree = pFile->readUint16LE();
return true;
}
//-------------------------------
}// end of namespace SCI

View file

@ -0,0 +1,123 @@
/* 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.
*
* $URL$
* $Id$
*
*/
#ifndef SCI_MEMMGR_H
#define SCI_MEMMGR_H
#include "common/savefile.h"
#include "common/endian.h"
#include "common/hashmap.h"
/*
Memory management functions for SCI engine;
All fuctions are simplified as there is no 16-bit limitations as in
original SCI. Although it may cause problems.
SCI Heap functionality.
Heap size is limited to 65535 bytes to be consistent with SCI scripts
Free block header is [wBlockSize][wNextFree]
Used block header is [wBlockSize][data.....]
^-----returned HEAPHANDLE
*/
namespace Sci {
typedef uint16 SCIHANDLE;
typedef uint16 HEAPHANDLE;
enum {
HEAP_SIZE = 0x10000l,
HEAP_START = 2
};
struct tagHandle {
byte *ptr; // data pointer
uint32 size; // memory block size
uint32 resId; // associated resource
};
//---------------------------------------------
// for debugger
enum kDataType {
kDataUnknown = 0,
kDataClass,
kDataObject,
kDataRect,
kDataWindow,
kDataPort,
kDataString,
kDataListHdr,
kDataListNode,
kDataCast,
kDataPalette,
kDataScript,
kDataFile
};
struct tagHeapInfo {
kDataType type;
char info[21];
};
void setHeapInfo(HEAPHANDLE hnd, kDataType type, const char *info = 0);
bool InitMem(int16 max_handles);
void FreeMem(void);
// hunk functions
SCIHANDLE hunkNeedHandle(uint16 size, uint32 resId = 0xFFFFFFFF);
void hunkDisposeHandle(SCIHANDLE handle);
byte *hunk2Ptr(SCIHANDLE handle);
SCIHANDLE ptr2hunk(byte *ptr);
uint32 hunkHandleSize(SCIHANDLE handle);
int16 hunkResourceNum(SCIHANDLE handle);
void hunkDump();
uint32 hunkUsed();
// heap functions
HEAPHANDLE heapNewPtr(uint16 size, kDataType type/*=kDataUnknown*/,
const char *info = 0);
void heapDisposePtr(HEAPHANDLE handle);
void heapDisposePtr(byte *ptr);
byte *heap2Ptr(HEAPHANDLE ptr);
HEAPHANDLE ptr2heap(byte *ptr);
uint16 heapGetBlockSize(HEAPHANDLE ptr);
uint16 heapGetDataSize(HEAPHANDLE ptr);
void heapFillPtr(HEAPHANDLE ptr, byte filler);
void heapClearPtr(HEAPHANDLE ptr);
void heapDump();
uint16 heapFreeSize();
uint16 heapLargestFreeSize();
void heapSetBlockSize(HEAPHANDLE ptr, uint16 nbytes);
HEAPHANDLE heapGetBlockNext(HEAPHANDLE ptr);
void heapSetBlockNext(HEAPHANDLE ptr, SCIHANDLE next);
bool saveMemState(Common::OutSaveFile *pFile);
bool restoreMemState(Common::InSaveFile *pFile);
} // end of namespace SCI
#endif

View file

@ -0,0 +1,592 @@
/* 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.
*
* $URL$
* $Id$
*
*/
#include "sci/sci.h"
#include "sci/engine/state.h"
#include "sci/tools.h"
#include "sci/gui/gui_screen.h"
#include "sci/gui/gui_gfx.h"
#include "sci/gui/gui_picture.h"
namespace Sci {
SciGUIpicture::SciGUIpicture(OSystem *system, EngineState *state, SciGUIgfx *gfx, SciGUIscreen *screen, sciResourceId resourceId)
: _system(system), _s(state), _gfx(gfx), _screen(screen), _resourceId(resourceId) {
assert(resourceId != -1);
initData(resourceId);
}
SciGUIpicture::~SciGUIpicture() {
}
void SciGUIpicture::initData(sciResourceId resourceId) {
_resource = _s->resMan->findResource(ResourceId(kResourceTypePic, resourceId), false);
if (!_resource) {
error("picture resource %d not found", resourceId);
}
}
sciResourceId SciGUIpicture::getResourceId() {
return _resourceId;
}
#define PALETTE_SIZE 1284
#define CEL_HEADER_SIZE 7
#define EXTRA_MAGIC_SIZE 15
void SciGUIpicture::draw(uint16 style, bool addToFlag, int16 EGApaletteNo) {
_style = style;
_addToFlag = addToFlag;
_EGApaletteNo = EGApaletteNo;
_curPort = _gfx->GetPort();
_priority = 0;
if (READ_LE_UINT16(_resource->data) == 0x26) {
// SCI 1.1 picture
draw11();
} else {
// Just directly draw the vector data
_gfx->SetEGApalette();
drawVectorData(_resource->data, _resource->size);
}
}
void SciGUIpicture::reset() {
int16 x, y;
for (y = _curPort->top; y < _screen->_height; y++) {
for (x = 0; x < _screen->_width; x++) {
_screen->Put_Pixel(x, y, SCI_SCREEN_MASK_ALL, 255, 0, 0);
}
}
}
void SciGUIpicture::draw11() {
byte *inbuffer = _resource->data;
int size = _resource->size;
int has_view = READ_LE_UINT16(inbuffer + 4);
int vector_data_ptr = READ_LE_UINT16(inbuffer + 16);
int vector_size = size - vector_data_ptr;
int palette_data_ptr = READ_LE_UINT16(inbuffer + 28);
int view_data_ptr = READ_LE_UINT16(inbuffer + 32);
int view_size = palette_data_ptr - view_data_ptr;
int view_rle_ptr = READ_LE_UINT16(inbuffer + view_data_ptr + 24);
int view_pixel_ptr = READ_LE_UINT16(inbuffer + view_data_ptr + 28);
byte *view = NULL;
sciPalette palette;
// Create palette and set it
_gfx->CreatePaletteFromData(inbuffer + palette_data_ptr, &palette);
_gfx->SetPalette(&palette, 2);
// drawPalette11(inbuffer + palette_data_ptr);
// display Cel-data
if (has_view) {
view = (byte *)malloc(size*2); // is there a way to know how much decoded view-data there will be?
if (!view) return;
memcpy(view, inbuffer + view_data_ptr, 8);
decodeRLE(inbuffer + view_rle_ptr, inbuffer + view_pixel_ptr, view + 8, view_size - 8);
drawCel(0, 0, view, size * 2);
free(view);
}
// process vector data
// ?? if we process vector data first some things in sq4 dont seem right, but this way we wont get _priority set
drawVectorData(inbuffer + vector_data_ptr, vector_size);
}
void SciGUIpicture::drawPalette11(byte *data) {
int start_color = data[25];
int format = data[32];
byte *pal_data = &data[37];
int colors_nr = READ_LE_UINT16(data + 29);
int i;
sciPalette palette = {0};
switch (format) {
case SCI_PAL_FORMAT_VARIABLE_FLAGS:
for (i = start_color; i < start_color + colors_nr; i ++) {
palette.colors[i].used = pal_data[0];
palette.colors[i].r = pal_data[1];
palette.colors[i].g = pal_data[2];
palette.colors[i].b = pal_data[3];
pal_data += 4;
}
break;
case SCI_PAL_FORMAT_CONSTANT_FLAGS:
for (i = start_color; i < start_color + colors_nr; i ++) {
palette.colors[i].used = 1;
palette.colors[i].r = pal_data[0];
palette.colors[i].g = pal_data[1];
palette.colors[i].b = pal_data[2];
pal_data += 3;
}
break;
}
_gfx->SetPalette(&palette, 2);
}
void SciGUIpicture::decodeRLE(byte *rledata, byte *pixeldata, byte *outbuffer, int size) {
int pos = 0;
byte nextbyte;
byte *rd = rledata;
byte *ob = outbuffer;
byte *pd = pixeldata;
while (pos < size) {
nextbyte = *(rd++);
*(ob++) = nextbyte;
pos ++;
switch (nextbyte&0xC0) {
case 0x40 :
case 0x00 :
memcpy(ob, pd, nextbyte);
pd += nextbyte;
ob += nextbyte;
pos += nextbyte;
break;
case 0xC0 :
break;
case 0x80 :
nextbyte = *(pd++);
*(ob++) = nextbyte;
pos ++;
break;
}
}
}
void SciGUIpicture::drawCel(int16 x, int16 y, byte *pdata, int size) {
byte* pend = pdata + size;
uint16 width = READ_LE_UINT16(pdata + 0);
uint16 height = READ_LE_UINT16(pdata + 2);
signed char dx = *(pdata + 4);
signed char dy = *(pdata + 5);
byte priority = _addToFlag ? _priority : 0;
byte clr = *(pdata + 6);
if (dx || dy || width != 320)
debug("Warning: embedded picture cel has width=%d dx=%d dy=%d", width, dx, dy);
byte *ptr = pdata + 8; // offset to data
y += _curPort->top;
uint16 j = 0, lasty = MIN<int16>(height + y, _curPort->rect.bottom) + _curPort->top;
byte b, brun;
while (y < lasty && ptr < pend) {
b = *ptr++;
brun = b & 0x3F; // bytes run length on this step
switch (b & 0xC0) {
case 0: // copy bytes as-is but skip transparent ones
while (brun-- && y < lasty && ptr < pend) {
if ((b = *ptr++) != clr && priority >= _screen->Get_Priority(x, y)) {
_screen->Put_Pixel(x, y, 3, b, priority, 0);
}
x++;
if (x >= _screen->_width) {
x -= _screen->_width; y++;
}
}
break;
case 0x80: // fill with color
b = *ptr++;
while (brun-- && y < lasty) {
if (priority >= _screen->Get_Priority(x, y)) {
_screen->Put_Pixel(x, y, 3, b, priority, 0);
}
x++;
if (x >= _screen->_width) {
x -= _screen->_width; y++;
}
}
break;
case 0xC0: // fill with transparent - skip
x += brun;
if (x >= _screen->_width) {
x -= _screen->_width; y++;
}
break;
}
}
}
void SciGUIpicture::drawCelAmiga(int16 x, int16 y, byte *pdata, int size) {
byte* pend = pdata + size;
uint16 width = READ_LE_UINT16(pdata + 0);
uint16 height = READ_LE_UINT16(pdata + 2);
signed char dx = *(pdata + 4);
signed char dy = *(pdata + 5);
byte priority = _addToFlag ? _priority : 0;
//byte clr = *(pdata + 8);
if (dx || dy || width != 320)
debug("Warning : cel have w=%d dx=%d dy=%d", width, dx, dy);
byte *ptr = pdata + 8; // offset to data
y += _curPort->top;
uint16 j = 0, lasty = MIN<int16>(height + y, _curPort->rect.bottom) + _curPort->top;
byte op, col, bytes;
while (y < lasty && ptr < pend) {
op = *ptr++;
if (op & 0x07) {
bytes = op & 0x07;
col = op >> 3;
while (bytes-- && y < lasty) {
if (priority >= _screen->Get_Priority(x, y)) {
_screen->Put_Pixel(x, y, 3, col, priority, 0);
}
x++;
if (x >= _screen->_width) {
x -= _screen->_width; y++;
}
}
} else {
bytes = op >> 3;
x += bytes;
if (x >= _screen->_width) {
x -= _screen->_width; y++;
}
}
}
}
enum {
PIC_OP_SET_COLOR = 0xf0,
PIC_OP_DISABLE_VISUAL = 0xf1,
PIC_OP_SET_PRIORITY = 0xf2,
PIC_OP_DISABLE_PRIORITY = 0xf3,
PIC_OP_SHORT_PATTERNS = 0xf4,
PIC_OP_MEDIUM_LINES = 0xf5,
PIC_OP_LONG_LINES = 0xf6,
PIC_OP_SHORT_LINES = 0xf7,
PIC_OP_FILL = 0xf8,
PIC_OP_SET_PATTERN = 0xf9,
PIC_OP_ABSOLUTE_PATTERN = 0xfa,
PIC_OP_SET_CONTROL = 0xfb,
PIC_OP_DISABLE_CONTROL = 0xfc,
PIC_OP_MEDIUM_PATTERNS = 0xfd,
PIC_OP_OPX = 0xfe,
PIC_OP_TERMINATE = 0xff
};
#define PIC_OP_FIRST PIC_OP_SET_COLOR
enum {
PIC_OPX_SCI0_SET_PALETTE_ENTRIES = 0,
PIC_OPX_SCI0_SET_PALETTE = 1,
PIC_OPX_SCI0_MONO0 = 2,
PIC_OPX_SCI0_MONO1 = 3,
PIC_OPX_SCI0_MONO2 = 4,
PIC_OPX_SCI0_MONO3 = 5,
PIC_OPX_SCI0_MONO4 = 6,
PIC_OPX_SCI0_EMBEDDED_VIEW = 7,
PIC_OPX_SCI0_SET_PRIORITY_TABLE = 8
};
enum {
PIC_OPX_SCI1_SET_PALETTE_ENTRIES = 0,
PIC_OPX_SCI1_EMBEDDED_VIEW = 1,
PIC_OPX_SCI1_SET_PALETTE = 2,
PIC_OPX_SCI1_PRIORITY_TABLE_EQDIST = 3,
PIC_OPX_SCI1_PRIORITY_TABLE_EXPLICIT = 4
};
#define PIC_EGAPALETTE_COUNT 4
#define PIC_EGAPALETTE_SIZE 40
#define PIC_EGAPALETTE_TOTALSIZE PIC_EGAPALETTE_COUNT*PIC_EGAPALETTE_SIZE
const byte vector_defaultEGApalette[PIC_EGAPALETTE_SIZE] = {
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0x88,
0x88, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x88,
0x88, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
0x08, 0x91, 0x2a, 0x3b, 0x4c, 0x5d, 0x6e, 0x88
};
void SciGUIpicture::drawVectorData(byte *data, int dataSize) {
byte pic_op;
byte pic_color = 0, pic_priority = 0x0F, pic_control = 0x0F;
int16 x = 0, y = 0, oldx, oldy;
byte EGApalette = 0;
byte EGAindex = 0;
byte EGApalettes[PIC_EGAPALETTE_TOTALSIZE] = {0};
bool EGAmapping = false;
int curPos = 0;
uint16 size;
byte byte;
int i;
sciPalette palette = {0};
int16 pattern_Code = 0, pattern_Texture = 0;
bool sci1 = false;
if (_EGApaletteNo >= PIC_EGAPALETTE_COUNT)
_EGApaletteNo = 0;
if (getSciVersion() >= SCI_VERSION_1_EGA)
sci1 = true;
for (i = 0; i < PIC_EGAPALETTE_TOTALSIZE; i += PIC_EGAPALETTE_SIZE)
memcpy(&EGApalettes[i], &vector_defaultEGApalette, sizeof(vector_defaultEGApalette));
// Drawing
while (curPos < dataSize) {
warning("%X at %d", data[curPos], curPos);
switch (pic_op = data[curPos++]) {
case PIC_OP_SET_COLOR:
byte = data[curPos++];
pic_color = EGAmapping ? EGApalettes[byte] : byte;
break;
case PIC_OP_DISABLE_VISUAL:
pic_color = 0xFF;
break;
case PIC_OP_SET_PRIORITY:
pic_priority = data[curPos++];
break;
case PIC_OP_DISABLE_PRIORITY:
pic_priority = 255;
break;
case PIC_OP_SET_CONTROL:
pic_control = data[curPos++];
break;
case PIC_OP_DISABLE_CONTROL:
pic_control = 255;
break;
case PIC_OP_SHORT_LINES: // short line
vectorGetAbsCoords(data, curPos, oldx, oldy);
while (vectorIsNonOpcode(data[curPos])) {
vectorGetRelCoords(data, curPos, oldx, oldy, x, y);
warning("line %d %d -> %d %d", oldy, oldx, y, x);
_gfx->Draw_Line(oldx, oldy, x, y, pic_color, pic_priority, pic_control);
oldx = x; oldy = y;
}
break;
case PIC_OP_MEDIUM_LINES: // medium line
vectorGetAbsCoords(data, curPos, oldx, oldy);
while (vectorIsNonOpcode(data[curPos])) {
vectorGetRelCoordsMed(data, curPos, oldx, oldy, x, y);
warning("line %d %d -> %d %d", oldy, oldx, y, x);
_gfx->Draw_Line(oldx, oldy, x, y, pic_color, pic_priority, pic_control);
oldx = x; oldy = y;
}
break;
case PIC_OP_LONG_LINES: // long line
vectorGetAbsCoords(data, curPos, oldx, oldy);
while (vectorIsNonOpcode(data[curPos])) {
vectorGetAbsCoords(data, curPos, x, y);
warning("line %d %d -> %d %d", oldy, oldx, y, x);
_gfx->Draw_Line(oldx, oldy, x, y, pic_color, pic_priority, pic_control);
oldx = x; oldy = y;
}
break;
case PIC_OP_FILL: //fill
while (vectorIsNonOpcode(data[curPos])) {
vectorGetAbsCoords(data, curPos, x, y);
warning("fill %d %d", y, x);
_gfx->Pic_Fill(x, y, pic_color, pic_priority, pic_control);
}
break;
case PIC_OP_SET_PATTERN:
pattern_Code = data[curPos++];
break;
case PIC_OP_SHORT_PATTERNS:
vectorGetPatternTexture(data, curPos, pattern_Code, pattern_Texture);
vectorGetAbsCoords(data, curPos, x, y);
warning("pattern %d %d", y, x);
_gfx->Draw_Pattern(x, y, pic_color, pic_priority, pic_control, pattern_Code, pattern_Texture);
while (vectorIsNonOpcode(data[curPos])) {
vectorGetPatternTexture(data, curPos, pattern_Code, pattern_Texture);
vectorGetRelCoords(data, curPos, x, y, x, y);
warning("pattern %d %d", y, x);
_gfx->Draw_Pattern(x, y, pic_color, pic_priority, pic_control, pattern_Code, pattern_Texture);
}
break;
case PIC_OP_MEDIUM_PATTERNS:
vectorGetPatternTexture(data, curPos, pattern_Code, pattern_Texture);
vectorGetAbsCoords(data, curPos, x, y);
warning("pattern %d %d", y, x);
_gfx->Draw_Pattern(x, y, pic_color, pic_priority, pic_control, pattern_Code, pattern_Texture);
while (vectorIsNonOpcode(data[curPos])) {
vectorGetPatternTexture(data, curPos, pattern_Code, pattern_Texture);
vectorGetRelCoordsMed(data, curPos, x, y, x, y);
warning("pattern %d %d", y, x);
_gfx->Draw_Pattern(x, y, pic_color, pic_priority, pic_control, pattern_Code, pattern_Texture);
}
break;
case PIC_OP_ABSOLUTE_PATTERN:
while (vectorIsNonOpcode(data[curPos])) {
vectorGetPatternTexture(data, curPos, pattern_Code, pattern_Texture);
vectorGetAbsCoords(data, curPos, x, y);
warning("pattern %d %d", y, x);
//_gfx->Draw_Pattern(x, y, pic_color, pic_priority, pic_control, pattern_Code, pattern_Texture);
}
break;
case PIC_OP_OPX: // Extended functions
if (sci1) {
warning("OPX SCI1 %X at %d", data[curPos], curPos);
switch (pic_op = data[curPos++]) {
case PIC_OPX_SCI1_SET_PALETTE_ENTRIES:
while (vectorIsNonOpcode(data[curPos])) {
curPos++; // skip commands
}
break;
case PIC_OPX_SCI1_SET_PALETTE:
curPos += 256 + 4; // Skip over mapping and timestamp
for (i = 0; i < 256; i++) {
palette.colors[i].used = data[curPos++];
palette.colors[i].r = data[curPos++]; palette.colors[i].g = data[curPos++]; palette.colors[i].b = data[curPos++];
}
_gfx->SetPalette(&palette, 2);
break;
case PIC_OPX_SCI1_EMBEDDED_VIEW: // draw cel
vectorGetAbsCoords(data, curPos, x, y);
size = READ_LE_UINT16(data + curPos); curPos += 2;
drawCel(x, y, data + curPos, size);
curPos += size;
break;
case PIC_OPX_SCI1_PRIORITY_TABLE_EQDIST:
//FIXME
//g_sci->InitPri(READ_LE_UINT16(ptr), READ_LE_UINT16(ptr + 2));
debug(5, "DrawPic::InitPri %d %d",
READ_LE_UINT16(data + curPos), READ_LE_UINT16(data + curPos + 2));
curPos += 4;
break;
case PIC_OPX_SCI1_PRIORITY_TABLE_EXPLICIT:
//FIXME
//g_sci->PriBands(ptr);
curPos += 14;
break;
default:
error("Unsupported sci1 extended pic-operation %X", pic_op);
}
} else {
switch (pic_op = data[curPos++]) {
case PIC_OPX_SCI0_SET_PALETTE_ENTRIES:
while (vectorIsNonOpcode(data[curPos])) {
byte = data[curPos++];
if (byte >= PIC_EGAPALETTE_TOTALSIZE) {
error("picture trying to write to invalid EGA-palette");
}
EGApalettes[byte] = data[curPos++];
}
break;
case PIC_OPX_SCI0_SET_PALETTE:
byte = data[curPos++];
if (EGApalette >= PIC_EGAPALETTE_COUNT) {
error("picture trying to write to invalid palette %d", EGApalette);
}
byte *= PIC_EGAPALETTE_SIZE;
for (i = 0; i < PIC_EGAPALETTE_SIZE; i++) {
EGApalettes[byte + i] = data[curPos++];
}
break;
case PIC_OPX_SCI0_MONO0:
curPos += 41;
break;
case PIC_OPX_SCI0_MONO1:
case PIC_OPX_SCI0_MONO3:
curPos++;
break;
case PIC_OPX_SCI0_MONO2:
case PIC_OPX_SCI0_MONO4:
break;
case PIC_OPX_SCI0_EMBEDDED_VIEW:
vectorGetAbsCoords(data, curPos, x, y);
size = READ_LE_UINT16(data + curPos); curPos += 2;
drawCel(x, y, data + curPos, size);
curPos += size;
break;
case PIC_OPX_SCI0_SET_PRIORITY_TABLE:
//FIXME
//g_sci->PriBands(ptr);
curPos += 14;
break;
default:
error("Unsupported sci1 extended pic-operation %X", pic_op);
}
}
break;
case PIC_OP_TERMINATE:
_priority = pic_priority;
return;
default:
error("Unsupported pic-operation %X", pic_op);
}
}
error("picture vector data without terminator");
}
bool SciGUIpicture::vectorIsNonOpcode(byte byte) {
if (byte >= PIC_OP_FIRST)
return false;
return true;
}
void SciGUIpicture::vectorGetAbsCoords(byte *data, int &curPos, int16 &x, int16 &y) {
byte byte = data[curPos++];
x = data[curPos++] + ((byte & 0xF0) << 4);
y = data[curPos++] + ((byte & 0x0F) << 8);
if (_style & PIC_STYLE_MIRRORED) x = 319 - x;
}
void SciGUIpicture::vectorGetRelCoords(byte *data, int &curPos, int16 oldx, int16 oldy, int16 &x, int16 &y) {
byte byte = data[curPos++];
if (byte & 0x80) {
x = oldx - ((byte >> 4) & 7) * (_style & PIC_STYLE_MIRRORED ? -1 : 1);
} else {
x = oldx + (byte >> 4) * (_style & PIC_STYLE_MIRRORED ? -1 : 1);
}
if (byte & 0x08) {
y = oldy - (byte & 7);
} else {
y = oldy + (byte & 7);
}
}
void SciGUIpicture::vectorGetRelCoordsMed(byte *data, int &curPos, int16 oldx, int16 oldy, int16 &x, int16 &y) {
byte byte = data[curPos++];
if (byte & 0x80) {
y = oldy - (byte & 0x7F);
} else {
y = oldy + byte;
}
byte = data[curPos++];
if (byte & 0x80) {
x = oldx - (128 - (byte & 0x7F)) * (_style & PIC_STYLE_MIRRORED ? -1 : 1);
} else {
x = oldx + byte * (_style & PIC_STYLE_MIRRORED ? -1 : 1);
}
}
void SciGUIpicture::vectorGetPatternTexture(byte *data, int &curPos, int16 pattern_Code, int16 &pattern_Texture) {
if (pattern_Code & SCI_PATTERN_CODE_USE_TEXTURE) {
pattern_Texture = (data[curPos++] >> 1) & 0x7f;
}
}
} // end of namespace Sci

View file

@ -0,0 +1,71 @@
/* 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.
*
* $URL$
* $Id$
*
*/
namespace Sci {
#define SCI_PAL_FORMAT_VARIABLE_FLAGS 0
#define SCI_PAL_FORMAT_CONSTANT_FLAGS 1
#define PIC_STYLE_MIRRORED 0x4000
class SciGUIpicture {
public:
SciGUIpicture(OSystem *system, EngineState *state, SciGUIgfx *gfx, SciGUIscreen *screen, sciResourceId resourceId);
~SciGUIpicture();
sciResourceId getResourceId();
void draw(uint16 style, bool addToFlag, int16 EGApaletteNo);
private:
void initData(sciResourceId resourceId);
void reset();
void draw11();
void decodeRLE(byte *rledata, byte *pixeldata, byte *outbuffer, int size);
void drawPalette11(byte *data);
void drawCel(int16 x, int16 y, byte *pdata, int size);
void drawCelAmiga(int16 x, int16 y, byte *pdata, int size);
void drawVectorData(byte *data, int size);
bool vectorIsNonOpcode(byte byte);
void vectorGetAbsCoords(byte *data, int &curPos, int16 &x, int16 &y);
void vectorGetRelCoords(byte *data, int &curPos, int16 oldx, int16 oldy, int16 &x, int16 &y);
void vectorGetRelCoordsMed(byte *data, int &curPos, int16 oldx, int16 oldy, int16 &x, int16 &y);
void vectorGetPatternTexture(byte *data, int &curPos, int16 pattern_Code, int16 &pattern_Texture);
OSystem *_system;
EngineState *_s;
SciGUIgfx *_gfx;
SciGUIscreen *_screen;
int16 _resourceId;
Resource *_resource;
sciPort *_curPort;
uint16 _style;
bool _addToFlag;
int16 _EGApaletteNo;
byte _priority;
};
} // end of namespace Sci

View file

@ -0,0 +1,209 @@
/* 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.
*
* $URL$
* $Id$
*
*/
#include "common/timer.h"
#include "common/util.h"
#include "sci/sci.h"
#include "sci/engine/state.h"
#include "sci/tools.h"
#include "sci/gui/gui_screen.h"
namespace Sci {
SciGUIscreen::SciGUIscreen(OSystem *system, EngineState *state)
: _system(system), _s(state) {
init();
}
SciGUIscreen::~SciGUIscreen() {
}
void SciGUIscreen::init() {
int i;
uint16 base = 0;
_width = 320;
_height = 200;
_pixels = _width * _height;
// if you want to do scaling, adjust Put_Pixel() accordingly
_displayWidth = 320;
_displayHeight = 200;
_displayPixels = _displayWidth * _displayHeight;
_bytesPerDisplayPixel = 1;
_visualScreen = initScreen(_pixels);
_priorityScreen = initScreen(_pixels);
_controlScreen = initScreen(_pixels);
_displayScreen = initScreen(_displayPixels);
for (i = 0; i < _height; i++) {
_baseTable[i] = base; _baseDisplayTable[i] = base;
base += _width;
}
}
byte *SciGUIscreen::initScreen(uint16 pixelCount) {
byte *screen = (byte *)malloc(pixelCount);
memset(screen, 0, pixelCount);
return screen;
}
void SciGUIscreen::UpdateWhole() {
_system->copyRectToScreen(_displayScreen, _displayWidth, 0, 0, _displayWidth, _displayHeight);
_system->updateScreen();
}
byte SciGUIscreen::GetDrawingMask(byte color, byte prio, byte control) {
byte flag = 0;
if (color != 255)
flag |= SCI_SCREEN_MASK_VISUAL;
if (prio != 255)
flag |= SCI_SCREEN_MASK_PRIORITY;
if (control != 255)
flag |= SCI_SCREEN_MASK_CONTROL;
return flag;
}
void SciGUIscreen::Put_Pixel(int x, int y, byte drawMask, byte color, byte priority, byte control) {
int offset = _baseTable[y] + x;
if (drawMask & SCI_SCREEN_MASK_VISUAL) {
if (!_s->resMan->isVGA()) {
// EGA output (16 colors, dithered)
color = ((x^y) & 1) ? color >> 4 : color & 0x0F;
}
*(_visualScreen + offset) = color;
_displayScreen[_baseDisplayTable[y] + x] = color;
}
if (drawMask & SCI_SCREEN_MASK_PRIORITY)
*(_priorityScreen + offset) = priority;
if (drawMask & SCI_SCREEN_MASK_CONTROL)
*(_controlScreen + offset) = control;
}
byte SciGUIscreen::Get_Visual(int x, int y) {
return _visualScreen[_baseTable[y] + x];
}
byte SciGUIscreen::Get_Priority(int x, int y) {
return _priorityScreen[_baseTable[y] + x];
}
byte SciGUIscreen::Get_Control(int x, int y) {
return _controlScreen[_baseTable[y] + x];
}
byte SciGUIscreen::IsFillMatch(int16 x, int16 y, byte flag, byte t_color, byte t_pri, byte t_con) {
int offset = _baseTable[y] + x;
byte match = 0;
if (flag & SCI_SCREEN_MASK_VISUAL && *(_visualScreen + offset) == t_color)
match |= SCI_SCREEN_MASK_VISUAL;
if (flag & SCI_SCREEN_MASK_PRIORITY && *(_priorityScreen + offset) == t_pri)
match |= SCI_SCREEN_MASK_PRIORITY;
if (flag & SCI_SCREEN_MASK_CONTROL && *(_controlScreen + offset) == t_con)
match |= SCI_SCREEN_MASK_CONTROL;
return match;
}
int SciGUIscreen::BitsGetDataSize(Common::Rect rect, byte mask) {
int byteCount = sizeof(rect) + sizeof(mask);
int pixels = rect.width() * rect.height();
if (mask & SCI_SCREEN_MASK_VISUAL) {
byteCount += pixels + (pixels * _bytesPerDisplayPixel);
}
if (mask & SCI_SCREEN_MASK_PRIORITY) {
byteCount += pixels;
}
if (mask & SCI_SCREEN_MASK_CONTROL) {
byteCount += pixels;
}
return byteCount;
}
void SciGUIscreen::BitsSave(Common::Rect rect, byte mask, byte *memoryPtr) {
memcpy(memoryPtr, (void *)&rect, sizeof(rect)); memoryPtr += sizeof(rect);
memcpy(memoryPtr, (void *)&mask, sizeof(mask)); memoryPtr += sizeof(mask);
if (mask & SCI_SCREEN_MASK_VISUAL) {
BitsSaveScreen(rect, _visualScreen, memoryPtr);
BitsSaveScreen(rect, _displayScreen, memoryPtr);
}
if (mask & SCI_SCREEN_MASK_PRIORITY) {
BitsSaveScreen(rect, _priorityScreen, memoryPtr);
}
if (mask & SCI_SCREEN_MASK_CONTROL) {
BitsSaveScreen(rect, _controlScreen, memoryPtr);
}
}
void SciGUIscreen::BitsSaveScreen(Common::Rect rect, byte *screen, byte *&memoryPtr) {
int width = rect.width();
int height = rect.height();
int y;
screen += (rect.top * _width) + rect.left;
for (y=rect.top; y<rect.bottom; y++) {
memcpy(memoryPtr, (void*)screen, width); memoryPtr += width;
screen += _width;
}
}
void SciGUIscreen::BitsRestore(byte *memoryPtr) {
Common::Rect rect;
byte mask;
memcpy((void *)&rect, memoryPtr, sizeof(rect)); memoryPtr += sizeof(rect);
memcpy((void *)&mask, memoryPtr, sizeof(mask)); memoryPtr += sizeof(mask);
if (mask & SCI_SCREEN_MASK_VISUAL) {
BitsRestoreScreen(rect, memoryPtr, _visualScreen);
BitsRestoreScreen(rect, memoryPtr, _displayScreen);
}
if (mask & SCI_SCREEN_MASK_PRIORITY) {
BitsRestoreScreen(rect, memoryPtr, _priorityScreen);
}
if (mask & SCI_SCREEN_MASK_CONTROL) {
BitsRestoreScreen(rect, memoryPtr, _controlScreen);
}
}
void SciGUIscreen::BitsRestoreScreen(Common::Rect rect, byte *&memoryPtr, byte *screen) {
int width = rect.width();
int height = rect.height();
int y;
screen += (rect.top * _width) + rect.left;
for (y=rect.top; y<rect.bottom; y++) {
memcpy((void*) screen, memoryPtr, width); memoryPtr += width;
screen += _width;
}
}
} // end of namespace Sci

View file

@ -0,0 +1,88 @@
/* 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.
*
* $URL$
* $Id$
*
*/
namespace Sci {
#define SCI_SCREEN_MAXHEIGHT 400
#define SCI_SCREEN_MASK_VISUAL 1
#define SCI_SCREEN_MASK_PRIORITY 2
#define SCI_SCREEN_MASK_CONTROL 4
#define SCI_SCREEN_MASK_ALL SCI_SCREEN_MASK_VISUAL|SCI_SCREEN_MASK_PRIORITY|SCI_SCREEN_MASK_CONTROL
#define SCI_SCREEN_MASK_DITHERED 128
class SciGUIscreen {
public:
SciGUIscreen(OSystem *system, EngineState *state);
~SciGUIscreen();
void init(void);
byte *initScreen(uint16 pixelCount);
void UpdateWhole();
byte GetDrawingMask(byte color, byte prio, byte control);
void Put_Pixel(int x, int y, byte drawMask, byte color, byte prio, byte control);
byte Get_Visual(int x, int y);
byte Get_Priority(int x, int y);
byte Get_Control(int x, int y);
byte IsFillMatch(int16 x, int16 y, byte drawMask, byte t_color, byte t_pri, byte t_con);
int BitsGetDataSize(Common::Rect rect, byte mask);
void BitsSave(Common::Rect rect, byte mask, byte *memoryPtr);
void BitsRestore(byte *memoryPtr);
sciPalette _sysPalette;
uint16 _width;
uint16 _height;
uint _pixels;
uint16 _displayWidth;
uint16 _displayHeight;
uint _displayPixels;
byte _bytesPerDisplayPixel;
private:
void BitsRestoreScreen(Common::Rect rect, byte *&memoryPtr, byte *screen);
void BitsSaveScreen(Common::Rect rect, byte *screen, byte *&memoryPtr);
OSystem *_system;
EngineState *_s;
uint16 _baseTable[SCI_SCREEN_MAXHEIGHT];
uint16 _baseDisplayTable[SCI_SCREEN_MAXHEIGHT];
// these screens have the real resolution of the game engine (320x200 for SCI0/SCI1/SCI11 games, 640x480 for SCI2 games)
// SCI0 games will be dithered in here at any time
byte *_visualScreen;
byte *_priorityScreen;
byte *_controlScreen;
// this screen is the one that is actually displayed to the user. It may be 640x480 for japanese SCI1 games
// SCI0 games may be undithered in here. Only read from this buffer for Save/ShowBits usage.
byte *_displayScreen;
};
} // end of namespace Sci

View file

@ -0,0 +1,296 @@
/* 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.
*
* $URL$
* $Id$
*
*/
#include "sci/sci.h"
#include "sci/engine/state.h"
#include "sci/tools.h"
#include "sci/gui/gui_gfx.h"
#include "sci/gui/gui_screen.h"
#include "sci/gui/gui_view.h"
namespace Sci {
SciGUIview::SciGUIview(OSystem *system, EngineState *state, SciGUIgfx *gfx, SciGUIscreen *screen, sciResourceId resourceId)
: _system(system), _s(state), _gfx(gfx), _screen(screen), _resourceId(resourceId) {
assert(resourceId != -1);
initData(resourceId);
}
SciGUIview::~SciGUIview() {
}
void SciGUIview::initData(sciResourceId resourceId) {
Resource *viewResource = _s->resMan->findResource(ResourceId(kResourceTypeView, resourceId), false);
if (!viewResource) {
error("view resource %d not found", resourceId);
}
_resourceData = viewResource->data;
byte *cellData, *loopData;
uint16 cellOffset;
sciViewCellInfo *cell;
uint16 cellCount = 0;
uint16 mirrorBits = 0;
uint16 palOffset = 0;
uint16 headerSize = 0;
uint16 loopSize = 0, cellSize = 0;
int loopNo, cellNo;
int16 version;
byte seekEntry;
_embeddedPal = false;
_loopCount = 0;
version = READ_LE_UINT16(_resourceData + 4);
switch (version) {
case 0: // View-format SCI1
// LoopCount:WORD MirrorMask:WORD Version:WORD PaletteOffset:WORD LoopOffset0:WORD LoopOffset1:WORD...
// bit 0x8000 of _resourceData[1] means palette is set
_loopCount = _resourceData[0];
mirrorBits = READ_LE_UINT16(_resourceData + 2);
palOffset = READ_LE_UINT16(_resourceData + 6);
if (palOffset && palOffset != 0x100) {
_gfx->CreatePaletteFromData(_resourceData + palOffset, &_palette);
_embeddedPal = true;
}
_loop = new sciViewLoopInfo[_loopCount];
for (loopNo = 0; loopNo < _loopCount; loopNo++) {
loopData = _resourceData + READ_LE_UINT16(_resourceData + 8 + loopNo * 2);
// CellCount:WORD Unknown:WORD CellOffset0:WORD CellOffset1:WORD...
cellCount = READ_LE_UINT16(loopData);
_loop[loopNo].cellCount = cellCount;
_loop[loopNo].mirrorFlag = mirrorBits & 1 ? true : false;
mirrorBits >>= 1;
// read cel info
_loop[loopNo].cell = new sciViewCellInfo[cellCount];
for (cellNo = 0; cellNo < cellCount; cellNo++) {
cellOffset = READ_LE_UINT16(loopData + 4 + cellNo * 2);
cellData = _resourceData + cellOffset;
cell = &_loop[loopNo].cell[cellNo];
cell->width = READ_LE_UINT16(cellData);
cell->height = READ_LE_UINT16(cellData + 2);
cell->displaceX = cellData[4];
cell->displaceY = cellData[5];
cell->clearKey = cellData[6];
cell->offsetRLE = cellOffset + 8;
cell->offsetLiteral = 0;
cell->rawBitmap = 0;
if (_loop[loopNo].mirrorFlag)
cell->displaceX = -cell->displaceX;
}
}
break;
case 1: // View-format SCI1.1
// LoopCount:WORD MirrorMask:WORD Version:WORD PaletteOffset:WORD LoopOffset0:WORD LoopOffset1:WORD...
// HeaderSize:WORD LoopCount:WORD Version:WORD Unknown:WORD PaletteOffset:WORD
headerSize = READ_LE_UINT16(_resourceData + 0);
_loopCount = READ_LE_UINT16(_resourceData + 2);
palOffset = READ_LE_UINT16(_resourceData + 8);
loopData = _resourceData + headerSize;
loopSize = _resourceData[12];
cellSize = _resourceData[13];
if (palOffset) {
_gfx->CreatePaletteFromData(_resourceData + palOffset, &_palette);
_embeddedPal = true;
}
_loop = new sciViewLoopInfo[_loopCount];
for (loopNo = 0; loopNo < _loopCount; loopNo++) {
loopData = _resourceData + headerSize + (loopNo * loopSize);
seekEntry = loopData[2];
if (seekEntry != 255) {
loopData = _resourceData + headerSize + (seekEntry * loopNo);
}
cellCount = loopData[4];
_loop[loopNo].cellCount = cellCount;
_loop[loopNo].mirrorFlag = false;
cellData = _resourceData + READ_LE_UINT16(loopData + 14);
// read cel info
_loop[loopNo].cell = new sciViewCellInfo[cellCount];
for (cellNo = 0; cellNo < cellCount; cellNo++) {
cell = &_loop[loopNo].cell[cellNo];
cell->width = READ_LE_UINT16(cellData);
cell->height = READ_LE_UINT16(cellData + 2);
cell->displaceX = READ_LE_UINT16(cellData + 4);
cell->displaceY = READ_LE_UINT16(cellData + 6);
cell->clearKey = cellData[8];
cell->offsetRLE = READ_LE_UINT16(cellData + 24);
cell->offsetLiteral = READ_LE_UINT16(cellData + 28);
cell->rawBitmap = 0;
if (_loop[loopNo].mirrorFlag)
cell->displaceX = -cell->displaceX;
cellData += cellSize;
}
}
break;
}
}
sciResourceId SciGUIview::getResourceId() {
return _resourceId;
}
int16 SciGUIview::getWidth(uint16 loopNo, uint16 cellNo) {
loopNo = CLIP<int16>(loopNo, 0, _loopCount -1);
if (cellNo < 0 || cellNo >= _loop[loopNo].cellCount)
cellNo = 0;
return _loopCount ? _loop[loopNo].cell[cellNo].width : 0;
}
int16 SciGUIview::getHeight(uint16 loopNo, uint16 cellNo) {
loopNo = CLIP<int16>(loopNo, 0, _loopCount -1);
if (cellNo < 0 || cellNo >= _loop[loopNo].cellCount)
cellNo = 0;
return _loopCount ? _loop[loopNo].cell[cellNo].height : 0;
}
sciViewCellInfo *SciGUIview::getCellInfo(uint16 loopNo, uint16 cellNo) {
loopNo = CLIP<int16>(loopNo, 0, _loopCount -1);
if (cellNo < 0 || cellNo >= _loop[loopNo].cellCount)
cellNo = 0;
return _loopCount ? &_loop[loopNo].cell[cellNo] : NULL;
}
void SciGUIview::unpackView(uint16 loopNo, uint16 cellNo, byte *outPtr, uint16 pixelCount) {
byte *rlePtr = _resourceData + _loop[loopNo].cell[cellNo].offsetRLE;
byte *literalPtr = _resourceData + _loop[loopNo].cell[cellNo].offsetLiteral;
uint16 pixelNo = 0, brun;
byte b;
if (literalPtr == _resourceData) { // no extra literal data
while (pixelNo < pixelCount) {
b = *rlePtr++;
brun = b & 0x3F; // bytes run length on this step
switch (b & 0xC0) {
case 0: // copy bytes as-is
while (brun-- && pixelNo < pixelCount)
outPtr[pixelNo++] = *rlePtr++;
break;
case 0x80: // fill with color
memset(outPtr + pixelNo, *rlePtr++, MIN<uint16>(brun, pixelCount - pixelNo));
pixelNo += brun;
break;
case 0xC0: // fill with transparent
pixelNo += brun;
break;
}
}
} else {
while (pixelNo < pixelCount) {
b = *rlePtr++;
brun = b & 0x3F; // bytes run length on this step
switch (b & 0xC0) {
case 0: // copy bytes as-is
while (brun-- && pixelNo < pixelCount)
outPtr[pixelNo++] = *literalPtr++;
break;
case 0x80: // fill with color
memset(outPtr + pixelNo, *literalPtr++, MIN<uint16>(brun, pixelCount - pixelNo));
pixelNo += brun;
break;
case 0xC0: // fill with transparent
pixelNo += brun;
break;
}
}
}
}
byte *SciGUIview::getBitmap(uint16 loopNo, uint16 cellNo) {
loopNo = CLIP<int16>(loopNo, 0, _loopCount -1);
if (cellNo < 0 || cellNo >= _loop[loopNo].cellCount)
cellNo = 0;
if (_loop[loopNo].cell[cellNo].rawBitmap)
return _loop[loopNo].cell[cellNo].rawBitmap;
uint16 width = _loop[loopNo].cell[cellNo].width;
uint16 height = _loop[loopNo].cell[cellNo].height;
// byte *ptr = _resourceData + _loop[loopNo].cell[cellNo].offset;
// allocating memory to store cel's bitmap
assert(width * height <= 64000);
uint16 pixelCount = width * height;
_loop[loopNo].cell[cellNo].rawBitmap = new byte[pixelCount];
byte *pOut = _loop[loopNo].cell[cellNo].rawBitmap;
memset(pOut, _loop[loopNo].cell[cellNo].clearKey, pixelCount);
//if (g_sci->getPlatform() == Common::kPlatformAmiga)
// unpackViewAmiga(ptr, pOut, pixelCount);
//else
unpackView(loopNo, cellNo, pOut, pixelCount);
// mirroring the view if needed
if (_loop[loopNo].mirrorFlag) {
for (int i = 0; i < height; i++, pOut += width)
for (int j = 0; j < width / 2; j++)
SWAP(pOut[j], pOut[width - j - 1]);
}
return _loop[loopNo].cell[cellNo].rawBitmap;
}
void SciGUIview::draw(Common::Rect rect, Common::Rect clipRect, uint16 loopNo, uint16 cellNo, byte priority, uint16 paletteNo) {
sciPalette *palette = _embeddedPal ? &_palette : &_gfx->_sysPalette;
sciViewCellInfo *cellInfo = getCellInfo(loopNo, cellNo);
byte *bitmap = getBitmap(loopNo, cellNo);
int16 cellHeight = cellInfo->height, cellWidth = cellInfo->width;
int16 width, height;
byte clearKey = cellInfo->clearKey;
byte color;
byte drawMask = priority == 255 ? SCI_SCREEN_MASK_VISUAL : SCI_SCREEN_MASK_VISUAL|SCI_SCREEN_MASK_PRIORITY;
int x, y;
// Merge view palette in...
if (_embeddedPal)
_gfx->SetPalette(&_palette, 1);
width = MIN(clipRect.width(), cellWidth);
height = MIN(clipRect.height(), cellHeight);
bitmap += (clipRect.top - rect.top) * cellWidth + (clipRect.left - rect.left);
_gfx->OffsetRect(clipRect);
for (y = clipRect.top; y < clipRect.top + height; y++, bitmap += cellWidth) {
for (x = 0; x < width; x++) {
color = bitmap[x];
if (color != clearKey && priority >= _screen->Get_Priority(clipRect.left + x, y))
_screen->Put_Pixel(clipRect.left + x, y, drawMask, palette->mapping[color], priority, 0);
}
}
}
} // end of namespace Sci

View file

@ -0,0 +1,77 @@
/* 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.
*
* $URL$
* $Id$
*
*/
namespace Sci {
struct sciViewCellInfo {
int16 width, height;
char displaceX;
byte displaceY;
byte clearKey;
uint16 offsetRLE;
uint16 offsetLiteral;
byte *rawBitmap;
};
struct sciViewLoopInfo {
bool mirrorFlag;
int16 cellCount;
sciViewCellInfo *cell;
};
class SciGUIview {
public:
SciGUIview(OSystem *system, EngineState *state, SciGUIgfx *gfx, SciGUIscreen *screen, sciResourceId resourceId);
~SciGUIview();
// TODO: Remove gfx reference after putting palette things into SciGUIscreen
sciResourceId getResourceId();
int16 getWidth(uint16 loopNo, uint16 cellNo);
int16 getHeight(uint16 loopNo, uint16 cellNo);
sciViewCellInfo *getCellInfo(uint16 loop, uint16 cel);
sciViewLoopInfo *getLoopInfo(uint16 loop);
byte *getBitmap(uint16 loopNo, uint16 cellNo);
void draw(Common::Rect rect, Common::Rect clipRect, uint16 loopNo, uint16 cellNo, byte priority, uint16 paletteNo);
private:
void initData(sciResourceId resourceId);
void unpackView(uint16 loopNo, uint16 cellNo, byte *outPtr, uint16 pixelCount);
OSystem *_system;
EngineState *_s;
SciGUIgfx *_gfx;
SciGUIscreen *_screen;
sciResourceId _resourceId;
byte *_resourceData;
uint16 _loopCount;
sciViewLoopInfo *_loop;
bool _embeddedPal;
sciPalette _palette;
};
} // end of namespace Sci

View file

@ -0,0 +1,326 @@
/* 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.
*
* $URL$
* $Id$
*
*/
#include "common/util.h"
#include "sci/sci.h"
#include "sci/engine/state.h"
#include "sci/tools.h"
#include "sci/gui/gui_gfx.h"
#include "sci/gui/gui_windowmgr.h"
#include "sci/gui/gui_memmgr.h"
namespace Sci {
Common::Rect _picRect(0,10,320, 200);
// window styles
enum {
TRANSPARENT = 1,
NOFRAME = 2,
TITLE = 4,
TOPMOST = 8,
USER = 0x80
};
SciGUIwindowMgr::SciGUIwindowMgr(EngineState *state, SciGUIgfx *gfx)
: _s(state), _gfx(gfx) {
// FIXME: remove memmgr
InitMem(0x320);
HEAPHANDLE wmgrPortH = heapNewPtr(sizeof(sciPort), kDataPort, "wmgrPort");
heapClearPtr(wmgrPortH);
_wmgrPort = (sciPort *)heap2Ptr(wmgrPortH);
int16 offTop = 20;
_gfx->OpenPort(_wmgrPort);
_gfx->SetPort(_wmgrPort);
_gfx->SetOrigin(0, offTop);
_wmgrPort->rect.bottom = 200 - offTop;
_wmgrPort->rect.right = 320;
_wmgrPort->rect.moveTo(0, 0);
_wmgrPort->curTop = 0;
_wmgrPort->curLeft = 0;
windowList.AddToFront(wmgrPortH);
_picWind = NewWindow(&_picRect, 0, 0, TRANSPARENT | NOFRAME, 0, 1);
}
SciGUIwindowMgr::~SciGUIwindowMgr() {
}
int16 SciGUIwindowMgr::isFrontWindow(sciWnd *pWnd) {
if (heap2Ptr(windowList.getLast()) == (byte *)pWnd)
return 1;
return 0;
}
void SciGUIwindowMgr::SelectWindow(HEAPHANDLE hh) {
sciPort *port = (sciPort *)heap2Ptr(hh);
_gfx->SetPort(port);
if (hh != windowList.getLast()) { // selecting not topmost window
sciWnd *prevwnd = (sciWnd *)heap2Ptr(port->node.prev);
BeginUpdate(prevwnd);
windowList.MoveToEnd(hh);
EndUpdate(prevwnd);
}
_gfx->SetPort(port);
}
void SciGUIwindowMgr::BeginUpdate(sciWnd *wnd) {
sciPort *oldPort = _gfx->SetPort(_wmgrPort);
sciWnd *node = (sciWnd *)heap2Ptr(windowList.getLast());
while (node != wnd) {
UpdateWindow(node);
node = (sciWnd *)heap2Ptr(node->node.prev);
}
_gfx->SetPort(oldPort);
}
void SciGUIwindowMgr::EndUpdate(sciWnd *wnd) {
sciPort *oldPort = _gfx->SetPort(_wmgrPort);
sciWnd *last = (sciWnd *)heap2Ptr(windowList.getLast());
while (wnd != last) {
wnd = (sciWnd *)heap2Ptr(wnd->node.next);
UpdateWindow(wnd);
}
_gfx->SetPort(oldPort);
}
SCILanguage SciGUIwindowMgr::getSCILanguage() {
return kLangEnglish;
}
char *SciGUIwindowMgr::StrSplit(char *buff, const char *msg, const char *fmt) {
SCILanguage gameLang = getSCILanguage();
SCILanguage subtitleLang = kLangNone;
char *retval;
// if (_theGame.getHandle())
//subtitleLang = (SCILanguage)_theGame.getProperty(0x58); // subtitleLang property
if (buff == msg) {
char str[2000];
getIntlString(str, msg, fmt, gameLang, subtitleLang);
retval = strcpy(buff, str);
} else
retval = getIntlString(buff, msg, fmt, gameLang, subtitleLang);
return retval;
}
//--------------------------------
// In multilanguage game the msg has format ___english_text__#I___italian_text___
// The function should place in buff a translated part of msg or the 1st one if a translation
// does not exist
char *SciGUIwindowMgr::getIntlString(char *buff, const char *msg, const char *fmt,
SCILanguage gameLang, SCILanguage subtitleLang) {
// prefer subtitleLang if set
SCILanguage lang = subtitleLang != kLangNone ? subtitleLang : gameLang;
const char *ptr = msg, *szFrom;
char ch;
int nLen = 0;
// searching for language code in msg
while (*ptr) {
ch = *(ptr + 1);
if(*ptr == '#' && (ch == 'I' || ch == 'F' || ch == 'G' || ch == 'S')) {
ptr +=2;
break;
}
ptr++;
}
// if a language code was found...
if (*ptr) {
if ((lang == kLangItalian && ch == 'I') || (lang == kLangFrench && ch == 'F') ||
(lang == kLangGerman && ch == 'G') || (lang == kLangSpanish && ch == 'S')) {
nLen = (int)strlen(ptr);
szFrom = ptr;
} else {
nLen = ptr - msg - 2;
szFrom = msg;
}
} else {
nLen = ptr - msg;
szFrom = msg;
}
if (fmt && subtitleLang != kLangNone) {
strcpy(buff, fmt);
strncat(buff, szFrom, nLen);
buff[nLen + strlen(fmt)] = 0;
} else {
strncpy(buff, szFrom, nLen);
buff[nLen] = 0;
}
return buff;
}
sciWnd *SciGUIwindowMgr::NewWindow(Common::Rect *rect, Common::Rect *rect2, const char *title, uint16 style, uint16 arg8, uint16 argA) {
HEAPHANDLE hWnd = heapNewPtr(sizeof(sciWnd), kDataWindow, title);
Common::Rect r;
if (!hWnd) {
warning("Can't open window!");
return 0;
}
heapClearPtr(hWnd);
if (style & TOPMOST)
windowList.AddToFront(hWnd);
else
windowList.AddToEnd(hWnd);
sciWnd *pwnd = (sciWnd *)heap2Ptr(hWnd);
_gfx->OpenPort((sciPort *)pwnd);
r = *rect;
pwnd->rect = *rect;
if (rect2)
pwnd->rect1 = *rect2;
pwnd->wndStyle = style;
pwnd->hSaved1 = pwnd->hSaved2 = NULL_REG;
pwnd->bDrawed = false;
if ((style & TRANSPARENT) == 0)
pwnd->uSaveFlag = (arg8 == 0xFFFF ? 1 : 3);
if (title && (style & TITLE)) {
HEAPHANDLE hTitle = heapNewPtr((uint16)strlen(title) + 1, kDataString, title);
if (!hTitle) {
warning("Can't open window!");
return 0;
}
pwnd->hTitle = hTitle;
StrSplit((char *)heap2Ptr(hTitle), title, NULL);
}
r = *rect;
if (style == USER || (style & NOFRAME) == 0) {
r.grow(1);
if (style & TITLE) {
r.top -= 10;
r.bottom++;
}
}
pwnd->rect0 = r;
const Common::Rect *wmprect = &_wmgrPort->rect;
int16 oldtop = pwnd->rect0.top;
int16 oldleft = pwnd->rect0.left;
if (wmprect->top > pwnd->rect0.top)
pwnd->rect0.moveTo(pwnd->rect0.left, wmprect->top);
if (wmprect->bottom < pwnd->rect0.bottom)
pwnd->rect0.moveTo(pwnd->rect0.left, wmprect->bottom
- pwnd->rect0.bottom + pwnd->rect0.top);
if (wmprect->right < pwnd->rect0.right)
pwnd->rect0.moveTo(wmprect->right + pwnd->rect0.left
- pwnd->rect0.right, pwnd->rect0.top);
if (wmprect->left > pwnd->rect0.left)
pwnd->rect0.moveTo(wmprect->left, pwnd->rect0.top);
pwnd->rect.moveTo(pwnd->rect.left + pwnd->rect0.left - oldleft,
pwnd->rect.top + pwnd->rect0.top - oldtop);
if (rect2 == 0)
pwnd->rect1 = pwnd->rect0;
if (argA)
DrawWindow(pwnd);
_gfx->SetPort((sciPort *)pwnd);
_gfx->SetOrigin(pwnd->rect.left, pwnd->rect.top + _wmgrPort->top);
pwnd->rect.moveTo(0, 0);
return pwnd;
}
void SciGUIwindowMgr::DrawWindow(sciWnd *pWnd) {
if (pWnd->bDrawed)
return;
Common::Rect r;
int16 wndStyle = pWnd->wndStyle;
pWnd->bDrawed = true;
sciPort *oldport = _gfx->SetPort(_wmgrPort);
_gfx->PenColor(0);
if ((wndStyle & TRANSPARENT) == 0) {
pWnd->hSaved1 = _gfx->SaveBits(pWnd->rect1, 1);
if (pWnd->uSaveFlag & 2) {
pWnd->hSaved2 = _gfx->SaveBits(pWnd->rect1, 2);
if ((wndStyle & USER) == 0)
_gfx->FillRect(pWnd->rect1, 2, 0, 0xF);
}
}
// drawing frame,shadow and title
if ((wndStyle & USER) == 0) {
r = pWnd->rect0;
if ((wndStyle & NOFRAME) == 0) {
r.translate(1, 1);
_gfx->FrameRect(r);// shadow
r.translate(-1, -1);
_gfx->FrameRect(r);// window frame
if (wndStyle & TITLE) {
_gfx->FrameRect(r);
r.grow(-1);
_gfx->FillRect(r, 1, 0);
if (pWnd->hTitle) {
int16 oldcolor = _gfx->GetPort()->penClr;
_gfx->PenColor(255);
_gfx->TextBox((char *)heap2Ptr(pWnd->hTitle), 1, r, 1, 0);
_gfx->PenColor(oldcolor);
}
r = pWnd->rect0;
r.top += 9;
}
r.grow(-1);
}
if ((wndStyle & TRANSPARENT) == 0)
_gfx->FillRect(r, 1, pWnd->backClr);
_gfx->ShowBits(pWnd->rect0, 1);
}
_gfx->SetPort(oldport);
}
void SciGUIwindowMgr::DisposeWindow(sciWnd *pWnd, int16 arg2) {
_gfx->SetPort(_wmgrPort);
_gfx->RestoreBits(pWnd->hSaved1);
_gfx->RestoreBits(pWnd->hSaved2);
if (arg2)
_gfx->ShowBits(pWnd->rect0, 1);
// else
// g_sci->ReAnimate(&pwnd->rect0);
HEAPHANDLE hh = ptr2heap((byte *)pWnd);
windowList.DeleteNode(hh);
SelectWindow(windowList.getLast());
if (pWnd->hTitle)
heapDisposePtr(pWnd->hTitle);
heapDisposePtr(hh);
}
void SciGUIwindowMgr::UpdateWindow(sciWnd *wnd) {
}
} // end of namespace Sci

View file

@ -0,0 +1,57 @@
/* 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.
*
* $URL$
* $Id$
*
*/
#include "sci/gui/gui_dbllist.h"
namespace Sci {
class SciGUIwindowMgr {
public:
SciGUIwindowMgr(EngineState *state, SciGUIgfx *gfx);
~SciGUIwindowMgr();
int16 isFrontWindow(sciWnd *wnd);
void SelectWindow(HEAPHANDLE hh);
void BeginUpdate(sciWnd *wnd);
void EndUpdate(sciWnd *wnd);
SCILanguage getSCILanguage();
char* StrSplit(char*buff, const char*msg, const char*fmt);
char* getIntlString(char*buff, const char*msg, const char*fmt, SCILanguage lang, SCILanguage prop);
sciWnd *NewWindow(Common::Rect *rect, Common::Rect *rect2, const char *title, uint16 style, uint16 arg8, uint16 argA);
void DrawWindow(sciWnd *wnd);
void DisposeWindow(sciWnd *pWnd, int16 arg2);
void UpdateWindow(sciWnd *wnd);
sciPort *_wmgrPort;
sciWnd *_picWind;
private:
EngineState *_s;
SciGUIgfx *_gfx;
DblList windowList;
};
} // end of namespace Sci

732
engines/sci/gui32/gui32.cpp Normal file
View file

@ -0,0 +1,732 @@
/* 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.
*
* $URL$
* $Id$
*
*/
#include "common/util.h"
#include "sci/sci.h"
#include "sci/engine/state.h"
#include "sci/tools.h"
#include "sci/debug.h" // for g_debug_sleeptime_factor
#include "sci/resource.h"
#include "sci/engine/state.h"
#include "sci/engine/kernel.h"
#include "sci/gfx/gfx_gui.h"
#include "sci/gfx/gfx_widgets.h"
#include "sci/gfx/gfx_state_internal.h" // required for GfxContainer, GfxPort, GfxVisual
#include "sci/gui32/gui32.h"
// This is the real width of a text with a specified width of 0
#define MAX_TEXT_WIDTH_MAGIC_VALUE 192
#define ADD_TO_CURRENT_PORT(widget) \
{if (s->port) \
s->port->add((GfxContainer *)s->port, widget); \
else \
s->picture_port->add((GfxContainer *)s->visual, widget);}
#define ADD_TO_CURRENT_PICTURE_PORT(widget) \
{if (s->port) \
s->port->add((GfxContainer *)s->port, widget); \
else \
s->picture_port->add((GfxContainer *)s->picture_port, widget);}
#define ADD_TO_WINDOW_PORT(widget) \
s->wm_port->add((GfxContainer *)s->wm_port, widget);
#define FULL_REDRAW()\
if (s->visual) \
s->visual->draw(gfxw_point_zero); \
gfxop_update(s->gfx_state);
#define K_DRAWPIC_FLAG_MIRRORED (1 << 14)
namespace Sci {
SciGUI32::SciGUI32(OSystem *system, EngineState *state)
: _system(system), s(state) {
}
SciGUI32::~SciGUI32() {
}
void SciGUI32::init(bool oldGfxFunctions) {
_usesOldGfxFunctions = oldGfxFunctions;
activated_icon_bar = false;
port_origin_x = 0;
port_origin_y = 0;
}
int16 SciGUI32::getTimeTicks() {
uint32 start_time;
start_time = _system->getMillis() - s->game_start_time;
return start_time * 60 / 1000;
}
void SciGUI32::wait(int16 ticks) {
uint32 time;
time = g_system->getMillis();
s->r_acc = make_reg(0, ((long)time - (long)s->last_wait_time) * 60 / 1000);
s->last_wait_time = time;
ticks *= g_debug_sleeptime_factor;
gfxop_sleep(s->gfx_state, ticks * 1000 / 60);
// Reset speed throttler: Game is playing along nicely anyway
if (ticks > 0)
s->speedThrottler->reset();
}
void SciGUI32::setPort(uint16 portPtr) {
GfxPort *new_port;
/* We depart from official semantics here, sorry!
Reasoning: Sierra SCI does not clip ports while we do.
Therefore a draw to the titlebar port (which is the
official semantics) would cut off the lower part of the
icons in an SCI1 icon bar. Instead we have an
iconbar_port that does not exist in SSCI. */
if (portPtr == 65535) portPtr = s->iconbar_port->_ID;
new_port = s->visual->getPort(portPtr);
if (!new_port) {
warning("Invalid port %04x requested", portPtr);
return;
}
s->port->draw(gfxw_point_zero); // Update the port we're leaving
s->port = new_port;
}
void SciGUI32::setPortPic(Common::Rect rect, int16 picTop, int16 picLeft) {
if (activated_icon_bar) {
port_origin_x = port_origin_y = 0;
activated_icon_bar = false;
return;
}
port_origin_y = rect.top;
port_origin_x = rect.left;
if (rect.top == -10) {
s->port->draw(gfxw_point_zero); // Update the port we're leaving
s->port = s->iconbar_port;
activated_icon_bar = true;
return;
}
// Notify the graphics resource manager that the pic port bounds changed
s->gfx_state->gfxResMan->changePortBounds(picLeft, picTop, rect.right + picLeft, rect.bottom + picTop);
// LSL6 calls kSetPort to extend the screen to draw the GUI. If we free all resources
// here, the background picture is freed too, and this makes everything a big mess.
// FIXME/TODO: This code really needs to be rewritten to conform to the original behavior
if (s->_gameName != "lsl6") {
s->gfx_state->pic_port_bounds = gfx_rect(picLeft, picTop, rect.right, rect.bottom);
// FIXME: Should really only invalidate all loaded pic resources here;
// this is overkill
s->gfx_state->gfxResMan->freeAllResources();
} else {
// WORKAROUND for LSL6
warning("SetPort case 6 called in LSL6.");
}
}
reg_t SciGUI32::getPort() {
return make_reg(0, s->port->_ID);
}
void SciGUI32::globalToLocal(int16 *x, int16 *y) {
*x = *x - s->port->zone.x;
*y = *y - s->port->zone.y;
}
void SciGUI32::localToGlobal(int16 *x, int16 *y) {
*x = *x + s->port->zone.x;
*y = *y + s->port->zone.y;
}
reg_t SciGUI32::newWindow(Common::Rect rect1, Common::Rect rect2, uint16 style, int16 priority, int16 colorPen, int16 colorBack, const char *title) {
GfxPort *window;
int x, y, xl, yl;
gfx_color_t bgcolor;
gfx_color_t fgcolor;
gfx_color_t black;
gfx_color_t lWhite;
y = rect1.top;
x = rect1.left;
yl = rect1.height();
xl = rect1.width();
y += s->wm_port->_bounds.y;
if (x + xl > 319)
x -= ((x + xl) - 319);
bgcolor.mask = 0;
if (colorBack >= 0) {
if (!s->resMan->isVGA())
bgcolor.visual = get_pic_color(s, MIN<int>(colorBack, 15));
else
bgcolor.visual = get_pic_color(s, colorBack);
bgcolor.mask = GFX_MASK_VISUAL;
} else {
bgcolor.visual = PaletteEntry(0,0,0);
}
bgcolor.priority = priority;
bgcolor.mask |= priority >= 0 ? GFX_MASK_PRIORITY : 0;
bgcolor.alpha = 0;
bgcolor.control = -1;
debugC(2, kDebugLevelGraphics, "New window with params %d, %d, %d, %d\n", rect1.top, rect1.left, rect1.height(), rect1.width());
fgcolor.visual = get_pic_color(s, colorPen);
fgcolor.mask = GFX_MASK_VISUAL;
fgcolor.control = -1;
fgcolor.priority = -1;
fgcolor.alpha = 0;
black.visual = get_pic_color(s, 0);
black.mask = GFX_MASK_VISUAL;
black.alpha = 0;
black.control = -1;
black.priority = -1;
lWhite.visual = get_pic_color(s, !s->resMan->isVGA() ? 15 : 255);
lWhite.mask = GFX_MASK_VISUAL;
lWhite.alpha = 0;
lWhite.priority = -1;
lWhite.control = -1;
window = sciw_new_window(s, gfx_rect(x, y, xl, yl), s->titlebar_port->_font, fgcolor, bgcolor,
s->titlebar_port->_font, lWhite, black, title ? s->strSplit(title, NULL).c_str() : NULL, style);
// PQ3 and SCI1.1 games have the interpreter store underBits implicitly
if (rect2.top != 0 && rect2.left != 0 && rect2.height() != 0 && rect2.width() != 0)
gfxw_port_auto_restore_background(s->visual, window, gfx_rect(rect2.left, rect2.top + s->wm_port->_bounds.y, rect2.width(), rect2.height()));
ADD_TO_WINDOW_PORT(window);
FULL_REDRAW();
window->draw(gfxw_point_zero);
gfxop_update(s->gfx_state);
s->port = window; // Set active port
return make_reg(0, window->_ID);
}
void SciGUI32::disposeWindow(uint16 windowPtr, int16 arg2) {
GfxPort *goner;
GfxPort *pred;
goner = s->visual->getPort(windowPtr);
if ((windowPtr < 3) || (goner == NULL)) {
error("Removal of invalid window %04x requested", windowPtr);
return;
}
if (s->dyn_views && (GfxContainer *)s->dyn_views->_parent == (GfxContainer *)goner) {
reparentize_primary_widget_lists(s, (GfxPort *) goner->_parent);
}
if (s->drop_views && (GfxContainer *)s->drop_views->_parent == (GfxContainer *)goner)
s->drop_views = NULL; // Kill it
pred = gfxw_remove_port(s->visual, goner);
if (goner == s->port) // Did we kill the active port?
s->port = pred;
// Find the last port that exists and that isn't marked no-switch
int id = s->visual->_portRefs.size() - 1;
while (id > 0 && (!s->visual->_portRefs[id] || (s->visual->_portRefs[id]->_flags & GFXW_FLAG_NO_IMPLICIT_SWITCH)))
id--;
debugC(2, kDebugLevelGraphics, "Activating port %d after disposing window %d\n", id, windowPtr);
s->port = (id >= 0) ? s->visual->_portRefs[id] : 0;
if (!s->port)
s->port = gfxw_find_default_port(s->visual);
gfxop_update(s->gfx_state);
}
#define K_DISPLAY_SET_COORDS 100
#define K_DISPLAY_SET_ALIGNMENT 101
#define K_DISPLAY_SET_COLOR 102
#define K_DISPLAY_SET_BGCOLOR 103
#define K_DISPLAY_SET_GRAYTEXT 104
#define K_DISPLAY_SET_FONT 105
#define K_DISPLAY_WIDTH 106
#define K_DISPLAY_SAVE_UNDER 107
#define K_DISPLAY_RESTORE_UNDER 108
#define K_DONT_UPDATE_IMMEDIATELY 121
void SciGUI32::display(const char *text, int argc, reg_t *argv) {
int argpt = 0;
int temp;
bool save_under = false;
gfx_color_t transparent = { PaletteEntry(), 0, -1, -1, 0 };
GfxPort *port = (s->port) ? s->port : s->picture_port;
bool update_immediately = true;
gfx_color_t color0, *color1, bg_color;
gfx_alignment_t halign = ALIGN_LEFT;
rect_t area = gfx_rect(port->draw_pos.x, port->draw_pos.y, 320 - port->draw_pos.x, 200 - port->draw_pos.y);
int gray = port->gray_text;
int font_nr = port->_font;
GfxText *text_handle;
color0 = port->_color;
bg_color = port->_bgcolor;
// TODO: in SCI1VGA the default colors for text and background are #0 (black)
// SCI0 case should be checked
if (s->resMan->isVGA()) {
// This priority check fixes the colors in the menus in KQ5
// TODO/FIXME: Is this correct?
if (color0.priority >= 0)
color0.visual = get_pic_color(s, 0);
if (bg_color.priority >= 0)
bg_color.visual = get_pic_color(s, 0);
}
while (argpt < argc) {
switch (argv[argpt++].toUint16()) {
case K_DISPLAY_SET_COORDS:
area.x = argv[argpt++].toUint16();
area.y = argv[argpt++].toUint16();
debugC(2, kDebugLevelGraphics, "Display: set_coords(%d, %d)\n", area.x, area.y);
break;
case K_DISPLAY_SET_ALIGNMENT:
halign = (gfx_alignment_t)argv[argpt++].toSint16();
debugC(2, kDebugLevelGraphics, "Display: set_align(%d)\n", halign);
break;
case K_DISPLAY_SET_COLOR:
temp = argv[argpt++].toSint16();
debugC(2, kDebugLevelGraphics, "Display: set_color(%d)\n", temp);
if (!s->resMan->isVGA() && temp >= 0 && temp <= 15)
color0 = (s->ega_colors[temp]);
else
if (s->resMan->isVGA() && temp >= 0 && temp < 256) {
color0.visual = get_pic_color(s, temp);
color0.mask = GFX_MASK_VISUAL;
} else
if (temp == -1)
color0 = transparent;
else
warning("Display: Attempt to set invalid fg color %d", temp);
break;
case K_DISPLAY_SET_BGCOLOR:
temp = argv[argpt++].toSint16();
debugC(2, kDebugLevelGraphics, "Display: set_bg_color(%d)\n", temp);
if (!s->resMan->isVGA() && temp >= 0 && temp <= 15)
bg_color = s->ega_colors[temp];
else
if (s->resMan->isVGA() && temp >= 0 && temp <= 256) {
bg_color.visual = get_pic_color(s, temp);
bg_color.mask = GFX_MASK_VISUAL;
} else
if (temp == -1)
bg_color = transparent;
else
warning("Display: Attempt to set invalid fg color %d", temp);
break;
case K_DISPLAY_SET_GRAYTEXT:
gray = argv[argpt++].toSint16();
debugC(2, kDebugLevelGraphics, "Display: set_graytext(%d)\n", gray);
break;
case K_DISPLAY_SET_FONT:
font_nr = argv[argpt++].toUint16();
debugC(2, kDebugLevelGraphics, "Display: set_font(\"font.%03d\")\n", font_nr);
break;
case K_DISPLAY_WIDTH:
area.width = argv[argpt++].toUint16();
if (area.width == 0)
area.width = MAX_TEXT_WIDTH_MAGIC_VALUE;
debugC(2, kDebugLevelGraphics, "Display: set_width(%d)\n", area.width);
break;
case K_DISPLAY_SAVE_UNDER:
save_under = true;
debugC(2, kDebugLevelGraphics, "Display: set_save_under()\n");
break;
case K_DISPLAY_RESTORE_UNDER:
debugC(2, kDebugLevelGraphics, "Display: restore_under(%04x)\n", argv[argpt].toUint16());
graph_restore_box(s, argv[argpt++]);
update_immediately = true;
argpt++;
return;
case K_DONT_UPDATE_IMMEDIATELY:
update_immediately = false;
debugC(2, kDebugLevelGraphics, "Display: set_dont_update()\n");
argpt++;
break;
default:
debugC(2, kDebugLevelGraphics, "Unknown Display() command %x\n", argv[argpt - 1].toUint16());
return;
}
}
if (halign == ALIGN_LEFT) {
// If the text does not fit on the screen, move it to the left and upwards until it does
gfxop_get_text_params(s->gfx_state, font_nr, text, area.width, &area.width, &area.height, 0, NULL, NULL, NULL);
// Make the text fit on the screen
if (area.x + area.width > 320)
area.x += 320 - area.x - area.width; // Plus negative number = subtraction
if (area.y + area.height > 200)
area.y += 200 - area.y - area.height; // Plus negative number = subtraction
} else {
// If the text does not fit on the screen, clip it till it does
if (area.x + area.width > s->gfx_state->pic_port_bounds.width)
area.width = s->gfx_state->pic_port_bounds.width - area.x;
if (area.y + area.height > s->gfx_state->pic_port_bounds.height)
area.height = s->gfx_state->pic_port_bounds.height - area.y;
}
if (gray)
color1 = &bg_color;
else
color1 = &color0;
assert_primary_widget_lists(s);
text_handle = gfxw_new_text(s->gfx_state, area, font_nr, s->strSplit(text).c_str(), halign, ALIGN_TOP, color0, *color1, bg_color, 0);
if (!text_handle) {
error("Display: Failed to create text widget");
return;
}
if (save_under) { // Backup
rect_t save_area = text_handle->_bounds;
save_area.x += port->_bounds.x;
save_area.y += port->_bounds.y;
s->r_acc = graph_save_box(s, save_area);
text_handle->_serial++; // This is evil!
debugC(2, kDebugLevelGraphics, "Saving (%d, %d) size (%d, %d) as %04x:%04x\n", save_area.x, save_area.y, save_area.width, save_area.height, PRINT_REG(s->r_acc));
}
debugC(2, kDebugLevelGraphics, "Display: Commiting text '%s'\n", text);
//ADD_TO_CURRENT_PICTURE_PORT(text_handle);
ADD_TO_CURRENT_PICTURE_PORT(text_handle);
if ((!s->pic_not_valid) && update_immediately) { // Refresh if drawn to valid picture
FULL_REDRAW();
debugC(2, kDebugLevelGraphics, "Refreshing display...\n");
}
}
void SciGUI32::textSize(const char *text, int16 fontId, int16 maxWidth, int16 *textWidth, int16 *textHeight) {
int width, height;
if (maxWidth < 0)
maxWidth = 0;
gfxop_get_text_params(s->gfx_state, fontId, text, maxWidth ? maxWidth : MAX_TEXT_WIDTH_MAGIC_VALUE,
&width, &height, 0, NULL, NULL, NULL);
*textWidth = width; *textHeight = height;
}
void SciGUI32::textFonts(int argc, reg_t *argv) {
// stub
}
void SciGUI32::textColors(int argc, reg_t *argv) {
// stub
}
void SciGUI32::drawPicture(sciResourceId pictureId, uint16 showStyle, uint16 flags, int16 EGApaletteNo) {
drawn_pic_t dp;
gfx_color_t transparent = s->wm_port->_bgcolor;
int picFlags = DRAWPIC01_FLAG_FILL_NORMALLY;
bool add_to_pic = flags;
dp.nr = pictureId;
if (EGApaletteNo != -1) {
dp.palette = EGApaletteNo;
} else {
dp.palette = 0;
}
if (showStyle & K_DRAWPIC_FLAG_MIRRORED)
picFlags |= DRAWPIC1_FLAG_MIRRORED;
gfxop_disable_dirty_frames(s->gfx_state);
if (NULL != s->old_screen) {
gfxop_free_pixmap(s->gfx_state, s->old_screen);
}
s->old_screen = gfxop_grab_pixmap(s->gfx_state, gfx_rect(0, 10, 320, 190));
debugC(2, kDebugLevelGraphics, "Drawing pic.%03d\n", pictureId);
if (add_to_pic) {
gfxop_add_to_pic(s->gfx_state, dp.nr, picFlags, dp.palette);
} else {
gfxop_new_pic(s->gfx_state, dp.nr, picFlags, dp.palette);
}
delete s->wm_port;
delete s->picture_port;
delete s->iconbar_port;
s->wm_port = new GfxPort(s->visual, s->gfx_state->pic_port_bounds, s->ega_colors[0], transparent);
s->picture_port = new GfxPort(s->visual, s->gfx_state->pic_port_bounds, s->ega_colors[0], transparent);
s->iconbar_port = new GfxPort(s->visual, gfx_rect(0, 0, 320, 200), s->ega_colors[0], transparent);
s->iconbar_port->_flags |= GFXW_FLAG_NO_IMPLICIT_SWITCH;
s->visual->add((GfxContainer *)s->visual, s->picture_port);
s->visual->add((GfxContainer *)s->visual, s->wm_port);
s->visual->add((GfxContainer *)s->visual, s->iconbar_port);
s->port = s->picture_port;
s->pic_priority_table = gfxop_get_pic_metainfo(s->gfx_state);
s->pic_animate = showStyle & 0xff; // The animation used during kAnimate() later on
s->dyn_views = NULL;
s->drop_views = NULL;
s->priority_first = 42;
if (_usesOldGfxFunctions)
s->priority_last = 200;
else
s->priority_last = 190;
s->pic_not_valid = 1;
s->pic_is_new = 1;
}
void SciGUI32::drawCell(sciResourceId viewId, uint16 loopNo, uint16 cellNo, uint16 leftPos, uint16 topPos, int16 priority, uint16 paletteNo) {
int loop = loopNo;
int cel = cellNo;
GfxView *new_view;
gfxop_check_cel(s->gfx_state, viewId, &loop, &cel);
debugC(2, kDebugLevelGraphics, "DrawCel((%d,%d), (view.%d, %d, %d), p=%d)\n", leftPos, topPos, viewId, loop, cel, priority);
new_view = gfxw_new_view(s->gfx_state, Common::Point(leftPos, topPos), viewId, loop, cel, 0, priority, -1,
ALIGN_LEFT, ALIGN_TOP, GFXW_VIEW_FLAG_DONT_MODIFY_OFFSET);
ADD_TO_CURRENT_PICTURE_PORT(new_view);
FULL_REDRAW();
}
void SciGUI32::drawControlButton(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 style, bool inverse) {
rect_t area = gfx_rect(rect.left, rect.top, rect.width(), rect.height());
ADD_TO_CURRENT_PICTURE_PORT(sciw_new_button_control(s->port, obj, area, text, fontId,
(int8)(style & kControlStateFramed), (int8)inverse, (int8)(style & kControlStateDisabled)));
if (!s->pic_not_valid) FULL_REDRAW();
}
void SciGUI32::drawControlText(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 mode, int16 style, bool inverse) {
rect_t area = gfx_rect(rect.left, rect.top, rect.width(), rect.height());
ADD_TO_CURRENT_PICTURE_PORT(sciw_new_text_control(s->port, obj, area, text, fontId, (gfx_alignment_t) mode,
(int8)(!!(style & kControlStateDitherFramed)), (int8)inverse));
if (!s->pic_not_valid) FULL_REDRAW();
}
static gfx_color_t graph_map_color(EngineState *s, int color, int priority, int control) {
gfx_color_t retval;
if (!s->resMan->isVGA()) {
retval = s->ega_colors[(color >=0 && color < 16)? color : 0];
gfxop_set_color(s->gfx_state, &retval, (color < 0) ? -1 : retval.visual.r, retval.visual.g, retval.visual.b,
(color == -1) ? 255 : 0, priority, control);
} else {
retval.visual = get_pic_color(s, color);
retval.alpha = 0;
retval.priority = priority;
retval.control = control;
retval.mask = GFX_MASK_VISUAL | ((priority >= 0) ? GFX_MASK_PRIORITY : 0) | ((control >= 0) ? GFX_MASK_CONTROL : 0);
};
return retval;
}
void _k_graph_rebuild_port_with_color(EngineState *s, gfx_color_t newbgcolor) {
GfxPort *port = s->port;
GfxPort *newport;
newport = sciw_new_window(s, port->zone, port->_font, port->_color, newbgcolor,
s->titlebar_port->_font, s->ega_colors[15], s->ega_colors[8],
port->_title_text.c_str(), port->port_flags & ~kWindowTransparent);
if (s->dyn_views) {
int found = 0;
GfxContainer *parent = s->dyn_views->_parent;
while (parent && !(found |= (parent == port)))
parent = parent->_parent;
s->dyn_views = NULL;
}
port->_parent->add((GfxContainer *)port->_parent, newport);
delete port;
}
void SciGUI32::graphFillBoxForeground(Common::Rect rect) {
_k_graph_rebuild_port_with_color(s, s->port->_color);
//port = _s->port;
FULL_REDRAW();
}
void SciGUI32::graphFillBoxBackground(Common::Rect rect) {
_k_graph_rebuild_port_with_color(s, s->port->_bgcolor);
//port = _s->port;
FULL_REDRAW();
}
void SciGUI32::graphFillBox(Common::Rect rect, uint16 colorMask, int16 color, int16 priority, int16 control) {
gfx_color_t fillColor = graph_map_color(s, color, priority, control);
fillColor.mask = (byte)colorMask;
rect_t area = gfx_rect(rect.left, rect.top, rect.width(), rect.height());
//debugC(2, kDebugLevelGraphics, "fill_box_any((%d, %d), (%d, %d), col=%d, p=%d, c=%d, mask=%d)\n",
// argv[2].toSint16(), argv[1].toSint16(), argv[4].toSint16(), argv[3].toSint16(), argv[6].toSint16(), priority, control, argv[5].toUint16());
// FIXME/TODO: this is not right, as some of the dialogs are drawn *behind* some widgets. But at least it works for now
//ADD_TO_CURRENT_PICTURE_PORT(gfxw_new_box(s->gfx_state, area, color, color, GFX_BOX_SHADE_FLAT)); // old code
// FillBox seems to be meant again s->port instead of s->picture_port, at least in QfG3
// warning("Fillbox");
// ADD_TO_CURRENT_PICTURE_PORT(gfxw_new_box(s->gfx_state, area, color, color, GFX_BOX_SHADE_FLAT));
s->picture_port->add((GfxContainer *)s->picture_port, gfxw_new_box(s->gfx_state, area, fillColor, fillColor, GFX_BOX_SHADE_FLAT));
}
void SciGUI32::graphDrawLine(Common::Rect rect, int16 color, int16 priority, int16 control) {
gfx_color_t gfxcolor = graph_map_color(s, color, priority, control);
debugC(2, kDebugLevelGraphics, "draw_line((%d, %d), (%d, %d), col=%d, p=%d, c=%d, mask=%d)\n",
rect.left, rect.top, rect.right, rect.bottom, color, priority, control, gfxcolor.mask);
// Note: it's quite possible that the coordinates of the line will *not* form a valid rectangle (e.g. it might
// have negative width/height). The actual dirty rectangle is constructed in gfxdr_add_dirty().
// FIXME/TODO: We need to change the semantics of this call, so that no fake rectangles are used. As it is, it's
// not possible change rect_t to Common::Rect, as we assume that Common::Rect forms a *valid* rectangle.
ADD_TO_CURRENT_PICTURE_PORT(gfxw_new_line(Common::Point(rect.left, rect.top), Common::Point(rect.right, rect.bottom),
gfxcolor, GFX_LINE_MODE_CORRECT, GFX_LINE_STYLE_NORMAL));
FULL_REDRAW();
}
reg_t SciGUI32::graphSaveBox(Common::Rect rect, uint16 flags) {
rect_t area;
area.x = rect.left + s->port->zone.x + port_origin_x;
area.y = rect.top + s->port->zone.y + port_origin_y;
area.width = rect.width() - port_origin_x;
area.height = rect.height() - port_origin_y;
return graph_save_box(s, area);
}
void SciGUI32::graphRestoreBox(reg_t handle) {
graph_restore_box(s, handle);
}
void SciGUI32::paletteSet(int resourceNo, int flags) {
//warning("STUB");
}
int16 SciGUI32::paletteFind(int r, int g, int b) {
int i, delta, bestindex = -1, bestdelta = 200000;
for (i = 0; i < s->gfx_state->gfxResMan->getColorCount(); i++) {
int dr = abs(s->gfx_state->gfxResMan->getColor(i).r - r);
int dg = abs(s->gfx_state->gfxResMan->getColor(i).g - g);
int db = abs(s->gfx_state->gfxResMan->getColor(i).b - b);
delta = dr * dr + dg * dg + db * db;
if (delta < bestdelta) {
bestdelta = delta;
bestindex = i;
}
}
// Don't warn about inexact mappings -- it's actually the
// rule rather than the exception
return bestindex;
}
void SciGUI32::paletteAnimate(int fromColor, int toColor, int speed) {
warning("STUB");
}
void SciGUI32::moveCursor(int16 x, int16 y) {
Common::Point newPos;
// newPos = s->gfx_state->pointer_pos;
newPos.x = x + s->port->zone.x;
newPos.y = y + s->port->zone.y;
if (newPos.x > s->port->zone.x + s->port->zone.width)
newPos.x = s->port->zone.x + s->port->zone.width;
if (newPos.y > s->port->zone.y + s->port->zone.height)
newPos.y = s->port->zone.y + s->port->zone.height;
if (newPos.x < 0) newPos.x = 0;
if (newPos.y < 0) newPos.y = 0;
gfxop_set_pointer_position(s->gfx_state, newPos);
}
} // End of namespace Sci

79
engines/sci/gui32/gui32.h Normal file
View file

@ -0,0 +1,79 @@
/* 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.
*
* $URL$
* $Id$
*
*/
namespace Sci {
class SciGUI32 : public SciGUI {
public:
SciGUI32(OSystem *system, EngineState *s);
~SciGUI32();
void init(bool oldGfxFunctions);
int16 getTimeTicks();
void wait(int16 ticks);
void setPort(uint16 portPtr);
void setPortPic(Common::Rect rect, int16 picTop, int16 picLeft);
reg_t getPort();
void globalToLocal(int16 *x, int16 *y);
void localToGlobal(int16 *x, int16 *y);
reg_t newWindow(Common::Rect rect1, Common::Rect rect2, uint16 style, int16 priority, int16 colorPen, int16 colorBack, const char *title);
void disposeWindow(uint16 windowPtr, int16 arg2);
void display(const char *text, int argc, reg_t *argv);
void textSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight);
void textFonts(int argc, reg_t *argv);
void textColors(int argc, reg_t *argv);
void drawPicture(sciResourceId pictureId, uint16 showStyle, uint16 flags, int16 EGApaletteNo);
void drawCell(sciResourceId viewId, uint16 loopNo, uint16 cellNo, uint16 leftPos, uint16 topPos, int16 priority, uint16 paletteNo);
void drawControlButton(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 style, bool inverse);
void drawControlText(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 mode, int16 style, bool inverse);
void graphFillBoxForeground(Common::Rect rect);
void graphFillBoxBackground(Common::Rect rect);
void graphFillBox(Common::Rect rect, uint16 colorMask, int16 color, int16 priority, int16 control);
void graphDrawLine(Common::Rect rect, int16 color, int16 priority, int16 control);
reg_t graphSaveBox(Common::Rect rect, uint16 flags);
void graphRestoreBox(reg_t handle);
void paletteSet(int resourceNo, int flags);
virtual int16 paletteFind(int r, int g, int b);
void paletteAnimate(int fromColor, int toColor, int speed);
void moveCursor(int16 x, int16 y);
private:
OSystem *_system;
EngineState *s;
bool _usesOldGfxFunctions;
bool activated_icon_bar; // FIXME: Avoid non-const global vars
int port_origin_x; // FIXME: Avoid non-const global vars
int port_origin_y; // FIXME: Avoid non-const global vars
};
} // End of namespace Sci

View file

@ -55,6 +55,16 @@ MODULE_OBJS = \
gfx/res_pic.o \ gfx/res_pic.o \
gfx/res_view.o \ gfx/res_view.o \
gfx/seq_decoder.o \ gfx/seq_decoder.o \
gui/gui.o \
gui/gui_dbllist.o \
gui/gui_font.o \
gui/gui_gfx.o \
gui/gui_memmgr.o \
gui/gui_picture.o \
gui/gui_screen.o \
gui/gui_view.o \
gui/gui_windowmgr.o \
gui32/gui32.o \
sfx/core.o \ sfx/core.o \
sfx/iterator.o \ sfx/iterator.o \
sfx/songlib.o \ sfx/songlib.o \

View file

@ -35,6 +35,8 @@
#include "sci/engine/state.h" #include "sci/engine/state.h"
#include "sci/engine/kernel.h" #include "sci/engine/kernel.h"
#include "sci/gui32/gui32.h"
#include "sci/gfx/gfx_resource.h" #include "sci/gfx/gfx_resource.h"
#include "sci/gfx/gfx_tools.h" #include "sci/gfx/gfx_tools.h"
#include "sci/gfx/operations.h" #include "sci/gfx/operations.h"
@ -44,7 +46,7 @@ namespace Sci {
class GfxDriver; class GfxDriver;
SciEngine::SciEngine(OSystem *syst, const SciGameDescription *desc) SciEngine::SciEngine(OSystem *syst, const SciGameDescription *desc)
: Engine(syst), _gameDescription(desc) { : Engine(syst), _gameDescription(desc), _system(syst) {
// Put your engine in a sane state, but do nothing big yet; // Put your engine in a sane state, but do nothing big yet;
// in particular, do not load data from files; rather, if you // in particular, do not load data from files; rather, if you
// need to do such things, do them from init(). // need to do such things, do them from init().
@ -152,6 +154,10 @@ Common::Error SciEngine::run() {
GfxState gfx_state; GfxState gfx_state;
_gamestate->gfx_state = &gfx_state; _gamestate->gfx_state = &gfx_state;
// GUI change
//_gamestate->gui = new SciGUI(_system, _gamestate); // new
_gamestate->gui = new SciGUI32(_system, _gamestate); // old
// Assign default values to the config manager, in case settings are missing // Assign default values to the config manager, in case settings are missing
ConfMan.registerDefault("dither_mode", "0"); ConfMan.registerDefault("dither_mode", "0");
@ -183,6 +189,8 @@ Common::Error SciEngine::run() {
return Common::kUnknownError; return Common::kUnknownError;
} }
_gamestate->gui->init(_kernel->usesOldGfxFunctions());
printf("Emulating SCI version %s\n", getSciVersionDesc(getSciVersion()).c_str()); printf("Emulating SCI version %s\n", getSciVersionDesc(getSciVersion()).c_str());
game_run(&_gamestate); // Run the game game_run(&_gamestate); // Run the game

View file

@ -132,6 +132,7 @@ private:
Kernel *_kernel; Kernel *_kernel;
Vocabulary *_vocabulary; Vocabulary *_vocabulary;
Console *_console; Console *_console;
OSystem *_system;
}; };
/** /**