gpulib: eliminate list scan-ahead
[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 #define sign_extend_12bit(value)                                               \
156   (((s32)((value) << 20)) >> 20)                                               \
157
158 #define sign_extend_11bit(value)                                               \
159   (((s32)((value) << 21)) >> 21)                                               \
160
161 #define sign_extend_10bit(value)                                               \
162   (((s32)((value) << 22)) >> 22)                                               \
163
164
165 #define get_vertex_data_xy(vertex_number, offset16)                            \
166   vertexes[vertex_number].x =                                                  \
167    sign_extend_12bit(list_s16[offset16]) + psx_gpu->offset_x;                  \
168   vertexes[vertex_number].y =                                                  \
169    sign_extend_12bit(list_s16[(offset16) + 1]) + psx_gpu->offset_y;            \
170
171 #define get_vertex_data_uv(vertex_number, offset16)                            \
172   vertexes[vertex_number].u = list_s16[offset16] & 0xFF;                       \
173   vertexes[vertex_number].v = (list_s16[offset16] >> 8) & 0xFF                 \
174
175 #define get_vertex_data_rgb(vertex_number, offset32)                           \
176   vertexes[vertex_number].r = list[offset32] & 0xFF;                           \
177   vertexes[vertex_number].g = (list[offset32] >> 8) & 0xFF;                    \
178   vertexes[vertex_number].b = (list[offset32] >> 16) & 0xFF                    \
179
180 #define get_vertex_data_xy_uv(vertex_number, offset16)                         \
181   get_vertex_data_xy(vertex_number, offset16);                                 \
182   get_vertex_data_uv(vertex_number, (offset16) + 2)                            \
183
184 #define get_vertex_data_xy_rgb(vertex_number, offset16)                        \
185   get_vertex_data_rgb(vertex_number, (offset16) / 2);                          \
186   get_vertex_data_xy(vertex_number, (offset16) + 2);                           \
187
188 #define get_vertex_data_xy_uv_rgb(vertex_number, offset16)                     \
189   get_vertex_data_rgb(vertex_number, (offset16) / 2);                          \
190   get_vertex_data_xy(vertex_number, (offset16) + 2);                           \
191   get_vertex_data_uv(vertex_number, (offset16) + 4);                           \
192
193 #define set_vertex_color_constant(vertex_number, color)                        \
194   vertexes[vertex_number].r = color & 0xFF;                                    \
195   vertexes[vertex_number].g = (color >> 8) & 0xFF;                             \
196   vertexes[vertex_number].b = (color >> 16) & 0xFF                             \
197
198 #define get_vertex_data_xy_rgb_constant(vertex_number, offset16, color)        \
199   get_vertex_data_xy(vertex_number, offset16);                                 \
200   set_vertex_color_constant(vertex_number, color)                              \
201
202 #ifndef SET_Ex
203 #define SET_Ex(r, v)
204 #endif
205
206 vertex_struct vertexes[4] __attribute__((aligned(32)));
207
208 u32 gpu_parse(psx_gpu_struct *psx_gpu, u32 *list, u32 size, u32 *last_command)
209 {
210   u32 current_command = 0, command_length;
211
212   u32 *list_start = list;
213   u32 *list_end = list + (size / 4);
214
215   for(; list < list_end; list += 1 + command_length)
216   {
217         s16 *list_s16 = (void *)list;
218         current_command = *list >> 24;
219         command_length = command_lengths[current_command];
220         if (list + 1 + command_length > list_end) {
221           current_command = (u32)-1;
222           break;
223         }
224
225         switch(current_command)
226         {
227                 case 0x00:
228                         break;
229   
230                 case 0x02:
231       {
232         u32 x = list_s16[2] & 0x3FF;
233         u32 y = list_s16[3] & 0x1FF;
234         u32 width = list_s16[4] & 0x3FF;
235         u32 height = list_s16[5] & 0x1FF;
236         u32 color = list[0] & 0xFFFFFF;
237
238         x &= ~0xF;
239         width = ((width + 0xF) & ~0xF);
240
241         if((x + width) > 1024)
242         {
243           u32 width_a = 1024 - x;
244           u32 width_b = width - width_a;
245
246           if((y + height) > 512)
247           {
248             u32 height_a = 512 - y;
249             u32 height_b = height - height_a;
250
251             render_block_fill(psx_gpu, color, x, y, width_a, height_a);
252             render_block_fill(psx_gpu, color, 0, y, width_b, height_a);
253             render_block_fill(psx_gpu, color, x, 0, width_a, height_b);
254             render_block_fill(psx_gpu, color, 0, 0, width_b, height_b);
255           }
256           else
257           {
258             render_block_fill(psx_gpu, color, x, y, width_a, height);
259             render_block_fill(psx_gpu, color, 0, y, width_b, height);
260           }
261         }
262         else
263         {
264           if((y + height) > 512)
265           {
266             u32 height_a = 512 - y;
267             u32 height_b = height - height_a;
268
269             render_block_fill(psx_gpu, color, x, y, width, height_a);
270             render_block_fill(psx_gpu, color, x, 0, width, height_b);
271           }
272           else
273           {
274             render_block_fill(psx_gpu, color, x, y, width, height);
275           }
276         }
277                         break;
278       }
279   
280                 case 0x20 ... 0x23:
281       {
282         set_triangle_color(psx_gpu, list[0] & 0xFFFFFF);
283   
284         get_vertex_data_xy(0, 2);
285         get_vertex_data_xy(1, 4);
286         get_vertex_data_xy(2, 6);
287           
288         render_triangle(psx_gpu, vertexes, current_command);
289                         break;
290       }
291   
292                 case 0x24 ... 0x27:
293       {
294         set_clut(psx_gpu, list_s16[5]);
295         set_texture(psx_gpu, list_s16[9]);
296         set_triangle_color(psx_gpu, list[0] & 0xFFFFFF);
297   
298         get_vertex_data_xy_uv(0, 2);
299         get_vertex_data_xy_uv(1, 6);
300         get_vertex_data_xy_uv(2, 10);
301   
302         render_triangle(psx_gpu, vertexes, current_command);
303                         break;
304       }
305   
306                 case 0x28 ... 0x2B:
307       {
308         set_triangle_color(psx_gpu, list[0] & 0xFFFFFF);
309   
310         get_vertex_data_xy(0, 2);
311         get_vertex_data_xy(1, 4);
312         get_vertex_data_xy(2, 6);
313         get_vertex_data_xy(3, 8);
314   
315         render_triangle(psx_gpu, vertexes, current_command);
316         render_triangle(psx_gpu, &(vertexes[1]), current_command);
317                         break;
318       }
319   
320                 case 0x2C ... 0x2F:
321       {
322         set_clut(psx_gpu, list_s16[5]);
323         set_texture(psx_gpu, list_s16[9]);
324         set_triangle_color(psx_gpu, list[0] & 0xFFFFFF);
325   
326         get_vertex_data_xy_uv(0, 2);   
327         get_vertex_data_xy_uv(1, 6);   
328         get_vertex_data_xy_uv(2, 10);  
329         get_vertex_data_xy_uv(3, 14);
330   
331         render_triangle(psx_gpu, vertexes, current_command);
332         render_triangle(psx_gpu, &(vertexes[1]), current_command);
333                         break;
334       }
335   
336                 case 0x30 ... 0x33:
337       {
338         get_vertex_data_xy_rgb(0, 0);
339         get_vertex_data_xy_rgb(1, 4);
340         get_vertex_data_xy_rgb(2, 8);
341   
342         render_triangle(psx_gpu, vertexes, current_command);
343                         break;
344       }
345   
346                 case 0x34:
347                 case 0x35:
348                 case 0x36:
349                 case 0x37:
350       {
351         set_clut(psx_gpu, list_s16[5]);
352         set_texture(psx_gpu, list_s16[11]);
353   
354         get_vertex_data_xy_uv_rgb(0, 0);
355         get_vertex_data_xy_uv_rgb(1, 6);
356         get_vertex_data_xy_uv_rgb(2, 12);
357
358         render_triangle(psx_gpu, vertexes, current_command);
359                         break;
360       }
361   
362                 case 0x38:
363                 case 0x39:
364                 case 0x3A:
365                 case 0x3B:
366       {
367         get_vertex_data_xy_rgb(0, 0);
368         get_vertex_data_xy_rgb(1, 4);
369         get_vertex_data_xy_rgb(2, 8);
370         get_vertex_data_xy_rgb(3, 12);
371   
372         render_triangle(psx_gpu, vertexes, current_command);
373         render_triangle(psx_gpu, &(vertexes[1]), current_command);
374                         break;
375       }
376   
377                 case 0x3C:
378                 case 0x3D:
379                 case 0x3E:
380                 case 0x3F:
381       {
382         set_clut(psx_gpu, list_s16[5]);
383         set_texture(psx_gpu, list_s16[11]);
384   
385         get_vertex_data_xy_uv_rgb(0, 0);
386         get_vertex_data_xy_uv_rgb(1, 6);
387         get_vertex_data_xy_uv_rgb(2, 12);
388         get_vertex_data_xy_uv_rgb(3, 18);
389   
390         render_triangle(psx_gpu, vertexes, current_command);
391         render_triangle(psx_gpu, &(vertexes[1]), current_command);
392                         break;
393       }
394   
395                 case 0x40 ... 0x47:
396       {
397         vertexes[0].x = list_s16[2] + psx_gpu->offset_x;
398         vertexes[0].y = list_s16[3] + psx_gpu->offset_y;
399         vertexes[1].x = list_s16[4] + psx_gpu->offset_x;
400         vertexes[1].y = list_s16[5] + psx_gpu->offset_y;
401
402         render_line(psx_gpu, vertexes, current_command, list[0]);
403                         break;
404       }
405   
406                 case 0x48 ... 0x4F:
407       {
408         u32 num_vertexes = 1;
409         u32 *list_position = &(list[2]);
410         u32 xy = list[1];
411
412         vertexes[1].x = (xy & 0xFFFF) + psx_gpu->offset_x;
413         vertexes[1].y = (xy >> 16) + psx_gpu->offset_y;
414       
415         while(1)
416         {
417           xy = *list_position;
418
419           if((xy & 0xF000F000) == 0x50005000)
420             break;
421
422           vertexes[0] = vertexes[1];
423
424           vertexes[1].x = (xy & 0xFFFF) + psx_gpu->offset_x;
425           vertexes[1].y = (xy >> 16) + psx_gpu->offset_y;
426
427           list_position++;
428           num_vertexes++;
429
430           if(list_position > list_end)
431             break;
432
433           render_line(psx_gpu, vertexes, current_command, list[0]);
434         }
435
436         if(num_vertexes > 2)
437           command_length += (num_vertexes - 2);
438
439                         break;
440       }
441   
442                 case 0x50 ... 0x57:
443       {
444         vertexes[0].r = list[0] & 0xFF;
445         vertexes[0].g = (list[0] >> 8) & 0xFF;
446         vertexes[0].b = (list[0] >> 16) & 0xFF;
447         vertexes[0].x = list_s16[2] + psx_gpu->offset_x;
448         vertexes[0].y = list_s16[3] + psx_gpu->offset_y;
449
450         vertexes[1].r = list[2] & 0xFF;
451         vertexes[1].g = (list[2] >> 8) & 0xFF;
452         vertexes[1].b = (list[2] >> 16) & 0xFF;
453         vertexes[1].x = list_s16[6] + psx_gpu->offset_x;
454         vertexes[1].y = list_s16[7] + psx_gpu->offset_y;
455
456         render_line(psx_gpu, vertexes, current_command, 0);
457                         break;
458       }
459  
460       case 0x58 ... 0x5F:
461       {
462         u32 num_vertexes = 1;
463         u32 *list_position = &(list[2]);
464         u32 color = list[0];
465         u32 xy = list[1];
466
467         vertexes[1].r = color & 0xFF;
468         vertexes[1].g = (color >> 8) & 0xFF;
469         vertexes[1].b = (color >> 16) & 0xFF;
470         vertexes[1].x = (xy & 0xFFFF) + psx_gpu->offset_x;
471         vertexes[1].y = (xy >> 16) + psx_gpu->offset_y;
472       
473         while(1)
474         {
475           color = list_position[0];
476           if((color & 0xF000F000) == 0x50005000)
477             break;
478
479           xy = list_position[1];
480
481           vertexes[0] = vertexes[1];
482
483           vertexes[1].r = color & 0xFF;
484           vertexes[1].g = (color >> 8) & 0xFF;
485           vertexes[1].b = (color >> 16) & 0xFF;
486           vertexes[1].x = (xy & 0xFFFF) + psx_gpu->offset_x;
487           vertexes[1].y = (xy >> 16) + psx_gpu->offset_y;
488
489           list_position += 2;
490           num_vertexes++;
491
492           if(list_position > list_end)
493             break;
494
495           render_line(psx_gpu, vertexes, current_command, 0);
496         }
497
498         if(num_vertexes > 2)
499           command_length += ((num_vertexes * 2) - 2);
500
501                         break;
502       }
503   
504                 case 0x60 ... 0x63:
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 width = list_s16[4] & 0x3FF;
509         u32 height = list_s16[5] & 0x1FF;
510
511         render_sprite(psx_gpu, x, y, 0, 0, width, height, current_command, list[0]);
512                         break;
513       }
514   
515                 case 0x64 ... 0x67:
516       {        
517         u32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
518         u32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
519         u32 uv = list_s16[4];
520         u32 width = list_s16[6] & 0x3FF;
521         u32 height = list_s16[7] & 0x1FF;
522
523         set_clut(psx_gpu, list_s16[5]);
524
525         render_sprite(psx_gpu, x, y, uv & 0xFF, (uv >> 8) & 0xFF, width, height,
526          current_command, list[0]);
527                         break;
528       }
529   
530                 case 0x68:
531                 case 0x69:
532                 case 0x6A:
533                 case 0x6B:
534       {
535         s32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
536         s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
537
538         render_sprite(psx_gpu, x, y, 0, 0, 1, 1, current_command, list[0]);
539                         break;
540       }
541   
542                 case 0x70:
543                 case 0x71:
544                 case 0x72:
545                 case 0x73:
546       {        
547         s32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
548         s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
549
550         render_sprite(psx_gpu, x, y, 0, 0, 8, 8, current_command, list[0]);
551                         break;
552       }
553   
554                 case 0x74:
555                 case 0x75:
556                 case 0x76:
557                 case 0x77:
558       {        
559         s32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
560         s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
561         u32 uv = list_s16[4];
562
563         set_clut(psx_gpu, list_s16[5]);
564
565         render_sprite(psx_gpu, x, y, uv & 0xFF, (uv >> 8) & 0xFF, 8, 8,
566          current_command, list[0]);
567                         break;
568       }
569   
570                 case 0x78:
571                 case 0x79:
572                 case 0x7A:
573                 case 0x7B:
574       {        
575         s32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
576         s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
577
578         render_sprite(psx_gpu, x, y, 0, 0, 16, 16, current_command, list[0]);
579                         break;
580       }
581   
582                 case 0x7C:
583                 case 0x7D:
584                 case 0x7E:
585                 case 0x7F:
586       {        
587         s32 x = sign_extend_11bit(list_s16[2] + psx_gpu->offset_x);
588         s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
589         u32 uv = list_s16[4];
590
591         set_clut(psx_gpu, list_s16[5]);
592
593         render_sprite(psx_gpu, x, y, uv & 0xFF, (uv >> 8) & 0xFF, 16, 16,
594          current_command, list[0]);
595                         break;
596       }
597   
598                 case 0x80:          //  vid -> vid
599         render_block_move(psx_gpu, list_s16[2] & 0x3FF, list_s16[3] & 0x1FF,
600          list_s16[4] & 0x3FF, list_s16[5] & 0x1FF, list_s16[6], list_s16[7]);
601                         break;
602  
603 #ifdef PCSX
604                 case 0xA0:          //  sys -> vid
605                 case 0xC0:          //  vid -> sys
606                         goto breakloop;
607 #else
608                 case 0xA0:          //  sys -> vid
609       {
610         u32 load_x = list_s16[2] & 0x3FF;
611         u32 load_y = list_s16[3] & 0x1FF;
612         u32 load_width = list_s16[4] & 0x3FF;
613         u32 load_height = list_s16[5] & 0x1FF;
614         u32 load_size = load_width * load_height;
615   
616         command_length += load_size / 2;
617
618         if(load_size & 1)
619           command_length++;
620
621         render_block_copy(psx_gpu, (u16 *)&(list_s16[6]), load_x, load_y,
622          load_width, load_height, load_width);
623                         break;
624       }
625
626                 case 0xC0:          //  vid -> sys
627                         break;
628 #endif
629
630                 case 0xE1:
631         set_texture(psx_gpu, list[0] & 0x1FF);
632
633         if(list[0] & (1 << 9))
634           psx_gpu->render_state_base |= RENDER_STATE_DITHER;
635         else
636           psx_gpu->render_state_base &= ~RENDER_STATE_DITHER;
637
638         psx_gpu->display_area_draw_enable = (list[0] >> 10) & 0x1;
639                         SET_Ex(1, list[0]);
640                         break;
641   
642                 case 0xE2:
643       {
644         // TODO: Clean
645         u32 texture_window_settings = list[0];
646         u32 tmp, x, y, w, h;
647
648         if(texture_window_settings != psx_gpu->texture_window_settings)
649         {
650           tmp = (texture_window_settings & 0x1F) | 0x20;
651           for(w = 8; (tmp & 1) == 0; tmp >>= 1, w <<= 1);
652
653           tmp = ((texture_window_settings >> 5) & 0x1f) | 0x20;
654           for (h = 8; (tmp & 1) == 0; tmp >>= 1, h <<= 1);
655
656           tmp = 32 - (w >> 3);
657           x = ((texture_window_settings >> 10) & tmp) << 3;
658
659           tmp = 32 - (h >> 3);
660           y = ((texture_window_settings >> 15) & tmp) << 3;
661
662           flush_render_block_buffer(psx_gpu);
663           
664           psx_gpu->texture_window_settings = texture_window_settings;
665           psx_gpu->texture_window_x = x;
666           psx_gpu->texture_window_y = y;
667           psx_gpu->texture_mask_width = w - 1;
668           psx_gpu->texture_mask_height = h - 1;
669
670           update_texture_ptr(psx_gpu);
671         }
672         SET_Ex(2, list[0]);
673         break;
674                 }
675   
676                 case 0xE3:
677         psx_gpu->viewport_start_x = list[0] & 0x3FF;
678         psx_gpu->viewport_start_y = (list[0] >> 10) & 0x1FF;
679
680 #ifdef TEXTURE_CACHE_4BPP
681         psx_gpu->viewport_mask =
682          texture_region_mask(psx_gpu->viewport_start_x,
683          psx_gpu->viewport_start_y, psx_gpu->viewport_end_x,
684          psx_gpu->viewport_end_y);
685 #endif
686                         SET_Ex(3, list[0]);
687                         break;
688   
689                 case 0xE4:
690         psx_gpu->viewport_end_x = list[0] & 0x3FF;
691         psx_gpu->viewport_end_y = (list[0] >> 10) & 0x1FF;
692
693 #ifdef TEXTURE_CACHE_4BPP
694         psx_gpu->viewport_mask =
695          texture_region_mask(psx_gpu->viewport_start_x,
696          psx_gpu->viewport_start_y, psx_gpu->viewport_end_x,
697          psx_gpu->viewport_end_y);
698 #endif
699                         SET_Ex(4, list[0]);
700                         break;
701   
702                 case 0xE5:
703       {
704         s32 offset_x = list[0] << 21;
705         s32 offset_y = list[0] << 10;
706         psx_gpu->offset_x = offset_x >> 21;
707         psx_gpu->offset_y = offset_y >> 21; 
708   
709                         SET_Ex(5, list[0]);
710                         break;
711                 }
712
713                 case 0xE6:
714       {
715         u32 mask_settings = list[0];
716         u16 mask_msb = mask_settings << 15;
717
718         if(list[0] & 0x2)
719           psx_gpu->render_state_base |= RENDER_STATE_MASK_EVALUATE;
720         else
721           psx_gpu->render_state_base &= ~RENDER_STATE_MASK_EVALUATE;
722
723         if(mask_msb != psx_gpu->mask_msb)
724         {
725           flush_render_block_buffer(psx_gpu);
726           psx_gpu->mask_msb = mask_msb;
727         }
728
729                         SET_Ex(6, list[0]);
730                         break;
731       }
732   
733                 default:
734                         break;
735         }
736   }
737
738 #ifdef PCSX
739 breakloop:
740 #endif
741   if (last_command != NULL)
742     *last_command = current_command;
743   return list - list_start;
744 }
745