From 0627dceb1ce0a3e2eafe739dd774b59734ad6aa5 Mon Sep 17 00:00:00 2001 From: Elisha Hollander Date: Thu, 26 Feb 2026 00:14:57 +0200 Subject: [PATCH 1/7] add `EMU_SLOW_FACTOR` environment variable to the README --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index f2c5fc5..5a79e90 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, the program will force the CPU to + take at least for this amount of milliseconds for every + opcode being executed. + Simple Example -------------- From d26a9511622bbfc88d4e03361096935ef3426ea9 Mon Sep 17 00:00:00 2001 From: Elisha Hollander Date: Thu, 26 Feb 2026 00:18:02 +0200 Subject: [PATCH 2/7] add `ENV_SLOW` macro --- src/env.h | 1 + 1 file changed, 1 insertion(+) 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" From 98c2985249aa9369d6efa36c26939363f6d3b482 Mon Sep 17 00:00:00 2001 From: Elisha Hollander Date: Thu, 26 Feb 2026 00:23:21 +0200 Subject: [PATCH 3/7] implement controlled execution speed --- src/cpu.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/cpu.c b/src/cpu.c index 8eef9a0..46ecc22 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,30 @@ static void do_instruction(uint8_t code) }; } + +static void slow_cpu(struct timespec *start) +{ + if (getenv(ENV_SLOW)) { + long remaining = atoi(getenv(ENV_SLOW)); + if (remaining > 0) { + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + remaining -= (now.tv_sec - start->tv_sec) * 1000000; + remaining -= (now.tv_nsec - start->tv_nsec) / 1000; + if (remaining > 0) usleep(remaining); + } + } +} + void execute(void) { for(; !exit_cpu;) { + struct timespec start; + clock_gettime(CLOCK_MONOTONIC, &start); handle_irq(); next_instruction(); + slow_clock(&start); } } From b6ed05b9ed8d15a2cffcb32773a9704a691e7b95 Mon Sep 17 00:00:00 2001 From: Elisha Hollander Date: Thu, 26 Feb 2026 00:26:33 +0200 Subject: [PATCH 4/7] typo fix --- src/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cpu.c b/src/cpu.c index 46ecc22..2d3e2fe 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -2576,7 +2576,7 @@ void execute(void) clock_gettime(CLOCK_MONOTONIC, &start); handle_irq(); next_instruction(); - slow_clock(&start); + slow_cpu(&start); } } From 14b1eb840dcaab9349c01cf565eaafc18097c7ef Mon Sep 17 00:00:00 2001 From: Elisha Hollander Date: Thu, 26 Feb 2026 00:28:52 +0200 Subject: [PATCH 5/7] fix wording --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5a79e90..37f684f 100644 --- a/README.md +++ b/README.md @@ -89,8 +89,8 @@ The available environment variables are: properly, some other will ignore this and setup the text mode again. -- `EMU_SLOW_FACTOR` Set a slowing factor, the program will force the CPU to - take at least for this amount of milliseconds for every +- `EMU_SLOW_FACTOR` Set a slowing factor, this forces the CPU to take at + least for the given amount of microseconds for every opcode being executed. From 6dcefbac955a516f955bffbec5b7799c92a5052d Mon Sep 17 00:00:00 2001 From: donno2048 Date: Tue, 10 Mar 2026 02:44:42 +0000 Subject: [PATCH 6/7] time deterministic --- src/cpu.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/cpu.c b/src/cpu.c index 2d3e2fe..e6f52b9 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -2553,23 +2553,27 @@ static void do_instruction(uint8_t code) }; } +static long slow_ms = 0; static void slow_cpu(struct timespec *start) { - if (getenv(ENV_SLOW)) { - long remaining = atoi(getenv(ENV_SLOW)); - if (remaining > 0) { - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - remaining -= (now.tv_sec - start->tv_sec) * 1000000; - remaining -= (now.tv_nsec - start->tv_nsec) / 1000; - if (remaining > 0) usleep(remaining); - } - } + if(!slow_ms) + return; + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + long left = slow_ms * 1000L - + (now.tv_sec - start->tv_sec) * 1000000000L - + (now.tv_nsec - start->tv_nsec); + if (left > 0) + clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, + &(struct timespec){left / 1000000000L, + left % 1000000000L}, NULL); } void execute(void) { + if (getenv(ENV_SLOW)) + slow_ms = atol(getenv(ENV_SLOW)); for(; !exit_cpu;) { struct timespec start; From 98ac2f936ebbcf22413e20802a05ae37fd67ae9b Mon Sep 17 00:00:00 2001 From: donno2048 Date: Tue, 10 Mar 2026 03:07:41 +0000 Subject: [PATCH 7/7] use nanoseconds and no TIMER_ABSTIME --- README.md | 2 +- src/cpu.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 37f684f..f2ab868 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ The available environment variables are: mode again. - `EMU_SLOW_FACTOR` Set a slowing factor, this forces the CPU to take at - least for the given amount of microseconds for every + least for the given amount of nanoseconds for every opcode being executed. diff --git a/src/cpu.c b/src/cpu.c index e6f52b9..aaee140 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -2553,19 +2553,19 @@ static void do_instruction(uint8_t code) }; } -static long slow_ms = 0; +static long slow_ns = 0; static void slow_cpu(struct timespec *start) { - if(!slow_ms) + if(!slow_ns) return; struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); - long left = slow_ms * 1000L - + long left = slow_ns - (now.tv_sec - start->tv_sec) * 1000000000L - (now.tv_nsec - start->tv_nsec); if (left > 0) - clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, + clock_nanosleep(CLOCK_MONOTONIC, 0, &(struct timespec){left / 1000000000L, left % 1000000000L}, NULL); } @@ -2573,7 +2573,7 @@ static void slow_cpu(struct timespec *start) void execute(void) { if (getenv(ENV_SLOW)) - slow_ms = atol(getenv(ENV_SLOW)); + slow_ns = atol(getenv(ENV_SLOW)); for(; !exit_cpu;) { struct timespec start;