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
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (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, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #ifndef KYRA_SCREEN_EOB_SEGACD_H
24 #define KYRA_SCREEN_EOB_SEGACD_H
25 
26 #ifdef ENABLE_EOB
27 
28 #define SEGA_PERFORMANCE		true
29 #define SEGA_USE_MEMPOOL		true
30 
31 #include "kyra/graphics/screen_eob.h"
32 
33 #if SEGA_USE_MEMPOOL
34 #include "common/memorypool.h"
35 #endif
36 
37 namespace Kyra {
38 
39 class SegaRenderer {
40 public:
41 	enum Plane {
42 		kPlaneA = 0,
43 		kPlaneB = 1,
44 		kWindowPlane = 2
45 	};
46 
47 	enum WindowMode {
48 		kWinToLeft = 0,
49 		kWinToTop = 0,
50 		kWinToRight = 1,
51 		kWinToBottom = 1
52 	};
53 
54 	enum HScrollMode {
55 		kHScrollFullScreen = 0,
56 		kHScroll8PixelRows,
57 		kHScroll1PixelRows
58 	};
59 
60 	enum VScrollMode {
61 		kVScrollFullScreen = 0,
62 		kVScroll16PixelStrips
63 	};
64 
65 public:
66 	SegaRenderer(Screen_EoB *screen);
67 	~SegaRenderer();
68 
69 	void setResolution(int w, int h);
70 	void setPlaneTableLocation(int plane, uint16 addr);
71 	// The hardware allows/demands separate modification of the vertical and horizontal properties.
72 	// To allow this without making another function the w/h parameters can be set to -1 which will
73 	// keep the existing value for that property.
74 	void setupPlaneAB(int pixelWidth, int pixelHeigth);
75 	// The hardware allows/demands separate modification of the vertical and horizontal properties.
76 	// To allow this without making another function the blockX/Y parameters can be set to -1 which
77 	// will keep the existing value for that property.
78 	void setupWindowPlane(int blockX, int blockY, int horizontalMode, int verticalMode);
79 	void setHScrollTableLocation(int addr);
80 	void setSpriteTableLocation(int addr);
81 	void setPitch(int pitch);
82 	void setHScrollMode(int mode);
83 	void setVScrollMode(int mode);
84 
85 	void loadToVRAM(const void *data, uint16 dataSize, uint16 addr);
86 	void loadStreamToVRAM(Common::SeekableReadStream *in, uint16 addr, bool compressedData = false);
87 	void memsetVRAM(int addr, uint8 val, int len);
88 	void fillRectWithTiles(int vramArea, int x, int y, int w, int h, uint16 nameTblEntry, bool incr = false, bool topToBottom = false, const uint16 *patternTable = 0);
89 	void writeUint16VSRAM(int addr, uint16 value);
90 	void writeUint8VRAM(int addr, uint8 value);
91 	void writeUint16VRAM(int addr, uint16 value);
92 	void clearPlanes();
93 
94 	void render(int destPageNum, int renderLeft = -1, int renderTop = -1, int renderWidth = -1, int renderHeight = -1, bool spritesOnly = false);
95 private:
96 	void renderPlanePart(int plane, uint8 *dstBuffer, int x1, int y1, int x2, int y2);
97 	void renderPlaneTile(uint8 *dst, int destX, const uint16 *nameTable, int vScrollLSBStart, int vScrollLSBEnd, int hScrollTableIndex, uint16 pitch);
98 	void renderSpriteTile(uint8 *dst, uint8 *mask, int x, int y, uint16 tile, uint8 pal, bool vflip, bool hflip, bool prio);
99 #if SEGA_PERFORMANCE
100 	template<bool hflip, bool oddStart, bool oddEnd> void renderLineFragmentM(uint8 *dst, uint8 *mask, const uint8 *src, int start, int end, uint8 pal);
101 	template<bool hflip, bool oddStart, bool oddEnd> void renderLineFragmentD(uint8 *dst, const uint8 *src, int start, int end, uint8 pal);
102 	typedef void(SegaRenderer::*renderFuncM)(uint8*, uint8*, const uint8*, int, int, uint8);
103 	typedef void(SegaRenderer::*renderFuncD)(uint8*, const uint8*, int, int, uint8);
104 	const renderFuncM *_renderLineFragmentM;
105 	const renderFuncD *_renderLineFragmentD;
106 #else
107 	template<bool hflip> void renderLineFragment(uint8 *dst, uint8 *mask, const uint8 *src, int start, int end, uint8 pal);
108 #endif
109 
110 	void initPrioRenderTask(uint8 *dst, uint8 *mask, const uint8 *src, int start, int end, uint8 pal, bool hflip);
111 	void clearPrioChain();
112 
113 	struct SegaPlane {
SegaPlaneSegaPlane114 		SegaPlane() : blockX(0), blockY(0), w(0), h(0), mod(0), nameTable(0), nameTableSize(0) {}
115 		int blockX, blockY;
116 		uint16 w, h, mod;
117 		uint16 *nameTable;
118 		uint16 nameTableSize;
119 	};
120 
121 	SegaPlane _planes[3];
122 	uint8 *_vram;
123 	uint16 *_vsram;
124 	uint16 *_hScrollTable;
125 	uint16 *_spriteTable;
126 	uint8 *_spriteMask;
127 	uint8 _hScrollMode;
128 	uint8 _vScrollMode;
129 	uint16 _pitch;
130 	uint16 _numSpritesMax;
131 
132 	struct PrioTileRenderObj {
PrioTileRenderObjPrioTileRenderObj133 		PrioTileRenderObj(PrioTileRenderObj *chainEnd, uint8 *dst, uint8 *mask, const uint8 *src, int start, int end, uint8 pal, bool hflip) :
134 			_pred(chainEnd), _next(0), _dst(dst), _mask(mask), _src(src), _start(start), _end(end), _pal(pal), _hflip(hflip) {
135 			if (_pred)
136 				_pred->_next = this;
137 		}
138 		uint8 *_dst;
139 		uint8 *_mask;
140 		const uint8 *_src;
141 		int _start;
142 		int _end;
143 		uint8 _pal;
144 		bool _hflip;
145 		PrioTileRenderObj *_pred;
146 		PrioTileRenderObj *_next;
147 	};
148 
149 #if SEGA_USE_MEMPOOL
150 	Common::ObjectPool<PrioTileRenderObj> _prioRenderMemPool;
151 #endif
152 	PrioTileRenderObj *_prioChainStart, *_prioChainEnd;
153 	uint16 _screenW, _screenH, _blocksW, _blocksH;
154 	Screen_EoB *_screen;
155 };
156 
157 class SegaAnimator {
158 public:
159 	SegaAnimator(SegaRenderer *renderer);
160 	~SegaAnimator();
161 
162 	void initSprite(int id, int16 x, int16 y, uint16 nameTbl, uint16 hw);
163 	void clearSprites();
164 	void moveMorphSprite(int id, uint16 nameTbl, int16 addX, int16 addY);
165 	void moveSprites(int id, uint16 num, int16 addX, int16 addY);
166 	void moveSprites2(int id, uint16 num, int16 addX, int16 addY);
167 
168 	void update();
169 
170 private:
171 	struct Sprite {
172 		int16 x;
173 		int16 y;
174 		uint16 nameTbl;
175 		uint16 hw;
176 	};
177 
178 	uint16 *_tempBuffer;
179 	Sprite *_sprites;
180 	SegaRenderer *_renderer;
181 	bool _needUpdate;
182 };
183 
184 class ScrollManager {
185 public:
186 	ScrollManager(SegaRenderer *renderer);
187 	~ScrollManager();
188 
189 	void setVScrollTimers(uint16 destA, int incrA, int delayA, uint16 destB, int incrB, int delayB);
190 	void setHScrollTimers(uint16 destA, int incrA, int delayA, uint16 destB, int incrB, int delayB);
191 	void updateScrollTimers();
192 	void fastForward();
193 
194 private:
195 	struct ScrollTimer {
ScrollTimerScrollTimer196 		ScrollTimer() : _offsCur(0), _offsDest(0), _incr(0), _delay(0), _timer(0) {}
197 		int16 _offsCur;
198 		int16 _offsDest;
199 		int16 _incr;
200 		int16 _delay;
201 		int16 _timer;
202 	};
203 
204 	ScrollTimer *_vScrollTimers;
205 	ScrollTimer *_hScrollTimers;
206 	SegaRenderer *_renderer;
207 };
208 
209 } // End of namespace Kyra
210 
211 #endif // ENABLE_EOB
212 
213 #endif
214