diff --git a/libs/sf2dlib/.gitignore b/libs/sf2dlib/.gitignore index e1071b6..a020760 100644 --- a/libs/sf2dlib/.gitignore +++ b/libs/sf2dlib/.gitignore @@ -1,2 +1,7 @@ -libsf2d/build/ -libsf2d/lib/ \ No newline at end of file +*.d +*.o +*.project +*.cproject +libsf2d/.settings/* +libsf2d/build/* +libsf2d/lib/* diff --git a/libs/sf2dlib/libsf2d/Makefile b/libs/sf2dlib/libsf2d/Makefile index 14e1112..28ccec1 100644 --- a/libs/sf2dlib/libsf2d/Makefile +++ b/libs/sf2dlib/libsf2d/Makefile @@ -30,6 +30,7 @@ CFLAGS := -g -Wall -O2\ $(ARCH) CFLAGS += $(INCLUDE) -DARM11 -D_3DS +#CFLAGS += -std=c11 #WILL HAVE TO BE REMOVED SOON CFLAGS += -DLIBCTRU_NO_DEPRECATION @@ -138,6 +139,8 @@ $(OUTPUT) : $(OFILES) @echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h @echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h +sf2d.c: shader.vsh + -include $(DEPENDS) #--------------------------------------------------------------------------------------- diff --git a/libs/sf2dlib/libsf2d/include/sf2d.h b/libs/sf2dlib/libsf2d/include/sf2d.h index 6385b83..f282d4f 100644 --- a/libs/sf2dlib/libsf2d/include/sf2d.h +++ b/libs/sf2dlib/libsf2d/include/sf2d.h @@ -4,7 +4,6 @@ * @date 22 March 2015 * @brief sf2dlib header */ - #ifndef SF2D_H #define SF2D_H @@ -136,6 +135,11 @@ typedef struct { void *data; /**< Pointer to the data */ } sf2d_texture; +typedef struct { + sf2d_texture texture; // "inherit"/extend standard texture + float projection[4*4]; /**< Orthographic projection matrix for this target */ +} sf2d_rendertarget; + // Basic functions /** @@ -171,6 +175,12 @@ void sf2d_set_3D(int enable); */ void sf2d_start_frame(gfxScreen_t screen, gfx3dSide_t side); +/** + * @brief Starts a frame bound to a rendertarget + * @param target rendertarget to draw to + */ +void sf2d_start_frame_target(sf2d_rendertarget *target); + /** * @brief Ends a frame, should be called on pair with sf2d_start_frame */ @@ -239,9 +249,10 @@ void sf2d_set_clear_color(u32 color); * @param y0 y coordinate of the first dot * @param x1 x coordinate of the second dot * @param y1 y coordinate of the sceond dot + * @param width thickness of the line * @param color the color to draw the line */ -void sf2d_draw_line(int x0, int y0, int x1, int y1, u32 color); + void sf2d_draw_line(float x0, float y0, float x1, float y1, float width, u32 color); /** * @brief Draws a rectangle @@ -292,12 +303,37 @@ void sf2d_draw_fill_circle(int x, int y, int radius, u32 color); */ sf2d_texture *sf2d_create_texture(int width, int height, sf2d_texfmt pixel_format, sf2d_place place); +/** + * @brief Creates an empty rendertarget. + * Functions similarly to sf2d_create_texture. + * @param width the width of the texture + * @param height the height of the texture + * @return a pointer to the newly created rendertarget + * @note Before drawing the texture, it needs to be tiled + * by calling sf2d_texture_tile32. + * The default texture params are both min and mag filters + * GPU_NEAREST, and both S and T wrappings GPU_CLAMP_TO_BORDER. + */ +sf2d_rendertarget *sf2d_create_rendertarget(int width, int height); + /** * @brief Frees a texture * @param texture pointer to the texture to freeze */ void sf2d_free_texture(sf2d_texture *texture); +/** + * @brief Frees a rendertarget + * @param target pointer to the rendertarget to free + */ +void sf2d_free_target(sf2d_rendertarget *target); + +/** + * @brief Clears a rendertarget to the specified color + * @param target pointer to the rendertarget to clear + */ +void sf2d_clear_target(sf2d_rendertarget *target, u32 color); + /** * @brief Fills an already allocated texture from a RGBA8 source * @param dst pointer to the destination texture to fill @@ -419,6 +455,33 @@ void sf2d_draw_texture_rotate(const sf2d_texture *texture, int x, int y, float r */ void sf2d_draw_texture_rotate_blend(const sf2d_texture *texture, int x, int y, float rad, u32 color); +/** + * @brief Draws a scaled texture with rotation around its hotspot + * @param texture the texture to draw + * @param x the x coordinate to draw the texture to + * @param y the y coordinate to draw the texture to + * @param rad rotation (in radians) to draw the texture + * @param x_scale the x scale + * @param y_scale the y scale + * @param center_x the x position of the hotspot + * @param center_y the y position of the hotspot + */ +void sf2d_draw_texture_rotate_scale_hotspot(const sf2d_texture *texture, int x, int y, float rad, float scale_x, float scale_y, float center_x, float center_y); + +/** + * @brief Draws a scaled texture with rotation around its hotspot with color + * @param texture the texture to draw + * @param x the x coordinate to draw the texture to + * @param y the y coordinate to draw the texture to + * @param rad rotation (in radians) to draw the texture + * @param x_scale the x scale + * @param y_scale the y scale + * @param center_x the x position of the hotspot + * @param center_y the y position of the hotspot + * @param color the color to blend with the texture + */ +void sf2d_draw_texture_rotate_scale_hotspot_blend(const sf2d_texture *texture, int x, int y, float rad, float scale_x, float scale_y, float center_x, float center_y, u32 color); + /** * @brief Draws a part of a texture * @param texture the texture to draw diff --git a/libs/sf2dlib/libsf2d/source/sf2d.c b/libs/sf2dlib/libsf2d/source/sf2d.c index be9e4aa..0b76e62 100644 --- a/libs/sf2dlib/libsf2d/source/sf2d.c +++ b/libs/sf2dlib/libsf2d/source/sf2d.c @@ -1,3 +1,4 @@ +#include #include "sf2d.h" #include "sf2d_private.h" #include "shader_vsh_shbin.h" @@ -32,6 +33,10 @@ static u32 projection_desc = -1; //Matrix static float ortho_matrix_top[4*4]; static float ortho_matrix_bot[4*4]; +//Rendertarget things +static sf2d_rendertarget * currentRenderTarget = NULL; +static void * targetDepthBuffer; +static int targetDepthBufferLen = 0; //Apt hook cookie static aptHookCookie apt_hook_cookie; //Functions @@ -111,6 +116,7 @@ int sf2d_fini() linearFree(gpu_cmd); vramFree(gpu_fb_addr); vramFree(gpu_depth_fb_addr); + linearFree(targetDepthBuffer); sf2d_initialized = 0; @@ -173,6 +179,53 @@ void sf2d_start_frame(gfxScreen_t screen, gfx3dSide_t side) GPU_SetDummyTexEnv(5); } +void sf2d_start_frame_target(sf2d_rendertarget *target) +{ + sf2d_pool_reset(); + GPUCMD_SetBufferOffset(0); + + // Upload saved uniform + matrix_gpu_set_uniform(target->projection, projection_desc); + + int bufferLen = target->texture.width * target->texture.height * 4; // apparently depth buffer is (or can be) 32bit? + if (bufferLen > targetDepthBufferLen) { // expand depth buffer + if (targetDepthBufferLen > 0) linearFree(targetDepthBuffer); + targetDepthBuffer = linearAlloc(bufferLen); + memset(targetDepthBuffer, 0, bufferLen); + targetDepthBufferLen = bufferLen; + } + + GPU_SetViewport((u32 *)osConvertVirtToPhys(targetDepthBuffer), + (u32 *)osConvertVirtToPhys(target->texture.data), + 0, 0, target->texture.height, target->texture.width); + + currentRenderTarget = target; + + GPU_DepthMap(-1.0f, 0.0f); + GPU_SetFaceCulling(GPU_CULL_NONE); + GPU_SetStencilTest(false, GPU_ALWAYS, 0x00, 0xFF, 0x00); + GPU_SetStencilOp(GPU_STENCIL_KEEP, GPU_STENCIL_KEEP, GPU_STENCIL_KEEP); + GPU_SetBlendingColor(0,0,0,0); + GPU_SetDepthTestAndWriteMask(true, GPU_GEQUAL, GPU_WRITE_ALL); + GPUCMD_AddMaskedWrite(GPUREG_EARLYDEPTH_TEST1, 0x1, 0); + GPUCMD_AddWrite(GPUREG_EARLYDEPTH_TEST2, 0); + + GPU_SetAlphaBlending( + GPU_BLEND_ADD, + GPU_BLEND_ADD, + GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, + GPU_ONE, GPU_ZERO + ); + + GPU_SetAlphaTest(false, GPU_ALWAYS, 0x00); + + GPU_SetDummyTexEnv(1); + GPU_SetDummyTexEnv(2); + GPU_SetDummyTexEnv(3); + GPU_SetDummyTexEnv(4); + GPU_SetDummyTexEnv(5); +} + void sf2d_end_frame() { GPU_FinishDrawing(); @@ -180,23 +233,30 @@ void sf2d_end_frame() GPUCMD_FlushAndRun(); gspWaitForP3D(); - //Copy the GPU rendered FB to the screen FB - if (cur_screen == GFX_TOP) { - GX_DisplayTransfer(gpu_fb_addr, GX_BUFFER_DIM(240, 400), - (u32 *)gfxGetFramebuffer(GFX_TOP, cur_side, NULL, NULL), - GX_BUFFER_DIM(240, 400), 0x1000); - } else { - GX_DisplayTransfer(gpu_fb_addr, GX_BUFFER_DIM(240, 320), - (u32 *)gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL), - GX_BUFFER_DIM(240, 320), 0x1000); - } - gspWaitForPPF(); + if (!currentRenderTarget) { + //Copy the GPU rendered FB to the screen FB + if (cur_screen == GFX_TOP) { + GX_DisplayTransfer(gpu_fb_addr, GX_BUFFER_DIM(240, 400), + (u32 *)gfxGetFramebuffer(GFX_TOP, cur_side, NULL, NULL), + GX_BUFFER_DIM(240, 400), 0x1000); + } else { + GX_DisplayTransfer(gpu_fb_addr, GX_BUFFER_DIM(240, 320), + (u32 *)gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL), + GX_BUFFER_DIM(240, 320), 0x1000); + } + gspWaitForPPF(); - //Clear the screen - GX_MemoryFill( - gpu_fb_addr, clear_color, &gpu_fb_addr[240*400], GX_FILL_TRIGGER | GX_FILL_32BIT_DEPTH, - gpu_depth_fb_addr, 0, &gpu_depth_fb_addr[240*400], GX_FILL_TRIGGER | GX_FILL_32BIT_DEPTH); - gspWaitForPSC0(); + //Clear the screen + GX_MemoryFill( + gpu_fb_addr, clear_color, &gpu_fb_addr[240*400], GX_FILL_TRIGGER | GX_FILL_32BIT_DEPTH, + gpu_depth_fb_addr, 0, &gpu_depth_fb_addr[240*400], GX_FILL_TRIGGER | GX_FILL_32BIT_DEPTH); + gspWaitForPSC0(); + } else { + //gspWaitForPPF(); + //gspWaitForPSC0(); + sf2d_texture_tile32(&(currentRenderTarget->texture)); + } + currentRenderTarget = NULL; } void sf2d_swapbuffers() diff --git a/libs/sf2dlib/libsf2d/source/sf2d_draw.c b/libs/sf2dlib/libsf2d/source/sf2d_draw.c index 28ef34b..59a792e 100644 --- a/libs/sf2dlib/libsf2d/source/sf2d_draw.c +++ b/libs/sf2dlib/libsf2d/source/sf2d_draw.c @@ -2,15 +2,36 @@ #include "sf2d_private.h" #include -void sf2d_draw_line(int x0, int y0, int x1, int y1, u32 color) +#ifndef M_PI +#define M_PI (3.14159265358979323846) +#endif + +void sf2d_draw_line(float x0, float y0, float x1, float y1, float width, u32 color) { sf2d_vertex_pos_col *vertices = sf2d_pool_memalign(4 * sizeof(sf2d_vertex_pos_col), 8); if (!vertices) return; - vertices[0].position = (sf2d_vector_3f){(float)x0+1.0f, (float)y0+1.0f, SF2D_DEFAULT_DEPTH}; - vertices[1].position = (sf2d_vector_3f){(float)x0-1.0f, (float)y0-1.0f, SF2D_DEFAULT_DEPTH}; - vertices[2].position = (sf2d_vector_3f){(float)x1+1.0f, (float)y1+1.0f, SF2D_DEFAULT_DEPTH}; - vertices[3].position = (sf2d_vector_3f){(float)x1-1.0f, (float)y1-1.0f, SF2D_DEFAULT_DEPTH}; + float dx = x1 - x0; + float dy = y1 - y0; + + float nx = -dy; + float ny = dx; + + float len = sqrt(nx * nx + ny * ny); + + if (len > 0 ){ + nx /= len; + ny /= len; + } + + nx *= width*0.5f; + ny *= width*0.5f; + + vertices[0].position = (sf2d_vector_3f){x0+nx, y0+ny, SF2D_DEFAULT_DEPTH}; + vertices[1].position = (sf2d_vector_3f){x0-nx, y0-ny, SF2D_DEFAULT_DEPTH}; + + vertices[2].position = (sf2d_vector_3f){x1+nx, y1+ny, SF2D_DEFAULT_DEPTH}; + vertices[3].position = (sf2d_vector_3f){x1-nx, y1-ny, SF2D_DEFAULT_DEPTH}; vertices[0].color = color; vertices[1].color = vertices[0].color; diff --git a/libs/sf2dlib/libsf2d/source/sf2d_private.c b/libs/sf2dlib/libsf2d/source/sf2d_private.c index 073c437..30b0ed8 100644 --- a/libs/sf2dlib/libsf2d/source/sf2d_private.c +++ b/libs/sf2dlib/libsf2d/source/sf2d_private.c @@ -2,6 +2,10 @@ #include #include "sf2d_private.h" +#ifndef M_PI +#define M_PI (3.14159265358979323846) +#endif + //stolen from staplebutt void GPU_SetDummyTexEnv(u8 num) { diff --git a/libs/sf2dlib/libsf2d/source/sf2d_texture.c b/libs/sf2dlib/libsf2d/source/sf2d_texture.c index df314a9..13345e9 100644 --- a/libs/sf2dlib/libsf2d/source/sf2d_texture.c +++ b/libs/sf2dlib/libsf2d/source/sf2d_texture.c @@ -4,6 +4,10 @@ #include "sf2d.h" #include "sf2d_private.h" +#ifndef M_PI +#define M_PI (3.14159265358979323846) +#endif + #define TEX_MIN_SIZE 8 static unsigned int nibbles_per_pixel(sf2d_texfmt format) @@ -93,6 +97,22 @@ sf2d_texture *sf2d_create_texture(int width, int height, sf2d_texfmt pixel_forma return texture; } +sf2d_rendertarget *sf2d_create_rendertarget(int width, int height) +{ + sf2d_texture *tx = sf2d_create_texture(width, height, TEXFMT_RGBA8, SF2D_PLACE_RAM); + sf2d_rendertarget *rt = malloc(sizeof(*rt)); + //memcpy(rt, tx, sizeof(*tx)); + rt->texture = *tx; + free(tx); + //tx = * rt->texture; + //rt->projection + + matrix_init_orthographic(rt->projection, 0.0f, width, height, 0.0f, 0.0f, 1.0f); + matrix_rotate_z(rt->projection, M_PI / 2.0f); + + return rt; +} + void sf2d_free_texture(sf2d_texture *texture) { if (texture) { @@ -105,6 +125,27 @@ void sf2d_free_texture(sf2d_texture *texture) } } +void sf2d_free_target(sf2d_rendertarget *target) +{ + sf2d_free_texture(&(target->texture)); + //free(target); // unnecessary since the texture is the start of the target struct +} + +void sf2d_clear_target(sf2d_rendertarget *target, u32 color) { + if (color == 0) { // if fully transparent, take a shortcut + memset(target->texture.data, 0, target->texture.width * target->texture.height * 4); + sf2d_texture_tile32(&(target->texture)); + return; + } + + color = ((color>>24)&0x000000FF) | ((color>>8)&0x0000FF00) | ((color<<8)&0x00FF0000) | ((color<<24)&0xFF000000); // reverse byte order + + int itarget = target->texture.width * target->texture.height; + for (int i = 0; i < itarget; i++) { memcpy(target->texture.data + i*4, &color, 4); } + + sf2d_texture_tile32(&(target->texture)); +} + void sf2d_fill_texture_from_RGBA8(sf2d_texture *dst, const void *rgba8, int source_w, int source_h) { // TODO: add support for non-RGBA8 textures @@ -344,6 +385,75 @@ void sf2d_draw_texture_rotate_blend(const sf2d_texture *texture, int x, int y, f color); } +static inline void sf2d_draw_texture_rotate_scale_hotspot_generic(const sf2d_texture *texture, int x, int y, float rad, float scale_x, float scale_y, float center_x, float center_y) +{ + sf2d_vertex_pos_tex *vertices = sf2d_pool_memalign(4 * sizeof(sf2d_vertex_pos_tex), 8); + if (!vertices) return; + + const float w = texture->width; + const float h = texture->height; + + vertices[0].position.x = -center_x * scale_x; + vertices[0].position.y = -center_y * scale_y; + vertices[0].position.z = SF2D_DEFAULT_DEPTH; + + vertices[1].position.x = (w - center_x) * scale_x; + vertices[1].position.y = -center_y * scale_y; + vertices[1].position.z = SF2D_DEFAULT_DEPTH; + + vertices[2].position.x = -center_x * scale_x; + vertices[2].position.y = (h - center_y) * scale_y; + vertices[2].position.z = SF2D_DEFAULT_DEPTH; + + vertices[3].position.x = (w - center_x) * scale_x; + vertices[3].position.y = h - center_y * scale_y; + vertices[3].position.z = SF2D_DEFAULT_DEPTH; + + float u = w/(float)texture->pow2_w; + float v = h/(float)texture->pow2_h; + + vertices[0].texcoord = (sf2d_vector_2f){0.0f, 0.0f}; + vertices[1].texcoord = (sf2d_vector_2f){u, 0.0f}; + vertices[2].texcoord = (sf2d_vector_2f){0.0f, v}; + vertices[3].texcoord = (sf2d_vector_2f){u, v}; + + const float c = cosf(rad); + const float s = sinf(rad); + int i; + for (i = 0; i < 4; ++i) { // Rotate and translate + float _x = vertices[i].position.x; + float _y = vertices[i].position.y; + vertices[i].position.x = _x*c - _y*s + x; + vertices[i].position.y = _x*s + _y*c + y; + } + + GPU_SetAttributeBuffers( + 2, // number of attributes + (u32*)osConvertVirtToPhys(vertices), + GPU_ATTRIBFMT(0, 3, GPU_FLOAT) | GPU_ATTRIBFMT(1, 2, GPU_FLOAT), + 0xFFFC, //0b1100 + 0x10, + 1, //number of buffers + (u32[]){0x0}, // buffer offsets (placeholders) + (u64[]){0x10}, // attribute permutations for each buffer + (u8[]){2} // number of attributes for each buffer + ); + + GPU_DrawArray(GPU_TRIANGLE_STRIP, 0, 4); +} + +void sf2d_draw_texture_rotate_scale_hotspot(const sf2d_texture *texture, int x, int y, float rad, float scale_x, float scale_y, float center_x, float center_y) +{ + sf2d_bind_texture(texture, GPU_TEXUNIT0); + sf2d_draw_texture_rotate_scale_hotspot_generic(texture, x, y, rad, scale_x, scale_y, center_x, center_y); +} + +void sf2d_draw_texture_rotate_scale_hotspot_blend(const sf2d_texture *texture, int x, int y, float rad, float scale_x, float scale_y, float center_x, float center_y, u32 color) +{ + sf2d_bind_texture_color(texture, GPU_TEXUNIT0, color); + sf2d_draw_texture_rotate_scale_hotspot_generic(texture, x, y, rad, scale_x, scale_y, center_x, center_y); +} + static inline void sf2d_draw_texture_part_generic(const sf2d_texture *texture, int x, int y, int tex_x, int tex_y, int tex_w, int tex_h) { sf2d_vertex_pos_tex *vertices = sf2d_pool_memalign(4 * sizeof(sf2d_vertex_pos_tex), 8); diff --git a/sdcard/3ds/ctruLua/examples/example.lua b/sdcard/3ds/ctruLua/examples/example.lua index b85c187..1c2a307 100644 --- a/sdcard/3ds/ctruLua/examples/example.lua +++ b/sdcard/3ds/ctruLua/examples/example.lua @@ -8,7 +8,7 @@ local dMul = 1 local angle = 0 -local texture1 = gfx.texture.load("sdmc:/3ds/ctruLua/icon.png"); +local texture1 = gfx.texture.load(ctr.root.."icon.png"); if not texture1 then error("Giants ducks came from another planet") end gfx.color.setBackground(gfx.color.RGBA8(200, 200, 200)) @@ -29,7 +29,7 @@ local function drawStuffIn3D(eye) gfx.color.setDefault(0xFF0000FF) gfx.rectangle(x + d(10*math.sin(ctr.time()/500)), y, 20, 20, angle) - gfx.line(50 + d(-6), 50, 75 + d(4), 96, gfx.color.RGBA8(52, 10, 65)) + gfx.line(50 + d(-6), 50, 75 + d(4), 96, 1, gfx.color.RGBA8(52, 10, 65)) gfx.circle(125 + d(-8), 125, 16) end diff --git a/source/ctr.c b/source/ctr.c index db919dc..49c93ba 100644 --- a/source/ctr.c +++ b/source/ctr.c @@ -182,7 +182,7 @@ struct { char *name; void (*load)(lua_State *L); void (*unload)(lua_State *L); } { "apt", load_apt_lib, NULL }, { "mic", load_mic_lib, NULL }, { "thread", load_thread_lib, NULL }, - { NULL, NULL } + { NULL, NULL, NULL } }; int luaopen_ctr_lib(lua_State *L) { diff --git a/source/gfx.c b/source/gfx.c index f356eaa..23a5faf 100644 --- a/source/gfx.c +++ b/source/gfx.c @@ -4,6 +4,8 @@ The `gfx` module. @usage local gfx = require("ctr.gfx") */ #include +#include +#include #include #include @@ -15,6 +17,11 @@ The `gfx` module. #include #include "font.h" +#include "texture.h" + +typedef struct { + sf2d_rendertarget *target; +} target_userdata; bool isGfxInitialized = false; bool is3DEnabled = false; //TODO: add a function for this in the ctrulib/sf2dlib. @@ -51,17 +58,23 @@ The `ctr.gfx.map` module. void load_map_lib(lua_State *L); /*** -Start drawing to a screen. +Start drawing to a screen/target. Must be called before any draw operation. @function start -@tparam number screen the screen to draw to (`gfx.TOP` or `gfx.BOTTOM`) +@tparam number/target screen the screen or target to draw to (`gfx.TOP`, `gfx.BOTTOM`, or render target) @tparam[opt=gfx.LEFT] number eye the eye to draw to (`gfx.LEFT` or `gfx.RIGHT`) */ static int gfx_start(lua_State *L) { - u8 screen = luaL_checkinteger(L, 1); - u8 eye = luaL_optinteger(L, 2, GFX_LEFT); + if (lua_isinteger(L, 1)) { + u8 screen = luaL_checkinteger(L, 1); + u8 eye = luaL_optinteger(L, 2, GFX_LEFT); - sf2d_start_frame(screen, eye); + sf2d_start_frame(screen, eye); + } else if (lua_isuserdata(L, 1)) { + target_userdata *target = luaL_checkudata(L, 1, "LTarget"); + + sf2d_start_frame_target(target->target); + } return 0; } @@ -170,6 +183,7 @@ Draw a line on the current screen. @tparam integer y1 line's starting point vertical coordinate, in pixels @tparam integer x2 line's endpoint horizontal coordinate, in pixels @tparam integer y2 line's endpoint vertical coordinate, in pixels +@tparam[opt=1] number width line's thickness, in pixels @tparam[opt=default color] integer color drawing color */ static int gfx_line(lua_State *L) { @@ -177,10 +191,11 @@ static int gfx_line(lua_State *L) { int y1 = luaL_checkinteger(L, 2); int x2 = luaL_checkinteger(L, 3); int y2 = luaL_checkinteger(L, 4); + float width = luaL_optnumber(L, 5, 1.0f); - u32 color = luaL_optinteger(L, 5, color_default); + u32 color = luaL_optinteger(L, 6, color_default); - sf2d_draw_line(x1, y1, x2, y2, color); + sf2d_draw_line(x1, y1, x2, y2, width, color); return 0; } @@ -404,6 +419,111 @@ static int gfx_scissor(lua_State *L) { return 0; } +/*** +__Work in progress__. Create a render target. Don't use it. +@function target +@tparam integer width +@tparam integer height +@treturn target +*/ +static int gfx_target(lua_State *L) { + int width = luaL_checkinteger(L, 1); + int height = luaL_checkinteger(L, 2); + int wpo2 = 0, hpo2 = 0; + for (;width>pow(2,wpo2);wpo2++); + width = pow(2,wpo2); + for (;height>pow(2,hpo2);hpo2++); + height = pow(2,hpo2); + + target_userdata *target; + target = (target_userdata*)lua_newuserdata(L, sizeof(*target)); + + luaL_getmetatable(L, "LTarget"); + lua_setmetatable(L, -2); + + target->target = sf2d_create_rendertarget(width, height); + + return 1; +} + +/*** +Render targets +@section target +*/ + +/*** +Clear a target to a specified color. +@function :clear +@tparam[opt=default color] integer color color to fill the target with +*/ +static int gfx_target_clear(lua_State *L) { + target_userdata *target = luaL_checkudata(L, 1, "LTarget"); + u32 color = luaL_optinteger(L, 2, color_default); + + sf2d_clear_target(target->target, color); + + return 0; +} + +/*** +Destroy a target. +@function :destroy +*/ +static int gfx_target_destroy(lua_State *L) { + target_userdata *target = luaL_checkudata(L, 1, "LTarget"); + + sf2d_free_target(target->target); + + return 0; +} + +static const struct luaL_Reg target_methods[]; +/*** + +*/ +static int gfx_target___index(lua_State *L) { + target_userdata *target = luaL_checkudata(L, 1, "LTarget"); + const char* name = luaL_checkstring(L, 2); + + if (strcmp(name, "texture") == 0) { + texture_userdata *texture; + texture = (texture_userdata*)lua_newuserdata(L, sizeof(*texture)); + luaL_getmetatable(L, "LTexture"); + lua_setmetatable(L, -2); + + texture->texture = &(target->target->texture); + texture->scaleX = 1.0f; + texture->scaleY = 1.0f; + texture->blendColor = 0xffffffff; + + return 1; + } else if (strcmp(name, "duck") == 0) { + sf2d_rendertarget *target = sf2d_create_rendertarget(64, 64); + for(int i=0;;i++) { + sf2d_clear_target(target, 0xff000000); + sf2d_start_frame_target(target); + sf2d_draw_fill_circle(i%380, i%200, 10, 0xff0000ff); + sf2d_end_frame(); + //sf2d_texture_tile32(&target->texture); + + sf2d_start_frame(GFX_TOP, GFX_LEFT); + sf2d_draw_texture(&target->texture, 10, 10); + sf2d_end_frame(); + sf2d_swapbuffers(); + } + } else { + for (u8 i=0;target_methods[i].name;i++) { + if (strcmp(target_methods[i].name, name) == 0) { + lua_pushcfunction(L, target_methods[i].func); + return 1; + } + } + } + + lua_pushnil(L); + return 1; +} + // Functions static const struct luaL_Reg gfx_lib[] = { { "start", gfx_start }, @@ -425,6 +545,16 @@ static const struct luaL_Reg gfx_lib[] = { { "setTextSize", gfx_setTextSize }, { "getTextSize", gfx_getTextSize }, { "scissor", gfx_scissor }, + { "target", gfx_target }, + { NULL, NULL } +}; + +// Render target +static const struct luaL_Reg target_methods[] = { + { "__index", gfx_target___index }, + {"clear", gfx_target_clear }, + {"destroy", gfx_target_destroy }, + {"__gc", gfx_target_destroy }, { NULL, NULL } }; @@ -491,6 +621,11 @@ struct { char *name; void (*load)(lua_State *L); void (*unload)(lua_State *L); } }; int luaopen_gfx_lib(lua_State *L) { + luaL_newmetatable(L, "LTarget"); + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__index"); + luaL_setfuncs(L, target_methods, 0); + luaL_newlib(L, gfx_lib); for (int i = 0; gfx_constants[i].name; i++) { diff --git a/source/httpc.c b/source/httpc.c index 5f15af7..1df43bd 100644 --- a/source/httpc.c +++ b/source/httpc.c @@ -228,9 +228,15 @@ static int httpc_addTrustedRootCA(lua_State *L) { u32 certsize; u8* cert = (u8*)luaL_checklstring(L, 2, (size_t*)&certsize); - httpcAddTrustedRootCA(context, cert, certsize); + Result ret = httpcAddTrustedRootCA(context, cert, certsize); + if (ret != 0) { + lua_pushnil(L); + lua_pushinteger(L, ret); + return 2; + } - return 0; + lua_pushboolean(L, true); + return 1; } // object @@ -242,6 +248,7 @@ static const struct luaL_Reg httpc_methods[] = { {"getDownloadSize", httpc_getDownloadSize }, {"downloadData", httpc_downloadData }, {"close", httpc_close }, + {"__gc", httpc_close }, {"addPostData", httpc_addPostData }, {"getResponseHeader", httpc_getResponseHeader }, {"addTrustedRootCA", httpc_addTrustedRootCA }, diff --git a/source/main.c b/source/main.c index 270c655..d106898 100644 --- a/source/main.c +++ b/source/main.c @@ -1,3 +1,5 @@ +#include + #include <3ds.h> #include @@ -32,7 +34,32 @@ void error(const char *error) { } // Main loop -int main() { +int main(int argc, char** argv) { + // Default arguments + char* mainFile = "main.lua"; + + // Parse arguments + for (int i=0;i