gpu_neon: flush queues before reads too
[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 const u8 command_lengths[256] =
20 {
21         0,  0,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   // 00
22         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   // 10
23         3,  3,  3,  3,  6,  6,  6,  6,  4,  4,  4,  4,  8,  8,  8,  8,   // 20
24         5,  5,  5,  5,  8,  8,  8,  8,  7,  7,  7,  7,  11, 11, 11, 11,  // 30
25         2,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,  3,  3,  3,  3,  3,   // 40
26         3,  3,  3,  3,  3,  3,  3,  3,  4,  4,  4,  4,  4,  4,  4,  4,   // 50
27         2,  2,  2,  2,  3,  3,  3,  3,  1,  1,  1,  1,  1,  1,  1,  1,   // 60
28         1,  1,  1,  1,  2,  2,  2,  2,  1,  1,  1,  1,  2,  2,  2,  2,   // 70
29         3,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   // 80
30         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   // 90
31         2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   // a0
32         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   // b0
33         2,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   // c0
34         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   // d0
35         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,   // e0
36         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0    // f0
37 };
38
39 void update_texture_ptr(psx_gpu_struct *psx_gpu)
40 {
41   u8 *texture_base;
42   u8 *texture_ptr;
43
44   switch((psx_gpu->render_state_base >> 8) & 0x3)
45   {
46     default:
47     case TEXTURE_MODE_4BPP:
48       texture_base = psx_gpu->texture_4bpp_cache[psx_gpu->current_texture_page];
49
50       texture_ptr = texture_base;
51       texture_ptr += psx_gpu->texture_window_x & 0xF;
52       texture_ptr += (psx_gpu->texture_window_y & 0xF) << 4;
53       texture_ptr += (psx_gpu->texture_window_x >> 4) << 8;
54       texture_ptr += (psx_gpu->texture_window_y >> 4) << 12;
55       break;
56
57     case TEXTURE_MODE_8BPP:
58       if(psx_gpu->current_texture_page & 0x1)
59       {
60         texture_base =
61          psx_gpu->texture_8bpp_odd_cache[psx_gpu->current_texture_page >> 1];
62       }
63       else
64       {
65         texture_base =
66          psx_gpu->texture_8bpp_even_cache[psx_gpu->current_texture_page >> 1];
67       }
68       
69       texture_ptr = texture_base;
70       texture_ptr += psx_gpu->texture_window_x & 0xF;
71       texture_ptr += (psx_gpu->texture_window_y & 0xF) << 4;
72       texture_ptr += (psx_gpu->texture_window_x >> 4) << 8;
73       texture_ptr += (psx_gpu->texture_window_y >> 4) << 12;
74       break;
75
76     case TEXTURE_MODE_16BPP:
77       texture_base = (u8 *)(psx_gpu->vram_ptr);
78       texture_base += (psx_gpu->current_texture_page & 0xF) * 128;
79       texture_base += ((psx_gpu->current_texture_page >> 4) * 256) * 2048;
80
81       texture_ptr = texture_base;
82       texture_ptr += psx_gpu->texture_window_x * 2;
83       texture_ptr += (psx_gpu->texture_window_y) * 2048;
84       break;
85   }
86
87   psx_gpu->texture_page_base = texture_base;
88   psx_gpu->texture_page_ptr = texture_ptr;  
89 }
90
91 void set_texture(psx_gpu_struct *psx_gpu, u32 texture_settings)
92 {
93   if(psx_gpu->texture_settings != texture_settings)
94   {
95     u32 new_texture_page = texture_settings & 0x1F;
96     u32 texture_mode = (texture_settings >> 7) & 0x3;
97     u32 render_state_base = psx_gpu->render_state_base;
98
99     flush_render_block_buffer(psx_gpu);
100
101     render_state_base &= ~(0xF << 6);
102     render_state_base |= ((texture_settings >> 5) & 0xF) << 6;
103
104     psx_gpu->render_state_base = render_state_base;
105
106     psx_gpu->current_texture_mask = 0x1 << new_texture_page;
107
108     if(texture_mode == TEXTURE_MODE_8BPP)
109     {     
110       // In 8bpp mode 256x256 takes up two pages. If it's on the right edge it
111       // wraps back around to the left edge.
112       u32 adjacent_texture_page = ((texture_settings + 1) & 0xF) | (texture_settings & 0x10);
113       psx_gpu->current_texture_mask |= 0x1 << adjacent_texture_page;
114
115       if((psx_gpu->last_8bpp_texture_page ^ new_texture_page) & 0x1)
116       {
117         u32 dirty_textures_8bpp_alternate_mask =
118          psx_gpu->dirty_textures_8bpp_alternate_mask;
119         psx_gpu->dirty_textures_8bpp_alternate_mask =
120          psx_gpu->dirty_textures_8bpp_mask;
121         psx_gpu->dirty_textures_8bpp_mask = dirty_textures_8bpp_alternate_mask;
122       }
123
124       psx_gpu->last_8bpp_texture_page = new_texture_page;
125     }
126
127     psx_gpu->current_texture_page = new_texture_page;
128     psx_gpu->texture_settings = texture_settings;
129
130     update_texture_ptr(psx_gpu);
131   }
132 }
133
134 void set_clut(psx_gpu_struct *psx_gpu, u32 clut_settings)
135 {
136   if(psx_gpu->clut_settings != clut_settings)
137   {
138     flush_render_block_buffer(psx_gpu);
139     psx_gpu->clut_settings = clut_settings;
140     psx_gpu->clut_ptr = psx_gpu->vram_ptr + ((clut_settings & 0x7FFF) * 16);
141   }
142 }
143
144 void set_triangle_color(psx_gpu_struct *psx_gpu, u32 triangle_color)
145 {
146   if(psx_gpu->triangle_color != triangle_color)
147   {
148     flush_render_block_buffer(psx_gpu);
149     psx_gpu->triangle_color = triangle_color;
150   }
151 }
152
153 #define sign_extend_12bit(value)                                               \
154   (((s32)((value) << 20)) >> 20)                                               \
155
156 #define sign_extend_11bit(value)                                               \
157   (((s32)((value) << 21)) >> 21)                                               \
158
159 #define sign_extend_10bit(value)                                               \
160   (((s32)((value) << 22)) >> 22)                                               \
161
162
163 #define get_vertex_data_xy(vertex_number, offset16)                            \
164   vertexes[vertex_number].x =                                                  \
165    sign_extend_12bit(list_s16[offset16]) + psx_gpu->offset_x;                  \
166   vertexes[vertex_number].y =                                                  \
167    sign_extend_12bit(list_s16[(offset16) + 1]) + psx_gpu->offset_y;            \
168
169 #define get_vertex_data_uv(vertex_number, offset16)                            \
170   vertexes[vertex_number].u = list_s16[offset16] & 0xFF;                       \
171   vertexes[vertex_number].v = (list_s16[offset16] >> 8) & 0xFF                 \
172
173 #define get_vertex_data_rgb(vertex_number, offset32)                           \
174   vertexes[vertex_number].r = list[offset32] & 0xFF;                           \
175   vertexes[vertex_number].g = (list[offset32] >> 8) & 0xFF;                    \
176   vertexes[vertex_number].b = (list[offset32] >> 16) & 0xFF                    \
177
178 #define get_vertex_data_xy_uv(vertex_number, offset16)                         \
179   get_vertex_data_xy(vertex_number, offset16);                                 \
180   get_vertex_data_uv(vertex_number, (offset16) + 2)                            \
181
182 #define get_vertex_data_xy_rgb(vertex_number, offset16)                        \
183   get_vertex_data_rgb(vertex_number, (offset16) / 2);                          \
184   get_vertex_data_xy(vertex_number, (offset16) + 2);                           \
185
186 #define get_vertex_data_xy_uv_rgb(vertex_number, offset16)                     \
187   get_vertex_data_rgb(vertex_number, (offset16) / 2);                          \
188   get_vertex_data_xy(vertex_number, (offset16) + 2);                           \
189   get_vertex_data_uv(vertex_number, (offset16) + 4);                           \
190
191 #define set_vertex_color_constant(vertex_number, color)                        \
192   vertexes[vertex_number].r = color & 0xFF;                                    \
193   vertexes[vertex_number].g = (color >> 8) & 0xFF;                             \
194   vertexes[vertex_number].b = (color >> 16) & 0xFF                             \
195
196 #define get_vertex_data_xy_rgb_constant(vertex_number, offset16, color)        \
197   get_vertex_data_xy(vertex_number, offset16);                                 \
198   set_vertex_color_constant(vertex_number, color)                              \
199
200 vertex_struct vertexes[4] __attribute__((aligned(32)));
201
202 void gpu_parse(psx_gpu_struct *psx_gpu, u32 *list, u32 size)
203 {
204   u32 current_command, command_length;
205   
206   u32 *list_end = list + (size / 4);
207
208   for(; list < list_end; list += 1 + command_length)
209   {
210         s16 *list_s16 = (void *)list;
211         current_command = *list >> 24;
212         command_length = command_lengths[current_command];
213
214         switch(current_command)
215         {
216                 case 0x00:
217                         break;
218   
219                 case 0x02:
220       {
221         u32 x = list_s16[2] & 0x3FF;
222         u32 y = list_s16[3] & 0x1FF;
223         u32 width = list_s16[4] & 0x3FF;
224         u32 height = list_s16[5] & 0x1FF;
225         u32 color = list[0] & 0xFFFFFF;
226
227         x &= ~0xF;
228         width = ((width + 0xF) & ~0xF);
229
230         if((x + width) > 1024)
231         {
232           u32 width_a = 1024 - x;
233           u32 width_b = width - width_a;
234
235           if((y + height) > 512)
236           {
237             u32 height_a = 512 - y;
238             u32 height_b = height - height_a;
239
240             render_block_fill(psx_gpu, color, x, y, width_a, height_a);
241             render_block_fill(psx_gpu, color, 0, y, width_b, height_a);
242             render_block_fill(psx_gpu, color, x, 0, width_a, height_b);
243             render_block_fill(psx_gpu, color, 0, 0, width_b, height_b);
244           }
245           else
246           {
247             render_block_fill(psx_gpu, color, x, y, width_a, height);
248             render_block_fill(psx_gpu, color, 0, y, width_b, height);
249           }
250         }
251         else
252         {
253           if((y + height) > 512)
254           {
255             u32 height_a = 512 - y;
256             u32 height_b = height - height_a;
257
258             render_block_fill(psx_gpu, color, x, y, width, height_a);
259             render_block_fill(psx_gpu, color, x, 0, width, height_b);
260           }
261           else
262           {
263             render_block_fill(psx_gpu, color, x, y, width, height);
264           }
265         }
266                         break;
267       }
268   
269                 case 0x20 ... 0x23:
270       {
271         set_triangle_color(psx_gpu, list[0] & 0xFFFFFF);
272   
273         get_vertex_data_xy(0, 2);
274         get_vertex_data_xy(1, 4);
275         get_vertex_data_xy(2, 6);
276           
277         render_triangle(psx_gpu, vertexes, current_command);
278                         break;
279       }
280   
281                 case 0x24 ... 0x27:
282       {
283         set_clut(psx_gpu, list_s16[5]);
284         set_texture(psx_gpu, list_s16[9]);
285         set_triangle_color(psx_gpu, list[0] & 0xFFFFFF);
286   
287         get_vertex_data_xy_uv(0, 2);
288         get_vertex_data_xy_uv(1, 6);
289         get_vertex_data_xy_uv(2, 10);
290   
291         render_triangle(psx_gpu, vertexes, current_command);
292                         break;
293       }
294   
295                 case 0x28 ... 0x2B:
296       {
297         set_triangle_color(psx_gpu, list[0] & 0xFFFFFF);
298   
299         get_vertex_data_xy(0, 2);
300         get_vertex_data_xy(1, 4);
301         get_vertex_data_xy(2, 6);
302         get_vertex_data_xy(3, 8);
303   
304         render_triangle(psx_gpu, vertexes, current_command);
305         render_triangle(psx_gpu, &(vertexes[1]), current_command);
306                         break;
307       }
308   
309                 case 0x2C ... 0x2F:
310       {
311         set_clut(psx_gpu, list_s16[5]);
312         set_texture(psx_gpu, list_s16[9]);
313         set_triangle_color(psx_gpu, list[0] & 0xFFFFFF);
314   
315         get_vertex_data_xy_uv(0, 2);   
316         get_vertex_data_xy_uv(1, 6);   
317         get_vertex_data_xy_uv(2, 10);  
318         get_vertex_data_xy_uv(3, 14);
319   
320         render_triangle(psx_gpu, vertexes, current_command);
321         render_triangle(psx_gpu, &(vertexes[1]), current_command);
322                         break;
323       }
324   
325                 case 0x30 ... 0x33:
326       {
327         get_vertex_data_xy_rgb(0, 0);
328         get_vertex_data_xy_rgb(1, 4);
329         get_vertex_data_xy_rgb(2, 8);
330   
331         render_triangle(psx_gpu, vertexes, current_command);
332                         break;
333       }
334   
335                 case 0x34:
336                 case 0x35:
337                 case 0x36:
338                 case 0x37:
339       {
340         set_clut(psx_gpu, list_s16[5]);
341         set_texture(psx_gpu, list_s16[11]);
342   
343         get_vertex_data_xy_uv_rgb(0, 0);
344         get_vertex_data_xy_uv_rgb(1, 6);
345         get_vertex_data_xy_uv_rgb(2, 12);
346
347         render_triangle(psx_gpu, vertexes, current_command);
348                         break;
349       }
350   
351                 case 0x38:
352                 case 0x39:
353                 case 0x3A:
354                 case 0x3B:
355       {
356         get_vertex_data_xy_rgb(0, 0);
357         get_vertex_data_xy_rgb(1, 4);
358         get_vertex_data_xy_rgb(2, 8);
359         get_vertex_data_xy_rgb(3, 12);
360   
361         render_triangle(psx_gpu, vertexes, current_command);
362         render_triangle(psx_gpu, &(vertexes[1]), current_command);
363                         break;
364       }
365   
366                 case 0x3C:
367                 case 0x3D:
368                 case 0x3E:
369                 case 0x3F:
370       {
371         set_clut(psx_gpu, list_s16[5]);
372         set_texture(psx_gpu, list_s16[11]);
373   
374         get_vertex_data_xy_uv_rgb(0, 0);
375         get_vertex_data_xy_uv_rgb(1, 6);
376         get_vertex_data_xy_uv_rgb(2, 12);
377         get_vertex_data_xy_uv_rgb(3, 18);
378   
379         render_triangle(psx_gpu, vertexes, current_command);
380         render_triangle(psx_gpu, &(vertexes[1]), current_command);
381                         break;
382       }
383   
384                 case 0x40 ... 0x47:
385       {
386         vertexes[0].x = list_s16[2] + psx_gpu->offset_x;
387         vertexes[0].y = list_s16[3] + psx_gpu->offset_y;
388         vertexes[1].x = list_s16[4] + psx_gpu->offset_x;
389         vertexes[1].y = list_s16[5] + psx_gpu->offset_y;
390
391         render_line(psx_gpu, vertexes, current_command, list[0]);
392                         break;
393       }
394   
395                 case 0x48 ... 0x4F:
396       {
397         u32 num_vertexes = 1;
398         u32 *list_position = &(list[2]);
399         u32 xy = list[1];
400
401         vertexes[1].x = (xy & 0xFFFF) + psx_gpu->offset_x;
402         vertexes[1].y = (xy >> 16) + psx_gpu->offset_y;
403       
404         while(1)
405         {
406           xy = *list_position;
407
408           if((xy & 0xF000F000) == 0x50005000)
409             break;
410
411           vertexes[0] = vertexes[1];
412
413           vertexes[1].x = (xy & 0xFFFF) + psx_gpu->offset_x;
414           vertexes[1].y = (xy >> 16) + psx_gpu->offset_y;
415
416           list_position++;
417           num_vertexes++;
418
419           if(list_position > list_end)
420             break;
421
422           render_line(psx_gpu, vertexes, current_command, list[0]);
423         }
424
425         if(num_vertexes > 2)
426           command_length += (num_vertexes - 2);
427
428                         break;
429       }
430   
431                 case 0x50 ... 0x57:
432       {
433         vertexes[0].r = list[0] & 0xFF;
434         vertexes[0].g = (list[0] >> 8) & 0xFF;
435         vertexes[0].b = (list[0] >> 16) & 0xFF;
436         vertexes[0].x = list_s16[2] + psx_gpu->offset_x;
437         vertexes[0].y = list_s16[3] + psx_gpu->offset_y;
438
439         vertexes[1].r = list[2] & 0xFF;
440         vertexes[1].g = (list[2] >> 8) & 0xFF;
441         vertexes[1].b = (list[2] >> 16) & 0xFF;
442         vertexes[1].x = list_s16[6] + psx_gpu->offset_x;
443         vertexes[1].y = list_s16[7] + psx_gpu->offset_y;
444
445         render_line(psx_gpu, vertexes, current_command, 0);
446                         break;
447       }
448  
449       case 0x58 ... 0x5F:
450       {
451         u32 num_vertexes = 1;
452         u32 *list_position = &(list[2]);
453         u32 color = list[0];
454         u32 xy = list[1];
455
456         vertexes[1].r = color & 0xFF;
457         vertexes[1].g = (color >> 8) & 0xFF;
458         vertexes[1].b = (color >> 16) & 0xFF;
459         vertexes[1].x = (xy & 0xFFFF) + psx_gpu->offset_x;
460         vertexes[1].y = (xy >> 16) + psx_gpu->offset_y;
461       
462         while(1)
463         {
464           color = list_position[0];
465           if((color & 0xF000F000) == 0x50005000)
466             break;
467
468           xy = list_position[1];
469
470           vertexes[0] = vertexes[1];
471
472           vertexes[1].r = color & 0xFF;
473           vertexes[1].g = (color >> 8) & 0xFF;
474           vertexes[1].b = (color >> 16) & 0xFF;
475           vertexes[1].x = (xy & 0xFFFF) + psx_gpu->offset_x;
476           vertexes[1].y = (xy >> 16) + psx_gpu->offset_y;
477
478           list_position += 2;
479           num_vertexes++;
480
481           if(list_position > list_end)
482             break;
483
484           render_line(psx_gpu, vertexes, current_command, 0);
485         }
486
487         if(num_vertexes > 2)
488           command_length += ((num_vertexes * 2) - 2);
489
490                         break;
491       }
492   
493                 case 0x60 ... 0x63:
494       {        
495         u32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
496         u32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
497         u32 width = list_s16[4] & 0x3FF;
498         u32 height = list_s16[5] & 0x1FF;
499
500         render_sprite(psx_gpu, x, y, 0, 0, width, height, current_command, list[0]);
501                         break;
502       }
503   
504                 case 0x64 ... 0x67:
505       {        
506         u32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
507         u32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
508         u32 uv = list_s16[4];
509         u32 width = list_s16[6] & 0x3FF;
510         u32 height = list_s16[7] & 0x1FF;
511
512         set_clut(psx_gpu, list_s16[5]);
513
514         render_sprite(psx_gpu, x, y, uv & 0xFF, (uv >> 8) & 0xFF, width, height,
515          current_command, list[0]);
516                         break;
517       }
518   
519                 case 0x68:
520                 case 0x69:
521                 case 0x6A:
522                 case 0x6B:
523       {
524         s32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
525         s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
526
527         render_sprite(psx_gpu, x, y, 0, 0, 1, 1, current_command, list[0]);
528                         break;
529       }
530   
531                 case 0x70:
532                 case 0x71:
533                 case 0x72:
534                 case 0x73:
535       {        
536         s32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
537         s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
538
539         render_sprite(psx_gpu, x, y, 0, 0, 8, 8, current_command, list[0]);
540                         break;
541       }
542   
543                 case 0x74:
544                 case 0x75:
545                 case 0x76:
546                 case 0x77:
547       {        
548         s32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
549         s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
550         u32 uv = list_s16[4];
551
552         set_clut(psx_gpu, list_s16[5]);
553
554         render_sprite(psx_gpu, x, y, uv & 0xFF, (uv >> 8) & 0xFF, 8, 8,
555          current_command, list[0]);
556                         break;
557       }
558   
559                 case 0x78:
560                 case 0x79:
561                 case 0x7A:
562                 case 0x7B:
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
567         render_sprite(psx_gpu, x, y, 0, 0, 16, 16, current_command, list[0]);
568                         break;
569       }
570   
571                 case 0x7C:
572                 case 0x7D:
573                 case 0x7E:
574                 case 0x7F:
575       {        
576         s32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
577         s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
578         u32 uv = list_s16[4];
579
580         set_clut(psx_gpu, list_s16[5]);
581
582         render_sprite(psx_gpu, x, y, uv & 0xFF, (uv >> 8) & 0xFF, 16, 16,
583          current_command, list[0]);
584                         break;
585       }
586   
587                 case 0x80:          //  vid -> vid
588         render_block_move(psx_gpu, list_s16[2] & 0x3FF, list_s16[3] & 0x1FF,
589          list_s16[4] & 0x3FF, list_s16[5] & 0x1FF, list_s16[6], list_s16[7]);
590                         break;
591   
592                 case 0xA0:          //  sys -> vid
593       {
594         u32 load_x = list_s16[2] & 0x3FF;
595         u32 load_y = list_s16[3] & 0x1FF;
596         u32 load_width = list_s16[4] & 0x3FF;
597         u32 load_height = list_s16[5] & 0x1FF;
598         u32 load_size = load_width * load_height;
599   
600         command_length += load_size / 2;
601
602         if(load_size & 1)
603           command_length++;
604
605         render_block_copy(psx_gpu, (u16 *)&(list_s16[6]), load_x, load_y,
606          load_width, load_height, load_width);
607                         break;
608       }
609   
610                 case 0xC0:          //  vid -> sys
611                         break;
612   
613                 case 0xE1:
614         set_texture(psx_gpu, list[0] & 0x1FF);
615
616         if(list[0] & (1 << 9))
617           psx_gpu->render_state_base |= RENDER_STATE_DITHER;
618         else
619           psx_gpu->render_state_base &= ~RENDER_STATE_DITHER;
620
621         psx_gpu->display_area_draw_enable = (list[0] >> 10) & 0x1;
622                         break;
623   
624                 case 0xE2:
625       {
626         // TODO: Clean
627         u32 texture_window_settings = list[0];
628         u32 tmp, x, y, w, h;
629
630         if(texture_window_settings != psx_gpu->texture_window_settings)
631         {
632           tmp = (texture_window_settings & 0x1F) | 0x20;
633           for(w = 8; (tmp & 1) == 0; tmp >>= 1, w <<= 1);
634
635           tmp = ((texture_window_settings >> 5) & 0x1f) | 0x20;
636           for (h = 8; (tmp & 1) == 0; tmp >>= 1, h <<= 1);
637
638           tmp = 32 - (w >> 3);
639           x = ((texture_window_settings >> 10) & tmp) << 3;
640
641           tmp = 32 - (h >> 3);
642           y = ((texture_window_settings >> 15) & tmp) << 3;
643
644           flush_render_block_buffer(psx_gpu);
645           
646           psx_gpu->texture_window_settings = texture_window_settings;
647           psx_gpu->texture_window_x = x;
648           psx_gpu->texture_window_y = y;
649           psx_gpu->texture_mask_width = w - 1;
650           psx_gpu->texture_mask_height = h - 1;
651
652           update_texture_ptr(psx_gpu);
653         }
654         break;
655                 }
656   
657                 case 0xE3:
658         psx_gpu->viewport_start_x = list[0] & 0x3FF;
659         psx_gpu->viewport_start_y = (list[0] >> 10) & 0x1FF;
660
661 #ifdef TEXTURE_CACHE_4BPP
662         psx_gpu->viewport_mask =
663          texture_region_mask(psx_gpu->viewport_start_x,
664          psx_gpu->viewport_start_y, psx_gpu->viewport_end_x,
665          psx_gpu->viewport_end_y);
666 #endif
667                         break;
668   
669                 case 0xE4:
670         psx_gpu->viewport_end_x = list[0] & 0x3FF;
671         psx_gpu->viewport_end_y = (list[0] >> 10) & 0x1FF;
672
673 #ifdef TEXTURE_CACHE_4BPP
674         psx_gpu->viewport_mask =
675          texture_region_mask(psx_gpu->viewport_start_x,
676          psx_gpu->viewport_start_y, psx_gpu->viewport_end_x,
677          psx_gpu->viewport_end_y);
678 #endif
679                         break;
680   
681                 case 0xE5:
682       {
683         s32 offset_x = list[0] << 21;
684         s32 offset_y = list[0] << 10;
685         psx_gpu->offset_x = offset_x >> 21;
686         psx_gpu->offset_y = offset_y >> 21; 
687   
688                         break;
689                 }
690
691                 case 0xE6:
692       {
693         u32 mask_settings = list[0];
694         u16 mask_msb = mask_settings << 15;
695
696         if(list[0] & 0x2)
697           psx_gpu->render_state_base |= RENDER_STATE_MASK_EVALUATE;
698         else
699           psx_gpu->render_state_base &= ~RENDER_STATE_MASK_EVALUATE;
700
701         if(mask_msb != psx_gpu->mask_msb)
702         {
703           flush_render_block_buffer(psx_gpu);
704           psx_gpu->mask_msb = mask_msb;
705         }
706
707                         break;
708       }
709   
710                 default:
711                         break;
712         }
713   }
714 }
715