Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 14 additions & 7 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,25 @@
"MIMode": "gdb"
},
{
"name": "macOS: Wizardry 安定化 (LOST=15000 + CONST_EXEC=1)",
"name": "macOS: Wizardry 安定化 4MHz",
"type": "lldb",
"request": "launch",
"program": "${workspaceFolder}/build/XM8.app/Contents/MacOS/xm8",
"args": [],
"cwd": "${workspaceFolder}",
"env": {
"XM8_FDC_TRACE": "1",
"XM8_FDC_TRACE_IO": "1",
"XM8_FDC_TRACE_MAX_LINES": "400000",
"XM8_FDC_TRACE_FILE": "xm8_fdc_trace_wiz_4mhz_stable.log",
"XM8_FDC_SEEK_SCALE": "1000",
"XM8_DISABLE_UNSTABLE_MASK": "1",
"XM8_FDC_LOST_USEC": "15000",
"XM8_FDC_CONST_EXEC_USEC": "1",
"XM8_FDC_TRACE_FILE": "xm8_fdc_trace_wiz_stable.log"
"XM8_FDC_CONST_EXEC_USEC": "1"
}
},
{
"name": "macOS: FDCトレース基準 (scale=1000, no-unstable)",
"name": "macOS: Wizardry 安定化 8MHz",
"type": "lldb",
"request": "launch",
"program": "${workspaceFolder}/build/XM8.app/Contents/MacOS/xm8",
Expand All @@ -47,9 +49,14 @@
"XM8_FDC_TRACE": "1",
"XM8_FDC_TRACE_IO": "1",
"XM8_FDC_TRACE_MAX_LINES": "400000",
"XM8_FDC_SEEK_SCALE": "1000",
"XM8_DISABLE_UNSTABLE_MASK": "1",
"XM8_FDC_TRACE_FILE": "xm8_fdc_trace_s1000_nounstable.log"
"XM8_FDC_TRACE_FILE": "xm8_fdc_trace_wiz_8mhz_stable.log",
"XM8_FDC_SEEK_SCALE_8MHZ": "1500",
"XM8_DISABLE_UNSTABLE_MASK_8MHZ": "1",
"XM8_FDC_LOST_USEC_8MHZ": "12000",
"XM8_FDC_CONST_EXEC_USEC_8MHZ": "1",
"XM8_FDC_CONST_EXEC_DELAY_USEC_8MHZ": "100",
"XM8_FDC_REQUEST_SINGLE_EXEC_8MHZ": "1",
"XM8_FDC_TC_EXEC_8MHZ": "0"
}
}
]
Expand Down
65 changes: 50 additions & 15 deletions Source/ePC-8801MA/vm/event.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,49 @@
*/

#include "event.h"
#ifdef SDL
#include "z80.h"
#endif // SDL
#ifdef SDL
#include "z80.h"
#include <cstdlib>
#endif // SDL

#define EVENT_MIX 0

#ifdef SDL
#define SINGLE_EXEC_TIMEOUT 10000
// exit single exec mode (us)

static bool g_single_exec_tuned = false;
static int g_single_exec_timeout_usec = SINGLE_EXEC_TIMEOUT;
static int g_single_exec_slice_clocks = 4;

static void tune_single_exec_params()
{
if(g_single_exec_tuned) {
return;
}
g_single_exec_tuned = true;

// PC-8801MA 8MHz mode needs a wider single-exec window for stable FDC boot timing.
if(config.cpu_type == 0) {
g_single_exec_timeout_usec = 20000;
g_single_exec_slice_clocks = 20;
}

const char* timeout_env = getenv("XM8_EVENT_SINGLE_EXEC_TIMEOUT_USEC");
if(timeout_env != NULL && timeout_env[0] != '\0') {
long v = strtol(timeout_env, NULL, 10);
if(v >= 1000 && v <= 1000000) {
g_single_exec_timeout_usec = (int)v;
}
}
const char* slice_env = getenv("XM8_EVENT_SINGLE_EXEC_SLICE_CLOCKS");
if(slice_env != NULL && slice_env[0] != '\0') {
long v = strtol(slice_env, NULL, 10);
if(v >= 1 && v <= 1024) {
g_single_exec_slice_clocks = (int)v;
}
}
}
#endif // SDL

