biosandbox/biosandbox/Emulation.h
2025-12-28 16:55:03 -05:00

96 lines
2.4 KiB
C++

#pragma once
#include <vector>
#include "bsuml.h"
#include <stdexcept>
#include <format>
#include <map>
#include <print>
namespace bio {
namespace emu {
using instruction_set = std::vector<native_callable<int, int, unsigned char*, bool*, std::vector<int>*, std::map<std::string, unsigned long long>*>>;
memory_dependent using mem_buffer = unsigned char[memsize];
struct symbol {
unsigned offset;
};
struct application {
std::vector<symbol> symbols;
// contents
unsigned bufferLength;
unsigned char* buffer;
};
memory_dependent class emulator_base {
public:
instruction_set isa;
mem_buffer<memsize> memory;
std::vector<symbol> symbols;
std::vector<int> callStack;
std::map<std::string, unsigned long long> registers;
virtual void load_app(application& app) = 0;
virtual bool run_symbol(int symbol) = 0;
void clear_registers() {
registers.clear();
}
void clear_memory() {
times(memsize) {
memory[___i] = 0;
}
}
};
memory_dependent class linear_emulator_base : public memory_passdown(emulator_base) {
public:
int instructionPointer;
bool run_symbol(int symbol) {
// check symbol ID is within symbol count
if (symbol > this->symbols.size() && symbol != -1)
throw std::out_of_range(
std::format("Symbol is outside of the symbol range ({} > {}, described as a maximum of {})",
symbol,
this->symbols.size(),
this->symbols.size() - 1
)
);
// check if symbol ID is erroneous
if (symbol < -1)
throw std::out_of_range(
std::format("Symbol ID for entry at start is explicitly -1 (received {} instead)",
symbol
)
);
// apply instruction pointer
if (symbol >= 0) instructionPointer = this->symbols[symbol].offset;
else instructionPointer = 0;
// execute
bool returned = false;
until(returned || instructionPointer >= memsize) {
this->instructionPointer +=
this->isa[this->memory[instructionPointer]](instructionPointer, this->memory, &returned, &this->callStack, &this->registers);
if (instructionPointer < 0 || instructionPointer > memsize) {
throw std::out_of_range("Symbol causes instruction pointer to err out of memory");
}
}
if (returned) {
std::print("Exited through conventional means [returned out of symbol]\n");
return true;
}
return false;
}
};
}
}