Add OPL4 playback and analyzer support

This commit is contained in:
2026-09-15 14:59:29 +03:00
commit 1686838e03
553 changed files with 50524 additions and 0 deletions
+236
View File
@@ -0,0 +1,236 @@
<#
.SYNOPSIS
Build multiple ISR frequency / command budget variants for A/B testing.
Each variant produces a separate tsconf_*.img disk image.
.DESCRIPTION
Generates inc\variant_cfg.h for each variant, runs build.bat, copies
the output image. Restores the original variant_cfg.h afterward.
NO source files are regex-patched — only variant_cfg.h is overwritten.
.NOTES
C compilation is SLOW (~60 sec per variant). Do NOT interrupt (Ctrl-C).
#>
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
$root = Split-Path -Parent $MyInvocation.MyCommand.Path # src_sdcc
$projRoot = Split-Path -Parent $root # project root
$cfgFile = "$root\inc\variant_cfg.h"
# ── Frequency tiers ──────────────────────────────────────────────────
# ISR_FREQ = 3 500 000 / Step; Entries = 71 680 / Step; TPF = Entries
# Shift = log2(44100 / Freq) rounded down
$freqTiers = @{
'2734' = @{ Tag=''; Freq=2734; Step=1280; Entries=56; Shift=4; Mask='0x0F'; TPF=56; Budgets=@(8,16) }
'1367' = @{ Tag='hf'; Freq=1367; Step=2560; Entries=28; Shift=5; Mask='0x1F'; TPF=28; Budgets=@(8,16,32) }
'683' = @{ Tag='qf'; Freq=683; Step=5120; Entries=14; Shift=6; Mask='0x3F'; TPF=14; Budgets=@(16,32,64) }
}
# ── Generate variants: 2+3+3 = 8 base × 2 NS = 16 total ─────────────
$baseVariants = @()
foreach ($ft in $freqTiers.Values | Sort-Object Freq -Descending) {
foreach ($b in $ft.Budgets) {
$suffix = if ($ft.Tag) { "_$($ft.Tag)" } else { '' }
$name = "b${b}${suffix}"
$baseVariants += @{
Name = $name
Budget = $b
Entries = $ft.Entries
Step = $ft.Step
Freq = $ft.Freq
Shift = $ft.Shift
Mask = $ft.Mask
TPF = $ft.TPF
DataLoc = '0xB600'
NS = $false
}
}
}
# Auto-generate _ns (no short waits) clones
$nsVariants = foreach ($bv in $baseVariants) {
$nv = $bv.Clone()
$nv.Name = $bv.Name + '_ns'
$nv.NS = $true
$nv
}
$variants = $baseVariants + $nsVariants
# ── Save original variant_cfg.h ─────────────────────────────────────
$cfgBackup = Get-Content $cfgFile -Raw
function Restore-Cfg {
Set-Content $script:cfgFile -Value $script:cfgBackup -NoNewline
}
# ── Helper: generate variant_cfg.h ──────────────────────────────────
function Write-VariantCfg($v) {
$nsLine = if ($v.NS) { "#define VGM_NO_SHORT_WAITS" } else { "/* #define VGM_NO_SHORT_WAITS */" }
$content = @"
/* variant_cfg.h -- AUTO-GENERATED by build_variants.ps1
* Variant: $($v.Name) Freq=$($v.Freq)Hz Budget=$($v.Budget) NS=$($v.NS)
*/
#ifndef VARIANT_CFG_H
#define VARIANT_CFG_H
#define ISR_FREQ $($v.Freq)
#define ISR_TICKS_PER_FRAME $($v.TPF)
#define VGM_SAMPLE_SHIFT $($v.Shift)
#define VGM_SAMPLE_MASK $($v.Mask)
#define VGM_FILL_CMD_BUDGET $($v.Budget)
#define VARIANT_POS_ENTRIES $($v.Entries)
#define VARIANT_POS_STEP $($v.Step)
#define VARIANT_DATA_LOC $($v.DataLoc)
$nsLine
#endif /* VARIANT_CFG_H */
"@
Set-Content $script:cfgFile -Value $content -NoNewline
}
# ── Output directory ─────────────────────────────────────────────────
$outDir = "$projRoot\variants"
if (-not (Test-Path $outDir)) { New-Item -ItemType Directory -Path $outDir | Out-Null }
# ── Build loop ──────────────────────────────────────────────────────
$total = $variants.Count
$idx = 0
$results = @()
foreach ($v in $variants) {
$idx++
$name = $v.Name
Write-Host "`n========== [$idx/$total] Building $name ==========" -ForegroundColor Cyan
Write-Host " Budget=$($v.Budget) Freq=$($v.Freq)Hz Entries=$($v.Entries) Step=$($v.Step) Shift=$($v.Shift) TPF=$($v.TPF) NS=$($v.NS)"
# --- Generate variant_cfg.h ---
Write-VariantCfg $v
# --- Clean .rel files to force recompile ---
Remove-Item "$root\build\*.rel" -ErrorAction SilentlyContinue
# --- Run build ---
Write-Host " Building... (this takes ~60 sec)" -ForegroundColor Yellow
$buildOut = cmd /c "cd /d $root && build.bat 2>&1"
$buildOk = $buildOut | Where-Object { $_ -match 'BUILD OK' }
$buildFail = $buildOut | Where-Object { $_ -match 'FAIL|ERROR|overflow' }
if ($buildFail -or -not $buildOk) {
Write-Host " *** BUILD FAILED for $name ***" -ForegroundColor Red
$buildOut | Where-Object { $_ -match 'FAIL|error|warning|_CODE|_DATA|Last byte|overflow|variant_cfg' } |
ForEach-Object { Write-Host " $_" }
$results += [pscustomobject]@{ Name=$name; Status='FAIL'; Code=0; Free=0 }
continue
}
# --- Extract sizes from output ---
$codeLine = $buildOut | Where-Object { $_ -match '_CODE' } | Select-Object -First 1
$freeLine = $buildOut | Where-Object { $_ -match 'Free before' } | Select-Object -First 1
$codeSize = if ($codeLine -match '(\d+)\s+bytes') { [int]$Matches[1] } else { 0 }
$freeSize = if ($freeLine -match 'Free before C000:\s*(\d+)') { [int]$Matches[1] } else { 0 }
# --- Show map ---
$buildOut | Where-Object { $_ -match 'variant_cfg:|Section|_CODE|_DATA|_GSINIT|_HOME|_INITIAL|Last byte|Code:|Written.*WMF' } |
ForEach-Object { Write-Host " $_" }
# --- Copy output image ---
$srcImg = "$projRoot\tsconf.img"
$dstImg = "$outDir\tsconf_$name.img"
if (Test-Path $srcImg) {
Copy-Item $srcImg $dstImg -Force
Write-Host " -> $dstImg" -ForegroundColor Green
} else {
Write-Host " WARNING: tsconf.img not found" -ForegroundColor Yellow
}
# Also copy WMF
$srcWmf = "$projRoot\DiskRef\WC\VGMPLAY.WMF"
$dstWmf = "$outDir\VGMPLAY_$name.WMF"
if (Test-Path $srcWmf) {
Copy-Item $srcWmf $dstWmf -Force
}
$results += [pscustomobject]@{ Name=$name; Status='OK'; Code=$codeSize; Free=$freeSize }
}
# ── Restore original variant_cfg.h ──────────────────────────────────
Write-Host "`n========== Restoring original variant_cfg.h ==========" -ForegroundColor Cyan
Restore-Cfg
# Rebuild baseline to leave workspace clean
Remove-Item "$root\build\*.rel" -ErrorAction SilentlyContinue
Write-Host " Rebuilding baseline..." -ForegroundColor Yellow
$null = cmd /c "cd /d $root && build.bat 2>&1"
Write-Host " Done." -ForegroundColor Green
# ── Summary ──────────────────────────────────────────────────────────
Write-Host "`n========== VARIANT SUMMARY ==========" -ForegroundColor Cyan
$fmt = "{0,-18} {1,6} {2,6} {3,6} {4,3} {5,5} {6,5}"
Write-Host ($fmt -f 'Name','Budget','Freq','Code','NS','Free','St')
Write-Host ($fmt -f '----','------','----','----','--','----','--')
foreach ($r in $results) {
$v = $variants | Where-Object { $_.Name -eq $r.Name }
$nsTag = if ($v.NS) { 'yes' } else { ' - ' }
$color = if ($r.Status -eq 'OK') { 'Green' } else { 'Red' }
Write-Host ($fmt -f $r.Name, $v.Budget, $v.Freq, $r.Code, $nsTag, $r.Free, $r.Status) -ForegroundColor $color
}
Write-Host "`nImages in: $outDir"
# ── Generate README.txt ──────────────────────────────────────────────
$readme = @"
Variants of VGM player for A/B testing
=======================================
Parameters stored in inc\variant_cfg.h (single config file).
build_variants.ps1 regenerates variant_cfg.h for each variant.
Frequency tiers:
qf - quarter freq (ISR 683 Hz, step 5120, 14 ticks/frame)
(none) - base freq (ISR 2734 Hz, step 1280, 56 ticks/frame)
hf - half freq (ISR 1367 Hz, step 2560, 28 ticks/frame)
Other tags:
b<N> - command budget (max commands between forced pauses)
ns - no short waits (0x70-0x7F pauses skipped)
"@
$readme += "{0,-30} {1,6} {2,8} {3,3} {4,6} {5,5} {6}`n" -f 'Image','Budget','Freq','NS','Code','Free','Status'
$readme += "{0,-30} {1,6} {2,8} {3,3} {4,6} {5,5} {6}`n" -f '-----','------','----','--','----','----','------'
foreach ($r in $results) {
$v = $variants | Where-Object { $_.Name -eq $r.Name }
$nsTag = if ($v.NS) { 'yes' } else { ' - ' }
$freq = "$($v.Freq)Hz"
$readme += "{0,-30} {1,6} {2,8} {3,3} {4,6} {5,5} {6}`n" -f "tsconf_$($r.Name).img", $v.Budget, $freq, $nsTag, $r.Code, $r.Free, $r.Status
}
$readme += @"
What to test
------------
1. Higher budget helps (b32/b48/b64 vs b8/b16)
-> Increase VGM_FILL_CMD_BUDGET.
2. Lower freq helps (hf or qf better than base)
-> ISR overhead is the bottleneck, reduce frequency.
3. Higher freq helps (base better than hf/qf)
-> More granular timing needed, keep higher ISR.
4. _ns variants better -> short waits 0x70-0x7F are the problem.
5. Nothing helps -> something else (OPL3 write delay, VGM parsing, etc.)
"@
Set-Content "$outDir\README.txt" -Value $readme -NoNewline -Encoding UTF8
Write-Host "`nREADME.txt written to $outDir" -ForegroundColor Green
Write-Host "`nLegend:" -ForegroundColor DarkGray
Write-Host " qf = quarter freq (683 Hz)" -ForegroundColor DarkGray
Write-Host " hf = half freq (1367 Hz)" -ForegroundColor DarkGray
Write-Host " (no suffix) = base freq (2734 Hz)" -ForegroundColor DarkGray
Write-Host " bN = budget N commands per ISR tick" -ForegroundColor DarkGray
Write-Host " ns = no short waits (0x70-0x7F skipped)" -ForegroundColor DarkGray