lucky / index 23.html
Studytime171's picture
Duplicate from Studytime171/Lalitgangwani
89610f7
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>GBA.js - Mobile Friendly</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<style>
body {
margin: 0;
padding: 0;
background: #111;
font-family: Arial, sans-serif;
overflow: hidden;
touch-action: none;
}
#screen {
display: block;
width: 100%;
height: auto;
image-rendering: pixelated;
}
#touchControls {
position: absolute;
inset: 0;
pointer-events: none;
z-index: 20;
padding: 10px;
box-sizing: border-box;
display: none;
}
.control-row {
display: flex;
justify-content: space-between;
align-items: flex-end;
height: 100%;
pointer-events: none;
}
.touch-btn, .face-btn, .shoulder-btn, .action-btn {
background: rgba(70,70,70,0.7);
color: white;
font-weight: bold;
border: none;
border-radius: 12px;
touch-action: manipulation;
-webkit-tap-highlight-color: transparent;
box-shadow: 0 3px 10px rgba(0,0,0,0.5);
user-select: none;
}
/* D-Pad */
#dpad {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
gap: 6px;
width: 38%;
max-width: 170px;
aspect-ratio: 1 / 1;
pointer-events: auto;
}
#dpad button {
font-size: clamp(1.8rem, 9vw, 2.6rem);
}
/* Face buttons (A/B) */
.face-btn {
width: clamp(64px, 18vw, 90px);
height: clamp(64px, 18vw, 90px);
border-radius: 50%;
font-size: clamp(1.9rem, 8vw, 2.6rem);
}
#a { background: rgba(220, 40, 40, 0.75); }
#b { background: rgba(40, 100, 220, 0.75); }
/* Shoulders L/R */
.shoulder-btn {
width: clamp(54px, 15vw, 80px);
height: clamp(34px, 9vw, 44px);
font-size: clamp(1.1rem, 4.5vw, 1.4rem);
border-radius: 8px;
background: rgba(110,110,110,0.75);
}
/* Start/Select */
.action-btn {
width: clamp(68px, 18vw, 90px);
height: clamp(38px, 10vw, 48px);
font-size: clamp(1rem, 4vw, 1.3rem);
border-radius: 10px;
background: rgba(50, 140, 50, 0.75);
}
/* Layout tweaks for very small screens */
@media (max-width: 380px) {
#dpad { max-width: 140px; gap: 5px; }
.face-btn { width: 62px; height: 62px; font-size: 1.8rem; }
.shoulder-btn { width: 50px; height: 32px; }
.action-btn { width: 64px; height: 36px; font-size: 0.95rem; }
}
@media (min-width: 700px) {
#dpad { max-width: 210px; }
.face-btn { width: 100px; height: 100px; font-size: 2.8rem; }
}
#controls {
position: absolute;
top: 8px;
left: 8px;
z-index: 30;
color: white;
background: rgba(0,0,0,0.4);
padding: 8px 12px;
border-radius: 8px;
font-size: 0.9rem;
pointer-events: auto;
}
</style>
</head>
<body>
<canvas id="screen" width="480" height="320"></canvas>
<div id="touchControls">
<div class="control-row">
<!-- LEFT - D-Pad -->
<div id="dpad">
<div></div>
<button id="up">↑</button>
<div></div>
<button id="left">←</button>
<div></div>
<button id="right">β†’</button>
<div></div>
<button id="down">↓</button>
<div></div>
</div>
<!-- RIGHT - Shoulders + Start/Select + A/B -->
<div style="display: flex; flex-direction: column; align-items: flex-end; gap: 10px; width: 58%; max-width: 240px; pointer-events: auto;">
<!-- L R -->
<div style="display: flex; gap: 12px; width: 100%; justify-content: flex-end;">
<button id="l" class="shoulder-btn">L</button>
<button id="r" class="shoulder-btn">R</button>
</div>
<!-- Select / Start -->
<div style="display: flex; gap: 12px; width: 100%; justify-content: flex-end;">
<button id="select" class="action-btn">Select</button>
<button id="start" class="action-btn">Start</button>
</div>
<!-- A B -->
<div style="display: flex; gap: 20px; justify-content: flex-end;">
<button id="b" class="face-btn">B</button>
<button id="a" class="face-btn">A</button>
</div>
</div>
</div>
</div>
<div id="controls">
<button onclick="document.getElementById('loader').click()">Load ROM</button>
<input id="loader" type="file" accept=".gba" style="display:none;">
</div>
<script src="https://raw.githack.com/gbajs/gbajs/master/js/util.js"></script>
<script src="https://raw.githack.com/gbajs/gbajs/master/js/core.js"></script>
<script src="https://raw.githack.com/gbajs/gbajs/master/js/arm.js"></script>
<script src="https://raw.githack.com/gbajs/gbajs/master/js/thumb.js"></script>
<script src="https://raw.githack.com/gbajs/gbajs/master/js/mmu.js"></script>
<script src="https://raw.githack.com/gbajs/gbajs/master/js/io.js"></script>
<script src="https://raw.githack.com/gbajs/gbajs/master/js/audio.js"></script>
<script src="https://raw.githack.com/gbajs/gbajs/master/js/video.js"></script>
<script src="https://raw.githack.com/gbajs/gbajs/master/js/video/proxy.js"></script>
<script src="https://raw.githack.com/gbajs/gbajs/master/js/video/software.js"></script>
<script src="https://raw.githack.com/gbajs/gbajs/master/js/irq.js"></script>
<script src="https://raw.githack.com/gbajs/gbajs/master/js/keypad.js"></script>
<script src="https://raw.githack.com/gbajs/gbajs/master/js/sio.js"></script>
<script src="https://raw.githack.com/gbajs/gbajs/master/js/savedata.js"></script>
<script src="https://raw.githack.com/gbajs/gbajs/master/js/gpio.js"></script>
<script src="https://raw.githack.com/gbajs/gbajs/master/js/gba.js"></script>
<script>
// ────────────────────────────────────────────────
var gba;
var canvas = document.getElementById('screen');
try {
gba = new GameBoyAdvance();
gba.keypad.eatInput = true;
gba.setCanvas(canvas);
gba.logLevel = gba.LOG_ERROR;
// Load official BIOS if you have it (optional)
// fetch('bios.bin').then(r=>r.arrayBuffer()).then(b=>gba.setBios(b));
} catch(e) {
console.error("GBA init failed", e);
}
// Show touch controls on mobile
if ('ontouchstart' in window || navigator.maxTouchPoints > 0) {
document.getElementById('touchControls').style.display = 'block';
canvas.style.width = '100%';
canvas.style.height = 'auto';
}
// ─── Touch β†’ Keyboard simulation ─────────────────────────────
function press(code) {
window.dispatchEvent(new KeyboardEvent('keydown', {keyCode: code, bubbles: true}));
}
function release(code) {
window.dispatchEvent(new KeyboardEvent('keyup', {keyCode: code, bubbles: true}));
}
const map = {
up: 38, // ↑
down: 40,
left: 37,
right: 39,
a: 88, // X
b: 90, // Z
l: 65, // A
r: 83, // S
start: 13, // Enter
select:16 // Shift
};
Object.keys(map).forEach(key => {
const btn = document.getElementById(key);
if (!btn) return;
btn.addEventListener('touchstart', e => { e.preventDefault(); press(map[key]); });
btn.addEventListener('touchend', e => { e.preventDefault(); release(map[key]); });
// Also support touch cancel / leave
btn.addEventListener('touchcancel', e => { e.preventDefault(); release(map[key]); });
});
// ─── File loading ─────────────────────────────────────────────
document.getElementById('loader').addEventListener('change', function(e) {
const file = e.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = function() {
try {
gba.loadRom(reader.result, function success() {
gba.runStable();
document.getElementById('controls').style.display = 'none';
});
} catch(e) {
alert("Could not load ROM\n" + e);
}
};
reader.readAsArrayBuffer(file);
});
</script>
</body>
</html>