void EVENT::initialize()
Expand Down Expand Up @@ -146,13 +180,14 @@ void EVENT::request_single_exec()
void EVENT::drive()
{
#ifdef SDL
tune_single_exec_params();
if (single_exec == true) {
// if passed 10ms, disable single_exec
if (passed_usec(single_exec_clock) > SINGLE_EXEC_TIMEOUT) {
if (passed_usec(single_exec_clock) > g_single_exec_timeout_usec) {
single_exec = false;
}
}
#endif // SDL
#endif // SDL

// raise pre frame events to update timing settings
for(int i = 0; i < frame_event_count; i++) {
Expand Down Expand Up @@ -249,8 +284,8 @@ void EVENT::drive()
if (main_cpu_exec > 0) {
// single execution ?
if (single_exec == true) {
if (main_cpu_exec > 4) {
main_cpu_exec = 4;
if (main_cpu_exec > g_single_exec_slice_clocks) {
main_cpu_exec = g_single_exec_slice_clocks;
}
}
cpu_done = d_cpu[0].device->run(main_cpu_exec);
Expand All @@ -265,11 +300,11 @@ void EVENT::drive()
// running sub cpu
if (d_cpu[1].update_clocks == 0x400) {
// main 4MHz
if (cpu_remain > 0) {
sub_cpu_exec = cpu_remain;
if (cpu_remain > 0) {
sub_cpu_exec = cpu_remain;
if (single_exec == true) {
if (sub_cpu_exec > 4) {
sub_cpu_exec = 4;
if (sub_cpu_exec > g_single_exec_slice_clocks) {
sub_cpu_exec = g_single_exec_slice_clocks;
}
}

Expand All @@ -279,11 +314,11 @@ void EVENT::drive()
}
else {
// main 8MHz
if (cpu_remain > 2) {
sub_cpu_exec = cpu_remain / 2;
if (cpu_remain > 2) {
sub_cpu_exec = cpu_remain / 2;
if (single_exec == true) {
if (sub_cpu_exec > 4) {
sub_cpu_exec = 4;
if (sub_cpu_exec > g_single_exec_slice_clocks) {
sub_cpu_exec = g_single_exec_slice_clocks;
}
}

Expand Down
88 changes: 79 additions & 9 deletions Source/ePC-8801MA/vm/upd765a.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ static bool g_fdc_disable_unstable_checked = false;
static bool g_fdc_disable_unstable = true;
static bool g_fdc_const_exec_checked = false;
static bool g_fdc_const_exec = true;
static bool g_fdc_const_exec_delay_usec_checked = false;
static int g_fdc_const_exec_delay_usec = 100;
static bool g_fdc_request_single_exec_checked = false;
static bool g_fdc_request_single_exec = true;
static bool g_fdc_tc_exec_checked = false;
Expand All @@ -95,6 +97,17 @@ static int g_fdc_lost_usec = 15000;

static void fdc_trace(const char* fmt, ...);

static bool fdc_is_8mhz_mode()
{
// PC-8801MA core uses cpu_type==0 as 8MHz path.
return (config.cpu_type == 0);
}

static const char* fdc_pick_env_name(const char* base_name, const char* mode_name)
{
return fdc_is_8mhz_mode() ? mode_name : base_name;
}

static bool fdc_trace_enabled()
{
if(!g_fdc_trace_checked) {
Expand Down Expand Up @@ -132,7 +145,11 @@ static bool fdc_trace_io_enabled()
static int fdc_seek_scale()
{
if(!g_fdc_seek_scale_checked) {
const char* env = getenv("XM8_FDC_SEEK_SCALE");
const char* env_name = fdc_pick_env_name("XM8_FDC_SEEK_SCALE", "XM8_FDC_SEEK_SCALE_8MHZ");
const char* env = getenv(env_name);
if((env == NULL || env[0] == '\0') && fdc_is_8mhz_mode()) {
env = getenv("XM8_FDC_SEEK_SCALE");
}
if(env != NULL && env[0] != '\0') {
long v = strtol(env, NULL, 10);
if(v >= 1 && v <= 10000) {
Expand All @@ -147,7 +164,11 @@ static int fdc_seek_scale()
static bool fdc_disable_unstable_mask()
{
if(!g_fdc_disable_unstable_checked) {
const char* env = getenv("XM8_DISABLE_UNSTABLE_MASK");
const char* env_name = fdc_pick_env_name("XM8_DISABLE_UNSTABLE_MASK", "XM8_DISABLE_UNSTABLE_MASK_8MHZ");
const char* env = getenv(env_name);
if((env == NULL || env[0] == '\0') && fdc_is_8mhz_mode()) {
env = getenv("XM8_DISABLE_UNSTABLE_MASK");
}
if(env != NULL && env[0] != '\0') {
g_fdc_disable_unstable = (env[0] != '0');
}
Expand All @@ -159,7 +180,11 @@ static bool fdc_disable_unstable_mask()
static bool fdc_const_exec_timing()
{
if(!g_fdc_const_exec_checked) {
const char* env = getenv("XM8_FDC_CONST_EXEC_USEC");
const char* env_name = fdc_pick_env_name("XM8_FDC_CONST_EXEC_USEC", "XM8_FDC_CONST_EXEC_USEC_8MHZ");
const char* env = getenv(env_name);
if((env == NULL || env[0] == '\0') && fdc_is_8mhz_mode()) {
env = getenv("XM8_FDC_CONST_EXEC_USEC");
}
if(env != NULL && env[0] != '\0') {
g_fdc_const_exec = (env[0] != '0');
}
Expand All @@ -168,10 +193,33 @@ static bool fdc_const_exec_timing()
return g_fdc_const_exec;
}

static int fdc_const_exec_delay_usec()
{
if(!g_fdc_const_exec_delay_usec_checked) {
const char* env_name = fdc_pick_env_name("XM8_FDC_CONST_EXEC_DELAY_USEC", "XM8_FDC_CONST_EXEC_DELAY_USEC_8MHZ");
const char* env = getenv(env_name);
if((env == NULL || env[0] == '\0') && fdc_is_8mhz_mode()) {
env = getenv("XM8_FDC_CONST_EXEC_DELAY_USEC");
}
if(env != NULL && env[0] != '\0') {
long v = strtol(env, NULL, 10);
if(v >= 1 && v <= 1000000) {
g_fdc_const_exec_delay_usec = (int)v;
}
}
g_fdc_const_exec_delay_usec_checked = true;
}
return g_fdc_const_exec_delay_usec;
}

static bool fdc_request_single_exec_enabled()
{
if(!g_fdc_request_single_exec_checked) {
const char* env = getenv("XM8_FDC_REQUEST_SINGLE_EXEC");
const char* env_name = fdc_pick_env_name("XM8_FDC_REQUEST_SINGLE_EXEC", "XM8_FDC_REQUEST_SINGLE_EXEC_8MHZ");
const char* env = getenv(env_name);
if((env == NULL || env[0] == '\0') && fdc_is_8mhz_mode()) {
env = getenv("XM8_FDC_REQUEST_SINGLE_EXEC");
}
if(env != NULL && env[0] != '\0') {
g_fdc_request_single_exec = (env[0] != '0');
}
Expand All @@ -183,7 +231,14 @@ static bool fdc_request_single_exec_enabled()
static bool fdc_tc_exec_enabled()
{
if(!g_fdc_tc_exec_checked) {
const char* env = getenv("XM8_FDC_TC_EXEC");
// 8MHz mode is more stable with legacy PHASE_EXEC->TC path disabled by default.
// 4MHz keeps the previous default behavior.
g_fdc_tc_exec = !fdc_is_8mhz_mode();
const char* env_name = fdc_pick_env_name("XM8_FDC_TC_EXEC", "XM8_FDC_TC_EXEC_8MHZ");
const char* env = getenv(env_name);
if((env == NULL || env[0] == '\0') && fdc_is_8mhz_mode()) {
env = getenv("XM8_FDC_TC_EXEC");
}
if(env != NULL && env[0] != '\0') {
g_fdc_tc_exec = (env[0] != '0');
}
Expand All @@ -195,7 +250,11 @@ static bool fdc_tc_exec_enabled()
static int fdc_lost_event_usec()
{
if(!g_fdc_lost_usec_checked) {
const char* env = getenv("XM8_FDC_LOST_USEC");
const char* env_name = fdc_pick_env_name("XM8_FDC_LOST_USEC", "XM8_FDC_LOST_USEC_8MHZ");
const char* env = getenv(env_name);
if((env == NULL || env[0] == '\0') && fdc_is_8mhz_mode()) {
env = getenv("XM8_FDC_LOST_USEC");
}
if(env != NULL && env[0] != '\0') {
long v = strtol(env, NULL, 10);
if(v >= 1 && v <= 10000000) {
Expand All @@ -221,11 +280,20 @@ static void fdc_dump_runtime_params()
int lost_usec = fdc_lost_event_usec();
bool disable_unstable = fdc_disable_unstable_mask();
bool const_exec = fdc_const_exec_timing();
fdc_trace("runtime_params: seek_scale=%d disable_unstable=%d lost_usec=%d const_exec=%d",
int const_exec_delay_usec = fdc_const_exec_delay_usec();
bool req_single_exec = fdc_request_single_exec_enabled();
bool tc_exec = fdc_tc_exec_enabled();
fdc_trace("runtime_params: cpu_type=%d cpu_power=%d mode=%s seek_scale=%d disable_unstable=%d lost_usec=%d const_exec=%d const_exec_delay_usec=%d req_single_exec=%d tc_exec=%d",
config.cpu_type,
config.cpu_power,
fdc_is_8mhz_mode() ? "8mhz" : "4mhz",
seek_scale,
disable_unstable ? 1 : 0,
lost_usec,
const_exec ? 1 : 0);
const_exec ? 1 : 0,
const_exec_delay_usec,
req_single_exec ? 1 : 0,
tc_exec ? 1 : 0);
}

static void fdc_trace(const char* fmt, ...)
Expand Down Expand Up @@ -435,6 +503,8 @@ void UPD765A::release()
g_fdc_disable_unstable = true;
g_fdc_const_exec_checked = false;
g_fdc_const_exec = true;
g_fdc_const_exec_delay_usec_checked = false;
g_fdc_const_exec_delay_usec = 100;
g_fdc_request_single_exec_checked = false;
g_fdc_request_single_exec = true;
g_fdc_tc_exec_checked = false;
Expand Down Expand Up @@ -1977,7 +2047,7 @@ double UPD765A::get_usec_to_exec_phase()
// Optional timing stabilization for troublesome titles:
// keep EXEC transition delay deterministic and independent of rotational position.
if(fdc_const_exec_timing()) {
return 100;
return fdc_const_exec_delay_usec();
}

// XXX: this image may have incorrect skew, so use constant period.
Expand Down