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 namespace Sci {
35 
36 enum {
37  SCI_SCREEN_UPSCALEDMAXHEIGHT = 200,
38  SCI_SCREEN_UPSCALEDMAXWIDTH = 320
39 };
40 
41 enum GfxScreenUpscaledMode {
42  GFX_SCREEN_UPSCALED_DISABLED = 0,
43  GFX_SCREEN_UPSCALED_480x300 = 1,
44  GFX_SCREEN_UPSCALED_640x400 = 2,
45  GFX_SCREEN_UPSCALED_640x440 = 3
46 };
47 
48 enum GfxScreenMasks {
49  GFX_SCREEN_MASK_VISUAL = 1,
50  GFX_SCREEN_MASK_PRIORITY = 2,
51  GFX_SCREEN_MASK_CONTROL = 4,
52  GFX_SCREEN_MASK_DISPLAY = 8, // not official sierra sci, only used internally
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 
68 class GfxScreen {
69 public:
70  GfxScreen(ResourceManager *resMan);
71  ~GfxScreen();
72 
73  uint16 getWidth() { return _width; }
74  uint16 getHeight() { return _height; }
75  uint16 getScriptWidth() { return _scriptWidth; }
76  uint16 getScriptHeight() { return _scriptHeight; }
77  uint16 getDisplayWidth() { return _displayWidth; }
78  uint16 getDisplayHeight() { return _displayHeight; }
79  byte getColorWhite() { return _colorWhite; }
80  byte getColorDefaultVectorData() { return _colorDefaultVectorData; }
81 
82  void clearForRestoreGame();
83  void copyToScreen();
84  void kernelSyncWithFramebuffer();
85  void copyRectToScreen(const Common::Rect &rect);
86  void copyDisplayRectToScreen(const Common::Rect &rect);
87  void copyRectToScreen(const Common::Rect &rect, int16 x, int16 y);
88 
89  // functions to manipulate a backup copy of the screen (for transitions)
90  void bakCreateBackup();
91  void bakCopyRectToScreen(const Common::Rect &rect, int16 x, int16 y);
92  void bakDiscard();
93 
94  // video frame displaying
95  void copyVideoFrameToScreen(const byte *buffer, int pitch, const Common::Rect &rect, bool is8bit);
96 
97  // Vector drawing
98 private:
99  void vectorPutLinePixel(int16 x, int16 y, byte drawMask, byte color, byte priority, byte control);
100  void vectorPutLinePixel480x300(int16 x, int16 y, byte drawMask, byte color, byte priority, byte control);
101 
102 public:
103  void vectorAdjustLineCoordinates(int16 *left, int16 *top, int16 *right, int16 *bottom, byte drawMask, byte color, byte priority, byte control);
104  byte vectorIsFillMatch(int16 x, int16 y, byte screenMask, byte checkForColor, byte checkForPriority, byte checkForControl, bool isEGA);
105 
106  byte getDrawingMask(byte color, byte prio, byte control);
107  void drawLine(Common::Point startPoint, Common::Point endPoint, byte color, byte prio, byte control);
108  void drawLine(int16 left, int16 top, int16 right, int16 bottom, byte color, byte prio, byte control) {
109  drawLine(Common::Point(left, top), Common::Point(right, bottom), color, prio, control);
110  }
111 
112  GfxScreenUpscaledMode getUpscaledHires() const {
113  return _upscaledHires;
114  }
115 
116  bool isUnditheringEnabled() const {
117  return _unditheringEnabled;
118  }
119  void enableUndithering(bool flag);
120 
121  void putMacChar(const Graphics::Font *commonFont, int16 x, int16 y, uint16 chr, byte color);
122  void putKanjiChar(Graphics::FontSJIS *commonFont, int16 x, int16 y, uint16 chr, byte color);
123  void putHangulChar(Graphics::FontKorean *commonFont, int16 x, int16 y, uint16 chr, byte color);
124 
125  int bitsGetDataSize(Common::Rect rect, byte mask);
126  void bitsSave(Common::Rect rect, byte mask, byte *memoryPtr);
127  void bitsGetRect(const byte *memoryPtr, Common::Rect *destRect);
128  void bitsRestore(const byte *memoryPtr);
129 
130  void scale2x(const SciSpan<const byte> &src, SciSpan<byte> &dst, int16 srcWidth, int16 srcHeight, byte bytesPerPixel = 1);
131 
132  void adjustToUpscaledCoordinates(int16 &y, int16 &x);
133  void adjustBackUpscaledCoordinates(int16 &y, int16 &x);
134 
135  void dither(bool addToFlag);
136 
137  // Force a color combination as a dithered color
138  void ditherForceDitheredColor(byte color);
139  int16 *unditherGetDitheredBgColors();
140 
141  void debugShowMap(int mapNo);
142 
143  int _picNotValid; // possible values 0, 1 and 2
144  int _picNotValidSci11; // another variable that is used by kPicNotValid in sci1.1
145 
146  int16 kernelPicNotValid(int16 newPicNotValid);
147  void kernelShakeScreen(uint16 shakeCount, uint16 direction);
148 
149  void setFontIsUpscaled(bool isUpscaled) { _fontIsUpscaled = isUpscaled; }
150  bool fontIsUpscaled() const { return _fontIsUpscaled; }
151 
152  void grabPalette(byte *buffer, uint start, uint num) const;
153  void setPalette(const byte *buffer, uint start, uint num, bool update = true);
154 
155  byte getCurPaletteMapValue() const { return _curPaletteMapValue; }
156  void setCurPaletteMapValue(byte val) { _curPaletteMapValue = val; }
157  void setPaletteMods(const PaletteMod *mods, unsigned int count);
158  bool paletteModsEnabled() const { return _paletteModsEnabled; }
159 
160 private:
161  uint16 _width;
162  uint16 _height;
163  uint _pixels;
164  uint16 _scriptWidth;
165  uint16 _scriptHeight;
166  uint16 _displayWidth;
167  uint16 _displayHeight;
168  uint _displayPixels;
169 
170  Graphics::PixelFormat _format;
171 
172  byte _colorWhite;
173  byte _colorDefaultVectorData;
174 
175  void bitsRestoreScreen(Common::Rect rect, const byte *&memoryPtr, byte *screen, uint16 screenWidth);
176  void bitsRestoreDisplayScreen(Common::Rect rect, const byte *&memoryPtr, byte *screen);
177  void bitsSaveScreen(Common::Rect rect, const byte *screen, uint16 screenWidth, byte *&memoryPtr);
178  void bitsSaveDisplayScreen(Common::Rect rect, const byte *screen, byte *&memoryPtr);
179 
180  void setShakePos(uint16 shakeXOffset, uint16 shakeYOffset);
181 
185  bool _unditheringEnabled;
186  int16 _ditheredPicColors[DITHERED_BG_COLORS_SIZE];
187 
188  // These screens have the real resolution of the game engine (320x200 for
189  // SCI0/SCI1/SCI11 PC games, other resolutions on Mac). SCI0 games will be
190  // dithered in here at any time.
191  byte *_visualScreen;
192  byte *_priorityScreen;
193  byte *_controlScreen;
194 
200  byte *_displayScreen;
201  Graphics::Surface _displayScreenSurface;
202 
203  // Screens for RGB mode support
204  byte *_displayedScreen;
205  byte *_rgbScreen;
206 
207  // For RGB per-view/pic palette mods
208  byte *_paletteMapScreen;
209  byte _curPaletteMapValue;
210  PaletteMod _paletteMods[256];
211  bool _paletteModsEnabled;
212 
213  byte *_backupScreen; // for bak* functions
214 
215  void convertToRGB(const Common::Rect &rect);
216  void displayRectRGB(const Common::Rect &rect, int x, int y);
217  void displayRect(const Common::Rect &rect, int x, int y);
218  byte *_palette;
219 
220  ResourceManager *_resMan;
221 
226  byte *_activeScreen;
227 
232  GfxScreenUpscaledMode _upscaledHires;
233 
238  int16 _upscaledHeightMapping[SCI_SCREEN_UPSCALEDMAXHEIGHT + 1];
239  int16 _upscaledWidthMapping[SCI_SCREEN_UPSCALEDMAXWIDTH + 1];
240 
245  bool _fontIsUpscaled;
246 
247 
248  // pixel related code, in header so that it can be inlined for performance
249 public:
250  void putPixel(int16 x, int16 y, byte drawMask, byte color, byte priority, byte control) {
251  if (_upscaledHires == GFX_SCREEN_UPSCALED_480x300) {
252  putPixel480x300(x, y, drawMask, color, priority, control);
253  return;
254  }
255 
256  // Set pixel for visual, priority and control map directly, those are not upscaled
257  const int offset = y * _width + x;
258 
259  if (drawMask & GFX_SCREEN_MASK_VISUAL) {
260  _visualScreen[offset] = color;
261  if (_paletteMapScreen)
262  _paletteMapScreen[offset] = _curPaletteMapValue;
263 
264  switch (_upscaledHires) {
265  case GFX_SCREEN_UPSCALED_DISABLED:
266  _displayScreen[offset] = color;
267  break;
268 
269  case GFX_SCREEN_UPSCALED_640x400:
270  case GFX_SCREEN_UPSCALED_640x440:
271  putScaledPixelOnDisplay(x, y, color);
272  break;
273  default:
274  break;
275  }
276  }
277  if (drawMask & GFX_SCREEN_MASK_PRIORITY) {
278  _priorityScreen[offset] = priority;
279  }
280  if (drawMask & GFX_SCREEN_MASK_CONTROL) {
281  _controlScreen[offset] = control;
282  }
283  }
284 
285  void putPixel480x300(int16 x, int16 y, byte drawMask, byte color, byte priority, byte control) {
286  const int offset = ((y * 3) / 2 * _width) + ((x * 3) / 2);
287 
288  // All maps are upscaled
289  // TODO: figure out, what Sierra exactly did on Mac for these games
290  if (drawMask & GFX_SCREEN_MASK_VISUAL) {
291  putPixel480x300Worker(x, y, offset, _visualScreen, color);
292  putPixel480x300Worker(x, y, offset, _displayScreen, color);
293  }
294  if (drawMask & GFX_SCREEN_MASK_PRIORITY) {
295  putPixel480x300Worker(x, y, offset, _priorityScreen, priority);
296  }
297  if (drawMask & GFX_SCREEN_MASK_CONTROL) {
298  putPixel480x300Worker(x, y, offset, _controlScreen, control);
299  }
300  }
301  void putPixel480x300Worker(int16 x, int16 y, int offset, byte *screen, byte byteToSet) {
302  screen[offset] = byteToSet;
303  if (x & 1)
304  screen[offset + 1] = byteToSet;
305  if (y & 1)
306  screen[offset + _width] = byteToSet;
307  if ((x & 1) && (y & 1))
308  screen[offset + _width + 1] = byteToSet;
309  }
310 
311  // This is called from vector drawing to put a pixel at a certain location
312  void vectorPutPixel(int16 x, int16 y, byte drawMask, byte color, byte priority, byte control) {
313  switch (_upscaledHires) {
314  case GFX_SCREEN_UPSCALED_640x400:
315  case GFX_SCREEN_UPSCALED_640x440:
316  // For regular upscaled modes forward to the regular putPixel
317  putPixel(x, y, drawMask, color, priority, control);
318  return;
319  break;
320 
321  default:
322  break;
323  }
324 
325  // For non-upscaled mode and 480x300 Mac put pixels directly
326  int offset = y * _width + x;
327 
328  if (drawMask & GFX_SCREEN_MASK_VISUAL) {
329  _visualScreen[offset] = color;
330  _displayScreen[offset] = color;
331  if (_paletteMapScreen)
332  _paletteMapScreen[offset] = _curPaletteMapValue;
333 
334  }
335  if (drawMask & GFX_SCREEN_MASK_PRIORITY) {
336  _priorityScreen[offset] = priority;
337  }
338  if (drawMask & GFX_SCREEN_MASK_CONTROL) {
339  _controlScreen[offset] = control;
340  }
341  }
342 
348  void putPixelOnDisplay(int16 x, int16 y, byte color) {
349  int offset = y * _displayWidth + x;
350  _displayScreen[offset] = color;
351  }
352 
353  // Upscales a pixel and puts it on display screen only
354  void putScaledPixelOnDisplay(int16 x, int16 y, byte color) {
355  int displayOffset = 0;
356 
357  switch (_upscaledHires) {
358  case GFX_SCREEN_UPSCALED_640x400:
359  displayOffset = (y * 2) * _displayWidth + x * 2; // straight 1 pixel -> 2 mapping
360 
361  _displayScreen[displayOffset] = color;
362  _displayScreen[displayOffset + 1] = color;
363  _displayScreen[displayOffset + _displayWidth] = color;
364  _displayScreen[displayOffset + _displayWidth + 1] = color;
365  break;
366 
367  case GFX_SCREEN_UPSCALED_640x440: {
368  int16 startY = (y * 11) / 5;
369  int16 endY = ((y + 1) * 11) / 5;
370  displayOffset = (startY * _displayWidth) + x * 2;
371 
372  for (int16 curY = startY; curY < endY; curY++) {
373  _displayScreen[displayOffset] = color;
374  _displayScreen[displayOffset + 1] = color;
375  displayOffset += _displayWidth;
376  }
377  break;
378  }
379  default:
380  break;
381  }
382  }
383 
389  void putFontPixel(int16 startingY, int16 x, int16 y, byte color) {
390  int16 actualY = startingY + y;
391  if (_fontIsUpscaled) {
392  // Do not scale ourselves, but put it on the display directly
393  putPixelOnDisplay(x, actualY, color);
394  } else {
395  if (_upscaledHires == GFX_SCREEN_UPSCALED_480x300) {
396  putPixel480x300(x, actualY, GFX_SCREEN_MASK_VISUAL, color, 0, 0);
397  return;
398  }
399 
400  int offset = actualY * _width + x;
401 
402  _visualScreen[offset] = color;
403  switch (_upscaledHires) {
404  case GFX_SCREEN_UPSCALED_DISABLED:
405  _displayScreen[offset] = color;
406  break;
407  case GFX_SCREEN_UPSCALED_640x400:
408  case GFX_SCREEN_UPSCALED_640x440: {
409  // to 1-> 4 pixels upscaling for all of those, so that fonts won't look weird
410  int displayOffset = (_upscaledHeightMapping[startingY] + y * 2) * _displayWidth + x * 2;
411  _displayScreen[displayOffset] = color;
412  _displayScreen[displayOffset + 1] = color;
413  displayOffset += _displayWidth;
414  _displayScreen[displayOffset] = color;
415  _displayScreen[displayOffset + 1] = color;
416  break;
417  }
418  default:
419  putScaledPixelOnDisplay(x, actualY, color);
420  break;
421  }
422  }
423  }
424 
425  byte getPixel(byte *screen, int16 x, int16 y) {
426  switch (_upscaledHires) {
427  case GFX_SCREEN_UPSCALED_480x300: {
428  int offset = ((y * 3) / 2) * _width + ((y * 3) / 2);
429 
430  return screen[offset];
431  break;
432  }
433  default:
434  break;
435  }
436  return screen[y * _width + x];
437  }
438 
439  byte getVisual(int16 x, int16 y) {
440  return getPixel(_visualScreen, x, y);
441  }
442  byte getPriority(int16 x, int16 y) {
443  return getPixel(_priorityScreen, x, y);
444  }
445  byte getControl(int16 x, int16 y) {
446  return getPixel(_controlScreen, x, y);
447  }
448 
449  // Vector related public code - in here, so that it can be inlined
450  byte vectorGetPixel(byte *screen, int16 x, int16 y) {
451  return screen[y * _width + x];
452  }
453 
454  byte vectorGetVisual(int16 x, int16 y) {
455  return vectorGetPixel(_visualScreen, x, y);
456  }
457  byte vectorGetPriority(int16 x, int16 y) {
458  return vectorGetPixel(_priorityScreen, x, y);
459  }
460  byte vectorGetControl(int16 x, int16 y) {
461  return vectorGetPixel(_controlScreen, x, y);
462  }
463 
464  void vectorAdjustCoordinate(int16 *x, int16 *y) {
465  switch (_upscaledHires) {
466  case GFX_SCREEN_UPSCALED_480x300:
467  *x = (*x * 3) / 2;
468  *y = (*y * 3) / 2;
469  break;
470  default:
471  break;
472  }
473  }
474 };
475 
476 } // End of namespace Sci
477 
478 #endif // SCI_GRAPHICS_SCREEN_H
void putPixelOnDisplay(int16 x, int16 y, byte color)
Definition: screen.h:348
Definition: font.h:82
Definition: surface.h:66
Definition: pixelformat.h:138
void putFontPixel(int16 startingY, int16 x, int16 y, byte color)
Definition: screen.h:389
Definition: korfont.h:42
Definition: rect.h:144
Definition: resource.h:327
Definition: rect.h:45
Definition: console.h:28
Definition: helpers.h:268
Definition: screen.h:68