1
0
Fork 0
mirror of https://github.com/ctruLua/ctruLua.git synced 2025-10-27 16:39:29 +00:00

ADDED SOCKETS ! Added ROMFS support (maybe), Improved the news library, added a VBLank waiting function

Sockets are only very buggy/unstable TCP clients, but working. The library was written from scratch.
This commit is contained in:
Firew0lf 2015-10-17 23:15:06 +02:00
parent dcdeec6525
commit 8500bcb8fa
7 changed files with 222 additions and 16 deletions

View file

@ -25,12 +25,14 @@ include $(DEVKITARM)/3ds_rules
# - <Project name>.png # - <Project name>.png
# - icon.png # - icon.png
# - <libctru folder>/default_icon.png # - <libctru folder>/default_icon.png
# ROMFS: if set, use the files at this path to build a ROMFS
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
TARGET := ctruLua TARGET := ctruLua
BUILD := build BUILD := build
SOURCES := source libs/lua-5.3.1/src SOURCES := source libs/lua-5.3.1/src
DATA := data DATA := data
INCLUDES := include libs/lua-5.3.1/src libs/lzlib INCLUDES := include libs/lua-5.3.1/src libs/lzlib
#ROMFS := romfs
APP_TITLE := ctruLua APP_TITLE := ctruLua
APP_DESCRIPTION := Lua for the 3DS. Yes, it works. APP_DESCRIPTION := Lua for the 3DS. Yes, it works.
@ -125,6 +127,11 @@ ifeq ($(strip $(NO_SMDH)),)
export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh
endif endif
ifneq ($(ROMFS),)
export _3DSXFLAGS += --romfs=$(CURDIR)/$(ROMFS)
CFLAGS += -DROMFS
endif
.PHONY: $(BUILD) clean all .PHONY: $(BUILD) clean all
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------

View file

@ -77,6 +77,13 @@ The `ctr.cfgu` module.
*/ */
void load_cfgu_lib(lua_State *L); void load_cfgu_lib(lua_State *L);
/***
The `ctr.socket` module.
@table socket
@see ctr.socket
*/
void load_socket_lib(lua_State *L);
//void load_cam_lib(lua_State *L); //void load_cam_lib(lua_State *L);
/*** /***
@ -110,15 +117,16 @@ static const struct luaL_Reg ctr_lib[] = {
// Subtables // Subtables
struct { char *name; void (*load)(lua_State *L); void (*unload)(lua_State *L); } ctr_libs[] = { struct { char *name; void (*load)(lua_State *L); void (*unload)(lua_State *L); } ctr_libs[] = {
{ "gfx", load_gfx_lib, unload_gfx_lib }, { "gfx", load_gfx_lib, unload_gfx_lib },
{ "news", load_news_lib, NULL }, { "news", load_news_lib, NULL },
{ "ptm", load_ptm_lib, NULL }, { "ptm", load_ptm_lib, NULL },
{ "hid", load_hid_lib, unload_hid_lib }, { "hid", load_hid_lib, unload_hid_lib },
{ "ir", load_ir_lib, NULL }, { "ir", load_ir_lib, NULL },
{ "fs", load_fs_lib, unload_fs_lib }, { "fs", load_fs_lib, unload_fs_lib },
{ "httpc", load_httpc_lib, unload_httpc_lib }, { "httpc", load_httpc_lib, unload_httpc_lib },
{ "qtm", load_qtm_lib, NULL }, { "qtm", load_qtm_lib, NULL },
{ "cfgu", load_cfgu_lib, NULL }, { "cfgu", load_cfgu_lib, NULL },
{ "socket", load_socket_lib, NULL },
// { "cam", load_cam_lib, NULL }, // { "cam", load_cam_lib, NULL },
{ NULL, NULL } { NULL, NULL }
}; };

View file

@ -9,6 +9,9 @@
Handle *fsuHandle; Handle *fsuHandle;
FS_archive sdmcArchive; FS_archive sdmcArchive;
#ifdef ROMFS
FS_archive romfsArchive;
#endif
void load_lzlib(lua_State *L); void load_lzlib(lua_State *L);
@ -126,12 +129,19 @@ void load_fs_lib(lua_State *L) {
sdmcArchive = (FS_archive){ARCH_SDMC, FS_makePath(PATH_EMPTY, "")}; sdmcArchive = (FS_archive){ARCH_SDMC, FS_makePath(PATH_EMPTY, "")};
FSUSER_OpenArchive(fsuHandle, &sdmcArchive); FSUSER_OpenArchive(fsuHandle, &sdmcArchive);
#ifdef ROMFS
romfsArchive = (FS_archive){ARCH_ROMFS, FS_makePath(PATH_EMPTY, "")};
FSUSER_OpenArchive(fsuHandle, &romfsArchive);
#endif
luaL_requiref(L, "ctr.fs", luaopen_fs_lib, false); luaL_requiref(L, "ctr.fs", luaopen_fs_lib, false);
} }
void unload_fs_lib(lua_State *L) { void unload_fs_lib(lua_State *L) {
FSUSER_CloseArchive(fsuHandle, &sdmcArchive); FSUSER_CloseArchive(fsuHandle, &sdmcArchive);
#ifdef ROMFS
FSUSER_CloseArchive(fsuHandle, &romfsArchive);
#endif
fsExit(); fsExit();
} }

View file

@ -9,6 +9,7 @@ The `gfx` module.
#include <sftd.h> #include <sftd.h>
#include <3ds/vram.h> #include <3ds/vram.h>
#include <3ds/services/gsp.h>
#include <lua.h> #include <lua.h>
#include <lauxlib.h> #include <lauxlib.h>
@ -134,6 +135,22 @@ static int gfx_setVBlankWait(lua_State *L) {
return 0; return 0;
} }
/***
Wait for the VBlank interruption.
@function waitForVBlank
@tparam[opt=GFX_TOP] number screen the screen's VBlank to wait for
*/
static int gfx_waitForVBlank(lua_State *L) {
u8 screen = luaL_optinteger(L, 1, GFX_TOP);
if (screen == GFX_TOP) {
gspWaitForVBlank0();
} else {
gspWaitForVBlank1();
}
return 0;
}
/*** /***
Get free VRAM space. Get free VRAM space.
@function vramSpaceFree @function vramSpaceFree
@ -348,6 +365,7 @@ static const struct luaL_Reg gfx_lib[] = {
{ "set3D", gfx_set3D }, { "set3D", gfx_set3D },
{ "get3D", gfx_get3D }, { "get3D", gfx_get3D },
{ "setVBlankWait", gfx_setVBlankWait }, { "setVBlankWait", gfx_setVBlankWait },
{ "waitForVBlank", gfx_waitForVBlank },
{ "vramSpaceFree", gfx_vramSpaceFree }, { "vramSpaceFree", gfx_vramSpaceFree },
{ "line", gfx_line }, { "line", gfx_line },
{ "point", gfx_point }, { "point", gfx_point },

View file

@ -103,6 +103,7 @@ Receive some data from the IR module.
@function receive @function receive
@tparam[opt=buffer size] number size bytes to receive @tparam[opt=buffer size] number size bytes to receive
@tparam[opt=false] boolean wait wait until the data is received @tparam[opt=false] boolean wait wait until the data is received
@return string data
*/ */
static int ir_receive(lua_State *L) { static int ir_receive(lua_State *L) {
u32 size = luaL_optinteger(L, 1, bufferSize); u32 size = luaL_optinteger(L, 1, bufferSize);

View file

@ -33,17 +33,13 @@ Send a notification to the user. WIP, do not use !!!
static int news_notification(lua_State *L) { static int news_notification(lua_State *L) {
const char *title = luaL_checkstring(L, 1); const char *title = luaL_checkstring(L, 1);
const char *message = luaL_checkstring(L, 2); const char *message = luaL_checkstring(L, 2);
const void *imageData = luaL_optstring(L, 3, NULL);
u32 imageDataLength = 0;
const void *imageData = luaL_optlstring(L, 3, NULL, (size_t*)&imageDataLength);
bool jpeg = false; bool jpeg = false;
if (lua_isboolean(L, 4)) if (lua_isboolean(L, 4))
jpeg = lua_toboolean(L, 4); jpeg = lua_toboolean(L, 4);
u32 imageDataLength = 0;
if (imageData) {
lua_len(L, 3);
luaL_checkinteger(L, -1);
}
const u16* cTitle = 0; const u16* cTitle = 0;
const u16* cMessage = 0; const u16* cMessage = 0;
u32 titleLength, messageLength; u32 titleLength, messageLength;

166
source/socket.c Normal file
View file

@ -0,0 +1,166 @@
/***
The `socket` module. Almost like luasocket, but for TCP/UDP only.
See http://w3.impa.br/~diego/software/luasocket/reference.html for a
documentation.
@module ctr.socket
@usage local socket = require("ctr.socket")
*/
#include <3ds.h>
#include <3ds/types.h>
#include <3ds/services/soc.h>
#include <lapi.h>
#include <lauxlib.h>
#include <malloc.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
typedef struct {
int socket;
struct sockaddr_in addr;
struct hostent *host; // only user for client sockets
} socket_userdata;
static int socket_init(lua_State *L) {
u32 size = luaL_optinteger(L, 1, 0x10000);
Result ret = SOC_Initialize((u32*)memalign(0x1000, size), size);
if (ret) {
lua_pushboolean(L, false);
lua_pushinteger(L, ret);
return 2;
}
lua_pushboolean(L, true);
return 1;
}
static int socket_shutdown(lua_State *L) {
SOC_Shutdown();
return 0;
}
static int socket_tcp(lua_State *L) {
socket_userdata *data = lua_newuserdata(L, sizeof(*data));
luaL_getmetatable(L, "LSocket");
lua_setmetatable(L, -2);
data->socket = socket(AF_INET, SOCK_STREAM, 0);
if (data->socket < 0) {
lua_pushnil(L);
lua_pushstring(L, "Failed to create a TCP socket");
return 2;
}
data->addr.sin_family = AF_INET;
return 1;
}
/* methods */
static int socket_close(lua_State *L) {
socket_userdata *data = luaL_checkudata(L, 1, "LSocket");
close(data->socket);
return 0;
}
static int socket_connect(lua_State *L) {
socket_userdata *data = luaL_checkudata(L, 1, "LSocket");
char *addr = (char*)luaL_checkstring(L, 2);
int port = luaL_checkinteger(L, 3);
data->host = gethostbyname(addr);
if (data->host == NULL) {
lua_pushnil(L);
lua_pushstring(L, "No such host");
return 2;
}
data->addr.sin_port = htons(port);
bcopy((char*)data->host->h_addr, (char*)&data->addr.sin_addr.s_addr, data->host->h_length);
if (connect(data->socket, (const struct sockaddr*)&data->addr, sizeof(data->addr)) < 0) {
lua_pushnil(L);
lua_pushstring(L, "Connection failed");
return 2;
}
lua_pushinteger(L, 1);
return 1;
}
static int socket_receive(lua_State *L) {
socket_userdata *userdata = luaL_checkudata(L, 1, "LSocket");
int count = 0;
int flags = 0;
if (lua_isnumber(L, 2)) {
count = luaL_checkinteger(L, 2);
} else if (lua_isstring(L, 2) && luaL_checkstring(L, 2) == (char*)&"*a") {
count = SIZE_MAX/2;
} else {
lua_pushnil(L);
lua_pushstring(L, "");
return 2;
}
char *buff = malloc(count);
recv(userdata->socket, buff, count, flags);
lua_pushstring(L, buff);
return 1;
}
static int socket_send(lua_State *L) {
socket_userdata *userdata = luaL_checkudata(L, 1, "LSocket");
size_t size = 0;
char *data = (char*)luaL_checklstring(L, 2, &size);
size_t sent = send(userdata->socket, data, size, 0);
lua_pushinteger(L, sent);
return 1;
}
// module functions
static const struct luaL_Reg socket_functions[] = {
{"init", socket_init },
{"shutdown", socket_shutdown},
{"tcp", socket_tcp },
{NULL, NULL}
};
// object
static const struct luaL_Reg socket_methods[] = {
{"close", socket_close },
{"connect", socket_connect },
{"receive", socket_receive },
{"send", socket_send },
{NULL, NULL}
};
int luaopen_socket_lib(lua_State *L) {
luaL_newmetatable(L, "LSocket");
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");
luaL_setfuncs(L, socket_methods, 0);
luaL_newlib(L, socket_functions);
return 1;
}
void load_socket_lib(lua_State *L) {
luaL_requiref(L, "ctr.socket", luaopen_socket_lib, false);
}