2022-03-27 13:01:06 -04:00
|
|
|
#include <stdio.h>
|
2023-01-28 19:47:41 -05:00
|
|
|
#include <stdlib.h>
|
2022-03-27 13:01:06 -04:00
|
|
|
|
2022-03-26 21:32:46 -04:00
|
|
|
#include "../uxn.h"
|
|
|
|
#include "system.h"
|
|
|
|
|
|
|
|
/*
|
2023-01-28 19:47:41 -05:00
|
|
|
Copyright (c) 2022-2023 Devine Lu Linvega, Andrew Alderwick
|
2022-03-26 21:32:46 -04:00
|
|
|
|
|
|
|
Permission to use, copy, modify, and distribute this software for any
|
|
|
|
purpose with or without fee is hereby granted, provided that the above
|
|
|
|
copyright notice and this permission notice appear in all copies.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
WITH REGARD TO THIS SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static const char *errors[] = {
|
2022-04-10 12:42:56 -04:00
|
|
|
"underflow",
|
|
|
|
"overflow",
|
2022-06-13 14:08:33 -04:00
|
|
|
"division by zero"};
|
2022-03-26 21:32:46 -04:00
|
|
|
|
|
|
|
static void
|
|
|
|
system_print(Stack *s, char *name)
|
|
|
|
{
|
|
|
|
Uint8 i;
|
|
|
|
fprintf(stderr, "<%s>", name);
|
|
|
|
for(i = 0; i < s->ptr; i++)
|
|
|
|
fprintf(stderr, " %02x", s->dat[i]);
|
|
|
|
if(!i)
|
|
|
|
fprintf(stderr, " empty");
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
}
|
|
|
|
|
2023-02-02 13:18:53 -05:00
|
|
|
static void
|
|
|
|
system_cmd(Uint8 *ram, Uint16 addr)
|
2022-03-26 21:32:46 -04:00
|
|
|
{
|
2023-04-17 14:36:17 -04:00
|
|
|
if(ram[addr] == 0x1) {
|
|
|
|
Uint16 i, length = PEEK2(ram + addr + 1);
|
|
|
|
Uint16 a_page = PEEK2(ram + addr + 1 + 2), a_addr = PEEK2(ram + addr + 1 + 4);
|
|
|
|
Uint16 b_page = PEEK2(ram + addr + 1 + 6), b_addr = PEEK2(ram + addr + 1 + 8);
|
2023-02-02 13:39:57 -05:00
|
|
|
int src = (a_page % RAM_PAGES) * 0x10000, dst = (b_page % RAM_PAGES) * 0x10000;
|
|
|
|
for(i = 0; i < length; i++)
|
|
|
|
ram[dst + (Uint16)(b_addr + i)] = ram[src + (Uint16)(a_addr + i)];
|
2023-02-02 13:18:53 -05:00
|
|
|
}
|
2022-03-26 21:32:46 -04:00
|
|
|
}
|
|
|
|
|
2023-04-10 17:32:54 -04:00
|
|
|
int
|
|
|
|
system_error(char *msg, const char *err)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "%s: %s\n", msg, err);
|
2023-04-17 14:36:17 -04:00
|
|
|
fflush(stderr);
|
2023-04-10 17:32:54 -04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2023-02-02 11:45:03 -05:00
|
|
|
int
|
|
|
|
system_load(Uxn *u, char *filename)
|
|
|
|
{
|
|
|
|
int l, i = 0;
|
|
|
|
FILE *f = fopen(filename, "rb");
|
|
|
|
if(!f)
|
|
|
|
return 0;
|
2023-02-02 12:34:14 -05:00
|
|
|
l = fread(&u->ram[PAGE_PROGRAM], 0x10000 - PAGE_PROGRAM, 1, f);
|
2023-02-02 11:45:03 -05:00
|
|
|
while(l && ++i < RAM_PAGES)
|
2023-02-02 12:34:14 -05:00
|
|
|
l = fread(u->ram + 0x10000 * i, 0x10000, 1, f);
|
2023-02-02 11:45:03 -05:00
|
|
|
fclose(f);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2023-04-17 14:36:17 -04:00
|
|
|
void
|
|
|
|
system_inspect(Uxn *u)
|
|
|
|
{
|
|
|
|
system_print(&u->wst, "wst");
|
|
|
|
system_print(&u->rst, "rst");
|
|
|
|
}
|
|
|
|
|
2023-08-08 19:26:13 -04:00
|
|
|
void
|
|
|
|
system_connect(Uint8 device, Uint8 ver, Uint16 dei, Uint16 deo)
|
2023-05-01 01:03:35 -04:00
|
|
|
{
|
2023-08-08 19:26:13 -04:00
|
|
|
dev_vers[device] = ver;
|
|
|
|
dei_mask[device] = dei;
|
|
|
|
deo_mask[device] = deo;
|
2023-05-01 01:03:35 -04:00
|
|
|
}
|
|
|
|
|
2023-08-08 19:26:13 -04:00
|
|
|
int
|
|
|
|
system_version(char *name, char *date)
|
2023-05-03 13:26:28 -04:00
|
|
|
{
|
2023-08-08 19:26:13 -04:00
|
|
|
int i;
|
|
|
|
printf("%s, %s.\n", name, date);
|
|
|
|
printf("Device Version Dei Deo\n");
|
|
|
|
for(i = 0; i < 0x10; i++)
|
|
|
|
if(dev_vers[i])
|
|
|
|
printf("%6x %7d %04x %04x\n", i, dev_vers[i], dei_mask[i], deo_mask[i]);
|
|
|
|
return 0;
|
2023-05-01 01:03:35 -04:00
|
|
|
}
|
|
|
|
|
2022-03-26 21:32:46 -04:00
|
|
|
/* IO */
|
|
|
|
|
|
|
|
void
|
2022-04-05 12:35:49 -04:00
|
|
|
system_deo(Uxn *u, Uint8 *d, Uint8 port)
|
2022-03-26 21:32:46 -04:00
|
|
|
{
|
|
|
|
switch(port) {
|
2023-01-28 19:47:41 -05:00
|
|
|
case 0x3:
|
2023-04-10 13:53:30 -04:00
|
|
|
system_cmd(u->ram, PEEK2(d + 2));
|
2023-01-28 19:47:41 -05:00
|
|
|
break;
|
2023-05-01 01:03:35 -04:00
|
|
|
case 0x5:
|
2023-08-08 19:26:13 -04:00
|
|
|
if(PEEK2(d + 4)) {
|
|
|
|
Uxn friend;
|
|
|
|
uxn_boot(&friend, u->ram);
|
|
|
|
uxn_eval(&friend, PEEK2(d + 4));
|
|
|
|
}
|
2023-05-01 01:03:35 -04:00
|
|
|
break;
|
2022-06-14 13:52:18 -04:00
|
|
|
case 0xe:
|
2023-04-10 13:53:30 -04:00
|
|
|
system_inspect(u);
|
2022-06-14 13:52:18 -04:00
|
|
|
break;
|
2022-03-26 21:32:46 -04:00
|
|
|
}
|
|
|
|
}
|
2023-04-17 14:36:17 -04:00
|
|
|
|
|
|
|
/* Errors */
|
|
|
|
|
|
|
|
int
|
2023-08-01 23:32:42 -04:00
|
|
|
emu_halt(Uxn *u, Uint8 instr, Uint8 err, Uint16 addr)
|
2023-04-17 14:36:17 -04:00
|
|
|
{
|
|
|
|
Uint8 *d = &u->dev[0];
|
|
|
|
Uint16 handler = PEEK2(d);
|
|
|
|
if(handler) {
|
|
|
|
u->wst.ptr = 4;
|
|
|
|
u->wst.dat[0] = addr >> 0x8;
|
|
|
|
u->wst.dat[1] = addr & 0xff;
|
|
|
|
u->wst.dat[2] = instr;
|
|
|
|
u->wst.dat[3] = err;
|
|
|
|
return uxn_eval(u, handler);
|
|
|
|
} else {
|
|
|
|
system_inspect(u);
|
|
|
|
fprintf(stderr, "%s %s, by %02x at 0x%04x.\n", (instr & 0x40) ? "Return-stack" : "Working-stack", errors[err - 1], instr, addr);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|