Simplified system loading

This commit is contained in:
Devine Lu Linvega 2023-02-02 08:45:03 -08:00
parent 7603ddf9cc
commit 9d889340ea
8 changed files with 76 additions and 78 deletions

BIN
oquonie.rom Normal file

Binary file not shown.

View File

@ -4,7 +4,7 @@
#include "datetime.h"
/*
Copyright (c) 2021 Devine Lu Linvega, Andrew Alderwick
Copyright (c) 2021-2023 Devine Lu Linvega, 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

View File

@ -8,6 +8,11 @@
#include <sys/stat.h>
#include <unistd.h>
#ifdef _WIN32
#include <libiberty/libiberty.h>
#define realpath(s, dummy) lrealpath(s)
#endif
#ifndef PATH_MAX
#define PATH_MAX 4096
#endif
@ -16,7 +21,7 @@
#include "file.h"
/*
Copyright (c) 2021 Devine Lu Linvega, Andrew Alderwick
Copyright (c) 2021-2023 Devine Lu Linvega, 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
@ -84,15 +89,18 @@ file_read_dir(UxnFile *c, char *dest, Uint16 len)
continue;
if(strcmp(c->de->d_name, "..") == 0) {
/* hide "sandbox/.." */
char cwd[PATH_MAX] = {'\0'}, t[PATH_MAX] = {'\0'};
char cwd[PATH_MAX] = {'\0'}, *t;
/* Note there's [currently] no way of chdir()ing from uxn, so $PWD
* is always the sandbox top level. */
getcwd(cwd, sizeof(cwd));
/* We already checked that c->current_filename exists so don't need a wrapper. */
realpath(c->current_filename, t);
if(strcmp(cwd, t) == 0)
t = realpath(c->current_filename, NULL);
if(strcmp(cwd, t) == 0) {
free(t);
continue;
}
free(t);
}
if(strlen(c->current_filename) + 1 + strlen(c->de->d_name) < sizeof(pathname))
sprintf(pathname, "%s/%s", c->current_filename, c->de->d_name);
else
@ -108,7 +116,7 @@ file_read_dir(UxnFile *c, char *dest, Uint16 len)
static char *
retry_realpath(const char *file_name)
{
char r[PATH_MAX] = {'\0'}, p[PATH_MAX] = {'\0'}, *x;
char *r, p[PATH_MAX] = {'\0'}, *x;
if(file_name == NULL) {
errno = EINVAL;
return NULL;
@ -123,7 +131,7 @@ retry_realpath(const char *file_name)
strcat(p, "/"); /* TODO: use a macro instead of '/' for the path delimiter */
}
strcat(p, file_name);
while(realpath(p, r) == NULL) {
while((r = realpath(p, NULL)) == NULL) {
if(errno != ENOENT)
return NULL;
x = strrchr(p, '/'); /* TODO: path delimiter macro */
@ -132,7 +140,7 @@ retry_realpath(const char *file_name)
else
return NULL;
}
return strdup(r);
return r;
}
static void
@ -168,7 +176,7 @@ file_init(UxnFile *c, char *filename, size_t max_len, int override_sandbox)
}
static Uint16
file_read(UxnFile *c, void *dest, Uint16 len)
file_read(UxnFile *c, void *dest, int len)
{
if(c->outside_sandbox) return 0;
if(c->state != FILE_READ && c->state != DIR_READ) {
@ -278,15 +286,3 @@ file_dei(Uint8 id, Uint8 *d, Uint8 port)
}
return d[port];
}
/* Boot */
int
load_rom(Uxn *u, char *filename)
{
int ret;
file_init(uxn_file, filename, strlen(filename) + 1, 1);
ret = file_read(uxn_file, &u->ram[PAGE_PROGRAM], 0x10000 - PAGE_PROGRAM);
reset(uxn_file);
return ret;
}

View File

@ -14,4 +14,3 @@ WITH REGARD TO THIS SOFTWARE.
void file_deo(Uint8 id, Uint8 *ram, Uint8 *d, Uint8 port);
Uint8 file_dei(Uint8 id, Uint8 *d, Uint8 port);
int load_rom(Uxn *u, char *filename);

View File

