Implement File device with Rockbox API.
This commit is contained in:
parent
52883316fd
commit
ba0e3268e8
|
@ -22,24 +22,24 @@ WITH REGARD TO THIS SOFTWARE.
|
||||||
//#include <unistd.h>
|
//#include <unistd.h>
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
|
||||||
static FILE *f;
|
static int f = -1;
|
||||||
static DIR *d;
|
static DIR *d;
|
||||||
static char *current_filename = "";
|
static char current_filename[4096];
|
||||||
static enum { IDLE,
|
static enum { IDLE,
|
||||||
FILE_READ,
|
FILE_READ,
|
||||||
FILE_WRITE,
|
FILE_WRITE,
|
||||||
DIR_READ } state;
|
DIR_READ } state;
|
||||||
static struct dirent *de;
|
static struct dirent *de;
|
||||||
|
|
||||||
static void
|
void
|
||||||
reset(void)
|
file_cleanup(void)
|
||||||
{
|
{
|
||||||
if(f != NULL) {
|
if(f >= 0) {
|
||||||
fclose(f);
|
rb->close(f);
|
||||||
f = NULL;
|
f = -1;
|
||||||
}
|
}
|
||||||
if(d != NULL) {
|
if(d != NULL) {
|
||||||
closedir(d);
|
rb->closedir(d);
|
||||||
d = NULL;
|
d = NULL;
|
||||||
}
|
}
|
||||||
de = NULL;
|
de = NULL;
|
||||||
|
@ -47,17 +47,14 @@ reset(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
static Uint16
|
static Uint16
|
||||||
get_entry(char *p, Uint16 len, const char *pathname, const char *basename, int fail_nonzero)
|
get_entry(char *p, Uint16 len, const char *basename, struct dirinfo info)
|
||||||
{
|
{
|
||||||
struct stat st;
|
|
||||||
if(len < strlen(basename) + 7)
|
if(len < strlen(basename) + 7)
|
||||||
return 0;
|
return 0;
|
||||||
if(stat(pathname, &st))
|
else if(info.attribute & ATTR_DIRECTORY)
|
||||||
return fail_nonzero ? snprintf(p, len, "!!!! %s\n", basename) : 0;
|
|
||||||
else if(S_ISDIR(st.st_mode))
|
|
||||||
return snprintf(p, len, "---- %s\n", basename);
|
return snprintf(p, len, "---- %s\n", basename);
|
||||||
else if(st.st_size < 0x10000)
|
else if(info.size < 0x10000)
|
||||||
return snprintf(p, len, "%04x %s\n", (Uint16)st.st_size, basename);
|
return snprintf(p, len, "%04x %s\n", (Uint16)info.size, basename);
|
||||||
else
|
else
|
||||||
return snprintf(p, len, "???? %s\n", basename);
|
return snprintf(p, len, "???? %s\n", basename);
|
||||||
}
|
}
|
||||||
|
@ -65,15 +62,13 @@ get_entry(char *p, Uint16 len, const char *pathname, const char *basename, int f
|
||||||
static Uint16
|
static Uint16
|
||||||
file_read_dir(char *dest, Uint16 len)
|
file_read_dir(char *dest, Uint16 len)
|
||||||
{
|
{
|
||||||
static char pathname[4096];
|
|
||||||
char *p = dest;
|
char *p = dest;
|
||||||
if(de == NULL) de = readdir(d);
|
if(de == NULL) de = rb->readdir(d);
|
||||||
for(; de != NULL; de = readdir(d)) {
|
for(; de != NULL; de = rb->readdir(d)) {
|
||||||
Uint16 n;
|
Uint16 n;
|
||||||
if(de->d_name[0] == '.' && de->d_name[1] == '\0')
|
if(de->d_name[0] == '.' && de->d_name[1] == '\0')
|
||||||
continue;
|
continue;
|
||||||
snprintf(pathname, sizeof(pathname), "%s/%s", current_filename, de->d_name);
|
n = get_entry(p, len, de->d_name, rb->dir_get_info(d, de));
|
||||||
n = get_entry(p, len, pathname, de->d_name, 1);
|
|
||||||
if(!n) break;
|
if(!n) break;
|
||||||
p += n;
|
p += n;
|
||||||
len -= n;
|
len -= n;
|
||||||
|
@ -82,10 +77,10 @@ file_read_dir(char *dest, Uint16 len)
|
||||||
}
|
}
|
||||||
|
|
||||||
Uint16
|
Uint16
|
||||||
file_init(void *filename)
|
file_init(const char *filename)
|
||||||
{
|
{
|
||||||
reset();
|
file_cleanup();
|
||||||
current_filename = filename;
|
snprintf(current_filename, sizeof(current_filename), "/%s", (filename[0] == '/') ? &filename[1] : filename);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,14 +88,15 @@ Uint16
|
||||||
file_read(void *dest, Uint16 len)
|
file_read(void *dest, Uint16 len)
|
||||||
{
|
{
|
||||||
if(state != FILE_READ && state != DIR_READ) {
|
if(state != FILE_READ && state != DIR_READ) {
|
||||||
reset();
|
file_cleanup();
|
||||||
if((d = opendir(current_filename)) != NULL)
|
if((d = rb->opendir(current_filename)) != NULL)
|
||||||
state = DIR_READ;
|
state = DIR_READ;
|
||||||
else if((f = fopen(current_filename, "rb")) != NULL)
|
else if((f = rb->open(current_filename, O_RDONLY)) >= 0)
|
||||||
state = FILE_READ;
|
state = FILE_READ;
|
||||||
}
|
}
|
||||||
if(state == FILE_READ)
|
if(state == FILE_READ) {
|
||||||
return fread(dest, 1, len, f);
|
return rb->read(f, dest, len);
|
||||||
|
}
|
||||||
if(state == DIR_READ)
|
if(state == DIR_READ)
|
||||||
return file_read_dir(dest, len);
|
return file_read_dir(dest, len);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -111,13 +107,12 @@ file_write(void *src, Uint16 len, Uint8 flags)
|
||||||
{
|
{
|
||||||
Uint16 ret = 0;
|
Uint16 ret = 0;
|
||||||
if(state != FILE_WRITE) {
|
if(state != FILE_WRITE) {
|
||||||
reset();
|
file_cleanup();
|
||||||
if((f = fopen(current_filename, (flags & 0x01) ? "ab" : "wb")) != NULL)
|
if((f = rb->open(current_filename, O_WRONLY | ((flags & 0x01) ? O_APPEND : 0))) >= 0)
|
||||||
state = FILE_WRITE;
|
state = FILE_WRITE;
|
||||||
}
|
}
|
||||||
if(state == FILE_WRITE) {
|
if(state == FILE_WRITE) {
|
||||||
if((ret = fwrite(src, 1, len, f)) > 0 && fflush(f) != 0)
|
ret = rb->write(f, src, len);
|
||||||
ret = 0;
|
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -125,16 +120,31 @@ file_write(void *src, Uint16 len, Uint8 flags)
|
||||||
Uint16
|
Uint16
|
||||||
file_stat(void *dest, Uint16 len)
|
file_stat(void *dest, Uint16 len)
|
||||||
{
|
{
|
||||||
|
DIR *sd;
|
||||||
|
struct dirent *sde;
|
||||||
char *basename = strrchr(current_filename, '/');
|
char *basename = strrchr(current_filename, '/');
|
||||||
if(basename != NULL)
|
if(basename != current_filename) {
|
||||||
|
*basename = '\0';
|
||||||
|
sd = rb->opendir(current_filename);
|
||||||
|
*basename++ = '/';
|
||||||
|
} else {
|
||||||
|
sd = rb->opendir("/");
|
||||||
++basename;
|
++basename;
|
||||||
else
|
}
|
||||||
basename = current_filename;
|
if(sd == NULL) return 0;
|
||||||
return get_entry(dest, len, current_filename, basename, 0);
|
while((sde = rb->readdir(sd)) != NULL) {
|
||||||
|
if(!strcmp(sde->d_name, basename)) {
|
||||||
|
Uint16 ret = get_entry(dest, len, basename, rb->dir_get_info(sd, sde));
|
||||||
|
rb->closedir(sd);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rb->closedir(sd);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Uint16
|
Uint16
|
||||||
file_delete(void)
|
file_delete(void)
|
||||||
{
|
{
|
||||||
return unlink(current_filename);
|
return rb->remove(current_filename);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,8 +10,9 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
WITH REGARD TO THIS SOFTWARE.
|
WITH REGARD TO THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Uint16 file_init(void *filename);
|
Uint16 file_init(const char *filename);
|
||||||
Uint16 file_read(void *dest, Uint16 len);
|
Uint16 file_read(void *dest, Uint16 len);
|
||||||
Uint16 file_write(void *src, Uint16 len, Uint8 flags);
|
Uint16 file_write(void *src, Uint16 len, Uint8 flags);
|
||||||
Uint16 file_stat(void *dest, Uint16 len);
|
Uint16 file_stat(void *dest, Uint16 len);
|
||||||
Uint16 file_delete(void);
|
Uint16 file_delete(void);
|
||||||
|
void file_cleanup(void);
|
||||||
|
|
|
@ -18,7 +18,7 @@ TODO clean up
|
||||||
|
|
||||||
#include "uxn.h"
|
#include "uxn.h"
|
||||||
#include "devices/ppu.h"
|
#include "devices/ppu.h"
|
||||||
// #include "devices/file.h"
|
#include "devices/file.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
#include "keymaps.h"
|
#include "keymaps.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -164,6 +164,20 @@ screen_talk(Device *d, Uint8 b0, Uint8 w)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
file_talk(Device *d, Uint8 b0, Uint8 w)
|
||||||
|
{
|
||||||
|
if(w) switch(b0) {
|
||||||
|
case 0x1: d->vector = peek16(d->dat, 0x0); break;
|
||||||
|
case 0x9: poke16(d->dat, 0x2, file_init(&d->mem[peek16(d->dat, 0x8)])); break;
|
||||||
|
case 0xd: poke16(d->dat, 0x2, file_read(&d->mem[peek16(d->dat, 0xc)], peek16(d->dat, 0xa))); break;
|
||||||
|
case 0xf: poke16(d->dat, 0x2, file_write(&d->mem[peek16(d->dat, 0xe)], peek16(d->dat, 0xa), d->dat[0x7])); break;
|
||||||
|
case 0x5: poke16(d->dat, 0x2, file_stat(&d->mem[peek16(d->dat, 0x4)], peek16(d->dat, 0xa))); break;
|
||||||
|
case 0x6: poke16(d->dat, 0x2, file_delete()); break;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
nil_talk(Device *d, Uint8 b0, Uint8 w)
|
nil_talk(Device *d, Uint8 b0, Uint8 w)
|
||||||
{
|
{
|
||||||
|
@ -329,7 +343,7 @@ enum plugin_status plugin_start(const void* parameter)
|
||||||
/* empty */ uxn_port(&u, 0x7, nil_talk);
|
/* empty */ uxn_port(&u, 0x7, nil_talk);
|
||||||
/* control */ devctrl = uxn_port(&u, 0x8, nil_talk);
|
/* control */ devctrl = uxn_port(&u, 0x8, nil_talk);
|
||||||
/* mouse */ uxn_port(&u, 0x9, nil_talk);
|
/* mouse */ uxn_port(&u, 0x9, nil_talk);
|
||||||
/* file */ uxn_port(&u, 0xa, nil_talk);
|
/* file */ uxn_port(&u, 0xa, file_talk);
|
||||||
/* datetime */ uxn_port(&u, 0xb, datetime_talk);
|
/* datetime */ uxn_port(&u, 0xb, datetime_talk);
|
||||||
/* empty */ uxn_port(&u, 0xc, nil_talk);
|
/* empty */ uxn_port(&u, 0xc, nil_talk);
|
||||||
/* empty */ uxn_port(&u, 0xd, nil_talk);
|
/* empty */ uxn_port(&u, 0xd, nil_talk);
|
||||||
|
@ -337,6 +351,7 @@ enum plugin_status plugin_start(const void* parameter)
|
||||||
/* empty */ uxn_port(&u, 0xf, nil_talk);
|
/* empty */ uxn_port(&u, 0xf, nil_talk);
|
||||||
uxn_eval(&u, 0x0100);
|
uxn_eval(&u, 0x0100);
|
||||||
run();
|
run();
|
||||||
|
file_cleanup();
|
||||||
return PLUGIN_OK;
|
return PLUGIN_OK;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue