1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444
|
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef SCI_GRAPHICS_FRAMEOUT_H
#define SCI_GRAPHICS_FRAMEOUT_H
#include "engines/util.h" // for initGraphics
#include "sci/event.h"
#include "sci/graphics/plane32.h"
#include "sci/graphics/screen_item32.h"
namespace Sci {
typedef Common::Array<DrawList> ScreenItemListList;
typedef Common::Array<RectList> EraseListList;
class GfxCursor32;
class GfxTransitions32;
struct PlaneShowStyle;
/**
* Frameout class, kFrameOut and relevant functions for SCI32 games.
* Roughly equivalent to GraphicsMgr in SSCI.
*/
class GfxFrameout {
friend class GfxTransitions32;
public:
GfxFrameout(SegManager *segMan, GfxPalette32 *palette, GfxTransitions32 *transitions, GfxCursor32 *cursor);
~GfxFrameout();
void clear();
void run();
/**
* Returns true if the game should render at a resolution greater than
* 320x240.
*/
inline bool isHiRes() const { return _isHiRes; }
/**
* Gets the x-resolution used by game scripts.
*/
inline int16 getScriptWidth() const { return _scriptWidth; }
/**
* Gets the y-resolution used by game scripts.
*/
inline int16 getScriptHeight() const { return _scriptHeight; }
/**
* Gets the x-resolution of the output buffer.
*/
inline int16 getScreenWidth() const { return _currentBuffer.w; }
/**
* Gets the y-resolution of the output buffer.
*/
inline int16 getScreenHeight() const { return _currentBuffer.h; }
private:
GfxCursor32 *_cursor;
GfxPalette32 *_palette;
GfxTransitions32 *_transitions;
SegManager *_segMan;
/**
* Whether or not the game should render at a resolution above 320x240.
*/
bool _isHiRes;
/**
* The resolution used by game scripts.
* @see celobj32.h comments on kLowResX/kLowResY.
*/
int16 _scriptWidth, _scriptHeight;
/**
* Determines whether the current game should be rendered in high
* resolution.
*/
bool detectHiRes() const;
#pragma mark -
#pragma mark Screen items
public:
/**
* Adds a screen item.
*/
void addScreenItem(ScreenItem &screenItem) const;
/**
* Updates a screen item.
*/
void updateScreenItem(ScreenItem &screenItem) const;
/**
* Deletes a screen item.
*/
void deleteScreenItem(ScreenItem &screenItem);
/**
* Deletes a screen item from the given plane.
*/
void deleteScreenItem(ScreenItem &screenItem, Plane &plane);
/**
* Deletes a screen item from the given plane.
*/
void deleteScreenItem(ScreenItem &screenItem, const reg_t plane);
void kernelAddScreenItem(const reg_t object);
void kernelUpdateScreenItem(const reg_t object);
void kernelDeleteScreenItem(const reg_t object);
bool kernelSetNowSeen(const reg_t screenItemObject) const;
int16 kernelObjectIntersect(const reg_t object1, const reg_t object2) const;
private:
void remapMarkRedraw();
bool getNowSeenRect(const reg_t screenItemObject, Common::Rect &result) const;
#pragma mark -
#pragma mark Planes
public:
/**
* Creates and adds a new plane to the plane list. Ownership of the passed
* object is transferred to GfxFrameout.
*
* @note This method is on Screen in SSCI, but it is only ever called on
* `GraphicsMgr.screen`.
*/
void addPlane(Plane *plane);
/**
* Deletes a plane within the current plane list.
*
* @note This method is on Screen in SSCI, but it is only ever called on
* `GraphicsMgr.screen`.
*/
void deletePlane(Plane &plane);
/**
* Deletes planes when restoring a Mac game.
*/
void deletePlanesForMacRestore();
const PlaneList &getPlanes() const {
return _planes;
}
const PlaneList &getVisiblePlanes() const {
return _visiblePlanes;
}
void kernelAddPlane(const reg_t object);
void kernelUpdatePlane(const reg_t object);
void kernelDeletePlane(const reg_t object);
void kernelMovePlaneItems(const reg_t object, const int16 deltaX, const int16 deltaY, const bool scrollPics);
int16 kernelGetHighPlanePri();
private:
/**
* The list of planes (i.e. layers) that will be rendered to the screen on
* the next call to `frameOut`.
*
* @note This field is on `GraphicsMgr.screen` in SSCI.
*/
PlaneList _planes;
/**
* Updates an existing plane with properties from the given VM object.
*/
void updatePlane(Plane &plane);
#pragma mark -
#pragma mark Pics
public:
void kernelAddPicAt(const reg_t planeObject, const GuiResourceId pictureId, const int16 pictureX, const int16 pictureY, const bool mirrorX, const bool deleteDuplicate);
#pragma mark -
#pragma mark Rendering
public:
/**
* Updates the hardware screen, no more than once per tick.
*
* @param delta An additional number of ticks that should elapse
* since the last time the screen was updated before it gets updated now.
* This is used for updating the screen within run_vm, where we normally
* expect that a call to kFrameOut will occur later during the current
* frame, but if it does not, then update the screen on the second frame
* anyway since the game is doing something bad.
*/
void updateScreen(const int delta = 0);
/**
* Resets the pixel format of the hardware surface to the given format.
*/
void setPixelFormat(const Graphics::PixelFormat &format) const {
initGraphics(_currentBuffer.w, _currentBuffer.h, &format);
}
/**
* Whether or not to throttle kFrameOut calls.
*/
bool _throttleKernelFrameOut;
/**
* Whether `palMorphFrameOut` should be used instead of `frameOut` for
* rendering. Used by `kMorphOn` to explicitly enable `palMorphFrameOut` for
* one frame.
*/
bool _palMorphIsOn;
inline const Buffer &getCurrentBuffer() const {
return _currentBuffer;
}
void kernelFrameOut(const bool showBits);
/**
* Throttles the engine as necessary to maintain 60fps output.
*/
void throttle();
/**
* Updates the internal screen buffer for the next frame. If
* `shouldShowBits` is true, also sends the buffer to hardware. If
* `eraseRect` is non-empty, it is added to the erase list for this frame.
*/
void frameOut(const bool shouldShowBits, const Common::Rect &eraseRect = Common::Rect());
/**
* TODO: Documentation
*/
void palMorphFrameOut(const int8 *styleRanges, PlaneShowStyle *showStyle);
/**
* Draws the given rect from the internal screen buffer to hardware without
* processing any other graphics updates except for cursor changes.
*/
void directFrameOut(const Common::Rect &showRect);
/**
* Redraws the game screen from the internal frame buffer to the system.
* Used after pixel format changes.
*
* @param skipRect An area of the screen that does not need to be redrawn.
*/
void redrawGameScreen(const Common::Rect &skipRect) const;
#ifdef USE_RGB_COLOR
/**
* Sends the entire internal screen buffer and palette to hardware.
*/
void resetHardware();
#endif
/**
* Modifies the raw pixel data for the next frame with new palette indexes
* based on matched style ranges.
*/
void alterVmap(const Palette &palette1, const Palette &palette2, const int8 style, const int8 *const styleRanges);
// This function is used within ScreenItem subsystem and assigned to various
// booleanish fields that seem to represent the state of the screen item
// (created, updated, deleted). In GK1/DOS, Phant1/m68k, SQ6/DOS, SQ6/Win,
// and Phant2/Win, this function simply returns 1. If you know of any
// game/environment where this function returns some value other than 1, or
// if you used to work at Sierra and can explain why this is a thing (and if
// anyone needs to care about it), please open a ticket!!
inline int getScreenCount() const {
return 1;
};
/**
* Shakes the screen.
*/
void shakeScreen(const int16 numShakes, const ShakeDirection direction);
Plane *getTopVisiblePlane();
private:
/**
* The last time the hardware screen was updated.
*/
uint32 _lastScreenUpdateTick;
/**
* State tracker to provide more accurate 60fps video throttling.
*/
uint8 _throttleState;
/**
* The internal display pixel buffer. During `frameOut`, this buffer is
* drawn into according to the draw and erase rects calculated by
* `calcLists`, then drawn out to the hardware surface according to the
* `_showList` rects (which are also calculated by `calcLists`).
*/
Buffer _currentBuffer;
/**
* When true, a change to the remap zone in the palette has occurred and
* screen items with remap data need to be redrawn.
*/
bool _remapOccurred;
/**
* A list of rectangles, in screen coordinates, that represent portions of
* the internal screen buffer that are dirty and should be drawn to the
* hardware display surface.
*
* @note This field is on `GraphicsMgr.screen` in SSCI.
*/
RectList _showList;
/**
* The amount of extra overdraw that is acceptable when merging two show
* list rectangles together into a single larger rectangle.
*
* @note This field is on `GraphicsMgr.screen` in SSCI.
*/
int _overdrawThreshold;
/**
* The list of planes that are currently drawn to the hardware display
* surface. Used to calculate differences in plane properties between the
* last frame and current frame.
*
* @note This field is on `GraphicsMgr.visibleScreen` in SSCI.
*/
PlaneList _visiblePlanes;
/**
* Calculates the location and dimensions of dirty rects over the entire
* screen for rendering the next frame. The draw and erase lists in
* `drawLists` and `eraseLists` each represent one plane on the screen.
* The optional `eraseRect` argument allows a specific area of the screen to
* be explicitly erased.
*/
void calcLists(ScreenItemListList &drawLists, EraseListList &eraseLists, const Common::Rect &eraseRect = Common::Rect());
/**
* Erases the areas in the given erase list from the visible screen buffer
* by filling them with the color from the corresponding plane. This is an
* optimisation for colored-type planes only; other plane types have to be
* redrawn from pixel data.
*/
void drawEraseList(const RectList &eraseList, const Plane &plane);
/**
* Draws all screen items from the given draw list to the visible screen
* buffer.
*/
void drawScreenItemList(const DrawList &screenItemList);
/**
* Adds a new rectangle to the list of regions to write out to the hardware.
* The provided rect may be merged into an existing rectangle to reduce the
* number of blit operations.
*/
void mergeToShowList(const Common::Rect &drawRect, RectList &showList, const int overdrawThreshold);
/**
* Sends all dirty rects from the internal frame buffer to the backend, then
* updates the hardware screen.
*/
void showBits();
/**
* Validates whether the given palette index in the style range should copy
* a color from the next palette to the source palette during a palette
* morph operation.
*/
inline bool validZeroStyle(const uint8 style, const int i) const {
if (style != 0) {
return false;
}
// TODO: Cannot check Shivers or MGDX until those executables can be
// unwrapped
switch (g_sci->getGameId()) {
case GID_KQ7:
case GID_PHANTASMAGORIA:
case GID_SQ6:
return (i > 71 && i < 104);
break;
default:
return true;
}
}
#pragma mark -
#pragma mark Mouse cursor
public:
reg_t kernelIsOnMe(const reg_t object, const Common::Point &position, const bool checkPixel) const;
private:
void updateMousePositionForRendering() const {
// In SSCI, mouse events were received via hardware interrupt, so the
// mouse cursor would always get updated immediately when the user moved
// the mouse. ScummVM must poll for mouse events from the backend
// instead, so we poll just before rendering so that the latest mouse
// position is rendered instead of whatever position it was at the last
// time kGetEvent was called. Without this, the mouse appears stuck
// during loops that do not make calls to kGetEvent, like transitions.
g_sci->getEventManager()->getSciEvent(kSciEventPeek);
}
/**
* Determines whether or not the point given by `position` is inside of the
* given screen item.
*/
bool isOnMe(const ScreenItem &screenItem, const Plane &plane, const Common::Point &position, const bool checkPixel) const;
#pragma mark -
#pragma mark Debugging
public:
void printPlaneList(Console *con) const;
void printVisiblePlaneList(Console *con) const;
void printPlaneListInternal(Console *con, const PlaneList &planeList) const;
void printPlaneItemList(Console *con, const reg_t planeObject) const;
void printVisiblePlaneItemList(Console *con, const reg_t planeObject) const;
void printPlaneItemListInternal(Console *con, const ScreenItemList &screenItemList) const;
};
} // End of namespace Sci
#endif
|