1use crate::structures::{FlipState, Vector};
2use rand::{rngs::ThreadRng, thread_rng};
3use serde::{Deserialize, Serialize};
4
5#[derive(Serialize, Deserialize)]
6pub struct Memory {
7 #[serde(skip, default = "deflogger")]
8 pub logger: Box<dyn Fn(&str)>,
9 pub graphics: Vec<u8>,
10 pub fontatlas: Vec<bool>,
11 pub map: Vec<u8>,
12 pub sprites: Vec<u8>,
13 pub flags: Vec<u8>,
14 pub buttons: Vec<bool>,
15
16 pub pallete: Vec<ColorState>,
17 pub camera: Vector,
18 #[serde(skip, default = "defrng")]
19 pub rng: ThreadRng,
20}
21fn deflogger() -> Box<dyn Fn(&str)> {
22 Box::new(dlog)
23}
24fn defrng() -> ThreadRng {
25 thread_rng()
26}
27fn dlog(t: &str) {
28 println!("{}", t);
29}
30#[derive(Debug, Clone, Serialize, Deserialize)]
31pub struct ColorState {
32 pub color: u8,
33 pub transparent: bool,
34}
35impl Memory {
36 pub fn new(map: String, sprites: String, flags: String, fontatlas: String) -> Memory {
37 let _random = thread_rng();
38 let mut graphics = vec![];
39 for i in 0..128 * 128 {
40 graphics.push((i % 15) as u8);
41 }
42 let mut pal = vec![];
43 for i in 0..16 {
44 pal.push(ColorState {
45 color: i,
46 transparent: false,
47 })
48 }
49 pal[0].transparent = true;
50 Memory {
51 logger: Box::new(|s| println!("{}", s)),
52 buttons: vec![false; 6],
53 graphics,
54 fontatlas: fontatlas.chars().map(|c| c == '0').collect(),
55 map: hex::decode(map).unwrap(),
56 sprites: sprites
57 .chars()
58 .map(|c| u8::from_str_radix(&format!("{}", c), 16).unwrap())
59 .collect(),
60 flags: hex::decode(flags).unwrap(),
61 pallete: pal,
62 rng: thread_rng(),
63 camera: Vector { x: 0.0, y: 0.0 },
64 }
65 }
66 pub fn spr(&mut self, sprite: u8, x: i32, y: i32, flip: Option<FlipState>) {
67 let flip = flip.unwrap_or(FlipState { x: false, y: false });
68 for i in 0..8 {
69 for j in 0..8 {
70 let mut ci = i;
71 let mut cj = j;
72 if flip.x {
73 ci = 7 - i;
74 }
75 if flip.y {
76 cj = 7 - j;
77 }
78 let color = self.sprites[((sprite as usize % 16) * 8)
79 + (((sprite as usize / 16) * 8 * 128) + ci + (cj * 128))];
80
81 if !self.pallete[color as usize].transparent {
82 self.pset(color, x + i as i32, y + j as i32);
83 }
84 }
85 }
86 }
87 pub fn map(&mut self, celx: u8, cely: u8, sx: i32, sy: i32, celw: u8, celh: u8, mask: u8) {
88 for ioffset in 0..celw {
89 for joffset in 0..celh {
90 let sprnum = self.mget(celx + ioffset, cely + joffset);
91 let flag = self.fget_all(sprnum);
92 if (flag & mask) == mask {
93 self.spr(
97 sprnum,
98 (sx + ioffset as i32) * 8,
99 (sy + joffset as i32) * 8,
100 None,
101 );
102 }
103 }
104 }
105 }
106 pub fn circfill(&mut self, xc: u8, yc: u8, r: i8, c: u8) {
107 let mut x: i8 = 0;
108 let mut y: i8 = r as i8;
109 let mut d: i8 = 3 - 2 * r;
110 self.draw_circ(xc as i32, yc as i32, x as i32, y as i32, c);
111 while y >= x as i8 {
112 x += 1;
113 if d > 0 {
114 y -= 1;
115 d = d + 4 * (x - y) + 10;
116 } else {
117 d = d + 4 * x + 6;
118 }
119 self.draw_circ(xc as i32, yc as i32, x as i32, y as i32, c);
120 }
121 }
122 pub fn draw_circ(&mut self, xc: i32, yc: i32, x: i32, y: i32, c: u8) {
123 self.rectfill(
124 (xc - x).into(),
125 (yc + y).into(),
126 (xc - x).into(),
127 (yc - y).into(),
128 c,
129 );
130 self.rectfill(
131 (xc + y).into(),
132 (yc + x).into(),
133 (xc - y).into(),
134 (yc + x).into(),
135 c,
136 );
137 self.rectfill(
138 (xc + x).into(),
139 (yc - y).into(),
140 (xc + x).into(),
141 (yc + y).into(),
142 c,
143 );
144 self.rectfill(
145 (xc - y).into(),
146 (yc - x).into(),
147 (xc + y).into(),
148 (yc - x).into(),
149 c,
150 );
151 self.rectfill(
152 (xc + x).into(),
153 (yc - y).into(),
154 (xc + x).into(),
155 (yc + y).into(),
156 c,
157 );
158 self.rectfill(
159 (xc - y).into(),
160 (yc - x).into(),
161 (xc + y).into(),
162 (yc - x).into(),
163 c,
164 );
165 }
166 pub fn rrectfill(&mut self, x: i32, y: i32, x1: i32, y1: i32, col: u8) {
167 let mut i = x;
168 loop {
169 let mut j = y;
170 loop {
171 self.pset(col, i, j);
172 j += (y1 - y).signum();
173 if j == y1 {
174 break;
175 }
176 }
177 i += (x1 - x).signum();
178 if i == x1 {
179 break;
180 }
181 }
182 }
183 pub fn camera(&mut self, x: f32, y: f32) {
184 self.camera = Vector { x, y };
185 }
186 pub fn rectfill(&mut self, x: i32, y: i32, x2: i32, y2: i32, c: u8) {
187 if x < 128 && x2 > 0 && y < 128 && y2 > 0 {
188 self.rrectfill(0.max(x), 0.max(y), x2.min(127), y2.min(127), c);
189 }
190 }
191
192 pub fn pal(&mut self, index: usize, color: u8) {
193 self.pallete[index].color = color;
194 }
195 pub fn palt(&mut self, index: usize, transparent: bool) {
196 self.pallete[index].transparent = transparent;
197 }
198 pub fn pal_reset(&mut self) {
199 for i in 0..self.pallete.len() {
200 self.pallete[i].color = i as u8;
201 self.pallete[i].transparent = false;
202 }
203 self.pallete[0].transparent = true;
204 }
205 pub fn print(&mut self, text: &str, x: i32, y: i32, col: u8) {
206 for (c, chr) in text.char_indices() {
207 let char_index = chr as usize;
208 for i in 0..3 {
209 for j in 0..5 {
210 if self.fontatlas[(char_index / 16 * (128 * 8))
211 + (char_index % 16 * 8)
212 + i as usize
213 + (j as usize * 128)]
214 {
215 self.pset(col, x + i + (c as i32 * 4), y + j);
216 }
217 }
218 }
219 }
220 }
221 pub fn pset(&mut self, col: u8, mut x: i32, mut y: i32) {
222 let c = &self.pallete[col as usize];
223 x += self.camera.x as i32;
224 y += self.camera.y as i32;
225 if x < 0 || y < 0 || x >= 128 || y >= 128 {
226 return;
227 }
228 self.graphics[x as usize + y as usize * 128] = c.color;
229 }
230
231 pub fn mget(&self, x: u8, y: u8) -> u8 {
232 if y == 64 {
233 return 0; }
235 let ind = x as usize + y as usize * 128;
236 if ind < 4096 {
237 self.map[ind]
238 } else {
239 let start = (ind - 4096) * 2 + 4096 * 2;
242
243 self.sprites[start + 1] * 16 + self.sprites[start] }
245 }
246 pub fn mset(&mut self, x: u8, y: u8, tile: u8) {
247 let ind = x as usize + y as usize * 128;
248 if ind < 4096 {
249 self.map[ind] = tile;
250 } else {
251 let start = (ind - 4096) * 2 + 4096 * 2;
252
253 self.sprites[start] = tile % 16;
254 self.sprites[start + 1] = tile / 16;
255 }
256 }
257 pub fn fget(&self, sprnum: u8, idx: u8) -> bool {
258 (self.flags[sprnum as usize] & 2 ^ idx) != 0
259 }
260 pub fn fget_all(&self, sprnum: u8) -> u8 {
261 self.flags[sprnum as usize]
262 }
263}