uwu
This commit is contained in:
commit
1216ed0d09
13 changed files with 1021 additions and 0 deletions
6
.cargo/config.toml
Normal file
6
.cargo/config.toml
Normal file
|
@ -0,0 +1,6 @@
|
|||
[unstable]
|
||||
build-std = ["core", "compiler_builtins", "alloc"]
|
||||
build-std-features = ["compiler-builtins-mem"]
|
||||
|
||||
[build]
|
||||
target = "aarch64-nintendo-switch-freestanding"
|
1
.envrc
Normal file
1
.envrc
Normal file
|
@ -0,0 +1 @@
|
|||
use flake
|
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
target/
|
||||
.direnv/
|
231
Cargo.lock
generated
Normal file
231
Cargo.lock
generated
Normal file
|
@ -0,0 +1,231 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "ab_glyph_rasterizer"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "330223a1aecc308757b9926e9391c9b47f8ef2dbd8aea9df88312aea18c5e8d6"
|
||||
dependencies = [
|
||||
"libm",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
|
||||
|
||||
[[package]]
|
||||
name = "convert_case"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca"
|
||||
dependencies = [
|
||||
"unicode-segmentation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "font8x8"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e63201c624b8c8883921b1a1accc8916c4fa9dbfb15d122b26e4dde945b86bbf"
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
|
||||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb"
|
||||
|
||||
[[package]]
|
||||
name = "linked_list_allocator"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "549ce1740e46b291953c4340adcd74c59bcf4308f4cac050fd33ba91b7168f4a"
|
||||
|
||||
[[package]]
|
||||
name = "logpacket"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/aarch64-switch-rs/logpacket#d807c993fb4578e3809d91e3484c7d97f59eb3db"
|
||||
|
||||
[[package]]
|
||||
name = "nx"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/aarch64-switch-rs/nx#31f4590cac1776a4731380c29bcbb972591b5bba"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"linked_list_allocator",
|
||||
"logpacket",
|
||||
"paste",
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "owned_ttf_parser"
|
||||
version = "0.15.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05e6affeb1632d6ff6a23d2cd40ffed138e82f1532571a26f527c8a284bb2fbb"
|
||||
dependencies = [
|
||||
"ttf-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "paste"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.49"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
|
||||
[[package]]
|
||||
name = "rusttype"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ff8374aa04134254b7995b63ad3dc41c7f7236f69528b28553da7d72efaa967"
|
||||
dependencies = [
|
||||
"ab_glyph_rasterizer",
|
||||
"libm",
|
||||
"owned_ttf_parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.152"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.152"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.107"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ttf-parser"
|
||||
version = "0.15.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b3e06c9b9d80ed6b745c7159c40b311ad2916abb34a49e9be2653b90db0d8dd"
|
||||
|
||||
[[package]]
|
||||
name = "ui2d"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"font8x8",
|
||||
"libm",
|
||||
"nx",
|
||||
"rusttype",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a"
|
||||
|
||||
[[package]]
|
||||
name = "uwurandom-nx"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"nx",
|
||||
"rand_core",
|
||||
"ui2d",
|
||||
"uwurandom-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uwurandom-proc-macros"
|
||||
version = "0.1.0"
|
||||
source = "git+https://git.skye.vg/me/uwurandom-rs#9b7344cadb7d1a73f5dec92ee2a77bad2a1e1d76"
|
||||
dependencies = [
|
||||
"convert_case",
|
||||
"quote",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uwurandom-rs"
|
||||
version = "0.1.0"
|
||||
source = "git+https://git.skye.vg/me/uwurandom-rs#9b7344cadb7d1a73f5dec92ee2a77bad2a1e1d76"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
"uwurandom-proc-macros",
|
||||
]
|
19
Cargo.toml
Normal file
19
Cargo.toml
Normal file
|
@ -0,0 +1,19 @@
|
|||
[package]
|
||||
name = "uwurandom-nx"
|
||||
authors = ["aarch64-switch-rs authors"]
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
nx = { git = "https://github.com/aarch64-switch-rs/nx", features=["input", "rand"] }
|
||||
rand_core = "0.6.4"
|
||||
ui2d = { path = "./ui2d" }
|
||||
uwurandom-rs = { git = "https://git.skye.vg/me/uwurandom-rs" }
|
||||
|
||||
# For help / more information, see https://github.com/aarch64-switch-rs/cargo-nx/wiki
|
||||
|
||||
[package.metadata.nx.nro.nacp]
|
||||
default_name = "uwurandom-nx"
|
||||
default_author = "skyevg"
|
||||
version = "0.1.0"
|
||||
application_id = "0x010018160C3AFA2D"
|
BIN
Inter-Regular.ttf
Normal file
BIN
Inter-Regular.ttf
Normal file
Binary file not shown.
94
flake.lock
Normal file
94
flake.lock
Normal file
|
@ -0,0 +1,94 @@
|
|||
{
|
||||
"nodes": {
|
||||
"flake-utils": {
|
||||
"locked": {
|
||||
"lastModified": 1667395993,
|
||||
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils_2": {
|
||||
"locked": {
|
||||
"lastModified": 1659877975,
|
||||
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1672525397,
|
||||
"narHash": "sha256-WASDnyxHKWVrEe0dIzkpH+jzKlCKAk0husv0f/9pyxg=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "8ba56d7c0d7490680f2d51ba46a141eca7c46afa",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1665296151,
|
||||
"narHash": "sha256-uOB0oxqxN9K7XGF1hcnY+PQnlQJ+3bP2vCn/+Ru/bbc=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "14ccaaedd95a488dd7ae142757884d8e125b3363",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"rust-overlay": "rust-overlay"
|
||||
}
|
||||
},
|
||||
"rust-overlay": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils_2",
|
||||
"nixpkgs": "nixpkgs_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1672712534,
|
||||
"narHash": "sha256-8S0DdMPcbITnlOu0uA81mTo3hgX84wK8S9wS34HEFY4=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "69fb7bf0a8c40e6c4c197fa1816773774c8ac59f",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
25
flake.nix
Normal file
25
flake.nix
Normal file
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
rust-overlay.url = "github:oxalica/rust-overlay";
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, rust-overlay, flake-utils, ... }:
|
||||
flake-utils.lib.eachDefaultSystem (system:
|
||||
let
|
||||
overlays = [ (import rust-overlay) ];
|
||||
pkgs = import nixpkgs { inherit system overlays; };
|
||||
in
|
||||
with pkgs; {
|
||||
devShells.default = mkShell {
|
||||
buildInputs = [
|
||||
(rust-bin.selectLatestNightlyWith (toolchain:
|
||||
toolchain.default.override {
|
||||
extensions = [ "rust-src" ];
|
||||
targets = [ "thumbv6m-none-eabi" ];
|
||||
}))
|
||||
];
|
||||
};
|
||||
});
|
||||
}
|
192
src/main.rs
Normal file
192
src/main.rs
Normal file
|
@ -0,0 +1,192 @@
|
|||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
extern crate alloc;
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
extern crate nx;
|
||||
use nx::diag::abort;
|
||||
use nx::diag::log::lm::LmLogger;
|
||||
use nx::gpu;
|
||||
use nx::input;
|
||||
use nx::rand::RandomGenerator;
|
||||
use nx::result::*;
|
||||
use nx::service::hid;
|
||||
use nx::svc;
|
||||
use nx::util;
|
||||
use rand_core::RngCore;
|
||||
use uwurandom_rs::StateMachine;
|
||||
|
||||
use core::panic;
|
||||
|
||||
extern crate ui2d;
|
||||
|
||||
#[no_mangle]
|
||||
pub fn initialize_heap(hbl_heap: util::PointerAndSize) -> util::PointerAndSize {
|
||||
if hbl_heap.is_valid() {
|
||||
hbl_heap
|
||||
} else {
|
||||
let heap_size: usize = 0x10000000;
|
||||
let heap_address = svc::set_heap_size(heap_size).unwrap();
|
||||
util::PointerAndSize::new(heap_address, heap_size)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Square {
|
||||
x: i32,
|
||||
y: i32,
|
||||
size: i32,
|
||||
x_incr: i32,
|
||||
y_incr: i32,
|
||||
x_mult: i32,
|
||||
y_mult: i32,
|
||||
color: ui2d::RGBA8,
|
||||
}
|
||||
|
||||
impl Square {
|
||||
pub fn new(x: i32, y: i32, size: i32, color: ui2d::RGBA8) -> Self {
|
||||
Self {
|
||||
x: x,
|
||||
y: y,
|
||||
size: size,
|
||||
x_incr: 1,
|
||||
y_incr: 1,
|
||||
x_mult: 1,
|
||||
y_mult: 1,
|
||||
color: color,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_render(&mut self, surface: &mut ui2d::SurfaceEx) {
|
||||
surface.draw(self.x, self.y, self.size, self.size, self.color, false);
|
||||
|
||||
self.x += self.x_incr * self.x_mult;
|
||||
self.y += self.y_incr * self.y_mult;
|
||||
|
||||
if self.x <= 0 {
|
||||
if self.x_incr < 0 {
|
||||
self.x_incr -= 1;
|
||||
self.x_incr = -self.x_incr;
|
||||
}
|
||||
self.x += self.x_incr * self.x_mult;
|
||||
self.x_mult += 1;
|
||||
} else if (self.x + self.size) as u32 >= surface.get_width() {
|
||||
if self.x_incr > 0 {
|
||||
self.x_incr += 1;
|
||||
self.x_incr = -self.x_incr;
|
||||
}
|
||||
self.x += self.x_incr * self.x_mult;
|
||||
self.x_mult += 1;
|
||||
}
|
||||
|
||||
if self.y <= 0 {
|
||||
if self.y_incr < 0 {
|
||||
self.y_incr -= 1;
|
||||
self.y_incr = -self.y_incr;
|
||||
}
|
||||
self.y += self.y_incr * self.y_mult;
|
||||
self.y_mult += 1;
|
||||
} else if (self.y + self.size) as u32 >= surface.get_height() {
|
||||
if self.y_incr > 0 {
|
||||
self.y_incr += 1;
|
||||
self.y_incr = -self.y_incr;
|
||||
}
|
||||
self.y += self.y_incr * self.y_mult;
|
||||
self.y_mult += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct NxRngWrap(nx::rand::SplCsrngGenerator);
|
||||
|
||||
impl RngCore for NxRngWrap {
|
||||
fn next_u32(&mut self) -> u32 {
|
||||
rand_core::impls::next_u32_via_fill(self)
|
||||
}
|
||||
|
||||
fn next_u64(&mut self) -> u64 {
|
||||
rand_core::impls::next_u64_via_fill(self)
|
||||
}
|
||||
|
||||
fn fill_bytes(&mut self, dest: &mut [u8]) {
|
||||
self.0.random_bytes(dest.as_ptr() as _, dest.len()).unwrap()
|
||||
}
|
||||
|
||||
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> core::result::Result<(), rand_core::Error> {
|
||||
Ok(self.fill_bytes(dest))
|
||||
}
|
||||
}
|
||||
|
||||
impl NxRngWrap {
|
||||
fn new() -> Self {
|
||||
Self(nx::rand::SplCsrngGenerator::new().unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn main() -> Result<()> {
|
||||
let mut gpu_ctx = gpu::Context::new(
|
||||
gpu::NvDrvServiceKind::Applet,
|
||||
gpu::ViServiceKind::System,
|
||||
0x800000,
|
||||
)?;
|
||||
|
||||
let supported_style_tags = hid::NpadStyleTag::Handheld();
|
||||
let supported_npad_ids = [hid::NpadIdType::Handheld];
|
||||
let input_ctx = input::Context::new(supported_style_tags, &supported_npad_ids)?;
|
||||
|
||||
let color_fmt = gpu::ColorFormat::A8B8G8R8;
|
||||
|
||||
let c_white = ui2d::RGBA8::new_rgb(0xFF, 0xFF, 0xFF);
|
||||
let c_black = ui2d::RGBA8::new_rgb(0, 0, 0);
|
||||
|
||||
let font_data = include_bytes!("../Inter-Regular.ttf");
|
||||
let font = ui2d::Font::try_from_bytes(font_data as &[u8]).unwrap();
|
||||
|
||||
let mut surface = ui2d::SurfaceEx::from(gpu_ctx.create_stray_layer_surface(
|
||||
"Default",
|
||||
2,
|
||||
color_fmt,
|
||||
gpu::PixelFormat::RGBA_8888,
|
||||
gpu::Layout::BlockLinear,
|
||||
)?);
|
||||
|
||||
let mut rng = NxRngWrap::new();
|
||||
|
||||
let mut uwurandom = StateMachine::new(&mut rng);
|
||||
|
||||
let mut result = String::from("Press + to exit\n");
|
||||
|
||||
loop {
|
||||
let mut p_handheld = input_ctx.get_player(hid::NpadIdType::Handheld);
|
||||
|
||||
let buttons_down = p_handheld.get_buttons_down();
|
||||
if buttons_down.contains(hid::NpadButton::A()) {
|
||||
let (new_state, generated) = uwurandom.generate(&mut rng);
|
||||
uwurandom = new_state;
|
||||
result.push(generated);
|
||||
if result.lines().last().unwrap().len() > 100 {
|
||||
result.push('\n');
|
||||
}
|
||||
} else if buttons_down.contains(hid::NpadButton::Plus()) {
|
||||
// Exit if Plus/+ is pressed.
|
||||
break;
|
||||
}
|
||||
|
||||
surface.start()?;
|
||||
|
||||
surface.clear(c_white);
|
||||
surface.draw_font_text(&font, result.clone(), c_black, 25.0, 10, 10, true);
|
||||
// surface.draw_bitmap_text(result.clone(), c_black, 2, 10, 250, true);
|
||||
|
||||
surface.end()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[panic_handler]
|
||||
fn panic_handler(info: &panic::PanicInfo) -> ! {
|
||||
util::simple_panic_handler::<LmLogger>(info, abort::AbortLevel::FatalThrow())
|
||||
}
|
3
ui2d/.cargo/config.toml
Normal file
3
ui2d/.cargo/config.toml
Normal file
|
@ -0,0 +1,3 @@
|
|||
[unstable]
|
||||
build-std = ["core", "compiler_builtins", "alloc"]
|
||||
build-std-features = ["compiler-builtins-mem"]
|
101
ui2d/Cargo.lock
generated
Normal file
101
ui2d/Cargo.lock
generated
Normal file
|
@ -0,0 +1,101 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "ab_glyph_rasterizer"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a13739d7177fbd22bb0ed28badfff9f372f8bef46c863db4e1c6248f6b223b6e"
|
||||
dependencies = [
|
||||
"libm",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
|
||||
|
||||
[[package]]
|
||||
name = "font8x8"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e63201c624b8c8883921b1a1accc8916c4fa9dbfb15d122b26e4dde945b86bbf"
|
||||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33a33a362ce288760ec6a508b94caaec573ae7d3bbbd91b87aa0bad4456839db"
|
||||
|
||||
[[package]]
|
||||
name = "linked_list_allocator"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "549ce1740e46b291953c4340adcd74c59bcf4308f4cac050fd33ba91b7168f4a"
|
||||
|
||||
[[package]]
|
||||
name = "logpacket"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/aarch64-switch-rs/logpacket#d807c993fb4578e3809d91e3484c7d97f59eb3db"
|
||||
|
||||
[[package]]
|
||||
name = "nx"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/aarch64-switch-rs/nx#bfa3d790e023acc6dbe07a3ac1f70987e6f62a28"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"linked_list_allocator",
|
||||
"logpacket",
|
||||
"paste",
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "owned_ttf_parser"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f923fb806c46266c02ab4a5b239735c144bdeda724a50ed058e5226f594cde3"
|
||||
dependencies = [
|
||||
"ttf-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "paste"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc"
|
||||
|
||||
[[package]]
|
||||
name = "rusttype"
|
||||
version = "0.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc7c727aded0be18c5b80c1640eae0ac8e396abf6fa8477d96cb37d18ee5ec59"
|
||||
dependencies = [
|
||||
"ab_glyph_rasterizer",
|
||||
"libm",
|
||||
"owned_ttf_parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "ttf-parser"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e5d7cd7ab3e47dda6e56542f4bbf3824c15234958c6e1bd6aaa347e93499fdc"
|
||||
|
||||
[[package]]
|
||||
name = "ui2d"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"font8x8",
|
||||
"libm",
|
||||
"nx",
|
||||
"rusttype",
|
||||
]
|
23
ui2d/Cargo.toml
Normal file
23
ui2d/Cargo.toml
Normal file
|
@ -0,0 +1,23 @@
|
|||
[package]
|
||||
name = "ui2d"
|
||||
version = "0.1.0"
|
||||
authors = ["XorTroll"]
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
nx = { git = "https://github.com/aarch64-switch-rs/nx", features = [ "gpu" ] }
|
||||
|
||||
[dependencies.font8x8]
|
||||
version = "0.2"
|
||||
default-features = false
|
||||
features = ["unicode"]
|
||||
|
||||
[dependencies.rusttype]
|
||||
version = "0.9.2"
|
||||
default-features = false
|
||||
features = ["libm-math"]
|
||||
|
||||
[dependencies.libm]
|
||||
version = "0.2.1"
|
||||
default-features = false
|
||||
features = []
|
324
ui2d/src/lib.rs
Normal file
324
ui2d/src/lib.rs
Normal file
|
@ -0,0 +1,324 @@
|
|||
#![no_std]
|
||||
|
||||
// Note: quite simple lib made for UI tests to easily render stuff
|
||||
|
||||
use nx::result::*;
|
||||
use nx::gpu;
|
||||
use nx::arm;
|
||||
|
||||
extern crate alloc;
|
||||
use alloc::string::String;
|
||||
use alloc::vec::Vec;
|
||||
use core::ptr;
|
||||
use core::mem;
|
||||
use font8x8::UnicodeFonts;
|
||||
|
||||
pub type Font<'a> = rusttype::Font<'a>;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct RGBA8 {
|
||||
pub r: u8,
|
||||
pub g: u8,
|
||||
pub b: u8,
|
||||
pub a: u8,
|
||||
}
|
||||
|
||||
impl RGBA8 {
|
||||
pub const fn new_rgba(r: u8, g: u8, b: u8, a: u8) -> Self {
|
||||
Self { r: r, g: g, b: b, a: a }
|
||||
}
|
||||
|
||||
pub const fn new_rgb(r: u8, g: u8, b: u8) -> Self {
|
||||
Self { r: r, g: g, b: b, a: 0xFF }
|
||||
}
|
||||
|
||||
const fn decode(raw: u32) -> (u8, u8, u8, u8) {
|
||||
let a = (raw & 0xFF) as u8;
|
||||
let b = ((raw >> 8) & 0xFF) as u8;
|
||||
let c = ((raw >> 16) & 0xFF) as u8;
|
||||
let d = ((raw >> 24) & 0xFF) as u8;
|
||||
(a, b, c, d)
|
||||
}
|
||||
|
||||
pub const fn from_rgba(raw: u32) -> Self {
|
||||
let (a, b, g, r) = Self::decode(raw);
|
||||
Self::new_rgba(r, g, b, a)
|
||||
}
|
||||
|
||||
pub const fn from_abgr(raw: u32) -> Self {
|
||||
let (r, g, b, a) = Self::decode(raw);
|
||||
Self::new_rgba(r, g, b, a)
|
||||
}
|
||||
|
||||
const fn encode(a: u8, b: u8, c: u8, d: u8) -> u32 {
|
||||
(a as u32 & 0xFF) | ((b as u32 & 0xFF) << 8) | ((c as u32 & 0xFF) << 16) | ((d as u32 & 0xFF) << 24)
|
||||
}
|
||||
|
||||
pub const fn encode_rgba(&self) -> u32 {
|
||||
Self::encode(self.a, self.b, self.g, self.r)
|
||||
}
|
||||
|
||||
pub const fn encode_abgr(&self) -> u32 {
|
||||
Self::encode(self.r, self.g, self.b, self.a)
|
||||
}
|
||||
|
||||
const fn blend_color_impl(src: u32, dst: u32, alpha: u32) -> u8 {
|
||||
let one_minus_a = 0xFF - alpha;
|
||||
((dst * alpha + src * one_minus_a) / 0xFF) as u8
|
||||
}
|
||||
|
||||
pub const fn blend_with(&self, other: Self) -> Self {
|
||||
let r = Self::blend_color_impl(other.r as u32, self.r as u32, self.a as u32);
|
||||
let g = Self::blend_color_impl(other.g as u32, self.g as u32, self.a as u32);
|
||||
let b = Self::blend_color_impl(other.b as u32, self.b as u32, self.a as u32);
|
||||
Self::new_rgb(r, g, b)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SurfaceEx {
|
||||
gpu_buf: *mut u32,
|
||||
gpu_buf_size: usize,
|
||||
linear_buf: *mut u32,
|
||||
linear_buf_size: usize,
|
||||
slot: i32,
|
||||
fences: gpu::MultiFence,
|
||||
surface_ref: gpu::surface::Surface,
|
||||
}
|
||||
|
||||
impl SurfaceEx {
|
||||
pub fn from(surface: gpu::surface::Surface) -> Self {
|
||||
let aligned_width = surface.compute_stride() as usize;
|
||||
let aligned_height = ((surface.get_height() + 7) & !7) as usize;
|
||||
let linear_buf_size = aligned_width * aligned_height;
|
||||
unsafe {
|
||||
let linear_buf_layout = alloc::alloc::Layout::from_size_align_unchecked(linear_buf_size, 8);
|
||||
let linear_buf = alloc::alloc::alloc_zeroed(linear_buf_layout);
|
||||
Self { gpu_buf: ptr::null_mut(), gpu_buf_size: 0, linear_buf: linear_buf as *mut u32, linear_buf_size: linear_buf_size, slot: 0, fences: mem::zeroed(), surface_ref: surface }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start(&mut self) -> Result<()> {
|
||||
let (buf, buf_size, slot, _has_fences, fences) = self.surface_ref.dequeue_buffer(true)?;
|
||||
self.gpu_buf = buf as *mut u32;
|
||||
self.gpu_buf_size = buf_size;
|
||||
self.slot = slot;
|
||||
self.fences = fences;
|
||||
self.surface_ref.wait_fences(fences, -1)
|
||||
}
|
||||
|
||||
pub fn get_surface(&mut self) -> &mut gpu::surface::Surface {
|
||||
&mut self.surface_ref
|
||||
}
|
||||
|
||||
fn convert_buffers_gob_impl(out_gob_buf: *mut u8, in_gob_buf: *mut u8, stride: u32) {
|
||||
unsafe {
|
||||
let mut tmp_out_gob_buf_128 = out_gob_buf as *mut u128;
|
||||
for i in 0..32 {
|
||||
let y = ((i >> 1) & 0x6) | (i & 0x1);
|
||||
let x = ((i << 3) & 0x10) | ((i << 1) & 0x20);
|
||||
let out_gob_buf_128 = tmp_out_gob_buf_128 as *mut u128;
|
||||
let in_gob_buf_128 = in_gob_buf.offset((y * stride + x) as isize) as *mut u128;
|
||||
*out_gob_buf_128 = *in_gob_buf_128;
|
||||
tmp_out_gob_buf_128 = tmp_out_gob_buf_128.offset(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_buffers_impl(out_buf: *mut u8, in_buf: *mut u8, stride: u32, height: u32) {
|
||||
let block_height_gobs = 1 << gpu::BLOCK_HEIGHT_LOG2;
|
||||
let block_height_px = 8 << gpu::BLOCK_HEIGHT_LOG2;
|
||||
|
||||
let width_blocks = stride >> 6;
|
||||
let height_blocks = (height + block_height_px - 1) >> (3 + gpu::BLOCK_HEIGHT_LOG2);
|
||||
let mut tmp_out_buf = out_buf;
|
||||
|
||||
for block_y in 0..height_blocks {
|
||||
for block_x in 0..width_blocks {
|
||||
for gob_y in 0..block_height_gobs {
|
||||
unsafe {
|
||||
let x = block_x * 64;
|
||||
let y = block_y * block_height_px + gob_y * 8;
|
||||
if y < height {
|
||||
let in_gob_buf = in_buf.offset((y * stride + x) as isize);
|
||||
Self::convert_buffers_gob_impl(tmp_out_buf, in_gob_buf, stride);
|
||||
}
|
||||
tmp_out_buf = tmp_out_buf.offset(512);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn end(&mut self) -> Result<()> {
|
||||
Self::convert_buffers_impl(self.gpu_buf as *mut u8, self.linear_buf as *mut u8, self.surface_ref.compute_stride(), self.surface_ref.get_height());
|
||||
arm::cache_flush(self.gpu_buf as *mut u8, self.gpu_buf_size);
|
||||
self.surface_ref.queue_buffer(self.slot, self.fences)?;
|
||||
self.surface_ref.wait_vsync_event(-1)
|
||||
}
|
||||
|
||||
pub fn clear(&mut self, color: RGBA8) {
|
||||
unsafe {
|
||||
let buf_size_32 = self.linear_buf_size / mem::size_of::<u32>();
|
||||
for i in 0..buf_size_32 {
|
||||
let cur = self.linear_buf.offset(i as isize);
|
||||
*cur = color.encode_abgr();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_single(&mut self, x: i32, y: i32, color: RGBA8, blend: bool) {
|
||||
unsafe {
|
||||
let offset = ((self.surface_ref.compute_stride() / mem::size_of::<u32>() as u32) as i32 * y + x) as isize;
|
||||
let cur = self.linear_buf.offset(offset);
|
||||
let old_color = RGBA8::from_abgr(*cur);
|
||||
let new_color = match blend {
|
||||
true => color.blend_with(old_color),
|
||||
false => color,
|
||||
};
|
||||
*cur = new_color.encode_abgr();
|
||||
}
|
||||
}
|
||||
|
||||
fn clamp(max: i32, value: i32) -> i32 {
|
||||
if value < 0 {
|
||||
return 0;
|
||||
}
|
||||
if value > max {
|
||||
return max;
|
||||
}
|
||||
value
|
||||
}
|
||||
|
||||
pub fn get_width(&self) -> u32 {
|
||||
self.surface_ref.get_width()
|
||||
}
|
||||
|
||||
pub fn get_height(&self) -> u32 {
|
||||
self.surface_ref.get_height()
|
||||
}
|
||||
|
||||
pub fn get_color_format(&self) -> gpu::ColorFormat {
|
||||
self.surface_ref.get_color_format()
|
||||
}
|
||||
|
||||
pub fn draw(&mut self, x: i32, y: i32, width: i32, height: i32, color: RGBA8, blend: bool) {
|
||||
let s_width = self.surface_ref.get_width() as i32;
|
||||
let s_height = self.surface_ref.get_height() as i32;
|
||||
let x0 = Self::clamp(s_width, x);
|
||||
let x1 = Self::clamp(s_width, x + width);
|
||||
let y0 = Self::clamp(s_height, y);
|
||||
let y1 = Self::clamp(s_height, y + height);
|
||||
for y in y0..y1 {
|
||||
for x in x0..x1 {
|
||||
self.draw_single(x, y, color, blend);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_font_text_impl(&mut self, font: &rusttype::Font, text: &str, color: RGBA8, scale: rusttype::Scale, v_metrics: rusttype::VMetrics, x: i32, y: i32, blend: bool) {
|
||||
let glyphs: Vec<_> = font.layout(&text[..], scale, rusttype::point(0.0, v_metrics.ascent)).collect();
|
||||
for glyph in &glyphs {
|
||||
if let Some(bounding_box) = glyph.pixel_bounding_box() {
|
||||
// Draw the glyph into the image per-pixel by using the draw closure
|
||||
glyph.draw(|g_x, g_y, g_v| {
|
||||
let mut pix_color = color;
|
||||
// Different alpha depending on the pixel
|
||||
pix_color.a = (g_v * 255.0) as u8;
|
||||
self.draw_single(x + g_x as i32 + bounding_box.min.x as i32, y + g_y as i32 + bounding_box.min.y as i32, pix_color, blend);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_font_text(&mut self, font: &rusttype::Font, text: String, color: RGBA8, size: f32, x: i32, y: i32, blend: bool) {
|
||||
let scale = rusttype::Scale::uniform(size);
|
||||
let v_metrics = font.v_metrics(scale);
|
||||
|
||||
let mut tmp_y = y;
|
||||
for semi_text in text.lines() {
|
||||
self.draw_font_text_impl(font, semi_text, color, scale, v_metrics, x, tmp_y, blend);
|
||||
tmp_y += v_metrics.ascent as i32;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_bitmap_text(&mut self, text: String, color: RGBA8, scale: i32, x: i32, y: i32, blend: bool) {
|
||||
let mut tmp_x = x;
|
||||
let mut tmp_y = y;
|
||||
for c in text.chars() {
|
||||
match c {
|
||||
'\n' | '\r' => {
|
||||
tmp_y += 8 * scale;
|
||||
tmp_x = x;
|
||||
},
|
||||
_ => {
|
||||
if let Some(glyph) = font8x8::BASIC_FONTS.get(c) {
|
||||
let char_tmp_x = tmp_x;
|
||||
let char_tmp_y = tmp_y;
|
||||
for gx in &glyph {
|
||||
for bit in 0..8 {
|
||||
match *gx & 1 << bit {
|
||||
0 => {},
|
||||
_ => {
|
||||
self.draw(tmp_x, tmp_y, scale, scale, color, blend);
|
||||
},
|
||||
}
|
||||
tmp_x += scale;
|
||||
}
|
||||
tmp_y += scale;
|
||||
tmp_x = char_tmp_x;
|
||||
}
|
||||
tmp_x += 8 * scale;
|
||||
tmp_y = char_tmp_y;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for SurfaceEx {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
let linear_buf_layout = alloc::alloc::Layout::from_size_align_unchecked(self.linear_buf_size, 8);
|
||||
alloc::alloc::dealloc(self.linear_buf as *mut u8, linear_buf_layout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Needed by rusttype
|
||||
|
||||
pub trait FloatExt {
|
||||
fn floor(self) -> Self;
|
||||
fn ceil(self) -> Self;
|
||||
fn fract(self) -> Self;
|
||||
fn trunc(self) -> Self;
|
||||
fn round(self) -> Self;
|
||||
fn abs(self) -> Self;
|
||||
}
|
||||
|
||||
impl FloatExt for f32 {
|
||||
#[inline]
|
||||
fn floor(self) -> Self {
|
||||
libm::floorf(self)
|
||||
}
|
||||
#[inline]
|
||||
fn ceil(self) -> Self {
|
||||
libm::ceilf(self)
|
||||
}
|
||||
#[inline]
|
||||
fn fract(self) -> Self {
|
||||
self - self.trunc()
|
||||
}
|
||||
#[inline]
|
||||
fn trunc(self) -> Self {
|
||||
libm::truncf(self)
|
||||
}
|
||||
#[inline]
|
||||
fn round(self) -> Self {
|
||||
libm::roundf(self)
|
||||
}
|
||||
#[inline]
|
||||
fn abs(self) -> Self {
|
||||
libm::fabsf(self)
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue