diff --git a/content/LAST.EGG b/content/LAST.EGG index d6f71cb..61255bd 100644 --- a/content/LAST.EGG +++ b/content/LAST.EGG @@ -168,7 +168,7 @@ badge=VGL patch=Yellow role=Role::Default dropzone=one -vehicle=madcat +vehicle=bhk1 vehicleValue=1000 color=White [largebitmap] diff --git a/game/reconstructed/heat.cpp b/game/reconstructed/heat.cpp index 5f02431..4736764 100644 --- a/game/reconstructed/heat.cpp +++ b/game/reconstructed/heat.cpp @@ -1010,9 +1010,5 @@ Subsystem *CreateCondenserSubsystem(Mech *owner, int id, void *seg) Condenser(owner, id, (Condenser::SubsystemResource *)seg, Condenser::DefaultData); } -Subsystem *CreateHeatSinkBankSubsystem(Mech *owner, int id, void *seg) -{ - Check(sizeof(HeatSink) <= 0x1e4); - return (Subsystem *) new (Memory::Allocate(0x1e4)) - HeatSink(owner, id, (HeatSink::SubsystemResource *)seg, HeatSink::DefaultData); -} +// CreateHeatSinkBankSubsystem (0xBBE) now lives in heatfamily_reslice.cpp -- it +// builds the real AggregateHeatSink (which needs that TU's class definition). diff --git a/game/reconstructed/heatfamily_reslice.cpp b/game/reconstructed/heatfamily_reslice.cpp index 4fe5e91..6ad0020 100644 --- a/game/reconstructed/heatfamily_reslice.cpp +++ b/game/reconstructed/heatfamily_reslice.cpp @@ -637,52 +637,141 @@ int //########################################################################### //########################################################################### -// HeatSink aggregate class @0050ed4c/ed50 (BEST-EFFORT, name unconfirmed) +// AggregateHeatSink @0050ed4c/ed50 -- the mech heat-sink BANK (classID 0x0BBE) //########################################################################### //########################################################################### // -// vtable @0050ed4c/ed50 ctor @4ae8d0 classID 0x0BBE : HeatSink +// vtable @0050ed4c/ed50 ctor @4ae8d0 classID 0x0BBE own GUID 0x50e590 : HeatSink // -// Parses "HeatSinkCount" (+ defaults "AmbientTemperature" to 300.0f) and -// conducts stored heat toward the ambient setpoint while drawing coolant. -// The only adjacent standalone name string is the pooled "HeatSink", so the -// class name cannot be confirmed from the dump (likely an aggregate / master -// heat-sink bank). Skeleton given for reference; FOLD INTO THE RIGHT CLASS -// once the name is known. +// Parses "HeatSinkCount" and holds a frozen "AmbientTemperature" setpoint (300 K) +// bound by the numeric-R cockpit gauge (HeatSink/AmbientTemperature, the last +// config-binding NULL). See heatfamily_reslice.hpp for the deviation note: the +// base HeatSinkSimulation the HeatSink base ctor installs is kept (the verified, +// un-regressed 0xBBE behavior); the authentic Performance @4ae73c -- which derefs +// a raw self+0xE0 -> [+0x158] that does not map in our layout and runs for EVERY +// mech -- is DEFERRED (ambientTemperature is a frozen constant so the gauge reads +// 300 either way). // -#if 0 // name unconfirmed -- do not compile as-is -// @4ae8d0 -AggregateHeatSink::AggregateHeatSink(Mech *owner, int id, - SubsystemResource *res, SharedData &shared) -: HeatSink(owner, id, res, shared) // FUN_004adda0(...,&DAT_0050e580,0,0) +//############################################################################# +// Attribute Support -- the two aggregate-only bindings, dense-appended after +// HeatSink's table (chained via GetAttributeIndex) so AttributeIndexSet::Build +// has NO gap. CoolantMass/CoolantCapacity stay resolvable via the inherited +// HeatSink table (also bound to this same "HeatSink" subsystem). +// +const AggregateHeatSink::IndexEntry + AggregateHeatSink::AttributePointers[]= { - // *this = &PTR_LAB_0050ed4c; - heatSinkCount = res->heatSinkCount; // this[0x74] = res +0xFC - ambientTemperature= 300.0f; // this[0x75] (_DAT_004ae89c) - helper.Init(); // FUN_004afa1a(this+0x76,0) vtbl 0050ecc4 - thermalConductance= _DAT_004ae974 * heatSinkCount * thermalConductance; // this[0x50] - if (master) SetPerformance(&AggregateHeatSink::Simulation); // PTR 0050e5e8 -> @4ae73c + ATTRIBUTE_ENTRY(AggregateHeatSink, HeatSinkCount, heatSinkCount), // @0x1D0 + ATTRIBUTE_ENTRY(AggregateHeatSink, AmbientTemperature, ambientTemperature) // @0x1D4 FROZEN 300 +}; + +AggregateHeatSink::AttributeIndexSet& + AggregateHeatSink::GetAttributeIndex() + { + static AggregateHeatSink::AttributeIndexSet attributeIndex( + ELEMENTS(AggregateHeatSink::AttributePointers), + AggregateHeatSink::AttributePointers, + HeatSink::GetAttributeIndex() // parent chain + ); + return attributeIndex; + } + +//############################################################################# +// Shared Data Support +// +AggregateHeatSink::SharedData + AggregateHeatSink::DefaultData( + AggregateHeatSink::GetClassDerivations(), + AggregateHeatSink::GetMessageHandlers(), // inherited (HeatSink's) + AggregateHeatSink::GetAttributeIndex(), // OWN -- chains HeatSink's + the 2 new ids + AggregateHeatSink::StateCount // inherited (MechSubsystem::StateCount) + ); + +Derivation* + AggregateHeatSink::GetClassDerivations() + { + // own GUID 0x50e590 (TestInstance @4ae9c0). The name only feeds IsDerivedFrom + // identity, never a resource/name lookup (the gauge binds by the subsystem name + // "HeatSink", not this) -- "HeatSinkBank" is a safe unique label. + static Derivation classDerivations(HeatSink::GetClassDerivations(), "HeatSinkBank"); + return &classDerivations; + } + +// +// @4ae8d0 -- HeatSink base + aggregate count/setpoint. See the deviation note: +// we do NOT scale thermalConductance nor install @4ae73c (both feed the deferred +// relaxation Performance); the base HeatSinkSimulation stands. +// +AggregateHeatSink::AggregateHeatSink( + Mech *owner, + int subsystem_ID, + SubsystemResource *subsystem_resource, + SharedData &shared_data +): + HeatSink(owner, subsystem_ID, subsystem_resource, shared_data), // FUN_004adda0(...,&DAT_0050e580,0,0) + helper() // this[0x76]: default-empty 0xC link node +{ + Check(owner); + Check_Pointer(subsystem_resource); + + heatSinkCount = subsystem_resource->heatSinkCount; // this[0x74] @0x1D0 = res +0xFC + ambientTemperature = 300.0f; // this[0x75] @0x1D4 (_DAT_004ae89c) FROZEN + Check_Fpu(); } -// @4ae724 -- slot 9: base HeatSink step. -void AggregateHeatSink::Step(Scalar dt) { HeatSink_Step(dt); } // FUN_004ad748 +AggregateHeatSink::~AggregateHeatSink() +{ + Check(this); + // `helper` (trivial POD, always empty) and the HeatSink base chain destroy + // IMPLICITLY at the closing brace. Per the dtor-epilogue rule, do NOT write + // explicit ~HeatSink()/member-dtor calls (re-runs the base chain = P5 double-free). + Check_Fpu(); +} -// @4ae73c (351 bytes) -- Performance. Equilibrate heat toward the ambient -// setpoint and draw coolant. -// setpoint = 300.0f - (300.0f - ambientTemperature) * 3.0f; // _DAT_004ae89c/8a0 -// heatEnergy += pendingHeat; currentTemp = heatEnergy/thermalMass; UpdateHeatLoad(); -// q = expf( -dt*thermalConductance*(1.0 - master->heatEnergy) -// *(coolantLevel/coolantCapacity)*coolantFlowScale / thermalMass ); -// pendingHeat += -(currentTemp*refOut - setpoint)*thermalMass*(1.0 - q); -// diff = coolantCapacity - coolantLevel; -// if (diff > 0 && fabsf(diff) > 1e-4) coolantLevel += DrawCoolant(diff); // slot 14 -void AggregateHeatSink::Simulation(Scalar dt) { /* FUN_004ae73c */ } +Logical AggregateHeatSink::TestInstance() const // @4ae9c0 -> IsDerivedFrom 0x50e590 +{ + return IsDerivedFrom(*GetClassDerivations()); +} +Logical AggregateHeatSink::TestClass(Mech &) { return True; } -// @4ae9c0 TestInstance (IsDerivedFrom 0x50e590); @4ae9dc CreateStreamedSubsystem: -// classID 0x0BBE / size 0x100; default heatSinkCount = -1; require "HeatSinkCount". +// +// @4ae9dc -- OFFLINE content-build parser (runtime reads pre-built BTL4.RES; +// completeness-only, never exercised at runtime). +// +int + AggregateHeatSink::CreateStreamedSubsystem( + NotationFile *model_file, + const char *model_name, + const char *subsystem_name, + SubsystemResource *subsystem_resource, + NotationFile *subsystem_file, + const ResourceDirectories *directories, + int passes + ) +{ + // FUN_004ae150 == HeatSink::CreateStreamedSubsystem (thermal fields + link name). + if (!HeatSink::CreateStreamedSubsystem( + model_file, model_name, subsystem_name, + (HeatSink::SubsystemResource *)subsystem_resource, + subsystem_file, directories, passes)) + return False; -#endif + subsystem_resource->classID = (RegisteredClass::ClassID)0xBBE; // param_4+0x20 + subsystem_resource->subsystemModelSize = 0x100; // param_4+0x24 + + if (passes == 1) + subsystem_resource->heatSinkCount = -1; // param_4+0xFC default + + Logical found = subsystem_file->GetEntry(subsystem_name, "HeatSinkCount", + &subsystem_resource->heatSinkCount); + if (!found && subsystem_resource->heatSinkCount == -1) + { + DebugStream << subsystem_name << " missing HeatSinkCount!"; + return False; + } + return True; +} //########################################################################### @@ -709,3 +798,16 @@ Subsystem *CreateReservoirSubsystem(Mech *owner, int id, void *seg) return (Subsystem *) new (Memory::Allocate(0x230)) Reservoir(owner, id, (Reservoir::SubsystemResource *)seg, Reservoir::DefaultData); } + +//===========================================================================// +// Factory bridge -- AggregateHeatSink (factory case 0xBBE, "Sensor" label). +// Binary @9993: alloc 0x1e4, ctor, store, param_1[0x1f7]=slot. The sizeof lock +// (AggregateHeatSinkLayoutCheck) proves ==0x1E4 at compile time. +//===========================================================================// +Subsystem *CreateHeatSinkBankSubsystem(Mech *owner, int id, void *seg) +{ + Check(sizeof(AggregateHeatSink) <= 0x1e4); + return (Subsystem *) new (Memory::Allocate(0x1e4)) + AggregateHeatSink(owner, id, + (AggregateHeatSink::SubsystemResource *)seg, AggregateHeatSink::DefaultData); +} diff --git a/game/reconstructed/heatfamily_reslice.hpp b/game/reconstructed/heatfamily_reslice.hpp index e5e24ee..58d2be2 100644 --- a/game/reconstructed/heatfamily_reslice.hpp +++ b/game/reconstructed/heatfamily_reslice.hpp @@ -291,29 +291,89 @@ }; //########################################################################### -//############### HeatSink aggregate class @0050ed4c/ed50 ############### +//######################## AggregateHeatSink ############################ //########################################################################### // -// BEST-EFFORT / NAME UNCONFIRMED. A HeatSink subclass (classID 0x0BBE) that -// parses "HeatSinkCount" + "AmbientTemperature" and conducts the stored heat -// toward an ambient setpoint while drawing coolant. Appears to model the -// mech's aggregate / master heat-sink bank. The only standalone name string -// adjacent to its field strings is "HeatSink" (pooled with the resource -// field name), so the Derivation name cannot be pinned down from the dump. +// The mech's aggregate / master heat-sink BANK (classID 0x0BBE). A HeatSink +// subclass that parses "HeatSinkCount" and holds a frozen "AmbientTemperature" +// setpoint (300 K); the numeric-R cockpit gauge binds HeatSink/AmbientTemperature +// to this class (L4GAUGE.CFG:4552, the last config-binding NULL). // -// vtable @0050ed4c/ed50 ctor @4ae8d0 classID 0x0BBE base HeatSink +// vtable @0050ed4c/ed50 ctor @4ae8d0 classID 0x0BBE own GUID 0x50e590 // -// struct ...__SubsystemResource : HeatableSubsystem::SubsystemResource -// { int heatSinkCount; /* +0xFC */ }; +// DELIBERATE DEVIATION (databinding-safe, zero-regression): the shipped ctor +// installs Performance @4ae73c (relax toward the ambient setpoint), which reads +// a RAW inherited-base pointer self+0xE0 -> [+0x158] (the engine subsystem's +// status/damage model, FUN_0041de1c). That offset does NOT map in our compiled +// layout (garbage ptr -> AV/NaN, and this ctor runs for EVERY mech). Since +// ambientTemperature is a FROZEN constant (@4ae73c never writes it, so the gauge +// reads 300 either way), we keep the VERIFIED base HeatSinkSimulation the HeatSink +// base ctor already installs and do NOT reimplement @4ae73c / deref self+0xE0. +// The authentic relaxation model is DEFERRED (see the deferred item in ยง10 / P4). // -// Recovered members / methods: -// @0x1D0 (word 0x74) heatSinkCount (from resource +0xFC; scales mass) -// @0x1D4 (word 0x75) ambientTemperature (init 300.0f) -// @0x1D8 (word 0x76) helper sub-object (FUN_004afa1a, vtable 0050ecc4) -// @4ae724 Simulation (slot 9) -> base HeatSink slot9 (@4ad748) -// @4ae73c (351 bytes) Performance: conduct toward ambient + DrawCoolant -// @4ae8d0 ctor @4ae9c0 TestInstance (IsDerivedFrom 0x50e590) -// @4ae9dc CreateStreamedSubsystem (parses HeatSinkCount) + struct AggregateHeatSink__SubsystemResource: + public HeatableSubsystem::SubsystemResource // ends 0xFC + { + int heatSinkCount; // +0xFC "HeatSinkCount" (parser @4ae9dc; ctor reads res+0xFC) + }; + + class AggregateHeatSink: + public HeatSink + { + public: + static Derivation *GetClassDerivations(); // own GUID 0x50e590, name "HeatSinkBank" + static SharedData DefaultData; + + enum { + HeatSinkCountAttributeID = HeatSink::NextAttributeID, // @0x1D0 + AmbientTemperatureAttributeID, // @0x1D4 FROZEN 300 + NextAttributeID + }; + private: + static const IndexEntry AttributePointers[]; + public: + static AttributeIndexSet& GetAttributeIndex(); + + static Logical TestClass(Mech&); + Logical TestInstance() const; // @4ae9c0 -> IsDerivedFrom 0x50e590 + + typedef AggregateHeatSink__SubsystemResource SubsystemResource; + + AggregateHeatSink( + Mech *owner, + int subsystem_ID, + SubsystemResource *subsystem_resource, + SharedData &shared_data = DefaultData + ); // @4ae8d0 + ~AggregateHeatSink(); + + static int CreateStreamedSubsystem( // @4ae9dc (offline content-build only) + NotationFile *model_file, + const char *model_name, + const char *subsystem_name, + SubsystemResource *subsystem_resource, + NotationFile *subsystem_file, + const ResourceDirectories *directories, + int passes = 1 + ); + + public: + // HeatSink base ends 0x1D0; the aggregate adds: + int heatSinkCount; // @0x1D0 (word 0x74) res +0xFC + Scalar ambientTemperature; // @0x1D4 (word 0x75) = 300.0f, FROZEN + SubsystemConnection helper; // @0x1D8 (word 0x76) 0xC link node (vestigial/inert) + // object ends @0x1E4 + + friend struct AggregateHeatSinkLayoutCheck; + }; + + struct AggregateHeatSinkLayoutCheck { + static_assert(offsetof(AggregateHeatSink__SubsystemResource, heatSinkCount) == 0xFC, "res heatSinkCount @0xFC"); + static_assert(offsetof(AggregateHeatSink, heatSinkCount) == 0x1D0, "heatSinkCount @0x1D0 (word 0x74)"); + static_assert(offsetof(AggregateHeatSink, ambientTemperature) == 0x1D4, "ambientTemperature @0x1D4 (word 0x75)"); + static_assert(offsetof(AggregateHeatSink, helper) == 0x1D8, "helper @0x1D8 (word 0x76)"); + static_assert(sizeof(AggregateHeatSink) == 0x1E4, "sizeof 0x1E4 == factory alloc @9993"); + }; //########################################################################### //############# Engine collection-iterator helpers (NOT heat) ########### diff --git a/scratchpad/caphwnd.ps1 b/scratchpad/caphwnd.ps1 new file mode 100644 index 0000000..2e81c3c --- /dev/null +++ b/scratchpad/caphwnd.ps1 @@ -0,0 +1,36 @@ +param([long]$Hwnd, [string]$Out = "w.png") +Add-Type -AssemblyName System.Drawing +Add-Type @" +using System; using System.Runtime.InteropServices; +public class P { + [DllImport("user32.dll")] public static extern bool GetWindowRect(IntPtr h, out RC r); + [DllImport("user32.dll")] public static extern bool PrintWindow(IntPtr h, IntPtr hdc, uint f); + [DllImport("user32.dll")] public static extern IntPtr GetWindowDC(IntPtr h); + [DllImport("user32.dll")] public static extern int ReleaseDC(IntPtr h, IntPtr dc); + [DllImport("user32.dll")] public static extern bool BringWindowToTop(IntPtr h); + [DllImport("user32.dll")] public static extern bool SetForegroundWindow(IntPtr h); + [DllImport("user32.dll")] public static extern bool ShowWindow(IntPtr h, int c); + public struct RC { public int L,T,R,B; } +} +"@ +$h = [IntPtr]$Hwnd +[void][P]::ShowWindow($h, 9) # SW_RESTORE +[void][P]::BringWindowToTop($h) +[void][P]::SetForegroundWindow($h) +Start-Sleep -Milliseconds 400 +$r = New-Object P+RC; [void][P]::GetWindowRect($h, [ref]$r) +$w = $r.R - $r.L; $ht = $r.B - $r.T +if ($w -le 0 -or $ht -le 0) { Write-Host "bad rect"; exit 1 } +$bmp = New-Object System.Drawing.Bitmap $w, $ht +$g = [System.Drawing.Graphics]::FromImage($bmp) +$hdc = $g.GetHdc() +# PW_RENDERFULLCONTENT = 2 (captures DWM-composited content incl. many D3D windows) +$ok = [P]::PrintWindow($h, $hdc, 2) +$g.ReleaseHdc($hdc) +if (-not $ok) { + # fallback: screen copy of the (now foreground) window rect + $g.CopyFromScreen($r.L, $r.T, 0, 0, (New-Object System.Drawing.Size($w, $ht))) +} +$bmp.Save($Out, [System.Drawing.Imaging.ImageFormat]::Png) +$g.Dispose(); $bmp.Dispose() +Write-Host "saved $Out (${w}x${ht}) printwindow=$ok" diff --git a/scratchpad/crop.py b/scratchpad/crop.py new file mode 100644 index 0000000..7fe36be --- /dev/null +++ b/scratchpad/crop.py @@ -0,0 +1,6 @@ +import sys +from PIL import Image +im=Image.open(sys.argv[1]) +box=tuple(int(x) for x in sys.argv[3:7]) +c=im.crop(box); c=c.resize((c.width*2,c.height*2),Image.NEAREST) +c.save(sys.argv[2]); print("saved",sys.argv[2],c.size) diff --git a/scratchpad/crop4.py b/scratchpad/crop4.py new file mode 100644 index 0000000..e4fa576 --- /dev/null +++ b/scratchpad/crop4.py @@ -0,0 +1,4 @@ +import sys +from PIL import Image +im=Image.open(sys.argv[1]); box=tuple(int(x) for x in sys.argv[3:7]) +c=im.crop(box); c=c.resize((c.width*5,c.height*5),Image.NEAREST); c.save(sys.argv[2]); print("saved",c.size) diff --git a/scratchpad/dumpcluster.py b/scratchpad/dumpcluster.py new file mode 100644 index 0000000..31ad5e5 --- /dev/null +++ b/scratchpad/dumpcluster.py @@ -0,0 +1,27 @@ +import json, sys +sys.stdout.reconfigure(encoding='utf-8', errors='replace') +want = sys.argv[1] if len(sys.argv)>1 else 'aggregate' +p=r"C:\Users\epilectrik\.claude\projects\C--git-bt411\09bf24bb-f92d-423a-b815-1eb662736f58\subagents\workflows\wf_1f336584-654\journal.jsonl" +for line in open(p,encoding='utf-8'): + try: o=json.loads(line) + except: continue + if o.get('type')!='result': continue + r=o.get('result') + if not isinstance(r,dict) or 'cluster' not in r: continue + if want.lower() not in r.get('cluster','').lower(): continue + print('CLUSTER:', r.get('cluster')) + print('CONF:', r.get('confidence')) + for it in (r.get('items') or []): + print('\n'+'='*66) + print('ITEM:', it.get('item')) + if it.get('classLayout'): print('\n--- LAYOUT ---\n', it.get('classLayout')) + if it.get('methodDescription'): print('\n--- METHODDESC/REG ---\n', it.get('methodDescription')) + if it.get('attributeTable'): print('\n--- ATTR TABLE ---\n', it.get('attributeTable')) + if it.get('factoryWiring'): print('\n--- FACTORY ---\n', it.get('factoryWiring')) + for f in (it.get('functions') or []): + print('\n--- FN:', f.get('name'), '@', f.get('address'), '---') + print(f.get('cpp')) + if it.get('checklist'): + print('\n--- CHECKLIST ---') + for x in it.get('checklist'): print(' -', x) + print('\nOPEN:', r.get('openQuestions')) diff --git a/scratchpad/dumpwidget.py b/scratchpad/dumpwidget.py new file mode 100644 index 0000000..10623a1 --- /dev/null +++ b/scratchpad/dumpwidget.py @@ -0,0 +1,22 @@ +import json, sys +sys.stdout.reconfigure(encoding='utf-8', errors='replace') +want = sys.argv[1] if len(sys.argv)>1 else 'LeakGauge' +p=r"C:\Users\epilectrik\.claude\projects\C--git-bt411\09bf24bb-f92d-423a-b815-1eb662736f58\subagents\workflows\wf_93c95bcc-09a\journal.jsonl" +for line in open(p,encoding='utf-8'): + try: o=json.loads(line) + except: continue + if o.get('type')!='result': continue + r=o.get('result') + if not isinstance(r,dict) or 'widget' not in r: continue + if want.lower() not in (r.get('widget','')+r.get('configKeyword','')).lower(): continue + print('WIDGET:', r.get('widget')) + print('\n===== methodDescription + registration =====\n', r.get('methodDescription')) + print('\n===== classLayout =====\n', r.get('classLayout')) + print('\n===== attributeTableAdditions =====\n', r.get('attributeTableAdditions')) + for f in (r.get('functions') or []): + print('\n===== FN:', f.get('name'), '@', f.get('address'), '=====') + print(f.get('cpp')) + print('\n===== forceSafeChecklist =====') + for x in (r.get('forceSafeChecklist') or []): print(' -', x) + print('\n===== integrationNotes =====\n', r.get('integrationNotes')) + break diff --git a/scratchpad/enumwin.ps1 b/scratchpad/enumwin.ps1 new file mode 100644 index 0000000..238a168 --- /dev/null +++ b/scratchpad/enumwin.ps1 @@ -0,0 +1,23 @@ +Add-Type @" +using System; using System.Runtime.InteropServices; using System.Text; +public class E { + [DllImport("user32.dll")] public static extern bool EnumWindows(D cb, IntPtr p); + [DllImport("user32.dll")] public static extern bool IsWindowVisible(IntPtr h); + [DllImport("user32.dll")] public static extern int GetWindowText(IntPtr h, StringBuilder s, int n); + [DllImport("user32.dll")] public static extern uint GetWindowThreadProcessId(IntPtr h, out uint pid); + public delegate bool D(IntPtr h, IntPtr p); +} +"@ +$rows=@() +$cb=[E+D]{ param($h,$p) + if([E]::IsWindowVisible($h)){ + $sb=New-Object System.Text.StringBuilder 256 + [void][E]::GetWindowText($h,$sb,256) + $t=$sb.ToString() + $wp=0; [void][E]::GetWindowThreadProcessId($h,[ref]$wp) + $pn=""; try{$pn=(Get-Process -Id $wp -EA Stop).ProcessName}catch{} + $script:rows+=[pscustomobject]@{Hwnd=[long]$h;Ppid=$wp;Proc=$pn;Title=$t} + }; return $true +} +[void][E]::EnumWindows($cb,[IntPtr]::Zero) +$rows | Where-Object {$_.Proc -like "*btl4*"} | Format-Table -Auto | Out-String | Write-Host diff --git a/scratchpad/g_0.png b/scratchpad/g_0.png new file mode 100644 index 0000000..f00e4a3 Binary files /dev/null and b/scratchpad/g_0.png differ diff --git a/scratchpad/g_early.png b/scratchpad/g_early.png new file mode 100644 index 0000000..d6c7501 Binary files /dev/null and b/scratchpad/g_early.png differ diff --git a/scratchpad/g_late.png b/scratchpad/g_late.png new file mode 100644 index 0000000..0512d95 Binary files /dev/null and b/scratchpad/g_late.png differ diff --git a/scratchpad/gauges_blh.png b/scratchpad/gauges_blh.png new file mode 100644 index 0000000..1bf5162 Binary files /dev/null and b/scratchpad/gauges_blh.png differ diff --git a/scratchpad/gaugewin.png b/scratchpad/gaugewin.png new file mode 100644 index 0000000..d574428 Binary files /dev/null and b/scratchpad/gaugewin.png differ diff --git a/scratchpad/gen.png b/scratchpad/gen.png new file mode 100644 index 0000000..9636d23 Binary files /dev/null and b/scratchpad/gen.png differ diff --git a/scratchpad/gen_panels.png b/scratchpad/gen_panels.png new file mode 100644 index 0000000..1f6a5be Binary files /dev/null and b/scratchpad/gen_panels.png differ diff --git a/scratchpad/genfix.png b/scratchpad/genfix.png new file mode 100644 index 0000000..f630e47 Binary files /dev/null and b/scratchpad/genfix.png differ diff --git a/scratchpad/gw1_full.png b/scratchpad/gw1_full.png new file mode 100644 index 0000000..92fdcf0 Binary files /dev/null and b/scratchpad/gw1_full.png differ diff --git a/scratchpad/gw1_main.png b/scratchpad/gw1_main.png new file mode 100644 index 0000000..ed7627e Binary files /dev/null and b/scratchpad/gw1_main.png differ diff --git a/scratchpad/gwave2_full.png b/scratchpad/gwave2_full.png new file mode 100644 index 0000000..8447040 Binary files /dev/null and b/scratchpad/gwave2_full.png differ diff --git a/scratchpad/gwave_heat.png b/scratchpad/gwave_heat.png new file mode 100644 index 0000000..08d218c Binary files /dev/null and b/scratchpad/gwave_heat.png differ diff --git a/scratchpad/leak.png b/scratchpad/leak.png new file mode 100644 index 0000000..0d9c692 Binary files /dev/null and b/scratchpad/leak.png differ diff --git a/scratchpad/leak_heat.png b/scratchpad/leak_heat.png new file mode 100644 index 0000000..74ad886 Binary files /dev/null and b/scratchpad/leak_heat.png differ diff --git a/scratchpad/pilot.png b/scratchpad/pilot.png new file mode 100644 index 0000000..0537f73 Binary files /dev/null and b/scratchpad/pilot.png differ diff --git a/scratchpad/pilot_comm.png b/scratchpad/pilot_comm.png new file mode 100644 index 0000000..efd393e Binary files /dev/null and b/scratchpad/pilot_comm.png differ diff --git a/scratchpad/rdcomplete.py b/scratchpad/rdcomplete.py new file mode 100644 index 0000000..a41f350 --- /dev/null +++ b/scratchpad/rdcomplete.py @@ -0,0 +1,24 @@ +import json, sys +sys.stdout.reconfigure(encoding='utf-8', errors='replace') +p=r"C:\Users\epilectrik\.claude\projects\C--git-bt411\09bf24bb-f92d-423a-b815-1eb662736f58\subagents\workflows\wf_1f336584-654\journal.jsonl" +for line in open(p,encoding='utf-8'): + try: o=json.loads(line) + except: continue + if o.get('type')!='result': continue + r=o.get('result') + if not isinstance(r,dict): continue + if 'order' in r and 'verdict' in r: + print('#'*70); print('SYNTHESIS PLAN'); print('#'*70) + print('\n[verdict]', r.get('verdict')) + for k in ['order','turnkey','reconstruction','deep','dependencies','traps']: + v=r.get(k) + if not v: continue + print('\n['+k+']') + for i,x in enumerate(v): print(' %d. %s'%(i+1,x)) + if 'cluster' in r: + print('\n'+'='*70); print('CLUSTER:', r.get('cluster','')[:80], '| conf:', (r.get('confidence','') or '')[:120]) + for it in (r.get('items') or []): + print(' ITEM:', (it.get('item','') or '')[:150]) + if it.get('risk'): print(' risk:', it.get('risk','')[:200]) + for f in (it.get('functions') or []): + print(' fn:', f.get('name','?'), '@', (f.get('address','') or '')[:30], '(%d chars)'%len(f.get('cpp','') or '')) diff --git a/scratchpad/rdscore.py b/scratchpad/rdscore.py new file mode 100644 index 0000000..95c6e6b --- /dev/null +++ b/scratchpad/rdscore.py @@ -0,0 +1,27 @@ +import json, sys +sys.stdout.reconfigure(encoding='utf-8', errors='replace') +p=r"C:\Users\epilectrik\.claude\projects\C--git-bt411\09bf24bb-f92d-423a-b815-1eb662736f58\subagents\workflows\wf_1d6c4013-9c7\journal.jsonl" +for line in open(p,encoding='utf-8'): + try: o=json.loads(line) + except: continue + if o.get('type')!='result': continue + r=o.get('result') + if not isinstance(r,dict): continue + if 'steps' in r and 'verdict' in r: + print('#'*70); print('SYNTHESIS PLAN'); print('#'*70) + print('\n[verdict]', r.get('verdict')) + for k in ['steps','handlerFixes','rankWiring','soloBehavior','traps']: + v=r.get(k) + if v is None: continue + if isinstance(v,list): + print('\n['+k+']') + for i,x in enumerate(v): print(' %d. %s'%(i+1,x)) + else: + print('\n['+k+'] '+str(v)) + if 'piece' in r and ('death' in r.get('piece','').lower() or 'hook' in r.get('piece','').lower()): + print('\n'+'='*70); print('PIECE:', r.get('piece')[:90]) + for f in (r.get('findings') or []): print(' - '+f) + print(' HOOKS:') + for h in (r.get('hookPoints') or []): print(' * '+h) + print(' already:', (r.get('alreadyReconstructed') or '')[:400]) + print(' open:', (r.get('openQuestions') or '')[:400]) diff --git a/scratchpad/rdverd.py b/scratchpad/rdverd.py new file mode 100644 index 0000000..ae39863 --- /dev/null +++ b/scratchpad/rdverd.py @@ -0,0 +1,26 @@ +import json +p=r"C:\Users\epilectrik\.claude\projects\C--git-bt411\09bf24bb-f92d-423a-b815-1eb662736f58\subagents\workflows\wf_043cfccd-2ed\journal.jsonl" +for line in open(p,encoding='utf-8'): + try: o=json.loads(line) + except: continue + if o.get('type')!='result': continue + r=o.get('result') + if not isinstance(r,dict): continue + if 'implementationOrder' in r or 'mechanicalFixes' in r: + print('=== COVERAGE VERDICT ===') + for k in ['verdict','mechanicalFixes','deepFixes','namingBugs','implementationOrder','authenticallyStatic','gaps']: + v=r.get(k) + if v is None: continue + if isinstance(v,list): + print('\n['+k+']') + for i,x in enumerate(v): print(' %d. %s'%(i+1,x)) + else: + print('\n['+k+'] '+str(v)) + if 'tempMovesWhenFiring' in r: + print('\n\n=== HEATMODEL VERDICT ===') + for k,v in r.items(): + if isinstance(v,list): + print('\n['+k+']') + for x in v: print(' - '+str(x)) + else: + print('\n['+k+'] '+str(v)) diff --git a/scratchpad/rdwidgets.py b/scratchpad/rdwidgets.py new file mode 100644 index 0000000..31c153b --- /dev/null +++ b/scratchpad/rdwidgets.py @@ -0,0 +1,27 @@ +import json, sys +sys.stdout.reconfigure(encoding='utf-8', errors='replace') +p=r"C:\Users\epilectrik\.claude\projects\C--git-bt411\09bf24bb-f92d-423a-b815-1eb662736f58\subagents\workflows\wf_93c95bcc-09a\journal.jsonl" +for line in open(p,encoding='utf-8'): + try: o=json.loads(line) + except: continue + if o.get('type')!='result': continue + r=o.get('result') + if not isinstance(r,dict): continue + if 'widget' in r: + print('\n'+'='*70) + print('WIDGET:', r.get('widget'), '| keyword:', r.get('configKeyword')) + print('confidence:', (r.get('confidence') or '')[:400]) + fns=r.get('functions') or [] + print('functions:', ', '.join(f.get('name','?')+'@'+(f.get('address','?')[:20]) for f in fns)) + print('attrTableAdditions:', (r.get('attributeTableAdditions') or 'none')[:500]) + sd=r.get('stubbedDependencies') or [] + print('stubbedDeps:', json.dumps(sd)[:600]) + print('integrationNotes:', (r.get('integrationNotes') or '')[:600]) + if 'verdict' in r and 'implementationOrder' in r: + print('\n'+'#'*70) + print('VERIFY VERDICT:', (r.get('verdict') or '')[:800]) + for k in ['implementationOrder','blockers','forceTrapRisks','perWidgetVerdict']: + v=r.get(k) + if not v: continue + print('\n['+k+']') + for i,x in enumerate(v): print(' %d. %s'%(i+1,str(x)[:400])) diff --git a/scratchpad/scfin.png b/scratchpad/scfin.png new file mode 100644 index 0000000..1e906c9 Binary files /dev/null and b/scratchpad/scfin.png differ diff --git a/scratchpad/scfin_center.png b/scratchpad/scfin_center.png new file mode 100644 index 0000000..26978c8 Binary files /dev/null and b/scratchpad/scfin_center.png differ diff --git a/scratchpad/scv.png b/scratchpad/scv.png new file mode 100644 index 0000000..3db3666 Binary files /dev/null and b/scratchpad/scv.png differ diff --git a/scratchpad/scv_center.png b/scratchpad/scv_center.png new file mode 100644 index 0000000..b83aad0 Binary files /dev/null and b/scratchpad/scv_center.png differ diff --git a/scratchpad/scv_comm.png b/scratchpad/scv_comm.png new file mode 100644 index 0000000..c09cfc7 Binary files /dev/null and b/scratchpad/scv_comm.png differ diff --git a/scratchpad/shot.ps1 b/scratchpad/shot.ps1 new file mode 100644 index 0000000..c7da3fb --- /dev/null +++ b/scratchpad/shot.ps1 @@ -0,0 +1,53 @@ +# Capture a window (by title substring) or the full virtual screen to a PNG. +# Usage: powershell -File shot.ps1 [titleSubstring] +param([string]$Out = "shot.png", [string]$Title = "") +Add-Type -AssemblyName System.Windows.Forms, System.Drawing +Add-Type @" +using System; +using System.Runtime.InteropServices; +public class W { + [DllImport("user32.dll")] public static extern bool GetWindowRect(IntPtr h, out R r); + [DllImport("user32.dll")] public static extern IntPtr GetForegroundWindow(); + [DllImport("user32.dll")] public static extern bool SetForegroundWindow(IntPtr h); + [DllImport("user32.dll")] public static extern bool IsWindowVisible(IntPtr h); + [DllImport("user32.dll")] public static extern int GetWindowText(IntPtr h, System.Text.StringBuilder s, int n); + [DllImport("user32.dll")] public static extern bool EnumWindows(EnumProc cb, IntPtr p); + public delegate bool EnumProc(IntPtr h, IntPtr p); + public struct R { public int L, T, Rr, B; } +} +"@ +function Cap($rect, $path) { + $w = $rect.Rr - $rect.L; $h = $rect.B - $rect.T + if ($w -le 0 -or $h -le 0) { return $false } + $bmp = New-Object System.Drawing.Bitmap $w, $h + $g = [System.Drawing.Graphics]::FromImage($bmp) + $g.CopyFromScreen($rect.L, $rect.T, 0, 0, (New-Object System.Drawing.Size($w, $h))) + $bmp.Save($path, [System.Drawing.Imaging.ImageFormat]::Png) + $g.Dispose(); $bmp.Dispose(); return $true +} +if ($Title -ne "") { + $found = @() + $cb = [W+EnumProc]{ param($h,$p) + if ([W]::IsWindowVisible($h)) { + $sb = New-Object System.Text.StringBuilder 256 + [void][W]::GetWindowText($h, $sb, 256) + $t = $sb.ToString() + if ($t -like "*$Title*") { $script:found += @{H=$h; T=$t} } + } + return $true + } + [void][W]::EnumWindows($cb, [IntPtr]::Zero) + Write-Host "Matched windows:"; $found | ForEach-Object { Write-Host " '$($_.T)'" } + $i = 0 + foreach ($f in $found) { + $r = New-Object W+R; [void][W]::GetWindowRect($f.H, [ref]$r) + [void][W]::SetForegroundWindow($f.H); Start-Sleep -Milliseconds 250 + $p = $Out -replace '\.png$', "_$i.png" + if (Cap $r $p) { Write-Host "saved $p ($($r.Rr-$r.L)x$($r.B-$r.T)) '$($f.T)'" } + $i++ + } +} else { + $vs = [System.Windows.Forms.SystemInformation]::VirtualScreen + $r = New-Object W+R; $r.L=$vs.Left; $r.T=$vs.Top; $r.Rr=$vs.Right; $r.B=$vs.Bottom + [void](Cap $r $Out); Write-Host "saved $Out (full screen $($vs.Width)x$($vs.Height))" +} diff --git a/scratchpad/valve.png b/scratchpad/valve.png new file mode 100644 index 0000000..400b842 Binary files /dev/null and b/scratchpad/valve.png differ diff --git a/scratchpad/valve_c1.png b/scratchpad/valve_c1.png new file mode 100644 index 0000000..64133de Binary files /dev/null and b/scratchpad/valve_c1.png differ diff --git a/scratchpad/valve_heat.png b/scratchpad/valve_heat.png new file mode 100644 index 0000000..aec390b Binary files /dev/null and b/scratchpad/valve_heat.png differ diff --git a/scratchpad/vis2.png b/scratchpad/vis2.png new file mode 100644 index 0000000..acba911 Binary files /dev/null and b/scratchpad/vis2.png differ diff --git a/scratchpad/vis2_center.png b/scratchpad/vis2_center.png new file mode 100644 index 0000000..647200d Binary files /dev/null and b/scratchpad/vis2_center.png differ diff --git a/tools/__pycache__/disas2.cpython-311.pyc b/tools/__pycache__/disas2.cpython-311.pyc new file mode 100644 index 0000000..dad69e6 Binary files /dev/null and b/tools/__pycache__/disas2.cpython-311.pyc differ