Browse Source

big refactoring

master
Alison Watson 10 months ago
parent
commit
343629861c
  1. 111
      Cargo.lock
  2. 35
      Cargo.toml
  3. 2
      README.md
  4. 70
      bl/main.rs
  5. 61
      fw/build.rs
  6. 2
      fw/conf.rs
  7. 2
      fw/data.rs
  8. 0
      fw/data/color.rs
  9. 59
      fw/data/deflate.rs
  10. 58
      fw/data/image.rs
  11. 168
      fw/data/model.rs
  12. 283
      fw/data/read.rs
  13. 2
      fw/data/shader.rs
  14. 4
      fw/data/text.rs
  15. 0
      fw/data/uniforms.rs
  16. 1
      fw/data/vertex.rs
  17. 209
      fw/data/vfs.rs
  18. 34
      fw/ffi.rs
  19. 7
      fw/hal.rs
  20. 0
      fw/hal/ctx.rs
  21. 6
      fw/hal/evt.rs
  22. 19
      fw/hal/sdl.rs
  23. 60
      fw/hal/win.rs
  24. 73
      fw/iter.rs
  25. 19
      fw/lib.rs
  26. 0
      fw/math.rs
  27. 8
      fw/meta.rs
  28. 503
      fw/render.rs
  29. 359
      fw/render/_image.rs
  30. 61
      fw/render/_sampler.rs
  31. 99
      fw/render/buffer.rs
  32. 0
      fw/render/conf.rs
  33. 8
      fw/render/model.rs
  34. 6
      fw/render/shader.rs
  35. 62
      fw/render/texture.rs
  36. 14
      fw/types.rs
  37. 8
      fw/vire.rs
  38. 139
      fw/vire/llvm.cxx
  39. 136
      fw/vire/llvm.rs
  40. 0
      fw/vire/parser.rs
  41. 2
      fw/vire/parser/tki.rs
  42. 2
      fw/vire/parser/tok.rs
  43. 58
      fw/vire/rt.rs
  44. 68
      fw/vire/rt/function.rs
  45. 2
      fw/vire/rt/nat.rs
  46. 117
      fw/vire/rt/types.rs
  47. 13
      glsl/main.frag
  48. 48
      glsl/main.vert
  49. 2
      ma/Cargo.toml
  50. 329
      ma/lib.rs
  51. 0
      res/blonkus.png
  52. 0
      res/blonkus.svgz
  53. 0
      res/blonkusicon.png
  54. 0
      res/vire.png
  55. 0
      res/vire.svgz
  56. 36
      source/framework/build.rs
  57. 230
      source/framework/data/bit.rs
  58. 79
      source/framework/data/read.rs
  59. 255
      source/framework/data/vfs.rs
  60. 5
      source/framework/types.rs
  61. 4
      source/framework/vire.rs
  62. 156
      source/framework/vire/compiler.rs
  63. 172
      source/framework/vire/compiler/types.rs
  64. 252
      source/macros/lib.rs
  65. 36
      source/main_test/main.rs
  66. 8
      tools/shader

111
Cargo.lock generated

