Initial commit

This commit is contained in:
Trevor Merritt 2024-07-22 14:07:35 -04:00
commit ceb62d2c53
16 changed files with 3245 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

83
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,83 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "launch",
"name": "Debug unit tests in library 'trevors_chip8_toy'",
"cargo": {
"args": [
"test",
"--no-run",
"--lib",
"--package=trevors_chip8_toy"
],
"filter": {
"name": "trevors_chip8_toy",
"kind": "lib"
}
},
"args": [],
"cwd": "${workspaceFolder}"
},
{
"type": "lldb",
"request": "launch",
"name": "Debug executable 'trevors_chip8_toy'",
"cargo": {
"args": [
"build",
"--bin=trevors_chip8_toy",
"--package=trevors_chip8_toy"
],
"filter": {
"name": "trevors_chip8_toy",
"kind": "bin"
}
},
"args": [],
"cwd": "${workspaceFolder}"
},
{
"type": "lldb",
"request": "launch",
"name": "Debug unit tests in executable 'trevors_chip8_toy'",
"cargo": {
"args": [
"test",
"--no-run",
"--bin=trevors_chip8_toy",
"--package=trevors_chip8_toy"
],
"filter": {
"name": "trevors_chip8_toy",
"kind": "bin"
}
},
"args": [],
"cwd": "${workspaceFolder}"
},
{
"type": "lldb",
"request": "launch",
"name": "Debug unit tests in library 'trevors_chip8_core'",
"cargo": {
"args": [
"test",
"--no-run",
"--lib",
"--package=trevors_chip8_core"
],
"filter": {
"name": "trevors_chip8_core",
"kind": "lib"
}
},
"args": [],
"cwd": "${workspaceFolder}"
}
]
}

2166
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

3
Cargo.toml Normal file
View File

@ -0,0 +1,3 @@
[workspace]
members = ["chip8_toy","chip8_core"]
resolver = "2"

9
chip8_core/Cargo.toml Normal file
View File

@ -0,0 +1,9 @@
[package]
name = "trevors_chip8_core"
version = "0.1.0"
edition = "2021"
[dependencies]
bitmask = "0.5.0"
[lib]

View File

@ -0,0 +1,21 @@
pub const CHIP8_MEMORY_SIZE: u16 = 0x1000;
pub const CHIP8_MEMORY_SIZE_USIZE: usize = 0x1000;
pub const FONT_0: [u8; 5] = [0xF0, 0x90, 0x90, 0x90, 0xF0];
pub const FONT_1: [u8; 5] = [0x20, 0x60, 0x20, 0x20, 0x70];
pub const FONT_2: [u8; 5] = [0xF0, 0x10, 0xF0, 0x80, 0xF0];
pub const FONT_3: [u8; 5] = [0xF0, 0x10, 0xF0, 0x10, 0xF0];
pub const FONT_4: [u8; 5] = [0x90, 0x90, 0xF0, 0x10, 0x10];
pub const FONT_5: [u8; 5] = [0xF0, 0x80, 0xF0, 0x10, 0xF0];
pub const FONT_6: [u8; 5] = [0xF0, 0x80, 0xF0, 0x90, 0xF0];
pub const FONT_7: [u8; 5] = [0xF0, 0x10, 0x20, 0x40, 0x40];
pub const FONT_8: [u8; 5] = [0xF0, 0x90, 0xF0, 0x90, 0xF0];
pub const FONT_9: [u8; 5] = [0xF0, 0x90, 0xF0, 0x10, 0xF0];
pub const FONT_A: [u8; 5] = [0xF0, 0x90, 0xF0, 0x90, 0x90];
pub const FONT_B: [u8; 5] = [0xE0, 0x90, 0xE0, 0x90, 0xE0];
pub const FONT_C: [u8; 5] = [0xF0, 0x80, 0x80, 0x80, 0xF0];
pub const FONT_D: [u8; 5] = [0xE0, 0x90, 0x90, 0x90, 0xE0];
pub const FONT_E: [u8; 5] = [0xF0, 0x80, 0xF0, 0x80, 0xF0];
pub const FONT_F: [u8; 5] = [0xF0, 0x80, 0xf0, 0x80, 0x80];

