aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/graphics/frameout.h
blob: 738011a84f5534c2e4bda5dcdfe0436a2fc300b5 (plain)
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
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
/* 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 "sci/graphics/plane32.h"
#include "sci/graphics/screen_item32.h"

namespace Sci {
// TODO: Don't do this this way
int splitRects(Common::Rect r, const Common::Rect &other, Common::Rect(&outRects)[4]);

// TODO: Verify display styles and adjust names appropriately for
// types 1 through 12 & 15 (others are correct)
// Names should be:
// * VShutterIn, VShutterOut
// * HShutterIn, HShutterOut
// * WipeLeft, WipeRight, WipeDown, WipeUp
// * PixelDissolve
// * ShutDown and Kill? (and Plain and Fade?)
enum ShowStyleType /* : uint8 */ {
	kShowStyleNone = 0,
	kShowStyleHShutterOut = 1,
	kShowStyleHShutterIn = 2,
	kShowStyleVShutterOut = 3,
	kShowStyleVShutterIn = 4,
	kShowStyleWipeLeft = 5,
	kShowStyleWipeRight = 6,
	kShowStyleWipeUp = 7,
	kShowStyleWipeDown = 8,
	kShowStyleIrisOut = 9,
	kShowStyleIrisIn = 10,
	kShowStyle11 = 11,
	kShowStyle12 = 12,
	kShowStyleFadeOut = 13,
	kShowStyleFadeIn = 14,
	// TODO: Only in SCI3
	kShowStyleUnknown = 15
};

/**
 * Show styles represent transitions applied to draw planes.
 * One show style per plane can be active at a time.
 */
struct ShowStyleEntry {
	/**
	 * The ID of the plane this show style belongs to.
	 * In SCI2.1mid (at least SQ6), per-plane transitions
	 * were removed and a single plane ID is used.
	 */
	reg_t plane;

	/**
	 * The type of the transition.
	 */
	ShowStyleType type;

	// TODO: This name is probably incorrect
	bool fadeUp;

	/**
	 * The number of steps for the show style.
	 */
	int16 divisions;

	// NOTE: This property exists from SCI2 through at least
	// SCI2.1mid but is never used in the actual processing
	// of the styles?
	int unknownC;

	/**
	 * The color used by transitions that draw CelObjColor
	 * screen items. -1 for transitions that do not draw
	 * screen items.
	 */
	int16 color;

	// TODO: Probably uint32
	// TODO: This field probably should be used in order to
	// provide time-accurate processing of show styles. In the
	// actual SCI engine (at least 2–2.1mid) it appears that
	// style transitions are drawn “as fast as possible”, one
	// step per loop, even though this delay field exists
	int delay;

	// TODO: Probably bool, but never seems to be true?
	int animate;

	/**
	 * The wall time at which the next step of the animation
	 * should execute.
	 */
	uint32 nextTick;

	/**
	 * During playback of the show style, the current step
	 * (out of divisions).
	 */
	int currentStep;

	/**
	 * The next show style.
	 */
	ShowStyleEntry *next;

	/**
	 * Whether or not this style has finished running and
	 * is ready for disposal.
	 */
	bool processed;

	//
	// Engine-specific properties for SCI2 through 2.1early
	//

	// TODO: Could union this stuff to save literally
	// several bytes of memory.

	/**
	 * The width of the plane. Used to determine the correct
	 * size of screen items for wipes.
	 */
	int width;

	/**
	 * The height of the plane. Used to determine the correct
	 * size of screen items for wipes.
	 */
	int height;

	/**
	 * The number of edges that a transition operates on.
	 * Slide wipe: 1 edge
	 * Reveal wipe: 2 edges
	 * Iris wipe: 4 edges
	 */
	// TODO: I have no idea why SCI engine stores this instead
	// of a screenItems count
	int edgeCount;

	/**
	 * Used by transition types 1 through 10.
	 * One screen item per division per edge.
	 */
	ScreenItemList screenItems;

