lucky / index 24.html
Studytime171's picture
Duplicate from Studytime171/Lalitgangwani
89610f7
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>GBA.js Mobile - Fixed Loader</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<style>
body { margin:0; background:#000; font-family:Arial; color:#fff; overflow:hidden; }
#screen { display:block; width:100%; height:auto; image-rendering:pixelated; }
#info { position:absolute; top:10px; left:10px; background:rgba(0,0,0,0.6); padding:10px; border-radius:8px; z-index:30; pointer-events:auto; }
#touchControls { position:absolute; inset:0; pointer-events:none; z-index:20; padding:10px; display:none; box-sizing:border-box; }
.control-row { display:flex; justify-content:space-between; align-items:flex-end; height:100%; pointer-events:none; }
button { background:rgba(80,80,80,0.7); color:white; font-weight:bold; border:none; border-radius:10px; box-shadow:0 3px 8px #000; touch-action:manipulation; -webkit-tap-highlight-color:transparent; }
#dpad { display:grid; grid-template-columns:repeat(3,1fr); grid-template-rows:repeat(3,1fr); gap:6px; width:35%; max-width:160px; aspect-ratio:1/1; pointer-events:auto; }
#dpad button { font-size:clamp(1.6rem,8vw,2.4rem); }
.face-btn { width:clamp(60px,17vw,85px); height:clamp(60px,17vw,85px); border-radius:50%; font-size:clamp(1.8rem,7vw,2.4rem); pointer-events:auto; }
#a { background:rgba(220,40,40,0.8); }
#b { background:rgba(40,100,220,0.8); }
.shoulder { width:clamp(50px,14vw,70px); height:clamp(32px,8vw,40px); font-size:clamp(1rem,4vw,1.3rem); background:rgba(100,100,100,0.8); }
.action { width:clamp(65px,17vw,85px); height:clamp(36px,9vw,44px); font-size:clamp(0.95rem,3.8vw,1.2rem); background:rgba(40,140,40,0.8); }
@media (max-width:360px) { #dpad {max-width:130px;} .face-btn {width:55px;height:55px;} }
</style>
</head>
<body>
<canvas id="screen" width="240" height="160"></canvas>
<div id="info">
<button onclick="document.getElementById('romfile').click()">Load .gba ROM</button>
<input id="romfile" type="file" accept=".gba" style="display:none;">
<p id="status">Waiting for ROM...</p>
</div>
<div id="touchControls">
<div class="control-row">
<!-- D-Pad left -->
<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 side controls -->
<div style="display:flex; flex-direction:column; align-items:flex-end; gap:8px; width:60%; pointer-events:auto;">
<div style="display:flex; gap:10px;">
<button id="l" class="shoulder">L</button>
<button id="r" class="shoulder">R</button>
</div>
<div style="display:flex; gap:10px;">
<button id="select" class="action">Select</button>
<button id="start" class="action">Start</button>
</div>
<div style="display:flex; gap:18px;">
<button id="b" class="face-btn">B</button>
<button id="a" class="face-btn">A</button>
</div>
</div>
</div>
</div>
<!-- Load GBA.js from reliable CDN mirror -->
<script src="https://cdn.jsdelivr.net/gh/gbajs/gbajs@master/js/util.js"></script>
<script src="https://cdn.jsdelivr.net/gh/gbajs/gbajs@master/js/core.js"></script>
<script src="https://cdn.jsdelivr.net/gh/gbajs/gbajs@master/js/arm.js"></script>
<script src="https://cdn.jsdelivr.net/gh/gbajs/gbajs@master/js/thumb.js"></script>
<script src="https://cdn.jsdelivr.net/gh/gbajs/gbajs@master/js/mmu.js"></script>
<script src="https://cdn.jsdelivr.net/gh/gbajs/gbajs@master/js/io.js"></script>
<script src="https://cdn.jsdelivr.net/gh/gbajs/gbajs@master/js/audio.js"></script>
<script src="https://cdn.jsdelivr.net/gh/gbajs/gbajs@master/js/video.js"></script>
<script src="https://cdn.jsdelivr.net/gh/gbajs/gbajs@master/js/video/software.js"></script>
<script src="https://cdn.jsdelivr.net/gh/gbajs/gbajs@master/js/irq.js"></script>
<script src="https://cdn.jsdelivr.net/gh/gbajs/gbajs@master/js/keypad.js"></script>
<script src="https://cdn.jsdelivr.net/gh/gbajs/gbajs@master/js/gba.js"></script>
<script>
let gba;
const canvas = document.getElementById('screen');
const status = document.getElementById('status');
try {
gba = new GameBoyAdvance();
gba.keypad.eatInput = true;
gba.setCanvas(canvas);
gba.logLevel = 0; // quiet unless error
console.log("GBA core initialized");
} catch(e) {
status.textContent = "Emulator init failed: " + e.message;
alert("Cannot start emulator: " + e);
}
if ('ontouchstart' in window || navigator.maxTouchPoints > 0) {
document.getElementById('touchControls').style.display = 'block';
canvas.style.width = '100%';
canvas.style.height = 'auto';
}
// Key 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 keys = {
up:38, down:40, left:37, right:39,
a:88, b:90, l:65, r:83,
start:13, select:16
};
Object.entries(keys).forEach(([id, code]) => {
const btn = document.getElementById(id);
if (btn) {
btn.addEventListener('touchstart', e => { e.preventDefault(); press(code); });
btn.addEventListener('touchend', e => { e.preventDefault(); release(code); });
btn.addEventListener('touchcancel', e => { e.preventDefault(); release(code); });
}
});
// Load ROM
document.getElementById('romfile').addEventListener('change', function(e) {
const file = e.target.files[0];
if (!file) return;
status.textContent = "Reading file... (" + (file.size / 1024 / 1024).toFixed(1) + " MB)";
const reader = new FileReader();
reader.onload = function() {
try {
const buffer = reader.result;
if (buffer.byteLength < 0x4000) {
throw new Error("File too small – probably not a GBA ROM");
}
gba.loadRom(buffer, (success) => {
if (success) {
status.textContent = "ROM loaded! Starting...";
gba.runStable();
setTimeout(() => { document.getElementById('info').style.display = 'none'; }, 1500);
} else {
throw new Error("loadRom returned false");
}
});
} catch (err) {
status.textContent = "Load failed: " + err.message;
alert("Error loading ROM:\n" + err.message + "\n\nTry a different .gba file (clean dump, not zipped).");
console.error(err);
}
};
reader.onerror = () => {
status.textContent = "File read error";
alert("Cannot read the file – maybe corrupted or browser blocked it.");
};
reader.readAsArrayBuffer(file);
});
</script>
</body>
</html>