Skip to content

Commit

Permalink
refactor: prefer deferred viewports (#306)
Browse files Browse the repository at this point in the history
  • Loading branch information
lukexor committed Jun 25, 2024
1 parent 17db5c8 commit e1e60d1
Show file tree
Hide file tree
Showing 16 changed files with 3,774 additions and 3,000 deletions.
6 changes: 5 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ jobs:
name: Lint TetaNES (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-latest, ubuntu-latest, windows-latest]
steps:
Expand All @@ -60,7 +61,9 @@ jobs:
fetch-depth: 0
- uses: dtolnay/rust-toolchain@master
with:
toolchain: nightly
# TODO: pin nightly temporarily to fix coreaudio-sys issue with 2024-06-23
# See: https://github.com/RustAudio/coreaudio-sys/issues/104
toolchain: nightly-2024-06-16
components: clippy
- uses: Swatinem/rust-cache@v2
- if: startsWith(matrix.os, 'ubuntu')
Expand All @@ -74,6 +77,7 @@ jobs:
name: Lint TetaNES Core (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-latest, ubuntu-latest, windows-latest]
toolchain: [nightly, stable, 1.78]
Expand Down
2 changes: 1 addition & 1 deletion tetanes/src/bin/build_artifacts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ impl Build {
let volume = PathBuf::from("/Volumes").join(&artifact_name);
let app_name = format!("{}.app", self.app_name);
let dmg_name = format!("{artifact_name}-uncompressed.dmg");
let dmg_path = build_dir.join(&dmg_name);
let dmg_path = build_dir.join(dmg_name);
let dmg_name_compressed = format!("{artifact_name}.dmg");
let dmg_path_compressed = build_dir.join(&dmg_name_compressed);
let dmg_path_dist = self.dist_dir.join(&dmg_name_compressed);
Expand Down
15 changes: 7 additions & 8 deletions tetanes/src/nes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use crate::{
nes::{
event::{RendererEvent, RunState, SendNesEvent, UiEvent},
event::{NesEventProxy, RendererEvent, RunState, UiEvent},
input::{Gamepads, InputBindings},
renderer::{FrameRecycle, Resources},
},
Expand All @@ -23,7 +23,7 @@ use thingbuf::mpsc::blocking;
use tracing::{debug, error};
use winit::{
event::Modifiers,
event_loop::{EventLoop, EventLoopBuilder, EventLoopProxy, EventLoopWindowTarget},
event_loop::{EventLoop, EventLoopBuilder, EventLoopWindowTarget},
window::{Window, WindowId},
};

Expand All @@ -44,7 +44,7 @@ pub struct Nes {
/// Set during initialization, then taken and set to `None` when running because
/// `EventLoopProxy` can only be created on the initial `EventLoop` and not on
/// `&EventLoopWindowTarget`.
pub(crate) init_state: Option<(Config, EventLoopProxy<NesEvent>)>,
pub(crate) init_state: Option<(Config, NesEventProxy)>,
/// Initially `Suspended`. `Pending` after `Resume` event received and spanwed. `Running` after
/// resources future completes.
pub(crate) state: State,
Expand Down Expand Up @@ -76,7 +76,7 @@ pub(crate) struct Running {
pub(crate) cfg: Config,
// Only used by wasm currently
#[allow(unused)]
pub(crate) tx: EventLoopProxy<NesEvent>,
pub(crate) tx: NesEventProxy,
pub(crate) emulation: Emulation,
pub(crate) renderer: Renderer,
pub(crate) input_bindings: InputBindings,
Expand Down Expand Up @@ -106,9 +106,8 @@ impl Nes {

/// Create the NES instance.
pub fn new(cfg: Config, event_loop: &EventLoop<NesEvent>) -> Self {
let tx = event_loop.create_proxy();
Self {
init_state: Some((cfg, tx)),
init_state: Some((cfg, NesEventProxy::new(event_loop))),
state: State::Suspended,
}
}
Expand Down Expand Up @@ -140,11 +139,11 @@ impl Nes {
match Renderer::create_painter(window).await {
Ok(painter) => {
painter_tx.send(painter).expect("failed to send painter");
event_tx.nes_event(RendererEvent::ResourcesReady);
event_tx.event(RendererEvent::ResourcesReady);
}
Err(err) => {
error!("failed to create painter: {err:?}");
event_tx.nes_event(UiEvent::Terminate);
event_tx.event(UiEvent::Terminate);
}
}
}
Expand Down
135 changes: 133 additions & 2 deletions tetanes/src/nes/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,18 @@ pub enum Action {
Debug(Debug),
}

impl PartialOrd for Action {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}

impl Ord for Action {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.as_ref().cmp(other.as_ref())
}
}

impl Action {
pub const BINDABLE: [Self; 111] = [
Self::Ui(Ui::Quit),
Expand Down Expand Up @@ -173,9 +185,10 @@ impl AsRef<str> for Action {
},
Action::Menu(menu) => match menu {
Menu::About => "Toggle About Window",
Menu::Keybinds => "Toggle Keybinds Window",
Menu::Keybinds => "Toggle Keybinds Menu",
Menu::PerfStats => "Toggle Performance Stats Window",
Menu::Preferences => "Toggle Preferences Window",
Menu::PpuViewer => "Toggle PPU Viewer",
Menu::Preferences => "Toggle Preferences Menu",
},
Action::Feature(feature) => match feature {
Feature::ToggleReplayRecording => "Toggle Replay Recording",
Expand Down Expand Up @@ -284,6 +297,124 @@ impl AsRef<str> for Action {
}
}

impl TryFrom<&str> for Action {
type Error = anyhow::Error;

fn try_from(s: &str) -> Result<Self, Self::Error> {
Ok(match s {
"Quit" => Self::Ui(Ui::Quit),
"Toggle Pause" => Self::Ui(Ui::TogglePause),
"Load ROM" => Self::Ui(Ui::LoadRom),
"Unload ROM" => Self::Ui(Ui::UnloadRom),
"Load Replay" => Self::Ui(Ui::LoadReplay),
"Toggle About Window" => Self::Menu(Menu::About),
"Toggle Keybinds Menu" => Self::Menu(Menu::Keybinds),
"Toggle Performance Stats Window" => Self::Menu(Menu::PerfStats),
"Toggle PPU Viewer" => Self::Menu(Menu::PpuViewer),
"Toggle Preferences Menu" => Self::Menu(Menu::Preferences),
"Toggle Replay Recording" => Self::Feature(Feature::ToggleReplayRecording),
"Toggle Audio Recording" => Self::Feature(Feature::ToggleAudioRecording),
"Visual Rewind" => Self::Feature(Feature::VisualRewind),
"Instant Rewind" => Self::Feature(Feature::InstantRewind),
"Take Screenshot" => Self::Feature(Feature::TakeScreenshot),
"Toggle Fullscreen" => Self::Setting(Setting::ToggleFullscreen),
"Toggle Embed Viewports" => Self::Setting(Setting::ToggleEmbedViewports),
"Toggle Always On Top" => Self::Setting(Setting::ToggleAlwaysOnTop),
"Toggle Audio" => Self::Setting(Setting::ToggleAudio),
"Toggle Cycle Accurate" => Self::Setting(Setting::ToggleCycleAccurate),
"Toggle Rewinding" => Self::Setting(Setting::ToggleRewinding),
"Toggle Overscan" => Self::Setting(Setting::ToggleOverscan),
"Toggle Menubar" => Self::Setting(Setting::ToggleMenubar),
"Toggle Messages" => Self::Setting(Setting::ToggleMessages),
"Toggle FPS" => Self::Setting(Setting::ToggleFps),
"Fast Forward" => Self::Setting(Setting::FastForward),
"Increment Scale" => Self::Setting(Setting::IncrementScale),
"Decrement Scale" => Self::Setting(Setting::DecrementScale),
"Increment Speed" => Self::Setting(Setting::IncrementSpeed),
"Decrement Speed" => Self::Setting(Setting::DecrementSpeed),
"Reset" => Self::Deck(DeckAction::Reset(ResetKind::Soft)),
"Power Cycle" => Self::Deck(DeckAction::Reset(ResetKind::Hard)),
"Joypad Left (P1)" => Self::Deck(DeckAction::Joypad((Player::One, JoypadBtn::Left))),
"Joypad Right (P1)" => Self::Deck(DeckAction::Joypad((Player::One, JoypadBtn::Right))),
"Joypad Up (P1)" => Self::Deck(DeckAction::Joypad((Player::One, JoypadBtn::Up))),
"Joypad Down (P1)" => Self::Deck(DeckAction::Joypad((Player::One, JoypadBtn::Down))),
"Joypad A (P1)" => Self::Deck(DeckAction::Joypad((Player::One, JoypadBtn::A))),
"Joypad B (P1)" => Self::Deck(DeckAction::Joypad((Player::One, JoypadBtn::B))),
"Joypad Turbo A (P1)" => {
Self::Deck(DeckAction::Joypad((Player::One, JoypadBtn::TurboA)))
}
"Joypad Turbo B (P1)" => {
Self::Deck(DeckAction::Joypad((Player::One, JoypadBtn::TurboB)))
}
"Joypad Select (P1)" => {
Self::Deck(DeckAction::Joypad((Player::One, JoypadBtn::Select)))
}
"Joypad Start (P1)" => Self::Deck(DeckAction::Joypad((Player::One, JoypadBtn::Start))),
"Toggle Zapper Connected" => Self::Deck(DeckAction::ToggleZapperConnected),
"Zapper Aim" => Self::Deck(DeckAction::ZapperAim((0, 0))),
"Zapper Aim Offscreen (Hold)" => Self::Deck(DeckAction::ZapperAimOffscreen),
"Zapper Trigger" => Self::Deck(DeckAction::ZapperTrigger),
"Disable Four Player Mode" => Self::Deck(DeckAction::FourPlayer(FourPlayer::Disabled)),
"Enable Four Player (FourScore)" => {
Self::Deck(DeckAction::FourPlayer(FourPlayer::FourScore))
}
"Enable Four Player (Satellite)" => {
Self::Deck(DeckAction::FourPlayer(FourPlayer::Satellite))
}
"Set Save Slot 1" => Self::Deck(DeckAction::SetSaveSlot(1)),
"Set Save Slot 2" => Self::Deck(DeckAction::SetSaveSlot(2)),
"Set Save Slot 3" => Self::Deck(DeckAction::SetSaveSlot(3)),
"Set Save Slot 4" => Self::Deck(DeckAction::SetSaveSlot(4)),
"Set Save Slot 5" => Self::Deck(DeckAction::SetSaveSlot(5)),
"Set Save Slot 6" => Self::Deck(DeckAction::SetSaveSlot(6)),
"Set Save Slot 7" => Self::Deck(DeckAction::SetSaveSlot(7)),
"Set Save Slot 8" => Self::Deck(DeckAction::SetSaveSlot(8)),
"Save State" => Self::Deck(DeckAction::SaveState),
"Load State" => Self::Deck(DeckAction::LoadState),
"Toggle Pulse1 Channel" => Self::Deck(DeckAction::ToggleApuChannel(Channel::Pulse1)),
"Toggle Pulse2 Channel" => Self::Deck(DeckAction::ToggleApuChannel(Channel::Pulse2)),
"Toggle Triangle Channel" => {
Self::Deck(DeckAction::ToggleApuChannel(Channel::Triangle))
}
"Toggle Noise Channel" => Self::Deck(DeckAction::ToggleApuChannel(Channel::Noise)),
"Toggle DMC Channel" => Self::Deck(DeckAction::ToggleApuChannel(Channel::Dmc)),
"Toggle Mapper Channel" => Self::Deck(DeckAction::ToggleApuChannel(Channel::Mapper)),
"Set Mapper Rev. to MMC3A" => Self::Deck(DeckAction::MapperRevision(
MapperRevision::Mmc3(Mmc3Revision::A),
)),
"Set Mapper Rev. to MMC3B/C" => Self::Deck(DeckAction::MapperRevision(
MapperRevision::Mmc3(Mmc3Revision::BC),
)),
"Set Mapper Rev. to MC-ACC" => Self::Deck(DeckAction::MapperRevision(
MapperRevision::Mmc3(Mmc3Revision::Acc),
)),
"Set Mapper Rev. to BF909x" => Self::Deck(DeckAction::MapperRevision(
MapperRevision::Bf909(Bf909Revision::Bf909x),
)),
"Set Mapper Rev. to BF9097" => Self::Deck(DeckAction::MapperRevision(
MapperRevision::Bf909(Bf909Revision::Bf9097),
)),
"Set Region to Auto-Detect" => Self::Deck(DeckAction::SetNesRegion(NesRegion::Auto)),
"Set Region to NTSC" => Self::Deck(DeckAction::SetNesRegion(NesRegion::Ntsc)),
"Set Region to PAL" => Self::Deck(DeckAction::SetNesRegion(NesRegion::Pal)),
"Set Region to Dendy" => Self::Deck(DeckAction::SetNesRegion(NesRegion::Dendy)),
"Set Filter to Pixellate" => {
Self::Deck(DeckAction::SetVideoFilter(VideoFilter::Pixellate))
}
"Set Filter to NTSC" => Self::Deck(DeckAction::SetVideoFilter(VideoFilter::Ntsc)),
"Toggle CPU Debugger" => Self::Debug(Debug::Toggle(Debugger::Cpu)),
"Toggle PPU Debugger" => Self::Debug(Debug::Toggle(Debugger::Ppu)),
"Toggle APU Debugger" => Self::Debug(Debug::Toggle(Debugger::Apu)),
"Step Into (CPU Debugger)" => Self::Debug(Debug::Step(DebugStep::Into)),
"Step Out (CPU Debugger)" => Self::Debug(Debug::Step(DebugStep::Out)),
"Step Over (CPU Debugger)" => Self::Debug(Debug::Step(DebugStep::Over)),
"Step Scanline (CPU Debugger)" => Self::Debug(Debug::Step(DebugStep::Scanline)),
"Step Frame (CPU Debugger)" => Self::Debug(Debug::Step(DebugStep::Frame)),
_ => return Err(anyhow::anyhow!("Invalid action string")),
})
}
}

impl From<Ui> for Action {
fn from(state: Ui) -> Self {
Self::Ui(state)
Expand Down
Loading

0 comments on commit e1e60d1

Please sign in to comment.