maurice 1.3.0

Maurice, a Thomson MO5 emulator
Documentation
pub(crate) mod color;

use crate::hardware::memory::Memory;
use crate::hardware::screen::color::{COLOR_DEPTH, PALETTE};
use crate::int;
use crate::raw_image::RawImage;

pub const WIDTH: usize = 320;
pub const HEIGHT: usize = 200;

pub const DEFAULT_PIXEL_SIZE: usize = 3;

#[derive(Debug)]
pub struct Screen {
    pub(crate) mouse_clic: bool,
    pub(crate) mouse_x: int,
    pub(crate) mouse_y: int,
    pixels: Vec<u8>,
    pub(crate) led: u8,
    pub(crate) show_led: u8,
    ratio: usize,
}

impl Screen {
    pub fn new(ratio: usize) -> Self {
        Screen {
            mouse_clic: false,
            mouse_x: -1,
            mouse_y: -1,
            pixels: vec![0; WIDTH * ratio * HEIGHT * ratio * COLOR_DEPTH],
            led: 0,
            show_led: 0,
            ratio,
        }
    }

    pub(crate) fn new_size(&mut self, new_size: crate::dimension::Dimension) {
        let x_ratio = new_size.width / WIDTH;
        let y_ratio = new_size.height / HEIGHT;
        self.set_ratio(std::cmp::min(x_ratio, y_ratio));
    }

    fn set_ratio(&mut self, mut ratio: usize) {
        if ratio == 0 {
            ratio = 1;
        }
        self.ratio = ratio;
        self.pixels = vec![0; WIDTH * ratio * HEIGHT * ratio * COLOR_DEPTH];
    }

    pub(crate) fn paint(&mut self, mem: &mut Memory) {
        self.dopaint(mem);
        if self.show_led > 0 {
            self.show_led -= 1;
            let sec = if self.led != 0 {
                [0xFF, 0x00, 0x00]
            } else {
                [0x00, 0x00, 0x00]
            };
            let mut line = Vec::with_capacity(16 * self.ratio * sec.len());
            for _ in 0..16 * self.ratio {
                line.extend(sec);
            }
            let pixels = &mut self.pixels;
            for y in 1..17 {
                let start = y * WIDTH * self.ratio * self.ratio * COLOR_DEPTH - line.len();
                let slice = &mut pixels[start..start + line.len()];
                slice.copy_from_slice(&line);
            }
        }
    }

    pub fn get_pixels(&mut self) -> RawImage {
        RawImage::new_with_data(WIDTH * self.ratio, HEIGHT * self.ratio, &self.pixels)
    }

    pub(crate) fn dopaint(&mut self, mem: &mut Memory) {
        let mut i = 0;

        let pixels = &mut self.pixels;
        for y in 0..HEIGHT {
            let offset = y * WIDTH * self.ratio * self.ratio * COLOR_DEPTH;
            if !mem.is_dirty(y) {
                i += 40;
            } else {
                let mut x = 0;
                for _ in 0..40 {
                    let col = mem.COLOR(i);
                    let c2 = (col & 0x0F) as usize;
                    let c1 = (col >> 4) as usize;
                    let cc2 = &PALETTE[c1];
                    let cc1 = &PALETTE[c2];

                    let pt = mem.POINT(i);
                    const PATTERN: [int; 8] = [0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01];
                    for v in PATTERN {
                        for _ in 0..self.ratio {
                            let range_start = x * COLOR_DEPTH + offset;
                            let pixel_range = range_start..range_start + COLOR_DEPTH;
                            if (v & pt) != 0 {
                                pixels[pixel_range].copy_from_slice(cc2);
                            } else {
                                pixels[pixel_range].copy_from_slice(cc1);
                            }
                            x += 1;
                        }
                    }
                    i += 1;
                }
            }
            for a in 1..self.ratio {
                pixels.copy_within(
                    offset..offset + WIDTH * COLOR_DEPTH * self.ratio,
                    offset + WIDTH * self.ratio * COLOR_DEPTH * a,
                );
            }
        }
    }
}