2022-10-03 04:20:44 +00:00
|
|
|
#![cfg(target_arch = "wasm32")]
|
|
|
|
|
2022-10-11 21:40:12 +00:00
|
|
|
use std::rc::Rc;
|
|
|
|
use instant::Instant;
|
2022-10-03 04:20:44 +00:00
|
|
|
use wasm_bindgen::prelude::*;
|
2022-10-11 21:40:12 +00:00
|
|
|
use winit::dpi::LogicalSize;
|
|
|
|
use winit::event_loop::EventLoop;
|
|
|
|
use winit::window::{Window, WindowBuilder};
|
|
|
|
|
|
|
|
use moa_core::{Clock, System};
|
2022-10-03 04:20:44 +00:00
|
|
|
|
|
|
|
use crate::settings;
|
2022-10-11 21:40:12 +00:00
|
|
|
use crate::frontend::{self, PixelsFrontend, LoadSystemFn};
|
2022-10-03 04:20:44 +00:00
|
|
|
|
|
|
|
pub fn start(load: LoadSystemFn) {
|
|
|
|
settings::set_rom_data(include_bytes!("../sonic.bin").to_vec());
|
|
|
|
|
|
|
|
std::panic::set_hook(Box::new(console_error_panic_hook::hook));
|
2022-10-11 21:40:12 +00:00
|
|
|
console_log::init_with_level(log::Level::Warn).expect("error initializing logger");
|
2022-10-03 04:20:44 +00:00
|
|
|
|
2022-10-11 21:40:12 +00:00
|
|
|
//wasm_bindgen_futures::spawn_local(frontend::run(load));
|
2022-10-03 04:20:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[wasm_bindgen]
|
|
|
|
pub fn set_rom_data(rom_data: Vec<u8>) {
|
|
|
|
settings::set_rom_data(rom_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[wasm_bindgen]
|
2022-10-11 21:40:12 +00:00
|
|
|
pub fn request_stop() {
|
|
|
|
settings::request_stop();
|
2022-10-03 04:20:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[wasm_bindgen]
|
|
|
|
pub fn toggle_run() {
|
|
|
|
settings::toggle_run();
|
|
|
|
}
|
|
|
|
|
2022-10-11 21:40:12 +00:00
|
|
|
#[wasm_bindgen]
|
|
|
|
pub fn is_running() -> bool {
|
|
|
|
settings::get().run
|
|
|
|
}
|
|
|
|
|
2022-10-03 04:20:44 +00:00
|
|
|
#[wasm_bindgen]
|
|
|
|
pub fn set_speed(speed: f32) {
|
2022-10-11 21:40:12 +00:00
|
|
|
settings::get().speed = speed;
|
|
|
|
}
|
|
|
|
|
|
|
|
#[wasm_bindgen]
|
|
|
|
pub fn get_speed() -> f32 {
|
|
|
|
settings::get().speed
|
2022-10-03 04:20:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[wasm_bindgen]
|
|
|
|
pub fn get_frames_since() -> usize {
|
|
|
|
settings::get_frames_since()
|
|
|
|
}
|
|
|
|
|
2022-10-11 21:40:12 +00:00
|
|
|
#[wasm_bindgen]
|
|
|
|
pub struct HostHandle(PixelsFrontend);
|
|
|
|
|
|
|
|
#[wasm_bindgen]
|
|
|
|
pub fn new_host() -> HostHandle {
|
|
|
|
HostHandle(PixelsFrontend::new())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[wasm_bindgen]
|
|
|
|
pub fn host_run_loop(handle: HostHandle) {
|
|
|
|
wasm_bindgen_futures::spawn_local(frontend::run_loop(handle.0));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[wasm_bindgen]
|
|
|
|
pub struct SystemHandle(System);
|
|
|
|
|
|
|
|
#[wasm_bindgen]
|
|
|
|
pub struct LoadSystemFnHandle(LoadSystemFn);
|
|
|
|
|
|
|
|
impl LoadSystemFnHandle {
|
|
|
|
pub fn new(load: LoadSystemFn) -> Self {
|
|
|
|
Self(load)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[wasm_bindgen]
|
|
|
|
pub fn load_system(handle: &mut HostHandle, load: LoadSystemFnHandle) -> SystemHandle {
|
|
|
|
let system = load.0(&mut handle.0, settings::get().rom_data.clone()).unwrap();
|
|
|
|
SystemHandle(system)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[wasm_bindgen]
|
|
|
|
pub fn run_system_for(handle: &mut SystemHandle, nanos: u32) -> usize {
|
|
|
|
let run_timer = Instant::now();
|
|
|
|
let nanoseconds_per_frame = nanos as Clock;
|
|
|
|
//let nanoseconds_per_frame = (16_600_000 as f32 * settings::get().speed) as Clock;
|
|
|
|
if let Err(err) = handle.0.run_for(nanoseconds_per_frame) {
|
|
|
|
log::error!("{:?}", err);
|
|
|
|
}
|
|
|
|
let run_time = run_timer.elapsed().as_millis();
|
2022-10-14 03:22:29 +00:00
|
|
|
log::debug!("ran simulation for {:?}ms in {:?}ms", nanoseconds_per_frame / 1_000_000, run_time);
|
2022-10-11 21:40:12 +00:00
|
|
|
run_time as usize
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn create_window<T>(event_loop: &EventLoop<T>) -> Rc<Window> {
|
|
|
|
use web_sys::HtmlCanvasElement;
|
|
|
|
use wasm_bindgen::JsCast;
|
|
|
|
use winit::platform::web::{WindowExtWebSys, WindowBuilderExtWebSys};
|
|
|
|
|
|
|
|
let canvas = web_sys::window()
|
|
|
|
.and_then(|win| win.document())
|
|
|
|
.and_then(|doc| doc.get_element_by_id("video"))
|
|
|
|
.and_then(|el| el.dyn_into::<web_sys::HtmlCanvasElement>().ok())
|
|
|
|
.expect("document to have canvas");
|
|
|
|
|
|
|
|
let window = {
|
|
|
|
let size = LogicalSize::new(frontend::WIDTH as f64, frontend::HEIGHT as f64);
|
|
|
|
WindowBuilder::new()
|
|
|
|
.with_canvas(Some(canvas))
|
|
|
|
.with_title("Hello Pixels + Web")
|
2022-10-12 05:36:49 +00:00
|
|
|
//.with_inner_size(size)
|
|
|
|
//.with_min_inner_size(size)
|
2022-10-11 21:40:12 +00:00
|
|
|
.build(event_loop)
|
|
|
|
.expect("WindowBuilder error")
|
|
|
|
};
|
|
|
|
|
|
|
|
let window = Rc::new(window);
|
|
|
|
|
2022-10-12 05:36:49 +00:00
|
|
|
/*
|
2022-10-11 21:40:12 +00:00
|
|
|
// Retrieve current width and height dimensions of browser client window
|
|
|
|
let get_window_size = || {
|
|
|
|
let client_window = web_sys::window().unwrap();
|
|
|
|
LogicalSize::new(
|
|
|
|
client_window.inner_width().unwrap().as_f64().unwrap(),
|
|
|
|
client_window.inner_height().unwrap().as_f64().unwrap(),
|
|
|
|
)
|
|
|
|
};
|
|
|
|
|
|
|
|
// Initialize winit window with current dimensions of browser client
|
|
|
|
window.set_inner_size(get_window_size());
|
2022-10-12 05:36:49 +00:00
|
|
|
*/
|
2022-10-11 21:40:12 +00:00
|
|
|
|
|
|
|
let client_window = web_sys::window().unwrap();
|
|
|
|
|
|
|
|
/*
|
|
|
|
// Attach winit canvas to body element
|
|
|
|
web_sys::window()
|
|
|
|
.and_then(|win| win.document())
|
|
|
|
.and_then(|doc| doc.get_element_by_id("video-screen"))
|
|
|
|
.and_then(|el| {
|
|
|
|
while let Some(child) = el.first_child() {
|
|
|
|
el.remove_child(&child);
|
|
|
|
}
|
|
|
|
el.append_child(&web_sys::Element::from(window.canvas()))
|
|
|
|
.ok()
|
|
|
|
})
|
|
|
|
.expect("couldn't append canvas to document body");
|
|
|
|
*/
|
|
|
|
|
2022-10-12 05:36:49 +00:00
|
|
|
/*
|
2022-10-11 21:40:12 +00:00
|
|
|
{
|
|
|
|
let window = window.clone();
|
|
|
|
// Listen for resize event on browser client. Adjust winit window dimensions
|
|
|
|
// on event trigger
|
|
|
|
let closure = wasm_bindgen::closure::Closure::wrap(Box::new(move |_e: web_sys::Event| {
|
|
|
|
let size = get_window_size();
|
|
|
|
window.set_inner_size(size)
|
|
|
|
}) as Box<dyn FnMut(_)>);
|
|
|
|
client_window
|
|
|
|
.add_event_listener_with_callback("resize", closure.as_ref().unchecked_ref())
|
|
|
|
.unwrap();
|
|
|
|
closure.forget();
|
|
|
|
}
|
2022-10-12 05:36:49 +00:00
|
|
|
*/
|
2022-10-11 21:40:12 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
let mut update_timer = Instant::now();
|
|
|
|
let mut system = load(&mut host, settings::get().rom_data.clone()).unwrap();
|
|
|
|
let closure = wasm_bindgen::closure::Closure::wrap(Box::new(move |_e: web_sys::Event| {
|
|
|
|
let run_timer = Instant::now();
|
|
|
|
let nanoseconds_per_frame = (16_600_000 as f32 * settings::get().speed) as Clock;
|
|
|
|
if let Err(err) = system.run_for(nanoseconds_per_frame) {
|
|
|
|
log::error!("{:?}", err);
|
|
|
|
}
|
|
|
|
log::info!("ran simulation for {:?}ms in {:?}ms", nanoseconds_per_frame / 1_000_000, run_timer.elapsed().as_millis());
|
|
|
|
|
|
|
|
let settings = settings::get();
|
|
|
|
if settings.run {
|
|
|
|
//match load(&mut host.lock().unwrap(), settings.rom_data.clone()) {
|
|
|
|
// Ok(s) => { system = s; },
|
|
|
|
// Err(err) => log::error!("{:?}", err),
|
|
|
|
//}
|
|
|
|
}
|
|
|
|
}) as Box<dyn FnMut(_)>);
|
|
|
|
client_window
|
|
|
|
.set_interval_with_callback_and_timeout_and_arguments_0(closure.as_ref().unchecked_ref(), 17)
|
|
|
|
.unwrap();
|
|
|
|
closure.forget();
|
|
|
|
*/
|
|
|
|
|
|
|
|
window
|
|
|
|
}
|
|
|
|
|