mirror of
https://github.com/kichikuou/system3-sdl2.git
synced 2026-10-14 10:09:29 +03:00
Scenario: Label / page calls share a single call stack
This allows the debugger to present a linear backtrace. It's still possible to return from the other call type.
This commit is contained in:
+68
-10
@@ -1,4 +1,5 @@
|
||||
#include "scenario.h"
|
||||
#include <algorithm>
|
||||
#include <string.h>
|
||||
#include "common.h"
|
||||
#include "encoding.h"
|
||||
@@ -44,35 +45,92 @@ void Scenario::get_syseng_string(char* buf, int size, Encoding *enc, uint8_t ter
|
||||
void Scenario::label_call(int label)
|
||||
{
|
||||
if (label == 0) {
|
||||
if (label_stack.empty()) {
|
||||
// Return
|
||||
auto it = std::find_if(call_stack.rbegin(), call_stack.rend(),
|
||||
[](const StackFrame& frame) { return !frame.is_page_call; });
|
||||
if (it == call_stack.rend()) {
|
||||
WARNING("Label stack underflow");
|
||||
return;
|
||||
}
|
||||
jump_to(label_stack.back());
|
||||
label_stack.pop_back();
|
||||
if (it != call_stack.rbegin()) {
|
||||
WARNING("Return from non-top label call");
|
||||
}
|
||||
if (it->page != page_) {
|
||||
sys_error("Illegal label return at %d:%04x", page_, cmd_addr_);
|
||||
}
|
||||
jump_to(it->addr);
|
||||
call_stack.erase(std::next(it).base());
|
||||
} else {
|
||||
label_stack.push_back(addr_);
|
||||
call_stack.emplace_back(false, page_, addr_);
|
||||
jump_to(label);
|
||||
}
|
||||
}
|
||||
|
||||
size_t Scenario::label_stack_size() const
|
||||
{
|
||||
return std::count_if(call_stack.begin(), call_stack.end(),
|
||||
[](const StackFrame& frame) { return !frame.is_page_call; });
|
||||
}
|
||||
|
||||
void Scenario::label_stack_pop()
|
||||
{
|
||||
auto it = std::find_if(call_stack.rbegin(), call_stack.rend(),
|
||||
[](const StackFrame& frame) { return !frame.is_page_call; });
|
||||
if (it == call_stack.rend())
|
||||
return;
|
||||
call_stack.erase(std::next(it).base());
|
||||
}
|
||||
|
||||
void Scenario::label_stack_clear()
|
||||
{
|
||||
call_stack.erase(std::remove_if(call_stack.begin(), call_stack.end(),
|
||||
[](const StackFrame& frame) { return !frame.is_page_call; }), call_stack.end());
|
||||
}
|
||||
|
||||
void Scenario::page_call(int target_page)
|
||||
{
|
||||
if (target_page == 0) {
|
||||
if (page_stack.empty()) {
|
||||
// Return
|
||||
auto it = std::find_if(call_stack.rbegin(), call_stack.rend(),
|
||||
[](const StackFrame& frame) { return frame.is_page_call; });
|
||||
if (it == call_stack.rend()) {
|
||||
WARNING("Page stack underflow");
|
||||
return;
|
||||
}
|
||||
auto& pair = page_stack.back();
|
||||
page_jump(pair.first, pair.second);
|
||||
page_stack.pop_back();
|
||||
if (it != call_stack.rbegin()) {
|
||||
WARNING("Return from non-top page call");
|
||||
}
|
||||
page_jump(it->page, it->addr);
|
||||
call_stack.erase(std::next(it).base());
|
||||
} else {
|
||||
page_stack.emplace_back(page_, addr_);
|
||||
call_stack.emplace_back(true, page_, addr_);
|
||||
page_jump(target_page, 2);
|
||||
}
|
||||
}
|
||||
|
||||
[[noreturn]] void Scenario::unknown_command(uint8_t cmd) {
|
||||
size_t Scenario::page_stack_size() const
|
||||
{
|
||||
return std::count_if(call_stack.begin(), call_stack.end(),
|
||||
[](const StackFrame& frame) { return frame.is_page_call; });
|
||||
}
|
||||
|
||||
void Scenario::page_stack_pop()
|
||||
{
|
||||
auto it = std::find_if(call_stack.rbegin(), call_stack.rend(),
|
||||
[](const StackFrame& frame) { return frame.is_page_call; });
|
||||
if (it == call_stack.rend())
|
||||
return;
|
||||
call_stack.erase(std::next(it).base());
|
||||
}
|
||||
|
||||
void Scenario::page_stack_clear()
|
||||
{
|
||||
call_stack.erase(std::remove_if(call_stack.begin(), call_stack.end(),
|
||||
[](const StackFrame& frame) { return frame.is_page_call; }), call_stack.end());
|
||||
}
|
||||
|
||||
[[noreturn]] void Scenario::unknown_command(uint8_t cmd)
|
||||
{
|
||||
if (cmd >= 0x20 && cmd < 0x7f) {
|
||||
sys_error("Unknown Command: '%c' at %d:%04x", cmd, page_, cmd_addr_);
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user