@ -1,5 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "ash"
version = "0.32.1"
@ -27,21 +29,21 @@ version = "0.1.0"
dependencies = [
"ash",
"bitflags",
"blonkus_ma",
"blonkus-ma",
"cc",
"easy-cast",
"glam",
"half",
"libc",
"seahash",
"serde",
"shh",
"smallvec",
"smol_str",
"thiserror",
"toml",
"twox-hash",
]
[[package]]
name = "blonkus_ma"
name = "blonkus-ma"
version = "0.1.0"
dependencies = [
"proc-macro2",
@ -50,10 +52,10 @@ dependencies = [
]
[[package]]
name = "cfg-if"
version = "0.1.10"
name = "cc"
version = "1.0.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
checksum = "d26a6ce4b6a484fa3edb70f7efa6fc430fd2b87285fe8b84304fd0936faa0dc0"
[[package]]
name = "cfg-if"
@ -61,6 +63,12 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "easy-cast"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bd102ee8c418348759919b83b81cdbdc933ffe29740b903df448b4bafaa348e"
[[package]]
name = "glam"
version = "0.13.1"
@ -77,10 +85,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62aca2aba2d62b4a7f5b33f3712cb1b0692779a56fb510499d5c0aa594daeaf3"
[[package]]
name = "libc"
version = "0.2.93"
name = "heck"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9385f66bf6105b241aa65a61cb923ef20efc665cb9f9bb50ac2f0c4b7f378d41"
checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
dependencies = [
"unicode-segmentation",
]
[[package]]
name = "libloading"
@ -88,7 +99,7 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f84d96438c15fcd6c3f244c8fce01d1e2b9c6b5623e9c711dc9286d8fc92d6a"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
"winapi",
]
@ -110,9 +121,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.26"
version = "1.0.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d"
dependencies = [
"unicode-xid",
]
@ -126,36 +137,32 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "seahash"
version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
[[package]]
name = "serde"
version = "1.0.125"
version = "1.0.130"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171"
checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.125"
version = "1.0.130"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d"
checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "shh"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5205eb079ac8be8ec77b7470aff4a050610d42c32819deee362ca414c926d3ab"
dependencies = [
"libc",
"winapi",
]
[[package]]
name = "smallvec"
version = "1.6.1"
@ -164,42 +171,46 @@ checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
[[package]]
name = "smol_str"
version = "0.1.17"
version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ca0f7ce3a29234210f0f4f0b56f8be2e722488b95cb522077943212da3b32eb"
checksum = "b203e79e90905594272c1c97c7af701533d42adaab0beb3859018e477d54a3b0"
[[package]]
name = "spirv-std"
version = "0.4.0-alpha.4"
version = "0.4.0-alpha.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "895a86b30e3dab8b15ca414bdf1d5d3f132374debb8bf03ca5e89109f674a171"
checksum = "0e2676f3e58345b7c742b266b5bec022445b43e6471b9a00895faec03a52723e"
dependencies = [
"bitflags",
"num-traits",
"spirv-std-macros",
"spirv-types",
]
[[package]]
name = "spirv-std-macros"
version = "0.4.0-alpha.4"
version = "0.4.0-alpha.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b76d9abb9f30d0da7c54e164efecbfab6c8af3493ae41d43c38ebfbb80b9894"
checksum = "207e8515dfbb48bff03f64bf5f8388d4e0f2f526ee769cc6556df98477098ca5"
dependencies = [
"heck",
"proc-macro2",
"quote",
"spirv-types",
"syn",
]
[[package]]
name = "static_assertions"
version = "1.1.0"
name = "spirv-types"
version = "0.4.0-alpha.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
checksum = "71cc4b8f7ec707459fdeddb4f137109947045592f5b0c139f7bf1360058bac6b"
[[package]]
name = "syn"
version = "1.0.69"
version = "1.0.76"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48fe99c6bd8b1cc636890bcc071842de909d902c81ac7dab53ba33c421ab8ffb"
checksum = "c6f107db402c2c2055242dbf4d2af0e69197202e9faacbef9571bbe47f5a1b84"
dependencies = [
"proc-macro2",
"quote",
@ -208,18 +219,18 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.24"
version = "1.0.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e"
checksum = "602eca064b2d83369e2b2f34b09c70b605402801927c65c11071ac911d299b88"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.24"
version = "1.0.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0"
checksum = "bad553cc2c78e8de258400763a647e80e6d1b31ee237275d756f6836d204494c"
dependencies = [
"proc-macro2",
"quote",
@ -236,20 +247,16 @@ dependencies = [
]
[[package]]
name = "twox-hash"
version = "1.6.0"
name = "unicode-segmentation"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04f8ab788026715fa63b31960869617cba39117e520eb415b0139543e325ab59"
dependencies = [
"cfg-if 0.1.10",
"static_assertions",
]
checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
[[package]]
name = "unicode-xid"
version = "0.2.1"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]]
name = "winapi"

35
Cargo.toml

@ -12,10 +12,12 @@ publish = false
keywords = ["gamedev", "engine"]
categories = ["game-development"]
resolver = "2"
build = "source/framework/build.rs"
build = "fw/build.rs"
[dependencies]
blonkus_ma = { path = "source/macros" }
# macros:
# - blonkus-ma for our macros
blonkus-ma = { path = "ma" }
# types:
# - bitflags for FFI usage
@ -28,32 +30,33 @@ smol_str = "~0.1"
thiserror = "~1.0"
# i/o:
# - serde for serializing and deserializing our own formats
# - shh for hacking around LLVM crimes
# - serde for config / description files
# - toml for config / description files
serde = { version = "~1.0", features = ["derive"] }
shh = "~1.0"
toml = "~0.5"
# math:
# - easy-cast for safer casting
# - glam for linear algebra
# - half for half-floats in certain areas
glam = "~0.13"
half = "~1.7"
easy-cast = "~0.4"
glam = "~0.13"
half = "~1.7"
# hashing:
# - intaglio for symbol tables?
# - intaglio for symbol interning?
# - rustc-hash for things like mesh names?
# - twox-hash for file deduplication
# - seahash for file deduplication
#intaglio = "~1.2"
#rustc-hash = { version = "~1.1", default-features = false }
twox-hash = { version = "~1.6", default-features = false }
seahash = { version = "~4.1" }
# bindings:
# - ash for the renderer implementation
# - libc for binding SDL2 and LLVM
ash = "~0.32"
libc = "~0.2"
ash = "~0.32"
[build-dependencies]
cc = "1.0"
[profile.dev]
opt-level = 1
@ -65,10 +68,10 @@ lto = "thin"
[lib]
name = "blonkus_fw"
path = "source/framework/lib.rs"
path = "fw/lib.rs"
[[bin]]
name = "blonkus_mt"
path = "source/main_test/main.rs"
name = "blonkus"
path = "bl/main.rs"
# EOF

2
README.md

