Compare commits
No commits in common. "fc6516cbb2d35eb431b3b397c88ec38067302036" and "36e46d3780a972ca314388ec249eaa4289490803" have entirely different histories.
fc6516cbb2
...
36e46d3780
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"recommendations": [
|
||||
"rust-lang.rust-analyzer",
|
||||
"matklad.rust-analyzer",
|
||||
"tamasfe.even-better-toml",
|
||||
"serayuzgur.crates",
|
||||
"vadimcn.vscode-lldb",
|
||||
|
|
File diff suppressed because it is too large
Load Diff
11
Cargo.toml
11
Cargo.toml
|
@ -10,9 +10,12 @@ edition = "2021"
|
|||
anyhow = "1.0"
|
||||
bitfield = "0.13"
|
||||
clap = { version = "3.1", features = ["cargo"] }
|
||||
gilrs = "0.9"
|
||||
egui-wgpu = "0.18"
|
||||
egui-winit = "0.18"
|
||||
gilrs = "0.8"
|
||||
winit = "0.26"
|
||||
egui = "0.15"
|
||||
wgpu = "0.11"
|
||||
egui_wgpu_backend = "0.14"
|
||||
egui_winit_platform = "0.12"
|
||||
pollster = "0.2"
|
||||
rodio = "0.15"
|
||||
rtrb = "0.2"
|
||||
|
@ -20,7 +23,7 @@ directories-next = "2.0"
|
|||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["std", "env-filter"] }
|
||||
thiserror = "1.0"
|
||||
once_cell = "1.12"
|
||||
once_cell = "1.10"
|
||||
|
||||
[profile.release]
|
||||
debug = true
|
||||
|
|
|
@ -4,14 +4,14 @@ use crate::cartridge::Cartridge;
|
|||
use crate::cpu::Cpu;
|
||||
use crate::{Cycle, GB_HEIGHT, GB_WIDTH};
|
||||
use clap::crate_name;
|
||||
use egui_winit::winit::event::KeyboardInput;
|
||||
use egui_winit::winit::event_loop::ControlFlow;
|
||||
use gilrs::Gilrs;
|
||||
use std::fs::File;
|
||||
use std::io::{Read, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::time::Duration;
|
||||
use thiserror::Error;
|
||||
use winit::event::KeyboardInput;
|
||||
use winit::event_loop::ControlFlow;
|
||||
|
||||
pub const SM83_CYCLE_TIME: Duration = Duration::from_nanos(1_000_000_000 / SM83_CLOCK_SPEED);
|
||||
pub const CYCLES_IN_FRAME: Cycle = 456 * 154; // 456 Cycles times 154 scanlines
|
||||
|
|
64
src/gui.rs
64
src/gui.rs
|
@ -1,9 +1,6 @@
|
|||
use egui_wgpu::wgpu;
|
||||
use egui_winit::egui;
|
||||
use egui_winit::winit;
|
||||
|
||||
use egui::{ClippedPrimitive, Context, TextureId};
|
||||
use egui_wgpu::renderer::{RenderPass, ScreenDescriptor};
|
||||
use egui::{ClippedMesh, CtxRef, TextureId};
|
||||
use egui_wgpu_backend::{BackendError, RenderPass, ScreenDescriptor};
|
||||
use egui_winit_platform::Platform;
|
||||
use wgpu::{
|
||||
Adapter, CommandEncoder, Device, Extent3d, FilterMode, Instance, Queue, RequestDeviceError,
|
||||
Surface, SurfaceConfiguration, SurfaceTexture, Texture, TextureFormat, TextureUsages,
|
||||
|
@ -124,6 +121,20 @@ pub fn surface_config(window: &Window, format: TextureFormat) -> SurfaceConfigur
|
|||
}
|
||||
}
|
||||
|
||||
pub fn platform_desc(window: &Window) -> Platform {
|
||||
use egui::FontDefinitions;
|
||||
use egui_winit_platform::PlatformDescriptor;
|
||||
|
||||
let size = window.inner_size();
|
||||
Platform::new(PlatformDescriptor {
|
||||
physical_width: size.width as u32,
|
||||
physical_height: size.height as u32,
|
||||
scale_factor: window.scale_factor(),
|
||||
font_definitions: FontDefinitions::default(),
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn texture_size() -> Extent3d {
|
||||
Extent3d {
|
||||
width: GB_WIDTH as u32,
|
||||
|
@ -173,6 +184,14 @@ pub fn write_to_texture(
|
|||
);
|
||||
}
|
||||
|
||||
pub fn expose_texture_to_egui(
|
||||
render_pass: &mut RenderPass,
|
||||
device: &Device,
|
||||
texture: &Texture,
|
||||
) -> TextureId {
|
||||
render_pass.egui_texture_from_wgpu_texture(device, texture, FILTER_MODE)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn create_view(frame: &SurfaceTexture) -> TextureView {
|
||||
use wgpu::TextureViewDescriptor;
|
||||
|
@ -189,19 +208,31 @@ pub fn create_command_encoder(device: &Device) -> CommandEncoder {
|
|||
})
|
||||
}
|
||||
|
||||
car#[inline]
|
||||
#[inline]
|
||||
pub fn create_screen_descriptor(
|
||||
window: &Window,
|
||||
config: &SurfaceConfiguration,
|
||||
) -> ScreenDescriptor {
|
||||
ScreenDescriptor {
|
||||
physical_width: config.width,
|
||||
physical_height: config.height,
|
||||
scale_factor: window.scale_factor() as f32,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn execute_render_pass(
|
||||
render_pass: &mut RenderPass,
|
||||
encoder: &mut CommandEncoder,
|
||||
view: &TextureView,
|
||||
jobs: Vec<ClippedPrimitive>,
|
||||
jobs: Vec<ClippedMesh>,
|
||||
descriptor: &ScreenDescriptor,
|
||||
) {
|
||||
) -> Result<(), BackendError> {
|
||||
render_pass.execute(encoder, view, &jobs, descriptor, Some(wgpu::Color::BLACK))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn draw_egui(cpu: &Cpu, app: &mut GuiState, ctx: &Context, texture_id: TextureId) {
|
||||
pub fn draw_egui(cpu: &Cpu, app: &mut GuiState, ctx: &CtxRef, texture_id: TextureId) {
|
||||
use crate::{cpu, instruction, ppu};
|
||||
|
||||
fn selectable_text(ui: &mut egui::Ui, mut text: &str) -> egui::Response {
|
||||
|
@ -209,7 +240,7 @@ pub fn draw_egui(cpu: &Cpu, app: &mut GuiState, ctx: &Context, texture_id: Textu
|
|||
}
|
||||
|
||||
egui::TopBottomPanel::top("top_panel").show(ctx, |ui| {
|
||||
ui.menu_button("File", |ui| {
|
||||
egui::menu::menu(ui, "File", |ui| {
|
||||
if ui.button("Quit").clicked() {
|
||||
app.quit = true;
|
||||
}
|
||||
|
@ -291,12 +322,9 @@ pub fn draw_egui(cpu: &Cpu, app: &mut GuiState, ctx: &Context, texture_id: Textu
|
|||
ui.horizontal(|ui| {
|
||||
let ie = cpu.int_enable();
|
||||
|
||||
let style = ctx.style();
|
||||
let font_id = egui::TextStyle::Body.resolve(&style);
|
||||
|
||||
let r_len = ctx.fonts().glyph_width(&font_id, 'R');
|
||||
let e_len = ctx.fonts().glyph_width(&font_id, 'E');
|
||||
let q_len = ctx.fonts().glyph_width(&font_id, 'Q');
|
||||
let r_len = ctx.fonts().glyph_width(egui::TextStyle::Body, 'R');
|
||||
let e_len = ctx.fonts().glyph_width(egui::TextStyle::Body, 'E');
|
||||
let q_len = ctx.fonts().glyph_width(egui::TextStyle::Body, 'Q');
|
||||
|
||||
ui.label("IE:");
|
||||
ui.add_space(q_len - (e_len - r_len));
|
||||
|
@ -322,7 +350,7 @@ pub fn draw_egui(cpu: &Cpu, app: &mut GuiState, ctx: &Context, texture_id: Textu
|
|||
}
|
||||
|
||||
pub mod kbd {
|
||||
use egui_winit::winit::event::{ElementState, KeyboardInput, VirtualKeyCode};
|
||||
use winit::event::{ElementState, KeyboardInput, VirtualKeyCode};
|
||||
|
||||
pub fn space_released(input: &KeyboardInput) -> bool {
|
||||
let keycode = input.virtual_keycode;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use egui_winit::winit::event::{ElementState, KeyboardInput, VirtualKeyCode};
|
||||
use gilrs::{Button, Event as GamepadEvent, EventType as GamepadEventType};
|
||||
use winit::event::{ElementState, KeyboardInput, VirtualKeyCode};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Joypad {
|
||||
|
|
49
src/main.rs
49
src/main.rs
|
@ -1,16 +1,15 @@
|
|||
use std::time::Instant;
|
||||
|
||||
use clap::{crate_authors, crate_description, crate_name, crate_version, Arg, Command};
|
||||
use egui_wgpu::renderer::RenderPass;
|
||||
use egui_wgpu_backend::RenderPass;
|
||||
use gb::gui::EmuMode;
|
||||
use gb::{emu, gui};
|
||||
use gilrs::Gilrs;
|
||||
use gui::GuiState;
|
||||
use rodio::{OutputStream, Sink};
|
||||
use tracing_subscriber::EnvFilter;
|
||||
|
||||
use egui_winit::winit::event::{Event, WindowEvent};
|
||||
use egui_winit::winit::event_loop::{EventLoop, EventLoopProxy};
|
||||
use winit::event::{Event, WindowEvent};
|
||||
use winit::event_loop::EventLoop;
|
||||
|
||||
const AUDIO_ENABLED: bool = true;
|
||||
|
||||
|
@ -49,7 +48,7 @@ fn main() {
|
|||
|
||||
// --Here lies a lot of winit + wgpu Boilerplate--
|
||||
let event_loop: EventLoop<Event<()>> = EventLoop::with_user_event();
|
||||
let window = gui::build_window(&event_loop).expect("create winit window");
|
||||
let window = gui::build_window(&event_loop).expect("build window");
|
||||
|
||||
let (instance, surface) = gui::create_surface(&window);
|
||||
let adapter = gui::request_adapter(&instance, &surface).expect("request adaptor");
|
||||
|
@ -60,7 +59,7 @@ fn main() {
|
|||
|
||||
let mut config = gui::surface_config(&window, format);
|
||||
surface.configure(&device, &config);
|
||||
let mut state = egui_winit::State::new(8192, &window);
|
||||
let mut platform = gui::platform_desc(&window);
|
||||
let mut render_pass = RenderPass::new(&device, format, 1);
|
||||
|
||||
// We interrupt your boiler plate to initialize the emulator so that
|
||||
|
@ -80,9 +79,7 @@ fn main() {
|
|||
let texture_size = gui::texture_size();
|
||||
let texture = gui::create_texture(&device, texture_size);
|
||||
gui::write_to_texture(&queue, &texture, emu::pixel_buf(&cpu), texture_size);
|
||||
let texture_id = todo!("Expose Texture ID to egui");
|
||||
|
||||
render_pass.
|
||||
let texture_id = gui::expose_texture_to_egui(&mut render_pass, &device, &texture);
|
||||
|
||||
// Load ROM if filepath was provided
|
||||
if let Some(path) = m.value_of("rom") {
|
||||
|
@ -119,13 +116,14 @@ fn main() {
|
|||
|
||||
// Set up state for the Immediate-mode GUI
|
||||
let mut app = GuiState::new(rom_title);
|
||||
let mut ctx = egui_winit::egui::Context::default();
|
||||
let mut last_key = gui::unused_key();
|
||||
|
||||
// used for egui animations
|
||||
let start_time = Instant::now();
|
||||
|
||||
event_loop.run(move |event, _, control_flow| {
|
||||
platform.handle_event(&event);
|
||||
|
||||
match event {
|
||||
Event::MainEventsCleared => {
|
||||
if app.quit {
|
||||
|
@ -149,6 +147,8 @@ fn main() {
|
|||
window.request_redraw();
|
||||
}
|
||||
Event::RedrawRequested(..) => {
|
||||
platform.update_time(start_time.elapsed().as_secs_f64());
|
||||
|
||||
let data = emu::pixel_buf(&cpu);
|
||||
gui::write_to_texture(&queue, &texture, data, texture_size);
|
||||
|
||||
|
@ -172,7 +172,7 @@ fn main() {
|
|||
let screen_descriptor = gui::create_screen_descriptor(&window, &config);
|
||||
|
||||
// Upload all resources for the GPU.
|
||||
render_pass.update_texture(&device, &queue, todo!(), todo!());
|
||||
render_pass.update_texture(&device, &queue, &platform.context().texture());
|
||||
render_pass.update_user_textures(&device, &queue);
|
||||
render_pass.update_buffers(&device, &queue, &paint_jobs, &screen_descriptor);
|
||||
|
||||
|
@ -192,23 +192,18 @@ fn main() {
|
|||
// Redraw egui
|
||||
output_frame.present();
|
||||
}
|
||||
Event::WindowEvent { event, .. } => {
|
||||
let exclusive_use = state.on_event(&ctx, &event);
|
||||
if !exclusive_use {
|
||||
match event {
|
||||
WindowEvent::Resized(size) => {
|
||||
config.width = size.width;
|
||||
config.height = size.height;
|
||||
surface.configure(&device, &config);
|
||||
}
|
||||
WindowEvent::CloseRequested => {
|
||||
emu::save_and_exit(&cpu, control_flow);
|
||||
}
|
||||
WindowEvent::KeyboardInput { input, .. } => last_key = input,
|
||||
_ => {}
|
||||
}
|
||||
Event::WindowEvent { event, .. } => match event {
|
||||
WindowEvent::Resized(size) => {
|
||||
config.width = size.width;
|
||||
config.height = size.height;
|
||||
surface.configure(&device, &config);
|
||||
}
|
||||
}
|
||||
WindowEvent::CloseRequested => {
|
||||
emu::save_and_exit(&cpu, control_flow);
|
||||
}
|
||||
WindowEvent::KeyboardInput { input, .. } => last_key = input,
|
||||
_ => {}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue