Changelog
Every shipped change, newest first. Sourced from CHANGELOG.md in the repo.
- 2026-11-01
Betrieb
- ·Bessere Nutzungsstatistik. Matomo zählt jetzt jeden Seitenwechsel innerhalb der App, nicht nur die erste Seite eines Besuchs, und misst die Verweildauer. Dazu kommen anonyme Zähler für Preset laden, herunterladen und veröffentlichen, die MIDI-Verbindung, das Senden ans Gerät, die Registrierung und Feedback. Es bleibt cookielos und respektiert „Do Not Track“.
- 2026-10-31
Features
- ·Feedback-Formular. Unter
/feedbackkönnen angemeldete Nutzer mit bestätigter E-Mail-Adresse Bugs melden, Features vorschlagen oder allgemeines Feedback geben. Der Button sitzt gut sichtbar in der Navigation und ist auf der Startseite sowie im Footer verlinkt. Bei Bug-Reports werden die Seite, von der man kommt, und die Browser-Version mitgeschickt.
Betrieb
- ·Health-Check.
/api/healthmeldet, ob App, Datenbank und Dateispeicher erreichbar sind. Docker und das Deploy-Skript nutzen ihn; ein Deploy, bei dem DB oder Speicher nicht erreichbar sind, wird zurückgerollt.
Fix
- ·E-Mails kommen in der richtigen Sprache. Die Registrierung hat die gewählte Sprache nicht gespeichert, deshalb gingen Bestätigungs- und Erinnerungsmails immer auf Englisch raus.
- ·Navigation läuft auf schmalen Bildschirmen nicht mehr über. Unter 1280 px Breite gibt es jetzt das Hamburger-Menü statt einer abgeschnittenen Linkzeile.
- ·Eigene Share-Seite lädt wieder. Wer die Share-Seite des eigenen Presets aufrief, bekam seit Einführung der Audio-Schnipsel eine Fehlerseite.
- ·Login- und Registrierungsdaten landen nicht mehr in der URL. Wer das Formular abschickte, bevor die Seite fertig geladen war, schickte die Eingaben als URL-Parameter. Der Button ist jetzt bis dahin gesperrt.
- ·Feedback-Formular. Unter
- 2026-10-22
Security
- ·Next.js 15.5.28. Schließt u. a. eine kritische Remote-Code-Execution-Lücke in der Bildoptimierung (SVG/AVIF), DoS/SSRF über Server Actions und Cache-Poisoning bei SSG/ISR-Seiten.
- ·sharp 0.35.5. Aktualisiert libvips, libheif und librsvg — relevant, weil hochgeladene Avatare mit sharp verarbeitet werden.
- ·music-metadata 11.16.1. Behebt mehrere Parser-DoS-Lücken, die über präparierte Audio-Schnipsel erreichbar waren.
- ·nodemailer 10. Behebt Header-Injection, DoS im Adress-Parser und einen prozessweiten TLS-Servername-Cache.
Inhalte
- ·Firefox wird als unterstützter Browser genannt. Hilfe, FAQ und Guides sagten noch, Live-MIDI laufe nur in Chrome/Edge. Firefox 108+ funktioniert: Beim ersten Verbinden bietet Firefox ein einmaliges MIDI-Add-on an, danach fragt es die MIDI-Berechtigung ab.
- ·Hilfe-Seite erklärt aktuelle Funktionen. Neu: Live-Übertragung beim Preset-Laden, EXP-/Controller-Zuweisungen, Umsortieren per Tastatur, Audio-Schnipsel, Kommentare und Bewertungen, Guides. Der veraltete Mini-Changelog auf der Hilfe-Seite verweist jetzt auf diese Seite.
Datenschutz
- ·Fehlerprotokoll mit Löschfrist. Einträge im Fehlerprotokoll enthalten IP-Adresse und ggf. Benutzer-ID. Sie werden jetzt 30 Tage nach dem letzten Auftreten automatisch gelöscht; ältere IP-Adressen werden nicht mehr in neue Einträge übernommen.
- ·Datenschutzerklärung ergänzt — um Fehlerprotokoll, Sprach-Cookie, Audio-Schnipsel sowie öffentliche Kommentare und Bewertungen. Die Aussage „verschlüsselt gespeichert“ wurde entfernt, weil sie technisch nicht zutraf.
- 2026-10-17
Features
- ·Guides in EN, DE, ES und PT-BR. Ausführliche Anleitungen zum GP-200-Editor und zum
.prst-Format unter/guides.
SEO
- ·
/en/…leitet dauerhaft (308) auf die englische URL ohne Präfix um. Galerie-Karten verlinken direkt die Share-Seite. Share- und Amp-Seiten haben kürzere, aussagekräftigere Titel und Beschreibungen in allen 7 Sprachen.
- ·Guides in EN, DE, ES und PT-BR. Ausführliche Anleitungen zum GP-200-Editor und zum
- 2026-08-31
Fix
- ·Admin-Nutzerliste — zeigt die echte Preset-Anzahl und markiert unbestätigte E-Mail-Adressen.
- 2026-08-05
Features
- ·Unterstützen-Button — ist in Navigation und Footer deutlicher sichtbar.
- 2026-07-31
SEO
- ·Englisch läuft ohne Sprachpräfix — (
/helpstatt/en/help). Canonicals zeigen jetzt auf echte Seiten statt auf Weiterleitungen; die Sitemap enthält nur noch Seiten mit eigenem Inhalt.
Fix
- ·Fehlender Upload-Button-Text — auf der Startseite in allen 7 Sprachen ergänzt.
- ·Englisch läuft ohne Sprachpräfix — (
- 2026-07-04
Fix
- ·Umsortierte Presets landen korrekt auf dem Gerät (#90). Live-Push und Save-to-Slot adressierten Blöcke nach Listenposition statt nach fester Block-Identität (PRE…VOL). Bei umsortierten Presets landeten Effekte, Parameter und An/Aus-Zustand deshalb auf dem falschen Block. Die Reihenfolge wird jetzt separat ans Gerät gesendet.
- ·Routing-Reihenfolge geht beim Laden nicht mehr verloren. Ein einzelnes ungültiges Routing-Byte setzte bisher die ganze Kette auf Standard-Reihenfolge zurück. Gültige Einträge bleiben jetzt erhalten, fehlende werden angehängt.
- 2026-06-28
Fix
- ·Preset-Laden überträgt alle Parameter zuverlässig (#80). Beim Laden einer
.prst-Datei mit verbundenem Gerät wird das Preset jetzt tatsächlich gesendet. Nach jedem Effektwechsel wartet der Editor, bis das Gerät umgeschaltet hat. Parameter gehen mit 40 ms Abstand und in zwei Durchgängen raus, weil das Gerät schnelle Bursts teilweise verwirft.
Features
- ·Fortschrittsanzeige beim Übertragen. Die Übertragung blockiert die Oberfläche nicht mehr. Wer währenddessen ein anderes Preset lädt, bricht die laufende Übertragung ab.
- ·Preset-Laden überträgt alle Parameter zuverlässig (#80). Beim Laden einer
- 2026-06-18
Fix
- ·Preset-Laden überträgt jetzt den Effekt-Typ ans Gerät (#80). Beim Laden einer
.prst-Datei – und beim Speichern in einen Slot – sendete der Editor nur Toggle, Parameter und Author per USB-MIDI, aber nie den Effekt-Typ selbst (SysExsub=0x14). Das Gerät behielt dadurch seinen zuvor geladenen Algorithmus pro Block, sodass Parameter und An/Aus-Zustand auf dem falschen Effekt landeten (die App zeigte z. B. „UK 800", während das Gerät noch „Tweedy" hatte und keine Werte übernahm). Beide Sync-Pfade senden jetzt pro Block in der Reihenfolge Effektwechsel → Parameter → Toggle, mit kurzer Settling-Pause, damit das Gerät den Algorithmus umschalten kann, bevor die Parameter ankommen.
- ·Preset-Laden überträgt jetzt den Effekt-Typ ans Gerät (#80). Beim Laden einer
- 2026-05-19
Security
- ·Admin-Flag wird auf allen öffentlichen Read-Paths enforced. Gallery,
/api/share/[token],/share/[token]/download,/share/[token]/jsonund Sitemap filtern jetzt zusätzlich aufflagged: false. Bis hierher konnte ein admin-geflaggtes Preset weiter ausgeliefert und von Googlebot gecrawlt werden — Moderation entzieht Inhalte jetzt tatsächlich. - ·
fast-xml-builderHIGH-Advisory geschlossen — (GHSA-5wm8-gmm8-39j9, CVSS 6.1) durchnpm update @aws-sdk/client-s3. Erreichte prod via@aws-sdk/xml-builder. - ·Admin-PATCH-User akzeptiert keine Email-Änderung mehr. Bisher konnte ein kompromittierter Admin-Account Victim-Emails überschreiben und sofort einen Password-Reset triggern → Account-Takeover. Email-Änderungen brauchen jetzt einen Out-of-Band-Weg.
- ·Avatar-Upload gehärtet: Magic-Byte-Probe (JPEG/PNG/WebP Signaturen),
limitInputPixels: 25 Mund try/catch umsharp()— eine PNG-Bombe oder umbenannte Binärdatei erzeugt jetzt 400 statt 500 mit CPU-/RAM-Spike. - ·Avatar-Cache
immutableentfernt — (Cache-Control: public, max-age=3600). Eine Admin-User-Löschung wirkt jetzt innerhalb einer Stunde an jedem Cache-Layer.
Fix
- ·Middleware-Auth-Guard erkennt
pt-BR. Die Regex(de|en|es|fr|it|pt)war beim Locale-Add nicht mitgezogen worden, sodass/pt-BR/profile&/pt-BR/adminden Cookie-Presence-Check der Middleware übersprangen. Page-Level-validateSessionhat es abgefangen — kein Datenleck —, aber Defense-in-Depth weg. Regex wird jetzt ausLOCALESgeneriert; Test stellt sicher, dass jeder Eintrag der LOCALES-Tuple gematcht wird. - ·
/api/admin/commentsnutztwithAdminAuth-Wrapper — statt manuellemtry/catch(requireAdmin)— konsistent zu allen anderen/api/admin/*Routen.
- ·Admin-Flag wird auf allen öffentlichen Read-Paths enforced. Gallery,
- 2026-05-19
Features
- ·30 s Audio-Schnipsel pro Preset. Owner können beim Save-to-Gallery oder nachträglich auf
/share/[token]ein MP3- oder M4A/AAC-File (max 30 s, max 2 MB) anhängen. Player erscheint auf der Share-Page (voll), im Homepage-Featured-Block und auf jeder Gallery-Card (Icon). Nur ein Player spielt gleichzeitig — Klick auf einen Card-Play pausiert alle anderen. - ·Admin-Audit für fremdes Audio. Wenn ein Admin Audio eines fremden Presets ersetzt oder löscht, wird die Aktion mit Reason (bei Delete) im AdminAction-Log auditiert.
Storage / Validation
- ·Neuer Garage S3-Bucket
gp200editor-audio. Server prüft Mime + Magic Bytes + Größe (≤ 2 MB) + Dauer (≤ 30.5 s viamusic-metadata) vor jedem S3 PUT.
Schema
- ·Drei neue nullable Felder auf
Preset:audioKey,audioMimeType,audioDurationMs.
- ·30 s Audio-Schnipsel pro Preset. Owner können beim Save-to-Gallery oder nachträglich auf
- 2026-05-19
Features
- ·Brasilianisches Portugiesisch (pt-BR) als 7. Locale. Vorher war
pt.jsonfaktisch brasilianisch übersetzt (Salvar/Senha/usuário/arquivo); der Inhalt wandert nachpt-BR.jsonund steht jetzt brasilianischen Nutzern als eigenes Locale mit 🇧🇷-Flag im Switcher zur Verfügung.pt.jsonwurde mit ~175 gezielten Substitutionen auf echtes europäisches Portugiesisch konvertiert (Guardar/Palavra-passe/utilizador/ficheiro/Iniciar sessão/A guardar/A carregar/Ligar/Registo/Rastreio).
i18n-Polish (Sprach-Review aller 7 Locales)
- ·DE/IT: 4 Admin-Buttons (
Unpublish/Republish/Flag/Unflag) waren noch englisch — jetzt übersetzt. - ·DE:
home.featured.titlehatte den „Featured ·"-Präfix verloren — wieder dran. - ·IT:
home.featured.titlehatte „Top Rated" englisch — jetzt „Più votati". - ·FR: tu/vous-Inkonsistenz behoben — drei FAQ-Antworten + zwei Tooltips + die Verify-Confirm-Seite waren in
vous, während die App sonsttunutzt. E-Mail-Templates bleiben bewusst invous(formaler Kontext). - ·PT-BR: Ein EU-PT-Slip in
gallery.rate.ownPresetTooltipkorrigiert.
Fix
- ·Übersetzungs-Skript-Bug korrigiert. Beim BR→EU-Sweep der
legal.privacyOverviewTextwurde „salvo quando exigido por lei" (im Sinne von „außer wenn") fälschlich zu „guardado quando exigido por lei" umgeschrieben. Zurückgedreht.
- ·Brasilianisches Portugiesisch (pt-BR) als 7. Locale. Vorher war
- 2026-05-19
Security
- ·Comments leak after un-publish — fixed.
GET /api/presets/[id]/commentsnow refuses to return the thread when the preset has been made non-public or flagged. POST top-level + Reply gained the same gate (Reply previously checked neither). Anyone who had the preset id from a previous public link can no longer continue reading a thread the author tried to retract. - ·Featured-Preset Sybil-Dampening verstärkt. Bayes-Konstante
mvon 5 auf 10 — eine einzelne 5★-Bewertung von einem Accomplice-Account scoret jetzt nur noch ~4.09 (statt 4.17) und schiebt sich nicht mehr vor etablierte Presets mit echtem Rating-Verlauf.
Bugfixes
- ·Inline-Rating Optimistic-UI ohne Rollback — bei fehlgeschlagenem POST blieb die UI bei der Phantom-Bewertung. Snapshot+Restore +
errorTooltip-Toast. - ·Comment-Textarea verlor Inhalt bei 429/Auth-Fail —
CommentFormclear jetzt nur bei Success; bei Fehler steht der Text zum Retry da. - ·CommentSection swallowed 401/5xx silently — separate Toasts für Rate-Limit, Session-Expired und generischen Fehler.
- ·Gallery-Rating Page 2+ zeigte falschen Count — bereits-bewertete Presets jenseits der ersten SSR-Page bekamen
existingRating=0, was bei Re-Rating zu Phantom-Counts führte. Session-Lookup zog ans/api/gallery-Endpoint, jede Card trägt jetzt korrekte Rating-Context. - ·AdminCommentsTab hatte keine Pagination-UI — alle Comments jenseits der ersten 50 waren unerreichbar. Load-More-Button + In-Flight-Guard.
UI / i18n
- ·Confirm-Dialog vor User-Soft-Delete. Klick auf „Delete" beim eigenen Kommentar öffnet jetzt einen Bestätigungsdialog (Soft-Delete ist nicht reversibel —
bodywird genullt). Admin-Hard-Delete behält seinen separaten Reason-Dialog. - ·Drei hardcoded englische Strings korrigiert — (
CommentsHeader,Email verification required, Admin-Cancel-Button) — jetzt in allen 6 Locales übersetzt. - ·Toter i18n-Key entfernt — (
comments.adminDeleteReasonLabel— Admin-Tab nutztadmin.comments.hardDeleteReasonLabel).
Schema / Performance
- ·Index
Comment(createdAt DESC)— die Admin-Moderation-Liste sortiert ohnepresetId-Filter; der bisherige Compound-Index half nicht. Cheap forward-looking change. - ·Shared
commentSerializer— Avatar-Mapping (avatarKey → /api/avatar/<key>) lebt jetzt insrc/lib/commentSerializer.ts; PATCH gab bisher den Raw-avatarKeyzurück, alle anderen Routes serialisierten zuavatarUrl. Inkonsistenz behoben.
- ·Comments leak after un-publish — fixed.
- 2026-05-18
Features
- ·Inline-Rating in der Gallery — Bewertungen können direkt auf der Gallery-Liste abgegeben werden. Anonyme Klicks zeigen einen Tooltip mit Login-Link; eigene Presets sind erwartungsgemäß nicht bewertbar.
- ·Kommentare auf Share-Pages — Plaintext-Kommentare mit 1-Level-Threading (Top-Level + Reply), max 1000 Zeichen, URLs werden automatisch verlinkt (
rel=nofollow). Verifizierte User können kommentieren, jederzeit editieren und soft-löschen. Soft-Delete zeigt einen Platzhalter, Replies bleiben sichtbar. - ·Admin-Moderation für Kommentare — Neuer Tab im Admin-Dashboard: Liste der letzten 50 Kommentare. Hard-Delete erfordert einen Grund (5–200 Zeichen) und wird im AdminAction-Log auditiert; kaskadiert auf Replies.
- ·Featured Preset auf der Startseite — Bayes-Average (m=5, C=globaler Durchschnitt) über alle Presets mit Ratings der letzten 30 Tage. Hero-Block mit Signal-Chain-Grafik (Amp/Cab-Realnamen), Sternebewertung, Beschreibung und den 3 neuesten Kommentaren. Fallback auf All-Time-Best wenn das 30-Tage-Fenster leer ist.
- ·FX-Loop SEND/RETURN editor — neuer Insertion-Point-Editor analog zum offiziellen Valeton GP-200 Editor. Pfeile (
↗SEND,↘RETURN) lassen sich per Drag & Drop oder Tastatur (←/→) zwischen den 11 Effekt-Slots (PRE…VOL) verschieben. Bypass-Anzeige wenn SEND === RETURN. ARIA-konform (role="slider", vollständige Screenreader-Labels in allen 6 Sprachen). - ·Live MIDI für FX-Loop — SEND/RETURN-Bewegungen werden bei verbundenem Gerät sofort als SysEx
sub=0x20ans Pedal geschickt. Push-Constraint (SEND ≤ RETURN) feuert bei Bedarf zwei Messages, um beide Pfeile synchron zu halten. - ·
.prstCodec für FX-Loop — SEND/RETURN werden an Bytes0x92/0x93(innerhalb des Routing-Section-Headers) gelesen und geschrieben. Round-Trip-stabil, inkl.rawSource-basierter Presets.
Schema
- ·Neue Tabelle
Comment— mit Self-FK für 1-Level-Threading (parentIdnullable), Soft-Delete-Marker (deletedAt/deletedBy), Cascade-Delete bei Preset/User/Parent-Removal.
Protocol
- ·
sub=0x20Reorder vs. FX-Loop Move differenziert —decoded[14]/[15]halten SEND/RETURN (vorher fälschlich als Konstanten markiert);decoded[27]ist ein Diskriminator:0x08= SEND verschoben,0xBA= RETURN verschoben,0x44= reine Routing-Umordnung. Reverse-engineered aus zwei USB-MIDI-Captures (2026-05-18), byte-für-byte verifiziert.
- 2026-04-11
Features
- ·PRST Library + JSON API — 145 curated Valeton GP-200 presets ingested from guitarpatches.com, each served with real-world amp/cab names (e.g. "Marshall® JCM800", "Fender® '65 Twin Reverb"). New
/api/share/[token]/jsonendpoint serves a round-trip JSON document with signal chain, highlights, and raw preset data. - ·SEO-crawlable signal chain on share pages — every share page now renders the full effect chain as semantic HTML with both Valeton fake names and real-world brand names. Google rich results supported via schema.org/Product markup per preset.
- ·Amp category landing pages — 64 new pages at
/[locale]/amp/[slug](e.g./en/amp/marshall-jcm800,/en/amp/mesa-boogie-dual-rectifier-modern-mode), each listing all presets using that amp. Pre-rendered for both locales. - ·hreflang + canonical + JSON-LD — every share page gets
<link rel="alternate" hreflang>for de/en/x-default,<link rel="canonical">, schema.org/Product JSON-LD with auto-extracted brand, Open Graph + Twitter Card metadata. - ·Dynamic Open Graph images — 1200×630 PNG per share page generated on demand via Next.js 15
ImageResponse, showing preset name + amp + cab real names with Preset Forge branding. - ·Ingest pipeline — new
scripts/ingest-presets.tsCLI with four source adapters: guitarpatches.com (polite 10s crawl delay), GitHub Code Search, Valeton factory folder, and a manual curated-URL list. Automatic validation (TSRP magic + checksum), dedup by source URL + sha256 content hash, auto-generated descriptions + tags. - ·Sitemap coverage — 586 URLs including 128 amp category pages, 450 preset URLs (de/en/json), and 8 static pages. Force-dynamic so newly-ingested presets become indexable without redeploying.
Bugfixes
- ·Decoder NaN handling — real .prst files from guitarpatches.com carry NaN bytes in unused effect params; the decoder now substitutes 0 so validation doesn't drop ~10% of the library.
- ·Factory-size checksum — 1176-byte factory presets no longer trip the out-of-bounds read at offset 0x4C6.
- ·Description generator —
generateDescriptionno longer produces "cabinet cabinet" when the real name already contains the module label. - ·metadataBase — Open Graph image URLs now resolve to
https://preset-forge.com/...instead ofhttp://localhost:3000/....
Local CI
- ·GitHub Actions removed — replaced with
scripts/local-ci.shrunning lint + typecheck + vitest + next build locally. Newnpm run cientry point.
Performance + Security (pre-library)
- ·Paginated
GET /api/presetsand/presetsSSR page (default 100, max 500) — previously unbounded. - ·Capped
sitemap.xmlquery at 10 000 rows withorderBy: updatedAt desc. - ·Memoized
getEffectParamslookup inEffectParams. - ·Middleware regex compilation moved to module scope (single pattern instead of three per request).
- ·
next-intlupgraded to 4.9.1 (GHSA-8f24-v5vv-gm5j open redirect). - ·
DELETE /api/admin/users/[id]refuses to delete admins — forces an auditable PATCH demotion first. - ·Per-IP rate limit on
/api/auth/forgot-passwordalongside the existing per-email limit, closing the account enumeration side-channel.
- ·PRST Library + JSON API — 145 curated Valeton GP-200 presets ingested from guitarpatches.com, each served with real-world amp/cab names (e.g. "Marshall® JCM800", "Fender® '65 Twin Reverb"). New
- 2026-03-24
Features
- ·Live param updates from hardware — When the user turns knobs on the GP-200 (Volume, Gain, Presence, Bass, Middle, Treble), sliders update in real-time in the webapp. New sub=0x10 D→H knob notification parsing with discriminator (bytes[29:37]=all zeros = knob, otherwise = toggle).
- ·AMP Head Panel — New
AmpHeadPanelcomponent showing the AMP block's main knobs (Gain/Presence/Volume + Bass/Middle/Treble) prominently at the top of the editor. Auto-detects AMP model from preset. - ·Collapsible head sections — AMP Head, Preset Info + Patch Settings, and Controller sections can be independently toggled via a button bar at the top of the editor.
- ·Auto-load preset names — After device connect, all 256 preset names load automatically in the background. Previously required opening the slot browser first.
Bugfixes
- ·Correct initial slot detection — State dump decoded[8:10] LE16 contains the active slot. Previously always returned slot 0. Verified via captures 084047 (slot 13/04-B) and 084156 (slot 0/01-A).
- ·Bank switching on device slot change — When device changes to a slot in a different bank, editor now pulls the entire new bank and switches tab. Previously loaded wrong preset into wrong tab.
- ·MIDI operation serialization — Background
loadPresetNamesno longer conflicts withpullPreset/pushPreset. AddedpauseNameLoading()that aborts name loader before any pull/push/write operation. - ·Nibble-encode slot for slots > 127 — SysEx data bytes must be 0-127. Slot 252 (64-A) was sent as raw 0xFC (invalid). Now nibble-encoded at [25:26] in
buildPresetChangeand decoded inonMidiMessage. - ·Status bar shows editor preset name —
currentPresetNamefrom editor takes priority over stale cachedpresetNames. - ·ControllerPanel visible when disconnected — Shows at 50% opacity instead of hidden.
- ·Cache-Control no-store in dev mode — Prevents browser from serving stale JS after code changes.
Protocol
- ·State dump header decoded — decoded[0:10]: constants + active slot at [8:10] LE16. Verified via captures 084047 (slot 13/04-B) and 084156 (slot 0/01-A).
- ·D→H Knob notification (sub=0x10) byte[22]=block, byte[24]=param, [29:37]=zeros discriminator, [37:45]=nibble float32 value. AMP block=3: param 0=Gain, 1=Presence, 2=Volume, 3=Bass, 4=Middle, 5=Treble.
- 2026-03-23
Features
- ·EXP controller assignments — Hardware-verified EXP1/EXP2 parameter selection + min/max via SysEx (sub=0x14 + sub=0x18).
- ·NAM upload analysis — Captured IR upload protocol (sub=0x1C, multi-chunk).
- ·Patch Settings — VOL/PAN/Tempo live editing via sub=0x10.
Protocol
- ·Save-to-Slot sub-slot index — decoded[4] = A(0)/B(1)/C(2)/D(3). Without this, save always wrote to slot A.
- ·Effekt-Change-Response (sub=0x0C) Block index, effect ID decoded from D→H notification.
- ·EXP/Controller Assignment — Navigation (sub=0x18) + Min/Max write (sub=0x14), hardware-verified.