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