From 136b8b9c01588a9fb973db28839891639a71433f Mon Sep 17 00:00:00 2001 From: AntonioND Date: Sun, 1 Feb 2015 17:09:34 +0100 Subject: [PATCH] Multicore rendering, yay!! Each core renders one of the top screens. :D Multicore rendering, yay!! Each core renders one of the top screens. :D --- pong-3ds.3dsx | Bin 867484 -> 868984 bytes send_3dsx.bat | 2 + source/draw.c | 255 ++++++++++++++++++++++++---------------------- source/draw.h | 30 +++--- source/engine.c | 56 +++++----- source/engine.h | 10 +- source/game.c | 215 +++++++++++++++++++------------------- source/game.h | 2 +- source/main.c | 151 +++++++++++++++++++++++---- source/polygon.c | 58 ++++++----- source/polygon.h | 4 +- source/syscalls.s | 8 ++ source/utils.c | 44 ++++---- source/utils.h | 10 +- template.pnproj | 2 +- 15 files changed, 493 insertions(+), 354 deletions(-) create mode 100644 send_3dsx.bat create mode 100644 source/syscalls.s diff --git a/pong-3ds.3dsx b/pong-3ds.3dsx index 340d33aa3d482512fc15a750c3f78649d8231cc7..ba9d4186bb06ddec266eef2d3f016100bd4a9414 100644 GIT binary patch delta 32161 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îoBhuY+ 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 0) && !_s3d_draw_back) return 0; - if((cross < 0) && !_s3d_draw_front) return 0; + if((cross > 0) && !_s3d_draw_back[screen]) return 0; + if((cross < 0) && !_s3d_draw_front[screen]) return 0; return 1; } @@ -593,41 +590,41 @@ void S3D_2D_QuadAllignedFill(u8 * buf, int x1, int y1, int x2, int y2, int r, in //--------------------------------------------------------------------------------------- -static u32 currcolor_r, currcolor_g, currcolor_b; -static u32 saved_r = 255, saved_g = 255, saved_b = 255; +static u32 currcolor_r[2], currcolor_g[2], currcolor_b[2]; +static u32 saved_r[2] = { 255, 255 }, saved_g[2] = { 255, 255 }, saved_b[2] = { 255, 255 }; #define MAX_LIGHT_SOURCES (2) // no more than 32 -static v4 light_dir[MAX_LIGHT_SOURCES]; -static v4 light_color[MAX_LIGHT_SOURCES]; -static u32 light_enabled = 0; -static int amb_r = 0, amb_g = 0, amb_b = 0; +static v4 light_dir[2][MAX_LIGHT_SOURCES]; +static v4 light_color[2][MAX_LIGHT_SOURCES]; +static u32 light_enabled[2] = { 0, 0 }; +static int amb_r[2] = { 0, 0 }, amb_g[2] = { 0, 0 }, amb_b[2] = { 0, 0 }; //--------------------------------------------- -void S3D_PolygonColor(u32 r, u32 g, u32 b) +void S3D_PolygonColor(int screen, u32 r, u32 g, u32 b) { - currcolor_r = saved_r = r; - currcolor_g = saved_g = g; - currcolor_b = saved_b = b; + currcolor_r[screen] = saved_r[screen] = r; + currcolor_g[screen] = saved_g[screen] = g; + currcolor_b[screen] = saved_b[screen] = b; } //--------------------------------------------- -void S3D_PolygonNormal(s32 x, s32 y, s32 z) +void S3D_PolygonNormal(int screen, s32 x, s32 y, s32 z) { v4 l = { x, y, z, 0}; - int fr = amb_r, fg = amb_g, fb = amb_b; // add factors + int fr = amb_r[screen], fg = amb_g[screen], fb = amb_b[screen]; // add factors int i; - for(i = 0; i < MAX_LIGHT_SOURCES; i++) if(light_enabled & S3D_LIGHT_N(i)) + for(i = 0; i < MAX_LIGHT_SOURCES; i++) if(light_enabled[screen] & S3D_LIGHT_N(i)) { - s32 factor = -v4_DotProduct(&l,&(light_dir[i])); // change sign because light goes AGAINST a normal + s32 factor = -v4_DotProduct(&l,&(light_dir[screen][i])); // change sign because light goes AGAINST a normal if(factor > 0) { - fr += fxmul(factor,light_color[i][0]); - fg += fxmul(factor,light_color[i][1]); - fb += fxmul(factor,light_color[i][2]); + fr += fxmul(factor,light_color[screen][i][0]); + fg += fxmul(factor,light_color[screen][i][1]); + fb += fxmul(factor,light_color[screen][i][2]); } } @@ -635,81 +632,86 @@ void S3D_PolygonNormal(s32 x, s32 y, s32 z) if(fg > 255) fg = 255; if(fb > 255) fb = 255; - int r = (saved_r * fr) / 256; - int g = (saved_g * fg) / 256; - int b = (saved_b * fb) / 256; + int r = (saved_r[screen] * fr) / 256; + int g = (saved_g[screen] * fg) / 256; + int b = (saved_b[screen] * fb) / 256; - currcolor_r = r; currcolor_g = g; currcolor_b = b; + currcolor_r[screen] = r; currcolor_g[screen] = g; currcolor_b[screen] = b; } //--------------------------------------------- -void S3D_LightAmbientColorSet(int r, int g, int b) +void S3D_LightAmbientColorSet(int screen, int r, int g, int b) { - amb_r = r; amb_g = g; amb_b = b; + amb_r[screen] = r; amb_g[screen] = g; amb_b[screen] = b; } -void S3D_LightDirectionalColorSet(int index, int r, int g, int b) +void S3D_LightDirectionalColorSet(int screen, int index, int r, int g, int b) { - light_color[index][0] = r; light_color[index][1] = g; light_color[index][2] = b; + light_color[screen][index][0] = r; + light_color[screen][index][1] = g; + light_color[screen][index][2] = b; } -void S3D_LightDirectionalVectorSet(int index, s32 x, s32 y, s32 z) +void S3D_LightDirectionalVectorSet(int screen, int index, s32 x, s32 y, s32 z) { - light_dir[index][0] = x; light_dir[index][1] = y; light_dir[index][2] = z; + light_dir[screen][index][0] = x; + light_dir[screen][index][1] = y; + light_dir[screen][index][2] = z; } -void S3D_LightEnable(u32 enable_mask) +void S3D_LightEnable(int screen, u32 enable_mask) { - light_enabled = enable_mask; + light_enabled[screen] = enable_mask; } //--------------------------------------------------------------------------------------- -static s3d_primitive currmode = S3D_TRIANGLES; -static u32 vtx_count = 0; -#define MAX_VERTICES_IN_A_PRIMITIVE (4) -static v4 vtx_array[MAX_VERTICES_IN_A_PRIMITIVE]; static const u32 primitive_num_vertices[S3D_PRIMITIVE_NUMBER] = {1,2,3,4,2,3,4}; -static u32 curr_max_vertices; -void S3D_PolygonBegin(s3d_primitive type) +static s3d_primitive currmode[2] = { S3D_TRIANGLES, S3D_TRIANGLES }; +static u32 vtx_count[2] = { 0, 0 }; +#define MAX_VERTICES_IN_A_PRIMITIVE (4) +static v4 vtx_array[2][MAX_VERTICES_IN_A_PRIMITIVE]; +static u32 curr_max_vertices[2]; + +void S3D_PolygonBegin(int screen, s3d_primitive type) { - currmode = type; - vtx_count = 0; - curr_max_vertices = primitive_num_vertices[currmode]; + currmode[screen] = type; + vtx_count[screen] = 0; + curr_max_vertices[screen] = primitive_num_vertices[type]; } //--------------------------------------------- #define LINE_THICKNESS (3) -void _s3d_draw_dot(int x, int y, int r, int g, int b) +void _s3d_draw_dot(int screen, int x, int y, int r, int g, int b) { - S3D_2D_PlotEx(curr_buf,LINE_THICKNESS,x,y,r,g,b); + S3D_2D_PlotEx(curr_buf[screen],LINE_THICKNESS,x,y,r,g,b); } -void _s3d_draw_line(int x1, int y1, int x2, int y2, int r, int g, int b) +void _s3d_draw_line(int screen, int x1, int y1, int x2, int y2, int r, int g, int b) { - S3D_2D_LineEx(curr_buf,LINE_THICKNESS,x1,y1,x2,y2,r,g,b); + S3D_2D_LineEx(curr_buf[screen],LINE_THICKNESS,x1,y1,x2,y2,r,g,b); } -void _s3d_draw_triangle(int x1, int y1, int x2, int y2, int x3, int y3, int r, int g, int b) +void _s3d_draw_triangle(int screen, int x1, int y1, int x2, int y2, int x3, int y3, int r, int g, int b) { - if(!_s3d_check_cull_face(x1,y1,x2,y2,x3,y3)) return; + if(!_s3d_check_cull_face(screen,x1,y1,x2,y2,x3,y3)) return; - S3D_2D_TriangleFill(curr_buf,x1,y1,x2,y2,x3,y3,r,g,b); + S3D_2D_TriangleFill(curr_buf[screen],x1,y1,x2,y2,x3,y3,r,g,b); } -void _s3d_draw_quad(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4, int r, int g, int b) +void _s3d_draw_quad(int screen, int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4, int r, int g, int b) { - if(!_s3d_check_cull_face(x1,y1,x2,y2,x3,y3)) return; + if(!_s3d_check_cull_face(screen,x1,y1,x2,y2,x3,y3)) return; if( (x1==x2) || (x2==x3) || (x3==x4) || (x4==x1) ) { // Nothing - S3D_2D_TriangleFill(curr_buf,x1,y1,x2,y2,x3,y3,r,g,b); - S3D_2D_TriangleFill(curr_buf,x1,y1,x3,y3,x4,y4,r,g,b); + S3D_2D_TriangleFill(curr_buf[screen],x1,y1,x2,y2,x3,y3,r,g,b); + S3D_2D_TriangleFill(curr_buf[screen],x1,y1,x3,y3,x4,y4,r,g,b); } else { @@ -727,108 +729,115 @@ void _s3d_draw_quad(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int } } - S3D_2D_TriangleFill(curr_buf,x1,y1,x2,y2,x4,y4,r,g,b); - S3D_2D_TriangleFill(curr_buf,x2,y2,x3,y3,x4,y4,r,g,b); + S3D_2D_TriangleFill(curr_buf[screen],x1,y1,x2,y2,x4,y4,r,g,b); + S3D_2D_TriangleFill(curr_buf[screen],x2,y2,x3,y3,x4,y4,r,g,b); } } //--------------------------------------------- //In engine.c -extern m44 S3D_GLOBAL_MATRIX; -inline void _s3d_global_matrix_update(void); +extern m44 S3D_GLOBAL_MATRIX[2]; +inline void _s3d_global_matrix_update(int screen); //In polygon.c -void _s3d_polygon_list_add_dot(v4 * a, int _r, int _g, int _b); -void _s3d_polygon_list_add_line(v4 * a, v4 * b, int _r, int _g, int _b); -void _s3d_polygon_list_add_triangle(v4 * a, v4 * b, v4 * c, int _r, int _g, int _b); -void _s3d_polygon_list_add_quad(v4 * a, v4 * b, v4 * c, v4 * d, int _r, int _g, int _b); +void _s3d_polygon_list_add_dot(int screen, v4 * a, int _r, int _g, int _b); +void _s3d_polygon_list_add_line(int screen, v4 * a, v4 * b, int _r, int _g, int _b); +void _s3d_polygon_list_add_triangle(int screen, v4 * a, v4 * b, v4 * c, int _r, int _g, int _b); +void _s3d_polygon_list_add_quad(int screen, v4 * a, v4 * b, v4 * c, v4 * d, int _r, int _g, int _b); -void S3D_PolygonVertex(s32 x, s32 y, s32 z) +void S3D_PolygonVertex(int screen, s32 x, s32 y, s32 z) { v4 v = { x, y, z, int2fx(1) }; v4 result; - _s3d_global_matrix_update(); + _s3d_global_matrix_update(screen); - m44_v4_Multiply(&S3D_GLOBAL_MATRIX,&v,&result); + m44_v4_Multiply(&S3D_GLOBAL_MATRIX[screen],&v,&result); - vtx_array[vtx_count][0] = fx2int(fxdiv(result[0],result[3])); - vtx_array[vtx_count][1] = fx2int(fxdiv(result[1],result[3])); - vtx_array[vtx_count][3] = result[3]; - vtx_count++; + vtx_array[screen][vtx_count[screen]][0] = fx2int(fxdiv(result[0],result[3])); + vtx_array[screen][vtx_count[screen]][1] = fx2int(fxdiv(result[1],result[3])); + vtx_array[screen][vtx_count[screen]][3] = result[3]; + vtx_count[screen]++; - if(vtx_count == curr_max_vertices) + if(vtx_count[screen] == curr_max_vertices[screen]) { - switch(currmode) + switch(currmode[screen]) { case S3D_DOTS: - _s3d_polygon_list_add_dot(&(vtx_array[0]), - currcolor_r,currcolor_g,currcolor_b); + _s3d_polygon_list_add_dot(screen, + &(vtx_array[screen][0]), + currcolor_r[screen],currcolor_g[screen],currcolor_b[screen]); - vtx_count = 0; + vtx_count[screen] = 0; break; case S3D_LINES: - _s3d_polygon_list_add_line(&(vtx_array[0]),&(vtx_array[1]), - currcolor_r,currcolor_g,currcolor_b); + _s3d_polygon_list_add_line(screen, + &(vtx_array[screen][0]),&(vtx_array[screen][1]), + currcolor_r[screen],currcolor_g[screen],currcolor_b[screen]); - vtx_count = 0; + vtx_count[screen] = 0; break; case S3D_TRIANGLES: - _s3d_polygon_list_add_triangle(&(vtx_array[0]),&(vtx_array[1]),&(vtx_array[2]), - currcolor_r,currcolor_g,currcolor_b); + _s3d_polygon_list_add_triangle(screen, + &(vtx_array[screen][0]),&(vtx_array[screen][1]),&(vtx_array[screen][2]), + currcolor_r[screen],currcolor_g[screen],currcolor_b[screen]); - vtx_count = 0; + vtx_count[screen] = 0; break; case S3D_QUADS: - _s3d_polygon_list_add_quad(&(vtx_array[0]),&(vtx_array[1]),&(vtx_array[2]),&(vtx_array[3]), - currcolor_r,currcolor_g,currcolor_b); + _s3d_polygon_list_add_quad(screen, + &(vtx_array[screen][0]),&(vtx_array[screen][1]),&(vtx_array[screen][2]),&(vtx_array[screen][3]), + currcolor_r[screen],currcolor_g[screen],currcolor_b[screen]); - vtx_count = 0; + vtx_count[screen] = 0; break; case S3D_LINE_STRIP: - _s3d_polygon_list_add_line(&(vtx_array[0]),&(vtx_array[1]), - currcolor_r,currcolor_g,currcolor_b); + _s3d_polygon_list_add_line(screen, + &(vtx_array[screen][0]),&(vtx_array[screen][1]), + currcolor_r[screen],currcolor_g[screen],currcolor_b[screen]); - vtx_array[0][0] = vtx_array[1][0]; - vtx_array[0][1] = vtx_array[1][1]; - vtx_array[0][3] = vtx_array[1][3]; + vtx_array[screen][0][0] = vtx_array[screen][1][0]; + vtx_array[screen][0][1] = vtx_array[screen][1][1]; + vtx_array[screen][0][3] = vtx_array[screen][1][3]; - vtx_count = 1; + vtx_count[screen] = 1; break; case S3D_TRIANGLE_STRIP: - _s3d_polygon_list_add_triangle(&(vtx_array[0]),&(vtx_array[1]),&(vtx_array[2]), - currcolor_r,currcolor_g,currcolor_b); + _s3d_polygon_list_add_triangle(screen, + &(vtx_array[screen][0]),&(vtx_array[screen][1]),&(vtx_array[screen][2]), + currcolor_r[screen],currcolor_g[screen],currcolor_b[screen]); - vtx_array[0][0] = vtx_array[2][0]; - vtx_array[0][1] = vtx_array[2][1]; - vtx_array[0][3] = vtx_array[2][3]; + vtx_array[screen][0][0] = vtx_array[screen][2][0]; + vtx_array[screen][0][1] = vtx_array[screen][2][1]; + vtx_array[screen][0][3] = vtx_array[screen][2][3]; - vtx_count = 2; + vtx_count[screen] = 2; break; case S3D_QUAD_STRIP: - _s3d_polygon_list_add_quad(&(vtx_array[0]),&(vtx_array[1]),&(vtx_array[2]),&(vtx_array[3]), - currcolor_r,currcolor_g,currcolor_b); + _s3d_polygon_list_add_quad(screen, + &(vtx_array[screen][0]),&(vtx_array[screen][1]),&(vtx_array[screen][2]),&(vtx_array[screen][3]), + currcolor_r[screen],currcolor_g[screen],currcolor_b[screen]); - vtx_array[0][0] = vtx_array[3][0]; - vtx_array[0][1] = vtx_array[3][1]; - vtx_array[0][3] = vtx_array[3][3]; + vtx_array[screen][0][0] = vtx_array[screen][3][0]; + vtx_array[screen][0][1] = vtx_array[screen][3][1]; + vtx_array[screen][0][3] = vtx_array[screen][3][3]; - vtx_array[1][0] = vtx_array[2][0]; - vtx_array[1][1] = vtx_array[2][1]; - vtx_array[1][3] = vtx_array[2][3]; + vtx_array[screen][1][0] = vtx_array[screen][2][0]; + vtx_array[screen][1][1] = vtx_array[screen][2][1]; + vtx_array[screen][1][3] = vtx_array[screen][2][3]; - vtx_count = 2; + vtx_count[screen] = 2; break; default: - vtx_count = 0; + vtx_count[screen] = 0; break; } } diff --git a/source/draw.h b/source/draw.h index 49809f9..79d1da1 100644 --- a/source/draw.h +++ b/source/draw.h @@ -8,14 +8,16 @@ //---------------------------------------------------------------------------------- -// in utils_asm.s -void S3D_FramebufferFill(void * dst, u32 color, u32 bottom_screen); // color = 31 _BGR 0 +void S3D_BuffersSetup(void); // must be called at the beginning of each frame + +u8 * S3D_BufferGet(int screen); -void S3D_FramebuffersClearTopScreen(int r, int g, int b); +//---------------------------------------------------------------------------------- -void S3D_BufferSetScreen(int right); +// in utils_asm.s +void S3D_FramebufferFill(void * dst, u32 color, u32 bottom_screen); // color = 31 _BGR 0 -u8 * S3D_BufferGetCurrent(void); +void S3D_FramebuffersClearTopScreen(int screen, int r, int g, int b); //-------------------------------------------------------------------------------------------------- @@ -52,29 +54,29 @@ typedef enum { S3D_PRIMITIVE_NUMBER } s3d_primitive; -void S3D_PolygonBegin(s3d_primitive type); +void S3D_PolygonBegin(int screen, s3d_primitive type); -void S3D_PolygonVertex(s32 x, s32 y, s32 z); +void S3D_PolygonVertex(int screen, s32 x, s32 y, s32 z); // Stores a color for the following polygons and sets drawing color to that color. Anulates the current normal. -void S3D_PolygonColor(u32 r, u32 g, u32 b); +void S3D_PolygonColor(int screen, u32 r, u32 g, u32 b); // Sets the drawing color to current stored color affected by light. -void S3D_PolygonNormal(s32 x, s32 y, s32 z); +void S3D_PolygonNormal(int screen, s32 x, s32 y, s32 z); //-------------------------------------------------------------------------------------------------- -void S3D_SetCulling(int draw_front, int draw_back); +void S3D_SetCulling(int screen, int draw_front, int draw_back); //-------------------------------------------------------------------------------------------------- -void S3D_LightAmbientColorSet(int r, int g, int b); +void S3D_LightAmbientColorSet(int screen, int r, int g, int b); -void S3D_LightDirectionalVectorSet(int index, s32 x, s32 y, s32 z); -void S3D_LightDirectionalColorSet(int index, int r, int g, int b); +void S3D_LightDirectionalVectorSet(int screen, int index, s32 x, s32 y, s32 z); +void S3D_LightDirectionalColorSet(int screen, int index, int r, int g, int b); #define S3D_LIGHT_N(i) (1<<(i)) -void S3D_LightEnable(u32 enable_mask); +void S3D_LightEnable(int screen, u32 enable_mask); //-------------------------------------------------------------------------------------------------- diff --git a/source/engine.c b/source/engine.c index e069220..2302c25 100644 --- a/source/engine.c +++ b/source/engine.c @@ -5,61 +5,61 @@ //---------------------------------------------------------------------------- -m44 S3D_GLOBAL_MATRIX; // global variable +m44 S3D_GLOBAL_MATRIX[2]; // global variable -static m44 PROJECTION, MODELVIEW; -static u32 global_updated = 0; +static m44 PROJECTION[2], MODELVIEW[2]; +static u32 global_updated[2] = { 0, 0 }; #define MATRIX_STACK_SIZE (8) -static m44 matrix_stack[MATRIX_STACK_SIZE]; -static s32 matrix_stack_ptr = 0; +static m44 matrix_stack[2][MATRIX_STACK_SIZE]; +static s32 matrix_stack_ptr[2] = { 0, 0 }; //---------------------------------------------------------------------------- -void S3D_ProjectionMatrixSet(m44 * m) +void S3D_ProjectionMatrixSet(int screen, m44 * m) { - m44_Copy(m,&PROJECTION); - global_updated = 0; + m44_Copy(m,&PROJECTION[screen]); + global_updated[screen] = 0; } //---------------------------------------------------------------------------- -void S3D_ModelviewMatrixSet(m44 * m) +void S3D_ModelviewMatrixSet(int screen, m44 * m) { - m44_Copy(m,&MODELVIEW); - global_updated = 0; + m44_Copy(m,&MODELVIEW[screen]); + global_updated[screen] = 0; } -void S3D_ModelviewMatrixPush(void) +void S3D_ModelviewMatrixPush(int screen) { - //if(matrix_stack_ptr >= MATRIX_STACK_SIZE) while(1); - m44_Copy(&MODELVIEW,&(matrix_stack[matrix_stack_ptr])); - matrix_stack_ptr++; + //if(matrix_stack_ptr[screen] >= MATRIX_STACK_SIZE) while(1); + m44_Copy(&MODELVIEW[screen],&(matrix_stack[screen][matrix_stack_ptr[screen]])); + matrix_stack_ptr[screen]++; } -void S3D_ModelviewMatrixPop(void) +void S3D_ModelviewMatrixPop(int screen) { - //if(matrix_stack_ptr < 0) while(1); - matrix_stack_ptr--; - m44_Copy(&(matrix_stack[matrix_stack_ptr]),&MODELVIEW); - global_updated = 0; + //if(matrix_stack_ptr[screen] < 0) while(1); + matrix_stack_ptr[screen]--; + m44_Copy(&(matrix_stack[screen][matrix_stack_ptr[screen]]),&MODELVIEW[screen]); + global_updated[screen] = 0; } -void S3D_ModelviewMatrixMultiply(m44 * m) +void S3D_ModelviewMatrixMultiply(int screen, m44 * m) { m44 temp; - m44_Copy(&MODELVIEW,&temp); - m44_Multiply(&temp,m,&MODELVIEW); - global_updated = 0; + m44_Copy(&MODELVIEW[screen],&temp); + m44_Multiply(&temp,m,&MODELVIEW[screen]); + global_updated[screen] = 0; } //---------------------------------------------------------------------------- -inline void _s3d_global_matrix_update(void) +inline void _s3d_global_matrix_update(int screen) { - if(global_updated) return; - global_updated = 1; - m44_Multiply(&PROJECTION,&MODELVIEW,&S3D_GLOBAL_MATRIX); + if(global_updated[screen]) return; + global_updated[screen] = 1; + m44_Multiply(&PROJECTION[screen],&MODELVIEW[screen],&S3D_GLOBAL_MATRIX[screen]); } //---------------------------------------------------------------------------- diff --git a/source/engine.h b/source/engine.h index 59dbd4a..dfb8c93 100644 --- a/source/engine.h +++ b/source/engine.h @@ -12,14 +12,14 @@ //---------------------------------------------------------------------------- -void S3D_ProjectionMatrixSet(m44 * m); +void S3D_ProjectionMatrixSet(int screen, m44 * m); //---------------------------------------------------------------------------- -void S3D_ModelviewMatrixSet(m44 * m); -void S3D_ModelviewMatrixMultiply(m44 * m); -void S3D_ModelviewMatrixPush(void); -void S3D_ModelviewMatrixPop(void); +void S3D_ModelviewMatrixSet(int screen, m44 * m); +void S3D_ModelviewMatrixMultiply(int screen, m44 * m); +void S3D_ModelviewMatrixPush(int screen); +void S3D_ModelviewMatrixPop(int screen); //---------------------------------------------------------------------------- diff --git a/source/game.c b/source/game.c index fed09d3..21e2738 100644 --- a/source/game.c +++ b/source/game.c @@ -81,139 +81,139 @@ _ball_t ball; //------------------------------------------------------------------------------------------------------- -void draw_scenario(int r, int g, int b) +void draw_scenario(int screen, int r, int g, int b) { // Surface... - S3D_PolygonColor(r,g,b); + S3D_PolygonColor(screen, r,g,b); - S3D_PolygonBegin(S3D_QUADS); + S3D_PolygonBegin(screen, S3D_QUADS); - S3D_PolygonNormal(float2fx(0.0),float2fx(1.0),float2fx(0.0)); + S3D_PolygonNormal(screen, float2fx(0.0),float2fx(1.0),float2fx(0.0)); - S3D_PolygonVertex(float2fx(-7),float2fx(-1),float2fx(-0.5)); - S3D_PolygonVertex(float2fx(-7),float2fx(-1),float2fx(10.5)); - S3D_PolygonVertex(float2fx(7),float2fx(-1),float2fx(10.5)); - S3D_PolygonVertex(float2fx(7),float2fx(-1),float2fx(-0.5)); + S3D_PolygonVertex(screen, float2fx(-7),float2fx(-1),float2fx(-0.5)); + S3D_PolygonVertex(screen, float2fx(-7),float2fx(-1),float2fx(10.5)); + S3D_PolygonVertex(screen, float2fx(7),float2fx(-1),float2fx(10.5)); + S3D_PolygonVertex(screen, float2fx(7),float2fx(-1),float2fx(-0.5)); - S3D_PolygonListFlush(0); + S3D_PolygonListFlush(screen, 0); // Lines... - S3D_PolygonColor(r/2,g/2,b/2); + S3D_PolygonColor(screen, r/2,g/2,b/2); - S3D_PolygonNormal(float2fx(0.0),float2fx(1.0),float2fx(0.0)); + S3D_PolygonNormal(screen, float2fx(0.0),float2fx(1.0),float2fx(0.0)); - S3D_PolygonBegin(S3D_LINES); + S3D_PolygonBegin(screen, S3D_LINES); - S3D_PolygonVertex(float2fx(-7),float2fx(-1),float2fx(-0.5)); - S3D_PolygonVertex(float2fx(7),float2fx(-1),float2fx(-0.5)); + S3D_PolygonVertex(screen, float2fx(-7),float2fx(-1),float2fx(-0.5)); + S3D_PolygonVertex(screen, float2fx(7),float2fx(-1),float2fx(-0.5)); - S3D_PolygonVertex(float2fx(7),float2fx(-1),float2fx(10.5)); - S3D_PolygonVertex(float2fx(-7),float2fx(-1),float2fx(10.5)); + S3D_PolygonVertex(screen, float2fx(7),float2fx(-1),float2fx(10.5)); + S3D_PolygonVertex(screen, float2fx(-7),float2fx(-1),float2fx(10.5)); - S3D_PolygonVertex(float2fx(-7),float2fx(-1),float2fx(5.0)); - S3D_PolygonVertex(float2fx(7),float2fx(-1),float2fx(5.0)); + S3D_PolygonVertex(screen, float2fx(-7),float2fx(-1),float2fx(5.0)); + S3D_PolygonVertex(screen, float2fx(7),float2fx(-1),float2fx(5.0)); - S3D_PolygonListFlush(0); + S3D_PolygonListFlush(screen, 0); // Borders ... - S3D_PolygonColor(r,g,b); + S3D_PolygonColor(screen, r,g,b); - S3D_PolygonBegin(S3D_QUADS); + S3D_PolygonBegin(screen, S3D_QUADS); - S3D_PolygonNormal(float2fx(1.0),float2fx(0.0),float2fx(0.0)); + S3D_PolygonNormal(screen, float2fx(1.0),float2fx(0.0),float2fx(0.0)); - S3D_PolygonVertex(float2fx(-7),float2fx(1),float2fx(-0.5)); - S3D_PolygonVertex(float2fx(-7),float2fx(1),float2fx(10.5)); - S3D_PolygonVertex(float2fx(-7),float2fx(-1),float2fx(10.5)); - S3D_PolygonVertex(float2fx(-7),float2fx(-1),float2fx(-0.5)); + S3D_PolygonVertex(screen, float2fx(-7),float2fx(1),float2fx(-0.5)); + S3D_PolygonVertex(screen, float2fx(-7),float2fx(1),float2fx(10.5)); + S3D_PolygonVertex(screen, float2fx(-7),float2fx(-1),float2fx(10.5)); + S3D_PolygonVertex(screen, float2fx(-7),float2fx(-1),float2fx(-0.5)); - S3D_PolygonNormal(float2fx(-1.0),float2fx(0.0),float2fx(0.0)); + S3D_PolygonNormal(screen, float2fx(-1.0),float2fx(0.0),float2fx(0.0)); - S3D_PolygonVertex(float2fx(7),float2fx(-1),float2fx(-0.5)); - S3D_PolygonVertex(float2fx(7),float2fx(-1),float2fx(10.5)); - S3D_PolygonVertex(float2fx(7),float2fx(1),float2fx(10.5)); - S3D_PolygonVertex(float2fx(7),float2fx(1),float2fx(-0.5)); + S3D_PolygonVertex(screen, float2fx(7),float2fx(-1),float2fx(-0.5)); + S3D_PolygonVertex(screen, float2fx(7),float2fx(-1),float2fx(10.5)); + S3D_PolygonVertex(screen, float2fx(7),float2fx(1),float2fx(10.5)); + S3D_PolygonVertex(screen, float2fx(7),float2fx(1),float2fx(-0.5)); - S3D_PolygonListFlush(1); + S3D_PolygonListFlush(screen, 1); } -void draw_ball(int r, int g, int b) +void draw_ball(int screen, int r, int g, int b) { - S3D_PolygonColor(r,g,b); + S3D_PolygonColor(screen, r,g,b); - S3D_PolygonBegin(S3D_QUAD_STRIP); + S3D_PolygonBegin(screen, S3D_QUAD_STRIP); - S3D_PolygonNormal(float2fx(-1.0),float2fx(0.0),float2fx(0.0)); + S3D_PolygonNormal(screen, float2fx(-1.0),float2fx(0.0),float2fx(0.0)); - S3D_PolygonVertex(float2fx(-0.75),float2fx(-1),float2fx(-0.75)); - S3D_PolygonVertex(float2fx(-0.75),float2fx(-1),float2fx(0.75)); - S3D_PolygonVertex(float2fx(-0.75),float2fx(0.5),float2fx(0.75)); - S3D_PolygonVertex(float2fx(-0.75),float2fx(0.5),float2fx(-0.75)); + S3D_PolygonVertex(screen, float2fx(-0.75),float2fx(-1),float2fx(-0.75)); + S3D_PolygonVertex(screen, float2fx(-0.75),float2fx(-1),float2fx(0.75)); + S3D_PolygonVertex(screen, float2fx(-0.75),float2fx(0.5),float2fx(0.75)); + S3D_PolygonVertex(screen, float2fx(-0.75),float2fx(0.5),float2fx(-0.75)); - S3D_PolygonNormal(float2fx(0.0),float2fx(1.0),float2fx(0.0)); + S3D_PolygonNormal(screen, float2fx(0.0),float2fx(1.0),float2fx(0.0)); - S3D_PolygonVertex(float2fx(0.75),float2fx(0.5),float2fx(0.75)); - S3D_PolygonVertex(float2fx(0.75),float2fx(0.5),float2fx(-0.75)); + S3D_PolygonVertex(screen, float2fx(0.75),float2fx(0.5),float2fx(0.75)); + S3D_PolygonVertex(screen, float2fx(0.75),float2fx(0.5),float2fx(-0.75)); - S3D_PolygonBegin(S3D_QUAD_STRIP); + S3D_PolygonBegin(screen, S3D_QUAD_STRIP); - S3D_PolygonNormal(float2fx(0.0),float2fx(0.0),float2fx(-1.0)); + S3D_PolygonNormal(screen, float2fx(0.0),float2fx(0.0),float2fx(-1.0)); - S3D_PolygonVertex(float2fx(-0.75),float2fx(-1),float2fx(-0.75)); - S3D_PolygonVertex(float2fx(-0.75),float2fx(0.5),float2fx(-0.75)); - S3D_PolygonVertex(float2fx(0.75),float2fx(0.5),float2fx(-0.75)); - S3D_PolygonVertex(float2fx(0.75),float2fx(-1),float2fx(-0.75)); + S3D_PolygonVertex(screen, float2fx(-0.75),float2fx(-1),float2fx(-0.75)); + S3D_PolygonVertex(screen, float2fx(-0.75),float2fx(0.5),float2fx(-0.75)); + S3D_PolygonVertex(screen, float2fx(0.75),float2fx(0.5),float2fx(-0.75)); + S3D_PolygonVertex(screen, float2fx(0.75),float2fx(-1),float2fx(-0.75)); - S3D_PolygonNormal(float2fx(1.0),float2fx(0.0),float2fx(0.0)); + S3D_PolygonNormal(screen, float2fx(1.0),float2fx(0.0),float2fx(0.0)); - S3D_PolygonVertex(float2fx(0.75),float2fx(0.5),float2fx(0.75)); - S3D_PolygonVertex(float2fx(0.75),float2fx(-1),float2fx(0.75)); + S3D_PolygonVertex(screen, float2fx(0.75),float2fx(0.5),float2fx(0.75)); + S3D_PolygonVertex(screen, float2fx(0.75),float2fx(-1),float2fx(0.75)); - S3D_PolygonNormal(float2fx(0.0),float2fx(0.0),float2fx(1.0)); + S3D_PolygonNormal(screen, float2fx(0.0),float2fx(0.0),float2fx(1.0)); - S3D_PolygonVertex(float2fx(-0.75),float2fx(0.5),float2fx(0.75)); - S3D_PolygonVertex(float2fx(-0.75),float2fx(-1),float2fx(0.75)); + S3D_PolygonVertex(screen, float2fx(-0.75),float2fx(0.5),float2fx(0.75)); + S3D_PolygonVertex(screen, float2fx(-0.75),float2fx(-1),float2fx(0.75)); } -void draw_pad(int r, int g, int b) +void draw_pad(int screen, int r, int g, int b) { - S3D_PolygonColor(r,g,b); + S3D_PolygonColor(screen, r,g,b); - S3D_PolygonBegin(S3D_QUAD_STRIP); + S3D_PolygonBegin(screen, S3D_QUAD_STRIP); - S3D_PolygonNormal(float2fx(-1.0),float2fx(0.0),float2fx(0.0)); + S3D_PolygonNormal(screen, float2fx(-1.0),float2fx(0.0),float2fx(0.0)); - S3D_PolygonVertex(float2fx(-2),float2fx(-1),float2fx(-0.5)); - S3D_PolygonVertex(float2fx(-2),float2fx(-1),float2fx(0.5)); - S3D_PolygonVertex(float2fx(-2),float2fx(1),float2fx(0.5)); - S3D_PolygonVertex(float2fx(-2),float2fx(1),float2fx(-0.5)); + S3D_PolygonVertex(screen, float2fx(-2),float2fx(-1),float2fx(-0.5)); + S3D_PolygonVertex(screen, float2fx(-2),float2fx(-1),float2fx(0.5)); + S3D_PolygonVertex(screen, float2fx(-2),float2fx(1),float2fx(0.5)); + S3D_PolygonVertex(screen, float2fx(-2),float2fx(1),float2fx(-0.5)); - S3D_PolygonNormal(float2fx(0.0),float2fx(1.0),float2fx(0.0)); + S3D_PolygonNormal(screen, float2fx(0.0),float2fx(1.0),float2fx(0.0)); - S3D_PolygonVertex(float2fx(2),float2fx(1),float2fx(0.5)); - S3D_PolygonVertex(float2fx(2),float2fx(1),float2fx(-0.5)); + S3D_PolygonVertex(screen, float2fx(2),float2fx(1),float2fx(0.5)); + S3D_PolygonVertex(screen, float2fx(2),float2fx(1),float2fx(-0.5)); - S3D_PolygonBegin(S3D_QUAD_STRIP); + S3D_PolygonBegin(screen, S3D_QUAD_STRIP); - S3D_PolygonNormal(float2fx(0.0),float2fx(0.0),float2fx(-1.0)); + S3D_PolygonNormal(screen, float2fx(0.0),float2fx(0.0),float2fx(-1.0)); - S3D_PolygonVertex(float2fx(-2),float2fx(-1),float2fx(-0.5)); - S3D_PolygonVertex(float2fx(-2),float2fx(1),float2fx(-0.5)); - S3D_PolygonVertex(float2fx(2),float2fx(1),float2fx(-0.5)); - S3D_PolygonVertex(float2fx(2),float2fx(-1),float2fx(-0.5)); + S3D_PolygonVertex(screen, float2fx(-2),float2fx(-1),float2fx(-0.5)); + S3D_PolygonVertex(screen, float2fx(-2),float2fx(1),float2fx(-0.5)); + S3D_PolygonVertex(screen, float2fx(2),float2fx(1),float2fx(-0.5)); + S3D_PolygonVertex(screen, float2fx(2),float2fx(-1),float2fx(-0.5)); - S3D_PolygonNormal(float2fx(1.0),float2fx(0.0),float2fx(0.0)); + S3D_PolygonNormal(screen, float2fx(1.0),float2fx(0.0),float2fx(0.0)); - S3D_PolygonVertex(float2fx(2),float2fx(1),float2fx(0.5)); - S3D_PolygonVertex(float2fx(2),float2fx(-1),float2fx(0.5)); + S3D_PolygonVertex(screen, float2fx(2),float2fx(1),float2fx(0.5)); + S3D_PolygonVertex(screen, float2fx(2),float2fx(-1),float2fx(0.5)); - S3D_PolygonNormal(float2fx(0.0),float2fx(0.0),float2fx(1.0)); + S3D_PolygonNormal(screen, float2fx(0.0),float2fx(0.0),float2fx(1.0)); - S3D_PolygonVertex(float2fx(-2),float2fx(1),float2fx(0.5)); - S3D_PolygonVertex(float2fx(-2),float2fx(-1),float2fx(0.5)); + S3D_PolygonVertex(screen, float2fx(-2),float2fx(1),float2fx(0.5)); + S3D_PolygonVertex(screen, float2fx(-2),float2fx(-1),float2fx(0.5)); } @@ -223,27 +223,30 @@ void Game_DrawBottomScreen(void) _quad_blit_unsafe_24(gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL),bottom_screen_png_bin,0,0,320,240); } -void Game_DrawScene(void) + +void Game_DrawScene(int screen) { + S3D_FramebuffersClearTopScreen(screen, 0,0,0); + //3D Stuff { //--------------------------------------------------- // Configuration //--------------------------------------------------- - S3D_SetCulling(1,0); + S3D_SetCulling(screen, 1,0); m44 m; m44_CreateTranslation(&m,0,int2fx(-2),int2fx(12)); - S3D_ModelviewMatrixSet(&m); + S3D_ModelviewMatrixSet(screen, &m); m44_CreateRotationX(&m,-0x1800); - S3D_ModelviewMatrixMultiply(&m); + S3D_ModelviewMatrixMultiply(screen, &m); - S3D_LightAmbientColorSet(64,64,64); + S3D_LightAmbientColorSet(screen, 64,64,64); - S3D_LightEnable(S3D_LIGHT_N(0)); - S3D_LightDirectionalColorSet(0, 192,192,192); - S3D_LightDirectionalVectorSet(0, float2fx(-0.38),float2fx(-0.76),float2fx(0.53)); + S3D_LightEnable(screen, S3D_LIGHT_N(0)); + S3D_LightDirectionalColorSet(screen, 0, 192,192,192); + S3D_LightDirectionalVectorSet(screen, 0, float2fx(-0.38),float2fx(-0.76),float2fx(0.53)); //--------------------------------------------------- // Draw scenario @@ -252,47 +255,47 @@ void Game_DrawScene(void) // Camera rotation effect... m44_CreateRotationY(&m,pad.x); //m44_create_rotation_axis(&m, angle1, float2fx(0.58), float2fx(0.58), float2fx(0.58)); - S3D_ModelviewMatrixMultiply(&m); + S3D_ModelviewMatrixMultiply(screen, &m); m44_CreateRotationZ(&m,-pad.x); - S3D_ModelviewMatrixMultiply(&m); - - draw_scenario(0,0,255); + S3D_ModelviewMatrixMultiply(screen, &m); + draw_scenario(screen, 0,0,255); + //--------------------------------------------------- // IA //--------------------------------------------------- - S3D_ModelviewMatrixPush(); + S3D_ModelviewMatrixPush(screen); m44_CreateTranslation(&m,pad_ia.x,0,int2fx(10)); - S3D_ModelviewMatrixMultiply(&m); + S3D_ModelviewMatrixMultiply(screen, &m); - draw_pad(255,0,0); + draw_pad(screen, 255,0,0); - S3D_ModelviewMatrixPop(); + S3D_ModelviewMatrixPop(screen); //--------------------------------------------------- // Ball //--------------------------------------------------- - S3D_ModelviewMatrixPush(); + S3D_ModelviewMatrixPush(screen); m44_CreateTranslation(&m,ball.x,0,ball.z); - S3D_ModelviewMatrixMultiply(&m); + S3D_ModelviewMatrixMultiply(screen, &m); - draw_ball(128,128,128); + draw_ball(screen, 128,128,128); - S3D_ModelviewMatrixPop(); + S3D_ModelviewMatrixPop(screen); //--------------------------------------------------- // Player //--------------------------------------------------- - S3D_ModelviewMatrixPush(); + S3D_ModelviewMatrixPush(screen); m44_CreateTranslation(&m,pad.x,0,0); - S3D_ModelviewMatrixMultiply(&m); + S3D_ModelviewMatrixMultiply(screen, &m); /* int keys = hidKeysHeld(); @@ -302,20 +305,21 @@ void Game_DrawScene(void) if(keys & KEY_R) { int i; for(i = 0; i < 5; i++) draw_pad(0,255,0); }; */ - draw_pad(0,255,0); + draw_pad(screen, 0,255,0); - S3D_ModelviewMatrixPop(); + S3D_ModelviewMatrixPop(screen); //--------------------------------------------------- // Flush //--------------------------------------------------- - S3D_PolygonListFlush(1); + S3D_PolygonListFlush(screen, 1); + } //2D stuff { - u8 * buf = S3D_BufferGetCurrent(); + u8 * buf = S3D_BufferGet(screen); /* @@ -354,9 +358,6 @@ void Game_DrawScene(void) } } - - - //------------------------------------------------------------------------------------------------------- void Game_Init(void) diff --git a/source/game.h b/source/game.h index d90a2b8..4372064 100644 --- a/source/game.h +++ b/source/game.h @@ -6,7 +6,7 @@ void Game_DrawBottomScreen(void); -void Game_DrawScene(void); +void Game_DrawScene(int screen); void Game_Init(void); diff --git a/source/main.c b/source/main.c index 5853d95..96344ee 100644 --- a/source/main.c +++ b/source/main.c @@ -15,6 +15,14 @@ #define CONFIG_3D_SLIDERSTATE (*(float*)0x1FF81080) //this should be in ctrulib... +//s32 __svcGetCurrentProcessorNumber(void); + +//------------------------------------------------------------------------------------------------------- + +int SecondaryThreadExit = 0; + +Handle SecondaryThreadHandle, mutex_thread_drawing, mutex_sync_frame; + //------------------------------------------------------------------------------------------------------- static m44 left_screen, right_screen; @@ -46,26 +54,125 @@ static void ProjectionMatricesConfigure(void) static void DrawScreens(void) { - S3D_BufferSetScreen(GFX_LEFT); - S3D_ProjectionMatrixSet(&left_screen); - S3D_PolygonListClear(); - Game_DrawScene(); - S3D_PolygonListFlush(1); + S3D_BuffersSetup(); - float slider = CONFIG_3D_SLIDERSTATE; - if(slider == 0.0f) return; + //---------------------------------------- + + svcWaitSynchronization(mutex_sync_frame, U64_MAX); + svcReleaseMutex(mutex_thread_drawing); + + //---------------------------------------- + + int screen = 0; + S3D_ProjectionMatrixSet(screen, &left_screen); + S3D_PolygonListClear(screen); + Game_DrawScene(screen); + S3D_PolygonListFlush(screen, 1); + + //---------------------------------------- + + svcWaitSynchronization(mutex_thread_drawing, U64_MAX); + svcReleaseMutex(mutex_sync_frame); +} + +//------------------------------------------------------------------------------------------------------- + +void SecondaryThreadFunction(u32 arg) +{ + //Running in CPU 1 + //Con_Print(b,0,60,"Thread 1 CPU: %d",__svcGetCurrentProcessorNumber()); + + Timing_Start(1); + + while(SecondaryThreadExit == 0) + { + while(SecondaryThreadExit == 0) + { + if(svcWaitSynchronization(mutex_thread_drawing, U64_MAX) == 0) break; + } + + if(SecondaryThreadExit) break; + + //---------------------------------------- + + Timing_StartFrame(1); + + float slider = CONFIG_3D_SLIDERSTATE; + if(slider > 0.0f) + { + int screen = 1; + S3D_ProjectionMatrixSet(screen, &right_screen); + S3D_PolygonListClear(screen); + Game_DrawScene(screen); + S3D_PolygonListFlush(screen, 1); + } + + Timing_EndFrame(1); + + //---------------------------------------- + + svcReleaseMutex(mutex_thread_drawing); + + while(SecondaryThreadExit == 0) + { + if(svcWaitSynchronization(mutex_sync_frame, U64_MAX) == 0) break; + } + + svcReleaseMutex(mutex_sync_frame); + } + + svcExitThread(); +} + +#define STACK_SIZE (0x2000) +u64 SecondaryThreadStack[STACK_SIZE/sizeof(u64)]; - S3D_BufferSetScreen(GFX_RIGHT); - S3D_ProjectionMatrixSet(&right_screen); - S3D_PolygonListClear(); - Game_DrawScene(); - S3D_PolygonListFlush(1); +void ThreadInit(void) +{ + int disablecores = 1; // Run on the other CPU only + u32 prio = 0x18; // 0x18 ... 0x3F. Lower is higher. main() is 0x30 + u32 arg = 0; + + s32 val = svcCreateThread(&SecondaryThreadHandle, SecondaryThreadFunction, arg, + (u32*)&(SecondaryThreadStack[STACK_SIZE/sizeof(u64)]), prio, disablecores); + if(val) + { + //error! + } + + val = svcCreateMutex(&mutex_thread_drawing, true); // initially locked + if(val) + { + //error! + } + + val = svcCreateMutex(&mutex_sync_frame, false); // initially released + if(val) + { + //error! + } +} + +void ThreadEnd(void) +{ + SecondaryThreadExit = 1; + + svcReleaseMutex(mutex_thread_drawing); + svcReleaseMutex(mutex_sync_frame); + + svcWaitSynchronization(SecondaryThreadHandle, U64_MAX); + + svcCloseHandle(mutex_thread_drawing); + svcCloseHandle(mutex_sync_frame); + svcCloseHandle(SecondaryThreadHandle); } //------------------------------------------------------------------------------------------------------- int main(int argc, char **argv) { + //Running in CPU 0 + aptInit(); gfxInitDefault(); gfxSet3D(true); //OMG 3D!!!!1!!! @@ -88,7 +195,6 @@ int main(int argc, char **argv) while(aptMainLoop()) { - hidScanInput(); int keys = hidKeysHeld(); if(keys & KEY_A) break; // break in order to return to hbmenu @@ -99,6 +205,7 @@ int main(int argc, char **argv) Con_Print(buf,0,200-1,"(Antonio Niño Díaz)"); Con_Print(buf,0,100,"CPU limit: %d%%",(int)percent); + //Con_Print(buf,0,80,"Thread 0 CPU: %d",__svcGetCurrentProcessorNumber()); Con_Print(buf,0,40,"A: Start."); Con_Print(buf,0,20,"SELECT: Screenshot."); @@ -109,32 +216,30 @@ int main(int argc, char **argv) gspWaitForVBlank(); } - - fast_srand(svcGetSystemTick()); + ThreadInit(); + Game_Init(); - Timing_Start(); + Timing_Start(0); // Main loop while(aptMainLoop()) { - Timing_StartFrame(); + Timing_StartFrame(0); hidScanInput(); int keys = hidKeysHeld(); if(keys & KEY_START) break; // break in order to return to hbmenu - S3D_FramebuffersClearTopScreen(0,0,0); - Game_Handle(keys); u8 * buf = gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL); Con_Print(buf,0,170,"3D Slider: %f ",CONFIG_3D_SLIDERSTATE); - Con_Print(buf,0,150,"FPS: %d ",Timing_GetFPS()); - Con_Print(buf,0,130,"CPU: %d%% ",(int)Timing_GetCPUUsage()); + Con_Print(buf,0,150,"FPS: %d %d ",Timing_GetFPS(0),Timing_GetFPS(1)); + Con_Print(buf,0,130,"CPU: %d%% %d%% ",(int)Timing_GetCPUUsage(0),(int)Timing_GetCPUUsage(1)); ProjectionMatricesConfigure(); DrawScreens(); @@ -148,12 +253,14 @@ int main(int argc, char **argv) //PNGScreenshot_Bottom(); } - Timing_EndFrame(); + Timing_EndFrame(0); gspWaitForVBlank(); } Game_End(); + + ThreadEnd(); gfxExit(); aptExit(); diff --git a/source/polygon.c b/source/polygon.c index 01e5b9e..a23e428 100644 --- a/source/polygon.c +++ b/source/polygon.c @@ -18,21 +18,22 @@ typedef struct { int r,g,b; } _poly_list_t; -static _poly_list_t List[MAX_POLYGONS_IN_LIST]; -static int polygon_number = 0; +static _poly_list_t List[2][MAX_POLYGONS_IN_LIST]; +static int polygon_number[2] = { 0, 0 }; //--------------------------------------------------------------------------------------- -void S3D_PolygonListClear(void) +void S3D_PolygonListClear(int screen) { - polygon_number = 0; + polygon_number[screen] = 0; } //--------------------------------------------------------------------------------------- -void _s3d_polygon_list_add_dot(v4 * a, int _r, int _g, int _b) +void _s3d_polygon_list_add_dot(int screen, v4 * a, int _r, int _g, int _b) { - _poly_list_t * e = &(List[polygon_number++]); + _poly_list_t * e = &(List[screen][polygon_number[screen]]); + polygon_number[screen]++; e->type = S3D_DOTS; int i; @@ -46,9 +47,10 @@ void _s3d_polygon_list_add_dot(v4 * a, int _r, int _g, int _b) e->r = _r; e->g = _g; e->b = _b; } -void _s3d_polygon_list_add_line(v4 * a, v4 * b, int _r, int _g, int _b) +void _s3d_polygon_list_add_line(int screen, v4 * a, v4 * b, int _r, int _g, int _b) { - _poly_list_t * e = &(List[polygon_number++]); + _poly_list_t * e = &(List[screen][polygon_number[screen]]); + polygon_number[screen]++; e->type = S3D_LINES; int i; @@ -64,9 +66,10 @@ void _s3d_polygon_list_add_line(v4 * a, v4 * b, int _r, int _g, int _b) e->r = _r; e->g = _g; e->b = _b; } -void _s3d_polygon_list_add_triangle(v4 * a, v4 * b, v4 * c, int _r, int _g, int _b) +void _s3d_polygon_list_add_triangle(int screen, v4 * a, v4 * b, v4 * c, int _r, int _g, int _b) { - _poly_list_t * e = &(List[polygon_number++]); + _poly_list_t * e = &(List[screen][polygon_number[screen]]); + polygon_number[screen]++; e->type = S3D_TRIANGLES; int i; @@ -83,9 +86,10 @@ void _s3d_polygon_list_add_triangle(v4 * a, v4 * b, v4 * c, int _r, int _g, int e->r = _r; e->g = _g; e->b = _b; } -void _s3d_polygon_list_add_quad(v4 * a, v4 * b, v4 * c, v4 * d, int _r, int _g, int _b) +void _s3d_polygon_list_add_quad(int screen, v4 * a, v4 * b, v4 * c, v4 * d, int _r, int _g, int _b) { - _poly_list_t * e = &(List[polygon_number++]); + _poly_list_t * e = &(List[screen][polygon_number[screen]]); + polygon_number[screen]++; e->type = S3D_QUADS; int i; @@ -106,10 +110,10 @@ void _s3d_polygon_list_add_quad(v4 * a, v4 * b, v4 * c, v4 * d, int _r, int _g, //--------------------------------------------------------------------------------------- //In draw.c -void _s3d_draw_dot(int x, int y, int r, int g, int b); -void _s3d_draw_line(int x1, int y1, int x2, int y2, int r, int g, int b); -void _s3d_draw_triangle(int x1, int y1, int x2, int y2, int x3, int y3, int r, int g, int b); -void _s3d_draw_quad(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4, int r, int g, int b); +void _s3d_draw_dot(int screen, int x, int y, int r, int g, int b); +void _s3d_draw_line(int screen, int x1, int y1, int x2, int y2, int r, int g, int b); +void _s3d_draw_triangle(int screen, int x1, int y1, int x2, int y2, int x3, int y3, int r, int g, int b); +void _s3d_draw_quad(int screen, int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4, int r, int g, int b); //--------------------------------------------------------------------------------------- @@ -120,34 +124,38 @@ static int _s3d_sort_poly_list_compare_function(const void * p1, const void * p2 return z1 - z2; } -void S3D_PolygonListFlush(int perform_z_sort) +void S3D_PolygonListFlush(int screen, int perform_z_sort) { if(perform_z_sort) - qsort((void*)List, polygon_number, sizeof(_poly_list_t), _s3d_sort_poly_list_compare_function); + qsort((void*)&(List[screen]), polygon_number[screen], sizeof(_poly_list_t), _s3d_sort_poly_list_compare_function); int i; - for(i = 0; i < polygon_number; i++) + for(i = 0; i < polygon_number[screen]; i++) { - _poly_list_t * e = &(List[i]); + _poly_list_t * e = &(List[screen][i]); switch(e->type) { case S3D_DOTS: - _s3d_draw_dot(e->v[0][0],e->v[0][1], + _s3d_draw_dot(screen, + e->v[0][0],e->v[0][1], e->r,e->g,e->b); break; case S3D_LINES: - _s3d_draw_line(e->v[0][0],e->v[0][1], e->v[1][0],e->v[1][1], + _s3d_draw_line(screen, + e->v[0][0],e->v[0][1], e->v[1][0],e->v[1][1], e->r,e->g,e->b); break; case S3D_TRIANGLES: - _s3d_draw_triangle(e->v[0][0],e->v[0][1], e->v[1][0],e->v[1][1], e->v[2][0],e->v[2][1], + _s3d_draw_triangle(screen, + e->v[0][0],e->v[0][1], e->v[1][0],e->v[1][1], e->v[2][0],e->v[2][1], e->r,e->g,e->b); break; case S3D_QUADS: - _s3d_draw_quad(e->v[0][0],e->v[0][1], e->v[1][0],e->v[1][1], e->v[2][0],e->v[2][1], e->v[3][0],e->v[3][1], + _s3d_draw_quad(screen, + e->v[0][0],e->v[0][1], e->v[1][0],e->v[1][1], e->v[2][0],e->v[2][1], e->v[3][0],e->v[3][1], e->r,e->g,e->b); break; @@ -156,7 +164,7 @@ void S3D_PolygonListFlush(int perform_z_sort) } } - polygon_number = 0; + polygon_number[screen] = 0; } //--------------------------------------------------------------------------------------- diff --git a/source/polygon.h b/source/polygon.h index 67f8524..5861cb7 100644 --- a/source/polygon.h +++ b/source/polygon.h @@ -4,9 +4,9 @@ //-------------------------------------------------------------------------------------------------- -void S3D_PolygonListClear(void); +void S3D_PolygonListClear(int screen); -void S3D_PolygonListFlush(int perform_z_sort); +void S3D_PolygonListFlush(int screen, int perform_z_sort); //-------------------------------------------------------------------------------------------------- diff --git a/source/syscalls.s b/source/syscalls.s new file mode 100644 index 0000000..539bbec --- /dev/null +++ b/source/syscalls.s @@ -0,0 +1,8 @@ +.arm +.align 4 + +.global __svcGetCurrentProcessorNumber +.type __svcGetCurrentProcessorNumber, %function +__svcGetCurrentProcessorNumber: + svc 0x11 + bx lr diff --git a/source/utils.c b/source/utils.c index 7684aad..77e992b 100644 --- a/source/utils.c +++ b/source/utils.c @@ -14,44 +14,46 @@ #define TICKS_PER_SEC (268123480) #define TICKS_PER_VBL (268123480/60) -int frame_count; -u64 last_ticks = 0; -int _FPS = 0; -u64 cpu_last_ticks = 0; -float _CPU = 0; +#define MAX_CORES (2) -void Timing_Start(void) +int frame_count[MAX_CORES] = { 0, 0 }; +u64 last_ticks[MAX_CORES] = { 0, 0 }; +int _FPS[MAX_CORES] = { 0, 0 }; +u64 cpu_last_ticks[MAX_CORES] = { 0, 0 }; +float _CPU[MAX_CORES] = { 0, 0 }; + +void Timing_Start(int cpu_core) { - last_ticks = svcGetSystemTick(); + last_ticks[cpu_core] = svcGetSystemTick(); } -void Timing_EndFrame(void) +void Timing_EndFrame(int cpu_core) { - frame_count ++; - u64 inc_ticks = svcGetSystemTick() - cpu_last_ticks; - _CPU = (float)inc_ticks*((float)100.0f/(float)TICKS_PER_VBL); + frame_count[cpu_core] ++; + u64 inc_ticks = svcGetSystemTick() - cpu_last_ticks[cpu_core]; + _CPU[cpu_core] = (float)inc_ticks*((float)100.0f/(float)TICKS_PER_VBL); } -void Timing_StartFrame(void) +void Timing_StartFrame(int cpu_core) { - if(svcGetSystemTick() >= last_ticks + TICKS_PER_SEC) + if(svcGetSystemTick() >= last_ticks[cpu_core] + TICKS_PER_SEC) { - last_ticks += TICKS_PER_SEC; - _FPS = frame_count; - frame_count = 0; + last_ticks[cpu_core] += TICKS_PER_SEC; + _FPS[cpu_core] = frame_count[cpu_core]; + frame_count[cpu_core] = 0; } - cpu_last_ticks = svcGetSystemTick(); + cpu_last_ticks[cpu_core] = svcGetSystemTick(); } -int Timing_GetFPS(void) +int Timing_GetFPS(int cpu_core) { - return _FPS; + return _FPS[cpu_core]; } -float Timing_GetCPUUsage(void) +float Timing_GetCPUUsage(int cpu_core) { - return _CPU; + return _CPU[cpu_core]; } diff --git a/source/utils.h b/source/utils.h index 7d8d178..a7e1c5f 100644 --- a/source/utils.h +++ b/source/utils.h @@ -8,11 +8,11 @@ //---------------------------------------------------------------------------------- -void Timing_Start(void); -void Timing_EndFrame(void); -void Timing_StartFrame(void); -int Timing_GetFPS(void); -float Timing_GetCPUUsage(void); +void Timing_Start(int cpu_core); +void Timing_EndFrame(int cpu_core); +void Timing_StartFrame(int cpu_core); +int Timing_GetFPS(int cpu_core); +float Timing_GetCPUUsage(int cpu_core); //---------------------------------------------------------------------------------- diff --git a/template.pnproj b/template.pnproj index b0d6e08..165ead1 100644 --- a/template.pnproj +++ b/template.pnproj @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file