From cd14815f9b7d6fd9f168bf3ea333a9e3310a808b Mon Sep 17 00:00:00 2001 From: bubio Date: Sat, 14 Mar 2026 09:02:45 +0900 Subject: [PATCH 1/4] Fix Wizardry boot failure by correcting FDC timing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix seek timing: multiply step rate by 1000 to convert msec to usec (was 1000x too fast, matching BubiC-8801MA reference implementation) - Use constant 100µs exec-phase delay in SDL mode instead of rotational-position-based calculation (SDL event system lacks sufficient precision for position tracking) - Disable TC acceptance during PHASE_EXEC in 8MHz mode to prevent premature read termination (Xanadu compat hack only for 4MHz) - Reduce DATA LOST timeout from 30ms to 15ms for tighter DRQ handling - Widen single_exec parameters for 8MHz mode (slice: 4→20 clocks, timeout: 10ms→20ms) so the CPU can complete instructions and handle FDC interrupts reliably at double clock speed Co-Authored-By: Claude Opus 4.6 (1M context) --- Source/ePC-8801MA/vm/event.cpp | 26 ++++++++++++++++++-------- Source/ePC-8801MA/vm/upd765a.cpp | 20 +++++++++++++++----- 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/Source/ePC-8801MA/vm/event.cpp b/Source/ePC-8801MA/vm/event.cpp index 547551a..bbfddd9 100644 --- a/Source/ePC-8801MA/vm/event.cpp +++ b/Source/ePC-8801MA/vm/event.cpp @@ -17,6 +17,12 @@ #ifdef SDL #define SINGLE_EXEC_TIMEOUT 10000 // exit single exec mode (us) +#define SINGLE_EXEC_TIMEOUT_8MHZ 20000 + // 8MHz mode needs wider window for stable FDC timing +#define SINGLE_EXEC_SLICE 4 + // max clocks per single-exec step +#define SINGLE_EXEC_SLICE_8MHZ 20 + // 8MHz mode needs larger slice for CPU to keep up #endif // SDL void EVENT::initialize() @@ -145,8 +151,9 @@ void EVENT::drive() { #ifdef SDL if (single_exec == true) { - // if passed 10ms, disable single_exec - if (passed_usec(single_exec_clock) > SINGLE_EXEC_TIMEOUT) { + // if passed timeout, disable single_exec + int timeout = (config.cpu_type == 0) ? SINGLE_EXEC_TIMEOUT_8MHZ : SINGLE_EXEC_TIMEOUT; + if (passed_usec(single_exec_clock) > timeout) { single_exec = false; } } @@ -244,8 +251,9 @@ void EVENT::drive() if (main_cpu_exec > 0) { // single execution ? if (single_exec == true) { - if (main_cpu_exec > 4) { - main_cpu_exec = 4; + int slice = (config.cpu_type == 0) ? SINGLE_EXEC_SLICE_8MHZ : SINGLE_EXEC_SLICE; + if (main_cpu_exec > slice) { + main_cpu_exec = slice; } } cpu_done = d_cpu[0].device->run(main_cpu_exec); @@ -263,8 +271,9 @@ void EVENT::drive() if (cpu_remain > 0) { sub_cpu_exec = cpu_remain; if (single_exec == true) { - if (sub_cpu_exec > 4) { - sub_cpu_exec = 4; + int slice = (config.cpu_type == 0) ? SINGLE_EXEC_SLICE_8MHZ : SINGLE_EXEC_SLICE; + if (sub_cpu_exec > slice) { + sub_cpu_exec = slice; } } @@ -277,8 +286,9 @@ void EVENT::drive() if (cpu_remain > 2) { sub_cpu_exec = cpu_remain / 2; if (single_exec == true) { - if (sub_cpu_exec > 4) { - sub_cpu_exec = 4; + int slice = (config.cpu_type == 0) ? SINGLE_EXEC_SLICE_8MHZ : SINGLE_EXEC_SLICE; + if (sub_cpu_exec > slice) { + sub_cpu_exec = slice; } } diff --git a/Source/ePC-8801MA/vm/upd765a.cpp b/Source/ePC-8801MA/vm/upd765a.cpp index 8811cf0..1273a9c 100644 --- a/Source/ePC-8801MA/vm/upd765a.cpp +++ b/Source/ePC-8801MA/vm/upd765a.cpp @@ -400,7 +400,9 @@ void UPD765A::write_signal(int id, uint32 data, uint32 mask) } else if(id == SIG_UPD765A_TC) { #ifdef SDL // phase==PHASE_EXEC support (for Xanadu Scenario II) - if(phase == PHASE_READ || phase == PHASE_WRITE || phase == PHASE_SCAN || (phase == PHASE_RESULT && count == 7) || (phase == PHASE_EXEC)) { + // but disable for 8MHz mode where it destabilizes Wizardry boot + bool tc_accept_exec = (config.cpu_type != 0); + if(phase == PHASE_READ || phase == PHASE_WRITE || phase == PHASE_SCAN || (phase == PHASE_RESULT && count == 7) || (tc_accept_exec && phase == PHASE_EXEC)) { #else if(phase == PHASE_READ || phase == PHASE_WRITE || phase == PHASE_SCAN || (phase == PHASE_RESULT && count == 7)) { #endif // SDL @@ -518,7 +520,7 @@ void UPD765A::set_drq(bool val) if((command & 0x1f) != 0x0d) { #ifdef SDL // for customized event manager + 2HD disk - register_event(this, EVENT_LOST, 30000, false, &lost_id); + register_event(this, EVENT_LOST, 15000, false, &lost_id); #else register_event(this, EVENT_LOST, disk[hdu & DRIVE_MASK]->get_usec_per_bytes(1), false, &lost_id); #endif // SDL @@ -684,8 +686,8 @@ void UPD765A::cmd_recalib() void UPD765A::seek(int drv, int trk) { - // get distance - int seektime = 32 - 2 * step_rate_time; + // get distance (step rate is in msec units, convert to usec) + int seektime = (32 - 2 * step_rate_time) * 1000; // msec -> usec if(disk[drv]->drive_type == DRIVE_TYPE_2HD) { seektime /= 2; } @@ -1466,7 +1468,15 @@ double UPD765A::get_usec_to_exec_phase() int drv = hdu & DRIVE_MASK; int trk = fdc[drv].track; int side = (hdu >> 2) & 1; - + +#ifdef SDL + // Use constant exec-phase delay for SDL mode. + // The SDL event system's position tracking is not precise enough + // for rotational-position-based timing, which causes timing-sensitive + // titles (e.g. Wizardry) to fail during boot. + return 100; +#endif + // XXX: this is a standard image and skew may be incorrect if(disk[drv]->is_standard_image) { return 100; From 5f23a34e4bb7fce4450c4228a6a4aa3df436ed8c Mon Sep 17 00:00:00 2001 From: bubio Date: Sat, 14 Mar 2026 09:41:56 +0900 Subject: [PATCH 2/4] Unify version management via CMake configure_file() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generate version.h from CMakeLists.txt so app.cpp no longer needs a hard-coded APP_VER. Also fix stale version strings in XM8.rc (1.7.5→1.7.7) and README.md download URLs (1.7.6→1.7.7). Co-Authored-By: Claude Opus 4.6 (1M context) --- Builder/Windows/XM8.rc | 4 ++-- CMakeLists.txt | 7 +++++++ README.md | 4 ++-- Source/UI/app.cpp | 3 +-- Source/ePC-8801MA/version.h.in | 5 +++++ 5 files changed, 17 insertions(+), 6 deletions(-) create mode 100644 Source/ePC-8801MA/version.h.in diff --git a/Builder/Windows/XM8.rc b/Builder/Windows/XM8.rc index 10cf20f..809cca0 100644 --- a/Builder/Windows/XM8.rc +++ b/Builder/Windows/XM8.rc @@ -36,12 +36,12 @@ BEGIN BEGIN VALUE "CompanyName", "\0" VALUE "FileDescription", "PC-8801MA EMULATOR XM8\0" - VALUE "FileVersion", "1.7.5.0\0" + VALUE "FileVersion", "1.7.7.0\0" VALUE "InternalName", "XM8.exe" VALUE "LegalCopyright", "Copyright (C) 2015-2018 �o�h�D" VALUE "OriginalFilename", "XM8.exe" VALUE "ProductName", "XM8" - VALUE "ProductVersion", "1.7.5.0\0" + VALUE "ProductVersion", "1.7.7.0\0" END END BLOCK "VarFileInfo" diff --git a/CMakeLists.txt b/CMakeLists.txt index 62a6b3d..415f91f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,6 +37,13 @@ set(PROJECT_VERSION 1.7.7) # Project Name project(XM8 VERSION ${PROJECT_VERSION}) +configure_file( + ${CMAKE_SOURCE_DIR}/Source/ePC-8801MA/version.h.in + ${CMAKE_BINARY_DIR}/generated/version.h + @ONLY +) +include_directories(${CMAKE_BINARY_DIR}/generated) + # Packaging options option(MACOSX_STANDALONE_APP_BUNDLE "Generate a portable app bundle to use on other devices (requires sudo)" OFF) diff --git a/README.md b/README.md index c8e53c5..6cef3e5 100644 --- a/README.md +++ b/README.md @@ -37,8 +37,8 @@ http://retropc.net/pi/xm8/index.html | CPU | 最小OSバージョン | 実行ファイル | | ------------- | ------------------- | ------------------------------------------------------------ | -| x86_64 | macOS 10.13 High Sierra | [x86_64版](https://github.com/bubio/xm8mac/releases/download/1.7.6/XM8_macOS_Universal.dmg) | -| Apple Silicon | macOS 11 Big Sur | [Apple Silicon版](https://github.com/bubio/xm8mac/releases/download/1.7.6/XM8_macOS_Universal.dmg) | +| x86_64 | macOS 10.13 High Sierra | [x86_64版](https://github.com/bubio/xm8mac/releases/download/1.7.7/XM8_macOS_Universal.dmg) | +| Apple Silicon | macOS 11 Big Sur | [Apple Silicon版](https://github.com/bubio/xm8mac/releases/download/1.7.7/XM8_macOS_Universal.dmg) |
diff --git a/Source/UI/app.cpp b/Source/UI/app.cpp index 762d1ec..8175a7f 100644 --- a/Source/UI/app.cpp +++ b/Source/UI/app.cpp @@ -41,8 +41,7 @@ // #define APP_NAME "XM8 (based on ePC-8801MA)"; // application name -#define APP_VER 0x0177 - // version (BCD) +#include "version.h" #define APP_WIDTH SCREEN_WIDTH // window width #define APP_HEIGHT_TRANSPARENT SCREEN_HEIGHT diff --git a/Source/ePC-8801MA/version.h.in b/Source/ePC-8801MA/version.h.in new file mode 100644 index 0000000..89844a1 --- /dev/null +++ b/Source/ePC-8801MA/version.h.in @@ -0,0 +1,5 @@ +// Auto-generated from CMakeLists.txt — do not edit +#define APP_VER_MAJOR @PROJECT_VERSION_MAJOR@ +#define APP_VER_MINOR @PROJECT_VERSION_MINOR@ +#define APP_VER_PATCH @PROJECT_VERSION_PATCH@ +#define APP_VER ((APP_VER_MAJOR << 8) | (APP_VER_MINOR << 4) | APP_VER_PATCH) From 726141e1ad9379eb78b0d32ffb2868a5ef120443 Mon Sep 17 00:00:00 2001 From: bubio Date: Sat, 14 Mar 2026 17:29:48 +0900 Subject: [PATCH 3/4] Revert "Unify version management via CMake configure_file()" This reverts commit 5f23a34e4bb7fce4450c4228a6a4aa3df436ed8c. --- Builder/Windows/XM8.rc | 4 ++-- CMakeLists.txt | 7 ------- README.md | 4 ++-- Source/UI/app.cpp | 3 ++- Source/ePC-8801MA/version.h.in | 5 ----- 5 files changed, 6 insertions(+), 17 deletions(-) delete mode 100644 Source/ePC-8801MA/version.h.in diff --git a/Builder/Windows/XM8.rc b/Builder/Windows/XM8.rc index 809cca0..10cf20f 100644 --- a/Builder/Windows/XM8.rc +++ b/Builder/Windows/XM8.rc @@ -36,12 +36,12 @@ BEGIN BEGIN VALUE "CompanyName", "\0" VALUE "FileDescription", "PC-8801MA EMULATOR XM8\0" - VALUE "FileVersion", "1.7.7.0\0" + VALUE "FileVersion", "1.7.5.0\0" VALUE "InternalName", "XM8.exe" VALUE "LegalCopyright", "Copyright (C) 2015-2018 �o�h�D" VALUE "OriginalFilename", "XM8.exe" VALUE "ProductName", "XM8" - VALUE "ProductVersion", "1.7.7.0\0" + VALUE "ProductVersion", "1.7.5.0\0" END END BLOCK "VarFileInfo" diff --git a/CMakeLists.txt b/CMakeLists.txt index 415f91f..62a6b3d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,13 +37,6 @@ set(PROJECT_VERSION 1.7.7) # Project Name project(XM8 VERSION ${PROJECT_VERSION}) -configure_file( - ${CMAKE_SOURCE_DIR}/Source/ePC-8801MA/version.h.in - ${CMAKE_BINARY_DIR}/generated/version.h - @ONLY -) -include_directories(${CMAKE_BINARY_DIR}/generated) - # Packaging options option(MACOSX_STANDALONE_APP_BUNDLE "Generate a portable app bundle to use on other devices (requires sudo)" OFF) diff --git a/README.md b/README.md index 6cef3e5..c8e53c5 100644 --- a/README.md +++ b/README.md @@ -37,8 +37,8 @@ http://retropc.net/pi/xm8/index.html | CPU | 最小OSバージョン | 実行ファイル | | ------------- | ------------------- | ------------------------------------------------------------ | -| x86_64 | macOS 10.13 High Sierra | [x86_64版](https://github.com/bubio/xm8mac/releases/download/1.7.7/XM8_macOS_Universal.dmg) | -| Apple Silicon | macOS 11 Big Sur | [Apple Silicon版](https://github.com/bubio/xm8mac/releases/download/1.7.7/XM8_macOS_Universal.dmg) | +| x86_64 | macOS 10.13 High Sierra | [x86_64版](https://github.com/bubio/xm8mac/releases/download/1.7.6/XM8_macOS_Universal.dmg) | +| Apple Silicon | macOS 11 Big Sur | [Apple Silicon版](https://github.com/bubio/xm8mac/releases/download/1.7.6/XM8_macOS_Universal.dmg) |
diff --git a/Source/UI/app.cpp b/Source/UI/app.cpp index 8175a7f..762d1ec 100644 --- a/Source/UI/app.cpp +++ b/Source/UI/app.cpp @@ -41,7 +41,8 @@ // #define APP_NAME "XM8 (based on ePC-8801MA)"; // application name -#include "version.h" +#define APP_VER 0x0177 + // version (BCD) #define APP_WIDTH SCREEN_WIDTH // window width #define APP_HEIGHT_TRANSPARENT SCREEN_HEIGHT diff --git a/Source/ePC-8801MA/version.h.in b/Source/ePC-8801MA/version.h.in deleted file mode 100644 index 89844a1..0000000 --- a/Source/ePC-8801MA/version.h.in +++ /dev/null @@ -1,5 +0,0 @@ -// Auto-generated from CMakeLists.txt — do not edit -#define APP_VER_MAJOR @PROJECT_VERSION_MAJOR@ -#define APP_VER_MINOR @PROJECT_VERSION_MINOR@ -#define APP_VER_PATCH @PROJECT_VERSION_PATCH@ -#define APP_VER ((APP_VER_MAJOR << 8) | (APP_VER_MINOR << 4) | APP_VER_PATCH) From 2dde981d186b9bc316091e58bd537ba39f04acb7 Mon Sep 17 00:00:00 2001 From: bubio Date: Sat, 14 Mar 2026 17:36:53 +0900 Subject: [PATCH 4/4] =?UTF-8?q?=E3=83=90=E3=83=BC=E3=82=B8=E3=83=A7?= =?UTF-8?q?=E3=83=B3=E6=9B=B4=E6=96=B0=E3=80=82=E3=83=90=E3=83=BC=E3=82=B8?= =?UTF-8?q?=E3=83=A7=E3=83=B3=E6=9B=B4=E6=96=B0=E7=94=A8=E3=82=B9=E3=82=AF?= =?UTF-8?q?=E3=83=AA=E3=83=97=E3=83=88=E8=BF=BD=E5=8A=A0=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Builder/Android/app/build.gradle | 2 +- .../Android/app/src/main/AndroidManifest.xml | 2 +- Builder/Windows/XM8.rc | 4 +- README.md | 4 +- scripts/update_version.ps1 | 88 +++++++++++++++++++ scripts/update_version.sh | 77 ++++++++++++++++ 6 files changed, 171 insertions(+), 6 deletions(-) create mode 100644 scripts/update_version.ps1 create mode 100755 scripts/update_version.sh diff --git a/Builder/Android/app/build.gradle b/Builder/Android/app/build.gradle index 6bf0c8e..e05ac46 100644 --- a/Builder/Android/app/build.gradle +++ b/Builder/Android/app/build.gradle @@ -20,7 +20,7 @@ android { minSdk 19 targetSdk 35 versionCode 4 - versionName "1.75" + versionName "1.77" testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' externalNativeBuild { ndkBuild { diff --git a/Builder/Android/app/src/main/AndroidManifest.xml b/Builder/Android/app/src/main/AndroidManifest.xml index 0e3499a..8ee436d 100644 --- a/Builder/Android/app/src/main/AndroidManifest.xml +++ b/Builder/Android/app/src/main/AndroidManifest.xml @@ -1,7 +1,7 @@ diff --git a/Builder/Windows/XM8.rc b/Builder/Windows/XM8.rc index 10cf20f..809cca0 100644 --- a/Builder/Windows/XM8.rc +++ b/Builder/Windows/XM8.rc @@ -36,12 +36,12 @@ BEGIN BEGIN VALUE "CompanyName", "\0" VALUE "FileDescription", "PC-8801MA EMULATOR XM8\0" - VALUE "FileVersion", "1.7.5.0\0" + VALUE "FileVersion", "1.7.7.0\0" VALUE "InternalName", "XM8.exe" VALUE "LegalCopyright", "Copyright (C) 2015-2018 �o�h�D" VALUE "OriginalFilename", "XM8.exe" VALUE "ProductName", "XM8" - VALUE "ProductVersion", "1.7.5.0\0" + VALUE "ProductVersion", "1.7.7.0\0" END END BLOCK "VarFileInfo" diff --git a/README.md b/README.md index c8e53c5..6cef3e5 100644 --- a/README.md +++ b/README.md @@ -37,8 +37,8 @@ http://retropc.net/pi/xm8/index.html | CPU | 最小OSバージョン | 実行ファイル | | ------------- | ------------------- | ------------------------------------------------------------ | -| x86_64 | macOS 10.13 High Sierra | [x86_64版](https://github.com/bubio/xm8mac/releases/download/1.7.6/XM8_macOS_Universal.dmg) | -| Apple Silicon | macOS 11 Big Sur | [Apple Silicon版](https://github.com/bubio/xm8mac/releases/download/1.7.6/XM8_macOS_Universal.dmg) | +| x86_64 | macOS 10.13 High Sierra | [x86_64版](https://github.com/bubio/xm8mac/releases/download/1.7.7/XM8_macOS_Universal.dmg) | +| Apple Silicon | macOS 11 Big Sur | [Apple Silicon版](https://github.com/bubio/xm8mac/releases/download/1.7.7/XM8_macOS_Universal.dmg) |
diff --git a/scripts/update_version.ps1 b/scripts/update_version.ps1 new file mode 100644 index 0000000..805fac0 --- /dev/null +++ b/scripts/update_version.ps1 @@ -0,0 +1,88 @@ +# +# Update version number across all build systems. +# +# Usage: .\scripts\update_version.ps1 +# Example: .\scripts\update_version.ps1 1 7 8 +# + +param( + [Parameter(Mandatory)][int]$Major, + [Parameter(Mandatory)][int]$Minor, + [Parameter(Mandatory)][int]$Patch +) + +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' + +if ($Major -lt 0 -or $Major -gt 9 -or $Minor -lt 0 -or $Minor -gt 9 -or $Patch -lt 0 -or $Patch -gt 9) { + Write-Error "major, minor, patch must each be a single digit (0-9)" + exit 1 +} + +$RootDir = Split-Path -Parent (Split-Path -Parent $MyInvocation.MyCommand.Path) + +$VerDot = "$Major.$Minor.$Patch" +$VerBCD = '0x{0:X2}{1:X}{2:X}' -f $Major, $Minor, $Patch +$VerAndroid = "$Major.$Minor$Patch" + +Write-Host "Updating version to $VerDot (BCD: $VerBCD, Android: $VerAndroid)" + +# Helper: read file, replace, write back (preserving encoding) +function Replace-InFile { + param([string]$Path, [string]$Pattern, [string]$Replacement) + $content = [System.IO.File]::ReadAllText($Path) + $newContent = [regex]::Replace($content, $Pattern, $Replacement) + if ($content -eq $newContent) { + Write-Warning "No match for pattern in $Path" + } + [System.IO.File]::WriteAllText($Path, $newContent) +} + +# 1. CMakeLists.txt +Replace-InFile "$RootDir\CMakeLists.txt" ` + '(?m)^(set\(PROJECT_VERSION )\d+\.\d+\.\d+\)' ` + "`${1}$VerDot)" + +# 2. Source/UI/app.cpp +Replace-InFile "$RootDir\Source\UI\app.cpp" ` + '(?m)^(#define APP_VER\s+)0x[0-9A-Fa-f]+' ` + "`${1}$VerBCD" + +# 3. Builder/Windows/XM8.rc — numeric versions +Replace-InFile "$RootDir\Builder\Windows\XM8.rc" ` + '(?m)^(FILEVERSION\s+)\d+,\d+,\d+,\d+' ` + "`${1}$Major,$Minor,$Patch,0" +Replace-InFile "$RootDir\Builder\Windows\XM8.rc" ` + '(?m)^(PRODUCTVERSION\s+)\d+,\d+,\d+,\d+' ` + "`${1}$Major,$Minor,$Patch,0" + +# 3b. XM8.rc — string versions +Replace-InFile "$RootDir\Builder\Windows\XM8.rc" ` + '(VALUE "FileVersion",\s+")\d+\.\d+\.\d+\.\d+' ` + "`${1}$VerDot.0" +Replace-InFile "$RootDir\Builder\Windows\XM8.rc" ` + '(VALUE "ProductVersion",\s+")\d+\.\d+\.\d+\.\d+' ` + "`${1}$VerDot.0" + +# 4. build.gradle +Replace-InFile "$RootDir\Builder\Android\app\build.gradle" ` + '(versionName ")\d+\.\d+"' ` + "`${1}$VerAndroid`"" + +# 5. AndroidManifest.xml +Replace-InFile "$RootDir\Builder\Android\app\src\main\AndroidManifest.xml" ` + '(android:versionName=")\d+\.\d+"' ` + "`${1}$VerAndroid`"" + +# 6. README.md +Replace-InFile "$RootDir\README.md" ` + '(releases/download/)\d+\.\d+\.\d+/' ` + "`${1}$VerDot/" + +Write-Host "Done. Updated files:" +Write-Host " CMakeLists.txt" +Write-Host " Source\UI\app.cpp" +Write-Host " Builder\Windows\XM8.rc" +Write-Host " Builder\Android\app\build.gradle" +Write-Host " Builder\Android\app\src\main\AndroidManifest.xml" +Write-Host " README.md" diff --git a/scripts/update_version.sh b/scripts/update_version.sh new file mode 100755 index 0000000..e6223f1 --- /dev/null +++ b/scripts/update_version.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +# +# Update version number across all build systems. +# +# Usage: ./scripts/update_version.sh +# Example: ./scripts/update_version.sh 1 7 8 +# + +set -euo pipefail + +if [ $# -ne 3 ]; then + echo "Usage: $0 " + echo "Example: $0 1 7 8" + exit 1 +fi + +MAJOR=$1 +MINOR=$2 +PATCH=$3 + +# Validate: single digits only (BCD constraint) +if ! [[ "$MAJOR" =~ ^[0-9]$ && "$MINOR" =~ ^[0-9]$ && "$PATCH" =~ ^[0-9]$ ]]; then + echo "Error: major, minor, patch must each be a single digit (0-9)" + exit 1 +fi + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" + +VER_DOT="${MAJOR}.${MINOR}.${PATCH}" +VER_BCD=$(printf "0x%02X%X%X" "$MAJOR" "$MINOR" "$PATCH") +VER_ANDROID="${MAJOR}.${MINOR}${PATCH}" + +echo "Updating version to ${VER_DOT} (BCD: ${VER_BCD}, Android: ${VER_ANDROID})" + +# 1. CMakeLists.txt — set(PROJECT_VERSION X.Y.Z) +sed -i.bak -E "s/^(set\(PROJECT_VERSION )[0-9]+\.[0-9]+\.[0-9]+\)/\1${VER_DOT})/" \ + "$ROOT_DIR/CMakeLists.txt" + +# 2. Source/UI/app.cpp — #define APP_VER 0xXYZ +sed -i.bak -E "s/^(#define APP_VER[[:space:]]+)0x[0-9A-Fa-f]+/\1${VER_BCD}/" \ + "$ROOT_DIR/Source/UI/app.cpp" + +# 3. Builder/Windows/XM8.rc — FILEVERSION / PRODUCTVERSION (numeric) +sed -i.bak -E "s/^(FILEVERSION[[:space:]]+)[0-9]+,[0-9]+,[0-9]+,[0-9]+/\1${MAJOR},${MINOR},${PATCH},0/" \ + "$ROOT_DIR/Builder/Windows/XM8.rc" +sed -i.bak -E "s/^(PRODUCTVERSION[[:space:]]+)[0-9]+,[0-9]+,[0-9]+,[0-9]+/\1${MAJOR},${MINOR},${PATCH},0/" \ + "$ROOT_DIR/Builder/Windows/XM8.rc" + +# 3b. XM8.rc — FileVersion / ProductVersion (string) +sed -i.bak -E "s/(VALUE \"FileVersion\",[[:space:]]+\")[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/\1${VER_DOT}.0/" \ + "$ROOT_DIR/Builder/Windows/XM8.rc" +sed -i.bak -E "s/(VALUE \"ProductVersion\",[[:space:]]+\")[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/\1${VER_DOT}.0/" \ + "$ROOT_DIR/Builder/Windows/XM8.rc" + +# 4. Builder/Android/app/build.gradle — versionName +sed -i.bak -E "s/(versionName \")[0-9]+\.[0-9]+\"/\1${VER_ANDROID}\"/" \ + "$ROOT_DIR/Builder/Android/app/build.gradle" + +# 5. Builder/Android/app/src/main/AndroidManifest.xml — android:versionName +sed -i.bak -E "s/(android:versionName=\")[0-9]+\.[0-9]+\"/\1${VER_ANDROID}\"/" \ + "$ROOT_DIR/Builder/Android/app/src/main/AndroidManifest.xml" + +# 6. README.md — download URL version +sed -i.bak -E "s|(releases/download/)[0-9]+\.[0-9]+\.[0-9]+/|\1${VER_DOT}/|g" \ + "$ROOT_DIR/README.md" + +# Clean up .bak files +find "$ROOT_DIR" -name "*.bak" -newer "$0" -delete 2>/dev/null || true + +echo "Done. Updated files:" +echo " CMakeLists.txt" +echo " Source/UI/app.cpp" +echo " Builder/Windows/XM8.rc" +echo " Builder/Android/app/build.gradle" +echo " Builder/Android/app/src/main/AndroidManifest.xml" +echo " README.md"