// machine.h // The SplitBit machine, with nothing attached to look at it. // Written by Anachronaut #ifndef MACHINE_H #define MACHINE_H #include #include #include "cpu.h" #include "utility.h" // ---- Why the machine is not a main ---- // // There are two front ends: SplitBit, which is a terminal, and Voyager, which is a window // and a speaker. THEY ARE THE SAME MACHINE. Keeping it here means the difference between // them is presentation and nothing else - neither can quietly acquire behaviour the other // lacks, and the suite can hold them to it by running a program through both and comparing // what came out. // // It also decides where the devices live. A video device that only existed in the windowed // binary would be untestable, because the suite has no display; here it is part of the // machine, advances on emulated cycles, and Raylib only presents what it already produced. // How fast the machine runs when it is not being told to hurry. #define CYCLE_RATE 1000000 typedef struct { long long cycles_per_sec; long long accumulator_ns; struct timespec prev; } CycleTimer; void cycle_timer_init(CycleTimer *t, long long cycles_per_sec); // Call once per host frame. Returns how many SplitBit cycles to execute. int cycle_timer_tick(CycleTimer *t); typedef struct { CPURegisters cpu; CycleTimer timer; unsigned long cycleCount; uint8_t limitReached; uint8_t restartFailed; const char *programFile; EmulatorOptions options; } Machine; #define MACHINE_OK 0 #define MACHINE_ERROR 1 // No image and no disk. Told apart from an ordinary failure so that the front end can // print its own help, which is the one thing here that knows what it is called. #define MACHINE_NOTHING_TO_RUN 2 uint8_t machineStart(Machine *m, const EmulatorOptions *options, const char *programFile); // Whether there is any more running to do. False once the machine has halted, faulted, or // spent the cycle limit it was given. int machineRunning(const Machine *m); // ---- One slice, not the whole run ---- // // A front end with a window has to get a turn: run a slice, present a frame, run another. // A terminal simply runs slices until the machine stops. Both loops are three lines, which // is the point of cutting it here rather than anywhere else. void machineRunSlice(Machine *m); void machineStop(Machine *m); // Says how the run went and returns what the process should exit with. int machineReport(const Machine *m); #endif // MACHINE_H