aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sword2/anims.cpp3
-rw-r--r--sword2/build_display.cpp383
-rw-r--r--sword2/build_display.h336
-rw-r--r--sword2/console.cpp8
-rw-r--r--sword2/controls.cpp77
-rw-r--r--sword2/controls.h1
-rw-r--r--sword2/debug.cpp107
-rw-r--r--sword2/debug.h2
-rw-r--r--sword2/driver/_mouse.cpp17
-rw-r--r--sword2/driver/animation.cpp67
-rw-r--r--sword2/driver/animation.h16
-rw-r--r--sword2/driver/d_draw.cpp58
-rw-r--r--sword2/driver/d_draw.h242
-rw-r--r--sword2/driver/d_sound.cpp6
-rw-r--r--sword2/driver/driver96.h30
-rw-r--r--sword2/driver/menu.cpp40
-rw-r--r--sword2/driver/palette.cpp112
-rw-r--r--sword2/driver/rdwin.cpp7
-rw-r--r--sword2/driver/render.cpp46
-rw-r--r--sword2/driver/sprite.cpp94
-rw-r--r--sword2/function.cpp325
-rw-r--r--sword2/icons.cpp30
-rw-r--r--sword2/layers.cpp51
-rw-r--r--sword2/layers.h24
-rw-r--r--sword2/logic.cpp9
-rw-r--r--sword2/logic.h2
-rw-r--r--sword2/maketext.cpp3
-rw-r--r--sword2/mouse.cpp520
-rw-r--r--sword2/mouse.h159
-rw-r--r--sword2/resman.cpp3
-rw-r--r--sword2/router.cpp7
-rw-r--r--sword2/save_rest.cpp29
-rw-r--r--sword2/scroll.cpp14
-rw-r--r--sword2/sound.cpp17
-rw-r--r--sword2/sound.h4
-rw-r--r--sword2/speech.cpp7
-rw-r--r--sword2/sword2.cpp115
-rw-r--r--sword2/sword2.h175
-rw-r--r--sword2/walker.cpp1
39 files changed, 1636 insertions, 1511 deletions
diff --git a/sword2/anims.cpp b/sword2/anims.cpp
index 385ff1885b..f8db3c57eb 100644
--- a/sword2/anims.cpp
+++ b/sword2/anims.cpp
@@ -26,8 +26,10 @@
#include "common/stdafx.h"
#include "common/file.h"
+
#include "sword2/sword2.h"
#include "sword2/defs.h"
+#include "sword2/build_display.h"
#include "sword2/controls.h"
#include "sword2/interpreter.h"
#include "sword2/logic.h"
@@ -36,7 +38,6 @@
#include "sword2/resman.h"
#include "sword2/sound.h"
#include "sword2/driver/animation.h"
-#include "sword2/driver/d_draw.h"
namespace Sword2 {
diff --git a/sword2/build_display.cpp b/sword2/build_display.cpp
index 98f738f75b..26f997a2ff 100644
--- a/sword2/build_display.cpp
+++ b/sword2/build_display.cpp
@@ -24,19 +24,77 @@
#include "common/stdafx.h"
#include "common/system.h"
+
#include "sword2/sword2.h"
#include "sword2/console.h"
#include "sword2/defs.h"
-#include "sword2/interpreter.h"
#include "sword2/logic.h"
#include "sword2/maketext.h"
-#include "sword2/memory.h"
+#include "sword2/mouse.h"
#include "sword2/resman.h"
-#include "sword2/driver/d_draw.h"
namespace Sword2 {
-void Sword2Engine::buildDisplay(void) {
+Screen::Screen(Sword2Engine *vm, int16 width, int16 height) {
+ _vm = vm;
+
+ _dirtyGrid = _buffer = NULL;
+
+ _vm->_system->initSize(width, height);
+
+ _screenWide = width;
+ _screenDeep = height;
+
+ _gridWide = width / CELLWIDE;
+ _gridDeep = height / CELLDEEP;
+
+ if ((width % CELLWIDE) || (height % CELLDEEP))
+ error("Bad cell size");
+
+ _dirtyGrid = (byte *) calloc(_gridWide, _gridDeep);
+ if (!_dirtyGrid)
+ error("Could not initialise dirty grid");
+
+ _buffer = (byte *) malloc(width * height);
+ if (!_buffer)
+ error("Could not initialise display");
+
+ for (int i = 0; i < ARRAYSIZE(_blockSurfaces); i++)
+ _blockSurfaces[i] = NULL;
+
+ _lightMask = NULL;
+ _needFullRedraw = false;
+
+ memset(&_thisScreen, 0, sizeof(_thisScreen));
+
+ _fps = 0;
+ _frameCount = 0;
+ _cycleTime = 0;
+
+ _lastPaletteRes = 0;
+
+ _scrollFraction = 16;
+
+ _largestLayerArea = 0;
+ _largestSpriteArea = 0;
+
+ strcpy(_largestLayerInfo, "largest layer: none registered");
+ strcpy(_largestSpriteInfo, "largest sprite: none registered");
+
+ _fadeStatus = RDFADE_NONE;
+ _renderAverageTime = 60;
+
+ _layer = 0;
+}
+
+Screen::~Screen() {
+ free(_buffer);
+ free(_dirtyGrid);
+ closeBackgroundLayer();
+ free(_lightMask);
+}
+
+void Screen::buildDisplay() {
if (_thisScreen.new_palette) {
// start the layer palette fading up
startNewPalette();
@@ -52,11 +110,11 @@ void Sword2Engine::buildDisplay(void) {
// there is a valid screen to run
- _graphics->setScrollTarget(_thisScreen.scroll_offset_x, _thisScreen.scroll_offset_y);
- _graphics->animateMouse();
- _graphics->startRenderCycle();
+ setScrollTarget(_thisScreen.scroll_offset_x, _thisScreen.scroll_offset_y);
+ _vm->_mouse->animateMouse();
+ startRenderCycle();
- byte *file = _resman->openResource(_thisScreen.background_layer_id);
+ byte *file = _vm->_resman->openResource(_thisScreen.background_layer_id);
MultiScreenHeader *screenLayerTable = (MultiScreenHeader *) (file + sizeof(StandardHeader));
// Render at least one frame, but if the screen is scrolling, and if
@@ -66,18 +124,18 @@ void Sword2Engine::buildDisplay(void) {
do {
// first background parallax + related anims
if (screenLayerTable->bg_parallax[0]) {
- _graphics->renderParallax(fetchBackgroundParallaxLayer(file, 0), 0);
+ renderParallax(_vm->fetchBackgroundParallaxLayer(file, 0), 0);
drawBackPar0Frames();
}
// second background parallax + related anims
if (screenLayerTable->bg_parallax[1]) {
- _graphics->renderParallax(fetchBackgroundParallaxLayer(file, 1), 1);
+ renderParallax(_vm->fetchBackgroundParallaxLayer(file, 1), 1);
drawBackPar1Frames();
}
// normal backround layer (just the one!)
- _graphics->renderParallax(fetchBackgroundLayer(file), 2);
+ renderParallax(_vm->fetchBackgroundLayer(file), 2);
// sprites & layers
drawBackFrames(); // background sprites
@@ -87,32 +145,32 @@ void Sword2Engine::buildDisplay(void) {
// first foreground parallax + related anims
if (screenLayerTable->fg_parallax[0]) {
- _graphics->renderParallax(fetchForegroundParallaxLayer(file, 0), 3);
+ renderParallax(_vm->fetchForegroundParallaxLayer(file, 0), 3);
drawForePar0Frames();
}
// second foreground parallax + related anims
if (screenLayerTable->fg_parallax[1]) {
- _graphics->renderParallax(fetchForegroundParallaxLayer(file, 1), 4);
+ renderParallax(_vm->fetchForegroundParallaxLayer(file, 1), 4);
drawForePar1Frames();
}
- _debugger->drawDebugGraphics();
- _fontRenderer->printTextBlocs();
- _graphics->processMenu();
+ _vm->_debugger->drawDebugGraphics();
+ _vm->_fontRenderer->printTextBlocs();
+ _vm->_mouse->processMenu();
- _graphics->updateDisplay();
+ updateDisplay();
_frameCount++;
- if (getMillis() > _cycleTime) {
+ if (_vm->getMillis() > _cycleTime) {
_fps = _frameCount;
_frameCount = 0;
- _cycleTime = getMillis() + 1000;
+ _cycleTime = _vm->getMillis() + 1000;
}
- } while (!_graphics->endRenderCycle());
+ } while (!endRenderCycle());
- _resman->closeResource(_thisScreen.background_layer_id);
+ _vm->_resman->closeResource(_thisScreen.background_layer_id);
}
/**
@@ -122,31 +180,31 @@ void Sword2Engine::buildDisplay(void) {
* until the user clicks the mouse or presses a key.
*/
-void Sword2Engine::displayMsg(byte *text, int time) {
+void Screen::displayMsg(byte *text, int time) {
byte pal[256 * 4];
byte oldPal[256 * 4];
debug(2, "DisplayMsg: %s", text);
- if (_graphics->getFadeStatus() != RDFADE_BLACK) {
- _graphics->fadeDown();
- _graphics->waitForFade();
+ if (getFadeStatus() != RDFADE_BLACK) {
+ fadeDown();
+ waitForFade();
}
- setMouse(0);
- setLuggage(0);
+ _vm->_mouse->setMouse(0);
+ _vm->_mouse->setLuggage(0);
+ _vm->_mouse->closeMenuImmediately();
- _graphics->closeMenuImmediately();
- _graphics->clearScene();
+ clearScene();
- byte *text_spr = _fontRenderer->makeTextSprite(text, 640, 187, _speechFontId);
+ byte *text_spr = _vm->_fontRenderer->makeTextSprite(text, 640, 187, _vm->_speechFontId);
FrameHeader *frame = (FrameHeader *) text_spr;
SpriteInfo spriteInfo;
- spriteInfo.x = _graphics->_screenWide / 2 - frame->width / 2;
+ spriteInfo.x = _screenWide / 2 - frame->width / 2;
if (!time)
- spriteInfo.y = _graphics->_screenDeep / 2 - frame->height / 2 - RDMENU_MENUDEEP;
+ spriteInfo.y = _screenDeep / 2 - frame->height / 2 - RDMENU_MENUDEEP;
else
spriteInfo.y = 400 - frame->height;
spriteInfo.w = frame->width;
@@ -159,65 +217,65 @@ void Sword2Engine::displayMsg(byte *text, int time) {
spriteInfo.data = text_spr + sizeof(FrameHeader);
spriteInfo.colourTable = 0;
- uint32 rv = _graphics->drawSprite(&spriteInfo);
+ uint32 rv = drawSprite(&spriteInfo);
if (rv)
error("Driver Error %.8x (in DisplayMsg)", rv);
- memcpy(oldPal, _graphics->_palette, sizeof(oldPal));
+ memcpy(oldPal, _palette, sizeof(oldPal));
memset(pal, 0, sizeof(pal));
pal[187 * 4 + 0] = 255;
pal[187 * 4 + 1] = 255;
pal[187 * 4 + 2] = 255;
- _graphics->setPalette(0, 256, pal, RDPAL_FADE);
- _graphics->fadeUp();
+ setPalette(0, 256, pal, RDPAL_FADE);
+ fadeUp();
free(text_spr);
- _graphics->waitForFade();
+ waitForFade();
if (time > 0) {
- uint32 targetTime = getMillis() + (time * 1000);
- sleepUntil(targetTime);
+ uint32 targetTime = _vm->getMillis() + (time * 1000);
+ _vm->sleepUntil(targetTime);
} else {
- while (!_quit) {
- MouseEvent *me = mouseEvent();
+ while (!_vm->_quit) {
+ MouseEvent *me = _vm->mouseEvent();
if (me && (me->buttons & (RD_LEFTBUTTONDOWN | RD_RIGHTBUTTONDOWN)))
break;
- if (keyboardEvent())
+ if (_vm->keyboardEvent())
break;
- _graphics->updateDisplay();
- _system->delayMillis(50);
+ updateDisplay();
+ _vm->_system->delayMillis(50);
}
}
- _graphics->fadeDown();
- _graphics->waitForFade();
- _graphics->clearScene();
- _graphics->setPalette(0, 256, oldPal, RDPAL_FADE);
- _graphics->fadeUp();
+ fadeDown();
+ waitForFade();
+ clearScene();
+ setPalette(0, 256, oldPal, RDPAL_FADE);
+ fadeUp();
}
-void Sword2Engine::drawBackPar0Frames(void) {
+void Screen::drawBackPar0Frames() {
// frame attached to 1st background parallax
for (uint i = 0; i < _curBgp0; i++)
processImage(&_bgp0List[i]);
}
-void Sword2Engine::drawBackPar1Frames(void) {
+void Screen::drawBackPar1Frames() {
// frame attached to 2nd background parallax
for (uint i = 0; i < _curBgp1; i++)
processImage(&_bgp1List[i]);
}
-void Sword2Engine::drawBackFrames(void) {
+void Screen::drawBackFrames() {
// background sprite, fixed to main background
for (uint i = 0; i < _curBack; i++)
processImage(&_backList[i]);
}
-void Sword2Engine::drawSortFrames(byte *file) {
+void Screen::drawSortFrames(byte *file) {
uint i, j;
// Sort the sort list. Used to be a separate function, but it was only
@@ -248,26 +306,26 @@ void Sword2Engine::drawSortFrames(byte *file) {
}
}
-void Sword2Engine::drawForeFrames(void) {
+void Screen::drawForeFrames() {
// foreground sprite, fixed to main background
for (uint i = 0; i < _curFore; i++)
processImage(&_foreList[i]);
}
-void Sword2Engine::drawForePar0Frames(void) {
+void Screen::drawForePar0Frames() {
// frame attached to 1st foreground parallax
for (uint i = 0; i < _curFgp0; i++)
processImage(&_fgp0List[i]);
}
-void Sword2Engine::drawForePar1Frames(void) {
+void Screen::drawForePar1Frames() {
// frame attached to 2nd foreground parallax
for (uint i = 0; i < _curFgp1; i++)
processImage(&_fgp1List[i]);
}
-void Sword2Engine::processLayer(byte *file, uint32 layer_number) {
- LayerHeader *layer_head = fetchLayerHeader(file, layer_number);
+void Screen::processLayer(byte *file, uint32 layer_number) {
+ LayerHeader *layer_head = _vm->fetchLayerHeader(file, layer_number);
SpriteInfo spriteInfo;
@@ -293,22 +351,22 @@ void Sword2Engine::processLayer(byte *file, uint32 layer_number) {
_largestLayerArea = current_layer_area;
sprintf(_largestLayerInfo,
"largest layer: %s layer(%d) is %dx%d",
- fetchObjectName(_thisScreen.background_layer_id, buf),
+ _vm->fetchObjectName(_thisScreen.background_layer_id, buf),
layer_number, layer_head->width, layer_head->height);
}
- uint32 rv = _graphics->drawSprite(&spriteInfo);
+ uint32 rv = drawSprite(&spriteInfo);
if (rv)
error("Driver Error %.8x in processLayer(%d)", rv, layer_number);
}
-void Sword2Engine::processImage(BuildUnit *build_unit) {
- byte *file = _resman->openResource(build_unit->anim_resource);
+void Screen::processImage(BuildUnit *build_unit) {
+ byte *file = _vm->_resman->openResource(build_unit->anim_resource);
byte *colTablePtr = NULL;
- AnimHeader *anim_head = fetchAnimHeader(file);
- CdtEntry *cdt_entry = fetchCdtEntry(file, build_unit->anim_pc);
- FrameHeader *frame_head = fetchFrameHeader(file, build_unit->anim_pc);
+ AnimHeader *anim_head = _vm->fetchAnimHeader(file);
+ CdtEntry *cdt_entry = _vm->fetchCdtEntry(file, build_unit->anim_pc);
+ FrameHeader *frame_head = _vm->fetchFrameHeader(file, build_unit->anim_pc);
// so that 0-colour is transparent
uint32 spriteType = RDSPR_TRANS;
@@ -379,7 +437,7 @@ void Sword2Engine::processImage(BuildUnit *build_unit) {
_largestSpriteArea = current_sprite_area;
sprintf(_largestSpriteInfo,
"largest sprite: %s frame(%d) is %dx%d",
- fetchObjectName(build_unit->anim_resource, buf),
+ _vm->fetchObjectName(build_unit->anim_resource, buf),
build_unit->anim_pc,
frame_head->width,
frame_head->height);
@@ -401,26 +459,27 @@ void Sword2Engine::processImage(BuildUnit *build_unit) {
spriteInfo.y = 1;
// create box to surround sprite - just outside sprite box
- _debugger->_rectX1 = spriteInfo.x - 1;
- _debugger->_rectY1 = spriteInfo.y - 1;
- _debugger->_rectX2 = spriteInfo.x + spriteInfo.scaledWidth;
- _debugger->_rectY2 = spriteInfo.y + spriteInfo.scaledHeight;
+ _vm->_debugger->_rectX1 = spriteInfo.x - 1;
+ _vm->_debugger->_rectY1 = spriteInfo.y - 1;
+ _vm->_debugger->_rectX2 = spriteInfo.x + spriteInfo.scaledWidth;
+ _vm->_debugger->_rectY2 = spriteInfo.y + spriteInfo.scaledHeight;
}
- uint32 rv = _graphics->drawSprite(&spriteInfo);
+ uint32 rv = drawSprite(&spriteInfo);
if (rv) {
byte buf[NAME_LEN];
error("Driver Error %.8x with sprite %s (%d) in processImage",
- rv, fetchObjectName(build_unit->anim_resource, buf),
+ rv,
+ _vm->fetchObjectName(build_unit->anim_resource, buf),
build_unit->anim_resource);
}
// release the anim resource
- _resman->closeResource(build_unit->anim_resource);
+ _vm->_resman->closeResource(build_unit->anim_resource);
}
-void Sword2Engine::resetRenderLists(void) {
+void Screen::resetRenderLists() {
// reset the sort lists - do this before a logic loop
// takes into account the fact that the start of the list is pre-built
// with the special sortable layers
@@ -441,28 +500,22 @@ void Sword2Engine::resetRenderLists(void) {
}
}
-void Sword2Engine::registerFrame(int32 *params, BuildUnit *build_unit) {
- // params: 0 pointer to mouse structure or NULL for no write to mouse
- // list (non-zero means write sprite-shape to mouse list)
- // 1 pointer to graphic structure
- // 2 pointer to mega structure
-
- ObjectGraphic *ob_graph = (ObjectGraphic *) _memory->decodePtr(params[1]);
+void Screen::registerFrame(ObjectMouse *ob_mouse, ObjectGraphic *ob_graph, ObjectMega *ob_mega, BuildUnit *build_unit) {
assert(ob_graph->anim_resource);
- byte *file = _resman->openResource(ob_graph->anim_resource);
+ byte *file = _vm->_resman->openResource(ob_graph->anim_resource);
- AnimHeader *anim_head = fetchAnimHeader(file);
- CdtEntry *cdt_entry = fetchCdtEntry(file, ob_graph->anim_pc);
- FrameHeader *frame_head = fetchFrameHeader(file, ob_graph->anim_pc);
+ AnimHeader *anim_head = _vm->fetchAnimHeader(file);
+ CdtEntry *cdt_entry = _vm->fetchCdtEntry(file, ob_graph->anim_pc);
+ FrameHeader *frame_head = _vm->fetchFrameHeader(file, ob_graph->anim_pc);
// update player graphic details for on-screen debug info
if (Logic::_scriptVars[ID] == CUR_PLAYER_ID) {
- _debugger->_playerGraphic.type = ob_graph->type;
- _debugger->_playerGraphic.anim_resource = ob_graph->anim_resource;
+ _vm->_debugger->_playerGraphic.type = ob_graph->type;
+ _vm->_debugger->_playerGraphic.anim_resource = ob_graph->anim_resource;
// counting 1st frame as 'frame 1'
- _debugger->_playerGraphic.anim_pc = ob_graph->anim_pc + 1;
- _debugger->_playerGraphicNoFrames = anim_head->noAnimFrames;
+ _vm->_debugger->_playerGraphic.anim_pc = ob_graph->anim_pc + 1;
+ _vm->_debugger->_playerGraphicNoFrames = anim_head->noAnimFrames;
}
// fill in the BuildUnit structure for this frame
@@ -482,9 +535,7 @@ void Sword2Engine::registerFrame(int32 *params, BuildUnit *build_unit) {
int scale = 0;
if (cdt_entry->frameType & FRAME_OFFSET) {
- ObjectMega *ob_mega = (ObjectMega *) _memory->decodePtr(params[2]);
-
- // calc scale at which to print the sprite, based on feet
+ // Calc scale at which to print the sprite, based on feet
// y-coord & scaling constants (NB. 'scale' is actually
// 256 * true_scale, to maintain accuracy)
@@ -519,184 +570,58 @@ void Sword2Engine::registerFrame(int32 *params, BuildUnit *build_unit) {
// calc the bottom y-coord for sorting purposes
build_unit->sort_y = build_unit->y + build_unit->scaled_height - 1;
- if (params[0]) {
+ if (ob_mouse) {
// passed a mouse structure, so add to the _mouseList
- ObjectMouse *ob_mouse = (ObjectMouse *) _memory->decodePtr(params[0]);
-
- if (ob_mouse->pointer) {
- assert(_curMouse < TOTAL_mouse_list);
-
- _mouseList[_curMouse].x1 = build_unit->x;
- _mouseList[_curMouse].y1 = build_unit->y;
- _mouseList[_curMouse].x2 = build_unit->x + build_unit->scaled_width;
- _mouseList[_curMouse].y2 = build_unit->y + build_unit->scaled_height;
-
- _mouseList[_curMouse].priority = ob_mouse->priority;
- _mouseList[_curMouse].pointer = ob_mouse->pointer;
-
- // check if pointer text field is set due to previous
- // object using this slot (ie. not correct for this
- // one)
-
- // if 'pointer_text' field is set, but the 'id' field
- // isn't same is current id then we don't want this
- // "left over" pointer text
-
- if (_mouseList[_curMouse].pointer_text && _mouseList[_curMouse].id != (int32) Logic::_scriptVars[ID])
- _mouseList[_curMouse].pointer_text = 0;
-
- _mouseList[_curMouse].id = Logic::_scriptVars[ID];
- // not using sprite as detection mask
- _mouseList[_curMouse].anim_resource = 0;
- _mouseList[_curMouse].anim_pc = 0;
+ _vm->_mouse->registerMouse(ob_mouse, build_unit);
- _curMouse++;
- }
}
- _resman->closeResource(ob_graph->anim_resource);
+ _vm->_resman->closeResource(ob_graph->anim_resource);
}
-int32 Sword2Engine::registerFrame(int32 *params) {
- ObjectGraphic *ob_graph = (ObjectGraphic *) _memory->decodePtr(params[1]);
-
+void Screen::registerFrame(ObjectMouse *ob_mouse, ObjectGraphic *ob_graph, ObjectMega *ob_mega) {
// check low word for sprite type
switch (ob_graph->type & 0x0000ffff) {
case BGP0_SPRITE:
assert(_curBgp0 < MAX_bgp0_sprites);
- registerFrame(params, &_bgp0List[_curBgp0]);
+ registerFrame(ob_mouse, ob_graph, ob_mega, &_bgp0List[_curBgp0]);
_curBgp0++;
break;
case BGP1_SPRITE:
assert(_curBgp1 < MAX_bgp1_sprites);
- registerFrame(params, &_bgp1List[_curBgp1]);
+ registerFrame(ob_mouse, ob_graph, ob_mega, &_bgp1List[_curBgp1]);
_curBgp1++;
break;
case BACK_SPRITE:
assert(_curBack < MAX_back_sprites);
- registerFrame(params, &_backList[_curBack]);
+ registerFrame(ob_mouse, ob_graph, ob_mega, &_backList[_curBack]);
_curBack++;
break;
case SORT_SPRITE:
assert(_curSort < MAX_sort_sprites);
_sortOrder[_curSort] = _curSort;
- registerFrame(params, &_sortList[_curSort]);
+ registerFrame(ob_mouse, ob_graph, ob_mega, &_sortList[_curSort]);
_curSort++;
break;
case FORE_SPRITE:
assert(_curFore < MAX_fore_sprites);
- registerFrame(params, &_foreList[_curFore]);
+ registerFrame(ob_mouse, ob_graph, ob_mega, &_foreList[_curFore]);
_curFore++;
break;
case FGP0_SPRITE:
assert(_curFgp0 < MAX_fgp0_sprites);
- registerFrame(params, &_fgp0List[_curFgp0]);
+ registerFrame(ob_mouse, ob_graph, ob_mega, &_fgp0List[_curFgp0]);
_curFgp0++;
break;
case FGP1_SPRITE:
assert(_curFgp1 < MAX_fgp1_sprites);
- registerFrame(params, &_fgp1List[_curFgp1]);
+ registerFrame(ob_mouse, ob_graph, ob_mega, &_fgp1List[_curFgp1]);
_curFgp1++;
break;
default:
// NO_SPRITE no registering!
break;
}
-
- return IR_CONT;
-}
-
-/**
- * Start layer palette fading up
- */
-
-void Sword2Engine::startNewPalette(void) {
- // if the screen is still fading down then wait for black - could
- // happen when everythings cached into a large memory model
- _graphics->waitForFade();
-
- byte *screenFile = _resman->openResource(_thisScreen.background_layer_id);
-
- _graphics->updatePaletteMatchTable((byte *) fetchPaletteMatchTable(screenFile));
- _graphics->setPalette(0, 256, fetchPalette(screenFile), RDPAL_FADE);
-
- // indicating that it's a screen palette
- _lastPaletteRes = 0;
-
- _resman->closeResource(_thisScreen.background_layer_id);
- _graphics->fadeUp();
- _thisScreen.new_palette = 0;
-}
-
-void Sword2Engine::setFullPalette(int32 palRes) {
- // fudge for hut interior
- // - unpausing should restore last palette as normal (could be screen
- // palette or 'dark_palette_13')
- // - but restoring the screen palette after 'dark_palette_13' should
- // now work properly too!
-
- // "Hut interior" refers to the watchman's hut in Marseille, and this
- // is apparently needed for the palette to be restored properly when
- // you turn the light off. (I didn't even notice the light switch!)
-
- if (Logic::_scriptVars[LOCATION] == 13) {
- // unpausing
- if (palRes == -1) {
- // restore whatever palette was last set (screen
- // palette or 'dark_palette_13')
- palRes = _lastPaletteRes;
- }
- } else {
- // check if we're just restoring the current screen palette
- // because we might actually need to use a separate palette
- // file anyway eg. for pausing & unpausing during the eclipse
-
- // unpausing (fudged for location 13)
- if (palRes == -1) {
- // we really meant '0'
- palRes = 0;
- }
-
- if (palRes == 0 && _lastPaletteRes)
- palRes = _lastPaletteRes;
- }
-
- // If non-zero, set palette to this separate palette file. Otherwise,
- // set palette to current screen palette.
-
- byte *file;
-
- if (palRes) {
- file = _resman->openResource(palRes);
-
- StandardHeader *head = (StandardHeader *) file;
- assert(head->fileType == PALETTE_FILE);
-
- file += sizeof(StandardHeader);
-
- // always set colour 0 to black because most background screen
- // palettes have a bright colour 0 although it should come out
- // as black in the game!
-
- file[0] = 0;
- file[1] = 0;
- file[2] = 0;
- file[3] = 0;
-
- _graphics->setPalette(0, 256, file, RDPAL_INSTANT);
- _resman->closeResource(palRes);
- } else {
- if (_thisScreen.background_layer_id) {
- file = _resman->openResource(_thisScreen.background_layer_id);
- _graphics->updatePaletteMatchTable(fetchPaletteMatchTable(file));
- _graphics->setPalette(0, 256, fetchPalette(file), RDPAL_INSTANT);
- _resman->closeResource(_thisScreen.background_layer_id);
- } else
- error("setFullPalette(0) called, but no current screen available!");
- }
-
- if (palRes != CONTROL_PANEL_PALETTE)
- _lastPaletteRes = palRes;
}
} // End of namespace Sword2
diff --git a/sword2/build_display.h b/sword2/build_display.h
index fe27009027..2b3bc0c6d6 100644
--- a/sword2/build_display.h
+++ b/sword2/build_display.h
@@ -21,6 +21,8 @@
#ifndef _BUILD_DISPLAY
#define _BUILD_DISPLAY
+#include "common/rect.h"
+
#define MAX_bgp0_sprites 6
#define MAX_bgp1_sprites 6
#define MAX_back_sprites 30
@@ -29,7 +31,341 @@
#define MAX_fgp0_sprites 6
#define MAX_fgp1_sprites 6
+#define PALTABLESIZE (64 * 64 * 64)
+
+#define BLOCKWIDTH 64
+#define BLOCKHEIGHT 64
+#define MAXLAYERS 5
+
+// Maximum scaled size of a sprite
+#define SCALE_MAXWIDTH 512
+#define SCALE_MAXHEIGHT 512
+
+// Dirty grid cell size
+#define CELLWIDE 10
+#define CELLDEEP 20
+
namespace Sword2 {
+
+struct ObjectMouse;
+struct ObjectGraphic;
+struct ObjectMega;
+
+// Structure filled out by each object to register its graphic printing
+// requrements
+
+struct BuildUnit {
+ int16 x;
+ int16 y;
+ uint16 scaled_width;
+ uint16 scaled_height;
+ int16 sort_y;
+ uint32 anim_resource;
+ uint16 anim_pc;
+
+ // Denotes a scaling sprite at print time - and holds the scaling value
+ // for the shrink routine
+
+ uint16 scale;
+
+ // Non-zero means this item is a layer - retrieve from background layer
+ // and send to special renderer
+
+ uint16 layer_number;
+
+ // True means we want this frame to be affected by the shading mask
+
+ bool shadingFlag;
+};
+
+enum {
+ MOUSE_normal = 0, // normal in game
+ MOUSE_menu = 1, // menu chooser
+ MOUSE_drag = 2, // dragging luggage
+ MOUSE_system_menu = 3, // system menu chooser
+ MOUSE_holding = 4 // special
+};
+
+struct ScreenInfo {
+ uint16 scroll_offset_x; // Position x
+ uint16 scroll_offset_y; // Position y
+ uint16 max_scroll_offset_x; // Calc'ed in fnInitBackground
+ uint16 max_scroll_offset_y;
+ int16 player_feet_x; // Feet coordinates to use - cant just
+ int16 player_feet_y; // fetch the player compact anymore
+ int16 feet_x; // Special offset-to-player position -
+ int16 feet_y; // tweek as desired - always set in
+ // screen manager object startup
+ uint16 screen_wide; // Size of background layer - hence
+ uint16 screen_deep; // size of back buffer itself (Paul
+ // actually malloc's it)
+ uint32 background_layer_id; // Id of the normal background layer
+ // from the header of the main
+ // background layer
+ uint16 number_of_layers;
+ uint8 new_palette; // Set to non zero to start the
+ // palette held within layer file
+ // fading up after a build_display
+ uint8 scroll_flag; // Scroll mode 0 off 1 on
+ bool mask_flag; // Using shading mask
+};
+
+// The SpriteInfo structure is used to tell the driver96 code what attributes
+// are linked to a sprite for drawing. These include position, scaling and
+// compression.
+
+struct SpriteInfo {
+ int16 x; // coords for top-left of sprite
+ int16 y;
+ uint16 w; // dimensions of sprite (before scaling)
+ uint16 h;
+ uint16 scale; // scale at which to draw, given in 256ths ['0' or '256' MEANS DON'T SCALE]
+ uint16 scaledWidth; // new dimensions (we calc these for the mouse area, so may as well pass to you to save time)
+ uint16 scaledHeight; //
+ uint16 type; // mask containing 'RDSPR_' bits specifying compression type, flip, transparency, etc
+ uint16 blend; // holds the blending values.
+ byte *data; // pointer to the sprite data
+ byte *colourTable; // pointer to 16-byte colour table, only applicable to 16-col compression type
+};
+
+struct BlockSurface {
+ byte data[BLOCKWIDTH * BLOCKHEIGHT];
+ bool transparent;
+};
+
+class Screen {
+private:
+ Sword2Engine *_vm;
+
+ // _thisScreen describes the current back buffer and its in-game scroll
+ // positions, etc.
+
+ ScreenInfo _thisScreen;
+
+ int32 _renderCaps;
+ int8 _renderLevel;
+
+ byte *_buffer;
+ byte *_lightMask;
+
+ // Game screen metrics
+ int16 _screenWide;
+ int16 _screenDeep;
+
+ bool _needFullRedraw;
+
+ // Scroll variables. _scrollX and _scrollY hold the current scroll
+ // position, and _scrollXTarget and _scrollYTarget are the target
+ // position for the end of the game cycle.
+
+ int16 _scrollX;
+ int16 _scrollY;
+
+ int16 _scrollXTarget;
+ int16 _scrollYTarget;
+ int16 _scrollXOld;
+ int16 _scrollYOld;
+
+ int16 _parallaxScrollX; // current x offset to link a sprite to the
+ // parallax layer
+ int16 _parallaxScrollY; // current y offset to link a sprite to the
+ // parallax layer
+ int16 _locationWide;
+ int16 _locationDeep;
+
+ // Dirty grid handling
+ byte *_dirtyGrid;
+
+ uint16 _gridWide;
+ uint16 _gridDeep;
+
+ byte _palette[256 * 4];
+ byte _paletteMatch[PALTABLESIZE];
+
+ uint8 _fadeStatus;
+ int32 _fadeStartTime;
+ int32 _fadeTotalTime;
+
+ // 'frames per second' counting stuff
+ uint32 _fps;
+ uint32 _cycleTime;
+ uint32 _frameCount;
+
+ int32 _initialTime;
+ int32 _startTime;
+ int32 _totalTime;
+ int32 _renderAverageTime;
+ int32 _framesPerGameCycle;
+ bool _renderTooSlow;
+
+ void startNewPalette();
+
+ void resetRenderEngine();
+
+ void startRenderCycle();
+ bool endRenderCycle();
+
+ // Holds the order of the sort list, i.e. the list stays static and we
+ // sort this array.
+
+ uint16 _sortOrder[MAX_sort_sprites];
+
+ BuildUnit _bgp0List[MAX_bgp0_sprites];
+ BuildUnit _bgp1List[MAX_bgp1_sprites];
+ BuildUnit _backList[MAX_back_sprites];
+ BuildUnit _sortList[MAX_sort_sprites];
+ BuildUnit _foreList[MAX_fore_sprites];
+ BuildUnit _fgp0List[MAX_fgp0_sprites];
+ BuildUnit _fgp1List[MAX_fgp1_sprites];
+
+ uint32 _curBgp0;
+ uint32 _curBgp1;
+ uint32 _curBack;
+ uint32 _curSort;
+ uint32 _curFore;
+ uint32 _curFgp0;
+ uint32 _curFgp1;
+
+ void drawBackPar0Frames();
+ void drawBackPar1Frames();
+ void drawBackFrames();
+ void drawSortFrames(byte *file);
+ void drawForeFrames();
+ void drawForePar0Frames();
+ void drawForePar1Frames();
+
+ void processLayer(byte *file, uint32 layer_number);
+ void processImage(BuildUnit *build_unit);
+
+ uint8 _scrollFraction;
+
+ // Last palette used - so that we can restore the correct one after a
+ // pause (which dims the screen) and it's not always the main screen
+ // palette that we want, eg. during the eclipse
+
+ // This flag gets set in startNewPalette() and setFullPalette()
+
+ uint32 _lastPaletteRes;
+
+ // Debugging stuff
+ uint32 _largestLayerArea;
+ uint32 _largestSpriteArea;
+ char _largestLayerInfo[128];
+ char _largestSpriteInfo[128];
+
+ void registerFrame(ObjectMouse *ob_mouse, ObjectGraphic *ob_graph, ObjectMega *ob_mega, BuildUnit *build_unit);
+
+ void mirrorSprite(byte *dst, byte *src, int16 w, int16 h);
+ int32 decompressRLE256(byte *dst, byte *src, int32 decompSize);
+ void unwindRaw16(byte *dst, byte *src, uint8 blockSize, byte *colTable);
+ int32 decompressRLE16(byte *dst, byte *src, int32 decompSize, byte *colTable);
+ void renderParallax(Parallax *p, int16 layer);
+
+ void markAsDirty(int16 x0, int16 y0, int16 x1, int16 y1);
+
+ uint8 _xBlocks[MAXLAYERS];
+ uint8 _yBlocks[MAXLAYERS];
+
+ // An array of sub-blocks, one for each of the parallax layers.
+
+ BlockSurface **_blockSurfaces[MAXLAYERS];
+
+ uint16 _xScale[SCALE_MAXWIDTH];
+ uint16 _yScale[SCALE_MAXHEIGHT];
+
+ void blitBlockSurface(BlockSurface *s, Common::Rect *r, Common::Rect *clipRect);
+
+ uint16 _layer;
+
+public:
+ Screen(Sword2Engine *vm, int16 width, int16 height);
+ ~Screen();
+
+ int8 getRenderLevel();
+ void setRenderLevel(int8 level);
+
+ byte *getScreen() { return _buffer; }
+ byte *getPalette() { return _palette; }
+ ScreenInfo *getScreenInfo() { return &_thisScreen; }
+
+ int16 getScreenWide() { return _screenWide; }
+ int16 getScreenDeep() { return _screenDeep; }
+
+ uint32 getCurBgp0() { return _curBgp0; }
+ uint32 getCurBgp1() { return _curBgp1; }
+ uint32 getCurBack() { return _curBack; }
+ uint32 getCurSort() { return _curSort; }
+ uint32 getCurFore() { return _curFore; }
+ uint32 getCurFgp0() { return _curFgp0; }
+ uint32 getCurFgp1() { return _curFgp1; }
+
+ uint32 getFps() { return _fps; }
+
+ uint32 getLargestLayerArea() { return _largestLayerArea; }
+ uint32 getLargestSpriteArea() { return _largestSpriteArea; }
+ char *getLargestLayerInfo() { return _largestLayerInfo; }
+ char *getLargestSpriteInfo() { return _largestSpriteInfo; }
+
+ void setNeedFullRedraw();
+
+ void clearScene();
+
+ void resetRenderLists();
+
+ void setLocationMetrics(uint16 w, uint16 h);
+ int32 initialiseBackgroundLayer(Parallax *p);
+ void closeBackgroundLayer();
+
+ void initialiseRenderCycle();
+
+ void initBackground(int32 res, int32 new_palette);
+ void registerFrame(ObjectMouse *ob_mouse, ObjectGraphic *ob_graph, ObjectMega *ob_mega);
+
+ void setScrollFraction(uint8 f) { _scrollFraction = f; }
+ void setScrollTarget(int16 x, int16 y);
+ void setScrolling();
+
+ void setFullPalette(int32 palRes);
+ void setPalette(int16 startEntry, int16 noEntries, byte *palette, uint8 setNow);
+ uint8 quickMatch(uint8 r, uint8 g, uint8 b);
+ int32 fadeUp(float time = 0.75);
+ int32 fadeDown(float time = 0.75);
+ uint8 getFadeStatus();
+ void dimPalette();
+ void waitForFade();
+ void fadeServer();
+
+ void updateDisplay(bool redrawScene = true);
+
+ void displayMsg(byte *text, int time);
+
+ int32 createSurface(SpriteInfo *s, byte **surface);
+ void drawSurface(SpriteInfo *s, byte *surface, Common::Rect *clipRect = NULL);
+ void deleteSurface(byte *surface);
+ int32 drawSprite(SpriteInfo *s);
+
+ void scaleImageFast(byte *dst, uint16 dstPitch, uint16 dstWidth,
+ uint16 dstHeight, byte *src, uint16 srcPitch, uint16 srcWidth,
+ uint16 srcHeight);
+ void scaleImageGood(byte *dst, uint16 dstPitch, uint16 dstWidth,
+ uint16 dstHeight, byte *src, uint16 srcPitch, uint16 srcWidth,
+ uint16 srcHeight, byte *backbuf);
+
+ void updateRect(Common::Rect *r);
+
+ int32 openLightMask(SpriteInfo *s);
+ int32 closeLightMask();
+
+ void buildDisplay();
+
+ void plotPoint(int16 x, int16 y, uint8 colour);
+ void drawLine(int16 x1, int16 y1, int16 x2, int16 y2, uint8 colour);
+#ifdef BACKEND_8BIT
+ void plotYUV(byte *lut, int width, int height, byte *const *dat);
+#endif
+
+};
+
} // End of namespace Sword2
#endif
diff --git a/sword2/console.cpp b/sword2/console.cpp
index 4c0ab2f550..32e7d6eeb2 100644
--- a/sword2/console.cpp
+++ b/sword2/console.cpp
@@ -25,9 +25,9 @@
#include "sword2/logic.h"
#include "sword2/maketext.h"
#include "sword2/memory.h"
+#include "sword2/mouse.h"
#include "sword2/resman.h"
#include "sword2/sound.h"
-#include "sword2/driver/d_draw.h"
#include "common/debugger.cpp"
@@ -144,9 +144,9 @@ void Debugger::postEnter() {
_vm->_sound->unpauseMusic();
}
- if (_vm->_graphics) {
+ if (_vm->_mouse) {
// Restore old mouse cursor
- _vm->_graphics->drawMouse();
+ _vm->_mouse->drawMouse();
}
}
@@ -219,7 +219,7 @@ bool Debugger::Cmd_Start(int argc, const char **argv) {
}
_vm->conStart(atoi(argv[1]));
- _vm->_graphics->setPalette(187, 1, pal, RDPAL_INSTANT);
+ _vm->_screen->setPalette(187, 1, pal, RDPAL_INSTANT);
return true;
}
diff --git a/sword2/controls.cpp b/sword2/controls.cpp
index 08444ed4d9..5ff77f8008 100644
--- a/sword2/controls.cpp
+++ b/sword2/controls.cpp
@@ -22,14 +22,15 @@
#include "common/rect.h"
#include "common/config-manager.h"
#include "common/system.h"
+
#include "sword2/sword2.h"
#include "sword2/controls.h"
#include "sword2/defs.h"
#include "sword2/logic.h"
+#include "sword2/mouse.h"
#include "sword2/resman.h"
#include "sword2/router.h"
#include "sword2/sound.h"
-#include "sword2/driver/d_draw.h"
#define MAX_STRING_LEN 64 // 20 was too low; better to be safe ;)
#define CHARACTER_OVERLAP 2 // overlap characters by 3 pixels
@@ -176,7 +177,7 @@ FontRendererGui::FontRendererGui(Gui *gui, int fontId)
sprite.data = (byte *) (head + 1);
sprite.w = head->width;
sprite.h = head->height;
- _gui->_vm->_graphics->createSurface(&sprite, &_glyph[i]._data);
+ _gui->_vm->_screen->createSurface(&sprite, &_glyph[i]._data);
_glyph[i]._width = head->width;
_glyph[i]._height = head->height;
}
@@ -186,7 +187,7 @@ FontRendererGui::FontRendererGui(Gui *gui, int fontId)
FontRendererGui::~FontRendererGui() {
for (int i = 0; i < SIZE_OF_CHAR_SET; i++)
- _gui->_vm->_graphics->deleteSurface(_glyph[i]._data);
+ _gui->_vm->_screen->deleteSurface(_glyph[i]._data);
}
void FontRendererGui::fetchText(uint32 textId, byte *buf) {
@@ -255,7 +256,7 @@ void FontRendererGui::drawText(byte *text, int x, int y, int alignment) {
sprite.w = getCharWidth(text[i]);
sprite.h = getCharHeight(text[i]);
- _gui->_vm->_graphics->drawSurface(&sprite, _glyph[text[i] - 32]._data);
+ _gui->_vm->_screen->drawSurface(&sprite, _glyph[text[i] - 32]._data);
sprite.x += (getCharWidth(text[i]) - CHARACTER_OVERLAP);
}
@@ -275,14 +276,14 @@ void FontRendererGui::drawText(uint32 textId, int x, int y, int alignment) {
Dialog::Dialog(Gui *gui)
: _numWidgets(0), _finish(false), _result(0), _gui(gui) {
- _gui->_vm->setFullPalette(CONTROL_PANEL_PALETTE);
- _gui->_vm->_graphics->clearScene();
+ _gui->_vm->_screen->setFullPalette(CONTROL_PANEL_PALETTE);
+ _gui->_vm->_screen->clearScene();
// HACK: Since the dialogs don't do normal scene updates we need to
// trigger a full redraw manually.
- _gui->_vm->_graphics->setNeedFullRedraw();
- _gui->_vm->_graphics->updateDisplay();
+ _gui->_vm->_screen->setNeedFullRedraw();
+ _gui->_vm->_screen->updateDisplay();
}
Dialog::~Dialog() {
@@ -296,7 +297,7 @@ void Dialog::registerWidget(Widget *widget) {
}
void Dialog::paint() {
- _gui->_vm->_graphics->clearScene();
+ _gui->_vm->_screen->clearScene();
for (int i = 0; i < _numWidgets; i++)
_widgets[i]->paint();
}
@@ -313,16 +314,19 @@ int Dialog::run() {
paint();
- int16 oldMouseX = -1;
- int16 oldMouseY = -1;
+ int oldMouseX = -1;
+ int oldMouseY = -1;
while (!_finish) {
// So that the menu icons will reach their full size
- _gui->_vm->_graphics->processMenu();
- _gui->_vm->_graphics->updateDisplay(false);
+ _gui->_vm->_mouse->processMenu();
+ _gui->_vm->_screen->updateDisplay(false);
+
+ int newMouseX, newMouseY;
+
+ _gui->_vm->_mouse->getPos(newMouseX, newMouseY);
- int16 newMouseX = _gui->_vm->_mouseX;
- int16 newMouseY = _gui->_vm->_mouseY + 40;
+ newMouseY += 40;
MouseEvent *me = _gui->_vm->mouseEvent();
KeyboardEvent *ke = _gui->_vm->keyboardEvent();
@@ -429,7 +433,7 @@ Widget::Widget(Dialog *parent, int states)
Widget::~Widget() {
for (int i = 0; i < _numStates; i++) {
if (_surfaces[i]._original)
- _parent->_gui->_vm->_graphics->deleteSurface(_surfaces[i]._surface);
+ _parent->_gui->_vm->_screen->deleteSurface(_surfaces[i]._surface);
}
free(_sprites);
free(_surfaces);
@@ -484,7 +488,7 @@ void Widget::createSurfaceImage(int state, uint32 res, int x, int y, uint32 pc)
// Points to just after frame header, ie. start of sprite data
_sprites[state].data = (byte *) (frame_head + 1);
- _parent->_gui->_vm->_graphics->createSurface(&_sprites[state], &_surfaces[state]._surface);
+ _parent->_gui->_vm->_screen->createSurface(&_sprites[state], &_surfaces[state]._surface);
_surfaces[state]._original = true;
// Release the anim resource
@@ -537,7 +541,7 @@ int Widget::getState() {
}
void Widget::paint(Common::Rect *clipRect) {
- _parent->_gui->_vm->_graphics->drawSurface(&_sprites[_state], _surfaces[_state]._surface, clipRect);
+ _parent->_gui->_vm->_screen->drawSurface(&_sprites[_state], _surfaces[_state]._surface, clipRect);
}
/**
@@ -940,7 +944,7 @@ public:
_objectLabelsSwitch->setValue(_gui->_pointerTextSelected);
_subtitlesSwitch->setValue(_gui->_subtitles);
- _reverseStereoSwitch->setValue(_gui->_stereoReversed);
+ _reverseStereoSwitch->setValue(_gui->_vm->_sound->isReverseStereo());
_musicSwitch->setValue(!_gui->_vm->_sound->isMusicMute());
_speechSwitch->setValue(!_gui->_vm->_sound->isSpeechMute());
_fxSwitch->setValue(!_gui->_vm->_sound->isFxMute());
@@ -949,8 +953,8 @@ public:
_speechSlider->setValue(_mixer->getVolumeForSoundType(SoundMixer::kSpeechAudioDataType));
_fxSlider->setValue(_mixer->getVolumeForSoundType(SoundMixer::kSFXAudioDataType));
- _gfxSlider->setValue(_gui->_vm->_graphics->getRenderLevel());
- _gfxPreview->setState(_gui->_vm->_graphics->getRenderLevel());
+ _gfxSlider->setValue(_gui->_vm->_screen->getRenderLevel());
+ _gfxPreview->setState(_gui->_vm->_screen->getRenderLevel());
}
~OptionsDialog() {
@@ -1020,12 +1024,12 @@ public:
} else if (widget == _okButton) {
_gui->_subtitles = _subtitlesSwitch->getValue();
_gui->_pointerTextSelected = _objectLabelsSwitch->getValue();
- _gui->_stereoReversed = _reverseStereoSwitch->getValue();
// Apply the changes
_gui->_vm->_sound->muteMusic(!_musicSwitch->getValue());
_gui->_vm->_sound->muteSpeech(!_speechSwitch->getValue());
_gui->_vm->_sound->muteFx(!_fxSwitch->getValue());
+ _gui->_vm->_sound->setReverseStereo(_reverseStereoSwitch->getValue());
_mixer->setVolumeForSoundType(SoundMixer::kMusicAudioDataType, _musicSlider->getValue());
_mixer->setVolumeForSoundType(SoundMixer::kSpeechAudioDataType, _speechSlider->getValue());
_mixer->setVolumeForSoundType(SoundMixer::kSFXAudioDataType, _fxSlider->getValue());
@@ -1449,7 +1453,7 @@ public:
break;
}
- _gui->_vm->displayMsg(_gui->_vm->fetchTextLine(_gui->_vm->_resman->openResource(textId / SIZE), textId & 0xffff) + 2, 0);
+ _gui->_vm->_screen->displayMsg(_gui->_vm->fetchTextLine(_gui->_vm->_resman->openResource(textId / SIZE), textId & 0xffff) + 2, 0);
result = 0;
}
} else {
@@ -1470,18 +1474,18 @@ public:
break;
}
- _gui->_vm->displayMsg(_gui->_vm->fetchTextLine(_gui->_vm->_resman->openResource(textId / SIZE), textId & 0xffff) + 2, 0);
+ _gui->_vm->_screen->displayMsg(_gui->_vm->fetchTextLine(_gui->_vm->_resman->openResource(textId / SIZE), textId & 0xffff) + 2, 0);
result = 0;
} else {
// Prime system with a game cycle
// Reset the graphic 'BuildUnit' list before a
// new logic list (see fnRegisterFrame)
- _gui->_vm->resetRenderLists();
+ _gui->_vm->_screen->resetRenderLists();
// Reset the mouse hot-spot list (see
// fnRegisterMouse and fnRegisterFrame)
- _gui->_vm->resetMouseList();
+ _gui->_vm->_mouse->resetMouseList();
if (_gui->_vm->_logic->processSession())
error("restore 1st cycle failed??");
@@ -1504,7 +1508,6 @@ Gui::Gui(Sword2Engine *vm) : _vm(vm), _baseSlot(0) {
void Gui::readOptionSettings(void) {
_subtitles = ConfMan.getBool("subtitles");
_pointerTextSelected = ConfMan.getBool("object_labels");
- _stereoReversed = ConfMan.getBool("reverse_stereo");
updateGraphicsLevel((uint8) ConfMan.getInt("gfx_details"));
@@ -1514,6 +1517,7 @@ void Gui::readOptionSettings(void) {
_vm->_sound->muteMusic(ConfMan.getBool("music_mute"));
_vm->_sound->muteSpeech(ConfMan.getBool("speech_mute"));
_vm->_sound->muteFx(ConfMan.getBool("sfx_mute"));
+ _vm->_sound->setReverseStereo(ConfMan.getBool("reverse_stereo"));
}
void Gui::writeOptionSettings(void) {
@@ -1523,10 +1527,10 @@ void Gui::writeOptionSettings(void) {
ConfMan.set("music_mute", _vm->_sound->isMusicMute());
ConfMan.set("speech_mute", _vm->_sound->isSpeechMute());
ConfMan.set("sfx_mute", _vm->_sound->isFxMute());
- ConfMan.set("gfx_details", _vm->_graphics->getRenderLevel());
+ ConfMan.set("gfx_details", _vm->_screen->getRenderLevel());
ConfMan.set("subtitles", _subtitles);
ConfMan.set("object_labels", _pointerTextSelected);
- ConfMan.set("reverse_stereo", _stereoReversed);
+ ConfMan.set("reverse_stereo", _vm->_sound->isReverseStereo());
ConfMan.flushToDisk();
}
@@ -1574,6 +1578,7 @@ void Gui::quitControl(void) {
}
void Gui::restartControl(void) {
+ ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
uint32 temp_demo_flag;
MiniDialog restartDialog(this, 149618693);
@@ -1581,7 +1586,7 @@ void Gui::restartControl(void) {
if (!restartDialog.run())
return;
- _vm->_graphics->closeMenuImmediately();
+ _vm->_mouse->closeMenuImmediately();
// Restart the game. To do this, we must...
@@ -1613,25 +1618,25 @@ void Gui::restartControl(void) {
// Reset the graphic 'BuildUnit' list before a new logic list
// (see fnRegisterFrame)
- _vm->resetRenderLists();
+ _vm->_screen->resetRenderLists();
// Reset the mouse hot-spot list (see fnRegisterMouse and
// fnRegisterFrame)
- _vm->resetMouseList();
+ _vm->_mouse->resetMouseList();
- _vm->_graphics->closeMenuImmediately();
+ _vm->_mouse->closeMenuImmediately();
// FOR THE DEMO - FORCE THE SCROLLING TO BE RESET!
// - this is taken from fnInitBackground
// switch on scrolling (2 means first time on screen)
- _vm->_thisScreen.scroll_flag = 2;
+ screenInfo->scroll_flag = 2;
if (_vm->_logic->processSession())
error("restart 1st cycle failed??");
// So palette not restored immediately after control panel - we want
// to fade up instead!
- _vm->_thisScreen.new_palette = 99;
+ screenInfo->new_palette = 99;
}
void Gui::optionControl(void) {
@@ -1647,7 +1652,7 @@ void Gui::updateGraphicsLevel(int newLevel) {
else if (newLevel > 3)
newLevel = 3;
- _vm->_graphics->setRenderLevel(newLevel);
+ _vm->_screen->setRenderLevel(newLevel);
// update our global variable - which needs to be checked when dimming
// the palette in PauseGame() in sword2.cpp (since palette-matching
diff --git a/sword2/controls.h b/sword2/controls.h
index d3eacc3822..27cf07f9f5 100644
--- a/sword2/controls.h
+++ b/sword2/controls.h
@@ -33,7 +33,6 @@ public:
uint8 _currentGraphicsLevel;
bool _subtitles;
- bool _stereoReversed;
bool _pointerTextSelected;
Gui(Sword2Engine *vm);
diff --git a/sword2/debug.cpp b/sword2/debug.cpp
index 5b9c9597e0..4d4d4eb8ff 100644
--- a/sword2/debug.cpp
+++ b/sword2/debug.cpp
@@ -25,9 +25,9 @@
#include "sword2/logic.h"
#include "sword2/maketext.h"
#include "sword2/memory.h"
+#include "sword2/mouse.h"
#include "sword2/resman.h"
#include "sword2/router.h"
-#include "sword2/driver/d_draw.h"
namespace Sword2 {
@@ -63,20 +63,24 @@ void Debugger::buildDebugText(void) {
int32 showVarPos;
int32 varNo;
+ ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
+
// clear the array of text block numbers for the debug text
clearDebugTextBlocks();
// mouse coords
-/*
// print mouse coords beside mouse-marker, if it's being displayed
- if (displayMouseMarker) {
- sprintf(buf, "%d,%d", mousex + _thisScreen.scroll_offset_x, mousey + _thisScreen.scroll_offset_y);
- if (mousex>560)
- makeDebugTextBlock(buf, mousex - 50, mousey - 15);
+ if (_displayMouseMarker) {
+ int mouseX, mouseY;
+
+ _vm->_mouse->getPos(mouseX, mouseY);
+
+ sprintf(buf, "%d,%d", mouseX + screenInfo->scroll_offset_x, mouseY + screenInfo->scroll_offset_y);
+ if (mouseX > 560)
+ makeDebugTextBlock(buf, mouseX - 50, mouseY - 15);
else
- makeDebugTextBlock(buf, mousex + 5, mousey - 15);
+ makeDebugTextBlock(buf, mouseX + 5, mouseY - 15);
}
-*/
// mouse area coords
@@ -186,16 +190,22 @@ void Debugger::buildDebugText(void) {
makeDebugTextBlock(buf, 0, 15);
- if (_vm->_mouseTouching)
+ uint32 mouseTouching = _vm->_mouse->getMouseTouching();
+
+ int mouseX, mouseY;
+
+ _vm->_mouse->getPos(mouseX, mouseY);
+
+ if (mouseTouching)
sprintf(buf, "mouse %d,%d (id %d: %s)",
- _vm->_mouseX + _vm->_thisScreen.scroll_offset_x,
- _vm->_mouseY + _vm->_thisScreen.scroll_offset_y,
- _vm->_mouseTouching,
- _vm->fetchObjectName(_vm->_mouseTouching, name));
+ mouseX + screenInfo->scroll_offset_x,
+ mouseY + screenInfo->scroll_offset_y,
+ mouseTouching,
+ _vm->fetchObjectName(mouseTouching, name));
else
sprintf(buf, "mouse %d,%d (not touching)",
- _vm->_mouseX + _vm->_thisScreen.scroll_offset_x,
- _vm->_mouseY + _vm->_thisScreen.scroll_offset_y);
+ mouseX + screenInfo->scroll_offset_x,
+ mouseY + screenInfo->scroll_offset_y);
makeDebugTextBlock(buf, 0, 30);
@@ -204,23 +214,23 @@ void Debugger::buildDebugText(void) {
if (_playerGraphic.anim_resource)
sprintf(buf, "player %d,%d %s (%d) #%d/%d",
- _vm->_thisScreen.player_feet_x,
- _vm->_thisScreen.player_feet_y,
+ screenInfo->player_feet_x,
+ screenInfo->player_feet_y,
_vm->fetchObjectName(_playerGraphic.anim_resource, name),
_playerGraphic.anim_resource,
_playerGraphic.anim_pc,
_playerGraphicNoFrames);
else
sprintf(buf, "player %d,%d --- %d",
- _vm->_thisScreen.player_feet_x,
- _vm->_thisScreen.player_feet_y,
+ screenInfo->player_feet_x,
+ screenInfo->player_feet_y,
_playerGraphic.anim_pc);
makeDebugTextBlock(buf, 0, 45);
// frames-per-second counter
- sprintf(buf, "fps %d", _vm->_fps);
+ sprintf(buf, "fps %d", _vm->_screen->getFps());
makeDebugTextBlock(buf, 440, 0);
// location number
@@ -240,32 +250,32 @@ void Debugger::buildDebugText(void) {
// sprite list usage
- sprintf(buf, "bgp0: %d/%d", _vm->_curBgp0, MAX_bgp0_sprites);
+ sprintf(buf, "bgp0: %d/%d", _vm->_screen->getCurBgp0(), MAX_bgp0_sprites);
makeDebugTextBlock(buf, 560, 0);
- sprintf(buf, "bgp1: %d/%d", _vm->_curBgp1, MAX_bgp1_sprites);
+ sprintf(buf, "bgp1: %d/%d", _vm->_screen->getCurBgp1(), MAX_bgp1_sprites);
makeDebugTextBlock(buf, 560, 15);
- sprintf(buf, "back: %d/%d", _vm->_curBack, MAX_back_sprites);
+ sprintf(buf, "back: %d/%d", _vm->_screen->getCurBack(), MAX_back_sprites);
makeDebugTextBlock(buf, 560, 30);
- sprintf(buf, "sort: %d/%d", _vm->_curSort, MAX_sort_sprites);
+ sprintf(buf, "sort: %d/%d", _vm->_screen->getCurSort(), MAX_sort_sprites);
makeDebugTextBlock(buf, 560, 45);
- sprintf(buf, "fore: %d/%d", _vm->_curFore, MAX_fore_sprites);
+ sprintf(buf, "fore: %d/%d", _vm->_screen->getCurFore(), MAX_fore_sprites);
makeDebugTextBlock(buf, 560, 60);
- sprintf(buf, "fgp0: %d/%d", _vm->_curFgp0, MAX_fgp0_sprites);
+ sprintf(buf, "fgp0: %d/%d", _vm->_screen->getCurFgp0(), MAX_fgp0_sprites);
makeDebugTextBlock(buf, 560, 75);
- sprintf(buf, "fgp1: %d/%d", _vm->_curFgp1, MAX_fgp1_sprites);
+ sprintf(buf, "fgp1: %d/%d", _vm->_screen->getCurFgp1(), MAX_fgp1_sprites);
makeDebugTextBlock(buf, 560, 90);
// largest layer & sprite
// NB. Strings already constructed in Build_display.cpp
- makeDebugTextBlock(_vm->_largestLayerInfo, 0, 60);
- makeDebugTextBlock(_vm->_largestSpriteInfo, 0, 75);
+ makeDebugTextBlock(_vm->_screen->getLargestLayerInfo(), 0, 60);
+ makeDebugTextBlock(_vm->_screen->getLargestSpriteInfo(), 0, 75);
// "waiting for person" indicator - set form fnTheyDo and
// fnTheyDoWeWait
@@ -303,6 +313,7 @@ void Debugger::buildDebugText(void) {
}
void Debugger::drawDebugGraphics(void) {
+ ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
// walk-grid
if (_displayWalkGrid)
@@ -311,12 +322,17 @@ void Debugger::drawDebugGraphics(void) {
// player feet coord marker
if (_displayPlayerMarker)
- plotCrossHair(_vm->_thisScreen.player_feet_x, _vm->_thisScreen.player_feet_y, 215);
+ plotCrossHair(screenInfo->player_feet_x, screenInfo->player_feet_y, 215);
// mouse marker & coords
- if (_displayMouseMarker)
- plotCrossHair(_vm->_mouseX + _vm->_thisScreen.scroll_offset_x, _vm->_mouseY + _vm->_thisScreen.scroll_offset_y, 215);
+ if (_displayMouseMarker) {
+ int mouseX, mouseY;
+
+ _vm->_mouse->getPos(mouseX, mouseY);
+
+ plotCrossHair(mouseX + screenInfo->scroll_offset_x, mouseY + screenInfo->scroll_offset_y, 215);
+ }
// mouse area rectangle / sprite box rectangle when testing anims
@@ -332,29 +348,30 @@ void Debugger::drawDebugGraphics(void) {
}
void Debugger::plotCrossHair(int16 x, int16 y, uint8 pen) {
- _vm->_graphics->plotPoint(x, y, pen);
+ _vm->_screen->plotPoint(x, y, pen);
- _vm->_graphics->drawLine(x - 2, y, x - 5, y, pen);
- _vm->_graphics->drawLine(x + 2, y, x + 5, y, pen);
+ _vm->_screen->drawLine(x - 2, y, x - 5, y, pen);
+ _vm->_screen->drawLine(x + 2, y, x + 5, y, pen);
- _vm->_graphics->drawLine(x, y - 2, x, y - 5, pen);
- _vm->_graphics->drawLine(x, y + 2, x, y + 5, pen);
+ _vm->_screen->drawLine(x, y - 2, x, y - 5, pen);
+ _vm->_screen->drawLine(x, y + 2, x, y + 5, pen);
}
void Debugger::drawRect(int16 x1, int16 y1, int16 x2, int16 y2, uint8 pen) {
- _vm->_graphics->drawLine(x1, y1, x2, y1, pen); // top edge
- _vm->_graphics->drawLine(x1, y2, x2, y2, pen); // bottom edge
- _vm->_graphics->drawLine(x1, y1, x1, y2, pen); // left edge
- _vm->_graphics->drawLine(x2, y1, x2, y2, pen); // right edge
+ _vm->_screen->drawLine(x1, y1, x2, y1, pen); // top edge
+ _vm->_screen->drawLine(x1, y2, x2, y2, pen); // bottom edge
+ _vm->_screen->drawLine(x1, y1, x1, y2, pen); // left edge
+ _vm->_screen->drawLine(x2, y1, x2, y2, pen); // right edge
}
void Debugger::printCurrentInfo(void) {
// prints general stuff about the screen, etc.
+ ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
- if (_vm->_thisScreen.background_layer_id) {
- DebugPrintf("background layer id %d\n", _vm->_thisScreen.background_layer_id);
- DebugPrintf("%d wide, %d high\n", _vm->_thisScreen.screen_wide, _vm->_thisScreen.screen_deep);
- DebugPrintf("%d normal layers\n", _vm->_thisScreen.number_of_layers);
+ if (screenInfo->background_layer_id) {
+ DebugPrintf("background layer id %d\n", screenInfo->background_layer_id);
+ DebugPrintf("%d wide, %d high\n", screenInfo->screen_wide, screenInfo->screen_deep);
+ DebugPrintf("%d normal layers\n", screenInfo->number_of_layers);
_vm->_logic->examineRunList();
} else
diff --git a/sword2/debug.h b/sword2/debug.h
index 87a9043990..a733052e14 100644
--- a/sword2/debug.h
+++ b/sword2/debug.h
@@ -22,7 +22,7 @@
#define D_DEBUG
// FIXME: I don't know how large this constant used to be
-#define MAX_DEBUG_TEXTS 50
+#define MAX_DEBUG_TEXTS 55
#define MAX_SHOWVARS 15
diff --git a/sword2/driver/_mouse.cpp b/sword2/driver/_mouse.cpp
index 42ee42872c..606d362767 100644
--- a/sword2/driver/_mouse.cpp
+++ b/sword2/driver/_mouse.cpp
@@ -20,14 +20,19 @@
#include "common/stdafx.h"
#include "common/system.h"
+
#include "sword2/sword2.h"
-#include "sword2/driver/d_draw.h"
+#include "sword2/mouse.h"
namespace Sword2 {
+// This is the maximum mouse cursor size in the SDL backend
+#define MAX_MOUSE_W 80
+#define MAX_MOUSE_H 80
+
#define MOUSEFLASHFRAME 6
-void Graphics::decompressMouse(byte *decomp, byte *comp, int width, int height, int pitch, int xOff, int yOff) {
+void Mouse::decompressMouse(byte *decomp, byte *comp, int width, int height, int pitch, int xOff, int yOff) {
int32 size = width * height;
int32 i = 0;
int x = 0;
@@ -52,7 +57,7 @@ void Graphics::decompressMouse(byte *decomp, byte *comp, int width, int height,
}
}
-void Graphics::drawMouse(void) {
+void Mouse::drawMouse() {
byte mouseData[MAX_MOUSE_W * MAX_MOUSE_H];
if (!_mouseAnim && !_luggageAnim)
@@ -129,7 +134,7 @@ void Graphics::drawMouse(void) {
* Animates the current mouse pointer
*/
-int32 Graphics::animateMouse(void) {
+int32 Mouse::animateMouse() {
uint8 prevMouseFrame = _mouseFrame;
if (!_mouseAnim)
@@ -154,7 +159,7 @@ int32 Graphics::animateMouse(void) {
* or not there is a lead-in animation
*/
-int32 Graphics::setMouseAnim(byte *ma, int32 size, int32 mouseFlash) {
+int32 Mouse::setMouseAnim(byte *ma, int32 size, int32 mouseFlash) {
if (_mouseAnim) {
free(_mouseAnim);
_mouseAnim = NULL;
@@ -194,7 +199,7 @@ int32 Graphics::setMouseAnim(byte *ma, int32 size, int32 mouseFlash) {
* @param size the size of the animation data
*/
-int32 Graphics::setLuggageAnim(byte *ma, int32 size) {
+int32 Mouse::setLuggageAnim(byte *ma, int32 size) {
if (_luggageAnim) {
free(_luggageAnim);
_luggageAnim = NULL;
diff --git a/sword2/driver/animation.cpp b/sword2/driver/animation.cpp
index d6d58e856d..260d42f454 100644
--- a/sword2/driver/animation.cpp
+++ b/sword2/driver/animation.cpp
@@ -31,7 +31,6 @@
#include "sword2/resman.h"
#include "sword2/sound.h"
#include "sword2/driver/animation.h"
-#include "sword2/driver/d_draw.h"
#include "sword2/driver/menu.h"
#include "sword2/driver/render.h"
@@ -47,7 +46,7 @@ AnimationState::~AnimationState() {
#ifdef BACKEND_8BIT
void AnimationState::setPalette(byte *pal) {
- _vm->_graphics->setPalette(0, 256, pal, RDPAL_INSTANT);
+ _vm->_screen->setPalette(0, 256, pal, RDPAL_INSTANT);
}
#else
@@ -82,7 +81,7 @@ void AnimationState::drawTextObject(SpriteInfo *s, byte *src) {
void AnimationState::clearScreen(void) {
#ifdef BACKEND_8BIT
- memset(_vm->_graphics->getScreen(), 0, MOVIE_WIDTH * MOVIE_HEIGHT);
+ memset(_vm->_screen->getScreen(), 0, MOVIE_WIDTH * MOVIE_HEIGHT);
#else
OverlayColor black = _sys->RGBToColor(0, 0, 0);
@@ -93,7 +92,7 @@ void AnimationState::clearScreen(void) {
void AnimationState::updateScreen(void) {
#ifdef BACKEND_8BIT
- byte *buf = _vm->_graphics->getScreen() + ((480 - MOVIE_HEIGHT) / 2) * RENDERWIDE + (640 - MOVIE_WIDTH) / 2;
+ byte *buf = _vm->_screen->getScreen() + ((480 - MOVIE_HEIGHT) / 2) * RENDERWIDE + (640 - MOVIE_WIDTH) / 2;
_vm->_system->copyRectToScreen(buf, MOVIE_WIDTH, (640 - MOVIE_WIDTH) / 2, (480 - MOVIE_HEIGHT) / 2, MOVIE_WIDTH, MOVIE_HEIGHT);
#else
@@ -104,7 +103,7 @@ void AnimationState::updateScreen(void) {
void AnimationState::drawYUV(int width, int height, byte *const *dat) {
#ifdef BACKEND_8BIT
- _vm->_graphics->plotYUV(lut, width, height, dat);
+ _vm->_screen->plotYUV(lut, width, height, dat);
#else
plotYUV(lookup, width, height, dat);
#endif
@@ -138,12 +137,12 @@ MoviePlayer::MoviePlayer(Sword2Engine *vm)
void MoviePlayer::openTextObject(MovieTextObject *obj) {
if (obj->textSprite)
- _vm->_graphics->createSurface(obj->textSprite, &_textSurface);
+ _vm->_screen->createSurface(obj->textSprite, &_textSurface);
}
void MoviePlayer::closeTextObject(MovieTextObject *obj) {
if (_textSurface) {
- _vm->_graphics->deleteSurface(_textSurface);
+ _vm->_screen->deleteSurface(_textSurface);
_textSurface = NULL;
}
}
@@ -151,12 +150,12 @@ void MoviePlayer::closeTextObject(MovieTextObject *obj) {
void MoviePlayer::drawTextObject(AnimationState *anim, MovieTextObject *obj) {
if (obj->textSprite && _textSurface) {
#ifdef BACKEND_8BIT
- _vm->_graphics->drawSurface(obj->textSprite, _textSurface);
+ _vm->_screen->drawSurface(obj->textSprite, _textSurface);
#else
if (anim)
anim->drawTextObject(obj->textSprite, _textSurface);
else
- _vm->_graphics->drawSurface(obj->textSprite, _textSurface);
+ _vm->_screen->drawSurface(obj->textSprite, _textSurface);
#endif
}
}
@@ -211,7 +210,7 @@ int32 MoviePlayer::play(const char *filename, MovieTextObject *text[], int32 lea
// Wait for the lead-out to stop, if there is any.
while (_leadOutHandle.isActive()) {
- _vm->_graphics->updateDisplay();
+ _vm->_screen->updateDisplay();
_vm->_system->delayMillis(30);
}
@@ -232,7 +231,7 @@ void MoviePlayer::playMPEG(const char *filename, MovieTextObject *text[], byte *
bool startNextText = false;
byte oldPal[256 * 4];
- memcpy(oldPal, _vm->_graphics->_palette, sizeof(oldPal));
+ memcpy(oldPal, _vm->_screen->getPalette(), sizeof(oldPal));
AnimationState *anim = new AnimationState(_vm);
@@ -246,8 +245,8 @@ void MoviePlayer::playMPEG(const char *filename, MovieTextObject *text[], byte *
#ifndef BACKEND_8BIT
// Clear the screen, because whatever is on it will be visible when the
// overlay is removed.
- _vm->_graphics->clearScene();
- _vm->_graphics->updateDisplay();
+ _vm->_screen->clearScene();
+ _vm->_screen->updateDisplay();
#endif
#ifndef SCUMM_BIG_ENDIAN
@@ -357,7 +356,7 @@ void MoviePlayer::playMPEG(const char *filename, MovieTextObject *text[], byte *
_snd->stopHandle(handle);
while (handle.isActive()) {
- _vm->_graphics->updateDisplay(false);
+ _vm->_screen->updateDisplay(false);
_sys->delayMillis(100);
}
@@ -365,7 +364,7 @@ void MoviePlayer::playMPEG(const char *filename, MovieTextObject *text[], byte *
anim->clearScreen();
anim->updateScreen();
- _vm->_graphics->setPalette(0, 256, oldPal, RDPAL_INSTANT);
+ _vm->_screen->setPalette(0, 256, oldPal, RDPAL_INSTANT);
delete anim;
}
@@ -384,14 +383,14 @@ void MoviePlayer::playDummy(const char *filename, MovieTextObject *text[], byte
byte oldPal[256 * 4];
byte tmpPal[256 * 4];
- _vm->_graphics->clearScene();
+ _vm->_screen->clearScene();
// HACK: Draw instructions
//
// I'm using the the menu area, because that's unlikely to be touched
// by anything else during the cutscene.
- memset(_vm->_graphics->_buffer, 0, _vm->_graphics->_screenWide * MENUDEEP);
+ memset(_vm->_screen->getScreen(), 0, _vm->_screen->getScreenWide() * MENUDEEP);
byte *data;
@@ -415,16 +414,16 @@ void MoviePlayer::playDummy(const char *filename, MovieTextObject *text[], byte
SpriteInfo msgSprite;
byte *msgSurface;
- msgSprite.x = _vm->_graphics->_screenWide / 2 - frame->width / 2;
+ msgSprite.x = _vm->_screen->getScreenWide() / 2 - frame->width / 2;
msgSprite.y = RDMENU_MENUDEEP / 2 - frame->height / 2;
msgSprite.w = frame->width;
msgSprite.h = frame->height;
msgSprite.type = RDSPR_NOCOMPRESSION;
msgSprite.data = data + sizeof(FrameHeader);
- _vm->_graphics->createSurface(&msgSprite, &msgSurface);
- _vm->_graphics->drawSurface(&msgSprite, msgSurface);
- _vm->_graphics->deleteSurface(msgSurface);
+ _vm->_screen->createSurface(&msgSprite, &msgSurface);
+ _vm->_screen->drawSurface(&msgSprite, msgSurface);
+ _vm->_screen->deleteSurface(msgSurface);
free(data);
@@ -436,12 +435,12 @@ void MoviePlayer::playDummy(const char *filename, MovieTextObject *text[], byte
// Fake a palette that will hopefully make the text visible. In the
// opening cutscene it seems to use colours 1 (black) and 255 (white).
- memcpy(oldPal, _vm->_graphics->_palette, sizeof(oldPal));
+ memcpy(oldPal, _vm->_screen->getPalette(), sizeof(oldPal));
memset(tmpPal, 0, sizeof(tmpPal));
tmpPal[255 * 4 + 0] = 255;
tmpPal[255 * 4 + 1] = 255;
tmpPal[255 * 4 + 2] = 255;
- _vm->_graphics->setPalette(0, 256, tmpPal, RDPAL_INSTANT);
+ _vm->_screen->setPalette(0, 256, tmpPal, RDPAL_INSTANT);
PlayingSoundHandle handle;
@@ -458,7 +457,7 @@ void MoviePlayer::playDummy(const char *filename, MovieTextObject *text[], byte
break;
if (frameCounter == text[textCounter]->startFrame) {
- _vm->_graphics->clearScene();
+ _vm->_screen->clearScene();
openTextObject(text[textCounter]);
drawTextObject(NULL, text[textCounter]);
if (text[textCounter]->speech) {
@@ -468,13 +467,13 @@ void MoviePlayer::playDummy(const char *filename, MovieTextObject *text[], byte
if (frameCounter == text[textCounter]->endFrame) {
closeTextObject(text[textCounter]);
- _vm->_graphics->clearScene();
- _vm->_graphics->setNeedFullRedraw();
+ _vm->_screen->clearScene();
+ _vm->_screen->setNeedFullRedraw();
textCounter++;
}
frameCounter++;
- _vm->_graphics->updateDisplay();
+ _vm->_screen->updateDisplay();
KeyboardEvent *ke = _vm->keyboardEvent();
@@ -496,23 +495,23 @@ void MoviePlayer::playDummy(const char *filename, MovieTextObject *text[], byte
// importantly - that we don't free the sound buffer while it's in use.
while (handle.isActive()) {
- _vm->_graphics->updateDisplay(false);
+ _vm->_screen->updateDisplay(false);
_sys->delayMillis(100);
}
closeTextObject(text[textCounter]);
- _vm->_graphics->clearScene();
- _vm->_graphics->setNeedFullRedraw();
+ _vm->_screen->clearScene();
+ _vm->_screen->setNeedFullRedraw();
// HACK: Remove the instructions created above
Common::Rect r;
- memset(_vm->_graphics->_buffer, 0, _vm->_graphics->_screenWide * MENUDEEP);
+ memset(_vm->_screen->getScreen(), 0, _vm->_screen->getScreenWide() * MENUDEEP);
r.left = r.top = 0;
- r.right = _vm->_graphics->_screenWide;
+ r.right = _vm->_screen->getScreenWide();
r.bottom = MENUDEEP;
- _vm->_graphics->updateRect(&r);
+ _vm->_screen->updateRect(&r);
// FIXME: For now, only play the lead-out music for cutscenes that have
// subtitles.
@@ -520,7 +519,7 @@ void MoviePlayer::playDummy(const char *filename, MovieTextObject *text[], byte
if (!skipCutscene && leadOut)
_vm->_sound->playFx(&_leadOutHandle, leadOut, leadOutLen, SoundMixer::kMaxChannelVolume, 0, false, SoundMixer::kMusicAudioDataType);
- _vm->_graphics->setPalette(0, 256, oldPal, RDPAL_INSTANT);
+ _vm->_screen->setPalette(0, 256, oldPal, RDPAL_INSTANT);
}
} // End of namespace Sword2
diff --git a/sword2/driver/animation.h b/sword2/driver/animation.h
index f34d8c8b06..0dcac3fc81 100644
--- a/sword2/driver/animation.h
+++ b/sword2/driver/animation.h
@@ -23,12 +23,24 @@
#define ANIMATION_H
#include "graphics/animation.h"
-
#include "sound/mixer.h"
-
namespace Sword2 {
+struct SpriteInfo;
+
+// This is the structure which is passed to the sequence player. It includes
+// the smack to play, and any text lines which are to be displayed over the top
+// of the sequence.
+
+struct MovieTextObject {
+ uint16 startFrame;
+ uint16 endFrame;
+ SpriteInfo *textSprite;
+ uint32 speechBufferSize;
+ uint16 *speech;
+};
+
class AnimationState : public ::Graphics::BaseAnimationState {
private:
Sword2Engine *_vm;
diff --git a/sword2/driver/d_draw.cpp b/sword2/driver/d_draw.cpp
index cee13d5d06..b20123e4b5 100644
--- a/sword2/driver/d_draw.cpp
+++ b/sword2/driver/d_draw.cpp
@@ -21,72 +21,20 @@
#include "common/stdafx.h"
#include "common/system.h"
#include "sword2/sword2.h"
-#include "sword2/driver/d_draw.h"
#include "sword2/driver/menu.h"
#include "sword2/driver/render.h"
namespace Sword2 {
-Graphics::Graphics(Sword2Engine *vm, int16 width, int16 height)
- : _vm(vm), _iconCount(0), _needFullRedraw(false),
- _fadeStatus(RDFADE_NONE), _mouseSprite(NULL), _mouseAnim(NULL),
- _luggageAnim(NULL), _layer(0), _renderAverageTime(60),
- _lightMask(NULL), _screenWide(width), _screenDeep(height) {
-
- int i, j;
-
- _buffer = _dirtyGrid = NULL;
-
- _buffer = (byte *) malloc(width * height);
- if (!_buffer)
- error("Could not initialise display");
-
- _vm->_system->initSize(width, height);
-
- _gridWide = width / CELLWIDE;
- _gridDeep = height / CELLDEEP;
-
- if ((width % CELLWIDE) || (height % CELLDEEP))
- error("Bad cell size");
-
- _dirtyGrid = (byte *) calloc(_gridWide, _gridDeep);
- if (!_buffer)
- error("Could not initialise dirty grid");
-
- for (i = 0; i < ARRAYSIZE(_blockSurfaces); i++)
- _blockSurfaces[i] = NULL;
-
- for (i = 0; i < 2; i++) {
- for (j = 0; j < RDMENU_MAXPOCKETS; j++) {
- _icons[i][j] = NULL;
- _pocketStatus[i][j] = 0;
- }
-
- _menuStatus[i] = RDMENU_HIDDEN;
- }
-}
-
-Graphics::~Graphics() {
- free(_buffer);
- free(_dirtyGrid);
- closeBackgroundLayer();
- free(_lightMask);
- free(_mouseAnim);
- free(_luggageAnim);
- for (int i = 0; i < 2; i++)
- for (int j = 0; j < RDMENU_MAXPOCKETS; j++)
- free(_icons[i][j]);
-}
-
/**
* @return the graphics detail setting
*/
-int8 Graphics::getRenderLevel(void) {
+int8 Screen::getRenderLevel() {
return _renderLevel;
}
-void Graphics::setRenderLevel(int8 level) {
+void Screen::setRenderLevel(int8 level) {
_renderLevel = level;
switch (_renderLevel) {
@@ -115,7 +63,7 @@ void Graphics::setRenderLevel(int8 level) {
* touch the menu areas of the screen.
*/
-void Graphics::clearScene(void) {
+void Screen::clearScene() {
memset(_buffer + MENUDEEP * _screenWide, 0, _screenWide * RENDERDEEP);
_needFullRedraw = true;
}
diff --git a/sword2/driver/d_draw.h b/sword2/driver/d_draw.h
deleted file mode 100644
index e9b27c7f2c..0000000000
--- a/sword2/driver/d_draw.h
+++ /dev/null
@@ -1,242 +0,0 @@
-/* Copyright (C) 1994-1998 Revolution Software Ltd.
- * Copyright (C) 2003-2005 The ScummVM project
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * $Header$
- */
-
-#ifndef D_DRAW_H
-#define D_DRAW_H
-
-#include "common/rect.h"
-
-namespace Sword2 {
-
-// This is the maximum mouse cursor size in the SDL backend
-
-#define MAX_MOUSE_W 80
-#define MAX_MOUSE_H 80
-
-#define RENDERAVERAGETOTAL 4
-
-#define BLOCKWIDTH 64
-#define BLOCKHEIGHT 64
-#define MAXLAYERS 5
-
-#define PALTABLESIZE 64 * 64 * 64
-
-// Maximum scaled size of a sprite
-#define SCALE_MAXWIDTH 512
-#define SCALE_MAXHEIGHT 512
-
-// Dirty grid cell size
-#define CELLWIDE 10
-#define CELLDEEP 20
-
-#if !defined(__GNUC__)
- #pragma START_PACK_STRUCTS
-#endif
-
-struct MouseAnim {
- uint8 runTimeComp; // type of runtime compression used for the
- // frame data
- uint8 noAnimFrames; // number of frames in the anim
- int8 xHotSpot;
- int8 yHotSpot;
- uint8 mousew;
- uint8 mouseh;
-} GCC_PACK;
-
-#if !defined(__GNUC__)
- #pragma END_PACK_STRUCTS
-#endif
-
-struct BlockSurface {
- byte data[BLOCKWIDTH * BLOCKHEIGHT];
- bool transparent;
-};
-
-class Graphics {
- friend class MoviePlayer;
-
-private:
- Sword2Engine *_vm;
-
- byte *_buffer;
- byte *_dirtyGrid;
-
- uint16 _gridWide;
- uint16 _gridDeep;
-
- int32 _renderCaps;
- int8 _renderLevel;
-
- uint8 _menuStatus[2];
- byte *_icons[2][RDMENU_MAXPOCKETS];
- uint8 _pocketStatus[2][RDMENU_MAXPOCKETS];
-
- uint8 _iconCount;
-
- bool _needFullRedraw;
-
- byte _paletteMatch[PALTABLESIZE];
-
- uint8 _fadeStatus;
-
- int32 _fadeStartTime;
- int32 _fadeTotalTime;
-
- uint8 _mouseFrame;
- byte *_mouseSprite;
- struct MouseAnim *_mouseAnim;
- struct MouseAnim *_luggageAnim;
- int32 *_mouseOffsets;
- int32 *_luggageOffset;
-
- // Scroll variables. _scrollX and _scrollY hold the current scroll
- // position, and _scrollXTarget and _scrollYTarget are the target
- // position for the end of the game cycle.
-
- int16 _scrollX;
- int16 _scrollY;
-
- int16 _scrollXTarget;
- int16 _scrollYTarget;
- int16 _scrollXOld;
- int16 _scrollYOld;
-
- int16 _parallaxScrollX; // current x offset to link a sprite to the
- // parallax layer
- int16 _parallaxScrollY; // current y offset to link a sprite to the
- // parallax layer
- int16 _locationWide;
- int16 _locationDeep;
-
- uint16 _layer;
-
- int32 _initialTime;
- int32 _startTime;
- int32 _totalTime;
- int32 _renderAverageTime;
- int32 _framesPerGameCycle;
- bool _renderTooSlow;
-
- uint8 _xBlocks[MAXLAYERS];
- uint8 _yBlocks[MAXLAYERS];
-
- // An array of sub-blocks, one for each of the parallax layers.
-
- BlockSurface **_blockSurfaces[MAXLAYERS];
-
- uint16 _xScale[SCALE_MAXWIDTH];
- uint16 _yScale[SCALE_MAXHEIGHT];
-
- byte *_lightMask;
-
- void clearIconArea(int menu, int pocket, Common::Rect *r);
-
- void decompressMouse(byte *decomp, byte *comp, int width, int height, int pitch, int xOff = 0, int yOff = 0);
-
- void fadeServer(void);
-
- void scaleImageFast(byte *dst, uint16 dstPitch, uint16 dstWidth,
- uint16 dstHeight, byte *src, uint16 srcPitch, uint16 srcWidth,
- uint16 srcHeight);
- void scaleImageGood(byte *dst, uint16 dstPitch, uint16 dstWidth,
- uint16 dstHeight, byte *src, uint16 srcPitch, uint16 srcWidth,
- uint16 srcHeight, byte *backbuf);
-
- void updateRect(Common::Rect *r);
-
- void blitBlockSurface(BlockSurface *s, Common::Rect *r, Common::Rect *clipRect);
-
- void mirrorSprite(byte *dst, byte *src, int16 w, int16 h);
- int32 decompressRLE256(byte *dest, byte *source, int32 decompSize);
- void unwindRaw16(byte *dest, byte *source, uint8 blockSize, byte *colTable);
- int32 decompressRLE16(byte *dest, byte *source, int32 decompSize, byte *colTable);
-
-
-public:
- Graphics(Sword2Engine *vm, int16 width, int16 height);
- ~Graphics();
-
- // Game screen metrics
- int16 _screenWide;
- int16 _screenDeep;
-
- byte _palette[256 * 4];
-
- byte *getScreen(void) { return _buffer; }
-
- int8 getRenderLevel(void);
- void setRenderLevel(int8 level);
-
- void clearScene(void);
-
- void processMenu(void);
- int32 showMenu(uint8 menu);
- int32 hideMenu(uint8 menu);
- int32 setMenuIcon(uint8 menu, uint8 pocket, byte *icon);
- void closeMenuImmediately(void);
-
- void markAsDirty(int16 x0, int16 y0, int16 x1, int16 y1);
- void updateDisplay(bool redrawScene = true);
- void setNeedFullRedraw(void);
-
- void setPalette(int16 startEntry, int16 noEntries, byte *palette, uint8 setNow);
- void updatePaletteMatchTable(byte *data);
- uint8 quickMatch(uint8 r, uint8 g, uint8 b);
- int32 fadeUp(float time = 0.75);
- int32 fadeDown(float time = 0.75);
- uint8 getFadeStatus(void);
- void dimPalette(void);
- void waitForFade(void);
-
- int32 setMouseAnim(byte *ma, int32 size, int32 mouseFlash);
- int32 setLuggageAnim(byte *la, int32 size);
- int32 animateMouse(void);
-
- void drawMouse(void);
-
- void resetRenderEngine(void);
-
- void setScrollTarget(int16 sx, int16 sy);
- void initialiseRenderCycle(void);
- void startRenderCycle(void);
- bool endRenderCycle(void);
- void renderParallax(Parallax *p, int16 layer);
- void setLocationMetrics(uint16 w, uint16 h);
- int32 initialiseBackgroundLayer(Parallax *p);
- void closeBackgroundLayer(void);
-
- void plotPoint(int16 x, int16 y, uint8 colour);
- void drawLine(int16 x1, int16 y1, int16 x2, int16 y2, uint8 colour);
-#ifdef BACKEND_8BIT
- void plotYUV(byte *lut, int width, int height, byte *const *dat);
-#endif
-
-
- int32 createSurface(SpriteInfo *s, byte **surface);
- void drawSurface(SpriteInfo *s, byte *surface, Common::Rect *clipRect = NULL);
- void deleteSurface(byte *surface);
- int32 drawSprite(SpriteInfo *s);
- int32 openLightMask(SpriteInfo *s);
- int32 closeLightMask(void);
-};
-
-} // End of namespace Sword2
-
-#endif
diff --git a/sword2/driver/d_sound.cpp b/sword2/driver/d_sound.cpp
index 39992b18d6..a8e3d444e0 100644
--- a/sword2/driver/d_sound.cpp
+++ b/sword2/driver/d_sound.cpp
@@ -35,7 +35,6 @@
#include "sword2/sword2.h"
#include "sword2/resman.h"
#include "sword2/sound.h"
-#include "sword2/driver/d_draw.h"
namespace Sword2 {
@@ -790,8 +789,11 @@ int32 Sound::setFxIdVolumePan(int32 i, int vol, int pan) {
_fxQueue[i].volume = (vol * SoundMixer::kMaxChannelVolume) / 16;
- if (pan != -1)
+ if (pan != 255) {
+ if (isReverseStereo())
+ pan = -pan;
_fxQueue[i].pan = (pan * 127) / 16;
+ }
if (!_fxMuted && _fxQueue[i].handle.isActive()) {
_vm->_mixer->setChannelVolume(_fxQueue[i].handle, _fxQueue[i].volume);
diff --git a/sword2/driver/driver96.h b/sword2/driver/driver96.h
index a10c4652f1..43acd6e7b2 100644
--- a/sword2/driver/driver96.h
+++ b/sword2/driver/driver96.h
@@ -177,36 +177,6 @@ struct Parallax {
#pragma END_PACK_STRUCTS
#endif
-// The SpriteInfo structure is used to tell the driver96 code what attributes
-// are linked to a sprite for drawing. These include position, scaling and
-// compression.
-
-struct SpriteInfo {
- int16 x; // coords for top-left of sprite
- int16 y;
- uint16 w; // dimensions of sprite (before scaling)
- uint16 h;
- uint16 scale; // scale at which to draw, given in 256ths ['0' or '256' MEANS DON'T SCALE]
- uint16 scaledWidth; // new dimensions (we calc these for the mouse area, so may as well pass to you to save time)
- uint16 scaledHeight; //
- uint16 type; // mask containing 'RDSPR_' bits specifying compression type, flip, transparency, etc
- uint16 blend; // holds the blending values.
- byte *data; // pointer to the sprite data
- byte *colourTable; // pointer to 16-byte colour table, only applicable to 16-col compression type
-};
-
-// This is the structure which is passed to the sequence player. It includes
-// the smack to play, and any text lines which are to be displayed over the top
-// of the sequence.
-
-struct MovieTextObject {
- uint16 startFrame;
- uint16 endFrame;
- SpriteInfo *textSprite;
- uint32 speechBufferSize;
- uint16 *speech;
-};
-
} // End of namespace Sword2
#endif
diff --git a/sword2/driver/menu.cpp b/sword2/driver/menu.cpp
index 4929a97696..267a254a4d 100644
--- a/sword2/driver/menu.cpp
+++ b/sword2/driver/menu.cpp
@@ -20,7 +20,7 @@
#include "common/stdafx.h"
#include "sword2/sword2.h"
-#include "sword2/driver/d_draw.h"
+#include "sword2/mouse.h"
#include "sword2/driver/render.h"
namespace Sword2 {
@@ -28,17 +28,20 @@ namespace Sword2 {
#define MENUDEEP 40
#define MAXMENUANIMS 8
-void Graphics::clearIconArea(int menu, int pocket, Common::Rect *r) {
+void Mouse::clearIconArea(int menu, int pocket, Common::Rect *r) {
+ byte *buf = _vm->_screen->getScreen();
+ int16 screenWide = _vm->_screen->getScreenWide();
+
r->top = menu * (RENDERDEEP + MENUDEEP) + (MENUDEEP - RDMENU_ICONDEEP) / 2;
r->bottom = r->top + RDMENU_ICONDEEP;
r->left = RDMENU_ICONSTART + pocket * (RDMENU_ICONWIDE + RDMENU_ICONSPACING);
r->right = r->left + RDMENU_ICONWIDE;
- byte *dst = _buffer + r->top * _screenWide + r->left;
+ byte *dst = buf + r->top * screenWide + r->left;
for (int i = 0; i < RDMENU_ICONDEEP; i++) {
memset(dst, 0, RDMENU_ICONWIDE);
- dst += _screenWide;
+ dst += screenWide;
}
}
@@ -48,13 +51,16 @@ void Graphics::clearIconArea(int menu, int pocket, Common::Rect *r) {
* system is.
*/
-void Graphics::processMenu(void) {
+void Mouse::processMenu() {
uint8 menu;
uint8 i, j;
uint8 frameCount;
Common::Rect r1, r2;
static int32 lastTime = 0;
+ byte *buf = _vm->_screen->getScreen();
+ int16 screenWide = _vm->_screen->getScreenWide();
+
if (lastTime == 0) {
lastTime = _vm->getMillis();
frameCount = 1;
@@ -153,22 +159,22 @@ void Graphics::processMenu(void) {
}
if (xoff != 0 && yoff != 0) {
- byte *dst = _buffer + r2.top * _screenWide + r2.left;
+ byte *dst = buf + r2.top * screenWide + r2.left;
byte *src = _icons[menu][i];
if (_pocketStatus[menu][i] != MAXMENUANIMS) {
- scaleImageFast(
- dst, _screenWide, r2.right - r2.left, r2.bottom - r2.top,
+ _vm->_screen->scaleImageFast(
+ dst, screenWide, r2.right - r2.left, r2.bottom - r2.top,
src, RDMENU_ICONWIDE, RDMENU_ICONWIDE, RDMENU_ICONDEEP);
} else {
for (j = 0; j < RDMENU_ICONDEEP; j++) {
memcpy(dst, src, RDMENU_ICONWIDE);
src += RDMENU_ICONWIDE;
- dst += _screenWide;
+ dst += screenWide;
}
}
}
- updateRect(&r1);
+ _vm->_screen->updateRect(&r1);
}
curx += (RDMENU_ICONSPACING + RDMENU_ICONWIDE);
}
@@ -181,7 +187,7 @@ void Graphics::processMenu(void) {
* @return RD_OK, or an error code
*/
-int32 Graphics::showMenu(uint8 menu) {
+int32 Mouse::showMenu(uint8 menu) {
// Check for invalid menu parameter
if (menu > RDMENU_BOTTOM)
return RDERR_INVALIDMENU;
@@ -201,7 +207,7 @@ int32 Graphics::showMenu(uint8 menu) {
* @return RD_OK, or an error code
*/
-int32 Graphics::hideMenu(uint8 menu) {
+int32 Mouse::hideMenu(uint8 menu) {
// Check for invalid menu parameter
if (menu > RDMENU_BOTTOM)
return RDERR_INVALIDMENU;
@@ -219,7 +225,7 @@ int32 Graphics::hideMenu(uint8 menu) {
* This function hides both menus immediately.
*/
-void Graphics::closeMenuImmediately(void) {
+void Mouse::closeMenuImmediately() {
Common::Rect r;
int i;
@@ -229,11 +235,11 @@ void Graphics::closeMenuImmediately(void) {
for (i = 0; i < RDMENU_MAXPOCKETS; i++) {
if (_icons[RDMENU_TOP][i]) {
clearIconArea(RDMENU_TOP, i, &r);
- updateRect(&r);
+ _vm->_screen->updateRect(&r);
}
if (_icons[RDMENU_BOTTOM][i]) {
clearIconArea(RDMENU_BOTTOM, i, &r);
- updateRect(&r);
+ _vm->_screen->updateRect(&r);
}
}
@@ -248,7 +254,7 @@ void Graphics::closeMenuImmediately(void) {
* @return RD_OK, or an error code
*/
-int32 Graphics::setMenuIcon(uint8 menu, uint8 pocket, byte *icon) {
+int32 Mouse::setMenuIcon(uint8 menu, uint8 pocket, byte *icon) {
Common::Rect r;
// Check for invalid menu parameter.
@@ -265,7 +271,7 @@ int32 Graphics::setMenuIcon(uint8 menu, uint8 pocket, byte *icon) {
free(_icons[menu][pocket]);
_icons[menu][pocket] = NULL;
clearIconArea(menu, pocket, &r);
- updateRect(&r);
+ _vm->_screen->updateRect(&r);
}
// Only put the icon in the pocket if it is not NULL
diff --git a/sword2/driver/palette.cpp b/sword2/driver/palette.cpp
index 754a3564ce..3e42cef493 100644
--- a/sword2/driver/palette.cpp
+++ b/sword2/driver/palette.cpp
@@ -21,19 +21,101 @@
#include "common/stdafx.h"
#include "common/system.h"
#include "sword2/sword2.h"
-#include "sword2/driver/d_draw.h"
+#include "sword2/defs.h"
+#include "sword2/logic.h"
+#include "sword2/resman.h"
namespace Sword2 {
/**
- * Sets a table of palette indices which will be searched later for a quick
- * palette match.
- * @param data the palette match table
+ * Start layer palette fading up
*/
-void Graphics::updatePaletteMatchTable(byte *data) {
- assert(data);
- memcpy(_paletteMatch, data, PALTABLESIZE);
+void Screen::startNewPalette() {
+ // If the screen is still fading down then wait for black - could
+ // happen when everythings cached into a large memory model
+ waitForFade();
+
+ byte *screenFile = _vm->_resman->openResource(_thisScreen.background_layer_id);
+
+ memcpy(_paletteMatch, _vm->fetchPaletteMatchTable(screenFile), PALTABLESIZE);
+ setPalette(0, 256, _vm->fetchPalette(screenFile), RDPAL_FADE);
+
+ // Indicating that it's a screen palette
+ _lastPaletteRes = 0;
+
+ _vm->_resman->closeResource(_thisScreen.background_layer_id);
+ fadeUp();
+ _thisScreen.new_palette = 0;
+}
+
+void Screen::setFullPalette(int32 palRes) {
+ // fudge for hut interior
+ // - unpausing should restore last palette as normal (could be screen
+ // palette or 'dark_palette_13')
+ // - but restoring the screen palette after 'dark_palette_13' should
+ // now work properly too!
+
+ // "Hut interior" refers to the watchman's hut in Marseille, and this
+ // is apparently needed for the palette to be restored properly when
+ // you turn the light off. (I didn't even notice the light switch!)
+
+ if (Logic::_scriptVars[LOCATION] == 13) {
+ // unpausing
+ if (palRes == -1) {
+ // restore whatever palette was last set (screen
+ // palette or 'dark_palette_13')
+ palRes = _lastPaletteRes;
+ }
+ } else {
+ // check if we're just restoring the current screen palette
+ // because we might actually need to use a separate palette
+ // file anyway eg. for pausing & unpausing during the eclipse
+
+ // unpausing (fudged for location 13)
+ if (palRes == -1) {
+ // we really meant '0'
+ palRes = 0;
+ }
+
+ if (palRes == 0 && _lastPaletteRes)
+ palRes = _lastPaletteRes;
+ }
+
+ // If non-zero, set palette to this separate palette file. Otherwise,
+ // set palette to current screen palette.
+
+ if (palRes) {
+ byte *pal = _vm->_resman->openResource(palRes);
+
+ StandardHeader *head = (StandardHeader *) pal;
+ assert(head->fileType == PALETTE_FILE);
+
+ pal += sizeof(StandardHeader);
+
+ // always set colour 0 to black because most background screen
+ // palettes have a bright colour 0 although it should come out
+ // as black in the game!
+
+ pal[0] = 0;
+ pal[1] = 0;
+ pal[2] = 0;
+ pal[3] = 0;
+
+ setPalette(0, 256, pal, RDPAL_INSTANT);
+ _vm->_resman->closeResource(palRes);
+ } else {
+ if (_thisScreen.background_layer_id) {
+ byte *data = _vm->_resman->openResource(_thisScreen.background_layer_id);
+ memcpy(_paletteMatch, _vm->fetchPaletteMatchTable(data), PALTABLESIZE);
+ setPalette(0, 256, _vm->fetchPalette(data), RDPAL_INSTANT);
+ _vm->_resman->closeResource(_thisScreen.background_layer_id);
+ } else
+ error("setFullPalette(0) called, but no current screen available!");
+ }
+
+ if (palRes != CONTROL_PANEL_PALETTE)
+ _lastPaletteRes = palRes;
}
/**
@@ -47,7 +129,7 @@ void Graphics::updatePaletteMatchTable(byte *data) {
// FIXME: This used to be inlined - probably a good idea - but the
// linker complained when I tried to use it in sprite.cpp.
-uint8 Graphics::quickMatch(uint8 r, uint8 g, uint8 b) {
+uint8 Screen::quickMatch(uint8 r, uint8 g, uint8 b) {
return _paletteMatch[((int32) (r >> 2) << 12) + ((int32) (g >> 2) << 6) + (b >> 2)];
}
@@ -59,7 +141,7 @@ uint8 Graphics::quickMatch(uint8 r, uint8 g, uint8 b) {
* @param fadeNow whether to perform the change immediately or delayed
*/
-void Graphics::setPalette(int16 startEntry, int16 noEntries, byte *colourTable, uint8 fadeNow) {
+void Screen::setPalette(int16 startEntry, int16 noEntries, byte *colourTable, uint8 fadeNow) {
assert(noEntries > 0);
memcpy(&_palette[4 * startEntry], colourTable, noEntries * 4);
@@ -70,7 +152,7 @@ void Graphics::setPalette(int16 startEntry, int16 noEntries, byte *colourTable,
}
}
-void Graphics::dimPalette(void) {
+void Screen::dimPalette() {
byte *p = _palette;
for (int i = 0; i < 256; i++) {
@@ -88,7 +170,7 @@ void Graphics::dimPalette(void) {
* @param time the time it will take the palette to fade up
*/
-int32 Graphics::fadeUp(float time) {
+int32 Screen::fadeUp(float time) {
if (getFadeStatus() != RDFADE_BLACK && getFadeStatus() != RDFADE_NONE)
return RDERR_FADEINCOMPLETE;
@@ -104,7 +186,7 @@ int32 Graphics::fadeUp(float time) {
* @param time the time it will take the palette to fade down
*/
-int32 Graphics::fadeDown(float time) {
+int32 Screen::fadeDown(float time) {
if (getFadeStatus() != RDFADE_BLACK && getFadeStatus() != RDFADE_NONE)
return RDERR_FADEINCOMPLETE;
@@ -121,18 +203,18 @@ int32 Graphics::fadeDown(float time) {
* (not faded), or RDFADE_BLACK (completely faded down)
*/
-uint8 Graphics::getFadeStatus(void) {
+uint8 Screen::getFadeStatus() {
return _fadeStatus;
}
-void Graphics::waitForFade(void) {
+void Screen::waitForFade() {
while (getFadeStatus() != RDFADE_NONE && getFadeStatus() != RDFADE_BLACK) {
updateDisplay();
_vm->_system->delayMillis(20);
}
}
-void Graphics::fadeServer(void) {
+void Screen::fadeServer() {
static int32 previousTime = 0;
byte fadePalette[256 * 4];
byte *newPalette = fadePalette;
diff --git a/sword2/driver/rdwin.cpp b/sword2/driver/rdwin.cpp
index 14d4e144f5..d74cc89bc8 100644
--- a/sword2/driver/rdwin.cpp
+++ b/sword2/driver/rdwin.cpp
@@ -21,7 +21,6 @@
#include "common/stdafx.h"
#include "common/system.h"
#include "sword2/sword2.h"
-#include "sword2/driver/d_draw.h"
#include "sword2/driver/menu.h"
namespace Sword2 {
@@ -30,7 +29,7 @@ namespace Sword2 {
* Tell updateDisplay() that the scene needs to be completely updated.
*/
-void Graphics::setNeedFullRedraw(void) {
+void Screen::setNeedFullRedraw() {
_needFullRedraw = true;
}
@@ -38,7 +37,7 @@ void Graphics::setNeedFullRedraw(void) {
* Mark an area of the screen as dirty, first generation.
*/
-void Graphics::markAsDirty(int16 x0, int16 y0, int16 x1, int16 y1) {
+void Screen::markAsDirty(int16 x0, int16 y0, int16 x1, int16 y1) {
int16 gridX0 = x0 / CELLWIDE;
int16 gridY0 = y0 / CELLDEEP;
int16 gridX1 = x1 / CELLWIDE;
@@ -58,7 +57,7 @@ void Graphics::markAsDirty(int16 x0, int16 y0, int16 x1, int16 y1) {
* @param redrawScene If true, redraw the scene.
*/
-void Graphics::updateDisplay(bool redrawScene) {
+void Screen::updateDisplay(bool redrawScene) {
_vm->parseEvents();
fadeServer();
diff --git a/sword2/driver/render.cpp b/sword2/driver/render.cpp
index 5ea1c63b06..ff0dcab5a9 100644
--- a/sword2/driver/render.cpp
+++ b/sword2/driver/render.cpp
@@ -21,22 +21,23 @@
#include "common/stdafx.h"
#include "common/system.h"
#include "sword2/sword2.h"
+#include "sword2/build_display.h"
#include "sword2/driver/animation.h"
-#include "sword2/driver/d_draw.h"
#include "sword2/driver/menu.h"
#include "sword2/driver/render.h"
namespace Sword2 {
-#define MILLISECSPERCYCLE 83
+#define MILLISECSPERCYCLE 83
+#define RENDERAVERAGETOTAL 4
-void Graphics::updateRect(Common::Rect *r) {
+void Screen::updateRect(Common::Rect *r) {
_vm->_system->copyRectToScreen(_buffer + r->top * _screenWide + r->left,
_screenWide, r->left, r->top, r->right - r->left,
r->bottom - r->top);
}
-void Graphics::blitBlockSurface(BlockSurface *s, Common::Rect *r, Common::Rect *clipRect) {
+void Screen::blitBlockSurface(BlockSurface *s, Common::Rect *r, Common::Rect *clipRect) {
if (!r->intersects(*clipRect))
return;
@@ -85,7 +86,7 @@ void Graphics::blitBlockSurface(BlockSurface *s, Common::Rect *r, Common::Rect *
// This code isn't quite like the original DrawSprite(), but should be close
// enough.
-void Graphics::scaleImageFast(byte *dst, uint16 dstPitch, uint16 dstWidth, uint16 dstHeight, byte *src, uint16 srcPitch, uint16 srcWidth, uint16 srcHeight) {
+void Screen::scaleImageFast(byte *dst, uint16 dstPitch, uint16 dstWidth, uint16 dstHeight, byte *src, uint16 srcPitch, uint16 srcWidth, uint16 srcHeight) {
int x, y;
for (x = 0; x < dstWidth; x++)
@@ -102,7 +103,7 @@ void Graphics::scaleImageFast(byte *dst, uint16 dstPitch, uint16 dstWidth, uint1
}
}
-void Graphics::scaleImageGood(byte *dst, uint16 dstPitch, uint16 dstWidth, uint16 dstHeight, byte *src, uint16 srcPitch, uint16 srcWidth, uint16 srcHeight, byte *backbuf) {
+void Screen::scaleImageGood(byte *dst, uint16 dstPitch, uint16 dstWidth, uint16 dstHeight, byte *src, uint16 srcPitch, uint16 srcWidth, uint16 srcHeight, byte *backbuf) {
for (int y = 0; y < dstHeight; y++) {
for (int x = 0; x < dstWidth; x++) {
uint8 c1, c2, c3, c4;
@@ -194,7 +195,7 @@ void Graphics::scaleImageGood(byte *dst, uint16 dstPitch, uint16 dstWidth, uint1
* @param colour colour of the point
*/
-void Graphics::plotPoint(int16 x, int16 y, uint8 colour) {
+void Screen::plotPoint(int16 x, int16 y, uint8 colour) {
byte *buf = _buffer + MENUDEEP * RENDERWIDE;
x -= _scrollX;
@@ -217,7 +218,7 @@ void Graphics::plotPoint(int16 x, int16 y, uint8 colour) {
// Uses Bresenham's incremental algorithm!
-void Graphics::drawLine(int16 x0, int16 y0, int16 x1, int16 y1, uint8 colour) {
+void Screen::drawLine(int16 x0, int16 y0, int16 x1, int16 y1, uint8 colour) {
int dxmod, dymod;
int ince, incne;
int d;
@@ -363,7 +364,7 @@ void Graphics::drawLine(int16 x0, int16 y0, int16 x1, int16 y1, uint8 colour) {
* @param h height of the current location
*/
-void Graphics::setLocationMetrics(uint16 w, uint16 h) {
+void Screen::setLocationMetrics(uint16 w, uint16 h) {
_locationWide = w;
_locationDeep = h;
setNeedFullRedraw();
@@ -374,7 +375,7 @@ void Graphics::setLocationMetrics(uint16 w, uint16 h) {
* parallax can be either foreground, background or the main screen.
*/
-void Graphics::renderParallax(Parallax *p, int16 l) {
+void Screen::renderParallax(Parallax *p, int16 l) {
int16 x, y;
Common::Rect r;
@@ -420,7 +421,7 @@ void Graphics::renderParallax(Parallax *p, int16 l) {
* Initialises the timers before the render loop is entered.
*/
-void Graphics::initialiseRenderCycle(void) {
+void Screen::initialiseRenderCycle(void) {
_initialTime = _vm->_system->getMillis();
_totalTime = _initialTime + MILLISECSPERCYCLE;
}
@@ -430,7 +431,7 @@ void Graphics::initialiseRenderCycle(void) {
* render cycle.
*/
-void Graphics::startRenderCycle(void) {
+void Screen::startRenderCycle(void) {
_scrollXOld = _scrollX;
_scrollYOld = _scrollY;
@@ -458,7 +459,7 @@ void Graphics::startRenderCycle(void) {
* or false if it should continue
*/
-bool Graphics::endRenderCycle(void) {
+bool Screen::endRenderCycle(void) {
static int32 renderTimeLog[4] = { 60, 60, 60, 60 };
static int32 renderCountIndex = 0;
int32 time;
@@ -524,7 +525,7 @@ bool Graphics::endRenderCycle(void) {
* Reset scrolling stuff. This function is called from initBackground()
*/
-void Graphics::resetRenderEngine(void) {
+void Screen::resetRenderEngine(void) {
_parallaxScrollX = 0;
_parallaxScrollY = 0;
_scrollX = 0;
@@ -532,22 +533,11 @@ void Graphics::resetRenderEngine(void) {
}
/**
- * Sets the scroll target position for the end of the game cycle. The driver
- * will then automatically scroll as many times as it can to reach this
- * position in the allotted time.
- */
-
-void Graphics::setScrollTarget(int16 sx, int16 sy) {
- _scrollXTarget = sx;
- _scrollYTarget = sy;
-}
-
-/**
* This function should be called five times with either the parallax layer
* or a NULL pointer in order of background parallax to foreground parallax.
*/
-int32 Graphics::initialiseBackgroundLayer(Parallax *p) {
+int32 Screen::initialiseBackgroundLayer(Parallax *p) {
uint16 i, j, k;
byte *data;
byte *dst;
@@ -666,7 +656,7 @@ int32 Graphics::initialiseBackgroundLayer(Parallax *p) {
* Should be called once after leaving the room to free up memory.
*/
-void Graphics::closeBackgroundLayer(void) {
+void Screen::closeBackgroundLayer(void) {
debug(2, "CloseBackgroundLayer");
for (int i = 0; i < MAXLAYERS; i++) {
@@ -683,7 +673,7 @@ void Graphics::closeBackgroundLayer(void) {
}
#ifdef BACKEND_8BIT
-void Graphics::plotYUV(byte *lut, int width, int height, byte *const *dat) {
+void Screen::plotYUV(byte *lut, int width, int height, byte *const *dat) {
byte *buf = _buffer + ((480 - height) / 2) * RENDERWIDE + (640 - width) / 2;
int x, y;
diff --git a/sword2/driver/sprite.cpp b/sword2/driver/sprite.cpp
index e6c1ffe0e8..7c96df75c2 100644
--- a/sword2/driver/sprite.cpp
+++ b/sword2/driver/sprite.cpp
@@ -20,7 +20,7 @@
#include "common/stdafx.h"
#include "sword2/sword2.h"
-#include "sword2/driver/d_draw.h"
+#include "sword2/build_display.h"
namespace Sword2 {
@@ -32,7 +32,7 @@ namespace Sword2 {
* @param h height of the sprite
*/
-void Graphics::mirrorSprite(byte *dst, byte *src, int16 w, int16 h) {
+void Screen::mirrorSprite(byte *dst, byte *src, int16 w, int16 h) {
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
*dst++ = *(src + w - x - 1);
@@ -44,12 +44,12 @@ void Graphics::mirrorSprite(byte *dst, byte *src, int16 w, int16 h) {
/**
* This function takes a compressed frame of a sprite with up to 256 colours
* and decompresses it.
- * @param dest destination buffer
- * @param source source buffer
+ * @param dst destination buffer
+ * @param src source buffer
* @param decompSize the expected size of the decompressed sprite
*/
-int32 Graphics::decompressRLE256(byte *dest, byte *source, int32 decompSize) {
+int32 Screen::decompressRLE256(byte *dst, byte *src, int32 decompSize) {
// PARAMETERS:
// source points to the start of the sprite data for input
// decompSize gives size of decompressed data in bytes
@@ -57,35 +57,35 @@ int32 Graphics::decompressRLE256(byte *dest, byte *source, int32 decompSize) {
// data
byte headerByte; // block header byte
- byte *endDest = dest + decompSize; // pointer to byte after end of decomp buffer
+ byte *endDest = dst + decompSize; // pointer to byte after end of decomp buffer
int32 rv;
- while(1) {
+ while (1) {
// FLAT block
// read FLAT block header & increment 'scan' to first pixel
// of block
- headerByte = *source++;
+ headerByte = *src++;
// if this isn't a zero-length block
if (headerByte) {
- if (dest + headerByte > endDest) {
+ if (dst + headerByte > endDest) {
rv = 1;
break;
}
// set the next 'headerByte' pixels to the next colour
// at 'source'
- memset(dest, *source, headerByte);
+ memset(dst, *src, headerByte);
// increment destination pointer to just after this
// block
- dest += headerByte;
+ dst += headerByte;
// increment source pointer to just after this colour
- source++;
+ src++;
// if we've decompressed all of the data
- if (dest == endDest) {
+ if (dst == endDest) {
rv = 0; // return "OK"
break;
}
@@ -94,28 +94,28 @@ int32 Graphics::decompressRLE256(byte *dest, byte *source, int32 decompSize) {
// RAW block
// read RAW block header & increment 'scan' to first pixel of
// block
- headerByte = *source++;
+ headerByte = *src++;
// if this isn't a zero-length block
if (headerByte) {
- if (dest + headerByte > endDest) {
+ if (dst + headerByte > endDest) {
rv = 1;
break;
}
// copy the next 'headerByte' pixels from source to
// destination
- memcpy(dest,source,headerByte);
+ memcpy(dst, src, headerByte);
// increment destination pointer to just after this
// block
- dest += headerByte;
+ dst += headerByte;
// increment source pointer to just after this block
- source += headerByte;
+ src += headerByte;
// if we've decompressed all of the data
- if (dest == endDest) {
+ if (dst == endDest) {
rv = 0; // return "OK"
break;
}
@@ -129,19 +129,19 @@ int32 Graphics::decompressRLE256(byte *dest, byte *source, int32 decompSize) {
* Unwinds a run of 16-colour data into 256-colour palette data.
*/
-void Graphics::unwindRaw16(byte *dest, byte *source, uint8 blockSize, byte *colTable) {
+void Screen::unwindRaw16(byte *dst, byte *src, uint8 blockSize, byte *colTable) {
// for each pair of pixels
while (blockSize > 1) {
// 1st colour = number in table at position given by upper
// nibble of source byte
- *dest++ = colTable[(*source) >> 4];
+ *dst++ = colTable[(*src) >> 4];
// 2nd colour = number in table at position given by lower
// nibble of source byte
- *dest++ = colTable[(*source) & 0x0f];
+ *dst++ = colTable[(*src) & 0x0f];
// point to next source byte
- source++;
+ src++;
// decrement count of how many pixels left to read
blockSize -= 2;
@@ -151,50 +151,50 @@ void Graphics::unwindRaw16(byte *dest, byte *source, uint8 blockSize, byte *colT
if (blockSize) {
// colour = number in table at position given by upper nibble
// of source byte
- *dest++ = colTable[(*source) >> 4];
+ *dst++ = colTable[(*src) >> 4];
}
}
/**
* This function takes a compressed frame of a sprite (with up to 16 colours)
* and decompresses it.
- * @param dest destination buffer
- * @param source source buffer
+ * @param dst destination buffer
+ * @param src source buffer
* @param decompSize the expected size of the uncompressed sprite
* @param colTable mapping from the 16 encoded colours to the current palette
*/
-int32 Graphics::decompressRLE16(byte *dest, byte *source, int32 decompSize, byte *colTable) {
+int32 Screen::decompressRLE16(byte *dst, byte *src, int32 decompSize, byte *colTable) {
byte headerByte; // block header byte
- byte *endDest = dest + decompSize; // pointer to byte after end of decomp buffer
+ byte *endDest = dst + decompSize; // pointer to byte after end of decomp buffer
int32 rv;
- while(1) {
+ while (1) {
// FLAT block
// read FLAT block header & increment 'scan' to first pixel
// of block
- headerByte = *source++;
+ headerByte = *src++;
// if this isn't a zero-length block
if (headerByte) {
- if (dest + headerByte > endDest) {
+ if (dst + headerByte > endDest) {
rv = 1;
break;
}
// set the next 'headerByte' pixels to the next
// colour at 'source'
- memset(dest, *source, headerByte);
+ memset(dst, *src, headerByte);
// increment destination pointer to just after this
// block
- dest += headerByte;
+ dst += headerByte;
// increment source pointer to just after this colour
- source++;
+ src++;
// if we've decompressed all of the data
- if (dest == endDest) {
+ if (dst == endDest) {
rv = 0; // return "OK"
break;
}
@@ -203,29 +203,29 @@ int32 Graphics::decompressRLE16(byte *dest, byte *source, int32 decompSize, byte
// RAW block
// read RAW block header & increment 'scan' to first pixel of
// block
- headerByte = *source++;
+ headerByte = *src++;
// if this isn't a zero-length block
if (headerByte) {
- if (dest + headerByte > endDest) {
+ if (dst + headerByte > endDest) {
rv = 1;
break;
}
// copy the next 'headerByte' pixels from source to
// destination (NB. 2 pixels per byte)
- unwindRaw16(dest, source, headerByte, colTable);
+ unwindRaw16(dst, src, headerByte, colTable);
// increment destination pointer to just after this
// block
- dest += headerByte;
+ dst += headerByte;
// increment source pointer to just after this block
// (NB. headerByte gives pixels, so /2 for bytes)
- source += (headerByte + 1) / 2;
+ src += (headerByte + 1) / 2;
// if we've decompressed all of the data
- if (dest >= endDest) {
+ if (dst >= endDest) {
rv = 0; // return "OK"
break;
}
@@ -244,7 +244,7 @@ int32 Graphics::decompressRLE16(byte *dest, byte *source, int32 decompSize, byte
* @return RD_OK, or an error code
*/
-int32 Graphics::createSurface(SpriteInfo *s, byte **sprite) {
+int32 Screen::createSurface(SpriteInfo *s, byte **sprite) {
*sprite = (byte *) malloc(s->w * s->h);
if (!*sprite)
return RDERR_OUTOFMEMORY;
@@ -269,7 +269,7 @@ int32 Graphics::createSurface(SpriteInfo *s, byte **sprite) {
* @param clipRect the clipping rectangle
*/
-void Graphics::drawSurface(SpriteInfo *s, byte *surface, Common::Rect *clipRect) {
+void Screen::drawSurface(SpriteInfo *s, byte *surface, Common::Rect *clipRect) {
Common::Rect rd, rs;
uint16 x, y;
byte *src, *dst;
@@ -328,7 +328,7 @@ void Graphics::drawSurface(SpriteInfo *s, byte *surface, Common::Rect *clipRect)
* Destroys a surface.
*/
-void Graphics::deleteSurface(byte *surface) {
+void Screen::deleteSurface(byte *surface) {
free(surface);
}
@@ -353,7 +353,7 @@ void Graphics::deleteSurface(byte *surface) {
// FIXME: I'm sure this could be optimized. There's plenty of data copying and
// mallocing here.
-int32 Graphics::drawSprite(SpriteInfo *s) {
+int32 Screen::drawSprite(SpriteInfo *s) {
byte *src, *dst;
byte *sprite, *newSprite;
uint16 scale;
@@ -610,7 +610,7 @@ int32 Graphics::drawSprite(SpriteInfo *s) {
* Opens the light masking sprite for a room.
*/
-int32 Graphics::openLightMask(SpriteInfo *s) {
+int32 Screen::openLightMask(SpriteInfo *s) {
// FIXME: The light mask is only needed on higher graphics detail
// settings, so to save memory we could simply ignore it on lower
// settings. But then we need to figure out how to ensure that it
@@ -633,7 +633,7 @@ int32 Graphics::openLightMask(SpriteInfo *s) {
* Closes the light masking sprite for a room.
*/
-int32 Graphics::closeLightMask(void) {
+int32 Screen::closeLightMask(void) {
if (!_lightMask)
return RDERR_NOTOPEN;
diff --git a/sword2/function.cpp b/sword2/function.cpp
index 748de8bec4..51931417b2 100644
--- a/sword2/function.cpp
+++ b/sword2/function.cpp
@@ -21,19 +21,21 @@
#include "common/stdafx.h"
#include "common/file.h"
#include "common/system.h"
+
#include "sword2/sword2.h"
#include "sword2/defs.h"
+#include "sword2/build_display.h"
#include "sword2/console.h"
#include "sword2/controls.h"
#include "sword2/interpreter.h"
#include "sword2/logic.h"
#include "sword2/maketext.h"
#include "sword2/memory.h"
+#include "sword2/mouse.h"
#include "sword2/resman.h"
#include "sword2/router.h"
#include "sword2/sound.h"
#include "sword2/driver/animation.h"
-#include "sword2/driver/d_draw.h"
#include "sword2/driver/render.h"
namespace Sword2 {
@@ -65,7 +67,8 @@ int32 Logic::fnInitBackground(int32 *params) {
// params: 0 res id of normal background layer - cannot be 0
// 1 1 yes 0 no for a new palette
- return _vm->initBackground(params[0], params[1]);
+ _vm->_screen->initBackground(params[0], params[1]);
+ return IR_CONT;
}
/**
@@ -106,7 +109,9 @@ int32 Logic::fnRegisterMouse(int32 *params) {
// params: 0 pointer to ObjectMouse or 0 for no write to mouse
// list
- _vm->registerMouse((ObjectMouse *) _vm->_memory->decodePtr(params[0]));
+ ObjectMouse *ob_mouse = (ObjectMouse *) _vm->_memory->decodePtr(params[0]);
+
+ _vm->_mouse->registerMouse(ob_mouse, NULL);
return IR_CONT;
}
@@ -244,15 +249,15 @@ int32 Logic::fnChoose(int32 *params) {
for (i = 0; i < _scriptVars[IN_SUBJECT]; i++) {
icon = _vm->_resman->openResource(_subjectList[i].res) + sizeof(StandardHeader) + RDMENU_ICONWIDE * RDMENU_ICONDEEP;
- _vm->_graphics->setMenuIcon(RDMENU_BOTTOM, i, icon);
+ _vm->_mouse->setMenuIcon(RDMENU_BOTTOM, i, icon);
_vm->_resman->closeResource(_subjectList[i].res);
}
for (; i < 15; i++)
- _vm->_graphics->setMenuIcon(RDMENU_BOTTOM, (uint8) i, NULL);
+ _vm->_mouse->setMenuIcon(RDMENU_BOTTOM, (uint8) i, NULL);
- _vm->_graphics->showMenu(RDMENU_BOTTOM);
- _vm->setMouse(NORMAL_MOUSE_ID);
+ _vm->_mouse->showMenu(RDMENU_BOTTOM);
+ _vm->_mouse->setMouse(NORMAL_MOUSE_ID);
_choosing = true;
return IR_REPEAT;
}
@@ -261,13 +266,16 @@ int32 Logic::fnChoose(int32 *params) {
// about left clicks.
MouseEvent *me = _vm->mouseEvent();
+ int mouseX, mouseY;
- if (!me || !(me->buttons & RD_LEFTBUTTONDOWN) || _vm->_mouseY < 400)
+ _vm->_mouse->getPos(mouseX, mouseY);
+
+ if (!me || !(me->buttons & RD_LEFTBUTTONDOWN) || mouseY < 400)
return IR_REPEAT;
// Check for click on a menu.
- int hit = _vm->menuClick(_scriptVars[IN_SUBJECT]);
+ int hit = _vm->_mouse->menuClick(_scriptVars[IN_SUBJECT]);
if (hit < 0)
return IR_REPEAT;
@@ -276,7 +284,7 @@ int32 Logic::fnChoose(int32 *params) {
for (i = 0; i < _scriptVars[IN_SUBJECT]; i++) {
if ((int) i != hit) {
icon = _vm->_resman->openResource(_subjectList[i].res) + sizeof(StandardHeader);
- _vm->_graphics->setMenuIcon(RDMENU_BOTTOM, i, icon);
+ _vm->_mouse->setMenuIcon(RDMENU_BOTTOM, i, icon);
_vm->_resman->closeResource(_subjectList[i].res);
}
}
@@ -288,7 +296,7 @@ int32 Logic::fnChoose(int32 *params) {
_choosing = false;
_scriptVars[IN_SUBJECT] = 0;
- _vm->setMouse(0);
+ _vm->_mouse->setMouse(0);
return IR_CONT | (_subjectList[hit].ref << 3);
}
@@ -371,7 +379,7 @@ int32 Logic::fnWalk(int32 *params) {
// Walk is about to start, so set the mega's graphic resource
ob_graph->anim_resource = ob_mega->megaset_res;
- } else if (_scriptVars[EXIT_FADING] && _vm->_graphics->getFadeStatus() == RDFADE_BLACK) {
+ } else if (_scriptVars[EXIT_FADING] && _vm->_screen->getFadeStatus() == RDFADE_BLACK) {
// Double clicked an exit so quit the walk when screen is black
// ok, thats it - back to script and change screen
@@ -687,8 +695,9 @@ int32 Logic::fnMegaTableAnim(int32 *params) {
int32 Logic::fnAddMenuObject(int32 *params) {
// params: 0 pointer to a MenuObject structure to copy down
+ MenuObject *menuObject = (MenuObject *) _vm->_memory->decodePtr(params[0]);
- _vm->addMenuObject((MenuObject *) _vm->_memory->decodePtr(params[0]));
+ _vm->_mouse->addMenuObject(menuObject);
return IR_CONT;
}
@@ -704,12 +713,7 @@ int32 Logic::fnAddMenuObject(int32 *params) {
int32 Logic::fnStartConversation(int32 *params) {
// params: none
- if (_scriptVars[TALK_FLAG] == 0) {
- // See fnChooser & speech scripts
- _scriptVars[CHOOSER_COUNT_FLAG] = 0;
- }
-
- fnNoHuman(params);
+ _vm->_mouse->startConversation();
return IR_CONT;
}
@@ -720,16 +724,7 @@ int32 Logic::fnStartConversation(int32 *params) {
int32 Logic::fnEndConversation(int32 *params) {
// params: none
- _vm->_graphics->hideMenu(RDMENU_BOTTOM);
-
- if (_vm->_mouseY > 399) {
- // Will wait for cursor to move off the bottom menu
- _vm->_mouseMode = MOUSE_holding;
- }
-
- // In case DC forgets
- _scriptVars[TALK_FLAG] = 0;
-
+ _vm->_mouse->endConversation();
return IR_CONT;
}
@@ -789,7 +784,12 @@ int32 Logic::fnRegisterFrame(int32 *params) {
// 1 pointer to graphic structure
// 2 pointer to mega structure or NULL if not a mega
- return _vm->registerFrame(params);
+ ObjectMouse *ob_mouse = (ObjectMouse *) _vm->_memory->decodePtr(params[0]);
+ ObjectGraphic *ob_graph = (ObjectGraphic *) _vm->_memory->decodePtr(params[1]);
+ ObjectMega *ob_mega = (ObjectMega *) _vm->_memory->decodePtr(params[2]);
+
+ _vm->_screen->registerFrame(ob_mouse, ob_graph, ob_mega);
+ return IR_CONT;
}
int32 Logic::fnNoSprite(int32 *params) {
@@ -824,15 +824,16 @@ int32 Logic::fnUpdatePlayerStats(int32 *params) {
// params: 0 pointer to mega structure
ObjectMega *ob_mega = (ObjectMega *) _vm->_memory->decodePtr(params[0]);
+ ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
- _vm->_thisScreen.player_feet_x = ob_mega->feet_x;
- _vm->_thisScreen.player_feet_y = ob_mega->feet_y;
+ screenInfo->player_feet_x = ob_mega->feet_x;
+ screenInfo->player_feet_y = ob_mega->feet_y;
// for the script
_scriptVars[PLAYER_FEET_X] = ob_mega->feet_x;
_scriptVars[PLAYER_FEET_Y] = ob_mega->feet_y;
_scriptVars[PLAYER_CUR_DIR] = ob_mega->current_dir;
- _scriptVars[SCROLL_OFFSET_X] = _vm->_thisScreen.scroll_offset_x;
+ _scriptVars[SCROLL_OFFSET_X] = screenInfo->scroll_offset_x;
debug(5, "fnUpdatePlayerStats: %d %d", ob_mega->feet_x, ob_mega->feet_y);
@@ -856,13 +857,14 @@ int32 Logic::fnInitFloorMouse(int32 *params) {
// params: 0 pointer to object's mouse structure
ObjectMouse *ob_mouse = (ObjectMouse *) _vm->_memory->decodePtr(params[0]);
+ ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
// floor is always lowest priority
ob_mouse->x1 = 0;
ob_mouse->y1 = 0;
- ob_mouse->x2 = _vm->_thisScreen.screen_wide - 1;
- ob_mouse->y2 = _vm->_thisScreen.screen_deep - 1;
+ ob_mouse->x2 = screenInfo->screen_wide - 1;
+ ob_mouse->y2 = screenInfo->screen_deep - 1;
ob_mouse->priority = 9;
ob_mouse->pointer = NORMAL_MOUSE_ID;
return IR_CONT;
@@ -939,95 +941,14 @@ int32 Logic::fnEndSession(int32 *params) {
int32 Logic::fnNoHuman(int32 *params) {
// params: none
- _vm->noHuman();
- _vm->clearPointerText();
-
- // must be normal mouse situation or a largely neutral situation -
- // special menus use noHuman
-
- // dont hide menu in conversations
- if (_scriptVars[TALK_FLAG] == 0)
- _vm->_graphics->hideMenu(RDMENU_BOTTOM);
-
- if (_vm->_mouseMode == MOUSE_system_menu) {
- // close menu
- _vm->_mouseMode = MOUSE_normal;
- _vm->_graphics->hideMenu(RDMENU_TOP);
- }
-
+ _vm->_mouse->noHuman();
return IR_CONT;
}
int32 Logic::fnAddHuman(int32 *params) {
// params: none
- // for logic scripts
- _scriptVars[MOUSE_AVAILABLE] = 1;
-
- // off
- if (_vm->_mouseStatus) {
- _vm->_mouseStatus = false; // on
- _vm->_mouseTouching = 1; // forces engine to choose a cursor
- }
-
- // clear this to reset no-second-click system
- _scriptVars[CLICKED_ID] = 0;
-
- // this is now done outside the OBJECT_HELD check in case it's set to
- // zero before now!
-
- // unlock the mouse from possible large object lock situtations - see
- // syphon in rm 3
-
- _vm->_mouseModeLocked = false;
-
- if (_scriptVars[OBJECT_HELD]) {
- // was dragging something around
- // need to clear this again
- _scriptVars[OBJECT_HELD] = 0;
-
- // and these may also need clearing, just in case
- _vm->_examiningMenuIcon = false;
- Logic::_scriptVars[COMBINE_BASE] = 0;
-
- _vm->setLuggage(0);
- }
-
- // if mouse is over menu area
- if (_vm->_mouseY > 399) {
- if (_vm->_mouseMode != MOUSE_holding) {
- // VITAL - reset things & rebuild the menu
- _vm->_mouseMode = MOUSE_normal;
- _vm->setMouse(NORMAL_MOUSE_ID);
- } else
- _vm->setMouse(NORMAL_MOUSE_ID);
- }
-
- // enabled/disabled from console; status printed with on-screen debug
- // info
-
- if (_vm->_debugger->_testingSnR) {
- uint8 black[4] = { 0, 0, 0, 0 };
- uint8 white[4] = { 255, 255, 255, 0 };
-
- // testing logic scripts by simulating an instant Save &
- // Restore
-
- _vm->_graphics->setPalette(0, 1, white, RDPAL_INSTANT);
-
- // stops all fx & clears the queue - eg. when leaving a
- // location
-
- _vm->_sound->clearFxQueue();
-
- // Trash all object resources so they load in fresh & restart
- // their logic scripts
-
- _vm->_resman->killAllObjects(false);
-
- _vm->_graphics->setPalette(0, 1, black, RDPAL_INSTANT);
- }
-
+ _vm->_mouse->addHuman();
return IR_CONT;
}
@@ -1265,8 +1186,8 @@ int32 Logic::fnFadeDown(int32 *params) {
// params: none
- if (_vm->_graphics->getFadeStatus() == RDFADE_NONE)
- _vm->_graphics->fadeDown();
+ if (_vm->_screen->getFadeStatus() == RDFADE_NONE)
+ _vm->_screen->fadeDown();
return IR_CONT;
}
@@ -1562,9 +1483,13 @@ int32 Logic::fnISpeak(int32 *params) {
// Ok, all is running along smoothly - but a click means stop
// unnaturally
+ int mouseX, mouseY;
+
+ _vm->_mouse->getPos(mouseX, mouseY);
+
// So that we can go to the options panel while text & speech is
// being tested
- if (_scriptVars[SYSTEM_TESTING_TEXT] == 0 || _vm->_mouseY > 0) {
+ if (_scriptVars[SYSTEM_TESTING_TEXT] == 0 || mouseY > 0) {
MouseEvent *me = _vm->mouseEvent();
// Note that we now have TWO click-delays - one for LEFT
@@ -2299,8 +2224,10 @@ int32 Logic::fnSetScrollCoordinate(int32 *params) {
// feet_x & feet_y refer to the physical screen coords where the
// system will try to maintain George's feet
- _vm->_thisScreen.feet_x = params[0];
- _vm->_thisScreen.feet_y = params[1];
+ ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
+
+ screenInfo->feet_x = params[0];
+ screenInfo->feet_y = params[1];
return IR_CONT;
}
@@ -2350,16 +2277,17 @@ int32 Logic::fnSetScrollLeftMouse(int32 *params) {
// params: 0 pointer to object's mouse structure
ObjectMouse *ob_mouse = (ObjectMouse *) _vm->_memory->decodePtr(params[0]);
+ ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
// Highest priority
ob_mouse->x1 = 0;
ob_mouse->y1 = 0;
- ob_mouse->x2 = _vm->_thisScreen.scroll_offset_x + SCROLL_MOUSE_WIDTH;
- ob_mouse->y2 = _vm->_thisScreen.screen_deep - 1;
+ ob_mouse->x2 = screenInfo->scroll_offset_x + SCROLL_MOUSE_WIDTH;
+ ob_mouse->y2 = screenInfo->screen_deep - 1;
ob_mouse->priority = 0;
- if (_vm->_thisScreen.scroll_offset_x > 0) {
+ if (screenInfo->scroll_offset_x > 0) {
// not fully scrolled to the left
ob_mouse->pointer = SCROLL_LEFT_MOUSE_ID;
} else {
@@ -2374,16 +2302,17 @@ int32 Logic::fnSetScrollRightMouse(int32 *params) {
// params: 0 pointer to object's mouse structure
ObjectMouse *ob_mouse = (ObjectMouse *) _vm->_memory->decodePtr(params[0]);
+ ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
// Highest priority
- ob_mouse->x1 = _vm->_thisScreen.scroll_offset_x + _vm->_graphics->_screenWide - SCROLL_MOUSE_WIDTH;
+ ob_mouse->x1 = screenInfo->scroll_offset_x + _vm->_screen->getScreenWide() - SCROLL_MOUSE_WIDTH;
ob_mouse->y1 = 0;
- ob_mouse->x2 = _vm->_thisScreen.screen_wide - 1;
- ob_mouse->y2 = _vm->_thisScreen.screen_deep - 1;
+ ob_mouse->x2 = screenInfo->screen_wide - 1;
+ ob_mouse->y2 = screenInfo->screen_deep - 1;
ob_mouse->priority = 0;
- if (_vm->_thisScreen.scroll_offset_x < _vm->_thisScreen.max_scroll_offset_x) {
+ if (screenInfo->scroll_offset_x < screenInfo->max_scroll_offset_x) {
// not fully scrolled to the right
ob_mouse->pointer = SCROLL_RIGHT_MOUSE_ID;
} else {
@@ -2405,19 +2334,19 @@ int32 Logic::fnColour(int32 *params) {
// what colour?
switch (params[0]) {
case BLACK:
- _vm->_graphics->setPalette(0, 1, black, RDPAL_INSTANT);
+ _vm->_screen->setPalette(0, 1, black, RDPAL_INSTANT);
break;
case WHITE:
- _vm->_graphics->setPalette(0, 1, white, RDPAL_INSTANT);
+ _vm->_screen->setPalette(0, 1, white, RDPAL_INSTANT);
break;
case RED:
- _vm->_graphics->setPalette(0, 1, red, RDPAL_INSTANT);
+ _vm->_screen->setPalette(0, 1, red, RDPAL_INSTANT);
break;
case GREEN:
- _vm->_graphics->setPalette(0, 1, green, RDPAL_INSTANT);
+ _vm->_screen->setPalette(0, 1, green, RDPAL_INSTANT);
break;
case BLUE:
- _vm->_graphics->setPalette(0, 1, blue, RDPAL_INSTANT);
+ _vm->_screen->setPalette(0, 1, blue, RDPAL_INSTANT);
break;
}
#endif
@@ -2450,25 +2379,25 @@ int32 Logic::fnFlash(int32 *params) {
// what colour?
switch (params[0]) {
case WHITE:
- _vm->_graphics->setPalette(0, 1, white, RDPAL_INSTANT);
+ _vm->_screen->setPalette(0, 1, white, RDPAL_INSTANT);
break;
case RED:
- _vm->_graphics->setPalette(0, 1, red, RDPAL_INSTANT);
+ _vm->_screen->setPalette(0, 1, red, RDPAL_INSTANT);
break;
case GREEN:
- _vm->_graphics->setPalette(0, 1, green, RDPAL_INSTANT);
+ _vm->_screen->setPalette(0, 1, green, RDPAL_INSTANT);
break;
case BLUE:
- _vm->_graphics->setPalette(0, 1, blue, RDPAL_INSTANT);
+ _vm->_screen->setPalette(0, 1, blue, RDPAL_INSTANT);
break;
}
// There used to be a busy-wait loop here, so I don't know how long
// the delay was meant to be. Probably doesn't matter much.
- _vm->_graphics->updateDisplay();
+ _vm->_screen->updateDisplay();
_vm->_system->delayMillis(250);
- _vm->_graphics->setPalette(0, 1, black, RDPAL_INSTANT);
+ _vm->_screen->setPalette(0, 1, black, RDPAL_INSTANT);
#endif
return IR_CONT;
@@ -2736,14 +2665,14 @@ int32 Logic::fnPlaySequence(int32 *params) {
// now clear the screen in case the Sequence was quitted (using ESC)
// rather than fading down to black
- _vm->_graphics->clearScene();
+ _vm->_screen->clearScene();
// zero the entire palette in case we're about to fade up!
byte pal[4 * 256];
memset(pal, 0, sizeof(pal));
- _vm->_graphics->setPalette(0, 256, pal, RDPAL_INSTANT);
+ _vm->_screen->setPalette(0, 256, pal, RDPAL_INSTANT);
debug(5, "fnPlaySequence FINISHED");
return IR_CONT;
@@ -2764,10 +2693,10 @@ int32 Logic::fnUnshadedSprite(int32 *params) {
int32 Logic::fnFadeUp(int32 *params) {
// params: none
- _vm->_graphics->waitForFade();
+ _vm->_screen->waitForFade();
- if (_vm->_graphics->getFadeStatus() == RDFADE_BLACK)
- _vm->_graphics->fadeUp();
+ if (_vm->_screen->getFadeStatus() == RDFADE_BLACK)
+ _vm->_screen->fadeUp();
return IR_CONT;
}
@@ -2785,7 +2714,7 @@ int32 Logic::fnDisplayMsg(int32 *params) {
// +2 to skip the encoded text number in the first 2 chars; 3 is
// duration in seconds
- _vm->displayMsg(_vm->fetchTextLine(_vm->_resman->openResource(text_res), local_text) + 2, 3);
+ _vm->_screen->displayMsg(_vm->fetchTextLine(_vm->_resman->openResource(text_res), local_text) + 2, 3);
_vm->_resman->closeResource(text_res);
return IR_CONT;
@@ -2793,14 +2722,9 @@ int32 Logic::fnDisplayMsg(int32 *params) {
int32 Logic::fnSetObjectHeld(int32 *params) {
// params: 0 luggage icon to set
+ uint32 res = (uint32) params[0];
- _vm->setLuggage(params[0]);
-
- _scriptVars[OBJECT_HELD] = params[0];
- _vm->_currentLuggageResource = params[0];
-
- // mode locked - no menu available
- _vm->_mouseModeLocked = true;
+ _vm->_mouse->setObjectHeld(res);
return IR_CONT;
}
@@ -2824,6 +2748,8 @@ int32 Logic::fnResetGlobals(int32 *params) {
// params: none
+ ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
+
int32 size;
uint32 *globals;
@@ -2846,7 +2772,7 @@ int32 Logic::fnResetGlobals(int32 *params) {
// - this is taken from fnInitBackground
// switch on scrolling (2 means first time on screen)
- _vm->_thisScreen.scroll_flag = 2;
+ screenInfo->scroll_flag = 2;
return IR_CONT;
}
@@ -2855,7 +2781,7 @@ int32 Logic::fnSetPalette(int32 *params) {
// params: 0 resource number of palette file, or 0 if it's to be
// the palette from the current screen
- _vm->setFullPalette(params[0]);
+ _vm->_screen->setFullPalette(params[0]);
return IR_CONT;
}
@@ -2866,13 +2792,7 @@ int32 Logic::fnSetPalette(int32 *params) {
int32 Logic::fnRegisterPointerText(int32 *params) {
// params: 0 local id of text line to use as pointer text
- assert(_vm->_curMouse < TOTAL_mouse_list);
-
- // current object id - used for checking pointer_text when mouse area
- // registered (in fnRegisterMouse and fnRegisterFrame)
-
- _vm->_mouseList[_vm->_curMouse].id = _scriptVars[ID];
- _vm->_mouseList[_vm->_curMouse].pointer_text = params[0];
+ _vm->_mouse->registerPointerText(params[0]);
return IR_CONT;
}
@@ -2940,18 +2860,9 @@ int32 Logic::fnCheckPlayerActivity(int32 *params) {
// params: 0 threshold delay in seconds, ie. what we want to
// check the actual delay against
- uint32 threshold = params[0] * 12; // in game cycles
-
- // if the actual delay is at or above the given threshold
- if (_vm->_playerActivityDelay >= threshold) {
- // reset activity delay counter, now that we've got a
- // positive check
-
- _vm->_playerActivityDelay = 0;
- _scriptVars[RESULT] = 1;
- } else
- _scriptVars[RESULT] = 0;
+ uint32 seconds = (uint32) params[0];
+ _vm->_mouse->checkPlayerActivity(seconds);
return IR_CONT;
}
@@ -2961,7 +2872,7 @@ int32 Logic::fnResetPlayerActivityDelay(int32 *params) {
// params: none
- _vm->_playerActivityDelay = 0;
+ _vm->_mouse->resetPlayerActivityDelay();
return IR_CONT;
}
@@ -3005,6 +2916,7 @@ struct CreditsLine {
#define CREDITS_LINE_SPACING 20
int32 Logic::fnPlayCredits(int32 *params) {
+ ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
uint32 loopingMusicId = _vm->_sound->getLoopingMusicId();
// This function just quits the game if this is the playable demo, ie.
@@ -3019,16 +2931,16 @@ int32 Logic::fnPlayCredits(int32 *params) {
// Prepare for the credits by fading down, stoping the music, etc.
- _vm->setMouse(0);
+ _vm->_mouse->setMouse(0);
_vm->_sound->muteFx(true);
_vm->_sound->muteSpeech(true);
- _vm->_graphics->waitForFade();
- _vm->_graphics->fadeDown();
- _vm->_graphics->waitForFade();
+ _vm->_screen->waitForFade();
+ _vm->_screen->fadeDown();
+ _vm->_screen->waitForFade();
- _vm->_graphics->closeMenuImmediately();
+ _vm->_mouse->closeMenuImmediately();
// There are three files which I believe are involved in showing the
// credits:
@@ -3093,7 +3005,7 @@ int32 Logic::fnPlayCredits(int32 *params) {
palette[14 * 4 + 3] = 0;
}
- _vm->_graphics->setPalette(0, 256, palette, RDPAL_INSTANT);
+ _vm->_screen->setPalette(0, 256, palette, RDPAL_INSTANT);
// Read the credits text
@@ -3206,8 +3118,8 @@ int32 Logic::fnPlayCredits(int32 *params) {
pars[1] = FX_SPOT;
fnPlayMusic(pars);
- _vm->_graphics->clearScene();
- _vm->_graphics->fadeUp(0);
+ _vm->_screen->clearScene();
+ _vm->_screen->fadeUp(0);
spriteInfo.scale = 0;
spriteInfo.scaledWidth = 0;
@@ -3232,7 +3144,7 @@ int32 Logic::fnPlayCredits(int32 *params) {
while (scrollPos < scrollSteps && !_vm->_quit) {
bool foundStartLine = false;
- _vm->_graphics->clearScene();
+ _vm->_screen->clearScene();
for (i = startLine; i < lineCount; i++) {
// Free any sprites that have scrolled off the screen
@@ -3284,23 +3196,23 @@ int32 Logic::fnPlayCredits(int32 *params) {
}
if (spriteInfo.data)
- _vm->_graphics->drawSprite(&spriteInfo);
+ _vm->_screen->drawSprite(&spriteInfo);
} else
break;
}
- _vm->_graphics->updateDisplay();
+ _vm->_screen->updateDisplay();
KeyboardEvent *ke = _vm->keyboardEvent();
if (ke && ke->keycode == 27) {
if (!abortCredits) {
abortCredits = true;
- _vm->_graphics->fadeDown();
+ _vm->_screen->fadeDown();
}
}
- if (abortCredits && _vm->_graphics->getFadeStatus() == RDFADE_BLACK)
+ if (abortCredits && _vm->_screen->getFadeStatus() == RDFADE_BLACK)
break;
_vm->sleepUntil(musicStart + (musicLength * scrollPos) / scrollSteps);
@@ -3325,7 +3237,7 @@ int32 Logic::fnPlayCredits(int32 *params) {
// wait for it to really happen.
while (_vm->_sound->musicTimeRemaining() && !_vm->_quit) {
- _vm->_graphics->updateDisplay(false);
+ _vm->_screen->updateDisplay(false);
_vm->_system->delayMillis(100);
}
}
@@ -3343,13 +3255,13 @@ int32 Logic::fnPlayCredits(int32 *params) {
} else
fnStopMusic(NULL);
- _vm->_thisScreen.new_palette = 99;
+ screenInfo->new_palette = 99;
- if (!_vm->_mouseStatus || _choosing)
- _vm->setMouse(NORMAL_MOUSE_ID);
+ if (!_vm->_mouse->getMouseStatus() || _choosing)
+ _vm->_mouse->setMouse(NORMAL_MOUSE_ID);
if (_scriptVars[DEAD])
- _vm->buildSystemMenu();
+ _vm->_mouse->buildSystemMenu();
return IR_CONT;
}
@@ -3357,24 +3269,24 @@ int32 Logic::fnPlayCredits(int32 *params) {
int32 Logic::fnSetScrollSpeedNormal(int32 *params) {
// params: none
- _vm->_scrollFraction = 16;
+ _vm->_screen->setScrollFraction(16);
return IR_CONT;
}
int32 Logic::fnSetScrollSpeedSlow(int32 *params) {
// params: none
- _vm->_scrollFraction = 32;
+ _vm->_screen->setScrollFraction(32);
return IR_CONT;
}
-// called from speech scripts to remove the chooser bar when it's not
+// Called from speech scripts to remove the chooser bar when it's not
// appropriate to keep it displayed
int32 Logic::fnRemoveChooser(int32 *params) {
// params: none
- _vm->_graphics->hideMenu(RDMENU_BOTTOM);
+ _vm->_mouse->hideMenu(RDMENU_BOTTOM);
return IR_CONT;
}
@@ -3413,34 +3325,27 @@ int32 Logic::fnRestoreGame(int32 *params) {
}
int32 Logic::fnRefreshInventory(int32 *params) {
- // called from 'menu_look_or_combine' script in 'menu_master' object
+ // Called from 'menu_look_or_combine' script in 'menu_master' object
// to update the menu to display a combined object while George runs
// voice-over. Note that 'object_held' must be set to the graphic of
// the combined object
// params: none
- // can reset this now
- _scriptVars[COMBINE_BASE] = 0;
-
- // so that the icon in 'object_held' is coloured while the rest are
- // grey
- _vm->_examiningMenuIcon = true;
- _vm->buildMenu();
- _vm->_examiningMenuIcon = false;
-
+ _vm->_mouse->refreshInventory();
return IR_CONT;
}
int32 Logic::fnChangeShadows(int32 *params) {
// params: none
+ ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
// if last screen was using a shading mask (see below)
- if (_vm->_thisScreen.mask_flag) {
- uint32 rv = _vm->_graphics->closeLightMask();
+ if (screenInfo->mask_flag) {
+ uint32 rv = _vm->_screen->closeLightMask();
if (rv)
error("Driver Error %.8x", rv);
- _vm->_thisScreen.mask_flag = false;
+ screenInfo->mask_flag = false;
}
return IR_CONT;
diff --git a/sword2/icons.cpp b/sword2/icons.cpp
index 7146743d8a..1182f0e220 100644
--- a/sword2/icons.cpp
+++ b/sword2/icons.cpp
@@ -24,12 +24,12 @@
#include "sword2/interpreter.h"
#include "sword2/logic.h"
#include "sword2/memory.h"
+#include "sword2/mouse.h"
#include "sword2/resman.h"
-#include "sword2/driver/d_draw.h"
namespace Sword2 {
-void Sword2Engine::addMenuObject(MenuObject *obj) {
+void Mouse::addMenuObject(MenuObject *obj) {
assert(_totalTemp < TOTAL_engine_pockets);
memcpy(&_tempList[_totalTemp], obj, sizeof(MenuObject));
_totalTemp++;
@@ -39,7 +39,7 @@ void Sword2Engine::addMenuObject(MenuObject *obj) {
* Create and start the inventory (bottom) menu
*/
-void Sword2Engine::buildMenu(void) {
+void Mouse::buildMenu() {
uint32 i, j;
// Clear the temporary inventory list, since we are going to build a
@@ -54,9 +54,9 @@ void Sword2Engine::buildMenu(void) {
// register all carried menu objects.
uint32 null_pc = 0;
- char *menuScript = (char *) _resman->openResource(MENU_MASTER_OBJECT);
- _logic->runScript(menuScript, menuScript, &null_pc);
- _resman->closeResource(MENU_MASTER_OBJECT);
+ char *menuScript = (char *) _vm->_resman->openResource(MENU_MASTER_OBJECT);
+ _vm->_logic->runScript(menuScript, menuScript, &null_pc);
+ _vm->_resman->closeResource(MENU_MASTER_OBJECT);
// Create a new master list based on the old master inventory list and
// the new temporary inventory list. The purpose of all this is, as
@@ -136,7 +136,7 @@ void Sword2Engine::buildMenu(void) {
icon_coloured = (res != Logic::_scriptVars[OBJECT_HELD]);
}
- icon = _resman->openResource(res) + sizeof(StandardHeader);
+ icon = _vm->_resman->openResource(res) + sizeof(StandardHeader);
// The coloured icon is stored directly after the
// greyed out one.
@@ -145,20 +145,20 @@ void Sword2Engine::buildMenu(void) {
icon += (RDMENU_ICONWIDE * RDMENU_ICONDEEP);
}
- _graphics->setMenuIcon(RDMENU_BOTTOM, i, icon);
+ setMenuIcon(RDMENU_BOTTOM, i, icon);
if (res)
- _resman->closeResource(res);
+ _vm->_resman->closeResource(res);
}
- _graphics->showMenu(RDMENU_BOTTOM);
+ showMenu(RDMENU_BOTTOM);
}
/**
* Build a fresh system (top) menu.
*/
-void Sword2Engine::buildSystemMenu(void) {
+void Mouse::buildSystemMenu() {
uint32 icon_list[5] = {
OPTIONS_ICON,
QUIT_ICON,
@@ -171,7 +171,7 @@ void Sword2Engine::buildSystemMenu(void) {
// rest will grey out.
for (int i = 0; i < ARRAYSIZE(icon_list); i++) {
- byte *icon = _resman->openResource(icon_list[i]) + sizeof(StandardHeader);
+ byte *icon = _vm->_resman->openResource(icon_list[i]) + sizeof(StandardHeader);
// The only case when an icon is grayed is when the player
// is dead. Then SAVE is not available.
@@ -179,11 +179,11 @@ void Sword2Engine::buildSystemMenu(void) {
if (!Logic::_scriptVars[DEAD] || icon_list[i] != SAVE_ICON)
icon += (RDMENU_ICONWIDE * RDMENU_ICONDEEP);
- _graphics->setMenuIcon(RDMENU_TOP, i, icon);
- _resman->closeResource(icon_list[i]);
+ setMenuIcon(RDMENU_TOP, i, icon);
+ _vm->_resman->closeResource(icon_list[i]);
}
- _graphics->showMenu(RDMENU_TOP);
+ showMenu(RDMENU_TOP);
}
} // End of namespace Sword2
diff --git a/sword2/layers.cpp b/sword2/layers.cpp
index 86debbd8c3..79b8cd9743 100644
--- a/sword2/layers.cpp
+++ b/sword2/layers.cpp
@@ -28,11 +28,9 @@
#include "common/stdafx.h"
#include "sword2/sword2.h"
-#include "sword2/interpreter.h"
#include "sword2/logic.h"
#include "sword2/resman.h"
#include "sword2/sound.h"
-#include "sword2/driver/d_draw.h"
namespace Sword2 {
@@ -42,30 +40,30 @@ namespace Sword2 {
* @param new_palette 1 for new palette, otherwise 0
*/
-int32 Sword2Engine::initBackground(int32 res, int32 new_palette) {
+void Screen::initBackground(int32 res, int32 new_palette) {
byte buf[NAME_LEN];
int i;
assert(res);
// The resources age every time a new room is entered.
- _resman->passTime();
- _resman->expireOldResources();
+ _vm->_resman->passTime();
+ _vm->_resman->expireOldResources();
- _sound->clearFxQueue();
- _graphics->waitForFade();
+ _vm->_sound->clearFxQueue();
+ waitForFade();
- debug(1, "CHANGED TO LOCATION \"%s\"", fetchObjectName(res, buf));
+ debug(1, "CHANGED TO LOCATION \"%s\"", _vm->fetchObjectName(res, buf));
// if last screen was using a shading mask (see below)
if (_thisScreen.mask_flag) {
- if (_graphics->closeLightMask() != RD_OK)
+ if (closeLightMask() != RD_OK)
error("Could not close light mask");
}
// Close the previous screen, if one is open
if (_thisScreen.background_layer_id)
- _graphics->closeBackgroundLayer();
+ closeBackgroundLayer();
_thisScreen.background_layer_id = res;
_thisScreen.new_palette = new_palette;
@@ -74,8 +72,8 @@ int32 Sword2Engine::initBackground(int32 res, int32 new_palette) {
// info/and set them up at the beginning of the sort list - why do it
// each cycle
- byte *file = _resman->openResource(_thisScreen.background_layer_id);
- ScreenHeader *screen_head = fetchScreenHeader(file);
+ byte *file = _vm->_resman->openResource(_thisScreen.background_layer_id);
+ ScreenHeader *screen_head = _vm->fetchScreenHeader(file);
// set number of special sort layers
_thisScreen.number_of_layers = screen_head->noLayers;
@@ -85,12 +83,12 @@ int32 Sword2Engine::initBackground(int32 res, int32 new_palette) {
debug(2, "layers=%d width=%d depth=%d", screen_head->noLayers, screen_head->width, screen_head->height);
// initialise the driver back buffer
- _graphics->setLocationMetrics(screen_head->width, screen_head->height);
+ setLocationMetrics(screen_head->width, screen_head->height);
for (i = 0; i < screen_head->noLayers; i++) {
debug(3, "init layer %d", i);
- LayerHeader *layer = fetchLayerHeader(file, i);
+ LayerHeader *layer = _vm->fetchLayerHeader(file, i);
// Add the layer to the sort list. We only provide just enough
// information so that it's clear that it's a layer, and where
@@ -104,7 +102,7 @@ int32 Sword2Engine::initBackground(int32 res, int32 new_palette) {
_thisScreen.scroll_offset_x = 0;
_thisScreen.scroll_offset_y = 0;
- if (screen_head->width > _graphics->_screenWide || screen_head->height > _graphics->_screenDeep) {
+ if (screen_head->width > _screenWide || screen_head->height > _screenDeep) {
// The layer is larger than the physical screen. Switch on
// scrolling. (2 means first time on screen)
_thisScreen.scroll_flag = 2;
@@ -115,14 +113,14 @@ int32 Sword2Engine::initBackground(int32 res, int32 new_palette) {
// Calculate the maximum scroll offsets to prevent scrolling
// off the edge. The minimum offsets are both 0.
- _thisScreen.max_scroll_offset_x = screen_head->width - _graphics->_screenWide;
- _thisScreen.max_scroll_offset_y = screen_head->height - (_graphics->_screenDeep - (RDMENU_MENUDEEP * 2));
+ _thisScreen.max_scroll_offset_x = screen_head->width - _screenWide;
+ _thisScreen.max_scroll_offset_y = screen_head->height - (_screenDeep - (RDMENU_MENUDEEP * 2));
} else {
// The later fits on the phyiscal screen. Switch off scrolling.
_thisScreen.scroll_flag = 0;
}
- _graphics->resetRenderEngine();
+ resetRenderEngine();
// These are the physical screen coords where the system will try to
// maintain George's actual feet coords.
@@ -146,10 +144,10 @@ int32 Sword2Engine::initBackground(int32 res, int32 new_palette) {
spriteInfo.scaledHeight = 0;
spriteInfo.type = 0;
spriteInfo.blend = 0;
- spriteInfo.data = fetchShadingMask(file);
+ spriteInfo.data = _vm->fetchShadingMask(file);
spriteInfo.colourTable = 0;
- if (_graphics->openLightMask(&spriteInfo) != RD_OK)
+ if (openLightMask(&spriteInfo) != RD_OK)
error("Could not open light mask");
// so we know to close it later! (see above)
@@ -163,26 +161,25 @@ int32 Sword2Engine::initBackground(int32 res, int32 new_palette) {
for (i = 0; i < 2; i++) {
if (screenLayerTable->bg_parallax[i])
- _graphics->initialiseBackgroundLayer(fetchBackgroundParallaxLayer(file, i));
+ initialiseBackgroundLayer(_vm->fetchBackgroundParallaxLayer(file, i));
else
- _graphics->initialiseBackgroundLayer(NULL);
+ initialiseBackgroundLayer(NULL);
}
// Normal backround layer
- _graphics->initialiseBackgroundLayer(fetchBackgroundLayer(file));
+ initialiseBackgroundLayer(_vm->fetchBackgroundLayer(file));
// Foreground parallax layers
for (i = 0; i < 2; i++) {
if (screenLayerTable->fg_parallax[i])
- _graphics->initialiseBackgroundLayer(fetchForegroundParallaxLayer(file, i));
+ initialiseBackgroundLayer(_vm->fetchForegroundParallaxLayer(file, i));
else
- _graphics->initialiseBackgroundLayer(NULL);
+ initialiseBackgroundLayer(NULL);
}
- _resman->closeResource(_thisScreen.background_layer_id);
- return IR_CONT;
+ _vm->_resman->closeResource(_thisScreen.background_layer_id);
}
} // End of namespace Sword2
diff --git a/sword2/layers.h b/sword2/layers.h
index 58edce52ce..3ffdf668b9 100644
--- a/sword2/layers.h
+++ b/sword2/layers.h
@@ -23,30 +23,6 @@
namespace Sword2 {
-struct ScreenInfo {
- uint16 scroll_offset_x; // Position x
- uint16 scroll_offset_y; // Position y
- uint16 max_scroll_offset_x; // Calc'ed in fnInitBackground
- uint16 max_scroll_offset_y;
- int16 player_feet_x; // Feet coordinates to use - cant just
- int16 player_feet_y; // fetch the player compact anymore
- int16 feet_x; // Special offset-to-player position -
- int16 feet_y; // tweek as desired - always set in
- // screen manager object startup
- uint16 screen_wide; // Size of background layer - hence
- uint16 screen_deep; // size of back buffer itself (Paul
- // actually malloc's it)
- uint32 background_layer_id; // Id of the normal background layer
- // from the header of the main
- // background layer
- uint16 number_of_layers;
- uint8 new_palette; // Set to non zero to start the
- // palette held within layer file
- // fading up after a build_display
- uint8 scroll_flag; // Scroll mode 0 off 1 on
- bool mask_flag; // Using shading mask
-};
-
} // End of namespace Sword2
#endif
diff --git a/sword2/logic.cpp b/sword2/logic.cpp
index db739c348f..2472c7f726 100644
--- a/sword2/logic.cpp
+++ b/sword2/logic.cpp
@@ -35,11 +35,10 @@
namespace Sword2 {
Logic::Logic(Sword2Engine *vm) :
- _vm(vm), _kills(0), _smackerLeadOut(0), _sequenceTextLines(0),
- _speechTime(0), _animId(0), _speechAnimType(0), _leftClickDelay(0),
- _rightClickDelay(0), _defaultResponseId(0), _officialTextNumber(0),
- _speechTextBlocNo(0),
- _choosing(false) {
+ _vm(vm), _kills(0), _smackerLeadIn(0), _smackerLeadOut(0),
+ _sequenceTextLines(0), _speechTime(0), _animId(0), _speechAnimType(0),
+ _leftClickDelay(0), _rightClickDelay(0), _defaultResponseId(0),
+ _officialTextNumber(0), _speechTextBlocNo(0), _choosing(false) {
_scriptVars = NULL;
memset(_subjectList, 0, sizeof(_subjectList));
memset(_eventList, 0, sizeof(_eventList));
diff --git a/sword2/logic.h b/sword2/logic.h
index f535ac4581..a75d93a4b2 100644
--- a/sword2/logic.h
+++ b/sword2/logic.h
@@ -27,6 +27,8 @@
namespace Sword2 {
+struct MovieTextObject;
+
#define MAX_events 10
// There won't be many, will there? Probably 2 at most i reckon
diff --git a/sword2/maketext.cpp b/sword2/maketext.cpp
index 8fec778383..aefccb4d86 100644
--- a/sword2/maketext.cpp
+++ b/sword2/maketext.cpp
@@ -43,7 +43,6 @@
#include "sword2/logic.h"
#include "sword2/maketext.h"
#include "sword2/resman.h"
-#include "sword2/driver/d_draw.h"
namespace Sword2 {
@@ -476,7 +475,7 @@ void FontRenderer::printTextBlocs(void) {
spriteInfo.data = _blocList[i].text_mem + sizeof(FrameHeader);
spriteInfo.colourTable = 0;
- uint32 rv = _vm->_graphics->drawSprite(&spriteInfo);
+ uint32 rv = _vm->_screen->drawSprite(&spriteInfo);
if (rv)
error("Driver Error %.8x in printTextBlocs", rv);
}
diff --git a/sword2/mouse.cpp b/sword2/mouse.cpp
index c0062ba635..be8953c254 100644
--- a/sword2/mouse.cpp
+++ b/sword2/mouse.cpp
@@ -27,13 +27,13 @@
#include "sword2/logic.h"
#include "sword2/maketext.h"
#include "sword2/memory.h"
+#include "sword2/mouse.h"
#include "sword2/resman.h"
#include "sword2/sound.h"
-#include "sword2/driver/d_draw.h"
namespace Sword2 {
-// pointer resource id's
+// Pointer resource id's
enum {
CROSHAIR = 18,
@@ -55,19 +55,132 @@ enum {
USE = 3100
};
+Mouse::Mouse(Sword2Engine *vm) {
+ _vm = vm;
+
+ setPos(0, 0);
+
+ _mouseTouching = 0;
+ _oldMouseTouching = 0;
+ _menuSelectedPos = 0;
+ _examiningMenuIcon = false;
+ _mousePointerRes = 0;
+ _mouseMode = 0;
+ _mouseStatus = false;
+ _mouseModeLocked = false;
+ _currentLuggageResource = 0;
+ _oldButton = 0;
+ _buttonClick = 0;
+ _pointerTextBlocNo = 0;
+ _playerActivityDelay = 0;
+ _realLuggageItem = 0;
+
+ _mouseSprite = NULL;
+ _mouseAnim = NULL;
+ _luggageAnim = NULL;
+
+ // For the menus
+ _totalTemp = 0;
+ memset(_tempList, 0, sizeof(_tempList));
+
+ _totalMasters = 0;
+ memset(_masterMenuList, 0, sizeof(_masterMenuList));
+ memset(_mouseList, 0, sizeof(_mouseList));
+
+ _iconCount = 0;
+
+ for (int i = 0; i < 2; i++) {
+ for (int j = 0; j < RDMENU_MAXPOCKETS; j++) {
+ _icons[i][j] = NULL;
+ _pocketStatus[i][j] = 0;
+ }
+
+ _menuStatus[i] = RDMENU_HIDDEN;
+ }
+}
+
+Mouse::~Mouse() {
+ free(_mouseAnim);
+ free(_luggageAnim);
+ for (int i = 0; i < 2; i++)
+ for (int j = 0; j < RDMENU_MAXPOCKETS; j++)
+ free(_icons[i][j]);
+}
+
+void Mouse::getPos(int &x, int &y) {
+ x = _pos.x;
+ y = _pos.y;
+}
+
+void Mouse::setPos(int x, int y) {
+ _pos.x = x;
+ _pos.y = y;
+}
+
/**
* Call at beginning of game loop
*/
-void Sword2Engine::resetMouseList(void) {
+void Mouse::resetMouseList() {
_curMouse = 1;
}
+void Mouse::registerMouse(ObjectMouse *ob_mouse, BuildUnit *build_unit) {
+ if (!ob_mouse->pointer)
+ return;
+
+ assert(_curMouse < TOTAL_mouse_list);
+
+ if (build_unit) {
+ _mouseList[_curMouse].x1 = build_unit->x;
+ _mouseList[_curMouse].y1 = build_unit->y;
+ _mouseList[_curMouse].x2 = build_unit->x + build_unit->scaled_width;
+ _mouseList[_curMouse].y2 = build_unit->y + build_unit->scaled_height;
+ } else {
+ _mouseList[_curMouse].x1 = ob_mouse->x1;
+ _mouseList[_curMouse].y1 = ob_mouse->y1;
+ _mouseList[_curMouse].x2 = ob_mouse->x2;
+ _mouseList[_curMouse].y2 = ob_mouse->y2;
+ }
+
+ _mouseList[_curMouse].priority = ob_mouse->priority;
+ _mouseList[_curMouse].pointer = ob_mouse->pointer;
+
+ // Check if pointer text field is set due to previous object using this
+ // slot (ie. not correct for this one)
+
+ // If 'pointer_text' field is set, but the 'id' field isn't same is
+ // current id then we don't want this "left over" pointer text
+
+ if (_mouseList[_curMouse].pointer_text && _mouseList[_curMouse].id != (int32) Logic::_scriptVars[ID])
+ _mouseList[_curMouse].pointer_text = 0;
+
+ // Get id from system variable 'id' which is correct for current object
+ _mouseList[_curMouse].id = Logic::_scriptVars[ID];
+
+ // Not using sprite as detection mask - this is only done from
+ // fnRegisterFrame()
+ _mouseList[_curMouse].anim_resource = 0;
+ _mouseList[_curMouse].anim_pc = 0;
+
+ _curMouse++;
+}
+
+void Mouse::registerPointerText(int32 text_id) {
+ assert(_curMouse < TOTAL_mouse_list);
+
+ // current object id - used for checking pointer_text when mouse area
+ // registered (in fnRegisterMouse and fnRegisterFrame)
+
+ _mouseList[_curMouse].id = Logic::_scriptVars[ID];
+ _mouseList[_curMouse].pointer_text = text_id;
+}
+
/**
* This function is called every game cycle.
*/
-void Sword2Engine::mouseEngine(void) {
+void Mouse::mouseEngine() {
monitorPlayerActivity();
clearPointerText();
@@ -109,7 +222,7 @@ void Sword2Engine::mouseEngine(void) {
systemMenuMouse();
break;
case MOUSE_holding:
- if (_mouseY < 400) {
+ if (_pos.y < 400) {
_mouseMode = MOUSE_normal;
debug(5, " releasing");
}
@@ -120,7 +233,7 @@ void Sword2Engine::mouseEngine(void) {
}
#if RIGHT_CLICK_CLEARS_LUGGAGE
-bool Sword2Engine::heldIsInInventory(void) {
+bool Mouse::heldIsInInventory() {
for (uint i = 0; i < _totalMasters; i++) {
if ((uint32) _masterMenuList[i].icon_resource == Logic::_scriptVars[OBJECT_HELD])
return true;
@@ -129,17 +242,17 @@ bool Sword2Engine::heldIsInInventory(void) {
}
#endif
-int Sword2Engine::menuClick(int menu_items) {
- if (_mouseX < RDMENU_ICONSTART)
+int Mouse::menuClick(int menu_items) {
+ if (_pos.x < RDMENU_ICONSTART)
return -1;
- if (_mouseX > RDMENU_ICONSTART + menu_items * (RDMENU_ICONWIDE + RDMENU_ICONSPACING) - RDMENU_ICONSPACING)
+ if (_pos.x > RDMENU_ICONSTART + menu_items * (RDMENU_ICONWIDE + RDMENU_ICONSPACING) - RDMENU_ICONSPACING)
return -1;
- return (_mouseX - RDMENU_ICONSTART) / (RDMENU_ICONWIDE + RDMENU_ICONSPACING);
+ return (_pos.x - RDMENU_ICONSTART) / (RDMENU_ICONWIDE + RDMENU_ICONSPACING);
}
-void Sword2Engine::systemMenuMouse(void) {
+void Mouse::systemMenuMouse(void) {
uint32 safe_looping_music_id;
MouseEvent *me;
int hit;
@@ -156,20 +269,20 @@ void Sword2Engine::systemMenuMouse(void) {
// If the mouse is moved off the menu, close it. Unless the player is
// dead, in which case the menu should always be visible.
- if (_mouseY > 0 && !Logic::_scriptVars[DEAD]) {
+ if (_pos.y > 0 && !Logic::_scriptVars[DEAD]) {
_mouseMode = MOUSE_normal;
- _graphics->hideMenu(RDMENU_TOP);
+ hideMenu(RDMENU_TOP);
return;
}
// Check if the user left-clicks anywhere in the menu area.
- me = mouseEvent();
+ me = _vm->mouseEvent();
if (!me || !(me->buttons & RD_LEFTBUTTONDOWN))
return;
- if (_mouseY > 0)
+ if (_pos.y > 0)
return;
hit = menuClick(ARRAYSIZE(icon_list));
@@ -186,46 +299,46 @@ void Sword2Engine::systemMenuMouse(void) {
for (int i = 0; i < ARRAYSIZE(icon_list); i++) {
if (i != hit) {
- icon = _resman->openResource(icon_list[i]) + sizeof(StandardHeader);
- _graphics->setMenuIcon(RDMENU_TOP, i, icon);
- _resman->closeResource(icon_list[i]);
+ icon = _vm->_resman->openResource(icon_list[i]) + sizeof(StandardHeader);
+ setMenuIcon(RDMENU_TOP, i, icon);
+ _vm->_resman->closeResource(icon_list[i]);
}
}
- _sound->pauseFx();
+ _vm->_sound->pauseFx();
// NB. Need to keep a safe copy of '_loopingMusicId' for savegame & for
// playing when returning from control panels because control panel
// music will overwrite it!
- safe_looping_music_id = _sound->getLoopingMusicId();
+ safe_looping_music_id = _vm->_sound->getLoopingMusicId();
pars[0] = 221;
pars[1] = FX_LOOP;
- _logic->fnPlayMusic(pars);
+ _vm->_logic->fnPlayMusic(pars);
// HACK: Restore proper looping_music_id
- _sound->setLoopingMusicId(safe_looping_music_id);
+ _vm->_sound->setLoopingMusicId(safe_looping_music_id);
- _graphics->processMenu();
+ processMenu();
// call the relevant screen
switch (hit) {
case 0:
- _gui->optionControl();
+ _vm->_gui->optionControl();
break;
case 1:
- _gui->quitControl();
+ _vm->_gui->quitControl();
break;
case 2:
- _gui->saveControl();
+ _vm->_gui->saveControl();
break;
case 3:
- _gui->restoreControl();
+ _vm->_gui->restoreControl();
break;
case 4:
- _gui->restartControl();
+ _vm->_gui->restartControl();
break;
}
@@ -233,7 +346,7 @@ void Sword2Engine::systemMenuMouse(void) {
if (!Logic::_scriptVars[DEAD]) {
_mouseMode = MOUSE_normal;
- _graphics->hideMenu(RDMENU_TOP);
+ hideMenu(RDMENU_TOP);
} else {
setMouse(NORMAL_MOUSE_ID);
buildSystemMenu();
@@ -241,35 +354,37 @@ void Sword2Engine::systemMenuMouse(void) {
// Back to the game again
- _graphics->processMenu();
+ processMenu();
// Reset game palette, but not after a successful restore or restart!
// See RestoreFromBuffer() in save_rest.cpp
- if (_thisScreen.new_palette != 99) {
+ ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
+
+ if (screenInfo->new_palette != 99) {
// 0 means put back game screen palette; see build_display.cpp
- setFullPalette(0);
+ _vm->_screen->setFullPalette(0);
// Stop the engine fading in the restored screens palette
- _thisScreen.new_palette = 0;
+ screenInfo->new_palette = 0;
} else
- _thisScreen.new_palette = 1;
+ screenInfo->new_palette = 1;
- _sound->unpauseFx();
+ _vm->_sound->unpauseFx();
// If there was looping music before coming into the control panels
// then restart it! NB. If a game has been restored the music will be
// restarted twice, but this shouldn't cause any harm.
- if (_sound->getLoopingMusicId()) {
- pars[0] = _sound->getLoopingMusicId();
+ if (_vm->_sound->getLoopingMusicId()) {
+ pars[0] = _vm->_sound->getLoopingMusicId();
pars[1] = FX_LOOP;
- _logic->fnPlayMusic(pars);
+ _vm->_logic->fnPlayMusic(pars);
} else
- _logic->fnStopMusic(NULL);
+ _vm->_logic->fnStopMusic(NULL);
}
-void Sword2Engine::dragMouse(void) {
+void Mouse::dragMouse(void) {
byte buf1[NAME_LEN], buf2[NAME_LEN];
MouseEvent *me;
int hit;
@@ -278,9 +393,9 @@ void Sword2Engine::dragMouse(void) {
// objects in the scene, so if the mouse moves off the inventory menu,
// then close it.
- if (_mouseY < 400) {
+ if (_pos.y < 400) {
_mouseMode = MOUSE_normal;
- _graphics->hideMenu(RDMENU_BOTTOM);
+ hideMenu(RDMENU_BOTTOM);
return;
}
@@ -290,7 +405,7 @@ void Sword2Engine::dragMouse(void) {
// Now do the normal click stuff
- me = mouseEvent();
+ me = _vm->mouseEvent();
if (!me)
return;
@@ -327,24 +442,25 @@ void Sword2Engine::dragMouse(void) {
Logic::_scriptVars[RIGHT_BUTTON] = 0;
// These might be required by the action script about to be run
+ ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
- Logic::_scriptVars[MOUSE_X] = _mouseX + _thisScreen.scroll_offset_x;
- Logic::_scriptVars[MOUSE_Y] = _mouseY + _thisScreen.scroll_offset_y;
+ Logic::_scriptVars[MOUSE_X] = _pos.x + screenInfo->scroll_offset_x;
+ Logic::_scriptVars[MOUSE_Y] = _pos.y + screenInfo->scroll_offset_y;
// For scripts to know what's been clicked. First used for
// 'room_13_turning_script' in object 'biscuits_13'
Logic::_scriptVars[CLICKED_ID] = _mouseTouching;
- _logic->setPlayerActionEvent(CUR_PLAYER_ID, _mouseTouching);
+ _vm->_logic->setPlayerActionEvent(CUR_PLAYER_ID, _mouseTouching);
debug(2, "Used \"%s\" on \"%s\"",
- fetchObjectName(Logic::_scriptVars[OBJECT_HELD], buf1),
- fetchObjectName(Logic::_scriptVars[CLICKED_ID], buf2));
+ _vm->fetchObjectName(Logic::_scriptVars[OBJECT_HELD], buf1),
+ _vm->fetchObjectName(Logic::_scriptVars[CLICKED_ID], buf2));
// Hide menu - back to normal menu mode
- _graphics->hideMenu(RDMENU_BOTTOM);
+ hideMenu(RDMENU_BOTTOM);
_mouseMode = MOUSE_normal;
return;
@@ -372,16 +488,16 @@ void Sword2Engine::dragMouse(void) {
// Otherwise, combine the two icons
Logic::_scriptVars[COMBINE_BASE] = _masterMenuList[hit].icon_resource;
- _logic->setPlayerActionEvent(CUR_PLAYER_ID, MENU_MASTER_OBJECT);
+ _vm->_logic->setPlayerActionEvent(CUR_PLAYER_ID, MENU_MASTER_OBJECT);
// Turn off mouse now, to prevent player trying to click
// elsewhere BUT leave the bottom menu open
- noHuman();
+ hideMouse();
debug(2, "Used \"%s\" on \"%s\"",
- fetchObjectName(Logic::_scriptVars[OBJECT_HELD], buf1),
- fetchObjectName(Logic::_scriptVars[COMBINE_BASE], buf2));
+ _vm->fetchObjectName(Logic::_scriptVars[OBJECT_HELD], buf1),
+ _vm->fetchObjectName(Logic::_scriptVars[COMBINE_BASE], buf2));
}
// Refresh the menu
@@ -389,20 +505,20 @@ void Sword2Engine::dragMouse(void) {
buildMenu();
}
-void Sword2Engine::menuMouse(void) {
+void Mouse::menuMouse() {
byte buf[NAME_LEN];
MouseEvent *me;
int hit;
// If the mouse is moved off the menu, close it.
- if (_mouseY < 400) {
+ if (_pos.y < 400) {
_mouseMode = MOUSE_normal;
- _graphics->hideMenu(RDMENU_BOTTOM);
+ hideMenu(RDMENU_BOTTOM);
return;
}
- me = mouseEvent();
+ me = _vm->mouseEvent();
if (!me)
return;
@@ -426,7 +542,7 @@ void Sword2Engine::menuMouse(void) {
Logic::_scriptVars[EXIT_CLICK_ID] = 0;
- _logic->setPlayerActionEvent(CUR_PLAYER_ID, MENU_MASTER_OBJECT);
+ _vm->_logic->setPlayerActionEvent(CUR_PLAYER_ID, MENU_MASTER_OBJECT);
// Refresh the menu
@@ -435,10 +551,10 @@ void Sword2Engine::menuMouse(void) {
// Turn off mouse now, to prevent player trying to click
// elsewhere BUT leave the bottom menu open
- noHuman();
+ hideMouse();
debug(2, "Right-click on \"%s\" icon",
- fetchObjectName(Logic::_scriptVars[OBJECT_HELD], buf));
+ _vm->fetchObjectName(Logic::_scriptVars[OBJECT_HELD], buf));
return;
}
@@ -466,11 +582,11 @@ void Sword2Engine::menuMouse(void) {
setLuggage(_masterMenuList[hit].luggage_resource);
debug(2, "Left-clicked on \"%s\" icon - switch to drag mode",
- fetchObjectName(Logic::_scriptVars[OBJECT_HELD], buf));
+ _vm->fetchObjectName(Logic::_scriptVars[OBJECT_HELD], buf));
}
}
-void Sword2Engine::normalMouse(void) {
+void Mouse::normalMouse(void) {
// The gane is playing and none of the menus are activated - but, we
// need to check if a menu is to start. Note, won't have luggage
@@ -480,7 +596,7 @@ void Sword2Engine::normalMouse(void) {
// big-object menu lock situation, of if the player is dragging an
// object.
- if (_mouseY < 0 && !_mouseModeLocked && !Logic::_scriptVars[OBJECT_HELD]) {
+ if (_pos.y < 0 && !_mouseModeLocked && !Logic::_scriptVars[OBJECT_HELD]) {
_mouseMode = MOUSE_system_menu;
if (_mouseTouching) {
@@ -499,7 +615,7 @@ void Sword2Engine::normalMouse(void) {
// Check if the cursor has moved onto the inventory menu area. No
// inventory in big-object menu lock situation,
- if (_mouseY > 399 && !_mouseModeLocked) {
+ if (_pos.y > 399 && !_mouseModeLocked) {
// If an object is being held, i.e. if the mouse cursor has a
// luggage, go to drag mode instead of menu mode, but the menu
// is still opened.
@@ -532,7 +648,7 @@ void Sword2Engine::normalMouse(void) {
mouseOnOff();
- me = mouseEvent();
+ me = _vm->mouseEvent();
if (!me)
return;
@@ -542,27 +658,29 @@ void Sword2Engine::normalMouse(void) {
// For debugging. We can draw a rectangle on the screen and see its
// coordinates. This was probably used to help defining hit areas.
- if (_debugger->_definingRectangles) {
- if (_debugger->_draggingRectangle == 0) {
+ if (_vm->_debugger->_definingRectangles) {
+ ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
+
+ if (_vm->_debugger->_draggingRectangle == 0) {
// Not yet dragging a rectangle, so need click to start
if (button_down) {
// set both (x1,y1) and (x2,y2) to this point
- _debugger->_rectX1 = _debugger->_rectX2 = (uint32) _mouseX + _thisScreen.scroll_offset_x;
- _debugger->_rectY1 = _debugger->_rectY2 = (uint32) _mouseY + _thisScreen.scroll_offset_y;
- _debugger->_draggingRectangle = 1;
+ _vm->_debugger->_rectX1 = _vm->_debugger->_rectX2 = (uint32) _pos.x + screenInfo->scroll_offset_x;
+ _vm->_debugger->_rectY1 = _vm->_debugger->_rectY2 = (uint32) _pos.y + screenInfo->scroll_offset_y;
+ _vm->_debugger->_draggingRectangle = 1;
}
- } else if (_debugger->_draggingRectangle == 1) {
+ } else if (_vm->_debugger->_draggingRectangle == 1) {
// currently dragging a rectangle - click means reset
if (button_down) {
// lock rectangle, so you can let go of mouse
// to type in the coords
- _debugger->_draggingRectangle = 2;
+ _vm->_debugger->_draggingRectangle = 2;
} else {
// drag rectangle
- _debugger->_rectX2 = (uint32) _mouseX + _thisScreen.scroll_offset_x;
- _debugger->_rectY2 = (uint32) _mouseY + _thisScreen.scroll_offset_y;
+ _vm->_debugger->_rectX2 = (uint32) _pos.x + screenInfo->scroll_offset_x;
+ _vm->_debugger->_rectY2 = (uint32) _pos.y + screenInfo->scroll_offset_y;
}
} else {
// currently locked to avoid knocking out of place
@@ -570,7 +688,7 @@ void Sword2Engine::normalMouse(void) {
if (button_down) {
// click means reset - back to start again
- _debugger->_draggingRectangle = 0;
+ _vm->_debugger->_draggingRectangle = 0;
}
}
@@ -622,17 +740,18 @@ void Sword2Engine::normalMouse(void) {
}
// These might be required by the action script about to be run
+ ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
- Logic::_scriptVars[MOUSE_X] = _mouseX + _thisScreen.scroll_offset_x;
- Logic::_scriptVars[MOUSE_Y] = _mouseY + _thisScreen.scroll_offset_y;
+ Logic::_scriptVars[MOUSE_X] = _pos.x + screenInfo->scroll_offset_x;
+ Logic::_scriptVars[MOUSE_Y] = _pos.y + screenInfo->scroll_offset_y;
if (_mouseTouching == Logic::_scriptVars[EXIT_CLICK_ID] && (me->buttons & RD_LEFTBUTTONDOWN)) {
// It's the exit double click situation. Let the existing
// interaction continue and start fading down. Switch the human
// off too
- _logic->fnNoHuman(NULL);
- _logic->fnFadeDown(NULL);
+ noHuman();
+ _vm->_logic->fnFadeDown(NULL);
// Tell the walker
@@ -669,24 +788,24 @@ void Sword2Engine::normalMouse(void) {
if (_mouseTouching == 2773 && !Logic::_scriptVars[LEFT_BUTTON]) {
warning("Working around elevator script bug");
} else
- _logic->setPlayerActionEvent(CUR_PLAYER_ID, _mouseTouching);
+ _vm->_logic->setPlayerActionEvent(CUR_PLAYER_ID, _mouseTouching);
byte buf1[NAME_LEN], buf2[NAME_LEN];
if (Logic::_scriptVars[OBJECT_HELD])
debug(2, "Used \"%s\" on \"%s\"",
- fetchObjectName(Logic::_scriptVars[OBJECT_HELD], buf1),
- fetchObjectName(Logic::_scriptVars[CLICKED_ID], buf2));
+ _vm->fetchObjectName(Logic::_scriptVars[OBJECT_HELD], buf1),
+ _vm->fetchObjectName(Logic::_scriptVars[CLICKED_ID], buf2));
else if (Logic::_scriptVars[LEFT_BUTTON])
debug(2, "Left-clicked on \"%s\"",
- fetchObjectName(Logic::_scriptVars[CLICKED_ID], buf1));
+ _vm->fetchObjectName(Logic::_scriptVars[CLICKED_ID], buf1));
else // RIGHT BUTTON
debug(2, "Right-clicked on \"%s\"",
- fetchObjectName(Logic::_scriptVars[CLICKED_ID], buf1));
+ _vm->fetchObjectName(Logic::_scriptVars[CLICKED_ID], buf1));
}
}
-void Sword2Engine::mouseOnOff(void) {
+void Mouse::mouseOnOff() {
// this handles the cursor graphic when moving on and off mouse areas
// it also handles the luggage thingy
@@ -698,7 +817,7 @@ void Sword2Engine::mouseOnOff(void) {
// don't detect objects that are hidden behind the menu bars (ie. in
// the scrolled-off areas of the screen)
- if (_mouseY < 0 || _mouseY > 399) {
+ if (_pos.y < 0 || _pos.y > 399) {
pointer_type = 0;
_mouseTouching = 0;
} else {
@@ -743,7 +862,7 @@ void Sword2Engine::mouseOnOff(void) {
} else {
byte buf[NAME_LEN];
- error("ERROR: mouse.pointer==0 for object %d (%s) - update logic script!", _mouseTouching, fetchObjectName(_mouseTouching, buf));
+ error("ERROR: mouse.pointer==0 for object %d (%s) - update logic script!", _mouseTouching, _vm->fetchObjectName(_mouseTouching, buf));
}
} else if (_oldMouseTouching && !_mouseTouching) {
// the cursor has moved off something - reset cursor to
@@ -783,55 +902,66 @@ void Sword2Engine::mouseOnOff(void) {
// screens
}
-void Sword2Engine::setMouse(uint32 res) {
+void Mouse::setMouse(uint32 res) {
// high level - whats the mouse - for the engine
_mousePointerRes = res;
if (res) {
- byte *icon = _resman->openResource(res) + sizeof(StandardHeader);
- uint32 len = _resman->fetchLen(res) - sizeof(StandardHeader);
+ byte *icon = _vm->_resman->openResource(res) + sizeof(StandardHeader);
+ uint32 len = _vm->_resman->fetchLen(res) - sizeof(StandardHeader);
// don't pulse the normal pointer - just do the regular anim
// loop
if (res == NORMAL_MOUSE_ID)
- _graphics->setMouseAnim(icon, len, RDMOUSE_NOFLASH);
+ setMouseAnim(icon, len, RDMOUSE_NOFLASH);
else
- _graphics->setMouseAnim(icon, len, RDMOUSE_FLASH);
+ setMouseAnim(icon, len, RDMOUSE_FLASH);
- _resman->closeResource(res);
+ _vm->_resman->closeResource(res);
} else {
// blank cursor
- _graphics->setMouseAnim(NULL, 0, 0);
+ setMouseAnim(NULL, 0, 0);
}
}
-void Sword2Engine::setLuggage(uint32 res) {
+void Mouse::setLuggage(uint32 res) {
_realLuggageItem = res;
if (res) {
- byte *icon = _resman->openResource(res) + sizeof(StandardHeader);
- uint32 len = _resman->fetchLen(res) - sizeof(StandardHeader);
+ byte *icon = _vm->_resman->openResource(res) + sizeof(StandardHeader);
+ uint32 len = _vm->_resman->fetchLen(res) - sizeof(StandardHeader);
- _graphics->setLuggageAnim(icon, len);
- _resman->closeResource(res);
+ setLuggageAnim(icon, len);
+ _vm->_resman->closeResource(res);
} else
- _graphics->setLuggageAnim(NULL, 0);
+ setLuggageAnim(NULL, 0);
}
-uint32 Sword2Engine::checkMouseList(void) {
- // Number of priorities subject to implementation needs
+void Mouse::setObjectHeld(uint32 res) {
+ setLuggage(res);
+ Logic::_scriptVars[OBJECT_HELD] = res;
+ _currentLuggageResource = res;
+
+ // mode locked - no menu available
+ _mouseModeLocked = true;
+}
+
+uint32 Mouse::checkMouseList() {
+ ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
+
+ // Number of priorities subject to implementation needs
for (int priority = 0; priority < 10; priority++) {
for (uint i = 1; i < _curMouse; i++) {
// If the mouse pointer is over this
// mouse-detection-box
if (_mouseList[i].priority == priority &&
- _mouseX + _thisScreen.scroll_offset_x >= _mouseList[i].x1 &&
- _mouseX + _thisScreen.scroll_offset_x <= _mouseList[i].x2 &&
- _mouseY + _thisScreen.scroll_offset_y >= _mouseList[i].y1 &&
- _mouseY + _thisScreen.scroll_offset_y <= _mouseList[i].y2) {
+ _pos.x + screenInfo->scroll_offset_x >= _mouseList[i].x1 &&
+ _pos.x + screenInfo->scroll_offset_x <= _mouseList[i].x2 &&
+ _pos.y + screenInfo->scroll_offset_y >= _mouseList[i].y1 &&
+ _pos.y + screenInfo->scroll_offset_y <= _mouseList[i].y2) {
// Record id
_mouseTouching = _mouseList[i].id;
@@ -855,7 +985,7 @@ uint32 Sword2Engine::checkMouseList(void) {
#define POINTER_TEXT_WIDTH 640 // just in case!
#define POINTER_TEXT_PEN 184 // white
-void Sword2Engine::createPointerText(uint32 text_id, uint32 pointer_res) {
+void Mouse::createPointerText(uint32 text_id, uint32 pointer_res) {
uint32 local_text;
uint32 text_res;
byte *text;
@@ -863,7 +993,7 @@ void Sword2Engine::createPointerText(uint32 text_id, uint32 pointer_res) {
int16 xOffset, yOffset;
uint8 justification;
- if (!_gui->_pointerTextSelected || !text_id)
+ if (!_vm->_gui->_pointerTextSelected || !text_id)
return;
// Check what the pointer is, to set offsets correctly for text
@@ -993,30 +1123,30 @@ void Sword2Engine::createPointerText(uint32 text_id, uint32 pointer_res) {
local_text = text_id & 0xffff;
// open text file & get the line
- text = fetchTextLine(_resman->openResource(text_res), local_text);
+ text = _vm->fetchTextLine(_vm->_resman->openResource(text_res), local_text);
// 'text+2' to skip the first 2 bytes which form the
// line reference number
- _pointerTextBlocNo = _fontRenderer->buildNewBloc(
- text + 2, _mouseX + xOffset,
- _mouseY + yOffset,
+ _pointerTextBlocNo = _vm->_fontRenderer->buildNewBloc(
+ text + 2, _pos.x + xOffset,
+ _pos.y + yOffset,
POINTER_TEXT_WIDTH, POINTER_TEXT_PEN,
RDSPR_TRANS | RDSPR_DISPLAYALIGN,
- _speechFontId, justification);
+ _vm->_speechFontId, justification);
// now ok to close the text file
- _resman->closeResource(text_res);
+ _vm->_resman->closeResource(text_res);
}
-void Sword2Engine::clearPointerText(void) {
+void Mouse::clearPointerText() {
if (_pointerTextBlocNo) {
- _fontRenderer->killTextBloc(_pointerTextBlocNo);
+ _vm->_fontRenderer->killTextBloc(_pointerTextBlocNo);
_pointerTextBlocNo = 0;
}
}
-void Sword2Engine::noHuman(void) {
+void Mouse::hideMouse() {
// leaves the menus open
// used by the system when clicking right on a menu item to examine
// it and when combining objects
@@ -1031,47 +1161,122 @@ void Sword2Engine::noHuman(void) {
setLuggage(0);
}
-void Sword2Engine::registerMouse(ObjectMouse *ob_mouse) {
- debug(5, "_curMouse = %d", _curMouse);
+void Mouse::noHuman() {
+ hideMouse();
+ clearPointerText();
- if (!ob_mouse->pointer)
- return;
+ // Must be normal mouse situation or a largely neutral situation -
+ // special menus use hideMouse()
- assert(_curMouse < TOTAL_mouse_list);
+ // Don't hide menu in conversations
+ if (Logic::_scriptVars[TALK_FLAG] == 0)
+ hideMenu(RDMENU_BOTTOM);
- _mouseList[_curMouse].x1 = ob_mouse->x1;
- _mouseList[_curMouse].y1 = ob_mouse->y1;
- _mouseList[_curMouse].x2 = ob_mouse->x2;
- _mouseList[_curMouse].y2 = ob_mouse->y2;
+ if (_mouseMode == MOUSE_system_menu) {
+ // Close menu
+ _mouseMode = MOUSE_normal;
+ hideMenu(RDMENU_TOP);
+ }
+}
- _mouseList[_curMouse].priority = ob_mouse->priority;
- _mouseList[_curMouse].pointer = ob_mouse->pointer;
+void Mouse::addHuman() {
+ // For logic scripts
+ Logic::_scriptVars[MOUSE_AVAILABLE] = 1;
- // Check if pointer text field is set due to previous object using this
- // slot (ie. not correct for this one)
+ if (_mouseStatus) {
+ // Force engine to choose a cursor
+ _mouseStatus = false;
+ _mouseTouching = 1;
+ }
- // If 'pointer_text' field is set, but the 'id' field isn't same is
- // current id, then we don't want this "left over" pointer text
+ // Clear this to reset no-second-click system
+ Logic::_scriptVars[CLICKED_ID] = 0;
- if (_mouseList[_curMouse].pointer_text && _mouseList[_curMouse].id != (int32) Logic::_scriptVars[ID])
- _mouseList[_curMouse].pointer_text = 0;
+ // This is now done outside the OBJECT_HELD check in case it's set to
+ // zero before now!
- // Get id from system variable 'id' which is correct for current object
+ // Unlock the mouse from possible large object lock situtations - see
+ // syphon in rm 3
- _mouseList[_curMouse].id = Logic::_scriptVars[ID];
+ _mouseModeLocked = false;
- // Not using sprite as mask - this is only done from fnRegisterFrame()
+ if (Logic::_scriptVars[OBJECT_HELD]) {
+ // Was dragging something around - need to clear this again
+ Logic::_scriptVars[OBJECT_HELD] = 0;
- _mouseList[_curMouse].anim_resource = 0;
- _mouseList[_curMouse].anim_pc = 0;
+ // And these may also need clearing, just in case
+ _examiningMenuIcon = false;
+ Logic::_scriptVars[COMBINE_BASE] = 0;
- debug(5, "mouse id %d", _mouseList[_curMouse].id);
- _curMouse++;
+ setLuggage(0);
+ }
+
+ // If mouse is over menu area
+ if (_pos.y > 399) {
+ if (_mouseMode != MOUSE_holding) {
+ // VITAL - reset things & rebuild the menu
+ _mouseMode = MOUSE_normal;
+ }
+ setMouse(NORMAL_MOUSE_ID);
+ }
+
+ // Enabled/disabled from console; status printed with on-screen debug
+ // info
+
+ if (_vm->_debugger->_testingSnR) {
+ uint8 black[4] = { 0, 0, 0, 0 };
+ uint8 white[4] = { 255, 255, 255, 0 };
+
+ // Testing logic scripts by simulating instant Save & Restore
+
+ _vm->_screen->setPalette(0, 1, white, RDPAL_INSTANT);
+
+ // Stops all fx & clears the queue - eg. when leaving a room
+ _vm->_sound->clearFxQueue();
+
+ // Trash all object resources so they load in fresh & restart
+ // their logic scripts
+
+ _vm->_resman->killAllObjects(false);
+
+ _vm->_screen->setPalette(0, 1, black, RDPAL_INSTANT);
+ }
+}
+
+void Mouse::refreshInventory() {
+ // Can reset this now
+ Logic::_scriptVars[COMBINE_BASE] = 0;
+
+ // Cause 'object_held' icon to be greyed. The rest are coloured.
+ _examiningMenuIcon = true;
+ buildMenu();
+ _examiningMenuIcon = false;
+}
+
+void Mouse::startConversation() {
+ if (Logic::_scriptVars[TALK_FLAG] == 0) {
+ // See fnChooser & speech scripts
+ Logic::_scriptVars[CHOOSER_COUNT_FLAG] = 0;
+ }
+
+ noHuman();
+}
+
+void Mouse::endConversation() {
+ hideMenu(RDMENU_BOTTOM);
+
+ if (_pos.y > 399) {
+ // Will wait for cursor to move off the bottom menu
+ _mouseMode = MOUSE_holding;
+ }
+
+ // In case DC forgets
+ Logic::_scriptVars[TALK_FLAG] = 0;
}
-void Sword2Engine::monitorPlayerActivity(void) {
+void Mouse::monitorPlayerActivity() {
// if there is at least one mouse event outstanding
- if (checkForMouseEvents()) {
+ if (_vm->checkForMouseEvents()) {
// reset activity delay counter
_playerActivityDelay = 0;
} else {
@@ -1080,4 +1285,33 @@ void Sword2Engine::monitorPlayerActivity(void) {
}
}
+void Mouse::checkPlayerActivity(uint32 seconds) {
+ // Convert seconds to game cycles
+ uint32 threshold = seconds * 12;
+
+ // If the actual delay is at or above the given threshold, reset the
+ // activity delay counter now that we've got a positive check.
+
+ if (_playerActivityDelay >= threshold) {
+ _playerActivityDelay = 0;
+ Logic::_scriptVars[RESULT] = 1;
+ } else
+ Logic::_scriptVars[RESULT] = 0;
+}
+
+void Mouse::pauseGame() {
+ // Make the mouse cursor normal. This is the only place where we are
+ // allowed to clear the luggage this way.
+
+ clearPointerText();
+ setLuggageAnim(NULL, 0);
+ setMouse(0);
+ setMouseTouching(1);
+}
+
+void Mouse::unpauseGame() {
+ if (Logic::_scriptVars[OBJECT_HELD] && _realLuggageItem)
+ setLuggage(_realLuggageItem);
+}
+
} // End of namespace Sword2
diff --git a/sword2/mouse.h b/sword2/mouse.h
index be39df6c44..e304db086b 100644
--- a/sword2/mouse.h
+++ b/sword2/mouse.h
@@ -21,17 +21,30 @@
#ifndef MOUSE_H
#define MOUSE_H
-#define TOTAL_mouse_list 50
+#define TOTAL_mouse_list 50
namespace Sword2 {
-enum {
- MOUSE_normal = 0, // normal in game
- MOUSE_menu = 1, // menu chooser
- MOUSE_drag = 2, // dragging luggage
- MOUSE_system_menu = 3, // system menu chooser
- MOUSE_holding = 4 // special
-};
+struct ObjectMouse;
+struct BuildUnit;
+
+#if !defined(__GNUC__)
+ #pragma START_PACK_STRUCTS
+#endif
+
+struct MouseAnim {
+ uint8 runTimeComp; // type of runtime compression used for the
+ // frame data
+ uint8 noAnimFrames; // number of frames in the anim
+ int8 xHotSpot;
+ int8 yHotSpot;
+ uint8 mousew;
+ uint8 mouseh;
+} GCC_PACK;
+
+#if !defined(__GNUC__)
+ #pragma END_PACK_STRUCTS
+#endif
// The MOUSE_holding mode is entered when the conversation menu is closed, and
// exited when the mouse cursor moves off that menu area. I don't know why yet.
@@ -68,6 +81,136 @@ struct MouseUnit {
int32 pointer_text;
};
+class Mouse {
+private:
+ Sword2Engine *_vm;
+
+ Common::Point _pos;
+
+ MouseUnit _mouseList[TOTAL_mouse_list];
+ uint32 _curMouse;
+
+ MenuObject _tempList[TOTAL_engine_pockets];
+ uint32 _totalTemp;
+
+ MenuObject _masterMenuList[TOTAL_engine_pockets];
+ uint32 _totalMasters;
+
+ uint8 _menuStatus[2];
+ byte *_icons[2][RDMENU_MAXPOCKETS];
+ uint8 _pocketStatus[2][RDMENU_MAXPOCKETS];
+
+ uint8 _iconCount;
+
+ // If it's NORMAL_MOUSE_ID (ie. normal pointer) then it's over a floor
+ // area (or hidden hot-zone)
+
+ uint32 _mousePointerRes;
+
+ struct MouseAnim *_mouseAnim;
+ struct MouseAnim *_luggageAnim;
+
+ uint8 _mouseFrame;
+ byte *_mouseSprite;
+ int32 *_mouseOffsets;
+ int32 *_luggageOffset;
+
+ uint32 _mouseMode;
+
+ bool _mouseStatus; // Human 0 on/1 off
+ bool _mouseModeLocked; // 0 not !0 mode cannot be changed from
+ // normal mouse to top menu (i.e. when
+ // carrying big objects)
+ uint32 _realLuggageItem; // Last minute for pause mode
+ uint32 _currentLuggageResource;
+ uint32 _oldButton; // For the re-click stuff - must be
+ // the same button you see
+ uint32 _buttonClick;
+ uint32 _pointerTextBlocNo;
+ uint32 _playerActivityDelay; // Player activity delay counter
+
+ bool _examiningMenuIcon;
+
+ // Set by checkMouseList()
+ uint32 _mouseTouching;
+ uint32 _oldMouseTouching;
+
+ uint32 _menuSelectedPos;
+
+ void decompressMouse(byte *decomp, byte *comp, int width, int height, int pitch, int xOff = 0, int yOff = 0);
+
+ int32 setMouseAnim(byte *ma, int32 size, int32 mouseFlash);
+ int32 setLuggageAnim(byte *la, int32 size);
+
+ void clearIconArea(int menu, int pocket, Common::Rect *r);
+
+public:
+ Mouse(Sword2Engine *vm);
+ ~Mouse();
+
+ void getPos(int &x, int &y);
+ void setPos(int x, int y);
+
+ bool getMouseStatus() { return _mouseStatus; }
+ uint32 getMouseTouching() { return _mouseTouching; }
+ void setMouseTouching(uint32 touching) { _mouseTouching = touching; }
+
+ void pauseGame();
+ void unpauseGame();
+
+ void setMouse(uint32 res);
+ void setLuggage(uint32 res);
+
+ void setObjectHeld(uint32 res);
+
+ void resetMouseList();
+
+ void registerMouse(ObjectMouse *ob_mouse, BuildUnit *build_unit);
+ void registerPointerText(int32 text_id);
+
+ void createPointerText(uint32 text_id, uint32 pointer_res);
+ void clearPointerText();
+
+ void drawMouse();
+ int32 animateMouse();
+
+ void processMenu();
+
+ void addMenuObject(MenuObject *obj);
+ void buildMenu();
+ void buildSystemMenu();
+
+ int32 showMenu(uint8 menu);
+ int32 hideMenu(uint8 menu);
+ int32 setMenuIcon(uint8 menu, uint8 pocket, byte *icon);
+
+ void closeMenuImmediately();
+
+ void refreshInventory();
+
+ void startConversation();
+ void endConversation();
+
+ void hideMouse();
+ void noHuman();
+ void addHuman();
+
+ void resetPlayerActivityDelay() { _playerActivityDelay = 0; }
+ void monitorPlayerActivity();
+ void checkPlayerActivity(uint32 seconds);
+
+ void mouseOnOff();
+ uint32 checkMouseList();
+ void mouseEngine();
+
+ void normalMouse();
+ void menuMouse();
+ void dragMouse();
+ void systemMenuMouse();
+
+ int menuClick(int menu_items);
+};
+
} // End of namespace Sword2
#endif
diff --git a/sword2/resman.cpp b/sword2/resman.cpp
index 099e218721..bfb5a7c7af 100644
--- a/sword2/resman.cpp
+++ b/sword2/resman.cpp
@@ -28,7 +28,6 @@
#include "sword2/resman.h"
#include "sword2/router.h"
#include "sword2/sound.h"
-#include "sword2/driver/d_draw.h"
#define Debug_Printf _vm->_debugger->DebugPrintf
@@ -870,7 +869,7 @@ void ResourceManager::getCd(int cd) {
_vm->_sound->stopMusic(true);
textRes = openResource(2283);
- _vm->displayMsg(_vm->fetchTextLine(textRes, 5 + cd) + 2, 0);
+ _vm->_screen->displayMsg(_vm->fetchTextLine(textRes, 5 + cd) + 2, 0);
closeResource(2283);
// The original code probably determined automagically when the correct
diff --git a/sword2/router.cpp b/sword2/router.cpp
index 33b342c177..ef0b81f5a6 100644
--- a/sword2/router.cpp
+++ b/sword2/router.cpp
@@ -79,7 +79,6 @@
#include "sword2/logic.h"
#include "sword2/resman.h"
#include "sword2/router.h"
-#include "sword2/driver/d_draw.h"
namespace Sword2 {
@@ -2367,7 +2366,7 @@ void Router::plotWalkGrid(void) {
// lines
for (i = 0; i < _nBars; i++)
- _vm->_graphics->drawLine(_bars[i].x1, _bars[i].y1, _bars[i].x2, _bars[i].y2, 254);
+ _vm->_screen->drawLine(_bars[i].x1, _bars[i].y1, _bars[i].x2, _bars[i].y2, 254);
// nodes
@@ -2377,8 +2376,8 @@ void Router::plotWalkGrid(void) {
}
void Router::plotCross(int16 x, int16 y, uint8 colour) {
- _vm->_graphics->drawLine(x - 1, y - 1, x + 1, y + 1, colour);
- _vm->_graphics->drawLine(x + 1, y - 1, x - 1, y + 1, colour);
+ _vm->_screen->drawLine(x - 1, y - 1, x + 1, y + 1, colour);
+ _vm->_screen->drawLine(x + 1, y - 1, x - 1, y + 1, colour);
}
void Router::loadWalkGrid(void) {
diff --git a/sword2/save_rest.cpp b/sword2/save_rest.cpp
index d3bd0035ff..ea1b34f5c0 100644
--- a/sword2/save_rest.cpp
+++ b/sword2/save_rest.cpp
@@ -34,6 +34,7 @@
#include "sword2/interpreter.h"
#include "sword2/logic.h"
#include "sword2/memory.h"
+#include "sword2/mouse.h"
#include "sword2/resman.h"
#include "sword2/sound.h"
@@ -115,13 +116,14 @@ uint32 Sword2Engine::findBufferSize(void) {
void Sword2Engine::fillSaveBuffer(byte *buffer, uint32 size, byte *desc) {
// Set up the _saveGameHeader. Checksum gets filled in last of all.
+ ScreenInfo *screenInfo = _screen->getScreenInfo();
strcpy(_saveGameHeader.description, (char *) desc);
_saveGameHeader.varLength = _resman->fetchLen(1);
- _saveGameHeader.screenId = _thisScreen.background_layer_id;
+ _saveGameHeader.screenId = screenInfo->background_layer_id;
_saveGameHeader.runListId = _logic->getRunList();
- _saveGameHeader.feet_x = _thisScreen.feet_x;
- _saveGameHeader.feet_y = _thisScreen.feet_y;
+ _saveGameHeader.feet_x = screenInfo->feet_x;
+ _saveGameHeader.feet_y = screenInfo->feet_y;
_saveGameHeader.music_id = _sound->getLoopingMusicId();
memcpy(&_saveGameHeader.player_hub, _resman->openResource(CUR_PLAYER_ID) + sizeof(StandardHeader), sizeof(ObjectHub));
@@ -205,7 +207,7 @@ uint32 Sword2Engine::restoreGame(uint16 slotNo) {
// Force the game engine to pick a cursor. This appears to be needed
// when using the -x command-line option to restore a game.
- _mouseTouching = 1;
+ _mouse->setMouseTouching(1);
return errorCode;
}
@@ -304,16 +306,18 @@ uint32 Sword2Engine::restoreFromBuffer(byte *buffer, uint32 size) {
pars[1] = 1;
_logic->fnInitBackground(pars);
+ ScreenInfo *screenInfo = _screen->getScreenInfo();
+
// So palette not restored immediately after control panel - we want to
// fade up instead!
- _thisScreen.new_palette = 99;
+ screenInfo->new_palette = 99;
// These need setting after the defaults get set in fnInitBackground.
// Remember that these can change through the game, so need saving &
// restoring too.
- _thisScreen.feet_x = _saveGameHeader.feet_x;
- _thisScreen.feet_y = _saveGameHeader.feet_y;
+ screenInfo->feet_x = _saveGameHeader.feet_x;
+ screenInfo->feet_y = _saveGameHeader.feet_y;
// Start the new run list
_logic->expressChangeSession(_saveGameHeader.runListId);
@@ -321,15 +325,14 @@ uint32 Sword2Engine::restoreFromBuffer(byte *buffer, uint32 size) {
// Force in the new scroll position, so unsightly scroll-catch-up does
// not occur when screen first draws after returning from restore panel
- // set '_thisScreen's record of player position
- // - ready for setScrolling()
+ // Set the screen record of player position - ready for setScrolling()
- _thisScreen.player_feet_x = _saveGameHeader.mega.feet_x;
- _thisScreen.player_feet_y = _saveGameHeader.mega.feet_y;
+ screenInfo->player_feet_x = _saveGameHeader.mega.feet_x;
+ screenInfo->player_feet_y = _saveGameHeader.mega.feet_y;
// if this screen is wide, recompute the scroll offsets now
- if (_thisScreen.scroll_flag)
- setScrolling();
+ if (screenInfo->scroll_flag)
+ _screen->setScrolling();
// Any music required will be started after we've returned from
// restoreControl() - see systemMenuMouse() in mouse.cpp!
diff --git a/sword2/scroll.cpp b/sword2/scroll.cpp
index 82fa0fa504..f1eb00fe9f 100644
--- a/sword2/scroll.cpp
+++ b/sword2/scroll.cpp
@@ -21,7 +21,6 @@
#include "common/stdafx.h"
#include "sword2/sword2.h"
#include "sword2/defs.h"
-#include "sword2/interpreter.h"
#include "sword2/logic.h"
namespace Sword2 {
@@ -30,11 +29,22 @@ namespace Sword2 {
#define MAX_SCROLL_DISTANCE 8
/**
+ * Sets the scroll target position for the end of the game cycle. The driver
+ * will then automatically scroll as many times as it can to reach this
+ * position in the allotted time.
+ */
+
+void Screen::setScrollTarget(int16 sx, int16 sy) {
+ _scrollXTarget = sx;
+ _scrollYTarget = sy;
+}
+
+/**
* If the room is larger than the physical screen, this function is called
* every game cycle to update the scroll offsets.
*/
-void Sword2Engine::setScrolling(void) {
+void Screen::setScrolling() {
// Normally we aim to get George's feet at (320,250) from top left
// of screen window
// feet_x = 128 + 320
diff --git a/sword2/sound.cpp b/sword2/sound.cpp
index 90e5f8a395..97155db266 100644
--- a/sword2/sound.cpp
+++ b/sword2/sound.cpp
@@ -82,6 +82,20 @@ Sound::~Sound() {
}
}
+void Sound::setReverseStereo(bool reverse) {
+ if (reverse != _reverseStereo) {
+ _reverseStereo = reverse;
+
+ for (int i = 0; i < FXQ_LENGTH; i++) {
+ if (!_fxQueue[i].resource)
+ continue;
+
+ _fxQueue[i].pan = -_fxQueue[i].pan;
+ _vm->_mixer->setChannelBalance(_fxQueue[i].handle, _fxQueue[i].pan);
+ }
+ }
+}
+
/**
* Stop all sounds, close their resources and clear the FX queue.
*/
@@ -190,6 +204,9 @@ void Sound::queueFx(int32 res, int32 type, int32 delay, int32 volume, int32 pan)
volume = (volume * SoundMixer::kMaxChannelVolume) / 16;
pan = (pan * 127) / 16;
+ if (isReverseStereo())
+ pan = -pan;
+
_fxQueue[i].resource = res;
_fxQueue[i].data = data + sizeof(StandardHeader);
_fxQueue[i].len = len;
diff --git a/sword2/sound.h b/sword2/sound.h
index 0d5c2371b5..64b441ff51 100644
--- a/sword2/sound.h
+++ b/sword2/sound.h
@@ -197,7 +197,7 @@ public:
void clearFxQueue();
void processFxQueue();
- void setReverseStereo(bool reverse) { _reverseStereo = reverse; }
+ void setReverseStereo(bool reverse);
bool isReverseStereo() const { return _reverseStereo; }
void muteSpeech(bool mute);
@@ -228,7 +228,7 @@ public:
int32 playFx(FxQueueEntry *fx);
int32 playFx(PlayingSoundHandle *handle, byte *data, uint32 len, uint8 vol, int8 pan, bool loop, SoundMixer::SoundType soundType);
int32 stopFx(int32 i);
- int32 setFxIdVolumePan(int32 id, int vol, int pan = -1);
+ int32 setFxIdVolumePan(int32 id, int vol, int pan = 255);
int32 getSpeechStatus();
int32 amISpeaking();
diff --git a/sword2/speech.cpp b/sword2/speech.cpp
index dcd3651a9e..abf0e67d85 100644
--- a/sword2/speech.cpp
+++ b/sword2/speech.cpp
@@ -30,7 +30,6 @@
#include "sword2/maketext.h"
#include "sword2/memory.h"
#include "sword2/resman.h"
-#include "sword2/driver/d_draw.h"
namespace Sword2 {
@@ -126,8 +125,10 @@ void Logic::locateTalker(int32 *params) {
// Adjust the text coords for RDSPR_DISPLAYALIGN
- _textX -= _vm->_thisScreen.scroll_offset_x;
- _textY -= _vm->_thisScreen.scroll_offset_y;
+ ScreenInfo *screenInfo = _vm->_screen->getScreenInfo();
+
+ _textX -= screenInfo->scroll_offset_x;
+ _textY -= screenInfo->scroll_offset_y;
}
/**
diff --git a/sword2/sword2.cpp b/sword2/sword2.cpp
index 9bc65fcb38..461401b8a7 100644
--- a/sword2/sword2.cpp
+++ b/sword2/sword2.cpp
@@ -36,9 +36,9 @@
#include "sword2/logic.h"
#include "sword2/maketext.h"
#include "sword2/memory.h"
+#include "sword2/mouse.h"
#include "sword2/resman.h"
#include "sword2/sound.h"
-#include "sword2/driver/d_draw.h"
#ifdef _WIN32_WCE
extern bool isSmartphone(void);
@@ -121,60 +121,21 @@ Sword2Engine::Sword2Engine(GameDetector *detector, OSystem *syst) : Engine(syst)
_bootParam = ConfMan.getInt("boot_param");
_saveSlot = ConfMan.getInt("save_slot");
- _debugger = NULL;
- _graphics = NULL;
+ _memory = NULL;
+ _resman = NULL;
_sound = NULL;
- _gui = NULL;
- _fontRenderer = NULL;
+ _screen = NULL;
+ _mouse = NULL;
_logic = NULL;
- _resman = NULL;
- _memory = NULL;
+ _fontRenderer = NULL;
+ _gui = NULL;
+ _debugger = NULL;
_keyboardEvent.pending = false;
_mouseEvent.pending = false;
- _lastPaletteRes = 0;
-
- _largestLayerArea = 0;
- _largestSpriteArea = 0;
-
- strcpy(_largestLayerInfo, "largest layer: none registered");
- strcpy(_largestSpriteInfo, "largest sprite: none registered");
-
- _fps = 0;
- _cycleTime = 0;
- _frameCount = 0;
-
_wantSfxDebug = false;
- // For the menus
-
- _totalTemp = 0;
- memset(_tempList, 0, sizeof(_tempList));
-
- _totalMasters = 0;
- memset(_masterMenuList, 0, sizeof(_masterMenuList));
- memset(&_thisScreen, 0, sizeof(_thisScreen));
- memset(_mouseList, 0, sizeof(_mouseList));
-
- _mouseX = _mouseY = 0;
- _mouseTouching = 0;
- _oldMouseTouching = 0;
- _menuSelectedPos = 0;
- _examiningMenuIcon = false;
- _mousePointerRes = 0;
- _mouseMode = 0;
- _mouseStatus = false;
- _mouseModeLocked = false;
- _currentLuggageResource = 0;
- _oldButton = 0;
- _buttonClick = 0;
- _pointerTextBlocNo = 0;
- _playerActivityDelay = 0;
- _realLuggageItem = 0;
-
- _scrollFraction = 16;
-
#ifdef SWORD2_DEBUG
_stepOneCycle = false;
_renderSkip = false;
@@ -190,10 +151,11 @@ Sword2Engine::Sword2Engine(GameDetector *detector, OSystem *syst) : Engine(syst)
Sword2Engine::~Sword2Engine() {
delete _debugger;
- delete _graphics;
delete _sound;
delete _gui;
delete _fontRenderer;
+ delete _screen;
+ delete _mouse;
delete _logic;
delete _resman;
delete _memory;
@@ -233,7 +195,7 @@ int Sword2Engine::init(GameDetector &detector) {
_system->beginGFXTransaction();
initCommonGFX(detector);
- _graphics = new Graphics(this, 640, 480);
+ _screen = new Screen(this, 640, 480);
_system->endGFXTransaction();
// Create the debugger as early as possible (but not before the
@@ -249,6 +211,7 @@ int Sword2Engine::init(GameDetector &detector) {
_fontRenderer = new FontRenderer(this);
_gui = new Gui(this);
_sound = new Sound(this);
+ _mouse = new Mouse(this);
// Setup mixer
if (!_mixer->isReady())
@@ -278,7 +241,7 @@ int Sword2Engine::init(GameDetector &detector) {
if (saveExists(_saveSlot))
restoreGame(_saveSlot);
else {
- setMouse(NORMAL_MOUSE_ID);
+ _mouse->setMouse(NORMAL_MOUSE_ID);
if (!_gui->restoreControl())
startGame();
}
@@ -286,7 +249,7 @@ int Sword2Engine::init(GameDetector &detector) {
int32 pars[2] = { 221, FX_LOOP };
bool result;
- setMouse(NORMAL_MOUSE_ID);
+ _mouse->setMouse(NORMAL_MOUSE_ID);
_logic->fnPlayMusic(pars);
result = _gui->startControl();
@@ -302,7 +265,7 @@ int Sword2Engine::init(GameDetector &detector) {
} else
startGame();
- _graphics->initialiseRenderCycle();
+ _screen->initialiseRenderCycle();
return 0;
}
@@ -374,9 +337,9 @@ int Sword2Engine::go() {
// display once every 4 game-cycles
if (!_renderSkip || (_gameCycle % 4) == 0)
- buildDisplay();
+ _screen->buildDisplay();
#else
- buildDisplay();
+ _screen->buildDisplay();
#endif
}
@@ -433,8 +396,7 @@ void Sword2Engine::parseEvents() {
break;
case OSystem::EVENT_MOUSEMOVE:
if (!(_eventFilter & RD_KEYDOWN)) {
- _mouseX = event.mouse.x;
- _mouseY = event.mouse.y - RDMENU_MENUDEEP;
+ _mouse->setPos(event.mouse.x, event.mouse.y - RDMENU_MENUDEEP);
}
break;
case OSystem::EVENT_LBUTTONDOWN:
@@ -493,8 +455,8 @@ void Sword2Engine::gameCycle() {
// will fill thrm through fnRegisterFrame() and
// fnRegisterMouse().
- resetRenderLists();
- resetMouseList();
+ _screen->resetRenderLists();
+ _mouse->resetMouseList();
// Keep going as long as new lists keep getting put in
// - i.e. screen changes.
@@ -505,10 +467,12 @@ void Sword2Engine::gameCycle() {
}
// If this screen is wide, recompute the scroll offsets every cycle
- if (_thisScreen.scroll_flag)
- setScrolling();
+ ScreenInfo *screenInfo = _screen->getScreenInfo();
- mouseEngine();
+ if (screenInfo->scroll_flag)
+ _screen->setScrolling();
+
+ _mouse->mouseEngine();
_sound->processFxQueue();
}
@@ -551,26 +515,19 @@ void Sword2Engine::sleepUntil(uint32 time) {
while (getMillis() < time) {
// Make sure menu animations and fades don't suffer, but don't
// redraw the entire scene.
- _graphics->processMenu();
- _graphics->updateDisplay(false);
+ _mouse->processMenu();
+ _screen->updateDisplay(false);
_system->delayMillis(10);
}
}
void Sword2Engine::pauseGame() {
// Don't allow Pause while screen fading or while black
- if (_graphics->getFadeStatus() != RDFADE_NONE)
+ if (_screen->getFadeStatus() != RDFADE_NONE)
return;
_sound->pauseAllSound();
-
- // Make the mouse cursor normal. This is the only place where we are
- // allowed to clear the luggage this way.
-
- clearPointerText();
- _graphics->setLuggageAnim(NULL, 0);
- setMouse(0);
- _mouseTouching = 1;
+ _mouse->pauseGame();
// If level at max, turn down because palette-matching won't work
// when dimmed
@@ -585,22 +542,20 @@ void Sword2Engine::pauseGame() {
// dim the palette during the pause
if (!_stepOneCycle)
- _graphics->dimPalette();
+ _screen->dimPalette();
#else
- _graphics->dimPalette();
+ _screen->dimPalette();
#endif
_gamePaused = true;
}
void Sword2Engine::unpauseGame() {
- if (Logic::_scriptVars[OBJECT_HELD] && _realLuggageItem)
- setLuggage(_realLuggageItem);
-
+ _mouse->unpauseGame();
_sound->unpauseAllSound();
// Put back game screen palette; see build_display.cpp
- setFullPalette(-1);
+ _screen->setFullPalette(-1);
// If graphics level at max, turn up again
if (_graphicsLevelFudged) {
@@ -611,8 +566,8 @@ void Sword2Engine::unpauseGame() {
_gamePaused = false;
// If mouse is about or we're in a chooser menu
- if (!_mouseStatus || _logic->_choosing)
- setMouse(NORMAL_MOUSE_ID);
+ if (!_mouse->getMouseStatus() || _logic->_choosing)
+ _mouse->setMouse(NORMAL_MOUSE_ID);
}
uint32 Sword2Engine::getMillis() {
diff --git a/sword2/sword2.h b/sword2/sword2.h
index c51202b447..8de53d64e4 100644
--- a/sword2/sword2.h
+++ b/sword2/sword2.h
@@ -36,8 +36,6 @@
#include "sword2/build_display.h"
#include "sword2/header.h"
#include "sword2/icons.h"
-#include "sword2/layers.h"
-#include "sword2/mouse.h"
#include "sword2/object.h"
#include "sword2/save_rest.h"
@@ -56,6 +54,8 @@ enum {
class MemoryManager;
class ResourceManager;
class Sound;
+class Screen;
+class Mouse;
class Graphics;
class Logic;
class FontRenderer;
@@ -96,67 +96,6 @@ private:
uint32 _bootParam;
int32 _saveSlot;
- // structure filled out by each object to register its graphic printing
- // requrements
-
- struct BuildUnit {
- int16 x;
- int16 y;
- uint16 scaled_width;
- uint16 scaled_height;
- int16 sort_y;
- uint32 anim_resource;
- uint16 anim_pc;
-
- // Denotes a scaling sprite at print time - and holds the
- // scaling value for the shrink routine
-
- uint16 scale;
-
- // Non-zero means this item is a layer - retrieve from
- // background layer and send to special renderer
-
- uint16 layer_number;
-
- // True means we want this frame to be affected by the shading
- // mask
-
- bool shadingFlag;
- };
-
- BuildUnit _bgp0List[MAX_bgp0_sprites];
- BuildUnit _bgp1List[MAX_bgp1_sprites];
- BuildUnit _backList[MAX_back_sprites];
- BuildUnit _sortList[MAX_sort_sprites];
- BuildUnit _foreList[MAX_fore_sprites];
- BuildUnit _fgp0List[MAX_fgp0_sprites];
- BuildUnit _fgp1List[MAX_fgp1_sprites];
-
- // Holds the order of the sort list, i.e. the list stays static and we
- // sort this array.
-
- uint16 _sortOrder[MAX_sort_sprites];
-
- // Last palette used - so that we can restore the correct one after a
- // pause (which dims the screen) and it's not always the main screen
- // palette that we want, eg. during the eclipse
-
- // This flag gets set in startNewPalette() and setFullPalette()
-
- uint32 _lastPaletteRes;
-
- void drawBackPar0Frames();
- void drawBackPar1Frames();
- void drawBackFrames();
- void drawSortFrames(byte *file);
- void drawForeFrames();
- void drawForePar0Frames();
- void drawForePar1Frames();
-
- void startNewPalette();
- void processLayer(byte *file, uint32 layer_number);
- void processImage(BuildUnit *build_unit);
-
void getPlayerStructures();
void putPlayerStructures();
@@ -168,12 +107,6 @@ private:
void pauseGame();
void unpauseGame();
- MenuObject _tempList[TOTAL_engine_pockets];
- uint32 _totalTemp;
-
- MenuObject _masterMenuList[TOTAL_engine_pockets];
- uint32 _totalMasters;
-
uint32 _totalStartups;
uint32 _totalScreenManagers;
uint32 _startRes;
@@ -208,7 +141,8 @@ public:
MemoryManager *_memory;
ResourceManager *_resman;
Sound *_sound;
- Graphics *_graphics;
+ Screen *_screen;
+ Mouse *_mouse;
Logic *_logic;
FontRenderer *_fontRenderer;
Gui *_gui;
@@ -221,9 +155,6 @@ public:
uint32 _controlsFontId;
uint32 _redFontId;
- int16 _mouseX;
- int16 _mouseY;
-
uint32 setEventFilter(uint32 filter);
void parseEvents();
@@ -232,36 +163,6 @@ public:
MouseEvent *mouseEvent();
KeyboardEvent *keyboardEvent();
- void resetRenderLists();
- void buildDisplay();
- void displayMsg(byte *text, int time);
- void setFullPalette(int32 palRes);
-
- int32 registerFrame(int32 *params);
- void registerFrame(int32 *params, BuildUnit *build_unit);
-
- // The debugger wants to access these
-
- uint32 _curBgp0;
- uint32 _curBgp1;
- uint32 _curBack;
- uint32 _curSort;
- uint32 _curFore;
- uint32 _curFgp0;
- uint32 _curFgp1;
-
- // Debugging stuff
-
- uint32 _largestLayerArea;
- uint32 _largestSpriteArea;
- char _largestLayerInfo[128];
- char _largestSpriteInfo[128];
-
- // 'frames per second' counting stuff
- uint32 _fps;
- uint32 _cycleTime;
- uint32 _frameCount;
-
bool _wantSfxDebug;
int32 _gameCycle;
@@ -271,74 +172,10 @@ public:
bool _stepOneCycle;
#endif
- int32 initBackground(int32 res, int32 new_palette);
-
#if RIGHT_CLICK_CLEARS_LUGGAGE
bool heldIsInInventory();
#endif
- int menuClick(int menu_items);
-
- void addMenuObject(MenuObject *obj);
- void buildMenu();
- void buildSystemMenu();
-
- // _thisScreen describes the current back buffer and its in-game scroll
- // positions, etc.
-
- ScreenInfo _thisScreen;
-
- uint32 _curMouse;
- MouseUnit _mouseList[TOTAL_mouse_list];
-
- // Set by checkMouseList()
- uint32 _mouseTouching;
- uint32 _oldMouseTouching;
-
- uint32 _menuSelectedPos;
-
- // If it's NORMAL_MOUSE_ID (ie. normal pointer) then it's over a floor
- // area (or hidden hot-zone)
-
- uint32 _mousePointerRes;
-
- uint32 _mouseMode;
- bool _examiningMenuIcon;
-
- bool _mouseStatus; // Human 0 on/1 off
- bool _mouseModeLocked; // 0 not !0 mode cannot be changed from
- // normal mouse to top menu (i.e. when
- // carrying big objects)
- uint32 _realLuggageItem; // Last minute for pause mode
- uint32 _currentLuggageResource;
- uint32 _oldButton; // For the re-click stuff - must be
- // the same button you see
- uint32 _buttonClick;
- uint32 _pointerTextBlocNo;
- uint32 _playerActivityDelay; // Player activity delay counter
-
- void resetMouseList();
-
- void normalMouse();
- void menuMouse();
- void dragMouse();
- void systemMenuMouse();
-
- void mouseOnOff();
- uint32 checkMouseList();
- void mouseEngine();
-
- void setMouse(uint32 res);
- void setLuggage(uint32 res);
-
- void clearPointerText();
-
- void createPointerText(uint32 text_id, uint32 pointer_res);
- void monitorPlayerActivity();
- void noHuman();
-
- void registerMouse(ObjectMouse *ob_mouse);
-
byte *fetchPalette(byte *screenFile);
ScreenHeader *fetchScreenHeader(byte *screenFile);
LayerHeader *fetchLayerHeader(byte *screenFile, uint16 layerNo);
@@ -395,10 +232,6 @@ public:
uint32 restoreFromBuffer(byte *buffer, uint32 size);
uint32 findBufferSize();
- uint8 _scrollFraction;
-
- void setScrolling();
-
bool _gamePaused;
bool _graphicsLevelFudged;
diff --git a/sword2/walker.cpp b/sword2/walker.cpp
index d0238b4df7..bf284f402e 100644
--- a/sword2/walker.cpp
+++ b/sword2/walker.cpp
@@ -31,7 +31,6 @@
#include "sword2/memory.h"
#include "sword2/resman.h"
#include "sword2/router.h"
-#include "sword2/driver/d_draw.h"
namespace Sword2 {