psx_gpu: add enhanced triangle rendering
[pcsx_rearmed.git] / plugins / gpu_neon / psx_gpu / psx_gpu_parse.c
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"
18
19 #ifndef command_lengths
20 const u8 command_lengths[256] =
21 {
22         0,  0,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   // 00
23         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   // 10
24         3,  3,  3,  3,  6,  6,  6,  6,  4,  4,  4,  4,  8,  8,  8,  8,   // 20
25         5,  5,  5,  5,  8,  8,  8,  8,  7,  7,  7,  7,  11, 11, 11, 11,  // 30
26         2,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,  3,  3,  3,  3,  3,   // 40
27         3,  3,  3,  3,  3,  3,  3,  3,  4,  4,  4,  4,  4,  4,  4,  4,   // 50
28         2,  2,  2,  2,  3,  3,  3,  3,  1,  1,  1,  1,  0,  0,  0,  0,   // 60
29         1,  1,  1,  1,  2,  2,  2,  2,  1,  1,  1,  1,  2,  2,  2,  2,   // 70
30         3,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   // 80
31         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   // 90
32         2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   // a0
33         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   // b0
34         2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   // c0
35         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   // d0
36         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   // e0
37         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0    // f0
38 };
39 #endif
40
41 void update_texture_ptr(psx_gpu_struct *psx_gpu)
42 {
43   u8 *texture_base;
44   u8 *texture_ptr;
45
46   switch((psx_gpu->render_state_base >> 8) & 0x3)
47   {
48     default:
49     case TEXTURE_MODE_4BPP:
50       texture_base = psx_gpu->texture_4bpp_cache[psx_gpu->current_texture_page];
51
52       texture_ptr = texture_base;
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;
57       break;
58
59     case TEXTURE_MODE_8BPP:
60       if(psx_gpu->current_texture_page & 0x1)
61       {
62         texture_base =
63          psx_gpu->texture_8bpp_odd_cache[psx_gpu->current_texture_page >> 1];
64       }
65       else
66       {
67         texture_base =
68          psx_gpu->texture_8bpp_even_cache[psx_gpu->current_texture_page >> 1];
69       }
70       
71       texture_ptr = texture_base;
72       texture_ptr += psx_gpu->texture_window_x & 0xF;
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;
76       break;
77
78     case TEXTURE_MODE_16BPP:
79       texture_base = (u8 *)(psx_gpu->vram_ptr);
80       texture_base += (psx_gpu->current_texture_page & 0xF) * 128;
81       texture_base += ((psx_gpu->current_texture_page >> 4) * 256) * 2048;
82
83       texture_ptr = texture_base;
84       texture_ptr += psx_gpu->texture_window_x * 2;
85       texture_ptr += (psx_gpu->texture_window_y) * 2048;
86       break;
87   }
88
89   psx_gpu->texture_page_base = texture_base;
90   psx_gpu->texture_page_ptr = texture_ptr;  
91 }
92
93 void set_texture(psx_gpu_struct *psx_gpu, u32 texture_settings)
94 {
95   if(psx_gpu->texture_settings != texture_settings)
96   {
97     u32 new_texture_page = texture_settings & 0x1F;
98     u32 texture_mode = (texture_settings >> 7) & 0x3;
99     u32 render_state_base = psx_gpu->render_state_base;
100
101     flush_render_block_buffer(psx_gpu);
102
103     render_state_base &= ~(0xF << 6);
104     render_state_base |= ((texture_settings >> 5) & 0xF) << 6;
105
106     psx_gpu->render_state_base = render_state_base;
107
108     psx_gpu->current_texture_mask = 0x1 << new_texture_page;
109
110     if(texture_mode == TEXTURE_MODE_8BPP)
111     {     
112       // In 8bpp mode 256x256 takes up two pages. If it's on the right edge it
113       // wraps back around to the left edge.
114       u32 adjacent_texture_page = ((texture_settings + 1) & 0xF) | (texture_settings & 0x10);
115       psx_gpu->current_texture_mask |= 0x1 << adjacent_texture_page;
116
117       if((psx_gpu->last_8bpp_texture_page ^ new_texture_page) & 0x1)
118       {
119         u32 dirty_textures_8bpp_alternate_mask =
120          psx_gpu->dirty_textures_8bpp_alternate_mask;
121         psx_gpu->dirty_textures_8bpp_alternate_mask =
122          psx_gpu->dirty_textures_8bpp_mask;
123         psx_gpu->dirty_textures_8bpp_mask = dirty_textures_8bpp_alternate_mask;
124       }
125
126       psx_gpu->last_8bpp_texture_page = new_texture_page;
127     }
128
129     psx_gpu->current_texture_page = new_texture_page;
130     psx_gpu->texture_settings = texture_settings;
131
132     update_texture_ptr(psx_gpu);
133   }
134 }
135
136 void set_clut(psx_gpu_struct *psx_gpu, u32 clut_settings)
137 {
138   if(psx_gpu->clut_settings != clut_settings)
139   {
140     flush_render_block_buffer(psx_gpu);
141     psx_gpu->clut_settings = clut_settings;
142     psx_gpu->clut_ptr = psx_gpu->vram_ptr + ((clut_settings & 0x7FFF) * 16);
143   }
144 }
145
146 void set_triangle_color(psx_gpu_struct *psx_gpu, u32 triangle_color)
147 {
148   if(psx_gpu->triangle_color != triangle_color)
149   {
150     flush_render_block_buffer(psx_gpu);
151     psx_gpu->triangle_color = triangle_color;
152   }
153 }
154
155 static void do_fill(psx_gpu_struct *psx_gpu, u32 x, u32 y,
156  u32 width, u32 height, u32 color)
157 {
158   x &= ~0xF;
159   width = ((width + 0xF) & ~0xF);
160
161   flush_render_block_buffer(psx_gpu);
162
163   if(unlikely((x + width) > 1024))
164   {
165     u32 width_a = 1024 - x;
166     u32 width_b = width - width_a;
167
168     if(unlikely((y + height) > 512))
169     {
170       u32 height_a = 512 - y;
171       u32 height_b = height - height_a;
172
173       render_block_fill(psx_gpu, color, x, y, width_a, height_a);
174       render_block_fill(psx_gpu, color, 0, y, width_b, height_a);
175       render_block_fill(psx_gpu, color, x, 0, width_a, height_b);
176       render_block_fill(psx_gpu, color, 0, 0, width_b, height_b);
177     }
178     else
179     {
180       render_block_fill(psx_gpu, color, x, y, width_a, height);
181       render_block_fill(psx_gpu, color, 0, y, width_b, height);
182     }
183   }
184   else
185   {
186     if(unlikely((y + height) > 512))
187     {
188       u32 height_a = 512 - y;
189       u32 height_b = height - height_a;
190
191       render_block_fill(psx_gpu, color, x, y, width, height_a);
192       render_block_fill(psx_gpu, color, x, 0, width, height_b);
193     }
194     else
195     {
196       render_block_fill(psx_gpu, color, x, y, width, height);
197     }
198   }
199 }
200
201 #define sign_extend_12bit(value)                                               \
202   (((s32)((value) << 20)) >> 20)                                               \
203
204 #define sign_extend_11bit(value)                                               \
205   (((s32)((value) << 21)) >> 21)                                               \
206
207 #define sign_extend_10bit(value)                                               \
208   (((s32)((value) << 22)) >> 22)                                               \
209
210
211 #define get_vertex_data_xy(vertex_number, offset16)                            \
212   vertexes[vertex_number].x =                                                  \
213    sign_extend_12bit(list_s16[offset16]) + psx_gpu->offset_x;                  \
214   vertexes[vertex_number].y =                                                  \
215    sign_extend_12bit(list_s16[(offset16) + 1]) + psx_gpu->offset_y;            \
216
217 #define get_vertex_data_uv(vertex_number, offset16)                            \
218   vertexes[vertex_number].u = list_s16[offset16] & 0xFF;                       \
219   vertexes[vertex_number].v = (list_s16[offset16] >> 8) & 0xFF                 \
220
221 #define get_vertex_data_rgb(vertex_number, offset32)                           \
222   vertexes[vertex_number].r = list[offset32] & 0xFF;                           \
223   vertexes[vertex_number].g = (list[offset32] >> 8) & 0xFF;                    \
224   vertexes[vertex_number].b = (list[offset32] >> 16) & 0xFF                    \
225
226 #define get_vertex_data_xy_uv(vertex_number, offset16)                         \
227   get_vertex_data_xy(vertex_number, offset16);                                 \
228   get_vertex_data_uv(vertex_number, (offset16) + 2)                            \
229
230 #define get_vertex_data_xy_rgb(vertex_number, offset16)                        \
231   get_vertex_data_rgb(vertex_number, (offset16) / 2);                          \
232   get_vertex_data_xy(vertex_number, (offset16) + 2);                           \
233
234 #define get_vertex_data_xy_uv_rgb(vertex_number, offset16)                     \
235   get_vertex_data_rgb(vertex_number, (offset16) / 2);                          \
236   get_vertex_data_xy(vertex_number, (offset16) + 2);                           \
237   get_vertex_data_uv(vertex_number, (offset16) + 4);                           \
238
239 #define set_vertex_color_constant(vertex_number, color)                        \
240   vertexes[vertex_number].r = color & 0xFF;                                    \
241   vertexes[vertex_number].g = (color >> 8) & 0xFF;                             \
242   vertexes[vertex_number].b = (color >> 16) & 0xFF                             \
243
244 #define get_vertex_data_xy_rgb_constant(vertex_number, offset16, color)        \
245   get_vertex_data_xy(vertex_number, offset16);                                 \
246   set_vertex_color_constant(vertex_number, color)                              \
247
248 #ifndef SET_Ex
249 #define SET_Ex(r, v)
250 #endif
251
252 vertex_struct vertexes[4] __attribute__((aligned(32)));
253
254 u32 gpu_parse(psx_gpu_struct *psx_gpu, u32 *list, u32 size, u32 *last_command)
255 {
256   u32 current_command = 0, command_length;
257
258   u32 *list_start = list;
259   u32 *list_end = list + (size / 4);
260
261   for(; list < list_end; list += 1 + command_length)
262   {
263         s16 *list_s16 = (void *)list;
264         current_command = *list >> 24;
265         command_length = command_lengths[current_command];
266         if (list + 1 + command_length > list_end) {
267           current_command = (u32)-1;
268           break;
269         }
270
271         switch(current_command)
272         {
273                 case 0x00:
274                         break;
275   
276                 case 0x02:
277       {
278         u32 x = list_s16[2] & 0x3FF;
279         u32 y = list_s16[3] & 0x1FF;
280         u32 width = list_s16[4] & 0x3FF;
281         u32 height = list_s16[5] & 0x1FF;
282         u32 color = list[0] & 0xFFFFFF;
283
284         do_fill(psx_gpu, x, y, width, height, color);
285                         break;
286       }
287   
288                 case 0x20 ... 0x23:
289       {
290         set_triangle_color(psx_gpu, list[0] & 0xFFFFFF);
291   
292         get_vertex_data_xy(0, 2);
293         get_vertex_data_xy(1, 4);
294         get_vertex_data_xy(2, 6);
295           
296         render_triangle(psx_gpu, vertexes, current_command);
297                         break;
298       }
299   
300                 case 0x24 ... 0x27:
301       {
302         set_clut(psx_gpu, list_s16[5]);
303         set_texture(psx_gpu, list_s16[9]);
304         set_triangle_color(psx_gpu, list[0] & 0xFFFFFF);
305   
306         get_vertex_data_xy_uv(0, 2);
307         get_vertex_data_xy_uv(1, 6);
308         get_vertex_data_xy_uv(2, 10);
309   
310         render_triangle(psx_gpu, vertexes, current_command);
311                         break;
312       }
313   
314                 case 0x28 ... 0x2B:
315       {
316         set_triangle_color(psx_gpu, list[0] & 0xFFFFFF);
317   
318         get_vertex_data_xy(0, 2);
319         get_vertex_data_xy(1, 4);
320         get_vertex_data_xy(2, 6);
321         get_vertex_data_xy(3, 8);
322   
323         render_triangle(psx_gpu, vertexes, current_command);
324         render_triangle(psx_gpu, &(vertexes[1]), current_command);
325                         break;
326       }
327   
328                 case 0x2C ... 0x2F:
329       {
330         set_clut(psx_gpu, list_s16[5]);
331         set_texture(psx_gpu, list_s16[9]);
332         set_triangle_color(psx_gpu, list[0] & 0xFFFFFF);
333   
334         get_vertex_data_xy_uv(0, 2);   
335         get_vertex_data_xy_uv(1, 6);   
336         get_vertex_data_xy_uv(2, 10);  
337         get_vertex_data_xy_uv(3, 14);
338   
339         render_triangle(psx_gpu, vertexes, current_command);
340         render_triangle(psx_gpu, &(vertexes[1]), current_command);
341                         break;
342       }
343   
344                 case 0x30 ... 0x33:
345       {
346         get_vertex_data_xy_rgb(0, 0);
347         get_vertex_data_xy_rgb(1, 4);
348         get_vertex_data_xy_rgb(2, 8);
349   
350         render_triangle(psx_gpu, vertexes, current_command);
351                         break;
352       }
353   
354                 case 0x34:
355                 case 0x35:
356                 case 0x36:
357                 case 0x37:
358       {
359         set_clut(psx_gpu, list_s16[5]);
360         set_texture(psx_gpu, list_s16[11]);
361   
362         get_vertex_data_xy_uv_rgb(0, 0);
363         get_vertex_data_xy_uv_rgb(1, 6);
364         get_vertex_data_xy_uv_rgb(2, 12);
365
366         render_triangle(psx_gpu, vertexes, current_command);
367                         break;
368       }
369   
370                 case 0x38:
371                 case 0x39:
372                 case 0x3A:
373                 case 0x3B:
374       {
375         get_vertex_data_xy_rgb(0, 0);
376         get_vertex_data_xy_rgb(1, 4);
377         get_vertex_data_xy_rgb(2, 8);
378         get_vertex_data_xy_rgb(3, 12);
379   
380         render_triangle(psx_gpu, vertexes, current_command);
381         render_triangle(psx_gpu, &(vertexes[1]), current_command);
382                         break;
383       }
384   
385                 case 0x3C:
386                 case 0x3D:
387                 case 0x3E:
388                 case 0x3F:
389       {
390         set_clut(psx_gpu, list_s16[5]);
391         set_texture(psx_gpu, list_s16[11]);
392   
393         get_vertex_data_xy_uv_rgb(0, 0);
394         get_vertex_data_xy_uv_rgb(1, 6);
395         get_vertex_data_xy_uv_rgb(2, 12);
396         get_vertex_data_xy_uv_rgb(3, 18);
397   
398         render_triangle(psx_gpu, vertexes, current_command);
399         render_triangle(psx_gpu, &(vertexes[1]), current_command);
400                         break;
401       }
402   
403                 case 0x40 ... 0x47:
404       {
405         vertexes[0].x = list_s16[2] + psx_gpu->offset_x;
406         vertexes[0].y = list_s16[3] + psx_gpu->offset_y;
407         vertexes[1].x = list_s16[4] + psx_gpu->offset_x;
408         vertexes[1].y = list_s16[5] + psx_gpu->offset_y;
409
410         render_line(psx_gpu, vertexes, current_command, list[0]);
411                         break;
412       }
413   
414                 case 0x48 ... 0x4F:
415       {
416         u32 num_vertexes = 1;
417         u32 *list_position = &(list[2]);
418         u32 xy = list[1];
419
420         vertexes[1].x = (xy & 0xFFFF) + psx_gpu->offset_x;
421         vertexes[1].y = (xy >> 16) + psx_gpu->offset_y;
422       
423         xy = *list_position;
424         while(1)
425         {
426           vertexes[0] = vertexes[1];
427
428           vertexes[1].x = (xy & 0xFFFF) + psx_gpu->offset_x;
429           vertexes[1].y = (xy >> 16) + psx_gpu->offset_y;
430
431           render_line(psx_gpu, vertexes, current_command, list[0]);
432
433           list_position++;
434           num_vertexes++;
435
436           if(list_position >= list_end)
437             break;
438
439           xy = *list_position;
440           if((xy & 0xF000F000) == 0x50005000)
441             break;
442         }
443
444         command_length += (num_vertexes - 2);
445         break;
446       }
447   
448                 case 0x50 ... 0x57:
449       {
450         vertexes[0].r = list[0] & 0xFF;
451         vertexes[0].g = (list[0] >> 8) & 0xFF;
452         vertexes[0].b = (list[0] >> 16) & 0xFF;
453         vertexes[0].x = list_s16[2] + psx_gpu->offset_x;
454         vertexes[0].y = list_s16[3] + psx_gpu->offset_y;
455
456         vertexes[1].r = list[2] & 0xFF;
457         vertexes[1].g = (list[2] >> 8) & 0xFF;
458         vertexes[1].b = (list[2] >> 16) & 0xFF;
459         vertexes[1].x = list_s16[6] + psx_gpu->offset_x;
460         vertexes[1].y = list_s16[7] + psx_gpu->offset_y;
461
462         render_line(psx_gpu, vertexes, current_command, 0);
463                         break;
464       }
465  
466       case 0x58 ... 0x5F:
467       {
468         u32 num_vertexes = 1;
469         u32 *list_position = &(list[2]);
470         u32 color = list[0];
471         u32 xy = list[1];
472
473         vertexes[1].r = color & 0xFF;
474         vertexes[1].g = (color >> 8) & 0xFF;
475         vertexes[1].b = (color >> 16) & 0xFF;
476         vertexes[1].x = (xy & 0xFFFF) + psx_gpu->offset_x;
477         vertexes[1].y = (xy >> 16) + psx_gpu->offset_y;
478       
479         color = list_position[0];
480         while(1)
481         {
482           xy = list_position[1];
483
484           vertexes[0] = vertexes[1];
485
486           vertexes[1].r = color & 0xFF;
487           vertexes[1].g = (color >> 8) & 0xFF;
488           vertexes[1].b = (color >> 16) & 0xFF;
489           vertexes[1].x = (xy & 0xFFFF) + psx_gpu->offset_x;
490           vertexes[1].y = (xy >> 16) + psx_gpu->offset_y;
491
492           render_line(psx_gpu, vertexes, current_command, 0);
493
494           list_position += 2;
495           num_vertexes++;
496
497           if(list_position >= list_end)
498             break;
499
500           color = list_position[0];
501           if((color & 0xF000F000) == 0x50005000)
502             break;
503         }
504
505         command_length += ((num_vertexes - 2) * 2);
506         break;
507       }
508   
509                 case 0x60 ... 0x63:
510       {        
511         u32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
512         u32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
513         u32 width = list_s16[4] & 0x3FF;
514         u32 height = list_s16[5] & 0x1FF;
515
516         render_sprite(psx_gpu, x, y, 0, 0, width, height, current_command, list[0]);
517                         break;
518       }
519   
520                 case 0x64 ... 0x67:
521       {        
522         u32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
523         u32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
524         u32 uv = list_s16[4];
525         u32 width = list_s16[6] & 0x3FF;
526         u32 height = list_s16[7] & 0x1FF;
527
528         set_clut(psx_gpu, list_s16[5]);
529
530         render_sprite(psx_gpu, x, y, uv & 0xFF, (uv >> 8) & 0xFF, width, height,
531          current_command, list[0]);
532                         break;
533       }
534   
535                 case 0x68:
536                 case 0x69:
537                 case 0x6A:
538                 case 0x6B:
539       {
540         s32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
541         s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
542
543         render_sprite(psx_gpu, x, y, 0, 0, 1, 1, current_command, list[0]);
544                         break;
545       }
546   
547                 case 0x70:
548                 case 0x71:
549                 case 0x72:
550                 case 0x73:
551       {        
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);
554
555         render_sprite(psx_gpu, x, y, 0, 0, 8, 8, current_command, list[0]);
556                         break;
557       }
558   
559                 case 0x74:
560                 case 0x75:
561                 case 0x76:
562                 case 0x77:
563       {        
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);
566         u32 uv = list_s16[4];
567
568         set_clut(psx_gpu, list_s16[5]);
569
570         render_sprite(psx_gpu, x, y, uv & 0xFF, (uv >> 8) & 0xFF, 8, 8,
571          current_command, list[0]);
572                         break;
573       }
574   
575                 case 0x78:
576                 case 0x79:
577                 case 0x7A:
578                 case 0x7B:
579       {        
580         s32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
581         s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
582
583         render_sprite(psx_gpu, x, y, 0, 0, 16, 16, current_command, list[0]);
584                         break;
585       }
586   
587                 case 0x7C:
588                 case 0x7D:
589                 case 0x7E:
590                 case 0x7F:
591       {        
592         s32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
593         s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
594         u32 uv = list_s16[4];
595
596         set_clut(psx_gpu, list_s16[5]);
597
598         render_sprite(psx_gpu, x, y, uv & 0xFF, (uv >> 8) & 0xFF, 16, 16,
599          current_command, list[0]);
600                         break;
601       }
602   
603                 case 0x80:          //  vid -> vid
604         render_block_move(psx_gpu, list_s16[2] & 0x3FF, list_s16[3] & 0x1FF,
605          list_s16[4] & 0x3FF, list_s16[5] & 0x1FF,
606          ((list_s16[6] - 1) & 0x3FF) + 1, ((list_s16[7] - 1) & 0x1FF) + 1);
607                         break;
608  
609 #ifdef PCSX
610                 case 0xA0:          //  sys -> vid
611                 case 0xC0:          //  vid -> sys
612                         goto breakloop;
613 #else
614                 case 0xA0:          //  sys -> vid
615       {
616         u32 load_x = list_s16[2] & 0x3FF;
617         u32 load_y = list_s16[3] & 0x1FF;
618         u32 load_width = list_s16[4] & 0x3FF;
619         u32 load_height = list_s16[5] & 0x1FF;
620         u32 load_size = load_width * load_height;
621   
622         command_length += load_size / 2;
623
624         if(load_size & 1)
625           command_length++;
626
627         render_block_copy(psx_gpu, (u16 *)&(list_s16[6]), load_x, load_y,
628          load_width, load_height, load_width);
629                         break;
630       }
631
632                 case 0xC0:          //  vid -> sys
633                         break;
634 #endif
635
636                 case 0xE1:
637         set_texture(psx_gpu, list[0] & 0x1FF);
638
639         if(list[0] & (1 << 9))
640           psx_gpu->render_state_base |= RENDER_STATE_DITHER;
641         else
642           psx_gpu->render_state_base &= ~RENDER_STATE_DITHER;
643
644         psx_gpu->display_area_draw_enable = (list[0] >> 10) & 0x1;
645                         SET_Ex(1, list[0]);
646                         break;
647   
648                 case 0xE2:
649       {
650         // TODO: Clean
651         u32 texture_window_settings = list[0];
652         u32 tmp, x, y, w, h;
653
654         if(texture_window_settings != psx_gpu->texture_window_settings)
655         {
656           tmp = (texture_window_settings & 0x1F) | 0x20;
657           for(w = 8; (tmp & 1) == 0; tmp >>= 1, w <<= 1);
658
659           tmp = ((texture_window_settings >> 5) & 0x1f) | 0x20;
660           for (h = 8; (tmp & 1) == 0; tmp >>= 1, h <<= 1);
661
662           tmp = 32 - (w >> 3);
663           x = ((texture_window_settings >> 10) & tmp) << 3;
664
665           tmp = 32 - (h >> 3);
666           y = ((texture_window_settings >> 15) & tmp) << 3;
667
668           flush_render_block_buffer(psx_gpu);
669           
670           psx_gpu->texture_window_settings = texture_window_settings;
671           psx_gpu->texture_window_x = x;
672           psx_gpu->texture_window_y = y;
673           psx_gpu->texture_mask_width = w - 1;
674           psx_gpu->texture_mask_height = h - 1;
675
676           update_texture_ptr(psx_gpu);
677         }
678         SET_Ex(2, list[0]);
679         break;
680                 }
681   
682                 case 0xE3:
683         psx_gpu->viewport_start_x = list[0] & 0x3FF;
684         psx_gpu->viewport_start_y = (list[0] >> 10) & 0x1FF;
685
686 #ifdef TEXTURE_CACHE_4BPP
687         psx_gpu->viewport_mask =
688          texture_region_mask(psx_gpu->viewport_start_x,
689          psx_gpu->viewport_start_y, psx_gpu->viewport_end_x,
690          psx_gpu->viewport_end_y);
691 #endif
692                         SET_Ex(3, list[0]);
693                         break;
694   
695                 case 0xE4:
696         psx_gpu->viewport_end_x = list[0] & 0x3FF;
697         psx_gpu->viewport_end_y = (list[0] >> 10) & 0x1FF;
698
699 #ifdef TEXTURE_CACHE_4BPP
700         psx_gpu->viewport_mask =
701          texture_region_mask(psx_gpu->viewport_start_x,
702          psx_gpu->viewport_start_y, psx_gpu->viewport_end_x,
703          psx_gpu->viewport_end_y);
704 #endif
705                         SET_Ex(4, list[0]);
706                         break;
707   
708                 case 0xE5:
709       {
710         s32 offset_x = list[0] << 21;
711         s32 offset_y = list[0] << 10;
712         psx_gpu->offset_x = offset_x >> 21;
713         psx_gpu->offset_y = offset_y >> 21; 
714   
715                         SET_Ex(5, list[0]);
716                         break;
717                 }
718
719                 case 0xE6:
720       {
721         u32 mask_settings = list[0];
722         u16 mask_msb = mask_settings << 15;
723
724         if(list[0] & 0x2)
725           psx_gpu->render_state_base |= RENDER_STATE_MASK_EVALUATE;
726         else
727           psx_gpu->render_state_base &= ~RENDER_STATE_MASK_EVALUATE;
728
729         if(mask_msb != psx_gpu->mask_msb)
730         {
731           flush_render_block_buffer(psx_gpu);
732           psx_gpu->mask_msb = mask_msb;
733         }
734
735                         SET_Ex(6, list[0]);
736                         break;
737       }
738   
739                 default:
740                         break;
741         }
742   }
743
744 #ifdef PCSX
745 breakloop:
746 #endif
747   if (last_command != NULL)
748     *last_command = current_command;
749   return list - list_start;
750 }
751
752 #define enhancement_disable() { \
753   psx_gpu->vram_out_ptr = psx_gpu->vram_ptr; \
754   psx_gpu->viewport_start_x = psx_gpu->saved_viewport_start_x; \
755   psx_gpu->viewport_start_y = psx_gpu->saved_viewport_start_y; \
756   psx_gpu->viewport_end_x = psx_gpu->saved_viewport_end_x; \
757   psx_gpu->viewport_end_y = psx_gpu->saved_viewport_end_y; \
758 }
759
760 #define enhancement_enable() { \
761   psx_gpu->vram_out_ptr = psx_gpu->enhancement_buf_ptr; \
762   psx_gpu->viewport_start_x = psx_gpu->saved_viewport_start_x * 2; \
763   psx_gpu->viewport_start_y = psx_gpu->saved_viewport_start_y * 2; \
764   psx_gpu->viewport_end_x = psx_gpu->saved_viewport_end_x * 2; \
765   psx_gpu->viewport_end_y = psx_gpu->saved_viewport_end_y * 2; \
766 }
767
768 #define shift_vertices3(v) { \
769   v[0]->x *= 2; \
770   v[0]->y *= 2; \
771   v[1]->x *= 2; \
772   v[1]->y *= 2; \
773   v[2]->x *= 2; \
774   v[2]->y *= 2; \
775 }
776
777 #define unshift_vertices3(v) { \
778   v[0]->x /= 2; \
779   v[0]->y /= 2; \
780   v[1]->x /= 2; \
781   v[1]->y /= 2; \
782   v[2]->x /= 2; \
783   v[2]->y /= 2; \
784 }
785
786 #define shift_triangle_area() \
787   psx_gpu->triangle_area *= 4
788
789 static int disable_main_render;
790
791 static void do_triangle_enhanced(psx_gpu_struct *psx_gpu,
792  vertex_struct *vertexes, u32 current_command)
793 {
794   vertex_struct *vertex_ptrs[3];
795
796   if (!prepare_triangle(psx_gpu, vertexes, vertex_ptrs))
797     return;
798
799   if (!disable_main_render)
800     render_triangle_p(psx_gpu, vertex_ptrs, current_command);
801
802   enhancement_enable();
803   shift_vertices3(vertex_ptrs);
804   shift_triangle_area();
805   render_triangle_p(psx_gpu, vertex_ptrs, current_command);
806 }
807
808 static void do_quad_enhanced(psx_gpu_struct *psx_gpu, vertex_struct *vertexes,
809  u32 current_command)
810 {
811   vertex_struct *vertex_ptrs[3];
812
813   if (prepare_triangle(psx_gpu, vertexes, vertex_ptrs)) {
814     if (!disable_main_render)
815       render_triangle_p(psx_gpu, vertex_ptrs, current_command);
816
817     enhancement_enable();
818     shift_vertices3(vertex_ptrs);
819     shift_triangle_area();
820     render_triangle_p(psx_gpu, vertex_ptrs, current_command);
821     unshift_vertices3(vertex_ptrs);
822   }
823   enhancement_disable();
824   if (prepare_triangle(psx_gpu, &vertexes[1], vertex_ptrs)) {
825     if (!disable_main_render)
826       render_triangle_p(psx_gpu, vertex_ptrs, current_command);
827
828     enhancement_enable();
829     shift_vertices3(vertex_ptrs);
830     shift_triangle_area();
831     render_triangle_p(psx_gpu, vertex_ptrs, current_command);
832   }
833 }
834
835 u32 gpu_parse_enhanced(psx_gpu_struct *psx_gpu, u32 *list, u32 size, u32 *last_command)
836 {
837   u32 current_command = 0, command_length;
838
839   u32 *list_start = list;
840   u32 *list_end = list + (size / 4);
841
842   psx_gpu->saved_viewport_start_x = psx_gpu->viewport_start_x;
843   psx_gpu->saved_viewport_start_y = psx_gpu->viewport_start_y;
844   psx_gpu->saved_viewport_end_x = psx_gpu->viewport_end_x;
845   psx_gpu->saved_viewport_end_y = psx_gpu->viewport_end_y;
846
847   for(; list < list_end; list += 1 + command_length)
848   {
849     s16 *list_s16 = (void *)list;
850     current_command = *list >> 24;
851     command_length = command_lengths[current_command];
852     if (list + 1 + command_length > list_end) {
853       current_command = (u32)-1;
854       break;
855     }
856
857     enhancement_disable();
858
859     switch(current_command)
860     {
861       case 0x00:
862         break;
863   
864       case 0x02:
865       {
866         u32 x = list_s16[2] & 0x3FF;
867         u32 y = list_s16[3] & 0x1FF;
868         u32 width = list_s16[4] & 0x3FF;
869         u32 height = list_s16[5] & 0x1FF;
870         u32 color = list[0] & 0xFFFFFF;
871
872         do_fill(psx_gpu, x, y, width, height, color);
873
874         psx_gpu->vram_out_ptr = psx_gpu->enhancement_buf_ptr;
875         x *= 2;
876         y *= 2;
877         width *= 2;
878         height *= 2;
879         if (width > 1024)
880           width = 1024;
881         render_block_fill(psx_gpu, color, x, y, width, height);
882         break;
883       }
884   
885       case 0x20 ... 0x23:
886       {
887         set_triangle_color(psx_gpu, list[0] & 0xFFFFFF);
888   
889         get_vertex_data_xy(0, 2);
890         get_vertex_data_xy(1, 4);
891         get_vertex_data_xy(2, 6);
892
893         do_triangle_enhanced(psx_gpu, vertexes, current_command);
894         break;
895       }
896   
897       case 0x24 ... 0x27:
898       {
899         set_clut(psx_gpu, list_s16[5]);
900         set_texture(psx_gpu, list_s16[9]);
901         set_triangle_color(psx_gpu, list[0] & 0xFFFFFF);
902   
903         get_vertex_data_xy_uv(0, 2);
904         get_vertex_data_xy_uv(1, 6);
905         get_vertex_data_xy_uv(2, 10);
906   
907         do_triangle_enhanced(psx_gpu, vertexes, current_command);
908         break;
909       }
910   
911       case 0x28 ... 0x2B:
912       {
913         set_triangle_color(psx_gpu, list[0] & 0xFFFFFF);
914   
915         get_vertex_data_xy(0, 2);
916         get_vertex_data_xy(1, 4);
917         get_vertex_data_xy(2, 6);
918         get_vertex_data_xy(3, 8);
919
920         do_quad_enhanced(psx_gpu, vertexes, current_command);
921         break;
922       }
923   
924       case 0x2C ... 0x2F:
925       {
926         set_clut(psx_gpu, list_s16[5]);
927         set_texture(psx_gpu, list_s16[9]);
928         set_triangle_color(psx_gpu, list[0] & 0xFFFFFF);
929   
930         get_vertex_data_xy_uv(0, 2);   
931         get_vertex_data_xy_uv(1, 6);   
932         get_vertex_data_xy_uv(2, 10);  
933         get_vertex_data_xy_uv(3, 14);
934   
935         do_quad_enhanced(psx_gpu, vertexes, current_command);
936         break;
937       }
938   
939       case 0x30 ... 0x33:
940       {
941         get_vertex_data_xy_rgb(0, 0);
942         get_vertex_data_xy_rgb(1, 4);
943         get_vertex_data_xy_rgb(2, 8);
944   
945         do_triangle_enhanced(psx_gpu, vertexes, current_command);
946         break;
947       }
948   
949       case 0x34:
950       case 0x35:
951       case 0x36:
952       case 0x37:
953       {
954         set_clut(psx_gpu, list_s16[5]);
955         set_texture(psx_gpu, list_s16[11]);
956   
957         get_vertex_data_xy_uv_rgb(0, 0);
958         get_vertex_data_xy_uv_rgb(1, 6);
959         get_vertex_data_xy_uv_rgb(2, 12);
960
961         do_triangle_enhanced(psx_gpu, vertexes, current_command);
962         break;
963       }
964   
965       case 0x38:
966       case 0x39:
967       case 0x3A:
968       case 0x3B:
969       {
970         get_vertex_data_xy_rgb(0, 0);
971         get_vertex_data_xy_rgb(1, 4);
972         get_vertex_data_xy_rgb(2, 8);
973         get_vertex_data_xy_rgb(3, 12);
974   
975         do_quad_enhanced(psx_gpu, vertexes, current_command);
976         break;
977       }
978   
979       case 0x3C:
980       case 0x3D:
981       case 0x3E:
982       case 0x3F:
983       {
984         set_clut(psx_gpu, list_s16[5]);
985         set_texture(psx_gpu, list_s16[11]);
986   
987         get_vertex_data_xy_uv_rgb(0, 0);
988         get_vertex_data_xy_uv_rgb(1, 6);
989         get_vertex_data_xy_uv_rgb(2, 12);
990         get_vertex_data_xy_uv_rgb(3, 18);
991
992         do_quad_enhanced(psx_gpu, vertexes, current_command);
993         break;
994       }
995   
996       case 0x40 ... 0x47:
997       {
998         vertexes[0].x = list_s16[2] + psx_gpu->offset_x;
999         vertexes[0].y = list_s16[3] + psx_gpu->offset_y;
1000         vertexes[1].x = list_s16[4] + psx_gpu->offset_x;
1001         vertexes[1].y = list_s16[5] + psx_gpu->offset_y;
1002
1003         render_line(psx_gpu, vertexes, current_command, list[0]);
1004         break;
1005       }
1006   
1007       case 0x48 ... 0x4F:
1008       {
1009         u32 num_vertexes = 1;
1010         u32 *list_position = &(list[2]);
1011         u32 xy = list[1];
1012
1013         vertexes[1].x = (xy & 0xFFFF) + psx_gpu->offset_x;
1014         vertexes[1].y = (xy >> 16) + psx_gpu->offset_y;
1015       
1016         xy = *list_position;
1017         while(1)
1018         {
1019           vertexes[0] = vertexes[1];
1020
1021           vertexes[1].x = (xy & 0xFFFF) + psx_gpu->offset_x;
1022           vertexes[1].y = (xy >> 16) + psx_gpu->offset_y;
1023
1024           render_line(psx_gpu, vertexes, current_command, list[0]);
1025
1026           list_position++;
1027           num_vertexes++;
1028
1029           if(list_position >= list_end)
1030             break;
1031
1032           xy = *list_position;
1033           if((xy & 0xF000F000) == 0x50005000)
1034             break;
1035         }
1036
1037         command_length += (num_vertexes - 2);
1038         break;
1039       }
1040   
1041       case 0x50 ... 0x57:
1042       {
1043         vertexes[0].r = list[0] & 0xFF;
1044         vertexes[0].g = (list[0] >> 8) & 0xFF;
1045         vertexes[0].b = (list[0] >> 16) & 0xFF;
1046         vertexes[0].x = list_s16[2] + psx_gpu->offset_x;
1047         vertexes[0].y = list_s16[3] + psx_gpu->offset_y;
1048
1049         vertexes[1].r = list[2] & 0xFF;
1050         vertexes[1].g = (list[2] >> 8) & 0xFF;
1051         vertexes[1].b = (list[2] >> 16) & 0xFF;
1052         vertexes[1].x = list_s16[6] + psx_gpu->offset_x;
1053         vertexes[1].y = list_s16[7] + psx_gpu->offset_y;
1054
1055         render_line(psx_gpu, vertexes, current_command, 0);
1056         break;
1057       }
1058  
1059       case 0x58 ... 0x5F:
1060       {
1061         u32 num_vertexes = 1;
1062         u32 *list_position = &(list[2]);
1063         u32 color = list[0];
1064         u32 xy = list[1];
1065
1066         vertexes[1].r = color & 0xFF;
1067         vertexes[1].g = (color >> 8) & 0xFF;
1068         vertexes[1].b = (color >> 16) & 0xFF;
1069         vertexes[1].x = (xy & 0xFFFF) + psx_gpu->offset_x;
1070         vertexes[1].y = (xy >> 16) + psx_gpu->offset_y;
1071       
1072         color = list_position[0];
1073         while(1)
1074         {
1075           xy = list_position[1];
1076
1077           vertexes[0] = vertexes[1];
1078
1079           vertexes[1].r = color & 0xFF;
1080           vertexes[1].g = (color >> 8) & 0xFF;
1081           vertexes[1].b = (color >> 16) & 0xFF;
1082           vertexes[1].x = (xy & 0xFFFF) + psx_gpu->offset_x;
1083           vertexes[1].y = (xy >> 16) + psx_gpu->offset_y;
1084
1085           render_line(psx_gpu, vertexes, current_command, 0);
1086
1087           list_position += 2;
1088           num_vertexes++;
1089
1090           if(list_position >= list_end)
1091             break;
1092
1093           color = list_position[0];
1094           if((color & 0xF000F000) == 0x50005000)
1095             break;
1096         }
1097
1098         command_length += ((num_vertexes - 2) * 2);
1099         break;
1100       }
1101   
1102       case 0x60 ... 0x63:
1103       {        
1104         u32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
1105         u32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
1106         u32 width = list_s16[4] & 0x3FF;
1107         u32 height = list_s16[5] & 0x1FF;
1108
1109         render_sprite(psx_gpu, x, y, 0, 0, width, height, current_command, list[0]);
1110         break;
1111       }
1112   
1113       case 0x64 ... 0x67:
1114       {        
1115         u32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
1116         u32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
1117         u32 uv = list_s16[4];
1118         u32 width = list_s16[6] & 0x3FF;
1119         u32 height = list_s16[7] & 0x1FF;
1120
1121         set_clut(psx_gpu, list_s16[5]);
1122
1123         render_sprite(psx_gpu, x, y, uv & 0xFF, (uv >> 8) & 0xFF, width, height,
1124          current_command, list[0]);
1125         break;
1126       }
1127   
1128       case 0x68:
1129       case 0x69:
1130       case 0x6A:
1131       case 0x6B:
1132       {
1133         s32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
1134         s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
1135
1136         render_sprite(psx_gpu, x, y, 0, 0, 1, 1, current_command, list[0]);
1137         break;
1138       }
1139   
1140       case 0x70:
1141       case 0x71:
1142       case 0x72:
1143       case 0x73:
1144       {        
1145         s32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
1146         s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
1147
1148         render_sprite(psx_gpu, x, y, 0, 0, 8, 8, current_command, list[0]);
1149         break;
1150       }
1151   
1152       case 0x74:
1153       case 0x75:
1154       case 0x76:
1155       case 0x77:
1156       {        
1157         s32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
1158         s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
1159         u32 uv = list_s16[4];
1160
1161         set_clut(psx_gpu, list_s16[5]);
1162
1163         render_sprite(psx_gpu, x, y, uv & 0xFF, (uv >> 8) & 0xFF, 8, 8,
1164          current_command, list[0]);
1165         break;
1166       }
1167   
1168       case 0x78:
1169       case 0x79:
1170       case 0x7A:
1171       case 0x7B:
1172       {        
1173         s32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
1174         s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
1175
1176         render_sprite(psx_gpu, x, y, 0, 0, 16, 16, current_command, list[0]);
1177         break;
1178       }
1179   
1180       case 0x7C:
1181       case 0x7D:
1182       case 0x7E:
1183       case 0x7F:
1184       {        
1185         s32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
1186         s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
1187         u32 uv = list_s16[4];
1188
1189         set_clut(psx_gpu, list_s16[5]);
1190
1191         render_sprite(psx_gpu, x, y, uv & 0xFF, (uv >> 8) & 0xFF, 16, 16,
1192          current_command, list[0]);
1193         break;
1194       }
1195   
1196       case 0x80:          //  vid -> vid
1197         render_block_move(psx_gpu, list_s16[2] & 0x3FF, list_s16[3] & 0x1FF,
1198          list_s16[4] & 0x3FF, list_s16[5] & 0x1FF,
1199          ((list_s16[6] - 1) & 0x3FF) + 1, ((list_s16[7] - 1) & 0x1FF) + 1);
1200         break;
1201  
1202 #ifdef PCSX
1203       case 0xA0:          //  sys -> vid
1204       case 0xC0:          //  vid -> sys
1205         goto breakloop;
1206 #else
1207       case 0xA0:          //  sys -> vid
1208       {
1209         u32 load_x = list_s16[2] & 0x3FF;
1210         u32 load_y = list_s16[3] & 0x1FF;
1211         u32 load_width = list_s16[4] & 0x3FF;
1212         u32 load_height = list_s16[5] & 0x1FF;
1213         u32 load_size = load_width * load_height;
1214   
1215         command_length += load_size / 2;
1216
1217         if(load_size & 1)
1218           command_length++;
1219
1220         render_block_copy(psx_gpu, (u16 *)&(list_s16[6]), load_x, load_y,
1221          load_width, load_height, load_width);
1222         break;
1223       }
1224
1225       case 0xC0:          //  vid -> sys
1226         break;
1227 #endif
1228
1229       case 0xE1:
1230         set_texture(psx_gpu, list[0] & 0x1FF);
1231
1232         if(list[0] & (1 << 9))
1233           psx_gpu->render_state_base |= RENDER_STATE_DITHER;
1234         else
1235           psx_gpu->render_state_base &= ~RENDER_STATE_DITHER;
1236
1237         psx_gpu->display_area_draw_enable = (list[0] >> 10) & 0x1;
1238         SET_Ex(1, list[0]);
1239         break;
1240   
1241       case 0xE2:
1242       {
1243         // TODO: Clean
1244         u32 texture_window_settings = list[0];
1245         u32 tmp, x, y, w, h;
1246
1247         if(texture_window_settings != psx_gpu->texture_window_settings)
1248         {
1249           tmp = (texture_window_settings & 0x1F) | 0x20;
1250           for(w = 8; (tmp & 1) == 0; tmp >>= 1, w <<= 1);
1251
1252           tmp = ((texture_window_settings >> 5) & 0x1f) | 0x20;
1253           for (h = 8; (tmp & 1) == 0; tmp >>= 1, h <<= 1);
1254
1255           tmp = 32 - (w >> 3);
1256           x = ((texture_window_settings >> 10) & tmp) << 3;
1257
1258           tmp = 32 - (h >> 3);
1259           y = ((texture_window_settings >> 15) & tmp) << 3;
1260
1261           flush_render_block_buffer(psx_gpu);
1262           
1263           psx_gpu->texture_window_settings = texture_window_settings;
1264           psx_gpu->texture_window_x = x;
1265           psx_gpu->texture_window_y = y;
1266           psx_gpu->texture_mask_width = w - 1;
1267           psx_gpu->texture_mask_height = h - 1;
1268
1269           update_texture_ptr(psx_gpu);
1270         }
1271         SET_Ex(2, list[0]);
1272         break;
1273       }
1274   
1275       case 0xE3:
1276         psx_gpu->viewport_start_x = list[0] & 0x3FF;
1277         psx_gpu->viewport_start_y = (list[0] >> 10) & 0x1FF;
1278         psx_gpu->saved_viewport_start_x = psx_gpu->viewport_start_x;
1279         psx_gpu->saved_viewport_start_y = psx_gpu->viewport_start_y;
1280
1281 #ifdef TEXTURE_CACHE_4BPP
1282         psx_gpu->viewport_mask =
1283          texture_region_mask(psx_gpu->viewport_start_x,
1284          psx_gpu->viewport_start_y, psx_gpu->viewport_end_x,
1285          psx_gpu->viewport_end_y);
1286 #endif
1287         SET_Ex(3, list[0]);
1288         break;
1289   
1290       case 0xE4:
1291         psx_gpu->viewport_end_x = list[0] & 0x3FF;
1292         psx_gpu->viewport_end_y = (list[0] >> 10) & 0x1FF;
1293         psx_gpu->saved_viewport_end_x = psx_gpu->viewport_end_x;
1294         psx_gpu->saved_viewport_end_y = psx_gpu->viewport_end_y;
1295
1296 #ifdef TEXTURE_CACHE_4BPP
1297         psx_gpu->viewport_mask =
1298          texture_region_mask(psx_gpu->viewport_start_x,
1299          psx_gpu->viewport_start_y, psx_gpu->viewport_end_x,
1300          psx_gpu->viewport_end_y);
1301 #endif
1302         SET_Ex(4, list[0]);
1303         break;
1304   
1305       case 0xE5:
1306       {
1307         s32 offset_x = list[0] << 21;
1308         s32 offset_y = list[0] << 10;
1309         psx_gpu->offset_x = offset_x >> 21;
1310         psx_gpu->offset_y = offset_y >> 21; 
1311   
1312         SET_Ex(5, list[0]);
1313         break;
1314       }
1315
1316       case 0xE6:
1317       {
1318         u32 mask_settings = list[0];
1319         u16 mask_msb = mask_settings << 15;
1320
1321         if(list[0] & 0x2)
1322           psx_gpu->render_state_base |= RENDER_STATE_MASK_EVALUATE;
1323         else
1324           psx_gpu->render_state_base &= ~RENDER_STATE_MASK_EVALUATE;
1325
1326         if(mask_msb != psx_gpu->mask_msb)
1327         {
1328           flush_render_block_buffer(psx_gpu);
1329           psx_gpu->mask_msb = mask_msb;
1330         }
1331
1332         SET_Ex(6, list[0]);
1333         break;
1334       }
1335   
1336       default:
1337         break;
1338     }
1339   }
1340
1341 #ifdef PCSX
1342 breakloop:
1343 #endif
1344 enhancement_disable();
1345   if (last_command != NULL)
1346     *last_command = current_command;
1347   return list - list_start;
1348 }
1349
1350 // vim:shiftwidth=2:expandtab