View File

@ -0,0 +1,195 @@
use bitmask::bitmask;
use crate::{chip8_constants::CHIP8_MEMORY_SIZE, parts::Display::Chip8Display};
enum Chip8StartOffset {
STANDARD,
ETI600,
OTHER,
}
struct Chip8Registers {
V: [u8; 16],
I: u16,
DelayTimer: u16,
SoundTimer: u16,
StackPointer: u8,
ProgramCounter: u16,
}
impl Default for Chip8Registers {
fn default() -> Self {
Chip8Registers {
DelayTimer: 60,
V: [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
],
I: 0x00,
SoundTimer: 60,
StackPointer: 255,
ProgramCounter: 0x200,
}
}
}
enum Chip8Instruction {
SYS(u16),
CLS,
RET,
JMP(u16),
CALL(u16),
SNEQ(u8, u16),
SNNE(u8, u8),
SNRE(u8, u8),
STOR(u8, u16),
ADD(u8, u16),
MOV(u8, u8),
OR(u8, u8),
AND(u8, u8),
XOR(u8, u8),
ADC(u8, u8),
SBC(u8, u8),
RSR(u8, u8),
LSR(u8, u8),
SNE(u8, u8),
STO(i16),
JMPI(u16),
RND(u8, u8),
SETD(u8),
SETT(u8),
BCD(u8),
}
enum Chip8Keys {
KEY0,
KEY1,
KEY2,
KEY3,
KEY4,
KEY5,
KEY6,
KEY7,
KEY8,
KEY9,
KEYA,
KEYB,
KEYC,
KEYD,
KEYE,
KEYF,
}
pub fn display_video_memory(system_memory: [u8; CHIP8_MEMORY_SIZE as usize]) {
// Assumes memory addresses from
}
const ZERO: u16 = 0b0000000000000000;
const BOTTOM_BYTE: u16 = 0b0000000011111111;
const TOP_BYTE: u16 = 0b1111111100000000;
const NIBBLE0: u16 = 0b1111000000000000;
const NIBBLE1: u16 = 0b0000111100000000;
const NIBBLE2: u16 = 0b0000000011110000;
const NIBBLE3: u16 = 0b0000000000001111;
const NIBBLE0_BALANCE: u16 = 0x0FFF;
const PMSK_0000: i16 = 0x0000;
const PMSK_00X0: i16 = 0x00F0;
const PMSK_0X00: i16 = 0x0F00;
const PMSK_0XXX: i16 = 0x0FFF;
// AND against the possible operand to find which one we have
bitmask! {
mask Chip8Instructions: u16 where flags Chip8InstructionFlags {
SYS = 0x00,
CLR = 0b0000000011100000,
RTS = 0b0000000011101110,
JUMP = 0b0001000000000000,
CALL = 0b0010000000000000,
SKE = 0b0011000000000000,
SKNE = 0b0100000000000000,
SKRE = 0b0101000000000000,
LOAD = 0b0110000000000000,
ADD = 0b0111000000000000,
MOVE = 0b1000000000000000,
OR = 0b1000000000000001,
AND = 0b1000000000000010,
XOR = 0b1000000000000011,
ADDR = 0b1000000000000100,
SUB = 0b1000000000000101,
SHR = 0b1000000000000110,
SHL = 0b1000000000001110,
SKRNE = 0b1001000000000000,
LOADI = 0b1010000000000000,
JUMPI = 0b1011000000000000,
RAND = 0b1100000000000000,
DRAW = 0b1101000000000000,
SKPR = 0b1110000000001110,
SKUP = 0b1111000010100001,
MOVED = 0b1111000000000111,
KEYD = 0b1111000000001010,
LOADD = 0b1111000000010101,
LOADS = 0b1111000000011000,
ADDI = 0b1111000000011110,
LDSPR = 0b1111000000101001,
BCD = 0b1111000000110011,
STOR = 0b1111000001010101,
MEMCPY = 0b1111000001100101
}
}
enum Chip8Asm {
SYS(u16),
CLR(),
RTS(),
JUMP(u16),
CALL(u16),
SKE(u8, u8),
SKNE(u8, u8),
SKRE(u8, u8),
LOAD(u8, u8),
ADD(u8, u8),
MOVE(u8, u8),
OR(u8, u8),
AND(u8, u8),
XOR(u8, u8),
ADDR(u8, u8),
SUB(u8, u8),
SHR(u8, u8),
SHL(u8, u8),
SKRNE(u8, u8),
LOADI(u16),
JUMPI(u16),
RAND(u8, u8),
DRAW(u8, u8, u8),
SKPR(u8),
SKUP(u8),
MOVED(u8),
KEYD(u8),
LOADD(u8),
LOADS(u8),
ADDI(u8),
LDSPR(u8),
BCD(u8),
STOR(u8),
READ(u8),
}
struct Chip8Cpu {}
struct Chip8System {
registers: Chip8Registers,
screen: Chip8Display,
}
impl Chip8System {
pub fn tick(self: Self) {
println!(" Ticking Chip8System");
// Fetch...
// ...Decode...
// ...Execute
// self.registers.tick();
self.screen.tick();
}
}

