6f2ee2be |
1 | /*************************************************************************** |
2 | * Copyright (C) 2010 PCSX4ALL Team * |
3 | * Copyright (C) 2010 Unai * |
4 | * Copyright (C) 2011 notaz * |
030d1121 |
5 | * Copyright (C) 2016 Senquack (dansilsby <AT> gmail <DOT> com) * |
6f2ee2be |
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 2 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, write to the * |
19 | * Free Software Foundation, Inc., * |
20 | * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. * |
21 | ***************************************************************************/ |
22 | |
030d1121 |
23 | #include <stddef.h> |
6f2ee2be |
24 | #include <stdio.h> |
25 | #include <stdlib.h> |
26 | #include <string.h> |
62d7fa95 |
27 | #include "../gpulib/gpu.h" |
030d1121 |
28 | //#include "port.h" |
29 | #include "gpu_unai.h" |
6f2ee2be |
30 | |
030d1121 |
31 | // GPU fixed point math |
32 | #include "gpu_fixedpoint.h" |
6f2ee2be |
33 | |
030d1121 |
34 | // Inner loop driver instantiation file |
35 | #include "gpu_inner.h" |
6f2ee2be |
36 | |
37 | // GPU internal image drawing functions |
030d1121 |
38 | #include "gpu_raster_image.h" |
6f2ee2be |
39 | |
40 | // GPU internal line drawing functions |
030d1121 |
41 | #include "gpu_raster_line.h" |
6f2ee2be |
42 | |
43 | // GPU internal polygon drawing functions |
030d1121 |
44 | #include "gpu_raster_polygon.h" |
6f2ee2be |
45 | |
46 | // GPU internal sprite drawing functions |
030d1121 |
47 | #include "gpu_raster_sprite.h" |
6f2ee2be |
48 | |
49 | // GPU command buffer execution/store |
030d1121 |
50 | #include "gpu_command.h" |
6f2ee2be |
51 | |
6f2ee2be |
52 | ///////////////////////////////////////////////////////////////////////////// |
53 | |
54 | int renderer_init(void) |
55 | { |
030d1121 |
56 | memset((void*)&gpu_unai, 0, sizeof(gpu_unai)); |
57 | gpu_unai.vram = (u16*)gpu.vram; |
58 | |
59 | // Original standalone gpu_unai initialized TextureWindow[]. I added the |
60 | // same behavior here, since it seems unsafe to leave [2],[3] unset when |
61 | // using HLE and Rearmed gpu_neon sets this similarly on init. -senquack |
62 | gpu_unai.TextureWindow[0] = 0; |
63 | gpu_unai.TextureWindow[1] = 0; |
64 | gpu_unai.TextureWindow[2] = 255; |
65 | gpu_unai.TextureWindow[3] = 255; |
66 | //senquack - new vars must be updated whenever texture window is changed: |
67 | // (used for polygon-drawing in gpu_inner.h, gpu_raster_polygon.h) |
68 | const u32 fb = FIXED_BITS; // # of fractional fixed-pt bits of u4/v4 |
69 | gpu_unai.u_msk = (((u32)gpu_unai.TextureWindow[2]) << fb) | ((1 << fb) - 1); |
70 | gpu_unai.v_msk = (((u32)gpu_unai.TextureWindow[3]) << fb) | ((1 << fb) - 1); |
71 | |
72 | // Configuration options |
73 | gpu_unai.config = gpu_unai_config_ext; |
74 | //senquack - disabled, not sure this is needed and would require modifying |
75 | // sprite-span functions, perhaps unnecessarily. No Abe Oddysey hack was |
76 | // present in latest PCSX4ALL sources we were using. |
77 | //gpu_unai.config.enableAbbeyHack = gpu_unai_config_ext.abe_hack; |
78 | gpu_unai.ilace_mask = gpu_unai.config.ilace_force; |
79 | |
80 | #ifdef GPU_UNAI_USE_INT_DIV_MULTINV |
81 | // s_invTable |
82 | for(int i=1;i<=(1<<TABLE_BITS);++i) |
83 | { |
84 | double v = 1.0 / double(i); |
85 | #ifdef GPU_TABLE_10_BITS |
86 | v *= double(0xffffffff>>1); |
87 | #else |
88 | v *= double(0x80000000); |
89 | #endif |
90 | s_invTable[i-1]=s32(v); |
91 | } |
92 | #endif |
93 | |
94 | SetupLightLUT(); |
95 | SetupDitheringConstants(); |
96 | |
97 | return 0; |
6f2ee2be |
98 | } |
99 | |
e929dec5 |
100 | void renderer_finish(void) |
101 | { |
102 | } |
103 | |
104 | void renderer_notify_res_change(void) |
105 | { |
030d1121 |
106 | if (PixelSkipEnabled()) { |
107 | // Set blit_mask for high horizontal resolutions. This allows skipping |
108 | // rendering pixels that would never get displayed on low-resolution |
109 | // platforms that use simple pixel-dropping scaler. |
110 | |
111 | switch (gpu.screen.hres) |
112 | { |
113 | case 512: gpu_unai.blit_mask = 0xa4; break; // GPU_BlitWWSWWSWS |
114 | case 640: gpu_unai.blit_mask = 0xaa; break; // GPU_BlitWS |
115 | default: gpu_unai.blit_mask = 0; break; |
116 | } |
117 | } else { |
118 | gpu_unai.blit_mask = 0; |
119 | } |
120 | |
121 | if (LineSkipEnabled()) { |
122 | // Set rendering line-skip (only render every other line in high-res |
123 | // 480 vertical mode, or, optionally, force it for all video modes) |
124 | |
125 | if (gpu.screen.vres == 480) { |
126 | if (gpu_unai.config.ilace_force) { |
127 | gpu_unai.ilace_mask = 3; // Only need 1/4 of lines |
128 | } else { |
129 | gpu_unai.ilace_mask = 1; // Only need 1/2 of lines |
130 | } |
131 | } else { |
132 | // Vert resolution changed from 480 to lower one |
133 | gpu_unai.ilace_mask = gpu_unai.config.ilace_force; |
134 | } |
135 | } else { |
136 | gpu_unai.ilace_mask = 0; |
137 | } |
138 | |
139 | /* |
140 | printf("res change hres: %d vres: %d depth: %d ilace_mask: %d\n", |
141 | gpu.screen.hres, gpu.screen.vres, gpu.status.rgb24 ? 24 : 15, |
142 | gpu_unai.ilace_mask); |
143 | */ |
144 | } |
145 | |
146 | // Handles GP0 draw settings commands 0xE1...0xE6 |
147 | static void gpuGP0Cmd_0xEx(gpu_unai_t &gpu_unai, u32 cmd_word) |
148 | { |
149 | // Assume incoming GP0 command is 0xE1..0xE6, convert to 1..6 |
150 | u8 num = (cmd_word >> 24) & 7; |
151 | gpu.ex_regs[num] = cmd_word; // Update gpulib register |
152 | switch (num) { |
153 | case 1: { |
154 | // GP0(E1h) - Draw Mode setting (aka "Texpage") |
155 | u32 cur_texpage = gpu_unai.GPU_GP1 & 0x7FF; |
156 | u32 new_texpage = cmd_word & 0x7FF; |
157 | if (cur_texpage != new_texpage) { |
158 | gpu_unai.GPU_GP1 = (gpu_unai.GPU_GP1 & ~0x7FF) | new_texpage; |
159 | gpuSetTexture(gpu_unai.GPU_GP1); |
160 | } |
161 | } break; |
162 | |
163 | case 2: { |
164 | // GP0(E2h) - Texture Window setting |
165 | if (cmd_word != gpu_unai.TextureWindowCur) { |
166 | static const u8 TextureMask[32] = { |
167 | 255, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7, |
168 | 127, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7 |
169 | }; |
170 | gpu_unai.TextureWindowCur = cmd_word; |
171 | gpu_unai.TextureWindow[0] = ((cmd_word >> 10) & 0x1F) << 3; |
172 | gpu_unai.TextureWindow[1] = ((cmd_word >> 15) & 0x1F) << 3; |
173 | gpu_unai.TextureWindow[2] = TextureMask[(cmd_word >> 0) & 0x1F]; |
174 | gpu_unai.TextureWindow[3] = TextureMask[(cmd_word >> 5) & 0x1F]; |
175 | gpu_unai.TextureWindow[0] &= ~gpu_unai.TextureWindow[2]; |
176 | gpu_unai.TextureWindow[1] &= ~gpu_unai.TextureWindow[3]; |
177 | |
178 | // Inner loop vars must be updated whenever texture window is changed: |
179 | const u32 fb = FIXED_BITS; // # of fractional fixed-pt bits of u4/v4 |
180 | gpu_unai.u_msk = (((u32)gpu_unai.TextureWindow[2]) << fb) | ((1 << fb) - 1); |
181 | gpu_unai.v_msk = (((u32)gpu_unai.TextureWindow[3]) << fb) | ((1 << fb) - 1); |
182 | |
183 | gpuSetTexture(gpu_unai.GPU_GP1); |
184 | } |
185 | } break; |
186 | |
187 | case 3: { |
188 | // GP0(E3h) - Set Drawing Area top left (X1,Y1) |
189 | gpu_unai.DrawingArea[0] = cmd_word & 0x3FF; |
190 | gpu_unai.DrawingArea[1] = (cmd_word >> 10) & 0x3FF; |
191 | } break; |
192 | |
193 | case 4: { |
194 | // GP0(E4h) - Set Drawing Area bottom right (X2,Y2) |
195 | gpu_unai.DrawingArea[2] = (cmd_word & 0x3FF) + 1; |
196 | gpu_unai.DrawingArea[3] = ((cmd_word >> 10) & 0x3FF) + 1; |
197 | } break; |
198 | |
199 | case 5: { |
200 | // GP0(E5h) - Set Drawing Offset (X,Y) |
201 | gpu_unai.DrawingOffset[0] = ((s32)cmd_word<<(32-11))>>(32-11); |
202 | gpu_unai.DrawingOffset[1] = ((s32)cmd_word<<(32-22))>>(32-11); |
203 | } break; |
204 | |
205 | case 6: { |
206 | // GP0(E6h) - Mask Bit Setting |
207 | gpu_unai.Masking = (cmd_word & 0x2) << 1; |
208 | gpu_unai.PixelMSB = (cmd_word & 0x1) << 8; |
209 | } break; |
210 | } |
e929dec5 |
211 | } |
212 | |
6f2ee2be |
213 | extern const unsigned char cmd_lengths[256]; |
214 | |
5f315a8f |
215 | int do_cmd_list(u32 *list, int list_len, int *last_cmd) |
6f2ee2be |
216 | { |
5f315a8f |
217 | u32 cmd = 0, len, i; |
218 | u32 *list_start = list; |
219 | u32 *list_end = list + list_len; |
6f2ee2be |
220 | |
030d1121 |
221 | //TODO: set ilace_mask when resolution changes instead of every time, |
222 | // eliminate #ifdef below. |
223 | gpu_unai.ilace_mask = gpu_unai.config.ilace_force; |
224 | |
8f2bb0cb |
225 | #ifdef HAVE_PRE_ARMV7 /* XXX */ |
030d1121 |
226 | gpu_unai.ilace_mask |= gpu.status.interlace; |
89c0de42 |
227 | #endif |
228 | |
6f2ee2be |
229 | for (; list < list_end; list += 1 + len) |
230 | { |
6f2ee2be |
231 | cmd = *list >> 24; |
232 | len = cmd_lengths[cmd]; |
b243416b |
233 | if (list + 1 + len > list_end) { |
234 | cmd = -1; |
235 | break; |
236 | } |
237 | |
42a261f1 |
238 | #define PRIM cmd |
030d1121 |
239 | gpu_unai.PacketBuffer.U4[0] = list[0]; |
42a261f1 |
240 | for (i = 1; i <= len; i++) |
030d1121 |
241 | gpu_unai.PacketBuffer.U4[i] = list[i]; |
242 | |
243 | PtrUnion packet = { .ptr = (void*)&gpu_unai.PacketBuffer }; |
6f2ee2be |
244 | |
42a261f1 |
245 | switch (cmd) |
6f2ee2be |
246 | { |
42a261f1 |
247 | case 0x02: |
030d1121 |
248 | gpuClearImage(packet); |
42a261f1 |
249 | break; |
250 | |
251 | case 0x20: |
252 | case 0x21: |
253 | case 0x22: |
030d1121 |
254 | case 0x23: { // Monochrome 3-pt poly |
255 | PP driver = gpuPolySpanDrivers[ |
256 | (gpu_unai.blit_mask?1024:0) | |
257 | Blending_Mode | |
258 | gpu_unai.Masking | Blending | gpu_unai.PixelMSB |
259 | ]; |
260 | gpuDrawPolyF(packet, driver, false); |
261 | } break; |
42a261f1 |
262 | |
263 | case 0x24: |
264 | case 0x25: |
265 | case 0x26: |
030d1121 |
266 | case 0x27: { // Textured 3-pt poly |
267 | gpuSetCLUT (gpu_unai.PacketBuffer.U4[2] >> 16); |
268 | gpuSetTexture(gpu_unai.PacketBuffer.U4[4] >> 16); |
269 | |
270 | u32 driver_idx = |
271 | (gpu_unai.blit_mask?1024:0) | |
272 | Dithering | |
273 | Blending_Mode | gpu_unai.TEXT_MODE | |
274 | gpu_unai.Masking | Blending | gpu_unai.PixelMSB; |
275 | |
276 | if (!FastLightingEnabled()) { |
277 | driver_idx |= Lighting; |
278 | } else { |
279 | if (!((gpu_unai.PacketBuffer.U1[0]>0x5F) && (gpu_unai.PacketBuffer.U1[1]>0x5F) && (gpu_unai.PacketBuffer.U1[2]>0x5F))) |
280 | driver_idx |= Lighting; |
281 | } |
282 | |
283 | PP driver = gpuPolySpanDrivers[driver_idx]; |
284 | gpuDrawPolyFT(packet, driver, false); |
285 | } break; |
42a261f1 |
286 | |
287 | case 0x28: |
288 | case 0x29: |
289 | case 0x2A: |
030d1121 |
290 | case 0x2B: { // Monochrome 4-pt poly |
291 | PP driver = gpuPolySpanDrivers[ |
292 | (gpu_unai.blit_mask?1024:0) | |
293 | Blending_Mode | |
294 | gpu_unai.Masking | Blending | gpu_unai.PixelMSB |
295 | ]; |
296 | gpuDrawPolyF(packet, driver, true); // is_quad = true |
297 | } break; |
42a261f1 |
298 | |
299 | case 0x2C: |
300 | case 0x2D: |
301 | case 0x2E: |
030d1121 |
302 | case 0x2F: { // Textured 4-pt poly |
303 | gpuSetCLUT (gpu_unai.PacketBuffer.U4[2] >> 16); |
304 | gpuSetTexture(gpu_unai.PacketBuffer.U4[4] >> 16); |
305 | |
306 | u32 driver_idx = |
307 | (gpu_unai.blit_mask?1024:0) | |
308 | Dithering | |
309 | Blending_Mode | gpu_unai.TEXT_MODE | |
310 | gpu_unai.Masking | Blending | gpu_unai.PixelMSB; |
311 | |
312 | if (!FastLightingEnabled()) { |
313 | driver_idx |= Lighting; |
314 | } else { |
315 | if (!((gpu_unai.PacketBuffer.U1[0]>0x5F) && (gpu_unai.PacketBuffer.U1[1]>0x5F) && (gpu_unai.PacketBuffer.U1[2]>0x5F))) |
316 | driver_idx |= Lighting; |
317 | } |
318 | |
319 | PP driver = gpuPolySpanDrivers[driver_idx]; |
320 | gpuDrawPolyFT(packet, driver, true); // is_quad = true |
321 | } break; |
42a261f1 |
322 | |
323 | case 0x30: |
324 | case 0x31: |
325 | case 0x32: |
030d1121 |
326 | case 0x33: { // Gouraud-shaded 3-pt poly |
327 | //NOTE: The '129' here is CF_GOURAUD | CF_LIGHT, however |
328 | // this is an untextured poly, so CF_LIGHT (texture blend) |
329 | // shouldn't apply. Until the original array of template |
330 | // instantiation ptrs is fixed, we're stuck with this. (TODO) |
331 | PP driver = gpuPolySpanDrivers[ |
332 | (gpu_unai.blit_mask?1024:0) | |
333 | Dithering | |
334 | Blending_Mode | |
335 | gpu_unai.Masking | Blending | 129 | gpu_unai.PixelMSB |
336 | ]; |
337 | gpuDrawPolyG(packet, driver, false); |
338 | } break; |
42a261f1 |
339 | |
340 | case 0x34: |
341 | case 0x35: |
342 | case 0x36: |
030d1121 |
343 | case 0x37: { // Gouraud-shaded, textured 3-pt poly |
344 | gpuSetCLUT (gpu_unai.PacketBuffer.U4[2] >> 16); |
345 | gpuSetTexture (gpu_unai.PacketBuffer.U4[5] >> 16); |
346 | PP driver = gpuPolySpanDrivers[ |
347 | (gpu_unai.blit_mask?1024:0) | |
348 | Dithering | |
349 | Blending_Mode | gpu_unai.TEXT_MODE | |
350 | gpu_unai.Masking | Blending | ((Lighting)?129:0) | gpu_unai.PixelMSB |
351 | ]; |
352 | gpuDrawPolyGT(packet, driver, false); |
353 | } break; |
42a261f1 |
354 | |
355 | case 0x38: |
356 | case 0x39: |
357 | case 0x3A: |
030d1121 |
358 | case 0x3B: { // Gouraud-shaded 4-pt poly |
359 | // See notes regarding '129' for 0x30..0x33 further above -senquack |
360 | PP driver = gpuPolySpanDrivers[ |
361 | (gpu_unai.blit_mask?1024:0) | |
362 | Dithering | |
363 | Blending_Mode | |
364 | gpu_unai.Masking | Blending | 129 | gpu_unai.PixelMSB |
365 | ]; |
366 | gpuDrawPolyG(packet, driver, true); // is_quad = true |
367 | } break; |
42a261f1 |
368 | |
369 | case 0x3C: |
370 | case 0x3D: |
371 | case 0x3E: |
030d1121 |
372 | case 0x3F: { // Gouraud-shaded, textured 4-pt poly |
373 | gpuSetCLUT (gpu_unai.PacketBuffer.U4[2] >> 16); |
374 | gpuSetTexture (gpu_unai.PacketBuffer.U4[5] >> 16); |
375 | PP driver = gpuPolySpanDrivers[ |
376 | (gpu_unai.blit_mask?1024:0) | |
377 | Dithering | |
378 | Blending_Mode | gpu_unai.TEXT_MODE | |
379 | gpu_unai.Masking | Blending | ((Lighting)?129:0) | gpu_unai.PixelMSB |
380 | ]; |
381 | gpuDrawPolyGT(packet, driver, true); // is_quad = true |
382 | } break; |
42a261f1 |
383 | |
384 | case 0x40: |
385 | case 0x41: |
386 | case 0x42: |
030d1121 |
387 | case 0x43: { // Monochrome line |
388 | // Shift index right by one, as untextured prims don't use lighting |
389 | u32 driver_idx = (Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1; |
390 | PSD driver = gpuPixelSpanDrivers[driver_idx]; |
391 | gpuDrawLineF(packet, driver); |
392 | } break; |
393 | |
394 | case 0x48 ... 0x4F: { // Monochrome line strip |
6f2ee2be |
395 | u32 num_vertexes = 1; |
5f315a8f |
396 | u32 *list_position = &(list[2]); |
8aea5f5a |
397 | |
030d1121 |
398 | // Shift index right by one, as untextured prims don't use lighting |
399 | u32 driver_idx = (Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1; |
400 | PSD driver = gpuPixelSpanDrivers[driver_idx]; |
401 | gpuDrawLineF(packet, driver); |
6f2ee2be |
402 | |
403 | while(1) |
404 | { |
030d1121 |
405 | gpu_unai.PacketBuffer.U4[1] = gpu_unai.PacketBuffer.U4[2]; |
406 | gpu_unai.PacketBuffer.U4[2] = *list_position++; |
407 | gpuDrawLineF(packet, driver); |
8aea5f5a |
408 | |
6f2ee2be |
409 | num_vertexes++; |
5f315a8f |
410 | if(list_position >= list_end) { |
804789d7 |
411 | cmd = -1; |
412 | goto breakloop; |
413 | } |
414 | if((*list_position & 0xf000f000) == 0x50005000) |
b243416b |
415 | break; |
6f2ee2be |
416 | } |
417 | |
b243416b |
418 | len += (num_vertexes - 2); |
030d1121 |
419 | } break; |
6f2ee2be |
420 | |
42a261f1 |
421 | case 0x50: |
422 | case 0x51: |
423 | case 0x52: |
030d1121 |
424 | case 0x53: { // Gouraud-shaded line |
425 | // Shift index right by one, as untextured prims don't use lighting |
426 | u32 driver_idx = (Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1; |
427 | // Index MSB selects Gouraud-shaded PixelSpanDriver: |
428 | driver_idx |= (1 << 5); |
429 | PSD driver = gpuPixelSpanDrivers[driver_idx]; |
430 | gpuDrawLineG(packet, driver); |
431 | } break; |
432 | |
433 | case 0x58 ... 0x5F: { // Gouraud-shaded line strip |
6f2ee2be |
434 | u32 num_vertexes = 1; |
5f315a8f |
435 | u32 *list_position = &(list[2]); |
8aea5f5a |
436 | |
030d1121 |
437 | // Shift index right by one, as untextured prims don't use lighting |
438 | u32 driver_idx = (Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1; |
439 | // Index MSB selects Gouraud-shaded PixelSpanDriver: |
440 | driver_idx |= (1 << 5); |
441 | PSD driver = gpuPixelSpanDrivers[driver_idx]; |
442 | gpuDrawLineG(packet, driver); |
6f2ee2be |
443 | |
444 | while(1) |
445 | { |
030d1121 |
446 | gpu_unai.PacketBuffer.U4[0] = gpu_unai.PacketBuffer.U4[2]; |
447 | gpu_unai.PacketBuffer.U4[1] = gpu_unai.PacketBuffer.U4[3]; |
448 | gpu_unai.PacketBuffer.U4[2] = *list_position++; |
449 | gpu_unai.PacketBuffer.U4[3] = *list_position++; |
450 | gpuDrawLineG(packet, driver); |
8aea5f5a |
451 | |
6f2ee2be |
452 | num_vertexes++; |
5f315a8f |
453 | if(list_position >= list_end) { |
804789d7 |
454 | cmd = -1; |
455 | goto breakloop; |
456 | } |
457 | if((*list_position & 0xf000f000) == 0x50005000) |
b243416b |
458 | break; |
6f2ee2be |
459 | } |
460 | |
b243416b |
461 | len += (num_vertexes - 2) * 2; |
030d1121 |
462 | } break; |
6f2ee2be |
463 | |
42a261f1 |
464 | case 0x60: |
465 | case 0x61: |
466 | case 0x62: |
030d1121 |
467 | case 0x63: { // Monochrome rectangle (variable size) |
468 | PT driver = gpuTileSpanDrivers[(Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1]; |
469 | gpuDrawT(packet, driver); |
470 | } break; |
42a261f1 |
471 | |
472 | case 0x64: |
473 | case 0x65: |
474 | case 0x66: |
030d1121 |
475 | case 0x67: { // Textured rectangle (variable size) |
476 | gpuSetCLUT (gpu_unai.PacketBuffer.U4[2] >> 16); |
477 | u32 driver_idx = Blending_Mode | gpu_unai.TEXT_MODE | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>1); |
478 | |
479 | //senquack - Only color 808080h-878787h allows skipping lighting calculation: |
480 | // This fixes Silent Hill running animation on loading screens: |
481 | // (On PSX, color values 0x00-0x7F darken the source texture's color, |
482 | // 0x81-FF lighten textures (ultimately clamped to 0x1F), |
483 | // 0x80 leaves source texture color unchanged, HOWEVER, |
484 | // gpu_unai uses a simple lighting LUT whereby only the upper |
485 | // 5 bits of an 8-bit color are used, so 0x80-0x87 all behave as |
486 | // 0x80. |
487 | // |
488 | // NOTE: I've changed all textured sprite draw commands here and |
489 | // elsewhere to use proper behavior, but left poly commands |
490 | // alone, I don't want to slow rendering down too much. (TODO) |
491 | //if ((gpu_unai.PacketBuffer.U1[0]>0x5F) && (gpu_unai.PacketBuffer.U1[1]>0x5F) && (gpu_unai.PacketBuffer.U1[2]>0x5F)) |
492 | // Strip lower 3 bits of each color and determine if lighting should be used: |
493 | if ((gpu_unai.PacketBuffer.U4[0] & 0xF8F8F8) != 0x808080) |
494 | driver_idx |= Lighting; |
495 | PS driver = gpuSpriteSpanDrivers[driver_idx]; |
496 | gpuDrawS(packet, driver); |
497 | } break; |
42a261f1 |
498 | |
499 | case 0x68: |
500 | case 0x69: |
501 | case 0x6A: |
030d1121 |
502 | case 0x6B: { // Monochrome rectangle (1x1 dot) |
503 | gpu_unai.PacketBuffer.U4[2] = 0x00010001; |
504 | PT driver = gpuTileSpanDrivers[(Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1]; |
505 | gpuDrawT(packet, driver); |
506 | } break; |
42a261f1 |
507 | |
508 | case 0x70: |
509 | case 0x71: |
510 | case 0x72: |
030d1121 |
511 | case 0x73: { // Monochrome rectangle (8x8) |
512 | gpu_unai.PacketBuffer.U4[2] = 0x00080008; |
513 | PT driver = gpuTileSpanDrivers[(Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1]; |
514 | gpuDrawT(packet, driver); |
515 | } break; |
42a261f1 |
516 | |
517 | case 0x74: |
518 | case 0x75: |
519 | case 0x76: |
030d1121 |
520 | case 0x77: { // Textured rectangle (8x8) |
521 | gpu_unai.PacketBuffer.U4[3] = 0x00080008; |
522 | gpuSetCLUT (gpu_unai.PacketBuffer.U4[2] >> 16); |
523 | u32 driver_idx = Blending_Mode | gpu_unai.TEXT_MODE | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>1); |
524 | |
525 | //senquack - Only color 808080h-878787h allows skipping lighting calculation: |
526 | //if ((gpu_unai.PacketBuffer.U1[0]>0x5F) && (gpu_unai.PacketBuffer.U1[1]>0x5F) && (gpu_unai.PacketBuffer.U1[2]>0x5F)) |
527 | // Strip lower 3 bits of each color and determine if lighting should be used: |
528 | if ((gpu_unai.PacketBuffer.U4[0] & 0xF8F8F8) != 0x808080) |
529 | driver_idx |= Lighting; |
530 | PS driver = gpuSpriteSpanDrivers[driver_idx]; |
531 | gpuDrawS(packet, driver); |
532 | } break; |
42a261f1 |
533 | |
534 | case 0x78: |
535 | case 0x79: |
536 | case 0x7A: |
030d1121 |
537 | case 0x7B: { // Monochrome rectangle (16x16) |
538 | gpu_unai.PacketBuffer.U4[2] = 0x00100010; |
539 | PT driver = gpuTileSpanDrivers[(Blending_Mode | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>3)) >> 1]; |
540 | gpuDrawT(packet, driver); |
541 | } break; |
42a261f1 |
542 | |
543 | case 0x7C: |
544 | case 0x7D: |
545 | #ifdef __arm__ |
030d1121 |
546 | if ((gpu_unai.GPU_GP1 & 0x180) == 0 && (gpu_unai.Masking | gpu_unai.PixelMSB) == 0) |
42a261f1 |
547 | { |
030d1121 |
548 | gpuSetCLUT (gpu_unai.PacketBuffer.U4[2] >> 16); |
549 | gpuDrawS16(packet); |
42a261f1 |
550 | break; |
551 | } |
552 | // fallthrough |
553 | #endif |
554 | case 0x7E: |
030d1121 |
555 | case 0x7F: { // Textured rectangle (16x16) |
556 | gpu_unai.PacketBuffer.U4[3] = 0x00100010; |
557 | gpuSetCLUT (gpu_unai.PacketBuffer.U4[2] >> 16); |
558 | u32 driver_idx = Blending_Mode | gpu_unai.TEXT_MODE | gpu_unai.Masking | Blending | (gpu_unai.PixelMSB>>1); |
559 | //senquack - Only color 808080h-878787h allows skipping lighting calculation: |
560 | //if ((gpu_unai.PacketBuffer.U1[0]>0x5F) && (gpu_unai.PacketBuffer.U1[1]>0x5F) && (gpu_unai.PacketBuffer.U1[2]>0x5F)) |
561 | // Strip lower 3 bits of each color and determine if lighting should be used: |
562 | if ((gpu_unai.PacketBuffer.U4[0] & 0xF8F8F8) != 0x808080) |
563 | driver_idx |= Lighting; |
564 | PS driver = gpuSpriteSpanDrivers[driver_idx]; |
565 | gpuDrawS(packet, driver); |
566 | } break; |
42a261f1 |
567 | |
568 | case 0x80: // vid -> vid |
030d1121 |
569 | gpuMoveImage(packet); |
42a261f1 |
570 | break; |
030d1121 |
571 | |
9a6e7816 |
572 | #ifdef TEST |
573 | case 0xA0: // sys -> vid |
574 | { |
575 | u32 load_width = list[2] & 0xffff; |
576 | u32 load_height = list[2] >> 16; |
577 | u32 load_size = load_width * load_height; |
578 | |
579 | len += load_size / 2; |
030d1121 |
580 | } break; |
581 | |
42a261f1 |
582 | case 0xC0: |
583 | break; |
584 | #else |
585 | case 0xA0: // sys ->vid |
586 | case 0xC0: // vid -> sys |
030d1121 |
587 | // Handled by gpulib |
42a261f1 |
588 | goto breakloop; |
9a6e7816 |
589 | #endif |
030d1121 |
590 | case 0xE1 ... 0xE6: { // Draw settings |
591 | gpuGP0Cmd_0xEx(gpu_unai, gpu_unai.PacketBuffer.U4[0]); |
592 | } break; |
6f2ee2be |
593 | } |
594 | } |
b243416b |
595 | |
42a261f1 |
596 | breakloop: |
b243416b |
597 | gpu.ex_regs[1] &= ~0x1ff; |
030d1121 |
598 | gpu.ex_regs[1] |= gpu_unai.GPU_GP1 & 0x1ff; |
b243416b |
599 | |
600 | *last_cmd = cmd; |
601 | return list - list_start; |
6f2ee2be |
602 | } |
603 | |
604 | void renderer_sync_ecmds(uint32_t *ecmds) |
605 | { |
42a261f1 |
606 | int dummy; |
607 | do_cmd_list(&ecmds[1], 6, &dummy); |
6f2ee2be |
608 | } |
609 | |
05740673 |
610 | void renderer_update_caches(int x, int y, int w, int h) |
6f2ee2be |
611 | { |
612 | } |
613 | |
614 | void renderer_flush_queues(void) |
615 | { |
616 | } |
914455e6 |
617 | |
5440b88e |
618 | void renderer_set_interlace(int enable, int is_odd) |
619 | { |
620 | } |
621 | |
914455e6 |
622 | #include "../../frontend/plugin_lib.h" |
030d1121 |
623 | // Handle any gpulib settings applicable to gpu_unai: |
914455e6 |
624 | void renderer_set_config(const struct rearmed_cbs *cbs) |
625 | { |
030d1121 |
626 | gpu_unai.vram = (u16*)gpu.vram; |
627 | gpu_unai.config.ilace_force = cbs->gpu_unai.ilace_force; |
628 | gpu_unai.config.pixel_skip = cbs->gpu_unai.pixel_skip; |
629 | gpu_unai.config.lighting = cbs->gpu_unai.lighting; |
630 | gpu_unai.config.fast_lighting = cbs->gpu_unai.fast_lighting; |
631 | gpu_unai.config.blending = cbs->gpu_unai.blending; |
632 | gpu_unai.config.dithering = cbs->gpu_unai.dithering; |
914455e6 |
633 | } |
9a6e7816 |
634 | |
42a261f1 |
635 | // vim:shiftwidth=2:expandtab |