1 /* Copyright (c) 2020 Themaister
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining
4  * a copy of this software and associated documentation files (the
5  * "Software"), to deal in the Software without restriction, including
6  * without limitation the rights to use, copy, modify, merge, publish,
7  * distribute, sublicense, and/or sell copies of the Software, and to
8  * permit persons to whom the Software is furnished to do so, subject to
9  * the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be
12  * included in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  */
22 
23 #pragma once
24 
25 namespace Vulkan
26 {
27 class Program;
28 class Shader;
29 }
30 
31 namespace RDP
32 {
33 template <typename Program, typename Shader> struct Shaders;
34 using ShaderBank = Shaders<Vulkan::Program *, Vulkan::Shader *>;
35 
36 // list of command IDs
37 enum class Op
38 {
39 	Nop = 0,
40 
41 	MetaSignalTimeline = 1,
42 	MetaFlush = 2,
43 	MetaIdle = 3,
44 	MetaSetQuirks = 4,
45 
46 	FillTriangle = 0x08,
47 	FillZBufferTriangle = 0x09,
48 	TextureTriangle = 0x0a,
49 	TextureZBufferTriangle = 0x0b,
50 	ShadeTriangle = 0x0c,
51 	ShadeZBufferTriangle = 0x0d,
52 	ShadeTextureTriangle = 0x0e,
53 	ShadeTextureZBufferTriangle = 0x0f,
54 	TextureRectangle = 0x24,
55 	TextureRectangleFlip = 0x25,
56 	SyncLoad = 0x26,
57 	SyncPipe = 0x27,
58 	SyncTile = 0x28,
59 	SyncFull = 0x29,
60 	SetKeyGB = 0x2a,
61 	SetKeyR = 0x2b,
62 	SetConvert = 0x2c,
63 	SetScissor = 0x2d,
64 	SetPrimDepth = 0x2e,
65 	SetOtherModes = 0x2f,
66 	LoadTLut = 0x30,
67 	SetTileSize = 0x32,
68 	LoadBlock = 0x33,
69 	LoadTile = 0x34,
70 	SetTile = 0x35,
71 	FillRectangle = 0x36,
72 	SetFillColor = 0x37,
73 	SetFogColor = 0x38,
74 	SetBlendColor = 0x39,
75 	SetPrimColor = 0x3a,
76 	SetEnvColor = 0x3b,
77 	SetCombine = 0x3c,
78 	SetTextureImage = 0x3d,
79 	SetMaskImage = 0x3e,
80 	SetColorImage = 0x3f
81 };
82 
83 enum class RGBMul : uint8_t
84 {
85 	Combined = 0,
86 	Texel0 = 1,
87 	Texel1 = 2,
88 	Primitive = 3,
89 	Shade = 4,
90 	Env = 5,
91 	KeyScale = 6,
92 	CombinedAlpha = 7,
93 	Texel0Alpha = 8,
94 	Texel1Alpha = 9,
95 	PrimitiveAlpha = 10,
96 	ShadeAlpha = 11,
97 	EnvAlpha = 12,
98 	LODFrac = 13,
99 	PrimLODFrac = 14,
100 	ConvertK5 = 15,
101 	Zero = 16
102 };
103 
104 enum class RGBMulAdd : uint8_t
105 {
106 	Combined = 0,
107 	Texel0 = 1,
108 	Texel1 = 2,
109 	Primitive = 3,
110 	Shade = 4,
111 	Env = 5,
112 	One = 6,
113 	Noise = 7,
114 	Zero = 8
115 };
116 
117 enum class RGBMulSub : uint8_t
118 {
119 	Combined = 0,
120 	Texel0 = 1,
121 	Texel1 = 2,
122 	Primitive = 3,
123 	Shade = 4,
124 	Env = 5,
125 	KeyCenter = 6,
126 	ConvertK4 = 7,
127 	Zero = 8
128 };
129 
130 enum class RGBAdd : uint8_t
131 {
132 	Combined = 0,
133 	Texel0 = 1,
134 	Texel1 = 2,
135 	Primitive = 3,
136 	Shade = 4,
137 	Env = 5,
138 	One = 6,
139 	Zero = 7
140 };
141 
142 enum class AlphaAddSub : uint8_t
143 {
144 	CombinedAlpha = 0,
145 	Texel0Alpha = 1,
146 	Texel1Alpha = 2,
147 	PrimitiveAlpha = 3,
148 	ShadeAlpha = 4,
149 	EnvAlpha = 5,
150 	One = 6,
151 	Zero = 7
152 };
153 
154 enum class AlphaMul : uint8_t
155 {
156 	LODFrac = 0,
157 	Texel0Alpha = 1,
158 	Texel1Alpha = 2,
159 	PrimitiveAlpha = 3,
160 	ShadeAlpha = 4,
161 	EnvAlpha = 5,
162 	PrimLODFrac = 6,
163 	Zero = 7
164 };
165 
166 enum class TextureSize : uint8_t
167 {
168 	Bpp4 = 0,
169 	Bpp8 = 1,
170 	Bpp16 = 2,
171 	Bpp32 = 3
172 };
173 
174 enum class TextureFormat : uint8_t
175 {
176 	RGBA = 0,
177 	YUV = 1,
178 	CI = 2,
179 	IA = 3,
180 	I = 4
181 };
182 
183 enum class RGBDitherMode : uint8_t
184 {
185 	Magic = 0,
186 	Bayer = 1,
187 	Noise = 2,
188 	Off = 3
189 };
190 
191 enum class AlphaDitherMode : uint8_t
192 {
193 	Pattern = 0,
194 	InvPattern = 1,
195 	Noise = 2,
196 	Off = 3
197 };
198 
199 enum class CycleType : uint8_t
200 {
201 	Cycle1 = 0,
202 	Cycle2 = 1,
203 	Copy = 2,
204 	Fill = 3
205 };
206 
207 enum class BlendMode1A : uint8_t
208 {
209 	PixelColor = 0,
210 	MemoryColor = 1,
211 	BlendColor = 2,
212 	FogColor = 3
213 };
214 
215 enum class BlendMode1B : uint8_t
216 {
217 	PixelAlpha = 0,
218 	FogAlpha = 1,
219 	ShadeAlpha = 2,
220 	Zero = 3
221 };
222 
223 enum class BlendMode2A : uint8_t
224 {
225 	PixelColor = 0,
226 	MemoryColor = 1,
227 	BlendColor = 2,
228 	FogColor = 3
229 };
230 
231 enum class BlendMode2B : uint8_t
232 {
233 	InvPixelAlpha = 0,
234 	MemoryAlpha = 1,
235 	One = 2,
236 	Zero = 3
237 };
238 
239 enum class CoverageMode : uint8_t
240 {
241 	Clamp = 0,
242 	Wrap = 1,
243 	Zap = 2,
244 	Save = 3
245 };
246 
247 enum class ZMode : uint8_t
248 {
249 	Opaque = 0,
250 	Interpenetrating = 1,
251 	Transparent = 2,
252 	Decal = 3
253 };
254 
255 enum TileInfoFlagBits
256 {
257 	TILE_INFO_CLAMP_S_BIT = 1 << 0,
258 	TILE_INFO_MIRROR_S_BIT = 1 << 1,
259 	TILE_INFO_CLAMP_T_BIT = 1 << 2,
260 	TILE_INFO_MIRROR_T_BIT = 1 << 3
261 };
262 using TileInfoFlags = uint8_t;
263 
264 struct TileSize
265 {
266 	uint32_t slo = 0;
267 	uint32_t shi = 0;
268 	uint32_t tlo = 0;
269 	uint32_t thi = 0;
270 };
271 
272 struct TileMeta
273 {
274 	uint32_t offset = 0;
275 	uint32_t stride = 0;
276 	TextureFormat fmt = TextureFormat::RGBA;
277 	TextureSize size = TextureSize::Bpp16;
278 	uint8_t palette = 0;
279 	uint8_t mask_s = 0;
280 	uint8_t shift_s = 0;
281 	uint8_t mask_t = 0;
282 	uint8_t shift_t = 0;
283 	TileInfoFlags flags = 0;
284 };
285 
286 struct TileInfo
287 {
288 	TileSize size;
289 	TileMeta meta;
290 };
291 
292 struct CombinerInputsRGB
293 {
294 	RGBMulAdd muladd;
295 	RGBMulSub mulsub;
296 	RGBMul mul;
297 	RGBAdd add;
298 };
299 
300 struct CombinerInputsAlpha
301 {
302 	AlphaAddSub muladd;
303 	AlphaAddSub mulsub;
304 	AlphaMul mul;
305 	AlphaAddSub add;
306 };
307 
308 struct CombinerInputs
309 {
310 	CombinerInputsRGB rgb;
311 	CombinerInputsAlpha alpha;
312 };
313 
314 struct BlendModes
315 {
316 	BlendMode1A blend_1a;
317 	BlendMode1B blend_1b;
318 	BlendMode2A blend_2a;
319 	BlendMode2B blend_2b;
320 };
321 
322 static_assert(sizeof(TileInfo) == 32, "TileInfo must be 32 bytes.");
323 
324 enum class VIRegister
325 {
326 	Control = 0,
327 	Origin,
328 	Width,
329 	Intr,
330 	VCurrentLine,
331 	Timing,
332 	VSync,
333 	HSync,
334 	Leap,
335 	HStart,
336 	VStart,
337 	VBurst,
338 	XScale,
339 	YScale,
340 	Count
341 };
342 
343 enum VIControlFlagBits
344 {
345 	VI_CONTROL_TYPE_BLANK_BIT = 0 << 0,
346 	VI_CONTROL_TYPE_RESERVED_BIT = 1 << 0,
347 	VI_CONTROL_TYPE_RGBA5551_BIT = 2 << 0,
348 	VI_CONTROL_TYPE_RGBA8888_BIT = 3 << 0,
349 	VI_CONTROL_TYPE_MASK = 3 << 0,
350 	VI_CONTROL_GAMMA_DITHER_ENABLE_BIT = 1 << 2,
351 	VI_CONTROL_GAMMA_ENABLE_BIT = 1 << 3,
352 	VI_CONTROL_DIVOT_ENABLE_BIT = 1 << 4,
353 	VI_CONTROL_SERRATE_BIT = 1 << 6,
354 	VI_CONTROL_AA_MODE_RESAMP_EXTRA_ALWAYS_BIT = 0 << 8,
355 	VI_CONTROL_AA_MODE_RESAMP_EXTRA_BIT = 1 << 8,
356 	VI_CONTROL_AA_MODE_RESAMP_ONLY_BIT = 2 << 8,
357 	VI_CONTROL_AA_MODE_RESAMP_REPLICATE_BIT = 3 << 8,
358 	VI_CONTROL_AA_MODE_MASK = 3 << 8,
359 	VI_CONTROL_DITHER_FILTER_ENABLE_BIT = 1 << 16,
360 	VI_CONTROL_META_AA_BIT = 1 << 17,
361 	VI_CONTROL_META_SCALE_BIT = 1 << 18
362 };
363 using VIControlFlags = uint32_t;
364 
make_vi_start_register(uint32_t start_value,uint32_t end_value)365 static inline uint32_t make_vi_start_register(uint32_t start_value, uint32_t end_value)
366 {
367 	return ((start_value & 0x3ff) << 16) | (end_value & 0x3ff);
368 }
369 
make_vi_scale_register(uint32_t scale_factor,uint32_t bias)370 static inline uint32_t make_vi_scale_register(uint32_t scale_factor, uint32_t bias)
371 {
372 	return ((bias & 0xfff) << 16) | (scale_factor & 0xfff);
373 }
374 
375 constexpr uint32_t VI_V_SYNC_NTSC = 525;
376 constexpr uint32_t VI_V_SYNC_PAL = 625;
377 constexpr uint32_t VI_H_OFFSET_NTSC = 108;
378 constexpr uint32_t VI_H_OFFSET_PAL = 128;
379 constexpr uint32_t VI_V_OFFSET_NTSC = 34;
380 constexpr uint32_t VI_V_OFFSET_PAL = 44;
381 constexpr uint32_t VI_V_RES_NTSC = 480;
382 constexpr uint32_t VI_V_RES_PAL = 576;
383 constexpr int VI_SCANOUT_WIDTH = 640;
384 
make_default_v_start()385 static inline uint32_t make_default_v_start()
386 {
387 	return make_vi_start_register(VI_V_OFFSET_NTSC, VI_V_OFFSET_NTSC + 224 * 2);
388 }
389 
make_default_h_start()390 static inline uint32_t make_default_h_start()
391 {
392 	return make_vi_start_register(VI_H_OFFSET_NTSC, VI_H_OFFSET_NTSC + VI_SCANOUT_WIDTH);
393 }
394 
395 template <int bits>
sext(int32_t v)396 static int32_t sext(int32_t v)
397 {
398 	struct { int32_t dummy : bits; } d;
399 	d.dummy = v;
400 	return d.dummy;
401 }
402 }