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