+ ldr column_data, [sp], #8; /* fb_ptr2 */ \
+ add texture_offset, texture_offset, #0xF00; \
+ strh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ] \
+
+
+#define setup_sprite_tile_half_4bpp_4x(edge) \
+ setup_sprite_tile_add_blocks(single_4x); \
+ str column_data, [sp, #-8]!; /* fb_ptr2 */ \
+ \
+ 4: \
+ and texture_block_ptr, texture_offset, texture_mask; \
+ pld [ fb_ptr ]; \
+ \
+ add texture_block_ptr, texture_page_ptr, texture_block_ptr; \
+ vld1.u32 { texels }, [ texture_block_ptr, :64 ]; \
+ \
+ add texture_block_ptr, texture_page_ptr, texture_block_ptr; \
+ vtbl.8 texels_low, { clut_low_a, clut_low_b }, texels; \
+ \
+ vtbl.8 texels_high, { clut_high_a, clut_high_b }, texels; \
+ add texture_offset, texture_offset, #0x10; \
+ \
+ vzip.8 texels_low, texels_high; \
+ do_texture_block_16bpp_4x(fb_ptr2, draw_mask_fb_ptr_##edge##_a, \
+ draw_mask_fb_ptr_##edge##_b); \
+ \
+ pld [ fb_ptr, #2048 ]; \
+ add fb_ptr, fb_ptr, #2048 * 2; \
+ \
+ subs sub_tile_height, sub_tile_height, #1; \
+ bne 4b; \
+ \
+ ldr column_data, [sp], #8; /* fb_ptr2 */ \
+ add texture_offset, texture_offset, #0xF00; \
+ strh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ] \
+
+
+#define setup_sprite_tile_full_8bpp_4x(edge) \
+ setup_sprite_tile_add_blocks(double_4x); \
+ add block, block, #16; \
+ str column_data, [sp, #-8]!; /* fb_ptr2 */ \
+ \
+ 4: \
+ and texture_block_ptr, texture_offset, texture_mask; \
+ pld [ fb_ptr ]; \
+ \
+ add texture_block_ptr, texture_page_ptr, texture_block_ptr; \
+ vld1.u32 { texels }, [ texture_block_ptr, :64 ]; \
+ \
+ add texture_block_ptr, texture_offset, #8; \
+ do_texture_block_8bpp_4x(fb_ptr2, draw_mask_fb_ptr_left_a, \
+ draw_mask_fb_ptr_left_b); \
+ \
+ pld [ fb_ptr, #2048 ]; \
+ and texture_block_ptr, texture_block_ptr, texture_mask; \
+ \
+ add fb_ptr, fb_ptr, #16*2; \
+ add texture_block_ptr, texture_page_ptr, texture_block_ptr; \
+ \
+ vld1.u32 { texels }, [ texture_block_ptr, :64 ]; \
+ \
+ do_texture_block_8bpp_4x(fb_ptr2, draw_mask_fb_ptr_right_a, \
+ draw_mask_fb_ptr_right_b); \
+ \
+ add texture_offset, texture_offset, #0x10; \
+ add fb_ptr, fb_ptr, #(2048 - 16) * 2; \
+ \
+ subs sub_tile_height, sub_tile_height, #1; \
+ bne 4b; \
+ \
+ sub block, block, #16; \
+ ldr column_data, [sp], #8; /* fb_ptr2 */ \
+ add texture_offset, texture_offset, #0xF00; \
+ strh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ] \
+
+
+#define setup_sprite_tile_half_8bpp_4x(edge) \
+ setup_sprite_tile_add_blocks(single_4x); \
+ add block, block, #16; \
+ str column_data, [sp, #-8]!; /* fb_ptr2 */ \
+ \
+ 4: \
+ and texture_block_ptr, texture_offset, texture_mask; \
+ pld [ fb_ptr ]; \
+ \
+ add texture_block_ptr, texture_page_ptr, texture_block_ptr; \
+ vld1.u32 { texels }, [ texture_block_ptr, :64 ]; \
+ \
+ pld [ fb_ptr, #2048 ]; \
+ do_texture_block_8bpp_4x(fb_ptr2, draw_mask_fb_ptr_##edge##_a, \
+ draw_mask_fb_ptr_##edge##_b); \
+ \
+ add texture_offset, texture_offset, #0x10; \
+ add fb_ptr, fb_ptr, #2048 * 2; \
+ \
+ subs sub_tile_height, sub_tile_height, #1; \
+ bne 4b; \
+ \
+ sub block, block, #16; \
+ ldr column_data, [sp], #8; /* fb_ptr2 */ \
+ add texture_offset, texture_offset, #0xF00; \
+ strh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ] \
+
+
+#define setup_sprite_tile_column_edge_pre_adjust_half_right_4x() \
+ add texture_offset, texture_offset_base, #8; \
+ add fb_ptr, fb_ptr, #16 * 2 \
+
+#define setup_sprite_tile_column_edge_pre_adjust_half_left_4x() \
+ mov texture_offset, texture_offset_base \
+
+#define setup_sprite_tile_column_edge_pre_adjust_half_4x(edge) \
+ setup_sprite_tile_column_edge_pre_adjust_half_##edge##_4x() \
+
+#define setup_sprite_tile_column_edge_pre_adjust_full_4x(edge) \
+ mov texture_offset, texture_offset_base \
+
+#define setup_sprite_tile_column_edge_post_adjust_half_right_4x() \
+ sub fb_ptr, fb_ptr, #16 * 2 \
+
+#define setup_sprite_tile_column_edge_post_adjust_half_left_4x() \
+
+#define setup_sprite_tile_column_edge_post_adjust_half_4x(edge) \
+ setup_sprite_tile_column_edge_post_adjust_half_##edge##_4x() \
+
+#define setup_sprite_tile_column_edge_post_adjust_full_4x(edge) \
+
+
+#define setup_sprite_setup_left_draw_mask_fb_ptr_4x() \
+ vdup.u8 draw_mask_fb_ptr_left_a, block_masks[0]; \
+ vdup.u8 draw_mask_fb_ptr_left_b, block_masks[1]; \
+ vdup.u8 draw_mask_fb_ptr_right_a, block_masks[2]; \
+ vdup.u8 draw_mask_fb_ptr_right_b, block_masks[3] \
+
+#define setup_sprite_setup_left_draw_mask_fb_ptr_advance_column_4x() \
+ mov fb_ptr_advance_column, #32 * 2; \
+ vdup.u8 draw_mask_fb_ptr_left_a, block_masks[0]; \
+ vdup.u8 draw_mask_fb_ptr_left_b, block_masks[1]; \
+ sub fb_ptr_advance_column, height, lsl #11 + 1; \
+ vdup.u8 draw_mask_fb_ptr_right_a, block_masks[2]; \
+ vdup.u8 draw_mask_fb_ptr_right_b, block_masks[3] \
+
+#define setup_sprite_setup_right_draw_mask_fb_ptr_4x() \
+ vdup.u8 draw_mask_fb_ptr_left_a, block_masks[4]; \
+ vdup.u8 draw_mask_fb_ptr_left_b, block_masks[5]; \
+ vdup.u8 draw_mask_fb_ptr_right_a, block_masks[6]; \
+ vdup.u8 draw_mask_fb_ptr_right_b, block_masks[7] \
+
+
+// r0: psx_gpu
+// r1: x
+// r2: y
+// r3: u
+// [ sp ]: v
+// [ sp + 4 ]: width
+// [ sp + 8 ]: height
+// [ sp + 12 ]: color (unused)
+
+#define setup_sprite_tiled_builder(texture_mode, x4mode) \
+ \
+setup_sprite_tile_column_width_multi(texture_mode, multi, full, full, \
+ x4mode); \
+setup_sprite_tile_column_width_single(texture_mode, multi, full, none, \
+ x4mode); \
+setup_sprite_tile_column_width_multi(texture_mode, single, full, full, \
+ x4mode); \
+setup_sprite_tile_column_width_single(texture_mode, single, full, none, \
+ x4mode); \
+setup_sprite_tile_column_width_multi(texture_mode, multi, half, full, \
+ x4mode); \
+setup_sprite_tile_column_width_single(texture_mode, multi, half, right, \
+ x4mode); \
+setup_sprite_tile_column_width_multi(texture_mode, single, half, full, \
+ x4mode); \
+setup_sprite_tile_column_width_single(texture_mode, single, half, right, \
+ x4mode); \
+setup_sprite_tile_column_width_multi(texture_mode, multi, full, half, \
+ x4mode); \
+setup_sprite_tile_column_width_single(texture_mode, multi, half, left, \
+ x4mode); \
+setup_sprite_tile_column_width_multi(texture_mode, single, full, half, \
+ x4mode); \
+setup_sprite_tile_column_width_single(texture_mode, single, half, left, \
+ x4mode); \
+setup_sprite_tile_column_width_multi(texture_mode, multi, half, half, \
+ x4mode); \
+setup_sprite_tile_column_width_multi(texture_mode, single, half, half, \
+ x4mode); \
+ \
+.align 4; \
+ \
+function(setup_sprite_##texture_mode##x4mode) \
+ stmdb sp!, { r4 - r11, r14 }; \
+ setup_sprite_tiled_initialize_##texture_mode##x4mode(); \
+ \
+ ldr v, [ sp, #36 ]; \
+ and offset_u, u, #0xF; \
+ \
+ ldr width, [ sp, #40 ]; \
+ ldr fb_ptr, [ psx_gpu, #psx_gpu_vram_out_ptr_offset ]; \
+ \
+ ldr height, [ sp, #44 ]; \
+ add fb_ptr, fb_ptr, y, lsl #11; \
+ \
+ add fb_ptr, fb_ptr, x, lsl #1; \
+ and offset_v, v, #0xF; \
+ \
+ sub fb_ptr, fb_ptr, offset_u, lsl #1; \
+ add width_rounded, offset_u, width; \
+ \
+ add height_rounded, offset_v, height; \
+ add width_rounded, width_rounded, #15; \
+ \
+ add height_rounded, height_rounded, #15; \
+ mov tile_width, width_rounded, lsr #4; \
+ \
+ /* texture_offset_base = VH-VL-00-00 */\
+ mov texture_offset_base, v, lsl #8; \
+ and offset_u_right, width_rounded, #0xF; \
+ \
+ /* texture_offset_base = VH-UH-UL-00 */\
+ bfi texture_offset_base, u, #4, #8; \
+ mov right_block_mask, #0xFFFFFFFE; \
+ \
+ setup_sprite_offset_u_adjust##x4mode(); \
+ \
+ /* texture_offset_base = VH-UH-VL-00 */\
+ bfi texture_offset_base, v, #4, #4; \
+ mov left_block_mask, #0xFFFFFFFF; \
+ \
+ mov tile_height, height_rounded, lsr #4; \
+ mvn left_block_mask, left_block_mask, lsl offset_u; \
+ \
+ /* texture_mask = HH-HL-WH-WL */\
+ ldrh texture_mask, [ psx_gpu, #psx_gpu_texture_mask_width_offset ]; \
+ mov right_block_mask, right_block_mask, lsl offset_u_right; \
+ \
+ /* texture_mask_rev = WH-WL-HH-HL */\
+ rev16 texture_mask_rev, texture_mask; \
+ vmov block_masks, left_block_mask, right_block_mask; \
+ \
+ /* texture_mask = HH-HL-HL-WL */\
+ bfi texture_mask, texture_mask_rev, #4, #4; \
+ /* texture_mask_rev = 00-00-00-WH */\
+ mov texture_mask_rev, texture_mask_rev, lsr #12; \
+ \
+ /* texture_mask = HH-WH-HL-WL */\
+ bfi texture_mask, texture_mask_rev, #8, #4; \
+ setup_sprite_get_left_block_mask##x4mode(); \
+ \
+ mov control_mask, #0; \
+ setup_sprite_compare_left_block_mask##x4mode(); \
+ \
+ setup_sprite_get_right_block_mask##x4mode(); \
+ orreq control_mask, control_mask, #0x4; \
+ \
+ ldrh num_blocks, [ psx_gpu, #psx_gpu_num_blocks_offset ]; \
+ setup_sprite_compare_right_block_mask##x4mode(); \
+ \
+ orreq control_mask, control_mask, #0x8; \
+ cmp tile_width, #1; \
+ \
+ add block, psx_gpu, #psx_gpu_blocks_offset; \
+ orreq control_mask, control_mask, #0x1; \