From 93e58c7f63f74a88d14869d6e800f21a3e1e2b52 Mon Sep 17 00:00:00 2001 From: Lephe Date: Sat, 5 Apr 2025 08:22:26 +0200 Subject: [PATCH 1/5] r61523: add r61523_set_pixel() function This is used for touch framerate experiments where a full frame refresh is too expensive. --- include/gint/drivers/r61523.h | 3 +++ src/r61523/r61523.c | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/include/gint/drivers/r61523.h b/include/gint/drivers/r61523.h index 70d9fa1..372cb9f 100644 --- a/include/gint/drivers/r61523.h +++ b/include/gint/drivers/r61523.h @@ -23,6 +23,9 @@ void r61523_display_rect( /* r61523_win_set(): Set the display window */ void r61523_win_set(int x1, int x2, int y1, int y2); +/* r61523_set_pixel(): Write a pixel directly to DD (slow) */ +void r61523_set_pixel(int x, int y, int color); + #ifdef __cplusplus } #endif diff --git a/src/r61523/r61523.c b/src/r61523/r61523.c index 827e63c..92cfa7e 100644 --- a/src/r61523/r61523.c +++ b/src/r61523/r61523.c @@ -172,6 +172,18 @@ void r61523_display_rect( } } +void r61523_set_pixel(int x, int y, int color) +{ + if((unsigned)x >= 320 || (unsigned)y >= 528) + return; + + // dma_transfer_wait(0); + r61523_win_set(x, x, y, y); + select(44); + uint16_t volatile *DISPLAY = (void *)0xb4000000; + *DISPLAY = color; +} + static bool r61523_update(int x, int y, image_t const *fb, int flags) { if(fb->format != IMAGE_RGB565) From 7180b52fd449716540296179e53aaa80db8f1ce7 Mon Sep 17 00:00:00 2001 From: Lephe Date: Sat, 5 Apr 2025 08:34:08 +0200 Subject: [PATCH 2/5] fs: first steps towards working fx-CP 400 support (compiles, no syscalls) --- include/gint/bfile.h | 7 ++ src/fs/fugue/BFile_Ext_Stat.c | 4 ++ src/fs/fugue/bfilecp.h | 121 ++++++++++++++++++++++++++++++++++ src/fs/fugue/fugue.c | 19 ++++++ src/fs/fugue/fugue_dir.c | 5 ++ src/fs/fugue/fugue_mkdir.c | 10 +++ src/fs/fugue/fugue_open.c | 81 +++++++++++++++-------- src/fs/fugue/fugue_rename.c | 34 +++++----- src/fs/fugue/fugue_rmdir.c | 14 ++-- src/fs/fugue/fugue_stat.c | 1 + src/fs/fugue/fugue_unlink.c | 23 ++++--- src/fs/fugue/util.c | 37 +++++++++++ 12 files changed, 296 insertions(+), 60 deletions(-) create mode 100644 src/fs/fugue/bfilecp.h diff --git a/include/gint/bfile.h b/include/gint/bfile.h index fecab0e..6be4ba5 100644 --- a/include/gint/bfile.h +++ b/include/gint/bfile.h @@ -64,8 +64,13 @@ extern "C" { #endif +#include #include +// BFile has a different interface on CP-400, which is not exposed by gint +// because the standard API is always available. +#if !GINT_OS_CP + //--- // Common file access functions //--- @@ -308,6 +313,8 @@ int BFile_FindClose(int shandle); /* BFile_Ext_Stat(): Stat an entry for type and size */ int BFile_Ext_Stat(uint16_t const *path, int *type, int *size); +#endif /* !GINT_OS_CP */ + #ifdef __cplusplus } #endif diff --git a/src/fs/fugue/BFile_Ext_Stat.c b/src/fs/fugue/BFile_Ext_Stat.c index bde0c2a..45b24a0 100644 --- a/src/fs/fugue/BFile_Ext_Stat.c +++ b/src/fs/fugue/BFile_Ext_Stat.c @@ -1,6 +1,10 @@ #include #include "util.h" +#include "bfilecp.h" +// TODO: BFile_Ext_Stat: Use native stat function on CP-400? +// Unlike find functions, it doesn't provide type, as per documented API at +// least, and stat really needs it. So for now I'm sticking to the find check. int BFile_Ext_Stat(uint16_t const *path, int *type, int *size) { int search_handle, rc; diff --git a/src/fs/fugue/bfilecp.h b/src/fs/fugue/bfilecp.h new file mode 100644 index 0000000..5822cf5 --- /dev/null +++ b/src/fs/fugue/bfilecp.h @@ -0,0 +1,121 @@ +// CP version of the BFile interface, which is much closer to POSIX. +// Functions not available elsewhere that could be useful for optimization: +// fstat, getAddr + +#ifndef GINT_FS_BFILECP_H +#define GINT_FS_BFILECP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +// Only for CP, obviously. +#if GINT_OS_CP + +#define BFileCP_ENOMEM -1 +#define BFileCP_EINVAL -2 +#define BFileCP_EDEVFAIL -3 +#define BFileCP_EMOUNTED -4 +#define BFileCP_EACCES -5 +#define BFileCP_EBADFSID -6 +#define BFileCP_ENOVOLUME -7 +#define BFileCP_ENOPATH -8 +#define BFileCP_EEXIST -9 +#define BFileCP_ENAMETOOLONG -10 +#define BFileCP_EOUTOFBOUND -11 +#define BFileCP_EUNFORMAT -12 +#define BFileCP_ENOSPC -13 +#define BFileCP_ENOENT -14 +#define BFileCP_EISDIRECTORY -15 +#define BFileCP_ESHARE -16 +#define BFileCP_EMFILE -17 +#define BFileCP_EBADF -18 +#define BFileCP_EEOF -19 +#define BFileCP_ENOTEMPTY -20 +#define BFileCP_ECLUSTERSIZEMISMATCH -40 +#define BFileCP_ESYSTEM -99 + +#define BFile_ReadOnly 0x01 +#define BFile_WriteOnly 0x02 +#define BFile_ReadWrite (BFile_ReadOnly | BFile_WriteOnly) +#define BFile_CreateFlag 0x04 +#define BFile_AppendFlag 0x10 + +int BFile_Open(const char *path, int flags); + +int BFile_Read(int fd, void *buf, int size); +int BFile_Write(int fd, void const *buf, int size); + +#define BFileCP_SEEK_SET 0 +#define BFileCP_SEEK_CUR 1 +#define BFileCP_SEEK_END 2 +int BFile_Seek(int fd, int offset, int whence); + +int BFile_Close(int fd); + +int BFile_Remove(char const *path); +int BFile_Rename(char const *oldpath, char const *newpath); +int BFile_Mkdir(char const *path); + +//--- +// Metadata API +//--- + +// Dates are bitfields { year-1980: 8; month-1-12: 4; day-1-31: 4; } +// Times are bitfields { hour: 5; minute: 6; seconds_div2: 5; } +struct BFile_Statbuf { + u32 _1; + u32 size; // file size in bytes + u16 creationDate; + u16 creationTime; + u16 lastModifiedDate; + u16 lastModifiedTime; + u16 _2; + u16 lastAccessDate; +}; + +int BFile_FStat(int fd, struct BFile_Statbuf *statbuf); + +// For API compatibility with older models. +static inline int BFile_Size(int fd) { + struct BFile_Statbuf statbuf; + int rc = BFile_FStat(fd, &statbuf); + return (rc >= 0) ? (int)statbuf.size : rc; +} + +int BFile_Stat(const char *path, struct BFile_Statbuf *statbuf); + +// Same as legacy, uses find API. +int BFile_Ext_Stat(uint16_t const *path, int *type, int *size); + +//--- +// Search API +//--- + +#define BFile_Type_File 1 +#define BFile_Type_Directory 5 + +struct BFile_FileInfo { + u32 _1; + u16 type; /* 1=File, 5=Directory */ + u16 _2; + u32 file_size; /* in bytes; 0 for folders */ + u32 _3, _4; +}; + +// Same as legacy. +int BFile_FindFirst(u16 const *pattern, int *shandle, u16 *foundfile, + struct BFile_FileInfo *fileinfo); +int BFile_FindNext( + int shandle, u16 *foundfile, struct BFile_FileInfo *fileinfo); +int BFile_FindClose(int shandle); + +#endif /* GINT_OS_CP */ + +#ifdef __cplusplus +} +#endif + +#endif /* GINT_FS_BFILECP_H */ diff --git a/src/fs/fugue/fugue.c b/src/fs/fugue/fugue.c index 00185da..fd55df7 100644 --- a/src/fs/fugue/fugue.c +++ b/src/fs/fugue/fugue.c @@ -8,6 +8,7 @@ #include #include "fugue.h" #include "util.h" +#include "bfilecp.h" ssize_t fugue_read(void *data0, void *buf, size_t size) { @@ -19,7 +20,11 @@ ssize_t fugue_read(void *data0, void *buf, size_t size) if(data->pos + (int)size > filesize) size = filesize - data->pos; +#if GINT_OS_CP + int rc = BFile_Read(fugue_fd, buf, size); +#else int rc = BFile_Read(fugue_fd, buf, size, -1); +#endif if(rc < 0) { errno = bfile_error_to_errno(rc); return -1; @@ -100,6 +105,19 @@ off_t fugue_lseek(void *data0, off_t offset, int whence) fugue_fd_t *data = data0; int fugue_fd = data->fd; + // TODO: fugue_lseek: CP400 optimization with native whence? +#if GINT_OS_CP + whence = (whence == SEEK_SET) ? BFileCP_SEEK_SET : + (whence == SEEK_CUR) ? BFileCP_SEEK_CUR : + BFileCP_SEEK_END; + int rc = BFile_Seek(fugue_fd, offset, whence); + if(rc < 0) { + errno = bfile_error_to_errno(rc); + return -1; + } + data->pos = rc; + return rc; +#else int filesize = BFile_Size(fugue_fd); if(whence == SEEK_CUR) @@ -121,6 +139,7 @@ off_t fugue_lseek(void *data0, off_t offset, int whence) /* rc is the amount of space left in the file (including pre-allocated space), so instead just return offset directly */ return offset; +#endif } int fugue_close(void *data0) diff --git a/src/fs/fugue/fugue_dir.c b/src/fs/fugue/fugue_dir.c index d8a8fc0..54292c7 100644 --- a/src/fs/fugue/fugue_dir.c +++ b/src/fs/fugue/fugue_dir.c @@ -9,6 +9,7 @@ #include #include "util.h" #include "fugue.h" +#include "bfilecp.h" typedef struct { @@ -116,7 +117,11 @@ void *fugue_dir_explore(char const *path) rc = BFile_FindFirst(search, &sd, fc_path, &info); if(rc < 0) { +#if GINT_OS_CP + if(rc != BFileCP_ENOENT) // BFileCP_EOUTOFBOUND? +#else if(rc != BFile_EntryNotFound) +#endif errno = bfile_error_to_errno(rc); goto error; } diff --git a/src/fs/fugue/fugue_mkdir.c b/src/fs/fugue/fugue_mkdir.c index 29f10b9..5dba72e 100644 --- a/src/fs/fugue/fugue_mkdir.c +++ b/src/fs/fugue/fugue_mkdir.c @@ -3,11 +3,20 @@ #include #include #include "util.h" +#include "bfilecp.h" int fugue_mkdir(char const *path, GUNUSED mode_t mode) { ENOTSUP_IF_NOT_FUGUE(-1); +#if GINT_OS_CP + int rc = BFile_Mkdir(path); + if(rc < 0) { + errno = bfile_error_to_errno(rc); + return -1; + } + return 0; +#else uint16_t *fcpath = fs_path_normalize_fc(path); if(!fcpath) { errno = ENOMEM; @@ -23,4 +32,5 @@ int fugue_mkdir(char const *path, GUNUSED mode_t mode) free(fcpath); return 0; +#endif } diff --git a/src/fs/fugue/fugue_open.c b/src/fs/fugue/fugue_open.c index c9ecce4..2599c7f 100644 --- a/src/fs/fugue/fugue_open.c +++ b/src/fs/fugue/fugue_open.c @@ -5,32 +5,44 @@ #include #include "util.h" #include "fugue.h" +#include "bfilecp.h" -static int new_file_size; +GUNUSED static int new_file_size; int fugue_open(char const *path, int flags, GUNUSED mode_t mode) { ENOTSUP_IF_NOT_FUGUE(-1); uint16_t *fcpath = fs_path_normalize_fc(path); - int fugue_fd, err, rc=-1, type, fd=-1; + int fugue_fd, rc=-1, type, fd=-1; if(!fcpath) { errno = ENOMEM; return -1; } +#if GINT_OS_CP + char *normpath = fs_path_normalize(path); + if(!normpath) { + errno = ENOMEM; + free(fcpath); + return -1; + } +#define NORMALIZED_PATH normpath +#else +#define NORMALIZED_PATH fcpath +#endif + /* Open mode */ int bfile_mode = BFile_ReadOnly; if(flags & O_WRONLY) bfile_mode = BFile_WriteOnly; else if(flags & O_RDWR) bfile_mode = BFile_ReadWrite; - - /* Exclusive open means no sense unless creation is also requested */ - bool excl = (flags & O_EXCL) && (flags & O_CREAT); - /* Truncation requires the file to be removed/recreated */ - bool trunc = (flags & O_TRUNC) && (flags & O_CREAT); +#if GINT_OS_CP + if(flags & O_APPEND) + bfile_mode |= BFile_AppendFlag; +#endif /* Stat the entry. A special case is needed for the root, which doesn't respond well. fs_path_normalize_fc() normalizes the path so we just @@ -45,8 +57,9 @@ int fugue_open(char const *path, int flags, GUNUSED mode_t mode) if(!exists) type = -1; } - /* If the entry exists and O_EXCL was requested, fail. */ - if(exists && excl) { + /* O_EXCL: Succeed *only* if we're creating the file. Only has an + effect when combined with O_CREAT, unsurprisingly. */ + if(exists && (flags & O_EXCL) && (flags & O_CREAT)) { errno = EEXIST; rc = -1; goto end; @@ -76,35 +89,42 @@ int fugue_open(char const *path, int flags, GUNUSED mode_t mode) goto end; } - /* Try and open the file normally, unless O_TRUNC is specified without - O_EXCL, in which case we simply delete and recreate the file. */ - if(trunc) - fugue_fd = BFile_EntryNotFound; - else - fugue_fd = BFile_Open(fcpath, bfile_mode); + /* We now have a regular file. Before opening it, we may need to: + 1. Delete it to truncate it (BFile never truncates AFAIK) + - If O_TRUNC and the file exists (obviously). + - Deleting and recreating for truncation purposes is allowed when + not setting O_CREAT. In case of error midway, good luck. + 2. Create it (except fx-CP 400 which can create in BFile_Open()) + - If it didn't exist and O_CREAT was allowed; or + - if it did exist but was removed for truncation in step 1. + 3. Finally, open the file. */ - /* If O_TRUNC is requested and either the file exists or we can create - it, remove it. (If fugue_fd < 0 an opening error might still have - occurred so we delete it just in case.) */ - if((flags & O_TRUNC) && (fugue_fd >= 0 || (flags & O_CREAT))) { - if(fugue_fd >= 0) - BFile_Close(fugue_fd); - BFile_Remove(fcpath); - fugue_fd = BFile_EntryNotFound; + /* Delete for truncation. */ + if((flags & O_TRUNC) && exists) { + BFile_Remove(NORMALIZED_PATH); + /* Whatever happens now, allow recreating the file. */ + exists = false; + flags |= O_CREAT; } - /* If the file does not exist and O_CREAT is set, create it */ - if((flags & O_CREAT) && ((flags & O_TRUNC) || fugue_fd < 0)) { - new_file_size = 0; - err = BFile_Create(fcpath, BFile_File, &new_file_size); + /* Create the file now, either directly with BFile_Create(), or with + the appropriate flag on fx-CP 400. */ + if((flags & O_CREAT) && !exists) { +#if GINT_OS_CP + bfile_mode |= BFile_CreateFlag; +#else + int err = BFile_Create(fcpath, BFile_File, &new_file_size); if(err < 0) { errno = bfile_error_to_errno(err); rc = -1; goto end; } - fugue_fd = BFile_Open(fcpath, bfile_mode); +#endif } + /* Proceed with the final BFile_Open() call. */ + fugue_fd = BFile_Open(NORMALIZED_PATH, bfile_mode); + if(fugue_fd < 0) { errno = bfile_error_to_errno(fugue_fd); rc = fugue_fd; @@ -114,10 +134,12 @@ int fugue_open(char const *path, int flags, GUNUSED mode_t mode) /* If O_APPEND is set, move to the end of the file */ // TODO: O_APPEND should move the cursor before *each* write int pos = 0; +#if !GINT_OS_CP if((flags & O_APPEND)) { pos = BFile_Size(fugue_fd); BFile_Seek(fugue_fd, pos); } +#endif /* Return the now-open file descriptor */ fugue_fd_t *data = malloc(sizeof *data); @@ -142,6 +164,9 @@ int fugue_open(char const *path, int flags, GUNUSED mode_t mode) } end: +#if GINT_OS_CP + free(normpath); +#endif free(fcpath); return rc; } diff --git a/src/fs/fugue/fugue_rename.c b/src/fs/fugue/fugue_rename.c index 6eaded6..d3ff266 100644 --- a/src/fs/fugue/fugue_rename.c +++ b/src/fs/fugue/fugue_rename.c @@ -4,35 +4,35 @@ #include #include #include "util.h" +#include "bfilecp.h" int fugue_rename(char const *oldpath, char const *newpath) { ENOTSUP_IF_NOT_FUGUE(-1); - int rc = -1; - uint16_t *fcpath_1 = NULL; - uint16_t *fcpath_2 = NULL; - - fcpath_1 = fs_path_normalize_fc(oldpath); +#if GINT_OS_CP + int rc = BFile_Rename(oldpath, newpath); +#else + u16 *fcpath_1 = fs_path_normalize_fc(oldpath); if(!fcpath_1) { errno = ENOMEM; - goto end; + return -1; } - fcpath_2 = fs_path_normalize_fc(newpath); + u16 *fcpath_2 = fs_path_normalize_fc(newpath); if(!fcpath_2) { errno = ENOMEM; - goto end; + free(fcpath_1); + return -1; } - rc = BFile_Rename(fcpath_1, fcpath_2); - if(rc < 0) { - errno = bfile_error_to_errno(rc); - rc = -1; - } - else rc = 0; - -end: + int rc = BFile_Rename(fcpath_1, fcpath_2); free(fcpath_1); free(fcpath_2); - return rc; +#endif + + if(rc < 0) { + errno = bfile_error_to_errno(rc); + return -1; + } + return 0; } diff --git a/src/fs/fugue/fugue_rmdir.c b/src/fs/fugue/fugue_rmdir.c index ceff28e..c0cf60e 100644 --- a/src/fs/fugue/fugue_rmdir.c +++ b/src/fs/fugue/fugue_rmdir.c @@ -6,6 +6,7 @@ #include #include "util.h" #include "fugue.h" +#include "bfilecp.h" int fugue_rmdir(char const *path) { @@ -33,6 +34,9 @@ int fugue_rmdir(char const *path) return -1; } +#if GINT_OS_CP + int rc = BFile_Remove(path); +#else uint16_t *fcpath = fs_path_normalize_fc(path); if(!fcpath) { errno = ENOMEM; @@ -40,12 +44,12 @@ int fugue_rmdir(char const *path) } int rc = BFile_Remove(fcpath); + free(fcpath); +#endif + if(rc < 0) { errno = bfile_error_to_errno(rc); - rc = -1; + return -1; } - else rc = 0; - - free(fcpath); - return rc; + return 0; } diff --git a/src/fs/fugue/fugue_stat.c b/src/fs/fugue/fugue_stat.c index 6cf43a9..14bc845 100644 --- a/src/fs/fugue/fugue_stat.c +++ b/src/fs/fugue/fugue_stat.c @@ -5,6 +5,7 @@ #include #include #include "util.h" +#include "bfilecp.h" int fugue_stat(char const * restrict path, struct stat * restrict statbuf) { diff --git a/src/fs/fugue/fugue_unlink.c b/src/fs/fugue/fugue_unlink.c index cff9cb8..be51a98 100644 --- a/src/fs/fugue/fugue_unlink.c +++ b/src/fs/fugue/fugue_unlink.c @@ -4,6 +4,7 @@ #include #include #include "util.h" +#include "bfilecp.h" int fugue_unlink(char const *path) { @@ -19,23 +20,25 @@ int fugue_unlink(char const *path) rc = BFile_Ext_Stat(fcpath, &type, &size); if(rc < 0) { errno = bfile_error_to_errno(rc); - rc = -1; - goto end; + free(fcpath); + return -1; } if(bfile_type_to_mode_t(type) != S_IFREG) { errno = ENOTDIR; - rc = -1; - goto end; + free(fcpath); + return -1; } +#if GINT_OS_CP + rc = BFile_Remove(path); +#else rc = BFile_Remove(fcpath); +#endif + free(fcpath); + if(rc < 0) { errno = bfile_error_to_errno(rc); - rc = -1; + return -1; } - else rc = 0; - -end: - free(fcpath); - return rc; + return 0; } diff --git a/src/fs/fugue/util.c b/src/fs/fugue/util.c index 2759bb3..b7131d2 100644 --- a/src/fs/fugue/util.c +++ b/src/fs/fugue/util.c @@ -1,4 +1,5 @@ #include "util.h" +#include "bfilecp.h" #include #include #include @@ -9,6 +10,33 @@ int bfile_error_to_errno(int e) { +#if GINT_OS_CP + switch(e) { + case BFileCP_ENOMEM: return ENOMEM; + case BFileCP_EINVAL: return EINVAL; + case BFileCP_EDEVFAIL: return EIO; + case BFileCP_EMOUNTED: return ENODEV; + case BFileCP_EACCES: return EACCES; + case BFileCP_EBADFSID: return ENODEV; + case BFileCP_ENOVOLUME: return ENODEV; + case BFileCP_ENOPATH: return ENOENT; + case BFileCP_EEXIST: return EEXIST; + case BFileCP_ENAMETOOLONG: return EINVAL; + case BFileCP_EOUTOFBOUND: return EINVAL; + case BFileCP_EUNFORMAT: return EINVAL; + case BFileCP_ENOSPC: return ENOSPC; + case BFileCP_ENOENT: return ENOENT; + case BFileCP_EISDIRECTORY: return EISDIR; + case BFileCP_ESHARE: return EINVAL; + case BFileCP_EMFILE: return EMFILE; + case BFileCP_EBADF: return EBADF; + case BFileCP_EEOF: return EINVAL; + case BFileCP_ENOTEMPTY: return EINVAL; + case BFileCP_ECLUSTERSIZEMISMATCH: return EINVAL; + case BFileCP_ESYSTEM: return EINVAL; + default: return errno; + } +#else /* TODO: Find BFile code for too many fds and map it to ENFILE. */ switch(e) { case BFile_EntryNotFound: return ENOENT; @@ -26,20 +54,28 @@ int bfile_error_to_errno(int e) case BFile_DeviceNotFound: return ENOENT; default: return errno; } +#endif } int bfile_type_to_mode_t(int bfile_type) { +#if GINT_OS_CP + return bfile_type == BFile_Type_Directory ? S_IFDIR : S_IFREG; +#else switch(bfile_type) { case BFile_Type_Directory: return S_IFDIR; case BFile_Type_Dot: return S_IFDIR; case BFile_Type_DotDot: return S_IFDIR; default: return S_IFREG; } +#endif } int bfile_type_to_dirent(int bfile_type) { +#if GINT_OS_CP + return bfile_type == BFile_Type_Directory ? DT_DIR : DT_REG; +#else switch(bfile_type) { case BFile_Type_Directory: return DT_DIR; case BFile_Type_Dot: return DT_DIR; @@ -54,6 +90,7 @@ int bfile_type_to_dirent(int bfile_type) case BFile_Type_Archived: return DT_REG; default: return DT_UNKNOWN; } +#endif } /* Length of FONTCHARACTER and UTF-8 strings, counting only ASCII characters */ From 8e64a8a1074529b099a5619012c03411f4dcbfe7 Mon Sep 17 00:00:00 2001 From: Lephe Date: Sun, 6 Apr 2025 15:49:43 +0200 Subject: [PATCH 3/5] fs: fx-CP 400 fixes, still unreliable when writing as previously known --- src/fs/fugue/fugue_mkdir.c | 21 +++++++++++---------- src/fs/fugue/fugue_open.c | 12 ++++++++---- src/fs/fugue/fugue_unlink.c | 31 +++++++++++++++++++++++-------- src/fs/fugue/util.c | 32 ++++++++++++++++++++++++-------- src/fs/fugue/util.h | 3 +++ src/kernel/hardware.c | 3 +-- src/kernel/syscalls.S | 33 +++++++++++++++++++++++++++++++++ 7 files changed, 103 insertions(+), 32 deletions(-) diff --git a/src/fs/fugue/fugue_mkdir.c b/src/fs/fugue/fugue_mkdir.c index 5dba72e..57e139f 100644 --- a/src/fs/fugue/fugue_mkdir.c +++ b/src/fs/fugue/fugue_mkdir.c @@ -10,12 +10,14 @@ int fugue_mkdir(char const *path, GUNUSED mode_t mode) ENOTSUP_IF_NOT_FUGUE(-1); #if GINT_OS_CP - int rc = BFile_Mkdir(path); - if(rc < 0) { - errno = bfile_error_to_errno(rc); + char *normpath = fs_path_normalize_opt(path, "\\fls0\\", '\\'); + if(!normpath) { + errno = ENOMEM; return -1; } - return 0; + + int rc = BFile_Mkdir(normpath); + free(normpath); #else uint16_t *fcpath = fs_path_normalize_fc(path); if(!fcpath) { @@ -24,13 +26,12 @@ int fugue_mkdir(char const *path, GUNUSED mode_t mode) } int rc = BFile_Create(fcpath, BFile_Folder, NULL); + free(fcpath); +#endif + if(rc < 0) { errno = bfile_error_to_errno(rc); - free(fcpath); - return -1; + rc = -1; } - - free(fcpath); - return 0; -#endif + return rc; } diff --git a/src/fs/fugue/fugue_open.c b/src/fs/fugue/fugue_open.c index 2599c7f..5f7047f 100644 --- a/src/fs/fugue/fugue_open.c +++ b/src/fs/fugue/fugue_open.c @@ -22,15 +22,15 @@ int fugue_open(char const *path, int flags, GUNUSED mode_t mode) } #if GINT_OS_CP - char *normpath = fs_path_normalize(path); + char *normpath = fs_path_normalize_opt(path, "\\fls0\\", '\\'); if(!normpath) { errno = ENOMEM; free(fcpath); return -1; } -#define NORMALIZED_PATH normpath +# define NORMALIZED_PATH normpath #else -#define NORMALIZED_PATH fcpath +# define NORMALIZED_PATH fcpath #endif /* Open mode */ @@ -48,7 +48,11 @@ int fugue_open(char const *path, int flags, GUNUSED mode_t mode) respond well. fs_path_normalize_fc() normalizes the path so we just have to check for the fixed string "\\fls0\". */ bool exists; +#if GINT_OS_CP + if(!memcmp(fcpath, u"\\fls0\\", 14)) { +#else if(!memcmp(fcpath, u"\\\\fls0\\", 16)) { +#endif exists = true; type = BFile_Type_Directory; } @@ -127,7 +131,7 @@ int fugue_open(char const *path, int flags, GUNUSED mode_t mode) if(fugue_fd < 0) { errno = bfile_error_to_errno(fugue_fd); - rc = fugue_fd; + rc = -1; goto end; } diff --git a/src/fs/fugue/fugue_unlink.c b/src/fs/fugue/fugue_unlink.c index be51a98..eb23375 100644 --- a/src/fs/fugue/fugue_unlink.c +++ b/src/fs/fugue/fugue_unlink.c @@ -16,29 +16,44 @@ int fugue_unlink(char const *path) return -1; } +#if GINT_OS_CP + char *normpath = fs_path_normalize_opt(path, "\\fls0\\", '\\'); + if(!normpath) { + errno = ENOMEM; + free(fcpath); + return -1; + } +#endif + int type, size, rc; rc = BFile_Ext_Stat(fcpath, &type, &size); if(rc < 0) { errno = bfile_error_to_errno(rc); - free(fcpath); - return -1; + rc = -1; + goto end; } if(bfile_type_to_mode_t(type) != S_IFREG) { errno = ENOTDIR; - free(fcpath); - return -1; + rc = -1; + goto end; } #if GINT_OS_CP - rc = BFile_Remove(path); + rc = BFile_Remove(normpath); #else rc = BFile_Remove(fcpath); #endif - free(fcpath); if(rc < 0) { errno = bfile_error_to_errno(rc); - return -1; + rc = -1; } - return 0; + rc = 0; + +end: + free(fcpath); +#if GINT_OS_CP + free(normpath); +#endif + return rc; } diff --git a/src/fs/fugue/util.c b/src/fs/fugue/util.c index b7131d2..747ab32 100644 --- a/src/fs/fugue/util.c +++ b/src/fs/fugue/util.c @@ -12,7 +12,7 @@ int bfile_error_to_errno(int e) { #if GINT_OS_CP switch(e) { - case BFileCP_ENOMEM: return ENOMEM; + case BFileCP_ENOMEM: return ENOENT; case BFileCP_EINVAL: return EINVAL; case BFileCP_EDEVFAIL: return EIO; case BFileCP_EMOUNTED: return ENODEV; @@ -206,8 +206,12 @@ char **fs_split_components(char *path, int *count) /* Generalization of fs_path_normalize(). Returns a [char *] if use_fc=false, otherwise returns an [uint16_t *]. */ -static void *path_normalize(char const *path, bool use_fc) +static void *path_normalize( + char const *path, bool use_fc, char const *prefix8, int dirsep) { + if(!prefix8) + prefix8 = "/"; + char *path_dup = strdup(path); if(!path_dup) return NULL; @@ -231,7 +235,8 @@ static void *path_normalize(char const *path, bool use_fc) } /* Count total length */ - int length = (use_fc ? 7 : 1) + (wr >= 1 ? wr - 1 : 0); + int prefix8_len = strlen(prefix8); + int length = (use_fc ? 7 : prefix8_len) + (wr >= 1 ? wr - 1 : 0); for(int i = 0; i < wr; i++) { length += utf8_len(comps[i]); } @@ -241,11 +246,16 @@ static void *path_normalize(char const *path, bool use_fc) uint16_t *fc = malloc((length + 1) * sizeof *fc); uint16_t *fc_init = fc; +#if GINT_OS_CP + memcpy(fc, u"\\fls0\\", 6*2); + fc += 6; +#else memcpy(fc, u"\\\\fls0\\", 7*2); fc += 7; +#endif for(int i = 0; i < wr; i++) { - if(i > 0) *fc++ = '\\'; + if(i > 0) *fc++ = dirsep; utf8_to_fc(fc, comps[i], (size_t)-1); fc += utf8_len(comps[i]); } @@ -258,10 +268,11 @@ static void *path_normalize(char const *path, bool use_fc) else { char *utf8 = malloc(length + 1); char *utf8_init = utf8; - *utf8++ = '/'; + memcpy(utf8, prefix8, prefix8_len); + utf8 += prefix8_len; for(int i = 0; i < wr; i++) { - if(i > 0) *utf8++ = '/'; + if(i > 0) *utf8++ = dirsep; strcpy(utf8, comps[i]); utf8 += utf8_len(comps[i]); } @@ -273,12 +284,17 @@ static void *path_normalize(char const *path, bool use_fc) } } + char *fs_path_normalize(char const *path) { - return path_normalize(path, false); + return path_normalize(path, false, NULL, '/'); } +char *fs_path_normalize_opt(char const *path, char const *prefix, int dirsep) +{ + return path_normalize(path, false, prefix, dirsep); +} uint16_t *fs_path_normalize_fc(char const *path) { - return path_normalize(path, true); + return path_normalize(path, true, NULL, '\\'); } diff --git a/src/fs/fugue/util.h b/src/fs/fugue/util.h index 0f66441..291d721 100644 --- a/src/fs/fugue/util.h +++ b/src/fs/fugue/util.h @@ -44,6 +44,9 @@ uint16_t *utf8_to_fc_alloc(uint16_t *prefix, char const *utf8, /* Same as fc_to_utf8() but allocates a string with malloc(). */ char *fc_to_utf8_alloc(uint16_t const *fc); +/* Same as fs_path_normalize() but with a prefix. If NULL, "/". */ +char *fs_path_normalize_opt(char const *path, char const *prefix, int dirsep); + #ifdef __cplusplus } #endif diff --git a/src/kernel/hardware.c b/src/kernel/hardware.c index 68d3d08..31b8635 100644 --- a/src/kernel/hardware.c +++ b/src/kernel/hardware.c @@ -176,8 +176,7 @@ void hw_detect(void) gint[HWCPUVR] = PVR; gint[HWCPUPR] = PRR; gint[HWCALC] = HWCALC_FXCP400; - // TODO: What filesystem implementation on the fx-CP 400? - gint[HWFS] = HWFS_NONE; + gint[HWFS] = HWFS_FUGUE; gint[HWRAM] = 16 << 20; // TOOD: How much ROM on the fx-CP 400? gint[HWROM] = 0; diff --git a/src/kernel/syscalls.S b/src/kernel/syscalls.S index fa71e9c..9f22036 100644 --- a/src/kernel/syscalls.S +++ b/src/kernel/syscalls.S @@ -33,6 +33,8 @@ .global _BFile_FindFirst .global _BFile_FindNext .global _BFile_FindClose +.global _BFile_FStat // fx-CP +.global _BFile_Mkdir // fx-CP /* Return to menu */ .global ___Timer_Install @@ -289,4 +291,35 @@ ___VRAMRestore: ___Reset: fixed(0xa0000000) +_BFile_Remove: + fixed(0x80057fc8) // atomic + HH2 (= 0x8005794e) +_BFile_Rename: + fixed(0x80057a06) +_BFile_Open: + fixed(0x80057854) +_BFile_Close: + fixed(0x80057912) +_BFile_Seek: + fixed(0x80057a96) +_BFile_Read: + fixed(0x800578a2) +_BFile_Write: + fixed(0x800578da) +_BFile_FindFirst: + fixed(0x8005a2ac) +_BFile_FindNext: + fixed(0x8005a5f0) +_BFile_FindClose: + fixed(0x8005a8ba) +_BFile_FStat: + fixed(0x8005798e) +_BFile_Mkdir: + fixed(0x80057814) +/* +_BFile_GetAddr: + fixed(0x80057c6a) +_BFile_Stat: + fixed(0x800579c2) +*/ + #endif /* GINT_OS_CP */ From 3dedbea70dfcc392b6a596370e598aca5e4fbde0 Mon Sep 17 00:00:00 2001 From: Lephe Date: Sun, 6 Apr 2025 15:54:22 +0200 Subject: [PATCH 4/5] fs: fix incorrect cursor state after pread/pwrite --- src/fs/pread.c | 2 +- src/fs/pwrite.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fs/pread.c b/src/fs/pread.c index d06f777..4d519f1 100644 --- a/src/fs/pread.c +++ b/src/fs/pread.c @@ -19,6 +19,6 @@ ssize_t pread(int fd, void *buf, size_t size, off_t offset) end: /* At the end, always try to restore the current position */ - lseek(fd, current, SEEK_CUR); + lseek(fd, current, SEEK_SET); return rc; } diff --git a/src/fs/pwrite.c b/src/fs/pwrite.c index 10b8ff7..b42ff5c 100644 --- a/src/fs/pwrite.c +++ b/src/fs/pwrite.c @@ -17,6 +17,6 @@ ssize_t pwrite(int fd, const void *buf, size_t size, off_t offset) end: /* At the end, always try to restore the current position */ - lseek(fd, current, SEEK_CUR); + lseek(fd, current, SEEK_SET); return rc; } From 416331d48bde4085cae94127a3cb9e5f3538e33c Mon Sep 17 00:00:00 2001 From: Lephe Date: Sun, 6 Apr 2025 22:00:40 +0200 Subject: [PATCH 5/5] kernel: replace CP400 file functions with Yatis', fixing unstability --- src/kernel/syscalls.S | 50 ++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/src/kernel/syscalls.S b/src/kernel/syscalls.S index 9f22036..5728353 100644 --- a/src/kernel/syscalls.S +++ b/src/kernel/syscalls.S @@ -291,35 +291,41 @@ ___VRAMRestore: ___Reset: fixed(0xa0000000) -_BFile_Remove: - fixed(0x80057fc8) // atomic + HH2 (= 0x8005794e) -_BFile_Rename: - fixed(0x80057a06) -_BFile_Open: - fixed(0x80057854) -_BFile_Close: - fixed(0x80057912) -_BFile_Seek: - fixed(0x80057a96) -_BFile_Read: - fixed(0x800578a2) -_BFile_Write: - fixed(0x800578da) _BFile_FindFirst: fixed(0x8005a2ac) _BFile_FindNext: fixed(0x8005a5f0) _BFile_FindClose: fixed(0x8005a8ba) -_BFile_FStat: - fixed(0x8005798e) +_BFile_Remove: + fixed(0x80057fc8) +_BFile_Open: + fixed(0x80057f1c) +_BFile_Write: + fixed(0x80057f74) +_BFile_Close: + fixed(0x80057fa2) +_BFile_Read: + fixed(0x80057f46) +// _BFile_Flush: +// fixed(0x8005809a) _BFile_Mkdir: - fixed(0x80057814) -/* -_BFile_GetAddr: - fixed(0x80057c6a) + fixed(0x80057ef6) +// _BFile_Mount: +// fixed(0x80057e7c) _BFile_Stat: - fixed(0x800579c2) -*/ + fixed(0x80057fee) +// _BFile_Reclaim: +// fixed(0x80058114) +// _BFile_FsInfo: +// fixed(0x800580ea) +// _BFile_Salvage: +// fixed(0x8005813e) +_BFile_Rename: + fixed(0x80058042) +_BFile_FStat: + fixed(0x80057fee) +_BFile_Seek: + fixed(0x8005806c) #endif /* GINT_OS_CP */