Compare commits
2 Commits
706789c81b
...
197ebcd615
| Author | SHA1 | Date | |
|---|---|---|---|
| 197ebcd615 | |||
| ecd411a9de |
+1
-8
@@ -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');
|
||||
|
||||
@@ -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
Executable
BIN
Binary file not shown.
@@ -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
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user