looklook 0.9.0

Descriptive signal synthesiser.
// Copyright 2026 Gabriel Bjørnager Jensen.
//
// This file is part of LOOKLOOK.
//
// LOOKLOOK is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free Software
// Foundation, either version 3 of the License, or (at your option) any later ver-
// sion.
//
// LOOKLOOK is distributed in the hope that it will be useful, but WITHOUT ANY WAR-
// RANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
// PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License along
// with LOOKLOOK. If not, see <https://www.gnu.org/licenses/>.

//! The [`Segment`] structure.

use crate::isa::Long;

mod tests;

/// A memory segment.
#[derive(Copy, Debug)]
#[derive_const(Clone, Eq, PartialEq)]
pub struct Segment {
	/// The virtual segment origin.
	pub v_origin: usize,

	/// The physical segment origin.
	pub p_origin: usize,

	/// The size of the segment.
	pub size: usize,
}

 impl Segment {
	/// The `IMG0` segment.
	pub const IMG0: &Self = &Self {
		v_origin: 0x000000,
		p_origin: 0x000000,
		size:     0x100000,
	};

	/// The `IMG1` segment.
	pub const IMG1: &Self = &Self {
		v_origin: 0x100000,
		p_origin: 0x100000,
		size:     0x100000,
	};

	/// The `IMG2` segment.
	pub const IMG2: &Self = &Self {
		v_origin: 0x200000,
		p_origin: 0x200000,
		size:     0x100000,
	};

	/// The `IMG3` segment.
	pub const IMG3: &Self = &Self {
		v_origin: 0x300000,
		p_origin: 0x300000,
		size:     0x100000,
	};

	/// The `IMG4` segment.
	pub const IMG4: &Self = &Self {
		v_origin: 0x400000,
		p_origin: 0x400000,
		size:     0x100000,
	};

	/// The `IMG5` segment.
	pub const IMG5: &Self = &Self {
		v_origin: 0x500000,
		p_origin: 0x500000,
		size:     0x100000,
	};

	/// The `IMG6` segment.
	pub const IMG6: &Self = &Self {
		v_origin: 0x600000,
		p_origin: 0x600000,
		size:     0x100000,
	};

	/// The `IMG7` segment.
	pub const IMG7: &Self = &Self {
		v_origin: 0x700000,
		p_origin: 0x700000,
		size:     0x100000,
	};

	/// The `WRAM` segment.
	pub const WRAM: &Self = &Self {
		v_origin: 0x800000,
		p_origin: 0x800000,
		size:     0x80000,
	};

	/// The `IO` segment.
	pub const IO: &Self = &Self {
		v_origin: 0xF00000,
		p_origin: 0x880000,
		size:     0x400,
	};

	/// Selects a segment according to a virtual address.
	///
	/// If the address is undefined, an unspecified but zero-length segment is returned.
	#[inline]
	#[must_use]
	pub const fn from_v_addr(addr: Long) -> &'static Self {
		const UNKNOWN: &Segment = &Segment {
			v_origin: 0x000000,
			p_origin: 0x000000,
			size:     0x000000,
		};

		static SEGMENTS: [&Segment; 16] = [
			Segment::IMG0,
			Segment::IMG1,
			Segment::IMG2,
			Segment::IMG3,
			Segment::IMG4,
			Segment::IMG5,
			Segment::IMG6,
			Segment::IMG7,
			Segment::WRAM,
			UNKNOWN,
			UNKNOWN,
			UNKNOWN,
			UNKNOWN,
			UNKNOWN,
			UNKNOWN,
			Segment::IO,
		];

		// The segment is encoded in the four most significant bits of the (`24`-bit!) ad-
		// dress.
		let segment = addr.as_usize() >> 20 & 0b1111;

		SEGMENTS[segment]
	}
}