File device: drop offset shorts, add stat and delete.

This commit is contained in:
Andrew Alderwick 2021-11-05 21:32:45 +00:00
parent 9b15f90008
commit c970e2c5ef
20 changed files with 240 additions and 54 deletions

View File

@ -17,6 +17,8 @@ then
clang-format -i src/devices/ppu.c
clang-format -i src/devices/apu.h
clang-format -i src/devices/apu.c
clang-format -i src/devices/file.h
clang-format -i src/devices/file.c
clang-format -i src/uxnasm.c
clang-format -i src/uxnemu.c
clang-format -i src/uxncli.c
@ -49,8 +51,8 @@ fi
echo "Building.."
cc ${CFLAGS} src/uxnasm.c -o bin/uxnasm
cc ${CFLAGS} ${CORE} src/devices/ppu.c src/devices/apu.c src/uxnemu.c ${UXNEMU_LDFLAGS} -o bin/uxnemu
cc ${CFLAGS} ${CORE} src/uxncli.c -o bin/uxncli
cc ${CFLAGS} ${CORE} src/devices/file.c src/devices/ppu.c src/devices/apu.c src/uxnemu.c ${UXNEMU_LDFLAGS} -o bin/uxnemu
cc ${CFLAGS} ${CORE} src/devices/file.c src/uxncli.c -o bin/uxncli
if [ -d "$HOME/bin" ]
then

View File

@ -21,7 +21,7 @@
|60 @Audio3 [ &vector $2 &position $2 &output $1 &pad $3 &adsr $2 &length $2 &addr $2 &volume $1 &pitch $1 ]
|80 @Controller [ &vector $2 &button $1 &key $1 ]
|90 @Mouse [ &vector $2 &x $2 &y $2 &state $1 &wheel $1 ]
|a0 @File [ &vector $2 &success $2 &offset-hs $2 &offset-ls $2 &name $2 &length $2 &load $2 &save $2 ]
|a0 @File [ &vector $2 &name $2 &length $2 &success $2 &load $2 &save $2 &stat $2 &delete $1 ]
|b0 @DateTime [ &year $2 &month $1 &day $1 &hour $1 &minute $1 &second $1 &dotw $1 &doty $2 &isdst $1 ]
( variables )

View File

@ -2,7 +2,7 @@
|00 @System [ &vector $2 &wst $1 &rst $1 &pad $4 &r $2 &g $2 &b $2 &debug $1 &halt $1 ]
|10 @Console [ &vector $2 &read $1 &pad $5 &write $1 &error $1 ]
|a0 @File [ &vector $2 &success $2 &offset-hs $2 &offset-ls $2 &name $2 &length $2 &load $2 &save $2 ]
|a0 @File [ &vector $2 &name $2 &length $2 &success $2 &load $2 &save $2 &stat $2 &delete $1 ]
( vectors )
@ -51,7 +51,6 @@
that will prevent an infinite loop.
)
;&dest-file .File/name DEO2
#0000 .File/offset-ls DEO2
#ff00 .File/length DEO2
#0100 .File/load
LIT DEO2 #00ff STA

View File

@ -30,7 +30,7 @@
|70 @Midi [ &vector $2 &channel $1 &note $1 &velocity $1 ]
|80 @Controller [ &vector $2 &button $1 &key $1 ]
|90 @Mouse [ &vector $2 &x $2 &y $2 &state $1 &wheel $1 ]
|a0 @File [ &vector $2 &success $2 &offset-hs $2 &offset-ls $2 &name $2 &length $2 &load $2 &save $2 ]
|a0 @File [ &vector $2 &name $2 &length $2 &success $2 &load $2 &save $2 &stat $2 &delete $1 ]
( variables )

View File

