(triangle_winding_##winding << 6)) \
static int prepare_triangle(psx_gpu_struct *psx_gpu, vertex_struct *vertexes,
- vertex_struct *vertexes_out[3])
+ prepared_triangle *triangle_out)
{
- s32 y_top, y_bottom;
+ s32 y_top, y_bottom, offset_x, offset_y, i;
s32 triangle_area;
u32 triangle_winding = 0;
y_bottom = c->y;
y_top = a->y;
+ offset_y = sign_extend_11bit(y_top + psx_gpu->offset_y) - y_top;
if((y_bottom - y_top) >= 512)
{
vertex_swap(a, b);
}
- if((c->x - psx_gpu->offset_x) >= 1024 || (c->x - a->x) >= 1024)
+ if(c->x - a->x >= 1024)
{
#ifdef PROFILE
trivial_rejects++;
return 0;
}
- if(invalidate_texture_cache_region_viewport(psx_gpu, a->x, y_top, c->x,
- y_bottom) == 0)
+ offset_x = sign_extend_11bit(a->x + psx_gpu->offset_x) - a->x;
+ if(invalidate_texture_cache_region_viewport(psx_gpu,
+ a->x + offset_x, y_top + offset_y,
+ c->x + offset_x, y_bottom + offset_y) == 0)
{
#ifdef PROFILE
trivial_rejects++;
return 0;
}
+ for (i = 0; i < 3; i++)
+ {
+ vertexes[i].x += offset_x;
+ vertexes[i].y += offset_y;
+ }
+
psx_gpu->triangle_area = triangle_area;
psx_gpu->triangle_winding = triangle_winding;
- vertexes_out[0] = a;
- vertexes_out[1] = b;
- vertexes_out[2] = c;
+ triangle_out->vertexes[0] = a;
+ triangle_out->vertexes[1] = b;
+ triangle_out->vertexes[2] = c;
+ triangle_out->offset_x = offset_x;
+ triangle_out->offset_y = offset_y;
return 1;
}
void render_triangle(psx_gpu_struct *psx_gpu, vertex_struct *vertexes,
u32 flags)
{
- vertex_struct *vertex_ptrs[3];
- if (prepare_triangle(psx_gpu, vertexes, vertex_ptrs))
- render_triangle_p(psx_gpu, vertex_ptrs, flags);
+ prepared_triangle triangle;
+ if (prepare_triangle(psx_gpu, vertexes, &triangle))
+ render_triangle_p(psx_gpu, triangle.vertexes, flags);
}
#if !defined(NEON_BUILD) || defined(SIMD_BUILD)
#define unlikely(x) __builtin_expect((x), 0)
#endif
+#define sign_extend_11bit(value) \
+ (((s32)((value) << 21)) >> 21)
+
typedef enum
{
PRIMITIVE_TYPE_TRIANGLE = 0,
u32 padding;
} vertex_struct;
+typedef struct
+{
+ vertex_struct *vertexes[3];
+ s16 offset_x;
+ s16 offset_y;
+} prepared_triangle;
+
void render_block_fill(psx_gpu_struct *psx_gpu, u32 color, u32 x, u32 y,
u32 width, u32 height);
void render_block_copy(psx_gpu_struct *psx_gpu, u16 *source, u32 x, u32 y,
}
}
-#define sign_extend_11bit(value) \
- (((s32)((value) << 21)) >> 21) \
-
#define get_vertex_data_xy(vertex_number, offset16) \
- vertexes[vertex_number].x = \
- sign_extend_11bit(list_s16[offset16]) + psx_gpu->offset_x; \
- vertexes[vertex_number].y = \
- sign_extend_11bit(list_s16[(offset16) + 1]) + psx_gpu->offset_y; \
+ vertexes[vertex_number].x = sign_extend_11bit(list_s16[offset16]); \
+ vertexes[vertex_number].y = sign_extend_11bit(list_s16[(offset16) + 1]); \
#define get_vertex_data_uv(vertex_number, offset16) \
vertexes[vertex_number].u = list_s16[offset16] & 0xFF; \
gput_sum(*cpu_cycles_sum, *cpu_cycles, gput_sprite(width, height));
}
+static void undo_offset(vertex_struct *vertexes, prepared_triangle *triangle)
+{
+ s32 i;
+ for (i = 0; i < 3; i++)
+ {
+ vertexes[i].x -= triangle->offset_x;
+ vertexes[i].y -= triangle->offset_y;
+ }
+}
+
+static void do_triangle(psx_gpu_struct *psx_gpu, vertex_struct *vertexes,
+ u32 current_command)
+{
+ prepared_triangle triangle;
+ if (prepare_triangle(psx_gpu, vertexes, &triangle))
+ render_triangle_p(psx_gpu, triangle.vertexes, current_command);
+}
+
+static void do_quad(psx_gpu_struct *psx_gpu, vertex_struct *vertexes,
+ u32 current_command)
+{
+ prepared_triangle triangle;
+ if (prepare_triangle(psx_gpu, vertexes, &triangle))
+ {
+ render_triangle_p(psx_gpu, triangle.vertexes, current_command);
+ undo_offset(vertexes, &triangle);
+ }
+ if (prepare_triangle(psx_gpu, vertexes + 1, &triangle))
+ render_triangle_p(psx_gpu, triangle.vertexes, current_command);
+}
+
u32 gpu_parse(psx_gpu_struct *psx_gpu, u32 *list, u32 size,
s32 *cpu_cycles_sum_out, s32 *cpu_cycles_last, u32 *last_command)
{
get_vertex_data_xy(1, 4);
get_vertex_data_xy(2, 6);
- render_triangle(psx_gpu, vertexes, current_command);
+ do_triangle(psx_gpu, vertexes, current_command);
gput_sum(cpu_cycles_sum, cpu_cycles, gput_poly_base());
break;
}
get_vertex_data_xy_uv(1, 6);
get_vertex_data_xy_uv(2, 10);
- render_triangle(psx_gpu, vertexes, current_command);
+ do_triangle(psx_gpu, vertexes, current_command);
gput_sum(cpu_cycles_sum, cpu_cycles, gput_poly_base_t());
break;
}
get_vertex_data_xy(1, 4);
get_vertex_data_xy(2, 6);
get_vertex_data_xy(3, 8);
-
- render_triangle(psx_gpu, vertexes, current_command);
- render_triangle(psx_gpu, &(vertexes[1]), current_command);
+
+ do_quad(psx_gpu, vertexes, current_command);
gput_sum(cpu_cycles_sum, cpu_cycles, gput_quad_base());
break;
}
get_vertex_data_xy_uv(1, 6);
get_vertex_data_xy_uv(2, 10);
get_vertex_data_xy_uv(3, 14);
-
- render_triangle(psx_gpu, vertexes, current_command);
- render_triangle(psx_gpu, &(vertexes[1]), current_command);
+
+ do_quad(psx_gpu, vertexes, current_command);
gput_sum(cpu_cycles_sum, cpu_cycles, gput_quad_base_t());
break;
}
get_vertex_data_xy_rgb(1, 4);
get_vertex_data_xy_rgb(2, 8);
- render_triangle(psx_gpu, vertexes, current_command);
+ do_triangle(psx_gpu, vertexes, current_command);
gput_sum(cpu_cycles_sum, cpu_cycles, gput_poly_base_g());
break;
}
get_vertex_data_xy_uv_rgb(1, 6);
get_vertex_data_xy_uv_rgb(2, 12);
- render_triangle(psx_gpu, vertexes, current_command);
+ do_triangle(psx_gpu, vertexes, current_command);
gput_sum(cpu_cycles_sum, cpu_cycles, gput_poly_base_gt());
break;
}
get_vertex_data_xy_rgb(1, 4);
get_vertex_data_xy_rgb(2, 8);
get_vertex_data_xy_rgb(3, 12);
-
- render_triangle(psx_gpu, vertexes, current_command);
- render_triangle(psx_gpu, &(vertexes[1]), current_command);
+
+ do_quad(psx_gpu, vertexes, current_command);
gput_sum(cpu_cycles_sum, cpu_cycles, gput_quad_base_g());
break;
}
get_vertex_data_xy_uv_rgb(1, 6);
get_vertex_data_xy_uv_rgb(2, 12);
get_vertex_data_xy_uv_rgb(3, 18);
-
- render_triangle(psx_gpu, vertexes, current_command);
- render_triangle(psx_gpu, &(vertexes[1]), current_command);
+
+ do_quad(psx_gpu, vertexes, current_command);
gput_sum(cpu_cycles_sum, cpu_cycles, gput_quad_base_gt());
break;
}
case 0xE5:
{
- s32 offset_x = list[0] << 21;
- s32 offset_y = list[0] << 10;
- psx_gpu->offset_x = offset_x >> 21;
- psx_gpu->offset_y = offset_y >> 21;
+ psx_gpu->offset_x = sign_extend_11bit(list[0]);
+ psx_gpu->offset_y = sign_extend_11bit(list[0] >> 11);
SET_Ex(5, list[0]);
break;
static void do_triangle_enhanced(psx_gpu_struct *psx_gpu,
vertex_struct *vertexes, u32 current_command)
{
- vertex_struct *vertex_ptrs[3];
+ prepared_triangle triangle;
- if (!prepare_triangle(psx_gpu, vertexes, vertex_ptrs))
+ if (!prepare_triangle(psx_gpu, vertexes, &triangle))
return;
if (!psx_gpu->hack_disable_main)
- render_triangle_p(psx_gpu, vertex_ptrs, current_command);
+ render_triangle_p(psx_gpu, triangle.vertexes, current_command);
- if (!check_enhanced_range(psx_gpu, vertex_ptrs[0]->x, vertex_ptrs[2]->x))
+ if (!check_enhanced_range(psx_gpu, triangle.vertexes[0]->x,
+ triangle.vertexes[2]->x))
return;
if (!enhancement_enable(psx_gpu))
if ((current_command & RENDER_FLAGS_TEXTURE_MAP) && psx_gpu->hack_texture_adj)
psx_gpu->hacks_active |= uv_hack(psx_gpu, vertexes);
- shift_vertices3(vertex_ptrs);
+ shift_vertices3(triangle.vertexes);
shift_triangle_area();
- render_triangle_p(psx_gpu, vertex_ptrs, current_command);
- unshift_vertices3(vertex_ptrs);
+ render_triangle_p(psx_gpu, triangle.vertexes, current_command);
+ //unshift_vertices3(triangle.vertexes);
}
static void do_quad_enhanced(psx_gpu_struct *psx_gpu, vertex_struct *vertexes,
u32 current_command)
{
+ s16 x12_save[2] = { vertexes[1].x, vertexes[2].x };
+ s16 y12_save[2] = { vertexes[1].y, vertexes[2].y };
do_triangle_enhanced(psx_gpu, vertexes, current_command);
enhancement_disable();
+ vertexes[1].x = x12_save[0], vertexes[2].x = x12_save[1];
+ vertexes[1].y = y12_save[0], vertexes[2].y = y12_save[1];
do_triangle_enhanced(psx_gpu, &vertexes[1], current_command);
}
int num_verts = (is_quad) ? 4 : 3;
le32_t *ptr;
- // X,Y coords, adjusted by draw offsets
- s32 x_off = gpu_unai.DrawingOffset[0];
- s32 y_off = gpu_unai.DrawingOffset[1];
+ // X,Y coords
ptr = &packet.U4[1];
for (int i=0; i < num_verts; ++i, ptr += vert_stride) {
u32 coords = le32_to_u32(*ptr);
- vbuf[i].x = GPU_EXPANDSIGN((s16)coords) + x_off;
- vbuf[i].y = GPU_EXPANDSIGN((s16)(coords >> 16)) + y_off;
+ vbuf[i].x = GPU_EXPANDSIGN(coords);
+ vbuf[i].y = GPU_EXPANDSIGN(coords >> 16);
}
// U,V texture coords (if applicable)
// or 1 for second triangle of a quad (idx 1,2,3 of vbuf[]).
// Returns true if triangle should be rendered, false if not.
///////////////////////////////////////////////////////////////////////////////
-static bool polyUseTriangle(const PolyVertex *vbuf, int tri_num, const PolyVertex **vert_ptrs)
+static bool polyUseTriangle(const PolyVertex *vbuf, int tri_num, const PolyVertex **vert_ptrs, s32 &x_off, s32 &y_off)
{
// Using verts 0,1,2 or is this the 2nd pass of a quad (verts 1,2,3)?
const PolyVertex *tri_ptr = &vbuf[(tri_num == 0) ? 0 : 1];
(highest_y - lowest_y) >= CHKMAX_Y)
return false;
+ // Determine offsets
+ x_off = gpu_unai.DrawingOffset[0];
+ y_off = gpu_unai.DrawingOffset[1];
+ x_off = GPU_EXPANDSIGN(lowest_x + x_off) - lowest_x;
+ y_off = GPU_EXPANDSIGN(lowest_y + y_off) - lowest_y;
+
// Determine if triangle is completely outside clipping range
int xmin, xmax, ymin, ymax;
xmin = gpu_unai.DrawingArea[0]; xmax = gpu_unai.DrawingArea[2];
ymin = gpu_unai.DrawingArea[1]; ymax = gpu_unai.DrawingArea[3];
- int clipped_lowest_x = Max2(xmin,lowest_x);
- int clipped_lowest_y = Max2(ymin,lowest_y);
- int clipped_highest_x = Min2(xmax,highest_x);
- int clipped_highest_y = Min2(ymax,highest_y);
+ int clipped_lowest_x = Max2(xmin, lowest_x + x_off);
+ int clipped_lowest_y = Max2(ymin, lowest_y + y_off);
+ int clipped_highest_x = Min2(xmax, highest_x + x_off);
+ int clipped_highest_y = Min2(ymax, highest_y + y_off);
if (clipped_lowest_x >= clipped_highest_x ||
clipped_lowest_y >= clipped_highest_y)
return false;
do
{
const PolyVertex* vptrs[3];
- if (polyUseTriangle(vbuf, cur_pass, vptrs) == false)
+ s32 x_off, y_off;
+ if (!polyUseTriangle(vbuf, cur_pass, vptrs, x_off, y_off))
continue;
s32 xa, xb, ya, yb;
s32 x3, dx3, x4, dx4, dx;
s32 x0, x1, x2, y0, y1, y2;
- x0 = vptrs[0]->x; y0 = vptrs[0]->y;
- x1 = vptrs[1]->x; y1 = vptrs[1]->y;
- x2 = vptrs[2]->x; y2 = vptrs[2]->y;
+ x0 = vptrs[0]->x + x_off; y0 = vptrs[0]->y + y_off;
+ x1 = vptrs[1]->x + x_off; y1 = vptrs[1]->y + y_off;
+ x2 = vptrs[2]->x + x_off; y2 = vptrs[2]->y + y_off;
ya = y2 - y0;
yb = y2 - y1;
do
{
const PolyVertex* vptrs[3];
- if (polyUseTriangle(vbuf, cur_pass, vptrs) == false)
+ s32 x_off, y_off;
+ if (!polyUseTriangle(vbuf, cur_pass, vptrs, x_off, y_off))
continue;
s32 xa, xb, ya, yb;
s32 u0, u1, u2, v0, v1, v2;
s32 du4, dv4;
- x0 = vptrs[0]->x; y0 = vptrs[0]->y;
- u0 = vptrs[0]->tex.u; v0 = vptrs[0]->tex.v;
- x1 = vptrs[1]->x; y1 = vptrs[1]->y;
- u1 = vptrs[1]->tex.u; v1 = vptrs[1]->tex.v;
- x2 = vptrs[2]->x; y2 = vptrs[2]->y;
- u2 = vptrs[2]->tex.u; v2 = vptrs[2]->tex.v;
+ x0 = vptrs[0]->x + x_off; y0 = vptrs[0]->y + y_off;
+ u0 = vptrs[0]->tex.u; v0 = vptrs[0]->tex.v;
+ x1 = vptrs[1]->x + x_off; y1 = vptrs[1]->y + y_off;
+ u1 = vptrs[1]->tex.u; v1 = vptrs[1]->tex.v;
+ x2 = vptrs[2]->x + x_off; y2 = vptrs[2]->y + y_off;
+ u2 = vptrs[2]->tex.u; v2 = vptrs[2]->tex.v;
ya = y2 - y0;
yb = y2 - y1;
do
{
const PolyVertex* vptrs[3];
- if (polyUseTriangle(vbuf, cur_pass, vptrs) == false)
+ s32 x_off, y_off;
+ if (!polyUseTriangle(vbuf, cur_pass, vptrs, x_off, y_off))
continue;
s32 xa, xb, ya, yb;
s32 r0, r1, r2, g0, g1, g2, b0, b1, b2;
s32 dr4, dg4, db4;
- x0 = vptrs[0]->x; y0 = vptrs[0]->y;
- r0 = vptrs[0]->col.r; g0 = vptrs[0]->col.g; b0 = vptrs[0]->col.b;
- x1 = vptrs[1]->x; y1 = vptrs[1]->y;
- r1 = vptrs[1]->col.r; g1 = vptrs[1]->col.g; b1 = vptrs[1]->col.b;
- x2 = vptrs[2]->x; y2 = vptrs[2]->y;
- r2 = vptrs[2]->col.r; g2 = vptrs[2]->col.g; b2 = vptrs[2]->col.b;
+ x0 = vptrs[0]->x + x_off; y0 = vptrs[0]->y + y_off;
+ r0 = vptrs[0]->col.r; g0 = vptrs[0]->col.g; b0 = vptrs[0]->col.b;
+ x1 = vptrs[1]->x + x_off; y1 = vptrs[1]->y + y_off;
+ r1 = vptrs[1]->col.r; g1 = vptrs[1]->col.g; b1 = vptrs[1]->col.b;
+ x2 = vptrs[2]->x + x_off; y2 = vptrs[2]->y + y_off;
+ r2 = vptrs[2]->col.r; g2 = vptrs[2]->col.g; b2 = vptrs[2]->col.b;
ya = y2 - y0;
yb = y2 - y1;
do
{
const PolyVertex* vptrs[3];
- if (polyUseTriangle(vbuf, cur_pass, vptrs) == false)
+ s32 x_off, y_off;
+ if (!polyUseTriangle(vbuf, cur_pass, vptrs, x_off, y_off))
continue;
s32 xa, xb, ya, yb;
s32 du4, dv4;
s32 dr4, dg4, db4;
- x0 = vptrs[0]->x; y0 = vptrs[0]->y;
- u0 = vptrs[0]->tex.u; v0 = vptrs[0]->tex.v;
- r0 = vptrs[0]->col.r; g0 = vptrs[0]->col.g; b0 = vptrs[0]->col.b;
- x1 = vptrs[1]->x; y1 = vptrs[1]->y;
- u1 = vptrs[1]->tex.u; v1 = vptrs[1]->tex.v;
- r1 = vptrs[1]->col.r; g1 = vptrs[1]->col.g; b1 = vptrs[1]->col.b;
- x2 = vptrs[2]->x; y2 = vptrs[2]->y;
- u2 = vptrs[2]->tex.u; v2 = vptrs[2]->tex.v;
- r2 = vptrs[2]->col.r; g2 = vptrs[2]->col.g; b2 = vptrs[2]->col.b;
+ x0 = vptrs[0]->x + x_off; y0 = vptrs[0]->y + y_off;
+ u0 = vptrs[0]->tex.u; v0 = vptrs[0]->tex.v;
+ r0 = vptrs[0]->col.r; g0 = vptrs[0]->col.g; b0 = vptrs[0]->col.b;
+ x1 = vptrs[1]->x + x_off; y1 = vptrs[1]->y + y_off;
+ u1 = vptrs[1]->tex.u; v1 = vptrs[1]->tex.v;
+ r1 = vptrs[1]->col.r; g1 = vptrs[1]->col.g; b1 = vptrs[1]->col.b;
+ x2 = vptrs[2]->x + x_off; y2 = vptrs[2]->y + y_off;
+ u2 = vptrs[2]->tex.u; v2 = vptrs[2]->tex.v;
+ r2 = vptrs[2]->col.r; g2 = vptrs[2]->col.g; b2 = vptrs[2]->col.b;
ya = y2 - y0;
yb = y2 - y1;
case 5: {
// GP0(E5h) - Set Drawing Offset (X,Y)
- gpu_unai.DrawingOffset[0] = ((s32)cmd_word<<(32-11))>>(32-11);
- gpu_unai.DrawingOffset[1] = ((s32)cmd_word<<(32-22))>>(32-11);
+ gpu_unai.DrawingOffset[0] = GPU_EXPANDSIGN(cmd_word);
+ gpu_unai.DrawingOffset[1] = GPU_EXPANDSIGN(cmd_word >> 11);
} break;
case 6: {