From 8087d11b2bd363328debbc3d78115d6c75d2ccc6 Mon Sep 17 00:00:00 2001 From: kichikuou Date: Fri, 10 Feb 2023 14:21:28 +0900 Subject: [PATCH] Fix UC command * UC0 should restore values pushed by US/TPx * UC1 should stop when the stack top is a page call * UC1/2 should restore status pushes by TPx * UC1/2 should not consume the count for non-call stack frames * Add support for UC3 command --- src/cmdu.c | 12 ++++++--- src/scenario.c | 73 +++++++++++++++++++++++++++++++++++--------------- src/scenario.h | 6 ++--- 3 files changed, 63 insertions(+), 28 deletions(-) diff --git a/src/cmdu.c b/src/cmdu.c index d35bf39..c02f3db 100644 --- a/src/cmdu.c +++ b/src/cmdu.c @@ -33,12 +33,16 @@ void commandUC() { /* 王道勇者 */ switch(mode) { case 0: - sl_stackClear_allCall(); break; + sl_clearStack(true); + break; case 1: - sl_stackClear_labelCall(num); break; + sl_dropLabelCalls(num); + break; case 2: - sl_stackClear_pageCall(num); break; - default: + sl_dropPageCalls(num); + break; + case 3: + sl_clearStack(false); break; } DEBUG_COMMAND("UC %d,%d:",mode,num); diff --git a/src/scenario.c b/src/scenario.c index 85536d8..609cea5 100644 --- a/src/scenario.c +++ b/src/scenario.c @@ -317,44 +317,75 @@ void sl_retFar2(void) { } /* UC0 */ -void sl_stackClear_allCall(void) { - free(stack_buf); - stack_buf = calloc(stack_size, sizeof(int)); - if (stack_buf == NULL) - NOMEMERR(); +void sl_clearStack(bool restore) { + if (!restore) { + stack_top = stack_buf; + return; + } + while (stack_top > stack_buf) { + int *tmp = sl_pop(); + switch (*tmp) { + case STACK_NEARJMP: + case STACK_FARJMP: + break; + case STACK_VARIABLE: + popVars(tmp); + break; + case STACK_TXXSTATE: + popState(tmp); + break; + default: + SYSERROR("broken stack"); + } + free(tmp); + } + labelCallCnt = pageCallCnt = 0; stack_top = stack_buf; } /* UC 2 */ -void sl_stackClear_pageCall(int cnt) { - int *tmp; - - while(cnt--) { - tmp = sl_pop(); - if (*tmp == STACK_NEARJMP) { +void sl_dropPageCalls(int cnt) { + while (cnt > 0 && stack_top > stack_buf) { + int *tmp = sl_pop(); + switch (*tmp) { + case STACK_NEARJMP: labelCallCnt--; - } else if (*tmp == STACK_FARJMP) { + break; + case STACK_FARJMP: pageCallCnt--; - } else if (*tmp == STACK_VARIABLE) { + cnt--; + break; + case STACK_VARIABLE: popVars(tmp); - } else { - SYSERROR("Stack buffer is illegal"); + break; + case STACK_TXXSTATE: + popState(tmp); + break; + default: + SYSERROR("broken stack"); } free(tmp); } } /* UC 1 */ -void sl_stackClear_labelCall(int cnt) { - while (cnt--) { +void sl_dropLabelCalls(int cnt) { + while (cnt > 0 && stack_top > stack_buf && stack_top[-1] != STACK_FARJMP) { int *tmp = sl_pop(); - if (*tmp == STACK_NEARJMP) { + switch (*tmp) { + case STACK_NEARJMP: labelCallCnt--; - } else if (*tmp == STACK_VARIABLE) { + cnt--; + break; + case STACK_VARIABLE: popVars(tmp); - } else { - SYSERROR("No label call to pop"); + break; + case STACK_TXXSTATE: + popState(tmp); + break; + default: + SYSERROR("broken stack"); } free(tmp); } diff --git a/src/scenario.h b/src/scenario.h index c2c6dd2..f537853 100644 --- a/src/scenario.h +++ b/src/scenario.h @@ -69,9 +69,9 @@ void sl_callFar(int page); void sl_callFar2(int page, int address); void sl_retFar(void); void sl_retFar2(void); -void sl_stackClear_allCall(void); -void sl_stackClear_labelCall(int cnt); -void sl_stackClear_pageCall(int cnt); +void sl_clearStack(bool restore); +void sl_dropLabelCalls(int cnt); +void sl_dropPageCalls(int cnt); void sl_pushVar(struct VarRef *vref, int cnt); void sl_popVar(struct VarRef *vref, int cnt); int *sl_getStackInfo(int *size);