gpu: improve timings of clipped sprites
[pcsx_rearmed.git] / plugins / gpu_neon / psx_gpu / psx_gpu_parse.c
CommitLineData
75e28f62
E
1/*
2 * Copyright (C) 2011 Gilead Kutnick "Exophase" <exophase@gmail.com>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of
7 * the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 */
14
15#include <stdio.h>
16
17#include "common.h"
90ac6fed 18#include "../../gpulib/gpu_timing.h"
75e28f62 19
652c6b8b 20#ifndef command_lengths
75e28f62
E
21const u8 command_lengths[256] =
22{
23 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00
24 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 10
25 3, 3, 3, 3, 6, 6, 6, 6, 4, 4, 4, 4, 8, 8, 8, 8, // 20
26 5, 5, 5, 5, 8, 8, 8, 8, 7, 7, 7, 7, 11, 11, 11, 11, // 30
27 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, // 40
28 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, // 50
652c6b8b 29 2, 2, 2, 2, 3, 3, 3, 3, 1, 1, 1, 1, 0, 0, 0, 0, // 60
75e28f62
E
30 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, // 70
31 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 80
32 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 90
33 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // a0
34 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // b0
35 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // c0
36 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // d0
37 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // e0
38 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // f0
39};
652c6b8b 40#endif
75e28f62
E
41
42void update_texture_ptr(psx_gpu_struct *psx_gpu)
43{
3867c6ef 44 u8 *texture_base;
75e28f62
E
45 u8 *texture_ptr;
46
47 switch((psx_gpu->render_state_base >> 8) & 0x3)
48 {
75e28f62 49 case TEXTURE_MODE_4BPP:
3867c6ef
E
50 texture_base = psx_gpu->texture_4bpp_cache[psx_gpu->current_texture_page];
51
52 texture_ptr = texture_base;
75e28f62
E
53 texture_ptr += psx_gpu->texture_window_x & 0xF;
54 texture_ptr += (psx_gpu->texture_window_y & 0xF) << 4;
55 texture_ptr += (psx_gpu->texture_window_x >> 4) << 8;
56 texture_ptr += (psx_gpu->texture_window_y >> 4) << 12;
75e28f62
E
57 break;
58
59 case TEXTURE_MODE_8BPP:
75e28f62
E
60 if(psx_gpu->current_texture_page & 0x1)
61 {
3867c6ef 62 texture_base =
75e28f62
E
63 psx_gpu->texture_8bpp_odd_cache[psx_gpu->current_texture_page >> 1];
64 }
65 else
66 {
3867c6ef 67 texture_base =
75e28f62
E
68 psx_gpu->texture_8bpp_even_cache[psx_gpu->current_texture_page >> 1];
69 }
70
3867c6ef
E
71 texture_ptr = texture_base;
72 texture_ptr += psx_gpu->texture_window_x & 0xF;
75e28f62
E
73 texture_ptr += (psx_gpu->texture_window_y & 0xF) << 4;
74 texture_ptr += (psx_gpu->texture_window_x >> 4) << 8;
75 texture_ptr += (psx_gpu->texture_window_y >> 4) << 12;
75e28f62
E
76 break;
77
b7f5c059 78 default:
75e28f62 79 case TEXTURE_MODE_16BPP:
3867c6ef
E
80 texture_base = (u8 *)(psx_gpu->vram_ptr);
81 texture_base += (psx_gpu->current_texture_page & 0xF) * 128;
82 texture_base += ((psx_gpu->current_texture_page >> 4) * 256) * 2048;
83
84 texture_ptr = texture_base;
75e28f62
E
85 texture_ptr += psx_gpu->texture_window_x * 2;
86 texture_ptr += (psx_gpu->texture_window_y) * 2048;
87 break;
88 }
89
3867c6ef 90 psx_gpu->texture_page_base = texture_base;
75e28f62
E
91 psx_gpu->texture_page_ptr = texture_ptr;
92}
93
94void set_texture(psx_gpu_struct *psx_gpu, u32 texture_settings)
95{
f3492649 96 texture_settings &= 0x1FF;
75e28f62
E
97 if(psx_gpu->texture_settings != texture_settings)
98 {
99 u32 new_texture_page = texture_settings & 0x1F;
100 u32 texture_mode = (texture_settings >> 7) & 0x3;
101 u32 render_state_base = psx_gpu->render_state_base;
102
b7ed0632 103 flush_render_block_buffer(psx_gpu);
75e28f62
E
104
105 render_state_base &= ~(0xF << 6);
106 render_state_base |= ((texture_settings >> 5) & 0xF) << 6;
107
108 psx_gpu->render_state_base = render_state_base;
109
110 psx_gpu->current_texture_mask = 0x1 << new_texture_page;
111
112 if(texture_mode == TEXTURE_MODE_8BPP)
113 {
114 // In 8bpp mode 256x256 takes up two pages. If it's on the right edge it
115 // wraps back around to the left edge.
116 u32 adjacent_texture_page = ((texture_settings + 1) & 0xF) | (texture_settings & 0x10);
117 psx_gpu->current_texture_mask |= 0x1 << adjacent_texture_page;
118
119 if((psx_gpu->last_8bpp_texture_page ^ new_texture_page) & 0x1)
120 {
121 u32 dirty_textures_8bpp_alternate_mask =
122 psx_gpu->dirty_textures_8bpp_alternate_mask;
123 psx_gpu->dirty_textures_8bpp_alternate_mask =
124 psx_gpu->dirty_textures_8bpp_mask;
125 psx_gpu->dirty_textures_8bpp_mask = dirty_textures_8bpp_alternate_mask;
126 }
127
128 psx_gpu->last_8bpp_texture_page = new_texture_page;
129 }
130
131 psx_gpu->current_texture_page = new_texture_page;
132 psx_gpu->texture_settings = texture_settings;
133
134 update_texture_ptr(psx_gpu);
135 }
136}
137
138void set_clut(psx_gpu_struct *psx_gpu, u32 clut_settings)
139{
140 if(psx_gpu->clut_settings != clut_settings)
141 {
142 flush_render_block_buffer(psx_gpu);
143 psx_gpu->clut_settings = clut_settings;
144 psx_gpu->clut_ptr = psx_gpu->vram_ptr + ((clut_settings & 0x7FFF) * 16);
145 }
146}
147
148void set_triangle_color(psx_gpu_struct *psx_gpu, u32 triangle_color)
149{
150 if(psx_gpu->triangle_color != triangle_color)
151 {
152 flush_render_block_buffer(psx_gpu);
153 psx_gpu->triangle_color = triangle_color;
154 }
155}
156
c1817bd9 157static void do_fill(psx_gpu_struct *psx_gpu, u32 x, u32 y,
158 u32 width, u32 height, u32 color)
159{
160 x &= ~0xF;
161 width = ((width + 0xF) & ~0xF);
162
163 flush_render_block_buffer(psx_gpu);
164
165 if(unlikely((x + width) > 1024))
166 {
167 u32 width_a = 1024 - x;
168 u32 width_b = width - width_a;
169
170 if(unlikely((y + height) > 512))
171 {
172 u32 height_a = 512 - y;
173 u32 height_b = height - height_a;
174
175 render_block_fill(psx_gpu, color, x, y, width_a, height_a);
176 render_block_fill(psx_gpu, color, 0, y, width_b, height_a);
177 render_block_fill(psx_gpu, color, x, 0, width_a, height_b);
178 render_block_fill(psx_gpu, color, 0, 0, width_b, height_b);
179 }
180 else
181 {
182 render_block_fill(psx_gpu, color, x, y, width_a, height);
183 render_block_fill(psx_gpu, color, 0, y, width_b, height);
184 }
185 }
186 else
187 {
188 if(unlikely((y + height) > 512))
189 {
190 u32 height_a = 512 - y;
191 u32 height_b = height - height_a;
192
193 render_block_fill(psx_gpu, color, x, y, width, height_a);
194 render_block_fill(psx_gpu, color, x, 0, width, height_b);
195 }
196 else
197 {
198 render_block_fill(psx_gpu, color, x, y, width, height);
199 }
200 }
201}
202
75e28f62
E
203#define sign_extend_12bit(value) \
204 (((s32)((value) << 20)) >> 20) \
205
4be044ba
E
206#define sign_extend_11bit(value) \
207 (((s32)((value) << 21)) >> 21) \
208
209#define sign_extend_10bit(value) \
210 (((s32)((value) << 22)) >> 22) \
211
212
75e28f62
E
213#define get_vertex_data_xy(vertex_number, offset16) \
214 vertexes[vertex_number].x = \
215 sign_extend_12bit(list_s16[offset16]) + psx_gpu->offset_x; \
216 vertexes[vertex_number].y = \
217 sign_extend_12bit(list_s16[(offset16) + 1]) + psx_gpu->offset_y; \
218
219#define get_vertex_data_uv(vertex_number, offset16) \
220 vertexes[vertex_number].u = list_s16[offset16] & 0xFF; \
221 vertexes[vertex_number].v = (list_s16[offset16] >> 8) & 0xFF \
222
223#define get_vertex_data_rgb(vertex_number, offset32) \
224 vertexes[vertex_number].r = list[offset32] & 0xFF; \
225 vertexes[vertex_number].g = (list[offset32] >> 8) & 0xFF; \
226 vertexes[vertex_number].b = (list[offset32] >> 16) & 0xFF \
227
228#define get_vertex_data_xy_uv(vertex_number, offset16) \
229 get_vertex_data_xy(vertex_number, offset16); \
230 get_vertex_data_uv(vertex_number, (offset16) + 2) \
231
232#define get_vertex_data_xy_rgb(vertex_number, offset16) \
233 get_vertex_data_rgb(vertex_number, (offset16) / 2); \
234 get_vertex_data_xy(vertex_number, (offset16) + 2); \
235
236#define get_vertex_data_xy_uv_rgb(vertex_number, offset16) \
237 get_vertex_data_rgb(vertex_number, (offset16) / 2); \
238 get_vertex_data_xy(vertex_number, (offset16) + 2); \
239 get_vertex_data_uv(vertex_number, (offset16) + 4); \
240
241#define set_vertex_color_constant(vertex_number, color) \
242 vertexes[vertex_number].r = color & 0xFF; \
243 vertexes[vertex_number].g = (color >> 8) & 0xFF; \
244 vertexes[vertex_number].b = (color >> 16) & 0xFF \
245
246#define get_vertex_data_xy_rgb_constant(vertex_number, offset16, color) \
247 get_vertex_data_xy(vertex_number, offset16); \
248 set_vertex_color_constant(vertex_number, color) \
249
b243416b 250#ifndef SET_Ex
251#define SET_Ex(r, v)
252#endif
253
90ac6fed 254u32 gpu_parse(psx_gpu_struct *psx_gpu, u32 *list, u32 size,
255 s32 *cpu_cycles_out, u32 *last_command)
75e28f62 256{
0b4038f8 257 vertex_struct vertexes[4] __attribute__((aligned(16))) = {};
90ac6fed 258 u32 current_command = 0, command_length, cpu_cycles = 0;
b243416b 259
260 u32 *list_start = list;
75e28f62
E
261 u32 *list_end = list + (size / 4);
262
263 for(; list < list_end; list += 1 + command_length)
264 {
90ac6fed 265 s16 *list_s16 = (void *)list;
266 current_command = *list >> 24;
267 command_length = command_lengths[current_command];
268 if (list + 1 + command_length > list_end) {
269 current_command = (u32)-1;
270 break;
271 }
272
273 switch(current_command)
274 {
275 case 0x00:
276 break;
277
278 case 0x02:
87c45ad1
E
279 {
280 u32 x = list_s16[2] & 0x3FF;
281 u32 y = list_s16[3] & 0x1FF;
282 u32 width = list_s16[4] & 0x3FF;
283 u32 height = list_s16[5] & 0x1FF;
284 u32 color = list[0] & 0xFFFFFF;
285
c1817bd9 286 do_fill(psx_gpu, x, y, width, height, color);
90ac6fed 287 cpu_cycles += gput_fill(width, height);
288 break;
87c45ad1 289 }
90ac6fed 290
291 case 0x20 ... 0x23:
75e28f62
E
292 {
293 set_triangle_color(psx_gpu, list[0] & 0xFFFFFF);
294
295 get_vertex_data_xy(0, 2);
296 get_vertex_data_xy(1, 4);
297 get_vertex_data_xy(2, 6);
f9248bbf 298
75e28f62 299 render_triangle(psx_gpu, vertexes, current_command);
90ac6fed 300 cpu_cycles += gput_poly_base();
301 break;
75e28f62
E
302 }
303
90ac6fed 304 case 0x24 ... 0x27:
75e28f62
E
305 {
306 set_clut(psx_gpu, list_s16[5]);
307 set_texture(psx_gpu, list_s16[9]);
308 set_triangle_color(psx_gpu, list[0] & 0xFFFFFF);
309
310 get_vertex_data_xy_uv(0, 2);
311 get_vertex_data_xy_uv(1, 6);
312 get_vertex_data_xy_uv(2, 10);
313
314 render_triangle(psx_gpu, vertexes, current_command);
90ac6fed 315 cpu_cycles += gput_poly_base_t();
316 break;
75e28f62
E
317 }
318
90ac6fed 319 case 0x28 ... 0x2B:
75e28f62
E
320 {
321 set_triangle_color(psx_gpu, list[0] & 0xFFFFFF);
322
323 get_vertex_data_xy(0, 2);
324 get_vertex_data_xy(1, 4);
325 get_vertex_data_xy(2, 6);
326 get_vertex_data_xy(3, 8);
327
328 render_triangle(psx_gpu, vertexes, current_command);
329 render_triangle(psx_gpu, &(vertexes[1]), current_command);
90ac6fed 330 cpu_cycles += gput_quad_base();
331 break;
75e28f62
E
332 }
333
90ac6fed 334 case 0x2C ... 0x2F:
75e28f62
E
335 {
336 set_clut(psx_gpu, list_s16[5]);
337 set_texture(psx_gpu, list_s16[9]);
338 set_triangle_color(psx_gpu, list[0] & 0xFFFFFF);
339
340 get_vertex_data_xy_uv(0, 2);
341 get_vertex_data_xy_uv(1, 6);
342 get_vertex_data_xy_uv(2, 10);
343 get_vertex_data_xy_uv(3, 14);
344
345 render_triangle(psx_gpu, vertexes, current_command);
346 render_triangle(psx_gpu, &(vertexes[1]), current_command);
90ac6fed 347 cpu_cycles += gput_quad_base_t();
348 break;
75e28f62
E
349 }
350
90ac6fed 351 case 0x30 ... 0x33:
75e28f62
E
352 {
353 get_vertex_data_xy_rgb(0, 0);
354 get_vertex_data_xy_rgb(1, 4);
355 get_vertex_data_xy_rgb(2, 8);
356
357 render_triangle(psx_gpu, vertexes, current_command);
90ac6fed 358 cpu_cycles += gput_poly_base_g();
359 break;
75e28f62
E
360 }
361
90ac6fed 362 case 0x34 ... 0x37:
75e28f62
E
363 {
364 set_clut(psx_gpu, list_s16[5]);
365 set_texture(psx_gpu, list_s16[11]);
366
367 get_vertex_data_xy_uv_rgb(0, 0);
368 get_vertex_data_xy_uv_rgb(1, 6);
369 get_vertex_data_xy_uv_rgb(2, 12);
370
371 render_triangle(psx_gpu, vertexes, current_command);
90ac6fed 372 cpu_cycles += gput_poly_base_gt();
373 break;
75e28f62
E
374 }
375
90ac6fed 376 case 0x38 ... 0x3B:
75e28f62
E
377 {
378 get_vertex_data_xy_rgb(0, 0);
379 get_vertex_data_xy_rgb(1, 4);
380 get_vertex_data_xy_rgb(2, 8);
381 get_vertex_data_xy_rgb(3, 12);
382
383 render_triangle(psx_gpu, vertexes, current_command);
384 render_triangle(psx_gpu, &(vertexes[1]), current_command);
90ac6fed 385 cpu_cycles += gput_quad_base_g();
386 break;
75e28f62
E
387 }
388
90ac6fed 389 case 0x3C ... 0x3F:
75e28f62
E
390 {
391 set_clut(psx_gpu, list_s16[5]);
392 set_texture(psx_gpu, list_s16[11]);
393
394 get_vertex_data_xy_uv_rgb(0, 0);
395 get_vertex_data_xy_uv_rgb(1, 6);
396 get_vertex_data_xy_uv_rgb(2, 12);
397 get_vertex_data_xy_uv_rgb(3, 18);
398
399 render_triangle(psx_gpu, vertexes, current_command);
400 render_triangle(psx_gpu, &(vertexes[1]), current_command);
90ac6fed 401 cpu_cycles += gput_quad_base_gt();
402 break;
75e28f62
E
403 }
404
90ac6fed 405 case 0x40 ... 0x47:
75e28f62
E
406 {
407 vertexes[0].x = list_s16[2] + psx_gpu->offset_x;
408 vertexes[0].y = list_s16[3] + psx_gpu->offset_y;
409 vertexes[1].x = list_s16[4] + psx_gpu->offset_x;
410 vertexes[1].y = list_s16[5] + psx_gpu->offset_y;
411
3b3dee71 412 render_line(psx_gpu, vertexes, current_command, list[0], 0);
90ac6fed 413 cpu_cycles += gput_line(0);
414 break;
75e28f62
E
415 }
416
90ac6fed 417 case 0x48 ... 0x4F:
75e28f62
E
418 {
419 u32 num_vertexes = 1;
420 u32 *list_position = &(list[2]);
421 u32 xy = list[1];
422
423 vertexes[1].x = (xy & 0xFFFF) + psx_gpu->offset_x;
424 vertexes[1].y = (xy >> 16) + psx_gpu->offset_y;
425
c8eaa363 426 xy = *list_position;
75e28f62
E
427 while(1)
428 {
75e28f62
E
429 vertexes[0] = vertexes[1];
430
431 vertexes[1].x = (xy & 0xFFFF) + psx_gpu->offset_x;
432 vertexes[1].y = (xy >> 16) + psx_gpu->offset_y;
433
3b3dee71 434 render_line(psx_gpu, vertexes, current_command, list[0], 0);
90ac6fed 435 cpu_cycles += gput_line(0);
c8eaa363 436
75e28f62
E
437 list_position++;
438 num_vertexes++;
439
c8eaa363 440 if(list_position >= list_end)
804789d7 441 {
442 current_command = (u32)-1;
443 goto breakloop;
444 }
f9248bbf 445
c8eaa363 446 xy = *list_position;
447 if((xy & 0xF000F000) == 0x50005000)
448 break;
75e28f62
E
449 }
450
c8eaa363 451 command_length += (num_vertexes - 2);
452 break;
75e28f62
E
453 }
454
90ac6fed 455 case 0x50 ... 0x57:
75e28f62
E
456 {
457 vertexes[0].r = list[0] & 0xFF;
458 vertexes[0].g = (list[0] >> 8) & 0xFF;
459 vertexes[0].b = (list[0] >> 16) & 0xFF;
460 vertexes[0].x = list_s16[2] + psx_gpu->offset_x;
461 vertexes[0].y = list_s16[3] + psx_gpu->offset_y;
462
463 vertexes[1].r = list[2] & 0xFF;
464 vertexes[1].g = (list[2] >> 8) & 0xFF;
465 vertexes[1].b = (list[2] >> 16) & 0xFF;
466 vertexes[1].x = list_s16[6] + psx_gpu->offset_x;
467 vertexes[1].y = list_s16[7] + psx_gpu->offset_y;
468
3b3dee71 469 render_line(psx_gpu, vertexes, current_command, 0, 0);
90ac6fed 470 cpu_cycles += gput_line(0);
471 break;
75e28f62
E
472 }
473
474 case 0x58 ... 0x5F:
475 {
476 u32 num_vertexes = 1;
477 u32 *list_position = &(list[2]);
478 u32 color = list[0];
479 u32 xy = list[1];
480
481 vertexes[1].r = color & 0xFF;
482 vertexes[1].g = (color >> 8) & 0xFF;
483 vertexes[1].b = (color >> 16) & 0xFF;
484 vertexes[1].x = (xy & 0xFFFF) + psx_gpu->offset_x;
485 vertexes[1].y = (xy >> 16) + psx_gpu->offset_y;
486
c8eaa363 487 color = list_position[0];
75e28f62
E
488 while(1)
489 {
75e28f62
E
490 xy = list_position[1];
491
492 vertexes[0] = vertexes[1];
493
494 vertexes[1].r = color & 0xFF;
495 vertexes[1].g = (color >> 8) & 0xFF;
496 vertexes[1].b = (color >> 16) & 0xFF;
497 vertexes[1].x = (xy & 0xFFFF) + psx_gpu->offset_x;
498 vertexes[1].y = (xy >> 16) + psx_gpu->offset_y;
499
3b3dee71 500 render_line(psx_gpu, vertexes, current_command, 0, 0);
90ac6fed 501 cpu_cycles += gput_line(0);
c8eaa363 502
75e28f62
E
503 list_position += 2;
504 num_vertexes++;
505
c8eaa363 506 if(list_position >= list_end)
804789d7 507 {
508 current_command = (u32)-1;
509 goto breakloop;
510 }
f9248bbf 511
c8eaa363 512 color = list_position[0];
513 if((color & 0xF000F000) == 0x50005000)
514 break;
75e28f62
E
515 }
516
c8eaa363 517 command_length += ((num_vertexes - 2) * 2);
518 break;
75e28f62
E
519 }
520
90ac6fed 521 case 0x60 ... 0x63:
75e28f62 522 {
4be044ba
E
523 u32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
524 u32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
1cec4719 525 s32 width = list_s16[4] & 0x3FF;
526 s32 height = list_s16[5] & 0x1FF;
75e28f62 527
1cec4719 528 render_sprite(psx_gpu, x, y, 0, 0, &width, &height,
529 current_command, list[0]);
90ac6fed 530 cpu_cycles += gput_sprite(width, height);
531 break;
75e28f62
E
532 }
533
90ac6fed 534 case 0x64 ... 0x67:
75e28f62 535 {
4be044ba
E
536 u32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
537 u32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
75e28f62 538 u32 uv = list_s16[4];
1cec4719 539 s32 width = list_s16[6] & 0x3FF;
540 s32 height = list_s16[7] & 0x1FF;
75e28f62 541
75e28f62
E
542 set_clut(psx_gpu, list_s16[5]);
543
1cec4719 544 render_sprite(psx_gpu, x, y, uv & 0xFF, (uv >> 8) & 0xFF,
545 &width, &height, current_command, list[0]);
90ac6fed 546 cpu_cycles += gput_sprite(width, height);
547 break;
75e28f62
E
548 }
549
90ac6fed 550 case 0x68 ... 0x6B:
75e28f62 551 {
4be044ba
E
552 s32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
553 s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
1cec4719 554 s32 width = 1, height = 1;
75e28f62 555
1cec4719 556 render_sprite(psx_gpu, x, y, 0, 0, &width, &height,
557 current_command, list[0]);
90ac6fed 558 cpu_cycles += gput_sprite(1, 1);
559 break;
75e28f62
E
560 }
561
90ac6fed 562 case 0x70 ... 0x73:
75e28f62 563 {
4be044ba
E
564 s32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
565 s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
1cec4719 566 s32 width = 8, height = 8;
75e28f62 567
1cec4719 568 render_sprite(psx_gpu, x, y, 0, 0, &width, &height,
569 current_command, list[0]);
570 cpu_cycles += gput_sprite(width, height);
90ac6fed 571 break;
75e28f62
E
572 }
573
90ac6fed 574 case 0x74 ... 0x77:
75e28f62 575 {
4be044ba
E
576 s32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
577 s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
75e28f62 578 u32 uv = list_s16[4];
1cec4719 579 s32 width = 8, height = 8;
75e28f62 580
75e28f62
E
581 set_clut(psx_gpu, list_s16[5]);
582
1cec4719 583 render_sprite(psx_gpu, x, y, uv & 0xFF, (uv >> 8) & 0xFF,
584 &width, &height, current_command, list[0]);
585 cpu_cycles += gput_sprite(width, height);
90ac6fed 586 break;
75e28f62
E
587 }
588
90ac6fed 589 case 0x78 ... 0x7B:
75e28f62 590 {
4be044ba
E
591 s32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
592 s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
1cec4719 593 s32 width = 16, height = 16;
75e28f62 594
1cec4719 595 render_sprite(psx_gpu, x, y, 0, 0, &width, &height,
596 current_command, list[0]);
597 cpu_cycles += gput_sprite(width, height);
90ac6fed 598 break;
75e28f62
E
599 }
600
90ac6fed 601 case 0x7C ... 0x7F:
75e28f62 602 {
4be044ba
E
603 s32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
604 s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
75e28f62 605 u32 uv = list_s16[4];
1cec4719 606 s32 width = 16, height = 16;
75e28f62 607
75e28f62
E
608 set_clut(psx_gpu, list_s16[5]);
609
1cec4719 610 render_sprite(psx_gpu, x, y, uv & 0xFF, (uv >> 8) & 0xFF,
611 &width, &height, current_command, list[0]);
612 cpu_cycles += gput_sprite(width, height);
90ac6fed 613 break;
75e28f62
E
614 }
615
72583812 616#ifdef PCSX
1cec4719 617 case 0x1F: // irq?
72583812 618 case 0x80 ... 0x9F: // vid -> vid
619 case 0xA0 ... 0xBF: // sys -> vid
620 case 0xC0 ... 0xDF: // vid -> sys
621 goto breakloop;
622#else
623 case 0x80 ... 0x9F: // vid -> vid
06bc35c8 624 {
625 u32 sx = list_s16[2] & 0x3FF;
626 u32 sy = list_s16[3] & 0x1FF;
627 u32 dx = list_s16[4] & 0x3FF;
628 u32 dy = list_s16[5] & 0x1FF;
629 u32 w = ((list_s16[6] - 1) & 0x3FF) + 1;
630 u32 h = ((list_s16[7] - 1) & 0x1FF) + 1;
631
632 if (sx == dx && sy == dy && psx_gpu->mask_msb == 0)
633 break;
634
635 render_block_move(psx_gpu, sx, sy, dx, dy, w, h);
636 break;
637 }
638
72583812 639 case 0xA0 ... 0xBF: // sys -> vid
75e28f62 640 {
1f88961f
E
641 u32 load_x = list_s16[2] & 0x3FF;
642 u32 load_y = list_s16[3] & 0x1FF;
643 u32 load_width = list_s16[4] & 0x3FF;
644 u32 load_height = list_s16[5] & 0x1FF;
75e28f62
E
645 u32 load_size = load_width * load_height;
646
647 command_length += load_size / 2;
cec398c0
E
648
649 if(load_size & 1)
650 command_length++;
651
75e28f62
E
652 render_block_copy(psx_gpu, (u16 *)&(list_s16[6]), load_x, load_y,
653 load_width, load_height, load_width);
90ac6fed 654 break;
75e28f62 655 }
b243416b 656
72583812 657 case 0xC0 ... 0xDF: // vid -> sys
658 break;
b243416b 659#endif
660
90ac6fed 661 case 0xE1:
f3492649 662 set_texture(psx_gpu, list[0]);
87c45ad1 663
75e28f62
E
664 if(list[0] & (1 << 9))
665 psx_gpu->render_state_base |= RENDER_STATE_DITHER;
666 else
667 psx_gpu->render_state_base &= ~RENDER_STATE_DITHER;
668
669 psx_gpu->display_area_draw_enable = (list[0] >> 10) & 0x1;
90ac6fed 670 SET_Ex(1, list[0]);
671 break;
75e28f62 672
90ac6fed 673 case 0xE2:
75e28f62
E
674 {
675 // TODO: Clean
676 u32 texture_window_settings = list[0];
677 u32 tmp, x, y, w, h;
678
679 if(texture_window_settings != psx_gpu->texture_window_settings)
680 {
681 tmp = (texture_window_settings & 0x1F) | 0x20;
682 for(w = 8; (tmp & 1) == 0; tmp >>= 1, w <<= 1);
683
684 tmp = ((texture_window_settings >> 5) & 0x1f) | 0x20;
685 for (h = 8; (tmp & 1) == 0; tmp >>= 1, h <<= 1);
686
687 tmp = 32 - (w >> 3);
688 x = ((texture_window_settings >> 10) & tmp) << 3;
689
690 tmp = 32 - (h >> 3);
691 y = ((texture_window_settings >> 15) & tmp) << 3;
692
693 flush_render_block_buffer(psx_gpu);
694
de35a464 695 psx_gpu->texture_window_settings = texture_window_settings;
75e28f62
E
696 psx_gpu->texture_window_x = x;
697 psx_gpu->texture_window_y = y;
698 psx_gpu->texture_mask_width = w - 1;
699 psx_gpu->texture_mask_height = h - 1;
700
701 update_texture_ptr(psx_gpu);
702 }
b243416b 703 SET_Ex(2, list[0]);
75e28f62 704 break;
77e34391 705 }
706
707 case 0xE3:
708 {
709 s16 viewport_start_x = list[0] & 0x3FF;
710 s16 viewport_start_y = (list[0] >> 10) & 0x1FF;
711
712 if(viewport_start_x == psx_gpu->viewport_start_x &&
713 viewport_start_y == psx_gpu->viewport_start_y)
714 {
715 break;
716 }
75e28f62 717
77e34391 718 psx_gpu->viewport_start_x = viewport_start_x;
719 psx_gpu->viewport_start_y = viewport_start_y;
75e28f62
E
720
721#ifdef TEXTURE_CACHE_4BPP
722 psx_gpu->viewport_mask =
723 texture_region_mask(psx_gpu->viewport_start_x,
724 psx_gpu->viewport_start_y, psx_gpu->viewport_end_x,
725 psx_gpu->viewport_end_y);
726#endif
77e34391 727 SET_Ex(3, list[0]);
728 break;
729 }
730
731 case 0xE4:
732 {
733 s16 viewport_end_x = list[0] & 0x3FF;
734 s16 viewport_end_y = (list[0] >> 10) & 0x1FF;
735
736 if(viewport_end_x == psx_gpu->viewport_end_x &&
737 viewport_end_y == psx_gpu->viewport_end_y)
738 {
739 break;
740 }
741
742 psx_gpu->viewport_end_x = viewport_end_x;
743 psx_gpu->viewport_end_y = viewport_end_y;
75e28f62
E
744
745#ifdef TEXTURE_CACHE_4BPP
746 psx_gpu->viewport_mask =
747 texture_region_mask(psx_gpu->viewport_start_x,
748 psx_gpu->viewport_start_y, psx_gpu->viewport_end_x,
749 psx_gpu->viewport_end_y);
750#endif
77e34391 751 SET_Ex(4, list[0]);
752 break;
753 }
75e28f62 754
77e34391 755 case 0xE5:
75e28f62
E
756 {
757 s32 offset_x = list[0] << 21;
758 s32 offset_y = list[0] << 10;
759 psx_gpu->offset_x = offset_x >> 21;
760 psx_gpu->offset_y = offset_y >> 21;
761
90ac6fed 762 SET_Ex(5, list[0]);
763 break;
764 }
75e28f62 765
90ac6fed 766 case 0xE6:
75e28f62
E
767 {
768 u32 mask_settings = list[0];
769 u16 mask_msb = mask_settings << 15;
770
771 if(list[0] & 0x2)
772 psx_gpu->render_state_base |= RENDER_STATE_MASK_EVALUATE;
773 else
774 psx_gpu->render_state_base &= ~RENDER_STATE_MASK_EVALUATE;
775
776 if(mask_msb != psx_gpu->mask_msb)
777 {
778 flush_render_block_buffer(psx_gpu);
779 psx_gpu->mask_msb = mask_msb;
780 }
781
90ac6fed 782 SET_Ex(6, list[0]);
783 break;
75e28f62
E
784 }
785
90ac6fed 786 default:
787 break;
788 }
75e28f62 789 }
b243416b 790
b243416b 791breakloop:
90ac6fed 792 *cpu_cycles_out += cpu_cycles;
793 *last_command = current_command;
b243416b 794 return list - list_start;
75e28f62
E
795}
796
fc6cef7d 797#ifdef PCSX
798
2da2fc76 799// this thing has become such a PITA, should just handle the 2048 width really
800static void update_enhancement_buf_scanouts(psx_gpu_struct *psx_gpu,
801 int x, int y, int w, int h)
0b4038f8 802{
2da2fc76 803 int max_bufs = ARRAY_SIZE(psx_gpu->enhancement_scanouts);
804 struct psx_gpu_scanout *s;
805 int i, sel, right, bottom;
806 u32 tol_x = 48, tol_y = 16;
807 u32 intersection;
808
809 //w = (w + 15) & ~15;
810 psx_gpu->saved_hres = w;
811 assert(!(max_bufs & (max_bufs - 1)));
812 for (i = 0; i < max_bufs; i++) {
813 s = &psx_gpu->enhancement_scanouts[i];
814 if (s->x == x && s->y == y && w - s->w <= tol_x && h - s->h <= tol_y)
815 return;
0b4038f8 816 }
7956599f 817
2da2fc76 818 // evict any scanout that intersects
819 right = x + w;
820 bottom = y + h;
821 for (i = 0, sel = -1; i < max_bufs; i++) {
822 s = &psx_gpu->enhancement_scanouts[i];
823 if (s->x >= right) continue;
824 if (s->x + s->w <= x) continue;
825 if (s->y >= bottom) continue;
826 if (s->y + s->h <= y) continue;
827 // ... but allow upto 16 pixels intersection that some games do
828 if ((intersection = s->x + s->w - x) - 1u <= tol_x) {
829 s->w -= intersection;
830 continue;
7956599f 831 }
2da2fc76 832 if ((intersection = s->y + s->h - y) - 1u <= tol_y) {
833 s->h -= intersection;
834 continue;
835 }
836 //printf("%4d%4d%4dx%d evicted\n", s->x, s->y, s->w, s->h);
837 s->w = 0;
838 sel = i;
839 break;
7956599f 840 }
2da2fc76 841 if (sel >= 0) {
842 // 2nd intersection check
843 for (i = 0; i < max_bufs; i++) {
844 s = &psx_gpu->enhancement_scanouts[i];
845 if (!s->w)
846 continue;
847 if ((intersection = right - s->x) - 1u <= tol_x) {
848 w -= intersection;
849 break;
850 }
851 if ((intersection = bottom - s->y) - 1u <= tol_y) {
852 h -= intersection;
853 break;
0b4038f8 854 }
0b4038f8 855 }
856 }
2da2fc76 857 else
858 sel = psx_gpu->enhancement_scanout_eselect++;
859 psx_gpu->enhancement_scanout_eselect &= max_bufs - 1;
860 s = &psx_gpu->enhancement_scanouts[sel];
861 s->x = x;
862 s->y = y;
863 s->w = w;
864 s->h = h;
865
866 sync_enhancement_buffers(x, y, w, h);
867#if 0
868 printf("scanouts:\n");
869 for (i = 0; i < ARRAY_SIZE(psx_gpu->enhancement_scanouts); i++) {
870 s = &psx_gpu->enhancement_scanouts[i];
871 if (s->w)
872 printf("%4d%4d%4dx%d\n", s->x, s->y, s->w, s->h);
873 }
0b4038f8 874#endif
e929dec5 875}
876
2da2fc76 877static int select_enhancement_buf_index(psx_gpu_struct *psx_gpu, s32 x, s32 y)
77e34391 878{
2da2fc76 879 int i;
880 for (i = 0; i < ARRAY_SIZE(psx_gpu->enhancement_scanouts); i++) {
881 const struct psx_gpu_scanout *s = &psx_gpu->enhancement_scanouts[i];
882 if (s->x <= x && x < s->x + s->w &&
883 s->y <= y && y < s->y + s->h)
884 return i;
885 }
886 return -1;
887}
77e34391 888
2da2fc76 889#define select_enhancement_buf_by_index(psx_gpu_, i_) \
890 ((psx_gpu_)->enhancement_buf_ptr + ((i_) << 20))
77e34391 891
2da2fc76 892static void *select_enhancement_buf_ptr(psx_gpu_struct *psx_gpu, s32 x, s32 y)
893{
894 int i = select_enhancement_buf_index(psx_gpu, x, y);
895 return i >= 0 ? select_enhancement_buf_by_index(psx_gpu, i) : NULL;
77e34391 896}
897
2da2fc76 898static void select_enhancement_buf(psx_gpu_struct *psx_gpu)
899{
1587b08e 900 s32 x = psx_gpu->saved_viewport_start_x + 16;
901 s32 y = psx_gpu->saved_viewport_start_y + 16;
2da2fc76 902 psx_gpu->enhancement_current_buf_ptr = select_enhancement_buf_ptr(psx_gpu, x, y);
903}
06bc35c8 904
c1817bd9 905#define enhancement_disable() { \
906 psx_gpu->vram_out_ptr = psx_gpu->vram_ptr; \
907 psx_gpu->viewport_start_x = psx_gpu->saved_viewport_start_x; \
908 psx_gpu->viewport_start_y = psx_gpu->saved_viewport_start_y; \
909 psx_gpu->viewport_end_x = psx_gpu->saved_viewport_end_x; \
910 psx_gpu->viewport_end_y = psx_gpu->saved_viewport_end_y; \
c6063f89 911 psx_gpu->uvrgb_phase = 0x8000; \
c1817bd9 912}
913
2da2fc76 914static int enhancement_enable(psx_gpu_struct *psx_gpu)
915{
916 if (!psx_gpu->enhancement_current_buf_ptr)
917 return 0;
918 psx_gpu->vram_out_ptr = psx_gpu->enhancement_current_buf_ptr;
919 psx_gpu->viewport_start_x = psx_gpu->saved_viewport_start_x * 2;
920 psx_gpu->viewport_start_y = psx_gpu->saved_viewport_start_y * 2;
921 psx_gpu->viewport_end_x = psx_gpu->saved_viewport_end_x * 2 + 1;
922 psx_gpu->viewport_end_y = psx_gpu->saved_viewport_end_y * 2 + 1;
923 if (psx_gpu->viewport_end_x - psx_gpu->viewport_start_x + 1 > 1024)
924 psx_gpu->viewport_end_x = psx_gpu->viewport_start_x + 1023;
925 psx_gpu->uvrgb_phase = 0x7fff;
926 return 1;
c1817bd9 927}
928
929#define shift_vertices3(v) { \
0b4038f8 930 v[0]->x <<= 1; \
931 v[0]->y <<= 1; \
932 v[1]->x <<= 1; \
933 v[1]->y <<= 1; \
934 v[2]->x <<= 1; \
935 v[2]->y <<= 1; \
c1817bd9 936}
937
938#define unshift_vertices3(v) { \
0b4038f8 939 v[0]->x >>= 1; \
940 v[0]->y >>= 1; \
941 v[1]->x >>= 1; \
942 v[1]->y >>= 1; \
943 v[2]->x >>= 1; \
944 v[2]->y >>= 1; \
c1817bd9 945}
946
947#define shift_triangle_area() \
948 psx_gpu->triangle_area *= 4
949
06bc35c8 950#ifndef NEON_BUILD
7a8d521f 951void scale2x_tiles8(void *dst, const void *src, int w8, int h)
952{
953 uint16_t* d = (uint16_t*)dst;
954 const uint16_t* s = (const uint16_t*)src;
955
956 while ( h-- )
957 {
958 uint16_t* d_save = d;
959 const uint16_t* s_save = s;
960 int w = w8;
961
962 while ( w-- )
963 {
964 d[ 0 ] = *s;
965 d[ 1 ] = *s;
966 d[ 1024 ] = *s;
967 d[ 1025 ] = *s;
968 d += 2; s++;
969
970 d[ 0 ] = *s;
971 d[ 1 ] = *s;
972 d[ 1024 ] = *s;
973 d[ 1025 ] = *s;
974 d += 2; s++;
975
976 d[ 0 ] = *s;
977 d[ 1 ] = *s;
978 d[ 1024 ] = *s;
979 d[ 1025 ] = *s;
980 d += 2; s++;
981
982 d[ 0 ] = *s;
983 d[ 1 ] = *s;
984 d[ 1024 ] = *s;
985 d[ 1025 ] = *s;
986 d += 2; s++;
987
988 d[ 0 ] = *s;
989 d[ 1 ] = *s;
990 d[ 1024 ] = *s;
991 d[ 1025 ] = *s;
992 d += 2; s++;
993
994 d[ 0 ] = *s;
995 d[ 1 ] = *s;
996 d[ 1024 ] = *s;
997 d[ 1025 ] = *s;
998 d += 2; s++;
999
1000 d[ 0 ] = *s;
1001 d[ 1 ] = *s;
1002 d[ 1024 ] = *s;
1003 d[ 1025 ] = *s;
1004 d += 2; s++;
1005
1006 d[ 0 ] = *s;
1007 d[ 1 ] = *s;
1008 d[ 1024 ] = *s;
1009 d[ 1025 ] = *s;
1010 d += 2; s++;
1011 }
1012
1013 d = d_save + 2048;
1014 s = s_save + 1024; /* or 512? */
1015 }
1016}
06bc35c8 1017#endif
1018
c1817bd9 1019static int disable_main_render;
1020
2da2fc76 1021// simple check for a case where no clipping is used
1022// - now handled by adjusting the viewport
1023static int check_enhanced_range(psx_gpu_struct *psx_gpu, int x, int y)
0b4038f8 1024{
0b4038f8 1025 return 1;
1026}
1027
39db3a96 1028static int is_in_array(int val, int array[], int len)
1029{
1030 int i;
1031 for (i = 0; i < len; i++)
1032 if (array[i] == val)
1033 return 1;
1034 return 0;
1035}
1036
1037static int make_members_unique(int array[], int len)
1038{
1039 int i, j;
1040 for (i = j = 1; i < len; i++)
1041 if (!is_in_array(array[i], array, j))
1042 array[j++] = array[i];
1043
1044 if (array[0] > array[1]) {
1045 i = array[0]; array[0] = array[1]; array[1] = i;
1046 }
1047 return j;
1048}
1049
1050static void patch_u(vertex_struct *vertex_ptrs, int count, int old, int new)
1051{
1052 int i;
1053 for (i = 0; i < count; i++)
1054 if (vertex_ptrs[i].u == old)
1055 vertex_ptrs[i].u = new;
1056}
1057
1058static void patch_v(vertex_struct *vertex_ptrs, int count, int old, int new)
1059{
1060 int i;
1061 for (i = 0; i < count; i++)
1062 if (vertex_ptrs[i].v == old)
1063 vertex_ptrs[i].v = new;
1064}
1065
1066static void uv_hack(vertex_struct *vertex_ptrs, int vertex_count)
1067{
1068 int i, u[4], v[4];
1069
1070 for (i = 0; i < vertex_count; i++) {
1071 u[i] = vertex_ptrs[i].u;
1072 v[i] = vertex_ptrs[i].v;
1073 }
1074 if (make_members_unique(u, vertex_count) == 2 && u[1] - u[0] >= 8) {
1075 if ((u[0] & 7) == 7) {
1076 patch_u(vertex_ptrs, vertex_count, u[0], u[0] + 1);
1077 //printf("u hack: %3u-%3u -> %3u-%3u\n", u[0], u[1], u[0]+1, u[1]);
1078 }
1079 else if ((u[1] & 7) == 0 || u[1] - u[0] > 128) {
1080 patch_u(vertex_ptrs, vertex_count, u[1], u[1] - 1);
1081 //printf("u hack: %3u-%3u -> %3u-%3u\n", u[0], u[1], u[0], u[1]-1);
1082 }
1083 }
1084 if (make_members_unique(v, vertex_count) == 2 && ((v[0] - v[1]) & 7) == 0) {
1085 if ((v[0] & 7) == 7) {
1086 patch_v(vertex_ptrs, vertex_count, v[0], v[0] + 1);
1087 //printf("v hack: %3u-%3u -> %3u-%3u\n", v[0], v[1], v[0]+1, v[1]);
1088 }
1089 else if ((v[1] & 7) == 0) {
1090 patch_v(vertex_ptrs, vertex_count, v[1], v[1] - 1);
1091 //printf("v hack: %3u-%3u -> %3u-%3u\n", v[0], v[1], v[0], v[1]-1);
1092 }
1093 }
1094}
1095
c1817bd9 1096static void do_triangle_enhanced(psx_gpu_struct *psx_gpu,
1097 vertex_struct *vertexes, u32 current_command)
1098{
1099 vertex_struct *vertex_ptrs[3];
1100
1101 if (!prepare_triangle(psx_gpu, vertexes, vertex_ptrs))
1102 return;
1103
1104 if (!disable_main_render)
1105 render_triangle_p(psx_gpu, vertex_ptrs, current_command);
1106
0b4038f8 1107 if (!check_enhanced_range(psx_gpu, vertex_ptrs[0]->x, vertex_ptrs[2]->x))
1108 return;
1109
2da2fc76 1110 if (!enhancement_enable(psx_gpu))
1111 return;
1112
c1817bd9 1113 shift_vertices3(vertex_ptrs);
1114 shift_triangle_area();
1115 render_triangle_p(psx_gpu, vertex_ptrs, current_command);
0b4038f8 1116 unshift_vertices3(vertex_ptrs);
c1817bd9 1117}
1118
1119static void do_quad_enhanced(psx_gpu_struct *psx_gpu, vertex_struct *vertexes,
1120 u32 current_command)
1121{
0b4038f8 1122 do_triangle_enhanced(psx_gpu, vertexes, current_command);
c1817bd9 1123 enhancement_disable();
0b4038f8 1124 do_triangle_enhanced(psx_gpu, &vertexes[1], current_command);
c1817bd9 1125}
1126
fc6cef7d 1127#if 0
1128
24c742fc 1129#define fill_vertex(i, x_, y_, u_, v_, rgb_) \
1130 vertexes[i].x = x_; \
1131 vertexes[i].y = y_; \
1132 vertexes[i].u = u_; \
1133 vertexes[i].v = v_; \
1134 vertexes[i].r = rgb_; \
1135 vertexes[i].g = (rgb_) >> 8; \
1136 vertexes[i].b = (rgb_) >> 16
1137
fc6cef7d 1138static void do_sprite_enhanced(psx_gpu_struct *psx_gpu, int x, int y,
24c742fc 1139 u32 u, u32 v, u32 w, u32 h, u32 cmd_rgb)
1140{
1141 vertex_struct *vertex_ptrs[3];
1142 u32 flags = (cmd_rgb >> 24);
1143 u32 color = cmd_rgb & 0xffffff;
1144 u32 render_state_base_saved = psx_gpu->render_state_base;
1145 int x1, y1;
1146 u8 u1, v1;
1147
1148 flags &=
1149 (RENDER_FLAGS_MODULATE_TEXELS | RENDER_FLAGS_BLEND |
1150 RENDER_FLAGS_TEXTURE_MAP);
1151
1152 set_triangle_color(psx_gpu, color);
1153 if(color == 0x808080)
1154 flags |= RENDER_FLAGS_MODULATE_TEXELS;
1155
1156 psx_gpu->render_state_base &= ~RENDER_STATE_DITHER;
1157 enhancement_enable();
1158
1159 x1 = x + w;
1160 y1 = y + h;
1161 u1 = u + w;
1162 v1 = v + h;
1163 // FIXME..
1164 if (u1 < u) u1 = 0xff;
1165 if (v1 < v) v1 = 0xff;
1166
1167 // 0-2
1168 // |/
1169 // 1
1170 fill_vertex(0, x, y, u, v, color);
1171 fill_vertex(1, x, y1, u, v1, color);
1172 fill_vertex(2, x1, y, u1, v, color);
1173 if (prepare_triangle(psx_gpu, vertexes, vertex_ptrs)) {
1174 shift_vertices3(vertex_ptrs);
1175 shift_triangle_area();
1176 render_triangle_p(psx_gpu, vertex_ptrs, flags);
1177 }
1178
1179 // 0
1180 // /|
1181 // 1-2
1182 fill_vertex(0, x1, y, u1, v, color);
1183 fill_vertex(1, x, y1, u, v1, color);
1184 fill_vertex(2, x1, y1, u1, v1, color);
1185 if (prepare_triangle(psx_gpu, vertexes, vertex_ptrs)) {
1186 shift_vertices3(vertex_ptrs);
1187 shift_triangle_area();
1188 render_triangle_p(psx_gpu, vertex_ptrs, flags);
1189 }
1190
1191 psx_gpu->render_state_base = render_state_base_saved;
1192}
fc6cef7d 1193#else
1194static void do_sprite_enhanced(psx_gpu_struct *psx_gpu, int x, int y,
1195 u32 u, u32 v, u32 w, u32 h, u32 cmd_rgb)
1196{
1197 u32 flags = (cmd_rgb >> 24);
1198 u32 color = cmd_rgb & 0xffffff;
1199
fc6cef7d 1200 render_sprite_4x(psx_gpu, x, y, u, v, w, h, flags, color);
1201}
1202#endif
24c742fc 1203
7956599f 1204u32 gpu_parse_enhanced(psx_gpu_struct *psx_gpu, u32 *list, u32 size,
90ac6fed 1205 s32 *cpu_cycles_out, u32 *last_command)
c1817bd9 1206{
0b4038f8 1207 vertex_struct vertexes[4] __attribute__((aligned(16))) = {};
90ac6fed 1208 u32 current_command = 0, command_length, cpu_cycles = 0;
c1817bd9 1209
1210 u32 *list_start = list;
1211 u32 *list_end = list + (size / 4);
1212
1213 psx_gpu->saved_viewport_start_x = psx_gpu->viewport_start_x;
1214 psx_gpu->saved_viewport_start_y = psx_gpu->viewport_start_y;
1215 psx_gpu->saved_viewport_end_x = psx_gpu->viewport_end_x;
1216 psx_gpu->saved_viewport_end_y = psx_gpu->viewport_end_y;
e929dec5 1217 select_enhancement_buf(psx_gpu);
c1817bd9 1218
1219 for(; list < list_end; list += 1 + command_length)
1220 {
1221 s16 *list_s16 = (void *)list;
1222 current_command = *list >> 24;
1223 command_length = command_lengths[current_command];
1224 if (list + 1 + command_length > list_end) {
1225 current_command = (u32)-1;
1226 break;
1227 }
1228
1229 enhancement_disable();
1230
1231 switch(current_command)
1232 {
1233 case 0x00:
1234 break;
1235
1236 case 0x02:
1237 {
1238 u32 x = list_s16[2] & 0x3FF;
1239 u32 y = list_s16[3] & 0x1FF;
1240 u32 width = list_s16[4] & 0x3FF;
1241 u32 height = list_s16[5] & 0x1FF;
1242 u32 color = list[0] & 0xFFFFFF;
2da2fc76 1243 s32 i1, i2;
c1817bd9 1244
f1359c57 1245 x &= ~0xF;
1246 width = ((width + 0xF) & ~0xF);
90ac6fed 1247 cpu_cycles += gput_fill(width, height);
0b4038f8 1248 if (width == 0 || height == 0)
1249 break;
f1359c57 1250
c1817bd9 1251 do_fill(psx_gpu, x, y, width, height, color);
1252
2da2fc76 1253 i1 = select_enhancement_buf_index(psx_gpu, x, y);
1254 i2 = select_enhancement_buf_index(psx_gpu, x + width - 1, y + height - 1);
1255 if (i1 < 0 || i1 != i2) {
0b4038f8 1256 sync_enhancement_buffers(x, y, width, height);
1257 break;
1258 }
0b4038f8 1259
2da2fc76 1260 psx_gpu->vram_out_ptr = select_enhancement_buf_by_index(psx_gpu, i1);
c1817bd9 1261 x *= 2;
1262 y *= 2;
1263 width *= 2;
1264 height *= 2;
f1359c57 1265 render_block_fill_enh(psx_gpu, color, x, y, width, height);
c1817bd9 1266 break;
1267 }
1268
1269 case 0x20 ... 0x23:
1270 {
1271 set_triangle_color(psx_gpu, list[0] & 0xFFFFFF);
1272
1273 get_vertex_data_xy(0, 2);
1274 get_vertex_data_xy(1, 4);
1275 get_vertex_data_xy(2, 6);
1276
1277 do_triangle_enhanced(psx_gpu, vertexes, current_command);
90ac6fed 1278 cpu_cycles += gput_poly_base();
c1817bd9 1279 break;
1280 }
1281
1282 case 0x24 ... 0x27:
1283 {
1284 set_clut(psx_gpu, list_s16[5]);
1285 set_texture(psx_gpu, list_s16[9]);
1286 set_triangle_color(psx_gpu, list[0] & 0xFFFFFF);
1287
1288 get_vertex_data_xy_uv(0, 2);
1289 get_vertex_data_xy_uv(1, 6);
1290 get_vertex_data_xy_uv(2, 10);
1291
1292 do_triangle_enhanced(psx_gpu, vertexes, current_command);
90ac6fed 1293 cpu_cycles += gput_poly_base_t();
c1817bd9 1294 break;
1295 }
1296
1297 case 0x28 ... 0x2B:
1298 {
1299 set_triangle_color(psx_gpu, list[0] & 0xFFFFFF);
1300
1301 get_vertex_data_xy(0, 2);
1302 get_vertex_data_xy(1, 4);
1303 get_vertex_data_xy(2, 6);
1304 get_vertex_data_xy(3, 8);
1305
1306 do_quad_enhanced(psx_gpu, vertexes, current_command);
90ac6fed 1307 cpu_cycles += gput_quad_base();
c1817bd9 1308 break;
1309 }
1310
1311 case 0x2C ... 0x2F:
1312 {
1313 set_clut(psx_gpu, list_s16[5]);
1314 set_texture(psx_gpu, list_s16[9]);
1315 set_triangle_color(psx_gpu, list[0] & 0xFFFFFF);
1316
1317 get_vertex_data_xy_uv(0, 2);
1318 get_vertex_data_xy_uv(1, 6);
1319 get_vertex_data_xy_uv(2, 10);
1320 get_vertex_data_xy_uv(3, 14);
1321
39db3a96 1322 uv_hack(vertexes, 4);
c1817bd9 1323 do_quad_enhanced(psx_gpu, vertexes, current_command);
90ac6fed 1324 cpu_cycles += gput_quad_base_t();
c1817bd9 1325 break;
1326 }
1327
1328 case 0x30 ... 0x33:
1329 {
1330 get_vertex_data_xy_rgb(0, 0);
1331 get_vertex_data_xy_rgb(1, 4);
1332 get_vertex_data_xy_rgb(2, 8);
1333
1334 do_triangle_enhanced(psx_gpu, vertexes, current_command);
90ac6fed 1335 cpu_cycles += gput_poly_base_g();
c1817bd9 1336 break;
1337 }
1338
90ac6fed 1339 case 0x34 ... 0x37:
c1817bd9 1340 {
1341 set_clut(psx_gpu, list_s16[5]);
1342 set_texture(psx_gpu, list_s16[11]);
1343
1344 get_vertex_data_xy_uv_rgb(0, 0);
1345 get_vertex_data_xy_uv_rgb(1, 6);
1346 get_vertex_data_xy_uv_rgb(2, 12);
1347
1348 do_triangle_enhanced(psx_gpu, vertexes, current_command);
90ac6fed 1349 cpu_cycles += gput_poly_base_gt();
c1817bd9 1350 break;
1351 }
1352
90ac6fed 1353 case 0x38 ... 0x3B:
c1817bd9 1354 {
1355 get_vertex_data_xy_rgb(0, 0);
1356 get_vertex_data_xy_rgb(1, 4);
1357 get_vertex_data_xy_rgb(2, 8);
1358 get_vertex_data_xy_rgb(3, 12);
1359
1360 do_quad_enhanced(psx_gpu, vertexes, current_command);
90ac6fed 1361 cpu_cycles += gput_quad_base_g();
c1817bd9 1362 break;
1363 }
1364
90ac6fed 1365 case 0x3C ... 0x3F:
c1817bd9 1366 {
1367 set_clut(psx_gpu, list_s16[5]);
1368 set_texture(psx_gpu, list_s16[11]);
1369
1370 get_vertex_data_xy_uv_rgb(0, 0);
1371 get_vertex_data_xy_uv_rgb(1, 6);
1372 get_vertex_data_xy_uv_rgb(2, 12);
1373 get_vertex_data_xy_uv_rgb(3, 18);
1374
39db3a96 1375 uv_hack(vertexes, 4);
c1817bd9 1376 do_quad_enhanced(psx_gpu, vertexes, current_command);
90ac6fed 1377 cpu_cycles += gput_quad_base_gt();
c1817bd9 1378 break;
1379 }
1380
1381 case 0x40 ... 0x47:
1382 {
1383 vertexes[0].x = list_s16[2] + psx_gpu->offset_x;
1384 vertexes[0].y = list_s16[3] + psx_gpu->offset_y;
1385 vertexes[1].x = list_s16[4] + psx_gpu->offset_x;
1386 vertexes[1].y = list_s16[5] + psx_gpu->offset_y;
1387
3b3dee71 1388 render_line(psx_gpu, vertexes, current_command, list[0], 0);
2da2fc76 1389 if (enhancement_enable(psx_gpu))
1390 render_line(psx_gpu, vertexes, current_command, list[0], 1);
90ac6fed 1391 cpu_cycles += gput_line(0);
c1817bd9 1392 break;
1393 }
1394
1395 case 0x48 ... 0x4F:
1396 {
1397 u32 num_vertexes = 1;
1398 u32 *list_position = &(list[2]);
1399 u32 xy = list[1];
1400
1401 vertexes[1].x = (xy & 0xFFFF) + psx_gpu->offset_x;
1402 vertexes[1].y = (xy >> 16) + psx_gpu->offset_y;
1403
1404 xy = *list_position;
1405 while(1)
1406 {
1407 vertexes[0] = vertexes[1];
1408
1409 vertexes[1].x = (xy & 0xFFFF) + psx_gpu->offset_x;
1410 vertexes[1].y = (xy >> 16) + psx_gpu->offset_y;
1411
3b3dee71 1412 enhancement_disable();
1413 render_line(psx_gpu, vertexes, current_command, list[0], 0);
2da2fc76 1414 if (enhancement_enable(psx_gpu))
1415 render_line(psx_gpu, vertexes, current_command, list[0], 1);
90ac6fed 1416 cpu_cycles += gput_line(0);
c1817bd9 1417
1418 list_position++;
1419 num_vertexes++;
1420
1421 if(list_position >= list_end)
804789d7 1422 {
1423 current_command = (u32)-1;
1424 goto breakloop;
1425 }
c1817bd9 1426
1427 xy = *list_position;
1428 if((xy & 0xF000F000) == 0x50005000)
1429 break;
1430 }
1431
1432 command_length += (num_vertexes - 2);
1433 break;
1434 }
1435
1436 case 0x50 ... 0x57:
1437 {
1438 vertexes[0].r = list[0] & 0xFF;
1439 vertexes[0].g = (list[0] >> 8) & 0xFF;
1440 vertexes[0].b = (list[0] >> 16) & 0xFF;
1441 vertexes[0].x = list_s16[2] + psx_gpu->offset_x;
1442 vertexes[0].y = list_s16[3] + psx_gpu->offset_y;
1443
1444 vertexes[1].r = list[2] & 0xFF;
1445 vertexes[1].g = (list[2] >> 8) & 0xFF;
1446 vertexes[1].b = (list[2] >> 16) & 0xFF;
1447 vertexes[1].x = list_s16[6] + psx_gpu->offset_x;
1448 vertexes[1].y = list_s16[7] + psx_gpu->offset_y;
1449
3b3dee71 1450 render_line(psx_gpu, vertexes, current_command, 0, 0);
2da2fc76 1451 if (enhancement_enable(psx_gpu))
1452 render_line(psx_gpu, vertexes, current_command, 0, 1);
90ac6fed 1453 cpu_cycles += gput_line(0);
c1817bd9 1454 break;
1455 }
1456
1457 case 0x58 ... 0x5F:
1458 {
1459 u32 num_vertexes = 1;
1460 u32 *list_position = &(list[2]);
1461 u32 color = list[0];
1462 u32 xy = list[1];
1463
1464 vertexes[1].r = color & 0xFF;
1465 vertexes[1].g = (color >> 8) & 0xFF;
1466 vertexes[1].b = (color >> 16) & 0xFF;
1467 vertexes[1].x = (xy & 0xFFFF) + psx_gpu->offset_x;
1468 vertexes[1].y = (xy >> 16) + psx_gpu->offset_y;
1469
1470 color = list_position[0];
1471 while(1)
1472 {
1473 xy = list_position[1];
1474
1475 vertexes[0] = vertexes[1];
1476
1477 vertexes[1].r = color & 0xFF;
1478 vertexes[1].g = (color >> 8) & 0xFF;
1479 vertexes[1].b = (color >> 16) & 0xFF;
1480 vertexes[1].x = (xy & 0xFFFF) + psx_gpu->offset_x;
1481 vertexes[1].y = (xy >> 16) + psx_gpu->offset_y;
1482
3b3dee71 1483 enhancement_disable();
1484 render_line(psx_gpu, vertexes, current_command, 0, 0);
2da2fc76 1485 if (enhancement_enable(psx_gpu))
1486 render_line(psx_gpu, vertexes, current_command, 0, 1);
90ac6fed 1487 cpu_cycles += gput_line(0);
c1817bd9 1488
1489 list_position += 2;
1490 num_vertexes++;
1491
1492 if(list_position >= list_end)
804789d7 1493 {
1494 current_command = (u32)-1;
1495 goto breakloop;
1496 }
c1817bd9 1497
1498 color = list_position[0];
1499 if((color & 0xF000F000) == 0x50005000)
1500 break;
1501 }
1502
1503 command_length += ((num_vertexes - 2) * 2);
1504 break;
1505 }
1506
1507 case 0x60 ... 0x63:
1508 {
1509 u32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
1510 u32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
1cec4719 1511 s32 width = list_s16[4] & 0x3FF;
1512 s32 height = list_s16[5] & 0x1FF;
c1817bd9 1513
1cec4719 1514 render_sprite(psx_gpu, x, y, 0, 0, &width, &height,
1515 current_command, list[0]);
0b4038f8 1516
1517 if (check_enhanced_range(psx_gpu, x, x + width))
1518 do_sprite_enhanced(psx_gpu, x, y, 0, 0, width, height, list[0]);
90ac6fed 1519 cpu_cycles += gput_sprite(width, height);
c1817bd9 1520 break;
1521 }
1522
1523 case 0x64 ... 0x67:
1524 {
1525 u32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
1526 u32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
24c742fc 1527 u8 u = list_s16[4];
1528 u8 v = list_s16[4] >> 8;
1cec4719 1529 s32 width = list_s16[6] & 0x3FF;
1530 s32 height = list_s16[7] & 0x1FF;
c1817bd9 1531
1532 set_clut(psx_gpu, list_s16[5]);
1533
1cec4719 1534 render_sprite(psx_gpu, x, y, u, v,
1535 &width, &height, current_command, list[0]);
0b4038f8 1536
1537 if (check_enhanced_range(psx_gpu, x, x + width))
1538 do_sprite_enhanced(psx_gpu, x, y, u, v, width, height, list[0]);
90ac6fed 1539 cpu_cycles += gput_sprite(width, height);
c1817bd9 1540 break;
1541 }
1542
90ac6fed 1543 case 0x68 ... 0x6B:
c1817bd9 1544 {
1545 s32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
1546 s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
1cec4719 1547 s32 width = 1, height = 1;
c1817bd9 1548
1cec4719 1549 render_sprite(psx_gpu, x, y, 0, 0, &width, &height,
1550 current_command, list[0]);
0b4038f8 1551
1552 if (check_enhanced_range(psx_gpu, x, x + 1))
1cec4719 1553 do_sprite_enhanced(psx_gpu, x, y, 0, 0, width, height, list[0]);
90ac6fed 1554 cpu_cycles += gput_sprite(1, 1);
c1817bd9 1555 break;
1556 }
1557
90ac6fed 1558 case 0x70 ... 0x73:
c1817bd9 1559 {
1560 s32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
1561 s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
1cec4719 1562 s32 width = 8, height = 8;
c1817bd9 1563
1cec4719 1564 render_sprite(psx_gpu, x, y, 0, 0, &width, &height,
1565 current_command, list[0]);
0b4038f8 1566
1567 if (check_enhanced_range(psx_gpu, x, x + 8))
1cec4719 1568 do_sprite_enhanced(psx_gpu, x, y, 0, 0, width, height, list[0]);
1569 cpu_cycles += gput_sprite(width, height);
c1817bd9 1570 break;
1571 }
1572
90ac6fed 1573 case 0x74 ... 0x77:
c1817bd9 1574 {
1575 s32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
1576 s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
24c742fc 1577 u8 u = list_s16[4];
1578 u8 v = list_s16[4] >> 8;
1cec4719 1579 s32 width = 8, height = 8;
c1817bd9 1580
1581 set_clut(psx_gpu, list_s16[5]);
1582
1cec4719 1583 render_sprite(psx_gpu, x, y, u, v,
1584 &width, &height, current_command, list[0]);
0b4038f8 1585
1586 if (check_enhanced_range(psx_gpu, x, x + 8))
1cec4719 1587 do_sprite_enhanced(psx_gpu, x, y, u, v, width, height, list[0]);
1588 cpu_cycles += gput_sprite(width, height);
c1817bd9 1589 break;
1590 }
1591
90ac6fed 1592 case 0x78 ... 0x7B:
c1817bd9 1593 {
1594 s32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
1595 s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
1cec4719 1596 s32 width = 16, height = 16;
c1817bd9 1597
1cec4719 1598 render_sprite(psx_gpu, x, y, 0, 0, &width, &height,
1599 current_command, list[0]);
0b4038f8 1600
1601 if (check_enhanced_range(psx_gpu, x, x + 16))
1cec4719 1602 do_sprite_enhanced(psx_gpu, x, y, 0, 0, width, height, list[0]);
1603 cpu_cycles += gput_sprite(width, height);
c1817bd9 1604 break;
1605 }
1606
90ac6fed 1607 case 0x7C ... 0x7F:
c1817bd9 1608 {
1609 s32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
1610 s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
24c742fc 1611 u8 u = list_s16[4];
1612 u8 v = list_s16[4] >> 8;
1cec4719 1613 s32 width = 16, height = 16;
c1817bd9 1614
1615 set_clut(psx_gpu, list_s16[5]);
1616
1cec4719 1617 render_sprite(psx_gpu, x, y, u, v,
1618 &width, &height, current_command, list[0]);
0b4038f8 1619
1620 if (check_enhanced_range(psx_gpu, x, x + 16))
1cec4719 1621 do_sprite_enhanced(psx_gpu, x, y, u, v, width, height, list[0]);
1622 cpu_cycles += gput_sprite(width, height);
c1817bd9 1623 break;
1624 }
06bc35c8 1625
72583812 1626 case 0x80 ... 0x9F: // vid -> vid
1627 case 0xA0 ... 0xBF: // sys -> vid
1628 case 0xC0 ... 0xDF: // vid -> sys
c1817bd9 1629 goto breakloop;
c1817bd9 1630
1631 case 0xE1:
f3492649 1632 set_texture(psx_gpu, list[0]);
c1817bd9 1633
1634 if(list[0] & (1 << 9))
1635 psx_gpu->render_state_base |= RENDER_STATE_DITHER;
1636 else
1637 psx_gpu->render_state_base &= ~RENDER_STATE_DITHER;
1638
1639 psx_gpu->display_area_draw_enable = (list[0] >> 10) & 0x1;
1640 SET_Ex(1, list[0]);
1641 break;
1642
1643 case 0xE2:
1644 {
1645 // TODO: Clean
1646 u32 texture_window_settings = list[0];
1647 u32 tmp, x, y, w, h;
1648
1649 if(texture_window_settings != psx_gpu->texture_window_settings)
1650 {
1651 tmp = (texture_window_settings & 0x1F) | 0x20;
1652 for(w = 8; (tmp & 1) == 0; tmp >>= 1, w <<= 1);
1653
1654 tmp = ((texture_window_settings >> 5) & 0x1f) | 0x20;
1655 for (h = 8; (tmp & 1) == 0; tmp >>= 1, h <<= 1);
1656
1657 tmp = 32 - (w >> 3);
1658 x = ((texture_window_settings >> 10) & tmp) << 3;
1659
1660 tmp = 32 - (h >> 3);
1661 y = ((texture_window_settings >> 15) & tmp) << 3;
1662
1663 flush_render_block_buffer(psx_gpu);
1664
1665 psx_gpu->texture_window_settings = texture_window_settings;
1666 psx_gpu->texture_window_x = x;
1667 psx_gpu->texture_window_y = y;
1668 psx_gpu->texture_mask_width = w - 1;
1669 psx_gpu->texture_mask_height = h - 1;
1670
1671 update_texture_ptr(psx_gpu);
1672 }
1673 SET_Ex(2, list[0]);
1674 break;
1675 }
1676
1677 case 0xE3:
7956599f 1678 {
77e34391 1679 s16 viewport_start_x = list[0] & 0x3FF;
1680 s16 viewport_start_y = (list[0] >> 10) & 0x1FF;
7956599f 1681
77e34391 1682 if(viewport_start_x == psx_gpu->viewport_start_x &&
1683 viewport_start_y == psx_gpu->viewport_start_y)
1684 {
1685 break;
1686 }
1687 psx_gpu->viewport_start_x = viewport_start_x;
1688 psx_gpu->viewport_start_y = viewport_start_y;
1689 psx_gpu->saved_viewport_start_x = viewport_start_x;
1690 psx_gpu->saved_viewport_start_y = viewport_start_y;
1691
e929dec5 1692 select_enhancement_buf(psx_gpu);
c1817bd9 1693
1694#ifdef TEXTURE_CACHE_4BPP
1695 psx_gpu->viewport_mask =
1696 texture_region_mask(psx_gpu->viewport_start_x,
1697 psx_gpu->viewport_start_y, psx_gpu->viewport_end_x,
1698 psx_gpu->viewport_end_y);
1699#endif
1700 SET_Ex(3, list[0]);
1701 break;
7956599f 1702 }
1703
c1817bd9 1704 case 0xE4:
77e34391 1705 {
1706 s16 viewport_end_x = list[0] & 0x3FF;
1707 s16 viewport_end_y = (list[0] >> 10) & 0x1FF;
77e34391 1708
1709 if(viewport_end_x == psx_gpu->viewport_end_x &&
1710 viewport_end_y == psx_gpu->viewport_end_y)
1711 {
1712 break;
1713 }
1714
1715 psx_gpu->viewport_end_x = viewport_end_x;
1716 psx_gpu->viewport_end_y = viewport_end_y;
1717 psx_gpu->saved_viewport_end_x = viewport_end_x;
1718 psx_gpu->saved_viewport_end_y = viewport_end_y;
1719
77e34391 1720 select_enhancement_buf(psx_gpu);
1587b08e 1721#if 0
1722 if (!psx_gpu->enhancement_current_buf_ptr)
1723 log_anomaly("vp %3d,%3d %3d,%d - no buf\n",
1724 psx_gpu->viewport_start_x, psx_gpu->viewport_start_y,
1725 viewport_end_x, viewport_end_y);
1726#endif
c1817bd9 1727#ifdef TEXTURE_CACHE_4BPP
1728 psx_gpu->viewport_mask =
1729 texture_region_mask(psx_gpu->viewport_start_x,
1730 psx_gpu->viewport_start_y, psx_gpu->viewport_end_x,
1731 psx_gpu->viewport_end_y);
1732#endif
1733 SET_Ex(4, list[0]);
1734 break;
77e34391 1735 }
c1817bd9 1736
1737 case 0xE5:
1738 {
1739 s32 offset_x = list[0] << 21;
1740 s32 offset_y = list[0] << 10;
1741 psx_gpu->offset_x = offset_x >> 21;
1742 psx_gpu->offset_y = offset_y >> 21;
1743
1744 SET_Ex(5, list[0]);
1745 break;
1746 }
1747
1748 case 0xE6:
1749 {
1750 u32 mask_settings = list[0];
1751 u16 mask_msb = mask_settings << 15;
1752
1753 if(list[0] & 0x2)
1754 psx_gpu->render_state_base |= RENDER_STATE_MASK_EVALUATE;
1755 else
1756 psx_gpu->render_state_base &= ~RENDER_STATE_MASK_EVALUATE;
1757
1758 if(mask_msb != psx_gpu->mask_msb)
1759 {
1760 flush_render_block_buffer(psx_gpu);
1761 psx_gpu->mask_msb = mask_msb;
1762 }
1763
1764 SET_Ex(6, list[0]);
1765 break;
1766 }
1767
1768 default:
1769 break;
1770 }
1771 }
1772
fc6cef7d 1773 enhancement_disable();
1774
c1817bd9 1775breakloop:
90ac6fed 1776 *cpu_cycles_out += cpu_cycles;
1777 *last_command = current_command;
c1817bd9 1778 return list - list_start;
1779}
1780
fc6cef7d 1781#endif /* PCSX */
1782
b0d96051 1783// vim:ts=2:shiftwidth=2:expandtab