@ -12,7 +12,7 @@
|00 @System &vector $2 &pad $6 &r $2 &g $2 &b $2
|20 @Screen &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1
|a0 @File &vector $2 &success $2 &offset-hs $2 &offset-ls $2 &name $2 &length $2 &load $2 &save $2
|a0 @File &vector $2 &name $2 &length $2 &success $2 &load $2 &save $2 &stat $2 &delete $1
( variables )

View File

@ -27,7 +27,7 @@
|70 @Midi [ &vector $2 &channel $1 &note $1 &velocity $1 ]
|80 @Controller [ &vector $2 &button $1 &key $1 ]
|90 @Mouse [ &vector $2 &x $2 &y $2 &state $1 &wheel $1 ]
|a0 @File [ &vector $2 &success $2 &offset-hs $2 &offset-ls $2 &name $2 &length $2 &load $2 &save $2 ]
|a0 @File [ &vector $2 &name $2 &length $2 &success $2 &load $2 &save $2 &stat $2 &delete $1 ]
( variables )

View File

@ -4,7 +4,7 @@
|00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ]
|20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ]
|a0 @File [ &vector $2 &success $2 &offset-hs $2 &offset-ls $2 &name $2 &length $2 &load $2 &save $2 ]
|a0 @File [ &vector $2 &name $2 &length $2 &success $2 &load $2 &save $2 &stat $2 &delete $1 ]
( variables )

View File

@ -3,7 +3,7 @@
( devices )
|00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ]
|a0 @File [ &vector $2 &success $2 &offset-hs $2 &offset-ls $2 &name $2 &length $2 &load $2 &save $2 ]
|a0 @File [ &vector $2 &name $2 &length $2 &success $2 &load $2 &save $2 &stat $2 &delete $1 ]
( variables )

View File

@ -8,7 +8,7 @@
|00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ]
|10 @Console [ &pad $8 &write $1 ]
|20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ]
|a0 @File [ &vector $2 &success $2 &offset-hs $2 &offset-ls $2 &name $2 &length $2 &load $2 &save $2 ]
|a0 @File [ &vector $2 &name $2 &length $2 &success $2 &load $2 &save $2 &stat $2 &delete $1 ]
( variables )

View File

@ -7,7 +7,7 @@
|00 @System [ &vector $2 &pad $6 &r $2 &g $2 &b $2 ]
|20 @Screen [ &vector $2 &width $2 &height $2 &auto $1 &pad $1 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ]
|a0 @File [ &vector $2 &success $2 &offset-hs $2 &offset-ls $2 &name $2 &length $2 &load $2 &save $2 ]
|a0 @File [ &vector $2 &name $2 &length $2 &success $2 &load $2 &save $2 &stat $2 &delete $1 ]
( variables )

View File

@ -196,12 +196,11 @@
@asma-init-next-pass ( -- )
;asma/pass LDA INC ;asma/pass STA
;asma-write-buffer ;asma-output/ptr STA2
#0000 DUP2k
;asma-output/offset STA2
#0000 DUP2
;asma/addr STA2
;asma/state STA
#01 SWP ( 0100 ) ;asma/written-addr STA2
;&preamble-end ;&preamble SUB2k ,asma-assemble-chunk JSR POP2 POP2
;&preamble-end ;&preamble SUB2k ;asma-assemble-chunk JSR2 POP2 POP2
JMP2r
&preamble
@ -498,15 +497,14 @@ include projects/library/binary-tree.tal
NIP2 ( start* )
,&after-flush JMP
@asma-output [ &ptr $2 &offset $2 ]
@asma-output [ &ptr $2 ]
@asma-flush-ignore ( len* -- )
POP2
JMP2r
@asma-flush-to-file ( len* -- )
DUP2 .File/length DEO2
,asma-output/offset LDR2 DUP2 .File/offset-ls DEO2 ADD2 ,asma-output/offset STR2
.File/length DEO2
;asma/dest-filename LDA2 .File/name DEO2
;asma-write-buffer .File/save DEO2
JMP2r

View File

