ScummVM API documentation
screen.h
1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 #ifndef SCI_GRAPHICS_SCREEN_H
23 #define SCI_GRAPHICS_SCREEN_H
24 
25 #include "sci/sci.h"
26 #include "sci/graphics/helpers.h"
27 #include "sci/graphics/view.h"
28 
29 #include "graphics/font.h"
30 #include "graphics/sjis.h"
31 #include "graphics/korfont.h"
32 #include "graphics/pixelformat.h"
33 
34 #include "common/rendermode.h"
35 
36 namespace Sci {
37 
38 enum {
39  SCI_SCREEN_UPSCALEDMAXHEIGHT = 200,
40  SCI_SCREEN_UPSCALEDMAXWIDTH = 320
41 };
42 
43 enum GfxScreenUpscaledMode {
44  GFX_SCREEN_UPSCALED_DISABLED = 0,
45  GFX_SCREEN_UPSCALED_480x300 = 1,
46  GFX_SCREEN_UPSCALED_640x400 = 2
47 };
48 
49 enum GfxScreenMasks {
50  GFX_SCREEN_MASK_VISUAL = 1,
51  GFX_SCREEN_MASK_PRIORITY = 2,
52  GFX_SCREEN_MASK_CONTROL = 4,
53  GFX_SCREEN_MASK_ALL = GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY|GFX_SCREEN_MASK_CONTROL
54 };
55 
56 enum {
57  DITHERED_BG_COLORS_SIZE = 256
58 };
59 
60 class GfxDriver;
61 
70 class GfxScreen {
71 public:
72  GfxScreen(ResourceManager *resMan, Common::RenderMode renderMode);
73  ~GfxScreen();
74 
75  uint16 getWidth() { return _width; }
76  uint16 getHeight() { return _height; }
77  uint16 getScriptWidth() { return _scriptWidth; }
78  uint16 getScriptHeight() { return _scriptHeight; }
79  uint16 getDisplayWidth() { return _displayWidth; }
80  uint16 getDisplayHeight() { return _displayHeight; }
81  byte getColorWhite() { return _colorWhite; }
82  byte getColorDefaultVectorData() { return _colorDefaultVectorData; }
83 
84  void clearForRestoreGame();
85  void copyToScreen();
86  void kernelSyncWithFramebuffer();
87  void copyRectToScreen(const Common::Rect &rect);
88  void copyHiResRectToScreen(const byte *srcBuffer, int pitch, int x, int y, int w, int h, const byte *colorMap);
89  void copyRectToScreen(const Common::Rect &rect, int16 x, int16 y);
90 
91  // functions to manipulate a backup copy of the screen (for transitions)
92  void bakCreateBackup();
93  void bakCopyRectToScreen(const Common::Rect &rect, int16 x, int16 y);
94  void bakDiscard();
95 
96  // video frame displaying
97  void copyVideoFrameToScreen(const byte *buffer, int pitch, const Common::Rect &rect);
98 
99  // Vector drawing
100 private:
101  void vectorPutLinePixel(int16 x, int16 y, byte drawMask, byte color, byte priority, byte control);
102  void vectorPutLinePixel480x300(int16 x, int16 y, byte drawMask, byte color, byte priority, byte control);
103 
104 public:
105  void vectorAdjustLineCoordinates(int16 *left, int16 *top, int16 *right, int16 *bottom, byte drawMask, byte color, byte priority, byte control);
106  byte vectorIsFillMatch(int16 x, int16 y, byte screenMask, byte checkForColor, byte checkForPriority, byte checkForControl, bool isEGA);
107 
108  byte getDrawingMask(byte color, byte prio, byte control);
109  void drawLine(Common::Point startPoint, Common::Point endPoint, byte color, byte prio, byte control);
110  void drawLine(int16 left, int16 top, int16 right, int16 bottom, byte color, byte prio, byte control) {
111  drawLine(Common::Point(left, top), Common::Point(right, bottom), color, prio, control);
112  }
113 
114  GfxScreenUpscaledMode getUpscaledHires() const {
115  return _upscaledHires;
116  }
117 
118  bool isUnditheringEnabled() const {
119  return _unditheringEnabled;
120  }
121  void enableUndithering(bool flag);
122 
123  void putMacChar(const Graphics::Font *commonFont, int16 x, int16 y, uint16 chr, byte color);
124  void putKanjiChar(Graphics::FontSJIS *commonFont, int16 x, int16 y, uint16 chr, byte color);
125  void putHangulChar(Graphics::FontKorean *commonFont, int16 x, int16 y, uint16 chr, byte color);
126 
127  int bitsGetDataSize(Common::Rect rect, byte mask);
128  void bitsSave(Common::Rect rect, byte mask, byte *memoryPtr);
129  void bitsGetRect(const byte *memoryPtr, Common::Rect *destRect);
130  void bitsRestore(const byte *memoryPtr);
131 
132  void scale2x(const SciSpan<const byte> &src, SciSpan<byte> &dst, int16 srcWidth, int16 srcHeight, byte bytesPerPixel = 1);
133 
134  void adjustToUpscaledCoordinates(int16 &y, int16 &x);
135  void adjustBackUpscaledCoordinates(int16 &y, int16 &x);
136 
137  void dither(bool addToFlag);
138 
139  // Force a color combination as a dithered color
140  void ditherForceDitheredColor(byte color);
141  int16 *unditherGetDitheredBgColors();
142 
143  void debugShowMap(int mapNo);
144 
145  int _picNotValid; // possible values 0, 1 and 2
146  int _picNotValidSci11; // another variable that is used by kPicNotValid in sci1.1
147 
148  int16 kernelPicNotValid(int16 newPicNotValid);
149  void kernelShakeScreen(uint16 shakeCount, uint16 direction);
150 
151  void setFontIsUpscaled(bool isUpscaled) { _fontIsUpscaled = isUpscaled; }
152  bool fontIsUpscaled() const { return _fontIsUpscaled; }
153 
154  void grabPalette(byte *buffer, uint start, uint num) const;
155  void setPalette(const byte *buffer, uint start, uint num, bool update = true);
156 
157  byte getCurPaletteMapValue() const { return _curPaletteMapValue; }
158  void setCurPaletteMapValue(byte val) { _curPaletteMapValue = val; }
159  void setPaletteMods(const PaletteMod *mods, unsigned int count);
160  bool paletteModsEnabled() const { return _paletteModsEnabled; }
161 
162  GfxDriver *gfxDriver() const { return _gfxDrv; }
163 
164 private:
165  uint16 _width;
166  uint16 _height;
167  uint _pixels;
168  uint16 _scriptWidth;
169  uint16 _scriptHeight;
170  uint16 _displayWidth;
171  uint16 _displayHeight;
172  uint _displayPixels;
173 
174  byte _colorWhite;
175  byte _colorDefaultVectorData;
176 
177  void bitsRestoreScreen(Common::Rect rect, const byte *&memoryPtr, byte *screen, uint16 screenWidth);
178  void bitsRestoreDisplayScreen(Common::Rect rect, const byte *&memoryPtr, byte *screen);
179  void bitsSaveScreen(Common::Rect rect, const byte *screen, uint16 screenWidth, byte *&memoryPtr);
180  void bitsSaveDisplayScreen(Common::Rect rect, const byte *screen, byte *&memoryPtr);
181 
182  void setShakePos(uint16 shakeXOffset, uint16 shakeYOffset);
183 
187  bool _unditheringEnabled;
188  int16 _ditheredPicColors[DITHERED_BG_COLORS_SIZE];
189 
190  // These screens have the real resolution of the game engine (320x200 for
191  // SCI0/SCI1/SCI11 PC games, other resolutions on Mac). SCI0 games will be
192  // dithered in here at any time.
193  byte *_visualScreen;
194  byte *_priorityScreen;
195  byte *_controlScreen;
196 
202  byte *_displayScreen;
203  Graphics::Surface _displayScreenSurface;
204 
209  GfxDriver *_gfxDrv;
210 
211  // For RGB per-view/pic palette mods
212  byte *_paletteMapScreen;
213  byte _curPaletteMapValue;
214  PaletteMod _paletteMods[256];
215  bool _paletteModsEnabled;
216 
217  byte *_backupScreen; // for bak* functions
218 
219  void displayRect(const Common::Rect &rect, int x, int y);
220 
221  ResourceManager *_resMan;
222 
227  byte *_activeScreen;
228 
233  GfxScreenUpscaledMode _upscaledHires;
234 
245  bool _activeHiresView;
246 
250  byte *_hiresGlyphBuffer;
251 
256  int16 _upscaledHeightMapping[SCI_SCREEN_UPSCALEDMAXHEIGHT + 1];
257  int16 _upscaledWidthMapping[SCI_SCREEN_UPSCALEDMAXWIDTH + 1];
258 
263  bool _fontIsUpscaled;
264 
265 
266  // pixel related code, in header so that it can be inlined for performance
267 public:
268  void putPixel(int16 x, int16 y, byte drawMask, byte color, byte priority, byte control) {
269  if (_upscaledHires == GFX_SCREEN_UPSCALED_480x300) {
270  putPixel480x300(x, y, drawMask, color, priority, control);
271  return;
272  }
273 
274  // Set pixel for visual, priority and control map directly, those are not upscaled
275  const int offset = y * _width + x;
276 
277  if (drawMask & GFX_SCREEN_MASK_VISUAL) {
278  _visualScreen[offset] = color;
279  if (_paletteMapScreen)
280  _paletteMapScreen[offset] = _curPaletteMapValue;
281 
282  switch (_upscaledHires) {
283  case GFX_SCREEN_UPSCALED_DISABLED:
284  _displayScreen[offset] = color;
285  break;
286 
287  case GFX_SCREEN_UPSCALED_640x400:
288  putScaledPixelOnDisplay(x, y, color);
289  break;
290  default:
291  break;
292  }
293  }
294  if (drawMask & GFX_SCREEN_MASK_PRIORITY) {
295  _priorityScreen[offset] = priority;
296  }
297  if (drawMask & GFX_SCREEN_MASK_CONTROL) {
298  _controlScreen[offset] = control;
299  }
300  }
301 
302  void putPixel480x300(int16 x, int16 y, byte drawMask, byte color, byte priority, byte control) {
303  const int offset = ((y * 3) / 2 * _width) + ((x * 3) / 2);
304 
305  // All maps are upscaled
306  // TODO: figure out, what Sierra exactly did on Mac for these games
307  if (drawMask & GFX_SCREEN_MASK_VISUAL) {
308  putPixel480x300Worker(x, y, offset, _visualScreen, color);
309  putPixel480x300Worker(x, y, offset, _displayScreen, color);
310  }
311  if (drawMask & GFX_SCREEN_MASK_PRIORITY) {
312  putPixel480x300Worker(x, y, offset, _priorityScreen, priority);
313  }
314  if (drawMask & GFX_SCREEN_MASK_CONTROL) {
315  putPixel480x300Worker(x, y, offset, _controlScreen, control);
316  }
317  }
318  void putPixel480x300Worker(int16 x, int16 y, int offset, byte *screen, byte byteToSet) {
319  screen[offset] = byteToSet;
320  if (x & 1)
321  screen[offset + 1] = byteToSet;
322  if (y & 1)
323  screen[offset + _width] = byteToSet;
324  if ((x & 1) && (y & 1))
325  screen[offset + _width + 1] = byteToSet;
326  }
327 
328  // This is called from vector drawing to put a pixel at a certain location
329  void vectorPutPixel(int16 x, int16 y, byte drawMask, byte color, byte priority, byte control) {
330  switch (_upscaledHires) {
331  case GFX_SCREEN_UPSCALED_640x400:
332  // For regular upscaled modes forward to the regular putPixel
333  putPixel(x, y, drawMask, color, priority, control);
334  return;
335  break;
336 
337  default:
338  break;
339  }
340 
341  // For non-upscaled mode and 480x300 Mac put pixels directly
342  int offset = y * _width + x;
343 
344  if (drawMask & GFX_SCREEN_MASK_VISUAL) {
345  _visualScreen[offset] = color;
346  _displayScreen[offset] = color;
347  if (_paletteMapScreen)
348  _paletteMapScreen[offset] = _curPaletteMapValue;
349 
350  }
351  if (drawMask & GFX_SCREEN_MASK_PRIORITY) {
352  _priorityScreen[offset] = priority;
353  }
354  if (drawMask & GFX_SCREEN_MASK_CONTROL) {
355  _controlScreen[offset] = control;
356  }
357  }
358 
364  void putPixelOnDisplay(int16 x, int16 y, byte color) {
365  int offset = y * _displayWidth + x;
366  _displayScreen[offset] = color;
367  }
368 
369  // Upscales a pixel and puts it on display screen only
370  void putScaledPixelOnDisplay(int16 x, int16 y, byte color) {
371  int displayOffset = 0;
372 
373  switch (_upscaledHires) {
374  case GFX_SCREEN_UPSCALED_640x400:
375  displayOffset = (y * 2) * _displayWidth + x * 2; // straight 1 pixel -> 2 mapping
376 
377  _displayScreen[displayOffset] = color;
378  _displayScreen[displayOffset + 1] = color;
379  _displayScreen[displayOffset + _displayWidth] = color;
380  _displayScreen[displayOffset + _displayWidth + 1] = color;
381  break;
382 
383  default:
384  break;
385  }
386  }
387 
393  void putFontPixel(int16 startingY, int16 x, int16 y, byte color) {
394  int16 actualY = startingY + y;
395  if (_fontIsUpscaled) {
396  // Do not scale ourselves, but put it on the display directly
397  putPixelOnDisplay(x, actualY, color);
398  } else {
399  if (_upscaledHires == GFX_SCREEN_UPSCALED_480x300) {
400  putPixel480x300(x, actualY, GFX_SCREEN_MASK_VISUAL, color, 0, 0);
401  return;
402  }
403 
404  int offset = actualY * _width + x;
405 
406  _visualScreen[offset] = color;
407  switch (_upscaledHires) {
408  case GFX_SCREEN_UPSCALED_DISABLED:
409  _displayScreen[offset] = color;
410  break;
411  case GFX_SCREEN_UPSCALED_640x400: {
412  // to 1-> 4 pixels upscaling for all of those, so that fonts won't look weird
413  int displayOffset = (_upscaledHeightMapping[startingY] + y * 2) * _displayWidth + x * 2;
414  _displayScreen[displayOffset] = color;
415  _displayScreen[displayOffset + 1] = color;
416  displayOffset += _displayWidth;
417  _displayScreen[displayOffset] = color;
418  _displayScreen[displayOffset + 1] = color;
419  break;
420  }
421  default:
422  putScaledPixelOnDisplay(x, actualY, color);
423  break;
424  }
425  }
426  }
427 
428  byte getPixel(byte *screen, int16 x, int16 y) {
429  switch (_upscaledHires) {
430  case GFX_SCREEN_UPSCALED_480x300: {
431  int offset = ((y * 3) / 2) * _width + ((y * 3) / 2);
432 
433  return screen[offset];
434  break;
435  }
436  default:
437  break;
438  }
439  return screen[y * _width + x];
440  }
441 
442  byte getVisual(int16 x, int16 y) {
443  return getPixel(_visualScreen, x, y);
444  }
445  byte getPriority(int16 x, int16 y) {
446  return getPixel(_priorityScreen, x, y);
447  }
448  byte getControl(int16 x, int16 y) {
449  return getPixel(_controlScreen, x, y);
450  }
451 
452  // Vector related public code - in here, so that it can be inlined
453  byte vectorGetPixel(byte *screen, int16 x, int16 y) {
454  return screen[y * _width + x];
455  }
456 
457  byte vectorGetVisual(int16 x, int16 y) {
458  return vectorGetPixel(_visualScreen, x, y);
459  }
460  byte vectorGetPriority(int16 x, int16 y) {
461  return vectorGetPixel(_priorityScreen, x, y);
462  }
463  byte vectorGetControl(int16 x, int16 y) {
464  return vectorGetPixel(_controlScreen, x, y);
465  }
466 
467  void vectorAdjustCoordinate(int16 *x, int16 *y) {
468  switch (_upscaledHires) {
469  case GFX_SCREEN_UPSCALED_480x300:
470  *x = (*x * 3) / 2;
471  *y = (*y * 3) / 2;
472  break;
473  default:
474  break;
475  }
476  }
477 
478  bool hasActiveHiresView() const { return _activeHiresView; }
479  void toggleActiveHiresView(bool toggle) { _activeHiresView = toggle; }
480 };
481 
482 } // End of namespace Sci
483 
484 #endif // SCI_GRAPHICS_SCREEN_H
void putPixelOnDisplay(int16 x, int16 y, byte color)
Definition: screen.h:364
Definition: font.h:83
Definition: surface.h:67
void putFontPixel(int16 startingY, int16 x, int16 y, byte color)
Definition: screen.h:393
Definition: korfont.h:42
RenderMode
Definition: rendermode.h:48
Definition: rect.h:144
Definition: resource.h:327
Definition: gfxdrivers.h:37
Definition: rect.h:45
Definition: console.h:28
Definition: helpers.h:269
Definition: screen.h:70