Compare commits
2 Commits
Author | SHA1 | Date |
---|---|---|
Eric-Paul I | 95506a7700 | |
Eric-Paul Ickhorn | 0d92060296 |
|
@ -1,2 +0,0 @@
|
||||||
[workspace]
|
|
||||||
members = ["base", "architectures/*"]
|
|
|
@ -12,5 +12,3 @@ crate-type = ["cdylib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wasm-bindgen = "0.2"
|
wasm-bindgen = "0.2"
|
||||||
console_error_panic_hook = "0.1"
|
|
||||||
chrono = "0.4"
|
|
|
@ -1,57 +0,0 @@
|
||||||
#[path = "../utils/mod.rs"]
|
|
||||||
mod utils;
|
|
||||||
|
|
||||||
use chrono::{Utc};
|
|
||||||
use crate::utils::utils_log;
|
|
||||||
|
|
||||||
pub struct NemuClock {
|
|
||||||
hertz: u32,
|
|
||||||
cycle_duration: u32,
|
|
||||||
command_queue: Vec<fn()>
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NemuClock {
|
|
||||||
pub fn init(hertz: u32) -> NemuClock{
|
|
||||||
let mut clock = NemuClock {
|
|
||||||
hertz,
|
|
||||||
cycle_duration: 0,
|
|
||||||
command_queue: Vec::new()
|
|
||||||
};
|
|
||||||
clock.hertz_set(hertz);
|
|
||||||
|
|
||||||
return clock;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn debug_info(&mut self) {
|
|
||||||
utils_log(&format!("Clock -> Hertz: {} Cycle Duration (nano): {}", self.hertz, self.cycle_duration));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn hertz_set(&mut self, hertz:u32) {
|
|
||||||
self.hertz = hertz;
|
|
||||||
self.cycle_duration = 1000000000 / hertz; // this is the duration of on cycle in nanoseconds
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn hertz_get(self) -> u32 {
|
|
||||||
return self.hertz;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_command(&mut self, command:fn()) {
|
|
||||||
self.command_queue.push(command);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn run(&mut self) {
|
|
||||||
|
|
||||||
while true {
|
|
||||||
let cycle_start = Utc::now().timestamp_subsec_nanos();
|
|
||||||
let cycle_end = cycle_start + self.cycle_duration;
|
|
||||||
|
|
||||||
utils_log(&format!("Clock -> Tick start: {} end: {}", cycle_start, cycle_end));
|
|
||||||
|
|
||||||
for command in &self.command_queue {
|
|
||||||
command();
|
|
||||||
}
|
|
||||||
|
|
||||||
while Utc::now().timestamp_subsec_nanos() < cycle_end {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,24 +1,11 @@
|
||||||
mod clock;
|
|
||||||
mod utils;
|
|
||||||
extern crate console_error_panic_hook;
|
|
||||||
|
|
||||||
use std::ptr::null;
|
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
use crate::clock::NemuClock;
|
|
||||||
use crate::utils::utils_log;
|
|
||||||
|
|
||||||
fn test() {
|
#[wasm_bindgen]
|
||||||
utils_log("test");
|
extern {
|
||||||
|
pub fn alert(s: &str);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
pub fn nemu_init() {
|
pub fn greet(name: &str) {
|
||||||
console_error_panic_hook::set_once();
|
alert(&format!("Hello, {}!", name));
|
||||||
utils_log("starting nemu");
|
|
||||||
let mut clock = NemuClock::init(8000);
|
|
||||||
|
|
||||||
clock.add_command(test, );
|
|
||||||
|
|
||||||
clock.debug_info();
|
|
||||||
clock.run();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
use wasm_bindgen::prelude::*;
|
|
||||||
|
|
||||||
|
|
||||||
#[wasm_bindgen]
|
|
||||||
extern {
|
|
||||||
fn alert(s: &str);
|
|
||||||
|
|
||||||
#[wasm_bindgen(js_namespace = console)]
|
|
||||||
fn log(s: &str);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn utils_log(s: &str) {
|
|
||||||
log(&format!("{}", s));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn utils_panic(s: &str) {
|
|
||||||
alert(&format!("Panic: {}", s));
|
|
||||||
}
|
|
|
@ -0,0 +1,166 @@
|
||||||
|
|
||||||
|
* {
|
||||||
|
|
||||||
|
padding: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
html, body, main {
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#configurator {
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
justify-content: space-around;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
width: 85vw;
|
||||||
|
height: 85vw;
|
||||||
|
|
||||||
|
max-width: 85vh;
|
||||||
|
max-height: 85vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-step > .header {
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
z-index: 4;
|
||||||
|
top: -32px;
|
||||||
|
|
||||||
|
height: 32px;
|
||||||
|
|
||||||
|
background-color: #161819;
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
text-align: center;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 650;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-step > .content {
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
z-index: 3;
|
||||||
|
top: -32px;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.config-step > .content > .inner-pane {
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pane-choose-configurator {
|
||||||
|
|
||||||
|
width: 80%;
|
||||||
|
height: 80%;
|
||||||
|
|
||||||
|
background-color: #1e2122;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#configurator-chooser-background {
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#configurator-chooser-preset-background {
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
bottom: 0%;
|
||||||
|
right: 0%;
|
||||||
|
z-index: 2;
|
||||||
|
|
||||||
|
width: 99%;
|
||||||
|
height: 99%;
|
||||||
|
|
||||||
|
clip-path: polygon(0% 0%, 0% 100%, 100% 0%);
|
||||||
|
|
||||||
|
background-color: #242728;
|
||||||
|
}
|
||||||
|
|
||||||
|
#configurator-chooser-preset-background:hover {
|
||||||
|
|
||||||
|
background-color: #2f3436;
|
||||||
|
}
|
||||||
|
|
||||||
|
#configurator-chooser-own-systems-background {
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
bottom: 98%;
|
||||||
|
right: -1%;
|
||||||
|
|
||||||
|
width: 99%;
|
||||||
|
height: 99%;
|
||||||
|
|
||||||
|
clip-path: polygon(100% 100%, 0% 100%, 100% 0%);
|
||||||
|
|
||||||
|
background-color: #242728;
|
||||||
|
}
|
||||||
|
|
||||||
|
#configurator-chooser-own-systems-background:hover {
|
||||||
|
|
||||||
|
background-color: #2f3436;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#button-choose-preset-configurator {
|
||||||
|
z-index: 2;
|
||||||
|
position: relative;
|
||||||
|
top: -70%;
|
||||||
|
left: 22.5%;
|
||||||
|
|
||||||
|
color: #fff;
|
||||||
|
font-size: 40px;
|
||||||
|
font-weight: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#button-choose-own-systems-configurator {
|
||||||
|
|
||||||
|
z-index: 2;
|
||||||
|
position: relative;
|
||||||
|
top: -40%;
|
||||||
|
left: 60%;
|
||||||
|
|
||||||
|
color: #fff;
|
||||||
|
font-size: 40px;
|
||||||
|
font-weight: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-desktop-container {
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
justify-content: space-around;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
background-color: #373939;
|
||||||
|
}
|
||||||
|
|
||||||
|
#control-bar {
|
||||||
|
|
||||||
|
position: fixed;
|
||||||
|
left: 0px;
|
||||||
|
top: 0px;
|
||||||
|
z-index: 16;
|
||||||
|
|
||||||
|
width: 48px;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
background-color: #1e2122;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
|
||||||
|
<title>NEMU | nerdcult.net emulator</title>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="configurator.css">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<main id="main-desktop-container">
|
||||||
|
|
||||||
|
<aside id="control-bar">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
<section id="configurator">
|
||||||
|
|
||||||
|
<div class="config-step" id="pane-choose-configurator">
|
||||||
|
|
||||||
|
<div class="header">
|
||||||
|
System Type
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content">
|
||||||
|
|
||||||
|
<div class="inner-pane">
|
||||||
|
|
||||||
|
<div id="configurator-chooser-background">
|
||||||
|
<div id="configurator-chooser-preset-background"></div>
|
||||||
|
<div id="configurator-chooser-own-systems-background"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="button-choose-preset-configurator"> <p>Preset</p> </div>
|
||||||
|
<div id="button-choose-own-systems-configurator"> <p>Own</p> </div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</footer>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
38
index.html
38
index.html
|
@ -8,40 +8,46 @@
|
||||||
<link rel="stylesheet" href="test.css">
|
<link rel="stylesheet" href="test.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header id="config-button"s>
|
<noscript>THIS PAGE DOES NOT WORK WITHOUT JAVASCRIPT!</noscript>
|
||||||
<div class="hamburger" id="configurator-button">
|
|
||||||
<div class="hamburger-slice"></div>
|
|
||||||
<div class="hamburger-slice"></div>
|
|
||||||
<div class="hamburger-slice"></div>
|
|
||||||
<div>
|
|
||||||
|
|
||||||
</header>
|
<div class="horizontal-aligner">
|
||||||
|
<div class="info-view generic-panel">
|
||||||
|
<div class="header">
|
||||||
|
<p>Information- / Debug - View</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="configurator-modal">
|
|
||||||
<div id="configurator-modal-background"></div>
|
|
||||||
|
|
||||||
<div id="configurator-modal-foreground">
|
</div>
|
||||||
|
|
||||||
|
<div class="monitor-view">
|
||||||
|
<div class="monitor" id="primary-monitor">
|
||||||
|
<div class="info-header">Primary Monitor</div>
|
||||||
|
<canvas class="output">HTML5 Canvas must be supported!</canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="control-view generic-panel">
|
||||||
|
<div class="header">
|
||||||
|
<p>Control Panel</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<main>
|
<div id="configurator">
|
||||||
|
|
||||||
<p id="output-title">The NerdEMU Emulator</p>
|
|
||||||
|
|
||||||
<canvas class="pixel-output"></canvas>
|
|
||||||
|
|
||||||
</main>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
<script src="test.js"></script>
|
<script src="test.js"></script>
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import init, { nemu_init } from "./base/pkg/nemu_base.js";
|
import init, { greet } from "./base/pkg/nemu_base.js";
|
||||||
|
|
||||||
init().then(() => {
|
init().then(() => {
|
||||||
nemu_init();
|
greet("NerdEMU");
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -2,13 +2,5 @@
|
||||||
"name": "i8086",
|
"name": "i8086",
|
||||||
"version": "0.0",
|
"version": "0.0",
|
||||||
|
|
||||||
"architecture": {
|
"architecture": "x86"
|
||||||
"id": "x86"
|
|
||||||
},
|
|
||||||
|
|
||||||
"devices": {
|
|
||||||
"monitor": {
|
|
||||||
"mode": "VGA"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
209
test.css
209
test.css
|
@ -1,134 +1,139 @@
|
||||||
|
|
||||||
* {
|
* {
|
||||||
|
|
||||||
margin: 0px;
|
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
|
margin: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
html, body {
|
html, body {
|
||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
background-color: #1a2b40;
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
main {
|
|
||||||
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
.horizontal-aligner {
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: row;
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
header {
|
|
||||||
|
|
||||||
position: fixed;
|
|
||||||
right: 0px;
|
|
||||||
top: 0px;
|
|
||||||
z-index: 10;
|
|
||||||
|
|
||||||
width: 48px;
|
|
||||||
height: 48px;
|
|
||||||
border-bottom-left-radius: 12px;
|
|
||||||
|
|
||||||
background-color: #0f141b;
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger {
|
|
||||||
|
|
||||||
margin-bottom: 2px;
|
|
||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger-slice {
|
|
||||||
|
|
||||||
margin: 3px;
|
|
||||||
|
|
||||||
width: 75%;
|
|
||||||
height: 6px;
|
|
||||||
|
|
||||||
background-color: #ffffff;
|
|
||||||
border-radius: 2.5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pixel-output {
|
|
||||||
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#config-button {
|
|
||||||
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.pixel-output {
|
|
||||||
|
|
||||||
z-index: 2;
|
|
||||||
width: 60vw;
|
|
||||||
max-height: 90vh;
|
|
||||||
|
|
||||||
/*So it's always a 16/9 aspect ratio */
|
|
||||||
height: calc(60vw*0.5625);
|
|
||||||
background-color: #000000;
|
background-color: #000000;
|
||||||
box-shadow: 0px 0px 8px 8px #0f141b55;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#output-title {
|
|
||||||
|
|
||||||
padding-bottom: 20px;
|
|
||||||
|
|
||||||
font-size: 32px;
|
.generic-panel {
|
||||||
font-weight: 1000;
|
|
||||||
|
min-width: 150px;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
background-color: #2c3046;
|
||||||
|
border-right: solid 1px #1c1e24;
|
||||||
|
border-left: solid 1px #1c1e24;
|
||||||
}
|
}
|
||||||
|
|
||||||
#configurator-modal {
|
.generic-panel > .header {
|
||||||
|
|
||||||
position: fixed;
|
display: flex;
|
||||||
right: 0px;
|
flex-direction: row;
|
||||||
top: 0px;
|
align-items: center;
|
||||||
display: none;
|
justify-content: space-around;
|
||||||
z-index: 4;
|
|
||||||
|
width: 100%;
|
||||||
width: 100%;
|
height: 24px;
|
||||||
height: 100%;
|
|
||||||
}
|
font-size: 16px;
|
||||||
|
font-weight: 750;
|
||||||
#configurator-modal-background {
|
|
||||||
|
background-color: #1c1e24;
|
||||||
position: fixed;
|
color: #ffffff;
|
||||||
right: 0px;
|
}
|
||||||
top: 0px;
|
|
||||||
z-index: 5;
|
|
||||||
|
|
||||||
width: 100%;
|
.info-view {
|
||||||
height: 100%;
|
|
||||||
|
min-width: 100px;
|
||||||
background-color: #0f141bb0;
|
width: 50%;
|
||||||
}
|
height: 100%;
|
||||||
|
|
||||||
#configurator-modal-foreground {
|
|
||||||
|
}
|
||||||
position: fixed;
|
|
||||||
right: 0px;
|
.control-view {
|
||||||
top: 0px;
|
|
||||||
z-index: 6;
|
min-width: 100px;
|
||||||
|
width: 25%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.monitor-view {
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-around;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
min-width: 400px;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
background-color: #080808;
|
||||||
|
}
|
||||||
|
|
||||||
|
.monitor {
|
||||||
|
|
||||||
|
width: 50vw;
|
||||||
|
height: auto;
|
||||||
|
padding-left: 3px;
|
||||||
|
padding-right: 3px;
|
||||||
|
|
||||||
|
background-color: #1c1e24;
|
||||||
|
border-bottom-left-radius: 5px;
|
||||||
|
border-bottom-right-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.monitor > .info-header {
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-around;
|
||||||
|
|
||||||
|
height: 24px;
|
||||||
|
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 750;
|
||||||
|
|
||||||
|
background-color: #1c1e24;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.monitor > .output {
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
height: calc(50vw * 0.5625);
|
||||||
|
|
||||||
|
background-color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
noscript {
|
||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
background-color: #000000;
|
||||||
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Reference in New Issue