8
chip8_core/src/lib.rs Normal file
View File

@ -0,0 +1,8 @@
pub mod chip8_mnemonics;
pub mod chip8_constants;
pub mod parts {
pub mod CPU;
pub mod Display;
pub mod Keyboard;
}

449
chip8_core/src/parts/CPU.rs Normal file
View File

@ -0,0 +1,449 @@
struct Chip8Registers {
}
impl Chip8Registers {
pub fn tick(self: &Self) {
println!("Ticking Registers");
}
}
pub struct Chip8InstructionParameter {
mask: u16
}
struct Chip8Instruction {
id: String,
mask: u16,
pattern: u16,
arguments: Vec<Chip8InstructionParameter>,
description: Box<str>
}
pub fn fill_chip8_instructions() {
let full_instruction_set = vec![
Chip8Instruction {
id: "SYS".to_string(),
mask: 0x00,
pattern: 0x00,
arguments: vec![
Chip8InstructionParameter {
mask: 0x0FFF
}
],
description: "Execute method at address referenced by parameter".into()
},
Chip8Instruction {
id: "CLR".to_string(),
mask: 0x00E0,
pattern: 0x00E0,
arguments: vec![],
description: "Clear the Screen".into()
},
Chip8Instruction {
id: "RET".to_string(),
mask: 0x00EE,
pattern: 0x00EE,
arguments: vec![],
description: "Return from Subroutine".into()
},
Chip8Instruction {
id: "JMP".to_string(),
mask: 0x1FFF,
pattern: 0x1000,
arguments: vec![
Chip8InstructionParameter {
mask: 0x0fff
}
],
description: "Jump to specified location".into()
},
Chip8Instruction {
id: "SEQ".to_string(),
mask: 0x3FFF,
pattern: 0x3000,
arguments: vec![
Chip8InstructionParameter {
mask: 0x0f00
},
Chip8InstructionParameter {
mask: 0x00ff
}
],
description: "Skip next instruction if Register does equal parameter".into()
},
Chip8Instruction {
id: "SNE".to_string(),
mask: 0x4FFF,
pattern: 0x4000,
arguments: vec! [
Chip8InstructionParameter {
mask: 0x0f00
},
Chip8InstructionParameter {
mask: 0x00ff
}
],
description: "Skip next instruction if Register doesn't equal parameter".into()
},
Chip8Instruction {
id: "SREQ".to_string(),
mask: 0x5FF0,
pattern: 0x5000,
arguments: vec![
Chip8InstructionParameter {
mask: 0x0f00
},
Chip8InstructionParameter {
mask: 0x00f0
}
],
description: "TBD".into()
},
Chip8Instruction {
id: "STO".to_string(),
mask: 0x6FFF,
pattern: 0x6000,
arguments: vec![
Chip8InstructionParameter {
mask: 0x0f00
},
Chip8InstructionParameter {
mask: 0x00ff
}
],
description: "Store value into register".into()
},
Chip8Instruction {
id: "ADD".to_string(),
mask: 0x7FFF,
pattern: 0x7000,
arguments: vec![
Chip8InstructionParameter {
mask: 0x0f00
},
Chip8InstructionParameter {
mask: 0x00ff
}
],
description: "TBD".into()
},
Chip8Instruction {
id: "CPY".to_string(),
mask: 0x8FF0,
pattern: 0x8000,
arguments: vec![
Chip8InstructionParameter {
mask: 0x0f00
},
Chip8InstructionParameter {
mask: 0x00f0
}
],
description: "TBD".into()
},
Chip8Instruction {
id: "OR".to_string(),
mask: 0x8FF1,
pattern: 0x8001,
arguments: vec![
Chip8InstructionParameter {
mask: 0x0f00
},
Chip8InstructionParameter {
mask: 0x00f0
}
],
description: "Logical OR of registers placing result in first register".into()
},
Chip8Instruction {
id: "AND".to_string(),
mask: 0x8FF2,
pattern: 0x8002,
arguments: vec![
Chip8InstructionParameter {
mask: 0x0f00
},
Chip8InstructionParameter {
mask: 0x00f0
}
],
description: "Logical AND of registers placing result in first register".into()
},
Chip8Instruction {
id: "XOR".to_string(),
mask: 0x8FF3,
pattern: 0x8003,
arguments: vec![
Chip8InstructionParameter {
mask: 0x0f00
},
Chip8InstructionParameter {
mask: 0x00f0
}
],
description: "Logical XOR of registers placing result in first register".into()
},
Chip8Instruction {
id: "ADC".to_string(),
mask: 0x8FF4,
pattern: 0x8004,
arguments: vec![
Chip8InstructionParameter {
mask: 0x0f00
},
Chip8InstructionParameter {
mask: 0x00f0
}
],
description: "Add 2 Registers with carry flag".into()
},
Chip8Instruction {
id: "SUBC".to_string(),
mask: 0x8FF5,
pattern: 0x8005,
arguments: vec![
Chip8InstructionParameter {
mask: 0x0f00
},
Chip8InstructionParameter {
mask: 0x00f0
}
],
description: "Subtract 2 Registers with carry flag".into()
},
Chip8Instruction {
id: "RSR".to_string(),
mask: 0x8FF6,
pattern: 0x8006,
arguments: vec![
Chip8InstructionParameter {
mask: 0x0f00
},
Chip8InstructionParameter {
mask: 0x00f0
}
],
description: "Register Shifted Right".into()
},
Chip8Instruction {
id: "SUBC".to_string(),
mask: 0x8FF7,
pattern: 0x8007,
arguments: vec![
Chip8InstructionParameter {
mask: 0x0f00
},
Chip8InstructionParameter {
mask: 0x00f0
}
],
description: "Subtract 2 Regiters with Carry".into()
},
Chip8Instruction {
id: "RSL".to_string(),
mask: 0x8FFE,
pattern: 0x800E,
arguments: vec![
Chip8InstructionParameter {
mask: 0x0f00
},
Chip8InstructionParameter {
mask: 0x00f0
}
],
description: "Register Shifted Left".into()
},
Chip8Instruction {
id: "SRNE".to_string(),
mask: 0x9FF0,
pattern: 0x9000,
arguments: vec![
Chip8InstructionParameter {
mask: 0x0f00
},
Chip8InstructionParameter {
mask: 0x00f0
}
],
description: "Skip next instruction if registers not equal".into()
},
Chip8Instruction {
id: "LDI".to_string(),
mask: 0xAFFF,
pattern: 0xA000,
arguments: vec![
Chip8InstructionParameter {
mask: 0x0fff
}
],
description: "Load Data from Memory Address".into()
},
Chip8Instruction {
id: "JMPI".to_string(),
mask: 0xBFFF,
pattern: 0xB000,
arguments: vec![
Chip8InstructionParameter {
mask: 0x0fff
}
],
description: "Jump to Memory Address".into()
},
Chip8Instruction {
id: "RNG".to_string(),
mask: 0xCFFF,
pattern: 0xC000,
arguments: vec![
Chip8InstructionParameter {
mask: 0x0f00
},
Chip8InstructionParameter {
mask: 0x00ff
}
],
description: "Random number Generator".into()
},
Chip8Instruction {
id: "SPR".to_string(),
mask: 0xDFFF,
pattern: 0xD000,
arguments: vec![
Chip8InstructionParameter {
mask: 0x0f00
},
Chip8InstructionParameter {
mask: 0x00f0
},
Chip8InstructionParameter {
mask: 0x000f
}
],
description: "TBD".into()
},
Chip8Instruction {
id: "JNK".to_string(),
mask: 0xEF9E,
pattern: 0xE09E,
arguments: vec![
Chip8InstructionParameter {
mask: 0x0f00
}
],
description: "Jump over next instruction if Key Pressed".into()
},
Chip8Instruction {
id: "JKP".to_string(),
mask: 0xEFA1,
pattern: 0xE0A1,
arguments: vec![
Chip8InstructionParameter {
mask: 0x0f00
}
],
description: "Jump over next instruction if Key Not Pressed".into()
},
Chip8Instruction {
id: "SDT".to_string(),
mask: 0xFF07,
pattern: 0xF007,
arguments: vec![
Chip8InstructionParameter {
mask: 0x0F00
}
],
description: "TBD".into()
},
Chip8Instruction {
id: "WKP".to_string(),
mask: 0xFF0A,
pattern: 0xF00A,
arguments: vec![
Chip8InstructionParameter {
mask: 0x0f00
}
],
description: "TBD".into()
},
Chip8Instruction {
id: "LDT".to_string(),
mask: 0xFF15,
pattern: 0xF015,
arguments: vec![
Chip8InstructionParameter {
mask: 0x0f00
}
],
description: "TBD".into()
},
Chip8Instruction {
id: "LST".to_string(),
mask: 0xFF18,
pattern: 0xF018,
arguments: vec![
Chip8InstructionParameter {
mask: 0x0f00
}
],
description: "TBD".into()
},
Chip8Instruction {
id: "ADDI".to_string(),
mask: 0xFF1E,
pattern: 0xF01E,
arguments: vec![
Chip8InstructionParameter {
mask: 0x0f00
}
],
description: "TBD".into()
},
Chip8Instruction {
id: "SETI".to_string(),
mask: 0xFF29,
pattern: 0xF029,
arguments: vec![
Chip8InstructionParameter {
mask: 0x0f00
}
],
description: "TBD".into()
},
Chip8Instruction{
id: "BCD".to_string(),
mask: 0xFF33,
pattern: 0xF033,
arguments: vec![
Chip8InstructionParameter {
mask: 0x0f00
}
],
description: "Binary Coded Decimal of register".into()
},
Chip8Instruction{
id: "MSTO".to_string(),
mask: 0xFF55,
pattern: 0xF055,
arguments: vec![
Chip8InstructionParameter {
mask: 0x0f00
}
],
description: "TBD".into()
},
Chip8Instruction {
id: "MLOAD".to_string(),
mask: 0xFF65,
pattern: 0xF065,
arguments: vec![
Chip8InstructionParameter {
mask: 0x0f00
}
],
description: "TBD".into()
}
];
}

