From 80f5c472210f70431ea8e0d0ce4f0aa116fabb38 Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 23 Dec 2024 00:30:15 +0100 Subject: [PATCH 1/7] AT ESDI: Fix controller name in IDENTIFY. --- src/disk/hdc_esdi_at.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/disk/hdc_esdi_at.c b/src/disk/hdc_esdi_at.c index c08ec636a..e92305476 100644 --- a/src/disk/hdc_esdi_at.c +++ b/src/disk/hdc_esdi_at.c @@ -825,12 +825,12 @@ format_error: esdi->buffer[20] = 2; /* controller type */ esdi->buffer[21] = 1; /* sector buffer size, in sectors */ esdi->buffer[22] = 0; /* ecc bytes appended */ - esdi->buffer[27] = 'W' | ('D' << 8); - esdi->buffer[28] = '1' | ('0' << 8); - esdi->buffer[29] = '0' | ('7' << 8); - esdi->buffer[30] = 'V' | ('-' << 8); - esdi->buffer[31] = 'S' | ('E' << 8); - esdi->buffer[32] = '1'; + esdi->buffer[27] = 'D' | ('W' << 8); + esdi->buffer[28] = '0' | ('1' << 8); + esdi->buffer[29] = '7' | ('0' << 8); + esdi->buffer[30] = '-' | ('V' << 8); + esdi->buffer[31] = 'E' | ('S' << 8); + esdi->buffer[31] = 0 | ('1' << 8); esdi->buffer[47] = 0; /* sectors per interrupt */ esdi->buffer[48] = 0; /* can use double word read/write? */ esdi->pos = 0; From 4297d72a890a3769d0f60d1e4296452d74bdf299 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 24 Dec 2024 19:22:55 +0100 Subject: [PATCH 2/7] AT ESDI: Bring IDENTIFY results in line with the real hardware, closes #5059. --- src/disk/hdc_esdi_at.c | 75 +++++++++++++++++++++++++++++------------- 1 file changed, 53 insertions(+), 22 deletions(-) diff --git a/src/disk/hdc_esdi_at.c b/src/disk/hdc_esdi_at.c index e92305476..7228cba62 100644 --- a/src/disk/hdc_esdi_at.c +++ b/src/disk/hdc_esdi_at.c @@ -552,6 +552,29 @@ esdi_read(uint16_t port, void *priv) return temp; } +/** + * Copy a string into a buffer, padding with spaces, and placing characters as + * if they were packed into 16-bit values, stored little-endian. + * + * @param str Destination buffer + * @param src Source string + * @param len Length of destination buffer to fill in. Strings shorter than + * this length will be padded with spaces. + */ +static void +esdi_padstr(char *str, const char *src, const int len) +{ + int v; + + for (int i = 0; i < len; i++) { + if (*src != '\0') + v = *src++; + else + v = ' '; + str[i ^ 1] = v; + } +} + static void esdi_callback(void *priv) { @@ -811,28 +834,36 @@ format_error: irq_raise(esdi); } else { memset(esdi->buffer, 0x00, 512); - esdi->buffer[0] = 0x44; /* general configuration */ - esdi->buffer[1] = drive->real_tracks; /* number of non-removable cylinders */ - esdi->buffer[2] = 0; /* number of removable cylinders */ - esdi->buffer[3] = drive->real_hpc; /* number of heads */ - esdi->buffer[4] = 600; /* number of unformatted bytes/sector */ - esdi->buffer[5] = esdi->buffer[4] * drive->real_spt; /* number of unformatted bytes/track */ - esdi->buffer[6] = drive->real_spt; /* number of sectors */ - esdi->buffer[7] = 0; /*minimum bytes in inter-sector gap*/ - esdi->buffer[8] = 0; /* minimum bytes in postamble */ - esdi->buffer[9] = 0; /* number of words of vendor status */ - /* controller info */ - esdi->buffer[20] = 2; /* controller type */ - esdi->buffer[21] = 1; /* sector buffer size, in sectors */ - esdi->buffer[22] = 0; /* ecc bytes appended */ - esdi->buffer[27] = 'D' | ('W' << 8); - esdi->buffer[28] = '0' | ('1' << 8); - esdi->buffer[29] = '7' | ('0' << 8); - esdi->buffer[30] = '-' | ('V' << 8); - esdi->buffer[31] = 'E' | ('S' << 8); - esdi->buffer[31] = 0 | ('1' << 8); - esdi->buffer[47] = 0; /* sectors per interrupt */ - esdi->buffer[48] = 0; /* can use double word read/write? */ + esdi->buffer[0] = 0x3244; /* + Soft sectored (0x0004), + Fixed drive (0x0040), + Transfer rate > 5 Mbps but <= 10 Mbps (0x0200), + Data strobe offset option (0x1000), + Track offset option (0x2000). + */ + if (drive->real_spt >= 26) + esdi->buffer[0] |= 0x0008; /* Not MFM encoded. */ + esdi->buffer[1] = drive->real_tracks; /* Fixed cylinders - the BIOS lists 2 less. */ + esdi->buffer[2] = 0; /* Removable cylinders. */ + esdi->buffer[3] = drive->real_hpc; /* Heads. */ + esdi->buffer[5] = 600; /* Unformatted bytes per sector. */ + esdi->buffer[4] = esdi->buffer[5] * drive->real_spt; /* Unformatted bytes per track. */ + esdi->buffer[6] = drive->real_spt; /* Sectors per track - the BIOS lists 1 less. */ + esdi->buffer[7] = 3088; /* Bytes in inter-sector gap. */ + esdi->buffer[8] = 11; /* Byce in sync fileds. */ + esdi->buffer[9] = 0xf; /* Number of vendor unique words. */ + /* Serial Number */ + esdi_padstr((char *) (esdi->buffer + 10), "00000000000000000000", 20); + /* Controller information. */ + esdi->buffer[20] = 3; /* Buffer type. */ + esdi->buffer[21] = 64; /* Buffer size in 512-byte increments. */ + esdi->buffer[22] = 4; /* Bytes of ECC. */ + /* Firmware */ + esdi_padstr((char *) (esdi->buffer + 23), "REV. A5", 8); + /* Model */ + esdi_padstr((char *) (esdi->buffer + 27), "WD1007V", 40); + esdi->buffer[47] = 1; /* Sectors per interrupt. */ + esdi->buffer[48] = 0; /* Can use DWord read/write? */ esdi->pos = 0; esdi->status = STAT_DRQ | STAT_READY | STAT_DSC; irq_raise(esdi); From 8db59e3c5c72294b83c28e238cd8247d44f90b03 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 24 Dec 2024 19:25:00 +0100 Subject: [PATCH 3/7] qt/qt_main.cpp: Use plat_delay_ms(1) instead of thread sleeping, closes #5066. --- src/qt/qt_main.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index 3cce79690..063e1e6c8 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -149,7 +149,12 @@ main_thread_fn() if (dopause) ack_pause(); +#ifdef USE_THREAD_SLEEP std::this_thread::sleep_for(std::chrono::milliseconds(1)); +#else + timeBeginPeriod(1); + plat_delay_ms(1); +#endif } } From 45124363a504a1059cae9c081187a0cfc13e9080 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 24 Dec 2024 19:30:35 +0100 Subject: [PATCH 4/7] Also replace the other thread sleep with play_delay_ms() and remove the #ifdef's. --- src/qt/qt_main.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index 063e1e6c8..1e93f436d 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -149,12 +149,8 @@ main_thread_fn() if (dopause) ack_pause(); -#ifdef USE_THREAD_SLEEP - std::this_thread::sleep_for(std::chrono::milliseconds(1)); -#else timeBeginPeriod(1); plat_delay_ms(1); -#endif } } @@ -162,7 +158,8 @@ main_thread_fn() for (uint8_t i = 1; i < GFXCARD_MAX; i ++) { if (gfxcard[i]) { ui_deinit_monitor(i); - std::this_thread::sleep_for(std::chrono::milliseconds(500)); + timeBeginPeriod(1); + plat_delay_ms(500); } } QTimer::singleShot(0, QApplication::instance(), []() { QApplication::processEvents(); QApplication::instance()->quit(); }); From 59baaaf5a69a66a5945c3e8f6356b3c20cfeb515 Mon Sep 17 00:00:00 2001 From: OBattler Date: Tue, 24 Dec 2024 20:29:44 +0100 Subject: [PATCH 5/7] Only call timerBeginPeriod(1); on Windows, fixes Linux and Mac builds. --- src/qt/qt_main.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index 1e93f436d..9b146ec1f 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -149,7 +149,9 @@ main_thread_fn() if (dopause) ack_pause(); +#ifdef Q_OS_WINDOWS timeBeginPeriod(1); +#endif plat_delay_ms(1); } } @@ -158,7 +160,9 @@ main_thread_fn() for (uint8_t i = 1; i < GFXCARD_MAX; i ++) { if (gfxcard[i]) { ui_deinit_monitor(i); +#ifdef Q_OS_WINDOWS timeBeginPeriod(1); +#endif plat_delay_ms(500); } } From cb957fe5171d227b6143e270acde25cc57dbd1b6 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 25 Dec 2024 00:29:56 +0100 Subject: [PATCH 6/7] Changed to plat_delay_ms() according to tneukom's latest suggestion. --- src/qt/qt_main.cpp | 6 ------ src/qt/qt_ui.cpp | 8 ++++++++ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index 9b146ec1f..3d32a4889 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -149,9 +149,6 @@ main_thread_fn() if (dopause) ack_pause(); -#ifdef Q_OS_WINDOWS - timeBeginPeriod(1); -#endif plat_delay_ms(1); } } @@ -160,9 +157,6 @@ main_thread_fn() for (uint8_t i = 1; i < GFXCARD_MAX; i ++) { if (gfxcard[i]) { ui_deinit_monitor(i); -#ifdef Q_OS_WINDOWS - timeBeginPeriod(1); -#endif plat_delay_ms(500); } } diff --git a/src/qt/qt_ui.cpp b/src/qt/qt_ui.cpp index b24731f55..4f7d9c7ba 100644 --- a/src/qt/qt_ui.cpp +++ b/src/qt/qt_ui.cpp @@ -59,7 +59,15 @@ extern "C" { void plat_delay_ms(uint32_t count) { +#ifdef Q_OS_WINDOWS + // On Win32 the accuracy of Sleep() depends on the timer resolution, which can be set by calling timeBeginPeriod + // https://learn.microsoft.com/en-us/windows/win32/api/timeapi/nf-timeapi-timebeginperiod + timeBeginPeriod(1); + Sleep(count); + timeEndPeriod(1); +#else QThread::msleep(count); +#endif } wchar_t * From e8cb5dc0fe27c90efe80a798e2250bbb66ab7426 Mon Sep 17 00:00:00 2001 From: OBattler Date: Wed, 25 Dec 2024 00:31:20 +0100 Subject: [PATCH 7/7] #include'd <86box/win.h> in qt/qt_ui.cpp. --- src/qt/qt_ui.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/qt/qt_ui.cpp b/src/qt/qt_ui.cpp index 4f7d9c7ba..b9253663b 100644 --- a/src/qt/qt_ui.cpp +++ b/src/qt/qt_ui.cpp @@ -56,6 +56,10 @@ extern "C" { #include <86box/network.h> #include <86box/machine_status.h> +#ifdef Q_OS_WINDOWS +# include <86box/win.h> +#endif + void plat_delay_ms(uint32_t count) {