From 7603ddf9cc694925ab6b36bdb230de3ab741e478 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Sat, 28 Jan 2023 16:47:41 -0800 Subject: [PATCH] Added MMU operation --- src/devices/system.c | 50 +++++++++++++++++++++++++++++++++++--------- src/devices/system.h | 6 ++++++ src/uxn11.c | 3 ++- src/uxncli.c | 9 ++++---- 4 files changed, 53 insertions(+), 15 deletions(-) diff --git a/src/devices/system.c b/src/devices/system.c index f1607cd..5339c41 100644 --- a/src/devices/system.c +++ b/src/devices/system.c @@ -1,10 +1,11 @@ #include +#include #include "../uxn.h" #include "system.h" /* -Copyright (c) 2022 Devine Lu Linvega, Andrew Alderwick +Copyright (c) 2022-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 @@ -42,27 +43,56 @@ int uxn_halt(Uxn *u, Uint8 instr, Uint8 err, Uint16 addr) { Uint8 *d = &u->dev[0x00]; - if(instr & 0x40) - u->rst->err = err; - else - u->wst->err = err; - if(GETVEC(d)) - uxn_eval(u, GETVEC(d)); - else { + Uint16 handler = GETVEC(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; } +/* 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 0x2: u->wst = (Stack *)(u->ram + (d[port] ? (d[port] * 0x100) : 0x10000)); break; - case 0x3: u->rst = (Stack *)(u->ram + (d[port] ? (d[port] * 0x100) : 0x10100)); break; + case 0x3: + PEKDEV(a, 0x2); + mmu_eval(u->ram, a); + break; case 0xe: if(u->wst->ptr || u->rst->ptr) system_inspect(u); break; diff --git a/src/devices/system.h b/src/devices/system.h index 9d8117d..6be1005 100644 --- a/src/devices/system.h +++ b/src/devices/system.h @@ -11,3 +11,9 @@ WITH REGARD TO THIS SOFTWARE. void system_inspect(Uxn *u); void system_deo(Uxn *u, Uint8 *d, Uint8 port); + +typedef struct { + Uint8 length, *pages; +} Mmu; + +Uint8 *mmu_init(Mmu *m, Uint16 pages); diff --git a/src/uxn11.c b/src/uxn11.c index a137766..01dafa1 100644 --- a/src/uxn11.c +++ b/src/uxn11.c @@ -225,6 +225,7 @@ int main(int argc, char **argv) { Uxn u; + Mmu m; int i; char expirations[8]; struct pollfd fds[2]; @@ -232,7 +233,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, (Uint8 *)calloc(0x10300, sizeof(Uint8)), emu_dei, emu_deo)) + if(!uxn_boot(&u, mmu_init(&m, 16), emu_dei, emu_deo)) return emu_error("Boot", "Failed"); /* start sequence */ if(!emu_start(&u, rom_path)) diff --git a/src/uxncli.c b/src/uxncli.c index 4a4538c..94d7935 100644 --- a/src/uxncli.c +++ b/src/uxncli.c @@ -7,7 +7,7 @@ #include "devices/datetime.h" /* -Copyright (c) 2021 Devine Lu Linvega +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 @@ -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,9 +78,10 @@ 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, (Uint8 *)calloc(0x10300, sizeof(Uint8)), emu_dei, emu_deo)) + if(!uxn_boot(&u, mmu_init(&mmu, 16), emu_dei, emu_deo)) return emu_error("Boot", "Failed"); if(!load_rom(&u, argv[1])) return emu_error("Load", "Failed");