Skip to content

Commit 395f24d

Browse files
committed
Implement packcolor and unpackcolor
1 parent a39b31c commit 395f24d

File tree

6 files changed

+173
-2
lines changed

6 files changed

+173
-2
lines changed

src/logic/ast.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,20 @@ pub enum Instruction {
3737
to: Value,
3838
from: Value,
3939
},
40+
PackColor {
41+
result: Value,
42+
r: Value,
43+
g: Value,
44+
b: Value,
45+
a: Value,
46+
},
47+
UnpackColor {
48+
r: Value,
49+
g: Value,
50+
b: Value,
51+
a: Value,
52+
value: Value,
53+
},
4054
// flow control
4155
Noop,
4256
Wait {

src/logic/grammar.lalrpop

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ match {
1919
"printchar",
2020
"format",
2121
"set",
22+
"packcolor",
23+
"unpackcolor",
2224
"noop",
2325
"wait",
2426
"stop",
@@ -131,6 +133,12 @@ Instruction: Instruction = {
131133
"set" <to:Value> <from:Value> =>
132134
Instruction::Set { <> },
133135

136+
"packcolor" <result:Value> <r:Value> <g:Value> <b:Value> <a:Value> =>
137+
Instruction::PackColor { <> },
138+
139+
"unpackcolor" <r:Value> <g:Value> <b:Value> <a:Value> <value:Value> =>
140+
Instruction::UnpackColor { <> },
141+
134142
// flow control
135143

136144
"noop" =>
@@ -277,6 +285,8 @@ Symbol = {
277285
"printchar",
278286
"format",
279287
"set",
288+
"packcolor",
289+
"unpackcolor",
280290
"noop",
281291
"wait",
282292
"stop",

src/logic/vm/instructions.rs

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ use super::{
55
processor::{MAX_TEXT_BUFFER, ProcessorState},
66
variables::{LValue, LVar},
77
};
8-
use crate::logic::ast::{self, ConditionOp};
8+
use crate::{
9+
logic::ast::{self, ConditionOp},
10+
types::colors::{f32_to_double_bits, f64_from_double_bits},
11+
};
912

1013
const MAX_IPT: usize = 1000;
1114
const EQUALITY_EPSILON: f64 = 0.000001;
@@ -67,6 +70,20 @@ pub fn parse_instruction(
6770
to: lvar(to),
6871
from: lvar(from),
6972
}),
73+
ast::Instruction::PackColor { result, r, g, b, a } => Box::new(PackColor {
74+
result: lvar(result),
75+
r: lvar(r),
76+
g: lvar(g),
77+
b: lvar(b),
78+
a: lvar(a),
79+
}),
80+
ast::Instruction::UnpackColor { r, g, b, a, value } => Box::new(UnpackColor {
81+
r: lvar(r),
82+
g: lvar(g),
83+
b: lvar(b),
84+
a: lvar(a),
85+
value: lvar(value),
86+
}),
7087

7188
// flow control
7289
ast::Instruction::Noop => Box::new(Noop),
@@ -222,6 +239,47 @@ impl SimpleInstruction for Set {
222239
}
223240
}
224241

242+
struct PackColor {
243+
result: LVar,
244+
r: LVar,
245+
g: LVar,
246+
b: LVar,
247+
a: LVar,
248+
}
249+
250+
impl SimpleInstruction for PackColor {
251+
fn execute(&self, state: &mut ProcessorState, _: &LogicVM) {
252+
self.result.set(
253+
state,
254+
f32_to_double_bits(
255+
self.r.get(state).numf().clamp(0., 1.),
256+
self.g.get(state).numf().clamp(0., 1.),
257+
self.b.get(state).numf().clamp(0., 1.),
258+
self.a.get(state).numf().clamp(0., 1.),
259+
)
260+
.into(),
261+
)
262+
}
263+
}
264+
265+
struct UnpackColor {
266+
r: LVar,
267+
g: LVar,
268+
b: LVar,
269+
a: LVar,
270+
value: LVar,
271+
}
272+
273+
impl SimpleInstruction for UnpackColor {
274+
fn execute(&self, state: &mut ProcessorState, _: &LogicVM) {
275+
let (r, g, b, a) = f64_from_double_bits(self.value.get(state).num());
276+
self.r.set(state, r.into());
277+
self.g.set(state, g.into());
278+
self.b.set(state, b.into());
279+
self.a.set(state, a.into());
280+
}
281+
}
282+
225283
// flow control
226284

227285
struct Noop;

src/logic/vm/mod.rs

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ mod tests {
172172

173173
use crate::{
174174
logic::vm::variables::{LValue, LVar},
175-
types::{Object, PackedPoint2, ProcessorConfig},
175+
types::{Object, PackedPoint2, ProcessorConfig, colors::COLORS},
176176
};
177177

178178
use super::{processor::Processor, *};
@@ -716,4 +716,60 @@ mod tests {
716716
assert_eq!(p.state.decode_printbuffer(), r#"4 aa {/} {:} {10} abcde"#);
717717
});
718718
}
719+
720+
#[test]
721+
fn test_pack_unpack_color() {
722+
let mut vm = single_processor_vm(
723+
BlockType::HyperProcessor,
724+
"
725+
packcolor packed1 0 0.5 0.75 1
726+
unpackcolor r1 g1 b1 a1 packed1
727+
unpackcolor r2 g2 b2 a2 %[royal]
728+
packcolor packed2 r2 g2 b2 a2
729+
stop
730+
",
731+
);
732+
733+
run(&mut vm, 1, true);
734+
735+
let state = take_processor(&mut vm, 0).state;
736+
737+
assert_eq!(
738+
state.variables["packed1"].get(&state),
739+
LValue::Number(f64::from_bits(0x00_7f_bf_ffu64))
740+
);
741+
742+
assert_eq!(state.variables["r1"].get(&state), LValue::Number(0.));
743+
assert_eq!(
744+
state.variables["g1"].get(&state),
745+
LValue::Number(127. / 255.)
746+
);
747+
assert_eq!(
748+
state.variables["b1"].get(&state),
749+
LValue::Number(191. / 255.)
750+
);
751+
assert_eq!(state.variables["a1"].get(&state), LValue::Number(1.));
752+
753+
assert_eq!(
754+
state.variables["r2"].get(&state),
755+
LValue::Number((0x41 as f64) / 255.)
756+
);
757+
assert_eq!(
758+
state.variables["g2"].get(&state),
759+
LValue::Number((0x69 as f64) / 255.)
760+
);
761+
assert_eq!(
762+
state.variables["b2"].get(&state),
763+
LValue::Number((0xe1 as f64) / 255.)
764+
);
765+
assert_eq!(
766+
state.variables["a2"].get(&state),
767+
LValue::Number((0xff as f64) / 255.)
768+
);
769+
770+
assert_eq!(
771+
state.variables["packed2"].get(&state),
772+
LValue::Number(COLORS["royal"])
773+
);
774+
}
719775
}

src/logic/vm/variables.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,10 @@ impl LValue {
111111
}
112112
}
113113

