Initial commit: NES emulator with GTK4 desktop frontend
Some checks failed
CI / rust (push) Has been cancelled

Full NES emulation: CPU, PPU, APU, 47 mappers, iNES/NES 2.0 parsing.
GTK4 desktop client with HeaderBar, pixel-perfect Cairo rendering,
drag-and-drop ROM loading, and keyboard shortcuts.
187 tests covering core emulation, mappers, and runtime.
This commit is contained in:
2026-03-13 11:48:45 +03:00
commit bdf23de8db
143 changed files with 18501 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
[package]
name = "nesemu-adapter-api"
version = "0.1.0"
edition = "2024"
description = "Backend-agnostic adapter traits for nesemu clients"
license = "MIT OR Apache-2.0"
rust-version = "1.85"
[dependencies]

View File

@@ -0,0 +1,70 @@
use std::collections::HashMap;
pub const BUTTONS_COUNT: usize = 8;
pub type ButtonState = [bool; BUTTONS_COUNT];
pub trait InputSource {
fn poll_buttons(&mut self) -> ButtonState;
}
pub trait VideoSink {
fn present_rgba(&mut self, frame: &[u8], width: u32, height: u32);
}
pub trait AudioSink {
fn push_samples(&mut self, samples: &[f32]);
}
pub trait TimeSource {
fn wait_next_frame(&mut self);
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum StorageError {
NotFound(String),
Io(String),
}
pub trait FileStore {
fn read(&self, key: &str) -> Result<Vec<u8>, StorageError>;
fn write(&mut self, key: &str, bytes: &[u8]) -> Result<(), StorageError>;
}
#[derive(Default)]
pub struct MemoryStore {
items: HashMap<String, Vec<u8>>,
}
impl FileStore for MemoryStore {
fn read(&self, key: &str) -> Result<Vec<u8>, StorageError> {
self.items
.get(key)
.cloned()
.ok_or_else(|| StorageError::NotFound(key.to_string()))
}
fn write(&mut self, key: &str, bytes: &[u8]) -> Result<(), StorageError> {
self.items.insert(key.to_string(), bytes.to_vec());
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::{FileStore, MemoryStore, StorageError};
#[test]
fn memory_store_roundtrip() {
let mut store = MemoryStore::default();
store.write("slot1", &[1, 2, 3]).expect("write");
assert_eq!(store.read("slot1").expect("read"), vec![1, 2, 3]);
}
#[test]
fn memory_store_not_found() {
let store = MemoryStore::default();
let err = store.read("missing").expect_err("must fail");
assert!(matches!(err, StorageError::NotFound(_)));
}
}