(uxnemu) Interrupt infinite loops with an error.
This commit is contained in:
parent
b9ff19d857
commit
0e7ebb69e6
|
@ -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)
|
||||
|
|
10
src/uxn.c
10
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -101,6 +101,12 @@ load(Uxn *u, char *filepath)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
uxn_interrupt(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
start(Uxn *u)
|
||||
{
|
||||
|
|
21
src/uxnemu.c
21
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();
|
||||
|
@ -467,6 +476,12 @@ run(Uxn *u)
|
|||
return error("SDL_WaitEvent", SDL_GetError());
|
||||
}
|
||||
|
||||
int
|
||||
uxn_interrupt(void)
|
||||
{
|
||||
return SDL_PeepEvents(NULL, 1, SDL_GETEVENT, interrupt_event, interrupt_event) < 1;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue