diff --git a/Cargo.toml b/Cargo.toml index 4bcd210ab7867f0689b2dfee0b0827c307e696d9..c6ac2e8d221b8ae5f5f17c2f198a033b5f8aa6b9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ spin = "0.9.4" volatile = "0.4.5" x86_64 = "0.14.10" uart_16550 = "0.2.18" +# bitvec = "1.0.1" #tracing = { version = "0.1.37", default-features = false } [dependencies.limine] diff --git a/Makefile b/Makefile index 4236c51607a94e03c58dd2c74572cb3a7f3f8241..35c767ca678b3a0751a0e93d366d75da5cd84eee 100644 --- a/Makefile +++ b/Makefile @@ -83,8 +83,8 @@ build: ${KERNEL} # bootable iso alias iso: ${HYPERION} -reset-cargo-deps: - rm ${CARGO_DIR}/hyperion.d +clippy: + ${CARGO} clippy ${CARGO_FLAGS} -- -D warnings # connect gdb to qemu gdb: diff --git a/cfg/limine.cfg b/cfg/limine.cfg index 0201da3a2b78b8d920f795caac393a7d087df11a..58c871991d9031bb93f864f581ca82b6742d8c9b 100644 --- a/cfg/limine.cfg +++ b/cfg/limine.cfg @@ -4,4 +4,4 @@ TIMEOUT=0 :Hyperion PROTOCOL=limine KERNEL_PATH=boot:///hyperion - KERNEL_CMDLINE=log=trace + KERNEL_CMDLINE=log=debug diff --git a/old_cargo_configs/runner.sh b/old_cargo_configs/runner.sh deleted file mode 100755 index e66833b774f66418285d8f9a737ee97127d47376..0000000000000000000000000000000000000000 --- a/old_cargo_configs/runner.sh +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/env bash -# -# Hyperion x86_64 is runnable - -set -xe - -echo $@ - -LIMINE_GIT_URL="https://github.com/limine-bootloader/limine.git" -ISO_DIR=target/hyperion/x86_64/iso -KERNEL=$1 - -# Clone the `limine` repository if we don't have it yet. -if [ ! -d target/limine ]; then - git clone $LIMINE_GIT_URL --depth=1 --branch v3.0-branch-binary target/limine -fi - -# Make sure we have an up-to-date version of the bootloader. -cd target/limine -git fetch -make -cd - - -# Copy the needed files into an ISO image. -mkdir -p $ISO_DIR -cp cfg/limine.cfg target/limine/limine{.sys,-cd.bin,-cd-efi.bin} $ISO_DIR -cp $KERNEL $ISO_DIR/hyperion - -xorriso -as mkisofs \ - -b limine-cd.bin \ - -no-emul-boot -boot-load-size 4 -boot-info-table \ - --efi-boot limine-cd-efi.bin \ - -efi-boot-part --efi-boot-image --protective-msdos-label \ - $ISO_DIR -o $KERNEL.iso - -# For the image to be bootable on BIOS systems, we must run `limine-deploy` on it. -target/limine/limine-deploy $KERNEL.iso - -# A hack to detect if the kernel is a testing kernel -# Cargo test binary generates a 'random id' for testing binaries -if [ "$(basename $KERNEL)" = "hyperion" ]; then - # Run the created image with QEMU. - qemu-system-x86_64 \ - -enable-kvm \ - -machine q35 \ - -cpu qemu64,+rdrand,+rdseed \ - -smp 8 \ - -m 512m \ - -M smm=off \ - -d int,guest_errors,cpu_reset \ - -no-reboot \ - -serial stdio \ - $KERNEL.iso - #-s -S \ - #-no-shutdown \ - #-D target/log.txt \ -else - set +e - # Run the created image with QEMU. - qemu-system-x86_64 \ - -enable-kvm \ - -machine q35 \ - -cpu qemu64,+rdrand,+rdseed \ - -smp 8 \ - -m 512m \ - -M smm=off \ - -d int,guest_errors,cpu_reset \ - -device isa-debug-exit,iobase=0xf4,iosize=0x04 \ - -no-reboot \ - -serial stdio \ - -display none \ - $KERNEL.iso - #-no-shutdown \ - #-D target/log.txt \ - - [ $? -ne 33 ] && exit 1 - exit 0 -fi diff --git a/src/boot/limine/addr.rs b/src/boot/limine/addr.rs index bae296dff6e328bf63e4ca4a52888a542258cad3..b083eeadf1ba0360ef840ca4fa8eedeef8db4c79 100644 --- a/src/boot/limine/addr.rs +++ b/src/boot/limine/addr.rs @@ -1,4 +1,4 @@ -use limine::{LimineKernelAddressRequest, LimineKernelAddressResponse}; +use limine::{LimineHhdmRequest, LimineKernelAddressRequest, LimineKernelAddressResponse}; use spin::Lazy; use x86_64::{PhysAddr, VirtAddr}; @@ -12,9 +12,23 @@ pub fn virt_addr() -> VirtAddr { VirtAddr::new(KERNEL_ADDR.virtual_base) } +pub fn hhdm_offset() -> u64 { + static HHDM_OFFSET: Lazy<u64> = Lazy::new(|| { + static REQ: LimineHhdmRequest = LimineHhdmRequest::new(0); + REQ.get_response() + .get() + .expect("Cannot get Limine HHDM response") + .offset + }); + + *HHDM_OFFSET +} + // static KERNEL_ADDR: Lazy<&'static LimineKernelAddressResponse> = Lazy::new(|| { static REQ: LimineKernelAddressRequest = LimineKernelAddressRequest::new(0); - REQ.get_response().get().unwrap() + REQ.get_response() + .get() + .expect("Cannot get Limine HHDM response") }); diff --git a/src/boot/limine/mem.rs b/src/boot/limine/mem.rs index ab4b1fe5841c820f129c4e8b1f717f2bb70f7f8f..e4ebbf672902dd0865a5a903a1a186b451bb5839 100644 --- a/src/boot/limine/mem.rs +++ b/src/boot/limine/mem.rs @@ -1,47 +1,37 @@ -use crate::mem::map::Memmap; +use crate::{ + mem::map::{Memmap, Memtype}, + trace, +}; +use core::sync::atomic::{AtomicBool, Ordering}; use limine::{LimineMemmapEntry, LimineMemmapRequest, LimineMemoryMapEntryType, NonNullPtr}; -use spin::Lazy; +use x86_64::PhysAddr; // pub fn memmap() -> impl Iterator<Item = Memmap> { - const DEFAULT_MEMMAP: Memmap = Memmap { - base: u64::MAX, - len: 0u64, - }; + static FIRST_TIME: AtomicBool = AtomicBool::new(true); + let first_time = FIRST_TIME.swap(false, Ordering::SeqCst); - memiter() - .scan(DEFAULT_MEMMAP, |acc, memmap| { - // TODO: zero init reclaimable regions - if let LimineMemoryMapEntryType::Usable - // | LimineMemoryMapEntryType::AcpiReclaimable - // | LimineMemoryMapEntryType::BootloaderReclaimable - = memmap.typ - { - acc.base = memmap.base.min(acc.base); - acc.len += memmap.len; - Some(None) - } else if acc.len == 0 { - acc.base = u64::MAX; - Some(None) - } else { - Some(Some(core::mem::replace(acc, DEFAULT_MEMMAP))) - } - }) - .flatten() -} + memiter().filter_map(move |memmap| { + // TODO: zero init reclaimable regions + + if first_time && memmap.typ != LimineMemoryMapEntryType::Reserved { + trace!("{memmap:?}"); + } -pub fn memtotal() -> u64 { - static TOTAL: Lazy<u64> = Lazy::new(|| { - memiter() - .filter(|memmap| { - memmap.typ != LimineMemoryMapEntryType::Reserved - && memmap.typ != LimineMemoryMapEntryType::Framebuffer - }) - .map(|memmap| memmap.len) - .sum::<u64>() - }); - *TOTAL + let ty = match memmap.typ { + LimineMemoryMapEntryType::Usable => Memtype::Usable, + LimineMemoryMapEntryType::BootloaderReclaimable => Memtype::BootloaderReclaimable, + LimineMemoryMapEntryType::KernelAndModules => Memtype::KernelAndModules, + _ => return None, + }; + + Some(Memmap { + base: PhysAddr::new(memmap.base), + len: memmap.len, + ty, + }) + }) } fn memiter() -> impl Iterator<Item = &'static NonNullPtr<LimineMemmapEntry>> { diff --git a/src/boot/limine/mod.rs b/src/boot/limine/mod.rs index a0288990b00450db288f597a52ad7fe8968c814e..f2d6c0db49c328244e07f7be7b16b89dc37218a9 100644 --- a/src/boot/limine/mod.rs +++ b/src/boot/limine/mod.rs @@ -3,10 +3,10 @@ use crate::{arch, kernel_main}; // +pub use addr::hhdm_offset; pub use addr::phys_addr; pub use addr::virt_addr; pub use mem::memmap; -pub use mem::memtotal; pub use term::_print; // diff --git a/src/main.rs b/src/main.rs index 7deb83197b1d4f8fd9a350ffe3f4a667afc502da..c38b63d0882ce95c2fdc065fd855dc2705383654 100644 --- a/src/main.rs +++ b/src/main.rs @@ -57,45 +57,14 @@ fn kernel_main() -> ! { debug!("Cmdline: {:?}", env::Arguments::get()); debug!( - "Kernel addr: {:?} {:?}", + "Kernel addr: {:?}, {:?}, HDDM Offset: {:#0X?}", boot::virt_addr(), - boot::phys_addr() + boot::phys_addr(), + boot::hhdm_offset() ); mem::init(); - /* let (l4, _) = Cr3::read(); - - let read_pt = |frame: PhysFrame| -> &mut PageTable { - let addr = VirtAddr::new(frame.start_address().as_u64()); - let table: *mut PageTable = addr.as_mut_ptr(); - unsafe { &mut *table } - }; - - for (i, e) in read_pt(l4).iter().enumerate() { - if !e.is_unused() { - println!("L4 entry {i}: {e:?}"); - - for (i, e) in read_pt(e.frame().unwrap()).iter().enumerate() { - if !e.is_unused() { - println!(" L3 entry {i}: {e:?}"); - - for (i, e) in read_pt(e.frame().unwrap()).iter().enumerate() { - if !e.is_unused() { - println!(" L2 entry {i}: {e:?}"); - - for (i, e) in read_pt(e.frame().unwrap()).iter().enumerate() { - if !e.is_unused() { - println!(" L1 entry {i}: {e:?}"); - } - } - } - } - } - } - } - } */ - // ofc. every kernel has to have this cringy ascii name splash info!("\n{}\n", include_str!("./splash")); diff --git a/src/mem/bump.rs b/src/mem/bump.rs index cd0b47c6fc706f4623d830eddfa393f2ddf4d35b..def5fef270dad68065445a78489af1f8d04f1d52 100644 --- a/src/mem/bump.rs +++ b/src/mem/bump.rs @@ -1,4 +1,4 @@ -use super::map::Memmap; +use super::{map::Memmap, to_higher_half}; use crate::{boot, error}; use core::{ alloc::{GlobalAlloc, Layout}, @@ -57,11 +57,11 @@ unsafe impl GlobalAlloc for BumpAllocator { let memory = inner.map.base; let mut remaining = inner.remaining.lock(); - let top = memory + *remaining; + let top = (memory + *remaining).as_u64(); let Some(tmp) = top.checked_sub(layout.size() as u64) else { error!("OUT OF MEMORY"); error!( - "ALLOC: size: {} align: {} top: {top} memory: {memory} remaining: {remaining}", + "ALLOC: size: {} align: {} top: {top} memory: {memory:?} remaining: {remaining}", layout.size(), layout.align() ); @@ -72,11 +72,11 @@ unsafe impl GlobalAlloc for BumpAllocator { if let Some(left) = remaining.checked_sub(reservation) { *remaining = left; - (memory + left) as _ + to_higher_half(memory + left).as_mut_ptr() } else { error!("OUT OF MEMORY"); error!( - "ALLOC: size: {} align: {} top: {top} new: {new_top} memory: {memory} remaining: {remaining}", + "ALLOC: size: {} align: {} top: {top} new: {new_top} memory: {memory:?} remaining: {remaining}", layout.size(), layout.align() ); diff --git a/src/mem/map.rs b/src/mem/map.rs index 6681f948e225fdcf5f0caf9e3b7f7a375cf13a62..eb55abe7b802c9729301c515fd962171595daebd 100644 --- a/src/mem/map.rs +++ b/src/mem/map.rs @@ -1,7 +1,73 @@ -#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] +use x86_64::PhysAddr; + +// + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct Memmap { - pub base: u64, + pub base: PhysAddr, pub len: u64, + pub ty: Memtype, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Memtype { + Usable, + BootloaderReclaimable, + KernelAndModules, +} + +// + +impl Memmap { + /// Returns `true` if the memtype is [`Usable`]. + /// + /// [`Usable`]: Memtype::Usable + #[must_use] + pub fn is_usable(&self) -> bool { + self.ty.is_usable() + } + + /// Returns `true` if the memtype is [`BootloaderReclaimable`]. + /// + /// [`BootloaderReclaimable`]: Memtype::BootloaderReclaimable + #[must_use] + pub fn is_bootloader_reclaimable(&self) -> bool { + self.ty.is_bootloader_reclaimable() + } + + /// Returns `true` if the memtype is [`KernelAndModules`]. + /// + /// [`KernelAndModules`]: Memtype::KernelAndModules + #[must_use] + pub fn is_kernel_and_modules(&self) -> bool { + self.ty.is_kernel_and_modules() + } +} + +impl Memtype { + /// Returns `true` if the memtype is [`Usable`]. + /// + /// [`Usable`]: Memtype::Usable + #[must_use] + pub fn is_usable(&self) -> bool { + matches!(self, Self::Usable) + } + + /// Returns `true` if the memtype is [`BootloaderReclaimable`]. + /// + /// [`BootloaderReclaimable`]: Memtype::BootloaderReclaimable + #[must_use] + pub fn is_bootloader_reclaimable(&self) -> bool { + matches!(self, Self::BootloaderReclaimable) + } + + /// Returns `true` if the memtype is [`KernelAndModules`]. + /// + /// [`KernelAndModules`]: Memtype::KernelAndModules + #[must_use] + pub fn is_kernel_and_modules(&self) -> bool { + matches!(self, Self::KernelAndModules) + } } // diff --git a/src/mem/mod.rs b/src/mem/mod.rs index 08297bbd94c06a9b6b9b7d835441aeb94c2dfbc1..8a01c6e666c39693df4add3e64f15ab8078ddc69 100644 --- a/src/mem/mod.rs +++ b/src/mem/mod.rs @@ -1,4 +1,9 @@ use crate::{boot, debug, mem::map::Memmap, util::fmt::NumberPostfix}; +use x86_64::{ + registers::control::Cr3, + structures::paging::{page_table::FrameError, PageTable, PhysFrame, Size2MiB, Size4KiB}, + PhysAddr, VirtAddr, +}; // @@ -6,16 +11,87 @@ pub mod map; // allocator pub mod bump; -pub mod pfa; +pub mod pmm; // pub fn init() { - let usable = boot::memmap().map(|Memmap { len, .. }| len).sum::<u64>(); - let total = boot::memtotal(); - debug!("Usable system memory: {}B", usable.postfix_binary()); - debug!("Total system memory: {}B", total.postfix_binary()); - bump::init(); - pfa::init(); + pmm::init(); +} + +// + +fn is_higher_half(addr: u64) -> bool { + addr >= boot::hhdm_offset() +} + +fn to_higher_half(addr: PhysAddr) -> VirtAddr { + let addr = addr.as_u64(); + if is_higher_half(addr) { + VirtAddr::new(addr) + } else { + VirtAddr::new(addr + boot::hhdm_offset()) + } +} + +fn from_higher_half(addr: VirtAddr) -> PhysAddr { + let addr = addr.as_u64(); + if is_higher_half(addr) { + PhysAddr::new(addr - boot::hhdm_offset()) + } else { + PhysAddr::new(addr) + } +} + +fn walk_page_tables(addr: VirtAddr) -> Option<PhysAddr> { + enum AnyPhysFrame { + Size4KiB(PhysFrame<Size4KiB>), + Size2MiB(PhysFrame<Size2MiB>), + } + + impl AnyPhysFrame { + fn start_address(&self) -> PhysAddr { + match self { + AnyPhysFrame::Size4KiB(v) => v.start_address(), + AnyPhysFrame::Size2MiB(v) => v.start_address(), + } + } + } + + let (l4, _) = Cr3::read(); + + let page_table_indices = [ + addr.p4_index(), + addr.p3_index(), + addr.p2_index(), + addr.p1_index(), + ]; + let mut frame = AnyPhysFrame::Size4KiB(l4); + + for index in page_table_indices { + let virt = to_higher_half(frame.start_address()); + let table: *const PageTable = virt.as_ptr(); + let table = unsafe { &*table }; + + let entry = &table[index]; + frame = match entry.frame() { + Ok(frame) => AnyPhysFrame::Size4KiB(frame), + Err(FrameError::FrameNotPresent) => return None, + Err(FrameError::HugeFrame) => { + AnyPhysFrame::Size2MiB(PhysFrame::<Size2MiB>::containing_address(entry.addr())) + } + } + } + + Some(frame.start_address() + u64::from(addr.page_offset())) +} + +fn debug_phys_addr(addr: PhysAddr) { + debug!( + "{:?} {:?} {:?}", + addr, + walk_page_tables(VirtAddr::new(addr.as_u64())), + walk_page_tables(to_higher_half(addr)) + ); } diff --git a/src/mem/pfa.rs b/src/mem/pfa.rs deleted file mode 100755 index b9241c9bdc6585b35a3ca18e553fbad2ace69976..0000000000000000000000000000000000000000 --- a/src/mem/pfa.rs +++ /dev/null @@ -1,112 +0,0 @@ -use super::map::Memmap; -use crate::{ - boot, debug, - mem::bump, - util::{bitmap::Bitmap, fmt::NumberPostfix}, -}; -use core::slice; -use spin::{Mutex, Once}; -use x86_64::{align_down, align_up}; - -// - -const PAGE_SIZE: u64 = 2u64.pow(12); // 4KiB pages - -// const PAGE_SIZE: u64 = 2u64.pow(21); // 2MiB pages - -static PFA: Once<Mutex<PageFrameAllocator>> = Once::new(); - -// - -pub fn init() { - let mem_bottom = boot::memmap() - .map(|Memmap { base, .. }| base) - .min() - .expect("No memory"); - - let mem_top = boot::memmap() - .map(|Memmap { base, len }| base + len) - .max() - .expect("No memory"); - - // size in bytes - let bitmap_size = (mem_top - mem_bottom) / PAGE_SIZE / 8 + 1; - let bitmap_data = boot::memmap() - .find(|Memmap { len, .. }| *len >= bitmap_size) - .expect("No place to store PageFrameAllocator bitmap") - .base; - - // SAFETY: this bitmap is going to be initialized before it is read from - let bitmap = unsafe { slice::from_raw_parts_mut(bitmap_data as _, bitmap_size as _) }; - let mut bitmap = Bitmap::new(bitmap); - bitmap.fill(true); // initialized here - - let bottom_page = align_up(mem_bottom, PAGE_SIZE) / PAGE_SIZE; - - // free up some pages - for Memmap { mut base, mut len } in boot::memmap() { - if let Some(map) = bump::map() && map.base == base { - // skip the BumpAllocator spot - base += map.base; - len -= map.len; - } - if base == bitmap_data { - // skip the bitmap allocation spot - base += bitmap_data; - len -= bitmap_size; - } - - let mut bottom = align_up(base, PAGE_SIZE); - let mut top = align_down(base + len, PAGE_SIZE); - - if bottom >= top { - continue; - } - - debug!( - "Free pages: {:#0X?} ({}B)", - bottom..top, - (top - bottom).postfix_binary() - ); - - bottom /= PAGE_SIZE; - top /= PAGE_SIZE; - bottom -= bottom_page; - top -= bottom_page; - - for page in bottom..top { - #[cfg(debug_assertions)] - bitmap.set(page as _, false).unwrap(); - #[cfg(not(debug_assertions))] - let res = bitmap.set(page as _, false); - } - } - - let free = bitmap.iter_false().count() as u64 * PAGE_SIZE; - let used = 0; - debug!("Free pages: ({}B)", free.postfix_binary()); - - PFA.call_once(|| { - Mutex::new(PageFrameAllocator { - bitmap, - free, - used, - bottom_page, - }) - }); -} - -// - -pub struct PageFrameAllocator { - bitmap: Bitmap<'static>, - free: u64, - used: u64, - bottom_page: u64, -} - -// - -impl PageFrameAllocator { - pub fn free_page(&mut self, _addr: u64) {} -} diff --git a/src/mem/pmm.rs b/src/mem/pmm.rs new file mode 100755 index 0000000000000000000000000000000000000000..413dc6c6ec741aacd37d09397acd89a7ab8c5260 --- /dev/null +++ b/src/mem/pmm.rs @@ -0,0 +1,328 @@ +use super::{map::Memmap, to_higher_half}; +use crate::{ + boot, debug, + log::{test_log_level, LogLevel}, + mem::{bump, map::Memtype}, + trace, + util::{bitmap::Bitmap, fmt::NumberPostfix}, +}; +use core::{ + any::type_name, + convert::identity, + fmt, slice, + sync::atomic::{AtomicU64, AtomicUsize, Ordering}, +}; +use spin::{Mutex, Once}; +use x86_64::{align_down, align_up, PhysAddr, VirtAddr}; + +// + +const PAGE_SIZE: u64 = 2u64.pow(12); // 4KiB pages + +// const PAGE_SIZE: u64 = 2u64.pow(21); // 2MiB pages + +static PFA: Once<PageFrameAllocator> = Once::new(); + +// + +pub fn init() { + // usable system memory + let usable: u64 = boot::memmap() + .filter(Memmap::is_usable) + .map(|Memmap { len, .. }| len) + .sum(); + + // total system memory + let total: u64 = boot::memmap().map(|Memmap { len, .. }| len).sum(); + + // the end of the usable physical memory address space + let top = boot::memmap() + .filter(Memmap::is_usable) + .map(|Memmap { base, len, ty }| base + len) + .max() + .expect("No memory"); + + // size in bytes + let bitmap_size = align_up(top.as_u64() / PAGE_SIZE / 8, PAGE_SIZE); + let bitmap_data = boot::memmap() + .filter(Memmap::is_usable) + .find(|Memmap { len, .. }| *len >= bitmap_size) + .expect("No place to store PageFrameAllocator bitmap") + .base; + + // SAFETY: this bitmap is going to be initialized before it is read from + let bitmap = unsafe { + slice::from_raw_parts_mut(to_higher_half(bitmap_data).as_mut_ptr(), bitmap_size as _) + }; + let mut bitmap = Bitmap::new(bitmap); + bitmap.fill(true); // initialized here + + // free up some pages + for Memmap { + mut base, + mut len, + ty, + } in boot::memmap().filter(Memmap::is_usable) + { + if let Some(map) = bump::map() && map.base == base { + // skip the BumpAllocator spot + base += map.base.as_u64(); + len -= map.len; + } + if base == bitmap_data { + // skip the bitmap allocation spot + base += bitmap_data.as_u64(); + len -= bitmap_size; + } + + let mut bottom = base.as_u64(); + let mut top = base.as_u64() + len; + + debug!( + "Free pages: {:#0X?} ({}B)", + bottom..top, + (top - bottom).postfix_binary() + ); + + bottom /= PAGE_SIZE; + top /= PAGE_SIZE; + + for page in bottom..top { + bitmap.set(page as _, false).unwrap(); + } + } + + let used = bump::map().map(|Memmap { len, .. }| len).unwrap_or(0) + bitmap_size; + + let pfa = PageFrameAllocator { + bitmap: bitmap.into(), + usable: usable.into(), + used: used.into(), + total: total.into(), + + last_alloc_index: 0.into(), + }; + + debug!("PFA:\n{pfa}"); + + PFA.call_once(|| pfa); +} + +// + +pub struct PageFrameAllocator { + // 1 bits are used pages + bitmap: Mutex<Bitmap<'static>>, + usable: AtomicU64, + used: AtomicU64, + total: AtomicU64, + + last_alloc_index: AtomicUsize, +} + +#[derive(Debug)] +pub struct PageFrame { + first: PhysAddr, + count: usize, +} + +// + +impl PageFrameAllocator { + /// System total memory in bytes + pub fn total_mem(&self) -> u64 { + self.total.load(Ordering::SeqCst) + } + + /// System usable memory in bytes + pub fn usable_mem(&self) -> u64 { + self.usable.load(Ordering::SeqCst) + } + + /// Currently used usable memory in bytes + pub fn used_mem(&self) -> u64 { + self.used.load(Ordering::SeqCst) + } + + /// Currently free usable memory in bytes + pub fn free_mem(&self) -> u64 { + self.usable_mem() - self.used_mem() + } + + /// Reserved memory in bytes + pub fn reserved_mem(&self) -> u64 { + self.total_mem() - self.usable_mem() + } + + /// Free up pages + /// + /// Double frees are not possible due to [`PageFrame`] missing [`Clone`] and it cannot be + /// constructed manually + pub fn free(&self, frame: PageFrame) { + if frame.first.as_u64() == 0 || frame.count == 0 { + return; + } + + let mut bitmap = self.bitmap.lock(); + let page = (frame.first.as_u64() / PAGE_SIZE) as usize; + for page in page..page + frame.count { + bitmap.set(page, false).unwrap(); + } + + self.used + .fetch_sub(frame.count as u64 * PAGE_SIZE, Ordering::SeqCst); + } + + /// Alloc pages + /// + /// Use [`Self::free`] to not leak pages (-> memory) + pub fn alloc(&self, count: usize) -> PageFrame { + if count == 0 { + return PageFrame { + first: PhysAddr::new(0), + count: 0, + }; + } + + let mut bitmap = self.bitmap.lock(); + + let first_page = self.alloc_at(&mut bitmap, count).unwrap_or_else(|| { + // TODO: handle OOM a bit better + self.alloc_from(0); + self.alloc_at(&mut bitmap, count).expect("OOM") + }); + + self.alloc_from(first_page + count); + + let addr = PhysAddr::new(first_page as u64 * PAGE_SIZE); + + // SAFETY: TODO: + let page_data: &mut [u8] = unsafe { + slice::from_raw_parts_mut( + to_higher_half(addr).as_mut_ptr(), + count * PAGE_SIZE as usize, + ) + }; + + // fill the page with zeros + trace!("Memzeroing {:?}", page_data.as_ptr_range()); + page_data.fill(0); + + self.used + .fetch_add(count as u64 * PAGE_SIZE, Ordering::SeqCst); + + PageFrame { first: addr, count } + } + + fn alloc_from(&self, index: usize) { + self.last_alloc_index.store(index, Ordering::SeqCst) + } + + // returns the page index, not the page address + fn alloc_at(&self, bitmap: &mut Bitmap, count: usize) -> Option<usize> { + let mut first_page = self.last_alloc_index.load(Ordering::SeqCst); + 'main: loop { + if first_page + count > bitmap.len() { + return None; + } + + /* if test_log_level(LogLevel::Trace) { + trace!( + "Trying to allocate {count} pages from {:?}", + to_higher_half(PhysAddr::new(first_page as u64 * PAGE_SIZE)) + ); + } */ + + // go reversed so that skips would be more efficient + for offs in (0..count).rev() { + // SAFETY: `first_page + offs` < `first_page + count` <= `bitmap.len()` + // => bitmap has to contain `first_page + offs` + if unsafe { bitmap.get(first_page + offs).unwrap_unchecked() } { + // skip all page windows which have this locked page + first_page = first_page + offs + 1; + continue 'main; + } + } + + // found a window of free pages + for offs in 0..count { + // lock them + _ = bitmap.set(first_page + offs, true); + } + + return Some(first_page); + } + } +} + +impl fmt::Display for PageFrameAllocator { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + writeln!( + f, + "Total system memory: {}B", + self.total_mem().postfix_binary() + )?; + writeln!( + f, + "Usable system memory: {}B", + self.usable_mem().postfix_binary() + )?; + writeln!( + f, + "Used system memory: {}B", + self.used_mem().postfix_binary() + )?; + writeln!( + f, + "Free system memory: {}B", + self.free_mem().postfix_binary() + )?; + write!( + f, + "Reserved system memory: {}B", + self.reserved_mem().postfix_binary() + )?; + + Ok(()) + } +} + +impl PageFrame { + pub fn addr(&self) -> PhysAddr { + self.first + } +} + +// + +#[cfg(test)] +mod tests { + use crate::mem::pmm::PFA; + + #[test_case] + fn pfa_simple() { + let pfa = PFA.get().unwrap(); + + let a = pfa.alloc(1); + assert_ne!(a.addr().as_u64(), 0); + + let b = pfa.alloc(1); + assert_ne!(b.addr().as_u64(), 0); + assert_ne!(a.addr().as_u64(), b.addr().as_u64()); + + pfa.free(a); + pfa.alloc_from(0); + let c = pfa.alloc(1); + assert_ne!(c.addr().as_u64(), 0); + assert_ne!(b.addr().as_u64(), c.addr().as_u64()); + + let d = pfa.alloc(1); + assert_ne!(d.addr().as_u64(), 0); + assert_ne!(c.addr().as_u64(), d.addr().as_u64()); + + // pfa.free(a); // <- compile error as expected + pfa.free(b); + pfa.free(c); + pfa.free(d); + } +} diff --git a/src/video/font.rs b/src/video/font.rs index 1224e2221682d2b0d81f6af1e8d0167a8321271f..2a9bbdbb074cf673a498d23f9cf37c1319c9701f 100644 --- a/src/video/font.rs +++ b/src/video/font.rs @@ -1,258 +1,1113 @@ pub static FONT: [([u16; 16], bool); 256] = [ - ([21845, 32768, 1, 32768, 1, 35410, 2647, 35418, 31123, 32768, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 51612, 19011, 64076, 19025, 51598, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 42460, 9347, 39052, 9361, 42126, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 42462, 9347, 39070, 9347, 42142, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 64926, 4675, 37470, 4675, 37278, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 45662, 19011, 51934, 27459, 62046, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 42380, 5203, 35934, 5203, 42386, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 35790, 2131, 35790, 2131, 64462, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 40056, 649, 35960, 4233, 36472, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 40772, 1093, 33916, 1093, 33860, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 40708, 261, 40708, 261, 33148, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 40772, 1093, 33860, 1065, 33808, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 40828, 261, 40828, 261, 33028, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 36728, 4357, 36612, 2309, 37240, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 36472, 4357, 37176, 4417, 36412, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 40824, 1029, 33848, 1089, 40764, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 47260, 2213, 47268, 2213, 48028, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 37262, 6227, 36946, 4179, 47502, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 39310, 8275, 36946, 2131, 47502, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 39310, 8275, 38994, 8275, 39310, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 41358, 12371, 43090, 14419, 41358, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 51602, 10839, 39510, 11227, 51794, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 51756, 22851, 59532, 18577, 51342, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 40414, 9347, 40094, 9347, 40094, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 42188, 11555, 46562, 9507, 42284, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 37244, 6917, 38268, 4357, 37244, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 47708, 19011, 47692, 19025, 47502, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 62366, 2115, 35230, 2563, 61918, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 36472, 265, 34424, 2057, 34568, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 36464, 265, 34408, 2121, 34672, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 36408, 329, 34360, 2089, 34632, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 36424, 329, 34376, 2121, 34608, 1, 32768, 1, 32768, 1, 43690], true), - ([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], false), - ([0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 0, 16, 16, 0, 0], false), - ([0, 0, 68, 68, 68, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], false), - ([0, 0, 0, 0, 72, 72, 72, 126, 36, 36, 126, 18, 18, 18, 0, 0], false), - ([0, 0, 0, 0, 16, 124, 146, 18, 28, 112, 144, 146, 124, 16, 0, 0], false), - ([0, 0, 0, 0, 140, 82, 82, 44, 16, 16, 104, 148, 148, 98, 0, 0], false), - ([0, 0, 0, 0, 56, 68, 68, 40, 24, 148, 162, 66, 98, 156, 0, 0], false), - ([0, 0, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], false), - ([0, 0, 0, 32, 16, 16, 8, 8, 8, 8, 8, 8, 16, 16, 32, 0], false), - ([0, 0, 0, 4, 8, 8, 16, 16, 16, 16, 16, 16, 8, 8, 4, 0], false), - ([0, 0, 0, 0, 0, 0, 16, 146, 84, 56, 84, 146, 16, 0, 0, 0], false), - ([0, 0, 0, 0, 0, 0, 16, 16, 16, 254, 16, 16, 16, 0, 0, 0], false), - ([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 16, 16, 8], false), - ([0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0], false), - ([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 24, 0, 0], false), - ([0, 0, 0, 0, 64, 64, 32, 16, 16, 8, 8, 4, 2, 2, 0, 0], false), - ([0, 0, 0, 0, 24, 36, 66, 98, 82, 74, 70, 66, 36, 24, 0, 0], false), - ([0, 0, 0, 0, 16, 24, 20, 16, 16, 16, 16, 16, 16, 124, 0, 0], false), - ([0, 0, 0, 0, 60, 66, 66, 64, 48, 8, 4, 2, 2, 126, 0, 0], false), - ([0, 0, 0, 0, 60, 66, 66, 64, 56, 64, 64, 66, 66, 60, 0, 0], false), - ([0, 0, 0, 0, 32, 48, 40, 36, 34, 34, 126, 32, 32, 32, 0, 0], false), - ([0, 0, 0, 0, 126, 2, 2, 2, 62, 64, 64, 64, 66, 60, 0, 0], false), - ([0, 0, 0, 0, 56, 4, 2, 2, 62, 66, 66, 66, 66, 60, 0, 0], false), - ([0, 0, 0, 0, 126, 64, 64, 32, 32, 32, 16, 16, 16, 16, 0, 0], false), - ([0, 0, 0, 0, 60, 66, 66, 66, 60, 66, 66, 66, 66, 60, 0, 0], false), - ([0, 0, 0, 0, 60, 66, 66, 66, 124, 64, 64, 64, 32, 28, 0, 0], false), - ([0, 0, 0, 0, 0, 0, 24, 24, 0, 0, 0, 24, 24, 0, 0, 0], false), - ([0, 0, 0, 0, 0, 0, 24, 24, 0, 0, 0, 24, 16, 16, 8, 0], false), - ([0, 0, 0, 0, 0, 64, 32, 16, 8, 4, 8, 16, 32, 64, 0, 0], false), - ([0, 0, 0, 0, 0, 0, 0, 126, 0, 0, 0, 126, 0, 0, 0, 0], false), - ([0, 0, 0, 0, 0, 2, 4, 8, 16, 32, 16, 8, 4, 2, 0, 0], false), - ([0, 0, 0, 0, 60, 66, 66, 64, 32, 16, 16, 0, 16, 16, 0, 0], false), - ([0, 0, 0, 0, 56, 68, 82, 106, 74, 74, 74, 114, 4, 120, 0, 0], false), - ([0, 0, 0, 0, 24, 36, 36, 66, 66, 126, 66, 66, 66, 66, 0, 0], false), - ([0, 0, 0, 0, 62, 66, 66, 66, 62, 66, 66, 66, 66, 62, 0, 0], false), - ([0, 0, 0, 0, 60, 66, 66, 2, 2, 2, 2, 66, 66, 60, 0, 0], false), - ([0, 0, 0, 0, 30, 34, 66, 66, 66, 66, 66, 66, 34, 30, 0, 0], false), - ([0, 0, 0, 0, 126, 2, 2, 2, 62, 2, 2, 2, 2, 126, 0, 0], false), - ([0, 0, 0, 0, 126, 2, 2, 2, 62, 2, 2, 2, 2, 2, 0, 0], false), - ([0, 0, 0, 0, 60, 66, 66, 2, 2, 114, 66, 66, 98, 92, 0, 0], false), - ([0, 0, 0, 0, 66, 66, 66, 66, 126, 66, 66, 66, 66, 66, 0, 0], false), - ([0, 0, 0, 0, 124, 16, 16, 16, 16, 16, 16, 16, 16, 124, 0, 0], false), - ([0, 0, 0, 0, 248, 32, 32, 32, 32, 32, 32, 34, 34, 28, 0, 0], false), - ([0, 0, 0, 0, 66, 34, 18, 10, 6, 6, 10, 18, 34, 66, 0, 0], false), - ([0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 126, 0, 0], false), - ([0, 0, 0, 0, 66, 66, 102, 102, 90, 90, 66, 66, 66, 66, 0, 0], false), - ([0, 0, 0, 0, 66, 70, 70, 74, 74, 82, 82, 98, 98, 66, 0, 0], false), - ([0, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 66, 66, 60, 0, 0], false), - ([0, 0, 0, 0, 62, 66, 66, 66, 62, 2, 2, 2, 2, 2, 0, 0], false), - ([0, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 90, 102, 60, 192, 0], false), - ([0, 0, 0, 0, 62, 66, 66, 66, 62, 18, 34, 34, 66, 66, 0, 0], false), - ([0, 0, 0, 0, 60, 66, 66, 2, 12, 48, 64, 66, 66, 60, 0, 0], false), - ([0, 0, 0, 0, 254, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0], false), - ([0, 0, 0, 0, 66, 66, 66, 66, 66, 66, 66, 66, 66, 60, 0, 0], false), - ([0, 0, 0, 0, 130, 130, 130, 68, 68, 68, 40, 40, 16, 16, 0, 0], false), - ([0, 0, 0, 0, 66, 66, 66, 66, 90, 90, 102, 102, 66, 66, 0, 0], false), - ([0, 0, 0, 0, 66, 66, 36, 36, 24, 24, 36, 36, 66, 66, 0, 0], false), - ([0, 0, 0, 0, 130, 130, 68, 68, 40, 16, 16, 16, 16, 16, 0, 0], false), - ([0, 0, 0, 0, 126, 64, 64, 32, 16, 8, 4, 2, 2, 126, 0, 0], false), - ([0, 0, 0, 112, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 112, 0], false), - ([0, 0, 0, 0, 2, 2, 4, 8, 8, 16, 16, 32, 64, 64, 0, 0], false), - ([0, 0, 0, 14, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 14, 0], false), - ([0, 0, 24, 36, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], false), - ([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 0], false), - ([0, 4, 8, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], false), - ([0, 0, 0, 0, 0, 0, 60, 66, 64, 124, 66, 66, 98, 92, 0, 0], false), - ([0, 0, 0, 2, 2, 2, 58, 70, 66, 66, 66, 66, 70, 58, 0, 0], false), - ([0, 0, 0, 0, 0, 0, 60, 66, 2, 2, 2, 2, 66, 60, 0, 0], false), - ([0, 0, 0, 64, 64, 64, 92, 98, 66, 66, 66, 66, 98, 92, 0, 0], false), - ([0, 0, 0, 0, 0, 0, 60, 66, 66, 126, 2, 2, 66, 60, 0, 0], false), - ([0, 0, 0, 48, 8, 8, 8, 62, 8, 8, 8, 8, 8, 8, 0, 0], false), - ([0, 0, 0, 0, 0, 64, 92, 34, 34, 34, 28, 4, 60, 66, 66, 60], false), - ([0, 0, 0, 2, 2, 2, 58, 70, 66, 66, 66, 66, 66, 66, 0, 0], false), - ([0, 0, 0, 16, 16, 0, 24, 16, 16, 16, 16, 16, 16, 124, 0, 0], false), - ([0, 0, 0, 32, 32, 0, 48, 32, 32, 32, 32, 32, 32, 32, 18, 12], false), - ([0, 0, 0, 2, 2, 2, 34, 18, 10, 6, 10, 18, 34, 66, 0, 0], false), - ([0, 0, 0, 24, 16, 16, 16, 16, 16, 16, 16, 16, 16, 124, 0, 0], false), - ([0, 0, 0, 0, 0, 0, 110, 146, 146, 146, 146, 146, 146, 146, 0, 0], false), - ([0, 0, 0, 0, 0, 0, 58, 70, 66, 66, 66, 66, 66, 66, 0, 0], false), - ([0, 0, 0, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 60, 0, 0], false), - ([0, 0, 0, 0, 0, 0, 58, 70, 66, 66, 66, 66, 70, 58, 2, 2], false), - ([0, 0, 0, 0, 0, 0, 92, 98, 66, 66, 66, 66, 98, 92, 64, 64], false), - ([0, 0, 0, 0, 0, 0, 58, 70, 66, 2, 2, 2, 2, 2, 0, 0], false), - ([0, 0, 0, 0, 0, 0, 60, 66, 2, 12, 48, 64, 66, 60, 0, 0], false), - ([0, 0, 0, 0, 8, 8, 8, 62, 8, 8, 8, 8, 8, 48, 0, 0], false), - ([0, 0, 0, 0, 0, 0, 66, 66, 66, 66, 66, 66, 98, 92, 0, 0], false), - ([0, 0, 0, 0, 0, 0, 66, 66, 66, 36, 36, 36, 24, 24, 0, 0], false), - ([0, 0, 0, 0, 0, 0, 130, 146, 146, 146, 146, 146, 146, 108, 0, 0], false), - ([0, 0, 0, 0, 0, 0, 66, 66, 36, 24, 24, 36, 66, 66, 0, 0], false), - ([0, 0, 0, 0, 0, 0, 66, 66, 66, 66, 66, 100, 88, 64, 64, 60], false), - ([0, 0, 0, 0, 0, 0, 126, 64, 32, 16, 8, 4, 2, 126, 0, 0], false), - ([0, 0, 0, 48, 8, 8, 16, 16, 8, 4, 8, 16, 16, 8, 8, 48], false), - ([0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16], false), - ([0, 0, 0, 12, 16, 16, 8, 8, 16, 32, 16, 8, 8, 16, 16, 12], false), - ([0, 0, 0, 140, 146, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], false), - ([21845, 32768, 1, 32768, 1, 35790, 2131, 35794, 2131, 64462, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 47502, 19027, 52174, 19011, 47682, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 47506, 19027, 47710, 2643, 35218, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 51662, 19027, 63950, 18515, 51278, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 51666, 19031, 63962, 19027, 51666, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 40238, 9573, 42404, 9509, 40238, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 35794, 2135, 35802, 2131, 64466, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 45980, 18499, 63884, 18961, 51662, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 45982, 18499, 63902, 18947, 51678, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 47570, 1171, 39070, 8339, 40082, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 48036, 8485, 41276, 8485, 39204, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 45986, 2339, 37154, 8469, 39176, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 47182, 18515, 51278, 18499, 48066, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 51278, 18515, 51278, 18499, 46018, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 33904, 1169, 33904, 1105, 33936, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 48028, 16451, 45452, 2577, 63950, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 48028, 16451, 45452, 16913, 47566, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 62350, 2131, 45138, 16467, 48014, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 41550, 12883, 41550, 8771, 61826, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 47694, 16979, 45646, 2627, 63874, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 47580, 1155, 39052, 8337, 40078, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 52124, 18499, 63554, 18499, 52124, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 37188, 4461, 38228, 6981, 37188, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 45532, 19011, 63948, 18513, 51278, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 45534, 19011, 63966, 18499, 51294, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 61852, 2627, 45644, 16977, 47502, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 55756, 17443, 50596, 17705, 55750, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 48028, 4163, 36940, 4177, 48014, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 48028, 4163, 37250, 4611, 47580, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 40816, 1033, 33840, 1089, 33848, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 62348, 2131, 35218, 2579, 61900, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 37176, 6985, 38200, 4361, 37128, 1, 32768, 1, 32768, 1, 43690], true), - ([21845, 32768, 1, 32768, 1, 61900, 2643, 35294, 2131, 61522, 1, 32768, 1, 32768, 1, 43690], true), - ([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], false), - ([0, 0, 0, 0, 16, 16, 0, 16, 16, 16, 16, 16, 16, 16, 0, 0], false), - ([0, 0, 0, 0, 16, 16, 124, 146, 18, 18, 146, 124, 16, 16, 0, 0], false), - ([0, 0, 0, 0, 112, 8, 8, 8, 62, 8, 8, 8, 124, 134, 0, 0], false), - ([0, 0, 0, 0, 0, 66, 60, 36, 66, 66, 36, 60, 66, 0, 0, 0], false), - ([0, 0, 0, 0, 130, 68, 40, 16, 254, 16, 254, 16, 16, 16, 0, 0], false), - ([0, 0, 0, 0, 16, 16, 16, 16, 0, 0, 16, 16, 16, 16, 0, 0], false), - ([0, 0, 0, 0, 60, 66, 2, 60, 66, 66, 60, 64, 66, 60, 0, 0], false), - ([36, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], false), - ([0, 0, 0, 0, 60, 66, 153, 165, 133, 133, 165, 153, 66, 60, 0, 0], false), - ([0, 0, 56, 64, 120, 68, 120, 0, 124, 0, 0, 0, 0, 0, 0, 0], false), - ([0, 0, 0, 0, 0, 72, 72, 36, 36, 18, 36, 36, 72, 72, 0, 0], false), - ([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 64, 64, 64, 0, 0], false), - ([21845, 32768, 1, 50780, 10819, 37836, 4689, 37454, 1, 32768, 1, 33728, 1, 32768, 1, 43690], true), - ([0, 0, 0, 0, 60, 66, 157, 165, 165, 157, 149, 165, 66, 60, 0, 0], false), - ([0, 0, 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], false), - ([0, 0, 0, 0, 24, 36, 36, 24, 0, 0, 0, 0, 0, 0, 0, 0], false), - ([0, 0, 0, 0, 16, 16, 16, 254, 16, 16, 16, 0, 254, 0, 0, 0], false), - ([0, 0, 0, 28, 34, 32, 24, 4, 2, 62, 0, 0, 0, 0, 0, 0], false), - ([0, 0, 0, 28, 34, 32, 28, 32, 34, 28, 0, 0, 0, 0, 0, 0], false), - ([0, 32, 16, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], false), - ([0, 0, 0, 0, 0, 0, 66, 66, 66, 66, 66, 66, 102, 154, 2, 1], false), - ([0, 0, 0, 0, 252, 94, 94, 94, 92, 80, 80, 80, 80, 80, 80, 0], false), - ([0, 0, 0, 0, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 0, 0], false), - ([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 12], false), - ([0, 0, 0, 8, 12, 10, 8, 8, 8, 62, 0, 0, 0, 0, 0, 0], false), - ([0, 0, 56, 68, 68, 68, 56, 0, 124, 0, 0, 0, 0, 0, 0, 0], false), - ([0, 0, 0, 0, 0, 18, 18, 36, 36, 72, 36, 36, 18, 18, 0, 0], false), - ([0, 0, 0, 0, 68, 70, 36, 20, 20, 72, 104, 84, 114, 66, 0, 0], false), - ([0, 0, 0, 0, 68, 70, 36, 20, 20, 40, 88, 68, 34, 114, 0, 0], false), - ([0, 0, 0, 0, 70, 72, 36, 24, 22, 72, 104, 84, 114, 66, 0, 0], false), - ([0, 0, 0, 0, 8, 8, 0, 8, 8, 4, 2, 66, 66, 60, 0, 0], false), - ([12, 48, 0, 0, 24, 36, 36, 66, 66, 126, 66, 66, 66, 66, 0, 0], false), - ([48, 12, 0, 0, 24, 36, 36, 66, 66, 126, 66, 66, 66, 66, 0, 0], false), - ([24, 36, 0, 0, 24, 36, 36, 66, 66, 126, 66, 66, 66, 66, 0, 0], false), - ([76, 50, 0, 0, 24, 36, 36, 66, 66, 126, 66, 66, 66, 66, 0, 0], false), - ([36, 36, 0, 0, 24, 36, 36, 66, 66, 126, 66, 66, 66, 66, 0, 0], false), - ([24, 36, 24, 0, 24, 36, 36, 66, 66, 126, 66, 66, 66, 66, 0, 0], false), - ([0, 0, 0, 0, 248, 20, 18, 18, 254, 18, 18, 18, 18, 242, 0, 0], false), - ([0, 0, 0, 0, 60, 66, 66, 2, 2, 2, 2, 66, 66, 60, 16, 12], false), - ([12, 48, 0, 0, 126, 2, 2, 2, 62, 2, 2, 2, 2, 126, 0, 0], false), - ([48, 12, 0, 0, 126, 2, 2, 2, 62, 2, 2, 2, 2, 126, 0, 0], false), - ([24, 36, 0, 0, 126, 2, 2, 2, 62, 2, 2, 2, 2, 126, 0, 0], false), - ([36, 36, 0, 0, 126, 2, 2, 2, 62, 2, 2, 2, 2, 126, 0, 0], false), - ([24, 96, 0, 0, 124, 16, 16, 16, 16, 16, 16, 16, 16, 124, 0, 0], false), - ([48, 12, 0, 0, 124, 16, 16, 16, 16, 16, 16, 16, 16, 124, 0, 0], false), - ([24, 36, 0, 0, 124, 16, 16, 16, 16, 16, 16, 16, 16, 124, 0, 0], false), - ([36, 36, 0, 0, 124, 16, 16, 16, 16, 16, 16, 16, 16, 124, 0, 0], false), - ([0, 0, 0, 0, 30, 34, 66, 66, 79, 66, 66, 66, 34, 30, 0, 0], false), - ([76, 50, 0, 0, 66, 70, 70, 74, 74, 82, 82, 98, 98, 66, 0, 0], false), - ([12, 48, 0, 0, 60, 66, 66, 66, 66, 66, 66, 66, 66, 60, 0, 0], false), - ([48, 12, 0, 0, 60, 66, 66, 66, 66, 66, 66, 66, 66, 60, 0, 0], false), - ([24, 36, 0, 0, 60, 66, 66, 66, 66, 66, 66, 66, 66, 60, 0, 0], false), - ([76, 50, 0, 0, 60, 66, 66, 66, 66, 66, 66, 66, 66, 60, 0, 0], false), - ([36, 36, 0, 0, 60, 66, 66, 66, 66, 66, 66, 66, 66, 60, 0, 0], false), - ([0, 0, 0, 0, 0, 0, 0, 66, 36, 24, 36, 66, 0, 0, 0, 0], false), - ([0, 0, 0, 64, 92, 34, 98, 82, 82, 74, 74, 70, 68, 58, 2, 0], false), - ([12, 48, 0, 0, 66, 66, 66, 66, 66, 66, 66, 66, 66, 60, 0, 0], false), - ([48, 12, 0, 0, 66, 66, 66, 66, 66, 66, 66, 66, 66, 60, 0, 0], false), - ([24, 36, 0, 0, 66, 66, 66, 66, 66, 66, 66, 66, 66, 60, 0, 0], false), - ([36, 36, 0, 0, 66, 66, 66, 66, 66, 66, 66, 66, 66, 60, 0, 0], false), - ([48, 12, 0, 0, 130, 130, 68, 68, 40, 16, 16, 16, 16, 16, 0, 0], false), - ([0, 0, 0, 2, 2, 30, 34, 66, 66, 34, 30, 2, 2, 2, 0, 0], false), - ([0, 0, 0, 0, 28, 34, 34, 18, 26, 34, 66, 66, 74, 50, 0, 0], false), - ([0, 0, 12, 48, 0, 0, 60, 66, 64, 124, 66, 66, 98, 92, 0, 0], false), - ([0, 0, 48, 12, 0, 0, 60, 66, 64, 124, 66, 66, 98, 92, 0, 0], false), - ([0, 0, 24, 36, 0, 0, 60, 66, 64, 124, 66, 66, 98, 92, 0, 0], false), - ([0, 0, 76, 50, 0, 0, 60, 66, 64, 124, 66, 66, 98, 92, 0, 0], false), - ([0, 0, 36, 36, 0, 0, 60, 66, 64, 124, 66, 66, 98, 92, 0, 0], false), - ([0, 24, 36, 24, 0, 0, 60, 66, 64, 124, 66, 66, 98, 92, 0, 0], false), - ([0, 0, 0, 0, 0, 0, 124, 146, 144, 252, 18, 18, 146, 124, 0, 0], false), - ([0, 0, 0, 0, 0, 0, 60, 66, 2, 2, 2, 2, 66, 60, 16, 12], false), - ([0, 0, 12, 48, 0, 0, 60, 66, 66, 126, 2, 2, 66, 60, 0, 0], false), - ([0, 0, 48, 12, 0, 0, 60, 66, 66, 126, 2, 2, 66, 60, 0, 0], false), - ([0, 0, 24, 36, 0, 0, 60, 66, 66, 126, 2, 2, 66, 60, 0, 0], false), - ([0, 0, 36, 36, 0, 0, 60, 66, 66, 126, 2, 2, 66, 60, 0, 0], false), - ([0, 0, 12, 48, 0, 0, 24, 16, 16, 16, 16, 16, 16, 124, 0, 0], false), - ([0, 0, 48, 12, 0, 0, 24, 16, 16, 16, 16, 16, 16, 124, 0, 0], false), - ([0, 0, 24, 36, 0, 0, 24, 16, 16, 16, 16, 16, 16, 124, 0, 0], false), - ([0, 0, 36, 36, 0, 0, 24, 16, 16, 16, 16, 16, 16, 124, 0, 0], false), - ([0, 0, 76, 48, 40, 68, 64, 124, 66, 66, 66, 66, 66, 60, 0, 0], false), - ([0, 0, 76, 50, 0, 0, 58, 70, 66, 66, 66, 66, 66, 66, 0, 0], false), - ([0, 0, 12, 48, 0, 0, 60, 66, 66, 66, 66, 66, 66, 60, 0, 0], false), - ([0, 0, 48, 12, 0, 0, 60, 66, 66, 66, 66, 66, 66, 60, 0, 0], false), - ([0, 0, 24, 36, 0, 0, 60, 66, 66, 66, 66, 66, 66, 60, 0, 0], false), - ([0, 0, 76, 50, 0, 0, 60, 66, 66, 66, 66, 66, 66, 60, 0, 0], false), - ([0, 0, 36, 36, 0, 0, 60, 66, 66, 66, 66, 66, 66, 60, 0, 0], false), - ([0, 0, 0, 0, 0, 0, 24, 0, 0, 126, 0, 0, 24, 0, 0, 0], false), - ([0, 0, 0, 0, 0, 64, 60, 98, 82, 82, 74, 74, 70, 60, 2, 0], false), - ([0, 0, 12, 48, 0, 0, 66, 66, 66, 66, 66, 66, 98, 92, 0, 0], false), - ([0, 0, 48, 12, 0, 0, 66, 66, 66, 66, 66, 66, 98, 92, 0, 0], false), - ([0, 0, 24, 36, 0, 0, 66, 66, 66, 66, 66, 66, 98, 92, 0, 0], false), - ([0, 0, 36, 36, 0, 0, 66, 66, 66, 66, 66, 66, 98, 92, 0, 0], false), - ([0, 0, 48, 12, 0, 0, 66, 66, 66, 66, 66, 100, 88, 64, 64, 60], false), - ([0, 0, 0, 2, 2, 2, 58, 70, 66, 66, 66, 66, 70, 58, 2, 2], false), - ([0, 0, 36, 36, 0, 0, 66, 66, 66, 66, 66, 100, 88, 64, 64, 60], false), -]; \ No newline at end of file + ( + [ + 21845, 32768, 1, 32768, 1, 35410, 2647, 35418, 31123, 32768, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 51612, 19011, 64076, 19025, 51598, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 42460, 9347, 39052, 9361, 42126, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 42462, 9347, 39070, 9347, 42142, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 64926, 4675, 37470, 4675, 37278, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 45662, 19011, 51934, 27459, 62046, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 42380, 5203, 35934, 5203, 42386, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 35790, 2131, 35790, 2131, 64462, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 40056, 649, 35960, 4233, 36472, 1, 32768, 1, 32768, 1, 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 40772, 1093, 33916, 1093, 33860, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 40708, 261, 40708, 261, 33148, 1, 32768, 1, 32768, 1, 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 40772, 1093, 33860, 1065, 33808, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 40828, 261, 40828, 261, 33028, 1, 32768, 1, 32768, 1, 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 36728, 4357, 36612, 2309, 37240, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 36472, 4357, 37176, 4417, 36412, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 40824, 1029, 33848, 1089, 40764, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 47260, 2213, 47268, 2213, 48028, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 37262, 6227, 36946, 4179, 47502, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 39310, 8275, 36946, 2131, 47502, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 39310, 8275, 38994, 8275, 39310, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 41358, 12371, 43090, 14419, 41358, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 51602, 10839, 39510, 11227, 51794, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 51756, 22851, 59532, 18577, 51342, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 40414, 9347, 40094, 9347, 40094, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 42188, 11555, 46562, 9507, 42284, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 37244, 6917, 38268, 4357, 37244, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 47708, 19011, 47692, 19025, 47502, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 62366, 2115, 35230, 2563, 61918, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 36472, 265, 34424, 2057, 34568, 1, 32768, 1, 32768, 1, 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 36464, 265, 34408, 2121, 34672, 1, 32768, 1, 32768, 1, 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 36408, 329, 34360, 2089, 34632, 1, 32768, 1, 32768, 1, 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 36424, 329, 34376, 2121, 34608, 1, 32768, 1, 32768, 1, 43690, + ], + true, + ), + ([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], false), + ( + [0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 0, 16, 16, 0, 0], + false, + ), + ([0, 0, 68, 68, 68, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], false), + ( + [0, 0, 0, 0, 72, 72, 72, 126, 36, 36, 126, 18, 18, 18, 0, 0], + false, + ), + ( + [ + 0, 0, 0, 0, 16, 124, 146, 18, 28, 112, 144, 146, 124, 16, 0, 0, + ], + false, + ), + ( + [0, 0, 0, 0, 140, 82, 82, 44, 16, 16, 104, 148, 148, 98, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 56, 68, 68, 40, 24, 148, 162, 66, 98, 156, 0, 0], + false, + ), + ([0, 0, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], false), + ( + [0, 0, 0, 32, 16, 16, 8, 8, 8, 8, 8, 8, 16, 16, 32, 0], + false, + ), + ( + [0, 0, 0, 4, 8, 8, 16, 16, 16, 16, 16, 16, 8, 8, 4, 0], + false, + ), + ( + [0, 0, 0, 0, 0, 0, 16, 146, 84, 56, 84, 146, 16, 0, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 0, 0, 16, 16, 16, 254, 16, 16, 16, 0, 0, 0], + false, + ), + ([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 16, 16, 8], false), + ([0, 0, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0], false), + ([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 24, 0, 0], false), + ([0, 0, 0, 0, 64, 64, 32, 16, 16, 8, 8, 4, 2, 2, 0, 0], false), + ( + [0, 0, 0, 0, 24, 36, 66, 98, 82, 74, 70, 66, 36, 24, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 16, 24, 20, 16, 16, 16, 16, 16, 16, 124, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 60, 66, 66, 64, 48, 8, 4, 2, 2, 126, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 60, 66, 66, 64, 56, 64, 64, 66, 66, 60, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 32, 48, 40, 36, 34, 34, 126, 32, 32, 32, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 126, 2, 2, 2, 62, 64, 64, 64, 66, 60, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 56, 4, 2, 2, 62, 66, 66, 66, 66, 60, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 126, 64, 64, 32, 32, 32, 16, 16, 16, 16, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 60, 66, 66, 66, 60, 66, 66, 66, 66, 60, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 60, 66, 66, 66, 124, 64, 64, 64, 32, 28, 0, 0], + false, + ), + ([0, 0, 0, 0, 0, 0, 24, 24, 0, 0, 0, 24, 24, 0, 0, 0], false), + ([0, 0, 0, 0, 0, 0, 24, 24, 0, 0, 0, 24, 16, 16, 8, 0], false), + ( + [0, 0, 0, 0, 0, 64, 32, 16, 8, 4, 8, 16, 32, 64, 0, 0], + false, + ), + ([0, 0, 0, 0, 0, 0, 0, 126, 0, 0, 0, 126, 0, 0, 0, 0], false), + ([0, 0, 0, 0, 0, 2, 4, 8, 16, 32, 16, 8, 4, 2, 0, 0], false), + ( + [0, 0, 0, 0, 60, 66, 66, 64, 32, 16, 16, 0, 16, 16, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 56, 68, 82, 106, 74, 74, 74, 114, 4, 120, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 24, 36, 36, 66, 66, 126, 66, 66, 66, 66, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 62, 66, 66, 66, 62, 66, 66, 66, 66, 62, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 60, 66, 66, 2, 2, 2, 2, 66, 66, 60, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 30, 34, 66, 66, 66, 66, 66, 66, 34, 30, 0, 0], + false, + ), + ([0, 0, 0, 0, 126, 2, 2, 2, 62, 2, 2, 2, 2, 126, 0, 0], false), + ([0, 0, 0, 0, 126, 2, 2, 2, 62, 2, 2, 2, 2, 2, 0, 0], false), + ( + [0, 0, 0, 0, 60, 66, 66, 2, 2, 114, 66, 66, 98, 92, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 66, 66, 66, 66, 126, 66, 66, 66, 66, 66, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 124, 16, 16, 16, 16, 16, 16, 16, 16, 124, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 248, 32, 32, 32, 32, 32, 32, 34, 34, 28, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 66, 34, 18, 10, 6, 6, 10, 18, 34, 66, 0, 0], + false, + ), + ([0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 126, 0, 0], false), + ( + [0, 0, 0, 0, 66, 66, 102, 102, 90, 90, 66, 66, 66, 66, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 66, 70, 70, 74, 74, 82, 82, 98, 98, 66, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 66, 66, 60, 0, 0], + false, + ), + ([0, 0, 0, 0, 62, 66, 66, 66, 62, 2, 2, 2, 2, 2, 0, 0], false), + ( + [0, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 90, 102, 60, 192, 0], + false, + ), + ( + [0, 0, 0, 0, 62, 66, 66, 66, 62, 18, 34, 34, 66, 66, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 60, 66, 66, 2, 12, 48, 64, 66, 66, 60, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 254, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 66, 66, 66, 66, 66, 66, 66, 66, 66, 60, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 130, 130, 130, 68, 68, 68, 40, 40, 16, 16, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 66, 66, 66, 66, 90, 90, 102, 102, 66, 66, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 66, 66, 36, 36, 24, 24, 36, 36, 66, 66, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 130, 130, 68, 68, 40, 16, 16, 16, 16, 16, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 126, 64, 64, 32, 16, 8, 4, 2, 2, 126, 0, 0], + false, + ), + ( + [0, 0, 0, 112, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 112, 0], + false, + ), + ([0, 0, 0, 0, 2, 2, 4, 8, 8, 16, 16, 32, 64, 64, 0, 0], false), + ([0, 0, 0, 14, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 14, 0], false), + ([0, 0, 24, 36, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], false), + ([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 0], false), + ([0, 4, 8, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], false), + ( + [0, 0, 0, 0, 0, 0, 60, 66, 64, 124, 66, 66, 98, 92, 0, 0], + false, + ), + ( + [0, 0, 0, 2, 2, 2, 58, 70, 66, 66, 66, 66, 70, 58, 0, 0], + false, + ), + ([0, 0, 0, 0, 0, 0, 60, 66, 2, 2, 2, 2, 66, 60, 0, 0], false), + ( + [0, 0, 0, 64, 64, 64, 92, 98, 66, 66, 66, 66, 98, 92, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 0, 0, 60, 66, 66, 126, 2, 2, 66, 60, 0, 0], + false, + ), + ([0, 0, 0, 48, 8, 8, 8, 62, 8, 8, 8, 8, 8, 8, 0, 0], false), + ( + [0, 0, 0, 0, 0, 64, 92, 34, 34, 34, 28, 4, 60, 66, 66, 60], + false, + ), + ( + [0, 0, 0, 2, 2, 2, 58, 70, 66, 66, 66, 66, 66, 66, 0, 0], + false, + ), + ( + [0, 0, 0, 16, 16, 0, 24, 16, 16, 16, 16, 16, 16, 124, 0, 0], + false, + ), + ( + [0, 0, 0, 32, 32, 0, 48, 32, 32, 32, 32, 32, 32, 32, 18, 12], + false, + ), + ( + [0, 0, 0, 2, 2, 2, 34, 18, 10, 6, 10, 18, 34, 66, 0, 0], + false, + ), + ( + [0, 0, 0, 24, 16, 16, 16, 16, 16, 16, 16, 16, 16, 124, 0, 0], + false, + ), + ( + [ + 0, 0, 0, 0, 0, 0, 110, 146, 146, 146, 146, 146, 146, 146, 0, 0, + ], + false, + ), + ( + [0, 0, 0, 0, 0, 0, 58, 70, 66, 66, 66, 66, 66, 66, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 0, 0, 60, 66, 66, 66, 66, 66, 66, 60, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 0, 0, 58, 70, 66, 66, 66, 66, 70, 58, 2, 2], + false, + ), + ( + [0, 0, 0, 0, 0, 0, 92, 98, 66, 66, 66, 66, 98, 92, 64, 64], + false, + ), + ([0, 0, 0, 0, 0, 0, 58, 70, 66, 2, 2, 2, 2, 2, 0, 0], false), + ( + [0, 0, 0, 0, 0, 0, 60, 66, 2, 12, 48, 64, 66, 60, 0, 0], + false, + ), + ([0, 0, 0, 0, 8, 8, 8, 62, 8, 8, 8, 8, 8, 48, 0, 0], false), + ( + [0, 0, 0, 0, 0, 0, 66, 66, 66, 66, 66, 66, 98, 92, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 0, 0, 66, 66, 66, 36, 36, 36, 24, 24, 0, 0], + false, + ), + ( + [ + 0, 0, 0, 0, 0, 0, 130, 146, 146, 146, 146, 146, 146, 108, 0, 0, + ], + false, + ), + ( + [0, 0, 0, 0, 0, 0, 66, 66, 36, 24, 24, 36, 66, 66, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 0, 0, 66, 66, 66, 66, 66, 100, 88, 64, 64, 60], + false, + ), + ( + [0, 0, 0, 0, 0, 0, 126, 64, 32, 16, 8, 4, 2, 126, 0, 0], + false, + ), + ( + [0, 0, 0, 48, 8, 8, 16, 16, 8, 4, 8, 16, 16, 8, 8, 48], + false, + ), + ( + [0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16], + false, + ), + ( + [0, 0, 0, 12, 16, 16, 8, 8, 16, 32, 16, 8, 8, 16, 16, 12], + false, + ), + ([0, 0, 0, 140, 146, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], false), + ( + [ + 21845, 32768, 1, 32768, 1, 35790, 2131, 35794, 2131, 64462, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 47502, 19027, 52174, 19011, 47682, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 47506, 19027, 47710, 2643, 35218, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 51662, 19027, 63950, 18515, 51278, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 51666, 19031, 63962, 19027, 51666, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 40238, 9573, 42404, 9509, 40238, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 35794, 2135, 35802, 2131, 64466, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 45980, 18499, 63884, 18961, 51662, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 45982, 18499, 63902, 18947, 51678, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 47570, 1171, 39070, 8339, 40082, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 48036, 8485, 41276, 8485, 39204, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 45986, 2339, 37154, 8469, 39176, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 47182, 18515, 51278, 18499, 48066, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 51278, 18515, 51278, 18499, 46018, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 33904, 1169, 33904, 1105, 33936, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 48028, 16451, 45452, 2577, 63950, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 48028, 16451, 45452, 16913, 47566, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 62350, 2131, 45138, 16467, 48014, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 41550, 12883, 41550, 8771, 61826, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 47694, 16979, 45646, 2627, 63874, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 47580, 1155, 39052, 8337, 40078, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 52124, 18499, 63554, 18499, 52124, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 37188, 4461, 38228, 6981, 37188, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 45532, 19011, 63948, 18513, 51278, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 45534, 19011, 63966, 18499, 51294, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 61852, 2627, 45644, 16977, 47502, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 55756, 17443, 50596, 17705, 55750, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 48028, 4163, 36940, 4177, 48014, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 48028, 4163, 37250, 4611, 47580, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 40816, 1033, 33840, 1089, 33848, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 62348, 2131, 35218, 2579, 61900, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 37176, 6985, 38200, 4361, 37128, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 21845, 32768, 1, 32768, 1, 61900, 2643, 35294, 2131, 61522, 1, 32768, 1, 32768, 1, + 43690, + ], + true, + ), + ([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], false), + ( + [0, 0, 0, 0, 16, 16, 0, 16, 16, 16, 16, 16, 16, 16, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 16, 16, 124, 146, 18, 18, 146, 124, 16, 16, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 112, 8, 8, 8, 62, 8, 8, 8, 124, 134, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 0, 66, 60, 36, 66, 66, 36, 60, 66, 0, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 130, 68, 40, 16, 254, 16, 254, 16, 16, 16, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 16, 16, 16, 16, 0, 0, 16, 16, 16, 16, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 60, 66, 2, 60, 66, 66, 60, 64, 66, 60, 0, 0], + false, + ), + ([36, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], false), + ( + [ + 0, 0, 0, 0, 60, 66, 153, 165, 133, 133, 165, 153, 66, 60, 0, 0, + ], + false, + ), + ( + [0, 0, 56, 64, 120, 68, 120, 0, 124, 0, 0, 0, 0, 0, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 0, 72, 72, 36, 36, 18, 36, 36, 72, 72, 0, 0], + false, + ), + ([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, 64, 64, 64, 0, 0], false), + ( + [ + 21845, 32768, 1, 50780, 10819, 37836, 4689, 37454, 1, 32768, 1, 33728, 1, 32768, 1, + 43690, + ], + true, + ), + ( + [ + 0, 0, 0, 0, 60, 66, 157, 165, 165, 157, 149, 165, 66, 60, 0, 0, + ], + false, + ), + ([0, 0, 126, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], false), + ([0, 0, 0, 0, 24, 36, 36, 24, 0, 0, 0, 0, 0, 0, 0, 0], false), + ( + [0, 0, 0, 0, 16, 16, 16, 254, 16, 16, 16, 0, 254, 0, 0, 0], + false, + ), + ([0, 0, 0, 28, 34, 32, 24, 4, 2, 62, 0, 0, 0, 0, 0, 0], false), + ( + [0, 0, 0, 28, 34, 32, 28, 32, 34, 28, 0, 0, 0, 0, 0, 0], + false, + ), + ([0, 32, 16, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], false), + ( + [0, 0, 0, 0, 0, 0, 66, 66, 66, 66, 66, 66, 102, 154, 2, 1], + false, + ), + ( + [0, 0, 0, 0, 252, 94, 94, 94, 92, 80, 80, 80, 80, 80, 80, 0], + false, + ), + ([0, 0, 0, 0, 0, 0, 0, 0, 24, 24, 0, 0, 0, 0, 0, 0], false), + ([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 12], false), + ([0, 0, 0, 8, 12, 10, 8, 8, 8, 62, 0, 0, 0, 0, 0, 0], false), + ( + [0, 0, 56, 68, 68, 68, 56, 0, 124, 0, 0, 0, 0, 0, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 0, 18, 18, 36, 36, 72, 36, 36, 18, 18, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 68, 70, 36, 20, 20, 72, 104, 84, 114, 66, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 68, 70, 36, 20, 20, 40, 88, 68, 34, 114, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 70, 72, 36, 24, 22, 72, 104, 84, 114, 66, 0, 0], + false, + ), + ([0, 0, 0, 0, 8, 8, 0, 8, 8, 4, 2, 66, 66, 60, 0, 0], false), + ( + [12, 48, 0, 0, 24, 36, 36, 66, 66, 126, 66, 66, 66, 66, 0, 0], + false, + ), + ( + [48, 12, 0, 0, 24, 36, 36, 66, 66, 126, 66, 66, 66, 66, 0, 0], + false, + ), + ( + [24, 36, 0, 0, 24, 36, 36, 66, 66, 126, 66, 66, 66, 66, 0, 0], + false, + ), + ( + [76, 50, 0, 0, 24, 36, 36, 66, 66, 126, 66, 66, 66, 66, 0, 0], + false, + ), + ( + [36, 36, 0, 0, 24, 36, 36, 66, 66, 126, 66, 66, 66, 66, 0, 0], + false, + ), + ( + [24, 36, 24, 0, 24, 36, 36, 66, 66, 126, 66, 66, 66, 66, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 248, 20, 18, 18, 254, 18, 18, 18, 18, 242, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 60, 66, 66, 2, 2, 2, 2, 66, 66, 60, 16, 12], + false, + ), + ( + [12, 48, 0, 0, 126, 2, 2, 2, 62, 2, 2, 2, 2, 126, 0, 0], + false, + ), + ( + [48, 12, 0, 0, 126, 2, 2, 2, 62, 2, 2, 2, 2, 126, 0, 0], + false, + ), + ( + [24, 36, 0, 0, 126, 2, 2, 2, 62, 2, 2, 2, 2, 126, 0, 0], + false, + ), + ( + [36, 36, 0, 0, 126, 2, 2, 2, 62, 2, 2, 2, 2, 126, 0, 0], + false, + ), + ( + [24, 96, 0, 0, 124, 16, 16, 16, 16, 16, 16, 16, 16, 124, 0, 0], + false, + ), + ( + [48, 12, 0, 0, 124, 16, 16, 16, 16, 16, 16, 16, 16, 124, 0, 0], + false, + ), + ( + [24, 36, 0, 0, 124, 16, 16, 16, 16, 16, 16, 16, 16, 124, 0, 0], + false, + ), + ( + [36, 36, 0, 0, 124, 16, 16, 16, 16, 16, 16, 16, 16, 124, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 30, 34, 66, 66, 79, 66, 66, 66, 34, 30, 0, 0], + false, + ), + ( + [76, 50, 0, 0, 66, 70, 70, 74, 74, 82, 82, 98, 98, 66, 0, 0], + false, + ), + ( + [12, 48, 0, 0, 60, 66, 66, 66, 66, 66, 66, 66, 66, 60, 0, 0], + false, + ), + ( + [48, 12, 0, 0, 60, 66, 66, 66, 66, 66, 66, 66, 66, 60, 0, 0], + false, + ), + ( + [24, 36, 0, 0, 60, 66, 66, 66, 66, 66, 66, 66, 66, 60, 0, 0], + false, + ), + ( + [76, 50, 0, 0, 60, 66, 66, 66, 66, 66, 66, 66, 66, 60, 0, 0], + false, + ), + ( + [36, 36, 0, 0, 60, 66, 66, 66, 66, 66, 66, 66, 66, 60, 0, 0], + false, + ), + ([0, 0, 0, 0, 0, 0, 0, 66, 36, 24, 36, 66, 0, 0, 0, 0], false), + ( + [0, 0, 0, 64, 92, 34, 98, 82, 82, 74, 74, 70, 68, 58, 2, 0], + false, + ), + ( + [12, 48, 0, 0, 66, 66, 66, 66, 66, 66, 66, 66, 66, 60, 0, 0], + false, + ), + ( + [48, 12, 0, 0, 66, 66, 66, 66, 66, 66, 66, 66, 66, 60, 0, 0], + false, + ), + ( + [24, 36, 0, 0, 66, 66, 66, 66, 66, 66, 66, 66, 66, 60, 0, 0], + false, + ), + ( + [36, 36, 0, 0, 66, 66, 66, 66, 66, 66, 66, 66, 66, 60, 0, 0], + false, + ), + ( + [48, 12, 0, 0, 130, 130, 68, 68, 40, 16, 16, 16, 16, 16, 0, 0], + false, + ), + ( + [0, 0, 0, 2, 2, 30, 34, 66, 66, 34, 30, 2, 2, 2, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 28, 34, 34, 18, 26, 34, 66, 66, 74, 50, 0, 0], + false, + ), + ( + [0, 0, 12, 48, 0, 0, 60, 66, 64, 124, 66, 66, 98, 92, 0, 0], + false, + ), + ( + [0, 0, 48, 12, 0, 0, 60, 66, 64, 124, 66, 66, 98, 92, 0, 0], + false, + ), + ( + [0, 0, 24, 36, 0, 0, 60, 66, 64, 124, 66, 66, 98, 92, 0, 0], + false, + ), + ( + [0, 0, 76, 50, 0, 0, 60, 66, 64, 124, 66, 66, 98, 92, 0, 0], + false, + ), + ( + [0, 0, 36, 36, 0, 0, 60, 66, 64, 124, 66, 66, 98, 92, 0, 0], + false, + ), + ( + [0, 24, 36, 24, 0, 0, 60, 66, 64, 124, 66, 66, 98, 92, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 0, 0, 124, 146, 144, 252, 18, 18, 146, 124, 0, 0], + false, + ), + ( + [0, 0, 0, 0, 0, 0, 60, 66, 2, 2, 2, 2, 66, 60, 16, 12], + false, + ), + ( + [0, 0, 12, 48, 0, 0, 60, 66, 66, 126, 2, 2, 66, 60, 0, 0], + false, + ), + ( + [0, 0, 48, 12, 0, 0, 60, 66, 66, 126, 2, 2, 66, 60, 0, 0], + false, + ), + ( + [0, 0, 24, 36, 0, 0, 60, 66, 66, 126, 2, 2, 66, 60, 0, 0], + false, + ), + ( + [0, 0, 36, 36, 0, 0, 60, 66, 66, 126, 2, 2, 66, 60, 0, 0], + false, + ), + ( + [0, 0, 12, 48, 0, 0, 24, 16, 16, 16, 16, 16, 16, 124, 0, 0], + false, + ), + ( + [0, 0, 48, 12, 0, 0, 24, 16, 16, 16, 16, 16, 16, 124, 0, 0], + false, + ), + ( + [0, 0, 24, 36, 0, 0, 24, 16, 16, 16, 16, 16, 16, 124, 0, 0], + false, + ), + ( + [0, 0, 36, 36, 0, 0, 24, 16, 16, 16, 16, 16, 16, 124, 0, 0], + false, + ), + ( + [0, 0, 76, 48, 40, 68, 64, 124, 66, 66, 66, 66, 66, 60, 0, 0], + false, + ), + ( + [0, 0, 76, 50, 0, 0, 58, 70, 66, 66, 66, 66, 66, 66, 0, 0], + false, + ), + ( + [0, 0, 12, 48, 0, 0, 60, 66, 66, 66, 66, 66, 66, 60, 0, 0], + false, + ), + ( + [0, 0, 48, 12, 0, 0, 60, 66, 66, 66, 66, 66, 66, 60, 0, 0], + false, + ), + ( + [0, 0, 24, 36, 0, 0, 60, 66, 66, 66, 66, 66, 66, 60, 0, 0], + false, + ), + ( + [0, 0, 76, 50, 0, 0, 60, 66, 66, 66, 66, 66, 66, 60, 0, 0], + false, + ), + ( + [0, 0, 36, 36, 0, 0, 60, 66, 66, 66, 66, 66, 66, 60, 0, 0], + false, + ), + ([0, 0, 0, 0, 0, 0, 24, 0, 0, 126, 0, 0, 24, 0, 0, 0], false), + ( + [0, 0, 0, 0, 0, 64, 60, 98, 82, 82, 74, 74, 70, 60, 2, 0], + false, + ), + ( + [0, 0, 12, 48, 0, 0, 66, 66, 66, 66, 66, 66, 98, 92, 0, 0], + false, + ), + ( + [0, 0, 48, 12, 0, 0, 66, 66, 66, 66, 66, 66, 98, 92, 0, 0], + false, + ), + ( + [0, 0, 24, 36, 0, 0, 66, 66, 66, 66, 66, 66, 98, 92, 0, 0], + false, + ), + ( + [0, 0, 36, 36, 0, 0, 66, 66, 66, 66, 66, 66, 98, 92, 0, 0], + false, + ), + ( + [0, 0, 48, 12, 0, 0, 66, 66, 66, 66, 66, 100, 88, 64, 64, 60], + false, + ), + ( + [0, 0, 0, 2, 2, 2, 58, 70, 66, 66, 66, 66, 70, 58, 2, 2], + false, + ), + ( + [0, 0, 36, 36, 0, 0, 66, 66, 66, 66, 66, 100, 88, 64, 64, 60], + false, + ), +]; diff --git a/src/video/logger.rs b/src/video/logger.rs index 5ebf9f7ca9193548f5a756c88a5957f05c3af8c6..75dcfc91416002b898e470fd3b7a74790b611f11 100644 --- a/src/video/logger.rs +++ b/src/video/logger.rs @@ -40,7 +40,18 @@ impl Writer { match self.escapes.next(byte) { DecodedPart::Byte(b'\n') => { if let Some(mut fbo) = get_fbo() { - self.new_line(1, &mut fbo) + #[cfg(debug_assertions)] + let lines = if self.cursor[1] + 1 >= Self::size(&mut fbo)[1] { + // scroll more if the cursor is near the bottom + // + // because scrolling is slow in debug mode + 8 + } else { + 1 + }; + #[cfg(not(debug_assertions))] + let lines = 1; + self.new_line(lines, &mut fbo) } } DecodedPart::Byte(b'\t') => {