mirror of
https://github.com/exoticorn/microw8.git
synced 2026-01-20 19:26:43 +01:00
Compare commits
2 Commits
9632adb57f
...
f21497dd2e
| Author | SHA1 | Date | |
|---|---|---|---|
| f21497dd2e | |||
| 381eaf970f |
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -1524,6 +1524,7 @@ dependencies = [
|
|||||||
"minifb",
|
"minifb",
|
||||||
"notify",
|
"notify",
|
||||||
"pico-args",
|
"pico-args",
|
||||||
|
"same-file",
|
||||||
"uw8-tool",
|
"uw8-tool",
|
||||||
"wasmtime",
|
"wasmtime",
|
||||||
"wat",
|
"wat",
|
||||||
|
|||||||
@@ -14,3 +14,4 @@ pico-args = "0.4"
|
|||||||
curlywas = { git = "https://github.com/exoticorn/curlywas.git", rev = "196719b" }
|
curlywas = { git = "https://github.com/exoticorn/curlywas.git", rev = "196719b" }
|
||||||
wat = "1"
|
wat = "1"
|
||||||
uw8-tool = { path = "uw8-tool" }
|
uw8-tool = { path = "uw8-tool" }
|
||||||
|
same-file = "1"
|
||||||
@@ -1,102 +1,21 @@
|
|||||||
import "env.memory" memory(4);
|
import "env.memory" memory(4);
|
||||||
|
|
||||||
import "env.cls" fn cls(i32);
|
import "env.cls" fn cls(i32);
|
||||||
import "env.setPixel" fn setPixel(i32, i32, i32);
|
|
||||||
import "env.time" fn time() -> f32;
|
import "env.time" fn time() -> f32;
|
||||||
|
import "env.line" fn line(f32, f32, f32, f32, i32);
|
||||||
import "env.sin" fn sin(f32) -> f32;
|
import "env.sin" fn sin(f32) -> f32;
|
||||||
import "env.cos" fn cos(f32) -> f32;
|
import "env.cos" fn cos(f32) -> f32;
|
||||||
|
|
||||||
fn line(x1: f32, y1: f32, x2: f32, y2: f32, col: i32) {
|
|
||||||
let swapTmp: f32;
|
|
||||||
if x1 > x2 {
|
|
||||||
swapTmp = x1;
|
|
||||||
x1 = x2;
|
|
||||||
x2 = swapTmp;
|
|
||||||
swapTmp = y1;
|
|
||||||
y1 = y2;
|
|
||||||
y2 = swapTmp;
|
|
||||||
}
|
|
||||||
if x1 < 0 as f32 & x2 >= 0 as f32 {
|
|
||||||
y1 = y1 + (y2 - y1) * -x1 / (x2 - x1);
|
|
||||||
x1 = 0 as f32;
|
|
||||||
}
|
|
||||||
if x1 < 320 as f32 & x2 >= 320 as f32 {
|
|
||||||
y2 = y2 + (y2 - y1) * (320 as f32 - x2) / (x2 - x1);
|
|
||||||
x2 = 320 as f32;
|
|
||||||
}
|
|
||||||
|
|
||||||
if y1 > y2 {
|
|
||||||
swapTmp = x1;
|
|
||||||
x1 = x2;
|
|
||||||
x2 = swapTmp;
|
|
||||||
swapTmp = y1;
|
|
||||||
y1 = y2;
|
|
||||||
y2 = swapTmp;
|
|
||||||
}
|
|
||||||
if y1 < 0 as f32 & y2 >= 0 as f32 {
|
|
||||||
x1 = x1 + (x2 - x1) * -y1 / (y2 - y1);
|
|
||||||
y1 = 0 as f32;
|
|
||||||
}
|
|
||||||
if y1 < 240 as f32 & y2 >= 240 as f32 {
|
|
||||||
x2 = x2 + (x2 - x1) * (240 as f32 - y2) / (y2 - y1);
|
|
||||||
y2 = 240 as f32;
|
|
||||||
}
|
|
||||||
|
|
||||||
let lazy dx = x2 - x1;
|
|
||||||
let lazy dy = y2 - y1;
|
|
||||||
let max_axis: f32;
|
|
||||||
let p: f32;
|
|
||||||
if abs(dx) >= dy {
|
|
||||||
max_axis = dx;
|
|
||||||
p = x1;
|
|
||||||
} else {
|
|
||||||
max_axis = dy;
|
|
||||||
p = y1;
|
|
||||||
}
|
|
||||||
|
|
||||||
let steps = floor(p + max_axis) as i32 - floor(p) as i32;
|
|
||||||
p = floor(p) + 0.5 - p;
|
|
||||||
if max_axis < 0 as f32 {
|
|
||||||
steps = -steps;
|
|
||||||
p = -p;
|
|
||||||
max_axis = -max_axis;
|
|
||||||
}
|
|
||||||
dx = dx / max_axis;
|
|
||||||
dy = dy / max_axis;
|
|
||||||
|
|
||||||
let f = min(max_axis, max(0 as f32, p));
|
|
||||||
setPixel((x1 + f * dx) as i32, (y1 + f * dy) as i32, col);
|
|
||||||
|
|
||||||
if !steps {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
x1 = x1 + (1 as f32 + p) * dx;
|
|
||||||
y1 = y1 + (1 as f32 + p) * dy;
|
|
||||||
|
|
||||||
p = p + steps as f32;
|
|
||||||
|
|
||||||
loop pixels {
|
|
||||||
if steps := steps - 1 {
|
|
||||||
setPixel(x1 as i32, y1 as i32, col);
|
|
||||||
x1 = x1 + dx;
|
|
||||||
y1 = y1 + dy;
|
|
||||||
branch pixels;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
f = min(max_axis, p) - p;
|
|
||||||
setPixel((x1 + f * dx) as i32, (y1 + f * dy) as i32, col);
|
|
||||||
}
|
|
||||||
|
|
||||||
export fn upd() {
|
export fn upd() {
|
||||||
cls(0);
|
cls(0);
|
||||||
// line(0.0, 4.0, 7.0, -2.0, 15);
|
|
||||||
// return;
|
|
||||||
let i: i32;
|
let i: i32;
|
||||||
loop lines {
|
loop lines {
|
||||||
let angle = i as f32 * (3.1415 / 25.0) + time() * 0.1;
|
let angle = i as f32 * (3.1415 / 25.0) + time() * 0.125;
|
||||||
line(160.0, 120.0, 160.0 + sin(angle) * 100.0, 120.0 + cos(angle) * 100.0, 47);
|
line(
|
||||||
|
160 as f32, 120 as f32,
|
||||||
|
160 as f32 + sin(angle) * 100 as f32,
|
||||||
|
120 as f32 + cos(angle) * 100 as f32,
|
||||||
|
47);
|
||||||
branch_if (i := i + 1) < 50: lines;
|
branch_if (i := i + 1) < 50: lines;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
65
logo.svg
Normal file
65
logo.svg
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="120"
|
||||||
|
height="120"
|
||||||
|
viewBox="0 0 120 120"
|
||||||
|
version="1.1"
|
||||||
|
id="svg5"
|
||||||
|
sodipodi:docname="logo.svg"
|
||||||
|
inkscape:version="1.1.1 (3bf5ae0d25, 2021-09-20, custom)"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview7"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="3.6041667"
|
||||||
|
inkscape:cx="21.780347"
|
||||||
|
inkscape:cy="63.260116"
|
||||||
|
inkscape:window-width="1916"
|
||||||
|
inkscape:window-height="1041"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="18"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="layer1" />
|
||||||
|
<defs
|
||||||
|
id="defs2" />
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<rect
|
||||||
|
style="fill:#85a6b2;fill-rule:evenodd;fill-opacity:1"
|
||||||
|
id="rect31"
|
||||||
|
width="112.05161"
|
||||||
|
height="109.64198"
|
||||||
|
x="3.9731982"
|
||||||
|
y="6.3613" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:117.333px;line-height:1.25;font-family:'Fira Code';-inkscape-font-specification:'Fira Code Bold';fill:#ffffff;fill-opacity:1;stroke:none"
|
||||||
|
x="-6.2686396"
|
||||||
|
y="117.70291"
|
||||||
|
id="text2691"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan2689"
|
||||||
|
x="-6.2686396"
|
||||||
|
y="117.70291">W8</tspan></text>
|
||||||
|
<circle
|
||||||
|
style="fill:#ffffff;stroke-width:1.32327"
|
||||||
|
id="path121"
|
||||||
|
cx="60.962471"
|
||||||
|
cy="6.7644148"
|
||||||
|
r="14.855442" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.9 KiB |
@@ -18,7 +18,7 @@ highlight_theme = "ascetic-white"
|
|||||||
[extra]
|
[extra]
|
||||||
# Put all your custom variables here
|
# Put all your custom variables here
|
||||||
juice_logo_name = "MicroW8"
|
juice_logo_name = "MicroW8"
|
||||||
juice_logo_path = "microw8.svg"
|
juice_logo_path = "img/microw8.svg"
|
||||||
juice_extra_menu = [
|
juice_extra_menu = [
|
||||||
{ title = "Github", link = "https://github.com/exoticorn/microw8" }
|
{ title = "Github", link = "https://github.com/exoticorn/microw8" }
|
||||||
]
|
]
|
||||||
5
site/static/img/microw8.svg
Normal file
5
site/static/img/microw8.svg
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
<svg width="120" height="120" version="1.1" viewBox="0 0 120 120" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="m3.9727 6.3613v27.945h7.8691l2.8281 66.549 6.9199-56.922h16.969l6.4375 56.922 4.1523-66.549h17.148l-9.5488 81.697h27.195c-4.1759-2.1972-7.3595-5.016-9.5234-8.4707-2.2464-3.6905-3.3691-7.6805-3.3691-11.973 0-4.7735 1.3845-8.9251 4.1523-12.455 2.7679-3.53 6.4981-6.3194 11.191-8.3652-4.2521-2.7277-7.3402-5.4948-9.2656-8.3027-1.8854-2.8481-2.8281-6.5783-2.8281-11.191 0-4.7334 1.223-8.8256 3.6699-12.275 2.4469-3.4498 5.7559-6.0981 9.9277-7.9434 4.212-1.8854 8.9647-2.8262 14.26-2.8262 5.2203 0 9.8397 0.84602 13.867 2.5234v-28.363h-40.227a14.855 14.855 0 0 1 0.019531 0.40234 14.855 14.855 0 0 1-14.855 14.855 14.855 14.855 0 0 1-14.855-14.855 14.855 14.855 0 0 1 0.052734-0.40234zm98.186 38.775c-3.0888 0-5.4939 0.863-7.2187 2.5879-1.6848 1.6848-2.5273 4.192-2.5273 7.5215 0 2.9283 0.98169 5.3538 2.9473 7.2793 1.9656 1.8854 5.0352 3.6113 9.207 5.1758 2.7277-2.0057 4.5928-3.971 5.5957-5.8965 1.0028-1.9656 1.5039-4.1129 1.5039-6.4395 0-2.9684-0.8017-5.4144-2.4062-7.3398-1.5644-1.9255-3.9326-2.8887-7.1016-2.8887zm-72.203 12.938-6.4902 57.93h12.393zm68.113 21.781c-2.4469 1.5644-4.3938 3.5502-5.8379 5.957-1.4441 2.4068-2.166 5.2741-2.166 8.6035 0 3.4498 1.0041 6.2781 3.0098 8.4844 2.0458 2.1662 5.0726 3.25 9.084 3.25 4.1317 0 7.142-1.1043 9.0274-3.3106 1.8854-2.2464 2.8281-4.8723 2.8281-7.8809 0-2.7679-0.56235-5.0153-1.6856-6.7402-1.0831-1.7249-2.7886-3.2096-5.1152-4.4531-2.3266-1.2836-5.3738-2.5864-9.1445-3.9102z" fill="#85a6b2" fill-rule="evenodd"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.6 KiB |
70
src/filewatcher.rs
Normal file
70
src/filewatcher.rs
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
use anyhow::{bail, Result};
|
||||||
|
use notify::{DebouncedEvent, Watcher, RecommendedWatcher};
|
||||||
|
use std::{
|
||||||
|
collections::BTreeSet,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
sync::mpsc,
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct FileWatcher {
|
||||||
|
_watcher: RecommendedWatcher,
|
||||||
|
watched_files: BTreeSet<PathBuf>,
|
||||||
|
rx: mpsc::Receiver<DebouncedEvent>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct FileWatcherBuilder(BTreeSet<PathBuf>);
|
||||||
|
|
||||||
|
impl FileWatcher {
|
||||||
|
pub fn builder() -> FileWatcherBuilder {
|
||||||
|
FileWatcherBuilder(BTreeSet::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn poll_changed_file(&self) -> Result<Option<PathBuf>> {
|
||||||
|
let event = self.rx.try_recv();
|
||||||
|
match event {
|
||||||
|
Ok(DebouncedEvent::Create(path) | DebouncedEvent::Write(path)) => {
|
||||||
|
let handle = same_file::Handle::from_path(&path)?;
|
||||||
|
for file in &self.watched_files {
|
||||||
|
if handle == same_file::Handle::from_path(file)? {
|
||||||
|
return Ok(Some(path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(mpsc::TryRecvError::Disconnected) => bail!("File watcher disconnected"),
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FileWatcherBuilder {
|
||||||
|
pub fn add_file<P: Into<PathBuf>>(&mut self, path: P) -> &mut Self {
|
||||||
|
self.0.insert(path.into());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(self) -> Result<FileWatcher> {
|
||||||
|
let mut directories: BTreeSet<&Path> = BTreeSet::new();
|
||||||
|
|
||||||
|
for file in &self.0 {
|
||||||
|
if let Some(directory) = file.parent() {
|
||||||
|
directories.insert(directory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let (tx, rx) = mpsc::channel();
|
||||||
|
let mut watcher = notify::watcher(tx, Duration::from_millis(100))?;
|
||||||
|
|
||||||
|
for directory in directories {
|
||||||
|
watcher.watch(directory, notify::RecursiveMode::NonRecursive)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(FileWatcher {
|
||||||
|
_watcher: watcher,
|
||||||
|
watched_files: self.0,
|
||||||
|
rx,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,6 +10,10 @@ use wasmtime::{
|
|||||||
Engine, GlobalType, Memory, MemoryType, Module, Mutability, Store, TypedFunc, ValType,
|
Engine, GlobalType, Memory, MemoryType, Module, Mutability, Store, TypedFunc, ValType,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
mod filewatcher;
|
||||||
|
|
||||||
|
pub use filewatcher::FileWatcher;
|
||||||
|
|
||||||
static GAMEPAD_KEYS: &'static [Key] = &[
|
static GAMEPAD_KEYS: &'static [Key] = &[
|
||||||
Key::Up,
|
Key::Up,
|
||||||
Key::Down,
|
Key::Down,
|
||||||
|
|||||||
20
src/main.rs
20
src/main.rs
@@ -1,17 +1,14 @@
|
|||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::process;
|
use std::process;
|
||||||
use std::sync::mpsc;
|
|
||||||
use std::time::Duration;
|
|
||||||
use std::{
|
use std::{
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
process::exit,
|
process::exit,
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
use anyhow::Result;
|
||||||
use notify::{DebouncedEvent, Watcher};
|
|
||||||
use pico_args::Arguments;
|
use pico_args::Arguments;
|
||||||
use uw8::MicroW8;
|
use uw8::{FileWatcher, MicroW8};
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
let mut args = Arguments::from_env();
|
let mut args = Arguments::from_env();
|
||||||
@@ -72,13 +69,14 @@ fn run(mut args: Arguments) -> Result<()> {
|
|||||||
uw8.set_timeout(timeout);
|
uw8.set_timeout(timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
let (tx, rx) = mpsc::channel();
|
let mut watcher = FileWatcher::builder();
|
||||||
let mut watcher = notify::watcher(tx, Duration::from_millis(100))?;
|
|
||||||
|
|
||||||
if watch_mode {
|
if watch_mode {
|
||||||
watcher.watch(&filename, notify::RecursiveMode::NonRecursive)?;
|
watcher.add_file(&filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let watcher = watcher.build()?;
|
||||||
|
|
||||||
if let Err(err) = start_cart(&filename, &mut uw8, &config) {
|
if let Err(err) = start_cart(&filename, &mut uw8, &config) {
|
||||||
eprintln!("Load error: {}", err);
|
eprintln!("Load error: {}", err);
|
||||||
if !watch_mode {
|
if !watch_mode {
|
||||||
@@ -87,15 +85,11 @@ fn run(mut args: Arguments) -> Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
while uw8.is_open() {
|
while uw8.is_open() {
|
||||||
match rx.try_recv() {
|
if watcher.poll_changed_file()?.is_some() {
|
||||||
Ok(DebouncedEvent::Create(_) | DebouncedEvent::Write(_)) => {
|
|
||||||
if let Err(err) = start_cart(&filename, &mut uw8, &config) {
|
if let Err(err) = start_cart(&filename, &mut uw8, &config) {
|
||||||
eprintln!("Load error: {}", err);
|
eprintln!("Load error: {}", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(mpsc::TryRecvError::Disconnected) => bail!("File watcher disconnected"),
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Err(err) = uw8.run_frame() {
|
if let Err(err) = uw8.run_frame() {
|
||||||
eprintln!("Runtime error: {}", err);
|
eprintln!("Runtime error: {}", err);
|
||||||
|
|||||||
Reference in New Issue
Block a user