gauge-complete P4b: AggregateHeatSink 0xBBE -> HeatSink/AmbientTemperature bound (last config NULL cleared)
The 0xBBE heat-sink BANK was built as a plain HeatSink, so the numeric-R cockpit gauge binding HeatSink/AmbientTemperature (L4GAUGE.CFG:4552) had no publisher -> the LAST unresolved config attribute. Reconstruct AggregateHeatSink : HeatSink (ctor @4ae8d0, own GUID 0x50e590), byte-exact + static_assert-locked (heatSinkCount@0x1D0, ambientTemperature @0x1D4=300, helper@0x1D8 0xC link node, sizeof 0x1E4 == factory alloc @9993). Publish HeatSinkCount + AmbientTemperature via a dense-prefix attribute table chained to HeatSink::NextAttributeID (shared HeatSink table unchanged, so CoolantMass/CoolantCapacity keep resolving). Move CreateHeatSinkBankSubsystem into heatfamily_reslice.cpp (needs the class def) and build the real class at factory case 0xBBE; mech.cpp unchanged. DELIBERATE DEVIATION (documented in the class): keep the base HeatSinkSimulation the HeatSink ctor installs; do NOT reimplement the authentic Performance @4ae73c -- it derefs a raw self+0xE0 -> [+0x158] that does not map in our compiled layout (AV/NaN, and runs for EVERY mech), and ambientTemperature is a frozen constant so the gauge reads 300 either way. Authentic relaxation model deferred. Verified: [attr] HeatSink/AmbientTemperature OK; all 50 config attribute bindings resolve (0 NULL); no every-mech crash; combat TARGET DESTROYED, FIRED #41+, un-regressed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@@ -168,7 +168,7 @@ badge=VGL
|
||||
patch=Yellow
|
||||
role=Role::Default
|
||||
dropzone=one
|
||||
vehicle=madcat
|
||||
vehicle=bhk1
|
||||
vehicleValue=1000
|
||||
color=White
|
||||
[largebitmap]
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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) ###########
|
||||
|
||||
@@ -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"
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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'))
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 3.6 MiB |
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 8.1 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 6.0 MiB |
|
After Width: | Height: | Size: 4.7 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 8.4 KiB |
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 5.9 KiB |
@@ -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 ''))
|
||||
@@ -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])
|
||||
@@ -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))
|
||||
@@ -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]))
|
||||
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 6.0 KiB |
@@ -0,0 +1,53 @@
|
||||
# Capture a window (by title substring) or the full virtual screen to a PNG.
|
||||
# Usage: powershell -File shot.ps1 <out.png> [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))"
|
||||
}
|
||||
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 8.4 KiB |
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 2.6 KiB |