	/**
	 * Used by transition types 11 and 12. A copy of the
	 * visible frame buffer.
	 */
	// TODO: This is a reg_t in SCI engine; not sure if
	// we can avoid allocation through SegMan or not.
	reg_t bitmapMemId;

	/**
	 * Used by transition types 11 and 12. A screen item
	 * used to display the associated bitmap data.
	 */
	ScreenItem *bitmapScreenItem;

	/**
	 * A number used to pick pixels to dissolve by types
	 * 11 and 12.
	 */
	int dissolveSeed;
	int unknown3A;
	// max?
	int dissolveInitial;

	//
	// Engine specific properties for SCI2.1mid through SCI3
	//

	/**
	 * The number of entries in the fadeColorRanges array.
	 */
	uint8 fadeColorRangesCount;

	/**
	 * A pointer to an dynamically sized array of palette
	 * indexes, in the order [ fromColor, toColor, ... ].
	 * Only colors within this range are transitioned.
	 */
	uint16 *fadeColorRanges;
};

typedef Common::Array<DrawList> ScreenItemListList;
typedef Common::Array<RectList> EraseListList;

class GfxCache;
class GfxCoordAdjuster32;
class GfxPaint32;
class GfxPalette;
class GfxScreen;

/**
 * Frameout class, kFrameout and relevant functions for SCI32 games.
 * Roughly equivalent to GraphicsMgr in the actual SCI engine.
 */
class GfxFrameout {
private:
	bool _isHiRes;
	GfxCache *_cache;
	GfxCoordAdjuster32 *_coordAdjuster;
	GfxPalette32 *_palette;
	ResourceManager *_resMan;
	GfxScreen *_screen;
	SegManager *_segMan;
	GfxPaint32 *_paint32;

public:
	GfxFrameout(SegManager *segMan, ResourceManager *resMan, GfxCoordAdjuster *coordAdjuster, GfxCache *cache, GfxScreen *screen, GfxPalette32 *palette, GfxPaint32 *paint32);
	~GfxFrameout();

	void clear();
	void syncWithScripts(bool addElements); // this is what Game::restore does, only needed when our ScummVM dialogs are patched in
	void run();

#pragma mark -
#pragma mark Screen items
private:
	void deleteScreenItem(ScreenItem *screenItem, const reg_t plane);

public:
	void kernelAddScreenItem(const reg_t object);
	void kernelUpdateScreenItem(const reg_t object);
	void kernelDeleteScreenItem(const reg_t object);

#pragma mark -
#pragma mark Planes
private:
	/**
	 * The list of planes (i.e. layers) that have been added
	 * to the screen.
	 *
	 * @note This field is on `GraphicsMgr.screen` in SCI
	 * engine.
	 */
	PlaneList _planes;

	/**
	 * Updates an existing plane with properties from the
	 * given VM object.
	 */
	void updatePlane(Plane &plane);

public:
	/**
	 * Creates and adds a new plane to the plane list, or
	 * cancels deletion and updates an already-existing
	 * plane if a plane matching the given plane VM object
	 * already exists within the current plane list.
	 *
	 * @note This method is on Screen in SCI engine, 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 SCI engine, but it
	 * is only ever called on `GraphicsMgr.screen`.
	 */
	void deletePlane(Plane &plane);

	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);
	int16 kernelGetHighPlanePri();

#pragma mark -
#pragma mark Pics
public:
	void kernelAddPicAt(const reg_t planeObject, const GuiResourceId pictureId, const int16 pictureX, const int16 pictureY, const bool mirrorX);

#pragma mark -

	// TODO: Remap-related?
	void kernelSetPalStyleRange(const uint8 fromColor, const uint8 toColor);

#pragma mark -
#pragma mark Transitions
private:
	int *_dissolveSequenceSeeds;
	int16 *_defaultDivisions;
	int16 *_defaultUnknownC;

	/**
	 * TODO: Documentation
	 */
	ShowStyleEntry *_showStyles;

	inline ShowStyleEntry *findShowStyleForPlane(const reg_t planeObj) const;
	inline ShowStyleEntry *deleteShowStyleInternal(ShowStyleEntry *const showStyle);
	void processShowStyles();
	bool processShowStyleNone(ShowStyleEntry *showStyle);
	bool processShowStyleMorph(ShowStyleEntry *showStyle);
	bool processShowStyleFade(const int direction, ShowStyleEntry *showStyle);