View File

@ -0,0 +1,28 @@
pub struct Chip8Display {
// 64w x 32h
pub memory: [bool; 512],
}
impl Chip8Display {
pub fn tick(self: &Self) {
println!("Ticking the display");
}
pub fn render_chip8_display(to_render: Chip8Display) {
// 32 rows...
for index_row in 0..=32 {
// ...64 columns
for index_col in 0..=64 {
let offset = (index_row * 64) + index_col;
if (to_render.memory[offset]) {
print!("*")
} else {
print!(" ")
};
}
println!("");
}
}
}

View File

@ -0,0 +1,82 @@
#[derive(Clone)]
struct Chip8Keyboard {
keys_state: [bool; 16]
}
impl Default for Chip8Keyboard {
fn default() -> Self {
Self { keys_state: [
false, false, false, false,
false, false, false, false,
false, false, false, false,
false, false, false, false
] }
}
}
impl Chip8Keyboard {
fn display_keyboard_key(self: Self, key_id: u8) {
let filler = if self.is_pressed(key_id) { "*" } else { " " };
print!("{}{}{}", filler, key_id, filler)
}
fn display_keyboard_horizontal_line(self: Self, row_values: [u8; 4]) {
print!("|");
for current in row_values {
self.clone().display_keyboard_key(current);
print!("|");
}
println!();
}
fn display_keyboard_seperator_line(self: Self) {
println!("+---+---+---+---+");
}
pub fn display_keyboard(self: Self) {
self.clone().display_keyboard_seperator_line();
self.clone().display_keyboard_horizontal_line(
[1,2,3,0xC]
);
println!("+---+---+---+---+");
println!("| 4 | 5 | 6 | D |");
println!("+---+---+---+---+");
println!("| 7 | 8 | 9 | E |");
println!("+---+---+---+---+");
println!("| A | 0 | B | F |");
println!("+---+---+---+---+");
}
pub fn press_key(self: &mut Self, key_id: u8) {
self.keys_state[key_id as usize] = true;
}
pub fn release_key(self: &mut Self, key_id: u8) {
self.keys_state[key_id as usize] = false;
}
pub fn is_pressed(self: Self, key_id: u8) -> bool {
self.keys_state[key_id as usize]
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn smoke_test() {
assert_eq!(true, true);
}
#[test]
fn basic_keyboard_display_works() {
let basic_keyboard = Chip8Keyboard::default();
}
}

7
chip8_toy/Cargo.lock generated Normal file
View File

@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "trevors_chip8_toy"
version = "0.1.0"

17
chip8_toy/Cargo.toml Normal file
View File

@ -0,0 +1,17 @@
[package]
name = "trevors_chip8_toy"
version = "0.1.0"
edition = "2021"
[dependencies]
trevors_chip8_core = { path = "../chip8_core" }
easy-imgui-sys = { version = "=0.6.0" }
easy-imgui = { version = "=0.6.0" }
easy-imgui-renderer = { version = "=0.6.0" }
easy-imgui-window = { version = "0.6.0" }
log ="0.4"
glutin = "0.32"
glutin-winit = { version = "0.5", optional = true }
raw-window-handle = "0.6"
arboard = { version = "3", optional = true, default-features = false }
winit = { version = "0.30", features = ["x11", "mint"] }

View File

@ -0,0 +1,79 @@
use easy_imgui::{Ui, UiBuilder};
use easy_imgui_window::{MainWindow, MainWindowWithRenderer};
use winit::{application::ApplicationHandler, event_loop::ActiveEventLoop, window::{Window, WindowAttributes}};
pub struct Chip8Display {
pub window: MainWindowWithRenderer,
}
impl Chip8Display {
pub fn new(event_loop: &ActiveEventLoop) -> Chip8Display {
Chip8Display { window: MainWindowWithRenderer::new(
MainWindow::new::<()>(&event_loop, Window::default_attributes().with_title("Chip8 Display")).unwrap())
}
}
pub fn render<M>(ui: &Ui<M>) {
}
}
impl UiBuilder for Chip8AppHandler {
fn do_ui(&mut self, ui: &Ui<Self>) {
ui.text("This is where the Chip8 UI Goes");
ui.text("Controls for Start/Stop/Load/Run Maybe?");
}
}
#[derive(Default)]
pub struct Chip8AppHandler {
pub windows: Vec<MainWindowWithRenderer>,
// pub display: Chip8Display
}
impl ApplicationHandler for Chip8AppHandler {
fn suspended(&mut self, _event_loop: &ActiveEventLoop) {
self.windows.clear();
}
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
self.windows.push(Chip8Display::new(event_loop).window);
}
fn window_event(
&mut self,
event_loop: &ActiveEventLoop,
window_id: winit::window::WindowId,
event: winit::event::WindowEvent,
) {
for window in &mut self.windows {
if window.main_window().window().id() != window_id {
continue;
}
let res = window.window_event(
&mut self,
&event,
easy_imgui_window::EventFlags::empty(),
);
if res.window_closed {
event_loop.exit();
}
break;
}
}
fn new_events(&mut self, _event_loop: &ActiveEventLoop, _cause: winit::event::StartCause) {
for window in &mut self.windows {
window.new_events();
}
}
fn about_to_wait(&mut self, _event_loop: &ActiveEventLoop) {
for window in &mut self.windows {
window.about_to_wait();
}
}
}

