diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 2efe480..d14f027 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -61,6 +61,7 @@ jobs: working-directory: site run: npx quartz build -d .. - name: Patch sidebar title link + working-directory: site run: python ../publish/quartz-patches/patch-title-link.py - name: Upload artifact uses: actions/upload-pages-artifact@v3 diff --git a/archive/threads/NOTimothyLottes/2023-08-03-spc-using-8-deep-swap-all-aliasing-same-bo-image/index.md b/archive/threads/NOTimothyLottes/2023-08-03-spc-using-8-deep-swap-all-aliasing-same-bo-image/index.md index 935daf0..4d37651 100644 --- a/archive/threads/NOTimothyLottes/2023-08-03-spc-using-8-deep-swap-all-aliasing-same-bo-image/index.md +++ b/archive/threads/NOTimothyLottes/2023-08-03-spc-using-8-deep-swap-all-aliasing-same-bo-image/index.md @@ -29,7 +29,7 @@ in_reply_to: "" SPC: Using 8 deep swap all aliasing same BO (image) fixes Game Mode crash with external display. Pipelined load gets to black screen in 2 ms. Takes 460 ms to allocate 4 GiB GTT video ram, 558 ms to copy 256 MiB cart from page cache to USWC (page faults), all in parallel. -Media (not lifted): `1687062786273062912_F2mmqYXWoAAG3fj_orig.jpg` +![](https://files.catbox.moe/yfbahk.jpg) **2/** @@ -39,7 +39,7 @@ Clearing page cache to simulate a cold launch: Takes 1.5 sec to read 256 MiB fro Forgot the timing capture ... Load from SSD. -Media (not lifted): `1687066126268674048_F2mpszoXMAE00Hy_orig.jpg` +`1687066126268674048_F2mpszoXMAE00Hy_orig.jpg` **4/** diff --git a/archive/threads/NOTimothyLottes/index.md b/archive/threads/NOTimothyLottes/index.md index e9a27da..f6436f0 100644 --- a/archive/threads/NOTimothyLottes/index.md +++ b/archive/threads/NOTimothyLottes/index.md @@ -1,12 +1,81 @@ --- -title: NOTimothyLottes -type: note -draft: false -description: Archived threads by NOTimothyLottes. -tags: - - archive - - twitter - - NOTimothyLottes ---- +- [[archive/threads/NOTimothyLottes/2022-11-04-vulkan-1500-lines-of-overhead-including-header]] +- [[archive/threads/NOTimothyLottes/2022-11-05-19-GPU-Programming-Tip-Line-Thread]] +- [[archive/threads/NOTimothyLottes/2022-11-08-example-of-bind-everything-once-layout-aliasing]] +- [[archive/threads/NOTimothyLottes/2022-11-09-if-only-pc-vendors-with-open-isas-amd-intel-would]] +- [[archive/threads/NOTimothyLottes/2022-11-13-my-prefered-method-of-managing-application-data]] +- [[archive/threads/NOTimothyLottes/2022-11-30-explicit-packed-16-bit-code-fsr1-example-https]] +- [[archive/threads/NOTimothyLottes/2023-04-26-can-make-a-custom-forth-to-binary-in-a-few-k]] +- [[archive/threads/NOTimothyLottes/2023-06-30-nothing-oriented-programming-nop-where-the-goal]] +- [[archive/threads/NOTimothyLottes/2023-08-03-spc-using-8-deep-swap-all-aliasing-same-bo-image]] - [[archive/threads/NOTimothyLottes/2023-08-04-for-anyone-tuning-in-now-spc-is-kind-of-like-a]] +- [[archive/threads/NOTimothyLottes/2023-08-06-the-next-challenge-is-overscan-safety-since-real]] +- [[archive/threads/NOTimothyLottes/2023-08-06-yeah-perhaps-wildly-alien-but-for-those-who-grew]] +- [[archive/threads/NOTimothyLottes/2023-08-07-crt-emulation-on-lcds-can-be-hard-for-example-its]] +- [[archive/threads/NOTimothyLottes/2023-08-18-spc-last-crt-shader-was-broken-corrected-it-its]] +- [[archive/threads/NOTimothyLottes/2023-08-18-the-subpix-version-is-definitely-better-because]] +- [[archive/threads/NOTimothyLottes/2023-12-15-long-thread]] +- [[archive/threads/NOTimothyLottes/2023-12-16-if-there-is-anything-to-learn-for-programming-it]] +- [[archive/threads/NOTimothyLottes/2023-12-19-multi-session-is-nice-since-the-binary-auto]] +- [[archive/threads/NOTimothyLottes/2024-02-13-once-upon-a-time-not-up-any-more-lots-of-color]] +- [[archive/threads/NOTimothyLottes/2024-04-06-on-https-mastodon-gamedev-place-notimothylottes]] +- [[archive/threads/NOTimothyLottes/2024-05-04-it-was-only-later-when-systems-forced-c-abi]] +- [[archive/threads/NOTimothyLottes/2024-11-16-that-line-of-thinking-is-universal-solution-to]] +- [[archive/threads/NOTimothyLottes/2024-11-19-after-vk-device-is-open-i-signal-a-background]] +- [[archive/threads/NOTimothyLottes/2024-11-21-32-oh-damn-32-should-probably-stop-now-until-next]] +- [[archive/threads/NOTimothyLottes/2024-12-15-texel-buffer-is-needed-for-whatever-formats-one]] +- [[archive/threads/NOTimothyLottes/2024-12-16-also-i-wouldnt-just-modify-an-existing-compiler]] +- [[archive/threads/NOTimothyLottes/2024-12-16-then-there-are-rough-edges-to-texel-buffer]] +- [[archive/threads/NOTimothyLottes/2024-12-21-not-sure-if-this-is-the-end-of-this-story-yet-but]] +- [[archive/threads/NOTimothyLottes/2025-04-30-3-i-got-side-tracked-by-building-a-language-that]] +- [[archive/threads/NOTimothyLottes/2025-04-30-i-laugh-when-people-say-c-is-like-assembly-they]] +- [[archive/threads/NOTimothyLottes/2025-06-29-many-of-my-forth-like-languages-worked-via-nested]] +- [[archive/threads/NOTimothyLottes/2025-07-23-i-dont-use-standard-c-libs-or-anything-like-that]] +- [[archive/threads/NOTimothyLottes/2025-07-31-people-claim-assembly-is-hard-a-good-counter-to]] +- [[archive/threads/NOTimothyLottes/2025-08-01-also-run-from-gpu-side-editing-tools-for-shader]] +- [[archive/threads/NOTimothyLottes/2025-08-02-so-far-the-plan-is-to-have-the-data-read-write]] +- [[archive/threads/NOTimothyLottes/2025-11-17-i-wish-everyone-would-just-adopt-reversed-with]] +- [[archive/threads/NOTimothyLottes/2026-01-14-can-do-that-but-at-least-these-kinds-of-systems]] +- [[archive/threads/NOTimothyLottes/2026-03-08-ill-add-one-conspiracy-theory-for-everyone]] +- [[archive/threads/NOTimothyLottes/2026-05-23-most-crap-o-grammers-today-in-the-user-space-c]] +- [[archive/threads/NOTimothyLottes/2026-05-29-https-trickybitsblog-github-io-2024-02-25]] +- [[archive/threads/NOTimothyLottes/2026-05-30-renovating-cpu-clock-code-im-assuming-x86-64-tsc]] +- [[archive/threads/NOTimothyLottes/2026-05-31-hits-the-easy-to-debug-cpu-or-gpu-stuff-in-the]] +- [[archive/threads/NOTimothyLottes/2026-05-31-no-debugger-debug-console-printf-style-prior]] +- [[archive/threads/NOTimothyLottes/2026-06-01-that-plus-an-oscilloscope-this-is-the-way]] +- [[archive/threads/NOTimothyLottes/2026-06-01-windows-thread-priority]] +- [[archive/threads/NOTimothyLottes/2026-06-02-for-windows-trying-to-standardize-on-highest]] +- [[archive/threads/NOTimothyLottes/2026-06-02-its-unfortunate-there-isnt-an-easy-way-to-map-the]] +- [[archive/threads/NOTimothyLottes/2026-06-03-back-running-640x480-on-my-vga-crts-to-prep-for]] +- [[archive/threads/NOTimothyLottes/2026-06-10-steamos-init]] +- [[archive/threads/NOTimothyLottes/2026-06-13-cross-compilation-is-up-just-like-on-windows-with]] +- [[archive/threads/NOTimothyLottes/2026-06-13-nanorc-done-and-back-to-actual-programming-with]] +- [[archive/threads/NOTimothyLottes/2026-06-13-the-glibc-implementation-would-do-that-i-bypass]] +- [[archive/threads/NOTimothyLottes/2026-06-14-on-linux-i-do-speculative-pinning-of-cpu-memory]] +- [[archive/threads/NOTimothyLottes/2026-06-26-quick-summary-of-why-not-pselect-ppoll-epoll]] +- [[archive/threads/NOTimothyLottes/2026-06-27-deterrent-to-alsa-is-just-parsing-through-snd-pcm]] +- [[archive/threads/NOTimothyLottes/2026-06-29-alsa-hell-month-continues-remember-it-might-be]] +- [[archive/threads/NOTimothyLottes/2026-06-29-eventually-figure-out-enough-to-get-aplay-to]] +- [[archive/threads/NOTimothyLottes/2026-06-30-working-on-the-linux-thread-priority-code-linux]] +- [[archive/threads/NOTimothyLottes/2026-07-01-did-manage-to-get-alsa-to-function-without-sndrv]] +- [[archive/threads/NOTimothyLottes/2026-07-01-haha-damn-i-thought-i-had-a-great-idea-for-wine]] +- [[archive/threads/NOTimothyLottes/2026-07-01-linux-by-default-doesnt-allow-any-increase-in]] +- [[archive/threads/NOTimothyLottes/2026-07-02-settings-im-using-for-snd-pcm-sw-params-for-alsa]] +- [[archive/threads/NOTimothyLottes/2026-07-02-yuck-starting-on-wdm-ks-audio-interface-for-win32]] +- [[archive/threads/NOTimothyLottes/2026-07-03-following-the-succession-thanks-of-re-trying]] +- [[archive/threads/NOTimothyLottes/2026-07-03-so-instead-of-the-massive-mmdeviceapi-h-mess-ware]] +- [[archive/threads/NOTimothyLottes/2026-07-04-wines-iaudioclient-getdeviceperiod-returns-53333]] +- [[archive/threads/NOTimothyLottes/2026-07-06-vulkan-starts-with-the-ping-pong-between-getting]] +- [[archive/threads/NOTimothyLottes/2026-07-08-next-pre-device-opening-activity-is-choosing]] +- [[archive/threads/NOTimothyLottes/2026-07-10-oh-i-probably-have-a-lot-to-learn-here-building]] +- [[archive/threads/NOTimothyLottes/2026-07-11-rethinking-vulkan-queue-choice-traditional-double]] +- [[archive/threads/NOTimothyLottes/2026-07-13-another-quality-of-life-change-exit-with-error]] +- [[archive/threads/NOTimothyLottes/2026-07-14-example-usage-after-clean-up]] +- [[archive/threads/NOTimothyLottes/2026-07-14-so-i-can-liter-error-checks-around-stuff-with]] +- [[archive/threads/NOTimothyLottes/2026-07-15-sar-on-a-control-word-can-in-theory-grab-3-values]] +- [[archive/threads/NOTimothyLottes/2026-07-17-oh-f-it-the-urge-to-drop-the-c-baggage-was-too]] +- [[archive/threads/NOTimothyLottes/2026-07-18-i-realized-at-some-point-i-can-have-most]] +- [[archive/threads/NOTimothyLottes/2026-07-19-the-aim-of-course-keep-the-stuff-that-doesnt-need]] +- [[archive/threads/NOTimothyLottes/2026-07-22-a-language-that-you-author-in-a-compressed-space]] +- [[archive/threads/NOTimothyLottes/2026-08-02-re-fpga-land-alus-im-firmly-distracted-by-an]] diff --git a/scripts/twitter/README.md b/scripts/twitter/README.md index f72c27f..c79176a 100644 --- a/scripts/twitter/README.md +++ b/scripts/twitter/README.md @@ -5,12 +5,14 @@ Front door: `tw.py`. Individual scripts still work. From the vault root: ``` -python scripts/twitter/tw.py locate --id -python scripts/twitter/tw.py graph --id -python scripts/twitter/tw.py refresh --id --tip -python scripts/twitter/tw.py lift --id --orig -python scripts/twitter/tw.py ocr --id -python scripts/twitter/tw.py publish --id +python C:\projects\Threadwell\scripts\twitter\tw.py locate --id +python C:\projects\Threadwell\scripts\twitter\tw.py graph --id +python C:\projects\Threadwell\scripts\twitter\tw.py refresh --id --tip +python C:\projects\Threadwell\scripts\twitter\tw.py lift --id --orig +python C:\projects\Threadwell\scripts\twitter\tw.py ocr --id +python C:\projects\Threadwell\scripts\twitter\tw.py publish --id +python C:\projects\Threadwell\scripts\twitter\tw.py sync --handle # rebuild handle index +python C:\projects\Threadwell\scripts\twitter\tw.py sync # rebuild all handle indexes ``` `paths.py` sets vault = two parents above this file, dumps = `../manual_slop/docs/twitter`, scratch = `../Threadwell-ai/scratch`. diff --git a/scripts/twitter/lift_catbox.py b/scripts/twitter/lift_catbox.py index f396d15..230b286 100644 --- a/scripts/twitter/lift_catbox.py +++ b/scripts/twitter/lift_catbox.py @@ -10,8 +10,18 @@ Default without --orig: only rows already publish=true. After upload, any note token that is the local filename (backticked or bare) or a previous url for that row becomes ![](https://files.catbox.moe/…). -Per-upload curl: --max-time 120, --retry 3, --retry-delay 2, --retry-all-errors. -Errors are sanitized to redact the userhash before printing. +Catbox rate-limits the userhash per minute. Algorithm: + + - One attempt per upload. No curl retries. A failure is a failure — + the user retries the whole lift later (the script persists progress + after each success, so partial work survives). + - 60-second sleep between consecutive uploads in the same run. + - 200 KB/s upload cap per curl. + - On empty/non-URL body: sleep 120s before raising, so a manual + retry minutes later doesn't arrive during catbox's cooldown. + - media.json is rewritten after each successful upload (atomic), + not at the end of the run. + - Errors are sanitized to redact the userhash before printing. """ from __future__ import annotations @@ -27,11 +37,10 @@ from pathlib import Path from paths import VAULT as VAULT_ROOT API = "https://catbox.moe/user/api.php" -MAX_TIME = 120 -RETRIES = 3 -RETRY_DELAY = 5 -THROTTLE_SECS = 5.0 -LIMIT_RATE = "500k" +MAX_TIME = 180 +THROTTLE_SECS = 60.0 +LIMIT_RATE = "200k" +EMPTY_BACKOFF = 120.0 def _redact_cmd(cmd: list[str]) -> str: @@ -75,11 +84,6 @@ def upload(path: Path, userhash: str) -> str: "-sS", "--max-time", str(MAX_TIME), - "--retry", - str(RETRIES), - "--retry-delay", - str(RETRY_DELAY), - "--retry-all-errors", "--limit-rate", LIMIT_RATE, "-F", @@ -93,13 +97,19 @@ def upload(path: Path, userhash: str) -> str: try: raw = subprocess.check_output(cmd, text=True, stderr=subprocess.STDOUT) except subprocess.CalledProcessError as exc: + time.sleep(EMPTY_BACKOFF) raise SystemExit( f"catbox upload failed for {path.name} " - f"(curl exit {exc.returncode}): {_redact_cmd(cmd)}" + f"(curl exit {exc.returncode}); waited {EMPTY_BACKOFF:.0f}s before exit. " + f"cmd: {_redact_cmd(cmd)}" ) from None url = raw.strip() if not url.startswith("https://"): - raise SystemExit(f"catbox refused {path.name}: {url[:200]}") + time.sleep(EMPTY_BACKOFF) + raise SystemExit( + f"catbox refused {path.name} (empty/non-URL body); " + f"waited {EMPTY_BACKOFF:.0f}s before exit. body[:200]={url[:200]!r}" + ) return url @@ -131,6 +141,14 @@ def rewrite_notes(notes_dir: Path, old_tokens: list[str], url: str) -> int: return changed +def persist(media_path: Path, data: dict) -> None: + media_path.write_text( + json.dumps(data, indent=2) + "\n", + encoding="utf-8", + newline="\n", + ) + + def main(argv: list[str] | None = None) -> int: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("--vault", type=Path, default=VAULT_ROOT) @@ -159,6 +177,7 @@ def main(argv: list[str] | None = None) -> int: publishable = [it for it in items if it.get("publish")] for i, item in enumerate(publishable): if i > 0 and not args.dry_run: + print(f"throttling {THROTTLE_SECS:.0f}s before next upload…") time.sleep(THROTTLE_SECS) name = str(item.get("filename") or "") src = args.thread / name @@ -175,9 +194,9 @@ def main(argv: list[str] | None = None) -> int: uploaded += 1 print(f"uploaded {name} -> {url}") rewrite_notes(args.notes, old, url) + persist(media_path, data) + print(f"persisted media.json ({uploaded} done so far)") - if not args.dry_run: - media_path.write_text(json.dumps(data, indent=2) + "\n", encoding="utf-8") print(f"uploaded {uploaded}") return 0 diff --git a/scripts/twitter/tw.py b/scripts/twitter/tw.py index f4743a7..ecfef09 100644 --- a/scripts/twitter/tw.py +++ b/scripts/twitter/tw.py @@ -251,6 +251,38 @@ def cmd_refresh(post_id: str, tip: bool, slug: str | None) -> int: return 0 +def cmd_sync(handle: str | None) -> int: + """Rebuild handle-index wikilinks from actual folder listing. + + Use after manual edits or a stale state. Idempotent. + """ + root = VAULT / "archive" / "threads" + targets = [root / handle] if handle else None + changed = 0 + for handle_dir in targets or sorted(root.iterdir()): + if not handle_dir.is_dir() or handle_dir.name.startswith("."): + continue + idx = handle_dir / "index.md" + if not idx.is_file(): + continue + text = idx.read_text(encoding="utf-8") + end = text.find("\n---", 3) + if end < 0: + continue + fm = text[: end + 4] + dirs = sorted(d.name for d in handle_dir.iterdir() if d.is_dir()) + links = "\n".join(f"- [[archive/threads/{handle_dir.name}/{d}]]" for d in dirs) + new = fm + "\n\n" + links + "\n" + if new != text: + idx.write_text(new, encoding="utf-8", newline="\n") + changed += 1 + print(f"rewrote {handle_dir.name}: {len(dirs)} dirs") + else: + print(f"ok {handle_dir.name}: {len(dirs)} dirs") + print(f"changed {changed}") + return 0 + + def cmd_publish(post_id: str) -> int: _assets, notes = locate(post_id) if notes is None: @@ -299,8 +331,12 @@ def main(argv: list[str] | None = None) -> int: default="umi", choices=("auto", "umi", "tesseract", "windows"), ) + sync = sub.add_parser( + "sync", help="rebuild handle-index wikilinks from actual folder listing" + ) + sync.add_argument("--handle", default=None, help="single handle, else all") args = parser.parse_args(argv) - post_id = args.id + post_id = getattr(args, "id", None) if args.cmd == "locate": return cmd_locate(post_id) if args.cmd == "graph": @@ -319,6 +355,8 @@ def main(argv: list[str] | None = None) -> int: return cmd_refresh(post_id, tip=args.tip, slug=args.slug) if args.cmd == "publish": return cmd_publish(post_id) + if args.cmd == "sync": + return cmd_sync(handle=args.handle) raise SystemExit(f"unknown {args.cmd}")