inital commit
This commit is contained in:
commit
06855542a1
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
rom.gb
|
||||||
|
node_modules/
|
||||||
|
pnpm-lock.yaml
|
58
app.js
Normal file
58
app.js
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
const imageboy = require("imageboy");
|
||||||
|
const fastify = require("fastify")();
|
||||||
|
const path = require("path");
|
||||||
|
const fs = require("fs");
|
||||||
|
let lastFrame = "";
|
||||||
|
let emulator;
|
||||||
|
const mainHTML = fs.readFileSync(path.join(__dirname, "html", "gb.html"), "utf8");
|
||||||
|
const KEYMAP = {
|
||||||
|
RIGHT: 0,
|
||||||
|
LEFT: 1,
|
||||||
|
UP: 2,
|
||||||
|
DOWN: 3,
|
||||||
|
A: 4,
|
||||||
|
B: 5,
|
||||||
|
SELECT: 6,
|
||||||
|
START: 7
|
||||||
|
};
|
||||||
|
|
||||||
|
async function run() {
|
||||||
|
if (!fs.existsSync(path.join(__dirname, "rom.gb"))) {
|
||||||
|
console.log("rom.gb missing.")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emulator = imageboy.run({
|
||||||
|
path: "./rom.gb",
|
||||||
|
interval: 16.6666667,
|
||||||
|
onFrame: function(frame) {
|
||||||
|
if (lastFrame !== frame) {
|
||||||
|
lastFrame = frame;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
fastify.get("/", async(request, reply) => {
|
||||||
|
reply.type("text/html");
|
||||||
|
reply.send(mainHTML);
|
||||||
|
});
|
||||||
|
|
||||||
|
fastify.get("/image", async(request, reply) => {
|
||||||
|
reply.type("image/png").send(lastFrame);
|
||||||
|
});
|
||||||
|
|
||||||
|
fastify.get("/control", async(request, reply) => {
|
||||||
|
const button = request.query.button;
|
||||||
|
if (button) {
|
||||||
|
const mappedButton = KEYMAP[button.toUpperCase()];
|
||||||
|
if (mappedButton) emulator.pressKeys(emulator.gameboy, [mappedButton]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
await fastify.listen({ port: 3000 });
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
run();
|
112
html/gb.html
Normal file
112
html/gb.html
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
<style>
|
||||||
|
.button {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<ul id='messages'></ul>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<body style="background-color: #121212">
|
||||||
|
<div>
|
||||||
|
<img id="image" src="http://localhost:3000/image" width="700" style="display: block; margin: auto;" />
|
||||||
|
<br>
|
||||||
|
<div style="position: absolute; left: 50%; transform: translate(-50%, 0);">
|
||||||
|
<a id="UP" class="button">
|
||||||
|
<img src="https://raw.githubusercontent.com/Giingu/Giingu/main/images/blank.png" width="35" />
|
||||||
|
<img src="https://raw.githubusercontent.com/Giingu/Giingu/main/images/up.png" width="35" />
|
||||||
|
</a>
|
||||||
|
<br>
|
||||||
|
<a id="LEFT" class="button">
|
||||||
|
<img src="https://raw.githubusercontent.com/Giingu/Giingu/main/images/left.png" width="35" />
|
||||||
|
</a>
|
||||||
|
<img src="https://raw.githubusercontent.com/Giingu/Giingu/main/images/blank.png" width="35" />
|
||||||
|
<a id="RIGHT" class="button">
|
||||||
|
<img src="https://raw.githubusercontent.com/Giingu/Giingu/main/images/right.png" width="35" />
|
||||||
|
</a>
|
||||||
|
<img src="https://raw.githubusercontent.com/Giingu/Giingu/main/images/blank.png" width="35" />
|
||||||
|
<img src="https://raw.githubusercontent.com/Giingu/Giingu/main/images/blank.png" width="35" />
|
||||||
|
<img src="https://raw.githubusercontent.com/Giingu/Giingu/main/images/blank.png" width="35" />
|
||||||
|
<a id="B" class="button">
|
||||||
|
<img src="https://raw.githubusercontent.com/Giingu/Giingu/main/images/B.png" width="35" />
|
||||||
|
</a>
|
||||||
|
<a id="A" class="button">
|
||||||
|
<img src="https://raw.githubusercontent.com/Giingu/Giingu/main/images/A.png" width="35" />
|
||||||
|
</a>
|
||||||
|
<br>
|
||||||
|
<a id="DOWN" class="button">
|
||||||
|
<img src="https://raw.githubusercontent.com/Giingu/Giingu/main/images/blank.png" width="35" />
|
||||||
|
<img src="https://raw.githubusercontent.com/Giingu/Giingu/main/images/down.png" width="35" />
|
||||||
|
</a>
|
||||||
|
<br>
|
||||||
|
<img src="https://raw.githubusercontent.com/Giingu/Giingu/main/images/blank.png" width="35" />
|
||||||
|
<img src="https://raw.githubusercontent.com/Giingu/Giingu/main/images/blank.png" width="35" />
|
||||||
|
<a id="SELECT" class="button">
|
||||||
|
<img src="https://raw.githubusercontent.com/Giingu/Giingu/main/images/select.png" height="35" />
|
||||||
|
</a>
|
||||||
|
<a id="START" class="button">
|
||||||
|
<img src="https://raw.githubusercontent.com/Giingu/Giingu/main/images/start.png" height="35" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/js-base64@3.7.2/base64.min.js"></script>
|
||||||
|
<script>
|
||||||
|
$(document).ready(function() {
|
||||||
|
|
||||||
|
function updateImage() {
|
||||||
|
toDataURL('http://localhost:3000/image', function(dataUrl) {
|
||||||
|
$('#image').attr('src', dataUrl);
|
||||||
|
updateImage();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function toDataURL(url, callback) {
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.onload = function() {
|
||||||
|
var reader = new FileReader();
|
||||||
|
reader.onloadend = function() {
|
||||||
|
callback(reader.result);
|
||||||
|
}
|
||||||
|
reader.readAsDataURL(xhr.response);
|
||||||
|
};
|
||||||
|
xhr.open('GET', url);
|
||||||
|
xhr.responseType = 'blob';
|
||||||
|
xhr.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
updateImage();
|
||||||
|
|
||||||
|
const controls = ["UP", "DOWN", "LEFT", "RIGHT", "A", "B", "SELECT", "START"];
|
||||||
|
const keyboard_key = {
|
||||||
|
"UP": "ArrowUp",
|
||||||
|
"DOWN": "ArrowDown",
|
||||||
|
"LEFT": "ArrowLeft",
|
||||||
|
"RIGHT": "ArrowRight",
|
||||||
|
"A": "Enter",
|
||||||
|
"B": "Return",
|
||||||
|
"SELECT": "KeyS",
|
||||||
|
"START": "KeyP"
|
||||||
|
};
|
||||||
|
|
||||||
|
$("body").keypress(function(key) {
|
||||||
|
console.log("key pressed: " + key);
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const key in controls) {
|
||||||
|
const control = controls[key];
|
||||||
|
$("#" + control).click(() => {
|
||||||
|
console.log("click " + control);
|
||||||
|
var settings = {
|
||||||
|
"url": "http://localhost:3000/control?button=" + control,
|
||||||
|
"method": "GET",
|
||||||
|
"timeout": 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
$.ajax(settings).done(function(response) {});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
24
package.json
Normal file
24
package.json
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
{
|
||||||
|
"name": "gbonline",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"start": "node app.js"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"@tensorflow/tfjs": ">=3.19.0 <4.0.0\n",
|
||||||
|
"@tensorflow/tfjs-node": "^3.19.0",
|
||||||
|
"fastify": "^4.4.0",
|
||||||
|
"fastify-socket.io": "^4.0.0",
|
||||||
|
"imageboy": "^1.1.1",
|
||||||
|
"seedrandom": "^3.0.5",
|
||||||
|
"serverboy": "^0.0.7",
|
||||||
|
"socket.io": "^4.5.1",
|
||||||
|
"upscaler": "1.0.0-beta.6",
|
||||||
|
"waifu2x": "^1.0.9"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user