mindustry logic execution, map- and schematic- parsing and rendering
packcolor
bendn 2023-11-15
parent 94b550b · commit 94efb4e
-rw-r--r--lemu/Cargo.toml2
-rw-r--r--lemu/src/instructions/draw.rs45
-rw-r--r--lemu/src/instructions/mod.rs38
-rw-r--r--lemu/src/instructions/mop2.rs2
-rw-r--r--lemu/src/lexer.rs1
-rw-r--r--lemu/src/parser/mod.rs26
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