rustic_mountain_core/
memory.rs

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                    // if sprnum == 11 || sprnum == 12 {
94                    //     dbg!((celx + ioffset, cely + joffset));
95                    // }
96                    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; //???
234        }
235        let ind = x as usize + y as usize * 128;
236        if ind < 4096 {
237            self.map[ind]
238        } else {
239            // after the 4096th octet, we start reading from the shared memory section at the bottom of sprites
240            // meaning we convert from 2 16s to 1 256
241            let start = (ind - 4096) * 2 + 4096 * 2;
242
243            self.sprites[start + 1] * 16 + self.sprites[start] // need to swap the nibbles
244        }
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}