|
|
@@ -121,7 +121,8 @@
|
|
|
<div class="row"><label>R4 (back upper-right)</label><select class="back" data-i="1"></select></div>
|
|
|
<div class="row"><label>L5 (back lower-left)</label><select class="back" data-i="2"></select></div>
|
|
|
<div class="row"><label>R5 (back lower-right)</label><select class="back" data-i="3"></select></div>
|
|
|
- <p class="note">Back-paddle → button, applied in Xbox & Switch modes.</p>
|
|
|
+ <div class="row"><label>QAM (3 dots)</label><select id="qamMap"></select></div>
|
|
|
+ <p class="note">Back-paddle → button, applied in Xbox & Switch modes. QAM remap applies to all modes (0 = default per-mode behavior).</p>
|
|
|
</div>
|
|
|
|
|
|
<div class="card logonly">
|
|
|
@@ -143,7 +144,7 @@
|
|
|
<script>
|
|
|
const MODE_NAMES = ["Steam (puck)","Xbox 360","Switch (HORIPAD)","Lizard (always)","Switch Pro + gyro","PS5 DualSense","HID gyro (DS4)"];
|
|
|
const CHORD_FIELD = [17, 18, 19];
|
|
|
-const BTN_CODES = [[0,"— none —"],[1,"A"],[2,"B"],[3,"X"],[4,"Y"],[5,"LB"],[6,"RB"],[7,"L3"],[8,"R3"],[9,"Back"],[10,"Start"],[11,"Guide"],[12,"D-pad Up"],[13,"D-pad Down"],[14,"D-pad Left"],[15,"D-pad Right"]];
|
|
|
+const BTN_CODES = [[0,"— none —"],[1,"A"],[2,"B"],[3,"X"],[4,"Y"],[5,"LB"],[6,"RB"],[7,"L3"],[8,"R3"],[9,"Back"],[10,"Quick Access Menu"],[11,"Guide"],[12,"D-pad Up"],[13,"D-pad Down"],[14,"D-pad Left"],[15,"D-pad Right"],[16,"PS Touch Click"],[17,"PS5 Mute"]];
|
|
|
let dev=null, epIn=0, epOut=0, ifNum=0, polling=false, capturing=false;
|
|
|
const $ = s=>document.querySelector(s);
|
|
|
function log(m){ const l=$("#log"); l.textContent=(new Date().toLocaleTimeString()+" "+m+"\n"+l.textContent).slice(0,2000); }
|
|
|
@@ -152,6 +153,10 @@ function log(m){ const l=$("#log"); l.textContent=(new Date().toLocaleTimeString
|
|
|
for(const sel of document.querySelectorAll("select.back")){
|
|
|
for(const [c,n] of BTN_CODES){ const o=document.createElement("option"); o.value=c; o.textContent=n; sel.appendChild(o); }
|
|
|
}
|
|
|
+{ const sel = document.getElementById("qamMap");
|
|
|
+ const d = document.createElement("option"); d.value=0; d.textContent="Default (varies by mode)"; sel.appendChild(d);
|
|
|
+ for(const [c,n] of BTN_CODES){ if(c===0) continue; const o=document.createElement("option"); o.value=c; o.textContent=n; sel.appendChild(o); }
|
|
|
+}
|
|
|
for(const sel of document.querySelectorAll("select.chord")){
|
|
|
MODE_NAMES.forEach((n,i)=>{ const o=document.createElement("option"); o.value=i; o.textContent=n; sel.appendChild(o); });
|
|
|
}
|
|
|
@@ -211,7 +216,7 @@ async function readBlob(){
|
|
|
}
|
|
|
function applyBlob(p){
|
|
|
// [ver][mode][mDiv][mFric][rsvd][abSwap][b0..b3][slot][up][f1lo][f1hi][pollU100(unused)][newlo][newhi]
|
|
|
- const mode=p[1], mDiv=p[2], mFric=p[3], abSwap=p[5]; // p[4] reserved (ex-padSmooth)
|
|
|
+ const mode=p[1], mDiv=p[2], mFric=p[3], qamMap=p[4], abSwap=p[5]; // p[4] = QAM remap code (0 = default)
|
|
|
const back=[p[6],p[7],p[8],p[9]], slot=p[10], up=p[11], f1=(p[12]|(p[13]<<8));
|
|
|
const newps=(p.length>16?(p[15]|(p[16]<<8)):0), persistMode=(p.length>22?p[22]:0);
|
|
|
const chord=(p.length>25)?[p[23],p[24],p[25]]:[3,1,2]; // v2 blob: chordBtn after qos/persist
|
|
|
@@ -251,6 +256,7 @@ function applyBlob(p){
|
|
|
$("#abSwap").textContent = abSwap? "on":"off"; $("#abSwap").classList.toggle("active",!!abSwap);
|
|
|
$("#persistMode").textContent = persistMode? "on":"off"; $("#persistMode").classList.toggle("active",!!persistMode);
|
|
|
for(const sel of document.querySelectorAll("select.back")){ if(document.activeElement!==sel) sel.value=back[+sel.dataset.i]; }
|
|
|
+ { const sel=$("#qamMap"); if(document.activeElement!==sel) sel.value=qamMap; }
|
|
|
for(const sel of document.querySelectorAll("select.chord")){ if(document.activeElement!==sel) sel.value=chord[+sel.dataset.i]; }
|
|
|
}
|
|
|
function fmtSlider(id,v){ return ""+v; }
|
|
|
@@ -364,6 +370,7 @@ for(const id of ["mDiv","mFric"]){
|
|
|
for(const sel of document.querySelectorAll("select.back")){
|
|
|
sel.addEventListener("change", ()=>setField(5 + +sel.dataset.i, +sel.value));
|
|
|
}
|
|
|
+$("#qamMap").addEventListener("change", ()=>setField(21, +$("#qamMap").value));
|
|
|
for(const sel of document.querySelectorAll("select.chord")){
|
|
|
sel.addEventListener("change", ()=>setField(CHORD_FIELD[+sel.dataset.i], +sel.value));
|
|
|
}
|