added & renamed some constants; fixed & added some doxygen comments; cleaned up the dirty screen code a bit (this should also fix a bug in V1/V2 games where part of the screen was not redrawn properly)

svn-id: r12118
This commit is contained in:
Max Horn 2004-01-03 21:22:07 +00:00
parent d49082065a
commit 34db2e793a
5 changed files with 86 additions and 78 deletions

View File

@ -29,7 +29,7 @@ namespace Scumm {
void ScummEngine::setCameraAtEx(int at) {
if (!(_features & GF_NEW_CAMERA)) {
camera._mode = CM_NORMAL;
camera._mode = kNormalCameraMode;
camera._cur.x = at;
setCameraAt(at, 0);
camera._movingToActor = false;
@ -37,7 +37,7 @@ void ScummEngine::setCameraAtEx(int at) {
}
void ScummEngine::setCameraAt(int pos_x, int pos_y) {
if (camera._mode != CM_FOLLOW_ACTOR || abs(pos_x - camera._cur.x) > (_screenWidth / 2)) {
if (camera._mode != kFollowActorCameraMode || abs(pos_x - camera._cur.x) > (_screenWidth / 2)) {
camera._cur.x = pos_x;
}
camera._dest.x = pos_x;
@ -89,12 +89,12 @@ void ScummEngine::setCameraFollows(Actor *a) {
int t, i;
camera._mode = CM_FOLLOW_ACTOR;
camera._mode = kFollowActorCameraMode;
camera._follows = a->number;
if (!a->isInCurrentRoom()) {
startScene(a->getRoom(), 0, 0);
camera._mode = CM_FOLLOW_ACTOR;
camera._mode = kFollowActorCameraMode;
camera._cur.x = a->_pos.x;
setCameraAt(camera._cur.x, 0);
}
@ -174,7 +174,7 @@ void ScummEngine::moveCamera() {
return;
}
if (camera._mode == CM_FOLLOW_ACTOR) {
if (camera._mode == kFollowActorCameraMode) {
a = derefActor(camera._follows, "moveCamera");
actorx = a->_pos.x;
@ -353,7 +353,7 @@ void ScummEngine::cameraMoved() {
void ScummEngine::panCameraTo(int x, int y) {
camera._dest.x = x;
camera._mode = CM_PANNING;
camera._mode = kPanningCameraMode;
camera._movingToActor = false;
}
@ -373,7 +373,7 @@ void ScummEngine::actorFollowCamera(int act) {
/*
// MI1 compatibilty
if (act == 0) {
camera._mode = CM_NORMAL;
camera._mode = kNormalCameraMode;
camera._follows = 0;
camera._movingToActor = false;
return;

View File

@ -250,9 +250,9 @@ void ScummEngine::initScreens(int a, int b, int w, int h) {
initVirtScreen(3, 0, 80, _screenWidth, 13, false, false);
}
}
initVirtScreen(0, 0, b, _screenWidth, h - b, true, true);
initVirtScreen(1, 0, 0, _screenWidth, b, false, false);
initVirtScreen(2, 0, h, _screenWidth, _screenHeight - h, false, false);
initVirtScreen(kMainVirtScreen, 0, b, _screenWidth, h - b, true, true);
initVirtScreen(kTextVirtScreen, 0, 0, _screenWidth, b, false, false);
initVirtScreen(kVerbVirtScreen, 0, h, _screenWidth, _screenHeight - h, false, false);
_screenB = b;
_screenH = h;
@ -371,32 +371,34 @@ void ScummEngine::updateDirtyRect(int virt, int left, int right, int top, int bo
}
}
/**
* Update all dirty screen areas. This method blits all of the internal engine
* graphics to the actual display, as needed. In addition, the 'shaking'
* code in the backend is controlled from here.
*/
void ScummEngine::drawDirtyScreenParts() {
int i;
VirtScreen *vs;
byte *src;
updateDirtyScreen(2);
// Update verbs
updateDirtyScreen(kVerbVirtScreen);
// In V1-V3, update the conversation area (at the top of the screen)
if (_version <= 3)
updateDirtyScreen(1);
updateDirtyScreen(kTextVirtScreen);
if (camera._last.x == camera._cur.x && (camera._last.y == camera._cur.y || !(_features & GF_NEW_CAMERA))) {
updateDirtyScreen(0);
// Update game area ("stage")
if (camera._last.x != camera._cur.x || (_features & GF_NEW_CAMERA && (camera._cur.y != camera._last.y))) {
// Camera moved: redraw everything
// Small side note: most of our GFX code relies on this identity:
// gdi._numStrips * 8 == _screenWidth == vs->width
VirtScreen *vs = &virtscr[kMainVirtScreen];
gdi.drawStripToScreen(vs, 0, vs->width, 0, vs->height);
vs->setDirtyRange(vs->height, 0);
} else {
vs = &virtscr[0];
src = vs->screenPtr + vs->xstart + _screenTop * _screenWidth;
_system->copy_rect(src, _screenWidth, 0, vs->topline, _screenWidth, vs->height - _screenTop);
for (i = 0; i < gdi._numStrips; i++) {
vs->tdirty[i] = vs->height;
vs->bdirty[i] = 0;
}
updateDirtyScreen(kMainVirtScreen);
}
/* Handle shaking */
// Handle shaking
if (_shakeEnabled) {
_shakeFrame = (_shakeFrame + 1) & (NUM_SHAKE_POSITIONS - 1);
_shakeFrame = (_shakeFrame + 1) % NUM_SHAKE_POSITIONS;
_system->set_shake_pos(shake_positions[_shakeFrame]);
} else if (!_shakeEnabled &&_shakeFrame != 0) {
_shakeFrame = 0;
@ -409,44 +411,38 @@ void ScummEngine::updateDirtyScreen(int slot) {
}
/**
* Blit the data from the given VirtScreen to the display. If the camera moved,
* Blit the dirty data from the given VirtScreen to the display. If the camera moved,
* a full blit is done, otherwise only the visible dirty areas are updated.
*/
void Gdi::updateDirtyScreen(VirtScreen *vs) {
// Do nothing for unused virtual screens
if (vs->height == 0)
return;
if (_vm->_features & GF_NEW_CAMERA && (_vm->camera._cur.y != _vm->camera._last.y)) {
drawStripToScreen(vs, 0, _numStrips * 8, 0, vs->height);
} else {
int i;
int start, w, top, bottom;
int i;
int w = 8;
int start = 0;
w = 8;
start = 0;
for (i = 0; i < _numStrips; i++) {
bottom = vs->bdirty[i];
if (bottom) {
top = vs->tdirty[i];
vs->tdirty[i] = vs->height;
vs->bdirty[i] = 0;
if (i != (_numStrips - 1) && vs->bdirty[i + 1] == bottom && vs->tdirty[i + 1] == top) {
// Simple optimizations: if two or more neighbouring strips form one bigger rectangle,
// blit them all at once.
w += 8;
continue;
}
// handle vertically scrolling rooms
if (_vm->_features & GF_NEW_CAMERA)
drawStripToScreen(vs, start * 8, w, 0, vs->height);
else
drawStripToScreen(vs, start * 8, w, top, bottom);
w = 8;
for (i = 0; i < _numStrips; i++) {
if (vs->bdirty[i]) {
const int bottom = vs->bdirty[i];
const int top = vs->tdirty[i];
vs->tdirty[i] = vs->height;
vs->bdirty[i] = 0;
if (i != (_numStrips - 1) && vs->bdirty[i + 1] == bottom && vs->tdirty[i + 1] == top) {
// Simple optimizations: if two or more neighbouring strips form one bigger rectangle,
// blit them all at once.
w += 8;
continue;
}
start = i + 1;
// handle vertically scrolling rooms
if (_vm->_features & GF_NEW_CAMERA)
drawStripToScreen(vs, start * 8, w, 0, vs->height);
else
drawStripToScreen(vs, start * 8, w, top, bottom);
w = 8;
}
start = i + 1;
}
}
@ -2257,7 +2253,7 @@ void ScummEngine::fadeOut(int effect) {
case 129:
// Just blit screen 0 to the display (i.e. display will be black)
vs->setDirtyRange(0, vs->height);
updateDirtyScreen(0);
updateDirtyScreen(kMainVirtScreen);
break;
case 134:
dissolveEffect(1, 1);
@ -2341,7 +2337,7 @@ void ScummEngine::transitionEffect(int a) {
else
virtscr[0].bdirty[l] = (b + 1) * 8;
}
updateDirtyScreen(0);
updateDirtyScreen(kMainVirtScreen);
}
for (i = 0; i < 16; i++)

View File

@ -29,13 +29,15 @@ namespace Scumm {
class ScummEngine;
enum { /** Camera modes */
CM_NORMAL = 1,
CM_FOLLOW_ACTOR = 2,
CM_PANNING = 3
/** Camera modes */
enum {
kNormalCameraMode = 1,
kFollowActorCameraMode = 2,
kPanningCameraMode = 3
};
struct CameraData { /** Camera state data */
/** Camera state data */
struct CameraData {
Common::Point _cur;
Common::Point _dest;
Common::Point _accel;
@ -45,7 +47,15 @@ struct CameraData { /** Camera state data */
bool _movingToActor;
};
struct VirtScreen { /** Virtual screen areas */
/** Virtual screen identifiers */
enum {
kMainVirtScreen = 0, // The 'stage'
kTextVirtScreen = 1, // In V1-V3 games: the area where text is printed
kVerbVirtScreen = 2 // The verb area
};
/** Virtual screen areas */
struct VirtScreen {
int number;
uint16 topline;
uint16 width, height;
@ -66,7 +76,8 @@ struct VirtScreen { /** Virtual screen areas */
}
};
struct ColorCycle { /** Palette cycles */
/** Palette cycles */
struct ColorCycle {
uint16 delay;
uint16 counter;
uint16 flags;
@ -74,7 +85,8 @@ struct ColorCycle { /** Palette cycles */
byte end;
};
struct BlastObject { /** BlastObjects to draw */
/** BlastObjects to draw */
struct BlastObject {
uint16 number;
int16 posX, posY;
uint16 width, height;
@ -190,14 +202,14 @@ public:
// to get it fixed and so that really interested parties can experiment it.
// It is NOT FIT FOR GENERAL USAGE! You have been warned.
//
// Doing this correctly will be quite some more complicated. Basically, with smooth
// scrolling, the virtual screen strips don't match the display screen strips.
// Hence we either have to draw partial strips - but that'd be rather cumbersome.
// Or the much simple (and IMHO more elegant) solution is to simply use a screen pitch
// that is 8 pixel wider than the real screen width, and always draw one strip more than
// needed to the backbuf. This will still require quite some code to be changed but
// should otherwise be relatively easy to understand, and using VirtScreen::pitch
// will actually clean up the code.
// Doing this correctly will be complicated. Basically, with smooth scrolling,
// the virtual screen strips don't match the display screen strips. Hence we
// either have to draw partial strips (but that'd be rather cumbersome). Or the
// alternative (and IMHO more elegant) solution is to simply use a screen pitch
// that is 8 pixel wider than the real screen width, and always draw one strip
// more than needed to the backbuf. This will still require quite some code to
// be changed but should otherwise be relatively easy to understand, and using
// VirtScreen::pitch will actually clean up the code.
//
// #define V7_SMOOTH_SCROLLING_HACK

View File

@ -1411,7 +1411,7 @@ void ScummEngine_v2::o2_endCutscene() {
if (_gameId == GID_MANIAC) {
camera._mode = (byte) vm.cutSceneData[3];
if (camera._mode == CM_FOLLOW_ACTOR) {
if (camera._mode == kFollowActorCameraMode) {
actorFollowCamera(VAR(VAR_EGO));
} else if (vm.cutSceneData[2] != _currentRoom) {
startScene(vm.cutSceneData[2], 0, 0);

View File

@ -2083,7 +2083,7 @@ void ScummEngine::startScene(int room, Actor *a, int objectNr) {
VAR(VAR_CAMERA_MAX_Y) = _roomHeight - (_screenHeight / 2);
setCameraAt(_screenWidth / 2, _screenHeight / 2);
} else {
camera._mode = CM_NORMAL;
camera._mode = kNormalCameraMode;
if (_version > 2)
camera._cur.x = camera._dest.x = _screenWidth / 2;
camera._cur.y = camera._dest.y = _screenHeight / 2;