Simplified system loading
This commit is contained in:
parent
7603ddf9cc
commit
9d889340ea
Binary file not shown.
|
@ -4,7 +4,7 @@
|
||||||
#include "datetime.h"
|
#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
|
Permission to use, copy, modify, and distribute this software for any
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
|
|
@ -8,6 +8,11 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <libiberty/libiberty.h>
|
||||||
|
#define realpath(s, dummy) lrealpath(s)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef PATH_MAX
|
#ifndef PATH_MAX
|
||||||
#define PATH_MAX 4096
|
#define PATH_MAX 4096
|
||||||
#endif
|
#endif
|
||||||
|
@ -16,7 +21,7 @@
|
||||||
#include "file.h"
|
#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
|
Permission to use, copy, modify, and distribute this software for any
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -84,14 +89,17 @@ file_read_dir(UxnFile *c, char *dest, Uint16 len)
|
||||||
continue;
|
continue;
|
||||||
if(strcmp(c->de->d_name, "..") == 0) {
|
if(strcmp(c->de->d_name, "..") == 0) {
|
||||||
/* hide "sandbox/.." */
|
/* 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
|
/* Note there's [currently] no way of chdir()ing from uxn, so $PWD
|
||||||
* is always the sandbox top level. */
|
* is always the sandbox top level. */
|
||||||
getcwd(cwd, sizeof(cwd));
|
getcwd(cwd, sizeof(cwd));
|
||||||
/* We already checked that c->current_filename exists so don't need a wrapper. */
|
/* We already checked that c->current_filename exists so don't need a wrapper. */
|
||||||
realpath(c->current_filename, t);
|
t = realpath(c->current_filename, NULL);
|
||||||
if(strcmp(cwd, t) == 0)
|
if(strcmp(cwd, t) == 0) {
|
||||||
|
free(t);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
free(t);
|
||||||
}
|
}
|
||||||
if(strlen(c->current_filename) + 1 + strlen(c->de->d_name) < sizeof(pathname))
|
if(strlen(c->current_filename) + 1 + strlen(c->de->d_name) < sizeof(pathname))
|
||||||
sprintf(pathname, "%s/%s", c->current_filename, c->de->d_name);
|
sprintf(pathname, "%s/%s", c->current_filename, c->de->d_name);
|
||||||
|
@ -108,7 +116,7 @@ file_read_dir(UxnFile *c, char *dest, Uint16 len)
|
||||||
static char *
|
static char *
|
||||||
retry_realpath(const char *file_name)
|
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) {
|
if(file_name == NULL) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return NULL;
|
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, "/"); /* TODO: use a macro instead of '/' for the path delimiter */
|
||||||
}
|
}
|
||||||
strcat(p, file_name);
|
strcat(p, file_name);
|
||||||
while(realpath(p, r) == NULL) {
|
while((r = realpath(p, NULL)) == NULL) {
|
||||||
if(errno != ENOENT)
|
if(errno != ENOENT)
|
||||||
return NULL;
|
return NULL;
|
||||||
x = strrchr(p, '/'); /* TODO: path delimiter macro */
|
x = strrchr(p, '/'); /* TODO: path delimiter macro */
|
||||||
|
@ -132,7 +140,7 @@ retry_realpath(const char *file_name)
|
||||||
else
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return strdup(r);
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -168,7 +176,7 @@ file_init(UxnFile *c, char *filename, size_t max_len, int override_sandbox)
|
||||||
}
|
}
|
||||||
|
|
||||||
static Uint16
|
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->outside_sandbox) return 0;
|
||||||
if(c->state != FILE_READ && c->state != DIR_READ) {
|
if(c->state != FILE_READ && c->state != DIR_READ) {
|
||||||
|
@ -278,15 +286,3 @@ file_dei(Uint8 id, Uint8 *d, Uint8 port)
|
||||||
}
|
}
|
||||||
return d[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;
|
|
||||||
}
|
|
||||||
|
|
|
@ -14,4 +14,3 @@ WITH REGARD TO THIS SOFTWARE.
|
||||||
|
|
||||||
void file_deo(Uint8 id, Uint8 *ram, Uint8 *d, Uint8 port);
|
void file_deo(Uint8 id, Uint8 *ram, Uint8 *d, Uint8 port);
|
||||||
Uint8 file_dei(Uint8 id, Uint8 *d, Uint8 port);
|
Uint8 file_dei(Uint8 id, Uint8 *d, Uint8 port);
|
||||||
int load_rom(Uxn *u, char *filename);
|
|
||||||
|
|
|
@ -39,6 +39,55 @@ system_inspect(Uxn *u)
|
||||||
system_print(u->rst, "rst");
|
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
|
int
|
||||||
uxn_halt(Uxn *u, Uint8 instr, Uint8 err, Uint16 addr)
|
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;
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -9,11 +9,8 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
WITH REGARD TO THIS SOFTWARE.
|
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);
|
void system_deo(Uxn *u, Uint8 *d, Uint8 port);
|
||||||
|
void system_inspect(Uxn *u);
|
||||||
typedef struct {
|
|
||||||
Uint8 length, *pages;
|
|
||||||
} Mmu;
|
|
||||||
|
|
||||||
Uint8 *mmu_init(Mmu *m, Uint16 pages);
|
|
||||||
|
|
|
@ -108,7 +108,7 @@ emu_draw(void)
|
||||||
static int
|
static int
|
||||||
emu_start(Uxn *u, char *rom)
|
emu_start(Uxn *u, char *rom)
|
||||||
{
|
{
|
||||||
if(!load_rom(u, rom))
|
if(!system_load(u, rom))
|
||||||
return 0;
|
return 0;
|
||||||
if(!uxn_screen.width || !uxn_screen.height)
|
if(!uxn_screen.width || !uxn_screen.height)
|
||||||
screen_resize(&uxn_screen, WIDTH, HEIGHT);
|
screen_resize(&uxn_screen, WIDTH, HEIGHT);
|
||||||
|
@ -225,7 +225,6 @@ int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
Uxn u;
|
Uxn u;
|
||||||
Mmu m;
|
|
||||||
int i;
|
int i;
|
||||||
char expirations[8];
|
char expirations[8];
|
||||||
struct pollfd fds[2];
|
struct pollfd fds[2];
|
||||||
|
@ -233,7 +232,7 @@ main(int argc, char **argv)
|
||||||
if(argc < 2)
|
if(argc < 2)
|
||||||
return emu_error("Usage", "uxn11 game.rom args");
|
return emu_error("Usage", "uxn11 game.rom args");
|
||||||
rom_path = argv[1];
|
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");
|
return emu_error("Boot", "Failed");
|
||||||
/* start sequence */
|
/* start sequence */
|
||||||
if(!emu_start(&u, rom_path))
|
if(!emu_start(&u, rom_path))
|
||||||
|
|
|
@ -37,8 +37,8 @@ console_input(Uxn *u, char c)
|
||||||
static void
|
static void
|
||||||
console_deo(Uint8 *d, Uint8 port)
|
console_deo(Uint8 *d, Uint8 port)
|
||||||
{
|
{
|
||||||
FILE *fd = port == 0x8 ? stdout : port == 0x9 ? stderr
|
FILE *fd = port == 0x8 ? stdout : port == 0x9 ? stderr :
|
||||||
: 0;
|
0;
|
||||||
if(fd) {
|
if(fd) {
|
||||||
fputc(d[port], fd);
|
fputc(d[port], fd);
|
||||||
fflush(fd);
|
fflush(fd);
|
||||||
|
@ -78,12 +78,11 @@ main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
Uxn u;
|
Uxn u;
|
||||||
int i;
|
int i;
|
||||||
Mmu mmu;
|
|
||||||
if(argc < 2)
|
if(argc < 2)
|
||||||
return emu_error("Usage", "uxncli game.rom args");
|
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");
|
return emu_error("Boot", "Failed");
|
||||||
if(!load_rom(&u, argv[1]))
|
if(!system_load(&u, argv[1]))
|
||||||
return emu_error("Load", "Failed");
|
return emu_error("Load", "Failed");
|
||||||
if(!uxn_eval(&u, PAGE_PROGRAM))
|
if(!uxn_eval(&u, PAGE_PROGRAM))
|
||||||
return emu_error("Init", "Failed");
|
return emu_error("Init", "Failed");
|
||||||
|
|
Loading…
Reference in New Issue