#if 0
	bool processShowStyleWipe(const int direction, ShowStyleEntry *const showStyle);
#endif

public:
	// NOTE: This signature is taken from SCI3 Phantasmagoria 2
	// and is valid for all implementations of SCI32
	void kernelSetShowStyle(const uint16 argc, const reg_t &planeObj, const ShowStyleType type, const int16 seconds, const int16 direction, const int16 priority, const int16 animate, const int16 frameOutNow, const reg_t &pFadeArray, const int16 divisions, const int16 blackScreen);

#pragma mark -
#pragma mark Rendering
private:
	/**
	 * TODO: Documentation
	 */
	int8 _styleRanges[256];

	/**
	 * 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;

	// TODO: In SCI2.1/SQ6, priority map pixels are not allocated
	// by default. In SCI2/GK1, pixels are allocated, but not used
	// anywhere except within CelObj::Draw in seemingly the same
	// way they are used in SCI2.1/SQ6: that is, never read, only
	// written.
	Buffer _priorityMap;

	/**
	 * TODO: Documentation
	 */
	bool _remapOccurred;

	/**
	 * Whether or not the data in the current buffer is what
	 * is visible to the user. During rendering updates,
	 * this flag is set to false.
	 */
	bool _frameNowVisible;

	/**
	 * TODO: Document
	 * TODO: Depending upon if the engine ever modifies this
	 * rect, it may be stupid to store it separately instead
	 * of just getting width/height from GfxScreen.
	 *
	 * @note This field is on `GraphicsMgr.screen` in SCI
	 * engine.
	 */
	Common::Rect _screenRect;

	/**
	 * A list of rectangles, in display coordinates, that
	 * represent portions of the internal screen buffer that
	 * should be drawn to the hardware display surface.
	 *
	 * @note This field is on `GraphicsMgr.screen` in SCI
	 * engine.
	 */
	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 SCI
	 * engine.
	 */
	int _overdrawThreshold;

	/**
	 * A 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
	 * SCI engine.
	 */
	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.
	 */
	void calcLists(ScreenItemListList &drawLists, EraseListList &eraseLists, const Common::Rect &calcRect);

	/**
	 * 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);

	/**
	 * TODO: Documentation
	 */
	void palMorphFrameOut(const int8 *styleRanges, const ShowStyleEntry *showStyle);

	/**
	 * Writes the internal frame buffer out to hardware and
	 * clears the show list.
	 */
	void showBits();

public:
	/**
	 * TODO: Document
	 * This is used by CelObj::Draw.
	 */
	bool _hasRemappedScreenItem;

	/**
	 * Whether palMorphFrameOut should be used instead of
	 * frameOut for rendering. Used by kMorphOn to
	 * explicitly enable palMorphFrameOut for one frame.
	 */
	bool _palMorphIsOn;

	inline Buffer &getCurrentBuffer() {
		return _currentBuffer;
	}

	void kernelFrameOut(const bool showBits);

	/**
	 * Updates the internal screen buffer for the next
	 * frame. If `shouldShowBits` is true, also sends the
	 * buffer to hardware.
	 */
	void frameOut(const bool shouldShowBits, const Common::Rect &rect = Common::Rect());

	/**
	 * 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);

	// TODO: SCI2 engine never uses priority map?
	inline Buffer &getPriorityMap() {
		return _priorityMap;
	}

	// NOTE: 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;
	};

	uint16 kernelIsOnMe(int16 x, int16 y, uint16 checkPixels, reg_t screenObject);
	uint16 isOnMe(Plane *screenItemPlane, ScreenItem *screenItem, int16 x, int16 y, uint16 checkPixels);

#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;
};

} // End of namespace Sci

#endif