diff --git a/README.md b/README.md index f2c5fc5..f2ab868 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,10 @@ The available environment variables are: properly, some other will ignore this and setup the text mode again. +- `EMU_SLOW_FACTOR` Set a slowing factor, this forces the CPU to take at + least for the given amount of nanoseconds for every + opcode being executed. + Simple Example -------------- diff --git a/src/cpu.c b/src/cpu.c index 8eef9a0..aaee140 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -1,11 +1,14 @@ #include #include +#include +#include #include "cpu.h" #include "dbg.h" #include "dis.h" #include "emu.h" #include "os.h" +#include "env.h" // Forward declarations static void do_instruction(uint8_t code); @@ -2550,12 +2553,34 @@ static void do_instruction(uint8_t code) }; } +static long slow_ns = 0; + +static void slow_cpu(struct timespec *start) +{ + if(!slow_ns) + return; + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + long left = slow_ns - + (now.tv_sec - start->tv_sec) * 1000000000L - + (now.tv_nsec - start->tv_nsec); + if (left > 0) + clock_nanosleep(CLOCK_MONOTONIC, 0, + &(struct timespec){left / 1000000000L, + left % 1000000000L}, NULL); +} + void execute(void) { + if (getenv(ENV_SLOW)) + slow_ns = atol(getenv(ENV_SLOW)); for(; !exit_cpu;) { + struct timespec start; + clock_gettime(CLOCK_MONOTONIC, &start); handle_irq(); next_instruction(); + slow_cpu(&start); } } diff --git a/src/env.h b/src/env.h index 780065b..5cabd6e 100644 --- a/src/env.h +++ b/src/env.h @@ -12,3 +12,4 @@ #define ENV_LOWMEM "EMU2_LOWMEM" #define ENV_ROWS "EMU2_ROWS" #define ENV_DOSVER "EMU2_DOSVER" +#define ENV_SLOW "EMU_SLOW_FACTOR"