Working on file operations.

This commit is contained in:
Scott Duensing 2024-01-22 19:37:11 -06:00
parent 496ef13a94
commit 03046dcf11
8 changed files with 332 additions and 39 deletions

View file

@ -24,33 +24,57 @@
#include "f256.h"
int main(void) {
byte x;
byte y;
void dirtest(void) {
DIR *dir;
struct dirent *dirent;
textPrint("Starting directory test.\n");
if ((dir = opendir("0:"))) {
textPrint("Directory opened.\n");
for (;;) {
if ((dirent = readdir(dir))) {
textPrint("dirent type=");
textPrintInt(dirent->d_type);
textPrint("\n");
if (_DE_ISREG(dirent->d_type)) {
textPrint(dirent->d_name);
textPrint(" (");
textPrintInt(dirent->d_blocks);
textPrint(")\n");
continue;
}
if (_DE_ISDIR(dirent->d_type)) {
textPrint(dirent->d_name);
textPrint("/\n");
continue;
}
if (_DE_ISLBL(dirent->d_type)) {
textPrint("Directory of ");
textPrint(dirent->d_name);
textPrint(":\n");
continue;
}
}
break;
}
textPrint("Closing.\n");
closedir(dir);
} else {
textPrint("Failed to open directory.\n");
}
}
int main(void) {
f256Init();
textPrint("F256 LIVES!\n");
textSetColor(LIGHT_GREEN, BLACK);
textPrint("Green!\n\n");
textSetColor(ORANGE, BLACK);
textPrint("byte is "); textPrintInt(sizeof(byte));
textPrint("\nint is "); textPrintInt(sizeof(int));
textPrint("\nint16_t is "); textPrintInt(sizeof(int16_t));
textPrint("\nint32_t is "); textPrintInt(sizeof(int32_t));
textPrint("\n");
textPrint("\nEvent Size: "); textPrintInt(sizeof(kernelEvent(key.PRESSED)));
textPrint("\n\n");
textGetXY(&x, &y);
while(1) {
//kernelCall(NextEvent);
textGotoXY(x, y);
textPrint("Pending: ");
textPrintInt(kernelGetPending());
textPrint(" ");
}
dirtest();
return 0;
}

View file

@ -32,6 +32,7 @@
#include "tile.c"
#include "graphics.c"
#include "sprite.c"
#include "file.c"
void f256Init(void) {
@ -58,6 +59,7 @@ void f256Init(void) {
bitmapReset();
tileReset();
spriteReset();
fileReset();
randomSeed(0); //***TODO*** Use clock or something.
}

View file

@ -163,6 +163,7 @@ void FAR_POKE(uint32_t address, byte value);
#include "tile.h"
#include "graphics.h"
#include "sprite.h"
#include "file.h"
#ifdef __cplusplus

185
f256lib/file.c Normal file
View file

@ -0,0 +1,185 @@
/*
* Copyright (c) 2024 Scott Duensing, scott@kangaroopunch.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <string.h>
#include "file.h"
#define MAX_DRIVES 8
static char _dirStream[MAX_DRIVES];
static char *pathWithoutDrive(char *path, char *drive);
int16_t fileCloseDir(fileDirT *dir) {
if (!dir) return -1;
for (;;) {
if (*dir->stream) {
kernelArgs->directory.close.stream = *dir->stream;
kernelCall(Directory.Close);
if (!kernelError) {
*dir->stream = 0;
}
}
kernelNextEvent();
if (kernelEventData.type == kernelEvent(directory.CLOSED)) {
free(dir);
dir = NULL;
return 0;
}
}
}
fileDirT *fileOpenDir(char *name) {
char drive;
char stream;
fileDirT *dir;
name = pathWithoutDrive(name, &drive);
if (_dirStream[drive]) return NULL; // Only one at a time.
kernelArgs->directory.open.drive = drive;
kernelArgs->common.buf = name;
kernelArgs->common.buflen = strlen(name);
stream = kernelCall(Directory.Open);
textPrint("kernelError = "); textPrintInt(kernelError); textPrint("\n");
textPrint("kernelReturn = "); textPrintInt(kernelReturn); textPrint("\n");
textPrint("stream = "); textPrintInt(stream); textPrint("\n");
if (kernelError) return NULL;
for (;;) {
kernelNextEvent();
if (kernelEventData.type != 0) {
textPrintInt(kernelEventData.type);
textPrint(" ");
}
if (kernelEventData.type == kernelEvent(directory.OPENED)) break;
if (kernelEventData.type == kernelEvent(directory.ERROR)) return NULL;
}
_dirStream[drive] = stream;
dir = (fileDirT *)malloc(sizeof(fileDirT));
dir->stream = &_dirStream[drive];
return dir;
}
fileDirEntT *fileReadDir(fileDirT *dir) {
static fileDirEntT dirent;
unsigned len;
if (!dir) return NULL;
textPrint("Calling Directory.Read.\n");
kernelArgs->directory.read.stream = *dir->stream;
kernelCall(Directory.Read);
if (kernelError) return NULL;
textPrint("Directory.Read called.\n");
for (;;) {
kernelNextEvent();
switch (kernelEventData.type) {
textPrintInt(kernelEventData.type);
textPrint(" ");
case kernelEvent(directory.VOLUME):
dirent.d_blocks = 0;
dirent.d_type = 2;
break;
case kernelEvent(directory.FILE):
kernelArgs->common.buf = &dirent.d_blocks;
kernelArgs->common.buflen = sizeof(dirent.d_blocks);
kernelCall(ReadExt);
dirent.d_type = (dirent.d_blocks == 0);
break;
case kernelEvent(directory.FREE):
// dirent doesn't care about these types of records.
kernelArgs->directory.read.stream = *dir->stream;
kernelCall(Directory.Read);
if (!kernelError) continue;
// Fall through.
case kernelEvent(directory.EOF):
case kernelEvent(directory.ERROR):
return NULL;
default:
continue;
}
// Copy the name.
len = kernelEventData.directory.file.len;
if (len >= sizeof(dirent.d_name)) {
len = sizeof(dirent.d_name) - 1;
}
if (len > 0) {
kernelArgs->common.buf = &dirent.d_name;
kernelArgs->common.buflen = len;
kernelCall(ReadData);
}
dirent.d_name[len] = '\0';
return &dirent;
}
}
void fileReset(void) {
byte x;
for (x=0; x<MAX_DRIVES; x++) _dirStream[x] = 0;
}
static char *pathWithoutDrive(char *path, char *drive) {
*drive = 0;
if (strlen(path) < 2) return path;
if (path[1] != ':') return path;
if ((*path >= '0') && (*path <= '7')) *drive = *path - '0';
return (path + 2);
}

75
f256lib/file.h Normal file
View file

@ -0,0 +1,75 @@
/*
* Copyright (c) 2024 Scott Duensing, scott@kangaroopunch.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef FILE_H
#define FILE_H
#ifdef __cplusplus
extern "C"
{
#endif
#include "f256.h"
typedef struct fileDirS {
char *stream;
} fileDirT;
typedef struct fileDirEntS {
unsigned char d_blocks;
unsigned char d_type;
char d_name[256];
} fileDirEntT;
int16_t fileCloseDir(fileDirT *dir);
fileDirT *fileOpenDir(char *name);
fileDirEntT *fileReadDir(fileDirT *dir);
void fileReset(void);
#define _DE_ISREG(t) (t == 0)
#define _DE_ISDIR(t) (t == 1)
#define _DE_ISLBL(t) (t == 2)
#define _DE_ISLNK(t) (0)
// Aliases to the standard names if they don't exist.
#ifndef DIR
#define DIR fileDirT
#define dirent fileDirEntS
#define opendir fileOpenDir
#define closedir fileCloseDir
#define readdir fileReadDir
#endif
#ifdef __cplusplus
}
#endif
#endif // FILE_H

View file

@ -26,6 +26,7 @@
kernelEventT kernelEventData; // Allocate some RAM to hold event data.
kernelArgsT *kernelArgs; // Create an alias for the kernel args.
char kernelReturn;
char kernelError;
@ -43,7 +44,7 @@ void kernelReset(void) {
/*
case EVENT(JOYSTICK):
case EVENT(GAME):
// Joystick
break;

View file

@ -34,24 +34,27 @@ extern "C"
#include "f256.h"
#define kernelNextEvent() ({ kernelEventData.type = 0; kernelCall(NextEvent); })
#define kernelEvent(member) (size_t)(&((struct events *)0)->member)
#define kernelVector(member) (size_t)(&((struct call *)0xff00)->member)
#define kernelCall(fn) \
asm("jsr %[addy] \n" \
({ asm("jsr %[addy] \n" \
"stz %[err] \n" \
"ror %[err]" \
: [err] "+m"(kernelError) \
"ror %[err] \n" \
"sta %[ret]" \
: [err] "+m"(kernelError), [ret] "+m"(kernelReturn) \
: [addy] "i"(kernelVector(fn)) \
: "a", "x", "y", "c", "v");
: "a", "x", "y", "c", "v"); kernelReturn; })
typedef struct event_t kernelEventT;
typedef struct call_args kernelArgsT;
extern char kernelError;
extern kernelArgsT *kernelArgs;
extern kernelEventT kernelEventData;
extern kernelArgsT *kernelArgs;
extern char kernelReturn;
extern char kernelError;
byte kernelGetPending(void);

View file

@ -112,10 +112,11 @@ void textGotoXY(byte x, byte y) {
// Print a string to the screen.
void textPrint(char *message) {
int x = 0;
int i = 0;
int j = 0;
byte mmu = PEEK(MMU_IO_CTRL); // Get current MMU state.
int16_t x = 0;
int16_t i = 0;
int16_t j = 0;
int16_t m = 0;
byte mmu = PEEK(MMU_IO_CTRL); // Get current MMU state.
volatile byte *vram = (byte *)mathUnsignedAddition(TEXT_MATRIX, mathUnsignedMultiply(_MAX_COL, _row));
volatile byte *save = 0;
@ -136,9 +137,12 @@ void textPrint(char *message) {
if (_row == _MAX_ROW) {
// Scroll contents up one line.
vram = (byte *)TEXT_MATRIX;
m = _MAX_COL * (_MAX_ROW - 1); // mathUnsignedMultiply(_MAX_COL, (_MAX_ROW - 1)); // It REALLY doesn't like using the copro for this.
POKE(MMU_IO_CTRL, MMU_IO_COLOR); // Swap I/O page 3 into bank 6.
for (j=0; j<2; j++) {
for (i = 0; i < mathUnsignedMultiply(_MAX_COL, (_MAX_ROW - 1)); i++) vram[i] = vram[i+_MAX_COL];
for (j=0; j<2; j++) { // Twice - first is the text, second is color.
for (i = 0; i < m; i++) {
vram[i] = vram[i + _MAX_COL];
}
POKE(MMU_IO_CTRL, MMU_IO_TEXT); // Swap I/O page 2 into bank 6.
}
// Clear bottom line.
@ -238,8 +242,6 @@ void textSetCursor(byte c) {
void textSetDouble(bool x, bool y) {
//***TODO*** Adding this function seems to have screwed up scrolling.
POKE(VKY_MSTR_CTRL_1, (PEEK(VKY_MSTR_CTRL_1) & 0xf9) | (x << 1) | (y << 2));
_MAX_COL = x ? 40 : 80;