/* ScummVM - Scumm Interpreter * Copyright (C) 2001 Ludvig Strigeus * Copyright (C) 2001-2004 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 GFX_H #define GFX_H #include "common/rect.h" #include "graphics/surface.h" namespace Scumm { class ScummEngine; /** Camera modes */ enum { kNormalCameraMode = 1, kFollowActorCameraMode = 2, kPanningCameraMode = 3 }; /** Camera state data */ struct CameraData { Common::Point _cur; Common::Point _dest; Common::Point _accel; Common::Point _last; int _leftTrigger, _rightTrigger; byte _follows, _mode; bool _movingToActor; }; /** Virtual screen identifiers */ enum VirtScreenNumber { kMainVirtScreen = 0, // The 'stage' kTextVirtScreen = 1, // In V1-V3 games: the area where text is printed kVerbVirtScreen = 2, // The verb area kUnkVirtScreen = 3 // ?? Not sure what this one is good for... }; /** * In all Scumm games, one to four virtual screen (or 'windows') together make * up the content of the actual screen. Thinking of virtual screens as fixed * size, fixed location windows might help understanding them. Typical, in all * scumm games there is either one single virtual screen covering the entire * real screen (mostly in all newer games, e.g. Sam & Max, and all V7+ games). * The classic setup consists of three virtual screens: one at the top of the * screen, where all conversation texts are printed; then the main one (which * I like calling 'the stage', since all the actors are doing their stuff * there), and finally the lower part of the real screen is taken up by the * verb area. * Finally, in V5 games and some V6 games, it's almost the same as in the * original games, except that there is no separate conversation area. * * If you now wonder what the last screen is/was good for: I am not 100% sure, * but it appears that it was used by the original engine to display stuff * like the pause message, or questions ("Do you really want to restart?"). * It seems that it is not used at all by ScummVM, so we probably could just * get rid of it and save a couple kilobytes of RAM. * * Each of these virtual screens has a fixed number or id (see also * \ref VirtScreenNumber). */ struct VirtScreen : Graphics::Surface { /** * The unique id of this screen (corresponds to its position in the * ScummEngine:virtscr array). */ VirtScreenNumber number; /** * Vertical position of the virtual screen. Tells how much the virtual * screen is shifted along the y axis relative to the real screen. * If you wonder why there is no horizontal position: there is none, * because all virtual screens are always exactly as wide as the * real screen. This might change in the future to allow smooth * horizontal scrolling in V7-V8 games. */ uint16 topline; /** * Horizontal scroll offset, tells how far the screen is scrolled to the * right. Only used for the main screen. After all, verbs and the * conversation text box don't have to scroll. */ uint16 xstart; /** * Flag indicating which tells whether this screen has a back buffer or * not. This is yet another feature which is only used by the main screen. * Strictly spoken one could remove this variable and replace checks * on it with checks on backBuf. But since some code needs to temporarily * disable the backBuf (so it can abuse drawBitmap; see drawVerbBitmap() * and useIm01Cursor()), we keep it (at least for now). */ bool hasTwoBuffers; /** * Pointer to the screen's back buffer, if it has one (see also * the hasTwoBuffers member). * The backBuf is used by drawBitmap to store the background graphics of * the active room. This eases redrawing: whenever a portion of the screen * has to be redrawn, first a copy from the backBuf content to screenPtr is * performed. Then, any objects/actors in that area are redrawn atop that. */ byte *backBuf; /** * Array containing for each visible strip of this virtual screen the * coordinate at which the dirty region of that strip starts. * 't' stands for 'top' - the top coordinate of the dirty region. * This together with bdirty is used to do efficient redrawing of * the screen. */ uint16 tdirty[80 + 1]; /** * Array containing for each visible strip of this virtual screen the * coordinate at which the dirty region of that strip end. * 'b' stands for 'bottom' - the bottom coordinate of the dirty region. * This together with tdirty is used to do efficient redrawing of * the screen. */ uint16 bdirty[80 + 1]; /** * Convenience method to set the whole tdirty and bdirty arrays to one * specific value each. This is mostly used to mark every as dirty in * a single step, like so: * vs->setDirtyRange(0, vs->height); * or to mark everything as clean, like so: * vs->setDirtyRange(0, 0); */ void setDirtyRange(int top, int bottom) { for (int i = 0; i < 80 + 1; i++) { tdirty[i] = top; bdirty[i] = bottom; } } byte *getPixels(int x, int y) const { return (byte *)pixels + xstart + y * pitch + x; } byte *getBackPixels(int x, int y) const { return (byte *)backBuf + xstart + y * pitch + x; } }; /** Palette cycles */ struct ColorCycle { uint16 delay; uint16 counter; uint16 flags; byte start; byte end; }; /** BlastObjects to draw */ struct BlastObject { uint16 number; Common::Rect rect; uint16 scaleX, scaleY; uint16 image; uint16 mode; }; /** Bomp graphics data, used as parameter to ScummEngine::drawBomp. */ struct BompDrawData { Graphics::Surface dst; int x, y; byte scale_x, scale_y; const byte *dataptr; int srcwidth, srcheight; uint16 shadowMode; int32 scaleRight, scaleBottom; byte *scalingXPtr, *scalingYPtr; byte *maskPtr; BompDrawData() { memset(this, 0, sizeof(*this)); } }; struct StripTable; class Gdi { friend class ScummEngine; // Mostly for the code in saveload.cpp ... ScummEngine *_vm; public: int _numZBuffer; int _imgBufOffs[8]; int32 _numStrips; byte _C64Colors[4]; Gdi(ScummEngine *vm); Graphics::Surface _textSurface; protected: byte *_compositeBuf; byte *_roomPalette; byte _decomp_shr, _decomp_mask; byte _transparentColor; uint32 _vertStripNextInc; bool _zbufferDisabled; byte _C64CharMap[2048], _C64ObjectMap[2048], _C64PicMap[4096], _C64ColorMap[4096]; byte _C64MaskMap[4096], _C64MaskChar[4096]; bool _C64ObjectMode; /* Bitmap decompressors */ bool decompressBitmap(byte *dst, int dstPitch, const byte *src, int numLinesToProcess); void drawStripEGA(byte *dst, int dstPitch, const byte *src, int height) const; void drawStripC64Object(byte *dst, int dstPitch, int stripnr, int width, int height); void drawStripC64Background(byte *dst, int dstPitch, int stripnr, int height); void drawStripComplex(byte *dst, int dstPitch, const byte *src, int height, const bool transpCheck) const; void drawStripBasicH(byte *dst, int dstPitch, const byte *src, int height, const bool transpCheck) const; void drawStripBasicV(byte *dst, int dstPitch, const byte *src, int height, const bool transpCheck) const; void unkDecode7(byte *dst, int dstPitch, const byte *src, int height) const; void unkDecode8(byte *dst, int dstPitch, const byte *src, int height) const; void unkDecode9(byte *dst, int dstPitch, const byte *src, int height) const; void unkDecode10(byte *dst, int dstPitch, const byte *src, int height) const; void unkDecode11(byte *dst, int dstPitch, const byte *src, int height) const; void drawStrip3DO(byte *dst, int dstPitch, const byte *src, int height, const bool transpCheck) const; void drawStripHE(byte *dst, int dstPitch, const byte *src, int w, int height, const bool transpCheck) const; /* Mask decompressors */ void drawStripC64Mask(byte *dst, int stripnr, int width, int height) const; void decompressMaskImgOr(byte *dst, const byte *src, int height) const; void decompressMaskImg(byte *dst, const byte *src, int height) const; /* Misc */ void drawStripToScreen(VirtScreen *vs, int x, int w, int t, int b); void updateDirtyScreen(VirtScreen *vs); byte *getMaskBuffer(int x, int y, int z); int getZPlanes(const byte *smap_ptr, const byte *zplane_list[9], bool bmapImage) const; void drawBitmapV2Helper(const byte *ptr, VirtScreen *vs, int x, int y, const int width, const int height, int stripnr, int numstrip, StripTable *table); public: void init(); void drawBitmap(const byte *ptr, VirtScreen *vs, int x, int y, const int width, const int height, int stripnr, int numstrip, byte flag, StripTable *table = 0); StripTable *generateStripTable(const byte *src, int width, int height, StripTable *table) const; void decodeC64Gfx(const byte *src, byte *dst, int size) const; void drawBMAPBg(const byte *ptr, VirtScreen *vs, int startstrip, int width); void drawBMAPObject(const byte *ptr, VirtScreen *vs, int obj, int x, int y, int w, int h); void copyWizImage(uint8 *dst, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect); void decompressWizImage(uint8 *dst, int dstPitch, const Common::Rect &dstRect, const uint8 *src, const Common::Rect &srcRect); void copyAuxImage(uint8 *dst1, uint8 *dst2, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect); void decompressAuxImage(uint8 *dst1, uint8 *dst2, int dstPitch, const Common::Rect &dstRect, const uint8 *src, const Common::Rect &srcRect); void copyVirtScreenBuffers(const Common::Rect &rect); void disableZBuffer() { _zbufferDisabled = true; } void enableZBuffer() { _zbufferDisabled = false; } void resetBackground(int top, int bottom, int strip); enum DrawBitmapFlags { dbAllowMaskOr = 1, dbDrawMaskOnAll = 2 }; }; // We now have mostly working smooth scrolling code in place for V7+ games // (i.e. The Dig, Full Throttle and COMI). It seems to work very well so far. // One area which still may need some work are the AKOS codecs (except for // codec 1, which I already updated): their masking code may need adjustments, // similar to the treatment codec 1 received. // // To understand how we achieve smooth scrolling, first note that with it, the // virtual screen strips don't match the display screen strips anymore. To // overcome that problem, we simply use a screen pitch that is 8 pixel wider // than the actual screen width, and always draw one strip more than needed to // the backbuf (of course we have to treat the right border seperately). This #define V7_SMOOTH_SCROLLING_HACK } // End of namespace Scumm #endif