mirror of
https://github.com/ctruLua/ctruLua.git
synced 2025-10-27 16:39:29 +00:00
Fixed the ROMFS, Removed some fields in fs.list(), Updated sftdlib
fs.list() now returns a table with tables containing the fields "name", "fileSize", and "isDirectory"
This commit is contained in:
parent
6b65df0b8e
commit
b798818e99
5 changed files with 149 additions and 143 deletions
|
|
@ -110,9 +110,19 @@ void sftd_draw_wtextf(sftd_font *font, int x, int y, unsigned int color, unsigne
|
||||||
* @param font the font used to calculate the width
|
* @param font the font used to calculate the width
|
||||||
* @param size the font size
|
* @param size the font size
|
||||||
* @param text a pointer to the text that will be used to calculate the length
|
* @param text a pointer to the text that will be used to calculate the length
|
||||||
|
* @return the width in pixels
|
||||||
*/
|
*/
|
||||||
int sftd_get_text_width(sftd_font *font, unsigned int size, const char *text);
|
int sftd_get_text_width(sftd_font *font, unsigned int size, const char *text);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the width of the given wide text in pixels
|
||||||
|
* @param font the font used to calculate the width
|
||||||
|
* @param size the font size
|
||||||
|
* @param text a pointer to the wide text that will be used to calculate the length
|
||||||
|
* @return the width in pixels
|
||||||
|
*/
|
||||||
|
int sftd_get_wtext_width(sftd_font *font, unsigned int size, const wchar_t *text);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Draws text using a font. The text will wrap after the pixels specified in lineWidth.
|
* @brief Draws text using a font. The text will wrap after the pixels specified in lineWidth.
|
||||||
* @param font the font to use
|
* @param font the font to use
|
||||||
|
|
@ -149,9 +159,6 @@ void sftd_calc_bounding_box(int *boundingWidth, int *boundingHeight, sftd_font *
|
||||||
*/
|
*/
|
||||||
void sftd_draw_textf_wrap(sftd_font *font, int x, int y, unsigned int color, unsigned int size, unsigned int lineWidth, const char *text, ...);
|
void sftd_draw_textf_wrap(sftd_font *font, int x, int y, unsigned int color, unsigned int size, unsigned int lineWidth, const char *text, ...);
|
||||||
|
|
||||||
// (ctruLua addition) Based on sftd_draw_wtext, returns the width of the text drawn.
|
|
||||||
int sftd_width_wtext(sftd_font *font, unsigned int size, const wchar_t *text);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -227,6 +227,13 @@ void sftd_draw_text(sftd_font *font, int x, int y, unsigned int color, unsigned
|
||||||
FT_ULong flags = FT_LOAD_RENDER | FT_LOAD_TARGET_NORMAL;
|
FT_ULong flags = FT_LOAD_RENDER | FT_LOAD_TARGET_NORMAL;
|
||||||
|
|
||||||
while (*text) {
|
while (*text) {
|
||||||
|
if(*text == '\n') {
|
||||||
|
pen_x = x;
|
||||||
|
pen_y += size;
|
||||||
|
text++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
glyph_index = FTC_CMapCache_Lookup(font->cmapcache, (FTC_FaceID)font, charmap_index, *text);
|
glyph_index = FTC_CMapCache_Lookup(font->cmapcache, (FTC_FaceID)font, charmap_index, *text);
|
||||||
|
|
||||||
if (use_kerning && previous && glyph_index) {
|
if (use_kerning && previous && glyph_index) {
|
||||||
|
|
@ -304,6 +311,13 @@ void sftd_draw_wtext(sftd_font *font, int x, int y, unsigned int color, unsigned
|
||||||
FT_ULong flags = FT_LOAD_RENDER | FT_LOAD_TARGET_NORMAL;
|
FT_ULong flags = FT_LOAD_RENDER | FT_LOAD_TARGET_NORMAL;
|
||||||
|
|
||||||
while (*text) {
|
while (*text) {
|
||||||
|
if(*text == '\n') {
|
||||||
|
pen_x = x;
|
||||||
|
pen_y += size;
|
||||||
|
text++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
glyph_index = FTC_CMapCache_Lookup(font->cmapcache, (FTC_FaceID)font, charmap_index, *text);
|
glyph_index = FTC_CMapCache_Lookup(font->cmapcache, (FTC_FaceID)font, charmap_index, *text);
|
||||||
|
|
||||||
if (use_kerning && previous && glyph_index) {
|
if (use_kerning && previous && glyph_index) {
|
||||||
|
|
@ -417,6 +431,66 @@ int sftd_get_text_width(sftd_font *font, unsigned int size, const char *text)
|
||||||
return pen_x;
|
return pen_x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sftd_get_wtext_width(sftd_font *font, unsigned int size, const wchar_t *text)
|
||||||
|
{
|
||||||
|
FTC_FaceID face_id = (FTC_FaceID)font;
|
||||||
|
FT_Face face;
|
||||||
|
FTC_Manager_LookupFace(font->ftcmanager, face_id, &face);
|
||||||
|
|
||||||
|
FT_Int charmap_index;
|
||||||
|
charmap_index = FT_Get_Charmap_Index(face->charmap);
|
||||||
|
|
||||||
|
FT_Glyph glyph;
|
||||||
|
FT_Bool use_kerning = FT_HAS_KERNING(face);
|
||||||
|
FT_UInt glyph_index, previous = 0;
|
||||||
|
int pen_x = 0;
|
||||||
|
int pen_y = size;
|
||||||
|
|
||||||
|
FTC_ScalerRec scaler;
|
||||||
|
scaler.face_id = face_id;
|
||||||
|
scaler.width = size;
|
||||||
|
scaler.height = size;
|
||||||
|
scaler.pixel = 1;
|
||||||
|
|
||||||
|
FT_ULong flags = FT_LOAD_RENDER | FT_LOAD_TARGET_NORMAL;
|
||||||
|
|
||||||
|
while (*text) {
|
||||||
|
glyph_index = FTC_CMapCache_Lookup(font->cmapcache, (FTC_FaceID)font, charmap_index, *text);
|
||||||
|
|
||||||
|
if (use_kerning && previous && glyph_index) {
|
||||||
|
FT_Vector delta;
|
||||||
|
FT_Get_Kerning(face, previous, glyph_index, FT_KERNING_DEFAULT, &delta);
|
||||||
|
pen_x += delta.x >> 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!texture_atlas_exists(font->tex_atlas, glyph_index)) {
|
||||||
|
FTC_ImageCache_LookupScaler(font->imagecache, &scaler, flags, glyph_index, &glyph, NULL);
|
||||||
|
|
||||||
|
if (!atlas_add_glyph(font->tex_atlas, glyph_index, (FT_BitmapGlyph)glyph, size)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bp2d_rectangle rect;
|
||||||
|
int bitmap_left, bitmap_top;
|
||||||
|
int advance_x, advance_y;
|
||||||
|
int glyph_size;
|
||||||
|
|
||||||
|
texture_atlas_get(font->tex_atlas, glyph_index,
|
||||||
|
&rect, &bitmap_left, &bitmap_top,
|
||||||
|
&advance_x, &advance_y, &glyph_size);
|
||||||
|
|
||||||
|
const float draw_scale = size/(float)glyph_size;
|
||||||
|
|
||||||
|
pen_x += (advance_x >> 16) * draw_scale;
|
||||||
|
pen_y += (advance_y >> 16) * draw_scale;
|
||||||
|
|
||||||
|
previous = glyph_index;
|
||||||
|
text++;
|
||||||
|
}
|
||||||
|
return pen_x;
|
||||||
|
}
|
||||||
|
|
||||||
void sftd_draw_text_wrap(sftd_font *font, int x, int y, unsigned int color, unsigned int size, unsigned int lineWidth, const char *text)
|
void sftd_draw_text_wrap(sftd_font *font, int x, int y, unsigned int color, unsigned int size, unsigned int lineWidth, const char *text)
|
||||||
{
|
{
|
||||||
FTC_FaceID face_id = (FTC_FaceID)font;
|
FTC_FaceID face_id = (FTC_FaceID)font;
|
||||||
|
|
@ -610,63 +684,3 @@ void sftd_draw_textf_wrap(sftd_font *font, int x, int y, unsigned int color, uns
|
||||||
sftd_draw_text_wrap(font, x, y, color, size, lineWidth, buffer);
|
sftd_draw_text_wrap(font, x, y, color, size, lineWidth, buffer);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
// (ctruLua addition) Based on sftd_draw_wtext, returns the width of the text drawn.
|
|
||||||
int sftd_width_wtext(sftd_font *font, unsigned int size, const wchar_t *text)
|
|
||||||
{
|
|
||||||
FTC_FaceID face_id = (FTC_FaceID)font;
|
|
||||||
FT_Face face;
|
|
||||||
FTC_Manager_LookupFace(font->ftcmanager, face_id, &face);
|
|
||||||
|
|
||||||
FT_Int charmap_index;
|
|
||||||
charmap_index = FT_Get_Charmap_Index(face->charmap);
|
|
||||||
|
|
||||||
FT_Glyph glyph;
|
|
||||||
FT_Bool use_kerning = FT_HAS_KERNING(face);
|
|
||||||
FT_UInt glyph_index, previous = 0;
|
|
||||||
int pen_x = 0;
|
|
||||||
|
|
||||||
FTC_ScalerRec scaler;
|
|
||||||
scaler.face_id = face_id;
|
|
||||||
scaler.width = size;
|
|
||||||
scaler.height = size;
|
|
||||||
scaler.pixel = 1;
|
|
||||||
|
|
||||||
FT_ULong flags = FT_LOAD_RENDER | FT_LOAD_TARGET_NORMAL;
|
|
||||||
|
|
||||||
while (*text) {
|
|
||||||
glyph_index = FTC_CMapCache_Lookup(font->cmapcache, (FTC_FaceID)font, charmap_index, *text);
|
|
||||||
|
|
||||||
if (use_kerning && previous && glyph_index) {
|
|
||||||
FT_Vector delta;
|
|
||||||
FT_Get_Kerning(face, previous, glyph_index, FT_KERNING_DEFAULT, &delta);
|
|
||||||
pen_x += delta.x >> 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!texture_atlas_exists(font->tex_atlas, glyph_index)) {
|
|
||||||
FTC_ImageCache_LookupScaler(font->imagecache, &scaler, flags, glyph_index, &glyph, NULL);
|
|
||||||
|
|
||||||
if (!atlas_add_glyph(font->tex_atlas, glyph_index, (FT_BitmapGlyph)glyph, size)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bp2d_rectangle rect;
|
|
||||||
int bitmap_left, bitmap_top;
|
|
||||||
int advance_x, advance_y;
|
|
||||||
int glyph_size;
|
|
||||||
|
|
||||||
texture_atlas_get(font->tex_atlas, glyph_index,
|
|
||||||
&rect, &bitmap_left, &bitmap_top,
|
|
||||||
&advance_x, &advance_y, &glyph_size);
|
|
||||||
|
|
||||||
const float draw_scale = size/(float)glyph_size;
|
|
||||||
|
|
||||||
pen_x += (advance_x >> 16) * draw_scale;
|
|
||||||
|
|
||||||
previous = glyph_index;
|
|
||||||
text++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pen_x;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ texture_atlas *texture_atlas_create(int width, int height, sf2d_texfmt format, s
|
||||||
rect.h = height;
|
rect.h = height;
|
||||||
|
|
||||||
atlas->tex = sf2d_create_texture(width, height, format, place);
|
atlas->tex = sf2d_create_texture(width, height, format, place);
|
||||||
|
sf2d_texture_set_params(atlas->tex, GPU_TEXTURE_MAG_FILTER(GPU_LINEAR) | GPU_TEXTURE_MIN_FILTER(GPU_LINEAR));
|
||||||
sf2d_texture_tile32(atlas->tex);
|
sf2d_texture_tile32(atlas->tex);
|
||||||
|
|
||||||
atlas->bp_root = bp2d_create(&rect);
|
atlas->bp_root = bp2d_create(&rect);
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ static int font_object_width(lua_State *L) {
|
||||||
len = mbstowcs(wtext, text, len);
|
len = mbstowcs(wtext, text, len);
|
||||||
*(wtext+len) = 0x0; // text end
|
*(wtext+len) = 0x0; // text end
|
||||||
|
|
||||||
lua_pushinteger(L, sftd_width_wtext(font->font, size, wtext));
|
lua_pushinteger(L, sftd_get_wtext_width(font->font, size, wtext));
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
142
source/fs.c
142
source/fs.c
|
|
@ -3,25 +3,24 @@ The `fs` module.
|
||||||
@module ctr.fs
|
@module ctr.fs
|
||||||
@usage local fs = require("ctr.fs")
|
@usage local fs = require("ctr.fs")
|
||||||
*/
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
#include <3ds/types.h>
|
#include <3ds/types.h>
|
||||||
#include <3ds/util/utf.h>
|
#include <3ds/util/utf.h>
|
||||||
#include <3ds/services/fs.h>
|
#include <3ds/services/fs.h>
|
||||||
|
#include <3ds/sdmc.h>
|
||||||
|
#include <3ds/romfs.h>
|
||||||
|
|
||||||
#include <lua.h>
|
#include <lua.h>
|
||||||
#include <lauxlib.h>
|
#include <lauxlib.h>
|
||||||
|
|
||||||
bool isFsInitialized = false;
|
bool isFsInitialized = false;
|
||||||
|
|
||||||
Handle *fsuHandle;
|
|
||||||
FS_Archive sdmcArchive;
|
|
||||||
#ifdef ROMFS
|
|
||||||
FS_Archive romfsArchive;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/***
|
/***
|
||||||
The `ctr.fs.lzlib` module.
|
The `ctr.fs.lzlib` module.
|
||||||
@table lzlib
|
@table lzlib
|
||||||
|
|
@ -57,81 +56,76 @@ Lists a directory contents (unsorted).
|
||||||
`
|
`
|
||||||
{
|
{
|
||||||
name = "Item name.txt",
|
name = "Item name.txt",
|
||||||
shortName = "ITEM~",
|
|
||||||
shortExt = "TXT",
|
|
||||||
isDirectory = false,
|
isDirectory = false,
|
||||||
isHidden = false,
|
|
||||||
isArchive = false,
|
|
||||||
isReadOnly = false,
|
|
||||||
fileSize = 321 -- (integer) in bytes
|
fileSize = 321 -- (integer) in bytes
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
*/
|
*/
|
||||||
static int fs_list(lua_State *L) {
|
static int fs_list(lua_State *L) {
|
||||||
const char *path = prefix_path(luaL_checkstring(L, 1));
|
const char* basepath = prefix_path(luaL_checkstring(L, 1));
|
||||||
|
char* path;
|
||||||
|
bool shouldFreePath = false;
|
||||||
|
if (basepath[strlen(basepath)-1] != '/') {
|
||||||
|
path = malloc(strlen(basepath)+2);
|
||||||
|
strcpy(path, basepath);
|
||||||
|
strcat(path, "/");
|
||||||
|
shouldFreePath = true;
|
||||||
|
} else {
|
||||||
|
path = (char*)basepath;
|
||||||
|
}
|
||||||
|
|
||||||
lua_newtable(L);
|
lua_newtable(L);
|
||||||
int i = 1; // table index
|
int i = 1; // table index
|
||||||
|
|
||||||
// Get default archive
|
DIR* dir = opendir(path);
|
||||||
#ifdef ROMFS
|
if (dir == NULL) {
|
||||||
FS_Archive archive = romfsArchive;
|
if (shouldFreePath) free(path);
|
||||||
#else
|
lua_pushboolean(L, false);
|
||||||
FS_Archive archive = sdmcArchive;
|
lua_pushstring(L, strerror(errno));
|
||||||
#endif
|
return 2;
|
||||||
// Archive path override (and skip path prefix)
|
|
||||||
if (strncmp(path, "sdmc:", 5) == 0) {
|
|
||||||
path += 5;
|
|
||||||
archive = sdmcArchive;
|
|
||||||
#ifdef ROMFS
|
|
||||||
} else if (strncmp(path, "romfs:", 6) == 0) {
|
|
||||||
path += 6;
|
|
||||||
archive = romfsArchive;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
errno = 0;
|
||||||
FS_Path dirPath = fsMakePath(PATH_ASCII, path);
|
struct dirent *entry;
|
||||||
|
while (((entry = readdir(dir)) != NULL) && !errno) {
|
||||||
Handle dirHandle;
|
lua_createtable(L, 0, 3);
|
||||||
FSUSER_OpenDirectory(&dirHandle, archive, dirPath);
|
|
||||||
|
lua_pushstring(L, (const char*)entry->d_name);
|
||||||
u32 entriesRead = 0;
|
|
||||||
do {
|
|
||||||
FS_DirectoryEntry buffer;
|
|
||||||
|
|
||||||
FSDIR_Read(dirHandle, &entriesRead, 1, &buffer);
|
|
||||||
|
|
||||||
if (!entriesRead) break;
|
|
||||||
|
|
||||||
uint8_t name[0x106+1]; // utf8 file name
|
|
||||||
size_t size = utf16_to_utf8(name, buffer.name, 0x106);
|
|
||||||
*(name+size) = 0x0; // mark text end
|
|
||||||
|
|
||||||
lua_createtable(L, 0, 8);
|
|
||||||
|
|
||||||
lua_pushstring(L, (const char *)name);
|
|
||||||
lua_setfield(L, -2, "name");
|
lua_setfield(L, -2, "name");
|
||||||
lua_pushstring(L, (const char *)buffer.shortName);
|
lua_pushboolean(L, entry->d_type==DT_DIR);
|
||||||
lua_setfield(L, -2, "shortName");
|
|
||||||
lua_pushstring(L, (const char *)buffer.shortExt);
|
|
||||||
lua_setfield(L, -2, "shortExt");
|
|
||||||
lua_pushboolean(L, buffer.attributes&FS_ATTRIBUTE_DIRECTORY);
|
|
||||||
lua_setfield(L, -2, "isDirectory");
|
lua_setfield(L, -2, "isDirectory");
|
||||||
lua_pushboolean(L, buffer.attributes&FS_ATTRIBUTE_HIDDEN);
|
|
||||||
lua_setfield(L, -2, "isHidden");
|
if (entry->d_type==DT_REG) { // Regular files: check size
|
||||||
lua_pushboolean(L, buffer.attributes&FS_ATTRIBUTE_ARCHIVE);
|
char* filepath = malloc(strlen(path)+strlen(entry->d_name)+1);
|
||||||
lua_setfield(L, -2, "isArchive");
|
if (filepath == NULL) {
|
||||||
lua_pushboolean(L, buffer.attributes&FS_ATTRIBUTE_READ_ONLY);
|
luaL_error(L, "Memory allocation error");
|
||||||
lua_setfield(L, -2, "isReadOnly");
|
}
|
||||||
lua_pushinteger(L, buffer.fileSize);
|
memset(filepath, 0, strlen(path)+strlen(entry->d_name)+1);
|
||||||
|
|
||||||
|
strcpy(filepath, path);
|
||||||
|
strcat(filepath, entry->d_name);
|
||||||
|
struct stat stats;
|
||||||
|
if (stat(filepath, &stats)) {
|
||||||
|
free(filepath);
|
||||||
|
if (shouldFreePath) free(path);
|
||||||
|
luaL_error(L, "Stat error: %s (%d)", strerror(errno), errno);
|
||||||
|
lua_pushboolean(L, false);
|
||||||
|
lua_pushstring(L, strerror(errno));
|
||||||
|
return 2;
|
||||||
|
} else {
|
||||||
|
lua_pushinteger(L, stats.st_size);
|
||||||
|
}
|
||||||
|
free(filepath);
|
||||||
|
} else { // Everything else: 0 bytes
|
||||||
|
lua_pushinteger(L, 0);
|
||||||
|
}
|
||||||
lua_setfield(L, -2, "fileSize");
|
lua_setfield(L, -2, "fileSize");
|
||||||
|
|
||||||
lua_seti(L, -2, i);
|
lua_seti(L, -2, i);
|
||||||
i++;
|
i++;
|
||||||
|
}
|
||||||
} while (entriesRead > 0);
|
|
||||||
|
closedir(dir);
|
||||||
FSDIR_Close(dirHandle);
|
if (shouldFreePath) free(path);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
@ -214,16 +208,9 @@ int luaopen_fs_lib(lua_State *L) {
|
||||||
|
|
||||||
void load_fs_lib(lua_State *L) {
|
void load_fs_lib(lua_State *L) {
|
||||||
if (!isFsInitialized) {
|
if (!isFsInitialized) {
|
||||||
fsInit();
|
sdmcInit();
|
||||||
|
|
||||||
fsuHandle = fsGetSessionHandle();
|
|
||||||
FSUSER_Initialize(*fsuHandle);
|
|
||||||
|
|
||||||
sdmcArchive = (FS_Archive){ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, "")};
|
|
||||||
FSUSER_OpenArchive(&sdmcArchive);
|
|
||||||
#ifdef ROMFS
|
#ifdef ROMFS
|
||||||
romfsArchive = (FS_Archive){ARCHIVE_ROMFS, fsMakePath(PATH_EMPTY, "")};
|
romfsInit();
|
||||||
FSUSER_OpenArchive(&romfsArchive);
|
|
||||||
#endif
|
#endif
|
||||||
isFsInitialized = true;
|
isFsInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
@ -232,11 +219,8 @@ void load_fs_lib(lua_State *L) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void unload_fs_lib(lua_State *L) {
|
void unload_fs_lib(lua_State *L) {
|
||||||
FSUSER_CloseArchive(&sdmcArchive);
|
sdmcExit();
|
||||||
#ifdef ROMFS
|
#ifdef ROMFS
|
||||||
FSUSER_CloseArchive(&romfsArchive);
|
romfsExit();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
fsExit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue