Files
VGMPLAY.WMF/src_sdcc/build_variants.ps1
T

237 lines
9.5 KiB
PowerShell
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<#
.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