spu: fix saving bug
[pcsx_rearmed.git] / plugins / gpu_neon / psx_gpu / psx_gpu_4x.c
1 #define select_enhancement_buf_ptr(psx_gpu, x) \\r
2   ((psx_gpu)->enhancement_buf_ptr + \\r
3    ((psx_gpu)->enhancement_buf_by_x16[(x) / 16] << 20))\r
4 \r
5 #ifndef NEON_BUILD\r
6 void setup_sprite_16bpp_4x(psx_gpu_struct *psx_gpu, s32 x, s32 y, s32 u,\r
7  s32 v, s32 width, s32 height, u32 color)\r
8 {\r
9   u32 left_offset = u & 0x7;\r
10   u32 width_rounded = width + left_offset + 7;\r
11 \r
12   u16 *fb_ptr = psx_gpu->vram_out_ptr + (y * 1024) + (s32)(x - left_offset * 2);\r
13   u32 right_width = width_rounded & 0x7;\r
14   u32 block_width = width_rounded / 8;\r
15   u32 fb_ptr_pitch = (2048 + 16) - (block_width * 16);\r
16 \r
17   u32 left_mask_bits = ~(0xFFFF << (left_offset * 2));\r
18   u32 right_mask_bits = 0xFFFC << (right_width * 2);\r
19 \r
20   u32 texture_offset_base = u + (v * 1024);\r
21   u32 texture_mask =\r
22    psx_gpu->texture_mask_width | (psx_gpu->texture_mask_height * 1024);\r
23 \r
24   u32 blocks_remaining;\r
25   u32 num_blocks = psx_gpu->num_blocks;\r
26   block_struct *block = psx_gpu->blocks + num_blocks;\r
27 \r
28   u16 *texture_page_ptr = psx_gpu->texture_page_ptr;\r
29   u16 *texture_block_ptr;\r
30 \r
31   texture_offset_base &= ~0x7;\r
32 \r
33   sprites_16bpp++;\r
34 \r
35   if(block_width == 1)\r
36   {\r
37     u32 mask_bits = left_mask_bits | right_mask_bits;\r
38     u32 mask_bits_a = mask_bits & 0xFF;\r
39     u32 mask_bits_b = mask_bits >> 8;\r
40     \r
41     vec_8x16u texels;\r
42     vec_8x16u texels_wide;\r
43 \r
44     while(height)\r
45     {\r
46       num_blocks += 4;\r
47       sprite_blocks += 4;\r
48 \r
49       if(num_blocks > MAX_BLOCKS)\r
50       {\r
51         flush_render_block_buffer(psx_gpu);\r
52         num_blocks = 4;\r
53         block = psx_gpu->blocks;\r
54       }\r
55       \r
56       texture_block_ptr =\r
57        texture_page_ptr + (texture_offset_base & texture_mask);\r
58 \r
59       load_128b(texels, texture_block_ptr);\r
60       \r
61       zip_4x32b(vector_cast(vec_4x32u, texels_wide), texels.low, texels.low);\r
62       block->texels = texels_wide;\r
63       block->draw_mask_bits = mask_bits_a;\r
64       block->fb_ptr = fb_ptr;          \r
65       block++;\r
66       \r
67       block->texels = texels_wide;\r
68       block->draw_mask_bits = mask_bits_a;\r
69       block->fb_ptr = fb_ptr + 1024;          \r
70       block++;\r
71       \r
72       zip_4x32b(vector_cast(vec_4x32u, texels_wide), texels.high, texels.high);\r
73       block->texels = texels_wide;\r
74       block->draw_mask_bits = mask_bits_b;\r
75       block->fb_ptr = fb_ptr + 8;\r
76       block++;\r
77       \r
78       block->texels = texels_wide;\r
79       block->draw_mask_bits = mask_bits_b;\r
80       block->fb_ptr = fb_ptr + 8 + 1024;          \r
81       block++;      \r
82 \r
83       texture_offset_base += 1024;\r
84       fb_ptr += 2048;\r
85 \r
86       height--;\r
87       psx_gpu->num_blocks = num_blocks;\r
88     }\r
89   }\r
90   else\r
91   {\r
92     u32 texture_offset;\r
93     \r
94     u32 left_mask_bits_a = left_mask_bits & 0xFF;\r
95     u32 left_mask_bits_b = left_mask_bits >> 8;\r
96     u32 right_mask_bits_a = right_mask_bits & 0xFF;\r
97     u32 right_mask_bits_b = right_mask_bits >> 8;\r
98     \r
99     vec_8x16u texels;\r
100     vec_8x16u texels_wide;    \r
101 \r
102     while(height)\r
103     {\r
104       blocks_remaining = block_width - 2;\r
105       num_blocks += block_width * 4;\r
106       sprite_blocks += block_width * 4;\r
107 \r
108       if(num_blocks > MAX_BLOCKS)\r
109       {\r
110         flush_render_block_buffer(psx_gpu);\r
111         num_blocks = block_width * 4;\r
112         block = psx_gpu->blocks;\r
113       }\r
114 \r
115       texture_offset = texture_offset_base;\r
116       texture_offset_base += 1024;\r
117 \r
118       texture_block_ptr = texture_page_ptr + (texture_offset & texture_mask);\r
119       \r
120       load_128b(texels, texture_block_ptr);\r
121 \r
122       zip_4x32b(vector_cast(vec_4x32u, texels_wide), texels.low, texels.low);\r
123       block->texels = texels_wide;\r
124       block->draw_mask_bits = left_mask_bits_a;\r
125       block->fb_ptr = fb_ptr;\r
126       block++;\r
127       \r
128       block->texels = texels_wide;\r
129       block->draw_mask_bits = left_mask_bits_a;\r
130       block->fb_ptr = fb_ptr + 1024;\r
131       block++;      \r
132 \r
133       zip_4x32b(vector_cast(vec_4x32u, texels_wide), texels.high, texels.high);\r
134       block->texels = texels_wide;\r
135       block->draw_mask_bits = left_mask_bits_b;\r
136       block->fb_ptr = fb_ptr + 8;\r
137       block++;  \r
138       \r
139       block->texels = texels_wide;\r
140       block->draw_mask_bits = left_mask_bits_b;\r
141       block->fb_ptr = fb_ptr + 8 + 1024;\r
142       block++;  \r
143       \r
144       texture_offset += 8;\r
145       fb_ptr += 16;\r
146 \r
147       while(blocks_remaining)\r
148       {\r
149         texture_block_ptr = texture_page_ptr + (texture_offset & texture_mask);\r
150         load_128b(texels, texture_block_ptr);\r
151 \r
152         zip_4x32b(vector_cast(vec_4x32u, texels_wide), texels.low, texels.low);\r
153         block->texels = texels_wide;\r
154         block->draw_mask_bits = 0;\r
155         block->fb_ptr = fb_ptr;\r
156         block++;\r
157         \r
158         block->texels = texels_wide;\r
159         block->draw_mask_bits = 0;\r
160         block->fb_ptr = fb_ptr + 1024;\r
161         block++;      \r
162 \r
163         zip_4x32b(vector_cast(vec_4x32u, texels_wide), texels.high, texels.high);\r
164         block->texels = texels_wide;\r
165         block->draw_mask_bits = 0;\r
166         block->fb_ptr = fb_ptr + 8;\r
167         block++;\r
168         \r
169         block->texels = texels_wide;\r
170         block->draw_mask_bits = 0;\r
171         block->fb_ptr = fb_ptr + 8 + 1024;\r
172         block++;\r
173         \r
174         texture_offset += 8;\r
175         fb_ptr += 16;\r
176 \r
177         blocks_remaining--;\r
178       }\r
179 \r
180       texture_block_ptr = texture_page_ptr + (texture_offset & texture_mask);\r
181       load_128b(texels, texture_block_ptr);\r
182       \r
183       zip_4x32b(vector_cast(vec_4x32u, texels_wide), texels.low, texels.low);\r
184       block->texels = texels_wide;\r
185       block->draw_mask_bits = right_mask_bits_a;\r
186       block->fb_ptr = fb_ptr;\r
187       block++;\r
188       \r
189       block->texels = texels_wide;\r
190       block->draw_mask_bits = right_mask_bits_a;\r
191       block->fb_ptr = fb_ptr + 1024;\r
192       block++;      \r
193 \r
194       zip_4x32b(vector_cast(vec_4x32u, texels_wide), texels.high, texels.high);\r
195       block->texels = texels_wide;\r
196       block->draw_mask_bits = right_mask_bits_b;\r
197       block->fb_ptr = fb_ptr + 8;\r
198       block++;\r
199 \r
200       block->texels = texels_wide;\r
201       block->draw_mask_bits = right_mask_bits_b;\r
202       block->fb_ptr = fb_ptr + 8 + 1024;      \r
203       block++;\r
204 \r
205       fb_ptr += fb_ptr_pitch;\r
206 \r
207       height--;\r
208       psx_gpu->num_blocks = num_blocks;\r
209     }\r
210   }\r
211 }\r
212 \r
213 #endif\r
214 \r
215 static void setup_sprite_untextured_4x(psx_gpu_struct *psx_gpu, s32 x, s32 y,\r
216  s32 u, s32 v, s32 width, s32 height, u32 color)\r
217 {\r
218   setup_sprite_untextured(psx_gpu, x, y, u, v, width * 2, height * 2, color);\r
219 }\r
220 \r
221 #define setup_sprite_blocks_switch_textured_4x(texture_mode)                   \\r
222   setup_sprite_##texture_mode##_4x                                             \\r
223 \r
224 #define setup_sprite_blocks_switch_untextured_4x(texture_mode)                 \\r
225   setup_sprite_untextured_4x                                                   \\r
226 \r
227 #define setup_sprite_blocks_switch_4x(texturing, texture_mode)                 \\r
228   setup_sprite_blocks_switch_##texturing##_4x(texture_mode)                    \\r
229 \r
230   \r
231 #define render_sprite_blocks_switch_block_modulation_4x(texture_mode,          \\r
232  blend_mode, mask_evaluate, shading, dithering, texturing, blending,           \\r
233  modulation)                                                                   \\r
234 {                                                                              \\r
235   setup_sprite_blocks_switch_4x(texturing, texture_mode),                      \\r
236   texture_sprite_blocks_switch_##texturing(texture_mode),                      \\r
237   shade_blocks_switch(unshaded, texturing, modulation, undithered, blending,   \\r
238    mask_evaluate),                                                             \\r
239   blend_blocks_switch(texturing, blending, blend_mode, mask_evaluate)          \\r
240 }                                                                              \\r
241 \r
242 #define render_sprite_blocks_switch_block_blending_4x(texture_mode,            \\r
243  blend_mode, mask_evaluate, shading, dithering, texturing, blending)           \\r
244   render_sprite_blocks_switch_block_modulation_4x(texture_mode, blend_mode,    \\r
245    mask_evaluate, shading, dithering, texturing, blending, modulated),         \\r
246   render_sprite_blocks_switch_block_modulation_4x(texture_mode, blend_mode,    \\r
247    mask_evaluate, shading, dithering, texturing, blending, unmodulated)        \\r
248 \r
249 #define render_sprite_blocks_switch_block_texturing_4x(texture_mode,           \\r
250  blend_mode, mask_evaluate, shading, dithering, texturing)                     \\r
251   render_sprite_blocks_switch_block_blending_4x(texture_mode, blend_mode,      \\r
252    mask_evaluate, shading, dithering, texturing, unblended),                   \\r
253   render_sprite_blocks_switch_block_blending_4x(texture_mode, blend_mode,      \\r
254    mask_evaluate, shading, dithering, texturing, blended)                      \\r
255 \r
256 #define render_sprite_blocks_switch_block_dithering_4x(texture_mode,           \\r
257  blend_mode, mask_evaluate, shading, dithering)                                \\r
258   render_sprite_blocks_switch_block_texturing_4x(texture_mode, blend_mode,     \\r
259    mask_evaluate, shading, dithering, untextured),                             \\r
260   render_sprite_blocks_switch_block_texturing_4x(texture_mode, blend_mode,     \\r
261    mask_evaluate, shading, dithering, textured)                                \\r
262 \r
263 #define render_sprite_blocks_switch_block_shading_4x(texture_mode, blend_mode, \\r
264  mask_evaluate, shading)                                                       \\r
265   render_sprite_blocks_switch_block_dithering_4x(texture_mode, blend_mode,     \\r
266    mask_evaluate, shading, undithered),                                        \\r
267   render_sprite_blocks_switch_block_dithering_4x(texture_mode, blend_mode,     \\r
268    mask_evaluate, shading, dithered)                                           \\r
269 \r
270 #define render_sprite_blocks_switch_block_mask_evaluate_4x(texture_mode,       \\r
271  blend_mode, mask_evaluate)                                                    \\r
272   render_sprite_blocks_switch_block_shading_4x(texture_mode, blend_mode,       \\r
273    mask_evaluate, unshaded),                                                   \\r
274   render_sprite_blocks_switch_block_shading_4x(texture_mode, blend_mode,       \\r
275    mask_evaluate, shaded)                                                      \\r
276 \r
277 #define render_sprite_blocks_switch_block_blend_mode_4x(texture_mode,          \\r
278  blend_mode)                                                                   \\r
279   render_sprite_blocks_switch_block_mask_evaluate_4x(texture_mode, blend_mode, \\r
280    off),                                                                       \\r
281   render_sprite_blocks_switch_block_mask_evaluate_4x(texture_mode, blend_mode, \\r
282    on)                                                                         \\r
283 \r
284 #define render_sprite_blocks_switch_block_texture_mode_4x(texture_mode)        \\r
285   render_sprite_blocks_switch_block_blend_mode_4x(texture_mode, average),      \\r
286   render_sprite_blocks_switch_block_blend_mode_4x(texture_mode, add),          \\r
287   render_sprite_blocks_switch_block_blend_mode_4x(texture_mode, subtract),     \\r
288   render_sprite_blocks_switch_block_blend_mode_4x(texture_mode, add_fourth)    \\r
289 \r
290 #define render_sprite_blocks_switch_block_4x()                                 \\r
291   render_sprite_blocks_switch_block_texture_mode_4x(4bpp),                     \\r
292   render_sprite_blocks_switch_block_texture_mode_4x(8bpp),                     \\r
293   render_sprite_blocks_switch_block_texture_mode_4x(16bpp),                    \\r
294   render_sprite_blocks_switch_block_texture_mode_4x(4bpp)                      \\r
295 \r
296 \r
297 render_block_handler_struct render_sprite_block_handlers_4x[] =\r
298 {\r
299   render_sprite_blocks_switch_block_4x()\r
300 };\r
301 \r
302 \r
303 void render_sprite_4x(psx_gpu_struct *psx_gpu, s32 x, s32 y, u32 u, u32 v,\r
304  s32 width, s32 height, u32 flags, u32 color)\r
305 {\r
306   s32 x_right = x + width - 1;\r
307   s32 y_bottom = y + height - 1;\r
308 \r
309 #ifdef PROFILE\r
310   sprites++;\r
311 #endif\r
312 \r
313   if(x < psx_gpu->viewport_start_x)\r
314   {\r
315     u32 clip = psx_gpu->viewport_start_x - x;\r
316     x += clip;\r
317     u += clip;\r
318     width -= clip;\r
319   }\r
320 \r
321   if(y < psx_gpu->viewport_start_y)\r
322   {\r
323     s32 clip = psx_gpu->viewport_start_y - y;\r
324     y += clip;\r
325     v += clip;\r
326     height -= clip;\r
327   }\r
328 \r
329   if(x_right > psx_gpu->viewport_end_x)\r
330     width -= x_right - psx_gpu->viewport_end_x;\r
331 \r
332   if(y_bottom > psx_gpu->viewport_end_y)\r
333     height -= y_bottom - psx_gpu->viewport_end_y;\r
334 \r
335   if((width <= 0) || (height <= 0))\r
336     return;\r
337 \r
338   psx_gpu->vram_out_ptr = select_enhancement_buf_ptr(psx_gpu, x);\r
339 \r
340   x *= 2;\r
341   y *= 2;\r
342 \r
343 #ifdef PROFILE\r
344   span_pixels += width * height;\r
345   spans += height;\r
346 #endif\r
347 \r
348   u32 render_state = flags &\r
349    (RENDER_FLAGS_MODULATE_TEXELS | RENDER_FLAGS_BLEND |\r
350    RENDER_FLAGS_TEXTURE_MAP);\r
351   render_state |=\r
352    (psx_gpu->render_state_base & ~RENDER_STATE_DITHER);\r
353 \r
354   if((psx_gpu->render_state != render_state) ||\r
355    (psx_gpu->primitive_type != PRIMITIVE_TYPE_SPRITE))\r
356   {\r
357     psx_gpu->render_state = render_state;\r
358     flush_render_block_buffer(psx_gpu);\r
359 #ifdef PROFILE\r
360     state_changes++;\r
361 #endif\r
362   }\r
363 \r
364   psx_gpu->primitive_type = PRIMITIVE_TYPE_SPRITE;\r
365 \r
366   color &= 0xFFFFFF;\r
367 \r
368   if(psx_gpu->triangle_color != color)\r
369   {\r
370     flush_render_block_buffer(psx_gpu);\r
371     psx_gpu->triangle_color = color;\r
372   }\r
373 \r
374   if(color == 0x808080)\r
375     render_state |= RENDER_FLAGS_MODULATE_TEXELS;\r
376 \r
377   render_block_handler_struct *render_block_handler =\r
378    &(render_sprite_block_handlers_4x[render_state]);\r
379   psx_gpu->render_block_handler = render_block_handler;\r
380 \r
381   ((setup_sprite_function_type *)render_block_handler->setup_blocks)\r
382    (psx_gpu, x, y, u, v, width, height, color);\r
383 }\r
384 \r