diff --git a/Cargo.toml b/Cargo.toml index 75555ed..7e7c319 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ authors = ["Jonathan 'theJPster' Pallant "] [dependencies] neotron-ffi = "0.1" neotron-api = "0.2" +neotron-common-bios = "0.12" [target.'cfg(unix)'.dependencies] crossterm = "0.26" diff --git a/src/ioctls/gfx.rs b/src/ioctls/gfx.rs new file mode 100644 index 0000000..5210764 --- /dev/null +++ b/src/ioctls/gfx.rs @@ -0,0 +1,44 @@ +//! Graphics ioctl constants + +/// Clear the screen +/// +/// The corresponding value is the fill colour, which is taken modulo the number of on-screen colours. +pub const COMMAND_CLEAR_SCREEN: u64 = 0; + +/// Plot a chunky pixel +/// +/// The command contains [ x | y | mode | colour ]. +/// +/// * `x` is 16 bits and marks the horizontal position (0 is left) +/// * `y` is 16 bits and marks the vertical position (0 is top) +/// * `mode` is 8 bits and is currently ignored +/// * `colour` is 24 bits, and is taken modulo the number of on-screen colours +/// +/// Use [`chunky_plot_value`] to create a suitable value for this ioctl command. +pub const COMMAND_CHUNKY_PLOT: u64 = 1; + +/// Change graphics mode +/// +/// The command contains the video mode in the upper 32 bits and a pointer to a +/// framebuffer in the lower 32 bits. +/// +/// The framebuffer pointer must point to a 32-bit aligned region of memory +/// that is large enough for the selected mode. If you pass `null`, then the OS +/// will attempt to allocate a framebuffer for you. +/// +/// Use [`change_mode_value`] to construct a value. +pub const COMMAND_CHANGE_MODE: u64 = 2; + +/// Calculate a 64-bit value argument for a gfx ioctl +pub fn chunky_plot_value(x: u16, y: u16, colour: u32) -> u64 { + (x as u64) << 48 | (y as u64) << 32 | (colour & 0xFFFFFF) as u64 +} + +/// Calculate a 64-bit value argument for a gfx ioctl +pub fn change_mode_value(mode: crate::VideoMode, fb_ptr: *mut u32) -> u64 { + let fb_ptr = fb_ptr as usize as u64; + let mode = mode.as_u8() as u64; + mode << 32 | fb_ptr +} + +// End of file diff --git a/src/ioctls/mod.rs b/src/ioctls/mod.rs new file mode 100644 index 0000000..9379d18 --- /dev/null +++ b/src/ioctls/mod.rs @@ -0,0 +1,3 @@ +//! A collection of ioctl constants + +pub mod gfx; diff --git a/src/lib.rs b/src/lib.rs index 5aa1943..b85e30f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,10 +27,14 @@ pub use neotron_ffi::{FfiBuffer, FfiByteSlice, FfiString}; pub use neotron_api::{file::Flags, path, Api, Error}; +pub use neotron_common_bios::video::Mode as VideoMode; + use neotron_api as api; pub mod console; +pub mod ioctls; + #[cfg(not(target_os = "none"))] mod fake_os_api; @@ -204,8 +208,14 @@ impl File { /// Perform a special I/O control operation. /// - /// The allowed values of `command` and `value` are TBD. - pub fn ioctl(&self, command: u64, value: u64) -> Result { + /// The allowed values of `command` and `value` are defined in the + /// [`ioctls`] module. + /// + /// # Safety + /// + /// Refer to the documentation for the ioctl you are using. Raw pointers may + /// be involved. + pub unsafe fn ioctl(&self, command: u64, value: u64) -> Result { let api = get_api(); match (api.ioctl)(self.0, command, value) { neotron_ffi::FfiResult::Ok(output) => Ok(output),