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 | |
147 | #ifdef USE_GPULIB |
148 | // Handles GP0 draw settings commands 0xE1...0xE6 |
149 | static void gpuGP0Cmd_0xEx(gpu_senquack_t &gpu_senquack, u32 cmd_word) |
150 | { |
151 | // Assume incoming GP0 command is 0xE1..0xE6, convert to 1..6 |
152 | u8 num = (cmd_word >> 24) & 7; |
153 | gpu.ex_regs[num] = cmd_word; // Update gpulib register |
154 | switch (num) { |
155 | case 1: { |
156 | // GP0(E1h) - Draw Mode setting (aka "Texpage") |
157 | u32 cur_texpage = gpu_senquack.GPU_GP1 & 0x7FF; |
158 | u32 new_texpage = cmd_word & 0x7FF; |
159 | if (cur_texpage != new_texpage) { |
160 | gpu_senquack.GPU_GP1 = (gpu_senquack.GPU_GP1 & ~0x7FF) | new_texpage; |
161 | gpuSetTexture(gpu_senquack.GPU_GP1); |
162 | } |
163 | } break; |
164 | |
165 | case 2: { |
166 | // GP0(E2h) - Texture Window setting |
167 | if (cmd_word != gpu_senquack.TextureWindowCur) { |
168 | static const u8 TextureMask[32] = { |
169 | 255, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7, |
170 | 127, 7, 15, 7, 31, 7, 15, 7, 63, 7, 15, 7, 31, 7, 15, 7 |
171 | }; |
172 | gpu_senquack.TextureWindowCur = cmd_word; |
173 | gpu_senquack.TextureWindow[0] = ((cmd_word >> 10) & 0x1F) << 3; |
174 | gpu_senquack.TextureWindow[1] = ((cmd_word >> 15) & 0x1F) << 3; |
175 | gpu_senquack.TextureWindow[2] = TextureMask[(cmd_word >> 0) & 0x1F]; |
176 | gpu_senquack.TextureWindow[3] = TextureMask[(cmd_word >> 5) & 0x1F]; |
177 | gpu_senquack.TextureWindow[0] &= ~gpu_senquack.TextureWindow[2]; |
178 | gpu_senquack.TextureWindow[1] &= ~gpu_senquack.TextureWindow[3]; |
179 | |
180 | // Inner loop vars must be updated whenever texture window is changed: |
181 | const u32 fb = FIXED_BITS; // # of fractional fixed-pt bits of u4/v4 |
182 | gpu_senquack.u_msk = (((u32)gpu_senquack.TextureWindow[2]) << fb) | ((1 << fb) - 1); |
183 | gpu_senquack.v_msk = (((u32)gpu_senquack.TextureWindow[3]) << fb) | ((1 << fb) - 1); |
184 | |
185 | gpuSetTexture(gpu_senquack.GPU_GP1); |
186 | } |
187 | } break; |
188 | |
189 | case 3: { |
190 | // GP0(E3h) - Set Drawing Area top left (X1,Y1) |
191 | gpu_senquack.DrawingArea[0] = cmd_word & 0x3FF; |
192 | gpu_senquack.DrawingArea[1] = (cmd_word >> 10) & 0x3FF; |
193 | } break; |
194 | |
195 | case 4: { |
196 | // GP0(E4h) - Set Drawing Area bottom right (X2,Y2) |
197 | gpu_senquack.DrawingArea[2] = (cmd_word & 0x3FF) + 1; |
198 | gpu_senquack.DrawingArea[3] = ((cmd_word >> 10) & 0x3FF) + 1; |
199 | } break; |
200 | |
201 | case 5: { |
202 | // GP0(E5h) - Set Drawing Offset (X,Y) |
203 | gpu_senquack.DrawingOffset[0] = ((s32)cmd_word<<(32-11))>>(32-11); |
204 | gpu_senquack.DrawingOffset[1] = ((s32)cmd_word<<(32-22))>>(32-11); |
205 | } break; |
206 | |
207 | case 6: { |
208 | // GP0(E6h) - Mask Bit Setting |
209 | gpu_senquack.Masking = (cmd_word & 0x2) << 1; |
210 | gpu_senquack.PixelMSB = (cmd_word & 0x1) << 8; |
211 | } break; |
212 | } |
213 | } |
214 | #endif |
215 | |
216 | extern const unsigned char cmd_lengths[256]; |
217 | |
218 | int do_cmd_list(u32 *list, int list_len, int *last_cmd) |
219 | { |
220 | u32 cmd = 0, len, i; |
221 | u32 *list_start = list; |
222 | u32 *list_end = list + list_len; |
223 | |
224 | //TODO: set ilace_mask when resolution changes instead of every time, |
225 | // eliminate #ifdef below. |
226 | gpu_senquack.ilace_mask = gpu_senquack.config.ilace_force; |
227 | |
228 | #ifdef HAVE_PRE_ARMV7 /* XXX */ |
229 | gpu_senquack.ilace_mask |= gpu.status.interlace; |
230 | #endif |
231 | if (gpu_senquack.config.scale_hires) { |
232 | gpu_senquack.ilace_mask |= gpu.status.interlace; |
233 | } |
234 | |
235 | for (; list < list_end; list += 1 + len) |
236 | { |
237 | cmd = *list >> 24; |
238 | len = cmd_lengths[cmd]; |
239 | if (list + 1 + len > list_end) { |
240 | cmd = -1; |
241 | break; |
242 | } |
243 | |
244 | #define PRIM cmd |
245 | gpu_senquack.PacketBuffer.U4[0] = list[0]; |
246 | for (i = 1; i <= len; i++) |
247 | gpu_senquack.PacketBuffer.U4[i] = list[i]; |
248 | |
249 | PtrUnion packet = { .ptr = (void*)&gpu_senquack.PacketBuffer }; |
250 | |
251 | switch (cmd) |
252 | { |
253 | case 0x02: |
254 | gpuClearImage(packet); |
255 | break; |
256 | |
257 | case 0x20: |
258 | case 0x21: |
259 | case 0x22: |
260 | case 0x23: { // Monochrome 3-pt poly |
261 | PP driver = gpuPolySpanDrivers[ |
262 | (gpu_senquack.blit_mask?1024:0) | |
263 | Blending_Mode | |
264 | gpu_senquack.Masking | Blending | gpu_senquack.PixelMSB |
265 | ]; |
266 | gpuDrawPolyF(packet, driver, false); |
267 | } break; |
268 | |
269 | case 0x24: |
270 | case 0x25: |
271 | case 0x26: |
272 | case 0x27: { // Textured 3-pt poly |
273 | gpuSetCLUT (gpu_senquack.PacketBuffer.U4[2] >> 16); |
274 | gpuSetTexture(gpu_senquack.PacketBuffer.U4[4] >> 16); |
275 | |
276 | u32 driver_idx = |
277 | (gpu_senquack.blit_mask?1024:0) | |
278 | Dithering | |
279 | Blending_Mode | gpu_senquack.TEXT_MODE | |
280 | gpu_senquack.Masking | Blending | gpu_senquack.PixelMSB; |
281 | |
282 | if (!FastLightingEnabled()) { |
283 | driver_idx |= Lighting; |
284 | } else { |
285 | if (!((gpu_senquack.PacketBuffer.U1[0]>0x5F) && (gpu_senquack.PacketBuffer.U1[1]>0x5F) && (gpu_senquack.PacketBuffer.U1[2]>0x5F))) |
286 | driver_idx |= Lighting; |
287 | } |
288 | |
289 | PP driver = gpuPolySpanDrivers[driver_idx]; |
290 | gpuDrawPolyFT(packet, driver, false); |
291 | } break; |
292 | |
293 | case 0x28: |
294 | case 0x29: |
295 | case 0x2A: |
296 | case 0x2B: { // Monochrome 4-pt poly |
297 | PP driver = gpuPolySpanDrivers[ |
298 | (gpu_senquack.blit_mask?1024:0) | |
299 | Blending_Mode | |
300 | gpu_senquack.Masking | Blending | gpu_senquack.PixelMSB |
301 | ]; |
302 | gpuDrawPolyF(packet, driver, true); // is_quad = true |
303 | } break; |
304 | |
305 | case 0x2C: |
306 | case 0x2D: |
307 | case 0x2E: |
308 | case 0x2F: { // Textured 4-pt poly |
309 | gpuSetCLUT (gpu_senquack.PacketBuffer.U4[2] >> 16); |
310 | gpuSetTexture(gpu_senquack.PacketBuffer.U4[4] >> 16); |
311 | |
312 | u32 driver_idx = |
313 | (gpu_senquack.blit_mask?1024:0) | |
314 | Dithering | |
315 | Blending_Mode | gpu_senquack.TEXT_MODE | |
316 | gpu_senquack.Masking | Blending | gpu_senquack.PixelMSB; |
317 | |
318 | if (!FastLightingEnabled()) { |
319 | driver_idx |= Lighting; |
320 | } else { |
321 | if (!((gpu_senquack.PacketBuffer.U1[0]>0x5F) && (gpu_senquack.PacketBuffer.U1[1]>0x5F) && (gpu_senquack.PacketBuffer.U1[2]>0x5F))) |
322 | driver_idx |= Lighting; |
323 | } |
324 | |
325 | PP driver = gpuPolySpanDrivers[driver_idx]; |
326 | gpuDrawPolyFT(packet, driver, true); // is_quad = true |
327 | } break; |
328 | |
329 | case 0x30: |
330 | case 0x31: |
331 | case 0x32: |
332 | case 0x33: { // Gouraud-shaded 3-pt poly |
333 | //NOTE: The '129' here is CF_GOURAUD | CF_LIGHT, however |
334 | // this is an untextured poly, so CF_LIGHT (texture blend) |
335 | // shouldn't apply. Until the original array of template |
336 | // instantiation ptrs is fixed, we're stuck with this. (TODO) |
337 | PP driver = gpuPolySpanDrivers[ |
338 | (gpu_senquack.blit_mask?1024:0) | |
339 | Dithering | |
340 | Blending_Mode | |
341 | gpu_senquack.Masking | Blending | 129 | gpu_senquack.PixelMSB |
342 | ]; |
343 | gpuDrawPolyG(packet, driver, false); |
344 | } break; |
345 | |
346 | case 0x34: |
347 | case 0x35: |
348 | case 0x36: |
349 | case 0x37: { // Gouraud-shaded, textured 3-pt poly |
350 | gpuSetCLUT (gpu_senquack.PacketBuffer.U4[2] >> 16); |
351 | gpuSetTexture (gpu_senquack.PacketBuffer.U4[5] >> 16); |
352 | PP driver = gpuPolySpanDrivers[ |
353 | (gpu_senquack.blit_mask?1024:0) | |
354 | Dithering | |
355 | Blending_Mode | gpu_senquack.TEXT_MODE | |
356 | gpu_senquack.Masking | Blending | ((Lighting)?129:0) | gpu_senquack.PixelMSB |
357 | ]; |
358 | gpuDrawPolyGT(packet, driver, false); |
359 | } break; |
360 | |
361 | case 0x38: |
362 | case 0x39: |
363 | case 0x3A: |
364 | case 0x3B: { // Gouraud-shaded 4-pt poly |
365 | // See notes regarding '129' for 0x30..0x33 further above -senquack |
366 | PP driver = gpuPolySpanDrivers[ |
367 | (gpu_senquack.blit_mask?1024:0) | |
368 | Dithering | |
369 | Blending_Mode | |
370 | gpu_senquack.Masking | Blending | 129 | gpu_senquack.PixelMSB |
371 | ]; |
372 | gpuDrawPolyG(packet, driver, true); // is_quad = true |
373 | } break; |
374 | |
375 | case 0x3C: |
376 | case 0x3D: |
377 | case 0x3E: |
378 | case 0x3F: { // Gouraud-shaded, textured 4-pt poly |
379 | gpuSetCLUT (gpu_senquack.PacketBuffer.U4[2] >> 16); |
380 | gpuSetTexture (gpu_senquack.PacketBuffer.U4[5] >> 16); |
381 | PP driver = gpuPolySpanDrivers[ |
382 | (gpu_senquack.blit_mask?1024:0) | |
383 | Dithering | |
384 | Blending_Mode | gpu_senquack.TEXT_MODE | |
385 | gpu_senquack.Masking | Blending | ((Lighting)?129:0) | gpu_senquack.PixelMSB |
386 | ]; |
387 | gpuDrawPolyGT(packet, driver, true); // is_quad = true |
388 | } break; |
389 | |
390 | case 0x40: |
391 | case 0x41: |
392 | case 0x42: |
393 | case 0x43: { // Monochrome line |
394 | // Shift index right by one, as untextured prims don't use lighting |
395 | u32 driver_idx = (Blending_Mode | gpu_senquack.Masking | Blending | (gpu_senquack.PixelMSB>>3)) >> 1; |
396 | PSD driver = gpuPixelSpanDrivers[driver_idx]; |
397 | gpuDrawLineF(packet, driver); |
398 | } break; |
399 | |
400 | case 0x48 ... 0x4F: { // Monochrome line strip |
401 | u32 num_vertexes = 1; |
402 | u32 *list_position = &(list[2]); |
403 | |
404 | // Shift index right by one, as untextured prims don't use lighting |
405 | u32 driver_idx = (Blending_Mode | gpu_senquack.Masking | Blending | (gpu_senquack.PixelMSB>>3)) >> 1; |
406 | PSD driver = gpuPixelSpanDrivers[driver_idx]; |
407 | gpuDrawLineF(packet, driver); |
408 | |
409 | while(1) |
410 | { |
411 | gpu_senquack.PacketBuffer.U4[1] = gpu_senquack.PacketBuffer.U4[2]; |
412 | gpu_senquack.PacketBuffer.U4[2] = *list_position++; |
413 | gpuDrawLineF(packet, driver); |
414 | |
415 | num_vertexes++; |
416 | if(list_position >= list_end) { |
417 | cmd = -1; |
418 | goto breakloop; |
419 | } |
420 | if((*list_position & 0xf000f000) == 0x50005000) |
421 | break; |
422 | } |
423 | |
424 | len += (num_vertexes - 2); |
425 | } break; |
426 | |
427 | case 0x50: |
428 | case 0x51: |
429 | case 0x52: |
430 | case 0x53: { // Gouraud-shaded line |
431 | // Shift index right by one, as untextured prims don't use lighting |
432 | u32 driver_idx = (Blending_Mode | gpu_senquack.Masking | Blending | (gpu_senquack.PixelMSB>>3)) >> 1; |
433 | // Index MSB selects Gouraud-shaded PixelSpanDriver: |
434 | driver_idx |= (1 << 5); |
435 | PSD driver = gpuPixelSpanDrivers[driver_idx]; |
436 | gpuDrawLineG(packet, driver); |
437 | } break; |
438 | |
439 | case 0x58 ... 0x5F: { // Gouraud-shaded line strip |
440 | u32 num_vertexes = 1; |
441 | u32 *list_position = &(list[2]); |
442 | |
443 | // Shift index right by one, as untextured prims don't use lighting |
444 | u32 driver_idx = (Blending_Mode | gpu_senquack.Masking | Blending | (gpu_senquack.PixelMSB>>3)) >> 1; |
445 | // Index MSB selects Gouraud-shaded PixelSpanDriver: |
446 | driver_idx |= (1 << 5); |
447 | PSD driver = gpuPixelSpanDrivers[driver_idx]; |
448 | gpuDrawLineG(packet, driver); |
449 | |
450 | while(1) |
451 | { |
452 | gpu_senquack.PacketBuffer.U4[0] = gpu_senquack.PacketBuffer.U4[2]; |
453 | gpu_senquack.PacketBuffer.U4[1] = gpu_senquack.PacketBuffer.U4[3]; |
454 | gpu_senquack.PacketBuffer.U4[2] = *list_position++; |
455 | gpu_senquack.PacketBuffer.U4[3] = *list_position++; |
456 | gpuDrawLineG(packet, driver); |
457 | |
458 | num_vertexes++; |
459 | if(list_position >= list_end) { |
460 | cmd = -1; |
461 | goto breakloop; |
462 | } |
463 | if((*list_position & 0xf000f000) == 0x50005000) |
464 | break; |
465 | } |
466 | |
467 | len += (num_vertexes - 2) * 2; |
468 | } break; |
469 | |
470 | case 0x60: |
471 | case 0x61: |
472 | case 0x62: |
473 | case 0x63: { // Monochrome rectangle (variable size) |
474 | PT driver = gpuTileSpanDrivers[(Blending_Mode | gpu_senquack.Masking | Blending | (gpu_senquack.PixelMSB>>3)) >> 1]; |
475 | gpuDrawT(packet, driver); |
476 | } break; |
477 | |
478 | case 0x64: |
479 | case 0x65: |
480 | case 0x66: |
481 | case 0x67: { // Textured rectangle (variable size) |
482 | gpuSetCLUT (gpu_senquack.PacketBuffer.U4[2] >> 16); |
483 | u32 driver_idx = Blending_Mode | gpu_senquack.TEXT_MODE | gpu_senquack.Masking | Blending | (gpu_senquack.PixelMSB>>1); |
484 | |
485 | //senquack - Only color 808080h-878787h allows skipping lighting calculation: |
486 | // This fixes Silent Hill running animation on loading screens: |
487 | // (On PSX, color values 0x00-0x7F darken the source texture's color, |
488 | // 0x81-FF lighten textures (ultimately clamped to 0x1F), |
489 | // 0x80 leaves source texture color unchanged, HOWEVER, |
490 | // gpu_senquack uses a simple lighting LUT whereby only the upper |
491 | // 5 bits of an 8-bit color are used, so 0x80-0x87 all behave as |
492 | // 0x80. |
493 | // |
494 | // NOTE: I've changed all textured sprite draw commands here and |
495 | // elsewhere to use proper behavior, but left poly commands |
496 | // alone, I don't want to slow rendering down too much. (TODO) |
497 | //if ((gpu_senquack.PacketBuffer.U1[0]>0x5F) && (gpu_senquack.PacketBuffer.U1[1]>0x5F) && (gpu_senquack.PacketBuffer.U1[2]>0x5F)) |
498 | // Strip lower 3 bits of each color and determine if lighting should be used: |
499 | if ((gpu_senquack.PacketBuffer.U4[0] & 0xF8F8F8) != 0x808080) |
500 | driver_idx |= Lighting; |
501 | PS driver = gpuSpriteSpanDrivers[driver_idx]; |
502 | gpuDrawS(packet, driver); |
503 | } break; |
504 | |
505 | case 0x68: |
506 | case 0x69: |
507 | case 0x6A: |
508 | case 0x6B: { // Monochrome rectangle (1x1 dot) |
509 | gpu_senquack.PacketBuffer.U4[2] = 0x00010001; |
510 | PT driver = gpuTileSpanDrivers[(Blending_Mode | gpu_senquack.Masking | Blending | (gpu_senquack.PixelMSB>>3)) >> 1]; |
511 | gpuDrawT(packet, driver); |
512 | } break; |
513 | |
514 | case 0x70: |
515 | case 0x71: |
516 | case 0x72: |
517 | case 0x73: { // Monochrome rectangle (8x8) |
518 | gpu_senquack.PacketBuffer.U4[2] = 0x00080008; |
519 | PT driver = gpuTileSpanDrivers[(Blending_Mode | gpu_senquack.Masking | Blending | (gpu_senquack.PixelMSB>>3)) >> 1]; |
520 | gpuDrawT(packet, driver); |
521 | } break; |
522 | |
523 | case 0x74: |
524 | case 0x75: |
525 | case 0x76: |
526 | case 0x77: { // Textured rectangle (8x8) |
527 | gpu_senquack.PacketBuffer.U4[3] = 0x00080008; |
528 | gpuSetCLUT (gpu_senquack.PacketBuffer.U4[2] >> 16); |
529 | u32 driver_idx = Blending_Mode | gpu_senquack.TEXT_MODE | gpu_senquack.Masking | Blending | (gpu_senquack.PixelMSB>>1); |
530 | |
531 | //senquack - Only color 808080h-878787h allows skipping lighting calculation: |
532 | //if ((gpu_senquack.PacketBuffer.U1[0]>0x5F) && (gpu_senquack.PacketBuffer.U1[1]>0x5F) && (gpu_senquack.PacketBuffer.U1[2]>0x5F)) |
533 | // Strip lower 3 bits of each color and determine if lighting should be used: |
534 | if ((gpu_senquack.PacketBuffer.U4[0] & 0xF8F8F8) != 0x808080) |
535 | driver_idx |= Lighting; |
536 | PS driver = gpuSpriteSpanDrivers[driver_idx]; |
537 | gpuDrawS(packet, driver); |
538 | } break; |
539 | |
540 | case 0x78: |
541 | case 0x79: |
542 | case 0x7A: |
543 | case 0x7B: { // Monochrome rectangle (16x16) |
544 | gpu_senquack.PacketBuffer.U4[2] = 0x00100010; |
545 | PT driver = gpuTileSpanDrivers[(Blending_Mode | gpu_senquack.Masking | Blending | (gpu_senquack.PixelMSB>>3)) >> 1]; |
546 | gpuDrawT(packet, driver); |
547 | } break; |
548 | |
549 | case 0x7C: |
550 | case 0x7D: |
551 | #ifdef __arm__ |
552 | if ((gpu_senquack.GPU_GP1 & 0x180) == 0 && (gpu_senquack.Masking | gpu_senquack.PixelMSB) == 0) |
553 | { |
554 | gpuSetCLUT (gpu_senquack.PacketBuffer.U4[2] >> 16); |
555 | gpuDrawS16(packet); |
556 | break; |
557 | } |
558 | // fallthrough |
559 | #endif |
560 | case 0x7E: |
561 | case 0x7F: { // Textured rectangle (16x16) |
562 | gpu_senquack.PacketBuffer.U4[3] = 0x00100010; |
563 | gpuSetCLUT (gpu_senquack.PacketBuffer.U4[2] >> 16); |
564 | u32 driver_idx = Blending_Mode | gpu_senquack.TEXT_MODE | gpu_senquack.Masking | Blending | (gpu_senquack.PixelMSB>>1); |
565 | //senquack - Only color 808080h-878787h allows skipping lighting calculation: |
566 | //if ((gpu_senquack.PacketBuffer.U1[0]>0x5F) && (gpu_senquack.PacketBuffer.U1[1]>0x5F) && (gpu_senquack.PacketBuffer.U1[2]>0x5F)) |
567 | // Strip lower 3 bits of each color and determine if lighting should be used: |
568 | if ((gpu_senquack.PacketBuffer.U4[0] & 0xF8F8F8) != 0x808080) |
569 | driver_idx |= Lighting; |
570 | PS driver = gpuSpriteSpanDrivers[driver_idx]; |
571 | gpuDrawS(packet, driver); |
572 | } break; |
573 | |
574 | case 0x80: // vid -> vid |
575 | gpuMoveImage(packet); |
576 | break; |
577 | |
578 | #ifdef TEST |
579 | case 0xA0: // sys -> vid |
580 | { |
581 | u32 load_width = list[2] & 0xffff; |
582 | u32 load_height = list[2] >> 16; |
583 | u32 load_size = load_width * load_height; |
584 | |
585 | len += load_size / 2; |
586 | } break; |
587 | |
588 | case 0xC0: |
589 | break; |
590 | #else |
591 | case 0xA0: // sys ->vid |
592 | case 0xC0: // vid -> sys |
593 | // Handled by gpulib |
594 | goto breakloop; |
595 | #endif |
596 | case 0xE1 ... 0xE6: { // Draw settings |
597 | gpuGP0Cmd_0xEx(gpu_senquack, gpu_senquack.PacketBuffer.U4[0]); |
598 | } break; |
599 | } |
600 | } |
601 | |
602 | breakloop: |
603 | gpu.ex_regs[1] &= ~0x1ff; |
604 | gpu.ex_regs[1] |= gpu_senquack.GPU_GP1 & 0x1ff; |
605 | |
606 | *last_cmd = cmd; |
607 | return list - list_start; |
608 | } |
609 | |
610 | void renderer_sync_ecmds(uint32_t *ecmds) |
611 | { |
612 | int dummy; |
613 | do_cmd_list(&ecmds[1], 6, &dummy); |
614 | } |
615 | |
616 | void renderer_update_caches(int x, int y, int w, int h) |
617 | { |
618 | } |
619 | |
620 | void renderer_flush_queues(void) |
621 | { |
622 | } |
623 | |
624 | void renderer_set_interlace(int enable, int is_odd) |
625 | { |
626 | } |
627 | |
628 | #include "../../frontend/plugin_lib.h" |
629 | // Handle any gpulib settings applicable to gpu_senquack: |
630 | void renderer_set_config(const struct rearmed_cbs *cbs) |
631 | { |
632 | gpu_senquack.vram = (u16*)gpu.vram; |
633 | gpu_senquack.config.ilace_force = cbs->gpu_senquack.ilace_force; |
634 | gpu_senquack.config.pixel_skip = cbs->gpu_senquack.pixel_skip; |
635 | gpu_senquack.config.lighting = cbs->gpu_senquack.lighting; |
636 | gpu_senquack.config.fast_lighting = cbs->gpu_senquack.fast_lighting; |
637 | gpu_senquack.config.blending = cbs->gpu_senquack.blending; |
638 | gpu_senquack.config.dithering = cbs->gpu_senquack.dithering; |
639 | gpu_senquack.config.scale_hires = cbs->gpu_senquack.scale_hires; |
640 | } |
641 | |
642 | // vim:shiftwidth=2:expandtab |