@ -1,5 +1,5 @@
# BLONKUS
![blonkus stylized logo](resource/blonkus.png)
![blonkus stylized logo](https://git.greyserv.net/marrub/blonkus/raw/branch/master/res/blonkus.png)
it's a thing

70
source/main_test/entry.rs → bl/main.rs

@ -1,44 +1,22 @@
#![allow(unused_imports)]
#![allow(unused_variables)]
#![allow(dead_code)]
use ash::{version::DeviceV1_0, vk};
use blonkus_fw::{
conf,
data::{self, vfs},
hal,
math::*,
meta,
render::Renderer,
//vire,
};
use std::{io::Cursor, rc::Rc};
pub fn run(conf: &conf::Conf) -> Result<(), Box<dyn std::error::Error>> {
let start_time = std::time::Instant::now();
let mut vfs = vfs::Vfs::default();
vfs.add_arc(vfs::Arc::read_path("testres".as_ref())?);
#![cfg(not(test))]
/*
let ctx = vire::compiler::Context::new()?;
let datum = vire::parser::Datum::parse_all(
vire::parser::tki::TokenIter::from_data(
"main.vire.gz",
vfs.get("main.vire.gz")?.text()?,
)?,
)?;
use blonkus_fw::*;
ctx.compile_all(datum)?;
fn entry(_conf: &conf::Conf) -> Result<(), Box<dyn std::error::Error>> {
//let start_time = std::time::Instant::now();
ctx.execute()?;
/*
let mut vfs = data::vfs::Vfs::default();
vfs.add_arc(data::vfs::Arc::read_path("testres".as_ref())?);
*/
//blonkus_fw::vire::rt::Rt::new()?;
/*
let hal = hal::ctx::Context::new()?;
let window = hal::win::Window::new(&hal, meta::ffi::NAME, 640, 480)?;
let mut ren = Renderer::new(
let mut ren = render::Renderer::new(
&window,
&conf.render,
&[
@ -57,7 +35,7 @@ pub fn run(conf: &conf::Conf) -> Result<(), Box<dyn std::error::Error>> {
/*
let img = {
let arc = vfs::Arc::read_tar(
let arc = data::vfs::Arc::read_tar(
&mut vfs.get("scientist/hltex000.texture")?.data(),
)?;
let img = data::image::MipImage::read(&*arc)?;
@ -72,14 +50,6 @@ pub fn run(conf: &conf::Conf) -> Result<(), Box<dyn std::error::Error>> {
vfs.get("scientist/scientist.iqm")?.data(),
))?;
let model = Model::create(&cmd_pool, model.0, model.1)?;
let spir_vert = Spir::read(MAIN_VERT);
let spir_frag = Spir::read(MAIN_FRAG);
let shader_vert = ShaderModule::create(device.clone(), &spir_vert)?;
let shader_frag = ShaderModule::create(device.clone(), &spir_frag)?;
let mut cur_c_frame = 0;
*/
'main_loop: loop {
@ -93,8 +63,24 @@ pub fn run(conf: &conf::Conf) -> Result<(), Box<dyn std::error::Error>> {
ren.draw_frame()?;
}
*/
Ok(())
}
fn main() {
let conf = conf::Conf::read("blonkus.toml").unwrap_or_else(|err| {
match err {
| conf::ErrConfLoad::NoFile => println!("{}", err),
| _ => eprintln!("{}", err),
};
println!("Using default configuration.");
conf::Conf::default()
});
if let Err(e) = entry(&conf) {
eprintln!("Uncaught error: {}", e);
}
}
// EOF

61
fw/build.rs

@ -0,0 +1,61 @@
fn llvm_config(args: Vec<&str>) -> String {
std::process::Command::new("llvm-config")
.args(args)
.output()
.map(|out| String::from_utf8(out.stdout).unwrap())
.unwrap()
.trim()
.to_owned()
}
fn split_to_array(string: String) -> Vec<String> {
string
.split(' ')
.filter(|lib| !lib.is_empty())
.map(|lib| lib.to_owned())
.collect()
}
fn with_components(mut v: Vec<&str>) -> Vec<&str> {
v.push("orcerror");
v.push("orcjit");
v.push("native");
v
}
fn main() {
let a_incdr = vec!["--includedir"];
let a_libdr = vec!["--libdir"];
let a_llibs = with_components(vec!["--libs", "--link-static"]);
let a_slibs = with_components(vec!["--system-libs", "--link-static"]);
let incdr = llvm_config(a_incdr);
let libdr = llvm_config(a_libdr);
let llibs = split_to_array(llvm_config(a_llibs));
let slibs = split_to_array(llvm_config(a_slibs));
println!("cargo:rustc-link-search=native={}", libdr);
for lib in llibs.into_iter().chain(slibs.into_iter()) {
println!("cargo:rustc-flags={}", lib);
}
#[cfg(any(
target_os = "macos",
target_os = "freebsd",
target_os = "openbsd"
))]
println!("cargo:rustc-link-lib=c++");
#[cfg(target_os = "linux")]
println!("cargo:rustc-link-lib=stdc++");
cc::Build::new()
.cpp(true)
.warnings_into_errors(true)
.static_flag(true)
.include(incdr)
.file("fw/vire/llvm.cxx")
.compile("helper");
}
// EOF

2
source/framework/conf.rs → fw/conf.rs

@ -4,7 +4,7 @@ pub struct Conf {
pub render: crate::render::conf::Conf,
}
#[derive(Error, Debug)]
#[derive(thiserror::Error, Debug)]
pub enum ErrConfLoad {
#[error("No existing configuration file")]
NoFile,

2
source/framework/data.rs → fw/data.rs

@ -1,5 +1,5 @@
pub mod bit;
pub mod color;
pub mod deflate;
pub mod image;
pub mod model;
pub mod read;

0
source/framework/data/color.rs → fw/data/color.rs

59
source/framework/defl.rs → fw/data/deflate.rs

@ -1,15 +1,15 @@
//! DEFLATE loader.
use crate::{
data::{bit::ReadBits, read},
data::read,
ffi,
types::{stkvec, StkVec},
types::{stkvec, Cast, StkVec},
};
use std::cmp::Ordering;
type AlphabetTable = StkVec<[u16; 320]>;
#[derive(Error, Debug)]
#[derive(thiserror::Error, Debug)]
pub enum Err {
#[error("Bad stream block type")]
BlockType,
@ -84,7 +84,7 @@ pub fn read_gzip(b: &[u8]) -> Option<&[u8]> {
let b = if fl & FEXT == 0 {
b
} else {
b.get(read::u16le_sz(b.get(0..2)?, 0) + 2..)?
b.get(usize::from(read::u16le(b.get(0..2)?, 0)) + 2..)?
};
let b =
if fl & FNAM == 0 { b } else { b.get(ffi::end_of_cstr(b) + 1..)? };
@ -97,17 +97,17 @@ pub fn read_gzip(b: &[u8]) -> Option<&[u8]> {
}
}
/// Decompresses a DEFLATE compressed bitstream.
/// Decompresses a DEFLATE compressed bitstream starting at the `p`-th bit.
///
/// # Errors
///
/// Returns `Err` if the bit-stream fails to parse.
pub fn read_defl(b: &[u8], p: &mut usize) -> Result<Vec<u8>, Err> {
pub fn read_deflate_from(b: &[u8], p: &mut usize) -> Result<Vec<u8>, Err> {
let mut v = Vec::new();
loop {
let bfinal = u8::read_bits_le(b, *p, 1).ok_or(Err::BlockBits)?;
let bstype = u8::read_bits_le(b, *p + 1, 2).ok_or(Err::BlockBits)?;
let bfinal = read::ble_u8(b, *p, 1).ok_or(Err::BlockBits)?;
let bstype = read::ble_u8(b, *p + 1, 2).ok_or(Err::BlockBits)?;
*p += 3;
match bstype {
@ -123,6 +123,15 @@ pub fn read_defl(b: &[u8], p: &mut usize) -> Result<Vec<u8>, Err> {
}
}
/// Decompresses a DEFLATE compressed bitstream.
///
/// # Errors
///
/// Returns `Err` if the bit-stream fails to parse.
pub fn read_deflate(b: &[u8]) -> Result<Vec<u8>, Err> {
read_deflate_from(b, &mut 0)
}
fn st_dynamic(b: &[u8], p: &mut usize, v: &mut Vec<u8>) -> Result<(), Err> {
const CODE_ORDERING: [usize; 19] =
[16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15];
@ -134,9 +143,9 @@ fn st_dynamic(b: &[u8], p: &mut usize, v: &mut Vec<u8>) -> Result<(), Err> {
// read the header: number of literal alphabet codes, number of
// distance alphabet codes, and number of lengths for decoding the
// alphabet
let hlits = usize::read_bits_le(b, *p, 5).ok_or(Err::DynStream)?;
let hdist = usize::read_bits_le(b, *p + 5, 5).ok_or(Err::DynStream)?;
let hclen = usize::read_bits_le(b, *p + 10, 4).ok_or(Err::DynStream)?;
let hlits = read::ble_usz(b, *p, 5).ok_or(Err::DynStream)?;
let hdist = read::ble_usz(b, *p + 5, 5).ok_or(Err::DynStream)?;
let hclen = read::ble_usz(b, *p + 10, 4).ok_or(Err::DynStream)?;
*p += 14;
let hlits = NHLITS + hlits;
@ -147,7 +156,7 @@ fn st_dynamic(b: &[u8], p: &mut usize, v: &mut Vec<u8>) -> Result<(), Err> {
// compressed
let mut table = [0; 19];
for &i in CODE_ORDERING.iter().take(hclen) {
table[i] = u16::read_bits_le(b, *p, 3).ok_or(Err::DynStream)?;
table[i] = read::ble_u16(b, *p, 3).ok_or(Err::DynStream)?;
*p += 3;
}
@ -190,7 +199,7 @@ fn st_literal(b: &[u8], p: &mut usize, v: &mut Vec<u8>) -> Result<(), Err> {
// copy data directly from byte boundary
let bound = *p / 8 + 1;
let b = &b[bound..];
let len = read::u16le_sz(b.get(0..2).ok_or(Err::Literal)?, 0);
let len = read::u16le(b.get(0..2).ok_or(Err::Literal)?, 0).into();
let b = &b[4..];
*p += bound * 8 + 4 * 8 + len * 8;
@ -227,7 +236,7 @@ fn read_alphabet(
| 16 => {
// copy previous code 3-6 times
let lst = alpha[i - 1];
let len = u8::read_bits_le(b, *p, 2).ok_or(Err::BitsCode)? + 3;
let len = read::ble_u8(b, *p, 2).ok_or(Err::BitsCode)? + 3;
*p += 2;
for _ in 0..len {
@ -236,7 +245,7 @@ fn read_alphabet(
}
| 17 => {
// repeat '0' 3-10 times
let len = u8::read_bits_le(b, *p, 3).ok_or(Err::Bits0)? + 3;
let len = read::ble_u8(b, *p, 3).ok_or(Err::Bits0)? + 3;
*p += 3;
for _ in 0..len {
@ -245,7 +254,7 @@ fn read_alphabet(
}
| 18 => {
// repeat '0' 11-138 times
let len = u8::read_bits_le(b, *p, 7).ok_or(Err::Bits0)? + 11;
let len = read::ble_u8(b, *p, 7).ok_or(Err::Bits0)? + 11;
*p += 7;
for _ in 0..len {
@ -310,7 +319,7 @@ fn output_tables(
}
let bit = LEN_EXTRA_BITS[sym];
let len = usize::read_bits_le(b, *p, bit).ok_or(Err::Pair)?;
let len = read::ble_usz(b, *p, bit).ok_or(Err::Pair)?;
*p += bit;
@ -322,7 +331,7 @@ fn output_tables(
let sym = usize::from(table_dst.decode(b, p)?);
let bit = DST_EXTRA_BITS[sym];
let dst = usize::read_bits_le(b, *p, bit).ok_or(Err::Pair)?;
let dst = read::ble_usz(b, *p, bit).ok_or(Err::Pair)?;
*p += bit;
@ -344,7 +353,7 @@ fn output_tables(
impl HuffmanTable {
fn read(table: &[u16]) -> Result<Self, Err> {
let mut syms = vec![0; table.len()];
let mut syms = stkvec![0; table.len()];
let mut nums = [0; 16];
// count the number of symbols for each bit length
@ -364,13 +373,13 @@ impl HuffmanTable {
}
// make the actual bit pattern table
for (n, &length) in table.iter().enumerate() {
for (&length, n) in table.iter().zip(0..table.len().cast()) {
// length 0 means this code isn't used, so only try to make bit
// patterns for codes that actually exist
if length != 0 {
// make sure to make each offset unique
let offset = &mut ofs[usize::from(length)];
syms[*offset] = n as u16;
syms[*offset] = n;
*offset += 1;
}
}
@ -382,14 +391,16 @@ impl HuffmanTable {
let mut codes = 0;
let mut first = 0;
let mut index = 0;
let mut i = 1;
for i in 1..=15 {
while i < 16 {
// add bit from file
codes |= usize::read_bits_le(b, *p, 1).ok_or(Err::Table)?;
codes |= read::ble_usz(b, *p, 1).ok_or(Err::Table)?;
*p += 1;
// check our symbol table for this one (quick tree check)
let count = self.nums[i];
i += 1;
if (codes as isize) - (count as isize) < (first as isize) {
return Ok(self.syms[index + codes - first]);
@ -410,7 +421,7 @@ impl HuffmanTable {
#[derive(Debug)]
struct HuffmanTable {
nums: [usize; 16],
syms: Vec<u16>,
syms: StkVec<[u16; 288]>,
}
// EOF

58
source/framework/data/image.rs → fw/data/image.rs

@ -1,7 +1,11 @@
use crate::data::{color::Color, read, vfs};
use crate::{
data::{color::Color, read, vfs},
iter::MaybeRev,
};
use std::io::{self, Read};
#[derive(Error, Debug)]
#[derive(thiserror::Error, Debug)]
#[non_exhaustive]
pub enum ErrImageRead {
#[error("Bad color encoding in texture")]
Encoding,
@ -25,12 +29,6 @@ pub struct MipImage {
heigh: usize,
}
#[derive(Clone, Debug)]
enum MaybeRev<I> {
Not(I),
Rev(I),
}
impl Image {
pub fn get(&self, x: usize, y: usize) -> Option<&Color> {
if x < self.width && y < self.heigh {
@ -93,8 +91,8 @@ impl Image {
// compile size info
let comps = if alpha { 4 } else { 3 };
let width = read::u16le_sz(&head, 12);
let heigh = read::u16le_sz(&head, 14);
let width = read::u16le(&head, 12).into();
let heigh = read::u16le(&head, 14).into();
let wsize = width * heigh;
let wscan = width * comps;
@ -150,14 +148,14 @@ impl MipImage {
self.datum.is_empty()
}
pub fn read(arc: &vfs::Arc) -> Result<Self, ErrImageRead> {
pub fn read(vfs: &vfs::Vfs) -> Result<Self, ErrImageRead> {
let mut datum = Vec::new();
let mut width = 0;
let mut heigh = 0;
let mut i = 0;
while let Some(file) = arc.get(&i.to_string()) {
while let Some(file) = vfs.get(&i.to_string()) {
let img = Image::read(&mut file.data())?;
if i == 0 {
@ -186,40 +184,4 @@ impl std::ops::Index<(usize, usize)> for Image {
}
}
impl<I> MaybeRev<I> {
const fn rev_if(it: I, rev: bool) -> Self {
if rev {
Self::Rev(it)
} else {
Self::Not(it)
}
}
}
impl<I> Iterator for MaybeRev<I>
where
I: Iterator + DoubleEndedIterator,
{
type Item = <I as Iterator>::Item;
fn next(&mut self) -> Option<Self::Item> {
match self {
| Self::Not(it) => it.next(),
| Self::Rev(it) => it.next_back(),
}
}
}
impl<I> ExactSizeIterator for MaybeRev<I>
where
I: ExactSizeIterator + DoubleEndedIterator,
{
fn len(&self) -> usize {
match self {
| Self::Not(it) => it.len(),
| Self::Rev(it) => it.len(),
}
}
}
// EOF

168
source/framework/data/model.rs → fw/data/model.rs

@ -2,7 +2,7 @@ use crate::{
data::{read, vertex::Vertex},
ffi,
math::*,
types::StkStr,
types::{Cast, StkStr},
};
use std::{
collections::HashMap,
@ -11,7 +11,8 @@ use std::{
str::Utf8Error,
};
#[derive(Error, Debug)]
#[derive(thiserror::Error, Debug)]
#[non_exhaustive]
pub enum Err {
#[error(transparent)]
Io(#[from] io::Error),
@ -41,6 +42,7 @@ struct Pose {
}
struct Joint {
#[allow(dead_code)]
nam: StkStr,
mat: Mat4,
inv: Mat4,
@ -77,7 +79,7 @@ const FMT_F16: u32 = 6;
const FMT_F32: u32 = 7;
const FMT_F64: u32 = 8;
fn fmt_check(fm: u32) -> Result<(), Err> {
const fn fmt_check(fm: u32) -> Result<(), Err> {
match fm {
| FMT_I8 | FMT_U8 | FMT_I16 | FMT_U16 | FMT_I32 | FMT_U32 | FMT_F16
| FMT_F32 | FMT_F64 => Ok(()),
@ -97,30 +99,30 @@ fn fmt_size(fm: u32) -> usize {
fn fmt_read_abs(fm: u32, vec: &[u8], pos: usize) -> f32 {
match fm {
| FMT_I8 => f32::from(vec[pos] as i8),
| FMT_U8 => f32::from(vec[pos]),
| FMT_I16 => f32::from(read::i16le_16(vec, pos)),
| FMT_U16 => f32::from(read::u16le_16(vec, pos)),
| FMT_I32 => read::i32le_32(vec, pos) as f32,
| FMT_U32 => read::u32le_32(vec, pos) as f32,
| FMT_F16 => read::f16le_32(vec, pos),
| FMT_F32 => read::f32le_32(vec, pos),
| FMT_F64 => read::f64le_32(vec, pos),
| FMT_I8 => read::i8x(vec, pos).into(),
| FMT_U8 => read::u8x(vec, pos).into(),
| FMT_I16 => read::i16le(vec, pos).into(),
| FMT_U16 => read::u16le(vec, pos).into(),
| FMT_I32 => read::i32le(vec, pos).cast(),
| FMT_U32 => read::u32le(vec, pos).cast(),
| FMT_F16 => read::f16le(vec, pos).to_f32(),
| FMT_F32 => read::f32le(vec, pos),
| FMT_F64 => read::f64le(vec, pos) as f32,
| _ => unsafe { std::hint::unreachable_unchecked() },
}
}
fn fmt_read_nrm(fm: u32, vec: &[u8], pos: usize) -> f32 {
match fm {
| FMT_I8 => f32::abs(f32::from(vec[pos] as i8) / 128.0),
| FMT_U8 => f32::from(vec[pos]) / 255.0,
| FMT_I16 => f32::abs(f32::from(read::i16le_16(vec, pos)) / 32768.0),
| FMT_U16 => f32::from(read::u16le_16(vec, pos)) / 65535.0,
| FMT_I32 => (read::i32le_32(vec, pos) as f64 / 2147483648.0) as f32,
| FMT_U32 => (read::u32le_32(vec, pos) as f64 / 4294967295.0) as f32,
| FMT_F16 => f32::clamp(read::f16le_32(vec, pos), 0.0, 1.0),
| FMT_F32 => f32::clamp(read::f32le_32(vec, pos), 0.0, 1.0),
| FMT_F64 => f32::clamp(read::f64le_64(vec, pos) as f32, 0.0, 1.0),
| FMT_I8 => f32::from(read::i8x(vec, pos)).abs() / 128.0,
| FMT_U8 => f32::from(read::u8x(vec, pos)) / 255.0,
| FMT_I16 => f32::from(read::i16le(vec, pos)).abs() / 32768.0,
| FMT_U16 => f32::from(read::u16le(vec, pos)) / 65535.0,
| FMT_I32 => (f64::from(read::i32le(vec, pos)) / 2147483648.0) as f32,
| FMT_U32 => (f64::from(read::u32le(vec, pos)) / 4294967295.0) as f32,
| FMT_F16 => f32::clamp(read::f16le(vec, pos).to_f32(), 0.0, 1.0),
| FMT_F32 => f32::clamp(read::f32le(vec, pos), 0.0, 1.0),
| FMT_F64 => f32::clamp(read::f64le(vec, pos) as f32, 0.0, 1.0),
| _ => unsafe { std::hint::unreachable_unchecked() },
}
}
@ -172,25 +174,25 @@ impl Model {
return Err(Err::Magic);
}
let num_text = read::u32le_sz(&head, 28);
let ofs_text = read::u32le_64(&head, 32);
let num_mesh = read::u32le_sz(&head, 36);
let ofs_mesh = read::u32le_64(&head, 40);
let num_vinf = read::u32le_sz(&head, 44);
let num_vert = read::u32le_sz(&head, 48);
let ofs_vinf = read::u32le_64(&head, 52);
let num_tris = read::u32le_sz(&head, 56);
let ofs_tris = read::u32le_64(&head, 60);
let num_join = read::u32le_sz(&head, 68);
let ofs_join = read::u32le_64(&head, 72);
let num_pose = read::u32le_sz(&head, 76);
let ofs_pose = read::u32le_64(&head, 80);
let num_anim = read::u32le_sz(&head, 84);
let ofs_anim = read::u32le_64(&head, 88);
let num_frms = read::u32le_sz(&head, 92);
let num_frmc = read::u32le_sz(&head, 96);
let ofs_frms = read::u32le_64(&head, 100);
let ofs_bnds = read::u32le_64(&head, 104);
let num_text = read::u32le(&head, 28) as usize;
let ofs_text = read::u32le(&head, 32).into();
let num_mesh = read::u32le(&head, 36) as usize;
let ofs_mesh = read::u32le(&head, 40).into();
let num_vinf = read::u32le(&head, 44) as usize;
let num_vert = read::u32le(&head, 48) as usize;
let ofs_vinf = read::u32le(&head, 52).into();
let num_tris = read::u32le(&head, 56) as usize;
let ofs_tris = read::u32le(&head, 60).into();
let num_join = read::u32le(&head, 68) as usize;
let ofs_join = read::u32le(&head, 72).into();
let num_pose = read::u32le(&head, 76) as usize;
let ofs_pose = read::u32le(&head, 80).into();
//let num_anim = read::u32le(&head, 84) as usize;
//let ofs_anim = read::u32le(&head, 88).into();
let num_frms = read::u32le(&head, 92) as usize;
let num_frmc = read::u32le(&head, 96) as usize;
let ofs_frms = read::u32le(&head, 100).into();
//let ofs_bnds = read::u32le(&head, 104).into();
if num_join != 0 && num_pose != 0 && num_pose != num_join {
return Err(Err::NumPoses);
@ -208,29 +210,28 @@ impl Model {
rd.seek(SeekFrom::Start(ofs_vinf))?;
for array_def in read::hunk(rd, num_vinf * 20)?.chunks(20) {
let ty = read::u32le_32(array_def, 0);
let fl = read::u32le_32(array_def, 4);
let fm = read::u32le_32(array_def, 8);
let sz = read::u32le_32(array_def, 12);
let of = read::u32le_64(array_def, 16);
let ty = read::u32le(array_def, 0);
//let fl = read::u32le(array_def, 4);
let fm = read::u32le(array_def, 8);
let sz = read::u32le(array_def, 12) as usize;
let of = read::u32le(array_def, 16).into();
fmt_check(fm)?;
rd.seek(SeekFrom::Start(of))?;
let obj_size = fmt_size(fm);
let obj_amnt = sz as usize;
let obj_blks = obj_size * obj_amnt;
let obj_blks = obj_size * sz;
let hunk = read::hunk(rd, obj_blks * num_vert)?;
let v2 = |v: &mut Vec<Vec3>, rd: fn(u32, &[u8], usize) -> f32| {
if obj_amnt != 2 {
if sz != 2 {
Err(Err::VaFormat)
} else {
for vec in hunk.chunks(obj_blks) {
let x = rd(fm, vec, obj_size * 0);
let y = rd(fm, vec, obj_size * 1);
let x = rd(fm, vec, 0);
let y = rd(fm, vec, obj_size);
v.push(Vec3::new(x, y, 0.0));
}
Ok(())
@ -238,12 +239,12 @@ impl Model {
};
let v3 = |v: &mut Vec<Vec3>, rd: fn(u32, &[u8], usize) -> f32| {
if obj_amnt != 3 {
if sz != 3 {
Err(Err::VaFormat)
} else {
for vec in hunk.chunks(obj_blks) {
let x = rd(fm, vec, obj_size * 0);
let y = rd(fm, vec, obj_size * 1);
let x = rd(fm, vec, 0);
let y = rd(fm, vec, obj_size);
let z = rd(fm, vec, obj_size * 2);
v.push(Vec3::new(x, y, z));
}
@ -252,12 +253,12 @@ impl Model {
};
let v4 = |v: &mut Vec<Vec4>, rd: fn(u32, &[u8], usize) -> f32| {
if obj_amnt != 4 {
if sz != 4 {
Err(Err::VaFormat)
} else {
for vec in hunk.chunks(obj_blks) {
let x = rd(fm, vec, obj_size * 0);
let y = rd(fm, vec, obj_size * 1);
let x = rd(fm, vec, 0);
let y = rd(fm, vec, obj_size);
let z = rd(fm, vec, obj_size * 2);
let w = rd(fm, vec, obj_size * 3);
v.push(Vec4::new(x, y, z, w));
@ -290,14 +291,15 @@ impl Model {
wgt_v.into_iter(),
clr_v.into_iter(),
)) {
let pos = pos.unwrap_or_else(|| Vec3::ZERO);
let tex = tex.unwrap_or_else(|| Vec3::ZERO);
let nrm = nrm.unwrap_or_else(|| Vec3::ZERO);
let tan = tan.unwrap_or_else(|| Vec4::ZERO);
let idx = idx.unwrap_or_else(|| Vec4::ZERO);
let wgt = wgt.unwrap_or_else(|| Vec4::ZERO);
let clr = clr.unwrap_or_else(|| Vec4::ONE);
vert_dat.push(Vertex { pos, tex, nrm, tan, idx, wgt, clr });
vert_dat.push(Vertex {
pos: pos.unwrap_or(Vec3::ZERO),
tex: tex.unwrap_or(Vec3::ZERO),
nrm: nrm.unwrap_or(Vec3::ZERO),
tan: tan.unwrap_or(Vec4::ZERO),
idx: idx.unwrap_or(Vec4::ZERO),
wgt: wgt.unwrap_or(Vec4::ZERO),
clr: clr.unwrap_or(Vec4::ONE),
});
}
// collect index info
@ -306,9 +308,9 @@ impl Model {
rd.seek(SeekFrom::Start(ofs_tris))?;
for tri in read::hunk(rd, num_tris * 4 * 3)?.chunks(4 * 3) {
indx_dat.push(read::u32le_32(tri, 0));
indx_dat.push(read::u32le_32(tri, 4));
indx_dat.push(read::u32le_32(tri, 8));
indx_dat.push(read::u32le(tri, 0));
indx_dat.push(read::u32le(tri, 4));
indx_dat.push(read::u32le(tri, 8));
}
// collect text
@ -322,12 +324,12 @@ impl Model {
rd.seek(SeekFrom::Start(ofs_mesh))?;
for mesh in read::hunk(rd, num_mesh * 4 * 6)?.chunks(4 * 6) {
let nam = read::u32le_sz(mesh, 0);
let mat = read::u32le_sz(mesh, 4);
let vtx = read::u32le_sz(mesh, 8);
let vnu = read::u32le_sz(mesh, 12);
let idx = read::u32le_sz(mesh, 16) * 3;
let inu = read::u32le_sz(mesh, 20) * 3;
let nam = read::u32le(mesh, 0) as usize;
let mat = read::u32le(mesh, 4) as usize;
let vtx = read::u32le(mesh, 8) as usize;
let vnu = read::u32le(mesh, 12) as usize;
let idx = read::u32le(mesh, 16) as usize * 3;
let inu = read::u32le(mesh, 20) as usize * 3;
let nam = StkStr::new(from_stab(&stab, nam)?);
let mat = StkStr::new(from_stab(&stab, mat)?);
@ -344,9 +346,9 @@ impl Model {
rd.seek(SeekFrom::Start(ofs_join))?;
for join in read::hunk(rd, num_join * 4 * 12)?.chunks(4 * 12) {
let nam = read::u32le_sz(join, 0);
let par = read::u32le_sz(join, 4);
let trs = read::array(read::f32le_32, join, [0.0; 10], 4, 8);
let nam = read::u32le(join, 0) as usize;
let par = read::u32le(join, 4) as usize;
let trs = read::array(read::f32le, join, [0.0; 10], 4, 8);
let nam = StkStr::new(from_stab(&stab, nam)?);
@ -372,7 +374,7 @@ impl Model {
rd.seek(SeekFrom::Start(ofs_frms))?;
for samp in read::hunk(rd, num_frms * num_frmc * 2)?.chunks(2) {
frames.push(read::u16le_16(samp, 0));
frames.push(read::u16le(samp, 0));
}
// collect pose info
@ -381,10 +383,10 @@ impl Model {
rd.seek(SeekFrom::Start(ofs_pose))?;
for pose in read::hunk(rd, num_pose * 4 * 22)?.chunks(4 * 22) {
let par = read::u32le_sz(pose, 0);
let msk = read::u32le_32(pose, 4);
let ofs = read::array(read::f32le_32, pose, [0.0; 10], 4, 8);
let scl = read::array(read::f32le_32, pose, [0.0; 10], 4, 48);
let par = read::u32le(pose, 0) as usize;
let msk = read::u32le(pose, 4);
let ofs = read::array(read::f32le, pose, [0.0; 10], 4, 8);
let scl = read::array(read::f32le, pose, [0.0; 10], 4, 48);
poses.push(Pose { par, msk, ofs, scl });
}
@ -399,10 +401,10 @@ impl Model {
for (pose, joint) in poses.iter().zip(joints.iter()) {
let mut ofs = pose.ofs;
for i in 0..10 {
for (i, off) in ofs.iter_mut().enumerate() {
if pose.msk & 1 << i != 0 {
let frm = f32::from(*frame.next().ok_or(Err::FrameCount)?);
ofs[i] += frm * pose.scl[i];
*off += frm * pose.scl[i];
}
}

283
fw/data/read.rs

@ -0,0 +1,283 @@
use half::f16;
use std::io::{self, Read};
pub const fn i8x(b: &[u8], p: usize) -> i8 {
i8::from_ne_bytes([b[p]])
}
pub const fn u8x(b: &[u8], p: usize) -> u8 {
b[p]
}
pub const fn i16le(b: &[u8], p: usize) -> i16 {
i16::from_le_bytes([b[p], b[p + 1]])
}
pub const fn u16le(b: &[u8], p: usize) -> u16 {
u16::from_le_bytes([b[p], b[p + 1]])
}
pub const fn i32le(b: &[u8], p: usize) -> i32 {
i32::from_le_bytes([b[p], b[p + 1], b[p + 2], b[p + 3]])
}
pub const fn u32le(b: &[u8], p: usize) -> u32 {
u32::from_le_bytes([b[p], b[p + 1], b[p + 2], b[p + 3]])
}
pub fn f16le(b: &[u8], p: usize) -> f16 {
f16::from_le_bytes([b[p], b[p + 1]])
}
pub fn f32le(b: &[u8], p: usize) -> f32 {
f32::from_le_bytes([b[p], b[p + 1], b[p + 2], b[p + 3]])
}
pub fn f64le(b: &[u8], p: usize) -> f64 {
f64::from_le_bytes([
b[p],
b[p + 1],