Compare commits

..

2 Commits

Author SHA1 Message Date
jasonhilder 197ebcd615 Removed debugging JS. 2026-07-06 07:45:56 +02:00
jasonhilder ecd411a9de Dedicated project page for chip8 sim. 2026-07-06 07:45:49 +02:00
8 changed files with 12643 additions and 15 deletions
+1 -8
View File
@@ -1,13 +1,6 @@
<?php
declare(strict_types=1);
// --- Security headers ---
header_remove('X-Powered-By');
header('X-Frame-Options: DENY');
header('X-Content-Type-Options: nosniff');
header('Referrer-Policy: strict-origin-when-cross-origin');
header('Content-Security-Policy: default-src \'self\'');
// --- Routing ---
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
@@ -18,7 +11,7 @@ if ($uri === false || $uri === null) {
$routes = [
'/' => 'web/pages/home.php',
'/about' => 'web/pages/about.php',
'/sim' => 'web/pages/sim.php',
];
$base = realpath(ROOT . '/web/pages');
+95
View File
@@ -0,0 +1,95 @@
<?php require ROOT . '/web/partials/head.php'; ?>
<style>
body {
margin: 0px;
background-color: black;
max-width: 2200px;
}
.game_wrapper {
max-width: 1500px;
margin-left: auto;
margin-right: auto;
font-family: sans-serif;
color: white;
}
.game_title {
text-align: center;
font-size: 1.8rem;
margin: 20px 0 12px 0;
}
canvas.game_canvas {
width: 100%;
height: auto;
/* match this to your actual internal render resolution ratio */
aspect-ratio: 16 / 9;
border: 0px none;
background-color: black;
display: block;
cursor: pointer;
}
.too_small_message {
display: none;
color: white;
font-family: sans-serif;
text-align: center;
padding: 40px 20px;
}
.game_info {
max-width: 900px;
margin: 20px auto 40px auto;
padding: 0 16px;
line-height: 1.5;
text-align: center;
color: #ccc;
font-size: 0.95rem;
}
.game_info strong {
color: white;
}
.game_info a {
color: #9cf;
}
.game_info p {
margin: 6px 0;
}
/* Below this width, hide the canvas and show the message instead */
@media (max-width: 950px) {
canvas.game_canvas {
display: none;
}
.too_small_message {
display: block;
}
}
</style>
<div class="game_wrapper">
<h1 class="game_title">Octal Cookie - Chip 8 Simulator</h1>
<canvas class="game_canvas" id="canvas" oncontextmenu="event.preventDefault()" tabindex="-1" onmousedown="event.target.focus()" onkeydown="event.preventDefault()"></canvas>
<div class="game_info">
<p><strong>Click inside the simulator to focus it</strong>, click outside to release focus.</p>
<p>Keypad is mapped to <strong>1234 / QWER / ASDF / ZXCV</strong>.</p>
<hr>
<p>A CHIP-8 emulator built in Odin and Raylib as a refresher project.</p>
<p> Functional Work in progress, not perfect.</p>
<p> Planned new features when time allows: </p>
<p><strong>Instruction Quirks with gui to toggle on/off</strong></p>
<p><strong>Super Chip8 implementation</strong></p>
</br><a href="https://gitea.sc.koldsoftware.com/jasonhilder/octal_cookie" target="_blank" rel="noopener">View source on Gitea →</a></p>
</div>
<div class="too_small_message">
Your screen is too small to run this app. Please use a larger window or device.
</div>
</div>
<script src="/web/static/apps/sim/odin.js"></script>
<script src="/web/static/apps/sim/init.js"></script>
<script src="/web/static/apps/sim/index.js"></script>
<?php require ROOT . '/web/partials/footer.php'; ?>
Binary file not shown.
File diff suppressed because it is too large Load Diff
BIN
View File
Binary file not shown.
+76
View File
@@ -0,0 +1,76 @@
var odinMemoryInterface = new odin.WasmMemoryInterface();
odinMemoryInterface.setIntSize(4);
var odinImports = odin.setupDefaultImports(odinMemoryInterface);
// The Module is used as configuration for emscripten.
var Module = {
// This is called by emscripten when it starts up.
instantiateWasm: (imports, successCallback) => {
const newImports = {
...odinImports,
...imports
}
return WebAssembly.instantiateStreaming(fetch("/web/static/apps/sim/index.wasm"), newImports).then(function(output) {
var e = output.instance.exports;
odinMemoryInterface.setExports(e);
odinMemoryInterface.setMemory(e.memory);
return successCallback(output.instance);
});
},
// This happens a bit after `instantiateWasm`, when everything is
// done setting up. At that point we can run code.
onRuntimeInitialized: () => {
var e = wasmExports;
// Calls any procedure marked with @init
e._start();
// See source/main_web/main_web.odin for main_start,
// main_update and main_end.
e.main_start();
function send_resize() {
var canvas = document.getElementById('canvas');
e.web_window_size_changed(canvas.width, canvas.height);
}
window.addEventListener('resize', function(event) {
send_resize();
}, true);
// This can probably be done better: Ideally we'd feed the
// initial size to `main_start`. But there seems to be a
// race condition. `canvas` doesn't have it's correct size yet.
send_resize();
// Runs the "main loop".
function do_main_update() {
if (!e.main_update()) {
e.main_end();
// Calls procedures marked with @fini
e._end();
return;
}
window.requestAnimationFrame(do_main_update);
}
window.requestAnimationFrame(do_main_update);
},
print: (function() {
var element = document.getElementById("output");
if (element) element.value = ''; // clear browser cache
return function(text) {
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
console.log(text);
if (element) {
element.value += text + "\n";
element.scrollTop = element.scrollHeight; // focus on bottom
}
};
})(),
canvas: (function() {
return document.getElementById("canvas");
})()
};
File diff suppressed because it is too large Load Diff
-7
View File
@@ -111,10 +111,3 @@ function checkOffsets() {
}
}
}
const debugToggle = document.querySelector(".debug-toggle");
function onDebugToggle() {
document.body.classList.toggle("debug", debugToggle.checked);
}
debugToggle.addEventListener("change", onDebugToggle);
onDebugToggle();