@ -2,6 +2,14 @@
# Summary
*** CAUTION: this library is deprecated! ***
Chunked file reads are now possible in the File device directly: just use
File/load or File/save multiple times. This library exists for compatibility to
keep asma going until it gets a more substantial rewrite.
***
Reads a file in chunks - perfect for when you have a small buffer or when you
don't know the file size. Copes with files up to 4,294,967,295 bytes long.
@ -17,9 +25,11 @@ don't know the file size. Copes with files up to 4,294,967,295 bytes long.
&loop
STH2kr .File/name DEO2 ( F* U* B* OL* OH* SZ* / FN* )
STH2k .File/length DEO2 ( F* U* B* OL* OH* / FN* SZ* )
STH2k .File/offset-hs DEO2 ( F* U* B* OL* / FN* SZ* OH* )
STH2k .File/offset-ls DEO2 ( F* U* B* / FN* SZ* OH* OL* )
STH2k ,ffwd/length STR2 ( F* U* B* OL* OH* / FN* SZ* )
STH2 ( F* U* B* OL* / FN* SZ* OH* )
STH2k ,ffwd/offset STR2 ( F* U* B* / FN* SZ* OH* OL* )
DUP2 ,ffwd/addr STR2
,ffwd JSR
SWP2 ( F* B* U* / FN* SZ* OH* OL* )
ROT2k NIP2 ( F* B* U* B* F* / FN* SZ* OH* OL* )
OVR2 .File/load DEO2 ( F* B* U* B* F* / FN* SZ* OH* OL* )
@ -40,6 +50,25 @@ don't know the file size. Copes with files up to 4,294,967,295 bytes long.
STH2r STH2r ( F* U'* B* OL'* OH'* SZ* / FN* )
,&loop JMP
@ffwd
LIT2 &length $2
LIT2 &offset $2
&coarse ( length* offset* )
GTH2k ,&fine JCN
OVR2 .File/length DEO2
,&addr LDR2 .File/load DEO2
OVR2 SUB2
,&coarse JMP
&fine ( length* offset* )
.File/length DEO2 ( length* )
,&addr LDR2 .File/load DEO2
.File/length DEO2 ( )
JMP2r
&addr $2
(
# Arguments

View File

@ -11,8 +11,6 @@
)
.File/name DEO2
#0000 .File/offset-hs DEO2
#0000 .File/offset-ls DEO2
( return if file can't be found, or zero length )
#0001 .File/length DEO2

View File

@ -1,8 +1,8 @@
( devices )
|00 @System [ &vector $2 &wst $1 &rst $1 &pad $4 &r $2 &g $2 &b $2 &debug $1 &halt $1 ]
|10 @Console [ &vector $2 &read $1 &pad $5 &write $1 &error $1 ]
|a0 @File [ &vector $2 &success $2 &offset-hs $2 &offset-ls $2 &name $2 &length $2 &load $2 &save $2 ]
|00 @System [ &vector $2 &wst $1 &rst $1 &pad $4 &r $2 &g $2 &b $2 &debug $1 &halt $1 ]
|10 @Console [ &vector $2 &read $1 &pad $5 &write $1 &error $1 ]
|a0 @File [ &vector $2 &name $2 &length $2 &success $2 &load $2 &save $2 &stat $2 &delete $1 ]
( vectors )

View File

@ -35,7 +35,7 @@
|30 @Audio0 [ &vector $2 &position $2 &output $1 &pad $3 &adsr $2 &length $2 &addr $2 &volume $1 &pitch $1 ]
|80 @Controller [ &vector $2 &button $1 &key $1 ]
|90 @Mouse [ &vector $2 &x $2 &y $2 &state $1 &wheel $1 ]
|a0 @File [ &vector $2 &success $2 &offset-hs $2 &offset-ls $2 &name $2 &length $2 &load $2 &save $2 ]
|a0 @File [ &vector $2 &name $2 &length $2 &success $2 &load $2 &save $2 &stat $2 &delete $1 ]
( variables )

View File

@ -22,7 +22,7 @@
|20 @Screen &vector $2 &width $2 &height $2 &auto $1 &pad $1 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1
|80 @Controller [ &vector $2 &button $1 &key $1 ]
|90 @Mouse [ &vector $2 &x $2 &y $2 &state $1 &wheel $1 ]
|a0 @File &vector $2 &success $2 &offset-hs $2 &offset-ls $2 &name $2 &length $2 &load $2 &save $2
|a0 @File &vector $2 &name $2 &length $2 &success $2 &load $2 &save $2 &stat $2 &delete $1
|b0 @DateTime [ &year $2 &month $1 &day $1 &hour $1 &minute $1 &second $1 &dotw $1 &doty $2 &isdst $1 ]
( variables )

135
src/devices/file.c Normal file
View File

@ -0,0 +1,135 @@
#include "../uxn.h"
#include "file.h"
/*
Copyright (c) 2021 Devine Lu Linvega
Copyright (c) 2021 Andrew Alderwick
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE.
*/
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
static FILE *f;
static DIR *d;
static int dir_fd;
static char *current_filename;
static enum { IDLE,
FILE_READ,
FILE_WRITE,
DIR_READ } state;
static struct dirent *de;
static char hex[] = "0123456789abcdef";
static void
reset(void)
{
if(f != NULL) {
fclose(f);
f = NULL;
}
if(d != NULL) {
closedir(d);
d = NULL;
}
de = NULL;
state = IDLE;
}
void
file_prepare(void *filename)
{
reset();
current_filename = (char *)filename;
}
static Uint16
write_entry(char *p, Uint16 len, const char *filename, struct stat *st)
{
if(len < strlen(filename) + 7) return 0;
memcpy(p, "???? ", 5);
strcpy(p + 5, filename);
strcat(p, "\n");
if(S_ISDIR(st->st_mode)) {
memcpy(p, "---- ", 5);
} else if(st->st_size < 0x10000) {
p[0] = hex[(st->st_size >> 12) & 0xf];
p[1] = hex[(st->st_size >> 8) & 0xf];
p[2] = hex[(st->st_size >> 4) & 0xf];
p[3] = hex[(st->st_size >> 0) & 0xf];
}
return strlen(p);
}
Uint16
file_read(void *dest, Uint16 len)
{
if(state != FILE_READ && state != DIR_READ) {
reset();
if((d = opendir(current_filename)) != NULL) {
state = DIR_READ;
dir_fd = dirfd(d);
} else if((f = fopen(current_filename, "rb")) != NULL)
state = FILE_READ;
}
if(state == FILE_READ)
return fread(dest, 1, len, f);
if(state == DIR_READ) {
char *p = dest;
if(de == NULL) de = readdir(d);
for(; de != NULL; de = readdir(d)) {
struct stat st;
Uint16 n;
if(de->d_name[0] == '.' && de->d_name[1] == '\0')
continue;
if(fstatat(dir_fd, de->d_name, &st, 0))
continue;
n = write_entry(p, len, de->d_name, &st);
if(!n) break;
p += n;
len -= n;
}
return p - (char *)dest;
}
return 0;
}
Uint16
file_write(void *src, Uint16 len)
{
if(state != FILE_WRITE) {
reset();
if((f = fopen(current_filename, "ab")) != NULL)
state = FILE_WRITE;
}
if(state == FILE_WRITE)
return fwrite(src, 1, len, f);
return 0;
}
Uint16
file_stat(void *dest, Uint16 len)
{
struct stat st;
if(stat(current_filename, &st))
return 0;
return write_entry((char *)dest, len, current_filename, &st);
}
Uint16
file_delete(void)
{
return unlink(current_filename);
}

17
src/devices/file.h Normal file
View File

@ -0,0 +1,17 @@
/*
Copyright (c) 2021 Devine Lu Linvega
Copyright (c) 2021 Andrew Alderwick
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE.
*/
void file_prepare(void *filename);
Uint16 file_read(void *dest, Uint16 len);
Uint16 file_write(void *src, Uint16 len);
Uint16 file_stat(void *dest, Uint16 len);
Uint16 file_delete();

View File

@ -2,6 +2,7 @@
#include <unistd.h>
#include <time.h>
#include "uxn.h"
#include "devices/file.h"
/*
Copyright (c) 2021 Devine Lu Linvega
@ -78,19 +79,22 @@ console_deo(Device *d, Uint8 port)
static void
file_deo(Device *d, Uint8 port)
{
Uint8 read = port == 0xd;
if(read || port == 0xf) {
char *name = (char *)&d->mem[peek16(d->dat, 0x8)];
Uint16 result = 0, length = peek16(d->dat, 0xa);
long offset = (peek16(d->dat, 0x4) << 16) + peek16(d->dat, 0x6);
Uint16 addr = peek16(d->dat, port - 1);
FILE *f = fopen(name, read ? "rb" : (offset ? "ab" : "wb"));
if(f) {
if(fseek(f, offset, SEEK_SET) != -1)
result = read ? fread(&d->mem[addr], 1, length, f) : fwrite(&d->mem[addr], 1, length, f);
fclose(f);
}
poke16(d->dat, 0x2, result);
switch(port) {
case 0x3:
file_prepare(&d->mem[peek16(d->dat, 0x2)]);
break;
case 0x9:
poke16(d->dat, 0x6, file_read(&d->mem[peek16(d->dat, 0x8)], peek16(d->dat, 0x4)));
break;
case 0xb:
poke16(d->dat, 0x6, file_write(&d->mem[peek16(d->dat, 0xa)], peek16(d->dat, 0x4)));
break;
case 0xd:
poke16(d->dat, 0x6, file_stat(&d->mem[peek16(d->dat, 0xc)], peek16(d->dat, 0x4)));
break;
case 0xe:
poke16(d->dat, 0x6, file_delete());
break;
}
}

View File

@ -8,6 +8,7 @@
#include <SDL.h>
#include "devices/ppu.h"
#include "devices/apu.h"
#include "devices/file.h"
#pragma GCC diagnostic pop
/*
@ -370,19 +371,22 @@ screen_deo(Device *d, Uint8 port)
static void
file_deo(Device *d, Uint8 port)
{
Uint8 read = port == 0xd;
if(read || port == 0xf) {
char *name = (char *)&d->mem[peek16(d->dat, 0x8)];
Uint16 result = 0, length = peek16(d->dat, 0xa);
long offset = (peek16(d->dat, 0x4) << 16) + peek16(d->dat, 0x6);
Uint16 addr = peek16(d->dat, port - 1);
FILE *f = fopen(name, read ? "rb" : (offset ? "ab" : "wb"));
if(f) {
if(fseek(f, offset, SEEK_SET) != -1)
result = read ? fread(&d->mem[addr], 1, length, f) : fwrite(&d->mem[addr], 1, length, f);
fclose(f);
}
poke16(d->dat, 0x2, result);
switch(port) {
case 0x3:
file_prepare(&d->mem[peek16(d->dat, 0x2)]);
break;
case 0x9:
poke16(d->dat, 0x6, file_read(&d->mem[peek16(d->dat, 0x8)], peek16(d->dat, 0x4)));
break;
case 0xb:
poke16(d->dat, 0x6, file_write(&d->mem[peek16(d->dat, 0xa)], peek16(d->dat, 0x4)));
break;
case 0xd:
poke16(d->dat, 0x6, file_stat(&d->mem[peek16(d->dat, 0xc)], peek16(d->dat, 0x4)));
break;
case 0xe:
poke16(d->dat, 0x6, file_delete());
break;
}
}