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