3
chip8_toy/src/lib.rs Normal file
View File

@ -0,0 +1,3 @@
pub mod gui {
pub mod display;
}

94
chip8_toy/src/main.rs Normal file
View File

@ -0,0 +1,94 @@
use easy_imgui_window::{
easy_imgui as imgui,
easy_imgui_renderer::Renderer,
winit::{
event_loop::{ActiveEventLoop, EventLoop},
window::Window,
},
MainWindow, MainWindowWithRenderer,
};
use trevors_chip8_toy::gui::display::{Chip8App, Chip8AppHandler};
use std::rc::Rc;
fn main() {
let event_loop = EventLoop::new().unwrap();
let mut main = Chip8AppHandler {
windows: vec![],
app: Chip8App,
};
event_loop.run_app(&mut main).unwrap();
}
#[derive(Default)]
struct AppHandler {
windows: Vec<MainWindowWithRenderer>,
app: App,
}
impl winit::application::ApplicationHandler for AppHandler {
fn suspended(&mut self, _event_loop: &ActiveEventLoop) {
self.windows.clear();
}
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
let wattr_1 = Window::default_attributes().with_title("Example #1");
let main_window_1 = MainWindow::new::<()>(&event_loop, wattr_1).unwrap();
let mut window_1 = MainWindowWithRenderer::new(main_window_1);
let wattr_2 = Window::default_attributes().with_title("Example #2");
let main_window_2 = MainWindow::new::<()>(&event_loop, wattr_2).unwrap();
// The GL context can be reused, but the imgui context cannot
let mut renderer_2 = Renderer::new(Rc::clone(window_1.renderer().gl_context())).unwrap();
renderer_2.set_background_color(Some(imgui::Color::GREEN));
let window_2 = MainWindowWithRenderer::new_with_renderer(main_window_2, renderer_2);
self.windows.push(window_1);
self.windows.push(window_2);
}
fn window_event(
&mut self,
event_loop: &ActiveEventLoop,
window_id: winit::window::WindowId,
event: winit::event::WindowEvent,
) {
for window in &mut self.windows {
if window.main_window().window().id() != window_id {
continue;
}
let res = window.window_event(
&mut self.app,
&event,
easy_imgui_window::EventFlags::empty(),
);
if res.window_closed {
event_loop.exit();
}
break;
}
}
fn new_events(&mut self, _event_loop: &ActiveEventLoop, _cause: winit::event::StartCause) {
for window in &mut self.windows {
window.new_events();
}
}
fn about_to_wait(&mut self, _event_loop: &ActiveEventLoop) {
for window in &mut self.windows {
window.about_to_wait();
}
}
}
#[derive(Default)]
struct App;
impl imgui::UiBuilder for App {
fn do_ui(&mut self, ui: &imgui::Ui<Self>) {
#[cfg(feature = "docking")]
{
ui.dock_space_over_viewport(0, imgui::DockNodeFlags::None);
}
ui.show_demo_window(None);
}
}