@ -39,6 +39,55 @@ system_inspect(Uxn *u)
system_print(u->rst, "rst");
}
/* RAM */
void
system_cmd(Uint8 *ram, Uint16 addr)
{
Uint16 a = addr, i = 0;
Uint8 o = ram[a++];
if(o == 1) {
Uint16 length = (ram[a++] << 8) + ram[a++];
Uint16 src_page = ((ram[a++] << 8) + ram[a++]) % 16, src_addr = (ram[a++] << 8) + ram[a++];
Uint16 dst_page = ((ram[a++] << 8) + ram[a++]) % 16, dst_addr = (ram[a++] << 8) + ram[a];
for(i = 0; i < length; i++)
ram[dst_page * 0x10000 + dst_addr + i] = ram[src_page * 0x10000 + src_addr + i];
}
}
int
system_load(Uxn *u, char *filename)
{
int l, i = 0;
FILE *f = fopen(filename, "rb");
if(!f)
return 0;
l = fread(&u->ram[PAGE_PROGRAM], 1, 0x10000 - PAGE_PROGRAM, f);
while(l && ++i < RAM_PAGES)
l = fread(u->ram + 0x10000 * i, 1, 0x10000, f);
fclose(f);
return 1;
}
/* IO */
void
system_deo(Uxn *u, Uint8 *d, Uint8 port)
{
Uint16 a;
switch(port) {
case 0x3:
PEKDEV(a, 0x2);
system_cmd(u->ram, a);
break;
case 0xe:
if(u->wst->ptr || u->rst->ptr) system_inspect(u);
break;
}
}
/* Error */
int
uxn_halt(Uxn *u, Uint8 instr, Uint8 err, Uint16 addr)
{
@ -57,44 +106,3 @@ uxn_halt(Uxn *u, Uint8 instr, Uint8 err, Uint16 addr)
}
return 0;
}
/* MMU */
Uint8 *
mmu_init(Mmu *m, Uint16 pages)
{
m->length = pages;
m->pages = (Uint8 *)calloc(0x10000 * pages, sizeof(Uint8));
return m->pages;
}
void
mmu_eval(Uint8 *ram, Uint16 addr)
{
Uint16 a = addr, i = 0;
Uint8 o = ram[a++];
if(o == 1) {
Uint16 length = (ram[a++] << 8) + ram[a++];
Uint16 src_page = ((ram[a++] << 8) + ram[a++]) % 16, src_addr = (ram[a++] << 8) + ram[a++];
Uint16 dst_page = ((ram[a++] << 8) + ram[a++]) % 16, dst_addr = (ram[a++] << 8) + ram[a];
for(i = 0; i < length; i++)
ram[dst_page * 0x10000 + dst_addr + i] = ram[src_page * 0x10000 + src_addr + i];
}
}
/* IO */
void
system_deo(Uxn *u, Uint8 *d, Uint8 port)
{
Uint16 a;
switch(port) {
case 0x3:
PEKDEV(a, 0x2);
mmu_eval(u->ram, a);
break;
case 0xe:
if(u->wst->ptr || u->rst->ptr) system_inspect(u);
break;
}
}

View File

@ -9,11 +9,8 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE.
*/
void system_inspect(Uxn *u);
#define RAM_PAGES 0x10
int system_load(Uxn *u, char *filename);
void system_deo(Uxn *u, Uint8 *d, Uint8 port);
typedef struct {
Uint8 length, *pages;
} Mmu;
Uint8 *mmu_init(Mmu *m, Uint16 pages);
void system_inspect(Uxn *u);

View File

@ -108,7 +108,7 @@ emu_draw(void)
static int
emu_start(Uxn *u, char *rom)
{
if(!load_rom(u, rom))
if(!system_load(u, rom))
return 0;
if(!uxn_screen.width || !uxn_screen.height)
screen_resize(&uxn_screen, WIDTH, HEIGHT);
@ -225,7 +225,6 @@ int
main(int argc, char **argv)
{
Uxn u;
Mmu m;
int i;
char expirations[8];
struct pollfd fds[2];
@ -233,7 +232,7 @@ main(int argc, char **argv)
if(argc < 2)
return emu_error("Usage", "uxn11 game.rom args");
rom_path = argv[1];
if(!uxn_boot(&u, mmu_init(&m, 16), emu_dei, emu_deo))
if(!uxn_boot(&u, (Uint8 *)calloc(0x10000 * RAM_PAGES, sizeof(Uint8)), emu_dei, emu_deo))
return emu_error("Boot", "Failed");
/* start sequence */
if(!emu_start(&u, rom_path))

View File

@ -37,8 +37,8 @@ console_input(Uxn *u, char c)
static void
console_deo(Uint8 *d, Uint8 port)
{
FILE *fd = port == 0x8 ? stdout : port == 0x9 ? stderr
: 0;
FILE *fd = port == 0x8 ? stdout : port == 0x9 ? stderr :
0;
if(fd) {
fputc(d[port], fd);
fflush(fd);
@ -78,12 +78,11 @@ main(int argc, char **argv)
{
Uxn u;
int i;
Mmu mmu;
if(argc < 2)
return emu_error("Usage", "uxncli game.rom args");
if(!uxn_boot(&u, mmu_init(&mmu, 16), emu_dei, emu_deo))
if(!uxn_boot(&u, (Uint8 *)calloc(0x10000 * RAM_PAGES, sizeof(Uint8)), emu_dei, emu_deo))
return emu_error("Boot", "Failed");
if(!load_rom(&u, argv[1]))
if(!system_load(&u, argv[1]))
return emu_error("Load", "Failed");
if(!uxn_eval(&u, PAGE_PROGRAM))
return emu_error("Init", "Failed");