analog/v2-analog-rev1/fs/fs.c
2023-01-29 10:50:12 -05:00

229 lines
5.9 KiB
C

#include <string.h>
#include <pico/stdlib.h>
#include <pico/multicore.h>
#include "common/config.h"
#include "common/buffers.h"
#include "fs/businterface.h"
#include "fs/fs.h"
#include "pico_hal.h"
typedef struct {
int handle;
bool valid;
} fs_file_t;
#define FS_MAXFILE 8
fs_file_t fs_file[FS_MAXFILE];
void fs_open(volatile uint8_t *fsregs) {
int file;
for(int i = 0; i < FS_MAXFILE; i++) {
if(!fs_file[i].valid) {
int flags = 0;
if(fsregs[FS_FLAGS] & FS_O_RD)
flags |= LFS_O_RDONLY;
if(fsregs[FS_FLAGS] & FS_O_WR)
flags |= LFS_O_WRONLY;
if(fsregs[FS_FLAGS] & FS_O_CREATE)
flags |= LFS_O_CREAT;
if(fsregs[FS_FLAGS] & FS_O_APPEND)
flags |= LFS_O_APPEND;
if(fsregs[FS_FLAGS] & FS_O_EXISTING)
flags |= LFS_O_EXCL;
if(fsregs[FS_FLAGS] & FS_O_TRUNC)
flags |= LFS_O_TRUNC;
if((flags & LFS_O_RDWR) != 0) {
// Ensure pathname is 128 bytes or less.
apple_memory[0xC880] = 0x00;
file = pico_open((char*)(apple_memory + 0xC800), flags);
} else {
fsregs[FS_STATUS] = FS_ERR_INVAL;
fsregs[FS_FILE] = FS_ERR_INVAL;
return;
}
if(file < 0) {
fsregs[FS_STATUS] = file;
fsregs[FS_FILE] = file;
return;
} else {
fs_file[i].handle = file;
fs_file[i].valid = true;
fsregs[FS_STATUS] = FS_ERR_OK;
fsregs[FS_FILE] = i;
return;
}
}
}
fsregs[FS_STATUS] = FS_ERR_NOMEM;
}
void fs_close(volatile uint8_t *fsregs) {
int i = fsregs[FS_FILE];
if((i >= FS_MAXFILE) || (!fs_file[i].valid) || (fs_file[i].handle < 0)) {
fsregs[FS_STATUS] = FS_ERR_INVAL;
return;
}
pico_close(fs_file[i].handle);
fs_file[i].handle = -1;
fs_file[i].valid = false;
}
void fs_read(volatile uint8_t *fsregs) {
int i = fsregs[FS_FILE];
uint16_t size = (((uint16_t)fsregs[FS_OFFMSB]) << 8) | ((uint16_t)fsregs[FS_SIZELSB]);
if((i >= FS_MAXFILE) || (!fs_file[i].valid) || (fs_file[i].handle < 0) || (size > 512)) {
fsregs[FS_STATUS] = FS_ERR_INVAL;
return;
}
if(size == 0) {
fsregs[FS_STATUS] = FS_ERR_OK;
}
int rv = pico_read(fs_file[i].handle, (uint8_t*)(apple_memory+0xC800), size);
if(rv < 0) {
fsregs[FS_STATUS] = rv;
} else {
fsregs[FS_SIZELSB] = rv & 0xFF;
fsregs[FS_SIZEMSB] = (rv >> 8);
fsregs[FS_STATUS] = FS_ERR_OK;
}
}
void fs_write(volatile uint8_t *fsregs) {
int i = fsregs[FS_FILE];
uint16_t size = (((uint16_t)fsregs[FS_OFFMSB]) << 8) | ((uint16_t)fsregs[FS_SIZELSB]);
if((i >= FS_MAXFILE) || (!fs_file[i].valid) || (fs_file[i].handle < 0) || (size > 512)) {
fsregs[FS_STATUS] = FS_ERR_INVAL;
return;
}
if(size == 0) {
fsregs[FS_STATUS] = FS_ERR_OK;
}
int rv = pico_write(fs_file[i].handle, (uint8_t*)(apple_memory+0xC800), size);
if(rv < 0) {
fsregs[FS_STATUS] = rv;
} else {
fsregs[FS_SIZELSB] = rv & 0xFF;
fsregs[FS_SIZEMSB] = (rv >> 8);
fsregs[FS_STATUS] = FS_ERR_OK;
}
}
void fs_seek(volatile uint8_t *fsregs) {
int i = fsregs[FS_FILE];
int16_t off = (int16_t)((((uint16_t)fsregs[FS_OFFMSB]) << 8) | ((uint16_t)fsregs[FS_OFFLSB]));
int whence = fsregs[FS_WHENCE];
if((i >= FS_MAXFILE) || (!fs_file[i].valid) || (fs_file[i].handle < 0)) {
fsregs[FS_STATUS] = FS_ERR_INVAL;
return;
}
int rv = pico_lseek(fs_file[i].handle, off, whence);
if(rv < 0) {
fsregs[FS_STATUS] = rv;
} else {
fsregs[FS_OFFLSB] = rv & 0xFF;
fsregs[FS_OFFMSB] = (rv >> 8);
fsregs[FS_STATUS] = FS_ERR_OK;
}
}
void fs_tell(volatile uint8_t *fsregs) {
int i = fsregs[FS_FILE];
if((i >= FS_MAXFILE) || (!fs_file[i].valid) || (fs_file[i].handle < 0)) {
fsregs[FS_STATUS] = FS_ERR_INVAL;
return;
}
int rv = pico_tell(fs_file[i].handle);
if(rv < 0) {
fsregs[FS_STATUS] = rv;
} else {
fsregs[FS_OFFLSB] = rv & 0xFF;
fsregs[FS_OFFMSB] = (rv >> 8);
fsregs[FS_STATUS] = FS_ERR_OK;
}
}
void prodos_command(volatile uint8_t *fsregs) {
}
void fs_handler(uint8_t slot) {
volatile uint8_t *fsregs = apple_memory + 0xC080 + (slot << 4);
if(fsregs[FS_EXECUTE] != 0x00) {
fsregs[FS_STATUS] = FS_ERR_INVAL;
return;
}
fsregs[FS_BUSY] = 0xff;
switch(fsregs[FS_COMMAND]) {
case FS_OPEN:
fs_open(fsregs);
break;
case FS_CLOSE:
fs_close(fsregs);
break;
case FS_READ:
fs_read(fsregs);
break;
case FS_WRITE:
fs_write(fsregs);
break;
case FS_SEEK:
fs_seek(fsregs);
break;
case FS_TELL:
fs_tell(fsregs);
break;
case PRODOS_COMMAND:
prodos_command(fsregs);
break;
}
fsregs[FS_BUSY] = 0x00;
}
void fsmain() {
int i;
memset((uint8_t*)(apple_memory+0xC000), 0xFF, 0x1000);
for(i = 0; i < FS_MAXFILE; i++) {
fs_file[i].handle = -1;
fs_file[i].valid = false;
}
// Attempt to open boot disk image
fs_file[0].handle = pico_open("boot.dsk", LFS_O_RDONLY);
fs_file[0].valid = (fs_file[0].handle >= 0);
strcpy((char*)(apple_memory+0xC0E0+(cardslot << 8)), "FSREADY.");
while(current_mode == MODE_FS) {
config_handler();
if(cardslot != 0)
fs_handler(cardslot);
sleep_ms(50);
}
// Close any open handles
for(i = 0; i < FS_MAXFILE; i++) {
if(fs_file[i].valid) {
pico_close(fs_file[i].handle);
fs_file[i].handle = -1;
fs_file[i].valid = false;
}
}
}