mirror of
https://github.com/exoticorn/microw8.git
synced 2026-01-21 03:36:41 +01:00
Compare commits
4 Commits
d478d3ad49
...
v0.2.1-che
| Author | SHA1 | Date | |
|---|---|---|---|
| a20e569723 | |||
| 8a473cc9b9 | |||
| 4a4beded11 | |||
| 9d629be747 |
2272
Cargo.lock
generated
2272
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
20
Cargo.toml
20
Cargo.toml
@@ -11,21 +11,21 @@ native = ["wasmtime", "uw8-window", "cpal", "rubato" ]
|
|||||||
browser = ["warp", "tokio", "tokio-stream", "webbrowser"]
|
browser = ["warp", "tokio", "tokio-stream", "webbrowser"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wasmtime = { version = "5.0.0", optional = true }
|
wasmtime = { version = "0.37.0", optional = true }
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
env_logger = "0.10"
|
env_logger = "0.9"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
uw8-window = { path = "uw8-window", optional = true }
|
uw8-window = { path = "uw8-window", optional = true }
|
||||||
notify = "5"
|
notify = "4"
|
||||||
pico-args = "0.5"
|
pico-args = "0.4"
|
||||||
curlywas = { git = "https://github.com/exoticorn/curlywas.git", rev = "0e7ea50" }
|
curlywas = { git = "https://github.com/exoticorn/curlywas.git", rev = "0e7ea50" }
|
||||||
wat = "1"
|
wat = "1"
|
||||||
uw8-tool = { path = "uw8-tool" }
|
uw8-tool = { path = "uw8-tool" }
|
||||||
same-file = "1"
|
same-file = "1"
|
||||||
warp = { version = "0.3.3", optional = true }
|
warp = { version = "0.3.2", optional = true }
|
||||||
tokio = { version = "1.24.0", features = ["sync", "rt"], optional = true }
|
tokio = { version = "1.17.0", features = ["sync", "rt"], optional = true }
|
||||||
tokio-stream = { version = "0.1.11", features = ["sync"], optional = true }
|
tokio-stream = { version = "0.1.8", features = ["sync"], optional = true }
|
||||||
webbrowser = { version = "0.8.6", optional = true }
|
webbrowser = { version = "0.6.0", optional = true }
|
||||||
ansi_term = "0.12.1"
|
ansi_term = "0.12.1"
|
||||||
cpal = { version = "0.14.2", optional = true }
|
cpal = { version = "0.14.1", optional = true }
|
||||||
rubato = { version = "0.12.0", optional = true }
|
rubato = { version = "0.11.0", optional = true }
|
||||||
|
|||||||
Binary file not shown.
@@ -62,7 +62,6 @@ export fn sndGes(t: i32) -> f32 {
|
|||||||
let phase = channelState!GesChannelState.Phase;
|
let phase = channelState!GesChannelState.Phase;
|
||||||
|
|
||||||
let inline pulseWidth = channelReg?1;
|
let inline pulseWidth = channelReg?1;
|
||||||
let phaseShift = (pulseWidth - 128) * 255;
|
|
||||||
let invPhaseInc = 1 as f32 / phaseInc as f32;
|
let invPhaseInc = 1 as f32 / phaseInc as f32;
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
@@ -131,7 +130,7 @@ export fn sndGes(t: i32) -> f32 {
|
|||||||
let phaseInc = (freq * (65536.0 / 44100.0)) as i32;
|
let phaseInc = (freq * (65536.0 / 44100.0)) as i32;
|
||||||
|
|
||||||
let phase = channelState!GesChannelState.Phase;
|
let phase = channelState!GesChannelState.Phase;
|
||||||
if modSrc > ch {
|
if modSrc < ch {
|
||||||
phase = phase - (phaseInc << 6);
|
phase = phase - (phaseInc << 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -372,16 +372,7 @@ export fn printChar(char: i32) {
|
|||||||
global mut controlCodeLength = 0;
|
global mut controlCodeLength = 0;
|
||||||
|
|
||||||
fn printSingleChar(char: i32) {
|
fn printSingleChar(char: i32) {
|
||||||
if char >= 4 & char <= 6 {
|
if outputChannel >= 2 & (char < 4 | char > 6) {
|
||||||
outputChannel = char - 4;
|
|
||||||
if !outputChannel {
|
|
||||||
textCursorX = 0;
|
|
||||||
textCursorY = 0;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if outputChannel >= 2 {
|
|
||||||
logChar(char);
|
logChar(char);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -399,6 +390,15 @@ fn printSingleChar(char: i32) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if char >= 4 & char <= 6 {
|
||||||
|
outputChannel = char - 4;
|
||||||
|
if !outputChannel {
|
||||||
|
textCursorX = 0;
|
||||||
|
textCursorY = 0;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if char == 7 {
|
if char == 7 {
|
||||||
80?0 = 80?0 ^ 2;
|
80?0 = 80?0 ^ 2;
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,21 +1,18 @@
|
|||||||
use anyhow::{anyhow, bail, Result};
|
use anyhow::{anyhow, bail, Result};
|
||||||
use notify::{Event, EventKind, RecommendedWatcher, Watcher};
|
use notify::{DebouncedEvent, RecommendedWatcher, Watcher};
|
||||||
use std::{collections::BTreeSet, path::PathBuf, sync::mpsc};
|
use std::{collections::BTreeSet, path::PathBuf, sync::mpsc, time::Duration};
|
||||||
|
|
||||||
pub struct FileWatcher {
|
pub struct FileWatcher {
|
||||||
watcher: RecommendedWatcher,
|
watcher: RecommendedWatcher,
|
||||||
watched_files: BTreeSet<PathBuf>,
|
watched_files: BTreeSet<PathBuf>,
|
||||||
directories: BTreeSet<PathBuf>,
|
directories: BTreeSet<PathBuf>,
|
||||||
rx: mpsc::Receiver<Event>,
|
rx: mpsc::Receiver<DebouncedEvent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FileWatcher {
|
impl FileWatcher {
|
||||||
pub fn new() -> Result<FileWatcher> {
|
pub fn new() -> Result<FileWatcher> {
|
||||||
let (tx, rx) = mpsc::channel();
|
let (tx, rx) = mpsc::channel();
|
||||||
let watcher = notify::recommended_watcher(move |res| match res {
|
let watcher = notify::watcher(tx, Duration::from_millis(100))?;
|
||||||
Ok(event) => _ = tx.send(event),
|
|
||||||
Err(err) => eprintln!("Error watching for file changes: {err}"),
|
|
||||||
})?;
|
|
||||||
Ok(FileWatcher {
|
Ok(FileWatcher {
|
||||||
watcher,
|
watcher,
|
||||||
watched_files: BTreeSet::new(),
|
watched_files: BTreeSet::new(),
|
||||||
@@ -39,20 +36,16 @@ impl FileWatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn poll_changed_file(&self) -> Result<Option<PathBuf>> {
|
pub fn poll_changed_file(&self) -> Result<Option<PathBuf>> {
|
||||||
match self.rx.try_recv() {
|
let event = self.rx.try_recv();
|
||||||
Ok(event) => match event.kind {
|
match event {
|
||||||
EventKind::Create(_) | EventKind::Modify(_) => {
|
Ok(DebouncedEvent::Create(path) | DebouncedEvent::Write(path)) => {
|
||||||
for path in event.paths {
|
let handle = same_file::Handle::from_path(&path)?;
|
||||||
let handle = same_file::Handle::from_path(&path)?;
|
for file in &self.watched_files {
|
||||||
for file in &self.watched_files {
|
if handle == same_file::Handle::from_path(file)? {
|
||||||
if handle == same_file::Handle::from_path(file)? {
|
return Ok(Some(path));
|
||||||
return Ok(Some(path));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => (),
|
}
|
||||||
},
|
|
||||||
Err(mpsc::TryRecvError::Disconnected) => bail!("File watcher disconnected"),
|
Err(mpsc::TryRecvError::Disconnected) => bail!("File watcher disconnected"),
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -93,7 +93,7 @@ impl super::Runtime for MicroW8 {
|
|||||||
linker.define("env", "memory", memory)?;
|
linker.define("env", "memory", memory)?;
|
||||||
|
|
||||||
let loader_instance = linker.instantiate(&mut store, &self.loader_module)?;
|
let loader_instance = linker.instantiate(&mut store, &self.loader_module)?;
|
||||||
let load_uw8 = loader_instance.get_typed_func::<i32, i32>(&mut store, "load_uw8")?;
|
let load_uw8 = loader_instance.get_typed_func::<i32, i32, _>(&mut store, "load_uw8")?;
|
||||||
|
|
||||||
let platform_data = include_bytes!("../platform/bin/platform.uw8");
|
let platform_data = include_bytes!("../platform/bin/platform.uw8");
|
||||||
memory.data_mut(&mut store)[..platform_data.len()].copy_from_slice(platform_data);
|
memory.data_mut(&mut store)[..platform_data.len()].copy_from_slice(platform_data);
|
||||||
@@ -131,8 +131,12 @@ impl super::Runtime for MicroW8 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let instance = linker.instantiate(&mut store, &module)?;
|
let instance = linker.instantiate(&mut store, &module)?;
|
||||||
let end_frame = platform_instance.get_typed_func::<(), ()>(&mut store, "endFrame")?;
|
let end_frame = platform_instance.get_typed_func::<(), (), _>(&mut store, "endFrame")?;
|
||||||
let update = instance.get_typed_func::<(), ()>(&mut store, "upd").ok();
|
let update = instance.get_typed_func::<(), (), _>(&mut store, "upd").ok();
|
||||||
|
|
||||||
|
if let Some(start) = instance.get_typed_func::<(), (), _>(&mut store, "start").ok() {
|
||||||
|
start.call(&mut store, ())?;
|
||||||
|
}
|
||||||
|
|
||||||
let (sound_tx, stream) = if self.disable_audio {
|
let (sound_tx, stream) = if self.disable_audio {
|
||||||
(None, None)
|
(None, None)
|
||||||
@@ -313,8 +317,8 @@ fn init_sound(
|
|||||||
let instance = linker.instantiate(&mut store, module)?;
|
let instance = linker.instantiate(&mut store, module)?;
|
||||||
|
|
||||||
let snd = instance
|
let snd = instance
|
||||||
.get_typed_func::<(i32,), f32>(&mut store, "snd")
|
.get_typed_func::<(i32,), f32, _>(&mut store, "snd")
|
||||||
.or_else(|_| platform_instance.get_typed_func::<(i32,), f32>(&mut store, "sndGes"))?;
|
.or_else(|_| platform_instance.get_typed_func::<(i32,), f32, _>(&mut store, "sndGes"))?;
|
||||||
|
|
||||||
let host = cpal::default_host();
|
let host = cpal::default_host();
|
||||||
let device = host
|
let device = host
|
||||||
@@ -419,6 +423,14 @@ fn init_sound(
|
|||||||
mem[64..68].copy_from_slice(¤t_time.to_le_bytes());
|
mem[64..68].copy_from_slice(¤t_time.to_le_bytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn clamp_sample(s: f32) -> f32 {
|
||||||
|
if s.is_nan() {
|
||||||
|
0.0
|
||||||
|
} else {
|
||||||
|
s.max(-1.0).min(1.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(ref mut resampler) = resampler {
|
if let Some(ref mut resampler) = resampler {
|
||||||
while !buffer.is_empty() {
|
while !buffer.is_empty() {
|
||||||
let copy_size = resampler.output_buffers[0]
|
let copy_size = resampler.output_buffers[0]
|
||||||
@@ -429,10 +441,12 @@ fn init_sound(
|
|||||||
resampler.input_buffers[0].clear();
|
resampler.input_buffers[0].clear();
|
||||||
resampler.input_buffers[1].clear();
|
resampler.input_buffers[1].clear();
|
||||||
for _ in 0..resampler.resampler.input_frames_next() {
|
for _ in 0..resampler.resampler.input_frames_next() {
|
||||||
resampler.input_buffers[0]
|
resampler.input_buffers[0].push(clamp_sample(
|
||||||
.push(snd.call(&mut store, (sample_index,)).unwrap_or(0.0));
|
snd.call(&mut store, (sample_index,)).unwrap_or(0.0),
|
||||||
resampler.input_buffers[1]
|
));
|
||||||
.push(snd.call(&mut store, (sample_index + 1,)).unwrap_or(0.0));
|
resampler.input_buffers[1].push(clamp_sample(
|
||||||
|
snd.call(&mut store, (sample_index + 1,)).unwrap_or(0.0),
|
||||||
|
));
|
||||||
sample_index = sample_index.wrapping_add(2);
|
sample_index = sample_index.wrapping_add(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -458,7 +472,7 @@ fn init_sound(
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for v in buffer {
|
for v in buffer {
|
||||||
*v = snd.call(&mut store, (sample_index,)).unwrap_or(0.0);
|
*v = clamp_sample(snd.call(&mut store, (sample_index,)).unwrap_or(0.0));
|
||||||
sample_index = sample_index.wrapping_add(1);
|
sample_index = sample_index.wrapping_add(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ use warp::{http::Response, Filter};
|
|||||||
pub struct RunWebServer {
|
pub struct RunWebServer {
|
||||||
cart: Arc<Mutex<Vec<u8>>>,
|
cart: Arc<Mutex<Vec<u8>>>,
|
||||||
tx: broadcast::Sender<()>,
|
tx: broadcast::Sender<()>,
|
||||||
|
socket_addr: SocketAddr,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RunWebServer {
|
impl RunWebServer {
|
||||||
@@ -18,8 +19,13 @@ impl RunWebServer {
|
|||||||
let cart = Arc::new(Mutex::new(Vec::new()));
|
let cart = Arc::new(Mutex::new(Vec::new()));
|
||||||
let (tx, _) = broadcast::channel(1);
|
let (tx, _) = broadcast::channel(1);
|
||||||
|
|
||||||
|
let socket_addr = "127.0.0.1:3030"
|
||||||
|
.parse::<SocketAddr>()
|
||||||
|
.expect("Failed to parse socket address");
|
||||||
|
|
||||||
let server_cart = cart.clone();
|
let server_cart = cart.clone();
|
||||||
let server_tx = tx.clone();
|
let server_tx = tx.clone();
|
||||||
|
let server_addr = socket_addr.clone();
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
let rt = tokio::runtime::Builder::new_current_thread()
|
let rt = tokio::runtime::Builder::new_current_thread()
|
||||||
.enable_io()
|
.enable_io()
|
||||||
@@ -47,24 +53,26 @@ impl RunWebServer {
|
|||||||
warp::sse::reply(warp::sse::keep_alive().stream(event_stream(&server_tx)))
|
warp::sse::reply(warp::sse::keep_alive().stream(event_stream(&server_tx)))
|
||||||
});
|
});
|
||||||
|
|
||||||
let socket_addr = "127.0.0.1:3030"
|
let server_future = warp::serve(html.or(cart).or(events)).bind(server_addr);
|
||||||
.parse::<SocketAddr>()
|
|
||||||
.expect("Failed to parse socket address");
|
|
||||||
|
|
||||||
let server_future = warp::serve(html.or(cart).or(events)).bind(socket_addr);
|
|
||||||
println!("Point browser at http://{}", socket_addr);
|
|
||||||
let _ignore_result = webbrowser::open(&format!("http://{}", socket_addr));
|
|
||||||
server_future.await
|
server_future.await
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
RunWebServer { cart, tx }
|
RunWebServer {
|
||||||
|
cart,
|
||||||
|
tx,
|
||||||
|
socket_addr,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl super::Runtime for RunWebServer {
|
impl super::Runtime for RunWebServer {
|
||||||
fn load(&mut self, module_data: &[u8]) -> Result<()> {
|
fn load(&mut self, module_data: &[u8]) -> Result<()> {
|
||||||
if let Ok(mut lock) = self.cart.lock() {
|
if let Ok(mut lock) = self.cart.lock() {
|
||||||
|
if lock.is_empty() && !module_data.is_empty() {
|
||||||
|
println!("Point browser at http://{}", self.socket_addr);
|
||||||
|
let _ignore_result = webbrowser::open(&format!("http://{}", self.socket_addr));
|
||||||
|
}
|
||||||
lock.clear();
|
lock.clear();
|
||||||
lock.extend_from_slice(module_data);
|
lock.extend_from_slice(module_data);
|
||||||
}
|
}
|
||||||
@@ -86,4 +94,4 @@ impl Default for RunWebServer {
|
|||||||
fn default() -> RunWebServer {
|
fn default() -> RunWebServer {
|
||||||
RunWebServer::new()
|
RunWebServer::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
5
test/start_fn.cwa
Normal file
5
test/start_fn.cwa
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
include "../examples/include/microw8-api.cwa"
|
||||||
|
|
||||||
|
export fn start() {
|
||||||
|
printChar('Test');
|
||||||
|
}
|
||||||
13
test/text_modes.cwa
Normal file
13
test/text_modes.cwa
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
include "../examples/include/microw8-api.cwa"
|
||||||
|
|
||||||
|
export fn upd() {
|
||||||
|
printString(USER_MEM);
|
||||||
|
}
|
||||||
|
|
||||||
|
data USER_MEM {
|
||||||
|
i8(12, 31, 5, 6) "Text mode"
|
||||||
|
i8(5, 31, 4, 5) "Graphics mode"
|
||||||
|
i8(6) "Console output\nSecond line\n"
|
||||||
|
i8(4, 31, 4, 12) "Back to text mode"
|
||||||
|
i8(0)
|
||||||
|
}
|
||||||
836
uw8-window/Cargo.lock
generated
836
uw8-window/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -6,13 +6,13 @@ edition = "2021"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
winit = "0.27.5"
|
winit = "0.26.1"
|
||||||
env_logger = "0.10"
|
env_logger = "0.9"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
pico-args = "0.5"
|
pico-args = "0.4"
|
||||||
wgpu = "0.15"
|
wgpu = "0.13.1"
|
||||||
pollster = "0.2.5"
|
pollster = "0.2"
|
||||||
bytemuck = { version = "1.13", features = [ "derive" ] }
|
bytemuck = { version = "1.4", features = [ "derive" ] }
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
minifb = { version = "0.23.0", default-features = false, features = ["x11"] }
|
minifb = { version = "0.23.0", default-features = false, features = ["x11"] }
|
||||||
winapi = { version = "0.3.9", features = [ "timeapi" ] }
|
winapi = "0.3.9"
|
||||||
|
|||||||
@@ -36,36 +36,36 @@ fn sample_pixel(coords: vec2<i32>, offset: vec4<f32>) -> vec3<f32> {
|
|||||||
|
|
||||||
@fragment
|
@fragment
|
||||||
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
||||||
let pixelf = floor(in.tex_coords);
|
let pixel = floor(in.tex_coords);
|
||||||
let o = vec2<f32>(0.5) - (in.tex_coords - pixelf);
|
let o = vec2<f32>(0.5) - (in.tex_coords - pixel);
|
||||||
let pixel = vec2<i32>(pixelf);
|
let pixel = vec2<i32>(pixel);
|
||||||
|
|
||||||
let offset_x = o.xxxx + vec4<f32>(-0.125, 0.375, 0.125, -0.375) * uniforms.texture_scale.z;
|
let offset_x = o.xxxx + vec4<f32>(-0.125, 0.375, 0.125, -0.375) * uniforms.texture_scale.z;
|
||||||
let offset_y = o.yyyy + vec4<f32>(-0.375, -0.125, 0.375, 0.125) * uniforms.texture_scale.z;
|
let offset_y = o.yyyy + vec4<f32>(-0.375, -0.125, 0.375, 0.125) * uniforms.texture_scale.z;
|
||||||
|
|
||||||
var offset_x0 = max(abs(offset_x + vec4<f32>(-1.0)) - vec4<f32>(0.5), vec4<f32>(0.0));
|
let offset_x0 = max(abs(offset_x + vec4<f32>(-1.0)) - vec4<f32>(0.5), vec4<f32>(0.0));
|
||||||
var offset_x1 = max(abs(offset_x) - vec4<f32>(0.5), vec4<f32>(0.0));
|
let offset_x1 = max(abs(offset_x) - vec4<f32>(0.5), vec4<f32>(0.0));
|
||||||
var offset_x2 = max(abs(offset_x + vec4<f32>(1.0)) - vec4<f32>(0.5), vec4<f32>(0.0));
|
let offset_x2 = max(abs(offset_x + vec4<f32>(1.0)) - vec4<f32>(0.5), vec4<f32>(0.0));
|
||||||
|
|
||||||
offset_x0 = offset_x0 * offset_x0;
|
let offset_x0 = offset_x0 * offset_x0;
|
||||||
offset_x1 = offset_x1 * offset_x1;
|
let offset_x1 = offset_x1 * offset_x1;
|
||||||
offset_x2 = offset_x2 * offset_x2;
|
let offset_x2 = offset_x2 * offset_x2;
|
||||||
|
|
||||||
var offset_yr = offset_y + vec4<f32>(-1.0);
|
let offset_yr = offset_y + vec4<f32>(-1.0);
|
||||||
offset_yr = vec4<f32>(0.02) + offset_yr * offset_yr;
|
let offset_yr = vec4<f32>(0.02) + offset_yr * offset_yr;
|
||||||
|
|
||||||
var acc = sample_pixel(pixel + vec2<i32>(-1, -1), offset_x0 + offset_yr);
|
var acc = sample_pixel(pixel + vec2<i32>(-1, -1), offset_x0 + offset_yr);
|
||||||
acc = acc + sample_pixel(pixel + vec2<i32>(0, -1), offset_x1 + offset_yr);
|
acc = acc + sample_pixel(pixel + vec2<i32>(0, -1), offset_x1 + offset_yr);
|
||||||
acc = acc + sample_pixel(pixel + vec2<i32>(1, -1), offset_x2 + offset_yr);
|
acc = acc + sample_pixel(pixel + vec2<i32>(1, -1), offset_x2 + offset_yr);
|
||||||
|
|
||||||
offset_yr = vec4<f32>(0.02) + offset_y * offset_y;
|
let offset_yr = vec4<f32>(0.02) + offset_y * offset_y;
|
||||||
|
|
||||||
acc = acc + sample_pixel(pixel + vec2<i32>(-1, 0), offset_x0 + offset_yr);
|
acc = acc + sample_pixel(pixel + vec2<i32>(-1, 0), offset_x0 + offset_yr);
|
||||||
acc = acc + sample_pixel(pixel, offset_x1 + offset_yr);
|
acc = acc + sample_pixel(pixel, offset_x1 + offset_yr);
|
||||||
acc = acc + sample_pixel(pixel + vec2<i32>(1, 0), offset_x2 + offset_yr);
|
acc = acc + sample_pixel(pixel + vec2<i32>(1, 0), offset_x2 + offset_yr);
|
||||||
|
|
||||||
offset_yr = offset_y + vec4<f32>(1.0);
|
let offset_yr = offset_y + vec4<f32>(1.0);
|
||||||
offset_yr = vec4<f32>(0.02) + offset_yr * offset_yr;
|
let offset_yr = vec4<f32>(0.02) + offset_yr * offset_yr;
|
||||||
|
|
||||||
acc = acc + sample_pixel(pixel + vec2<i32>(-1, 1), offset_x0 + offset_yr);
|
acc = acc + sample_pixel(pixel + vec2<i32>(-1, 1), offset_x0 + offset_yr);
|
||||||
acc = acc + sample_pixel(pixel + vec2<i32>(0, 1), offset_x1 + offset_yr);
|
acc = acc + sample_pixel(pixel + vec2<i32>(0, 1), offset_x1 + offset_yr);
|
||||||
|
|||||||
@@ -53,8 +53,8 @@ impl Window {
|
|||||||
|
|
||||||
window.set_cursor_visible(false);
|
window.set_cursor_visible(false);
|
||||||
|
|
||||||
let instance = wgpu::Instance::new(Default::default());
|
let instance = wgpu::Instance::new(wgpu::Backends::all());
|
||||||
let surface = unsafe { instance.create_surface(&window) }?;
|
let surface = unsafe { instance.create_surface(&window) };
|
||||||
let adapter = instance
|
let adapter = instance
|
||||||
.request_adapter(&wgpu::RequestAdapterOptions {
|
.request_adapter(&wgpu::RequestAdapterOptions {
|
||||||
power_preference: wgpu::PowerPreference::LowPower,
|
power_preference: wgpu::PowerPreference::LowPower,
|
||||||
@@ -71,8 +71,11 @@ impl Window {
|
|||||||
let palette_screen_mode = PaletteScreenMode::new(&device);
|
let palette_screen_mode = PaletteScreenMode::new(&device);
|
||||||
|
|
||||||
let surface_config = wgpu::SurfaceConfiguration {
|
let surface_config = wgpu::SurfaceConfiguration {
|
||||||
|
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
|
||||||
|
format: surface.get_supported_formats(&adapter)[0],
|
||||||
|
width: window.inner_size().width,
|
||||||
|
height: window.inner_size().height,
|
||||||
present_mode: wgpu::PresentMode::AutoNoVsync,
|
present_mode: wgpu::PresentMode::AutoNoVsync,
|
||||||
..surface.get_default_config(&adapter, window.inner_size().width, window.inner_size().height).expect("Surface incompatible with adapter")
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let filter: Box<dyn Filter> = create_filter(
|
let filter: Box<dyn Filter> = create_filter(
|
||||||
@@ -354,7 +357,6 @@ impl PaletteScreenMode {
|
|||||||
format: wgpu::TextureFormat::R8Uint,
|
format: wgpu::TextureFormat::R8Uint,
|
||||||
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
|
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
|
||||||
label: None,
|
label: None,
|
||||||
view_formats: &[]
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let palette_texture = device.create_texture(&wgpu::TextureDescriptor {
|
let palette_texture = device.create_texture(&wgpu::TextureDescriptor {
|
||||||
@@ -369,7 +371,6 @@ impl PaletteScreenMode {
|
|||||||
format: wgpu::TextureFormat::Rgba8UnormSrgb,
|
format: wgpu::TextureFormat::Rgba8UnormSrgb,
|
||||||
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
|
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
|
||||||
label: None,
|
label: None,
|
||||||
view_formats: &[]
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let screen_texture = device.create_texture(&wgpu::TextureDescriptor {
|
let screen_texture = device.create_texture(&wgpu::TextureDescriptor {
|
||||||
@@ -384,7 +385,6 @@ impl PaletteScreenMode {
|
|||||||
format: wgpu::TextureFormat::Rgba8UnormSrgb,
|
format: wgpu::TextureFormat::Rgba8UnormSrgb,
|
||||||
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::RENDER_ATTACHMENT,
|
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::RENDER_ATTACHMENT,
|
||||||
label: None,
|
label: None,
|
||||||
view_formats: &[]
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let framebuffer_texture_view =
|
let framebuffer_texture_view =
|
||||||
|
|||||||
@@ -263,6 +263,10 @@ export default function MicroW8(screen, config = {}) {
|
|||||||
window.addEventListener('blur', () => updateVisibility(false), { signal: abortController.signal });
|
window.addEventListener('blur', () => updateVisibility(false), { signal: abortController.signal });
|
||||||
updateVisibility(document.hasFocus());
|
updateVisibility(document.hasFocus());
|
||||||
|
|
||||||
|
if (instance.exports.start) {
|
||||||
|
instance.exports.start();
|
||||||
|
}
|
||||||
|
|
||||||
function mainloop() {
|
function mainloop() {
|
||||||
if (!keepRunning) {
|
if (!keepRunning) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in New Issue
Block a user