gpu: start doing some basic gpu timing
[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);
75e28f62
E
525 u32 width = list_s16[4] & 0x3FF;
526 u32 height = list_s16[5] & 0x1FF;
527
75e28f62 528 render_sprite(psx_gpu, x, y, 0, 0, width, height, current_command, list[0]);
90ac6fed 529 cpu_cycles += gput_sprite(width, height);
530 break;
75e28f62
E
531 }
532
90ac6fed 533 case 0x64 ... 0x67:
75e28f62 534 {
4be044ba
E
535 u32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
536 u32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
75e28f62
E
537 u32 uv = list_s16[4];
538 u32 width = list_s16[6] & 0x3FF;
539 u32 height = list_s16[7] & 0x1FF;
540
75e28f62
E
541 set_clut(psx_gpu, list_s16[5]);
542
543 render_sprite(psx_gpu, x, y, uv & 0xFF, (uv >> 8) & 0xFF, width, height,
544 current_command, list[0]);
90ac6fed 545 cpu_cycles += gput_sprite(width, height);
546 break;
75e28f62
E
547 }
548
90ac6fed 549 case 0x68 ... 0x6B:
75e28f62 550 {
4be044ba
E
551 s32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
552 s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
75e28f62 553
75e28f62 554 render_sprite(psx_gpu, x, y, 0, 0, 1, 1, current_command, list[0]);
90ac6fed 555 cpu_cycles += gput_sprite(1, 1);
556 break;
75e28f62
E
557 }
558
90ac6fed 559 case 0x70 ... 0x73:
75e28f62 560 {
4be044ba
E
561 s32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
562 s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
75e28f62 563
75e28f62 564 render_sprite(psx_gpu, x, y, 0, 0, 8, 8, current_command, list[0]);
90ac6fed 565 cpu_cycles += gput_sprite(8, 8);
566 break;
75e28f62
E
567 }
568
90ac6fed 569 case 0x74 ... 0x77:
75e28f62 570 {
4be044ba
E
571 s32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
572 s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
75e28f62
E
573 u32 uv = list_s16[4];
574
75e28f62
E
575 set_clut(psx_gpu, list_s16[5]);
576
577 render_sprite(psx_gpu, x, y, uv & 0xFF, (uv >> 8) & 0xFF, 8, 8,
578 current_command, list[0]);
90ac6fed 579 cpu_cycles += gput_sprite(8, 8);
580 break;
75e28f62
E
581 }
582
90ac6fed 583 case 0x78 ... 0x7B:
75e28f62 584 {
4be044ba
E
585 s32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
586 s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
75e28f62 587
75e28f62 588 render_sprite(psx_gpu, x, y, 0, 0, 16, 16, current_command, list[0]);
90ac6fed 589 cpu_cycles += gput_sprite(16, 16);
590 break;
75e28f62
E
591 }
592
90ac6fed 593 case 0x7C ... 0x7F:
75e28f62 594 {
4be044ba
E
595 s32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
596 s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
75e28f62
E
597 u32 uv = list_s16[4];
598
75e28f62
E
599 set_clut(psx_gpu, list_s16[5]);
600
601 render_sprite(psx_gpu, x, y, uv & 0xFF, (uv >> 8) & 0xFF, 16, 16,
602 current_command, list[0]);
90ac6fed 603 cpu_cycles += gput_sprite(16, 16);
604 break;
75e28f62
E
605 }
606
72583812 607#ifdef PCSX
608 case 0x80 ... 0x9F: // vid -> vid
609 case 0xA0 ... 0xBF: // sys -> vid
610 case 0xC0 ... 0xDF: // vid -> sys
611 goto breakloop;
612#else
613 case 0x80 ... 0x9F: // vid -> vid
06bc35c8 614 {
615 u32 sx = list_s16[2] & 0x3FF;
616 u32 sy = list_s16[3] & 0x1FF;
617 u32 dx = list_s16[4] & 0x3FF;
618 u32 dy = list_s16[5] & 0x1FF;
619 u32 w = ((list_s16[6] - 1) & 0x3FF) + 1;
620 u32 h = ((list_s16[7] - 1) & 0x1FF) + 1;
621
622 if (sx == dx && sy == dy && psx_gpu->mask_msb == 0)
623 break;
624
625 render_block_move(psx_gpu, sx, sy, dx, dy, w, h);
626 break;
627 }
628
72583812 629 case 0xA0 ... 0xBF: // sys -> vid
75e28f62 630 {
1f88961f
E
631 u32 load_x = list_s16[2] & 0x3FF;
632 u32 load_y = list_s16[3] & 0x1FF;
633 u32 load_width = list_s16[4] & 0x3FF;
634 u32 load_height = list_s16[5] & 0x1FF;
75e28f62
E
635 u32 load_size = load_width * load_height;
636
637 command_length += load_size / 2;
cec398c0
E
638
639 if(load_size & 1)
640 command_length++;
641
75e28f62
E
642 render_block_copy(psx_gpu, (u16 *)&(list_s16[6]), load_x, load_y,
643 load_width, load_height, load_width);
90ac6fed 644 break;
75e28f62 645 }
b243416b 646
72583812 647 case 0xC0 ... 0xDF: // vid -> sys
648 break;
b243416b 649#endif
650
90ac6fed 651 case 0xE1:
f3492649 652 set_texture(psx_gpu, list[0]);
87c45ad1 653
75e28f62
E
654 if(list[0] & (1 << 9))
655 psx_gpu->render_state_base |= RENDER_STATE_DITHER;
656 else
657 psx_gpu->render_state_base &= ~RENDER_STATE_DITHER;
658
659 psx_gpu->display_area_draw_enable = (list[0] >> 10) & 0x1;
90ac6fed 660 SET_Ex(1, list[0]);
661 break;
75e28f62 662
90ac6fed 663 case 0xE2:
75e28f62
E
664 {
665 // TODO: Clean
666 u32 texture_window_settings = list[0];
667 u32 tmp, x, y, w, h;
668
669 if(texture_window_settings != psx_gpu->texture_window_settings)
670 {
671 tmp = (texture_window_settings & 0x1F) | 0x20;
672 for(w = 8; (tmp & 1) == 0; tmp >>= 1, w <<= 1);
673
674 tmp = ((texture_window_settings >> 5) & 0x1f) | 0x20;
675 for (h = 8; (tmp & 1) == 0; tmp >>= 1, h <<= 1);
676
677 tmp = 32 - (w >> 3);
678 x = ((texture_window_settings >> 10) & tmp) << 3;
679
680 tmp = 32 - (h >> 3);
681 y = ((texture_window_settings >> 15) & tmp) << 3;
682
683 flush_render_block_buffer(psx_gpu);
684
de35a464 685 psx_gpu->texture_window_settings = texture_window_settings;
75e28f62
E
686 psx_gpu->texture_window_x = x;
687 psx_gpu->texture_window_y = y;
688 psx_gpu->texture_mask_width = w - 1;
689 psx_gpu->texture_mask_height = h - 1;
690
691 update_texture_ptr(psx_gpu);
692 }
b243416b 693 SET_Ex(2, list[0]);
75e28f62 694 break;
77e34391 695 }
696
697 case 0xE3:
698 {
699 s16 viewport_start_x = list[0] & 0x3FF;
700 s16 viewport_start_y = (list[0] >> 10) & 0x1FF;
701
702 if(viewport_start_x == psx_gpu->viewport_start_x &&
703 viewport_start_y == psx_gpu->viewport_start_y)
704 {
705 break;
706 }
75e28f62 707
77e34391 708 psx_gpu->viewport_start_x = viewport_start_x;
709 psx_gpu->viewport_start_y = viewport_start_y;
75e28f62
E
710
711#ifdef TEXTURE_CACHE_4BPP
712 psx_gpu->viewport_mask =
713 texture_region_mask(psx_gpu->viewport_start_x,
714 psx_gpu->viewport_start_y, psx_gpu->viewport_end_x,
715 psx_gpu->viewport_end_y);
716#endif
77e34391 717 SET_Ex(3, list[0]);
718 break;
719 }
720
721 case 0xE4:
722 {
723 s16 viewport_end_x = list[0] & 0x3FF;
724 s16 viewport_end_y = (list[0] >> 10) & 0x1FF;
725
726 if(viewport_end_x == psx_gpu->viewport_end_x &&
727 viewport_end_y == psx_gpu->viewport_end_y)
728 {
729 break;
730 }
731
732 psx_gpu->viewport_end_x = viewport_end_x;
733 psx_gpu->viewport_end_y = viewport_end_y;
75e28f62
E
734
735#ifdef TEXTURE_CACHE_4BPP
736 psx_gpu->viewport_mask =
737 texture_region_mask(psx_gpu->viewport_start_x,
738 psx_gpu->viewport_start_y, psx_gpu->viewport_end_x,
739 psx_gpu->viewport_end_y);
740#endif
77e34391 741 SET_Ex(4, list[0]);
742 break;
743 }
75e28f62 744
77e34391 745 case 0xE5:
75e28f62
E
746 {
747 s32 offset_x = list[0] << 21;
748 s32 offset_y = list[0] << 10;
749 psx_gpu->offset_x = offset_x >> 21;
750 psx_gpu->offset_y = offset_y >> 21;
751
90ac6fed 752 SET_Ex(5, list[0]);
753 break;
754 }
75e28f62 755
90ac6fed 756 case 0xE6:
75e28f62
E
757 {
758 u32 mask_settings = list[0];
759 u16 mask_msb = mask_settings << 15;
760
761 if(list[0] & 0x2)
762 psx_gpu->render_state_base |= RENDER_STATE_MASK_EVALUATE;
763 else
764 psx_gpu->render_state_base &= ~RENDER_STATE_MASK_EVALUATE;
765
766 if(mask_msb != psx_gpu->mask_msb)
767 {
768 flush_render_block_buffer(psx_gpu);
769 psx_gpu->mask_msb = mask_msb;
770 }
771
90ac6fed 772 SET_Ex(6, list[0]);
773 break;
75e28f62
E
774 }
775
90ac6fed 776 default:
777 break;
778 }
75e28f62 779 }
b243416b 780
b243416b 781breakloop:
90ac6fed 782 *cpu_cycles_out += cpu_cycles;
783 *last_command = current_command;
b243416b 784 return list - list_start;
75e28f62
E
785}
786
fc6cef7d 787#ifdef PCSX
788
2da2fc76 789// this thing has become such a PITA, should just handle the 2048 width really
790static void update_enhancement_buf_scanouts(psx_gpu_struct *psx_gpu,
791 int x, int y, int w, int h)
0b4038f8 792{
2da2fc76 793 int max_bufs = ARRAY_SIZE(psx_gpu->enhancement_scanouts);
794 struct psx_gpu_scanout *s;
795 int i, sel, right, bottom;
796 u32 tol_x = 48, tol_y = 16;
797 u32 intersection;
798
799 //w = (w + 15) & ~15;
800 psx_gpu->saved_hres = w;
801 assert(!(max_bufs & (max_bufs - 1)));
802 for (i = 0; i < max_bufs; i++) {
803 s = &psx_gpu->enhancement_scanouts[i];
804 if (s->x == x && s->y == y && w - s->w <= tol_x && h - s->h <= tol_y)
805 return;
0b4038f8 806 }
7956599f 807
2da2fc76 808 // evict any scanout that intersects
809 right = x + w;
810 bottom = y + h;
811 for (i = 0, sel = -1; i < max_bufs; i++) {
812 s = &psx_gpu->enhancement_scanouts[i];
813 if (s->x >= right) continue;
814 if (s->x + s->w <= x) continue;
815 if (s->y >= bottom) continue;
816 if (s->y + s->h <= y) continue;
817 // ... but allow upto 16 pixels intersection that some games do
818 if ((intersection = s->x + s->w - x) - 1u <= tol_x) {
819 s->w -= intersection;
820 continue;
7956599f 821 }
2da2fc76 822 if ((intersection = s->y + s->h - y) - 1u <= tol_y) {
823 s->h -= intersection;
824 continue;
825 }
826 //printf("%4d%4d%4dx%d evicted\n", s->x, s->y, s->w, s->h);
827 s->w = 0;
828 sel = i;
829 break;
7956599f 830 }
2da2fc76 831 if (sel >= 0) {
832 // 2nd intersection check
833 for (i = 0; i < max_bufs; i++) {
834 s = &psx_gpu->enhancement_scanouts[i];
835 if (!s->w)
836 continue;
837 if ((intersection = right - s->x) - 1u <= tol_x) {
838 w -= intersection;
839 break;
840 }
841 if ((intersection = bottom - s->y) - 1u <= tol_y) {
842 h -= intersection;
843 break;
0b4038f8 844 }
0b4038f8 845 }
846 }
2da2fc76 847 else
848 sel = psx_gpu->enhancement_scanout_eselect++;
849 psx_gpu->enhancement_scanout_eselect &= max_bufs - 1;
850 s = &psx_gpu->enhancement_scanouts[sel];
851 s->x = x;
852 s->y = y;
853 s->w = w;
854 s->h = h;
855
856 sync_enhancement_buffers(x, y, w, h);
857#if 0
858 printf("scanouts:\n");
859 for (i = 0; i < ARRAY_SIZE(psx_gpu->enhancement_scanouts); i++) {
860 s = &psx_gpu->enhancement_scanouts[i];
861 if (s->w)
862 printf("%4d%4d%4dx%d\n", s->x, s->y, s->w, s->h);
863 }
0b4038f8 864#endif
e929dec5 865}
866
2da2fc76 867static int select_enhancement_buf_index(psx_gpu_struct *psx_gpu, s32 x, s32 y)
77e34391 868{
2da2fc76 869 int i;
870 for (i = 0; i < ARRAY_SIZE(psx_gpu->enhancement_scanouts); i++) {
871 const struct psx_gpu_scanout *s = &psx_gpu->enhancement_scanouts[i];
872 if (s->x <= x && x < s->x + s->w &&
873 s->y <= y && y < s->y + s->h)
874 return i;
875 }
876 return -1;
877}
77e34391 878
2da2fc76 879#define select_enhancement_buf_by_index(psx_gpu_, i_) \
880 ((psx_gpu_)->enhancement_buf_ptr + ((i_) << 20))
77e34391 881
2da2fc76 882static void *select_enhancement_buf_ptr(psx_gpu_struct *psx_gpu, s32 x, s32 y)
883{
884 int i = select_enhancement_buf_index(psx_gpu, x, y);
885 return i >= 0 ? select_enhancement_buf_by_index(psx_gpu, i) : NULL;
77e34391 886}
887
2da2fc76 888static void select_enhancement_buf(psx_gpu_struct *psx_gpu)
889{
1587b08e 890 s32 x = psx_gpu->saved_viewport_start_x + 16;
891 s32 y = psx_gpu->saved_viewport_start_y + 16;
2da2fc76 892 psx_gpu->enhancement_current_buf_ptr = select_enhancement_buf_ptr(psx_gpu, x, y);
893}
06bc35c8 894
c1817bd9 895#define enhancement_disable() { \
896 psx_gpu->vram_out_ptr = psx_gpu->vram_ptr; \
897 psx_gpu->viewport_start_x = psx_gpu->saved_viewport_start_x; \
898 psx_gpu->viewport_start_y = psx_gpu->saved_viewport_start_y; \
899 psx_gpu->viewport_end_x = psx_gpu->saved_viewport_end_x; \
900 psx_gpu->viewport_end_y = psx_gpu->saved_viewport_end_y; \
c6063f89 901 psx_gpu->uvrgb_phase = 0x8000; \
c1817bd9 902}
903
2da2fc76 904static int enhancement_enable(psx_gpu_struct *psx_gpu)
905{
906 if (!psx_gpu->enhancement_current_buf_ptr)
907 return 0;
908 psx_gpu->vram_out_ptr = psx_gpu->enhancement_current_buf_ptr;
909 psx_gpu->viewport_start_x = psx_gpu->saved_viewport_start_x * 2;
910 psx_gpu->viewport_start_y = psx_gpu->saved_viewport_start_y * 2;
911 psx_gpu->viewport_end_x = psx_gpu->saved_viewport_end_x * 2 + 1;
912 psx_gpu->viewport_end_y = psx_gpu->saved_viewport_end_y * 2 + 1;
913 if (psx_gpu->viewport_end_x - psx_gpu->viewport_start_x + 1 > 1024)
914 psx_gpu->viewport_end_x = psx_gpu->viewport_start_x + 1023;
915 psx_gpu->uvrgb_phase = 0x7fff;
916 return 1;
c1817bd9 917}
918
919#define shift_vertices3(v) { \
0b4038f8 920 v[0]->x <<= 1; \
921 v[0]->y <<= 1; \
922 v[1]->x <<= 1; \
923 v[1]->y <<= 1; \
924 v[2]->x <<= 1; \
925 v[2]->y <<= 1; \
c1817bd9 926}
927
928#define unshift_vertices3(v) { \
0b4038f8 929 v[0]->x >>= 1; \
930 v[0]->y >>= 1; \
931 v[1]->x >>= 1; \
932 v[1]->y >>= 1; \
933 v[2]->x >>= 1; \
934 v[2]->y >>= 1; \
c1817bd9 935}
936
937#define shift_triangle_area() \
938 psx_gpu->triangle_area *= 4
939
06bc35c8 940#ifndef NEON_BUILD
7a8d521f 941void scale2x_tiles8(void *dst, const void *src, int w8, int h)
942{
943 uint16_t* d = (uint16_t*)dst;
944 const uint16_t* s = (const uint16_t*)src;
945
946 while ( h-- )
947 {
948 uint16_t* d_save = d;
949 const uint16_t* s_save = s;
950 int w = w8;
951
952 while ( w-- )
953 {
954 d[ 0 ] = *s;
955 d[ 1 ] = *s;
956 d[ 1024 ] = *s;
957 d[ 1025 ] = *s;
958 d += 2; s++;
959
960 d[ 0 ] = *s;
961 d[ 1 ] = *s;
962 d[ 1024 ] = *s;
963 d[ 1025 ] = *s;
964 d += 2; s++;
965
966 d[ 0 ] = *s;
967 d[ 1 ] = *s;
968 d[ 1024 ] = *s;
969 d[ 1025 ] = *s;
970 d += 2; s++;
971
972 d[ 0 ] = *s;
973 d[ 1 ] = *s;
974 d[ 1024 ] = *s;
975 d[ 1025 ] = *s;
976 d += 2; s++;
977
978 d[ 0 ] = *s;
979 d[ 1 ] = *s;
980 d[ 1024 ] = *s;
981 d[ 1025 ] = *s;
982 d += 2; s++;
983
984 d[ 0 ] = *s;
985 d[ 1 ] = *s;
986 d[ 1024 ] = *s;
987 d[ 1025 ] = *s;
988 d += 2; s++;
989
990 d[ 0 ] = *s;
991 d[ 1 ] = *s;
992 d[ 1024 ] = *s;
993 d[ 1025 ] = *s;
994 d += 2; s++;
995
996 d[ 0 ] = *s;
997 d[ 1 ] = *s;
998 d[ 1024 ] = *s;
999 d[ 1025 ] = *s;
1000 d += 2; s++;
1001 }
1002
1003 d = d_save + 2048;
1004 s = s_save + 1024; /* or 512? */
1005 }
1006}
06bc35c8 1007#endif
1008
c1817bd9 1009static int disable_main_render;
1010
2da2fc76 1011// simple check for a case where no clipping is used
1012// - now handled by adjusting the viewport
1013static int check_enhanced_range(psx_gpu_struct *psx_gpu, int x, int y)
0b4038f8 1014{
0b4038f8 1015 return 1;
1016}
1017
39db3a96 1018static int is_in_array(int val, int array[], int len)
1019{
1020 int i;
1021 for (i = 0; i < len; i++)
1022 if (array[i] == val)
1023 return 1;
1024 return 0;
1025}
1026
1027static int make_members_unique(int array[], int len)
1028{
1029 int i, j;
1030 for (i = j = 1; i < len; i++)
1031 if (!is_in_array(array[i], array, j))
1032 array[j++] = array[i];
1033
1034 if (array[0] > array[1]) {
1035 i = array[0]; array[0] = array[1]; array[1] = i;
1036 }
1037 return j;
1038}
1039
1040static void patch_u(vertex_struct *vertex_ptrs, int count, int old, int new)
1041{
1042 int i;
1043 for (i = 0; i < count; i++)
1044 if (vertex_ptrs[i].u == old)
1045 vertex_ptrs[i].u = new;
1046}
1047
1048static void patch_v(vertex_struct *vertex_ptrs, int count, int old, int new)
1049{
1050 int i;
1051 for (i = 0; i < count; i++)
1052 if (vertex_ptrs[i].v == old)
1053 vertex_ptrs[i].v = new;
1054}
1055
1056static void uv_hack(vertex_struct *vertex_ptrs, int vertex_count)
1057{
1058 int i, u[4], v[4];
1059
1060 for (i = 0; i < vertex_count; i++) {
1061 u[i] = vertex_ptrs[i].u;
1062 v[i] = vertex_ptrs[i].v;
1063 }
1064 if (make_members_unique(u, vertex_count) == 2 && u[1] - u[0] >= 8) {
1065 if ((u[0] & 7) == 7) {
1066 patch_u(vertex_ptrs, vertex_count, u[0], u[0] + 1);
1067 //printf("u hack: %3u-%3u -> %3u-%3u\n", u[0], u[1], u[0]+1, u[1]);
1068 }
1069 else if ((u[1] & 7) == 0 || u[1] - u[0] > 128) {
1070 patch_u(vertex_ptrs, vertex_count, u[1], u[1] - 1);
1071 //printf("u hack: %3u-%3u -> %3u-%3u\n", u[0], u[1], u[0], u[1]-1);
1072 }
1073 }
1074 if (make_members_unique(v, vertex_count) == 2 && ((v[0] - v[1]) & 7) == 0) {
1075 if ((v[0] & 7) == 7) {
1076 patch_v(vertex_ptrs, vertex_count, v[0], v[0] + 1);
1077 //printf("v hack: %3u-%3u -> %3u-%3u\n", v[0], v[1], v[0]+1, v[1]);
1078 }
1079 else if ((v[1] & 7) == 0) {
1080 patch_v(vertex_ptrs, vertex_count, v[1], v[1] - 1);
1081 //printf("v hack: %3u-%3u -> %3u-%3u\n", v[0], v[1], v[0], v[1]-1);
1082 }
1083 }
1084}
1085
c1817bd9 1086static void do_triangle_enhanced(psx_gpu_struct *psx_gpu,
1087 vertex_struct *vertexes, u32 current_command)
1088{
1089 vertex_struct *vertex_ptrs[3];
1090
1091 if (!prepare_triangle(psx_gpu, vertexes, vertex_ptrs))
1092 return;
1093
1094 if (!disable_main_render)
1095 render_triangle_p(psx_gpu, vertex_ptrs, current_command);
1096
0b4038f8 1097 if (!check_enhanced_range(psx_gpu, vertex_ptrs[0]->x, vertex_ptrs[2]->x))
1098 return;
1099
2da2fc76 1100 if (!enhancement_enable(psx_gpu))
1101 return;
1102
c1817bd9 1103 shift_vertices3(vertex_ptrs);
1104 shift_triangle_area();
1105 render_triangle_p(psx_gpu, vertex_ptrs, current_command);
0b4038f8 1106 unshift_vertices3(vertex_ptrs);
c1817bd9 1107}
1108
1109static void do_quad_enhanced(psx_gpu_struct *psx_gpu, vertex_struct *vertexes,
1110 u32 current_command)
1111{
0b4038f8 1112 do_triangle_enhanced(psx_gpu, vertexes, current_command);
c1817bd9 1113 enhancement_disable();
0b4038f8 1114 do_triangle_enhanced(psx_gpu, &vertexes[1], current_command);
c1817bd9 1115}
1116
fc6cef7d 1117#if 0
1118
24c742fc 1119#define fill_vertex(i, x_, y_, u_, v_, rgb_) \
1120 vertexes[i].x = x_; \
1121 vertexes[i].y = y_; \
1122 vertexes[i].u = u_; \
1123 vertexes[i].v = v_; \
1124 vertexes[i].r = rgb_; \
1125 vertexes[i].g = (rgb_) >> 8; \
1126 vertexes[i].b = (rgb_) >> 16
1127
fc6cef7d 1128static void do_sprite_enhanced(psx_gpu_struct *psx_gpu, int x, int y,
24c742fc 1129 u32 u, u32 v, u32 w, u32 h, u32 cmd_rgb)
1130{
1131 vertex_struct *vertex_ptrs[3];
1132 u32 flags = (cmd_rgb >> 24);
1133 u32 color = cmd_rgb & 0xffffff;
1134 u32 render_state_base_saved = psx_gpu->render_state_base;
1135 int x1, y1;
1136 u8 u1, v1;
1137
1138 flags &=
1139 (RENDER_FLAGS_MODULATE_TEXELS | RENDER_FLAGS_BLEND |
1140 RENDER_FLAGS_TEXTURE_MAP);
1141
1142 set_triangle_color(psx_gpu, color);
1143 if(color == 0x808080)
1144 flags |= RENDER_FLAGS_MODULATE_TEXELS;
1145
1146 psx_gpu->render_state_base &= ~RENDER_STATE_DITHER;
1147 enhancement_enable();
1148
1149 x1 = x + w;
1150 y1 = y + h;
1151 u1 = u + w;
1152 v1 = v + h;
1153 // FIXME..
1154 if (u1 < u) u1 = 0xff;
1155 if (v1 < v) v1 = 0xff;
1156
1157 // 0-2
1158 // |/
1159 // 1
1160 fill_vertex(0, x, y, u, v, color);
1161 fill_vertex(1, x, y1, u, v1, color);
1162 fill_vertex(2, x1, y, u1, v, color);
1163 if (prepare_triangle(psx_gpu, vertexes, vertex_ptrs)) {
1164 shift_vertices3(vertex_ptrs);
1165 shift_triangle_area();
1166 render_triangle_p(psx_gpu, vertex_ptrs, flags);
1167 }
1168
1169 // 0
1170 // /|
1171 // 1-2
1172 fill_vertex(0, x1, y, u1, v, color);
1173 fill_vertex(1, x, y1, u, v1, color);
1174 fill_vertex(2, x1, y1, u1, v1, color);
1175 if (prepare_triangle(psx_gpu, vertexes, vertex_ptrs)) {
1176 shift_vertices3(vertex_ptrs);
1177 shift_triangle_area();
1178 render_triangle_p(psx_gpu, vertex_ptrs, flags);
1179 }
1180
1181 psx_gpu->render_state_base = render_state_base_saved;
1182}
fc6cef7d 1183#else
1184static void do_sprite_enhanced(psx_gpu_struct *psx_gpu, int x, int y,
1185 u32 u, u32 v, u32 w, u32 h, u32 cmd_rgb)
1186{
1187 u32 flags = (cmd_rgb >> 24);
1188 u32 color = cmd_rgb & 0xffffff;
1189
fc6cef7d 1190 render_sprite_4x(psx_gpu, x, y, u, v, w, h, flags, color);
1191}
1192#endif
24c742fc 1193
7956599f 1194u32 gpu_parse_enhanced(psx_gpu_struct *psx_gpu, u32 *list, u32 size,
90ac6fed 1195 s32 *cpu_cycles_out, u32 *last_command)
c1817bd9 1196{
0b4038f8 1197 vertex_struct vertexes[4] __attribute__((aligned(16))) = {};
90ac6fed 1198 u32 current_command = 0, command_length, cpu_cycles = 0;
c1817bd9 1199
1200 u32 *list_start = list;
1201 u32 *list_end = list + (size / 4);
1202
1203 psx_gpu->saved_viewport_start_x = psx_gpu->viewport_start_x;
1204 psx_gpu->saved_viewport_start_y = psx_gpu->viewport_start_y;
1205 psx_gpu->saved_viewport_end_x = psx_gpu->viewport_end_x;
1206 psx_gpu->saved_viewport_end_y = psx_gpu->viewport_end_y;
e929dec5 1207 select_enhancement_buf(psx_gpu);
c1817bd9 1208
1209 for(; list < list_end; list += 1 + command_length)
1210 {
1211 s16 *list_s16 = (void *)list;
1212 current_command = *list >> 24;
1213 command_length = command_lengths[current_command];
1214 if (list + 1 + command_length > list_end) {
1215 current_command = (u32)-1;
1216 break;
1217 }
1218
1219 enhancement_disable();
1220
1221 switch(current_command)
1222 {
1223 case 0x00:
1224 break;
1225
1226 case 0x02:
1227 {
1228 u32 x = list_s16[2] & 0x3FF;
1229 u32 y = list_s16[3] & 0x1FF;
1230 u32 width = list_s16[4] & 0x3FF;
1231 u32 height = list_s16[5] & 0x1FF;
1232 u32 color = list[0] & 0xFFFFFF;
2da2fc76 1233 s32 i1, i2;
c1817bd9 1234
f1359c57 1235 x &= ~0xF;
1236 width = ((width + 0xF) & ~0xF);
90ac6fed 1237 cpu_cycles += gput_fill(width, height);
0b4038f8 1238 if (width == 0 || height == 0)
1239 break;
f1359c57 1240
c1817bd9 1241 do_fill(psx_gpu, x, y, width, height, color);
1242
2da2fc76 1243 i1 = select_enhancement_buf_index(psx_gpu, x, y);
1244 i2 = select_enhancement_buf_index(psx_gpu, x + width - 1, y + height - 1);
1245 if (i1 < 0 || i1 != i2) {
0b4038f8 1246 sync_enhancement_buffers(x, y, width, height);
1247 break;
1248 }
0b4038f8 1249
2da2fc76 1250 psx_gpu->vram_out_ptr = select_enhancement_buf_by_index(psx_gpu, i1);
c1817bd9 1251 x *= 2;
1252 y *= 2;
1253 width *= 2;
1254 height *= 2;
f1359c57 1255 render_block_fill_enh(psx_gpu, color, x, y, width, height);
c1817bd9 1256 break;
1257 }
1258
1259 case 0x20 ... 0x23:
1260 {
1261 set_triangle_color(psx_gpu, list[0] & 0xFFFFFF);
1262
1263 get_vertex_data_xy(0, 2);
1264 get_vertex_data_xy(1, 4);
1265 get_vertex_data_xy(2, 6);
1266
1267 do_triangle_enhanced(psx_gpu, vertexes, current_command);
90ac6fed 1268 cpu_cycles += gput_poly_base();
c1817bd9 1269 break;
1270 }
1271
1272 case 0x24 ... 0x27:
1273 {
1274 set_clut(psx_gpu, list_s16[5]);
1275 set_texture(psx_gpu, list_s16[9]);
1276 set_triangle_color(psx_gpu, list[0] & 0xFFFFFF);
1277
1278 get_vertex_data_xy_uv(0, 2);
1279 get_vertex_data_xy_uv(1, 6);
1280 get_vertex_data_xy_uv(2, 10);
1281
1282 do_triangle_enhanced(psx_gpu, vertexes, current_command);
90ac6fed 1283 cpu_cycles += gput_poly_base_t();
c1817bd9 1284 break;
1285 }
1286
1287 case 0x28 ... 0x2B:
1288 {
1289 set_triangle_color(psx_gpu, list[0] & 0xFFFFFF);
1290
1291 get_vertex_data_xy(0, 2);
1292 get_vertex_data_xy(1, 4);
1293 get_vertex_data_xy(2, 6);
1294 get_vertex_data_xy(3, 8);
1295
1296 do_quad_enhanced(psx_gpu, vertexes, current_command);
90ac6fed 1297 cpu_cycles += gput_quad_base();
c1817bd9 1298 break;
1299 }
1300
1301 case 0x2C ... 0x2F:
1302 {
1303 set_clut(psx_gpu, list_s16[5]);
1304 set_texture(psx_gpu, list_s16[9]);
1305 set_triangle_color(psx_gpu, list[0] & 0xFFFFFF);
1306
1307 get_vertex_data_xy_uv(0, 2);
1308 get_vertex_data_xy_uv(1, 6);
1309 get_vertex_data_xy_uv(2, 10);
1310 get_vertex_data_xy_uv(3, 14);
1311
39db3a96 1312 uv_hack(vertexes, 4);
c1817bd9 1313 do_quad_enhanced(psx_gpu, vertexes, current_command);
90ac6fed 1314 cpu_cycles += gput_quad_base_t();
c1817bd9 1315 break;
1316 }
1317
1318 case 0x30 ... 0x33:
1319 {
1320 get_vertex_data_xy_rgb(0, 0);
1321 get_vertex_data_xy_rgb(1, 4);
1322 get_vertex_data_xy_rgb(2, 8);
1323
1324 do_triangle_enhanced(psx_gpu, vertexes, current_command);
90ac6fed 1325 cpu_cycles += gput_poly_base_g();
c1817bd9 1326 break;
1327 }
1328
90ac6fed 1329 case 0x34 ... 0x37:
c1817bd9 1330 {
1331 set_clut(psx_gpu, list_s16[5]);
1332 set_texture(psx_gpu, list_s16[11]);
1333
1334 get_vertex_data_xy_uv_rgb(0, 0);
1335 get_vertex_data_xy_uv_rgb(1, 6);
1336 get_vertex_data_xy_uv_rgb(2, 12);
1337
1338 do_triangle_enhanced(psx_gpu, vertexes, current_command);
90ac6fed 1339 cpu_cycles += gput_poly_base_gt();
c1817bd9 1340 break;
1341 }
1342
90ac6fed 1343 case 0x38 ... 0x3B:
c1817bd9 1344 {
1345 get_vertex_data_xy_rgb(0, 0);
1346 get_vertex_data_xy_rgb(1, 4);
1347 get_vertex_data_xy_rgb(2, 8);
1348 get_vertex_data_xy_rgb(3, 12);
1349
1350 do_quad_enhanced(psx_gpu, vertexes, current_command);
90ac6fed 1351 cpu_cycles += gput_quad_base_g();
c1817bd9 1352 break;
1353 }
1354
90ac6fed 1355 case 0x3C ... 0x3F:
c1817bd9 1356 {
1357 set_clut(psx_gpu, list_s16[5]);
1358 set_texture(psx_gpu, list_s16[11]);
1359
1360 get_vertex_data_xy_uv_rgb(0, 0);
1361 get_vertex_data_xy_uv_rgb(1, 6);
1362 get_vertex_data_xy_uv_rgb(2, 12);
1363 get_vertex_data_xy_uv_rgb(3, 18);
1364
39db3a96 1365 uv_hack(vertexes, 4);
c1817bd9 1366 do_quad_enhanced(psx_gpu, vertexes, current_command);
90ac6fed 1367 cpu_cycles += gput_quad_base_gt();
c1817bd9 1368 break;
1369 }
1370
1371 case 0x40 ... 0x47:
1372 {
1373 vertexes[0].x = list_s16[2] + psx_gpu->offset_x;
1374 vertexes[0].y = list_s16[3] + psx_gpu->offset_y;
1375 vertexes[1].x = list_s16[4] + psx_gpu->offset_x;
1376 vertexes[1].y = list_s16[5] + psx_gpu->offset_y;
1377
3b3dee71 1378 render_line(psx_gpu, vertexes, current_command, list[0], 0);
2da2fc76 1379 if (enhancement_enable(psx_gpu))
1380 render_line(psx_gpu, vertexes, current_command, list[0], 1);
90ac6fed 1381 cpu_cycles += gput_line(0);
c1817bd9 1382 break;
1383 }
1384
1385 case 0x48 ... 0x4F:
1386 {
1387 u32 num_vertexes = 1;
1388 u32 *list_position = &(list[2]);
1389 u32 xy = list[1];
1390
1391 vertexes[1].x = (xy & 0xFFFF) + psx_gpu->offset_x;
1392 vertexes[1].y = (xy >> 16) + psx_gpu->offset_y;
1393
1394 xy = *list_position;
1395 while(1)
1396 {
1397 vertexes[0] = vertexes[1];
1398
1399 vertexes[1].x = (xy & 0xFFFF) + psx_gpu->offset_x;
1400 vertexes[1].y = (xy >> 16) + psx_gpu->offset_y;
1401
3b3dee71 1402 enhancement_disable();
1403 render_line(psx_gpu, vertexes, current_command, list[0], 0);
2da2fc76 1404 if (enhancement_enable(psx_gpu))
1405 render_line(psx_gpu, vertexes, current_command, list[0], 1);
90ac6fed 1406 cpu_cycles += gput_line(0);
c1817bd9 1407
1408 list_position++;
1409 num_vertexes++;
1410
1411 if(list_position >= list_end)
804789d7 1412 {
1413 current_command = (u32)-1;
1414 goto breakloop;
1415 }
c1817bd9 1416
1417 xy = *list_position;
1418 if((xy & 0xF000F000) == 0x50005000)
1419 break;
1420 }
1421
1422 command_length += (num_vertexes - 2);
1423 break;
1424 }
1425
1426 case 0x50 ... 0x57:
1427 {
1428 vertexes[0].r = list[0] & 0xFF;
1429 vertexes[0].g = (list[0] >> 8) & 0xFF;
1430 vertexes[0].b = (list[0] >> 16) & 0xFF;
1431 vertexes[0].x = list_s16[2] + psx_gpu->offset_x;
1432 vertexes[0].y = list_s16[3] + psx_gpu->offset_y;
1433
1434 vertexes[1].r = list[2] & 0xFF;
1435 vertexes[1].g = (list[2] >> 8) & 0xFF;
1436 vertexes[1].b = (list[2] >> 16) & 0xFF;
1437 vertexes[1].x = list_s16[6] + psx_gpu->offset_x;
1438 vertexes[1].y = list_s16[7] + psx_gpu->offset_y;
1439
3b3dee71 1440 render_line(psx_gpu, vertexes, current_command, 0, 0);
2da2fc76 1441 if (enhancement_enable(psx_gpu))
1442 render_line(psx_gpu, vertexes, current_command, 0, 1);
90ac6fed 1443 cpu_cycles += gput_line(0);
c1817bd9 1444 break;
1445 }
1446
1447 case 0x58 ... 0x5F:
1448 {
1449 u32 num_vertexes = 1;
1450 u32 *list_position = &(list[2]);
1451 u32 color = list[0];
1452 u32 xy = list[1];
1453
1454 vertexes[1].r = color & 0xFF;
1455 vertexes[1].g = (color >> 8) & 0xFF;
1456 vertexes[1].b = (color >> 16) & 0xFF;
1457 vertexes[1].x = (xy & 0xFFFF) + psx_gpu->offset_x;
1458 vertexes[1].y = (xy >> 16) + psx_gpu->offset_y;
1459
1460 color = list_position[0];
1461 while(1)
1462 {
1463 xy = list_position[1];
1464
1465 vertexes[0] = vertexes[1];
1466
1467 vertexes[1].r = color & 0xFF;
1468 vertexes[1].g = (color >> 8) & 0xFF;
1469 vertexes[1].b = (color >> 16) & 0xFF;
1470 vertexes[1].x = (xy & 0xFFFF) + psx_gpu->offset_x;
1471 vertexes[1].y = (xy >> 16) + psx_gpu->offset_y;
1472
3b3dee71 1473 enhancement_disable();
1474 render_line(psx_gpu, vertexes, current_command, 0, 0);
2da2fc76 1475 if (enhancement_enable(psx_gpu))
1476 render_line(psx_gpu, vertexes, current_command, 0, 1);
90ac6fed 1477 cpu_cycles += gput_line(0);
c1817bd9 1478
1479 list_position += 2;
1480 num_vertexes++;
1481
1482 if(list_position >= list_end)
804789d7 1483 {
1484 current_command = (u32)-1;
1485 goto breakloop;
1486 }
c1817bd9 1487
1488 color = list_position[0];
1489 if((color & 0xF000F000) == 0x50005000)
1490 break;
1491 }
1492
1493 command_length += ((num_vertexes - 2) * 2);
1494 break;
1495 }
1496
1497 case 0x60 ... 0x63:
1498 {
1499 u32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
1500 u32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
1501 u32 width = list_s16[4] & 0x3FF;
1502 u32 height = list_s16[5] & 0x1FF;
1503
1504 render_sprite(psx_gpu, x, y, 0, 0, width, height, current_command, list[0]);
0b4038f8 1505
1506 if (check_enhanced_range(psx_gpu, x, x + width))
1507 do_sprite_enhanced(psx_gpu, x, y, 0, 0, width, height, list[0]);
90ac6fed 1508 cpu_cycles += gput_sprite(width, height);
c1817bd9 1509 break;
1510 }
1511
1512 case 0x64 ... 0x67:
1513 {
1514 u32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
1515 u32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
24c742fc 1516 u8 u = list_s16[4];
1517 u8 v = list_s16[4] >> 8;
c1817bd9 1518 u32 width = list_s16[6] & 0x3FF;
1519 u32 height = list_s16[7] & 0x1FF;
1520
1521 set_clut(psx_gpu, list_s16[5]);
1522
24c742fc 1523 render_sprite(psx_gpu, x, y, u, v, width, height,
c1817bd9 1524 current_command, list[0]);
0b4038f8 1525
1526 if (check_enhanced_range(psx_gpu, x, x + width))
1527 do_sprite_enhanced(psx_gpu, x, y, u, v, width, height, list[0]);
90ac6fed 1528 cpu_cycles += gput_sprite(width, height);
c1817bd9 1529 break;
1530 }
1531
90ac6fed 1532 case 0x68 ... 0x6B:
c1817bd9 1533 {
1534 s32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
1535 s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
1536
1537 render_sprite(psx_gpu, x, y, 0, 0, 1, 1, current_command, list[0]);
0b4038f8 1538
1539 if (check_enhanced_range(psx_gpu, x, x + 1))
1540 do_sprite_enhanced(psx_gpu, x, y, 0, 0, 1, 1, list[0]);
90ac6fed 1541 cpu_cycles += gput_sprite(1, 1);
c1817bd9 1542 break;
1543 }
1544
90ac6fed 1545 case 0x70 ... 0x73:
c1817bd9 1546 {
1547 s32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
1548 s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
1549
1550 render_sprite(psx_gpu, x, y, 0, 0, 8, 8, current_command, list[0]);
0b4038f8 1551
1552 if (check_enhanced_range(psx_gpu, x, x + 8))
1553 do_sprite_enhanced(psx_gpu, x, y, 0, 0, 8, 8, list[0]);
90ac6fed 1554 cpu_cycles += gput_sprite(8, 8);
c1817bd9 1555 break;
1556 }
1557
90ac6fed 1558 case 0x74 ... 0x77:
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);
24c742fc 1562 u8 u = list_s16[4];
1563 u8 v = list_s16[4] >> 8;
c1817bd9 1564
1565 set_clut(psx_gpu, list_s16[5]);
1566
24c742fc 1567 render_sprite(psx_gpu, x, y, u, v, 8, 8,
c1817bd9 1568 current_command, list[0]);
0b4038f8 1569
1570 if (check_enhanced_range(psx_gpu, x, x + 8))
1571 do_sprite_enhanced(psx_gpu, x, y, u, v, 8, 8, list[0]);
90ac6fed 1572 cpu_cycles += gput_sprite(8, 8);
c1817bd9 1573 break;
1574 }
1575
90ac6fed 1576 case 0x78 ... 0x7B:
c1817bd9 1577 {
1578 s32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
1579 s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
1580
1581 render_sprite(psx_gpu, x, y, 0, 0, 16, 16, current_command, list[0]);
0b4038f8 1582
1583 if (check_enhanced_range(psx_gpu, x, x + 16))
1584 do_sprite_enhanced(psx_gpu, x, y, 0, 0, 16, 16, list[0]);
90ac6fed 1585 cpu_cycles += gput_sprite(16, 16);
c1817bd9 1586 break;
1587 }
1588
90ac6fed 1589 case 0x7C ... 0x7F:
c1817bd9 1590 {
1591 s32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
1592 s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
24c742fc 1593 u8 u = list_s16[4];
1594 u8 v = list_s16[4] >> 8;
c1817bd9 1595
1596 set_clut(psx_gpu, list_s16[5]);
1597
24c742fc 1598 render_sprite(psx_gpu, x, y, u, v, 16, 16, current_command, list[0]);
0b4038f8 1599
1600 if (check_enhanced_range(psx_gpu, x, x + 16))
1601 do_sprite_enhanced(psx_gpu, x, y, u, v, 16, 16, list[0]);
90ac6fed 1602 cpu_cycles += gput_sprite(16, 16);
c1817bd9 1603 break;
1604 }
06bc35c8 1605
72583812 1606 case 0x80 ... 0x9F: // vid -> vid
1607 case 0xA0 ... 0xBF: // sys -> vid
1608 case 0xC0 ... 0xDF: // vid -> sys
c1817bd9 1609 goto breakloop;
c1817bd9 1610
1611 case 0xE1:
f3492649 1612 set_texture(psx_gpu, list[0]);
c1817bd9 1613
1614 if(list[0] & (1 << 9))
1615 psx_gpu->render_state_base |= RENDER_STATE_DITHER;
1616 else
1617 psx_gpu->render_state_base &= ~RENDER_STATE_DITHER;
1618
1619 psx_gpu->display_area_draw_enable = (list[0] >> 10) & 0x1;
1620 SET_Ex(1, list[0]);
1621 break;
1622
1623 case 0xE2:
1624 {
1625 // TODO: Clean
1626 u32 texture_window_settings = list[0];
1627 u32 tmp, x, y, w, h;
1628
1629 if(texture_window_settings != psx_gpu->texture_window_settings)
1630 {
1631 tmp = (texture_window_settings & 0x1F) | 0x20;
1632 for(w = 8; (tmp & 1) == 0; tmp >>= 1, w <<= 1);
1633
1634 tmp = ((texture_window_settings >> 5) & 0x1f) | 0x20;
1635 for (h = 8; (tmp & 1) == 0; tmp >>= 1, h <<= 1);
1636
1637 tmp = 32 - (w >> 3);
1638 x = ((texture_window_settings >> 10) & tmp) << 3;
1639
1640 tmp = 32 - (h >> 3);
1641 y = ((texture_window_settings >> 15) & tmp) << 3;
1642
1643 flush_render_block_buffer(psx_gpu);
1644
1645 psx_gpu->texture_window_settings = texture_window_settings;
1646 psx_gpu->texture_window_x = x;
1647 psx_gpu->texture_window_y = y;
1648 psx_gpu->texture_mask_width = w - 1;
1649 psx_gpu->texture_mask_height = h - 1;
1650
1651 update_texture_ptr(psx_gpu);
1652 }
1653 SET_Ex(2, list[0]);
1654 break;
1655 }
1656
1657 case 0xE3:
7956599f 1658 {
77e34391 1659 s16 viewport_start_x = list[0] & 0x3FF;
1660 s16 viewport_start_y = (list[0] >> 10) & 0x1FF;
7956599f 1661
77e34391 1662 if(viewport_start_x == psx_gpu->viewport_start_x &&
1663 viewport_start_y == psx_gpu->viewport_start_y)
1664 {
1665 break;
1666 }
1667 psx_gpu->viewport_start_x = viewport_start_x;
1668 psx_gpu->viewport_start_y = viewport_start_y;
1669 psx_gpu->saved_viewport_start_x = viewport_start_x;
1670 psx_gpu->saved_viewport_start_y = viewport_start_y;
1671
e929dec5 1672 select_enhancement_buf(psx_gpu);
c1817bd9 1673
1674#ifdef TEXTURE_CACHE_4BPP
1675 psx_gpu->viewport_mask =
1676 texture_region_mask(psx_gpu->viewport_start_x,
1677 psx_gpu->viewport_start_y, psx_gpu->viewport_end_x,
1678 psx_gpu->viewport_end_y);
1679#endif
1680 SET_Ex(3, list[0]);
1681 break;
7956599f 1682 }
1683
c1817bd9 1684 case 0xE4:
77e34391 1685 {
1686 s16 viewport_end_x = list[0] & 0x3FF;
1687 s16 viewport_end_y = (list[0] >> 10) & 0x1FF;
77e34391 1688
1689 if(viewport_end_x == psx_gpu->viewport_end_x &&
1690 viewport_end_y == psx_gpu->viewport_end_y)
1691 {
1692 break;
1693 }
1694
1695 psx_gpu->viewport_end_x = viewport_end_x;
1696 psx_gpu->viewport_end_y = viewport_end_y;
1697 psx_gpu->saved_viewport_end_x = viewport_end_x;
1698 psx_gpu->saved_viewport_end_y = viewport_end_y;
1699
77e34391 1700 select_enhancement_buf(psx_gpu);
1587b08e 1701#if 0
1702 if (!psx_gpu->enhancement_current_buf_ptr)
1703 log_anomaly("vp %3d,%3d %3d,%d - no buf\n",
1704 psx_gpu->viewport_start_x, psx_gpu->viewport_start_y,
1705 viewport_end_x, viewport_end_y);
1706#endif
c1817bd9 1707#ifdef TEXTURE_CACHE_4BPP
1708 psx_gpu->viewport_mask =
1709 texture_region_mask(psx_gpu->viewport_start_x,
1710 psx_gpu->viewport_start_y, psx_gpu->viewport_end_x,
1711 psx_gpu->viewport_end_y);
1712#endif
1713 SET_Ex(4, list[0]);
1714 break;
77e34391 1715 }
c1817bd9 1716
1717 case 0xE5:
1718 {
1719 s32 offset_x = list[0] << 21;
1720 s32 offset_y = list[0] << 10;
1721 psx_gpu->offset_x = offset_x >> 21;
1722 psx_gpu->offset_y = offset_y >> 21;
1723
1724 SET_Ex(5, list[0]);
1725 break;
1726 }
1727
1728 case 0xE6:
1729 {
1730 u32 mask_settings = list[0];
1731 u16 mask_msb = mask_settings << 15;
1732
1733 if(list[0] & 0x2)
1734 psx_gpu->render_state_base |= RENDER_STATE_MASK_EVALUATE;
1735 else
1736 psx_gpu->render_state_base &= ~RENDER_STATE_MASK_EVALUATE;
1737
1738 if(mask_msb != psx_gpu->mask_msb)
1739 {
1740 flush_render_block_buffer(psx_gpu);
1741 psx_gpu->mask_msb = mask_msb;
1742 }
1743
1744 SET_Ex(6, list[0]);
1745 break;
1746 }
1747
1748 default:
1749 break;
1750 }
1751 }
1752
fc6cef7d 1753 enhancement_disable();
1754
c1817bd9 1755breakloop:
90ac6fed 1756 *cpu_cycles_out += cpu_cycles;
1757 *last_command = current_command;
c1817bd9 1758 return list - list_start;
1759}
1760
fc6cef7d 1761#endif /* PCSX */
1762
b0d96051 1763// vim:ts=2:shiftwidth=2:expandtab