Compare commits
2 Commits
30a7d1c5e4
...
47efeef83d
| Author | SHA1 | Date | |
|---|---|---|---|
| 47efeef83d | |||
| 20f7c289ed |
795
Cargo.lock
generated
795
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
[workspace]
|
||||
resolver = "3"
|
||||
members = ["simu","asm"]
|
||||
members = ["simu","asm","bitmap_to_asm"]
|
||||
|
||||
[profile.release]
|
||||
debug = "line-tables-only"
|
||||
|
||||
8
bitmap_to_asm/Cargo.toml
Normal file
8
bitmap_to_asm/Cargo.toml
Normal file
@@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "bitmap_to_asm"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
image = "0.25.10"
|
||||
regex = "1.12.3"
|
||||
53
bitmap_to_asm/src/main.rs
Normal file
53
bitmap_to_asm/src/main.rs
Normal file
@@ -0,0 +1,53 @@
|
||||
use regex::Regex;
|
||||
use std::env::args;
|
||||
|
||||
fn main() {
|
||||
let path = args().nth(1).expect("usage: 1 image file argument");
|
||||
let (data, name, width, height) = path_to_img(path.as_str());
|
||||
|
||||
println!("{name}:");
|
||||
println!(" D {width}");
|
||||
println!(" D {height}");
|
||||
for d in data {
|
||||
println!(" D 0x{d:08x}");
|
||||
}
|
||||
}
|
||||
fn remove_non_alphanumeric(input: &str) -> String {
|
||||
let re = Regex::new(r"[^a-zA-Z0-9_]+").unwrap();
|
||||
re.replace_all(input, "").to_string()
|
||||
}
|
||||
|
||||
fn path_to_img(path: &str) -> (Vec<u32>, String, u32, u32) {
|
||||
let img = match image::open(path) {
|
||||
Ok(img) => img.to_luma8(),
|
||||
Err(e) => panic!("failed to open image {path}: {e}"),
|
||||
};
|
||||
|
||||
let width = img.width();
|
||||
let height = img.height();
|
||||
|
||||
let mut bytes = Vec::new();
|
||||
let mut bit = 0;
|
||||
let mut byte = 0;
|
||||
for y in 0..height {
|
||||
for x in 0..width {
|
||||
let pix = img.get_pixel(x, y)[0];
|
||||
if pix >= 127 {
|
||||
byte |= 1 << bit
|
||||
}
|
||||
bit += 1;
|
||||
if bit == 32 {
|
||||
bytes.push(byte);
|
||||
byte = 0;
|
||||
bit = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if bit != 0 {
|
||||
bytes.push(byte);
|
||||
}
|
||||
let path = path.split('/').next_back().unwrap();
|
||||
let split: Vec<_> = path.split('.').collect();
|
||||
let name = remove_non_alphanumeric(&split[0..split.len() - 1].join("_")).to_lowercase();
|
||||
(bytes, name, width, height)
|
||||
}
|
||||
@@ -4,11 +4,11 @@ version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
atomic-wait = "1.1.0"
|
||||
pixels = "0.15.0"
|
||||
winit = { version = "0.30.13", features = ["x11", "x11-dl", "x11rb", "ahash", "bytemuck", "memmap2", "rwh_06", "sctk", "sctk-adwaita"] }
|
||||
winit_input_helper = "0.17.0"
|
||||
parse_int = { version = "0.9.0", optional = true }
|
||||
wait_on_address = "0.1.4"
|
||||
|
||||
|
||||
[features]
|
||||
|
||||
@@ -9,7 +9,7 @@ use std::{
|
||||
sync::atomic::AtomicU32,
|
||||
time::{self, Instant},
|
||||
};
|
||||
|
||||
use wait_on_address::AtomicWait;
|
||||
pub(crate) struct SharedState {
|
||||
pub(crate) keyboard: [AtomicU32; 4],
|
||||
pub(crate) screen_buf: [AtomicU32; 480 * 640],
|
||||
@@ -124,6 +124,7 @@ impl Cond {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)] //depen on features
|
||||
enum Instruction {
|
||||
Copy(Reg, Op2),
|
||||
Add(Reg, Reg, Op2),
|
||||
@@ -599,7 +600,7 @@ impl Computer {
|
||||
}
|
||||
println!("awaiting interupt...");
|
||||
}
|
||||
atomic_wait::wait(&SHARED.external_interupts, 0);
|
||||
SHARED.external_interupts.wait(0);
|
||||
}
|
||||
self.pc = (addr + self.pc as u32) as usize;
|
||||
}
|
||||
@@ -642,7 +643,7 @@ impl Computer {
|
||||
InteruptKind::MMIO => {
|
||||
(&SHARED.external_interupts)
|
||||
.store(0, std::sync::atomic::Ordering::Release);
|
||||
atomic_wait::wake_all(&SHARED.external_interupts);
|
||||
SHARED.external_interupts.notify_one();
|
||||
//no need to check prev because MMIO is the lowest priority
|
||||
self.interupts = InteruptState::Enabled
|
||||
}
|
||||
@@ -687,7 +688,7 @@ impl Computer {
|
||||
(&SHARED.external_enabled_interupts)
|
||||
.store(0, std::sync::atomic::Ordering::Relaxed);
|
||||
(&SHARED.external_interupts).store(0, std::sync::atomic::Ordering::Relaxed);
|
||||
atomic_wait::wake_all(&SHARED.external_interupts);
|
||||
SHARED.external_interupts.notify_all();
|
||||
}
|
||||
Instruction::Swi() => {
|
||||
self.pc += 1;
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
use std::env::args;
|
||||
use std::hint::unlikely;
|
||||
use std::io::stdin;
|
||||
use std::process::exit;
|
||||
use std::sync::{
|
||||
Arc,
|
||||
@@ -18,17 +17,16 @@ use std::thread::scope;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use pixels::{Error, Pixels, SurfaceTexture};
|
||||
use wait_on_address::AtomicWait;
|
||||
use winit::application::ApplicationHandler;
|
||||
use winit::dpi::LogicalSize;
|
||||
use winit::event::WindowEvent;
|
||||
use winit::event_loop::EventLoop;
|
||||
use winit::platform::modifier_supplement::KeyEventExtModifierSupplement;
|
||||
use winit::platform::scancode::PhysicalKeyExtScancode;
|
||||
use winit::window::Window;
|
||||
// use winit_input_helper::WinitInputHelper;
|
||||
|
||||
use crate::cpu::{Computer, MMIOInterupt};
|
||||
|
||||
mod cpu;
|
||||
use cpu::SHARED;
|
||||
|
||||
@@ -37,7 +35,7 @@ fn wait_int() {
|
||||
while unlikely(v != 0) {
|
||||
#[cfg(feature = "debug")]
|
||||
println!("wating for interupt clear {v}");
|
||||
atomic_wait::wait(&SHARED.external_interupts, v);
|
||||
SHARED.external_interupts.wait(v);
|
||||
v = (&SHARED.external_interupts).load(Acquire);
|
||||
}
|
||||
}
|
||||
@@ -93,20 +91,21 @@ impl<'a> ApplicationHandler for App<'a> {
|
||||
print!("Keyboard event: ");
|
||||
#[cfg(feature = "rich_keyboard")]
|
||||
{
|
||||
let kb0 = key_event
|
||||
.text_with_all_modifiers()
|
||||
.unwrap_or("")
|
||||
.as_bytes()
|
||||
let kb0 = key_event.text_with_all_modifiers().map_or(u32::MAX, |s| {
|
||||
s.as_bytes()
|
||||
.into_iter()
|
||||
.fold(0, |a, e| a << 8 | (*e as u32));
|
||||
.fold(0, |a, e| a << 8 | (*e as u32))
|
||||
});
|
||||
SHARED.keyboard[0].store(kb0, Relaxed);
|
||||
let kb1 = key_event
|
||||
.key_without_modifiers()
|
||||
.to_text()
|
||||
.unwrap_or("")
|
||||
.as_bytes()
|
||||
.map_or(u32::MAX, |s| {
|
||||
s.as_bytes()
|
||||
.into_iter()
|
||||
.fold(0, |a, e| a << 8 | (*e as u32));
|
||||
.fold(0, |a, e| a << 8 | (*e as u32))
|
||||
});
|
||||
|
||||
SHARED.keyboard[1].store(kb1, Relaxed);
|
||||
let kb2 =
|
||||
key_event.state.is_pressed() as u32 | ((key_event.repeat as u32) << 1);
|
||||
@@ -122,7 +121,7 @@ impl<'a> ApplicationHandler for App<'a> {
|
||||
(&SHARED.external_interupts).store(MMIOInterupt::Keyboard.into(), Release);
|
||||
#[cfg(feature = "debug")]
|
||||
println!("wake due to keyboard event");
|
||||
atomic_wait::wake_all(&SHARED.external_interupts);
|
||||
SHARED.external_interupts.notify_one();
|
||||
}
|
||||
}
|
||||
WindowEvent::CursorMoved { position, .. } => {
|
||||
@@ -151,7 +150,7 @@ impl<'a> ApplicationHandler for App<'a> {
|
||||
(&SHARED.external_interupts).store(MMIOInterupt::MouseMove.into(), Release);
|
||||
#[cfg(feature = "debug")]
|
||||
println!("wake due mouse move");
|
||||
atomic_wait::wake_all(&SHARED.external_interupts);
|
||||
SHARED.external_interupts.notify_one();
|
||||
}
|
||||
}
|
||||
// WindowEvent::MouseWheel {
|
||||
@@ -185,7 +184,7 @@ impl<'a> ApplicationHandler for App<'a> {
|
||||
(&SHARED.external_interupts).store(MMIOInterupt::MouseClick.into(), Release);
|
||||
#[cfg(feature = "debug")]
|
||||
println!("wake mouse click");
|
||||
atomic_wait::wake_all(&SHARED.external_interupts);
|
||||
SHARED.external_interupts.notify_one();
|
||||
}
|
||||
}
|
||||
WindowEvent::ScaleFactorChanged { .. } => {
|
||||
@@ -198,7 +197,7 @@ impl<'a> ApplicationHandler for App<'a> {
|
||||
!= 0;
|
||||
if enabled {
|
||||
(&SHARED.external_interupts).store(MMIOInterupt::VSync.into(), Relaxed);
|
||||
atomic_wait::wake_all(&SHARED.external_interupts);
|
||||
SHARED.external_interupts.notify_one();
|
||||
wait_int();
|
||||
}
|
||||
let pix = self.pixels.as_mut().unwrap();
|
||||
|
||||
Reference in New Issue
Block a user