lucky / index 18.html
Studytime171's picture
Duplicate from Studytime171/Lalitgangwani
89610f7
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>GBA.js - Touch Controls</title>
<link rel="stylesheet" href="resources/main.css">
<style>
body {
margin: 0;
padding: 0;
background: #000;
overflow: hidden;
height: 100vh;
touch-action: none;
}
#screen {
image-rendering: pixelated;
image-rendering: crisp-edges;
width: 100%;
height: auto;
max-height: 100vh;
display: block;
margin: 0 auto;
}
.touch-controls {
position: absolute;
inset: 0;
pointer-events: none;
z-index: 10;
touch-action: none;
user-select: none;
display: none; /* shown after game loads */
}
.dpad, .face {
position: absolute;
bottom: 8%;
pointer-events: auto;
}
.dpad {
left: 5%;
width: 160px;
height: 160px;
}
.face {
right: 5%;
width: 200px;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 12px;
}
.ctrl-btn {
background: rgba(140,140,140,0.4);
border: 3px solid rgba(240,240,240,0.65);
border-radius: 50%;
color: white;
font-weight: bold;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.2rem;
box-shadow: 0 3px 12px rgba(0,0,0,0.5);
transition: all 0.1s ease;
}
.ctrl-btn:active,
.ctrl-btn.pressed {
transform: scale(0.88);
opacity: 0.7;
background: rgba(220,220,220,0.65);
}
/* D-pad shapes */
#up { width:70px; height:70px; position:absolute; left:45px; top:0; border-radius:14px 14px 50% 50%; }
#down { width:70px; height:70px; position:absolute; left:45px; bottom:0; border-radius:50% 50% 14px 14px; }
#left { width:70px; height:70px; position:absolute; top:45px; left:0; border-radius:14px 50% 50% 14px; }
#right { width:70px; height:70px; position:absolute; top:45px; right:0; border-radius:50% 14px 14px 50%; }
#center{ width:70px; height:70px; position:absolute; left:45px; top:45px; background:transparent; border:none; pointer-events:none; }
/* Buttons */
#a { background:rgba(0,200,0,0.55); grid-column:3; grid-row:2; border-radius:50%; width:80px; height:80px; font-size:1.6rem; }
#b { background:rgba(220,0,0,0.55); grid-column:2; grid-row:3; border-radius:50%; width:80px; height:80px; font-size:1.6rem; }
#l { background:rgba(80,80,255,0.55); grid-column:1; grid-row:1; width:70px; height:55px; border-radius:12px; font-size:1.1rem; }
#r { background:rgba(80,80,255,0.55); grid-column:3; grid-row:1; width:70px; height:55px; border-radius:12px; font-size:1.1rem; }
#start { background:rgba(220,220,60,0.65); grid-column:2/4; grid-row:1; width:auto; height:50px; border-radius:12px; font-size:1rem; }
#select{ background:rgba(220,220,60,0.65); grid-column:1/3; grid-row:1; width:auto; height:50px; border-radius:12px; font-size:1rem; }
@media (orientation: landscape) and (min-width: 900px) {
.touch-controls { display: none !important; } /* optional: hide on large landscape */
}
</style>
</head>
<body>
<canvas id="screen" width="480" height="320"></canvas>
<div id="touch-controls" class="touch-controls">
<!-- D-Pad -->
<div class="dpad">
<div id="up" class="ctrl-btn" data-bit="6"></div>
<div id="down" class="ctrl-btn" data-bit="7"></div>
<div id="left" class="ctrl-btn" data-bit="5"></div>
<div id="right" class="ctrl-btn" data-bit="4"></div>
<div id="center"></div>
</div>
<!-- Face / shoulder / menu buttons -->
<div class="face">
<div id="l" class="ctrl-btn" data-bit="9">L</div>
<div id="select" class="ctrl-btn" data-bit="2">Select</div>
<div id="start" class="ctrl-btn" data-bit="3">Start</div>
<div id="r" class="ctrl-btn" data-bit="8">R</div>
<div id="b" class="ctrl-btn" data-bit="1">B</div>
<div id="a" class="ctrl-btn" data-bit="0">A</div>
</div>
</div>
<section id="controls">
<div id="preload">
<button class="bigbutton" id="select" onclick="document.getElementById('loader').click()">SELECT</button>
<input id="loader" type="file" accept=".gba" onchange="run(this.files[0]);">
<button onclick="document.getElementById('saveloader').click()">Upload Savegame</button>
<input id="saveloader" type="file" onchange="uploadSavedataPending(this.files[0]);">
</div>
<div id="ingame" class="hidden">
<button id="pause" class="bigbutton" onclick="togglePause()">PAUSE</button>
<button class="bigbutton" onclick="reset()">RESET</button>
<button onclick="gba.downloadSavedata()">Download Savegame</button>
<button onclick="screenshot()">Screenshot</button>
<label id="pixelated">
<input type="checkbox" onchange="setPixelated(this.checked)">
<p>Pixelated</p>
</label>
<div id="sound">
<input type="checkbox" checked onchange="gba.audio.masterEnable = this.checked">
<p>Sound</p>
<input type="range" min="0" max="1" value="1" step="any" onchange="setVolume(this.value)" oninput="setVolume(this.value)">
</div>
<p id="openDebug" onclick="enableDebug()">Debugger</p>
</div>
</section>
<script src="js/util.js"></script>
<script src="js/core.js"></script>
<script src="js/arm.js"></script>
<script src="js/thumb.js"></script>
<script src="js/mmu.js"></script>
<script src="js/io.js"></script>
<script src="js/audio.js"></script>
<script src="js/video.js"></script>
<script src="js/video/proxy.js"></script>
<script src="js/video/software.js"></script>
<script src="js/irq.js"></script>
<script src="js/keypad.js"></script>
<script src="js/sio.js"></script>
<script src="js/savedata.js"></script>
<script src="js/gpio.js"></script>
<script src="js/gba.js"></script>
<script src="resources/xhr.js"></script>
<script>
// Your original script (slightly cleaned + touch integration)
var gba;
var runCommands = [];
var debug = null;
try {
gba = new GameBoyAdvance();
gba.keypad.eatInput = true;
gba.setLogger(function(level, error) {
console.log(error);
gba.pause();
var screen = document.getElementById('screen');
if (screen.getAttribute('class') == 'dead') return;
var crash = document.createElement('img');
crash.id = 'crash';
crash.src = 'resources/crash.png';
screen.parentElement.insertBefore(crash, screen);
screen.className = 'dead';
});
} catch (e) {
gba = null;
}
window.onload = function() {
if (gba && FileReader) {
var canvas = document.getElementById('screen');
gba.setCanvas(canvas);
gba.logLevel = gba.LOG_ERROR;
// Optional BIOS load - uncomment if you have it
// loadRom('resources/bios.bin', bios => gba.setBios(bios));
if (!gba.audio.context) {
var soundbox = document.getElementById('sound');
if (soundbox && soundbox.parentElement) soundbox.parentElement.removeChild(soundbox);
}
} else {
var dead = document.getElementById('controls');
if (dead && dead.parentElement) dead.parentElement.removeChild(dead);
}
};
// ──────────────────────────────────────────────
// Your original functions (fadeOut, run, reset, etc.)
// ──────────────────────────────────────────────
function fadeOut(id, nextId, kill) {
var e = document.getElementById(id);
var e2 = document.getElementById(nextId);
if (!e) return;
var removeSelf = function() {
if (kill) e.parentElement?.removeChild(e);
else {
e.className = 'dead';
e.removeEventListener('transitionend', removeSelf);
}
if (e2) {
e2.className = 'hidden';
setTimeout(() => e2.removeAttribute('class'), 0);
}
};
e.addEventListener('transitionend', removeSelf);
e.className = 'hidden';
}
function run(file) {
document.getElementById('loader').value = '';
var load = document.getElementById('select');
load.textContent = 'Loading...';
load.removeAttribute('onclick');
var pause = document.getElementById('pause');
pause.textContent = "PAUSE";
gba.loadRomFromFile(file, function(result) {
if (result) {
runCommands.forEach(cmd => cmd());
runCommands = [];
fadeOut('preload', 'ingame');
fadeOut('instructions', null, true);
gba.runStable();
// Show touch controls
document.getElementById('touch-controls').style.display = 'block';
} else {
load.textContent = 'FAILED';
setTimeout(() => {
load.textContent = 'SELECT';
load.onclick = () => document.getElementById('loader').click();
}, 3000);
}
});
}
// ... keep your other functions (reset, togglePause, screenshot, setVolume, setPixelated, enableDebug, etc.) ...
// ──────────────────────────────────────────────
// TOUCH CONTROLS - DIRECT KEYPAD BIT MANIPULATION
// ──────────────────────────────────────────────
if ('ontouchstart' in window || navigator.maxTouchPoints > 0) {
if (gba?.keypad) {
const keypad = gba.keypad;
const pressed = new Set();
document.querySelectorAll('.ctrl-btn[data-bit]').forEach(el => {
const bit = parseInt(el.dataset.bit, 10);
const toggle = 1 << bit;
const press = () => {
if (!pressed.has(el.id)) {
pressed.add(el.id);
keypad.currentDown &= ~toggle; // press = clear bit
}
el.classList.add('pressed');
};
const release = () => {
if (pressed.has(el.id)) {
pressed.delete(el.id);
keypad.currentDown |= toggle; // release = set bit
}
el.classList.remove('pressed');
};
el.addEventListener('touchstart', e => { e.preventDefault(); press(); }, { passive: false });
el.addEventListener('touchend', e => { e.preventDefault(); release(); }, { passive: false });
el.addEventListener('touchcancel',e => { e.preventDefault(); release(); }, { passive: false });
});
console.log("Touch controls activated (direct keypad mode)");
} else {
console.warn("gba.keypad not available β†’ touch controls disabled");
}
}
</script>
</body>
</html>