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 "plugin.h"
|
||||
|
||||
static FILE *f;
|
||||
static int f = -1;
|
||||
static DIR *d;
|
||||
static char *current_filename = "";
|
||||
static char current_filename[4096];
|
||||
static enum { IDLE,
|
||||
FILE_READ,
|
||||
FILE_WRITE,
|
||||
DIR_READ } state;
|
||||
static struct dirent *de;
|
||||
|
||||
static void
|
||||
reset(void)
|
||||
void
|
||||
file_cleanup(void)
|
||||
{
|
||||
if(f != NULL) {
|
||||
fclose(f);
|
||||
f = NULL;
|
||||
if(f >= 0) {
|
||||
rb->close(f);
|
||||
f = -1;
|
||||
}
|
||||
if(d != NULL) {
|
||||
closedir(d);
|
||||
rb->closedir(d);
|
||||
d = NULL;
|
||||
}
|
||||
de = NULL;
|
||||
|
@ -47,17 +47,14 @@ reset(void)
|
|||
}
|
||||
|
||||
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)
|
||||
return 0;
|
||||
if(stat(pathname, &st))
|
||||
return fail_nonzero ? snprintf(p, len, "!!!! %s\n", basename) : 0;
|
||||
else if(S_ISDIR(st.st_mode))
|
||||
else if(info.attribute & ATTR_DIRECTORY)
|
||||
return snprintf(p, len, "---- %s\n", basename);
|
||||
else if(st.st_size < 0x10000)
|
||||
return snprintf(p, len, "%04x %s\n", (Uint16)st.st_size, basename);
|
||||
else if(info.size < 0x10000)
|
||||
return snprintf(p, len, "%04x %s\n", (Uint16)info.size, basename);
|
||||
else
|
||||
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
|
||||
file_read_dir(char *dest, Uint16 len)
|
||||
{
|
||||
static char pathname[4096];
|
||||
char *p = dest;
|
||||
if(de == NULL) de = readdir(d);
|
||||
for(; de != NULL; de = readdir(d)) {
|
||||
if(de == NULL) de = rb->readdir(d);
|
||||
for(; de != NULL; de = rb->readdir(d)) {
|
||||
Uint16 n;
|
||||
if(de->d_name[0] == '.' && de->d_name[1] == '\0')
|
||||
continue;
|
||||
snprintf(pathname, sizeof(pathname), "%s/%s", current_filename, de->d_name);
|
||||
n = get_entry(p, len, pathname, de->d_name, 1);
|
||||
n = get_entry(p, len, de->d_name, rb->dir_get_info(d, de));
|
||||
if(!n) break;
|
||||
p += n;
|
||||
len -= n;
|
||||
|
@ -82,10 +77,10 @@ file_read_dir(char *dest, Uint16 len)
|
|||
}
|
||||
|
||||
Uint16
|
||||
file_init(void *filename)
|
||||
file_init(const char *filename)
|
||||
{
|
||||
reset();
|
||||
current_filename = filename;
|
||||
file_cleanup();
|
||||
snprintf(current_filename, sizeof(current_filename), "/%s", (filename[0] == '/') ? &filename[1] : filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -93,14 +88,15 @@ Uint16
|
|||
file_read(void *dest, Uint16 len)
|
||||
{
|
||||
if(state != FILE_READ && state != DIR_READ) {
|
||||
reset();
|
||||
if((d = opendir(current_filename)) != NULL)
|
||||
file_cleanup();
|
||||
if((d = rb->opendir(current_filename)) != NULL)
|
||||
state = DIR_READ;
|
||||
else if((f = fopen(current_filename, "rb")) != NULL)
|
||||
else if((f = rb->open(current_filename, O_RDONLY)) >= 0)
|
||||
state = FILE_READ;
|
||||
}
|
||||
if(state == FILE_READ)
|
||||
return fread(dest, 1, len, f);
|
||||
if(state == FILE_READ) {
|
||||
return rb->read(f, dest, len);
|
||||
}
|
||||
if(state == DIR_READ)
|
||||
return file_read_dir(dest, len);
|
||||
return 0;
|
||||
|
@ -111,13 +107,12 @@ file_write(void *src, Uint16 len, Uint8 flags)
|
|||
{
|
||||
Uint16 ret = 0;
|
||||
if(state != FILE_WRITE) {
|
||||
reset();
|
||||
if((f = fopen(current_filename, (flags & 0x01) ? "ab" : "wb")) != NULL)
|
||||
file_cleanup();
|
||||
if((f = rb->open(current_filename, O_WRONLY | ((flags & 0x01) ? O_APPEND : 0))) >= 0)
|
||||
state = FILE_WRITE;
|
||||
}
|
||||
if(state == FILE_WRITE) {
|
||||
if((ret = fwrite(src, 1, len, f)) > 0 && fflush(f) != 0)
|
||||
ret = 0;
|
||||
ret = rb->write(f, src, len);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -125,16 +120,31 @@ file_write(void *src, Uint16 len, Uint8 flags)
|
|||
Uint16
|
||||
file_stat(void *dest, Uint16 len)
|
||||
{
|
||||
DIR *sd;
|
||||
struct dirent *sde;
|
||||
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;
|
||||
else
|
||||
basename = current_filename;
|
||||
return get_entry(dest, len, current_filename, basename, 0);
|
||||
}
|
||||
if(sd == NULL) return 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
|
||||
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.
|
||||
*/
|
||||
|
||||
Uint16 file_init(void *filename);
|
||||
Uint16 file_init(const char *filename);
|
||||
Uint16 file_read(void *dest, Uint16 len);
|
||||
Uint16 file_write(void *src, Uint16 len, Uint8 flags);
|
||||
Uint16 file_stat(void *dest, Uint16 len);
|
||||
Uint16 file_delete(void);
|
||||
void file_cleanup(void);
|
||||
|
|
|
@ -18,7 +18,7 @@ TODO clean up
|
|||
|
||||
#include "uxn.h"
|
||||
#include "devices/ppu.h"
|
||||
// #include "devices/file.h"
|
||||
#include "devices/file.h"
|
||||
#include "plugin.h"
|
||||
#include "keymaps.h"
|
||||
#include <stdio.h>
|
||||
|
@ -164,6 +164,20 @@ screen_talk(Device *d, Uint8 b0, Uint8 w)
|
|||
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
|
||||
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);
|
||||
/* control */ devctrl = uxn_port(&u, 0x8, 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);
|
||||
/* empty */ uxn_port(&u, 0xc, 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);
|
||||
uxn_eval(&u, 0x0100);
|
||||
run();
|
||||
file_cleanup();
|
||||
return PLUGIN_OK;
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue