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:
parent
dcdeec6525
commit
8500bcb8fa
7 changed files with 222 additions and 16 deletions
26
source/ctr.c
26
source/ctr.c
|
|
@ -77,6 +77,13 @@ The `ctr.cfgu` module.
|
|||
*/
|
||||
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);
|
||||
|
||||
/***
|
||||
|
|
@ -110,15 +117,16 @@ static const struct luaL_Reg ctr_lib[] = {
|
|||
|
||||
// Subtables
|
||||
struct { char *name; void (*load)(lua_State *L); void (*unload)(lua_State *L); } ctr_libs[] = {
|
||||
{ "gfx", load_gfx_lib, unload_gfx_lib },
|
||||
{ "news", load_news_lib, NULL },
|
||||
{ "ptm", load_ptm_lib, NULL },
|
||||
{ "hid", load_hid_lib, unload_hid_lib },
|
||||
{ "ir", load_ir_lib, NULL },
|
||||
{ "fs", load_fs_lib, unload_fs_lib },
|
||||
{ "httpc", load_httpc_lib, unload_httpc_lib },
|
||||
{ "qtm", load_qtm_lib, NULL },
|
||||
{ "cfgu", load_cfgu_lib, NULL },
|
||||
{ "gfx", load_gfx_lib, unload_gfx_lib },
|
||||
{ "news", load_news_lib, NULL },
|
||||
{ "ptm", load_ptm_lib, NULL },
|
||||
{ "hid", load_hid_lib, unload_hid_lib },
|
||||
{ "ir", load_ir_lib, NULL },
|
||||
{ "fs", load_fs_lib, unload_fs_lib },
|
||||
{ "httpc", load_httpc_lib, unload_httpc_lib },
|
||||
{ "qtm", load_qtm_lib, NULL },
|
||||
{ "cfgu", load_cfgu_lib, NULL },
|
||||
{ "socket", load_socket_lib, NULL },
|
||||
// { "cam", load_cam_lib, NULL },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
|
|
|||
10
source/fs.c
10
source/fs.c
|
|
@ -9,6 +9,9 @@
|
|||
|
||||
Handle *fsuHandle;
|
||||
FS_archive sdmcArchive;
|
||||
#ifdef ROMFS
|
||||
FS_archive romfsArchive;
|
||||
#endif
|
||||
|
||||
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, "")};
|
||||
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);
|
||||
}
|
||||
|
||||
void unload_fs_lib(lua_State *L) {
|
||||
FSUSER_CloseArchive(fsuHandle, &sdmcArchive);
|
||||
#ifdef ROMFS
|
||||
FSUSER_CloseArchive(fsuHandle, &romfsArchive);
|
||||
#endif
|
||||
|
||||
fsExit();
|
||||
}
|
||||
|
|
|
|||
18
source/gfx.c
18
source/gfx.c
|
|
@ -9,6 +9,7 @@ The `gfx` module.
|
|||
#include <sftd.h>
|
||||
|
||||
#include <3ds/vram.h>
|
||||
#include <3ds/services/gsp.h>
|
||||
|
||||
#include <lua.h>
|
||||
#include <lauxlib.h>
|
||||
|
|
@ -134,6 +135,22 @@ static int gfx_setVBlankWait(lua_State *L) {
|
|||
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.
|
||||
@function vramSpaceFree
|
||||
|
|
@ -348,6 +365,7 @@ static const struct luaL_Reg gfx_lib[] = {
|
|||
{ "set3D", gfx_set3D },
|
||||
{ "get3D", gfx_get3D },
|
||||
{ "setVBlankWait", gfx_setVBlankWait },
|
||||
{ "waitForVBlank", gfx_waitForVBlank },
|
||||
{ "vramSpaceFree", gfx_vramSpaceFree },
|
||||
{ "line", gfx_line },
|
||||
{ "point", gfx_point },
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ Receive some data from the IR module.
|
|||
@function receive
|
||||
@tparam[opt=buffer size] number size bytes to receive
|
||||
@tparam[opt=false] boolean wait wait until the data is received
|
||||
@return string data
|
||||
*/
|
||||
static int ir_receive(lua_State *L) {
|
||||
u32 size = luaL_optinteger(L, 1, bufferSize);
|
||||
|
|
|
|||
|
|
@ -33,17 +33,13 @@ Send a notification to the user. WIP, do not use !!!
|
|||
static int news_notification(lua_State *L) {
|
||||
const char *title = luaL_checkstring(L, 1);
|
||||
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;
|
||||
if (lua_isboolean(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* cMessage = 0;
|
||||
u32 titleLength, messageLength;
|
||||
|
|
|
|||
166
source/socket.c
Normal file
166
source/socket.c
Normal 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);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue