Working on file operations.
This commit is contained in:
parent
496ef13a94
commit
03046dcf11
8 changed files with 332 additions and 39 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
}
|
||||
|
|
|
@ -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
185
f256lib/file.c
Normal 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
75
f256lib/file.h
Normal 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
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue