uxn

Varvara Ordinator, written in ANSI C(SDL2)
git clone https://git.eamoncaddigan.net/uxn.git
Log | Files | Refs | README | LICENSE

commit 0e7ebb69e61107dc17282339d0696baee582dbd4
parent b9ff19d857a0451cf4a4024fca17a163169c284d
Author: Andrew Alderwick <andrew@alderwick.co.uk>
Date:   Sun, 27 Mar 2022 13:53:25 +0100

(uxnemu) Interrupt infinite loops with an error.

Diffstat:
Msrc/devices/system.c | 3++-
Msrc/uxn.c | 10++++++++++
Msrc/uxn.h | 1+
Msrc/uxncli.c | 6++++++
Msrc/uxnemu.c | 21++++++++++++++++++---
5 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/src/devices/system.c b/src/devices/system.c @@ -20,7 +20,8 @@ static const char *errors[] = { "Working-stack overflow", "Return-stack overflow", "Working-stack division by zero", - "Return-stack division by zero"}; + "Return-stack division by zero", + "Execution timeout"}; static void system_print(Stack *s, char *name) diff --git a/src/uxn.c b/src/uxn.c @@ -30,16 +30,25 @@ WITH REGARD TO THIS SOFTWARE. #define DEVW8(x, y) { dev->dat[(x) & 0xf] = y; dev->deo(dev, (x) & 0x0f); } #define DEVW(d, x, y) { dev = (d); if(bs) { DEVW8((x), (y) >> 8); DEVW8((x) + 1, (y)); } else { DEVW8((x), (y)) } } #define WARP(x) { if(bs) pc = (x); else pc += (Sint8)(x); } +#define LIMIT 0x40000 /* around 3 ms */ int uxn_eval(Uxn *u, Uint16 pc) { unsigned int a, b, c, j, k, bs, instr, errcode; + unsigned int limit = LIMIT; Uint8 kptr, *sp; Stack *src, *dst; Device *dev; if(!pc || u->dev[0].dat[0xf]) return 0; while((instr = u->ram[pc++])) { + if(!limit--) { + if(!uxn_interrupt()) { + errcode = 6; + goto timeout; + } + limit = LIMIT; + } /* Return Mode */ if(instr & 0x40) { src = &u->rst; dst = &u->wst; @@ -101,6 +110,7 @@ err: /* set 1 in errcode if it involved the return stack instead of the working stack */ /* (stack overflow & ( opcode was STH / JSR )) ^ Return Mode */ errcode |= ((errcode >> 1 & ((instr & 0x1e) == 0x0e)) ^ instr >> 6) & 1; +timeout: return uxn_halt(u, errcode, pc - 1); } diff --git a/src/uxn.h b/src/uxn.h @@ -47,6 +47,7 @@ typedef struct Uxn { int uxn_boot(Uxn *u, Uint8 *ram); int uxn_eval(Uxn *u, Uint16 pc); +int uxn_interrupt(void); int uxn_halt(Uxn *u, Uint8 error, Uint16 addr); Device *uxn_port(Uxn *u, Uint8 id, Uint8 (*deifn)(Device *, Uint8), void (*deofn)(Device *, Uint8)); #endif /* UXN_UXN_H */ diff --git a/src/uxncli.c b/src/uxncli.c @@ -101,6 +101,12 @@ load(Uxn *u, char *filepath) return 1; } +int +uxn_interrupt(void) +{ + return 1; +} + static int start(Uxn *u) { diff --git a/src/uxnemu.c b/src/uxnemu.c @@ -32,6 +32,7 @@ WITH REGARD TO THIS SOFTWARE. #define WIDTH 64 * 8 #define HEIGHT 40 * 8 #define PAD 4 +#define TIMEOUT_FRAMES 10 static SDL_Window *gWindow; static SDL_Texture *gTexture; @@ -43,7 +44,7 @@ static SDL_Rect gRect; static Device *devscreen, *devmouse, *devctrl, *devaudio0, *devfile0; static Uint8 zoom = 1; -static Uint32 stdin_event, audio0_event, redraw_event; +static Uint32 stdin_event, audio0_event, redraw_event, interrupt_event; static int error(char *msg, const char *err) @@ -89,12 +90,19 @@ stdin_handler(void *p) static int redraw_handler(void *p) { - SDL_Event event; + int dropped_frames = 0; + SDL_Event event, interrupt; event.type = redraw_event; + interrupt.type = interrupt_event; for(;;) { SDL_Delay(16); - if(SDL_HasEvent(redraw_event) == SDL_FALSE) + if(SDL_HasEvent(redraw_event) == SDL_FALSE) { SDL_PushEvent(&event); + dropped_frames = 0; + } + else if(++dropped_frames == TIMEOUT_FRAMES) { + SDL_PushEvent(&interrupt); + } } return 0; (void)p; @@ -169,6 +177,7 @@ init(void) stdin_event = SDL_RegisterEvents(1); audio0_event = SDL_RegisterEvents(POLYPHONY); redraw_event = SDL_RegisterEvents(1); + interrupt_event = SDL_RegisterEvents(1); SDL_CreateThread(stdin_handler, "stdin", NULL); SDL_CreateThread(redraw_handler, "redraw", NULL); SDL_StartTextInput(); @@ -468,6 +477,12 @@ run(Uxn *u) } int +uxn_interrupt(void) +{ + return SDL_PeepEvents(NULL, 1, SDL_GETEVENT, interrupt_event, interrupt_event) < 1; +} + +int main(int argc, char **argv) { SDL_DisplayMode DM;