diff --git a/src/cmdu.c b/src/cmdu.c index 60f99c3..a81b663 100644 --- a/src/cmdu.c +++ b/src/cmdu.c @@ -66,15 +66,17 @@ void commandUD() { void commandUR() { /* 最後に積まれたスタックの属性をリード */ int *var = getCaliVariable(); - // TODO: implement - var[0] = 0; - var[1] = 0; - var[2] = 0; - var[3] = 0; - var[4] = 0; - var[5] = 0; + + struct stack_info info; + sl_getStackInfo(&info); + var[0] = info.top_attr; + var[1] = info.page_calls; + var[2] = info.label_calls; + var[3] = info.var_pushes; + var[4] = info.label_calls_after_page_call; + var[5] = info.var_pushes_after_call; - DEBUG_COMMAND_YET("UR %p:",var); + DEBUG_COMMAND("UR %p:",var); } void commandUS() { diff --git a/src/debugger.c b/src/debugger.c index 8bbc8c6..a294f88 100644 --- a/src/debugger.c +++ b/src/debugger.c @@ -390,7 +390,7 @@ static void set_stack_frame(StackFrame *frame, int page, int addr, boolean is_re StackTrace *dbg_stack_trace(void) { int stack_size; - const int *stack_base = sl_getStackInfo(&stack_size); + const int *stack_base = sl_getStack(&stack_size); int page = nact->current_page; @@ -440,7 +440,7 @@ static boolean should_continue_step(void) { void dbg_stepout(void) { // Set an internal breakpoint at the return address of current frame. int stack_size; - const int *stack_base = sl_getStackInfo(&stack_size); + const int *stack_base = sl_getStack(&stack_size); const int *p = stack_base + stack_size - 1; while (p >= stack_base) { int page, addr = -1; diff --git a/src/savedata.c b/src/savedata.c index 2401879..a477db4 100644 --- a/src/savedata.c +++ b/src/savedata.c @@ -525,7 +525,7 @@ int save_saveAll(int no) { /* スタック情報のセーブ */ static void *saveStackInfo(Ald_stackHdr *head) { int count; - int *info = sl_getStackInfo(&count); + int *info = sl_getStack(&count); head->size = count * sizeof(int); return (void *)info; @@ -535,7 +535,7 @@ static void *saveStackInfo(Ald_stackHdr *head) { static void loadStackInfo(char *buf) { Ald_stackHdr *head = (Ald_stackHdr *)buf; char *data = buf + sizeof(Ald_stackHdr); - sl_putStackInfo((int *)data, head->size / sizeof(int)); + sl_putStack((int *)data, head->size / sizeof(int)); } /* 文字列変数のセーブ */ diff --git a/src/scenario.c b/src/scenario.c index 1352993..7cc76c6 100644 --- a/src/scenario.c +++ b/src/scenario.c @@ -47,9 +47,6 @@ static int *stack_buf; static int *stack_top; static int stack_size = 1024; -static int labelCallCnt = 0; -static int pageCallCnt = 0; - static char strbuf[512]; static dridata *dfile; // dri object for current page @@ -64,8 +61,6 @@ boolean sl_init(void) { stack_top = stack_buf; sl_jmpFar(0); - labelCallCnt = 0; - pageCallCnt = 0; return TRUE; } @@ -221,8 +216,6 @@ void sl_callNear(int address) { val[0] = sl_index; sl_push(STACK_NEARJMP, val, 1); sl_jmpNear(address); - - labelCallCnt++; } void sl_retNear(void) { @@ -245,15 +238,12 @@ void sl_retNear(void) { index = *(tmp + 2); free(tmp); sl_jmpNear(index); - - labelCallCnt--; } void sl_callFar(int page) { int val[2] = { sl_page, sl_index }; sl_push(STACK_FARJMP, val, 2); boolean ok = sl_jmpFar(page); - pageCallCnt++; if (!ok) sl_retFar(); } @@ -262,7 +252,6 @@ void sl_callFar2(int page, int address) { int val[2] = { sl_page, sl_index }; sl_push(STACK_FARJMP, val, 2); boolean ok = sl_jmpFar2(page, address); - pageCallCnt++; if (!ok) sl_retFar(); } @@ -273,7 +262,7 @@ void sl_retFar(void) { while (*tmp != STACK_FARJMP) { if (*tmp == STACK_NEARJMP) { - labelCallCnt--; + // do nothing } else if (*tmp == STACK_TXXSTATE) { popState(tmp); } else if (*tmp == STACK_VARIABLE) { @@ -288,8 +277,6 @@ void sl_retFar(void) { index = *(tmp + 3); free(tmp); sl_jmpFar2(page, index); - - pageCallCnt--; } /* UC0 */ @@ -316,7 +303,6 @@ void sl_clearStack(bool restore) { free(tmp); } - labelCallCnt = pageCallCnt = 0; stack_top = stack_buf; } @@ -326,10 +312,8 @@ void sl_dropPageCalls(int cnt) { int *tmp = sl_pop(); switch (*tmp) { case STACK_NEARJMP: - labelCallCnt--; break; case STACK_FARJMP: - pageCallCnt--; cnt--; break; case STACK_VARIABLE: @@ -351,7 +335,6 @@ void sl_dropLabelCalls(int cnt) { int *tmp = sl_pop(); switch (*tmp) { case STACK_NEARJMP: - labelCallCnt--; cnt--; break; case STACK_VARIABLE: @@ -419,12 +402,12 @@ static void popVars(int *tmp) { memcpy(topVar, tmp + 4, sizeof(int) * cnt); } -int *sl_getStackInfo(int *size) { +int *sl_getStack(int *size) { *size = stack_top - stack_buf; return stack_buf; } -void sl_putStackInfo(int *data, int size) { +void sl_putStack(int *data, int size) { if (size > stack_size) { stack_size = size << 1; stack_buf = calloc(stack_size, sizeof(int)); @@ -435,6 +418,28 @@ void sl_putStackInfo(int *data, int size) { stack_top = stack_buf + size; } +void sl_getStackInfo(struct stack_info *info) { + memset(info, 0, sizeof(struct stack_info)); + for (int *p = stack_top; p > stack_buf; p -= p[-2] + 2) { + switch (p[-1]) { + case STACK_NEARJMP: + info->label_calls++; + if (!info->page_calls) + info->label_calls_after_page_call++; + break; + case STACK_FARJMP: + info->page_calls++; + break; + case STACK_VARIABLE: + info->var_pushes += p[-2] - 2; + if (info->page_calls + info->label_calls == 0) + info->var_pushes_after_call += p[-2] - 2; + break; + case STACK_TXXSTATE: + break; + } + } +} /* TPx */ void sl_pushState(enum txx_type type, int val1, int val2) { @@ -516,12 +521,9 @@ void sl_returnGoto(int address) { // index = *(tmp + 3); free(tmp); sl_jmpFar2(page, address); - pageCallCnt--; } else { // index = *(tmp + 2); free(tmp); sl_jmpNear(address); - - labelCallCnt--; } } diff --git a/src/scenario.h b/src/scenario.h index d22a7fd..05048c7 100644 --- a/src/scenario.h +++ b/src/scenario.h @@ -43,6 +43,15 @@ enum txx_type { TxxTEXTLOC = 3 }; +struct stack_info { + int top_attr; // always zero? + int page_calls; + int label_calls; + int var_pushes; + int label_calls_after_page_call; + int var_pushes_after_call; +}; + // Use functions below instead of accessing these variables directly. extern const uint8_t *sl_sco; // scenario page buffer extern int sl_page; // current scenario page (0-based) @@ -73,8 +82,9 @@ 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); -void sl_putStackInfo(int *data, int size); +int *sl_getStack(int *size); +void sl_putStack(int *data, int size); +void sl_getStackInfo(struct stack_info *info); void sl_pushState(enum txx_type type, int val1, int val2); void sl_popState(enum txx_type expected_type); void *sl_setDataTable(int page, int index);