mindustry logic execution, map- and schematic- parsing and rendering
packcolor
| -rw-r--r-- | lemu/Cargo.toml | 2 | ||||
| -rw-r--r-- | lemu/src/instructions/draw.rs | 45 | ||||
| -rw-r--r-- | lemu/src/instructions/mod.rs | 38 | ||||
| -rw-r--r-- | lemu/src/instructions/mop2.rs | 2 | ||||
| -rw-r--r-- | lemu/src/lexer.rs | 1 | ||||
| -rw-r--r-- | lemu/src/parser/mod.rs | 26 |
6 files changed, 75 insertions, 39 deletions
diff --git a/lemu/Cargo.toml b/lemu/Cargo.toml index e207df1..072d9f5 100644 --- a/lemu/Cargo.toml +++ b/lemu/Cargo.toml @@ -12,7 +12,7 @@ keywords = ["mindustry", "logic", "emulator", "executor"] [dependencies] thiserror = "1.0" enum_dispatch = "0.3" -fimg = { version = "0.4.16", default-features = false } +fimg = { version = "0.4.26", default-features = false } logos = "0.13.0" rust-fuzzy-search = { version = "0.1.1", optional = true } beef = "0.5" diff --git a/lemu/src/instructions/draw.rs b/lemu/src/instructions/draw.rs index 1a3573a..db0b52e 100644 --- a/lemu/src/instructions/draw.rs +++ b/lemu/src/instructions/draw.rs @@ -102,27 +102,29 @@ pub struct Clear { } #[derive(Debug, Copy, Clone)] -pub struct ClearD(u8, u8, u8); +pub struct ClearD((u8, u8, u8)); impl Apply for ClearD { fn apply(self, mut image: Image<&mut [u8], 4>, _: &mut DisplayState) { + let (r, g, b) = self.0; for [r2, g2, b2, a2] in image.chunked_mut() { - (*r2, *b2, *g2, *a2) = (self.0, self.1, self.2, 255); + (*r2, *b2, *g2, *a2) = (r, g, b, 255); } } } +macro_rules! u8 { + ($self:ident, $mem:expr, $($v:ident)+) => { + ($(match $mem.get($self.$v) { + LVar::Num(n) => n.round() as u8, + _ => return None, + },)+) + }; +} + impl Frozen<ClearD> for Clear { fn freeze(&self, mem: &LRegistry<'_>) -> Option<ClearD> { - macro_rules! u8 { - ($v:ident) => { - match mem.get(self.$v) { - LVar::Num(n) => n.round() as u8, - _ => return None, - } - }; - } - Some(ClearD(u8!(r), u8!(g), u8!(b))) + Some(ClearD(u8!(self, mem, r g b))) } } @@ -138,7 +140,7 @@ impl Printable for Clear { impl Disp for ClearD { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "draw clear {} {} {}", self.0, self.1, self.2) + write!(f, "draw clear {} {} {}", self.0.0, self.0.1, self.0.2) } } @@ -162,15 +164,7 @@ pub struct SetColor { impl Frozen<SetColorD> for SetColor { fn freeze(&self, mem: &LRegistry<'_>) -> Option<SetColorD> { - macro_rules! u8 { - ($v:ident) => { - match mem.get(self.$v) { - LVar::Num(n) => n.round() as u8, - _ => return None, - } - }; - } - Some(SetColorD((u8!(r), u8!(g), u8!(b), u8!(a)))) + Some(SetColorD(u8!(self, mem, r g b a))) } } @@ -204,13 +198,8 @@ impl Printable for SetCol { impl Frozen<SetColorD> for SetCol { fn freeze(&self, mem: &LRegistry<'_>) -> Option<SetColorD> { - let col = mem.get(self.col).num()? as u32; - Some(SetColorD(( - (col & 0xff00_0000 >> 24) as u8, - (col & 0x00ff_0000 >> 16) as u8, - (col & 0x0000_ff00 >> 8) as u8, - (col & 0x0000_00ff) as u8, - ))) + let [r, g, b, a] = fimg::Pack::unpack(mem.get(self.col).num()? as u32); + Some(SetColorD((r, g, b, a))) } } diff --git a/lemu/src/instructions/mod.rs b/lemu/src/instructions/mod.rs index e072a24..ddca3a0 100644 --- a/lemu/src/instructions/mod.rs +++ b/lemu/src/instructions/mod.rs @@ -9,6 +9,7 @@ //! read //! write //! print +//! packcolor //! //! draw {color, col, flush, line, rect, lineRect, triangle, stroke, clear} //! ``` @@ -104,6 +105,7 @@ pub enum Instr { DynJump(DynJump), Print(io::Print), Stop(Stop), + PackColor(PackColor), End(End), } @@ -122,6 +124,7 @@ impl Printable for Instr { Self::Print(i) => i.print(info, f), Self::Stop(i) => i.print(info, f), Self::End(i) => i.print(info, f), + Self::PackColor(i) => i.print(info, f), } } } @@ -403,3 +406,38 @@ impl Printable for Stop { write!(f, "stop") } } + +#[derive(Copy, Clone, Debug)] +pub struct PackColor { + pub out: LAddress, + pub r: LAddress, + pub g: LAddress, + pub b: LAddress, + pub a: LAddress, +} + +impl LInstruction for PackColor { + fn run<W: Write>(&self, exec: &mut ExecutorContext<'_, W>) -> Flow { + macro_rules! num { + ($($n:ident)+) => { + ($(match exec.memory[self.$n] { + LVar::Num(n) => (n.clamp(0.0, 1.0) * 255.0) as u8, + _ => 255, + },)+) + }; + } + let (r, g, b, a) = num!(r g b a); + exec.memory[self.out] = LVar::from(fimg::Pack::pack(&[r, g, b, a]) as f64); + Flow::Continue + } +} + +impl Printable for PackColor { + fn print(&self, info: &DebugInfo<'_>, f: &mut impl fmt::Write) -> fmt::Result { + write!( + f, + "packcolor {} {} {} {} {}", + info[self.out], info[self.r], info[self.g], info[self.b], info[self.a] + ) + } +} diff --git a/lemu/src/instructions/mop2.rs b/lemu/src/instructions/mop2.rs index 6051794..7751736 100644 --- a/lemu/src/instructions/mop2.rs +++ b/lemu/src/instructions/mop2.rs @@ -66,7 +66,7 @@ num!(and | a, b | a != 0.0 && b != 0.0); op!(add +); op!(sub -); op!(mul *); -bop!(idiv /); +num!(idiv | a: f64 , b: f64 | (a / b).floor()); op!(lt <); op!(le <=); op!(gt >); diff --git a/lemu/src/lexer.rs b/lemu/src/lexer.rs index 01a75b4..bee3d67 100644 --- a/lemu/src/lexer.rs +++ b/lemu/src/lexer.rs @@ -47,6 +47,7 @@ instrs! { "set" => Set, "op" => Op, "end" => End, + "packcolor" => PackColor, "drawflush" => DrawFlush, "draw" => Draw, "print" => Print, diff --git a/lemu/src/parser/mod.rs b/lemu/src/parser/mod.rs index 70a11f6..b72c3b8 100644 --- a/lemu/src/parser/mod.rs +++ b/lemu/src/parser/mod.rs @@ -3,6 +3,15 @@ use std::io::Write as Wr; mod error; pub use error::Error; +#[rustfmt::skip] +macro_rules! three { ($a:expr) => { ($a, $a, $a) }; } +#[rustfmt::skip] +macro_rules! four { ($a:expr) => { ($a, $a, $a, $a) }; } +#[rustfmt::skip] +macro_rules! five { ($a:expr) => { ($a, $a, $a, $a, $a) }; } +#[rustfmt::skip] +macro_rules! six { ($a:expr) => { ($a, $a, $a, $a, $a, $a) }; } + use super::{ debug::info::{VarData, VarInfo}, executor::{ExecutorBuilderInternal, Instruction, UPInstr}, @@ -12,7 +21,8 @@ use super::{ SetStroke, Triangle, }, io::{Print, Read, Write}, - AlwaysJump, ConditionOp, DynJump, End, Instr, Jump, MathOp1, MathOp2, Op1, Op2, Set, Stop, + AlwaysJump, ConditionOp, DynJump, End, Instr, Jump, MathOp1, MathOp2, Op1, Op2, PackColor, + Set, Stop, }, lexer::{Lexer, Token}, memory::{LAddress, LVar}, @@ -22,6 +32,7 @@ macro_rules! tokstr { ($tok:expr) => { match $tok { Token::Ident(i) => Some(i), + Token::PackColor => Some("packcolor"), Token::Null => Some("null"), Token::Read => Some("read"), Token::Write => Some("write"), @@ -373,14 +384,6 @@ pub fn parse<'source, W: Wr>( let Token::Ident(instr) = dty else { yeet!(ExpectedIdent(dty)); }; - #[rustfmt::skip] - macro_rules! three { ($a:expr) => { ($a, $a, $a) }; } - #[rustfmt::skip] - macro_rules! four { ($a:expr) => { ($a, $a, $a, $a) }; } - #[rustfmt::skip] - macro_rules! five { ($a:expr) => { ($a, $a, $a, $a, $a) }; } - #[rustfmt::skip] - macro_rules! six { ($a:expr) => { ($a, $a, $a, $a, $a, $a) }; } match instr { "clear" => { let (r, g, b) = three! { num_or_255!(tok!())? }; @@ -449,6 +452,11 @@ pub fn parse<'source, W: Wr>( i => yeet!(UnsupportedImageOp(i)), } } + Token::PackColor => { + let out = take_numvar!(tok!()?)?; + let (r, g, b, a) = four! { take_numvar!(tok!()?)? }; + executor.add(PackColor { out, r, g, b, a }); + } Token::DrawFlush => { let t = tok!(); if let Ok(t) = t |