Add live GPS momentum weights
This commit is contained in:
@@ -2,6 +2,32 @@
|
|||||||
|
|
||||||
Current date/time context: 2026-06-27, local timezone America/Chicago.
|
Current date/time context: 2026-06-27, local timezone America/Chicago.
|
||||||
|
|
||||||
|
## 2026-06-27 Live Momentum Knob Installed
|
||||||
|
|
||||||
|
- Installed a new telemetry/control DLL at about `03:21` local while the game was
|
||||||
|
cold. Installed size: `16899519` bytes.
|
||||||
|
- Active installed config:
|
||||||
|
`solver_weights.bin = 1.0` and `momentum_weights.bin = 8.0`.
|
||||||
|
- The plugin log beside the DLL was truncated to zero after install:
|
||||||
|
`red4ext/plugins/EdgeWeightGPS/EdgeWeightGPS.log`.
|
||||||
|
- `momentum_weights.bin` is one little-endian `float32`, hot-polled every
|
||||||
|
500 ms. `0.0` disables the fixed ordinary-edge penalty; `8.0` is the current
|
||||||
|
prototype; larger values are stress tests. Presets are in
|
||||||
|
`presets/momentum/` and can be written live with
|
||||||
|
`python3 tools/write_momentum_weights.py <preset>`.
|
||||||
|
- New presets:
|
||||||
|
`vanilla=0.0`, `mild=4.0`, `default=8.0`, `strong=16.0`,
|
||||||
|
`silly=80.0`, `pathological=250.0`.
|
||||||
|
- The `gps-momentum-summary` line now waits for a nonzero result route-record
|
||||||
|
count before marking a query as summarized. It should report
|
||||||
|
`gpsResultRouteCount` directly instead of showing `0` from the staging fetch.
|
||||||
|
- Build verification passed:
|
||||||
|
`toolbox run -c 2077 ./tools/build_red4ext_shim.sh`.
|
||||||
|
- Next test should start with current `momentum=8.0`, then while the game is
|
||||||
|
open switch to `vanilla` and `silly` on one or two fixed routes to confirm
|
||||||
|
live A/B behavior. Good candidates from the last run: The Damned/Dogtown
|
||||||
|
pathological route and the SW Badlands fuel station route.
|
||||||
|
|
||||||
## 2026-06-27 Momentum Telemetry Test Installed
|
## 2026-06-27 Momentum Telemetry Test Installed
|
||||||
|
|
||||||
- Installed telemetry DLL at about `03:04` local while the game was cold.
|
- Installed telemetry DLL at about `03:04` local while the game was cold.
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -224,7 +224,8 @@ constexpr float kGpsSolverPavementMultiplier = 1.25f;
|
|||||||
constexpr size_t kGpsNodeMultiplierRoadTailPatchSize = 14;
|
constexpr size_t kGpsNodeMultiplierRoadTailPatchSize = 14;
|
||||||
constexpr size_t kGpsMomentumRelaxPatchSize = 23;
|
constexpr size_t kGpsMomentumRelaxPatchSize = 23;
|
||||||
constexpr size_t kGpsMomentumPenaltyCaveSize = 96;
|
constexpr size_t kGpsMomentumPenaltyCaveSize = 96;
|
||||||
constexpr float kGpsMomentumFixedEdgePenalty = 8.0f;
|
constexpr float kGpsMomentumFixedEdgePenaltyDefault = 8.0f;
|
||||||
|
constexpr float kGpsMomentumFixedEdgePenaltyMax = 1000.0f;
|
||||||
constexpr std::array<float, 8> kGpsSolverNonRoadMultipliers = {
|
constexpr std::array<float, 8> kGpsSolverNonRoadMultipliers = {
|
||||||
10.0f, 6.0f, 2.0f, 0.0f, 4.0f, 2.5f, 1.5f, 0.0f,
|
10.0f, 6.0f, 2.0f, 0.0f, 4.0f, 2.5f, 1.5f, 0.0f,
|
||||||
};
|
};
|
||||||
@@ -236,6 +237,7 @@ constexpr float kGpsSpatialPavementMultiplier = 1.35f;
|
|||||||
constexpr float kGpsSpatialUnknownMultiplier = 1.05f;
|
constexpr float kGpsSpatialUnknownMultiplier = 1.05f;
|
||||||
constexpr uint64_t kGpsSolverWeightsReloadIntervalMs = 500;
|
constexpr uint64_t kGpsSolverWeightsReloadIntervalMs = 500;
|
||||||
constexpr uint64_t kGpsSpatialWeightsReloadIntervalMs = 500;
|
constexpr uint64_t kGpsSpatialWeightsReloadIntervalMs = 500;
|
||||||
|
constexpr uint64_t kGpsMomentumWeightsReloadIntervalMs = 500;
|
||||||
|
|
||||||
struct GpsProviderClassOverride
|
struct GpsProviderClassOverride
|
||||||
{
|
{
|
||||||
@@ -601,13 +603,18 @@ std::array<std::atomic<float>, 5> gGpsSpatialMultipliers = {
|
|||||||
kGpsSpatialUnknownMultiplier,
|
kGpsSpatialUnknownMultiplier,
|
||||||
};
|
};
|
||||||
std::atomic<float> gGpsSolverHighwayMultiplier{kGpsSolverHighwayMultiplierDefault};
|
std::atomic<float> gGpsSolverHighwayMultiplier{kGpsSolverHighwayMultiplierDefault};
|
||||||
|
std::atomic<float> gGpsMomentumFixedEdgePenalty{kGpsMomentumFixedEdgePenaltyDefault};
|
||||||
std::mutex gGpsSpatialWeightsMutex;
|
std::mutex gGpsSpatialWeightsMutex;
|
||||||
|
std::mutex gGpsMomentumWeightsMutex;
|
||||||
std::atomic<uint64_t> gGpsSolverWeightsNextReloadCheckMs = 0;
|
std::atomic<uint64_t> gGpsSolverWeightsNextReloadCheckMs = 0;
|
||||||
std::atomic<uint64_t> gGpsSpatialWeightsNextReloadCheckMs = 0;
|
std::atomic<uint64_t> gGpsSpatialWeightsNextReloadCheckMs = 0;
|
||||||
|
std::atomic<uint64_t> gGpsMomentumWeightsNextReloadCheckMs = 0;
|
||||||
std::filesystem::file_time_type gGpsSolverWeightsLastWriteTime{};
|
std::filesystem::file_time_type gGpsSolverWeightsLastWriteTime{};
|
||||||
std::filesystem::file_time_type gGpsSpatialWeightsLastWriteTime{};
|
std::filesystem::file_time_type gGpsSpatialWeightsLastWriteTime{};
|
||||||
|
std::filesystem::file_time_type gGpsMomentumWeightsLastWriteTime{};
|
||||||
bool gGpsSolverWeightsFileKnown = false;
|
bool gGpsSolverWeightsFileKnown = false;
|
||||||
bool gGpsSpatialWeightsFileKnown = false;
|
bool gGpsSpatialWeightsFileKnown = false;
|
||||||
|
bool gGpsMomentumWeightsFileKnown = false;
|
||||||
|
|
||||||
uintptr_t GetImageBase();
|
uintptr_t GetImageBase();
|
||||||
|
|
||||||
@@ -638,6 +645,11 @@ std::filesystem::path GetSolverWeightsPath()
|
|||||||
return GetPluginDirectory() / L"solver_weights.bin";
|
return GetPluginDirectory() / L"solver_weights.bin";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::filesystem::path GetMomentumWeightsPath()
|
||||||
|
{
|
||||||
|
return GetPluginDirectory() / L"momentum_weights.bin";
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t GetElapsedMs()
|
uint64_t GetElapsedMs()
|
||||||
{
|
{
|
||||||
if (!gLogStartTick || !gLogFrequency)
|
if (!gLogStartTick || !gLogFrequency)
|
||||||
@@ -715,6 +727,34 @@ void LogGpsSolverHighwayMultiplier(std::string_view aPrefix, float aValue)
|
|||||||
LogRed4ext(line.str());
|
LogRed4ext(line.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsUsableMomentumPenalty(float aValue)
|
||||||
|
{
|
||||||
|
return std::isfinite(aValue) && aValue >= 0.0f && aValue <= kGpsMomentumFixedEdgePenaltyMax;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StoreGpsMomentumFixedEdgePenalty(float aValue)
|
||||||
|
{
|
||||||
|
gGpsMomentumFixedEdgePenalty.store(aValue, std::memory_order_relaxed);
|
||||||
|
|
||||||
|
for (auto& site : gGpsMomentumPenaltyPatchSites)
|
||||||
|
{
|
||||||
|
if (!site.penaltyConstant)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteFloat(site.penaltyConstant, aValue);
|
||||||
|
FlushInstructionCache(GetCurrentProcess(), site.penaltyConstant, sizeof(aValue));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LogGpsMomentumFixedEdgePenalty(std::string_view aPrefix, float aValue)
|
||||||
|
{
|
||||||
|
std::ostringstream line;
|
||||||
|
line << aPrefix << " fixedEdgePenalty=" << aValue;
|
||||||
|
LogRed4ext(line.str());
|
||||||
|
}
|
||||||
|
|
||||||
void EmitAbsoluteRaxCall(uint8_t* aCave, size_t& aOffset, uintptr_t aTarget)
|
void EmitAbsoluteRaxCall(uint8_t* aCave, size_t& aOffset, uintptr_t aTarget)
|
||||||
{
|
{
|
||||||
aCave[aOffset++] = 0x48; // mov rax, imm64
|
aCave[aOffset++] = 0x48; // mov rax, imm64
|
||||||
@@ -838,6 +878,82 @@ void MaybeReloadGpsSolverWeights(bool aForce = false)
|
|||||||
LogRed4ext(line.str());
|
LogRed4ext(line.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MaybeReloadGpsMomentumWeights(bool aForce = false)
|
||||||
|
{
|
||||||
|
if (!kEnableGpsMomentumPenaltyInlinePatch)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto nowMs = GetElapsedMs();
|
||||||
|
if (!aForce && nowMs < gGpsMomentumWeightsNextReloadCheckMs.load(std::memory_order_relaxed))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard lock(gGpsMomentumWeightsMutex);
|
||||||
|
if (!aForce && nowMs < gGpsMomentumWeightsNextReloadCheckMs.load(std::memory_order_relaxed))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
gGpsMomentumWeightsNextReloadCheckMs.store(nowMs + kGpsMomentumWeightsReloadIntervalMs,
|
||||||
|
std::memory_order_relaxed);
|
||||||
|
|
||||||
|
const auto path = GetMomentumWeightsPath();
|
||||||
|
std::error_code error;
|
||||||
|
const auto writeTime = std::filesystem::last_write_time(path, error);
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
if (aForce || gGpsMomentumWeightsFileKnown)
|
||||||
|
{
|
||||||
|
gGpsMomentumWeightsFileKnown = false;
|
||||||
|
std::ostringstream line;
|
||||||
|
line << "momentum weights file unavailable path=" << path.string()
|
||||||
|
<< " using fixedEdgePenalty=" << gGpsMomentumFixedEdgePenalty.load(std::memory_order_relaxed);
|
||||||
|
LogRed4ext(line.str());
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!aForce && gGpsMomentumWeightsFileKnown && writeTime == gGpsMomentumWeightsLastWriteTime)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float fixedEdgePenalty = 0.0f;
|
||||||
|
std::ifstream input(path, std::ios::binary);
|
||||||
|
input.read(reinterpret_cast<char*>(&fixedEdgePenalty), static_cast<std::streamsize>(sizeof(fixedEdgePenalty)));
|
||||||
|
if (input.gcount() != static_cast<std::streamsize>(sizeof(fixedEdgePenalty)))
|
||||||
|
{
|
||||||
|
std::ostringstream line;
|
||||||
|
line << "momentum weights reload skipped path=" << path.string() << " bytes=" << input.gcount()
|
||||||
|
<< " expected=" << sizeof(fixedEdgePenalty);
|
||||||
|
LogRed4ext(line.str());
|
||||||
|
gGpsMomentumWeightsFileKnown = true;
|
||||||
|
gGpsMomentumWeightsLastWriteTime = writeTime;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IsUsableMomentumPenalty(fixedEdgePenalty))
|
||||||
|
{
|
||||||
|
std::ostringstream line;
|
||||||
|
line << "momentum weights reload skipped path=" << path.string()
|
||||||
|
<< " invalidFixedEdgePenalty=" << fixedEdgePenalty;
|
||||||
|
LogRed4ext(line.str());
|
||||||
|
gGpsMomentumWeightsFileKnown = true;
|
||||||
|
gGpsMomentumWeightsLastWriteTime = writeTime;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
StoreGpsMomentumFixedEdgePenalty(fixedEdgePenalty);
|
||||||
|
gGpsMomentumWeightsFileKnown = true;
|
||||||
|
gGpsMomentumWeightsLastWriteTime = writeTime;
|
||||||
|
|
||||||
|
std::ostringstream line;
|
||||||
|
line << "momentum weights reloaded path=" << path.string() << " fixedEdgePenalty=" << fixedEdgePenalty;
|
||||||
|
LogRed4ext(line.str());
|
||||||
|
}
|
||||||
|
|
||||||
void RemoveGpsMomentumPenaltyInlinePatch();
|
void RemoveGpsMomentumPenaltyInlinePatch();
|
||||||
|
|
||||||
bool InstallGpsMomentumPenaltyPatchSite(GpsMomentumPenaltyPatchSite& aSite,
|
bool InstallGpsMomentumPenaltyPatchSite(GpsMomentumPenaltyPatchSite& aSite,
|
||||||
@@ -889,7 +1005,7 @@ bool InstallGpsMomentumPenaltyPatchSite(GpsMomentumPenaltyPatchSite& aSite,
|
|||||||
}
|
}
|
||||||
|
|
||||||
const auto penaltyConstantOffset = offset;
|
const auto penaltyConstantOffset = offset;
|
||||||
WriteFloat(cave + offset, kGpsMomentumFixedEdgePenalty);
|
WriteFloat(cave + offset, gGpsMomentumFixedEdgePenalty.load(std::memory_order_relaxed));
|
||||||
offset += sizeof(float);
|
offset += sizeof(float);
|
||||||
|
|
||||||
const auto caveAddress = reinterpret_cast<uintptr_t>(cave);
|
const auto caveAddress = reinterpret_cast<uintptr_t>(cave);
|
||||||
@@ -925,7 +1041,7 @@ bool InstallGpsMomentumPenaltyPatchSite(GpsMomentumPenaltyPatchSite& aSite,
|
|||||||
std::ostringstream line;
|
std::ostringstream line;
|
||||||
line << "gps-momentum-penalty-inline-patch applied site=" << aSite.name << " target_rva=0x" << std::hex
|
line << "gps-momentum-penalty-inline-patch applied site=" << aSite.name << " target_rva=0x" << std::hex
|
||||||
<< aSite.targetRva << " cave=" << static_cast<void*>(cave) << std::dec
|
<< aSite.targetRva << " cave=" << static_cast<void*>(cave) << std::dec
|
||||||
<< " fixedEdgePenalty=" << kGpsMomentumFixedEdgePenalty;
|
<< " fixedEdgePenalty=" << gGpsMomentumFixedEdgePenalty.load(std::memory_order_relaxed);
|
||||||
LogRed4ext(line.str());
|
LogRed4ext(line.str());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -2604,6 +2720,14 @@ void AppendGpsResultObjectLightCounts(std::ostringstream& aLine, const char* aPr
|
|||||||
aLine << " " << aPrefix << "_pointCount=" << pointCount;
|
aLine << " " << aPrefix << "_pointCount=" << pointCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TryReadGpsResultRouteCount(void* aResultObject, uint32_t& aRouteCount)
|
||||||
|
{
|
||||||
|
aRouteCount = 0;
|
||||||
|
return aResultObject &&
|
||||||
|
TryReadMemory(reinterpret_cast<const void*>(reinterpret_cast<uintptr_t>(aResultObject) + 0x34),
|
||||||
|
aRouteCount);
|
||||||
|
}
|
||||||
|
|
||||||
void AppendGpsResultElementArraySummary(std::ostringstream& aLine, const char* aPrefix, void* aResultObject)
|
void AppendGpsResultElementArraySummary(std::ostringstream& aLine, const char* aPrefix, void* aResultObject)
|
||||||
{
|
{
|
||||||
uint32_t capacity = 0;
|
uint32_t capacity = 0;
|
||||||
@@ -4555,7 +4679,9 @@ bool DetourGpsQueryResultFetch(void* aManager, uint32_t aQueryId, void* aOutPath
|
|||||||
(!isTracked && callCount < kMaxUntrackedSamples && aQueryId < 2))
|
(!isTracked && callCount < kMaxUntrackedSamples && aQueryId < 2))
|
||||||
: (result && isMapRouteQuery);
|
: (result && isMapRouteQuery);
|
||||||
|
|
||||||
if (result && isMapRouteQuery)
|
uint32_t gpsResultRouteCount = 0;
|
||||||
|
const auto hasGpsResultRouteCount = TryReadGpsResultRouteCount(aOutPath, gpsResultRouteCount);
|
||||||
|
if (result && isMapRouteQuery && hasGpsResultRouteCount && gpsResultRouteCount > 0)
|
||||||
{
|
{
|
||||||
TrackedGpsQuery summaryQuery{};
|
TrackedGpsQuery summaryQuery{};
|
||||||
uint64_t callsA = 0;
|
uint64_t callsA = 0;
|
||||||
@@ -4566,14 +4692,15 @@ bool DetourGpsQueryResultFetch(void* aManager, uint32_t aQueryId, void* aOutPath
|
|||||||
globalCallsB))
|
globalCallsB))
|
||||||
{
|
{
|
||||||
const auto totalCalls = callsA + callsB;
|
const auto totalCalls = callsA + callsB;
|
||||||
const auto fixedPenalty = kGpsMomentumFixedEdgePenalty;
|
const auto fixedPenalty = gGpsMomentumFixedEdgePenalty.load(std::memory_order_relaxed);
|
||||||
std::ostringstream line;
|
std::ostringstream line;
|
||||||
line << "gps-momentum-summary queryId=" << aQueryId << " resultFetchCall=" << perQueryCall;
|
line << "gps-momentum-summary queryId=" << aQueryId << " resultFetchCall=" << perQueryCall;
|
||||||
AppendTrackedGpsQuery(line, summaryQuery);
|
AppendTrackedGpsQuery(line, summaryQuery);
|
||||||
line << " callsA=" << callsA << " callsB=" << callsB << " callsTotal=" << totalCalls
|
line << " callsA=" << callsA << " callsB=" << callsB << " callsTotal=" << totalCalls
|
||||||
<< " fixedPenalty=" << fixedPenalty
|
<< " fixedPenalty=" << fixedPenalty
|
||||||
<< " penaltyTotal=" << static_cast<double>(totalCalls) * static_cast<double>(fixedPenalty)
|
<< " penaltyTotal=" << static_cast<double>(totalCalls) * static_cast<double>(fixedPenalty)
|
||||||
<< " globalCallsA=" << globalCallsA << " globalCallsB=" << globalCallsB;
|
<< " globalCallsA=" << globalCallsA << " globalCallsB=" << globalCallsB
|
||||||
|
<< " gpsResultRouteCount=" << gpsResultRouteCount;
|
||||||
AppendGpsResultObjectLightCounts(line, "gpsResult", aOutPath);
|
AppendGpsResultObjectLightCounts(line, "gpsResult", aOutPath);
|
||||||
LogRed4ext(line.str());
|
LogRed4ext(line.str());
|
||||||
}
|
}
|
||||||
@@ -5787,6 +5914,7 @@ bool OnRunningUpdate(void* aApp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
MaybeReloadGpsSolverWeights();
|
MaybeReloadGpsSolverWeights();
|
||||||
|
MaybeReloadGpsMomentumWeights();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -5869,9 +5997,11 @@ RED4EXT_C_EXPORT bool RED4EXT_CALL Main(RED4ext::v1::PluginHandle aHandle, RED4e
|
|||||||
if (kEnableGpsMomentumPenaltyInlinePatch)
|
if (kEnableGpsMomentumPenaltyInlinePatch)
|
||||||
{
|
{
|
||||||
std::ostringstream line;
|
std::ostringstream line;
|
||||||
line << "momentum fixed-edge penalty active value=" << kGpsMomentumFixedEdgePenalty
|
line << "momentum weights path=" << GetMomentumWeightsPath().string();
|
||||||
<< " sites=ordinary-expansion";
|
|
||||||
LogRed4ext(line.str());
|
LogRed4ext(line.str());
|
||||||
|
MaybeReloadGpsMomentumWeights(true);
|
||||||
|
LogGpsMomentumFixedEdgePenalty("momentum fixed-edge penalty active",
|
||||||
|
gGpsMomentumFixedEdgePenalty.load(std::memory_order_relaxed));
|
||||||
}
|
}
|
||||||
|
|
||||||
InstallGpsNodeMultiplierInlinePatch();
|
InstallGpsNodeMultiplierInlinePatch();
|
||||||
|
|||||||
Executable
+60
@@ -0,0 +1,60 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Write EdgeWeightGPS momentum penalty presets as one raw float32 value."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import struct
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
DEFAULT_INSTALL_PATH = Path(
|
||||||
|
"/var/home/salt/.var/app/com.valvesoftware.Steam/.local/share/Steam/steamapps/common/"
|
||||||
|
"Cyberpunk 2077/red4ext/plugins/EdgeWeightGPS/momentum_weights.bin"
|
||||||
|
)
|
||||||
|
|
||||||
|
PRESETS: dict[str, float] = {
|
||||||
|
"vanilla": 0.0,
|
||||||
|
"default": 8.0,
|
||||||
|
"mild": 4.0,
|
||||||
|
"strong": 16.0,
|
||||||
|
"silly": 80.0,
|
||||||
|
"pathological": 250.0,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def parse_penalty(text: str) -> float:
|
||||||
|
value = float(text)
|
||||||
|
if not 0.0 <= value <= 1000.0:
|
||||||
|
raise argparse.ArgumentTypeError("penalty must be between 0 and 1000")
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def write_weight(path: Path, value: float) -> None:
|
||||||
|
path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
path.write_bytes(struct.pack("<f", value))
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("preset", nargs="?", choices=sorted(PRESETS), default="default")
|
||||||
|
parser.add_argument("--value", type=parse_penalty, help="explicit fixed edge penalty")
|
||||||
|
parser.add_argument("--output", type=Path, default=DEFAULT_INSTALL_PATH)
|
||||||
|
parser.add_argument("--preset-dir", type=Path, help="write every named preset into this directory")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if args.preset_dir:
|
||||||
|
for name, value in PRESETS.items():
|
||||||
|
path = args.preset_dir / f"{name}.bin"
|
||||||
|
write_weight(path, value)
|
||||||
|
print(f"{path}: {value}")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
value = args.value if args.value is not None else PRESETS[args.preset]
|
||||||
|
write_weight(args.output, value)
|
||||||
|
print(f"{args.output}: {value}")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
Reference in New Issue
Block a user