114+
pub fn numf(&self) -> f32 {
115+
self.num() as f32
116+
}
117+
114118
pub fn isobj(&self) -> bool {
115119
!matches!(self, Self::Number(_))
116120
}

src/types/colors.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,10 +104,39 @@ lazy_static! {
104104
};
105105
}
106106

107+
pub fn f32_to_double_bits(r: f32, g: f32, b: f32, a: f32) -> f64 {
108+
to_double_bits(
109+
(r * 255.) as i32,
110+
(g * 255.) as i32,
111+
(b * 255.) as i32,
112+
(a * 255.) as i32,
113+
)
114+
}
115+
107116
pub fn to_double_bits(r: i32, g: i32, b: i32, a: i32) -> f64 {
108117
rgba8888_to_double_bits(((r << 24) | (g << 16) | (b << 8) | a) as u32)
109118
}
110119

111120
pub fn rgba8888_to_double_bits(value: u32) -> f64 {
112121
f64::from_bits(value as u64)
113122
}
123+
124+
pub fn from_double_bits(value: f64) -> (u8, u8, u8, u8) {
125+
let value = value.to_bits();
126+
(
127+
(value >> 24) as u8,
128+
(value >> 16) as u8,
129+
(value >> 8) as u8,
130+
value as u8,
131+
)
132+
}
133+
134+
pub fn f64_from_double_bits(value: f64) -> (f64, f64, f64, f64) {
135+
let (r, g, b, a) = from_double_bits(value);
136+
(
137+
(r as f64) / 255.,
138+
(g as f64) / 255.,
139+
(b as f64) / 255.,
140+
(a as f64) / 255.,
141+
)
142+
}

0 commit comments

Comments
 (0)