2021-03-22 22:04:31 -04:00
|
|
|
#include <stdio.h>
|
2021-05-26 13:02:13 -04:00
|
|
|
#include <time.h>
|
2021-06-27 16:45:50 -04:00
|
|
|
#include <unistd.h>
|
|
|
|
#include <string.h>
|
2021-05-12 21:28:45 -04:00
|
|
|
#include "uxn.h"
|
2021-03-22 22:04:31 -04:00
|
|
|
|
|
|
|
/*
|
|
|
|
Copyright (c) 2021 Devine Lu Linvega
|
|
|
|
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma mark - Core
|
|
|
|
|
2021-06-27 16:45:50 -04:00
|
|
|
static Device *devconsole;
|
|
|
|
|
2021-03-22 22:04:31 -04:00
|
|
|
int
|
|
|
|
error(char *msg, const char *err)
|
|
|
|
{
|
|
|
|
printf("Error %s: %s\n", msg, err);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-03-22 22:24:05 -04:00
|
|
|
void
|
|
|
|
printstack(Stack *s)
|
|
|
|
{
|
|
|
|
Uint8 x, y;
|
2021-05-26 13:02:13 -04:00
|
|
|
printf("\n\n");
|
2021-03-22 22:24:05 -04:00
|
|
|
for(y = 0; y < 0x08; ++y) {
|
|
|
|
for(x = 0; x < 0x08; ++x) {
|
|
|
|
Uint8 p = y * 0x08 + x;
|
|
|
|
printf(p == s->ptr ? "[%02x]" : " %02x ", s->dat[p]);
|
|
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-22 22:04:31 -04:00
|
|
|
#pragma mark - Devices
|
|
|
|
|
2021-04-24 04:10:24 -04:00
|
|
|
void
|
2021-04-24 13:15:47 -04:00
|
|
|
console_talk(Device *d, Uint8 b0, Uint8 w)
|
2021-03-22 22:04:31 -04:00
|
|
|
{
|
2021-06-27 16:45:50 -04:00
|
|
|
char buffer[7], *p = buffer;
|
|
|
|
int len = 0;
|
2021-04-24 13:15:47 -04:00
|
|
|
if(!w) return;
|
2021-03-22 22:04:31 -04:00
|
|
|
switch(b0) {
|
2021-06-27 16:45:50 -04:00
|
|
|
case 0x8: len = 1, p = (char *)&d->dat[0x8]; break;
|
|
|
|
case 0x9: len = sprintf(p, "0x%02x", d->dat[0x9]); break;
|
|
|
|
case 0xb: len = sprintf(p, "0x%04x", mempeek16(d->dat, 0xa)); break;
|
|
|
|
case 0xd: len = strlen(p = (char *)&d->mem[mempeek16(d->dat, 0xc)]); break;
|
2021-03-22 22:04:31 -04:00
|
|
|
}
|
2021-06-27 16:45:50 -04:00
|
|
|
if(len) write(1, p, len);
|
2021-03-22 22:04:31 -04:00
|
|
|
}
|
|
|
|
|
2021-04-24 04:10:24 -04:00
|
|
|
void
|
2021-04-24 13:15:47 -04:00
|
|
|
file_talk(Device *d, Uint8 b0, Uint8 w)
|
2021-03-22 22:04:31 -04:00
|
|
|
{
|
2021-04-20 17:30:26 -04:00
|
|
|
Uint8 read = b0 == 0xd;
|
2021-04-24 13:15:47 -04:00
|
|
|
if(w && (read || b0 == 0xf)) {
|
2021-04-21 08:37:41 -04:00
|
|
|
char *name = (char *)&d->mem[mempeek16(d->dat, 0x8)];
|
|
|
|
Uint16 result = 0, length = mempeek16(d->dat, 0xa);
|
|
|
|
Uint16 offset = mempeek16(d->dat, 0x4);
|
2021-04-24 04:10:24 -04:00
|
|
|
Uint16 addr = mempeek16(d->dat, b0 - 1);
|
2021-04-20 17:30:26 -04:00
|
|
|
FILE *f = fopen(name, read ? "r" : (offset ? "a" : "w"));
|
|
|
|
if(f) {
|
2021-05-26 13:02:13 -04:00
|
|
|
printf("%s %04x %s %s: ", read ? "Loading" : "Saving", addr, read ? "from" : "to", name);
|
|
|
|
if(fseek(f, offset, SEEK_SET) != -1)
|
|
|
|
result = read ? fread(&d->mem[addr], 1, length, f) : fwrite(&d->mem[addr], 1, length, f);
|
|
|
|
printf("%04x bytes\n", result);
|
2021-03-22 22:04:31 -04:00
|
|
|
fclose(f);
|
|
|
|
}
|
2021-04-21 08:37:41 -04:00
|
|
|
mempoke16(d->dat, 0x2, result);
|
2021-03-22 22:04:31 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-26 13:02:13 -04:00
|
|
|
void
|
|
|
|
datetime_talk(Device *d, Uint8 b0, Uint8 w)
|
|
|
|
{
|
|
|
|
time_t seconds = time(NULL);
|
|
|
|
struct tm *t = localtime(&seconds);
|
|
|
|
t->tm_year += 1900;
|
|
|
|
mempoke16(d->dat, 0x0, t->tm_year);
|
|
|
|
d->dat[0x2] = t->tm_mon;
|
|
|
|
d->dat[0x3] = t->tm_mday;
|
|
|
|
d->dat[0x4] = t->tm_hour;
|
|
|
|
d->dat[0x5] = t->tm_min;
|
|
|
|
d->dat[0x6] = t->tm_sec;
|
|
|
|
d->dat[0x7] = t->tm_wday;
|
|
|
|
mempoke16(d->dat, 0x08, t->tm_yday);
|
|
|
|
d->dat[0xa] = t->tm_isdst;
|
|
|
|
(void)b0;
|
|
|
|
(void)w;
|
|
|
|
}
|
|
|
|
|
2021-04-24 04:10:24 -04:00
|
|
|
void
|
2021-04-24 13:15:47 -04:00
|
|
|
nil_talk(Device *d, Uint8 b0, Uint8 w)
|
2021-03-22 22:04:31 -04:00
|
|
|
{
|
2021-04-21 00:21:31 -04:00
|
|
|
(void)d;
|
2021-03-22 22:04:31 -04:00
|
|
|
(void)b0;
|
2021-04-24 13:15:47 -04:00
|
|
|
(void)w;
|
2021-03-22 22:04:31 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
#pragma mark - Generics
|
|
|
|
|
|
|
|
int
|
|
|
|
start(Uxn *u)
|
|
|
|
{
|
2021-04-08 12:59:45 -04:00
|
|
|
if(!evaluxn(u, PAGE_PROGRAM))
|
2021-03-22 22:04:31 -04:00
|
|
|
return error("Reset", "Failed");
|
2021-06-27 16:45:50 -04:00
|
|
|
while(mempeek16(devconsole->dat, 0))
|
|
|
|
while(read(0, &devconsole->dat[0x8], 1) > 0)
|
|
|
|
evaluxn(u, mempeek16(devconsole->dat, 0));
|
2021-03-22 22:04:31 -04:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
main(int argc, char **argv)
|
|
|
|
{
|
|
|
|
Uxn u;
|
|
|
|
|
|
|
|
if(argc < 2)
|
|
|
|
return error("Input", "Missing");
|
|
|
|
if(!bootuxn(&u))
|
|
|
|
return error("Boot", "Failed");
|
|
|
|
if(!loaduxn(&u, argv[1]))
|
|
|
|
return error("Load", "Failed");
|
|
|
|
|
2021-05-26 13:02:13 -04:00
|
|
|
portuxn(&u, 0x0, "empty", nil_talk);
|
2021-06-27 16:45:50 -04:00
|
|
|
devconsole = portuxn(&u, 0x1, "console", console_talk);
|
2021-05-26 13:02:13 -04:00
|
|
|
portuxn(&u, 0x2, "empty", nil_talk);
|
|
|
|
portuxn(&u, 0x3, "empty", nil_talk);
|
|
|
|
portuxn(&u, 0x4, "empty", nil_talk);
|
|
|
|
portuxn(&u, 0x5, "empty", nil_talk);
|
|
|
|
portuxn(&u, 0x6, "empty", nil_talk);
|
|
|
|
portuxn(&u, 0x7, "empty", nil_talk);
|
|
|
|
portuxn(&u, 0x8, "empty", nil_talk);
|
|
|
|
portuxn(&u, 0x9, "empty", nil_talk);
|
|
|
|
portuxn(&u, 0xa, "file", file_talk);
|
|
|
|
portuxn(&u, 0xb, "datetime", datetime_talk);
|
|
|
|
portuxn(&u, 0xc, "empty", nil_talk);
|
|
|
|
portuxn(&u, 0xd, "empty", nil_talk);
|
|
|
|
portuxn(&u, 0xe, "empty", nil_talk);
|
|
|
|
portuxn(&u, 0xf, "empty", nil_talk);
|
2021-05-26 13:16:42 -04:00
|
|
|
|
2021-03-22 22:04:31 -04:00
|
|
|
start(&u);
|
|
|
|
|
2021-05-26 13:02:13 -04:00
|
|
|
if(argc > 2)
|
|
|
|
printstack(&u.wst);
|
2021-03-22 22:04:31 -04:00
|
|
|
return 0;
|
|
|
|
}
|